aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Rahm <joshuarahm@gmail.com>2024-03-09 15:00:41 -0700
committerJosh Rahm <joshuarahm@gmail.com>2024-03-09 15:00:41 -0700
commit7a7f497b483cd65e340064f23ed1c73425ecba0a (patch)
treed5c99ea22a1e10300d06165f8ac96df6b0dc59e1
parent1b7b916b7631ddf73c38e3a0070d64e4636cb2f3 (diff)
parentade1b12f49c3b3914c74847d791eb90ea90b56b7 (diff)
downloadrneovim-7a7f497b483cd65e340064f23ed1c73425ecba0a.tar.gz
rneovim-7a7f497b483cd65e340064f23ed1c73425ecba0a.tar.bz2
rneovim-7a7f497b483cd65e340064f23ed1c73425ecba0a.zip
Merge remote-tracking branch 'upstream/master' into aucmd_textputpost
-rw-r--r--.cirrus.yml2
-rw-r--r--.clang-tidy1
-rw-r--r--.git-blame-ignore-revs5
-rwxr-xr-x.gitattributes1
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml11
-rw-r--r--.github/ISSUE_TEMPLATE/feature_request.yml2
-rw-r--r--.github/ISSUE_TEMPLATE/lsp_bug_report.yml2
-rw-r--r--.github/actions/cache/action.yml2
-rw-r--r--.github/actions/setup/action.yml29
-rw-r--r--.github/labeler.yml66
-rwxr-xr-x.github/scripts/build_universal_macos.sh7
-rw-r--r--.github/scripts/close_unresponsive.js1
-rwxr-xr-x.github/scripts/install_deps.sh4
-rw-r--r--.github/scripts/labeler_configuration.yml71
-rw-r--r--.github/scripts/reviewers_add.js (renamed from .github/scripts/reviews.js)8
-rw-r--r--.github/scripts/reviewers_remove.js (renamed from .github/scripts/remove-reviewers.js)0
-rw-r--r--.github/workflows/backport.yml8
-rw-r--r--.github/workflows/build.yml18
-rw-r--r--.github/workflows/codeql.yml15
-rw-r--r--.github/workflows/coverity.yml6
-rw-r--r--.github/workflows/docs.yml (renamed from .github/workflows/api-docs.yml)17
-rw-r--r--.github/workflows/labeler_issue.yml (renamed from .github/workflows/issue-open-check.yml)9
-rw-r--r--.github/workflows/labeler_pr.yml (renamed from .github/workflows/labeler.yml)15
-rw-r--r--.github/workflows/lintcommit.yml6
-rw-r--r--.github/workflows/news.yml6
-rw-r--r--.github/workflows/notes.md2
-rw-r--r--.github/workflows/optional.yml23
-rw-r--r--.github/workflows/release.yml63
-rw-r--r--.github/workflows/reviewers_add.yml (renamed from .github/workflows/add-reviewers.yml)4
-rw-r--r--.github/workflows/reviewers_remove.yml (renamed from .github/workflows/remove-reviewers.yml)4
-rw-r--r--.github/workflows/test.yml48
-rw-r--r--.github/workflows/vim_patches.yml (renamed from .github/workflows/vim-patches.yml)0
-rw-r--r--.luacheckrc1
-rw-r--r--.luarc.json4
-rw-r--r--.stylua.toml2
-rw-r--r--.styluaignore15
-rw-r--r--BUILD.md450
-rw-r--r--CMakeLists.txt77
-rw-r--r--CONTRIBUTING.md44
-rw-r--r--INSTALL.md416
-rw-r--r--MAINTAIN.md58
-rw-r--r--Makefile144
-rw-r--r--README.md6
-rw-r--r--cmake.config/CMakeLists.txt47
-rw-r--r--cmake.config/config.h.in5
-rw-r--r--cmake.config/iwyu/mapping.imp2
-rw-r--r--cmake.config/iwyu/posix.imp6
-rw-r--r--cmake.config/versiondef.h.in6
-rw-r--r--cmake.config/versiondef_old.h.in21
-rw-r--r--cmake.deps/CMakeLists.txt45
-rw-r--r--cmake.deps/cmake/BuildLibtermkey.cmake13
-rw-r--r--cmake.deps/cmake/BuildLpeg.cmake18
-rw-r--r--cmake.deps/cmake/BuildLuajit.cmake6
-rw-r--r--cmake.deps/cmake/BuildLuv.cmake13
-rw-r--r--cmake.deps/cmake/BuildTreesitter.cmake1
-rw-r--r--cmake.deps/cmake/GettextCMakeLists.txt2
-rw-r--r--cmake.deps/cmake/LibiconvCMakeLists.txt3
-rw-r--r--cmake.deps/cmake/LibtermkeyCMakeLists.txt37
-rw-r--r--cmake.deps/cmake/LibvtermCMakeLists.txt2
-rw-r--r--cmake.deps/cmake/LpegCMakeLists.txt2
-rw-r--r--cmake.deps/cmake/MarkdownParserCMakeLists.txt3
-rw-r--r--cmake.deps/cmake/TreesitterCMakeLists.txt3
-rw-r--r--cmake.deps/cmake/TreesitterParserCMakeLists.txt2
-rw-r--r--cmake.deps/deps.txt43
-rw-r--r--cmake/FindLibintl.cmake6
-rw-r--r--cmake/FindLibtermkey.cmake9
-rw-r--r--cmake/FindLibuv.cmake16
-rw-r--r--cmake/FindTreesitter.cmake20
-rw-r--r--cmake/Format.cmake65
-rw-r--r--cmake/InstallHelpers.cmake13
-rw-r--r--cmake/RunTests.cmake9
-rw-r--r--cmake/Util.cmake25
-rw-r--r--contrib/flake.lock12
-rw-r--r--contrib/flake.nix6
-rw-r--r--contrib/local.mk.example6
-rw-r--r--contrib/minimal.lua14
-rw-r--r--runtime/CMakeLists.txt38
-rw-r--r--runtime/autoload/modula2.vim31
-rw-r--r--runtime/autoload/netrw.vim132
-rw-r--r--runtime/autoload/netrwFileHandlers.vim3
-rw-r--r--runtime/autoload/netrwSettings.vim3
-rw-r--r--runtime/autoload/provider/perl.vim80
-rw-r--r--runtime/autoload/provider/python3.vim44
-rw-r--r--runtime/autoload/provider/pythonx.vim112
-rw-r--r--runtime/autoload/provider/ruby.vim67
-rw-r--r--runtime/autoload/remote/host.vim6
-rw-r--r--runtime/autoload/rubycomplete.vim7
-rw-r--r--runtime/autoload/tar.vim39
-rw-r--r--runtime/autoload/tohtml.vim951
-rw-r--r--runtime/autoload/zip.vim3
-rw-r--r--runtime/colors/blue.vim25
-rw-r--r--runtime/colors/darkblue.vim17
-rw-r--r--runtime/colors/default.vim15
-rw-r--r--runtime/colors/delek.vim9
-rw-r--r--runtime/colors/desert.vim9
-rw-r--r--runtime/colors/elflord.vim9
-rw-r--r--runtime/colors/evening.vim21
-rw-r--r--runtime/colors/habamax.vim29
-rw-r--r--runtime/colors/industry.vim9
-rw-r--r--runtime/colors/koehler.vim9
-rw-r--r--runtime/colors/lunaperche.vim96
-rw-r--r--runtime/colors/morning.vim9
-rw-r--r--runtime/colors/murphy.vim11
-rw-r--r--runtime/colors/pablo.vim9
-rw-r--r--runtime/colors/peachpuff.vim9
-rw-r--r--runtime/colors/quiet.vim9
-rw-r--r--runtime/colors/retrobox.vim41
-rw-r--r--runtime/colors/ron.vim9
-rw-r--r--runtime/colors/shine.vim9
-rw-r--r--runtime/colors/slate.vim9
-rw-r--r--runtime/colors/sorbet.vim9
-rw-r--r--runtime/colors/torte.vim9
-rw-r--r--runtime/colors/vim.lua285
-rw-r--r--runtime/colors/wildcharm.vim125
-rw-r--r--runtime/colors/zaibatsu.vim9
-rw-r--r--runtime/colors/zellner.vim9
-rw-r--r--runtime/compiler/gm2.vim26
-rw-r--r--runtime/doc/api.txt495
-rw-r--r--runtime/doc/autocmd.txt16
-rw-r--r--runtime/doc/backers.txt (renamed from BACKERS.md)24
-rw-r--r--runtime/doc/builtin.txt213
-rw-r--r--runtime/doc/change.txt11
-rw-r--r--runtime/doc/cmdline.txt5
-rw-r--r--runtime/doc/deprecated.txt11
-rw-r--r--runtime/doc/dev_style.txt125
-rw-r--r--runtime/doc/dev_theme.txt121
-rw-r--r--runtime/doc/dev_tools.txt192
-rw-r--r--runtime/doc/dev_vimpatch.txt303
-rw-r--r--runtime/doc/develop.txt45
-rw-r--r--runtime/doc/diagnostic.txt609
-rw-r--r--runtime/doc/editing.txt5
-rw-r--r--runtime/doc/editorconfig.txt2
-rw-r--r--runtime/doc/eval.txt667
-rw-r--r--runtime/doc/faq.txt485
-rw-r--r--runtime/doc/filetype.txt33
-rw-r--r--runtime/doc/ft_ada.txt2
-rw-r--r--runtime/doc/ft_sql.txt2
-rw-r--r--runtime/doc/help.txt5
-rw-r--r--runtime/doc/indent.txt59
-rw-r--r--runtime/doc/index.txt2
-rw-r--r--runtime/doc/insert.txt4
-rw-r--r--runtime/doc/intro.txt3
-rw-r--r--runtime/doc/lsp.txt1322
-rw-r--r--runtime/doc/lua-guide.txt2
-rw-r--r--runtime/doc/lua.txt1859
-rw-r--r--runtime/doc/luaref.txt4
-rw-r--r--runtime/doc/luvref.txt58
-rw-r--r--runtime/doc/map.txt10
-rw-r--r--runtime/doc/message.txt2
-rw-r--r--runtime/doc/motion.txt22
-rw-r--r--runtime/doc/news.txt243
-rw-r--r--runtime/doc/nvim_terminal_emulator.txt27
-rw-r--r--runtime/doc/options.txt634
-rw-r--r--runtime/doc/pi_netrw.txt41
-rw-r--r--runtime/doc/quickfix.txt10
-rw-r--r--runtime/doc/quickref.txt10
-rw-r--r--runtime/doc/recover.txt8
-rw-r--r--runtime/doc/repeat.txt18
-rw-r--r--runtime/doc/syntax.txt773
-rw-r--r--runtime/doc/treesitter.txt726
-rw-r--r--runtime/doc/ui.txt20
-rw-r--r--runtime/doc/usr_41.txt6
-rw-r--r--runtime/doc/vim_diff.txt24
-rw-r--r--runtime/doc/visual.txt14
-rw-r--r--runtime/doc/vvars.txt735
-rw-r--r--runtime/doc/windows.txt7
-rw-r--r--runtime/ftplugin/aap.vim9
-rw-r--r--runtime/ftplugin/abap.vim15
-rw-r--r--runtime/ftplugin/abaqus.vim9
-rw-r--r--runtime/ftplugin/ant.vim15
-rw-r--r--runtime/ftplugin/asciidoc.vim67
-rw-r--r--runtime/ftplugin/aspvbs.vim15
-rw-r--r--runtime/ftplugin/awk.vim14
-rw-r--r--runtime/ftplugin/basic.vim10
-rw-r--r--runtime/ftplugin/c.vim32
-rw-r--r--runtime/ftplugin/clojure.vim9
-rw-r--r--runtime/ftplugin/cobol.vim9
-rw-r--r--runtime/ftplugin/config.vim15
-rw-r--r--runtime/ftplugin/cpp.vim3
-rw-r--r--runtime/ftplugin/cs.vim11
-rw-r--r--runtime/ftplugin/csh.vim10
-rw-r--r--runtime/ftplugin/diff.vim9
-rw-r--r--runtime/ftplugin/dosbatch.vim12
-rw-r--r--runtime/ftplugin/dtd.vim15
-rw-r--r--runtime/ftplugin/eiffel.vim10
-rw-r--r--runtime/ftplugin/elixir.vim10
-rw-r--r--runtime/ftplugin/erlang.vim18
-rw-r--r--runtime/ftplugin/eruby.vim11
-rw-r--r--runtime/ftplugin/expect.vim10
-rw-r--r--runtime/ftplugin/falcon.vim13
-rw-r--r--runtime/ftplugin/forth.vim9
-rw-r--r--runtime/ftplugin/fortran.vim36
-rw-r--r--runtime/ftplugin/fpcmake.vim12
-rw-r--r--runtime/ftplugin/freebasic.vim10
-rw-r--r--runtime/ftplugin/gdscript.vim68
-rw-r--r--runtime/ftplugin/gdshader.vim13
-rw-r--r--runtime/ftplugin/git.vim15
-rw-r--r--runtime/ftplugin/gitcommit.vim15
-rw-r--r--runtime/ftplugin/haml.vim15
-rw-r--r--runtime/ftplugin/help.lua29
-rw-r--r--runtime/ftplugin/help.vim4
-rw-r--r--runtime/ftplugin/html.vim12
-rw-r--r--runtime/ftplugin/hurl.vim11
-rw-r--r--runtime/ftplugin/icon.vim16
-rw-r--r--runtime/ftplugin/ishd.vim10
-rw-r--r--runtime/ftplugin/j.vim7
-rw-r--r--runtime/ftplugin/java.vim15
-rw-r--r--runtime/ftplugin/javascript.vim8
-rw-r--r--runtime/ftplugin/json5.vim10
-rw-r--r--runtime/ftplugin/jsp.vim15
-rw-r--r--runtime/ftplugin/kotlin.vim10
-rw-r--r--runtime/ftplugin/kwt.vim15
-rw-r--r--runtime/ftplugin/logtalk.dict19
-rw-r--r--runtime/ftplugin/lua.lua2
-rw-r--r--runtime/ftplugin/lua.vim10
-rw-r--r--runtime/ftplugin/lynx.vim10
-rw-r--r--runtime/ftplugin/m3build.vim10
-rw-r--r--runtime/ftplugin/m3quake.vim10
-rw-r--r--runtime/ftplugin/markdown.vim4
-rw-r--r--runtime/ftplugin/meson.vim9
-rw-r--r--runtime/ftplugin/modula2.vim43
-rw-r--r--runtime/ftplugin/modula3.vim10
-rw-r--r--runtime/ftplugin/msmessages.vim13
-rw-r--r--runtime/ftplugin/occam.vim17
-rw-r--r--runtime/ftplugin/octave.vim10
-rw-r--r--runtime/ftplugin/odin.vim26
-rw-r--r--runtime/ftplugin/pascal.vim10
-rw-r--r--runtime/ftplugin/perl.vim9
-rw-r--r--runtime/ftplugin/php.vim10
-rw-r--r--runtime/ftplugin/pod.vim10
-rw-r--r--runtime/ftplugin/poke.vim16
-rw-r--r--runtime/ftplugin/postscr.vim15
-rw-r--r--runtime/ftplugin/ps1.vim13
-rw-r--r--runtime/ftplugin/ps1xml.vim13
-rw-r--r--runtime/ftplugin/pyrex.vim13
-rw-r--r--runtime/ftplugin/python.vim9
-rw-r--r--runtime/ftplugin/qf.vim23
-rw-r--r--runtime/ftplugin/qml.vim12
-rw-r--r--runtime/ftplugin/query.lua2
-rw-r--r--runtime/ftplugin/r.vim17
-rw-r--r--runtime/ftplugin/racket.vim9
-rw-r--r--runtime/ftplugin/readline.vim10
-rw-r--r--runtime/ftplugin/registry.vim15
-rw-r--r--runtime/ftplugin/rhelp.vim17
-rw-r--r--runtime/ftplugin/rmd.vim17
-rw-r--r--runtime/ftplugin/rnoweb.vim17
-rw-r--r--runtime/ftplugin/routeros.vim9
-rw-r--r--runtime/ftplugin/rrst.vim17
-rw-r--r--runtime/ftplugin/ruby.vim53
-rw-r--r--runtime/ftplugin/sass.vim7
-rw-r--r--runtime/ftplugin/sbt.vim3
-rw-r--r--runtime/ftplugin/sed.vim10
-rw-r--r--runtime/ftplugin/sgml.vim15
-rw-r--r--runtime/ftplugin/sh.vim16
-rw-r--r--runtime/ftplugin/solution.vim10
-rw-r--r--runtime/ftplugin/sql.vim13
-rw-r--r--runtime/ftplugin/svg.vim15
-rw-r--r--runtime/ftplugin/tcl.vim13
-rw-r--r--runtime/ftplugin/tcsh.vim10
-rw-r--r--runtime/ftplugin/tidy.vim16
-rw-r--r--runtime/ftplugin/typescript.vim15
-rw-r--r--runtime/ftplugin/vb.vim10
-rw-r--r--runtime/ftplugin/verilog.vim13
-rw-r--r--runtime/ftplugin/vhdl.vim14
-rw-r--r--runtime/ftplugin/vim.vim13
-rw-r--r--runtime/ftplugin/wget.vim10
-rw-r--r--runtime/ftplugin/wget2.vim10
-rw-r--r--runtime/ftplugin/xhtml.vim15
-rw-r--r--runtime/ftplugin/xml.vim9
-rw-r--r--runtime/ftplugin/xsd.vim15
-rw-r--r--runtime/ftplugin/xslt.vim2
-rw-r--r--runtime/indent/cmake.vim49
-rw-r--r--runtime/indent/cucumber.vim77
-rw-r--r--runtime/indent/fortran.vim24
-rw-r--r--runtime/indent/gdscript.vim154
-rw-r--r--runtime/indent/odin.vim124
-rw-r--r--runtime/indent/qml.vim6
-rw-r--r--runtime/indent/query.lua2
-rw-r--r--runtime/indent/r.vim81
-rw-r--r--runtime/indent/racket.vim17
-rw-r--r--runtime/indent/rhelp.vim8
-rw-r--r--runtime/indent/rmd.vim8
-rw-r--r--runtime/indent/rnoweb.vim8
-rw-r--r--runtime/indent/rrst.vim8
-rw-r--r--runtime/indent/sass.vim6
-rw-r--r--runtime/indent/yaml.vim7
-rw-r--r--runtime/lua/man.lua2
-rw-r--r--runtime/lua/nvim/health.lua47
-rw-r--r--runtime/lua/provider/clipboard/health.lua40
-rw-r--r--runtime/lua/provider/health.lua916
-rw-r--r--runtime/lua/provider/node/health.lua105
-rw-r--r--runtime/lua/provider/perl/health.lua90
-rw-r--r--runtime/lua/provider/python/health.lua500
-rw-r--r--runtime/lua/provider/ruby/health.lua71
-rw-r--r--runtime/lua/tohtml.lua1349
-rw-r--r--runtime/lua/vim/F.lua5
-rw-r--r--runtime/lua/vim/_defaults.lua386
-rw-r--r--runtime/lua/vim/_editor.lua135
-rw-r--r--runtime/lua/vim/_init_packages.lua10
-rw-r--r--runtime/lua/vim/_inspector.lua35
-rw-r--r--runtime/lua/vim/_meta.lua4
-rw-r--r--runtime/lua/vim/_meta/api.lua1021
-rw-r--r--runtime/lua/vim/_meta/api_keysets.lua101
-rw-r--r--runtime/lua/vim/_meta/api_keysets_extra.lua167
-rw-r--r--runtime/lua/vim/_meta/builtin.lua133
-rw-r--r--runtime/lua/vim/_meta/builtin_types.lua6
-rw-r--r--runtime/lua/vim/_meta/json.lua2
-rw-r--r--runtime/lua/vim/_meta/lpeg.lua103
-rw-r--r--runtime/lua/vim/_meta/misc.lua3
-rw-r--r--runtime/lua/vim/_meta/mpack.lua5
-rw-r--r--runtime/lua/vim/_meta/options.lua736
-rw-r--r--runtime/lua/vim/_meta/re.lua54
-rw-r--r--runtime/lua/vim/_meta/regex.lua3
-rw-r--r--runtime/lua/vim/_meta/vimfn.lua268
-rw-r--r--runtime/lua/vim/_meta/vvars.lua779
-rw-r--r--runtime/lua/vim/_options.lua433
-rw-r--r--runtime/lua/vim/_system.lua12
-rw-r--r--runtime/lua/vim/_watch.lua304
-rw-r--r--runtime/lua/vim/diagnostic.lua1010
-rw-r--r--runtime/lua/vim/filetype.lua54
-rw-r--r--runtime/lua/vim/filetype/detect.lua78
-rw-r--r--runtime/lua/vim/fs.lua74
-rw-r--r--runtime/lua/vim/glob.lua84
-rw-r--r--runtime/lua/vim/health.lua235
-rw-r--r--runtime/lua/vim/highlight.lua37
-rw-r--r--runtime/lua/vim/iter.lua274
-rw-r--r--runtime/lua/vim/keymap.lua4
-rw-r--r--runtime/lua/vim/loader.lua90
-rw-r--r--runtime/lua/vim/lsp.lua1769
-rw-r--r--runtime/lua/vim/lsp/_changetracking.lua373
-rw-r--r--runtime/lua/vim/lsp/_completion.lua52
-rw-r--r--runtime/lua/vim/lsp/_dynamic.lua31
-rw-r--r--runtime/lua/vim/lsp/_meta.lua10
-rw-r--r--runtime/lua/vim/lsp/_meta/protocol.lua1320
-rw-r--r--runtime/lua/vim/lsp/_tagfunc.lua (renamed from runtime/lua/vim/lsp/tagfunc.lua)0
-rw-r--r--runtime/lua/vim/lsp/_watchfiles.lua118
-rw-r--r--runtime/lua/vim/lsp/buf.lua279
-rw-r--r--runtime/lua/vim/lsp/client.lua1056
-rw-r--r--runtime/lua/vim/lsp/codelens.lua45
-rw-r--r--runtime/lua/vim/lsp/diagnostic.lua208
-rw-r--r--runtime/lua/vim/lsp/handlers.lua212
-rw-r--r--runtime/lua/vim/lsp/health.lua46
-rw-r--r--runtime/lua/vim/lsp/inlay_hint.lua72
-rw-r--r--runtime/lua/vim/lsp/log.lua214
-rw-r--r--runtime/lua/vim/lsp/protocol.lua150
-rw-r--r--runtime/lua/vim/lsp/rpc.lua456
-rw-r--r--runtime/lua/vim/lsp/semantic_tokens.lua90
-rw-r--r--runtime/lua/vim/lsp/sync.lua57
-rw-r--r--runtime/lua/vim/lsp/util.lua274
-rw-r--r--runtime/lua/vim/provider.lua7
-rw-r--r--runtime/lua/vim/provider/perl.lua66
-rw-r--r--runtime/lua/vim/provider/python.lua150
-rw-r--r--runtime/lua/vim/provider/ruby.lua61
-rw-r--r--runtime/lua/vim/re.lua1
-rw-r--r--runtime/lua/vim/secure.lua25
-rw-r--r--runtime/lua/vim/shared.lua330
-rw-r--r--runtime/lua/vim/snippet.lua49
-rw-r--r--runtime/lua/vim/termcap.lua59
-rw-r--r--runtime/lua/vim/text.lua2
-rw-r--r--runtime/lua/vim/treesitter.lua164
-rw-r--r--runtime/lua/vim/treesitter/_fold.lua300
-rw-r--r--runtime/lua/vim/treesitter/_meta.lua28
-rw-r--r--runtime/lua/vim/treesitter/_query_linter.lua46
-rw-r--r--runtime/lua/vim/treesitter/dev.lua228
-rw-r--r--runtime/lua/vim/treesitter/health.lua2
-rw-r--r--runtime/lua/vim/treesitter/highlighter.lua194
-rw-r--r--runtime/lua/vim/treesitter/language.lua40
-rw-r--r--runtime/lua/vim/treesitter/languagetree.lua95
-rw-r--r--runtime/lua/vim/treesitter/query.lua602
-rw-r--r--runtime/lua/vim/ui.lua17
-rw-r--r--runtime/lua/vim/ui/clipboard/osc52.lua4
-rw-r--r--runtime/lua/vim/uri.lua19
-rw-r--r--runtime/lua/vim/version.lua101
-rw-r--r--runtime/lua/vim/vimhelp.lua36
-rw-r--r--runtime/macros/less.vim232
-rw-r--r--runtime/makemenu.vim6
-rw-r--r--runtime/mswin.vim23
-rw-r--r--runtime/nvim.appdata.xml2
-rw-r--r--runtime/pack/dist/opt/justify/plugin/justify.vim2
-rw-r--r--runtime/pack/dist/opt/termdebug/plugin/termdebug.vim176
-rw-r--r--runtime/plugin/netrwPlugin.vim3
-rw-r--r--runtime/plugin/osc52.lua18
-rw-r--r--runtime/plugin/tarPlugin.vim2
-rw-r--r--runtime/plugin/tohtml.lua12
-rw-r--r--runtime/plugin/tohtml.vim254
-rw-r--r--runtime/plugin/zipPlugin.vim3
-rw-r--r--runtime/queries/bash/folds.scm1
-rw-r--r--runtime/queries/bash/highlights.scm250
-rw-r--r--runtime/queries/c/folds.scm32
-rw-r--r--runtime/queries/c/highlights.scm182
-rw-r--r--runtime/queries/c/injections.scm23
-rw-r--r--runtime/queries/lua/folds.scm18
-rw-r--r--runtime/queries/lua/highlights.scm254
-rw-r--r--runtime/queries/lua/injections.scm119
-rw-r--r--runtime/queries/markdown/folds.scm16
-rw-r--r--runtime/queries/markdown/highlights.scm130
-rw-r--r--runtime/queries/markdown/injections.scm28
-rw-r--r--runtime/queries/markdown_inline/highlights.scm100
-rw-r--r--runtime/queries/markdown_inline/injections.scm9
-rw-r--r--runtime/queries/python/folds.scm5
-rw-r--r--runtime/queries/python/highlights.scm346
-rw-r--r--runtime/queries/query/highlights.scm79
-rw-r--r--runtime/queries/vim/folds.scm4
-rw-r--r--runtime/queries/vim/highlights.scm254
-rw-r--r--runtime/queries/vim/injections.scm64
-rw-r--r--runtime/queries/vimdoc/highlights.scm67
-rw-r--r--runtime/queries/vimdoc/injections.scm2
-rw-r--r--runtime/synmenu.vim49
-rw-r--r--runtime/syntax/2html.vim2068
-rw-r--r--runtime/syntax/8th.vim683
-rw-r--r--runtime/syntax/amiga.vim5
-rw-r--r--runtime/syntax/ant.vim94
-rw-r--r--runtime/syntax/c.vim12
-rw-r--r--runtime/syntax/chuck.vim187
-rw-r--r--runtime/syntax/cmake.vim4713
-rw-r--r--runtime/syntax/cpp.vim3
-rw-r--r--runtime/syntax/csh.vim5
-rw-r--r--runtime/syntax/css.vim19
-rw-r--r--runtime/syntax/cucumber.vim146
-rw-r--r--runtime/syntax/dcl.vim5
-rw-r--r--runtime/syntax/deb822sources.vim24
-rw-r--r--runtime/syntax/debcontrol.vim4
-rw-r--r--runtime/syntax/debsources.vim9
-rw-r--r--runtime/syntax/diff.vim6
-rw-r--r--runtime/syntax/dosbatch.vim31
-rw-r--r--runtime/syntax/elmfilt.vim5
-rw-r--r--runtime/syntax/exports.vim5
-rw-r--r--runtime/syntax/fortran.vim656
-rw-r--r--runtime/syntax/git.vim4
-rw-r--r--runtime/syntax/gitcommit.vim8
-rw-r--r--runtime/syntax/go.vim20
-rw-r--r--runtime/syntax/gpg.vim21
-rw-r--r--runtime/syntax/help.vim7
-rw-r--r--runtime/syntax/html.vim90
-rw-r--r--runtime/syntax/i3config.vim8
-rw-r--r--runtime/syntax/java.vim99
-rw-r--r--runtime/syntax/json5.vim9
-rw-r--r--runtime/syntax/lex.vim6
-rw-r--r--runtime/syntax/lisp.vim6
-rw-r--r--runtime/syntax/logtalk.vim51
-rw-r--r--runtime/syntax/mail.vim19
-rw-r--r--runtime/syntax/maple.vim6
-rw-r--r--runtime/syntax/masm.vim16
-rw-r--r--runtime/syntax/mermaid.vim52
-rw-r--r--runtime/syntax/modula2.vim71
-rw-r--r--runtime/syntax/modula2/opt/iso.vim380
-rw-r--r--runtime/syntax/modula2/opt/pim.vim377
-rw-r--r--runtime/syntax/modula2/opt/r10.vim452
-rw-r--r--runtime/syntax/netrw.vim6
-rw-r--r--runtime/syntax/odin.vim109
-rw-r--r--runtime/syntax/pacmanlog.vim41
-rw-r--r--runtime/syntax/qf.vim6
-rw-r--r--runtime/syntax/quarto.vim8
-rw-r--r--runtime/syntax/query.lua2
-rw-r--r--runtime/syntax/r.vim20
-rw-r--r--runtime/syntax/racket.vim9
-rw-r--r--runtime/syntax/rhelp.vim10
-rw-r--r--runtime/syntax/rmd.vim56
-rw-r--r--runtime/syntax/rpcgen.vim6
-rw-r--r--runtime/syntax/sh.vim50
-rw-r--r--runtime/syntax/shared/debversions.vim6
-rw-r--r--runtime/syntax/sm.vim6
-rw-r--r--runtime/syntax/spec.vim2
-rw-r--r--runtime/syntax/squirrel.vim3
-rw-r--r--runtime/syntax/swayconfig.vim12
-rw-r--r--runtime/syntax/tags.vim6
-rw-r--r--runtime/syntax/tex.vim6
-rw-r--r--runtime/syntax/tmux.vim160
-rw-r--r--runtime/syntax/vim.vim337
-rw-r--r--runtime/syntax/xmath.vim6
-rw-r--r--runtime/syntax/xxd.vim6
-rw-r--r--runtime/syntax/yacc.vim5
-rw-r--r--runtime/tutor/en/vim-01-beginner.tutor10
-rw-r--r--runtime/tutor/ja/vim-01-beginner.tutor995
-rw-r--r--runtime/tutor/ja/vim-01-beginner.tutor.json44
-rwxr-xr-xscripts/bump_deps.lua53
-rw-r--r--scripts/cdoc_grammar.lua87
-rw-r--r--scripts/cdoc_parser.lua223
-rwxr-xr-xscripts/gen_eval_files.lua406
-rw-r--r--scripts/gen_filetype.lua102
-rw-r--r--scripts/gen_help_html.lua587
-rw-r--r--scripts/gen_lsp.lua294
-rwxr-xr-xscripts/gen_vimdoc.lua953
-rwxr-xr-xscripts/gen_vimdoc.py1447
-rwxr-xr-xscripts/genappimage.sh6
-rw-r--r--scripts/lintcommit.lua76
-rwxr-xr-xscripts/lintdoc.lua20
-rw-r--r--scripts/lua2dox.lua475
-rw-r--r--scripts/luacats_grammar.lua184
-rw-r--r--scripts/luacats_parser.lua537
-rw-r--r--scripts/text_utils.lua361
-rwxr-xr-xscripts/vim-patch.sh6
-rwxr-xr-xscripts/vimpatch.lua10
-rw-r--r--scripts/windows.ti6
-rwxr-xr-xsrc/clint.py168
-rw-r--r--src/klib/kbtree.h477
-rw-r--r--src/klib/kvec.h9
-rw-r--r--src/mpack/lmpack.c4
-rw-r--r--src/nvim/CMakeLists.txt379
-rw-r--r--src/nvim/README.md68
-rw-r--r--src/nvim/api/autocmd.c252
-rw-r--r--src/nvim/api/buffer.c347
-rw-r--r--src/nvim/api/buffer.h3
-rw-r--r--src/nvim/api/command.c218
-rw-r--r--src/nvim/api/deprecated.c114
-rw-r--r--src/nvim/api/deprecated.h1
-rw-r--r--src/nvim/api/dispatch_deprecated.lua132
-rw-r--r--src/nvim/api/extmark.c360
-rw-r--r--src/nvim/api/keysets_defs.h76
-rw-r--r--src/nvim/api/options.c344
-rw-r--r--src/nvim/api/private/converter.c121
-rw-r--r--src/nvim/api/private/defs.h10
-rw-r--r--src/nvim/api/private/dispatch.h16
-rw-r--r--src/nvim/api/private/helpers.c282
-rw-r--r--src/nvim/api/private/helpers.h30
-rw-r--r--src/nvim/api/private/validate.h2
-rw-r--r--src/nvim/api/tabpage.c54
-rw-r--r--src/nvim/api/ui.c499
-rw-r--r--src/nvim/api/ui.h19
-rw-r--r--src/nvim/api/ui_events.in.h2
-rw-r--r--src/nvim/api/vim.c600
-rw-r--r--src/nvim/api/vimscript.c285
-rw-r--r--src/nvim/api/win_config.c630
-rw-r--r--src/nvim/api/window.c45
-rw-r--r--src/nvim/arabic.c20
-rw-r--r--src/nvim/arglist.c37
-rw-r--r--src/nvim/arglist.h4
-rw-r--r--src/nvim/arglist_defs.h4
-rw-r--r--src/nvim/ascii_defs.h47
-rw-r--r--src/nvim/assert_defs.h2
-rw-r--r--src/nvim/auevents.lua304
-rw-r--r--src/nvim/autocmd.c86
-rw-r--r--src/nvim/autocmd.h66
-rw-r--r--src/nvim/autocmd_defs.h8
-rw-r--r--src/nvim/base64.c3
-rw-r--r--src/nvim/buffer.c558
-rw-r--r--src/nvim/buffer.h64
-rw-r--r--src/nvim/buffer_defs.h177
-rw-r--r--src/nvim/buffer_updates.c114
-rw-r--r--src/nvim/bufwrite.c57
-rw-r--r--src/nvim/bufwrite.h2
-rw-r--r--src/nvim/change.c240
-rw-r--r--src/nvim/change.h4
-rw-r--r--src/nvim/channel.c139
-rw-r--r--src/nvim/channel.h72
-rw-r--r--src/nvim/channel_defs.h61
-rw-r--r--src/nvim/charset.c16
-rw-r--r--src/nvim/charset.h7
-rw-r--r--src/nvim/cmdexpand.c54
-rw-r--r--src/nvim/cmdexpand.h5
-rw-r--r--src/nvim/cmdexpand_defs.h4
-rw-r--r--src/nvim/cmdhist.c7
-rw-r--r--src/nvim/cmdhist.h13
-rw-r--r--src/nvim/context.c31
-rw-r--r--src/nvim/cursor.c27
-rw-r--r--src/nvim/cursor.h2
-rw-r--r--src/nvim/cursor_shape.c23
-rw-r--r--src/nvim/cursor_shape.h2
-rw-r--r--src/nvim/debugger.c19
-rw-r--r--src/nvim/decoration.c418
-rw-r--r--src/nvim/decoration.h26
-rw-r--r--src/nvim/decoration_defs.h38
-rw-r--r--src/nvim/decoration_provider.c142
-rw-r--r--src/nvim/decoration_provider.h26
-rw-r--r--src/nvim/diff.c52
-rw-r--r--src/nvim/diff.h11
-rw-r--r--src/nvim/digraph.c21
-rw-r--r--src/nvim/digraph.h1
-rw-r--r--src/nvim/drawline.c1471
-rw-r--r--src/nvim/drawline.h8
-rw-r--r--src/nvim/drawscreen.c347
-rw-r--r--src/nvim/drawscreen.h9
-rw-r--r--src/nvim/edit.c269
-rw-r--r--src/nvim/edit.h2
-rw-r--r--src/nvim/eval.c512
-rw-r--r--src/nvim/eval.h61
-rw-r--r--src/nvim/eval.lua324
-rw-r--r--src/nvim/eval/buffer.c8
-rw-r--r--src/nvim/eval/decode.c18
-rw-r--r--src/nvim/eval/encode.c17
-rw-r--r--src/nvim/eval/encode.h18
-rw-r--r--src/nvim/eval/executor.c5
-rw-r--r--src/nvim/eval/funcs.c713
-rw-r--r--src/nvim/eval/funcs.h1
-rw-r--r--src/nvim/eval/gc.h2
-rw-r--r--src/nvim/eval/typval.c62
-rw-r--r--src/nvim/eval/typval.h23
-rw-r--r--src/nvim/eval/typval_defs.h20
-rw-r--r--src/nvim/eval/typval_encode.c.h3
-rw-r--r--src/nvim/eval/userfunc.c45
-rw-r--r--src/nvim/eval/userfunc.h4
-rw-r--r--src/nvim/eval/vars.c116
-rw-r--r--src/nvim/eval/window.c94
-rw-r--r--src/nvim/eval/window.h70
-rw-r--r--src/nvim/eval_defs.h30
-rw-r--r--src/nvim/event/defs.h171
-rw-r--r--src/nvim/event/libuv_process.c14
-rw-r--r--src/nvim/event/libuv_process.h13
-rw-r--r--src/nvim/event/loop.c5
-rw-r--r--src/nvim/event/loop.h48
-rw-r--r--src/nvim/event/multiqueue.c7
-rw-r--r--src/nvim/event/multiqueue.h56
-rw-r--r--src/nvim/event/process.c15
-rw-r--r--src/nvim/event/process.h39
-rw-r--r--src/nvim/event/rstream.c14
-rw-r--r--src/nvim/event/rstream.h8
-rw-r--r--src/nvim/event/signal.c6
-rw-r--r--src/nvim/event/signal.h20
-rw-r--r--src/nvim/event/socket.c11
-rw-r--r--src/nvim/event/socket.h36
-rw-r--r--src/nvim/event/stream.c14
-rw-r--r--src/nvim/event/stream.h58
-rw-r--r--src/nvim/event/time.c9
-rw-r--r--src/nvim/event/time.h20
-rw-r--r--src/nvim/event/wstream.c5
-rw-r--r--src/nvim/event/wstream.h20
-rw-r--r--src/nvim/ex_cmds.c163
-rw-r--r--src/nvim/ex_cmds.h44
-rw-r--r--src/nvim/ex_cmds.lua4478
-rw-r--r--src/nvim/ex_cmds2.c39
-rw-r--r--src/nvim/ex_cmds2.h2
-rw-r--r--src/nvim/ex_cmds_defs.h12
-rw-r--r--src/nvim/ex_docmd.c192
-rw-r--r--src/nvim/ex_docmd.h2
-rw-r--r--src/nvim/ex_eval.c49
-rw-r--r--src/nvim/ex_eval.h2
-rw-r--r--src/nvim/ex_eval_defs.h8
-rw-r--r--src/nvim/ex_getln.c154
-rw-r--r--src/nvim/ex_getln.h69
-rw-r--r--src/nvim/ex_getln_defs.h68
-rw-r--r--src/nvim/ex_session.c80
-rw-r--r--src/nvim/extmark.c166
-rw-r--r--src/nvim/extmark.h13
-rw-r--r--src/nvim/extmark_defs.h1
-rw-r--r--src/nvim/file_search.c54
-rw-r--r--src/nvim/file_search.h14
-rw-r--r--src/nvim/fileio.c77
-rw-r--r--src/nvim/fileio.h66
-rw-r--r--src/nvim/fold.c83
-rw-r--r--src/nvim/fold.h11
-rw-r--r--src/nvim/fold_defs.h2
-rw-r--r--src/nvim/func_attr.h29
-rw-r--r--src/nvim/garray.c12
-rw-r--r--src/nvim/garray.h13
-rw-r--r--src/nvim/garray_defs.h2
-rw-r--r--src/nvim/generators/c_grammar.lua131
-rw-r--r--src/nvim/generators/dump_bin_array.lua4
-rw-r--r--src/nvim/generators/gen_api_dispatch.lua714
-rw-r--r--src/nvim/generators/gen_api_ui_events.lua121
-rw-r--r--src/nvim/generators/gen_char_blob.lua31
-rw-r--r--src/nvim/generators/gen_declarations.lua200
-rw-r--r--src/nvim/generators/gen_eval.lua43
-rw-r--r--src/nvim/generators/gen_events.lua10
-rw-r--r--src/nvim/generators/gen_ex_cmds.lua81
-rw-r--r--src/nvim/generators/gen_options.lua156
-rw-r--r--src/nvim/generators/gen_options_enum.lua129
-rw-r--r--src/nvim/generators/gen_unicode_tables.lua33
-rw-r--r--src/nvim/generators/gen_vimvim.lua20
-rw-r--r--src/nvim/generators/hashy.lua83
-rw-r--r--src/nvim/generators/nvim_version.lua.in9
-rw-r--r--src/nvim/generators/preload.lua7
-rw-r--r--src/nvim/getchar.c187
-rw-r--r--src/nvim/getchar.h14
-rw-r--r--src/nvim/getchar_defs.h13
-rw-r--r--src/nvim/gettext_defs.h (renamed from src/nvim/gettext.h)0
-rw-r--r--src/nvim/globals.h135
-rw-r--r--src/nvim/grid.c308
-rw-r--r--src/nvim/grid.h18
-rw-r--r--src/nvim/hashtab.c11
-rw-r--r--src/nvim/hashtab.h2
-rw-r--r--src/nvim/hashtab_defs.h16
-rw-r--r--src/nvim/help.c74
-rw-r--r--src/nvim/highlight.c163
-rw-r--r--src/nvim/highlight.h104
-rw-r--r--src/nvim/highlight_defs.h240
-rw-r--r--src/nvim/highlight_group.c623
-rw-r--r--src/nvim/highlight_group.h7
-rw-r--r--src/nvim/indent.c433
-rw-r--r--src/nvim/indent.h1
-rw-r--r--src/nvim/indent_c.c12
-rw-r--r--src/nvim/indent_c.h2
-rw-r--r--src/nvim/input.c20
-rw-r--r--src/nvim/input.h2
-rw-r--r--src/nvim/insexpand.c174
-rw-r--r--src/nvim/insexpand.h3
-rw-r--r--src/nvim/keycodes.c42
-rw-r--r--src/nvim/keycodes.h11
-rw-r--r--src/nvim/lib/queue_defs.h (renamed from src/nvim/lib/queue.h)32
-rw-r--r--src/nvim/lib/ringbuf.h290
-rw-r--r--src/nvim/log.c4
-rw-r--r--src/nvim/log.h12
-rw-r--r--src/nvim/lua/converter.c261
-rw-r--r--src/nvim/lua/executor.c219
-rw-r--r--src/nvim/lua/executor.h24
-rw-r--r--src/nvim/lua/secure.c2
-rw-r--r--src/nvim/lua/spell.c6
-rw-r--r--src/nvim/lua/stdlib.c33
-rw-r--r--src/nvim/lua/treesitter.c40
-rw-r--r--src/nvim/lua/xdiff.c173
-rw-r--r--src/nvim/macros_defs.h44
-rw-r--r--src/nvim/main.c284
-rw-r--r--src/nvim/main.h1
-rw-r--r--src/nvim/map_defs.h20
-rw-r--r--src/nvim/mapping.c261
-rw-r--r--src/nvim/mapping.h29
-rw-r--r--src/nvim/mapping_defs.h4
-rw-r--r--src/nvim/mark.c22
-rw-r--r--src/nvim/mark.h119
-rw-r--r--src/nvim/mark_defs.h49
-rw-r--r--src/nvim/marktree.c437
-rw-r--r--src/nvim/marktree.h103
-rw-r--r--src/nvim/marktree_defs.h103
-rw-r--r--src/nvim/match.c13
-rw-r--r--src/nvim/math.c31
-rw-r--r--src/nvim/math.h9
-rw-r--r--src/nvim/mbyte.c406
-rw-r--r--src/nvim/mbyte.h116
-rw-r--r--src/nvim/mbyte_defs.h31
-rw-r--r--src/nvim/memfile.c14
-rw-r--r--src/nvim/memfile.h4
-rw-r--r--src/nvim/memfile_defs.h6
-rw-r--r--src/nvim/memline.c114
-rw-r--r--src/nvim/memline.h8
-rw-r--r--src/nvim/memline_defs.h7
-rw-r--r--src/nvim/memory.c134
-rw-r--r--src/nvim/memory.h4
-rw-r--r--src/nvim/menu.c29
-rw-r--r--src/nvim/menu.h2
-rw-r--r--src/nvim/message.c265
-rw-r--r--src/nvim/message.h31
-rw-r--r--src/nvim/message_defs.h22
-rw-r--r--src/nvim/mouse.c140
-rw-r--r--src/nvim/mouse.h3
-rw-r--r--src/nvim/move.c164
-rw-r--r--src/nvim/move.h5
-rw-r--r--src/nvim/msgpack_rpc/channel.c284
-rw-r--r--src/nvim/msgpack_rpc/channel.h8
-rw-r--r--src/nvim/msgpack_rpc/channel_defs.h4
-rw-r--r--src/nvim/msgpack_rpc/helpers.c547
-rw-r--r--src/nvim/msgpack_rpc/helpers.h20
-rw-r--r--src/nvim/msgpack_rpc/packer.c235
-rw-r--r--src/nvim/msgpack_rpc/packer.h76
-rw-r--r--src/nvim/msgpack_rpc/packer_defs.h24
-rw-r--r--src/nvim/msgpack_rpc/server.c3
-rw-r--r--src/nvim/msgpack_rpc/unpacker.c6
-rw-r--r--src/nvim/msgpack_rpc/unpacker.h6
-rw-r--r--src/nvim/normal.c126
-rw-r--r--src/nvim/normal.h6
-rw-r--r--src/nvim/normal_defs.h7
-rw-r--r--src/nvim/ops.c494
-rw-r--r--src/nvim/ops.h29
-rw-r--r--src/nvim/option.c1897
-rw-r--r--src/nvim/option.h83
-rw-r--r--src/nvim/option_defs.h20
-rw-r--r--src/nvim/option_vars.h234
-rw-r--r--src/nvim/options.lua1474
-rw-r--r--src/nvim/optionstr.c432
-rw-r--r--src/nvim/optionstr.h7
-rw-r--r--src/nvim/os/dl.c2
-rw-r--r--src/nvim/os/env.c64
-rw-r--r--src/nvim/os/fileio.c101
-rw-r--r--src/nvim/os/fileio.h43
-rw-r--r--src/nvim/os/fileio_defs.h43
-rw-r--r--src/nvim/os/fs.c29
-rw-r--r--src/nvim/os/fs.h2
-rw-r--r--src/nvim/os/input.c28
-rw-r--r--src/nvim/os/input.h2
-rw-r--r--src/nvim/os/lang.c40
-rw-r--r--src/nvim/os/os.h22
-rw-r--r--src/nvim/os/os_defs.h28
-rw-r--r--src/nvim/os/os_win_console.c38
-rw-r--r--src/nvim/os/process.c12
-rw-r--r--src/nvim/os/pty_conpty_win.c1
-rw-r--r--src/nvim/os/pty_conpty_win.h2
-rw-r--r--src/nvim/os/pty_process_unix.c14
-rw-r--r--src/nvim/os/pty_process_unix.h15
-rw-r--r--src/nvim/os/pty_process_win.c49
-rw-r--r--src/nvim/os/pty_process_win.h14
-rw-r--r--src/nvim/os/shell.c32
-rw-r--r--src/nvim/os/signal.c4
-rw-r--r--src/nvim/os/stdpaths.c5
-rw-r--r--src/nvim/os/time.c6
-rw-r--r--src/nvim/os/time.h2
-rw-r--r--src/nvim/os/tty.c49
-rw-r--r--src/nvim/os/tty.h5
-rw-r--r--src/nvim/os/users.c8
-rw-r--r--src/nvim/path.c52
-rw-r--r--src/nvim/path.h43
-rw-r--r--src/nvim/plines.c585
-rw-r--r--src/nvim/plines.h101
-rw-r--r--src/nvim/po/CMakeLists.txt11
-rw-r--r--src/nvim/po/uk.po420
-rw-r--r--src/nvim/popupmenu.c282
-rw-r--r--src/nvim/popupmenu.h1
-rw-r--r--src/nvim/pos_defs.h16
-rw-r--r--src/nvim/profile.c57
-rw-r--r--src/nvim/quickfix.c83
-rw-r--r--src/nvim/quickfix.h1
-rw-r--r--src/nvim/rbuffer.c24
-rw-r--r--src/nvim/rbuffer.h34
-rw-r--r--src/nvim/rbuffer_defs.h45
-rw-r--r--src/nvim/regexp.c318
-rw-r--r--src/nvim/regexp.h4
-rw-r--r--src/nvim/regexp_defs.h144
-rw-r--r--src/nvim/runtime.c64
-rw-r--r--src/nvim/runtime.h2
-rw-r--r--src/nvim/runtime_defs.h5
-rw-r--r--src/nvim/search.c60
-rw-r--r--src/nvim/search.h99
-rw-r--r--src/nvim/shada.c201
-rw-r--r--src/nvim/sign.c142
-rw-r--r--src/nvim/sign.h3
-rw-r--r--src/nvim/sign_defs.h15
-rw-r--r--src/nvim/spell.c51
-rw-r--r--src/nvim/spell.h7
-rw-r--r--src/nvim/spell_defs.h34
-rw-r--r--src/nvim/spellfile.c56
-rw-r--r--src/nvim/spellsuggest.c59
-rw-r--r--src/nvim/state.c12
-rw-r--r--src/nvim/state.h2
-rw-r--r--src/nvim/statusline.c213
-rw-r--r--src/nvim/statusline.h5
-rw-r--r--src/nvim/statusline_defs.h15
-rw-r--r--src/nvim/strings.c176
-rw-r--r--src/nvim/strings.h7
-rw-r--r--src/nvim/syntax.c149
-rw-r--r--src/nvim/syntax.h47
-rw-r--r--src/nvim/syntax_defs.h9
-rw-r--r--src/nvim/tag.c75
-rw-r--r--src/nvim/tag.h2
-rw-r--r--src/nvim/terminal.c206
-rw-r--r--src/nvim/terminal.h10
-rw-r--r--src/nvim/testing.c6
-rw-r--r--src/nvim/textformat.c59
-rw-r--r--src/nvim/textobject.c40
-rw-r--r--src/nvim/textobject.h2
-rw-r--r--src/nvim/tui/input.c90
-rw-r--r--src/nvim/tui/input.h14
-rw-r--r--src/nvim/tui/terminfo_defs.h55
-rw-r--r--src/nvim/tui/tui.c350
-rw-r--r--src/nvim/tui/tui.h19
-rw-r--r--src/nvim/tui/tui_defs.h15
-rw-r--r--src/nvim/types_defs.h10
-rw-r--r--src/nvim/ugrid.h4
-rw-r--r--src/nvim/ui.c124
-rw-r--r--src/nvim/ui.h125
-rw-r--r--src/nvim/ui_client.c46
-rw-r--r--src/nvim/ui_client.h9
-rw-r--r--src/nvim/ui_compositor.c20
-rw-r--r--src/nvim/ui_compositor.h3
-rw-r--r--src/nvim/ui_defs.h90
-rw-r--r--src/nvim/undo.c79
-rw-r--r--src/nvim/undo.h4
-rw-r--r--src/nvim/undo_defs.h6
-rw-r--r--src/nvim/usercmd.c83
-rw-r--r--src/nvim/usercmd.h5
-rw-r--r--src/nvim/version.c38
-rw-r--r--src/nvim/version.h1
-rw-r--r--src/nvim/vim_defs.h50
-rw-r--r--src/nvim/viml/parser/expressions.c3
-rw-r--r--src/nvim/viml/parser/expressions.h4
-rw-r--r--src/nvim/viml/parser/parser.c63
-rw-r--r--src/nvim/viml/parser/parser.h141
-rw-r--r--src/nvim/viml/parser/parser_defs.h79
-rw-r--r--src/nvim/vvars.lua885
-rw-r--r--src/nvim/window.c304
-rw-r--r--src/nvim/window.h27
-rw-r--r--src/nvim/winfloat.c69
-rw-r--r--src/nvim/winfloat.h7
-rw-r--r--src/termkey/driver-csi.c772
-rw-r--r--src/termkey/driver-ti.c654
-rw-r--r--src/termkey/termkey-internal.h112
-rw-r--r--src/termkey/termkey.c1606
-rw-r--r--src/termkey/termkey.h249
-rw-r--r--src/uncrustify.cfg1
-rw-r--r--src/unicode/CaseFolding.txt9
-rw-r--r--src/unicode/EastAsianWidth.txt5170
-rw-r--r--src/unicode/UnicodeData.txt7
-rw-r--r--src/unicode/emoji-data.txt6
-rw-r--r--test/.luarc.json2
-rw-r--r--test/CMakeLists.txt55
-rw-r--r--test/benchmark/autocmd_spec.lua56
-rw-r--r--test/benchmark/bench_regexp_spec.lua3
-rw-r--r--test/benchmark/deepcopy_spec.lua58
-rw-r--r--test/benchmark/screenpos_spec.lua376
-rw-r--r--test/benchmark/treesitter_spec.lua7
-rw-r--r--test/busted/outputHandlers/nvim.lua95
-rw-r--r--test/client/msgpack_rpc_stream.lua53
-rw-r--r--test/client/session.lua44
-rw-r--r--test/client/uv_stream.lua63
-rw-r--r--test/deprecated.lua9
-rw-r--r--test/format_string.lua168
-rw-r--r--test/functional/api/autocmd_spec.lua1093
-rw-r--r--test/functional/api/buffer_spec.lua1598
-rw-r--r--test/functional/api/buffer_updates_spec.lua544
-rw-r--r--test/functional/api/command_spec.lua985
-rw-r--r--test/functional/api/extmark_spec.lua1046
-rw-r--r--test/functional/api/highlight_spec.lua530
-rw-r--r--test/functional/api/keymap_spec.lua997
-rw-r--r--test/functional/api/menu_spec.lua29
-rw-r--r--test/functional/api/proc_spec.lua36
-rw-r--r--test/functional/api/rpc_fixture.lua10
-rw-r--r--test/functional/api/server_notifications_spec.lua67
-rw-r--r--test/functional/api/server_requests_spec.lua203
-rw-r--r--test/functional/api/tabpage_spec.lua150
-rw-r--r--test/functional/api/ui_spec.lua98
-rw-r--r--test/functional/api/version_spec.lua191
-rw-r--r--test/functional/api/vim_spec.lua3895
-rw-r--r--test/functional/api/window_spec.lua1908
-rw-r--r--test/functional/autocmd/autocmd_oldtest_spec.lua45
-rw-r--r--test/functional/autocmd/autocmd_spec.lua322
-rw-r--r--test/functional/autocmd/bufenter_spec.lua25
-rw-r--r--test/functional/autocmd/bufmodifiedset_spec.lua4
-rw-r--r--test/functional/autocmd/cmdline_spec.lua142
-rw-r--r--test/functional/autocmd/cursorhold_spec.lua50
-rw-r--r--test/functional/autocmd/cursormoved_spec.lua12
-rw-r--r--test/functional/autocmd/dirchanged_spec.lua266
-rw-r--r--test/functional/autocmd/filetype_spec.lua16
-rw-r--r--test/functional/autocmd/focus_spec.lua61
-rw-r--r--test/functional/autocmd/modechanged_spec.lua6
-rw-r--r--test/functional/autocmd/safestate_spec.lua22
-rw-r--r--test/functional/autocmd/searchwrapped_spec.lua7
-rw-r--r--test/functional/autocmd/show_spec.lua66
-rw-r--r--test/functional/autocmd/signal_spec.lua22
-rw-r--r--test/functional/autocmd/tabclose_spec.lua79
-rw-r--r--test/functional/autocmd/tabnewentered_spec.lua505
-rw-r--r--test/functional/autocmd/termxx_spec.lua158
-rw-r--r--test/functional/autocmd/textchanged_spec.lua27
-rw-r--r--test/functional/autocmd/textyankpost_spec.lua54
-rw-r--r--test/functional/autocmd/win_scrolled_resized_spec.lua163
-rw-r--r--test/functional/core/channels_spec.lua250
-rw-r--r--test/functional/core/exit_spec.lua19
-rw-r--r--test/functional/core/fileio_spec.lua258
-rw-r--r--test/functional/core/job_spec.lua778
-rw-r--r--test/functional/core/log_spec.lua16
-rw-r--r--test/functional/core/main_spec.lua167
-rw-r--r--test/functional/core/path_spec.lua50
-rw-r--r--test/functional/core/remote_spec.lua39
-rw-r--r--test/functional/core/spellfile_spec.lua55
-rw-r--r--test/functional/core/startup_spec.lua907
-rw-r--r--test/functional/editor/K_spec.lua25
-rw-r--r--test/functional/editor/completion_spec.lua589
-rw-r--r--test/functional/editor/ctrl_c_spec.lua40
-rw-r--r--test/functional/editor/fold_spec.lua226
-rw-r--r--test/functional/editor/jump_spec.lua310
-rw-r--r--test/functional/editor/lang_spec.lua46
-rw-r--r--test/functional/editor/langmap_spec.lua44
-rw-r--r--test/functional/editor/macro_spec.lua102
-rw-r--r--test/functional/editor/mark_spec.lua426
-rw-r--r--test/functional/editor/meta_key_spec.lua8
-rw-r--r--test/functional/editor/mode_cmdline_spec.lua62
-rw-r--r--test/functional/editor/mode_insert_spec.lua49
-rw-r--r--test/functional/editor/mode_normal_spec.lua22
-rw-r--r--test/functional/editor/put_spec.lua361
-rw-r--r--test/functional/editor/search_spec.lua7
-rw-r--r--test/functional/editor/tabpage_spec.lua81
-rw-r--r--test/functional/editor/undo_spec.lua38
-rw-r--r--test/functional/ex_cmds/append_spec.lua40
-rw-r--r--test/functional/ex_cmds/arg_spec.lua38
-rw-r--r--test/functional/ex_cmds/cd_spec.lua75
-rw-r--r--test/functional/ex_cmds/cmd_map_spec.lua333
-rw-r--r--test/functional/ex_cmds/debug_spec.lua39
-rw-r--r--test/functional/ex_cmds/dict_notifications_spec.lua194
-rw-r--r--test/functional/ex_cmds/digraphs_spec.lua14
-rw-r--r--test/functional/ex_cmds/drop_spec.lua64
-rw-r--r--test/functional/ex_cmds/echo_spec.lua224
-rw-r--r--test/functional/ex_cmds/edit_spec.lua30
-rw-r--r--test/functional/ex_cmds/encoding_spec.lua5
-rw-r--r--test/functional/ex_cmds/excmd_spec.lua52
-rw-r--r--test/functional/ex_cmds/file_spec.lua18
-rw-r--r--test/functional/ex_cmds/grep_spec.lua4
-rw-r--r--test/functional/ex_cmds/help_spec.lua14
-rw-r--r--test/functional/ex_cmds/highlight_spec.lua35
-rw-r--r--test/functional/ex_cmds/ls_spec.lua6
-rw-r--r--test/functional/ex_cmds/make_spec.lua23
-rw-r--r--test/functional/ex_cmds/map_spec.lua85
-rw-r--r--test/functional/ex_cmds/menu_spec.lua416
-rw-r--r--test/functional/ex_cmds/mksession_spec.lua93
-rw-r--r--test/functional/ex_cmds/mkview_spec.lua12
-rw-r--r--test/functional/ex_cmds/normal_spec.lua10
-rw-r--r--test/functional/ex_cmds/oldfiles_spec.lua48
-rw-r--r--test/functional/ex_cmds/print_commands_spec.lua5
-rw-r--r--test/functional/ex_cmds/profile_spec.lua22
-rw-r--r--test/functional/ex_cmds/quickfix_commands_spec.lua145
-rw-r--r--test/functional/ex_cmds/quit_spec.lua1
-rw-r--r--test/functional/ex_cmds/script_spec.lua45
-rw-r--r--test/functional/ex_cmds/sign_spec.lua26
-rw-r--r--test/functional/ex_cmds/source_spec.lua75
-rw-r--r--test/functional/ex_cmds/swapfile_preserve_recover_spec.lua344
-rw-r--r--test/functional/ex_cmds/syntax_spec.lua9
-rw-r--r--test/functional/ex_cmds/trust_spec.lua35
-rw-r--r--test/functional/ex_cmds/verbose_spec.lua122
-rw-r--r--test/functional/ex_cmds/wincmd_spec.lua8
-rw-r--r--test/functional/ex_cmds/write_spec.lua92
-rw-r--r--test/functional/ex_cmds/wundo_spec.lua23
-rw-r--r--test/functional/ex_cmds/wviminfo_spec.lua33
-rw-r--r--test/functional/example_spec.lua29
-rw-r--r--test/functional/fixtures/CMakeLists.txt2
-rw-r--r--test/functional/fixtures/fake-lsp-server.lua661
-rw-r--r--test/functional/fixtures/middle/filen.lua2
-rw-r--r--test/functional/fixtures/nvim/after/filen.lua2
-rw-r--r--test/functional/fixtures/nvim/filen.lua2
-rw-r--r--test/functional/fixtures/pack/foo/opt/bonus/lua/bonus.lua6
-rw-r--r--test/functional/fixtures/pack/foo/opt/funky/filen.lua4
-rw-r--r--test/functional/fixtures/pack/foo/opt/superspecial/after/filen.lua2
-rw-r--r--test/functional/fixtures/pack/foo/opt/superspecial/filen.lua2
-rw-r--r--test/functional/fixtures/pack/foo/start/bar/lua/bar.lua6
-rw-r--r--test/functional/fixtures/pack/foo/start/bar/lua/baz-quux.lua6
-rw-r--r--test/functional/fixtures/pack/foo/start/fancyplugin/after/filen.lua2
-rw-r--r--test/functional/fixtures/pack/foo/start/fancyplugin/after/lua/fancy_y.lua2
-rw-r--r--test/functional/fixtures/pack/foo/start/fancyplugin/after/lua/fancy_z.lua2
-rw-r--r--test/functional/fixtures/pack/foo/start/fancyplugin/filen.lua2
-rw-r--r--test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_x.lua2
-rw-r--r--test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_x/init.lua2
-rw-r--r--test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_y/init.lua3
-rw-r--r--test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua7
-rw-r--r--test/functional/fixtures/start/nvim-leftpad/lua/leftpad.lua4
-rw-r--r--test/functional/helpers.lua616
-rw-r--r--test/functional/legacy/008_autocommands_spec.lua18
-rw-r--r--test/functional/legacy/011_autocommands_spec.lua52
-rw-r--r--test/functional/legacy/012_directory_spec.lua33
-rw-r--r--test/functional/legacy/023_edit_arguments_spec.lua2
-rw-r--r--test/functional/legacy/025_jump_tag_hidden_spec.lua2
-rw-r--r--test/functional/legacy/029_join_spec.lua4
-rw-r--r--test/functional/legacy/031_close_commands_spec.lua7
-rw-r--r--test/functional/legacy/034_user_function_spec.lua73
-rw-r--r--test/functional/legacy/036_regexp_character_classes_spec.lua83
-rw-r--r--test/functional/legacy/038_virtual_replace_spec.lua4
-rw-r--r--test/functional/legacy/039_visual_block_mode_commands_spec.lua21
-rw-r--r--test/functional/legacy/055_list_and_dict_types_spec.lua6
-rw-r--r--test/functional/legacy/057_sort_spec.lua4
-rw-r--r--test/functional/legacy/060_exists_and_has_functions_spec.lua9
-rw-r--r--test/functional/legacy/063_match_and_matchadd_spec.lua21
-rw-r--r--test/functional/legacy/069_multibyte_formatting_spec.lua9
-rw-r--r--test/functional/legacy/074_global_var_in_viminfo_spec.lua120
-rw-r--r--test/functional/legacy/078_swapfile_recover_spec.lua4
-rw-r--r--test/functional/legacy/083_tag_search_with_file_encoding_spec.lua22
-rw-r--r--test/functional/legacy/090_sha256_spec.lua2
-rw-r--r--test/functional/legacy/091_context_variables_spec.lua2
-rw-r--r--test/functional/legacy/096_location_list_spec.lua37
-rw-r--r--test/functional/legacy/097_glob_path_spec.lua14
-rw-r--r--test/functional/legacy/102_fnameescape_spec.lua4
-rw-r--r--test/functional/legacy/106_errorformat_spec.lua2
-rw-r--r--test/functional/legacy/107_adjust_window_and_contents_spec.lua10
-rw-r--r--test/functional/legacy/108_backtrace_debug_commands_spec.lua2
-rw-r--r--test/functional/legacy/arglist_spec.lua5
-rw-r--r--test/functional/legacy/assert_spec.lua37
-rw-r--r--test/functional/legacy/autochdir_spec.lua60
-rw-r--r--test/functional/legacy/autocmd_option_spec.lua316
-rw-r--r--test/functional/legacy/autocmd_spec.lua40
-rw-r--r--test/functional/legacy/breakindent_spec.lua78
-rw-r--r--test/functional/legacy/buffer_spec.lua8
-rw-r--r--test/functional/legacy/changelist_spec.lua2
-rw-r--r--test/functional/legacy/close_count_spec.lua40
-rw-r--r--test/functional/legacy/cmdline_spec.lua177
-rw-r--r--test/functional/legacy/conceal_spec.lua46
-rw-r--r--test/functional/legacy/cpoptions_spec.lua10
-rw-r--r--test/functional/legacy/crash_spec.lua19
-rw-r--r--test/functional/legacy/debugger_spec.lua46
-rw-r--r--test/functional/legacy/delete_spec.lua4
-rw-r--r--test/functional/legacy/digraph_spec.lua21
-rw-r--r--test/functional/legacy/display_spec.lua111
-rw-r--r--test/functional/legacy/edit_spec.lua52
-rw-r--r--test/functional/legacy/erasebackword_spec.lua1
-rw-r--r--test/functional/legacy/eval_spec.lua386
-rw-r--r--test/functional/legacy/ex_mode_spec.lua26
-rw-r--r--test/functional/legacy/excmd_spec.lua136
-rw-r--r--test/functional/legacy/filechanged_spec.lua10
-rw-r--r--test/functional/legacy/fixeol_spec.lua10
-rw-r--r--test/functional/legacy/fnamemodify_spec.lua4
-rw-r--r--test/functional/legacy/fold_spec.lua69
-rw-r--r--test/functional/legacy/function_sort_spec.lua26
-rw-r--r--test/functional/legacy/gf_spec.lua6
-rw-r--r--test/functional/legacy/global_spec.lua13
-rw-r--r--test/functional/legacy/highlight_spec.lua18
-rw-r--r--test/functional/legacy/increment_spec.lua9
-rw-r--r--test/functional/legacy/lispwords_spec.lua2
-rw-r--r--test/functional/legacy/listchars_spec.lua48
-rw-r--r--test/functional/legacy/listlbr_spec.lua46
-rw-r--r--test/functional/legacy/listlbr_utf8_spec.lua29
-rw-r--r--test/functional/legacy/mapping_spec.lua20
-rw-r--r--test/functional/legacy/match_spec.lua35
-rw-r--r--test/functional/legacy/matchparen_spec.lua32
-rw-r--r--test/functional/legacy/memory_usage_spec.lua68
-rw-r--r--test/functional/legacy/messages_spec.lua187
-rw-r--r--test/functional/legacy/mksession_spec.lua6
-rw-r--r--test/functional/legacy/move_spec.lua18
-rw-r--r--test/functional/legacy/normal_spec.lua32
-rw-r--r--test/functional/legacy/number_spec.lua306
-rw-r--r--test/functional/legacy/options_spec.lua16
-rw-r--r--test/functional/legacy/prompt_buffer_spec.lua165
-rw-r--r--test/functional/legacy/put_spec.lua9
-rw-r--r--test/functional/legacy/scroll_opt_spec.lua256
-rw-r--r--test/functional/legacy/search_spec.lua133
-rw-r--r--test/functional/legacy/search_stat_spec.lua78
-rw-r--r--test/functional/legacy/source_spec.lua16
-rw-r--r--test/functional/legacy/statusline_spec.lua43
-rw-r--r--test/functional/legacy/substitute_spec.lua138
-rw-r--r--test/functional/legacy/syn_attr_spec.lua4
-rw-r--r--test/functional/legacy/tabline_spec.lua28
-rw-r--r--test/functional/legacy/tagcase_spec.lua7
-rw-r--r--test/functional/legacy/undolevels_spec.lua4
-rw-r--r--test/functional/legacy/vimscript_spec.lua28
-rw-r--r--test/functional/legacy/visual_spec.lua16
-rw-r--r--test/functional/legacy/window_cmd_spec.lua10
-rw-r--r--test/functional/legacy/wordcount_spec.lua77
-rw-r--r--test/functional/lua/api_spec.lua398
-rw-r--r--test/functional/lua/base64_spec.lua7
-rw-r--r--test/functional/lua/buffer_updates_spec.lua970
-rw-r--r--test/functional/lua/command_line_completion_spec.lua76
-rw-r--r--test/functional/lua/commands_spec.lua288
-rw-r--r--test/functional/lua/diagnostic_spec.lua1059
-rw-r--r--test/functional/lua/ffi_spec.lua25
-rw-r--r--test/functional/lua/filetype_spec.lua75
-rw-r--r--test/functional/lua/fs_spec.lua188
-rw-r--r--test/functional/lua/glob_spec.lua (renamed from test/functional/plugin/lsp/watchfiles_spec.lua)20
-rw-r--r--test/functional/lua/help_spec.lua53
-rw-r--r--test/functional/lua/highlight_spec.lua34
-rw-r--r--test/functional/lua/inspector_spec.lua10
-rw-r--r--test/functional/lua/iter_spec.lua289
-rw-r--r--test/functional/lua/json_spec.lua75
-rw-r--r--test/functional/lua/loader_spec.lua52
-rw-r--r--test/functional/lua/loop_spec.lua59
-rw-r--r--test/functional/lua/luaeval_spec.lua132
-rw-r--r--test/functional/lua/mpack_spec.lua14
-rw-r--r--test/functional/lua/overrides_spec.lua270
-rw-r--r--test/functional/lua/runtime_spec.lua300
-rw-r--r--test/functional/lua/secure_spec.lua252
-rw-r--r--test/functional/lua/snippet_spec.lua63
-rw-r--r--test/functional/lua/spell_spec.lua41
-rw-r--r--test/functional/lua/system_spec.lua37
-rw-r--r--test/functional/lua/text_spec.lua1
-rw-r--r--test/functional/lua/thread_spec.lua108
-rw-r--r--test/functional/lua/ui_event_spec.lua89
-rw-r--r--test/functional/lua/ui_spec.lua42
-rw-r--r--test/functional/lua/uri_spec.lua118
-rw-r--r--test/functional/lua/version_spec.lua215
-rw-r--r--test/functional/lua/vim_spec.lua2385
-rw-r--r--test/functional/lua/watch_spec.lua227
-rw-r--r--test/functional/lua/xdiff_spec.lua93
-rw-r--r--test/functional/options/autochdir_spec.lua35
-rw-r--r--test/functional/options/chars_spec.lua144
-rw-r--r--test/functional/options/cursorbind_spec.lua33
-rw-r--r--test/functional/options/defaults_spec.lua1218
-rw-r--r--test/functional/options/keymap_spec.lua35
-rw-r--r--test/functional/options/mousescroll_spec.lua10
-rw-r--r--test/functional/options/num_options_spec.lua52
-rw-r--r--test/functional/options/shortmess_spec.lua28
-rw-r--r--test/functional/options/tabstop_spec.lua2
-rw-r--r--test/functional/plugin/cfilter_spec.lua18
-rw-r--r--test/functional/plugin/editorconfig_spec.lua16
-rw-r--r--test/functional/plugin/health_spec.lua255
-rw-r--r--test/functional/plugin/lsp/codelens_spec.lua43
-rw-r--r--test/functional/plugin/lsp/completion_spec.lua118
-rw-r--r--test/functional/plugin/lsp/diagnostic_spec.lua61
-rw-r--r--test/functional/plugin/lsp/handler_spec.lua19
-rw-r--r--test/functional/plugin/lsp/helpers.lua45
-rw-r--r--test/functional/plugin/lsp/incremental_sync_spec.lua430
-rw-r--r--test/functional/plugin/lsp/inlay_hint_spec.lua16
-rw-r--r--test/functional/plugin/lsp/semantic_tokens_spec.lua426
-rw-r--r--test/functional/plugin/lsp/utils_spec.lua117
-rw-r--r--test/functional/plugin/lsp_spec.lua2834
-rw-r--r--test/functional/plugin/man_spec.lua136
-rw-r--r--test/functional/plugin/matchparen_spec.lua17
-rw-r--r--test/functional/plugin/msgpack_spec.lua519
-rw-r--r--test/functional/plugin/shada_spec.lua3651
-rw-r--r--test/functional/plugin/tohtml_spec.lua372
-rw-r--r--test/functional/plugin/tutor_spec.lua6
-rw-r--r--test/functional/plugin/vim_syntax_spec.lua40
-rw-r--r--test/functional/preload.lua26
-rw-r--r--test/functional/provider/clipboard_spec.lua222
-rw-r--r--test/functional/provider/define_spec.lua92
-rw-r--r--test/functional/provider/nodejs_spec.lua33
-rw-r--r--test/functional/provider/perl_spec.lua41
-rw-r--r--test/functional/provider/provider_spec.lua13
-rw-r--r--test/functional/provider/python3_spec.lua54
-rw-r--r--test/functional/provider/ruby_spec.lua18
-rw-r--r--test/functional/script/luacats_grammar_spec.lua154
-rw-r--r--test/functional/script/luacats_parser_spec.lua106
-rw-r--r--test/functional/script/text_utils_spec.lua60
-rw-r--r--test/functional/shada/buffers_spec.lua51
-rw-r--r--test/functional/shada/compatibility_spec.lua154
-rw-r--r--test/functional/shada/errors_spec.lua593
-rw-r--r--test/functional/shada/helpers.lua31
-rw-r--r--test/functional/shada/history_spec.lua168
-rw-r--r--test/functional/shada/marks_spec.lua89
-rw-r--r--test/functional/shada/merging_spec.lua743
-rw-r--r--test/functional/shada/registers_spec.lua177
-rw-r--r--test/functional/shada/shada_spec.lua201
-rw-r--r--test/functional/shada/variables_spec.lua106
-rw-r--r--test/functional/terminal/altscreen_spec.lua54
-rw-r--r--test/functional/terminal/api_spec.lua57
-rw-r--r--test/functional/terminal/buffer_spec.lua371
-rw-r--r--test/functional/terminal/channel_spec.lua199
-rw-r--r--test/functional/terminal/cursor_spec.lua582
-rw-r--r--test/functional/terminal/edit_spec.lua48
-rw-r--r--test/functional/terminal/ex_terminal_spec.lua223
-rw-r--r--test/functional/terminal/helpers.lua150
-rw-r--r--test/functional/terminal/highlight_spec.lua209
-rw-r--r--test/functional/terminal/mouse_spec.lua136
-rw-r--r--test/functional/terminal/scrollback_spec.lua211
-rw-r--r--test/functional/terminal/tui_spec.lua2132
-rw-r--r--test/functional/terminal/window_spec.lua68
-rw-r--r--test/functional/terminal/window_split_tab_spec.lua38
-rw-r--r--test/functional/treesitter/fold_spec.lua553
-rw-r--r--test/functional/treesitter/highlight_spec.lua475
-rw-r--r--test/functional/treesitter/inspect_tree_spec.lua115
-rw-r--r--test/functional/treesitter/language_spec.lua88
-rw-r--r--test/functional/treesitter/node_spec.lua19
-rw-r--r--test/functional/treesitter/parser_spec.lua961
-rw-r--r--test/functional/treesitter/utils_spec.lua1
-rw-r--r--test/functional/ui/bufhl_spec.lua721
-rw-r--r--test/functional/ui/cmdline_highlight_spec.lua484
-rw-r--r--test/functional/ui/cmdline_spec.lua1671
-rw-r--r--test/functional/ui/cursor_spec.lua149
-rw-r--r--test/functional/ui/decorations_spec.lua2033
-rw-r--r--test/functional/ui/diff_spec.lua716
-rw-r--r--test/functional/ui/embed_spec.lua314
-rw-r--r--test/functional/ui/float_spec.lua5239
-rw-r--r--test/functional/ui/fold_spec.lua2391
-rw-r--r--test/functional/ui/highlight_spec.lua1705
-rw-r--r--test/functional/ui/hlstate_spec.lua564
-rw-r--r--test/functional/ui/inccommand_spec.lua1833
-rw-r--r--test/functional/ui/inccommand_user_spec.lua142
-rw-r--r--test/functional/ui/input_spec.lua248
-rw-r--r--test/functional/ui/linematch_spec.lua288
-rw-r--r--test/functional/ui/messages_spec.lua2251
-rw-r--r--test/functional/ui/mode_spec.lua257
-rw-r--r--test/functional/ui/mouse_spec.lua846
-rw-r--r--test/functional/ui/multibyte_spec.lua233
-rw-r--r--test/functional/ui/multigrid_spec.lua2645
-rw-r--r--test/functional/ui/options_spec.lua141
-rw-r--r--test/functional/ui/output_spec.lua128
-rw-r--r--test/functional/ui/popupmenu_spec.lua3174
-rw-r--r--test/functional/ui/quickfix_spec.lua37
-rw-r--r--test/functional/ui/screen.lua939
-rw-r--r--test/functional/ui/screen_basic_spec.lua624
-rw-r--r--test/functional/ui/searchhl_spec.lua352
-rw-r--r--test/functional/ui/sign_spec.lua652
-rw-r--r--test/functional/ui/spell_spec.lua146
-rw-r--r--test/functional/ui/statuscolumn_spec.lua289
-rw-r--r--test/functional/ui/statusline_spec.lua582
-rw-r--r--test/functional/ui/syntax_conceal_spec.lua673
-rw-r--r--test/functional/ui/tabline_spec.lua186
-rw-r--r--test/functional/ui/title_spec.lua57
-rw-r--r--test/functional/ui/wildmode_spec.lua379
-rw-r--r--test/functional/ui/winbar_spec.lua406
-rw-r--r--test/functional/vimscript/api_functions_spec.lua182
-rw-r--r--test/functional/vimscript/buf_functions_spec.lua361
-rw-r--r--test/functional/vimscript/changedtick_spec.lua163
-rw-r--r--test/functional/vimscript/container_functions_spec.lua20
-rw-r--r--test/functional/vimscript/ctx_functions_spec.lua246
-rw-r--r--test/functional/vimscript/environ_spec.lua33
-rw-r--r--test/functional/vimscript/errorlist_spec.lua33
-rw-r--r--test/functional/vimscript/eval_spec.lua134
-rw-r--r--test/functional/vimscript/executable_spec.lua134
-rw-r--r--test/functional/vimscript/execute_spec.lua95
-rw-r--r--test/functional/vimscript/exepath_spec.lua47
-rw-r--r--test/functional/vimscript/fnamemodify_spec.lua10
-rw-r--r--test/functional/vimscript/getline_spec.lua6
-rw-r--r--test/functional/vimscript/glob_spec.lua7
-rw-r--r--test/functional/vimscript/has_spec.lua120
-rw-r--r--test/functional/vimscript/hostname_spec.lua6
-rw-r--r--test/functional/vimscript/input_spec.lua336
-rw-r--r--test/functional/vimscript/json_functions_spec.lua948
-rw-r--r--test/functional/vimscript/lang_spec.lua6
-rw-r--r--test/functional/vimscript/let_spec.lua42
-rw-r--r--test/functional/vimscript/map_functions_spec.lua160
-rw-r--r--test/functional/vimscript/match_functions_spec.lua275
-rw-r--r--test/functional/vimscript/minmax_functions_spec.lua41
-rw-r--r--test/functional/vimscript/modeline_spec.lua2
-rw-r--r--test/functional/vimscript/msgpack_functions_spec.lua295
-rw-r--r--test/functional/vimscript/null_spec.lua167
-rw-r--r--test/functional/vimscript/operators_spec.lua22
-rw-r--r--test/functional/vimscript/printf_spec.lua48
-rw-r--r--test/functional/vimscript/reltime_spec.lua10
-rw-r--r--test/functional/vimscript/screenchar_spec.lua50
-rw-r--r--test/functional/vimscript/screenpos_spec.lua84
-rw-r--r--test/functional/vimscript/server_spec.lua120
-rw-r--r--test/functional/vimscript/setpos_spec.lua43
-rw-r--r--test/functional/vimscript/sort_spec.lua54
-rw-r--r--test/functional/vimscript/special_vars_spec.lua64
-rw-r--r--test/functional/vimscript/state_spec.lua24
-rw-r--r--test/functional/vimscript/string_spec.lua231
-rw-r--r--test/functional/vimscript/system_spec.lua312
-rw-r--r--test/functional/vimscript/timer_spec.lua110
-rw-r--r--test/functional/vimscript/uniq_spec.lua12
-rw-r--r--test/functional/vimscript/vvar_event_spec.lua1
-rw-r--r--test/functional/vimscript/wait_spec.lua21
-rw-r--r--test/functional/vimscript/writefile_spec.lua157
-rw-r--r--test/helpers.lua569
-rw-r--r--test/lua_runner.lua28
-rw-r--r--test/old/testdir/Makefile17
-rw-r--r--test/old/testdir/crash/poc_did_set_langmap1
-rw-r--r--test/old/testdir/crash/poc_ex_substitutebin0 -> 135 bytes
-rw-r--r--test/old/testdir/crash/poc_suggest_trie_walkbin0 -> 100 bytes
-rw-r--r--test/old/testdir/crash/poc_win_enter_extbin0 -> 1958 bytes
-rw-r--r--test/old/testdir/runnvim.vim5
-rw-r--r--test/old/testdir/runtest.vim2
-rw-r--r--test/old/testdir/setup.vim3
-rw-r--r--test/old/testdir/test_autocmd.vim60
-rw-r--r--test/old/testdir/test_breakindent.vim107
-rw-r--r--test/old/testdir/test_cmdline.vim71
-rw-r--r--test/old/testdir/test_cmdwin.vim112
-rw-r--r--test/old/testdir/test_crash.vim37
-rw-r--r--test/old/testdir/test_cursor_func.vim5
-rw-r--r--test/old/testdir/test_diffmode.vim50
-rw-r--r--test/old/testdir/test_display.vim20
-rw-r--r--test/old/testdir/test_edit.vim34
-rw-r--r--test/old/testdir/test_excmd.vim22
-rw-r--r--test/old/testdir/test_filetype.vim117
-rw-r--r--test/old/testdir/test_filter_map.vim151
-rw-r--r--test/old/testdir/test_fold.vim13
-rw-r--r--test/old/testdir/test_functions.vim190
-rw-r--r--test/old/testdir/test_getvar.vim1
-rw-r--r--test/old/testdir/test_goto.vim13
-rw-r--r--test/old/testdir/test_highlight.vim21
-rw-r--r--test/old/testdir/test_ins_complete.vim29
-rw-r--r--test/old/testdir/test_lispindent.vim1
-rw-r--r--test/old/testdir/test_listchars.vim76
-rw-r--r--test/old/testdir/test_listdict.vim21
-rw-r--r--test/old/testdir/test_listlbr.vim8
-rw-r--r--test/old/testdir/test_listlbr_utf8.vim21
-rw-r--r--test/old/testdir/test_map_functions.vim2
-rw-r--r--test/old/testdir/test_mapping.vim20
-rw-r--r--test/old/testdir/test_messages.vim12
-rw-r--r--test/old/testdir/test_normal.vim48
-rw-r--r--test/old/testdir/test_number.vim71
-rw-r--r--test/old/testdir/test_options.vim90
-rw-r--r--test/old/testdir/test_popup.vim18
-rw-r--r--test/old/testdir/test_prompt_buffer.vim45
-rw-r--r--test/old/testdir/test_put.vim38
-rw-r--r--test/old/testdir/test_python3.vim2
-rw-r--r--test/old/testdir/test_pyx3.vim2
-rw-r--r--test/old/testdir/test_regexp_utf8.vim11
-rw-r--r--test/old/testdir/test_registers.vim104
-rw-r--r--test/old/testdir/test_scroll_opt.vim19
-rw-r--r--test/old/testdir/test_syntax.vim8
-rw-r--r--test/old/testdir/test_tabpage.vim115
-rw-r--r--test/old/testdir/test_tagjump.vim41
-rw-r--r--test/old/testdir/test_termdebug.vim89
-rw-r--r--test/old/testdir/test_textobjects.vim132
-rw-r--r--test/old/testdir/test_undo.vim2
-rw-r--r--test/old/testdir/test_utf8_comparisons.vim37
-rw-r--r--test/old/testdir/test_virtualedit.vim17
-rw-r--r--test/old/testdir/test_visual.vim358
-rw-r--r--test/old/testdir/test_window_cmd.vim58
-rw-r--r--test/old/testdir/vim9.vim47
-rw-r--r--test/unit/api/helpers.lua99
-rw-r--r--test/unit/api/private_helpers_spec.lua80
-rw-r--r--test/unit/buffer_spec.lua46
-rw-r--r--test/unit/charset/vim_str2nr_spec.lua584
-rw-r--r--test/unit/eval/decode_spec.lua41
-rw-r--r--test/unit/eval/encode_spec.lua39
-rw-r--r--test/unit/eval/helpers.lua285
-rw-r--r--test/unit/eval/tricks_spec.lua3
-rw-r--r--test/unit/eval/tv_clear_spec.lua14
-rw-r--r--test/unit/eval/typval_spec.lua1549
-rw-r--r--test/unit/fileio_spec.lua25
-rw-r--r--test/unit/fixtures/multiqueue.c2
-rw-r--r--test/unit/formatc.lua201
-rw-r--r--test/unit/garray_spec.lua57
-rw-r--r--test/unit/helpers.lua180
-rw-r--r--test/unit/indent_spec.lua38
-rw-r--r--test/unit/keycodes_spec.lua28
-rw-r--r--test/unit/marktree_spec.lua358
-rw-r--r--test/unit/mbyte_spec.lua205
-rw-r--r--test/unit/memory_spec.lua30
-rw-r--r--test/unit/message_spec.lua9
-rw-r--r--test/unit/msgpack_spec.lua40
-rw-r--r--test/unit/multiqueue_spec.lua6
-rw-r--r--test/unit/optionstr_spec.lua17
-rw-r--r--test/unit/os/env_spec.lua19
-rw-r--r--test/unit/os/fileio_spec.lua155
-rw-r--r--test/unit/os/fs_spec.lua285
-rw-r--r--test/unit/os/shell_spec.lua50
-rw-r--r--test/unit/path_spec.lua125
-rw-r--r--test/unit/preprocess.lua101
-rw-r--r--test/unit/profile_spec.lua92
-rw-r--r--test/unit/rbuffer_spec.lua54
-rw-r--r--test/unit/search_spec.lua40
-rw-r--r--test/unit/set.lua6
-rw-r--r--test/unit/statusline_spec.lua555
-rw-r--r--test/unit/strings_spec.lua89
-rw-r--r--test/unit/undo_spec.lua77
-rw-r--r--test/unit/viml/expressions/lexer_spec.lua603
-rw-r--r--test/unit/viml/expressions/parser_spec.lua384
-rw-r--r--test/unit/viml/expressions/parser_tests.lua239
-rw-r--r--test/unit/viml/helpers.lua59
1389 files changed, 123295 insertions, 90589 deletions
diff --git a/.cirrus.yml b/.cirrus.yml
index ab4bead7fb..bb98430763 100644
--- a/.cirrus.yml
+++ b/.cirrus.yml
@@ -6,7 +6,7 @@ freebsd_task:
name: FreeBSD
only_if: $BRANCH != "master"
freebsd_instance:
- image_family: freebsd-13-2
+ image_family: freebsd-14-0
timeout_in: 30m
install_script:
- pkg install -y cmake gmake ninja unzip wget gettext python git
diff --git a/.clang-tidy b/.clang-tidy
index 927909cf8d..6776d86d21 100644
--- a/.clang-tidy
+++ b/.clang-tidy
@@ -46,7 +46,6 @@ Checks: >
-cppcoreguidelines-init-variables,
-llvm-header-guard, We use #pragma once,
-llvmlibc-restrict-system-libc-headers, We want to use glibc,
- -misc-header-include-cycle, Looks useful but redundant with IWYU. We may replace IWYU with this one day,
-misc-include-cleaner, Looks useful but redundant with IWYU. We may replace IWYU with this one day,
-misc-misplaced-const,
-misc-no-recursion,
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 4dba469ebe..07fbd669e5 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -58,6 +58,11 @@ aa4f9c5341f5280f16cce0630ea54b84eef717b3
6ff245732a5a8ab821598a38fb0c5805e6bd3779
abf758a2977c4e6cab4dfa217f56da853d85851c
cb84f5ee530f0f32b92bed5b4ad41344e8b551aa
+f98b8d2d44d289263b1a3b33b6a7f20644ef671c
+544ef994df72c3cbe0dca6b856ce2dcbc5169767
+45fe4d11add933df76a2ea4bf52ce8904f4a778b
+517f0cc634b985057da5b95cf4ad659ee456a77e
+04f2f864e270e772c6326cefdf24947f0130e492
# typos
d238b8f6003d34cae7f65ff7585b48a2cd9449fb
diff --git a/.gitattributes b/.gitattributes
index 75f92454e3..381fc27e80 100755
--- a/.gitattributes
+++ b/.gitattributes
@@ -6,6 +6,7 @@ runtime/doc/* linguist-documentation
runtime/doc/builtin.txt linguist-generated
runtime/lua/vim/_meta/vimfn.lua linguist-generated
+runtime/lua/vim/_meta/vvars.lua linguist-generated
runtime/lua/vim/_meta/api.lua linguist-generated
runtime/lua/vim/_meta/api_keysets.lua linguist-generated
runtime/lua/vim/_meta/options.lua linguist-generated
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
index c07ae66c6f..578a776b32 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -8,11 +8,11 @@ body:
value: |
*Before reporting:*
- Confirm the problem is reproducible on [**master**](https://github.com/neovim/neovim/releases/nightly) or [**latest stable**](https://github.com/neovim/neovim/releases/stable) release
- - run `make distclean` when encountering build issues
- - search [existing issues](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aopen+label%3Abug)
- - check the [FAQ](https://github.com/neovim/neovim/wiki/FAQ)
+ - Run `make distclean` when encountering build issues
+ - Search [existing issues](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aopen+label%3Abug,bug-crash) (including [closed](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aclosed+label%3Abug%2Cbug-crash))
+ - Read the [FAQ](https://neovim.io/doc/user/faq.html) and ["Reporting Problems" in CONTRIBUTING.md](https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#reporting-problems).
- Usage or "How to" questions belong on the [stackoverflow](https://vi.stackexchange.com/) and will be closed.
+ Usage or "How to" questions belong on [stackoverflow](https://vi.stackexchange.com/) and will be closed.
- type: textarea
attributes:
label: "Problem"
@@ -24,8 +24,9 @@ body:
label: "Steps to reproduce"
description: |
- For build failures: list the exact steps including CMake flags (if any).
+ - If the bug pertains to crashing (or segfault), please include a [stacktrace](https://neovim.io/doc/user/dev_tools.html#dev-tools-backtrace).
- For startup or shell-related problems: try `env -i TERM=ansi-256color "$(which nvim)"`.
- - See [Minimal-reproduction-template](https://github.com/neovim/neovim/wiki/Minimal-reproduction-template) for how to create a minimal configuration.
+ - Use the provided [minimal reproduction template](https://github.com/neovim/neovim/blob/master/contrib/minimal.lua) to create a minimal configuration. After you fill it out with necessary information, run with `nvim --clean -u minimal.lua`.
- Please do **not** include a package manager in the reproduction steps.
placeholder: |
nvim --clean
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml
index 4b9a443064..711d70c589 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yml
@@ -6,7 +6,7 @@ body:
- type: markdown
attributes:
value: |
- Before requesting: search [existing issues](https://github.com/neovim/neovim/labels/enhancement) and check the [FAQ](https://github.com/neovim/neovim/wiki/FAQ).
+ Before requesting: search [existing feature requests](https://github.com/neovim/neovim/labels/enhancement) and check the [FAQ](https://neovim.io/doc/user/faq.html).
- type: textarea
attributes:
diff --git a/.github/ISSUE_TEMPLATE/lsp_bug_report.yml b/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
index bdad12e412..0e2111923d 100644
--- a/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
+++ b/.github/ISSUE_TEMPLATE/lsp_bug_report.yml
@@ -6,7 +6,7 @@ body:
- type: markdown
attributes:
value: |
- _Before reporting:_ search [existing issues](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aopen+label%3Abug) and check the [FAQ](https://github.com/neovim/neovim/wiki/FAQ). Usage questions or "Why isn't X language server/feature working?" belong on [stackoverflow](https://vi.stackexchange.com/) and will be closed.
+ _Before reporting:_ search [existing issues](https://github.com/neovim/neovim/issues?q=is%3Aissue+is%3Aopen+label%3Abug) and check the [FAQ](https://neovim.io/doc/user/faq.html). Usage questions or "Why isn't X language server/feature working?" belong on [stackoverflow](https://vi.stackexchange.com/) and will be closed.
- type: textarea
attributes:
diff --git a/.github/actions/cache/action.yml b/.github/actions/cache/action.yml
index d668c7a7cc..8a5c53a139 100644
--- a/.github/actions/cache/action.yml
+++ b/.github/actions/cache/action.yml
@@ -25,7 +25,7 @@ runs:
# if it makes the expression below simpler. hashFiles() has a timer that
# will fail the job if it times out, which can happen if there are too many
# files to search through.
- - uses: actions/cache@v3
+ - uses: actions/cache@v4
with:
path: .deps
key: ${{ env.CACHE_KEY }}-${{ steps.image.outputs.version }}-${{ hashFiles('cmake**',
diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml
new file mode 100644
index 0000000000..dfa3101abc
--- /dev/null
+++ b/.github/actions/setup/action.yml
@@ -0,0 +1,29 @@
+name: 'setup'
+description: "Creates necessary setup for CI"
+inputs:
+ install_flags:
+ description: 'Install script flags'
+ required: false
+ default: ''
+runs:
+ using: "composite"
+ steps:
+ - name: Set $BIN_DIR
+ shell: bash
+ run: echo "$BIN_DIR" >> $GITHUB_PATH
+
+ - if: ${{ runner.os != 'Windows' }}
+ name: Set ulimit
+ shell: bash
+ run: ulimit -c unlimited
+
+ - if: ${{ runner.os == 'Windows' }}
+ run: .github/scripts/env.ps1
+ shell: pwsh
+
+ - name: Install dependencies
+ run: ./.github/scripts/install_deps.sh ${{ inputs.install_flags }}
+ shell: bash
+
+ - name: Cache
+ uses: ./.github/actions/cache
diff --git a/.github/labeler.yml b/.github/labeler.yml
deleted file mode 100644
index 111fc5f373..0000000000
--- a/.github/labeler.yml
+++ /dev/null
@@ -1,66 +0,0 @@
-"lsp":
- - runtime/lua/vim/lsp.lua
- - runtime/lua/vim/lsp/*
-
-"tui":
- - src/nvim/tui/tui.*
-
-"treesitter":
- - src/nvim/lua/treesitter.*
- - runtime/lua/vim/treesitter.lua
- - runtime/lua/vim/treesitter/*
- - runtime/queries/**/*
-
-"diagnostic":
- - runtime/lua/vim/diagnostic.lua
-
-"dependencies":
- - cmake.deps/**/*
-
-"spell":
- - src/nvim/spell*
-
-"terminal":
- - src/nvim/terminal.*
-
-"column":
- - src/nvim/sign*
-
-"folds":
- - src/nvim/fold*
-
-"mouse":
- - src/nvim/mouse*
-
-"documentation":
- - all: ["runtime/doc/*"]
- - all: ["**/*.md"]
-
-"clipboard":
- - runtime/autoload/provider/clipboard.vim
-
-"diff":
- - src/nvim/diff.*
-
-"build":
- - CMakeLists.txt
- - "**/CMakeLists.txt"
- - "**/Makefile"
- - "**/*.cmake"
-
-"test":
- - all: ["test/**/*"]
-
-"ci":
- - .github/labeler.yml
- - .github/workflows/**/*
- - .builds/*
- - ci/**/*
-
-"filetype":
- - runtime/lua/vim/filetype.lua
- - runtime/lua/vim/filetype/detect.lua
-
-"platform:nix":
- - contrib/flake.lock
- - contrib/flake.nix
diff --git a/.github/scripts/build_universal_macos.sh b/.github/scripts/build_universal_macos.sh
index d07c395cd6..aeda93ee03 100755
--- a/.github/scripts/build_universal_macos.sh
+++ b/.github/scripts/build_universal_macos.sh
@@ -1,17 +1,18 @@
#!/bin/bash -e
-MACOSX_DEPLOYMENT_TARGET="$(sw_vers -productVersion | cut -f1 -d.)"
+MACOSX_DEPLOYMENT_TARGET=11.0
export MACOSX_DEPLOYMENT_TARGET
cmake -S cmake.deps -B .deps -G Ninja \
- -D CMAKE_BUILD_TYPE=${NVIM_BUILD_TYPE} \
+ -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \
-D CMAKE_OSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET} \
-D CMAKE_OSX_ARCHITECTURES=arm64\;x86_64 \
-D CMAKE_FIND_FRAMEWORK=NEVER
cmake --build .deps
cmake -B build -G Ninja \
- -D CMAKE_BUILD_TYPE=${NVIM_BUILD_TYPE} \
+ -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE} \
-D CMAKE_OSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET} \
-D CMAKE_OSX_ARCHITECTURES=arm64\;x86_64 \
+ -D ENABLE_LIBINTL=OFF \
-D CMAKE_FIND_FRAMEWORK=NEVER
cmake --build build
# Make sure we build everything for M1 as well
diff --git a/.github/scripts/close_unresponsive.js b/.github/scripts/close_unresponsive.js
index f0e8bbe93e..b16c19b653 100644
--- a/.github/scripts/close_unresponsive.js
+++ b/.github/scripts/close_unresponsive.js
@@ -41,6 +41,7 @@ module.exports = async ({ github, context }) => {
owner: owner,
repo: repo,
issue_number: number,
+ state_reason: "not_planned",
state: "closed",
});
diff --git a/.github/scripts/install_deps.sh b/.github/scripts/install_deps.sh
index 9a782e9698..ad81e053f9 100755
--- a/.github/scripts/install_deps.sh
+++ b/.github/scripts/install_deps.sh
@@ -30,12 +30,12 @@ if [[ $os == Linux ]]; then
fi
if [[ -n $TEST ]]; then
- sudo apt-get install -y locales-all cpanminus attr libattr1-dev gdb
+ sudo apt-get install -y locales-all cpanminus attr libattr1-dev gdb fswatch
fi
elif [[ $os == Darwin ]]; then
brew update --quiet
brew install ninja
if [[ -n $TEST ]]; then
- brew install cpanminus
+ brew install cpanminus fswatch
fi
fi
diff --git a/.github/scripts/labeler_configuration.yml b/.github/scripts/labeler_configuration.yml
new file mode 100644
index 0000000000..3db8444fde
--- /dev/null
+++ b/.github/scripts/labeler_configuration.yml
@@ -0,0 +1,71 @@
+lsp:
+ - changed-files:
+ - any-glob-to-any-file: [ runtime/lua/vim/lsp.lua, runtime/lua/vim/lsp/* ]
+
+tui:
+ - changed-files:
+ - any-glob-to-any-file: [ src/nvim/tui/tui.* ]
+
+treesitter:
+ - changed-files:
+ - any-glob-to-any-file: [ src/nvim/lua/treesitter.*, runtime/lua/vim/treesitter.lua, runtime/lua/vim/treesitter/*, runtime/queries/**/* ]
+
+diagnostic:
+ - changed-files:
+ - any-glob-to-any-file: [ runtime/lua/vim/diagnostic.lua ]
+
+dependencies:
+ - changed-files:
+ - any-glob-to-any-file: [ cmake.deps/**/* ]
+
+spell:
+ - changed-files:
+ - any-glob-to-any-file: [ src/nvim/spell* ]
+
+terminal:
+ - changed-files:
+ - any-glob-to-any-file: [ src/nvim/terminal.* ]
+
+column:
+ - changed-files:
+ - any-glob-to-any-file: [ src/nvim/sign* ]
+
+folds:
+ - changed-files:
+ - any-glob-to-any-file: [ src/nvim/fold* ]
+
+mouse:
+ - changed-files:
+ - any-glob-to-any-file: [ src/nvim/mouse* ]
+
+documentation:
+ - changed-files:
+ - any-glob-to-all-files: [ runtime/doc/*, "**/*.md" ]
+
+clipboard:
+ - changed-files:
+ - any-glob-to-any-file: [ runtime/autoload/provider/clipboard.vim ]
+
+diff:
+ - changed-files:
+ - any-glob-to-any-file: [ src/nvim/diff.* ]
+
+build:
+ - changed-files:
+ - any-glob-to-any-file: [ CMakeLists.txt, "**/CMakeLists.txt", "**/Makefile", "**/*.cmake" ]
+
+test:
+ - changed-files:
+ - any-glob-to-all-files: [test/**/*]
+
+ci:
+ - changed-files:
+ - any-glob-to-any-file: [ .github/actions/**, .github/workflows/**, .github/scripts/** ]
+
+filetype:
+ - changed-files:
+ - any-glob-to-any-file: [ runtime/lua/vim/filetype.lua, runtime/lua/vim/filetype/detect.lua ]
+
+platform:nix:
+ - changed-files:
+ - any-glob-to-any-file: [ contrib/flake.lock, contrib/flake.nix ]
diff --git a/.github/scripts/reviews.js b/.github/scripts/reviewers_add.js
index d28d91c2f6..c6a878ec8e 100644
--- a/.github/scripts/reviews.js
+++ b/.github/scripts/reviewers_add.js
@@ -28,6 +28,10 @@ module.exports = async ({ github, context }) => {
reviewers.add("lewis6991");
}
+ if (labels.includes("defaults")) {
+ reviewers.add("gpanders");
+ }
+
if (labels.includes("dependencies")) {
reviewers.add("jamessan");
}
@@ -91,6 +95,10 @@ module.exports = async ({ github, context }) => {
reviewers.add("lewis6991");
}
+ if (labels.includes("tui")) {
+ reviewers.add("gpanders");
+ }
+
if (labels.includes("typo")) {
reviewers.add("dundargoc");
}
diff --git a/.github/scripts/remove-reviewers.js b/.github/scripts/reviewers_remove.js
index 9e44e4ac86..9e44e4ac86 100644
--- a/.github/scripts/remove-reviewers.js
+++ b/.github/scripts/reviewers_remove.js
diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml
index 321cd02b0c..88cddcded4 100644
--- a/.github/workflows/backport.yml
+++ b/.github/workflows/backport.yml
@@ -1,4 +1,4 @@
-name: Backport
+name: backport
on:
pull_request_target:
types: [closed, labeled]
@@ -14,3 +14,9 @@ jobs:
- uses: actions/checkout@v4
- name: Create backport PRs
uses: korthout/backport-action@v2
+ with:
+ # https://github.com/korthout/backport-action/pull/399
+ experimental: >
+ {
+ "detect_merge_method": true
+ }
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index d6e11fcdcb..13fa692be1 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -21,12 +21,12 @@ env:
jobs:
macos-universal:
- runs-on: macos-latest
+ runs-on: macos-14
timeout-minutes: 20
steps:
- uses: actions/checkout@v4
- - run: ./.github/scripts/install_deps.sh
- - run: printf 'NVIM_BUILD_TYPE=Release\n' >> $GITHUB_ENV
+ - uses: ./.github/actions/setup
+ - run: printf 'CMAKE_BUILD_TYPE=Release\n' >> $GITHUB_ENV
- name: Build universal binary
run: ./.github/scripts/build_universal_macos.sh
@@ -36,15 +36,11 @@ jobs:
runs-on: ubuntu-22.04
timeout-minutes: 15
env:
- CMAKE_URL: 'https://cmake.org/files/v3.10/cmake-3.10.0-Linux-x86_64.sh'
- CMAKE_VERSION: '3.10.0'
+ CMAKE_URL: 'https://cmake.org/files/v3.13/cmake-3.13.0-Linux-x86_64.sh'
+ CMAKE_VERSION: '3.13.0'
steps:
- uses: actions/checkout@v4
- - run: ./.github/scripts/install_deps.sh
-
- - name: Set up environment
- run: echo "$BIN_DIR" >> $GITHUB_PATH
-
+ - uses: ./.github/actions/setup
- name: Install minimum required version of cmake
run: |
@@ -73,7 +69,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- - run: ./.github/scripts/install_deps.sh
+ - uses: ./.github/actions/setup
- name: Build bundled dependencies
run: make deps
diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml
index 365c3fdf56..c2db78dd25 100644
--- a/.github/workflows/codeql.yml
+++ b/.github/workflows/codeql.yml
@@ -1,4 +1,4 @@
-name: "CodeQL"
+name: "codeql"
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
@@ -20,20 +20,15 @@ jobs:
security-events: write
steps:
- - name: Checkout repository
- uses: actions/checkout@v4
-
- - name: Install dependencies
- run: ./.github/scripts/install_deps.sh
+ - uses: actions/checkout@v4
+ - uses: ./.github/actions/setup
- name: Initialize CodeQL
- uses: github/codeql-action/init@v2
+ uses: github/codeql-action/init@v3
with:
languages: cpp
- - uses: ./.github/actions/cache
-
- run: make
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v2
+ uses: github/codeql-action/analyze@v3
diff --git a/.github/workflows/coverity.yml b/.github/workflows/coverity.yml
index 3eed1e51df..db0f878de4 100644
--- a/.github/workflows/coverity.yml
+++ b/.github/workflows/coverity.yml
@@ -1,4 +1,4 @@
-name: Coverity
+name: coverity
on:
schedule:
- cron: '10 0 * * *' # Run every day at 00:10
@@ -9,9 +9,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
-
- - name: Install dependencies
- run: ./.github/scripts/install_deps.sh
+ - uses: ./.github/actions/setup
- name: Download Coverity
run: |
diff --git a/.github/workflows/api-docs.yml b/.github/workflows/docs.yml
index 6f8fe107d2..c91f2945fb 100644
--- a/.github/workflows/api-docs.yml
+++ b/.github/workflows/docs.yml
@@ -1,5 +1,4 @@
-# Check if any PR needs to run the autogenerate script
-name: Autogenerate API docs and types
+name: docs
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
@@ -8,9 +7,10 @@ on:
- 'src/nvim/eval.lua'
- 'runtime/lua/**.lua'
- 'runtime/doc/**'
-
+ - 'scripts/gen_vimdoc.py'
+ - 'scripts/gen_help_html.lua'
jobs:
- regen-api-docs-and-types:
+ docs:
runs-on: ubuntu-latest
if: github.event.pull_request.draft == false
permissions:
@@ -18,11 +18,7 @@ jobs:
pull-requests: write
steps:
- uses: actions/checkout@v4
- - name: Install dependencies
- run: |
- ./.github/scripts/install_deps.sh
- sudo apt-get install -y doxygen python3-msgpack
- - uses: ./.github/actions/cache
+ - uses: ./.github/actions/setup
- name: Generate docs
run: |
@@ -32,3 +28,6 @@ jobs:
echo "::error::The doc generation produces the following changes:"
git diff --color --exit-code
fi
+
+ - name: Validate docs
+ run: make lintdoc
diff --git a/.github/workflows/issue-open-check.yml b/.github/workflows/labeler_issue.yml
index eac1c2ee4d..deba3cd5a5 100644
--- a/.github/workflows/issue-open-check.yml
+++ b/.github/workflows/labeler_issue.yml
@@ -1,22 +1,19 @@
-name: Issue Open Check
-
+name: "labeler: issue"
on:
issues:
types: [opened]
-
jobs:
- issue-open-check:
+ labeler:
permissions:
issues: write
runs-on: ubuntu-latest
steps:
- name: check issue title
- id: check-issue
uses: actions/github-script@v7
with:
script: |
const title = context.payload.issue.title;
- const titleSplit = title.split(/\s+/).map(e => e.toLowerCase());
+ const titleSplit = title.split(/\b/).map(e => e.toLowerCase());
const keywords = ['api', 'treesitter', 'ui', 'lsp'];
var match = new Set();
for (const keyword of keywords) {
diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler_pr.yml
index 52682d93dd..8fd93bfb6d 100644
--- a/.github/workflows/labeler.yml
+++ b/.github/workflows/labeler_pr.yml
@@ -1,20 +1,21 @@
-name: "Pull Request Labeler"
+name: "labeler: PR"
on:
pull_request_target:
types: [opened]
jobs:
- triage:
+ changed-files:
runs-on: ubuntu-latest
permissions:
contents: read
pull-requests: write
steps:
- - uses: actions/labeler@v4
+ - uses: actions/checkout@v4
+ - uses: actions/labeler@v5
with:
- sync-labels: ""
+ configuration-path: .github/scripts/labeler_configuration.yml
type-scope:
- needs: triage
+ needs: changed-files
runs-on: ubuntu-latest
permissions:
contents: write
@@ -33,7 +34,7 @@ jobs:
run: gh pr edit "$PR_NUMBER" --add-label "$(echo "$PR_TITLE" | sed -E 's|[[:alpha:]]+(\(.*\))?!:.*|breaking-change|')" || true
request-reviewer:
- needs: ["triage", "type-scope"]
+ needs: ["changed-files", "type-scope"]
permissions:
pull-requests: write
- uses: ./.github/workflows/add-reviewers.yml
+ uses: ./.github/workflows/reviewers_add.yml
diff --git a/.github/workflows/lintcommit.yml b/.github/workflows/lintcommit.yml
index 8f56c057ae..3d140532cd 100644
--- a/.github/workflows/lintcommit.yml
+++ b/.github/workflows/lintcommit.yml
@@ -1,4 +1,4 @@
-name: "Commit Linter"
+name: "lintcommit"
on:
pull_request:
types: [opened, synchronize, reopened, ready_for_review]
@@ -14,8 +14,8 @@ jobs:
fetch-depth: 0
ref: ${{ github.event.pull_request.head.sha }}
- - run: ./.github/scripts/install_deps.sh
- - uses: ./.github/actions/cache
+ - uses: ./.github/actions/setup
+
- name: Build
run: |
cmake -S cmake.deps --preset ci
diff --git a/.github/workflows/news.yml b/.github/workflows/news.yml
index d4f8e5ad65..8d21b86e8e 100644
--- a/.github/workflows/news.yml
+++ b/.github/workflows/news.yml
@@ -1,13 +1,13 @@
-name: "news.txt check"
+name: "news.txt"
on:
pull_request:
- types: [opened, synchronize, reopened, ready_for_review]
+ types: [opened, synchronize, reopened, ready_for_review, labeled, unlabeled]
branches:
- 'master'
jobs:
check:
runs-on: ubuntu-latest
- if: github.event.pull_request.draft == false
+ if: github.event.pull_request.draft == false && !contains(github.event.pull_request.labels.*.name, 'ci:skip-news')
steps:
- uses: actions/checkout@v4
with:
diff --git a/.github/workflows/notes.md b/.github/workflows/notes.md
index 8c518b0bdb..294d92ebb5 100644
--- a/.github/workflows/notes.md
+++ b/.github/workflows/notes.md
@@ -48,7 +48,7 @@ https://github.com/neovim/neovim-releases.
### Other
-- Install by [package manager](https://github.com/neovim/neovim/wiki/Installing-Neovim)
+- Install by [package manager](https://github.com/neovim/neovim/blob/master/INSTALL.md#install-from-package)
## SHA256 Checksums
diff --git a/.github/workflows/optional.yml b/.github/workflows/optional.yml
index ebaf23d29b..c9a8205f87 100644
--- a/.github/workflows/optional.yml
+++ b/.github/workflows/optional.yml
@@ -2,6 +2,7 @@ name: optional
on:
pull_request:
types: [labeled, opened, synchronize, reopened]
+ workflow_dispatch:
concurrency:
group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.head_ref || github.sha }}
@@ -9,12 +10,14 @@ concurrency:
env:
INSTALL_PREFIX: ${{ github.workspace }}/nvim-install
+ # Double test timeout since it's running via qemu
+ TEST_TIMEOUT: 2400
# TEST_FILE: test/functional/shada
# TEST_FILTER: foo
jobs:
s390x:
- if: contains(github.event.pull_request.labels.*.name, 'ci-s390x')
+ if: contains(github.event.pull_request.labels.*.name, 'ci:s390x') || github.event_name == 'workflow_dispatch'
strategy:
fail-fast: false
matrix:
@@ -25,17 +28,21 @@ jobs:
- run: docker run --rm --privileged multiarch/qemu-user-static:register --reset
- uses: docker://multiarch/ubuntu-core:s390x-focal
with:
+ # Docker runs the command as root, but we want the build/test to run
+ # as non-root so permissions based tests run correctly
args: >
bash -c
"
apt-get -y update &&
DEBIAN_FRONTEND=noninteractive apt-get -y install build-essential cmake curl gettext ninja-build locales-all cpanminus git attr libattr1-dev &&
- git clone --depth=1 https://github.com/neovim/neovim.git &&
+ useradd --create-home qemuci &&
+ chown -R qemuci. . &&
+ runuser -u qemuci -- git clone --depth=1 https://github.com/neovim/neovim.git &&
cd neovim &&
- git fetch origin ${{ github.ref }}:pr &&
- git switch pr &&
- cmake -S cmake.deps -B .deps -G Ninja -D USE_BUNDLED_LUAJIT=OFF -D USE_BUNDLED_LUA=ON &&
- cmake --build .deps &&
- cmake -B build -G Ninja -D PREFER_LUA=ON &&
- make ${{ matrix.test }}
+ runuser -u qemuci -- git fetch origin ${{ github.ref }}:pr &&
+ runuser -u qemuci -- git switch pr &&
+ runuser -u qemuci -- cmake -S cmake.deps -B .deps -G Ninja -D USE_BUNDLED_LUAJIT=OFF -D USE_BUNDLED_LUA=ON &&
+ runuser -u qemuci -- cmake --build .deps &&
+ runuser -u qemuci -- cmake -B build -G Ninja -D CI_BUILD=ON -D PREFER_LUA=ON &&
+ runuser -u qemuci -- make ${{ matrix.test }}
"
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index b19019d06d..48a3901955 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -1,4 +1,4 @@
-name: Release
+name: release
on:
schedule:
- cron: '5 5 * * *'
@@ -23,27 +23,30 @@ jobs:
version: ${{ steps.build.outputs.version }}
steps:
- uses: actions/checkout@v4
+ with:
+ # Perform a full checkout #13471
+ fetch-depth: 0
- run: ./.github/scripts/install_deps.sh
- if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name != 'nightly')
run: |
- echo 'NVIM_BUILD_TYPE=Release' >> $GITHUB_ENV
+ echo 'CMAKE_BUILD_TYPE=Release' >> $GITHUB_ENV
echo 'APPIMAGE_TAG=latest' >> $GITHUB_ENV
- if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name == 'nightly')
run: |
- echo 'NVIM_BUILD_TYPE=RelWithDebInfo' >> $GITHUB_ENV
+ echo 'CMAKE_BUILD_TYPE=RelWithDebInfo' >> $GITHUB_ENV
echo 'APPIMAGE_TAG=nightly' >> $GITHUB_ENV
- name: appimage
run: ./scripts/genappimage.sh ${APPIMAGE_TAG}
- name: tar.gz
run: cpack --config build/CPackConfig.cmake -G TGZ
- - uses: actions/upload-artifact@v3
+ - uses: actions/upload-artifact@v4
with:
name: appimage
path: |
build/bin/nvim.appimage
build/bin/nvim.appimage.zsync
retention-days: 1
- - uses: actions/upload-artifact@v3
+ - uses: actions/upload-artifact@v4
with:
name: nvim-linux64
path: |
@@ -57,18 +60,21 @@ jobs:
printf 'END\n' >> $GITHUB_OUTPUT
macOS:
- runs-on: macos-11
+ runs-on: macos-14
steps:
- uses: actions/checkout@v4
+ with:
+ # Perform a full checkout #13471
+ fetch-depth: 0
- name: Install dependencies
run: ./.github/scripts/install_deps.sh
- if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name != 'nightly')
- run: printf 'NVIM_BUILD_TYPE=Release\n' >> $GITHUB_ENV
+ run: printf 'CMAKE_BUILD_TYPE=Release\n' >> $GITHUB_ENV
- if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name == 'nightly')
- run: printf 'NVIM_BUILD_TYPE=RelWithDebInfo\n' >> $GITHUB_ENV
+ run: printf 'CMAKE_BUILD_TYPE=RelWithDebInfo\n' >> $GITHUB_ENV
- name: Build universal binary
run: ./.github/scripts/build_universal_macos.sh
- - uses: actions/upload-artifact@v3
+ - uses: actions/upload-artifact@v4
with:
name: nvim-macos
path: build/nvim-macos.tar.gz
@@ -79,6 +85,9 @@ jobs:
name: windows (MSVC_64)
steps:
- uses: actions/checkout@v4
+ with:
+ # Perform a full checkout #13471
+ fetch-depth: 0
- run: .github/scripts/env.ps1
- name: Build deps
run: |
@@ -88,7 +97,7 @@ jobs:
run: |
cmake -B build -G Ninja -DCMAKE_BUILD_TYPE='RelWithDebInfo'
cmake --build build --target package
- - uses: actions/upload-artifact@v3
+ - uses: actions/upload-artifact@v4
with:
name: nvim-win64
path: |
@@ -109,7 +118,7 @@ jobs:
# before running, and would therefore delete the downloaded artifacts
- uses: actions/checkout@v4
- - uses: actions/download-artifact@v3
+ - uses: actions/download-artifact@v4
- name: Install dependencies
run: sudo apt-get update && sudo apt-get install -y gettext-base
@@ -169,37 +178,7 @@ jobs:
DEBUG: api
run: |
envsubst < "$GITHUB_WORKSPACE/.github/workflows/notes.md" > "$RUNNER_TEMP/notes.md"
- gh release create $TAG_NAME $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos/* nvim-linux64/* appimage/* nvim-win64/*
if [ "$TAG_NAME" != "nightly" ]; then
gh release create stable $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos/* nvim-linux64/* appimage/* nvim-win64/*
fi
-
- publish-winget:
- needs: publish
- runs-on: windows-latest
- steps:
- - if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name != 'nightly')
- name: Publish stable
- uses: vedantmgoyal2009/winget-releaser@v2
- with:
- identifier: Neovim.Neovim
- release-tag: ${{ github.event.inputs.tag_name || github.ref_name }}
- token: ${{ secrets.WINGET_TOKEN }}
- - name: Fetch nightly build msi from previous job
- if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name == 'nightly')
- uses: actions/download-artifact@v3
- - if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name == 'nightly')
- name: Get version from nightly build msi
- id: get-version
- run: |
- Install-Module -Name 'Carbon.Windows.Installer' -Force
- $VERSION = (Get-CMsi (Resolve-Path .\nvim-win64\nvim-win64.msi).Path).ProductVersion
- "version=$VERSION" >> $env:GITHUB_OUTPUT
- - if: github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && github.event.inputs.tag_name == 'nightly')
- name: Publish nightly
- uses: vedantmgoyal2009/winget-releaser@v2
- with:
- identifier: Neovim.Neovim.Nightly
- version: ${{ steps.get-version.outputs.version }}
- release-tag: nightly
- token: ${{ secrets.WINGET_TOKEN }}
+ gh release create $TAG_NAME $PRERELEASE --notes-file "$RUNNER_TEMP/notes.md" --title "$SUBJECT" --target $GITHUB_SHA nvim-macos/* nvim-linux64/* appimage/* nvim-win64/*
diff --git a/.github/workflows/add-reviewers.yml b/.github/workflows/reviewers_add.yml
index 22c68b6ef7..b116bca29b 100644
--- a/.github/workflows/add-reviewers.yml
+++ b/.github/workflows/reviewers_add.yml
@@ -1,4 +1,4 @@
-name: "Request reviews"
+name: "reviewers: add"
on:
pull_request_target:
types: [labeled, ready_for_review, reopened]
@@ -15,5 +15,5 @@ jobs:
uses: actions/github-script@v7
with:
script: |
- const script = require('./.github/scripts/reviews.js')
+ const script = require('./.github/scripts/reviewers_add.js')
await script({github, context})
diff --git a/.github/workflows/remove-reviewers.yml b/.github/workflows/reviewers_remove.yml
index 3fe7493b93..b10d8c3d23 100644
--- a/.github/workflows/remove-reviewers.yml
+++ b/.github/workflows/reviewers_remove.yml
@@ -1,4 +1,4 @@
-name: "Remove reviewers"
+name: "reviewers: remove"
on:
pull_request_target:
types: [converted_to_draft, closed]
@@ -13,5 +13,5 @@ jobs:
uses: actions/github-script@v7
with:
script: |
- const script = require('./.github/scripts/remove-reviewers.js')
+ const script = require('./.github/scripts/reviewers_remove.js')
await script({github, context})
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index acf0f195b9..6bd40b8561 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -35,15 +35,12 @@ jobs:
CC: clang
steps:
- uses: actions/checkout@v4
- - run: ./.github/scripts/install_deps.sh
- - uses: ./.github/actions/cache
+ - uses: ./.github/actions/setup
- name: Install stylua
run: |
- URL=$(curl -L https://api.github.com/repos/JohnnyMorganz/StyLua/releases/latest | jq -r '.assets[] | select(.name == "stylua-linux-x86_64.zip") | .browser_download_url')
- wget --directory-prefix="$BIN_DIR" "$URL"
+ wget --directory-prefix="$BIN_DIR" https://github.com/JohnnyMorganz/StyLua/releases/latest/download/stylua-linux-x86_64.zip
(cd "$BIN_DIR"; unzip stylua*.zip)
- echo "$BIN_DIR" >> $GITHUB_PATH
- name: Build third-party deps
run: |
@@ -88,8 +85,7 @@ jobs:
CC: clang
steps:
- uses: actions/checkout@v4
- - run: ./.github/scripts/install_deps.sh
- - uses: ./.github/actions/cache
+ - uses: ./.github/actions/setup
- name: Build third-party deps
run: |
cmake -S cmake.deps --preset ci
@@ -108,14 +104,17 @@ jobs:
{ runner: ubuntu-22.04, flavor: tsan, cc: clang, flags: -D ENABLE_TSAN=ON },
{ runner: ubuntu-22.04, cc: gcc },
{ runner: macos-12, cc: clang, flags: -D CMAKE_FIND_FRAMEWORK=NEVER, deps_flags: -D CMAKE_FIND_FRAMEWORK=NEVER },
- { runner: ubuntu-22.04, flavor: functionaltest-lua, cc: gcc, deps_flags: -D USE_BUNDLED_LUAJIT=OFF -D USE_BUNDLED_LUA=ON, flags: -D PREFER_LUA=ON },
+ { runner: macos-14, cc: clang, flags: -D CMAKE_FIND_FRAMEWORK=NEVER, deps_flags: -D CMAKE_FIND_FRAMEWORK=NEVER },
+ { runner: ubuntu-22.04, flavor: puc-lua, cc: gcc, deps_flags: -D USE_BUNDLED_LUAJIT=OFF -D USE_BUNDLED_LUA=ON, flags: -D PREFER_LUA=ON },
]
test: [unittest, functionaltest, oldtest]
exclude:
- test: unittest
build: { flavor: tsan }
- test: unittest
- build: { flavor: functionaltest-lua }
+ build: { flavor: puc-lua }
+ - test: unittest
+ build: { runner: macos-14 } # unittests don't work on M1 #26145
- test: oldtest
build: { flavor: tsan }
runs-on: ${{ matrix.build.runner }}
@@ -124,24 +123,13 @@ jobs:
CC: ${{ matrix.build.cc }}
steps:
- uses: actions/checkout@v4
- - run: ./.github/scripts/install_deps.sh --test
- - uses: ./.github/actions/cache
-
- - name: Set up environment
- run: |
- ulimit -c unlimited
- echo "$BIN_DIR" >> $GITHUB_PATH
+ - uses: ./.github/actions/setup
+ with:
+ install_flags: "--test"
- name: Create log dir
run: mkdir -p "$LOG_DIR"
- # FIXME(dundargoc): this workaround is needed for macos as the python3
- # provider tests suddenly started to become extremely flaky, and this
- # removes the flakiness for some reason.
- - uses: actions/setup-python@v4
- with:
- python-version: '3.11'
-
- if: ${{ matrix.test != 'unittest' }}
name: Set up interpreter packages
run: |
@@ -161,12 +149,12 @@ jobs:
- name: Build third-party deps
run: |
- cmake -S cmake.deps --preset ci ${{ matrix.build.deps_flags }}
+ cmake -S cmake.deps --preset ci -D CMAKE_BUILD_TYPE=Debug ${{ matrix.build.deps_flags }}
cmake --build .deps
- name: Build
run: |
- cmake --preset ci -D CMAKE_INSTALL_PREFIX:PATH=$INSTALL_PREFIX ${{ matrix.build.flags }}
+ cmake --preset ci -D CMAKE_BUILD_TYPE=Debug -D CMAKE_INSTALL_PREFIX:PATH=$INSTALL_PREFIX ${{ matrix.build.flags }}
cmake --build build
- name: ${{ matrix.test }}
@@ -213,8 +201,7 @@ jobs:
test: [functional, old]
steps:
- uses: actions/checkout@v4
- - uses: ./.github/actions/cache
- - run: .github/scripts/env.ps1
+ - uses: ./.github/actions/setup
- name: Build deps
run: |
@@ -281,8 +268,7 @@ jobs:
CC: gcc
steps:
- uses: actions/checkout@v4
- - run: ./.github/scripts/install_deps.sh
- - uses: ./.github/actions/cache
+ - uses: ./.github/actions/setup
- name: Build third-party deps
run: |
@@ -308,11 +294,11 @@ jobs:
CC: gcc
steps:
- uses: actions/checkout@v4
+ - uses: ./.github/actions/setup
- name: Install dependencies
run: |
sudo add-apt-repository ppa:neovim-ppa/stable
- ./.github/scripts/install_deps.sh
sudo apt-get install -y \
libluajit-5.1-dev \
libmsgpack-dev \
@@ -329,8 +315,6 @@ jobs:
# Remove comments from packages once we start using these external
# dependencies.
- - uses: ./.github/actions/cache
-
- name: Build third-party deps
run: |
cmake -S cmake.deps --preset external_deps
diff --git a/.github/workflows/vim-patches.yml b/.github/workflows/vim_patches.yml
index 711ddae815..711ddae815 100644
--- a/.github/workflows/vim-patches.yml
+++ b/.github/workflows/vim_patches.yml
diff --git a/.luacheckrc b/.luacheckrc
index 701f461dc4..d54c61e9e7 100644
--- a/.luacheckrc
+++ b/.luacheckrc
@@ -47,5 +47,6 @@ exclude_files = {
'runtime/lua/vim/_meta/vimfn.lua',
'runtime/lua/vim/_meta/api.lua',
'runtime/lua/vim/re.lua',
+ 'runtime/lua/coxpcall.lua',
'src/nvim/eval.lua',
}
diff --git a/.luarc.json b/.luarc.json
index 5a014a26ea..2bd57d6973 100644
--- a/.luarc.json
+++ b/.luarc.json
@@ -1,7 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/LuaLS/vscode-lua/master/setting/schema.json",
"runtime": {
- "version": "LuaJIT"
+ "version": "LuaJIT"
},
"workspace": {
"library": [
@@ -12,7 +12,7 @@
"ignoreDir": [
"test"
],
- "checkThirdParty": false
+ "checkThirdParty": "Disable"
},
"diagnostics": {
"groupFileStatus": {
diff --git a/.stylua.toml b/.stylua.toml
index a2b3447506..22d6d3e6fc 100644
--- a/.stylua.toml
+++ b/.stylua.toml
@@ -3,4 +3,4 @@ line_endings = "Unix"
indent_type = "Spaces"
indent_width = 2
quote_style = "AutoPreferSingle"
-call_parentheses = "Always"
+call_parentheses = "Input"
diff --git a/.styluaignore b/.styluaignore
index c9303e07ce..80c6a9692c 100644
--- a/.styluaignore
+++ b/.styluaignore
@@ -1,7 +1,14 @@
-/build
+/build/
+/.deps/
/runtime/lua/coxpcall.lua
/runtime/lua/vim/_meta
/runtime/lua/vim/re.lua
-/scripts
-/src
-/test
+
+test/functional/ui/decorations_spec.lua
+test/functional/ui/float_spec.lua
+test/functional/ui/multigrid_spec.lua
+/test/functional/fixtures/lua/syntax_error.lua
+/test/functional/legacy/030_fileformats_spec.lua
+/test/functional/legacy/044_099_regexp_multibyte_magic_spec.lua
+/test/functional/legacy/093_mksession_cursor_cols_latin1_spec.lua
+/test/functional/lua/luaeval_spec.lua
diff --git a/BUILD.md b/BUILD.md
new file mode 100644
index 0000000000..ce553eb8bf
--- /dev/null
+++ b/BUILD.md
@@ -0,0 +1,450 @@
+- **IMPORTANT**: Before upgrading to a new version, **always check for [breaking changes](https://neovim.io/doc/user/news.html#news-breaking).**
+
+
+## Quick start
+
+1. Install [build prerequisites](#build-prerequisites) on your system
+2. `git clone https://github.com/neovim/neovim`
+3. `cd neovim && make CMAKE_BUILD_TYPE=RelWithDebInfo`
+ - If you want the **stable release**, also run `git checkout stable`.
+ - If you want to install to a custom location, set `CMAKE_INSTALL_PREFIX`. See also [INSTALL.md](./INSTALL.md#install-from-source).
+ - On BSD, use `gmake` instead of `make`.
+ - To build on Windows, see the [Building on Windows](#building-on-windows) section. _MSVC (Visual Studio) is recommended._
+4. `sudo make install`
+ - Default install location is `/usr/local`
+ - On Debian/Ubuntu, instead of installing files directly with `sudo make install`, you can run `cd build && cpack -G DEB && sudo dpkg -i nvim-linux64.deb` to build DEB-package and install it. This should help ensuring the clean removal of installed files.
+
+**Notes**:
+- From the repository's root directory, running `make` will download and build all the needed dependencies and put the `nvim` executable in `build/bin`.
+- Third-party dependencies (libuv, LuaJIT, etc.) are downloaded automatically to `.deps/`. See the [FAQ](FAQ#build-issues) if you have issues.
+- After building, you can run the `nvim` executable without installing it by running `VIMRUNTIME=runtime ./build/bin/nvim`.
+- If you plan to develop Neovim, install [Ninja](https://ninja-build.org/) for faster builds. It will automatically be used.
+- Install [ccache](https://ccache.dev/) for faster rebuilds of Neovim. It's used by default. To disable it, use `CCACHE_DISABLE=true make`.
+
+## Running tests
+
+See [test/README.md](https://github.com/neovim/neovim/blob/master/test/README.md).
+
+## Building
+
+First make sure you installed the [build prerequisites](#build-prerequisites). Now that you have the dependencies, you can try other build targets explained below.
+
+The _build type_ determines the level of used compiler optimizations and debug information:
+
+- `Release`: Full compiler optimizations and no debug information. Expect the best performance from this build type. Often used by package maintainers.
+- `Debug`: Full debug information; few optimizations. Use this for development to get meaningful output from debuggers like GDB or LLDB. This is the default if `CMAKE_BUILD_TYPE` is not specified.
+- `RelWithDebInfo` ("Release With Debug Info"): Enables many optimizations and adds enough debug info so that when Neovim ever crashes, you can still get a backtrace.
+
+So, for a release build, just use:
+
+```
+make CMAKE_BUILD_TYPE=Release
+```
+(Do not add a `-j` flag if `ninja` is installed! The build will be in parallel automatically.)
+
+Afterwards, the `nvim` executable can be found in `build/bin`. To verify the build type after compilation, run:
+
+```sh
+./build/bin/nvim --version | grep ^Build
+```
+
+To install the executable to a certain location, use:
+
+```
+make CMAKE_INSTALL_PREFIX=$HOME/local/nvim install
+```
+
+CMake, our main build system, caches a lot of things in `build/CMakeCache.txt`. If you ever want to change `CMAKE_BUILD_TYPE` or `CMAKE_INSTALL_PREFIX`, run `rm -rf build` first. This is also required when rebuilding after a Git commit adds or removes files (including from `runtime`) — when in doubt, run `make distclean` (which is basically a shortcut for `rm -rf build .deps`).
+
+By default (`USE_BUNDLED=1`), Neovim downloads and statically links its needed dependencies. In order to be able to use a debugger on these libraries, you might want to compile them with debug information as well:
+
+<!-- THIS CAUSES SCREEN INTERFERENCE
+```
+make distclean
+VERBOSE=1 DEBUG=1 make deps
+```
+-->
+```
+make distclean
+make deps
+```
+
+## Building on Windows
+
+### Windows / MSVC
+
+**MSVC (Visual Studio) is the recommended way to build on Windows.** These steps were confirmed as of 2023.
+
+1. Install [Visual Studio](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community) (2017 or later) with the _Desktop development with C++_ workload.
+ - On 32-bit Windows, you will need [this workaround](https://developercommunity.visualstudio.com/content/problem/212989/ninja-binary-format.html).
+2. Open the Neovim project folder.
+ - Visual Studio should detect the cmake files and automatically start building...
+3. Choose the `nvim.exe (bin\nvim.exe)` target and hit F5.
+ - If the build fails, it may be because Visual Studio started the build with `x64-{Debug,Release}` before you switched the configuration to `x86-Release`.
+ - Right-click _CMakeLists.txt → Delete Cache_.
+ - Right-click _CMakeLists.txt → Generate Cache_.
+ - If you see an "access violation" from `ntdll`, you can ignore it and continue.
+4. If you set an error like `msgpackc.dll not found`, try the `nvim.exe (Install)` target. Then switch back to `nvim.exe (bin\nvim.exe)`.
+
+### Windows / MSVC PowerShell
+
+To build from the command line (i.e. invoke the `cmake` commands yourself),
+
+1. Ensure you have the Visual Studio environment variables, using any of the following:
+ - Using the [Visual Studio Developer Command Prompt or Visual Studio Developer PowerShell](https://learn.microsoft.com/en-us/visualstudio/ide/reference/command-prompt-powershell?view=vs-2022)
+ - Invoking `Import-VisualStudioVars` in PowerShell from [this PowerShell module](https://github.com/Pscx/Pscx)
+ - Invoking `VsDevCmd.bat` in Command Prompt
+ ```
+ VsDevCmd.bat -arch=x64
+ ```
+ This is to make sure that `luarocks` finds the Visual Studio installation, and doesn't fall back to MinGW with errors like:
+ ```
+ 'mingw32-gcc' is not recognized as an internal or external command
+ ```
+2. From the "Developer PowerShell" or "Developer Command Prompt":
+ ```
+ cmake -S cmake.deps -B .deps -G Ninja -D CMAKE_BUILD_TYPE=Release
+ cmake --build .deps --config Release
+ cmake -B build -G Ninja -D CMAKE_BUILD_TYPE=Release
+ cmake --build build --config Release
+ ```
+ - Omit `--config Release` if you want a debug build.
+ - Omit `-G Ninja` to use the "Visual Studio" generator.
+
+### Windows / CLion
+
+1. Install [CLion](https://www.jetbrains.com/clion/).
+2. Open the Neovim project in CLion.
+3. Select _Build → Build All in 'Release'_.
+
+### Windows / Cygwin
+
+Install all dependencies the normal way, then build Neovim the normal way for a random CMake application (i.e. do not use the `Makefile` that automatically downloads and builds "bundled" dependencies).
+
+The `cygport` repo contains Cygport files (e.g. `APKBUILD`, `PKGBUILD`) for all the dependencies not available in the Cygwin distribution, and describes any special commands or arguments needed to build. The Cygport definitions also try to describe the required dependencies for each one. Unless custom commands are provided, Cygport just calls `autogen`/`cmake`, `make`, `make install`, etc. in a clean and consistent way.
+
+https://github.com/cascent/neovim-cygwin was built on Cygwin 2.9.0. Newer `libuv` should require slightly less patching. Some SSP stuff changed in Cygwin 2.10.0, so that might change things too when building Neovim.
+
+
+### Windows / MSYS2 / MinGW
+
+1. From the MSYS2 shell, install these packages:
+ ```
+ pacman -S \
+ mingw-w64-x86_64-{gcc,cmake,make,ninja,diffutils}
+ ```
+2. From the Windows Command Prompt (`cmd.exe`), set up the `PATH` and build.
+
+ ```cmd
+ set PATH=c:\msys64\mingw64\bin;c:\msys64\usr\bin;%PATH%
+ ```
+3. You have two options:
+ - Build using `cmake` and `Ninja` generator:
+ ```cmd
+ cmake -S cmake.deps -B .deps -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo
+ cmake --build .deps
+ cmake -B build -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo
+ cmake --build build
+ ```
+ If you cannot install neovim with `ninja install` due to permission restriction, you can install neovim in a directory you have write access to.
+ ```cmd
+ cmake -S cmake.deps -B .deps -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo
+ cmake --build .deps
+ cmake -B build -G Ninja -D CMAKE_INSTALL_PREFIX=C:\nvim -D CMAKE_BUILD_TYPE=RelWithDebInfo
+ cmake --build build
+ ```
+ - Or, alternatively, you can use `mingw32-make`:
+ ```cmd
+ mingw32-make deps
+ mingw32-make CMAKE_BUILD_TYPE=RelWithDebInfo
+ :: Or you can do the previous command specifying a custom prefix
+ :: (Default is C:\Program Files (x86)\nvim)
+ :: mingw32-make CMAKE_BUILD_TYPE=RelWithDebInfo CMAKE_INSTALL_PREFIX=C:\nvim
+ mingw32-make install
+ ```
+
+## Localization
+
+### Localization build
+
+A normal build will create `.mo` files in `build/src/nvim/po`.
+
+* If you see `msgfmt: command not found`, you need to install [`gettext`](http://en.wikipedia.org/wiki/Gettext). On most systems, the package is just called `gettext`.
+
+### Localization check
+
+To check the translations for `$LANG`, run `make -C build check-po-$LANG`. Examples:
+
+```
+cmake --build build --target check-po-de
+cmake --build build --target check-po-pt_BR
+```
+
+- `check-po-$LANG` generates a detailed report in `./build/src/nvim/po/check-${LANG}.log`. (The report is generated by `nvim`, not by `msgfmt`.)
+
+### Localization update
+
+To update the `src/nvim/po/$LANG.po` file with the latest strings, run the following:
+
+```
+cmake --build build --target update-po-$LANG
+```
+
+- **Note**: Run `src/nvim/po/cleanup.vim` after updating.
+
+## Compiler options
+
+To see the chain of includes, use the `-H` option ([#918](https://github.com/neovim/neovim/issues/918)):
+
+```sh
+echo '#include "./src/nvim/buffer.h"' | \
+> clang -I.deps/usr/include -Isrc -std=c99 -P -E -H - 2>&1 >/dev/null | \
+> grep -v /usr/
+```
+
+- `grep -v /usr/` is used to filter out system header files.
+- `-save-temps` can be added as well to see expanded macros or commented assembly.
+
+## Custom Makefile
+
+You can customize the build process locally by creating a `local.mk`, which is referenced at the top of the main `Makefile`. It's listed in `.gitignore`, so it can be used across branches. **A new target in `local.mk` overrides the default make-target.**
+
+Here's a sample `local.mk` which adds a target to force a rebuild but *does not* override the default-target:
+
+```make
+all:
+
+rebuild:
+ rm -rf build
+ make
+```
+
+## Third-party dependencies
+
+Reference the [Debian package](https://packages.debian.org/sid/source/neovim) (or alternatively, the [Homebrew formula](https://github.com/Homebrew/homebrew-core/blob/master/Formula/neovim.rb)) for the precise list of dependencies/versions.
+
+To build the bundled dependencies using CMake:
+
+```sh
+cmake -S cmake.deps -B .deps -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo
+cmake --build .deps
+```
+
+By default the libraries and headers are placed in `.deps/usr`. Now you can build Neovim:
+
+```sh
+cmake -B build -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo
+cmake --build build
+```
+
+### How to build without "bundled" dependencies
+
+1. Manually install the dependencies:
+ - libuv libluv libtermkey luajit lua-lpeg lua-mpack msgpack-c tree-sitter unibilium
+2. Run CMake:
+ ```sh
+ cmake -B build -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo
+ cmake --build build
+ ```
+ If all the dependencies are not available in the package, you can use only some of the bundled dependencies as follows (example of using `ninja`):
+ ```sh
+ cmake -S cmake.deps -B .deps -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo -DUSE_BUNDLED=OFF -DUSE_BUNDLED_LIBVTERM=ON -DUSE_BUNDLED_TS=ON
+ cmake --build .deps
+ cmake -B build -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo
+ cmake --build build
+ ```
+3. Run `make`, `ninja`, or whatever build tool you told CMake to generate.
+ - Using `ninja` is strongly recommended.
+
+#### Debian 10 (Buster) example:
+
+```sh
+sudo apt install luajit libluajit-5.1-dev lua-mpack lua-lpeg libunibilium-dev libmsgpack-dev libtermkey-dev
+cmake -S cmake.deps -B .deps -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo -DUSE_BUNDLED=OFF -DUSE_BUNDLED_LIBUV=ON -DUSE_BUNDLED_LUV=ON -DUSE_BUNDLED_LIBVTERM=ON -DUSE_BUNDLED_TS=ON
+cmake --build .deps
+cmake -B build -G Ninja -D CMAKE_BUILD_TYPE=RelWithDebInfo
+cmake --build build
+```
+
+#### Example of using a Makefile
+
+- Example of using a package with all dependencies:
+ ```
+ make USE_BUNDLED=OFF
+ ```
+- Example of using a package with some dependencies:
+ ```
+ make BUNDLED_CMAKE_FLAG="-DUSE_BUNDLED=OFF -DUSE_BUNDLED_LUV=ON -DUSE_BUNDLED_TS=ON -DUSE_BUNDLED_LIBVTERM=ON -DUSE_BUNDLED_LIBUV=ON"
+ ```
+
+## Build prerequisites
+
+General requirements (see [#1469](https://github.com/neovim/neovim/issues/1469#issuecomment-63058312)):
+
+- Clang or GCC version 4.9+
+- CMake version 3.13+, built with TLS/SSL support
+ - Optional: Get the latest CMake from an [installer](https://github.com/Kitware/CMake/releases) or the [Python package](https://pypi.org/project/cmake/) (`pip install cmake`)
+
+Platform-specific requirements are listed below.
+
+### Ubuntu / Debian
+
+```sh
+sudo apt-get install ninja-build gettext cmake unzip curl
+```
+
+### CentOS / RHEL / Fedora
+
+```
+sudo dnf -y install ninja-build cmake gcc make unzip gettext curl
+```
+
+### openSUSE
+
+```
+sudo zypper install ninja cmake gcc-c++ gettext-tools curl
+```
+
+### Arch Linux
+
+```
+sudo pacman -S base-devel cmake unzip ninja curl
+```
+
+### Alpine Linux
+
+```
+apk add build-base cmake coreutils curl unzip gettext-tiny-dev
+```
+
+### Void Linux
+
+```
+xbps-install base-devel cmake curl git
+```
+
+### NixOS / Nix
+
+Starting from NixOS 18.03, the Neovim binary resides in the `neovim-unwrapped` Nix package (the `neovim` package being just a wrapper to setup runtime options like Ruby/Python support):
+
+```sh
+cd path/to/neovim/src
+```
+
+Drop into `nix-shell` to pull in the Neovim dependencies:
+
+```
+nix-shell '<nixpkgs>' -A neovim-unwrapped
+```
+
+Configure and build:
+
+```sh
+rm -rf build && cmakeConfigurePhase
+buildPhase
+```
+
+Tests are not available by default, because of some unfixed failures. You can enable them via adding this package in your overlay:
+```
+ neovim-dev = (super.pkgs.neovim-unwrapped.override {
+ doCheck=true;
+ }).overrideAttrs(oa:{
+ cmakeBuildType="debug";
+
+ nativeBuildInputs = oa.nativeBuildInputs ++ [ self.pkgs.valgrind ];
+ shellHook = ''
+ export NVIM_PYTHON_LOG_LEVEL=DEBUG
+ export NVIM_LOG_FILE=/tmp/log
+ export VALGRIND_LOG="$PWD/valgrind.log"
+ '';
+ });
+```
+and replacing `neovim-unwrapped` with `neovim-dev`:
+```
+nix-shell '<nixpkgs>' -A neovim-dev
+```
+
+Neovim contains a Nix flake in the `contrib` folder, with 3 packages:
+- `neovim` to run the nightly
+- `neovim-debug` to run the package with debug symbols
+- `neovim-developer` to get all the tools to develop on `neovim`
+
+Thus you can run Neovim nightly with `nix run github:neovim/neovim?dir=contrib`.
+Similarly to develop on Neovim: `nix develop github:neovim/neovim?dir=contrib#neovim-developer`.
+
+### FreeBSD
+
+```
+sudo pkg install cmake gmake sha unzip wget gettext curl
+```
+
+If you get an error regarding a `sha256sum` mismatch, where the actual SHA-256 hash is `e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855`, then this is your issue (that's the `sha256sum` of an empty file).
+
+### OpenBSD
+
+```sh
+doas pkg_add gmake cmake unzip curl gettext-tools
+```
+
+Build can sometimes fail when using the top level `Makefile`, apparently due to some third-party component (see [#2445-comment](https://github.com/neovim/neovim/issues/2445#issuecomment-108124236)). The following instructions use CMake:
+
+```sh
+mkdir .deps
+cd .deps
+cmake ../cmake.deps/
+gmake
+cd ..
+mkdir build
+cd build
+cmake ..
+gmake
+```
+
+### macOS
+
+#### macOS / Homebrew
+
+1. Install Xcode Command Line Tools: `xcode-select --install`
+2. Install [Homebrew](http://brew.sh)
+3. Install Neovim build dependencies:
+ ```
+ brew install ninja cmake gettext curl
+ ```
+ - **Note**: If you see Wget certificate errors (for older macOS versions less than 10.10):
+ ```sh
+ brew install curl-ca-bundle
+ echo CA_CERTIFICATE=$(brew --prefix curl-ca-bundle)/share/ca-bundle.crt >> ~/.wgetrc
+ ```
+ - **Note**: If you see `'stdio.h' file not found`, try the following:
+ ```
+ open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg
+ ```
+
+#### macOS / MacPorts
+
+1. Install Xcode Command Line Tools: `xcode-select --install`
+2. Install [MacPorts](http://www.macports.org)
+3. Install Neovim build dependencies:
+ ```
+ sudo port install ninja cmake gettext
+ ```
+ - **Note**: If you see Wget certificate errors (for older macOS versions less than 10.10):
+ ```sh
+ sudo port install curl-ca-bundle
+ echo CA_CERTIFICATE=/opt/local/share/curl/curl-ca-bundle.crt >> ~/.wgetrc
+ ```
+ - **Note**: If you see `'stdio.h' file not found`, try the following:
+ ```
+ open /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg
+ ```
+
+#### Building for older macOS versions
+
+From a newer macOS version, to build for older macOS versions, you will have to set the macOS deployment target:
+
+```
+make CMAKE_BUILD_TYPE=Release MACOSX_DEPLOYMENT_TARGET=10.13 DEPS_CMAKE_FLAGS="-DCMAKE_CXX_COMPILER=$(xcrun -find c++)"
+```
+
+Note that the C++ compiler is explicitly set so that it can be found when the deployment target is set.
+
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 475a1a2c3e..009b562953 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -4,7 +4,7 @@
# pitfalls: https://izzys.casa/2019/02/everything-you-never-wanted-to-know-about-cmake/
# Version should match the tested CMAKE_URL in .github/workflows/build.yml.
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.13)
# Can be removed once minimum version is at least 3.15
if(POLICY CMP0092)
@@ -13,13 +13,14 @@ endif()
project(nvim C)
-if(POLICY CMP0075)
- cmake_policy(SET CMP0075 NEW)
-endif()
if(POLICY CMP0135)
cmake_policy(SET CMP0135 NEW)
endif()
+if(XCODE)
+ message(FATAL_ERROR [[Xcode generator is not supported. Use "Ninja" or "Unix Makefiles" instead.]])
+endif()
+
# Point CMake at any custom modules we may ship
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")
@@ -36,11 +37,17 @@ include(InstallHelpers)
include(PreventInTreeBuilds)
include(Util)
+#-------------------------------------------------------------------------------
+# Variables
+#-------------------------------------------------------------------------------
+set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack)
+set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches)
+
+file(GLOB DOCFILES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/runtime/doc/*.txt)
+
set_directory_properties(PROPERTIES
EP_PREFIX "${DEPS_BUILD_DIR}")
-set(TOUCHES_DIR ${PROJECT_BINARY_DIR}/touches)
-
find_program(CCACHE_PRG ccache)
if(CCACHE_PRG)
set(CMAKE_C_COMPILER_LAUNCHER ${CMAKE_COMMAND} -E env CCACHE_SLOPPINESS=pch_defines,time_macros ${CCACHE_PRG})
@@ -54,6 +61,12 @@ if(${CMAKE_VERSION} VERSION_LESS 3.20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
endif()
+if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.26)
+ set(COPY_DIRECTORY copy_directory_if_different)
+else()
+ set(COPY_DIRECTORY copy_directory)
+endif()
+
# Prefer our bundled versions of dependencies.
if(DEFINED ENV{DEPS_BUILD_DIR})
set(DEPS_PREFIX "$ENV{DEPS_BUILD_DIR}/usr" CACHE PATH "Path prefix for finding dependencies")
@@ -116,10 +129,11 @@ if (MINGW)
else()
option(ENABLE_LTO "enable link time optimization" ON)
endif()
+option(ENABLE_LIBINTL "enable libintl" ON)
message(STATUS "CMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}")
-set_default_buildtype()
+set_default_buildtype(Debug)
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT isMultiConfig)
# Unlike build dependencies in cmake.deps, we assume we want dev dependencies
@@ -220,27 +234,24 @@ endif()
find_program(SHELLCHECK_PRG shellcheck ${LINT_REQUIRED})
find_program(STYLUA_PRG stylua ${LINT_REQUIRED})
+set(STYLUA_DIRS runtime scripts src test contrib)
+
add_glob_target(
TARGET lintlua-luacheck
- COMMAND $<TARGET_FILE:nvim>
+ COMMAND $<TARGET_FILE:nvim_bin>
FLAGS -ll ${PROJECT_SOURCE_DIR}/test/lua_runner.lua ${CMAKE_BINARY_DIR}/usr luacheck -q
- GLOB_DIRS runtime/ scripts/ src/ test/
+ GLOB_DIRS runtime scripts src test
GLOB_PAT *.lua
- EXCLUDE
- runtime/lua/vim/_meta/.*
- runtime/lua/coxpcall.lua
- TOUCH_STRATEGY SINGLE)
+ TOUCH_STRATEGY PER_DIR)
add_dependencies(lintlua-luacheck lua-dev-deps)
add_glob_target(
TARGET lintlua-stylua
COMMAND ${STYLUA_PRG}
FLAGS --color=always --check --respect-ignores
- GLOB_DIRS runtime/
+ GLOB_DIRS ${STYLUA_DIRS}
GLOB_PAT *.lua
- EXCLUDE
- /runtime/lua/vim/_meta
- TOUCH_STRATEGY SINGLE)
+ TOUCH_STRATEGY PER_DIR)
add_custom_target(lintlua)
add_dependencies(lintlua lintlua-luacheck lintlua-stylua)
@@ -251,22 +262,23 @@ add_glob_target(
FLAGS -x -a
GLOB_DIRS scripts
GLOB_PAT *.sh
- TOUCH_STRATEGY SINGLE)
+ TOUCH_STRATEGY PER_DIR)
add_custom_target(lintcommit
- COMMAND $<TARGET_FILE:nvim> -u NONE -l ${PROJECT_SOURCE_DIR}/scripts/lintcommit.lua main)
-add_dependencies(lintcommit nvim)
+ COMMAND $<TARGET_FILE:nvim_bin> -u NONE -l ${PROJECT_SOURCE_DIR}/scripts/lintcommit.lua main)
+add_dependencies(lintcommit nvim_bin)
add_custom_target(lint)
-add_dependencies(lint lintc lintlua lintsh lintcommit)
+add_dependencies(lint lintc lintlua lintsh lintcommit lintdoc)
# Format
-add_custom_target(formatlua
- COMMAND ${CMAKE_COMMAND}
- -D FORMAT_PRG=${STYLUA_PRG}
- -D LANG=lua
- -P ${PROJECT_SOURCE_DIR}/cmake/Format.cmake
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
+add_glob_target(
+ TARGET formatlua
+ COMMAND ${STYLUA_PRG}
+ FLAGS --respect-ignores
+ GLOB_DIRS ${STYLUA_DIRS}
+ GLOB_PAT *.lua
+ TOUCH_STRATEGY PER_DIR)
add_custom_target(format)
add_dependencies(format formatc formatlua)
@@ -275,6 +287,9 @@ install_helper(
FILES ${CMAKE_SOURCE_DIR}/src/man/nvim.1
DESTINATION ${CMAKE_INSTALL_MANDIR}/man1)
+add_custom_target(nvim ALL)
+add_dependencies(nvim nvim_bin nvim_runtime_deps nvim_runtime)
+
add_subdirectory(src/nvim)
add_subdirectory(cmake.config)
add_subdirectory(runtime)
@@ -290,24 +305,24 @@ endif()
ExternalProject_Add(uncrustify
URL https://github.com/uncrustify/uncrustify/archive/uncrustify-0.78.1.tar.gz
URL_HASH SHA256=ecaf4c0adca14c36dfffa30bc28e69865115ecd602c90eb16a8cddccb41caad2
- 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)
+ EXCLUDE_FROM_ALL TRUE
+ ${EXTERNALPROJECT_OPTIONS})
option(USE_BUNDLED_BUSTED "Use bundled busted" ON)
if(USE_BUNDLED_BUSTED)
ExternalProject_Add(lua-dev-deps
URL https://github.com/neovim/deps/raw/5a1f71cceb24990a0b15fd9a472a5f549f019248/opt/lua-dev-deps.tar.gz
URL_HASH SHA256=27db2495f5eddc7fc191701ec9b291486853530c6125609d3197d03481e8d5a2
- DOWNLOAD_NO_PROGRESS TRUE
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/lua-dev-deps
SOURCE_DIR ${DEPS_SHARE_DIR}
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
- EXCLUDE_FROM_ALL TRUE)
+ EXCLUDE_FROM_ALL TRUE
+ ${EXTERNALPROJECT_OPTIONS})
else()
add_custom_target(lua-dev-deps)
endif()
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 4f9c0d720d..2f5c2cce5a 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -21,10 +21,11 @@ Reporting problems
- [Search existing issues][github-issues] (including closed!)
- Update Neovim to the latest version to see if your problem persists.
- Try to reproduce with `nvim --clean` ("factory defaults").
+- If a specific configuration or plugin is necessary to recreate the problem, use the minimal template in `contrib/minimal.lua` with `nvim --clean -u contrib/minimal.lua` after making the necessary changes.
- [Bisect](https://neovim.io/doc/user/starting.html#bisect) your config: disable plugins incrementally, to narrow down the cause of the issue.
- [Bisect][git-bisect] Neovim's source code to find the cause of a regression, if you can. This is _extremely_ helpful.
-- When reporting a crash, [include a stacktrace](https://github.com/neovim/neovim/wiki/FAQ#backtrace-linux).
-- Use [ASAN/UBSAN](#clang-sanitizers-asan-and-ubsan) to get detailed errors for segfaults and undefined behavior.
+- When reporting a crash, [include a stacktrace](https://neovim.io/doc/user/dev_tools.html#dev-tools-backtrace).
+- Use [ASAN/UBSAN](#sanitizers-asan-and-ubsan) to get detailed errors for segfaults and undefined behavior.
- Check the logs. `:edit $NVIM_LOG_FILE`
- Include `cmake --system-information` for build-related issues.
@@ -148,8 +149,10 @@ View the [Clang report] to see potential bugs found by the Clang
### Coverity
-[Coverity](https://scan.coverity.com/projects/neovim-neovim) runs against the
-master build. To view the defects, just request access; you will be approved.
+Coverity runs against the master build. To view the defects you must
+[request access](https://scan.coverity.com/projects/neovim-neovim) (Coverity
+does not have a "public" view), then you will be approved as soon as
+a maintainer sees the email.
- Use this format for commit messages (where `{id}` is the CID (Coverity ID);
([example](https://github.com/neovim/neovim/pull/804))):
@@ -262,12 +265,23 @@ Many `:help` docs are autogenerated from (C or Lua) docstrings. To generate the
make doc
```
+To validate the documentation files, run:
+
+```bash
+make lintdoc
+```
+
If you need to modify or debug the documentation flow, these are the main files:
-- `./scripts/gen_vimdoc.py`:
- Main doc generator. Drives doxygen to generate xml files, and scrapes those
- xml files to render vimdoc files.
-- `./scripts/lua2dox.lua`:
- Used by `gen_vimdoc.py` to transform Lua files into a format compatible with doxygen.
+- `./scripts/gen_vimdoc.lua`:
+ Main doc generator. Parses C and Lua files to render vimdoc files.
+- `./scripts/luacats_parser.lua`:
+ Documentation parser for Lua files.
+- `./scripts/cdoc_parser.lua`:
+ Documentation parser for C files.
+- `./scripts/luacats_grammar.lua`:
+ Lpeg grammar for LuaCATS
+- `./scripts/cdoc_grammar.lua`:
+ Lpeg grammar for C doc comments
- `./scripts/gen_eval_files.lua`:
Generates documentation and Lua type files from metadata files:
```
@@ -279,10 +293,12 @@ If you need to modify or debug the documentation flow, these are the main files:
src/nvim/options.lua => runtime/doc/options.txt
```
+- `./scripts/lintdoc.lua`: Validation and linting of documentation files.
+
### Lua docstrings
Use [LuaLS] annotations in Lua docstrings to annotate parameter types, return
-types, etc. See [:help dev-doc-lua][dev-doc-lua].
+types, etc. See [:help dev-lua-doc][dev-lua-doc].
- The template for function documentation is:
```lua
@@ -326,12 +342,12 @@ as context, use the `-W` argument as well.
[Clang report]: https://neovim.io/doc/reports/clang/
[GitHub Actions]: https://github.com/neovim/neovim/actions
[clangd]: https://clangd.llvm.org
-[Merge a Vim patch]: https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-Vim
+[Merge a Vim patch]: https://neovim.io/doc/user/dev_vimpatch.html
[complexity:low]: https://github.com/neovim/neovim/issues?q=is%3Aopen+is%3Aissue+label%3Acomplexity%3Alow
[conventional_commits]: https://www.conventionalcommits.org
[dev-doc-guide]: https://neovim.io/doc/user/develop.html#dev-doc
-[dev-doc-lua]: https://neovim.io/doc/user/develop.html#dev-lua-doc
-[LuaLS]: https://github.com/LuaLS/lua-language-server/wiki/Annotations
+[dev-lua-doc]: https://neovim.io/doc/user/develop.html#dev-lua-doc
+[LuaLS]: https://luals.github.io/wiki/annotations/
[gcc-warnings]: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html
[gh]: https://cli.github.com/
[git-bisect]: http://git-scm.com/book/en/v2/Git-Tools-Debugging-with-Git
@@ -346,4 +362,4 @@ as context, use the `-W` argument as well.
[pr-ready]: https://docs.github.com/en/github/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-stage-of-a-pull-request
[run-tests]: https://github.com/neovim/neovim/blob/master/test/README.md#running-tests
[style-guide]: https://neovim.io/doc/user/dev_style.html#dev-style
-[wiki-faq]: https://github.com/neovim/neovim/wiki/FAQ
+[wiki-faq]: https://neovim.io/doc/user/faq.html
diff --git a/INSTALL.md b/INSTALL.md
new file mode 100644
index 0000000000..9bba1f0a8c
--- /dev/null
+++ b/INSTALL.md
@@ -0,0 +1,416 @@
+You can install Neovim from [download](#install-from-download), [package](#install-from-package), or [source](#install-from-source) in just a few seconds.
+
+---
+
+- To start Neovim, run `nvim` (not `neovim`).
+ - [Discover plugins](https://github.com/neovim/neovim/wiki/Related-projects#plugins).
+- Before upgrading to a new version, **check [Breaking Changes](https://neovim.io/doc/user/news.html#news-breaking).**
+- For config (vimrc) see [the FAQ](https://neovim.io/doc/user/faq.html#faq-general).
+
+---
+
+Install from download
+=====================
+
+Downloads are available on the [Releases](https://github.com/neovim/neovim/releases) page.
+
+* Latest [stable release](https://github.com/neovim/neovim/releases/latest)
+ * [macOS](https://github.com/neovim/neovim/releases/latest/download/nvim-macos.tar.gz)
+ * [Linux](https://github.com/neovim/neovim/releases/latest/download/nvim-linux64.tar.gz)
+ * [Windows](https://github.com/neovim/neovim/releases/latest/download/nvim-win64.msi)
+* Latest [development prerelease](https://github.com/neovim/neovim/releases/nightly)
+
+
+Install from package
+====================
+
+Packages are listed below. (You can also [build Neovim from source](#install-from-source).)
+
+## Windows
+
+Windows 8+ is required. Windows 7 or older is not supported.
+
+### [Winget](https://docs.microsoft.com/en-us/windows/package-manager/winget/)
+
+- **Release:** `winget install Neovim.Neovim`
+
+### [Chocolatey](https://chocolatey.org)
+
+- **Release (v0.7):** `choco install neovim` (use -y for automatically skipping confirmation messages)
+- **Development (pre-release):** `choco install neovim --pre`
+
+### [Scoop](https://scoop.sh/)
+```
+scoop bucket add main
+scoop install neovim
+```
+- **Release:** `scoop install neovim`
+
+Several Neovim GUIs are available from scoop (extras): [scoop.sh/#/apps?q=neovim](https://scoop.sh/#/apps?q=neovim)
+
+### Pre-built archives
+
+0. If you are missing `VCRUNTIME140.dll`, install the [Visual Studio 2015 C++ redistributable](https://support.microsoft.com/en-us/kb/2977003) (choose x86_64 or x86 depending on your system).
+1. Choose a package (**nvim-winXX.zip**) from the [releases page](https://github.com/neovim/neovim/releases).
+2. Unzip the package. Any location is fine, administrator privileges are _not_ required.
+ - `$VIMRUNTIME` will be set to that location automatically.
+3. Double-click `nvim-qt.exe`.
+
+**Optional** steps:
+
+- Add the `bin` folder (e.g. `C:\Program Files\nvim\bin`) to your PATH.
+ - This makes it easy to run `nvim` and `nvim-qt` from anywhere.
+- If `:set spell` does not work, create the `C:/Users/foo/AppData/Local/nvim/site/spell` folder.
+ You can then copy your spell files over (for English, located
+ [here](https://github.com/vim/vim/blob/master/runtime/spell/en.utf-8.spl) and
+ [here](https://github.com/vim/vim/blob/master/runtime/spell/en.utf-8.sug));
+- For Python plugins you need the `pynvim` module. "Virtual envs" are recommended. After activating the virtual env do `pip install pynvim` (in *both*). Edit your `init.vim` so that it contains the path to the env's Python executable:
+ ```vim
+ let g:python3_host_prog='C:/Users/foo/Envs/neovim3/Scripts/python.exe'
+ ```
+ - Run `:checkhealth` and read `:help provider-python`.
+- **init.vim ("vimrc"):** If you already have Vim installed you can copy `%userprofile%\_vimrc` to `%userprofile%\AppData\Local\nvim\init.vim` to use your Vim config with Neovim.
+
+
+## macOS / OS X
+
+### Pre-built archives
+
+The [Releases](https://github.com/neovim/neovim/releases) page provides pre-built binaries for macOS 10.15+.
+
+ curl -LO https://github.com/neovim/neovim/releases/download/nightly/nvim-macos.tar.gz
+ tar xzf nvim-macos.tar.gz
+ ./nvim-macos/bin/nvim
+
+### [Homebrew](https://brew.sh) on macOS or Linux
+
+ brew install neovim
+
+### [MacPorts](https://www.macports.org/)
+
+ sudo port selfupdate
+ sudo port install neovim
+
+## Linux
+
+### Pre-built archives
+
+The [Releases](https://github.com/neovim/neovim/releases) page provides pre-built binaries for Linux systems.
+
+```sh
+curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim-linux64.tar.gz
+sudo rm -rf /opt/nvim
+sudo tar -C /opt -xzf nvim-linux64.tar.gz
+```
+
+After this step add this to `~/.bashrc`:
+
+ export PATH="$PATH:/opt/nvim-linux64/bin"
+
+### AppImage ("universal" Linux package)
+
+The [Releases](https://github.com/neovim/neovim/releases) page provides an [AppImage](https://appimage.org) that runs on most Linux systems. No installation is needed, just download `nvim.appimage` and run it. (It might not work if your Linux distribution is more than 4 years old.)
+
+ curl -LO https://github.com/neovim/neovim/releases/latest/download/nvim.appimage
+ chmod u+x nvim.appimage
+ ./nvim.appimage
+
+To expose nvim globally:
+
+ mkdir -p /opt/nvim
+ mv nvim.appimage /opt/nvim/nvim
+
+And the following line to `~/.bashrc`:
+
+ export PATH="$PATH:/opt/nvim/"
+
+If the `./nvim.appimage` command fails, try:
+```sh
+./nvim.appimage --appimage-extract
+./squashfs-root/AppRun --version
+
+# Optional: exposing nvim globally.
+sudo mv squashfs-root /
+sudo ln -s /squashfs-root/AppRun /usr/bin/nvim
+nvim
+```
+
+### Arch Linux
+
+Neovim can be installed from the community repository:
+
+ sudo pacman -S neovim
+
+Alternatively, Neovim can be also installed using the PKGBUILD [`neovim-git`](https://aur.archlinux.org/packages/neovim-git), available on the [AUR](https://wiki.archlinux.org/index.php/Arch_User_Repository).
+
+Alternatively, Neovim Nightly builds can be also installed using the PKGBUILD [`neovim-nightly-bin`](https://aur.archlinux.org/packages/neovim-nightly-bin), available on the [AUR](https://wiki.archlinux.org/index.php/Arch_User_Repository).
+
+The Python module is available from the community repository:
+
+ sudo pacman -S python-pynvim
+
+Ruby modules (currently only supported in `neovim-git`) are available from the AUR as [`ruby-neovim`](https://aur.archlinux.org/packages/ruby-neovim).
+
+### CentOS 8 / RHEL 8
+
+Neovim is available through [EPEL (Extra Packages for Enterprise Linux)](https://fedoraproject.org/wiki/EPEL)
+
+ yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm
+ yum install -y neovim python3-neovim
+
+### Clear Linux OS
+
+Neovim is available through the [neovim bundle](https://github.com/clearlinux/clr-bundles/blob/master/bundles/neovim)
+
+ sudo swupd bundle-add neovim
+
+Python (`:python`) support is available if the [python-basic bundle](https://github.com/clearlinux/clr-bundles/blob/master/bundles/python-basic) is installed.
+
+ sudo swupd bundle-add python-basic
+
+### Debian
+
+Neovim is in [Debian](https://packages.debian.org/search?keywords=neovim).
+
+ sudo apt-get install neovim
+
+Python (`:python`) support is installable via the package manager on Debian unstable.
+
+ sudo apt-get install python3-neovim
+
+### Exherbo Linux
+
+Exhereses for scm and released versions are currently available in repository `::medvid`. Python client (with GTK+ GUI included) and Qt5 GUI are also available as suggestions:
+
+ cave resolve app-editors/neovim --take dev-python/neovim-python --take app-editors/neovim-qt
+
+### Fedora
+
+Neovim is in [Fedora](https://src.fedoraproject.org/rpms/neovim) starting with Fedora 25:
+
+ sudo dnf install -y neovim python3-neovim
+
+You can also get nightly builds of git master from the [Copr automated build system](https://copr.fedoraproject.org/coprs/agriffis/neovim-nightly/):
+
+ dnf copr enable agriffis/neovim-nightly
+ dnf install -y neovim python3-neovim
+
+See the [blog post](https://arongriffis.com/2019/03/02/neovim-nightly-builds) for information on how these are built.
+
+### Flatpak
+
+You can find Neovim on [Flathub](https://flathub.org/apps/details/io.neovim.nvim). Providing you have Flatpak [set up](https://flatpak.org/setup/):
+
+ flatpak install flathub io.neovim.nvim
+ flatpak run io.neovim.nvim
+
+You can add `/var/lib/flatpak/exports/bin` (or `~/.local/share/flatpak/exports/bin` if you used `--user`) to the `$PATH` and run it with `io.neovim.nvim`.
+
+Note that Flatpak'ed Neovim will look for `init.vim` in `~/.var/app/io.neovim.nvim/config/nvim` instead of `~/.config/nvim`.
+
+### Gentoo Linux
+
+An ebuild is available in Gentoo's official portage repository:
+
+ emerge -a app-editors/neovim
+
+### GNU Guix
+
+Neovim can be installed with:
+
+ guix install neovim
+
+### GoboLinux
+
+Neovim can be installed with:
+
+ sudo -H Compile NeoVim
+
+### Nix / NixOS
+
+Neovim can be installed with:
+
+ nix-env -iA nixpkgs.neovim
+
+Or alternatively, if you use flakes:
+
+ nix profile install nixpkgs#neovim
+
+### Mageia 7
+
+ urpmi neovim
+
+To install the Python modules:
+
+ urpmi python3-pynvim
+
+### makedeb Package Repository (MPR)
+
+Neovim is available inside the [MPR](https://mpr.makedeb.org/packages/neovim). You can install it with:
+
+ git clone https://mpr.makedeb.org/neovim
+ cd neovim/
+ makedeb -si
+
+### OpenSUSE
+
+Neovim can be installed with:
+
+ sudo zypper in neovim
+
+To install the Python modules:
+
+ sudo zypper in python-neovim python3-neovim
+
+### PLD Linux
+
+Neovim is in [PLD Linux](https://github.com/pld-linux/neovim):
+
+ poldek -u neovim
+ poldek -u python-neovim python3-neovim
+ poldek -u python-neovim-gui python3-neovim-gui
+
+### Slackware
+
+See [neovim on SlackBuilds](https://slackbuilds.org/apps/neovim/).
+
+### Source Mage
+
+Neovim can be installed using the Sorcery package manager:
+
+ cast neovim
+
+### Solus
+
+Neovim can be installed using the default package manager in Solus (eopkg):
+
+ sudo eopkg install neovim
+
+### Snap
+
+Neovim nightly and stable are available on the [snap store](https://snapcraft.io/nvim).
+
+**Stable Builds**
+
+```sh
+sudo snap install --beta nvim --classic
+```
+
+**Nightly Builds**
+
+```sh
+sudo snap install --edge nvim --classic
+```
+
+### Ubuntu
+As in Debian, Neovim is in [Ubuntu](https://packages.ubuntu.com/search?keywords=neovim).
+
+ sudo apt install neovim
+
+Python (`:python`) support seems to be automatically installed
+
+ sudo apt install python3-neovim
+
+Neovim has been added to a "Personal Package Archive" (PPA). This allows you to install it with `apt-get`. Follow the links to the PPAs to see which versions of Ubuntu are currently available via the PPA. Choose **stable** or **unstable**:
+
+- [https://launchpad.net/~neovim-ppa/+archive/ubuntu/**stable**](https://launchpad.net/~neovim-ppa/+archive/ubuntu/stable)
+- [https://launchpad.net/~neovim-ppa/+archive/ubuntu/**unstable**](https://launchpad.net/~neovim-ppa/+archive/ubuntu/unstable)
+
+**Important:** The Neovim team does not maintain the PPA packages. For problems or questions about the PPA specifically contact https://launchpad.net/~neovim-ppa.
+
+To be able to use **add-apt-repository** you may need to install software-properties-common:
+
+ sudo apt-get install software-properties-common
+
+If you're using an older version Ubuntu you must use:
+
+ sudo apt-get install python-software-properties
+
+Run the following commands:
+
+ sudo add-apt-repository ppa:neovim-ppa/stable
+ sudo apt-get update
+ sudo apt-get install neovim
+
+Prerequisites for the Python modules:
+
+ sudo apt-get install python-dev python-pip python3-dev python3-pip
+
+If you're using an older version Ubuntu you must use:
+
+ sudo apt-get install python-dev python-pip python3-dev
+ sudo apt-get install python3-setuptools
+ sudo easy_install3 pip
+
+### Void-Linux
+
+Neovim can be installed using the xbps package manager
+
+ sudo xbps-install -S neovim
+
+### Alpine Linux
+
+Neovim can be installed using the apk package manager
+
+ sudo apk add neovim
+
+## BSD
+
+### FreeBSD
+
+Neovim can be installed using [`pkg(8)`](https://www.freebsd.org/cgi/man.cgi?query=pkg&sektion=8&n=1):
+
+ pkg install neovim
+
+or [from the ports tree](https://www.freshports.org/editors/neovim/):
+
+ cd /usr/ports/editors/neovim/ && make install clean
+
+To install the pynvim Python modules using [`pkg(8)`](https://www.freebsd.org/cgi/man.cgi?query=pkg&sektion=8&n=1) run:
+
+ pkg install py36-pynvim
+
+### OpenBSD
+
+Neovim can be installed using [`pkg_add(1)`](https://man.openbsd.org/pkg_add):
+
+ pkg_add neovim
+
+or [from the ports tree](https://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/editors/neovim/):
+
+ cd /usr/ports/editors/neovim/ && make install
+
+## Android
+
+[Termux](https://github.com/termux/termux-app) offers a Neovim package.
+
+
+Install from source
+===================
+
+If a package is not provided for your platform, you can build Neovim from source. See [BUILD.md](./BUILD.md) for details. If you have the [prerequisites](./BUILD.md#build-prerequisites) then building is easy:
+
+ make CMAKE_BUILD_TYPE=Release
+ sudo make install
+
+For Unix-like systems this installs Neovim to `/usr/local`, while for Windows to `C:\Program Files`. Note, however, that this can complicate uninstallation. The following example avoids this by isolating an installation under `$HOME/neovim`:
+
+ rm -r build/ # clear the CMake cache
+ make CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=$HOME/neovim"
+ make install
+ export PATH="$HOME/neovim/bin:$PATH"
+
+## Uninstall
+
+There is a CMake target to _uninstall_ after `make install`:
+
+```sh
+sudo cmake --build build/ --target uninstall
+```
+
+Alternatively, just delete the `CMAKE_INSTALL_PREFIX` artifacts:
+
+```sh
+sudo rm /usr/local/bin/nvim
+sudo rm -r /usr/local/share/nvim/
+```
diff --git a/MAINTAIN.md b/MAINTAIN.md
index ff5f3fe5a1..3c21b13276 100644
--- a/MAINTAIN.md
+++ b/MAINTAIN.md
@@ -73,13 +73,17 @@ When a (non-experimental) feature is slated to be removed it should:
1. Be _soft_ deprecated in the _next_ release
- Use of the deprecated feature will still work.
- - This means deprecating via documentation and annotation (`@deprecated`) only.
+ - This means deprecating via documentation and annotation (`@deprecated`).
- Include a note in `news.txt` under `DEPRECATIONS`.
+ - For Lua features, use `vim.deprecate()`. The specified version is the
+ current minor version + 2. For example, if the current version is
+ `v0.10.0-dev-1957+gd676746c33` then use `0.12`.
+ - For Vimscript features, use `v:lua.vim.deprecate()`. Use the same version
+ as described for Lua features.
2. Be _hard_ deprecated in a following a release in which it was soft deprecated.
- - Use of the deprecated feature will still work but should issue a warning
- (typically via `vim.deprecate()` for Lua features).
- - Features implemented in Vimscript or in C will need bespoke implementations
- to communicate to users that the feature is deprecated
+ - Use of the deprecated feature will still work but should issue a warning.
+ - Features implemented in C will need bespoke implementations to communicate
+ to users that the feature is deprecated.
3. Be removed in a release following the release in which it was hard deprecated
- Usually this will be the next release, but it may be a later release if a
longer deprecation cycle is desired
@@ -93,7 +97,7 @@ Example:
┆ ┆ ┆
┆ Soft ┆ Hard ┆
┆ Deprecation ┆ Deprecation ┆
- ┆ Period ┆ Preiod ┆
+ ┆ Period ┆ Period ┆
────────────────────────────────────────────────────────────
Version: 0.10 0.11 0.12
────────────────────────────────────────────────────────────
@@ -113,6 +117,11 @@ should be stated explicitly and publicly.
Third-party dependencies
------------------------
+For some dependencies we maintain temporary "forks", which are simply private
+branches with a few extra patches, while we wait for the upstream project to
+merge the patches. This is done instead of maintaining the patches as (fragile)
+CMake `PATCH_COMMAND` steps.
+
These "bundled" dependencies can be updated by bumping their versions in `cmake.deps/deps.txt`.
Some can be auto-bumped by `scripts/bump_deps.lua`.
@@ -122,12 +131,13 @@ Some can be auto-bumped by `scripts/bump_deps.lua`.
* When bumping, also sync [our bundled documentation](https://github.com/neovim/neovim/blob/master/runtime/doc/luvref.txt) with [the upstream documentation](https://github.com/luvit/luv/blob/master/docs.md).
* [gettext](https://ftp.gnu.org/pub/gnu/gettext/)
* [libiconv](https://ftp.gnu.org/pub/gnu/libiconv)
-* [libtermkey](https://github.com/neovim/libtermkey)
* [libuv](https://github.com/libuv/libuv)
* [libvterm](http://www.leonerd.org.uk/code/libvterm/)
+ * Downloading from the original source is unreliable, so we use our [mirror](https://github.com/neovim/libvterm) instead.
* [lua-compat](https://github.com/keplerproject/lua-compat-5.3)
* [tree-sitter](https://github.com/tree-sitter/tree-sitter)
* [unibilium](https://github.com/neovim/unibilium)
+ * The original project [was abandoned](https://github.com/neovim/neovim/issues/10302), so the [neovim/unibilium](https://github.com/neovim/unibilium) fork is considered "upstream" and is maintained on the `master` branch.
* [treesitter parsers](https://github.com/neovim/neovim/blob/7e97c773e3ba78fcddbb2a0b9b0d572c8210c83e/cmake.deps/deps.txt#L47-L62)
### Vendored dependencies
@@ -146,14 +156,14 @@ These dependencies are "vendored" (inlined), we must update the sources manually
* Run `scripts/gen_lsp.lua` to update.
* `runtime/lua/vim/_meta/lpeg.lua`: LPeg definitions.
* Refer to [`LuaCATS/lpeg`](https://github.com/LuaCATS/lpeg) for updates.
+ * Update the git SHA revision from which the documentation was taken.
* `runtime/lua/vim/re.lua`: LPeg regex module.
* Vendored from LPeg. Needs to be updated when LPeg is updated.
+* `runtime/lua/vim/_meta/re.lua`: docs for LPeg regex module.
+ * Needs to be updated when LPeg is updated.
* `src/bit.c`: only for PUC lua: port of `require'bit'` from luajit https://bitop.luajit.org/
* `runtime/lua/coxpcall.lua`: coxpcall (only needed for PUC lua, builtin to luajit)
-
-### Forks
-
-We may maintain forks, if we are waiting on upstream changes: https://github.com/neovim/neovim/wiki/Deps
+* `src/termkey`: [libtermkey](https://github.com/neovim/libtermkey)
Non-technical dependencies
--------------------------
@@ -168,6 +178,22 @@ Non-technical dependencies
* pkgjson.org
* DNS for the above domains is managed in https://cloudflare.com (not the domain registrar)
+
+Refactoring
+-----------
+
+### Frozen legacy modules
+
+Refactoring Vim structurally and aesthetically is an important goal of Neovim.
+But there are some modules that should not be changed significantly, because
+they are maintained Vim, at present. Until someone takes "ownership" of these
+modules, the cost of any significant changes (including style or structural
+changes that re-arrange the code) to these modules outweighs the benefit. The
+modules are:
+
+- `regexp.c`
+- `indent_c.c`
+
Automation (CI)
---------------
@@ -199,6 +225,16 @@ https://github.com/neovim/neovim-backup
trying to produce images that work in the broadest number of environments,
and therefore want to use older releases.
+### Special labels
+
+Some github labels are used to trigger certain jobs:
+
+* `backport release-x.y` - backport to release branch
+* `ci:s390x` - enable s390x CI
+* `ci:skip-news` - skip news.yml workflows
+* `needs:response` - close PR after a certain amount of time if author doesn't
+ respond
+
See also
--------
diff --git a/Makefile b/Makefile
index 3781d06a6c..c44be8f8c7 100644
--- a/Makefile
+++ b/Makefile
@@ -9,8 +9,7 @@ filter-true = $(strip $(filter-out 1 on ON true TRUE,$1))
all: nvim
-CMAKE_PRG ?= $(shell (command -v cmake3 || echo cmake))
-CMAKE_BUILD_TYPE ?= Debug
+CMAKE ?= $(shell (command -v cmake3 || echo cmake))
CMAKE_FLAGS := -DCMAKE_BUILD_TYPE=$(CMAKE_BUILD_TYPE)
# Extra CMake flags which extend the default set
CMAKE_EXTRA_FLAGS ?=
@@ -28,7 +27,7 @@ override CMAKE_EXTRA_FLAGS += -DCMAKE_INSTALL_PREFIX=$(CMAKE_INSTALL_PREFIX)
checkprefix:
@if [ -f build/.ran-cmake ]; then \
- cached_prefix=$(shell $(CMAKE_PRG) -L -N build | 2>/dev/null grep 'CMAKE_INSTALL_PREFIX' | cut -d '=' -f2); \
+ cached_prefix=$(shell $(CMAKE) -L -N build | 2>/dev/null grep 'CMAKE_INSTALL_PREFIX' | cut -d '=' -f2); \
if ! [ "$(CMAKE_INSTALL_PREFIX)" = "$$cached_prefix" ]; then \
printf "Re-running CMake: CMAKE_INSTALL_PREFIX '$(CMAKE_INSTALL_PREFIX)' does not match cached value '%s'.\n" "$$cached_prefix"; \
$(RM) build/.ran-cmake; \
@@ -53,17 +52,6 @@ ifeq (,$(BUILD_TOOL))
endif
endif
-# Only need to handle Ninja here. Make will inherit the VERBOSE variable, and the -j, -l, and -n flags.
-ifeq ($(CMAKE_GENERATOR),Ninja)
- ifneq ($(VERBOSE),)
- BUILD_TOOL += -v
- endif
- BUILD_TOOL += $(shell printf '%s' '$(MAKEFLAGS)' | grep -o -- ' *-[jl][0-9]\+ *')
- ifeq (n,$(findstring n,$(firstword -$(MAKEFLAGS))))
- BUILD_TOOL += -n
- endif
-endif
-
DEPS_CMAKE_FLAGS ?=
USE_BUNDLED ?=
@@ -81,155 +69,73 @@ endif
SINGLE_MAKE = export MAKEFLAGS= ; $(MAKE)
nvim: build/.ran-cmake deps
- +$(BUILD_TOOL) -C build
+ $(BUILD_TOOL) -C build
libnvim: build/.ran-cmake deps
- +$(BUILD_TOOL) -C build libnvim
+ $(BUILD_TOOL) -C build libnvim
cmake:
touch CMakeLists.txt
$(MAKE) build/.ran-cmake
build/.ran-cmake: | deps
- cd build && $(CMAKE_PRG) -G '$(CMAKE_GENERATOR)' $(CMAKE_FLAGS) $(CMAKE_EXTRA_FLAGS) $(MAKEFILE_DIR)
+ $(CMAKE) -B build -G '$(CMAKE_GENERATOR)' $(CMAKE_FLAGS) $(CMAKE_EXTRA_FLAGS) $(MAKEFILE_DIR)
touch $@
deps: | build/.ran-deps-cmake
ifeq ($(call filter-true,$(USE_BUNDLED)),)
- +$(BUILD_TOOL) -C $(DEPS_BUILD_DIR)
+ $(BUILD_TOOL) -C $(DEPS_BUILD_DIR)
endif
ifeq ($(call filter-true,$(USE_BUNDLED)),)
$(DEPS_BUILD_DIR):
mkdir -p "$@"
build/.ran-deps-cmake:: $(DEPS_BUILD_DIR)
- cd $(DEPS_BUILD_DIR) && \
- $(CMAKE_PRG) -G '$(CMAKE_GENERATOR)' $(BUNDLED_CMAKE_FLAG) $(BUNDLED_LUA_CMAKE_FLAG) \
- $(DEPS_CMAKE_FLAGS) $(MAKEFILE_DIR)/cmake.deps
+ $(CMAKE) -S $(MAKEFILE_DIR)/cmake.deps -B $(DEPS_BUILD_DIR) -G '$(CMAKE_GENERATOR)' \
+ $(BUNDLED_CMAKE_FLAG) $(BUNDLED_LUA_CMAKE_FLAG) $(DEPS_CMAKE_FLAGS)
endif
build/.ran-deps-cmake::
mkdir -p build
touch $@
# TODO: cmake 3.2+ add_custom_target() has a USES_TERMINAL flag.
-oldtest: | nvim build/runtime/doc/tags
- +$(SINGLE_MAKE) -C test/old/testdir clean
+oldtest: | nvim
+ $(SINGLE_MAKE) -C test/old/testdir clean
ifeq ($(strip $(TEST_FILE)),)
- +$(SINGLE_MAKE) -C test/old/testdir NVIM_PRG=$(NVIM_PRG) $(MAKEOVERRIDES)
+ $(SINGLE_MAKE) -C test/old/testdir NVIM_PRG=$(NVIM_PRG) $(MAKEOVERRIDES)
else
@# Handle TEST_FILE=test_foo{,.res,.vim}.
- +$(SINGLE_MAKE) -C test/old/testdir NVIM_PRG=$(NVIM_PRG) SCRIPTS= $(MAKEOVERRIDES) $(patsubst %.vim,%,$(patsubst %.res,%,$(TEST_FILE)))
+ $(SINGLE_MAKE) -C test/old/testdir NVIM_PRG=$(NVIM_PRG) SCRIPTS= $(MAKEOVERRIDES) $(patsubst %.vim,%,$(patsubst %.res,%,$(TEST_FILE)))
endif
# Build oldtest by specifying the relative .vim filename.
.PHONY: phony_force
test/old/testdir/%.vim: phony_force nvim
- +$(SINGLE_MAKE) -C test/old/testdir NVIM_PRG=$(NVIM_PRG) SCRIPTS= $(MAKEOVERRIDES) $(patsubst test/old/testdir/%.vim,%,$@)
+ $(SINGLE_MAKE) -C test/old/testdir NVIM_PRG=$(NVIM_PRG) SCRIPTS= $(MAKEOVERRIDES) $(patsubst test/old/testdir/%.vim,%,$@)
functionaltest-lua: | nvim
$(BUILD_TOOL) -C build functionaltest
FORMAT=formatc formatlua format
-LINT=lintlua lintsh lintc clang-analyzer lintcommit lint
+LINT=lintlua lintsh lintc clang-analyzer lintcommit lintdoc lint
TEST=functionaltest unittest
generated-sources benchmark $(FORMAT) $(LINT) $(TEST) doc: | build/.ran-cmake
- $(CMAKE_PRG) --build build --target $@
+ $(CMAKE) --build build --target $@
test: $(TEST)
-# The ignored header files should be synced with the `check_includes_ignore`
-# array in src/clint.py
iwyu: build/.ran-cmake
- cmake --preset iwyu
- cmake --build build > build/iwyu.log
- iwyu-fix-includes --only_re="src/nvim" --ignore_re="(src/nvim/eval/encode.c|src/nvim/auto/|src/nvim/os/lang.c|src/nvim/map.c\
- |src/nvim/api/extmark.h\
- |src/nvim/api/private/dispatch.h\
- |src/nvim/api/private/helpers.h\
- |src/nvim/api/private/validate.h\
- |src/nvim/api/ui.h\
- |src/nvim/ascii_defs.h\
- |src/nvim/assert_defs.h\
- |src/nvim/autocmd.h\
- |src/nvim/autocmd_defs.h\
- |src/nvim/buffer.h\
- |src/nvim/buffer_defs.h\
- |src/nvim/channel.h\
- |src/nvim/charset.h\
- |src/nvim/cmdexpand.h\
- |src/nvim/cmdhist.h\
- |src/nvim/decoration.h\
- |src/nvim/diff.h\
- |src/nvim/drawline.h\
- |src/nvim/drawscreen.h\
- |src/nvim/eval.h\
- |src/nvim/eval/encode.h\
- |src/nvim/eval/typval.h\
- |src/nvim/eval/typval_defs.h\
- |src/nvim/eval/userfunc.h\
- |src/nvim/eval/window.h\
- |src/nvim/event/libuv_process.h\
- |src/nvim/event/loop.h\
- |src/nvim/event/multiqueue.h\
- |src/nvim/event/process.h\
- |src/nvim/event/rstream.h\
- |src/nvim/event/signal.h\
- |src/nvim/event/socket.h\
- |src/nvim/event/stream.h\
- |src/nvim/event/time.h\
- |src/nvim/event/wstream.h\
- |src/nvim/ex_cmds.h\
- |src/nvim/ex_cmds_defs.h\
- |src/nvim/ex_docmd.h\
- |src/nvim/extmark.h\
- |src/nvim/file_search.h\
- |src/nvim/fileio.h\
- |src/nvim/fold.h\
- |src/nvim/garray.h\
- |src/nvim/getchar.h\
- |src/nvim/globals.h\
- |src/nvim/grid.h\
- |src/nvim/highlight.h\
- |src/nvim/highlight_group.h\
- |src/nvim/input.h\
- |src/nvim/insexpand.h\
- |src/nvim/keycodes.h\
- |src/nvim/log.h\
- |src/nvim/lua/executor.h\
- |src/nvim/main.h\
- |src/nvim/mark.h\
- |src/nvim/mouse.h\
- |src/nvim/move.h\
- |src/nvim/msgpack_rpc/channel.h\
- |src/nvim/msgpack_rpc/channel_defs.h\
- |src/nvim/msgpack_rpc/helpers.h\
- |src/nvim/msgpack_rpc/unpacker.h\
- |src/nvim/option.h\
- |src/nvim/os/fileio.h\
- |src/nvim/os/input.h\
- |src/nvim/os/pty_conpty_win.h\
- |src/nvim/os/pty_process_unix.h\
- |src/nvim/os/pty_process_win.h\
- |src/nvim/path.h\
- |src/nvim/plines.h\
- |src/nvim/popupmenu.h\
- |src/nvim/search.h\
- |src/nvim/spell.h\
- |src/nvim/syntax.h\
- |src/nvim/textobject.h\
- |src/nvim/tui/input.h\
- |src/nvim/tui/tui.h\
- |src/nvim/ui.h\
- |src/nvim/ui_client.h\
- |src/nvim/ui_compositor.h\
- |src/nvim/viml/parser/expressions.h\
- |src/nvim/viml/parser/parser.h\
- |src/nvim/window.h\
+ $(CMAKE) --preset iwyu
+ $(CMAKE) --build build > build/iwyu.log
+ iwyu-fix-includes --only_re="src/nvim" --ignore_re="(src/nvim/eval/encode.c\
+ |src/nvim/auto/\
+ |src/nvim/os/lang.c\
+ |src/nvim/map.c\
)" --nosafe_headers < build/iwyu.log
- cmake -B build -U ENABLE_IWYU
- cmake --build build
+ $(CMAKE) -B build -U ENABLE_IWYU
+ $(CMAKE) --build build
clean:
- +test -d build && $(BUILD_TOOL) -C build clean || true
+ test -d build && $(BUILD_TOOL) -C build clean || true
$(MAKE) -C test/old/testdir clean
$(MAKE) -C runtime/indent clean
@@ -238,7 +144,7 @@ distclean:
$(MAKE) clean
install: checkprefix nvim
- +$(BUILD_TOOL) -C build install
+ $(BUILD_TOOL) -C build install
appimage:
bash scripts/genappimage.sh
diff --git a/README.md b/README.md
index be8b3178f3..71d611b582 100644
--- a/README.md
+++ b/README.md
@@ -16,7 +16,7 @@ Neovim is a project that seeks to aggressively refactor [Vim](https://www.vim.or
- Simplify maintenance and encourage [contributions](CONTRIBUTING.md)
- Split the work between multiple developers
- Enable [advanced UIs] without modifications to the core
-- Maximize [extensibility](https://github.com/neovim/neovim/wiki/Plugin-UI-architecture)
+- Maximize [extensibility](https://neovim.io/doc/user/ui.html)
See the [Introduction](https://github.com/neovim/neovim/wiki/Introduction) wiki page and [Roadmap]
for more information.
@@ -47,7 +47,7 @@ Pre-built packages for Windows, macOS, and Linux are found on the
Install from source
-------------------
-See the [Building Neovim](https://github.com/neovim/neovim/wiki/Building-Neovim) wiki page and [supported platforms](https://neovim.io/doc/user/support.html#supported-platforms) for details.
+See [BUILD.md](./BUILD.md) and [supported platforms](https://neovim.io/doc/user/support.html#supported-platforms) for details.
The build is CMake-based, but a Makefile is provided as a convenience.
After installing the dependencies, run the following command.
@@ -113,7 +113,7 @@ Apache 2.0 license, except for contributions copied from Vim (identified by the
[nvim-news]: https://neovim.io/doc/user/news.html
[Roadmap]: https://neovim.io/roadmap/
[advanced UIs]: https://github.com/neovim/neovim/wiki/Related-projects#gui
-[Managed packages]: https://github.com/neovim/neovim/wiki/Installing-Neovim#install-from-package
+[Managed packages]: ./INSTALL.md#install-from-package
[Debian]: https://packages.debian.org/testing/neovim
[Ubuntu]: https://packages.ubuntu.com/search?keywords=neovim
[Fedora]: https://packages.fedoraproject.org/pkgs/neovim/neovim/
diff --git a/cmake.config/CMakeLists.txt b/cmake.config/CMakeLists.txt
index ed405c602e..f3cc803cf5 100644
--- a/cmake.config/CMakeLists.txt
+++ b/cmake.config/CMakeLists.txt
@@ -139,17 +139,44 @@ configure_file (
"${PROJECT_BINARY_DIR}/cmake.config/auto/config.h"
)
-# Prevent double space in --version output if CMAKE_C_FLAGS is empty
-set(C_FLAGS_VERSION_OUTPUT ${CMAKE_C_FLAGS})
-if(C_FLAGS_VERSION_OUTPUT)
- string(PREPEND C_FLAGS_VERSION_OUTPUT " ")
-endif()
+set(VERSION_STRING "${CMAKE_C_COMPILER} ${CMAKE_C_FLAGS} ")
-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()
+foreach(BUILD_TYPE Debug Release RelWithDebInfo MinSizeRel)
+ string(TOUPPER ${BUILD_TYPE} BUILD_TYPE_UPPER)
+ set(GEN_CONFIG "$<CONFIG:${BUILD_TYPE}>")
+
+ set(GEN_RHS "${CMAKE_C_FLAGS_${BUILD_TYPE_UPPER}} ")
+ string(APPEND VERSION_STRING "$<${GEN_CONFIG}:${GEN_RHS}>")
+
+ set(GEN_RHS "$<$<BOOL:$<TARGET_PROPERTY:nvim_bin,INTERPROCEDURAL_OPTIMIZATION_${BUILD_TYPE_UPPER}>>:${CMAKE_C_COMPILE_OPTIONS_IPO}>")
+ string(APPEND VERSION_STRING "$<${GEN_CONFIG}:${GEN_RHS}>")
+endforeach()
+
+string(APPEND VERSION_STRING " ")
+
+function(append_target_expression)
+ cmake_parse_arguments(ARG
+ ""
+ "PREFIX;PROPERTY"
+ ""
+ ${ARGN})
+
+ set(TARGET_EXPRESSION "$<TARGET_PROPERTY:nvim_bin,${ARG_PROPERTY}>")
+ if(${CMAKE_VERSION} VERSION_GREATER_EQUAL 3.15)
+ set(TARGET_EXPRESSION "$<REMOVE_DUPLICATES:${TARGET_EXPRESSION}>")
+ endif()
+ set(TARGET_EXPRESSION "${ARG_PREFIX}$<JOIN:${TARGET_EXPRESSION}, ${ARG_PREFIX}>")
+
+ set(VERSION_STRING "${VERSION_STRING} ${TARGET_EXPRESSION} " PARENT_SCOPE)
+endfunction()
+append_target_expression(PROPERTY COMPILE_OPTIONS)
+append_target_expression(PROPERTY LINK_OPTIONS)
+append_target_expression(PREFIX "-D" PROPERTY COMPILE_DEFINITIONS)
+append_target_expression(PREFIX "-I" PROPERTY INCLUDE_DIRECTORIES)
+string(REPLACE ";" " " VERSION_STRING "${VERSION_STRING}")
+string(REPLACE " " " " VERSION_STRING "${VERSION_STRING}")
+
+configure_file(versiondef.h.in auto/versiondef.h.gen)
file(GENERATE
OUTPUT "${PROJECT_BINARY_DIR}/cmake.config/auto/versiondef-$<CONFIG>.h"
diff --git a/cmake.config/config.h.in b/cmake.config/config.h.in
index fb12a7c558..47fbb5bafe 100644
--- a/cmake.config/config.h.in
+++ b/cmake.config/config.h.in
@@ -1,5 +1,4 @@
-#ifndef AUTO_CONFIG_H
-#define AUTO_CONFIG_H
+#pragma once
#cmakedefine SIZEOF_INT @SIZEOF_INT@
#cmakedefine SIZEOF_INTMAX_T @SIZEOF_INTMAX_T@
@@ -53,5 +52,3 @@
#cmakedefine HAVE_EXECINFO_BACKTRACE
#cmakedefine HAVE_BUILTIN_ADD_OVERFLOW
#cmakedefine HAVE_WIMPLICIT_FALLTHROUGH_FLAG
-
-#endif // AUTO_CONFIG_H
diff --git a/cmake.config/iwyu/mapping.imp b/cmake.config/iwyu/mapping.imp
index 4056070958..104fe7c4f9 100644
--- a/cmake.config/iwyu/mapping.imp
+++ b/cmake.config/iwyu/mapping.imp
@@ -22,8 +22,8 @@
{ symbol: [ "MIN", private, '"nvim/macros_defs.h"', public ] },
{ symbol: [ "extern_proc", private, '<uv.h>', public ] },
{ symbol: [ "iovec", private, '<sys/uio.h>', public ] },
+ { symbol: [ "ssize_t", private, '<uv.h>', public ] },
- { include: [ '"keysets_defs.generated.h"', private, '"nvim/api/private/dispatch.h"', public ] },
{ include: [ '<uv/unix.h>', private, '<uv.h>', public ] },
]
diff --git a/cmake.config/iwyu/posix.imp b/cmake.config/iwyu/posix.imp
index 2eabd3063b..c787c9a165 100644
--- a/cmake.config/iwyu/posix.imp
+++ b/cmake.config/iwyu/posix.imp
@@ -13,20 +13,20 @@
{ include: [ '<bits/termios-c_cflag.h>', private, '<termios.h>', public ] },
{ include: [ '<bits/termios-c_iflag.h>', private, '<termios.h>', public ] },
{ include: [ '<bits/termios-c_oflag.h>', private, '<termios.h>', public ] },
- { include: [ '<sys/unistd.h>', private, '<unistd.h>', public ] },
+ { include: [ '<sys/ttycom.h>', private, '<sys/ioctl.h>', public ] },
+ { include: [ '<sys/unistd.h>', private, '<unistd.h>', private ] },
{ symbol: ["SOCK_STREAM", private, "<sys/socket.h>", public ] },
{ symbol: ["SSIZE_MAX", private, "<limits.h>", public ] },
{ symbol: ["S_IREAD", private, "<sys/stat.h>", public ] },
{ symbol: ["S_IWRITE", private, "<sys/stat.h>", public ] },
- { symbol: ["_POSIX_VDISABLE", private, "<unistd.h>", public ] },
+ { symbol: ["_POSIX_VDISABLE", private, "<unistd.h>", private ] },
{ symbol: ["flock", private, "<sys/file.h>", public ] },
{ symbol: ["iovec", private, "<sys/uio.h>", public ] },
{ symbol: ["mode_t", private, "<sys/types.h>", public ] },
{ symbol: ["ntohs", private, "<arpa/inet.h>", public ] },
{ symbol: ["pthread_sigmask", private, "<signal.h>", public ] },
{ symbol: ["sigset_t", private, "<signal.h>", public ] },
- { symbol: ["ssize_t", private, "<sys/types.h>", public ] },
{ symbol: ["uid_t", private, "<sys/types.h>", public ] },
]
diff --git a/cmake.config/versiondef.h.in b/cmake.config/versiondef.h.in
index bda21b27ec..9771e0d148 100644
--- a/cmake.config/versiondef.h.in
+++ b/cmake.config/versiondef.h.in
@@ -11,11 +11,7 @@
# 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}${C_FLAGS_VERSION_OUTPUT} $<$<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_CFLAGS "${VERSION_STRING}"
#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
deleted file mode 100644
index 4e21e0c7be..0000000000
--- a/cmake.config/versiondef_old.h.in
+++ /dev/null
@@ -1,21 +0,0 @@
-#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}${C_FLAGS_VERSION_OUTPUT} $<$<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 aa4a34709a..e37b606bd9 100644
--- a/cmake.deps/CMakeLists.txt
+++ b/cmake.deps/CMakeLists.txt
@@ -1,5 +1,5 @@
# This is not meant to be included by the top-level.
-cmake_minimum_required (VERSION 3.10)
+cmake_minimum_required (VERSION 3.13)
project(NVIM_DEPS C)
if(POLICY CMP0135)
@@ -17,7 +17,7 @@ include(Deps)
include(Find)
include(Util)
-set_default_buildtype()
+set_default_buildtype(Release)
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(NOT isMultiConfig)
list(APPEND DEPS_CMAKE_ARGS -D CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE})
@@ -34,19 +34,17 @@ set(DEPS_INCLUDE_FLAGS "-I${DEPS_INSTALL_DIR}/include -I${DEPS_INSTALL_DIR}/incl
option(USE_BUNDLED "Use bundled dependencies." ON)
-option(USE_BUNDLED_UNIBILIUM "Use the bundled unibilium." ${USE_BUNDLED})
-option(USE_BUNDLED_LIBTERMKEY "Use the bundled libtermkey." ${USE_BUNDLED})
-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_LUV "Use the bundled version of luv." ${USE_BUNDLED})
+option(USE_BUNDLED_LIBVTERM "Use the bundled libvterm." ${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
-# build it unless explicitly requested
+# PUC Lua is only used for tests, unless explicitly requested.
option(USE_BUNDLED_LUA "Use the bundled version of lua." OFF)
-option(USE_BUNDLED_TS_PARSERS "Use the bundled treesitter parsers." ${USE_BUNDLED})
+option(USE_BUNDLED_LUAJIT "Use the bundled version of luajit." ${USE_BUNDLED})
+option(USE_BUNDLED_LUV "Use the bundled version of luv." ${USE_BUNDLED})
+option(USE_BUNDLED_MSGPACK "Use the bundled msgpack." ${USE_BUNDLED})
option(USE_BUNDLED_TS "Use the bundled treesitter runtime." ${USE_BUNDLED})
+option(USE_BUNDLED_TS_PARSERS "Use the bundled treesitter parsers." ${USE_BUNDLED})
+option(USE_BUNDLED_UNIBILIUM "Use the bundled unibilium." ${USE_BUNDLED})
if(USE_BUNDLED AND MSVC)
option(USE_BUNDLED_GETTEXT "Use the bundled version of gettext." ON)
@@ -89,15 +87,26 @@ foreach(dep ${DEPENDENCIES})
endif()
endforeach()
-if(USE_BUNDLED_UNIBILIUM)
- include(BuildUnibilium)
+if(USE_BUNDLED_LUAJIT)
+ set(LUA_ENGINE LuaJit)
+elseif(USE_BUNDLED_LUA)
+ set(LUA_ENGINE Lua)
+else()
+ find_package(Luajit)
+ find_package(Lua 5.1 EXACT)
+ if(LUAJIT_FOUND)
+ set(LUA_ENGINE LuaJit)
+ string(APPEND DEPS_INCLUDE_FLAGS " -I${LUAJIT_INCLUDE_DIR}")
+ elseif(LUA_FOUND)
+ set(LUA_ENGINE Lua)
+ string(APPEND DEPS_INCLUDE_FLAGS " -I${LUA_INCLUDE_DIR}")
+ else()
+ message(FATAL_ERROR "Could not find system lua or luajit")
+ endif()
endif()
-if(USE_BUNDLED_LIBTERMKEY)
- include(BuildLibtermkey)
- if(USE_BUNDLED_UNIBILIUM)
- add_dependencies(libtermkey unibilium)
- endif()
+if(USE_BUNDLED_UNIBILIUM)
+ include(BuildUnibilium)
endif()
if(USE_BUNDLED_LIBVTERM)
diff --git a/cmake.deps/cmake/BuildLibtermkey.cmake b/cmake.deps/cmake/BuildLibtermkey.cmake
deleted file mode 100644
index 185b276def..0000000000
--- a/cmake.deps/cmake/BuildLibtermkey.cmake
+++ /dev/null
@@ -1,13 +0,0 @@
-ExternalProject_Add(libtermkey
- URL ${LIBTERMKEY_URL}
- URL_HASH SHA256=${LIBTERMKEY_SHA256}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/libtermkey
- PATCH_COMMAND ${CMAKE_COMMAND} -E copy
- ${CMAKE_CURRENT_SOURCE_DIR}/cmake/LibtermkeyCMakeLists.txt
- ${DEPS_BUILD_DIR}/src/libtermkey/CMakeLists.txt
- CMAKE_ARGS ${DEPS_CMAKE_ARGS}
- -D CMAKE_SHARED_LIBRARY_LINK_C_FLAGS="" # Hack to avoid -rdynamic in Mingw
- -D UNIBILIUM_INCLUDE_DIRS=${DEPS_INSTALL_DIR}/include
- -D UNIBILIUM_LIBRARIES=${DEPS_LIB_DIR}/${CMAKE_STATIC_LIBRARY_PREFIX}unibilium${CMAKE_STATIC_LIBRARY_SUFFIX}
- CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS}
- ${EXTERNALPROJECT_OPTIONS})
diff --git a/cmake.deps/cmake/BuildLpeg.cmake b/cmake.deps/cmake/BuildLpeg.cmake
index bba23fe42b..b65baf4c0f 100644
--- a/cmake.deps/cmake/BuildLpeg.cmake
+++ b/cmake.deps/cmake/BuildLpeg.cmake
@@ -1,19 +1,3 @@
-set(LPEG_INCLUDE_FLAGS ${DEPS_INCLUDE_FLAGS})
-
-if(NOT USE_BUNDLED_LUAJIT AND NOT USE_BUNDLED_LUA)
- find_package(Luajit)
- if(LUAJIT_FOUND)
- string(CONCAT LPEG_INCLUDE_FLAGS ${DEPS_INCLUDE_FLAGS} " -I${LUAJIT_INCLUDE_DIR}")
- else()
- find_package(Lua 5.1 EXACT)
- if(LUA_FOUND)
- string(CONCAT LPEG_INCLUDE_FLAGS ${DEPS_INCLUDE_FLAGS} " -I${LUA_INCLUDE_DIR}")
- endif()
- endif()
-endif()
-
-list(APPEND LPEG_CMAKE_ARGS -DCMAKE_C_FLAGS=${LPEG_INCLUDE_FLAGS})
-
ExternalProject_Add(lpeg
URL ${LPEG_URL}
URL_HASH SHA256=${LPEG_SHA256}
@@ -21,7 +5,7 @@ ExternalProject_Add(lpeg
PATCH_COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/cmake/LpegCMakeLists.txt
${DEPS_BUILD_DIR}/src/lpeg/CMakeLists.txt
- CMAKE_ARGS ${DEPS_CMAKE_ARGS} ${LPEG_CMAKE_ARGS}
+ CMAKE_ARGS ${DEPS_CMAKE_ARGS} -DCMAKE_C_FLAGS=${DEPS_INCLUDE_FLAGS}
CMAKE_CACHE_ARGS ${DEPS_CMAKE_CACHE_ARGS}
${EXTERNALPROJECT_OPTIONS})
diff --git a/cmake.deps/cmake/BuildLuajit.cmake b/cmake.deps/cmake/BuildLuajit.cmake
index aa4c8e9293..81fa6446c4 100644
--- a/cmake.deps/cmake/BuildLuajit.cmake
+++ b/cmake.deps/cmake/BuildLuajit.cmake
@@ -7,10 +7,6 @@ function(BuildLuajit)
"TARGET"
"CONFIGURE_COMMAND;BUILD_COMMAND;INSTALL_COMMAND;DEPENDS"
${ARGN})
- if(NOT _luajit_CONFIGURE_COMMAND AND NOT _luajit_BUILD_COMMAND
- AND NOT _luajit_INSTALL_COMMAND)
- message(FATAL_ERROR "Must pass at least one of CONFIGURE_COMMAND, BUILD_COMMAND, INSTALL_COMMAND")
- endif()
if(NOT _luajit_TARGET)
set(_luajit_TARGET "luajit")
endif()
@@ -18,7 +14,7 @@ function(BuildLuajit)
ExternalProject_Add(${_luajit_TARGET}
URL ${LUAJIT_URL}
URL_HASH SHA256=${LUAJIT_SHA256}
- DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/luajit
+ DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/${_luajit_TARGET}
CONFIGURE_COMMAND "${_luajit_CONFIGURE_COMMAND}"
BUILD_IN_SOURCE 1
BUILD_COMMAND "${_luajit_BUILD_COMMAND}"
diff --git a/cmake.deps/cmake/BuildLuv.cmake b/cmake.deps/cmake/BuildLuv.cmake
index 004fea7790..9830ea717a 100644
--- a/cmake.deps/cmake/BuildLuv.cmake
+++ b/cmake.deps/cmake/BuildLuv.cmake
@@ -5,18 +5,7 @@ set(LUV_CMAKE_ARGS
-D BUILD_STATIC_LIBS=ON
-D BUILD_MODULE=OFF)
-if(USE_BUNDLED_LUAJIT)
- list(APPEND LUV_CMAKE_ARGS -D WITH_LUA_ENGINE=LuaJit)
-elseif(USE_BUNDLED_LUA)
- list(APPEND LUV_CMAKE_ARGS -D WITH_LUA_ENGINE=Lua)
-else()
- find_package(Luajit)
- if(LUAJIT_FOUND)
- list(APPEND LUV_CMAKE_ARGS -D WITH_LUA_ENGINE=LuaJit)
- else()
- list(APPEND LUV_CMAKE_ARGS -D WITH_LUA_ENGINE=Lua)
- endif()
-endif()
+list(APPEND LUV_CMAKE_ARGS -D WITH_LUA_ENGINE=${LUA_ENGINE})
if(USE_BUNDLED_LIBUV)
list(APPEND LUV_CMAKE_ARGS -D CMAKE_PREFIX_PATH=${DEPS_INSTALL_DIR})
diff --git a/cmake.deps/cmake/BuildTreesitter.cmake b/cmake.deps/cmake/BuildTreesitter.cmake
index c17773ae9d..cd27a13ee3 100644
--- a/cmake.deps/cmake/BuildTreesitter.cmake
+++ b/cmake.deps/cmake/BuildTreesitter.cmake
@@ -2,7 +2,6 @@ ExternalProject_Add(treesitter
URL ${TREESITTER_URL}
URL_HASH SHA256=${TREESITTER_SHA256}
DOWNLOAD_DIR ${DEPS_DOWNLOAD_DIR}/treesitter
- INSTALL_DIR ${DEPS_INSTALL_DIR}
PATCH_COMMAND ${CMAKE_COMMAND} -E copy
${CMAKE_CURRENT_SOURCE_DIR}/cmake/TreesitterCMakeLists.txt
${DEPS_BUILD_DIR}/src/treesitter/CMakeLists.txt
diff --git a/cmake.deps/cmake/GettextCMakeLists.txt b/cmake.deps/cmake/GettextCMakeLists.txt
index e40a73d0c2..16fce4485f 100644
--- a/cmake.deps/cmake/GettextCMakeLists.txt
+++ b/cmake.deps/cmake/GettextCMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.13)
# Can be removed once minimum version is at least 3.15
if(POLICY CMP0092)
diff --git a/cmake.deps/cmake/LibiconvCMakeLists.txt b/cmake.deps/cmake/LibiconvCMakeLists.txt
index ec80c93e71..220e3e07cb 100644
--- a/cmake.deps/cmake/LibiconvCMakeLists.txt
+++ b/cmake.deps/cmake/LibiconvCMakeLists.txt
@@ -1,5 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
-
+cmake_minimum_required(VERSION 3.13)
# Can be removed once minimum version is at least 3.15
if(POLICY CMP0092)
cmake_policy(SET CMP0092 NEW)
diff --git a/cmake.deps/cmake/LibtermkeyCMakeLists.txt b/cmake.deps/cmake/LibtermkeyCMakeLists.txt
deleted file mode 100644
index 24d67a7ba5..0000000000
--- a/cmake.deps/cmake/LibtermkeyCMakeLists.txt
+++ /dev/null
@@ -1,37 +0,0 @@
-cmake_minimum_required(VERSION 3.10)
-# Can be removed once minimum version is at least 3.15
-if(POLICY CMP0092)
- cmake_policy(SET CMP0092 NEW)
-endif()
-project(libtermkey C)
-
-add_compile_options(-w)
-
-if(EXISTS ${PROJECT_SOURCE_DIR}/termkey.h.in)
- file(STRINGS Makefile TERMKEY_VERSION_MAJOR REGEX "VERSION_MAJOR")
- string(REGEX MATCH "[0-9]+" TERMKEY_VERSION_MAJOR ${TERMKEY_VERSION_MAJOR})
-
- file(STRINGS Makefile TERMKEY_VERSION_MINOR REGEX "VERSION_MINOR")
- string(REGEX MATCH "[0-9]+" TERMKEY_VERSION_MINOR ${TERMKEY_VERSION_MINOR})
-
- file(READ termkey.h.in TERMKEY_TEXT)
- string(REPLACE "@@VERSION_MAJOR@@" "${TERMKEY_VERSION_MAJOR}" TERMKEY_TEXT "${TERMKEY_TEXT}")
- string(REPLACE "@@VERSION_MINOR@@" "${TERMKEY_VERSION_MINOR}" TERMKEY_TEXT "${TERMKEY_TEXT}")
- file(WRITE termkey.h "${TERMKEY_TEXT}")
-endif()
-
-add_library(termkey termkey.c driver-csi.c driver-ti.c)
-
-target_compile_definitions(termkey PRIVATE HAVE_UNIBILIUM)
-target_include_directories(termkey PRIVATE SYSTEM ${UNIBILIUM_INCLUDE_DIRS})
-
-set_target_properties(termkey PROPERTIES
- PUBLIC_HEADER ${PROJECT_SOURCE_DIR}/termkey.h)
-target_link_libraries(termkey PRIVATE ${UNIBILIUM_LIBRARIES})
-
-include(GNUInstallDirs)
-install(TARGETS termkey
- ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
- PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
-
-# vim: set ft=cmake:
diff --git a/cmake.deps/cmake/LibvtermCMakeLists.txt b/cmake.deps/cmake/LibvtermCMakeLists.txt
index 519926e542..41c79a915f 100644
--- a/cmake.deps/cmake/LibvtermCMakeLists.txt
+++ b/cmake.deps/cmake/LibvtermCMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.13)
# Can be removed once minimum version is at least 3.15
if(POLICY CMP0092)
cmake_policy(SET CMP0092 NEW)
diff --git a/cmake.deps/cmake/LpegCMakeLists.txt b/cmake.deps/cmake/LpegCMakeLists.txt
index a3b3327cf7..4dcf3a1b77 100644
--- a/cmake.deps/cmake/LpegCMakeLists.txt
+++ b/cmake.deps/cmake/LpegCMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.13)
project (lpeg C)
include(GNUInstallDirs)
diff --git a/cmake.deps/cmake/MarkdownParserCMakeLists.txt b/cmake.deps/cmake/MarkdownParserCMakeLists.txt
index a5917334c9..8ee149e774 100644
--- a/cmake.deps/cmake/MarkdownParserCMakeLists.txt
+++ b/cmake.deps/cmake/MarkdownParserCMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.13)
# Can be removed once minimum version is at least 3.15
if(POLICY CMP0092)
cmake_policy(SET CMP0092 NEW)
@@ -6,7 +6,6 @@ endif()
project(${PARSERLANG} C)
add_compile_options(-w)
-set(CMAKE_C_STANDARD 99)
add_library(markdown MODULE
tree-sitter-markdown/src/parser.c
diff --git a/cmake.deps/cmake/TreesitterCMakeLists.txt b/cmake.deps/cmake/TreesitterCMakeLists.txt
index 3d80ffc331..f1e0d4e575 100644
--- a/cmake.deps/cmake/TreesitterCMakeLists.txt
+++ b/cmake.deps/cmake/TreesitterCMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.13)
# Can be removed once minimum version is at least 3.15
if(POLICY CMP0092)
cmake_policy(SET CMP0092 NEW)
@@ -13,7 +13,6 @@ target_include_directories(tree-sitter
install(FILES
lib/include/tree_sitter/api.h
- lib/include/tree_sitter/parser.h
DESTINATION include/tree_sitter)
include(GNUInstallDirs)
diff --git a/cmake.deps/cmake/TreesitterParserCMakeLists.txt b/cmake.deps/cmake/TreesitterParserCMakeLists.txt
index bdb3f05c11..c71a0a8f9b 100644
--- a/cmake.deps/cmake/TreesitterParserCMakeLists.txt
+++ b/cmake.deps/cmake/TreesitterParserCMakeLists.txt
@@ -1,4 +1,4 @@
-cmake_minimum_required(VERSION 3.10)
+cmake_minimum_required(VERSION 3.13)
# Can be removed once minimum version is at least 3.15
if(POLICY CMP0092)
cmake_policy(SET CMP0092 NEW)
diff --git a/cmake.deps/deps.txt b/cmake.deps/deps.txt
index 7007ceff27..de212460c7 100644
--- a/cmake.deps/deps.txt
+++ b/cmake.deps/deps.txt
@@ -1,11 +1,11 @@
-LIBUV_URL https://github.com/libuv/libuv/archive/v1.47.0.tar.gz
-LIBUV_SHA256 d50af7e6d72526db137e66fad812421c8a1cae09d146b0ec2bb9a22c5f23ba93
+LIBUV_URL https://github.com/libuv/libuv/archive/v1.48.0.tar.gz
+LIBUV_SHA256 8c253adb0f800926a6cbd1c6576abae0bc8eb86a4f891049b72f9e5b7dc58f33
MSGPACK_URL https://github.com/msgpack/msgpack-c/archive/c-6.0.0.tar.gz
MSGPACK_SHA256 af6f3cf25edb220aa2140b09bb5bdd73ddf00938194bd94ebe5c92090cccb466
-LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/43d0a19158ceabaa51b0462c1ebc97612b420a2e.tar.gz
-LUAJIT_SHA256 4fefa19bc5600928fb13c928bf5325eaa1c78f2c1738a8ac9552154ef178bb9a
+LUAJIT_URL https://github.com/LuaJIT/LuaJIT/archive/0d313b243194a0b8d2399d8b549ca5a0ff234db5.tar.gz
+LUAJIT_SHA256 53731880dbc4adbbf82ba69a85b5dbe15266032b8b94a077c0835bc10ec75f12
LUA_URL https://www.lua.org/ftp/lua-5.1.5.tar.gz
LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
@@ -13,20 +13,17 @@ LUA_SHA256 2640fc56a795f29d28ef15e13c34a47e223960b0240e8cb0a82d9b0738695333
UNIBILIUM_URL https://github.com/neovim/unibilium/archive/d72c3598e7ac5d1ebf86ee268b8b4ed95c0fa628.tar.gz
UNIBILIUM_SHA256 9c4747c862ab5e3076dcf8fa8f0ea7a6b50f20ec5905618b9536655596797487
-LIBTERMKEY_URL https://github.com/neovim/libtermkey/archive/dcb198a85c520ce38450a5970c97f8ff03b50f0e.tar.gz
-LIBTERMKEY_SHA256 5eb3e50af54312817bd56fa63b9f8dbd12ec11cedbcf8a7aa0fd79950cc83259
-
LIBVTERM_URL https://github.com/neovim/libvterm/archive/v0.3.3.tar.gz
LIBVTERM_SHA256 0babe3ab42c354925dadede90d352f054aa9c4ae6842ea803a20c9741e172e56
-LUV_URL https://github.com/luvit/luv/archive/dcd1a1cad5b05634a7691402d6ca2f214fb4ae76.tar.gz
-LUV_SHA256 b68c73ed233918da7e0b34b57c6bac0490e6c6f1b12c1051266b6ad9efa780d0
+LUV_URL https://github.com/luvit/luv/releases/download/1.48.0-2/luv-1.48.0-2.tar.gz
+LUV_SHA256 2c3a1ddfebb4f6550293a40ee789f7122e97647eede51511f57203de48c03b7a
LPEG_URL https://github.com/neovim/deps/raw/d495ee6f79e7962a53ad79670cb92488abe0b9b4/opt/lpeg-1.1.0.tar.gz
LPEG_SHA256 4b155d67d2246c1ffa7ad7bc466c1ea899bbc40fef0257cc9c03cecbaed4352a
-LUA_COMPAT53_URL https://github.com/keplerproject/lua-compat-5.3/archive/v0.9.tar.gz
-LUA_COMPAT53_SHA256 ad05540d2d96a48725bb79a1def35cf6652a4e2ec26376e2617c8ce2baa6f416
+LUA_COMPAT53_URL https://github.com/lunarmodules/lua-compat-5.3/archive/v0.13.tar.gz
+LUA_COMPAT53_SHA256 f5dc30e7b1fda856ee4d392be457642c1f0c259264a9b9bfbcb680302ce88fc2
CAT_URL https://github.com/neovim/deps/raw/21c5e8bdda33521a6ed497b315e03265a2785cbc/opt/cat.exe
CAT_SHA256 93b8d307bb15af3968920bdea3beb869a49d166f9164853c58a4e6ffdcae61c6
@@ -38,27 +35,27 @@ XXD_SHA256 7a581e3882d28161cc52850f9a11d634b3eaf2c029276f093c1ed4c90e45a10c
WIN32YANK_X86_64_URL https://github.com/equalsraf/win32yank/releases/download/v0.1.1/win32yank-x64.zip
WIN32YANK_X86_64_SHA256 247c9a05b94387a884b49d3db13f806b1677dfc38020f955f719be6902260cd6
-GETTEXT_URL https://ftp.gnu.org/pub/gnu/gettext/gettext-0.20.1.tar.gz
+GETTEXT_URL https://github.com/neovim/deps/raw/b9bf36eb31f27e8136d907da38fa23518927737e/opt/gettext-0.20.1.tar.gz
GETTEXT_SHA256 66415634c6e8c3fa8b71362879ec7575e27da43da562c798a8a2f223e6e47f5c
-LIBICONV_URL https://ftp.gnu.org/pub/gnu/libiconv/libiconv-1.17.tar.gz
+LIBICONV_URL https://github.com/neovim/deps/raw/b9bf36eb31f27e8136d907da38fa23518927737e/opt/libiconv-1.17.tar.gz
LIBICONV_SHA256 8f74213b56238c85a50a5329f77e06198771e70dd9a739779f4c02f65d971313
-TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.20.6.tar.gz
-TREESITTER_C_SHA256 44989072e1a9cd3d8f16e9cc3e726af50de6d3017f1231bdf3303b8cc007424e
-TREESITTER_LUA_URL https://github.com/MunifTanjim/tree-sitter-lua/archive/v0.0.19.tar.gz
+TREESITTER_C_URL https://github.com/tree-sitter/tree-sitter-c/archive/v0.20.8.tar.gz
+TREESITTER_C_SHA256 50f8aa6a84e2ad532cc3384e84e9f9f91fe3ec41c74f58e0c1e1013df5bf3a88
+TREESITTER_LUA_URL https://github.com/tree-sitter-grammars/tree-sitter-lua/archive/v0.0.19.tar.gz
TREESITTER_LUA_SHA256 974230f212d0049fce8e881b88b18eebbd05f1fd0edd16fe4ba5bdd2bcd78d08
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.1.tar.gz
-TREESITTER_VIMDOC_SHA256 61e165df29778dc0c9277c2a7bc67447cc4e1bed36ca916a2f476dd25ce3260e
-TREESITTER_QUERY_URL https://github.com/nvim-treesitter/tree-sitter-query/archive/v0.1.0.tar.gz
+TREESITTER_VIMDOC_URL https://github.com/neovim/tree-sitter-vimdoc/archive/v2.2.0.tar.gz
+TREESITTER_VIMDOC_SHA256 2cd898245d28bb606b05c022f04077031381d998faa3c6825c5ca01b7c89e2ae
+TREESITTER_QUERY_URL https://github.com/tree-sitter-grammars/tree-sitter-query/archive/v0.1.0.tar.gz
TREESITTER_QUERY_SHA256 e2b806f80e8bf1c4f4e5a96248393fe6622fc1fc6189d6896d269658f67f914c
TREESITTER_PYTHON_URL https://github.com/tree-sitter/tree-sitter-python/archive/v0.20.4.tar.gz
TREESITTER_PYTHON_SHA256 1e38c991832f461c0da8ca222fbe5be3b82b868fe34025f0295206b5e5789d7a
-TREESITTER_BASH_URL https://github.com/tree-sitter/tree-sitter-bash/archive/493646764e7ad61ce63ce3b8c59ebeb37f71b841.tar.gz
-TREESITTER_BASH_SHA256 99ebe9f2886efecc1a5e9e1360d804a1b49ad89976a66bb5c3871539cca5fb7e
+TREESITTER_BASH_URL https://github.com/tree-sitter/tree-sitter-bash/archive/v0.20.5.tar.gz
+TREESITTER_BASH_SHA256 7bba80ac64a18ec1b3f47e738e6a168f065c3cb4244234eff1b773816008f5a7
TREESITTER_MARKDOWN_URL https://github.com/MDeiml/tree-sitter-markdown/archive/v0.1.7.tar.gz
TREESITTER_MARKDOWN_SHA256 7d0e7f7ed4516ed0816f9c304e2e7fa93b2c16f9280416c2fb64dc4efd9c5f83
-TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/46af27796a76c72d8466627d499f2bca4af958ee.tar.gz
-TREESITTER_SHA256 2e35fa4c4d66c34d04fdb4a3a6c3abe01a05dff571ed9553b15aabf25d870f69
+TREESITTER_URL https://github.com/tree-sitter/tree-sitter/archive/v0.21.0.tar.gz
+TREESITTER_SHA256 6bb60e5b63c1dc18aba57a9e7b3ea775b4f9ceec44cc35dac4634d26db4eb69c
diff --git a/cmake/FindLibintl.cmake b/cmake/FindLibintl.cmake
index 630a3545fc..faee0537ff 100644
--- a/cmake/FindLibintl.cmake
+++ b/cmake/FindLibintl.cmake
@@ -78,3 +78,9 @@ endif()
find_package_handle_standard_args(Libintl DEFAULT_MSG
${REQUIRED_VARIABLES})
mark_as_advanced(LIBINTL_LIBRARY LIBINTL_INCLUDE_DIR)
+
+add_library(libintl INTERFACE)
+target_include_directories(libintl SYSTEM BEFORE INTERFACE ${LIBINTL_INCLUDE_DIR})
+if (LIBINTL_LIBRARY)
+ target_link_libraries(libintl INTERFACE ${LIBINTL_LIBRARY})
+endif()
diff --git a/cmake/FindLibtermkey.cmake b/cmake/FindLibtermkey.cmake
deleted file mode 100644
index 8039ae7994..0000000000
--- a/cmake/FindLibtermkey.cmake
+++ /dev/null
@@ -1,9 +0,0 @@
-find_path2(LIBTERMKEY_INCLUDE_DIR termkey.h)
-find_library2(LIBTERMKEY_LIBRARY NAMES termkey)
-find_package_handle_standard_args(Libtermkey DEFAULT_MSG
- LIBTERMKEY_LIBRARY LIBTERMKEY_INCLUDE_DIR)
-mark_as_advanced(LIBTERMKEY_INCLUDE_DIR LIBTERMKEY_LIBRARY)
-
-add_library(libtermkey INTERFACE)
-target_include_directories(libtermkey SYSTEM BEFORE INTERFACE ${LIBTERMKEY_INCLUDE_DIR})
-target_link_libraries(libtermkey INTERFACE ${LIBTERMKEY_LIBRARY})
diff --git a/cmake/FindLibuv.cmake b/cmake/FindLibuv.cmake
index 19315388dd..dcd9b9559d 100644
--- a/cmake/FindLibuv.cmake
+++ b/cmake/FindLibuv.cmake
@@ -1,5 +1,5 @@
find_path2(LIBUV_INCLUDE_DIR uv.h)
-find_library2(LIBUV_LIBRARY NAMES uv_a uv)
+find_library2(LIBUV_LIBRARY NAMES uv_a uv libuv)
set(LIBUV_LIBRARIES ${LIBUV_LIBRARY})
@@ -41,10 +41,12 @@ endif()
if(WIN32)
# check_library_exists() does not work for Win32 API calls in X86 due to name
# mangling calling conventions
- list(APPEND LIBUV_LIBRARIES iphlpapi)
- list(APPEND LIBUV_LIBRARIES psapi)
- list(APPEND LIBUV_LIBRARIES userenv)
- list(APPEND LIBUV_LIBRARIES ws2_32)
+ list(APPEND LIBUV_LIBRARIES
+ iphlpapi
+ psapi
+ userenv
+ ws2_32
+ dbghelp)
endif()
find_package(Threads)
@@ -59,3 +61,7 @@ find_package_handle_standard_args(Libuv DEFAULT_MSG
LIBUV_LIBRARY LIBUV_INCLUDE_DIR)
mark_as_advanced(LIBUV_INCLUDE_DIR LIBUV_LIBRARY)
+
+add_library(libuv INTERFACE)
+target_include_directories(libuv SYSTEM BEFORE INTERFACE ${LIBUV_INCLUDE_DIR})
+target_link_libraries(libuv INTERFACE ${LIBUV_LIBRARIES})
diff --git a/cmake/FindTreesitter.cmake b/cmake/FindTreesitter.cmake
index 8dac13337b..0d0897be70 100644
--- a/cmake/FindTreesitter.cmake
+++ b/cmake/FindTreesitter.cmake
@@ -7,23 +7,3 @@ 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
deleted file mode 100644
index 7097e5766f..0000000000
--- a/cmake/Format.cmake
+++ /dev/null
@@ -1,65 +0,0 @@
-# Returns a list of all files that has been changed in current branch compared
-# to master branch. This includes unstaged, staged and committed files.
-function(get_changed_files outvar)
- execute_process(
- COMMAND git branch --show-current
- OUTPUT_VARIABLE current_branch
- OUTPUT_STRIP_TRAILING_WHITESPACE)
-
- execute_process(
- COMMAND git merge-base master HEAD
- OUTPUT_VARIABLE ancestor_commit
- OUTPUT_STRIP_TRAILING_WHITESPACE)
-
- # Changed files that have been committed
- execute_process(
- 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 --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 --diff-filter=d --cached --name-only
- OUTPUT_VARIABLE staged_files
- OUTPUT_STRIP_TRAILING_WHITESPACE)
- separate_arguments(staged_files NATIVE_COMMAND ${staged_files})
-
- set(files ${committed_files} ${unstaged_files} ${staged_files})
- list(REMOVE_DUPLICATES files)
-
- set(${outvar} "${files}" PARENT_SCOPE)
-endfunction()
-
-get_changed_files(changed_files)
-
-if(LANG STREQUAL c)
- list(FILTER changed_files INCLUDE REGEX "\\.[ch]$")
- list(FILTER changed_files INCLUDE REGEX "^src/nvim/")
-
- if(changed_files)
- if(FORMAT_PRG)
- execute_process(COMMAND ${FORMAT_PRG} -c "src/uncrustify.cfg" --replace --no-backup ${changed_files})
- else()
- message(STATUS "Uncrustify not found. Skip formatting C files.")
- endif()
- endif()
-elseif(LANG STREQUAL lua)
- list(FILTER changed_files INCLUDE REGEX "\\.lua$")
- list(FILTER changed_files INCLUDE REGEX "^runtime/")
-
- if(changed_files)
- if(FORMAT_PRG)
- execute_process(COMMAND ${FORMAT_PRG} ${changed_files})
- else()
- message(STATUS "Stylua not found. Skip formatting lua files.")
- endif()
- endif()
-endif()
diff --git a/cmake/InstallHelpers.cmake b/cmake/InstallHelpers.cmake
index 63bf2bb73b..0a07bf9859 100644
--- a/cmake/InstallHelpers.cmake
+++ b/cmake/InstallHelpers.cmake
@@ -151,16 +151,3 @@ function(install_helper)
${RENAME})
endif()
endfunction()
-
-# Without CONFIGURE_DEPENDS globbing reuses cached file tree on rebuild.
-# For example it will ignore new files.
-# CONFIGURE_DEPENDS was introduced in 3.12
-
-function(glob_wrapper outvar)
- if(${CMAKE_VERSION} VERSION_LESS 3.12)
- file(GLOB ${outvar} ${ARGN})
- else()
- file(GLOB ${outvar} CONFIGURE_DEPENDS ${ARGN})
- endif()
- set(${outvar} ${${outvar}} PARENT_SCOPE)
-endfunction()
diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake
index 8d5b0d2402..6f93f73bc0 100644
--- a/cmake/RunTests.cmake
+++ b/cmake/RunTests.cmake
@@ -32,12 +32,7 @@ if(IS_ABSOLUTE ${TEST_PATH})
file(RELATIVE_PATH TEST_PATH "${WORKING_DIR}" "${TEST_PATH}")
endif()
-if(BUSTED_OUTPUT_TYPE STREQUAL junit)
- set(EXTRA_ARGS OUTPUT_FILE ${BUILD_DIR}/${TEST_TYPE}test-junit.xml)
-endif()
-
-set(BUSTED_ARGS $ENV{BUSTED_ARGS})
-separate_arguments(BUSTED_ARGS)
+separate_arguments(BUSTED_ARGS NATIVE_COMMAND $ENV{BUSTED_ARGS})
if(DEFINED ENV{TEST_TAG} AND NOT "$ENV{TEST_TAG}" STREQUAL "")
list(APPEND BUSTED_ARGS --tags $ENV{TEST_TAG})
@@ -72,7 +67,7 @@ endif()
execute_process(
# Note: because of "-ll" (low-level interpreter mode), some modules like
# _editor.lua are not loaded.
- COMMAND ${NVIM_PRG} -ll ${WORKING_DIR}/test/lua_runner.lua ${DEPS_INSTALL_DIR} busted -v -o test.busted.outputHandlers.${BUSTED_OUTPUT_TYPE}
+ COMMAND ${NVIM_PRG} -ll ${WORKING_DIR}/test/lua_runner.lua ${DEPS_INSTALL_DIR} busted -v -o test.busted.outputHandlers.nvim
--lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua
--lpath=${BUILD_DIR}/?.lua
--lpath=${WORKING_DIR}/runtime/lua/?.lua
diff --git a/cmake/Util.cmake b/cmake/Util.cmake
index 01d34d6752..80f81fd0b4 100644
--- a/cmake/Util.cmake
+++ b/cmake/Util.cmake
@@ -75,6 +75,7 @@ function(add_glob_target)
list(APPEND ARG_FILES ${globfiles})
endforeach()
+ list(APPEND ARG_EXCLUDE runtime/lua/vim/_meta) # only generated files, always ignore
foreach(exclude_pattern ${ARG_EXCLUDE})
list(FILTER ARG_FILES EXCLUDE REGEX ${exclude_pattern})
endforeach()
@@ -88,7 +89,7 @@ function(add_glob_target)
endif()
if(ARG_TOUCH_STRATEGY STREQUAL SINGLE)
- set(touch_file ${TOUCHES_DIR}/ran-${ARG_TARGET})
+ set(touch_file ${TOUCHES_DIR}/${ARG_TARGET})
add_custom_command(
OUTPUT ${touch_file}
COMMAND ${CMAKE_COMMAND} -E touch ${touch_file}
@@ -102,7 +103,7 @@ function(add_glob_target)
foreach(f ${ARG_FILES})
string(REGEX REPLACE "^${PROJECT_SOURCE_DIR}/" "" tf ${f})
string(REGEX REPLACE "[/.]" "-" tf ${tf})
- set(touch_file ${touch_dir}/ran-${tf})
+ set(touch_file ${touch_dir}/${tf})
add_custom_command(
OUTPUT ${touch_file}
COMMAND ${CMAKE_COMMAND} -E touch ${touch_file}
@@ -132,7 +133,7 @@ function(add_glob_target)
file(MAKE_DIRECTORY ${td})
string(REGEX REPLACE "^${PROJECT_SOURCE_DIR}/" "" tf ${touch_dir})
string(REGEX REPLACE "[/.]" "-" tf ${tf})
- set(touch_file ${td}/ran-${tf})
+ set(touch_file ${td}/${tf})
add_custom_command(
OUTPUT ${touch_file}
@@ -147,8 +148,8 @@ function(add_glob_target)
add_custom_target(${ARG_TARGET} DEPENDS ${touch_list})
endfunction()
-# Set default build type to Debug. Also limit the list of allowable build types
-# to the ones defined in variable allowableBuildTypes.
+# Set default build type to BUILD_TYPE. Also limit the list of allowable build
+# types to the ones defined in variable allowableBuildTypes.
#
# The correct way to specify build type (for example Release) for
# single-configuration generators (Make and Ninja) is to run
@@ -164,21 +165,27 @@ endfunction()
#
# Passing CMAKE_BUILD_TYPE for multi-config generators will not only not be
# used, but also generate a warning for the user.
-function(set_default_buildtype)
+function(set_default_buildtype BUILD_TYPE)
set(allowableBuildTypes Debug Release MinSizeRel RelWithDebInfo)
+ if(NOT BUILD_TYPE IN_LIST allowableBuildTypes)
+ message(FATAL_ERROR "Invalid build type: ${BUILD_TYPE}")
+ endif()
get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
if(isMultiConfig)
+ # Multi-config generators use the first element in CMAKE_CONFIGURATION_TYPES as the default build type
+ list(INSERT allowableBuildTypes 0 ${BUILD_TYPE})
+ list(REMOVE_DUPLICATES allowableBuildTypes)
set(CMAKE_CONFIGURATION_TYPES ${allowableBuildTypes} PARENT_SCOPE)
if(CMAKE_BUILD_TYPE)
message(WARNING "CMAKE_BUILD_TYPE specified which is ignored on \
- multi-configuration generators. Defaulting to Debug build type.")
+ multi-configuration generators. Defaulting to ${BUILD_TYPE} build type.")
endif()
else()
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "${allowableBuildTypes}")
if(NOT CMAKE_BUILD_TYPE)
- message(STATUS "CMAKE_BUILD_TYPE not specified, default is 'Debug'")
- set(CMAKE_BUILD_TYPE Debug CACHE STRING "Choose the type of build" FORCE)
+ message(STATUS "CMAKE_BUILD_TYPE not specified, default is '${BUILD_TYPE}'")
+ set(CMAKE_BUILD_TYPE ${BUILD_TYPE} CACHE STRING "Choose the type of build" FORCE)
elseif(NOT CMAKE_BUILD_TYPE IN_LIST allowableBuildTypes)
message(FATAL_ERROR "Invalid build type: ${CMAKE_BUILD_TYPE}")
else()
diff --git a/contrib/flake.lock b/contrib/flake.lock
index 554dc22bdb..0259dd4c8c 100644
--- a/contrib/flake.lock
+++ b/contrib/flake.lock
@@ -5,11 +5,11 @@
"systems": "systems"
},
"locked": {
- "lastModified": 1685518550,
- "narHash": "sha256-o2d0KcvaXzTrPRIo0kOLV0/QXHhDQ5DTi+OxcjO8xqY=",
+ "lastModified": 1701680307,
+ "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
- "rev": "a1720a10a6cfe8234c0e93907ffe81be440f4cef",
+ "rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
@@ -20,11 +20,11 @@
},
"nixpkgs": {
"locked": {
- "lastModified": 1686226982,
- "narHash": "sha256-nLuiPoeiVfqqzeq9rmXxpybh77VS37dsY/k8N2LoxVg=",
+ "lastModified": 1703013332,
+ "narHash": "sha256-+tFNwMvlXLbJZXiMHqYq77z/RfmpfpiI3yjL6o/Zo9M=",
"owner": "nixos",
"repo": "nixpkgs",
- "rev": "a64b73e07d4aa65cfcbda29ecf78eaf9e72e44bd",
+ "rev": "54aac082a4d9bb5bbc5c4e899603abfb76a3f6d6",
"type": "github"
},
"original": {
diff --git a/contrib/flake.nix b/contrib/flake.nix
index 57e56d0fdb..6355f3a68a 100644
--- a/contrib/flake.nix
+++ b/contrib/flake.nix
@@ -134,14 +134,16 @@
buildInputs = with pkgs;
oa.buildInputs ++ [
- cmake
lua.pkgs.luacheck
sumneko-lua-language-server
pythonEnv
include-what-you-use # for scripts/check-includes.py
jq # jq for scripts/vim-patch.sh -r
shellcheck # for `make shlint`
- doxygen # for script/gen_vimdoc.py
+ ];
+
+ nativeBuildInputs = with pkgs;
+ oa.nativeBuildInputs ++ [
clang-tools # for clangd to find the correct headers
];
diff --git a/contrib/local.mk.example b/contrib/local.mk.example
index bda2c1b4dc..4e8a510f2d 100644
--- a/contrib/local.mk.example
+++ b/contrib/local.mk.example
@@ -55,9 +55,3 @@
# DEPS_CMAKE_FLAGS += -DUSE_BUNDLED=OFF
# .DEFAULT_GOAL := nvim
-#
-# Run doxygen over the source code.
-# Output will be in build/doxygen
-#
-# doxygen:
-# doxygen src/Doxyfile
diff --git a/contrib/minimal.lua b/contrib/minimal.lua
new file mode 100644
index 0000000000..2391e12f68
--- /dev/null
+++ b/contrib/minimal.lua
@@ -0,0 +1,14 @@
+-- Run this file as `nvim --clean -u minimal.lua`
+
+for name, url in pairs {
+ -- ADD PLUGINS _NECESSARY_ TO REPRODUCE THE ISSUE, e.g:
+ -- some_plugin = 'https://github.com/author/plugin.nvim'
+} do
+ local install_path = vim.fn.fnamemodify('nvim_issue/' .. name, ':p')
+ if vim.fn.isdirectory(install_path) == 0 then
+ vim.fn.system { 'git', 'clone', '--depth=1', url, install_path }
+ end
+ vim.opt.runtimepath:append(install_path)
+end
+
+-- ADD INIT.LUA SETTINGS _NECESSARY_ FOR REPRODUCING THE ISSUE
diff --git a/runtime/CMakeLists.txt b/runtime/CMakeLists.txt
index 0077604141..c171fab9e9 100644
--- a/runtime/CMakeLists.txt
+++ b/runtime/CMakeLists.txt
@@ -1,12 +1,10 @@
-set(SYN_VIM_GENERATOR ${PROJECT_SOURCE_DIR}/src/nvim/generators/gen_vimvim.lua)
set(GENERATED_RUNTIME_DIR ${PROJECT_BINARY_DIR}/runtime)
-set(GENERATED_SYN_VIM ${GENERATED_RUNTIME_DIR}/syntax/vim/generated.vim)
+
set(GENERATED_HELP_TAGS ${GENERATED_RUNTIME_DIR}/doc/tags)
set(GENERATED_PACKAGE_DIR ${GENERATED_RUNTIME_DIR}/pack/dist/opt)
-set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack)
+set(GENERATED_SYN_VIM ${GENERATED_RUNTIME_DIR}/syntax/vim/generated.vim)
+set(SYN_VIM_GENERATOR ${PROJECT_SOURCE_DIR}/src/nvim/generators/gen_vimvim.lua)
-file(MAKE_DIRECTORY ${GENERATED_RUNTIME_DIR})
-file(MAKE_DIRECTORY ${GENERATED_RUNTIME_DIR}/syntax)
file(MAKE_DIRECTORY ${GENERATED_RUNTIME_DIR}/syntax/vim)
get_directory_property(LUA_GEN DIRECTORY ${PROJECT_SOURCE_DIR}/src/nvim DEFINITION LUA_GEN)
@@ -24,21 +22,21 @@ add_custom_command(OUTPUT ${GENERATED_SYN_VIM}
${FUNCS_DATA}
)
-glob_wrapper(PACKAGES ${PROJECT_SOURCE_DIR}/runtime/pack/dist/opt/*)
+file(GLOB PACKAGES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/runtime/pack/dist/opt/*)
set(GENERATED_PACKAGE_TAGS)
foreach(PACKAGE ${PACKAGES})
get_filename_component(PACKNAME ${PACKAGE} NAME)
- glob_wrapper("${PACKNAME}_DOC_FILES" ${PACKAGE}/doc/*.txt)
+ file(GLOB "${PACKNAME}_DOC_FILES" CONFIGURE_DEPENDS ${PACKAGE}/doc/*.txt)
if(${PACKNAME}_DOC_FILES)
file(MAKE_DIRECTORY ${GENERATED_PACKAGE_DIR}/${PACKNAME})
add_custom_command(OUTPUT "${GENERATED_PACKAGE_DIR}/${PACKNAME}/doc/tags"
COMMAND ${CMAKE_COMMAND} -E copy_directory
${PACKAGE} ${GENERATED_PACKAGE_DIR}/${PACKNAME}
- COMMAND "${PROJECT_BINARY_DIR}/bin/nvim"
+ COMMAND $<TARGET_FILE:nvim_bin>
-u NONE -i NONE -e --headless -c "helptags doc" -c quit
DEPENDS
- nvim
+ nvim_bin
nvim_runtime_deps
WORKING_DIRECTORY "${GENERATED_PACKAGE_DIR}/${PACKNAME}"
)
@@ -57,8 +55,6 @@ foreach(PACKAGE ${PACKAGES})
endif()
endforeach()
-glob_wrapper(DOCFILES ${PROJECT_SOURCE_DIR}/runtime/doc/*.txt)
-
set(BUILDDOCFILES)
foreach(DF ${DOCFILES})
get_filename_component(F ${DF} NAME)
@@ -69,26 +65,16 @@ add_custom_command(OUTPUT ${GENERATED_HELP_TAGS}
COMMAND ${CMAKE_COMMAND} -E remove_directory doc
COMMAND ${CMAKE_COMMAND} -E copy_directory
${PROJECT_SOURCE_DIR}/runtime/doc doc
- COMMAND "${PROJECT_BINARY_DIR}/bin/nvim"
+ COMMAND $<TARGET_FILE:nvim_bin>
-u NONE -i NONE -e --headless -c "helptags ++t doc" -c quit
DEPENDS
- nvim
+ nvim_bin
nvim_runtime_deps
WORKING_DIRECTORY "${GENERATED_RUNTIME_DIR}"
)
-
-# TODO: This doesn't work. wait for "nvim -l" to land?
-add_custom_target(doc_html
- COMMAND "${PROJECT_BINARY_DIR}/bin/nvim"
- -V1 -es --clean -c "lua require('scripts.gen_help_html').gen('./build/runtime/doc', './build/doc_html', nil, 'todo_commit_id')" -c "0cq"
- DEPENDS
- ${GENERATED_HELP_TAGS}
- WORKING_DIRECTORY "${GENERATED_RUNTIME_DIR}/doc"
-)
-
add_custom_target(
- runtime ALL
+ nvim_runtime
DEPENDS
${GENERATED_SYN_VIM}
${GENERATED_HELP_TAGS}
@@ -119,11 +105,11 @@ install_helper(
FILES ${CMAKE_CURRENT_SOURCE_DIR}/nvim.png
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/icons/hicolor/128x128/apps)
-glob_wrapper(RUNTIME_ROOT_FILES *.vim *.lua *.ico)
+file(GLOB RUNTIME_ROOT_FILES CONFIGURE_DEPENDS *.vim *.lua *.ico)
install_helper(FILES ${RUNTIME_ROOT_FILES}
DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/nvim/runtime/)
-glob_wrapper(RUNTIME_DIRS */)
+file(GLOB RUNTIME_DIRS CONFIGURE_DEPENDS */)
foreach(D ${RUNTIME_DIRS})
if(IS_DIRECTORY ${D})
install_helper(DIRECTORY ${D}
diff --git a/runtime/autoload/modula2.vim b/runtime/autoload/modula2.vim
new file mode 100644
index 0000000000..284dc2768f
--- /dev/null
+++ b/runtime/autoload/modula2.vim
@@ -0,0 +1,31 @@
+" Vim filetype plugin file
+" Language: Modula-2
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Last Change: 2024 Jan 04
+
+" Dialect can be one of pim, iso, r10
+function modula2#GetDialect() abort
+
+ if exists("b:modula2.dialect")
+ return b:modula2.dialect
+ endif
+
+ if exists("g:modula2_default_dialect")
+ let dialect = g:modula2_default_dialect
+ else
+ let dialect = "pim"
+ endif
+
+ return dialect
+endfunction
+
+function modula2#SetDialect(dialect, extension = "") abort
+ if exists("b:modula2")
+ unlockvar! b:modula2
+ endif
+
+ let b:modula2 = #{ dialect: a:dialect, extension: a:extension }
+ lockvar! b:modula2
+endfunction
+
+" vim: nowrap sw=2 sts=2 ts=8 noet fdm=marker:
diff --git a/runtime/autoload/netrw.vim b/runtime/autoload/netrw.vim
index b8092ebeeb..fa08bb3848 100644
--- a/runtime/autoload/netrw.vim
+++ b/runtime/autoload/netrw.vim
@@ -1,11 +1,14 @@
" netrw.vim: Handles file transfer and remote directory listing across
" AUTOLOAD SECTION
-" Date: May 03, 2023
+" Maintainer: This runtime file is looking for a new maintainer.
+" Date: May 03, 2023
" Version: 173a
" Last Change:
" 2023 Nov 21 by Vim Project: ignore wildignore when expanding $COMSPEC (v173a)
" 2023 Nov 22 by Vim Project: fix handling of very long filename on longlist style (v173a)
-" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" 2024 Feb 19 by Vim Project: (announce adoption)
+" 2024 Feb 29 by Vim Project: handle symlinks in tree mode correctly
+" Former Maintainer: Charles E Campbell
" GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim
" Copyright: Copyright (C) 2016 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
@@ -1973,7 +1976,7 @@ fun! NetrwStatusLine()
if !exists("w:netrw_explore_bufnr") || w:netrw_explore_bufnr != bufnr("%") || !exists("w:netrw_explore_line") || w:netrw_explore_line != line(".") || !exists("w:netrw_explore_list")
" restore user's status line
- let &stl = s:netrw_users_stl
+ let &l:stl = s:netrw_users_stl
let &laststatus = s:netrw_users_ls
if exists("w:netrw_explore_bufnr")|unlet w:netrw_explore_bufnr|endif
if exists("w:netrw_explore_line") |unlet w:netrw_explore_line |endif
@@ -2074,9 +2077,9 @@ fun! netrw#NetRead(mode,...)
let wholechoice = wholechoice . " " . choice
let ichoice = ichoice + 1
if ichoice > a:0
- if !exists("g:netrw_quiet")
- call netrw#ErrorMsg(s:ERROR,"Unbalanced string in filename '". wholechoice ."'",3)
- endif
+ if !exists("g:netrw_quiet")
+ call netrw#ErrorMsg(s:ERROR,"Unbalanced string in filename '". wholechoice ."'",3)
+ endif
" call Dret("netrw#NetRead :2 getcwd<".getcwd().">")
return
endif
@@ -2497,9 +2500,9 @@ fun! netrw#NetWrite(...) range
let wholechoice= wholechoice . " " . choice
let ichoice = ichoice + 1
if choice > a:0
- if !exists("g:netrw_quiet")
- call netrw#ErrorMsg(s:ERROR,"Unbalanced string in filename '". wholechoice ."'",13)
- endif
+ if !exists("g:netrw_quiet")
+ call netrw#ErrorMsg(s:ERROR,"Unbalanced string in filename '". wholechoice ."'",13)
+ endif
" call Dret("netrw#NetWrite")
return
endif
@@ -2770,7 +2773,7 @@ fun! netrw#NetWrite(...) range
if a:firstline == 1 && a:lastline == line("$")
" restore modifiability; usually equivalent to set nomod
- let &mod= mod
+ let &l:mod= mod
" call Decho(" ro=".&l:ro." ma=".&l:ma." mod=".&l:mod." wrap=".&l:wrap." (filename<".expand("%")."> win#".winnr()." ft<".&ft.">)",'~'.expand("<slnum>"))
elseif !exists("leavemod")
" indicate that the buffer has not been modified since last written
@@ -2959,7 +2962,7 @@ fun! s:NetrwGetFile(readcmd, tfile, method)
setl isk-=/
filetype detect
" call Decho("..local filetype<".&ft."> for buf#".bufnr()."<".bufname().">")
- let &isk= iskkeep
+ let &l:isk= iskkeep
" call Dredir("ls!","NetrwGetFile (renamed buffer back to remote filename<".rfile."> : expand(%)<".expand("%").">)")
let line1 = 1
let line2 = line("$")
@@ -4956,12 +4959,12 @@ fun! s:NetrwBrowseChgDir(islocal,newdir,...)
if g:netrw_chgwin >= 1
" call Decho("edit-a-file: changing window to #".g:netrw_chgwin.": (due to g:netrw_chgwin)",'~'.expand("<slnum>"))
if winnr("$")+1 == g:netrw_chgwin
- " if g:netrw_chgwin is set to one more than the last window, then
- " vertically split the last window to make that window available.
- let curwin= winnr()
- exe "NetrwKeepj keepalt ".winnr("$")."wincmd w"
- vs
- exe "NetrwKeepj keepalt ".g:netrw_chgwin."wincmd ".curwin
+ " if g:netrw_chgwin is set to one more than the last window, then
+ " vertically split the last window to make that window available.
+ let curwin= winnr()
+ exe "NetrwKeepj keepalt ".winnr("$")."wincmd w"
+ vs
+ exe "NetrwKeepj keepalt ".g:netrw_chgwin."wincmd ".curwin
endif
exe "NetrwKeepj keepalt ".g:netrw_chgwin."wincmd w"
endif
@@ -5268,7 +5271,8 @@ fun! s:NetrwBrowseUpDir(islocal)
endif
call s:RestorePosn(s:netrw_posn)
let curdir= substitute(curdir,'^.*[\/]','','')
- call search('\<'.curdir.'/','wc')
+ let curdir= '\<'. escape(curdir, '~'). '/'
+ call search(curdir,'wc')
endif
" call Dret("s:NetrwBrowseUpDir")
endfun
@@ -6069,7 +6073,7 @@ fun! s:NetrwServerEdit(islocal,fname)
" used something like <cr>.
" call Decho("user must have closed server AND did not use ctrl-r",'~'.expand("<slnum>"))
if exists("g:netrw_browse_split")
- unlet g:netrw_browse_split
+ unlet g:netrw_browse_split
endif
let g:netrw_browse_split= 0
if exists("s:netrw_browse_split_".winnr())
@@ -6103,7 +6107,7 @@ fun! s:NetrwServerEdit(islocal,fname)
if !ctrlr
" call Decho("server<".g:netrw_servername."> not available and ctrl-r not used",'~'.expand("<slnum>"))
if exists("g:netrw_browse_split")
- unlet g:netrw_browse_split
+ unlet g:netrw_browse_split
endif
let g:netrw_browse_split= 0
call s:NetrwBrowse(islocal,s:NetrwBrowseChgDir(islocal,a:fname))
@@ -6619,14 +6623,14 @@ fun! s:NetrwMaps(islocal)
nmap <buffer> <2-leftmouse> <Plug>Netrw2Leftmouse
imap <buffer> <leftmouse> <Plug>ILeftmouse
imap <buffer> <middlemouse> <Plug>IMiddlemouse
- nno <buffer> <silent> <Plug>NetrwLeftmouse <leftmouse>:call <SID>NetrwLeftmouse(1)<cr>
- nno <buffer> <silent> <Plug>NetrwCLeftmouse <leftmouse>:call <SID>NetrwCLeftmouse(1)<cr>
- nno <buffer> <silent> <Plug>NetrwMiddlemouse <leftmouse>:call <SID>NetrwPrevWinOpen(1)<cr>
- nno <buffer> <silent> <Plug>NetrwSLeftmouse <leftmouse>:call <SID>NetrwSLeftmouse(1)<cr>
- nno <buffer> <silent> <Plug>NetrwSLeftdrag <leftmouse>:call <SID>NetrwSLeftdrag(1)<cr>
+ nno <buffer> <silent> <Plug>NetrwLeftmouse :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwLeftmouse(1)<cr>
+ nno <buffer> <silent> <Plug>NetrwCLeftmouse :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwCLeftmouse(1)<cr>
+ nno <buffer> <silent> <Plug>NetrwMiddlemouse :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwPrevWinOpen(1)<cr>
+ nno <buffer> <silent> <Plug>NetrwSLeftmouse :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwSLeftmouse(1)<cr>
+ nno <buffer> <silent> <Plug>NetrwSLeftdrag :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwSLeftdrag(1)<cr>
nmap <buffer> <silent> <Plug>Netrw2Leftmouse -
- exe 'nnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
- exe 'vnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
+ exe 'nnoremap <buffer> <silent> <rightmouse> :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
+ exe 'vnoremap <buffer> <silent> <rightmouse> :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
endif
exe 'nnoremap <buffer> <silent> <nowait> <del> :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
exe 'nnoremap <buffer> <silent> <nowait> D :call <SID>NetrwLocalRm("'.mapsafecurdir.'")<cr>'
@@ -6719,22 +6723,22 @@ fun! s:NetrwMaps(islocal)
nnoremap <buffer> <silent> <Plug>NetrwRefresh :call <SID>NetrwRefresh(0,<SID>NetrwBrowseChgDir(0,'./'))<cr>
if g:netrw_mousemaps == 1
nmap <buffer> <leftmouse> <Plug>NetrwLeftmouse
- nno <buffer> <silent> <Plug>NetrwLeftmouse <leftmouse>:call <SID>NetrwLeftmouse(0)<cr>
+ nno <buffer> <silent> <Plug>NetrwLeftmouse :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwLeftmouse(0)<cr>
nmap <buffer> <c-leftmouse> <Plug>NetrwCLeftmouse
- nno <buffer> <silent> <Plug>NetrwCLeftmouse <leftmouse>:call <SID>NetrwCLeftmouse(0)<cr>
+ nno <buffer> <silent> <Plug>NetrwCLeftmouse :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwCLeftmouse(0)<cr>
nmap <buffer> <s-leftmouse> <Plug>NetrwSLeftmouse
- nno <buffer> <silent> <Plug>NetrwSLeftmouse <leftmouse>:call <SID>NetrwSLeftmouse(0)<cr>
+ nno <buffer> <silent> <Plug>NetrwSLeftmouse :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwSLeftmouse(0)<cr>
nmap <buffer> <s-leftdrag> <Plug>NetrwSLeftdrag
- nno <buffer> <silent> <Plug>NetrwSLeftdrag <leftmouse>:call <SID>NetrwSLeftdrag(0)<cr>
+ nno <buffer> <silent> <Plug>NetrwSLeftdrag :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwSLeftdrag(0)<cr>
nmap <middlemouse> <Plug>NetrwMiddlemouse
- nno <buffer> <silent> <middlemouse> <Plug>NetrwMiddlemouse <leftmouse>:call <SID>NetrwPrevWinOpen(0)<cr>
+ nno <buffer> <silent> <middlemouse> <Plug>NetrwMiddlemouse :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwPrevWinOpen(0)<cr>
nmap <buffer> <2-leftmouse> <Plug>Netrw2Leftmouse
nmap <buffer> <silent> <Plug>Netrw2Leftmouse -
imap <buffer> <leftmouse> <Plug>ILeftmouse
imap <buffer> <middlemouse> <Plug>IMiddlemouse
imap <buffer> <s-leftmouse> <Plug>ISLeftmouse
- exe 'nnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
- exe 'vnoremap <buffer> <silent> <rightmouse> <leftmouse>:call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
+ exe 'nnoremap <buffer> <silent> <rightmouse> :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
+ exe 'vnoremap <buffer> <silent> <rightmouse> :exec "norm! \<lt>leftmouse>"<bar>call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
endif
exe 'nnoremap <buffer> <silent> <nowait> <del> :call <SID>NetrwRemoteRm("'.mapsafeusermach.'","'.mapsafepath.'")<cr>'
exe 'nnoremap <buffer> <silent> <nowait> d :call <SID>NetrwMakeDir("'.mapsafeusermach.'")<cr>'
@@ -7445,7 +7449,7 @@ fun! s:NetrwMarkFileExe(islocal,enbloc)
for fname in s:netrwmarkfilelist_{curbufnr}
if a:islocal
if g:netrw_keepdir
- let fname= s:ShellEscape(netrw#WinPath(s:ComposePath(curdir,fname)))
+ let fname= s:ShellEscape(netrw#WinPath(s:ComposePath(curdir,fname)))
endif
else
let fname= s:ShellEscape(netrw#WinPath(b:netrw_curdir.fname))
@@ -7801,7 +7805,7 @@ fun! s:NetrwMarkFileMove(islocal)
let movecmd = netrw#WinPath(movecmd).movecmdargs
" call Decho("windows exception: movecmd<".movecmd."> (#1: had a space)",'~'.expand("<slnum>"))
else
- let movecmd = netrw#WinPath(movecmd)
+ let movecmd = netrw#WinPath(g:netrw_localmovecmd)
" call Decho("windows exception: movecmd<".movecmd."> (#2: no space)",'~'.expand("<slnum>"))
endif
else
@@ -7815,10 +7819,6 @@ fun! s:NetrwMarkFileMove(islocal)
endif
if !g:netrw_cygwin && (has("win32") || has("win95") || has("win64") || has("win16"))
let fname= substitute(fname,'/','\\','g')
- if g:netrw_keepdir
- " Jul 19, 2022: fixing file move when g:netrw_keepdir is 1
- let fname= b:netrw_curdir."\\".fname
- endif
endif
" call Decho("system(".movecmd." ".s:ShellEscape(fname)." ".tgt.")",'~'.expand("<slnum>"))
let ret= system(movecmd.g:netrw_localmovecmdopt." ".s:ShellEscape(fname)." ".tgt)
@@ -9377,7 +9377,7 @@ fun! s:NetrwTreeDir(islocal)
" call Decho("treedir<".treedir.">",'~'.expand("<slnum>"))
elseif curline =~ '@$'
" call Decho("handle symbolic link from current line",'~'.expand("<slnum>"))
- let treedir= resolve(substitute(substitute(getline('.'),'@.*$','','e'),'^|*\s*','','e'))
+ let potentialdir= resolve(substitute(substitute(getline('.'),'@.*$','','e'),'^|*\s*','','e'))
" call Decho("treedir<".treedir.">",'~'.expand("<slnum>"))
else
" call Decho("do not extract tree subdirectory from current line and set treedir to empty",'~'.expand("<slnum>"))
@@ -9402,7 +9402,6 @@ fun! s:NetrwTreeDir(islocal)
" call Decho("COMBAK#23 : mod=".&mod." win#".winnr())
" call Decho("islocal=".a:islocal." curline<".curline.">",'~'.expand("<slnum>"))
- let potentialdir= s:NetrwFile(substitute(curline,'^'.s:treedepthstring.'\+ \(.*\)@$','\1',''))
" call Decho("potentialdir<".potentialdir."> isdir=".isdirectory(potentialdir),'~'.expand("<slnum>"))
" call Decho("COMBAK#24 : mod=".&mod." win#".winnr())
@@ -9415,8 +9414,15 @@ fun! s:NetrwTreeDir(islocal)
" " call Decho("newdir <".newdir.">",'~'.expand("<slnum>"))
" else
" call Decho("apply NetrwTreePath to treetop<".w:netrw_treetop.">",'~'.expand("<slnum>"))
- let treedir = s:NetrwTreePath(w:netrw_treetop)
-" endif
+ if a:islocal && curline =~ '@$'
+ if isdirectory(s:NetrwFile(potentialdir))
+ let treedir = w:netrw_treetop.'/'.potentialdir.'/'
+ let w:netrw_treetop = treedir
+ endif
+ else
+ let potentialdir= s:NetrwFile(substitute(curline,'^'.s:treedepthstring.'\+ \(.*\)@$','\1',''))
+ let treedir = s:NetrwTreePath(w:netrw_treetop)
+ endif
endif
" call Decho("COMBAK#25 : mod=".&mod." win#".winnr())
@@ -10104,7 +10110,7 @@ fun! s:SetupNetrwStatusLine(statline)
" set up status line (may use User9 highlighting)
" insure that windows have a statusline
" make sure statusline is displayed
- let &stl=a:statline
+ let &l:stl=a:statline
setl laststatus=2
" call Decho("stl=".&stl,'~'.expand("<slnum>"))
redraw
@@ -10220,7 +10226,7 @@ fun! s:NetrwRemoteFtpCmd(path,listcmd)
setl ff=unix
" restore settings
- let &ff= ffkeep
+ let &l:ff= ffkeep
" call Dret("NetrwRemoteFtpCmd")
return
@@ -10257,7 +10263,7 @@ fun! s:NetrwRemoteFtpCmd(path,listcmd)
endif
" restore settings " {{{3
- let &ff= ffkeep
+ let &l:ff= ffkeep
" call Dret("NetrwRemoteFtpCmd")
endfun
@@ -10270,7 +10276,7 @@ fun! s:NetrwRemoteListing()
let w:netrw_bannercnt= s:bannercnt
endif
if !exists("w:netrw_bannercnt") && exists("b:bannercnt")
- let w:netrw_bannercnt= s:bannercnt
+ let w:netrw_bannercnt= b:bannercnt
endif
call s:RemotePathAnalysis(b:netrw_curdir)
@@ -10561,7 +10567,7 @@ fun! s:NetrwRemoteRmFile(path,rmfile,all)
NetrwKeepj call netrw#ErrorMsg(s:ERROR,"for some reason b:netrw_curdir doesn't exist!",53)
let ok="q"
else
- let remotedir= substitute(b:netrw_curdir,'^.*//[^/]\+/\(.*\)$','\1','')
+ let remotedir= substitute(b:netrw_curdir,'^.\{-}//[^/]\+/\(.*\)$','\1','')
" call Decho("netrw_rm_cmd<".netrw_rm_cmd.">",'~'.expand("<slnum>"))
" call Decho("remotedir<".remotedir.">",'~'.expand("<slnum>"))
" call Decho("rmfile<".a:rmfile.">",'~'.expand("<slnum>"))
@@ -10574,7 +10580,7 @@ fun! s:NetrwRemoteRmFile(path,rmfile,all)
let ret= system(netrw_rm_cmd)
if v:shell_error != 0
if exists("b:netrw_curdir") && b:netrw_curdir != getcwd() && !g:netrw_keepdir
- call netrw#ErrorMsg(s:ERROR,"remove failed; perhaps due to vim's current directory<".getcwd()."> not matching netrw's (".b:netrw_curdir.") (see :help netrw-cd)",102)
+ call netrw#ErrorMsg(s:ERROR,"remove failed; perhaps due to vim's current directory<".getcwd()."> not matching netrw's (".b:netrw_curdir.") (see :help netrw-cd)",102)
else
call netrw#ErrorMsg(s:WARNING,"cmd<".netrw_rm_cmd."> failed",60)
endif
@@ -10852,6 +10858,10 @@ fun! s:LocalBrowseRefresh()
" call Dret("s:LocalBrowseRefresh : don't refresh when focus not on netrw window")
return
endif
+ if !empty(getcmdwintype())
+ " cannot move away from cmdline window, see :h E11
+ return
+ endif
if exists("s:netrw_events") && s:netrw_events == 1
" s:LocalFastBrowser gets called (indirectly) from a
let s:netrw_events= 2
@@ -11078,16 +11088,16 @@ fun! s:LocalListing()
" call Decho("pfile <".pfile.">",'~'.expand("<slnum>"))
if w:netrw_liststyle == s:LONGLIST
- let longfile= printf("%-".g:netrw_maxfilenamelen."S",pfile)
- let sz = getfsize(filename)
- let szlen = 15 - (strdisplaywidth(longfile) - g:netrw_maxfilenamelen)
- let szlen = (szlen > 0) ? szlen : 0
+ let longfile = printf("%-".g:netrw_maxfilenamelen."S",pfile)
+ let sz = getfsize(filename)
+ let szlen = 15 - (strdisplaywidth(longfile) - g:netrw_maxfilenamelen)
+ let szlen = (szlen > 0) ? szlen : 0
if g:netrw_sizestyle =~# "[hH]"
let sz= s:NetrwHumanReadable(sz)
endif
let fsz = printf("%".szlen."S",sz)
- let pfile = longfile." ".fsz." ".strftime(g:netrw_timefmt,getftime(filename))
+ let pfile= longfile." ".fsz." ".strftime(g:netrw_timefmt,getftime(filename))
" call Decho("longlist support: sz=".sz." fsz=".fsz,'~'.expand("<slnum>"))
endif
@@ -11164,6 +11174,10 @@ endfun
fun! s:NetrwLocalRename(path) range
" call Dfunc("NetrwLocalRename(path<".a:path.">)")
+ if !exists("w:netrw_bannercnt")
+ let w:netrw_bannercnt= b:netrw_bannercnt
+ endif
+
" preparation for removing multiple files/directories
let ykeep = @@
let ctr = a:firstline
@@ -11265,6 +11279,10 @@ fun! s:NetrwLocalRm(path) range
" call Dfunc("s:NetrwLocalRm(path<".a:path.">)")
" call Decho("firstline=".a:firstline." lastline=".a:lastline,'~'.expand("<slnum>"))
+ if !exists("w:netrw_bannercnt")
+ let w:netrw_bannercnt= b:netrw_bannercnt
+ endif
+
" preparation for removing multiple files/directories
let ykeep = @@
let ret = 0
@@ -11464,7 +11482,7 @@ endfun
" netrw#RFC2396: converts %xx into characters {{{2
fun! netrw#RFC2396(fname)
" call Dfunc("netrw#RFC2396(fname<".a:fname.">)")
- let fname = escape(substitute(a:fname,'%\(\x\x\)','\=nr2char("0x".submatch(1))','ge')," \t")
+ let fname = escape(substitute(a:fname,'%\(\x\x\)','\=printf("%c","0x".submatch(1))','ge')," \t")
" call Dret("netrw#RFC2396 ".fname)
return fname
endfun
@@ -12099,7 +12117,7 @@ fun! s:NetrwLcd(newdir)
if (has("win32") || has("win95") || has("win64") || has("win16")) && !g:netrw_cygwin
if a:newdir =~ '^\\\\\w\+' || a:newdir =~ '^//\w\+'
let dirname = '\'
- exe 'NetrwKeepj sil lcd '.fnameescape(dirname)
+ exe 'NetrwKeepj sil lcd '.fnameescape(dirname)
endif
endif
catch /^Vim\%((\a\+)\)\=:E472/
diff --git a/runtime/autoload/netrwFileHandlers.vim b/runtime/autoload/netrwFileHandlers.vim
index d07235c107..2b6f8f7a0f 100644
--- a/runtime/autoload/netrwFileHandlers.vim
+++ b/runtime/autoload/netrwFileHandlers.vim
@@ -1,6 +1,7 @@
" netrwFileHandlers: contains various extension-based file handlers for
" netrw's browsers' x command ("eXecute launcher")
-" Author: Charles E. Campbell
+" Maintainer: This runtime file is looking for a new maintainer.
+" Original Author: Charles E. Campbell
" Date: Sep 18, 2020
" Version: 11
" Copyright: Copyright (C) 1999-2012 Charles E. Campbell {{{1
diff --git a/runtime/autoload/netrwSettings.vim b/runtime/autoload/netrwSettings.vim
index d65f83144e..5525c0d035 100644
--- a/runtime/autoload/netrwSettings.vim
+++ b/runtime/autoload/netrwSettings.vim
@@ -1,6 +1,7 @@
" netrwSettings.vim: makes netrw settings simpler
" Date: Nov 15, 2021
-" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E Campbell
" Version: 18
" Copyright: Copyright (C) 1999-2007 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
diff --git a/runtime/autoload/provider/perl.vim b/runtime/autoload/provider/perl.vim
index 24f2b018bb..b439f751ae 100644
--- a/runtime/autoload/provider/perl.vim
+++ b/runtime/autoload/provider/perl.vim
@@ -1,83 +1,15 @@
-if exists('s:loaded_perl_provider')
+if exists('g:loaded_perl_provider')
finish
endif
-let s:loaded_perl_provider = 1
-
-function! provider#perl#Detect() abort
- " use g:perl_host_prog if set or check if perl is on the path
- let prog = exepath(get(g:, 'perl_host_prog', 'perl'))
- if empty(prog)
- return ['', '']
- endif
-
- " if perl is available, make sure we have 5.22+
- call system([prog, '-e', 'use v5.22'])
- if v:shell_error
- return ['', 'Perl version is too old, 5.22+ required']
- endif
-
- " if perl is available, make sure the required module is available
- call system([prog, '-W', '-MNeovim::Ext', '-e', ''])
- if v:shell_error
- return ['', '"Neovim::Ext" cpan module is not installed']
- endif
-
- return [prog, '']
-endfunction
-
-function! provider#perl#Prog() abort
- return s:prog
+function! provider#perl#Call(method, args) abort
+ return v:lua.vim.provider.perl.call(a:method, a:args)
endfunction
function! provider#perl#Require(host) abort
- if s:err != ''
- echoerr s:err
- return
- endif
-
- let prog = provider#perl#Prog()
- let args = [s:prog, '-e', 'use Neovim::Ext; start_host();']
-
- " Collect registered perl plugins into args
- let perl_plugins = remote#host#PluginsForHost(a:host.name)
- for plugin in perl_plugins
- call add(args, plugin.path)
- endfor
-
- return provider#Poll(args, a:host.orig_name, '$NVIM_PERL_LOG_FILE')
+ return v:lua.vim.provider.perl.require(a:host, s:prog)
endfunction
-function! provider#perl#Call(method, args) abort
- if s:err != ''
- echoerr s:err
- return
- endif
-
- if !exists('s:host')
- try
- let s:host = remote#host#Require('legacy-perl-provider')
- catch
- let s:err = v:exception
- echohl WarningMsg
- echomsg v:exception
- echohl None
- return
- endtry
- endif
- return call('rpcrequest', insert(insert(a:args, 'perl_'.a:method), s:host))
-endfunction
-
-let [s:prog, s:err] = provider#perl#Detect()
+let s:prog = v:lua.vim.provider.perl.detect()
let g:loaded_perl_provider = empty(s:prog) ? 1 : 2
-
-if g:loaded_perl_provider != 2
- let s:err = 'Cannot find perl or the required perl module'
-endif
-
-
-" The perl provider plugin will run in a separate instance of the perl
-" host.
-call remote#host#RegisterClone('legacy-perl-provider', 'perl')
-call remote#host#RegisterPlugin('legacy-perl-provider', 'ScriptHost.pm', [])
-
+call v:lua.require'vim.provider.perl'.start()
diff --git a/runtime/autoload/provider/python3.vim b/runtime/autoload/provider/python3.vim
index 38ef0cccfc..43c14122d0 100644
--- a/runtime/autoload/provider/python3.vim
+++ b/runtime/autoload/provider/python3.vim
@@ -1,45 +1,15 @@
-" The Python3 provider uses a Python3 host to emulate an environment for running
-" python3 plugins. :help provider
-"
-" Associating the plugin with the Python3 host is the first step because
-" plugins will be passed as command-line arguments
-
if exists('g:loaded_python3_provider')
finish
endif
-let [s:prog, s:err] = provider#pythonx#Detect(3)
-let g:loaded_python3_provider = empty(s:prog) ? 1 : 2
-function! provider#python3#Prog() abort
- return s:prog
+function! provider#python3#Call(method, args) abort
+ return v:lua.vim.provider.python.call(a:method, a:args)
endfunction
-function! provider#python3#Error() abort
- return s:err
+function! provider#python3#Require(host) abort
+ return v:lua.vim.provider.python.require(a:host)
endfunction
-" The Python3 provider plugin will run in a separate instance of the Python3
-" host.
-call remote#host#RegisterClone('legacy-python3-provider', 'python3')
-call remote#host#RegisterPlugin('legacy-python3-provider', 'script_host.py', [])
-
-function! provider#python3#Call(method, args) abort
- if s:err != ''
- return
- endif
- if !exists('s:host')
- let s:rpcrequest = function('rpcrequest')
-
- " Ensure that we can load the Python3 host before bootstrapping
- try
- let s:host = remote#host#Require('legacy-python3-provider')
- catch
- let s:err = v:exception
- echohl WarningMsg
- echomsg v:exception
- echohl None
- return
- endtry
- endif
- return call(s:rpcrequest, insert(insert(a:args, 'python_'.a:method), s:host))
-endfunction
+let s:prog = v:lua.vim.provider.python.detect_by_module('neovim')
+let g:loaded_python3_provider = empty(s:prog) ? 1 : 2
+call v:lua.require'vim.provider.python'.start()
diff --git a/runtime/autoload/provider/pythonx.vim b/runtime/autoload/provider/pythonx.vim
deleted file mode 100644
index 48b96c699a..0000000000
--- a/runtime/autoload/provider/pythonx.vim
+++ /dev/null
@@ -1,112 +0,0 @@
-" The Python provider helper
-if exists('s:loaded_pythonx_provider')
- finish
-endif
-
-let s:loaded_pythonx_provider = 1
-
-function! provider#pythonx#Require(host) abort
- " Python host arguments
- let prog = provider#python3#Prog()
- let args = [prog, '-c', 'import sys; sys.path = [p for p in sys.path if p != ""]; import neovim; neovim.start_host()']
-
-
- " Collect registered Python plugins into args
- let python_plugins = remote#host#PluginsForHost(a:host.name)
- for plugin in python_plugins
- call add(args, plugin.path)
- endfor
-
- return provider#Poll(args, a:host.orig_name, '$NVIM_PYTHON_LOG_FILE', {'overlapped': v:true})
-endfunction
-
-function! s:get_python_executable_from_host_var(major_version) abort
- return expand(get(g:, 'python'.(a:major_version == 3 ? '3' : execute("throw 'unsupported'")).'_host_prog', ''), v:true)
-endfunction
-
-function! s:get_python_candidates(major_version) abort
- return {
- \ 3: ['python3', 'python3.12', 'python3.11', 'python3.10', 'python3.9', 'python3.8', 'python3.7', 'python']
- \ }[a:major_version]
-endfunction
-
-" Returns [path_to_python_executable, error_message]
-function! provider#pythonx#Detect(major_version) abort
- return provider#pythonx#DetectByModule('neovim', a:major_version)
-endfunction
-
-" Returns [path_to_python_executable, error_message]
-function! provider#pythonx#DetectByModule(module, major_version) abort
- let python_exe = s:get_python_executable_from_host_var(a:major_version)
-
- if !empty(python_exe)
- return [exepath(expand(python_exe, v:true)), '']
- endif
-
- let candidates = s:get_python_candidates(a:major_version)
- let errors = []
-
- for exe in candidates
- let [result, error] = provider#pythonx#CheckForModule(exe, a:module, a:major_version)
- if result
- return [exe, error]
- endif
- " Accumulate errors in case we don't find any suitable Python executable.
- call add(errors, error)
- endfor
-
- " No suitable Python executable found.
- return ['', 'Could not load Python '.a:major_version.":\n".join(errors, "\n")]
-endfunction
-
-" Returns array: [prog_exitcode, prog_version]
-function! s:import_module(prog, module) abort
- let prog_version = system([a:prog, '-W', 'ignore', '-c', printf(
- \ 'import sys, importlib.util; ' .
- \ 'sys.path = [p for p in sys.path if p != ""]; ' .
- \ 'sys.stdout.write(str(sys.version_info[0]) + "." + str(sys.version_info[1])); ' .
- \ 'sys.exit(2 * int(importlib.util.find_spec("%s") is None))',
- \ a:module)])
- return [v:shell_error, prog_version]
-endfunction
-
-" Returns array: [was_success, error_message]
-function! provider#pythonx#CheckForModule(prog, module, major_version) abort
- let prog_path = exepath(a:prog)
- if prog_path ==# ''
- return [0, a:prog . ' not found in search path or not executable.']
- endif
-
- let min_version = '3.7'
-
- " Try to load module, and output Python version.
- " Exit codes:
- " 0 module can be loaded.
- " 2 module cannot be loaded.
- " Otherwise something else went wrong (e.g. 1 or 127).
- let [prog_exitcode, prog_version] = s:import_module(a:prog, a:module)
-
- if prog_exitcode == 2 || prog_exitcode == 0
- " Check version only for expected return codes.
- if prog_version !~ '^' . a:major_version
- return [0, prog_path . ' is Python ' . prog_version . ' and cannot provide Python '
- \ . a:major_version . '.']
- elseif prog_version =~ '^' . a:major_version && str2nr(prog_version[2:]) < str2nr(min_version[2:])
- return [0, prog_path . ' is Python ' . prog_version . ' and cannot provide Python >= '
- \ . min_version . '.']
- endif
- endif
-
- if prog_exitcode == 2
- return [0, prog_path.' does not have the "' . a:module . '" module.']
- elseif prog_exitcode == 127
- " This can happen with pyenv's shims.
- return [0, prog_path . ' does not exist: ' . prog_version]
- elseif prog_exitcode
- return [0, 'Checking ' . prog_path . ' caused an unknown error. '
- \ . '(' . prog_exitcode . ', output: ' . prog_version . ')'
- \ . ' Report this at https://github.com/neovim/neovim']
- endif
-
- return [1, '']
-endfunction
diff --git a/runtime/autoload/provider/ruby.vim b/runtime/autoload/provider/ruby.vim
index 1428fab1cc..07b4aca23f 100644
--- a/runtime/autoload/provider/ruby.vim
+++ b/runtime/autoload/provider/ruby.vim
@@ -1,73 +1,16 @@
-" The Ruby provider helper
if exists('g:loaded_ruby_provider')
finish
endif
-let g:loaded_ruby_provider = 1
-
-function! provider#ruby#Detect() abort
- let e = empty(s:prog) ? 'missing ruby or ruby-host' : ''
- return [s:prog, e]
-endfunction
-
-function! provider#ruby#Prog() abort
- return s:prog
-endfunction
function! provider#ruby#Require(host) abort
- let prog = provider#ruby#Prog()
- let ruby_plugins = remote#host#PluginsForHost(a:host.name)
-
- for plugin in ruby_plugins
- let prog .= " " . shellescape(plugin.path)
- endfor
-
- return provider#Poll(prog, a:host.orig_name, '$NVIM_RUBY_LOG_FILE')
+ return v:lua.vim.provider.ruby.require(a:host)
endfunction
function! provider#ruby#Call(method, args) abort
- if s:err != ''
- echoerr s:err
- return
- endif
-
- if !exists('s:host')
- try
- let s:host = remote#host#Require('legacy-ruby-provider')
- catch
- let s:err = v:exception
- echohl WarningMsg
- echomsg v:exception
- echohl None
- return
- endtry
- endif
- return call('rpcrequest', insert(insert(a:args, 'ruby_'.a:method), s:host))
+ return v:lua.vim.provider.ruby.call(a:method, a:args)
endfunction
-function! s:detect()
- if exists("g:ruby_host_prog")
- return expand(g:ruby_host_prog, v:true)
- elseif has('win32')
- return exepath('neovim-ruby-host.bat')
- else
- let p = exepath('neovim-ruby-host')
- if empty(p)
- return ''
- endif
- " neovim-ruby-host could be an rbenv shim for another Ruby version.
- call system(p)
- return v:shell_error ? '' : p
- end
-endfunction
-
-let s:err = ''
-let s:prog = s:detect()
-let s:plugin_path = expand('<sfile>:p:h') . '/script_host.rb'
+let s:prog = v:lua.vim.provider.ruby.detect()
let g:loaded_ruby_provider = empty(s:prog) ? 1 : 2
-
-if g:loaded_ruby_provider != 2
- let s:err = 'Cannot find the neovim RubyGem. Try :checkhealth'
-endif
-
-call remote#host#RegisterClone('legacy-ruby-provider', 'ruby')
-call remote#host#RegisterPlugin('legacy-ruby-provider', s:plugin_path, [])
+let s:plugin_path = expand('<sfile>:p:h') . '/script_host.rb'
+call v:lua.require'vim.provider.ruby'.start(s:plugin_path)
diff --git a/runtime/autoload/remote/host.vim b/runtime/autoload/remote/host.vim
index 884b478f19..0032a4b71e 100644
--- a/runtime/autoload/remote/host.vim
+++ b/runtime/autoload/remote/host.vim
@@ -190,11 +190,9 @@ endfunction
" Registration of standard hosts
-" Python/Python3
-call remote#host#Register('python', '*',
- \ function('provider#pythonx#Require'))
+" Python3
call remote#host#Register('python3', '*',
- \ function('provider#pythonx#Require'))
+ \ function('provider#python3#Require'))
" Ruby
call remote#host#Register('ruby', '*.rb',
diff --git a/runtime/autoload/rubycomplete.vim b/runtime/autoload/rubycomplete.vim
index 3677b25aeb..6ead0fd837 100644
--- a/runtime/autoload/rubycomplete.vim
+++ b/runtime/autoload/rubycomplete.vim
@@ -2,8 +2,7 @@
" Language: Ruby
" Maintainer: Mark Guzman <segfault@hasno.info>
" URL: https://github.com/vim-ruby/vim-ruby
-" Release Coordinator: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2020 Apr 12
+" Last Change: 2023 Dec 31
" ----------------------------------------------------------------------------
"
" Ruby IRB/Complete author: Keiju ISHITSUKA(keiju@ishitsuka.com)
@@ -490,7 +489,7 @@ class VimRubyCompletion
trail = "%s%s" % [ dir, sub ]
tcfg = "%sconfig" % trail
- if File.exists?( tcfg )
+ if File.exist?( tcfg )
rails_base = trail
break
end
@@ -503,7 +502,7 @@ class VimRubyCompletion
bootfile = rails_base + "config/boot.rb"
envfile = rails_base + "config/environment.rb"
- if File.exists?( bootfile ) && File.exists?( envfile )
+ if File.exist?( bootfile ) && File.exist?( envfile )
begin
require bootfile
require envfile
diff --git a/runtime/autoload/tar.vim b/runtime/autoload/tar.vim
index e242fe98e3..f2a74db5ed 100644
--- a/runtime/autoload/tar.vim
+++ b/runtime/autoload/tar.vim
@@ -2,7 +2,8 @@
" AUTOLOAD PORTION
" Date: Nov 14, 2023
" Version: 32b (with modifications from the Vim Project)
-" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E Campbell
" License: Vim License (see vim's :help license)
"
" Contains many ideas from Michael Toren's <tar.vim>
@@ -163,9 +164,9 @@ fun! tar#Browse(tarfile)
" call Decho("1: exe silent r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
exe "sil! r! gzip -d -c -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
- elseif tarfile =~# '\.\(tgz\)$' || tarfile =~# '\.\(tbz\)$' || tarfile =~# '\.\(txz\)$' || tarfile =~# '\.\(tzs\)$'
+ elseif tarfile =~# '\.\(tgz\)$' || tarfile =~# '\.\(tbz\)$' || tarfile =~# '\.\(txz\)$' || tarfile =~# '\.\(tzst\)$'
if has("unix") && executable("file")
- let filekind= system("file ".shellescape(tarfile,1)) =~ "bzip2"
+ let filekind= system("file ".shellescape(tarfile,1))
else
let filekind= ""
endif
@@ -192,7 +193,7 @@ fun! tar#Browse(tarfile)
elseif tarfile =~# '\.\(xz\|txz\)$'
" call Decho("3: exe silent r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - ")
exe "sil! r! xz --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
- elseif tarfile =~# '\.\(zst\|tzs\)$'
+ elseif tarfile =~# '\.\(zst\|tzst\)$'
exe "sil! r! zstd --decompress --stdout -- ".shellescape(tarfile,1)." | ".g:tar_cmd." -".g:tar_browseoptions." - "
else
if tarfile =~ '^\s*-'
@@ -230,7 +231,7 @@ fun! tar#Browse(tarfile)
" set up maps supported for tar
setlocal noma nomod ro
noremap <silent> <buffer> <cr> :call <SID>TarBrowseSelect()<cr>
- noremap <silent> <buffer> x :call tar#Extract()<cr>
+ noremap <silent> <buffer> x :call tar#Extract()<cr>
if &mouse != ""
noremap <silent> <buffer> <leftmouse> <leftmouse>:call <SID>TarBrowseSelect()<cr>
endif
@@ -468,9 +469,9 @@ fun! tar#Write(fname)
let compress= "xz -- ".shellescape(tarfile,0)
" call Decho("compress<".compress.">")
elseif tarfile =~# '\.zst'
- call system("zstd --decompress -- ".shellescape(tarfile,0))
+ call system("zstd --decompress --rm -- ".shellescape(tarfile,0))
let tarfile = substitute(tarfile,'\.zst','','e')
- let compress= "zstd -- ".shellescape(tarfile,0)
+ let compress= "zstd --rm -- ".shellescape(tarfile,0)
elseif tarfile =~# '\.lzma'
call system("lzma -d -- ".shellescape(tarfile,0))
let tarfile = substitute(tarfile,'\.lzma','','e')
@@ -486,7 +487,7 @@ fun! tar#Write(fname)
else
" call Decho("tarfile<".tarfile."> fname<".fname.">")
-
+
if fname =~ '/'
let dirpath = substitute(fname,'/[^/]\+$','','e')
if has("win32unix") && executable("cygpath")
@@ -502,7 +503,7 @@ fun! tar#Write(fname)
let tarfile = substitute(tarfile, '-', './-', '')
endif
" call Decho("tarfile<".tarfile."> fname<".fname.">")
-
+
if exists("g:tar_secure")
let tar_secure= " -- "
else
@@ -512,7 +513,7 @@ fun! tar#Write(fname)
if has("win32unix") && executable("cygpath")
let tarfile = substitute(system("cygpath ".shellescape(tarfile,0)),'\n','','e')
endif
-
+
" delete old file from tarfile
" call Decho("system(".g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0)." -- ".shellescape(fname,0).")")
call system(g:tar_cmd." ".g:tar_delfile." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
@@ -521,8 +522,8 @@ fun! tar#Write(fname)
" call Decho("***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname))
echohl Error | echo "***error*** (tar#Write) sorry, unable to update ".fnameescape(tarfile)." with ".fnameescape(fname) | echohl None
else
-
- " update tarfile with new file
+
+ " update tarfile with new file
" call Decho(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
call system(g:tar_cmd." -".g:tar_writeoptions." ".shellescape(tarfile,0).tar_secure.shellescape(fname,0))
if v:shell_error != 0
@@ -555,7 +556,7 @@ fun! tar#Write(fname)
unlet s:tblfile_{winnr()}
endif
endif
-
+
" cleanup and restore current directory
cd ..
call s:Rmdir("_ZIPVIM_")
@@ -696,13 +697,13 @@ fun! tar#Extract()
echo "***note*** successfully extracted ".fname
endif
- elseif filereadable(tarbase.".tzs")
+ elseif filereadable(tarbase.".tzst")
let extractcmd= substitute(extractcmd,"-","--zstd","")
-" call Decho("system(".extractcmd." ".shellescape(tarbase).".tzs ".shellescape(fname).")")
- call system(extractcmd." ".shellescape(tarbase).".txz ".shellescape(fname))
+" call Decho("system(".extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname).")")
+ call system(extractcmd." ".shellescape(tarbase).".tzst ".shellescape(fname))
if v:shell_error != 0
- echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tzs ".fname.": failed!" | echohl NONE
-" call Decho("***error*** ".extractcmd." ".tarbase.".tzs ".fname.": failed!")
+ echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tzst ".fname.": failed!" | echohl NONE
+" call Decho("***error*** ".extractcmd." ".tarbase.".tzst ".fname.": failed!")
else
echo "***note*** successfully extracted ".fname
endif
@@ -710,7 +711,7 @@ fun! tar#Extract()
elseif filereadable(tarbase.".tar.zst")
let extractcmd= substitute(extractcmd,"-","--zstd","")
" call Decho("system(".extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname).")")
- call system(extractcmd." ".shellescape(tarbase).".tar.xz ".shellescape(fname))
+ call system(extractcmd." ".shellescape(tarbase).".tar.zst ".shellescape(fname))
if v:shell_error != 0
echohl Error | echo "***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!" | echohl NONE
" call Decho("***error*** ".extractcmd." ".tarbase.".tar.zst ".fname.": failed!")
diff --git a/runtime/autoload/tohtml.vim b/runtime/autoload/tohtml.vim
deleted file mode 100644
index b1693efc5d..0000000000
--- a/runtime/autoload/tohtml.vim
+++ /dev/null
@@ -1,951 +0,0 @@
-" Vim autoload file for the tohtml plugin.
-" Maintainer: Ben Fritz <fritzophrenic@gmail.com>
-" Last Change: 2023 Sep 03
-"
-" Additional contributors:
-"
-" Original by Bram Moolenaar <Bram@vim.org>
-" Diff2HTML() added by Christian Brabandt <cb@256bit.org>
-"
-" See Mercurial change logs for more!
-
-" this file uses line continuations
-let s:cpo_sav = &cpo
-set cpo&vim
-
-" Automatically find charsets from all encodings supported natively by Vim. With
-" the 8bit- and 2byte- prefixes, Vim can actually support more encodings than
-" this. Let the user specify these however since they won't be supported on
-" every system.
-"
-" Note, not all of Vim's supported encodings have a charset to use.
-"
-" Names in this list are from:
-" http://www.iana.org/assignments/character-sets
-" g:tohtml#encoding_to_charset: {{{
-let g:tohtml#encoding_to_charset = {
- \ 'latin1' : 'ISO-8859-1',
- \ 'iso-8859-2' : 'ISO-8859-2',
- \ 'iso-8859-3' : 'ISO-8859-3',
- \ 'iso-8859-4' : 'ISO-8859-4',
- \ 'iso-8859-5' : 'ISO-8859-5',
- \ 'iso-8859-6' : 'ISO-8859-6',
- \ 'iso-8859-7' : 'ISO-8859-7',
- \ 'iso-8859-8' : 'ISO-8859-8',
- \ 'iso-8859-9' : 'ISO-8859-9',
- \ 'iso-8859-10' : '',
- \ 'iso-8859-13' : 'ISO-8859-13',
- \ 'iso-8859-14' : '',
- \ 'iso-8859-15' : 'ISO-8859-15',
- \ 'koi8-r' : 'KOI8-R',
- \ 'koi8-u' : 'KOI8-U',
- \ 'macroman' : 'macintosh',
- \ 'cp437' : '',
- \ 'cp775' : '',
- \ 'cp850' : '',
- \ 'cp852' : '',
- \ 'cp855' : '',
- \ 'cp857' : '',
- \ 'cp860' : '',
- \ 'cp861' : '',
- \ 'cp862' : '',
- \ 'cp863' : '',
- \ 'cp865' : '',
- \ 'cp866' : 'IBM866',
- \ 'cp869' : '',
- \ 'cp874' : '',
- \ 'cp1250' : 'windows-1250',
- \ 'cp1251' : 'windows-1251',
- \ 'cp1253' : 'windows-1253',
- \ 'cp1254' : 'windows-1254',
- \ 'cp1255' : 'windows-1255',
- \ 'cp1256' : 'windows-1256',
- \ 'cp1257' : 'windows-1257',
- \ 'cp1258' : 'windows-1258',
- \ 'euc-jp' : 'EUC-JP',
- \ 'sjis' : 'Shift_JIS',
- \ 'cp932' : 'Shift_JIS',
- \ 'cp949' : '',
- \ 'euc-kr' : 'EUC-KR',
- \ 'cp936' : 'GBK',
- \ 'euc-cn' : 'GB2312',
- \ 'big5' : 'Big5',
- \ 'cp950' : 'Big5',
- \ 'utf-8' : 'UTF-8',
- \ 'ucs-2' : 'UTF-8',
- \ 'ucs-2le' : 'UTF-8',
- \ 'utf-16' : 'UTF-8',
- \ 'utf-16le' : 'UTF-8',
- \ 'ucs-4' : 'UTF-8',
- \ 'ucs-4le' : 'UTF-8',
- \ }
-lockvar g:tohtml#encoding_to_charset
-" Notes:
-" 1. All UCS/UTF are converted to UTF-8 because it is much better supported
-" 2. Any blank spaces are there because Vim supports it but at least one major
-" web browser does not according to http://wiki.whatwg.org/wiki/Web_Encodings.
-" }}}
-
-" Only automatically find encodings supported natively by Vim, let the user
-" specify the encoding if it's not natively supported. This function is only
-" used when the user specifies the charset, they better know what they are
-" doing!
-"
-" Names in this list are from:
-" http://www.iana.org/assignments/character-sets
-" g:tohtml#charset_to_encoding: {{{
-let g:tohtml#charset_to_encoding = {
- \ 'iso_8859-1:1987' : 'latin1',
- \ 'iso-ir-100' : 'latin1',
- \ 'iso_8859-1' : 'latin1',
- \ 'iso-8859-1' : 'latin1',
- \ 'latin1' : 'latin1',
- \ 'l1' : 'latin1',
- \ 'ibm819' : 'latin1',
- \ 'cp819' : 'latin1',
- \ 'csisolatin1' : 'latin1',
- \ 'iso_8859-2:1987' : 'iso-8859-2',
- \ 'iso-ir-101' : 'iso-8859-2',
- \ 'iso_8859-2' : 'iso-8859-2',
- \ 'iso-8859-2' : 'iso-8859-2',
- \ 'latin2' : 'iso-8859-2',
- \ 'l2' : 'iso-8859-2',
- \ 'csisolatin2' : 'iso-8859-2',
- \ 'iso_8859-3:1988' : 'iso-8859-3',
- \ 'iso-ir-109' : 'iso-8859-3',
- \ 'iso_8859-3' : 'iso-8859-3',
- \ 'iso-8859-3' : 'iso-8859-3',
- \ 'latin3' : 'iso-8859-3',
- \ 'l3' : 'iso-8859-3',
- \ 'csisolatin3' : 'iso-8859-3',
- \ 'iso_8859-4:1988' : 'iso-8859-4',
- \ 'iso-ir-110' : 'iso-8859-4',
- \ 'iso_8859-4' : 'iso-8859-4',
- \ 'iso-8859-4' : 'iso-8859-4',
- \ 'latin4' : 'iso-8859-4',
- \ 'l4' : 'iso-8859-4',
- \ 'csisolatin4' : 'iso-8859-4',
- \ 'iso_8859-5:1988' : 'iso-8859-5',
- \ 'iso-ir-144' : 'iso-8859-5',
- \ 'iso_8859-5' : 'iso-8859-5',
- \ 'iso-8859-5' : 'iso-8859-5',
- \ 'cyrillic' : 'iso-8859-5',
- \ 'csisolatincyrillic' : 'iso-8859-5',
- \ 'iso_8859-6:1987' : 'iso-8859-6',
- \ 'iso-ir-127' : 'iso-8859-6',
- \ 'iso_8859-6' : 'iso-8859-6',
- \ 'iso-8859-6' : 'iso-8859-6',
- \ 'ecma-114' : 'iso-8859-6',
- \ 'asmo-708' : 'iso-8859-6',
- \ 'arabic' : 'iso-8859-6',
- \ 'csisolatinarabic' : 'iso-8859-6',
- \ 'iso_8859-7:1987' : 'iso-8859-7',
- \ 'iso-ir-126' : 'iso-8859-7',
- \ 'iso_8859-7' : 'iso-8859-7',
- \ 'iso-8859-7' : 'iso-8859-7',
- \ 'elot_928' : 'iso-8859-7',
- \ 'ecma-118' : 'iso-8859-7',
- \ 'greek' : 'iso-8859-7',
- \ 'greek8' : 'iso-8859-7',
- \ 'csisolatingreek' : 'iso-8859-7',
- \ 'iso_8859-8:1988' : 'iso-8859-8',
- \ 'iso-ir-138' : 'iso-8859-8',
- \ 'iso_8859-8' : 'iso-8859-8',
- \ 'iso-8859-8' : 'iso-8859-8',
- \ 'hebrew' : 'iso-8859-8',
- \ 'csisolatinhebrew' : 'iso-8859-8',
- \ 'iso_8859-9:1989' : 'iso-8859-9',
- \ 'iso-ir-148' : 'iso-8859-9',
- \ 'iso_8859-9' : 'iso-8859-9',
- \ 'iso-8859-9' : 'iso-8859-9',
- \ 'latin5' : 'iso-8859-9',
- \ 'l5' : 'iso-8859-9',
- \ 'csisolatin5' : 'iso-8859-9',
- \ 'iso-8859-10' : 'iso-8859-10',
- \ 'iso-ir-157' : 'iso-8859-10',
- \ 'l6' : 'iso-8859-10',
- \ 'iso_8859-10:1992' : 'iso-8859-10',
- \ 'csisolatin6' : 'iso-8859-10',
- \ 'latin6' : 'iso-8859-10',
- \ 'iso-8859-13' : 'iso-8859-13',
- \ 'iso-8859-14' : 'iso-8859-14',
- \ 'iso-ir-199' : 'iso-8859-14',
- \ 'iso_8859-14:1998' : 'iso-8859-14',
- \ 'iso_8859-14' : 'iso-8859-14',
- \ 'latin8' : 'iso-8859-14',
- \ 'iso-celtic' : 'iso-8859-14',
- \ 'l8' : 'iso-8859-14',
- \ 'iso-8859-15' : 'iso-8859-15',
- \ 'iso_8859-15' : 'iso-8859-15',
- \ 'latin-9' : 'iso-8859-15',
- \ 'koi8-r' : 'koi8-r',
- \ 'cskoi8r' : 'koi8-r',
- \ 'koi8-u' : 'koi8-u',
- \ 'macintosh' : 'macroman',
- \ 'mac' : 'macroman',
- \ 'csmacintosh' : 'macroman',
- \ 'ibm437' : 'cp437',
- \ 'cp437' : 'cp437',
- \ '437' : 'cp437',
- \ 'cspc8codepage437' : 'cp437',
- \ 'ibm775' : 'cp775',
- \ 'cp775' : 'cp775',
- \ 'cspc775baltic' : 'cp775',
- \ 'ibm850' : 'cp850',
- \ 'cp850' : 'cp850',
- \ '850' : 'cp850',
- \ 'cspc850multilingual' : 'cp850',
- \ 'ibm852' : 'cp852',
- \ 'cp852' : 'cp852',
- \ '852' : 'cp852',
- \ 'cspcp852' : 'cp852',
- \ 'ibm855' : 'cp855',
- \ 'cp855' : 'cp855',
- \ '855' : 'cp855',
- \ 'csibm855' : 'cp855',
- \ 'ibm857' : 'cp857',
- \ 'cp857' : 'cp857',
- \ '857' : 'cp857',
- \ 'csibm857' : 'cp857',
- \ 'ibm860' : 'cp860',
- \ 'cp860' : 'cp860',
- \ '860' : 'cp860',
- \ 'csibm860' : 'cp860',
- \ 'ibm861' : 'cp861',
- \ 'cp861' : 'cp861',
- \ '861' : 'cp861',
- \ 'cp-is' : 'cp861',
- \ 'csibm861' : 'cp861',
- \ 'ibm862' : 'cp862',
- \ 'cp862' : 'cp862',
- \ '862' : 'cp862',
- \ 'cspc862latinhebrew' : 'cp862',
- \ 'ibm863' : 'cp863',
- \ 'cp863' : 'cp863',
- \ '863' : 'cp863',
- \ 'csibm863' : 'cp863',
- \ 'ibm865' : 'cp865',
- \ 'cp865' : 'cp865',
- \ '865' : 'cp865',
- \ 'csibm865' : 'cp865',
- \ 'ibm866' : 'cp866',
- \ 'cp866' : 'cp866',
- \ '866' : 'cp866',
- \ 'csibm866' : 'cp866',
- \ 'ibm869' : 'cp869',
- \ 'cp869' : 'cp869',
- \ '869' : 'cp869',
- \ 'cp-gr' : 'cp869',
- \ 'csibm869' : 'cp869',
- \ 'windows-1250' : 'cp1250',
- \ 'windows-1251' : 'cp1251',
- \ 'windows-1253' : 'cp1253',
- \ 'windows-1254' : 'cp1254',
- \ 'windows-1255' : 'cp1255',
- \ 'windows-1256' : 'cp1256',
- \ 'windows-1257' : 'cp1257',
- \ 'windows-1258' : 'cp1258',
- \ 'extended_unix_code_packed_format_for_japanese' : 'euc-jp',
- \ 'cseucpkdfmtjapanese' : 'euc-jp',
- \ 'euc-jp' : 'euc-jp',
- \ 'shift_jis' : 'sjis',
- \ 'ms_kanji' : 'sjis',
- \ 'sjis' : 'sjis',
- \ 'csshiftjis' : 'sjis',
- \ 'ibm-thai' : 'cp874',
- \ 'csibmthai' : 'cp874',
- \ 'ks_c_5601-1987' : 'cp949',
- \ 'iso-ir-149' : 'cp949',
- \ 'ks_c_5601-1989' : 'cp949',
- \ 'ksc_5601' : 'cp949',
- \ 'korean' : 'cp949',
- \ 'csksc56011987' : 'cp949',
- \ 'euc-kr' : 'euc-kr',
- \ 'cseuckr' : 'euc-kr',
- \ 'gbk' : 'cp936',
- \ 'cp936' : 'cp936',
- \ 'ms936' : 'cp936',
- \ 'windows-936' : 'cp936',
- \ 'gb_2312-80' : 'euc-cn',
- \ 'iso-ir-58' : 'euc-cn',
- \ 'chinese' : 'euc-cn',
- \ 'csiso58gb231280' : 'euc-cn',
- \ 'big5' : 'big5',
- \ 'csbig5' : 'big5',
- \ 'utf-8' : 'utf-8',
- \ 'iso-10646-ucs-2' : 'ucs-2',
- \ 'csunicode' : 'ucs-2',
- \ 'utf-16' : 'utf-16',
- \ 'utf-16be' : 'utf-16',
- \ 'utf-16le' : 'utf-16le',
- \ 'utf-32' : 'ucs-4',
- \ 'utf-32be' : 'ucs-4',
- \ 'utf-32le' : 'ucs-4le',
- \ 'iso-10646-ucs-4' : 'ucs-4',
- \ 'csucs4' : 'ucs-4'
- \ }
-lockvar g:tohtml#charset_to_encoding
-"}}}
-
-func! tohtml#Convert2HTML(line1, line2) "{{{
- let s:settings = tohtml#GetUserSettings()
-
- if !&diff || s:settings.diff_one_file "{{{
- if a:line2 >= a:line1
- let g:html_start_line = a:line1
- let g:html_end_line = a:line2
- else
- let g:html_start_line = a:line2
- let g:html_end_line = a:line1
- endif
- runtime syntax/2html.vim "}}}
- else "{{{
- let win_list = []
- let buf_list = []
- windo if &diff | call add(win_list, winbufnr(0)) | endif
- let s:settings.whole_filler = 1
- let g:html_diff_win_num = 0
- for window in win_list
- " switch to the next buffer to convert
- exe ":" .. bufwinnr(window) .. "wincmd w"
-
- " figure out whether current charset and encoding will work, if not
- " default to UTF-8
- if !exists('g:html_use_encoding') &&
- \ (((&l:fileencoding=='' || (&l:buftype!='' && &l:buftype!=?'help'))
- \ && &encoding!=?s:settings.vim_encoding)
- \ || &l:fileencoding!='' && &l:fileencoding!=?s:settings.vim_encoding)
- echohl WarningMsg
- echomsg "TOhtml: mismatched file encodings in Diff buffers, using UTF-8"
- echohl None
- let s:settings.vim_encoding = 'utf-8'
- let s:settings.encoding = 'UTF-8'
- endif
-
- " set up for diff-mode conversion
- let g:html_start_line = 1
- let g:html_end_line = line('$')
- let g:html_diff_win_num += 1
-
- " convert this file
- runtime syntax/2html.vim
-
- " remember the HTML buffer for later combination
- call add(buf_list, bufnr('%'))
- endfor
- unlet g:html_diff_win_num
- call tohtml#Diff2HTML(win_list, buf_list)
- endif "}}}
-
- unlet g:html_start_line
- unlet g:html_end_line
- unlet s:settings
-endfunc "}}}
-
-func! tohtml#Diff2HTML(win_list, buf_list) "{{{
- let xml_line = ""
- let tag_close = '>'
-
- let s:old_paste = &paste
- set paste
- let s:old_magic = &magic
- set magic
-
- let html = []
- if !s:settings.no_doc
- if s:settings.use_xhtml
- if s:settings.encoding != ""
- let xml_line = "<?xml version=\"1.0\" encoding=\"" .. s:settings.encoding .. "\"?>"
- else
- let xml_line = "<?xml version=\"1.0\"?>"
- endif
- let tag_close = ' />'
- endif
-
- let style = [s:settings.use_xhtml ? "" : '-->']
- let body_line = ''
-
- let s:html5 = 0
- if s:settings.use_xhtml
- call add(html, xml_line)
- endif
- if s:settings.use_xhtml
- call add(html, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">")
- call add(html, '<html xmlns="http://www.w3.org/1999/xhtml">')
- elseif s:settings.use_css && !s:settings.no_pre
- call add(html, "<!DOCTYPE html>")
- call add(html, '<html>')
- let s:html5 = 1
- else
- call add(html, '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"')
- call add(html, ' "http://www.w3.org/TR/html4/loose.dtd">')
- call add(html, '<html>')
- endif
- call add(html, '<head>')
-
- " include encoding as close to the top as possible, but only if not already
- " contained in XML information
- if s:settings.encoding != "" && !s:settings.use_xhtml
- if s:html5
- call add(html, '<meta charset="' .. s:settings.encoding .. '"' .. tag_close)
- else
- call add(html, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" .. s:settings.encoding .. '"' .. tag_close)
- endif
- endif
-
- call add(html, '<title>diff</title>')
- call add(html, '<meta name="Generator" content="Vim/'..v:version/100..'.'..v:version%100..'"'..tag_close)
- call add(html, '<meta name="plugin-version" content="'..g:loaded_2html_plugin..'"'..tag_close)
- call add(html, '<meta name="settings" content="'.
- \ join(filter(keys(s:settings),'s:settings[v:val]'),',').
- \ ',prevent_copy='..s:settings.prevent_copy.
- \ ',use_input_for_pc='..s:settings.use_input_for_pc.
- \ '"'..tag_close)
- call add(html, '<meta name="colorscheme" content="'.
- \ (exists('g:colors_name')
- \ ? g:colors_name
- \ : 'none').. '"'..tag_close)
-
- call add(html, '</head>')
- let body_line_num = len(html)
- call add(html, '<body'..(s:settings.line_ids ? ' onload="JumpToLine();"' : '')..'>')
- endif
- call add(html, "<table "..(s:settings.use_css? "" : "border='1' width='100%' ").."id='vimCodeElement"..s:settings.id_suffix.."'>")
-
- call add(html, '<tr>')
- for buf in a:win_list
- call add(html, '<th>'..bufname(buf)..'</th>')
- endfor
- call add(html, '</tr><tr>')
-
- let diff_style_start = 0
- let insert_index = 0
-
- for buf in a:buf_list
- let temp = []
- exe bufwinnr(buf) .. 'wincmd w'
-
- " If text is folded because of user foldmethod settings, etc. we don't want
- " to act on everything in a fold by mistake.
- setlocal nofoldenable
-
- " When not using CSS or when using xhtml, the <body> line can be important.
- " Assume it will be the same for all buffers and grab it from the first
- " buffer. Similarly, need to grab the body end line as well.
- if !s:settings.no_doc
- if body_line == ''
- 1
- call search('<body')
- let body_line = getline('.')
- $
- call search('</body>', 'b')
- let s:body_end_line = getline('.')
- endif
-
- " Grab the style information. Some of this will be duplicated so only insert
- " it if it's not already there. {{{
- 1
- let style_start = search('^<style\( type="text/css"\)\?>')
- 1
- let style_end = search('^</style>')
- if style_start > 0 && style_end > 0
- let buf_styles = getline(style_start + 1, style_end - 1)
- for a_style in buf_styles
- if index(style, a_style) == -1
- if diff_style_start == 0
- if a_style =~ '\<Diff\(Change\|Text\|Add\|Delete\)'
- let diff_style_start = len(style)-1
- endif
- endif
- call insert(style, a_style, insert_index)
- let insert_index += 1
- endif
- endfor
- endif " }}}
-
- " everything new will get added before the diff styles so diff highlight
- " properly overrides normal highlight
- if diff_style_start != 0
- let insert_index = diff_style_start
- endif
-
- " Delete those parts that are not needed so we can include the rest into the
- " resulting table.
- 1,/^<body.*\%(\n<!--.*-->\_s\+.*id='oneCharWidth'.*\_s\+.*id='oneInputWidth'.*\_s\+.*id='oneEmWidth'\)\?\zs/d_
- $
- ?</body>?,$d_
- elseif !s:settings.no_modeline
- " remove modeline from source files if it is included and we haven't deleted
- " due to removing html footer already
- $d
- endif
- let temp = getline(1,'$')
- " clean out id on the main content container because we already set it on
- " the table
- let temp[0] = substitute(temp[0], " id='vimCodeElement[^']*'", "", "")
- " undo deletion of start and end part
- " so we can later save the file as valid html
- " TODO: restore using grabbed lines if undolevel is 1?
- if !s:settings.no_doc
- normal! 2u
- elseif !s:settings.no_modeline
- normal! u
- endif
- if s:settings.use_css
- call add(html, '<td><div>')
- elseif s:settings.use_xhtml
- call add(html, '<td nowrap="nowrap" valign="top"><div>')
- else
- call add(html, '<td nowrap valign="top"><div>')
- endif
- let html += temp
- call add(html, '</div></td>')
-
- " Close this buffer
- " TODO: the comment above says we're going to allow saving the file
- " later...but here we discard it?
- quit!
- endfor
-
- if !s:settings.no_doc
- let html[body_line_num] = body_line
- endif
-
- call add(html, '</tr>')
- call add(html, '</table>')
- if !s:settings.no_doc
- call add(html, s:body_end_line)
- call add(html, '</html>')
- endif
-
- " The generated HTML is admittedly ugly and takes a LONG time to fold.
- " Make sure the user doesn't do syntax folding when loading a generated file,
- " using a modeline.
- if !s:settings.no_modeline
- call add(html, '<!-- vim: set foldmethod=manual : -->')
- endif
-
- let i = 1
- let name = "Diff" .. (s:settings.use_xhtml ? ".xhtml" : ".html")
- " Find an unused file name if current file name is already in use
- while filereadable(name)
- let name = substitute(name, '\d*\.x\?html$', '', '') .. i .. '.' .. fnamemodify(copy(name), ":t:e")
- let i += 1
- endwhile
-
- let s:ei_sav = &eventignore
- set eventignore+=FileType
- exe "topleft new " .. name
- let &eventignore=s:ei_sav
- unlet s:ei_sav
-
- setlocal modifiable
-
- " just in case some user autocmd creates content in the new buffer, make sure
- " it is empty before proceeding
- %d
-
- " set the fileencoding to match the charset we'll be using
- let &l:fileencoding=s:settings.vim_encoding
-
- " According to http://www.w3.org/TR/html4/charset.html#doc-char-set, the byte
- " order mark is highly recommend on the web when using multibyte encodings. But,
- " it is not a good idea to include it on UTF-8 files. Otherwise, let Vim
- " determine when it is actually inserted.
- if s:settings.vim_encoding == 'utf-8'
- setlocal nobomb
- else
- setlocal bomb
- endif
-
- call append(0, html)
-
- if !s:settings.no_doc
- if len(style) > 0
- 1
- let style_start = search('^</head>')-1
-
- " add required javascript in reverse order so we can just call append again
- " and again without adjusting {{{
-
- let s:uses_script = s:settings.dynamic_folds || s:settings.line_ids
-
- " insert script closing tag if needed
- if s:uses_script
- call append(style_start, [
- \ '',
- \ s:settings.use_xhtml ? '//]]>' : '-->',
- \ "</script>"
- \ ])
- endif
-
- " insert javascript to get IDs from line numbers, and to open a fold before
- " jumping to any lines contained therein
- if s:settings.line_ids
- call append(style_start, [
- \ " /* Always jump to new location even if the line was hidden inside a fold, or",
- \ " * we corrected the raw number to a line ID.",
- \ " */",
- \ " if (lineElem) {",
- \ " lineElem.scrollIntoView(true);",
- \ " }",
- \ " return true;",
- \ "}",
- \ "if ('onhashchange' in window) {",
- \ " window.onhashchange = JumpToLine;",
- \ "}"
- \ ])
-
- if s:settings.dynamic_folds
- call append(style_start, [
- \ "",
- \ " /* navigate upwards in the DOM tree to open all folds containing the line */",
- \ " var node = lineElem;",
- \ " while (node && node.id != 'vimCodeElement"..s:settings.id_suffix.."')",
- \ " {",
- \ " if (node.className == 'closed-fold')",
- \ " {",
- \ " /* toggle open the fold ID (remove window ID) */",
- \ " toggleFold(node.id.substr(4));",
- \ " }",
- \ " node = node.parentNode;",
- \ " }",
- \ ])
- endif
- endif
-
- if s:settings.line_ids
- call append(style_start, [
- \ "",
- \ "/* function to open any folds containing a jumped-to line before jumping to it */",
- \ "function JumpToLine()",
- \ "{",
- \ " var lineNum;",
- \ " lineNum = window.location.hash;",
- \ " lineNum = lineNum.substr(1); /* strip off '#' */",
- \ "",
- \ " if (lineNum.indexOf('L') == -1) {",
- \ " lineNum = 'L'+lineNum;",
- \ " }",
- \ " if (lineNum.indexOf('W') == -1) {",
- \ " lineNum = 'W1'+lineNum;",
- \ " }",
- \ " var lineElem = document.getElementById(lineNum);"
- \ ])
- endif
-
- " Insert javascript to toggle matching folds open and closed in all windows,
- " if dynamic folding is active.
- if s:settings.dynamic_folds
- call append(style_start, [
- \ " function toggleFold(objID)",
- \ " {",
- \ " for (win_num = 1; win_num <= "..len(a:buf_list).."; win_num++)",
- \ " {",
- \ " var fold;",
- \ ' fold = document.getElementById("win"+win_num+objID);',
- \ " if(fold.className == 'closed-fold')",
- \ " {",
- \ " fold.className = 'open-fold';",
- \ " }",
- \ " else if (fold.className == 'open-fold')",
- \ " {",
- \ " fold.className = 'closed-fold';",
- \ " }",
- \ " }",
- \ " }",
- \ ])
- endif
-
- if s:uses_script
- " insert script tag if needed
- call append(style_start, [
- \ "<script" .. (s:html5 ? "" : " type='text/javascript'") .. ">",
- \ s:settings.use_xhtml ? '//<![CDATA[' : "<!--"])
- endif
-
- " Insert styles from all the generated html documents and additional styles
- " for the table-based layout of the side-by-side diff. The diff should take
- " up the full browser window (but not more), and be static in size,
- " horizontally scrollable when the lines are too long. Otherwise, the diff
- " is pretty useless for really long lines. {{{
- if s:settings.use_css
- call append(style_start,
- \ ['<style' .. (s:html5 ? '' : 'type="text/css"') .. '>']+
- \ style+
- \ [ s:settings.use_xhtml ? '' : '<!--',
- \ 'table { table-layout: fixed; }',
- \ 'html, body, table, tbody { width: 100%; margin: 0; padding: 0; }',
- \ 'table, td, th { border: 1px solid; }',
- \ 'td { vertical-align: top; }',
- \ 'th, td { width: '..printf("%.1f",100.0/len(a:win_list))..'%; }',
- \ 'td div { overflow: auto; }',
- \ s:settings.use_xhtml ? '' : '-->',
- \ '</style>'
- \])
- endif "}}}
- endif
- endif
-
- let &paste = s:old_paste
- let &magic = s:old_magic
-endfunc "}}}
-
-" Gets a single user option and sets it in the passed-in Dict, or gives it the
-" default value if the option doesn't actually exist.
-func! tohtml#GetOption(settings, option, default) "{{{
- if exists('g:html_'..a:option)
- let a:settings[a:option] = g:html_{a:option}
- else
- let a:settings[a:option] = a:default
- endif
-endfunc "}}}
-
-" returns a Dict containing the values of all user options for 2html, including
-" default values for those not given an explicit value by the user. Discards the
-" html_ prefix of the option for nicer looking code.
-func! tohtml#GetUserSettings() "{{{
- if exists('s:settings')
- " just restore the known options if we've already retrieved them
- return s:settings
- else
- " otherwise figure out which options are set
- let user_settings = {}
-
- " Define the correct option if the old option name exists and we haven't
- " already defined the correct one.
- if exists('g:use_xhtml') && !exists("g:html_use_xhtml")
- echohl WarningMsg
- echomsg "Warning: g:use_xhtml is deprecated, use g:html_use_xhtml"
- echohl None
- let g:html_use_xhtml = g:use_xhtml
- endif
-
- " get current option settings with appropriate defaults {{{
- call tohtml#GetOption(user_settings, 'no_progress', !has("statusline") )
- call tohtml#GetOption(user_settings, 'diff_one_file', 0 )
- call tohtml#GetOption(user_settings, 'number_lines', &number )
- call tohtml#GetOption(user_settings, 'pre_wrap', &wrap )
- call tohtml#GetOption(user_settings, 'use_css', 1 )
- call tohtml#GetOption(user_settings, 'ignore_conceal', 0 )
- call tohtml#GetOption(user_settings, 'ignore_folding', 0 )
- call tohtml#GetOption(user_settings, 'dynamic_folds', 0 )
- call tohtml#GetOption(user_settings, 'no_foldcolumn', user_settings.ignore_folding)
- call tohtml#GetOption(user_settings, 'hover_unfold', 0 )
- call tohtml#GetOption(user_settings, 'no_pre', 0 )
- call tohtml#GetOption(user_settings, 'no_doc', 0 )
- call tohtml#GetOption(user_settings, 'no_links', 0 )
- call tohtml#GetOption(user_settings, 'no_modeline', 0 )
- call tohtml#GetOption(user_settings, 'no_invalid', 0 )
- call tohtml#GetOption(user_settings, 'whole_filler', 0 )
- call tohtml#GetOption(user_settings, 'use_xhtml', 0 )
- call tohtml#GetOption(user_settings, 'line_ids', user_settings.number_lines )
- call tohtml#GetOption(user_settings, 'use_input_for_pc', 'none')
- " }}}
-
- " override those settings that need it {{{
-
- " hover opening implies dynamic folding
- if user_settings.hover_unfold
- let user_settings.dynamic_folds = 1
- endif
-
- " ignore folding overrides dynamic folding
- if user_settings.ignore_folding && user_settings.dynamic_folds
- let user_settings.dynamic_folds = 0
- let user_settings.hover_unfold = 0
- endif
-
- " dynamic folding with no foldcolumn implies hover opens
- if user_settings.dynamic_folds && user_settings.no_foldcolumn
- let user_settings.hover_unfold = 1
- endif
-
- " dynamic folding implies css
- if user_settings.dynamic_folds
- let user_settings.use_css = 1
- else
- let user_settings.no_foldcolumn = 1 " won't do anything but for consistency and for the test suite
- endif
-
- " if we're not using CSS we cannot use a pre section because <font> tags
- " aren't allowed inside a <pre> block
- if !user_settings.use_css
- let user_settings.no_pre = 1
- endif
-
- " pre_wrap doesn't do anything if not using pre or not using CSS
- if user_settings.no_pre || !user_settings.use_css
- let user_settings.pre_wrap = 0
- endif
- "}}}
-
- " set up expand_tabs option after all the overrides so we know the
- " appropriate defaults {{{
- if user_settings.no_pre == 0
- call tohtml#GetOption(user_settings,
- \ 'expand_tabs',
- \ &expandtab || &ts != 8 || (exists("+vts") && &vts != '') || user_settings.number_lines ||
- \ (user_settings.dynamic_folds && !user_settings.no_foldcolumn))
- else
- let user_settings.expand_tabs = 1
- endif
- " }}}
-
- " textual options
- if exists("g:html_use_encoding") "{{{
- " user specified the desired MIME charset, figure out proper
- " 'fileencoding' from it or warn the user if we cannot
- let user_settings.encoding = g:html_use_encoding
- let user_settings.vim_encoding = tohtml#EncodingFromCharset(g:html_use_encoding)
- if user_settings.vim_encoding == ''
- echohl WarningMsg
- echomsg "TOhtml: file encoding for"
- \ g:html_use_encoding
- \ "unknown, please set 'fileencoding'"
- echohl None
- endif
- else
- " Figure out proper MIME charset from 'fileencoding' if possible
- if &l:fileencoding != ''
- " If the buffer is not a "normal" type, the 'fileencoding' value may not
- " be trusted; since the buffer should not be written the fileencoding is
- " not intended to be used.
- if &l:buftype=='' || &l:buftype==?'help'
- let user_settings.vim_encoding = &l:fileencoding
- call tohtml#CharsetFromEncoding(user_settings)
- else
- let user_settings.encoding = '' " trigger detection using &encoding
- endif
- endif
-
- " else from 'encoding' if possible
- if &l:fileencoding == '' || user_settings.encoding == ''
- let user_settings.vim_encoding = &encoding
- call tohtml#CharsetFromEncoding(user_settings)
- endif
-
- " else default to UTF-8 and warn user
- if user_settings.encoding == ''
- let user_settings.vim_encoding = 'utf-8'
- let user_settings.encoding = 'UTF-8'
- echohl WarningMsg
- echomsg "TOhtml: couldn't determine MIME charset, using UTF-8"
- echohl None
- endif
- endif "}}}
-
- " Default to making nothing uncopyable, because we default to
- " not-standards way of doing things, and also because Microsoft Word and
- " others paste the <input> elements anyway.
- "
- " html_prevent_copy only has an effect when using CSS.
- "
- " All options:
- " f - fold column
- " n - line numbers (also within fold text)
- " t - fold text
- " d - diff filler
- " c - concealed text (reserved future)
- " l - listchars (reserved possible future)
- " s - signs (reserved possible future)
- "
- " Normal text is always selectable.
- let user_settings.prevent_copy = ""
- if user_settings.use_css
- if exists("g:html_prevent_copy")
- if user_settings.dynamic_folds && !user_settings.no_foldcolumn && g:html_prevent_copy =~# 'f'
- let user_settings.prevent_copy ..= 'f'
- endif
- if user_settings.number_lines && g:html_prevent_copy =~# 'n'
- let user_settings.prevent_copy ..= 'n'
- endif
- if &diff && g:html_prevent_copy =~# 'd'
- let user_settings.prevent_copy ..= 'd'
- endif
- if !user_settings.ignore_folding && g:html_prevent_copy =~# 't'
- let user_settings.prevent_copy ..= 't'
- endif
- else
- let user_settings.prevent_copy = ""
- endif
- endif
- if empty(user_settings.prevent_copy)
- let user_settings.no_invalid = 0
- endif
-
- " enforce valid values for use_input_for_pc
- if user_settings.use_input_for_pc !~# 'fallback\|none\|all'
- let user_settings.use_input_for_pc = 'none'
- echohl WarningMsg
- echomsg '2html: "' .. g:html_use_input_for_pc .. '" is not valid for g:html_use_input_for_pc'
- echomsg '2html: defaulting to "' .. user_settings.use_input_for_pc .. '"'
- echohl None
- sleep 3
- endif
-
- if exists('g:html_id_expr')
- let user_settings.id_suffix = eval(g:html_id_expr)
- if user_settings.id_suffix !~ '^[-_:.A-Za-z0-9]*$'
- echohl WarningMsg
- echomsg '2html: g:html_id_expr evaluated to invalid string for HTML id attributes'
- echomsg '2html: Omitting user-specified suffix'
- echohl None
- sleep 3
- let user_settings.id_suffix=""
- endif
- else
- let user_settings.id_suffix=""
- endif
-
- " TODO: font
-
- return user_settings
- endif
-endfunc "}}}
-
-" get the proper HTML charset name from a Vim encoding option.
-function! tohtml#CharsetFromEncoding(settings) "{{{
- let l:vim_encoding = a:settings.vim_encoding
- if exists('g:html_charset_override') && has_key(g:html_charset_override, l:vim_encoding)
- let a:settings.encoding = g:html_charset_override[l:vim_encoding]
- else
- if l:vim_encoding =~ '^8bit\|^2byte'
- " 8bit- and 2byte- prefixes are to indicate encodings available on the
- " system that Vim will convert with iconv(), look up just the encoding name,
- " not Vim's prefix.
- let l:vim_encoding = substitute(l:vim_encoding, '^8bit-\|^2byte-', '', '')
- endif
- if has_key(g:tohtml#encoding_to_charset, l:vim_encoding)
- let a:settings.encoding = g:tohtml#encoding_to_charset[l:vim_encoding]
- else
- let a:settings.encoding = ""
- endif
- endif
- if a:settings.encoding != ""
- let l:vim_encoding = tohtml#EncodingFromCharset(a:settings.encoding)
- if l:vim_encoding != ""
- " if the Vim encoding to HTML encoding conversion is set up (by default or
- " by the user) to convert to a different encoding, we need to also change
- " the Vim encoding of the new buffer
- let a:settings.vim_encoding = l:vim_encoding
- endif
- endif
-endfun "}}}
-
-" Get the proper Vim encoding option setting from an HTML charset name.
-function! tohtml#EncodingFromCharset(encoding) "{{{
- if exists('g:html_encoding_override') && has_key(g:html_encoding_override, a:encoding)
- return g:html_encoding_override[a:encoding]
- elseif has_key(g:tohtml#charset_to_encoding, tolower(a:encoding))
- return g:tohtml#charset_to_encoding[tolower(a:encoding)]
- else
- return ""
- endif
-endfun "}}}
-
-let &cpo = s:cpo_sav
-unlet s:cpo_sav
-
-" Make sure any patches will probably use consistent indent
-" vim: ts=8 sw=2 sts=2 noet fdm=marker
diff --git a/runtime/autoload/zip.vim b/runtime/autoload/zip.vim
index e61293c357..c0034f8a7a 100644
--- a/runtime/autoload/zip.vim
+++ b/runtime/autoload/zip.vim
@@ -2,7 +2,8 @@
" AUTOLOAD PORTION
" Date: Mar 12, 2023
" Version: 33
-" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E Campbell
" License: Vim License (see vim's :help license)
" Copyright: Copyright (C) 2005-2019 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
diff --git a/runtime/colors/blue.vim b/runtime/colors/blue.vim
index aa99bacd3b..d6931e4c71 100644
--- a/runtime/colors/blue.vim
+++ b/runtime/colors/blue.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer Steven Vertigan <steven@vertigan.wattle.id.au>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:41:44 MSK
+" Last Updated: Mon 08 Jan 2024 09:42:49 AM AEDT
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'blue'
let s:t_Co = &t_Co
@@ -80,8 +81,8 @@ hi Underlined guifg=NONE guibg=NONE gui=underline ctermfg=NONE ctermbg=NONE cter
hi Label guifg=#ffd700 guibg=NONE gui=NONE cterm=NONE
hi! link Terminal Normal
hi! link Debug Special
-hi! link diffAdded String
-hi! link diffRemoved WarningMsg
+hi! link Added String
+hi! link Removed WarningMsg
hi! link diffOnly WarningMsg
hi! link diffNoEOL WarningMsg
hi! link diffIsA WarningMsg
@@ -190,8 +191,8 @@ if s:t_Co >= 256
hi Label ctermfg=220 ctermbg=NONE cterm=NONE
hi! link Terminal Normal
hi! link Debug Special
- hi! link diffAdded String
- hi! link diffRemoved WarningMsg
+ hi! link Added String
+ hi! link Removed WarningMsg
hi! link diffOnly WarningMsg
hi! link diffNoEOL WarningMsg
hi! link diffIsA WarningMsg
@@ -303,8 +304,8 @@ if s:t_Co >= 16
hi Label ctermfg=yellow ctermbg=NONE cterm=NONE
hi! link Terminal Normal
hi! link Debug Special
- hi! link diffAdded String
- hi! link diffRemoved WarningMsg
+ hi! link Added String
+ hi! link Removed WarningMsg
hi! link diffOnly WarningMsg
hi! link diffNoEOL WarningMsg
hi! link diffIsA WarningMsg
@@ -415,8 +416,8 @@ if s:t_Co >= 8
hi Label ctermfg=yellow ctermbg=NONE cterm=NONE
hi! link Terminal Normal
hi! link Debug Special
- hi! link diffAdded String
- hi! link diffRemoved WarningMsg
+ hi! link Added String
+ hi! link Removed WarningMsg
hi! link diffOnly WarningMsg
hi! link diffNoEOL WarningMsg
hi! link diffIsA WarningMsg
@@ -587,4 +588,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/darkblue.vim b/runtime/colors/darkblue.vim
index c7bba4471e..471b8561fb 100644
--- a/runtime/colors/darkblue.vim
+++ b/runtime/colors/darkblue.vim
@@ -4,13 +4,14 @@
" Maintainer: Original author Bohdan Vlasyuk <bohdan@vstu.edu.ua>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:40:36 MSK
+" Last Updated: Mon 08 Jan 2024 09:43:03 AM AEDT
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'darkblue'
let s:t_Co = &t_Co
@@ -58,8 +59,8 @@ hi! link Structure Type
hi! link Tag Special
hi! link Typedef Type
hi! link Debug Special
-hi! link diffAdded String
-hi! link diffRemoved WarningMsg
+hi! link Added String
+hi! link Removed WarningMsg
hi! link diffOnly WarningMsg
hi! link diffNoEOL WarningMsg
hi! link diffIsA WarningMsg
@@ -166,8 +167,8 @@ if s:t_Co >= 256
hi! link Tag Special
hi! link Typedef Type
hi! link Debug Special
- hi! link diffAdded String
- hi! link diffRemoved WarningMsg
+ hi! link Added String
+ hi! link Removed WarningMsg
hi! link diffOnly WarningMsg
hi! link diffNoEOL WarningMsg
hi! link diffIsA WarningMsg
@@ -471,4 +472,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/default.vim b/runtime/colors/default.vim
index d2960fa78b..8ee18a4ec4 100644
--- a/runtime/colors/default.vim
+++ b/runtime/colors/default.vim
@@ -1,15 +1,8 @@
-" Vim color file
-" Maintainer: The Vim Project <https://github.com/vim/vim>
-" Last Change: 2023 Aug 10
-" Former Maintainer: Bram Moolenaar <Bram@vim.org>
+" Neovim color file
+" Maintainer: The Neovim Project <https://github.com/neovim/neovim>
+" Last Change: 2023 Dec 01
-" This is the default color scheme. It doesn't define the Normal
-" highlighting, it uses whatever the colors used to be.
-
-" Set 'background' back to the default. The value can't always be estimated
-" and is then guessed.
-hi clear Normal
-set bg&
+" This is the default color scheme. See `:help dev_theme`.
" Remove all existing highlighting and set the defaults.
hi clear
diff --git a/runtime/colors/delek.vim b/runtime/colors/delek.vim
index d9db90f2c5..1919526760 100644
--- a/runtime/colors/delek.vim
+++ b/runtime/colors/delek.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer David Schweikert <david@schweikert.ch>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Sun 04 Sep 2022 09:31:26 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:34
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=light
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'delek'
let s:t_Co = &t_Co
@@ -412,4 +413,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/desert.vim b/runtime/colors/desert.vim
index 0b56740664..453e966899 100644
--- a/runtime/colors/desert.vim
+++ b/runtime/colors/desert.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer Hans Fugal <hans@fugal.net>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:39:21 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:34
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'desert'
let s:t_Co = &t_Co
@@ -401,4 +402,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/elflord.vim b/runtime/colors/elflord.vim
index 4a33e33eec..001368861f 100644
--- a/runtime/colors/elflord.vim
+++ b/runtime/colors/elflord.vim
@@ -3,13 +3,14 @@
" Maintainer: original maintainer Ron Aaron <ron@ronware.org>
" Website: https://www.github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:44:22 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:35
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'elflord'
let s:t_Co = &t_Co
@@ -450,4 +451,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/evening.vim b/runtime/colors/evening.vim
index 70ae55aa8d..1abdd8006f 100644
--- a/runtime/colors/evening.vim
+++ b/runtime/colors/evening.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer Steven Vertigan <steven@vertigan.wattle.id.au>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Sun 04 Sep 2022 09:48:34 MSK
+" Last Updated: Mon 08 Jan 2024 09:43:27 AM AEDT
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'evening'
let s:t_Co = &t_Co
@@ -32,8 +33,8 @@ hi! link CursorIM Cursor
hi! link LineNrAbove LineNr
hi! link LineNrBelow LineNr
hi! link Debug Special
-hi! link diffAdded String
-hi! link diffRemoved WarningMsg
+hi! link Added String
+hi! link Removed WarningMsg
hi! link diffOnly WarningMsg
hi! link diffNoEOL WarningMsg
hi! link diffIsA WarningMsg
@@ -140,8 +141,8 @@ if s:t_Co >= 256
hi! link LineNrAbove LineNr
hi! link LineNrBelow LineNr
hi! link Debug Special
- hi! link diffAdded String
- hi! link diffRemoved WarningMsg
+ hi! link Added String
+ hi! link Removed WarningMsg
hi! link diffOnly WarningMsg
hi! link diffNoEOL WarningMsg
hi! link diffIsA WarningMsg
@@ -251,8 +252,8 @@ if s:t_Co >= 16
hi! link LineNrAbove LineNr
hi! link LineNrBelow LineNr
hi! link Debug Special
- hi! link diffAdded String
- hi! link diffRemoved WarningMsg
+ hi! link Added String
+ hi! link Removed WarningMsg
hi! link diffOnly WarningMsg
hi! link diffNoEOL WarningMsg
hi! link diffIsA WarningMsg
@@ -532,4 +533,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/habamax.vim b/runtime/colors/habamax.vim
index c84354ca03..66f40ab56a 100644
--- a/runtime/colors/habamax.vim
+++ b/runtime/colors/habamax.vim
@@ -4,13 +4,14 @@
" Maintainer: Maxim Kim <habamax@gmail.com>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 24 Mar 2023 20:28:06 AEDT
+" Last Updated: Mon 08 Jan 2024 09:39:53 AM AEDT
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'habamax'
let s:t_Co = &t_Co
@@ -110,8 +111,9 @@ hi Ignore guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
hi Debug guifg=#5f8787 guibg=NONE gui=NONE cterm=NONE
hi DiffAdd guifg=#dadada guibg=#5f875f gui=NONE cterm=NONE
hi DiffDelete guifg=#af875f guibg=NONE gui=NONE cterm=NONE
-hi diffAdded guifg=#87af87 guibg=NONE gui=NONE cterm=NONE
-hi diffRemoved guifg=#d75f5f guibg=NONE gui=NONE cterm=NONE
+hi Added guifg=#87af87 guibg=NONE gui=NONE cterm=NONE
+hi Changed guifg=#5f8787 guibg=NONE gui=NONE cterm=NONE
+hi Removed guifg=#d75f5f guibg=NONE gui=NONE cterm=NONE
hi diffSubname guifg=#af87af guibg=NONE gui=NONE cterm=NONE
hi DiffText guifg=#dadada guibg=#878787 gui=NONE cterm=NONE
hi DiffChange guifg=#bcbcbc guibg=#5f5f5f gui=NONE cterm=NONE
@@ -203,8 +205,9 @@ if s:t_Co >= 256
hi Debug ctermfg=66 ctermbg=NONE cterm=NONE
hi DiffAdd ctermfg=253 ctermbg=65 cterm=NONE
hi DiffDelete ctermfg=137 ctermbg=NONE cterm=NONE
- hi diffAdded ctermfg=108 ctermbg=NONE cterm=NONE
- hi diffRemoved ctermfg=167 ctermbg=NONE cterm=NONE
+ hi Added ctermfg=108 ctermbg=NONE cterm=NONE
+ hi Changed ctermfg=66 ctermbg=NONE cterm=NONE
+ hi Removed ctermfg=167 ctermbg=NONE cterm=NONE
hi diffSubname ctermfg=139 ctermbg=NONE cterm=NONE
hi DiffText ctermfg=253 ctermbg=102 cterm=NONE
hi DiffChange ctermfg=250 ctermbg=59 cterm=NONE
@@ -281,8 +284,9 @@ if s:t_Co >= 16
hi Debug ctermfg=darkcyan ctermbg=NONE cterm=NONE
hi DiffAdd ctermfg=white ctermbg=darkgreen cterm=NONE
hi DiffDelete ctermfg=darkyellow ctermbg=NONE cterm=NONE
- hi diffAdded ctermfg=darkgreen ctermbg=NONE cterm=NONE
- hi diffRemoved ctermfg=darkred ctermbg=NONE cterm=NONE
+ hi Added ctermfg=darkgreen ctermbg=NONE cterm=NONE
+ hi Changed ctermfg=darkcyan ctermbg=NONE cterm=NONE
+ hi Removed ctermfg=darkred ctermbg=NONE cterm=NONE
hi diffSubname ctermfg=darkmagenta ctermbg=NONE cterm=NONE
hi DiffText ctermfg=white ctermbg=lightgrey cterm=NONE
hi DiffChange ctermfg=white ctermbg=darkgray cterm=NONE
@@ -359,8 +363,9 @@ if s:t_Co >= 8
hi Debug ctermfg=darkcyan ctermbg=NONE cterm=NONE
hi DiffAdd ctermfg=white ctermbg=darkgreen cterm=NONE
hi DiffDelete ctermfg=darkyellow ctermbg=NONE cterm=NONE
- hi diffAdded ctermfg=darkgreen ctermbg=NONE cterm=NONE
- hi diffRemoved ctermfg=darkred ctermbg=NONE cterm=NONE
+ hi Added ctermfg=darkgreen ctermbg=NONE cterm=NONE
+ hi Changed ctermfg=darkcyan ctermbg=NONE cterm=NONE
+ hi Removed ctermfg=darkred ctermbg=NONE cterm=NONE
hi diffSubname ctermfg=darkmagenta ctermbg=NONE cterm=NONE
hi DiffText ctermfg=white ctermbg=black cterm=bold,reverse
hi DiffChange ctermfg=black ctermbg=white cterm=NONE
@@ -469,4 +474,4 @@ endif
" Color: white #dadada 253 white
" Term colors: color00 color01 color02 color03 color04 color05 color06 color07
" Term colors: color08 color09 color10 color11 color12 color13 color14 color15
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/industry.vim b/runtime/colors/industry.vim
index f09786000d..449bf3b676 100644
--- a/runtime/colors/industry.vim
+++ b/runtime/colors/industry.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer Shian Lee.
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Sun 04 Sep 2022 09:50:04 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:36
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'industry'
let s:t_Co = &t_Co
@@ -413,4 +414,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/koehler.vim b/runtime/colors/koehler.vim
index 67719123a2..8a63f91a94 100644
--- a/runtime/colors/koehler.vim
+++ b/runtime/colors/koehler.vim
@@ -3,13 +3,14 @@
" Maintainer: original maintainer Ron Aaron <ron@ronware.org>
" Website: https://www.github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:23:56 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:36
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'koehler'
let s:t_Co = &t_Co
@@ -427,4 +428,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/lunaperche.vim b/runtime/colors/lunaperche.vim
index 44c75c40cb..62538468dc 100644
--- a/runtime/colors/lunaperche.vim
+++ b/runtime/colors/lunaperche.vim
@@ -4,11 +4,12 @@
" Maintainer: Maxim Kim <habamax@gmail.com>
" Website: https://www.github.com/vim/colorschemes
" License: Vim License (see `:help license`)
-" Last Updated: Sun 26 Mar 2023 23:04:18 AEDT
+" Last Updated: Mon 08 Jan 2024 09:41:03 AM AEDT
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'lunaperche'
let s:t_Co = &t_Co
@@ -16,8 +17,24 @@ let s:t_Co = &t_Co
hi! link helpVim Title
hi! link helpHeader Title
hi! link helpHyperTextJump Underlined
+hi! link fugitiveSymbolicRef PreProc
+hi! link fugitiveHeading Statement
+hi! link fugitiveStagedHeading Statement
+hi! link fugitiveUnstagedHeading Statement
+hi! link fugitiveUntrackedHeading Statement
+hi! link fugitiveStagedModifier PreProc
+hi! link fugitiveUnstagedModifier PreProc
+hi! link fugitiveHash Constant
hi! link diffFile PreProc
hi! link markdownHeadingDelimiter Special
+hi! link rstSectionDelimiter Statement
+hi! link rstDirective PreProc
+hi! link rstHyperlinkReference Special
+hi! link rstFieldName Constant
+hi! link rstDelimiter Special
+hi! link rstInterpretedText Special
+hi! link rstCodeBlock Normal
+hi! link rstLiteralBlock rstCodeBlock
hi! link markdownUrl String
hi! link colortemplateKey Statement
hi! link xmlTagName Statement
@@ -122,10 +139,10 @@ if &background ==# 'dark'
hi WildMenu guifg=#000000 guibg=#ffd787 gui=bold cterm=bold
hi debugPC guifg=#5f87af guibg=NONE gui=reverse cterm=reverse
hi debugBreakpoint guifg=#5fafaf guibg=NONE gui=reverse cterm=reverse
- hi Cursor guifg=NONE guibg=NONE gui=reverse ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi Cursor guifg=#000000 guibg=#ffffff gui=NONE cterm=NONE
hi lCursor guifg=#ff5fff guibg=#000000 gui=reverse cterm=reverse
hi Visual guifg=#ffffff guibg=#005f87 gui=NONE cterm=NONE
- hi MatchParen guifg=#c5e7c5 guibg=#000000 gui=reverse cterm=reverse
+ hi MatchParen guifg=#ff00af guibg=NONE gui=bold cterm=bold
hi VisualNOS guifg=#000000 guibg=#5fafaf gui=NONE cterm=NONE
hi CursorLine guifg=NONE guibg=#262626 gui=NONE cterm=NONE
hi CursorColumn guifg=NONE guibg=#262626 gui=NONE cterm=NONE
@@ -152,8 +169,9 @@ if &background ==# 'dark'
hi DiffChange guifg=#c6c6c6 guibg=#5f5f5f gui=NONE cterm=NONE
hi DiffText guifg=#afffff guibg=#5f8787 gui=NONE cterm=NONE
hi DiffDelete guifg=#d78787 guibg=NONE gui=NONE cterm=NONE
- hi diffAdded guifg=#5fd75f guibg=NONE gui=NONE cterm=NONE
- hi diffRemoved guifg=#d78787 guibg=NONE gui=NONE cterm=NONE
+ hi Added guifg=#5fd75f guibg=NONE gui=NONE cterm=NONE
+ hi Changed guifg=#5fafff guibg=NONE gui=NONE cterm=NONE
+ hi Removed guifg=#d78787 guibg=NONE gui=NONE cterm=NONE
hi diffSubname guifg=#ff87ff guibg=NONE gui=NONE cterm=NONE
hi dirType guifg=#d787d7 guibg=NONE gui=NONE cterm=NONE
hi dirPermissionUser guifg=#5faf5f guibg=NONE gui=NONE cterm=NONE
@@ -216,10 +234,10 @@ else
hi WildMenu guifg=#000000 guibg=#ffd787 gui=bold cterm=bold
hi debugPC guifg=#005fd7 guibg=NONE gui=reverse cterm=reverse
hi debugBreakpoint guifg=#005f5f guibg=NONE gui=reverse cterm=reverse
- hi Cursor guifg=NONE guibg=NONE gui=reverse ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi Cursor guifg=#ffffff guibg=#000000 gui=NONE cterm=NONE
hi lCursor guifg=#ff00ff guibg=#000000 gui=reverse cterm=reverse
hi Visual guifg=#ffffff guibg=#5f87af gui=NONE cterm=NONE
- hi MatchParen guifg=NONE guibg=#c5e7c5 gui=NONE cterm=NONE
+ hi MatchParen guifg=#ff00af guibg=NONE gui=bold cterm=bold
hi VisualNOS guifg=#ffffff guibg=#008787 gui=NONE cterm=NONE
hi CursorLine guifg=NONE guibg=#eeeeee gui=NONE cterm=NONE
hi CursorColumn guifg=NONE guibg=#eeeeee gui=NONE cterm=NONE
@@ -246,8 +264,9 @@ else
hi DiffChange guifg=#000000 guibg=#d0d0d0 gui=NONE cterm=NONE
hi DiffText guifg=#000000 guibg=#5fd7d7 gui=NONE cterm=NONE
hi DiffDelete guifg=#870000 guibg=NONE gui=NONE cterm=NONE
- hi diffAdded guifg=#008700 guibg=NONE gui=NONE cterm=NONE
- hi diffRemoved guifg=#d70000 guibg=NONE gui=NONE cterm=NONE
+ hi Added guifg=#008700 guibg=NONE gui=NONE cterm=NONE
+ hi Changed guifg=#005fd7 guibg=NONE gui=NONE cterm=NONE
+ hi Removed guifg=#d70000 guibg=NONE gui=NONE cterm=NONE
hi diffSubname guifg=#af00af guibg=NONE gui=NONE cterm=NONE
hi dirType guifg=#005f5f guibg=NONE gui=NONE cterm=NONE
hi dirPermissionUser guifg=#af5f00 guibg=NONE gui=NONE cterm=NONE
@@ -270,8 +289,24 @@ if s:t_Co >= 256
hi! link helpVim Title
hi! link helpHeader Title
hi! link helpHyperTextJump Underlined
+ hi! link fugitiveSymbolicRef PreProc
+ hi! link fugitiveHeading Statement
+ hi! link fugitiveStagedHeading Statement
+ hi! link fugitiveUnstagedHeading Statement
+ hi! link fugitiveUntrackedHeading Statement
+ hi! link fugitiveStagedModifier PreProc
+ hi! link fugitiveUnstagedModifier PreProc
+ hi! link fugitiveHash Constant
hi! link diffFile PreProc
hi! link markdownHeadingDelimiter Special
+ hi! link rstSectionDelimiter Statement
+ hi! link rstDirective PreProc
+ hi! link rstHyperlinkReference Special
+ hi! link rstFieldName Constant
+ hi! link rstDelimiter Special
+ hi! link rstInterpretedText Special
+ hi! link rstCodeBlock Normal
+ hi! link rstLiteralBlock rstCodeBlock
hi! link markdownUrl String
hi! link colortemplateKey Statement
hi! link xmlTagName Statement
@@ -370,7 +405,7 @@ if s:t_Co >= 256
hi debugPC ctermfg=67 ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=73 ctermbg=NONE cterm=reverse
hi Visual ctermfg=231 ctermbg=24 cterm=NONE
- hi MatchParen ctermfg=30 ctermbg=16 cterm=reverse
+ hi MatchParen ctermfg=199 ctermbg=NONE cterm=bold
hi VisualNOS ctermfg=16 ctermbg=73 cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=235 cterm=NONE
hi CursorColumn ctermfg=NONE ctermbg=235 cterm=NONE
@@ -397,8 +432,9 @@ if s:t_Co >= 256
hi DiffChange ctermfg=251 ctermbg=59 cterm=NONE
hi DiffText ctermfg=159 ctermbg=66 cterm=NONE
hi DiffDelete ctermfg=174 ctermbg=NONE cterm=NONE
- hi diffAdded ctermfg=77 ctermbg=NONE cterm=NONE
- hi diffRemoved ctermfg=174 ctermbg=NONE cterm=NONE
+ hi Added ctermfg=77 ctermbg=NONE cterm=NONE
+ hi Changed ctermfg=75 ctermbg=NONE cterm=NONE
+ hi Removed ctermfg=174 ctermbg=NONE cterm=NONE
hi diffSubname ctermfg=213 ctermbg=NONE cterm=NONE
hi dirType ctermfg=176 ctermbg=NONE cterm=NONE
hi dirPermissionUser ctermfg=71 ctermbg=NONE cterm=NONE
@@ -455,7 +491,7 @@ if s:t_Co >= 256
hi debugPC ctermfg=26 ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=23 ctermbg=NONE cterm=reverse
hi Visual ctermfg=231 ctermbg=67 cterm=NONE
- hi MatchParen ctermfg=30 ctermbg=231 cterm=reverse
+ hi MatchParen ctermfg=199 ctermbg=NONE cterm=bold
hi VisualNOS ctermfg=231 ctermbg=30 cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=255 cterm=NONE
hi CursorColumn ctermfg=NONE ctermbg=255 cterm=NONE
@@ -482,8 +518,9 @@ if s:t_Co >= 256
hi DiffChange ctermfg=16 ctermbg=252 cterm=NONE
hi DiffText ctermfg=16 ctermbg=80 cterm=NONE
hi DiffDelete ctermfg=88 ctermbg=NONE cterm=NONE
- hi diffAdded ctermfg=28 ctermbg=NONE cterm=NONE
- hi diffRemoved ctermfg=160 ctermbg=NONE cterm=NONE
+ hi Added ctermfg=28 ctermbg=NONE cterm=NONE
+ hi Changed ctermfg=26 ctermbg=NONE cterm=NONE
+ hi Removed ctermfg=160 ctermbg=NONE cterm=NONE
hi diffSubname ctermfg=127 ctermbg=NONE cterm=NONE
hi dirType ctermfg=23 ctermbg=NONE cterm=NONE
hi dirPermissionUser ctermfg=130 ctermbg=NONE cterm=NONE
@@ -545,8 +582,7 @@ if s:t_Co >= 16
hi WildMenu ctermfg=black ctermbg=yellow cterm=bold
hi debugPC ctermfg=darkblue ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=darkcyan ctermbg=NONE cterm=reverse
- hi Visual ctermfg=white ctermbg=darkblue cterm=NONE
- hi MatchParen ctermfg=darkcyan ctermbg=black cterm=reverse
+ hi MatchParen ctermfg=NONE ctermbg=NONE cterm=bold,underline
hi VisualNOS ctermfg=black ctermbg=darkcyan cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=NONE cterm=underline
hi CursorColumn ctermfg=black ctermbg=yellow cterm=NONE
@@ -573,8 +609,9 @@ if s:t_Co >= 16
hi DiffChange ctermfg=white ctermbg=darkgreen cterm=NONE
hi DiffText ctermfg=black ctermbg=cyan cterm=NONE
hi DiffDelete ctermfg=darkred ctermbg=NONE cterm=NONE
- hi diffAdded ctermfg=green ctermbg=NONE cterm=NONE
- hi diffRemoved ctermfg=darkred ctermbg=NONE cterm=NONE
+ hi Added ctermfg=green ctermbg=NONE cterm=NONE
+ hi Changed ctermfg=blue ctermbg=NONE cterm=NONE
+ hi Removed ctermfg=darkred ctermbg=NONE cterm=NONE
hi diffSubname ctermfg=magenta ctermbg=NONE cterm=NONE
hi dirType ctermfg=darkmagenta ctermbg=NONE cterm=NONE
hi dirPermissionUser ctermfg=darkgreen ctermbg=NONE cterm=NONE
@@ -631,7 +668,7 @@ if s:t_Co >= 16
hi debugPC ctermfg=darkblue ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=darkcyan ctermbg=NONE cterm=reverse
hi Visual ctermfg=white ctermbg=darkblue cterm=NONE
- hi MatchParen ctermfg=darkcyan ctermbg=white cterm=reverse
+ hi MatchParen ctermfg=NONE ctermbg=NONE cterm=bold,underline
hi VisualNOS ctermfg=black ctermbg=cyan cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=NONE cterm=underline
hi CursorColumn ctermfg=black ctermbg=yellow cterm=NONE
@@ -658,8 +695,9 @@ if s:t_Co >= 16
hi DiffChange ctermfg=black ctermbg=lightgray cterm=NONE
hi DiffText ctermfg=black ctermbg=cyan cterm=NONE
hi DiffDelete ctermfg=darkred ctermbg=NONE cterm=NONE
- hi diffAdded ctermfg=darkgreen ctermbg=NONE cterm=NONE
- hi diffRemoved ctermfg=red ctermbg=NONE cterm=NONE
+ hi Added ctermfg=darkgreen ctermbg=NONE cterm=NONE
+ hi Changed ctermfg=darkblue ctermbg=NONE cterm=NONE
+ hi Removed ctermfg=red ctermbg=NONE cterm=NONE
hi diffSubname ctermfg=darkmagenta ctermbg=NONE cterm=NONE
hi dirType ctermfg=darkcyan ctermbg=NONE cterm=NONE
hi dirPermissionUser ctermfg=darkyellow ctermbg=NONE cterm=NONE
@@ -722,7 +760,7 @@ if s:t_Co >= 8
hi debugPC ctermfg=darkblue ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=darkcyan ctermbg=NONE cterm=reverse
hi Visual ctermfg=NONE ctermbg=NONE cterm=reverse
- hi MatchParen ctermfg=darkcyan ctermbg=black cterm=reverse
+ hi MatchParen ctermfg=magenta ctermbg=NONE cterm=bold
hi VisualNOS ctermfg=black ctermbg=darkcyan cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=NONE cterm=underline
hi CursorColumn ctermfg=black ctermbg=darkyellow cterm=NONE
@@ -789,7 +827,7 @@ if s:t_Co >= 8
hi debugPC ctermfg=darkblue ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=darkcyan ctermbg=NONE cterm=reverse
hi Visual ctermfg=NONE ctermbg=NONE cterm=reverse
- hi MatchParen ctermfg=darkcyan ctermbg=grey cterm=reverse
+ hi MatchParen ctermfg=magenta ctermbg=NONE cterm=bold
hi VisualNOS ctermfg=black ctermbg=darkcyan cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=NONE cterm=underline
hi CursorColumn ctermfg=black ctermbg=darkyellow cterm=NONE
@@ -914,7 +952,7 @@ endif
" Color: colorC #FFFFFF 231 white
" Color: colorlC #FF5FFF 207 magenta
" Color: colorV #005F87 24 darkblue
-" Color: colorMP #C5E7C5 30 darkcyan
+" Color: colorMP #ff00af 199 magenta
" Color: colorPMenuSel #4e4e4e 239 darkcyan
" Color: colorDim #878787 102 grey
" Color: diffAdd #875f87 96 darkmagenta
@@ -949,7 +987,7 @@ endif
" Color: colorC #000000 16 black
" Color: colorlC #FF00FF 201 magenta
" Color: colorV #5F87AF 67 darkblue
-" Color: colorMP #C5E7C5 30 darkcyan
+" Color: colorMP #ff00af 199 magenta
" Color: colorPMenuSel #C6C6C6 251 darkcyan
" Color: colorDim #626262 241 darkgrey
" Color: diffAdd #D7AFD7 182 darkmagenta
@@ -960,4 +998,4 @@ endif
" Term colors: color00 color01 color02 color03 color04 color05 color06 color07
" Term colors: color08 color09 color10 color11 color12 color13 color14 color15
" Background: any
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/morning.vim b/runtime/colors/morning.vim
index 5c6a617137..12f1efe9a6 100644
--- a/runtime/colors/morning.vim
+++ b/runtime/colors/morning.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer Bram Moolenaar <Bram@vim.org>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:46:24 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:37
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=light
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'morning'
let s:t_Co = &t_Co
@@ -404,4 +405,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/murphy.vim b/runtime/colors/murphy.vim
index 47d7dbe22e..c1612fbc0e 100644
--- a/runtime/colors/murphy.vim
+++ b/runtime/colors/murphy.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer Ron Aaron <ron@ronware.org>.
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:47:20 MSK
+" Last Updated: Mon 08 Jan 2024 09:50:15 AM AEDT
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'murphy'
let s:t_Co = &t_Co
@@ -32,6 +33,7 @@ hi! link StatusLineTerm StatusLine
hi! link StatusLineTermNC StatusLineNC
hi! link MessageWindow Pmenu
hi! link PopupNotification Todo
+hi! link Added Constant
hi Normal guifg=#87ff87 guibg=#000000 gui=NONE cterm=NONE
hi EndOfBuffer guifg=#0000ff guibg=#000000 gui=NONE cterm=NONE
hi StatusLine guifg=#ffffff guibg=#00008b gui=NONE cterm=NONE
@@ -104,6 +106,7 @@ if s:t_Co >= 256
hi! link StatusLineTermNC StatusLineNC
hi! link MessageWindow Pmenu
hi! link PopupNotification Todo
+ hi! link Added Constant
hi Normal ctermfg=120 ctermbg=16 cterm=NONE
hi EndOfBuffer ctermfg=21 ctermbg=16 cterm=NONE
hi StatusLine ctermfg=231 ctermbg=18 cterm=NONE
@@ -398,4 +401,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/pablo.vim b/runtime/colors/pablo.vim
index 8766cc4776..f53739bc6d 100644
--- a/runtime/colors/pablo.vim
+++ b/runtime/colors/pablo.vim
@@ -3,13 +3,14 @@
" Maintainer: Original maintainerRon Aaron <ron@ronware.org>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Wed 14 Sep 2022 19:05:27 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:38
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'pablo'
let s:t_Co = &t_Co
@@ -431,4 +432,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/peachpuff.vim b/runtime/colors/peachpuff.vim
index 0bab72dace..f4c1e21697 100644
--- a/runtime/colors/peachpuff.vim
+++ b/runtime/colors/peachpuff.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer David Ne\v{c}as (Yeti) <yeti@physics.muni.cz>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:50:02 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:39
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=light
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'peachpuff'
let s:t_Co = &t_Co
@@ -409,4 +410,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/quiet.vim b/runtime/colors/quiet.vim
index 9ab313b837..d7f8582888 100644
--- a/runtime/colors/quiet.vim
+++ b/runtime/colors/quiet.vim
@@ -4,11 +4,12 @@
" Maintainer: Maxence Weynans <neutaaaaan@gmail.com>
" Website: https://github.com/vim/colorschemes
" License: Vim License (see `:help license`)`
-" Last Updated: Wed 15 Mar 2023 06:45:06 PM CET
+" Last Updated: Fri 15 Dec 2023 20:05:39
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'quiet'
let s:t_Co = &t_Co
@@ -750,4 +751,4 @@ endif
" Term colors: light0 light1 light2 light3 light4 light5 light6 light7
" Term colors: light8 light9 light10 light11 light12 light13 light14 light15
" Background: any
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/retrobox.vim b/runtime/colors/retrobox.vim
index c0c4f9f6c2..b4a194d885 100644
--- a/runtime/colors/retrobox.vim
+++ b/runtime/colors/retrobox.vim
@@ -4,11 +4,12 @@
" Maintainer: Maxim Kim <habamax@gmail.com>, ported from gruvbox8 of Lifepillar <lifepillar@lifepillar.me>
" Website: https://www.github.com/vim/colorschemes
" License: Vim License (see `:help license`)
-" Last Updated: Sun 12 Mar 2023 15:14:04 AEDT
+" Last Updated: Fri 15 Dec 2023 20:05:40
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'retrobox'
let s:t_Co = &t_Co
@@ -65,7 +66,7 @@ if &background ==# 'dark'
hi WildMenu guifg=#83a598 guibg=#504945 gui=bold cterm=bold
hi EndOfBuffer guifg=#504945 guibg=NONE gui=NONE cterm=NONE
hi Conceal guifg=#83a598 guibg=NONE gui=NONE cterm=NONE
- hi Cursor guifg=NONE guibg=NONE gui=reverse ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi Cursor guifg=#1c1c1c guibg=#fbf1c7 gui=NONE cterm=NONE
hi DiffAdd guifg=#b8bb26 guibg=#1c1c1c gui=reverse cterm=reverse
hi DiffChange guifg=#8ec07c guibg=#1c1c1c gui=reverse cterm=reverse
hi DiffDelete guifg=#fb4934 guibg=#1c1c1c gui=reverse cterm=reverse
@@ -116,7 +117,7 @@ if &background ==# 'dark'
hi Type guifg=#fabd2f guibg=NONE gui=NONE cterm=NONE
hi Typedef guifg=#fabd2f guibg=NONE gui=NONE cterm=NONE
hi Underlined guifg=#83a598 guibg=NONE gui=underline cterm=underline
- hi CursorIM guifg=NONE guibg=NONE gui=reverse ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi CursorIM guifg=#1c1c1c guibg=#fbf1c7 gui=NONE cterm=NONE
else
" Light background
if (has('termguicolors') && &termguicolors) || has('gui_running')
@@ -160,7 +161,7 @@ else
hi WildMenu guifg=#076678 guibg=#e5d4b1 gui=bold cterm=bold
hi EndOfBuffer guifg=#e5d4b1 guibg=NONE gui=NONE cterm=NONE
hi Conceal guifg=#076678 guibg=NONE gui=NONE cterm=NONE
- hi Cursor guifg=NONE guibg=NONE gui=reverse ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi Cursor guifg=#fbf1c7 guibg=#282828 gui=NONE cterm=NONE
hi DiffAdd guifg=#79740e guibg=#fbf1c7 gui=reverse cterm=reverse
hi DiffChange guifg=#427b58 guibg=#fbf1c7 gui=reverse cterm=reverse
hi DiffDelete guifg=#9d0006 guibg=#fbf1c7 gui=reverse cterm=reverse
@@ -211,7 +212,7 @@ else
hi Type guifg=#b57614 guibg=NONE gui=NONE cterm=NONE
hi Typedef guifg=#b57614 guibg=NONE gui=NONE cterm=NONE
hi Underlined guifg=#076678 guibg=NONE gui=underline cterm=underline
- hi CursorIM guifg=NONE guibg=NONE gui=reverse ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi CursorIM guifg=#fbf1c7 guibg=#282828 gui=NONE cterm=NONE
endif
if s:t_Co >= 256
@@ -250,7 +251,7 @@ if s:t_Co >= 256
hi WildMenu ctermfg=109 ctermbg=239 cterm=bold
hi EndOfBuffer ctermfg=239 ctermbg=NONE cterm=NONE
hi Conceal ctermfg=109 ctermbg=NONE cterm=NONE
- hi Cursor ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi Cursor ctermfg=234 ctermbg=230 cterm=NONE
hi DiffAdd ctermfg=142 ctermbg=234 cterm=reverse
hi DiffChange ctermfg=107 ctermbg=234 cterm=reverse
hi DiffDelete ctermfg=203 ctermbg=234 cterm=reverse
@@ -301,7 +302,7 @@ if s:t_Co >= 256
hi Type ctermfg=214 ctermbg=NONE cterm=NONE
hi Typedef ctermfg=214 ctermbg=NONE cterm=NONE
hi Underlined ctermfg=109 ctermbg=NONE cterm=underline
- hi CursorIM ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi CursorIM ctermfg=234 ctermbg=230 cterm=NONE
else
" Light background
hi Normal ctermfg=237 ctermbg=230 cterm=NONE
@@ -338,7 +339,7 @@ if s:t_Co >= 256
hi WildMenu ctermfg=23 ctermbg=188 cterm=bold
hi EndOfBuffer ctermfg=188 ctermbg=NONE cterm=NONE
hi Conceal ctermfg=23 ctermbg=NONE cterm=NONE
- hi Cursor ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi Cursor ctermfg=230 ctermbg=235 cterm=NONE
hi DiffAdd ctermfg=64 ctermbg=230 cterm=reverse
hi DiffChange ctermfg=29 ctermbg=230 cterm=reverse
hi DiffDelete ctermfg=124 ctermbg=230 cterm=reverse
@@ -389,7 +390,7 @@ if s:t_Co >= 256
hi Type ctermfg=172 ctermbg=NONE cterm=NONE
hi Typedef ctermfg=172 ctermbg=NONE cterm=NONE
hi Underlined ctermfg=23 ctermbg=NONE cterm=underline
- hi CursorIM ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi CursorIM ctermfg=230 ctermbg=235 cterm=NONE
endif
unlet s:t_Co
finish
@@ -431,7 +432,7 @@ if s:t_Co >= 16
hi WildMenu ctermfg=White ctermbg=Black cterm=bold
hi EndOfBuffer ctermfg=DarkGray ctermbg=NONE cterm=NONE
hi Conceal ctermfg=Blue ctermbg=NONE cterm=NONE
- hi Cursor ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi Cursor ctermfg=Black ctermbg=White cterm=NONE
hi DiffAdd ctermfg=Green ctermbg=Black cterm=reverse
hi DiffChange ctermfg=Cyan ctermbg=Black cterm=reverse
hi DiffDelete ctermfg=Red ctermbg=Black cterm=reverse
@@ -482,7 +483,7 @@ if s:t_Co >= 16
hi Type ctermfg=Yellow ctermbg=NONE cterm=NONE
hi Typedef ctermfg=Yellow ctermbg=NONE cterm=NONE
hi Underlined ctermfg=Blue ctermbg=NONE cterm=underline
- hi CursorIM ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi CursorIM ctermfg=Black ctermbg=White cterm=NONE
else
" Light background
hi Normal ctermfg=Black ctermbg=White cterm=NONE
@@ -519,7 +520,7 @@ if s:t_Co >= 16
hi WildMenu ctermfg=Black ctermbg=White cterm=bold
hi EndOfBuffer ctermfg=Grey ctermbg=NONE cterm=NONE
hi Conceal ctermfg=Blue ctermbg=NONE cterm=NONE
- hi Cursor ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi Cursor ctermfg=White ctermbg=DarkGray cterm=NONE
hi DiffAdd ctermfg=Green ctermbg=White cterm=reverse
hi DiffChange ctermfg=Cyan ctermbg=White cterm=reverse
hi DiffDelete ctermfg=Red ctermbg=White cterm=reverse
@@ -570,7 +571,7 @@ if s:t_Co >= 16
hi Type ctermfg=Yellow ctermbg=NONE cterm=NONE
hi Typedef ctermfg=Yellow ctermbg=NONE cterm=NONE
hi Underlined ctermfg=Blue ctermbg=NONE cterm=underline
- hi CursorIM ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi CursorIM ctermfg=White ctermbg=DarkGray cterm=NONE
endif
unlet s:t_Co
finish
@@ -612,7 +613,7 @@ if s:t_Co >= 8
hi WildMenu ctermfg=Blue ctermbg=DarkGray cterm=bold
hi EndOfBuffer ctermfg=NONE ctermbg=NONE cterm=NONE
hi Conceal ctermfg=Blue ctermbg=NONE cterm=NONE
- hi Cursor ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi Cursor ctermfg=Black ctermbg=White cterm=NONE
hi DiffAdd ctermfg=Green ctermbg=Black cterm=reverse
hi DiffChange ctermfg=Cyan ctermbg=Black cterm=reverse
hi DiffDelete ctermfg=Red ctermbg=Black cterm=reverse
@@ -663,7 +664,7 @@ if s:t_Co >= 8
hi Type ctermfg=Yellow ctermbg=NONE cterm=NONE
hi Typedef ctermfg=Yellow ctermbg=NONE cterm=NONE
hi Underlined ctermfg=Blue ctermbg=NONE cterm=underline
- hi CursorIM ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi CursorIM ctermfg=Black ctermbg=White cterm=NONE
else
" Light background
hi Normal ctermfg=Black ctermbg=Grey cterm=NONE
@@ -700,7 +701,7 @@ if s:t_Co >= 8
hi WildMenu ctermfg=Blue ctermbg=Grey cterm=bold
hi EndOfBuffer ctermfg=NONE ctermbg=NONE cterm=NONE
hi Conceal ctermfg=Blue ctermbg=NONE cterm=NONE
- hi Cursor ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi Cursor ctermfg=White ctermbg=DarkGray cterm=NONE
hi DiffAdd ctermfg=Green ctermbg=White cterm=reverse
hi DiffChange ctermfg=Cyan ctermbg=White cterm=reverse
hi DiffDelete ctermfg=Red ctermbg=White cterm=reverse
@@ -751,7 +752,7 @@ if s:t_Co >= 8
hi Type ctermfg=Yellow ctermbg=NONE cterm=NONE
hi Typedef ctermfg=Yellow ctermbg=NONE cterm=NONE
hi Underlined ctermfg=Blue ctermbg=NONE cterm=underline
- hi CursorIM ctermfg=NONE ctermbg=NONE cterm=reverse
+ hi CursorIM ctermfg=White ctermbg=DarkGray cterm=NONE
endif
unlet s:t_Co
finish
@@ -879,4 +880,4 @@ endif
" Term colors: fg1 neutralred neutralgreen neutralyellow neutralblue neutralpurple neutralaqua fg4
" Term colors: grey red green yellow blue purple aqua bg0
" Background: any
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/ron.vim b/runtime/colors/ron.vim
index d3a692a69f..4d55f9978f 100644
--- a/runtime/colors/ron.vim
+++ b/runtime/colors/ron.vim
@@ -3,13 +3,14 @@
" Maintainer: original maintainer Ron Aaron <ron@ronware.org>
" Website: https://www.github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:50:56 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:41
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'ron'
let s:t_Co = &t_Co
@@ -445,4 +446,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/shine.vim b/runtime/colors/shine.vim
index b30ac415d0..b4a8793589 100644
--- a/runtime/colors/shine.vim
+++ b/runtime/colors/shine.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer is Yasuhiro Matsumoto <mattn@mail.goo.ne.jp>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:51:42 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:41
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=light
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'shine'
let s:t_Co = &t_Co
@@ -417,4 +418,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/slate.vim b/runtime/colors/slate.vim
index 6da572d9a7..aab6208b26 100644
--- a/runtime/colors/slate.vim
+++ b/runtime/colors/slate.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer Ralph Amissah <ralph@amissah.com>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:52:25 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:41
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'slate'
let s:t_Co = &t_Co
@@ -432,4 +433,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/sorbet.vim b/runtime/colors/sorbet.vim
index 38cb141243..e4ef42469c 100644
--- a/runtime/colors/sorbet.vim
+++ b/runtime/colors/sorbet.vim
@@ -4,13 +4,14 @@
" Maintainer: Maxence Weynans <neutaaaaan@gmail.com>
" Website: https://github.com/vim/colorschemes
" License: Vim License (see `:help license`)`
-" Last Updated: Wed 15 Mar 2023 05:40:19 PM CET
+" Last Updated: Fri 15 Dec 2023 20:05:42
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'sorbet'
let s:t_Co = &t_Co
@@ -445,4 +446,4 @@ endif
" Color: errorred #ff5f5f 203 red
" Term colors: dark0 dark1 dark2 dark3 dark4 dark5 dark6 dark7
" Term colors: dark8 dark9 dark10 dark11 dark12 dark13 dark14 dark15
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/torte.vim b/runtime/colors/torte.vim
index bec681bb4e..36da28e596 100644
--- a/runtime/colors/torte.vim
+++ b/runtime/colors/torte.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer Thorsten Maerz <info@netztorte.de>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:53:21 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:42
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'torte'
let s:t_Co = &t_Co
@@ -424,4 +425,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/vim.lua b/runtime/colors/vim.lua
new file mode 100644
index 0000000000..5a29ba0ec6
--- /dev/null
+++ b/runtime/colors/vim.lua
@@ -0,0 +1,285 @@
+-- Name: vim
+-- Description: Vim's default color scheme
+-- Author: Bram Moolenaar <Bram@vim.org>
+-- Maintainer: The Vim Project <https://github.com/vim/vim>
+-- Website: https://github.com/vim/vim
+-- License: Same as Vim
+-- Last Updated: 2023 Aug 10
+
+-- This is Vim's default color scheme. It doesn't define the Normal
+-- highlighting, it uses whatever the colors used to be.
+
+vim.cmd.highlight('clear')
+vim.g.colors_name = 'vim'
+
+local hi = function(name, val)
+ -- Force links
+ val.force = true
+
+ -- Make sure that `cterm` attribute is not populated from `gui`
+ val.cterm = val.cterm or {}
+
+ -- Define global highlight
+ vim.api.nvim_set_hl(0, name, val)
+end
+
+--stylua: ignore start
+-- General
+hi('Normal', {})
+
+hi('Conceal', { fg = 'LightGrey', bg = 'DarkGrey', ctermfg = 'LightGrey', ctermbg = 'DarkGrey' })
+hi('Cursor', {})
+hi('lCursor', {})
+hi('DiffText', { bg = 'Red', bold = true, ctermbg = 'Red', cterm = { bold = true } })
+hi('ErrorMsg', { fg = 'White', bg = 'Red', ctermfg = 'White', ctermbg = 'DarkRed' })
+hi('IncSearch', { reverse = true, cterm = { reverse = true } })
+hi('ModeMsg', { bold = true, cterm = { bold = true } })
+hi('NonText', { fg = 'Blue', bold = true, ctermfg = 'Blue' })
+hi('PmenuSbar', { bg = 'Grey', ctermbg = 'Grey' })
+hi('StatusLine', { reverse = true, bold = true, cterm = { reverse = true, bold = true }})
+hi('StatusLineNC', { reverse = true, cterm = { reverse = true } })
+hi('TabLineFill', { reverse = true, cterm = { reverse = true } })
+hi('TabLineSel', { bold = true, cterm = { bold = true } })
+hi('TermCursor', { reverse = true, cterm = { reverse = true } })
+hi('WinBar', { bold = true, cterm = { bold = true } })
+hi('WildMenu', { fg = 'Black', bg = 'Yellow', ctermfg = 'Black', ctermbg = 'Yellow' })
+
+hi('VertSplit', { link = 'Normal' })
+hi('WinSeparator', { link = 'VertSplit' })
+hi('WinBarNC', { link = 'WinBar' })
+hi('EndOfBuffer', { link = 'NonText' })
+hi('LineNrAbove', { link = 'LineNr' })
+hi('LineNrBelow', { link = 'LineNr' })
+hi('QuickFixLine', { link = 'Search' })
+hi('CursorLineSign', { link = 'SignColumn' })
+hi('CursorLineFold', { link = 'FoldColumn' })
+hi('CurSearch', { link = 'Search' })
+hi('PmenuKind', { link = 'Pmenu' })
+hi('PmenuKindSel', { link = 'PmenuSel' })
+hi('PmenuExtra', { link = 'Pmenu' })
+hi('PmenuExtraSel', { link = 'PmenuSel' })
+hi('Substitute', { link = 'Search' })
+hi('Whitespace', { link = 'NonText' })
+hi('MsgSeparator', { link = 'StatusLine' })
+hi('NormalFloat', { link = 'Pmenu' })
+hi('FloatBorder', { link = 'WinSeparator' })
+hi('FloatTitle', { link = 'Title' })
+hi('FloatFooter', { link = 'Title' })
+
+hi('FloatShadow', { bg = 'Black', blend=80 })
+hi('FloatShadowThrough', { bg = 'Black', blend=100 })
+hi('RedrawDebugNormal', { reverse = true, cterm = { reverse = true } })
+hi('RedrawDebugClear', { bg = 'Yellow', ctermbg = 'Yellow' })
+hi('RedrawDebugComposed', { bg = 'Green', ctermbg = 'Green' })
+hi('RedrawDebugRecompose', { bg = 'Red', ctermbg = 'Red' })
+hi('Error', { fg = 'White', bg = 'Red', ctermfg = 'White', ctermbg = 'Red' })
+hi('Todo', { fg = 'Blue', bg = 'Yellow', ctermfg = 'Black', ctermbg = 'Yellow' })
+
+hi('String', { link = 'Constant' })
+hi('Character', { link = 'Constant' })
+hi('Number', { link = 'Constant' })
+hi('Boolean', { link = 'Constant' })
+hi('Float', { link = 'Number' })
+hi('Function', { link = 'Identifier' })
+hi('Conditional', { link = 'Statement' })
+hi('Repeat', { link = 'Statement' })
+hi('Label', { link = 'Statement' })
+hi('Operator', { link = 'Statement' })
+hi('Keyword', { link = 'Statement' })
+hi('Exception', { link = 'Statement' })
+hi('Include', { link = 'PreProc' })
+hi('Define', { link = 'PreProc' })
+hi('Macro', { link = 'PreProc' })
+hi('PreCondit', { link = 'PreProc' })
+hi('StorageClass', { link = 'Type' })
+hi('Structure', { link = 'Type' })
+hi('Typedef', { link = 'Type' })
+hi('Tag', { link = 'Special' })
+hi('SpecialChar', { link = 'Special' })
+hi('Delimiter', { link = 'Special' })
+hi('SpecialComment', { link = 'Special' })
+hi('Debug', { link = 'Special' })
+
+hi('DiagnosticError', { fg = 'Red', ctermfg = 1 })
+hi('DiagnosticWarn', { fg = 'Orange', ctermfg = 3 })
+hi('DiagnosticInfo', { fg = 'LightBlue', ctermfg = 4 })
+hi('DiagnosticHint', { fg = 'LightGrey', ctermfg = 7 })
+hi('DiagnosticOk', { fg = 'LightGreen', ctermfg = 10 })
+hi('DiagnosticUnderlineError', { sp = 'Red', underline = true, cterm = { underline = true } })
+hi('DiagnosticUnderlineWarn', { sp = 'Orange', underline = true, cterm = { underline = true } })
+hi('DiagnosticUnderlineInfo', { sp = 'LightBlue', underline = true, cterm = { underline = true } })
+hi('DiagnosticUnderlineHint', { sp = 'LightGrey', underline = true, cterm = { underline = true } })
+hi('DiagnosticUnderlineOk', { sp = 'LightGreen', underline = true, cterm = { underline = true } })
+hi('DiagnosticVirtualTextError', { link = 'DiagnosticError' })
+hi('DiagnosticVirtualTextWarn', { link = 'DiagnosticWarn' })
+hi('DiagnosticVirtualTextInfo', { link = 'DiagnosticInfo' })
+hi('DiagnosticVirtualTextHint', { link = 'DiagnosticHint' })
+hi('DiagnosticVirtualTextOk', { link = 'DiagnosticOk' })
+hi('DiagnosticFloatingError', { link = 'DiagnosticError' })
+hi('DiagnosticFloatingWarn', { link = 'DiagnosticWarn' })
+hi('DiagnosticFloatingInfo', { link = 'DiagnosticInfo' })
+hi('DiagnosticFloatingHint', { link = 'DiagnosticHint' })
+hi('DiagnosticFloatingOk', { link = 'DiagnosticOk' })
+hi('DiagnosticSignError', { link = 'DiagnosticError' })
+hi('DiagnosticSignWarn', { link = 'DiagnosticWarn' })
+hi('DiagnosticSignInfo', { link = 'DiagnosticInfo' })
+hi('DiagnosticSignHint', { link = 'DiagnosticHint' })
+hi('DiagnosticSignOk', { link = 'DiagnosticOk' })
+hi('DiagnosticDeprecated', { sp = 'Red', strikethrough = true, cterm = { strikethrough = true } })
+
+hi('DiagnosticUnnecessary', { link = 'Comment' })
+hi('LspInlayHint', { link = 'NonText' })
+hi('SnippetTabstop', { link = 'Visual' })
+
+-- Text
+hi('@markup.raw', { link = 'Comment' })
+hi('@markup.link', { link = 'Identifier' })
+hi('@markup.heading', { link = 'Title' })
+hi('@markup.link.url', { link = 'Underlined' })
+hi('@markup.underline', { link = 'Underlined' })
+hi('@comment.todo', { link = 'Todo' })
+
+-- Miscs
+hi('@comment', { link = 'Comment' })
+hi('@punctuation', { link = 'Delimiter' })
+
+-- Constants
+hi('@constant', { link = 'Constant' })
+hi('@constant.builtin', { link = 'Special' })
+hi('@constant.macro', { link = 'Define' })
+hi('@keyword.directive', { link = 'Define' })
+hi('@string', { link = 'String' })
+hi('@string.escape', { link = 'SpecialChar' })
+hi('@string.special', { link = 'SpecialChar' })
+hi('@character', { link = 'Character' })
+hi('@character.special', { link = 'SpecialChar' })
+hi('@number', { link = 'Number' })
+hi('@boolean', { link = 'Boolean' })
+hi('@number.float', { link = 'Float' })
+
+-- Functions
+hi('@function', { link = 'Function' })
+hi('@function.builtin', { link = 'Special' })
+hi('@function.macro', { link = 'Macro' })
+hi('@variable.parameter', { link = 'Identifier' })
+hi('@function.method', { link = 'Function' })
+hi('@variable.member', { link = 'Identifier' })
+hi('@property', { link = 'Identifier' })
+hi('@constructor', { link = 'Special' })
+
+-- Keywords
+hi('@keyword.conditional', { link = 'Conditional' })
+hi('@keyword.repeat', { link = 'Repeat' })
+hi('@label', { link = 'Label' })
+hi('@operator', { link = 'Operator' })
+hi('@keyword', { link = 'Keyword' })
+hi('@keyword.exception', { link = 'Exception' })
+
+hi('@variable', { link = 'Identifier' })
+hi('@type', { link = 'Type' })
+hi('@type.definition', { link = 'Typedef' })
+hi('@keyword.storage', { link = 'StorageClass' })
+hi('@module', { link = 'Identifier' })
+hi('@keyword.import', { link = 'Include' })
+hi('@keyword.directive', { link = 'PreProc' })
+hi('@keyword.debug', { link = 'Debug' })
+hi('@tag', { link = 'Tag' })
+
+-- LSP semantic tokens
+hi('@lsp.type.class', { link = 'Structure' })
+hi('@lsp.type.comment', { link = 'Comment' })
+hi('@lsp.type.decorator', { link = 'Function' })
+hi('@lsp.type.enum', { link = 'Structure' })
+hi('@lsp.type.enumMember', { link = 'Constant' })
+hi('@lsp.type.function', { link = 'Function' })
+hi('@lsp.type.interface', { link = 'Structure' })
+hi('@lsp.type.macro', { link = 'Macro' })
+hi('@lsp.type.method', { link = 'Function' })
+hi('@lsp.type.namespace', { link = 'Structure' })
+hi('@lsp.type.parameter', { link = 'Identifier' })
+hi('@lsp.type.property', { link = 'Identifier' })
+hi('@lsp.type.struct', { link = 'Structure' })
+hi('@lsp.type.type', { link = 'Type' })
+hi('@lsp.type.typeParameter', { link = 'TypeDef' })
+hi('@lsp.type.variable', { link = 'Identifier' })
+
+if vim.o.background == 'light' then
+ -- Default colors only used with a light background.
+ hi('ColorColumn', { bg = 'LightRed', ctermbg = 'LightRed' })
+ hi('CursorColumn', { bg = 'Grey90', ctermbg = 'LightGrey' })
+ hi('CursorLine', { bg = 'Grey90', cterm = { underline = true } })
+ hi('CursorLineNr', { fg = 'Brown', bold = true, ctermfg = 'Brown', cterm = { underline = true } })
+ hi('DiffAdd', { bg = 'LightBlue', ctermbg = 'LightBlue' })
+ hi('DiffChange', { bg = 'LightMagenta', ctermbg = 'LightMagenta' })
+ hi('DiffDelete', { fg = 'Blue', bg = 'LightCyan', bold = true, ctermfg = 'Blue', ctermbg = 'LightCyan' })
+ hi('Directory', { fg = 'Blue', ctermfg = 'DarkBlue' })
+ hi('FoldColumn', { fg = 'DarkBlue', bg = 'Grey', ctermfg = 'DarkBlue', ctermbg = 'Grey' })
+ hi('Folded', { fg = 'DarkBlue', bg = 'LightGrey', ctermfg = 'DarkBlue', ctermbg = 'Grey' })
+ hi('LineNr', { fg = 'Brown', ctermfg = 'Brown' })
+ hi('MatchParen', { bg = 'Cyan', ctermbg = 'Cyan' })
+ hi('MoreMsg', { fg = 'SeaGreen', bold = true, ctermfg = 'DarkGreen' })
+ hi('Pmenu', { bg = 'LightMagenta', ctermfg = 'Black', ctermbg = 'LightMagenta' })
+ hi('PmenuSel', { bg = 'Grey', ctermfg = 'Black', ctermbg = 'LightGrey' })
+ hi('PmenuThumb', { bg = 'Black', ctermbg = 'Black' })
+ hi('Question', { fg = 'SeaGreen', bold = true, ctermfg = 'DarkGreen' })
+ hi('Search', { bg = 'Yellow', ctermbg = 'Yellow' })
+ hi('SignColumn', { fg = 'DarkBlue', bg = 'Grey', ctermfg = 'DarkBlue', ctermbg = 'Grey' })
+ hi('SpecialKey', { fg = 'Blue', ctermfg = 'DarkBlue' })
+ hi('SpellBad', { sp = 'Red', undercurl = true, ctermbg = 'LightRed' })
+ hi('SpellCap', { sp = 'Blue', undercurl = true, ctermbg = 'LightBlue' })
+ hi('SpellLocal', { sp = 'DarkCyan', undercurl = true, ctermbg = 'Cyan' })
+ hi('SpellRare', { sp = 'Magenta', undercurl = true, ctermbg = 'LightMagenta' })
+ hi('TabLine', { bg = 'LightGrey', underline = true, ctermfg = 'Black', ctermbg = 'LightGrey', cterm = { underline = true } })
+ hi('Title', { fg = 'Magenta', bold = true, ctermfg = 'DarkMagenta' })
+ hi('Visual', { fg = 'Black', bg = 'LightGrey', ctermfg = 'Black', ctermbg = 'Grey' })
+ hi('WarningMsg', { fg = 'Red', ctermfg = 'DarkRed' })
+ hi('Comment', { fg = 'Blue', ctermfg = 'DarkBlue' })
+ hi('Constant', { fg = 'Magenta', ctermfg = 'DarkRed' })
+ hi('Special', { fg = '#6a5acd', ctermfg = 'DarkMagenta' })
+ hi('Identifier', { fg = 'DarkCyan', ctermfg = 'DarkCyan' })
+ hi('Statement', { fg = 'Brown', bold = true, ctermfg = 'Brown' })
+ hi('PreProc', { fg = '#6a0dad', ctermfg = 'DarkMagenta' })
+ hi('Type', { fg = 'SeaGreen', bold = true, ctermfg = 'DarkGreen' })
+ hi('Underlined', { fg = 'SlateBlue', underline = true, ctermfg = 'DarkMagenta', cterm = { underline = true } })
+ hi('Ignore', { ctermfg = 'White' })
+else
+ -- Default colors only used with a dark background.
+ hi('ColorColumn', { bg = 'DarkRed', ctermbg = 'DarkRed' })
+ hi('CursorColumn', { bg = 'Grey40', ctermbg = 'DarkGrey' })
+ hi('CursorLine', { bg = 'Grey40', cterm = { underline = true } })
+ hi('CursorLineNr', { fg = 'Yellow', bold = true, ctermfg = 'Yellow', cterm = { underline = true } })
+ hi('DiffAdd', { bg = 'DarkBlue', ctermbg = 'DarkBlue' })
+ hi('DiffChange', { bg = 'DarkMagenta', ctermbg = 'DarkMagenta' })
+ hi('DiffDelete', { fg = 'Blue', bg = 'DarkCyan', bold = true, ctermfg = 'Blue', ctermbg = 'DarkCyan' })
+ hi('Directory', { fg = 'Cyan', ctermfg = 'LightCyan' })
+ hi('FoldColumn', { fg = 'Cyan', bg = 'Grey', ctermfg = 'Cyan', ctermbg = 'DarkGrey' })
+ hi('Folded', { fg = 'Cyan', bg = 'DarkGrey', ctermfg = 'Cyan', ctermbg = 'DarkGrey' })
+ hi('LineNr', { fg = 'Yellow', ctermfg = 'Yellow' })
+ hi('MatchParen', { bg = 'DarkCyan', ctermbg = 'DarkCyan' })
+ hi('MoreMsg', { fg = 'SeaGreen', bold = true, ctermfg = 'LightGreen' })
+ hi('Pmenu', { bg = 'Magenta', ctermfg = 'Black', ctermbg = 'Magenta' })
+ hi('PmenuSel', { bg = 'DarkGrey', ctermfg = 'DarkGrey', ctermbg = 'Black' })
+ hi('PmenuThumb', { bg = 'White', ctermbg = 'White' })
+ hi('Question', { fg = 'Green', bold = true, ctermfg = 'LightGreen' })
+ hi('Search', { fg = 'Black', bg = 'Yellow', ctermfg = 'Black', ctermbg = 'Yellow' })
+ hi('SignColumn', { fg = 'Cyan', bg = 'Grey', ctermfg = 'Cyan', ctermbg = 'DarkGrey' })
+ hi('SpecialKey', { fg = 'Cyan', ctermfg = 'LightBlue' })
+ hi('SpellBad', { sp = 'Red', undercurl = true, ctermbg = 'Red' })
+ hi('SpellCap', { sp = 'Blue', undercurl = true, ctermbg = 'Blue' })
+ hi('SpellLocal', { sp = 'Cyan', undercurl = true, ctermbg = 'Cyan' })
+ hi('SpellRare', { sp = 'Magenta', undercurl = true, ctermbg = 'Magenta' })
+ hi('TabLine', { bg = 'DarkGrey', underline = true, ctermfg = 'White', ctermbg = 'DarkGrey', cterm = { underline = true } })
+ hi('Title', { fg = 'Magenta', bold = true, ctermfg = 'LightMagenta' })
+ hi('Visual', { fg = 'LightGrey', bg = '#575757', ctermfg = 'Black', ctermbg = 'Grey' })
+ hi('WarningMsg', { fg = 'Red', ctermfg = 'LightRed' })
+ hi('Comment', { fg = '#80a0ff', ctermfg = 'Cyan' })
+ hi('Constant', { fg = '#ffa0a0', ctermfg = 'Magenta' })
+ hi('Special', { fg = 'Orange', ctermfg = 'LightRed' })
+ hi('Identifier', { fg = '#40ffff', ctermfg = 'Cyan', cterm = { bold = true } })
+ hi('Statement', { fg = '#ffff60', bold = true, ctermfg = 'Yellow' })
+ hi('PreProc', { fg = '#ff80ff', ctermfg = 'LightBlue' })
+ hi('Type', { fg = '#60ff60', bold = true, ctermfg = 'LightGreen' })
+ hi('Underlined', { fg = '#80a0ff', underline = true, ctermfg = 'LightBlue', cterm = { underline = true } })
+ hi('Ignore', { ctermfg = 'Black' })
+end
+--stylua: ignore end
diff --git a/runtime/colors/wildcharm.vim b/runtime/colors/wildcharm.vim
index 0f95ec88bb..c47a66d148 100644
--- a/runtime/colors/wildcharm.vim
+++ b/runtime/colors/wildcharm.vim
@@ -4,11 +4,12 @@
" Maintainer: Maxim Kim <habamax@gmail.com>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Sun 12 Mar 2023 18:46:06 AEDT
+" Last Updated: Mon 08 Jan 2024 09:40:36 AM AEDT
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'wildcharm'
let s:t_Co = &t_Co
@@ -55,8 +56,8 @@ if &background ==# 'dark'
hi PmenuExtra guifg=#767676 guibg=#303030 gui=NONE cterm=NONE
hi PmenuExtraSel guifg=#000000 guibg=#ffaf00 gui=NONE cterm=NONE
hi SignColumn guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
- hi Error guifg=#ffffff guibg=#d7005f gui=NONE cterm=NONE
- hi ErrorMsg guifg=#ffffff guibg=#d7005f gui=NONE cterm=NONE
+ hi Error guifg=#d7005f guibg=#ffffff gui=reverse cterm=reverse
+ hi ErrorMsg guifg=#d7005f guibg=#ffffff gui=reverse cterm=reverse
hi ModeMsg guifg=NONE guibg=NONE gui=bold ctermfg=NONE ctermbg=NONE cterm=bold
hi MoreMsg guifg=#00d75f guibg=NONE gui=NONE cterm=NONE
hi Question guifg=#ff87ff guibg=NONE gui=NONE cterm=NONE
@@ -67,9 +68,9 @@ if &background ==# 'dark'
hi WildMenu guifg=#000000 guibg=#ffaf00 gui=NONE cterm=NONE
hi debugPC guifg=#0087d7 guibg=NONE gui=reverse cterm=reverse
hi debugBreakpoint guifg=#00afaf guibg=NONE gui=reverse cterm=reverse
- hi Cursor guifg=#ffffff guibg=#000000 gui=reverse cterm=reverse
- hi lCursor guifg=#ff5fff guibg=#000000 gui=reverse cterm=reverse
- hi Visual guifg=#000000 guibg=#0087d7 gui=NONE cterm=NONE
+ hi Cursor guifg=#000000 guibg=#ffffff gui=NONE cterm=NONE
+ hi lCursor guifg=#000000 guibg=#ff5fff gui=NONE cterm=NONE
+ hi Visual guifg=#0087d7 guibg=#000000 gui=reverse cterm=reverse
hi VisualNOS guifg=#000000 guibg=#00afff gui=NONE cterm=NONE
hi CursorLine guifg=NONE guibg=#262626 gui=NONE cterm=NONE
hi CursorColumn guifg=NONE guibg=#262626 gui=NONE cterm=NONE
@@ -97,8 +98,9 @@ if &background ==# 'dark'
hi DiffChange guifg=#d0d0d0 guibg=#5f5f5f gui=NONE cterm=NONE
hi DiffText guifg=#afffff guibg=#5f8787 gui=NONE cterm=NONE
hi DiffDelete guifg=#ffafaf guibg=#875f5f gui=NONE cterm=NONE
- hi diffAdded guifg=#00af5f guibg=NONE gui=NONE cterm=NONE
- hi diffRemoved guifg=#d7005f guibg=NONE gui=NONE cterm=NONE
+ hi Added guifg=#00af5f guibg=NONE gui=NONE cterm=NONE
+ hi Changed guifg=#0087d7 guibg=NONE gui=NONE cterm=NONE
+ hi Removed guifg=#d7005f guibg=NONE gui=NONE cterm=NONE
else
" Light background
if (has('termguicolors') && &termguicolors) || has('gui_running')
@@ -133,8 +135,8 @@ else
hi PmenuExtra guifg=#808080 guibg=#e4e4e4 gui=NONE cterm=NONE
hi PmenuExtraSel guifg=#ffffff guibg=#d78700 gui=NONE cterm=NONE
hi SignColumn guifg=NONE guibg=NONE gui=NONE ctermfg=NONE ctermbg=NONE cterm=NONE
- hi Error guifg=#ffffff guibg=#d70000 gui=NONE cterm=NONE
- hi ErrorMsg guifg=#ffffff guibg=#d70000 gui=NONE cterm=NONE
+ hi Error guifg=#d70000 guibg=#ffffff gui=reverse cterm=reverse
+ hi ErrorMsg guifg=#d70000 guibg=#ffffff gui=reverse cterm=reverse
hi ModeMsg guifg=NONE guibg=NONE gui=bold ctermfg=NONE ctermbg=NONE cterm=bold
hi MoreMsg guifg=#008700 guibg=NONE gui=NONE cterm=NONE
hi Question guifg=#870087 guibg=NONE gui=NONE cterm=NONE
@@ -145,9 +147,9 @@ else
hi WildMenu guifg=#ffffff guibg=#d78700 gui=NONE cterm=NONE
hi debugPC guifg=#005faf guibg=NONE gui=reverse cterm=reverse
hi debugBreakpoint guifg=#008787 guibg=NONE gui=reverse cterm=reverse
- hi Cursor guifg=#000000 guibg=#ffffff gui=reverse cterm=reverse
- hi lCursor guifg=#ff00ff guibg=#000000 gui=reverse cterm=reverse
- hi Visual guifg=#ffffff guibg=#0087d7 gui=NONE cterm=NONE
+ hi Cursor guifg=#ffffff guibg=#000000 gui=NONE cterm=NONE
+ hi lCursor guifg=#000000 guibg=#ff00ff gui=NONE cterm=NONE
+ hi Visual guifg=#0087d7 guibg=#ffffff gui=reverse cterm=reverse
hi VisualNOS guifg=#ffffff guibg=#005faf gui=NONE cterm=NONE
hi CursorLine guifg=NONE guibg=#eeeeee gui=NONE cterm=NONE
hi CursorColumn guifg=NONE guibg=#eeeeee gui=NONE cterm=NONE
@@ -175,8 +177,9 @@ else
hi DiffChange guifg=#262626 guibg=#dadada gui=NONE cterm=NONE
hi DiffText guifg=#005f5f guibg=#afd7d7 gui=NONE cterm=NONE
hi DiffDelete guifg=#875f5f guibg=#ffd7d7 gui=NONE cterm=NONE
- hi diffAdded guifg=#008700 guibg=NONE gui=NONE cterm=NONE
- hi diffRemoved guifg=#d70000 guibg=NONE gui=NONE cterm=NONE
+ hi Added guifg=#5faf5f guibg=NONE gui=NONE cterm=NONE
+ hi Changed guifg=#0087d7 guibg=NONE gui=NONE cterm=NONE
+ hi Removed guifg=#d70000 guibg=NONE gui=NONE cterm=NONE
endif
if s:t_Co >= 256
@@ -215,8 +218,8 @@ if s:t_Co >= 256
hi PmenuExtra ctermfg=243 ctermbg=236 cterm=NONE
hi PmenuExtraSel ctermfg=16 ctermbg=214 cterm=NONE
hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE
- hi Error ctermfg=231 ctermbg=161 cterm=NONE
- hi ErrorMsg ctermfg=231 ctermbg=161 cterm=NONE
+ hi Error ctermfg=161 ctermbg=231 cterm=reverse
+ hi ErrorMsg ctermfg=161 ctermbg=231 cterm=reverse
hi ModeMsg ctermfg=NONE ctermbg=NONE cterm=bold
hi MoreMsg ctermfg=41 ctermbg=NONE cterm=NONE
hi Question ctermfg=213 ctermbg=NONE cterm=NONE
@@ -227,7 +230,7 @@ if s:t_Co >= 256
hi WildMenu ctermfg=16 ctermbg=214 cterm=NONE
hi debugPC ctermfg=32 ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=37 ctermbg=NONE cterm=reverse
- hi Visual ctermfg=16 ctermbg=32 cterm=NONE
+ hi Visual ctermfg=32 ctermbg=16 cterm=reverse
hi VisualNOS ctermfg=16 ctermbg=39 cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=235 cterm=NONE
hi CursorColumn ctermfg=NONE ctermbg=235 cterm=NONE
@@ -255,8 +258,9 @@ if s:t_Co >= 256
hi DiffChange ctermfg=252 ctermbg=59 cterm=NONE
hi DiffText ctermfg=159 ctermbg=66 cterm=NONE
hi DiffDelete ctermfg=217 ctermbg=95 cterm=NONE
- hi diffAdded ctermfg=35 ctermbg=NONE cterm=NONE
- hi diffRemoved ctermfg=161 ctermbg=NONE cterm=NONE
+ hi Added ctermfg=35 ctermbg=NONE cterm=NONE
+ hi Changed ctermfg=32 ctermbg=NONE cterm=NONE
+ hi Removed ctermfg=161 ctermbg=NONE cterm=NONE
else
" Light background
hi Normal ctermfg=16 ctermbg=231 cterm=NONE
@@ -284,8 +288,8 @@ if s:t_Co >= 256
hi PmenuExtra ctermfg=240 ctermbg=254 cterm=NONE
hi PmenuExtraSel ctermfg=231 ctermbg=172 cterm=NONE
hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE
- hi Error ctermfg=231 ctermbg=160 cterm=NONE
- hi ErrorMsg ctermfg=231 ctermbg=160 cterm=NONE
+ hi Error ctermfg=160 ctermbg=231 cterm=reverse
+ hi ErrorMsg ctermfg=160 ctermbg=231 cterm=reverse
hi ModeMsg ctermfg=NONE ctermbg=NONE cterm=bold
hi MoreMsg ctermfg=28 ctermbg=NONE cterm=NONE
hi Question ctermfg=90 ctermbg=NONE cterm=NONE
@@ -296,7 +300,7 @@ if s:t_Co >= 256
hi WildMenu ctermfg=231 ctermbg=172 cterm=NONE
hi debugPC ctermfg=25 ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=30 ctermbg=NONE cterm=reverse
- hi Visual ctermfg=231 ctermbg=32 cterm=NONE
+ hi Visual ctermfg=32 ctermbg=231 cterm=reverse
hi VisualNOS ctermfg=231 ctermbg=25 cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=255 cterm=NONE
hi CursorColumn ctermfg=NONE ctermbg=255 cterm=NONE
@@ -324,8 +328,9 @@ if s:t_Co >= 256
hi DiffChange ctermfg=235 ctermbg=253 cterm=NONE
hi DiffText ctermfg=23 ctermbg=152 cterm=NONE
hi DiffDelete ctermfg=95 ctermbg=224 cterm=NONE
- hi diffAdded ctermfg=28 ctermbg=NONE cterm=NONE
- hi diffRemoved ctermfg=160 ctermbg=NONE cterm=NONE
+ hi Added ctermfg=71 ctermbg=NONE cterm=NONE
+ hi Changed ctermfg=32 ctermbg=NONE cterm=NONE
+ hi Removed ctermfg=160 ctermbg=NONE cterm=NONE
endif
unlet s:t_Co
finish
@@ -358,8 +363,8 @@ if s:t_Co >= 16
hi PmenuExtra ctermfg=darkgrey ctermbg=grey cterm=NONE
hi PmenuExtraSel ctermfg=black ctermbg=darkyellow cterm=NONE
hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE
- hi Error ctermfg=white ctermbg=darkred cterm=NONE
- hi ErrorMsg ctermfg=white ctermbg=darkred cterm=NONE
+ hi Error ctermfg=darkred ctermbg=white cterm=reverse
+ hi ErrorMsg ctermfg=darkred ctermbg=white cterm=reverse
hi ModeMsg ctermfg=NONE ctermbg=NONE cterm=bold
hi MoreMsg ctermfg=green ctermbg=NONE cterm=NONE
hi Question ctermfg=magenta ctermbg=NONE cterm=NONE
@@ -370,7 +375,7 @@ if s:t_Co >= 16
hi WildMenu ctermfg=black ctermbg=yellow cterm=NONE
hi debugPC ctermfg=darkblue ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=darkcyan ctermbg=NONE cterm=reverse
- hi Visual ctermfg=black ctermbg=darkblue cterm=NONE
+ hi Visual ctermfg=darkblue ctermbg=black cterm=reverse
hi VisualNOS ctermfg=black ctermbg=blue cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=NONE cterm=underline
hi CursorColumn ctermfg=black ctermbg=yellow cterm=NONE
@@ -394,12 +399,13 @@ if s:t_Co >= 16
hi Directory ctermfg=blue ctermbg=NONE cterm=bold
hi Conceal ctermfg=NONE ctermbg=NONE cterm=NONE
hi Ignore ctermfg=NONE ctermbg=NONE cterm=NONE
- hi DiffAdd ctermfg=black ctermbg=darkmagenta cterm=NONE
+ hi DiffAdd ctermfg=black ctermbg=darkgreen cterm=NONE
hi DiffChange ctermfg=black ctermbg=lightgray cterm=NONE
hi DiffText ctermfg=black ctermbg=cyan cterm=NONE
hi DiffDelete ctermfg=black ctermbg=darkred cterm=NONE
- hi diffAdded ctermfg=darkgreen ctermbg=NONE cterm=NONE
- hi diffRemoved ctermfg=darkred ctermbg=NONE cterm=NONE
+ hi Added ctermfg=darkgreen ctermbg=NONE cterm=NONE
+ hi Changed ctermfg=darkblue ctermbg=NONE cterm=NONE
+ hi Removed ctermfg=darkred ctermbg=NONE cterm=NONE
else
" Light background
hi Normal ctermfg=black ctermbg=white cterm=NONE
@@ -427,8 +433,8 @@ if s:t_Co >= 16
hi PmenuExtra ctermfg=darkgrey ctermbg=grey cterm=NONE
hi PmenuExtraSel ctermfg=black ctermbg=darkyellow cterm=NONE
hi SignColumn ctermfg=NONE ctermbg=NONE cterm=NONE
- hi Error ctermfg=white ctermbg=red cterm=NONE
- hi ErrorMsg ctermfg=white ctermbg=red cterm=NONE
+ hi Error ctermfg=red ctermbg=white cterm=reverse
+ hi ErrorMsg ctermfg=red ctermbg=white cterm=reverse
hi ModeMsg ctermfg=NONE ctermbg=NONE cterm=bold
hi MoreMsg ctermfg=darkgreen ctermbg=NONE cterm=NONE
hi Question ctermfg=darkmagenta ctermbg=NONE cterm=NONE
@@ -439,7 +445,7 @@ if s:t_Co >= 16
hi WildMenu ctermfg=white ctermbg=yellow cterm=NONE
hi debugPC ctermfg=darkblue ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=darkcyan ctermbg=NONE cterm=reverse
- hi Visual ctermfg=white ctermbg=blue cterm=NONE
+ hi Visual ctermfg=blue ctermbg=white cterm=reverse
hi VisualNOS ctermfg=white ctermbg=darkblue cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=NONE cterm=underline
hi CursorColumn ctermfg=black ctermbg=yellow cterm=NONE
@@ -463,12 +469,13 @@ if s:t_Co >= 16
hi Directory ctermfg=darkblue ctermbg=NONE cterm=bold
hi Conceal ctermfg=NONE ctermbg=NONE cterm=NONE
hi Ignore ctermfg=NONE ctermbg=NONE cterm=NONE
- hi DiffAdd ctermfg=black ctermbg=darkmagenta cterm=NONE
+ hi DiffAdd ctermfg=black ctermbg=darkgreen cterm=NONE
hi DiffChange ctermfg=black ctermbg=lightgray cterm=NONE
hi DiffText ctermfg=black ctermbg=cyan cterm=NONE
hi DiffDelete ctermfg=black ctermbg=darkred cterm=NONE
- hi diffAdded ctermfg=darkgreen ctermbg=NONE cterm=NONE
- hi diffRemoved ctermfg=red ctermbg=NONE cterm=NONE
+ hi Added ctermfg=green ctermbg=NONE cterm=NONE
+ hi Changed ctermfg=blue ctermbg=NONE cterm=NONE
+ hi Removed ctermfg=red ctermbg=NONE cterm=NONE
endif
unlet s:t_Co
finish
@@ -513,12 +520,12 @@ if s:t_Co >= 8
hi WildMenu ctermfg=black ctermbg=darkyellow cterm=NONE
hi debugPC ctermfg=darkblue ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=darkcyan ctermbg=NONE cterm=reverse
- hi Visual ctermfg=black ctermbg=darkblue cterm=NONE
+ hi Visual ctermfg=darkblue ctermbg=black cterm=reverse
hi MatchParen ctermfg=NONE ctermbg=NONE cterm=bold,underline
hi VisualNOS ctermfg=black ctermbg=darkblue cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=NONE cterm=underline
hi CursorColumn ctermfg=black ctermbg=darkyellow cterm=NONE
- hi Folded ctermfg=black ctermbg=NONE cterm=bold
+ hi Folded ctermfg=grey ctermbg=NONE cterm=bold
hi ColorColumn ctermfg=black ctermbg=darkyellow cterm=NONE
hi SpellBad ctermfg=darkred ctermbg=NONE cterm=reverse
hi SpellCap ctermfg=darkcyan ctermbg=NONE cterm=reverse
@@ -527,20 +534,20 @@ if s:t_Co >= 8
hi Comment ctermfg=NONE ctermbg=NONE cterm=bold
hi Constant ctermfg=darkred ctermbg=NONE cterm=NONE
hi String ctermfg=darkgreen ctermbg=NONE cterm=NONE
- hi Identifier ctermfg=NONE ctermbg=NONE cterm=NONE
- hi Statement ctermfg=darkblue ctermbg=NONE cterm=bold
+ hi Identifier ctermfg=darkmagenta ctermbg=NONE cterm=NONE
+ hi Statement ctermfg=darkblue ctermbg=NONE cterm=NONE
hi Type ctermfg=darkyellow ctermbg=NONE cterm=NONE
hi PreProc ctermfg=darkcyan ctermbg=NONE cterm=NONE
- hi Special ctermfg=darkcyan ctermbg=NONE cterm=NONE
+ hi Special ctermfg=darkmagenta ctermbg=NONE cterm=NONE
hi Underlined ctermfg=NONE ctermbg=NONE cterm=underline
hi Title ctermfg=NONE ctermbg=NONE cterm=bold
hi Directory ctermfg=darkblue ctermbg=NONE cterm=bold
hi Conceal ctermfg=NONE ctermbg=NONE cterm=NONE
hi Ignore ctermfg=NONE ctermbg=NONE cterm=NONE
- hi DiffAdd ctermfg=black ctermbg=darkmagenta cterm=NONE
- hi DiffChange ctermfg=black ctermbg=darkcyan cterm=NONE
- hi DiffText ctermfg=black ctermbg=grey cterm=NONE
- hi DiffDelete ctermfg=darkred ctermbg=NONE cterm=NONE
+ hi DiffAdd ctermfg=black ctermbg=darkgreen cterm=NONE
+ hi DiffChange ctermfg=black ctermbg=darkblue cterm=NONE
+ hi DiffText ctermfg=black ctermbg=darkmagenta cterm=NONE
+ hi DiffDelete ctermfg=black ctermbg=darkred cterm=NONE
else
" Light background
hi Normal ctermfg=black ctermbg=grey cterm=NONE
@@ -580,7 +587,7 @@ if s:t_Co >= 8
hi WildMenu ctermfg=black ctermbg=darkyellow cterm=NONE
hi debugPC ctermfg=darkblue ctermbg=NONE cterm=reverse
hi debugBreakpoint ctermfg=darkcyan ctermbg=NONE cterm=reverse
- hi Visual ctermfg=grey ctermbg=darkblue cterm=NONE
+ hi Visual ctermfg=darkblue ctermbg=grey cterm=reverse
hi MatchParen ctermfg=NONE ctermbg=NONE cterm=bold,underline
hi VisualNOS ctermfg=black ctermbg=darkblue cterm=NONE
hi CursorLine ctermfg=NONE ctermbg=NONE cterm=underline
@@ -594,20 +601,20 @@ if s:t_Co >= 8
hi Comment ctermfg=NONE ctermbg=NONE cterm=bold
hi Constant ctermfg=darkred ctermbg=NONE cterm=NONE
hi String ctermfg=darkgreen ctermbg=NONE cterm=NONE
- hi Identifier ctermfg=NONE ctermbg=NONE cterm=NONE
- hi Statement ctermfg=darkblue ctermbg=NONE cterm=bold
+ hi Identifier ctermfg=darkmagenta ctermbg=NONE cterm=NONE
+ hi Statement ctermfg=darkblue ctermbg=NONE cterm=NONE
hi Type ctermfg=darkyellow ctermbg=NONE cterm=NONE
hi PreProc ctermfg=darkcyan ctermbg=NONE cterm=NONE
- hi Special ctermfg=darkcyan ctermbg=NONE cterm=NONE
+ hi Special ctermfg=darkmagenta ctermbg=NONE cterm=NONE
hi Underlined ctermfg=NONE ctermbg=NONE cterm=underline
hi Title ctermfg=NONE ctermbg=NONE cterm=bold
hi Directory ctermfg=darkblue ctermbg=NONE cterm=bold
hi Conceal ctermfg=NONE ctermbg=NONE cterm=NONE
hi Ignore ctermfg=NONE ctermbg=NONE cterm=NONE
- hi DiffAdd ctermfg=black ctermbg=darkmagenta cterm=NONE
- hi DiffChange ctermfg=black ctermbg=darkcyan cterm=NONE
- hi DiffText ctermfg=grey ctermbg=black cterm=NONE
- hi DiffDelete ctermfg=darkred ctermbg=NONE cterm=NONE
+ hi DiffAdd ctermfg=black ctermbg=darkgreen cterm=NONE
+ hi DiffChange ctermfg=black ctermbg=darkblue cterm=NONE
+ hi DiffText ctermfg=black ctermbg=darkmagenta cterm=NONE
+ hi DiffDelete ctermfg=black ctermbg=darkred cterm=NONE
endif
unlet s:t_Co
finish
@@ -708,7 +715,7 @@ endif
" Color: colorlC #ff5fff 207 magenta
" Color: colorDim #878787 102 grey
" Color: colorMP #ff00af 199 magenta
-" Color: diffAdd #5f875f 65 darkmagenta
+" Color: diffAdd #5f875f 65 darkgreen
" Color: diffAddFg #afffaf 157 black
" Color: diffDelete #875f5f 95 darkred
" Color: diffDeleteFg #ffafaf 217 black
@@ -747,7 +754,7 @@ endif
" Color: colorDim #626262 241 darkgrey
" Color: colorSt #5f5f5f 59 darkgrey
" Color: colorMP #ff00af 199 magenta
-" Color: diffAdd #afd7af 151 darkmagenta
+" Color: diffAdd #afd7af 151 darkgreen
" Color: diffAddFg #005f00 22 black
" Color: diffDelete #ffd7d7 224 darkred
" Color: diffDeleteFg #875f5f 95 black
@@ -758,4 +765,4 @@ endif
" Term colors: color00 color01 color02 color03 color04 color05 color06 color07
" Term colors: color08 color09 color10 color11 color12 color13 color14 color15
" Background: any
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/zaibatsu.vim b/runtime/colors/zaibatsu.vim
index e029f1451b..726843345b 100644
--- a/runtime/colors/zaibatsu.vim
+++ b/runtime/colors/zaibatsu.vim
@@ -4,13 +4,14 @@
" Maintainer: Romain Lafourcade <romainlafourcade@gmail.com>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Sun Mar 12 17:21:15 2023
+" Last Updated: Fri 15 Dec 2023 20:05:43
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=dark
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'zaibatsu'
let s:t_Co = &t_Co
@@ -564,4 +565,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/colors/zellner.vim b/runtime/colors/zellner.vim
index af48ef86dc..37f012e92d 100644
--- a/runtime/colors/zellner.vim
+++ b/runtime/colors/zellner.vim
@@ -4,13 +4,14 @@
" Maintainer: Original maintainer Ron Aaron <ron@ronware.org>
" Website: https://github.com/vim/colorschemes
" License: Same as Vim
-" Last Updated: Fri 02 Sep 2022 09:54:15 MSK
+" Last Updated: Fri 15 Dec 2023 20:05:44
-" Generated by Colortemplate v2.2.0
+" Generated by Colortemplate v2.2.3
set background=light
-hi clear
+" hi clear
+source $VIMRUNTIME/colors/vim.lua " Nvim: revert to Vim default color scheme
let g:colors_name = 'zellner'
let s:t_Co = &t_Co
@@ -412,4 +413,4 @@ endif
" Color: fgDiffB #000000 16 black
" Color: bgDiffC8 #5F87AF 67 darkblue
" Color: bgDiffD8 #AF5FAF 133 darkmagenta
-" vim: et ts=2 sw=2
+" vim: et ts=8 sw=2 sts=2
diff --git a/runtime/compiler/gm2.vim b/runtime/compiler/gm2.vim
new file mode 100644
index 0000000000..5053912200
--- /dev/null
+++ b/runtime/compiler/gm2.vim
@@ -0,0 +1,26 @@
+" Vim compiler file
+" Compiler: GNU Modula-2 Compiler
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Last Change: 2024 Jan 04
+
+if exists("current_compiler")
+ finish
+endif
+let current_compiler = "gm2"
+
+if exists(":CompilerSet") != 2 " older Vim always used :setlocal
+ command -nargs=* CompilerSet setlocal <args>
+endif
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+CompilerSet makeprg=gm2
+CompilerSet errorformat=%-G%f:%l:%c:\ error:\ compilation\ failed,
+ \%f:%l:%c:\ %trror:\ %m,
+ \%f:%l:%c:\ %tarning:\ %m,
+ \%f:%l:%c:\ %tote:\ %m,
+ \%-G%.%#
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt
index ba3b7c0915..87269ad147 100644
--- a/runtime/doc/api.txt
+++ b/runtime/doc/api.txt
@@ -579,7 +579,7 @@ created for extmark changes.
==============================================================================
Global Functions *api-global*
-nvim__get_runtime({pat}, {all}, {*opts}) *nvim__get_runtime()*
+nvim__get_runtime({pat}, {all}, {opts}) *nvim__get_runtime()*
Find files in runtime directories
Attributes: ~
@@ -700,6 +700,21 @@ nvim_chan_send({chan}, {data}) *nvim_chan_send()*
• {chan} id of the channel
• {data} data to write. 8-bit clean: can contain NUL bytes.
+nvim_complete_set({index}, {opts}) *nvim_complete_set()*
+ Set info for the completion candidate index. if the info was shown in a
+ window, then the window and buffer ids are returned for further
+ customization. If the text was not shown, an empty dict is returned.
+
+ Parameters: ~
+ • {index} the completion candidate index
+ • {opts} Optional parameters.
+ • info: (string) info text.
+
+ Return: ~
+ Dictionary containing these keys:
+ • winid: (number) floating window id
+ • bufnr: (number) buffer id in floating window
+
nvim_create_buf({listed}, {scratch}) *nvim_create_buf()*
Creates a new, empty, unnamed buffer.
@@ -751,13 +766,13 @@ nvim_del_var({name}) *nvim_del_var()*
Parameters: ~
• {name} Variable name
-nvim_echo({chunks}, {history}, {*opts}) *nvim_echo()*
+nvim_echo({chunks}, {history}, {opts}) *nvim_echo()*
Echo a message.
Parameters: ~
- • {chunks} A list of [text, hl_group] arrays, each representing a text
- chunk with specified highlight. `hl_group` element can be
- omitted for no highlight.
+ • {chunks} A list of `[text, hl_group]` arrays, each representing a
+ text chunk with specified highlight. `hl_group` element can
+ be omitted for no highlight.
• {history} if true, add to |message-history|.
• {opts} Optional parameters.
• verbose: Message was printed as a result of 'verbose'
@@ -782,7 +797,7 @@ nvim_err_writeln({str}) *nvim_err_writeln()*
See also: ~
• nvim_err_write()
-nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()*
+nvim_eval_statusline({str}, {opts}) *nvim_eval_statusline()*
Evaluates statusline string.
Attributes: ~
@@ -863,16 +878,19 @@ nvim_get_api_info() *nvim_get_api_info()*
Returns a 2-tuple (Array), where item 0 is the current channel id and item
1 is the |api-metadata| map (Dictionary).
- Return: ~
- 2-tuple [{channel-id}, {api-metadata}]
-
Attributes: ~
|api-fast|
|RPC| only
+ Return: ~
+ 2-tuple `[{channel-id}, {api-metadata}]`
+
nvim_get_chan_info({chan}) *nvim_get_chan_info()*
Gets information about a channel.
+ Parameters: ~
+ • {chan} channel_id, or 0 for current channel
+
Return: ~
Dictionary describing a channel, with these keys:
• "id" Channel id.
@@ -882,12 +900,10 @@ nvim_get_chan_info({chan}) *nvim_get_chan_info()*
• "stderr" stderr of this Nvim instance
• "socket" TCP/IP socket or named pipe
• "job" Job with communication over its stdio.
-
• "mode" How data received on the channel is interpreted.
• "bytes" Send and receive raw bytes.
• "terminal" |terminal| instance interprets ASCII sequences.
• "rpc" |RPC| communication on the channel is active.
-
• "pty" (optional) Name of pseudoterminal. On a POSIX system this is a
device path like "/dev/pts/1". If the name is unknown, the key will
still be present if a pty is used (e.g. for conpty on Windows).
@@ -919,7 +935,7 @@ nvim_get_color_map() *nvim_get_color_map()*
Return: ~
Map of color names and RGB values.
-nvim_get_context({*opts}) *nvim_get_context()*
+nvim_get_context({opts}) *nvim_get_context()*
Gets a map of the current editor state.
Parameters: ~
@@ -954,7 +970,7 @@ nvim_get_current_win() *nvim_get_current_win()*
Return: ~
Window handle
-nvim_get_hl({ns_id}, {*opts}) *nvim_get_hl()*
+nvim_get_hl({ns_id}, {opts}) *nvim_get_hl()*
Gets all or specific highlight groups in a namespace.
Note: ~
@@ -983,7 +999,7 @@ nvim_get_hl_id_by_name({name}) *nvim_get_hl_id_by_name()*
similar to |hlID()|, but allocates a new ID if not present.
-nvim_get_hl_ns({*opts}) *nvim_get_hl_ns()*
+nvim_get_hl_ns({opts}) *nvim_get_hl_ns()*
Gets the active highlight namespace.
Parameters: ~
@@ -1032,12 +1048,12 @@ nvim_get_mode() *nvim_get_mode()*
Gets the current mode. |mode()| "blocking" is true if Nvim is waiting for
input.
- Return: ~
- Dictionary { "mode": String, "blocking": Boolean }
-
Attributes: ~
|api-fast|
+ Return: ~
+ Dictionary { "mode": String, "blocking": Boolean }
+
nvim_get_proc({pid}) *nvim_get_proc()*
Gets info describing process `pid`.
@@ -1099,7 +1115,7 @@ nvim_input({keys}) *nvim_input()*
• |keycodes| like <CR> are translated, so "<" is special. To input a
literal "<", send <LT>.
• For mouse events use |nvim_input_mouse()|. The pseudokey form
- "<LeftMouse><col,row>" is deprecated since |api-level| 6.
+ `<LeftMouse><col,row>` is deprecated since |api-level| 6.
Attributes: ~
|api-fast|
@@ -1122,7 +1138,7 @@ nvim_input_mouse({button}, {action}, {modifier}, {grid}, {row}, {col})
• Currently this doesn't support "scripting" multiple mouse events by
calling it multiple times in a loop: the intermediate mouse positions
will be ignored. It should be used to implement real-time mouse input
- in a GUI. The deprecated pseudokey form ("<LeftMouse><col,row>") of
+ in a GUI. The deprecated pseudokey form (`<LeftMouse><col,row>`) of
|nvim_input()| has the same limitation.
Attributes: ~
@@ -1130,7 +1146,7 @@ nvim_input_mouse({button}, {action}, {modifier}, {grid}, {row}, {col})
Parameters: ~
• {button} Mouse button: one of "left", "right", "middle", "wheel",
- "move".
+ "move", "x1", "x2".
• {action} For ordinary buttons, one of "press", "drag", "release".
For the wheel, one of "up", "down", "left", "right".
Ignored for "move".
@@ -1230,7 +1246,9 @@ nvim_open_term({buffer}, {opts}) *nvim_open_term()*
be to the pty master end. For instance, a carriage return
is sent as a "\r", not as a "\n". |textlock| applies. It
is possible to call |nvim_chan_send()| directly in the
- callback however. ["input", term, bufnr, data]
+ callback however. `["input", term, bufnr, data]`
+ • force_crlf: (boolean, default true) Convert "\n" to
+ "\r\n".
Return: ~
Channel id, or 0 on error
@@ -1260,13 +1278,13 @@ nvim_paste({data}, {crlf}, {phase}) *nvim_paste()*
• {data} Multiline input. May be binary (containing NUL bytes).
• {crlf} Also break lines at CR and CRLF.
• {phase} -1: paste in a single call (i.e. without streaming). To
- "stream" a paste, call `nvim_paste` sequentially with these `phase` values:
+ "stream" a paste, call `nvim_paste` sequentially with these
+ `phase` values:
• 1: starts the paste (exactly once)
• 2: continues the paste (zero or more times)
• 3: ends the paste (exactly once)
Return: ~
-
• true: Client may continue pasting.
• false: Client must cancel the paste.
@@ -1429,20 +1447,20 @@ nvim_set_current_win({window}) *nvim_set_current_win()*
Parameters: ~
• {window} Window handle
-nvim_set_hl({ns_id}, {name}, {*val}) *nvim_set_hl()*
+nvim_set_hl({ns_id}, {name}, {val}) *nvim_set_hl()*
Sets a highlight group.
Note: ~
- • Unlike the `:highlight` command which can update a highlight group, this
- function completely replaces the definition. For example:
+ • Unlike the `:highlight` command which can update a highlight group,
+ this function completely replaces the definition. For example:
`nvim_set_hl(0, 'Visual', {})` will clear the highlight group
'Visual'.
- • The fg and bg keys also accept the string values `"fg"` or `"bg"` which
- act as aliases to the corresponding foreground and background values
- of the Normal group. If the Normal group has not been defined, using
- these values results in an error.
- • If `link` is used in combination with other attributes; only the `link`
- will take effect (see |:hi-link|).
+ • The fg and bg keys also accept the string values `"fg"` or `"bg"`
+ which act as aliases to the corresponding foreground and background
+ values of the Normal group. If the Normal group has not been defined,
+ using these values results in an error.
+ • If `link` is used in combination with other attributes; only the
+ `link` will take effect (see |:hi-link|).
Parameters: ~
• {ns_id} Namespace id for this highlight |nvim_create_namespace()|.
@@ -1452,9 +1470,9 @@ nvim_set_hl({ns_id}, {name}, {*val}) *nvim_set_hl()*
activate them.
• {name} Highlight group name, e.g. "ErrorMsg"
• {val} Highlight definition map, accepts the following keys:
- • fg (or foreground): color name or "#RRGGBB", see note.
- • bg (or background): color name or "#RRGGBB", see note.
- • sp (or special): color name or "#RRGGBB"
+ • fg: color name or "#RRGGBB", see note.
+ • bg: color name or "#RRGGBB", see note.
+ • sp: color name or "#RRGGBB"
• blend: integer between 0 and 100
• bold: boolean
• standout: boolean
@@ -1499,13 +1517,13 @@ nvim_set_hl_ns_fast({ns_id}) *nvim_set_hl_ns_fast()*
Parameters: ~
• {ns_id} the namespace to activate
-nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()*
+nvim_set_keymap({mode}, {lhs}, {rhs}, {opts}) *nvim_set_keymap()*
Sets a global |mapping| for the given mode.
To set a buffer-local mapping, use |nvim_buf_set_keymap()|.
Unlike |:map|, leading/trailing whitespace is accepted as part of the
- {lhs} or {rhs}. Empty {rhs} is |<Nop>|. |keycodes| are replaced as usual.
+ {lhs} or {rhs}. Empty {rhs} is <Nop>. |keycodes| are replaced as usual.
Example: >vim
call nvim_set_keymap('n', ' <NL>', '', {'nowait': v:true})
@@ -1516,14 +1534,14 @@ nvim_set_keymap({mode}, {lhs}, {rhs}, {*opts}) *nvim_set_keymap()*
<
Parameters: ~
- • {mode} Mode short-name (map command prefix: "n", "i", "v", "x", …) or
- "!" for |:map!|, or empty string for |:map|. "ia", "ca" or
+ • {mode} Mode short-name (map command prefix: "n", "i", "v", "x", …)
+ or "!" for |:map!|, or empty string for |:map|. "ia", "ca" or
"!a" for abbreviation in Insert mode, Cmdline mode, or both,
respectively
• {lhs} Left-hand-side |{lhs}| of the mapping.
• {rhs} Right-hand-side |{rhs}| of the mapping.
• {opts} Optional parameters map: Accepts all |:map-arguments| as keys
- except |<buffer>|, values are booleans (default false). Also:
+ except <buffer>, values are booleans (default false). Also:
• "noremap" disables |recursive_mapping|, like |:noremap|
• "desc" human-readable description.
• "callback" Lua function called in place of {rhs}.
@@ -1630,7 +1648,7 @@ nvim_eval({expr}) *nvim_eval()*
Return: ~
Evaluation result or expanded object
-nvim_exec2({src}, {*opts}) *nvim_exec2()*
+nvim_exec2({src}, {opts}) *nvim_exec2()*
Executes Vimscript (multiline block of Ex commands), like anonymous
|:source|.
@@ -1671,8 +1689,8 @@ nvim_parse_expression({expr}, {flags}, {highlight})
operator/space, though also yielding an error).
• "l" when needing to start parsing with lvalues for
":let" or ":for". Common flag sets:
- • "m" to parse like for ":echo".
- • "E" to parse like for "<C-r>=".
+ • "m" to parse like for `":echo"`.
+ • "E" to parse like for `"<C-r>="`.
• empty string for ":call".
• "lm" to parse for ":let".
• {highlight} If true, return value will also include "highlight" key
@@ -1683,22 +1701,20 @@ nvim_parse_expression({expr}, {flags}, {highlight})
region [start_col, end_col)).
Return: ~
-
• AST: top-level dictionary with these keys:
• "error": Dictionary with error, present only if parser saw some
error. Contains the following keys:
• "message": String, error message in printf format, translated.
Must contain exactly one "%.*s".
• "arg": String, error message argument.
-
• "len": Amount of bytes successfully parsed. With flags equal to ""
- that should be equal to the length of expr string. (“Successfully
- parsed†here means “participated in AST creationâ€, not “till the
- first errorâ€.)
+ that should be equal to the length of expr string. ("Successfully
+ parsed" here means "participated in AST creation", not "till the
+ first error".)
• "ast": AST, either nil or a dictionary with these keys:
• "type": node type, one of the value names from ExprASTNodeType
stringified without "kExprNode" prefix.
- • "start": a pair [line, column] describing where node is
+ • "start": a pair `[line, column]` describing where node is
"started" where "line" is always 0 (will not be 0 if you will be
using this API on e.g. ":let", but that is not present yet).
Both elements are Integers.
@@ -1709,7 +1725,6 @@ nvim_parse_expression({expr}, {flags}, {highlight})
is zero, one or two children, key will not be present if node
has no children. Maximum number of children may be found in
node_maxchildren array.
-
• Local values (present only for certain nodes):
• "scope": a single Integer, specifies scope for "Option" and
"PlainIdentifier" nodes. For "Option" it is one of ExprOptScope
@@ -1739,11 +1754,11 @@ nvim_parse_expression({expr}, {flags}, {highlight})
Command Functions *api-command*
*nvim_buf_create_user_command()*
-nvim_buf_create_user_command({buffer}, {name}, {command}, {*opts})
+nvim_buf_create_user_command({buffer}, {name}, {command}, {opts})
Creates a buffer-local command |user-commands|.
Parameters: ~
- • {buffer} Buffer handle, or 0 for current buffer.
+ • {buffer} Buffer handle, or 0 for current buffer.
See also: ~
• nvim_create_user_command
@@ -1759,7 +1774,7 @@ nvim_buf_del_user_command({buffer}, {name})
• {buffer} Buffer handle, or 0 for current buffer.
• {name} Name of the command to delete.
-nvim_buf_get_commands({buffer}, {*opts}) *nvim_buf_get_commands()*
+nvim_buf_get_commands({buffer}, {opts}) *nvim_buf_get_commands()*
Gets a map of buffer-local |user-commands|.
Parameters: ~
@@ -1769,7 +1784,7 @@ nvim_buf_get_commands({buffer}, {*opts}) *nvim_buf_get_commands()*
Return: ~
Map of maps describing commands.
-nvim_cmd({*cmd}, {*opts}) *nvim_cmd()*
+nvim_cmd({cmd}, {opts}) *nvim_cmd()*
Executes an Ex command.
Unlike |nvim_command()| this command takes a structured Dictionary instead
@@ -1804,7 +1819,7 @@ nvim_cmd({*cmd}, {*opts}) *nvim_cmd()*
• |nvim_command()|
*nvim_create_user_command()*
-nvim_create_user_command({name}, {command}, {*opts})
+nvim_create_user_command({name}, {command}, {opts})
Creates a global |user-commands| command.
For Lua usage see |lua-guide-commands-create|.
@@ -1824,22 +1839,21 @@ nvim_create_user_command({name}, {command}, {*opts})
argument that contains the following keys:
• name: (string) Command name
• args: (string) The args passed to the command, if any
- |<args>|
+ <args>
• fargs: (table) The args split by unescaped whitespace
- (when more than one argument is allowed), if any
- |<f-args>|
+ (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>|
+ ! modifier <bang>
• line1: (number) The starting line of the command range
- |<line1>|
+ <line1>
• line2: (number) The final line of the command range
- |<line2>|
+ <line2>
• range: (number) The number of items in the command range:
- 0, 1, or 2 |<range>|
- • count: (number) Any count supplied |<count>|
- • reg: (string) The optional register, if specified |<reg>|
- • mods: (string) Command modifiers, if any |<mods>|
+ 0, 1, or 2 <range>
+ • count: (number) Any count supplied <count>
+ • reg: (string) The optional register, if specified <reg>
+ • mods: (string) Command modifiers, if any <mods>
• smods: (table) Command modifiers in a structured format.
Has the same structure as the "mods" key of
|nvim_parse_cmd()|.
@@ -1864,7 +1878,7 @@ nvim_del_user_command({name}) *nvim_del_user_command()*
Parameters: ~
• {name} Name of the command to delete.
-nvim_get_commands({*opts}) *nvim_get_commands()*
+nvim_get_commands({opts}) *nvim_get_commands()*
Gets a map of global (non-buffer-local) Ex commands.
Currently only |user-commands| are supported, not builtin Ex commands.
@@ -1893,16 +1907,15 @@ nvim_parse_cmd({str}, {opts}) *nvim_parse_cmd()*
Return: ~
Dictionary containing command information, with these keys:
• cmd: (string) Command name.
- • range: (array) (optional) Command range (|<line1>| |<line2>|).
- Omitted if command doesn't accept a range. Otherwise, has no
- elements if no range was specified, one element if only a single
- range item was specified, or two elements if both range items were
- specified.
- • count: (number) (optional) Command |<count>|. Omitted if command
+ • range: (array) (optional) Command range (<line1> <line2>). Omitted
+ if command doesn't accept a range. Otherwise, has no elements if no
+ range was specified, one element if only a single range item was
+ specified, or two elements if both range items were specified.
+ • count: (number) (optional) Command <count>. Omitted if command
cannot take a count.
- • reg: (string) (optional) Command |<register>|. Omitted if command
+ • reg: (string) (optional) Command <register>. Omitted if command
cannot take a register.
- • bang: (boolean) Whether command contains a |<bang>| (!) modifier.
+ • bang: (boolean) Whether command contains a <bang> (!) modifier.
• args: (array) Command arguments.
• addr: (string) Value of |:command-addr|. Uses short name or "line"
for -addr=lines.
@@ -1916,13 +1929,11 @@ nvim_parse_cmd({str}, {opts}) *nvim_parse_cmd()*
• bar: (boolean) The "|" character is treated as a command separator
and the double quote character (") is treated as the start of a
comment.
-
• mods: (dictionary) |:command-modifiers|.
• filter: (dictionary) |:filter|.
• pattern: (string) Filter pattern. Empty string if there is no
filter.
• force: (boolean) Whether filter is inverted or not.
-
• silent: (boolean) |:silent|.
• emsg_silent: (boolean) |:silent!|.
• unsilent: (boolean) |:unsilent|.
@@ -1965,7 +1976,7 @@ nvim_get_all_options_info() *nvim_get_all_options_info()*
See also: ~
• |nvim_get_commands()|
-nvim_get_option_info2({name}, {*opts}) *nvim_get_option_info2()*
+nvim_get_option_info2({name}, {opts}) *nvim_get_option_info2()*
Gets the option information for one option from arbitrary buffer or window
Resulting dictionary has keys:
@@ -1999,7 +2010,7 @@ nvim_get_option_info2({name}, {*opts}) *nvim_get_option_info2()*
Return: ~
Option Information
-nvim_get_option_value({name}, {*opts}) *nvim_get_option_value()*
+nvim_get_option_value({name}, {opts}) *nvim_get_option_value()*
Gets the value of an option. The behavior of this function matches that of
|:set|: the local value of an option is returned if it exists; otherwise,
the global value is returned. Local values always correspond to the
@@ -2022,7 +2033,7 @@ nvim_get_option_value({name}, {*opts}) *nvim_get_option_value()*
Option value
*nvim_set_option_value()*
-nvim_set_option_value({name}, {value}, {*opts})
+nvim_set_option_value({name}, {value}, {opts})
Sets the value of an option. The behavior of this function matches that of
|:set|: for global-local options, both the global and local value are set
unless otherwise specified with {scope}.
@@ -2048,15 +2059,15 @@ For more information on buffers, see |buffers|.
Unloaded Buffers: ~
Buffers may be unloaded by the |:bunload| command or the buffer's
-|'bufhidden'| option. When a buffer is unloaded its file contents are
-freed from memory and vim cannot operate on the buffer lines until it is
-reloaded (usually by opening the buffer again in a new window). API
-methods such as |nvim_buf_get_lines()| and |nvim_buf_line_count()| will be
-affected.
+|'bufhidden'| option. When a buffer is unloaded its file contents are freed
+from memory and vim cannot operate on the buffer lines until it is reloaded
+(usually by opening the buffer again in a new window). API methods such as
+|nvim_buf_get_lines()| and |nvim_buf_line_count()| will be affected.
You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()| to check
whether a buffer is loaded.
+
nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
Activates buffer-update events on a channel, or as Lua callbacks.
@@ -2078,7 +2089,8 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
will be `nvim_buf_changedtick_event`. Not for Lua
callbacks.
• {opts} Optional parameters.
- • on_lines: Lua callback invoked on change. Return `true` to detach. Args:
+ • on_lines: Lua callback invoked on change. Return a
+ truthy value (not `false` or `nil`) to detach. Args:
• the string "lines"
• buffer handle
• b:changedtick
@@ -2088,10 +2100,10 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
• byte count of previous contents
• deleted_codepoints (if `utf_sizes` is true)
• deleted_codeunits (if `utf_sizes` is true)
-
• on_bytes: Lua callback invoked on change. This
callback receives more granular information about the
- change compared to on_lines. Return `true` to detach. Args:
+ change compared to on_lines. Return a truthy value
+ (not `false` or `nil`) to detach. Args:
• the string "bytes"
• buffer handle
• b:changedtick
@@ -2099,28 +2111,28 @@ nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
• start column of the changed text
• byte offset of the changed text (from the start of
the buffer)
- • old end row of the changed text
- • old end column of the changed text
+ • old end row of the changed text (offset from start
+ row)
+ • old end column of the changed text (if old end row
+ = 0, offset from start column)
• old end byte length of the changed text
- • new end row of the changed text
- • new end column of the changed text
+ • new end row of the changed text (offset from start
+ row)
+ • new end column of the changed text (if new end row
+ = 0, offset from start column)
• new end byte length of the changed text
-
• on_changedtick: Lua callback invoked on changedtick
increment without text change. Args:
• the string "changedtick"
• buffer handle
• b:changedtick
-
• on_detach: Lua callback invoked on detach. Args:
• the string "detach"
• buffer handle
-
• on_reload: Lua callback invoked on reload. The entire
buffer content should be considered changed. Args:
• the string "reload"
• buffer handle
-
• utf_sizes: include UTF-32 and UTF-16 size of the
replaced region, as args to `on_lines`.
• preview: also attach to command preview (i.e.
@@ -2156,8 +2168,7 @@ nvim_buf_call({buffer}, {fun}) *nvim_buf_call()*
only)
Return: ~
- Return value of function. NB: will deepcopy Lua values currently, use
- upvalues to send Lua references in and out.
+ Return value of function.
nvim_buf_del_keymap({buffer}, {mode}, {lhs}) *nvim_buf_del_keymap()*
Unmaps a buffer-local |mapping| for the given mode.
@@ -2235,8 +2246,8 @@ nvim_buf_get_keymap({buffer}, {mode}) *nvim_buf_get_keymap()*
Gets a list of buffer-local |mapping| definitions.
Parameters: ~
- • {mode} Mode short-name ("n", "i", "v", ...)
• {buffer} Buffer handle, or 0 for current buffer
+ • {mode} Mode short-name ("n", "i", "v", ...)
Return: ~
Array of |maparg()|-like dictionaries describing mappings. The
@@ -2375,7 +2386,7 @@ nvim_buf_line_count({buffer}) *nvim_buf_line_count()*
Line count, or 0 for unloaded buffer. |api-buffer|
*nvim_buf_set_keymap()*
-nvim_buf_set_keymap({buffer}, {mode}, {lhs}, {rhs}, {*opts})
+nvim_buf_set_keymap({buffer}, {mode}, {lhs}, {rhs}, {opts})
Sets a buffer-local |mapping| for the given mode.
Parameters: ~
@@ -2454,9 +2465,9 @@ nvim_buf_set_text({buffer}, {start_row}, {start_col}, {end_row}, {end_col},
Indexing is zero-based. Row indices are end-inclusive, and column indices
are end-exclusive.
- To insert text at a given `(row, column)` location, use `start_row =
- end_row = row` and `start_col = end_col = col`. To delete the text in a
- range, use `replacement = {}`.
+ To insert text at a given `(row, column)` location, use
+ `start_row = end_row = row` and `start_col = end_col = col`. To delete the
+ text in a range, use `replacement = {}`.
Prefer |nvim_buf_set_lines()| if you are only adding or deleting entire
lines.
@@ -2569,9 +2580,9 @@ nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id}, {opts})
0-indexed (row, col) tuple or empty list () if extmark id was absent
*nvim_buf_get_extmarks()*
-nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {*opts})
- Gets |extmarks| (including |signs|) in "traversal order" from a |charwise|
- region defined by buffer positions (inclusive, 0-indexed |api-indexing|).
+nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts})
+ Gets |extmarks| in "traversal order" from a |charwise| region defined by
+ buffer positions (inclusive, 0-indexed |api-indexing|).
Region can be given as (row,col) tuples, or valid extmark ids (whose
positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
@@ -2587,6 +2598,10 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {*opts})
the `overlap` option might be useful. Otherwise only the start position of
an extmark will be considered.
+ Note: legacy signs placed through the |:sign| commands are implemented as
+ extmarks and will show up here. Their details array will contain a
+ `sign_name` field.
+
Example: >lua
local api = vim.api
local pos = api.nvim_win_get_cursor(0)
@@ -2622,10 +2637,10 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {*opts})
"virt_text" and "virt_lines"
Return: ~
- List of [extmark_id, row, col] tuples in "traversal order".
+ List of `[extmark_id, row, col]` tuples in "traversal order".
*nvim_buf_set_extmark()*
-nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
+nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {opts})
Creates or updates an |extmark|.
By default a new extmark is created when no id is passed in, but it is
@@ -2657,7 +2672,7 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
EOL of a line, continue the highlight for the rest of the
screen line (just like for diff and cursorline highlight).
• virt_text : virtual text to link to this mark. A list of
- [text, highlight] tuples, each representing a text chunk
+ `[text, highlight]` tuples, each representing a text chunk
with specified highlight. `highlight` element can either
be a single highlight group, or an array of multiple
highlight groups that will be stacked (highest priority
@@ -2671,7 +2686,6 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
• "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 of the
screen line) instead of "virt_text_pos".
@@ -2679,6 +2693,8 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
text is selected or hidden because of scrolling with
'nowrap' or 'smoothscroll'. Currently only affects
"overlay" virt_text.
+ • virt_text_repeat_linebreak : repeat the virtual text on
+ wrapped lines.
• hl_mode : control how highlights are combined with the
highlights of the text. Currently only affects virt_text
highlights, but might affect `hl_group` in later versions.
@@ -2687,16 +2703,16 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
• "combine": combine with background text color.
• "blend": blend with background text color. Not supported
for "inline" virt_text.
-
• virt_lines : virtual lines to add next to this mark This
should be an array over lines, where each line in turn is
- an array over [text, highlight] tuples. In general, buffer
- and window options do not affect the display of the text.
- In particular 'wrap' and 'linebreak' options do not take
- effect, so the number of extra screen lines will always
- match the size of the array. However the 'tabstop' buffer
- option is still used for hard tabs. By default lines are
- placed below the buffer line containing the mark.
+ an array over `[text, highlight]` tuples. In general,
+ buffer and window options do not affect the display of the
+ text. In particular 'wrap' and 'linebreak' options do not
+ take effect, so the number of extra screen lines will
+ always match the size of the array. However the 'tabstop'
+ buffer option is still used for hard tabs. By default
+ lines are placed below the buffer line containing the
+ mark.
• virt_lines_above: place virtual lines above instead.
• virt_lines_leftcol: Place extmarks in the leftmost column
of the window, bypassing sign and number columns.
@@ -2715,30 +2731,28 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
text around the mark was deleted and then restored by
undo. Defaults to true.
• invalidate : boolean that indicates whether to hide the
- extmark if the entirety of its range is deleted. If
+ extmark if the entirety of its range is deleted. For
+ hidden marks, an "invalid" key is added to the "details"
+ array of |nvim_buf_get_extmarks()| and family. If
"undo_restore" is false, the extmark is deleted instead.
- • priority: a priority value for the highlight group or sign
- attribute. For example treesitter highlighting uses a
- value of 100.
+ • priority: a priority value for the highlight group, sign
+ attribute or virtual text. For virtual text, item with
+ highest priority is drawn last. For example treesitter
+ highlighting uses a value of 100.
• strict: boolean that indicates extmark should not be
placed if the line or column value is past the end of the
buffer or end of the line respectively. Defaults to true.
• sign_text: string of length 1-2 used to display in the
- sign column. Note: ranges are unsupported and decorations
- are only applied to start_row
+ sign column.
• sign_hl_group: name of the highlight group used to
- highlight the sign column text. Note: ranges are
- unsupported and decorations are only applied to start_row
+ highlight the sign column text.
• number_hl_group: name of the highlight group used to
- highlight the number column. Note: ranges are unsupported
- and decorations are only applied to start_row
+ highlight the number column.
• line_hl_group: name of the highlight group used to
- highlight the whole line. Note: ranges are unsupported and
- decorations are only applied to start_row
+ highlight the whole line.
• cursorline_hl_group: name of the highlight group used to
- highlight the line when the cursor is on the same line as
- the mark and 'cursorline' is enabled. Note: ranges are
- unsupported and decorations are only applied to start_row
+ highlight the sign column text when the cursor is on the
+ same line as the mark and 'cursorline' is enabled.
• conceal: string which should be either empty or a single
character. Enable concealing similar to |:syn-conceal|.
When a character is supplied it is used as |:syn-cchar|.
@@ -2750,6 +2764,11 @@ nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts})
drawn by a UI. When set, the UI will receive win_extmark
events. Note: the mark is positioned by virt_text
attributes. Can be used together with virt_text.
+ • url: A URL to associate with this extmark. In the TUI, the
+ OSC 8 control sequence is used to generate a clickable
+ hyperlink to this URL.
+ • scoped: boolean that indicates that the extmark should
+ only be displayed in the namespace scope. (experimental)
Return: ~
Id of the created/updated extmark
@@ -2777,7 +2796,7 @@ nvim_get_namespaces() *nvim_get_namespaces()*
dict that maps from names to namespace ids.
*nvim_set_decoration_provider()*
-nvim_set_decoration_provider({ns_id}, {*opts})
+nvim_set_decoration_provider({ns_id}, {opts})
Set or change decoration provider for a |namespace|
This is a very general purpose interface for having Lua callbacks being
@@ -2813,18 +2832,52 @@ nvim_set_decoration_provider({ns_id}, {*opts})
Parameters: ~
• {ns_id} Namespace id from |nvim_create_namespace()|
• {opts} Table of callbacks:
- • on_start: called first on each screen redraw ["start",
- tick]
+ • on_start: called first on each screen redraw >
+ ["start", tick]
+<
• on_buf: called for each buffer being redrawn (before window
- callbacks) ["buf", bufnr, tick]
- • on_win: called when starting to redraw a specific window.
- botline_guess is an approximation that does not exceed the
- last line number. ["win", winid, bufnr, topline,
- botline_guess]
+ callbacks) >
+ ["buf", bufnr, tick]
+<
+ • on_win: called when starting to redraw a specific window. >
+ ["win", winid, bufnr, topline, botline]
+<
• on_line: called for each buffer line being redrawn. (The
- interaction with fold lines is subject to change) ["win",
- winid, bufnr, row]
- • on_end: called at the end of a redraw cycle ["end", tick]
+ interaction with fold lines is subject to change) >
+ ["line", winid, bufnr, row]
+<
+ • on_end: called at the end of a redraw cycle >
+ ["end", tick]
+<
+
+nvim_win_add_ns({window}, {ns_id}) *nvim_win_add_ns()*
+ Adds the namespace scope to the window.
+
+ Parameters: ~
+ • {window} Window handle, or 0 for current window
+ • {ns_id} the namespace to add
+
+ Return: ~
+ true if the namespace was added, else false
+
+nvim_win_get_ns({window}) *nvim_win_get_ns()*
+ Gets all the namespaces scopes associated with a window.
+
+ Parameters: ~
+ • {window} Window handle, or 0 for current window
+
+ Return: ~
+ a list of namespaces ids
+
+nvim_win_remove_ns({window}, {ns_id}) *nvim_win_remove_ns()*
+ Removes the namespace scope from the window.
+
+ Parameters: ~
+ • {window} Window handle, or 0 for current window
+ • {ns_id} the namespace to remove
+
+ Return: ~
+ true if the namespace was removed, else false
==============================================================================
@@ -2842,8 +2895,7 @@ nvim_win_call({window}, {fun}) *nvim_win_call()*
only)
Return: ~
- Return value of function. NB: will deepcopy Lua values currently, use
- upvalues to send Lua references in and out.
+ Return value of function.
See also: ~
• |win_execute()|
@@ -3002,7 +3054,7 @@ nvim_win_set_hl_ns({window}, {ns_id}) *nvim_win_set_hl_ns()*
This takes precedence over the 'winhighlight' option.
Parameters: ~
- • {ns_id} the namespace to use
+ • {ns_id} the namespace to use
nvim_win_set_var({window}, {name}, {value}) *nvim_win_set_var()*
Sets a window-scoped (w:) variable
@@ -3020,7 +3072,7 @@ nvim_win_set_width({window}, {width}) *nvim_win_set_width()*
• {window} Window handle, or 0 for current window
• {width} Width as a count of columns
-nvim_win_text_height({window}, {*opts}) *nvim_win_text_height()*
+nvim_win_text_height({window}, {opts}) *nvim_win_text_height()*
Computes the number of screen lines occupied by a range of text in a given
window. Works for off-screen text and takes folds into account.
@@ -3056,21 +3108,31 @@ nvim_win_text_height({window}, {*opts}) *nvim_win_text_height()*
==============================================================================
-Win_Config Functions *api-win_config*
+Win_config Functions *api-win_config*
-nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
- Open a new window.
+nvim_open_win({buffer}, {enter}, {config}) *nvim_open_win()*
+ Opens a new split window, or a floating window if `relative` is specified,
+ or an external window (managed by the UI) if `external` is specified.
- Currently this is used to open floating and external windows. Floats are
- windows that are drawn above the split layout, at some anchor position in
- some other window. Floats can be drawn internally or by external GUI with
- the |ui-multigrid| extension. External windows are only supported with
- multigrid GUIs, and are displayed as separate top-level windows.
+ Floats are windows that are drawn above the split layout, at some anchor
+ position in some other window. Floats can be drawn internally or by
+ external GUI with the |ui-multigrid| extension. External windows are only
+ supported with multigrid GUIs, and are displayed as separate top-level
+ windows.
For a general overview of floats, see |api-floatwin|.
- Exactly one of `external` and `relative` must be specified. The `width`
- and `height` of the new window must be specified.
+ The `width` and `height` of the new window must be specified when opening
+ a floating window, but are optional for normal windows.
+
+ If `relative` and `external` are omitted, a normal "split" window is
+ created. The `win` property determines which window will be split. If no
+ `win` is provided or `win == 0`, a window will be created adjacent to the
+ current window. If -1 is provided, a top-level split will be created.
+ `vertical` and `split` are only valid for normal windows, and are used to
+ control split direction. For `vertical`, the exact direction is determined
+ by |'splitright'| and |'splitbelow'|. Split windows cannot have
+ `bufpos`/`row`/`col`/`border`/`title`/`footer` properties.
With relative=editor (row=0,col=0) refers to the top-left corner of the
screen-grid and (row=Lines-1,col=Columns-1) refers to the bottom-right
@@ -3091,6 +3153,12 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
Example (Lua): buffer-relative float (travels as buffer is scrolled) >lua
vim.api.nvim_open_win(0, false,
{relative='win', width=12, height=3, bufpos={100,10}})
+<
+
+ Example (Lua): vertical split left of the current window >lua
+ vim.api.nvim_open_win(0, false, {
+ split = 'left',
+ win = 0
})
<
@@ -3108,25 +3176,23 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
window.
• "cursor" Cursor position in current window.
• "mouse" Mouse position
-
- • win: |window-ID| for relative="win".
+ • win: |window-ID| window to split, or relative window when
+ creating a float (relative="win").
• anchor: Decides which corner of the float to place at
(row,col):
• "NW" northwest (default)
• "NE" northeast
• "SW" southwest
• "SE" southeast
-
• width: Window width (in character cells). Minimum of 1.
• height: Window height (in character cells). Minimum of 1.
• bufpos: Places float relative to buffer text (only when
- relative="win"). Takes a tuple of zero-indexed [line,
- column]. `row` and `col` if given are applied relative to this position, else they
- default to:
+ relative="win"). Takes a tuple of zero-indexed
+ `[line, column]`. `row` and `col` if given are applied
+ relative to this position, else they default to:
• `row=1` and `col=0` if `anchor` is "NW" or "NE"
• `row=0` and `col=0` if `anchor` is "SW" or "SE" (thus
like a tooltip near the buffer text).
-
• row: Row position in units of "screen cell height", may be
fractional.
• col: Column position in units of "screen cell width", may
@@ -3137,8 +3203,9 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
• external: GUI should display the window as an external
top-level window. Currently accepts no other positioning
configuration together with this.
- • zindex: Stacking order. floats with higher `zindex` go on top on floats with lower indices. Must be larger
- than zero. The following screen elements have hard-coded
+ • zindex: Stacking order. floats with higher `zindex` go on
+ top on floats with lower indices. Must be larger than
+ zero. The following screen elements have hard-coded
z-indices:
• 100: insert completion popupmenu
• 200: message scrollback
@@ -3146,7 +3213,6 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
wildoptions+=pum) The default value for floats are 50.
In general, values below 100 are recommended, unless
there is a good reason to overshadow builtin elements.
-
• style: (optional) Configure the appearance of the window.
Currently only supports one value:
• "minimal" Nvim will display the window with many UI
@@ -3159,14 +3225,13 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
empty. The end-of-buffer region is hidden by setting
`eob` flag of 'fillchars' to a space char, and clearing
the |hl-EndOfBuffer| region in 'winhighlight'.
-
• border: Style of (optional) window border. This can either
be a string or an array. The string values are
• "none": No border (default).
• "single": A single line box.
• "double": A double line box.
- • "rounded": Like "single", but with rounded corners ("╭"
- etc.).
+ • "rounded": Like "single", but with rounded corners
+ ("â•­" etc.).
• "solid": Adds padding by a single whitespace cell.
• "shadow": A drop shadow effect by blending with the
background.
@@ -3174,19 +3239,26 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
any divisor of eight. The array will specify the eight
chars building up the border in a clockwise fashion
starting with the top-left corner. As an example, the
- double box style could be specified as [ "â•”", "â•" ,"â•—",
- "â•‘", "â•", "â•", "╚", "â•‘" ]. If the number of chars are
- less than eight, they will be repeated. Thus an ASCII
- border could be specified as [ "/", "-", "\\", "|" ], or
- all chars the same as [ "x" ]. An empty string can be
- used to turn off a specific border, for instance, [ "",
- "", "", ">", "", "", "", "<" ] will only make vertical
- borders but not horizontal ones. By default,
- `FloatBorder` highlight is used, which links to
- `WinSeparator` when not defined. It could also be
- specified by character: [ ["+", "MyCorner"], ["x",
- "MyBorder"] ].
-
+ double box style could be specified as: >
+ [ "â•”", "â•" ,"â•—", "â•‘", "â•", "â•", "╚", "â•‘" ].
+<
+ If the number of chars are less than eight, they will be
+ repeated. Thus an ASCII border could be specified as >
+ [ "/", "-", \"\\\\\", "|" ],
+<
+ or all chars the same as >
+ [ "x" ].
+<
+ An empty string can be used to turn off a specific border,
+ for instance, >
+ [ "", "", "", ">", "", "", "", "<" ]
+<
+ will only make vertical borders but not horizontal ones.
+ By default, `FloatBorder` highlight is used, which links
+ to `WinSeparator` when not defined. It could also be
+ specified by character: >
+ [ ["+", "MyCorner"], ["x", "MyBorder"] ].
+<
• title: Title (optional) in window border, string or list.
List should consist of `[text, highlight]` tuples. If
string, the default highlight group is `FloatTitle`.
@@ -3205,6 +3277,8 @@ nvim_open_win({buffer}, {enter}, {*config}) *nvim_open_win()*
• fixed: If true when anchor is NW or SW, the float window
would be kept fixed even if the window would be truncated.
• hide: If true the floating window will be hidden.
+ • vertical: Split vertically |:vertical|.
+ • split: Split direction: "left", "right", "above", "below".
Return: ~
Window handle, or 0 on error
@@ -3222,7 +3296,7 @@ nvim_win_get_config({window}) *nvim_win_get_config()*
Return: ~
Map defining the window configuration, see |nvim_open_win()|
-nvim_win_set_config({window}, {*config}) *nvim_win_set_config()*
+nvim_win_set_config({window}, {config}) *nvim_win_set_config()*
Configures window layout. Currently only for floating and external windows
(including changing a split window to those layouts).
@@ -3302,11 +3376,18 @@ nvim_tabpage_set_var({tabpage}, {name}, {value})
• {name} Variable name
• {value} Variable value
+nvim_tabpage_set_win({tabpage}, {win}) *nvim_tabpage_set_win()*
+ Sets the current window in a tabpage
+
+ Parameters: ~
+ • {tabpage} Tabpage handle, or 0 for current tabpage
+ • {win} Window handle, must already belong to {tabpage}
+
==============================================================================
Autocmd Functions *api-autocmd*
-nvim_clear_autocmds({*opts}) *nvim_clear_autocmds()*
+nvim_clear_autocmds({opts}) *nvim_clear_autocmds()*
Clears all autocommands selected by {opts}. To delete autocmds see
|nvim_del_autocmd()|.
@@ -3316,24 +3397,21 @@ nvim_clear_autocmds({*opts}) *nvim_clear_autocmds()*
• event: "pat1"
• event: { "pat1" }
• event: { "pat1", "pat2", "pat3" }
-
• pattern: (string|table)
• pattern or patterns to match exactly.
• For example, if you have `*.py` as that pattern for the
autocmd, you must pass `*.py` exactly to clear it.
`test.py` will not match the pattern.
-
• defaults to clearing all patterns.
• NOTE: Cannot be used with {buffer}
-
• buffer: (bufnr)
• clear only |autocmd-buflocal| autocommands.
• NOTE: Cannot be used with {pattern}
-
• group: (string|int) The augroup name or id.
- • NOTE: If not passed, will only delete autocmds not in any group.
+ • NOTE: If not passed, will only delete autocmds not in any
+ group.
-nvim_create_augroup({name}, {*opts}) *nvim_create_augroup()*
+nvim_create_augroup({name}, {opts}) *nvim_create_augroup()*
Create or get an autocommand group |autocmd-groups|.
To get an existing group id, do: >lua
@@ -3354,8 +3432,10 @@ nvim_create_augroup({name}, {*opts}) *nvim_create_augroup()*
See also: ~
• |autocmd-groups|
-nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
- Creates an |autocommand| event handler, defined by `callback` (Lua function or Vimscript function name string) or `command` (Ex command string).
+nvim_create_autocmd({event}, {opts}) *nvim_create_autocmd()*
+ Creates an |autocommand| event handler, defined by `callback` (Lua
+ function or Vimscript function name string) or `command` (Ex command
+ string).
Example using Lua callback: >lua
vim.api.nvim_create_autocmd({"BufEnter", "BufWinEnter"}, {
@@ -3393,19 +3473,18 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()*
troubleshooting).
• callback (function|string) optional: Lua function (or
Vimscript function name, if string) called when the
- event(s) is triggered. Lua callback can return true to
- delete the autocommand, and receives a table argument with
- these keys:
+ event(s) is triggered. Lua callback can return a truthy
+ value (not `false` or `nil`) to delete the autocommand.
+ Receives a table argument with these keys:
• id: (number) autocommand id
• event: (string) name of the triggered event
|autocmd-events|
• group: (number|nil) autocommand group id, if any
- • match: (string) expanded value of |<amatch>|
- • buf: (number) expanded value of |<abuf>|
- • file: (string) expanded value of |<afile>|
+ • match: (string) expanded value of <amatch>
+ • buf: (number) expanded value of <abuf>
+ • file: (string) expanded value of <afile>
• data: (any) arbitrary data passed from
|nvim_exec_autocmds()|
-
• command (string) optional: Vim command to execute on event.
Cannot be used with {callback}
• once (boolean) optional: defaults to false. Run the
@@ -3455,7 +3534,7 @@ nvim_del_autocmd({id}) *nvim_del_autocmd()*
Parameters: ~
• {id} Integer Autocommand id returned by |nvim_create_autocmd()|
-nvim_exec_autocmds({event}, {*opts}) *nvim_exec_autocmds()*
+nvim_exec_autocmds({event}, {opts}) *nvim_exec_autocmds()*
Execute all autocommands for {event} that match the corresponding {opts}
|autocmd-execute|.
@@ -3469,14 +3548,14 @@ nvim_exec_autocmds({event}, {*opts}) *nvim_exec_autocmds()*
• buffer (integer) optional: buffer number
|autocmd-buflocal|. Cannot be used with {pattern}.
• modeline (bool) optional: defaults to true. Process the
- modeline after the autocommands |<nomodeline>|.
+ modeline after the autocommands <nomodeline>.
• data (any): arbitrary data to send to the autocommand
callback. See |nvim_create_autocmd()| for details.
See also: ~
• |:doautocmd|
-nvim_get_autocmds({*opts}) *nvim_get_autocmds()*
+nvim_get_autocmds({opts}) *nvim_get_autocmds()*
Get all autocommands that match the corresponding {opts}.
These examples will get autocommands matching ALL the given criteria: >lua
@@ -3590,13 +3669,12 @@ nvim_ui_pum_set_height({height}) *nvim_ui_pum_set_height()*
• {height} Popupmenu height, must be greater than zero.
nvim_ui_set_focus({gained}) *nvim_ui_set_focus()*
- Tells the nvim server if focus was gained or lost by the GUI.
+ Tells the nvim server if focus was gained or lost by the GUI
Attributes: ~
|RPC| only
nvim_ui_set_option({name}, {value}) *nvim_ui_set_option()*
- TODO: Documentation
Attributes: ~
|RPC| only
@@ -3605,7 +3683,6 @@ nvim_ui_term_event({event}, {value}) *nvim_ui_term_event()*
Tells Nvim when a terminal event has occurred
The following terminal events are supported:
-
• "termresponse": The terminal sent an OSC or DCS response sequence to
Nvim. The payload is the received response. Sets |v:termresponse| and
fires |TermResponse|.
@@ -3614,11 +3691,10 @@ nvim_ui_term_event({event}, {value}) *nvim_ui_term_event()*
|RPC| only
Parameters: ~
- • {event} Event name
- • {payload} Event payload
+ • {event} Event name
+ • {value} Event payload
nvim_ui_try_resize({width}, {height}) *nvim_ui_try_resize()*
- TODO: Documentation
Attributes: ~
|RPC| only
@@ -3638,4 +3714,5 @@ nvim_ui_try_resize_grid({grid}, {width}, {height})
• {width} The new requested width.
• {height} The new requested height.
+
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt
index c6f6559e37..8890872e1a 100644
--- a/runtime/doc/autocmd.txt
+++ b/runtime/doc/autocmd.txt
@@ -784,9 +784,6 @@ OptionSet After setting an option (except during
are not global-local it is the old local
value.
- OptionSet is not triggered on startup and for
- the 'key' option for obvious reasons.
-
Usage example: Check for the existence of the
directory in the 'backupdir' and 'undodir'
options, create the directory if it doesn't
@@ -800,6 +797,8 @@ OptionSet After setting an option (except during
Non-recursive: |:set| in the autocommand does
not trigger OptionSet again.
+ Not triggered on startup.
+
*QuickFixCmdPre*
QuickFixCmdPre Before a quickfix command is run (|:make|,
|:lmake|, |:grep|, |:lgrep|, |:grepadd|,
@@ -874,7 +873,7 @@ SafeState When nothing is pending, going to wait for the
- Command line completion is active
You can use `mode()` to find out what state
Vim is in. That may be:
- - VIsual mode
+ - Visual mode
- Normal mode
- Insert mode
- Command-line mode
@@ -986,6 +985,11 @@ TermLeave After leaving |Terminal-mode|.
TermClose When a |terminal| job ends.
Sets these |v:event| keys:
status
+ *TermRequest*
+TermRequest When a |terminal| job emits an OSC or DCS
+ sequence. Sets |v:termrequest|. When used from
+ Lua, the request string is included in the
+ "data" field of the autocommand callback.
*TermResponse*
TermResponse When Nvim receives an OSC or DCS response from
the terminal. Sets |v:termresponse|. When used
@@ -1001,10 +1005,10 @@ TermResponse When Nvim receives an OSC or DCS response from
once = true,
callback = function(args)
local resp = args.data
- local r, g, b = resp:match("\x1b%]4;1;rgb:(%w+)/(%w+)/(%w+)")
+ local r, g, b = resp:match("\027%]4;1;rgb:(%w+)/(%w+)/(%w+)")
end,
})
- io.stdout:write("\x1b]4;1;?\x1b\\")
+ io.stdout:write("\027]4;1;?\027\\")
<
*TextChanged*
TextChanged After a change was made to the text in the
diff --git a/BACKERS.md b/runtime/doc/backers.txt
index 6cfcb0b407..d0cbd94978 100644
--- a/BACKERS.md
+++ b/runtime/doc/backers.txt
@@ -1,8 +1,15 @@
-# Bountysource Backers
+*backers.txt* Nvim
-Thank you to everyone who backed our [Bountysource fundraiser](https://www.bountysource.com/teams/neovim/fundraiser)!
-### Your name and URL in BACKERS.md.
+ NVIM REFERENCE MANUAL
+
+
+==============================================================================
+Fundraiser Backers
+
+Thank you to everyone who backed the original Neovim Fundraiser.
+
+LIST OF BACKERS
- [Bob Breznak](http://brez.io)
- [Tim Uruski](http://timuruski.net)
@@ -223,7 +230,7 @@ Thank you to everyone who backed our [Bountysource fundraiser](https://www.bount
- BenBergman
- Bengt Lüers
- Benjamin Bryant
-- Bèr 'berkes' Kessels
+- Bèr "berkes" Kessels
- Bernd Homuth
- Bheesham Persaud
- Bilal Quadri
@@ -459,7 +466,7 @@ Thank you to everyone who backed our [Bountysource fundraiser](https://www.bount
- Matthias Lehmann
- Maximilian Gerlach
- Meryn Stol
-- Michael 'manveru' Fellinger
+- Michael "manveru" Fellinger
- Michael "beefsack" Alexander
- Michael Iles
- Michael Irwin/mdi
@@ -641,6 +648,9 @@ Thank you to everyone who backed our [Bountysource fundraiser](https://www.bount
- Ziling Zhao
- Zsolt Botykai
-### Anonymous Supporters
+ANONYMOUS SUPPORTERS
+
+There were also 307 other people who didn't claim any level of reward but
+contributed to the fundraiser. Thank you all for the support!
-There were also 307 other people who didn't claim any level of reward but contributed to the fundraiser. Thank you all for the support!
+vim:tw=78:ts=8:et:ft=help:norl:
diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt
index 6ffb514487..c5f3946871 100644
--- a/runtime/doc/builtin.txt
+++ b/runtime/doc/builtin.txt
@@ -802,6 +802,8 @@ complete_info([{what}]) *complete_info()*
no item is selected when using the <Up> or
<Down> keys)
inserted Inserted string. [NOT IMPLEMENTED YET]
+ preview_winid Info floating preview window id.
+ preview_bufnr Info floating preview buffer id.
*complete_info_mode*
mode values are:
@@ -963,8 +965,8 @@ ctxset({context} [, {index}]) *ctxset()*
ctxsize() *ctxsize()*
Returns the size of the |context-stack|.
-cursor({lnum}, {col} [, {off}])
-cursor({list}) *cursor()*
+cursor({lnum}, {col} [, {off}]) *cursor()*
+cursor({list})
Positions the cursor at the column (byte count) {col} in the
line {lnum}. The first column is one.
@@ -1367,6 +1369,7 @@ exists({expr}) *exists()*
echo exists("*strftime")
echo exists("*s:MyFunc")
echo exists("*MyFunc")
+ echo exists("*v:lua.Func")
echo exists("bufcount")
echo exists(":Make")
echo exists("#CursorHold")
@@ -1864,6 +1867,40 @@ foldtextresult({lnum}) *foldtextresult()*
line, "'m" mark m, etc.
Useful when exporting folded text, e.g., to HTML.
+foreach({expr1}, {expr2}) *foreach()*
+ {expr1} must be a |List|, |String|, |Blob| or |Dictionary|.
+ For each item in {expr1} execute {expr2}. {expr1} is not
+ modified; its values may be, as with |:lockvar| 1. |E741|
+ See |map()| and |filter()| to modify {expr1}.
+
+ {expr2} must be a |string| or |Funcref|.
+
+ If {expr2} is a |string|, inside {expr2} |v:val| has the value
+ of the current item. For a |Dictionary| |v:key| has the key
+ of the current item and for a |List| |v:key| has the index of
+ the current item. For a |Blob| |v:key| has the index of the
+ current byte. For a |String| |v:key| has the index of the
+ current character.
+ Examples: >vim
+ call foreach(mylist, 'let used[v:val] = v:true')
+< This records the items that are in the {expr1} list.
+
+ Note that {expr2} is the result of expression and is then used
+ as a command. Often it is good to use a |literal-string| to
+ avoid having to double backslashes.
+
+ If {expr2} is a |Funcref| it must take two arguments:
+ 1. the key or the index of the current item.
+ 2. the value of the current item.
+ With a lambda you don't get an error if it only accepts one
+ argument.
+ If the function returns a value, it is ignored.
+
+ Returns {expr1} in all cases.
+ When an error is encountered while executing {expr2} no
+ further items in {expr1} are processed.
+ When {expr2} is a Funcref errors inside a function are ignored,
+ unless it was defined with the "abort" flag.
fullcommand({name}) *fullcommand()*
Get the full command name from a short abbreviated command
@@ -2018,8 +2055,8 @@ get({func}, {what})
"args" The list with arguments
Returns zero on error.
-getbufinfo([{buf}])
-getbufinfo([{dict}]) *getbufinfo()*
+getbufinfo([{buf}]) *getbufinfo()*
+getbufinfo([{dict}])
Get information about buffers as a List of Dictionaries.
Without an argument information about all the buffers is
@@ -2042,6 +2079,8 @@ getbufinfo([{dict}]) *getbufinfo()*
bufnr Buffer number.
changed TRUE if the buffer is modified.
changedtick Number of changes made to the buffer.
+ command TRUE if the buffer belongs to the
+ command-line window |cmdwin|.
hidden TRUE if the buffer is hidden.
lastused Timestamp in seconds, like
|localtime()|, when the buffer was
@@ -2233,7 +2272,7 @@ getcharmod() *getcharmod()*
32 mouse double click
64 mouse triple click
96 mouse quadruple click (== 32 + 64)
- 128 command (Macintosh only)
+ 128 command (Mac) or super
Only the modifiers that have not been included in the
character itself are obtained. Thus Shift-a results in "A"
without a modifier. Returns 0 if no modifiers are used.
@@ -2370,6 +2409,7 @@ getcompletion({pat}, {type} [, {filtered}]) *getcompletion()*
help help subjects
highlight highlight groups
history |:history| suboptions
+ keymap keyboard mappings
locale locale names (as output of locale -a)
mapclear buffer argument
mapping mapping name
@@ -2878,6 +2918,57 @@ getreginfo([{regname}]) *getreginfo()*
If {regname} is not specified, |v:register| is used.
The returned Dictionary can be passed to |setreg()|.
+getregion({pos1}, {pos2} [, {opts}]) *getregion()*
+ Returns the list of strings from {pos1} to {pos2} from a
+ buffer.
+
+ {pos1} and {pos2} must both be |List|s with four numbers.
+ See |getpos()| for the format of the list. It's possible
+ to specify positions from a different buffer, but please
+ note the limitations at |getregion-notes|.
+
+ The optional argument {opts} is a Dict and supports the
+ following items:
+
+ type Specify the region's selection type
+ (default: "v"):
+ "v" for |charwise| mode
+ "V" for |linewise| mode
+ "<CTRL-V>" for |blockwise-visual| mode
+
+ exclusive If |TRUE|, use exclusive selection
+ for the end position
+ (default: follow 'selection')
+
+ You can get the last selection type by |visualmode()|.
+ If Visual mode is active, use |mode()| to get the Visual mode
+ (e.g., in a |:vmap|).
+ This function is useful to get text starting and ending in
+ different columns, such as a |charwise-visual| selection.
+
+ *getregion-notes*
+ Note that:
+ - Order of {pos1} and {pos2} doesn't matter, it will always
+ return content from the upper left position to the lower
+ right position.
+ - If 'virtualedit' is enabled and the region is past the end
+ of the lines, resulting lines are padded with spaces.
+ - If the region is blockwise and it starts or ends in the
+ middle of a multi-cell character, it is not included but
+ its selected part is substituted with spaces.
+ - If {pos1} and {pos2} are not in the same buffer, an empty
+ list is returned.
+ - {pos1} and {pos2} must belong to a |bufloaded()| buffer.
+ - It is evaluated in current window context, which makes a
+ difference if the buffer is displayed in a window with
+ different 'virtualedit' or 'list' values.
+
+ Examples: >
+ :xnoremap <CR>
+ \ <Cmd>echom getregion(
+ \ getpos('v'), getpos('.'), #{ type: mode() })<CR>
+<
+
getregtype([{regname}]) *getregtype()*
The result is a String, which is type of register {regname}.
The value will be one of:
@@ -3873,8 +3964,7 @@ json_decode({expr}) *json_decode()*
Vim value. In the following cases it will output
|msgpack-special-dict|:
1. Dictionary contains duplicate key.
- 2. Dictionary contains empty key.
- 3. String contains NUL byte. Two special dictionaries: for
+ 2. String contains NUL byte. Two special dictionaries: for
dictionary and for string will be emitted in case string
with NUL byte was a dictionary key.
@@ -4272,6 +4362,7 @@ mapnew({expr1}, {expr2}) *mapnew()*
don't want that use |deepcopy()| first.
mapset({mode}, {abbr}, {dict}) *mapset()*
+mapset({dict})
Restore a mapping from a dictionary, possibly returned by
|maparg()| or |maplist()|. A buffer mapping, when dict.buffer
is true, is set on the current buffer; it is up to the caller
@@ -4360,6 +4451,7 @@ match({expr}, {pat} [, {start} [, {count}]]) *match()*
Note that when {count} is added the way {start} works changes,
see above.
+ *match-pattern*
See |pattern| for the patterns that are accepted.
The 'ignorecase' option is used to set the ignore-caseness of
the pattern. 'smartcase' is NOT used. The matching is always
@@ -4477,6 +4569,50 @@ matcharg({nr}) *matcharg()*
Highlighting matches using the |:match| commands are limited
to three matches. |matchadd()| does not have this limitation.
+matchbufline({buf}, {pat}, {lnum}, {end}, [, {dict}]) *matchbufline()*
+ Returns the |List| of matches in lines from {lnum} to {end} in
+ buffer {buf} where {pat} matches.
+
+ {lnum} and {end} can either be a line number or the string "$"
+ to refer to the last line in {buf}.
+
+ The {dict} argument supports following items:
+ submatches include submatch information (|/\(|)
+
+ For each match, a |Dict| with the following items is returned:
+ byteidx starting byte index of the match
+ lnum line number where there is a match
+ text matched string
+ Note that there can be multiple matches in a single line.
+
+ This function works only for loaded buffers. First call
+ |bufload()| if needed.
+
+ See |match-pattern| for information about the effect of some
+ option settings on the pattern.
+
+ When {buf} is not a valid buffer, the buffer is not loaded or
+ {lnum} or {end} is not valid then an error is given and an
+ empty |List| is returned.
+
+ Examples: >vim
+ " Assuming line 3 in buffer 5 contains "a"
+ :echo matchbufline(5, '\<\k\+\>', 3, 3)
+ [{'lnum': 3, 'byteidx': 0, 'text': 'a'}]
+ " Assuming line 4 in buffer 10 contains "tik tok"
+ :echo matchbufline(10, '\<\k\+\>', 1, 4)
+ [{'lnum': 4, 'byteidx': 0, 'text': 'tik'}, {'lnum': 4, 'byteidx': 4, 'text': 'tok'}]
+<
+ If {submatch} is present and is v:true, then submatches like
+ "\1", "\2", etc. are also returned. Example: >vim
+ " Assuming line 2 in buffer 2 contains "acd"
+ :echo matchbufline(2, '\(a\)\?\(b\)\?\(c\)\?\(.*\)', 2, 2
+ \ {'submatches': v:true})
+ [{'lnum': 2, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
+< The "submatches" List always contains 9 items. If a submatch
+ is not found, then an empty string is returned for that
+ submatch.
+
matchdelete({id} [, {win}]) *matchdelete()* *E802* *E803*
Deletes a match with ID {id} previously defined by |matchadd()|
or one of the |:match| commands. Returns 0 if successful,
@@ -4614,6 +4750,39 @@ matchstr({expr}, {pat} [, {start} [, {count}]]) *matchstr()*
When {expr} is a |List| then the matching item is returned.
The type isn't changed, it's not necessarily a String.
+matchstrlist({list}, {pat} [, {dict}]) *matchstrlist()*
+ Returns the |List| of matches in {list} where {pat} matches.
+ {list} is a |List| of strings. {pat} is matched against each
+ string in {list}.
+
+ The {dict} argument supports following items:
+ submatches include submatch information (|/\(|)
+
+ For each match, a |Dict| with the following items is returned:
+ byteidx starting byte index of the match.
+ idx index in {list} of the match.
+ text matched string
+ submatches a List of submatches. Present only if
+ "submatches" is set to v:true in {dict}.
+
+ See |match-pattern| for information about the effect of some
+ option settings on the pattern.
+
+ Example: >vim
+ :echo matchstrlist(['tik tok'], '\<\k\+\>')
+ [{'idx': 0, 'byteidx': 0, 'text': 'tik'}, {'idx': 0, 'byteidx': 4, 'text': 'tok'}]
+ :echo matchstrlist(['a', 'b'], '\<\k\+\>')
+ [{'idx': 0, 'byteidx': 0, 'text': 'a'}, {'idx': 1, 'byteidx': 0, 'text': 'b'}]
+<
+ If "submatches" is present and is v:true, then submatches like
+ "\1", "\2", etc. are also returned. Example: >vim
+ :echo matchstrlist(['acd'], '\(a\)\?\(b\)\?\(c\)\?\(.*\)',
+ \ #{submatches: v:true})
+ [{'idx': 0, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
+< The "submatches" List always contains 9 items. If a submatch
+ is not found, then an empty string is returned for that
+ submatch.
+
matchstrpos({expr}, {pat} [, {start} [, {count}]]) *matchstrpos()*
Same as |matchstr()|, but return the matched string, the start
position and the end position of the match. Example: >vim
@@ -4640,7 +4809,7 @@ max({expr}) *max()*
it returns the maximum of all values in the Dictionary.
If {expr} is neither a List nor a Dictionary, or one of the
items in {expr} cannot be used as a Number this results in
- an error. An empty |List| or |Dictionary| results in zero.
+ an error. An empty |List| or |Dictionary| results in zero.
menu_get({path} [, {modes}]) *menu_get()*
Returns a |List| of |Dictionaries| describing |menus| (defined
@@ -4954,7 +5123,6 @@ msgpackparse({data}) *msgpackparse()*
are binary strings).
2. String with NUL byte inside.
3. Duplicate key.
- 4. Empty key.
ext |List| with two values: first is a signed integer
representing extension type. Second is
|readfile()|-style list of strings.
@@ -5173,9 +5341,9 @@ printf({fmt}, {expr1} ...) *printf()*
< This limits the length of the text used from "line" to
"width" bytes.
- If the argument to be formatted is specified using a posional
- argument specifier, and a '*' is used to indicate that a
- number argument is to be used to specify the width or
+ If the argument to be formatted is specified using a
+ positional argument specifier, and a '*' is used to indicate
+ that a number argument is to be used to specify the width or
precision, the argument(s) to be used must also be specified
using a {n$} positional argument specifier. See |printf-$|.
@@ -5630,9 +5798,9 @@ reg_recording() *reg_recording()*
Returns the single letter name of the register being recorded.
Returns an empty string when not recording. See |q|.
-reltime()
+reltime() *reltime()*
reltime({start})
-reltime({start}, {end}) *reltime()*
+reltime({start}, {end})
Return an item that represents a time value. The item is a
list with items that depend on the system.
The item can be passed to |reltimestr()| to convert it to a
@@ -5677,8 +5845,8 @@ reltimestr({time}) *reltimestr()*
< Also see |profiling|.
If there is an error an empty string is returned
-remove({list}, {idx})
-remove({list}, {idx}, {end}) *remove()*
+remove({list}, {idx}) *remove()*
+remove({list}, {idx}, {end})
Without {end}: Remove the item at {idx} from |List| {list} and
return the item.
With {end}: Remove items from {idx} to {end} (inclusive) and
@@ -6407,8 +6575,8 @@ setcmdpos({pos}) *setcmdpos()*
Returns 0 when successful, 1 when not editing the command
line.
-setcursorcharpos({lnum}, {col} [, {off}])
-setcursorcharpos({list}) *setcursorcharpos()*
+setcursorcharpos({lnum}, {col} [, {off}]) *setcursorcharpos()*
+setcursorcharpos({list})
Same as |cursor()| but uses the specified column number as the
character index instead of the byte index in the line.
@@ -6834,8 +7002,8 @@ shiftwidth([{col}]) *shiftwidth()*
'vartabstop' feature. If no {col} argument is given, column 1
will be assumed.
-sign_define({name} [, {dict}])
-sign_define({list}) *sign_define()*
+sign_define({name} [, {dict}]) *sign_define()*
+sign_define({list})
Define a new sign named {name} or modify the attributes of an
existing sign. This is similar to the |:sign-define| command.
@@ -7102,8 +7270,8 @@ sign_placelist({list}) *sign_placelist()*
\ ])
<
-sign_undefine([{name}])
-sign_undefine({list}) *sign_undefine()*
+sign_undefine([{name}]) *sign_undefine()*
+sign_undefine({list})
Deletes a previously defined sign {name}. This is similar to
the |:sign-undefine| command. If {name} is not supplied, then
deletes all the defined signs.
@@ -8255,7 +8423,6 @@ test_garbagecollect_now() *test_garbagecollect_now()*
internally, and |v:testing| must have been set before calling
any function.
-
timer_info([{id}]) *timer_info()*
Return a list with information about timers.
When {id} is given only information about this timer is
diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt
index e1bb7c5fc7..703addf51a 100644
--- a/runtime/doc/change.txt
+++ b/runtime/doc/change.txt
@@ -424,9 +424,12 @@ octal number.
Note that when 'nrformats' includes "octal", decimal numbers with leading
zeros cause mistakes, because they can be confused with octal numbers.
-Note similarly, when 'nrformats' includes "bin", binary numbers with a leading
-'0x' or '0X' can be interpreted as hexadecimal rather than binary since '0b'
-are valid hexadecimal digits.
+Note similarly, when 'nrformats' includes both "bin" and "hex", binary numbers
+with a leading '0x' or '0X' can be interpreted as hexadecimal rather than
+binary since '0b' are valid hexadecimal digits. CTRL-A on "0x0b11" results in
+"0x0b12", not "0x0b100".
+When 'nrformats' includes "bin" and doesn't include "hex", CTRL-A on "0b11" in
+"0x0b11" results in "0x0b100".
When the number under the cursor is too big to fit into 64 bits, it will be
rounded off to the nearest number that can be represented, and the
@@ -485,7 +488,7 @@ SHIFTING LINES LEFT OR RIGHT *shift-left-right*
lines to [indent] (default 0).
*:>*
-:[range]> [flags] Shift {count} [range] lines one 'shiftwidth' right.
+:[range]> [flags] Shift [range] lines one 'shiftwidth' right.
Repeat '>' for shifting multiple 'shiftwidth's.
See |ex-flags| for [flags].
diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt
index 8bed8a9ffc..57a4223c53 100644
--- a/runtime/doc/cmdline.txt
+++ b/runtime/doc/cmdline.txt
@@ -439,9 +439,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, '?'
-matches exactly one character.
+a previous version <Esc> was used). In the pattern standard |wildcards| are
+accepted when matching file names.
When repeating 'wildchar' or CTRL-N you cycle through the matches, eventually
ending up back to what was typed. If the first match is not what you wanted,
diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt
index 0a07f06c75..5ac4ad4ce2 100644
--- a/runtime/doc/deprecated.txt
+++ b/runtime/doc/deprecated.txt
@@ -90,7 +90,7 @@ For each of the functions below, use the corresponding function in
- *vim.lsp.diagnostic.enable()*
- *vim.lsp.diagnostic.get()*
- *vim.lsp.diagnostic.get_all()* Use |vim.diagnostic.get()| instead.
-- *vim.lsp.diagnostic.get_count()* Use |vim.diagnostic.get()| instead.
+- *vim.lsp.diagnostic.get_count()* Use |vim.diagnostic.count()| instead.
- *vim.lsp.diagnostic.get_line_diagnostics()* Use |vim.diagnostic.get()| instead.
- *vim.lsp.diagnostic.get_next()*
- *vim.lsp.diagnostic.get_next_pos()*
@@ -116,6 +116,9 @@ internally and are no longer exposed as part of the API. Instead, use
- *vim.lsp.diagnostic.set_underline()*
- *vim.lsp.diagnostic.set_virtual_text()*
+Configuring |diagnostic-signs| with |:sign-define| or |sign_define()| is no
+longer supported. Use the "signs" key of |vim.diagnostic.config()| instead.
+
LSP FUNCTIONS
- *vim.lsp.buf.server_ready()*
Use |LspAttach| instead, depending on your use-case. "Server ready" is not
@@ -138,9 +141,11 @@ LSP FUNCTIONS
- *vim.lsp.buf.range_formatting()* Use |vim.lsp.formatexpr()|
or |vim.lsp.buf.format()| instead.
- *vim.lsp.util.get_progress_messages()* Use |vim.lsp.status()| or access
- `progress` of |vim.lsp.client|
+ `progress` of |vim.lsp.Client|
- *vim.lsp.get_active_clients()* Use |vim.lsp.get_clients()|
- *vim.lsp.for_each_buffer_client()* Use |vim.lsp.get_clients()|
+- *vim.lsp.util.lookup_section()* Use |vim.tbl_get()| and
+ |vim.split()| with {plain=true} instead.
- *vim.lsp.util.trim_empty_lines()* Use |vim.split()| with `trimempty` instead.
- *vim.lsp.util.try_trim_markdown_code_blocks()*
- *vim.lsp.util.set_lines()*
@@ -164,6 +169,7 @@ LUA
- vim.register_keystroke_callback() Use |vim.on_key()| instead.
- *vim.pretty_print()* Use |vim.print()| instead.
- *vim.loop* Use |vim.uv| instead.
+- *vim.tbl_add_reverse_lookup()*
NORMAL COMMANDS
- *]f* *[f* Same as "gf".
@@ -171,7 +177,6 @@ NORMAL COMMANDS
OPTIONS
- *cpo-<* *:menu-<special>* *:menu-special* *:map-<special>* *:map-special*
`<>` notation is always enabled.
-- 'gdefault' Enables the |:substitute| flag 'g' by default.
- *'fe'* 'fenc'+'enc' before Vim 6.0; no longer used.
- *'highlight'* *'hl'* Names of builtin |highlight-groups| cannot be changed.
- *'langnoremap'* Deprecated alias to 'nolangremap'.
diff --git a/runtime/doc/dev_style.txt b/runtime/doc/dev_style.txt
index cb28f1a845..85aeddd425 100644
--- a/runtime/doc/dev_style.txt
+++ b/runtime/doc/dev_style.txt
@@ -41,17 +41,44 @@ All header files should start with `#pragma once` to prevent multiple inclusion.
#pragma once
<
+Headers system ~
-Constants ~
+Nvim uses two types of headers. There are "normal" headers and "defs" headers.
+Typically, each normal header will have a corresponding defs header, e.g.
+`fileio.h` and `fileio_defs.h`. This distinction is done to minimize
+recompilation on change. The reason for this is because adding a function or
+modifying a function's signature happens more frequently than changing a type
+The goal is to achieve the following:
-Do not use macros to define constants in headers.
+- All headers (defs and normal) must include only defs headers, system
+ headers, and generated declarations. In other words, headers must not
+ include normal headers.
-Macro constants in header files cannot be used by unit tests.
+- Source (.c) files may include all headers, but should only include normal
+ headers if they need symbols and not types.
-However, you are allowed to define a macro that holds the same value as a
-non-enum constant (defined in the same header) if the value of the constant
-represents the size of an array.
+Use the following guideline to determine what to put where:
+Symbols:
+ - regular function declarations
+ - `extern` variables (including the `EXTERN` macro)
+
+Non-symbols:
+ - macros, i.e. `#define`.
+ - static inline functions, but only if its function declaration has a
+ `REAL_FATTR_ALWAYS_INLINE` attribute.
+ - typedefs
+ - structs
+ - enums
+
+- All symbols must be moved to normal headers.
+
+- Non-symbols used by multiple headers should be moved to defs headers. This
+ is to ensure headers only include defs headers. Conversely, non-symbols used
+ by only a single header should be moved to that header.
+
+- EXCEPTION: if the macro calls a function, then it must be moved to a normal
+ header.
==============================================================================
Scoping *dev-style-scope*
@@ -73,6 +100,24 @@ should be used instead of declaration and assignment, e.g. >c
int j = g(); // GOOD: declaration has initialization.
+Initialization ~
+
+Multiple declarations can be defined in one line if they aren't initialized,
+but each initialization should be done on a separate line.
+
+>c
+ int i;
+ int j; // GOOD
+
+ int i, j; // GOOD: multiple declarations, no initialization.
+
+ int i = 0;
+ int j = 0; // GOOD: one initialization per line.
+
+ int i = 0, j; // BAD: multiple declarations with initialization.
+
+ int i = 0, j = 0; // BAD: multiple declarations with initialization.
+
==============================================================================
Nvim-Specific Magic
@@ -190,7 +235,7 @@ Function declarations ~
Every function must not have a separate declaration.
-Function declarations are created by the gendeclarations.lua script. >c
+Function declarations are created by the gen_declarations.lua script. >c
static void f(void);
@@ -773,47 +818,6 @@ example, `"\uFEFF"`, is the Unicode zero-width no-break space character, which
would be invisible if included in the source as straight UTF-8.
-Function Calls ~
-
-On one line if it fits; otherwise, wrap arguments at the parenthesis.
-
-Function calls have the following format: >c
-
- bool retval = do_something(argument1, argument2, argument3);
-
-If the arguments do not all fit on one line, they should be broken up onto
-multiple lines, with each subsequent line aligned with the first argument. Do
-not add spaces after the open paren or before the close paren: >c
-
- bool retval = do_something(averyveryveryverylongargument1,
- argument2, argument3);
-
-If the function has many arguments, consider having one per line if this makes
-the code more readable: >c
-
- bool retval = do_something(argument1,
- argument2,
- argument3,
- argument4);
-
-Arguments may optionally all be placed on subsequent lines, with one line per
-argument: >c
-
- if (...) {
- ...
- ...
- if (...) {
- do_something(
- argument1, // 4 space indent
- argument2,
- argument3,
- argument4);
- }
-
-In particular, this should be done if the function signature is so long that
-it cannot fit within the maximum line length.
-
-
Braced Initializer Lists ~
Format a braced list exactly like you would format a function call in its
@@ -915,11 +919,6 @@ Horizontal Whitespace ~
Use of horizontal whitespace depends on location.
- General ~
->c
- int x[] = { 0 }; // Spaces inside braces for braced-init-list.
-<
-
Variables ~
>c
int long_variable = 0; // Don't align assignments.
@@ -936,26 +935,6 @@ Use of horizontal whitespace depends on location.
};
<
-
- Operators ~
->c
- x = 0; // Assignment operators always have spaces around
- // them.
- x = -5; // No spaces separating unary operators and their
- x++; // arguments.
- if (x && !y)
-<
-
-Vertical Whitespace ~
-
-Minimize use of vertical whitespace.
-
-The basic principle is: The more code that fits on one screen, the easier it
-is to follow and understand the control flow of the program. Of course,
-readability can suffer from code being too dense as well as too spread out, so
-use your judgment. But in general, minimize use of vertical whitespace.
-
-
==============================================================================
Parting Words
diff --git a/runtime/doc/dev_theme.txt b/runtime/doc/dev_theme.txt
new file mode 100644
index 0000000000..29a2da0d90
--- /dev/null
+++ b/runtime/doc/dev_theme.txt
@@ -0,0 +1,121 @@
+*dev_theme.txt* Nvim
+
+
+ NVIM REFERENCE MANUAL
+
+
+Nvim theme style guide *dev-theme*
+
+This is style guide for developers working on Nvim's default color scheme.
+
+License: CC-By 3.0 https://creativecommons.org/licenses/by/3.0/
+
+ Type |gO| to see the table of contents.
+
+==============================================================================
+Design
+
+- Be "Neovim branded", i.e. have mostly "green-blue" feel plus one or two
+ colors reserved for very occasional user attention.
+
+- Be oriented for 'termguicolors' (true colors) while being extra minimal for
+ 'notermguicolors' (16 colors) as fallback.
+
+- Be accessible, i.e. have high enough contrast ratio (as defined in
+ https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef).
+ This means to have value at least 7 for |hl-Normal| and 4.5 for some common
+ cases (|hl-Visual|, `Comment` with set 'cursorline', colored syntax, `Diff*`,
+ |hl-Search|).
+
+- Be suitable for dark and light backgrounds via exchange of dark and light
+ palettes.
+
+- Be usable, i.e. provide enough visual feedback for common objects.
+
+
+==============================================================================
+Palettes
+
+- There are two separate palettes: dark and light. They all contain the same
+ set of colors exported as `NvimDark*` and `NvimLight*` colors respectively.
+
+- The dark palette is used for background in the dark color scheme and for
+ foreground in the light color scheme; and vice versa. This introduces
+ recognizable visual system without too standing out.
+
+- Actual computation of palettes should be done in a perceptually uniform
+ color space. Oklch is a good choice.
+
+- Each palette has the following colors (descriptions are for dark background;
+ reverse for light one):
+
+ - Four shades of colored "cold" greys for general UI.
+
+ - Dark ones (from darkest to lightest) are reserved as background for
+ |hl-NormalFloat| (considered as "black"), |hl-Normal| (background),
+ |hl-CursorLine|, |hl-Visual|.
+
+ - Light ones (also from darkest to lightest) are reserved for
+ `Comment`, |hl-StatusLine|/|hl-TabLine|, |hl-Normal| (foreground),
+ and color considered as "white".
+
+- Six colors to provide enough terminal colors: red, yellow, green, cyan,
+ blue, magenta.
+ They should have (reasonably) similar lightness and chroma to make them
+ visually coherent. Lightness should be as equal to the palette's basic grey
+ (which is used for |hl-Normal|) as possible. They should have (reasonably)
+ different hues to make them visually separable.
+
+- For 16 colors:
+
+ - Greys are not used and are replaced with the foreground and background
+ colors of the terminal emulator.
+
+ - Non-grey colors fall back to terminal colors as ordered in ANSI codes
+ (https://en.wikipedia.org/wiki/ANSI_escape_code#3-bit_and_4-bit),
+ that is red (1, 9), green (2, 10), yellow (3, 11), blue (4, 12),
+ magenta (5, 13), cyan (6, 14).
+ To increase contrast, colors 1-6 are used for light background and 9-14
+ for dark background.
+
+
+==============================================================================
+Highlight groups
+
+Use:
+
+- Grey shades for general UI according to their design.
+
+- Bold text for keywords (`Statement` highlight group). This is an important
+ choice to increase accessibility for people with color deficiencies, as it
+ doesn't rely on actual color.
+
+- Green for strings, |hl-DiffAdd| (as background), |hl-DiagnosticOk|, and some
+ minor text UI elements.
+
+- Cyan as main syntax color, i.e. for function usage (`Function` highlight
+ group), |hl-DiffText|, |hl-DiagnosticInfo|, and some minor text UI elements.
+
+- Red to generally mean high user attention, i.e. errors; in particular for
+ |hl-ErrorMsg|, |hl-DiffDelete|, |hl-DiagnosticError|.
+
+- Yellow very sparingly to mean mild user attention, i.e. warnings. That is,
+ |hl-DiagnosticWarn| and |hl-WarningMsg|.
+
+- Blue very sparingly as |hl-DiagnosticHint| and some additional important
+ syntax group (like `Identifier`).
+
+- Magenta very carefully (if at all).
+
+In case of 16 colors:
+
+- Rely on the assumption "Background color can be used as background; other
+ colors can be used as foreground". This means that in any
+ foreground/background combination there should be background and one
+ non-background color.
+
+- Use 0 (black) or 15 (bright white) as foreground for non-grey background,
+ depending on whether normal background is light or dark.
+
+
+ vim:tw=78:ts=8:et:ft=help:norl:
diff --git a/runtime/doc/dev_tools.txt b/runtime/doc/dev_tools.txt
new file mode 100644
index 0000000000..3ee48bec90
--- /dev/null
+++ b/runtime/doc/dev_tools.txt
@@ -0,0 +1,192 @@
+*dev_tools.txt* Nvim
+
+
+ NVIM REFERENCE MANUAL
+
+
+Tools and techniques for developing Nvim *dev-tools*
+
+The following advice is helpful when working on or debugging issues with Nvim
+itself. See also |debug.txt| for advice that applies to Vim.
+
+ Type |gO| to see the table of contents.
+
+==============================================================================
+Backtraces *dev-tools-backtrace*
+
+LINUX ~
+
+Core dumps are disabled by default on Ubuntu
+https://stackoverflow.com/a/18368068, CentOS and others. To enable core dumps:
+>bash
+ ulimit -c unlimited
+<
+On systemd-based systems getting a backtrace is as easy as:
+>bash
+ coredumpctl -1 gdb
+<
+It's an optional tool, so you may need to install it:
+>bash
+ sudo apt install systemd-coredump
+<
+
+The full backtrace is most useful, send us the `bt.txt` file:
+>bash
+ 2>&1 coredumpctl -1 gdb | tee -a bt.txt
+ thread apply all bt full
+<
+On older systems a `core` file will appear in the current directory. To get
+a backtrace from the `core` file:
+>bash
+ gdb build/bin/nvim core 2>&1 | tee backtrace.txt
+ thread apply all bt full
+<
+
+MACOS
+
+If `nvim` crashes, you can see the backtrace in `Console.app` (under "Crash
+Reports" or "User Diagnostic Reports" for older macOS versions).
+>bash
+ open -a Console
+<
+You may also want to enable core dumps on macOS. To do this, first make sure
+the `/cores/` directory exists and is writable:
+>bash
+ sudo mkdir /cores
+ sudo chown root:admin /cores
+ sudo chmod 1775 /cores
+<
+Then set the core size limit to `unlimited`:
+>bash
+ ulimit -c unlimited
+<
+Note that this is done per shell process. If you want to make this the default
+for all shells, add the above line to your shell's init file (e.g. `~/.bashrc`
+or similar).
+
+You can then open the core file in `lldb`:
+>bash
+ lldb -c /cores/core.12345
+<
+Apple's documentation archive has some other useful information
+https://developer.apple.com/library/archive/technotes/tn2124/_index.html#//apple_ref/doc/uid/DTS10003391-CH1-SECCOREDUMPS,
+but note that some of the things on this page are out of date (such as enabling
+core dumps with `/etc/launchd.conf`).
+
+==============================================================================
+Gdb *dev-tools-gdb*
+
+USING GDB TO STEP THROUGH FUNCTIONAL TESTS ~
+
+Use `TEST_TAG` to run tests matching busted tags (of the form `#foo` e.g.
+`it("test #foo ...", ...)`):
+>bash
+ GDB=1 TEST_TAG=foo make functionaltest
+<
+Then, in another terminal:
+>bash
+ gdb build/bin/nvim
+ target remote localhost:7777
+<
+- See also test/functional/helpers.lua https://github.com/neovim/neovim/blob/3098b18a2b63a841351f6d5e3697cb69db3035ef/test/functional/helpers.lua#L38-L44.
+
+
+USING LLDB TO STEP THROUGH UNIT TESTS ~
+
+>bash
+ lldb .deps/usr/bin/luajit -- .deps/usr/bin/busted --lpath="./build/?.lua" test/unit/
+<
+
+USING GDB ~
+
+To attach to a running `nvim` process with a pid of 1234:
+>bash
+ gdb -tui -p 1234 build/bin/nvim
+<
+The `gdb` interactive prompt will appear. At any time you can:
+
+- `break foo` to set a breakpoint on the `foo()` function
+- `n` to step over the next statement
+ - `<Enter>` to repeat the last command
+- `s` to step into the next statement
+- `c` to continue
+- `finish` to step out of the current function
+- `p zub` to print the value of `zub`
+- `bt` to see a backtrace (callstack) from the current location
+- `CTRL-x CTRL-a` or `tui enable` to show a TUI view of the source file in the
+ current debugging context. This can be extremely useful as it avoids the
+ need for a gdb "frontend".
+- `<up>` and `<down>` to scroll the source file view
+
+
+GDB "REVERSE DEBUGGING" ~
+
+- `set record full insn-number-max unlimited`
+- `continue` for a bit (at least until `main()` is executed
+- `record`
+- provoke the bug, then use `revert-next`, `reverse-step`, etc. to rewind the
+ debugger
+
+
+USING GDBSERVER ~
+
+You may want to connect multiple `gdb` clients to the same running `nvim`
+process, or you may want to connect to a remote `nvim` process with a local
+`gdb`. Using `gdbserver`, you can attach to a single process and control it
+from multiple `gdb` clients.
+
+Open a terminal and start `gdbserver` attached to `nvim` like this:
+>bash
+ gdbserver :6666 build/bin/nvim 2> gdbserver.log
+<
+`gdbserver` is now listening on port 6666. You then need to attach to this
+debugging session in another terminal:
+>bash
+ gdb build/bin/nvim
+<
+Once you've entered `gdb`, you need to attach to the remote session:
+>
+ target remote localhost:6666
+<
+In case gdbserver puts the TUI as a background process, the TUI can become
+unable to read input from pty (and receives SIGTTIN signal) and/or output data
+(SIGTTOU signal). To force the TUI as the foreground process, you can add
+>
+ signal (SIGTTOU, SIG_IGN);
+ if (!tcsetpgrp(data->input.in_fd, getpid())) {
+ perror("tcsetpgrp failed");
+ }
+<
+to `tui.c:terminfo_start`.
+
+
+USING GDBSERVER IN TMUX ~
+
+Consider using a custom makefile
+https://github.com/neovim/neovim/blob/master/BUILD.md#custom-makefile to
+quickly start debugging sessions using the `gdbserver` method mentioned above.
+This example `local.mk` will create the debugging session when you type `make
+debug`.
+>make
+ .PHONY: dbg-start dbg-attach debug build
+
+ build:
+ @$(MAKE) nvim
+
+ dbg-start: build
+ @tmux new-window -n 'dbg-neovim' 'gdbserver :6666 ./build/bin/nvim -D'
+
+ dbg-attach:
+ @tmux new-window -n 'dbg-cgdb' 'cgdb -x gdb_start.sh ./build/bin/nvim'
+
+ debug: dbg-start dbg-attach
+<
+Here `gdb_start.sh` includes `gdb` commands to be called when the debugger
+starts. It needs to attach to the server started by the `dbg-start` rule. For
+example:
+>
+ target remote localhost:6666
+ br main
+<
+
+vim:tw=78:ts=8:et:ft=help:norl:
diff --git a/runtime/doc/dev_vimpatch.txt b/runtime/doc/dev_vimpatch.txt
new file mode 100644
index 0000000000..96307dc7df
--- /dev/null
+++ b/runtime/doc/dev_vimpatch.txt
@@ -0,0 +1,303 @@
+*dev_vimpatch.txt* Nvim
+
+ NVIM REFERENCE MANUAL
+
+Merging patches from Vim *dev-vimpatch*
+
+
+Nvim was forked from Vim 7.4.160; it is kept up-to-date with relevant Vim
+patches in order to avoid duplicate work. Run `vim-patch.sh`
+https://github.com/neovim/neovim/blob/master/scripts/vim-patch.sh to see the
+status of Vim patches:
+>bash
+ ./scripts/vim-patch.sh -l
+<
+Everyone is welcome to |dev-vimpatch-pull-requests| for relevant Vim
+patches, but some types of patches are |dev-vimpatch-not-applicable|.
+See |dev-vimpatch-quickstart| to get started immediately.
+
+
+ Type |gO| to see the table of contents.
+
+==============================================================================
+QUICKSTART *dev-vimpatch-quickstart*
+
+1. Pull the Nvim source:
+>bash
+ git clone https://github.com/neovim/neovim.git
+<
+2. Run `./scripts/vim-patch.sh -l` to see the list of missing Vim patches.
+
+3. Choose a patch from the list (usually the oldest one), e.g. `8.0.0123`.
+
+ - Check for open vim-patch PRs
+ https://github.com/neovim/neovim/pulls?q=is%3Apr+is%3Aopen+label%3Avim-patch.
+
+4. Run `./scripts/vim-patch.sh -p 8.0.0123`
+
+5. Follow the instructions given by the script.
+
+NOTES ~
+
+- It's strongly recommended to work on the oldest missing patch, because
+ later patches might depend on the changes.
+- Use `git log --grep` or `git log -G` to search the Nvim/Vim source history
+ (even deleted code). E.g. to find `reset_option_was_set`: >bash
+
+ git log -p -G reset_option_was_set
+<
+- Pass `git log` options like `--grep` and `-G` to `./scripts/vim-patch.sh -L`
+ to filter unmerged Vim patches E.g. to find `+quickfix` patches: >bash
+
+ ./scripts/vim-patch.sh -L --grep quickfix -- src
+<
+==============================================================================
+PULL REQUESTS *dev-vimpatch-pull-requests*
+
+Note: vim-patch.sh automates these steps for you. Use it!
+
+- Install `gh` (https://cli.github.com/) if you want to use `vim-patch.sh` to
+ create PRs automatically
+- The pull request title should include `vim-patch:8.x.xxxx` (no whitespace)
+- The commit message
+ https://github.com/neovim/neovim/commit/4ccf1125ff569eccfc34abc4ad794044c5ab7455
+ should include:
+ - A token indicating the Vim patch number, formatted as follows:
+ `vim-patch:8.0.0123` (no whitespace)
+ - A URL pointing to the Vim commit:
+ https://github.com/vim/vim/commit/c8020ee825b9d9196b1329c0e097424576fc9b3a
+ - The original Vim commit message, including author
+
+Reviewers: hint for reviewing `runtime/` patches
+https://github.com/neovim/neovim/pull/1744#issuecomment-68202876
+
+==============================================================================
+NA (NOT APPLICABLE) PATCHES *dev-vimpatch-not-applicable*
+
+Many Vim patches are not applicable to Nvim. If you find NA patches, visit an
+open "version.c: update" pull request
+https://github.com/neovim/neovim/pulls?q=is%3Apr+author%3Aapp%2Fgithub-actions+version.c+is%3Aopen
+and mention the NA patches in a comment (please edit/update one comment,
+rather than adding a new comment for each patch).
+
+If there are no open `version.c: update` pull requests, include NA patches in
+a commit message in the following format:
+>
+ vim-patch:<version-or-commit>
+ vim-patch:<version-or-commit>
+ ...
+<
+where `<version-or-commit>` is a valid Vim version (like `8.0.0123`) or
+commit-id (SHA). Each patch is on a separate line.
+
+It is preferred to include NA patches by squashing it in applicable Vim
+patches, especially if the Vim patches are related. First line of the commit
+message should be from the applicable Vim patch.
+>
+ ./scripts/vim-patch -p <na-patch>
+ ./scripts/vim-patch -p <na-patch>
+ ...
+ ./scripts/vim-patch -P <patch>
+ git rebase -i master
+<
+Example:
+https://github.com/neovim/neovim/commit/00f60c2ce78fc1280e93d5a36bc7b2267d5f4ac6
+
+TYPES OF "NOT APPLICABLE" VIM PATCHES ~
+
+- Vim9script features, and anything related to `:scriptversion`. (Nvim
+ supports Vimscript version 1 only.) Be aware that patches labelled `Vim9:`
+ may still contain applicable fixes to other parts of the codebase, so these
+ patch need to be checked individually.
+- Updates to `testdir/Makefile` are usually NA because the Makefile implicitly
+ finds
+ https://github.com/neovim/neovim/commit/8a677f8a4bff6005fa39f090c14e970c3dfdbe6e#diff-b3c6ad6680a25a1b42095879e3a87104R52
+ all `test_*.vim` files.
+- Compiler warning fixes: Nvim strives to have no warnings at all, and has a
+ very different build system from Vim.
+ - Note: Coverity fixes in Vim are relevant to Nvim.
+- `*.proto` changes: Nvim autogenerates function prototypes
+- `#ifdef` tweaking: For example, Vim decided to enable `FEAT_VISUAL` for all
+ platforms - but Nvim already does that. Adding new `FEAT_` guards also isn't
+ relevant to Nvim.
+- Legacy system support: Fixes for legacy systems such as Amiga, OS/2 Xenix,
+ Mac OS 9, Windows older than XP SP2, are not needed because they are not
+ supported by Nvim.
+ - NA files: `src/Make_*`, `src/testdir/Make__*`
+- `if_*.c` changes: `if_python.c` et. al. were removed.
+- `term.c` changes: the Nvim TUI uses `libtermkey` to read terminal sequences;
+ Vim's `term.c` was removed.
+- `job` patches: incompatible API and implementation
+ - NA files: `src/channel_*`, `src/job_*`, `src/testdir/test_channel_*`,
+ `src/testdir/test_job_*`
+- `:terminal` patches that modify NA files: incompatible API and
+ implementation
+ - NA files: `src/terminal_*`, `src/testdir/test_terminal_*`
+- `defaults.vim` patches
+- Most GUI-related changes: Nvim GUIs are implemented external to the core C
+ codebase.
+ - NA files: `src/gui_*`, `src/gvim_*`, `src/GvimExt/*`, `src/testdir/test_gui*`
+- `balloon` changes: Nvim does not support balloon feature
+ - NA files: `src/beval_*`, `src/testdir/test_balloon_*`
+- libvterm changes: Nvim does not vendor libvterm in `src/`.
+- Screendump tests from `test_popupwin.vim`, `test_popupwin_textprop.vim`:
+ https://github.com/neovim/neovim/pull/12741#issuecomment-704677141
+- json changes: incompatible API https://github.com/neovim/neovim/pull/4131
+ - NA files: `src/json*`, `src/testdir/test_json.vim`
+- `test_restricted.vim` restricted mode is removed in
+ https://github.com/neovim/neovim/pull/11996
+- Many tests in `test_prompt_buffer.vim` require incompatible Vim features
+ such as `channel`; they should still be included, but skipped
+- non-runtime documentation: Moved to https://neovim.io/doc/,
+ - NA files: `Filelist`, `README`, `INSTALL`,
+- Anything else might be relevant; err on the side of caution, and post an
+ issue if you aren't sure.
+
+==============================================================================
+VERSION.C *dev-vimpatch-version.c*
+
+The list of Vim patches in `src/nvim/version.c` is automatically updated
+https://github.com/neovim/neovim/pull/7780 based on the presence of
+`vim-patch:xxx` tokens in the Nvim git log.
+
+- Don't update `src/nvim/version.c` yourself.
+ - `scripts/vim-patch.sh -p` intentionally omits `version.c` to avoid merge
+ conflicts and save time when porting a patch.
+- The automation script (`scripts/vimpatch.lua`) only recognizes tokens like
+ `vim-patch:8.0.1206`, not `vim-patch:<hash>`.
+
+==============================================================================
+CODE DIFFERENCES *dev-vimpatch-code-differences*
+
+The following functions have been removed or deprecated in favor of newer
+alternatives. See `memory.c`
+https://github.com/neovim/neovim/blob/master/src/nvim/memory.c for more
+information.
+>
+ -----------------------------------------------------------------------
+ Deprecated or removed Replacement
+ -----------------------------------------------------------------------
+ vim_free xfree
+ VIM_CLEAR(&foo) XFREE_CLEAR(foo)
+ malloc alloc lalloc lalloc_id ALLOC_ONE xmalloc
+ calloc lalloc_clear xcalloc
+ realloc vim_realloc xrealloc
+ mch_memmove memmove
+ vim_memset copy_chars copy_spaces memset
+ vim_strbyte strchr
+ vim_strncpy strncpy xstrlcpy
+ vim_strcat strncat xstrlcat
+ VIM_ISWHITE ascii_iswhite
+ IS_WHITE_OR_NUL ascii_iswhite_or_nul
+ vim_isalpha mb_isalpha
+ vim_isNormalIDc ascii_isident
+ vim_islower vim_isupper mb_islower mb_isupper
+ vim_tolower vim_toupper mb_tolower mb_toupper
+ mb_ptr2len utfc_ptr2len
+ mb_ptr2len_len utfc_ptr2len_len
+ mb_char2len utf_char2len
+ mb_char2bytes utf_char2bytes
+ mb_ptr2cells utf_ptr2cells
+ mb_ptr2cells_len utf_ptr2cells_len
+ mb_char2cells utf_char2cells
+ mb_off2cells utf_off2cells
+ mb_ptr2char utf_ptr2char
+ mb_head_off utf_head_off
+ mb_tail_off utf_cp_bounds
+ mb_lefthalve grid_lefthalve
+ mb_fix_col grid_fix_col
+ utf_off2cells grid_off2cells
+ ml_get_curline get_cursor_line_ptr
+ ml_get_cursor get_cursor_pos_ptr
+ screen_char ui_line
+ screen_line grid_put_linebuf
+ screen_* (most functions) grid_*
+ update_prepare, update_finish #9484 removed; use update_screen only
+ ARRAY_LENGTH ARRAY_SIZE
+ vim_strsave_escape_csi vim_strsave_escape_ks
+ vim_unescape_csi vim_unescape_ks
+ gettail path_tail
+ mch_isFullName path_is_absolute
+ script_do_profile profile_init
+
+ -----------------------------------------------------------------------
+<
+Make sure to note the difference between `utf_` and `utfc_` when replacing
+`mb_` functions. Also indirect call syntax `(*mb_ptr2len)(...)` should be
+replaced with an ordinary function call `utfc_ptr2len(...)`.
+>
+ -----------------------------------------------------------------------
+ Data type Format (Vim source) Portable format (Nvim source)
+ ------------ ----------------------- ----------------------------------
+ long long "%lld" "%" PRId64
+ size_t "%ld" "%zu"
+ linenr_T "%ld" "%" PRIdLINENR
+ -----------------------------------------------------------------------
+<
+- See also: https://github.com/neovim/neovim/pull/1729#discussion_r22423779
+- Vim's `ga_init2` was renamed to `ga_init` and the original `ga_init` is
+ gone.
+- "Old style" Vim tests (`src/testdir/*.in`) should be converted to Lua tests
+ (see #1286 https://github.com/neovim/neovim/issues/1286 and #1328
+ https://github.com/neovim/neovim/pull/1328). See Checklist for migrating
+ legacy tests
+ https://github.com/neovim/neovim/blob/master/test/README.md#checklist-for-migrating-legacy-tests.
+ - However, please do not convert "new style" Vim tests
+ (`src/testdir/*.vim`) to Lua. The "new style" Vim tests are faster than
+ the old ones, and converting them takes time and effort better spent
+ elsewhere. Just copy them to `test/old/testdir/*.vim`.
+- Conditions that check `enc_utf8` or `has_mbyte` are obsolete (only the
+ "true" case is applicable).
+ - `enc_utf8` and `has_mbyte` macros were removed in
+ https://github.com/neovim/neovim/pull/13293
+- Check for `CSI` in typeahead buffer is only necessary in Vim with
+ `FEAT_GUI`. `CSI` does not have a special meaning in typeahead buffer in
+ Nvim. (also see https://github.com/neovim/neovim/pull/16936)
+
+==============================================================================
+LIST MANAGEMENT *dev-vimpatch-list-management*
+
+Management of lists (types `list_T` and `listitem_T` from vim) was changed in
+https://github.com/neovim/neovim/pull/7708/. There is a lint against the "old"
+usage, but here are the most important changes.
+
+Declarations for the table
+
+- `list_T list`: a list
+- `listitem_T li`: an item of `list`
+- `int val` a value for `lv_copyID`
+
+>
+ --------------------------------------------------------------------------------------
+ Old New Comment
+ ------------------------------- ------------------------------------------------------
+ list->lv_first tv_list_first(list)
+ list->lv_last tv_list_last(list)
+ li->li_next TV_LIST_ITEM_NEXT(list, li) To be avoided if possible, must use list which li belongs to.
+ li->li_prev TV_LIST_ITEM_PREV(list, li) To be avoided if possible, must use list which li belongs to.
+ Suggestion by @ZyX-l: Use TV_LIST_ITER or indexing instead of the previous two calls.
+ list->lv_len tv_list_len(list)
+ list->lv_lock tv_list_locked(list)
+ &li->li_tv TV_LIST_ITEM_TV(li)
+ list->lv_refcount++ tv_list_ref(list)
+ val = list->lv_copyID val = tv_list_copyid(list)
+ list->lv_copyID = val tv_list_set_copyid(list, val)
+
+ for (li = list->lv_first; TV_LIST_ITER_CONST(list, li, Use TV_LIST_ITER(...) if you need to
+ li != NULL && another_cond; { if (another_cond) {break;} code}) modify list items (note: assigning copyID is also modification and this happens
+ li = li->li_next) code always when recursively traversing a list).
+
+ --------------------------------------------------------------------------------------
+<
+For more details and some more advanced usage, see `typval.h` and `typval.c`.
+
+==============================================================================
+DOCUMENTATION DIFFERENCES *dev-vimpatch-documentation*
+
+The following should be removed from all imported documentation, and not be
+used in new documentation:
+
+- `{Only when compiled with ...}`: the vast majority of features have been
+ made non-optional (see https://github.com/neovim/neovim/wiki/Introduction)
+
+vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/develop.txt b/runtime/doc/develop.txt
index f1d74326c7..767f46ad1e 100644
--- a/runtime/doc/develop.txt
+++ b/runtime/doc/develop.txt
@@ -102,11 +102,11 @@ Examples:
The provider framework invokes Vimscript from C. It is composed of two
functions in eval.c:
-- eval_call_provider(name, method, arguments, discard): calls
- provider#{name}#Call with the method and arguments. If discard is true, any
+- eval_call_provider({name}, {method}, {arguments}, {discard}): Calls
+ `provider#{name}#Call` with {method} and {arguments}. If {discard} is true, any
value returned by the provider will be discarded and empty value will be
returned.
-- eval_has_provider(name): Checks the `g:loaded_{name}_provider` variable
+- eval_has_provider({name}): Checks the `g:loaded_{name}_provider` variable
which must be set to 2 by the provider script to indicate that it is
"enabled and working". Called by |has()| to check if features are available.
@@ -179,19 +179,22 @@ Strict "vimdoc" subset:
- Do not use indentation in random places—that prevents the page from using
"flow" layout. If you need a preformatted section, put it in
a |help-codeblock| starting with ">".
+- Parameters and fields are documented as `{foo}`.
+- Optional parameters and fields are documented as `{foo}?`.
C docstrings ~
-Nvim API documentation lives in the source code, as docstrings (Doxygen
+Nvim API documentation lives in the source code, as docstrings (doc
comments) on the function definitions. The |api| :help is generated
from the docstrings defined in src/nvim/api/*.c.
Docstring format:
- Lines start with `///`
- Special tokens start with `@` followed by the token name:
- `@note`, `@param`, `@returns`
-- Limited markdown is supported.
- - List-items start with `-` (useful to nest or "indent")
+ `@note`, `@param`, `@return`
+- Markdown is supported.
+- Tags are written as `[tag]()`.
+- References are written as `[tag]`
- Use ``` for code samples.
Code samples can be annotated as `vim` or `lua`
@@ -233,11 +236,35 @@ definitions. The |lua-vim| :help is generated from the docstrings.
Docstring format:
- Use LuaCATS annotations: https://luals.github.io/wiki/annotations/
-- Limited markdown is supported.
- - List-items start with `-` (useful to nest or "indent")
+- Markdown is supported.
+- Tags are written as `[tag]()`.
+- References are written as `[tag]`
- Use ``` for code samples.
Code samples can be annotated as `vim` or `lua`
- Use `@nodoc` to prevent documentation generation.
+- Use `@inlinedoc` to inline `@class` blocks into `@param` blocks.
+ E.g. >lua
+ --- Object with fields:
+ --- @class myOpts
+ --- @inlinedoc
+ ---
+ --- Documentation for some field
+ --- @field somefield? integer
+
+ --- @param opts? myOpts
+ function foo(opts)
+ end
+<
+
+ Will be rendered as: >vimdoc
+
+ foo({opts})
+
+ Parameters:
+ - {opts}? (table) Object with the fields:
+ - {somefield}? (integer) Documentation
+ for some field
+<
- Files which has `@meta` are only used for typing and documentation.
Example: the help for |vim.paste()| is generated from a docstring decorating
diff --git a/runtime/doc/diagnostic.txt b/runtime/doc/diagnostic.txt
index 7f5c809ac3..c9e783ca62 100644
--- a/runtime/doc/diagnostic.txt
+++ b/runtime/doc/diagnostic.txt
@@ -38,24 +38,6 @@ optionally supplied). A good rule of thumb is that if a method is meant to
modify the diagnostics for a buffer (e.g. |vim.diagnostic.set()|) then it
requires a namespace.
- *diagnostic-structure*
-A diagnostic is a Lua table with the following keys. Required keys are
-indicated with (+):
-
- bufnr: Buffer number
- lnum(+): The starting line of the diagnostic
- end_lnum: The final line of the diagnostic
- col(+): The starting column of the diagnostic
- end_col: The final column of the diagnostic
- severity: The severity of the diagnostic |vim.diagnostic.severity|
- message(+): The diagnostic text
- source: The source of the diagnostic
- code: The diagnostic code
- user_data: Arbitrary data plugins or users can add
-
-Diagnostics use the same indexing as the rest of the Nvim API (i.e. 0-based
-rows and columns). |api-indexing|
-
*vim.diagnostic.severity* *diagnostic-severity*
The "severity" key in a diagnostic is one of the values defined in
`vim.diagnostic.severity`:
@@ -317,12 +299,24 @@ SIGNS *diagnostic-signs*
Signs are defined for each diagnostic severity. The default text for each sign
is the first letter of the severity name (for example, "E" for ERROR). Signs
-can be customized using the following: >vim
+can be customized with |vim.diagnostic.config()|. Example: >lua
- sign define DiagnosticSignError text=E texthl=DiagnosticSignError linehl= numhl=
- sign define DiagnosticSignWarn text=W texthl=DiagnosticSignWarn linehl= numhl=
- sign define DiagnosticSignInfo text=I texthl=DiagnosticSignInfo linehl= numhl=
- sign define DiagnosticSignHint text=H texthl=DiagnosticSignHint linehl= numhl=
+ -- Highlight entire line for errors
+ -- Highlight the line number for warnings
+ vim.diagnostic.config({
+ signs = {
+ text = {
+ [vim.diagnostic.severity.ERROR] = '',
+ [vim.diagnostic.severity.WARN] = '',
+ },
+ linehl = {
+ [vim.diagnostic.severity.ERROR] = 'ErrorMsg',
+ },
+ numhl = {
+ [vim.diagnostic.severity.WARN] = 'WarningMsg',
+ },
+ },
+ })
When the "severity_sort" option is set (see |vim.diagnostic.config()|) the
priority of each sign depends on the severity of the associated diagnostic.
@@ -349,6 +343,236 @@ Example: >lua
==============================================================================
Lua module: vim.diagnostic *diagnostic-api*
+*vim.Diagnostic*
+ *diagnostic-structure*
+
+ Diagnostics use the same indexing as the rest of the Nvim API (i.e.
+ 0-based rows and columns). |api-indexing|
+
+ Fields: ~
+ • {bufnr}? (`integer`) Buffer number
+ • {lnum} (`integer`) The starting line of the diagnostic
+ (0-indexed)
+ • {end_lnum}? (`integer`) The final line of the diagnostic (0-indexed)
+ • {col} (`integer`) The starting column of the diagnostic
+ (0-indexed)
+ • {end_col}? (`integer`) The final column of the diagnostic
+ (0-indexed)
+ • {severity}? (`vim.diagnostic.Severity`) The severity of the
+ diagnostic |vim.diagnostic.severity|
+ • {message} (`string`) The diagnostic text
+ • {source}? (`string`) The source of the diagnostic
+ • {code}? (`string|integer`) The diagnostic code
+ • {_tags}? (`{ deprecated: boolean, unnecessary: boolean}`)
+ • {user_data}? (`any`) arbitrary data plugins can add
+ • {namespace}? (`integer`)
+
+*vim.diagnostic.GetOpts*
+ A table with the following keys:
+
+ Fields: ~
+ • {namespace}? (`integer`) Limit diagnostics to the given namespace.
+ • {lnum}? (`integer`) Limit diagnostics to the given line number.
+ • {severity}? (`vim.diagnostic.SeverityFilter`) See
+ |diagnostic-severity|.
+
+*vim.diagnostic.GotoOpts*
+ Extends: |vim.diagnostic.GetOpts|
+
+ Configuration table with the following keys:
+
+ Fields: ~
+ • {cursor_position}? (`{[1]:integer,[2]:integer}`, default: current cursor position)
+ Cursor position as a `(row, col)` tuple. See
+ |nvim_win_get_cursor()|.
+ • {wrap}? (`boolean`, default: `true`) Whether to loop
+ around file or not. Similar to 'wrapscan'.
+ • {severity} (`vim.diagnostic.Severity`) See
+ |diagnostic-severity|.
+ • {float}? (`boolean|vim.diagnostic.Opts.Float`, default:
+ `true`) If `true`, call
+ |vim.diagnostic.open_float()| after moving. If a
+ table, pass the table as the {opts} parameter to
+ |vim.diagnostic.open_float()|. Unless overridden,
+ the float will show diagnostics at the new cursor
+ position (as if "cursor" were passed to the
+ "scope" option).
+ • {win_id}? (`integer`, default: `0`) Window ID
+
+*vim.diagnostic.NS*
+
+ Fields: ~
+ • {name} (`string`)
+ • {opts} (`vim.diagnostic.Opts`) See |vim.diagnostic.Opts|.
+ • {user_data} (`table`)
+ • {disabled}? (`boolean`)
+
+*vim.diagnostic.Opts*
+ Each of the configuration options below accepts one of the following:
+ • `false`: Disable this feature
+ • `true`: Enable this feature, use default settings.
+ • `table`: Enable this feature with overrides. Use an empty table to use
+ default values.
+ • `function`: Function with signature (namespace, bufnr) that returns any
+ of the above.
+
+ Fields: ~
+ • {underline}? (`boolean|vim.diagnostic.Opts.Underline|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.Underline`, default: `true`)
+ Use underline for diagnostics.
+ • {virtual_text}? (`boolean|vim.diagnostic.Opts.VirtualText|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.VirtualText`, default: `true`)
+ Use virtual text for diagnostics. If multiple
+ diagnostics are set for a namespace, one prefix
+ per diagnostic + the last diagnostic message are
+ shown.
+ • {signs}? (`boolean|vim.diagnostic.Opts.Signs|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.Signs`, default: `true`)
+ Use signs for diagnostics |diagnostic-signs|.
+ • {float}? (`boolean|vim.diagnostic.Opts.Float|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.Float`)
+ Options for floating windows. See
+ |vim.diagnostic.Opts.Float|.
+ • {update_in_insert}? (`boolean`, default: `false`) Update diagnostics
+ in Insert mode (if `false`, diagnostics are
+ updated on |InsertLeave|)
+ • {severity_sort}? (`boolean|{reverse?:boolean}`, default: `false)
+ Sort diagnostics by severity. This affects the
+ order in which signs and virtual text are
+ displayed. When true, higher severities are
+ displayed before lower severities (e.g. ERROR is
+ displayed before WARN). Options:
+ • {reverse}? (boolean) Reverse sort order
+
+*vim.diagnostic.Opts.Float*
+
+ Fields: ~
+ • {bufnr}? (`integer`, default: current buffer) Buffer number
+ to show diagnostics from.
+ • {namespace}? (`integer`) Limit diagnostics to the given namespace
+ • {scope}? (`'line'|'buffer'|'cursor'|'c'|'l'|'b'`, default:
+ `line`) Show diagnostics from the whole buffer
+ (`buffer"`, the current cursor line (`line`), or the
+ current cursor position (`cursor`). Shorthand
+ versions are also accepted (`c` for `cursor`, `l`
+ for `line`, `b` for `buffer`).
+ • {pos}? (`integer|{[1]:integer,[2]:integer}`) If {scope} is
+ "line" or "cursor", use this position rather than
+ the cursor position. If a number, interpreted as a
+ line number; otherwise, a (row, col) tuple.
+ • {severity_sort}? (`boolean|{reverse?:boolean}`, default: `false`)
+ Sort diagnostics by severity. Overrides the setting
+ from |vim.diagnostic.config()|.
+ • {severity}? (`vim.diagnostic.SeverityFilter`) See
+ |diagnostic-severity|. Overrides the setting from
+ |vim.diagnostic.config()|.
+ • {header}? (`string|{[1]:string,[2]:any}`) String to use as the
+ header for the floating window. If a table, it is
+ interpreted as a `[text, hl_group]` tuple. Overrides
+ the setting from |vim.diagnostic.config()|.
+ • {source}? (`boolean|'if_many'`) Include the diagnostic source
+ in the message. Use "if_many" to only show sources
+ if there is more than one source of diagnostics in
+ the buffer. Otherwise, any truthy value means to
+ always show the diagnostic source. Overrides the
+ setting from |vim.diagnostic.config()|.
+ • {format}? (`fun(diagnostic:vim.Diagnostic): string`) A
+ function that takes a diagnostic as input and
+ returns a string. The return value is the text used
+ to display the diagnostic. Overrides the setting
+ from |vim.diagnostic.config()|.
+ • {prefix}? (`string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)`)
+ Prefix each diagnostic in the floating window:
+ • If a `function`, {i} is the index of the
+ diagnostic being evaluated and {total} is the
+ total number of diagnostics displayed in the
+ window. The function should return a `string`
+ which is prepended to each diagnostic in the
+ window as well as an (optional) highlight group
+ which will be used to highlight the prefix.
+ • If a `table`, it is interpreted as a
+ `[text, hl_group]` tuple as in |nvim_echo()|
+ • If a `string`, it is prepended to each diagnostic
+ in the window with no highlight. Overrides the
+ setting from |vim.diagnostic.config()|.
+ • {suffix}? (`string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)`)
+ Same as {prefix}, but appends the text to the
+ diagnostic instead of prepending it. Overrides the
+ setting from |vim.diagnostic.config()|.
+ • {focus_id}? (`string`)
+
+*vim.diagnostic.Opts.Signs*
+
+ Fields: ~
+ • {severity}? (`vim.diagnostic.SeverityFilter`) Only show virtual text
+ for diagnostics matching the given severity
+ |diagnostic-severity|
+ • {priority}? (`integer`, default: `10`) Base priority to use for
+ signs. When {severity_sort} is used, the priority of a
+ sign is adjusted based on its severity. Otherwise, all
+ signs use the same priority.
+ • {text}? (`table<vim.diagnostic.Severity,string>`) A table mapping
+ |diagnostic-severity| to the sign text to display in the
+ sign column. The default is to use `"E"`, `"W"`, `"I"`,
+ and `"H"` for errors, warnings, information, and hints,
+ respectively. Example: >lua
+ vim.diagnostic.config({
+ signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } }
+ })
+<
+ • {numhl}? (`table<vim.diagnostic.Severity,string>`) A table mapping
+ |diagnostic-severity| to the highlight group used for the
+ line number where the sign is placed.
+ • {linehl}? (`table<vim.diagnostic.Severity,string>`) A table mapping
+ |diagnostic-severity| to the highlight group used for the
+ whole line the sign is placed in.
+
+*vim.diagnostic.Opts.Underline*
+
+ Fields: ~
+ • {severity}? (`vim.diagnostic.SeverityFilter`) Only underline
+ diagnostics matching the given severity
+ |diagnostic-severity|.
+
+*vim.diagnostic.Opts.VirtualText*
+
+ Fields: ~
+ • {severity}? (`vim.diagnostic.SeverityFilter`) Only show
+ virtual text for diagnostics matching the given
+ severity |diagnostic-severity|
+ • {source}? (`boolean|"if_many"`) Include the diagnostic
+ source in virtual text. Use `'if_many'` to only
+ show sources if there is more than one
+ diagnostic source in the buffer. Otherwise, any
+ truthy value means to always show the diagnostic
+ source.
+ • {spacing}? (`integer`) Amount of empty spaces inserted at
+ the beginning of the virtual text.
+ • {prefix}? (`string|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string)`)
+ Prepend diagnostic message with prefix. If a
+ `function`, {i} is the index of the diagnostic
+ being evaluated, and {total} is the total number
+ of diagnostics for the line. This can be used to
+ render diagnostic symbols or error codes.
+ • {suffix}? (`string|(fun(diagnostic:vim.Diagnostic): string)`)
+ Append diagnostic message with suffix. This can
+ be used to render an LSP diagnostic error code.
+ • {format}? (`fun(diagnostic:vim.Diagnostic): string`) The
+ return value is the text used to display the
+ diagnostic. Example: >lua
+ function(diagnostic)
+ if diagnostic.severity == vim.diagnostic.severity.ERROR then
+ return string.format("E: %s", diagnostic.message)
+ end
+ return diagnostic.message
+ end
+<
+ • {hl_mode}? (`'replace'|'combine'|'blend'`) See
+ |nvim_buf_set_extmark()|.
+ • {virt_text}? (`{[1]:string,[2]:any}[]`) See
+ |nvim_buf_set_extmark()|.
+ • {virt_text_pos}? (`'eol'|'overlay'|'right_align'|'inline'`) See
+ |nvim_buf_set_extmark()|.
+ • {virt_text_win_col}? (`integer`) See |nvim_buf_set_extmark()|.
+ • {virt_text_hide}? (`boolean`) See |nvim_buf_set_extmark()|.
+
+
config({opts}, {namespace}) *vim.diagnostic.config()*
Configure diagnostic options globally or for a specific diagnostic
namespace.
@@ -368,115 +592,56 @@ config({opts}, {namespace}) *vim.diagnostic.config()*
then virtual text will not be enabled for those diagnostics.
- Note: ~
- • Each of the configuration options below accepts one of the following:
- • `false`: Disable this feature
- • `true`: Enable this feature, use default settings.
- • `table`: Enable this feature with overrides. Use an empty table to
- use default values.
- • `function`: Function with signature (namespace, bufnr) that returns
- any of the above.
+ Parameters: ~
+ • {opts} (`vim.diagnostic.Opts?`) When omitted or `nil`, retrieve
+ the current configuration. Otherwise, a configuration
+ table (see |vim.diagnostic.Opts|).
+ • {namespace} (`integer?`) Update the options for the given namespace.
+ When omitted, update the global diagnostic options.
+
+ Return: ~
+ (`vim.diagnostic.Opts?`) Current diagnostic config if {opts} is
+ omitted. See |vim.diagnostic.Opts|.
+
+count({bufnr}, {opts}) *vim.diagnostic.count()*
+ Get current diagnostics count.
Parameters: ~
- • {opts} (table|nil) When omitted or "nil", retrieve the current
- configuration. Otherwise, a configuration table with the
- following keys:
- • underline: (default true) Use underline for
- diagnostics. Options:
- • severity: Only underline diagnostics matching the
- given severity |diagnostic-severity|
-
- • virtual_text: (default true) Use virtual text for
- diagnostics. If multiple diagnostics are set for a
- namespace, one prefix per diagnostic + the last
- diagnostic message are shown. In addition to the
- options listed below, the "virt_text" options of
- |nvim_buf_set_extmark()| may also be used here (e.g.
- "virt_text_pos" and "hl_mode"). Options:
- • severity: Only show virtual text for diagnostics
- matching the given severity |diagnostic-severity|
- • source: (boolean or string) Include the diagnostic
- source in virtual text. Use "if_many" to only show
- sources if there is more than one diagnostic source
- in the buffer. Otherwise, any truthy value means to
- always show the diagnostic source.
- • spacing: (number) Amount of empty spaces inserted at
- the beginning of the virtual text.
- • prefix: (string or function) prepend diagnostic
- message with prefix. If a function, it must have the
- signature (diagnostic, i, total) -> string, where
- {diagnostic} is of type |diagnostic-structure|, {i}
- is the index of the diagnostic being evaluated, and
- {total} is the total number of diagnostics for the
- line. This can be used to render diagnostic symbols
- or error codes.
- • suffix: (string or function) Append diagnostic
- message with suffix. If a function, it must have the
- signature (diagnostic) -> string, where {diagnostic}
- is of type |diagnostic-structure|. This can be used
- to render an LSP diagnostic error code.
- • format: (function) A function that takes a diagnostic
- as input and returns a string. The return value is
- the text used to display the diagnostic. Example: >lua
-
- function(diagnostic)
- if diagnostic.severity == vim.diagnostic.severity.ERROR then
- return string.format("E: %s", diagnostic.message)
- end
- return diagnostic.message
- end
-<
+ • {bufnr} (`integer?`) Buffer number to get diagnostics from. Use 0 for
+ current buffer or nil for all buffers.
+ • {opts} (`vim.diagnostic.GetOpts?`) See |vim.diagnostic.GetOpts|.
- • signs: (default true) Use signs for diagnostics.
- Options:
- • severity: Only show signs for diagnostics matching
- the given severity |diagnostic-severity|
- • priority: (number, default 10) Base priority to use
- for signs. When {severity_sort} is used, the priority
- of a sign is adjusted based on its severity.
- Otherwise, all signs use the same priority.
-
- • float: Options for floating windows. See
- |vim.diagnostic.open_float()|.
- • update_in_insert: (default false) Update diagnostics in
- Insert mode (if false, diagnostics are updated on
- InsertLeave)
- • severity_sort: (default false) Sort diagnostics by
- severity. This affects the order in which signs and
- virtual text are displayed. When true, higher
- severities are displayed before lower severities (e.g.
- ERROR is displayed before WARN). Options:
- • reverse: (boolean) Reverse sort order
- • {namespace} (integer|nil) Update the options for the given namespace.
- When omitted, update the global diagnostic options.
+ Return: ~
+ (`table`) Table with actually present severity values as keys (see
+ |diagnostic-severity|) and integer counts as values.
disable({bufnr}, {namespace}) *vim.diagnostic.disable()*
Disable diagnostics in the given buffer.
Parameters: ~
- • {bufnr} (integer|nil) Buffer number, or 0 for current buffer.
- When omitted, disable diagnostics in all buffers.
- • {namespace} (integer|nil) Only disable diagnostics for the given
+ • {bufnr} (`integer?`) Buffer number, or 0 for current buffer. When
+ omitted, disable diagnostics in all buffers.
+ • {namespace} (`integer?`) Only disable diagnostics for the given
namespace.
enable({bufnr}, {namespace}) *vim.diagnostic.enable()*
Enable diagnostics in the given buffer.
Parameters: ~
- • {bufnr} (integer|nil) Buffer number, or 0 for current buffer.
- When omitted, enable diagnostics in all buffers.
- • {namespace} (integer|nil) Only enable diagnostics for the given
+ • {bufnr} (`integer?`) Buffer number, or 0 for current buffer. When
+ omitted, enable diagnostics in all buffers.
+ • {namespace} (`integer?`) Only enable diagnostics for the given
namespace.
fromqflist({list}) *vim.diagnostic.fromqflist()*
Convert a list of quickfix items to a list of diagnostics.
Parameters: ~
- • {list} table[] List of quickfix items from |getqflist()| or
+ • {list} (`table[]`) List of quickfix items from |getqflist()| or
|getloclist()|.
Return: ~
- Diagnostic [] array of |diagnostic-structure|
+ (`vim.Diagnostic[]`) See |vim.Diagnostic|.
get({bufnr}, {opts}) *vim.diagnostic.get()*
Get current diagnostics.
@@ -485,96 +650,79 @@ get({bufnr}, {opts}) *vim.diagnostic.get()*
diagnostics in a buffer, use |vim.diagnostic.set()|.
Parameters: ~
- • {bufnr} (integer|nil) Buffer number to get diagnostics from. Use 0
- for current buffer or nil for all buffers.
- • {opts} (table|nil) A table with the following keys:
- • namespace: (number) Limit diagnostics to the given
- namespace.
- • lnum: (number) Limit diagnostics to the given line number.
- • severity: See |diagnostic-severity|.
+ • {bufnr} (`integer?`) Buffer number to get diagnostics from. Use 0 for
+ current buffer or nil for all buffers.
+ • {opts} (`vim.diagnostic.GetOpts?`) See |vim.diagnostic.GetOpts|.
Return: ~
- Diagnostic [] table A list of diagnostic items |diagnostic-structure|. Keys `bufnr` , `end_lnum` , `end_col` , and `severity` are guaranteed to be present.
+ (`vim.Diagnostic[]`) Fields `bufnr`, `end_lnum`, `end_col`, and
+ `severity` are guaranteed to be present. See |vim.Diagnostic|.
get_namespace({namespace}) *vim.diagnostic.get_namespace()*
Get namespace metadata.
Parameters: ~
- • {namespace} (integer) Diagnostic namespace
+ • {namespace} (`integer`) Diagnostic namespace
Return: ~
- (table) Namespace metadata
+ (`vim.diagnostic.NS`) Namespace metadata. See |vim.diagnostic.NS|.
get_namespaces() *vim.diagnostic.get_namespaces()*
Get current diagnostic namespaces.
Return: ~
- (table) A list of active diagnostic namespaces |vim.diagnostic|.
+ (`table<integer,vim.diagnostic.NS>`) List of active diagnostic
+ namespaces |vim.diagnostic|.
get_next({opts}) *vim.diagnostic.get_next()*
Get the next diagnostic closest to the cursor position.
Parameters: ~
- • {opts} (table|nil) See |vim.diagnostic.goto_next()|
+ • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|.
Return: ~
- Diagnostic|nil Next diagnostic
+ (`vim.Diagnostic?`) Next diagnostic. See |vim.Diagnostic|.
get_next_pos({opts}) *vim.diagnostic.get_next_pos()*
Return the position of the next diagnostic in the current buffer.
Parameters: ~
- • {opts} (table|nil) See |vim.diagnostic.goto_next()|
+ • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|.
Return: ~
- table|false Next diagnostic position as a (row, col) tuple or false if
- no next diagnostic.
+ (`table|false`) Next diagnostic position as a `(row, col)` tuple or
+ false if no next diagnostic.
get_prev({opts}) *vim.diagnostic.get_prev()*
Get the previous diagnostic closest to the cursor position.
Parameters: ~
- • {opts} nil|table See |vim.diagnostic.goto_next()|
+ • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|.
Return: ~
- Diagnostic|nil Previous diagnostic
+ (`vim.Diagnostic?`) Previous diagnostic. See |vim.Diagnostic|.
get_prev_pos({opts}) *vim.diagnostic.get_prev_pos()*
Return the position of the previous diagnostic in the current buffer.
Parameters: ~
- • {opts} (table|nil) See |vim.diagnostic.goto_next()|
+ • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|.
Return: ~
- table|false Previous diagnostic position as a (row, col) tuple or
- false if there is no prior diagnostic
+ (`table|false`) Previous diagnostic position as a `(row, col)` tuple
+ or `false` if there is no prior diagnostic.
goto_next({opts}) *vim.diagnostic.goto_next()*
Move to the next diagnostic.
Parameters: ~
- • {opts} (table|nil) Configuration table with the following keys:
- • namespace: (number) Only consider diagnostics from the given
- namespace.
- • cursor_position: (cursor position) Cursor position as a
- (row, col) tuple. See |nvim_win_get_cursor()|. Defaults to
- the current cursor position.
- • wrap: (boolean, default true) Whether to loop around file or
- not. Similar to 'wrapscan'.
- • severity: See |diagnostic-severity|.
- • float: (boolean or table, default true) If "true", call
- |vim.diagnostic.open_float()| after moving. If a table, pass
- the table as the {opts} parameter to
- |vim.diagnostic.open_float()|. Unless overridden, the float
- will show diagnostics at the new cursor position (as if
- "cursor" were passed to the "scope" option).
- • win_id: (number, default 0) Window ID
+ • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|.
goto_prev({opts}) *vim.diagnostic.goto_prev()*
Move to the previous diagnostic in the current buffer.
Parameters: ~
- • {opts} (table|nil) See |vim.diagnostic.goto_next()|
+ • {opts} (`vim.diagnostic.GotoOpts?`) See |vim.diagnostic.GotoOpts|.
hide({namespace}, {bufnr}) *vim.diagnostic.hide()*
Hide currently displayed diagnostics.
@@ -587,22 +735,22 @@ hide({namespace}, {bufnr}) *vim.diagnostic.hide()*
|vim.diagnostic.disable()|.
Parameters: ~
- • {namespace} (integer|nil) Diagnostic namespace. When omitted, hide diagnostics from all
- namespaces.
- • {bufnr} (integer|nil) Buffer number, or 0 for current buffer.
- When omitted, hide diagnostics in all buffers.
+ • {namespace} (`integer?`) Diagnostic namespace. When omitted, hide
+ diagnostics from all namespaces.
+ • {bufnr} (`integer?`) Buffer number, or 0 for current buffer. When
+ omitted, hide diagnostics in all buffers.
is_disabled({bufnr}, {namespace}) *vim.diagnostic.is_disabled()*
Check whether diagnostics are disabled in a given buffer.
Parameters: ~
- • {bufnr} (integer|nil) Buffer number, or 0 for current buffer.
- • {namespace} (integer|nil) Diagnostic namespace. When omitted, checks if all diagnostics are
- disabled in {bufnr}. Otherwise, only checks if
- diagnostics from {namespace} are disabled.
+ • {bufnr} (`integer?`) Buffer number, or 0 for current buffer.
+ • {namespace} (`integer?`) Diagnostic namespace. When omitted, checks
+ if all diagnostics are disabled in {bufnr}. Otherwise,
+ only checks if diagnostics from {namespace} are disabled.
Return: ~
- (boolean)
+ (`boolean`)
*vim.diagnostic.match()*
match({str}, {pat}, {groups}, {severity_map}, {defaults})
@@ -612,7 +760,7 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults})
WARNING filename:27:3: Variable 'foo' does not exist
<
- This can be parsed into a diagnostic |diagnostic-structure| with: >lua
+ This can be parsed into |vim.Diagnostic| structure with: >lua
local s = "WARNING filename:27:3: Variable 'foo' does not exist"
local pattern = "^(%w+) %w+:(%d+):(%d+): (.+)$"
local groups = { "severity", "lnum", "col", "message" }
@@ -620,75 +768,30 @@ match({str}, {pat}, {groups}, {severity_map}, {defaults})
<
Parameters: ~
- • {str} (string) String to parse diagnostics from.
- • {pat} (string) Lua pattern with capture groups.
- • {groups} (table) List of fields in a |diagnostic-structure| to
- associate with captures from {pat}.
- • {severity_map} (table) A table mapping the severity field from
+ • {str} (`string`) String to parse diagnostics from.
+ • {pat} (`string`) Lua pattern with capture groups.
+ • {groups} (`string[]`) List of fields in a |vim.Diagnostic|
+ structure to associate with captures from {pat}.
+ • {severity_map} (`table`) A table mapping the severity field from
{groups} with an item from |vim.diagnostic.severity|.
- • {defaults} (table|nil) Table of default values for any fields not
+ • {defaults} (`table?`) Table of default values for any fields not
listed in {groups}. When omitted, numeric values
default to 0 and "severity" defaults to ERROR.
Return: ~
- Diagnostic|nil: |diagnostic-structure| or `nil` if {pat} fails to
- match {str}.
+ (`vim.Diagnostic?`) |vim.Diagnostic| structure or `nil` if {pat} fails
+ to match {str}.
-open_float({opts}, {...}) *vim.diagnostic.open_float()*
+open_float({opts}) *vim.diagnostic.open_float()*
Show diagnostics in a floating window.
Parameters: ~
- • {opts} (table|nil) Configuration table with the same keys as
- |vim.lsp.util.open_floating_preview()| in addition to the
- following:
- • bufnr: (number) Buffer number to show diagnostics from.
- Defaults to the current buffer.
- • namespace: (number) Limit diagnostics to the given namespace
- • scope: (string, default "line") Show diagnostics from the
- whole buffer ("buffer"), the current cursor line ("line"),
- or the current cursor position ("cursor"). Shorthand
- versions are also accepted ("c" for "cursor", "l" for
- "line", "b" for "buffer").
- • pos: (number or table) If {scope} is "line" or "cursor", use
- this position rather than the cursor position. If a number,
- interpreted as a line number; otherwise, a (row, col) tuple.
- • severity_sort: (default false) Sort diagnostics by severity.
- Overrides the setting from |vim.diagnostic.config()|.
- • severity: See |diagnostic-severity|. Overrides the setting
- from |vim.diagnostic.config()|.
- • header: (string or table) String to use as the header for
- the floating window. If a table, it is interpreted as a
- [text, hl_group] tuple. Overrides the setting from
- |vim.diagnostic.config()|.
- • source: (boolean or string) Include the diagnostic source in
- the message. Use "if_many" to only show sources if there is
- more than one source of diagnostics in the buffer.
- Otherwise, any truthy value means to always show the
- diagnostic source. Overrides the setting from
- |vim.diagnostic.config()|.
- • format: (function) A function that takes a diagnostic as
- input and returns a string. The return value is the text
- used to display the diagnostic. Overrides the setting from
- |vim.diagnostic.config()|.
- • prefix: (function, string, or table) Prefix each diagnostic
- in the floating window. If a function, it must have the
- signature (diagnostic, i, total) -> (string, string), where
- {i} is the index of the diagnostic being evaluated and
- {total} is the total number of diagnostics displayed in the
- window. The function should return a string which is
- prepended to each diagnostic in the window as well as an
- (optional) highlight group which will be used to highlight
- the prefix. If {prefix} is a table, it is interpreted as a
- [text, hl_group] tuple as in |nvim_echo()|; otherwise, if
- {prefix} is a string, it is prepended to each diagnostic in
- the window with no highlight. Overrides the setting from
- |vim.diagnostic.config()|.
- • suffix: Same as {prefix}, but appends the text to the
- diagnostic instead of prepending it. Overrides the setting
- from |vim.diagnostic.config()|.
+ • {opts} (`vim.diagnostic.Opts.Float?`) See
+ |vim.diagnostic.Opts.Float|.
- Return: ~
- integer|nil, integer|nil: ({float_bufnr}, {win_id})
+ Return (multiple): ~
+ (`integer?`) float_bufnr
+ (`integer?`) win_id
reset({namespace}, {bufnr}) *vim.diagnostic.reset()*
Remove all diagnostics from the given namespace.
@@ -699,76 +802,78 @@ reset({namespace}, {bufnr}) *vim.diagnostic.reset()*
re-displayed, use |vim.diagnostic.hide()|.
Parameters: ~
- • {namespace} (integer|nil) Diagnostic namespace. When omitted, remove diagnostics from all
- namespaces.
- • {bufnr} (integer|nil) Remove diagnostics for the given buffer.
+ • {namespace} (`integer?`) Diagnostic namespace. When omitted, remove
+ diagnostics from all namespaces.
+ • {bufnr} (`integer?`) Remove diagnostics for the given buffer.
When omitted, diagnostics are removed for all buffers.
set({namespace}, {bufnr}, {diagnostics}, {opts}) *vim.diagnostic.set()*
Set diagnostics for the given namespace and buffer.
Parameters: ~
- • {namespace} (integer) The diagnostic namespace
- • {bufnr} (integer) Buffer number
- • {diagnostics} (table) A list of diagnostic items
- |diagnostic-structure|
- • {opts} (table|nil) Display options to pass to
- |vim.diagnostic.show()|
+ • {namespace} (`integer`) The diagnostic namespace
+ • {bufnr} (`integer`) Buffer number
+ • {diagnostics} (`vim.Diagnostic[]`) See |vim.Diagnostic|.
+ • {opts} (`vim.diagnostic.Opts?`) Display options to pass to
+ |vim.diagnostic.show()|. See |vim.diagnostic.Opts|.
setloclist({opts}) *vim.diagnostic.setloclist()*
Add buffer diagnostics to the location list.
Parameters: ~
- • {opts} (table|nil) Configuration table with the following keys:
- • namespace: (number) Only add diagnostics from the given
+ • {opts} (`table?`) Configuration table with the following keys:
+ • {namespace}? (`integer`) Only add diagnostics from the given
namespace.
- • winnr: (number, default 0) Window number to set location
- list for.
- • open: (boolean, default true) Open the location list after
- setting.
- • title: (string) Title of the location list. Defaults to
+ • {winnr}? (`integer`, default: `0`) Window number to set
+ location list for.
+ • {open}? (`boolean`, default: `true`) Open the location list
+ after setting.
+ • {title}? (`string`) Title of the location list. Defaults to
"Diagnostics".
- • severity: See |diagnostic-severity|.
+ • {severity}? (`vim.diagnostic.Severity`) See
+ |diagnostic-severity|.
setqflist({opts}) *vim.diagnostic.setqflist()*
Add all diagnostics to the quickfix list.
Parameters: ~
- • {opts} (table|nil) Configuration table with the following keys:
- • namespace: (number) Only add diagnostics from the given
+ • {opts} (`table?`) Configuration table with the following keys:
+ • {namespace}? (`integer`) Only add diagnostics from the given
namespace.
- • open: (boolean, default true) Open quickfix list after
- setting.
- • title: (string) Title of quickfix list. Defaults to
+ • {open}? (`boolean`, default: `true`) Open quickfix list
+ after setting.
+ • {title}? (`string`) Title of quickfix list. Defaults to
"Diagnostics".
- • severity: See |diagnostic-severity|.
+ • {severity}? (`vim.diagnostic.Severity`) See
+ |diagnostic-severity|.
*vim.diagnostic.show()*
show({namespace}, {bufnr}, {diagnostics}, {opts})
Display diagnostics for the given namespace and buffer.
Parameters: ~
- • {namespace} (integer|nil) Diagnostic namespace. When omitted, show diagnostics from all
- namespaces.
- • {bufnr} (integer|nil) Buffer number, or 0 for current buffer.
+ • {namespace} (`integer?`) Diagnostic namespace. When omitted, show
+ diagnostics from all namespaces.
+ • {bufnr} (`integer?`) Buffer number, or 0 for current buffer.
When omitted, show diagnostics in all buffers.
- • {diagnostics} (table|nil) The diagnostics to display. When omitted,
- use the saved diagnostics for the given namespace and
- buffer. This can be used to display a list of
- diagnostics without saving them or to display only a
- subset of diagnostics. May not be used when {namespace}
- or {bufnr} is nil.
- • {opts} (table|nil) Display options. See
- |vim.diagnostic.config()|.
+ • {diagnostics} (`vim.Diagnostic[]?`) The diagnostics to display. When
+ omitted, use the saved diagnostics for the given
+ namespace and buffer. This can be used to display a
+ list of diagnostics without saving them or to display
+ only a subset of diagnostics. May not be used when
+ {namespace} or {bufnr} is nil. See |vim.Diagnostic|.
+ • {opts} (`vim.diagnostic.Opts?`) Display options. See
+ |vim.diagnostic.Opts|.
toqflist({diagnostics}) *vim.diagnostic.toqflist()*
Convert a list of diagnostics to a list of quickfix items that can be
passed to |setqflist()| or |setloclist()|.
Parameters: ~
- • {diagnostics} (table) List of diagnostics |diagnostic-structure|.
+ • {diagnostics} (`vim.Diagnostic[]`) See |vim.Diagnostic|.
Return: ~
- table[] of quickfix list items |setqflist-what|
+ (`table[]`) Quickfix list items |setqflist-what|
+
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt
index 7df2eb9742..1a4572e94a 100644
--- a/runtime/doc/editing.txt
+++ b/runtime/doc/editing.txt
@@ -1291,8 +1291,9 @@ b:browsefilter variable. You would most likely set b:browsefilter in a
filetype plugin, so that the browse dialog would contain entries related to
the type of file you are currently editing. Disadvantage: This makes it
difficult to start editing a file of a different type. To overcome this, you
-may want to add "All Files\t*.*\n" as the final filter, so that the user can
-still access any desired file.
+may want to add "All Files (*.*)\t*\n" as the final filter on Windows or "All
+Files (*)\t*\n" on other platforms, so that the user can still access any
+desired file.
To avoid setting browsefilter when Vim does not actually support it, you can
use has("browsefilter"): >
diff --git a/runtime/doc/editorconfig.txt b/runtime/doc/editorconfig.txt
index 7c6e8fb95f..a2281a7b7c 100644
--- a/runtime/doc/editorconfig.txt
+++ b/runtime/doc/editorconfig.txt
@@ -49,6 +49,8 @@ indent_size A number indicating the size of a single indent.
Alternatively, use the value "tab" to use the value of
the tab_width property. Sets the 'shiftwidth' and
'softtabstop' options.
+ If this value is not "tab" and the tab_width property
+ is not set, 'tabstop' is also set to this value.
*editorconfig_insert_final_newline*
insert_final_newline "true" or "false" to ensure the file always has a
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index a73932be00..ef416fe56f 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -252,10 +252,15 @@ List concatenation ~
*list-concatenation*
Two lists can be concatenated with the "+" operator: >
:let longlist = mylist + [5, 6]
- :let mylist += [7, 8]
+ :let longlist = [5, 6] + mylist
+To prepend or append an item, turn it into a list by putting [] around it.
-To prepend or append an item, turn the item into a list by putting [] around
-it. To change a list in-place, refer to |list-modification| below.
+A list can be concatenated with another one in-place using |:let+=| or
+|extend()|: >
+ :let mylist += [7, 8]
+ :call extend(mylist, [7, 8])
+<
+See |list-modification| below for more about changing a list in-place.
Sublist ~
@@ -374,6 +379,18 @@ To change part of a list you can specify the first and last item to be
modified. The value must at least have the number of items in the range: >
:let list[3:5] = [3, 4, 5]
+To add items to a List in-place, you can use |:let+=| (|list-concatenation|): >
+ :let listA = [1, 2]
+ :let listA += [3, 4]
+<
+When two variables refer to the same List, changing one List in-place will
+cause the referenced List to be changed in-place: >
+ :let listA = [1, 2]
+ :let listB = listA
+ :let listB += [3, 4]
+ :echo listA
+ [1, 2, 3, 4]
+<
Adding and removing items from a list is done with functions. Here are a few
examples: >
:call insert(list, 'a') " prepend item 'a'
@@ -682,12 +699,15 @@ This calls Doit() with 0x11, 0x22 and 0x33.
Blob concatenation ~
-
+ *blob-concatenation*
Two blobs can be concatenated with the "+" operator: >
:let longblob = myblob + 0z4455
+ :let longblob = 0z4455 + myblob
+<
+A blob can be concatenated with another one in-place using |:let+=|: >
:let myblob += 0z6677
-
-To change a blob in-place see |blob-modification| below.
+<
+See |blob-modification| below for more about changing a blob in-place.
Part of a blob ~
@@ -730,6 +750,18 @@ To change part of a blob you can specify the first and last byte to be
modified. The value must have the same number of bytes in the range: >
:let blob[3:5] = 0z334455
+To add items to a Blob in-place, you can use |:let+=| (|blob-concatenation|): >
+ :let blobA = 0z1122
+ :let blobA += 0z3344
+<
+When two variables refer to the same Blob, changing one Blob in-place will
+cause the referenced Blob to be changed in-place: >
+ :let blobA = 0z1122
+ :let blobB = blobA
+ :let blobB += 0z3344
+ :echo blobA
+ 0z11223344
+<
You can also use the functions |add()|, |remove()| and |insert()|.
@@ -1765,624 +1797,9 @@ variables for each buffer. Use local buffer variables instead |b:var|.
PREDEFINED VIM VARIABLES *vim-variable* *v:var* *v:*
*E963*
-Some variables can be set by the user, but the type cannot be changed.
-
- *v:argv* *argv-variable*
-v:argv The command line arguments Vim was invoked with. This is a
- list of strings. The first item is the Vim command.
- See |v:progpath| for the command with full path.
-
- *v:char* *char-variable*
-v:char Argument for evaluating 'formatexpr' and used for the typed
- character when using <expr> in an abbreviation |:map-<expr>|.
- It is also used by the |InsertCharPre| and |InsertEnter| events.
-
- *v:charconvert_from* *charconvert_from-variable*
-v:charconvert_from
- The name of the character encoding of a file to be converted.
- Only valid while evaluating the 'charconvert' option.
-
- *v:charconvert_to* *charconvert_to-variable*
-v:charconvert_to
- The name of the character encoding of a file after conversion.
- Only valid while evaluating the 'charconvert' option.
-
- *v:cmdarg* *cmdarg-variable*
-v:cmdarg
- The extra arguments ("++p", "++enc=", "++ff=") given to a file
- read/write command. This is set before an autocommand event
- for a file read/write command is triggered. There is a
- leading space to make it possible to append this variable
- directly after the read/write command. Note: "+cmd" isn't
- included here, because it will be executed anyway.
-
- *v:collate* *collate-variable*
-v:collate The current locale setting for collation order of the runtime
- environment. This allows Vim scripts to be aware of the
- current locale encoding. Technical: it's the value of
- LC_COLLATE. When not using a locale the value is "C".
- This variable can not be set directly, use the |:language|
- command.
- See |multi-lang|.
-
- *v:cmdbang* *cmdbang-variable*
-v:cmdbang Set like v:cmdarg for a file read/write command. When a "!"
- was used the value is 1, otherwise it is 0. Note that this
- can only be used in autocommands. For user commands |<bang>|
- can be used.
-
- *v:completed_item* *completed_item-variable*
-v:completed_item
- Dictionary containing the most recent |complete-items| after
- |CompleteDone|. Empty if the completion failed, or after
- leaving and re-entering insert mode.
- Note: Plugins can modify the value to emulate the builtin
- |CompleteDone| event behavior.
-
- *v:count* *count-variable*
-v:count The count given for the last Normal mode command. Can be used
- to get the count before a mapping. Read-only. Example: >
- :map _x :<C-U>echo "the count is " .. v:count<CR>
-< Note: The <C-U> is required to remove the line range that you
- get when typing ':' after a count.
- When there are two counts, as in "3d2w", they are multiplied,
- just like what happens in the command, "d6w" for the example.
- Also used for evaluating the 'formatexpr' option.
-
- *v:count1* *count1-variable*
-v:count1 Just like "v:count", but defaults to one when no count is
- used.
-
- *v:ctype* *ctype-variable*
-v:ctype The current locale setting for characters of the runtime
- environment. This allows Vim scripts to be aware of the
- current locale encoding. Technical: it's the value of
- LC_CTYPE. When not using a locale the value is "C".
- This variable can not be set directly, use the |:language|
- command.
- See |multi-lang|.
-
- *v:dying* *dying-variable*
-v:dying Normally zero. When a deadly signal is caught it's set to
- one. When multiple signals are caught the number increases.
- Can be used in an autocommand to check if Vim didn't
- terminate normally.
- Example: >
- :au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif
-< Note: if another deadly signal is caught when v:dying is one,
- VimLeave autocommands will not be executed.
-
- *v:exiting* *exiting-variable*
-v:exiting Exit code, or |v:null| before invoking the |VimLeavePre|
- and |VimLeave| autocmds. See |:q|, |:x| and |:cquit|.
- Example: >
- :au VimLeave * echo "Exit value is " .. v:exiting
-<
- *v:echospace* *echospace-variable*
-v:echospace Number of screen cells that can be used for an `:echo` message
- in the last screen line before causing the |hit-enter-prompt|.
- Depends on 'showcmd', 'ruler' and 'columns'. You need to
- check 'cmdheight' for whether there are full-width lines
- available above the last line.
-
- *v:errmsg* *errmsg-variable*
-v:errmsg Last given error message.
- Modifiable (can be set).
- Example: >
- :let v:errmsg = ""
- :silent! next
- :if v:errmsg != ""
- : ... handle error
-<
- *v:errors* *errors-variable* *assert-return*
-v:errors Errors found by assert functions, such as |assert_true()|.
- This is a list of strings.
- The assert functions append an item when an assert fails.
- The return value indicates this: a one is returned if an item
- was added to v:errors, otherwise zero is returned.
- To remove old results make it empty: >
- :let v:errors = []
-< If v:errors is set to anything but a list it is made an empty
- list by the assert function.
-
- *v:event* *event-variable*
-v:event Dictionary of event data for the current |autocommand|. Valid
- only during the event lifetime; storing or passing v:event is
- invalid! Copy it instead: >
- au TextYankPost * let g:foo = deepcopy(v:event)
-< Keys vary by event; see the documentation for the specific
- event, e.g. |DirChanged| or |TextYankPost|.
- KEY DESCRIPTION ~
- abort Whether the event triggered during
- an aborting condition (e.g. |c_Esc| or
- |c_CTRL-C| for |CmdlineLeave|).
- chan |channel-id|
- cmdlevel Level of cmdline.
- cmdtype Type of cmdline, |cmdline-char|.
- cwd Current working directory.
- inclusive Motion is |inclusive|, else exclusive.
- scope Event-specific scope name.
- operator Current |operator|. Also set for Ex
- commands (unlike |v:operator|). For
- example if |TextYankPost| is triggered
- by the |:yank| Ex command then
- `v:event.operator` is "y".
- regcontents Text stored in the register as a
- |readfile()|-style list of lines.
- regname Requested register (e.g "x" for "xyy)
- or the empty string for an unnamed
- operation.
- regtype Type of register as returned by
- |getregtype()|.
- visual Selection is visual (as opposed to,
- e.g., via motion).
- completed_item Current selected complete item on
- |CompleteChanged|, Is `{}` when no complete
- item selected.
- height Height of popup menu on |CompleteChanged|
- width width of popup menu on |CompleteChanged|
- row Row count of popup menu on |CompleteChanged|,
- relative to screen.
- col Col count of popup menu on |CompleteChanged|,
- relative to screen.
- size Total number of completion items on
- |CompleteChanged|.
- scrollbar Is |v:true| if popup menu have scrollbar, or
- |v:false| if not.
- changed_window Is |v:true| if the event fired while
- changing window (or tab) on |DirChanged|.
- status Job status or exit code, -1 means "unknown". |TermClose|
-
- *v:exception* *exception-variable*
-v:exception The value of the exception most recently caught and not
- finished. See also |v:throwpoint| and |throw-variables|.
- Example: >
- :try
- : throw "oops"
- :catch /.*/
- : echo "caught " .. v:exception
- :endtry
-< Output: "caught oops".
-
- *v:false* *false-variable*
-v:false Special value used to put "false" in JSON and msgpack. See
- |json_encode()|. This value is converted to "v:false" when used
- as a String (e.g. in |expr5| with string concatenation
- operator) and to zero when used as a Number (e.g. in |expr5|
- or |expr7| when used with numeric operators). Read-only.
-
- *v:fcs_reason* *fcs_reason-variable*
-v:fcs_reason The reason why the |FileChangedShell| event was triggered.
- Can be used in an autocommand to decide what to do and/or what
- to set v:fcs_choice to. Possible values:
- deleted file no longer exists
- conflict file contents, mode or timestamp was
- changed and buffer is modified
- changed file contents has changed
- mode mode of file changed
- time only file timestamp changed
-
- *v:fcs_choice* *fcs_choice-variable*
-v:fcs_choice What should happen after a |FileChangedShell| event was
- triggered. Can be used in an autocommand to tell Vim what to
- do with the affected buffer:
- reload Reload the buffer (does not work if
- the file was deleted).
- edit Reload the buffer and detect the
- values for options such as
- 'fileformat', 'fileencoding', 'binary'
- (does not work if the file was
- deleted).
- ask Ask the user what to do, as if there
- was no autocommand. Except that when
- only the timestamp changed nothing
- will happen.
- <empty> Nothing, the autocommand should do
- everything that needs to be done.
- The default is empty. If another (invalid) value is used then
- Vim behaves like it is empty, there is no warning message.
-
- *v:fname* *fname-variable*
-v:fname When evaluating 'includeexpr': the file name that was
- detected. Empty otherwise.
-
- *v:fname_in* *fname_in-variable*
-v:fname_in The name of the input file. Valid while evaluating:
- option used for ~
- 'charconvert' file to be converted
- 'diffexpr' original file
- 'patchexpr' original file
- And set to the swap file name for |SwapExists|.
-
- *v:fname_out* *fname_out-variable*
-v:fname_out The name of the output file. Only valid while
- evaluating:
- option used for ~
- 'charconvert' resulting converted file [1]
- 'diffexpr' output of diff
- 'patchexpr' resulting patched file
- [1] When doing conversion for a write command (e.g., ":w
- file") it will be equal to v:fname_in. When doing conversion
- for a read command (e.g., ":e file") it will be a temporary
- file and different from v:fname_in.
-
- *v:fname_new* *fname_new-variable*
-v:fname_new The name of the new version of the file. Only valid while
- evaluating 'diffexpr'.
-
- *v:fname_diff* *fname_diff-variable*
-v:fname_diff The name of the diff (patch) file. Only valid while
- evaluating 'patchexpr'.
-
- *v:folddashes* *folddashes-variable*
-v:folddashes Used for 'foldtext': dashes representing foldlevel of a closed
- fold.
- Read-only in the |sandbox|. |fold-foldtext|
-
- *v:foldlevel* *foldlevel-variable*
-v:foldlevel Used for 'foldtext': foldlevel of closed fold.
- Read-only in the |sandbox|. |fold-foldtext|
-
- *v:foldend* *foldend-variable*
-v:foldend Used for 'foldtext': last line of closed fold.
- Read-only in the |sandbox|. |fold-foldtext|
-
- *v:foldstart* *foldstart-variable*
-v:foldstart Used for 'foldtext': first line of closed fold.
- Read-only in the |sandbox|. |fold-foldtext|
-
- *v:hlsearch* *hlsearch-variable*
-v:hlsearch Variable that indicates whether search highlighting is on.
- Setting it makes sense only if 'hlsearch' is enabled. Setting
- this variable to zero acts like the |:nohlsearch| command,
- setting it to one acts like >
- let &hlsearch = &hlsearch
-< Note that the value is restored when returning from a
- function. |function-search-undo|.
-
- *v:insertmode* *insertmode-variable*
-v:insertmode Used for the |InsertEnter| and |InsertChange| autocommand
- events. Values:
- i Insert mode
- r Replace mode
- v Virtual Replace mode
-
- *v:key* *key-variable*
-v:key Key of the current item of a |Dictionary|. Only valid while
- evaluating the expression used with |map()| and |filter()|.
- Read-only.
-
- *v:lang* *lang-variable*
-v:lang The current locale setting for messages of the runtime
- environment. This allows Vim scripts to be aware of the
- current language. Technical: it's the value of LC_MESSAGES.
- The value is system dependent.
- This variable can not be set directly, use the |:language|
- command.
- It can be different from |v:ctype| when messages are desired
- in a different language than what is used for character
- encoding. See |multi-lang|.
-
- *v:lc_time* *lc_time-variable*
-v:lc_time The current locale setting for time messages of the runtime
- environment. This allows Vim scripts to be aware of the
- current language. Technical: it's the value of LC_TIME.
- This variable can not be set directly, use the |:language|
- command. See |multi-lang|.
-
- *v:lnum* *lnum-variable*
-v:lnum Line number for the 'foldexpr' |fold-expr|, 'formatexpr',
- 'indentexpr' and 'statuscolumn' expressions, tab page number
- for 'guitablabel' and 'guitabtooltip'. Only valid while one of
- these expressions is being evaluated. Read-only when in the
- |sandbox|.
-
- *v:lua* *lua-variable*
-v:lua Prefix for calling Lua functions from expressions.
- See |v:lua-call| for more information.
-
- *v:maxcol* *maxcol-variable*
-v:maxcol Maximum line length. Depending on where it is used it can be
- screen columns, characters or bytes. The value currently is
- 2147483647 on all systems.
-
- *v:mouse_win* *mouse_win-variable*
-v:mouse_win Window number for a mouse click obtained with |getchar()|.
- First window has number 1, like with |winnr()|. The value is
- zero when there was no mouse button click.
-
- *v:mouse_winid* *mouse_winid-variable*
-v:mouse_winid |window-ID| for a mouse click obtained with |getchar()|.
- The value is zero when there was no mouse button click.
-
- *v:mouse_lnum* *mouse_lnum-variable*
-v:mouse_lnum Line number for a mouse click obtained with |getchar()|.
- This is the text line number, not the screen line number. The
- value is zero when there was no mouse button click.
-
- *v:mouse_col* *mouse_col-variable*
-v:mouse_col Column number for a mouse click obtained with |getchar()|.
- This is the screen column number, like with |virtcol()|. The
- value is zero when there was no mouse button click.
-
- *v:msgpack_types* *msgpack_types-variable*
-v:msgpack_types Dictionary containing msgpack types used by |msgpackparse()|
- and |msgpackdump()|. All types inside dictionary are fixed
- (not editable) empty lists. To check whether some list is one
- of msgpack types, use |is| operator.
-
- *v:null* *null-variable*
-v:null Special value used to put "null" in JSON and NIL in msgpack.
- See |json_encode()|. This value is converted to "v:null" when
- used as a String (e.g. in |expr5| with string concatenation
- operator) and to zero when used as a Number (e.g. in |expr5|
- or |expr7| when used with numeric operators). Read-only.
- In some places `v:null` can be used for a List, Dict, etc.
- that is not set. That is slightly different than an empty
- List, Dict, etc.
-
- *v:numbermax* *numbermax-variable*
-v:numbermax Maximum value of a number.
-
- *v:numbermin* *numbermin-variable*
-v:numbermin Minimum value of a number (negative).
-
- *v:numbersize* *numbersize-variable*
-v:numbersize Number of bits in a Number. This is normally 64, but on some
- systems it may be 32.
-
- *v:oldfiles* *oldfiles-variable*
-v:oldfiles List of file names that is loaded from the |shada| file on
- startup. These are the files that Vim remembers marks for.
- The length of the List is limited by the ' argument of the
- 'shada' option (default is 100).
- When the |shada| file is not used the List is empty.
- Also see |:oldfiles| and |c_#<|.
- The List can be modified, but this has no effect on what is
- stored in the |shada| file later. If you use values other
- than String this will cause trouble.
-
- *v:option_new*
-v:option_new New value of the option. Valid while executing an |OptionSet|
- autocommand.
- *v:option_old*
-v:option_old Old value of the option. Valid while executing an |OptionSet|
- autocommand. Depending on the command used for setting and the
- kind of option this is either the local old value or the
- global old value.
- *v:option_oldlocal*
-v:option_oldlocal
- Old local value of the option. Valid while executing an
- |OptionSet| autocommand.
- *v:option_oldglobal*
-v:option_oldglobal
- Old global value of the option. Valid while executing an
- |OptionSet| autocommand.
- *v:option_type*
-v:option_type Scope of the set command. Valid while executing an
- |OptionSet| autocommand. Can be either "global" or "local"
- *v:option_command*
-v:option_command
- Command used to set the option. Valid while executing an
- |OptionSet| autocommand.
- value option was set via ~
- "setlocal" |:setlocal| or ":let l:xxx"
- "setglobal" |:setglobal| or ":let g:xxx"
- "set" |:set| or |:let|
- "modeline" |modeline|
- *v:operator* *operator-variable*
-v:operator The last operator given in Normal mode. This is a single
- character except for commands starting with <g> or <z>,
- in which case it is two characters. Best used alongside
- |v:prevcount| and |v:register|. Useful if you want to cancel
- Operator-pending mode and then use the operator, e.g.: >
- :omap O <Esc>:call MyMotion(v:operator)<CR>
-< The value remains set until another operator is entered, thus
- don't expect it to be empty.
- v:operator is not set for |:delete|, |:yank| or other Ex
- commands.
- Read-only.
-
- *v:prevcount* *prevcount-variable*
-v:prevcount The count given for the last but one Normal mode command.
- This is the v:count value of the previous command. Useful if
- you want to cancel Visual or Operator-pending mode and then
- use the count, e.g.: >
- :vmap % <Esc>:call MyFilter(v:prevcount)<CR>
-< Read-only.
-
- *v:profiling* *profiling-variable*
-v:profiling Normally zero. Set to one after using ":profile start".
- See |profiling|.
-
- *v:progname* *progname-variable*
-v:progname The name by which Nvim was invoked (with path removed).
- Read-only.
-
- *v:progpath* *progpath-variable*
-v:progpath Absolute path to the current running Nvim.
- Read-only.
-
- *v:register* *register-variable*
-v:register The name of the register in effect for the current normal mode
- command (regardless of whether that command actually used a
- register). Or for the currently executing normal mode mapping
- (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 '+'.
- Also see |getreg()| and |setreg()|
-
- *v:relnum* *relnum-variable*
-v:relnum Relative line number for the 'statuscolumn' expression.
- Read-only.
-
- *v:scrollstart* *scrollstart-variable*
-v:scrollstart String describing the script or function that caused the
- screen to scroll up. It's only set when it is empty, thus the
- first reason is remembered. It is set to "Unknown" for a
- typed command.
- This can be used to find out why your script causes the
- hit-enter prompt.
-
- *v:servername* *servername-variable*
-v:servername Primary listen-address of Nvim, the first item returned by
- |serverlist()|. Usually this is the named pipe created by Nvim
- at |startup| or given by |--listen| (or the deprecated
- |$NVIM_LISTEN_ADDRESS| env var).
-
- See also |serverstart()| |serverstop()|.
- Read-only.
-
- *$NVIM*
- $NVIM is set by |terminal| and |jobstart()|, and is thus
- a hint that the current environment is a subprocess of Nvim.
- Example: >
- if $NVIM
- echo nvim_get_chan_info(v:parent)
- endif
-
-< Note the contents of $NVIM may change in the future.
-
-v:searchforward *v:searchforward* *searchforward-variable*
- Search direction: 1 after a forward search, 0 after a
- backward search. It is reset to forward when directly setting
- the last search pattern, see |quote/|.
- Note that the value is restored when returning from a
- function. |function-search-undo|.
- Read-write.
-
- *v:shell_error* *shell_error-variable*
-v:shell_error Result of the last shell command. When non-zero, the last
- shell command had an error. When zero, there was no problem.
- This only works when the shell returns the error code to Vim.
- The value -1 is often used when the command could not be
- executed. Read-only.
- Example: >
- :!mv foo bar
- :if v:shell_error
- : echo 'could not rename "foo" to "bar"!'
- :endif
-<
- *v:statusmsg* *statusmsg-variable*
-v:statusmsg Last given status message.
- Modifiable (can be set).
-
- *v:stderr* *stderr-variable*
-v:stderr |channel-id| corresponding to stderr. The value is always 2;
- use this variable to make your code more descriptive.
- Unlike stdin and stdout (see |stdioopen()|), stderr is always
- open for writing. Example: >
- :call chansend(v:stderr, "error: toaster empty\n")
-<
- *v:swapname* *swapname-variable*
-v:swapname Name of the swapfile found.
- Only valid during |SwapExists| event.
- Read-only.
-
- *v:swapchoice* *swapchoice-variable*
-v:swapchoice |SwapExists| autocommands can set this to the selected choice
- for handling an existing swapfile:
- 'o' Open read-only
- 'e' Edit anyway
- 'r' Recover
- 'd' Delete swapfile
- 'q' Quit
- 'a' Abort
- The value should be a single-character string. An empty value
- results in the user being asked, as would happen when there is
- no SwapExists autocommand. The default is empty.
-
- *v:swapcommand* *swapcommand-variable*
-v:swapcommand Normal mode command to be executed after a file has been
- opened. Can be used for a |SwapExists| autocommand to have
- another Vim open the file and jump to the right place. For
- example, when jumping to a tag the value is ":tag tagname\r".
- For ":edit +cmd file" the value is ":cmd\r".
-
- *v:t_TYPE* *v:t_bool* *t_bool-variable*
-v:t_bool Value of |Boolean| type. Read-only. See: |type()|
- *v:t_dict* *t_dict-variable*
-v:t_dict Value of |Dictionary| type. Read-only. See: |type()|
- *v:t_float* *t_float-variable*
-v:t_float Value of |Float| type. Read-only. See: |type()|
- *v:t_func* *t_func-variable*
-v:t_func Value of |Funcref| type. Read-only. See: |type()|
- *v:t_list* *t_list-variable*
-v:t_list Value of |List| type. Read-only. See: |type()|
- *v:t_number* *t_number-variable*
-v:t_number Value of |Number| type. Read-only. See: |type()|
- *v:t_string* *t_string-variable*
-v:t_string Value of |String| type. Read-only. See: |type()|
- *v:t_blob* *t_blob-variable*
-v:t_blob Value of |Blob| type. Read-only. See: |type()|
-
- *v:termresponse* *termresponse-variable*
-v:termresponse The value of the most recent OSC or DCS escape sequence
- received by Nvim from the terminal. This can be read in a
- |TermResponse| event handler after querying the terminal using
- another escape sequence.
-
- *v:testing* *testing-variable*
-v:testing Must be set before using `test_garbagecollect_now()`.
-
- *v:this_session* *this_session-variable*
-v:this_session Full filename of the last loaded or saved session file.
- Empty when no session file has been saved. See |:mksession|.
- Modifiable (can be set).
-
- *v:throwpoint* *throwpoint-variable*
-v:throwpoint The point where the exception most recently caught and not
- finished was thrown. Not set when commands are typed. See
- also |v:exception| and |throw-variables|.
- Example: >
- :try
- : throw "oops"
- :catch /.*/
- : echo "Exception from" v:throwpoint
- :endtry
-< Output: "Exception from test.vim, line 2"
-
- *v:true* *true-variable*
-v:true Special value used to put "true" in JSON and msgpack. See
- |json_encode()|. This value is converted to "v:true" when used
- as a String (e.g. in |expr5| with string concatenation
- operator) and to one when used as a Number (e.g. in |expr5| or
- |expr7| when used with numeric operators). Read-only.
-
- *v:val* *val-variable*
-v:val Value of the current item of a |List| or |Dictionary|. Only
- valid while evaluating the expression used with |map()| and
- |filter()|. Read-only.
-
- *v:version* *version-variable*
-v:version Vim version number: major version times 100 plus minor
- version. Vim 5.0 is 500, Vim 5.1 is 501.
- Read-only.
- Use |has()| to check the Nvim (not Vim) version: >
- :if has("nvim-0.2.1")
-<
-
- *v:virtnum* *virtnum-variable*
-v:virtnum Virtual line number for the 'statuscolumn' expression.
- Negative when drawing the status column for virtual lines, zero
- when drawing an actual buffer line, and positive when drawing
- the wrapped part of a buffer line.
- Read-only.
-
- *v:vim_did_enter* *vim_did_enter-variable*
-v:vim_did_enter 0 during startup, 1 just before |VimEnter|.
- Read-only.
-
- *v:warningmsg* *warningmsg-variable*
-v:warningmsg Last given warning message.
- Modifiable (can be set).
- *v:windowid* *windowid-variable*
-v:windowid Application-specific window "handle" which may be set by any
- attached UI. Defaults to zero.
- Note: For Nvim |windows| use |winnr()| or |win_getid()|, see
- |window-ID|.
+The alphabetic list of all builtin variables and details are in a separate
+help file: |vvars|.
==============================================================================
4. Builtin Functions *vim-function* *functions*
@@ -2493,6 +1910,8 @@ This does NOT work: >
:let {var} ..= {expr1} Like ":let {var} = {var} .. {expr1}".
These fail if {var} was not set yet and when the type
of {var} and {expr1} don't fit the operator.
+ `+=` modifies a |List| or a |Blob| in-place instead of
+ creating a new one.
:let ${env-name} = {expr1} *:let-environment* *:let-$*
@@ -4365,7 +3784,7 @@ have Vim execute random executables or may have forbidden to do so for
specific filetypes by setting the "<filetype>_exec" variable (|plugin_exec|).
It returns |TRUE| or |FALSE| to indicate whether the plugin should run the given
-exectuable. It takes the following arguments:
+executable. It takes the following arguments:
argument type ~
diff --git a/runtime/doc/faq.txt b/runtime/doc/faq.txt
new file mode 100644
index 0000000000..09bf829512
--- /dev/null
+++ b/runtime/doc/faq.txt
@@ -0,0 +1,485 @@
+*faq.txt* Nvim
+
+ NVIM REFERENCE MANUAL
+
+
+Frequently asked Questions *faq*
+
+ Type |gO| to see the table of contents.
+
+==============================================================================
+General Questions *faq-general*
+
+
+WHERE SHOULD I PUT MY CONFIG (VIMRC)? ~
+
+See |config|; you can copy (or symlink) your existing vimrc. |nvim-from-vim|
+
+
+HOW STABLE IS THE DEVELOPMENT (PRE-RELEASE) VERSION? ~
+
+The unstable (pre-release)
+https://github.com/neovim/neovim/releases/tag/nightly version of Nvim
+("HEAD", i.e. the `master` branch) is used to aggressively stage new features
+and changes. It's usually stable, but will occasionally break your workflow.
+We depend on HEAD users to report "blind spots" that were not caught by
+automated tests.
+
+Use the stable (release) https://github.com/neovim/neovim/releases/latest
+version for a more predictable experience.
+
+
+CAN I USE RUBY-BASED VIM PLUGINS (E.G. LUSTYEXPLORER)? ~
+
+Yes, starting with Nvim 0.1.5 PR #4980
+https://github.com/neovim/neovim/pull/4980 the legacy Vim `if_ruby` interface
+is supported.
+
+
+CAN I USE LUA-BASED VIM PLUGINS (E.G. NEOCOMPLETE)? ~
+
+No. Starting with Nvim 0.2 PR #4411
+https://github.com/neovim/neovim/pull/4411 Lua is built-in, but the legacy
+Vim `if_lua` interface is not supported.
+
+
+HOW CAN I USE "TRUE COLOR" IN THE TERMINAL? ~
+
+Truecolor (24bit colors) are enabled by default if a supporting terminal is
+detected. If your terminal is not detected but you are sure it supports
+truecolor, add this to your |init.vim|:
+>vim
+ set termguicolors
+<
+
+NVIM SHOWS WEIRD SYMBOLS (`�[2 q`) WHEN CHANGING MODES ~
+
+This is a bug in your terminal emulator. It happens because Nvim sends
+cursor-shape termcodes by default, if the terminal appears to be
+xterm-compatible (`TERM=xterm-256color`).
+
+To workaround the issue, you can:
+
+- Use a different terminal emulator
+- Disable 'guicursor' in your Nvim config: >vim
+
+ :set guicursor=
+ " Workaround some broken plugins which set guicursor indiscriminately.
+ :autocmd OptionSet guicursor noautocmd set guicursor=
+<
+See also |$TERM| for recommended values of `$TERM`.
+
+
+HOW TO CHANGE CURSOR SHAPE IN THE TERMINAL? ~
+
+- For Nvim 0.1.7 or older: see the note about `NVIM_TUI_ENABLE_CURSOR_SHAPE` in `man nvim`.
+- For Nvim 0.2 or newer: cursor styling is controlled by the 'guicursor' option.
+ - To _disable_ cursor-styling, set 'guicursor' to empty: >vim
+
+ :set guicursor=
+ " Workaround some broken plugins which set guicursor indiscriminately.
+ :autocmd OptionSet guicursor noautocmd set guicursor=
+<
+ - If you want a non-blinking cursor, use `blinkon0`. See 'guicursor'.
+ - 'guicursor' is enabled by default, unless Nvim thinks your terminal doesn't
+ support it. If you're sure that your terminal supports cursor-shaping, set
+ 'guicursor' in your |init.vim|, as described in 'guicursor'.
+- The Vim terminal options |t_SI| and `t_EI` are ignored, like all other |t_xx| options.
+- Old versions of libvte (gnome-terminal, roxterm, terminator, ...) do not
+ support cursor style control codes. #2537
+ https://github.com/neovim/neovim/issues/2537
+
+
+HOW TO CHANGE CURSOR COLOR IN THE TERMINAL? ~
+
+Cursor styling (shape, color, behavior) is controlled by 'guicursor', even in
+the terminal. Cursor color (as opposed to shape) only works if
+'termguicolors' is set.
+
+'guicursor' gives an example, but here's a more complicated example
+which sets different colors in insert-mode and normal-mode:
+>vim
+ :set termguicolors
+ :hi Cursor guifg=green guibg=green
+ :hi Cursor2 guifg=red guibg=red
+ :set guicursor=n-v-c:block-Cursor/lCursor,i-ci-ve:ver25-Cursor2/lCursor2,r-cr:hor20,o:hor50
+<
+
+CURSOR STYLE ISN'T RESTORED AFTER EXITING OR SUSPENDING AND RESUMING NVIM ~
+
+Terminals do not provide a way to query the cursor style. Use autocommands to
+manage the cursor style:
+>vim
+ au VimEnter,VimResume * set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50
+ \,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor
+ \,sm:block-blinkwait175-blinkoff150-blinkon175
+
+ au VimLeave,VimSuspend * set guicursor=a:block-blinkon0
+<
+
+CURSOR SHAPE DOESN'T CHANGE IN TMUX ~
+
+tmux decides that, not Nvim. See |tui-cursor-shape| for a fix.
+
+See #3165 https://github.com/neovim/neovim/pull/3165 for discussion.
+
+
+CURSOR FLICKER IN TMUX? ~
+
+If cursor `_` appears and disappears very quickly when opening nvim without a
+document under tmux, and you set |ctermbg| in `EndOfBuffer` and `Normal`, try
+setting these to `NONE`:
+>vim
+ hi EndOfBuffer ctermbg=NONE ctermfg=200 cterm=NONE
+ hi Normal ctermbg=NONE ctermfg=200 cterm=NONE
+<
+
+WHAT HAPPENED TO --remote AND FRIENDS? ~
+
+|--remote| is partly supported. |clientserver|
+
+If you require flags from Vim that are missing in Nvim, you can use
+https://github.com/mhinz/neovim-remote instead.
+
+==============================================================================
+Runtime issues *faq-runtime*
+
+
+COPYING TO X11 PRIMARY SELECTION WITH THE MOUSE DOESN'T WORK ~
+
+`clipboard=autoselect` is not implemented yet
+https://github.com/neovim/neovim/issues/2325. You may find this workaround to
+be useful:
+>vim
+ vnoremap <LeftRelease> "*ygv
+ vnoremap <2-LeftRelease> "*ygv
+<
+
+MY CTRL-H MAPPING DOESN'T WORK ~
+
+This was fixed in Nvim 0.2. If you are running Nvim 0.1.7 or older,
+adjust your terminal's "kbs" (key_backspace) terminfo entry:
+>vim
+ infocmp $TERM | sed 's/kbs=^[hH]/kbs=\\177/' > $TERM.ti
+ tic $TERM.ti
+<
+(Feel free to delete the temporary `*.ti` file created after running the above
+commands).
+
+
+<HOME> OR SOME OTHER "SPECIAL" KEY DOESN'T WORK ~
+
+Make sure |$TERM| is set correctly.
+
+- For screen or tmux, `$TERM` should be `screen-256color` (not `xterm-256color`!)
+- In other cases if "256" does not appear in the string it's probably wrong.
+ Try `TERM=xterm-256color`.
+
+
+:! AND SYSTEM() DO WEIRD THINGS WITH INTERACTIVE PROCESSES ~
+
+Interactive commands are supported by |:terminal| in Nvim. But |:!| and
+|system()| do not support interactive commands, primarily because Nvim UIs use
+stdio for msgpack communication, but also for performance, reliability, and
+consistency across platforms (see
+https://vimhelp.org/gui_x11.txt.html#gui-pty).
+
+See also #1496 https://github.com/neovim/neovim/issues/1496 and #8217
+https://github.com/neovim/neovim/issues/8217#issuecomment-402152307.
+
+
+PYTHON SUPPORT ISN'T WORKING ~
+
+Run |:checkhealth| in Nvim for automatic diagnosis.
+
+Other hints:
+
+- The python `neovim` module was renamed to `pynvim` (long ago).
+- If you're using pyenv or virtualenv for the `pynvim` module
+ https://pypi.python.org/pypi/pynvim/, you must set `g:python3_host_prog` to
+ the virtualenv's interpreter path.
+- Read |provider-python|.
+- Be sure you have the latest version of the `pynvim` Python module: >bash
+
+ python -m pip install setuptools
+ python -m pip install --upgrade pynvim
+ python3 -m pip install --upgrade pynvim
+<
+- Try with `nvim -u NORC` to make sure your config (|init.vim|) isn't causing a
+ problem. If you get `E117: Unknown function`, that means there's a runtime
+ issue: |faq-runtime|.
+
+
+:CHECKHEALTH REPORTS E5009: INVALID $VIMRUNTIME ~
+
+This means `health#check()` couldn't load, which suggests that |$VIMRUNTIME|
+or 'runtimepath' is broken.
+
+- |$VIMRUNTIME| must point to Nvim's runtime files, not Vim's.
+- The |$VIMRUNTIME| directory contents should be readable by the current user.
+- Verify that `:echo &runtimepath` contains the $VIMRUNTIME path.
+- Check the output of: >vim
+
+ :call health#check()
+ :verbose func health#check
+<
+
+NEOVIM CAN'T FIND ITS RUNTIME ~
+
+This is the case if `:help nvim` shows `E149: Sorry, no help for nvim`.
+
+Make sure that |$VIM| and |$VIMRUNTIME| point to Nvim's (as opposed to
+Vim's) runtime by checking `:echo $VIM` and `:echo $VIMRUNTIME`. This should
+give something like `/usr/share/nvim` resp. `/usr/share/nvim/runtime`.
+
+Also make sure that you don't accidentally overwrite your runtimepath
+(`:set runtimepath?`), which includes the above |$VIMRUNTIME| by default (see
+'runtimepath').
+
+
+NEOVIM IS SLOW ~
+
+
+Use a fast terminal emulator:
+
+- kitty https://github.com/kovidgoyal/kitty
+- alacritty https://github.com/jwilm/alacritty
+
+
+Use an optimized build:
+
+`:checkhealth nvim` should report one of these "build types":
+>
+ Build type: RelWithDebInfo
+ Build type: MinSizeRel
+ Build type: Release
+<
+If it reports `Build type: Debug` and you're building Nvim from source, see
+https://github.com/neovim/neovim/blob/master/BUILD.md.
+
+
+COLORS AREN'T DISPLAYED CORRECTLY ~
+
+Ensure that |$TERM| is set correctly.
+
+From a shell, run `TERM=xterm-256color nvim`. If colors are displayed
+correctly, then export that value of `TERM` in your user profile (usually
+`~/.profile`):
+>bash
+ export TERM=xterm-256color
+<
+If you're using `tmux`, instead add this to your `tmux.conf`:
+>bash
+ set -g default-terminal "tmux-256color"
+<
+
+For GNU `screen`, configure your `.screenrc`
+<https://wiki.archlinux.org/index.php/GNU_Screen#Use_256_colors>:
+>
+ term screen-256color
+<
+
+NOTE: Nvim ignores `t_Co` and other |t_xx| terminal codes.
+
+
+NEOVIM CAN'T READ UTF-8 CHARACTERS ~
+
+Run the following from the command line:
+>bash
+ locale | grep -E '(LANG|LC_CTYPE|LC_ALL)=(.*\.)?(UTF|utf)-?8'
+<
+If there's no results, then you might not be using a UTF-8 locale. See the
+following issues:
+#1601 https://github.com/neovim/neovim/issues/1601
+#1858 https://github.com/neovim/neovim/issues/1858
+#2386 https://github.com/neovim/neovim/issues/2386
+
+
+ESC IN TMUX OR GNU SCREEN IS DELAYED ~
+
+This is a common problem
+https://www.google.com/?q=tmux%20vim%20escape%20delay in `tmux` / `screen`
+(see also tmux/#131
+https://github.com/tmux/tmux/issues/131#issuecomment-145853211). The
+corresponding timeout needs to be tweaked to a low value (10-20ms).
+
+`.tmux.conf`:
+>
+ set -g escape-time 10
+ # Or for tmux >= 2.6
+ set -sg escape-time 10
+<
+`.screenrc`:
+>
+ maptimeout 10
+<
+
+"WHY DOESN'T THIS HAPPEN IN VIM?"
+
+It does happen (try `vim -N -u NONE`), but if you hit a key quickly after
+ESC_ then Vim interprets the ESC as ESC instead of ALT (META). You won't
+notice the delay unless you closely observe the cursor. The tradeoff is that
+Vim won't understand ALT (META) key-chords, so for example `nnoremap <M-a>`
+won't work. ALT (META) key-chords always work in Nvim. See also `:help
+xterm-cursor-keys` in Vim.
+
+Nvim 0.3 mimics the Vim behavior while still fully supporting ALT mappings. See
+|i_ALT|.
+
+
+ESC IN GNU SCREEN IS LOST WHEN MOUSE MODE IS ENABLED ~
+
+This happens because of a bug in screen https://savannah.gnu.org/bugs/?60196:
+in mouse mode, screen assumes that `ESC` is part of a mouse sequence and will
+wait an unlimited time for the rest of the sequence, regardless of
+`maptimeout`. Until it's fixed in screen, there's no known workaround for
+this other than double-pressing escape, which causes a single escape to be
+passed through to Nvim.
+
+
+CALLING INPUTLIST(), ECHOMSG, ... IN FILETYPE PLUGINS AND AUTOCMD DOES NOT WORK ~
+
+#10008 https://github.com/neovim/neovim/issues/10008,
+#10116 https://github.com/neovim/neovim/issues/10116,
+#12288 https://github.com/neovim/neovim/issues/12288,
+# vim/vim#4379 https://github.com/vim/vim/issues/4379.
+This is because Nvim sets `shortmess+=F` by default. Vim behaves the same way
+with `set shortmes+=F`. There are plans to improve this, but meanwhile as a
+workaround, use `set shortmess-=F` or use `unsilent` as follows.
+>vim
+ unsilent let var = inputlist(['1. item1', '2. item2'])
+ autocmd BufNewFile * unsilent echomsg 'The autocmd has been fired.'
+<
+
+G:CLIPBOARD SETTINGS ARE NOT USED. ~
+
+If the clipboard provider is already loaded, you will need to reload it after
+configuration. Use the following configuration.
+>vim
+ let g:clipboard = { 'name' : ... }
+ if exists('g:loaded_clipboard_provider')
+ unlet g:loaded_clipboard_provider
+ runtime autoload/provider/clipboard.vim
+ endif
+<
+
+Or, if you want automatic reloading when assigning to |g:clipboard|, set
+|init.vim| as follows.
+>vim
+ function! s:clipboard_changed(...) abort
+ if exists('g:loaded_clipboard_provider')
+ unlet g:loaded_clipboard_provider
+ endif
+ runtime autoload/provider/clipboard.vim
+ endfunction
+
+ if !exists('s:loaded")
+ call dictwatcheradd(g:, 'clipboard', function('s:clipboard_changed'))
+ endif
+ let s:loaded = v:true
+<
+
+==============================================================================
+Build issues *faq-build*
+
+
+GENERAL BUILD ISSUES ~
+
+Run `make distclean && make` to rule out a stale build environment causing the
+failure.
+
+
+SETTINGS IN LOCAL.MK DON'T TAKE EFFECT ~
+
+CMake caches build settings, so you might need to run `rm -r build && make`
+after modifying `local.mk`.
+
+
+CMAKE ERRORS ~
+
+`configure_file Problem configuring file`
+
+This is probably a permissions issue, which can happen if you run `make` as the
+root user, then later run an unprivileged `make`. To fix this, run `rm -rf
+build` and try again.
+
+
+GENERATING HELPTAGS FAILED ~
+
+If re-installation fails with "Generating helptags failed", try removing the
+previously installed runtime directory (if `CMAKE_INSTALL_PREFIX` is not set
+during building, the default is `/usr/local/share/nvim`):
+>bash
+ rm -r /usr/local/share/nvim
+<
+
+==============================================================================
+Design *faq-design*
+
+
+WHY NOT USE JSON FOR RPC? ~
+
+- JSON cannot easily/efficiently handle binary data
+- JSON specification is ambiguous: https://seriot.ch/parsing_json.php
+
+
+WHY EMBED LUA INSTEAD OF X? ~
+
+- Lua is a very small language, ideal for embedding. The biggest advantage of
+ Python/Ruby/etc is their huge collection of libraries, but that isn't
+ relevant for Nvim, where Nvim is the "batteries included" library:
+ introducing another stdlib would be redundant.
+- Lua 5.1 is a complete language: the syntax is frozen. This is great for
+ backwards compatibility.
+- Nvim also uses Lua internally as an alternative to C. Extra performance is
+ useful there, as opposed to a slow language like Python or Vim9script.
+- LuaJIT is one of the fastest runtimes on the planet, 10x faster than Python
+ and "Vim9script" https://vimhelp.org/vim9.txt.html, 100x faster than
+ Vimscript.
+- Python/JS cost more than Lua in terms of size and portability, and there are
+ already numerous Python/JS-based editors. So Python/JS would make Nvim
+ bigger and less portable, in exchange for a non-differentiating feature.
+
+See also:
+
+- Why Lua https://web.archive.org/web/20150219224654/https://blog.datamules.com/blog/2012/01/30/why-lua/
+- The Design of Lua https://cacm.acm.org/magazines/2018/11/232214-a-look-at-the-design-of-lua/fulltext
+- Scripting architecture considerations http://oldblog.antirez.com/post/redis-and-scripting.html
+- LuaJIT performance https://julialang.org/benchmarks/
+- Discussion of JavaScript vs Lua https://github.com/vim/vim/pull/5198#issuecomment-554693754
+- Discussion Python embedding https://lobste.rs/s/pnuak4/mercurial_s_journey_reflections_on#c_zshdwy
+
+
+WHY LUA 5.1 INSTEAD OF LUA 5.3+? ~
+
+Lua 5.1 is a different language than 5.3. The Lua org makes breaking changes
+with every new version, so even if we switched (not upgraded, but switched) to
+5.3 we gain nothing when they create the next new language in 5.4, 5.5, etc.
+And we would lose LuaJIT, which is far more valuable than Lua 5.3+.
+
+Lua 5.1 is a complete language. To "upgrade" it, add libraries, not syntax.
+Nvim itself already is a pretty good "stdlib" for Lua, and we will continue to
+grow and enhance it. Changing the rules of Lua gains nothing in this context.
+
+
+WILL NEOVIM TRANSLATE VIMSCRIPT TO LUA, INSTEAD OF EXECUTING VIMSCRIPT DIRECTLY? ~
+
+- We are experimenting with vim9jit https://github.com/tjdevries/vim9jit to
+ transpile Vim9script (Vim9's Vimscript variant) to Lua and have used this to
+ port Vim9 plugins https://github.com/neovim/neovim/pull/21662 to Nvim Lua.
+- We have no plans for transpiling legacy Vimscript.
+
+
+ARE PLUGIN AUTHORS ENCOURAGED TO PORT THEIR PLUGINS FROM VIMSCRIPT TO LUA? DO YOU PLAN ON SUPPORTING VIMSCRIPT INDEFINITELY? (#1152) ~
+
+We don't anticipate any reason to deprecate Vimscript, which is a valuable DSL
+https://en.wikipedia.org/wiki/Domain-specific_language for text-editing tasks.
+Maintaining Vimscript compatibility is less costly than a mass migration of
+existing Vim plugins.
+
+Porting from Vimscript to Lua just for the heck of it gains nothing. Nvim is
+emphatically a fork of Vim in order to leverage the work already spent on
+thousands of Vim plugins, while enabling new types of plugins and
+integrations.
+
+vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/filetype.txt b/runtime/doc/filetype.txt
index ed21dc1c37..071a45c9c3 100644
--- a/runtime/doc/filetype.txt
+++ b/runtime/doc/filetype.txt
@@ -146,6 +146,7 @@ variables can be used to overrule the filetype used for certain extensions:
`*.cls` g:filetype_cls
`*.csh` g:filetype_csh |ft-csh-syntax|
`*.dat` g:filetype_dat
+ `*.def` g:filetype_def
`*.f` g:filetype_f |ft-forth-syntax|
`*.frm` g:filetype_frm |ft-form-syntax|
`*.fs` g:filetype_fs |ft-forth-syntax|
@@ -167,6 +168,7 @@ variables can be used to overrule the filetype used for certain extensions:
`*.sh` g:bash_is_sh |ft-sh-syntax|
`*.tex` g:tex_flavor |ft-tex-plugin|
`*.typ` g:filetype_typ
+ `*.v` g:filetype_v
`*.w` g:filetype_w |ft-cweb-syntax|
For a few filetypes the global variable is used only when the filetype could
@@ -457,7 +459,7 @@ g:changelog_new_date_format
%% insert a single '%' character
%d insert the date from above
%u insert the user from above
- %p insert result of b:changelog_entry_prefix
+ %p insert result of b:changelog_entry_prefix
%c where to position cursor when done
The default is "%d %u\n\n\t* %p%c\n\n", which produces
something like (| is where cursor will be, unless at
@@ -471,7 +473,7 @@ g:changelog_new_entry_format
The format used when creating a new entry.
The following table describes special tokens in the
string:
- %p insert result of b:changelog_entry_prefix
+ %p insert result of b:changelog_entry_prefix
%c where to position cursor when done
The default is "\t*%c", which produces something
similar to >
@@ -525,13 +527,26 @@ under it. If not found, a new entry and item is prepended to the beginning of
the Changelog.
+ASCIIDOC *ft-asciidoc-plugin*
+
+To enable |folding| use this: >
+ let g:asciidoc_folding = 1
+
+To disable nesting of folded headers use this: >
+ let g:asciidoc_foldnested = 0
+
+To disable folding everything under the title use this: >
+ let asciidoc_fold_under_title = 0
+
+
FORTRAN *ft-fortran-plugin*
Options:
'expandtab' is switched on to avoid tabs as required by the Fortran
standards unless the user has set fortran_have_tabs in vimrc.
-'textwidth' is set to 72 for fixed source format as required by the
- Fortran standards and to 80 for free source format.
+'textwidth' is set to 80 for fixed source format whereas it is set to 132
+ for free source format. Setting the fortran_extended_line_length
+ variable increases the width to 132 for fixed source format.
'formatoptions' is set to break code and comment lines and to preserve long
lines. You can format comments with |gq|.
For further discussion of fortran_have_tabs and the method used for the
@@ -684,7 +699,7 @@ To disable this behavior, set the following variable in your vimrc: >
QUERY *ft-query-plugin*
-Linting of tree-sitter queries for installed parsers using
+Linting of treesitter queries for installed parsers using
|vim.treesitter.query.lint()| is enabled by default on `BufEnter` and
`BufWrite`. To change the events that trigger linting, use >lua
@@ -734,6 +749,14 @@ To enable this behavior, set the following variable in your vimrc: >
let g:rst_style = 1
+RNOWEB *ft-rnoweb-plugin*
+
+The 'formatexpr' option is set dynamically with different values for R code
+and for LaTeX code. If you prefer that 'formatexpr' is not set, add to your
+|vimrc|: >
+ let rnw_dynamic_comments = 0
+
+
RPM SPEC *ft-spec-plugin*
Since the text for this plugin is rather long it has been put in a separate
diff --git a/runtime/doc/ft_ada.txt b/runtime/doc/ft_ada.txt
index 3b7d6a73dd..a9302cde97 100644
--- a/runtime/doc/ft_ada.txt
+++ b/runtime/doc/ft_ada.txt
@@ -172,7 +172,7 @@ GNAT OBJECT ~
*g:gnat.Make()*
g:gnat.Make()
Calls |g:gnat.Make_Command| and displays the result inside a
- |quickfix| window.
+ |quickfix| window.
*g:gnat.Pretty()*
g:gnat.Pretty()
diff --git a/runtime/doc/ft_sql.txt b/runtime/doc/ft_sql.txt
index 68e26d2a5b..241fa4bd74 100644
--- a/runtime/doc/ft_sql.txt
+++ b/runtime/doc/ft_sql.txt
@@ -375,7 +375,7 @@ This command breaks down as: >
'sqlKeyword' - Display the items for the sqlKeyword highlight
group
'sqlKeyword\w*' - A second option available with Vim 7.4 which
- uses a regular expression to determine which
+ uses a regular expression to determine which
syntax groups to use
)<CR> - Execute the :let command
<C-X><C-O> - Trigger the standard omni completion key stroke.
diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt
index b8526b55e9..7545d2c621 100644
--- a/runtime/doc/help.txt
+++ b/runtime/doc/help.txt
@@ -47,6 +47,7 @@ ABOUT NVIM *reference_toc* *doc-file-list* *Q_ct*
|news| News since the previous release
|nvim| Transitioning from Vim
|vim-differences| Nvim compared to Vim
+|faq| Frequently Asked Questions
|user-manual| User manual: How to accomplish editing tasks.
|quickref| Overview of common commands
|tutor| 30-minute interactive course for beginners
@@ -167,7 +168,9 @@ DEVELOPING NVIM
|dev| Development of Nvim
|dev-style| Development style guidelines
-|debug.txt| Debugging Vim itself
+|dev-theme| Design guidelines (colorschemes etc.)
+|dev-tools| Tools and techniques for developing Nvim
+|dev-vimpatch| Merging patches from Vim
Standard plugins ~
*standard-plugin-list*
diff --git a/runtime/doc/indent.txt b/runtime/doc/indent.txt
index 853facdaa0..c20143bc6e 100644
--- a/runtime/doc/indent.txt
+++ b/runtime/doc/indent.txt
@@ -708,29 +708,29 @@ clojure-mode.el:
FORTRAN *ft-fortran-indent*
-Block if, select case, where, and forall constructs are indented. So are
-type, interface, associate, block, and enum constructs. The indenting of
-subroutines, functions, modules, and program blocks is optional. Comments,
-labelled statements and continuation lines are indented if the Fortran is in
-free source form, whereas they are not indented if the Fortran is in fixed
-source form because of the left margin requirements. Hence manual indent
-corrections will be necessary for labelled statements and continuation lines
-when fixed source form is being used. For further discussion of the method
-used for the detection of source format see |ft-fortran-syntax|.
+Block if, select case, select type, select rank, where, forall, type,
+interface, associate, block, enum, critical, and change team constructs are
+indented. The indenting of subroutines, functions, modules, and program blocks
+is optional. Comments, labeled statements, and continuation lines are indented
+if the Fortran is in free source form, whereas they are not indented if the
+Fortran is in fixed source form because of the left margin requirements. Hence
+manual indent corrections will be necessary for labeled statements and
+continuation lines when fixed source form is being used. For further
+discussion of the method used for the detection of source format see
+|ft-fortran-syntax|.
Do loops ~
All do loops are left unindented by default. Do loops can be unstructured in
-Fortran with (possibly multiple) loops ending on a labelled executable
+Fortran with (possibly multiple) loops ending on a labeled executable
statement of almost arbitrary type. Correct indentation requires
-compiler-quality parsing. Old code with do loops ending on labelled statements
-of arbitrary type can be indented with elaborate programs such as Tidy
-(https://www.unb.ca/chem/ajit/f_tidy.htm). Structured do/continue loops are
-also left unindented because continue statements are also used for purposes
-other than ending a do loop. Programs such as Tidy can convert structured
-do/continue loops to the do/enddo form. Do loops of the do/enddo variety can
-be indented. If you use only structured loops of the do/enddo form, you should
-declare this by setting the fortran_do_enddo variable in your vimrc as
-follows >
+compiler-quality parsing. Old code with do loops ending on labeled statements
+of arbitrary type can be indented with elaborate programs such as Tidy.
+Structured do/continue loops are also left unindented because continue
+statements are used for purposes other than ending a do loop. Programs such
+as Tidy can convert structured do/continue loops to the do/enddo form. Do
+loops of the do/enddo variety can be indented. If you use only structured
+loops of the do/enddo form, you should declare this by setting the
+fortran_do_enddo variable in your vimrc as follows >
let fortran_do_enddo=1
@@ -744,15 +744,14 @@ to get do loops indented in .f90 files and left alone in Fortran files with
other extensions such as .for.
Program units ~
-The indenting of program units (subroutines, functions, modules, and program
-blocks) is enabled by default but can be suppressed if a lighter, screen-width
-preserving indent style is desired. To suppress the indenting of program
-units for all fortran files set the global fortran_indent_less variable in
-your vimrc as follows >
+Indenting of program units (subroutines, functions, modules, and program
+blocks) can be increased by setting the variable fortran_indent_more and can
+be decreased by setting the variable fortran_indent_less. These variables
+can be set for all fortran files in your vimrc as follows >
let fortran_indent_less=1
-A finer level of suppression can be achieved by setting the corresponding
+A finer level of control can be achieved by setting the corresponding
buffer-local variable as follows >
let b:fortran_indent_less=1
@@ -1033,8 +1032,8 @@ r_indent_comment_column, as in the example below:
let r_indent_comment_column = 30
<
Any code after a line that ends with "<-" is indented. Emacs/ESS does not
-indent the code if it is a top level function. If you prefer that the
-Vim-R-plugin behaves like Emacs/ESS in this regard, put in your |vimrc|:
+indent the code if it is a top-level function. If you prefer a behavior like
+Emacs/ESS one in this regard, put in your |vimrc|:
>
let r_indent_ess_compatible = 1
<
@@ -1227,5 +1226,11 @@ indent for a continuation line, a line that starts with a backslash: >
Three times shiftwidth is the default value.
+YAML *ft-yaml-indent*
+
+By default, the yaml indent script does not try to detect multiline scalars.
+If you want to enable this, set the following variable: >
+
+ let g:yaml_indent_multiline_scalar = 1
vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt
index 75b12fece2..c1a8aec40e 100644
--- a/runtime/doc/index.txt
+++ b/runtime/doc/index.txt
@@ -1146,6 +1146,8 @@ tag command action ~
|:>| :> shift lines one 'shiftwidth' right
|:@| :@ execute contents of a register
|:@@| :@@ repeat the previous ":@"
+|:2match| :2mat[ch] define a second match to highlight
+|:3match| :3mat[ch] define a third match to highlight
|:Next| :N[ext] go to previous file in the argument list
|:append| :a[ppend] append text
|:abbreviate| :ab[breviate] enter abbreviation
diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt
index ce2ec36ca3..34affb22e9 100644
--- a/runtime/doc/insert.txt
+++ b/runtime/doc/insert.txt
@@ -160,22 +160,22 @@ CTRL-R CTRL-O {register} *i_CTRL-R_CTRL-O*
auto-indent. Does the same as pasting with the mouse
|<MiddleMouse>|. When the register is linewise this will
insert the text above the current line, like with `P`.
- Does not replace characters!
The '.' register (last inserted text) is still inserted as
typed.
After this command, the '.' register contains the command
typed and not the text. I.e., the literals "^R^O" and not the
text from the register.
+ Does not replace characters in |Replace-mode|!
CTRL-R CTRL-P {register} *i_CTRL-R_CTRL-P*
Insert the contents of a register literally and fix the
indent, like |[<MiddleMouse>|.
- Does not replace characters!
The '.' register (last inserted text) is still inserted as
typed.
After this command, the '.' register contains the command
typed and not the text. I.e., the literals "^R^P" and not the
text from the register.
+ Does not replace characters in |Replace-mode|!
*i_CTRL-T*
CTRL-T Insert one shiftwidth of indent at the start of the current
diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt
index 85115fc22b..c9211291d0 100644
--- a/runtime/doc/intro.txt
+++ b/runtime/doc/intro.txt
@@ -49,10 +49,9 @@ For more information try one of these:
==============================================================================
Nvim on the interwebs *internet*
- *www* *faq* *distribution* *download*
+ *www* *distribution* *download*
Nvim home page: https://neovim.io/
- Nvim FAQ: https://github.com/neovim/neovim/wiki/FAQ
Downloads: https://github.com/neovim/neovim/releases
Vim FAQ: https://vimhelp.org/vim_faq.txt.html
diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt
index 5e97628f42..eb37cb2a6f 100644
--- a/runtime/doc/lsp.txt
+++ b/runtime/doc/lsp.txt
@@ -218,7 +218,7 @@ Each response handler has this signature: >
- {ctx} (table) Table of calling state associated with the
handler, with these keys:
- {method} (string) |lsp-method| name.
- - {client_id} (number) |vim.lsp.client| identifier.
+ - {client_id} (number) |vim.lsp.Client| identifier.
- {bufnr} (Buffer) Buffer handle.
- {params} (table|nil) Request parameters table.
- {version} (number) Document version at time of
@@ -366,31 +366,6 @@ https://microsoft.github.io/language-server-protocol/specifications/specificatio
LSP notification shape:
https://microsoft.github.io/language-server-protocol/specifications/specification-current/#notificationMessage
- *lsp-on-list-handler*
-
-`on_list` receives a table with:
-
- - `items` table[], structured like |setqflist-what|
- - `title` string, title for the list.
- - `context` table|nil. `ctx` from |lsp-handler|
-
-This table can be used with vim.fn.setqflist or vim.fn.setloclist. E.g.:
->lua
- local function on_list(options)
- vim.fn.setqflist({}, ' ', options)
- vim.api.nvim_command('cfirst')
- end
-
- vim.lsp.buf.definition{on_list=on_list}
- vim.lsp.buf.references(nil, {on_list=on_list})
-<
-If you prefer loclist do something like this:
->lua
- local function on_list(options)
- vim.fn.setloclist(0, {}, ' ', options)
- vim.api.nvim_command('lopen')
- end
-<
================================================================================
LSP HIGHLIGHT *lsp-highlight*
@@ -480,23 +455,23 @@ Use |LspTokenUpdate| and |vim.lsp.semantic_tokens.highlight_token()| for more
complex highlighting.
The following groups are linked by default to standard |group-name|s:
->
- @lsp.type.class Structure
- @lsp.type.decorator Function
- @lsp.type.enum Structure
- @lsp.type.enumMember Constant
- @lsp.type.function Function
- @lsp.type.interface Structure
- @lsp.type.macro Macro
- @lsp.type.method Function
- @lsp.type.namespace Structure
- @lsp.type.parameter Identifier
- @lsp.type.property Identifier
- @lsp.type.struct Structure
- @lsp.type.type Type
- @lsp.type.typeParameter TypeDef
- @lsp.type.variable Identifier
-<
+
+@lsp.type.class Structure
+@lsp.type.decorator Function
+@lsp.type.enum Structure
+@lsp.type.enumMember Constant
+@lsp.type.function Function
+@lsp.type.interface Structure
+@lsp.type.macro Macro
+@lsp.type.method Function
+@lsp.type.namespace Structure
+@lsp.type.parameter Identifier
+@lsp.type.property Identifier
+@lsp.type.struct Structure
+@lsp.type.type Type
+@lsp.type.typeParameter TypeDef
+@lsp.type.variable Identifier
+
==============================================================================
EVENTS *lsp-events*
@@ -557,7 +532,7 @@ LspNotify *LspNotify*
LspProgress *LspProgress*
Upon receipt of a progress notification from the server. Notifications can
- be polled from a `progress` ring buffer of a |vim.lsp.client| or use
+ be polled from a `progress` ring buffer of a |vim.lsp.Client| or use
|vim.lsp.status()| to get an aggregate message
If the server sends a "work done progress", the `pattern` is set to `kind`
@@ -583,7 +558,7 @@ LspRequest *LspRequest*
will trigger with {type} == `cancel`.
When used from Lua, the client ID, request ID, and request are sent in
- the "data" table. See {requests} in |vim.lsp.client| for details on the
+ the "data" table. See {requests} in |vim.lsp.Client| for details on the
{request} value. If the request type is `complete`, the request will be
deleted from the client's pending requests table immediately after
calling the event's callbacks. Example: >lua
@@ -642,12 +617,12 @@ buf_attach_client({bufnr}, {client_id}) *vim.lsp.buf_attach_client()*
Without calling this, the server won't be notified of changes to a buffer.
Parameters: ~
- • {bufnr} (integer) Buffer handle, or 0 for current
- • {client_id} (integer) Client id
+ • {bufnr} (`integer`) Buffer handle, or 0 for current
+ • {client_id} (`integer`) Client id
Return: ~
- (boolean) success `true` if client was attached successfully; `false`
- otherwise
+ (`boolean`) success `true` if client was attached successfully;
+ `false` otherwise
buf_detach_client({bufnr}, {client_id}) *vim.lsp.buf_detach_client()*
Detaches client from the specified buffer. Note: While the server is
@@ -655,26 +630,26 @@ buf_detach_client({bufnr}, {client_id}) *vim.lsp.buf_detach_client()*
send notifications should it ignore this notification.
Parameters: ~
- • {bufnr} (integer) Buffer handle, or 0 for current
- • {client_id} (integer) Client id
+ • {bufnr} (`integer`) Buffer handle, or 0 for current
+ • {client_id} (`integer`) Client id
buf_is_attached({bufnr}, {client_id}) *vim.lsp.buf_is_attached()*
Checks if a buffer is attached for a particular client.
Parameters: ~
- • {bufnr} (integer) Buffer handle, or 0 for current
- • {client_id} (integer) the client id
+ • {bufnr} (`integer`) Buffer handle, or 0 for current
+ • {client_id} (`integer`) the client id
buf_notify({bufnr}, {method}, {params}) *vim.lsp.buf_notify()*
Send a notification to a server
Parameters: ~
- • {bufnr} (integer|nil) The number of the buffer
- • {method} (string) Name of the request method
- • {params} (any) Arguments to send to the server
+ • {bufnr} (`integer?`) The number of the buffer
+ • {method} (`string`) Name of the request method
+ • {params} (`any`) Arguments to send to the server
Return: ~
- (boolean) success true if any client returns true; false otherwise
+ (`boolean`) success true if any client returns true; false otherwise
*vim.lsp.buf_request_all()*
buf_request_all({bufnr}, {method}, {params}, {handler})
@@ -682,14 +657,15 @@ buf_request_all({bufnr}, {method}, {params}, {handler})
executes the `handler` callback with the combined result.
Parameters: ~
- • {bufnr} (integer) Buffer handle, or 0 for current.
- • {method} (string) LSP method name
- • {params} (table|nil) Parameters to send to the server
- • {handler} (function) Handler called after all requests are completed.
- Server results are passed as a `client_id:result` map.
+ • {bufnr} (`integer`) Buffer handle, or 0 for current.
+ • {method} (`string`) LSP method name
+ • {params} (`table?`) Parameters to send to the server
+ • {handler} (`function`) Handler called after all requests are
+ completed. Server results are passed as a
+ `client_id:result` map.
Return: ~
- (function) cancel Function that cancels all requests.
+ (`function`) cancel Function that cancels all requests.
*vim.lsp.buf_request_sync()*
buf_request_sync({bufnr}, {method}, {params}, {timeout_ms})
@@ -697,89 +673,29 @@ buf_request_sync({bufnr}, {method}, {params}, {timeout_ms})
Calls |vim.lsp.buf_request_all()| but blocks Nvim while awaiting the
result. Parameters are the same as |vim.lsp.buf_request_all()| but the
- result is different. Waits a maximum of {timeout_ms} (default 1000) ms.
+ result is different. Waits a maximum of {timeout_ms}.
Parameters: ~
- • {bufnr} (integer) Buffer handle, or 0 for current.
- • {method} (string) LSP method name
- • {params} (table|nil) Parameters to send to the server
- • {timeout_ms} (integer|nil) Maximum time in milliseconds to wait for a
- result. Defaults to 1000
+ • {bufnr} (`integer`) Buffer handle, or 0 for current.
+ • {method} (`string`) LSP method name
+ • {params} (`table?`) Parameters to send to the server
+ • {timeout_ms} (`integer?`, default: `1000`) Maximum time in
+ milliseconds to wait for a result.
Return (multiple): ~
- (table) result Map of client_id:request_result.
- (string|nil) err On timeout, cancel, or error, `err` is a string
+ (`table<integer, {err: lsp.ResponseError, result: any}>?`) result Map
+ of client_id:request_result.
+ (`string?`) err On timeout, cancel, or error, `err` is a string
describing the failure reason, and `result` is nil.
-client() *vim.lsp.client*
- LSP client object. You can get an active client object via
- |vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|.
-
- • Methods:
- • request(method, params, [handler], bufnr) Sends a request to the
- server. This is a thin wrapper around {client.rpc.request} with some
- additional checking. If {handler} is not specified, If one is not
- found there, then an error will occur. Returns: {status},
- {[client_id]}. {status} is a boolean indicating if the notification
- was successful. If it is `false`, then it will always be `false` (the
- client has shutdown). If {status} is `true`, the function returns
- {request_id} as the second result. You can use this with
- `client.cancel_request(request_id)` to cancel the request.
- • request_sync(method, params, timeout_ms, bufnr) Sends a request to the
- server and synchronously waits for the response. This is a wrapper
- around {client.request} Returns: { err=err, result=result }, a
- dictionary, where `err` and `result` come from the |lsp-handler|. On
- timeout, cancel or error, returns `(nil, err)` where `err` is a string
- describing the failure reason. If the request was unsuccessful returns
- `nil`.
- • notify(method, params) Sends a notification to an LSP server. Returns:
- a boolean to indicate if the notification was successful. If it is
- false, then it will always be false (the client has shutdown).
- • cancel_request(id) Cancels a request with a given request id. Returns:
- same as `notify()`.
- • stop([force]) Stops a client, optionally with force. By default, it
- will just ask the server to shutdown without force. If you request to
- stop a client which has previously been requested to shutdown, it will
- automatically escalate and force shutdown.
- • is_stopped() Checks whether a client is stopped. Returns: true if the
- client is fully stopped.
- • on_attach(client, bufnr) Runs the on_attach function from the client's
- config if it was defined. Useful for buffer-local setup.
-
- • Members
- • {id} (number): The id allocated to the client.
- • {name} (string): If a name is specified on creation, that will be
- used. Otherwise it is just the client id. This is used for logs and
- messages.
- • {rpc} (table): RPC client object, for low level interaction with the
- client. See |vim.lsp.rpc.start()|.
- • {offset_encoding} (string): The encoding used for communicating with
- the server. You can modify this in the `config`'s `on_init` method
- before text is sent to the server.
- • {handlers} (table): The handlers used by the client as described in
- |lsp-handler|.
- • {requests} (table): The current pending requests in flight to the
- server. Entries are key-value pairs with the key being the request ID
- while the value is a table with `type`, `bufnr`, and `method`
- key-value pairs. `type` is either "pending" for an active request, or
- "cancel" for a cancel request. It will be "complete" ephemerally while
- executing |LspRequest| autocmds when replies are received from the
- server.
- • {config} (table): copy of the table that was passed by the user to
- |vim.lsp.start_client()|.
- • {server_capabilities} (table): Response from the server sent on
- `initialize` describing the server's capabilities.
- • {progress} A ring buffer (|vim.ringbuf()|) containing progress
- messages sent by the server.
-
client_is_stopped({client_id}) *vim.lsp.client_is_stopped()*
Checks whether a client is stopped.
Parameters: ~
- • {client_id} (integer)
+ • {client_id} (`integer`)
Return: ~
- (boolean) stopped true if client is stopped, false otherwise.
+ (`boolean`) stopped true if client is stopped, false otherwise.
commands *vim.lsp.commands*
Registry for client side commands. This is an extension point for plugins
@@ -803,68 +719,67 @@ formatexpr({opts}) *vim.lsp.formatexpr()*
Provides an interface between the built-in client and a `formatexpr`
function.
- 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.bo[bufnr].formatexpr =
- 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`.
+ 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.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`.
Parameters: ~
- • {opts} (table) options for customizing the formatting expression
- which takes the following optional keys:
- • timeout_ms (default 500ms). The timeout period for the
- formatting request.
+ • {opts} (`table?`) A table with the following fields:
+ • {timeout_ms} (`integer`, default: 500ms) The timeout period
+ for the formatting request..
*vim.lsp.get_buffers_by_client_id()*
get_buffers_by_client_id({client_id})
Returns list of buffers attached to client_id.
Parameters: ~
- • {client_id} (integer) client id
+ • {client_id} (`integer`) client id
Return: ~
- integer[] buffers list of buffer ids
+ (`integer[]`) buffers list of buffer ids
get_client_by_id({client_id}) *vim.lsp.get_client_by_id()*
Gets a client by id, or nil if the id is invalid. The returned client may
not yet be fully initialized.
Parameters: ~
- • {client_id} (integer) client id
+ • {client_id} (`integer`) client id
Return: ~
- (nil|lsp.Client) client rpc object
+ (`vim.lsp.Client?`) client rpc object
get_clients({filter}) *vim.lsp.get_clients()*
Get active clients.
Parameters: ~
- • {filter} (table|nil) A table with key-value pairs used to filter the
- returned clients. The available keys are:
- • id (number): Only return clients with the given id
- • bufnr (number): Only return clients attached to this
+ • {filter} (`table?`) Key-value pairs used to filter the returned
+ clients.
+ • {id}? (`integer`) Only return clients with the given id
+ • {bufnr}? (`integer`) Only return clients attached to this
buffer
- • name (string): Only return clients with the given name
- • method (string): Only return clients supporting the given
- method
+ • {name}? (`string`) Only return clients with the given name
+ • {method}? (`string`) Only return clients supporting the
+ given method
Return: ~
- lsp.Client []: List of |vim.lsp.client| objects
+ (`vim.lsp.Client[]`) List of |vim.lsp.Client| objects
get_log_path() *vim.lsp.get_log_path()*
Gets the path of the logfile used by the LSP client.
Return: ~
- (string) path to log file
+ (`string`) path to log file
omnifunc({findstart}, {base}) *vim.lsp.omnifunc()*
Implements 'omnifunc' compatible LSP completion.
Parameters: ~
- • {findstart} (integer) 0 or 1, decides behavior
- • {base} (integer) findstart=0, text to match against
+ • {findstart} (`integer`) 0 or 1, decides behavior
+ • {base} (`integer`) findstart=0, text to match against
Return: ~
- integer|table Decided by {findstart}:
+ (`integer|table`) Decided by {findstart}:
• findstart=0: column where the completion starts, or -2 or -3
• findstart=1: list of matches (actually just calls |complete()|)
@@ -883,7 +798,7 @@ set_log_level({level}) *vim.lsp.set_log_level()*
Use `lsp.log_levels` for reverse lookup.
Parameters: ~
- • {level} (integer|string) the case insensitive level name or number
+ • {level} (`integer|string`) the case insensitive level name or number
See also: ~
• |vim.lsp.log_levels|
@@ -903,12 +818,10 @@ start({config}, {opts}) *vim.lsp.start()*
See |vim.lsp.start_client()| for all available options. The most important
are:
-
• `name` arbitrary name for the LSP client. Should be unique per language
server.
- • `cmd` command (in list form) used to start the language server. Must be
- absolute, or found on `$PATH`. Shell constructs like `~` are not
- expanded.
+ • `cmd` command string[] or function, described at
+ |vim.lsp.start_client()|.
• `root_dir` path to the project root. By default this is used to decide
if an existing client should be re-used. The example above uses
|vim.fs.find()| and |vim.fs.dirname()| to detect the root by traversing
@@ -928,135 +841,29 @@ start({config}, {opts}) *vim.lsp.start()*
`ftplugin/<filetype_name>.lua` (See |ftplugin-name|)
Parameters: ~
- • {config} (table) Same configuration as documented in
- |vim.lsp.start_client()|
- • {opts} (nil|lsp.StartOpts) Optional keyword arguments:
- • reuse_client (fun(client: client, config: table): boolean)
+ • {config} (`vim.lsp.ClientConfig`) Configuration for the server. See
+ |vim.lsp.ClientConfig|.
+ • {opts} (`table?`) Optional keyword arguments
+ • {reuse_client}
+ (`fun(client: vim.lsp.Client, config: table): boolean`)
Predicate used to decide if a client should be re-used.
Used on all running clients. The default implementation
re-uses a client if name and root_dir matches.
- • bufnr (number) Buffer handle to attach to if starting or
- re-using a client (0 for current).
+ • {bufnr} (`integer`) Buffer handle to attach to if starting
+ or re-using a client (0 for current).
Return: ~
- (integer|nil) client_id
+ (`integer?`) client_id
start_client({config}) *vim.lsp.start_client()*
Starts and initializes a client with the given configuration.
- Field `cmd` in {config} is required.
-
- Parameters: ~
- • {config} ( lsp.ClientConfig ) Configuration for the 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` 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 table. Non-string values
- are coerced to string. Example: >
-
- { PORT = 8080; HOST = "0.0.0.0"; }
-<
- • detached: (boolean, default true) Daemonize the server
- process so that it runs in a separate process group from
- Nvim. Nvim will shutdown the process on exit, but if Nvim
- fails to exit cleanly this could leave behind orphaned
- server processes.
- • workspace_folders: (table) List of workspace folders
- passed to the language server. For backwards compatibility
- rootUri and rootPath will be derived from the first
- workspace folder in this list. See `workspaceFolders` in
- the LSP spec.
- • capabilities: Map overriding the default capabilities
- defined by |vim.lsp.protocol.make_client_capabilities()|,
- passed to the language server on initialization. Hint: use
- make_client_capabilities() and modify its result.
- • Note: To send an empty dictionary use
- |vim.empty_dict()|, else it will be encoded as an array.
-
- • handlers: Map of language server method names to
- |lsp-handler|
- • settings: Map with language server specific settings.
- These are returned to the language server if requested via
- `workspace/configuration`. Keys are case-sensitive.
- • commands: table Table that maps string of clientside
- commands to user-defined functions. Commands passed to
- start_client take precedence over the global command
- registry. Each key must be a unique command name, and the
- value is a function which is called if any LSP action
- (code action, code lenses, ...) triggers the command.
- • init_options Values to pass in the initialization request
- as `initializationOptions`. See `initialize` in the LSP
- spec.
- • name: (string, default=client-id) Name in log messages.
- • get_language_id: function(bufnr, filetype) -> language ID
- as string. Defaults to the filetype.
- • offset_encoding: (default="utf-16") One of "utf-8",
- "utf-16", or "utf-32" which is the encoding that the LSP
- server expects. Client does not verify this is correct.
- • on_error: Callback with parameters (code, ...), invoked
- when the client operation throws an error. `code` is a
- number describing the error. Other arguments may be passed
- depending on the error kind. See
- `vim.lsp.rpc.client_errors` for possible errors. Use
- `vim.lsp.rpc.client_errors[code]` to get human-friendly
- name.
- • before_init: Callback with parameters (initialize_params,
- config) invoked before the LSP "initialize" phase, where
- `params` contains the parameters being sent to the server
- and `config` is the config that was passed to
- |vim.lsp.start_client()|. You can use this to modify
- parameters before they are sent.
- • on_init: Callback (client, initialize_result) invoked
- after LSP "initialize", where `result` is a table of
- `capabilities` and anything else the server may send. For
- example, clangd sends `initialize_result.offsetEncoding`
- if `capabilities.offsetEncoding` was sent to it. You can
- only modify the `client.offset_encoding` here before any
- notifications are sent. Most language servers expect to be
- sent client specified settings after initialization. Nvim
- does not make this assumption. A
- `workspace/didChangeConfiguration` notification should be
- sent to the server during on_init.
- • on_exit Callback (code, signal, client_id) invoked on
- client exit.
- • code: exit code of the process
- • signal: number describing the signal used to terminate
- (if any)
- • client_id: client handle
-
- • on_attach: Callback (client, bufnr) invoked when client
- attaches to a buffer.
- • trace: ("off" | "messages" | "verbose" | nil) passed
- directly to the language server in the initialize request.
- Invalid/empty values will default to "off"
- • flags: A table with flags for the client. The current
- (experimental) flags are:
- • allow_incremental_sync (bool, default true): Allow using
- incremental sync for buffer edits
- • debounce_text_changes (number, default 150): Debounce
- didChange notifications to the server by the given
- number in milliseconds. No debounce occurs if nil
- • exit_timeout (number|boolean, default false):
- Milliseconds to wait for server to exit cleanly after
- sending the "shutdown" request before sending kill -15.
- If set to false, nvim exits immediately after sending
- the "shutdown" request to the server.
-
- • root_dir: (string) Directory where the LSP server will
- base its workspaceFolders, rootUri, and rootPath on
- initialization.
+ Parameters: ~
+ • {config} (`vim.lsp.ClientConfig`) Configuration for the server. See
+ |vim.lsp.ClientConfig|.
Return: ~
- (integer|nil) client_id. |vim.lsp.get_client_by_id()| Note: client may
+ (`integer?`) client_id |vim.lsp.get_client_by_id()| Note: client may
not be fully initialized. Use `on_init` to do any actions once the
client has been initialized.
@@ -1065,12 +872,12 @@ status() *vim.lsp.status()*
a string. Empty if there are no clients or if no new messages
Return: ~
- (string)
+ (`string`)
stop_client({client_id}, {force}) *vim.lsp.stop_client()*
Stops a client(s).
- You can also use the `stop()` function on a |vim.lsp.client| object. To
+ You can also use the `stop()` function on a |vim.lsp.Client| object. To
stop all clients: >lua
vim.lsp.stop_client(vim.lsp.get_clients())
<
@@ -1079,9 +886,9 @@ stop_client({client_id}, {force}) *vim.lsp.stop_client()*
for this client, then force-shutdown is attempted.
Parameters: ~
- • {client_id} integer|table id or |vim.lsp.client| object, or list
- thereof
- • {force} (boolean|nil) shutdown forcefully
+ • {client_id} (`integer|vim.lsp.Client`) id or |vim.lsp.Client| object,
+ or list thereof
+ • {force} (`boolean?`) shutdown forcefully
tagfunc({pattern}, {flags}) *vim.lsp.tagfunc()*
Provides an interface between the built-in client and 'tagfunc'.
@@ -1092,29 +899,325 @@ tagfunc({pattern}, {flags}) *vim.lsp.tagfunc()*
LSP servers, falls back to using built-in tags.
Parameters: ~
- • {pattern} (string) Pattern used to find a workspace symbol
- • {flags} (string) See |tag-function|
+ • {pattern} (`string`) Pattern used to find a workspace symbol
+ • {flags} (`string`) See |tag-function|
Return: ~
- table[] tags A list of matching tags
+ (`table[]`) tags A list of matching tags
with({handler}, {override_config}) *vim.lsp.with()*
Function to manage overriding defaults for LSP handlers.
Parameters: ~
- • {handler} (function) See |lsp-handler|
- • {override_config} (table) Table containing the keys to override
+ • {handler} (`lsp.Handler`) See |lsp-handler|
+ • {override_config} (`table`) Table containing the keys to override
behavior of the {handler}
==============================================================================
+Lua module: vim.lsp.client *lsp-client*
+
+*vim.lsp.Client*
+
+ Fields: ~
+ • {id} (`integer`) The id allocated to the client.
+ • {name} (`string`) If a name is specified on creation,
+ that will be used. Otherwise it is just the
+ client id. This is used for logs and messages.
+ • {rpc} (`vim.lsp.rpc.PublicClient`) RPC client
+ object, for low level interaction with the
+ client. See |vim.lsp.rpc.start()|.
+ • {offset_encoding} (`string`) The encoding used for communicating
+ with the server. You can modify this in the
+ `config`'s `on_init` method before text is
+ sent to the server.
+ • {handlers} (`table<string,lsp.Handler>`) The handlers
+ used by the client as described in
+ |lsp-handler|.
+ • {requests} (`table<integer,{ type: string, bufnr: integer, method: string}>`)
+ The current pending requests in flight to the
+ server. Entries are key-value pairs with the
+ key being the request id while the value is a
+ table with `type`, `bufnr`, and `method`
+ key-value pairs. `type` is either "pending"
+ for an active request, or "cancel" for a
+ cancel request. It will be "complete"
+ ephemerally while executing |LspRequest|
+ autocmds when replies are received from the
+ server.
+ • {config} (`vim.lsp.ClientConfig`) copy of the table
+ that was passed by the user to
+ |vim.lsp.start_client()|. See
+ |vim.lsp.ClientConfig|.
+ • {server_capabilities} (`lsp.ServerCapabilities?`) Response from the
+ server sent on `initialize` describing the
+ server's capabilities.
+ • {progress} (`vim.lsp.Client.Progress`) A ring buffer
+ (|vim.ringbuf()|) containing progress messages
+ sent by the server. See
+ |vim.lsp.Client.Progress|.
+ • {initialized} (`true?`)
+ • {workspace_folders} (`lsp.WorkspaceFolder[]?`) The workspace
+ folders configured in the client when the
+ server starts. This property is only available
+ if the client supports workspace folders. It
+ can be `null` if the client supports workspace
+ folders but none are configured.
+ • {root_dir} (`string`)
+ • {attached_buffers} (`table<integer,true>`)
+ • {commands} (`table<string,fun(command: lsp.Command, ctx: table)>`)
+ Table of command name to function which is
+ called if any LSP action (code action, code
+ lenses, ...) triggers the command. Client
+ commands take precedence over the global
+ command registry.
+ • {settings} (`table`) Map with language server specific
+ settings. These are returned to the language
+ server if requested via
+ `workspace/configuration`. Keys are
+ case-sensitive.
+ • {flags} (`table`) A table with flags for the client.
+ The current (experimental) flags are:
+ • {allow_incremental_sync}? (`boolean`) Allow
+ using incremental sync for buffer edits
+ (defailt: `true`)
+ • {debounce_text_changes} (`integer`, default:
+ `150`) Debounce `didChange` notifications to
+ the server by the given number in
+ milliseconds. No debounce occurs if `nil`.
+ • {exit_timeout} (`integer|false`, default:
+ `false`) Milliseconds to wait for server to
+ exit cleanly after sending the "shutdown"
+ request before sending kill -15. If set to
+ false, nvim exits immediately after sending
+ the "shutdown" request to the server.
+ • {get_language_id} (`fun(bufnr: integer, filetype: string): string`)
+ • {capabilities} (`lsp.ClientCapabilities`) The capabilities
+ provided by the client (editor or tool)
+ • {dynamic_capabilities} (`lsp.DynamicCapabilities`)
+ • {request} (`fun(method: string, params: table?, handler: lsp.Handler?, bufnr: integer): boolean, integer?`)
+ Sends a request to the server. This is a thin
+ wrapper around {client.rpc.request} with some
+ additional checking. If {handler} is not
+ specified and if there's no respective global
+ handler, then an error will occur. Returns:
+ {status}, {client_id}?. {status} is a boolean
+ indicating if the notification was successful.
+ If it is `false`, then it will always be
+ `false` (the client has shutdown). If {status}
+ is `true`, the function returns {request_id}
+ as the second result. You can use this with
+ `client.cancel_request(request_id)` to cancel
+ the request.
+ • {request_sync} (`fun(method: string, params: table?, timeout_ms: integer?, bufnr: integer): {err: lsp.ResponseError?, result:any}?, string?`)
+ err # a dictionary, where
+ • {notify} (`fun(method: string, params: table?): boolean`)
+ Sends a notification to an LSP server.
+ Returns: a boolean to indicate if the
+ notification was successful. If it is false,
+ then it will always be false (the client has
+ shutdown).
+ • {cancel_request} (`fun(id: integer): boolean`) Cancels a
+ request with a given request id. Returns: same
+ as `notify()`.
+ • {stop} (`fun(force?: boolean)`) Stops a client,
+ optionally with force. By default, it will
+ just ask the server to shutdown without force.
+ If you request to stop a client which has
+ previously been requested to shutdown, it will
+ automatically escalate and force shutdown.
+ • {on_attach} (`fun(bufnr: integer)`) Runs the on_attach
+ function from the client's config if it was
+ defined. Useful for buffer-local setup.
+ • {supports_method} (`fun(method: string, opts?: {bufnr: integer?}): boolean`)
+ Checks if a client supports a given method.
+ Always returns true for unknown off-spec
+ methods. {opts} is a optional
+ `{bufnr?: integer}` table. Some language
+ server capabilities can be file specific.
+ • {is_stopped} (`fun(): boolean`) Checks whether a client is
+ stopped. Returns: true if the client is fully
+ stopped.
+
+*vim.lsp.Client.Progress*
+ Extends: |vim.Ringbuf|
+
+
+ Fields: ~
+ • {pending} (`table<lsp.ProgressToken,lsp.LSPAny>`)
+
+*vim.lsp.ClientConfig*
+
+ Fields: ~
+ • {cmd} (`string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient?`)
+ command string[] that launches the language
+ server (treated as in |jobstart()|, must be
+ absolute or on `$PATH`, shell constructs like
+ "~" are not expanded), or function that creates
+ an RPC client. Function receives a `dispatchers`
+ table and returns a table with member functions
+ `request`, `notify`, `is_closing` and
+ `terminate`. See |vim.lsp.rpc.request()|,
+ |vim.lsp.rpc.notify()|. For TCP there is a
+ builtin RPC client factory:
+ |vim.lsp.rpc.connect()|
+ • {cmd_cwd}? (`string`, default: cwd) 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 table.
+ Non-string values are coerced to string.
+ Example: >lua
+ { PORT = 8080; HOST = "0.0.0.0"; }
+<
+ • {detached}? (`boolean`, default: true) Daemonize the server
+ process so that it runs in a separate process
+ group from Nvim. Nvim will shutdown the process
+ on exit, but if Nvim fails to exit cleanly this
+ could leave behind orphaned server processes.
+ • {workspace_folders}? (`lsp.WorkspaceFolder[]`) List of workspace
+ folders passed to the language server. For
+ backwards compatibility rootUri and rootPath
+ will be derived from the first workspace folder
+ in this list. See `workspaceFolders` in the LSP
+ spec.
+ • {capabilities}? (`lsp.ClientCapabilities`) Map overriding the
+ default capabilities defined by
+ |vim.lsp.protocol.make_client_capabilities()|,
+ passed to the language server on initialization.
+ Hint: use make_client_capabilities() and modify
+ its result.
+ • Note: To send an empty dictionary use
+ |vim.empty_dict()|, else it will be encoded as
+ an array.
+ • {handlers}? (`table<string,function>`) Map of language
+ server method names to |lsp-handler|
+ • {settings}? (`table`) Map with language server specific
+ settings. See the {settings} in
+ |vim.lsp.Client|.
+ • {commands}? (`table<string,fun(command: lsp.Command, ctx: table)>`)
+ Table that maps string of clientside commands to
+ user-defined functions. Commands passed to
+ start_client take precedence over the global
+ command registry. Each key must be a unique
+ command name, and the value is a function which
+ is called if any LSP action (code action, code
+ lenses, ...) triggers the command.
+ • {init_options}? (`table`) Values to pass in the initialization
+ request as `initializationOptions`. See
+ `initialize` in the LSP spec.
+ • {name}? (`string`, default: client-id) Name in log
+ messages.
+ • {get_language_id}? (`fun(bufnr: integer, filetype: string): string`)
+ Language ID as string. Defaults to the filetype.
+ • {offset_encoding}? (`'utf-8'|'utf-16'|'utf-32'`) The encoding that
+ the LSP server expects. Client does not verify
+ this is correct.
+ • {on_error}? (`fun(code: integer, err: string)`) Callback
+ invoked when the client operation throws an
+ error. `code` is a number describing the error.
+ Other arguments may be passed depending on the
+ error kind. See `vim.lsp.rpc.client_errors` for
+ possible errors. Use
+ `vim.lsp.rpc.client_errors[code]` to get
+ human-friendly name.
+ • {before_init}? (`fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)`)
+ Callback invoked before the LSP "initialize"
+ phase, where `params` contains the parameters
+ being sent to the server and `config` is the
+ config that was passed to
+ |vim.lsp.start_client()|. You can use this to
+ modify parameters before they are sent.
+ • {on_init}? (`elem_or_list<fun(client: vim.lsp.Client, initialize_result: lsp.InitializeResult)>`)
+ Callback invoked after LSP "initialize", where
+ `result` is a table of `capabilities` and
+ anything else the server may send. For example,
+ clangd sends `initialize_result.offsetEncoding`
+ if `capabilities.offsetEncoding` was sent to it.
+ You can only modify the `client.offset_encoding`
+ here before any notifications are sent.
+ • {on_exit}? (`elem_or_list<fun(code: integer, signal: integer, client_id: integer)>`)
+ Callback invoked on client exit.
+ • code: exit code of the process
+ • signal: number describing the signal used to
+ terminate (if any)
+ • client_id: client handle
+ • {on_attach}? (`elem_or_list<fun(client: vim.lsp.Client, bufnr: integer)>`)
+ Callback invoked when client attaches to a
+ buffer.
+ • {trace}? (`'off'|'messages'|'verbose'`, default: "off")
+ Passed directly to the language server in the
+ initialize request. Invalid/empty values will
+ • {flags}? (`table`) A table with flags for the client. The
+ current (experimental) flags are:
+ • {allow_incremental_sync}? (`boolean`) Allow
+ using incremental sync for buffer edits
+ (defailt: `true`)
+ • {debounce_text_changes} (`integer`, default:
+ `150`) Debounce `didChange` notifications to
+ the server by the given number in
+ milliseconds. No debounce occurs if `nil`.
+ • {exit_timeout} (`integer|false`, default:
+ `false`) Milliseconds to wait for server to
+ exit cleanly after sending the "shutdown"
+ request before sending kill -15. If set to
+ false, nvim exits immediately after sending
+ the "shutdown" request to the server.
+ • {root_dir}? (`string`) Directory where the LSP server will
+ base its workspaceFolders, rootUri, and rootPath
+ on initialization.
+
+
+
+==============================================================================
Lua module: vim.lsp.buf *lsp-buf*
+*vim.lsp.ListOpts*
+
+ Fields: ~
+ • {on_list}? (`fun(t: vim.lsp.LocationOpts.OnList)`) list-handler
+ replacing the default handler. Called for any non-empty
+ result. This table can be used with |setqflist()| or
+ |setloclist()|. E.g.: >lua
+ local function on_list(options)
+ vim.fn.setqflist({}, ' ', options)
+ vim.cmd.cfirst()
+ end
+
+ vim.lsp.buf.definition({ on_list = on_list })
+ vim.lsp.buf.references(nil, { on_list = on_list })
+<
+
+ If you prefer loclist do something like this: >lua
+ local function on_list(options)
+ vim.fn.setloclist(0, {}, ' ', options)
+ vim.cmd.lopen()
+ end
+<
+
+*vim.lsp.LocationOpts*
+ Extends: |vim.lsp.ListOpts|
+
+
+ Fields: ~
+ • {reuse_win}? (`boolean`) Jump to existing window if buffer is already
+ open.
+
+*vim.lsp.LocationOpts.OnList*
+
+ Fields: ~
+ • {items} (`table[]`) Structured like |setqflist-what|
+ • {title}? (`string`) Title for the list.
+ • {context}? (`table`) `ctx` from |lsp-handler|
+
+
*vim.lsp.buf.add_workspace_folder()*
add_workspace_folder({workspace_folder})
Add the folder at path to the workspace folders. If {path} is not
provided, the user will be prompted for a path using |input()|.
+ Parameters: ~
+ • {workspace_folder} (`string?`)
+
clear_references() *vim.lsp.buf.clear_references()*
Removes document highlights from current buffer.
@@ -1122,27 +1225,26 @@ code_action({options}) *vim.lsp.buf.code_action()*
Selects a code action available at the current cursor position.
Parameters: ~
- • {options} (table|nil) Optional table which holds the following
- optional fields:
- • context: (table|nil) Corresponds to `CodeActionContext` of the LSP specification:
- • diagnostics (table|nil): LSP `Diagnostic[]`. Inferred
+ • {options} (`table?`) A table with the following fields:
+ • {context}? (`lsp.CodeActionContext`) Corresponds to
+ `CodeActionContext` of the LSP specification:
+ • {diagnostics}? (`table`) LSP `Diagnostic[]`. Inferred
from the current position if not provided.
- • only (table|nil): List of LSP `CodeActionKind`s used to
+ • {only}? (`table`) List of LSP `CodeActionKind`s used to
filter the code actions. Most language servers support
values like `refactor` or `quickfix`.
- • triggerKind (number|nil): The reason why code actions
+ • {triggerKind}? (`integer`) The reason why code actions
were requested.
-
- • filter: (function|nil) Predicate taking an `CodeAction`
- and returning a boolean.
- • apply: (boolean|nil) When set to `true`, and there is
+ • {filter}? (`fun(x: lsp.CodeAction|lsp.Command):boolean`)
+ Predicate taking an `CodeAction` and returning a boolean.
+ • {apply}? (`boolean`) When set to `true`, and there is
just one remaining action (after filtering), the action
is applied without user query.
- • range: (table|nil) Range for which code actions should be
- requested. If in visual mode this defaults to the active
- selection. Table must contain `start` and `end` keys with
- {row,col} tuples using mark-like indexing. See
- |api-indexing|
+ • {range}? (`{start: integer[], end: integer[]}`) Range for
+ which code actions should be requested. If in visual mode
+ this defaults to the active selection. Table must contain
+ `start` and `end` keys with {row,col} tuples using
+ mark-like indexing. See |api-indexing|
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
@@ -1153,7 +1255,7 @@ completion({context}) *vim.lsp.buf.completion()*
called in Insert mode.
Parameters: ~
- • {context} (table) (context support not yet implemented) Additional
+ • {context} (`table`) (context support not yet implemented) Additional
information about the context in which a completion was
triggered (how it was triggered, and by which trigger
character, if applicable)
@@ -1169,21 +1271,13 @@ declaration({options}) *vim.lsp.buf.declaration()*
|vim.lsp.buf.definition()| instead.
Parameters: ~
- • {options} (table|nil) additional options
- • reuse_win: (boolean) Jump to existing window if buffer is
- already open.
- • on_list: (function) |lsp-on-list-handler| replacing the
- default handler. Called for any non-empty result.
+ • {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|.
definition({options}) *vim.lsp.buf.definition()*
Jumps to the definition of the symbol under the cursor.
Parameters: ~
- • {options} (table|nil) additional options
- • reuse_win: (boolean) Jump to existing window if buffer is
- already open.
- • on_list: (function) |lsp-on-list-handler| replacing the
- default handler. Called for any non-empty result.
+ • {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|.
document_highlight() *vim.lsp.buf.document_highlight()*
Send request to the server to resolve document highlights for the current
@@ -1203,15 +1297,13 @@ document_symbol({options}) *vim.lsp.buf.document_symbol()*
Lists all symbols in the current buffer in the quickfix window.
Parameters: ~
- • {options} (table|nil) additional options
- • on_list: (function) handler for list results. See
- |lsp-on-list-handler|
+ • {options} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|.
execute_command({command_params}) *vim.lsp.buf.execute_command()*
Executes an LSP server command.
Parameters: ~
- • {command_params} (table) A valid `ExecuteCommandParams` object
+ • {command_params} (`lsp.ExecuteCommandParams`)
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
@@ -1221,38 +1313,37 @@ format({options}) *vim.lsp.buf.format()*
server clients.
Parameters: ~
- • {options} (table|nil) Optional table which holds the following
- optional fields:
- • formatting_options (table|nil): Can be used to specify
+ • {options} (`table?`) A table with the following fields:
+ • {formatting_options}? (`table`) Can be used to specify
FormattingOptions. Some unspecified options will be
- automatically derived from the current Nvim options. See https://microsoft.github.io/language-server-protocol/specification/#formattingOptions
- • timeout_ms (integer|nil, default 1000): Time in
+ automatically derived from the current Nvim options. See
+ https://microsoft.github.io/language-server-protocol/specification/#formattingOptions
+ • {timeout_ms}? (`integer`, default: `1000`) Time in
milliseconds to block for formatting requests. No effect
- if async=true
- • bufnr (number|nil): Restrict formatting to the clients
- attached to the given buffer, defaults to the current
- buffer (0).
- • filter (function|nil): Predicate used to filter clients.
- Receives a client as argument and must return a boolean.
- Clients matching the predicate are included. Example: >lua
-
- -- Never request typescript-language-server for formatting
- vim.lsp.buf.format {
- filter = function(client) return client.name ~= "tsserver" end
- }
+ if async=true.
+ • {bufnr}? (`integer`, default: current buffer) Restrict
+ formatting to the clients attached to the given buffer.
+ • {filter}? (`fun(client: vim.lsp.Client): boolean?`)
+ Predicate used to filter clients. Receives a client as
+ argument and must return a boolean. Clients matching the
+ predicate are included. Example: >lua
+ -- Never request typescript-language-server for formatting
+ vim.lsp.buf.format {
+ filter = function(client) return client.name ~= "tsserver" end
+ }
<
- • async boolean|nil If true the method won't block.
- Defaults to false. Editing the buffer while formatting
+ • {async}? (`boolean`, default: false) If true the method
+ won't block. Editing the buffer while formatting
asynchronous can lead to unexpected changes.
- • id (number|nil): Restrict formatting to the client with
+ • {id}? (`integer`) Restrict formatting to the client with
ID (client.id) matching this field.
- • name (string|nil): Restrict formatting to the client with
+ • {name}? (`string`) Restrict formatting to the client with
name (client.name) matching this field.
- • range (table|nil) Range to format. Table must contain
- `start` and `end` keys with {row,col} tuples using (1,0)
- indexing. Defaults to current selection in visual mode
- Defaults to `nil` in other modes, formatting the full
- buffer
+ • {range}? (`{start:integer[],end:integer[]}`, default:
+ current selection in visual mode, `nil` in other modes,
+ formatting the full buffer) Range to format. Table must
+ contain `start` and `end` keys with {row,col} tuples
+ using (1,0) indexing.
hover() *vim.lsp.buf.hover()*
Displays hover information about the symbol under the cursor in a floating
@@ -1263,9 +1354,7 @@ implementation({options}) *vim.lsp.buf.implementation()*
quickfix window.
Parameters: ~
- • {options} (table|nil) additional options
- • on_list: (function) |lsp-on-list-handler| replacing the
- default handler. Called for any non-empty result.
+ • {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|.
incoming_calls() *vim.lsp.buf.incoming_calls()*
Lists all the call sites of the symbol under the cursor in the |quickfix|
@@ -1285,10 +1374,8 @@ references({context}, {options}) *vim.lsp.buf.references()*
window.
Parameters: ~
- • {context} (table|nil) Context for the request
- • {options} (table|nil) additional options
- • on_list: (function) handler for list results. See
- |lsp-on-list-handler|
+ • {context} (`table?`) Context for the request
+ • {options} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|.
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
@@ -1298,18 +1385,23 @@ remove_workspace_folder({workspace_folder})
Remove the folder at path from the workspace folders. If {path} is not
provided, the user will be prompted for a path using |input()|.
+ Parameters: ~
+ • {workspace_folder} (`string?`)
+
rename({new_name}, {options}) *vim.lsp.buf.rename()*
Renames all references to the symbol under the cursor.
Parameters: ~
- • {new_name} (string|nil) If not provided, the user will be prompted
- for a new name using |vim.ui.input()|.
- • {options} (table|nil) additional options
- • filter (function|nil): Predicate used to filter clients.
- Receives a client as argument and must return a boolean.
- Clients matching the predicate are included.
- • name (string|nil): Restrict clients used for rename to
+ • {new_name} (`string?`) If not provided, the user will be prompted for
+ a new name using |vim.ui.input()|.
+ • {options} (`table?`) Additional options:
+ • {filter}? (`fun(client: vim.lsp.Client): boolean?`)
+ Predicate used to filter clients. Receives a client as
+ argument and must return a boolean. Clients matching the
+ predicate are included.
+ • {name}? (`string`) Restrict clients used for rename to
ones where client.name matches this field.
+ • {bufnr}? (`integer`) (default: current buffer)
signature_help() *vim.lsp.buf.signature_help()*
Displays signature information about the symbol under the cursor in a
@@ -1319,11 +1411,7 @@ type_definition({options}) *vim.lsp.buf.type_definition()*
Jumps to the definition of the type of the symbol under the cursor.
Parameters: ~
- • {options} (table|nil) additional options
- • reuse_win: (boolean) Jump to existing window if buffer is
- already open.
- • on_list: (function) |lsp-on-list-handler| replacing the
- default handler. Called for any non-empty result.
+ • {options} (`vim.lsp.LocationOpts?`) See |vim.lsp.LocationOpts|.
workspace_symbol({query}, {options}) *vim.lsp.buf.workspace_symbol()*
Lists all symbols in the current workspace in the quickfix window.
@@ -1333,10 +1421,8 @@ workspace_symbol({query}, {options}) *vim.lsp.buf.workspace_symbol()*
string means no filtering is done.
Parameters: ~
- • {query} (string|nil) optional
- • {options} (table|nil) additional options
- • on_list: (function) handler for list results. See
- |lsp-on-list-handler|
+ • {query} (`string?`) optional
+ • {options} (`vim.lsp.ListOpts?`) See |vim.lsp.ListOpts|.
==============================================================================
@@ -1348,8 +1434,8 @@ get_namespace({client_id}, {is_pull})
|vim.diagnostic| for diagnostics
Parameters: ~
- • {client_id} (integer) The id of the LSP client
- • {is_pull} boolean? Whether the namespace is for a pull or push
+ • {client_id} (`integer`) The id of the LSP client
+ • {is_pull} (`boolean?`) Whether the namespace is for a pull or push
client. Defaults to push
*vim.lsp.diagnostic.on_diagnostic()*
@@ -1378,7 +1464,10 @@ on_diagnostic({_}, {result}, {ctx}, {config})
<
Parameters: ~
- • {config} (table) Configuration table (see |vim.diagnostic.config()|).
+ • {result} (`lsp.DocumentDiagnosticReport`)
+ • {ctx} (`lsp.HandlerContext`)
+ • {config} (`vim.diagnostic.Opts`) Configuration table (see
+ |vim.diagnostic.config()|).
*vim.lsp.diagnostic.on_publish_diagnostics()*
on_publish_diagnostics({_}, {result}, {ctx}, {config})
@@ -1406,7 +1495,10 @@ on_publish_diagnostics({_}, {result}, {ctx}, {config})
<
Parameters: ~
- • {config} (table) Configuration table (see |vim.diagnostic.config()|).
+ • {result} (`lsp.PublishDiagnosticsParams`)
+ • {ctx} (`lsp.HandlerContext`)
+ • {config} (`vim.diagnostic.Opts?`) Configuration table (see
+ |vim.diagnostic.config()|).
==============================================================================
@@ -1416,40 +1508,50 @@ clear({client_id}, {bufnr}) *vim.lsp.codelens.clear()*
Clear the lenses
Parameters: ~
- • {client_id} (integer|nil) filter by client_id. All clients if nil
- • {bufnr} (integer|nil) filter by buffer. All buffers if nil
+ • {client_id} (`integer?`) filter by client_id. All clients if nil
+ • {bufnr} (`integer?`) filter by buffer. All buffers if nil, 0 for
+ current buffer
display({lenses}, {bufnr}, {client_id}) *vim.lsp.codelens.display()*
Display the lenses using virtual text
Parameters: ~
- • {lenses} lsp.CodeLens[]|nil lenses to display
- • {bufnr} (integer)
- • {client_id} (integer)
+ • {lenses} (`lsp.CodeLens[]?`) lenses to display
+ • {bufnr} (`integer`)
+ • {client_id} (`integer`)
get({bufnr}) *vim.lsp.codelens.get()*
Return all lenses for the given buffer
Parameters: ~
- • {bufnr} (integer) Buffer number. 0 can be used for the current
+ • {bufnr} (`integer`) Buffer number. 0 can be used for the current
buffer.
Return: ~
- lsp.CodeLens[]
+ (`lsp.CodeLens[]`)
- *vim.lsp.codelens.on_codelens()*
-on_codelens({err}, {result}, {ctx}, {_})
+on_codelens({err}, {result}, {ctx}) *vim.lsp.codelens.on_codelens()*
|lsp-handler| for the method `textDocument/codeLens`
-refresh() *vim.lsp.codelens.refresh()*
- Refresh the codelens for the current buffer
+ Parameters: ~
+ • {err} (`lsp.ResponseError?`)
+ • {result} (`lsp.CodeLens[]`)
+ • {ctx} (`lsp.HandlerContext`)
+
+refresh({opts}) *vim.lsp.codelens.refresh()*
+ Refresh the lenses.
It is recommended to trigger this using an autocmd or via keymap.
Example: >vim
- autocmd BufEnter,CursorHold,InsertLeave <buffer> lua vim.lsp.codelens.refresh()
+ autocmd BufEnter,CursorHold,InsertLeave <buffer> lua vim.lsp.codelens.refresh({ bufnr = 0 })
<
+ Parameters: ~
+ • {opts} (`table?`) Optional fields
+ • {bufnr} (`integer?`) filter by buffer. All buffers if nil, 0
+ for current buffer
+
run() *vim.lsp.codelens.run()*
Run the code lens in the current line
@@ -1457,23 +1559,27 @@ save({lenses}, {bufnr}, {client_id}) *vim.lsp.codelens.save()*
Store lenses for a specific buffer and client
Parameters: ~
- • {lenses} lsp.CodeLens[]|nil lenses to store
- • {bufnr} (integer)
- • {client_id} (integer)
+ • {lenses} (`lsp.CodeLens[]?`) lenses to store
+ • {bufnr} (`integer`)
+ • {client_id} (`integer`)
==============================================================================
Lua module: vim.lsp.inlay_hint *lsp-inlay_hint*
enable({bufnr}, {enable}) *vim.lsp.inlay_hint.enable()*
- Enable/disable/toggle inlay hints for a buffer
+ Enables or disables inlay hints for a buffer.
+
+ To "toggle", pass the inverse of `is_enabled()`: >lua
+ vim.lsp.inlay_hint.enable(0, not vim.lsp.inlay_hint.is_enabled())
+<
Note: ~
- This API is pre-release (unstable).
+ • This API is pre-release (unstable).
Parameters: ~
- • {bufnr} (integer|nil) Buffer handle, or 0 or nil for current
- • {enable} (boolean|nil) true/nil to enable, false to disable
+ • {bufnr} (`integer?`) Buffer handle, or 0 or nil for current
+ • {enable} (`boolean?`) true/nil to enable, false to disable
get({filter}) *vim.lsp.inlay_hint.get()*
Get the list of inlay hints, (optionally) restricted by buffer or range.
@@ -1493,28 +1599,29 @@ get({filter}) *vim.lsp.inlay_hint.get()*
<
Note: ~
- This API is pre-release (unstable).
+ • This API is pre-release (unstable).
Parameters: ~
- • {filter} vim.lsp.inlay_hint.get.filter ? Optional filters |kwargs|:
- • bufnr (integer?): 0 for current buffer
- • range (lsp.Range?)
+ • {filter} (`table?`) Optional filters |kwargs|:
+ • {bufnr} (`integer?`)
+ • {range} (`lsp.Range?`)
Return: ~
- vim.lsp.inlay_hint.get.ret [] Each list item is a table with the following fields:
- • bufnr (integer)
- • client_id (integer)
- • inlay_hint (lsp.InlayHint)
+ (`table[]`) A list of objects with the following fields:
+ • {bufnr} (`integer`)
+ • {client_id} (`integer`)
+ • {inlay_hint} (`lsp.InlayHint`)
is_enabled({bufnr}) *vim.lsp.inlay_hint.is_enabled()*
+
Note: ~
- This API is pre-release (unstable).
+ • This API is pre-release (unstable).
Parameters: ~
- • {bufnr} (integer|nil) Buffer handle, or 0 or nil for current
+ • {bufnr} (`integer?`) Buffer handle, or 0 or nil for current
Return: ~
- (boolean)
+ (`boolean`)
==============================================================================
@@ -1527,7 +1634,7 @@ force_refresh({bufnr}) *vim.lsp.semantic_tokens.force_refresh()*
highlighting (|vim.lsp.semantic_tokens.start()| has been called for it)
Parameters: ~
- • {bufnr} (integer|nil) filter by buffer. All buffers if nil, current
+ • {bufnr} (`integer?`) filter by buffer. All buffers if nil, current
buffer if 0
*vim.lsp.semantic_tokens.get_at_pos()*
@@ -1536,12 +1643,12 @@ get_at_pos({bufnr}, {row}, {col})
arguments, returns the token under the cursor.
Parameters: ~
- • {bufnr} (integer|nil) Buffer number (0 for current buffer, default)
- • {row} (integer|nil) Position row (default cursor position)
- • {col} (integer|nil) Position column (default cursor position)
+ • {bufnr} (`integer?`) Buffer number (0 for current buffer, default)
+ • {row} (`integer?`) Position row (default cursor position)
+ • {col} (`integer?`) Position column (default cursor position)
Return: ~
- (table|nil) List of tokens at position. Each token has the following
+ (`table?`) List of tokens at position. Each token has the following
fields:
• line (integer) line number, 0-based
• start_col (integer) start column, 0-based
@@ -1549,6 +1656,7 @@ get_at_pos({bufnr}, {row}, {col})
• type (string) token type as string, e.g. "variable"
• modifiers (table) token modifiers as a set. E.g., { static = true,
readonly = true }
+ • client_id (integer)
*vim.lsp.semantic_tokens.highlight_token()*
highlight_token({token}, {bufnr}, {client_id}, {hl_group}, {opts})
@@ -1560,15 +1668,15 @@ highlight_token({token}, {bufnr}, {client_id}, {hl_group}, {opts})
use inside |LspTokenUpdate| callbacks.
Parameters: ~
- • {token} (table) a semantic token, found as `args.data.token` in
+ • {token} (`table`) a semantic token, found as `args.data.token` in
|LspTokenUpdate|.
- • {bufnr} (integer) the buffer to highlight
- • {client_id} (integer) The ID of the |vim.lsp.client|
- • {hl_group} (string) Highlight group name
- • {opts} (table|nil) Optional parameters.
- • priority: (integer|nil) Priority for the applied
- extmark. Defaults to
- `vim.highlight.priorities.semantic_tokens + 3`
+ • {bufnr} (`integer`) the buffer to highlight
+ • {client_id} (`integer`) The ID of the |vim.lsp.Client|
+ • {hl_group} (`string`) Highlight group name
+ • {opts} (`table?`) Optional parameters:
+ • {priority}? (`integer`, default:
+ `vim.highlight.priorities.semantic_tokens + 3`)
+ Priority for the applied extmark.
start({bufnr}, {client_id}, {opts}) *vim.lsp.semantic_tokens.start()*
Start the semantic token highlighting engine for the given buffer with the
@@ -1583,9 +1691,9 @@ start({bufnr}, {client_id}, {opts}) *vim.lsp.semantic_tokens.start()*
<
Parameters: ~
- • {bufnr} (integer)
- • {client_id} (integer)
- • {opts} (nil|table) Optional keyword arguments
+ • {bufnr} (`integer`)
+ • {client_id} (`integer`)
+ • {opts} (`table?`) Optional keyword arguments
• debounce (integer, default: 200): Debounce token
requests to the server by the given number in
milliseconds
@@ -1600,8 +1708,8 @@ stop({bufnr}, {client_id}) *vim.lsp.semantic_tokens.stop()*
from the buffer.
Parameters: ~
- • {bufnr} (integer)
- • {client_id} (integer)
+ • {bufnr} (`integer`)
+ • {client_id} (`integer`)
==============================================================================
@@ -1620,7 +1728,9 @@ hover({_}, {result}, {ctx}, {config}) *vim.lsp.handlers.hover()*
<
Parameters: ~
- • {config} (table) Configuration table.
+ • {result} (`lsp.Hover`)
+ • {ctx} (`lsp.HandlerContext`)
+ • {config} (`table`) Configuration table.
• border: (default=nil)
• Add borders to the floating window
• See |vim.lsp.util.open_floating_preview()| for more
@@ -1640,9 +1750,9 @@ signature_help({_}, {result}, {ctx}, {config})
<
Parameters: ~
- • {result} (table) Response from the language server
- • {ctx} (table) Client context
- • {config} (table) Configuration table.
+ • {result} (`lsp.SignatureHelp`) Response from the language server
+ • {ctx} (`lsp.HandlerContext`) Client context
+ • {config} (`table`) Configuration table.
• border: (default=nil)
• Add borders to the floating window
• See |vim.lsp.util.open_floating_preview()| for more
@@ -1658,9 +1768,10 @@ apply_text_document_edit({text_document_edit}, {index}, {offset_encoding})
document.
Parameters: ~
- • {text_document_edit} (table) a `TextDocumentEdit` object
- • {index} (integer) Optional index of the edit, if from a
- list of edits (or nil, if not from a list)
+ • {text_document_edit} (`table`) a `TextDocumentEdit` object
+ • {index} (`integer`) Optional index of the edit, if from
+ a list of edits (or nil, if not from a list)
+ • {offset_encoding} (`string?`)
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit
@@ -1670,9 +1781,9 @@ apply_text_edits({text_edits}, {bufnr}, {offset_encoding})
Applies a list of text edits to a buffer.
Parameters: ~
- • {text_edits} (table) list of `TextEdit` objects
- • {bufnr} (integer) Buffer id
- • {offset_encoding} (string) utf-8|utf-16|utf-32
+ • {text_edits} (`table`) list of `TextEdit` objects
+ • {bufnr} (`integer`) Buffer id
+ • {offset_encoding} (`string`) utf-8|utf-16|utf-32
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textEdit
@@ -1682,24 +1793,27 @@ apply_workspace_edit({workspace_edit}, {offset_encoding})
Applies a `WorkspaceEdit`.
Parameters: ~
- • {workspace_edit} (table) `WorkspaceEdit`
- • {offset_encoding} (string) utf-8|utf-16|utf-32 (required)
+ • {workspace_edit} (`table`) `WorkspaceEdit`
+ • {offset_encoding} (`string`) utf-8|utf-16|utf-32 (required)
+
+ See also: ~
+ • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
buf_clear_references({bufnr}) *vim.lsp.util.buf_clear_references()*
Removes document highlights from a buffer.
Parameters: ~
- • {bufnr} (integer|nil) Buffer id
+ • {bufnr} (`integer?`) Buffer id
*vim.lsp.util.buf_highlight_references()*
buf_highlight_references({bufnr}, {references}, {offset_encoding})
Shows a list of document highlights for a certain buffer.
Parameters: ~
- • {bufnr} (integer) Buffer id
- • {references} (table) List of `DocumentHighlight` objects to
+ • {bufnr} (`integer`) Buffer id
+ • {references} (`table`) List of `DocumentHighlight` objects to
highlight
- • {offset_encoding} (string) One of "utf-8", "utf-16", "utf-32".
+ • {offset_encoding} (`string`) One of "utf-8", "utf-16", "utf-32".
See also: ~
• https://microsoft.github.io/language-server-protocol/specification/#textDocumentContentChangeEvent
@@ -1709,14 +1823,14 @@ character_offset({buf}, {row}, {col}, {offset_encoding})
Returns the UTF-32 and UTF-16 offsets for a position in a certain buffer.
Parameters: ~
- • {buf} (integer) buffer number (0 for current)
- • {row} 0-indexed line
- • {col} 0-indexed byte offset in line
- • {offset_encoding} (string) utf-8|utf-16|utf-32 defaults to
+ • {buf} (`integer`) buffer number (0 for current)
+ • {row} (`integer`) 0-indexed line
+ • {col} (`integer`) 0-indexed byte offset in line
+ • {offset_encoding} (`string`) utf-8|utf-16|utf-32 defaults to
`offset_encoding` of first client of `buf`
Return: ~
- (integer) `offset_encoding` index of the character in line {row}
+ (`integer`) `offset_encoding` index of the character in line {row}
column {col} in buffer {buf}
*vim.lsp.util.convert_input_to_markdown_lines()*
@@ -1731,12 +1845,12 @@ convert_input_to_markdown_lines({input}, {contents})
modifications.
Parameters: ~
- • {input} (`MarkedString` | `MarkedString[]` | `MarkupContent`)
- • {contents} (table|nil) List of strings to extend with converted
- lines. Defaults to {}.
+ • {input} (`lsp.MarkedString|lsp.MarkedString[]|lsp.MarkupContent`)
+ • {contents} (`table?`) List of strings to extend with converted lines.
+ Defaults to {}.
Return: ~
- string[] extended with lines of converted markdown.
+ (`string[]`) extended with lines of converted markdown.
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover
@@ -1746,15 +1860,15 @@ convert_signature_help_to_markdown_lines({signature_help}, {ft}, {triggers})
Converts `textDocument/signatureHelp` response to markdown lines.
Parameters: ~
- • {signature_help} (table) Response of `textDocument/SignatureHelp`
- • {ft} (string|nil) filetype that will be use as the `lang`
+ • {signature_help} (`table`) Response of `textDocument/SignatureHelp`
+ • {ft} (`string?`) filetype that will be use as the `lang`
for the label markdown code block
- • {triggers} (table|nil) list of trigger characters from the lsp
+ • {triggers} (`table?`) list of trigger characters from the lsp
server. used to better determine parameter offsets
Return (multiple): ~
- (table|nil) table list of lines of converted markdown.
- (table|nil) table of active hl
+ (`table?`) table list of lines of converted markdown.
+ (`table?`) table of active hl
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp
@@ -1763,10 +1877,10 @@ get_effective_tabstop({bufnr}) *vim.lsp.util.get_effective_tabstop()*
Returns indentation size.
Parameters: ~
- • {bufnr} (integer|nil) Buffer handle, defaults to current
+ • {bufnr} (`integer?`) Buffer handle, defaults to current
Return: ~
- (integer) indentation size
+ (`integer`) indentation size
See also: ~
• 'shiftwidth'
@@ -1776,13 +1890,13 @@ jump_to_location({location}, {offset_encoding}, {reuse_win})
Jumps to a location.
Parameters: ~
- • {location} (table) (`Location`|`LocationLink`)
- • {offset_encoding} (string|nil) utf-8|utf-16|utf-32
- • {reuse_win} (boolean|nil) Jump to existing window if buffer is
+ • {location} (`table`) (`Location`|`LocationLink`)
+ • {offset_encoding} (`string?`) utf-8|utf-16|utf-32
+ • {reuse_win} (`boolean?`) Jump to existing window if buffer is
already open.
Return: ~
- (boolean) `true` if the jump succeeded
+ (`boolean`) `true` if the jump succeeded
*vim.lsp.util.locations_to_items()*
locations_to_items({locations}, {offset_encoding})
@@ -1796,23 +1910,18 @@ locations_to_items({locations}, {offset_encoding})
|setloclist()|.
Parameters: ~
- • {locations} (table) list of `Location`s or `LocationLink`s
- • {offset_encoding} (string) offset_encoding for locations
+ • {locations} (`lsp.Location[]|lsp.LocationLink[]`)
+ • {offset_encoding} (`string`) offset_encoding for locations
utf-8|utf-16|utf-32 default to first client of
buffer
Return: ~
- (table) list of items
-
-lookup_section({settings}, {section}) *vim.lsp.util.lookup_section()*
- Helper function to return nested values in language server settings
-
- Parameters: ~
- • {settings} (table) language server settings
- • {section} string indicating the field of the settings table
-
- Return: ~
- table|string The value of settings accessed via section
+ (`table[]`) A list of objects with the following fields:
+ • {filename} (`string`)
+ • {lnum} (`integer`) 1-indexed line number
+ • {col} (`integer`) 1-indexed column
+ • {text} (`string`)
+ • {user_data} (`lsp.Location|lsp.LocationLink`)
*vim.lsp.util.make_floating_popup_options()*
make_floating_popup_options({width}, {height}, {opts})
@@ -1820,9 +1929,9 @@ make_floating_popup_options({width}, {height}, {opts})
table can be passed to |nvim_open_win()|.
Parameters: ~
- • {width} (integer) window width (in character cells)
- • {height} (integer) window height (in character cells)
- • {opts} (table) optional
+ • {width} (`integer`) window width (in character cells)
+ • {height} (`integer`) window height (in character cells)
+ • {opts} (`table`) optional
• offset_x (integer) offset to add to `col`
• offset_y (integer) offset to add to `row`
• border (string or table) override `border`
@@ -1838,7 +1947,7 @@ make_floating_popup_options({width}, {height}, {opts})
are not enough lines to display the full window height.
Return: ~
- (table) Options
+ (`table`) Options
*vim.lsp.util.make_formatting_params()*
make_formatting_params({options})
@@ -1846,10 +1955,10 @@ make_formatting_params({options})
cursor position.
Parameters: ~
- • {options} (table|nil) with valid `FormattingOptions` entries
+ • {options} (`table?`) with valid `FormattingOptions` entries
Return: ~
- `DocumentFormattingParams` object
+ (`lsp.DocumentFormattingParams`) object
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting
@@ -1860,18 +1969,18 @@ make_given_range_params({start_pos}, {end_pos}, {bufnr}, {offset_encoding})
similar to |vim.lsp.util.make_range_params()|.
Parameters: ~
- • {start_pos} integer[]|nil {row,col} mark-indexed position.
+ • {start_pos} (`integer[]?`) {row,col} mark-indexed position.
Defaults to the start of the last visual selection.
- • {end_pos} integer[]|nil {row,col} mark-indexed position.
+ • {end_pos} (`integer[]?`) {row,col} mark-indexed position.
Defaults to the end of the last visual selection.
- • {bufnr} (integer|nil) buffer handle or 0 for current,
+ • {bufnr} (`integer?`) buffer handle or 0 for current,
defaults to current
- • {offset_encoding} "utf-8"|"utf-16"|"utf-32"|nil defaults to
+ • {offset_encoding} (`"utf-8"|"utf-16"|"utf-32"?`) defaults to
`offset_encoding` of first client of `bufnr`
Return: ~
- (table) { textDocument = { uri = `current_file_uri` }, range = { start
- = `start_position`, end = `end_position` } }
+ (`table`) { textDocument = { uri = `current_file_uri` }, range = {
+ start = `start_position`, end = `end_position` } }
*vim.lsp.util.make_position_params()*
make_position_params({window}, {offset_encoding})
@@ -1879,14 +1988,14 @@ make_position_params({window}, {offset_encoding})
cursor position.
Parameters: ~
- • {window} (integer|nil) window handle or 0 for current,
+ • {window} (`integer?`) window handle or 0 for current,
defaults to current
- • {offset_encoding} (string|nil) utf-8|utf-16|utf-32|nil defaults to
+ • {offset_encoding} (`string?`) utf-8|utf-16|utf-32|nil defaults to
`offset_encoding` of first client of buffer of
`window`
Return: ~
- (table) `TextDocumentPositionParams` object
+ (`table`) `TextDocumentPositionParams` object
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentPositionParams
@@ -1899,25 +2008,25 @@ make_range_params({window}, {offset_encoding})
`textDocument/rangeFormatting`.
Parameters: ~
- • {window} (integer|nil) window handle or 0 for current,
+ • {window} (`integer?`) window handle or 0 for current,
defaults to current
- • {offset_encoding} "utf-8"|"utf-16"|"utf-32"|nil defaults to
+ • {offset_encoding} (`"utf-8"|"utf-16"|"utf-32"?`) defaults to
`offset_encoding` of first client of buffer of
`window`
Return: ~
- (table) { textDocument = { uri = `current_file_uri` }, range = { start
- = `current_position`, end = `current_position` } }
+ (`table`) { textDocument = { uri = `current_file_uri` }, range = {
+ start = `current_position`, end = `current_position` } }
*vim.lsp.util.make_text_document_params()*
make_text_document_params({bufnr})
Creates a `TextDocumentIdentifier` object for the current buffer.
Parameters: ~
- • {bufnr} (integer|nil) Buffer handle, defaults to current
+ • {bufnr} (`integer?`) Buffer handle, defaults to current
Return: ~
- (table) `TextDocumentIdentifier`
+ (`table`) `TextDocumentIdentifier`
See also: ~
• https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentIdentifier
@@ -1927,38 +2036,41 @@ make_workspace_params({added}, {removed})
Create the workspace params
Parameters: ~
- • {added} (table)
- • {removed} (table)
+ • {added} (`table`)
+ • {removed} (`table`)
*vim.lsp.util.open_floating_preview()*
open_floating_preview({contents}, {syntax}, {opts})
Shows contents in a floating window.
Parameters: ~
- • {contents} (table) of lines to show in window
- • {syntax} (string) of syntax to set for opened buffer
- • {opts} (table) with optional fields (additional keys are filtered
- with |vim.lsp.util.make_floating_popup_options()| before
- they are passed on to |nvim_open_win()|)
- • height: (integer) height of floating window
- • width: (integer) width of floating window
- • wrap: (boolean, default true) wrap long lines
- • wrap_at: (integer) character to wrap at for computing
- height when wrap is enabled
- • max_width: (integer) maximal width of floating window
- • max_height: (integer) maximal height of floating window
- • focus_id: (string) if a popup with this id is opened,
- then focus it
- • close_events: (table) list of events that closes the
+ • {contents} (`table`) of lines to show in window
+ • {syntax} (`string`) of syntax to set for opened buffer
+ • {opts} (`table?`) with optional fields (additional keys are
+ filtered with |vim.lsp.util.make_floating_popup_options()|
+ before they are passed on to |nvim_open_win()|)
+ • {height}? (`integer`) Height of floating window
+ • {width}? (`integer`) Width of floating window
+ • {wrap}? (`boolean`, default: `true`) Wrap long lines
+ • {wrap_at}? (`integer`) Character to wrap at for
+ computing height when wrap is enabled
+ • {max_width}? (`integer`) Maximal width of floating
+ window
+ • {max_height}? (`integer`) Maximal height of floating
+ window
+ • {focus_id}? (`string`) If a popup with this id is
+ opened, then focus it
+ • {close_events}? (`table`) List of events that closes the
floating window
- • focusable: (boolean, default true) Make float focusable
- • focus: (boolean, default true) If `true`, and if
+ • {focusable}? (`boolean`, default: `true`) Make float
+ focusable.
+ • {focus}? (`boolean`, default: `true`) If `true`, and if
{focusable} is also `true`, focus an existing floating
window with the same {focus_id}
Return (multiple): ~
- (integer) bufnr of newly created float window
- (integer) winid of newly created float window preview window
+ (`integer`) bufnr of newly created float window
+ (`integer`) winid of newly created float window preview window
preview_location({location}, {opts}) *vim.lsp.util.preview_location()*
Previews a location in a floating window
@@ -1969,33 +2081,46 @@ preview_location({location}, {opts}) *vim.lsp.util.preview_location()*
definition)
Parameters: ~
- • {location} (table) a single `Location` or `LocationLink`
+ • {location} (`table`) a single `Location` or `LocationLink`
+ • {opts} (`table`)
Return (multiple): ~
- (integer|nil) buffer id of float window
- (integer|nil) window id of float window
+ (`integer?`) buffer id of float window
+ (`integer?`) window id of float window
rename({old_fname}, {new_fname}, {opts}) *vim.lsp.util.rename()*
Rename old_fname to new_fname
+ Existing buffers are renamed as well, while maintaining their bufnr.
+
+ It deletes existing buffers that conflict with the renamed file name only
+ when
+ • `opts` requests overwriting; or
+ • the conflicting buffers are not loaded, so that deleting thme does not
+ result in data loss.
+
Parameters: ~
- • {opts} (table)
+ • {old_fname} (`string`)
+ • {new_fname} (`string`)
+ • {opts} (`table?`) Options:
+ • {overwrite}? (`boolean`)
+ • {ignoreIfExists}? (`boolean`)
*vim.lsp.util.show_document()*
show_document({location}, {offset_encoding}, {opts})
Shows document and optionally jumps to the location.
Parameters: ~
- • {location} (table) (`Location`|`LocationLink`)
- • {offset_encoding} (string|nil) utf-8|utf-16|utf-32
- • {opts} (table|nil) options
+ • {location} (`table`) (`Location`|`LocationLink`)
+ • {offset_encoding} (`string?`) utf-8|utf-16|utf-32
+ • {opts} (`table?`) options
• reuse_win (boolean) Jump to existing window if
buffer is already open.
• focus (boolean) Whether to focus/jump to location
if possible. Defaults to true.
Return: ~
- (boolean) `true` if succeeded
+ (`boolean`) `true` if succeeded
*vim.lsp.util.stylize_markdown()*
stylize_markdown({bufnr}, {contents}, {opts})
@@ -2010,8 +2135,9 @@ stylize_markdown({bufnr}, {contents}, {opts})
`open_floating_preview` instead
Parameters: ~
- • {contents} (table) of lines to show in window
- • {opts} (table) with optional fields
+ • {bufnr} (`integer`)
+ • {contents} (`table`) of lines to show in window
+ • {opts} (`table`) with optional fields
• height of floating window
• width of floating window
• wrap_at character to wrap at for computing height
@@ -2020,13 +2146,14 @@ stylize_markdown({bufnr}, {contents}, {opts})
• separator insert separator after code block
Return: ~
- (table) stripped content
+ (`table`) stripped content
symbols_to_items({symbols}, {bufnr}) *vim.lsp.util.symbols_to_items()*
Converts symbols to quickfix list items.
Parameters: ~
- • {symbols} (table) DocumentSymbol[] or SymbolInformation[]
+ • {symbols} (`table`) DocumentSymbol[] or SymbolInformation[]
+ • {bufnr} (`integer`)
==============================================================================
@@ -2036,127 +2163,167 @@ get_filename() *vim.lsp.log.get_filename()*
Returns the log filename.
Return: ~
- (string) log filename
+ (`string`) log filename
get_level() *vim.lsp.log.get_level()*
Gets the current log level.
Return: ~
- (integer) current log level
+ (`integer`) current log level
set_format_func({handle}) *vim.lsp.log.set_format_func()*
Sets formatting function used to format logs
Parameters: ~
- • {handle} (function) function to apply to logging arguments, pass
+ • {handle} (`function`) function to apply to logging arguments, pass
vim.inspect for multi-line formatting
set_level({level}) *vim.lsp.log.set_level()*
Sets the current log level.
Parameters: ~
- • {level} (string|integer) One of `vim.lsp.log.levels`
+ • {level} (`string|integer`) One of `vim.lsp.log.levels`
should_log({level}) *vim.lsp.log.should_log()*
Checks whether the level is sufficient for logging.
Parameters: ~
- • {level} (integer) log level
+ • {level} (`integer`) log level
Return: ~
- (bool) true if would log, false if not
+ (`bool`) true if would log, false if not
==============================================================================
Lua module: vim.lsp.rpc *lsp-rpc*
+*vim.lsp.rpc.PublicClient*
+
+ Fields: ~
+ • {request} (`fun(method: string, params: table?, callback: fun(err: lsp.ResponseError?, result: any), notify_reply_callback: fun(integer)?):boolean,integer?`)
+ see |vim.lsp.rpc.request()|
+ • {notify} (`fun(method: string, params: any):boolean`) see
+ |vim.lsp.rpc.notify()|
+ • {is_closing} (`fun(): boolean`)
+ • {terminate} (`fun()`)
+
+
connect({host}, {port}) *vim.lsp.rpc.connect()*
Create a LSP RPC client factory that connects via TCP to the given host
- and port
+ and port.
+
+ Return a function that can be passed to the `cmd` field for
+ |vim.lsp.start_client()| or |vim.lsp.start()|.
+
+ Parameters: ~
+ • {host} (`string`) host to connect to
+ • {port} (`integer`) port to connect to
+
+ Return: ~
+ (`fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`)
+
+ *vim.lsp.rpc.domain_socket_connect()*
+domain_socket_connect({pipe_path})
+ Create a LSP RPC client factory that connects via named pipes (Windows) or
+ unix domain sockets (Unix) to the given pipe_path (file path on Unix and
+ name on Windows).
+
+ Return a function that can be passed to the `cmd` field for
+ |vim.lsp.start_client()| or |vim.lsp.start()|.
Parameters: ~
- • {host} (string)
- • {port} (integer)
+ • {pipe_path} (`string`) file path of the domain socket (Unix) or name
+ of the named pipe (Windows) to connect to
Return: ~
- (function)
+ (`fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient`)
format_rpc_error({err}) *vim.lsp.rpc.format_rpc_error()*
Constructs an error message from an LSP error object.
Parameters: ~
- • {err} (table) The error object
+ • {err} (`table`) The error object
Return: ~
- (string) The formatted error message
+ (`string`) error_message The formatted error message
notify({method}, {params}) *vim.lsp.rpc.notify()*
Sends a notification to the LSP server.
Parameters: ~
- • {method} (string) The invoked LSP method
- • {params} (table|nil) Parameters for the invoked LSP method
+ • {method} (`string`) The invoked LSP method
+ • {params} (`table?`) Parameters for the invoked LSP method
Return: ~
- (boolean) `true` if notification could be sent, `false` if not
+ (`boolean`) `true` if notification could be sent, `false` if not
*vim.lsp.rpc.request()*
request({method}, {params}, {callback}, {notify_reply_callback})
Sends a request to the LSP server and runs {callback} upon response.
Parameters: ~
- • {method} (string) The invoked LSP method
- • {params} (table|nil) Parameters for the invoked LSP
+ • {method} (`string`) The invoked LSP method
+ • {params} (`table?`) Parameters for the invoked LSP
method
- • {callback} fun(err: lsp.ResponseError | nil, result:
- any) Callback to invoke
- • {notify_reply_callback} (function|nil) Callback to invoke as soon as
- a request is no longer pending
+ • {callback} (`fun(err: lsp.ResponseError?, result: any)`)
+ Callback to invoke
+ • {notify_reply_callback} (`fun(message_id: integer)?`) Callback to
+ invoke as soon as a request is no longer
+ pending
- Return: ~
- (boolean) success, integer|nil request_id true, message_id if request
- could be sent, `false` if not
+ Return (multiple): ~
+ (`boolean`) success `true` if request could be sent, `false` if not
+ (`integer?`) message_id if request could be sent, `nil` if not
*vim.lsp.rpc.rpc_response_error()*
rpc_response_error({code}, {message}, {data})
- Creates an RPC response object/table.
+ Creates an RPC response table `error` to be sent to the LSP response.
Parameters: ~
- • {code} (integer) RPC error code defined in
+ • {code} (`integer`) RPC error code defined, see
`vim.lsp.protocol.ErrorCodes`
- • {message} (string|nil) arbitrary message to send to server
- • {data} any|nil arbitrary data to send to server
+ • {message} (`string?`) arbitrary message to send to server
+ • {data} (`any?`) arbitrary data to send to server
- *vim.lsp.rpc.start()*
-start({cmd}, {cmd_args}, {dispatchers}, {extra_spawn_params})
+ Return: ~
+ (`lsp.ResponseError`)
+
+ See also: ~
+ • lsp.ErrorCodes See `vim.lsp.protocol.ErrorCodes`
+
+start({cmd}, {dispatchers}, {extra_spawn_params}) *vim.lsp.rpc.start()*
Starts an LSP server process and create an LSP RPC client object to
interact with it. Communication with the spawned process happens via
stdio. For communication via TCP, spawn a process manually and use
|vim.lsp.rpc.connect()|
Parameters: ~
- • {cmd} (string) Command to start the LSP server.
- • {cmd_args} (table) List of additional string arguments to
- pass to {cmd}.
- • {dispatchers} (table|nil) Dispatchers for LSP message types.
- Valid dispatcher names are:
- • `"notification"`
- • `"server_request"`
- • `"on_error"`
- • `"on_exit"`
- • {extra_spawn_params} (table|nil) Additional context for the LSP
- server process. May contain:
- • {cwd} (string) Working directory for the LSP
- server process
- • {env} (table) Additional environment variables
- for LSP server process
+ • {cmd} (`string[]`) Command to start the LSP server.
+ • {dispatchers} (`table?`) Dispatchers for LSP message types.
+ • {notification}
+ (`fun(method: string, params: table)`)
+ • {server_request}
+ (`fun(method: string, params: table): any?, lsp.ResponseError?`)
+ • {on_exit}
+ (`fun(code: integer, signal: integer)`)
+ • {on_error} (`fun(code: integer, err: any)`)
+ • {extra_spawn_params} (`table?`) Additional context for the LSP server
+ process.
+ • {cwd}? (`string`) Working directory for the
+ LSP server process
+ • {detached}? (`boolean`) Detach the LSP server
+ process from the current process
+ • {env}? (`table<string,string>`) Additional
+ environment variables for LSP server process.
+ See |vim.system()|
Return: ~
- (table|nil) Client RPC object, with these methods:
+ (`vim.lsp.rpc.PublicClient?`) Client RPC object, with these methods:
• `notify()` |vim.lsp.rpc.notify()|
• `request()` |vim.lsp.rpc.request()|
• `is_closing()` returns a boolean indicating if the RPC is closing.
- • `terminate()` terminates the RPC client.
+ • `terminate()` terminates the RPC client. See
+ |vim.lsp.rpc.PublicClient|.
==============================================================================
@@ -2168,23 +2335,24 @@ make_client_capabilities()
capabilities.
Return: ~
- lsp.ClientCapabilities
+ (`lsp.ClientCapabilities`)
Methods *vim.lsp.protocol.Methods*
LSP method names.
See also: ~
- • https://microsoft.github.io/language-server-protocol/specifications/specification-current/#metaModel
+ • https://microsoft.github.io/language-server-protocol/specification/#metaModel
*vim.lsp.protocol.resolve_capabilities()*
resolve_capabilities({server_capabilities})
Creates a normalized object describing LSP server capabilities.
Parameters: ~
- • {server_capabilities} (table) Table of capabilities supported by the
- server
+ • {server_capabilities} (`table`) Table of capabilities supported by
+ the server
Return: ~
- (table|nil) Normalized table of capabilities
+ (`lsp.ServerCapabilities?`) Normalized table of capabilities
+
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/doc/lua-guide.txt b/runtime/doc/lua-guide.txt
index c15b1b0495..e8757a1859 100644
--- a/runtime/doc/lua-guide.txt
+++ b/runtime/doc/lua-guide.txt
@@ -157,7 +157,7 @@ its functions if this succeeds and prints an error message otherwise:
end
<
In contrast to |:source|, |require()| not only searches through all `lua/` directories
-under |'runtimepath'|, it also cache the module on first use. Calling
+under |'runtimepath'|, it also caches the module on first use. Calling
`require()` a second time will therefore _not_ execute the script again and
instead return the cached file. To rerun the file, you need to remove it from
the cache manually first:
diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt
index a35d70cae8..367b5c36d2 100644
--- a/runtime/doc/lua.txt
+++ b/runtime/doc/lua.txt
@@ -121,16 +121,14 @@ languages like Python and C#. Example: >lua
func_with_opts { foo = true, filename = "hello.world" }
<
-There's nothing special going on here except that parentheses are treated as
-whitespace. But visually, this small bit of sugar gets reasonably close to
-a "keyword args" interface. Nvim code tends to prefer this style.
-
-------------------------------------------------------------------------------
-LUA PATTERNS *lua-patterns*
+There's nothing special going on here except that parentheses are implicitly
+added. But visually, this small bit of sugar gets reasonably close to a
+"keyword args" interface.
+ *lua-regex*
Lua intentionally does not support regular expressions, instead it has limited
-"patterns" |lua-pattern| which avoid the performance pitfalls of extended
-regex. Lua scripts can also use Vim regex via |vim.regex()|.
+|lua-patterns| which avoid the performance pitfalls of extended regex. Lua
+scripts can also use Vim regex via |vim.regex()|.
Examples: >lua
@@ -256,6 +254,14 @@ arguments separated by " " (space) instead of "\t" (tab).
< To see the LuaJIT version: >vim
:lua =jit.version
<
+:{range}lua
+ Executes buffer lines in {range} as Lua code. Unlike |:source|, this
+ always treats the lines as Lua code.
+
+ Example: select the following code and type ":lua<Enter>" to execute it: >lua
+ print(string.format(
+ 'unix time: %s', os.time()))
+<
*:lua-heredoc*
:lua << [trim] [{endmarker}]
{script}
@@ -268,10 +274,8 @@ arguments separated by " " (space) instead of "\t" (tab).
function! CurrentLineInfo()
lua << EOF
local linenr = vim.api.nvim_win_get_cursor(0)[1]
- local curline = vim.api.nvim_buf_get_lines(
- 0, linenr - 1, linenr, false)[1]
- print(string.format("Current line [%d] has %d bytes",
- linenr, #curline))
+ local curline = vim.api.nvim_buf_get_lines(0, linenr - 1, linenr, false)[1]
+ print(string.format('Line [%d] has %d bytes', linenr, #curline))
EOF
endfunction
<
@@ -574,41 +578,30 @@ A subset of the `vim.*` API is available in threads. This includes:
like `vim.split`, `vim.tbl_*`, `vim.list_*`, and so on.
- `vim.is_thread()` returns true from a non-main thread.
-------------------------------------------------------------------------------
-VIM.LPEG *lua-lpeg*
-
- *vim.lpeg* *vim.re*
-The Lpeg library for parsing expression grammars is being included as
-`vim.lpeg` (https://www.inf.puc-rio.br/~roberto/lpeg/). In addition, its regex-like
-interface is available as `vim.re` (https://www.inf.puc-rio.br/~roberto/lpeg/re.html).
==============================================================================
VIM.HIGHLIGHT *vim.highlight*
-
Nvim includes a function for highlighting a selection on yank.
To enable it, add the following to your `init.vim`: >vim
au TextYankPost * silent! lua vim.highlight.on_yank()
-
<
-You can customize the highlight group and the duration of the highlight
-via: >vim
+You can customize the highlight group and the duration of the highlight via: >vim
au TextYankPost * silent! lua vim.highlight.on_yank {higroup="IncSearch", timeout=150}
-
<
If you want to exclude visual selections from highlighting on yank, use: >vim
au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false}
-
<
+
vim.highlight.on_yank({opts}) *vim.highlight.on_yank()*
Highlight the yanked text
Parameters: ~
- • {opts} (table|nil) Optional parameters
+ • {opts} (`table?`) Optional parameters
• higroup highlight group for yanked region (default
"IncSearch")
• timeout time in ms before highlight is cleared (default 150)
@@ -622,7 +615,7 @@ vim.highlight.on_yank({opts}) *vim.highlight.on_yank()*
vim.highlight.priorities *vim.highlight.priorities*
Table with default priorities used for highlighting:
• `syntax`: `50`, used for standard syntax highlighting
- • `treesitter`: `100`, used for tree-sitter-based highlighting
+ • `treesitter`: `100`, used for treesitter-based highlighting
• `semantic_tokens`: `125`, used for LSP semantic token highlighting
• `diagnostics`: `150`, used for code analysis such as diagnostics
• `user`: `200`, used for user-triggered highlights such as LSP document
@@ -633,14 +626,14 @@ vim.highlight.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts})
Apply highlight group to range of text.
Parameters: ~
- • {bufnr} (integer) Buffer number to apply highlighting to
- • {ns} (integer) Namespace to add highlight to
- • {higroup} (string) Highlight group to use for highlighting
- • {start} integer[]|string Start of region as a (line, column) tuple
- or string accepted by |getpos()|
- • {finish} integer[]|string End of region as a (line, column) tuple or
- string accepted by |getpos()|
- • {opts} (table|nil) Optional parameters
+ • {bufnr} (`integer`) Buffer number to apply highlighting to
+ • {ns} (`integer`) Namespace to add highlight to
+ • {higroup} (`string`) Highlight group to use for highlighting
+ • {start} (`integer[]|string`) Start of region as a (line, column)
+ tuple or string accepted by |getpos()|
+ • {finish} (`integer[]|string`) End of region as a (line, column)
+ tuple or string accepted by |getpos()|
+ • {opts} (`table?`) Optional parameters
• regtype type of range (see |setreg()|, default charwise)
• inclusive boolean indicating whether the range is
end-inclusive (default false)
@@ -649,47 +642,6 @@ vim.highlight.range({bufnr}, {ns}, {higroup}, {start}, {finish}, {opts})
==============================================================================
-VIM.REGEX *vim.regex*
-
-
-Vim regexes can be used directly from Lua. Currently they only allow
-matching within a single line.
-
-
-vim.regex({re}) *vim.regex()*
- Parse the Vim regex {re} and return a regex object. Regexes are "magic"
- and case-sensitive by default, regardless of 'magic' and 'ignorecase'.
- They can be controlled with flags, see |/magic| and |/ignorecase|.
-
- Parameters: ~
- • {re} (string)
-
- Return: ~
- vim.regex
-
- *regex:match_line()*
-vim.regex:match_line({bufnr}, {line_idx}, {start}, {end_})
- Match line {line_idx} (zero-based) in buffer {bufnr}. If {start} and {end}
- are supplied, match only this byte index range. Otherwise see
- |regex:match_str()|. If {start} is used, then the returned byte indices
- will be relative {start}.
-
- Parameters: ~
- • {bufnr} (integer)
- • {line_idx} (integer)
- • {start} (integer|nil)
- • {end_} (integer|nil)
-
-vim.regex:match_str({str}) *regex:match_str()*
- Match the string against the regex. If the string should match the regex
- precisely, surround the regex with `^` and `$` . If there was a match, the byte indices for the beginning and end of the
- match are returned. When there is no match, `nil` is returned. Because any integer is "truthy", `regex:match_str()` can be directly used as a condition in an if-statement.
-
- Parameters: ~
- • {str} (string)
-
-
-==============================================================================
VIM.DIFF *vim.diff*
vim.diff({a}, {b}, {opts}) *vim.diff()*
@@ -712,22 +664,20 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
<
Parameters: ~
- • {a} (string) First string to compare
- • {b} (string) Second string to compare
- • {opts} table<string,any> Optional parameters:
- • `on_hunk` (callback): Invoked for each hunk in the diff. Return a
- negative number to cancel the callback for any remaining
- hunks. Args:
+ • {a} (`string`) First string to compare
+ • {b} (`string`) Second string to compare
+ • {opts} (`table<string,any>`) Optional parameters:
+ • `on_hunk` (callback): Invoked for each hunk in the diff.
+ Return a negative number to cancel the callback for any
+ remaining hunks. Args:
• `start_a` (integer): Start line of hunk in {a}.
• `count_a` (integer): Hunk size in {a}.
• `start_b` (integer): Start line of hunk in {b}.
• `count_b` (integer): Hunk size in {b}.
-
• `result_type` (string): Form of the returned diff:
• "unified": (default) String in unified format.
• "indices": Array of hunk locations. Note: This option is
ignored if `on_hunk` is used.
-
• `linematch` (boolean|integer): Run linematch on the
resulting hunks from xdiff. When integer, only hunks upto
this size in lines are run through linematch. Requires
@@ -738,7 +688,6 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
possible diff
• "patience" patience diff algorithm
• "histogram" histogram diff algorithm
-
• `ctxlen` (integer): Context length
• `interhunkctxlen` (integer): Inter hunk context length
• `ignore_whitespace` (boolean): Ignore whitespace
@@ -753,37 +702,45 @@ vim.diff({a}, {b}, {opts}) *vim.diff()*
the internal diff library.
Return: ~
- string|table|nil See {opts.result_type}. `nil` if {opts.on_hunk} is
+ (`string|table?`) See {opts.result_type}. `nil` if {opts.on_hunk} is
given.
==============================================================================
VIM.MPACK *vim.mpack*
-
This module provides encoding and decoding of Lua objects to and from
msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
+
vim.mpack.decode({str}) *vim.mpack.decode()*
Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object.
Parameters: ~
- • {str} (string)
+ • {str} (`string`)
+
+ Return: ~
+ (`any`)
vim.mpack.encode({obj}) *vim.mpack.encode()*
Encodes (or "packs") Lua object {obj} as msgpack in a Lua string.
+ Parameters: ~
+ • {obj} (`any`)
+
+ Return: ~
+ (`string`)
+
==============================================================================
VIM.JSON *vim.json*
-
This module provides encoding and decoding of Lua objects to and from
JSON-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
+
vim.json.decode({str}, {opts}) *vim.json.decode()*
Decodes (or "unpacks") the JSON-encoded {str} to a Lua object.
-
• Decodes JSON "null" as |vim.NIL| (controllable by {opts}, see below).
• Decodes empty object as |vim.empty_dict()|.
• Decodes empty array as `{}` (empty Lua table).
@@ -794,8 +751,8 @@ vim.json.decode({str}, {opts}) *vim.json.decode()*
<
Parameters: ~
- • {str} (string) Stringified JSON data.
- • {opts} table<string,any>|nil Options table with keys:
+ • {str} (`string`) Stringified JSON data.
+ • {opts} (`table<string,any>?`) Options table with keys:
• luanil: (table) Table with keys:
• object: (boolean) When true, converts `null` in JSON
objects to Lua `nil` instead of |vim.NIL|.
@@ -803,16 +760,16 @@ vim.json.decode({str}, {opts}) *vim.json.decode()*
to Lua `nil` instead of |vim.NIL|.
Return: ~
- any
+ (`any`)
vim.json.encode({obj}) *vim.json.encode()*
Encodes (or "packs") Lua object {obj} as JSON in a Lua string.
Parameters: ~
- • {obj} any
+ • {obj} (`any`)
Return: ~
- (string)
+ (`string`)
==============================================================================
@@ -822,19 +779,19 @@ vim.base64.decode({str}) *vim.base64.decode()*
Decode a Base64 encoded string.
Parameters: ~
- • {str} (string) Base64 encoded string
+ • {str} (`string`) Base64 encoded string
Return: ~
- (string) Decoded string
+ (`string`) Decoded string
vim.base64.encode({str}) *vim.base64.encode()*
Encode {str} using Base64.
Parameters: ~
- • {str} (string) String to encode
+ • {str} (`string`) String to encode
Return: ~
- (string) Encoded string
+ (`string`) Encoded string
==============================================================================
@@ -857,10 +814,11 @@ vim.spell.check({str}) *vim.spell.check()*
<
Parameters: ~
- • {str} (string)
+ • {str} (`string`)
Return: ~
- `{[1]: string, [2]: string, [3]: string}[]` List of tuples with three items:
+ (`{[1]: string, [2]: string, [3]: string}[]`) List of tuples with
+ three items:
• The badly spelled word.
• The type of the spelling error: "bad" spelling mistake "rare" rare
word "local" word only valid in another region "caps" word should
@@ -872,24 +830,24 @@ vim.spell.check({str}) *vim.spell.check()*
VIM *vim.builtin*
-vim.api.{func}({...}) *vim.api*
+vim.api.{func}({...}) *vim.api*
Invokes Nvim |API| function {func} with arguments {...}.
Example: call the "nvim_get_current_line()" API function: >lua
print(tostring(vim.api.nvim_get_current_line()))
-vim.NIL *vim.NIL*
+vim.NIL *vim.NIL*
Special value representing NIL in |RPC| and |v:null| in Vimscript
conversion, and similar cases. Lua `nil` cannot be used as part of a Lua
table representing a Dictionary or Array, because it is treated as
missing: `{"foo", nil}` is the same as `{"foo"}`.
-vim.type_idx *vim.type_idx*
+vim.type_idx *vim.type_idx*
Type index for use in |lua-special-tbl|. Specifying one of the values from
|vim.types| allows typing the empty table (it is unclear whether empty Lua
table represents empty list or empty array) and forcing integral numbers
to be |Float|. See |lua-special-tbl| for more details.
-vim.val_idx *vim.val_idx*
+vim.val_idx *vim.val_idx*
Value index for tables representing |Float|s. A table representing
floating-point value 1.0 looks like this: >lua
{
@@ -898,7 +856,7 @@ vim.val_idx *vim.val_id
}
< See also |vim.type_idx| and |lua-special-tbl|.
-vim.types *vim.types*
+vim.types *vim.types*
Table with possible values for |vim.type_idx|. Contains two sets of
key-value pairs: first maps possible values for |vim.type_idx| to
human-readable strings, second maps human-readable type names to values
@@ -927,6 +885,8 @@ Log levels are one of the values defined in `vim.log.levels`:
vim.log.levels.WARN
vim.log.levels.OFF
+
+
vim.empty_dict() *vim.empty_dict()*
Creates a special empty table (marked with a metatable), which Nvim
converts to an empty dictionary when translating Lua values to Vimscript
@@ -936,6 +896,9 @@ vim.empty_dict() *vim.empty_dict()*
Note: If numeric keys are present in the table, Nvim ignores the metatable
marker and converts the dict to a list/array anyway.
+ Return: ~
+ (`table`)
+
vim.iconv({str}, {from}, {to}, {opts}) *vim.iconv()*
The result is a String, which is the text {str} converted from encoding
{from} to encoding {to}. When the conversion fails `nil` is returned. When
@@ -944,13 +907,13 @@ vim.iconv({str}, {from}, {to}, {opts}) *vim.iconv()*
":Man 3 iconv".
Parameters: ~
- • {str} (string) Text to convert
- • {from} (number) Encoding of {str}
- • {to} (number) Target encoding
- • {opts} table<string,any>|nil
+ • {str} (`string`) Text to convert
+ • {from} (`number`) Encoding of {str}
+ • {to} (`number`) Target encoding
+ • {opts} (`table<string,any>?`)
Return: ~
- (string|nil) Converted string if conversion succeeds, `nil` otherwise.
+ (`string?`) Converted string if conversion succeeds, `nil` otherwise.
vim.in_fast_event() *vim.in_fast_event()*
Returns true if the code is executing as part of a "fast" event handler,
@@ -959,19 +922,18 @@ vim.in_fast_event() *vim.in_fast_event()*
When this is `false` most API functions are callable (but may be subject
to other restrictions such as |textlock|).
-vim.rpcnotify({channel}, {method}, {args}, {...}) *vim.rpcnotify()*
+vim.rpcnotify({channel}, {method}, {...}) *vim.rpcnotify()*
Sends {event} to {channel} via |RPC| and returns immediately. If {channel}
is 0, the event is broadcast to all channels.
This function also works in a fast callback |lua-loop-callbacks|.
Parameters: ~
- • {channel} (integer)
- • {method} (string)
- • {args} any[]|nil
- • {...} any|nil
+ • {channel} (`integer`)
+ • {method} (`string`)
+ • {...} (`any?`)
-vim.rpcrequest({channel}, {method}, {args}, {...}) *vim.rpcrequest()*
+vim.rpcrequest({channel}, {method}, {...}) *vim.rpcrequest()*
Sends a request to {channel} to invoke {method} via |RPC| and blocks until
a response is received.
@@ -979,17 +941,16 @@ vim.rpcrequest({channel}, {method}, {args}, {...}) *vim.rpcrequest()*
special value
Parameters: ~
- • {channel} (integer)
- • {method} (string)
- • {args} any[]|nil
- • {...} any|nil
+ • {channel} (`integer`)
+ • {method} (`string`)
+ • {...} (`any?`)
vim.schedule({fn}) *vim.schedule()*
Schedules {fn} to be invoked soon by the main event-loop. Useful to avoid
|textlock| or other temporary restrictions.
Parameters: ~
- • {fn} (function)
+ • {fn} (`function`)
vim.str_byteindex({str}, {index}, {use_utf16}) *vim.str_byteindex()*
Convert UTF-32 or UTF-16 {index} to byte index. If {use_utf16} is not
@@ -1000,9 +961,9 @@ vim.str_byteindex({str}, {index}, {use_utf16}) *vim.str_byteindex()*
sequence.
Parameters: ~
- • {str} (string)
- • {index} (number)
- • {use_utf16} any|nil
+ • {str} (`string`)
+ • {index} (`number`)
+ • {use_utf16} (`any?`)
vim.str_utf_end({str}, {index}) *vim.str_utf_end()*
Gets the distance (in bytes) from the last byte of the codepoint
@@ -1019,11 +980,11 @@ vim.str_utf_end({str}, {index}) *vim.str_utf_end()*
<
Parameters: ~
- • {str} (string)
- • {index} (number)
+ • {str} (`string`)
+ • {index} (`number`)
Return: ~
- (number)
+ (`number`)
vim.str_utf_pos({str}) *vim.str_utf_pos()*
Gets a list of the starting byte positions of each UTF-8 codepoint in the
@@ -1032,10 +993,10 @@ vim.str_utf_pos({str}) *vim.str_utf_pos()*
Embedded NUL bytes are treated as terminating the string.
Parameters: ~
- • {str} (string)
+ • {str} (`string`)
Return: ~
- (table)
+ (`table`)
vim.str_utf_start({str}, {index}) *vim.str_utf_start()*
Gets the distance (in bytes) from the starting byte of the codepoint
@@ -1055,11 +1016,11 @@ vim.str_utf_start({str}, {index}) *vim.str_utf_start()*
<
Parameters: ~
- • {str} (string)
- • {index} (number)
+ • {str} (`string`)
+ • {index} (`number`)
Return: ~
- (number)
+ (`number`)
vim.str_utfindex({str}, {index}) *vim.str_utfindex()*
Convert byte index to UTF-32 and UTF-16 indices. If {index} is not
@@ -1071,23 +1032,23 @@ vim.str_utfindex({str}, {index}) *vim.str_utfindex()*
that sequence.
Parameters: ~
- • {str} (string)
- • {index} (number|nil)
+ • {str} (`string`)
+ • {index} (`number?`)
Return (multiple): ~
- (integer) UTF-32 index
- (integer) UTF-16 index
+ (`integer`) UTF-32 index
+ (`integer`) UTF-16 index
vim.stricmp({a}, {b}) *vim.stricmp()*
Compares strings case-insensitively.
Parameters: ~
- • {a} (string)
- • {b} (string)
+ • {a} (`string`)
+ • {b} (`string`)
Return: ~
- 0|1|-1 if strings are equal, {a} is greater than {b} or {a} is lesser
- than {b}, respectively.
+ (`0|1|-1`) if strings are equal, {a} is greater than {b} or {a} is
+ lesser than {b}, respectively.
vim.ui_attach({ns}, {options}, {callback}) *vim.ui_attach()*
Attach to ui events, similar to |nvim_ui_attach()| but receive events as
@@ -1125,16 +1086,16 @@ vim.ui_attach({ns}, {options}, {callback}) *vim.ui_attach()*
<
Parameters: ~
- • {ns} (integer)
- • {options} table<string, any>
- • {callback} fun()
+ • {ns} (`integer`)
+ • {options} (`table<string, any>`)
+ • {callback} (`fun()`)
vim.ui_detach({ns}) *vim.ui_detach()*
Detach a callback previously attached with |vim.ui_attach()| for the given
namespace {ns}.
Parameters: ~
- • {ns} (integer)
+ • {ns} (`integer`)
vim.wait({time}, {callback}, {interval}, {fast_only}) *vim.wait()*
Wait for {time} in milliseconds until {callback} returns `true`.
@@ -1169,16 +1130,17 @@ vim.wait({time}, {callback}, {interval}, {fast_only}) *vim.wait()*
<
Parameters: ~
- • {time} (integer) Number of milliseconds to wait
- • {callback} fun():|nil boolean Optional callback. Waits until
+ • {time} (`integer`) Number of milliseconds to wait
+ • {callback} (`fun(): boolean?`) Optional callback. Waits until
{callback} returns true
- • {interval} (integer|nil) (Approximate) number of milliseconds to
- wait between polls
- • {fast_only} (boolean|nil) If true, only |api-fast| events will be
+ • {interval} (`integer?`) (Approximate) number of milliseconds to wait
+ between polls
+ • {fast_only} (`boolean?`) If true, only |api-fast| events will be
processed.
- Return: ~
- boolean, nil|-1|-2
+ Return (multiple): ~
+ (`boolean`)
+ (`-1|-2?`)
• If {callback} returns `true` during the {time}: `true, nil`
• If {callback} never returns `true` during the {time}: `false, -1`
• If {callback} is interrupted during the {time}: `false, -2`
@@ -1188,18 +1150,15 @@ vim.wait({time}, {callback}, {interval}, {fast_only}) *vim.wait()*
==============================================================================
LUA-VIMSCRIPT BRIDGE *lua-vimscript*
-
Nvim Lua provides an interface or "bridge" to Vimscript variables and
functions, and editor commands and options.
Objects passed over this bridge are COPIED (marshalled): there are no
-"references". |lua-guide-variables| For example, using `vim.fn.remove()`
-on a Lua list copies the list object to Vimscript and does NOT modify the
-Lua list: >lua
+"references". |lua-guide-variables| For example, using `vim.fn.remove()` on a
+Lua list copies the list object to Vimscript and does NOT modify the Lua list: >lua
local list = { 1, 2, 3 }
vim.fn.remove(list, 0)
vim.print(list) --> "{ 1, 2, 3 }"
-
<
vim.call({func}, {...}) *vim.call()*
@@ -1280,7 +1239,7 @@ vim.v *vim.v*
|v:| variables.
Invalid or unset key returns `nil`.
-` ` *lua-options*
+ *lua-options*
*lua-vim-options*
*lua-vim-set*
*lua-vim-setlocal*
@@ -1303,9 +1262,10 @@ window-scoped options. Note that this must NOT be confused with
|local-options| and |:setlocal|. There is also |vim.go| that only accesses the
global value of a |global-local| option, see |:setglobal|.
-` ` *vim.opt_local*
- *vim.opt_global*
- *vim.opt*
+ *vim.opt_local*
+ *vim.opt_global*
+ *vim.opt*
+
A special interface |vim.opt| exists for conveniently interacting with list-
and map-style option from Lua: It allows accessing them as Lua tables and
@@ -1366,6 +1326,7 @@ In any of the above examples, to replicate the behavior |:setlocal|, use
`vim.opt_local`. Additionally, to replicate the behavior of |:setglobal|, use
`vim.opt_global`.
+
Option:append({value}) *vim.opt:append()*
Append a value to string-style options. See |:set+=|
@@ -1375,7 +1336,7 @@ Option:append({value}) *vim.opt:append()*
<
Parameters: ~
- • {value} (string) Value to append
+ • {value} (`string`) Value to append
Option:get() *vim.opt:get()*
Returns a Lua-representation of the option. Boolean, number and string
@@ -1421,7 +1382,7 @@ Option:get() *vim.opt:get()*
<
Return: ~
- string|integer|boolean|nil value of option
+ (`string|integer|boolean?`) value of option
Option:prepend({value}) *vim.opt:prepend()*
Prepend a value to string-style options. See |:set^=|
@@ -1432,7 +1393,7 @@ Option:prepend({value}) *vim.opt:prepend()*
<
Parameters: ~
- • {value} (string) Value to prepend
+ • {value} (`string`) Value to prepend
Option:remove({value}) *vim.opt:remove()*
Remove a value from string-style options. See |:set-=|
@@ -1443,14 +1404,15 @@ Option:remove({value}) *vim.opt:remove()*
<
Parameters: ~
- • {value} (string) Value to remove
+ • {value} (`string`) Value to remove
vim.bo *vim.bo*
- Get or set buffer-scoped |options| for the buffer with number {bufnr}.
- Like `:set` and `:setlocal`. If [{bufnr}] is omitted then the current
- buffer is used. Invalid {bufnr} or key is an error.
+ Get or set buffer-scoped |options| for the buffer with number {bufnr}. If
+ {bufnr} is omitted then the current buffer is used. Invalid {bufnr} or key
+ is an error.
- Note: this is equivalent to both `:set` and `:setlocal`.
+ Note: this is equivalent to `:setlocal` for |global-local| options and
+ `:set` otherwise.
Example: >lua
local bufnr = vim.api.nvim_get_current_buf()
@@ -1469,9 +1431,6 @@ vim.env *vim.env*
print(vim.env.TERM)
<
- Parameters: ~
- • {var} (string)
-
vim.go *vim.go*
Get or set global |options|. Like `:setglobal`. Invalid key is an error.
@@ -1499,9 +1458,10 @@ vim.o *vim.o*
vim.wo *vim.wo*
Get or set window-scoped |options| for the window with handle {winid} and
- buffer with number {bufnr}. Like `:setlocal` if {bufnr} is provided, like
- `:set` otherwise. If [{winid}] is omitted then the current window is used.
- Invalid {winid}, {bufnr} or key is an error.
+ buffer with number {bufnr}. Like `:setlocal` if setting a |global-local|
+ option or if {bufnr} is provided, like `:set` otherwise. If {winid} is
+ omitted then the current window is used. Invalid {winid}, {bufnr} or key
+ is an error.
Note: only {bufnr} with value `0` (the current buffer in the window) is
supported.
@@ -1518,7 +1478,7 @@ vim.wo *vim.wo*
==============================================================================
Lua module: vim *lua-vim*
-vim.cmd *vim.cmd()*
+vim.cmd({command}) *vim.cmd()*
Executes Vim script commands.
Note that `vim.cmd` can be indexed with a command name to return a
@@ -1552,12 +1512,12 @@ vim.cmd *vim.cmd()*
<
Parameters: ~
- • {command} string|table Command(s) to execute. If a string, executes
- multiple lines of Vim script at once. In this case, it is
- an alias to |nvim_exec2()|, where `opts.output` is set to
- false. Thus it works identical to |:source|. If a table,
- executes a single command. In this case, it is an alias to
- |nvim_cmd()| where `opts` is empty.
+ • {command} (`string|table`) Command(s) to execute. If a string,
+ executes multiple lines of Vim script at once. In this
+ case, it is an alias to |nvim_exec2()|, where `opts.output`
+ is set to false. Thus it works identical to |:source|. If a
+ table, executes a single command. In this case, it is an
+ alias to |nvim_cmd()| where `opts` is empty.
See also: ~
• |ex-cmd-index|
@@ -1569,33 +1529,34 @@ vim.defer_fn({fn}, {timeout}) *vim.defer_fn()*
|vim.schedule_wrap()|ped automatically, so API functions are safe to call.
Parameters: ~
- • {fn} (function) Callback to call once `timeout` expires
- • {timeout} (integer) Number of milliseconds to wait before calling
+ • {fn} (`function`) Callback to call once `timeout` expires
+ • {timeout} (`integer`) Number of milliseconds to wait before calling
`fn`
Return: ~
- (table) timer luv timer object
+ (`table`) timer luv timer object
*vim.deprecate()*
vim.deprecate({name}, {alternative}, {version}, {plugin}, {backtrace})
Shows a deprecation message to the user.
Parameters: ~
- • {name} string Deprecated feature (function, API, etc.).
- • {alternative} (string|nil) Suggested alternative feature.
- • {version} string Version when the deprecated function will be removed.
- • {plugin} string|nil Name of the plugin that owns the deprecated
+ • {name} (`string`) Deprecated feature (function, API, etc.).
+ • {alternative} (`string?`) Suggested alternative feature.
+ • {version} (`string`) Version when the deprecated function will be
+ removed.
+ • {plugin} (`string?`) Name of the plugin that owns the deprecated
feature. Defaults to "Nvim".
- • {backtrace} boolean|nil Prints backtrace. Defaults to true.
+ • {backtrace} (`boolean?`) Prints backtrace. Defaults to true.
Return: ~
- (string|nil) Deprecated message, or nil if no message was shown.
+ (`string?`) Deprecated message, or nil if no message was shown.
-vim.inspect *vim.inspect()*
+vim.inspect() *vim.inspect()*
Gets a human-readable representation of the given object.
Return: ~
- (string)
+ (`string`)
See also: ~
• |vim.print()|
@@ -1611,20 +1572,23 @@ vim.keycode({str}) *vim.keycode()*
<
Parameters: ~
- • {str} (string) String to be converted.
+ • {str} (`string`) String to be converted.
Return: ~
- (string)
+ (`string`)
See also: ~
• |nvim_replace_termcodes()|
-vim.lua_omnifunc({find_start}, {_}) *vim.lua_omnifunc()*
+vim.lua_omnifunc({find_start}) *vim.lua_omnifunc()*
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.
+ Parameters: ~
+ • {find_start} (`1|0`)
+
vim.notify({msg}, {level}, {opts}) *vim.notify()*
Displays a notification to the user.
@@ -1633,9 +1597,9 @@ vim.notify({msg}, {level}, {opts}) *vim.notify()*
writes to |:messages|.
Parameters: ~
- • {msg} (string) Content of the notification to show to the user.
- • {level} (integer|nil) One of the values from |vim.log.levels|.
- • {opts} (table|nil) Optional parameters. Unused by default.
+ • {msg} (`string`) Content of the notification to show to the user.
+ • {level} (`integer?`) One of the values from |vim.log.levels|.
+ • {opts} (`table?`) Optional parameters. Unused by default.
vim.notify_once({msg}, {level}, {opts}) *vim.notify_once()*
Displays a notification only one time.
@@ -1644,12 +1608,12 @@ vim.notify_once({msg}, {level}, {opts}) *vim.notify_once()*
display a notification.
Parameters: ~
- • {msg} (string) Content of the notification to show to the user.
- • {level} (integer|nil) One of the values from |vim.log.levels|.
- • {opts} (table|nil) Optional parameters. Unused by default.
+ • {msg} (`string`) Content of the notification to show to the user.
+ • {level} (`integer?`) One of the values from |vim.log.levels|.
+ • {opts} (`table?`) Optional parameters. Unused by default.
Return: ~
- (boolean) true if message was displayed, else false
+ (`boolean`) true if message was displayed, else false
vim.on_key({fn}, {ns_id}) *vim.on_key()*
Adds Lua function {fn} with namespace id {ns_id} as a listener to every,
@@ -1664,15 +1628,15 @@ vim.on_key({fn}, {ns_id}) *vim.on_key()*
• {fn} will receive the keys after mappings have been evaluated
Parameters: ~
- • {fn} fun(key: string) Function invoked on every key press.
- |i_CTRL-V| Returning nil removes the callback associated with
- namespace {ns_id}.
- • {ns_id} integer? Namespace ID. If nil or 0, generates and returns a
- new |nvim_create_namespace()| id.
+ • {fn} (`fun(key: string)?`) Function invoked on every key press.
+ |i_CTRL-V| Passing in nil when {ns_id} is specified removes
+ the callback associated with namespace {ns_id}.
+ • {ns_id} (`integer?`) Namespace ID. If nil or 0, generates and returns
+ a new |nvim_create_namespace()| id.
Return: ~
- (integer) Namespace id associated with {fn}. Or count of all callbacks
- if on_key() is called without arguments.
+ (`integer`) Namespace id associated with {fn}. Or count of all
+ callbacks if on_key() is called without arguments.
vim.paste({lines}, {phase}) *vim.paste()*
Paste handler, invoked by |nvim_paste()| when a conforming UI (such as the
@@ -1691,19 +1655,20 @@ vim.paste({lines}, {phase}) *vim.paste()*
<
Parameters: ~
- • {lines} string[] # |readfile()|-style list of lines to paste.
+ • {lines} (`string[]`) |readfile()|-style list of lines to paste.
|channel-lines|
- • {phase} paste_phase -1: "non-streaming" paste: the call contains all
- lines. If paste is "streamed", `phase` indicates the stream state:
+ • {phase} (`-1|1|2|3`) -1: "non-streaming" paste: the call contains all
+ lines. If paste is "streamed", `phase` indicates the stream
+ state:
• 1: starts the paste (exactly once)
• 2: continues the paste (zero or more times)
• 3: ends the paste (exactly once)
Return: ~
- (boolean) result false if client should cancel the paste.
+ (`boolean`) result false if client should cancel the paste.
See also: ~
- • |paste| @alias paste_phase -1 | 1 | 2 | 3
+ • |paste|
vim.print({...}) *vim.print()*
"Pretty prints" the given arguments and returns them unmodified.
@@ -1712,8 +1677,11 @@ vim.print({...}) *vim.print()*
local hl_normal = vim.print(vim.api.nvim_get_hl(0, { name = 'Normal' }))
<
+ Parameters: ~
+ • {...} (`any`)
+
Return: ~
- any given arguments.
+ (`any`) given arguments.
See also: ~
• |vim.inspect()|
@@ -1729,17 +1697,17 @@ vim.region({bufnr}, {pos1}, {pos2}, {regtype}, {inclusive})
returned as |v:maxcol| (big number).
Parameters: ~
- • {bufnr} (integer) Buffer number, or 0 for current buffer
- • {pos1} integer[]|string Start of region as a (line, column)
+ • {bufnr} (`integer`) Buffer number, or 0 for current buffer
+ • {pos1} (`integer[]|string`) Start of region as a (line, column)
tuple or |getpos()|-compatible string
- • {pos2} integer[]|string End of region as a (line, column) tuple
- or |getpos()|-compatible string
- • {regtype} (string) |setreg()|-style selection type
- • {inclusive} (boolean) Controls whether the ending column is inclusive
- (see also 'selection').
+ • {pos2} (`integer[]|string`) End of region as a (line, column)
+ tuple or |getpos()|-compatible string
+ • {regtype} (`string`) |setreg()|-style selection type
+ • {inclusive} (`boolean`) Controls whether the ending column is
+ inclusive (see also 'selection').
Return: ~
- (table) region Dict of the form `{linenr = {startcol,endcol}}`.
+ (`table`) region Dict of the form `{linenr = {startcol,endcol}}`.
`endcol` is exclusive, and whole lines are returned as
`{startcol,endcol} = {0,-1}`.
@@ -1756,10 +1724,10 @@ vim.schedule_wrap({fn}) *vim.schedule_wrap()*
<
Parameters: ~
- • {fn} (function)
+ • {fn} (`function`)
Return: ~
- (function)
+ (`function`)
See also: ~
• |lua-loop-callbacks|
@@ -1789,8 +1757,8 @@ vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
throws an error if {cmd} cannot be run.
Parameters: ~
- • {cmd} (string[]) Command to execute
- • {opts} (SystemOpts|nil) Options:
+ • {cmd} (`string[]`) Command to execute
+ • {opts} (`vim.SystemOpts?`) Options:
• cwd: (string) Set the current working directory for the
sub-process.
• env: table<string,string> Set environment variables for
@@ -1820,12 +1788,13 @@ vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
process will still keep the parent's event loop alive
unless the parent process calls |uv.unref()| on the
child's process handle.
- • {on_exit} (function|nil) Called when subprocess exits. When provided,
- the command runs asynchronously. Receives SystemCompleted
- object, see return of SystemObj:wait().
+ • {on_exit} (`fun(out: vim.SystemCompleted)?`) Called when subprocess
+ exits. When provided, the command runs asynchronously.
+ Receives SystemCompleted object, see return of
+ SystemObj:wait().
Return: ~
- vim.SystemObj Object with the fields:
+ (`vim.SystemObj`) Object with the fields:
• pid (integer) Process ID
• wait (fun(timeout: integer|nil): SystemCompleted) Wait for the
process to complete. Upon timeout the process is sent the KILL
@@ -1836,7 +1805,6 @@ vim.system({cmd}, {opts}, {on_exit}) *vim.system()*
• signal: (integer)
• stdout: (string), nil if stdout argument is passed
• stderr: (string), nil if stderr argument is passed
-
• kill (fun(signal: integer|string))
• write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to
close the stream.
@@ -1852,24 +1820,24 @@ vim.inspect_pos({bufnr}, {row}, {col}, {filter}) *vim.inspect_pos()*
Can also be pretty-printed with `:Inspect!`. *:Inspect!*
Parameters: ~
- • {bufnr} (integer|nil) defaults to the current buffer
- • {row} (integer|nil) row to inspect, 0-based. Defaults to the row
- of the current cursor
- • {col} (integer|nil) col to inspect, 0-based. Defaults to the col
- of the current cursor
- • {filter} (table|nil) a table with key-value pairs to filter the items
- • syntax (boolean): include syntax based highlight groups
- (defaults to true)
- • treesitter (boolean): include treesitter based highlight
- groups (defaults to true)
- • extmarks (boolean|"all"): include extmarks. When `all`,
- then extmarks without a `hl_group` will also be included
- (defaults to true)
- • semantic_tokens (boolean): include semantic tokens
- (defaults to true)
-
- Return: ~
- (table) a table with the following key-value pairs. Items are in
+ • {bufnr} (`integer?`) defaults to the current buffer
+ • {row} (`integer?`) row to inspect, 0-based. Defaults to the row of
+ the current cursor
+ • {col} (`integer?`) col to inspect, 0-based. Defaults to the col of
+ the current cursor
+ • {filter} (`table?`) Table with key-value pairs to filter the items
+ • {syntax} (`boolean`, default: `true`) Include syntax based
+ highlight groups.
+ • {treesitter} (`boolean`, default: `true`) Include
+ treesitter based highlight groups.
+ • {extmarks} (`boolean|"all"`, default: true) Include
+ extmarks. When `all`, then extmarks without a `hl_group`
+ will also be included.
+ • {semantic_tokens} (`boolean`, default: true) Include
+ semantic token highlights.
+
+ Return: ~
+ (`table`) a table with the following key-value pairs. Items are in
"traversal order":
• treesitter: a list of treesitter captures
• syntax: a list of syntax groups
@@ -1885,40 +1853,91 @@ vim.show_pos({bufnr}, {row}, {col}, {filter}) *vim.show_pos()*
Can also be shown with `:Inspect`. *:Inspect*
Parameters: ~
- • {bufnr} (integer|nil) defaults to the current buffer
- • {row} (integer|nil) row to inspect, 0-based. Defaults to the row
- of the current cursor
- • {col} (integer|nil) col to inspect, 0-based. Defaults to the col
- of the current cursor
- • {filter} (table|nil) see |vim.inspect_pos()|
+ • {bufnr} (`integer?`) defaults to the current buffer
+ • {row} (`integer?`) row to inspect, 0-based. Defaults to the row of
+ the current cursor
+ • {col} (`integer?`) col to inspect, 0-based. Defaults to the col of
+ the current cursor
+ • {filter} (`table?`) A table with the following fields:
+ • {syntax} (`boolean`, default: `true`) Include syntax based
+ highlight groups.
+ • {treesitter} (`boolean`, default: `true`) Include
+ treesitter based highlight groups.
+ • {extmarks} (`boolean|"all"`, default: true) Include
+ extmarks. When `all`, then extmarks without a `hl_group`
+ will also be included.
+ • {semantic_tokens} (`boolean`, default: true) Include
+ semantic token highlights.
+
+
+
+
+*vim.Ringbuf*
+
+ Fields: ~
+ • {clear} (`fun()`) Clear all items
+ • {push} (`fun(item: T)`) Adds an item, overriding the oldest item if
+ the buffer is full.
+ • {pop} (`fun(): T?`) Removes and returns the first unread item
+ • {peek} (`fun(): T?`) Returns the first unread item without removing
+ it
+
+
+Ringbuf:clear() *Ringbuf:clear()*
+ Clear all items
+
+Ringbuf:peek() *Ringbuf:peek()*
+ Returns the first unread item without removing it
+
+ Return: ~
+ (`any?`)
+Ringbuf:pop() *Ringbuf:pop()*
+ Removes and returns the first unread item
+
+ Return: ~
+ (`any?`)
+Ringbuf:push({item}) *Ringbuf:push()*
+ Adds an item, overriding the oldest item if the buffer is full.
+ Parameters: ~
+ • {item} (`any`)
vim.deep_equal({a}, {b}) *vim.deep_equal()*
Deep compare values for equality
- Tables are compared recursively unless they both provide the `eq` metamethod. All other types are compared using the equality `==` operator.
+ Tables are compared recursively unless they both provide the `eq`
+ metamethod. All other types are compared using the equality `==` operator.
Parameters: ~
- • {a} any First value
- • {b} any Second value
+ • {a} (`any`) First value
+ • {b} (`any`) Second value
Return: ~
- (boolean) `true` if values are equals, else `false`
+ (`boolean`) `true` if values are equals, else `false`
-vim.deepcopy({orig}) *vim.deepcopy()*
+vim.deepcopy({orig}, {noref}) *vim.deepcopy()*
Returns a deep copy of the given object. Non-table objects are copied as
in a typical Lua assignment, whereas table objects are copied recursively.
Functions are naively copied, so functions in the copied table point to
the same functions as those in the input table. Userdata and threads are
not copied and will throw an error.
+ Note: `noref=true` is much more performant on tables with unique table
+ fields, while `noref=false` is more performant on tables that reuse table
+ fields.
+
Parameters: ~
- • {orig} (table) Table to copy
+ • {orig} (`table`) Table to copy
+ • {noref} (`boolean?`) When `false` (default) a contained table is only
+ copied once and all references point to this single copy.
+ When `true` every occurrence of a table results in a new
+ copy. This also means that a cyclic reference can cause
+ `deepcopy()` to fail.
Return: ~
- (table) Table of copied keys and (nested) values.
+ (`table`) Table of copied keys and (nested) values.
vim.defaulttable({createfn}) *vim.defaulttable()*
Creates a table whose missing keys are provided by {createfn} (like
@@ -1931,21 +1950,21 @@ vim.defaulttable({createfn}) *vim.defaulttable()*
<
Parameters: ~
- • {createfn} function?(key:any):any Provides the value for a missing
+ • {createfn} (`fun(key:any):any?`) Provides the value for a missing
`key`.
Return: ~
- (table) Empty table with `__index` metamethod.
+ (`table`) Empty table with `__index` metamethod.
vim.endswith({s}, {suffix}) *vim.endswith()*
Tests if `s` ends with `suffix`.
Parameters: ~
- • {s} (string) String
- • {suffix} (string) Suffix to match
+ • {s} (`string`) String
+ • {suffix} (`string`) Suffix to match
Return: ~
- (boolean) `true` if `suffix` is a suffix of `s`
+ (`boolean`) `true` if `suffix` is a suffix of `s`
vim.gsplit({s}, {sep}, {opts}) *vim.gsplit()*
Gets an |iterator| that splits a string at each instance of a separator,
@@ -1965,15 +1984,16 @@ vim.gsplit({s}, {sep}, {opts}) *vim.gsplit()*
<
Parameters: ~
- • {s} (string) String to split
- • {sep} (string) Separator or pattern
- • {opts} (table|nil) Keyword arguments |kwargs|:
- • plain: (boolean) Use `sep` literally (as in string.find).
- • trimempty: (boolean) Discard empty segments at start and end
- of the sequence.
+ • {s} (`string`) String to split
+ • {sep} (`string`) Separator or pattern
+ • {opts} (`table?`) Keyword arguments |kwargs|:
+ • {plain}? (`boolean`) Use `sep` literally (as in
+ string.find).
+ • {trimempty}? (`boolean`) Discard empty segments at start and
+ end of the sequence.
Return: ~
- (function) Iterator over the split components
+ (`fun():string?`) Iterator over the split components
See also: ~
• |string.gmatch()|
@@ -1986,20 +2006,20 @@ vim.is_callable({f}) *vim.is_callable()*
Returns true if object `f` can be called as a function.
Parameters: ~
- • {f} any Any object
+ • {f} (`any`) Any object
Return: ~
- (boolean) `true` if `f` is callable, else `false`
+ (`boolean`) `true` if `f` is callable, else `false`
vim.list_contains({t}, {value}) *vim.list_contains()*
Checks if a list-like table (integer keys without gaps) contains `value`.
Parameters: ~
- • {t} (table) Table to check (must be list-like, not validated)
- • {value} any Value to compare
+ • {t} (`table`) Table to check (must be list-like, not validated)
+ • {value} (`any`) Value to compare
Return: ~
- (boolean) `true` if `t` contains `value`
+ (`boolean`) `true` if `t` contains `value`
See also: ~
• |vim.tbl_contains()| for checking values in general tables
@@ -2010,13 +2030,13 @@ vim.list_extend({dst}, {src}, {start}, {finish}) *vim.list_extend()*
NOTE: This mutates dst!
Parameters: ~
- • {dst} (table) List which will be modified and appended to
- • {src} (table) List from which values will be inserted
- • {start} (integer|nil) Start index on src. Defaults to 1
- • {finish} (integer|nil) Final index on src. Defaults to `#src`
+ • {dst} (`table`) List which will be modified and appended to
+ • {src} (`table`) List from which values will be inserted
+ • {start} (`integer?`) Start index on src. Defaults to 1
+ • {finish} (`integer?`) Final index on src. Defaults to `#src`
Return: ~
- (table) dst
+ (`table`) dst
See also: ~
• |vim.tbl_extend()|
@@ -2026,21 +2046,21 @@ vim.list_slice({list}, {start}, {finish}) *vim.list_slice()*
(inclusive)
Parameters: ~
- • {list} (list) Table
- • {start} (integer|nil) Start range of slice
- • {finish} (integer|nil) End range of slice
+ • {list} (`any[]`) Table
+ • {start} (`integer?`) Start range of slice
+ • {finish} (`integer?`) End range of slice
Return: ~
- (list) Copy of table sliced from start to finish (inclusive)
+ (`any[]`) Copy of table sliced from start to finish (inclusive)
vim.pesc({s}) *vim.pesc()*
Escapes magic chars in |lua-patterns|.
Parameters: ~
- • {s} (string) String to escape
+ • {s} (`string`) String to escape
Return: ~
- (string) %-escaped pattern string
+ (`string`) %-escaped pattern string
See also: ~
• https://github.com/rxi/lume
@@ -2064,50 +2084,31 @@ vim.ringbuf({size}) *vim.ringbuf()*
<
Returns a Ringbuf instance with the following methods:
-
• |Ringbuf:push()|
• |Ringbuf:pop()|
• |Ringbuf:peek()|
• |Ringbuf:clear()|
Parameters: ~
- • {size} (integer)
-
- Return: ~
- (table)
-
-vim.Ringbuf:clear() *Ringbuf:clear()*
- Clear all items.
-
-vim.Ringbuf:peek() *Ringbuf:peek()*
- Returns the first unread item without removing it
+ • {size} (`integer`)
Return: ~
- any?|nil
-
-vim.Ringbuf:pop() *Ringbuf:pop()*
- Removes and returns the first unread item
-
- Return: ~
- any?|nil
-
-vim.Ringbuf:push({item}) *Ringbuf:push()*
- Adds an item, overriding the oldest item if the buffer is full.
-
- Parameters: ~
- • {item} any
+ (`vim.Ringbuf`) ringbuf See |vim.Ringbuf|.
vim.spairs({t}) *vim.spairs()*
Enumerates key-value pairs of a table, ordered by key.
Parameters: ~
- • {t} (table) Dict-like table
+ • {t} (`table`) Dict-like table
- Return: ~
- (function) |for-in| iterator over sorted keys and their values
+ Return (multiple): ~
+ (`fun(table: table<K, V>, index?: K):K, V`) |for-in| iterator over
+ sorted keys and their values
+ (`table`)
See also: ~
- • Based on https://github.com/premake/premake-core/blob/master/src/base/table.lua
+ • Based on
+ https://github.com/premake/premake-core/blob/master/src/base/table.lua
vim.split({s}, {sep}, {opts}) *vim.split()*
Splits a string at each instance of a separator and returns the result as
@@ -2121,13 +2122,16 @@ vim.split({s}, {sep}, {opts}) *vim.split()*
<
Parameters: ~
- • {s} (string) String to split
- • {sep} (string) Separator or pattern
- • {opts} (table|nil) Keyword arguments |kwargs| accepted by
- |vim.gsplit()|
+ • {s} (`string`) String to split
+ • {sep} (`string`) Separator or pattern
+ • {opts} (`table?`) Keyword arguments |kwargs|:
+ • {plain}? (`boolean`) Use `sep` literally (as in
+ string.find).
+ • {trimempty}? (`boolean`) Discard empty segments at start and
+ end of the sequence.
Return: ~
- string[] List of split components
+ (`string[]`) List of split components
See also: ~
• |vim.gsplit()|
@@ -2137,23 +2141,11 @@ vim.startswith({s}, {prefix}) *vim.startswith()*
Tests if `s` starts with `prefix`.
Parameters: ~
- • {s} (string) String
- • {prefix} (string) Prefix to match
-
- Return: ~
- (boolean) `true` if `prefix` is a prefix of `s`
-
-vim.tbl_add_reverse_lookup({o}) *vim.tbl_add_reverse_lookup()*
- Add the reverse lookup values to an existing table. For example:
- `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }`
-
- Note that this modifies the input.
-
- Parameters: ~
- • {o} (table) Table to add the reverse to
+ • {s} (`string`) String
+ • {prefix} (`string`) Prefix to match
Return: ~
- (table) o
+ (`boolean`) `true` if `prefix` is a prefix of `s`
vim.tbl_contains({t}, {value}, {opts}) *vim.tbl_contains()*
Checks if a table contains a given value, specified either directly or via
@@ -2167,14 +2159,14 @@ vim.tbl_contains({t}, {value}, {opts}) *vim.tbl_contains()*
<
Parameters: ~
- • {t} (table) Table to check
- • {value} any Value to compare or predicate function reference
- • {opts} (table|nil) Keyword arguments |kwargs|:
- • predicate: (boolean) `value` is a function reference to be
- checked (default false)
+ • {t} (`table`) Table to check
+ • {value} (`any`) Value to compare or predicate function reference
+ • {opts} (`table?`) Keyword arguments |kwargs|:
+ • {predicate}? (`boolean`) `value` is a function reference to
+ be checked (default false)
Return: ~
- (boolean) `true` if `t` contains `value`
+ (`boolean`) `true` if `t` contains `value`
See also: ~
• |vim.list_contains()| for checking values in list-like tables
@@ -2186,10 +2178,10 @@ vim.tbl_count({t}) *vim.tbl_count()*
<
Parameters: ~
- • {t} (table) Table
+ • {t} (`table`) Table
Return: ~
- (integer) Number of non-nil values in table
+ (`integer`) Number of non-nil values in table
See also: ~
• https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
@@ -2198,15 +2190,15 @@ vim.tbl_deep_extend({behavior}, {...}) *vim.tbl_deep_extend()*
Merges recursively two or more tables.
Parameters: ~
- • {behavior} (string) Decides what to do if a key is found in more than
- one map:
+ • {behavior} (`"error"|"keep"|"force"`) (string) Decides what to do if
+ a key is found in more than one map:
• "error": raise an error
• "keep": use value from the leftmost map
• "force": use value from the rightmost map
- • {...} (table) Two or more tables
+ • {...} (`table`) Two or more tables
Return: ~
- (table) Merged table
+ (`table`) Merged table
See also: ~
• |vim.tbl_extend()|
@@ -2215,15 +2207,15 @@ vim.tbl_extend({behavior}, {...}) *vim.tbl_extend()*
Merges two or more tables.
Parameters: ~
- • {behavior} (string) Decides what to do if a key is found in more than
- one map:
+ • {behavior} (`string`) Decides what to do if a key is found in more
+ than one map:
• "error": raise an error
• "keep": use value from the leftmost map
• "force": use value from the rightmost map
- • {...} (table) Two or more tables
+ • {...} (`table`) Two or more tables
Return: ~
- (table) Merged table
+ (`table`) Merged table
See also: ~
• |extend()|
@@ -2232,24 +2224,25 @@ vim.tbl_filter({func}, {t}) *vim.tbl_filter()*
Filter a table using a predicate function
Parameters: ~
- • {func} (function) Function
- • {t} (table) Table
+ • {func} (`function`) Function
+ • {t} (`table`) Table
Return: ~
- (table) Table of filtered values
+ (`any[]`) Table of filtered values
vim.tbl_flatten({t}) *vim.tbl_flatten()*
Creates a copy of a list-like table such that any nested tables are
"unrolled" and appended to the result.
Parameters: ~
- • {t} (table) List-like table
+ • {t} (`table`) List-like table
Return: ~
- (table) Flattened copy of the given list-like table
+ (`table`) Flattened copy of the given list-like table
See also: ~
- • From https://github.com/premake/premake-core/blob/master/src/base/table.lua
+ • From
+ https://github.com/premake/premake-core/blob/master/src/base/table.lua
vim.tbl_get({o}, {...}) *vim.tbl_get()*
Index into a table (first argument) via string keys passed as subsequent
@@ -2261,15 +2254,16 @@ vim.tbl_get({o}, {...}) *vim.tbl_get()*
<
Parameters: ~
- • {o} (table) Table to index
- • {...} any Optional keys (0 or more, variadic) via which to index the
- table
+ • {o} (`table`) Table to index
+ • {...} (`any`) Optional keys (0 or more, variadic) via which to index
+ the table
Return: ~
- any Nested value indexed by key (if it exists), else nil
+ (`any`) Nested value indexed by key (if it exists), else nil
vim.tbl_isarray({t}) *vim.tbl_isarray()*
- Tests if `t` is an "array": a table indexed only by integers (potentially non-contiguous).
+ Tests if `t` is an "array": a table indexed only by integers (potentially
+ non-contiguous).
If the indexes start from 1 and are contiguous then the array is also a
list. |vim.tbl_islist()|
@@ -2279,10 +2273,10 @@ vim.tbl_isarray({t}) *vim.tbl_isarray()*
|rpcrequest()| or |vim.fn|.
Parameters: ~
- • {t} (table)
+ • {t} (`table`)
Return: ~
- (boolean) `true` if array-like table, else `false`.
+ (`boolean`) `true` if array-like table, else `false`.
See also: ~
• https://github.com/openresty/luajit2#tableisarray
@@ -2291,27 +2285,27 @@ vim.tbl_isempty({t}) *vim.tbl_isempty()*
Checks if a table is empty.
Parameters: ~
- • {t} (table) Table to check
+ • {t} (`table`) Table to check
Return: ~
- (boolean) `true` if `t` is empty
+ (`boolean`) `true` if `t` is empty
See also: ~
• https://github.com/premake/premake-core/blob/master/src/base/table.lua
vim.tbl_islist({t}) *vim.tbl_islist()*
- Tests if `t` is a "list": a table indexed only by contiguous integers starting from 1 (what |lua-length| calls a "regular
- array").
+ Tests if `t` is a "list": a table indexed only by contiguous integers
+ starting from 1 (what |lua-length| calls a "regular array").
Empty table `{}` is a list, unless it was created by |vim.empty_dict()| or
returned as a dict-like |API| or Vimscript result, for example from
|rpcrequest()| or |vim.fn|.
Parameters: ~
- • {t} (table)
+ • {t} (`table`)
Return: ~
- (boolean) `true` if list-like table, else `false`.
+ (`boolean`) `true` if list-like table, else `false`.
See also: ~
• |vim.tbl_isarray()|
@@ -2321,42 +2315,43 @@ vim.tbl_keys({t}) *vim.tbl_keys()*
return table of keys is not guaranteed.
Parameters: ~
- • {t} (table) Table
+ • {t} (`table`) Table
Return: ~
- (list) List of keys
+ (`any[]`) List of keys
See also: ~
- • From https://github.com/premake/premake-core/blob/master/src/base/table.lua
+ • From
+ https://github.com/premake/premake-core/blob/master/src/base/table.lua
vim.tbl_map({func}, {t}) *vim.tbl_map()*
Apply a function to all values of a table.
Parameters: ~
- • {func} (function) Function
- • {t} (table) Table
+ • {func} (`fun(value: T): any`) Function
+ • {t} (`table<any, T>`) Table
Return: ~
- (table) Table of transformed values
+ (`table`) Table of transformed values
vim.tbl_values({t}) *vim.tbl_values()*
Return a list of all values used in a table. However, the order of the
return table of values is not guaranteed.
Parameters: ~
- • {t} (table) Table
+ • {t} (`table`) Table
Return: ~
- (list) List of values
+ (`any[]`) List of values
vim.trim({s}) *vim.trim()*
Trim whitespace (Lua pattern "%s") from both sides of a string.
Parameters: ~
- • {s} (string) String to trim
+ • {s} (`string`) String to trim
Return: ~
- (string) String with whitespace removed from its beginning and end
+ (`string`) String with whitespace removed from its beginning and end
See also: ~
• |lua-patterns|
@@ -2396,7 +2391,7 @@ vim.validate({opt}) *vim.validate()*
<
Parameters: ~
- • {opt} (table) Names of parameters to validate. Each key is a
+ • {opt} (`table`) Names of parameters to validate. Each key is a
parameter name; each value is a tuple in one of these forms:
1. (arg_value, type_name, optional)
• arg_value: argument value
@@ -2404,7 +2399,6 @@ vim.validate({opt}) *vim.validate()*
"string", "s", "number", "n", "boolean", "b", "function",
"f", "nil", "thread", "userdata") or list of them.
• optional: (optional) boolean, if true, `nil` is valid
-
2. (arg_value, fn, msg)
• arg_value: argument value
• fn: any function accepting one argument, returns true if
@@ -2433,32 +2427,32 @@ vim.loader.find({modname}, {opts}) *vim.loader.find()*
Finds Lua modules for the given module name.
Parameters: ~
- • {modname} (string) Module name, or `"*"` to find the top-level
+ • {modname} (`string`) Module name, or `"*"` to find the top-level
modules instead
- • {opts} (table|nil) Options for finding a module:
- • rtp: (boolean) Search for modname in the runtime path
- (defaults to `true`)
- • paths: (string[]) Extra paths to search for modname
- (defaults to `{}`)
- • patterns: (string[]) List of patterns to use when
+ • {opts} (`table?`) Options for finding a module:
+ • {rtp}? (`boolean`, default: `true`) Search for modname in
+ the runtime path.
+ • {paths}? (`string[]`, default: `{}`) Extra paths to
+ search for modname
+ • {patterns}? (`string[]`, default:
+ `{"/init.lua", ".lua"}`) List of patterns to use when
searching for modules. A pattern is a string added to the
- basename of the Lua module being searched. (defaults to
- `{"/init.lua", ".lua"}`)
- • all: (boolean) Return all matches instead of just the
- first one (defaults to `false`)
+ basename of the Lua module being searched.
+ • {all}? (`boolean`, default: `false`) Search for all
+ matches.
Return: ~
- (list) A list of results with the following properties:
- • modpath: (string) the path to the module
- • modname: (string) the name of the module
- • stat: (table|nil) the fs_stat of the module path. Won't be returned
- for `modname="*"`
+ (`table[]`) A list of objects with the following fields:
+ • {modpath} (`string`) Path of the module
+ • {modname} (`string`) Name of the module
+ • {stat}? (`uv.uv_fs_t`) The fs_stat of the module path. Won't be
+ returned for `modname="*"`
vim.loader.reset({path}) *vim.loader.reset()*
Resets the cache for the path, or all the paths if path is nil.
Parameters: ~
- • {path} string? path to reset
+ • {path} (`string?`) path to reset
==============================================================================
@@ -2468,57 +2462,57 @@ vim.uri_decode({str}) *vim.uri_decode()*
URI-decodes a string containing percent escapes.
Parameters: ~
- • {str} (string) string to decode
+ • {str} (`string`) string to decode
Return: ~
- (string) decoded string
+ (`string`) decoded string
vim.uri_encode({str}, {rfc}) *vim.uri_encode()*
URI-encodes a string using percent escapes.
Parameters: ~
- • {str} (string) string to encode
- • {rfc} "rfc2396" | "rfc2732" | "rfc3986" | nil
+ • {str} (`string`) string to encode
+ • {rfc} (`"rfc2396"|"rfc2732"|"rfc3986"?`)
Return: ~
- (string) encoded string
+ (`string`) encoded string
vim.uri_from_bufnr({bufnr}) *vim.uri_from_bufnr()*
Gets a URI from a bufnr.
Parameters: ~
- • {bufnr} (integer)
+ • {bufnr} (`integer`)
Return: ~
- (string) URI
+ (`string`) URI
vim.uri_from_fname({path}) *vim.uri_from_fname()*
Gets a URI from a file path.
Parameters: ~
- • {path} (string) Path to file
+ • {path} (`string`) Path to file
Return: ~
- (string) URI
+ (`string`) URI
vim.uri_to_bufnr({uri}) *vim.uri_to_bufnr()*
Gets the buffer for a uri. Creates a new unloaded buffer if no buffer for
the uri already exists.
Parameters: ~
- • {uri} (string)
+ • {uri} (`string`)
Return: ~
- (integer) bufnr
+ (`integer`) bufnr
vim.uri_to_fname({uri}) *vim.uri_to_fname()*
Gets a filename from a URI.
Parameters: ~
- • {uri} (string)
+ • {uri} (`string`)
Return: ~
- (string) filename or unchanged URI for non-file URIs
+ (`string`) filename or unchanged URI for non-file URIs
==============================================================================
@@ -2535,7 +2529,7 @@ vim.ui.input({opts}, {on_confirm}) *vim.ui.input()*
<
Parameters: ~
- • {opts} (table) Additional options. See |input()|
+ • {opts} (`table?`) Additional options. See |input()|
• prompt (string|nil) Text of the prompt
• default (string|nil) Default reply to the input
• completion (string|nil) Specifies type of completion
@@ -2544,7 +2538,7 @@ vim.ui.input({opts}, {on_confirm}) *vim.ui.input()*
"-complete=" argument. See |:command-completion|
• highlight (function) Function that will be used for
highlighting user inputs.
- • {on_confirm} (function) ((input|nil) -> ()) Called once the user
+ • {on_confirm} (`function`) ((input|nil) -> ()) Called once the user
confirms or abort the input. `input` is what the user
typed (it might be an empty string if nothing was
entered), or `nil` if the user aborted the dialog.
@@ -2563,11 +2557,11 @@ vim.ui.open({path}) *vim.ui.open()*
<
Parameters: ~
- • {path} (string) Path or URL to open
+ • {path} (`string`) Path or URL to open
Return (multiple): ~
- vim.SystemCompleted|nil Command result, or nil if not found.
- (string|nil) Error message on failure
+ (`vim.SystemCompleted?`) Command result, or nil if not found.
+ (`string?`) Error message on failure
See also: ~
• |vim.system()|
@@ -2592,8 +2586,8 @@ vim.ui.select({items}, {opts}, {on_choice}) *vim.ui.select()*
<
Parameters: ~
- • {items} (table) Arbitrary items
- • {opts} (table) Additional options
+ • {items} (`any[]`) Arbitrary items
+ • {opts} (`table`) Additional options
• prompt (string|nil) Text of the prompt. Defaults to
`Select one of:`
• format_item (function item -> text) Function to format
@@ -2603,8 +2597,8 @@ vim.ui.select({items}, {opts}, {on_choice}) *vim.ui.select()*
item shape. Plugins reimplementing `vim.ui.select` may
wish to use this to infer the structure or semantics of
`items`, or the context in which select() was called.
- • {on_choice} (function) ((item|nil, idx|nil) -> ()) Called once the
- user made a choice. `idx` is the 1-based index of `item`
+ • {on_choice} (`fun(item: any?, idx: integer?)`) Called once the user
+ made a choice. `idx` is the 1-based index of `item`
within `items`. `nil` if the user aborted the dialog.
@@ -2658,9 +2652,9 @@ vim.filetype.add({filetypes}) *vim.filetype.add()*
['/etc/foo/config'] = 'toml',
},
pattern = {
- ['.*&zwj;/etc/foo/.*'] = 'fooscript',
+ ['.*/etc/foo/.*'] = 'fooscript',
-- Using an optional priority
- ['.*&zwj;/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } },
+ ['.*/etc/foo/.*%.conf'] = { 'dosini', { priority = 10 } },
-- A pattern containing an environment variable
['${XDG_CONFIG_HOME}/foo/git'] = 'git',
['README.(%a+)$'] = function(path, bufnr, ext)
@@ -2693,8 +2687,11 @@ vim.filetype.add({filetypes}) *vim.filetype.add()*
<
Parameters: ~
- • {filetypes} (table) A table containing new filetype maps (see
+ • {filetypes} (`table`) A table containing new filetype maps (see
example).
+ • {pattern}? (`vim.filetype.mapping`)
+ • {extension}? (`vim.filetype.mapping`)
+ • {filename}? (`vim.filetype.mapping`)
*vim.filetype.get_option()*
vim.filetype.get_option({filetype}, {option})
@@ -2713,11 +2710,11 @@ vim.filetype.get_option({filetype}, {option})
may not reflect later changes.
Parameters: ~
- • {filetype} (string) Filetype
- • {option} (string) Option name
+ • {filetype} (`string`) Filetype
+ • {option} (`string`) Option name
Return: ~
- string|boolean|integer: Option value
+ (`string|boolean|integer`) Option value
vim.filetype.match({args}) *vim.filetype.match()*
Perform filetype detection.
@@ -2749,24 +2746,24 @@ vim.filetype.match({args}) *vim.filetype.match()*
<
Parameters: ~
- • {args} (table) Table specifying which matching strategy to use.
+ • {args} (`table`) Table specifying which matching strategy to use.
Accepted keys are:
- • buf (number): Buffer number to use for matching. Mutually
- exclusive with {contents}
- • filename (string): Filename to use for matching. When {buf}
- is given, defaults to the filename of the given buffer
+ • {buf}? (`integer`) Buffer number to use for matching.
+ Mutually exclusive with {contents}
+ • {filename}? (`string`) Filename to use for matching. When
+ {buf} is given, defaults to the filename of the given buffer
number. The file need not actually exist in the filesystem.
When used without {buf} only the name of the file is used
for filetype matching. This may result in failure to detect
the filetype in cases where the filename alone is not enough
to disambiguate the filetype.
- • contents (table): An array of lines representing file
+ • {contents}? (`string[]`) An array of lines representing file
contents to use for matching. Can be used with {filename}.
Mutually exclusive with {buf}.
Return (multiple): ~
- (string|nil) If a match was found, the matched filetype.
- (function|nil) A function that modifies buffer state when called (for
+ (`string?`) If a match was found, the matched filetype.
+ (`function?`) A function that modifies buffer state when called (for
example, to set some filetype specific buffer variables). The function
accepts a buffer number as its only argument.
@@ -2782,9 +2779,11 @@ vim.keymap.del({modes}, {lhs}, {opts}) *vim.keymap.del()*
<
Parameters: ~
- • {opts} (table|nil) A table of optional arguments:
- • "buffer": (integer|boolean) Remove a mapping from the given
- buffer. When `0` or `true`, use the current buffer.
+ • {modes} (`string|string[]`)
+ • {lhs} (`string`)
+ • {opts} (`table?`) A table of optional arguments:
+ • "buffer": (integer|boolean) Remove a mapping from the given
+ buffer. When `0` or `true`, use the current buffer.
See also: ~
• |vim.keymap.set()|
@@ -2806,16 +2805,15 @@ vim.keymap.set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()*
<
Parameters: ~
- • {mode} string|table Mode short-name, see |nvim_set_keymap()|. Can
+ • {mode} (`string|table`) Mode short-name, see |nvim_set_keymap()|. Can
also be list of modes to create mapping on multiple modes.
- • {lhs} (string) Left-hand side |{lhs}| of the mapping.
- • {rhs} string|function Right-hand side |{rhs}| of the mapping, can be
- a Lua function.
- • {opts} (table|nil) Table of |:map-arguments|.
+ • {lhs} (`string`) Left-hand side |{lhs}| of the mapping.
+ • {rhs} (`string|function`) Right-hand side |{rhs}| of the mapping,
+ can be a Lua function.
+ • {opts} (`table?`) Table of |:map-arguments|.
• Same as |nvim_set_keymap()| {opts}, except:
• "replace_keycodes" defaults to `true` if "expr" is `true`.
• "noremap": inverse of "remap" (see below).
-
• Also accepts:
• "buffer": (integer|boolean) Creates buffer-local mapping,
`0` or `true` for current buffer.
@@ -2836,26 +2834,26 @@ vim.fs.basename({file}) *vim.fs.basename()*
Return the basename of the given path
Parameters: ~
- • {file} (string) Path
+ • {file} (`string?`) Path
Return: ~
- (string|nil) Basename of {file}
+ (`string?`) Basename of {file}
vim.fs.dir({path}, {opts}) *vim.fs.dir()*
Return an iterator over the items located in {path}
Parameters: ~
- • {path} (string) An absolute or relative path to the directory to
+ • {path} (`string`) An absolute or relative path to the directory to
iterate over. The path is first normalized
|vim.fs.normalize()|.
- • {opts} (table|nil) Optional keyword arguments:
+ • {opts} (`table?`) Optional keyword arguments:
• depth: integer|nil How deep the traverse (default 1)
• skip: (fun(dir_name: string): boolean)|nil Predicate to
control traversal. Return false to stop searching the
current directory. Only useful when depth > 1
Return: ~
- Iterator over items in {path}. Each iteration yields two values:
+ (`Iterator`) over items in {path}. Each iteration yields two values:
"name" and "type". "name" is the basename of the item relative to
{path}. "type" is one of the following: "file", "directory", "link",
"fifo", "socket", "char", "block", "unknown".
@@ -2864,10 +2862,10 @@ vim.fs.dirname({file}) *vim.fs.dirname()*
Return the parent directory of the given path
Parameters: ~
- • {file} (string) Path
+ • {file} (`string?`) Path
Return: ~
- (string|nil) Parent directory of {file}
+ (`string?`) Parent directory of {file}
vim.fs.find({names}, {opts}) *vim.fs.find()*
Find files or directories (or other items as specified by `opts.type`) in
@@ -2903,7 +2901,7 @@ vim.fs.find({names}, {opts}) *vim.fs.find()*
<
Parameters: ~
- • {names} (string|string[]|fun(name: string, path: string): boolean)
+ • {names} (`string|string[]|fun(name: string, path: string): boolean`)
Names of the items to find. Must be base names, paths and
globs are not supported when {names} is a string or a table.
If {names} is a function, it is called for each traversed
@@ -2911,32 +2909,33 @@ vim.fs.find({names}, {opts}) *vim.fs.find()*
• name: base name of the current item
• path: full path of the current item The function should
return `true` if the given item is considered a match.
- • {opts} (table) Optional keyword arguments:
- • path (string): Path to begin searching from. If omitted,
- the |current-directory| is used.
- • upward (boolean, default false): If true, search upward
+ • {opts} (`table`) Optional keyword arguments:
+ • {path}? (`string`) Path to begin searching from. If
+ omitted, the |current-directory| is used.
+ • {upward}? (`boolean`, default: `false`) Search upward
through parent directories. Otherwise, search through child
directories (recursively).
- • stop (string): Stop searching when this directory is
+ • {stop}? (`string`) Stop searching when this directory is
reached. The directory itself is not searched.
- • type (string): Find only items of the given type. If
+ • {type}? (`string`) Find only items of the given type. If
omitted, all items that match {names} are included.
- • limit (number, default 1): Stop the search after finding
- this many matches. Use `math.huge` to place no limit on the
- number of matches.
+ • {limit}? (`number`, default: `1`) Stop the search after
+ finding this many matches. Use `math.huge` to place no
+ limit on the number of matches.
Return: ~
- (string[]) Normalized paths |vim.fs.normalize()| of all matching items
+ (`string[]`) Normalized paths |vim.fs.normalize()| of all matching
+ items
vim.fs.joinpath({...}) *vim.fs.joinpath()*
Concatenate directories and/or file paths into a single path with
normalization (e.g., `"foo/"` and `"bar"` get joined to `"foo/bar"`)
Parameters: ~
- • {...} (string)
+ • {...} (`string`)
Return: ~
- (string)
+ (`string`)
vim.fs.normalize({path}, {opts}) *vim.fs.normalize()*
Normalize a path to a standard format. A tilde (~) character at the
@@ -2956,13 +2955,13 @@ vim.fs.normalize({path}, {opts}) *vim.fs.normalize()*
<
Parameters: ~
- • {path} (string) Path to normalize
- • {opts} (table|nil) Options:
- • expand_env: boolean Expand environment variables (default:
- true)
+ • {path} (`string`) Path to normalize
+ • {opts} (`table?`) A table with the following fields:
+ • {expand_env} (`boolean`, default: `true`) Expand environment
+ variables.
Return: ~
- (string) Normalized path
+ (`string`) Normalized path
vim.fs.parents({start}) *vim.fs.parents()*
Iterate over all the parents of the given path.
@@ -2982,12 +2981,552 @@ vim.fs.parents({start}) *vim.fs.parents()*
<
Parameters: ~
- • {start} (string) Initial path.
+ • {start} (`string`) Initial path.
+
+ Return (multiple): ~
+ (`fun(_, dir: string): string?`) Iterator
+ (`nil`)
+ (`string?`)
+
+
+==============================================================================
+Lua module: vim.glob *vim.glob*
+
+vim.glob.to_lpeg({pattern}) *vim.glob.to_lpeg()*
+ Parses a raw glob into an |lua-lpeg| pattern.
+
+ This uses glob semantics from LSP 3.17.0:
+ https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern
+
+ Glob patterns can have the following syntax:
+ • `*` to match one or more characters in a path segment
+ • `?` to match on one character in a path segment
+ • `**` to match any number of path segments, including none
+ • `{}` to group conditions (e.g. `*.{ts,js}` matches TypeScript and
+ JavaScript files)
+ • `[]` to declare a range of characters to match in a path segment (e.g.,
+ `example.[0-9]` to match on `example.0`, `example.1`, …)
+ • `[!...]` to negate a range of characters to match in a path segment
+ (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not
+ `example.0`)
+
+ Parameters: ~
+ • {pattern} (`string`) The raw glob pattern
+
+ Return: ~
+ (`vim.lpeg.Pattern`) pattern An |lua-lpeg| representation of the
+ pattern
+
+
+==============================================================================
+VIM.LPEG *vim.lpeg*
+
+
+LPeg is a pattern-matching library for Lua, based on
+Parsing Expression Grammars (https://bford.info/packrat/) (PEGs).
+
+ *lua-lpeg*
+ *vim.lpeg.Pattern*
+The LPeg library for parsing expression grammars is included as `vim.lpeg`
+(https://www.inf.puc-rio.br/~roberto/lpeg/).
+
+In addition, its regex-like interface is available as |vim.re|
+(https://www.inf.puc-rio.br/~roberto/lpeg/re.html).
+
+
+
+Pattern:match({subject}, {init}) *Pattern:match()*
+ Matches the given `pattern` against the `subject` string. If the match
+ succeeds, returns the index in the subject of the first character after
+ the match, or the captured values (if the pattern captured any value). An
+ optional numeric argument `init` makes the match start at that position in
+ the subject string. As usual in Lua libraries, a negative value counts
+ from the end. Unlike typical pattern-matching functions, `match` works
+ only in anchored mode; that is, it tries to match the pattern with a
+ prefix of the given subject string (at position `init`), not with an
+ arbitrary substring of the subject. So, if we want to find a pattern
+ anywhere in a string, we must either write a loop in Lua or write a
+ pattern that matches anywhere.
+
+ Example: >lua
+ local pattern = lpeg.R('az') ^ 1 * -1
+ assert(pattern:match('hello') == 6)
+ assert(lpeg.match(pattern, 'hello') == 6)
+ assert(pattern:match('1 hello') == nil)
+<
+
+ Parameters: ~
+ • {subject} (`string`)
+ • {init} (`integer?`)
+
+ Return: ~
+ (`integer|vim.lpeg.Capture?`)
+
+vim.lpeg.B({pattern}) *vim.lpeg.B()*
+ Returns a pattern that matches only if the input string at the current
+ position is preceded by `patt`. Pattern `patt` must match only strings
+ with some fixed length, and it cannot contain captures. Like the `and`
+ predicate, this pattern never consumes any input, independently of success
+ or failure.
+
+ Parameters: ~
+ • {pattern} (`vim.lpeg.Pattern`)
+
+ Return: ~
+ (`vim.lpeg.Pattern`)
+
+vim.lpeg.C({patt}) *vim.lpeg.C()*
+ Creates a simple capture, which captures the substring of the subject that
+ matches `patt`. The captured value is a string. If `patt` has other
+ captures, their values are returned after this one.
+
+ Example: >lua
+ local function split (s, sep)
+ sep = lpeg.P(sep)
+ local elem = lpeg.C((1 - sep) ^ 0)
+ local p = elem * (sep * elem) ^ 0
+ return lpeg.match(p, s)
+ end
+ local a, b, c = split('a,b,c', ',')
+ assert(a == 'a')
+ assert(b == 'b')
+ assert(c == 'c')
+<
+
+ Parameters: ~
+ • {patt} (`vim.lpeg.Pattern`)
+
+ Return: ~
+ (`vim.lpeg.Capture`)
+
+vim.lpeg.Carg({n}) *vim.lpeg.Carg()*
+ Creates an argument capture. This pattern matches the empty string and
+ produces the value given as the nth extra argument given in the call to
+ `lpeg.match`.
+
+ Parameters: ~
+ • {n} (`integer`)
+
+ Return: ~
+ (`vim.lpeg.Capture`)
+
+vim.lpeg.Cb({name}) *vim.lpeg.Cb()*
+ Creates a back capture. This pattern matches the empty string and produces
+ the values produced by the most recent group capture named `name` (where
+ `name` can be any Lua value). Most recent means the last complete
+ outermost group capture with the given name. A Complete capture means that
+ the entire pattern corresponding to the capture has matched. An Outermost
+ capture means that the capture is not inside another complete capture. In
+ the same way that LPeg does not specify when it evaluates captures, it
+ does not specify whether it reuses values previously produced by the group
+ or re-evaluates them.
+
+ Parameters: ~
+ • {name} (`any`)
+
+ Return: ~
+ (`vim.lpeg.Capture`)
+
+vim.lpeg.Cc({...}) *vim.lpeg.Cc()*
+ Creates a constant capture. This pattern matches the empty string and
+ produces all given values as its captured values.
+
+ Parameters: ~
+ • {...} (`any`)
+
+ Return: ~
+ (`vim.lpeg.Capture`)
+
+vim.lpeg.Cf({patt}, {func}) *vim.lpeg.Cf()*
+ Creates a fold capture. If `patt` produces a list of captures C1 C2 ...
+ Cn, this capture will produce the value
+ `func(...func(func(C1, C2), C3)...,Cn)`, that is, it will fold (or
+ accumulate, or reduce) the captures from `patt` using function `func`.
+ This capture assumes that `patt` should produce at least one capture with
+ at least one value (of any type), which becomes the initial value of an
+ accumulator. (If you need a specific initial value, you may prefix a
+ constant captureto `patt`.) For each subsequent capture, LPeg calls `func`
+ with this accumulator as the first argument and all values produced by the
+ capture as extra arguments; the first result from this call becomes the
+ new value for the accumulator. The final value of the accumulator becomes
+ the captured value.
+
+ Example: >lua
+ local number = lpeg.R('09') ^ 1 / tonumber
+ local list = number * (',' * number) ^ 0
+ local function add(acc, newvalue) return acc + newvalue end
+ local sum = lpeg.Cf(list, add)
+ assert(sum:match('10,30,43') == 83)
+<
+
+ Parameters: ~
+ • {patt} (`vim.lpeg.Pattern`)
+ • {func} (`fun(acc, newvalue)`)
+
+ Return: ~
+ (`vim.lpeg.Capture`)
+
+vim.lpeg.Cg({patt}, {name}) *vim.lpeg.Cg()*
+ Creates a group capture. It groups all values returned by `patt` into a
+ single capture. The group may be anonymous (if no name is given) or named
+ with the given name (which can be any non-nil Lua value).
+
+ Parameters: ~
+ • {patt} (`vim.lpeg.Pattern`)
+ • {name} (`string?`)
+
+ Return: ~
+ (`vim.lpeg.Capture`)
+
+vim.lpeg.Cmt({patt}, {fn}) *vim.lpeg.Cmt()*
+ Creates a match-time capture. Unlike all other captures, this one is
+ evaluated immediately when a match occurs (even if it is part of a larger
+ pattern that fails later). It forces the immediate evaluation of all its
+ nested captures and then calls `function`. The given function gets as
+ arguments the entire subject, the current position (after the match of
+ `patt`), plus any capture values produced by `patt`. The first value
+ returned by `function` defines how the match happens. If the call returns
+ a number, the match succeeds and the returned number becomes the new
+ current position. (Assuming a subject sand current position `i`, the
+ returned number must be in the range `[i, len(s) + 1]`.) If the call
+ returns `true`, the match succeeds without consuming any input (so, to
+ return true is equivalent to return `i`). If the call returns `false`,
+ `nil`, or no value, the match fails. Any extra values returned by the
+ function become the values produced by the capture.
+
+ Parameters: ~
+ • {patt} (`vim.lpeg.Pattern`)
+ • {fn} (`function`)
+
+ Return: ~
+ (`vim.lpeg.Capture`)
+
+vim.lpeg.Cp() *vim.lpeg.Cp()*
+ Creates a position capture. It matches the empty string and captures the
+ position in the subject where the match occurs. The captured value is a
+ number.
+
+ Example: >lua
+ local I = lpeg.Cp()
+ local function anywhere(p) return lpeg.P({I * p * I + 1 * lpeg.V(1)}) end
+ local match_start, match_end = anywhere('world'):match('hello world!')
+ assert(match_start == 7)
+ assert(match_end == 12)
+<
+
+ Return: ~
+ (`vim.lpeg.Capture`)
+
+vim.lpeg.Cs({patt}) *vim.lpeg.Cs()*
+ Creates a substitution capture. This function creates a substitution
+ capture, which captures the substring of the subject that matches `patt`,
+ with substitutions. For any capture inside `patt` with a value, the
+ substring that matched the capture is replaced by the capture value (which
+ should be a string). The final captured value is the string resulting from
+ all replacements.
+
+ Example: >lua
+ local function gsub (s, patt, repl)
+ patt = lpeg.P(patt)
+ patt = lpeg.Cs((patt / repl + 1) ^ 0)
+ return lpeg.match(patt, s)
+ end
+ assert(gsub('Hello, xxx!', 'xxx', 'World') == 'Hello, World!')
+<
+
+ Parameters: ~
+ • {patt} (`vim.lpeg.Pattern`)
+
+ Return: ~
+ (`vim.lpeg.Capture`)
+
+vim.lpeg.Ct({patt}) *vim.lpeg.Ct()*
+ Creates a table capture. This capture returns a table with all values from
+ all anonymous captures made by `patt` inside this table in successive
+ integer keys, starting at 1. Moreover, for each named capture group
+ created by `patt`, the first value of the group is put into the table with
+ the group name as its key. The captured value is only the table.
+
+ Parameters: ~
+ • {patt} (`vim.lpeg.Pattern|''`)
+
+ Return: ~
+ (`vim.lpeg.Capture`)
+
+vim.lpeg.locale({tab}) *vim.lpeg.locale()*
+ Returns a table with patterns for matching some character classes
+ according to the current locale. The table has fields named `alnum`,
+ `alpha`, `cntrl`, `digit`, `graph`, `lower`, `print`, `punct`, `space`,
+ `upper`, and `xdigit`, each one containing a correspondent pattern. Each
+ pattern matches any single character that belongs to its class. If called
+ with an argument `table`, then it creates those fields inside the given
+ table and returns that table.
+
+ Example: >lua
+ lpeg.locale(lpeg)
+ local space = lpeg.space ^ 0
+ local name = lpeg.C(lpeg.alpha ^ 1) * space
+ local sep = lpeg.S(',;') * space
+ local pair = lpeg.Cg(name * '=' * space * name) * sep ^ -1
+ local list = lpeg.Cf(lpeg.Ct('') * pair ^ 0, rawset)
+ local t = list:match('a=b, c = hi; next = pi')
+ assert(t.a == 'b')
+ assert(t.c == 'hi')
+ assert(t.next == 'pi')
+ local locale = lpeg.locale()
+ assert(type(locale.digit) == 'userdata')
+<
+
+ Parameters: ~
+ • {tab} (`table?`)
+
+ Return: ~
+ (`vim.lpeg.Locale`)
+
+vim.lpeg.match({pattern}, {subject}, {init}) *vim.lpeg.match()*
+ Matches the given `pattern` against the `subject` string. If the match
+ succeeds, returns the index in the subject of the first character after
+ the match, or the captured values (if the pattern captured any value). An
+ optional numeric argument `init` makes the match start at that position in
+ the subject string. As usual in Lua libraries, a negative value counts
+ from the end. Unlike typical pattern-matching functions, `match` works
+ only in anchored mode; that is, it tries to match the pattern with a
+ prefix of the given subject string (at position `init`), not with an
+ arbitrary substring of the subject. So, if we want to find a pattern
+ anywhere in a string, we must either write a loop in Lua or write a
+ pattern that matches anywhere.
+
+ Example: >lua
+ local pattern = lpeg.R('az') ^ 1 * -1
+ assert(pattern:match('hello') == 6)
+ assert(lpeg.match(pattern, 'hello') == 6)
+ assert(pattern:match('1 hello') == nil)
+<
+
+ Parameters: ~
+ • {pattern} (`vim.lpeg.Pattern`)
+ • {subject} (`string`)
+ • {init} (`integer?`)
+
+ Return: ~
+ (`integer|vim.lpeg.Capture?`)
+
+vim.lpeg.P({value}) *vim.lpeg.P()*
+ Converts the given value into a proper pattern. The following rules are
+ applied:
+ • If the argument is a pattern, it is returned unmodified.
+ • If the argument is a string, it is translated to a pattern that matches
+ the string literally.
+ • If the argument is a non-negative number `n`, the result is a pattern
+ that matches exactly `n` characters.
+ • If the argument is a negative number `-n`, the result is a pattern that
+ succeeds only if the input string has less than `n` characters left:
+ `lpeg.P(-n)` is equivalent to `-lpeg.P(n)` (see the unary minus
+ operation).
+ • If the argument is a boolean, the result is a pattern that always
+ succeeds or always fails (according to the boolean value), without
+ consuming any input.
+ • If the argument is a table, it is interpreted as a grammar (see
+ Grammars).
+ • If the argument is a function, returns a pattern equivalent to a
+ match-time capture over the empty string.
+
+ Parameters: ~
+ • {value} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
+
+ Return: ~
+ (`vim.lpeg.Pattern`)
+
+vim.lpeg.R({...}) *vim.lpeg.R()*
+ Returns a pattern that matches any single character belonging to one of
+ the given ranges. Each `range` is a string `xy` of length 2, representing
+ all characters with code between the codes of `x` and `y` (both
+ inclusive). As an example, the pattern `lpeg.R('09')` matches any digit,
+ and `lpeg.R('az', 'AZ')` matches any ASCII letter.
+
+ Example: >lua
+ local pattern = lpeg.R('az') ^ 1 * -1
+ assert(pattern:match('hello') == 6)
+<
+
+ Parameters: ~
+ • {...} (`string`)
+
+ Return: ~
+ (`vim.lpeg.Pattern`)
+
+vim.lpeg.S({string}) *vim.lpeg.S()*
+ Returns a pattern that matches any single character that appears in the
+ given string (the `S` stands for Set). As an example, the pattern
+ `lpeg.S('+-*/')` matches any arithmetic operator. Note that, if `s` is a
+ character (that is, a string of length 1), then `lpeg.P(s)` is equivalent
+ to `lpeg.S(s)` which is equivalent to `lpeg.R(s..s)`. Note also that both
+ `lpeg.S('')` and `lpeg.R()` are patterns that always fail.
+
+ Parameters: ~
+ • {string} (`string`)
+
+ Return: ~
+ (`vim.lpeg.Pattern`)
+
+vim.lpeg.setmaxstack({max}) *vim.lpeg.setmaxstack()*
+ Sets a limit for the size of the backtrack stack used by LPeg to track
+ calls and choices. The default limit is `400`. Most well-written patterns
+ need little backtrack levels and therefore you seldom need to change this
+ limit; before changing it you should try to rewrite your pattern to avoid
+ the need for extra space. Nevertheless, a few useful patterns may
+ overflow. Also, with recursive grammars, subjects with deep recursion may
+ also need larger limits.
+
+ Parameters: ~
+ • {max} (`integer`)
+
+vim.lpeg.type({value}) *vim.lpeg.type()*
+ Returns the string `"pattern"` if the given value is a pattern, otherwise
+ `nil`.
+
+ Parameters: ~
+ • {value} (`vim.lpeg.Pattern|string|integer|boolean|table|function`)
+
+ Return: ~
+ (`"pattern"?`)
+
+vim.lpeg.V({v}) *vim.lpeg.V()*
+ Creates a non-terminal (a variable) for a grammar. This operation creates
+ a non-terminal (a variable) for a grammar. The created non-terminal refers
+ to the rule indexed by `v` in the enclosing grammar.
+
+ Example: >lua
+ local b = lpeg.P({'(' * ((1 - lpeg.S '()') + lpeg.V(1)) ^ 0 * ')'})
+ assert(b:match('((string))') == 11)
+ assert(b:match('(') == nil)
+<
+
+ Parameters: ~
+ • {v} (`string|integer`)
+
+ Return: ~
+ (`vim.lpeg.Pattern`)
+
+vim.lpeg.version() *vim.lpeg.version()*
+ Returns a string with the running version of LPeg.
+
+ Return: ~
+ (`string`)
+
+
+==============================================================================
+VIM.RE *vim.re*
+
+The `vim.re` module provides a conventional regex-like syntax for pattern
+usage within LPeg |vim.lpeg|.
+
+See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original
+documentation including regex syntax and more concrete examples.
+
+
+vim.re.compile({string}, {defs}) *vim.re.compile()*
+ Compiles the given {string} and returns an equivalent LPeg pattern. The
+ given string may define either an expression or a grammar. The optional
+ {defs} table provides extra Lua values to be used by the pattern.
+
+ Parameters: ~
+ • {string} (`string`)
+ • {defs} (`table?`)
+
+ Return: ~
+ (`vim.lpeg.Pattern`)
+
+vim.re.find({subject}, {pattern}, {init}) *vim.re.find()*
+ Searches the given {pattern} in the given {subject}. If it finds a match,
+ returns the index where this occurrence starts and the index where it
+ ends. Otherwise, returns nil.
+
+ An optional numeric argument {init} makes the search starts at that
+ position in the subject string. As usual in Lua libraries, a negative
+ value counts from the end.
+
+ Parameters: ~
+ • {subject} (`string`)
+ • {pattern} (`vim.lpeg.Pattern|string`)
+ • {init} (`integer?`)
Return (multiple): ~
- fun(_, dir: string): string? Iterator
- nil
- (string|nil)
+ (`integer?`) the index where the occurrence starts, nil if no match
+ (`integer?`) the index where the occurrence ends, nil if no match
+
+vim.re.gsub({subject}, {pattern}, {replacement}) *vim.re.gsub()*
+ Does a global substitution, replacing all occurrences of {pattern} in the
+ given {subject} by {replacement}.
+
+ Parameters: ~
+ • {subject} (`string`)
+ • {pattern} (`vim.lpeg.Pattern|string`)
+ • {replacement} (`string`)
+
+ Return: ~
+ (`string`)
+
+vim.re.match({subject}, {pattern}, {init}) *vim.re.match()*
+ Matches the given {pattern} against the given {subject}, returning all
+ captures.
+
+ Parameters: ~
+ • {subject} (`string`)
+ • {pattern} (`vim.lpeg.Pattern|string`)
+ • {init} (`integer?`)
+
+ Return: ~
+ (`integer|vim.lpeg.Capture?`)
+
+ See also: ~
+ • vim.lpeg.match()
+
+vim.re.updatelocale() *vim.re.updatelocale()*
+ Updates the pre-defined character classes to the current locale.
+
+
+==============================================================================
+VIM.REGEX *vim.regex*
+
+Vim regexes can be used directly from Lua. Currently they only allow matching
+within a single line.
+
+
+ *regex:match_line()*
+regex:match_line({bufnr}, {line_idx}, {start}, {end_})
+ Match line {line_idx} (zero-based) in buffer {bufnr}. If {start} and {end}
+ are supplied, match only this byte index range. Otherwise see
+ |regex:match_str()|. If {start} is used, then the returned byte indices
+ will be relative {start}.
+
+ Parameters: ~
+ • {bufnr} (`integer`)
+ • {line_idx} (`integer`)
+ • {start} (`integer?`)
+ • {end_} (`integer?`)
+
+regex:match_str({str}) *regex:match_str()*
+ Match the string against the regex. If the string should match the regex
+ precisely, surround the regex with `^` and `$`. If there was a match, the
+ byte indices for the beginning and end of the match are returned. When
+ there is no match, `nil` is returned. Because any integer is "truthy",
+ `regex:match_str()` can be directly used as a condition in an
+ if-statement.
+
+ Parameters: ~
+ • {str} (`string`)
+
+vim.regex({re}) *vim.regex()*
+ Parse the Vim regex {re} and return a regex object. Regexes are "magic"
+ and case-sensitive by default, regardless of 'magic' and 'ignorecase'.
+ They can be controlled with flags, see |/magic| and |/ignorecase|.
+
+ Parameters: ~
+ • {re} (`string`)
+
+ Return: ~
+ (`vim.regex`)
==============================================================================
@@ -2999,10 +3538,10 @@ vim.secure.read({path}) *vim.secure.read()*
$XDG_STATE_HOME/nvim/trust.
Parameters: ~
- • {path} (string) Path to a file to read.
+ • {path} (`string`) Path to a file to read.
Return: ~
- (string|nil) The contents of the given file if it exists and is
+ (`string?`) The contents of the given file if it exists and is
trusted, or nil otherwise.
See also: ~
@@ -3014,47 +3553,43 @@ vim.secure.trust({opts}) *vim.secure.trust()*
The trust database is located at |$XDG_STATE_HOME|/nvim/trust.
Parameters: ~
- • {opts} (table)
- • action (string): "allow" to add a file to the trust database
- and trust it, "deny" to add a file to the trust database and
- deny it, "remove" to remove file from the trust database
- • path (string|nil): Path to a file to update. Mutually
+ • {opts} (`table?`) A table with the following fields:
+ • {action} (`'allow'|'deny'|'remove'`) - `'allow'` to add a
+ file to the trust database and trust it,
+ • `'deny'` to add a file to the trust database and deny it,
+ • `'remove'` to remove file from the trust database
+ • {path}? (`string`) Path to a file to update. Mutually
exclusive with {bufnr}. Cannot be used when {action} is
"allow".
- • bufnr (number|nil): Buffer number to update. Mutually
+ • {bufnr}? (`integer`) Buffer number to update. Mutually
exclusive with {path}.
Return (multiple): ~
- (boolean) success true if operation was successful
- (string) msg full path if operation was successful, else error message
+ (`boolean`) success true if operation was successful
+ (`string`) msg full path if operation was successful, else error
+ message
==============================================================================
Lua module: vim.version *vim.version*
-
-The `vim.version` module provides functions for comparing versions and
-ranges conforming to the
-
-https://semver.org
-
-spec. Plugins, and plugin managers, can use this to check available tools
-and dependencies on the current system.
+The `vim.version` module provides functions for comparing versions and ranges
+conforming to the https://semver.org spec. Plugins, and plugin managers, can
+use this to check available tools and dependencies on the current system.
Example: >lua
local v = vim.version.parse(vim.fn.system({'tmux', '-V'}), {strict=false})
if vim.version.gt(v, {3, 2, 0}) then
-- ...
end
-
<
*vim.version()* returns the version of the current Nvim process.
-VERSION RANGE SPEC *version-range*
+VERSION RANGE SPEC *version-range*
-A version "range spec" defines a semantic version range which can be
-tested against a version, using |vim.version.range()|.
+A version "range spec" defines a semantic version range which can be tested
+against a version, using |vim.version.range()|.
Supported range specs are shown in the following table. Note: suffixed
versions (1.2.3-rc1) are not matched. >
@@ -3085,9 +3620,9 @@ versions (1.2.3-rc1) are not matched. >
Partial left: missing pieces treated as 0 (1.2 => 1.2.0).
1.2 - 2.3.0 is 1.2.0 - 2.3.0
-
<
+
vim.version.cmp({v1}, {v2}) *vim.version.cmp()*
Parses and compares two version objects (the result of
|vim.version.parse()|, or specified literally as a `{major, minor, patch}`
@@ -3109,50 +3644,71 @@ vim.version.cmp({v1}, {v2}) *vim.version.cmp()*
otherwise-equivalent versions.
Parameters: ~
- • {v1} Version|number[] Version object.
- • {v2} Version|number[] Version to compare with `v1` .
+ • {v1} (`vim.Version|number[]|string`) Version object.
+ • {v2} (`vim.Version|number[]|string`) Version to compare with `v1`.
Return: ~
- (integer) -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`.
+ (`integer`) -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`.
vim.version.eq({v1}, {v2}) *vim.version.eq()*
- Returns `true` if the given versions are equal. See |vim.version.cmp()| for usage.
+ Returns `true` if the given versions are equal. See |vim.version.cmp()|
+ for usage.
Parameters: ~
- • {v1} Version|number[]
- • {v2} Version|number[]
+ • {v1} (`vim.Version|number[]|string`)
+ • {v2} (`vim.Version|number[]|string`)
Return: ~
- (boolean)
+ (`boolean`)
+
+vim.version.ge({v1}, {v2}) *vim.version.ge()*
+ Returns `true` if `v1 >= v2`. See |vim.version.cmp()| for usage.
+
+ Parameters: ~
+ • {v1} (`vim.Version|number[]|string`)
+ • {v2} (`vim.Version|number[]|string`)
+
+ Return: ~
+ (`boolean`)
vim.version.gt({v1}, {v2}) *vim.version.gt()*
- Returns `true` if `v1 > v2` . See |vim.version.cmp()| for usage.
+ Returns `true` if `v1 > v2`. See |vim.version.cmp()| for usage.
Parameters: ~
- • {v1} Version|number[]
- • {v2} Version|number[]
+ • {v1} (`vim.Version|number[]|string`)
+ • {v2} (`vim.Version|number[]|string`)
Return: ~
- (boolean)
+ (`boolean`)
vim.version.last({versions}) *vim.version.last()*
TODO: generalize this, move to func.lua
Parameters: ~
- • {versions} Version []
+ • {versions} (`vim.Version[]`)
+
+ Return: ~
+ (`vim.Version?`)
+
+vim.version.le({v1}, {v2}) *vim.version.le()*
+ Returns `true` if `v1 <= v2`. See |vim.version.cmp()| for usage.
+
+ Parameters: ~
+ • {v1} (`vim.Version|number[]|string`)
+ • {v2} (`vim.Version|number[]|string`)
Return: ~
- Version ?|nil
+ (`boolean`)
vim.version.lt({v1}, {v2}) *vim.version.lt()*
- Returns `true` if `v1 < v2` . See |vim.version.cmp()| for usage.
+ Returns `true` if `v1 < v2`. See |vim.version.cmp()| for usage.
Parameters: ~
- • {v1} Version|number[]
- • {v2} Version|number[]
+ • {v1} (`vim.Version|number[]|string`)
+ • {v2} (`vim.Version|number[]|string`)
Return: ~
- (boolean)
+ (`boolean`)
vim.version.parse({version}, {opts}) *vim.version.parse()*
Parses a semantic version string and returns a version object which can be
@@ -3162,18 +3718,19 @@ vim.version.parse({version}, {opts}) *vim.version.parse()*
<
Parameters: ~
- • {version} (string) Version string to parse.
- • {opts} (table|nil) Optional keyword arguments:
+ • {version} (`string`) Version string to parse.
+ • {opts} (`table?`) Optional keyword arguments:
• strict (boolean): Default false. If `true`, no coercion
is attempted on input not conforming to semver v2.0.0. If
`false`, `parse()` attempts to coerce input such as
"1.0", "0-x", "tmux 3.2a" into valid versions.
Return: ~
- (table|nil) parsed_version Version object or `nil` if input is invalid.
+ (`vim.Version?`) parsed_version Version object or `nil` if input is
+ invalid.
See also: ~
- • # https://semver.org/spec/v2.0.0.html
+ • https://semver.org/spec/v2.0.0.html
vim.version.range({spec}) *vim.version.range()*
Parses a semver |version-range| "spec" and returns a range object: >
@@ -3194,44 +3751,46 @@ vim.version.range({spec}) *vim.version.range()*
print(r:has(vim.version())) -- check against current Nvim version
<
- Or use cmp(), eq(), lt(), and gt() to compare `.to` and `.from` directly: >lua
- local r = vim.version.range('1.0.0 - 2.0.0')
- print(vim.version.gt({1,0,3}, r.from) and vim.version.lt({1,0,3}, r.to))
+ Or use cmp(), le(), lt(), ge(), gt(), and/or eq() to compare a version
+ against `.to` and `.from` directly: >lua
+ local r = vim.version.range('1.0.0 - 2.0.0') -- >=1.0, <2.0
+ print(vim.version.ge({1,0,3}, r.from) and vim.version.lt({1,0,3}, r.to))
<
Parameters: ~
- • {spec} (string) Version range "spec"
+ • {spec} (`string`) Version range "spec"
+
+ Return: ~
+ (`table?`) A table with the following fields:
+ • {from} (`vim.Version`)
+ • {to}? (`vim.Version`)
+ • {has} (`fun(self: vim.VersionRangeversion: string|vim.Version)`)
See also: ~
- • # https://github.com/npm/node-semver#ranges
+ • https://github.com/npm/node-semver#ranges
==============================================================================
Lua module: vim.iter *vim.iter*
-
*vim.iter()* is an interface for |iterable|s: it wraps a table or function
argument into an *Iter* object with methods (such as |Iter:filter()| and
-|Iter:map()|) that transform the underlying source data. These methods can
-be chained to create iterator "pipelines": the output of each pipeline
-stage is input to the next stage. The first stage depends on the type
-passed to `vim.iter()`:
-
+|Iter:map()|) that transform the underlying source data. These methods can be
+chained to create iterator "pipelines": the output of each pipeline stage is
+input to the next stage. The first stage depends on the type passed to
+`vim.iter()`:
• List tables (arrays, |lua-list|) yield only the value of each element.
• Use |Iter:enumerate()| to also pass the index to the next stage.
• Or initialize with ipairs(): `vim.iter(ipairs(…))`.
-
-• Non-list tables (|lua-dict|) yield both the key and value of each
- element.
-• Function |iterator|s yield all values returned by the underlying
- function.
+• Non-list tables (|lua-dict|) yield both the key and value of each element.
+• Function |iterator|s yield all values returned by the underlying function.
• Tables with a |__call()| metamethod are treated as function iterators.
-The iterator pipeline terminates when the underlying |iterable| is
-exhausted (for function iterators this means it returned nil).
+The iterator pipeline terminates when the underlying |iterable| is exhausted
+(for function iterators this means it returned nil).
-Note: `vim.iter()` scans table input to decide if it is a list or a dict;
-to avoid this cost you can wrap the table with an iterator e.g.
+Note: `vim.iter()` scans table input to decide if it is a list or a dict; to
+avoid this cost you can wrap the table with an iterator e.g.
`vim.iter(ipairs({…}))`, but that precludes the use of |list-iterator|
operations such as |Iter:rev()|).
@@ -3272,26 +3831,26 @@ Examples: >lua
rb:push("b")
vim.iter(rb):totable()
-- { "a", "b" }
-
<
In addition to the |vim.iter()| function, the |vim.iter| module provides
convenience functions like |vim.iter.filter()| and |vim.iter.totable()|.
-filter({f}, {src}, {...}) *vim.iter.filter()*
+
+filter({f}, {src}) *vim.iter.filter()*
Filters a table or other |iterable|. >lua
-- Equivalent to:
vim.iter(src):filter(f):totable()
<
Parameters: ~
- • {f} function(...):bool Filter function. Accepts the current
+ • {f} (`fun(...):boolean`) Filter function. Accepts the current
iterator or table values as arguments and returns true if those
values should be kept in the final table
- • {src} table|function Table or iterator function to filter
+ • {src} (`table|function`) Table or iterator function to filter
Return: ~
- (table)
+ (`table`)
See also: ~
• |Iter:filter()|
@@ -3300,7 +3859,7 @@ Iter:all({pred}) *Iter:all()*
Returns true if all items in the iterator match the given predicate.
Parameters: ~
- • {pred} function(...):bool Predicate function. Takes all values
+ • {pred} (`fun(...):boolean`) Predicate function. Takes all values
returned from the previous stage in the pipeline as arguments
and returns true if the predicate matches.
@@ -3309,7 +3868,7 @@ Iter:any({pred}) *Iter:any()*
predicate.
Parameters: ~
- • {pred} function(...):bool Predicate function. Takes all values
+ • {pred} (`fun(...):boolean`) Predicate function. Takes all values
returned from the previous stage in the pipeline as arguments
and returns true if the predicate matches.
@@ -3321,7 +3880,7 @@ Iter:each({f}) *Iter:each()*
|Iter:map()|.
Parameters: ~
- • {f} function(...) Function to execute for each item in the pipeline.
+ • {f} (`fun(...)`) Function to execute for each item in the pipeline.
Takes all of the values returned by the previous stage in the
pipeline as arguments.
@@ -3340,15 +3899,15 @@ Iter:enumerate() *Iter:enumerate()*
Example: >lua
local it = vim.iter(vim.gsplit('abc', '')):enumerate()
it:next()
- -- 1 'a'
+ -- 1 'a'
it:next()
- -- 2 'b'
+ -- 2 'b'
it:next()
- -- 3 'c'
+ -- 3 'c'
<
Return: ~
- Iter
+ (`Iter`)
Iter:filter({f}) *Iter:filter()*
Filters an iterator pipeline.
@@ -3358,12 +3917,12 @@ Iter:filter({f}) *Iter:filter()*
<
Parameters: ~
- • {f} function(...):bool Takes all values returned from the previous
+ • {f} (`fun(...):boolean`) Takes all values returned from the previous
stage in the pipeline and returns false or nil if the current
iterator element should be removed.
Return: ~
- Iter
+ (`Iter`)
Iter:find({f}) *Iter:find()*
Find the first value in the iterator that satisfies the given predicate.
@@ -3385,8 +3944,33 @@ Iter:find({f}) *Iter:find()*
-- 12
<
+ Parameters: ~
+ • {f} (`any`)
+
+ Return: ~
+ (`any`)
+
+Iter:flatten({depth}) *Iter:flatten()*
+ Flattens a |list-iterator|, un-nesting nested values up to the given
+ {depth}. Errors if it attempts to flatten a dict-like value.
+
+ Examples: >lua
+ vim.iter({ 1, { 2 }, { { 3 } } }):flatten():totable()
+ -- { 1, 2, { 3 } }
+
+ vim.iter({1, { { a = 2 } }, { 3 } }):flatten():totable()
+ -- { 1, { a = 2 }, 3 }
+
+ vim.iter({ 1, { { a = 2 } }, { 3 } }):flatten(math.huge):totable()
+ -- error: attempt to flatten a dict-like table
+<
+
+ Parameters: ~
+ • {depth} (`number?`) Depth to which |list-iterator| should be
+ flattened (defaults to 1)
+
Return: ~
- any
+ (`Iter`)
Iter:fold({init}, {f}) *Iter:fold()*
Folds ("reduces") an iterator into a single value.
@@ -3404,11 +3988,24 @@ Iter:fold({init}, {f}) *Iter:fold()*
<
Parameters: ~
- • {init} any Initial value of the accumulator.
- • {f} function(acc:any, ...):A Accumulation function.
+ • {init} (`any`) Initial value of the accumulator.
+ • {f} (`fun(acc:A, ...):A`) Accumulation function.
Return: ~
- any
+ (`any`)
+
+Iter:join({delim}) *Iter:join()*
+ Collect the iterator into a delimited string.
+
+ Each element in the iterator is joined into a string separated by {delim}.
+
+ Consumes the iterator.
+
+ Parameters: ~
+ • {delim} (`string`) Delimiter
+
+ Return: ~
+ (`string`)
Iter:last() *Iter:last()*
Drains the iterator and returns the last item.
@@ -3424,7 +4021,7 @@ Iter:last() *Iter:last()*
<
Return: ~
- any
+ (`any`)
Iter:map({f}) *Iter:map()*
Maps the items of an iterator pipeline to the values returned by `f`.
@@ -3442,13 +4039,13 @@ Iter:map({f}) *Iter:map()*
<
Parameters: ~
- • {f} function(...):any Mapping function. Takes all values returned
- from the previous stage in the pipeline as arguments and returns
- one or more new values, which are used in the next pipeline
- stage. Nil return values are filtered from the output.
+ • {f} (`fun(...):any`) Mapping function. Takes all values returned from
+ the previous stage in the pipeline as arguments and returns one
+ or more new values, which are used in the next pipeline stage.
+ Nil return values are filtered from the output.
Return: ~
- Iter
+ (`Iter`)
Iter:next() *Iter:next()*
Gets the next value from the iterator.
@@ -3464,7 +4061,7 @@ Iter:next() *Iter:next()*
<
Return: ~
- any
+ (`any`)
Iter:nextback() *Iter:nextback()*
"Pops" a value from a |list-iterator| (gets the last value and decrements
@@ -3479,7 +4076,7 @@ Iter:nextback() *Iter:nextback()*
<
Return: ~
- any
+ (`any`)
Iter:nth({n}) *Iter:nth()*
Gets the nth value of an iterator (and advances to it).
@@ -3493,10 +4090,10 @@ Iter:nth({n}) *Iter:nth()*
<
Parameters: ~
- • {n} (number) The index of the value to return.
+ • {n} (`number`) The index of the value to return.
Return: ~
- any
+ (`any`)
Iter:nthback({n}) *Iter:nthback()*
Gets the nth value from the end of a |list-iterator| (and advances to it).
@@ -3510,10 +4107,10 @@ Iter:nthback({n}) *Iter:nthback()*
<
Parameters: ~
- • {n} (number) The index of the value to return.
+ • {n} (`number`) The index of the value to return.
Return: ~
- any
+ (`any`)
Iter:peek() *Iter:peek()*
Gets the next value in a |list-iterator| without consuming it.
@@ -3529,7 +4126,7 @@ Iter:peek() *Iter:peek()*
<
Return: ~
- any
+ (`any`)
Iter:peekback() *Iter:peekback()*
Gets the last value of a |list-iterator| without consuming it.
@@ -3547,7 +4144,7 @@ Iter:peekback() *Iter:peekback()*
<
Return: ~
- any
+ (`any`)
Iter:rev() *Iter:rev()*
Reverses a |list-iterator| pipeline.
@@ -3559,7 +4156,7 @@ Iter:rev() *Iter:rev()*
<
Return: ~
- Iter
+ (`Iter`)
Iter:rfind({f}) *Iter:rfind()*
Gets the first value in a |list-iterator| that satisfies a predicate,
@@ -3571,13 +4168,16 @@ Iter:rfind({f}) *Iter:rfind()*
Examples: >lua
local it = vim.iter({ 1, 2, 3, 2, 1 }):enumerate()
it:rfind(1)
- -- 5 1
+ -- 5 1
it:rfind(1)
- -- 1 1
+ -- 1 1
<
+ Parameters: ~
+ • {f} (`any`)
+
Return: ~
- any
+ (`any`)
See also: ~
• Iter.find
@@ -3592,10 +4192,10 @@ Iter:skip({n}) *Iter:skip()*
<
Parameters: ~
- • {n} (number) Number of values to skip.
+ • {n} (`number`) Number of values to skip.
Return: ~
- Iter
+ (`Iter`)
Iter:skipback({n}) *Iter:skipback()*
Skips `n` values backwards from the end of a |list-iterator| pipeline.
@@ -3609,10 +4209,10 @@ Iter:skipback({n}) *Iter:skipback()*
<
Parameters: ~
- • {n} (number) Number of values to skip.
+ • {n} (`number`) Number of values to skip.
Return: ~
- Iter
+ (`Iter`)
Iter:slice({first}, {last}) *Iter:slice()*
Sets the start and end of a |list-iterator| pipeline.
@@ -3620,11 +4220,30 @@ Iter:slice({first}, {last}) *Iter:slice()*
Equivalent to `:skip(first - 1):skipback(len - last + 1)`.
Parameters: ~
- • {first} (number)
- • {last} (number)
+ • {first} (`number`)
+ • {last} (`number`)
Return: ~
- Iter
+ (`Iter`)
+
+Iter:take({n}) *Iter:take()*
+ Transforms an iterator to yield only the first n values.
+
+ Example: >lua
+ local it = vim.iter({ 1, 2, 3, 4 }):take(2)
+ it:next()
+ -- 1
+ it:next()
+ -- 2
+ it:next()
+ -- nil
+<
+
+ Parameters: ~
+ • {n} (`integer`)
+
+ Return: ~
+ (`Iter`)
Iter:totable() *Iter:totable()*
Collect the iterator into a table.
@@ -3650,37 +4269,37 @@ Iter:totable() *Iter:totable()*
|Iter:fold()|.
Return: ~
- (table)
+ (`table`)
-map({f}, {src}, {...}) *vim.iter.map()*
+map({f}, {src}) *vim.iter.map()*
Maps a table or other |iterable|. >lua
-- Equivalent to:
vim.iter(src):map(f):totable()
<
Parameters: ~
- • {f} function(...):?any Map function. Accepts the current iterator
+ • {f} (`fun(...): any?`) Map function. Accepts the current iterator
or table values as arguments and returns one or more new
values. Nil values are removed from the final table.
- • {src} table|function Table or iterator function to filter
+ • {src} (`table|function`) Table or iterator function to filter
Return: ~
- (table)
+ (`table`)
See also: ~
• |Iter:map()|
-totable({f}, {...}) *vim.iter.totable()*
+totable({f}) *vim.iter.totable()*
Collects an |iterable| into a table. >lua
-- Equivalent to:
vim.iter(f):totable()
<
Parameters: ~
- • {f} (function) Iterator function
+ • {f} (`function`) Iterator function
Return: ~
- (table)
+ (`table`)
==============================================================================
@@ -3690,18 +4309,20 @@ vim.snippet.active() *vim.snippet.active()*
Returns `true` if there's an active snippet in the current buffer.
Return: ~
- (boolean)
+ (`boolean`)
vim.snippet.exit() *vim.snippet.exit()*
Exits the current snippet.
vim.snippet.expand({input}) *vim.snippet.expand()*
- Expands the given snippet text. Refer to https://microsoft.github.io/language-server-protocol/specification/#snippet_syntax for the specification of valid input.
+ Expands the given snippet text. Refer to
+ https://microsoft.github.io/language-server-protocol/specification/#snippet_syntax
+ for the specification of valid input.
Tabstops are highlighted with hl-SnippetTabstop.
Parameters: ~
- • {input} (string)
+ • {input} (`string`)
vim.snippet.jump({direction}) *vim.snippet.jump()*
Jumps within the active snippet in the given direction. If the jump isn't
@@ -3718,7 +4339,7 @@ vim.snippet.jump({direction}) *vim.snippet.jump()*
<
Parameters: ~
- • {direction} (vim.snippet.Direction) Navigation direction. -1 for
+ • {direction} (`vim.snippet.Direction`) Navigation direction. -1 for
previous, 1 for next.
vim.snippet.jumpable({direction}) *vim.snippet.jumpable()*
@@ -3735,11 +4356,11 @@ vim.snippet.jumpable({direction}) *vim.snippet.jumpable()*
<
Parameters: ~
- • {direction} (vim.snippet.Direction) Navigation direction. -1 for
+ • {direction} (`vim.snippet.Direction`) Navigation direction. -1 for
previous, 1 for next.
Return: ~
- (boolean)
+ (`boolean`)
==============================================================================
@@ -3749,18 +4370,50 @@ vim.text.hexdecode({enc}) *vim.text.hexdecode()*
Hex decode a string.
Parameters: ~
- • {enc} (string) String to decode
+ • {enc} (`string`) String to decode
Return: ~
- (string) Decoded string
+ (`string`) Decoded string
vim.text.hexencode({str}) *vim.text.hexencode()*
Hex encode a string.
Parameters: ~
- • {str} (string) String to encode
+ • {str} (`string`) String to encode
Return: ~
- (string) Hex encoded string
+ (`string`) Hex encoded string
+
+
+==============================================================================
+Lua module: tohtml *vim.tohtml*
+
+
+:TOhtml {file} *:TOhtml*
+Converts the buffer shown in the current window to HTML, opens the generated
+HTML in a new split window, and saves its contents to {file}. If {file} is not
+given, a temporary file (created by |tempname()|) is used.
+
+
+tohtml.tohtml({winid}, {opt}) *tohtml.tohtml.tohtml()*
+ Converts the buffer shown in the window {winid} to HTML and returns the
+ output as a list of string.
+
+ Parameters: ~
+ • {winid} (`integer?`) Window to convert (defaults to current window)
+ • {opt} (`table?`) Optional parameters.
+ • {title}? (`string|false`, default: buffer name) Title tag
+ to set in the generated HTML code.
+ • {number_lines}? (`boolean`, default: `false`) Show line
+ numbers.
+ • {font}? (`string[]|string`, default: `guifont`) Fonts to
+ use.
+ • {width}? (`integer`, default: 'textwidth' if non-zero or
+ window width otherwise) Width used for items which are
+ either right aligned or repeat a character infinitely.
+
+ Return: ~
+ (`string[]`)
+
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/doc/luaref.txt b/runtime/doc/luaref.txt
index 467b5760cf..e7b62f4c6c 100644
--- a/runtime/doc/luaref.txt
+++ b/runtime/doc/luaref.txt
@@ -4150,7 +4150,7 @@ string.upper({s}) *string.upper()*
locale.
------------------------------------------------------------------------------
-5.4.1 Patterns *lua-patterns
+5.4.1 Patterns *lua-patterns*
A character class is used to represent a set of characters. The following
combinations are allowed in describing a character class:
@@ -4811,7 +4811,7 @@ debug.setupvalue({func}, {up}, {value}) *debug.setupvalue()*
upvalue with the given index. Otherwise, it returns the name of the
upvalue.
-debug.traceback([{thread},] [{message}] [,{level}]) *debug.traceback()*
+debug.traceback([{thread},] [{message} [,{level}]]) *debug.traceback()*
Returns a string with a traceback of the call stack. An optional
{message} string is appended at the beginning of the traceback. An
optional {level} number tells at which level to start the traceback
diff --git a/runtime/doc/luvref.txt b/runtime/doc/luvref.txt
index 915b69efe3..2be73f0412 100644
--- a/runtime/doc/luvref.txt
+++ b/runtime/doc/luvref.txt
@@ -837,7 +837,7 @@ uv.new_prepare() *uv.new_prepare()*
Creates and initializes a new |uv_prepare_t|. Returns the Lua
userdata wrapping it.
- Returns: `uv_prepare_t userdata` or `fail`
+ Returns: `uv_prepare_t userdata`
uv.prepare_start({prepare}, {callback}) *uv.prepare_start()*
@@ -882,7 +882,7 @@ uv.new_check() *uv.new_check()*
Creates and initializes a new |uv_check_t|. Returns the Lua
userdata wrapping it.
- Returns: `uv_check_t userdata` or `fail`
+ Returns: `uv_check_t userdata`
uv.check_start({check}, {callback}) *uv.check_start()*
@@ -934,7 +934,7 @@ uv.new_idle() *uv.new_idle()*
Creates and initializes a new |uv_idle_t|. Returns the Lua
userdata wrapping it.
- Returns: `uv_idle_t userdata` or `fail`
+ Returns: `uv_idle_t userdata`
uv.idle_start({idle}, {callback}) *uv.idle_start()*
@@ -977,15 +977,15 @@ called from another thread.
async:send()
<
-uv.new_async([{callback}]) *uv.new_async()*
+uv.new_async({callback}) *uv.new_async()*
Parameters:
- - `callback`: `callable` or `nil`
+ - `callback`: `callable`
- `...`: `threadargs` passed to/from
`uv.async_send(async, ...)`
Creates and initializes a new |uv_async_t|. Returns the Lua
- userdata wrapping it. A `nil` callback is allowed.
+ userdata wrapping it.
Returns: `uv_async_t userdata` or `fail`
@@ -2067,17 +2067,17 @@ uv.pipe({read_flags}, {write_flags}) *uv.pipe()*
uv.pipe_bind2({pipe}, {name}, {flags}) *uv.pipe_bind2()*
> method form `pipe:pipe_bind(name, flags)`
-
+
Parameters:
- `pipe`: `uv_pipe_t userdata`
- `name`: `string`
- - `flags`: `integer` or `table` or `nil`(default: 0)
+ - `flags`: `integer` or `table` or `nil` (default: 0)
Flags:
- If `type(flags)` is `number`, it must be `0` or
`uv.constants.PIPE_NO_TRUNCATE`.
- If `type(flags)` is `table`, it must be `{}` or
- `{ no_trunate = true|false }`.
+ `{ no_truncate = true|false }`.
- If `type(flags)` is `nil`, it use default value `0`.
- Returns `EINVAL` for unsupported flags without performing the
bind.
@@ -2101,7 +2101,7 @@ uv.pipe_connect2(pipe, name, [flags], [callback]) *uv.pipe_connect2()*
Parameters:
- `pipe`: `uv_pipe_t userdata`
- `name`: `string`
- - `flags`: `integer` or `table` or `nil`(default: 0)
+ - `flags`: `integer` or `table` or `nil` (default: 0)
- `callback`: `callable` or `nil`
- `err`: `nil` or `string`
@@ -2110,7 +2110,7 @@ uv.pipe_connect2(pipe, name, [flags], [callback]) *uv.pipe_connect2()*
- If `type(flags)` is `number`, it must be `0` or
`uv.constants.PIPE_NO_TRUNCATE`.
- If `type(flags)` is `table`, it must be `{}` or
- `{ no_trunate = true|false }`.
+ `{ no_truncate = true|false }`.
- If `type(flags)` is `nil`, it use default value `0`.
- Returns `EINVAL` for unsupported flags without performing the
bind operation.
@@ -3630,6 +3630,42 @@ uv.thread_getcpu() *uv.thread_getcpu()*
Returns: `integer` or `fail`
+uv.thread_setpriority({thread}, {priority}) *uv.thread.setpriority()*
+
+ > method form `thread:setpriority(priority)`
+
+ Parameters:
+ - `thread`: `luv_thread_t userdata`
+ - `priority`: `number`
+
+ Sets the specified thread's scheduling priority setting. It
+ requires elevated privilege to set specific priorities on some
+ platforms. The priority can be set to the following constants:
+ - `uv.constants.THREAD_PRIORITY_HIGHEST`
+ - `uv.constants.THREAD_PRIORITY_ABOVE_NORMAL`
+ - `uv.constants.THREAD_PRIORITY_NORMAL`
+ - `uv.constants.THREAD_PRIORITY_BELOW_NORMAL`
+ - `uv.constants.THREAD_PRIORITY_LOWEST`
+
+ Returns: `boolean` or `fail`
+
+uv.thread_getpriority({thread}) *uv.thread.getpriority()*
+
+ > method form `thread:getpriority()`
+
+ Parameters:
+ - `thread`: `luv_thread_t userdata`
+
+ Gets the thread's priority setting.
+
+ Retrieves the scheduling priority of the specified thread. The
+ returned priority value is platform dependent.
+
+ For Linux, when schedule policy is SCHED_OTHER (default),
+ priority is 0.
+
+ Returns: `number` or `fail`
+
uv.thread_self() *uv.thread_self()*
Returns the handle for the thread in which this is called.
diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt
index 6f61259af0..68206dd494 100644
--- a/runtime/doc/map.txt
+++ b/runtime/doc/map.txt
@@ -849,8 +849,15 @@ For the Meta modifier the "T" character is used. For example, to map Meta-b
in Insert mode: >
:imap <T-b> terrible
+1.12 MAPPING SUPER-KEYS or COMMAND-KEYS *:map-super-keys* *:map-cmd-key*
-1.12 MAPPING AN OPERATOR *:map-operator*
+The Super / Command modifier is available if the terminal or GUI supports it.
+The character "D" is used for the Super / Command modifier.
+
+For example, to map Command-b in Insert mode: >
+ :imap <D-b> barritone
+
+1.13 MAPPING AN OPERATOR *:map-operator*
An operator is used before a {motion} command. To define your own operator
you must create a mapping that first sets the 'operatorfunc' option and then
@@ -1389,6 +1396,7 @@ completion can be enabled:
-complete=help help subjects
-complete=highlight highlight groups
-complete=history :history suboptions
+ -complete=keymap keyboard mappings
-complete=locale locale names (as output of locale -a)
-complete=lua Lua expression |:lua|
-complete=mapclear buffer argument
diff --git a/runtime/doc/message.txt b/runtime/doc/message.txt
index 9f06e8c931..c3154fc372 100644
--- a/runtime/doc/message.txt
+++ b/runtime/doc/message.txt
@@ -127,8 +127,6 @@ This happens when an Ex command executes an Ex command that executes an Ex
command, etc. The limit is 200 or the value of 'maxfuncdepth', whatever is
larger. When it's more there probably is an endless loop. Probably a
|:execute| or |:source| command is involved.
-Can also happen with a recursive callback function (|channel-callback|).
-A limit of 20 is used here.
*E254* >
Cannot allocate color {name}
diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt
index aa18e44225..e80969c583 100644
--- a/runtime/doc/motion.txt
+++ b/runtime/doc/motion.txt
@@ -578,7 +578,8 @@ i] *v_i]* *v_i[* *i]* *i[*
i[ "inner [] block", select [count] '[' ']' blocks. This
goes backwards to the [count] unclosed '[', and finds
the matching ']'. The enclosed text is selected,
- excluding the '[' and ']'. The |cpo-M| option flag
+ excluding the '[' and ']'. It's an error to select an
+ empty inner block like "[]". The |cpo-M| option flag
is used to handle escaped brackets.
When used in Visual mode it is made charwise.
@@ -596,7 +597,8 @@ i( *vib* *v_ib* *v_i(* *ib*
ib "inner block", select [count] blocks, from "[count] [("
to the matching ')', excluding the '(' and ')' (see
|[(|). If the cursor is not inside a () block, then
- find the next "(". The |cpo-M| option flag
+ find the next "(". It's an error to select an empty
+ inner block like "()". The |cpo-M| option flag
is used to handle escaped parenthesis.
When used in Visual mode it is made charwise.
@@ -610,8 +612,9 @@ a< "a <> block", select [count] <> blocks, from the
i> *v_i>* *v_i<* *i>* *i<*
i< "inner <> block", select [count] <> blocks, from
the [count]'th unmatched '<' backwards to the matching
- '>', excluding the '<' and '>'. The |cpo-M| option flag
- is used to handle escaped '<' and '>'.
+ '>', excluding the '<' and '>'. It's an error to
+ select an empty inner block like "<>". The |cpo-M|
+ option flag is used to handle escaped '<' and '>'.
When used in Visual mode it is made charwise.
*v_at* *at*
@@ -640,7 +643,8 @@ i} *v_i}* *i}* *i{*
i{ *v_iB* *v_i{* *iB*
iB "inner Block", select [count] Blocks, from `[count] [{`
to the matching "}", excluding the "{" and "}" (see
- |[{|). The |cpo-M| option flag is used to handle
+ |[{|). It"s an error to select an empty inner block
+ like "{}". The |cpo-M| option flag is used to handle
escaped braces.
When used in Visual mode it is made charwise.
@@ -1044,7 +1048,7 @@ CTRL-I Go to [count] newer cursor position in jump list
|tui-modifyOtherKeys| or |tui-csiu|, CTRL-I can be
mapped separately from <Tab>, on the condition that
both keys are mapped, otherwise the mapping applies to
- both.
+ both. Except in tmux: https://github.com/tmux/tmux/issues/2705
*:ju* *:jumps*
:ju[mps] Print the jump list (not a motion command).
@@ -1292,14 +1296,12 @@ bring you back to the switch statement.
]m Go to [count] next start of a method (for Java or
similar structured language). When not before the
start of a method, jump to the start or end of the
- class. When no '{' is found after the cursor, this is
- an error. |exclusive| motion.
+ class. |exclusive| motion.
*]M*
]M Go to [count] next end of a method (for Java or
similar structured language). When not before the end
of a method, jump to the start or end of the class.
- When no '}' is found after the cursor, this is an
- error. |exclusive| motion.
+ |exclusive| motion.
*[m*
[m Go to [count] previous start of a method (for Java or
similar structured language). When not after the
diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt
index 825e5ba41f..3029414500 100644
--- a/runtime/doc/news.txt
+++ b/runtime/doc/news.txt
@@ -15,7 +15,7 @@ BREAKING CHANGES *news-breaking*
The following changes may require adaptations in user config or plugins.
-• In some cases, the cursor in the Nvim |TUI| would blink even without
+• In some cases, the cursor in the Nvim |TUI| used to blink even without
configuring 'guicursor' as mentioned in |cursor-blinking|. This was a bug
that has now been fixed. If your cursor has stopped blinking, add the
following (or similar, adapted to user preference) to your |config| file: >vim
@@ -71,9 +71,6 @@ The following changes may require adaptations in user config or plugins.
now requires an explicit range argument to be passed. If injections are
required, provide an explicit range via `parser:parse({ start_row, end_row })`.
-• Float window support hide and show by setting `hide` on `nvim_open_win` and
- `nvim_win_set_config`.
-
• |vim.lsp.util.parse_snippet()| will now strictly follow the snippet grammar
defined by LSP, and hence previously parsed snippets might now be considered
invalid input.
@@ -95,14 +92,59 @@ The following changes may require adaptations in user config or plugins.
• Legacy and extmark signs are displayed and listed with the same priority:
line number -> priority -> sign id -> recently placed
+• Default color scheme has been updated to be "Nvim branded" and accessible.
+ Use `:colorscheme vim` to revert to the old legacy color scheme.
+
+ Here is a list of Nvim specific highlight groups which are now defined in
+ a meaningfully different way and might need an update:
+ • |hl-FloatBorder| is linked to |hl-NormalFloat| instead of |hl-WinSeparator|.
+ • |hl-NormalFloat| is not linked to |hl-Pmenu|.
+ • |hl-WinBar| has different background.
+ • |hl-WinBarNC| is similar to |hl-WinBar| but not bold.
+ • |hl-WinSeparator| is linked to |hl-Normal| instead of |hl-VertSplit|.
+
+ This also might result into some color schemes looking differently due to
+ them relying on implicit assumptions about how highlight groups are defined
+ by default. To account for this, define all attributes of highlight groups
+ explicitly. Alternatively, use `:colorscheme vim` or `:source
+ $VIMRUNTIME/colors/vim.lua` to restore previous definitions.
+
+• 'termguicolors' is enabled by default when Nvim is able to determine that
+ the host terminal emulator supports 24-bit color.
+
+• Treesitter highlight groups have been renamed to be more in line with
+ upstream tree-sitter and Helix to make it easier to share queries. The full
+ list is documented in |treesitter-highlight-groups|.
+
+• |vim.lsp.codelens.refresh()| now takes an `opts` argument. With this change,
+ the default behavior of just refreshing the current buffer has been replaced by
+ refreshing all buffers.
+
+• |shm-q| now fully hides macro recording message instead of only shortening it.
+
+• Returning any truthy value from a callback passed to |nvim_create_autocmd()|
+ (rather than just `true`) will delete the autocommand.
+
+• |vim.lsp.util.extract_completion_items()| will no longer return reliable
+ results, since it does not apply `itemDefaults` when its input is a
+ `CompletionList`.
+ Moreover, since support for LSP `completionList.itemDefaults` was added,
+ some third party plugins might be negatively impacted in case the language
+ servers support the feature but the plugin does not.
+ If necessary, the respective capability can be
+ removed when calling |vim.lsp.protocol.make_client_capabilities()|.
+
+• |:TOhtml| has been rewritten in Lua to support Neovim-specific decorations,
+ and many options have been removed.
+
==============================================================================
BREAKING CHANGES IN HEAD *news-breaking-dev*
The following breaking changes were made during the development cycle to
unreleased features on Nvim HEAD.
-• ...
-• ...
+• Removed `vim.treesitter.foldtext` as transparent foldtext is now supported
+ https://github.com/neovim/neovim/pull/20750
==============================================================================
NEW FEATURES *news-features*
@@ -115,31 +157,39 @@ The following new APIs and features were added.
• Treesitter highlighting now parses injections incrementally during
screen redraws only for the line range being rendered. This significantly
improves performance in large files with many injections.
+ • 'breakindent' performance is significantly improved for wrapped lines.
+ • Cursor movement, insertion with [count] and |screenpos()| are now faster.
• |vim.iter()| provides a generic iterator interface for tables and Lua
iterators |for-in|.
-• Added |vim.ringbuf()| to create ring buffers.
+• |vim.ringbuf()| creates ring buffers.
-• Added |vim.keycode()| for translating keycodes in a string.
+• |vim.keycode()| translates keycodes in a string.
• |'smoothscroll'| option to scroll by screen line rather than by text line
when |'wrap'| is set.
-• Added inline virtual text support to |nvim_buf_set_extmark()|.
+• |nvim_buf_set_extmark()| supports inline virtual text.
• 'foldtext' now supports virtual text format. |fold-foldtext|
+• |'foldtext'| can be set to an empty string to disable and render the line:
+ as normal with regular highlighting and no line wrapping.
+
• 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.
• |vim.system()| for running system commands.
-• Added |nvim_win_text_height()| to compute the number of screen lines occupied
+• |vim.lpeg| and |vim.re| expose the bundled Lpeg expression grammar parser
+ and its regex interface.
+
+• |nvim_win_text_height()| computes the number of screen lines occupied
by a range of text in a given window.
-• |nvim_set_keymap()| and |nvim_del_keymap()| now support abbreviations.
+• Mapping APIs now support abbreviations when mode short-name has suffix "a".
• Better cmdline completion for string option value. |complete-set-option|
@@ -158,7 +208,7 @@ The following new APIs and features were added.
https://microsoft.github.io/language-server-protocol/specification/#textDocument_inlayHint
• Implemented pull diagnostic textDocument/diagnostic: |vim.lsp.diagnostic.on_diagnostic()|
https://microsoft.github.io/language-server-protocol/specification/#textDocument_diagnostic
- • Added |vim.lsp.status()| to consume the last progress messages as a string.
+ • |vim.lsp.status()| consumes the last progress messages as a string.
• LSP client now always saves and restores named buffer marks when applying
text edits.
• LSP client now supports the `positionEncoding` server capability. If a server
@@ -169,26 +219,39 @@ The following new APIs and features were added.
indicator to see if a server supports a feature. Instead use
`client.supports_method(<method>)`. It considers both the dynamic
capabilities and static `server_capabilities`.
- • Added a new `anchor_bias` option to |lsp-handlers| to aid in positioning of
- floating windows.
+ • `anchor_bias` option to |lsp-handlers| aids in positioning of floating
+ windows.
+ • |vim.lsp.util.locations_to_items()| sets the `user_data` of each item to
+ the original LSP `Location` or `LocationLink`.
+ • Added support for connecting to servers using named pipes (Windows) or
+ unix domain sockets (Unix) via |vim.lsp.rpc.domain_socket_connect()|.
+ • Added support for `completionList.itemDefaults`, reducing overhead when
+ computing completion items where properties often share the same value
+ (e.g. `commitCharacters`). Note that this might affect plugins and
+ language servers that don't support the feature, and in such cases the
+ respective capability can be unset.
• Treesitter
• Bundled parsers and queries (highlight, folds) for Markdown, Python, and
Bash.
- • Added |vim.treesitter.query.omnifunc()| for treesitter query files (set by
+ • |vim.treesitter.query.omnifunc()| for treesitter query files (set by
default).
• |Query:iter_matches()| now has the ability to set the maximum start depth
for matches.
- • `@injection.language` now has smarter resolution and will now fallback to language aliases and/or attempt lower case variants of the text.
- language via aliases (e.g., filetype) registered via
- `vim.treesitter.language.register`.
- • The `#set!` directive now supports `injection.self` and `injection.parent` for injecting either the current node's language
- or the parent LanguageTree's language, respectively.
- • Added `vim.treesitter.query.edit()`, for live editing of treesitter
+ • `@injection.language` now has smarter resolution and will fall back to
+ language aliases (e.g., filetype or custom shorthands) registered via
+ |vim.treesitter.language.register()| and/or attempt lower case variants of
+ the text.
+ • The `#set!` directive now supports `injection.self` and `injection.parent`
+ for injecting either the current node's language or the parent
+ |LanguageTree|'s language, respectively.
+ • |vim.treesitter.query.edit()| allows live editing of treesitter
queries.
• Improved error messages for query parsing.
- • Added |vim.treesitter.foldtext()| to apply treesitter highlighting to
- foldtext.
+ • |:InspectTree| shows node ranges in 0-based indexing instead of 1-based
+ indexing.
+ • |:InspectTree| shows root nodes
+ • |:InspectTree| now supports |folding|
• |vim.ui.open()| opens URIs using the system default handler (macOS `open`,
Windows `explorer`, Linux `xdg-open`, etc.)
@@ -200,34 +263,35 @@ The following new APIs and features were added.
• `vim.*`
• `vim.fn.*`
• `vim.api.*`
+ • `vim.v.*`
• Improved messages for type errors in `vim.api.*` calls (including `opts` params)
• Functions that take a severity as an optional parameter (e.g.
|vim.diagnostic.get()|) now also accept a list of severities |vim.diagnostic.severity|
-• New RPC client type `msgpack-rpc` is added for `nvim_set_client_info` to
+• New RPC client type `msgpack-rpc` is added for |nvim_set_client_info()| to
support fully MessagePack-RPC compliant clients.
• Floating windows can now show footer with new `footer` and `footer_pos`
config fields. Uses |hl-FloatFooter| by default.
-• The |:terminal| command now accepts some |:command-modifiers| (specifically
- |:horizontal| and those that affect splitting a window).
+• Floating windows can now be hidden by setting `hide` in |nvim_open_win()| or
+ |nvim_win_set_config()|.
-• |vim.lsp.util.locations_to_items()| sets the `user_data` of each item to the
- original LSP `Location` or `LocationLink`.
+• |:terminal| command now accepts some |:command-modifiers| (specifically
+ |:horizontal| and those that affect splitting a window).
• |$NVIM_APPNAME| can be set to a relative path instead of only a name.
-• Added |:fclose| command.
+• |:fclose| command.
-• Added |vim.snippet| for snippet expansion support.
+• |vim.snippet| handles expansion of snippets in LSP format.
• 'complete' option supports "f" flag for completing buffer names.
-• Added |vim.base64.encode()| and |vim.base64.decode()| for encoding and decoding
- strings using Base64 encoding.
+• |vim.base64.encode()| and |vim.base64.decode()| encode and decode strings
+ using Base64 encoding.
• The |TermResponse| autocommand event can be used with |v:termresponse| to
read escape sequence responses from the terminal.
@@ -236,11 +300,45 @@ The following new APIs and features were added.
clipboard is now bundled by default and will be automatically enabled under
certain conditions. |clipboard-osc52|
-• The 'termsync' option asks the terminal emulator to buffer screen updates
- until the redraw cycle is complete. Requires support from the terminal.
+• 'termsync' option asks the terminal emulator to buffer screen updates until
+ the redraw cycle is complete. Requires support from the terminal.
+
+• |vim.text.hexencode()| and |vim.text.hexdecode()| convert strings to and
+ from byte representations.
+
+• 'completeopt' option supports "popup" flag to show extra information in a
+ floating window.
+
+• |nvim_input_mouse()| supports mouse buttons "x1" and "x2".
+
+• |v_Q-default| and |v_@-default| repeat a register for each line of a visual
+ selection.
+
+• |vim.diagnostic.count()| returns the number of diagnostics for a given
+ buffer and/or namespace, by severity. This is a faster alternative to
+ |vim.diagnostic.get()| when only the number of diagnostics is needed, but
+ not the diagnostics themselves.
+
+• |vim.deepcopy()| has a `noref` argument to avoid hashing table values.
+
+• Terminal buffers emit a |TermRequest| autocommand event when the child
+ process emits an OSC or DCS control sequence.
-• Added |vim.text.hexencode()| and |vim.text.hexdecode()| to convert strings
- to and from byte representations.
+• Terminal buffers respond to OSC background and foreground requests. |default-autocmds|
+
+• |vim.version.le()| and |vim.version.ge()| are added to |vim.version|.
+
+• |extmarks| can be associated with a URL and URLs are included as a new
+ highlight attribute. The TUI will display URLs using the OSC 8 control
+ sequence, enabling clickable text in supporting terminals.
+
+• Added |nvim_tabpage_set_win()| to set the current window of a tabpage.
+
+• Clicking on a tabpage in the tabline with the middle mouse button closes it.
+
+• |namespace| can now have window scopes. |nvim_win_add_ns()|
+
+• |extmarks| option `scoped`: only show the extmarks in its namespace's scope.
==============================================================================
CHANGED FEATURES *news-changed*
@@ -253,7 +351,7 @@ The following changes to existing APIs or features add new behavior.
• |vim.region()| can use a string accepted by |getpos()| as position.
-• vim.diagnostic.config() now accepts a function for the virtual_text.prefix
+• |vim.diagnostic.config()| now accepts a function for the virtual_text.prefix
option, which allows for rendering e.g., diagnostic severities differently.
• Defaults:
@@ -266,16 +364,24 @@ The following changes to existing APIs or features add new behavior.
vim.g.query_lint_on = {}
<
• Enabled treesitter highlighting for treesitter query files.
+ • Enabled treesitter highlighting for help files.
+ • Enabled treesitter highlighting for Lua files.
• The `workspace/didChangeWatchedFiles` LSP client capability is now enabled
by default.
+ • On Mac or Windows, `libuv.fs_watch` is used as the backend.
+ • On Linux, `fswatch` (recommended) is used as the backend if available,
+ otherwise `libuv.fs_event` is used on each subdirectory.
• |LspRequest| autocmd callbacks now contain additional information about the LSP
request status update that occurred.
-• `:source` without arguments treats a buffer with its 'filetype' set to "lua"
+• |:source| without arguments treats a buffer with its 'filetype' set to "lua"
as Lua code regardless of its extension.
+• |:lua| with a |[range]| executes that range in the current buffer as Lua code
+ regardless of its extension.
+
• |:checkhealth| buffer now implements |folding|. The initial folding status is
defined by the 'foldenable' option.
@@ -283,6 +389,7 @@ The following changes to existing APIs or features add new behavior.
• |gx| now uses |vim.ui.open()| and not netrw. To customize, you can redefine
`vim.ui.open` or remap `gx`. To continue using netrw (deprecated): >vim
+
:call netrw#BrowseX(expand(exists("g:netrw_gx")? g:netrw_gx : '<cfile>'), netrw#CheckIfRemote())<CR>
• |vim.lsp.start()| now maps |K| to use |vim.lsp.buf.hover()| if the server
@@ -307,11 +414,10 @@ The following changes to existing APIs or features add new behavior.
In addition, |nvim_buf_get_extmarks()| has gained an "overlap" option to
return such ranges even if they started before the specified position.
-• Extmarks can opt-out of precise undo tracking using the new "undo_restore"
- flag to |nvim_buf_set_extmark()|
-
-• Extmarks can be automatically hidden or removed using the new "invalidate"
- flag to |nvim_buf_set_extmark()|
+• The following flags were added to |nvim_buf_set_extmark()|:
+ - "undo_restore": opt-out extmarks of precise undo tracking.
+ - "invalidate": automatically hide or delete extmarks.
+ - "virt_text_repeat_linebreak": repeat virtual text on wrapped lines.
• LSP hover and signature help now use Treesitter for highlighting of Markdown
content.
@@ -327,17 +433,50 @@ The following changes to existing APIs or features add new behavior.
• |vim.wait()| is no longer allowed to be called in |api-fast|.
+• Vimscript function |exists()| supports checking |v:lua| functions.
+
+• Added "force_crlf" option field in |nvim_open_term()|.
+
+• Attempting to set an invalid keycode option (e.g. `set t_foo=123`) no longer
+ gives an error.
+
+• Passing 0 to |nvim_get_chan_info()| gets info about the current channel.
+
+• |:checkhealth| buffer can now be opened in a split window using modifiers like
+ |:vertical|, |:horizontal| and |:botright|.
+
+• |nvim_open_win()| and |nvim_win_set_config()| now support opening normal (split)
+ windows, and moving floating windows into split windows.
+
+• 'errorfile' (|-q|) accepts `-` as an alias for stdin.
+
+• |--startuptime| reports the startup times for both processes (TUI + server) as separate sections.
+
+• |nvim_buf_call()| and |nvim_win_call()| now preserves any return value (NB: not multiple return values)
+
+• Treesitter
+ • |Query:iter_matches()|, |vim.treesitter.query.add_predicate()|, and
+ |vim.treesitter.query.add_directive()| accept a new `all` option which
+ ensures that all matching nodes are returned as a table. The default option
+ `all=false` returns only a single node, breaking captures with quantifiers
+ like `(comment)+ @comment; it is only provided for backward compatibility
+ and will be removed after Nvim 0.10.
+ • |vim.treesitter.query.add_predicate()| and
+ |vim.treesitter.query.add_directive()| now accept an options table rather
+ than a boolean "force" argument. To force a predicate or directive to
+ override an existing predicate or directive, use `{ force = true }`.
+
==============================================================================
REMOVED FEATURES *news-removed*
The following deprecated functions or APIs were removed.
-• Vimball support is removed.
- - :Vimuntar command removed.
+• Vimball support
+ - :Vimuntar command
-• Support for legacy treesitter injection queries is removed.
+• Support for legacy treesitter injection queries
-• Removed 'shortmess' flags:
+• 'shortmess' flags:
- |shm-f|. Always uses "(3 of 5)", never "(file 3 of 5)"
- |shm-i|. Always use "[noeol]".
- |shm-x|. Always use "[dos]", "[unix]" and "[mac]"
@@ -349,6 +488,9 @@ DEPRECATIONS *news-deprecations*
The following functions are now deprecated and will be removed in a future
release.
+• Configuring |diagnostic-signs| using |:sign-define| or |sign_define()|. Use
+ the "signs" key of |vim.diagnostic.config()| instead.
+
• Checkhealth functions:
- |health#report_error|, |vim.health.report_error()| Use |vim.health.error()| instead.
- |health#report_info|, |vim.health.report_info()| Use |vim.health.info()| instead.
@@ -375,13 +517,16 @@ release.
- |vim.lsp.util.parse_snippet()|
- |vim.lsp.util.text_document_completion_list_to_complete_items()|
-• `vim.loop` has been renamed to `vim.uv`.
+• `vim.loop` has been renamed to |vim.uv|.
-• vim.treesitter.languagetree functions:
+• vim.treesitter functions:
- |LanguageTree:for_each_child()| Use |LanguageTree:children()| (non-recursive) instead.
• The "term_background" UI option |ui-ext-options| is deprecated and no longer
populated. Background color detection is now performed in Lua by the Nvim
core, not the TUI.
+• vim.shared functions:
+ - |vim.tbl_add_reverse_lookup()|
+
vim:tw=78:ts=8:sw=2:et:ft=help:norl:
diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt
index dbc14f5a44..d4e05cee26 100644
--- a/runtime/doc/nvim_terminal_emulator.txt
+++ b/runtime/doc/nvim_terminal_emulator.txt
@@ -140,9 +140,9 @@ Example: >vim
- |'channel'| Terminal PTY |job-id|. Can be used with |chansend()| to send
input to the terminal.
- The |TermClose| event gives the terminal job exit code in the |v:event|
- "status" field. For example, this autocmd closes terminal buffers if the job
- exited without error: >vim
- autocmd TermClose * if !v:event.status | exe 'bdelete! '..expand('<abuf>') | endif
+ "status" field. For example, this autocommand outputs the terminal's exit
+ code to |:messages|: >vim
+ autocmd TermClose * echom 'Terminal exited with status '..v:event.status
Use |jobwait()| to check if the terminal job has finished: >vim
let running = jobwait([&channel], 0)[0] == -1
@@ -240,7 +240,7 @@ gdb window and use a "print" command, e.g.: >
If mouse pointer movements are working, Vim will also show a balloon when the
mouse rests on text that can be evaluated by gdb.
You can also use the "K" mapping that will either use Nvim floating windows
-if available to show the results or print below the status bar.
+to show the results.
Now go back to the source window and put the cursor on the first line after
the for loop, then type: >
@@ -283,8 +283,13 @@ gdb:
`:Run` [args] run the program with [args] or the previous arguments
`:Arguments` {args} set arguments for the next `:Run`
- *:Break* set a breakpoint at the current line; a sign will be displayed
- *:Clear* delete the breakpoint at the current line
+ *:Break* set a breakpoint at the cursor position
+ :Break {position}
+ set a breakpoint at the specified position
+ *:Tbreak* set a temporary breakpoint at the cursor position
+ :Tbreak {position}
+ set a temporary breakpoint at the specified position
+ *:Clear* delete the breakpoint at the cursor position
*:Step* execute the gdb "step" command
*:Over* execute the gdb "next" command (`:Next` is a Vim command)
@@ -315,6 +320,8 @@ Inspecting variables ~
This is similar to using "print" in the gdb window.
You can usually shorten `:Evaluate` to `:Ev`.
+The result is displayed in a floating window.
+You can move the cursor to this window by running `:Evaluate` (or `K`) again.
Navigating stack frames ~
@@ -338,8 +345,8 @@ Other commands ~
*:Asm* jump to the window with the disassembly, create it if there
isn't one
*:Var* jump to the window with the local and argument variables,
- create it if there isn't one. This window updates whenever the
- program is stopped
+ create it if there isn't one. This window updates whenever the
+ program is stopped
Events ~
*termdebug-events*
@@ -470,10 +477,6 @@ If the command needs an argument use a List: >vim
If there is no g:termdebug_config you can use: >vim
let g:termdebugger = ['rr', 'replay', '--']
-To not use Nvim floating windows for previewing variable evaluation, set the
-`g:termdebug_useFloatingHover` variable like this: >vim
- let g:termdebug_useFloatingHover = 0
-
If you are a mouse person, you can also define a mapping using your right
click to one of the terminal command like evaluate the variable under the
cursor: >vim
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index f47093782c..edd5149621 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -30,6 +30,7 @@ achieve special effects. These options come in three forms:
*E518* *E519*
:se[t] {option}? Show value of {option}.
+ NOTE: some legacy options were removed. |nvim-removed|
:se[t] {option} Toggle option: set, switch it on.
Number option: show value.
@@ -301,11 +302,24 @@ created, thus they behave slightly differently:
For a global option the global value is
shown (but that might change in the future).
-:setl[ocal] {option}< Set the local value of {option} to its global value by
- copying the value.
-
-:se[t] {option}< For |global-local| options: Remove the local value of
- {option}, so that the global value will be used.
+:se[t] {option}< Set the effective value of {option} to its global
+ value.
+ For string |global-local| options, the local value is
+ removed, so that the global value will be used.
+ For all other options, the global value is copied to
+ the local value.
+
+:setl[ocal] {option}< Set the effective value of {option} to its global
+ value.
+ For number and boolean |global-local| options, the
+ local value is removed, so that the global value will
+ be used.
+ For all other options, including string |global-local|
+ options, the global value is copied to the local
+ value.
+
+Note that the behaviour for |global-local| options is slightly different
+between string and number-based options.
*:setg* *:setglobal*
:setg[lobal][!] ... Like ":set" but set only the global value for a local
@@ -731,8 +745,8 @@ A jump table for the options with a short description can be found at |Q_op|.
from before it was deleted. When it appears again then it is read.
|timestamp|
If this option has a local value, use this command to switch back to
- using the global value: >
- :set autoread<
+ using the global value: >vim
+ set autoread<
<
*'autowrite'* *'aw'* *'noautowrite'* *'noaw'*
@@ -773,23 +787,19 @@ A jump table for the options with a short description can be found at |Q_op|.
See |:hi-normal| if you want to set the background color explicitly.
*g:colors_name*
When a color scheme is loaded (the "g:colors_name" variable is set)
- setting 'background' will cause the color scheme to be reloaded. If
+ changing 'background' will cause the color scheme to be reloaded. If
the color scheme adjusts to the value of 'background' this will work.
However, if the color scheme sets 'background' itself the effect may
be undone. First delete the "g:colors_name" variable when needed.
Normally this option would be set in the vimrc file. Possibly
- depending on the terminal name. Example: >
- :if $TERM ==# "xterm"
- : set background=dark
- :endif
-< When this option is set, the default settings for the highlight groups
+ depending on the terminal name. Example: >vim
+ if $TERM ==# "xterm"
+ set background=dark
+ endif
+< When this option is changed, the default settings for the highlight groups
will change. To use other settings, place ":highlight" commands AFTER
the setting of the 'background' option.
- This option is also used in the "$VIMRUNTIME/syntax/syntax.vim" file
- to select the colors for syntax highlighting. After changing this
- option, you must load syntax.vim again to see the result. This can be
- done with ":syntax on".
*'backspace'* *'bs'*
'backspace' 'bs' string (default "indent,eol,start")
@@ -917,12 +927,12 @@ A jump table for the options with a short description can be found at |Q_op|.
use '//', instead of '\\'.
- Environment variables are expanded |:set_env|.
- Careful with '\' characters, type one before a space, type two to
- get one in the option (see |option-backslash|), for example: >
- :set bdir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
+ get one in the option (see |option-backslash|), for example: >vim
+ set bdir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
<
See also 'backup' and 'writebackup' options.
- If you want to hide your backup files on Unix, consider this value: >
- :set backupdir=./.backup,~/.backup,.,/tmp
+ If you want to hide your backup files on Unix, consider this value: >vim
+ set backupdir=./.backup,~/.backup,.,/tmp
< You must create a ".backup" directory in each directory and in your
home directory for this to work properly.
The use of |:set+=| and |:set-=| is preferred when adding or removing
@@ -943,8 +953,8 @@ A jump table for the options with a short description can be found at |Q_op|.
If you like to keep a lot of backups, you could use a BufWritePre
autocommand to change 'backupext' just before writing the file to
- include a timestamp. >
- :au BufWritePre * let &bex = '-' .. strftime("%Y%b%d%X") .. '~'
+ include a timestamp. >vim
+ au BufWritePre * let &bex = '-' .. strftime("%Y%b%d%X") .. '~'
< Use 'backupdir' to put the backup in a different directory.
*'backupskip'* *'bsk'*
@@ -967,7 +977,7 @@ A jump table for the options with a short description can be found at |Q_op|.
Note that environment variables are not expanded. If you want to use
$HOME you must expand it explicitly, e.g.: >vim
- :let &backupskip = escape(expand('$HOME'), '\') .. '/tmp/*'
+ let &backupskip = escape(expand('$HOME'), '\') .. '/tmp/*'
< Note that the default also makes sure that "crontab -e" works (when a
backup would be made by renaming the original file crontab won't see
@@ -1230,8 +1240,8 @@ A jump table for the options with a short description can be found at |Q_op|.
in the current directory first.
If the default value taken from $CDPATH is not what you want, include
a modified version of the following command in your vimrc file to
- override it: >
- :let &cdpath = ',' .. substitute(substitute($CDPATH, '[, ]', '\\\0', 'g'), ':', ',', 'g')
+ override it: >vim
+ let &cdpath = ',' .. substitute(substitute($CDPATH, '[, ]', '\\\0', 'g'), ':', ',', 'g')
< This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
(parts of 'cdpath' can be passed to the shell to expand file names).
@@ -1242,9 +1252,9 @@ A jump table for the options with a short description can be found at |Q_op|.
The key used in Command-line Mode to open the command-line window.
Only non-printable keys are allowed.
The key can be specified as a single character, but it is difficult to
- type. The preferred way is to use the <> notation. Examples: >
- :exe "set cedit=\<C-Y>"
- :exe "set cedit=\<Esc>"
+ type. The preferred way is to use the <> notation. Examples: >vim
+ exe "set cedit=\<C-Y>"
+ exe "set cedit=\<Esc>"
< |Nvi| also has this option, but it only uses the first character.
See |cmdwin|.
@@ -1274,7 +1284,7 @@ A jump table for the options with a short description can be found at |Q_op|.
Conversion between "latin1", "unicode", "ucs-2", "ucs-4" and "utf-8"
is done internally by Vim, 'charconvert' is not used for this.
Also used for Unicode conversion.
- Example: >
+ Example: >vim
set charconvert=CharConvert()
fun CharConvert()
system("recode "
@@ -1326,7 +1336,7 @@ A jump table for the options with a short description can be found at |Q_op|.
local to buffer
Keywords that are interpreted as a C++ scope declaration by |cino-g|.
Useful e.g. for working with the Qt framework that defines additional
- scope declarations "signals", "public slots" and "private slots": >
+ scope declarations "signals", "public slots" and "private slots": >vim
set cinscopedecls+=signals,public\ slots,private\ slots
<
@@ -1396,11 +1406,11 @@ A jump table for the options with a short description can be found at |Q_op|.
highlighted with ColorColumn |hl-ColorColumn|. Useful to align
text. Will make screen redrawing slower.
The screen column can be an absolute number, or a number preceded with
- '+' or '-', which is added to or subtracted from 'textwidth'. >
+ '+' or '-', which is added to or subtracted from 'textwidth'. >vim
- :set cc=+1 " highlight column after 'textwidth'
- :set cc=+1,+2,+3 " highlight three columns after 'textwidth'
- :hi ColorColumn ctermbg=lightgrey guibg=lightgrey
+ set cc=+1 " highlight column after 'textwidth'
+ set cc=+1,+2,+3 " highlight three columns after 'textwidth'
+ hi ColorColumn ctermbg=lightgrey guibg=lightgrey
<
When 'textwidth' is zero then the items with '-' and '+' are not used.
A maximum of 256 columns are highlighted.
@@ -1417,8 +1427,8 @@ A jump table for the options with a short description can be found at |Q_op|.
number of columns of the display, the display may be messed up. For
the GUI it is always possible and Vim limits the number of columns to
what fits on the screen. You can use this command to get the widest
- window possible: >
- :set columns=9999
+ window possible: >vim
+ set columns=9999
< Minimum value is 12, maximum value is 10000.
*'comments'* *'com'* *E524* *E525*
@@ -1450,8 +1460,8 @@ A jump table for the options with a short description can be found at |Q_op|.
k scan the files given with the 'dictionary' option
kspell use the currently active spell checking |spell|
k{dict} scan the file {dict}. Several "k" flags can be given,
- patterns are valid too. For example: >
- :set cpt=k/usr/dict/*,k~/spanish
+ patterns are valid too. For example: >vim
+ set cpt=k/usr/dict/*,k~/spanish
< s scan the files given with the 'thesaurus' option
s{tsr} scan the file {tsr}. Several "s" flags can be given, patterns
are valid too.
@@ -1507,14 +1517,18 @@ A jump table for the options with a short description can be found at |Q_op|.
completion in the preview window. Only works in
combination with "menu" or "menuone".
- noinsert Do not insert any text for a match until the user selects
+ noinsert Do not insert any text for a match until the user selects
a match from the menu. Only works in combination with
"menu" or "menuone". No effect if "longest" is present.
- noselect Do not select a match in the menu, force the user to
+ noselect Do not select a match in the menu, force the user to
select one from the menu. Only works in combination with
"menu" or "menuone".
+ popup Show extra information about the currently selected
+ completion in a popup window. Only works in combination
+ with "menu" or "menuone". Overrides "preview".
+
*'completeslash'* *'csl'*
'completeslash' 'csl' string (default "")
local to buffer
@@ -1719,9 +1733,6 @@ A jump table for the options with a short description can be found at |Q_op|.
when it didn't exist when editing it. This is a
protection against a file unexpectedly created by
someone else. Vi didn't complain about this.
- *cpo-p*
- p Vi compatible Lisp indenting. When not present, a
- slightly better algorithm is used.
*cpo-P*
P When included, a ":write" command that appends to a
file will set the file name for the current buffer, if
@@ -1848,7 +1859,7 @@ A jump table for the options with a short description can be found at |Q_op|.
|hl-CursorColumn|. Useful to align text. Will make screen redrawing
slower.
If you only want the highlighting in the current window you can use
- these autocommands: >
+ these autocommands: >vim
au WinLeave * set nocursorline nocursorcolumn
au WinEnter * set cursorline cursorcolumn
<
@@ -1911,7 +1922,7 @@ A jump table for the options with a short description can be found at |Q_op|.
< If the function is defined with `func_name : function() {...`: >
^\s*\ze\i\+\s*[:]\s*(*function\s*(
< When using the ":set" command, you need to double the backslashes!
- To avoid that use `:let` with a single quote string: >
+ To avoid that use `:let` with a single quote string: >vim
let &l:define = '^\s*\ze\k\+\s*=\s*function('
<
@@ -2071,11 +2082,11 @@ A jump table for the options with a short description can be found at |Q_op|.
patience patience diff algorithm
histogram histogram diff algorithm
- Examples: >
- :set diffopt=internal,filler,context:4
- :set diffopt=
- :set diffopt=internal,filler,foldcolumn:3
- :set diffopt-=internal " do NOT use the internal diff parser
+ Examples: >vim
+ set diffopt=internal,filler,context:4
+ set diffopt=
+ set diffopt=internal,filler,foldcolumn:3
+ set diffopt-=internal " do NOT use the internal diff parser
<
*'digraph'* *'dg'* *'nodigraph'* *'nodg'*
@@ -2118,8 +2129,8 @@ A jump table for the options with a short description can be found at |Q_op|.
- A directory name may end in an ':' or '/'.
- Environment variables are expanded |:set_env|.
- Careful with '\' characters, type one before a space, type two to
- get one in the option (see |option-backslash|), for example: >
- :set dir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
+ get one in the option (see |option-backslash|), for example: >vim
+ set dir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
<
Editing the same file twice will result in a warning. Using "/tmp" on
is discouraged: if the system crashes you lose the swap file. And
@@ -2264,8 +2275,8 @@ A jump table for the options with a short description can be found at |Q_op|.
A list of autocommand event names, which are to be ignored.
When set to "all" or when "all" is one of the items, all autocommand
events are ignored, autocommands will not be executed.
- Otherwise this is a comma-separated list of event names. Example: >
- :set ei=WinEnter,WinLeave
+ Otherwise this is a comma-separated list of event names. Example: >vim
+ set ei=WinEnter,WinLeave
<
*'expandtab'* *'et'* *'noexpandtab'* *'noet'*
@@ -2347,7 +2358,7 @@ A jump table for the options with a short description can be found at |Q_op|.
will work and the first entry of 'fileencodings' will be used (except
"ucs-bom", which requires the BOM to be present). If you prefer
another encoding use an BufReadPost autocommand event to test if your
- preferred encoding is to be used. Example: >
+ preferred encoding is to be used. Example: >vim
au BufReadPost * if search('\S', 'w') == 0 |
\ set fenc=iso-2022-jp | endif
< This sets 'fileencoding' to "iso-2022-jp" if the file does not contain
@@ -2355,8 +2366,8 @@ A jump table for the options with a short description can be found at |Q_op|.
When the |++enc| argument is used then the value of 'fileencodings' is
not used.
Note that 'fileencodings' is not used for a new file, the global value
- of 'fileencoding' is used instead. You can set it with: >
- :setglobal fenc=iso-8859-2
+ of 'fileencoding' is used instead. You can set it with: >vim
+ setglobal fenc=iso-8859-2
< This means that a non-existing file may get a different encoding than
an empty file.
The special value "ucs-bom" can be used to check for a Unicode BOM
@@ -2468,11 +2479,11 @@ A jump table for the options with a short description can be found at |Q_op|.
this use the ":filetype on" command. |:filetype|
Setting this option to a different value is most useful in a modeline,
for a file for which the file type is not automatically recognized.
- Example, for in an IDL file: >
+ Example, for in an IDL file: >c
/* vim: set filetype=idl : */
< |FileType| |filetypes|
When a dot appears in the value then this separates two filetype
- names. Example: >
+ names. Example: >c
/* vim: set filetype=c.doxygen : */
< This will use the "c" filetype first, then the "doxygen" filetype.
This works both for filetype plugins and for syntax files. More than
@@ -2487,7 +2498,7 @@ A jump table for the options with a short description can be found at |Q_op|.
Characters to fill the statuslines, vertical separators and special
lines in the window.
It is a comma-separated list of items. Each item has a name, a colon
- and the value of that item:
+ and the value of that item: |E1511|
item default Used for ~
stl ' ' statusline of the current window
@@ -2520,12 +2531,12 @@ A jump table for the options with a short description can be found at |Q_op|.
"vert", "vertleft", "vertright", "verthoriz", "foldsep" and "fold"
default to single-byte alternatives.
- Example: >
- :set fillchars=stl:\ ,stlnc:\ ,vert:│,fold:·,diff:-
+ Example: >vim
+ set fillchars=stl:\ ,stlnc:\ ,vert:│,fold:·,diff:-
<
For the "stl", "stlnc", "foldopen", "foldclose" and "foldsep" items
single-byte and multibyte characters are supported. But double-width
- characters are not supported.
+ characters are not supported. |E1512|
The highlighting used for these items:
item highlight group ~
@@ -2716,6 +2727,9 @@ A jump table for the options with a short description can be found at |Q_op|.
It is not allowed to change text or jump to another window while
evaluating 'foldtext' |textlock|.
+ When set to an empty string, foldtext is disabled, and the line
+ is displayed normally with highlighting and no line wrapping.
+
*'formatexpr'* *'fex'*
'formatexpr' 'fex' string (default "")
local to buffer
@@ -2730,8 +2744,8 @@ A jump table for the options with a short description can be found at |Q_op|.
automatic formatting. This can be empty. Don't insert
it yet!
- Example: >
- :set formatexpr=mylang#Format()
+ Example: >vim
+ set formatexpr=mylang#Format()
< This will invoke the mylang#Format() function in the
autoload/mylang.vim file in 'runtimepath'. |autoload|
@@ -2745,7 +2759,7 @@ A jump table for the options with a short description can be found at |Q_op|.
the internal format mechanism.
If the expression starts with s: or |<SID>|, then it is replaced with
- the script ID (|local-function|). Example: >
+ the script ID (|local-function|). Example: >vim
set formatexpr=s:MyFormatExpr()
set formatexpr=<SID>SomeFormatExpr()
< Otherwise, the expression is evaluated in the context of the script
@@ -2826,9 +2840,9 @@ A jump table for the options with a short description can be found at |Q_op|.
:s///g subst. one subst. all
:s///gg subst. all subst. one
- DEPRECATED: Setting this option may break plugins that are not aware
- of this option. Also, many users get confused that adding the /g flag
- has the opposite effect of that it normally does.
+ NOTE: Setting this option may break plugins that rely on the default
+ behavior of the 'g' flag. This will also make the 'g' flag have the
+ opposite effect of that documented in |:s_g|.
*'grepformat'* *'gfm'*
'grepformat' 'gfm' string (default "%f:%l:%m,%f:%l%m,%f %l%m")
@@ -2847,8 +2861,8 @@ A jump table for the options with a short description can be found at |Q_op|.
will be included. Environment variables are expanded |:set_env|. See
|option-backslash| about including spaces and backslashes.
When your "grep" accepts the "-H" argument, use this to make ":grep"
- also work well with a single file: >
- :set grepprg=grep\ -nH
+ also work well with a single file: >vim
+ set grepprg=grep\ -nH
< Special value: When 'grepprg' is set to "internal" the |:grep| command
works like |:vimgrep|, |:lgrep| like |:lvimgrep|, |:grepadd| like
|:vimgrepadd| and |:lgrepadd| like |:lvimgrepadd|.
@@ -2863,11 +2877,11 @@ A jump table for the options with a short description can be found at |Q_op|.
Configures the cursor style for each mode. Works in the GUI and many
terminals. See |tui-cursor-shape|.
- To disable cursor-styling, reset the option: >
- :set guicursor=
+ To disable cursor-styling, reset the option: >vim
+ set guicursor=
-< To enable mode shapes, "Cursor" highlight, and blinking: >
- :set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50
+< To enable mode shapes, "Cursor" highlight, and blinking: >vim
+ set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50
\,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor
\,sm:block-blinkwait175-blinkoff150-blinkon175
@@ -2900,8 +2914,8 @@ A jump table for the options with a short description can be found at |Q_op|.
the cursor starts blinking, blinkon is the time that
the cursor is shown and blinkoff is the time that the
cursor is not shown. Times are in msec. When one of
- the numbers is zero, there is no blinking. E.g.: >
- :set guicursor=n:blinkon0
+ the numbers is zero, there is no blinking. E.g.: >vim
+ set guicursor=n:blinkon0
< - Default is "blinkon0" for each mode.
{group-name}
Highlight group that decides the color and font of the
@@ -2939,9 +2953,9 @@ A jump table for the options with a short description can be found at |Q_op|.
to do a common setting for all modes. For example, to switch off
blinking: "a:blinkon0"
- Examples of cursor highlighting: >
- :highlight Cursor gui=reverse guifg=NONE guibg=NONE
- :highlight Cursor gui=NONE guifg=bg guibg=fg
+ Examples of cursor highlighting: >vim
+ highlight Cursor gui=reverse guifg=NONE guibg=NONE
+ highlight Cursor gui=NONE guifg=bg guibg=fg
<
*'guifont'* *'gfn'* *E235* *E596*
@@ -2956,8 +2970,8 @@ A jump table for the options with a short description can be found at |Q_op|.
Spaces after a comma are ignored. To include a comma in a font name
precede it with a backslash. Setting an option requires an extra
backslash before a space and a backslash. See also
- |option-backslash|. For example: >
- :set guifont=Screen15,\ 7x13,font\\,with\\,commas
+ |option-backslash|. For example: >vim
+ set guifont=Screen15,\ 7x13,font\\,with\\,commas
< will make Vim try to use the font "Screen15" first, and if it fails it
will try to use "7x13" and then "font,with,commas" instead.
@@ -2968,14 +2982,14 @@ A jump table for the options with a short description can be found at |Q_op|.
the case of X). The font names given should be "normal" fonts. Vim
will try to find the related bold and italic fonts.
- For Win32 and Mac OS: >
- :set guifont=*
+ For Win32 and Mac OS: >vim
+ set guifont=*
< will bring up a font requester, where you can pick the font you want.
The font name depends on the GUI used.
- For Mac OSX you can use something like this: >
- :set guifont=Monaco:h10
+ For Mac OSX you can use something like this: >vim
+ set guifont=Monaco:h10
< *E236*
Note that the fonts must be mono-spaced (all characters have the same
width).
@@ -3000,9 +3014,9 @@ A jump table for the options with a short description can be found at |Q_op|.
Use a ':' to separate the options.
- A '_' can be used in the place of a space, so you don't need to use
backslashes to escape the spaces.
- - Examples: >
- :set guifont=courier_new:h12:w5:b:cRUSSIAN
- :set guifont=Andale_Mono:h7.5:w4.5
+ - Examples: >vim
+ set guifont=courier_new:h12:w5:b:cRUSSIAN
+ set guifont=Andale_Mono:h7.5:w4.5
<
*'guifontwide'* *'gfw'* *E231* *E533* *E534*
@@ -3142,8 +3156,8 @@ A jump table for the options with a short description can be found at |Q_op|.
When non-empty describes the text to use in a tooltip for the GUI tab
pages line. When empty Vim will use a default tooltip.
This option is otherwise just like 'guitablabel' above.
- You can include a line break. Simplest method is to use |:let|: >
- :let &guitabtooltip = "line one\nline two"
+ You can include a line break. Simplest method is to use |:let|: >vim
+ let &guitabtooltip = "line one\nline two"
<
*'helpfile'* *'hf'*
@@ -3177,8 +3191,8 @@ A jump table for the options with a short description can be found at |Q_op|.
be used as a last resort. You can add "en" to prefer English over
another language, but that will only find tags that exist in that
language and not in the English help.
- Example: >
- :set helplang=de,it
+ Example: >vim
+ set helplang=de,it
< This will first search German, then Italian and finally English help
files.
When using |CTRL-]| and ":help!" in a non-English help file Vim will
@@ -3289,8 +3303,8 @@ A jump table for the options with a short description can be found at |Q_op|.
1 :lmap is ON and IM is off
2 :lmap is off and IM is ON
To always reset the option to zero when leaving Insert mode with <Esc>
- this can be used: >
- :inoremap <ESC> <ESC>:set iminsert=0<CR>
+ this can be used: >vim
+ inoremap <ESC> <ESC>:set iminsert=0<CR>
< This makes :lmap and IM turn off automatically when leaving Insert
mode.
Note that this option changes when using CTRL-^ in Insert mode
@@ -3348,20 +3362,20 @@ A jump table for the options with a short description can be found at |Q_op|.
'includeexpr' 'inex' string (default "")
local to buffer
Expression to be used to transform the string found with the 'include'
- option to a file name. Mostly useful to change "." to "/" for Java: >
- :setlocal includeexpr=substitute(v:fname,'\\.','/','g')
+ option to a file name. Mostly useful to change "." to "/" for Java: >vim
+ setlocal includeexpr=substitute(v:fname,'\\.','/','g')
< The "v:fname" variable will be set to the file name that was detected.
Note the double backslash: the `:set` command first halves them, then
one remains in the value, where "\." matches a dot literally. For
- simple character replacements `tr()` avoids the need for escaping: >
- :setlocal includeexpr=tr(v:fname,'.','/')
+ simple character replacements `tr()` avoids the need for escaping: >vim
+ setlocal includeexpr=tr(v:fname,'.','/')
<
Also used for the |gf| command if an unmodified file name can't be
found. Allows doing "gf" on the name after an 'include' statement.
Also used for |<cfile>|.
If the expression starts with s: or |<SID>|, then it is replaced with
- the script ID (|local-function|). Example: >
+ the script ID (|local-function|). Example: >vim
setlocal includeexpr=s:MyIncludeExpr(v:fname)
setlocal includeexpr=<SID>SomeIncludeExpr(v:fname)
< Otherwise, the expression is evaluated in the context of the script
@@ -3395,7 +3409,7 @@ A jump table for the options with a short description can be found at |Q_op|.
typing a search command. See also: 'hlsearch'.
If you don't want to turn 'hlsearch' on, but want to highlight all
matches while searching, you can turn on and off 'hlsearch' with
- autocmd. Example: >
+ autocmd. Example: >vim
augroup vimrc-incsearch-highlight
autocmd!
autocmd CmdlineEnter /,\? :set hlsearch
@@ -3423,7 +3437,7 @@ A jump table for the options with a short description can be found at |Q_op|.
when the expression is evaluated (but it may be moved around).
If the expression starts with s: or |<SID>|, then it is replaced with
- the script ID (|local-function|). Example: >
+ the script ID (|local-function|). Example: >vim
set indentexpr=s:MyIndentExpr()
set indentexpr=<SID>SomeIndentExpr()
< Otherwise, the expression is evaluated in the context of the script
@@ -3437,8 +3451,8 @@ A jump table for the options with a short description can be found at |Q_op|.
The evaluation of the expression must not have side effects! It must
not change the text, jump to another window, etc. Afterwards the
cursor position is always restored, thus the cursor may be moved.
- Normally this option would be set to call a function: >
- :set indentexpr=GetMyIndent()
+ Normally this option would be set to call a function: >vim
+ set indentexpr=GetMyIndent()
< Error messages will be suppressed, unless the 'debug' option contains
"msg".
See |indent-expression|.
@@ -3635,9 +3649,9 @@ A jump table for the options with a short description can be found at |Q_op|.
When "man" or "man -s" is used, Vim will automatically translate
a [count] for the "K" command to a section number.
See |option-backslash| about including spaces and backslashes.
- Example: >
- :set keywordprg=man\ -s
- :set keywordprg=:Man
+ Example: >vim
+ set keywordprg=man\ -s
+ set keywordprg=:Man
< This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
@@ -3657,10 +3671,10 @@ A jump table for the options with a short description can be found at |Q_op|.
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
- Example (for Greek, in UTF-8): *greek* >
- :set langmap=ΑA,Î’B,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ΜM,ÎN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,ΘU,ΩV,WW,ΧX,Î¥Y,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,Ï€p,qq,Ïr,σs,Ï„t,θu,ωv,Ï‚w,χx,Ï…y,ζz
-< Example (exchanges meaning of z and y for commands): >
- :set langmap=zy,yz,ZY,YZ
+ Example (for Greek, in UTF-8): *greek* >vim
+ set langmap=ΑA,Î’B,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ΜM,ÎN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,ΘU,ΩV,WW,ΧX,Î¥Y,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,Ï€p,qq,Ïr,σs,Ï„t,θu,ωv,Ï‚w,χx,Ï…y,ζz
+< Example (exchanges meaning of z and y for commands): >vim
+ set langmap=zy,yz,ZY,YZ
<
The 'langmap' option is a list of parts, separated with commas. Each
part can be in one of two forms:
@@ -3688,22 +3702,22 @@ A jump table for the options with a short description can be found at |Q_op|.
'langmenu' 'lm' string (default "")
global
Language to use for menu translation. Tells which file is loaded
- from the "lang" directory in 'runtimepath': >
+ from the "lang" directory in 'runtimepath': >vim
"lang/menu_" .. &langmenu .. ".vim"
< (without the spaces). For example, to always use the Dutch menus, no
- matter what $LANG is set to: >
- :set langmenu=nl_NL.ISO_8859-1
+ matter what $LANG is set to: >vim
+ set langmenu=nl_NL.ISO_8859-1
< When 'langmenu' is empty, |v:lang| is used.
Only normal file name characters can be used, `/\*?[|<>` are illegal.
If your $LANG is set to a non-English language but you do want to use
- the English menus: >
- :set langmenu=none
+ the English menus: >vim
+ set langmenu=none
< This option must be set before loading menus, switching on filetype
detection or syntax highlighting. Once the menus are defined setting
- this option has no effect. But you could do this: >
- :source $VIMRUNTIME/delmenu.vim
- :set langmenu=de_DE.ISO_8859-1
- :source $VIMRUNTIME/menu.vim
+ this option has no effect. But you could do this: >vim
+ source $VIMRUNTIME/delmenu.vim
+ set langmenu=de_DE.ISO_8859-1
+ source $VIMRUNTIME/menu.vim
< Warning: This deletes all menus that you defined yourself!
*'langremap'* *'lrm'* *'nolangremap'* *'nolrm'*
@@ -3759,8 +3773,8 @@ A jump table for the options with a short description can be found at |Q_op|.
option will cause the window size to be changed. When you only want
to use the size for the GUI, put the command in your |gvimrc| file.
Vim limits the number of lines to what fits on the screen. You can
- use this command to get the tallest window possible: >
- :set lines=999
+ use this command to get the tallest window possible: >vim
+ set lines=999
< Minimum value is 2, maximum value is 1000.
*'linespace'* *'lsp'*
@@ -3814,8 +3828,8 @@ A jump table for the options with a short description can be found at |Q_op|.
The cursor is displayed at the start of the space a Tab character
occupies, not at the end as usual in Normal mode. To get this cursor
- position while displaying Tabs with spaces, use: >
- :set list lcs=tab:\ \
+ position while displaying Tabs with spaces, use: >vim
+ set list lcs=tab:\ \
<
Note that list mode will also affect formatting (set with 'textwidth'
or 'wrapmargin') when 'cpoptions' includes 'L'. See 'listchars' for
@@ -3825,7 +3839,7 @@ A jump table for the options with a short description can be found at |Q_op|.
'listchars' 'lcs' string (default "tab:> ,trail:-,nbsp:+")
global or local to window |global-local|
Strings to use in 'list' mode and for the |:list| command. It is a
- comma-separated list of string settings.
+ comma-separated list of string settings. *E1511*
*lcs-eol*
eol:c Character to show at the end of each line. When
@@ -3869,8 +3883,8 @@ A jump table for the options with a short description can be found at |Q_op|.
lead:c Character to show for leading spaces. When omitted,
leading spaces are blank. Overrides the "space" and
"multispace" settings for leading spaces. You can
- combine it with "tab:", for example: >
- :set listchars+=tab:>-,lead:.
+ combine it with "tab:", for example: >vim
+ set listchars+=tab:>-,lead:.
<
*lcs-leadmultispace*
leadmultispace:c...
@@ -3904,19 +3918,19 @@ A jump table for the options with a short description can be found at |Q_op|.
omitted.
The characters ':' and ',' should not be used. UTF-8 characters can
- be used. All characters must be single width.
+ be used. All characters must be single width. *E1512*
- Each character can be specified as hex: >
+ Each character can be specified as hex: >vim
set listchars=eol:\\x24
set listchars=eol:\\u21b5
set listchars=eol:\\U000021b5
< Note that a double backslash is used. The number of hex characters
must be exactly 2 for \\x, 4 for \\u and 8 for \\U.
- Examples: >
- :set lcs=tab:>-,trail:-
- :set lcs=tab:>-,eol:<,nbsp:%
- :set lcs=extends:>,precedes:<
+ Examples: >vim
+ set lcs=tab:>-,trail:-
+ set lcs=tab:>-,eol:<,nbsp:%
+ set lcs=extends:>,precedes:<
< |hl-NonText| highlighting will be used for "eol", "extends" and
"precedes". |hl-Whitespace| for "nbsp", "space", "tab", "multispace",
"lead" and "trail".
@@ -3967,8 +3981,8 @@ A jump table for the options with a short description can be found at |Q_op|.
This would be mostly useful when you use MS-Windows. If iconv is
enabled, setting 'makeencoding' to "char" has the same effect as
- setting to the system locale encoding. Example: >
- :set makeencoding=char " system locale is used
+ setting to the system locale encoding. Example: >vim
+ set makeencoding=char " system locale is used
<
*'makeprg'* *'mp'*
@@ -3982,11 +3996,11 @@ A jump table for the options with a short description can be found at |Q_op|.
about including spaces and backslashes.
Note that a '|' must be escaped twice: once for ":set" and once for
the interpretation of a command. When you use a filter called
- "myfilter" do it like this: >
- :set makeprg=gmake\ \\\|\ myfilter
+ "myfilter" do it like this: >vim
+ set makeprg=gmake\ \\\|\ myfilter
< The placeholder "$*" can be given (even multiple times) to specify
- where the arguments will be included, for example: >
- :set makeprg=latex\ \\\\nonstopmode\ \\\\input\\{$*}
+ where the arguments will be included, for example: >vim
+ set makeprg=latex\ \\\\nonstopmode\ \\\\input\\{$*}
< This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
@@ -3999,12 +4013,12 @@ A jump table for the options with a short description can be found at |Q_op|.
jump between two double quotes.
The characters must be separated by a colon.
The pairs must be separated by a comma. Example for including '<' and
- '>' (for HTML): >
- :set mps+=<:>
+ '>' (for HTML): >vim
+ set mps+=<:>
< A more exotic example, to jump between the '=' and ';' in an
- assignment, useful for languages like C and Java: >
- :au FileType c,cpp,java set mps+==:;
+ assignment, useful for languages like C and Java: >vim
+ au FileType c,cpp,java set mps+==:;
< For a more advanced way of using "%", see the matchit.vim plugin in
the $VIMRUNTIME/plugin directory. |add-local-help|
@@ -4026,6 +4040,7 @@ A jump table for the options with a short description can be found at |Q_op|.
Increasing this limit above 200 also changes the maximum for Ex
command recursion, see |E169|.
See also |:function|.
+ Also used for maximum depth of callback functions.
*'maxmapdepth'* *'mmd'* *E223*
'maxmapdepth' 'mmd' number (default 1000)
@@ -4090,8 +4105,8 @@ A jump table for the options with a short description can be found at |Q_op|.
The languages for which these numbers are important are Italian and
Hungarian. The default works for when you have about 512 Mbyte. If
- you have 1 Gbyte you could use: >
- :set mkspellmem=900000,3000,800
+ you have 1 Gbyte you could use: >vim
+ set mkspellmem=900000,3000,800
< If you have less than 512 Mbyte |:mkspell| may fail for some
languages, no matter what you set 'mkspellmem' to.
@@ -4165,8 +4180,8 @@ A jump table for the options with a short description can be found at |Q_op|.
'mouse' string (default "nvi")
global
Enables mouse support. For example, to enable the mouse in Normal mode
- and Visual mode: >
- :set mouse=nv
+ and Visual mode: >vim
+ set mouse=nv
<
To temporarily disable mouse support, hold the shift key while using
the mouse.
@@ -4249,19 +4264,19 @@ A jump table for the options with a short description can be found at |Q_op|.
Note that you can further refine the meaning of buttons with mappings.
See |mouse-overview|. But mappings are NOT used for modeless selection.
- Example: >
- :map <S-LeftMouse> <RightMouse>
- :map <S-LeftDrag> <RightDrag>
- :map <S-LeftRelease> <RightRelease>
- :map <2-S-LeftMouse> <2-RightMouse>
- :map <2-S-LeftDrag> <2-RightDrag>
- :map <2-S-LeftRelease> <2-RightRelease>
- :map <3-S-LeftMouse> <3-RightMouse>
- :map <3-S-LeftDrag> <3-RightDrag>
- :map <3-S-LeftRelease> <3-RightRelease>
- :map <4-S-LeftMouse> <4-RightMouse>
- :map <4-S-LeftDrag> <4-RightDrag>
- :map <4-S-LeftRelease> <4-RightRelease>
+ Example: >vim
+ map <S-LeftMouse> <RightMouse>
+ map <S-LeftDrag> <RightDrag>
+ map <S-LeftRelease> <RightRelease>
+ map <2-S-LeftMouse> <2-RightMouse>
+ map <2-S-LeftDrag> <2-RightDrag>
+ map <2-S-LeftRelease> <2-RightRelease>
+ map <3-S-LeftMouse> <3-RightMouse>
+ map <3-S-LeftDrag> <3-RightDrag>
+ map <3-S-LeftRelease> <3-RightRelease>
+ map <4-S-LeftMouse> <4-RightMouse>
+ map <4-S-LeftDrag> <4-RightDrag>
+ map <4-S-LeftRelease> <4-RightRelease>
<
Mouse commands requiring the CTRL modifier can be simulated by typing
the "g" key before using the mouse:
@@ -4293,8 +4308,8 @@ A jump table for the options with a short description can be found at |Q_op|.
for vertical scrolling). You can disable mouse scrolling by using
a count of 0.
- Example: >
- :set mousescroll=ver:5,hor:2
+ Example: >vim
+ set mousescroll=ver:5,hor:2
< Will make Nvim scroll 5 lines at a time when scrolling vertically, and
scroll 2 columns at a time when scrolling horizontally.
@@ -4355,8 +4370,8 @@ A jump table for the options with a short description can be found at |Q_op|.
Any modes not specified or shapes not available use the normal mouse
pointer.
- Example: >
- :set mouseshape=s:udsizing,m:no
+ Example: >vim
+ set mouseshape=s:udsizing,m:no
< will make the mouse turn to a sizing arrow over the status lines and
indicate no input when the hit-enter prompt is displayed (since
clicking the mouse has no effect in this state.)
@@ -4521,30 +4536,30 @@ A jump table for the options with a short description can be found at |Q_op|.
provided that the file being searched for has a relative path (not
starting with "/", "./" or "../"). The directories in the 'path'
option may be relative or absolute.
- - Use commas to separate directory names: >
- :set path=.,/usr/local/include,/usr/include
+ - Use commas to separate directory names: >vim
+ set path=.,/usr/local/include,/usr/include
< - Spaces can also be used to separate directory names. To have a
space in a directory name, precede it with an extra backslash, and
- escape the space: >
- :set path=.,/dir/with\\\ space
+ escape the space: >vim
+ set path=.,/dir/with\\\ space
< - To include a comma in a directory name precede it with an extra
- backslash: >
- :set path=.,/dir/with\\,comma
-< - To search relative to the directory of the current file, use: >
- :set path=.
+ backslash: >vim
+ set path=.,/dir/with\\,comma
+< - To search relative to the directory of the current file, use: >vim
+ set path=.
< - To search in the current directory use an empty string between two
- commas: >
- :set path=,,
+ commas: >vim
+ set path=,,
< - A directory name may end in a ':' or '/'.
- Environment variables are expanded |:set_env|.
- When using |netrw.vim| URLs can be used. For example, adding
"https://www.vim.org" will make ":find index.html" work.
- Search upwards and downwards in a directory tree using "*", "**" and
";". See |file-searching| for info and syntax.
- - Careful with '\' characters, type two to get one in the option: >
- :set path=.,c:\\include
-< Or just use '/' instead: >
- :set path=.,c:/include
+ - Careful with '\' characters, type two to get one in the option: >vim
+ set path=.,c:\\include
+< Or just use '/' instead: >vim
+ set path=.,c:/include
< Don't forget "." or files won't even be found in the same directory as
the file!
The maximum length is limited. How much depends on the system, mostly
@@ -4553,14 +4568,14 @@ A jump table for the options with a short description can be found at |Q_op|.
'path', see |:checkpath|.
The use of |:set+=| and |:set-=| is preferred when adding or removing
directories from the list. This avoids problems when a future version
- uses another default. To remove the current directory use: >
- :set path-=
-< To add the current directory use: >
- :set path+=
+ uses another default. To remove the current directory use: >vim
+ set path-=
+< To add the current directory use: >vim
+ set path+=
< To use an environment variable, you probably need to replace the
separator. Here is an example to append $INCL, in which directory
- names are separated with a semi-colon: >
- :let &path = &path .. "," .. substitute($INCL, ';', ',', 'g')
+ names are separated with a semi-colon: >vim
+ let &path = &path .. "," .. substitute($INCL, ';', ',', 'g')
< Replace the ';' with a ':' or whatever separator is used. Note that
this doesn't work when $INCL contains a comma or white space.
@@ -4602,10 +4617,10 @@ A jump table for the options with a short description can be found at |Q_op|.
It is possible to override the level for individual highlights within
the popupmenu using |highlight-blend|. For instance, to enable
- transparency but force the current selected element to be fully opaque: >
+ transparency but force the current selected element to be fully opaque: >vim
- :set pumblend=15
- :hi PmenuSel blend=0
+ set pumblend=15
+ hi PmenuSel blend=0
<
UI-dependent. Works best with RGB colors. 'termguicolors'
@@ -4828,8 +4843,8 @@ A jump table for the options with a short description can be found at |Q_op|.
The default ruler width is 17 characters. To make the ruler 15
characters wide, put "%15(" at the start and "%)" at the end.
- Example: >
- :set rulerformat=%15(%c%V\ %p%%%)
+ Example: >vim
+ set rulerformat=%15(%c%V\ %p%%%)
<
*'runtimepath'* *'rtp'* *vimfiles*
@@ -4907,8 +4922,8 @@ A jump table for the options with a short description can be found at |Q_op|.
runtime files. For speed, use as few items as possible and avoid
wildcards.
See |:runtime|.
- Example: >
- :set runtimepath=~/vimruntime,/mygroup/vim,$VIMRUNTIME
+ Example: >vim
+ set runtimepath=~/vimruntime,/mygroup/vim,$VIMRUNTIME
< This will use the directory "~/vimruntime" first (containing your
personal Nvim runtime files), then "/mygroup/vim", and finally
"$VIMRUNTIME" (the default runtime files).
@@ -4972,7 +4987,7 @@ A jump table for the options with a short description can be found at |Q_op|.
in the middle of the window (except at the start or end of the file or
when long lines wrap).
After using the local value, go back the global value with one of
- these two: >
+ these two: >vim
setlocal scrolloff<
setlocal scrolloff=-1
< For scrolling horizontally see 'sidescrolloff'.
@@ -5181,8 +5196,8 @@ A jump table for the options with a short description can be found at |Q_op|.
2^8 < 10240 < 2^16) + 10240 bytes (requested maximum item
contents size) = 10253 bytes.
- Example: >
- :set shada='50,<1000,s100,:0,n~/nvim/shada
+ Example: >vim
+ set shada='50,<1000,s100,:0,n~/nvim/shada
<
'50 Marks will be remembered for the last 50 files you
edited.
@@ -5225,12 +5240,12 @@ A jump table for the options with a short description can be found at |Q_op|.
Environment variables are expanded |:set_env|.
If the name of the shell contains a space, you need to enclose it in
- quotes. Example with quotes: >
- :set shell=\"c:\program\ files\unix\sh.exe\"\ -f
+ quotes. Example with quotes: >vim
+ set shell=\"c:\program\ files\unix\sh.exe\"\ -f
< Note the backslash before each quote (to avoid starting a comment) and
each space (to avoid ending the option value), so better use |:let-&|
- like this: >
- :let &shell='"C:\Program Files\unix\sh.exe" -f'
+ like this: >vim
+ let &shell='"C:\Program Files\unix\sh.exe" -f'
< Also note that the "-f" is not inside the quotes, because it is not
part of the command name.
*shell-unquoting*
@@ -5253,7 +5268,7 @@ A jump table for the options with a short description can be found at |Q_op|.
Note that such processing is done after |:set| did its own round of
unescaping, so to keep yourself sane use |:let-&| like shown above.
*shell-powershell*
- To use PowerShell: >
+ To use PowerShell: >vim
let &shell = executable('pwsh') ? 'pwsh' : 'powershell'
let &shellcmdflag = '-NoLogo -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new();$PSDefaultParameterValues[''Out-File:Encoding'']=''utf8'';Remove-Alias -Force -ErrorAction SilentlyContinue tee;'
let &shellredir = '2>&1 | %%{ "$_" } | Out-File %s; exit $LastExitCode'
@@ -5363,7 +5378,7 @@ A jump table for the options with a short description can be found at |Q_op|.
existing file names, thus this option needs to be set before opening
any file for best results. This might change in the future.
'shellslash' only works when a backslash can be used as a path
- separator. To test if this is so use: >
+ separator. To test if this is so use: >vim
if exists('+shellslash')
< Also see 'completeslash'.
@@ -5457,9 +5472,10 @@ A jump table for the options with a short description can be found at |Q_op|.
match", "Pattern not found", "Back at original", etc.
C don't give messages while scanning for ins-completion *shm-C*
items, for instance "scanning tags"
- q use "recording" instead of "recording @a" *shm-q*
+ q do not show "recording @a" when recording a macro *shm-q*
F don't give the file info when editing a file, like *shm-F*
- `:silent` was used for the command
+ `:silent` was used for the command; note that this also
+ affects messages from 'autoread' reloading
S do not show search count message when searching, e.g. *shm-S*
"[1/5]"
@@ -5476,9 +5492,9 @@ A jump table for the options with a short description can be found at |Q_op|.
'showbreak' 'sbr' string (default "")
global or local to window |global-local|
String to put at the start of lines that have been wrapped. Useful
- values are "> " or "+++ ": >
- :let &showbreak = "> "
- :let &showbreak = '+++ '
+ values are "> " or "+++ ": >vim
+ let &showbreak = "> "
+ let &showbreak = '+++ '
< Only printable single-cell characters are allowed, excluding <Tab> and
comma (in a future version the comma might be used to separate the
part that is shown at the end and at the start of a line).
@@ -5487,8 +5503,8 @@ A jump table for the options with a short description can be found at |Q_op|.
If you want the 'showbreak' to appear in between line numbers, add the
"n" flag to 'cpoptions'.
A window-local value overrules a global value. If the global value is
- set and you want no value in the current window use NONE: >
- :setlocal showbreak=NONE
+ set and you want no value in the current window use NONE: >vim
+ setlocal showbreak=NONE
<
*'showcmd'* *'sc'* *'noshowcmd'* *'nosc'*
@@ -5592,16 +5608,16 @@ A jump table for the options with a short description can be found at |Q_op|.
horizontally centered in the window, as long as one does not come too
close to the beginning of the line.
After using the local value, go back the global value with one of
- these two: >
+ these two: >vim
setlocal sidescrolloff<
setlocal sidescrolloff=-1
<
Example: Try this together with 'sidescroll' and 'listchars' as
in the following example to never allow the cursor to move
- onto the "extends" character: >
+ onto the "extends" character: >vim
- :set nowrap sidescroll=1 listchars=extends:>,precedes:<
- :set sidescrolloff=1
+ set nowrap sidescroll=1 listchars=extends:>,precedes:<
+ set sidescrolloff=1
<
*'signcolumn'* *'scl'*
@@ -5727,7 +5743,7 @@ A jump table for the options with a short description can be found at |Q_op|.
Name of the word list file where words are added for the |zg| and |zw|
commands. It must end in ".{encoding}.add". You need to include the
path, otherwise the file is placed in the current directory.
- The path may include characters from 'isfname', space, comma and '@'.
+ The path may include characters from 'isfname', ' ', ',', '@' and ':'.
*E765*
It may also be a comma-separated list of names. A count before the
|zg| and |zw| commands can be used to access each. This allows using
@@ -5750,7 +5766,7 @@ A jump table for the options with a short description can be found at |Q_op|.
'spelllang' 'spl' string (default "en")
local to buffer
A comma-separated list of word list names. When the 'spell' option is
- on spellchecking will be done for these languages. Example: >
+ on spellchecking will be done for these languages. Example: >vim
set spelllang=en_us,nl,medical
< This means US English, Dutch and medical words are recognized. Words
that are not recognized will be highlighted.
@@ -5860,8 +5876,8 @@ A jump table for the options with a short description can be found at |Q_op|.
'verbose' option to a non-zero value.
Only one of "best", "double" or "fast" may be used. The others may
- appear several times in any order. Example: >
- :set sps=file:~/.config/nvim/sugg,best,expr:MySuggest()
+ appear several times in any order. Example: >vim
+ set sps=file:~/.config/nvim/sugg,best,expr:MySuggest()
<
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
@@ -5924,9 +5940,13 @@ A jump table for the options with a short description can be found at |Q_op|.
%s sign column for currently drawn line
%C fold column for currently drawn line
- NOTE: To draw the sign and fold columns, their items must be included in
- 'statuscolumn'. Even when they are not included, the status column width
- will adapt to the 'signcolumn' and 'foldcolumn' width.
+ The 'statuscolumn' width follows that of the default columns and
+ adapts to the |'numberwidth'|, |'signcolumn'| and |'foldcolumn'| option
+ values (regardless of whether the sign and fold items are present).
+ Additionally, the 'statuscolumn' grows with the size of the evaluated
+ format string, up to a point (following the maximum size of the default
+ fold, sign and number columns). Shrinking only happens when the number
+ of lines in a buffer changes, or the 'statuscolumn' option is set.
The |v:lnum| variable holds the line number to be drawn.
The |v:relnum| variable holds the relative line number to be drawn.
@@ -5934,6 +5954,9 @@ A jump table for the options with a short description can be found at |Q_op|.
when drawing the actual buffer line, and positive when
drawing the wrapped part of a buffer line.
+ When using |v:relnum|, keep in mind that cursor movement by itself will
+ not cause the 'statuscolumn' to update unless |'relativenumber'| is set.
+
NOTE: The %@ click execute function item is supported as well but the
specified function will be the same for each row in the same column.
It cannot be switched out through a dynamic 'statuscolumn' format, the
@@ -5941,21 +5964,21 @@ A jump table for the options with a short description can be found at |Q_op|.
Examples: >vim
" Relative number with bar separator and click handlers:
- :set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T
+ set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T
" Right aligned relative cursor line number:
- :let &stc='%=%{v:relnum?v:relnum:v:lnum} '
+ let &stc='%=%{v:relnum?v:relnum:v:lnum} '
" Line numbers in hexadecimal for non wrapped part of lines:
- :let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} '
+ let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} '
" Human readable line numbers with thousands separator:
- :let &stc='%{substitute(v:lnum,"\\d\\zs\\ze\\'
+ let &stc='%{substitute(v:lnum,"\\d\\zs\\ze\\'
. '%(\\d\\d\\d\\)\\+$",",","g")}'
" Both relative and absolute line numbers with different
" highlighting for odd and even relative numbers:
- :let &stc='%#NonText#%{&nu?v:lnum:""}' .
+ let &stc='%#NonText#%{&nu?v:lnum:""}' .
'%=%{&rnu&&(v:lnum%2)?"\ ".v:relnum:""}' .
'%#LineNr#%{&rnu&&!(v:lnum%2)?"\ ".v:relnum:""}'
@@ -5975,8 +5998,8 @@ A jump table for the options with a short description can be found at |Q_op|.
be given as "%%".
When the option starts with "%!" then it is used as an expression,
- evaluated and the result is used as the option value. Example: >
- :set statusline=%!MyStatusLine()
+ evaluated and the result is used as the option value. Example: >vim
+ set statusline=%!MyStatusLine()
< The *g:statusline_winid* variable will be set to the |window-ID| of the
window that the status line belongs to.
The result can contain %{} items that will be evaluated too.
@@ -6057,7 +6080,7 @@ A jump table for the options with a short description can be found at |Q_op|.
return value of expr contains "%" items they will get expanded.
The expression can contain the "}" character, the end of
expression is denoted by "%}".
- For example: >
+ For example: >vim
func! Stl_filename() abort
return "%t"
endfunc
@@ -6069,16 +6092,17 @@ A jump table for the options with a short description can be found at |Q_op|.
) - End of item group. No width fields allowed.
T N For 'tabline': start of tab page N label. Use %T or %X to end
the label. Clicking this label with left mouse button switches
- to the specified tab page.
+ to the specified tab page, while clicking it with middle mouse
+ button closes the specified tab page.
X N For 'tabline': start of close tab N label. Use %X or %T to end
the label, e.g.: %3Xclose%X. Use %999X for a "close current
- tab" label. Clicking this label with left mouse button closes
- specified tab page.
- @ N Start of execute function label. Use %X or %T to
- end the label, e.g.: %10@SwitchBuffer@foo.c%X. Clicking this
- label runs specified function: in the example when clicking once
- using left mouse button on "foo.c" "SwitchBuffer(10, 1, 'l',
- ' ')" expression will be run. Function receives the
+ tab" label. Clicking this label with left mouse button closes
+ the specified tab page.
+ @ N Start of execute function label. Use %X or %T to end the label,
+ e.g.: %10@SwitchBuffer@foo.c%X. Clicking this label runs the
+ specified function: in the example when clicking once using left
+ mouse button on "foo.c", a `SwitchBuffer(10, 1, 'l', ' ')`
+ expression will be run. The specified function receives the
following arguments in order:
1. minwid field value or zero if no N was specified
2. number of mouse clicks to detect multiple clicks
@@ -6124,8 +6148,8 @@ A jump table for the options with a short description can be found at |Q_op|.
When all items in a group becomes an empty string (i.e. flags that are
not set) and a minwid is not set for the group, the whole group will
become empty. This will make a group like the following disappear
- completely from the statusline when none of the flags are set. >
- :set statusline=...%(\ [%M%R%H]%)...
+ completely from the statusline when none of the flags are set. >vim
+ set statusline=...%(\ [%M%R%H]%)...
< Beware that an expression is evaluated each and every time the status
line is displayed.
*stl-%{* *g:actual_curbuf* *g:actual_curwin*
@@ -6156,23 +6180,23 @@ A jump table for the options with a short description can be found at |Q_op|.
edit your vimrc or whatever with "vim --clean" to get it right.
Examples:
- Emulate standard status line with 'ruler' set >
- :set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
-< Similar, but add ASCII value of char under the cursor (like "ga") >
- :set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P
-< Display byte count and byte value, modified flag in red. >
- :set statusline=%<%f%=\ [%1*%M%*%n%R%H]\ %-19(%3l,%02c%03V%)%O'%02b'
- :hi User1 term=inverse,bold cterm=inverse,bold ctermfg=red
-< Display a ,GZ flag if a compressed file is loaded >
- :set statusline=...%r%{VarExists('b:gzflag','\ [GZ]')}%h...
-< In the |:autocmd|'s: >
- :let b:gzflag = 1
-< And: >
- :unlet b:gzflag
-< And define this function: >
- :function VarExists(var, val)
- : if exists(a:var) | return a:val | else | return '' | endif
- :endfunction
+ Emulate standard status line with 'ruler' set >vim
+ set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
+< Similar, but add ASCII value of char under the cursor (like "ga") >vim
+ set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P
+< Display byte count and byte value, modified flag in red. >vim
+ set statusline=%<%f%=\ [%1*%M%*%n%R%H]\ %-19(%3l,%02c%03V%)%O'%02b'
+ hi User1 term=inverse,bold cterm=inverse,bold ctermfg=red
+< Display a ,GZ flag if a compressed file is loaded >vim
+ set statusline=...%r%{VarExists('b:gzflag','\ [GZ]')}%h...
+< In the |:autocmd|'s: >vim
+ let b:gzflag = 1
+< And: >vim
+ unlet b:gzflag
+< And define this function: >vim
+ function VarExists(var, val)
+ if exists(a:var) | return a:val | else | return '' | endif
+ endfunction
<
*'suffixes'* *'su'*
@@ -6193,8 +6217,8 @@ A jump table for the options with a short description can be found at |Q_op|.
'suffixesadd' 'sua' string (default "")
local to buffer
Comma-separated list of suffixes, which are used when searching for a
- file for the "gf", "[I", etc. commands. Example: >
- :set suffixesadd=.java
+ file for the "gf", "[I", etc. commands. Example: >vim
+ set suffixesadd=.java
<
*'swapfile'* *'swf'* *'noswapfile'* *'noswf'*
@@ -6266,19 +6290,19 @@ A jump table for the options with a short description can be found at |Q_op|.
Otherwise this option does not always reflect the current syntax (the
b:current_syntax variable does).
This option is most useful in a modeline, for a file which syntax is
- not automatically recognized. Example, in an IDL file: >
+ not automatically recognized. Example, in an IDL file: >c
/* vim: set syntax=idl : */
< When a dot appears in the value then this separates two filetype
- names. Example: >
+ names. Example: >c
/* vim: set syntax=c.doxygen : */
< This will use the "c" syntax first, then the "doxygen" syntax.
Note that the second one must be prepared to be loaded as an addition,
otherwise it will be skipped. More than one dot may appear.
- To switch off syntax highlighting for the current file, use: >
- :set syntax=OFF
+ To switch off syntax highlighting for the current file, use: >vim
+ set syntax=OFF
< To switch syntax highlighting on according to the current value of the
- 'filetype' option: >
- :set syntax=ON
+ 'filetype' option: >vim
+ set syntax=ON
< What actually happens when setting the 'syntax' option is that the
Syntax autocommand event is triggered with the value as argument.
This option is not copied to another buffer, independent of the 's' or
@@ -6495,6 +6519,10 @@ A jump table for the options with a short description can be found at |Q_op|.
attributes instead of "cterm" attributes. |guifg|
Requires an ISO-8613-3 compatible terminal.
+ Nvim will automatically attempt to determine if the host terminal
+ supports 24-bit color and will enable this option if it does
+ (unless explicitly disabled by the user).
+
*'termpastefilter'* *'tpf'*
'termpastefilter' 'tpf' string (default "BS,HT,ESC,DEL")
global
@@ -6628,13 +6656,13 @@ A jump table for the options with a short description can be found at |Q_op|.
expanded according to the rules used for 'statusline'.
This option cannot be set in a modeline when 'modelineexpr' is off.
- Example: >
- :auto BufEnter * let &titlestring = hostname() .. "/" .. expand("%:p")
- :set title titlestring=%<%F%=%l/%L-%P titlelen=70
+ Example: >vim
+ auto BufEnter * let &titlestring = hostname() .. "/" .. expand("%:p")
+ set title titlestring=%<%F%=%l/%L-%P titlelen=70
< The value of 'titlelen' is used to align items in the middle or right
of the available space.
- Some people prefer to have the file name first: >
- :set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:.:h\")})%)%(\ %a%)
+ Some people prefer to have the file name first: >vim
+ set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:.:h\")})%)%(\ %a%)
< Note the use of "%{ }" and an expression to get the path of the file,
without the file name. The "%( %)" constructs are used to add a
separating space only when needed.
@@ -6706,13 +6734,13 @@ A jump table for the options with a short description can be found at |Q_op|.
is kept in memory, higher numbers will cause more memory to be used.
Nevertheless, a single change can already use a large amount of memory.
Set to 0 for Vi compatibility: One level of undo and "u" undoes
- itself: >
+ itself: >vim
set ul=0
< But you can also get Vi compatibility by including the 'u' flag in
'cpoptions', and still be able to use CTRL-R to repeat undo.
Also see |undo-two-ways|.
Set to -1 for no undo at all. You might want to do this only for the
- current buffer: >
+ current buffer: >vim
setlocal ul=-1
< This helps when you run out of memory for a single change.
@@ -6768,8 +6796,8 @@ A jump table for the options with a short description can be found at |Q_op|.
For example, when editing assembly language files where statements
start in the 9th column and comments in the 41st, it may be useful
- to use the following: >
- :set varsofttabstop=8,32,8
+ to use the following: >vim
+ set varsofttabstop=8,32,8
< This will set soft tabstops with 8 and 8 + 32 spaces, and 8 more
for every column thereafter.
@@ -6781,8 +6809,8 @@ A jump table for the options with a short description can be found at |Q_op|.
local to buffer
A list of the number of spaces that a <Tab> in the file counts for,
separated by commas. Each value corresponds to one tab, with the
- final value applying to all subsequent tabs. For example: >
- :set vartabstop=4,20,10,8
+ final value applying to all subsequent tabs. For example: >vim
+ set vartabstop=4,20,10,8
< This will make the first tab 4 spaces wide, the second 20 spaces,
the third 10 spaces, and all following tabs 8 spaces.
@@ -6794,15 +6822,15 @@ A jump table for the options with a short description can be found at |Q_op|.
global
Sets the verbosity level. Also set by |-V| and |:verbose|.
- Tracing of options in Lua scripts is activated at level 1; Lua scripts
- are not traced with verbose=0, for performance.
+ Tracing of assignments to options, mappings, etc. in Lua scripts is
+ enabled at level 1; Lua scripts are not traced when 'verbose' is 0,
+ for performance.
If greater than or equal to a given level, Nvim produces the following
messages:
Level Messages ~
----------------------------------------------------------------------
- 1 Lua assignments to options, mappings, etc.
2 When a file is ":source"'ed, or |shada| file is read or written.
3 UI info, terminal capabilities.
4 Shell commands.
@@ -6911,8 +6939,8 @@ A jump table for the options with a short description can be found at |Q_op|.
~ "~" Normal
[ <Left> Insert and Replace
] <Right> Insert and Replace
- For example: >
- :set ww=<,>,[,]
+ For example: >vim
+ set ww=<,>,[,]
< allows wrap only when cursor keys are used.
When the movement keys are used in combination with a delete or change
operator, the <EOL> also counts for a character. This makes "3h"
@@ -6936,8 +6964,8 @@ A jump table for the options with a short description can be found at |Q_op|.
Some keys will not work, such as CTRL-C, <CR> and Enter.
<Esc> can be used, but hitting it twice in a row will still exit
command-line as a failsafe measure.
- Although 'wc' is a number option, you can set it to a special key: >
- :set wc=<Tab>
+ Although 'wc' is a number option, you can set it to a special key: >vim
+ set wc=<Tab>
<
*'wildcharm'* *'wcm'*
@@ -6947,9 +6975,9 @@ A jump table for the options with a short description can be found at |Q_op|.
recognized when used inside a macro. You can find "spare" command-line
keys suitable for this option by looking at |ex-edit-index|. Normally
you'll never actually type 'wildcharm', just use it in mappings that
- automatically invoke completion mode, e.g.: >
- :set wcm=<C-Z>
- :cnoremap ss so $vim/sessions/*.vim<C-Z>
+ automatically invoke completion mode, e.g.: >vim
+ set wcm=<C-Z>
+ cnoremap ss so $vim/sessions/*.vim<C-Z>
< Then after typing :ss you can use CTRL-P & CTRL-N.
*'wildignore'* *'wig'*
@@ -6961,8 +6989,8 @@ A jump table for the options with a short description can be found at |Q_op|.
|globpath()| unless a flag is passed to disable this.
The pattern is used like with |:autocmd|, see |autocmd-pattern|.
Also see 'suffixes'.
- Example: >
- :set wildignore=*.o,*.obj
+ Example: >vim
+ set wildignore=*.o,*.obj
< The use of |:set+=| and |:set-=| is preferred when adding or removing
a pattern from the list. This avoids problems when a future version
uses another default.
@@ -7010,9 +7038,9 @@ A jump table for the options with a short description can be found at |Q_op|.
completion.
If you want <Left> and <Right> to move the cursor instead of selecting
- a different match, use this: >
- :cnoremap <Left> <Space><BS><Left>
- :cnoremap <Right> <Space><BS><Right>
+ a different match, use this: >vim
+ cnoremap <Left> <Space><BS><Left>
+ cnoremap <Right> <Space><BS><Right>
<
|hl-WildMenu| highlights the current match.
@@ -7050,16 +7078,16 @@ A jump table for the options with a short description can be found at |Q_op|.
and sort buffers by time last used (other than the
current buffer).
- Examples: >
- :set wildmode=full
-< Complete first full match, next match, etc. (the default) >
- :set wildmode=longest,full
-< Complete longest common string, then each full match >
- :set wildmode=list:full
-< List all matches and complete each full match >
- :set wildmode=list,full
-< List all matches without completing, then each full match >
- :set wildmode=longest,list
+ Examples: >vim
+ set wildmode=full
+< Complete first full match, next match, etc. (the default) >vim
+ set wildmode=longest,full
+< Complete longest common string, then each full match >vim
+ set wildmode=list:full
+< List all matches and complete each full match >vim
+ set wildmode=list,full
+< List all matches without completing, then each full match >vim
+ set wildmode=longest,list
< Complete longest common string, then list alternatives.
More info here: |cmdline-completion|.
@@ -7169,7 +7197,7 @@ A jump table for the options with a short description can be found at |Q_op|.
Other windows will be only 'winminheight' high. This has the drawback
that ":all" will create only two windows. To avoid "vim -o 1 2 3 4"
to create only two windows, set the option after startup is done,
- using the |VimEnter| event: >
+ using the |VimEnter| event: >vim
au VimEnter * set winheight=999
< Minimum value is 1.
The height is not adjusted after one of the commands that change the
@@ -7194,7 +7222,7 @@ A jump table for the options with a short description can be found at |Q_op|.
the popupmenu are determined by the current window. Highlights in the
message area cannot be overridden.
- Example: show a different color for non-current windows: >
+ Example: show a different color for non-current windows: >vim
set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC
<
@@ -7250,9 +7278,9 @@ A jump table for the options with a short description can be found at |Q_op|.
horizontally.
The line will be broken in the middle of a word if necessary. See
'linebreak' to get the break at a word boundary.
- To make scrolling horizontally a bit more useful, try this: >
- :set sidescroll=5
- :set listchars+=precedes:<,extends:>
+ To make scrolling horizontally a bit more useful, try this: >vim
+ set sidescroll=5
+ set listchars+=precedes:<,extends:>
< See 'sidescroll', 'listchars' and |wrap-off|.
This option can't be set from a |modeline| when the 'diff' option is
on.
diff --git a/runtime/doc/pi_netrw.txt b/runtime/doc/pi_netrw.txt
index 85ac290361..d8fcd066a8 100644
--- a/runtime/doc/pi_netrw.txt
+++ b/runtime/doc/pi_netrw.txt
@@ -639,7 +639,7 @@ additional prompting.
work with your ftp client. Otherwise the script will
prompt for user-id and password.
- (*3) for ftp, "machine" may be machine#port or machine:port
+ (*3) for ftp, "machine" may be machine#port or machine:port
if a different port is needed than the standard ftp port
(*4) for http:..., if wget is available it will be used. Otherwise,
@@ -785,7 +785,7 @@ below, a {netfile} is a URL to a remote file.
(related: |netrw-userpass|)
:NetrwSettings This command is described in |netrw-settings| -- used to
- display netrw settings and change netrw behavior.
+ display netrw settings and change netrw behavior.
==============================================================================
@@ -1621,10 +1621,8 @@ A further approach is to delete files which match a pattern.
This will cause the matching files to be marked. Then,
press "D".
-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.
+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
@@ -1643,8 +1641,7 @@ 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_localrmdir| |g:netrw_rm_cmd|
- |g:netrw_rmdir_cmd| |g:netrw_ssh_cmd|
+Associated setting variable: |g:netrw_rm_cmd| |g:netrw_ssh_cmd|
*netrw-explore* *netrw-hexplore* *netrw-nexplore* *netrw-pexplore*
@@ -1687,7 +1684,11 @@ 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.
+ 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
Those who like this method often also like tree style displays;
see |g:netrw_liststyle|.
@@ -2848,14 +2849,6 @@ 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
@@ -3766,7 +3759,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_localrmdir|, |g:netrw_mkdir_cmd|).
+ |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
@@ -3892,8 +3885,13 @@ netrw:
==============================================================================
12. History *netrw-history* {{{1
- v172: Apr 22, 2023 * removed g:netrw_localrmdiropt
- removed g:netrw_localrmdir
+ 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
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,7 +3979,6 @@ netrw:
|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
@@ -4041,7 +4038,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|;
diff --git a/runtime/doc/quickfix.txt b/runtime/doc/quickfix.txt
index 4428ff2f65..9037ecc0f9 100644
--- a/runtime/doc/quickfix.txt
+++ b/runtime/doc/quickfix.txt
@@ -368,12 +368,12 @@ processing a quickfix or location list command, it will be aborted.
:cl[ist]! +{count} List the current and next {count} error lines. This
is useful to see unrecognized lines after the current
one. For example, if ":clist" shows:
- 8384 testje.java:252: error: cannot find symbol ~
+ 8384 testje.java:252: error: cannot find symbol ~
Then using ":cl! +3" shows the reason:
- 8384 testje.java:252: error: cannot find symbol ~
- 8385: ZexitCode = Fmainx(); ~
- 8386: ^ ~
- 8387: symbol: method Fmainx() ~
+ 8384 testje.java:252: error: cannot find symbol ~
+ 8385: ZexitCode = Fmainx(); ~
+ 8386: ^ ~
+ 8387: symbol: method Fmainx() ~
:lli[st] [from] [, [to]] *:lli* *:llist*
Same as ":clist", except the location list for the
diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt
index f976eb7464..572dc8a841 100644
--- a/runtime/doc/quickref.txt
+++ b/runtime/doc/quickref.txt
@@ -623,9 +623,9 @@ Short explanation of each option: *option-list*
'aleph' 'al' ASCII code of the letter Aleph (Hebrew)
'allowrevins' 'ari' allow CTRL-_ in Insert and Command-line mode
'ambiwidth' 'ambw' what to do with Unicode chars of ambiguous width
-'autochdir' 'acd' change directory to the file in the current window
'arabic' 'arab' for Arabic as a default second language
'arabicshape' 'arshape' do shaping for Arabic characters
+'autochdir' 'acd' change directory to the file in the current window
'autoindent' 'ai' take indent for new line from previous line
'autoread' 'ar' autom. read file when changed outside of Vim
'autowrite' 'aw' automatically write file if changed
@@ -655,8 +655,8 @@ Short explanation of each option: *option-list*
'cindent' 'cin' do C program indenting
'cinkeys' 'cink' keys that trigger indent when 'cindent' is set
'cinoptions' 'cino' how to do indenting when 'cindent' is set
-'cinwords' 'cinw' words where 'si' and 'cin' add an indent
'cinscopedecls' 'cinsd' words that are recognized by 'cino-g'
+'cinwords' 'cinw' words where 'si' and 'cin' add an indent
'clipboard' 'cb' use the clipboard as the unnamed register
'cmdheight' 'ch' number of lines to use for the command-line
'cmdwinheight' 'cwh' height of the command-line window
@@ -738,10 +738,10 @@ Short explanation of each option: *option-list*
'helpheight' 'hh' minimum height of a new help window
'helplang' 'hlg' preferred help languages
'hidden' 'hid' don't unload buffer when it is |abandon|ed
-'hlsearch' 'hls' highlight matches with last search pattern
'history' 'hi' number of command-lines that are remembered
'hkmap' 'hk' Hebrew keyboard mapping
'hkmapp' 'hkp' phonetic Hebrew keyboard mapping
+'hlsearch' 'hls' highlight matches with last search pattern
'icon' let Vim set the text of the window icon
'iconstring' string to use for the Vim icon text
'ignorecase' 'ic' ignore case in search patterns
@@ -939,10 +939,10 @@ Short explanation of each option: *option-list*
'wildoptions' 'wop' specifies how command line completion is done
'winaltkeys' 'wak' when the windows system handles ALT keys
'window' 'wi' nr of lines to scroll for CTRL-F and CTRL-B
-'winheight' 'wh' minimum number of lines for the current window
-'winhighlight' 'winhl' window-local highlighting
'winfixheight' 'wfh' keep window height when opening/closing windows
'winfixwidth' 'wfw' keep window width when opening/closing windows
+'winheight' 'wh' minimum number of lines for the current window
+'winhighlight' 'winhl' window-local highlighting
'winminheight' 'wmh' minimum number of lines for any window
'winminwidth' 'wmw' minimal number of columns for any window
'winwidth' 'wiw' minimal number of columns for current window
diff --git a/runtime/doc/recover.txt b/runtime/doc/recover.txt
index e6b5b06744..4312716b22 100644
--- a/runtime/doc/recover.txt
+++ b/runtime/doc/recover.txt
@@ -85,10 +85,10 @@ You can find this in the user manual, section |11.3|.
*W325*
The default |SwapExists| handler (|default-autocmds|) skips the |E325| prompt
-(selects "(E)dit") if the swapfile owner process (1) is still running and (2)
-was started by the current user. This presumes that you normally don't want
-to be bothered with the |ATTENTION| message just because you happen to edit
-the same file from multiple Nvim instances. In the worst case (a system
+(and automatically chooses "(E)dit") if the swapfile owner process is still
+running and owned by the current user. This presumes that you normally don't
+want to be bothered with the |ATTENTION| message just because you happen to
+edit the same file from multiple Nvim instances. In the worst case (a system
crash) there will be more than one swapfile for the file; use |:recover| to
inspect all of its swapfiles.
diff --git a/runtime/doc/repeat.txt b/runtime/doc/repeat.txt
index 53f6904170..ae827fa06f 100644
--- a/runtime/doc/repeat.txt
+++ b/runtime/doc/repeat.txt
@@ -148,10 +148,20 @@ q Stops recording.
*@@* *E748*
@@ Repeat the previous @{0-9a-z":*} [count] times.
+ *v_@-default*
+{Visual}@{0-9a-z".=*+} In Visual mode, execute the contents of the register
+{Visual}@@ but for each selected line.
+ See |visual-repeat|, |default-mappings|.
+
*Q*
Q Repeat the last recorded register [count] times.
See |reg_recorded()|.
+ *v_Q-default*
+{Visual}Q In Visual mode, repeat the last recorded register for
+ each selected line.
+ See |visual-repeat|, |default-mappings|.
+
*:@*
:[addr]@{0-9a-z".=*+} Execute the contents of register {0-9a-z".=*+} as an Ex
command. First set cursor at line [addr] (default is
@@ -182,11 +192,11 @@ Using Vim scripts *using-scripts*
For writing a Vim script, see chapter 41 of the user manual |usr_41.txt|.
*:so* *:source* *load-vim-script*
-:[range]so[urce] [file] Runs |Ex| commands or Lua code (".lua" files) from
+:[range]so[urce] [file] Runs |Ex-commands| or Lua code (".lua" files) from
[file].
- If no [file], the current buffer is used, and it is
- treated as Lua code if its 'filetype' is "lua" or its
- file name ends with ".lua".
+ If no [file], the current buffer is used and treated
+ as Lua code if 'filetype' is "lua" or its filename
+ ends with ".lua".
Triggers the |SourcePre| autocommand.
*:source!*
:[range]so[urce]! {file}
diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt
index e1053b54f1..c02752a2b7 100644
--- a/runtime/doc/syntax.txt
+++ b/runtime/doc/syntax.txt
@@ -196,52 +196,56 @@ be preferred names for highlight groups that are common for many languages.
These are the suggested group names (if syntax highlighting works properly
you can see the actual color, except for "Ignore"):
- Comment any comment
+Comment any comment
- Constant any constant
- String a string constant: "this is a string"
- Character a character constant: 'c', '\n'
- Number a number constant: 234, 0xff
- Boolean a boolean constant: TRUE, false
- Float a floating point constant: 2.3e10
+Constant any constant
+String a string constant: "this is a string"
+Character a character constant: 'c', '\n'
+Number a number constant: 234, 0xff
+Boolean a boolean constant: TRUE, false
+Float a floating point constant: 2.3e10
- Identifier any variable name
- Function function name (also: methods for classes)
+Identifier any variable name
+Function function name (also: methods for classes)
- Statement any statement
- Conditional if, then, else, endif, switch, etc.
- Repeat for, do, while, etc.
- Label case, default, etc.
- Operator "sizeof", "+", "*", etc.
- Keyword any other keyword
- Exception try, catch, throw
+Statement any statement
+Conditional if, then, else, endif, switch, etc.
+Repeat for, do, while, etc.
+Label case, default, etc.
+Operator "sizeof", "+", "*", etc.
+Keyword any other keyword
+Exception try, catch, throw
- PreProc generic Preprocessor
- Include preprocessor #include
- Define preprocessor #define
- Macro same as Define
- PreCondit preprocessor #if, #else, #endif, etc.
+PreProc generic Preprocessor
+Include preprocessor #include
+Define preprocessor #define
+Macro same as Define
+PreCondit preprocessor #if, #else, #endif, etc.
- Type int, long, char, etc.
- StorageClass static, register, volatile, etc.
- Structure struct, union, enum, etc.
- Typedef A typedef
+Type int, long, char, etc.
+StorageClass static, register, volatile, etc.
+Structure struct, union, enum, etc.
+Typedef a typedef
- Special any special symbol
- SpecialChar special character in a constant
- Tag you can use CTRL-] on this
- Delimiter character that needs attention
- SpecialComment special things inside a comment
- Debug debugging statements
+Special any special symbol
+SpecialChar special character in a constant
+Tag you can use CTRL-] on this
+Delimiter character that needs attention
+SpecialComment special things inside a comment
+Debug debugging statements
- Underlined text that stands out, HTML links
+Underlined text that stands out, HTML links
- Ignore left blank, hidden |hl-Ignore|
+Ignore left blank, hidden |hl-Ignore|
- Error any erroneous construct
+Error any erroneous construct
- Todo anything that needs extra attention; mostly the
- keywords TODO FIXME and XXX
+Todo anything that needs extra attention; mostly the
+ keywords TODO FIXME and XXX
+
+Added added line in a diff
+Changed changed line in a diff
+Removed removed line in a diff
The names marked with * are the preferred groups; the others are minor groups.
For the preferred groups, the "syntax.vim" file contains default highlighting.
@@ -337,443 +341,11 @@ Upon loading a file, Vim finds the relevant syntax file as follows:
syntax.
==============================================================================
-4. Conversion to HTML *2html.vim* *convert-to-HTML*
-
-2html is not a syntax file itself, but a script that converts the current
-window into HTML. Vim opens a new window in which it builds the HTML file.
-
-After you save the resulting file, you can view it with any browser. The
-colors should be exactly the same as you see them in Vim. With
-|g:html_line_ids| you can jump to specific lines by adding (for example) #L123
-or #123 to the end of the URL in your browser's address bar. And with
-|g:html_dynamic_folds| enabled, you can show or hide the text that is folded
-in Vim.
+4. Conversion to HTML *convert-to-HTML* *2html.vim*
-You are not supposed to set the 'filetype' or 'syntax' option to "2html"!
-Source the script to convert the current file: >
-
- :runtime! syntax/2html.vim
-<
-Many variables affect the output of 2html.vim; see below. Any of the on/off
-options listed below can be enabled or disabled by setting them explicitly to
-the desired value, or restored to their default by removing the variable using
-|:unlet|.
-
-Remarks:
-- Some truly ancient browsers may not show the background colors.
-- From most browsers you can also print the file (in color)!
-
-Here is an example how to run the script over all .c and .h files from a
-Unix shell: >
- for f in *.[ch]; do gvim -f +"syn on" +"run! syntax/2html.vim" +"wq" +"q" $f; done
-<
- *g:html_start_line* *g:html_end_line*
-To restrict the conversion to a range of lines, use a range with the |:TOhtml|
-command below, or set "g:html_start_line" and "g:html_end_line" to the first
-and last line to be converted. Example, using the last set Visual area: >
-
- :let g:html_start_line = line("'<")
- :let g:html_end_line = line("'>")
- :runtime! syntax/2html.vim
-<
- *:TOhtml*
-:[range]TOhtml The ":TOhtml" command is defined in a standard plugin.
- This command will source |2html.vim| for you. When a
- range is given, this command sets |g:html_start_line|
- and |g:html_end_line| to the start and end of the
- range, respectively. Default range is the entire
- buffer.
-
- If the current window is part of a |diff|, unless
- |g:html_diff_one_file| is set, :TOhtml will convert
- all windows which are part of the diff in the current
- tab and place them side-by-side in a <table> element
- in the generated HTML. With |g:html_line_ids| you can
- jump to lines in specific windows with (for example)
- #W1L42 for line 42 in the first diffed window, or
- #W3L87 for line 87 in the third.
-
- Examples: >
-
- :10,40TOhtml " convert lines 10-40 to html
- :'<,'>TOhtml " convert current/last visual selection
- :TOhtml " convert entire buffer
-<
- *g:html_diff_one_file*
-Default: 0.
-When 0, and using |:TOhtml| all windows involved in a |diff| in the current tab
-page are converted to HTML and placed side-by-side in a <table> element. When
-1, only the current buffer is converted.
-Example: >
+The old to html converter has ben replaced by a Lua version and the
+documentation has been moved to |:TOhtml|.
- let g:html_diff_one_file = 1
-<
- *g:html_whole_filler*
-Default: 0.
-When 0, if |g:html_diff_one_file| is 1, a sequence of more than 3 filler lines
-is displayed as three lines with the middle line mentioning the total number
-of inserted lines.
-When 1, always display all inserted lines as if |g:html_diff_one_file| were
-not set.
->
- :let g:html_whole_filler = 1
-<
- *TOhtml-performance* *g:html_no_progress*
-Default: 0.
-When 0, display a progress bar in the statusline for each major step in the
-2html.vim conversion process.
-When 1, do not display the progress bar. This offers a minor speed improvement
-but you won't have any idea how much longer the conversion might take; for big
-files it can take a long time!
-Example: >
-
- let g:html_no_progress = 1
-<
-You can obtain better performance improvements by also instructing Vim to not
-run interactively, so that too much time is not taken to redraw as the script
-moves through the buffer, switches windows, and the like: >
-
- vim -E -s -c "let g:html_no_progress=1" -c "syntax on" -c "set ft=c" -c "runtime syntax/2html.vim" -cwqa myfile.c
-<
-Note that the -s flag prevents loading your vimrc and any plugins, so you
-need to explicitly source/enable anything that will affect the HTML
-conversion. See |-E| and |-s-ex| for details. It is probably best to create a
-script to replace all the -c commands and use it with the -u flag instead of
-specifying each command separately.
-
- *hl-TOhtmlProgress* *TOhtml-progress-color*
-When displayed, the progress bar will show colored boxes along the statusline
-as the HTML conversion proceeds. By default, the background color as the
-current "DiffDelete" highlight group is used. If "DiffDelete" and "StatusLine"
-have the same background color, TOhtml will automatically adjust the color to
-differ. If you do not like the automatically selected colors, you can define
-your own highlight colors for the progress bar. Example: >
-
- hi TOhtmlProgress guifg=#c0ffee ctermbg=7
-<
- *g:html_number_lines*
-Default: Current 'number' setting.
-When 0, buffer text is displayed in the generated HTML without line numbering.
-When 1, a column of line numbers is added to the generated HTML with the same
-highlighting as the line number column in Vim (|hl-LineNr|).
-Force line numbers even if 'number' is not set: >
- :let g:html_number_lines = 1
-Force to omit the line numbers: >
- :let g:html_number_lines = 0
-Go back to the default to use 'number' by deleting the variable: >
- :unlet g:html_number_lines
-<
- *g:html_line_ids*
-Default: 1 if |g:html_number_lines| is set, 0 otherwise.
-When 1, adds an HTML id attribute to each line number, or to an empty <span>
-inserted for that purpose if no line numbers are shown. This ID attribute
-takes the form of L123 for single-buffer HTML pages, or W2L123 for diff-view
-pages, and is used to jump to a specific line (in a specific window of a diff
-view). Javascript is inserted to open any closed dynamic folds
-(|g:html_dynamic_folds|) containing the specified line before jumping. The
-javascript also allows omitting the window ID in the url, and the leading L.
-For example: >
-
- page.html#L123 jumps to line 123 in a single-buffer file
- page.html#123 does the same
-
- diff.html#W1L42 jumps to line 42 in the first window in a diff
- diff.html#42 does the same
-<
- *g:html_use_css*
-Default: 1.
-When 1, generate valid HTML 5 markup with CSS styling, supported in all modern
-browsers and many old browsers.
-When 0, generate <font> tags and similar outdated markup. This is not
-recommended but it may work better in really old browsers, email clients,
-forum posts, and similar situations where basic CSS support is unavailable.
-Example: >
- :let g:html_use_css = 0
-<
- *g:html_ignore_conceal*
-Default: 0.
-When 0, concealed text is removed from the HTML and replaced with a character
-from |:syn-cchar| or 'listchars' as appropriate, depending on the current
-value of 'conceallevel'.
-When 1, include all text from the buffer in the generated HTML, even if it is
-|conceal|ed.
-
-Either of the following commands will ensure that all text in the buffer is
-included in the generated HTML (unless it is folded): >
- :let g:html_ignore_conceal = 1
- :setl conceallevel=0
-<
- *g:html_ignore_folding*
-Default: 0.
-When 0, text in a closed fold is replaced by the text shown for the fold in
-Vim (|fold-foldtext|). See |g:html_dynamic_folds| if you also want to allow
-the user to expand the fold as in Vim to see the text inside.
-When 1, include all text from the buffer in the generated HTML; whether the
-text is in a fold has no impact at all. |g:html_dynamic_folds| has no effect.
-
-Either of these commands will ensure that all text in the buffer is included
-in the generated HTML (unless it is concealed): >
- zR
- :let g:html_ignore_folding = 1
-<
- *g:html_dynamic_folds*
-Default: 0.
-When 0, text in a closed fold is not included at all in the generated HTML.
-When 1, generate javascript to open a fold and show the text within, just like
-in Vim.
-
-Setting this variable to 1 causes 2html.vim to always use CSS for styling,
-regardless of what |g:html_use_css| is set to.
-
-This variable is ignored when |g:html_ignore_folding| is set.
->
- :let g:html_dynamic_folds = 1
-<
- *g:html_no_foldcolumn*
-Default: 0.
-When 0, if |g:html_dynamic_folds| is 1, generate a column of text similar to
-Vim's foldcolumn (|fold-foldcolumn|) the user can click on to toggle folds
-open or closed. The minimum width of the generated text column is the current
-'foldcolumn' setting.
-When 1, do not generate this column; instead, hovering the mouse cursor over
-folded text will open the fold as if |g:html_hover_unfold| were set.
->
- :let g:html_no_foldcolumn = 1
-<
- *TOhtml-uncopyable-text* *g:html_prevent_copy*
-Default: Empty string.
-This option prevents certain regions of the generated HTML from being copied,
-when you select all text in document rendered in a browser and copy it. Useful
-for allowing users to copy-paste only the source text even if a fold column or
-line numbers are shown in the generated content. Specify regions to be
-affected in this way as follows:
- f: fold column
- n: line numbers (also within fold text)
- t: fold text
- d: diff filler
-
-Example, to make the fold column and line numbers uncopyable: >
- :let g:html_prevent_copy = "fn"
-<
-The method used to prevent copying in the generated page depends on the value
-of |g:html_use_input_for_pc|.
-
- *g:html_use_input_for_pc*
-Default: "none"
-If |g:html_prevent_copy| is non-empty, then:
-
-When "all", read-only <input> elements are used in place of normal text for
-uncopyable regions. In some browsers, especially older browsers, after
-selecting an entire page and copying the selection, the <input> tags are not
-pasted with the page text. If |g:html_no_invalid| is 0, the <input> tags have
-invalid type; this works in more browsers, but the page will not validate.
-Note: This method does NOT work in recent versions of Chrome and equivalent
-browsers; the <input> tags get pasted with the text.
-
-When "fallback" (default value), the same <input> elements are generated for
-older browsers, but newer browsers (detected by CSS feature query) hide the
-<input> elements and instead use generated content in an ::before pseudoelement
-to display the uncopyable text. This method should work with the largest
-number of browsers, both old and new.
-
-When "none", the <input> elements are not generated at all. Only the
-generated-content method is used. This means that old browsers, notably
-Internet Explorer, will either copy the text intended not to be copyable, or
-the non-copyable text may not appear at all. However, this is the most
-standards-based method, and there will be much less markup.
-
- *g:html_no_invalid*
-Default: 0.
-When 0, if |g:html_prevent_copy| is non-empty and |g:html_use_input_for_pc| is
-not "none", an invalid attribute is intentionally inserted into the <input>
-element for the uncopyable areas. This prevents pasting the <input> elements
-in some applications. Specifically, some versions of Microsoft Word will not
-paste the <input> elements if they contain this invalid attribute. When 1, no
-invalid markup is inserted, and the generated page should validate. However,
-<input> elements may be pasted into some applications and can be difficult to
-remove afterward.
-
- *g:html_hover_unfold*
-Default: 0.
-When 0, the only way to open a fold generated by 2html.vim with
-|g:html_dynamic_folds| set, is to click on the generated fold column.
-When 1, use CSS 2.0 to allow the user to open a fold by moving the mouse
-cursor over the displayed fold text. This is useful to allow users with
-disabled javascript to view the folded text.
-
-Note that old browsers (notably Internet Explorer 6) will not support this
-feature. Browser-specific markup for IE6 is included to fall back to the
-normal CSS1 styling so that the folds show up correctly for this browser, but
-they will not be openable without a foldcolumn.
->
- :let g:html_hover_unfold = 1
-<
- *g:html_id_expr*
-Default: ""
-Dynamic folding and jumping to line IDs rely on unique IDs within the document
-to work. If generated HTML is copied into a larger document, these IDs are no
-longer guaranteed to be unique. Set g:html_id_expr to an expression Vim can
-evaluate to get a unique string to append to each ID used in a given document,
-so that the full IDs will be unique even when combined with other content in a
-larger HTML document. Example, to append _ and the buffer number to each ID: >
-
- :let g:html_id_expr = '"_" .. bufnr("%")'
-<
-To append a string "_mystring" to the end of each ID: >
-
- :let g:html_id_expr = '"_mystring"'
-<
-Note: When converting a diff view to HTML, the expression will only be
-evaluated for the first window in the diff, and the result used for all the
-windows.
-
- *TOhtml-wrap-text* *g:html_pre_wrap*
-Default: Current 'wrap' setting.
-When 0, if |g:html_no_pre| is 0 or unset, the text in the generated HTML does
-not wrap at the edge of the browser window.
-When 1, if |g:html_use_css| is 1, the CSS 2.0 "white-space:pre-wrap" value is
-used, causing the text to wrap at whitespace at the edge of the browser
-window.
-Explicitly enable text wrapping: >
- :let g:html_pre_wrap = 1
-Explicitly disable wrapping: >
- :let g:html_pre_wrap = 0
-Go back to default, determine wrapping from 'wrap' setting: >
- :unlet g:html_pre_wrap
-<
- *g:html_no_pre*
-Default: 0.
-When 0, buffer text in the generated HTML is surrounded by <pre>...</pre>
-tags. Series of whitespace is shown as in Vim without special markup, and tab
-characters can be included literally (see |g:html_expand_tabs|).
-When 1 (not recommended), the <pre> tags are omitted, and a plain <div> is
-used instead. Whitespace is replaced by a series of &nbsp; character
-references, and <br> is used to end each line. This is another way to allow
-text in the generated HTML is wrap (see |g:html_pre_wrap|) which also works in
-old browsers, but may cause noticeable differences between Vim's display and
-the rendered page generated by 2html.vim.
->
- :let g:html_no_pre = 1
-<
- *g:html_no_doc*
-Default: 0.
-When 1 it doesn't generate a full HTML document with a DOCTYPE, <head>,
-<body>, etc. If |g:html_use_css| is enabled (the default) you'll have to
-define the CSS manually. The |g:html_dynamic_folds| and |g:html_line_ids|
-settings (off by default) also insert some JavaScript.
-
-
- *g:html_no_links*
-Default: 0.
-Don't generate <a> tags for text that looks like an URL.
-
- *g:html_no_modeline*
-Default: 0.
-Don't generate a modeline disabling folding.
-
- *g:html_expand_tabs*
-Default: 0 if 'tabstop' is 8, 'expandtab' is 0, 'vartabstop' is not in use,
- and no fold column or line numbers occur in the generated HTML;
- 1 otherwise.
-When 1, <Tab> characters in the buffer text are replaced with an appropriate
-number of space characters, or &nbsp; references if |g:html_no_pre| is 1.
-When 0, if |g:html_no_pre| is 0 or unset, <Tab> characters in the buffer text
-are included as-is in the generated HTML. This is useful for when you want to
-allow copy and paste from a browser without losing the actual whitespace in
-the source document. Note that this can easily break text alignment and
-indentation in the HTML, unless set by default.
-
-Force |2html.vim| to keep <Tab> characters: >
- :let g:html_expand_tabs = 0
-<
-Force tabs to be expanded: >
- :let g:html_expand_tabs = 1
-<
- *TOhtml-encoding-detect* *TOhtml-encoding*
-It is highly recommended to set your desired encoding with
-|g:html_use_encoding| for any content which will be placed on a web server.
-
-If you do not specify an encoding, |2html.vim| uses the preferred IANA name
-for the current value of 'fileencoding' if set, or 'encoding' if not.
-'encoding' is always used for certain 'buftype' values. 'fileencoding' will be
-set to match the chosen document encoding.
-
-Automatic detection works for the encodings mentioned specifically by name in
-|encoding-names|, but TOhtml will only automatically use those encodings with
-wide browser support. However, you can override this to support specific
-encodings that may not be automatically detected by default (see options
-below). See https://www.iana.org/assignments/character-sets for the IANA names.
-
-Note: By default all Unicode encodings are converted to UTF-8 with no BOM in
-the generated HTML, as recommended by W3C:
-
- https://www.w3.org/International/questions/qa-choosing-encodings
- https://www.w3.org/International/questions/qa-byte-order-mark
-
- *g:html_use_encoding*
-Default: none, uses IANA name for current 'fileencoding' as above.
-To overrule all automatic charset detection, set g:html_use_encoding to the
-name of the charset to be used. It is recommended to set this variable to
-something widely supported, like UTF-8, for anything you will be hosting on a
-webserver: >
- :let g:html_use_encoding = "UTF-8"
-You can also use this option to omit the line that specifies the charset
-entirely, by setting g:html_use_encoding to an empty string (NOT recommended): >
- :let g:html_use_encoding = ""
-To go back to the automatic mechanism, delete the |g:html_use_encoding|
-variable: >
- :unlet g:html_use_encoding
-<
- *g:html_encoding_override*
-Default: none, autoload/tohtml.vim contains default conversions for encodings
- mentioned by name at |encoding-names|.
-This option allows |2html.vim| to detect the correct 'fileencoding' when you
-specify an encoding with |g:html_use_encoding| which is not in the default
-list of conversions.
-
-This is a dictionary of charset-encoding pairs that will replace existing
-pairs automatically detected by TOhtml, or supplement with new pairs.
-
-Detect the HTML charset "windows-1252" as the encoding "8bit-cp1252": >
- :let g:html_encoding_override = {'windows-1252': '8bit-cp1252'}
-<
- *g:html_charset_override*
-Default: none, autoload/tohtml.vim contains default conversions for encodings
- mentioned by name at |encoding-names| and which have wide
- browser support.
-This option allows |2html.vim| to detect the HTML charset for any
-'fileencoding' or 'encoding' which is not detected automatically. You can also
-use it to override specific existing encoding-charset pairs. For example,
-TOhtml will by default use UTF-8 for all Unicode/UCS encodings. To use UTF-16
-and UTF-32 instead, use: >
- :let g:html_charset_override = {'ucs-4': 'UTF-32', 'utf-16': 'UTF-16'}
-
-Note that documents encoded in either UTF-32 or UTF-16 have known
-compatibility problems with some major browsers.
-
- *g:html_font*
-Default: "monospace"
-You can specify the font or fonts used in the converted document using
-g:html_font. If this option is set to a string, then the value will be
-surrounded with single quotes. If this option is set to a list then each list
-item is surrounded by single quotes and the list is joined with commas. Either
-way, "monospace" is added as the fallback generic family name and the entire
-result used as the font family (using CSS) or font face (if not using CSS).
-Examples: >
-
- " font-family: 'Consolas', monospace;
- :let g:html_font = "Consolas"
-
- " font-family: 'DejaVu Sans Mono', 'Consolas', monospace;
- :let g:html_font = ["DejaVu Sans Mono", "Consolas"]
-<
- *convert-to-XML* *convert-to-XHTML* *g:html_use_xhtml*
-Default: 0.
-When 0, generate standard HTML 4.01 (strict when possible).
-When 1, generate XHTML 1.0 instead (XML compliant HTML).
->
- :let g:html_use_xhtml = 1
-<
==============================================================================
5. Syntax file remarks *:syn-file-remarks*
@@ -964,27 +536,29 @@ An alternative is to switch to the C++ highlighting: >
Variable Highlight ~
*c_gnu* GNU gcc specific items
*c_comment_strings* strings and numbers inside a comment
-*c_space_errors* trailing white space and spaces before a <Tab>
-*c_no_trail_space_error* ... but no trailing spaces
+*c_space_errors* trailing white space and spaces before a <Tab>
+*c_no_trail_space_error* ... but no trailing spaces
*c_no_tab_space_error* ... but no spaces before a <Tab>
*c_no_bracket_error* don't highlight {}; inside [] as errors
*c_no_curly_error* don't highlight {}; inside [] and () as errors;
- except { and } in first column
- Default is to highlight them, otherwise you
- can't spot a missing ")".
+ ...except { and } in first column
+ Default is to highlight them, otherwise you
+ can't spot a missing ")".
*c_curly_error* highlight a missing } by finding all pairs; this
forces syncing from the start of the file, can be slow
*c_no_ansi* don't do standard ANSI types and constants
-*c_ansi_typedefs* ... but do standard ANSI types
+*c_ansi_typedefs* ... but do standard ANSI types
*c_ansi_constants* ... but do standard ANSI constants
*c_no_utf* don't highlight \u and \U in strings
-*c_syntax_for_h* for `*.h` files use C syntax instead of C++ and use objc
+*c_syntax_for_h* for `*.h` files use C syntax instead of C++ and use objc
syntax instead of objcpp
*c_no_if0* don't highlight "#if 0" blocks as comments
*c_no_cformat* don't highlight %-formats in strings
*c_no_c99* don't highlight C99 standard items
*c_no_c11* don't highlight C11 standard items
*c_no_bsd* don't highlight BSD specific types
+*c_functions* highlight function calls and definitions
+*c_function_pointers* highlight function pointers definitions
When 'foldmethod' is set to "syntax" then `/* */` comments and { } blocks will
become a fold. If you don't want comments to become a fold use: >
@@ -1233,7 +807,6 @@ there are very long lines in the file. To disable translations: >
Also see |diff-slow|.
-
DIRCOLORS *dircolors.vim* *ft-dircolors-syntax*
The dircolors utility highlighting definition has one option. It exists to
@@ -1289,12 +862,15 @@ Stack Overflow -
https://stackoverflow.com/questions/12407800/which-comment-style-should-i-use-in-batch-files
-To allow the use of the :: idiom for comments in the Windows Command
-Interpreter or working with MS-DOS bat files, set the
-dosbatch_colons_comment variable to anything: >
+To allow the use of the :: idiom for comments in command blocks with the
+Windows Command Interpreter set the dosbatch_colons_comment variable to
+anything: >
:let dosbatch_colons_comment = 1
+If this variable is set then a :: comment that is the last line in a command
+block will be highlighted as an error.
+
There is an option that covers whether `*.btm` files should be detected as type
"dosbatch" (MS-DOS batch files) or type "btm" (4DOS batch files). The latter
is used by default. You may select the former with the following line: >
@@ -1552,21 +1128,26 @@ edit F# or Fortran at all, use this in your startup vimrc: >
FORTRAN *fortran.vim* *ft-fortran-syntax*
Default highlighting and dialect ~
-Highlighting appropriate for Fortran 2008 is used by default. This choice
-should be appropriate for most users most of the time because Fortran 2008 is
-almost a superset of previous versions (Fortran 2003, 95, 90, and 77).
+Vim highlights according to Fortran 2023 (the most recent standard). This
+choice should be appropriate for most users most of the time because Fortran
+2023 is almost a superset of previous versions (Fortran 2018, 2008, 2003, 95,
+90, 77, and 66). A few legacy constructs deleted or declared obsolescent,
+respectively, in recent Fortran standards are highlighted as errors and todo
+items.
+
+The syntax script no longer supports Fortran dialects. The variable
+fortran_dialect is now silently ignored. Since computers are much faster now,
+the variable fortran_more_precise is no longer needed and is silently ignored.
Fortran source code form ~
Fortran code can be in either fixed or free source form. Note that the
syntax highlighting will not be correct if the form is incorrectly set.
-When you create a new fortran file, the syntax script assumes fixed source
+When you create a new Fortran file, the syntax script assumes fixed source
form. If you always use free source form, then >
:let fortran_free_source=1
-in your vimrc prior to the :syntax on command. If you always use fixed
-source form, then >
+If you always use fixed source form, then >
:let fortran_fixed_source=1
-in your vimrc prior to the :syntax on command.
If the form of the source code depends, in a non-standard way, upon the file
extension, then it is most convenient to set fortran_free_source in a ftplugin
@@ -1575,105 +1156,65 @@ will work only if the "filetype plugin indent on" command precedes the "syntax
on" command in your .vimrc file.
-When you edit an existing fortran file, the syntax script will assume free
+When you edit an existing Fortran file, the syntax script will assume free
source form if the fortran_free_source variable has been set, and assumes
-fixed source form if the fortran_fixed_source variable has been set. If
-neither of these variables have been set, the syntax script attempts to
+fixed source form if the fortran_fixed_source variable has been set. Suppose
+neither of these variables have been set. In that case, the syntax script attempts to
determine which source form has been used by examining the file extension
using conventions common to the ifort, gfortran, Cray, NAG, and PathScale
compilers (.f, .for, .f77 for fixed-source, .f90, .f95, .f03, .f08 for
-free-source). If none of this works, then the script examines the first five
-columns of the first 500 lines of your file. If no signs of free source form
-are detected, then the file is assumed to be in fixed source form. The
-algorithm should work in the vast majority of cases. In some cases, such as a
-file that begins with 500 or more full-line comments, the script may
-incorrectly decide that the fortran code is in fixed form. If that happens,
-just add a non-comment statement beginning anywhere in the first five columns
-of the first twenty-five lines, save (:w) and then reload (:e!) the file.
-
-Tabs in fortran files ~
+free-source). No default is used for the .fpp and .ftn file extensions because
+different compilers treat them differently. If none of this works, then the
+script examines the first five columns of the first 500 lines of your file. If
+no signs of free source form are detected, then the file is assumed to be in
+fixed source form. The algorithm should work in the vast majority of cases.
+In some cases, such as a file that begins with 500 or more full-line comments,
+the script may incorrectly decide that the code is in fixed form. If that
+happens, just add a non-comment statement beginning anywhere in the first five
+columns of the first twenty-five lines, save (:w), and then reload (:e!) the
+file.
+
+Vendor extensions ~
+Fixed-form Fortran requires a maximum line length of 72 characters but the
+script allows a maximum line length of 80 characters as do all compilers
+created in the last three decades. An even longer line length of 132
+characters is allowed if you set the variable fortran_extended_line_length
+with a command such as >
+ :let fortran_extended_line_length=1
+
+If you want additional highlighting of the CUDA Fortran extensions, you should
+set the variable fortran_CUDA with a command such as >
+ :let fortran_CUDA=1
+
+To activate recognition of some common, non-standard, vendor-supplied
+intrinsics, you should set the variable fortran_vendor_intrinsics with a
+command such as >
+ :let fortran_vendor_intrinsics=1
+
+Tabs in Fortran files ~
Tabs are not recognized by the Fortran standards. Tabs are not a good idea in
-fixed format fortran source code which requires fixed column boundaries.
+fixed format Fortran source code which requires fixed column boundaries.
Therefore, tabs are marked as errors. Nevertheless, some programmers like
-using tabs. If your fortran files contain tabs, then you should set the
+using tabs. If your Fortran files contain tabs, then you should set the
variable fortran_have_tabs in your vimrc with a command such as >
:let fortran_have_tabs=1
-placed prior to the :syntax on command. Unfortunately, the use of tabs will
-mean that the syntax file will not be able to detect incorrect margins.
+Unfortunately, the use of tabs will mean that the syntax file will not be able
+to detect incorrect margins.
-Syntax folding of fortran files ~
-If you wish to use foldmethod=syntax, then you must first set the variable
-fortran_fold with a command such as >
+Syntax folding of Fortran files ~
+Vim will fold your file using foldmethod=syntax, if you set the variable
+fortran_fold in your .vimrc with a command such as >
:let fortran_fold=1
to instruct the syntax script to define fold regions for program units, that
is main programs starting with a program statement, subroutines, function
-subprograms, block data subprograms, interface blocks, and modules. If you
-also set the variable fortran_fold_conditionals with a command such as >
+subprograms, modules, submodules, blocks of comment lines, and block data
+units. Block, interface, associate, critical, type definition, and change team
+constructs will also be folded. If you also set the variable
+fortran_fold_conditionals with a command such as >
:let fortran_fold_conditionals=1
-then fold regions will also be defined for do loops, if blocks, and select
-case constructs. If you also set the variable
-fortran_fold_multilinecomments with a command such as >
- :let fortran_fold_multilinecomments=1
-then fold regions will also be defined for three or more consecutive comment
-lines. Note that defining fold regions can be slow for large files.
-
-If fortran_fold, and possibly fortran_fold_conditionals and/or
-fortran_fold_multilinecomments, have been set, then vim will fold your file if
-you set foldmethod=syntax. Comments or blank lines placed between two program
-units are not folded because they are seen as not belonging to any program
-unit.
-
-More precise fortran syntax ~
-If you set the variable fortran_more_precise with a command such as >
- :let fortran_more_precise=1
-then the syntax coloring will be more precise but slower. In particular,
-statement labels used in do, goto and arithmetic if statements will be
-recognized, as will construct names at the end of a do, if, select or forall
-construct.
-
-Non-default fortran dialects ~
-The syntax script supports two Fortran dialects: f08 and F. You will probably
-find the default highlighting (f08) satisfactory. A few legacy constructs
-deleted or declared obsolescent in the 2008 standard are highlighted as todo
-items.
-
-If you use F, the advantage of setting the dialect appropriately is that
-other legacy features excluded from F will be highlighted as todo items and
-that free source form will be assumed.
-
-The dialect can be selected in various ways. If all your fortran files use
-the same dialect, set the global variable fortran_dialect in your vimrc prior
-to your syntax on statement. The case-sensitive, permissible values of
-fortran_dialect are "f08" or "F". Invalid values of fortran_dialect are
-ignored.
-
-If the dialect depends upon the file extension, then it is most convenient to
-set a buffer-local variable in a ftplugin file. For more information on
-ftplugin files, see |ftplugin|. For example, if all your fortran files with
-an .f90 extension are written in the F subset, your ftplugin file should
-contain the code >
- let s:extfname = expand("%:e")
- if s:extfname ==? "f90"
- let b:fortran_dialect="F"
- else
- unlet! b:fortran_dialect
- endif
-Note that this will work only if the "filetype plugin indent on" command
-precedes the "syntax on" command in your vimrc file.
-
-Finer control is necessary if the file extension does not uniquely identify
-the dialect. You can override the default dialect, on a file-by-file basis,
-by including a comment with the directive "fortran_dialect=xx" (where xx=F or
-f08) in one of the first three lines in your file. For example, your older .f
-files may be legacy code but your newer ones may be F codes, and you would
-identify the latter by including in the first three lines of those files a
-Fortran comment of the form >
- ! fortran_dialect=F
-
-For previous versions of the syntax, you may have set fortran_dialect to the
-now-obsolete values "f77", "f90", "f95", or "elf". Such settings will be
-silently handled as "f08". Users of "elf" may wish to experiment with "F"
-instead.
+then fold regions will also be defined for do loops, if blocks, select case,
+select type, and select rank constructs. Note that defining fold regions can
+be slow for large files.
The syntax/fortran.vim script contains embedded comments that tell you how to
comment and/or uncomment some lines to (a) activate recognition of some
@@ -1686,7 +1227,7 @@ Parenthesis checking does not catch too few closing parentheses. Hollerith
strings are not recognized. Some keywords may be highlighted incorrectly
because Fortran90 has no reserved words.
-For further information related to fortran, see |ft-fortran-indent| and
+For further information related to Fortran, see |ft-fortran-indent| and
|ft-fortran-plugin|.
FREEBASIC *freebasic.vim* *ft-freebasic-syntax*
@@ -2236,6 +1777,56 @@ have the following in your vimrc: >
let filetype_m = "mma"
+MODULA2 *modula2.vim* *ft-modula2-syntax*
+
+Vim will recognise comments with dialect tags to automatically select a given
+dialect.
+
+The syntax for a dialect tag comment is: >
+
+ taggedComment :=
+ '(*!' dialectTag '*)'
+ ;
+
+ dialectTag :=
+ m2pim | m2iso | m2r10
+ ;
+
+ reserved words
+ m2pim = 'm2pim', m2iso = 'm2iso', m2r10 = 'm2r10'
+
+A dialect tag comment is recognised by Vim if it occurs within the first 200
+lines of the source file. Only the very first such comment is recognised, any
+additional dialect tag comments are ignored.
+
+Example: >
+
+ DEFINITION MODULE FooLib; (*!m2pim*)
+ ...
+
+Variable g:modula2_default_dialect sets the default Modula-2 dialect when the
+dialect cannot be determined from the contents of the Modula-2 file: if
+defined and set to 'm2pim', the default dialect is PIM.
+
+Example: >
+
+ let g:modula2_default_dialect = 'm2pim'
+
+
+Highlighting is further configurable for each dialect via the following
+variables.
+
+Variable Highlight ~
+*modula2_iso_allow_lowline* allow low line in identifiers
+*modula2_iso_disallow_octals* disallow octal integer literals
+*modula2_iso_disallow_synonyms* disallow "@", "&" and "~" synonyms
+
+*modula2_pim_allow_lowline* allow low line in identifiers
+*modula2_pim_disallow_octals* disallow octal integer literals
+*modula2_pim_disallow_synonyms* disallow "&" and "~" synonyms
+
+*modula2_r10_allow_lowline* allow low line in identifiers
+
MOO *moo.vim* *ft-moo-syntax*
If you use C-style comments inside expressions and find it mangles your
@@ -2827,10 +2418,20 @@ To highlight R code in knitr chunk headers: >
let rmd_syn_hl_chunk = 1
By default, chunks of R code will be highlighted following the rules of R
-language. If you want proper syntax highlighting of chunks of other languages,
-you should add them to either `markdown_fenced_languages` or
-`rmd_fenced_languages`. For example to properly highlight both R and Python,
-you may add this to your |vimrc|: >
+language. Moreover, whenever the buffer is saved, Vim scans the buffer and
+highlights other languages if they are present in new chunks. LaTeX code also
+is automatically recognized and highlighted when the buffer is saved. This
+behavior can be controlled with the variables `rmd_dynamic_fenced_languages`,
+and `rmd_include_latex` whose valid values are: >
+ let rmd_dynamic_fenced_languages = 0 " No autodetection of languages
+ let rmd_dynamic_fenced_languages = 1 " Autodetection of languages
+ let rmd_include_latex = 0 " Don't highlight LaTeX code
+ let rmd_include_latex = 1 " Autodetect LaTeX code
+ let rmd_include_latex = 2 " Always include LaTeX highlighting
+
+If the value of `rmd_dynamic_fenced_languages` is 0, you still can set the
+list of languages whose chunks of code should be properly highlighted, as in
+the example: >
let rmd_fenced_languages = ['r', 'python']
@@ -5163,6 +4764,18 @@ guisp={color-name} *guisp*
Black White
Orange Purple Violet
+ Colors which define Nvim's default color scheme:
+ NvimDarkBlue NvimLightBlue
+ NvimDarkCyan NvimLightCyan
+ NvimDarkGreen NvimLightGreen
+ NvimDarkGrey1 NvimLightGrey1
+ NvimDarkGrey2 NvimLightGrey2
+ NvimDarkGrey3 NvimLightGrey3
+ NvimDarkGrey4 NvimLightGrey4
+ NvimDarkMagenta NvimLightMagenta
+ NvimDarkRed NvimLightRed
+ NvimDarkYellow NvimLightYellow
+
You can also specify a color by its RGB (red, green, blue) values.
The format is "#rrggbb", where
"rr" is the Red value
diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt
index 9bdc6b8d24..5f33802ad5 100644
--- a/runtime/doc/treesitter.txt
+++ b/runtime/doc/treesitter.txt
@@ -17,25 +17,33 @@ 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
+Parsers are the heart of treesitter. They are libraries that treesitter will
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".
+installed via a plugin like https://github.com/nvim-treesitter/nvim-treesitter
+or even manually.
+
+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.
+(NOTE: 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" })
<
+To associate certain |filetypes| with a treesitter language (name of parser),
+use |vim.treesitter.language.register()|. For example, to use the `xml`
+treesitter parser for buffers with filetype `svg` or `xslt`, use: >lua
+
+ vim.treesitter.language.register('xml', { 'svg', 'xslt' })
+<
+
==============================================================================
TREESITTER TREES *treesitter-tree*
*TSTree*
A "treesitter tree" represents the parsed contents of a buffer, which can be
used to perform further analysis. It is a |userdata| reference to an object
-held by the tree-sitter library.
+held by the treesitter library.
An instance `TSTree` of a treesitter tree supports the following methods.
@@ -51,7 +59,7 @@ TREESITTER NODES *treesitter-node*
A "treesitter node" represents one specific element of the parsed contents of
a buffer, which can be captured by a |Query| for, e.g., highlighting. It is
-a |userdata| reference to an object held by the tree-sitter library.
+a |userdata| reference to an object held by the treesitter library.
An instance `TSNode` of a treesitter node supports the following methods.
@@ -202,33 +210,53 @@ TREESITTER QUERY PREDICATES *treesitter-predicates*
Predicates are special scheme nodes that are evaluated to conditionally capture
nodes. For example, the `eq?` predicate can be used as follows: >query
- ((identifier) @foo (#eq? @foo "foo"))
+ ((identifier) @variable.builtin
+ (#eq? @variable.builtin "self"))
<
-to only match identifier corresponding to the `"foo"` text.
+to only match identifier corresponding to the `"self"` text. Such queries can
+be used to highlight built-in functions or variables differently, for instance.
The following predicates are built in:
`eq?` *treesitter-predicate-eq?*
Match a string against the text corresponding to a node: >query
- ((identifier) @foo (#eq? @foo "foo"))
+ ((identifier) @variable.builtin (#eq? @variable.builtin "self"))
((node1) @left (node2) @right (#eq? @left @right))
<
+ `any-eq?` *treesitter-predicate-any-eq?*
+ Like `eq?`, but for quantified patterns only one captured node must
+ match.
+
`match?` *treesitter-predicate-match?*
`vim-match?` *treesitter-predicate-vim-match?*
Match a |regexp| against the text corresponding to a node: >query
((identifier) @constant (#match? @constant "^[A-Z_]+$"))
-< Note: The `^` and `$` anchors will match the start and end of the
+<
+ Note: The `^` and `$` anchors will match the start and end of the
node's text.
+ `any-match?` *treesitter-predicate-any-match?*
+ `any-vim-match?` *treesitter-predicate-any-vim-match?*
+ Like `match?`, but for quantified patterns only one captured node must
+ match.
+
`lua-match?` *treesitter-predicate-lua-match?*
Match |lua-patterns| against the text corresponding to a node,
similar to `match?`
+ `any-lua-match?` *treesitter-predicate-any-lua-match?*
+ Like `lua-match?`, but for quantified patterns only one captured node
+ must match.
+
`contains?` *treesitter-predicate-contains?*
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"))
<
+ `any-contains?` *treesitter-predicate-any-contains?*
+ Like `contains?`, but for quantified patterns only one captured node
+ must match.
+
`any-of?` *treesitter-predicate-any-of?*
Match any of the given strings against the text corresponding to
a node: >query
@@ -254,6 +282,32 @@ The following predicates are built in:
Each predicate has a `not-` prefixed predicate that is just the negation of
the predicate.
+ *lua-treesitter-all-predicate*
+ *lua-treesitter-any-predicate*
+Queries can use quantifiers to capture multiple nodes. When a capture contains
+multiple nodes, predicates match only if ALL nodes contained by the capture
+match the predicate. Some predicates (`eq?`, `match?`, `lua-match?`,
+`contains?`) accept an `any-` prefix to instead match if ANY of the nodes
+contained by the capture match the predicate.
+
+As an example, consider the following Lua code: >lua
+
+ -- TODO: This is a
+ -- very long
+ -- comment (just imagine it)
+<
+using the following predicated query:
+>query
+ (((comment)+ @comment)
+ (#match? @comment "TODO"))
+<
+This query will not match because not all of the nodes captured by @comment
+match the predicate. Instead, use:
+>query
+ (((comment)+ @comment)
+ (#any-match? @comment "TODO"))
+<
+
Further predicates can be added via |vim.treesitter.query.add_predicate()|.
Use |vim.treesitter.query.list_predicates()| to list all available predicates.
@@ -280,11 +334,12 @@ The following directives are built in:
Examples: >query
((identifier) @foo (#set! @foo "kind" "parameter"))
((node1) @left (node2) @right (#set! "type" "pair"))
+ ((codeblock) @markup.raw.block (#set! "priority" 90))
<
`offset!` *treesitter-directive-offset!*
Takes the range of the captured node and applies an offset. This will
- generate a new range object for the captured node as
- `metadata[capture_id].range`.
+ set a new `Range4` object for the captured node with `capture_id` as
+ `metadata[capture_id].range`. Useful for |treesitter-language-injections|.
Parameters: ~
{capture_id}
@@ -297,12 +352,13 @@ The following directives are built in:
((identifier) @constant (#offset! @constant 0 1 0 -1))
<
`gsub!` *treesitter-directive-gsub!*
- Transforms the content of the node using a Lua pattern. This will set
+ Transforms the content of the node using a |lua-pattern|. This will set
a new `metadata[capture_id].text`.
Parameters: ~
{capture_id}
{pattern}
+ {replacement}
Example: >query
(#gsub! @_node ".*%.(.*)" "%1")
@@ -344,13 +400,13 @@ 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
+ ;; inherits: typescript,jsx
;; extends
<
>query
;; extends
;;
- ;; inherits: baz
+ ;; inherits: css
<
==============================================================================
TREESITTER SYNTAX HIGHLIGHTING *treesitter-highlight*
@@ -359,30 +415,47 @@ Syntax highlighting is specified through queries named `highlights.scm`,
which match a |TSNode| in the parsed |TSTree| to a `capture` that can be
assigned a highlight group. For example, the query >query
- (parameters (identifier) @parameter)
+ (parameters (identifier) @variable.parameter)
<
-matches any `identifier` node inside a function `parameter` node (e.g., the
-`bar` in `foo(bar)`) to the capture named `@parameter`. It is also possible to
-match literal expressions (provided the parser returns them): >query
+matches any `identifier` node inside a function `parameters` node to the
+capture named `@variable.parameter`. For example, for a Lua code >lua
- "return" @keyword.return
+ function f(foo, bar) end
+<
+which will be parsed as (see |:InspectTree|): >query
+
+ (function_declaration ; [1:1 - 24]
+ name: (identifier) ; [1:10 - 10]
+ parameters: (parameters ; [1:11 - 20]
+ name: (identifier) ; [1:12 - 14]
+ name: (identifier))) ; [1:17 - 19]
+<
+the above query will highlight `foo` and `bar` as `@variable.parameter`.
+
+It is also possible to match literal expressions (provided the parser returns
+them):
+>query
+ [
+ "if"
+ "else"
+ ] @keyword.conditional
<
Assuming a suitable parser and `highlights.scm` query is found in runtimepath,
treesitter highlighting for the current buffer can be enabled simply via
|vim.treesitter.start()|.
*treesitter-highlight-groups*
-The capture names, with `@` included, are directly usable as highlight groups.
+The capture names, prefixed with `@`, are directly usable as highlight groups.
For many commonly used captures, the corresponding highlight groups are linked
-to Nvim's standard |highlight-groups| by default but can be overridden in
-colorschemes.
+to Nvim's standard |highlight-groups| by default (e.g., `@comment` links to
+`Comment`) but can be overridden in colorschemes.
A fallback system is implemented, so that more specific groups fallback to
-more generic ones. For instance, in a language that has separate doc comments,
-`@comment.doc` could be used. If this group is not defined, the highlighting
-for an ordinary `@comment` is used. This way, existing color schemes already
-work out of the box, but it is possible to add more specific variants for
-queries that make them available.
+more generic ones. For instance, in a language that has separate doc comments
+(e.g., c, java, etc.), `@comment.documentation` could be used. If this group
+is not defined, the highlighting for an ordinary `@comment` is used. This way,
+existing color schemes already work out of the box, but it is possible to add
+more specific variants for queries that make them available.
As an additional rule, capture highlights can always be specialized by
language, by appending the language name after an additional dot. For
@@ -390,61 +463,119 @@ instance, to highlight comments differently per language: >vim
hi @comment.c guifg=Blue
hi @comment.lua guifg=DarkBlue
- hi link @comment.doc.java String
-<
-The following captures are linked by default to standard |group-name|s:
->
- @text.literal Comment
- @text.reference Identifier
- @text.title Title
- @text.uri Underlined
- @text.underline Underlined
- @text.todo Todo
-
- @comment Comment
- @punctuation Delimiter
-
- @constant Constant
- @constant.builtin Special
- @constant.macro Define
- @define Define
- @macro Macro
- @string String
- @string.escape SpecialChar
- @string.special SpecialChar
- @character Character
- @character.special SpecialChar
- @number Number
- @boolean Boolean
- @float Float
-
- @function Function
- @function.builtin Special
- @function.macro Macro
- @parameter Identifier
- @method Function
- @field Identifier
- @property Identifier
- @constructor Special
-
- @conditional Conditional
- @repeat Repeat
- @label Label
- @operator Operator
- @keyword Keyword
- @exception Exception
-
- @variable Identifier
- @type Type
- @type.definition Typedef
- @storageclass StorageClass
- @structure Structure
- @namespace Identifier
- @include Include
- @preproc PreProc
- @debug Debug
- @tag Tag
+ hi link @comment.documentation.java String
<
+The following is a list of standard captures used in queries for Nvim,
+highlighted according to the current colorscheme (use |:Inspect| on one to see
+the exact definition):
+
+@variable various variable names
+@variable.builtin built-in variable names (e.g. `this` / `self`)
+@variable.parameter parameters of a function
+@variable.member object and struct fields
+
+@constant constant identifiers
+@constant.builtin built-in constant values
+@constant.macro constants defined by the preprocessor
+
+@module modules or namespaces
+@module.builtin built-in modules or namespaces
+@label GOTO and other labels (e.g. `label:` in C), including heredoc labels
+
+@string string literals
+@string.documentation string documenting code (e.g. Python docstrings)
+@string.regexp regular expressions
+@string.escape escape sequences
+@string.special other special strings (e.g. dates)
+@string.special.symbol symbols or atoms
+@string.special.path filenames
+@string.special.url URIs (e.g. hyperlinks)
+
+@character character literals
+@character.special special characters (e.g. wildcards)
+
+@boolean boolean literals
+@number numeric literals
+@number.float floating-point number literals
+
+@type type or class definitions and annotations
+@type.builtin built-in types
+@type.definition identifiers in type definitions (e.g. `typedef <type> <identifier>` in C)
+@type.qualifier type qualifiers (e.g. `const`)
+
+@attribute attribute annotations (e.g. Python decorators)
+@property the key in key/value pairs
+
+@function function definitions
+@function.builtin built-in functions
+@function.call function calls
+@function.macro preprocessor macros
+
+@function.method method definitions
+@function.method.call method calls
+
+@constructor constructor calls and definitions
+@operator symbolic operators (e.g. `+` / `*`)
+
+@keyword keywords not fitting into specific categories
+@keyword.coroutine keywords related to coroutines (e.g. `go` in Go, `async/await` in Python)
+@keyword.function keywords that define a function (e.g. `func` in Go, `def` in Python)
+@keyword.operator operators that are English words (e.g. `and` / `or`)
+@keyword.import keywords for including modules (e.g. `import` / `from` in Python)
+@keyword.storage modifiers that affect storage in memory or life-time
+@keyword.repeat keywords related to loops (e.g. `for` / `while`)
+@keyword.return keywords like `return` and `yield`
+@keyword.debug keywords related to debugging
+@keyword.exception keywords related to exceptions (e.g. `throw` / `catch`)
+
+@keyword.conditional keywords related to conditionals (e.g. `if` / `else`)
+@keyword.conditional.ternary ternary operator (e.g. `?` / `:`)
+
+@keyword.directive various preprocessor directives and shebangs
+@keyword.directive.define preprocessor definition directives
+
+@punctuation.delimiter delimiters (e.g. `;` / `.` / `,`)
+@punctuation.bracket brackets (e.g. `()` / `{}` / `[]`)
+@punctuation.special special symbols (e.g. `{}` in string interpolation)
+
+@comment line and block comments
+@comment.documentation comments documenting code
+
+@comment.error error-type comments (e.g. `ERROR`, `FIXME`, `DEPRECATED`)
+@comment.warning warning-type comments (e.g. `WARNING`, `FIX`, `HACK`)
+@comment.todo todo-type comments (e.g. `TODO`, `WIP`, `FIXME`)
+@comment.note note-type comments (e.g. `NOTE`, `INFO`, `XXX`)
+
+@markup.strong bold text
+@markup.italic italic text
+@markup.strikethrough struck-through text
+@markup.underline underlined text (only for literal underline markup!)
+
+@markup.heading headings, titles (including markers)
+
+@markup.quote block quotes
+@markup.math math environments (e.g. `$ ... $` in LaTeX)
+@markup.environment environments (e.g. in LaTeX)
+
+@markup.link text references, footnotes, citations, etc.
+@markup.link.label link, reference descriptions
+@markup.link.url URL-style links
+
+@markup.raw literal or verbatim text (e.g. inline code)
+@markup.raw.block literal or verbatim text as a stand-alone block
+
+@markup.list list markers
+@markup.list.checked checked todo-style list markers
+@markup.list.unchecked unchecked todo-style list markers
+
+@diff.plus added text (for diff files)
+@diff.minus deleted text (for diff files)
+@diff.delta changed text (for diff files)
+
+@tag XML-style tag names (e.g. in XML, HTML, etc.)
+@tag.attribute XML-style tag attributes
+@tag.delimiter XML-style tag delimiters
+
*treesitter-highlight-spell*
The special `@spell` capture can be used to indicate that a node should be
spell checked by Nvim's builtin |spell| checker. For example, the following
@@ -475,7 +606,7 @@ Conceals specified in this way respect 'conceallevel'.
*treesitter-highlight-priority*
Treesitter uses |nvim_buf_set_extmark()| to set highlights with a default
priority of 100. This enables plugins to set a highlighting priority lower or
-higher than tree-sitter. It is also possible to change the priority of an
+higher than treesitter. It is also possible to change the priority of an
individual query pattern manually by setting its `"priority"` metadata
attribute: >query
@@ -536,17 +667,17 @@ associated with patterns:
VIM.TREESITTER *lua-treesitter*
The remainder of this document is a reference manual for the `vim.treesitter`
-Lua module, which is the main interface for Nvim's tree-sitter integration.
+Lua module, which is the main interface for Nvim's treesitter integration.
Most of the following content is automatically generated from the function
documentation.
*vim.treesitter.language_version*
-The latest parser ABI version that is supported by the bundled tree-sitter
+The latest parser ABI version that is supported by the bundled treesitter
library.
*vim.treesitter.minimum_language_version*
-The earliest parser ABI version that is supported by the bundled tree-sitter
+The earliest parser ABI version that is supported by the bundled treesitter
library.
==============================================================================
@@ -559,30 +690,20 @@ foldexpr({lnum}) *vim.treesitter.foldexpr()*
<
Parameters: ~
- • {lnum} (integer|nil) Line number to calculate fold level for
-
- Return: ~
- (string)
-
-foldtext() *vim.treesitter.foldtext()*
- Returns the highlighted content of the first line of the fold or falls
- back to |foldtext()| if no treesitter parser is found. Can be set directly
- to 'foldtext': >lua
- vim.wo.foldtext = 'v:lua.vim.treesitter.foldtext()'
-<
+ • {lnum} (`integer?`) Line number to calculate fold level for
Return: ~
- `{ [1]: string, [2]: string[] }[]` | string
+ (`string`)
*vim.treesitter.get_captures_at_cursor()*
get_captures_at_cursor({winnr})
Returns a list of highlight capture names under the cursor
Parameters: ~
- • {winnr} (integer|nil) Window handle or 0 for current window (default)
+ • {winnr} (`integer?`) Window handle or 0 for current window (default)
Return: ~
- string[] List of capture names
+ (`string[]`) List of capture names
*vim.treesitter.get_captures_at_pos()*
get_captures_at_pos({bufnr}, {row}, {col})
@@ -593,12 +714,13 @@ get_captures_at_pos({bufnr}, {row}, {col})
if none are defined).
Parameters: ~
- • {bufnr} (integer) Buffer number (0 for current buffer)
- • {row} (integer) Position row
- • {col} (integer) Position column
+ • {bufnr} (`integer`) Buffer number (0 for current buffer)
+ • {row} (`integer`) Position row
+ • {col} (`integer`) Position column
Return: ~
- table[] List of captures `{ capture = "name", metadata = { ... } }`
+ (`table[]`) List of captures
+ `{ capture = "name", metadata = { ... } }`
get_node({opts}) *vim.treesitter.get_node()*
Returns the smallest named node at the given position
@@ -610,45 +732,47 @@ get_node({opts}) *vim.treesitter.get_node()*
<
Parameters: ~
- • {opts} (table|nil) Optional keyword arguments:
- • bufnr integer|nil Buffer number (nil or 0 for current
+ • {opts} (`table?`) Optional keyword arguments:
+ • {bufnr} (`integer?`) Buffer number (nil or 0 for current
buffer)
- • pos table|nil 0-indexed (row, col) tuple. Defaults to cursor
- position in the current window. Required if {bufnr} is not
- the current buffer
- • ignore_injections boolean Ignore injected languages (default
- true)
+ • {pos} (`{ [1]: integer, [2]: integer }?`) 0-indexed (row,
+ col) tuple. Defaults to cursor position in the current
+ window. Required if {bufnr} is not the current buffer
+ • {lang} (`string?`) Parser language. (default: from buffer
+ filetype)
+ • {ignore_injections} (`boolean?`) Ignore injected languages
+ (default true)
Return: ~
- |TSNode| | nil Node at the given position
+ (`TSNode?`) Node at the given position
get_node_range({node_or_range}) *vim.treesitter.get_node_range()*
Returns the node's range or an unpacked range table
Parameters: ~
- • {node_or_range} (|TSNode| | table) Node or table of positions
+ • {node_or_range} (`TSNode|table`) Node or table of positions
Return (multiple): ~
- (integer) start_row
- (integer) start_col
- (integer) end_row
- (integer) end_col
+ (`integer`) start_row
+ (`integer`) start_col
+ (`integer`) end_row
+ (`integer`) end_col
*vim.treesitter.get_node_text()*
get_node_text({node}, {source}, {opts})
Gets the text corresponding to a given node
Parameters: ~
- • {node} |TSNode|
- • {source} (integer|string) Buffer or string from which the {node} is
+ • {node} (`TSNode`)
+ • {source} (`integer|string`) Buffer or string from which the {node} is
extracted
- • {opts} (table|nil) Optional parameters.
+ • {opts} (`table?`) Optional parameters.
• metadata (table) Metadata of a specific capture. This
would be set to `metadata[capture_id]` when using
|vim.treesitter.query.add_directive()|.
Return: ~
- (string)
+ (`string`)
get_parser({bufnr}, {lang}, {opts}) *vim.treesitter.get_parser()*
Returns the parser for a specific buffer and attaches it to the buffer
@@ -656,39 +780,39 @@ get_parser({bufnr}, {lang}, {opts}) *vim.treesitter.get_parser()*
If needed, this will create the parser.
Parameters: ~
- • {bufnr} (integer|nil) Buffer the parser should be tied to (default:
+ • {bufnr} (`integer?`) Buffer the parser should be tied to (default:
current buffer)
- • {lang} (string|nil) Filetype of this parser (default: buffer
+ • {lang} (`string?`) Language of this parser (default: from buffer
filetype)
- • {opts} (table|nil) Options to pass to the created language tree
+ • {opts} (`table?`) Options to pass to the created language tree
Return: ~
- |LanguageTree| object to use for parsing
+ (`vim.treesitter.LanguageTree`) object to use for parsing
get_range({node}, {source}, {metadata}) *vim.treesitter.get_range()*
Get the range of a |TSNode|. Can also supply {source} and {metadata} to
get the range with directives applied.
Parameters: ~
- • {node} |TSNode|
- • {source} integer|string|nil Buffer or string from which the {node}
+ • {node} (`TSNode`)
+ • {source} (`integer|string?`) Buffer or string from which the {node}
is extracted
- • {metadata} TSMetadata|nil
+ • {metadata} (`vim.treesitter.query.TSMetadata?`)
Return: ~
- (table)
+ (`Range6`)
*vim.treesitter.get_string_parser()*
get_string_parser({str}, {lang}, {opts})
Returns a string parser
Parameters: ~
- • {str} (string) Text to parse
- • {lang} (string) Language of this string
- • {opts} (table|nil) Options to pass to the created language tree
+ • {str} (`string`) Text to parse
+ • {lang} (`string`) Language of this string
+ • {opts} (`table?`) Options to pass to the created language tree
Return: ~
- |LanguageTree| object to use for parsing
+ (`vim.treesitter.LanguageTree`) object to use for parsing
inspect_tree({opts}) *vim.treesitter.inspect_tree()*
Open a window that displays a textual representation of the nodes in the
@@ -697,15 +821,15 @@ inspect_tree({opts}) *vim.treesitter.inspect_tree()*
While in the window, press "a" to toggle display of anonymous nodes, "I"
to toggle the display of the source language of each node, "o" to toggle
the query editor, and press <Enter> to jump to the node under the cursor
- in the source buffer.
+ in the source buffer. Folding also works (try |zo|, |zc|, etc.).
Can also be shown with `:InspectTree`. *:InspectTree*
Parameters: ~
- • {opts} (table|nil) Optional options table with the following possible
+ • {opts} (`table?`) Optional options table with the following possible
keys:
• lang (string|nil): The language of the source buffer. If
- omitted, the filetype of the source buffer is used.
+ omitted, detect from the filetype of the source buffer.
• bufnr (integer|nil): Buffer to draw the tree into. If
omitted, a new buffer is created.
• winid (integer|nil): Window id to display the tree buffer
@@ -722,33 +846,33 @@ is_ancestor({dest}, {source}) *vim.treesitter.is_ancestor()*
Determines whether a node is the ancestor of another
Parameters: ~
- • {dest} |TSNode| Possible ancestor
- • {source} |TSNode| Possible descendant
+ • {dest} (`TSNode`) Possible ancestor
+ • {source} (`TSNode`) Possible descendant
Return: ~
- (boolean) True if {dest} is an ancestor of {source}
+ (`boolean`) True if {dest} is an ancestor of {source}
*vim.treesitter.is_in_node_range()*
is_in_node_range({node}, {line}, {col})
Determines whether (line, col) position is in node range
Parameters: ~
- • {node} |TSNode| defining the range
- • {line} (integer) Line (0-based)
- • {col} (integer) Column (0-based)
+ • {node} (`TSNode`) defining the range
+ • {line} (`integer`) Line (0-based)
+ • {col} (`integer`) Column (0-based)
Return: ~
- (boolean) True if the position is in node range
+ (`boolean`) True if the position is in node range
node_contains({node}, {range}) *vim.treesitter.node_contains()*
Determines if a node contains a range
Parameters: ~
- • {node} |TSNode|
- • {range} (table)
+ • {node} (`TSNode`)
+ • {range} (`table`)
Return: ~
- (boolean) True if the {node} contains the {range}
+ (`boolean`) True if the {node} contains the {range}
start({bufnr}, {lang}) *vim.treesitter.start()*
Starts treesitter highlighting for a buffer
@@ -769,16 +893,16 @@ start({bufnr}, {lang}) *vim.treesitter.start()*
<
Parameters: ~
- • {bufnr} (integer|nil) Buffer to be highlighted (default: current
+ • {bufnr} (`integer?`) Buffer to be highlighted (default: current
buffer)
- • {lang} (string|nil) Language of the parser (default: buffer
+ • {lang} (`string?`) Language of the parser (default: from buffer
filetype)
stop({bufnr}) *vim.treesitter.stop()*
Stops treesitter highlighting for a buffer
Parameters: ~
- • {bufnr} (integer|nil) Buffer to stop highlighting (default: current
+ • {bufnr} (`integer?`) Buffer to stop highlighting (default: current
buffer)
@@ -792,29 +916,30 @@ add({lang}, {opts}) *vim.treesitter.language.add()*
{path}
Parameters: ~
- • {lang} (string) Name of the parser (alphanumerical and `_` only)
- • {opts} (table|nil) Options:
- • filetype (string|string[]) Default filetype the parser
- should be associated with. Defaults to {lang}.
- • path (string|nil) Optional path the parser is located at
- • symbol_name (string|nil) Internal symbol name for the
+ • {lang} (`string`) Name of the parser (alphanumerical and `_` only)
+ • {opts} (`table?`) Options:
+ • {filetype}? (`string|string[]`, default: {lang}) Default
+ filetype the parser should be associated with.
+ • {path}? (`string`) Optional path the parser is located at
+ • {symbol_name}? (`string`) Internal symbol name for the
language to load
get_filetypes({lang}) *vim.treesitter.language.get_filetypes()*
Get the filetypes associated with the parser named {lang}.
Parameters: ~
- • {lang} (string) Name of parser
+ • {lang} (`string`) Name of parser
Return: ~
- string[] filetypes
+ (`string[]`) filetypes
get_lang({filetype}) *vim.treesitter.language.get_lang()*
+
Parameters: ~
- • {filetype} (string)
+ • {filetype} (`string`)
Return: ~
- (string|nil)
+ (`string?`)
inspect({lang}) *vim.treesitter.language.inspect()*
Inspects the provided language.
@@ -823,55 +948,70 @@ inspect({lang}) *vim.treesitter.language.inspect()*
names, ...
Parameters: ~
- • {lang} (string) Language
+ • {lang} (`string`) Language
Return: ~
- (table)
+ (`table`)
register({lang}, {filetype}) *vim.treesitter.language.register()*
Register a parser named {lang} to be used for {filetype}(s).
+ Note: this adds or overrides the mapping for {filetype}, any existing
+ mappings from other filetypes to {lang} will be preserved.
+
Parameters: ~
- • {lang} (string) Name of parser
- • {filetype} string|string[] Filetype(s) to associate with lang
+ • {lang} (`string`) Name of parser
+ • {filetype} (`string|string[]`) Filetype(s) to associate with lang
==============================================================================
Lua module: vim.treesitter.query *lua-treesitter-query*
*vim.treesitter.query.add_directive()*
-add_directive({name}, {handler}, {force})
+add_directive({name}, {handler}, {opts})
Adds a new directive to be used in queries
Handlers can set match level data by setting directly on the metadata
- object `metadata.key = value`, additionally, handlers can set node level
+ object `metadata.key = value`. Additionally, handlers can set node level
data by using the capture id on the metadata table
`metadata[capture_id].key = value`
Parameters: ~
- • {name} (string) Name of the directive, without leading #
- • {handler} function(match:table<string,|TSNode|>, pattern:string,
- bufnr:integer, predicate:string[], metadata:table)
- • match: see |treesitter-query|
- • node-level data are accessible via `match[capture_id]`
-
- • pattern: see |treesitter-query|
+ • {name} (`string`) Name of the directive, without leading #
+ • {handler} (`function`)
+ • match: A table mapping capture IDs to a list of captured
+ nodes
+ • pattern: the index of the matching pattern in the query
+ file
• predicate: list of strings containing the full directive
being called, e.g. `(node (#set! conceal "-"))` would get
the predicate `{ "#set!", "conceal", "-" }`
- • {force} (boolean|nil)
+ • {opts} (`table<string, any>`) Optional options:
+ • force (boolean): Override an existing predicate of the
+ same name
+ • all (boolean): Use the correct implementation of the
+ match table where capture IDs map to a list of nodes
+ instead of a single node. Defaults to false (for backward
+ compatibility). This option will eventually become the
+ default and removed.
*vim.treesitter.query.add_predicate()*
-add_predicate({name}, {handler}, {force})
+add_predicate({name}, {handler}, {opts})
Adds a new predicate to be used in queries
Parameters: ~
- • {name} (string) Name of the predicate, without leading #
- • {handler} function(match:table<string,|TSNode|>, pattern:string,
- bufnr:integer, predicate:string[])
+ • {name} (`string`) Name of the predicate, without leading #
+ • {handler} (`function`)
• see |vim.treesitter.query.add_directive()| for argument
meanings
- • {force} (boolean|nil)
+ • {opts} (`table<string, any>`) Optional options:
+ • force (boolean): Override an existing predicate of the
+ same name
+ • all (boolean): Use the correct implementation of the
+ match table where capture IDs map to a list of nodes
+ instead of a single node. Defaults to false (for backward
+ compatibility). This option will eventually become the
+ default and removed.
edit({lang}) *vim.treesitter.query.edit()*
Opens a live editor to query the buffer you started from.
@@ -884,31 +1024,33 @@ edit({lang}) *vim.treesitter.query.edit()*
`$VIMRUNTIME/queries/`.
Parameters: ~
- • {lang} (string|nil) language to open the query editor for. If
- omitted, inferred from the current buffer's filetype.
+ • {lang} (`string?`) language to open the query editor for. If omitted,
+ inferred from the current buffer's filetype.
get({lang}, {query_name}) *vim.treesitter.query.get()*
Returns the runtime query {query_name} for {lang}.
Parameters: ~
- • {lang} (string) Language to use for the query
- • {query_name} (string) Name of the query (e.g. "highlights")
+ • {lang} (`string`) Language to use for the query
+ • {query_name} (`string`) Name of the query (e.g. "highlights")
Return: ~
- Query|nil Parsed query
+ (`vim.treesitter.Query?`) Parsed query. `nil` if no query files are
+ found.
*vim.treesitter.query.get_files()*
get_files({lang}, {query_name}, {is_included})
Gets the list of files used to make up a query
Parameters: ~
- • {lang} (string) Language to get query for
- • {query_name} (string) Name of the query to load (e.g., "highlights")
- • {is_included} (boolean|nil) Internal parameter, most of the time left
+ • {lang} (`string`) Language to get query for
+ • {query_name} (`string`) Name of the query to load (e.g.,
+ "highlights")
+ • {is_included} (`boolean?`) Internal parameter, most of the time left
as `nil`
Return: ~
- string[] query_files List of files to load for given query and
+ (`string[]`) query_files List of files to load for given query and
language
lint({buf}, {opts}) *vim.treesitter.query.lint()*
@@ -916,34 +1058,34 @@ lint({buf}, {opts}) *vim.treesitter.query.lint()*
Use |treesitter-parsers| in runtimepath to check the query file in {buf}
for errors:
-
• verify that used nodes are valid identifiers in the grammar.
• verify that predicates and directives are valid.
• verify that top-level s-expressions are valid.
The found diagnostics are reported using |diagnostic-api|. By default, the
parser used for verification is determined by the containing folder of the
- query file, e.g., if the path ends in `/lua/highlights.scm` , the parser for the `lua` language will be used.
+ query file, e.g., if the path ends in `/lua/highlights.scm`, the parser
+ for the `lua` language will be used.
Parameters: ~
- • {buf} (integer) Buffer handle
- • {opts} (QueryLinterOpts|nil) Optional keyword arguments:
- • langs (string|string[]|nil) Language(s) to use for checking
+ • {buf} (`integer`) Buffer handle
+ • {opts} (`table?`) Optional keyword arguments:
+ • {langs}? (`string|string[]`) Language(s) to use for checking
the query. If multiple languages are specified, queries are
validated for all of them
- • clear (boolean) if `true`, just clear current lint errors
+ • {clear} (`boolean`) Just clear current lint errors
list_directives() *vim.treesitter.query.list_directives()*
Lists the currently available directives to use in queries.
Return: ~
- string[] List of supported directives.
+ (`string[]`) List of supported directives.
list_predicates() *vim.treesitter.query.list_predicates()*
Lists the currently available predicates to use in queries.
Return: ~
- string[] List of supported predicates.
+ (`string[]`) List of supported predicates.
omnifunc({findstart}, {base}) *vim.treesitter.query.omnifunc()*
Omnifunc for completing node names and predicates in treesitter queries.
@@ -952,24 +1094,32 @@ omnifunc({findstart}, {base}) *vim.treesitter.query.omnifunc()*
vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc'
<
+ Parameters: ~
+ • {findstart} (`0|1`)
+ • {base} (`string`)
+
parse({lang}, {query}) *vim.treesitter.query.parse()*
Parse {query} as a string. (If the query is in a file, the caller should
read the contents into a string before calling).
- Returns a `Query` (see |lua-treesitter-query|) object which can be used to search nodes in
- the syntax tree for the patterns defined in {query} using `iter_*` methods below.
+ Returns a `Query` (see |lua-treesitter-query|) object which can be used to
+ search nodes in the syntax tree for the patterns defined in {query} using
+ the `iter_captures` and `iter_matches` methods.
Exposes `info` and `captures` with additional context about {query}.
• `captures` contains the list of unique capture names defined in {query}.
- -`info.captures` also points to `captures`.
+ • `info.captures` also points to `captures`.
• `info.patterns` contains information about predicates.
Parameters: ~
- • {lang} (string) Language to use for the query
- • {query} (string) Query in s-expr syntax
+ • {lang} (`string`) Language to use for the query
+ • {query} (`string`) Query in s-expr syntax
Return: ~
- Query Parsed query
+ (`vim.treesitter.Query`) Parsed query
+
+ See also: ~
+ • |vim.treesitter.query.get()|
*Query:iter_captures()*
Query:iter_captures({node}, {source}, {start}, {stop})
@@ -995,15 +1145,17 @@ Query:iter_captures({node}, {source}, {start}, {stop})
<
Parameters: ~
- • {node} |TSNode| under which the search will occur
- • {source} (integer|string) Source buffer or string to extract text
+ • {node} (`TSNode`) under which the search will occur
+ • {source} (`integer|string`) Source buffer or string to extract text
from
- • {start} (integer) Starting line for the search
- • {stop} (integer) Stopping line for the search (end-exclusive)
+ • {start} (`integer?`) Starting line for the search. Defaults to
+ `node:start()`.
+ • {stop} (`integer?`) Stopping line for the search (end-exclusive).
+ Defaults to `node:end_()`.
Return: ~
- (fun(end_line: integer|nil): integer, TSNode, TSMetadata): capture id,
- capture node, metadata
+ (`fun(end_line: integer?): integer, TSNode, vim.treesitter.query.TSMetadata`)
+ capture id, capture node, metadata
*Query:iter_matches()*
Query:iter_matches({node}, {source}, {start}, {stop}, {opts})
@@ -1012,35 +1164,48 @@ Query:iter_matches({node}, {source}, {start}, {stop}, {opts})
Iterate over all matches within a {node}. The arguments are the same as
for |Query:iter_captures()| but the iterated values are different: an
(1-based) index of the pattern in the query, a table mapping capture
- indices to nodes, and metadata from any directives processing the match.
- If the query has more than one pattern, the capture table might be sparse
- and e.g. `pairs()` method should be used over `ipairs`. Here is an example
- iterating over all captures in every match: >lua
- for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, first, last) do
- for id, node in pairs(match) do
- local name = query.captures[id]
- -- `node` was captured by the `name` capture in the match
+ indices to a list of nodes, and metadata from any directives processing
+ the match.
+
+ WARNING: Set `all=true` to ensure all matching nodes in a match are
+ returned, otherwise only the last node in a match is returned, breaking
+ captures involving quantifiers such as `(comment)+ @comment`. The default
+ option `all=false` is only provided for backward compatibility and will be
+ removed after Nvim 0.10.
- local node_data = metadata[id] -- Node level metadata
+ Example: >lua
+ for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, 0, -1, { all = true }) do
+ for id, nodes in pairs(match) do
+ local name = query.captures[id]
+ for _, node in ipairs(nodes) do
+ -- `node` was captured by the `name` capture in the match
- -- ... use the info here ...
+ local node_data = metadata[id] -- Node level metadata
+ ... use the info here ...
+ end
end
end
<
Parameters: ~
- • {node} |TSNode| under which the search will occur
- • {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:
+ • {node} (`TSNode`) under which the search will occur
+ • {source} (`integer|string`) Source buffer or string to search
+ • {start} (`integer?`) Starting line for the search. Defaults to
+ `node:start()`.
+ • {stop} (`integer?`) Stopping line for the search (end-exclusive).
+ Defaults to `node:end_()`.
+ • {opts} (`table?`) Optional keyword arguments:
• 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.
+ traversing too deep into a tree.
+ • all (boolean) When set, the returned match table maps
+ capture IDs to a list of nodes. Older versions of
+ iter_matches incorrectly mapped capture IDs to a single
+ node, which is incorrect behavior. This option will
+ eventually become the default and removed.
Return: ~
- (fun(): integer, table<integer,TSNode>, table): pattern id, match,
+ (`fun(): integer, table<integer, TSNode[]>, table`) pattern id, match,
metadata
set({lang}, {query_name}, {text}) *vim.treesitter.query.set()*
@@ -1050,49 +1215,44 @@ set({lang}, {query_name}, {text}) *vim.treesitter.query.set()*
by plugins.
Parameters: ~
- • {lang} (string) Language to use for the query
- • {query_name} (string) Name of the query (e.g., "highlights")
- • {text} (string) Query text (unparsed).
+ • {lang} (`string`) Language to use for the query
+ • {query_name} (`string`) Name of the query (e.g., "highlights")
+ • {text} (`string`) Query text (unparsed).
==============================================================================
Lua module: vim.treesitter.languagetree *lua-treesitter-languagetree*
-
-A *LanguageTree* contains a tree of parsers: the root treesitter parser
-for {lang} and any "injected" language parsers, which themselves may
-inject other languages, recursively. For example a Lua buffer containing
-some Vimscript commands needs multiple parsers to fully understand its
-contents.
+A *LanguageTree* contains a tree of parsers: the root treesitter parser for
+{lang} and any "injected" language parsers, which themselves may inject other
+languages, recursively. For example a Lua buffer containing some Vimscript
+commands needs multiple parsers to fully understand its contents.
To create a LanguageTree (parser object) for a given buffer and language, use: >lua
local parser = vim.treesitter.get_parser(bufnr, lang)
-
<
-(where `bufnr=0` means current buffer). `lang` defaults to 'filetype'.
-Note: currently the parser is retained for the lifetime of a buffer but
-this may change; a plugin should keep a reference to the parser object if
-it wants incremental updates.
+(where `bufnr=0` means current buffer). `lang` defaults to 'filetype'. Note:
+currently the parser is retained for the lifetime of a buffer but this may
+change; a plugin should keep a reference to the parser object if it wants
+incremental updates.
Whenever you need to access the current syntax tree, parse the buffer: >lua
local tree = parser:parse({ start_row, end_row })
-
<
-This returns a table of immutable |treesitter-tree| objects representing
-the current state of the buffer. When the plugin wants to access the state
-after a (possible) edit it must call `parse()` again. If the buffer wasn't
-edited, the same tree will be returned again without extra work. If the
-buffer was parsed before, incremental parsing will be done of the changed
-parts.
+This returns a table of immutable |treesitter-tree| objects representing the
+current state of the buffer. When the plugin wants to access the state after a
+(possible) edit it must call `parse()` again. If the buffer wasn't edited, the
+same tree will be returned again without extra work. If the buffer was parsed
+before, incremental parsing will be done of the changed parts.
+
+Note: To use the parser directly inside a |nvim_buf_attach()| Lua callback,
+you must call |vim.treesitter.get_parser()| before you register your callback.
+But preferably parsing 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.
-Note: To use the parser directly inside a |nvim_buf_attach()| Lua
-callback, you must call |vim.treesitter.get_parser()| before you register
-your callback. But preferably parsing 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.
LanguageTree:children() *LanguageTree:children()*
Returns a map of language to child tree.
@@ -1101,10 +1261,10 @@ LanguageTree:contains({range}) *LanguageTree:contains()*
Determines whether {range} is contained in the |LanguageTree|.
Parameters: ~
- • {range} (table) `{ start_line, start_col, end_line, end_col }`
+ • {range} (`Range4`) `{ start_line, start_col, end_line, end_col }`
Return: ~
- (boolean)
+ (`boolean`)
LanguageTree:destroy() *LanguageTree:destroy()*
Destroys this |LanguageTree| and all its children.
@@ -1120,32 +1280,33 @@ LanguageTree:for_each_tree({fn}) *LanguageTree:for_each_tree()*
Note: This includes the invoking tree's child trees as well.
Parameters: ~
- • {fn} fun(tree: TSTree, ltree: LanguageTree)
+ • {fn} (`fun(tree: TSTree, ltree: vim.treesitter.LanguageTree)`)
LanguageTree:included_regions() *LanguageTree:included_regions()*
- Gets the set of included regions managed by this LanguageTree . This can be different from the regions set by injection query, because a
- partial |LanguageTree:parse()| drops the regions outside the requested
- range.
+ Gets the set of included regions managed by this LanguageTree. This can be
+ different from the regions set by injection query, because a partial
+ |LanguageTree:parse()| drops the regions outside the requested range.
Return: ~
- table<integer, Range6[]>
+ (`table<integer, Range6[]>`)
LanguageTree:invalidate({reload}) *LanguageTree:invalidate()*
Invalidates this parser and all its children
Parameters: ~
- • {reload} (boolean|nil)
+ • {reload} (`boolean?`)
LanguageTree:is_valid({exclude_children}) *LanguageTree:is_valid()*
- Returns whether this LanguageTree is valid, i.e., |LanguageTree:trees()| reflects the latest state of the
- source. If invalid, user should call |LanguageTree:parse()|.
+ Returns whether this LanguageTree is valid, i.e., |LanguageTree:trees()|
+ reflects the latest state of the source. If invalid, user should call
+ |LanguageTree:parse()|.
Parameters: ~
- • {exclude_children} (boolean|nil) whether to ignore the validity of
+ • {exclude_children} (`boolean?`) whether to ignore the validity of
children (default `false`)
Return: ~
- (boolean)
+ (`boolean`)
LanguageTree:lang() *LanguageTree:lang()*
Gets the language of this tree node.
@@ -1155,23 +1316,23 @@ LanguageTree:language_for_range({range})
Gets the appropriate language that contains {range}.
Parameters: ~
- • {range} (table) `{ start_line, start_col, end_line, end_col }`
+ • {range} (`Range4`) `{ start_line, start_col, end_line, end_col }`
Return: ~
- |LanguageTree| Managing {range}
+ (`vim.treesitter.LanguageTree`) Managing {range}
*LanguageTree:named_node_for_range()*
LanguageTree:named_node_for_range({range}, {opts})
Gets the smallest named node that contains {range}.
Parameters: ~
- • {range} (table) `{ start_line, start_col, end_line, end_col }`
- • {opts} (table|nil) Optional keyword arguments:
+ • {range} (`Range4`) `{ start_line, start_col, end_line, end_col }`
+ • {opts} (`table?`) Optional keyword arguments:
• ignore_injections boolean Ignore injected languages
(default true)
Return: ~
- |TSNode| | nil Found node
+ (`TSNode?`) Found node
LanguageTree:parse({range}) *LanguageTree:parse()*
Recursively parse all regions in the language tree using
@@ -1184,23 +1345,24 @@ LanguageTree:parse({range}) *LanguageTree:parse()*
if {range} is `true`).
Parameters: ~
- • {range} boolean|Range|nil: Parse this range in the parser's source.
+ • {range} (`boolean|Range?`) Parse this range in the parser's source.
Set to `true` to run a complete parse of the source (Note:
Can be slow!) Set to `false|nil` to only parse regions with
empty ranges (typically only the root tree without
injections).
Return: ~
- table<integer, TSTree>
+ (`table<integer, TSTree>`)
*LanguageTree:register_cbs()*
LanguageTree:register_cbs({cbs}, {recursive})
Registers callbacks for the |LanguageTree|.
Parameters: ~
- • {cbs} (table) An |nvim_buf_attach()|-like table argument with
+ • {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_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 be
passed two arguments: a table of the ranges (as node
@@ -1212,7 +1374,7 @@ LanguageTree:register_cbs({cbs}, {recursive})
• `on_detach` : emitted when the buffer is detached, see
|nvim_buf_detach_event|. Takes one argument, the number
of the buffer.
- • {recursive} (boolean|nil) Apply callbacks recursively for all
+ • {recursive} (`boolean?`) Apply callbacks recursively for all
children. Any new children will also inherit the
callbacks.
@@ -1224,21 +1386,23 @@ LanguageTree:tree_for_range({range}, {opts})
Gets the tree that contains {range}.
Parameters: ~
- • {range} (table) `{ start_line, start_col, end_line, end_col }`
- • {opts} (table|nil) Optional keyword arguments:
+ • {range} (`Range4`) `{ start_line, start_col, end_line, end_col }`
+ • {opts} (`table?`) Optional keyword arguments:
• ignore_injections boolean Ignore injected languages
(default true)
Return: ~
- TSTree|nil
+ (`TSTree?`)
LanguageTree:trees() *LanguageTree:trees()*
Returns all trees of the regions parsed by this parser. Does not include
child languages. The result is list-like if
- • this LanguageTree is the root, in which case the result is empty or a singleton list; or
+ • this LanguageTree is the root, in which case the result is empty or a
+ singleton list; or
• the root LanguageTree is fully parsed.
Return: ~
- table<integer, TSTree>
+ (`table<integer, TSTree>`)
+
vim:tw=78:ts=8:sw=4:sts=4:et:ft=help:norl:
diff --git a/runtime/doc/ui.txt b/runtime/doc/ui.txt
index ab99b0446f..b8d47923ca 100644
--- a/runtime/doc/ui.txt
+++ b/runtime/doc/ui.txt
@@ -26,12 +26,12 @@ with these (optional) keys:
*ui-rgb*
- `rgb` Decides the color format.
- - true: (default) 24-bit RGB colors
- - false: Terminal colors (8-bit, max 256)
+ - true: (default) 24-bit RGB colors
+ - false: Terminal colors (8-bit, max 256)
*ui-override*
- `override` Decides how UI capabilities are resolved.
- - true: Enable requested UI capabilities, even if not
+ - true: Enable requested UI capabilities, even if not
supported by all connected UIs (including |TUI|).
- false: (default) Disable UI capabilities not
supported by all connected UIs (including TUI).
@@ -138,7 +138,7 @@ procedure:
to set |g:| variables visible to init.vim
3. If the UI wants to do additional setup after user config is loaded,
- register a VimEnter autocmd: >vim
+ register a VimEnter autocmd: >lua
nvim_command("autocmd VimEnter * call rpcrequest(1, 'vimenter')")
4. Now invoke |nvim_ui_attach()|. The UI must handle user input by now:
@@ -188,7 +188,7 @@ the editor.
`attr_id`: Cursor attribute id (defined by `hl_attr_define`).
When attr_id is 0, the background and foreground
colors should be swapped.
- `attr_id_lm`: Cursor attribute id for when 'langmap' is active.
+ `attr_id_lm`: Cursor attribute id for when |:lmap| is on.
`short_name`: Mode code name, see 'guicursor'.
`name`: Mode descriptive name.
`mouse_shape`: (To be implemented.)
@@ -228,6 +228,10 @@ the editor.
however a UI might still use such options when rendering raw text
sent from Nvim, like for |ui-cmdline|.
+["chdir", path] ~
+ The |current-directory| of the embedded Nvim process changed to
+ `path`.
+
["mode_change", mode, mode_idx] ~
Editor mode changed. The `mode` parameter is a string representing
the current mode. `mode_idx` is an index into the array emitted in
@@ -324,9 +328,11 @@ numerical highlight ids to the actual attributes.
`underdotted`: underdotted text. The dots have `special` color.
`underdashed`: underdashed text. The dashes have `special` color.
`altfont`: alternative font.
- `blend`: Blend level (0-100). Could be used by UIs to
+ `blend`: blend level (0-100). Could be used by UIs to
support blending floating windows to the
background or to signal a transparent cursor.
+ `url`: a URL associated with this highlight. UIs can
+ display this URL however they wish.
For absent color keys the default color should be used. Don't store
the default value in the table, rather a sentinel value, so that
@@ -555,7 +561,7 @@ with the following possible keys:
`kind`: always present. One of the following values:
"ui": Builtin UI highlight. |highlight-groups|
"syntax": Highlight applied to a buffer by a syntax declaration or
- other runtime/plugin functionality such as
+ other runtime/plugin functionality such as
|nvim_buf_add_highlight()|
"terminal": highlight from a process running in a |terminal-emulator|.
Contains no further semantic information.
diff --git a/runtime/doc/usr_41.txt b/runtime/doc/usr_41.txt
index e206a804f4..56750420e9 100644
--- a/runtime/doc/usr_41.txt
+++ b/runtime/doc/usr_41.txt
@@ -610,10 +610,13 @@ String manipulation: *string-functions*
toupper() turn a string to uppercase
charclass() class of a character
match() position where a pattern matches in a string
+ matchbufline() all the matches of a pattern in a buffer
matchend() position where a pattern match ends in a string
matchfuzzy() fuzzy matches a string in a list of strings
matchfuzzypos() fuzzy matches a string in a list of strings
matchstr() match of a pattern in a string
+ matchstrlist() all the matches of a pattern in a List of
+ strings
matchstrpos() match and positions of a pattern in a string
matchlist() like matchstr() and also return submatches
stridx() first index of a short string in a long string
@@ -662,6 +665,7 @@ List manipulation: *list-functions*
filter() remove selected items from a List
map() change each List item
mapnew() make a new List with changed items
+ foreach() apply function to List items
reduce() reduce a List to a value
slice() take a slice of a List
sort() sort a List
@@ -693,6 +697,7 @@ Dictionary manipulation: *dict-functions*
filter() remove selected entries from a Dictionary
map() change each Dictionary entry
mapnew() make a new Dictionary with changed items
+ foreach() apply function to Dictionary items
keys() get List of Dictionary keys
values() get List of Dictionary values
items() get List of Dictionary key-value pairs
@@ -788,6 +793,7 @@ Cursor and mark position: *cursor-functions* *mark-functions*
Working with text in the current buffer: *text-functions*
getline() get a line or list of lines from the buffer
+ getregion() get a region of text from the buffer
setline() replace a line in the buffer
append() append line or list of lines in the buffer
indent() indent of a specific line
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index cf9b3cf0e5..b0caf9fdaf 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -30,6 +30,11 @@ Defaults *nvim-defaults*
":filetype off" to |init.vim|.
- Syntax highlighting is enabled by default. This can be disabled by adding
":syntax off" to |init.vim|.
+- Default color scheme has been updated. This can result in color schemes
+ looking differently due to them relying on how highlight groups are defined
+ by default. Add ":colorscheme vim" to |init.vim| or
+ ":source $VIMRUNTIME/colors/vim.lua" to your color scheme file to restore
+ the old default links and colors.
- 'autoindent' is enabled
- 'autoread' is enabled (works in all UIs, including terminal)
@@ -73,6 +78,8 @@ Defaults *nvim-defaults*
- 'switchbuf' defaults to "uselast"
- 'tabpagemax' defaults to 50
- 'tags' defaults to "./tags;,tags"
+- 'termguicolors' is enabled by default if Nvim can detect support from the
+ host terminal
- 'ttimeoutlen' defaults to 50
- 'ttyfast' is always set
- 'undodir' defaults to ~/.local/state/nvim/undo// (|xdg|), auto-created
@@ -122,6 +129,8 @@ of these in your config by simply removing the mapping, e.g. ":unmap Y".
- <C-W> |i_CTRL-W-default|
- <C-L> |CTRL-L-default|
- & |&-default|
+- Q |v_Q-default|
+- @ |v_@-default|
- # |v_#-default|
- * |v_star-default|
- Nvim LSP client defaults |lsp-defaults|
@@ -136,6 +145,12 @@ nvim_terminal:
- BufReadCmd: Treats "term://" buffers as |terminal| buffers. |terminal-start|
- TermClose: A |terminal| buffer started with no arguments (which thus uses
'shell') and which exits with no error is closed automatically.
+- TermRequest: The terminal emulator responds to OSC background and foreground
+ requests, indicating (1) a black background and white foreground when Nvim
+ option 'background' is "dark" or (2) a white background and black foreground
+ when 'background' is "light". While this may not reflect the actual
+ foreground/background color, it permits 'background' to be retained for a
+ nested Nvim instance running in the terminal emulator.
nvim_cmdwin:
- CmdwinEnter: Limits syntax sync to maxlines=1 in the |cmdwin|.
@@ -312,7 +327,8 @@ Options:
'shortmess' "F" flag does not affect output from autocommands
'signcolumn' supports up to 9 dynamic/fixed columns
'statuscolumn' full control of columns using 'statusline' format
- 'tabline' %@Func@foo%X can call any function on mouse-click
+ 'tabline' middle-click on tabpage label closes tabpage,
+ and %@Func@foo%X can call any function on mouse-click
'termpastefilter'
'ttimeout', 'ttimeoutlen' behavior was simplified
'winblend' pseudo-transparency in floating windows |api-floatwin|
@@ -566,6 +582,9 @@ Autocommands:
- |TermResponse| is fired for any OSC sequence received from the terminal,
instead of the Primary Device Attributes response. |v:termresponse|
+Options:
+- |shm-q| fully hides macro recording message instead of only shortening it.
+
==============================================================================
Missing features *nvim-missing*
@@ -616,6 +635,7 @@ Commands:
:lcscope
:scscope
:Vimuntar
+ The old `:TOhtml`, replaced by a Lua version (contains many differences)
Compile-time features:
Emacs tags support
@@ -666,7 +686,7 @@ Options:
bioskey (MS-DOS)
conskey (MS-DOS)
*'cp'* *'nocompatible'* *'nocp'* *'compatible'* (Nvim is always "nocompatible".)
- 'cpoptions' (gjkHw<*- and all POSIX flags were removed)
+ 'cpoptions' (gjpkHw<*- and all POSIX flags were removed)
*'cryptmethod'* *'cm'* *'key'* (Vim encryption implementation)
cscopepathcomp
cscopeprg
diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt
index 0d1ea937c0..a20fb6d31e 100644
--- a/runtime/doc/visual.txt
+++ b/runtime/doc/visual.txt
@@ -366,6 +366,20 @@ one of the last commands to extend the highlighted text, the repeating will
be applied up to the rightmost column of the longest line. Any count passed
to the `.` command is not used.
+Visual mode |default-mappings| "@" and "Q" can repeat commands in a register
+for all selected lines. See |v_@-default| and |v_Q-default| for details. For
+example, given the text:
+
+ 123(hello)321
+ 456(world)654
+ 456(NOT THIS)654
+
+With register "x" containing the commands `yi(VP`, Visually selecting the
+first two lines and typing `@x` produces:
+
+ hello
+ world
+ 456(NOT THIS)654
==============================================================================
7. Examples *visual-examples*
diff --git a/runtime/doc/vvars.txt b/runtime/doc/vvars.txt
new file mode 100644
index 0000000000..e71e31abf8
--- /dev/null
+++ b/runtime/doc/vvars.txt
@@ -0,0 +1,735 @@
+*vvars.txt* Nvim
+
+
+ NVIM REFERENCE MANUAL
+
+
+Predefined variables *vvars*
+
+Some variables can be set by the user, but the type cannot be changed.
+
+ Type |gO| to see the table of contents.
+
+ *v:argv* *argv-variable*
+v:argv
+ The command line arguments Vim was invoked with. This is a
+ list of strings. The first item is the Vim command.
+ See |v:progpath| for the command with full path.
+
+ *v:char* *char-variable*
+v:char
+ Argument for evaluating 'formatexpr' and used for the typed
+ character when using <expr> in an abbreviation |:map-<expr>|.
+ It is also used by the |InsertCharPre| and |InsertEnter| events.
+
+ *v:charconvert_from* *charconvert_from-variable*
+v:charconvert_from
+ The name of the character encoding of a file to be converted.
+ Only valid while evaluating the 'charconvert' option.
+
+ *v:charconvert_to* *charconvert_to-variable*
+v:charconvert_to
+ The name of the character encoding of a file after conversion.
+ Only valid while evaluating the 'charconvert' option.
+
+ *v:cmdarg* *cmdarg-variable*
+v:cmdarg
+ The extra arguments ("++p", "++enc=", "++ff=") given to a file
+ read/write command. This is set before an autocommand event
+ for a file read/write command is triggered. There is a
+ leading space to make it possible to append this variable
+ directly after the read/write command. Note: "+cmd" isn't
+ included here, because it will be executed anyway.
+
+ *v:cmdbang* *cmdbang-variable*
+v:cmdbang
+ Set like v:cmdarg for a file read/write command. When a "!"
+ was used the value is 1, otherwise it is 0. Note that this
+ can only be used in autocommands. For user commands |<bang>|
+ can be used.
+
+ *v:collate* *collate-variable*
+v:collate
+ The current locale setting for collation order of the runtime
+ environment. This allows Vim scripts to be aware of the
+ current locale encoding. Technical: it's the value of
+ LC_COLLATE. When not using a locale the value is "C".
+ This variable can not be set directly, use the |:language|
+ command.
+ See |multi-lang|.
+
+ *v:completed_item* *completed_item-variable*
+v:completed_item
+ Dictionary containing the most recent |complete-items| after
+ |CompleteDone|. Empty if the completion failed, or after
+ leaving and re-entering insert mode.
+ Note: Plugins can modify the value to emulate the builtin
+ |CompleteDone| event behavior.
+
+ *v:count* *count-variable*
+v:count
+ The count given for the last Normal mode command. Can be used
+ to get the count before a mapping. Read-only. Example: >vim
+ :map _x :<C-U>echo "the count is " .. v:count<CR>
+<
+ Note: The <C-U> is required to remove the line range that you
+ get when typing ':' after a count.
+ When there are two counts, as in "3d2w", they are multiplied,
+ just like what happens in the command, "d6w" for the example.
+ Also used for evaluating the 'formatexpr' option.
+
+ *v:count1* *count1-variable*
+v:count1
+ Just like "v:count", but defaults to one when no count is
+ used.
+
+ *v:ctype* *ctype-variable*
+v:ctype
+ The current locale setting for characters of the runtime
+ environment. This allows Vim scripts to be aware of the
+ current locale encoding. Technical: it's the value of
+ LC_CTYPE. When not using a locale the value is "C".
+ This variable can not be set directly, use the |:language|
+ command.
+ See |multi-lang|.
+
+ *v:dying* *dying-variable*
+v:dying
+ Normally zero. When a deadly signal is caught it's set to
+ one. When multiple signals are caught the number increases.
+ Can be used in an autocommand to check if Vim didn't
+ terminate normally.
+ Example: >vim
+ :au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif
+<
+ Note: if another deadly signal is caught when v:dying is one,
+ VimLeave autocommands will not be executed.
+
+ *v:echospace* *echospace-variable*
+v:echospace
+ Number of screen cells that can be used for an `:echo` message
+ in the last screen line before causing the |hit-enter-prompt|.
+ Depends on 'showcmd', 'ruler' and 'columns'. You need to
+ check 'cmdheight' for whether there are full-width lines
+ available above the last line.
+
+ *v:errmsg* *errmsg-variable*
+v:errmsg
+ Last given error message.
+ Modifiable (can be set).
+ Example: >vim
+ let v:errmsg = ""
+ silent! next
+ if v:errmsg != ""
+ " ... handle error
+<
+
+ *v:errors* *errors-variable* *assert-return*
+v:errors
+ Errors found by assert functions, such as |assert_true()|.
+ This is a list of strings.
+ The assert functions append an item when an assert fails.
+ The return value indicates this: a one is returned if an item
+ was added to v:errors, otherwise zero is returned.
+ To remove old results make it empty: >vim
+ let v:errors = []
+<
+ If v:errors is set to anything but a list it is made an empty
+ list by the assert function.
+
+ *v:event* *event-variable*
+v:event
+ Dictionary of event data for the current |autocommand|. Valid
+ only during the event lifetime; storing or passing v:event is
+ invalid! Copy it instead: >vim
+ au TextYankPost * let g:foo = deepcopy(v:event)
+<
+ Keys vary by event; see the documentation for the specific
+ event, e.g. |DirChanged| or |TextYankPost|.
+ KEY DESCRIPTION ~
+ abort Whether the event triggered during
+ an aborting condition (e.g. |c_Esc| or
+ |c_CTRL-C| for |CmdlineLeave|).
+ chan |channel-id|
+ cmdlevel Level of cmdline.
+ cmdtype Type of cmdline, |cmdline-char|.
+ cwd Current working directory.
+ inclusive Motion is |inclusive|, else exclusive.
+ scope Event-specific scope name.
+ operator Current |operator|. Also set for Ex
+ commands (unlike |v:operator|). For
+ example if |TextYankPost| is triggered
+ by the |:yank| Ex command then
+ `v:event.operator` is "y".
+ regcontents Text stored in the register as a
+ |readfile()|-style list of lines.
+ regname Requested register (e.g "x" for "xyy)
+ or the empty string for an unnamed
+ operation.
+ regtype Type of register as returned by
+ |getregtype()|.
+ visual Selection is visual (as opposed to,
+ e.g., via motion).
+ completed_item Current selected complete item on
+ |CompleteChanged|, Is `{}` when no complete
+ item selected.
+ height Height of popup menu on |CompleteChanged|
+ width Width of popup menu on |CompleteChanged|
+ row Row count of popup menu on |CompleteChanged|,
+ relative to screen.
+ col Col count of popup menu on |CompleteChanged|,
+ relative to screen.
+ size Total number of completion items on
+ |CompleteChanged|.
+ scrollbar Is |v:true| if popup menu have scrollbar, or
+ |v:false| if not.
+ changed_window Is |v:true| if the event fired while
+ changing window (or tab) on |DirChanged|.
+ status Job status or exit code, -1 means "unknown". |TermClose|
+
+ *v:exception* *exception-variable*
+v:exception
+ The value of the exception most recently caught and not
+ finished. See also |v:throwpoint| and |throw-variables|.
+ Example: >vim
+ try
+ throw "oops"
+ catch /.*/
+ echo "caught " .. v:exception
+ endtry
+<
+ Output: "caught oops".
+
+ *v:exiting* *exiting-variable*
+v:exiting
+ Exit code, or |v:null| before invoking the |VimLeavePre|
+ and |VimLeave| autocmds. See |:q|, |:x| and |:cquit|.
+ Example: >vim
+ :au VimLeave * echo "Exit value is " .. v:exiting
+<
+
+ *v:false* *false-variable*
+v:false
+ Special value used to put "false" in JSON and msgpack. See
+ |json_encode()|. This value is converted to "v:false" when used
+ as a String (e.g. in |expr5| with string concatenation
+ operator) and to zero when used as a Number (e.g. in |expr5|
+ or |expr7| when used with numeric operators). Read-only.
+
+ *v:fcs_choice* *fcs_choice-variable*
+v:fcs_choice
+ What should happen after a |FileChangedShell| event was
+ triggered. Can be used in an autocommand to tell Vim what to
+ do with the affected buffer:
+ reload Reload the buffer (does not work if
+ the file was deleted).
+ edit Reload the buffer and detect the
+ values for options such as
+ 'fileformat', 'fileencoding', 'binary'
+ (does not work if the file was
+ deleted).
+ ask Ask the user what to do, as if there
+ was no autocommand. Except that when
+ only the timestamp changed nothing
+ will happen.
+ <empty> Nothing, the autocommand should do
+ everything that needs to be done.
+ The default is empty. If another (invalid) value is used then
+ Vim behaves like it is empty, there is no warning message.
+
+ *v:fcs_reason* *fcs_reason-variable*
+v:fcs_reason
+ The reason why the |FileChangedShell| event was triggered.
+ Can be used in an autocommand to decide what to do and/or what
+ to set v:fcs_choice to. Possible values:
+ deleted file no longer exists
+ conflict file contents, mode or timestamp was
+ changed and buffer is modified
+ changed file contents has changed
+ mode mode of file changed
+ time only file timestamp changed
+
+ *v:fname* *fname-variable*
+v:fname
+ When evaluating 'includeexpr': the file name that was
+ detected. Empty otherwise.
+
+ *v:fname_diff* *fname_diff-variable*
+v:fname_diff
+ The name of the diff (patch) file. Only valid while
+ evaluating 'patchexpr'.
+
+ *v:fname_in* *fname_in-variable*
+v:fname_in
+ The name of the input file. Valid while evaluating:
+ option used for ~
+ 'charconvert' file to be converted
+ 'diffexpr' original file
+ 'patchexpr' original file
+ And set to the swap file name for |SwapExists|.
+
+ *v:fname_new* *fname_new-variable*
+v:fname_new
+ The name of the new version of the file. Only valid while
+ evaluating 'diffexpr'.
+
+ *v:fname_out* *fname_out-variable*
+v:fname_out
+ The name of the output file. Only valid while
+ evaluating:
+ option used for ~
+ 'charconvert' resulting converted file [1]
+ 'diffexpr' output of diff
+ 'patchexpr' resulting patched file
+ [1] When doing conversion for a write command (e.g., ":w
+ file") it will be equal to v:fname_in. When doing conversion
+ for a read command (e.g., ":e file") it will be a temporary
+ file and different from v:fname_in.
+
+ *v:folddashes* *folddashes-variable*
+v:folddashes
+ Used for 'foldtext': dashes representing foldlevel of a closed
+ fold.
+ Read-only in the |sandbox|. |fold-foldtext|
+
+ *v:foldend* *foldend-variable*
+v:foldend
+ Used for 'foldtext': last line of closed fold.
+ Read-only in the |sandbox|. |fold-foldtext|
+
+ *v:foldlevel* *foldlevel-variable*
+v:foldlevel
+ Used for 'foldtext': foldlevel of closed fold.
+ Read-only in the |sandbox|. |fold-foldtext|
+
+ *v:foldstart* *foldstart-variable*
+v:foldstart
+ Used for 'foldtext': first line of closed fold.
+ Read-only in the |sandbox|. |fold-foldtext|
+
+ *v:hlsearch* *hlsearch-variable*
+v:hlsearch
+ Variable that indicates whether search highlighting is on.
+ Setting it makes sense only if 'hlsearch' is enabled. Setting
+ this variable to zero acts like the |:nohlsearch| command,
+ setting it to one acts like >vim
+ let &hlsearch = &hlsearch
+<
+ Note that the value is restored when returning from a
+ function. |function-search-undo|.
+
+ *v:insertmode* *insertmode-variable*
+v:insertmode
+ Used for the |InsertEnter| and |InsertChange| autocommand
+ events. Values:
+ i Insert mode
+ r Replace mode
+ v Virtual Replace mode
+
+ *v:key* *key-variable*
+v:key
+ Key of the current item of a |Dictionary|. Only valid while
+ evaluating the expression used with |map()| and |filter()|.
+ Read-only.
+
+ *v:lang* *lang-variable*
+v:lang
+ The current locale setting for messages of the runtime
+ environment. This allows Vim scripts to be aware of the
+ current language. Technical: it's the value of LC_MESSAGES.
+ The value is system dependent.
+ This variable can not be set directly, use the |:language|
+ command.
+ It can be different from |v:ctype| when messages are desired
+ in a different language than what is used for character
+ encoding. See |multi-lang|.
+
+ *v:lc_time* *lc_time-variable*
+v:lc_time
+ The current locale setting for time messages of the runtime
+ environment. This allows Vim scripts to be aware of the
+ current language. Technical: it's the value of LC_TIME.
+ This variable can not be set directly, use the |:language|
+ command. See |multi-lang|.
+
+ *v:lnum* *lnum-variable*
+v:lnum
+ Line number for the 'foldexpr' |fold-expr|, 'formatexpr',
+ 'indentexpr' and 'statuscolumn' expressions, tab page number
+ for 'guitablabel' and 'guitabtooltip'. Only valid while one of
+ these expressions is being evaluated. Read-only when in the
+ |sandbox|.
+
+ *v:lua* *lua-variable*
+v:lua
+ Prefix for calling Lua functions from expressions.
+ See |v:lua-call| for more information.
+
+ *v:maxcol* *maxcol-variable*
+v:maxcol
+ Maximum line length. Depending on where it is used it can be
+ screen columns, characters or bytes. The value currently is
+ 2147483647 on all systems.
+
+ *v:mouse_col* *mouse_col-variable*
+v:mouse_col
+ Column number for a mouse click obtained with |getchar()|.
+ This is the screen column number, like with |virtcol()|. The
+ value is zero when there was no mouse button click.
+
+ *v:mouse_lnum* *mouse_lnum-variable*
+v:mouse_lnum
+ Line number for a mouse click obtained with |getchar()|.
+ This is the text line number, not the screen line number. The
+ value is zero when there was no mouse button click.
+
+ *v:mouse_win* *mouse_win-variable*
+v:mouse_win
+ Window number for a mouse click obtained with |getchar()|.
+ First window has number 1, like with |winnr()|. The value is
+ zero when there was no mouse button click.
+
+ *v:mouse_winid* *mouse_winid-variable*
+v:mouse_winid
+ |window-ID| for a mouse click obtained with |getchar()|.
+ The value is zero when there was no mouse button click.
+
+ *v:msgpack_types* *msgpack_types-variable*
+v:msgpack_types
+ Dictionary containing msgpack types used by |msgpackparse()|
+ and |msgpackdump()|. All types inside dictionary are fixed
+ (not editable) empty lists. To check whether some list is one
+ of msgpack types, use |is| operator.
+
+ *v:null* *null-variable*
+v:null
+ Special value used to put "null" in JSON and NIL in msgpack.
+ See |json_encode()|. This value is converted to "v:null" when
+ used as a String (e.g. in |expr5| with string concatenation
+ operator) and to zero when used as a Number (e.g. in |expr5|
+ or |expr7| when used with numeric operators). Read-only.
+ In some places `v:null` can be used for a List, Dict, etc.
+ that is not set. That is slightly different than an empty
+ List, Dict, etc.
+
+ *v:numbermax* *numbermax-variable*
+v:numbermax Maximum value of a number.
+
+ *v:numbermin* *numbermin-variable*
+v:numbermin Minimum value of a number (negative).
+
+ *v:numbersize* *numbersize-variable*
+v:numbersize
+ Number of bits in a Number. This is normally 64, but on some
+ systems it may be 32.
+
+ *v:oldfiles* *oldfiles-variable*
+v:oldfiles
+ List of file names that is loaded from the |shada| file on
+ startup. These are the files that Vim remembers marks for.
+ The length of the List is limited by the ' argument of the
+ 'shada' option (default is 100).
+ When the |shada| file is not used the List is empty.
+ Also see |:oldfiles| and |c_#<|.
+ The List can be modified, but this has no effect on what is
+ stored in the |shada| file later. If you use values other
+ than String this will cause trouble.
+
+ *v:operator* *operator-variable*
+v:operator
+ The last operator given in Normal mode. This is a single
+ character except for commands starting with <g> or <z>,
+ in which case it is two characters. Best used alongside
+ |v:prevcount| and |v:register|. Useful if you want to cancel
+ Operator-pending mode and then use the operator, e.g.: >vim
+ :omap O <Esc>:call MyMotion(v:operator)<CR>
+<
+ The value remains set until another operator is entered, thus
+ don't expect it to be empty.
+ v:operator is not set for |:delete|, |:yank| or other Ex
+ commands.
+ Read-only.
+
+ *v:option_command* *option_command-variable*
+v:option_command
+ Command used to set the option. Valid while executing an
+ |OptionSet| autocommand.
+ value option was set via ~
+ "setlocal" |:setlocal| or `:let l:xxx`
+ "setglobal" |:setglobal| or `:let g:xxx`
+ "set" |:set| or |:let|
+ "modeline" |modeline|
+
+ *v:option_new* *option_new-variable*
+v:option_new
+ New value of the option. Valid while executing an |OptionSet|
+ autocommand.
+
+ *v:option_old* *option_old-variable*
+v:option_old
+ Old value of the option. Valid while executing an |OptionSet|
+ autocommand. Depending on the command used for setting and the
+ kind of option this is either the local old value or the
+ global old value.
+
+ *v:option_oldglobal* *option_oldglobal-variable*
+v:option_oldglobal
+ Old global value of the option. Valid while executing an
+ |OptionSet| autocommand.
+
+ *v:option_oldlocal* *option_oldlocal-variable*
+v:option_oldlocal
+ Old local value of the option. Valid while executing an
+ |OptionSet| autocommand.
+
+ *v:option_type* *option_type-variable*
+v:option_type
+ Scope of the set command. Valid while executing an
+ |OptionSet| autocommand. Can be either "global" or "local"
+
+ *v:prevcount* *prevcount-variable*
+v:prevcount
+ The count given for the last but one Normal mode command.
+ This is the v:count value of the previous command. Useful if
+ you want to cancel Visual or Operator-pending mode and then
+ use the count, e.g.: >vim
+ :vmap % <Esc>:call MyFilter(v:prevcount)<CR>
+<
+ Read-only.
+
+ *v:profiling* *profiling-variable*
+v:profiling
+ Normally zero. Set to one after using ":profile start".
+ See |profiling|.
+
+ *v:progname* *progname-variable*
+v:progname
+ The name by which Nvim was invoked (with path removed).
+ Read-only.
+
+ *v:progpath* *progpath-variable*
+v:progpath
+ Absolute path to the current running Nvim.
+ Read-only.
+
+ *v:register* *register-variable*
+v:register
+ The name of the register in effect for the current normal mode
+ command (regardless of whether that command actually used a
+ register). Or for the currently executing normal mode mapping
+ (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 '+'.
+ Also see |getreg()| and |setreg()|
+
+ *v:relnum* *relnum-variable*
+v:relnum
+ Relative line number for the 'statuscolumn' expression.
+ Read-only.
+
+ *v:scrollstart* *scrollstart-variable*
+v:scrollstart
+ String describing the script or function that caused the
+ screen to scroll up. It's only set when it is empty, thus the
+ first reason is remembered. It is set to "Unknown" for a
+ typed command.
+ This can be used to find out why your script causes the
+ hit-enter prompt.
+
+ *v:searchforward* *searchforward-variable*
+v:searchforward
+ Search direction: 1 after a forward search, 0 after a
+ backward search. It is reset to forward when directly setting
+ the last search pattern, see |quote/|.
+ Note that the value is restored when returning from a
+ function. |function-search-undo|.
+ Read-write.
+
+ *v:servername* *servername-variable*
+v:servername
+ Primary listen-address of Nvim, the first item returned by
+ |serverlist()|. Usually this is the named pipe created by Nvim
+ at |startup| or given by |--listen| (or the deprecated
+ |$NVIM_LISTEN_ADDRESS| env var).
+
+ See also |serverstart()| |serverstop()|.
+ Read-only.
+
+ *$NVIM*
+ $NVIM is set by |terminal| and |jobstart()|, and is thus
+ a hint that the current environment is a subprocess of Nvim.
+ Example: >vim
+ if $NVIM
+ echo nvim_get_chan_info(v:parent)
+ endif
+<
+
+ Note the contents of $NVIM may change in the future.
+
+ *v:shell_error* *shell_error-variable*
+v:shell_error
+ Result of the last shell command. When non-zero, the last
+ shell command had an error. When zero, there was no problem.
+ This only works when the shell returns the error code to Vim.
+ The value -1 is often used when the command could not be
+ executed. Read-only.
+ Example: >vim
+ !mv foo bar
+ if v:shell_error
+ echo 'could not rename "foo" to "bar"!'
+ endif
+<
+
+ *v:statusmsg* *statusmsg-variable*
+v:statusmsg
+ Last given status message.
+ Modifiable (can be set).
+
+ *v:stderr* *stderr-variable*
+v:stderr
+ |channel-id| corresponding to stderr. The value is always 2;
+ use this variable to make your code more descriptive.
+ Unlike stdin and stdout (see |stdioopen()|), stderr is always
+ open for writing. Example: >vim
+ :call chansend(v:stderr, "error: toaster empty\n")
+<
+
+ *v:swapchoice* *swapchoice-variable*
+v:swapchoice
+ |SwapExists| autocommands can set this to the selected choice
+ for handling an existing swapfile:
+ 'o' Open read-only
+ 'e' Edit anyway
+ 'r' Recover
+ 'd' Delete swapfile
+ 'q' Quit
+ 'a' Abort
+ The value should be a single-character string. An empty value
+ results in the user being asked, as would happen when there is
+ no SwapExists autocommand. The default is empty.
+
+ *v:swapcommand* *swapcommand-variable*
+v:swapcommand
+ Normal mode command to be executed after a file has been
+ opened. Can be used for a |SwapExists| autocommand to have
+ another Vim open the file and jump to the right place. For
+ example, when jumping to a tag the value is ":tag tagname\r".
+ For ":edit +cmd file" the value is ":cmd\r".
+
+ *v:swapname* *swapname-variable*
+v:swapname
+ Name of the swapfile found.
+ Only valid during |SwapExists| event.
+ Read-only.
+
+ *v:t_blob* *t_blob-variable* *v:t_TYPE*
+v:t_blob Value of |Blob| type. Read-only. See: |type()|
+
+ *v:t_bool* *t_bool-variable*
+v:t_bool Value of |Boolean| type. Read-only. See: |type()|
+
+ *v:t_dict* *t_dict-variable*
+v:t_dict Value of |Dictionary| type. Read-only. See: |type()|
+
+ *v:t_float* *t_float-variable*
+v:t_float Value of |Float| type. Read-only. See: |type()|
+
+ *v:t_func* *t_func-variable*
+v:t_func Value of |Funcref| type. Read-only. See: |type()|
+
+ *v:t_list* *t_list-variable*
+v:t_list Value of |List| type. Read-only. See: |type()|
+
+ *v:t_number* *t_number-variable*
+v:t_number Value of |Number| type. Read-only. See: |type()|
+
+ *v:t_string* *t_string-variable*
+v:t_string Value of |String| type. Read-only. See: |type()|
+
+ *v:termrequest* *termrequest-variable*
+v:termrequest
+ The value of the most recent OSC or DCS control sequence
+ sent from a process running in the embedded |terminal|.
+ This can be read in a |TermRequest| event handler to respond
+ to queries from embedded applications.
+
+ *v:termresponse* *termresponse-variable*
+v:termresponse
+ The value of the most recent OSC or DCS control sequence
+ received by Nvim from the terminal. This can be read in a
+ |TermResponse| event handler after querying the terminal using
+ another escape sequence.
+
+ *v:testing* *testing-variable*
+v:testing Must be set before using `test_garbagecollect_now()`.
+
+ *v:this_session* *this_session-variable*
+v:this_session
+ Full filename of the last loaded or saved session file.
+ Empty when no session file has been saved. See |:mksession|.
+ Modifiable (can be set).
+
+ *v:throwpoint* *throwpoint-variable*
+v:throwpoint
+ The point where the exception most recently caught and not
+ finished was thrown. Not set when commands are typed. See
+ also |v:exception| and |throw-variables|.
+ Example: >vim
+ try
+ throw "oops"
+ catch /.*/
+ echo "Exception from" v:throwpoint
+ endtry
+<
+ Output: "Exception from test.vim, line 2"
+
+ *v:true* *true-variable*
+v:true
+ Special value used to put "true" in JSON and msgpack. See
+ |json_encode()|. This value is converted to "v:true" when used
+ as a String (e.g. in |expr5| with string concatenation
+ operator) and to one when used as a Number (e.g. in |expr5| or
+ |expr7| when used with numeric operators). Read-only.
+
+ *v:val* *val-variable*
+v:val
+ Value of the current item of a |List| or |Dictionary|. Only
+ valid while evaluating the expression used with |map()| and
+ |filter()|. Read-only.
+
+ *v:version* *version-variable*
+v:version
+ Vim version number: major version times 100 plus minor
+ version. Vim 5.0 is 500, Vim 5.1 is 501.
+ Read-only.
+ Use |has()| to check the Nvim (not Vim) version: >vim
+ :if has("nvim-0.2.1")
+<
+
+ *v:vim_did_enter* *vim_did_enter-variable*
+v:vim_did_enter
+ 0 during startup, 1 just before |VimEnter|.
+ Read-only.
+
+ *v:virtnum* *virtnum-variable*
+v:virtnum
+ Virtual line number for the 'statuscolumn' expression.
+ Negative when drawing the status column for virtual lines, zero
+ when drawing an actual buffer line, and positive when drawing
+ the wrapped part of a buffer line.
+ Read-only.
+
+ *v:warningmsg* *warningmsg-variable*
+v:warningmsg
+ Last given warning message.
+ Modifiable (can be set).
+
+ *v:windowid* *windowid-variable*
+v:windowid
+ Application-specific window "handle" which may be set by any
+ attached UI. Defaults to zero.
+ Note: For Nvim |windows| use |winnr()| or |win_getid()|, see
+ |window-ID|.
+
+ vim:tw=78:ts=8:noet:ft=help:norl:
diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt
index d6fce89f23..b71e7c80ab 100644
--- a/runtime/doc/windows.txt
+++ b/runtime/doc/windows.txt
@@ -242,9 +242,10 @@ and 'winminwidth' are relevant.
*:hor* *:horizontal*
:hor[izontal] {cmd}
Execute {cmd}. Currently only makes a difference for
- `horizontal wincmd =`, which will equalize windows only
- horizontally, and |:terminal|, which will open a |terminal|
- buffer in a split window.
+ the following commands:
+ - `:wincmd =`: equalize windows only horizontally.
+ - |:terminal|: open a |terminal| buffer in a split window.
+ - |:checkhealth|: open a healthcheck buffer in a split window.
:lefta[bove] {cmd} *:lefta* *:leftabove*
:abo[veleft] {cmd} *:abo* *:aboveleft*
diff --git a/runtime/ftplugin/aap.vim b/runtime/ftplugin/aap.vim
index df839c99ae..cd7e2a425e 100644
--- a/runtime/ftplugin/aap.vim
+++ b/runtime/ftplugin/aap.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Aap recipe
" Maintainer: The Vim Project <https://github.com/vim/vim>
-" Last Change: 2023 Aug 10
+" Last Change: 2024 Jan 14
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
" Only do this when not done yet for this buffer
@@ -28,6 +28,11 @@ setlocal commentstring=#\ %s
setlocal expandtab
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Aap Recipe Files (*.aap)\t*.aap\nAll Files (*.*)\t*.*\n"
+ let b:browsefilter = "Aap Recipe Files (*.aap)\t*.aap\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/abap.vim b/runtime/ftplugin/abap.vim
index 61db8093fb..8b2040e5aa 100644
--- a/runtime/ftplugin/abap.vim
+++ b/runtime/ftplugin/abap.vim
@@ -3,7 +3,8 @@
" Author: Steven Oliver <oliver.steven@gmail.com>
" Copyright: Copyright (c) 2013 Steven Oliver
" License: You may redistribute this under the same terms as Vim itself
-" Last Change: 2023 Aug 28 by Vim Project (undo_ftplugin)
+" Last Change: 2023 Aug 28 by Vim Project (undo_ftplugin)
+" 2024 Jan 14 by Vim Project (browsefilter)
" --------------------------------------------------------------------------
" Only do this when not done yet for this buffer
@@ -21,10 +22,14 @@ setlocal suffixesadd=.abap
let b:undo_ftplugin = "setl sts< sua< sw<"
" Windows allows you to filter the open file dialog
-if has("gui_win32") && !exists("b:browsefilter")
- let b:browsefilter = "ABAP Source Files (*.abap)\t*.abap\n" .
- \ "All Files (*.*)\t*.*\n"
- let b:undo_ftplugin .= " | unlet! b:browsefilter"
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "ABAP Source Files (*.abap)\t*.abap\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
+ let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
let &cpo = s:cpo_save
diff --git a/runtime/ftplugin/abaqus.vim b/runtime/ftplugin/abaqus.vim
index 5931cd921d..c16e7b032e 100644
--- a/runtime/ftplugin/abaqus.vim
+++ b/runtime/ftplugin/abaqus.vim
@@ -2,6 +2,7 @@
" Language: Abaqus finite element input file (www.abaqus.com)
" Maintainer: Carl Osterwisch <costerwi@gmail.com>
" Last Change: 2022 Oct 08
+" 2024 Jan 14 by Vim Project (browsefilter)
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin") | finish | endif
@@ -49,8 +50,12 @@ endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "Abaqus Input Files (*.inp *.inc)\t*.inp;*.inc\n" .
\ "Abaqus Results (*.dat)\t*.dat\n" .
- \ "Abaqus Messages (*.pre *.msg *.sta)\t*.pre;*.msg;*.sta\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "Abaqus Messages (*.pre, *.msg, *.sta)\t*.pre;*.msg;*.sta\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin .= "|unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/ant.vim b/runtime/ftplugin/ant.vim
index aee07ca4b9..65e01a1a76 100644
--- a/runtime/ftplugin/ant.vim
+++ b/runtime/ftplugin/ant.vim
@@ -1,10 +1,11 @@
" Vim filetype plugin file
-" Language: ant
+" Language: ant
"
" This runtime file is looking for a new maintainer.
"
" Former maintainer: Dan Sharp
-" Last Changed: 20 Jan 2009
+" Last Change: 2009 Jan 20
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
@@ -15,8 +16,12 @@ set cpo-=C
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
-let s:browsefilter = "XML Files (*.xml)\t*.xml\n" .
- \ "All Files (*.*)\t*.*\n"
+let s:browsefilter = "XML Files (*.xml)\t*.xml\n"
+if has("win32")
+ let s:browsefilter .= "All Files (*.*)\t*\n"
+else
+ let s:browsefilter .= "All Files (*)\t*\n"
+endif
runtime! ftplugin/xml.vim ftplugin/xml_*.vim ftplugin/xml/*.vim
let b:did_ftplugin = 1
@@ -30,7 +35,7 @@ if exists("b:browsefilter")
endif
" Change the :browse e filter to primarily show Ant-related files.
-if has("gui_win32")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "Build Files (build.xml)\tbuild.xml\n" .
\ "Java Files (*.java)\t*.java\n" .
\ "Properties Files (*.prop*)\t*.prop*\n" .
diff --git a/runtime/ftplugin/asciidoc.vim b/runtime/ftplugin/asciidoc.vim
new file mode 100644
index 0000000000..5974e28dc2
--- /dev/null
+++ b/runtime/ftplugin/asciidoc.vim
@@ -0,0 +1,67 @@
+" Vim filetype plugin file
+" Original Author: Maxim Kim <habamax@gmail.com>
+" Language: asciidoc
+" Maintainer: Luca Saccarola <github.e41mv@aleeas.com>
+" Last Change: 2024 Jan 16
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+if exists('b:undo_ftplugin')
+ let b:undo_ftplugin .= "|setl cms< com< fo< flp< inex< efm< cfu< fde< fdm<"
+else
+ let b:undo_ftplugin = "setl cms< com< fo< flp< inex< efm< cfu< fde< fdm<"
+endif
+
+" gf to open include::file.ext[] and link:file.ext[] files
+setlocal includeexpr=substitute(v:fname,'\\(link:\\\|include::\\)\\(.\\{-}\\)\\[.*','\\2','g')
+
+setlocal comments=
+setlocal commentstring=//\ %s
+
+setlocal formatoptions+=cqn
+setlocal formatlistpat=^\\s*[\\[({]\\?\\([0-9]\\+
+setlocal formatlistpat+=\\\|[a-zA-Z]\\)[\\]:.)}]\\s\\+
+setlocal formatlistpat+=\\\|^\\s*-\\s\\+
+setlocal formatlistpat+=\\\|^\\s*[*]\\+\\s\\+
+setlocal formatlistpat+=\\\|^\\s*[.]\\+\\s\\+
+
+function AsciidocFold()
+ let line = getline(v:lnum)
+
+ if (v:lnum == 1) && (line =~ '^----*$')
+ return ">1"
+ endif
+
+ let nested = get(g:, "asciidoc_foldnested", 1)
+
+ " Regular headers
+ let depth = match(line, '\(^=\+\)\@<=\( .*$\)\@=')
+
+ " Do not fold nested regular headers
+ if depth > 1 && !nested
+ let depth = 1
+ endif
+
+ if depth > 0
+ " fold all sections under title
+ if depth > 1 && !get(g:, "asciidoc_fold_under_title", 1)
+ let depth -= 1
+ endif
+ " check syntax, it should be asciidocTitle or asciidocH
+ let syncode = synstack(v:lnum, 1)
+ if len(syncode) > 0 && synIDattr(syncode[0], 'name') =~ 'asciidoc\%(H[1-6]\)\|Title'
+ return ">" . depth
+ endif
+ endif
+
+ return "="
+endfunction
+
+if has("folding") && get(g:, 'asciidoc_folding', 0)
+ setlocal foldexpr=AsciidocFold()
+ setlocal foldmethod=expr
+ let b:undo_ftplugin .= "|setl foldexpr< foldmethod< foldtext<"
+endif
diff --git a/runtime/ftplugin/aspvbs.vim b/runtime/ftplugin/aspvbs.vim
index 70a130d287..6979bb8f84 100644
--- a/runtime/ftplugin/aspvbs.vim
+++ b/runtime/ftplugin/aspvbs.vim
@@ -1,10 +1,11 @@
" Vim filetype plugin file
-" Language: aspvbs
+" Language: aspvbs
"
" This runtime file is looking for a new maintainer.
"
" Former maintainer: Dan Sharp
-" Last Changed: 20 Jan 2009
+" Last Change: 2009 Jan 20
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
@@ -15,8 +16,12 @@ set cpo-=C
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
-let s:browsefilter = "HTML Files (*.html, *.htm)\t*.htm*\n" .
- \ "All Files (*.*)\t*.*\n"
+let s:browsefilter = "HTML Files (*.html, *.htm)\t*.htm*\n"
+if has("win32")
+ let s:browsefilter .= "All Files (*.*)\t*\n"
+else
+ let s:browsefilter .= "All Files (*)\t*\n"
+endif
let s:match_words = ""
runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim
@@ -51,7 +56,7 @@ if exists("loaded_matchit")
endif
" Change the :browse e filter to primarily show ASP-related files.
-if has("gui_win32")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="ASP Files (*.asp)\t*.asp\n" . s:browsefilter
endif
diff --git a/runtime/ftplugin/awk.vim b/runtime/ftplugin/awk.vim
index 40fe304cf4..bcd772350a 100644
--- a/runtime/ftplugin/awk.vim
+++ b/runtime/ftplugin/awk.vim
@@ -2,7 +2,7 @@
" Language: awk, nawk, gawk, mawk
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer: Antonio Colombo <azc100@gmail.com>
-" Last Change: 2020 Sep 28
+" Last Change: 2024 Jan 14
" This plugin was prepared by Mark Sikora
" This plugin was updated as proposed by Doug Kearns
@@ -25,8 +25,7 @@ setlocal formatoptions-=t formatoptions+=croql
setlocal define=function
setlocal suffixesadd+=.awk
-let b:undo_ftplugin = "setl fo< com< cms< def< sua<" .
- \ " | unlet! b:browsefilter"
+let b:undo_ftplugin = "setl fo< com< cms< def< sua<"
" TODO: set this in scripts.vim?
if exists("g:awk_is_gawk")
@@ -49,8 +48,13 @@ if exists("g:awk_is_gawk")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Awk Source Files (*.awk,*.gawk)\t*.awk;*.gawk\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Awk Source Files (*.awk, *.gawk)\t*.awk;*.gawk\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
+ let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
let &cpo = s:cpo_save
diff --git a/runtime/ftplugin/basic.vim b/runtime/ftplugin/basic.vim
index 4399fbf3ad..32f713b43e 100644
--- a/runtime/ftplugin/basic.vim
+++ b/runtime/ftplugin/basic.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: BASIC (QuickBASIC 4.5)
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2022 Jun 22
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -45,8 +45,12 @@ endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "BASIC Source Files (*.bas)\t*.bas\n" ..
- \ "BASIC Include Files (*.bi, *.bm)\t*.bi;*.bm\n" ..
- \ "All Files (*.*)\t*.*\n"
+ \ "BASIC Include Files (*.bi, *.bm)\t*.bi;*.bm\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:basic_set_browsefilter = 1
let b:undo_ftplugin ..= " | unlet! b:browsefilter b:basic_set_browsefilter"
endif
diff --git a/runtime/ftplugin/c.vim b/runtime/ftplugin/c.vim
index 83fb9ead68..716b454675 100644
--- a/runtime/ftplugin/c.vim
+++ b/runtime/ftplugin/c.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: C
" Maintainer: The Vim Project <https://github.com/vim/vim>
-" Last Change: 2023 Aug 10
+" Last Change: 2023 Aug 22
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
" Only do this when not done yet for this buffer
@@ -43,24 +43,26 @@ if !exists("b:match_words")
let b:undo_ftplugin ..= " | unlet! b:match_skip b:match_words"
endif
-" Win32 can filter files in the browse dialog
+" Win32 and GTK can filter files in the browse dialog
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
if &ft == "cpp"
- let b:browsefilter = "C++ Source Files (*.cpp *.c++)\t*.cpp;*.c++\n" .
- \ "C Header Files (*.h)\t*.h\n" .
- \ "C Source Files (*.c)\t*.c\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "C++ Source Files (*.cpp, *.c++)\t*.cpp;*.c++\n" ..
+ \ "C Header Files (*.h)\t*.h\n" ..
+ \ "C Source Files (*.c)\t*.c\n"
elseif &ft == "ch"
- let b:browsefilter = "Ch Source Files (*.ch *.chf)\t*.ch;*.chf\n" .
- \ "C Header Files (*.h)\t*.h\n" .
- \ "C Source Files (*.c)\t*.c\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Ch Source Files (*.ch, *.chf)\t*.ch;*.chf\n" ..
+ \ "C Header Files (*.h)\t*.h\n" ..
+ \ "C Source Files (*.c)\t*.c\n"
else
- let b:browsefilter = "C Source Files (*.c)\t*.c\n" .
- \ "C Header Files (*.h)\t*.h\n" .
- \ "Ch Source Files (*.ch *.chf)\t*.ch;*.chf\n" .
- \ "C++ Source Files (*.cpp *.c++)\t*.cpp;*.c++\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "C Source Files (*.c)\t*.c\n" ..
+ \ "C Header Files (*.h)\t*.h\n" ..
+ \ "Ch Source Files (*.ch, *.chf)\t*.ch;*.chf\n" ..
+ \ "C++ Source Files (*.cpp, *.c++)\t*.cpp;*.c++\n"
+ endif
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/clojure.vim b/runtime/ftplugin/clojure.vim
index c922d75699..4da7554d85 100644
--- a/runtime/ftplugin/clojure.vim
+++ b/runtime/ftplugin/clojure.vim
@@ -6,6 +6,7 @@
" URL: https://github.com/clojure-vim/clojure.vim
" License: Vim (see :h license)
" Last Change: 2022-03-24
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin")
finish
@@ -66,10 +67,14 @@ endif
" Filter files in the browse dialog
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "All Files\t*\n" .
- \ "Clojure Files\t*.clj;*.cljc;*.cljs;*.cljx\n" .
+ let b:browsefilter = "Clojure Files\t*.clj;*.cljc;*.cljs;*.cljx\n" .
\ "EDN Files\t*.edn\n" .
\ "Java Files\t*.java\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin .= ' | unlet! b:browsefilter'
endif
diff --git a/runtime/ftplugin/cobol.vim b/runtime/ftplugin/cobol.vim
index ec1e95456d..5e52702fd5 100644
--- a/runtime/ftplugin/cobol.vim
+++ b/runtime/ftplugin/cobol.vim
@@ -3,6 +3,7 @@
" Maintainer: Ankit Jain <ajatkj@yahoo.co.in>
" (formerly Tim Pope <vimNOSPAM@tpope.info>)
" Last Update: By Ankit Jain (add gtk support) on 15.08.2020
+" 2024 Jan 14 by Vim Project (browsefilter)
" Insert mode mappings: <C-T> <C-D> <Tab>
" Normal mode mappings: < > << >> [[ ]] [] ][
@@ -39,8 +40,12 @@ endif
" add gtk support
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "COBOL Source Files (*.cbl, *.cob)\t*.cbl;*.cob;*.lib\n".
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "COBOL Source Files (*.cbl, *.cob)\t*.cbl;*.cob;*.lib\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
let b:undo_ftplugin = "setlocal com< cms< fo< et< tw<" .
diff --git a/runtime/ftplugin/config.vim b/runtime/ftplugin/config.vim
index 73136cbc66..595fc657b9 100644
--- a/runtime/ftplugin/config.vim
+++ b/runtime/ftplugin/config.vim
@@ -1,10 +1,11 @@
" Vim filetype plugin file
-" Language: config
+" Language: config
"
" This runtime file is looking for a new maintainer.
"
" Former maintainer: Dan Sharp
-" Last Changed: 20 Jan 2009
+" Last Change: 2009 Jan 20
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
@@ -15,8 +16,12 @@ set cpo-=C
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
-let s:browsefilter = "Bourne Shell Files (*.sh)\t*.sh\n" .
- \ "All Files (*.*)\t*.*\n"
+let s:browsefilter = "Bourne Shell Files (*.sh)\t*.sh\n"
+if has("win32")
+ let s:browsefilter .= "All Files (*.*)\t*\n"
+else
+ let s:browsefilter .= "All Files (*)\t*\n"
+endif
let s:match_words = ""
runtime! ftplugin/sh.vim ftplugin/sh_*.vim ftplugin/sh/*.vim
@@ -31,7 +36,7 @@ if exists("b:browsefilter")
endif
" Change the :browse e filter to primarily show configure-related files.
-if has("gui_win32")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="Configure Scripts (configure.*, config.*)\tconfigure*;config.*\n" .
\ s:browsefilter
endif
diff --git a/runtime/ftplugin/cpp.vim b/runtime/ftplugin/cpp.vim
index cb425aa8e7..d4931a2533 100644
--- a/runtime/ftplugin/cpp.vim
+++ b/runtime/ftplugin/cpp.vim
@@ -10,8 +10,7 @@ if exists("b:did_ftplugin")
endif
" Behaves mostly just like C
-runtime! ftplugin/c.vim ftplugin/c_*.vim ftplugin/c/*.vim
-runtime! ftplugin/c.lua ftplugin/c_*.lua ftplugin/c/*.lua
+runtime! ftplugin/c.{vim,lua} ftplugin/c_*.{vim,lua} ftplugin/c/*.{vim,lua}
" C++ uses templates with <things>
" Disabled, because it gives an error for typing an unmatched ">".
diff --git a/runtime/ftplugin/cs.vim b/runtime/ftplugin/cs.vim
index 0734d11d22..ada71315e1 100644
--- a/runtime/ftplugin/cs.vim
+++ b/runtime/ftplugin/cs.vim
@@ -3,6 +3,7 @@
" Maintainer: Nick Jensen <nickspoon@gmail.com>
" Former Maintainer: Johannes Zellner <johannes@zellner.org>
" Last Change: 2022-11-16
+" 2024 Jan 14 by Vim Project (browsefilter)
" License: Vim (see :h license)
" Repository: https://github.com/nickspoons/vim-cs
@@ -31,10 +32,14 @@ if exists('loaded_matchit') && !exists('b:match_words')
endif
if (has('gui_win32') || has('gui_gtk')) && !exists('b:browsefilter')
- let b:browsefilter = "C# Source Files (*.cs *.csx)\t*.cs;*.csx\n" .
+ let b:browsefilter = "C# Source Files (*.cs, *.csx)\t*.cs;*.csx\n" .
\ "C# Project Files (*.csproj)\t*.csproj\n" .
- \ "Visual Studio Solution Files (*.sln)\t*.sln\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "Visual Studio Solution Files (*.sln)\t*.sln\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin .= ' | unlet! b:browsefilter'
endif
diff --git a/runtime/ftplugin/csh.vim b/runtime/ftplugin/csh.vim
index 2feec57bb2..a22bee3279 100644
--- a/runtime/ftplugin/csh.vim
+++ b/runtime/ftplugin/csh.vim
@@ -3,7 +3,7 @@
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer: Dan Sharp
" Contributor: Johannes Zellner <johannes@zellner.org>
-" Last Change: 2023 Oct 09
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -44,8 +44,12 @@ if exists("loaded_matchit") && !exists("b:match_words")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "csh Scripts (*.csh)\t*.csh\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "csh Scripts (*.csh)\t*.csh\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:csh_set_browsefilter = 1
let b:undo_ftplugin ..= " | unlet! b:browsefilter b:csh_set_browsefilter"
endif
diff --git a/runtime/ftplugin/diff.vim b/runtime/ftplugin/diff.vim
index f2a0820be9..2daa48aeb4 100644
--- a/runtime/ftplugin/diff.vim
+++ b/runtime/ftplugin/diff.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Diff
" Maintainer: The Vim Project <https://github.com/vim/vim>
-" Last Change: 2023 Aug 10
+" Last Change: 2023 Aug 22
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
" Only do this when not done yet for this buffer
@@ -19,6 +19,11 @@ setlocal nomodeline
let &l:commentstring = "# %s"
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Diff Files (*.diff)\t*.diff\nPatch Files (*.patch)\t*.h\nAll Files (*.*)\t*.*\n"
+ let b:browsefilter = "Diff Files (*.diff)\t*.diff\nPatch Files (*.patch)\t*.h\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/dosbatch.vim b/runtime/ftplugin/dosbatch.vim
index f02f26b1fd..5001cf68bd 100644
--- a/runtime/ftplugin/dosbatch.vim
+++ b/runtime/ftplugin/dosbatch.vim
@@ -2,6 +2,7 @@
" Language: MS-DOS/Windows .bat files
" Maintainer: Mike Williams <mrmrdubya@gmail.com>
" Last Change: 12th February 2023
+" 2024 Jan 14 by Vim Project (browsefilter)
"
" Options Flags:
" dosbatch_colons_comment - any value to treat :: as comment line
@@ -37,12 +38,17 @@ if executable('help.exe')
endif
" Define patterns for the browse file filter
-if has("gui_win32") && !exists("b:browsefilter")
- let b:browsefilter = "DOS Batch Files (*.bat, *.cmd)\t*.bat;*.cmd\nAll Files (*.*)\t*.*\n"
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "DOS Batch Files (*.bat, *.cmd)\t*.bat;*.cmd\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
endif
let b:undo_ftplugin = "setlocal comments< formatoptions< keywordprg<"
- \ . "| unlet! b:browsefiler"
+ \ . "| unlet! b:browsefilter"
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/dtd.vim b/runtime/ftplugin/dtd.vim
index a046118c70..bea8c5c18a 100644
--- a/runtime/ftplugin/dtd.vim
+++ b/runtime/ftplugin/dtd.vim
@@ -1,10 +1,11 @@
" Vim filetype plugin file
-" Language: dtd
+" Language: dtd
"
" This runtime file is looking for a new maintainer.
"
" Former maintainer: Dan Sharp
-" Last Changed: 20 Jan 2009
+" Last Change: 2009 Jan 20
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
let b:did_ftplugin = 1
@@ -27,10 +28,14 @@ if exists("loaded_matchit")
endif
" Change the :browse e filter to primarily show Java-related files.
-if has("gui_win32")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="DTD Files (*.dtd)\t*.dtd\n" .
- \ "XML Files (*.xml)\t*.xml\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "XML Files (*.xml)\t*.xml\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
" Undo the stuff we changed.
diff --git a/runtime/ftplugin/eiffel.vim b/runtime/ftplugin/eiffel.vim
index 216fdde162..e193110cde 100644
--- a/runtime/ftplugin/eiffel.vim
+++ b/runtime/ftplugin/eiffel.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin
" Language: Eiffel
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2010 Aug 29
+" Last Change: 2024 Jan 14
if (exists("b:did_ftplugin"))
finish
@@ -18,8 +18,12 @@ setlocal formatoptions-=t formatoptions+=croql
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "Eiffel Source Files (*.e)\t*.e\n" .
- \ "Eiffel Control Files (*.ecf, *.ace, *.xace)\t*.ecf;*.ace;*.xace\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "Eiffel Control Files (*.ecf, *.ace, *.xace)\t*.ecf;*.ace;*.xace\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
if exists("loaded_matchit") && !exists("b:match_words")
diff --git a/runtime/ftplugin/elixir.vim b/runtime/ftplugin/elixir.vim
index 50f63673dc..d067f472b7 100644
--- a/runtime/ftplugin/elixir.vim
+++ b/runtime/ftplugin/elixir.vim
@@ -1,7 +1,7 @@
" Elixir filetype plugin
" Language: Elixir
" Maintainer: Mitchell Hanberg <vimNOSPAM@mitchellhanberg.com>
-" Last Change: 2022 Sep 20
+" Last Change: 2023 Dec 27
if exists("b:did_ftplugin")
finish
@@ -27,7 +27,13 @@ setlocal shiftwidth=2 softtabstop=2 expandtab iskeyword+=!,?
setlocal comments=:#
setlocal commentstring=#\ %s
-let b:undo_ftplugin = 'setlocal sw< sts< et< isk< com< cms<'
+setlocal indentkeys=0#,!^F,o,O
+" Enable keys for blocks
+setlocal indentkeys+=0=after,0=catch,0=do,0=else,0=end,0=rescue
+" Enable keys that are usually the first keys in a line
+setlocal indentkeys+=0->,0\|>,0},0],0),>
+
+let b:undo_ftplugin = 'setlocal sw< sts< et< isk< com< cms< indk<'
let &cpo = s:save_cpo
unlet s:save_cpo
diff --git a/runtime/ftplugin/erlang.vim b/runtime/ftplugin/erlang.vim
index 31fa0c3213..1cb57f4c85 100644
--- a/runtime/ftplugin/erlang.vim
+++ b/runtime/ftplugin/erlang.vim
@@ -5,7 +5,8 @@
" Contributors: Ricardo Catalinas Jiménez <jimenezrick@gmail.com>
" Eduardo Lopez (http://github.com/tapichu)
" Arvid Bjurklint (http://github.com/slarwise)
-" Last Update: 2021-Nov-22
+" Paweł Zacharek (http://github.com/subc2)
+" Last Update: 2023-Dec-20
" License: Vim license
" URL: https://github.com/vim-erlang/vim-erlang-runtime
@@ -57,7 +58,7 @@ setlocal suffixesadd=.erl,.hrl
let &l:include = '^\s*-\%(include\|include_lib\)\s*("\zs\f*\ze")'
let &l:define = '^\s*-\%(define\|record\|type\|opaque\)'
-let s:erlang_fun_begin = '^\a\w*(.*$'
+let s:erlang_fun_begin = '^\l[A-Za-z0-9_@]*(.*$'
let s:erlang_fun_end = '^[^%]*\.\s*\(%.*\)\?$'
if !exists('*GetErlangFold')
@@ -95,9 +96,22 @@ if !exists('*ErlangFoldText')
endfunction
endif
+" The following lines enable the macros/matchit.vim plugin for extended
+" matching with the % key.
+let b:match_ignorecase = 0
+let b:match_words =
+ \ '\<\%(begin\|case\|fun\|if\|maybe\|receive\|try\)\>' .
+ \ ':\<\%(after\|catch\|else\|of\)\>' .
+ \ ':\<end\>,' .
+ \ '^\l[A-Za-z0-9_@]*' .
+ \ ':^\%(\%(\t\| \{' . shiftwidth() .
+ \ '}\)\%([^\t\ %][^%]*\)\?\)\?;\s*\%(%.*\)\?$\|\.[\t\ %]\|\.$'
+let b:match_skip = 's:comment\|string\|erlangmodifier\|erlangquotedatom'
+
let b:undo_ftplugin = "setlocal keywordprg< foldmethod< foldexpr< foldtext<"
\ . " comments< commentstring< formatoptions< suffixesadd< include<"
\ . " define<"
+ \ . " | unlet b:match_ignorecase b:match_words b:match_skip"
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/eruby.vim b/runtime/ftplugin/eruby.vim
index 893fa58d32..b5c4665d24 100644
--- a/runtime/ftplugin/eruby.vim
+++ b/runtime/ftplugin/eruby.vim
@@ -4,6 +4,7 @@
" URL: https://github.com/vim-ruby/vim-ruby
" Release Coordinator: Doug Kearns <dougkearns@gmail.com>
" Last Change: 2022 May 15
+" 2024 Jan 14 by Vim Project (browsefilter)
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -15,7 +16,11 @@ set cpo-=C
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
-let s:browsefilter = "All Files (*.*)\t*.*\n"
+if has("win32")
+ let s:browsefilter = "All Files (*.*)\t*\n"
+else
+ let s:browsefilter = "All Files (*)\t*\n"
+endif
let s:match_words = ""
if !exists("g:eruby_default_subtype")
@@ -109,8 +114,8 @@ exe 'cmap <buffer><script><expr> <Plug><cfile> ErubyAtCursor() ? ' . maparg('<Pl
exe 'cmap <buffer><script><expr> <Plug><ctag> ErubyAtCursor() ? ' . maparg('<Plug><ctag>', 'c') . ' : ' . get(s:ctagmap, 'rhs', '"\022\027"')
unlet s:cfilemap s:ctagmap s:include s:path s:suffixesadd
-" Change the browse dialog on Win32 to show mainly eRuby-related files
-if has("gui_win32")
+" Change the browse dialog on Win32 and GTK to show mainly eRuby-related files
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="eRuby Files (*.erb, *.rhtml)\t*.erb;*.rhtml\n" . s:browsefilter
endif
diff --git a/runtime/ftplugin/expect.vim b/runtime/ftplugin/expect.vim
index a4c6af96ce..b4db154999 100644
--- a/runtime/ftplugin/expect.vim
+++ b/runtime/ftplugin/expect.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Expect
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2022 Jul 16
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -14,8 +14,12 @@ let s:cpo_save = &cpo
set cpo&vim
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Expect Command Files (*.exp)\t*.exp\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Expect Command Files (*.exp)\t*.exp\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
endif
let &cpo = s:cpo_save
diff --git a/runtime/ftplugin/falcon.vim b/runtime/ftplugin/falcon.vim
index affca38481..1000b62e76 100644
--- a/runtime/ftplugin/falcon.vim
+++ b/runtime/ftplugin/falcon.vim
@@ -4,6 +4,7 @@
" Copyright: Copyright (c) 2009-2013 Steven Oliver
" License: You may redistribute this under the same terms as Vim itself
" Last Update: 2020 Oct 10
+" 2024 Jan 14 by Vim Project (browsefilter)
" --------------------------------------------------------------------------
" Only do this when not done yet for this buffer
@@ -34,14 +35,18 @@ endif
setlocal comments=sO:*\ -,mO:*\ \ ,exO:*/,s1:/*,mb:*,ex:*/,://
" Windows allows you to filter the open file dialog
-if has("gui_win32") && !exists("b:browsefilter")
- let b:browsefilter = "Falcon Source Files (*.fal *.ftd)\t*.fal;*.ftd\n" .
- \ "All Files (*.*)\t*.*\n"
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "Falcon Source Files (*.fal, *.ftd)\t*.fal;*.ftd\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
endif
let b:undo_ftplugin = "setlocal tabstop< shiftwidth< expandtab< fileencoding<"
\ . " suffixesadd< comments<"
- \ . "| unlet! b:browsefiler"
+ \ . "| unlet! b:browsefilter"
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/forth.vim b/runtime/ftplugin/forth.vim
index d28c8484e1..df4694f206 100644
--- a/runtime/ftplugin/forth.vim
+++ b/runtime/ftplugin/forth.vim
@@ -2,6 +2,7 @@
" Language: Forth
" Maintainer: Johan Kotlinski <kotlinski@gmail.com>
" Last Change: 2023 Sep 15
+" 2024 Jan 14 by Vim Project (browsefilter)
" URL: https://github.com/jkotlinski/forth.vim
if exists("b:did_ftplugin")
@@ -62,8 +63,12 @@ if exists("loaded_matchit") && !exists("b:match_words")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Forth Source Files (*.f *.fs *.ft *.fth *.4th)\t*.f;*.fs;*.ft;*.fth;*.4th\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Forth Source Files (*.f, *.fs, *.ft, *.fth, *.4th)\t*.f;*.fs;*.ft;*.fth;*.4th\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/fortran.vim b/runtime/ftplugin/fortran.vim
index 8f5b243b82..3c325818d3 100644
--- a/runtime/ftplugin/fortran.vim
+++ b/runtime/ftplugin/fortran.vim
@@ -1,13 +1,16 @@
" Vim settings file
-" Language: Fortran 2008 (and older: Fortran 2003, 95, 90, 77, 66)
-" Version: (v53) 2021 April 06 (updated 2022 May 22)
-" Maintainer: Ajit J. Thakkar <ajit@unb.ca>; <http://www2.unb.ca/~ajit/>
+" Language: Fortran 2023 (and Fortran 2018, 2008, 2003, 95, 90, 77, 66)
+" Version: (v55) 2023 December 22
+" Maintainers: Ajit J. Thakkar <ajit@unb.ca>; <https://ajit.ext.unb.ca/>
+" Joshua Hollett <j.hollett@uwinnipeg.ca>
" Usage: For instructions, do :help fortran-plugin from Vim
" Credits:
" Version 0.1 was created in September 2000 by Ajit Thakkar.
" Since then, useful suggestions and contributions have been made, in order, by:
" Stefano Zacchiroli, Hendrik Merx, Ben Fritz, David Barnett, Eisuke Kawashima,
" Doug Kearns, and Fritz Reese.
+" Last Change: 2023 Dec 22
+" 2024 Jan 14 by Vim Project (browsefilter)
" Only do these settings when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -39,7 +42,7 @@ if !exists("b:fortran_fixed_source")
" Fixed-form file extension defaults
let b:fortran_fixed_source = 1
else
- " Modern fortran still allows both fixed and free source form
+ " Modern fortran compilers still allow both fixed and free source form
" Assume fixed source form unless signs of free source form
" are detected in the first five columns of the first s:lmax lines.
" Detection becomes more accurate and time-consuming if more lines
@@ -70,14 +73,14 @@ if (b:fortran_fixed_source == 1)
" but some vendor extensions allow longer lines
if exists("fortran_extended_line_length")
setlocal tw=132
- elseif exists("fortran_cardimage_line_length")
- setlocal tw=80
else
- setlocal tw=72
+ " The use of columns 73-80 for sequence numbers is obsolete
+ " so almost all compilers allow a textwidth of 80
+ setlocal tw=80
" If you need to add "&" on continued lines so that the code is
" compatible with both free and fixed format, then you should do so
- " in column 73 and uncomment the next line
- " setlocal tw=73
+ " in column 81 and uncomment the next line
+ " setlocal tw=81
endif
else
setlocal comments=:!
@@ -109,7 +112,9 @@ if !exists("b:match_words")
let b:match_ignorecase = 1
let b:match_words =
\ '(:),' .
- \ '\<select\s*case\>:' . s:notselect. '\<case\>:\<end\s*select\>,' .
+ \ s:notend .'\<select\s\+type\>:' . s:notselect. '\<type\|class\>:\<end\s*select\>,' .
+ \ s:notend .'\<select\s\+rank\>:' . s:notselect. '\<rank\>:\<end\s*select\>,' .
+ \ s:notend .'\<select\>:' . s:notselect. '\<case\>:\<end\s*select\>,' .
\ s:notelse . '\<if\s*(.\+)\s*then\>:' .
\ s:nothash . '\<else\s*\%(if\s*(.\+)\s*then\)\=\>:' . s:nothash . '\<end\s*if\>,'.
\ 'do\s\+\(\d\+\):\%(^\s*\)\@<=\1\s,'.
@@ -118,6 +123,9 @@ if !exists("b:match_words")
\ s:notend . '\<type\s*[^(]:\<end\s*type\>,'.
\ s:notend . '\<forall\>:\<end\s*forall\>,'.
\ s:notend . '\<associate\>:\<end\s*associate\>,'.
+ \ s:notend . '\<change\s\+team\>:\<end\s*team\>,'.
+ \ s:notend . '\<critical\>:\<end\s*critical\>,'.
+ \ s:notend . '\<block\>:\<end\s*block\>,'.
\ s:notend . '\<enum\>:\<end\s*enum\>,'.
\ s:notend . '\<interface\>:\<end\s*interface\>,'.
\ s:notend . '\<subroutine\>:\<end\s*subroutine\>,'.
@@ -129,8 +137,12 @@ endif
" File filters for :browse e
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Fortran Files (*.f;*.for;*.f77;*.f90;*.f95;*.f03;*.f08;*.fpp;*.ftn)\t*.f;*.for;*.f77;*.f90;*.f95;*.f03;*.f08;*.fpp;*.ftn\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Fortran Files (*.f, *.for, *.f77, *.f90, *.f95, *.f03, *.f08, *.fpp, *.ftn)\t*.f;*.for;*.f77;*.f90;*.f95;*.f03;*.f08;*.fpp;*.ftn\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
let b:undo_ftplugin = "setl fo< com< tw< cms< et< inc< sua<"
diff --git a/runtime/ftplugin/fpcmake.vim b/runtime/ftplugin/fpcmake.vim
index 8d950838c7..e365ba7801 100644
--- a/runtime/ftplugin/fpcmake.vim
+++ b/runtime/ftplugin/fpcmake.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Free Pascal Makefile Generator
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2021 Apr 23
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -13,11 +13,15 @@ set cpo&vim
runtime! ftplugin/make.vim
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Free Pascal Makefile Definition Files (*.fpc)\t*.fpc\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Free Pascal Makefile Definition Files (*.fpc)\t*.fpc\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
+ let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
-let b:undo_ftplugin = b:undo_ftplugin .. " | unlet! b:browsefilter"
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/freebasic.vim b/runtime/ftplugin/freebasic.vim
index 1680e84c9c..8eadb44c21 100644
--- a/runtime/ftplugin/freebasic.vim
+++ b/runtime/ftplugin/freebasic.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: FreeBASIC
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2022 Jun 24
+" Last Change: 2023 Aug 22
" Setup {{{1
if exists("b:did_ftplugin")
@@ -70,8 +70,12 @@ endif
if (has("gui_win32") || has("gui_gtk")) && exists("b:basic_set_browsefilter")
let b:browsefilter = "FreeBASIC Source Files (*.bas)\t*.bas\n" ..
- \ "FreeBASIC Header Files (*.bi)\t*.bi\n" ..
- \ "All Files (*.*)\t*.*\n"
+ \ "FreeBASIC Header Files (*.bi)\t*.bi\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
endif
" Cleanup {{{1
diff --git a/runtime/ftplugin/gdscript.vim b/runtime/ftplugin/gdscript.vim
new file mode 100644
index 0000000000..692afdd0ea
--- /dev/null
+++ b/runtime/ftplugin/gdscript.vim
@@ -0,0 +1,68 @@
+" Vim filetype plugin file
+" Language: gdscript (Godot game engine scripting language)
+" Maintainer: Maxim Kim <habamax@gmail.com>
+" Website: https://github.com/habamax/vim-gdscript
+"
+" This file has been manually translated from Vim9 script.
+
+if exists("b:did_ftplugin") | finish | endif
+
+let s:save_cpo = &cpo
+set cpo&vim
+
+let b:did_ftplugin = 1
+let b:undo_ftplugin = 'setlocal cinkeys<'
+ \ .. '| setlocal indentkeys<'
+ \ .. '| setlocal commentstring<'
+ \ .. '| setlocal suffixesadd<'
+ \ .. '| setlocal foldexpr<'
+ \ .. '| setlocal foldignore<'
+
+setlocal cinkeys-=0#
+setlocal indentkeys-=0#
+setlocal suffixesadd=.gd
+setlocal commentstring=#\ %s
+setlocal foldignore=
+setlocal foldexpr=s:GDScriptFoldLevel()
+
+
+function s:GDScriptFoldLevel() abort
+ let line = getline(v:lnum)
+ if line =~? '^\s*$'
+ return "-1"
+ endif
+
+ let sw = shiftwidth()
+ let indent = indent(v:lnum) / sw
+ let indent_next = indent(nextnonblank(v:lnum + 1)) / sw
+
+ if indent_next > indent && line =~# ':\s*$'
+ return $">{indent_next}"
+ else
+ return $"{indent}"
+ endif
+endfunction
+
+
+if !exists("g:no_plugin_maps")
+ " Next/Previous section
+ function s:NextSection(back, cnt) abort
+ for n in range(a:cnt)
+ call search('^\s*func\s', a:back ? 'bW' : 'W')
+ endfor
+ endfunction
+
+ " Nvim: <scriptcmd> hasn't been ported yet.
+ " nnoremap <silent><buffer> ]] <scriptcmd>NextSection(false, v:count1)<CR>
+ " nnoremap <silent><buffer> [[ <scriptcmd>NextSection(true, v:count1)<CR>
+ nnoremap <silent><buffer> ]] <Cmd>call <SID>NextSection(v:false, v:count1)<CR>
+ nnoremap <silent><buffer> [[ <Cmd>call <SID>NextSection(v:true, v:count1)<CR>
+ xmap <buffer><expr> ]] $'<C-\><C-N>{v:count1}]]m>gv'
+ xmap <buffer><expr> [[ $'<C-\><C-N>{v:count1}[[m>gv'
+ let b:undo_ftplugin ..=
+ \ " | silent exe 'unmap <buffer> [['"
+ \ .. " | silent exe 'unmap <buffer> ]]'"
+endif
+
+let &cpo = s:save_cpo
+unlet s:save_cpo
diff --git a/runtime/ftplugin/gdshader.vim b/runtime/ftplugin/gdshader.vim
new file mode 100644
index 0000000000..f0d34ee5a6
--- /dev/null
+++ b/runtime/ftplugin/gdshader.vim
@@ -0,0 +1,13 @@
+" Vim filetype plugin file
+" Language: Godot shading language
+" Maintainer: Maxim Kim <habamax@gmail.com>
+" Website: https://github.com/habamax/vim-gdscript
+"
+" This file has been manually translated from Vim9 script.
+
+if exists("b:did_ftplugin") | finish | endif
+let b:did_ftplugin = 1
+
+let b:undo_ftplugin = 'setlocal suffixesadd<'
+
+setlocal suffixesadd=.gdshader
diff --git a/runtime/ftplugin/git.vim b/runtime/ftplugin/git.vim
new file mode 100644
index 0000000000..7fcce53056
--- /dev/null
+++ b/runtime/ftplugin/git.vim
@@ -0,0 +1,15 @@
+" Vim filetype plugin
+" Language: generic git output
+" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
+" Last Change: 2023 Mar 26
+
+" Only do this when not done yet for this buffer
+if (exists("b:did_ftplugin"))
+ finish
+endif
+
+let b:did_ftplugin = 1
+
+setlocal nomodeline
+
+let b:undo_ftplugin = "setl modeline<"
diff --git a/runtime/ftplugin/gitcommit.vim b/runtime/ftplugin/gitcommit.vim
index 9342799b56..3749328595 100644
--- a/runtime/ftplugin/gitcommit.vim
+++ b/runtime/ftplugin/gitcommit.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin
" Language: git commit file
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
-" Last Change: 2022 Jan 05
+" Last Change: 2023 Dec 28
" Only do this when not done yet for this buffer
if (exists("b:did_ftplugin"))
@@ -12,7 +12,7 @@ let b:did_ftplugin = 1
setlocal nomodeline tabstop=8 formatoptions+=tl textwidth=72
setlocal formatoptions-=c formatoptions-=r formatoptions-=o formatoptions-=q formatoptions+=n
-setlocal formatlistpat+=\\\|^\\s*[-*+]\\s\\+
+setlocal formatlistpat=^\\s*\\d\\+[\\]:.)}]\\s\\+\\\|^\\s*[-*+]\\s\\+
setlocal include=^+++
setlocal includeexpr=substitute(v:fname,'^[bi]/','','')
@@ -42,6 +42,11 @@ function! s:diffcomplete(A, L, P) abort
return args
endfunction
+function! s:setupdiff() abort
+ command! -bang -bar -buffer -complete=custom,s:diffcomplete -nargs=* DiffGitCached :call s:gitdiffcached(<bang>0, <f-args>)
+ setlocal buftype=nowrite nobuflisted noswapfile nomodifiable filetype=git
+endfunction
+
function! s:gitdiffcached(bang, ...) abort
let name = tempname()
if a:0
@@ -50,8 +55,6 @@ function! s:gitdiffcached(bang, ...) abort
let extra = "-p --stat=".&columns
endif
call system("git diff --cached --no-color --no-ext-diff ".extra." > ".shellescape(name))
- exe "pedit " . fnameescape(name)
- wincmd P
- command! -bang -bar -buffer -complete=custom,s:diffcomplete -nargs=* DiffGitCached :call s:gitdiffcached(<bang>0, <f-args>)
- setlocal buftype=nowrite nobuflisted noswapfile nomodifiable filetype=git
+ exe 'pedit +call\ s:setupdiff()' fnameescape(name)
+ silent! wincmd P
endfunction
diff --git a/runtime/ftplugin/haml.vim b/runtime/ftplugin/haml.vim
index 6f30169958..910d9c78b3 100644
--- a/runtime/ftplugin/haml.vim
+++ b/runtime/ftplugin/haml.vim
@@ -2,6 +2,7 @@
" Language: Haml
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
" Last Change: 2019 Dec 05
+" 2024 Jan 14 by Vim Project (browsefilter)
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -13,7 +14,11 @@ set cpo-=C
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
-let s:browsefilter = "All Files (*.*)\t*.*\n"
+if has("win32")
+ let s:browsefilter = "All Files (*.*)\t*\n"
+else
+ let s:browsefilter = "All Files (*)\t*\n"
+endif
let s:match_words = ""
runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim
@@ -44,14 +49,14 @@ if exists("b:undo_ftplugin")
let s:undo_ftplugin = b:undo_ftplugin . " | " . s:undo_ftplugin
endif
if exists ("b:browsefilter")
- let s:browsefilter = substitute(b:browsefilter,'\cAll Files (\*\.\*)\t\*\.\*\n','','') . s:browsefilter
+ let s:browsefilter = substitute(b:browsefilter,'\cAll Files (.*)\t\*\n','','') . s:browsefilter
endif
if exists("b:match_words")
let s:match_words = b:match_words . ',' . s:match_words
endif
-" Change the browse dialog on Win32 to show mainly Haml-related files
-if has("gui_win32")
+" Change the browse dialog on Win32 and GTK to show mainly Haml-related files
+if has("gui_win32") || has("gui_gtk")
let b:browsefilter="Haml Files (*.haml)\t*.haml\nSass Files (*.sass)\t*.sass\n" . s:browsefilter
endif
@@ -62,7 +67,7 @@ endif
setlocal comments= commentstring=-#\ %s
-let b:undo_ftplugin = "setl def< cms< com< "
+let b:undo_ftplugin = "setl def< cms< com< " .
\ " | unlet! b:browsefilter b:match_words | " . s:undo_ftplugin
let &cpo = s:save_cpo
diff --git a/runtime/ftplugin/help.lua b/runtime/ftplugin/help.lua
index 4cc3386167..67c417b1be 100644
--- a/runtime/ftplugin/help.lua
+++ b/runtime/ftplugin/help.lua
@@ -1,3 +1,28 @@
-if vim.endswith(vim.fs.normalize(vim.api.nvim_buf_get_name(0)), '/doc/syntax.txt') then
- require('vim.vimhelp').highlight_groups()
+-- use treesitter over syntax (for highlighted code blocks)
+vim.treesitter.start()
+
+-- add custom highlights for list in `:h highlight-groups`
+local bufname = vim.fs.normalize(vim.api.nvim_buf_get_name(0))
+if vim.endswith(bufname, '/doc/syntax.txt') then
+ require('vim.vimhelp').highlight_groups({
+ { start = [[\*group-name\*]], stop = '^======', match = '^(%w+)\t' },
+ { start = [[\*highlight-groups\*]], stop = '^======', match = '^(%w+)\t' },
+ })
+elseif vim.endswith(bufname, '/doc/treesitter.txt') then
+ require('vim.vimhelp').highlight_groups({
+ {
+ start = [[\*treesitter-highlight-groups\*]],
+ stop = [[\*treesitter-highlight-spell\*]],
+ match = '^@[%w%p]+',
+ },
+ })
+elseif vim.endswith(bufname, '/doc/diagnostic.txt') then
+ require('vim.vimhelp').highlight_groups({
+ { start = [[\*diagnostic-highlights\*]], stop = '^======', match = '^(%w+)' },
+ })
+elseif vim.endswith(bufname, '/doc/lsp.txt') then
+ require('vim.vimhelp').highlight_groups({
+ { start = [[\*lsp-highlight\*]], stop = '^------', match = '^(%w+)' },
+ { start = [[\*lsp-semantic-highlight\*]], stop = '^======', match = '^@[%w%p]+' },
+ })
end
diff --git a/runtime/ftplugin/help.vim b/runtime/ftplugin/help.vim
index a6a6652b2f..a188e45cb4 100644
--- a/runtime/ftplugin/help.vim
+++ b/runtime/ftplugin/help.vim
@@ -71,7 +71,7 @@ if !exists('g:no_plugin_maps')
if indent(lnum) <= indent(l)
let level = has_section + has_sub_section
- let add_text = matchstr(text, '\S.*')
+ let add_text = matchstr(text, '\S.\{-}\ze\s\=\~$')
endif
endif
@@ -79,7 +79,7 @@ if !exists('g:no_plugin_maps')
if !empty(add_text) && last_added != lnum
let last_added = lnum
call add(toc, {'bufnr': bufnr('%'), 'lnum': lnum,
- \ 'text': repeat(' ', level) . add_text})
+ \ 'text': repeat("\u00a0\u00a0", level) . add_text})
endif
let lnum = nextnonblank(lnum + 1)
endwhile
diff --git a/runtime/ftplugin/html.vim b/runtime/ftplugin/html.vim
index 94cb62653f..3aa60a873e 100644
--- a/runtime/ftplugin/html.vim
+++ b/runtime/ftplugin/html.vim
@@ -2,7 +2,7 @@
" Language: HTML
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer: Dan Sharp
-" Last Changed: 2022 Jul 20
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -43,10 +43,14 @@ endif
" Change the :browse e filter to primarily show HTML-related files.
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "HTML Files (*.html *.htm)\t*.htm;*.html\n" ..
+ let b:browsefilter = "HTML Files (*.html, *.htm)\t*.html;*.htm\n" ..
\ "JavaScript Files (*.js)\t*.js\n" ..
- \ "Cascading StyleSheets (*.css)\t*.css\n" ..
- \ "All Files (*.*)\t*.*\n"
+ \ "Cascading StyleSheets (*.css)\t*.css\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:html_set_browsefilter = 1
let b:undo_ftplugin ..= " | unlet! b:browsefilter b:html_set_browsefilter"
endif
diff --git a/runtime/ftplugin/hurl.vim b/runtime/ftplugin/hurl.vim
new file mode 100644
index 0000000000..10a3131d3a
--- /dev/null
+++ b/runtime/ftplugin/hurl.vim
@@ -0,0 +1,11 @@
+" Vim filetype plugin file
+" Language: hurl
+" Maintainer: Melker Ulander <melker.ulander@pm.me>
+" Last Changed: 2024 01 26
+
+if exists("b:did_ftplugin") | finish | endif
+
+let b:did_ftplugin = 1
+setlocal commentstring=#\ %s
+
+let b:undo_ftplugin = "setlocal commentstring<"
diff --git a/runtime/ftplugin/icon.vim b/runtime/ftplugin/icon.vim
index 33a86dfb9e..10411c8194 100644
--- a/runtime/ftplugin/icon.vim
+++ b/runtime/ftplugin/icon.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Icon
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2022 Jun 16
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -18,15 +18,19 @@ setlocal formatoptions-=t formatoptions+=croql
let b:undo_ftplugin = "setl fo< com< cms<"
if exists("loaded_matchit")
- " let b:match_ignorecase = 0
- let b:match_words = '^\s*$\s*if\(def\|ndef\)\=\>:^\s*$\s*elif\>:^\s*$\s*else\>:^\s*$\s*endif\>,' .
+ let b:match_ignorecase = 0
+ let b:match_words = '^\s*$\s*if\(def\|ndef\)\=\>:^\s*$\s*elif\>:^\s*$\s*else\>:^\s*$\s*endif\>,' ..
\ '\<procedure\>:\<\%(initial\|return\|suspend\|fail\)\>:\<end\>'
- let b:undo_ftplugin ..= " | unlet! b:match_words"
+ let b:undo_ftplugin ..= " | unlet! b:match_ignorecase b:match_words"
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Icon Source Files (*.icn)\t*.icn\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Icon Source Files (*.icn)\t*.icn\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/ishd.vim b/runtime/ftplugin/ishd.vim
index b160349033..5e33efde78 100644
--- a/runtime/ftplugin/ishd.vim
+++ b/runtime/ftplugin/ishd.vim
@@ -2,7 +2,7 @@
" Language: InstallShield (ft=ishd)
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer: Johannes Zellner <johannes@zellner.org>
-" Last Change: 2023 Aug 28
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin") | finish | endif
let b:did_ftplugin = 1
@@ -29,8 +29,12 @@ if exists("loaded_matchit")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "InstallShield Files (*.rul)\t*.rul\n" .
- \ "All Files (*.*)\t*\n"
+ let b:browsefilter = "InstallShield Files (*.rul)\t*.rul\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/j.vim b/runtime/ftplugin/j.vim
index ae235abba8..8335ea06c6 100644
--- a/runtime/ftplugin/j.vim
+++ b/runtime/ftplugin/j.vim
@@ -3,6 +3,7 @@
" Maintainer: David Bürgin <dbuergin@gluet.ch>
" URL: https://gitlab.com/glts/vim-j
" Last Change: 2022-08-06
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists('b:did_ftplugin')
finish
@@ -67,7 +68,11 @@ endif
" Browse dialog filter on Windows and GTK (see ":help browsefilter")
if (has('gui_win32') || has('gui_gtk')) && !exists('b:browsefilter')
let b:browsefilter = "J Script Files (*.ijs)\t*.ijs\n"
- \ . "All Files (*.*)\t*.*\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin .= ' | unlet! b:browsefilter'
endif
diff --git a/runtime/ftplugin/java.vim b/runtime/ftplugin/java.vim
index 74c8e8d1c1..bb7e7cd72c 100644
--- a/runtime/ftplugin/java.vim
+++ b/runtime/ftplugin/java.vim
@@ -1,10 +1,11 @@
" Vim filetype plugin file
-" Language: Java
+" Language: Java
"
" This runtime file is looking for a new maintainer.
"
" Former maintainer: Dan Sharp
-" Last Change: 2012 Mar 11
+" Last Change: 2012 Mar 11
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
let b:did_ftplugin = 1
@@ -36,11 +37,15 @@ setlocal comments& comments^=sO:*\ -,mO:*\ \ ,exO:*/
setlocal commentstring=//%s
" Change the :browse e filter to primarily show Java-related files.
-if has("gui_win32")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="Java Files (*.java)\t*.java\n" .
\ "Properties Files (*.prop*)\t*.prop*\n" .
- \ "Manifest Files (*.mf)\t*.mf\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "Manifest Files (*.mf)\t*.mf\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
" Undo the stuff we changed.
diff --git a/runtime/ftplugin/javascript.vim b/runtime/ftplugin/javascript.vim
index 9a0b29e0ca..2633954903 100644
--- a/runtime/ftplugin/javascript.vim
+++ b/runtime/ftplugin/javascript.vim
@@ -1,8 +1,8 @@
" Vim filetype plugin file
" Language: Javascript
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2020 Jun 23
" Contributor: Romain Lafourcade <romainlafourcade@gmail.com>
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -34,7 +34,11 @@ if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
\ .. "JavaScript Modules (*.es, *.es6, *.cjs, *.mjs, *.jsm)\t*.es;*.es6;*.cjs;*.mjs;*.jsm\n"
\ .. "Vue Templates (*.vue)\t*.vue\n"
\ .. "JSON Files (*.json)\t*.json\n"
- \ .. "All Files (*.*)\t*.*\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
endif
" The following suffixes should be implied when resolving filenames
diff --git a/runtime/ftplugin/json5.vim b/runtime/ftplugin/json5.vim
index 2560857a33..302ed7606c 100644
--- a/runtime/ftplugin/json5.vim
+++ b/runtime/ftplugin/json5.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: JSON5
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2023 Oct 19
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -19,8 +19,12 @@ let b:undo_ftplugin = "setl fo< com< cms<"
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "JSON5 Files (*.json5)\t*.json5\n" ..
- \ "JSON Files (*.json)\t*.json\n" ..
- \ "All Files (*.*)\t*.*\n"
+ \ "JSON Files (*.json)\t*.json\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/jsp.vim b/runtime/ftplugin/jsp.vim
index 18136ccc24..cc7023279a 100644
--- a/runtime/ftplugin/jsp.vim
+++ b/runtime/ftplugin/jsp.vim
@@ -1,10 +1,11 @@
" Vim filetype plugin file
-" Language: jsp
+" Language: jsp
"
" This runtime file is looking for a new maintainer.
"
" Former maintainer: Dan Sharp
-" Last Changed: 20 Jan 2009
+" Last Change: 2009 Jan 20
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
@@ -16,8 +17,12 @@ set cpo-=C
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
let s:browsefilter = "Java Files (*.java)\t*.java\n" .
- \ "HTML Files (*.html, *.htm)\t*.html;*.htm\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "HTML Files (*.html, *.htm)\t*.html;*.htm\n"
+if has("win32")
+ let s:browsefilter .= "All Files (*.*)\t*\n"
+else
+ let s:browsefilter .= "All Files (*)\t*\n"
+endif
let s:match_words = ""
runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim
@@ -57,7 +62,7 @@ if exists("loaded_matchit")
endif
" Change the :browse e filter to primarily show JSP-related files.
-if has("gui_win32")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="JSP Files (*.jsp)\t*.jsp\n" . s:browsefilter
endif
diff --git a/runtime/ftplugin/kotlin.vim b/runtime/ftplugin/kotlin.vim
index b21de603ea..5c07088adb 100644
--- a/runtime/ftplugin/kotlin.vim
+++ b/runtime/ftplugin/kotlin.vim
@@ -3,7 +3,7 @@
" Maintainer: Alexander Udalov
" URL: https://github.com/udalov/kotlin-vim
" Last Change: 7 November 2021
-" 2023 Sep 17 by Vim Project (browsefilter)
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists('b:did_ftplugin') | finish | endif
let b:did_ftplugin = 1
@@ -24,8 +24,12 @@ let b:undo_ftplugin = "setlocal comments< commentstring< ".
\ "formatoptions< includeexpr< suffixesadd<"
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Kotlin Source Files (*.kt, *kts)\t*.kt;*.kts\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Kotlin Source Files (*.kt, *kts)\t*.kt;*.kts\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/kwt.vim b/runtime/ftplugin/kwt.vim
index 05b40d4e29..b37c7fa3a3 100644
--- a/runtime/ftplugin/kwt.vim
+++ b/runtime/ftplugin/kwt.vim
@@ -2,6 +2,7 @@
" Language: Kimwitu++
" Maintainer: Michael Piefel <entwurf@piefel.de>
" Last Change: 10 March 2012
+" 2024 Jan 14 by Vim Project (browsefilter)
" Behaves almost like C++
runtime! ftplugin/cpp.vim ftplugin/cpp_*.vim ftplugin/cpp/*.vim
@@ -10,11 +11,15 @@ let s:cpo_save = &cpo
set cpo&vim
" Limit the browser to related files
-if has("gui_win32") && !exists("b:browsefilter")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "Kimwitu/Kimwitu++ Files (*.k)\t*.k\n" .
\ "Lex/Flex Files (*.l)\t*.l\n" .
- \ "Yacc/Bison Files (*.y)\t*.y\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "Yacc/Bison Files (*.y)\t*.y\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
endif
" Set the errorformat for the Kimwitu++ compiler
@@ -22,10 +27,10 @@ set efm+=kc%.%#:\ error\ at\ %f:%l:\ %m
if exists("b:undo_ftplugin")
let b:undo_ftplugin = b:undo_ftplugin . " | setlocal efm<"
- \ . "| unlet! b:browsefiler"
+ \ . "| unlet! b:browsefilter"
else
let b:undo_ftplugin = "setlocal efm<"
- \ . "| unlet! b:browsefiler"
+ \ . "| unlet! b:browsefilter"
endif
let &cpo = s:cpo_save
diff --git a/runtime/ftplugin/logtalk.dict b/runtime/ftplugin/logtalk.dict
index 3fcdfc6f6a..0d076b7b3e 100644
--- a/runtime/ftplugin/logtalk.dict
+++ b/runtime/ftplugin/logtalk.dict
@@ -18,11 +18,8 @@ atan2
atom
atomic
atom_chars
-atom_chars
-atom_codes
atom_codes
atom_concat
-atom_concat
atom_length
at_end_of_stream
bagof
@@ -32,6 +29,7 @@ call
callable
calls
catch
+catchall_catch
category
category_property
ceiling
@@ -45,9 +43,9 @@ coinduction
coinductive
compare
complements
-complements
complements_object
compound
+conditionals
conforms_to_protocol
context
context_switching_calls
@@ -87,6 +85,7 @@ end_object
end_protocol
engines
ensure_loaded
+error
evaluation_error
events
existence_error
@@ -152,12 +151,13 @@ nonvar
number
numbervars
number_chars
-number_chars
-number_codes
number_codes
object
object_property
once
+one
+one_or_error
+one_or_more
op
open
optimize
@@ -226,6 +226,7 @@ term_variables
this
threaded
threaded_call
+threaded_cancel
threaded_engine
threaded_engine_create
threaded_engine_destroy
@@ -250,6 +251,7 @@ type_error
undefined_predicates
underscore_variables
unify_with_occurs_check
+uninstantiation_error
unknown_entities
unknown_predicates
uses
@@ -260,3 +262,8 @@ write
writeq
write_canonical
xor
+zero
+zero_or_error
+zero_or_more
+zero_or_one
+zero_or_one_or_error
diff --git a/runtime/ftplugin/lua.lua b/runtime/ftplugin/lua.lua
new file mode 100644
index 0000000000..98f218e36e
--- /dev/null
+++ b/runtime/ftplugin/lua.lua
@@ -0,0 +1,2 @@
+-- use treesitter over syntax
+vim.treesitter.start()
diff --git a/runtime/ftplugin/lua.vim b/runtime/ftplugin/lua.vim
index 3529e1e3fd..80cbba78a2 100644
--- a/runtime/ftplugin/lua.vim
+++ b/runtime/ftplugin/lua.vim
@@ -5,7 +5,7 @@
" Contributor: Dorai Sitaram <ds26@gte.com>
" C.D. MacEachern <craig.daniel.maceachern@gmail.com>
" Tyler Miller <tmillr@proton.me>
-" Last Change: 2023 Mar 24
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -39,8 +39,12 @@ if exists("loaded_matchit") && !exists("b:match_words")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Lua Source Files (*.lua)\t*.lua\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Lua Source Files (*.lua)\t*.lua\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/lynx.vim b/runtime/ftplugin/lynx.vim
index bf8410d6a0..4afed0a249 100644
--- a/runtime/ftplugin/lynx.vim
+++ b/runtime/ftplugin/lynx.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Lynx Web Browser Configuration
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2023 Nov 09
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -18,8 +18,12 @@ setlocal formatoptions-=t formatoptions+=croql
let b:undo_ftplugin = "setl cms< com< fo<"
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Lynx Configuration Files (lynx.cfg, .lynxrc)\tlynx.cfg;.lynxrc\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Lynx Configuration Files (lynx.cfg, .lynxrc)\tlynx.cfg;.lynxrc\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/m3build.vim b/runtime/ftplugin/m3build.vim
index c910eaecd0..71960cec6d 100644
--- a/runtime/ftplugin/m3build.vim
+++ b/runtime/ftplugin/m3build.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Modula-3 Makefile
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2022 June 12
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -13,8 +13,12 @@ set cpo&vim
runtime! ftplugin/m3quake.vim
if (has("gui_win32") || has("gui_gtk")) && exists("b:m3quake_set_browsefilter")
- let b:browsefilter = "Modula-3 Makefile (m3makefile m3overrides)\tm3makefile;m3overrides\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Modula-3 Makefile (m3makefile, m3overrides)\tm3makefile;m3overrides\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
endif
let &cpo = s:cpo_save
diff --git a/runtime/ftplugin/m3quake.vim b/runtime/ftplugin/m3quake.vim
index 7762875db9..33ba633ac6 100644
--- a/runtime/ftplugin/m3quake.vim
+++ b/runtime/ftplugin/m3quake.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Modula-3 Quake
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2022 June 12
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -23,8 +23,12 @@ if exists("loaded_matchit") && !exists("b:match_words")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Modula-3 Quake Source Files (*.quake)\t*.quake\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Modula-3 Quake Source Files (*.quake)\t*.quake\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:m3quake_set_browsefilter = 1
let b:undo_ftplugin ..= " | unlet! b:browsefilter b:m3quake_set_browsefilter"
endif
diff --git a/runtime/ftplugin/markdown.vim b/runtime/ftplugin/markdown.vim
index 2b963f139d..022dd0d601 100644
--- a/runtime/ftplugin/markdown.vim
+++ b/runtime/ftplugin/markdown.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin
" Language: Markdown
" Maintainer: Tim Pope <https://github.com/tpope/vim-markdown>
-" Last Change: 2022 Oct 13
+" Last Change: 2023 Dec 28
if exists("b:did_ftplugin")
finish
@@ -35,7 +35,7 @@ if !exists("g:no_plugin_maps") && !exists("g:no_markdown_maps")
endif
function! s:NotCodeBlock(lnum) abort
- return synIDattr(synID(a:lnum, 1, 1), 'name') !=# 'markdownCode'
+ return synIDattr(synID(a:lnum, 1, 1), 'name') !=# 'markdownCodeBlock'
endfunction
function! MarkdownFold() abort
diff --git a/runtime/ftplugin/meson.vim b/runtime/ftplugin/meson.vim
index 1ce9a03037..17ffd5320a 100644
--- a/runtime/ftplugin/meson.vim
+++ b/runtime/ftplugin/meson.vim
@@ -4,6 +4,7 @@
" Maintainer: Liam Beguin <liambeguin@gmail.com>
" Original Author: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
" Last Change: 2018 Nov 27
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
let b:did_ftplugin = 1
@@ -30,8 +31,12 @@ if exists("loaded_matchit") && !exists("b:match_words")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Meson Build Files (meson.build)\tmeson.build\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Meson Build Files (meson.build)\tmeson.build\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/modula2.vim b/runtime/ftplugin/modula2.vim
index 1d0e81ee70..9c1acc276a 100644
--- a/runtime/ftplugin/modula2.vim
+++ b/runtime/ftplugin/modula2.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Modula-2
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2021 Apr 08
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -11,28 +11,43 @@ let b:did_ftplugin = 1
let s:cpo_save = &cpo
set cpo&vim
-setlocal comments=s0:(*,mb:\ ,ex:*)
-setlocal commentstring=(*%s*)
+let s:dialect = modula2#GetDialect()
+
+if s:dialect ==# "r10"
+ setlocal comments=s:(*,m:\ ,e:*),:!
+ setlocal commentstring=!\ %s
+else
+ setlocal commentstring=(*%s*)
+ setlocal comments=s:(*,m:\ ,e:*)
+endif
setlocal formatoptions-=t formatoptions+=croql
+let b:undo_ftplugin = "setl com< cms< fo<"
+
if exists("loaded_matchit") && !exists("b:match_words")
- " The second branch of the middle pattern is intended to match CASE labels
+ let b:match_ignorecase = 0
+ " the second branch of the middle pattern is intended to match CASE labels
let b:match_words = '\<REPEAT\>:\<UNTIL\>,' ..
- \ '\<\%(BEGIN\|CASE\|FOR\|IF\|LOOP\|WHILE\|WITH\)\>' ..
- \ ':' ..
- \ '\<\%(ELSIF\|ELSE\)\>\|\%(^\s*\)\@<=\w\+\%(\s*\,\s*\w\+\)\=\s*\:=\@!' ..
- \ ':' ..
- \ '\<END\>'
+ \ '\<\%(BEGIN\|CASE\|FOR\|IF\|LOOP\|WHILE\|WITH\|RECORD\)\>' ..
+ \ ':' ..
+ \ '\<\%(ELSIF\|ELSE\)\>\|\%(^\s*\)\@<=\w\+\%(\s*\,\s*\w\+\)\=\s*\:=\@!' ..
+ \ ':' ..
+ \ '\<END\>,' ..
+ \ '(\*:\*),<\*:\*>'
+ let b:match_skip = 's:Comment\|Pragma'
+ let b:undo_ftplugin ..= " | unlet! b:match_ignorecase b:match_skip b:match_words"
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Modula-2 Source Files (*.def *.mod)\t*.def;*.mod\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Modula-2 Source Files (*.def, *.mod)\t*.def;*.mod\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
+ let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
-let b:undo_ftplugin = "setl com< cms< fo< " ..
- \ "| unlet! b:browsefilter b:match_words"
-
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/modula3.vim b/runtime/ftplugin/modula3.vim
index 1f8ab359d5..45dd7ca01c 100644
--- a/runtime/ftplugin/modula3.vim
+++ b/runtime/ftplugin/modula3.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Modula-3
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2022 June 12
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -31,8 +31,12 @@ if exists("loaded_matchit") && !exists("b:match_words")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Modula-3 Source Files (*.m3)\t*.m3\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Modula-3 Source Files (*.m3, *.i3, *.mg, *ig)\t*.m3;*.i3;*.mg;*.ig\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/msmessages.vim b/runtime/ftplugin/msmessages.vim
index 791eafe794..c4cbd94b13 100644
--- a/runtime/ftplugin/msmessages.vim
+++ b/runtime/ftplugin/msmessages.vim
@@ -2,6 +2,7 @@
" Language: MS Message files (*.mc)
" Maintainer: Kevin Locke <kwl7@cornell.edu>
" Last Change: 2008 April 09
+" 2024 Jan 14 by Vim Project (browsefilter)
" Location: http://kevinlocke.name/programs/vim/syntax/msmessages.vim
" Based on c.vim
@@ -29,11 +30,15 @@ setlocal fo-=ct fo+=roql
setlocal comments=:;,:;//,:;\ //,s:;\ /*\ ,m:;\ \ *\ ,e:;\ \ */
setlocal commentstring=;\ //\ %s
-" Win32 can filter files in the browse dialog
-if has("gui_win32") && !exists("b:browsefilter")
+" Win32 and GTK can filter files in the browse dialog
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "MS Message Files (*.mc)\t*.mc\n" .
- \ "Resource Files (*.rc)\t*.rc\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "Resource Files (*.rc)\t*.rc\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
let &cpo = s:cpo_save
diff --git a/runtime/ftplugin/occam.vim b/runtime/ftplugin/occam.vim
index e9b7c014b3..0eb510f76d 100644
--- a/runtime/ftplugin/occam.vim
+++ b/runtime/ftplugin/occam.vim
@@ -3,6 +3,7 @@
" Copyright: Christian Jacobsen <clj3@kent.ac.uk>, Mario Schweigler <ms44@kent.ac.uk>
" Maintainer: Mario Schweigler <ms44@kent.ac.uk>
" Last Change: 23 April 2003
+" 2024 Jan 14 by Vim Project (browsefilter)
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -30,19 +31,23 @@ setlocal textwidth=78
"}}}
"{{{ File browsing filters
-" Win32 can filter files in the browse dialog
-if has("gui_win32") && !exists("b:browsefilter")
- let b:browsefilter = "All Occam Files (*.occ *.inc)\t*.occ;*.inc\n" .
+" Win32 and GTK can filter files in the browse dialog
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "All Occam Files (*.occ, *.inc)\t*.occ;*.inc\n" .
\ "Occam Include Files (*.inc)\t*.inc\n" .
- \ "Occam Source Files (*.occ)\t*.occ\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "Occam Source Files (*.occ)\t*.occ\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
"}}}
"{{{ Undo settings
let b:undo_ftplugin = "setlocal shiftwidth< softtabstop< expandtab<"
\ . " formatoptions< comments< textwidth<"
- \ . "| unlet! b:browsefiler"
+ \ . "| unlet! b:browsefilter"
"}}}
let &cpo = s:keepcpo
diff --git a/runtime/ftplugin/octave.vim b/runtime/ftplugin/octave.vim
index 7cab7c212a..480b46a6eb 100644
--- a/runtime/ftplugin/octave.vim
+++ b/runtime/ftplugin/octave.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: GNU Octave
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2021 Sep 02
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -50,8 +50,12 @@ if exists("loaded_matchit") && !exists("b:match_words")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "GNU Octave Source Files (*.m)\t*.m\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "GNU Octave Source Files (*.m)\t*.m\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
endif
let b:undo_ftplugin = "setl com< cms< fo< kp< " ..
diff --git a/runtime/ftplugin/odin.vim b/runtime/ftplugin/odin.vim
new file mode 100644
index 0000000000..c50fea65a3
--- /dev/null
+++ b/runtime/ftplugin/odin.vim
@@ -0,0 +1,26 @@
+" Vim filetype plugin file
+" Language: Odin
+" Maintainer: Maxim Kim <habamax@gmail.com>
+" Website: https://github.com/habamax/vim-odin
+" Last Change: 2024-01-15
+"
+" This file has been manually translated from Vim9 script.
+
+if exists("b:did_ftplugin")
+ finish
+endif
+let b:did_ftplugin = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+let b:undo_ftplugin = 'setlocal commentstring<'
+ \ .. '| setlocal comments<'
+ \ .. '| setlocal suffixesadd<'
+
+setlocal suffixesadd=.odin
+setlocal commentstring=//%s
+setlocal comments=s1:/*,mb:*,ex:*/,://
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/ftplugin/pascal.vim b/runtime/ftplugin/pascal.vim
index aba1e54f27..9abd7dd382 100644
--- a/runtime/ftplugin/pascal.vim
+++ b/runtime/ftplugin/pascal.vim
@@ -2,7 +2,7 @@
" Language: Pascal
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer: Dan Sharp
-" Last Change: 2021 Apr 23
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin") | finish | endif
let b:did_ftplugin = 1
@@ -37,8 +37,12 @@ if exists("loaded_matchit")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Pascal Source Files (*.pas *.pp *.inc)\t*.pas;*.pp;*.inc\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Pascal Source Files (*.pas, *.pp, *.inc)\t*.pas;*.pp;*.inc\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
endif
let b:undo_ftplugin = "setl fo< cms< com< " ..
diff --git a/runtime/ftplugin/perl.vim b/runtime/ftplugin/perl.vim
index c63bd3f9c7..8c6a80eb4f 100644
--- a/runtime/ftplugin/perl.vim
+++ b/runtime/ftplugin/perl.vim
@@ -7,6 +7,7 @@
" Last Change: 2021 Nov 10
" 2023 Sep 07 by Vim Project (safety check: don't execute perl
" from current directory)
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
let b:did_ftplugin = 1
@@ -95,8 +96,12 @@ let b:undo_ftplugin .= " | setlocal pa<"
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "Perl Source Files (*.pl)\t*.pl\n" .
\ "Perl Modules (*.pm)\t*.pm\n" .
- \ "Perl Documentation Files (*.pod)\t*.pod\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "Perl Documentation Files (*.pod)\t*.pod\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/php.vim b/runtime/ftplugin/php.vim
index 540653e030..f03f14512a 100644
--- a/runtime/ftplugin/php.vim
+++ b/runtime/ftplugin/php.vim
@@ -2,7 +2,7 @@
" Language: PHP
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer: Dan Sharp
-" Last Changed: 2022 Jul 20
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -15,8 +15,12 @@ set cpo&vim
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
-let s:browsefilter = "HTML Files (*.html, *.htm)\t*.html;*.htm\n" ..
- \ "All Files (*.*)\t*.*\n"
+let s:browsefilter = "HTML Files (*.html, *.htm)\t*.html;*.htm\n"
+if has("win32")
+ let s:browsefilter ..= "All Files (*.*)\t*\n"
+else
+ let s:browsefilter ..= "All Files (*)\t*\n"
+endif
let s:match_words = ""
runtime! ftplugin/html.vim ftplugin/html_*.vim ftplugin/html/*.vim
diff --git a/runtime/ftplugin/pod.vim b/runtime/ftplugin/pod.vim
index 61a4aa094a..81b0011bc5 100644
--- a/runtime/ftplugin/pod.vim
+++ b/runtime/ftplugin/pod.vim
@@ -6,6 +6,8 @@
" Bugs/requests: https://github.com/vim-perl/vim-perl/issues
" License: Vim License (see :help license)
" Last Change: 2023 Jul 05
+" Last Change: 2021 Oct 19
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin")
finish
@@ -33,8 +35,12 @@ endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "POD Source Files (*.pod)\t*.pod\n" .
\ "Perl Source Files (*.pl)\t*.pl\n" .
- \ "Perl Modules (*.pm)\t*.pm\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "Perl Modules (*.pm)\t*.pm\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/poke.vim b/runtime/ftplugin/poke.vim
index 2be86695c8..4e31700995 100644
--- a/runtime/ftplugin/poke.vim
+++ b/runtime/ftplugin/poke.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: GNU Poke
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2021 March 11
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -18,14 +18,18 @@ setlocal formatoptions-=t formatoptions+=croql
setlocal include=load
setlocal suffixesadd=.pk
+let b:undo_ftplugin = "setl fo< com< cms< inc< sua<"
+
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Poke Files (*.pk)\t*.pk\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Poke Files (*.pk)\t*.pk\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
+ let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
-let b:undo_ftplugin = "setl fo< com< cms< inc< sua<" .
- \ " | unlet! b:browsefilter"
-
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/postscr.vim b/runtime/ftplugin/postscr.vim
index 3bdd2e6ffa..b4c5e06324 100644
--- a/runtime/ftplugin/postscr.vim
+++ b/runtime/ftplugin/postscr.vim
@@ -1,7 +1,8 @@
" Vim filetype plugin file
" Language: PostScript
" Maintainer: Mike Williams <mrw@eandem.co.uk>
-" Last Change: 24th April 2012
+" Last Change: 24th April 2012
+" 2024 Jan 14 by Vim Project (browsefilter)
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -25,14 +26,18 @@ if !exists("b:match_words")
endif
" Define patterns for the browse file filter
-if has("gui_win32") && !exists("b:browsefilter")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "PostScript Files (*.ps)\t*.ps\n" .
- \ "EPS Files (*.eps)\t*.eps\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "EPS Files (*.eps)\t*.eps\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
let b:undo_ftplugin = "setlocal comments< formatoptions<"
- \ . "| unlet! b:browsefiler b:match_ignorecase b:match_words"
+ \ . "| unlet! b:browsefilter b:match_ignorecase b:match_words"
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/ps1.vim b/runtime/ftplugin/ps1.vim
index aac3bc9903..d6ab01016b 100644
--- a/runtime/ftplugin/ps1.vim
+++ b/runtime/ftplugin/ps1.vim
@@ -2,6 +2,7 @@
" Language: Windows PowerShell
" URL: https://github.com/PProvost/vim-ps1
" Last Change: 2021 Apr 02
+" 2024 Jan 14 by Vim Project (browsefilter)
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin") | finish | endif
@@ -19,14 +20,18 @@ setlocal formatoptions=tcqro
" e.g. Get-Content or Get-ADUser
setlocal iskeyword+=-
-" Change the browse dialog on Win32 to show mainly PowerShell-related files
-if has("gui_win32")
+" Change the browse dialog on Win32 and GTK to show mainly PowerShell-related files
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter =
\ "All PowerShell Files (*.ps1, *.psd1, *.psm1, *.ps1xml)\t*.ps1;*.psd1;*.psm1;*.ps1xml\n" .
\ "PowerShell Script Files (*.ps1)\t*.ps1\n" .
\ "PowerShell Module Files (*.psd1, *.psm1)\t*.psd1;*.psm1\n" .
- \ "PowerShell XML Files (*.ps1xml)\t*.ps1xml\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "PowerShell XML Files (*.ps1xml)\t*.ps1xml\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
" Look up keywords by Get-Help:
diff --git a/runtime/ftplugin/ps1xml.vim b/runtime/ftplugin/ps1xml.vim
index 837a3309b4..17bb181f37 100644
--- a/runtime/ftplugin/ps1xml.vim
+++ b/runtime/ftplugin/ps1xml.vim
@@ -2,6 +2,7 @@
" Language: Windows PowerShell
" URL: https://github.com/PProvost/vim-ps1
" Last Change: 2021 Apr 02
+" 2024 Jan 14 by Vim Project (browsefilter)
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin") | finish | endif
@@ -16,14 +17,18 @@ setlocal tw=0
setlocal commentstring=#%s
setlocal formatoptions=tcqro
-" Change the browse dialog on Win32 to show mainly PowerShell-related files
-if has("gui_win32")
+" Change the browse dialog on Win32 and GTK to show mainly PowerShell-related files
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter =
\ "All PowerShell Files (*.ps1, *.psd1, *.psm1, *.ps1xml)\t*.ps1;*.psd1;*.psm1;*.ps1xml\n" .
\ "PowerShell Script Files (*.ps1)\t*.ps1\n" .
\ "PowerShell Module Files (*.psd1, *.psm1)\t*.psd1;*.psm1\n" .
- \ "PowerShell XML Files (*.ps1xml)\t*.ps1xml\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "PowerShell XML Files (*.ps1xml)\t*.ps1xml\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
" Undo the stuff we changed
diff --git a/runtime/ftplugin/pyrex.vim b/runtime/ftplugin/pyrex.vim
index 251da39df4..ec254761ec 100644
--- a/runtime/ftplugin/pyrex.vim
+++ b/runtime/ftplugin/pyrex.vim
@@ -3,6 +3,7 @@
" Maintainer: Marco Barisione <marco.bari@people.it>
" URL: http://marcobari.altervista.org/pyrex_vim.html
" Last Change: 2012 May 18
+" 2024 Jan 14 by Vim Project (browsefilter)
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -14,13 +15,17 @@ set cpo&vim
" Behaves just like Python
runtime! ftplugin/python.vim ftplugin/python_*.vim ftplugin/python/*.vim
-if has("gui_win32") && exists("b:browsefilter")
- let b:browsefilter = "Pyrex files (*.pyx,*.pxd)\t*.pyx;*.pxd\n" .
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "Pyrex files (*.pyx, *.pxd)\t*.pyx;*.pxd\n" .
\ "Python Files (*.py)\t*.py\n" .
\ "C Source Files (*.c)\t*.c\n" .
\ "C Header Files (*.h)\t*.h\n" .
- \ "C++ Source Files (*.cpp *.c++)\t*.cpp;*.c++\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "C++ Source Files (*.cpp, *.c++)\t*.cpp;*.c++\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
let &cpo = s:keepcpo
diff --git a/runtime/ftplugin/python.vim b/runtime/ftplugin/python.vim
index 000ddf52a3..79acaa6f08 100644
--- a/runtime/ftplugin/python.vim
+++ b/runtime/ftplugin/python.vim
@@ -4,6 +4,7 @@
" Previous Maintainer: James Sully <sullyj3@gmail.com>
" Previous Maintainer: Johannes Zellner <johannes@zellner.org>
" Last Change: Mon, 5 October 2020
+" 2024 Jan 14 by Vim Project (browsefilter)
" https://github.com/tpict/vim-ftplugin-python
if exists("b:did_ftplugin") | finish | endif
@@ -110,8 +111,12 @@ if !exists('*<SID>Python_jump')
endif
if has("browsefilter") && !exists("b:browsefilter")
- let b:browsefilter = "Python Files (*.py)\t*.py\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Python Files (*.py)\t*.py\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
if !exists("g:python_recommended_style") || g:python_recommended_style != 0
diff --git a/runtime/ftplugin/qf.vim b/runtime/ftplugin/qf.vim
index a3dfce0e76..85fb9f6125 100644
--- a/runtime/ftplugin/qf.vim
+++ b/runtime/ftplugin/qf.vim
@@ -16,26 +16,3 @@ if !get(g:, 'qf_disable_statusline')
" Display the command that produced the list in the quickfix window:
setlocal stl=%t%{exists('w:quickfix_title')?\ '\ '.w:quickfix_title\ :\ ''}\ %=%-15(%l,%c%V%)\ %P
endif
-
-function! s:setup_toc() abort
- if get(w:, 'quickfix_title') !~# '\<TOC$' || &syntax != 'qf'
- return
- endif
-
- let list = getloclist(0)
- if empty(list)
- return
- endif
-
- let bufnr = list[0].bufnr
- setlocal modifiable
- silent %delete _
- call setline(1, map(list, 'v:val.text'))
- setlocal nomodifiable nomodified
- let &syntax = getbufvar(bufnr, '&syntax')
-endfunction
-
-augroup qf_toc
- autocmd!
- autocmd Syntax <buffer> call s:setup_toc()
-augroup END
diff --git a/runtime/ftplugin/qml.vim b/runtime/ftplugin/qml.vim
index fd5ddbb4bc..aa05c11bf9 100644
--- a/runtime/ftplugin/qml.vim
+++ b/runtime/ftplugin/qml.vim
@@ -2,6 +2,7 @@
" Language: QML
" Maintainer: Chase Knowlden <haroldknowlden@gmail.com>
" Last Change: 2023 Aug 16
+" 2023 Aug 23 by Vim Project (browsefilter)
if exists( 'b:did_ftplugin' )
finish
@@ -14,10 +15,15 @@ set cpoptions&vim
" command for undo
let b:undo_ftplugin = "setlocal formatoptions< comments< commentstring<"
-if (has("gui_win32") || has("gui_gtk")) && !exists( 'b:browsefilter' )
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter =
- \ 'QML Files (*.qml,*.qbs)\t*.qml;*.qbs\n' .
- \ 'All Files\t*\n'
+ \ "QML Files (*.qml, *.qbs)\t*.qml;*.qbs\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
+ let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
" Set 'comments' to format dashed lists in comments.
diff --git a/runtime/ftplugin/query.lua b/runtime/ftplugin/query.lua
index 964c221ad4..c75dc30430 100644
--- a/runtime/ftplugin/query.lua
+++ b/runtime/ftplugin/query.lua
@@ -1,5 +1,5 @@
-- Neovim filetype plugin file
--- Language: Tree-sitter query
+-- Language: Treesitter query
-- Last Change: 2023 Aug 23
if vim.b.did_ftplugin == 1 then
diff --git a/runtime/ftplugin/r.vim b/runtime/ftplugin/r.vim
index 28966368cb..6b07744c4a 100644
--- a/runtime/ftplugin/r.vim
+++ b/runtime/ftplugin/r.vim
@@ -1,8 +1,9 @@
" Vim filetype plugin file
-" Language: R
-" Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Sun Apr 24, 2022 09:14AM
+" Language: R
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2024 Feb 28 by Vim Project
" Only do this when not yet done for this buffer
if exists("b:did_ftplugin")
@@ -22,8 +23,12 @@ setlocal comments=:#',:###,:##,:#
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "R Source Files (*.R)\t*.R\n" .
- \ "Files that include R (*.Rnw *.Rd *.Rmd *.Rrst *.qmd)\t*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "Files that include R (*.Rnw, *.Rd, *.Rmd, *.Rrst, *.qmd)\t*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
let b:undo_ftplugin = "setl cms< com< fo< isk< | unlet! b:browsefilter"
diff --git a/runtime/ftplugin/racket.vim b/runtime/ftplugin/racket.vim
index 3aa413397e..84f5422140 100644
--- a/runtime/ftplugin/racket.vim
+++ b/runtime/ftplugin/racket.vim
@@ -4,6 +4,7 @@
" Previous Maintainer: Will Langstroth <will@langstroth.com>
" URL: https://github.com/benknoble/vim-racket
" Last Change: 2022 Aug 29
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin")
finish
@@ -68,8 +69,12 @@ endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter =
- \ "Racket Source Files (*.rkt *.rktl)\t*.rkt;*.rktl\n"
- \. "All Files (*.*)\t*.*\n"
+ \ "Racket Source Files (*.rkt, *.rktl)\t*.rkt;*.rktl\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/readline.vim b/runtime/ftplugin/readline.vim
index 181d8ac661..f5934ce2c0 100644
--- a/runtime/ftplugin/readline.vim
+++ b/runtime/ftplugin/readline.vim
@@ -2,7 +2,7 @@
" Language: readline(3) configuration file
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Last Change: 2022 Dec 09
+" Last Change: 2023 Aug 22
if exists("b:did_ftplugin")
finish
@@ -25,8 +25,12 @@ if exists("loaded_matchit") && !exists("b:match_words")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Readline Initialization Files (inputrc .inputrc)\tinputrc;*.inputrc\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Readline Intialization Files (inputrc, .inputrc)\tinputrc;*.inputrc\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/registry.vim b/runtime/ftplugin/registry.vim
index 385785ac60..bb851c5491 100644
--- a/runtime/ftplugin/registry.vim
+++ b/runtime/ftplugin/registry.vim
@@ -2,6 +2,7 @@
" Language: Windows Registry export with regedit (*.reg)
" Maintainer: Cade Forester <ahx2323@gmail.com>
" Latest Revision: 2014-01-09
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin")
finish
@@ -12,18 +13,22 @@ let s:cpo_save = &cpo
set cpo&vim
let b:undo_ftplugin =
- \ 'let b:browsefilter = "" | ' .
\ 'setlocal ' .
\ 'comments< '.
\ 'commentstring< ' .
- \ 'formatoptions< '
+ \ 'formatoptions<'
-if has( 'gui_win32' )
+if ( has( 'gui_win32' ) || has( 'gui_gtk' ) )
\ && !exists( 'b:browsefilter' )
let b:browsefilter =
- \ 'registry files (*.reg)\t*.reg\n' .
- \ 'All files (*.*)\t*.*\n'
+ \ "registry files (*.reg)\t*.reg\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
+ let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
setlocal comments=:;
diff --git a/runtime/ftplugin/rhelp.vim b/runtime/ftplugin/rhelp.vim
index 2fde4875c6..0fa1e56573 100644
--- a/runtime/ftplugin/rhelp.vim
+++ b/runtime/ftplugin/rhelp.vim
@@ -1,8 +1,9 @@
" Vim filetype plugin file
-" Language: R help file
-" Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Sun Apr 24, 2022 09:12AM
+" Language: R help file
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2024 Feb 28 by Vim Project
" Only do this when not yet done for this buffer
if exists("b:did_ftplugin")
@@ -18,8 +19,12 @@ set cpo&vim
setlocal iskeyword=@,48-57,_,.
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "R Source Files (*.R, *.Rnw, *.Rd, *.Rmd, *.Rrst, *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
let b:undo_ftplugin = "setl isk< | unlet! b:browsefilter"
diff --git a/runtime/ftplugin/rmd.vim b/runtime/ftplugin/rmd.vim
index a407c236dd..a537017aad 100644
--- a/runtime/ftplugin/rmd.vim
+++ b/runtime/ftplugin/rmd.vim
@@ -1,8 +1,9 @@
" Vim filetype plugin file
-" Language: R Markdown file
-" Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Mon May 29, 2023 06:31AM
+" Language: R Markdown file
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2024 Feb 28 by Vim Project
" Original work by Alex Zvoleff (adjusted from R help for rmd by Michel Kuhlmann)
" Only do this when not yet done for this buffer
@@ -64,8 +65,12 @@ runtime ftplugin/pandoc.vim
let b:did_ftplugin = 1
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "R Source Files (*.R, *.Rnw, *.Rd, *.Rmd, *.Rrst, *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
if exists('b:undo_ftplugin')
diff --git a/runtime/ftplugin/rnoweb.vim b/runtime/ftplugin/rnoweb.vim
index 26c1ab4e3f..8dfdf1e80f 100644
--- a/runtime/ftplugin/rnoweb.vim
+++ b/runtime/ftplugin/rnoweb.vim
@@ -1,8 +1,9 @@
" Vim filetype plugin file
-" Language: Rnoweb
-" Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Mon Feb 27, 2023 07:16PM
+" Language: Rnoweb
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2024 Feb 28 by Vim Project
" Only do this when not yet done for this buffer
if exists("b:did_ftplugin")
@@ -25,8 +26,12 @@ setlocal suffixesadd=.bib,.tex
setlocal comments=b:%,b:#,b:##,b:###,b:#'
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "R Source Files (*.R, *.Rnw, *.Rd, *.Rmd, *.Rrst, *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
function SetRnwCommentStr()
diff --git a/runtime/ftplugin/routeros.vim b/runtime/ftplugin/routeros.vim
index c6e4799aa2..9cd0b10344 100644
--- a/runtime/ftplugin/routeros.vim
+++ b/runtime/ftplugin/routeros.vim
@@ -2,6 +2,7 @@
" Language: MikroTik RouterOS Script
" Maintainer: zainin <z@wintr.dev>
" Last Change: 2021 Nov 14
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin")
finish
@@ -18,8 +19,12 @@ setlocal formatoptions-=t formatoptions+=croql
let b:undo_ftplugin = "setlocal com< cms< fo<"
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "RouterOS Script Files (*.rsc)\t*.rsc\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "RouterOS Script Files (*.rsc)\t*.rsc\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/rrst.vim b/runtime/ftplugin/rrst.vim
index d9df5e587f..d088f98224 100644
--- a/runtime/ftplugin/rrst.vim
+++ b/runtime/ftplugin/rrst.vim
@@ -1,8 +1,9 @@
" Vim filetype plugin file
-" Language: reStructuredText documentation format with R code
-" Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Mon Feb 27, 2023 07:16PM
+" Language: reStructuredText documentation format with R code
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2024 Feb 28 by Vim Project
" Original work by Alex Zvoleff
" Only do this when not yet done for this buffer
@@ -38,8 +39,12 @@ if !exists("g:rrst_dynamic_comments") || (exists("g:rrst_dynamic_comments") && g
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "R Source Files (*.R *.Rnw *.Rd *.Rmd *.Rrst *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "R Source Files (*.R, *.Rnw, *.Rd, *.Rmd, *.Rrst, *.qmd)\t*.R;*.Rnw;*.Rd;*.Rmd;*.Rrst;*.qmd\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
if exists('b:undo_ftplugin')
diff --git a/runtime/ftplugin/ruby.vim b/runtime/ftplugin/ruby.vim
index b61c1765d9..ab0a32576c 100644
--- a/runtime/ftplugin/ruby.vim
+++ b/runtime/ftplugin/ruby.vim
@@ -2,8 +2,8 @@
" Language: Ruby
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
" URL: https://github.com/vim-ruby/vim-ruby
-" Release Coordinator: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2023 Sep 1st
+" Last Change: 2023 Dec 31
+" 2024 Jan 14 by Vim Project (browsefilter)
if (exists("b:did_ftplugin"))
finish
@@ -60,35 +60,38 @@ if !exists('g:ruby_version_paths')
let g:ruby_version_paths = {}
endif
+let s:path_split = has('win32') ? ';' : ':'
+
function! s:query_path(root) abort
- " Disabled by default for security reasons.
- if !get(g:, 'ruby_exec', get(g:, 'plugin_exec', 0))
- return []
+ " Disabled by default for security reasons.
+ if !get(g:, 'ruby_exec', get(g:, 'plugin_exec', 0)) || empty(a:root)
+ return map(split($RUBYLIB, s:path_split), 'v:val ==# "." ? "" : v:val')
endif
let code = "print $:.join %q{,}"
- if &shell =~# 'sh' && empty(&shellxquote)
- let prefix = 'env PATH='.shellescape($PATH).' '
- else
- let prefix = ''
- endif
if &shellxquote == "'"
- let path_check = prefix.'ruby --disable-gems -e "' . code . '"'
+ let args = ' --disable-gems -e "' . code . '"'
else
- let path_check = prefix."ruby --disable-gems -e '" . code . "'"
+ let args = " --disable-gems -e '" . code . "'"
endif
- let cd = haslocaldir() ? 'lcd' : 'cd'
+ let cd = haslocaldir() ? 'lcd' : exists(':tcd') && haslocaldir(-1) ? 'tcd' : 'cd'
let cwd = fnameescape(getcwd())
try
exe cd fnameescape(a:root)
- let s:tmp_cwd = getcwd()
- if (fnamemodify(exepath('ruby'), ':p:h') ==# cwd
- \ && (index(split($PATH,has("win32")? ';' : ':'), s:tmp_cwd) == -1 || s:tmp_cwd == '.'))
- let path = []
+ for dir in split($PATH, s:path_split)
+ if dir !=# '.' && executable(dir . '/ruby') == 1
+ let exepath = dir . '/ruby'
+ break
+ endif
+ endfor
+ if exists('l:exepath')
+ let path = split(system(exepath . args),',')
+ if v:shell_error
+ let path = []
+ endif
else
- let path = split(system(path_check),',')
+ let path = []
endif
- unlet! s:tmp_cwd
exe cd cwd
return path
finally
@@ -129,10 +132,8 @@ else
if !exists('g:ruby_default_path')
if has("ruby") && has("win32")
ruby ::VIM::command( 'let g:ruby_default_path = split("%s",",")' % $:.join(%q{,}) )
- elseif executable('ruby') && !empty($HOME)
- let g:ruby_default_path = s:query_path($HOME)
else
- let g:ruby_default_path = map(split($RUBYLIB,':'), 'v:val ==# "." ? "" : v:val')
+ let g:ruby_default_path = s:query_path($HOME)
endif
endif
let s:ruby_paths = g:ruby_default_path
@@ -147,8 +148,12 @@ if exists('s:ruby_paths') && stridx(&l:tags, join(map(copy(s:ruby_paths),'v:val.
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Ruby Source Files (*.rb)\t*.rb\n" .
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Ruby Source Files (*.rb)\t*.rb\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
let b:undo_ftplugin = "setl inc= sua= path= tags= fo< com< cms< kp="
diff --git a/runtime/ftplugin/sass.vim b/runtime/ftplugin/sass.vim
index 9ce446137a..e650be9312 100644
--- a/runtime/ftplugin/sass.vim
+++ b/runtime/ftplugin/sass.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin
" Language: Sass
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
-" Last Change: 2019 Dec 05
+" Last Change: 2023 Dec 28
" Only do this when not done yet for this buffer
if exists("b:did_ftplugin")
@@ -23,6 +23,11 @@ if &filetype =~# '\<s[ac]ss]\>'
let b:undo_ftplugin .= ' isk<'
endif
+if get(g:, 'sass_recommended_style', 1)
+ setlocal shiftwidth=2 softtabstop=2 expandtab
+ let b:undo_ftplugin .= ' sw< sts< et<'
+endif
+
let &l:define = '^\C\v\s*%(\@function|\@mixin|\=)|^\s*%(\$[[:alnum:]-]+:|[%.][:alnum:]-]+\s*%(\{|$))@='
let &l:include = '^\s*@import\s\+\%(url(\)\=["'']\='
diff --git a/runtime/ftplugin/sbt.vim b/runtime/ftplugin/sbt.vim
index 309d30e503..bf2c7a657a 100644
--- a/runtime/ftplugin/sbt.vim
+++ b/runtime/ftplugin/sbt.vim
@@ -9,7 +9,6 @@ if exists('b:did_ftplugin') || &cp
finish
endif
-let b:did_ftplugin = 1
-
runtime! ftplugin/scala.vim
+let b:did_ftplugin = 1
diff --git a/runtime/ftplugin/sed.vim b/runtime/ftplugin/sed.vim
index 0073872877..acd089089a 100644
--- a/runtime/ftplugin/sed.vim
+++ b/runtime/ftplugin/sed.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: sed
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2020 Apr 1
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -18,8 +18,12 @@ setlocal formatoptions-=t formatoptions+=croql
let b:undo_ftplugin = "setl com< cms< fo<"
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "sed Script Files (*.sed)\t*.sed\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "sed Script Files (*.sed)\t*.sed\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/sgml.vim b/runtime/ftplugin/sgml.vim
index ef52125c68..b6dbf1a0d1 100644
--- a/runtime/ftplugin/sgml.vim
+++ b/runtime/ftplugin/sgml.vim
@@ -1,10 +1,11 @@
" Vim filetype plugin file
-" Language: sgml
+" Language: sgml
"
" This runtime file is looking for a new maintainer.
"
" Former maintainer: Dan Sharp
-" Last Changed: 20 Jan 2009
+" Last Change: 2009 Jan 20
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
@@ -15,8 +16,12 @@ set cpo-=C
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
-let s:browsefilter = "XML Files (*.xml)\t*.xml\n" .
- \ "All Files (*.*)\t*.*\n"
+let s:browsefilter = "XML Files (*.xml)\t*.xml\n"
+if has("win32")
+ let s:browsefilter .= "All Files (*.*)\t*\n"
+else
+ let s:browsefilter .= "All Files (*)\t*\n"
+endif
runtime! ftplugin/xml.vim ftplugin/xml_*.vim ftplugin/xml/*.vim
let b:did_ftplugin = 1
@@ -30,7 +35,7 @@ if exists("b:browsefilter")
endif
" Change the :browse e filter to primarily show xml-related files.
-if has("gui_win32")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="SGML Files (*.sgml,*.sgm)\t*.sgm*\n" . s:browsefilter
endif
diff --git a/runtime/ftplugin/sh.vim b/runtime/ftplugin/sh.vim
index c1a6bc5ade..6d2093bf83 100644
--- a/runtime/ftplugin/sh.vim
+++ b/runtime/ftplugin/sh.vim
@@ -4,7 +4,7 @@
" Previous Maintainer: Dan Sharp
" Contributor: Enno Nagel <ennonagel+vim@gmail.com>
" Eisuke Kawashima
-" Last Change: 2023 Sep 28
+" Last Change: 2024 Feb 27
if exists("b:did_ftplugin")
finish
@@ -14,7 +14,7 @@ let b:did_ftplugin = 1
let s:save_cpo = &cpo
set cpo-=C
-setlocal comments=:#
+setlocal comments=b:#
setlocal commentstring=#\ %s
setlocal formatoptions-=t formatoptions+=croql
@@ -33,10 +33,14 @@ if exists("loaded_matchit") && !exists("b:match_words")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Bourne Shell Scripts (*.sh)\t*.sh\n" ..
- \ "Korn Shell Scripts (*.ksh)\t*.ksh\n" ..
- \ "Bash Shell Scripts (*.bash)\t*.bash\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Bourne Shell Scripts (*.sh)\t*.sh\n" ..
+ \ "Korn Shell Scripts (*.ksh)\t*.ksh\n" ..
+ \ "Bash Shell Scripts (*.bash)\t*.bash\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/solution.vim b/runtime/ftplugin/solution.vim
index bd30c7bb19..19ec392ec5 100644
--- a/runtime/ftplugin/solution.vim
+++ b/runtime/ftplugin/solution.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Microsoft Visual Studio Solution
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2021 Dec 15
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -26,8 +26,12 @@ if exists("loaded_matchit") && !exists("b:match_words")
endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Microsoft Visual Studio Solution Files\t*.sln\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Microsoft Visual Studio Solution Files(*.sln)\t*.sln\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/sql.vim b/runtime/ftplugin/sql.vim
index 7a29d39f8e..c85232f51b 100644
--- a/runtime/ftplugin/sql.vim
+++ b/runtime/ftplugin/sql.vim
@@ -3,6 +3,7 @@
" Version: 12.0
" Maintainer: David Fishburn <dfishburn dot vim at gmail dot com>
" Last Change: 2017 Mar 07
+" 2024 Jan 14 by Vim Project (browsefilter)
" Download: http://vim.sourceforge.net/script.php?script_id=454
" For more details please use:
@@ -272,10 +273,14 @@ let b:undo_ftplugin = "setl comments< formatoptions< define< omnifunc<" .
let b:did_ftplugin = 1
let b:current_ftplugin = 'sql'
-" Win32 can filter files in the browse dialog
-if has("gui_win32") && !exists("b:browsefilter")
- let b:browsefilter = "SQL Files (*.sql)\t*.sql\n" .
- \ "All Files (*.*)\t*.*\n"
+" Win32 and GTK can filter files in the browse dialog
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "SQL Files (*.sql)\t*.sql\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
" Some standard expressions for use with the matchit strings
diff --git a/runtime/ftplugin/svg.vim b/runtime/ftplugin/svg.vim
index 6f16b1a0f4..4ee9e4b77b 100644
--- a/runtime/ftplugin/svg.vim
+++ b/runtime/ftplugin/svg.vim
@@ -1,10 +1,11 @@
" Vim filetype plugin file
-" Language: svg
+" Language: svg
"
" This runtime file is looking for a new maintainer.
"
" Former maintainer: Dan Sharp
-" Last Changed: 20 Jan 2009
+" Last Change: 2009 Jan 20
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
@@ -15,8 +16,12 @@ set cpo-=C
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
-let s:browsefilter = "XML Files (*.xml)\t*.xml\n" .
- \ "All Files (*.*)\t*.*\n"
+let s:browsefilter = "XML Files (*.xml)\t*.xml\n"
+if has("win32")
+ let s:browsefilter .= "All Files (*.*)\t*\n"
+else
+ let s:browsefilter .= "All Files (*)\t*\n"
+endif
runtime! ftplugin/xml.vim ftplugin/xml_*.vim ftplugin/xml/*.vim
let b:did_ftplugin = 1
@@ -30,7 +35,7 @@ if exists("b:browsefilter")
endif
" Change the :browse e filter to primarily show xml-related files.
-if has("gui_win32")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="SVG Files (*.svg)\t*.svg\n" . s:browsefilter
endif
diff --git a/runtime/ftplugin/tcl.vim b/runtime/ftplugin/tcl.vim
index 1cc24d341e..fa900096c0 100644
--- a/runtime/ftplugin/tcl.vim
+++ b/runtime/ftplugin/tcl.vim
@@ -2,6 +2,7 @@
" Language: Tcl
" Maintainer: Robert L Hicks <sigzero@gmail.com>
" Latest Revision: 2009-05-01
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin")
finish
@@ -18,10 +19,14 @@ setlocal commentstring=#%s
setlocal formatoptions+=croql
" Change the browse dialog on Windows to show mainly Tcl-related files
-if has("gui_win32")
- let b:browsefilter = "Tcl Source Files (.tcl)\t*.tcl\n" .
- \ "Tcl Test Files (.test)\t*.test\n" .
- \ "All Files (*.*)\t*.*\n"
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "Tcl Source Files (*.tcl)\t*.tcl\n" .
+ \ "Tcl Test Files (*.test)\t*.test\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
"-----------------------------------------------------------------------------
diff --git a/runtime/ftplugin/tcsh.vim b/runtime/ftplugin/tcsh.vim
index b2467b43a2..74095aabe2 100644
--- a/runtime/ftplugin/tcsh.vim
+++ b/runtime/ftplugin/tcsh.vim
@@ -2,7 +2,7 @@
" Language: tcsh
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer: Dan Sharp
-" Last Change: 2023 Oct 09
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -13,8 +13,12 @@ set cpo-=C
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
-let s:browsefilter = "csh Files (*.csh)\t*.csh\n" ..
- \ "All Files (*.*)\t*.*\n"
+let s:browsefilter = "csh Files (*.csh)\t*.csh\n"
+if has("win32")
+ let s:browsefilter ..= "All Files (*.*)\t*\n"
+else
+ let s:browsefilter ..= "All Files (*)\t*\n"
+endif
runtime! ftplugin/csh.vim ftplugin/csh_*.vim ftplugin/csh/*.vim
let b:did_ftplugin = 1
diff --git a/runtime/ftplugin/tidy.vim b/runtime/ftplugin/tidy.vim
index b81b66db4a..9a613799af 100644
--- a/runtime/ftplugin/tidy.vim
+++ b/runtime/ftplugin/tidy.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: HTML Tidy Configuration
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2020 Sep 4
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -15,17 +15,21 @@ setlocal comments=:#,://
setlocal commentstring=#\ %s
setlocal formatoptions-=t formatoptions+=croql
+let b:undo_ftplugin = "setl fo< com< cms<"
+
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "HTML Tidy Files (tidyrc, .tidyrc, tidy.conf)\ttidyrc;.tidyrc;tidy.conf\n" .
\ "HTML Files (*.html, *.htm)\t*.html;*.htm\n" .
\ "XHTML Files (*.xhtml, *.xhtm)\t*.xhtml;*.xhtm\n" .
- \ "XML Files (*.xml)\t*.xml\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "XML Files (*.xml)\t*.xml\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
+ let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
-let b:undo_ftplugin = "setl fo< com< cms<" .
- \ " | unlet! b:browsefilter"
-
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/typescript.vim b/runtime/ftplugin/typescript.vim
index f701ae96cd..680521df31 100644
--- a/runtime/ftplugin/typescript.vim
+++ b/runtime/ftplugin/typescript.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: TypeScript
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2019 Aug 30
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -22,6 +22,8 @@ setlocal commentstring=//%s
setlocal suffixesadd+=.ts,.d.ts,.tsx,.js,.jsx,.cjs,.mjs
+let b:undo_ftplugin = "setl fo< com< cms< sua<"
+
" Change the :browse e filter to primarily show TypeScript-related files.
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="TypeScript Files (*.ts)\t*.ts\n" .
@@ -29,11 +31,14 @@ if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
\ "TSX Files (*.tsx)\t*.tsx\n" .
\ "JavaScript Files (*.js)\t*.js\n" .
\ "JavaScript Modules (*.es, *.cjs, *.mjs)\t*.es;*.cjs;*.mjs\n" .
- \ "JSON Files (*.json)\t*.json\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "JSON Files (*.json)\t*.json\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
+ let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
-let b:undo_ftplugin = "setl fo< com< cms< sua< | unlet! b:browsefilter"
-
let &cpo = s:cpo_save
unlet s:cpo_save
diff --git a/runtime/ftplugin/vb.vim b/runtime/ftplugin/vb.vim
index 5a9548115b..94a2f35ff3 100644
--- a/runtime/ftplugin/vb.vim
+++ b/runtime/ftplugin/vb.vim
@@ -2,7 +2,7 @@
" Language: Visual Basic (ft=vb)
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainer: Johannes Zellner <johannes@zellner.org>
-" Last Change: 2021 Nov 17
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -62,8 +62,12 @@ endif
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter = "Visual Basic Source Files (*.bas)\t*.bas\n" .
- \ "Visual Basic Form Files (*.frm)\t*.frm\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "Visual Basic Form Files (*.frm)\t*.frm\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin .= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/verilog.vim b/runtime/ftplugin/verilog.vim
index cbf30a3185..83c3754e05 100644
--- a/runtime/ftplugin/verilog.vim
+++ b/runtime/ftplugin/verilog.vim
@@ -2,6 +2,7 @@
" Language: Verilog HDL
" Maintainer: Chih-Tsun Huang <cthuang@cs.nthu.edu.tw>
" Last Change: 2017 Aug 25 by Chih-Tsun Huang
+" 2024 Jan 14 by Vim Project (browsefilter)
" URL: http://www.cs.nthu.edu.tw/~cthuang/vim/ftplugin/verilog.vim
"
" Credits:
@@ -36,10 +37,14 @@ if &textwidth == 0
setlocal tw=78
endif
-" Win32 can filter files in the browse dialog
-if has("gui_win32") && !exists("b:browsefilter")
- let b:browsefilter = "Verilog Source Files (*.v)\t*.v\n" .
- \ "All Files (*.*)\t*.*\n"
+" Win32 and GTK can filter files in the browse dialog
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+ let b:browsefilter = "Verilog Source Files (*.v)\t*.v\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
" Let the matchit plugin know what items can be matched.
diff --git a/runtime/ftplugin/vhdl.vim b/runtime/ftplugin/vhdl.vim
index ff56166ebe..3850c70d50 100644
--- a/runtime/ftplugin/vhdl.vim
+++ b/runtime/ftplugin/vhdl.vim
@@ -3,6 +3,7 @@
" Maintainer: R.Shankar <shankar.pec?gmail.com>
" Modified By: Gerald Lai <laigera+vim?gmail.com>
" Last Change: 2011 Dec 11
+" 2024 Jan 14 by Vim Project (browsefilter)
" 2023 Aug 28 by Vim Project (undo_ftplugin, commentstring)
" Only do this when not done yet for this buffer
@@ -28,14 +29,15 @@ setlocal commentstring=--\ %s
" Format comments to be up to 78 characters long
"setlocal tw=75
-" let b:undo_ftplugin = "setl cms< com< fo< tw<"
-
let b:undo_ftplugin = "setl cms< "
-" Win32 can filter files in the browse dialog
-"if has("gui_win32") && !exists("b:browsefilter")
-" let b:browsefilter = "Verilog Source Files (*.v)\t*.v\n" .
-" \ "All Files (*.*)\t*.*\n"
+" Win32 and GTK can filter files in the browse dialog
+"if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
+" if has("win32")
+" let b:browsefilter ..= "All Files (*.*)\t*\n"
+" else
+" let b:browsefilter ..= "All Files (*)\t*\n"
+" endif
" let b:undo_ftplugin .= " | unlet! b:browsefilter"
"endif
diff --git a/runtime/ftplugin/vim.vim b/runtime/ftplugin/vim.vim
index 06369e8a82..f5dae0f94e 100644
--- a/runtime/ftplugin/vim.vim
+++ b/runtime/ftplugin/vim.vim
@@ -49,18 +49,17 @@ setlocal isk+=#
" Use :help to lookup the keyword under the cursor with K.
setlocal keywordprg=:help
-" if "\n" .. getline(1, 10)->join("\n") =~# '\n\s*vim9\%[script]\>'
-if "\n" .. join(getline(1, 10), "\n") =~# '\n\s*vim9\%[script]\>'
- " Set 'comments' to format dashed lists in comments
- setlocal com=sO:#\ -,mO:#\ \ ,eO:##,:#
- " Comments starts with # in Vim9 script
+" Comments starts with # in Vim9 script. We have to guess which one to use.
+if "\n" .. getline(1, 10)->join("\n") =~# '\n\s*vim9\%[script]\>'
setlocal commentstring=#%s
else
- setlocal com=sO:\"\ -,mO:\"\ \ ,eO:\"\",:\"
- " Comments starts with a double quote in legacy script
setlocal commentstring=\"%s
endif
+" Set 'comments' to format dashed lists in comments, both in Vim9 and legacy
+" script.
+setlocal com=sO:#\ -,mO:#\ \ ,eO:##,:#\\\ ,:#,sO:\"\ -,mO:\"\ \ ,eO:\"\",:\"\\\ ,:\"
+
" Format comments to be up to 78 characters long
if &tw == 0
diff --git a/runtime/ftplugin/wget.vim b/runtime/ftplugin/wget.vim
index db3b62191e..c7fdec292e 100644
--- a/runtime/ftplugin/wget.vim
+++ b/runtime/ftplugin/wget.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Wget configuration file (/etc/wgetrc ~/.wgetrc)
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2022 Apr 28
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -18,8 +18,12 @@ setlocal formatoptions-=t formatoptions+=croql
let b:undo_ftplugin = "setl fo< com< cms<"
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Wget Configuration File (wgetrc, .wgetrc)\twgetrc;.wgetrc\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Wget Configuration File (wgetrc, .wgetrc)\twgetrc;.wgetrc\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/wget2.vim b/runtime/ftplugin/wget2.vim
index 8cfcd514e5..40da5c502a 100644
--- a/runtime/ftplugin/wget2.vim
+++ b/runtime/ftplugin/wget2.vim
@@ -1,7 +1,7 @@
" Vim filetype plugin file
" Language: Wget2 configuration file (/etc/wget2rc ~/.wget2rc)
" Maintainer: Doug Kearns <dougkearns@gmail.com>
-" Last Change: 2022 Apr 28
+" Last Change: 2024 Jan 14
if exists("b:did_ftplugin")
finish
@@ -18,8 +18,12 @@ setlocal formatoptions-=t formatoptions+=croql
let b:undo_ftplugin = "setl fo< com< cms<"
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
- let b:browsefilter = "Wget2 Configuration File (wget2rc, .wget2rc)\twget2rc;.wget2rc\n" ..
- \ "All Files (*.*)\t*.*\n"
+ let b:browsefilter = "Wget2 Configuration File (wget2rc, .wget2rc)\twget2rc;.wget2rc\n"
+ if has("win32")
+ let b:browsefilter ..= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter ..= "All Files (*)\t*\n"
+ endif
let b:undo_ftplugin ..= " | unlet! b:browsefilter"
endif
diff --git a/runtime/ftplugin/xhtml.vim b/runtime/ftplugin/xhtml.vim
index d2a1c0b566..8a45ba76b1 100644
--- a/runtime/ftplugin/xhtml.vim
+++ b/runtime/ftplugin/xhtml.vim
@@ -1,10 +1,11 @@
" Vim filetype plugin file
-" Language: xhtml
+" Language: xhtml
"
" This runtime file is looking for a new maintainer.
"
" Former maintainer: Dan Sharp
-" Last Changed: 20 Jan 2009
+" Last Changed: 2009 Jan 20
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
@@ -16,8 +17,12 @@ set cpo-=C
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
let s:browsefilter = "HTML Files (*.html, *.htm)\t*.html;*.htm\n" .
- \ "XML Files (*.xml)\t*.xml\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "XML Files (*.xml)\t*.xml\n"
+if has("win32")
+ let s:browsefilter .= "All Files (*.*)\t*\n"
+else
+ let s:browsefilter .= "All Files (*)\t*\n"
+endif
let s:match_words = ""
runtime! ftplugin/xml.vim ftplugin/xml_*.vim ftplugin/xml/*.vim
@@ -57,7 +62,7 @@ if exists("loaded_matchit")
endif
" Change the :browse e filter to primarily show tcsh-related files.
-if has("gui_win32")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="XHTML files (*.xhtml, *.xhtm)\t*.xhtml;*.xhtm\n" . s:browsefilter
endif
diff --git a/runtime/ftplugin/xml.vim b/runtime/ftplugin/xml.vim
index 9aa188cecc..b81c3980d2 100644
--- a/runtime/ftplugin/xml.vim
+++ b/runtime/ftplugin/xml.vim
@@ -2,6 +2,7 @@
" Language: xml
" Maintainer: Christian Brabandt <cb@256bit.org>
" Last Changed: Dec 07th, 2018
+" 2024 Jan 14 by Vim Project (browsefilter)
" Repository: https://github.com/chrisbra/vim-xml-ftplugin
" Previous Maintainer: Dan Sharp
" URL: http://dwsharp.users.sourceforge.net/vim/ftplugin
@@ -52,8 +53,12 @@ command! -nargs=? XMLent call xmlcomplete#CreateEntConnection(<f-args>)
if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="XML Files (*.xml)\t*.xml\n" .
\ "DTD Files (*.dtd)\t*.dtd\n" .
- \ "XSD Files (*.xsd)\t*.xsd\n" .
- \ "All Files (*.*)\t*.*\n"
+ \ "XSD Files (*.xsd)\t*.xsd\n"
+ if has("win32")
+ let b:browsefilter .= "All Files (*.*)\t*\n"
+ else
+ let b:browsefilter .= "All Files (*)\t*\n"
+ endif
endif
" Undo the stuff we changed.
diff --git a/runtime/ftplugin/xsd.vim b/runtime/ftplugin/xsd.vim
index 7d3efbb390..aaec8a0f7d 100644
--- a/runtime/ftplugin/xsd.vim
+++ b/runtime/ftplugin/xsd.vim
@@ -1,10 +1,11 @@
" Vim filetype plugin file
-" Language: xsd
+" Language: xsd
"
" This runtime file is looking for a new maintainer.
"
" Former maintainer: Dan Sharp
-" Last Changed: 20 Jan 2009
+" Last Changed: 2009 Jan 20
+" 2024 Jan 14 by Vim Project (browsefilter)
if exists("b:did_ftplugin") | finish | endif
@@ -15,8 +16,12 @@ set cpo-=C
" Define some defaults in case the included ftplugins don't set them.
let s:undo_ftplugin = ""
-let s:browsefilter = "XML Files (*.xml)\t*.xml\n" .
- \ "All Files (*.*)\t*.*\n"
+let s:browsefilter = "XML Files (*.xml)\t*.xml\n"
+if has("win32")
+ let s:browsefilter .= "All Files (*.*)\t*\n"
+else
+ let s:browsefilter .= "All Files (*)\t*\n"
+endif
runtime! ftplugin/xml.vim ftplugin/xml_*.vim ftplugin/xml/*.vim
let b:did_ftplugin = 1
@@ -30,7 +35,7 @@ if exists("b:browsefilter")
endif
" Change the :browse e filter to primarily show xsd-related files.
-if has("gui_win32")
+if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter")
let b:browsefilter="XSD Files (*.xsd)\t*.xsd\n" . s:browsefilter
endif
diff --git a/runtime/ftplugin/xslt.vim b/runtime/ftplugin/xslt.vim
index 47e78eb81d..70986c9e48 100644
--- a/runtime/ftplugin/xslt.vim
+++ b/runtime/ftplugin/xslt.vim
@@ -14,5 +14,5 @@ let b:did_ftplugin = 1
" Change the :browse e filter to primarily show xsd-related files.
if (has("gui_win32") || has("gui_gtk")) && exists("b:browsefilter")
- let b:browsefilter = "XSLT Files (*.xsl,*.xslt)\t*.xsl;*.xslt\n" . b:browsefilter
+ let b:browsefilter = "XSLT Files (*.xsl, *.xslt)\t*.xsl;*.xslt\n" . b:browsefilter
endif
diff --git a/runtime/indent/cmake.vim b/runtime/indent/cmake.vim
index af27c0d49b..c1aa3bff86 100644
--- a/runtime/indent/cmake.vim
+++ b/runtime/indent/cmake.vim
@@ -3,9 +3,9 @@
" Author: Andy Cedilnik <andy.cedilnik@kitware.com>
" Maintainer: Dimitri Merejkowsky <d.merej@gmail.com>
" Former Maintainer: Karthik Krishnan <karthik.krishnan@kitware.com>
-" Last Change: 2022 Apr 06
+" Last Change: 2023 Dec 12
"
-" Licence: The CMake license applies to this file. See
+" License: The CMake license applies to this file. See
" https://cmake.org/licensing
" This implies that distribution with Vim is allowed
@@ -55,32 +55,41 @@ fun! CMakeGetIndent(lnum)
let cmake_indent_open_regex = '^\s*' . cmake_regex_identifier .
\ '\s*(' . cmake_regex_arguments .
\ '\(' . cmake_regex_comment . '\)\?$'
-
let cmake_indent_close_regex = '^' . cmake_regex_arguments .
\ ')\s*' .
\ '\(' . cmake_regex_comment . '\)\?$'
- let cmake_indent_begin_regex = '^\s*\(IF\|MACRO\|FOREACH\|ELSE\|ELSEIF\|WHILE\|FUNCTION\)\s*('
- let cmake_indent_end_regex = '^\s*\(ENDIF\|ENDFOREACH\|ENDMACRO\|ELSE\|ELSEIF\|ENDWHILE\|ENDFUNCTION\)\s*('
+ let cmake_closing_parens_line = '^\s*\()\+\)\s*$'
- " Add
- if previous_line =~? cmake_indent_comment_line " Handle comments
- let ind = ind
- else
- if previous_line =~? cmake_indent_begin_regex
- let ind = ind + shiftwidth()
+ let cmake_indent_begin_regex = '^\s*\(BLOCK\|IF\|MACRO\|FOREACH\|ELSE\|ELSEIF\|WHILE\|FUNCTION\)\s*('
+ let cmake_indent_end_regex = '^\s*\(ENDBLOCK\|ENDIF\|ENDFOREACH\|ENDMACRO\|ELSE\|ELSEIF\|ENDWHILE\|ENDFUNCTION\)\s*('
+
+ if this_line =~? cmake_closing_parens_line
+ if previous_line !~? cmake_indent_open_regex
+ let ind = ind - shiftwidth()
endif
- if previous_line =~? cmake_indent_open_regex
- let ind = ind + shiftwidth()
+ else
+ " Add
+ if previous_line =~? cmake_indent_comment_line " Handle comments
+ let ind = ind
+ else
+ if previous_line =~? cmake_indent_begin_regex
+ let ind = ind + shiftwidth()
+ endif
+ if previous_line =~? cmake_indent_open_regex
+ let ind = ind + shiftwidth()
+ endif
endif
- endif
- " Subtract
- if this_line =~? cmake_indent_end_regex
- let ind = ind - shiftwidth()
- endif
- if previous_line =~? cmake_indent_close_regex
- let ind = ind - shiftwidth()
+ " Subtract
+ if this_line =~? cmake_indent_end_regex
+ let ind = ind - shiftwidth()
+ endif
+ if previous_line !~? cmake_closing_parens_line
+ if previous_line =~? cmake_indent_close_regex
+ let ind = ind - shiftwidth()
+ endif
+ endif
endif
return ind
diff --git a/runtime/indent/cucumber.vim b/runtime/indent/cucumber.vim
index ad28a67a0d..5d144e426b 100644
--- a/runtime/indent/cucumber.vim
+++ b/runtime/indent/cucumber.vim
@@ -1,7 +1,7 @@
" Vim indent file
" Language: Cucumber
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
-" Last Change: 2017 Jun 13
+" Last Change: 2023 Dec 28
if exists("b:did_indent")
finish
@@ -19,57 +19,80 @@ if exists("*GetCucumberIndent")
finish
endif
-function! s:syn(lnum)
- return synIDattr(synID(a:lnum,1+indent(a:lnum),1),'name')
+let s:headings = {
+ \ 'Feature': 'feature',
+ \ 'Rule': 'rule',
+ \ 'Background': 'bg_or_scenario',
+ \ 'Scenario': 'bg_or_scenario',
+ \ 'ScenarioOutline': 'bg_or_scenario',
+ \ 'Examples': 'examples',
+ \ 'Scenarios': 'examples'}
+
+function! s:Line(lnum) abort
+ if getline(a:lnum) =~# ':'
+ let group = matchstr(synIDattr(synID(a:lnum,1+indent(a:lnum), 1), 'name'), '^cucumber\zs.*')
+ if !has_key(s:headings, group)
+ let group = substitute(matchstr(getline(a:lnum), '^\s*\zs\%([^:]\+\)\ze:\S\@!'), '\s\+', '', 'g')
+ endif
+ else
+ let group = ''
+ endif
+ let char = matchstr(getline(a:lnum), '^\s*\zs[[:punct:]]')
+ return {
+ \ 'lnum': a:lnum,
+ \ 'indent': indent(a:lnum),
+ \ 'heading': get(s:headings, group, ''),
+ \ 'tag': char ==# '@',
+ \ 'table': char ==# '|',
+ \ 'comment': char ==# '#',
+ \ }
endfunction
-function! GetCucumberIndent()
- let line = getline(prevnonblank(v:lnum-1))
- let cline = getline(v:lnum)
- let nline = getline(nextnonblank(v:lnum+1))
- let sw = exists('*shiftwidth') ? shiftwidth() : shiftwidth()
- let syn = s:syn(prevnonblank(v:lnum-1))
- let csyn = s:syn(v:lnum)
- let nsyn = s:syn(nextnonblank(v:lnum+1))
- if csyn ==# 'cucumberFeature' || cline =~# '^\s*Feature:'
+function! GetCucumberIndent(...) abort
+ let lnum = a:0 ? a:1 : v:lnum
+ let sw = shiftwidth()
+ let prev = s:Line(prevnonblank(lnum-1))
+ let curr = s:Line(lnum)
+ let next = s:Line(nextnonblank(lnum+1))
+ if curr.heading ==# 'feature'
" feature heading
return 0
- elseif csyn ==# 'cucumberExamples' || cline =~# '^\s*\%(Examples\|Scenarios\):'
+ elseif curr.heading ==# 'examples'
" examples heading
return 2 * sw
- elseif csyn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || cline =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):'
+ elseif curr.heading ==# 'bg_or_scenario'
" background, scenario or outline heading
return sw
- elseif syn ==# 'cucumberFeature' || line =~# '^\s*Feature:'
+ elseif prev.heading ==# 'feature'
" line after feature heading
return sw
- elseif syn ==# 'cucumberExamples' || line =~# '^\s*\%(Examples\|Scenarios\):'
+ elseif prev.heading ==# 'examples'
" line after examples heading
return 3 * sw
- elseif syn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || line =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):'
+ elseif prev.heading ==# 'bg_or_scenario'
" line after background, scenario or outline heading
return 2 * sw
- elseif cline =~# '^\s*[@#]' && (nsyn == 'cucumberFeature' || nline =~# '^\s*Feature:' || indent(prevnonblank(v:lnum-1)) <= 0)
+ elseif (curr.tag || curr.comment) && (next.heading ==# 'feature' || prev.indent <= 0)
" tag or comment before a feature heading
return 0
- elseif cline =~# '^\s*@'
+ elseif curr.tag
" other tags
return sw
- elseif cline =~# '^\s*[#|]' && line =~# '^\s*|'
+ elseif (curr.table || curr.comment) && prev.table
" mid-table
" preserve indent
- return indent(prevnonblank(v:lnum-1))
- elseif cline =~# '^\s*|' && line =~# '^\s*[^|]'
+ return prev.indent
+ elseif curr.table && !prev.table
" first line of a table, relative indent
- return indent(prevnonblank(v:lnum-1)) + sw
- elseif cline =~# '^\s*[^|]' && line =~# '^\s*|'
+ return prev.indent + sw
+ elseif !curr.table && prev.table
" line after a table, relative unindent
- return indent(prevnonblank(v:lnum-1)) - sw
- elseif cline =~# '^\s*#' && getline(v:lnum-1) =~ '^\s*$' && (nsyn =~# '^cucumber\%(Background\|Scenario\|ScenarioOutline\)$' || nline =~# '^\s*\%(Background\|Scenario\|Scenario Outline\):')
+ return prev.indent - sw
+ elseif curr.comment && getline(v:lnum-1) =~# '^\s*$' && next.heading ==# 'bg_or_scenario'
" comments on scenarios
return sw
endif
- return indent(prevnonblank(v:lnum-1))
+ return prev.indent < 0 ? 0 : prev.indent
endfunction
" vim:set sts=2 sw=2:
diff --git a/runtime/indent/fortran.vim b/runtime/indent/fortran.vim
index 9623014818..392b2d29d5 100644
--- a/runtime/indent/fortran.vim
+++ b/runtime/indent/fortran.vim
@@ -1,7 +1,8 @@
" Vim indent file
-" Language: Fortran 2008 (and older: Fortran 2003, 95, 90, and 77)
-" Version: (v49) 2022 May 14
-" Maintainer: Ajit J. Thakkar <thakkar.ajit@gmail.com>; <http://www2.unb.ca/~ajit/>
+" Language: Fortran 2023 (and Fortran 2018, 2008, 2003, 95, 90, 77, 66)
+" Version: (v50) 2023 December 22
+" Maintainers: Ajit J. Thakkar <ajit@unb.ca>; <https://ajit.ext.unb.ca/>
+" Joshua Hollett <j.hollett@uwinnipeg.ca>
" Usage: For instructions, do :help fortran-indent from Vim
" Credits:
" Version 0.1 was created in September 2000 by Ajit Thakkar.
@@ -21,8 +22,8 @@ let b:undo_indent = "setl inde< indk<"
setlocal indentkeys+==~end,=~case,=~if,=~else,=~do,=~where,=~elsewhere,=~select
setlocal indentkeys+==~endif,=~enddo,=~endwhere,=~endselect,=~elseif
-setlocal indentkeys+==~type,=~interface,=~forall,=~associate,=~block,=~enum
-setlocal indentkeys+==~endforall,=~endassociate,=~endblock,=~endenum
+setlocal indentkeys+==~interface,=~forall,=~associate,=~block,=~enum,=~critical
+setlocal indentkeys+==~endforall,=~endassociate,=~endblock,=~endenum,=~endcritical
if exists("b:fortran_indent_more") || exists("g:fortran_indent_more")
setlocal indentkeys+==~function,=~subroutine,=~module,=~contains,=~program
setlocal indentkeys+==~endfunction,=~endsubroutine,=~endmodule
@@ -48,7 +49,7 @@ if !exists("b:fortran_fixed_source")
" Fixed-form file extension defaults
let b:fortran_fixed_source = 1
else
- " Modern fortran still allows both fixed and free source form
+ " Modern fortran compilers still allow both fixed and free source form
" Assume fixed source form unless signs of free source form
" are detected in the first five columns of the first s:lmax lines.
" Detection becomes more accurate and time-consuming if more lines
@@ -108,8 +109,9 @@ function FortranGetIndent(lnum)
"Add a shiftwidth to statements following if, else, else if, case, class,
"where, else where, forall, type, interface and associate statements
- if prevstat =~? '^\s*\(case\|class\|else\|else\s*if\|else\s*where\)\>'
- \ ||prevstat=~? '^\s*\(type\|interface\|associate\|enum\)\>'
+ if prevstat =~? '^\s*\(case\|class\s\+is\|else\|else\s*if\|else\s*where\)\>'
+ \ ||prevstat=~? '^\s*\(type\|rank\|interface\|associate\|enum\|critical\)\>'
+ \ ||prevstat=~? '^\s*change\s\+team\>'
\ ||prevstat=~?'^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*\(forall\|where\|block\)\>'
\ ||prevstat=~? '^\s*\(\d\+\s\)\=\s*\(\a\w*\s*:\)\=\s*if\>'
let ind = ind + shiftwidth()
@@ -144,10 +146,10 @@ function FortranGetIndent(lnum)
"Subtract a shiftwidth from else, else if, elsewhere, case, class, end if,
" end where, end select, end forall, end interface, end associate,
- " end enum, end type, end block and end type statements
+ " end enum, end type, end block, end team and end type statements
if getline(v:lnum) =~? '^\s*\(\d\+\s\)\=\s*'
- \. '\(else\|else\s*if\|else\s*where\|case\|class\|'
- \. 'end\s*\(if\|where\|select\|interface\|'
+ \. '\(else\|else\s*if\|else\s*where\|case\|class\|rank\|type\s\+is\|'
+ \. 'end\s*\(if\|where\|select\|interface\|critical\|team\|'
\. 'type\|forall\|associate\|enum\|block\)\)\>'
let ind = ind - shiftwidth()
" Fix indent for case statement immediately after select
diff --git a/runtime/indent/gdscript.vim b/runtime/indent/gdscript.vim
new file mode 100644
index 0000000000..bbb4f284f1
--- /dev/null
+++ b/runtime/indent/gdscript.vim
@@ -0,0 +1,154 @@
+" Vim indent file
+" Language: gdscript (Godot game engine)
+" Maintainer: Maxim Kim <habamax@gmail.com>
+" Based on python indent file.
+"
+" This file has been manually translated from Vim9 script.
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+let s:save_cpo = &cpo
+set cpo&vim
+
+let s:undo_opts = "setl indentexpr< indentkeys< lisp< autoindent<"
+
+if exists('b:undo_indent')
+ let b:undo_indent ..= "|" .. s:undo_opts
+else
+ let b:undo_indent = s:undo_opts
+endif
+
+setlocal nolisp
+setlocal autoindent
+setlocal indentexpr=s:GDScriptIndent()
+setlocal indentkeys+=<:>,=elif,=except
+
+
+function s:GDScriptIndent() abort
+ " If this line is explicitly joined: If the previous line was also joined,
+ " line it up with that one, otherwise add two 'shiftwidth'
+ if getline(v:lnum - 1) =~# '\\$'
+ if v:lnum > 1 && getline(v:lnum - 2) =~# '\\$'
+ return indent(v:lnum - 1)
+ endif
+ return indent(v:lnum - 1) + (shiftwidth() * 2)
+ endif
+
+ " If the start of the line is in a string don't change the indent.
+ if has('syntax_items') && synIDattr(synID(v:lnum, 1, 1), "name") =~# "String$"
+ return -1
+ endif
+
+ " Search backwards for the previous non-empty line.
+ let plnum = prevnonblank(v:lnum - 1)
+
+ if plnum == 0
+ " This is the first non-empty line, use zero indent.
+ return 0
+ endif
+
+ let plindent = indent(plnum)
+ let plnumstart = plnum
+
+ " Get the line and remove a trailing comment.
+ " Use syntax highlighting attributes when possible.
+ let pline = getline(plnum)
+ let pline_len = strlen(pline)
+ if has('syntax_items')
+ " If the last character in the line is a comment, do a binary search for
+ " the start of the comment. synID() is slow, a linear search would take
+ " too long on a long line.
+ if synIDattr(synID(plnum, pline_len, 1), "name") =~# "\\(Comment\\|Todo\\)$"
+ let min = 1
+ let max = pline_len
+ while min < max
+ let col = (min + max) / 2
+ if synIDattr(synID(plnum, col, 1), "name") =~# "\\(Comment\\|Todo\\)$"
+ let max = col
+ else
+ let min = col + 1
+ endif
+ endwhile
+ let pline = strpart(pline, 0, min - 1)
+ endif
+ else
+ let col = 0
+ while col < pline_len
+ if pline[col] ==# '#'
+ let pline = strpart(pline, 0, col)
+ break
+ endif
+ let col = col + 1
+ endwhile
+ endif
+
+
+ " When "inside" parenthesis: If at the first line below the parenthesis add
+ " one 'shiftwidth' ("inside" is simplified and not really checked)
+ " my_var = (
+ " a
+ " + b
+ " + c
+ " )
+ if pline =~# '[({\[]\s*$'
+ return indent(plnum) + shiftwidth()
+ endif
+
+
+ " If the previous line ended with a colon, indent this line
+ if pline =~# ':\s*$'
+ return plindent + shiftwidth()
+ endif
+
+ " If the previous line was a stop-execution statement...
+ if getline(plnum) =~# '^\s*\(break\|continue\|raise\|return\|pass\)\>'
+ " See if the user has already dedented
+ if indent(v:lnum) > indent(plnum) - shiftwidth()
+ " If not, recommend one dedent
+ return indent(plnum) - shiftwidth()
+ endif
+ " Otherwise, trust the user
+ return -1
+ endif
+
+ " If the current line begins with a keyword that lines up with "try"
+ if getline(v:lnum) =~# '^\s*\(except\|finally\)\>'
+ let lnum = v:lnum - 1
+ while lnum >= 1
+ if getline(lnum) =~# '^\s*\(try\|except\)\>'
+ let ind = indent(lnum)
+ if ind >= indent(v:lnum)
+ return -1 " indent is already less than this
+ endif
+ return ind " line up with previous try or except
+ endif
+ let lnum = lnum - 1
+ endwhile
+ return -1 " no matching "try"!
+ endif
+
+
+ " If the current line begins with a header keyword, dedent
+ if getline(v:lnum) =~# '^\s*\(elif\|else\)\>'
+
+ " Unless the previous line was a one-liner
+ if getline(plnumstart) =~# '^\s*\(for\|if\|try\)\>'
+ return plindent
+ endif
+
+ " Or the user has already dedented
+ if indent(v:lnum) <= plindent - shiftwidth()
+ return -1
+ endif
+
+ return plindent - shiftwidth()
+ endif
+
+ return -1
+endfunction
+
+let &cpo = s:save_cpo
+unlet s:save_cpo
diff --git a/runtime/indent/odin.vim b/runtime/indent/odin.vim
new file mode 100644
index 0000000000..0747b6b155
--- /dev/null
+++ b/runtime/indent/odin.vim
@@ -0,0 +1,124 @@
+" Vim indent plugin file
+" Language: Odin
+" Maintainer: Maxim Kim <habamax@gmail.com>
+" Website: https://github.com/habamax/vim-odin
+" Last Change: 2024-01-15
+"
+" This file has been manually translated from Vim9 script.
+
+if exists("b:did_indent")
+ finish
+endif
+let b:did_indent = 1
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+let b:undo_indent = 'setlocal cindent< cinoptions< cinkeys< indentexpr<'
+
+setlocal cindent
+setlocal cinoptions=L0,m1,(s,j1,J1,l1,+0,:0,#1
+setlocal cinkeys=0{,0},0),0],!^F,:,o,O
+
+setlocal indentexpr=s:GetOdinIndent(v:lnum)
+
+function s:PrevLine(lnum) abort
+ let plnum = a:lnum - 1
+ while plnum > 1
+ let plnum = prevnonblank(plnum)
+ let pline = getline(plnum)
+ " XXX: take into account nested multiline /* /* */ */ comments
+ if pline =~# '\*/\s*$'
+ while getline(plnum) !~# '/\*' && plnum > 1
+ let plnum -= 1
+ endwhile
+ if getline(plnum) =~# '^\s*/\*'
+ let plnum -= 1
+ else
+ break
+ endif
+ elseif pline =~# '^\s*//'
+ let plnum -= 1
+ else
+ break
+ endif
+ endwhile
+ return plnum
+endfunction
+
+function s:GetOdinIndent(lnum) abort
+ let plnum = s:PrevLine(a:lnum)
+ let pline = getline(plnum)
+ let pindent = indent(plnum)
+ " workaround of cindent "hang"
+ " if the previous line looks like:
+ " : #{}
+ " : #whatever{whateverelse}
+ " and variations where : # { } are in the string
+ " cindent(lnum) hangs
+ if pline =~# ':\s\+#.*{.*}'
+ return pindent
+ endif
+
+ let indent = cindent(a:lnum)
+ let line = getline(a:lnum)
+
+ if line =~# '^\s*#\k\+'
+ if pline =~# '[{:]\s*$'
+ let indent = pindent + shiftwidth()
+ else
+ let indent = pindent
+ endif
+ elseif pline =~# 'switch\s.*{\s*$'
+ let indent = pindent
+ elseif pline =~# 'case\s*.*,\s*\(//.*\)\?$' " https://github.com/habamax/vim-odin/issues/8
+ let indent = pindent + matchstr(pline, 'case\s*')->strcharlen()
+ elseif line =~# '^\s*case\s\+.*,\s*$'
+ let indent = pindent - shiftwidth()
+ elseif pline =~# 'case\s*.*:\s*\(//.*\)\?$'
+ if line !~# '^\s*}\s*$' && line !~# '^\s*case[[:space:]:]'
+ let indent = pindent + shiftwidth()
+ endif
+ elseif pline =~# '^\s*@.*' && line !~# '^\s*}'
+ let indent = pindent
+ elseif pline =~# ':[:=].*}\s*$'
+ let indent = pindent
+ elseif pline =~# '^\s*}\s*$'
+ if line !~# '^\s*}' && line !~# 'case\s*.*:\s*$'
+ let indent = pindent
+ else
+ let indent = pindent - shiftwidth()
+ endif
+ elseif pline =~# '\S:\s*$'
+ " looking up for a case something,
+ " whatever,
+ " anything:
+ " ... 20 lines before
+ for idx in range(plnum - 1, plnum - 21, -1)
+ if plnum < 1
+ break
+ endif
+ if getline(idx) =~# '^\s*case\s.*,\s*$'
+ let indent = indent(idx) + shiftwidth()
+ break
+ endif
+ endfor
+ elseif pline =~# '{[^{]*}\s*$' && line !~# '^\s*[})]\s*$' " https://github.com/habamax/vim-odin/issues/2
+ let indent = pindent
+ elseif pline =~# '^\s*}\s*$' " https://github.com/habamax/vim-odin/issues/3
+ " Find line with opening { and check if there is a label:
+ " If there is, return indent of the closing }
+ call cursor(plnum, 1)
+ silent normal! %
+ let brlnum = line('.')
+ let brline = getline('.')
+ if plnum != brlnum && (brline =~# '^\s*\k\+:\s\+for' || brline =~# '^\s*\k\+\s*:=')
+ let indent = pindent
+ endif
+ endif
+
+ return indent
+endfunction
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/indent/qml.vim b/runtime/indent/qml.vim
index 8c9fa91250..cf0ba41957 100644
--- a/runtime/indent/qml.vim
+++ b/runtime/indent/qml.vim
@@ -1,7 +1,7 @@
" Vim indent file
" Language: QML
" Maintainer: Chase Knowlden <haroldknowlden@gmail.com>
-" Last Change: 2023 Aug 16
+" Last Change: 2024 Jan 24 by Vim Project
"
" Improved JavaScript indent script.
@@ -40,10 +40,10 @@ function! s:GetQmlIndent()
" bracket/brace/paren blocks
if pline =~ '[{[(]$'
- let ind += &sw
+ let ind += shiftwidth()
endif
if line =~ '^[}\])]'
- let ind -= &sw
+ let ind -= shiftwidth()
endif
" '/*' comments
diff --git a/runtime/indent/query.lua b/runtime/indent/query.lua
index c86948e95e..3261376d87 100644
--- a/runtime/indent/query.lua
+++ b/runtime/indent/query.lua
@@ -1,5 +1,5 @@
-- Neovim indent file
--- Language: Tree-sitter query
+-- Language: Treesitter query
-- Last Change: 2022 Mar 29
-- it's a lisp!
diff --git a/runtime/indent/r.vim b/runtime/indent/r.vim
index 07dfd13881..339c46b172 100644
--- a/runtime/indent/r.vim
+++ b/runtime/indent/r.vim
@@ -1,8 +1,10 @@
" Vim indent file
" Language: R
-" Author: Jakson Alves de Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Mon Feb 27, 2023 07:16PM
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2023 Oct 08 10:45AM
+" 2024 Feb 19 by Vim Project (announce adoption)
" Only load this indent file when no other was loaded.
@@ -13,6 +15,7 @@ let b:did_indent = 1
setlocal indentkeys=0{,0},:,!^F,o,O,e
setlocal indentexpr=GetRIndent()
+setlocal autoindent
let b:undo_indent = "setl inde< indk<"
@@ -47,27 +50,23 @@ function s:RDelete_quotes(line)
if a:line[i] == '"'
let i += 1
endif
- else
+ elseif a:line[i] == "'"
+ let i += 1
+ let line1 = line1 . 's'
+ while !(a:line[i] == "'" && ((i > 1 && a:line[i-1] == '\' && a:line[i-2] == '\') || a:line[i-1] != '\')) && i < llen
+ let i += 1
+ endwhile
if a:line[i] == "'"
let i += 1
- let line1 = line1 . 's'
- while !(a:line[i] == "'" && ((i > 1 && a:line[i-1] == '\' && a:line[i-2] == '\') || a:line[i-1] != '\')) && i < llen
- let i += 1
- endwhile
- if a:line[i] == "'"
- let i += 1
- endif
- else
- if a:line[i] == "`"
- let i += 1
- let line1 = line1 . 's'
- while a:line[i] != "`" && i < llen
- let i += 1
- endwhile
- if a:line[i] == "`"
- let i += 1
- endif
- endif
+ endif
+ elseif a:line[i] == "`"
+ let i += 1
+ let line1 = line1 . 's'
+ while a:line[i] != "`" && i < llen
+ let i += 1
+ endwhile
+ if a:line[i] == "`"
+ let i += 1
endif
endif
if i == llen
@@ -97,10 +96,8 @@ function s:RDelete_parens(line)
let i += 1
if a:line[i] == ')'
let nop -= 1
- else
- if a:line[i] == '('
- let nop += 1
- endif
+ elseif a:line[i] == '('
+ let nop += 1
endif
endwhile
let line1 = line1 . a:line[i]
@@ -174,10 +171,8 @@ function s:Get_last_paren_idx(line, o, c, pb)
if blc == 0
let theidx = idx
endif
- else
- if line[idx] == a:c
- let blc += 1
- endif
+ elseif line[idx] == a:c
+ let blc += 1
endif
let idx += 1
endwhile
@@ -316,6 +311,11 @@ function GetRIndent()
endif
if pb < 0 && line =~ '.*[,&|\-\*+<>]$'
+ if line =~ '.*[\-\*+>]$'
+ let is_op = v:true
+ else
+ let is_op = v:false
+ endif
let lnum = s:Get_prev_line(lnum)
while pb < 1 && lnum > 0
let line = SanitizeRLine(getline(lnum))
@@ -324,9 +324,10 @@ function GetRIndent()
while ind > 0
if line[ind] == ')'
let pb -= 1
- else
- if line[ind] == '('
- let pb += 1
+ elseif line[ind] == '('
+ let pb += 1
+ if is_op && pb == 0
+ return indent(lnum)
endif
endif
if pb == 1
@@ -367,10 +368,8 @@ function GetRIndent()
else
return indent(lnum) + shiftwidth()
endif
- else
- if substitute(oline, '#.*', '', '') =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0
- return indent(lnum) - shiftwidth()
- endif
+ elseif substitute(oline, '#.*', '', '') =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0
+ return indent(lnum) - shiftwidth()
endif
elseif substitute(line, '#.*', '', '') =~ g:r_indent_op_pattern && s:Get_paren_balance(line, "(", ")") == 0
return indent(lnum) + shiftwidth()
@@ -404,12 +403,10 @@ function GetRIndent()
if cline =~ '^\s*else'
if line =~ '<-\s*if\s*()'
return indent(lnum) + shiftwidth()
+ elseif line =~ '\<if\s*()'
+ return indent(lnum)
else
- if line =~ '\<if\s*()'
- return indent(lnum)
- else
- return indent(lnum) - shiftwidth()
- endif
+ return indent(lnum) - shiftwidth()
endif
endif
diff --git a/runtime/indent/racket.vim b/runtime/indent/racket.vim
index 93bd38fbff..d301cd64f9 100644
--- a/runtime/indent/racket.vim
+++ b/runtime/indent/racket.vim
@@ -3,7 +3,7 @@
" Maintainer: D. Ben Knoble <ben.knoble+github@gmail.com>
" Previous Maintainer: Will Langstroth <will@langstroth.com>
" URL: https://github.com/benknoble/vim-racket
-" Last Change: 2022 Aug 12
+" Last Change: 2024 Jan 31
if exists("b:did_indent")
finish
@@ -11,18 +11,25 @@ endif
let b:did_indent = 1
setlocal lisp autoindent nosmartindent
+if has('vim9script')
+ setlocal indentexpr=racket#Indent() lispoptions+=expr:1
+endif
-setlocal lispwords+=module,module*,module+,parameterize,let-values,let*-values,letrec-values,local
+setlocal lispwords+=module,module*,module+,parameterize,parameterize*,let-values,let*-values,letrec-values,local
setlocal lispwords+=define/contract
setlocal lispwords+=λ
setlocal lispwords+=with-handlers
setlocal lispwords+=define-values,opt-lambda,case-lambda,syntax-rules,with-syntax,syntax-case,syntax-parse
setlocal lispwords+=define-for-syntax,define-syntax-parser,define-syntax-parse-rule,define-syntax-class,define-splicing-syntax-class
+setlocal lispwords+=define-syntax-parameter,syntax-parameterize
setlocal lispwords+=define-signature,unit,unit/sig,compund-unit/sig,define-values/invoke-unit/sig
setlocal lispwords+=define-opt/c,define-syntax-rule
-setlocal lispwords+=define-test-suite
+setlocal lispwords+=define-test-suite,test-case
setlocal lispwords+=struct
setlocal lispwords+=with-input-from-file,with-output-to-file
+setlocal lispwords+=begin,begin0
+setlocal lispwords+=place
+setlocal lispwords+=cond
" Racket OOP
" TODO missing a lot of define-like forms here (e.g., define/augment, etc.)
@@ -41,6 +48,8 @@ setlocal lispwords+=for/hash,for/hasheq,for/hasheqv,for/sum,for/flvector,for*/fl
setlocal lispwords+=for/async
setlocal lispwords+=for/set,for*/set
setlocal lispwords+=for/first,for*/first
+setlocal lispwords+=for/last,for*/last
+setlocal lispwords+=for/stream,for*/stream
setlocal lispwords+=match,match*,match/values,define/match,match-lambda,match-lambda*,match-lambda**
setlocal lispwords+=match-let,match-let*,match-let-values,match-let*-values
@@ -57,4 +66,4 @@ setlocal lispwords+=if-view,case-view,cond-view,list-view,dyn-view
setlocal lispwords+=case/dep
setlocal lispwords+=define/obs
-let b:undo_indent = "setlocal lisp< ai< si< lw<"
+let b:undo_indent = "setlocal lisp< ai< si< lw<" .. (has('vim9script') ? ' indentexpr< lispoptions<' : '')
diff --git a/runtime/indent/rhelp.vim b/runtime/indent/rhelp.vim
index 334802ab78..97820ae148 100644
--- a/runtime/indent/rhelp.vim
+++ b/runtime/indent/rhelp.vim
@@ -1,8 +1,10 @@
" Vim indent file
" Language: R Documentation (Help), *.Rd
-" Author: Jakson Alves de Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Mon Feb 27, 2023 07:01PM
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2023 Feb 27 07:01PM
+" 2024 Feb 19 by Vim Project (announce adoption)
" Only load this indent file when no other was loaded.
diff --git a/runtime/indent/rmd.vim b/runtime/indent/rmd.vim
index a043b0c994..f2d34a3f32 100644
--- a/runtime/indent/rmd.vim
+++ b/runtime/indent/rmd.vim
@@ -1,8 +1,10 @@
" Vim indent file
" Language: Rmd
-" Author: Jakson Alves de Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Wed Nov 09, 2022 09:44PM
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2022 Nov 09 09:44PM
+" 2024 Feb 19 by Vim Project (announce adoption)
" Only load this indent file when no other was loaded.
diff --git a/runtime/indent/rnoweb.vim b/runtime/indent/rnoweb.vim
index 668cdb7ddd..1bdf7f3b12 100644
--- a/runtime/indent/rnoweb.vim
+++ b/runtime/indent/rnoweb.vim
@@ -1,8 +1,10 @@
" Vim indent file
" Language: Rnoweb
-" Author: Jakson Alves de Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Mon Feb 27, 2023 07:17PM
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2024 Feb 27 07:17PM
+" 2024 Feb 19 by Vim Project (announce adoption)
" Only load this indent file when no other was loaded.
diff --git a/runtime/indent/rrst.vim b/runtime/indent/rrst.vim
index 585c5e6654..73c8b04611 100644
--- a/runtime/indent/rrst.vim
+++ b/runtime/indent/rrst.vim
@@ -1,8 +1,10 @@
" Vim indent file
" Language: Rrst
-" Author: Jakson Alves de Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Feb 25, 2023
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2023 Feb 25
+" 2024 Feb 19 by Vim Project (announce adoption)
" Only load this indent file when no other was loaded.
diff --git a/runtime/indent/sass.vim b/runtime/indent/sass.vim
index 8c0ecd0746..45dc869a55 100644
--- a/runtime/indent/sass.vim
+++ b/runtime/indent/sass.vim
@@ -1,14 +1,14 @@
" Vim indent file
" Language: Sass
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
-" Last Change: 2022 Mar 15
+" Last Change: 2023 Dec 28
if exists("b:did_indent")
finish
endif
let b:did_indent = 1
-setlocal autoindent sw=2 et
+setlocal autoindent
setlocal indentexpr=GetSassIndent()
setlocal indentkeys=o,O,*<Return>,<:>,!^F
@@ -26,10 +26,8 @@ function! GetSassIndent()
let lnum = prevnonblank(v:lnum-1)
let line = substitute(getline(lnum),'\s\+$','','')
let cline = substitute(substitute(getline(v:lnum),'\s\+$','',''),'^\s\+','','')
- let lastcol = strlen(line)
let line = substitute(line,'^\s\+','','')
let indent = indent(lnum)
- let cindent = indent(v:lnum)
if line !~ s:property && line !~ s:extend && cline =~ s:property
return indent + shiftwidth()
else
diff --git a/runtime/indent/yaml.vim b/runtime/indent/yaml.vim
index 93fd8ea6f6..e5daf9f219 100644
--- a/runtime/indent/yaml.vim
+++ b/runtime/indent/yaml.vim
@@ -3,6 +3,7 @@
" Maintainer: Nikolai Pavlov <zyx.vim@gmail.com>
" Last Updates: Lukas Reineke, "lacygoill"
" Last Change: 2022 Jun 17
+" 2024 Feb 29 disable mulitline indent by default (The Vim project)
" Only load this indent file when no other was loaded.
if exists('b:did_indent')
@@ -138,11 +139,13 @@ function GetYAMLIndent(lnum)
else
return indent(prevmapline)
endif
- elseif prevline =~# '^\s*- '
+ elseif get(g:, 'yaml_indent_multiline_scalar', 0) &&
+ \ prevline =~# '^\s*- '
" - List with
" multiline scalar
return previndent+2
- elseif prevline =~# s:mapkeyregex .. '\v\s*%(%(' .. s:c_ns_tag_property ..
+ elseif get(g:, 'yaml_indent_multiline_scalar', 0) &&
+ \ prevline =~# s:mapkeyregex .. '\v\s*%(%(' .. s:c_ns_tag_property ..
\ '\v|' .. s:c_ns_anchor_property ..
\ '\v|' .. s:block_scalar_header ..
\ '\v)%(\s+|\s*%(\#.*)?$))*'
diff --git a/runtime/lua/man.lua b/runtime/lua/man.lua
index dcdfc2b87f..ac15aff60c 100644
--- a/runtime/lua/man.lua
+++ b/runtime/lua/man.lua
@@ -238,7 +238,7 @@ local function get_path(sect, name, silent)
-- If you run man -w strlen and string.3 comes up first, this is a problem. We
-- should search for a matching named one in the results list.
-- However, if you search for man -w clock_gettime, you will *only* get
- -- clock_getres.2, which is the right page. Searching the resuls for
+ -- clock_getres.2, which is the right page. Searching the results for
-- clock_gettime will no longer work. In this case, we should just use the
-- first one that was found in the correct section.
--
diff --git a/runtime/lua/nvim/health.lua b/runtime/lua/nvim/health.lua
index 6b6370fa19..0480e4df4e 100644
--- a/runtime/lua/nvim/health.lua
+++ b/runtime/lua/nvim/health.lua
@@ -17,15 +17,21 @@ local shell_error = function()
return vim.v.shell_error ~= 0
end
-local suggest_faq = 'https://github.com/neovim/neovim/wiki/Building-Neovim#optimized-builds'
+local suggest_faq = 'https://github.com/neovim/neovim/blob/docs/install/BUILD.md#building'
local function check_runtime()
health.start('Runtime')
-- Files from an old installation.
local bad_files = {
+ ['plugin/health.vim'] = false,
+ ['autoload/health/nvim.vim'] = false,
+ ['autoload/health/provider.vim'] = false,
+ ['autoload/man.vim'] = false,
['plugin/man.vim'] = false,
+ ['queries/help/highlights.scm'] = false,
+ ['queries/help/injections.scm'] = false,
['scripts.vim'] = false,
- ['autoload/man.vim'] = false,
+ ['syntax/syncolor.vim'] = false,
}
local bad_files_msg = ''
for k, _ in pairs(bad_files) do
@@ -42,10 +48,10 @@ local function check_runtime()
if not ok then
health.error(
string.format(
- '$VIMRUNTIME has files from an old installation (this can cause weird behavior):\n%s',
+ 'Found old files in $VIMRUNTIME (this can cause weird behavior):\n%s',
bad_files_msg
),
- { 'Delete $VIMRUNTIME (or uninstall Nvim), then reinstall Nvim.' }
+ { 'Delete the $VIMRUNTIME directory (or uninstall Nvim), then reinstall Nvim.' }
)
end
end
@@ -183,10 +189,6 @@ local function check_rplugin_manifest()
health.start('Remote Plugins')
local existing_rplugins = {}
- for _, item in ipairs(vim.fn['remote#host#PluginsForHost']('python')) do
- existing_rplugins[item.path] = 'python'
- end
-
for _, item in ipairs(vim.fn['remote#host#PluginsForHost']('python3')) do
existing_rplugins[item.path] = 'python3'
end
@@ -324,24 +326,17 @@ local function check_tmux()
end
-- check for RGB capabilities
- local info = vim.fn.system({ 'tmux', 'display-message', '-p', '#{client_termfeatures}' })
- info = vim.split(vim.trim(info), ',', { trimempty = true })
- if not vim.list_contains(info, 'RGB') then
- local has_rgb = false
- if #info == 0 then
- -- client_termfeatures may not be supported; fallback to checking show-messages
- info = vim.fn.system({ 'tmux', 'show-messages', '-JT' })
- has_rgb = info:find(' Tc: (flag) true', 1, true) or info:find(' RGB: (flag) true', 1, true)
- end
- if not has_rgb then
- health.warn(
- "Neither Tc nor RGB capability set. True colors are disabled. |'termguicolors'| won't work properly.",
- {
- "Put this in your ~/.tmux.conf and replace XXX by your $TERM outside of tmux:\nset-option -sa terminal-features ',XXX:RGB'",
- "For older tmux versions use this instead:\nset-option -ga terminal-overrides ',XXX:Tc'",
- }
- )
- end
+ local info = vim.fn.system({ 'tmux', 'show-messages', '-T' })
+ local has_setrgbb = vim.fn.stridx(info, ' setrgbb: (string)') ~= -1
+ local has_setrgbf = vim.fn.stridx(info, ' setrgbf: (string)') ~= -1
+ if not has_setrgbb or not has_setrgbf then
+ health.warn(
+ "True color support could not be detected. |'termguicolors'| won't work properly.",
+ {
+ "Add the following to your tmux configuration file, replacing XXX by the value of $TERM outside of tmux:\nset-option -a terminal-features 'XXX:RGB'",
+ "For older tmux versions use this instead:\nset-option -a terminal-overrides 'XXX:Tc'",
+ }
+ )
end
end
diff --git a/runtime/lua/provider/clipboard/health.lua b/runtime/lua/provider/clipboard/health.lua
new file mode 100644
index 0000000000..dc33cb0ab0
--- /dev/null
+++ b/runtime/lua/provider/clipboard/health.lua
@@ -0,0 +1,40 @@
+local health = vim.health
+local executable = health.executable
+
+local M = {}
+
+function M.check()
+ health.start('Clipboard (optional)')
+
+ if
+ os.getenv('TMUX')
+ and executable('tmux')
+ and executable('pbpaste')
+ and not health.cmd_ok('pbpaste')
+ then
+ local tmux_version = string.match(vim.fn.system('tmux -V'), '%d+%.%d+')
+ local advice = {
+ 'Install tmux 2.6+. https://superuser.com/q/231130',
+ 'or use tmux with reattach-to-user-namespace. https://superuser.com/a/413233',
+ }
+ health.error('pbcopy does not work with tmux version: ' .. tmux_version, advice)
+ end
+
+ local clipboard_tool = vim.fn['provider#clipboard#Executable']()
+ if vim.g.clipboard ~= nil and clipboard_tool == '' then
+ local error_message = vim.fn['provider#clipboard#Error']()
+ health.error(
+ error_message,
+ "Use the example in :help g:clipboard as a template, or don't set g:clipboard at all."
+ )
+ elseif clipboard_tool:find('^%s*$') then
+ health.warn(
+ 'No clipboard tool found. Clipboard registers (`"+` and `"*`) will not work.',
+ ':help clipboard'
+ )
+ else
+ health.ok('Clipboard tool found: ' .. clipboard_tool)
+ end
+end
+
+return M
diff --git a/runtime/lua/provider/health.lua b/runtime/lua/provider/health.lua
deleted file mode 100644
index d33f74f6e9..0000000000
--- a/runtime/lua/provider/health.lua
+++ /dev/null
@@ -1,916 +0,0 @@
-local M = {}
-
-local start = vim.health.start
-local ok = vim.health.ok
-local info = vim.health.info
-local warn = vim.health.warn
-local error = vim.health.error
-local iswin = vim.uv.os_uname().sysname == 'Windows_NT'
-
-local shell_error_code = 0
-local function shell_error()
- return shell_error_code ~= 0
-end
-
--- Returns true if `cmd` exits with success, else false.
-local function cmd_ok(cmd)
- vim.fn.system(cmd)
- return vim.v.shell_error == 0
-end
-
-local function executable(exe)
- return vim.fn.executable(exe) == 1
-end
-
-local function is_blank(s)
- return s:find('^%s*$') ~= nil
-end
-
-local function isdir(path)
- if not path then
- return false
- end
- local stat = vim.uv.fs_stat(path)
- if not stat then
- return false
- end
- return stat.type == 'directory'
-end
-
-local function isfile(path)
- if not path then
- return false
- end
- local stat = vim.uv.fs_stat(path)
- if not stat then
- return false
- end
- return stat.type == 'file'
-end
-
--- Handler for s:system() function.
-local function system_handler(self, _, data, event)
- if event == 'stderr' then
- if self.add_stderr_to_output then
- self.output = self.output .. vim.fn.join(data, '')
- else
- self.stderr = self.stderr .. vim.fn.join(data, '')
- end
- elseif event == 'stdout' then
- self.output = self.output .. vim.fn.join(data, '')
- elseif event == 'exit' then
- shell_error_code = data
- end
-end
-
--- Attempts to construct a shell command from an args list.
--- Only for display, to help users debug a failed command.
-local function shellify(cmd)
- if type(cmd) ~= 'table' then
- return cmd
- end
- return vim.fn.join(
- vim.fn.map(vim.fn.copy(cmd), [[v:val =~# ''\m[^\-.a-zA-Z_/]'' ? shellescape(v:val) : v:val]]),
- ' '
- )
-end
-
--- Run a system command and timeout after 30 seconds.
-local function system(cmd, ...)
- local args = { ... }
- local args_count = vim.tbl_count(args)
-
- local stdin = (args_count > 0 and args[1] or '')
- local stderr = (args_count > 1 and args[2] or false)
- local ignore_error = (args_count > 2 and args[3] or false)
-
- local opts = {
- add_stderr_to_output = stderr,
- output = '',
- stderr = '',
- on_stdout = system_handler,
- on_stderr = system_handler,
- on_exit = system_handler,
- }
- local jobid = vim.fn.jobstart(cmd, opts)
-
- if jobid < 1 then
- local message = 'Command error (job='
- .. jobid
- .. '): `'
- .. shellify(cmd)
- .. '` (in '
- .. vim.fn.string(vim.fn.getcwd())
- .. ')'
-
- error(message)
- shell_error_code = 1
- return opts.output
- end
-
- if not is_blank(stdin) then
- vim.api.nvim_chan_send(jobid, stdin)
- end
-
- local res = vim.fn.jobwait({ jobid }, 30000)
- if res[1] == -1 then
- error('Command timed out: ' .. shellify(cmd))
- vim.fn.jobstop(jobid)
- elseif shell_error() and not ignore_error then
- local emsg = 'Command error (job='
- .. jobid
- .. ', exit code '
- .. shell_error_code
- .. '): `'
- .. shellify(cmd)
- .. '` (in '
- .. vim.fn.string(vim.fn.getcwd())
- .. ')'
- if not is_blank(opts.output) then
- emsg = emsg .. '\noutput: ' .. opts.output
- end
- if not is_blank(opts.stderr) then
- emsg = emsg .. '\nstderr: ' .. opts.stderr
- end
- error(emsg)
- end
-
- -- return opts.output
- local _ = ...
- return vim.trim(vim.fn.system(cmd))
-end
-
-local function clipboard()
- start('Clipboard (optional)')
-
- if
- os.getenv('TMUX')
- and executable('tmux')
- and executable('pbpaste')
- and not cmd_ok('pbpaste')
- then
- local tmux_version = string.match(vim.fn.system('tmux -V'), '%d+%.%d+')
- local advice = {
- 'Install tmux 2.6+. https://superuser.com/q/231130',
- 'or use tmux with reattach-to-user-namespace. https://superuser.com/a/413233',
- }
- error('pbcopy does not work with tmux version: ' .. tmux_version, advice)
- end
-
- local clipboard_tool = vim.fn['provider#clipboard#Executable']()
- if vim.g.clipboard and is_blank(clipboard_tool) then
- local error_message = vim.fn['provider#clipboard#Error']()
- error(
- error_message,
- "Use the example in :help g:clipboard as a template, or don't set g:clipboard at all."
- )
- elseif is_blank(clipboard_tool) then
- warn(
- 'No clipboard tool found. Clipboard registers (`"+` and `"*`) will not work.',
- ':help clipboard'
- )
- else
- ok('Clipboard tool found: ' .. clipboard_tool)
- end
-end
-
-local function disabled_via_loaded_var(provider)
- local loaded_var = 'loaded_' .. provider .. '_provider'
- local v = vim.g[loaded_var]
- if v == 0 then
- info('Disabled (' .. loaded_var .. '=' .. v .. ').')
- return true
- end
- return false
-end
-
--- Check if pyenv is available and a valid pyenv root can be found, then return
--- their respective paths. If either of those is invalid, return two empty
--- strings, effectively ignoring pyenv.
-local function check_for_pyenv()
- local pyenv_path = vim.fn.resolve(vim.fn.exepath('pyenv'))
-
- if is_blank(pyenv_path) then
- return { '', '' }
- end
-
- info('pyenv: Path: ' .. pyenv_path)
-
- local pyenv_root = os.getenv('PYENV_ROOT') and vim.fn.resolve(os.getenv('PYENV_ROOT')) or ''
-
- if is_blank(pyenv_root) then
- pyenv_root = vim.trim(system({ pyenv_path, 'root' }))
- info('pyenv: $PYENV_ROOT is not set. Infer from `pyenv root`.')
- end
-
- if not isdir(pyenv_root) then
- local message = 'pyenv: Root does not exist: '
- .. pyenv_root
- .. '. Ignoring pyenv for all following checks.'
- warn(message)
- return { '', '' }
- end
-
- info('pyenv: Root: ' .. pyenv_root)
-
- return { pyenv_path, pyenv_root }
-end
-
--- Check the Python interpreter's usability.
-local function check_bin(bin)
- if not isfile(bin) and (not iswin or not isfile(bin .. '.exe')) then
- error('"' .. bin .. '" was not found.')
- return false
- elseif not executable(bin) then
- error('"' .. bin .. '" is not executable.')
- return false
- end
- return true
-end
-
--- Fetch the contents of a URL.
-local function download(url)
- local has_curl = executable('curl')
- if has_curl and vim.fn.system({ 'curl', '-V' }):find('Protocols:.*https') then
- local rv = system({ 'curl', '-sL', url }, '', 1, 1)
- if shell_error() then
- return 'curl error with ' .. url .. ': ' .. shell_error_code
- else
- return rv
- end
- elseif executable('python') then
- local script = "try:\n\
- from urllib.request import urlopen\n\
- except ImportError:\n\
- from urllib2 import urlopen\n\
- response = urlopen('" .. url .. "')\n\
- print(response.read().decode('utf8'))\n"
- local rv = system({ 'python', '-c', script })
- if is_blank(rv) and shell_error() then
- return 'python urllib.request error: ' .. shell_error_code
- else
- return rv
- end
- end
-
- local message = 'missing `curl` '
-
- if has_curl then
- message = message .. '(with HTTPS support) '
- end
- message = message .. 'and `python`, cannot make web request'
-
- return message
-end
-
--- Get the latest Nvim Python client (pynvim) version from PyPI.
-local function latest_pypi_version()
- local pypi_version = 'unable to get pypi response'
- local pypi_response = download('https://pypi.python.org/pypi/pynvim/json')
- if not is_blank(pypi_response) then
- local pcall_ok, output = pcall(vim.fn.json_decode, pypi_response)
- local pypi_data
- if pcall_ok then
- pypi_data = output
- else
- return 'error: ' .. pypi_response
- end
-
- local pypi_element = pypi_data['info'] or {}
- pypi_version = pypi_element['version'] or 'unable to parse'
- end
- return pypi_version
-end
-
-local function is_bad_response(s)
- local lower = s:lower()
- return vim.startswith(lower, 'unable')
- or vim.startswith(lower, 'error')
- or vim.startswith(lower, 'outdated')
-end
-
--- Get version information using the specified interpreter. The interpreter is
--- used directly in case breaking changes were introduced since the last time
--- Nvim's Python client was updated.
---
--- Returns: {
--- {python executable version},
--- {current nvim version},
--- {current pypi nvim status},
--- {installed version status}
--- }
-local function version_info(python)
- local pypi_version = latest_pypi_version()
-
- local python_version = vim.trim(system({
- python,
- '-c',
- 'import sys; print(".".join(str(x) for x in sys.version_info[:3]))',
- }))
-
- if is_blank(python_version) then
- python_version = 'unable to parse ' .. python .. ' response'
- end
-
- local nvim_path = vim.trim(system({
- python,
- '-c',
- 'import sys; sys.path = [p for p in sys.path if p != ""]; import neovim; print(neovim.__file__)',
- }))
- if shell_error() or is_blank(nvim_path) then
- return { python_version, 'unable to load neovim Python module', pypi_version, nvim_path }
- end
-
- -- Assuming that multiple versions of a package are installed, sort them
- -- numerically in descending order.
- local function compare(metapath1, metapath2)
- local a = vim.fn.matchstr(vim.fn.fnamemodify(metapath1, ':p:h:t'), [[[0-9.]\+]])
- local b = vim.fn.matchstr(vim.fn.fnamemodify(metapath2, ':p:h:t'), [[[0-9.]\+]])
- if a == b then
- return 0
- elseif a > b then
- return 1
- else
- return -1
- end
- end
-
- -- Try to get neovim.VERSION (added in 0.1.11dev).
- local nvim_version = system({
- python,
- '-c',
- 'from neovim import VERSION as v; print("{}.{}.{}{}".format(v.major, v.minor, v.patch, v.prerelease))',
- }, '', 1, 1)
- if is_blank(nvim_version) then
- nvim_version = 'unable to find pynvim module version'
- local base = vim.fs.basename(nvim_path, ':h')
- local metas = vim.fn.glob(base .. '-*/METADATA', 1, 1)
- vim.list_extend(metas, vim.fn.glob(base .. '-*/PKG-INFO', 1, 1))
- vim.list_extend(metas, vim.fn.glob(base .. '.egg-info/PKG-INFO', 1, 1))
- metas = table.sort(metas, compare)
-
- if metas and next(metas) ~= nil then
- for _, meta_line in ipairs(vim.fn.readfile(metas[1])) do
- if vim.startswith(meta_line, 'Version:') then
- nvim_version = vim.fn.matchstr(meta_line, [[^Version: \zs\S\+]])
- break
- end
- end
- end
- end
-
- local nvim_path_base = vim.fn.fnamemodify(nvim_path, [[:~:h]])
- local version_status = 'unknown; ' .. nvim_path_base
- if is_bad_response(nvim_version) and is_bad_response(pypi_version) then
- if vim.version.lt(nvim_version, pypi_version) then
- version_status = 'outdated; from ' .. nvim_path_base
- else
- version_status = 'up to date'
- end
- end
-
- return { python_version, nvim_version, pypi_version, version_status }
-end
-
--- Resolves Python executable path by invoking and checking `sys.executable`.
-local function python_exepath(invocation)
- return vim.fs.normalize(
- system(vim.fn.fnameescape(invocation) .. ' -c "import sys; sys.stdout.write(sys.executable)"')
- )
-end
-
-local function python()
- start('Python 3 provider (optional)')
-
- local pyname = 'python3'
- local python_exe = ''
- local virtual_env = os.getenv('VIRTUAL_ENV')
- local venv = virtual_env and vim.fn.resolve(virtual_env) or ''
- local host_prog_var = pyname .. '_host_prog'
- local python_multiple = {}
-
- if disabled_via_loaded_var(pyname) then
- return
- end
-
- local pyenv_table = check_for_pyenv()
- local pyenv = pyenv_table[1]
- local pyenv_root = pyenv_table[2]
-
- if vim.g[host_prog_var] then
- local message = 'Using: g:' .. host_prog_var .. ' = "' .. vim.g[host_prog_var] .. '"'
- info(message)
- end
-
- local python_table = vim.fn['provider#pythonx#Detect'](3)
- pyname = python_table[1]
- local pythonx_warnings = python_table[2]
-
- if is_blank(pyname) then
- warn(
- 'No Python executable found that can `import neovim`. '
- .. 'Using the first available executable for diagnostics.'
- )
- elseif vim.g[host_prog_var] then
- python_exe = pyname
- end
-
- -- No Python executable could `import neovim`, or host_prog_var was used.
- if not is_blank(pythonx_warnings) then
- warn(pythonx_warnings, {
- 'See :help provider-python for more information.',
- 'You may disable this provider (and warning) by adding `let g:loaded_python3_provider = 0` to your init.vim',
- })
- elseif not is_blank(pyname) and is_blank(python_exe) then
- if not vim.g[host_prog_var] then
- local message = '`g:'
- .. host_prog_var
- .. '` is not set. Searching for '
- .. pyname
- .. ' in the environment.'
- info(message)
- end
-
- if not is_blank(pyenv) then
- python_exe = vim.trim(system({ pyenv, 'which', pyname }, '', 1))
- if is_blank(python_exe) then
- warn('pyenv could not find ' .. pyname .. '.')
- end
- end
-
- if is_blank(python_exe) then
- python_exe = vim.fn.exepath(pyname)
-
- if os.getenv('PATH') then
- local path_sep = iswin and ';' or ':'
- local paths = vim.split(os.getenv('PATH') or '', path_sep)
-
- for _, path in ipairs(paths) do
- local path_bin = vim.fs.normalize(path .. '/' .. pyname)
- if
- path_bin ~= vim.fs.normalize(python_exe)
- and vim.list_contains(python_multiple, path_bin)
- and executable(path_bin)
- then
- python_multiple[#python_multiple + 1] = path_bin
- end
- end
-
- if vim.tbl_count(python_multiple) > 0 then
- -- This is worth noting since the user may install something
- -- that changes $PATH, like homebrew.
- local message = 'Multiple '
- .. pyname
- .. ' executables found. '
- .. 'Set `g:'
- .. host_prog_var
- .. '` to avoid surprises.'
- info(message)
- end
-
- if python_exe:find('shims') then
- local message = '`' .. python_exe .. '` appears to be a pyenv shim.'
- local advice = '`pyenv` is not in $PATH, your pyenv installation is broken. Set `g:'
- .. host_prog_var
- .. '` to avoid surprises.'
-
- warn(message, advice)
- end
- end
- end
- end
-
- if not is_blank(python_exe) and not vim.g[host_prog_var] then
- if
- is_blank(venv)
- and not is_blank(pyenv)
- and not is_blank(pyenv_root)
- and vim.startswith(vim.fn.resolve(python_exe), pyenv_root .. '/')
- then
- local advice = 'Create a virtualenv specifically for Nvim using pyenv, and set `g:'
- .. host_prog_var
- .. '`. This will avoid the need to install the pynvim module in each version/virtualenv.'
- warn('pyenv is not set up optimally.', advice)
- elseif not is_blank(venv) then
- local venv_root
- if not is_blank(pyenv_root) then
- venv_root = pyenv_root
- else
- venv_root = vim.fs.dirname(venv)
- end
-
- if vim.startswith(vim.fn.resolve(python_exe), venv_root .. '/') then
- local advice = 'Create a virtualenv specifically for Nvim and use `g:'
- .. host_prog_var
- .. '`. This will avoid the need to install the pynvim module in each virtualenv.'
- warn('Your virtualenv is not set up optimally.', advice)
- end
- end
- end
-
- if is_blank(python_exe) and not is_blank(pyname) then
- -- An error message should have already printed.
- error('`' .. pyname .. '` was not found.')
- elseif not is_blank(python_exe) and not check_bin(python_exe) then
- python_exe = ''
- end
-
- -- Diagnostic output
- info('Executable: ' .. (is_blank(python_exe) and 'Not found' or python_exe))
- if vim.tbl_count(python_multiple) > 0 then
- for _, path_bin in ipairs(python_multiple) do
- info('Other python executable: ' .. path_bin)
- end
- end
-
- if is_blank(python_exe) then
- -- No Python executable can import 'neovim'. Check if any Python executable
- -- can import 'pynvim'. If so, that Python failed to import 'neovim' as
- -- well, which is most probably due to a failed pip upgrade:
- -- https://github.com/neovim/neovim/wiki/Following-HEAD#20181118
- local pynvim_table = vim.fn['provider#pythonx#DetectByModule']('pynvim', 3)
- local pynvim_exe = pynvim_table[1]
- if not is_blank(pynvim_exe) then
- local message = 'Detected pip upgrade failure: Python executable can import "pynvim" but not "neovim": '
- .. pynvim_exe
- local advice = {
- 'Use that Python version to reinstall "pynvim" and optionally "neovim".',
- pynvim_exe .. ' -m pip uninstall pynvim neovim',
- pynvim_exe .. ' -m pip install pynvim',
- pynvim_exe .. ' -m pip install neovim # only if needed by third-party software',
- }
- error(message, advice)
- end
- else
- local version_info_table = version_info(python_exe)
- local majorpyversion = version_info_table[1]
- local current = version_info_table[2]
- local latest = version_info_table[3]
- local status = version_info_table[4]
-
- if vim.fn.str2nr(majorpyversion) ~= 3 then
- warn('Unexpected Python version. This could lead to confusing error messages.')
- end
-
- info('Python version: ' .. majorpyversion)
-
- if is_bad_response(status) then
- info('pynvim version: ' .. current .. ' (' .. status .. ')')
- else
- info('pynvim version: ' .. current)
- end
-
- if is_bad_response(current) then
- error(
- 'pynvim is not installed.\nError: ' .. current,
- 'Run in shell: ' .. python_exe .. ' -m pip install pynvim'
- )
- end
-
- if is_bad_response(latest) then
- warn('Could not contact PyPI to get latest version.')
- error('HTTP request failed: ' .. latest)
- elseif is_bad_response(status) then
- warn('Latest pynvim is NOT installed: ' .. latest)
- elseif not is_bad_response(current) then
- ok('Latest pynvim is installed.')
- end
- end
-
- start('Python virtualenv')
- if not virtual_env then
- ok('no $VIRTUAL_ENV')
- return
- end
- local errors = {}
- -- Keep hints as dict keys in order to discard duplicates.
- local hints = {}
- -- The virtualenv should contain some Python executables, and those
- -- executables should be first both on Nvim's $PATH and the $PATH of
- -- subshells launched from Nvim.
- local bin_dir = iswin and 'Scripts' or 'bin'
- local venv_bins = vim.tbl_filter(function(v)
- -- XXX: Remove irrelevant executables found in bin/.
- return not v:match('python%-config')
- end, vim.fn.glob(string.format('%s/%s/python*', virtual_env, bin_dir), true, true))
- if vim.tbl_count(venv_bins) > 0 then
- for _, venv_bin in pairs(venv_bins) do
- venv_bin = vim.fs.normalize(venv_bin)
- local py_bin_basename = vim.fs.basename(venv_bin)
- local nvim_py_bin = python_exepath(vim.fn.exepath(py_bin_basename))
- local subshell_py_bin = python_exepath(py_bin_basename)
- if venv_bin ~= nvim_py_bin then
- errors[#errors + 1] = '$PATH yields this '
- .. py_bin_basename
- .. ' executable: '
- .. nvim_py_bin
- local hint = '$PATH ambiguities arise if the virtualenv is not '
- .. 'properly activated prior to launching Nvim. Close Nvim, activate the virtualenv, '
- .. 'check that invoking Python from the command line launches the correct one, '
- .. 'then relaunch Nvim.'
- hints[hint] = true
- end
- if venv_bin ~= subshell_py_bin then
- errors[#errors + 1] = '$PATH in subshells yields this '
- .. py_bin_basename
- .. ' executable: '
- .. subshell_py_bin
- local hint = '$PATH ambiguities in subshells typically are '
- .. 'caused by your shell config overriding the $PATH previously set by the '
- .. 'virtualenv. Either prevent them from doing so, or use this workaround: '
- .. 'https://vi.stackexchange.com/a/34996'
- hints[hint] = true
- end
- end
- else
- errors[#errors + 1] = 'no Python executables found in the virtualenv '
- .. bin_dir
- .. ' directory.'
- end
-
- local msg = '$VIRTUAL_ENV is set to: ' .. virtual_env
- if vim.tbl_count(errors) > 0 then
- if vim.tbl_count(venv_bins) > 0 then
- msg = msg
- .. '\nAnd its '
- .. bin_dir
- .. ' directory contains: '
- .. vim.fn.join(vim.fn.map(venv_bins, [[fnamemodify(v:val, ':t')]]), ', ')
- end
- local conj = '\nBut '
- for _, err in ipairs(errors) do
- msg = msg .. conj .. err
- conj = '\nAnd '
- end
- msg = msg .. '\nSo invoking Python may lead to unexpected results.'
- warn(msg, vim.fn.keys(hints))
- else
- info(msg)
- info(
- 'Python version: '
- .. system('python -c "import platform, sys; sys.stdout.write(platform.python_version())"')
- )
- ok('$VIRTUAL_ENV provides :!python.')
- end
-end
-
-local function ruby()
- start('Ruby provider (optional)')
-
- if disabled_via_loaded_var('ruby') then
- return
- end
-
- if not executable('ruby') or not executable('gem') then
- warn(
- '`ruby` and `gem` must be in $PATH.',
- 'Install Ruby and verify that `ruby` and `gem` commands work.'
- )
- return
- end
- info('Ruby: ' .. system({ 'ruby', '-v' }))
-
- local ruby_detect_table = vim.fn['provider#ruby#Detect']()
- local host = ruby_detect_table[1]
- if is_blank(host) then
- warn('`neovim-ruby-host` not found.', {
- 'Run `gem install neovim` to ensure the neovim RubyGem is installed.',
- 'Run `gem environment` to ensure the gem bin directory is in $PATH.',
- 'If you are using rvm/rbenv/chruby, try "rehashing".',
- 'See :help g:ruby_host_prog for non-standard gem installations.',
- 'You may disable this provider (and warning) by adding `let g:loaded_ruby_provider = 0` to your init.vim',
- })
- return
- end
- info('Host: ' .. host)
-
- local latest_gem_cmd = (iswin and 'cmd /c gem list -ra "^^neovim$"' or 'gem list -ra ^neovim$')
- local latest_gem = system(vim.fn.split(latest_gem_cmd))
- if shell_error() or is_blank(latest_gem) then
- error(
- 'Failed to run: ' .. latest_gem_cmd,
- { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' }
- )
- return
- end
- local gem_split = vim.split(latest_gem, [[neovim (\|, \|)$]])
- latest_gem = gem_split[1] or 'not found'
-
- local current_gem_cmd = { host, '--version' }
- local current_gem = system(current_gem_cmd)
- if shell_error() then
- error(
- 'Failed to run: ' .. table.concat(current_gem_cmd, ' '),
- { 'Report this issue with the output of: ', table.concat(current_gem_cmd, ' ') }
- )
- return
- end
-
- if vim.version.lt(current_gem, latest_gem) then
- local message = 'Gem "neovim" is out-of-date. Installed: '
- .. current_gem
- .. ', latest: '
- .. latest_gem
- warn(message, 'Run in shell: gem update neovim')
- else
- ok('Latest "neovim" gem is installed: ' .. current_gem)
- end
-end
-
-local function node()
- start('Node.js provider (optional)')
-
- if disabled_via_loaded_var('node') then
- return
- end
-
- if
- not executable('node')
- or (not executable('npm') and not executable('yarn') and not executable('pnpm'))
- then
- warn(
- '`node` and `npm` (or `yarn`, `pnpm`) must be in $PATH.',
- 'Install Node.js and verify that `node` and `npm` (or `yarn`, `pnpm`) commands work.'
- )
- return
- end
-
- -- local node_v = vim.fn.split(system({'node', '-v'}), "\n")[1] or ''
- local node_v = system({ 'node', '-v' })
- info('Node.js: ' .. node_v)
- if shell_error() or vim.version.lt(node_v, '6.0.0') then
- warn('Nvim node.js host does not support Node ' .. node_v)
- -- Skip further checks, they are nonsense if nodejs is too old.
- return
- end
- if vim.fn['provider#node#can_inspect']() == 0 then
- warn(
- 'node.js on this system does not support --inspect-brk so $NVIM_NODE_HOST_DEBUG is ignored.'
- )
- end
-
- local node_detect_table = vim.fn['provider#node#Detect']()
- local host = node_detect_table[1]
- if is_blank(host) then
- warn('Missing "neovim" npm (or yarn, pnpm) package.', {
- 'Run in shell: npm install -g neovim',
- 'Run in shell (if you use yarn): yarn global add neovim',
- 'Run in shell (if you use pnpm): pnpm install -g neovim',
- 'You may disable this provider (and warning) by adding `let g:loaded_node_provider = 0` to your init.vim',
- })
- return
- end
- info('Nvim node.js host: ' .. host)
-
- local manager = 'npm'
- if executable('yarn') then
- manager = 'yarn'
- elseif executable('pnpm') then
- manager = 'pnpm'
- end
-
- local latest_npm_cmd = (
- iswin and 'cmd /c ' .. manager .. ' info neovim --json' or manager .. ' info neovim --json'
- )
- local latest_npm = system(vim.fn.split(latest_npm_cmd))
- if shell_error() or is_blank(latest_npm) then
- error(
- 'Failed to run: ' .. latest_npm_cmd,
- { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' }
- )
- return
- end
-
- local pcall_ok, output = pcall(vim.fn.json_decode, latest_npm)
- local pkg_data
- if pcall_ok then
- pkg_data = output
- else
- return 'error: ' .. latest_npm
- end
- local latest_npm_subtable = pkg_data['dist-tags'] or {}
- latest_npm = latest_npm_subtable['latest'] or 'unable to parse'
-
- local current_npm_cmd = { 'node', host, '--version' }
- local current_npm = system(current_npm_cmd)
- if shell_error() then
- error(
- 'Failed to run: ' .. table.concat(current_npm_cmd, ' '),
- { 'Report this issue with the output of: ', table.concat(current_npm_cmd, ' ') }
- )
- return
- end
-
- if latest_npm ~= 'unable to parse' and vim.version.lt(current_npm, latest_npm) then
- local message = 'Package "neovim" is out-of-date. Installed: '
- .. current_npm
- .. ' latest: '
- .. latest_npm
- warn(message, {
- 'Run in shell: npm install -g neovim',
- 'Run in shell (if you use yarn): yarn global add neovim',
- 'Run in shell (if you use pnpm): pnpm install -g neovim',
- })
- else
- ok('Latest "neovim" npm/yarn/pnpm package is installed: ' .. current_npm)
- end
-end
-
-local function perl()
- start('Perl provider (optional)')
-
- if disabled_via_loaded_var('perl') then
- return
- end
-
- local perl_detect_table = vim.fn['provider#perl#Detect']()
- local perl_exec = perl_detect_table[1]
- local perl_warnings = perl_detect_table[2]
-
- if is_blank(perl_exec) then
- if not is_blank(perl_warnings) then
- warn(perl_warnings, {
- 'See :help provider-perl for more information.',
- 'You may disable this provider (and warning) by adding `let g:loaded_perl_provider = 0` to your init.vim',
- })
- else
- warn('No usable perl executable found')
- end
- return
- end
-
- info('perl executable: ' .. perl_exec)
-
- -- we cannot use cpanm that is on the path, as it may not be for the perl
- -- set with g:perl_host_prog
- system({ perl_exec, '-W', '-MApp::cpanminus', '-e', '' })
- if shell_error() then
- return { perl_exec, '"App::cpanminus" module is not installed' }
- end
-
- local latest_cpan_cmd = {
- perl_exec,
- '-MApp::cpanminus::script',
- '-e',
- 'my $app = App::cpanminus::script->new; $app->parse_options ("--info", "-q", "Neovim::Ext"); exit $app->doit',
- }
-
- local latest_cpan = system(latest_cpan_cmd)
- if shell_error() or is_blank(latest_cpan) then
- error(
- 'Failed to run: ' .. table.concat(latest_cpan_cmd, ' '),
- { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' }
- )
- return
- elseif latest_cpan[1] == '!' then
- local cpanm_errs = vim.split(latest_cpan, '!')
- if cpanm_errs[1]:find("Can't write to ") then
- local advice = {}
- for i = 2, #cpanm_errs do
- advice[#advice + 1] = cpanm_errs[i]
- end
-
- warn(cpanm_errs[1], advice)
- -- Last line is the package info
- latest_cpan = cpanm_errs[#cpanm_errs]
- else
- error('Unknown warning from command: ' .. latest_cpan_cmd, cpanm_errs)
- return
- end
- end
- latest_cpan = vim.fn.matchstr(latest_cpan, [[\(\.\?\d\)\+]])
- if is_blank(latest_cpan) then
- error('Cannot parse version number from cpanm output: ' .. latest_cpan)
- return
- end
-
- local current_cpan_cmd = { perl_exec, '-W', '-MNeovim::Ext', '-e', 'print $Neovim::Ext::VERSION' }
- local current_cpan = system(current_cpan_cmd)
- if shell_error() then
- error(
- 'Failed to run: ' .. table.concat(current_cpan_cmd, ' '),
- { 'Report this issue with the output of: ', table.concat(current_cpan_cmd, ' ') }
- )
- return
- end
-
- if vim.version.lt(current_cpan, latest_cpan) then
- local message = 'Module "Neovim::Ext" is out-of-date. Installed: '
- .. current_cpan
- .. ', latest: '
- .. latest_cpan
- warn(message, 'Run in shell: cpanm -n Neovim::Ext')
- else
- ok('Latest "Neovim::Ext" cpan module is installed: ' .. current_cpan)
- end
-end
-
-function M.check()
- clipboard()
- python()
- ruby()
- node()
- perl()
-end
-
-return M
diff --git a/runtime/lua/provider/node/health.lua b/runtime/lua/provider/node/health.lua
new file mode 100644
index 0000000000..a434f8a92b
--- /dev/null
+++ b/runtime/lua/provider/node/health.lua
@@ -0,0 +1,105 @@
+local health = vim.health
+local executable = health.executable
+local iswin = vim.loop.os_uname().sysname == 'Windows_NT'
+
+local M = {}
+
+function M.check()
+ health.start('Node.js provider (optional)')
+
+ if health.provider_disabled('node') then
+ return
+ end
+
+ if
+ not executable('node')
+ or (not executable('npm') and not executable('yarn') and not executable('pnpm'))
+ then
+ health.warn(
+ '`node` and `npm` (or `yarn`, `pnpm`) must be in $PATH.',
+ 'Install Node.js and verify that `node` and `npm` (or `yarn`, `pnpm`) commands work.'
+ )
+ return
+ end
+
+ -- local node_v = vim.fn.split(system({'node', '-v'}), "\n")[1] or ''
+ local ok, node_v = health.cmd_ok({ 'node', '-v' })
+ health.info('Node.js: ' .. node_v)
+ if not ok or vim.version.lt(node_v, '6.0.0') then
+ health.warn('Nvim node.js host does not support Node ' .. node_v)
+ -- Skip further checks, they are nonsense if nodejs is too old.
+ return
+ end
+ if vim.fn['provider#node#can_inspect']() == 0 then
+ health.warn(
+ 'node.js on this system does not support --inspect-brk so $NVIM_NODE_HOST_DEBUG is ignored.'
+ )
+ end
+
+ local node_detect_table = vim.fn['provider#node#Detect']()
+ local host = node_detect_table[1]
+ if host:find('^%s*$') then
+ health.warn('Missing "neovim" npm (or yarn, pnpm) package.', {
+ 'Run in shell: npm install -g neovim',
+ 'Run in shell (if you use yarn): yarn global add neovim',
+ 'Run in shell (if you use pnpm): pnpm install -g neovim',
+ 'You may disable this provider (and warning) by adding `let g:loaded_node_provider = 0` to your init.vim',
+ })
+ return
+ end
+ health.info('Nvim node.js host: ' .. host)
+
+ local manager = 'npm'
+ if executable('yarn') then
+ manager = 'yarn'
+ elseif executable('pnpm') then
+ manager = 'pnpm'
+ end
+
+ local latest_npm_cmd = (
+ iswin and 'cmd /c ' .. manager .. ' info neovim --json' or manager .. ' info neovim --json'
+ )
+ local latest_npm
+ ok, latest_npm = health.cmd_ok(vim.split(latest_npm_cmd, ' '))
+ if not ok or latest_npm:find('^%s$') then
+ health.error(
+ 'Failed to run: ' .. latest_npm_cmd,
+ { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' }
+ )
+ return
+ end
+
+ local pcall_ok, pkg_data = pcall(vim.json.decode, latest_npm)
+ if not pcall_ok then
+ return 'error: ' .. latest_npm
+ end
+ local latest_npm_subtable = pkg_data['dist-tags'] or {}
+ latest_npm = latest_npm_subtable['latest'] or 'unable to parse'
+
+ local current_npm_cmd = { 'node', host, '--version' }
+ local current_npm
+ ok, current_npm = health.cmd_ok(current_npm_cmd)
+ if not ok then
+ health.error(
+ 'Failed to run: ' .. table.concat(current_npm_cmd, ' '),
+ { 'Report this issue with the output of: ', table.concat(current_npm_cmd, ' ') }
+ )
+ return
+ end
+
+ if latest_npm ~= 'unable to parse' and vim.version.lt(current_npm, latest_npm) then
+ local message = 'Package "neovim" is out-of-date. Installed: '
+ .. current_npm
+ .. ' latest: '
+ .. latest_npm
+ health.warn(message({
+ 'Run in shell: npm install -g neovim',
+ 'Run in shell (if you use yarn): yarn global add neovim',
+ 'Run in shell (if you use pnpm): pnpm install -g neovim',
+ }))
+ else
+ health.ok('Latest "neovim" npm/yarn/pnpm package is installed: ' .. current_npm)
+ end
+end
+
+return M
diff --git a/runtime/lua/provider/perl/health.lua b/runtime/lua/provider/perl/health.lua
new file mode 100644
index 0000000000..535093d793
--- /dev/null
+++ b/runtime/lua/provider/perl/health.lua
@@ -0,0 +1,90 @@
+local health = vim.health
+
+local M = {}
+
+function M.check()
+ health.start('Perl provider (optional)')
+
+ if health.provider_disabled('perl') then
+ return
+ end
+
+ local perl_exec, perl_warnings = vim.provider.perl.detect()
+
+ if not perl_exec then
+ health.warn(assert(perl_warnings), {
+ 'See :help provider-perl for more information.',
+ 'You may disable this provider (and warning) by adding `let g:loaded_perl_provider = 0` to your init.vim',
+ })
+ health.warn('No usable perl executable found')
+ return
+ end
+
+ health.info('perl executable: ' .. perl_exec)
+
+ -- we cannot use cpanm that is on the path, as it may not be for the perl
+ -- set with g:perl_host_prog
+ local ok = health.cmd_ok({ perl_exec, '-W', '-MApp::cpanminus', '-e', '' })
+ if not ok then
+ return { perl_exec, '"App::cpanminus" module is not installed' }
+ end
+
+ local latest_cpan_cmd = {
+ perl_exec,
+ '-MApp::cpanminus::fatscript',
+ '-e',
+ 'my $app = App::cpanminus::script->new; $app->parse_options ("--info", "-q", "Neovim::Ext"); exit $app->doit',
+ }
+ local latest_cpan
+ ok, latest_cpan = health.cmd_ok(latest_cpan_cmd)
+ if not ok or latest_cpan:find('^%s*$') then
+ health.error(
+ 'Failed to run: ' .. table.concat(latest_cpan_cmd, ' '),
+ { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' }
+ )
+ return
+ elseif latest_cpan[1] == '!' then
+ local cpanm_errs = vim.split(latest_cpan, '!')
+ if cpanm_errs[1]:find("Can't write to ") then
+ local advice = {}
+ for i = 2, #cpanm_errs do
+ advice[#advice + 1] = cpanm_errs[i]
+ end
+
+ health.warn(cpanm_errs[1], advice)
+ -- Last line is the package info
+ latest_cpan = cpanm_errs[#cpanm_errs]
+ else
+ health.error('Unknown warning from command: ' .. latest_cpan_cmd, cpanm_errs)
+ return
+ end
+ end
+ latest_cpan = vim.fn.matchstr(latest_cpan, [[\(\.\?\d\)\+]])
+ if latest_cpan:find('^%s*$') then
+ health.error('Cannot parse version number from cpanm output: ' .. latest_cpan)
+ return
+ end
+
+ local current_cpan_cmd = { perl_exec, '-W', '-MNeovim::Ext', '-e', 'print $Neovim::Ext::VERSION' }
+ local current_cpan
+ ok, current_cpan = health.cmd_ok(current_cpan_cmd)
+ if not ok then
+ health.error(
+ 'Failed to run: ' .. table.concat(current_cpan_cmd, ' '),
+ { 'Report this issue with the output of: ', table.concat(current_cpan_cmd, ' ') }
+ )
+ return
+ end
+
+ if vim.version.lt(current_cpan, latest_cpan) then
+ local message = 'Module "Neovim::Ext" is out-of-date. Installed: '
+ .. current_cpan
+ .. ', latest: '
+ .. latest_cpan
+ health.warn(message, 'Run in shell: cpanm -n Neovim::Ext')
+ else
+ health.ok('Latest "Neovim::Ext" cpan module is installed: ' .. current_cpan)
+ end
+end
+
+return M
diff --git a/runtime/lua/provider/python/health.lua b/runtime/lua/provider/python/health.lua
new file mode 100644
index 0000000000..333890b62b
--- /dev/null
+++ b/runtime/lua/provider/python/health.lua
@@ -0,0 +1,500 @@
+local health = vim.health
+local executable = health.executable
+local iswin = vim.loop.os_uname().sysname == 'Windows_NT'
+
+local M = {}
+
+local function is(path, ty)
+ if not path then
+ return false
+ end
+ local stat = vim.loop.fs_stat(path)
+ if not stat then
+ return false
+ end
+ return stat.type == ty
+end
+
+-- Resolves Python executable path by invoking and checking `sys.executable`.
+local function python_exepath(invocation)
+ local p = vim.system({ invocation, '-c', 'import sys; sys.stdout.write(sys.executable)' }):wait()
+ assert(p.code == 0, p.stderr)
+ return vim.fs.normalize(vim.trim(p.stdout))
+end
+
+-- Check if pyenv is available and a valid pyenv root can be found, then return
+-- their respective paths. If either of those is invalid, return two empty
+-- strings, effectively ignoring pyenv.
+local function check_for_pyenv()
+ local pyenv_path = vim.fn.resolve(vim.fn.exepath('pyenv'))
+
+ if pyenv_path == '' then
+ return { '', '' }
+ end
+
+ health.info('pyenv: Path: ' .. pyenv_path)
+
+ local pyenv_root = vim.fn.resolve(os.getenv('PYENV_ROOT') or '')
+
+ if pyenv_root == '' then
+ pyenv_root = vim.fn.system({ pyenv_path, 'root' })
+ health.info('pyenv: $PYENV_ROOT is not set. Infer from `pyenv root`.')
+ end
+
+ if not is(pyenv_root, 'directory') then
+ local message = string.format(
+ 'pyenv: Root does not exist: %s. Ignoring pyenv for all following checks.',
+ pyenv_root
+ )
+ health.warn(message)
+ return { '', '' }
+ end
+
+ health.info('pyenv: Root: ' .. pyenv_root)
+
+ return { pyenv_path, pyenv_root }
+end
+
+-- Check the Python interpreter's usability.
+local function check_bin(bin)
+ if not is(bin, 'file') and (not iswin or not is(bin .. '.exe', 'file')) then
+ health.error('"' .. bin .. '" was not found.')
+ return false
+ elseif not executable(bin) then
+ health.error('"' .. bin .. '" is not executable.')
+ return false
+ end
+ return true
+end
+
+-- Fetch the contents of a URL.
+local function download(url)
+ local has_curl = executable('curl')
+ if has_curl and vim.fn.system({ 'curl', '-V' }):find('Protocols:.*https') then
+ local out, rc = health.system({ 'curl', '-sL', url }, { stderr = true, ignore_error = true })
+ if rc ~= 0 then
+ return 'curl error with ' .. url .. ': ' .. rc
+ else
+ return out
+ end
+ elseif executable('python') then
+ local script = "try:\n\
+ from urllib.request import urlopen\n\
+ except ImportError:\n\
+ from urllib2 import urlopen\n\
+ response = urlopen('" .. url .. "')\n\
+ print(response.read().decode('utf8'))\n"
+ local out, rc = health.system({ 'python', '-c', script })
+ if out == '' and rc ~= 0 then
+ return 'python urllib.request error: ' .. rc
+ else
+ return out
+ end
+ end
+
+ local message = 'missing `curl` '
+
+ if has_curl then
+ message = message .. '(with HTTPS support) '
+ end
+ message = message .. 'and `python`, cannot make web request'
+
+ return message
+end
+
+-- Get the latest Nvim Python client (pynvim) version from PyPI.
+local function latest_pypi_version()
+ local pypi_version = 'unable to get pypi response'
+ local pypi_response = download('https://pypi.python.org/pypi/pynvim/json')
+ if pypi_response ~= '' then
+ local pcall_ok, output = pcall(vim.fn.json_decode, pypi_response)
+ local pypi_data
+ if pcall_ok then
+ pypi_data = output
+ else
+ return 'error: ' .. pypi_response
+ end
+
+ local pypi_element = pypi_data['info'] or {}
+ pypi_version = pypi_element['version'] or 'unable to parse'
+ end
+ return pypi_version
+end
+
+local function is_bad_response(s)
+ local lower = s:lower()
+ return vim.startswith(lower, 'unable')
+ or vim.startswith(lower, 'error')
+ or vim.startswith(lower, 'outdated')
+end
+
+-- Get version information using the specified interpreter. The interpreter is
+-- used directly in case breaking changes were introduced since the last time
+-- Nvim's Python client was updated.
+--
+-- Returns: {
+-- {python executable version},
+-- {current nvim version},
+-- {current pypi nvim status},
+-- {installed version status}
+-- }
+local function version_info(python)
+ local pypi_version = latest_pypi_version()
+
+ local python_version, rc = health.system({
+ python,
+ '-c',
+ 'import sys; print(".".join(str(x) for x in sys.version_info[:3]))',
+ })
+
+ if rc ~= 0 or python_version == '' then
+ python_version = 'unable to parse ' .. python .. ' response'
+ end
+
+ local nvim_path
+ nvim_path, rc = health.system({
+ python,
+ '-c',
+ 'import sys; sys.path = [p for p in sys.path if p != ""]; import neovim; print(neovim.__file__)',
+ })
+ if rc ~= 0 or nvim_path == '' then
+ return { python_version, 'unable to load neovim Python module', pypi_version, nvim_path }
+ end
+
+ -- Assuming that multiple versions of a package are installed, sort them
+ -- numerically in descending order.
+ local function compare(metapath1, metapath2)
+ local a = vim.fn.matchstr(vim.fn.fnamemodify(metapath1, ':p:h:t'), [[[0-9.]\+]])
+ local b = vim.fn.matchstr(vim.fn.fnamemodify(metapath2, ':p:h:t'), [[[0-9.]\+]])
+ if a == b then
+ return 0
+ elseif a > b then
+ return 1
+ else
+ return -1
+ end
+ end
+
+ -- Try to get neovim.VERSION (added in 0.1.11dev).
+ local nvim_version
+ nvim_version, rc = health.system({
+ python,
+ '-c',
+ 'from neovim import VERSION as v; print("{}.{}.{}{}".format(v.major, v.minor, v.patch, v.prerelease))',
+ }, { stderr = true, ignore_error = true })
+ if rc ~= 0 or nvim_version == '' then
+ nvim_version = 'unable to find pynvim module version'
+ local base = vim.fs.basename(nvim_path)
+ local metas = vim.fn.glob(base .. '-*/METADATA', 1, 1)
+ vim.list_extend(metas, vim.fn.glob(base .. '-*/PKG-INFO', 1, 1))
+ vim.list_extend(metas, vim.fn.glob(base .. '.egg-info/PKG-INFO', 1, 1))
+ metas = table.sort(metas, compare)
+
+ if metas and next(metas) ~= nil then
+ for line in io.lines(metas[1]) do
+ local version = line:match('^Version: (%S+)')
+ if version then
+ nvim_version = version
+ break
+ end
+ end
+ end
+ end
+
+ local nvim_path_base = vim.fn.fnamemodify(nvim_path, [[:~:h]])
+ local version_status = 'unknown; ' .. nvim_path_base
+ if is_bad_response(nvim_version) and is_bad_response(pypi_version) then
+ if vim.version.lt(nvim_version, pypi_version) then
+ version_status = 'outdated; from ' .. nvim_path_base
+ else
+ version_status = 'up to date'
+ end
+ end
+
+ return { python_version, nvim_version, pypi_version, version_status }
+end
+
+function M.check()
+ health.start('Python 3 provider (optional)')
+
+ local pyname = 'python3' ---@type string?
+ local python_exe = ''
+ local virtual_env = os.getenv('VIRTUAL_ENV')
+ local venv = virtual_env and vim.fn.resolve(virtual_env) or ''
+ local host_prog_var = pyname .. '_host_prog'
+ local python_multiple = {}
+
+ if health.provider_disabled(pyname) then
+ return
+ end
+
+ local pyenv_table = check_for_pyenv()
+ local pyenv = pyenv_table[1]
+ local pyenv_root = pyenv_table[2]
+
+ if vim.g[host_prog_var] then
+ local message = string.format('Using: g:%s = "%s"', host_prog_var, vim.g[host_prog_var])
+ health.info(message)
+ end
+
+ local pythonx_warnings
+ pyname, pythonx_warnings = vim.provider.python.detect_by_module('neovim')
+
+ if not pyname then
+ health.warn(
+ 'No Python executable found that can `import neovim`. '
+ .. 'Using the first available executable for diagnostics.'
+ )
+ elseif vim.g[host_prog_var] then
+ python_exe = pyname
+ end
+
+ -- No Python executable could `import neovim`, or host_prog_var was used.
+ if pythonx_warnings then
+ health.warn(pythonx_warnings, {
+ 'See :help provider-python for more information.',
+ 'You may disable this provider (and warning) by adding `let g:loaded_python3_provider = 0` to your init.vim',
+ })
+ elseif pyname and pyname ~= '' and python_exe == '' then
+ if not vim.g[host_prog_var] then
+ local message = string.format(
+ '`g:%s` is not set. Searching for %s in the environment.',
+ host_prog_var,
+ pyname
+ )
+ health.info(message)
+ end
+
+ if pyenv ~= '' then
+ python_exe = health.system({ pyenv, 'which', pyname }, { stderr = true })
+ if python_exe == '' then
+ health.warn('pyenv could not find ' .. pyname .. '.')
+ end
+ end
+
+ if python_exe == '' then
+ python_exe = vim.fn.exepath(pyname)
+
+ if os.getenv('PATH') then
+ local path_sep = iswin and ';' or ':'
+ local paths = vim.split(os.getenv('PATH') or '', path_sep)
+
+ for _, path in ipairs(paths) do
+ local path_bin = vim.fs.normalize(path .. '/' .. pyname)
+ if
+ path_bin ~= vim.fs.normalize(python_exe)
+ and vim.tbl_contains(python_multiple, path_bin)
+ and executable(path_bin)
+ then
+ python_multiple[#python_multiple + 1] = path_bin
+ end
+ end
+
+ if vim.tbl_count(python_multiple) > 0 then
+ -- This is worth noting since the user may install something
+ -- that changes $PATH, like homebrew.
+ local message = string.format(
+ 'Multiple %s executables found. Set `g:%s` to avoid surprises.',
+ pyname,
+ host_prog_var
+ )
+ health.info(message)
+ end
+
+ if python_exe:find('shims') then
+ local message = string.format('`%s` appears to be a pyenv shim.', python_exe)
+ local advice = string.format(
+ '`pyenv` is not in $PATH, your pyenv installation is broken. Set `g:%s` to avoid surprises.',
+ host_prog_var
+ )
+ health.warn(message, advice)
+ end
+ end
+ end
+ end
+
+ if python_exe ~= '' and not vim.g[host_prog_var] then
+ if
+ venv == ''
+ and pyenv ~= ''
+ and pyenv_root ~= ''
+ and vim.startswith(vim.fn.resolve(python_exe), pyenv_root .. '/')
+ then
+ local advice = string.format(
+ 'Create a virtualenv specifically for Nvim using pyenv, and set `g:%s`. This will avoid the need to install the pynvim module in each version/virtualenv.',
+ host_prog_var
+ )
+ health.warn('pyenv is not set up optimally.', advice)
+ elseif venv ~= '' then
+ local venv_root
+ if pyenv_root ~= '' then
+ venv_root = pyenv_root
+ else
+ venv_root = vim.fs.dirname(venv)
+ end
+
+ if vim.startswith(vim.fn.resolve(python_exe), venv_root .. '/') then
+ local advice = string.format(
+ 'Create a virtualenv specifically for Nvim and use `g:%s`. This will avoid the need to install the pynvim module in each virtualenv.',
+ host_prog_var
+ )
+ health.warn('Your virtualenv is not set up optimally.', advice)
+ end
+ end
+ end
+
+ if pyname and python_exe == '' and pyname ~= '' then
+ -- An error message should have already printed.
+ health.error('`' .. pyname .. '` was not found.')
+ elseif python_exe ~= '' and not check_bin(python_exe) then
+ python_exe = ''
+ end
+
+ -- Diagnostic output
+ health.info('Executable: ' .. (python_exe == '' and 'Not found' or python_exe))
+ if vim.tbl_count(python_multiple) > 0 then
+ for _, path_bin in ipairs(python_multiple) do
+ health.info('Other python executable: ' .. path_bin)
+ end
+ end
+
+ if python_exe == '' then
+ -- No Python executable can import 'neovim'. Check if any Python executable
+ -- can import 'pynvim'. If so, that Python failed to import 'neovim' as
+ -- well, which is most probably due to a failed pip upgrade:
+ -- https://github.com/neovim/neovim/wiki/Following-HEAD#20181118
+ local pynvim_exe = vim.provider.python.detect_by_module('pynvim')
+ if pynvim_exe then
+ local message = 'Detected pip upgrade failure: Python executable can import "pynvim" but not "neovim": '
+ .. pynvim_exe
+ local advice = {
+ 'Use that Python version to reinstall "pynvim" and optionally "neovim".',
+ pynvim_exe .. ' -m pip uninstall pynvim neovim',
+ pynvim_exe .. ' -m pip install pynvim',
+ pynvim_exe .. ' -m pip install neovim # only if needed by third-party software',
+ }
+ health.error(message, advice)
+ end
+ else
+ local version_info_table = version_info(python_exe)
+ local pyversion = version_info_table[1]
+ local current = version_info_table[2]
+ local latest = version_info_table[3]
+ local status = version_info_table[4]
+
+ if not vim.version.range('~3'):has(pyversion) then
+ health.warn('Unexpected Python version. This could lead to confusing error messages.')
+ end
+
+ health.info('Python version: ' .. pyversion)
+
+ if is_bad_response(status) then
+ health.info('pynvim version: ' .. current .. ' (' .. status .. ')')
+ else
+ health.info('pynvim version: ' .. current)
+ end
+
+ if is_bad_response(current) then
+ health.error(
+ 'pynvim is not installed.\nError: ' .. current,
+ 'Run in shell: ' .. python_exe .. ' -m pip install pynvim'
+ )
+ end
+
+ if is_bad_response(latest) then
+ health.warn('Could not contact PyPI to get latest version.')
+ health.error('HTTP request failed: ' .. latest)
+ elseif is_bad_response(status) then
+ health.warn('Latest pynvim is NOT installed: ' .. latest)
+ elseif not is_bad_response(current) then
+ health.ok('Latest pynvim is installed.')
+ end
+ end
+
+ health.start('Python virtualenv')
+ if not virtual_env then
+ health.ok('no $VIRTUAL_ENV')
+ return
+ end
+ local errors = {}
+ -- Keep hints as dict keys in order to discard duplicates.
+ local hints = {}
+ -- The virtualenv should contain some Python executables, and those
+ -- executables should be first both on Nvim's $PATH and the $PATH of
+ -- subshells launched from Nvim.
+ local bin_dir = iswin and 'Scripts' or 'bin'
+ local venv_bins = vim.fn.glob(string.format('%s/%s/python*', virtual_env, bin_dir), true, true)
+ venv_bins = vim.tbl_filter(function(v)
+ -- XXX: Remove irrelevant executables found in bin/.
+ return not v:match('python%-config')
+ end, venv_bins)
+ if vim.tbl_count(venv_bins) > 0 then
+ for _, venv_bin in pairs(venv_bins) do
+ venv_bin = vim.fs.normalize(venv_bin)
+ local py_bin_basename = vim.fs.basename(venv_bin)
+ local nvim_py_bin = python_exepath(vim.fn.exepath(py_bin_basename))
+ local subshell_py_bin = python_exepath(py_bin_basename)
+ if venv_bin ~= nvim_py_bin then
+ errors[#errors + 1] = '$PATH yields this '
+ .. py_bin_basename
+ .. ' executable: '
+ .. nvim_py_bin
+ local hint = '$PATH ambiguities arise if the virtualenv is not '
+ .. 'properly activated prior to launching Nvim. Close Nvim, activate the virtualenv, '
+ .. 'check that invoking Python from the command line launches the correct one, '
+ .. 'then relaunch Nvim.'
+ hints[hint] = true
+ end
+ if venv_bin ~= subshell_py_bin then
+ errors[#errors + 1] = '$PATH in subshells yields this '
+ .. py_bin_basename
+ .. ' executable: '
+ .. subshell_py_bin
+ local hint = '$PATH ambiguities in subshells typically are '
+ .. 'caused by your shell config overriding the $PATH previously set by the '
+ .. 'virtualenv. Either prevent them from doing so, or use this workaround: '
+ .. 'https://vi.stackexchange.com/a/34996'
+ hints[hint] = true
+ end
+ end
+ else
+ errors[#errors + 1] = 'no Python executables found in the virtualenv '
+ .. bin_dir
+ .. ' directory.'
+ end
+
+ local msg = '$VIRTUAL_ENV is set to: ' .. virtual_env
+ if vim.tbl_count(errors) > 0 then
+ if vim.tbl_count(venv_bins) > 0 then
+ msg = string.format(
+ '%s\nAnd its %s directory contains: %s',
+ msg,
+ bin_dir,
+ table.concat(
+ vim.tbl_map(function(v)
+ return vim.fn.fnamemodify(v, ':t')
+ end, venv_bins),
+ ', '
+ )
+ )
+ end
+ local conj = '\nBut '
+ for _, err in ipairs(errors) do
+ msg = msg .. conj .. err
+ conj = '\nAnd '
+ end
+ msg = msg .. '\nSo invoking Python may lead to unexpected results.'
+ health.warn(msg, vim.tbl_keys(hints))
+ else
+ health.info(msg)
+ health.info(
+ 'Python version: '
+ .. health.system(
+ 'python -c "import platform, sys; sys.stdout.write(platform.python_version())"'
+ )
+ )
+ health.ok('$VIRTUAL_ENV provides :!python.')
+ end
+end
+
+return M
diff --git a/runtime/lua/provider/ruby/health.lua b/runtime/lua/provider/ruby/health.lua
new file mode 100644
index 0000000000..04f6e303e6
--- /dev/null
+++ b/runtime/lua/provider/ruby/health.lua
@@ -0,0 +1,71 @@
+local health = vim.health
+local executable = health.executable
+local iswin = vim.loop.os_uname().sysname == 'Windows_NT'
+
+local M = {}
+
+function M.check()
+ health.start('Ruby provider (optional)')
+
+ if health.provider_disabled('ruby') then
+ return
+ end
+
+ if not executable('ruby') or not executable('gem') then
+ health.warn(
+ '`ruby` and `gem` must be in $PATH.',
+ 'Install Ruby and verify that `ruby` and `gem` commands work.'
+ )
+ return
+ end
+ health.info('Ruby: ' .. health.system({ 'ruby', '-v' }))
+
+ local ruby_detect_table = vim.provider.ruby.detect()
+ local host = ruby_detect_table[1]
+ if (not host) or host:find('^%s*$') then
+ health.warn('`neovim-ruby-host` not found.', {
+ 'Run `gem install neovim` to ensure the neovim RubyGem is installed.',
+ 'Run `gem environment` to ensure the gem bin directory is in $PATH.',
+ 'If you are using rvm/rbenv/chruby, try "rehashing".',
+ 'See :help g:ruby_host_prog for non-standard gem installations.',
+ 'You may disable this provider (and warning) by adding `let g:loaded_ruby_provider = 0` to your init.vim',
+ })
+ return
+ end
+ health.info('Host: ' .. host)
+
+ local latest_gem_cmd = (iswin and 'cmd /c gem list -ra "^^neovim$"' or 'gem list -ra ^neovim$')
+ local ok, latest_gem = health.cmd_ok(vim.split(latest_gem_cmd, ' '))
+ if not ok or latest_gem:find('^%s*$') then
+ health.error(
+ 'Failed to run: ' .. latest_gem_cmd,
+ { "Make sure you're connected to the internet.", 'Are you behind a firewall or proxy?' }
+ )
+ return
+ end
+ local gem_split = vim.split(latest_gem, [[neovim (\|, \|)$]])
+ latest_gem = gem_split[1] or 'not found'
+
+ local current_gem_cmd = { host, '--version' }
+ local current_gem
+ ok, current_gem = health.cmd_ok(current_gem_cmd)
+ if not ok then
+ health.error(
+ 'Failed to run: ' .. table.concat(current_gem_cmd, ' '),
+ { 'Report this issue with the output of: ', table.concat(current_gem_cmd, ' ') }
+ )
+ return
+ end
+
+ if vim.version.lt(current_gem, latest_gem) then
+ local message = 'Gem "neovim" is out-of-date. Installed: '
+ .. current_gem
+ .. ', latest: '
+ .. latest_gem
+ health.warn(message, 'Run in shell: gem update neovim')
+ else
+ health.ok('Latest "neovim" gem is installed: ' .. current_gem)
+ end
+end
+
+return M
diff --git a/runtime/lua/tohtml.lua b/runtime/lua/tohtml.lua
new file mode 100644
index 0000000000..505de720ba
--- /dev/null
+++ b/runtime/lua/tohtml.lua
@@ -0,0 +1,1349 @@
+--- @brief
+---<pre>help
+---:TOhtml {file} *:TOhtml*
+---Converts the buffer shown in the current window to HTML, opens the generated
+---HTML in a new split window, and saves its contents to {file}. If {file} is not
+---given, a temporary file (created by |tempname()|) is used.
+---</pre>
+
+-- The HTML conversion script is different from Vim's one. If you want to use
+-- Vim's TOhtml converter, download it from the vim GitHub repo.
+-- Here are the Vim files related to this functionality:
+-- - https://github.com/vim/vim/blob/master/runtime/syntax/2html.vim
+-- - https://github.com/vim/vim/blob/master/runtime/autoload/tohtml.vim
+-- - https://github.com/vim/vim/blob/master/runtime/plugin/tohtml.vim
+--
+-- Main differences between this and the vim version:
+-- - No "ignore some visual thing" settings (just set the right Vim option)
+-- - No support for legacy web engines
+-- - No support for legacy encoding (supports only UTF-8)
+-- - No interactive webpage
+-- - No specifying the internal HTML (no XHTML, no use_css=false)
+-- - No multiwindow diffs
+-- - No ranges
+--
+-- Remarks:
+-- - Not all visuals are supported, so it may differ.
+
+--- @class (private) vim.tohtml.state.global
+--- @field background string
+--- @field foreground string
+--- @field title string|false
+--- @field font string
+--- @field highlights_name table<integer,string>
+--- @field conf vim.tohtml.opt
+
+--- @class (private) vim.tohtml.state:vim.tohtml.state.global
+--- @field style vim.tohtml.styletable
+--- @field tabstop string|false
+--- @field opt vim.wo
+--- @field winid integer
+--- @field bufnr integer
+--- @field width integer
+--- @field buflen integer
+
+--- @class (private) vim.tohtml.styletable
+--- @field [integer] vim.tohtml.line (integer: (1-index, exclusive))
+
+--- @class (private) vim.tohtml.line
+--- @field virt_lines {[integer]:{[1]:string,[2]:integer}[]}
+--- @field pre_text string[][]
+--- @field hide? boolean
+--- @field [integer] vim.tohtml.cell? (integer: (1-index, exclusive))
+
+--- @class (private) vim.tohtml.cell
+--- @field [1] integer[] start
+--- @field [2] integer[] close
+--- @field [3] any[][] virt_text
+--- @field [4] any[][] overlay_text
+
+local HIDE_ID = -1
+-- stylua: ignore start
+local cterm_8_to_hex={
+ [0] = "#808080", "#ff6060", "#00ff00", "#ffff00",
+ "#8080ff", "#ff40ff", "#00ffff", "#ffffff",
+}
+local cterm_16_to_hex={
+ [0] = "#000000", "#c00000", "#008000", "#804000",
+ "#0000c0", "#c000c0", "#008080", "#c0c0c0",
+ "#808080", "#ff6060", "#00ff00", "#ffff00",
+ "#8080ff", "#ff40ff", "#00ffff", "#ffffff",
+}
+local cterm_88_to_hex={
+ [0] = "#000000", "#c00000", "#008000", "#804000",
+ "#0000c0", "#c000c0", "#008080", "#c0c0c0",
+ "#808080", "#ff6060", "#00ff00", "#ffff00",
+ "#8080ff", "#ff40ff", "#00ffff", "#ffffff",
+ "#000000", "#00008b", "#0000cd", "#0000ff",
+ "#008b00", "#008b8b", "#008bcd", "#008bff",
+ "#00cd00", "#00cd8b", "#00cdcd", "#00cdff",
+ "#00ff00", "#00ff8b", "#00ffcd", "#00ffff",
+ "#8b0000", "#8b008b", "#8b00cd", "#8b00ff",
+ "#8b8b00", "#8b8b8b", "#8b8bcd", "#8b8bff",
+ "#8bcd00", "#8bcd8b", "#8bcdcd", "#8bcdff",
+ "#8bff00", "#8bff8b", "#8bffcd", "#8bffff",
+ "#cd0000", "#cd008b", "#cd00cd", "#cd00ff",
+ "#cd8b00", "#cd8b8b", "#cd8bcd", "#cd8bff",
+ "#cdcd00", "#cdcd8b", "#cdcdcd", "#cdcdff",
+ "#cdff00", "#cdff8b", "#cdffcd", "#cdffff",
+ "#ff0000", "#ff008b", "#ff00cd", "#ff00ff",
+ "#ff8b00", "#ff8b8b", "#ff8bcd", "#ff8bff",
+ "#ffcd00", "#ffcd8b", "#ffcdcd", "#ffcdff",
+ "#ffff00", "#ffff8b", "#ffffcd", "#ffffff",
+ "#2e2e2e", "#5c5c5c", "#737373", "#8b8b8b",
+ "#a2a2a2", "#b9b9b9", "#d0d0d0", "#e7e7e7",
+}
+local cterm_256_to_hex={
+ [0] = "#000000", "#c00000", "#008000", "#804000",
+ "#0000c0", "#c000c0", "#008080", "#c0c0c0",
+ "#808080", "#ff6060", "#00ff00", "#ffff00",
+ "#8080ff", "#ff40ff", "#00ffff", "#ffffff",
+ "#000000", "#00005f", "#000087", "#0000af",
+ "#0000d7", "#0000ff", "#005f00", "#005f5f",
+ "#005f87", "#005faf", "#005fd7", "#005fff",
+ "#008700", "#00875f", "#008787", "#0087af",
+ "#0087d7", "#0087ff", "#00af00", "#00af5f",
+ "#00af87", "#00afaf", "#00afd7", "#00afff",
+ "#00d700", "#00d75f", "#00d787", "#00d7af",
+ "#00d7d7", "#00d7ff", "#00ff00", "#00ff5f",
+ "#00ff87", "#00ffaf", "#00ffd7", "#00ffff",
+ "#5f0000", "#5f005f", "#5f0087", "#5f00af",
+ "#5f00d7", "#5f00ff", "#5f5f00", "#5f5f5f",
+ "#5f5f87", "#5f5faf", "#5f5fd7", "#5f5fff",
+ "#5f8700", "#5f875f", "#5f8787", "#5f87af",
+ "#5f87d7", "#5f87ff", "#5faf00", "#5faf5f",
+ "#5faf87", "#5fafaf", "#5fafd7", "#5fafff",
+ "#5fd700", "#5fd75f", "#5fd787", "#5fd7af",
+ "#5fd7d7", "#5fd7ff", "#5fff00", "#5fff5f",
+ "#5fff87", "#5fffaf", "#5fffd7", "#5fffff",
+ "#870000", "#87005f", "#870087", "#8700af",
+ "#8700d7", "#8700ff", "#875f00", "#875f5f",
+ "#875f87", "#875faf", "#875fd7", "#875fff",
+ "#878700", "#87875f", "#878787", "#8787af",
+ "#8787d7", "#8787ff", "#87af00", "#87af5f",
+ "#87af87", "#87afaf", "#87afd7", "#87afff",
+ "#87d700", "#87d75f", "#87d787", "#87d7af",
+ "#87d7d7", "#87d7ff", "#87ff00", "#87ff5f",
+ "#87ff87", "#87ffaf", "#87ffd7", "#87ffff",
+ "#af0000", "#af005f", "#af0087", "#af00af",
+ "#af00d7", "#af00ff", "#af5f00", "#af5f5f",
+ "#af5f87", "#af5faf", "#af5fd7", "#af5fff",
+ "#af8700", "#af875f", "#af8787", "#af87af",
+ "#af87d7", "#af87ff", "#afaf00", "#afaf5f",
+ "#afaf87", "#afafaf", "#afafd7", "#afafff",
+ "#afd700", "#afd75f", "#afd787", "#afd7af",
+ "#afd7d7", "#afd7ff", "#afff00", "#afff5f",
+ "#afff87", "#afffaf", "#afffd7", "#afffff",
+ "#d70000", "#d7005f", "#d70087", "#d700af",
+ "#d700d7", "#d700ff", "#d75f00", "#d75f5f",
+ "#d75f87", "#d75faf", "#d75fd7", "#d75fff",
+ "#d78700", "#d7875f", "#d78787", "#d787af",
+ "#d787d7", "#d787ff", "#d7af00", "#d7af5f",
+ "#d7af87", "#d7afaf", "#d7afd7", "#d7afff",
+ "#d7d700", "#d7d75f", "#d7d787", "#d7d7af",
+ "#d7d7d7", "#d7d7ff", "#d7ff00", "#d7ff5f",
+ "#d7ff87", "#d7ffaf", "#d7ffd7", "#d7ffff",
+ "#ff0000", "#ff005f", "#ff0087", "#ff00af",
+ "#ff00d7", "#ff00ff", "#ff5f00", "#ff5f5f",
+ "#ff5f87", "#ff5faf", "#ff5fd7", "#ff5fff",
+ "#ff8700", "#ff875f", "#ff8787", "#ff87af",
+ "#ff87d7", "#ff87ff", "#ffaf00", "#ffaf5f",
+ "#ffaf87", "#ffafaf", "#ffafd7", "#ffafff",
+ "#ffd700", "#ffd75f", "#ffd787", "#ffd7af",
+ "#ffd7d7", "#ffd7ff", "#ffff00", "#ffff5f",
+ "#ffff87", "#ffffaf", "#ffffd7", "#ffffff",
+ "#080808", "#121212", "#1c1c1c", "#262626",
+ "#303030", "#3a3a3a", "#444444", "#4e4e4e",
+ "#585858", "#626262", "#6c6c6c", "#767676",
+ "#808080", "#8a8a8a", "#949494", "#9e9e9e",
+ "#a8a8a8", "#b2b2b2", "#bcbcbc", "#c6c6c6",
+ "#d0d0d0", "#dadada", "#e4e4e4", "#eeeeee",
+}
+-- stylua: ignore end
+
+--- @type table<integer,string>
+local cterm_color_cache = {}
+--- @type string?
+local background_color_cache = nil
+--- @type string?
+local foreground_color_cache = nil
+
+--- @see https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Operating-System-Commands
+--- @param color "background"|"foreground"|integer
+--- @return string?
+local function try_query_terminal_color(color)
+ local parameter = 4
+ if color == 'foreground' then
+ parameter = 10
+ elseif color == 'background' then
+ parameter = 11
+ end
+ --- @type string?
+ local hex = nil
+ local au = vim.api.nvim_create_autocmd('TermResponse', {
+ once = true,
+ callback = function(args)
+ hex = '#'
+ .. table.concat({ args.data:match('\027%]%d+;%d*;?rgb:(%w%w)%w%w/(%w%w)%w%w/(%w%w)%w%w') })
+ end,
+ })
+ if type(color) == 'number' then
+ io.stdout:write(('\027]%s;%s;?\027\\'):format(parameter, color))
+ else
+ io.stdout:write(('\027]%s;?\027\\'):format(parameter))
+ end
+ vim.wait(100, function()
+ return hex and true or false
+ end)
+ pcall(vim.api.nvim_del_autocmd, au)
+ return hex
+end
+
+--- @param colorstr string
+--- @return string
+local function cterm_to_hex(colorstr)
+ if colorstr:sub(1, 1) == '#' then
+ return colorstr
+ end
+ assert(colorstr ~= '')
+ local color = tonumber(colorstr)
+ assert(color and 0 <= color and color <= 255)
+ if cterm_color_cache[color] then
+ return cterm_color_cache[color]
+ end
+ local hex = try_query_terminal_color(color)
+ if hex then
+ cterm_color_cache[color] = hex
+ else
+ vim.notify_once("Info(TOhtml): Couldn't get terminal colors, using fallback")
+ local t_Co = tonumber(vim.api.nvim_eval('&t_Co'))
+ if t_Co <= 8 then
+ cterm_color_cache = cterm_8_to_hex
+ elseif t_Co == 88 then
+ cterm_color_cache = cterm_88_to_hex
+ elseif t_Co == 256 then
+ cterm_color_cache = cterm_256_to_hex
+ else
+ cterm_color_cache = cterm_16_to_hex
+ end
+ end
+ return cterm_color_cache[color]
+end
+
+--- @return string
+local function get_background_color()
+ local bg = vim.fn.synIDattr(vim.fn.hlID('Normal'), 'bg#')
+ if bg ~= '' then
+ return cterm_to_hex(bg)
+ end
+ if background_color_cache then
+ return background_color_cache
+ end
+ local hex = try_query_terminal_color('background')
+ if not hex or not hex:match('#%x%x%x%x%x%x') then
+ vim.notify_once("Info(TOhtml): Couldn't get terminal background colors, using fallback")
+ hex = vim.o.background == 'light' and '#ffffff' or '#000000'
+ end
+ background_color_cache = hex
+ return hex
+end
+
+--- @return string
+local function get_foreground_color()
+ local fg = vim.fn.synIDattr(vim.fn.hlID('Normal'), 'fg#')
+ if fg ~= '' then
+ return cterm_to_hex(fg)
+ end
+ if foreground_color_cache then
+ return foreground_color_cache
+ end
+ local hex = try_query_terminal_color('foreground')
+ if not hex or not hex:match('#%x%x%x%x%x%x') then
+ vim.notify_once("Info(TOhtml): Couldn't get terminal foreground colors, using fallback")
+ hex = vim.o.background == 'light' and '#000000' or '#ffffff'
+ end
+ foreground_color_cache = hex
+ return hex
+end
+
+--- @param style_line vim.tohtml.line
+--- @param col integer (1-index)
+--- @param field integer
+--- @param val any
+local function _style_line_insert(style_line, col, field, val)
+ if style_line[col] == nil then
+ style_line[col] = { {}, {}, {}, {} }
+ end
+ table.insert(style_line[col][field], val)
+end
+
+--- @param style_line vim.tohtml.line
+--- @param col integer (1-index)
+--- @param val any[]
+local function style_line_insert_overlay_char(style_line, col, val)
+ _style_line_insert(style_line, col, 4, val)
+end
+
+--- @param style_line vim.tohtml.line
+--- @param col integer (1-index)
+--- @param val any[]
+local function style_line_insert_virt_text(style_line, col, val)
+ _style_line_insert(style_line, col, 3, val)
+end
+
+--- @param state vim.tohtml.state
+--- @param hl string|integer|nil
+--- @return nil|integer
+local function register_hl(state, hl)
+ if type(hl) == 'nil' then
+ return
+ elseif type(hl) == 'string' then
+ hl = vim.fn.hlID(hl)
+ assert(hl ~= 0)
+ end
+ hl = vim.fn.synIDtrans(hl)
+ if not state.highlights_name[hl] then
+ local name = vim.fn.synIDattr(hl, 'name')
+ assert(name ~= '')
+ state.highlights_name[hl] = name
+ end
+ return hl
+end
+
+--- @param state vim.tohtml.state
+--- @param start_row integer (1-index)
+--- @param start_col integer (1-index)
+--- @param end_row integer (1-index)
+--- @param end_col integer (1-index)
+--- @param conceal_text string
+--- @param hl_group string|integer?
+local function styletable_insert_conceal(
+ state,
+ start_row,
+ start_col,
+ end_row,
+ end_col,
+ conceal_text,
+ hl_group
+)
+ assert(state.opt.conceallevel > 0)
+ local styletable = state.style
+ if start_col == end_col and start_row == end_row then
+ return
+ end
+ if state.opt.conceallevel == 1 and conceal_text == '' then
+ conceal_text = vim.opt_local.listchars:get().conceal or ' '
+ end
+ local hlid = register_hl(state, hl_group)
+ if vim.wo[state.winid].conceallevel ~= 3 then
+ _style_line_insert(styletable[start_row], start_col, 3, { conceal_text, hlid })
+ end
+ _style_line_insert(styletable[start_row], start_col, 1, HIDE_ID)
+ _style_line_insert(styletable[end_row], end_col, 2, HIDE_ID)
+end
+
+--- @param state vim.tohtml.state
+--- @param start_row integer (1-index)
+--- @param start_col integer (1-index)
+--- @param end_row integer (1-index)
+--- @param end_col integer (1-index)
+--- @param hl_group string|integer|nil
+local function styletable_insert_range(state, start_row, start_col, end_row, end_col, hl_group)
+ if start_col == end_col and start_row == end_row or not hl_group then
+ return
+ end
+ local styletable = state.style
+ _style_line_insert(styletable[start_row], start_col, 1, hl_group)
+ _style_line_insert(styletable[end_row], end_col, 2, hl_group)
+end
+
+--- @param bufnr integer
+--- @return vim.tohtml.styletable
+local function generate_styletable(bufnr)
+ --- @type vim.tohtml.styletable
+ local styletable = {}
+ for row = 1, vim.api.nvim_buf_line_count(bufnr) + 1 do
+ styletable[row] = { virt_lines = {}, pre_text = {} }
+ end
+ return styletable
+end
+
+--- @param state vim.tohtml.state
+local function styletable_syntax(state)
+ for row = 1, state.buflen do
+ local prev_id = 0
+ local prev_col = nil
+ for col = 1, #vim.fn.getline(row) + 1 do
+ local hlid = vim.fn.synID(row, col, 1)
+ hlid = hlid == 0 and 0 or assert(register_hl(state, hlid))
+ if hlid ~= prev_id then
+ if prev_id ~= 0 then
+ styletable_insert_range(state, row, assert(prev_col), row, col, prev_id)
+ end
+ prev_col = col
+ prev_id = hlid
+ end
+ end
+ end
+end
+
+--- @param state vim.tohtml.state
+local function styletable_diff(state)
+ local styletable = state.style
+ for row = 1, state.buflen do
+ local style_line = styletable[row]
+ local filler = vim.fn.diff_filler(row)
+ if filler ~= 0 then
+ local fill = (vim.opt_local.fillchars:get().diff or '-')
+ table.insert(
+ style_line.virt_lines,
+ { { fill:rep(state.width), register_hl(state, 'DiffDelete') } }
+ )
+ end
+ if row == state.buflen + 1 then
+ break
+ end
+ local prev_id = 0
+ local prev_col = nil
+ for col = 1, #vim.fn.getline(row) do
+ local hlid = vim.fn.diff_hlID(row, col)
+ hlid = hlid == 0 and 0 or assert(register_hl(state, hlid))
+ if hlid ~= prev_id then
+ if prev_id ~= 0 then
+ styletable_insert_range(state, row, assert(prev_col), row, col, prev_id)
+ end
+ prev_col = col
+ prev_id = hlid
+ end
+ end
+ if prev_id ~= 0 then
+ styletable_insert_range(state, row, assert(prev_col), row, #vim.fn.getline(row) + 1, prev_id)
+ end
+ end
+end
+
+--- @param state vim.tohtml.state
+local function styletable_treesitter(state)
+ local bufnr = state.bufnr
+ local buf_highlighter = vim.treesitter.highlighter.active[bufnr]
+ if not buf_highlighter then
+ return
+ end
+ buf_highlighter.tree:parse(true)
+ buf_highlighter.tree:for_each_tree(function(tstree, tree)
+ --- @cast tree vim.treesitter.LanguageTree
+ if not tstree then
+ return
+ end
+ local root = tstree:root()
+ local q = buf_highlighter:get_query(tree:lang())
+ --- @type vim.treesitter.Query?
+ local query = q:query()
+ if not query then
+ return
+ end
+ for capture, node, metadata in query:iter_captures(root, buf_highlighter.bufnr, 0, state.buflen) do
+ local srow, scol, erow, ecol = node:range()
+ --- @diagnostic disable-next-line: invisible
+ local c = q._query.captures[capture]
+ if c ~= nil then
+ local hlid = register_hl(state, '@' .. c .. '.' .. tree:lang())
+ if metadata.conceal and state.opt.conceallevel ~= 0 then
+ styletable_insert_conceal(state, srow + 1, scol + 1, erow + 1, ecol + 1, metadata.conceal)
+ end
+ styletable_insert_range(state, srow + 1, scol + 1, erow + 1, ecol + 1, hlid)
+ end
+ end
+ end)
+end
+
+--- @param state vim.tohtml.state
+--- @param extmark {[1]:integer,[2]:integer,[3]:integer,[4]:vim.api.keyset.set_extmark|any}
+--- @param namespaces table<integer,string>
+local function _styletable_extmarks_highlight(state, extmark, namespaces)
+ if not extmark[4].hl_group then
+ return
+ end
+ ---TODO(altermo) LSP semantic tokens (and some other extmarks) are only
+ ---generated in visible lines, and not in the whole buffer.
+ if (namespaces[extmark[4].ns_id] or ''):find('vim_lsp_semantic_tokens') then
+ vim.notify_once('Info(TOhtml): lsp semantic tokens are not supported, HTML may be incorrect')
+ return
+ end
+ local srow, scol, erow, ecol =
+ extmark[2], extmark[3], extmark[4].end_row or extmark[2], extmark[4].end_col or extmark[3]
+ if scol == ecol and srow == erow then
+ return
+ end
+ local hlid = register_hl(state, extmark[4].hl_group)
+ styletable_insert_range(state, srow + 1, scol + 1, erow + 1, ecol + 1, hlid)
+end
+
+--- @param state vim.tohtml.state
+--- @param extmark {[1]:integer,[2]:integer,[3]:integer,[4]:vim.api.keyset.set_extmark|any}
+local function _styletable_extmarks_virt_text(state, extmark)
+ if not extmark[4].virt_text then
+ return
+ end
+ local styletable = state.style
+ --- @type integer,integer
+ local row, col = extmark[2], extmark[3]
+ if
+ extmark[4].virt_text_pos == 'inline'
+ or extmark[4].virt_text_pos == 'eol'
+ or extmark[4].virt_text_pos == 'overlay'
+ then
+ if extmark[4].virt_text_pos == 'eol' then
+ style_line_insert_virt_text(styletable[row + 1], #vim.fn.getline(row + 1) + 1, { ' ' })
+ end
+ local virt_text_len = 0
+ for _, i in
+ ipairs(extmark[4].virt_text --[[@as (string[][])]])
+ do
+ local hlid = register_hl(state, i[2])
+ if extmark[4].virt_text_pos == 'eol' then
+ style_line_insert_virt_text(
+ styletable[row + 1],
+ #vim.fn.getline(row + 1) + 1,
+ { i[1], hlid }
+ )
+ else
+ style_line_insert_virt_text(styletable[row + 1], col + 1, { i[1], hlid })
+ end
+ virt_text_len = virt_text_len + #i[1]
+ end
+ if extmark[4].virt_text_pos == 'overlay' then
+ styletable_insert_range(state, row + 1, col + 1, row + 1, col + virt_text_len + 1, HIDE_ID)
+ end
+ end
+ local not_supported = {
+ virt_text_pos = 'right_align',
+ hl_mode = 'blend',
+ hl_group = 'combine',
+ }
+ for opt, val in ipairs(not_supported) do
+ if extmark[4][opt] == val then
+ vim.notify_once(
+ ('Info(TOhtml): extmark.%s="%s" is not supported, HTML may be incorrect'):format(opt, val)
+ )
+ end
+ end
+end
+
+--- @param state vim.tohtml.state
+--- @param extmark {[1]:integer,[2]:integer,[3]:integer,[4]:vim.api.keyset.set_extmark|any}
+local function _styletable_extmarks_virt_lines(state, extmark)
+ ---TODO(altermo) if the fold start is equal to virt_line start then the fold hides the virt_line
+ if not extmark[4].virt_lines then
+ return
+ end
+ --- @type integer
+ local row = extmark[2] + (extmark[4].virt_lines_above and 1 or 2)
+ for _, line in
+ ipairs(extmark[4].virt_lines --[[@as (string[][][])]])
+ do
+ local virt_line = {}
+ for _, i in ipairs(line) do
+ local hlid = register_hl(state, i[2])
+ table.insert(virt_line, { i[1], hlid })
+ end
+ table.insert(state.style[row].virt_lines, virt_line)
+ end
+end
+
+--- @param state vim.tohtml.state
+--- @param extmark {[1]:integer,[2]:integer,[3]:integer,[4]:vim.api.keyset.set_extmark|any}
+local function _styletable_extmarks_conceal(state, extmark)
+ if not extmark[4].conceal or state.opt.conceallevel == 0 then
+ return
+ end
+ local srow, scol, erow, ecol =
+ extmark[2], extmark[3], extmark[4].end_row or extmark[2], extmark[4].end_col or extmark[3]
+ styletable_insert_conceal(
+ state,
+ srow + 1,
+ scol + 1,
+ erow + 1,
+ ecol + 1,
+ extmark[4].conceal,
+ extmark[4].hl_group or 'Conceal'
+ )
+end
+
+--- @param state vim.tohtml.state
+local function styletable_extmarks(state)
+ --TODO(altermo) extmarks may have col/row which is outside of the buffer, which could cause an error
+ local bufnr = state.bufnr
+ local extmarks = vim.api.nvim_buf_get_extmarks(bufnr, -1, 0, -1, { details = true })
+ local namespaces = {} --- @type table<integer, string>
+ for ns, ns_id in pairs(vim.api.nvim_get_namespaces()) do
+ namespaces[ns_id] = ns
+ end
+ for _, v in ipairs(extmarks) do
+ _styletable_extmarks_highlight(state, v, namespaces)
+ end
+ for _, v in ipairs(extmarks) do
+ _styletable_extmarks_conceal(state, v)
+ end
+ for _, v in ipairs(extmarks) do
+ _styletable_extmarks_virt_text(state, v)
+ end
+ for _, v in ipairs(extmarks) do
+ _styletable_extmarks_virt_lines(state, v)
+ end
+end
+
+--- @param state vim.tohtml.state
+local function styletable_folds(state)
+ local styletable = state.style
+ local has_folded = false
+ for row = 1, state.buflen do
+ if vim.fn.foldclosed(row) > 0 then
+ has_folded = true
+ styletable[row].hide = true
+ end
+ if vim.fn.foldclosed(row) == row then
+ local hlid = register_hl(state, 'Folded')
+ ---TODO(altermo): Is there a way to get highlighted foldtext?
+ local foldtext = vim.fn.foldtextresult(row)
+ foldtext = foldtext .. (vim.opt.fillchars:get().fold or '·'):rep(state.width - #foldtext)
+ table.insert(styletable[row].virt_lines, { { foldtext, hlid } })
+ end
+ end
+ if has_folded and type(({ pcall(vim.api.nvim_eval, vim.o.foldtext) })[2]) == 'table' then
+ vim.notify_once(
+ 'Info(TOhtml): foldtext returning a table is half supported, HTML may be incorrect'
+ )
+ end
+end
+
+--- @param state vim.tohtml.state
+local function styletable_conceal(state)
+ local bufnr = state.bufnr
+ vim.api.nvim_buf_call(bufnr, function()
+ for row = 1, state.buflen do
+ --- @type table<integer,{[1]:integer,[2]:integer,[3]:string}>
+ local conceals = {}
+ local line_len_exclusive = #vim.fn.getline(row) + 1
+ for col = 1, line_len_exclusive do
+ --- @type integer,string,integer
+ local is_concealed, conceal, hlid = unpack(vim.fn.synconcealed(row, col) --[[@as table]])
+ if is_concealed == 0 then
+ assert(true)
+ elseif not conceals[hlid] then
+ conceals[hlid] = { col, math.min(col + 1, line_len_exclusive), conceal }
+ else
+ conceals[hlid][2] = math.min(col + 1, line_len_exclusive)
+ end
+ end
+ for _, v in pairs(conceals) do
+ styletable_insert_conceal(state, row, v[1], row, v[2], v[3], 'Conceal')
+ end
+ end
+ end)
+end
+
+--- @param state vim.tohtml.state
+local function styletable_match(state)
+ for _, match in
+ ipairs(vim.fn.getmatches(state.winid) --[[@as (table[])]])
+ do
+ local hlid = register_hl(state, match.group)
+ local function range(srow, scol, erow, ecol)
+ if match.group == 'Conceal' and state.opt.conceallevel ~= 0 then
+ styletable_insert_conceal(state, srow, scol, erow, ecol, match.conceal or '', hlid)
+ else
+ styletable_insert_range(state, srow, scol, erow, ecol, hlid)
+ end
+ end
+ if match.pos1 then
+ for key, v in
+ pairs(match --[[@as (table<string,integer[]>)]])
+ do
+ if not key:match('^pos(%d+)$') then
+ assert(true)
+ elseif #v == 1 then
+ range(v[1], 1, v[1], #vim.fn.getline(v[1]) + 1)
+ else
+ range(v[1], v[2], v[1], v[3] + v[2])
+ end
+ end
+ else
+ for _, v in
+ ipairs(vim.fn.matchbufline(state.bufnr, match.pattern, 1, '$') --[[@as (table[])]])
+ do
+ range(v.lnum, v.byteidx + 1, v.lnum, v.byteidx + 1 + #v.text)
+ end
+ end
+ end
+end
+
+--- Requires state.conf.number_lines to be set to true
+--- @param state vim.tohtml.state
+local function styletable_statuscolumn(state)
+ if not state.conf.number_lines then
+ return
+ end
+ local statuscolumn = state.opt.statuscolumn
+
+ if statuscolumn == '' then
+ if state.opt.relativenumber then
+ if state.opt.number then
+ statuscolumn = '%C%s%{%v:lnum!=line(".")?"%=".v:relnum." ":v:lnum%}'
+ else
+ statuscolumn = '%C%s%{%"%=".v:relnum." "%}'
+ end
+ else
+ statuscolumn = '%C%s%{%"%=".v:lnum." "%}'
+ end
+ end
+ local minwidth = 0
+
+ local signcolumn = state.opt.signcolumn
+ if state.opt.number or state.opt.relativenumber then
+ minwidth = minwidth + state.opt.numberwidth
+ if signcolumn == 'number' then
+ signcolumn = 'no'
+ end
+ end
+ if signcolumn == 'number' then
+ signcolumn = 'auto'
+ end
+ if signcolumn ~= 'no' then
+ local max = tonumber(signcolumn:match('^%w-:(%d)')) or 1
+ if signcolumn:match('^auto') then
+ --- @type table<integer,integer>
+ local signcount = {}
+ for _, extmark in
+ ipairs(vim.api.nvim_buf_get_extmarks(state.bufnr, -1, 0, -1, { details = true }))
+ do
+ if extmark[4].sign_text then
+ signcount[extmark[2]] = (signcount[extmark[2]] or 0) + 1
+ end
+ end
+ local maxsigns = 0
+ for _, v in pairs(signcount) do
+ if v > maxsigns then
+ maxsigns = v
+ end
+ end
+ minwidth = minwidth + math.min(maxsigns, max) * 2
+ else
+ minwidth = minwidth + max * 2
+ end
+ end
+
+ local foldcolumn = state.opt.foldcolumn
+ if foldcolumn ~= '0' then
+ if foldcolumn:match('^auto') then
+ local max = tonumber(foldcolumn:match('^%w-:(%d)')) or 1
+ local maxfold = 0
+ vim.api.nvim_buf_call(state.bufnr, function()
+ for row = 1, vim.api.nvim_buf_line_count(state.bufnr) do
+ local foldlevel = vim.fn.foldlevel(row)
+ if foldlevel > maxfold then
+ maxfold = foldlevel
+ end
+ end
+ end)
+ minwidth = minwidth + math.min(maxfold, max)
+ else
+ minwidth = minwidth + tonumber(foldcolumn)
+ end
+ end
+
+ --- @type table<integer,any>
+ local statuses = {}
+ for row = 1, state.buflen do
+ local status = vim.api.nvim_eval_statusline(
+ statuscolumn,
+ { winid = state.winid, use_statuscol_lnum = row, highlights = true }
+ )
+ local width = vim.api.nvim_strwidth(status.str)
+ if width > minwidth then
+ minwidth = width
+ end
+ table.insert(statuses, status)
+ --- @type string
+ end
+ for row, status in pairs(statuses) do
+ --- @type string
+ local str = status.str
+ --- @type table[]
+ local hls = status.highlights
+ for k, v in ipairs(hls) do
+ local text = str:sub(v.start + 1, hls[k + 1] and hls[k + 1].start or nil)
+ if k == #hls then
+ text = text .. (' '):rep(minwidth - vim.api.nvim_strwidth(str))
+ end
+ if text ~= '' then
+ local hlid = register_hl(state, v.group)
+ local virt_text = { text, hlid }
+ table.insert(state.style[row].pre_text, virt_text)
+ end
+ end
+ end
+end
+
+--- @param state vim.tohtml.state
+local function styletable_listchars(state)
+ if not state.opt.list then
+ return
+ end
+ --- @return string
+ local function utf8_sub(str, i, j)
+ return vim.fn.strcharpart(str, i - 1, j and j - i + 1 or nil)
+ end
+ local len = vim.api.nvim_strwidth
+ --- @type table<string,string>
+ local listchars = vim.opt_local.listchars:get()
+ local ids = setmetatable({}, {
+ __index = function(t, k)
+ rawset(t, k, register_hl(state, k))
+ return rawget(t, k)
+ end,
+ })
+
+ if listchars.eol then
+ for row = 1, state.buflen do
+ local style_line = state.style[row]
+ style_line_insert_overlay_char(
+ style_line,
+ #vim.fn.getline(row) + 1,
+ { listchars.eol, ids.NonText }
+ )
+ end
+ end
+
+ if listchars.tab and state.tabstop then
+ for _, match in
+ ipairs(vim.fn.matchbufline(state.bufnr, '\t', 1, '$') --[[@as (table[])]])
+ do
+ --- @type integer
+ local tablen = #state.tabstop
+ - ((vim.fn.virtcol({ match.lnum, match.byteidx }, false, state.winid)) % #state.tabstop)
+ --- @type string?
+ local text
+ if len(listchars.tab) == 3 then
+ if tablen == 1 then
+ text = utf8_sub(listchars.tab, 3, 3)
+ else
+ text = utf8_sub(listchars.tab, 1, 1)
+ .. utf8_sub(listchars.tab, 2, 2):rep(tablen - 2)
+ .. utf8_sub(listchars.tab, 3, 3)
+ end
+ else
+ text = utf8_sub(listchars.tab, 1, 1) .. utf8_sub(listchars.tab, 2, 2):rep(tablen - 1)
+ end
+ style_line_insert_overlay_char(
+ state.style[match.lnum],
+ match.byteidx + 1,
+ { text, ids.Whitespace }
+ )
+ end
+ end
+
+ if listchars.space then
+ for _, match in
+ ipairs(vim.fn.matchbufline(state.bufnr, ' ', 1, '$') --[[@as (table[])]])
+ do
+ style_line_insert_overlay_char(
+ state.style[match.lnum],
+ match.byteidx + 1,
+ { listchars.space, ids.Whitespace }
+ )
+ end
+ end
+
+ if listchars.multispace then
+ for _, match in
+ ipairs(vim.fn.matchbufline(state.bufnr, [[ \+]], 1, '$') --[[@as (table[])]])
+ do
+ local text = utf8_sub(listchars.multispace:rep(len(match.text)), 1, len(match.text))
+ for i = 1, len(text) do
+ style_line_insert_overlay_char(
+ state.style[match.lnum],
+ match.byteidx + i,
+ { utf8_sub(text, i, i), ids.Whitespace }
+ )
+ end
+ end
+ end
+
+ if listchars.lead or listchars.leadmultispace then
+ for _, match in
+ ipairs(vim.fn.matchbufline(state.bufnr, [[^ \+]], 1, '$') --[[@as (table[])]])
+ do
+ local text = ''
+ if len(match.text) == 1 or not listchars.leadmultispace then
+ if listchars.lead then
+ text = listchars.lead:rep(len(match.text))
+ end
+ elseif listchars.leadmultispace then
+ text = utf8_sub(listchars.leadmultispace:rep(len(match.text)), 1, len(match.text))
+ end
+ for i = 1, len(text) do
+ style_line_insert_overlay_char(
+ state.style[match.lnum],
+ match.byteidx + i,
+ { utf8_sub(text, i, i), ids.Whitespace }
+ )
+ end
+ end
+ end
+
+ if listchars.trail then
+ for _, match in
+ ipairs(vim.fn.matchbufline(state.bufnr, [[ \+$]], 1, '$') --[[@as (table[])]])
+ do
+ local text = listchars.trail:rep(len(match.text))
+ for i = 1, len(text) do
+ style_line_insert_overlay_char(
+ state.style[match.lnum],
+ match.byteidx + i,
+ { utf8_sub(text, i, i), ids.Whitespace }
+ )
+ end
+ end
+ end
+
+ if listchars.nbsp then
+ for _, match in
+ ipairs(
+ vim.fn.matchbufline(state.bufnr, '\226\128\175\\|\194\160', 1, '$') --[[@as (table[])]]
+ )
+ do
+ style_line_insert_overlay_char(
+ state.style[match.lnum],
+ match.byteidx + 1,
+ { listchars.nbsp, ids.Whitespace }
+ )
+ for i = 2, #match.text do
+ style_line_insert_overlay_char(
+ state.style[match.lnum],
+ match.byteidx + i,
+ { '', ids.Whitespace }
+ )
+ end
+ end
+ end
+end
+
+--- @param name string
+--- @return string
+local function highlight_name_to_class_name(name)
+ return (name:gsub('%.', '-'):gsub('@', '-'))
+end
+
+--- @param name string
+--- @return string
+local function name_to_tag(name)
+ return '<span class="' .. highlight_name_to_class_name(name) .. '">'
+end
+
+--- @param _ string
+--- @return string
+local function name_to_closetag(_)
+ return '</span>'
+end
+
+--- @param str string
+--- @param tabstop string|false?
+--- @return string
+local function html_escape(str, tabstop)
+ str = str:gsub('&', '&amp;'):gsub('<', '&lt;'):gsub('>', '&gt;'):gsub('"', '&quot;')
+ if tabstop then
+ --- @type string
+ str = str:gsub('\t', tabstop)
+ end
+ return str
+end
+
+--- @param out string[]
+--- @param state vim.tohtml.state.global
+local function extend_style(out, state)
+ table.insert(out, '<style>')
+ table.insert(out, ('* {font-family: %s}'):format(state.font))
+ table.insert(
+ out,
+ ('body {background-color: %s; color: %s}'):format(state.background, state.foreground)
+ )
+ for hlid, name in pairs(state.highlights_name) do
+ --TODO(altermo) use local namespace (instead of global 0)
+ local fg = vim.fn.synIDattr(hlid, 'fg#')
+ local bg = vim.fn.synIDattr(hlid, 'bg#')
+ local decor_line = {}
+ if vim.fn.synIDattr(hlid, 'underline') ~= '' then
+ table.insert(decor_line, 'underline')
+ end
+ if vim.fn.synIDattr(hlid, 'strikethrough') ~= '' then
+ table.insert(decor_line, 'line-through')
+ end
+ if vim.fn.synIDattr(hlid, 'undercurl') ~= '' then
+ table.insert(decor_line, 'underline')
+ end
+ local c = {
+ color = fg ~= '' and cterm_to_hex(fg) or nil,
+ ['background-color'] = bg ~= '' and cterm_to_hex(bg) or nil,
+ ['font-style'] = vim.fn.synIDattr(hlid, 'italic') ~= '' and 'italic' or nil,
+ ['font-weight'] = vim.fn.synIDattr(hlid, 'bold') ~= '' and 'bold' or nil,
+ ['text-decoration-line'] = not vim.tbl_isempty(decor_line) and table.concat(decor_line, ' ')
+ or nil,
+ --TODO(altermo) if strikethrough and undercurl then the strikethrough becomes wavy
+ ['text-decoration-style'] = vim.fn.synIDattr(hlid, 'undercurl') ~= '' and 'wavy' or nil,
+ }
+ local attrs = {}
+ for attr, val in pairs(c) do
+ table.insert(attrs, attr .. ': ' .. val)
+ end
+ table.insert(
+ out,
+ '.' .. highlight_name_to_class_name(name) .. ' {' .. table.concat(attrs, '; ') .. '}'
+ )
+ end
+ table.insert(out, '</style>')
+end
+
+--- @param out string[]
+--- @param state vim.tohtml.state.global
+local function extend_head(out, state)
+ table.insert(out, '<head>')
+ table.insert(out, '<meta charset="UTF-8">')
+ if state.title ~= false then
+ table.insert(out, ('<title>%s</title>'):format(state.title))
+ end
+ local colorscheme = vim.api.nvim_exec2('colorscheme', { output = true }).output
+ table.insert(
+ out,
+ ('<meta name="colorscheme" content="%s"></meta>'):format(html_escape(colorscheme))
+ )
+ extend_style(out, state)
+ table.insert(out, '</head>')
+end
+
+--- @param out string[]
+--- @param state vim.tohtml.state
+--- @param row integer
+local function _extend_virt_lines(out, state, row)
+ local style_line = state.style[row]
+ for _, virt_line in ipairs(style_line.virt_lines) do
+ local virt_s = ''
+ for _, v in ipairs(virt_line) do
+ if v[2] then
+ virt_s = virt_s .. (name_to_tag(state.highlights_name[v[2]]))
+ end
+ virt_s = virt_s .. v[1]
+ if v[2] then
+ --- @type string
+ virt_s = virt_s .. (name_to_closetag(state.highlights_name[v[2]]))
+ end
+ end
+ table.insert(out, virt_s)
+ end
+end
+
+--- @param state vim.tohtml.state
+--- @param row integer
+--- @return string
+local function _pre_text_to_html(state, row)
+ local style_line = state.style[row]
+ local s = ''
+ for _, pre_text in ipairs(style_line.pre_text) do
+ if pre_text[2] then
+ s = s .. (name_to_tag(state.highlights_name[pre_text[2]]))
+ end
+ s = s .. (html_escape(pre_text[1], state.tabstop))
+ if pre_text[2] then
+ --- @type string
+ s = s .. (name_to_closetag(state.highlights_name[pre_text[2]]))
+ end
+ end
+ return s
+end
+
+--- @param state vim.tohtml.state
+--- @param char table
+--- @return string
+local function _char_to_html(state, char)
+ local s = ''
+ if char[2] then
+ s = s .. name_to_tag(state.highlights_name[char[2]])
+ end
+ s = s .. html_escape(char[1], state.tabstop)
+ if char[2] then
+ s = s .. name_to_closetag(state.highlights_name[char[2]])
+ end
+ return s
+end
+
+--- @param state vim.tohtml.state
+--- @param cell vim.tohtml.cell
+--- @return string
+local function _virt_text_to_html(state, cell)
+ local s = ''
+ for _, v in ipairs(cell[3]) do
+ if v[2] then
+ s = s .. (name_to_tag(state.highlights_name[v[2]]))
+ end
+ --- @type string
+ s = s .. html_escape(v[1], state.tabstop)
+ if v[2] then
+ s = s .. name_to_closetag(state.highlights_name[v[2]])
+ end
+ end
+ return s
+end
+
+--- @param out string[]
+--- @param state vim.tohtml.state
+local function extend_pre(out, state)
+ local styletable = state.style
+ table.insert(out, '<pre>')
+ local hide_count = 0
+ --- @type integer[]
+ local stack = {}
+
+ local function loop(row)
+ local style_line = styletable[row]
+ if style_line.hide and (styletable[row - 1] or {}).hide then
+ return
+ end
+ _extend_virt_lines(out, state, row)
+ --Possible improvement (altermo):
+ --Instead of looping over all the buffer characters per line,
+ --why not loop over all the style_line cells,
+ --and then calculating the amount of text.
+ if style_line.hide then
+ return
+ end
+ local line = vim.api.nvim_buf_get_lines(state.bufnr, row - 1, row, false)[1] or ''
+ local s = ''
+ s = s .. _pre_text_to_html(state, row)
+ for col = 1, #line + 1 do
+ local cell = style_line[col]
+ --- @type table?
+ local char
+ if cell then
+ for i = #cell[2], 1, -1 do
+ local hlid = cell[2][i]
+ if hlid < 0 then
+ if hlid == HIDE_ID then
+ hide_count = hide_count - 1
+ end
+ else
+ --- @type integer?
+ local index
+ for idx = #stack, 1, -1 do
+ s = s .. (name_to_closetag(state.highlights_name[stack[idx]]))
+ if stack[idx] == hlid then
+ index = idx
+ break
+ end
+ end
+ assert(index, 'a coles tag which has no corresponding open tag')
+ for idx = index + 1, #stack do
+ s = s .. (name_to_tag(state.highlights_name[stack[idx]]))
+ end
+ table.remove(stack, index)
+ end
+ end
+
+ for _, hlid in ipairs(cell[1]) do
+ if hlid < 0 then
+ if hlid == HIDE_ID then
+ hide_count = hide_count + 1
+ end
+ else
+ table.insert(stack, hlid)
+ s = s .. (name_to_tag(state.highlights_name[hlid]))
+ end
+ end
+
+ if cell[3] then
+ s = s .. _virt_text_to_html(state, cell)
+ end
+
+ char = cell[4][#cell[4]]
+ end
+
+ if col == #line + 1 and not char then
+ break
+ end
+
+ if hide_count == 0 then
+ s = s
+ .. _char_to_html(
+ state,
+ char
+ or { vim.api.nvim_buf_get_text(state.bufnr, row - 1, col - 1, row - 1, col, {})[1] }
+ )
+ end
+ end
+ table.insert(out, s)
+ end
+
+ for row = 1, state.buflen + 1 do
+ loop(row)
+ end
+ assert(#stack == 0, 'an open HTML tag was never closed')
+ table.insert(out, '</pre>')
+end
+
+--- @param out string[]
+--- @param fn fun()
+local function extend_body(out, fn)
+ table.insert(out, '<body style="display: flex">')
+ fn()
+ table.insert(out, '</body>')
+end
+
+--- @param out string[]
+--- @param fn fun()
+local function extend_html(out, fn)
+ table.insert(out, '<!DOCTYPE html>')
+ table.insert(out, '<html>')
+ fn()
+ table.insert(out, '</html>')
+end
+
+--- @param winid integer
+--- @param global_state vim.tohtml.state.global
+--- @return vim.tohtml.state
+local function global_state_to_state(winid, global_state)
+ local bufnr = vim.api.nvim_win_get_buf(winid)
+ local opt = global_state.conf
+ local width = opt.width or vim.bo[bufnr].textwidth
+ if not width or width < 1 then
+ width = vim.api.nvim_win_get_width(winid)
+ end
+ local state = setmetatable({
+ winid = winid == 0 and vim.api.nvim_get_current_win() or winid,
+ opt = vim.wo[winid],
+ style = generate_styletable(bufnr),
+ bufnr = bufnr,
+ tabstop = (' '):rep(vim.bo[bufnr].tabstop),
+ width = width,
+ buflen = vim.api.nvim_buf_line_count(bufnr),
+ }, { __index = global_state })
+ return state --[[@as vim.tohtml.state]]
+end
+
+--- @param opt vim.tohtml.opt
+--- @param title? string
+--- @return vim.tohtml.state.global
+local function opt_to_global_state(opt, title)
+ local fonts = {}
+ if opt.font then
+ fonts = type(opt.font) == 'string' and { opt.font } or opt.font --[[@as (string[])]]
+ elseif vim.o.guifont:match('^[^:]+') then
+ table.insert(fonts, vim.o.guifont:match('^[^:]+'))
+ end
+ table.insert(fonts, 'monospace')
+ --- @type vim.tohtml.state.global
+ local state = {
+ background = get_background_color(),
+ foreground = get_foreground_color(),
+ title = opt.title or title or false,
+ font = table.concat(fonts, ','),
+ highlights_name = {},
+ conf = opt,
+ }
+ return state
+end
+
+--- @type fun(state: vim.tohtml.state)[]
+local styletable_funcs = {
+ styletable_syntax,
+ styletable_diff,
+ styletable_treesitter,
+ styletable_match,
+ styletable_extmarks,
+ styletable_conceal,
+ styletable_listchars,
+ styletable_folds,
+ styletable_statuscolumn,
+}
+
+--- @param state vim.tohtml.state
+local function state_generate_style(state)
+ vim.api.nvim_win_call(state.winid, function()
+ for _, fn in ipairs(styletable_funcs) do
+ --- @type string?
+ local cond
+ if type(fn) == 'table' then
+ cond = fn[2] --[[@as string]]
+ --- @type function
+ fn = fn[1]
+ end
+ if not cond or cond(state) then
+ fn(state)
+ end
+ end
+ end)
+end
+
+--- @param winid integer[]|integer
+--- @param opt? vim.tohtml.opt
+--- @return string[]
+local function win_to_html(winid, opt)
+ if type(winid) == 'number' then
+ winid = { winid }
+ end
+ --- @cast winid integer[]
+ assert(#winid > 0, 'no window specified')
+ opt = opt or {}
+ local title = table.concat(
+ vim.tbl_map(vim.api.nvim_buf_get_name, vim.tbl_map(vim.api.nvim_win_get_buf, winid)),
+ ','
+ )
+ local global_state = opt_to_global_state(opt, title)
+ --- @type vim.tohtml.state[]
+ local states = {}
+ for _, i in ipairs(winid) do
+ local state = global_state_to_state(i, global_state)
+ state_generate_style(state)
+ table.insert(states, state)
+ end
+ local html = {}
+ extend_html(html, function()
+ extend_head(html, global_state)
+ extend_body(html, function()
+ for _, state in ipairs(states) do
+ extend_pre(html, state)
+ end
+ end)
+ end)
+ return html
+end
+
+local M = {}
+
+--- @class vim.tohtml.opt
+--- @inlinedoc
+---
+--- Title tag to set in the generated HTML code.
+--- (default: buffer name)
+--- @field title? string|false
+---
+--- Show line numbers.
+--- (default: `false`)
+--- @field number_lines? boolean
+---
+--- Fonts to use.
+--- (default: `guifont`)
+--- @field font? string[]|string
+---
+--- Width used for items which are either right aligned or repeat a character
+--- infinitely.
+--- (default: 'textwidth' if non-zero or window width otherwise)
+--- @field width? integer
+
+--- Converts the buffer shown in the window {winid} to HTML and returns the output as a list of string.
+--- @param winid? integer Window to convert (defaults to current window)
+--- @param opt? vim.tohtml.opt Optional parameters.
+--- @return string[]
+function M.tohtml(winid, opt)
+ return win_to_html(winid or 0, opt)
+end
+
+return M
diff --git a/runtime/lua/vim/F.lua b/runtime/lua/vim/F.lua
index 5ed60ca8ab..8eb17a4c95 100644
--- a/runtime/lua/vim/F.lua
+++ b/runtime/lua/vim/F.lua
@@ -14,8 +14,9 @@ local F = {}
--- assert(vim.F.if_nil(a, b, c, d) == 42)
--- ```
---
----@param ... any
----@return any
+---@generic T
+---@param ... T
+---@return T
function F.if_nil(...)
local nargs = select('#', ...)
for i = 1, nargs do
diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua
index cc872dea83..91baee1a1e 100644
--- a/runtime/lua/vim/_defaults.lua
+++ b/runtime/lua/vim/_defaults.lua
@@ -4,27 +4,10 @@ do
---
--- See |v_star-default| and |v_#-default|
do
- local function region_chunks(region)
- local chunks = {}
- local maxcol = vim.v.maxcol
- for line, cols in vim.spairs(region) do
- local endcol = cols[2] == maxcol and -1 or cols[2]
- local chunk = vim.api.nvim_buf_get_text(0, line, cols[1], line, endcol, {})[1]
- table.insert(chunks, chunk)
- end
- return chunks
- end
-
local function _visual_search(cmd)
assert(cmd == '/' or cmd == '?')
- local region = vim.region(
- 0,
- '.',
- 'v',
- vim.api.nvim_get_mode().mode:sub(1, 1),
- vim.o.selection == 'inclusive'
- )
- local chunks = region_chunks(region)
+ local chunks =
+ vim.fn.getregion(vim.fn.getpos('.'), vim.fn.getpos('v'), { type = vim.fn.mode() })
local esc_chunks = vim
.iter(chunks)
:map(function(v)
@@ -67,17 +50,23 @@ do
--- See |&-default|
vim.keymap.set('n', '&', ':&&<CR>', { desc = ':help &-default' })
+ --- Use Q in visual mode to execute a macro on each line of the selection. #21422
+ ---
+ --- Applies to @x and includes @@ too.
+ vim.keymap.set(
+ 'x',
+ 'Q',
+ ':normal! @<C-R>=reg_recorded()<CR><CR>',
+ { silent = true, desc = ':help v_Q-default' }
+ )
+ vim.keymap.set(
+ 'x',
+ '@',
+ "':normal! @'.getcharstr().'<CR>'",
+ { silent = true, expr = true, desc = ':help v_@-default' }
+ )
--- Map |gx| to call |vim.ui.open| on the identifier under the cursor
do
- -- TODO: use vim.region() when it lands... #13896 #16843
- local function get_visual_selection()
- local save_a = vim.fn.getreginfo('a')
- vim.cmd([[norm! "ay]])
- local selection = vim.fn.getreg('a', 1)
- vim.fn.setreg('a', save_a)
- return selection
- end
-
local function do_open(uri)
local _, err = vim.ui.open(uri)
if err then
@@ -91,7 +80,10 @@ do
do_open(vim.fn.expand('<cfile>'))
end, { desc = gx_desc })
vim.keymap.set({ 'x' }, 'gx', function()
- do_open(get_visual_selection())
+ local lines =
+ vim.fn.getregion(vim.fn.getpos('.'), vim.fn.getpos('v'), { type = vim.fn.mode() })
+ -- Trim whitespace on each line and concatenate.
+ do_open(table.concat(vim.iter(lines):map(vim.trim):totable()))
end, { desc = gx_desc })
end
end
@@ -128,14 +120,43 @@ do
vim.api.nvim_create_autocmd({ 'TermClose' }, {
group = nvim_terminal_augroup,
+ nested = true,
desc = 'Automatically close terminal buffers when started with no arguments and exiting without an error',
callback = function(args)
- if vim.v.event.status == 0 then
- local info = vim.api.nvim_get_chan_info(vim.bo[args.buf].channel)
- local argv = info.argv or {}
- if #argv == 1 and argv[1] == vim.o.shell then
- vim.cmd({ cmd = 'bdelete', args = { args.buf }, bang = true })
+ if vim.v.event.status ~= 0 then
+ return
+ end
+ local info = vim.api.nvim_get_chan_info(vim.bo[args.buf].channel)
+ local argv = info.argv or {}
+ if #argv == 1 and argv[1] == vim.o.shell then
+ vim.api.nvim_buf_delete(args.buf, { force = true })
+ end
+ end,
+ })
+
+ vim.api.nvim_create_autocmd('TermRequest', {
+ group = nvim_terminal_augroup,
+ desc = 'Respond to OSC foreground/background color requests',
+ callback = function(args)
+ local channel = vim.bo[args.buf].channel
+ if channel == 0 then
+ return
+ end
+ local fg_request = args.data == '\027]10;?'
+ local bg_request = args.data == '\027]11;?'
+ if fg_request or bg_request then
+ -- WARN: This does not return the actual foreground/background color,
+ -- but rather returns:
+ -- - fg=white/bg=black when Nvim option 'background' is 'dark'
+ -- - fg=black/bg=white when Nvim option 'background' is 'light'
+ local red, green, blue = 0, 0, 0
+ local bg_option_dark = vim.o.background == 'dark'
+ if (fg_request and bg_option_dark) or (bg_request and not bg_option_dark) then
+ red, green, blue = 65535, 65535, 65535
end
+ local command = fg_request and 10 or 11
+ local data = string.format('\027]%d;rgb:%04x/%04x/%04x\007', command, red, green, blue)
+ vim.api.nvim_chan_send(channel, data)
end
end,
})
@@ -165,118 +186,125 @@ do
})
end
---- Guess value of 'background' based on terminal color.
----
---- We write Operating System Command (OSC) 11 to the terminal to request the
---- terminal's background color. We then wait for a response. If the response
---- matches `rgba:RRRR/GGGG/BBBB/AAAA` where R, G, B, and A are hex digits, then
---- compute the luminance[1] of the RGB color and classify it as light/dark
---- accordingly. Note that the color components may have anywhere from one to
---- four hex digits, and require scaling accordingly as values out of 4, 8, 12,
---- or 16 bits. Also note the A(lpha) component is optional, and is parsed but
---- ignored in the calculations.
----
---- [1] https://en.wikipedia.org/wiki/Luma_%28video%29
-do
- --- Parse a string of hex characters as a color.
- ---
- --- The string can contain 1 to 4 hex characters. The returned value is
- --- between 0.0 and 1.0 (inclusive) representing the intensity of the color.
- ---
- --- For instance, if only a single hex char "a" is used, then this function
- --- returns 0.625 (10 / 16), while a value of "aa" would return 0.664 (170 /
- --- 256).
+-- Only do the following when the TUI is attached
+local tty = nil
+for _, ui in ipairs(vim.api.nvim_list_uis()) do
+ if ui.chan == 1 and ui.stdout_tty then
+ tty = ui
+ break
+ end
+end
+
+if tty then
+ local group = vim.api.nvim_create_augroup('nvim_tty', {})
+
+ --- Set an option after startup (so that OptionSet is fired), but only if not
+ --- already set by the user.
---
- --- @param c string Color as a string of hex chars
- --- @return number? Intensity of the color
- local function parsecolor(c)
- if #c == 0 or #c > 4 then
- return nil
+ --- @param option string Option name
+ --- @param value any Option value
+ local function setoption(option, value)
+ if vim.api.nvim_get_option_info2(option, {}).was_set then
+ -- Don't do anything if option is already set
+ return
end
- local val = tonumber(c, 16)
- if not val then
- return nil
+ -- Wait until Nvim is finished starting to set the option to ensure the
+ -- OptionSet event fires.
+ if vim.v.vim_did_enter == 1 then
+ vim.o[option] = value
+ else
+ vim.api.nvim_create_autocmd('VimEnter', {
+ group = group,
+ once = true,
+ nested = true,
+ callback = function()
+ setoption(option, value)
+ end,
+ })
end
-
- local max = tonumber(string.rep('f', #c), 16)
- return val / max
end
- --- Parse an OSC 11 response
- ---
- --- Either of the two formats below are accepted:
- ---
- --- OSC 11 ; rgb:<red>/<green>/<blue>
+ --- Guess value of 'background' based on terminal color.
---
- --- or
+ --- We write Operating System Command (OSC) 11 to the terminal to request the
+ --- terminal's background color. We then wait for a response. If the response
+ --- matches `rgba:RRRR/GGGG/BBBB/AAAA` where R, G, B, and A are hex digits, then
+ --- compute the luminance[1] of the RGB color and classify it as light/dark
+ --- accordingly. Note that the color components may have anywhere from one to
+ --- four hex digits, and require scaling accordingly as values out of 4, 8, 12,
+ --- or 16 bits. Also note the A(lpha) component is optional, and is parsed but
+ --- ignored in the calculations.
---
- --- OSC 11 ; rgba:<red>/<green>/<blue>/<alpha>
- ---
- --- where
- ---
- --- <red>, <green>, <blue>, <alpha> := h | hh | hhh | hhhh
- ---
- --- The alpha component is ignored, if present.
- ---
- --- @param resp string OSC 11 response
- --- @return string? Red component
- --- @return string? Green component
- --- @return string? Blue component
- local function parseosc11(resp)
- local r, g, b
- r, g, b = resp:match('^\027%]11;rgb:(%x+)/(%x+)/(%x+)$')
- if not r and not g and not b then
- local a
- r, g, b, a = resp:match('^\027%]11;rgba:(%x+)/(%x+)/(%x+)/(%x+)$')
- if not a or #a > 4 then
- return nil, nil, nil
+ --- [1] https://en.wikipedia.org/wiki/Luma_%28video%29
+ do
+ --- Parse a string of hex characters as a color.
+ ---
+ --- The string can contain 1 to 4 hex characters. The returned value is
+ --- between 0.0 and 1.0 (inclusive) representing the intensity of the color.
+ ---
+ --- For instance, if only a single hex char "a" is used, then this function
+ --- returns 0.625 (10 / 16), while a value of "aa" would return 0.664 (170 /
+ --- 256).
+ ---
+ --- @param c string Color as a string of hex chars
+ --- @return number? Intensity of the color
+ local function parsecolor(c)
+ if #c == 0 or #c > 4 then
+ return nil
end
- end
-
- if r and g and b and #r <= 4 and #g <= 4 and #b <= 4 then
- return r, g, b
- end
- return nil, nil, nil
- end
+ local val = tonumber(c, 16)
+ if not val then
+ return nil
+ end
- local tty = false
- for _, ui in ipairs(vim.api.nvim_list_uis()) do
- if ui.chan == 1 and ui.stdout_tty then
- tty = true
- break
+ local max = tonumber(string.rep('f', #c), 16)
+ return val / max
end
- end
-
- if tty then
- local timer = assert(vim.uv.new_timer())
- ---@param bg string New value of the 'background' option
- local function setbg(bg)
- if vim.api.nvim_get_option_info2('background', {}).was_set then
- -- Don't do anything if 'background' is already set
- return
+ --- Parse an OSC 11 response
+ ---
+ --- Either of the two formats below are accepted:
+ ---
+ --- OSC 11 ; rgb:<red>/<green>/<blue>
+ ---
+ --- or
+ ---
+ --- OSC 11 ; rgba:<red>/<green>/<blue>/<alpha>
+ ---
+ --- where
+ ---
+ --- <red>, <green>, <blue>, <alpha> := h | hh | hhh | hhhh
+ ---
+ --- The alpha component is ignored, if present.
+ ---
+ --- @param resp string OSC 11 response
+ --- @return string? Red component
+ --- @return string? Green component
+ --- @return string? Blue component
+ local function parseosc11(resp)
+ local r, g, b
+ r, g, b = resp:match('^\027%]11;rgb:(%x+)/(%x+)/(%x+)$')
+ if not r and not g and not b then
+ local a
+ r, g, b, a = resp:match('^\027%]11;rgba:(%x+)/(%x+)/(%x+)/(%x+)$')
+ if not a or #a > 4 then
+ return nil, nil, nil
+ end
end
- -- Wait until Nvim is finished starting to set 'background' to ensure the
- -- OptionSet event fires.
- if vim.v.vim_did_enter == 1 then
- if vim.o.background ~= bg then
- vim.o.background = bg
- end
- else
- vim.api.nvim_create_autocmd('VimEnter', {
- once = true,
- nested = true,
- callback = function()
- setbg(bg)
- end,
- })
+ if r and g and b and #r <= 4 and #g <= 4 and #b <= 4 then
+ return r, g, b
end
+
+ return nil, nil, nil
end
+ local timer = assert(vim.uv.new_timer())
+
local id = vim.api.nvim_create_autocmd('TermResponse', {
+ group = group,
nested = true,
callback = function(args)
local resp = args.data ---@type string
@@ -289,7 +317,7 @@ do
if rr and gg and bb then
local luminance = (0.299 * rr) + (0.587 * gg) + (0.114 * bb)
local bg = luminance < 0.5 and 'dark' or 'light'
- setbg(bg)
+ setoption('background', bg)
end
return true
@@ -297,10 +325,10 @@ do
end,
})
- io.stdout:write('\027]11;?\027\\')
+ io.stdout:write('\027]11;?\007')
timer:start(1000, 0, function()
- -- No response received. Delete the autocommand
+ -- Delete the autocommand if no response was received
vim.schedule(function()
-- Suppress error if autocommand has already been deleted
pcall(vim.api.nvim_del_autocmd, id)
@@ -311,4 +339,102 @@ do
end
end)
end
+
+ --- If the TUI (term_has_truecolor) was able to determine that the host
+ --- terminal supports truecolor, enable 'termguicolors'. Otherwise, query the
+ --- terminal (using both XTGETTCAP and SGR + DECRQSS). If the terminal's
+ --- response indicates that it does support truecolor enable 'termguicolors',
+ --- but only if the user has not already disabled it.
+ do
+ if tty.rgb then
+ -- The TUI was able to determine truecolor support
+ setoption('termguicolors', true)
+ else
+ local caps = {} ---@type table<string, boolean>
+ require('vim.termcap').query({ 'Tc', 'RGB', 'setrgbf', 'setrgbb' }, function(cap, found)
+ if not found then
+ return
+ end
+
+ caps[cap] = true
+ if caps.Tc or caps.RGB or (caps.setrgbf and caps.setrgbb) then
+ setoption('termguicolors', true)
+ end
+ end)
+
+ local timer = assert(vim.uv.new_timer())
+
+ -- Arbitrary colors to set in the SGR sequence
+ local r = 1
+ local g = 2
+ local b = 3
+
+ local id = vim.api.nvim_create_autocmd('TermResponse', {
+ group = group,
+ nested = true,
+ callback = function(args)
+ local resp = args.data ---@type string
+ local decrqss = resp:match('^\027P1%$r([%d;:]+)m$')
+
+ if decrqss then
+ -- The DECRQSS SGR response first contains attributes separated by
+ -- semicolons, followed by the SGR itself with parameters separated
+ -- by colons. Some terminals include "0" in the attribute list
+ -- unconditionally; others do not. Our SGR sequence did not set any
+ -- attributes, so there should be no attributes in the list.
+ local attrs = vim.split(decrqss, ';')
+ if #attrs ~= 1 and (#attrs ~= 2 or attrs[1] ~= '0') then
+ return true
+ end
+
+ -- The returned SGR sequence should begin with 48:2
+ local sgr = attrs[#attrs]:match('^48:2:([%d:]+)$')
+ if not sgr then
+ return true
+ end
+
+ -- The remaining elements of the SGR sequence should be the 3 colors
+ -- we set. Some terminals also include an additional parameter
+ -- (which can even be empty!), so handle those cases as well
+ local params = vim.split(sgr, ':')
+ if #params ~= 3 and (#params ~= 4 or (params[1] ~= '' and params[1] ~= '1')) then
+ return true
+ end
+
+ if
+ tonumber(params[#params - 2]) == r
+ and tonumber(params[#params - 1]) == g
+ and tonumber(params[#params]) == b
+ then
+ setoption('termguicolors', true)
+ end
+
+ return true
+ end
+ end,
+ })
+
+ -- Write SGR followed by DECRQSS. This sets the background color then
+ -- immediately asks the terminal what the background color is. If the
+ -- terminal responds to the DECRQSS with the same SGR sequence that we
+ -- sent then the terminal supports truecolor.
+ local decrqss = '\027P$qm\027\\'
+ if os.getenv('TMUX') then
+ decrqss = string.format('\027Ptmux;%s\027\\', decrqss:gsub('\027', '\027\027'))
+ end
+ io.stdout:write(string.format('\027[48;2;%d;%d;%dm%s', r, g, b, decrqss))
+
+ timer:start(1000, 0, function()
+ -- Delete the autocommand if no response was received
+ vim.schedule(function()
+ -- Suppress error if autocommand has already been deleted
+ pcall(vim.api.nvim_del_autocmd, id)
+ end)
+
+ if not timer:is_closing() then
+ timer:close()
+ end
+ end)
+ end
+ end
end
diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua
index 6cccbe8313..6cf77b4648 100644
--- a/runtime/lua/vim/_editor.lua
+++ b/runtime/lua/vim/_editor.lua
@@ -95,7 +95,7 @@ vim.log = {
--- throws an error if {cmd} cannot be run.
---
--- @param cmd (string[]) Command to execute
---- @param opts (SystemOpts|nil) Options:
+--- @param opts vim.SystemOpts? Options:
--- - cwd: (string) Set the current working directory for the sub-process.
--- - env: table<string,string> Set environment variables for the new process. Inherits the
--- current environment with `NVIM` set to |v:servername|.
@@ -118,7 +118,7 @@ vim.log = {
--- parent exits. Note that the child process will still keep the parent's event loop alive
--- unless the parent process calls |uv.unref()| on the child's process handle.
---
---- @param on_exit (function|nil) Called when subprocess exits. When provided, the command runs
+--- @param on_exit? fun(out: vim.SystemCompleted) Called when subprocess exits. When provided, the command runs
--- asynchronously. Receives SystemCompleted object, see return of SystemObj:wait().
---
--- @return vim.SystemObj Object with the fields:
@@ -127,10 +127,10 @@ vim.log = {
--- timeout the process is sent the KILL signal (9) and the exit code is set to 124. Cannot
--- be called in |api-fast|.
--- - SystemCompleted is an object with the fields:
---- - code: (integer)
---- - signal: (integer)
---- - stdout: (string), nil if stdout argument is passed
---- - stderr: (string), nil if stderr argument is passed
+--- - code: (integer)
+--- - signal: (integer)
+--- - stdout: (string), nil if stdout argument is passed
+--- - stderr: (string), nil if stderr argument is passed
--- - kill (fun(signal: integer|string))
--- - write (fun(data: string|nil)) Requires `stdin=true`. Pass `nil` to close the stream.
--- - is_closing (fun(): boolean)
@@ -156,10 +156,10 @@ function vim._os_proc_info(pid)
elseif r.code ~= 0 then
error('command failed: ' .. vim.fn.string(cmd))
end
- local ppid = assert(vim.system({ 'ps', '-p', pid, '-o', 'ppid=' }):wait().stdout)
+ local ppid_string = assert(vim.system({ 'ps', '-p', pid, '-o', 'ppid=' }):wait().stdout)
-- Remove trailing whitespace.
name = vim.trim(name):gsub('^.*/', '')
- ppid = tonumber(ppid) or -1
+ local ppid = tonumber(ppid_string) or -1
return {
name = name,
pid = pid,
@@ -190,12 +190,19 @@ function vim._os_proc_children(ppid)
return children
end
+--- @nodoc
+--- @class vim.inspect.Opts
+--- @field depth? integer
+--- @field newline? string
+--- @field process? fun(item:any, path: string[]): any
+
--- Gets a human-readable representation of the given object.
---
---@see |vim.print()|
---@see https://github.com/kikito/inspect.lua
---@see https://github.com/mpeterv/vinspect
---@return string
+---@overload fun(x: any, opts?: vim.inspect.Opts): string
vim.inspect = vim.inspect
do
@@ -219,10 +226,9 @@ do
--- ```
---
---@see |paste|
- ---@alias paste_phase -1 | 1 | 2 | 3
---
---@param lines string[] # |readfile()|-style list of lines to paste. |channel-lines|
- ---@param phase paste_phase -1: "non-streaming" paste: the call contains all lines.
+ ---@param phase (-1|1|2|3) -1: "non-streaming" paste: the call contains all lines.
--- If paste is "streamed", `phase` indicates the stream state:
--- - 1: starts the paste (exactly once)
--- - 2: continues the paste (zero or more times)
@@ -269,6 +275,7 @@ do
for _, line in ipairs(lines) do
nchars = nchars + line:len()
end
+ --- @type integer, integer
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
local bufline = vim.api.nvim_buf_get_lines(0, row - 1, row, true)[1]
local firstline = lines[1]
@@ -347,10 +354,13 @@ function vim.schedule_wrap(fn)
end
-- vim.fn.{func}(...)
----@private
+---@nodoc
vim.fn = setmetatable({}, {
+ --- @param t table<string,function>
+ --- @param key string
+ --- @return function
__index = function(t, key)
- local _fn
+ local _fn --- @type function
if vim.api[key] ~= nil then
_fn = function()
error(string.format('Tried to call API function with vim.fn: use vim.api.%s instead', key))
@@ -449,7 +459,7 @@ vim.cmd = setmetatable({}, {
end,
})
---- @class vim.var_accessor
+--- @class (private) vim.var_accessor
--- @field [string] any
--- @field [integer] vim.var_accessor
@@ -478,7 +488,7 @@ do
end
vim.g = make_dict_accessor('g', false)
- vim.v = make_dict_accessor('v', false)
+ vim.v = make_dict_accessor('v', false) --[[@as vim.v]]
vim.b = make_dict_accessor('b')
vim.w = make_dict_accessor('w')
vim.t = make_dict_accessor('t')
@@ -492,7 +502,7 @@ end
---@param bufnr integer Buffer number, or 0 for current buffer
---@param pos1 integer[]|string Start of region as a (line, column) tuple or |getpos()|-compatible string
---@param pos2 integer[]|string End of region as a (line, column) tuple or |getpos()|-compatible string
----@param regtype string \|setreg()|-style selection type
+---@param regtype string [setreg()]-style selection type
---@param inclusive boolean Controls whether the ending column is inclusive (see also 'selection').
---@return table region Dict of the form `{linenr = {startcol,endcol}}`. `endcol` is exclusive, and
---whole lines are returned as `{startcol,endcol} = {0,-1}`.
@@ -533,20 +543,21 @@ function vim.region(bufnr, pos1, pos2, regtype, inclusive)
local region = {}
for l = pos1[1], pos2[1] do
- local c1, c2
+ local c1 --- @type number
+ local c2 --- @type number
if regtype:byte() == 22 then -- block selection: take width from regtype
c1 = pos1[2]
- c2 = c1 + regtype:sub(2)
+ c2 = c1 + tonumber(regtype:sub(2))
-- and adjust for non-ASCII characters
local bufline = vim.api.nvim_buf_get_lines(bufnr, l, l + 1, true)[1]
local utflen = vim.str_utfindex(bufline, #bufline)
if c1 <= utflen then
- c1 = vim.str_byteindex(bufline, c1)
+ c1 = assert(tonumber(vim.str_byteindex(bufline, c1)))
else
c1 = #bufline + 1
end
if c2 <= utflen then
- c2 = vim.str_byteindex(bufline, c2)
+ c2 = assert(tonumber(vim.str_byteindex(bufline, c2)))
else
c2 = #bufline + 1
end
@@ -576,7 +587,7 @@ end
---@return table timer luv timer object
function vim.defer_fn(fn, timeout)
vim.validate({ fn = { fn, 'c', true } })
- local timer = vim.uv.new_timer()
+ local timer = assert(vim.uv.new_timer())
timer:start(
timeout,
0,
@@ -601,6 +612,7 @@ end
---@param msg string Content of the notification to show to the user.
---@param level integer|nil One of the values from |vim.log.levels|.
---@param opts table|nil Optional parameters. Unused by default.
+---@diagnostic disable-next-line: unused-local
function vim.notify(msg, level, opts) -- luacheck: no unused args
if level == vim.log.levels.ERROR then
vim.api.nvim_err_writeln(msg)
@@ -612,7 +624,7 @@ function vim.notify(msg, level, opts) -- luacheck: no unused args
end
do
- local notified = {}
+ local notified = {} --- @type table<string,true>
--- Displays a notification only one time.
---
@@ -633,7 +645,7 @@ do
end
end
-local on_key_cbs = {}
+local on_key_cbs = {} --- @type table<integer,function>
--- Adds Lua function {fn} with namespace id {ns_id} as a listener to every,
--- yes every, input key.
@@ -645,8 +657,9 @@ local on_key_cbs = {}
---@note {fn} will not be cleared by |nvim_buf_clear_namespace()|
---@note {fn} will receive the keys after mappings have been evaluated
---
----@param fn fun(key: string) Function invoked on every key press. |i_CTRL-V|
---- Returning nil removes the callback associated with namespace {ns_id}.
+---@param fn fun(key: string)? Function invoked on every key press. |i_CTRL-V|
+--- Passing in nil when {ns_id} is specified removes the
+--- callback associated with namespace {ns_id}.
---@param ns_id integer? Namespace ID. If nil or 0, generates and returns a
--- new |nvim_create_namespace()| id.
---
@@ -698,8 +711,11 @@ end
--- Generates a list of possible completions for the string.
--- String has the pattern.
---
---- 1. Can we get it to just return things in the global namespace with that name prefix
---- 2. Can we get it to return things from global namespace even with `print(` in front.
+--- 1. Can we get it to just return things in the global namespace with that name prefix
+--- 2. Can we get it to return things from global namespace even with `print(` in front.
+---
+--- @param pat string
+--- @return any[], integer
function vim._expand_pat(pat, env)
env = env or _G
@@ -732,7 +748,7 @@ function vim._expand_pat(pat, env)
if type(final_env) ~= 'table' then
return {}, 0
end
- local key
+ local key --- @type any
-- Normally, we just have a string
-- Just attempt to get the string directly from the environment
@@ -774,7 +790,8 @@ function vim._expand_pat(pat, env)
end
end
- local keys = {}
+ local keys = {} --- @type table<string,true>
+ --- @param obj table<any,any>
local function insert_keys(obj)
for k, _ in pairs(obj) do
if type(k) == 'string' and string.sub(k, 1, string.len(match_part)) == match_part then
@@ -801,11 +818,14 @@ function vim._expand_pat(pat, env)
return keys, #prefix_match_pat
end
+--- @param lua_string string
+--- @return (string|string[])[], integer
vim._expand_pat_get_parts = function(lua_string)
local parts = {}
local accumulator, search_index = '', 1
- local in_brackets, bracket_end = false, -1
+ local in_brackets = false
+ local bracket_end = -1 --- @type integer?
local string_char = nil
for idx = 1, #lua_string do
local s = lua_string:sub(idx, idx)
@@ -857,6 +877,7 @@ vim._expand_pat_get_parts = function(lua_string)
end
end
+ --- @param val any[]
parts = vim.tbl_filter(function(val)
return #val > 0
end, parts)
@@ -867,12 +888,13 @@ end
do
-- Ideally we should just call complete() inside omnifunc, though there are
-- some bugs, so fake the two-step dance for now.
- local matches
+ local matches --- @type any[]
--- 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.
+ --- @param find_start 1|0
function vim.lua_omnifunc(find_start, _)
if find_start == 1 then
local line = vim.api.nvim_get_current_line()
@@ -886,12 +908,6 @@ do
end
end
----@private
-function vim.pretty_print(...)
- vim.deprecate('vim.pretty_print', 'vim.print', '0.10')
- return vim.print(...)
-end
-
--- "Pretty prints" the given arguments and returns them unmodified.
---
--- Example:
@@ -902,6 +918,7 @@ end
---
--- @see |vim.inspect()|
--- @see |:=|
+--- @param ... any
--- @return any # given arguments.
function vim.print(...)
if vim.in_fast_event() then
@@ -938,9 +955,12 @@ function vim.keycode(str)
return vim.api.nvim_replace_termcodes(str, true, true, true)
end
+--- @param server_addr string
+--- @param connect_error string
function vim._cs_remote(rcid, server_addr, connect_error, args)
+ --- @return string
local function connection_failure_errmsg(consequence)
- local explanation
+ local explanation --- @type string
if server_addr == '' then
explanation = 'No server specified with --server'
else
@@ -983,7 +1003,7 @@ function vim._cs_remote(rcid, server_addr, connect_error, args)
local res = tostring(vim.rpcrequest(rcid, 'nvim_eval', args[2]))
return { result = res, should_exit = true, tabbed = false }
elseif subcmd ~= '' then
- return { errmsg = 'Unknown option argument: ' .. args[1] }
+ return { errmsg = 'Unknown option argument: ' .. tostring(args[1]) }
end
if rcid == 0 then
@@ -1019,9 +1039,44 @@ end
---
---@return string|nil # Deprecated message, or nil if no message was shown.
function vim.deprecate(name, alternative, version, plugin, backtrace)
- local msg = ('%s is deprecated'):format(name)
+ vim.validate {
+ name = { name, 'string' },
+ alternative = { alternative, 'string', true },
+ version = { version, 'string', true },
+ plugin = { plugin, 'string', true },
+ }
plugin = plugin or 'Nvim'
- msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or msg
+
+ -- Only issue warning if feature is hard-deprecated as specified by MAINTAIN.md.
+ -- e.g., when planned to be removed in version = '0.12' (soft-deprecated since 0.10-dev),
+ -- show warnings since 0.11, including 0.11-dev (hard_deprecated_since = 0.11-dev).
+ if plugin == 'Nvim' then
+ local current_version = vim.version() ---@type vim.Version
+ local removal_version = assert(vim.version.parse(version))
+ local is_hard_deprecated ---@type boolean
+
+ if removal_version.minor > 0 then
+ local hard_deprecated_since = assert(vim.version._version({
+ major = removal_version.major,
+ minor = removal_version.minor - 1,
+ patch = 0,
+ prerelease = 'dev', -- Show deprecation warnings in devel (nightly) version as well
+ }))
+ is_hard_deprecated = (current_version >= hard_deprecated_since)
+ else
+ -- Assume there will be no next minor version before bumping up the major version;
+ -- therefore we can always show a warning.
+ assert(removal_version.minor == 0, vim.inspect(removal_version))
+ is_hard_deprecated = true
+ end
+
+ if not is_hard_deprecated then
+ return
+ end
+ end
+
+ local msg = ('%s is deprecated'):format(name)
+ msg = alternative and ('%s, use %s instead.'):format(msg, alternative) or (msg .. '.')
msg = ('%s%s\nThis feature will be removed in %s version %s'):format(
msg,
(plugin == 'Nvim' and ' :help deprecated' or ''),
diff --git a/runtime/lua/vim/_init_packages.lua b/runtime/lua/vim/_init_packages.lua
index 4a961970cc..d0bb91114e 100644
--- a/runtime/lua/vim/_init_packages.lua
+++ b/runtime/lua/vim/_init_packages.lua
@@ -1,5 +1,5 @@
-local pathtrails = {}
-vim._so_trails = {}
+local pathtrails = {} --- @type table<string,true> ta
+vim._so_trails = {} --- @type string[]
for s in (package.cpath .. ';'):gmatch('[^;]*;') do
s = s:sub(1, -2) -- Strip trailing semicolon
-- Find out path patterns. pathtrail should contain something like
@@ -12,6 +12,7 @@ for s in (package.cpath .. ';'):gmatch('[^;]*;') do
end
end
+--- @param name string
function vim._load_package(name)
local basename = name:gsub('%.', '/')
local paths = { 'lua/' .. basename .. '.lua', 'lua/' .. basename .. '/init.lua' }
@@ -55,13 +56,16 @@ vim._submodules = {
inspect = true,
version = true,
fs = true,
+ glob = true,
iter = true,
re = true,
text = true,
+ provider = true,
}
-- These are for loading runtime modules in the vim namespace lazily.
setmetatable(vim, {
+ --- @param t table<any,any>
__index = function(t, key)
if vim._submodules[key] then
t[key] = require('vim.' .. key)
@@ -70,6 +74,7 @@ setmetatable(vim, {
require('vim._inspector')
return t[key]
elseif vim.startswith(key, 'uri_') then
+ --- @type any?
local val = require('vim.uri')[key]
if val ~= nil then
-- Expose all `vim.uri` functions on the `vim` module.
@@ -83,6 +88,7 @@ setmetatable(vim, {
--- <Docs described in |vim.empty_dict()| >
---@private
--- TODO: should be in vim.shared when vim.shared always uses nvim-lua
+--- @diagnostic disable-next-line:duplicate-set-field
function vim.empty_dict()
return setmetatable({}, vim._empty_dict_mt)
end
diff --git a/runtime/lua/vim/_inspector.lua b/runtime/lua/vim/_inspector.lua
index 3f7b9d2c23..afbd6211cd 100644
--- a/runtime/lua/vim/_inspector.lua
+++ b/runtime/lua/vim/_inspector.lua
@@ -1,8 +1,21 @@
----@class InspectorFilter
----@field syntax boolean include syntax based highlight groups (defaults to true)
----@field treesitter boolean include treesitter based highlight groups (defaults to true)
----@field extmarks boolean|"all" include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true)
----@field semantic_tokens boolean include semantic token highlights (defaults to true)
+--- @class vim._inspector.Filter
+--- @inlinedoc
+---
+--- Include syntax based highlight groups.
+--- (default: `true`)
+--- @field syntax boolean
+---
+--- Include treesitter based highlight groups.
+--- (default: `true`)
+--- @field treesitter boolean
+---
+--- Include extmarks. When `all`, then extmarks without a `hl_group` will also be included.
+--- (default: true)
+--- @field extmarks boolean|"all"
+---
+--- Include semantic token highlights.
+--- (default: true)
+--- @field semantic_tokens boolean
local defaults = {
syntax = true,
treesitter = true,
@@ -12,16 +25,12 @@ local defaults = {
---Get all the items at a given buffer position.
---
----Can also be pretty-printed with `:Inspect!`. *:Inspect!*
+---Can also be pretty-printed with `:Inspect!`. [:Inspect!]()
---
---@param bufnr? integer defaults to the current buffer
---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
----@param filter? InspectorFilter (table|nil) a table with key-value pairs to filter the items
---- - syntax (boolean): include syntax based highlight groups (defaults to true)
---- - treesitter (boolean): include treesitter based highlight groups (defaults to true)
---- - extmarks (boolean|"all"): include extmarks. When `all`, then extmarks without a `hl_group` will also be included (defaults to true)
---- - semantic_tokens (boolean): include semantic tokens (defaults to true)
+---@param filter? vim._inspector.Filter Table with key-value pairs to filter the items
---@return {treesitter:table,syntax:table,extmarks:table,semantic_tokens:table,buffer:integer,col:integer,row:integer} (table) a table with the following key-value pairs. Items are in "traversal order":
--- - treesitter: a list of treesitter captures
--- - syntax: a list of syntax groups
@@ -134,12 +143,12 @@ end
---Show all the items at a given buffer position.
---
----Can also be shown with `:Inspect`. *:Inspect*
+---Can also be shown with `:Inspect`. [:Inspect]()
---
---@param bufnr? integer defaults to the current buffer
---@param row? integer row to inspect, 0-based. Defaults to the row of the current cursor
---@param col? integer col to inspect, 0-based. Defaults to the col of the current cursor
----@param filter? InspectorFilter (table|nil) see |vim.inspect_pos()|
+---@param filter? vim._inspector.Filter
function vim.show_pos(bufnr, row, col, filter)
local items = vim.inspect_pos(bufnr, row, col, filter)
diff --git a/runtime/lua/vim/_meta.lua b/runtime/lua/vim/_meta.lua
index e3b99f6b3d..731dd5b923 100644
--- a/runtime/lua/vim/_meta.lua
+++ b/runtime/lua/vim/_meta.lua
@@ -1,5 +1,7 @@
--- @meta
+--- @alias elem_or_list<T> T|T[]
+
---@type uv
vim.uv = ...
@@ -11,6 +13,7 @@ vim.diagnostic = require('vim.diagnostic')
vim.filetype = require('vim.filetype')
vim.fs = require('vim.fs')
vim.func = require('vim.func')
+vim.glob = require('vim.glob')
vim.health = require('vim.health')
vim.highlight = require('vim.highlight')
vim.iter = require('vim.iter')
@@ -20,6 +23,7 @@ vim.lsp = require('vim.lsp')
vim.re = require('vim.re')
vim.secure = require('vim.secure')
vim.snippet = require('vim.snippet')
+vim.text = require('vim.text')
vim.treesitter = require('vim.treesitter')
vim.ui = require('vim.ui')
vim.version = require('vim.version')
diff --git a/runtime/lua/vim/_meta/api.lua b/runtime/lua/vim/_meta/api.lua
index 49269ba631..cb4c8749b8 100644
--- a/runtime/lua/vim/_meta/api.lua
+++ b/runtime/lua/vim/_meta/api.lua
@@ -38,6 +38,7 @@ function vim.api.nvim__get_runtime(pat, all, opts) end
--- @private
--- Returns object given as argument.
+---
--- This API function is used for testing. One should not rely on its presence
--- in plugins.
---
@@ -47,6 +48,7 @@ function vim.api.nvim__id(obj) end
--- @private
--- Returns array given as argument.
+---
--- This API function is used for testing. One should not rely on its presence
--- in plugins.
---
@@ -56,6 +58,7 @@ function vim.api.nvim__id_array(arr) end
--- @private
--- Returns dictionary given as argument.
+---
--- This API function is used for testing. One should not rely on its presence
--- in plugins.
---
@@ -65,6 +68,7 @@ function vim.api.nvim__id_dictionary(dct) end
--- @private
--- Returns floating-point value given as argument.
+---
--- This API function is used for testing. One should not rely on its presence
--- in plugins.
---
@@ -73,6 +77,9 @@ function vim.api.nvim__id_dictionary(dct) end
function vim.api.nvim__id_float(flt) end
--- @private
+--- NB: if your UI doesn't use hlstate, this will not return hlstate first
+--- time.
+---
--- @param grid integer
--- @param row integer
--- @param col integer
@@ -105,17 +112,20 @@ function vim.api.nvim__stats() end
function vim.api.nvim__unpack(str) end
--- Adds a highlight to buffer.
+---
--- Useful for plugins that dynamically generate highlights to a buffer (like
--- a semantic highlighter or linter). The function adds a single highlight to
--- a buffer. Unlike `matchaddpos()` highlights follow changes to line
--- numbering (as lines are inserted/removed above the highlighted line), like
--- signs and marks do.
+---
--- Namespaces are used for batch deletion/updating of a set of highlights. To
--- create a namespace, use `nvim_create_namespace()` which returns a
--- namespace id. Pass it in to this function as `ns_id` to add highlights to
--- the namespace. All highlights in the same namespace can then be cleared
--- with single call to `nvim_buf_clear_namespace()`. If the highlight never
--- will be deleted by an API call, pass `ns_id = -1`.
+---
--- As a shorthand, `ns_id = 0` can be used to create a new namespace for the
--- highlight, the allocated id is then returned. If `hl_group` is the empty
--- string no highlight is added, but a new `ns_id` is still returned. This is
@@ -128,11 +138,12 @@ function vim.api.nvim__unpack(str) end
--- @param line integer Line to highlight (zero-indexed)
--- @param col_start integer Start of (byte-indexed) column range to highlight
--- @param col_end integer End of (byte-indexed) column range to highlight, or -1 to
---- highlight to end of line
+--- highlight to end of line
--- @return integer
function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start, col_end) end
--- Activates buffer-update events on a channel, or as Lua callbacks.
+---
--- Example (Lua): capture buffer updates in a global `events` variable (use
--- "vim.print(events)" to see its contents):
---
@@ -145,76 +156,78 @@ function vim.api.nvim_buf_add_highlight(buffer, ns_id, hl_group, line, col_start
--- })
--- ```
---
+---
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param send_buffer boolean True if the initial notification should contain the
--- whole buffer: first notification will be
--- `nvim_buf_lines_event`. Else the first notification
--- will be `nvim_buf_changedtick_event`. Not for Lua
--- callbacks.
---- @param opts table<string,function> Optional parameters.
---- • on_lines: Lua callback invoked on change. Return `true` to detach. Args:
---- • the string "lines"
---- • buffer handle
---- • b:changedtick
---- • first line that changed (zero-indexed)
---- • last line that was changed
---- • last line in the updated range
---- • byte count of previous contents
---- • deleted_codepoints (if `utf_sizes` is true)
---- • deleted_codeunits (if `utf_sizes` is true)
----
---- • on_bytes: Lua callback invoked on change. This
---- callback receives more granular information about the
---- change compared to on_lines. Return `true` to detach. Args:
---- • the string "bytes"
---- • buffer handle
---- • b:changedtick
---- • start row of the changed text (zero-indexed)
---- • start column of the changed text
---- • byte offset of the changed text (from the start of
---- the buffer)
---- • old end row of the changed text
---- • old end column of the changed text
---- • old end byte length of the changed text
---- • new end row of the changed text
---- • new end column of the changed text
---- • new end byte length of the changed text
----
---- • on_changedtick: Lua callback invoked on changedtick
---- increment without text change. Args:
---- • the string "changedtick"
---- • buffer handle
---- • b:changedtick
----
---- • on_detach: Lua callback invoked on detach. Args:
---- • the string "detach"
---- • buffer handle
----
---- • on_reload: Lua callback invoked on reload. The entire
---- buffer content should be considered changed. Args:
---- • the string "reload"
---- • buffer handle
----
---- • utf_sizes: include UTF-32 and UTF-16 size of the
---- replaced region, as args to `on_lines`.
---- • preview: also attach to command preview (i.e.
---- 'inccommand') events.
+--- @param opts vim.api.keyset.buf_attach Optional parameters.
+--- • on_lines: Lua callback invoked on change. Return a truthy
+--- value (not `false` or `nil`) to detach. Args:
+--- • the string "lines"
+--- • buffer handle
+--- • b:changedtick
+--- • first line that changed (zero-indexed)
+--- • last line that was changed
+--- • last line in the updated range
+--- • byte count of previous contents
+--- • deleted_codepoints (if `utf_sizes` is true)
+--- • deleted_codeunits (if `utf_sizes` is true)
+--- • on_bytes: Lua callback invoked on change. This callback
+--- receives more granular information about the change compared
+--- to on_lines. Return a truthy value (not `false` or `nil`) to
+--- detach. Args:
+--- • the string "bytes"
+--- • buffer handle
+--- • b:changedtick
+--- • start row of the changed text (zero-indexed)
+--- • start column of the changed text
+--- • byte offset of the changed text (from the start of the
+--- buffer)
+--- • old end row of the changed text (offset from start row)
+--- • old end column of the changed text (if old end row = 0,
+--- offset from start column)
+--- • old end byte length of the changed text
+--- • new end row of the changed text (offset from start row)
+--- • new end column of the changed text (if new end row = 0,
+--- offset from start column)
+--- • new end byte length of the changed text
+--- • on_changedtick: Lua callback invoked on changedtick
+--- increment without text change. Args:
+--- • the string "changedtick"
+--- • buffer handle
+--- • b:changedtick
+--- • on_detach: Lua callback invoked on detach. Args:
+--- • the string "detach"
+--- • buffer handle
+--- • on_reload: Lua callback invoked on reload. The entire buffer
+--- content should be considered changed. Args:
+--- • the string "reload"
+--- • buffer handle
+--- • utf_sizes: include UTF-32 and UTF-16 size of the replaced
+--- region, as args to `on_lines`.
+--- • preview: also attach to command preview (i.e. 'inccommand')
+--- events.
--- @return boolean
function vim.api.nvim_buf_attach(buffer, send_buffer, opts) end
--- call a function with buffer as temporary current buffer
+---
--- This temporarily switches current buffer to "buffer". If the current
--- window already shows "buffer", the window is not switched If a window
--- inside the current tabpage (including a float) already shows the buffer
--- One of these windows will be set as current window temporarily. Otherwise
--- a temporary scratch window (called the "autocmd window" for historical
--- reasons) will be used.
+---
--- This is useful e.g. to call Vimscript functions that only work with the
--- current buffer/window currently, like `termopen()`.
---
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param fun function Function to call inside the buffer (currently Lua callable
---- only)
+--- only)
--- @return any
function vim.api.nvim_buf_call(buffer, fun) end
@@ -227,14 +240,15 @@ function vim.api.nvim_buf_clear_highlight(buffer, ns_id, line_start, line_end) e
--- Clears `namespace`d objects (highlights, `extmarks`, virtual text) from a
--- region.
+---
--- Lines are 0-indexed. `api-indexing` To clear the namespace in the entire
--- buffer, specify line_start=0 and line_end=-1.
---
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param ns_id integer Namespace to clear, or -1 to clear all namespaces.
--- @param line_start integer Start of range of lines to clear
---- @param line_end integer End of range of lines to clear (exclusive) or -1 to
---- clear to end of buffer.
+--- @param line_end integer End of range of lines to clear (exclusive) or -1 to clear
+--- to end of buffer.
function vim.api.nvim_buf_clear_namespace(buffer, ns_id, line_start, line_end) end
--- Creates a buffer-local command `user-commands`.
@@ -268,6 +282,7 @@ function vim.api.nvim_buf_del_keymap(buffer, mode, lhs) end
function vim.api.nvim_buf_del_mark(buffer, name) end
--- Delete a buffer-local user-defined command.
+---
--- Only commands created with `:command-buffer` or
--- `nvim_buf_create_user_command()` can be deleted with this function.
---
@@ -284,9 +299,9 @@ function vim.api.nvim_buf_del_var(buffer, name) end
--- Deletes the buffer. See `:bwipeout`
---
--- @param buffer integer Buffer handle, or 0 for current buffer
---- @param opts table<string,any> Optional parameters. Keys:
---- • force: Force deletion and ignore unsaved changes.
---- • unload: Unloaded only, do not delete. See `:bunload`
+--- @param opts vim.api.keyset.buf_delete Optional parameters. Keys:
+--- • force: Force deletion and ignore unsaved changes.
+--- • unload: Unloaded only, do not delete. See `:bunload`
function vim.api.nvim_buf_delete(buffer, opts) end
--- Gets a changed tick of a buffer
@@ -307,15 +322,16 @@ function vim.api.nvim_buf_get_commands(buffer, opts) end
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param ns_id integer Namespace id from `nvim_create_namespace()`
--- @param id integer Extmark id
---- @param opts table<string,any> Optional parameters. Keys:
---- • details: Whether to include the details dict
---- • hl_name: Whether to include highlight group name instead
---- of id, true if omitted
---- @return integer[]
+--- @param opts vim.api.keyset.get_extmark Optional parameters. Keys:
+--- • details: Whether to include the details dict
+--- • hl_name: Whether to include highlight group name instead of
+--- id, true if omitted
+--- @return vim.api.keyset.get_extmark_item
function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end
---- Gets `extmarks` (including `signs`) in "traversal order" from a `charwise`
---- region defined by buffer positions (inclusive, 0-indexed `api-indexing`).
+--- Gets `extmarks` in "traversal order" from a `charwise` region defined by
+--- buffer positions (inclusive, 0-indexed `api-indexing`).
+---
--- Region can be given as (row,col) tuples, or valid extmark ids (whose
--- positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
--- respectively, thus the following are equivalent:
@@ -327,9 +343,15 @@ function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end
---
--- If `end` is less than `start`, traversal works backwards. (Useful with
--- `limit`, to get the first marks prior to a given position.)
+---
--- Note: when using extmark ranges (marks with a end_row/end_col position)
--- the `overlap` option might be useful. Otherwise only the start position of
--- an extmark will be considered.
+---
+--- Note: legacy signs placed through the `:sign` commands are implemented as
+--- extmarks and will show up here. Their details array will contain a
+--- `sign_name` field.
+---
--- Example:
---
--- ```lua
@@ -347,37 +369,39 @@ function vim.api.nvim_buf_get_extmark_by_id(buffer, ns_id, id, opts) end
--- vim.print(ms)
--- ```
---
+---
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param ns_id integer Namespace id from `nvim_create_namespace()` or -1 for all
---- namespaces
+--- namespaces
--- @param start any Start of range: a 0-indexed (row, col) or valid extmark id
---- (whose position defines the bound). `api-indexing`
+--- (whose position defines the bound). `api-indexing`
--- @param end_ any End of range (inclusive): a 0-indexed (row, col) or valid
---- extmark id (whose position defines the bound).
---- `api-indexing`
+--- extmark id (whose position defines the bound). `api-indexing`
--- @param opts vim.api.keyset.get_extmarks Optional parameters. Keys:
---- • limit: Maximum number of marks to return
---- • details: Whether to include the details dict
---- • hl_name: Whether to include highlight group name instead
---- of id, true if omitted
---- • overlap: Also include marks which overlap the range, even
---- if their start position is less than `start`
---- • type: Filter marks by type: "highlight", "sign",
---- "virt_text" and "virt_lines"
---- @return any[]
+--- • limit: Maximum number of marks to return
+--- • details: Whether to include the details dict
+--- • hl_name: Whether to include highlight group name instead of
+--- id, true if omitted
+--- • overlap: Also include marks which overlap the range, even if
+--- their start position is less than `start`
+--- • type: Filter marks by type: "highlight", "sign", "virt_text"
+--- and "virt_lines"
+--- @return vim.api.keyset.get_extmark_item[]
function vim.api.nvim_buf_get_extmarks(buffer, ns_id, start, end_, opts) end
--- Gets a list of buffer-local `mapping` definitions.
---
--- @param buffer integer Buffer handle, or 0 for current buffer
--- @param mode string Mode short-name ("n", "i", "v", ...)
---- @return table<string,any>[]
+--- @return vim.api.keyset.keymap[]
function vim.api.nvim_buf_get_keymap(buffer, mode) end
--- Gets a line-range from the buffer.
+---
--- Indexing is zero-based, end-exclusive. Negative indices are interpreted as
--- length+1+index: -1 refers to the index past the end. So to get the last
--- element use start=-2 and end=-1.
+---
--- Out-of-bounds indices are clamped to the nearest valid value, unless
--- `strict_indexing` is set.
---
@@ -391,6 +415,7 @@ function vim.api.nvim_buf_get_lines(buffer, start, end_, strict_indexing) end
--- Returns a `(row,col)` tuple representing the position of the named mark.
--- "End of line" column position is returned as `v:maxcol` (big number). See
--- `mark-motions`.
+---
--- Marks are (1,0)-indexed. `api-indexing`
---
--- @param buffer integer Buffer handle, or 0 for current buffer
@@ -410,10 +435,12 @@ function vim.api.nvim_buf_get_name(buffer) end
function vim.api.nvim_buf_get_number(buffer) end
--- Returns the byte offset of a line (0-indexed). `api-indexing`
+---
--- Line 1 (index=0) has offset 0. UTF-8 bytes are counted. EOL is one byte.
--- 'fileformat' and 'fileencoding' are ignored. The line index just after the
--- last line gives the total byte-count of the buffer. A final EOL byte is
--- counted if it would be written, see 'eol'.
+---
--- Unlike `line2byte()`, throws error for out-of-bounds indexing. Returns -1
--- for unloaded buffer.
---
@@ -429,10 +456,13 @@ function vim.api.nvim_buf_get_offset(buffer, index) end
function vim.api.nvim_buf_get_option(buffer, name) end
--- Gets a range from the buffer.
+---
--- This differs from `nvim_buf_get_lines()` in that it allows retrieving only
--- portions of a line.
+---
--- Indexing is zero-based. Row indices are end-inclusive, and column indices
--- are end-exclusive.
+---
--- Prefer `nvim_buf_get_lines()` when retrieving entire lines.
---
--- @param buffer integer Buffer handle, or 0 for current buffer
@@ -440,7 +470,7 @@ function vim.api.nvim_buf_get_option(buffer, name) end
--- @param start_col integer Starting column (byte offset) on first line
--- @param end_row integer Last line index, inclusive
--- @param end_col integer Ending column (byte offset) on last line, exclusive
---- @param opts table<string,any> Optional parameters. Currently unused.
+--- @param opts vim.api.keyset.empty Optional parameters. Currently unused.
--- @return string[]
function vim.api.nvim_buf_get_text(buffer, start_row, start_col, end_row, end_col, opts) end
@@ -471,13 +501,16 @@ function vim.api.nvim_buf_is_valid(buffer) end
function vim.api.nvim_buf_line_count(buffer) end
--- Creates or updates an `extmark`.
+---
--- By default a new extmark is created when no id is passed in, but it is
--- also possible to create a new mark by passing in a previously unused id or
--- move an existing mark by passing in its id. The caller must then keep
--- track of existing and unused ids itself. (Useful over RPC, to avoid
--- waiting for the return value.)
+---
--- Using the optional arguments, it is possible to use this to highlight a
--- range of text, and also to associate virtual text to the mark.
+---
--- If present, the position defined by `end_col` and `end_row` should be
--- after the start position in order for the extmark to cover a range. An
--- earlier end position is not an error, but then it behaves like an empty
@@ -488,108 +521,110 @@ function vim.api.nvim_buf_line_count(buffer) end
--- @param line integer Line where to place the mark, 0-based. `api-indexing`
--- @param col integer Column where to place the mark, 0-based. `api-indexing`
--- @param opts vim.api.keyset.set_extmark Optional parameters.
---- • id : id of the extmark to edit.
---- • end_row : ending line of the mark, 0-based inclusive.
---- • end_col : ending col of the mark, 0-based exclusive.
---- • hl_group : name of the highlight group used to highlight
---- this mark.
---- • hl_eol : when true, for a multiline highlight covering the
---- EOL of a line, continue the highlight for the rest of the
---- screen line (just like for diff and cursorline highlight).
---- • virt_text : virtual text to link to this mark. A list of
---- [text, highlight] tuples, each representing a text chunk
---- with specified highlight. `highlight` element can either
---- be a single highlight group, or an array of multiple
---- highlight groups that will be stacked (highest priority
---- last). A highlight group can be supplied either as a
---- string or as an integer, the latter which can be obtained
---- using `nvim_get_hl_id_by_name()`.
---- • virt_text_pos : position of virtual text. Possible values:
---- • "eol": right after eol character (default).
---- • "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 of the
---- screen line) instead of "virt_text_pos".
---- • virt_text_hide : hide the virtual text when the background
---- text is selected or hidden because of scrolling with
---- 'nowrap' or 'smoothscroll'. Currently only affects
---- "overlay" virt_text.
---- • hl_mode : control how highlights are combined with the
---- highlights of the text. Currently only affects virt_text
---- highlights, but might affect `hl_group` in later versions.
---- • "replace": only show the virt_text color. This is the
---- default.
---- • "combine": combine with background text color.
---- • "blend": blend with background text color. Not supported
---- for "inline" virt_text.
----
---- • virt_lines : virtual lines to add next to this mark This
---- should be an array over lines, where each line in turn is
---- an array over [text, highlight] tuples. In general, buffer
---- and window options do not affect the display of the text.
---- In particular 'wrap' and 'linebreak' options do not take
---- effect, so the number of extra screen lines will always
---- match the size of the array. However the 'tabstop' buffer
---- option is still used for hard tabs. By default lines are
---- placed below the buffer line containing the mark.
---- • virt_lines_above: place virtual lines above instead.
---- • virt_lines_leftcol: Place extmarks in the leftmost column
---- of the window, bypassing sign and number columns.
---- • ephemeral : for use with `nvim_set_decoration_provider()`
---- callbacks. The mark will only be used for the current
---- redraw cycle, and not be permantently stored in the
---- buffer.
---- • right_gravity : boolean that indicates the direction the
---- extmark will be shifted in when new text is inserted (true
---- for right, false for left). Defaults to true.
---- • end_right_gravity : boolean that indicates the direction
---- the extmark end position (if it exists) will be shifted in
---- when new text is inserted (true for right, false for
---- left). Defaults to false.
---- • undo_restore : Restore the exact position of the mark if
---- text around the mark was deleted and then restored by
---- undo. Defaults to true.
---- • invalidate : boolean that indicates whether to hide the
---- extmark if the entirety of its range is deleted. If
---- "undo_restore" is false, the extmark is deleted instead.
---- • priority: a priority value for the highlight group or sign
---- attribute. For example treesitter highlighting uses a
---- value of 100.
---- • strict: boolean that indicates extmark should not be
---- placed if the line or column value is past the end of the
---- buffer or end of the line respectively. Defaults to true.
---- • sign_text: string of length 1-2 used to display in the
---- sign column. Note: ranges are unsupported and decorations
---- are only applied to start_row
---- • sign_hl_group: name of the highlight group used to
---- highlight the sign column text. Note: ranges are
---- unsupported and decorations are only applied to start_row
---- • number_hl_group: name of the highlight group used to
---- highlight the number column. Note: ranges are unsupported
---- and decorations are only applied to start_row
---- • line_hl_group: name of the highlight group used to
---- highlight the whole line. Note: ranges are unsupported and
---- decorations are only applied to start_row
---- • cursorline_hl_group: name of the highlight group used to
---- highlight the line when the cursor is on the same line as
---- the mark and 'cursorline' is enabled. Note: ranges are
---- unsupported and decorations are only applied to start_row
---- • conceal: string which should be either empty or a single
---- character. Enable concealing similar to `:syn-conceal`.
---- When a character is supplied it is used as `:syn-cchar`.
---- "hl_group" is used as highlight for the cchar if provided,
---- otherwise it defaults to `hl-Conceal`.
---- • spell: boolean indicating that spell checking should be
---- performed within this extmark
---- • ui_watched: boolean that indicates the mark should be
---- drawn by a UI. When set, the UI will receive win_extmark
---- events. Note: the mark is positioned by virt_text
---- attributes. Can be used together with virt_text.
+--- • id : id of the extmark to edit.
+--- • end_row : ending line of the mark, 0-based inclusive.
+--- • end_col : ending col of the mark, 0-based exclusive.
+--- • hl_group : name of the highlight group used to highlight
+--- this mark.
+--- • hl_eol : when true, for a multiline highlight covering the
+--- EOL of a line, continue the highlight for the rest of the
+--- screen line (just like for diff and cursorline highlight).
+--- • virt_text : virtual text to link to this mark. A list of
+--- `[text, highlight]` tuples, each representing a text chunk
+--- with specified highlight. `highlight` element can either be
+--- a single highlight group, or an array of multiple highlight
+--- groups that will be stacked (highest priority last). A
+--- highlight group can be supplied either as a string or as an
+--- integer, the latter which can be obtained using
+--- `nvim_get_hl_id_by_name()`.
+--- • virt_text_pos : position of virtual text. Possible values:
+--- • "eol": right after eol character (default).
+--- • "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 of the
+--- screen line) instead of "virt_text_pos".
+--- • virt_text_hide : hide the virtual text when the background
+--- text is selected or hidden because of scrolling with
+--- 'nowrap' or 'smoothscroll'. Currently only affects "overlay"
+--- virt_text.
+--- • virt_text_repeat_linebreak : repeat the virtual text on
+--- wrapped lines.
+--- • hl_mode : control how highlights are combined with the
+--- highlights of the text. Currently only affects virt_text
+--- highlights, but might affect `hl_group` in later versions.
+--- • "replace": only show the virt_text color. This is the
+--- default.
+--- • "combine": combine with background text color.
+--- • "blend": blend with background text color. Not supported
+--- for "inline" virt_text.
+--- • virt_lines : virtual lines to add next to this mark This
+--- should be an array over lines, where each line in turn is an
+--- array over `[text, highlight]` tuples. In general, buffer
+--- and window options do not affect the display of the text. In
+--- particular 'wrap' and 'linebreak' options do not take
+--- effect, so the number of extra screen lines will always
+--- match the size of the array. However the 'tabstop' buffer
+--- option is still used for hard tabs. By default lines are
+--- placed below the buffer line containing the mark.
+--- • virt_lines_above: place virtual lines above instead.
+--- • virt_lines_leftcol: Place extmarks in the leftmost column of
+--- the window, bypassing sign and number columns.
+--- • ephemeral : for use with `nvim_set_decoration_provider()`
+--- callbacks. The mark will only be used for the current redraw
+--- cycle, and not be permantently stored in the buffer.
+--- • right_gravity : boolean that indicates the direction the
+--- extmark will be shifted in when new text is inserted (true
+--- for right, false for left). Defaults to true.
+--- • end_right_gravity : boolean that indicates the direction the
+--- extmark end position (if it exists) will be shifted in when
+--- new text is inserted (true for right, false for left).
+--- Defaults to false.
+--- • undo_restore : Restore the exact position of the mark if
+--- text around the mark was deleted and then restored by undo.
+--- Defaults to true.
+--- • invalidate : boolean that indicates whether to hide the
+--- extmark if the entirety of its range is deleted. For hidden
+--- marks, an "invalid" key is added to the "details" array of
+--- `nvim_buf_get_extmarks()` and family. If "undo_restore" is
+--- false, the extmark is deleted instead.
+--- • priority: a priority value for the highlight group, sign
+--- attribute or virtual text. For virtual text, item with
+--- highest priority is drawn last. For example treesitter
+--- highlighting uses a value of 100.
+--- • strict: boolean that indicates extmark should not be placed
+--- if the line or column value is past the end of the buffer or
+--- end of the line respectively. Defaults to true.
+--- • sign_text: string of length 1-2 used to display in the sign
+--- column.
+--- • sign_hl_group: name of the highlight group used to highlight
+--- the sign column text.
+--- • number_hl_group: name of the highlight group used to
+--- highlight the number column.
+--- • line_hl_group: name of the highlight group used to highlight
+--- the whole line.
+--- • cursorline_hl_group: name of the highlight group used to
+--- highlight the sign column text when the cursor is on the
+--- same line as the mark and 'cursorline' is enabled.
+--- • conceal: string which should be either empty or a single
+--- character. Enable concealing similar to `:syn-conceal`. When
+--- a character is supplied it is used as `:syn-cchar`.
+--- "hl_group" is used as highlight for the cchar if provided,
+--- otherwise it defaults to `hl-Conceal`.
+--- • spell: boolean indicating that spell checking should be
+--- performed within this extmark
+--- • ui_watched: boolean that indicates the mark should be drawn
+--- by a UI. When set, the UI will receive win_extmark events.
+--- Note: the mark is positioned by virt_text attributes. Can be
+--- used together with virt_text.
+--- • url: A URL to associate with this extmark. In the TUI, the
+--- OSC 8 control sequence is used to generate a clickable
+--- hyperlink to this URL.
+--- • scoped: boolean that indicates that the extmark should only
+--- be displayed in the namespace scope. (experimental)
--- @return integer
function vim.api.nvim_buf_set_extmark(buffer, ns_id, line, col, opts) end
@@ -603,11 +638,14 @@ function vim.api.nvim_buf_set_extmark(buffer, ns_id, line, col, opts) end
function vim.api.nvim_buf_set_keymap(buffer, mode, lhs, rhs, opts) end
--- Sets (replaces) a line-range in the buffer.
+---
--- Indexing is zero-based, end-exclusive. Negative indices are interpreted as
--- length+1+index: -1 refers to the index past the end. So to change or
--- delete the last element use start=-2 and end=-1.
+---
--- To insert lines at a given index, set `start` and `end` to the same index.
--- To delete a range of lines, set `replacement` to an empty array.
+---
--- Out-of-bounds indices are clamped to the nearest valid value, unless
--- `strict_indexing` is set.
---
@@ -620,13 +658,14 @@ function vim.api.nvim_buf_set_lines(buffer, start, end_, strict_indexing, replac
--- Sets a named mark in the given buffer, all marks are allowed
--- file/uppercase, visual, last change, etc. See `mark-motions`.
+---
--- Marks are (1,0)-indexed. `api-indexing`
---
--- @param buffer integer Buffer to set the mark on
--- @param name string Mark name
--- @param line integer Line number
--- @param col integer Column/row number
---- @param opts table<string,any> Optional parameters. Reserved for future use.
+--- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use.
--- @return boolean
function vim.api.nvim_buf_set_mark(buffer, name, line, col, opts) end
@@ -643,16 +682,21 @@ function vim.api.nvim_buf_set_name(buffer, name) end
function vim.api.nvim_buf_set_option(buffer, name, value) end
--- Sets (replaces) a range in the buffer
+---
--- This is recommended over `nvim_buf_set_lines()` when only modifying parts
--- of a line, as extmarks will be preserved on non-modified parts of the
--- touched lines.
+---
--- Indexing is zero-based. Row indices are end-inclusive, and column indices
--- are end-exclusive.
---- To insert text at a given `(row, column)` location, use `start_row =
---- end_row = row` and `start_col = end_col = col`. To delete the text in a
---- range, use `replacement = {}`.
+---
+--- To insert text at a given `(row, column)` location, use
+--- `start_row = end_row = row` and `start_col = end_col = col`. To delete the
+--- text in a range, use `replacement = {}`.
+---
--- Prefer `nvim_buf_set_lines()` if you are only adding or deleting entire
--- lines.
+---
--- Prefer `nvim_put()` if you want to insert text at the cursor position.
---
--- @param buffer integer Buffer handle, or 0 for current buffer
@@ -675,11 +719,12 @@ function vim.api.nvim_buf_set_var(buffer, name, value) end
--- @param src_id integer
--- @param line integer
--- @param chunks any[]
---- @param opts table<string,any>
+--- @param opts vim.api.keyset.empty
--- @return integer
function vim.api.nvim_buf_set_virtual_text(buffer, src_id, line, chunks, opts) end
--- Calls a Vimscript `Dictionary-function` with the given arguments.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
---
--- @param dict any Dictionary, or String evaluating to a Vimscript `self` dict
@@ -689,6 +734,7 @@ function vim.api.nvim_buf_set_virtual_text(buffer, src_id, line, chunks, opts) e
function vim.api.nvim_call_dict_function(dict, fn, args) end
--- Calls a Vimscript function with the given arguments.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
---
--- @param fn string Function to call
@@ -700,6 +746,7 @@ function vim.api.nvim_call_function(fn, args) end
--- process. For the stdio channel `channel-stdio`, it writes to Nvim's
--- stdout. For an internal terminal instance (`nvim_open_term()`) it writes
--- directly to terminal output. See `channel-bytes` for more information.
+---
--- This function writes raw data, not RPC messages. If the channel was
--- created with `rpc=true` then the channel expects RPC messages, use
--- `vim.rpcnotify()` and `vim.rpcrequest()` instead.
@@ -716,41 +763,41 @@ function vim.api.nvim_chan_send(chan, data) end
--- • event: "pat1"
--- • event: { "pat1" }
--- • event: { "pat1", "pat2", "pat3" }
----
--- • pattern: (string|table)
--- • pattern or patterns to match exactly.
--- • For example, if you have `*.py` as that pattern for the
--- autocmd, you must pass `*.py` exactly to clear it.
--- `test.py` will not match the pattern.
----
--- • defaults to clearing all patterns.
--- • NOTE: Cannot be used with {buffer}
----
--- • buffer: (bufnr)
--- • clear only `autocmd-buflocal` autocommands.
--- • NOTE: Cannot be used with {pattern}
----
--- • group: (string|int) The augroup name or id.
---- • NOTE: If not passed, will only delete autocmds not in any group.
+--- • NOTE: If not passed, will only delete autocmds not in any
+--- group.
function vim.api.nvim_clear_autocmds(opts) end
--- Executes an Ex command.
+---
--- Unlike `nvim_command()` this command takes a structured Dictionary instead
--- of a String. This allows for easier construction and manipulation of an Ex
--- command. This also allows for things such as having spaces inside a
--- command argument, expanding filenames in a command that otherwise doesn't
--- expand filenames, etc. Command arguments may also be Number, Boolean or
--- String.
+---
--- The first argument may also be used instead of count for commands that
--- support it in order to make their usage simpler with `vim.cmd()`. For
--- example, instead of `vim.cmd.bdelete{ count = 2 }`, you may do
--- `vim.cmd.bdelete(2)`.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
---
--- @param cmd vim.api.keyset.cmd Command to execute. Must be a Dictionary that can contain the
---- same values as the return value of `nvim_parse_cmd()` except
---- "addr", "nargs" and "nextcmd" which are ignored if provided.
---- All values except for "cmd" are optional.
+--- same values as the return value of `nvim_parse_cmd()` except
+--- "addr", "nargs" and "nextcmd" which are ignored if provided.
+--- All values except for "cmd" are optional.
--- @param opts vim.api.keyset.cmd_opts Optional parameters.
--- • output: (boolean, default false) Whether to return command
--- output.
@@ -758,7 +805,9 @@ function vim.api.nvim_clear_autocmds(opts) end
function vim.api.nvim_cmd(cmd, opts) end
--- Executes an Ex command.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
+---
--- Prefer using `nvim_cmd()` or `nvim_exec2()` over this. To evaluate
--- multiple lines of Vim script or an Ex command directly, use
--- `nvim_exec2()`. To construct an Ex command using a structured format and
@@ -773,7 +822,18 @@ function vim.api.nvim_command(command) end
--- @return string
function vim.api.nvim_command_output(command) end
+--- Set info for the completion candidate index. if the info was shown in a
+--- window, then the window and buffer ids are returned for further
+--- customization. If the text was not shown, an empty dict is returned.
+---
+--- @param index integer the completion candidate index
+--- @param opts vim.api.keyset.complete_set Optional parameters.
+--- • info: (string) info text.
+--- @return table<string,any>
+function vim.api.nvim_complete_set(index, opts) end
+
--- Create or get an autocommand group `autocmd-groups`.
+---
--- To get an existing group id, do:
---
--- ```lua
@@ -782,6 +842,7 @@ function vim.api.nvim_command_output(command) end
--- })
--- ```
---
+---
--- @param name string String: The name of the group
--- @param opts vim.api.keyset.create_augroup Dictionary Parameters
--- • clear (bool) optional: defaults to true. Clear existing
@@ -789,7 +850,10 @@ function vim.api.nvim_command_output(command) end
--- @return integer
function vim.api.nvim_create_augroup(name, opts) end
---- Creates an `autocommand` event handler, defined by `callback` (Lua function or Vimscript function name string) or `command` (Ex command string).
+--- Creates an `autocommand` event handler, defined by `callback` (Lua
+--- function or Vimscript function name string) or `command` (Ex command
+--- string).
+---
--- Example using Lua callback:
---
--- ```lua
@@ -817,39 +881,39 @@ function vim.api.nvim_create_augroup(name, opts) end
--- pattern = vim.fn.expand("~") .. "/some/path/*.py"
--- ```
---
+---
--- @param event any (string|array) Event(s) that will trigger the handler
--- (`callback` or `command`).
--- @param opts vim.api.keyset.create_autocmd Options dict:
---- • group (string|integer) optional: autocommand group name or
---- id to match against.
---- • pattern (string|array) optional: pattern(s) to match
---- literally `autocmd-pattern`.
---- • buffer (integer) optional: buffer number for buffer-local
---- autocommands `autocmd-buflocal`. Cannot be used with
---- {pattern}.
---- • desc (string) optional: description (for documentation and
---- troubleshooting).
---- • callback (function|string) optional: Lua function (or
---- Vimscript function name, if string) called when the
---- event(s) is triggered. Lua callback can return true to
---- delete the autocommand, and receives a table argument with
---- these keys:
---- • id: (number) autocommand id
---- • event: (string) name of the triggered event
---- `autocmd-events`
---- • group: (number|nil) autocommand group id, if any
---- • match: (string) expanded value of `<amatch>`
---- • buf: (number) expanded value of `<abuf>`
---- • file: (string) expanded value of `<afile>`
---- • data: (any) arbitrary data passed from
---- `nvim_exec_autocmds()`
----
---- • command (string) optional: Vim command to execute on event.
---- Cannot be used with {callback}
---- • once (boolean) optional: defaults to false. Run the
---- autocommand only once `autocmd-once`.
---- • nested (boolean) optional: defaults to false. Run nested
---- autocommands `autocmd-nested`.
+--- • group (string|integer) optional: autocommand group name or
+--- id to match against.
+--- • pattern (string|array) optional: pattern(s) to match
+--- literally `autocmd-pattern`.
+--- • buffer (integer) optional: buffer number for buffer-local
+--- autocommands `autocmd-buflocal`. Cannot be used with
+--- {pattern}.
+--- • desc (string) optional: description (for documentation and
+--- troubleshooting).
+--- • callback (function|string) optional: Lua function (or
+--- Vimscript function name, if string) called when the event(s)
+--- is triggered. Lua callback can return a truthy value (not
+--- `false` or `nil`) to delete the autocommand. Receives a
+--- table argument with these keys:
+--- • id: (number) autocommand id
+--- • event: (string) name of the triggered event
+--- `autocmd-events`
+--- • group: (number|nil) autocommand group id, if any
+--- • match: (string) expanded value of <amatch>
+--- • buf: (number) expanded value of <abuf>
+--- • file: (string) expanded value of <afile>
+--- • data: (any) arbitrary data passed from
+--- `nvim_exec_autocmds()`
+--- • command (string) optional: Vim command to execute on event.
+--- Cannot be used with {callback}
+--- • once (boolean) optional: defaults to false. Run the
+--- autocommand only once `autocmd-once`.
+--- • nested (boolean) optional: defaults to false. Run nested
+--- autocommands `autocmd-nested`.
--- @return integer
function vim.api.nvim_create_autocmd(event, opts) end
@@ -862,9 +926,11 @@ function vim.api.nvim_create_autocmd(event, opts) end
--- @return integer
function vim.api.nvim_create_buf(listed, scratch) end
---- Creates a new namespace or gets an existing one. *namespace*
+--- Creates a new namespace or gets an existing one. *namespace*
+---
--- Namespaces are used for buffer highlights and virtual text, see
--- `nvim_buf_add_highlight()` and `nvim_buf_set_extmark()`.
+---
--- Namespaces can be named or anonymous. If `name` matches an existing
--- namespace, the associated id is returned. If `name` is an empty string a
--- new, anonymous namespace is created.
@@ -874,7 +940,9 @@ function vim.api.nvim_create_buf(listed, scratch) end
function vim.api.nvim_create_namespace(name) end
--- Creates a global `user-commands` command.
+---
--- For Lua usage see `lua-guide-commands-create`.
+---
--- Example:
---
--- ```vim
@@ -883,51 +951,52 @@ function vim.api.nvim_create_namespace(name) end
--- Hello world!
--- ```
---
+---
--- @param name string Name of the new user command. Must begin with an uppercase
---- letter.
+--- letter.
--- @param command any Replacement command to execute when this user command is
--- executed. When called from Lua, the command can also be a
--- Lua function. The function is called with a single table
--- argument that contains the following keys:
--- • name: (string) Command name
--- • args: (string) The args passed to the command, if any
---- `<args>`
+--- <args>
--- • fargs: (table) The args split by unescaped whitespace
---- (when more than one argument is allowed), if any
---- `<f-args>`
+--- (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>`
+--- ! modifier <bang>
--- • line1: (number) The starting line of the command range
---- `<line1>`
+--- <line1>
--- • line2: (number) The final line of the command range
---- `<line2>`
+--- <line2>
--- • range: (number) The number of items in the command range:
---- 0, 1, or 2 `<range>`
---- • count: (number) Any count supplied `<count>`
---- • reg: (string) The optional register, if specified `<reg>`
---- • mods: (string) Command modifiers, if any `<mods>`
+--- 0, 1, or 2 <range>
+--- • count: (number) Any count supplied <count>
+--- • reg: (string) The optional register, if specified <reg>
+--- • mods: (string) Command modifiers, if any <mods>
--- • smods: (table) Command modifiers in a structured format.
--- Has the same structure as the "mods" key of
--- `nvim_parse_cmd()`.
--- @param opts vim.api.keyset.user_command Optional `command-attributes`.
---- • Set boolean attributes such as `:command-bang` or
---- `:command-bar` to true (but not `:command-buffer`, use
---- `nvim_buf_create_user_command()` instead).
---- • "complete" `:command-complete` also accepts a Lua
---- function which works like
---- `:command-completion-customlist`.
---- • Other parameters:
---- • desc: (string) Used for listing the command when a Lua
---- function is used for {command}.
---- • force: (boolean, default true) Override any previous
---- definition.
---- • preview: (function) Preview callback for 'inccommand'
---- `:command-preview`
+--- • Set boolean attributes such as `:command-bang` or
+--- `:command-bar` to true (but not `:command-buffer`, use
+--- `nvim_buf_create_user_command()` instead).
+--- • "complete" `:command-complete` also accepts a Lua function
+--- which works like `:command-completion-customlist`.
+--- • Other parameters:
+--- • desc: (string) Used for listing the command when a Lua
+--- function is used for {command}.
+--- • force: (boolean, default true) Override any previous
+--- definition.
+--- • preview: (function) Preview callback for 'inccommand'
+--- `:command-preview`
function vim.api.nvim_create_user_command(name, command, opts) end
--- Delete an autocommand group by id.
+---
--- To get a group id one can use `nvim_get_autocmds()`.
+---
--- NOTE: behavior differs from `:augroup-delete`. When deleting a group,
--- autocommands contained in this group will also be deleted and cleared.
--- This group will no longer exist.
@@ -936,6 +1005,7 @@ function vim.api.nvim_create_user_command(name, command, opts) end
function vim.api.nvim_del_augroup_by_id(id) end
--- Delete an autocommand group by name.
+---
--- NOTE: behavior differs from `:augroup-delete`. When deleting a group,
--- autocommands contained in this group will also be deleted and cleared.
--- This group will no longer exist.
@@ -953,6 +1023,7 @@ function vim.api.nvim_del_autocmd(id) end
function vim.api.nvim_del_current_line() end
--- Unmaps a global `mapping` for the given mode.
+---
--- To unmap a buffer-local mapping, use `nvim_buf_del_keymap()`.
---
--- @param mode string
@@ -977,15 +1048,15 @@ function vim.api.nvim_del_var(name) end
--- Echo a message.
---
---- @param chunks any[] A list of [text, hl_group] arrays, each representing a text
---- chunk with specified highlight. `hl_group` element can be
---- omitted for no highlight.
+--- @param chunks any[] A list of `[text, hl_group]` arrays, each representing a
+--- text chunk with specified highlight. `hl_group` element can
+--- be omitted for no highlight.
--- @param history boolean if true, add to `message-history`.
--- @param opts vim.api.keyset.echo_opts Optional parameters.
---- • verbose: Message was printed as a result of 'verbose'
---- option if Nvim was invoked with -V3log_file, the message
---- will be redirected to the log_file and suppressed from
---- direct output.
+--- • verbose: Message was printed as a result of 'verbose' option
+--- if Nvim was invoked with -V3log_file, the message will be
+--- redirected to the log_file and suppressed from direct
+--- output.
function vim.api.nvim_echo(chunks, history, opts) end
--- Writes a message to the Vim error buffer. Does not append "\n", the
@@ -1002,6 +1073,7 @@ function vim.api.nvim_err_writeln(str) end
--- Evaluates a Vimscript `expression`. Dictionaries and Lists are recursively
--- expanded.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
---
--- @param expr string Vimscript expression string
@@ -1036,8 +1108,10 @@ function vim.api.nvim_exec(src, output) end
--- Executes Vimscript (multiline block of Ex commands), like anonymous
--- `:source`.
+---
--- Unlike `nvim_command()` this function supports heredocs, script-scope
--- (s:), etc.
+---
--- On execution error: fails with Vimscript error, updates v:errmsg.
---
--- @param src string Vimscript code
@@ -1052,24 +1126,27 @@ function vim.api.nvim_exec2(src, opts) end
---
--- @param event any (String|Array) The event or events to execute
--- @param opts vim.api.keyset.exec_autocmds Dictionary of autocommand options:
---- • group (string|integer) optional: the autocommand group name
---- or id to match against. `autocmd-groups`.
---- • pattern (string|array) optional: defaults to "*"
---- `autocmd-pattern`. Cannot be used with {buffer}.
---- • buffer (integer) optional: buffer number
---- `autocmd-buflocal`. Cannot be used with {pattern}.
---- • modeline (bool) optional: defaults to true. Process the
---- modeline after the autocommands `<nomodeline>`.
---- • data (any): arbitrary data to send to the autocommand
---- callback. See `nvim_create_autocmd()` for details.
+--- • group (string|integer) optional: the autocommand group name
+--- or id to match against. `autocmd-groups`.
+--- • pattern (string|array) optional: defaults to "*"
+--- `autocmd-pattern`. Cannot be used with {buffer}.
+--- • buffer (integer) optional: buffer number `autocmd-buflocal`.
+--- Cannot be used with {pattern}.
+--- • modeline (bool) optional: defaults to true. Process the
+--- modeline after the autocommands <nomodeline>.
+--- • data (any): arbitrary data to send to the autocommand
+--- callback. See `nvim_create_autocmd()` for details.
function vim.api.nvim_exec_autocmds(event, opts) end
--- Sends input-keys to Nvim, subject to various quirks controlled by `mode`
--- flags. This is a blocking call, unlike `nvim_input()`.
+---
--- On execution error: does not fail, but updates v:errmsg.
+---
--- To input sequences like <C-o> use `nvim_replace_termcodes()` (typically
--- with escape_ks=false) to replace `keycodes`, then pass the result to
--- nvim_feedkeys().
+---
--- Example:
---
--- ```vim
@@ -1077,6 +1154,7 @@ function vim.api.nvim_exec_autocmds(event, opts) end
--- :call nvim_feedkeys(key, 'n', v:false)
--- ```
---
+---
--- @param keys string to be typed
--- @param mode string behavior flags, see `feedkeys()`
--- @param escape_ks boolean If true, escape K_SPECIAL bytes in `keys`. This should be
@@ -1085,6 +1163,7 @@ function vim.api.nvim_exec_autocmds(event, opts) end
function vim.api.nvim_feedkeys(keys, mode, escape_ks) end
--- Gets the option information for all options.
+---
--- The dictionary has the full option names as keys and option metadata
--- dictionaries as detailed at `nvim_get_option_info2()`.
---
@@ -1092,6 +1171,7 @@ function vim.api.nvim_feedkeys(keys, mode, escape_ks) end
function vim.api.nvim_get_all_options_info() end
--- Get all autocommands that match the corresponding {opts}.
+---
--- These examples will get autocommands matching ALL the given criteria:
---
--- ```lua
@@ -1121,17 +1201,18 @@ function vim.api.nvim_get_all_options_info() end
--- • buffer: Buffer number or list of buffer numbers for buffer
--- local autocommands `autocmd-buflocal`. Cannot be used with
--- {pattern}
---- @return any[]
+--- @return vim.api.keyset.get_autocmds.ret[]
function vim.api.nvim_get_autocmds(opts) end
--- Gets information about a channel.
---
---- @param chan integer
+--- @param chan integer channel_id, or 0 for current channel
--- @return table<string,any>
function vim.api.nvim_get_chan_info(chan) end
--- Returns the 24-bit RGB value of a `nvim_get_color_map()` color name or
--- "#rrggbb" hexadecimal string.
+---
--- Example:
---
--- ```vim
@@ -1139,18 +1220,21 @@ function vim.api.nvim_get_chan_info(chan) end
--- :echo nvim_get_color_by_name("#cbcbcb")
--- ```
---
+---
--- @param name string Color name or "#rrggbb" string
--- @return integer
function vim.api.nvim_get_color_by_name(name) end
--- Returns a map of color names and RGB values.
+---
--- Keys are color names (e.g. "Aqua") and values are 24-bit RGB color values
--- (e.g. 65535).
---
---- @return table<string,any>
+--- @return table<string,integer>
function vim.api.nvim_get_color_map() end
--- Gets a map of global (non-buffer-local) Ex commands.
+---
--- Currently only `user-commands` are supported, not builtin Ex commands.
---
--- @param opts vim.api.keyset.get_commands Optional parameters. Currently only supports {"builtin":false}
@@ -1191,13 +1275,13 @@ function vim.api.nvim_get_current_win() end
--- `nvim_get_namespaces()`. Use 0 to get global highlight groups
--- `:highlight`.
--- @param opts vim.api.keyset.get_highlight Options dict:
---- • name: (string) Get a highlight definition by name.
---- • id: (integer) Get a highlight definition by id.
---- • link: (boolean, default true) Show linked group name
---- instead of effective definition `:hi-link`.
---- • create: (boolean, default true) When highlight group
---- doesn't exist create it.
---- @return table<string,any>
+--- • name: (string) Get a highlight definition by name.
+--- • id: (integer) Get a highlight definition by id.
+--- • link: (boolean, default true) Show linked group name instead
+--- of effective definition `:hi-link`.
+--- • create: (boolean, default true) When highlight group doesn't
+--- exist create it.
+--- @return vim.api.keyset.hl_info
function vim.api.nvim_get_hl(ns_id, opts) end
--- @deprecated
@@ -1213,6 +1297,7 @@ function vim.api.nvim_get_hl_by_id(hl_id, rgb) end
function vim.api.nvim_get_hl_by_name(name, rgb) end
--- Gets a highlight group by name
+---
--- similar to `hlID()`, but allocates a new ID if not present.
---
--- @param name string
@@ -1232,28 +1317,29 @@ function vim.api.nvim_get_hl_ns(opts) end
--- Gets a list of global (non-buffer-local) `mapping` definitions.
---
--- @param mode string Mode short-name ("n", "i", "v", ...)
---- @return table<string,any>[]
+--- @return vim.api.keyset.keymap[]
function vim.api.nvim_get_keymap(mode) end
--- Returns a `(row, col, buffer, buffername)` tuple representing the position
--- of the uppercase/file named mark. "End of line" column position is
--- returned as `v:maxcol` (big number). See `mark-motions`.
+---
--- Marks are (1,0)-indexed. `api-indexing`
---
--- @param name string Mark name
---- @param opts table<string,any> Optional parameters. Reserved for future use.
---- @return any[]
+--- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use.
+--- @return vim.api.keyset.get_mark
function vim.api.nvim_get_mark(name, opts) end
--- Gets the current mode. `mode()` "blocking" is true if Nvim is waiting for
--- input.
---
---- @return table<string,any>
+--- @return vim.api.keyset.get_mode
function vim.api.nvim_get_mode() end
--- Gets existing, non-anonymous `namespace`s.
---
---- @return table<string,any>
+--- @return table<string,integer>
function vim.api.nvim_get_namespaces() end
--- @deprecated
@@ -1263,10 +1349,11 @@ function vim.api.nvim_get_option(name) end
--- @deprecated
--- @param name string
---- @return table<string,any>
+--- @return vim.api.keyset.get_option_info
function vim.api.nvim_get_option_info(name) end
--- Gets the option information for one option from arbitrary buffer or window
+---
--- Resulting dictionary has keys:
--- • name: Name of the option (like 'filetype')
--- • shortname: Shortened name of the option (like 'ft')
@@ -1293,7 +1380,7 @@ function vim.api.nvim_get_option_info(name) end
--- • win: `window-ID`. Used for getting window local options.
--- • buf: Buffer number. Used for getting buffer local options.
--- Implies {scope} is "local".
---- @return table<string,any>
+--- @return vim.api.keyset.get_option_info
function vim.api.nvim_get_option_info2(name, opts) end
--- Gets the value of an option. The behavior of this function matches that of
@@ -1328,10 +1415,12 @@ function vim.api.nvim_get_proc(pid) end
function vim.api.nvim_get_proc_children(pid) end
--- Find files in runtime directories
+---
--- "name" can contain wildcards. For example
--- nvim_get_runtime_file("colors/*.vim", true) will return all color scheme
--- files. Always use forward slashes (/) in the search pattern for
--- subdirectories regardless of platform.
+---
--- It is not an error to not find any files. An empty array is returned then.
---
--- @param name string pattern of files to search for
@@ -1354,6 +1443,7 @@ function vim.api.nvim_get_vvar(name) end
--- Queues raw user-input. Unlike `nvim_feedkeys()`, this uses a low-level
--- input buffer and the call is non-blocking (input is processed
--- asynchronously by the eventloop).
+---
--- On execution error: does not fail, but updates v:errmsg.
---
--- @param keys string to be typed
@@ -1361,14 +1451,15 @@ function vim.api.nvim_get_vvar(name) end
function vim.api.nvim_input(keys) end
--- Send mouse event from GUI.
+---
--- Non-blocking: does not wait on any result, but queues the event to be
--- processed soon by the event loop.
---
--- @param button string Mouse button: one of "left", "right", "middle", "wheel",
---- "move".
---- @param action string For ordinary buttons, one of "press", "drag", "release".
---- For the wheel, one of "up", "down", "left", "right".
---- Ignored for "move".
+--- "move", "x1", "x2".
+--- @param action string For ordinary buttons, one of "press", "drag", "release". For
+--- the wheel, one of "up", "down", "left", "right". Ignored for
+--- "move".
--- @param modifier string String of modifiers each represented by a single char. The
--- same specifiers are used as for a key press, except that
--- the "-" separator is optional, so "C-A-", "c-a" and "CA"
@@ -1379,6 +1470,7 @@ function vim.api.nvim_input(keys) end
function vim.api.nvim_input_mouse(button, action, modifier, grid, row, col) end
--- Gets the current list of buffer handles
+---
--- Includes unlisted (unloaded/deleted) buffers, like `:ls!`. Use
--- `nvim_buf_is_loaded()` to check if a buffer is loaded.
---
@@ -1417,6 +1509,7 @@ function vim.api.nvim_list_wins() end
function vim.api.nvim_load_context(dict) end
--- Notify the user with a message
+---
--- Relays the call to vim.notify . By default forwards your message in the
--- echo area but can be overridden to trigger desktop notifications.
---
@@ -1427,10 +1520,12 @@ function vim.api.nvim_load_context(dict) end
function vim.api.nvim_notify(msg, log_level, opts) end
--- Open a terminal instance in a buffer
+---
--- By default (and currently the only option) the terminal will not be
--- connected to an external process. Instead, input send on the channel will
--- be echoed directly by the terminal. This is useful to display ANSI
--- terminal sequences returned as part of a rpc message, or similar.
+---
--- Note: to directly initiate the terminal using the right size, display the
--- buffer in a configured window before calling this. For instance, for a
--- floating display, first create an empty buffer using `nvim_create_buf()`,
@@ -1439,34 +1534,51 @@ function vim.api.nvim_notify(msg, log_level, opts) end
--- virtual terminal having the intended size.
---
--- @param buffer integer the buffer to use (expected to be empty)
---- @param opts table<string,function> Optional parameters.
---- • on_input: Lua callback for input sent, i e keypresses in
---- terminal mode. Note: keypresses are sent raw as they would
---- be to the pty master end. For instance, a carriage return
---- is sent as a "\r", not as a "\n". `textlock` applies. It
---- is possible to call `nvim_chan_send()` directly in the
---- callback however. ["input", term, bufnr, data]
+--- @param opts vim.api.keyset.open_term Optional parameters.
+--- • on_input: Lua callback for input sent, i e keypresses in
+--- terminal mode. Note: keypresses are sent raw as they would
+--- be to the pty master end. For instance, a carriage return is
+--- sent as a "\r", not as a "\n". `textlock` applies. It is
+--- possible to call `nvim_chan_send()` directly in the callback
+--- however. `["input", term, bufnr, data]`
+--- • force_crlf: (boolean, default true) Convert "\n" to "\r\n".
--- @return integer
function vim.api.nvim_open_term(buffer, opts) end
---- Open a new window.
---- Currently this is used to open floating and external windows. Floats are
---- windows that are drawn above the split layout, at some anchor position in
---- some other window. Floats can be drawn internally or by external GUI with
---- the `ui-multigrid` extension. External windows are only supported with
---- multigrid GUIs, and are displayed as separate top-level windows.
+--- Opens a new split window, or a floating window if `relative` is specified,
+--- or an external window (managed by the UI) if `external` is specified.
+---
+--- Floats are windows that are drawn above the split layout, at some anchor
+--- position in some other window. Floats can be drawn internally or by
+--- external GUI with the `ui-multigrid` extension. External windows are only
+--- supported with multigrid GUIs, and are displayed as separate top-level
+--- windows.
+---
--- For a general overview of floats, see `api-floatwin`.
---- Exactly one of `external` and `relative` must be specified. The `width`
---- and `height` of the new window must be specified.
+---
+--- The `width` and `height` of the new window must be specified when opening
+--- a floating window, but are optional for normal windows.
+---
+--- If `relative` and `external` are omitted, a normal "split" window is
+--- created. The `win` property determines which window will be split. If no
+--- `win` is provided or `win == 0`, a window will be created adjacent to the
+--- current window. If -1 is provided, a top-level split will be created.
+--- `vertical` and `split` are only valid for normal windows, and are used to
+--- control split direction. For `vertical`, the exact direction is determined
+--- by `'splitright'` and `'splitbelow'`. Split windows cannot have
+--- `bufpos`/`row`/`col`/`border`/`title`/`footer` properties.
+---
--- With relative=editor (row=0,col=0) refers to the top-left corner of the
--- screen-grid and (row=Lines-1,col=Columns-1) refers to the bottom-right
--- corner. Fractional values are allowed, but the builtin implementation
--- (used by non-multigrid UIs) will always round down to nearest integer.
+---
--- Out-of-bounds values, and configurations that make the float not fit
--- inside the main editor, are allowed. The builtin implementation truncates
--- values so floats are fully within the main screen grid. External GUIs
--- could let floats hover outside of the main window like a tooltip, but this
--- should not be used to specify arbitrary WM screen positions.
+---
--- Example (Lua): window-relative float
---
--- ```lua
@@ -1479,12 +1591,21 @@ function vim.api.nvim_open_term(buffer, opts) end
--- ```lua
--- vim.api.nvim_open_win(0, false,
--- {relative='win', width=12, height=3, bufpos={100,10}})
+--- ```
+---
+--- Example (Lua): vertical split left of the current window
+---
+--- ```lua
+--- vim.api.nvim_open_win(0, false, {
+--- split = 'left',
+--- win = 0
--- })
--- ```
---
+---
--- @param buffer integer Buffer to display, or 0 for current buffer
--- @param enter boolean Enter the window (make it the current window)
---- @param config vim.api.keyset.float_config Map defining the window configuration. Keys:
+--- @param config vim.api.keyset.win_config Map defining the window configuration. Keys:
--- • relative: Sets the window layout to "floating", placed at
--- (row,col) coordinates relative to:
--- • "editor" The global editor grid
@@ -1492,25 +1613,23 @@ function vim.api.nvim_open_term(buffer, opts) end
--- window.
--- • "cursor" Cursor position in current window.
--- • "mouse" Mouse position
----
---- • win: `window-ID` for relative="win".
+--- • win: `window-ID` window to split, or relative window when
+--- creating a float (relative="win").
--- • anchor: Decides which corner of the float to place at
--- (row,col):
--- • "NW" northwest (default)
--- • "NE" northeast
--- • "SW" southwest
--- • "SE" southeast
----
--- • width: Window width (in character cells). Minimum of 1.
--- • height: Window height (in character cells). Minimum of 1.
--- • bufpos: Places float relative to buffer text (only when
---- relative="win"). Takes a tuple of zero-indexed [line,
---- column]. `row` and `col` if given are applied relative to this position, else they
---- default to:
+--- relative="win"). Takes a tuple of zero-indexed
+--- `[line, column]`. `row` and `col` if given are applied
+--- relative to this position, else they default to:
--- • `row=1` and `col=0` if `anchor` is "NW" or "NE"
--- • `row=0` and `col=0` if `anchor` is "SW" or "SE" (thus
--- like a tooltip near the buffer text).
----
--- • row: Row position in units of "screen cell height", may be
--- fractional.
--- • col: Column position in units of "screen cell width", may
@@ -1521,8 +1640,9 @@ function vim.api.nvim_open_term(buffer, opts) end
--- • external: GUI should display the window as an external
--- top-level window. Currently accepts no other positioning
--- configuration together with this.
---- • zindex: Stacking order. floats with higher `zindex` go on top on floats with lower indices. Must be larger
---- than zero. The following screen elements have hard-coded
+--- • zindex: Stacking order. floats with higher `zindex` go on
+--- top on floats with lower indices. Must be larger than
+--- zero. The following screen elements have hard-coded
--- z-indices:
--- • 100: insert completion popupmenu
--- • 200: message scrollback
@@ -1530,7 +1650,6 @@ function vim.api.nvim_open_term(buffer, opts) end
--- wildoptions+=pum) The default value for floats are 50.
--- In general, values below 100 are recommended, unless
--- there is a good reason to overshadow builtin elements.
----
--- • style: (optional) Configure the appearance of the window.
--- Currently only supports one value:
--- • "minimal" Nvim will display the window with many UI
@@ -1543,14 +1662,13 @@ function vim.api.nvim_open_term(buffer, opts) end
--- empty. The end-of-buffer region is hidden by setting
--- `eob` flag of 'fillchars' to a space char, and clearing
--- the `hl-EndOfBuffer` region in 'winhighlight'.
----
--- • border: Style of (optional) window border. This can either
--- be a string or an array. The string values are
--- • "none": No border (default).
--- • "single": A single line box.
--- • "double": A double line box.
---- • "rounded": Like "single", but with rounded corners ("╭"
---- etc.).
+--- • "rounded": Like "single", but with rounded corners
+--- ("â•­" etc.).
--- • "solid": Adds padding by a single whitespace cell.
--- • "shadow": A drop shadow effect by blending with the
--- background.
@@ -1558,18 +1676,35 @@ function vim.api.nvim_open_term(buffer, opts) end
--- any divisor of eight. The array will specify the eight
--- chars building up the border in a clockwise fashion
--- starting with the top-left corner. As an example, the
---- double box style could be specified as [ "â•”", "â•" ,"â•—",
---- "â•‘", "â•", "â•", "╚", "â•‘" ]. If the number of chars are
---- less than eight, they will be repeated. Thus an ASCII
---- border could be specified as [ "/", "-", "\\", "|" ], or
---- all chars the same as [ "x" ]. An empty string can be
---- used to turn off a specific border, for instance, [ "",
---- "", "", ">", "", "", "", "<" ] will only make vertical
---- borders but not horizontal ones. By default,
---- `FloatBorder` highlight is used, which links to
---- `WinSeparator` when not defined. It could also be
---- specified by character: [ ["+", "MyCorner"], ["x",
---- "MyBorder"] ].
+--- double box style could be specified as:
+--- ```
+--- [ "â•”", "â•" ,"â•—", "â•‘", "â•", "â•", "╚", "â•‘" ].
+--- ```
+---
+--- If the number of chars are less than eight, they will be
+--- repeated. Thus an ASCII border could be specified as
+--- ```
+--- [ "/", "-", \"\\\\\", "|" ],
+--- ```
+---
+--- or all chars the same as
+--- ```
+--- [ "x" ].
+--- ```
+---
+--- An empty string can be used to turn off a specific border,
+--- for instance,
+--- ```
+--- [ "", "", "", ">", "", "", "", "<" ]
+--- ```
+---
+--- will only make vertical borders but not horizontal ones.
+--- By default, `FloatBorder` highlight is used, which links
+--- to `WinSeparator` when not defined. It could also be
+--- specified by character:
+--- ```
+--- [ ["+", "MyCorner"], ["x", "MyBorder"] ].
+--- ```
---
--- • title: Title (optional) in window border, string or list.
--- List should consist of `[text, highlight]` tuples. If
@@ -1589,6 +1724,8 @@ function vim.api.nvim_open_term(buffer, opts) end
--- • fixed: If true when anchor is NW or SW, the float window
--- would be kept fixed even if the window would be truncated.
--- • hide: If true the floating window will be hidden.
+--- • vertical: Split vertically `:vertical`.
+--- • split: Split direction: "left", "right", "above", "below".
--- @return integer
function vim.api.nvim_open_win(buffer, enter, config) end
@@ -1599,28 +1736,29 @@ function vim.api.nvim_open_win(buffer, enter, config) end
function vim.api.nvim_out_write(str) end
--- Parse command line.
+---
--- Doesn't check the validity of command arguments.
---
--- @param str string Command line string to parse. Cannot contain "\n".
---- @param opts table<string,any> Optional parameters. Reserved for future use.
---- @return table<string,any>
+--- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use.
+--- @return vim.api.keyset.parse_cmd
function vim.api.nvim_parse_cmd(str, opts) end
--- Parse a Vimscript expression.
---
--- @param expr string Expression to parse. Always treated as a single line.
--- @param flags string Flags:
---- • "m" if multiple expressions in a row are allowed (only
---- the first one will be parsed),
---- • "E" if EOC tokens are not allowed (determines whether
---- they will stop parsing process or be recognized as an
---- operator/space, though also yielding an error).
---- • "l" when needing to start parsing with lvalues for
---- ":let" or ":for". Common flag sets:
---- • "m" to parse like for ":echo".
---- • "E" to parse like for "<C-r>=".
---- • empty string for ":call".
---- • "lm" to parse for ":let".
+--- • "m" if multiple expressions in a row are allowed (only the
+--- first one will be parsed),
+--- • "E" if EOC tokens are not allowed (determines whether they
+--- will stop parsing process or be recognized as an
+--- operator/space, though also yielding an error).
+--- • "l" when needing to start parsing with lvalues for ":let"
+--- or ":for". Common flag sets:
+--- • "m" to parse like for `":echo"`.
+--- • "E" to parse like for `"<C-r>="`.
+--- • empty string for ":call".
+--- • "lm" to parse for ":let".
--- @param highlight boolean If true, return value will also include "highlight" key
--- containing array of 4-tuples (arrays) (Integer, Integer,
--- Integer, String), where first three numbers define the
@@ -1631,8 +1769,10 @@ function vim.api.nvim_parse_cmd(str, opts) end
function vim.api.nvim_parse_expression(expr, flags, highlight) end
--- Pastes at cursor, in any mode.
+---
--- Invokes the `vim.paste` handler, which handles each mode appropriately.
--- Sets redo/undo. Faster than `nvim_input()`. Lines break at LF ("\n").
+---
--- Errors ('nomodifiable', `vim.paste()` failure, …) are reflected in `err`
--- but do not affect the return value (which is strictly decided by
--- `vim.paste()`). On error, subsequent calls are ignored ("drained") until
@@ -1641,7 +1781,8 @@ function vim.api.nvim_parse_expression(expr, flags, highlight) end
--- @param data string Multiline input. May be binary (containing NUL bytes).
--- @param crlf boolean Also break lines at CR and CRLF.
--- @param phase integer -1: paste in a single call (i.e. without streaming). To
---- "stream" a paste, call `nvim_paste` sequentially with these `phase` values:
+--- "stream" a paste, call `nvim_paste` sequentially with these
+--- `phase` values:
--- • 1: starts the paste (exactly once)
--- • 2: continues the paste (zero or more times)
--- • 3: ends the paste (exactly once)
@@ -1649,16 +1790,16 @@ function vim.api.nvim_parse_expression(expr, flags, highlight) end
function vim.api.nvim_paste(data, crlf, phase) end
--- Puts text at cursor, in any mode.
+---
--- Compare `:put` and `p` which are always linewise.
---
--- @param lines string[] `readfile()`-style list of lines. `channel-lines`
--- @param type string Edit behavior: any `getregtype()` result, or:
---- • "b" `blockwise-visual` mode (may include width, e.g. "b3")
---- • "c" `charwise` mode
---- • "l" `linewise` mode
---- • "" guess by contents, see `setreg()`
---- @param after boolean If true insert after cursor (like `p`), or before (like
---- `P`).
+--- • "b" `blockwise-visual` mode (may include width, e.g. "b3")
+--- • "c" `charwise` mode
+--- • "l" `linewise` mode
+--- • "" guess by contents, see `setreg()`
+--- @param after boolean If true insert after cursor (like `p`), or before (like `P`).
--- @param follow boolean If true place cursor at end of inserted text.
function vim.api.nvim_put(lines, type, after, follow) end
@@ -1673,19 +1814,20 @@ function vim.api.nvim_put(lines, type, after, follow) end
function vim.api.nvim_replace_termcodes(str, from_part, do_lt, special) end
--- Selects an item in the completion popup menu.
+---
--- If neither `ins-completion` nor `cmdline-completion` popup menu is active
--- this API call is silently ignored. Useful for an external UI using
--- `ui-popupmenu` to control the popup menu with the mouse. Can also be used
--- in a mapping; use <Cmd> `:map-cmd` or a Lua mapping to ensure the mapping
--- doesn't end completion mode.
---
---- @param item integer Index (zero-based) of the item to select. Value of -1
---- selects nothing and restores the original text.
+--- @param item integer Index (zero-based) of the item to select. Value of -1 selects
+--- nothing and restores the original text.
--- @param insert boolean For `ins-completion`, whether the selection should be
--- inserted in the buffer. Ignored for `cmdline-completion`.
--- @param finish boolean Finish the completion and dismiss the popup menu. Implies
--- {insert}.
---- @param opts table<string,any> Optional parameters. Reserved for future use.
+--- @param opts vim.api.keyset.empty Optional parameters. Reserved for future use.
function vim.api.nvim_select_popupmenu_item(item, insert, finish, opts) end
--- Sets the current buffer.
@@ -1714,13 +1856,16 @@ function vim.api.nvim_set_current_tabpage(tabpage) end
function vim.api.nvim_set_current_win(window) end
--- Set or change decoration provider for a `namespace`
+---
--- This is a very general purpose interface for having Lua callbacks being
--- triggered during the redraw code.
+---
--- The expected usage is to set `extmarks` for the currently redrawn buffer.
--- `nvim_buf_set_extmark()` can be called to add marks on a per-window or
--- per-lines basis. Use the `ephemeral` key to only use the mark for the
--- current screen redraw (the callback will be called again for the next
--- redraw).
+---
--- Note: this function should not be called often. Rather, the callbacks
--- themselves can be used to throttle unneeded callbacks. the `on_start`
--- callback can return `false` to disable the provider until the next redraw.
@@ -1729,28 +1874,44 @@ function vim.api.nvim_set_current_win(window) end
--- plugin managing multiple sources of decoration should ideally only set one
--- provider, and merge the sources internally. You can use multiple `ns_id`
--- for the extmarks set/modified inside the callback anyway.
+---
--- Note: doing anything other than setting extmarks is considered
--- experimental. Doing things like changing options are not explicitly
--- forbidden, but is likely to have unexpected consequences (such as 100% CPU
--- consumption). doing `vim.rpcnotify` should be OK, but `vim.rpcrequest` is
--- quite dubious for the moment.
+---
--- Note: It is not allowed to remove or update extmarks in 'on_line'
--- callbacks.
---
--- @param ns_id integer Namespace id from `nvim_create_namespace()`
--- @param opts vim.api.keyset.set_decoration_provider Table of callbacks:
---- • on_start: called first on each screen redraw ["start",
---- tick]
---- • on_buf: called for each buffer being redrawn (before window
---- callbacks) ["buf", bufnr, tick]
---- • on_win: called when starting to redraw a specific window.
---- botline_guess is an approximation that does not exceed the
---- last line number. ["win", winid, bufnr, topline,
---- botline_guess]
---- • on_line: called for each buffer line being redrawn. (The
---- interaction with fold lines is subject to change) ["win",
---- winid, bufnr, row]
---- • on_end: called at the end of a redraw cycle ["end", tick]
+--- • on_start: called first on each screen redraw
+--- ```
+--- ["start", tick]
+--- ```
+---
+--- • on_buf: called for each buffer being redrawn (before window
+--- callbacks)
+--- ```
+--- ["buf", bufnr, tick]
+--- ```
+---
+--- • on_win: called when starting to redraw a specific window.
+--- ```
+--- ["win", winid, bufnr, topline, botline]
+--- ```
+---
+--- • on_line: called for each buffer line being redrawn. (The
+--- interaction with fold lines is subject to change)
+--- ```
+--- ["line", winid, bufnr, row]
+--- ```
+---
+--- • on_end: called at the end of a redraw cycle
+--- ```
+--- ["end", tick]
+--- ```
function vim.api.nvim_set_decoration_provider(ns_id, opts) end
--- Sets a highlight group.
@@ -1762,31 +1923,31 @@ function vim.api.nvim_set_decoration_provider(ns_id, opts) end
--- activate them.
--- @param name string Highlight group name, e.g. "ErrorMsg"
--- @param val vim.api.keyset.highlight Highlight definition map, accepts the following keys:
---- • fg (or foreground): color name or "#RRGGBB", see note.
---- • bg (or background): color name or "#RRGGBB", see note.
---- • sp (or special): color name or "#RRGGBB"
---- • blend: integer between 0 and 100
---- • bold: boolean
---- • standout: boolean
---- • underline: boolean
---- • undercurl: boolean
---- • underdouble: boolean
---- • underdotted: boolean
---- • underdashed: boolean
---- • strikethrough: boolean
---- • italic: boolean
---- • reverse: boolean
---- • nocombine: boolean
---- • link: name of another highlight group to link to, see
---- `:hi-link`.
---- • default: Don't override existing definition `:hi-default`
---- • ctermfg: Sets foreground of cterm color `ctermfg`
---- • ctermbg: Sets background of cterm color `ctermbg`
---- • cterm: cterm attribute map, like `highlight-args`. If not
---- set, cterm attributes will match those from the attribute
---- map documented above.
---- • force: if true force update the highlight group when it
---- exists.
+--- • fg: color name or "#RRGGBB", see note.
+--- • bg: color name or "#RRGGBB", see note.
+--- • sp: color name or "#RRGGBB"
+--- • blend: integer between 0 and 100
+--- • bold: boolean
+--- • standout: boolean
+--- • underline: boolean
+--- • undercurl: boolean
+--- • underdouble: boolean
+--- • underdotted: boolean
+--- • underdashed: boolean
+--- • strikethrough: boolean
+--- • italic: boolean
+--- • reverse: boolean
+--- • nocombine: boolean
+--- • link: name of another highlight group to link to, see
+--- `:hi-link`.
+--- • default: Don't override existing definition `:hi-default`
+--- • ctermfg: Sets foreground of cterm color `ctermfg`
+--- • ctermbg: Sets background of cterm color `ctermbg`
+--- • cterm: cterm attribute map, like `highlight-args`. If not
+--- set, cterm attributes will match those from the attribute map
+--- documented above.
+--- • force: if true force update the highlight group when it
+--- exists.
function vim.api.nvim_set_hl(ns_id, name, val) end
--- Set active namespace for highlights defined with `nvim_set_hl()`. This can
@@ -1797,6 +1958,7 @@ function vim.api.nvim_set_hl_ns(ns_id) end
--- Set active namespace for highlights defined with `nvim_set_hl()` while
--- redrawing.
+---
--- This function meant to be called while redrawing, primarily from
--- `nvim_set_decoration_provider()` on_win and on_line callbacks, which are
--- allowed to change the namespace during a redraw cycle.
@@ -1805,9 +1967,12 @@ function vim.api.nvim_set_hl_ns(ns_id) end
function vim.api.nvim_set_hl_ns_fast(ns_id) end
--- Sets a global `mapping` for the given mode.
+---
--- To set a buffer-local mapping, use `nvim_buf_set_keymap()`.
+---
--- Unlike `:map`, leading/trailing whitespace is accepted as part of the
---- {lhs} or {rhs}. Empty {rhs} is `<Nop>`. `keycodes` are replaced as usual.
+--- {lhs} or {rhs}. Empty {rhs} is <Nop>. `keycodes` are replaced as usual.
+---
--- Example:
---
--- ```vim
@@ -1820,14 +1985,15 @@ function vim.api.nvim_set_hl_ns_fast(ns_id) end
--- nmap <nowait> <Space><NL> <Nop>
--- ```
---
---- @param mode string Mode short-name (map command prefix: "n", "i", "v", "x", …) or
---- "!" for `:map!`, or empty string for `:map`. "ia", "ca" or
+---
+--- @param mode string Mode short-name (map command prefix: "n", "i", "v", "x", …)
+--- or "!" for `:map!`, or empty string for `:map`. "ia", "ca" or
--- "!a" for abbreviation in Insert mode, Cmdline mode, or both,
--- respectively
--- @param lhs string Left-hand-side `{lhs}` of the mapping.
--- @param rhs string Right-hand-side `{rhs}` of the mapping.
--- @param opts vim.api.keyset.keymap Optional parameters map: Accepts all `:map-arguments` as keys
---- except `<buffer>`, values are booleans (default false). Also:
+--- except <buffer>, values are booleans (default false). Also:
--- • "noremap" disables `recursive_mapping`, like `:noremap`
--- • "desc" human-readable description.
--- • "callback" Lua function called in place of {rhs}.
@@ -1845,15 +2011,16 @@ function vim.api.nvim_set_option(name, value) end
--- Sets the value of an option. The behavior of this function matches that of
--- `:set`: for global-local options, both the global and local value are set
--- unless otherwise specified with {scope}.
+---
--- Note the options {win} and {buf} cannot be used together.
---
--- @param name string Option name
--- @param value any New option value
--- @param opts vim.api.keyset.option Optional parameters
---- • scope: One of "global" or "local". Analogous to
---- `:setglobal` and `:setlocal`, respectively.
---- • win: `window-ID`. Used for setting window local option.
---- • buf: Buffer number. Used for setting buffer local option.
+--- • scope: One of "global" or "local". Analogous to `:setglobal`
+--- and `:setlocal`, respectively.
+--- • win: `window-ID`. Used for setting window local option.
+--- • buf: Buffer number. Used for setting buffer local option.
function vim.api.nvim_set_option_value(name, value, opts) end
--- Sets a global (g:) variable.
@@ -1919,11 +2086,24 @@ function vim.api.nvim_tabpage_list_wins(tabpage) end
--- @param value any Variable value
function vim.api.nvim_tabpage_set_var(tabpage, name, value) end
+--- Sets the current window in a tabpage
+---
+--- @param tabpage integer Tabpage handle, or 0 for current tabpage
+--- @param win integer Window handle, must already belong to {tabpage}
+function vim.api.nvim_tabpage_set_win(tabpage, win) end
+
+--- Adds the namespace scope to the window.
+---
+--- @param window integer Window handle, or 0 for current window
+--- @param ns_id integer the namespace to add
+--- @return boolean
+function vim.api.nvim_win_add_ns(window, ns_id) end
+
--- Calls a function with window as temporary current window.
---
--- @param window integer Window handle, or 0 for current window
--- @param fun function Function to call inside the window (currently Lua callable
---- only)
+--- only)
--- @return any
function vim.api.nvim_win_call(window, fun) end
@@ -1931,8 +2111,8 @@ function vim.api.nvim_win_call(window, fun) end
---
--- @param window integer Window handle, or 0 for current window
--- @param force boolean Behave like `:close!` The last window of a buffer with
---- unwritten changes can be closed. The buffer will become
---- hidden, even if 'hidden' is not set.
+--- unwritten changes can be closed. The buffer will become
+--- hidden, even if 'hidden' is not set.
function vim.api.nvim_win_close(window, force) end
--- Removes a window-scoped (w:) variable
@@ -1948,11 +2128,13 @@ function vim.api.nvim_win_del_var(window, name) end
function vim.api.nvim_win_get_buf(window) end
--- Gets window configuration.
+---
--- The returned value may be given to `nvim_open_win()`.
+---
--- `relative` is empty for normal windows.
---
--- @param window integer Window handle, or 0 for current window
---- @return table<string,any>
+--- @return vim.api.keyset.win_config
function vim.api.nvim_win_get_config(window) end
--- Gets the (1,0)-indexed, buffer-relative cursor position for a given window
@@ -1969,6 +2151,12 @@ function vim.api.nvim_win_get_cursor(window) end
--- @return integer
function vim.api.nvim_win_get_height(window) end
+--- Gets all the namespaces scopes associated with a window.
+---
+--- @param window integer Window handle, or 0 for current window
+--- @return integer[]
+function vim.api.nvim_win_get_ns(window) end
+
--- Gets the window number
---
--- @param window integer Window handle, or 0 for current window
@@ -2008,6 +2196,7 @@ function vim.api.nvim_win_get_width(window) end
--- Closes the window and hide the buffer it contains (like `:hide` with a
--- `window-ID`).
+---
--- Like `:hide` the buffer becomes hidden unless another window is editing
--- it, or 'bufhidden' is `unload`, `delete` or `wipe` as opposed to `:close`
--- or `nvim_win_close()`, which will close the buffer.
@@ -2021,6 +2210,13 @@ function vim.api.nvim_win_hide(window) end
--- @return boolean
function vim.api.nvim_win_is_valid(window) end
+--- Removes the namespace scope from the window.
+---
+--- @param window integer Window handle, or 0 for current window
+--- @param ns_id integer the namespace to remove
+--- @return boolean
+function vim.api.nvim_win_remove_ns(window, ns_id) end
+
--- Sets the current buffer in a window, without side effects
---
--- @param window integer Window handle, or 0 for current window
@@ -2029,11 +2225,12 @@ function vim.api.nvim_win_set_buf(window, buffer) end
--- Configures window layout. Currently only for floating and external windows
--- (including changing a split window to those layouts).
+---
--- When reconfiguring a floating window, absent option keys will not be
--- changed. `row`/`col` and `relative` must be reconfigured together.
---
--- @param window integer Window handle, or 0 for current window
---- @param config vim.api.keyset.float_config Map defining the window configuration, see `nvim_open_win()`
+--- @param config vim.api.keyset.win_config Map defining the window configuration, see `nvim_open_win()`
function vim.api.nvim_win_set_config(window, config) end
--- Sets the (1,0)-indexed cursor position in the window. `api-indexing` This
@@ -2052,6 +2249,7 @@ function vim.api.nvim_win_set_height(window, height) end
--- Set highlight namespace for a window. This will use highlights defined
--- with `nvim_set_hl()` for this namespace, but fall back to global
--- highlights (ns=0) when missing.
+---
--- This takes precedence over the 'winhighlight' option.
---
--- @param window integer
@@ -2080,23 +2278,26 @@ function vim.api.nvim_win_set_width(window, width) end
--- Computes the number of screen lines occupied by a range of text in a given
--- window. Works for off-screen text and takes folds into account.
+---
--- Diff filler or virtual lines above a line are counted as a part of that
--- line, unless the line is on "start_row" and "start_vcol" is specified.
+---
--- Diff filler or virtual lines below the last buffer line are counted in the
--- result when "end_row" is omitted.
+---
--- Line indexing is similar to `nvim_buf_get_text()`.
---
--- @param window integer Window handle, or 0 for current window.
--- @param opts vim.api.keyset.win_text_height Optional parameters:
---- • start_row: Starting line index, 0-based inclusive. When
---- omitted start at the very top.
---- • end_row: Ending line index, 0-based inclusive. When
---- omitted end at the very bottom.
---- • start_vcol: Starting virtual column index on "start_row",
---- 0-based inclusive, rounded down to full screen lines. When
---- omitted include the whole line.
---- • end_vcol: Ending virtual column index on "end_row",
---- 0-based exclusive, rounded up to full screen lines. When
---- omitted include the whole line.
+--- • start_row: Starting line index, 0-based inclusive. When
+--- omitted start at the very top.
+--- • end_row: Ending line index, 0-based inclusive. When omitted
+--- end at the very bottom.
+--- • start_vcol: Starting virtual column index on "start_row",
+--- 0-based inclusive, rounded down to full screen lines. When
+--- omitted include the whole line.
+--- • end_vcol: Ending virtual column index on "end_row", 0-based
+--- exclusive, rounded up to full screen lines. When omitted
+--- include the whole line.
--- @return table<string,any>
function vim.api.nvim_win_text_height(window, opts) end
diff --git a/runtime/lua/vim/_meta/api_keysets.lua b/runtime/lua/vim/_meta/api_keysets.lua
index f69e5a92c7..37e4372196 100644
--- a/runtime/lua/vim/_meta/api_keysets.lua
+++ b/runtime/lua/vim/_meta/api_keysets.lua
@@ -3,6 +3,19 @@
-- DO NOT EDIT
error('Cannot require a meta file')
+--- @class vim.api.keyset.buf_attach
+--- @field on_lines? function
+--- @field on_bytes? function
+--- @field on_changedtick? function
+--- @field on_detach? function
+--- @field on_reload? function
+--- @field utf_sizes? boolean
+--- @field preview? boolean
+
+--- @class vim.api.keyset.buf_delete
+--- @field force? boolean
+--- @field unload? boolean
+
--- @class vim.api.keyset.clear_autocmds
--- @field buffer? integer
--- @field event? any
@@ -55,6 +68,9 @@ error('Cannot require a meta file')
--- @class vim.api.keyset.cmd_opts
--- @field output? boolean
+--- @class vim.api.keyset.complete_set
+--- @field info? string
+
--- @class vim.api.keyset.context
--- @field types? any[]
@@ -74,6 +90,8 @@ error('Cannot require a meta file')
--- @class vim.api.keyset.echo_opts
--- @field verbose? boolean
+--- @class vim.api.keyset.empty
+
--- @class vim.api.keyset.eval_statusline
--- @field winid? integer
--- @field maxwidth? integer
@@ -93,28 +111,6 @@ error('Cannot require a meta file')
--- @class vim.api.keyset.exec_opts
--- @field output? boolean
---- @class vim.api.keyset.float_config
---- @field row? number
---- @field col? number
---- @field width? integer
---- @field height? integer
---- @field anchor? string
---- @field relative? string
---- @field win? integer
---- @field bufpos? any[]
---- @field external? boolean
---- @field focusable? boolean
---- @field zindex? integer
---- @field border? any
---- @field title? any
---- @field title_pos? string
---- @field footer? any
---- @field footer_pos? string
---- @field style? string
---- @field noautocmd? boolean
---- @field fixed? boolean
---- @field hide? boolean
-
--- @class vim.api.keyset.get_autocmds
--- @field event? any
--- @field group? any
@@ -124,6 +120,10 @@ error('Cannot require a meta file')
--- @class vim.api.keyset.get_commands
--- @field builtin? boolean
+--- @class vim.api.keyset.get_extmark
+--- @field details? boolean
+--- @field hl_name? boolean
+
--- @class vim.api.keyset.get_extmarks
--- @field limit? integer
--- @field details? boolean
@@ -170,6 +170,7 @@ error('Cannot require a meta file')
--- @field fg_indexed? boolean
--- @field bg_indexed? boolean
--- @field force? boolean
+--- @field url? string
--- @class vim.api.keyset.highlight_cterm
--- @field bold? boolean
@@ -196,6 +197,10 @@ error('Cannot require a meta file')
--- @field desc? string
--- @field replace_keycodes? boolean
+--- @class vim.api.keyset.open_term
+--- @field on_input? function
+--- @field force_crlf? boolean
+
--- @class vim.api.keyset.option
--- @field scope? string
--- @field win? integer
@@ -220,11 +225,12 @@ error('Cannot require a meta file')
--- @field end_line? integer
--- @field end_row? integer
--- @field end_col? integer
---- @field hl_group? any
+--- @field hl_group? number|string
--- @field virt_text? any[]
--- @field virt_text_pos? string
--- @field virt_text_win_col? integer
--- @field virt_text_hide? boolean
+--- @field virt_text_repeat_linebreak? boolean
--- @field hl_eol? boolean
--- @field hl_mode? string
--- @field invalidate? boolean
@@ -237,14 +243,17 @@ error('Cannot require a meta file')
--- @field virt_lines_leftcol? boolean
--- @field strict? boolean
--- @field sign_text? string
---- @field sign_hl_group? any
---- @field number_hl_group? any
---- @field line_hl_group? any
---- @field cursorline_hl_group? any
+--- @field sign_hl_group? number|string
+--- @field number_hl_group? number|string
+--- @field line_hl_group? number|string
+--- @field cursorline_hl_group? number|string
--- @field conceal? string
--- @field spell? boolean
--- @field ui_watched? boolean
--- @field undo_restore? boolean
+--- @field url? string
+--- @field scoped? boolean
+--- @field _subpriority? integer
--- @class vim.api.keyset.user_command
--- @field addr? any
@@ -260,8 +269,46 @@ error('Cannot require a meta file')
--- @field range? any
--- @field register? boolean
+--- @class vim.api.keyset.win_config
+--- @field row? number
+--- @field col? number
+--- @field width? integer
+--- @field height? integer
+--- @field anchor? string
+--- @field relative? string
+--- @field split? string
+--- @field win? integer
+--- @field bufpos? any[]
+--- @field external? boolean
+--- @field focusable? boolean
+--- @field vertical? boolean
+--- @field zindex? integer
+--- @field border? any
+--- @field title? any
+--- @field title_pos? string
+--- @field footer? any
+--- @field footer_pos? string
+--- @field style? string
+--- @field noautocmd? boolean
+--- @field fixed? boolean
+--- @field hide? boolean
+
--- @class vim.api.keyset.win_text_height
--- @field start_row? integer
--- @field end_row? integer
--- @field start_vcol? integer
--- @field end_vcol? integer
+
+--- @class vim.api.keyset.xdl_diff
+--- @field on_hunk? function
+--- @field result_type? string
+--- @field algorithm? string
+--- @field ctxlen? integer
+--- @field interhunkctxlen? integer
+--- @field linematch? any
+--- @field ignore_whitespace? boolean
+--- @field ignore_whitespace_change? boolean
+--- @field ignore_whitespace_change_at_eol? boolean
+--- @field ignore_cr_at_eol? boolean
+--- @field ignore_blank_lines? boolean
+--- @field indent_heuristic? boolean
diff --git a/runtime/lua/vim/_meta/api_keysets_extra.lua b/runtime/lua/vim/_meta/api_keysets_extra.lua
new file mode 100644
index 0000000000..d61dd2c02f
--- /dev/null
+++ b/runtime/lua/vim/_meta/api_keysets_extra.lua
@@ -0,0 +1,167 @@
+--- @meta _
+error('Cannot require a meta file')
+
+--- Extra types we can't generate keysets for
+
+--- @class vim.api.keyset.extmark_details
+--- @field ns_id integer
+--- @field right_gravity boolean
+---
+--- @field end_row? integer
+--- @field end_col? integer
+--- @field end_right_gravity? integer
+---
+--- @field priority? integer
+---
+--- @field undo_restore? false
+--- @field invalidate? true
+--- @field invalid? true
+---
+--- @field hl_group? string
+--- @field hl_eol? boolean
+---
+--- @field conceal? boolean
+--- @field spell? boolean
+--- @field ui_watched? boolean
+--- @field url? boolean
+--- @field hl_mode? string
+---
+--- @field virt_text? {[1]: string, [2]: string}[]
+--- @field virt_text_hide? boolean
+--- @field virt_text_repeat_linebreak? boolean
+--- @field virt_text_win_col? integer
+--- @field virt_text_pos? string
+---
+--- @field virt_lines? {[1]: string, [2]: string}[][]
+--- @field virt_lines_above? boolean
+--- @field virt_lines_leftcol? boolean
+---
+--- @field sign_text? string
+--- @field sign_name? string
+--- @field sign_hl_group? string
+--- @field number_hl_group? string
+--- @field line_hl_group? string
+--- @field cursorline_hl_group? string
+
+--- @class vim.api.keyset.get_extmark_item
+--- @field [1] integer row
+--- @field [2] integer col
+--- @field [3] vim.api.keyset.extmark_details?
+
+--- @class vim.api.keyset.get_mark
+--- @field [1] integer row
+--- @field [2] integer col
+--- @field [3] integer buffer
+--- @field [4] string buffername
+
+--- @class vim.api.keyset.get_autocmds.ret
+--- @field id? integer
+--- @field group? integer
+--- @field group_name? integer
+--- @field desc? string
+--- @field event? string
+--- @field command? string
+--- @field callback? function
+--- @field once? boolean
+--- @field pattern? string
+--- @field buflocal? boolean
+--- @field buffer? integer
+
+--- @class vim.api.keyset.command_info
+--- @field name string
+--- @field definition string
+--- @field script_id integer
+--- @field bang boolean
+--- @field bar boolean
+--- @field register boolean
+--- @field keepscript boolean
+--- @field preview boolean
+--- @field nargs string
+--- @field complete? string
+--- @field complete_arg? string
+--- @field count? string
+--- @field range? string
+--- @field addr? string
+
+--- @class vim.api.keyset.hl_info.base
+--- @field reverse? true
+--- @field bold? true
+--- @field italic? true
+--- @field underline? true
+--- @field undercurl? true
+--- @field underdouble? true
+--- @field underdotted? true
+--- @field underdashed? true
+--- @field standout? true
+--- @field strikethrough? true
+--- @field altfont? true
+--- @field nocombine? true
+
+--- @class vim.api.keyset.hl_info.cterm : vim.api.keyset.hl_info.base
+--- @field ctermfg? integer
+--- @field ctermbg? integer
+--- @field foreground? integer
+--- @field background? integer
+
+--- @class vim.api.keyset.hl_info : vim.api.keyset.hl_info.base
+--- @field fg? integer
+--- @field bg? integer
+--- @field sp? integer
+--- @field default? true
+--- @field link? string
+--- @field blend? integer
+--- @field cterm? vim.api.keyset.hl_info.cterm
+
+--- @class vim.api.keyset.get_mode
+--- @field blocking boolean
+--- @field mode string
+
+--- @class vim.api.keyset.get_option_info
+--- @field name string
+--- @field shortname string
+--- @field scope 'buf'|'win'|'global'
+--- @field global_local boolean
+--- @field commalist boolean
+--- @field flaglist boolean
+--- @field was_set boolean
+--- @field last_set_id integer
+--- @field last_set_linenr integer
+--- @field last_set_chan integer
+--- @field type 'string'|'boolean'|'number'
+--- @field default string|boolean|integer
+--- @field allows_duplicates boolean
+
+--- @class vim.api.keyset.parse_cmd.mods
+--- @field filter { force: boolean, pattern: string }
+--- @field silent boolean
+--- @field emsg_silent boolean
+--- @field unsilent boolean
+--- @field sandbox boolean
+--- @field noautocmd boolean
+--- @field tab integer
+--- @field verbose integer
+--- @field browse boolean
+--- @field confirm boolean
+--- @field hide boolean
+--- @field keepalt boolean
+--- @field keepjumps boolean
+--- @field keepmarks boolean
+--- @field keeppatterns boolean
+--- @field lockmarks boolean
+--- @field noswapfile boolean
+--- @field vertical boolean
+--- @field horizontal boolean
+--- @field split ''|'botright'|'topleft'|'belowright'|'aboveleft'
+
+--- @class vim.api.keyset.parse_cmd
+--- @field addr 'line'|'arg'|'buf'|'load'|'win'|'tab'|'qf'|'none'|'?'
+--- @field args string[]
+--- @field bang boolean
+--- @field cmd string
+--- @field magic {bar: boolean, file: boolean}
+--- @field mods vim.api.keyset.parse_cmd.mods
+--- @field nargs '0'|'1'|'?'|'+'|'*'
+--- @field nextcmd string
+--- @field range? integer[]
+--- @field count? integer
+--- @field reg? string
diff --git a/runtime/lua/vim/_meta/builtin.lua b/runtime/lua/vim/_meta/builtin.lua
index eeba356672..9a67667f02 100644
--- a/runtime/lua/vim/_meta/builtin.lua
+++ b/runtime/lua/vim/_meta/builtin.lua
@@ -1,66 +1,72 @@
---@meta
-
-- luacheck: no unused args
----@defgroup vim.builtin
----
----@brief <pre>help
----vim.api.{func}({...}) *vim.api*
---- Invokes Nvim |API| function {func} with arguments {...}.
---- Example: call the "nvim_get_current_line()" API function: >lua
---- print(tostring(vim.api.nvim_get_current_line()))
----
----vim.NIL *vim.NIL*
---- Special value representing NIL in |RPC| and |v:null| in Vimscript
---- conversion, and similar cases. Lua `nil` cannot be used as part of a Lua
---- table representing a Dictionary or Array, because it is treated as
---- missing: `{"foo", nil}` is the same as `{"foo"}`.
----
----vim.type_idx *vim.type_idx*
---- Type index for use in |lua-special-tbl|. Specifying one of the values from
---- |vim.types| allows typing the empty table (it is unclear whether empty Lua
---- table represents empty list or empty array) and forcing integral numbers
---- to be |Float|. See |lua-special-tbl| for more details.
----
----vim.val_idx *vim.val_idx*
---- Value index for tables representing |Float|s. A table representing
---- floating-point value 1.0 looks like this: >lua
---- {
---- [vim.type_idx] = vim.types.float,
---- [vim.val_idx] = 1.0,
---- }
----< See also |vim.type_idx| and |lua-special-tbl|.
----
----vim.types *vim.types*
---- Table with possible values for |vim.type_idx|. Contains two sets of
---- key-value pairs: first maps possible values for |vim.type_idx| to
---- human-readable strings, second maps human-readable type names to values
---- for |vim.type_idx|. Currently contains pairs for `float`, `array` and
---- `dictionary` types.
----
---- Note: One must expect that values corresponding to `vim.types.float`,
---- `vim.types.array` and `vim.types.dictionary` fall under only two following
---- assumptions:
---- 1. Value may serve both as a key and as a value in a table. Given the
---- properties of Lua tables this basically means “value is not `nil`â€.
---- 2. For each value in `vim.types` table `vim.types[vim.types[value]]` is the
---- same as `value`.
---- No other restrictions are put on types, and it is not guaranteed that
---- values corresponding to `vim.types.float`, `vim.types.array` and
---- `vim.types.dictionary` will not change or that `vim.types` table will only
---- contain values for these three types.
----
---- *log_levels* *vim.log.levels*
----Log levels are one of the values defined in `vim.log.levels`:
----
---- vim.log.levels.DEBUG
---- vim.log.levels.ERROR
---- vim.log.levels.INFO
---- vim.log.levels.TRACE
---- vim.log.levels.WARN
---- vim.log.levels.OFF
----
----</pre>
+error('Cannot require a meta file')
+
+--- @brief <pre>help
+--- vim.api.{func}({...}) *vim.api*
+--- Invokes Nvim |API| function {func} with arguments {...}.
+--- Example: call the "nvim_get_current_line()" API function: >lua
+--- print(tostring(vim.api.nvim_get_current_line()))
+---
+--- vim.NIL *vim.NIL*
+--- Special value representing NIL in |RPC| and |v:null| in Vimscript
+--- conversion, and similar cases. Lua `nil` cannot be used as part of a Lua
+--- table representing a Dictionary or Array, because it is treated as
+--- missing: `{"foo", nil}` is the same as `{"foo"}`.
+---
+--- vim.type_idx *vim.type_idx*
+--- Type index for use in |lua-special-tbl|. Specifying one of the values from
+--- |vim.types| allows typing the empty table (it is unclear whether empty Lua
+--- table represents empty list or empty array) and forcing integral numbers
+--- to be |Float|. See |lua-special-tbl| for more details.
+---
+--- vim.val_idx *vim.val_idx*
+--- Value index for tables representing |Float|s. A table representing
+--- floating-point value 1.0 looks like this: >lua
+--- {
+--- [vim.type_idx] = vim.types.float,
+--- [vim.val_idx] = 1.0,
+--- }
+--- < See also |vim.type_idx| and |lua-special-tbl|.
+---
+--- vim.types *vim.types*
+--- Table with possible values for |vim.type_idx|. Contains two sets of
+--- key-value pairs: first maps possible values for |vim.type_idx| to
+--- human-readable strings, second maps human-readable type names to values
+--- for |vim.type_idx|. Currently contains pairs for `float`, `array` and
+--- `dictionary` types.
+---
+--- Note: One must expect that values corresponding to `vim.types.float`,
+--- `vim.types.array` and `vim.types.dictionary` fall under only two following
+--- assumptions:
+--- 1. Value may serve both as a key and as a value in a table. Given the
+--- properties of Lua tables this basically means “value is not `nil`â€.
+--- 2. For each value in `vim.types` table `vim.types[vim.types[value]]` is the
+--- same as `value`.
+--- No other restrictions are put on types, and it is not guaranteed that
+--- values corresponding to `vim.types.float`, `vim.types.array` and
+--- `vim.types.dictionary` will not change or that `vim.types` table will only
+--- contain values for these three types.
+---
+--- *log_levels* *vim.log.levels*
+--- Log levels are one of the values defined in `vim.log.levels`:
+---
+--- vim.log.levels.DEBUG
+--- vim.log.levels.ERROR
+--- vim.log.levels.INFO
+--- vim.log.levels.TRACE
+--- vim.log.levels.WARN
+--- vim.log.levels.OFF
+---
+--- </pre>
+
+---@nodoc
+---@class vim.NIL
+
+---@type vim.NIL
+---@nodoc
+vim.NIL = ...
--- Returns true if the code is executing as part of a "fast" event handler,
--- where most of the API is disabled. These are low-level events (e.g.
@@ -76,6 +82,7 @@ function vim.in_fast_event() end
---
--- Note: If numeric keys are present in the table, Nvim ignores the metatable
--- marker and converts the dict to a list/array anyway.
+--- @return table
function vim.empty_dict() end
--- Sends {event} to {channel} via |RPC| and returns immediately. If {channel}
@@ -84,9 +91,8 @@ function vim.empty_dict() end
--- This function also works in a fast callback |lua-loop-callbacks|.
--- @param channel integer
--- @param method string
---- @param args? any[]
--- @param ...? any
-function vim.rpcnotify(channel, method, args, ...) end
+function vim.rpcnotify(channel, method, ...) end
--- Sends a request to {channel} to invoke {method} via |RPC| and blocks until
--- a response is received.
@@ -95,9 +101,8 @@ function vim.rpcnotify(channel, method, args, ...) end
--- special value
--- @param channel integer
--- @param method string
---- @param args? any[]
--- @param ...? any
-function vim.rpcrequest(channel, method, args, ...) end
+function vim.rpcrequest(channel, method, ...) end
--- Compares strings case-insensitively.
--- @param a string
diff --git a/runtime/lua/vim/_meta/builtin_types.lua b/runtime/lua/vim/_meta/builtin_types.lua
index ef0452c649..0bbc3e9bc8 100644
--- a/runtime/lua/vim/_meta/builtin_types.lua
+++ b/runtime/lua/vim/_meta/builtin_types.lua
@@ -81,10 +81,10 @@
--- @class vim.fn.sign_getplaced.dict
--- @field group? string
--- @field id? integer
---- @field lnum? string
+--- @field lnum? string|integer
--- @class vim.fn.sign_getplaced.ret.item
---- @field buf integer
+--- @field bufnr integer
--- @field signs vim.fn.sign[]
--- @class vim.fn.sign_place.dict
@@ -118,7 +118,7 @@
--- @field topfill? integer
--- @field topline? integer
---- @class vim.fn.winsaveview.ret
+--- @class vim.fn.winsaveview.ret: vim.fn.winrestview.dict
--- @field col integer
--- @field coladd integer
--- @field curswant integer
diff --git a/runtime/lua/vim/_meta/json.lua b/runtime/lua/vim/_meta/json.lua
index e010086615..07d89aafc8 100644
--- a/runtime/lua/vim/_meta/json.lua
+++ b/runtime/lua/vim/_meta/json.lua
@@ -5,7 +5,7 @@ vim.json = {}
-- luacheck: no unused args
----@defgroup vim.json
+---@brief
---
--- This module provides encoding and decoding of Lua objects to and
--- from JSON-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
diff --git a/runtime/lua/vim/_meta/lpeg.lua b/runtime/lua/vim/_meta/lpeg.lua
index 42c9a6449e..1ce40f3340 100644
--- a/runtime/lua/vim/_meta/lpeg.lua
+++ b/runtime/lua/vim/_meta/lpeg.lua
@@ -1,11 +1,27 @@
--- @meta
+error('Cannot require a meta file')
--- These types were taken from https://github.com/LuaCATS/lpeg, with types being renamed to include
--- the vim namespace and with some descriptions made less verbose.
+-- These types were taken from https://github.com/LuaCATS/lpeg
+-- (based on revision e6789e28e5b91a4a277a2a03081d708c403a3e34)
+-- with types being renamed to include the vim namespace and with some descriptions made less verbose.
+
+--- @brief <pre>help
+--- LPeg is a pattern-matching library for Lua, based on
+--- Parsing Expression Grammars (https://bford.info/packrat/) (PEGs).
+---
+--- *lua-lpeg*
+--- *vim.lpeg.Pattern*
+--- The LPeg library for parsing expression grammars is included as `vim.lpeg`
+--- (https://www.inf.puc-rio.br/~roberto/lpeg/).
+---
+--- In addition, its regex-like interface is available as |vim.re|
+--- (https://www.inf.puc-rio.br/~roberto/lpeg/re.html).
+---
+--- </pre>
---- *LPeg* is a new pattern-matching library for Lua, based on [Parsing Expression Grammars](https://bford.info/packrat/) (PEGs).
vim.lpeg = {}
+--- @nodoc
--- @class vim.lpeg.Pattern
--- @operator unm: vim.lpeg.Pattern
--- @operator add(vim.lpeg.Pattern): vim.lpeg.Pattern
@@ -32,11 +48,12 @@ local Pattern = {}
--- matches anywhere.
---
--- Example:
+---
--- ```lua
---- local pattern = lpeg.R("az") ^ 1 * -1
---- assert(pattern:match("hello") == 6)
---- assert(lpeg.match(pattern, "hello") == 6)
---- assert(pattern:match("1 hello") == nil)
+--- local pattern = lpeg.R('az') ^ 1 * -1
+--- assert(pattern:match('hello') == 6)
+--- assert(lpeg.match(pattern, 'hello') == 6)
+--- assert(pattern:match('1 hello') == nil)
--- ```
---
--- @param pattern vim.lpeg.Pattern
@@ -55,11 +72,12 @@ function vim.lpeg.match(pattern, subject, init) end
--- we must either write a loop in Lua or write a pattern that matches anywhere.
---
--- Example:
+---
--- ```lua
---- local pattern = lpeg.R("az") ^ 1 * -1
---- assert(pattern:match("hello") == 6)
---- assert(lpeg.match(pattern, "hello") == 6)
---- assert(pattern:match("1 hello") == nil)
+--- local pattern = lpeg.R('az') ^ 1 * -1
+--- assert(pattern:match('hello') == 6)
+--- assert(lpeg.match(pattern, 'hello') == 6)
+--- assert(pattern:match('1 hello') == nil)
--- ```
---
--- @param subject string
@@ -69,7 +87,8 @@ function Pattern:match(subject, init) end
--- Returns the string `"pattern"` if the given value is a pattern, otherwise `nil`.
---
---- @return 'pattern'|nil
+--- @param value vim.lpeg.Pattern|string|integer|boolean|table|function
+--- @return "pattern"|nil
function vim.lpeg.type(value) end
--- Returns a string with the running version of LPeg.
@@ -85,7 +104,7 @@ function vim.lpeg.version() end
--- @param max integer
function vim.lpeg.setmaxstack(max) end
---- Converts the given value into a proper pattern. This following rules are applied:
+--- Converts the given value into a proper pattern. The following rules are applied:
--- * If the argument is a pattern, it is returned unmodified.
--- * If the argument is a string, it is translated to a pattern that matches the string literally.
--- * If the argument is a non-negative number `n`, the result is a pattern that matches exactly `n` characters.
@@ -95,7 +114,7 @@ function vim.lpeg.setmaxstack(max) end
--- * If the argument is a boolean, the result is a pattern that always succeeds or always fails
--- (according to the boolean value), without consuming any input.
--- * If the argument is a table, it is interpreted as a grammar (see Grammars).
---- * If the argument is a function, returns a pattern equivalent to a match-time captureover the empty string.
+--- * If the argument is a function, returns a pattern equivalent to a match-time capture over the empty string.
---
--- @param value vim.lpeg.Pattern|string|integer|boolean|table|function
--- @return vim.lpeg.Pattern
@@ -103,7 +122,7 @@ function vim.lpeg.P(value) end
--- Returns a pattern that matches only if the input string at the current position is preceded by `patt`.
--- Pattern `patt` must match only strings with some fixed length, and it cannot contain captures.
---- Like the and predicate, this pattern never consumes any input, independently of success or failure.
+--- Like the `and` predicate, this pattern never consumes any input, independently of success or failure.
---
--- @param pattern vim.lpeg.Pattern
--- @return vim.lpeg.Pattern
@@ -111,13 +130,14 @@ function vim.lpeg.B(pattern) end
--- Returns a pattern that matches any single character belonging to one of the given ranges.
--- Each `range` is a string `xy` of length 2, representing all characters with code between the codes of
---- `x` and `y` (both inclusive). As an example, the pattern `lpeg.R("09")` matches any digit, and
---- `lpeg.R("az", "AZ")` matches any ASCII letter.
+--- `x` and `y` (both inclusive). As an example, the pattern `lpeg.R('09')` matches any digit, and
+--- `lpeg.R('az', 'AZ')` matches any ASCII letter.
---
--- Example:
+---
--- ```lua
---- local pattern = lpeg.R("az") ^ 1 * -1
---- assert(pattern:match("hello") == 6)
+--- local pattern = lpeg.R('az') ^ 1 * -1
+--- assert(pattern:match('hello') == 6)
--- ```
---
--- @param ... string
@@ -125,9 +145,9 @@ function vim.lpeg.B(pattern) end
function vim.lpeg.R(...) end
--- Returns a pattern that matches any single character that appears in the given string (the `S` stands for Set).
---- As an example, the pattern `lpeg.S("+-*/")` matches any arithmetic operator. Note that, if `s` is a character
+--- As an example, the pattern `lpeg.S('+-*/')` matches any arithmetic operator. Note that, if `s` is a character
--- (that is, a string of length 1), then `lpeg.P(s)` is equivalent to `lpeg.S(s)` which is equivalent to
---- `lpeg.R(s..s)`. Note also that both `lpeg.S("")` and `lpeg.R()` are patterns that always fail.
+--- `lpeg.R(s..s)`. Note also that both `lpeg.S('')` and `lpeg.R()` are patterns that always fail.
---
--- @param string string
--- @return vim.lpeg.Pattern
@@ -137,8 +157,9 @@ function vim.lpeg.S(string) end
--- for a grammar. The created non-terminal refers to the rule indexed by `v` in the enclosing grammar.
---
--- Example:
+---
--- ```lua
---- local b = lpeg.P({"(" * ((1 - lpeg.S "()") + lpeg.V(1)) ^ 0 * ")"})
+--- local b = lpeg.P({'(' * ((1 - lpeg.S '()') + lpeg.V(1)) ^ 0 * ')'})
--- assert(b:match('((string))') == 11)
--- assert(b:match('(') == nil)
--- ```
@@ -147,6 +168,7 @@ function vim.lpeg.S(string) end
--- @return vim.lpeg.Pattern
function vim.lpeg.V(v) end
+--- @nodoc
--- @class vim.lpeg.Locale
--- @field alnum userdata
--- @field alpha userdata
@@ -168,14 +190,15 @@ function vim.lpeg.V(v) end
--- that table.
---
--- Example:
+---
--- ```lua
--- lpeg.locale(lpeg)
---- local space = lpeg.space^0
---- local name = lpeg.C(lpeg.alpha^1) * space
---- local sep = lpeg.S(",;") * space
---- local pair = lpeg.Cg(name * "=" * space * name) * sep^-1
---- local list = lpeg.Cf(lpeg.Ct("") * pair^0, rawset)
---- local t = list:match("a=b, c = hi; next = pi")
+--- local space = lpeg.space ^ 0
+--- local name = lpeg.C(lpeg.alpha ^ 1) * space
+--- local sep = lpeg.S(',;') * space
+--- local pair = lpeg.Cg(name * '=' * space * name) * sep ^ -1
+--- local list = lpeg.Cf(lpeg.Ct('') * pair ^ 0, rawset)
+--- local t = list:match('a=b, c = hi; next = pi')
--- assert(t.a == 'b')
--- assert(t.c == 'hi')
--- assert(t.next == 'pi')
@@ -191,11 +214,12 @@ function vim.lpeg.locale(tab) end
--- The captured value is a string. If `patt` has other captures, their values are returned after this one.
---
--- Example:
+---
--- ```lua
--- local function split (s, sep)
--- sep = lpeg.P(sep)
---- local elem = lpeg.C((1 - sep)^0)
---- local p = elem * (sep * elem)^0
+--- local elem = lpeg.C((1 - sep) ^ 0)
+--- local p = elem * (sep * elem) ^ 0
--- return lpeg.match(p, s)
--- end
--- local a, b, c = split('a,b,c', ',')
@@ -241,12 +265,13 @@ function vim.lpeg.Cc(...) end
--- becomes the captured value.
---
--- Example:
+---
--- ```lua
---- local number = lpeg.R("09") ^ 1 / tonumber
---- local list = number * ("," * number) ^ 0
+--- local number = lpeg.R('09') ^ 1 / tonumber
+--- local list = number * (',' * number) ^ 0
--- local function add(acc, newvalue) return acc + newvalue end
--- local sum = lpeg.Cf(list, add)
---- assert(sum:match("10,30,43") == 83)
+--- assert(sum:match('10,30,43') == 83)
--- ```
---
--- @param patt vim.lpeg.Pattern
@@ -267,10 +292,11 @@ function vim.lpeg.Cg(patt, name) end
--- subject where the match occurs. The captured value is a number.
---
--- Example:
+---
--- ```lua
--- local I = lpeg.Cp()
--- local function anywhere(p) return lpeg.P({I * p * I + 1 * lpeg.V(1)}) end
---- local match_start, match_end = anywhere("world"):match("hello world!")
+--- local match_start, match_end = anywhere('world'):match('hello world!')
--- assert(match_start == 7)
--- assert(match_end == 12)
--- ```
@@ -285,10 +311,11 @@ function vim.lpeg.Cp() end
--- value is the string resulting from all replacements.
---
--- Example:
+---
--- ```lua
--- local function gsub (s, patt, repl)
--- patt = lpeg.P(patt)
---- patt = lpeg.Cs((patt / repl + 1)^0)
+--- patt = lpeg.Cs((patt / repl + 1) ^ 0)
--- return lpeg.match(patt, s)
--- end
--- assert(gsub('Hello, xxx!', 'xxx', 'World') == 'Hello, World!')
@@ -312,9 +339,9 @@ function vim.lpeg.Ct(patt) end
--- and then calls `function`. The given function gets as arguments the entire subject, the current position
--- (after the match of `patt`), plus any capture values produced by `patt`. The first value returned by `function`
--- defines how the match happens. If the call returns a number, the match succeeds and the returned number
---- becomes the new current position. (Assuming a subject sand current position i, the returned number must be
---- in the range [i, len(s) + 1].) If the call returns true, the match succeeds without consuming any input
---- (so, to return true is equivalent to return i). If the call returns false, nil, or no value, the match fails.
+--- becomes the new current position. (Assuming a subject sand current position `i`, the returned number must be
+--- in the range `[i, len(s) + 1]`.) If the call returns `true`, the match succeeds without consuming any input
+--- (so, to return true is equivalent to return `i`). If the call returns `false`, `nil`, or no value, the match fails.
--- Any extra values returned by the function become the values produced by the capture.
---
--- @param patt vim.lpeg.Pattern
diff --git a/runtime/lua/vim/_meta/misc.lua b/runtime/lua/vim/_meta/misc.lua
index 0d70e16314..ab80e18434 100644
--- a/runtime/lua/vim/_meta/misc.lua
+++ b/runtime/lua/vim/_meta/misc.lua
@@ -10,6 +10,7 @@
--- vim.fn[func]({...})
--- ```
---
---- @param func fun()
+--- @param func string
--- @param ... any
+--- @return any
function vim.call(func, ...) end
diff --git a/runtime/lua/vim/_meta/mpack.lua b/runtime/lua/vim/_meta/mpack.lua
index 54e097ad97..3970341b78 100644
--- a/runtime/lua/vim/_meta/mpack.lua
+++ b/runtime/lua/vim/_meta/mpack.lua
@@ -2,14 +2,17 @@
-- luacheck: no unused args
---- @defgroup vim.mpack
+--- @brief
---
--- This module provides encoding and decoding of Lua objects to and
--- from msgpack-encoded strings. Supports |vim.NIL| and |vim.empty_dict()|.
--- Decodes (or "unpacks") the msgpack-encoded {str} to a Lua object.
--- @param str string
+--- @return any
function vim.mpack.decode(str) end
--- Encodes (or "packs") Lua object {obj} as msgpack in a Lua string.
+--- @param obj any
+--- @return string
function vim.mpack.encode(obj) end
diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua
index d2bdab4d28..757720d8fb 100644
--- a/runtime/lua/vim/_meta/options.lua
+++ b/runtime/lua/vim/_meta/options.lua
@@ -137,8 +137,9 @@ vim.bo.ai = vim.bo.autoindent
--- `timestamp`
--- If this option has a local value, use this command to switch back to
--- using the global value:
---- ```
---- :set autoread<
+---
+--- ```vim
+--- set autoread<
--- ```
---
---
@@ -191,25 +192,22 @@ vim.go.awa = vim.go.autowriteall
--- See `:hi-normal` if you want to set the background color explicitly.
--- *g:colors_name*
--- When a color scheme is loaded (the "g:colors_name" variable is set)
---- setting 'background' will cause the color scheme to be reloaded. If
+--- changing 'background' will cause the color scheme to be reloaded. If
--- the color scheme adjusts to the value of 'background' this will work.
--- However, if the color scheme sets 'background' itself the effect may
--- be undone. First delete the "g:colors_name" variable when needed.
---
--- Normally this option would be set in the vimrc file. Possibly
--- depending on the terminal name. Example:
+---
+--- ```vim
+--- if $TERM ==# "xterm"
+--- set background=dark
+--- endif
--- ```
---- :if $TERM ==# "xterm"
---- : set background=dark
---- :endif
---- ```
---- When this option is set, the default settings for the highlight groups
+--- When this option is changed, the default settings for the highlight groups
--- will change. To use other settings, place ":highlight" commands AFTER
--- the setting of the 'background' option.
---- This option is also used in the "$VIMRUNTIME/syntax/syntax.vim" file
---- to select the colors for syntax highlighting. After changing this
---- option, you must load syntax.vim again to see the result. This can be
---- done with ":syntax on".
---
--- @type string
vim.o.background = "dark"
@@ -352,14 +350,16 @@ vim.go.bkc = vim.go.backupcopy
--- - Environment variables are expanded `:set_env`.
--- - Careful with '\' characters, type one before a space, type two to
--- get one in the option (see `option-backslash`), for example:
---- ```
---- :set bdir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
+---
+--- ```vim
+--- set bdir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
--- ```
---
--- See also 'backup' and 'writebackup' options.
--- If you want to hide your backup files on Unix, consider this value:
---- ```
---- :set backupdir=./.backup,~/.backup,.,/tmp
+---
+--- ```vim
+--- set backupdir=./.backup,~/.backup,.,/tmp
--- ```
--- You must create a ".backup" directory in each directory and in your
--- home directory for this to work properly.
@@ -385,8 +385,9 @@ vim.go.bdir = vim.go.backupdir
--- If you like to keep a lot of backups, you could use a BufWritePre
--- autocommand to change 'backupext' just before writing the file to
--- include a timestamp.
---- ```
---- :au BufWritePre * let &bex = '-' .. strftime("%Y%b%d%X") .. '~'
+---
+--- ```vim
+--- au BufWritePre * let &bex = '-' .. strftime("%Y%b%d%X") .. '~'
--- ```
--- Use 'backupdir' to put the backup in a different directory.
---
@@ -413,7 +414,7 @@ vim.go.bex = vim.go.backupext
--- $HOME you must expand it explicitly, e.g.:
---
--- ```vim
---- :let &backupskip = escape(expand('$HOME'), '\') .. '/tmp/*'
+--- let &backupskip = escape(expand('$HOME'), '\') .. '/tmp/*'
--- ```
--- Note that the default also makes sure that "crontab -e" works (when a
--- backup would be made by renaming the original file crontab won't see
@@ -714,8 +715,9 @@ vim.go.cdh = vim.go.cdhome
--- If the default value taken from $CDPATH is not what you want, include
--- a modified version of the following command in your vimrc file to
--- override it:
---- ```
---- :let &cdpath = ',' .. substitute(substitute($CDPATH, '[, ]', '\\\0', 'g'), ':', ',', 'g')
+---
+--- ```vim
+--- let &cdpath = ',' .. substitute(substitute($CDPATH, '[, ]', '\\\0', 'g'), ':', ',', 'g')
--- ```
--- This option cannot be set from a `modeline` or in the `sandbox`, for
--- security reasons.
@@ -731,9 +733,10 @@ vim.go.cd = vim.go.cdpath
--- Only non-printable keys are allowed.
--- The key can be specified as a single character, but it is difficult to
--- type. The preferred way is to use the <> notation. Examples:
---- ```
---- :exe "set cedit=\\<C-Y>"
---- :exe "set cedit=\\<Esc>"
+---
+--- ```vim
+--- exe "set cedit=\\<C-Y>"
+--- exe "set cedit=\\<Esc>"
--- ```
--- `Nvi` also has this option, but it only uses the first character.
--- See `cmdwin`.
@@ -767,7 +770,8 @@ vim.bo.channel = vim.o.channel
--- is done internally by Vim, 'charconvert' is not used for this.
--- Also used for Unicode conversion.
--- Example:
---- ```
+---
+--- ```vim
--- set charconvert=CharConvert()
--- fun CharConvert()
--- system("recode "
@@ -833,7 +837,8 @@ vim.bo.cino = vim.bo.cinoptions
--- Keywords that are interpreted as a C++ scope declaration by `cino-g`.
--- Useful e.g. for working with the Qt framework that defines additional
--- scope declarations "signals", "public slots" and "private slots":
---- ```
+---
+--- ```vim
--- set cinscopedecls+=signals,public\ slots,private\ slots
--- ```
---
@@ -920,10 +925,12 @@ vim.go.cwh = vim.go.cmdwinheight
--- text. Will make screen redrawing slower.
--- The screen column can be an absolute number, or a number preceded with
--- '+' or '-', which is added to or subtracted from 'textwidth'.
---- ```
---- :set cc=+1 " highlight column after 'textwidth'
---- :set cc=+1,+2,+3 " highlight three columns after 'textwidth'
---- :hi ColorColumn ctermbg=lightgrey guibg=lightgrey
+---
+--- ```vim
+---
+--- set cc=+1 " highlight column after 'textwidth'
+--- set cc=+1,+2,+3 " highlight three columns after 'textwidth'
+--- hi ColorColumn ctermbg=lightgrey guibg=lightgrey
--- ```
---
--- When 'textwidth' is zero then the items with '-' and '+' are not used.
@@ -945,8 +952,9 @@ vim.wo.cc = vim.wo.colorcolumn
--- the GUI it is always possible and Vim limits the number of columns to
--- what fits on the screen. You can use this command to get the widest
--- window possible:
---- ```
---- :set columns=9999
+---
+--- ```vim
+--- set columns=9999
--- ```
--- Minimum value is 12, maximum value is 10000.
---
@@ -989,8 +997,9 @@ vim.bo.cms = vim.bo.commentstring
--- kspell use the currently active spell checking `spell`
--- k{dict} scan the file {dict}. Several "k" flags can be given,
--- patterns are valid too. For example:
---- ```
---- :set cpt=k/usr/dict/*,k~/spanish
+---
+--- ```vim
+--- set cpt=k/usr/dict/*,k~/spanish
--- ```
--- s scan the files given with the 'thesaurus' option
--- s{tsr} scan the file {tsr}. Several "s" flags can be given, patterns
@@ -1053,14 +1062,18 @@ vim.bo.cfu = vim.bo.completefunc
--- completion in the preview window. Only works in
--- combination with "menu" or "menuone".
---
---- noinsert Do not insert any text for a match until the user selects
+--- noinsert Do not insert any text for a match until the user selects
--- a match from the menu. Only works in combination with
--- "menu" or "menuone". No effect if "longest" is present.
---
---- noselect Do not select a match in the menu, force the user to
+--- noselect Do not select a match in the menu, force the user to
--- select one from the menu. Only works in combination with
--- "menu" or "menuone".
---
+--- popup Show extra information about the currently selected
+--- completion in a popup window. Only works in combination
+--- with "menu" or "menuone". Overrides "preview".
+---
--- @type string
vim.o.completeopt = "menu,preview"
vim.o.cot = vim.o.completeopt
@@ -1283,9 +1296,6 @@ vim.bo.ci = vim.bo.copyindent
--- when it didn't exist when editing it. This is a
--- protection against a file unexpectedly created by
--- someone else. Vi didn't complain about this.
---- *cpo-p*
---- p Vi compatible Lisp indenting. When not present, a
---- slightly better algorithm is used.
--- *cpo-P*
--- P When included, a ":write" command that appends to a
--- file will set the file name for the current buffer, if
@@ -1419,7 +1429,8 @@ vim.wo.crb = vim.wo.cursorbind
--- slower.
--- If you only want the highlighting in the current window you can use
--- these autocommands:
---- ```
+---
+--- ```vim
--- au WinLeave * set nocursorline nocursorcolumn
--- au WinEnter * set cursorline cursorcolumn
--- ```
@@ -1502,7 +1513,8 @@ vim.go.debug = vim.o.debug
--- ```
--- When using the ":set" command, you need to double the backslashes!
--- To avoid that use `:let` with a single quote string:
---- ```
+---
+--- ```vim
--- let &l:define = '^\s*\ze\k\+\s*=\s*function('
--- ```
---
@@ -1681,11 +1693,12 @@ vim.go.dex = vim.go.diffexpr
--- histogram histogram diff algorithm
---
--- Examples:
---- ```
---- :set diffopt=internal,filler,context:4
---- :set diffopt=
---- :set diffopt=internal,filler,foldcolumn:3
---- :set diffopt-=internal " do NOT use the internal diff parser
+---
+--- ```vim
+--- set diffopt=internal,filler,context:4
+--- set diffopt=
+--- set diffopt=internal,filler,foldcolumn:3
+--- set diffopt-=internal " do NOT use the internal diff parser
--- ```
---
---
@@ -1736,8 +1749,9 @@ vim.go.dg = vim.go.digraph
--- - Environment variables are expanded `:set_env`.
--- - Careful with '\' characters, type one before a space, type two to
--- get one in the option (see `option-backslash`), for example:
---- ```
---- :set dir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
+---
+--- ```vim
+--- set dir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
--- ```
---
--- Editing the same file twice will result in a warning. Using "/tmp" on
@@ -1924,8 +1938,9 @@ vim.go.efm = vim.go.errorformat
--- When set to "all" or when "all" is one of the items, all autocommand
--- events are ignored, autocommands will not be executed.
--- Otherwise this is a comma-separated list of event names. Example:
---- ```
---- :set ei=WinEnter,WinLeave
+---
+--- ```vim
+--- set ei=WinEnter,WinLeave
--- ```
---
---
@@ -2021,7 +2036,8 @@ vim.bo.fenc = vim.bo.fileencoding
--- "ucs-bom", which requires the BOM to be present). If you prefer
--- another encoding use an BufReadPost autocommand event to test if your
--- preferred encoding is to be used. Example:
---- ```
+---
+--- ```vim
--- au BufReadPost * if search('\S', 'w') == 0 |
--- \ set fenc=iso-2022-jp | endif
--- ```
@@ -2031,8 +2047,9 @@ vim.bo.fenc = vim.bo.fileencoding
--- not used.
--- Note that 'fileencodings' is not used for a new file, the global value
--- of 'fileencoding' is used instead. You can set it with:
---- ```
---- :setglobal fenc=iso-8859-2
+---
+--- ```vim
+--- setglobal fenc=iso-8859-2
--- ```
--- This means that a non-existing file may get a different encoding than
--- an empty file.
@@ -2156,14 +2173,12 @@ vim.go.fic = vim.go.fileignorecase
--- this use the ":filetype on" command. `:filetype`
--- Setting this option to a different value is most useful in a modeline,
--- for a file for which the file type is not automatically recognized.
---- Example, for in an IDL file:
---- ```
+--- Example, for in an IDL file: >c
--- /* vim: set filetype=idl : */
--- ```
--- `FileType` `filetypes`
--- When a dot appears in the value then this separates two filetype
---- names. Example:
---- ```
+--- names. Example: >c
--- /* vim: set filetype=c.doxygen : */
--- ```
--- This will use the "c" filetype first, then the "doxygen" filetype.
@@ -2182,7 +2197,7 @@ vim.bo.ft = vim.bo.filetype
--- Characters to fill the statuslines, vertical separators and special
--- lines in the window.
--- It is a comma-separated list of items. Each item has a name, a colon
---- and the value of that item:
+--- and the value of that item: `E1511`
---
--- item default Used for ~
--- stl ' ' statusline of the current window
@@ -2216,13 +2231,14 @@ vim.bo.ft = vim.bo.filetype
--- default to single-byte alternatives.
---
--- Example:
---- ```
---- :set fillchars=stl:\ ,stlnc:\ ,vert:│,fold:·,diff:-
+---
+--- ```vim
+--- set fillchars=stl:\ ,stlnc:\ ,vert:│,fold:·,diff:-
--- ```
---
--- For the "stl", "stlnc", "foldopen", "foldclose" and "foldsep" items
--- single-byte and multibyte characters are supported. But double-width
---- characters are not supported.
+--- characters are not supported. `E1512`
---
--- The highlighting used for these items:
--- item highlight group ~
@@ -2457,6 +2473,9 @@ vim.go.fdo = vim.go.foldopen
--- It is not allowed to change text or jump to another window while
--- evaluating 'foldtext' `textlock`.
---
+--- When set to an empty string, foldtext is disabled, and the line
+--- is displayed normally with highlighting and no line wrapping.
+---
--- @type string
vim.o.foldtext = "foldtext()"
vim.o.fdt = vim.o.foldtext
@@ -2475,8 +2494,9 @@ vim.wo.fdt = vim.wo.foldtext
--- it yet!
---
--- Example:
---- ```
---- :set formatexpr=mylang#Format()
+---
+--- ```vim
+--- set formatexpr=mylang#Format()
--- ```
--- This will invoke the mylang#Format() function in the
--- autoload/mylang.vim file in 'runtimepath'. `autoload`
@@ -2492,7 +2512,8 @@ vim.wo.fdt = vim.wo.foldtext
---
--- If the expression starts with s: or `<SID>`, then it is replaced with
--- the script ID (`local-function`). Example:
---- ```
+---
+--- ```vim
--- set formatexpr=s:MyFormatExpr()
--- set formatexpr=<SID>SomeFormatExpr()
--- ```
@@ -2591,9 +2612,9 @@ vim.go.fs = vim.go.fsync
--- :s///g subst. one subst. all
--- :s///gg subst. all subst. one
---
---- DEPRECATED: Setting this option may break plugins that are not aware
---- of this option. Also, many users get confused that adding the /g flag
---- has the opposite effect of that it normally does.
+--- NOTE: Setting this option may break plugins that rely on the default
+--- behavior of the 'g' flag. This will also make the 'g' flag have the
+--- opposite effect of that documented in `:s_g`.
---
--- @type boolean
vim.o.gdefault = false
@@ -2618,8 +2639,9 @@ vim.go.gfm = vim.go.grepformat
--- `option-backslash` about including spaces and backslashes.
--- When your "grep" accepts the "-H" argument, use this to make ":grep"
--- also work well with a single file:
---- ```
---- :set grepprg=grep\ -nH
+---
+--- ```vim
+--- set grepprg=grep\ -nH
--- ```
--- Special value: When 'grepprg' is set to "internal" the `:grep` command
--- works like `:vimgrep`, `:lgrep` like `:lvimgrep`, `:grepadd` like
@@ -2641,12 +2663,14 @@ vim.go.gp = vim.go.grepprg
--- terminals. See `tui-cursor-shape`.
---
--- To disable cursor-styling, reset the option:
---- ```
---- :set guicursor=
+---
+--- ```vim
+--- set guicursor=
--- ```
--- To enable mode shapes, "Cursor" highlight, and blinking:
---- ```
---- :set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50
+---
+--- ```vim
+--- set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50
--- \,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor
--- \,sm:block-blinkwait175-blinkoff150-blinkon175
--- ```
@@ -2680,8 +2704,9 @@ vim.go.gp = vim.go.grepprg
--- the cursor is shown and blinkoff is the time that the
--- cursor is not shown. Times are in msec. When one of
--- the numbers is zero, there is no blinking. E.g.:
---- ```
---- :set guicursor=n:blinkon0
+---
+--- ```vim
+--- set guicursor=n:blinkon0
--- ```
--- - Default is "blinkon0" for each mode.
--- {group-name}
@@ -2721,9 +2746,10 @@ vim.go.gp = vim.go.grepprg
--- blinking: "a:blinkon0"
---
--- Examples of cursor highlighting:
---- ```
---- :highlight Cursor gui=reverse guifg=NONE guibg=NONE
---- :highlight Cursor gui=NONE guifg=bg guibg=fg
+---
+--- ```vim
+--- highlight Cursor gui=reverse guifg=NONE guibg=NONE
+--- highlight Cursor gui=NONE guifg=bg guibg=fg
--- ```
---
---
@@ -2743,8 +2769,9 @@ vim.go.gcr = vim.go.guicursor
--- precede it with a backslash. Setting an option requires an extra
--- backslash before a space and a backslash. See also
--- `option-backslash`. For example:
---- ```
---- :set guifont=Screen15,\ 7x13,font\\,with\\,commas
+---
+--- ```vim
+--- set guifont=Screen15,\ 7x13,font\\,with\\,commas
--- ```
--- will make Vim try to use the font "Screen15" first, and if it fails it
--- will try to use "7x13" and then "font,with,commas" instead.
@@ -2757,16 +2784,18 @@ vim.go.gcr = vim.go.guicursor
--- will try to find the related bold and italic fonts.
---
--- For Win32 and Mac OS:
---- ```
---- :set guifont=*
+---
+--- ```vim
+--- set guifont=*
--- ```
--- will bring up a font requester, where you can pick the font you want.
---
--- The font name depends on the GUI used.
---
--- For Mac OSX you can use something like this:
---- ```
---- :set guifont=Monaco:h10
+---
+--- ```vim
+--- set guifont=Monaco:h10
--- ```
--- *E236*
--- Note that the fonts must be mono-spaced (all characters have the same
@@ -2793,9 +2822,10 @@ vim.go.gcr = vim.go.guicursor
--- - A '_' can be used in the place of a space, so you don't need to use
--- backslashes to escape the spaces.
--- - Examples:
---- ```
---- :set guifont=courier_new:h12:w5:b:cRUSSIAN
---- :set guifont=Andale_Mono:h7.5:w4.5
+---
+--- ```vim
+--- set guifont=courier_new:h12:w5:b:cRUSSIAN
+--- set guifont=Andale_Mono:h7.5:w4.5
--- ```
---
---
@@ -2949,8 +2979,9 @@ vim.go.gtl = vim.go.guitablabel
--- pages line. When empty Vim will use a default tooltip.
--- This option is otherwise just like 'guitablabel' above.
--- You can include a line break. Simplest method is to use `:let`:
---- ```
---- :let &guitabtooltip = "line one\nline two"
+---
+--- ```vim
+--- let &guitabtooltip = "line one\nline two"
--- ```
---
---
@@ -2994,8 +3025,9 @@ vim.go.hh = vim.go.helpheight
--- another language, but that will only find tags that exist in that
--- language and not in the English help.
--- Example:
---- ```
---- :set helplang=de,it
+---
+--- ```vim
+--- set helplang=de,it
--- ```
--- This will first search German, then Italian and finally English help
--- files.
@@ -3131,8 +3163,9 @@ vim.go.imd = vim.go.imdisable
--- 2 :lmap is off and IM is ON
--- To always reset the option to zero when leaving Insert mode with <Esc>
--- this can be used:
---- ```
---- :inoremap <ESC> <ESC>:set iminsert=0<CR>
+---
+--- ```vim
+--- inoremap <ESC> <ESC>:set iminsert=0<CR>
--- ```
--- This makes :lmap and IM turn off automatically when leaving Insert
--- mode.
@@ -3206,15 +3239,17 @@ vim.go.inc = vim.go.include
--- Expression to be used to transform the string found with the 'include'
--- option to a file name. Mostly useful to change "." to "/" for Java:
---- ```
---- :setlocal includeexpr=substitute(v:fname,'\\.','/','g')
+---
+--- ```vim
+--- setlocal includeexpr=substitute(v:fname,'\\.','/','g')
--- ```
--- The "v:fname" variable will be set to the file name that was detected.
--- Note the double backslash: the `:set` command first halves them, then
--- one remains in the value, where "\." matches a dot literally. For
--- simple character replacements `tr()` avoids the need for escaping:
---- ```
---- :setlocal includeexpr=tr(v:fname,'.','/')
+---
+--- ```vim
+--- setlocal includeexpr=tr(v:fname,'.','/')
--- ```
---
--- Also used for the `gf` command if an unmodified file name can't be
@@ -3223,7 +3258,8 @@ vim.go.inc = vim.go.include
---
--- If the expression starts with s: or `<SID>`, then it is replaced with
--- the script ID (`local-function`). Example:
---- ```
+---
+--- ```vim
--- setlocal includeexpr=s:MyIncludeExpr(v:fname)
--- setlocal includeexpr=<SID>SomeIncludeExpr(v:fname)
--- ```
@@ -3262,7 +3298,8 @@ vim.bo.inex = vim.bo.includeexpr
--- If you don't want to turn 'hlsearch' on, but want to highlight all
--- matches while searching, you can turn on and off 'hlsearch' with
--- autocmd. Example:
---- ```
+---
+--- ```vim
--- augroup vimrc-incsearch-highlight
--- autocmd!
--- autocmd CmdlineEnter /,\? :set hlsearch
@@ -3295,7 +3332,8 @@ vim.go.is = vim.go.incsearch
---
--- If the expression starts with s: or `<SID>`, then it is replaced with
--- the script ID (`local-function`). Example:
---- ```
+---
+--- ```vim
--- set indentexpr=s:MyIndentExpr()
--- set indentexpr=<SID>SomeIndentExpr()
--- ```
@@ -3311,8 +3349,9 @@ vim.go.is = vim.go.incsearch
--- not change the text, jump to another window, etc. Afterwards the
--- cursor position is always restored, thus the cursor may be moved.
--- Normally this option would be set to call a function:
---- ```
---- :set indentexpr=GetMyIndent()
+---
+--- ```vim
+--- set indentexpr=GetMyIndent()
--- ```
--- Error messages will be suppressed, unless the 'debug' option contains
--- "msg".
@@ -3540,9 +3579,10 @@ vim.go.km = vim.go.keymodel
--- a [count] for the "K" command to a section number.
--- See `option-backslash` about including spaces and backslashes.
--- Example:
---- ```
---- :set keywordprg=man\ -s
---- :set keywordprg=:Man
+---
+--- ```vim
+--- set keywordprg=man\ -s
+--- set keywordprg=:Man
--- ```
--- This option cannot be set from a `modeline` or in the `sandbox`, for
--- security reasons.
@@ -3569,12 +3609,14 @@ vim.go.kp = vim.go.keywordprg
--- security reasons.
---
--- Example (for Greek, in UTF-8): *greek*
---- ```
---- :set langmap=ΑA,Î’B,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ΜM,ÎN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,ΘU,ΩV,WW,ΧX,Î¥Y,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,Ï€p,qq,Ïr,σs,Ï„t,θu,ωv,Ï‚w,χx,Ï…y,ζz
+---
+--- ```vim
+--- set langmap=ΑA,Î’B,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ΜM,ÎN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,ΘU,ΩV,WW,ΧX,Î¥Y,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,Ï€p,qq,Ïr,σs,Ï„t,θu,ωv,Ï‚w,χx,Ï…y,ζz
--- ```
--- Example (exchanges meaning of z and y for commands):
---- ```
---- :set langmap=zy,yz,ZY,YZ
+---
+--- ```vim
+--- set langmap=zy,yz,ZY,YZ
--- ```
---
--- The 'langmap' option is a list of parts, separated with commas. Each
@@ -3607,28 +3649,32 @@ vim.go.lmap = vim.go.langmap
--- Language to use for menu translation. Tells which file is loaded
--- from the "lang" directory in 'runtimepath':
---- ```
+---
+--- ```vim
--- "lang/menu_" .. &langmenu .. ".vim"
--- ```
--- (without the spaces). For example, to always use the Dutch menus, no
--- matter what $LANG is set to:
---- ```
---- :set langmenu=nl_NL.ISO_8859-1
+---
+--- ```vim
+--- set langmenu=nl_NL.ISO_8859-1
--- ```
--- When 'langmenu' is empty, `v:lang` is used.
--- Only normal file name characters can be used, `/\*?[|<>` are illegal.
--- If your $LANG is set to a non-English language but you do want to use
--- the English menus:
---- ```
---- :set langmenu=none
+---
+--- ```vim
+--- set langmenu=none
--- ```
--- This option must be set before loading menus, switching on filetype
--- detection or syntax highlighting. Once the menus are defined setting
--- this option has no effect. But you could do this:
---- ```
---- :source $VIMRUNTIME/delmenu.vim
---- :set langmenu=de_DE.ISO_8859-1
---- :source $VIMRUNTIME/menu.vim
+---
+--- ```vim
+--- source $VIMRUNTIME/delmenu.vim
+--- set langmenu=de_DE.ISO_8859-1
+--- source $VIMRUNTIME/menu.vim
--- ```
--- Warning: This deletes all menus that you defined yourself!
---
@@ -3701,8 +3747,9 @@ vim.wo.lbr = vim.wo.linebreak
--- to use the size for the GUI, put the command in your `gvimrc` file.
--- Vim limits the number of lines to what fits on the screen. You can
--- use this command to get the tallest window possible:
---- ```
---- :set lines=999
+---
+--- ```vim
+--- set lines=999
--- ```
--- Minimum value is 2, maximum value is 1000.
---
@@ -3771,8 +3818,9 @@ vim.go.lw = vim.go.lispwords
--- The cursor is displayed at the start of the space a Tab character
--- occupies, not at the end as usual in Normal mode. To get this cursor
--- position while displaying Tabs with spaces, use:
---- ```
---- :set list lcs=tab:\ \
+---
+--- ```vim
+--- set list lcs=tab:\ \
--- ```
---
--- Note that list mode will also affect formatting (set with 'textwidth'
@@ -3784,7 +3832,7 @@ vim.o.list = false
vim.wo.list = vim.o.list
--- Strings to use in 'list' mode and for the `:list` command. It is a
---- comma-separated list of string settings.
+--- comma-separated list of string settings. *E1511*
---
--- *lcs-eol*
--- eol:c Character to show at the end of each line. When
@@ -3837,8 +3885,9 @@ vim.wo.list = vim.o.list
--- leading spaces are blank. Overrides the "space" and
--- "multispace" settings for leading spaces. You can
--- combine it with "tab:", for example:
---- ```
---- :set listchars+=tab:>-,lead:.
+---
+--- ```vim
+--- set listchars+=tab:>-,lead:.
--- ```
---
--- *lcs-leadmultispace*
@@ -3875,10 +3924,11 @@ vim.wo.list = vim.o.list
--- omitted.
---
--- The characters ':' and ',' should not be used. UTF-8 characters can
---- be used. All characters must be single width.
+--- be used. All characters must be single width. *E1512*
---
--- Each character can be specified as hex:
---- ```
+---
+--- ```vim
--- set listchars=eol:\\x24
--- set listchars=eol:\\u21b5
--- set listchars=eol:\\U000021b5
@@ -3887,10 +3937,11 @@ vim.wo.list = vim.o.list
--- must be exactly 2 for \\x, 4 for \\u and 8 for \\U.
---
--- Examples:
---- ```
---- :set lcs=tab:>-,trail:-
---- :set lcs=tab:>-,eol:<,nbsp:%
---- :set lcs=extends:>,precedes:<
+---
+--- ```vim
+--- set lcs=tab:>-,trail:-
+--- set lcs=tab:>-,eol:<,nbsp:%
+--- set lcs=extends:>,precedes:<
--- ```
--- `hl-NonText` highlighting will be used for "eol", "extends" and
--- "precedes". `hl-Whitespace` for "nbsp", "space", "tab", "multispace",
@@ -3955,8 +4006,9 @@ vim.go.mef = vim.go.makeef
--- This would be mostly useful when you use MS-Windows. If iconv is
--- enabled, setting 'makeencoding' to "char" has the same effect as
--- setting to the system locale encoding. Example:
---- ```
---- :set makeencoding=char " system locale is used
+---
+--- ```vim
+--- set makeencoding=char " system locale is used
--- ```
---
---
@@ -3977,13 +4029,15 @@ vim.go.menc = vim.go.makeencoding
--- Note that a '|' must be escaped twice: once for ":set" and once for
--- the interpretation of a command. When you use a filter called
--- "myfilter" do it like this:
---- ```
---- :set makeprg=gmake\ \\\|\ myfilter
+---
+--- ```vim
+--- set makeprg=gmake\ \\\|\ myfilter
--- ```
--- The placeholder "$*" can be given (even multiple times) to specify
--- where the arguments will be included, for example:
---- ```
---- :set makeprg=latex\ \\\\nonstopmode\ \\\\input\\{$*}
+---
+--- ```vim
+--- set makeprg=latex\ \\\\nonstopmode\ \\\\input\\{$*}
--- ```
--- This option cannot be set from a `modeline` or in the `sandbox`, for
--- security reasons.
@@ -4003,13 +4057,15 @@ vim.go.mp = vim.go.makeprg
--- The characters must be separated by a colon.
--- The pairs must be separated by a comma. Example for including '<' and
--- '>' (for HTML):
---- ```
---- :set mps+=<:>
+---
+--- ```vim
+--- set mps+=<:>
--- ```
--- A more exotic example, to jump between the '=' and ';' in an
--- assignment, useful for languages like C and Java:
---- ```
---- :au FileType c,cpp,java set mps+==:;
+---
+--- ```vim
+--- au FileType c,cpp,java set mps+==:;
--- ```
--- For a more advanced way of using "%", see the matchit.vim plugin in
--- the $VIMRUNTIME/plugin directory. `add-local-help`
@@ -4037,6 +4093,7 @@ vim.go.mat = vim.go.matchtime
--- Increasing this limit above 200 also changes the maximum for Ex
--- command recursion, see `E169`.
--- See also `:function`.
+--- Also used for maximum depth of callback functions.
---
--- @type integer
vim.o.maxfuncdepth = 100
@@ -4116,8 +4173,9 @@ vim.go.mis = vim.go.menuitems
--- The languages for which these numbers are important are Italian and
--- Hungarian. The default works for when you have about 512 Mbyte. If
--- you have 1 Gbyte you could use:
---- ```
---- :set mkspellmem=900000,3000,800
+---
+--- ```vim
+--- set mkspellmem=900000,3000,800
--- ```
--- If you have less than 512 Mbyte `:mkspell` may fail for some
--- languages, no matter what you set 'mkspellmem' to.
@@ -4212,8 +4270,9 @@ vim.go.more = vim.o.more
--- Enables mouse support. For example, to enable the mouse in Normal mode
--- and Visual mode:
---- ```
---- :set mouse=nv
+---
+--- ```vim
+--- set mouse=nv
--- ```
---
--- To temporarily disable mouse support, hold the shift key while using
@@ -4305,19 +4364,20 @@ vim.go.mh = vim.go.mousehide
--- See `mouse-overview`. But mappings are NOT used for modeless selection.
---
--- Example:
---- ```
---- :map <S-LeftMouse> <RightMouse>
---- :map <S-LeftDrag> <RightDrag>
---- :map <S-LeftRelease> <RightRelease>
---- :map <2-S-LeftMouse> <2-RightMouse>
---- :map <2-S-LeftDrag> <2-RightDrag>
---- :map <2-S-LeftRelease> <2-RightRelease>
---- :map <3-S-LeftMouse> <3-RightMouse>
---- :map <3-S-LeftDrag> <3-RightDrag>
---- :map <3-S-LeftRelease> <3-RightRelease>
---- :map <4-S-LeftMouse> <4-RightMouse>
---- :map <4-S-LeftDrag> <4-RightDrag>
---- :map <4-S-LeftRelease> <4-RightRelease>
+---
+--- ```vim
+--- map <S-LeftMouse> <RightMouse>
+--- map <S-LeftDrag> <RightDrag>
+--- map <S-LeftRelease> <RightRelease>
+--- map <2-S-LeftMouse> <2-RightMouse>
+--- map <2-S-LeftDrag> <2-RightDrag>
+--- map <2-S-LeftRelease> <2-RightRelease>
+--- map <3-S-LeftMouse> <3-RightMouse>
+--- map <3-S-LeftDrag> <3-RightDrag>
+--- map <3-S-LeftRelease> <3-RightRelease>
+--- map <4-S-LeftMouse> <4-RightMouse>
+--- map <4-S-LeftDrag> <4-RightDrag>
+--- map <4-S-LeftRelease> <4-RightRelease>
--- ```
---
--- Mouse commands requiring the CTRL modifier can be simulated by typing
@@ -4357,8 +4417,9 @@ vim.go.mousemev = vim.go.mousemoveevent
--- a count of 0.
---
--- Example:
---- ```
---- :set mousescroll=ver:5,hor:2
+---
+--- ```vim
+--- set mousescroll=ver:5,hor:2
--- ```
--- Will make Nvim scroll 5 lines at a time when scrolling vertically, and
--- scroll 2 columns at a time when scrolling horizontally.
@@ -4421,8 +4482,9 @@ vim.go.mousescroll = vim.o.mousescroll
--- pointer.
---
--- Example:
---- ```
---- :set mouseshape=s:udsizing,m:no
+---
+--- ```vim
+--- set mouseshape=s:udsizing,m:no
--- ```
--- will make the mouse turn to a sizing arrow over the status lines and
--- indicate no input when the hit-enter prompt is displayed (since
@@ -4626,28 +4688,33 @@ vim.go.pm = vim.go.patchmode
--- starting with "/", "./" or "../"). The directories in the 'path'
--- option may be relative or absolute.
--- - Use commas to separate directory names:
---- ```
---- :set path=.,/usr/local/include,/usr/include
+---
+--- ```vim
+--- set path=.,/usr/local/include,/usr/include
--- ```
--- - Spaces can also be used to separate directory names. To have a
--- space in a directory name, precede it with an extra backslash, and
--- escape the space:
---- ```
---- :set path=.,/dir/with\\\ space
+---
+--- ```vim
+--- set path=.,/dir/with\\\ space
--- ```
--- - To include a comma in a directory name precede it with an extra
--- backslash:
---- ```
---- :set path=.,/dir/with\\,comma
+---
+--- ```vim
+--- set path=.,/dir/with\\,comma
--- ```
--- - To search relative to the directory of the current file, use:
---- ```
---- :set path=.
+---
+--- ```vim
+--- set path=.
--- ```
--- - To search in the current directory use an empty string between two
--- commas:
---- ```
---- :set path=,,
+---
+--- ```vim
+--- set path=,,
--- ```
--- - A directory name may end in a ':' or '/'.
--- - Environment variables are expanded `:set_env`.
@@ -4656,12 +4723,14 @@ vim.go.pm = vim.go.patchmode
--- - Search upwards and downwards in a directory tree using "*", "**" and
--- ";". See `file-searching` for info and syntax.
--- - Careful with '\' characters, type two to get one in the option:
---- ```
---- :set path=.,c:\\include
+---
+--- ```vim
+--- set path=.,c:\\include
--- ```
--- Or just use '/' instead:
---- ```
---- :set path=.,c:/include
+---
+--- ```vim
+--- set path=.,c:/include
--- ```
--- Don't forget "." or files won't even be found in the same directory as
--- the file!
@@ -4672,18 +4741,21 @@ vim.go.pm = vim.go.patchmode
--- The use of `:set+=` and `:set-=` is preferred when adding or removing
--- directories from the list. This avoids problems when a future version
--- uses another default. To remove the current directory use:
---- ```
---- :set path-=
+---
+--- ```vim
+--- set path-=
--- ```
--- To add the current directory use:
---- ```
---- :set path+=
+---
+--- ```vim
+--- set path+=
--- ```
--- To use an environment variable, you probably need to replace the
--- separator. Here is an example to append $INCL, in which directory
--- names are separated with a semi-colon:
---- ```
---- :let &path = &path .. "," .. substitute($INCL, ';', ',', 'g')
+---
+--- ```vim
+--- let &path = &path .. "," .. substitute($INCL, ';', ',', 'g')
--- ```
--- Replace the ';' with a ':' or whatever separator is used. Note that
--- this doesn't work when $INCL contains a comma or white space.
@@ -4741,9 +4813,11 @@ vim.wo.pvw = vim.wo.previewwindow
--- It is possible to override the level for individual highlights within
--- the popupmenu using `highlight-blend`. For instance, to enable
--- transparency but force the current selected element to be fully opaque:
---- ```
---- :set pumblend=15
---- :hi PmenuSel blend=0
+---
+--- ```vim
+---
+--- set pumblend=15
+--- hi PmenuSel blend=0
--- ```
---
--- UI-dependent. Works best with RGB colors. 'termguicolors'
@@ -5014,8 +5088,9 @@ vim.go.ru = vim.go.ruler
--- The default ruler width is 17 characters. To make the ruler 15
--- characters wide, put "%15(" at the start and "%)" at the end.
--- Example:
---- ```
---- :set rulerformat=%15(%c%V\ %p%%%)
+---
+--- ```vim
+--- set rulerformat=%15(%c%V\ %p%%%)
--- ```
---
---
@@ -5082,8 +5157,9 @@ vim.go.ruf = vim.go.rulerformat
--- wildcards.
--- See `:runtime`.
--- Example:
---- ```
---- :set runtimepath=~/vimruntime,/mygroup/vim,$VIMRUNTIME
+---
+--- ```vim
+--- set runtimepath=~/vimruntime,/mygroup/vim,$VIMRUNTIME
--- ```
--- This will use the directory "~/vimruntime" first (containing your
--- personal Nvim runtime files), then "/mygroup/vim", and finally
@@ -5164,7 +5240,8 @@ vim.go.sj = vim.go.scrolljump
--- when long lines wrap).
--- After using the local value, go back the global value with one of
--- these two:
---- ```
+---
+--- ```vim
--- setlocal scrolloff<
--- setlocal scrolloff=-1
--- ```
@@ -5393,8 +5470,9 @@ vim.go.ssop = vim.go.sessionoptions
--- contents size) = 10253 bytes.
---
--- Example:
---- ```
---- :set shada='50,<1000,s100,:0,n~/nvim/shada
+---
+--- ```vim
+--- set shada='50,<1000,s100,:0,n~/nvim/shada
--- ```
---
--- '50 Marks will be remembered for the last 50 files you
@@ -5445,14 +5523,16 @@ vim.go.sdf = vim.go.shadafile
---
--- If the name of the shell contains a space, you need to enclose it in
--- quotes. Example with quotes:
---- ```
---- :set shell=\"c:\program\ files\unix\sh.exe\"\ -f
+---
+--- ```vim
+--- set shell=\"c:\program\ files\unix\sh.exe\"\ -f
--- ```
--- Note the backslash before each quote (to avoid starting a comment) and
--- each space (to avoid ending the option value), so better use `:let-&`
--- like this:
---- ```
---- :let &shell='"C:\Program Files\unix\sh.exe" -f'
+---
+--- ```vim
+--- let &shell='"C:\Program Files\unix\sh.exe" -f'
--- ```
--- Also note that the "-f" is not inside the quotes, because it is not
--- part of the command name.
@@ -5477,7 +5557,8 @@ vim.go.sdf = vim.go.shadafile
--- unescaping, so to keep yourself sane use `:let-&` like shown above.
--- *shell-powershell*
--- To use PowerShell:
---- ```
+---
+--- ```vim
--- let &shell = executable('pwsh') ? 'pwsh' : 'powershell'
--- let &shellcmdflag = '-NoLogo -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new();$PSDefaultParameterValues[''Out-File:Encoding'']=''utf8'';Remove-Alias -Force -ErrorAction SilentlyContinue tee;'
--- let &shellredir = '2>&1 | %%{ "$_" } | Out-File %s; exit $LastExitCode'
@@ -5602,7 +5683,8 @@ vim.go.srr = vim.go.shellredir
--- any file for best results. This might change in the future.
--- 'shellslash' only works when a backslash can be used as a path
--- separator. To test if this is so use:
---- ```
+---
+--- ```vim
--- if exists('+shellslash')
--- ```
--- Also see 'completeslash'.
@@ -5715,9 +5797,10 @@ vim.bo.sw = vim.bo.shiftwidth
--- match", "Pattern not found", "Back at original", etc.
--- C don't give messages while scanning for ins-completion *shm-C*
--- items, for instance "scanning tags"
---- q use "recording" instead of "recording @a" *shm-q*
+--- q do not show "recording @a" when recording a macro *shm-q*
--- F don't give the file info when editing a file, like *shm-F*
---- `:silent` was used for the command
+--- `:silent` was used for the command; note that this also
+--- affects messages from 'autoread' reloading
--- S do not show search count message when searching, e.g. *shm-S*
--- "[1/5]"
---
@@ -5738,9 +5821,10 @@ vim.go.shm = vim.go.shortmess
--- String to put at the start of lines that have been wrapped. Useful
--- values are "> " or "+++ ":
---- ```
---- :let &showbreak = "> "
---- :let &showbreak = '+++ '
+---
+--- ```vim
+--- let &showbreak = "> "
+--- let &showbreak = '+++ '
--- ```
--- Only printable single-cell characters are allowed, excluding <Tab> and
--- comma (in a future version the comma might be used to separate the
@@ -5751,8 +5835,9 @@ vim.go.shm = vim.go.shortmess
--- "n" flag to 'cpoptions'.
--- A window-local value overrules a global value. If the global value is
--- set and you want no value in the current window use NONE:
---- ```
---- :setlocal showbreak=NONE
+---
+--- ```vim
+--- setlocal showbreak=NONE
--- ```
---
---
@@ -5884,7 +5969,8 @@ vim.go.ss = vim.go.sidescroll
--- close to the beginning of the line.
--- After using the local value, go back the global value with one of
--- these two:
---- ```
+---
+--- ```vim
--- setlocal sidescrolloff<
--- setlocal sidescrolloff=-1
--- ```
@@ -5892,9 +5978,11 @@ vim.go.ss = vim.go.sidescroll
--- Example: Try this together with 'sidescroll' and 'listchars' as
--- in the following example to never allow the cursor to move
--- onto the "extends" character:
---- ```
---- :set nowrap sidescroll=1 listchars=extends:>,precedes:<
---- :set sidescrolloff=1
+---
+--- ```vim
+---
+--- set nowrap sidescroll=1 listchars=extends:>,precedes:<
+--- set sidescrolloff=1
--- ```
---
---
@@ -6048,7 +6136,7 @@ vim.bo.spc = vim.bo.spellcapcheck
--- Name of the word list file where words are added for the `zg` and `zw`
--- commands. It must end in ".{encoding}.add". You need to include the
--- path, otherwise the file is placed in the current directory.
---- The path may include characters from 'isfname', space, comma and '@'.
+--- The path may include characters from 'isfname', ' ', ',', '@' and ':'.
--- *E765*
--- It may also be a comma-separated list of names. A count before the
--- `zg` and `zw` commands can be used to access each. This allows using
@@ -6075,7 +6163,8 @@ vim.bo.spf = vim.bo.spellfile
--- A comma-separated list of word list names. When the 'spell' option is
--- on spellchecking will be done for these languages. Example:
---- ```
+---
+--- ```vim
--- set spelllang=en_us,nl,medical
--- ```
--- This means US English, Dutch and medical words are recognized. Words
@@ -6193,8 +6282,9 @@ vim.bo.spo = vim.bo.spelloptions
---
--- Only one of "best", "double" or "fast" may be used. The others may
--- appear several times in any order. Example:
---- ```
---- :set sps=file:~/.config/nvim/sugg,best,expr:MySuggest()
+---
+--- ```vim
+--- set sps=file:~/.config/nvim/sugg,best,expr:MySuggest()
--- ```
---
--- This option cannot be set from a `modeline` or in the `sandbox`, for
@@ -6273,9 +6363,13 @@ vim.go.sol = vim.go.startofline
--- %s sign column for currently drawn line
--- %C fold column for currently drawn line
---
---- NOTE: To draw the sign and fold columns, their items must be included in
---- 'statuscolumn'. Even when they are not included, the status column width
---- will adapt to the 'signcolumn' and 'foldcolumn' width.
+--- The 'statuscolumn' width follows that of the default columns and
+--- adapts to the `'numberwidth'`, `'signcolumn'` and `'foldcolumn'` option
+--- values (regardless of whether the sign and fold items are present).
+--- Additionally, the 'statuscolumn' grows with the size of the evaluated
+--- format string, up to a point (following the maximum size of the default
+--- fold, sign and number columns). Shrinking only happens when the number
+--- of lines in a buffer changes, or the 'statuscolumn' option is set.
---
--- The `v:lnum` variable holds the line number to be drawn.
--- The `v:relnum` variable holds the relative line number to be drawn.
@@ -6283,6 +6377,9 @@ vim.go.sol = vim.go.startofline
--- when drawing the actual buffer line, and positive when
--- drawing the wrapped part of a buffer line.
---
+--- When using `v:relnum`, keep in mind that cursor movement by itself will
+--- not cause the 'statuscolumn' to update unless `'relativenumber'` is set.
+---
--- NOTE: The %@ click execute function item is supported as well but the
--- specified function will be the same for each row in the same column.
--- It cannot be switched out through a dynamic 'statuscolumn' format, the
@@ -6292,21 +6389,21 @@ vim.go.sol = vim.go.startofline
---
--- ```vim
--- " Relative number with bar separator and click handlers:
---- :set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T
+--- set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T
---
--- " Right aligned relative cursor line number:
---- :let &stc='%=%{v:relnum?v:relnum:v:lnum} '
+--- let &stc='%=%{v:relnum?v:relnum:v:lnum} '
---
--- " Line numbers in hexadecimal for non wrapped part of lines:
---- :let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} '
+--- let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} '
---
--- " Human readable line numbers with thousands separator:
---- :let &stc='%{substitute(v:lnum,"\\d\\zs\\ze\\'
+--- let &stc='%{substitute(v:lnum,"\\d\\zs\\ze\\'
--- . '%(\\d\\d\\d\\)\\+$",",","g")}'
---
--- " Both relative and absolute line numbers with different
--- " highlighting for odd and even relative numbers:
---- :let &stc='%#NonText#%{&nu?v:lnum:""}' .
+--- let &stc='%#NonText#%{&nu?v:lnum:""}' .
--- '%=%{&rnu&&(v:lnum%2)?"\ ".v:relnum:""}' .
--- '%#LineNr#%{&rnu&&!(v:lnum%2)?"\ ".v:relnum:""}'
--- ```
@@ -6330,8 +6427,9 @@ vim.wo.stc = vim.wo.statuscolumn
---
--- When the option starts with "%!" then it is used as an expression,
--- evaluated and the result is used as the option value. Example:
---- ```
---- :set statusline=%!MyStatusLine()
+---
+--- ```vim
+--- set statusline=%!MyStatusLine()
--- ```
--- The *g:statusline_winid* variable will be set to the `window-ID` of the
--- window that the status line belongs to.
@@ -6414,7 +6512,8 @@ vim.wo.stc = vim.wo.statuscolumn
--- The expression can contain the "}" character, the end of
--- expression is denoted by "%}".
--- For example:
---- ```
+---
+--- ```vim
--- func! Stl_filename() abort
--- return "%t"
--- endfunc
@@ -6427,16 +6526,17 @@ vim.wo.stc = vim.wo.statuscolumn
--- ) - End of item group. No width fields allowed.
--- T N For 'tabline': start of tab page N label. Use %T or %X to end
--- the label. Clicking this label with left mouse button switches
---- to the specified tab page.
+--- to the specified tab page, while clicking it with middle mouse
+--- button closes the specified tab page.
--- X N For 'tabline': start of close tab N label. Use %X or %T to end
--- the label, e.g.: %3Xclose%X. Use %999X for a "close current
---- tab" label. Clicking this label with left mouse button closes
---- specified tab page.
---- @ N Start of execute function label. Use %X or %T to
---- end the label, e.g.: %10@SwitchBuffer@foo.c%X. Clicking this
---- label runs specified function: in the example when clicking once
---- using left mouse button on "foo.c" "SwitchBuffer(10, 1, 'l',
---- ' ')" expression will be run. Function receives the
+--- tab" label. Clicking this label with left mouse button closes
+--- the specified tab page.
+--- @ N Start of execute function label. Use %X or %T to end the label,
+--- e.g.: %10@SwitchBuffer@foo.c%X. Clicking this label runs the
+--- specified function: in the example when clicking once using left
+--- mouse button on "foo.c", a `SwitchBuffer(10, 1, 'l', ' ')`
+--- expression will be run. The specified function receives the
--- following arguments in order:
--- 1. minwid field value or zero if no N was specified
--- 2. number of mouse clicks to detect multiple clicks
@@ -6483,8 +6583,9 @@ vim.wo.stc = vim.wo.statuscolumn
--- not set) and a minwid is not set for the group, the whole group will
--- become empty. This will make a group like the following disappear
--- completely from the statusline when none of the flags are set.
---- ```
---- :set statusline=...%(\ [%M%R%H]%)...
+---
+--- ```vim
+--- set statusline=...%(\ [%M%R%H]%)...
--- ```
--- Beware that an expression is evaluated each and every time the status
--- line is displayed.
@@ -6517,35 +6618,42 @@ vim.wo.stc = vim.wo.statuscolumn
---
--- Examples:
--- Emulate standard status line with 'ruler' set
---- ```
---- :set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
+---
+--- ```vim
+--- set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
--- ```
--- Similar, but add ASCII value of char under the cursor (like "ga")
---- ```
---- :set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P
+---
+--- ```vim
+--- set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P
--- ```
--- Display byte count and byte value, modified flag in red.
---- ```
---- :set statusline=%<%f%=\ [%1*%M%*%n%R%H]\ %-19(%3l,%02c%03V%)%O'%02b'
---- :hi User1 term=inverse,bold cterm=inverse,bold ctermfg=red
+---
+--- ```vim
+--- set statusline=%<%f%=\ [%1*%M%*%n%R%H]\ %-19(%3l,%02c%03V%)%O'%02b'
+--- hi User1 term=inverse,bold cterm=inverse,bold ctermfg=red
--- ```
--- Display a ,GZ flag if a compressed file is loaded
---- ```
---- :set statusline=...%r%{VarExists('b:gzflag','\ [GZ]')}%h...
+---
+--- ```vim
+--- set statusline=...%r%{VarExists('b:gzflag','\ [GZ]')}%h...
--- ```
--- In the `:autocmd`'s:
---- ```
---- :let b:gzflag = 1
+---
+--- ```vim
+--- let b:gzflag = 1
--- ```
--- And:
---- ```
---- :unlet b:gzflag
+---
+--- ```vim
+--- unlet b:gzflag
--- ```
--- And define this function:
---- ```
---- :function VarExists(var, val)
---- : if exists(a:var) | return a:val | else | return '' | endif
---- :endfunction
+---
+--- ```vim
+--- function VarExists(var, val)
+--- if exists(a:var) | return a:val | else | return '' | endif
+--- endfunction
--- ```
---
---
@@ -6576,8 +6684,9 @@ vim.go.su = vim.go.suffixes
--- Comma-separated list of suffixes, which are used when searching for a
--- file for the "gf", "[I", etc. commands. Example:
---- ```
---- :set suffixesadd=.java
+---
+--- ```vim
+--- set suffixesadd=.java
--- ```
---
---
@@ -6662,26 +6771,26 @@ vim.bo.smc = vim.bo.synmaxcol
--- Otherwise this option does not always reflect the current syntax (the
--- b:current_syntax variable does).
--- This option is most useful in a modeline, for a file which syntax is
---- not automatically recognized. Example, in an IDL file:
---- ```
+--- not automatically recognized. Example, in an IDL file: >c
--- /* vim: set syntax=idl : */
--- ```
--- When a dot appears in the value then this separates two filetype
---- names. Example:
---- ```
+--- names. Example: >c
--- /* vim: set syntax=c.doxygen : */
--- ```
--- This will use the "c" syntax first, then the "doxygen" syntax.
--- Note that the second one must be prepared to be loaded as an addition,
--- otherwise it will be skipped. More than one dot may appear.
--- To switch off syntax highlighting for the current file, use:
---- ```
---- :set syntax=OFF
+---
+--- ```vim
+--- set syntax=OFF
--- ```
--- To switch syntax highlighting on according to the current value of the
--- 'filetype' option:
---- ```
---- :set syntax=ON
+---
+--- ```vim
+--- set syntax=ON
--- ```
--- What actually happens when setting the 'syntax' option is that the
--- Syntax autocommand event is triggered with the value as argument.
@@ -6941,6 +7050,10 @@ vim.go.tbidi = vim.go.termbidi
--- attributes instead of "cterm" attributes. `guifg`
--- Requires an ISO-8613-3 compatible terminal.
---
+--- Nvim will automatically attempt to determine if the host terminal
+--- supports 24-bit color and will enable this option if it does
+--- (unless explicitly disabled by the user).
+---
--- @type boolean
vim.o.termguicolors = false
vim.o.tgc = vim.o.termguicolors
@@ -7107,15 +7220,17 @@ vim.go.titleold = vim.o.titleold
--- This option cannot be set in a modeline when 'modelineexpr' is off.
---
--- Example:
---- ```
---- :auto BufEnter * let &titlestring = hostname() .. "/" .. expand("%:p")
---- :set title titlestring=%<%F%=%l/%L-%P titlelen=70
+---
+--- ```vim
+--- auto BufEnter * let &titlestring = hostname() .. "/" .. expand("%:p")
+--- set title titlestring=%<%F%=%l/%L-%P titlelen=70
--- ```
--- The value of 'titlelen' is used to align items in the middle or right
--- of the available space.
--- Some people prefer to have the file name first:
---- ```
---- :set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:.:h\")})%)%(\ %a%)
+---
+--- ```vim
+--- set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:.:h\")})%)%(\ %a%)
--- ```
--- Note the use of "%{ }" and an expression to get the path of the file,
--- without the file name. The "%( %)" constructs are used to add a
@@ -7200,7 +7315,8 @@ vim.bo.udf = vim.bo.undofile
--- Nevertheless, a single change can already use a large amount of memory.
--- Set to 0 for Vi compatibility: One level of undo and "u" undoes
--- itself:
---- ```
+---
+--- ```vim
--- set ul=0
--- ```
--- But you can also get Vi compatibility by including the 'u' flag in
@@ -7208,7 +7324,8 @@ vim.bo.udf = vim.bo.undofile
--- Also see `undo-two-ways`.
--- Set to -1 for no undo at all. You might want to do this only for the
--- current buffer:
---- ```
+---
+--- ```vim
--- setlocal ul=-1
--- ```
--- This helps when you run out of memory for a single change.
@@ -7280,8 +7397,9 @@ vim.go.ut = vim.go.updatetime
--- For example, when editing assembly language files where statements
--- start in the 9th column and comments in the 41st, it may be useful
--- to use the following:
---- ```
---- :set varsofttabstop=8,32,8
+---
+--- ```vim
+--- set varsofttabstop=8,32,8
--- ```
--- This will set soft tabstops with 8 and 8 + 32 spaces, and 8 more
--- for every column thereafter.
@@ -7298,8 +7416,9 @@ vim.bo.vsts = vim.bo.varsofttabstop
--- A list of the number of spaces that a <Tab> in the file counts for,
--- separated by commas. Each value corresponds to one tab, with the
--- final value applying to all subsequent tabs. For example:
---- ```
---- :set vartabstop=4,20,10,8
+---
+--- ```vim
+--- set vartabstop=4,20,10,8
--- ```
--- This will make the first tab 4 spaces wide, the second 20 spaces,
--- the third 10 spaces, and all following tabs 8 spaces.
@@ -7315,15 +7434,15 @@ vim.bo.vts = vim.bo.vartabstop
--- Sets the verbosity level. Also set by `-V` and `:verbose`.
---
---- Tracing of options in Lua scripts is activated at level 1; Lua scripts
---- are not traced with verbose=0, for performance.
+--- Tracing of assignments to options, mappings, etc. in Lua scripts is
+--- enabled at level 1; Lua scripts are not traced when 'verbose' is 0,
+--- for performance.
---
--- If greater than or equal to a given level, Nvim produces the following
--- messages:
---
--- Level Messages ~
--- ----------------------------------------------------------------------
---- 1 Lua assignments to options, mappings, etc.
--- 2 When a file is ":source"'ed, or `shada` file is read or written.
--- 3 UI info, terminal capabilities.
--- 4 Shell commands.
@@ -7454,8 +7573,9 @@ vim.go.warn = vim.o.warn
--- [ <Left> Insert and Replace
--- ] <Right> Insert and Replace
--- For example:
---- ```
---- :set ww=<,>,[,]
+---
+--- ```vim
+--- set ww=<,>,[,]
--- ```
--- allows wrap only when cursor keys are used.
--- When the movement keys are used in combination with a delete or change
@@ -7484,8 +7604,9 @@ vim.go.ww = vim.go.whichwrap
--- <Esc> can be used, but hitting it twice in a row will still exit
--- command-line as a failsafe measure.
--- Although 'wc' is a number option, you can set it to a special key:
---- ```
---- :set wc=<Tab>
+---
+--- ```vim
+--- set wc=<Tab>
--- ```
---
---
@@ -7500,9 +7621,10 @@ vim.go.wc = vim.go.wildchar
--- keys suitable for this option by looking at `ex-edit-index`. Normally
--- you'll never actually type 'wildcharm', just use it in mappings that
--- automatically invoke completion mode, e.g.:
---- ```
---- :set wcm=<C-Z>
---- :cnoremap ss so $vim/sessions/*.vim<C-Z>
+---
+--- ```vim
+--- set wcm=<C-Z>
+--- cnoremap ss so $vim/sessions/*.vim<C-Z>
--- ```
--- Then after typing :ss you can use CTRL-P & CTRL-N.
---
@@ -7519,8 +7641,9 @@ vim.go.wcm = vim.go.wildcharm
--- The pattern is used like with `:autocmd`, see `autocmd-pattern`.
--- Also see 'suffixes'.
--- Example:
---- ```
---- :set wildignore=*.o,*.obj
+---
+--- ```vim
+--- set wildignore=*.o,*.obj
--- ```
--- The use of `:set+=` and `:set-=` is preferred when adding or removing
--- a pattern from the list. This avoids problems when a future version
@@ -7576,9 +7699,10 @@ vim.go.wic = vim.go.wildignorecase
---
--- If you want <Left> and <Right> to move the cursor instead of selecting
--- a different match, use this:
---- ```
---- :cnoremap <Left> <Space><BS><Left>
---- :cnoremap <Right> <Space><BS><Right>
+---
+--- ```vim
+--- cnoremap <Left> <Space><BS><Left>
+--- cnoremap <Right> <Space><BS><Right>
--- ```
---
--- `hl-WildMenu` highlights the current match.
@@ -7621,24 +7745,29 @@ vim.go.wmnu = vim.go.wildmenu
--- current buffer).
---
--- Examples:
---- ```
---- :set wildmode=full
+---
+--- ```vim
+--- set wildmode=full
--- ```
--- Complete first full match, next match, etc. (the default)
---- ```
---- :set wildmode=longest,full
+---
+--- ```vim
+--- set wildmode=longest,full
--- ```
--- Complete longest common string, then each full match
---- ```
---- :set wildmode=list:full
+---
+--- ```vim
+--- set wildmode=list:full
--- ```
--- List all matches and complete each full match
---- ```
---- :set wildmode=list,full
+---
+--- ```vim
+--- set wildmode=list,full
--- ```
--- List all matches without completing, then each full match
---- ```
---- :set wildmode=longest,list
+---
+--- ```vim
+--- set wildmode=longest,list
--- ```
--- Complete longest common string, then list alternatives.
--- More info here: `cmdline-completion`.
@@ -7776,7 +7905,8 @@ vim.wo.wfw = vim.wo.winfixwidth
--- that ":all" will create only two windows. To avoid "vim -o 1 2 3 4"
--- to create only two windows, set the option after startup is done,
--- using the `VimEnter` event:
---- ```
+---
+--- ```vim
--- au VimEnter * set winheight=999
--- ```
--- Minimum value is 1.
@@ -7806,7 +7936,8 @@ vim.go.wh = vim.go.winheight
--- message area cannot be overridden.
---
--- Example: show a different color for non-current windows:
---- ```
+---
+--- ```vim
--- set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC
--- ```
---
@@ -7876,9 +8007,10 @@ vim.go.wiw = vim.go.winwidth
--- The line will be broken in the middle of a word if necessary. See
--- 'linebreak' to get the break at a word boundary.
--- To make scrolling horizontally a bit more useful, try this:
---- ```
---- :set sidescroll=5
---- :set listchars+=precedes:<,extends:>
+---
+--- ```vim
+--- set sidescroll=5
+--- set listchars+=precedes:<,extends:>
--- ```
--- See 'sidescroll', 'listchars' and `wrap-off`.
--- This option can't be set from a `modeline` when the 'diff' option is
diff --git a/runtime/lua/vim/_meta/re.lua b/runtime/lua/vim/_meta/re.lua
new file mode 100644
index 0000000000..14c94c7824
--- /dev/null
+++ b/runtime/lua/vim/_meta/re.lua
@@ -0,0 +1,54 @@
+--- @meta
+error('Cannot require a meta file')
+
+-- Documentations and Lua types for vim.re (vendored re.lua, lpeg-1.1.0)
+-- https://www.inf.puc-rio.br/~roberto/lpeg/re.html
+--
+-- Copyright © 2007-2023 Lua.org, PUC-Rio.
+-- See 'lpeg.html' for license
+
+--- @brief
+--- The `vim.re` module provides a conventional regex-like syntax for pattern usage
+--- within LPeg |vim.lpeg|.
+---
+--- See https://www.inf.puc-rio.br/~roberto/lpeg/re.html for the original
+--- documentation including regex syntax and more concrete examples.
+
+--- Compiles the given {string} and returns an equivalent LPeg pattern. The given string may define
+--- either an expression or a grammar. The optional {defs} table provides extra Lua values to be used
+--- by the pattern.
+--- @param string string
+--- @param defs? table
+--- @return vim.lpeg.Pattern
+function vim.re.compile(string, defs) end
+
+--- Searches the given {pattern} in the given {subject}. If it finds a match, returns the index
+--- where this occurrence starts and the index where it ends. Otherwise, returns nil.
+---
+--- An optional numeric argument {init} makes the search starts at that position in the subject
+--- string. As usual in Lua libraries, a negative value counts from the end.
+--- @param subject string
+--- @param pattern vim.lpeg.Pattern|string
+--- @param init? integer
+--- @return integer|nil the index where the occurrence starts, nil if no match
+--- @return integer|nil the index where the occurrence ends, nil if no match
+function vim.re.find(subject, pattern, init) end
+
+--- Does a global substitution, replacing all occurrences of {pattern} in the given {subject} by
+--- {replacement}.
+--- @param subject string
+--- @param pattern vim.lpeg.Pattern|string
+--- @param replacement string
+--- @return string
+function vim.re.gsub(subject, pattern, replacement) end
+
+--- Matches the given {pattern} against the given {subject}, returning all captures.
+--- @param subject string
+--- @param pattern vim.lpeg.Pattern|string
+--- @param init? integer
+--- @return integer|vim.lpeg.Capture|nil
+--- @see vim.lpeg.match()
+function vim.re.match(subject, pattern, init) end
+
+--- Updates the pre-defined character classes to the current locale.
+function vim.re.updatelocale() end
diff --git a/runtime/lua/vim/_meta/regex.lua b/runtime/lua/vim/_meta/regex.lua
index 58aa2be8c2..595ad96319 100644
--- a/runtime/lua/vim/_meta/regex.lua
+++ b/runtime/lua/vim/_meta/regex.lua
@@ -2,8 +2,6 @@
-- luacheck: no unused args
---- @defgroup vim.regex
----
--- @brief Vim regexes can be used directly from Lua. Currently they only allow
--- matching within a single line.
@@ -14,6 +12,7 @@
--- @return vim.regex
function vim.regex(re) end
+--- @nodoc
--- @class vim.regex
local regex = {} -- luacheck: no unused
diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua
index 05e5b2b871..ac25547212 100644
--- a/runtime/lua/vim/_meta/vimfn.lua
+++ b/runtime/lua/vim/_meta/vimfn.lua
@@ -582,7 +582,7 @@ function vim.fn.bufloaded(buf) end
--- echo bufname("file2") " name of buffer where "file2" matches.
--- <
---
---- @param buf? any
+--- @param buf? integer|string
--- @return string
function vim.fn.bufname(buf) end
@@ -599,7 +599,7 @@ function vim.fn.bufname(buf) end
--- number necessarily exist, because ":bwipeout" may have removed
--- them. Use bufexists() to test for the existence of a buffer.
---
---- @param buf? any
+--- @param buf? integer|string
--- @param create? any
--- @return integer
function vim.fn.bufnr(buf, create) end
@@ -1024,6 +1024,8 @@ function vim.fn.complete_check() end
--- no item is selected when using the <Up> or
--- <Down> keys)
--- inserted Inserted string. [NOT IMPLEMENTED YET]
+--- preview_winid Info floating preview window id.
+--- preview_bufnr Info floating preview buffer id.
---
--- *complete_info_mode*
--- mode values are:
@@ -1707,6 +1709,7 @@ function vim.fn.exepath(expr) end
--- echo exists("*strftime")
--- echo exists("*s:MyFunc")
--- echo exists("*MyFunc")
+--- echo exists("*v:lua.Func")
--- echo exists("bufcount")
--- echo exists(":Make")
--- echo exists("#CursorHold")
@@ -1841,7 +1844,13 @@ function vim.fn.exp(expr) end
---
--- @param string string
--- @param nosuf? boolean
---- @param list? any
+--- @param list? nil|false
+--- @return string
+function vim.fn.expand(string, nosuf, list) end
+
+--- @param string string
+--- @param nosuf boolean
+--- @param list true|number|string|table
--- @return string|string[]
function vim.fn.expand(string, nosuf, list) end
@@ -2300,6 +2309,45 @@ function vim.fn.foldtext() end
--- @return string
function vim.fn.foldtextresult(lnum) end
+--- {expr1} must be a |List|, |String|, |Blob| or |Dictionary|.
+--- For each item in {expr1} execute {expr2}. {expr1} is not
+--- modified; its values may be, as with |:lockvar| 1. |E741|
+--- See |map()| and |filter()| to modify {expr1}.
+---
+--- {expr2} must be a |string| or |Funcref|.
+---
+--- If {expr2} is a |string|, inside {expr2} |v:val| has the value
+--- of the current item. For a |Dictionary| |v:key| has the key
+--- of the current item and for a |List| |v:key| has the index of
+--- the current item. For a |Blob| |v:key| has the index of the
+--- current byte. For a |String| |v:key| has the index of the
+--- current character.
+--- Examples: >vim
+--- call foreach(mylist, 'let used[v:val] = v:true')
+--- <This records the items that are in the {expr1} list.
+---
+--- Note that {expr2} is the result of expression and is then used
+--- as a command. Often it is good to use a |literal-string| to
+--- avoid having to double backslashes.
+---
+--- If {expr2} is a |Funcref| it must take two arguments:
+--- 1. the key or the index of the current item.
+--- 2. the value of the current item.
+--- With a lambda you don't get an error if it only accepts one
+--- argument.
+--- If the function returns a value, it is ignored.
+---
+--- Returns {expr1} in all cases.
+--- When an error is encountered while executing {expr2} no
+--- further items in {expr1} are processed.
+--- When {expr2} is a Funcref errors inside a function are ignored,
+--- unless it was defined with the "abort" flag.
+---
+--- @param expr1 any
+--- @param expr2 any
+--- @return any
+function vim.fn.foreach(expr1, expr2) end
+
--- Get the full command name from a short abbreviated command
--- name; see |20.2| for details on command abbreviations.
---
@@ -2514,6 +2562,8 @@ function vim.fn.getbufinfo(buf) end
--- bufnr Buffer number.
--- changed TRUE if the buffer is modified.
--- changedtick Number of changes made to the buffer.
+--- command TRUE if the buffer belongs to the
+--- command-line window |cmdwin|.
--- hidden TRUE if the buffer is hidden.
--- lastused Timestamp in seconds, like
--- |localtime()|, when the buffer was
@@ -2729,7 +2779,7 @@ function vim.fn.getchar() end
--- 32 mouse double click
--- 64 mouse triple click
--- 96 mouse quadruple click (== 32 + 64)
---- 128 command (Macintosh only)
+--- 128 command (Mac) or super
--- Only the modifiers that have not been included in the
--- character itself are obtained. Thus Shift-a results in "A"
--- without a modifier. Returns 0 if no modifiers are used.
@@ -2887,6 +2937,7 @@ function vim.fn.getcmdwintype() end
--- help help subjects
--- highlight highlight groups
--- history |:history| suboptions
+--- keymap keyboard mappings
--- locale locale names (as output of locale -a)
--- mapclear buffer argument
--- mapping mapping name
@@ -3134,8 +3185,13 @@ function vim.fn.getjumplist(winnr, tabnr) end
--- <To get lines from another buffer see |getbufline()| and
--- |getbufoneline()|
---
+--- @param lnum integer|string
+--- @param end_? nil|false
+--- @return string
+function vim.fn.getline(lnum, end_) end
+
--- @param lnum integer
---- @param end_? any
+--- @param end_ true|number|string|table
--- @return string|string[]
function vim.fn.getline(lnum, end_) end
@@ -3433,7 +3489,12 @@ function vim.fn.getqflist(what) end
--- If {regname} is not specified, |v:register| is used.
---
--- @param regname? string
---- @param list? any
+--- @param list? nil|false
+--- @return string
+function vim.fn.getreg(regname, list) end
+
+--- @param regname string
+--- @param list true|number|string|table
--- @return string|string[]
function vim.fn.getreg(regname, list) end
@@ -3464,6 +3525,62 @@ function vim.fn.getreg(regname, list) end
--- @return table
function vim.fn.getreginfo(regname) end
+--- Returns the list of strings from {pos1} to {pos2} from a
+--- buffer.
+---
+--- {pos1} and {pos2} must both be |List|s with four numbers.
+--- See |getpos()| for the format of the list. It's possible
+--- to specify positions from a different buffer, but please
+--- note the limitations at |getregion-notes|.
+---
+--- The optional argument {opts} is a Dict and supports the
+--- following items:
+---
+--- type Specify the region's selection type
+--- (default: "v"):
+--- "v" for |charwise| mode
+--- "V" for |linewise| mode
+--- "<CTRL-V>" for |blockwise-visual| mode
+---
+--- exclusive If |TRUE|, use exclusive selection
+--- for the end position
+--- (default: follow 'selection')
+---
+--- You can get the last selection type by |visualmode()|.
+--- If Visual mode is active, use |mode()| to get the Visual mode
+--- (e.g., in a |:vmap|).
+--- This function is useful to get text starting and ending in
+--- different columns, such as a |charwise-visual| selection.
+---
+--- *getregion-notes*
+--- Note that:
+--- - Order of {pos1} and {pos2} doesn't matter, it will always
+--- return content from the upper left position to the lower
+--- right position.
+--- - If 'virtualedit' is enabled and the region is past the end
+--- of the lines, resulting lines are padded with spaces.
+--- - If the region is blockwise and it starts or ends in the
+--- middle of a multi-cell character, it is not included but
+--- its selected part is substituted with spaces.
+--- - If {pos1} and {pos2} are not in the same buffer, an empty
+--- list is returned.
+--- - {pos1} and {pos2} must belong to a |bufloaded()| buffer.
+--- - It is evaluated in current window context, which makes a
+--- difference if the buffer is displayed in a window with
+--- different 'virtualedit' or 'list' values.
+---
+--- Examples: >
+--- :xnoremap <CR>
+--- \ <Cmd>echom getregion(
+--- \ getpos('v'), getpos('.'), #{ type: mode() })<CR>
+--- <
+---
+--- @param pos1 table
+--- @param pos2 table
+--- @param opts? table
+--- @return string[]
+function vim.fn.getregion(pos1, pos2, opts) end
+
--- The result is a String, which is type of register {regname}.
--- The value will be one of:
--- "v" for |charwise| text
@@ -4135,7 +4252,7 @@ function vim.fn.id(expr) end
--- |getline()|.
--- When {lnum} is invalid -1 is returned.
---
---- @param lnum integer
+--- @param lnum integer|string
--- @return integer
function vim.fn.indent(lnum) end
@@ -4678,8 +4795,7 @@ function vim.fn.join(list, sep) end
--- Vim value. In the following cases it will output
--- |msgpack-special-dict|:
--- 1. Dictionary contains duplicate key.
---- 2. Dictionary contains empty key.
---- 3. String contains NUL byte. Two special dictionaries: for
+--- 2. String contains NUL byte. Two special dictionaries: for
--- dictionary and for string will be emitted in case string
--- with NUL byte was a dictionary key.
---
@@ -5065,7 +5181,14 @@ function vim.fn.map(expr1, expr2) end
--- @param name string
--- @param mode? string
--- @param abbr? boolean
---- @param dict? boolean
+--- @param dict? false
+--- @return string
+function vim.fn.maparg(name, mode, abbr, dict) end
+
+--- @param name string
+--- @param mode string
+--- @param abbr boolean
+--- @param dict true
--- @return string|table<string,any>
function vim.fn.maparg(name, mode, abbr, dict) end
@@ -5150,6 +5273,12 @@ function vim.fn.maplist() end
--- @return any
function vim.fn.mapnew(expr1, expr2) end
+--- @param mode string
+--- @param abbr? any
+--- @param dict? any
+--- @return any
+function vim.fn.mapset(mode, abbr, dict) end
+
--- Restore a mapping from a dictionary, possibly returned by
--- |maparg()| or |maplist()|. A buffer mapping, when dict.buffer
--- is true, is set on the current buffer; it is up to the caller
@@ -5185,11 +5314,9 @@ function vim.fn.mapnew(expr1, expr2) end
--- call mapset(d)
--- endfor
---
---- @param mode string
---- @param abbr? any
---- @param dict? any
+--- @param dict any
--- @return any
-function vim.fn.mapset(mode, abbr, dict) end
+function vim.fn.mapset(dict) end
--- When {expr} is a |List| then this returns the index of the
--- first item where {pat} matches. Each item is used as a
@@ -5243,6 +5370,7 @@ function vim.fn.mapset(mode, abbr, dict) end
--- Note that when {count} is added the way {start} works changes,
--- see above.
---
+--- *match-pattern*
--- See |pattern| for the patterns that are accepted.
--- The 'ignorecase' option is used to set the ignore-caseness of
--- the pattern. 'smartcase' is NOT used. The matching is always
@@ -5383,6 +5511,57 @@ function vim.fn.matchaddpos(group, pos, priority, id, dict) end
--- @return any
function vim.fn.matcharg(nr) end
+--- Returns the |List| of matches in lines from {lnum} to {end} in
+--- buffer {buf} where {pat} matches.
+---
+--- {lnum} and {end} can either be a line number or the string "$"
+--- to refer to the last line in {buf}.
+---
+--- The {dict} argument supports following items:
+--- submatches include submatch information (|/\(|)
+---
+--- For each match, a |Dict| with the following items is returned:
+--- byteidx starting byte index of the match
+--- lnum line number where there is a match
+--- text matched string
+--- Note that there can be multiple matches in a single line.
+---
+--- This function works only for loaded buffers. First call
+--- |bufload()| if needed.
+---
+--- See |match-pattern| for information about the effect of some
+--- option settings on the pattern.
+---
+--- When {buf} is not a valid buffer, the buffer is not loaded or
+--- {lnum} or {end} is not valid then an error is given and an
+--- empty |List| is returned.
+---
+--- Examples: >vim
+--- " Assuming line 3 in buffer 5 contains "a"
+--- :echo matchbufline(5, '\<\k\+\>', 3, 3)
+--- [{'lnum': 3, 'byteidx': 0, 'text': 'a'}]
+--- " Assuming line 4 in buffer 10 contains "tik tok"
+--- :echo matchbufline(10, '\<\k\+\>', 1, 4)
+--- [{'lnum': 4, 'byteidx': 0, 'text': 'tik'}, {'lnum': 4, 'byteidx': 4, 'text': 'tok'}]
+--- <
+--- If {submatch} is present and is v:true, then submatches like
+--- "\1", "\2", etc. are also returned. Example: >vim
+--- " Assuming line 2 in buffer 2 contains "acd"
+--- :echo matchbufline(2, '\(a\)\?\(b\)\?\(c\)\?\(.*\)', 2, 2
+--- \ {'submatches': v:true})
+--- [{'lnum': 2, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
+--- <The "submatches" List always contains 9 items. If a submatch
+--- is not found, then an empty string is returned for that
+--- submatch.
+---
+--- @param buf string|integer
+--- @param pat string
+--- @param lnum string|integer
+--- @param end_ string|integer
+--- @param dict? table
+--- @return any
+function vim.fn.matchbufline(buf, pat, lnum, end_, dict) end
+
--- Deletes a match with ID {id} previously defined by |matchadd()|
--- or one of the |:match| commands. Returns 0 if successful,
--- otherwise -1. See example for |matchadd()|. All matches can
@@ -5552,6 +5731,44 @@ function vim.fn.matchlist(expr, pat, start, count) end
--- @return any
function vim.fn.matchstr(expr, pat, start, count) end
+--- Returns the |List| of matches in {list} where {pat} matches.
+--- {list} is a |List| of strings. {pat} is matched against each
+--- string in {list}.
+---
+--- The {dict} argument supports following items:
+--- submatches include submatch information (|/\(|)
+---
+--- For each match, a |Dict| with the following items is returned:
+--- byteidx starting byte index of the match.
+--- idx index in {list} of the match.
+--- text matched string
+--- submatches a List of submatches. Present only if
+--- "submatches" is set to v:true in {dict}.
+---
+--- See |match-pattern| for information about the effect of some
+--- option settings on the pattern.
+---
+--- Example: >vim
+--- :echo matchstrlist(['tik tok'], '\<\k\+\>')
+--- [{'idx': 0, 'byteidx': 0, 'text': 'tik'}, {'idx': 0, 'byteidx': 4, 'text': 'tok'}]
+--- :echo matchstrlist(['a', 'b'], '\<\k\+\>')
+--- [{'idx': 0, 'byteidx': 0, 'text': 'a'}, {'idx': 1, 'byteidx': 0, 'text': 'b'}]
+--- <
+--- If "submatches" is present and is v:true, then submatches like
+--- "\1", "\2", etc. are also returned. Example: >vim
+--- :echo matchstrlist(['acd'], '\(a\)\?\(b\)\?\(c\)\?\(.*\)',
+--- \ #{submatches: v:true})
+--- [{'idx': 0, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
+--- <The "submatches" List always contains 9 items. If a submatch
+--- is not found, then an empty string is returned for that
+--- submatch.
+---
+--- @param list string[]
+--- @param pat string
+--- @param dict? table
+--- @return any
+function vim.fn.matchstrlist(list, pat, dict) end
+
--- Same as |matchstr()|, but return the matched string, the start
--- position and the end position of the match. Example: >vim
--- echo matchstrpos("testing", "ing")
@@ -5583,7 +5800,7 @@ function vim.fn.matchstrpos(expr, pat, start, count) end
--- it returns the maximum of all values in the Dictionary.
--- If {expr} is neither a List nor a Dictionary, or one of the
--- items in {expr} cannot be used as a Number this results in
---- an error. An empty |List| or |Dictionary| results in zero.
+--- an error. An empty |List| or |Dictionary| results in zero.
---
--- @param expr any
--- @return any
@@ -5828,8 +6045,9 @@ function vim.fn.mkdir(name, flags, prot) end
--- the leading character(s).
--- Also see |visualmode()|.
---
+--- @param expr? any
--- @return any
-function vim.fn.mode() end
+function vim.fn.mode(expr) end
--- Convert a list of Vimscript objects to msgpack. Returned value is a
--- |readfile()|-style list. When {type} contains "B", a |Blob| is
@@ -5922,7 +6140,6 @@ function vim.fn.msgpackdump(list, type) end
--- are binary strings).
--- 2. String with NUL byte inside.
--- 3. Duplicate key.
---- 4. Empty key.
--- ext |List| with two values: first is a signed integer
--- representing extension type. Second is
--- |readfile()|-style list of strings.
@@ -6158,9 +6375,9 @@ function vim.fn.prevnonblank(lnum) end
--- <This limits the length of the text used from "line" to
--- "width" bytes.
---
---- If the argument to be formatted is specified using a posional
---- argument specifier, and a '*' is used to indicate that a
---- number argument is to be used to specify the width or
+--- If the argument to be formatted is specified using a
+--- positional argument specifier, and a '*' is used to indicate
+--- that a number argument is to be used to specify the width or
--- precision, the argument(s) to be used must also be specified
--- using a {n$} positional argument specifier. See |printf-$|.
---
@@ -7969,7 +8186,7 @@ function vim.fn.setqflist(list, action, what) end
---
--- @param regname string
--- @param value any
---- @param options? table
+--- @param options? string
--- @return any
function vim.fn.setreg(regname, value, options) end
@@ -9311,7 +9528,12 @@ function vim.fn.strwidth(string) end
--- A line break is included as a newline character.
---
--- @param nr integer
---- @param list? integer
+--- @param list? nil
+--- @return string
+function vim.fn.submatch(nr, list) end
+
+--- @param nr integer
+--- @param list integer
--- @return string|string[]
function vim.fn.submatch(nr, list) end
@@ -9527,7 +9749,7 @@ function vim.fn.synIDtrans(synID) end
---
--- @param lnum integer
--- @param col integer
---- @return {[1]: integer, [2]: string, [3]: integer}[]
+--- @return {[1]: integer, [2]: string, [3]: integer}
function vim.fn.synconcealed(lnum, col) end
--- Return a |List|, which is the stack of syntax items at the
diff --git a/runtime/lua/vim/_meta/vvars.lua b/runtime/lua/vim/_meta/vvars.lua
new file mode 100644
index 0000000000..ee6d8ddf35
--- /dev/null
+++ b/runtime/lua/vim/_meta/vvars.lua
@@ -0,0 +1,779 @@
+--- @meta _
+-- THIS FILE IS GENERATED
+-- DO NOT EDIT
+error('Cannot require a meta file')
+
+--- @class vim.v
+vim.v = ...
+
+--- The command line arguments Vim was invoked with. This is a
+--- list of strings. The first item is the Vim command.
+--- See `v:progpath` for the command with full path.
+--- @type string[]
+vim.v.argv = ...
+
+--- Argument for evaluating 'formatexpr' and used for the typed
+--- character when using <expr> in an abbreviation `:map-<expr>`.
+--- It is also used by the `InsertCharPre` and `InsertEnter` events.
+--- @type any
+vim.v.char = ...
+
+--- The name of the character encoding of a file to be converted.
+--- Only valid while evaluating the 'charconvert' option.
+--- @type string
+vim.v.charconvert_from = ...
+
+--- The name of the character encoding of a file after conversion.
+--- Only valid while evaluating the 'charconvert' option.
+--- @type string
+vim.v.charconvert_to = ...
+
+--- The extra arguments ("++p", "++enc=", "++ff=") given to a file
+--- read/write command. This is set before an autocommand event
+--- for a file read/write command is triggered. There is a
+--- leading space to make it possible to append this variable
+--- directly after the read/write command. Note: "+cmd" isn't
+--- included here, because it will be executed anyway.
+--- @type string
+vim.v.cmdarg = ...
+
+--- Set like v:cmdarg for a file read/write command. When a "!"
+--- was used the value is 1, otherwise it is 0. Note that this
+--- can only be used in autocommands. For user commands `<bang>`
+--- can be used.
+--- @type integer
+vim.v.cmdbang = ...
+
+--- The current locale setting for collation order of the runtime
+--- environment. This allows Vim scripts to be aware of the
+--- current locale encoding. Technical: it's the value of
+--- LC_COLLATE. When not using a locale the value is "C".
+--- This variable can not be set directly, use the `:language`
+--- command.
+--- See `multi-lang`.
+--- @type string
+vim.v.collate = ...
+
+--- Dictionary containing the most recent `complete-items` after
+--- `CompleteDone`. Empty if the completion failed, or after
+--- leaving and re-entering insert mode.
+--- Note: Plugins can modify the value to emulate the builtin
+--- `CompleteDone` event behavior.
+--- @type any
+vim.v.completed_item = ...
+
+--- The count given for the last Normal mode command. Can be used
+--- to get the count before a mapping. Read-only. Example:
+---
+--- ```vim
+--- :map _x :<C-U>echo "the count is " .. v:count<CR>
+--- ```
+---
+--- Note: The <C-U> is required to remove the line range that you
+--- get when typing ':' after a count.
+--- When there are two counts, as in "3d2w", they are multiplied,
+--- just like what happens in the command, "d6w" for the example.
+--- Also used for evaluating the 'formatexpr' option.
+--- @type integer
+vim.v.count = ...
+
+--- Just like "v:count", but defaults to one when no count is
+--- used.
+--- @type integer
+vim.v.count1 = ...
+
+--- The current locale setting for characters of the runtime
+--- environment. This allows Vim scripts to be aware of the
+--- current locale encoding. Technical: it's the value of
+--- LC_CTYPE. When not using a locale the value is "C".
+--- This variable can not be set directly, use the `:language`
+--- command.
+--- See `multi-lang`.
+--- @type any
+vim.v.ctype = ...
+
+--- Normally zero. When a deadly signal is caught it's set to
+--- one. When multiple signals are caught the number increases.
+--- Can be used in an autocommand to check if Vim didn't
+--- terminate normally.
+--- Example:
+---
+--- ```vim
+--- :au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif
+--- ```
+---
+--- Note: if another deadly signal is caught when v:dying is one,
+--- VimLeave autocommands will not be executed.
+--- @type integer
+vim.v.dying = ...
+
+--- Number of screen cells that can be used for an `:echo` message
+--- in the last screen line before causing the `hit-enter-prompt`.
+--- Depends on 'showcmd', 'ruler' and 'columns'. You need to
+--- check 'cmdheight' for whether there are full-width lines
+--- available above the last line.
+--- @type integer
+vim.v.echospace = ...
+
+--- Last given error message.
+--- Modifiable (can be set).
+--- Example:
+---
+--- ```vim
+--- let v:errmsg = ""
+--- silent! next
+--- if v:errmsg != ""
+--- " ... handle error
+--- ```
+--- @type string
+vim.v.errmsg = ...
+
+--- Errors found by assert functions, such as `assert_true()`.
+--- This is a list of strings.
+--- The assert functions append an item when an assert fails.
+--- The return value indicates this: a one is returned if an item
+--- was added to v:errors, otherwise zero is returned.
+--- To remove old results make it empty:
+---
+--- ```vim
+--- let v:errors = []
+--- ```
+---
+--- If v:errors is set to anything but a list it is made an empty
+--- list by the assert function.
+--- @type string[]
+vim.v.errors = ...
+
+--- Dictionary of event data for the current `autocommand`. Valid
+--- only during the event lifetime; storing or passing v:event is
+--- invalid! Copy it instead:
+---
+--- ```vim
+--- au TextYankPost * let g:foo = deepcopy(v:event)
+--- ```
+---
+--- Keys vary by event; see the documentation for the specific
+--- event, e.g. `DirChanged` or `TextYankPost`.
+--- KEY DESCRIPTION ~
+--- abort Whether the event triggered during
+--- an aborting condition (e.g. `c_Esc` or
+--- `c_CTRL-C` for `CmdlineLeave`).
+--- chan `channel-id`
+--- cmdlevel Level of cmdline.
+--- cmdtype Type of cmdline, `cmdline-char`.
+--- cwd Current working directory.
+--- inclusive Motion is `inclusive`, else exclusive.
+--- scope Event-specific scope name.
+--- operator Current `operator`. Also set for Ex
+--- commands (unlike `v:operator`). For
+--- example if `TextYankPost` is triggered
+--- by the `:yank` Ex command then
+--- `v:event.operator` is "y".
+--- regcontents Text stored in the register as a
+--- `readfile()`-style list of lines.
+--- regname Requested register (e.g "x" for "xyy)
+--- or the empty string for an unnamed
+--- operation.
+--- regtype Type of register as returned by
+--- `getregtype()`.
+--- visual Selection is visual (as opposed to,
+--- e.g., via motion).
+--- completed_item Current selected complete item on
+--- `CompleteChanged`, Is `{}` when no complete
+--- item selected.
+--- height Height of popup menu on `CompleteChanged`
+--- width Width of popup menu on `CompleteChanged`
+--- row Row count of popup menu on `CompleteChanged`,
+--- relative to screen.
+--- col Col count of popup menu on `CompleteChanged`,
+--- relative to screen.
+--- size Total number of completion items on
+--- `CompleteChanged`.
+--- scrollbar Is `v:true` if popup menu have scrollbar, or
+--- `v:false` if not.
+--- changed_window Is `v:true` if the event fired while
+--- changing window (or tab) on `DirChanged`.
+--- status Job status or exit code, -1 means "unknown". `TermClose`
+--- @type any
+vim.v.event = ...
+
+--- The value of the exception most recently caught and not
+--- finished. See also `v:throwpoint` and `throw-variables`.
+--- Example:
+---
+--- ```vim
+--- try
+--- throw "oops"
+--- catch /.*/
+--- echo "caught " .. v:exception
+--- endtry
+--- ```
+---
+--- Output: "caught oops".
+--- @type string
+vim.v.exception = ...
+
+--- Exit code, or `v:null` before invoking the `VimLeavePre`
+--- and `VimLeave` autocmds. See `:q`, `:x` and `:cquit`.
+--- Example:
+---
+--- ```vim
+--- :au VimLeave * echo "Exit value is " .. v:exiting
+--- ```
+--- @type any
+vim.v.exiting = ...
+
+--- Special value used to put "false" in JSON and msgpack. See
+--- `json_encode()`. This value is converted to "v:false" when used
+--- as a String (e.g. in `expr5` with string concatenation
+--- operator) and to zero when used as a Number (e.g. in `expr5`
+--- or `expr7` when used with numeric operators). Read-only.
+--- @type boolean
+vim.v['false'] = ...
+
+--- What should happen after a `FileChangedShell` event was
+--- triggered. Can be used in an autocommand to tell Vim what to
+--- do with the affected buffer:
+--- reload Reload the buffer (does not work if
+--- the file was deleted).
+--- edit Reload the buffer and detect the
+--- values for options such as
+--- 'fileformat', 'fileencoding', 'binary'
+--- (does not work if the file was
+--- deleted).
+--- ask Ask the user what to do, as if there
+--- was no autocommand. Except that when
+--- only the timestamp changed nothing
+--- will happen.
+--- <empty> Nothing, the autocommand should do
+--- everything that needs to be done.
+--- The default is empty. If another (invalid) value is used then
+--- Vim behaves like it is empty, there is no warning message.
+--- @type string
+vim.v.fcs_choice = ...
+
+--- The reason why the `FileChangedShell` event was triggered.
+--- Can be used in an autocommand to decide what to do and/or what
+--- to set v:fcs_choice to. Possible values:
+--- deleted file no longer exists
+--- conflict file contents, mode or timestamp was
+--- changed and buffer is modified
+--- changed file contents has changed
+--- mode mode of file changed
+--- time only file timestamp changed
+--- @type string
+vim.v.fcs_reason = ...
+
+--- When evaluating 'includeexpr': the file name that was
+--- detected. Empty otherwise.
+--- @type string
+vim.v.fname = ...
+
+--- The name of the diff (patch) file. Only valid while
+--- evaluating 'patchexpr'.
+--- @type string
+vim.v.fname_diff = ...
+
+--- The name of the input file. Valid while evaluating:
+--- option used for ~
+--- 'charconvert' file to be converted
+--- 'diffexpr' original file
+--- 'patchexpr' original file
+--- And set to the swap file name for `SwapExists`.
+--- @type string
+vim.v.fname_in = ...
+
+--- The name of the new version of the file. Only valid while
+--- evaluating 'diffexpr'.
+--- @type string
+vim.v.fname_new = ...
+
+--- The name of the output file. Only valid while
+--- evaluating:
+--- option used for ~
+--- 'charconvert' resulting converted file [1]
+--- 'diffexpr' output of diff
+--- 'patchexpr' resulting patched file
+--- [1] When doing conversion for a write command (e.g., ":w
+--- file") it will be equal to v:fname_in. When doing conversion
+--- for a read command (e.g., ":e file") it will be a temporary
+--- file and different from v:fname_in.
+--- @type string
+vim.v.fname_out = ...
+
+--- Used for 'foldtext': dashes representing foldlevel of a closed
+--- fold.
+--- Read-only in the `sandbox`. `fold-foldtext`
+--- @type string
+vim.v.folddashes = ...
+
+--- Used for 'foldtext': last line of closed fold.
+--- Read-only in the `sandbox`. `fold-foldtext`
+--- @type integer
+vim.v.foldend = ...
+
+--- Used for 'foldtext': foldlevel of closed fold.
+--- Read-only in the `sandbox`. `fold-foldtext`
+--- @type integer
+vim.v.foldlevel = ...
+
+--- Used for 'foldtext': first line of closed fold.
+--- Read-only in the `sandbox`. `fold-foldtext`
+--- @type integer
+vim.v.foldstart = ...
+
+--- Variable that indicates whether search highlighting is on.
+--- Setting it makes sense only if 'hlsearch' is enabled. Setting
+--- this variable to zero acts like the `:nohlsearch` command,
+--- setting it to one acts like
+---
+--- ```vim
+--- let &hlsearch = &hlsearch
+--- ```
+---
+--- Note that the value is restored when returning from a
+--- function. `function-search-undo`.
+--- @type integer
+vim.v.hlsearch = ...
+
+--- Used for the `InsertEnter` and `InsertChange` autocommand
+--- events. Values:
+--- i Insert mode
+--- r Replace mode
+--- v Virtual Replace mode
+--- @type string
+vim.v.insertmode = ...
+
+--- Key of the current item of a `Dictionary`. Only valid while
+--- evaluating the expression used with `map()` and `filter()`.
+--- Read-only.
+--- @type string
+vim.v.key = ...
+
+--- The current locale setting for messages of the runtime
+--- environment. This allows Vim scripts to be aware of the
+--- current language. Technical: it's the value of LC_MESSAGES.
+--- The value is system dependent.
+--- This variable can not be set directly, use the `:language`
+--- command.
+--- It can be different from `v:ctype` when messages are desired
+--- in a different language than what is used for character
+--- encoding. See `multi-lang`.
+--- @type string
+vim.v.lang = ...
+
+--- The current locale setting for time messages of the runtime
+--- environment. This allows Vim scripts to be aware of the
+--- current language. Technical: it's the value of LC_TIME.
+--- This variable can not be set directly, use the `:language`
+--- command. See `multi-lang`.
+--- @type string
+vim.v.lc_time = ...
+
+--- Line number for the 'foldexpr' `fold-expr`, 'formatexpr',
+--- 'indentexpr' and 'statuscolumn' expressions, tab page number
+--- for 'guitablabel' and 'guitabtooltip'. Only valid while one of
+--- these expressions is being evaluated. Read-only when in the
+--- `sandbox`.
+--- @type integer
+vim.v.lnum = ...
+
+--- Prefix for calling Lua functions from expressions.
+--- See `v:lua-call` for more information.
+--- @type any
+vim.v.lua = ...
+
+--- Maximum line length. Depending on where it is used it can be
+--- screen columns, characters or bytes. The value currently is
+--- 2147483647 on all systems.
+--- @type integer
+vim.v.maxcol = ...
+
+--- Column number for a mouse click obtained with `getchar()`.
+--- This is the screen column number, like with `virtcol()`. The
+--- value is zero when there was no mouse button click.
+--- @type integer
+vim.v.mouse_col = ...
+
+--- Line number for a mouse click obtained with `getchar()`.
+--- This is the text line number, not the screen line number. The
+--- value is zero when there was no mouse button click.
+--- @type integer
+vim.v.mouse_lnum = ...
+
+--- Window number for a mouse click obtained with `getchar()`.
+--- First window has number 1, like with `winnr()`. The value is
+--- zero when there was no mouse button click.
+--- @type integer
+vim.v.mouse_win = ...
+
+--- `window-ID` for a mouse click obtained with `getchar()`.
+--- The value is zero when there was no mouse button click.
+--- @type integer
+vim.v.mouse_winid = ...
+
+--- Dictionary containing msgpack types used by `msgpackparse()`
+--- and `msgpackdump()`. All types inside dictionary are fixed
+--- (not editable) empty lists. To check whether some list is one
+--- of msgpack types, use `is` operator.
+--- @type any
+vim.v.msgpack_types = ...
+
+--- Special value used to put "null" in JSON and NIL in msgpack.
+--- See `json_encode()`. This value is converted to "v:null" when
+--- used as a String (e.g. in `expr5` with string concatenation
+--- operator) and to zero when used as a Number (e.g. in `expr5`
+--- or `expr7` when used with numeric operators). Read-only.
+--- In some places `v:null` can be used for a List, Dict, etc.
+--- that is not set. That is slightly different than an empty
+--- List, Dict, etc.
+--- @type vim.NIL
+vim.v.null = ...
+
+--- Maximum value of a number.
+--- @type integer
+vim.v.numbermax = ...
+
+--- Minimum value of a number (negative).
+--- @type integer
+vim.v.numbermin = ...
+
+--- Number of bits in a Number. This is normally 64, but on some
+--- systems it may be 32.
+--- @type integer
+vim.v.numbersize = ...
+
+--- List of file names that is loaded from the `shada` file on
+--- startup. These are the files that Vim remembers marks for.
+--- The length of the List is limited by the ' argument of the
+--- 'shada' option (default is 100).
+--- When the `shada` file is not used the List is empty.
+--- Also see `:oldfiles` and `c_#<`.
+--- The List can be modified, but this has no effect on what is
+--- stored in the `shada` file later. If you use values other
+--- than String this will cause trouble.
+--- @type string[]
+vim.v.oldfiles = ...
+
+--- The last operator given in Normal mode. This is a single
+--- character except for commands starting with <g> or <z>,
+--- in which case it is two characters. Best used alongside
+--- `v:prevcount` and `v:register`. Useful if you want to cancel
+--- Operator-pending mode and then use the operator, e.g.:
+---
+--- ```vim
+--- :omap O <Esc>:call MyMotion(v:operator)<CR>
+--- ```
+---
+--- The value remains set until another operator is entered, thus
+--- don't expect it to be empty.
+--- v:operator is not set for `:delete`, `:yank` or other Ex
+--- commands.
+--- Read-only.
+--- @type string
+vim.v.operator = ...
+
+--- Command used to set the option. Valid while executing an
+--- `OptionSet` autocommand.
+--- value option was set via ~
+--- "setlocal" `:setlocal` or `:let l:xxx`
+--- "setglobal" `:setglobal` or `:let g:xxx`
+--- "set" `:set` or `:let`
+--- "modeline" `modeline`
+--- @type string
+vim.v.option_command = ...
+
+--- New value of the option. Valid while executing an `OptionSet`
+--- autocommand.
+--- @type any
+vim.v.option_new = ...
+
+--- Old value of the option. Valid while executing an `OptionSet`
+--- autocommand. Depending on the command used for setting and the
+--- kind of option this is either the local old value or the
+--- global old value.
+--- @type any
+vim.v.option_old = ...
+
+--- Old global value of the option. Valid while executing an
+--- `OptionSet` autocommand.
+--- @type any
+vim.v.option_oldglobal = ...
+
+--- Old local value of the option. Valid while executing an
+--- `OptionSet` autocommand.
+--- @type any
+vim.v.option_oldlocal = ...
+
+--- Scope of the set command. Valid while executing an
+--- `OptionSet` autocommand. Can be either "global" or "local"
+--- @type string
+vim.v.option_type = ...
+
+--- The count given for the last but one Normal mode command.
+--- This is the v:count value of the previous command. Useful if
+--- you want to cancel Visual or Operator-pending mode and then
+--- use the count, e.g.:
+---
+--- ```vim
+--- :vmap % <Esc>:call MyFilter(v:prevcount)<CR>
+--- ```
+---
+--- Read-only.
+--- @type integer
+vim.v.prevcount = ...
+
+--- Normally zero. Set to one after using ":profile start".
+--- See `profiling`.
+--- @type integer
+vim.v.profiling = ...
+
+--- The name by which Nvim was invoked (with path removed).
+--- Read-only.
+--- @type string
+vim.v.progname = ...
+
+--- Absolute path to the current running Nvim.
+--- Read-only.
+--- @type string
+vim.v.progpath = ...
+
+--- The name of the register in effect for the current normal mode
+--- command (regardless of whether that command actually used a
+--- register). Or for the currently executing normal mode mapping
+--- (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 '+'.
+--- Also see `getreg()` and `setreg()`
+--- @type string
+vim.v.register = ...
+
+--- Relative line number for the 'statuscolumn' expression.
+--- Read-only.
+--- @type integer
+vim.v.relnum = ...
+
+--- String describing the script or function that caused the
+--- screen to scroll up. It's only set when it is empty, thus the
+--- first reason is remembered. It is set to "Unknown" for a
+--- typed command.
+--- This can be used to find out why your script causes the
+--- hit-enter prompt.
+--- @type any
+vim.v.scrollstart = ...
+
+--- Search direction: 1 after a forward search, 0 after a
+--- backward search. It is reset to forward when directly setting
+--- the last search pattern, see `quote/`.
+--- Note that the value is restored when returning from a
+--- function. `function-search-undo`.
+--- Read-write.
+--- @type integer
+vim.v.searchforward = ...
+
+--- Primary listen-address of Nvim, the first item returned by
+--- `serverlist()`. Usually this is the named pipe created by Nvim
+--- at `startup` or given by `--listen` (or the deprecated
+--- `$NVIM_LISTEN_ADDRESS` env var).
+---
+--- See also `serverstart()` `serverstop()`.
+--- Read-only.
+---
+--- *$NVIM*
+--- $NVIM is set by `terminal` and `jobstart()`, and is thus
+--- a hint that the current environment is a subprocess of Nvim.
+--- Example:
+---
+--- ```vim
+--- if $NVIM
+--- echo nvim_get_chan_info(v:parent)
+--- endif
+--- ```
+---
+--- Note the contents of $NVIM may change in the future.
+--- @type string
+vim.v.servername = ...
+
+--- Result of the last shell command. When non-zero, the last
+--- shell command had an error. When zero, there was no problem.
+--- This only works when the shell returns the error code to Vim.
+--- The value -1 is often used when the command could not be
+--- executed. Read-only.
+--- Example:
+---
+--- ```vim
+--- !mv foo bar
+--- if v:shell_error
+--- echo 'could not rename "foo" to "bar"!'
+--- endif
+--- ```
+--- @type integer
+vim.v.shell_error = ...
+
+--- Last given status message.
+--- Modifiable (can be set).
+--- @type string
+vim.v.statusmsg = ...
+
+--- `channel-id` corresponding to stderr. The value is always 2;
+--- use this variable to make your code more descriptive.
+--- Unlike stdin and stdout (see `stdioopen()`), stderr is always
+--- open for writing. Example:
+---
+--- ```vim
+--- :call chansend(v:stderr, "error: toaster empty\n")
+--- ```
+--- @type integer
+vim.v.stderr = ...
+
+--- `SwapExists` autocommands can set this to the selected choice
+--- for handling an existing swapfile:
+--- 'o' Open read-only
+--- 'e' Edit anyway
+--- 'r' Recover
+--- 'd' Delete swapfile
+--- 'q' Quit
+--- 'a' Abort
+--- The value should be a single-character string. An empty value
+--- results in the user being asked, as would happen when there is
+--- no SwapExists autocommand. The default is empty.
+--- @type string
+vim.v.swapchoice = ...
+
+--- Normal mode command to be executed after a file has been
+--- opened. Can be used for a `SwapExists` autocommand to have
+--- another Vim open the file and jump to the right place. For
+--- example, when jumping to a tag the value is ":tag tagname\r".
+--- For ":edit +cmd file" the value is ":cmd\r".
+--- @type string
+vim.v.swapcommand = ...
+
+--- Name of the swapfile found.
+--- Only valid during `SwapExists` event.
+--- Read-only.
+--- @type string
+vim.v.swapname = ...
+
+--- Value of `Blob` type. Read-only. See: `type()`
+--- @type integer
+vim.v.t_blob = ...
+
+--- Value of `Boolean` type. Read-only. See: `type()`
+--- @type integer
+vim.v.t_bool = ...
+
+--- Value of `Dictionary` type. Read-only. See: `type()`
+--- @type integer
+vim.v.t_dict = ...
+
+--- Value of `Float` type. Read-only. See: `type()`
+--- @type integer
+vim.v.t_float = ...
+
+--- Value of `Funcref` type. Read-only. See: `type()`
+--- @type integer
+vim.v.t_func = ...
+
+--- Value of `List` type. Read-only. See: `type()`
+--- @type integer
+vim.v.t_list = ...
+
+--- Value of `Number` type. Read-only. See: `type()`
+--- @type integer
+vim.v.t_number = ...
+
+--- Value of `String` type. Read-only. See: `type()`
+--- @type integer
+vim.v.t_string = ...
+
+--- The value of the most recent OSC or DCS control sequence
+--- sent from a process running in the embedded `terminal`.
+--- This can be read in a `TermRequest` event handler to respond
+--- to queries from embedded applications.
+--- @type string
+vim.v.termrequest = ...
+
+--- The value of the most recent OSC or DCS control sequence
+--- received by Nvim from the terminal. This can be read in a
+--- `TermResponse` event handler after querying the terminal using
+--- another escape sequence.
+--- @type string
+vim.v.termresponse = ...
+
+--- Must be set before using `test_garbagecollect_now()`.
+--- @type any
+vim.v.testing = ...
+
+--- Full filename of the last loaded or saved session file.
+--- Empty when no session file has been saved. See `:mksession`.
+--- Modifiable (can be set).
+--- @type any
+vim.v.this_session = ...
+
+--- The point where the exception most recently caught and not
+--- finished was thrown. Not set when commands are typed. See
+--- also `v:exception` and `throw-variables`.
+--- Example:
+---
+--- ```vim
+--- try
+--- throw "oops"
+--- catch /.*/
+--- echo "Exception from" v:throwpoint
+--- endtry
+--- ```
+---
+--- Output: "Exception from test.vim, line 2"
+--- @type any
+vim.v.throwpoint = ...
+
+--- Special value used to put "true" in JSON and msgpack. See
+--- `json_encode()`. This value is converted to "v:true" when used
+--- as a String (e.g. in `expr5` with string concatenation
+--- operator) and to one when used as a Number (e.g. in `expr5` or
+--- `expr7` when used with numeric operators). Read-only.
+--- @type boolean
+vim.v['true'] = ...
+
+--- Value of the current item of a `List` or `Dictionary`. Only
+--- valid while evaluating the expression used with `map()` and
+--- `filter()`. Read-only.
+--- @type any
+vim.v.val = ...
+
+--- Vim version number: major version times 100 plus minor
+--- version. Vim 5.0 is 500, Vim 5.1 is 501.
+--- Read-only.
+--- Use `has()` to check the Nvim (not Vim) version:
+---
+--- ```vim
+--- :if has("nvim-0.2.1")
+--- ```
+--- @type integer
+vim.v.version = ...
+
+--- 0 during startup, 1 just before `VimEnter`.
+--- Read-only.
+--- @type integer
+vim.v.vim_did_enter = ...
+
+--- Virtual line number for the 'statuscolumn' expression.
+--- Negative when drawing the status column for virtual lines, zero
+--- when drawing an actual buffer line, and positive when drawing
+--- the wrapped part of a buffer line.
+--- Read-only.
+--- @type integer
+vim.v.virtnum = ...
+
+--- Last given warning message.
+--- Modifiable (can be set).
+--- @type string
+vim.v.warningmsg = ...
+
+--- Application-specific window "handle" which may be set by any
+--- attached UI. Defaults to zero.
+--- Note: For Nvim `windows` use `winnr()` or `win_getid()`, see
+--- `window-ID`.
+--- @type integer
+vim.v.windowid = ...
diff --git a/runtime/lua/vim/_options.lua b/runtime/lua/vim/_options.lua
index b83a8dd4b1..13ad6cc58f 100644
--- a/runtime/lua/vim/_options.lua
+++ b/runtime/lua/vim/_options.lua
@@ -1,12 +1,10 @@
----@defgroup lua-vimscript
+--- @brief Nvim Lua provides an interface or "bridge" to Vimscript variables and
+--- functions, and editor commands and options.
---
----@brief Nvim Lua provides an interface or "bridge" to Vimscript variables and
----functions, and editor commands and options.
----
----Objects passed over this bridge are COPIED (marshalled): there are no
----"references". |lua-guide-variables| For example, using \`vim.fn.remove()\` on
----a Lua list copies the list object to Vimscript and does NOT modify the Lua
----list:
+--- Objects passed over this bridge are COPIED (marshalled): there are no
+--- "references". |lua-guide-variables| For example, using `vim.fn.remove()` on
+--- a Lua list copies the list object to Vimscript and does NOT modify the Lua
+--- list:
---
--- ```lua
--- local list = { 1, 2, 3 }
@@ -14,86 +12,85 @@
--- vim.print(list) --> "{ 1, 2, 3 }"
--- ```
----@addtogroup lua-vimscript
----@brief <pre>help
----vim.call({func}, {...}) *vim.call()*
---- Invokes |vim-function| or |user-function| {func} with arguments {...}.
---- See also |vim.fn|.
---- Equivalent to: >lua
---- vim.fn[func]({...})
----<
----vim.cmd({command})
---- See |vim.cmd()|.
----
----vim.fn.{func}({...}) *vim.fn*
---- Invokes |vim-function| or |user-function| {func} with arguments {...}.
---- To call autoload functions, use the syntax: >lua
---- vim.fn['some\#function']({...})
----<
---- Unlike vim.api.|nvim_call_function()| this converts directly between Vim
---- objects and Lua objects. If the Vim function returns a float, it will be
---- represented directly as a Lua number. Empty lists and dictionaries both
---- are represented by an empty table.
----
---- Note: |v:null| values as part of the return value is represented as
---- |vim.NIL| special value
----
---- Note: vim.fn keys are generated lazily, thus `pairs(vim.fn)` only
---- enumerates functions that were called at least once.
----
---- Note: The majority of functions cannot run in |api-fast| callbacks with some
---- undocumented exceptions which are allowed.
----
---- *lua-vim-variables*
----The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
----from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables
----described below. In this way you can easily read and modify global Vimscript
----variables from Lua.
----
----Example: >lua
----
---- vim.g.foo = 5 -- Set the g:foo Vimscript variable.
---- print(vim.g.foo) -- Get and print the g:foo Vimscript variable.
---- vim.g.foo = nil -- Delete (:unlet) the Vimscript variable.
---- vim.b[2].foo = 6 -- Set b:foo for buffer 2
----<
----
----Note that setting dictionary fields directly will not write them back into
----Nvim. This is because the index into the namespace simply returns a copy.
----Instead the whole dictionary must be written as one. This can be achieved by
----creating a short-lived temporary.
----
----Example: >lua
----
---- vim.g.my_dict.field1 = 'value' -- Does not work
----
---- local my_dict = vim.g.my_dict --
---- my_dict.field1 = 'value' -- Instead do
---- vim.g.my_dict = my_dict --
----
----vim.g *vim.g*
---- Global (|g:|) editor variables.
---- Key with no value returns `nil`.
----
----vim.b *vim.b*
---- Buffer-scoped (|b:|) variables for the current buffer.
---- Invalid or unset key returns `nil`. Can be indexed with
---- an integer to access variables for a specific buffer.
----
----vim.w *vim.w*
---- Window-scoped (|w:|) variables for the current window.
---- Invalid or unset key returns `nil`. Can be indexed with
---- an integer to access variables for a specific window.
----
----vim.t *vim.t*
---- Tabpage-scoped (|t:|) variables for the current tabpage.
---- Invalid or unset key returns `nil`. Can be indexed with
---- an integer to access variables for a specific tabpage.
----
----vim.v *vim.v*
---- |v:| variables.
---- Invalid or unset key returns `nil`.
----</pre>
+--- @brief <pre>help
+--- vim.call({func}, {...}) *vim.call()*
+--- Invokes |vim-function| or |user-function| {func} with arguments {...}.
+--- See also |vim.fn|.
+--- Equivalent to: >lua
+--- vim.fn[func]({...})
+--- <
+--- vim.cmd({command})
+--- See |vim.cmd()|.
+---
+--- vim.fn.{func}({...}) *vim.fn*
+--- Invokes |vim-function| or |user-function| {func} with arguments {...}.
+--- To call autoload functions, use the syntax: >lua
+--- vim.fn['some#function']({...})
+--- <
+--- Unlike vim.api.|nvim_call_function()| this converts directly between Vim
+--- objects and Lua objects. If the Vim function returns a float, it will be
+--- represented directly as a Lua number. Empty lists and dictionaries both
+--- are represented by an empty table.
+---
+--- Note: |v:null| values as part of the return value is represented as
+--- |vim.NIL| special value
+---
+--- Note: vim.fn keys are generated lazily, thus `pairs(vim.fn)` only
+--- enumerates functions that were called at least once.
+---
+--- Note: The majority of functions cannot run in |api-fast| callbacks with some
+--- undocumented exceptions which are allowed.
+---
+--- *lua-vim-variables*
+--- The Vim editor global dictionaries |g:| |w:| |b:| |t:| |v:| can be accessed
+--- from Lua conveniently and idiomatically by referencing the `vim.*` Lua tables
+--- described below. In this way you can easily read and modify global Vimscript
+--- variables from Lua.
+---
+--- Example: >lua
+---
+--- vim.g.foo = 5 -- Set the g:foo Vimscript variable.
+--- print(vim.g.foo) -- Get and print the g:foo Vimscript variable.
+--- vim.g.foo = nil -- Delete (:unlet) the Vimscript variable.
+--- vim.b[2].foo = 6 -- Set b:foo for buffer 2
+--- <
+---
+--- Note that setting dictionary fields directly will not write them back into
+--- Nvim. This is because the index into the namespace simply returns a copy.
+--- Instead the whole dictionary must be written as one. This can be achieved by
+--- creating a short-lived temporary.
+---
+--- Example: >lua
+---
+--- vim.g.my_dict.field1 = 'value' -- Does not work
+---
+--- local my_dict = vim.g.my_dict --
+--- my_dict.field1 = 'value' -- Instead do
+--- vim.g.my_dict = my_dict --
+---
+--- vim.g *vim.g*
+--- Global (|g:|) editor variables.
+--- Key with no value returns `nil`.
+---
+--- vim.b *vim.b*
+--- Buffer-scoped (|b:|) variables for the current buffer.
+--- Invalid or unset key returns `nil`. Can be indexed with
+--- an integer to access variables for a specific buffer.
+---
+--- vim.w *vim.w*
+--- Window-scoped (|w:|) variables for the current window.
+--- Invalid or unset key returns `nil`. Can be indexed with
+--- an integer to access variables for a specific window.
+---
+--- vim.t *vim.t*
+--- Tabpage-scoped (|t:|) variables for the current tabpage.
+--- Invalid or unset key returns `nil`. Can be indexed with
+--- an integer to access variables for a specific tabpage.
+---
+--- vim.v *vim.v*
+--- |v:| variables.
+--- Invalid or unset key returns `nil`.
+--- </pre>
local api = vim.api
@@ -108,6 +105,10 @@ local key_value_options = {
winhl = true,
}
+--- @nodoc
+--- @class vim._option.Info : vim.api.keyset.get_option_info
+--- @field metatype 'boolean'|'string'|'number'|'map'|'array'|'set'
+
--- Convert a vimoption_T style dictionary to the correct OptionType associated with it.
---@return string
local function get_option_metatype(name, info)
@@ -126,8 +127,10 @@ local function get_option_metatype(name, info)
end
--- @param name string
+--- @return vim._option.Info
local function get_options_info(name)
local info = api.nvim_get_option_info2(name, {})
+ --- @cast info vim._option.Info
info.metatype = get_option_metatype(name, info)
return info
end
@@ -142,8 +145,6 @@ end
--- vim.env.FOO = 'bar'
--- print(vim.env.TERM)
--- ```
----
----@param var string
vim.env = setmetatable({}, {
__index = function(_, k)
local v = vim.fn.getenv(k)
@@ -205,31 +206,30 @@ local function new_win_opt_accessor(winid, bufnr)
})
end
----@addtogroup lua-vimscript
----@brief <pre>help
----` ` *lua-options*
---- *lua-vim-options*
---- *lua-vim-set*
---- *lua-vim-setlocal*
+--- @brief <pre>help
+--- *lua-options*
+--- *lua-vim-options*
+--- *lua-vim-set*
+--- *lua-vim-setlocal*
---
----Vim options can be accessed through |vim.o|, which behaves like Vimscript
----|:set|.
+--- Vim options can be accessed through |vim.o|, which behaves like Vimscript
+--- |:set|.
---
---- Examples: ~
+--- Examples: ~
---
---- To set a boolean toggle:
---- Vimscript: `set number`
---- Lua: `vim.o.number = true`
+--- To set a boolean toggle:
+--- Vimscript: `set number`
+--- Lua: `vim.o.number = true`
---
---- To set a string value:
---- Vimscript: `set wildignore=*.o,*.a,__pycache__`
---- Lua: `vim.o.wildignore = '*.o,*.a,__pycache__'`
+--- To set a string value:
+--- Vimscript: `set wildignore=*.o,*.a,__pycache__`
+--- Lua: `vim.o.wildignore = '*.o,*.a,__pycache__'`
---
----Similarly, there is |vim.bo| and |vim.wo| for setting buffer-scoped and
----window-scoped options. Note that this must NOT be confused with
----|local-options| and |:setlocal|. There is also |vim.go| that only accesses the
----global value of a |global-local| option, see |:setglobal|.
----</pre>
+--- Similarly, there is |vim.bo| and |vim.wo| for setting buffer-scoped and
+--- window-scoped options. Note that this must NOT be confused with
+--- |local-options| and |:setlocal|. There is also |vim.go| that only accesses the
+--- global value of a |global-local| option, see |:setglobal|.
+--- </pre>
--- Get or set |options|. Like `:set`. Invalid key is an error.
---
@@ -276,10 +276,10 @@ vim.go = setmetatable({}, {
})
--- Get or set buffer-scoped |options| for the buffer with number {bufnr}.
---- Like `:set` and `:setlocal`. If [{bufnr}] is omitted then the current
---- buffer is used. Invalid {bufnr} or key is an error.
+--- If {bufnr} is omitted then the current buffer is used.
+--- Invalid {bufnr} or key is an error.
---
---- Note: this is equivalent to both `:set` and `:setlocal`.
+--- Note: this is equivalent to `:setlocal` for |global-local| options and `:set` otherwise.
---
--- Example:
---
@@ -292,9 +292,9 @@ vim.go = setmetatable({}, {
vim.bo = new_buf_opt_accessor()
--- Get or set window-scoped |options| for the window with handle {winid} and
---- buffer with number {bufnr}. Like `:setlocal` if {bufnr} is provided, like
---- `:set` otherwise. If [{winid}] is omitted then the current window is
---- used. Invalid {winid}, {bufnr} or key is an error.
+--- buffer with number {bufnr}. Like `:setlocal` if setting a |global-local| option
+--- or if {bufnr} is provided, like `:set` otherwise. If {winid} is omitted then
+--- the current window is used. Invalid {winid}, {bufnr} or key is an error.
---
--- Note: only {bufnr} with value `0` (the current buffer in the window) is
--- supported.
@@ -310,18 +310,21 @@ vim.bo = new_buf_opt_accessor()
--- ```
vim.wo = new_win_opt_accessor()
----@brief [[
--- vim.opt, vim.opt_local and vim.opt_global implementation
---
--- To be used as helpers for working with options within neovim.
--- For information on how to use, see :help vim.opt
----
----@brief ]]
--- Preserves the order and does not mutate the original list
+--- @generic T
+--- @param t T[]
+--- @return T[]
local function remove_duplicate_values(t)
+ --- @type table, table<any,true>
local result, seen = {}, {}
- for _, v in ipairs(t) do
+ for _, v in
+ ipairs(t --[[@as any[] ]])
+ do
if not seen[v] then
table.insert(result, v)
end
@@ -332,8 +335,11 @@ local function remove_duplicate_values(t)
return result
end
--- Check whether the OptionTypes is allowed for vim.opt
--- If it does not match, throw an error which indicates which option causes the error.
+--- Check whether the OptionTypes is allowed for vim.opt
+--- If it does not match, throw an error which indicates which option causes the error.
+--- @param name any
+--- @param value any
+--- @param types string[]
local function assert_valid_value(name, value, types)
local type_of_value = type(value)
for _, valid_type in ipairs(types) do
@@ -360,6 +366,8 @@ local function tbl_merge(left, right)
return vim.tbl_extend('force', left, right)
end
+--- @param t table<any,any>
+--- @param value any|any[]
local function tbl_remove(t, value)
if type(value) == 'string' then
t[value] = nil
@@ -388,6 +396,8 @@ local to_vim_value = {
number = passthrough,
string = passthrough,
+ --- @param info vim._option.Info
+ --- @param value string|table<string,true>
set = function(info, value)
if type(value) == 'string' then
return value
@@ -415,6 +425,8 @@ local to_vim_value = {
end
end,
+ --- @param info vim._option.Info
+ --- @param value string|string[]
array = function(info, value)
if type(value) == 'string' then
return value
@@ -425,6 +437,7 @@ local to_vim_value = {
return table.concat(value, ',')
end,
+ --- @param value string|table<string,string>
map = function(_, value)
if type(value) == 'string' then
return value
@@ -474,7 +487,8 @@ local to_lua_value = {
end
-- Handles unescaped commas in a list.
- if string.find(value, ',,,') then
+ if value:find(',,,') then
+ --- @type string, string
local left, right = unpack(vim.split(value, ',,,'))
local result = {}
@@ -487,8 +501,9 @@ local to_lua_value = {
return result
end
- if string.find(value, ',^,,', 1, true) then
- local left, right = unpack(vim.split(value, ',^,,', true))
+ if value:find(',^,,', 1, true) then
+ --- @type string, string
+ local left, right = unpack(vim.split(value, ',^,,', { plain = true }))
local result = {}
vim.list_extend(result, vim.split(left, ','))
@@ -516,22 +531,20 @@ local to_lua_value = {
assert(info.flaglist, 'That is the only one I know how to handle')
+ local result = {} --- @type table<string,true>
+
if info.flaglist and info.commalist then
local split_value = vim.split(value, ',')
- local result = {}
for _, v in ipairs(split_value) do
result[v] = true
end
-
- return result
else
- local result = {}
for i = 1, #value do
result[value:sub(i, i)] = true
end
-
- return result
end
+
+ return result
end,
map = function(info, raw_value)
@@ -541,10 +554,11 @@ local to_lua_value = {
assert(info.commalist, 'Only commas are supported currently')
- local result = {}
+ local result = {} --- @type table<string,string>
local comma_split = vim.split(raw_value, ',')
for _, key_value_str in ipairs(comma_split) do
+ --- @type string, string
local key, value = unpack(vim.split(key_value_str, ':'))
key = vim.trim(key)
@@ -590,14 +604,21 @@ local function prepend_value(info, current, new)
end
local add_methods = {
+ --- @param left integer
+ --- @param right integer
number = function(left, right)
return left + right
end,
+ --- @param left string
+ --- @param right string
string = function(left, right)
return left .. right
end,
+ --- @param left string[]
+ --- @param right string[]
+ --- @return string[]
array = function(left, right)
for _, v in ipairs(right) do
table.insert(left, v)
@@ -618,6 +639,8 @@ local function add_value(info, current, new)
)
end
+--- @param t table<any,any>
+--- @param val any
local function remove_one_item(t, val)
if vim.tbl_islist(t) then
local remove_index = nil
@@ -636,6 +659,8 @@ local function remove_one_item(t, val)
end
local remove_methods = {
+ --- @param left integer
+ --- @param right integer
number = function(left, right)
return left - right
end,
@@ -644,6 +669,9 @@ local remove_methods = {
error('Subtraction not supported for strings.')
end,
+ --- @param left string[]
+ --- @param right string[]
+ --- @return string[]
array = function(left, right)
if type(right) == 'string' then
remove_one_item(left, right)
@@ -739,74 +767,74 @@ local function create_option_accessor(scope)
})
end
----@addtogroup lua-vimscript
----@brief <pre>help
----` ` *vim.opt_local*
---- *vim.opt_global*
---- *vim.opt*
----
----
----A special interface |vim.opt| exists for conveniently interacting with list-
----and map-style option from Lua: It allows accessing them as Lua tables and
----offers object-oriented method for adding and removing entries.
----
---- Examples: ~
----
---- The following methods of setting a list-style option are equivalent:
---- In Vimscript: >vim
---- set wildignore=*.o,*.a,__pycache__
----<
---- In Lua using `vim.o`: >lua
---- vim.o.wildignore = '*.o,*.a,__pycache__'
----<
---- In Lua using `vim.opt`: >lua
---- vim.opt.wildignore = { '*.o', '*.a', '__pycache__' }
----<
---- To replicate the behavior of |:set+=|, use: >lua
----
---- vim.opt.wildignore:append { "*.pyc", "node_modules" }
----<
---- To replicate the behavior of |:set^=|, use: >lua
----
---- vim.opt.wildignore:prepend { "new_first_value" }
----<
---- To replicate the behavior of |:set-=|, use: >lua
----
---- vim.opt.wildignore:remove { "node_modules" }
----<
---- The following methods of setting a map-style option are equivalent:
---- In Vimscript: >vim
---- set listchars=space:_,tab:>~
----<
---- In Lua using `vim.o`: >lua
---- vim.o.listchars = 'space:_,tab:>~'
----<
---- In Lua using `vim.opt`: >lua
---- vim.opt.listchars = { space = '_', tab = '>~' }
----<
----
----Note that |vim.opt| returns an `Option` object, not the value of the option,
----which is accessed through |vim.opt:get()|:
----
---- Examples: ~
----
---- The following methods of getting a list-style option are equivalent:
---- In Vimscript: >vim
---- echo wildignore
----<
---- In Lua using `vim.o`: >lua
---- print(vim.o.wildignore)
----<
---- In Lua using `vim.opt`: >lua
---- vim.print(vim.opt.wildignore:get())
----<
----
----In any of the above examples, to replicate the behavior |:setlocal|, use
----`vim.opt_local`. Additionally, to replicate the behavior of |:setglobal|, use
----`vim.opt_global`.
----</pre>
-
---- @diagnostic disable-next-line:unused-local used for gen_vimdoc
+--- @brief <pre>help
+--- *vim.opt_local*
+--- *vim.opt_global*
+--- *vim.opt*
+---
+---
+--- A special interface |vim.opt| exists for conveniently interacting with list-
+--- and map-style option from Lua: It allows accessing them as Lua tables and
+--- offers object-oriented method for adding and removing entries.
+---
+--- Examples: ~
+---
+--- The following methods of setting a list-style option are equivalent:
+--- In Vimscript: >vim
+--- set wildignore=*.o,*.a,__pycache__
+--- <
+--- In Lua using `vim.o`: >lua
+--- vim.o.wildignore = '*.o,*.a,__pycache__'
+--- <
+--- In Lua using `vim.opt`: >lua
+--- vim.opt.wildignore = { '*.o', '*.a', '__pycache__' }
+--- <
+--- To replicate the behavior of |:set+=|, use: >lua
+---
+--- vim.opt.wildignore:append { "*.pyc", "node_modules" }
+--- <
+--- To replicate the behavior of |:set^=|, use: >lua
+---
+--- vim.opt.wildignore:prepend { "new_first_value" }
+--- <
+--- To replicate the behavior of |:set-=|, use: >lua
+---
+--- vim.opt.wildignore:remove { "node_modules" }
+--- <
+--- The following methods of setting a map-style option are equivalent:
+--- In Vimscript: >vim
+--- set listchars=space:_,tab:>~
+--- <
+--- In Lua using `vim.o`: >lua
+--- vim.o.listchars = 'space:_,tab:>~'
+--- <
+--- In Lua using `vim.opt`: >lua
+--- vim.opt.listchars = { space = '_', tab = '>~' }
+--- <
+---
+--- Note that |vim.opt| returns an `Option` object, not the value of the option,
+--- which is accessed through |vim.opt:get()|:
+---
+--- Examples: ~
+---
+--- The following methods of getting a list-style option are equivalent:
+--- In Vimscript: >vim
+--- echo wildignore
+--- <
+--- In Lua using `vim.o`: >lua
+--- print(vim.o.wildignore)
+--- <
+--- In Lua using `vim.opt`: >lua
+--- vim.print(vim.opt.wildignore:get())
+--- <
+---
+--- In any of the above examples, to replicate the behavior |:setlocal|, use
+--- `vim.opt_local`. Additionally, to replicate the behavior of |:setglobal|, use
+--- `vim.opt_global`.
+--- </pre>
+
+--- @nodoc
+--- @class vim.Option
local Option = {} -- luacheck: no unused
--- Returns a Lua-representation of the option. Boolean, number and string
@@ -856,9 +884,7 @@ local Option = {} -- luacheck: no unused
--- print("J is enabled!")
--- end
--- ```
----
---@return string|integer|boolean|nil value of option
----@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:get() end
--- Append a value to string-style options. See |:set+=|
@@ -869,7 +895,6 @@ function Option:get() end
--- vim.opt.formatoptions:append('j')
--- vim.opt.formatoptions = vim.opt.formatoptions + 'j'
--- ```
----
---@param value string Value to append
---@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:append(value) end -- luacheck: no unused
@@ -882,7 +907,6 @@ function Option:append(value) end -- luacheck: no unused
--- vim.opt.wildignore:prepend('*.o')
--- vim.opt.wildignore = vim.opt.wildignore ^ '*.o'
--- ```
----
---@param value string Value to prepend
---@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:prepend(value) end -- luacheck: no unused
@@ -895,7 +919,6 @@ function Option:prepend(value) end -- luacheck: no unused
--- vim.opt.wildignore:remove('*.pyc')
--- vim.opt.wildignore = vim.opt.wildignore - '*.pyc'
--- ```
----
---@param value string Value to remove
---@diagnostic disable-next-line:unused-local used for gen_vimdoc
function Option:remove(value) end -- luacheck: no unused
diff --git a/runtime/lua/vim/_system.lua b/runtime/lua/vim/_system.lua
index 9279febddf..e97a5fc6c3 100644
--- a/runtime/lua/vim/_system.lua
+++ b/runtime/lua/vim/_system.lua
@@ -1,6 +1,6 @@
local uv = vim.uv
---- @class SystemOpts
+--- @class vim.SystemOpts
--- @field stdin? string|string[]|true
--- @field stdout? fun(err:string?, data: string?)|false
--- @field stderr? fun(err:string?, data: string?)|false
@@ -61,7 +61,7 @@ end
--- @field wait fun(self: vim.SystemObj, timeout?: integer): vim.SystemCompleted
--- @field kill fun(self: vim.SystemObj, signal: integer|string)
--- @field write fun(self: vim.SystemObj, data?: string|string[])
---- @field is_closing fun(self: vim.SystemObj): boolean?
+--- @field is_closing fun(self: vim.SystemObj): boolean
local SystemObj = {}
--- @param state vim.SystemState
@@ -94,14 +94,14 @@ function SystemObj:wait(timeout)
local done = vim.wait(timeout or state.timeout or MAX_TIMEOUT, function()
return state.result ~= nil
- end)
+ end, nil, true)
if not done then
-- Send sigkill since this cannot be caught
self:_timeout(SIG.KILL)
vim.wait(timeout or state.timeout or MAX_TIMEOUT, function()
return state.result ~= nil
- end)
+ end, nil, true)
end
return state.result
@@ -140,7 +140,7 @@ end
--- @return boolean
function SystemObj:is_closing()
local handle = self._state.handle
- return handle == nil or handle:is_closing()
+ return handle == nil or handle:is_closing() or false
end
---@param output fun(err:string?, data: string?)|false
@@ -302,7 +302,7 @@ end
--- Run a system command
---
--- @param cmd string[]
---- @param opts? SystemOpts
+--- @param opts? vim.SystemOpts
--- @param on_exit? fun(out: vim.SystemCompleted)
--- @return vim.SystemObj
function M.run(cmd, opts, on_exit)
diff --git a/runtime/lua/vim/_watch.lua b/runtime/lua/vim/_watch.lua
index 43fce3bf7f..97c5481ad1 100644
--- a/runtime/lua/vim/_watch.lua
+++ b/runtime/lua/vim/_watch.lua
@@ -1,45 +1,61 @@
-local M = {}
local uv = vim.uv
----@enum vim._watch.FileChangeType
-local FileChangeType = {
+local M = {}
+
+--- @enum vim._watch.FileChangeType
+--- Types of events watchers will emit.
+M.FileChangeType = {
Created = 1,
Changed = 2,
Deleted = 3,
}
---- Enumeration describing the types of events watchers will emit.
-M.FileChangeType = vim.tbl_add_reverse_lookup(FileChangeType)
-
---- Joins filepath elements by static '/' separator
+--- @class vim._watch.Opts
---
----@param ... (string) The path elements.
----@return string
-local function filepath_join(...)
- return table.concat({ ... }, '/')
-end
-
---- Stops and closes a libuv |uv_fs_event_t| or |uv_fs_poll_t| handle
+--- @field debounce? integer ms
+---
+--- An |lpeg| pattern. Only changes to files whose full paths match the pattern
+--- will be reported. Only matches against non-directoriess, all directories will
+--- be watched for new potentially-matching files. exclude_pattern can be used to
+--- filter out directories. When nil, matches any file name.
+--- @field include_pattern? vim.lpeg.Pattern
---
----@param handle (uv.uv_fs_event_t|uv.uv_fs_poll_t) The handle to stop
-local function stop(handle)
- local _, stop_err = handle:stop()
- assert(not stop_err, stop_err)
- local is_closing, close_err = handle:is_closing()
- assert(not close_err, close_err)
- if not is_closing then
- handle:close()
+--- An |lpeg| pattern. Only changes to files and directories whose full path does
+--- not match the pattern will be reported. Matches against both files and
+--- directories. When nil, matches nothing.
+--- @field exclude_pattern? vim.lpeg.Pattern
+
+--- @alias vim._watch.Callback fun(path: string, change_type: vim._watch.FileChangeType)
+
+--- @class vim._watch.watch.Opts : vim._watch.Opts
+--- @field uvflags? uv.fs_event_start.flags
+
+--- @param path string
+--- @param opts? vim._watch.Opts
+local function skip(path, opts)
+ if not opts then
+ return false
+ end
+
+ if opts.include_pattern and opts.include_pattern:match(path) == nil then
+ return true
+ end
+
+ if opts.exclude_pattern and opts.exclude_pattern:match(path) ~= nil then
+ return true
end
+
+ return false
end
--- Initializes and starts a |uv_fs_event_t|
---
----@param path (string) The path to watch
----@param opts (table|nil) Additional options
---- - uvflags (table|nil)
---- Same flags as accepted by |uv.fs_event_start()|
----@param callback (function) The function called when new events
----@return (function) Stops the watcher
+--- @param path string The path to watch
+--- @param opts vim._watch.watch.Opts? Additional options:
+--- - uvflags (table|nil)
+--- Same flags as accepted by |uv.fs_event_start()|
+--- @param callback vim._watch.Callback Callback for new events
+--- @return fun() cancel Stops the watcher
function M.watch(path, opts, callback)
vim.validate({
path = { path, 'string', false },
@@ -47,110 +63,120 @@ function M.watch(path, opts, callback)
callback = { callback, 'function', false },
})
+ opts = opts or {}
+
path = vim.fs.normalize(path)
local uvflags = opts and opts.uvflags or {}
- local handle, new_err = vim.uv.new_fs_event()
- assert(not new_err, new_err)
+ local handle = assert(uv.new_fs_event())
+
local _, start_err = handle:start(path, uvflags, function(err, filename, events)
assert(not err, err)
local fullpath = path
if filename then
- filename = filename:gsub('\\', '/')
- fullpath = filepath_join(fullpath, filename)
+ fullpath = vim.fs.normalize(vim.fs.joinpath(fullpath, filename))
end
- local change_type = events.change and M.FileChangeType.Changed or 0
+
+ if skip(fullpath, opts) then
+ return
+ end
+
+ --- @type vim._watch.FileChangeType
+ local change_type
if events.rename then
- local _, staterr, staterrname = vim.uv.fs_stat(fullpath)
+ local _, staterr, staterrname = uv.fs_stat(fullpath)
if staterrname == 'ENOENT' then
change_type = M.FileChangeType.Deleted
else
assert(not staterr, staterr)
change_type = M.FileChangeType.Created
end
+ elseif events.change then
+ change_type = M.FileChangeType.Changed
end
callback(fullpath, change_type)
end)
+
assert(not start_err, start_err)
+
return function()
- stop(handle)
+ local _, stop_err = handle:stop()
+ assert(not stop_err, stop_err)
+ local is_closing, close_err = handle:is_closing()
+ assert(not close_err, close_err)
+ if not is_closing then
+ handle:close()
+ end
end
end
---- @class watch.PollOpts
---- @field debounce? integer
---- @field include_pattern? vim.lpeg.Pattern
---- @field exclude_pattern? vim.lpeg.Pattern
+--- Initializes and starts a |uv_fs_event_t| recursively watching every directory underneath the
+--- directory at path.
+---
+--- @param path string The path to watch. Must refer to a directory.
+--- @param opts vim._watch.Opts? Additional options
+--- @param callback vim._watch.Callback Callback for new events
+--- @return fun() cancel Stops the watcher
+function M.watchdirs(path, opts, callback)
+ vim.validate({
+ path = { path, 'string', false },
+ opts = { opts, 'table', true },
+ callback = { callback, 'function', false },
+ })
----@param path string
----@param opts watch.PollOpts
----@param callback function Called on new events
----@return function cancel stops the watcher
-local function recurse_watch(path, opts, callback)
opts = opts or {}
local debounce = opts.debounce or 500
- local uvflags = {}
+
---@type table<string, uv.uv_fs_event_t> handle by fullpath
local handles = {}
local timer = assert(uv.new_timer())
- ---@type table[]
- local changesets = {}
-
- local function is_included(filepath)
- return opts.include_pattern and opts.include_pattern:match(filepath)
- end
- local function is_excluded(filepath)
- return opts.exclude_pattern and opts.exclude_pattern:match(filepath)
- end
+ --- Map of file path to boolean indicating if the file has been changed
+ --- at some point within the debounce cycle.
+ --- @type table<string, boolean>
+ local filechanges = {}
- local process_changes = function()
- assert(false, "Replaced later. I'm only here as forward reference")
- end
+ local process_changes --- @type fun()
+ --- @param filepath string
+ --- @return uv.fs_event_start.callback
local function create_on_change(filepath)
return function(err, filename, events)
assert(not err, err)
local fullpath = vim.fs.joinpath(filepath, filename)
- if is_included(fullpath) and not is_excluded(filepath) then
- table.insert(changesets, {
- fullpath = fullpath,
- events = events,
- })
- timer:start(debounce, 0, process_changes)
+ if skip(fullpath, opts) then
+ return
+ end
+
+ if not filechanges[fullpath] then
+ filechanges[fullpath] = events.change or false
end
+ timer:start(debounce, 0, process_changes)
end
end
process_changes = function()
- ---@type table<string, table[]>
- local filechanges = vim.defaulttable()
- for i, change in ipairs(changesets) do
- changesets[i] = nil
- if is_included(change.fullpath) and not is_excluded(change.fullpath) then
- table.insert(filechanges[change.fullpath], change.events)
- end
- end
- for fullpath, events_list in pairs(filechanges) do
+ -- Since the callback is debounced it may have also been deleted later on
+ -- so we always need to check the existence of the file:
+ -- stat succeeds, changed=true -> Changed
+ -- stat succeeds, changed=false -> Created
+ -- stat fails -> Removed
+ for fullpath, changed in pairs(filechanges) do
uv.fs_stat(fullpath, function(_, stat)
---@type vim._watch.FileChangeType
local change_type
if stat then
- change_type = FileChangeType.Created
- for _, event in ipairs(events_list) do
- if event.change then
- change_type = FileChangeType.Changed
- end
- end
+ change_type = changed and M.FileChangeType.Changed or M.FileChangeType.Created
if stat.type == 'directory' then
local handle = handles[fullpath]
if not handle then
handle = assert(uv.new_fs_event())
handles[fullpath] = handle
- handle:start(fullpath, uvflags, create_on_change(fullpath))
+ handle:start(fullpath, {}, create_on_change(fullpath))
end
end
else
+ change_type = M.FileChangeType.Deleted
local handle = handles[fullpath]
if handle then
if not handle:is_closing() then
@@ -158,15 +184,16 @@ local function recurse_watch(path, opts, callback)
end
handles[fullpath] = nil
end
- change_type = FileChangeType.Deleted
end
callback(fullpath, change_type)
end)
end
+ filechanges = {}
end
+
local root_handle = assert(uv.new_fs_event())
handles[path] = root_handle
- root_handle:start(path, uvflags, create_on_change(path))
+ root_handle:start(path, {}, create_on_change(path))
--- "640K ought to be enough for anyone"
--- Who has folders this deep?
@@ -174,12 +201,13 @@ local function recurse_watch(path, opts, callback)
for name, type in vim.fs.dir(path, { depth = max_depth }) do
local filepath = vim.fs.joinpath(path, name)
- if type == 'directory' and not is_excluded(filepath) then
+ if type == 'directory' and not skip(filepath, opts) then
local handle = assert(uv.new_fs_event())
handles[filepath] = handle
- handle:start(filepath, uvflags, create_on_change(filepath))
+ handle:start(filepath, {}, create_on_change(filepath))
end
end
+
local function cancel()
for fullpath, handle in pairs(handles) do
if not handle:is_closing() then
@@ -190,34 +218,96 @@ local function recurse_watch(path, opts, callback)
timer:stop()
timer:close()
end
+
return cancel
end
---- Initializes and starts a |uv_fs_poll_t| recursively watching every file underneath the
---- directory at path.
----
----@param path (string) The path to watch. Must refer to a directory.
----@param opts (table|nil) Additional options
---- - debounce (number|nil)
---- Time events are debounced in ms. Defaults to 500
---- - include_pattern (LPeg pattern|nil)
---- An |lpeg| pattern. Only changes to files whose full paths match the pattern
---- will be reported. Only matches against non-directoriess, all directories will
---- be watched for new potentially-matching files. exclude_pattern can be used to
---- filter out directories. When nil, matches any file name.
---- - exclude_pattern (LPeg pattern|nil)
---- An |lpeg| pattern. Only changes to files and directories whose full path does
---- not match the pattern will be reported. Matches against both files and
---- directories. When nil, matches nothing.
----@param callback (function) The function called when new events
----@return function Stops the watcher
-function M.poll(path, opts, callback)
- vim.validate({
- path = { path, 'string', false },
- opts = { opts, 'table', true },
- callback = { callback, 'function', false },
+--- @param data string
+--- @param opts vim._watch.Opts?
+--- @param callback vim._watch.Callback
+local function fswatch_output_handler(data, opts, callback)
+ local d = vim.split(data, '%s+')
+
+ -- only consider the last reported event
+ local fullpath, event = d[1], d[#d]
+
+ if skip(fullpath, opts) then
+ return
+ end
+
+ --- @type integer
+ local change_type
+
+ if event == 'Created' then
+ change_type = M.FileChangeType.Created
+ elseif event == 'Removed' then
+ change_type = M.FileChangeType.Deleted
+ elseif event == 'Updated' then
+ change_type = M.FileChangeType.Changed
+ elseif event == 'Renamed' then
+ local _, staterr, staterrname = uv.fs_stat(fullpath)
+ if staterrname == 'ENOENT' then
+ change_type = M.FileChangeType.Deleted
+ else
+ assert(not staterr, staterr)
+ change_type = M.FileChangeType.Created
+ end
+ end
+
+ if change_type then
+ callback(fullpath, change_type)
+ end
+end
+
+--- @param path string The path to watch. Must refer to a directory.
+--- @param opts vim._watch.Opts?
+--- @param callback vim._watch.Callback Callback for new events
+--- @return fun() cancel Stops the watcher
+function M.fswatch(path, opts, callback)
+ -- debounce isn't the same as latency but close enough
+ local latency = 0.5 -- seconds
+ if opts and opts.debounce then
+ latency = opts.debounce / 1000
+ end
+
+ local obj = vim.system({
+ 'fswatch',
+ '--event=Created',
+ '--event=Removed',
+ '--event=Updated',
+ '--event=Renamed',
+ '--event-flags',
+ '--recursive',
+ '--latency=' .. tostring(latency),
+ '--exclude',
+ '/.git/',
+ path,
+ }, {
+ stderr = function(err, data)
+ if err then
+ error(err)
+ end
+
+ if data and #vim.trim(data) > 0 then
+ vim.schedule(function()
+ vim.notify('fswatch: ' .. data, vim.log.levels.ERROR)
+ end)
+ end
+ end,
+ stdout = function(err, data)
+ if err then
+ error(err)
+ end
+
+ for line in vim.gsplit(data or '', '\n', { plain = true, trimempty = true }) do
+ fswatch_output_handler(line, opts, callback)
+ end
+ end,
})
- return recurse_watch(path, opts, callback)
+
+ return function()
+ obj:kill(2)
+ end
end
return M
diff --git a/runtime/lua/vim/diagnostic.lua b/runtime/lua/vim/diagnostic.lua
index 99448982b4..d5075d7d3d 100644
--- a/runtime/lua/vim/diagnostic.lua
+++ b/runtime/lua/vim/diagnostic.lua
@@ -2,15 +2,260 @@ local api, if_nil = vim.api, vim.F.if_nil
local M = {}
----@enum DiagnosticSeverity
+--- [diagnostic-structure]()
+---
+--- Diagnostics use the same indexing as the rest of the Nvim API (i.e. 0-based
+--- rows and columns). |api-indexing|
+--- @class vim.Diagnostic
+---
+--- Buffer number
+--- @field bufnr? integer
+---
+--- The starting line of the diagnostic (0-indexed)
+--- @field lnum integer
+---
+--- The final line of the diagnostic (0-indexed)
+--- @field end_lnum? integer
+---
+--- The starting column of the diagnostic (0-indexed)
+--- @field col integer
+---
+--- The final column of the diagnostic (0-indexed)
+--- @field end_col? integer
+---
+--- The severity of the diagnostic |vim.diagnostic.severity|
+--- @field severity? vim.diagnostic.Severity
+---
+--- The diagnostic text
+--- @field message string
+---
+--- The source of the diagnostic
+--- @field source? string
+---
+--- The diagnostic code
+--- @field code? string|integer
+---
+--- @field _tags? { deprecated: boolean, unnecessary: boolean}
+---
+--- Arbitrary data plugins or users can add
+--- @field user_data? any arbitrary data plugins can add
+---
+--- @field namespace? integer
+
+--- Each of the configuration options below accepts one of the following:
+--- - `false`: Disable this feature
+--- - `true`: Enable this feature, use default settings.
+--- - `table`: Enable this feature with overrides. Use an empty table to use default values.
+--- - `function`: Function with signature (namespace, bufnr) that returns any of the above.
+--- @class vim.diagnostic.Opts
+---
+--- Use underline for diagnostics.
+--- (default: `true`)
+--- @field underline? boolean|vim.diagnostic.Opts.Underline|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.Underline
+---
+--- Use virtual text for diagnostics. If multiple diagnostics are set for a
+--- namespace, one prefix per diagnostic + the last diagnostic message are
+--- shown.
+--- (default: `true`)
+--- @field virtual_text? boolean|vim.diagnostic.Opts.VirtualText|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.VirtualText
+---
+--- Use signs for diagnostics |diagnostic-signs|.
+--- (default: `true`)
+--- @field signs? boolean|vim.diagnostic.Opts.Signs|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.Signs
+---
+--- Options for floating windows. See |vim.diagnostic.Opts.Float|.
+--- @field float? boolean|vim.diagnostic.Opts.Float|fun(namespace: integer, bufnr:integer): vim.diagnostic.Opts.Float
+---
+--- Update diagnostics in Insert mode
+--- (if `false`, diagnostics are updated on |InsertLeave|)
+--- (default: `false`)
+--- @field update_in_insert? boolean
+---
+--- Sort diagnostics by severity. This affects the order in which signs and
+--- virtual text are displayed. When true, higher severities are displayed
+--- before lower severities (e.g. ERROR is displayed before WARN).
+--- Options:
+--- - {reverse}? (boolean) Reverse sort order
+--- (default: `false)
+--- @field severity_sort? boolean|{reverse?:boolean}
+
+--- @class (private) vim.diagnostic.OptsResolved
+--- @field float vim.diagnostic.Opts.Float
+--- @field update_in_insert boolean
+--- @field underline vim.diagnostic.Opts.Underline
+--- @field virtual_text vim.diagnostic.Opts.VirtualText
+--- @field signs vim.diagnostic.Opts.Signs
+--- @field severity_sort {reverse?:boolean}
+
+--- @class vim.diagnostic.Opts.Float
+---
+--- Buffer number to show diagnostics from.
+--- (default: current buffer)
+--- @field bufnr? integer
+---
+--- Limit diagnostics to the given namespace
+--- @field namespace? integer
+---
+--- Show diagnostics from the whole buffer (`buffer"`, the current cursor line
+--- (`line`), or the current cursor position (`cursor`). Shorthand versions
+--- are also accepted (`c` for `cursor`, `l` for `line`, `b` for `buffer`).
+--- (default: `line`)
+--- @field scope? 'line'|'buffer'|'cursor'|'c'|'l'|'b'
+---
+--- If {scope} is "line" or "cursor", use this position rather than the cursor
+--- position. If a number, interpreted as a line number; otherwise, a
+--- (row, col) tuple.
+--- @field pos? integer|{[1]:integer,[2]:integer}
+---
+--- Sort diagnostics by severity.
+--- Overrides the setting from |vim.diagnostic.config()|.
+--- (default: `false`)
+--- @field severity_sort? boolean|{reverse?:boolean}
+---
+--- See |diagnostic-severity|.
+--- Overrides the setting from |vim.diagnostic.config()|.
+--- @field severity? vim.diagnostic.SeverityFilter
+---
+--- String to use as the header for the floating window. If a table, it is
+--- interpreted as a `[text, hl_group]` tuple.
+--- Overrides the setting from |vim.diagnostic.config()|.
+--- @field header? string|{[1]:string,[2]:any}
+---
+--- Include the diagnostic source in the message.
+--- Use "if_many" to only show sources if there is more than one source of
+--- diagnostics in the buffer. Otherwise, any truthy value means to always show
+--- the diagnostic source.
+--- Overrides the setting from |vim.diagnostic.config()|.
+--- @field source? boolean|'if_many'
+---
+--- A function that takes a diagnostic as input and returns a string.
+--- The return value is the text used to display the diagnostic.
+--- Overrides the setting from |vim.diagnostic.config()|.
+--- @field format? fun(diagnostic:vim.Diagnostic): string
+---
+--- Prefix each diagnostic in the floating window:
+--- - If a `function`, {i} is the index of the diagnostic being evaluated and
+--- {total} is the total number of diagnostics displayed in the window. The
+--- function should return a `string` which is prepended to each diagnostic
+--- in the window as well as an (optional) highlight group which will be
+--- used to highlight the prefix.
+--- - If a `table`, it is interpreted as a `[text, hl_group]` tuple as
+--- in |nvim_echo()|
+--- - If a `string`, it is prepended to each diagnostic in the window with no
+--- highlight.
+--- Overrides the setting from |vim.diagnostic.config()|.
+--- @field prefix? string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)
+---
+--- Same as {prefix}, but appends the text to the diagnostic instead of
+--- prepending it.
+--- Overrides the setting from |vim.diagnostic.config()|.
+--- @field suffix? string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)
+---
+--- @field focus_id? string
+
+--- @class vim.diagnostic.Opts.Underline
+---
+--- Only underline diagnostics matching the given
+--- severity |diagnostic-severity|.
+--- @field severity? vim.diagnostic.SeverityFilter
+
+--- @class vim.diagnostic.Opts.VirtualText
+---
+--- Only show virtual text for diagnostics matching the given
+--- severity |diagnostic-severity|
+--- @field severity? vim.diagnostic.SeverityFilter
+---
+--- Include the diagnostic source in virtual text. Use `'if_many'` to only
+--- show sources if there is more than one diagnostic source in the buffer.
+--- Otherwise, any truthy value means to always show the diagnostic source.
+--- @field source? boolean|"if_many"
+---
+--- Amount of empty spaces inserted at the beginning of the virtual text.
+--- @field spacing? integer
+---
+--- Prepend diagnostic message with prefix. If a `function`, {i} is the index
+--- of the diagnostic being evaluated, and {total} is the total number of
+--- diagnostics for the line. This can be used to render diagnostic symbols
+--- or error codes.
+--- @field prefix? string|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string)
+---
+--- Append diagnostic message with suffix.
+--- This can be used to render an LSP diagnostic error code.
+--- @field suffix? string|(fun(diagnostic:vim.Diagnostic): string)
+---
+--- The return value is the text used to display the diagnostic. Example:
+--- ```lua
+--- function(diagnostic)
+--- if diagnostic.severity == vim.diagnostic.severity.ERROR then
+--- return string.format("E: %s", diagnostic.message)
+--- end
+--- return diagnostic.message
+--- end
+--- ```
+--- @field format? fun(diagnostic:vim.Diagnostic): string
+---
+--- See |nvim_buf_set_extmark()|.
+--- @field hl_mode? 'replace'|'combine'|'blend'
+---
+--- See |nvim_buf_set_extmark()|.
+--- @field virt_text? {[1]:string,[2]:any}[]
+---
+--- See |nvim_buf_set_extmark()|.
+--- @field virt_text_pos? 'eol'|'overlay'|'right_align'|'inline'
+---
+--- See |nvim_buf_set_extmark()|.
+--- @field virt_text_win_col? integer
+---
+--- See |nvim_buf_set_extmark()|.
+--- @field virt_text_hide? boolean
+
+--- @class vim.diagnostic.Opts.Signs
+---
+--- Only show virtual text for diagnostics matching the given
+--- severity |diagnostic-severity|
+--- @field severity? vim.diagnostic.SeverityFilter
+---
+--- Base priority to use for signs. When {severity_sort} is used, the priority
+--- of a sign is adjusted based on its severity.
+--- Otherwise, all signs use the same priority.
+--- (default: `10`)
+--- @field priority? integer
+---
+--- A table mapping |diagnostic-severity| to the sign text to display in the
+--- sign column. The default is to use `"E"`, `"W"`, `"I"`, and `"H"` for errors,
+--- warnings, information, and hints, respectively. Example:
+--- ```lua
+--- vim.diagnostic.config({
+--- signs = { text = { [vim.diagnostic.severity.ERROR] = 'E', ... } }
+--- })
+--- ```
+--- @field text? table<vim.diagnostic.Severity,string>
+---
+--- A table mapping |diagnostic-severity| to the highlight group used for the
+--- line number where the sign is placed.
+--- @field numhl? table<vim.diagnostic.Severity,string>
+---
+--- A table mapping |diagnostic-severity| to the highlight group used for the
+--- whole line the sign is placed in.
+--- @field linehl? table<vim.diagnostic.Severity,string>
+
+--- @nodoc
+--- @enum vim.diagnostic.Severity
M.severity = {
ERROR = 1,
WARN = 2,
INFO = 3,
HINT = 4,
+ [1] = 'ERROR',
+ [2] = 'WARN',
+ [3] = 'INFO',
+ [4] = 'HINT',
}
-vim.tbl_add_reverse_lookup(M.severity)
+--- @alias vim.diagnostic.SeverityInt 1|2|3|4
+
+--- See |diagnostic-severity| and |vim.diagnostic.get()|
+--- @alias vim.diagnostic.SeverityFilter vim.diagnostic.Severity|vim.diagnostic.Severity[]|{min:vim.diagnostic.Severity,max:vim.diagnostic.Severity}
-- Mappings from qflist/loclist error types to severities
M.severity.E = M.severity.ERROR
@@ -18,6 +263,7 @@ M.severity.W = M.severity.WARN
M.severity.I = M.severity.INFO
M.severity.N = M.severity.HINT
+--- @type vim.diagnostic.Opts
local global_diagnostic_options = {
signs = true,
underline = true,
@@ -27,6 +273,12 @@ local global_diagnostic_options = {
severity_sort = false,
}
+--- @class (private) vim.diagnostic.Handler
+--- @field show? fun(namespace: integer, bufnr: integer, diagnostics: vim.Diagnostic[], opts?: vim.diagnostic.OptsResolved)
+--- @field hide? fun(namespace:integer, bufnr:integer)
+
+--- @nodoc
+--- @type table<string,vim.diagnostic.Handler>
M.handlers = setmetatable({}, {
__newindex = function(t, name, handler)
vim.validate({ handler = { handler, 't' } })
@@ -39,6 +291,9 @@ M.handlers = setmetatable({}, {
-- Metatable that automatically creates an empty table when assigning to a missing key
local bufnr_and_namespace_cacher_mt = {
+ --- @param t table<integer,table>
+ --- @param bufnr integer
+ --- @return table
__index = function(t, bufnr)
assert(bufnr > 0, 'Invalid buffer number')
t[bufnr] = {}
@@ -46,10 +301,13 @@ local bufnr_and_namespace_cacher_mt = {
end,
}
-local diagnostic_cache
+-- bufnr -> ns -> Diagnostic[]
+local diagnostic_cache = {} --- @type table<integer,table<integer,vim.Diagnostic[]>>
do
local group = api.nvim_create_augroup('DiagnosticBufWipeout', {})
- diagnostic_cache = setmetatable({}, {
+ setmetatable(diagnostic_cache, {
+ --- @param t table<integer,vim.Diagnostic[]>
+ --- @param bufnr integer
__index = function(t, bufnr)
assert(bufnr > 0, 'Invalid buffer number')
api.nvim_create_autocmd('BufWipeout', {
@@ -65,61 +323,93 @@ do
})
end
+--- @class (private) vim.diagnostic._extmark
+--- @field [1] integer id
+--- @field [2] integer start
+--- @field [3] integer end
+--- @field [4] table details
+
+--- @type table<integer,table<integer,vim.diagnostic._extmark[]>>
local diagnostic_cache_extmarks = setmetatable({}, bufnr_and_namespace_cacher_mt)
+
+--- @type table<integer,true>
local diagnostic_attached_buffers = {}
+
+--- @type table<integer,true|table<integer,true>>
local diagnostic_disabled = {}
+
+--- @type table<integer,table<integer,table>>
local bufs_waiting_to_update = setmetatable({}, bufnr_and_namespace_cacher_mt)
+--- @class vim.diagnostic.NS
+--- @field name string
+--- @field opts vim.diagnostic.Opts
+--- @field user_data table
+--- @field disabled? boolean
+
+--- @type table<integer,vim.diagnostic.NS>
local all_namespaces = {}
+---@param severity string|vim.diagnostic.Severity
+---@return vim.diagnostic.Severity?
local function to_severity(severity)
if type(severity) == 'string' then
- return assert(
- M.severity[string.upper(severity)],
- string.format('Invalid severity: %s', severity)
- )
+ assert(M.severity[string.upper(severity)], string.format('Invalid severity: %s', severity))
+ return M.severity[string.upper(severity)]
end
return severity
end
+--- @param severity vim.diagnostic.SeverityFilter
+--- @param diagnostics vim.Diagnostic[]
+--- @return vim.Diagnostic[]
local function filter_by_severity(severity, diagnostics)
if not severity then
return diagnostics
end
if type(severity) ~= 'table' then
- severity = to_severity(severity)
+ severity = assert(to_severity(severity))
+ --- @param t vim.Diagnostic
return vim.tbl_filter(function(t)
return t.severity == severity
end, diagnostics)
end
if severity.min or severity.max then
+ --- @cast severity {min:vim.diagnostic.Severity,max:vim.diagnostic.Severity}
local min_severity = to_severity(severity.min) or M.severity.HINT
local max_severity = to_severity(severity.max) or M.severity.ERROR
+ --- @param t vim.Diagnostic
return vim.tbl_filter(function(t)
return t.severity <= min_severity and t.severity >= max_severity
end, diagnostics)
end
- local severities = {}
+ --- @cast severity vim.diagnostic.Severity[]
+
+ local severities = {} --- @type table<vim.diagnostic.Severity,true>
for _, s in ipairs(severity) do
- severities[to_severity(s)] = true
+ severities[assert(to_severity(s))] = true
end
+ --- @param t vim.Diagnostic
return vim.tbl_filter(function(t)
return severities[t.severity]
end, diagnostics)
end
+--- @param bufnr integer
+--- @return integer
local function count_sources(bufnr)
- local seen = {}
+ local seen = {} --- @type table<string,true>
local count = 0
for _, namespace_diagnostics in pairs(diagnostic_cache[bufnr]) do
for _, diagnostic in ipairs(namespace_diagnostics) do
- if diagnostic.source and not seen[diagnostic.source] then
- seen[diagnostic.source] = true
+ local source = diagnostic.source
+ if source and not seen[source] then
+ seen[source] = true
count = count + 1
end
end
@@ -127,51 +417,65 @@ local function count_sources(bufnr)
return count
end
+--- @param diagnostics vim.Diagnostic[]
+--- @return vim.Diagnostic[]
local function prefix_source(diagnostics)
+ --- @param d vim.Diagnostic
return vim.tbl_map(function(d)
if not d.source then
return d
end
- local t = vim.deepcopy(d)
+ local t = vim.deepcopy(d, true)
t.message = string.format('%s: %s', d.source, d.message)
return t
end, diagnostics)
end
+--- @param diagnostics vim.Diagnostic[]
+--- @return vim.Diagnostic[]
local function reformat_diagnostics(format, diagnostics)
vim.validate({
format = { format, 'f' },
diagnostics = { diagnostics, 't' },
})
- local formatted = vim.deepcopy(diagnostics)
+ local formatted = vim.deepcopy(diagnostics, true)
for _, diagnostic in ipairs(formatted) do
diagnostic.message = format(diagnostic)
end
return formatted
end
+--- @param option string
+--- @param namespace integer?
+--- @return table
local function enabled_value(option, namespace)
local ns = namespace and M.get_namespace(namespace) or {}
if ns.opts and type(ns.opts[option]) == 'table' then
return ns.opts[option]
end
- if type(global_diagnostic_options[option]) == 'table' then
- return global_diagnostic_options[option]
+ local global_opt = global_diagnostic_options[option]
+ if type(global_opt) == 'table' then
+ return global_opt
end
return {}
end
+--- @param option string
+--- @param value any?
+--- @param namespace integer?
+--- @param bufnr integer
+--- @return any
local function resolve_optional_value(option, value, namespace, bufnr)
if not value then
return false
elseif value == true then
return enabled_value(option, namespace)
elseif type(value) == 'function' then
- local val = value(namespace, bufnr)
+ local val = value(namespace, bufnr) --- @type any
if val == true then
return enabled_value(option, namespace)
else
@@ -179,15 +483,18 @@ local function resolve_optional_value(option, value, namespace, bufnr)
end
elseif type(value) == 'table' then
return value
- else
- error('Unexpected option type: ' .. vim.inspect(value))
end
+ error('Unexpected option type: ' .. vim.inspect(value))
end
+--- @param opts vim.diagnostic.Opts?
+--- @param namespace integer?
+--- @param bufnr integer
+--- @return vim.diagnostic.OptsResolved
local function get_resolved_options(opts, namespace, bufnr)
local ns = namespace and M.get_namespace(namespace) or {}
-- Do not use tbl_deep_extend so that an empty table can be used to reset to default values
- local resolved = vim.tbl_extend('keep', opts or {}, ns.opts or {}, global_diagnostic_options)
+ local resolved = vim.tbl_extend('keep', opts or {}, ns.opts or {}, global_diagnostic_options) --- @type table<string,any>
for k in pairs(global_diagnostic_options) do
if resolved[k] ~= nil then
resolved[k] = resolve_optional_value(k, resolved[k], namespace, bufnr)
@@ -204,9 +511,11 @@ local diagnostic_severities = {
[M.severity.HINT] = { ctermfg = 7, guifg = 'LightGrey' },
}
--- Make a map from DiagnosticSeverity -> Highlight Name
+--- Make a map from vim.diagnostic.Severity -> Highlight Name
+--- @param base_name string
+--- @return table<vim.diagnostic.SeverityInt,string>
local function make_highlight_map(base_name)
- local result = {}
+ local result = {} --- @type table<vim.diagnostic.SeverityInt,string>
for k in pairs(diagnostic_severities) do
local name = M.severity[k]
name = name:sub(1, 1) .. name:sub(2):lower()
@@ -216,35 +525,13 @@ local function make_highlight_map(base_name)
return result
end
+-- TODO(lewis6991): these highlight maps can only be indexed with an integer, however there usage
+-- implies they can be indexed with any vim.diagnostic.Severity
local virtual_text_highlight_map = make_highlight_map('VirtualText')
local underline_highlight_map = make_highlight_map('Underline')
local floating_highlight_map = make_highlight_map('Floating')
local sign_highlight_map = make_highlight_map('Sign')
----@private
-local define_default_signs = (function()
- local signs_defined = false
- return function()
- if signs_defined then
- return
- end
-
- for severity, sign_hl_name in pairs(sign_highlight_map) do
- if vim.tbl_isempty(vim.fn.sign_getdefined(sign_hl_name)) then
- local severity_name = M.severity[severity]
- vim.fn.sign_define(sign_hl_name, {
- text = (severity_name or 'U'):sub(1, 1),
- texthl = sign_hl_name,
- linehl = '',
- numhl = '',
- })
- end
- end
-
- signs_defined = true
- end
-end)()
-
local function get_bufnr(bufnr)
if not bufnr or bufnr == 0 then
return api.nvim_get_current_buf()
@@ -252,12 +539,14 @@ local function get_bufnr(bufnr)
return bufnr
end
+--- @param diagnostics vim.Diagnostic[]
+--- @return table<integer,vim.Diagnostic[]>
local function diagnostic_lines(diagnostics)
if not diagnostics then
return {}
end
- local diagnostics_by_line = {}
+ local diagnostics_by_line = {} --- @type table<integer,vim.Diagnostic[]>
for _, diagnostic in ipairs(diagnostics) do
local line_diagnostics = diagnostics_by_line[diagnostic.lnum]
if not line_diagnostics then
@@ -269,6 +558,9 @@ local function diagnostic_lines(diagnostics)
return diagnostics_by_line
end
+--- @param namespace integer
+--- @param bufnr integer
+--- @param diagnostics vim.Diagnostic[]
local function set_diagnostic_cache(namespace, bufnr, diagnostics)
for _, diagnostic in ipairs(diagnostics) do
assert(diagnostic.lnum, 'Diagnostic line number is required')
@@ -283,10 +575,12 @@ local function set_diagnostic_cache(namespace, bufnr, diagnostics)
diagnostic_cache[bufnr][namespace] = diagnostics
end
+--- @param bufnr integer
+--- @param last integer
local function restore_extmarks(bufnr, last)
for ns, extmarks in pairs(diagnostic_cache_extmarks[bufnr]) do
local extmarks_current = api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, { details = true })
- local found = {}
+ local found = {} --- @type table<integer,true>
for _, extmark in ipairs(extmarks_current) do
-- nvim_buf_set_lines will move any extmark to the line after the last
-- nvim_buf_set_text will move any extmark to the last line
@@ -304,6 +598,8 @@ local function restore_extmarks(bufnr, last)
end
end
+--- @param namespace integer
+--- @param bufnr? integer
local function save_extmarks(namespace, bufnr)
bufnr = get_bufnr(bufnr)
if not diagnostic_attached_buffers[bufnr] then
@@ -321,6 +617,7 @@ local function save_extmarks(namespace, bufnr)
api.nvim_buf_get_extmarks(bufnr, namespace, 0, -1, { details = true })
end
+--- @type table<string,true>
local registered_autocmds = {}
local function make_augroup_key(namespace, bufnr)
@@ -328,6 +625,8 @@ local function make_augroup_key(namespace, bufnr)
return string.format('DiagnosticInsertLeave:%s:%s', bufnr, ns.name)
end
+--- @param namespace integer
+--- @param bufnr integer
local function execute_scheduled_display(namespace, bufnr)
local args = bufs_waiting_to_update[bufnr][namespace]
if not args then
@@ -343,6 +642,9 @@ end
--- Table of autocmd events to fire the update for displaying new diagnostic information
local insert_leave_auto_cmds = { 'InsertLeave', 'CursorHoldI' }
+--- @param namespace integer
+--- @param bufnr integer
+--- @param args any[]
local function schedule_display(namespace, bufnr, args)
bufs_waiting_to_update[bufnr][namespace] = args
@@ -361,6 +663,8 @@ local function schedule_display(namespace, bufnr, args)
end
end
+--- @param namespace integer
+--- @param bufnr integer
local function clear_scheduled_display(namespace, bufnr)
local key = make_augroup_key(namespace, bufnr)
@@ -370,6 +674,10 @@ local function clear_scheduled_display(namespace, bufnr)
end
end
+--- @param bufnr integer?
+--- @param opts vim.diagnostic.GetOpts?
+--- @param clamp boolean
+--- @return vim.Diagnostic[]
local function get_diagnostics(bufnr, opts, clamp)
opts = opts or {}
@@ -377,16 +685,21 @@ local function get_diagnostics(bufnr, opts, clamp)
local diagnostics = {}
-- Memoized results of buf_line_count per bufnr
+ --- @type table<integer,integer>
local buf_line_count = setmetatable({}, {
+ --- @param t table<integer,integer>
+ --- @param k integer
+ --- @return integer
__index = function(t, k)
t[k] = api.nvim_buf_line_count(k)
return rawget(t, k)
end,
})
+ ---@param b integer
+ ---@param d vim.Diagnostic
local function add(b, d)
if not opts.lnum or d.lnum == opts.lnum then
- d = vim.deepcopy(d)
if clamp and api.nvim_buf_is_loaded(b) then
local line_count = buf_line_count[b] - 1
if
@@ -397,8 +710,9 @@ local function get_diagnostics(bufnr, opts, clamp)
or d.col < 0
or d.end_col < 0
then
+ d = vim.deepcopy(d, true)
d.lnum = math.max(math.min(d.lnum, line_count), 0)
- d.end_lnum = math.max(math.min(d.end_lnum, line_count), 0)
+ d.end_lnum = math.max(math.min(assert(d.end_lnum), line_count), 0)
d.col = math.max(d.col, 0)
d.end_col = math.max(d.end_col, 0)
end
@@ -407,6 +721,8 @@ local function get_diagnostics(bufnr, opts, clamp)
end
end
+ --- @param buf integer
+ --- @param diags vim.Diagnostic[]
local function add_all_diags(buf, diags)
for _, diagnostic in pairs(diags) do
add(buf, diagnostic)
@@ -440,18 +756,20 @@ local function get_diagnostics(bufnr, opts, clamp)
return diagnostics
end
+--- @param loclist boolean
+--- @param opts vim.diagnostic.setqflist.Opts|vim.diagnostic.setloclist.Opts?
local function set_list(loclist, opts)
opts = opts or {}
- local open = vim.F.if_nil(opts.open, true)
+ local open = if_nil(opts.open, true)
local title = opts.title or 'Diagnostics'
local winnr = opts.winnr or 0
- local bufnr
+ local bufnr --- @type integer?
if loclist then
bufnr = api.nvim_win_get_buf(winnr)
end
-- Don't clamp line numbers since the quickfix list can already handle line
-- numbers beyond the end of the buffer
- local diagnostics = get_diagnostics(bufnr, opts, false)
+ local diagnostics = get_diagnostics(bufnr, opts --[[@as vim.diagnostic.GetOpts]], false)
local items = M.toqflist(diagnostics)
if loclist then
vim.fn.setloclist(winnr, {}, ' ', { title = title, items = items })
@@ -463,10 +781,16 @@ local function set_list(loclist, opts)
end
end
+--- @param position {[1]: integer, [2]: integer}
+--- @param search_forward boolean
+--- @param bufnr integer
+--- @param opts vim.diagnostic.GotoOpts
+--- @param namespace integer
+--- @return vim.Diagnostic?
local function next_diagnostic(position, search_forward, bufnr, opts, namespace)
position[1] = position[1] - 1
bufnr = get_bufnr(bufnr)
- local wrap = vim.F.if_nil(opts.wrap, true)
+ local wrap = if_nil(opts.wrap, true)
local line_count = api.nvim_buf_line_count(bufnr)
local diagnostics =
get_diagnostics(bufnr, vim.tbl_extend('keep', opts, { namespace = namespace }), true)
@@ -483,6 +807,7 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace)
end
if line_diagnostics[lnum] and not vim.tbl_isempty(line_diagnostics[lnum]) then
local line_length = #api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, true)[1]
+ --- @type function, function
local sort_diagnostics, is_next
if search_forward then
sort_diagnostics = function(a, b)
@@ -501,7 +826,9 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace)
end
table.sort(line_diagnostics[lnum], sort_diagnostics)
if i == 0 then
- for _, v in pairs(line_diagnostics[lnum]) do
+ for _, v in
+ pairs(line_diagnostics[lnum] --[[@as table<string,any>]])
+ do
if is_next(v) then
return v
end
@@ -513,10 +840,12 @@ local function next_diagnostic(position, search_forward, bufnr, opts, namespace)
end
end
+--- @param opts vim.diagnostic.GotoOpts?
+--- @param pos {[1]:integer,[2]:integer}|false
local function diagnostic_move_pos(opts, pos)
opts = opts or {}
- local float = vim.F.if_nil(opts.float, true)
+ local float = if_nil(opts.float, true)
local win_id = opts.win_id or api.nvim_get_current_win()
if not pos then
@@ -566,76 +895,18 @@ end
---
--- then virtual text will not be enabled for those diagnostics.
---
----@note Each of the configuration options below accepts one of the following:
---- - `false`: Disable this feature
---- - `true`: Enable this feature, use default settings.
---- - `table`: Enable this feature with overrides. Use an empty table to use default values.
---- - `function`: Function with signature (namespace, bufnr) that returns any of the above.
----
----@param opts table|nil When omitted or "nil", retrieve the current configuration. Otherwise, a
---- configuration table with the following keys:
---- - underline: (default true) Use underline for diagnostics. Options:
---- * severity: Only underline diagnostics matching the given
---- severity |diagnostic-severity|
---- - virtual_text: (default true) Use virtual text for diagnostics. If multiple diagnostics
---- are set for a namespace, one prefix per diagnostic + the last diagnostic
---- message are shown. In addition to the options listed below, the
---- "virt_text" options of |nvim_buf_set_extmark()| may also be used here
---- (e.g. "virt_text_pos" and "hl_mode").
---- Options:
---- * severity: Only show virtual text for diagnostics matching the given
---- severity |diagnostic-severity|
---- * source: (boolean or string) Include the diagnostic source in virtual
---- text. Use "if_many" to only show sources if there is more than
---- one diagnostic source in the buffer. Otherwise, any truthy value
---- means to always show the diagnostic source.
---- * spacing: (number) Amount of empty spaces inserted at the beginning
---- of the virtual text.
---- * prefix: (string or function) prepend diagnostic message with prefix.
---- If a function, it must have the signature (diagnostic, i, total)
---- -> string, where {diagnostic} is of type |diagnostic-structure|,
---- {i} is the index of the diagnostic being evaluated, and {total}
---- is the total number of diagnostics for the line. This can be
---- used to render diagnostic symbols or error codes.
---- * suffix: (string or function) Append diagnostic message with suffix.
---- If a function, it must have the signature (diagnostic) ->
---- string, where {diagnostic} is of type |diagnostic-structure|.
---- This can be used to render an LSP diagnostic error code.
---- * format: (function) A function that takes a diagnostic as input and
---- returns a string. The return value is the text used to display
---- the diagnostic. Example:
---- <pre>lua
---- function(diagnostic)
---- if diagnostic.severity == vim.diagnostic.severity.ERROR then
---- return string.format("E: %s", diagnostic.message)
---- end
---- return diagnostic.message
---- end
---- </pre>
---- - signs: (default true) Use signs for diagnostics. Options:
---- * severity: Only show signs for diagnostics matching the given
---- severity |diagnostic-severity|
---- * priority: (number, default 10) Base priority to use for signs. When
---- {severity_sort} is used, the priority of a sign is adjusted based on
---- its severity. Otherwise, all signs use the same priority.
---- - float: Options for floating windows. See |vim.diagnostic.open_float()|.
---- - update_in_insert: (default false) Update diagnostics in Insert mode (if false,
---- diagnostics are updated on InsertLeave)
---- - severity_sort: (default false) Sort diagnostics by severity. This affects the order in
---- which signs and virtual text are displayed. When true, higher severities
---- are displayed before lower severities (e.g. ERROR is displayed before WARN).
---- Options:
---- * reverse: (boolean) Reverse sort order
----
----@param namespace integer|nil Update the options for the given namespace. When omitted, update the
---- global diagnostic options.
+---@param opts vim.diagnostic.Opts? When omitted or `nil`, retrieve the current
+--- configuration. Otherwise, a configuration table (see |vim.diagnostic.Opts|).
+---@param namespace integer? Update the options for the given namespace.
+--- When omitted, update the global diagnostic options.
+---@return vim.diagnostic.Opts? : Current diagnostic config if {opts} is omitted.
function M.config(opts, namespace)
vim.validate({
opts = { opts, 't', true },
namespace = { namespace, 'n', true },
})
- local t
+ local t --- @type vim.diagnostic.Opts
if namespace then
local ns = M.get_namespace(namespace)
t = ns.opts
@@ -645,10 +916,12 @@ function M.config(opts, namespace)
if not opts then
-- Return current config
- return vim.deepcopy(t)
+ return vim.deepcopy(t, true)
end
- for k, v in pairs(opts) do
+ for k, v in
+ pairs(opts --[[@as table<any,any>]])
+ do
t[k] = v
end
@@ -671,8 +944,8 @@ end
---
---@param namespace integer The diagnostic namespace
---@param bufnr integer Buffer number
----@param diagnostics table A list of diagnostic items |diagnostic-structure|
----@param opts table|nil Display options to pass to |vim.diagnostic.show()|
+---@param diagnostics vim.Diagnostic[]
+---@param opts? vim.diagnostic.Opts Display options to pass to |vim.diagnostic.show()|
function M.set(namespace, bufnr, diagnostics, opts)
vim.validate({
namespace = { namespace, 'n' },
@@ -698,6 +971,7 @@ function M.set(namespace, bufnr, diagnostics, opts)
api.nvim_exec_autocmds('DiagnosticChanged', {
modeline = false,
buffer = bufnr,
+ -- TODO(lewis6991): should this be deepcopy()'d like they are in vim.diagnostic.get()
data = { diagnostics = diagnostics },
})
end
@@ -705,11 +979,11 @@ end
--- Get namespace metadata.
---
---@param namespace integer Diagnostic namespace
----@return table Namespace metadata
+---@return vim.diagnostic.NS : Namespace metadata
function M.get_namespace(namespace)
vim.validate({ namespace = { namespace, 'n' } })
if not all_namespaces[namespace] then
- local name
+ local name --- @type string?
for k, v in pairs(api.nvim_get_namespaces()) do
if namespace == v then
name = k
@@ -730,48 +1004,56 @@ end
--- Get current diagnostic namespaces.
---
----@return table A list of active diagnostic namespaces |vim.diagnostic|.
+---@return table<integer,vim.diagnostic.NS> : List of active diagnostic namespaces |vim.diagnostic|.
function M.get_namespaces()
- return vim.deepcopy(all_namespaces)
+ return vim.deepcopy(all_namespaces, true)
end
----@class Diagnostic
----@field bufnr? integer
----@field lnum integer 0-indexed
----@field end_lnum? integer 0-indexed
----@field col integer 0-indexed
----@field end_col? integer 0-indexed
----@field severity? DiagnosticSeverity
----@field message string
----@field source? string
----@field code? string
----@field _tags? { deprecated: boolean, unnecessary: boolean}
----@field user_data? any arbitrary data plugins can add
-
--- Get current diagnostics.
---
---- Modifying diagnostics in the returned table has no effect. To set diagnostics in a buffer, use |vim.diagnostic.set()|.
+--- Modifying diagnostics in the returned table has no effect.
+--- To set diagnostics in a buffer, use |vim.diagnostic.set()|.
---
----@param bufnr integer|nil Buffer number to get diagnostics from. Use 0 for
---- current buffer or nil for all buffers.
----@param opts table|nil A table with the following keys:
---- - namespace: (number) Limit diagnostics to the given namespace.
---- - lnum: (number) Limit diagnostics to the given line number.
---- - severity: See |diagnostic-severity|.
----@return Diagnostic[] table A list of diagnostic items |diagnostic-structure|. Keys `bufnr`, `end_lnum`, `end_col`, and `severity` are guaranteed to be present.
+---@param bufnr integer? Buffer number to get diagnostics from. Use 0 for
+--- current buffer or nil for all buffers.
+---@param opts? vim.diagnostic.GetOpts
+---@return vim.Diagnostic[] : Fields `bufnr`, `end_lnum`, `end_col`, and `severity`
+--- are guaranteed to be present.
function M.get(bufnr, opts)
vim.validate({
bufnr = { bufnr, 'n', true },
opts = { opts, 't', true },
})
- return get_diagnostics(bufnr, opts, false)
+ return vim.deepcopy(get_diagnostics(bufnr, opts, false), true)
+end
+
+--- Get current diagnostics count.
+---
+---@param bufnr? integer Buffer number to get diagnostics from. Use 0 for
+--- current buffer or nil for all buffers.
+---@param opts? vim.diagnostic.GetOpts
+---@return table : Table with actually present severity values as keys
+--- (see |diagnostic-severity|) and integer counts as values.
+function M.count(bufnr, opts)
+ vim.validate({
+ bufnr = { bufnr, 'n', true },
+ opts = { opts, 't', true },
+ })
+
+ local diagnostics = get_diagnostics(bufnr, opts, false)
+ local count = {} --- @type table<integer,integer>
+ for i = 1, #diagnostics do
+ local severity = diagnostics[i].severity --[[@as integer]]
+ count[severity] = (count[severity] or 0) + 1
+ end
+ return count
end
--- Get the previous diagnostic closest to the cursor position.
---
----@param opts nil|table See |vim.diagnostic.goto_next()|
----@return Diagnostic|nil Previous diagnostic
+---@param opts? vim.diagnostic.GotoOpts
+---@return vim.Diagnostic? : Previous diagnostic
function M.get_prev(opts)
opts = opts or {}
@@ -784,9 +1066,9 @@ end
--- Return the position of the previous diagnostic in the current buffer.
---
----@param opts table|nil See |vim.diagnostic.goto_next()|
----@return table|false Previous diagnostic position as a (row, col) tuple or false if there is no
---- prior diagnostic
+---@param opts? vim.diagnostic.GotoOpts
+---@return table|false: Previous diagnostic position as a `(row, col)` tuple
+--- or `false` if there is no prior diagnostic.
function M.get_prev_pos(opts)
local prev = M.get_prev(opts)
if not prev then
@@ -797,15 +1079,15 @@ function M.get_prev_pos(opts)
end
--- Move to the previous diagnostic in the current buffer.
----@param opts table|nil See |vim.diagnostic.goto_next()|
+---@param opts? vim.diagnostic.GotoOpts
function M.goto_prev(opts)
return diagnostic_move_pos(opts, M.get_prev_pos(opts))
end
--- Get the next diagnostic closest to the cursor position.
---
----@param opts table|nil See |vim.diagnostic.goto_next()|
----@return Diagnostic|nil Next diagnostic
+---@param opts? vim.diagnostic.GotoOpts
+---@return vim.Diagnostic? : Next diagnostic
function M.get_next(opts)
opts = opts or {}
@@ -818,9 +1100,9 @@ end
--- Return the position of the next diagnostic in the current buffer.
---
----@param opts table|nil See |vim.diagnostic.goto_next()|
----@return table|false Next diagnostic position as a (row, col) tuple or false if no next
---- diagnostic.
+---@param opts? vim.diagnostic.GotoOpts
+---@return table|false : Next diagnostic position as a `(row, col)` tuple or false if no next
+--- diagnostic.
function M.get_next_pos(opts)
local next = M.get_next(opts)
if not next then
@@ -830,22 +1112,49 @@ function M.get_next_pos(opts)
return { next.lnum, next.col }
end
+--- A table with the following keys:
+--- @class vim.diagnostic.GetOpts
+---
+--- Limit diagnostics to the given namespace.
+--- @field namespace? integer
+---
+--- Limit diagnostics to the given line number.
+--- @field lnum? integer
+---
+--- See |diagnostic-severity|.
+--- @field severity? vim.diagnostic.SeverityFilter
+
+--- Configuration table with the following keys:
+--- @class vim.diagnostic.GotoOpts : vim.diagnostic.GetOpts
+---
+--- Cursor position as a `(row, col)` tuple.
+--- See |nvim_win_get_cursor()|.
+--- (default: current cursor position)
+--- @field cursor_position? {[1]:integer,[2]:integer}
+---
+--- Whether to loop around file or not. Similar to 'wrapscan'.
+--- (default: `true`)
+--- @field wrap? boolean
+---
+--- See |diagnostic-severity|.
+--- @field severity vim.diagnostic.Severity
+---
+--- If `true`, call |vim.diagnostic.open_float()| after moving.
+--- If a table, pass the table as the {opts} parameter to |vim.diagnostic.open_float()|.
+--- Unless overridden, the float will show diagnostics at the new cursor
+--- position (as if "cursor" were passed to the "scope" option).
+--- (default: `true`)
+--- @field float? boolean|vim.diagnostic.Opts.Float
+---
+--- Window ID
+--- (default: `0`)
+--- @field win_id? integer
+
--- Move to the next diagnostic.
---
----@param opts table|nil Configuration table with the following keys:
---- - namespace: (number) Only consider diagnostics from the given namespace.
---- - cursor_position: (cursor position) Cursor position as a (row, col) tuple.
---- See |nvim_win_get_cursor()|. Defaults to the current cursor position.
---- - wrap: (boolean, default true) Whether to loop around file or not. Similar to 'wrapscan'.
---- - severity: See |diagnostic-severity|.
---- - float: (boolean or table, default true) If "true", call |vim.diagnostic.open_float()|
---- after moving. If a table, pass the table as the {opts} parameter
---- to |vim.diagnostic.open_float()|. Unless overridden, the float will show
---- diagnostics at the new cursor position (as if "cursor" were passed to
---- the "scope" option).
---- - win_id: (number, default 0) Window ID
+---@param opts? vim.diagnostic.GotoOpts
function M.goto_next(opts)
- return diagnostic_move_pos(opts, M.get_next_pos(opts))
+ diagnostic_move_pos(opts, M.get_next_pos(opts))
end
M.handlers.signs = {
@@ -868,11 +1177,9 @@ M.handlers.signs = {
diagnostics = filter_by_severity(opts.signs.severity, diagnostics)
end
- define_default_signs()
-
-- 10 is the default sign priority when none is explicitly specified
local priority = opts.signs and opts.signs.priority or 10
- local get_priority
+ local get_priority --- @type function
if opts.severity_sort then
if type(opts.severity_sort) == 'table' and opts.severity_sort.reverse then
get_priority = function(severity)
@@ -890,22 +1197,85 @@ M.handlers.signs = {
end
local ns = M.get_namespace(namespace)
- if not ns.user_data.sign_group then
- ns.user_data.sign_group = string.format('vim.diagnostic.%s', ns.name)
+ if not ns.user_data.sign_ns then
+ ns.user_data.sign_ns =
+ api.nvim_create_namespace(string.format('%s/diagnostic/signs', ns.name))
end
- local sign_group = ns.user_data.sign_group
+ -- Handle legacy diagnostic sign definitions
+ -- These were deprecated in 0.10 and will be removed in 0.12
+ if opts.signs and not opts.signs.text and not opts.signs.numhl then
+ for _, v in ipairs({ 'Error', 'Warn', 'Info', 'Hint' }) do
+ local name = string.format('DiagnosticSign%s', v)
+ local sign = vim.fn.sign_getdefined(name)[1]
+ if sign then
+ local severity = M.severity[v:upper()]
+ vim.deprecate(
+ 'Defining diagnostic signs with :sign-define or sign_define()',
+ 'vim.diagnostic.config()',
+ '0.12',
+ nil,
+ false
+ )
+
+ if not opts.signs.text then
+ opts.signs.text = {}
+ end
+
+ if not opts.signs.numhl then
+ opts.signs.numhl = {}
+ end
+
+ if not opts.signs.linehl then
+ opts.signs.linehl = {}
+ end
+
+ if opts.signs.text[severity] == nil then
+ opts.signs.text[severity] = sign.text or ''
+ end
+
+ if opts.signs.numhl[severity] == nil then
+ opts.signs.numhl[severity] = sign.numhl
+ end
+
+ if opts.signs.linehl[severity] == nil then
+ opts.signs.linehl[severity] = sign.linehl
+ end
+ end
+ end
+ end
+
+ local text = {} ---@type table<vim.diagnostic.Severity|string, string>
+ for k in pairs(M.severity) do
+ if opts.signs.text and opts.signs.text[k] then
+ text[k] = opts.signs.text[k]
+ elseif type(k) == 'string' and not text[k] then
+ text[k] = string.sub(k, 1, 1):upper()
+ end
+ end
+
+ local numhl = opts.signs.numhl or {}
+ local linehl = opts.signs.linehl or {}
+
for _, diagnostic in ipairs(diagnostics) do
- vim.fn.sign_place(0, sign_group, sign_highlight_map[diagnostic.severity], bufnr, {
- priority = get_priority(diagnostic.severity),
- lnum = diagnostic.lnum + 1,
- })
+ if api.nvim_buf_is_loaded(diagnostic.bufnr) then
+ api.nvim_buf_set_extmark(bufnr, ns.user_data.sign_ns, diagnostic.lnum, 0, {
+ sign_text = text[diagnostic.severity] or text[M.severity[diagnostic.severity]] or 'U',
+ sign_hl_group = sign_highlight_map[diagnostic.severity],
+ number_hl_group = numhl[diagnostic.severity],
+ line_hl_group = linehl[diagnostic.severity],
+ priority = get_priority(diagnostic.severity),
+ })
+ end
end
end,
+
+ --- @param namespace integer
+ --- @param bufnr integer
hide = function(namespace, bufnr)
local ns = M.get_namespace(namespace)
- if ns.user_data.sign_group and api.nvim_buf_is_valid(bufnr) then
- vim.fn.sign_unplace(ns.user_data.sign_group, { buffer = bufnr })
+ if ns.user_data.sign_ns and api.nvim_buf_is_valid(bufnr) then
+ api.nvim_buf_clear_namespace(bufnr, ns.user_data.sign_ns, 0, -1)
end
end,
}
@@ -936,15 +1306,18 @@ M.handlers.underline = {
local ns = M.get_namespace(namespace)
if not ns.user_data.underline_ns then
- ns.user_data.underline_ns = api.nvim_create_namespace('')
+ ns.user_data.underline_ns =
+ api.nvim_create_namespace(string.format('%s/diagnostic/underline', ns.name))
end
local underline_ns = ns.user_data.underline_ns
for _, diagnostic in ipairs(diagnostics) do
- local higroup = underline_highlight_map[diagnostic.severity]
+ --- @type string?
+ local higroup = underline_highlight_map[assert(diagnostic.severity)]
if higroup == nil then
-- Default to error if we don't have a highlight associated
+ -- TODO(lewis6991): this is always nil since underline_highlight_map only has integer keys
higroup = underline_highlight_map.Error
end
@@ -1000,7 +1373,7 @@ M.handlers.virtual_text = {
return
end
- local severity
+ local severity --- @type vim.diagnostic.SeverityFilter?
if opts.virtual_text then
if opts.virtual_text.format then
diagnostics = reformat_diagnostics(opts.virtual_text.format, diagnostics)
@@ -1018,7 +1391,8 @@ M.handlers.virtual_text = {
local ns = M.get_namespace(namespace)
if not ns.user_data.virt_text_ns then
- ns.user_data.virt_text_ns = api.nvim_create_namespace('')
+ ns.user_data.virt_text_ns =
+ api.nvim_create_namespace(string.format('%s/diagnostic/virtual_text', ns.name))
end
local virt_text_ns = ns.user_data.virt_text_ns
@@ -1057,7 +1431,9 @@ M.handlers.virtual_text = {
--- Exported for backward compatibility with
--- vim.lsp.diagnostic.get_virtual_text_chunks_for_line(). When that function is eventually removed,
--- this can be made local.
----@private
+--- @private
+--- @param line_diags table<integer,vim.Diagnostic>
+--- @param opts vim.diagnostic.Opts.VirtualText
function M._get_virt_text_chunks(line_diags, opts)
if #line_diags == 0 then
return nil
@@ -1107,10 +1483,10 @@ end
--- To hide diagnostics and prevent them from re-displaying, use
--- |vim.diagnostic.disable()|.
---
----@param namespace integer|nil Diagnostic namespace. When omitted, hide
---- diagnostics from all namespaces.
----@param bufnr integer|nil Buffer number, or 0 for current buffer. When
---- omitted, hide diagnostics in all buffers.
+---@param namespace integer? Diagnostic namespace. When omitted, hide
+--- diagnostics from all namespaces.
+---@param bufnr integer? Buffer number, or 0 for current buffer. When
+--- omitted, hide diagnostics in all buffers.
function M.hide(namespace, bufnr)
vim.validate({
namespace = { namespace, 'n', true },
@@ -1132,11 +1508,11 @@ end
--- Check whether diagnostics are disabled in a given buffer.
---
----@param bufnr integer|nil Buffer number, or 0 for current buffer.
----@param namespace integer|nil Diagnostic namespace. When omitted, checks if
---- all diagnostics are disabled in {bufnr}.
---- Otherwise, only checks if diagnostics from
---- {namespace} are disabled.
+---@param bufnr integer? Buffer number, or 0 for current buffer.
+---@param namespace integer? Diagnostic namespace. When omitted, checks if
+--- all diagnostics are disabled in {bufnr}.
+--- Otherwise, only checks if diagnostics from
+--- {namespace} are disabled.
---@return boolean
function M.is_disabled(bufnr, namespace)
bufnr = get_bufnr(bufnr)
@@ -1153,17 +1529,17 @@ end
--- Display diagnostics for the given namespace and buffer.
---
----@param namespace integer|nil Diagnostic namespace. When omitted, show
---- diagnostics from all namespaces.
----@param bufnr integer|nil Buffer number, or 0 for current buffer. When omitted, show
---- diagnostics in all buffers.
----@param diagnostics table|nil The diagnostics to display. When omitted, use the
+---@param namespace integer? Diagnostic namespace. When omitted, show
+--- diagnostics from all namespaces.
+---@param bufnr integer? Buffer number, or 0 for current buffer. When omitted, show
+--- diagnostics in all buffers.
+---@param diagnostics vim.Diagnostic[]? The diagnostics to display. When omitted, use the
--- saved diagnostics for the given namespace and
--- buffer. This can be used to display a list of diagnostics
--- without saving them or to display only a subset of
--- diagnostics. May not be used when {namespace}
--- or {bufnr} is nil.
----@param opts table|nil Display options. See |vim.diagnostic.config()|.
+---@param opts? vim.diagnostic.Opts Display options.
function M.show(namespace, bufnr, diagnostics, opts)
vim.validate({
namespace = { namespace, 'n', true },
@@ -1202,24 +1578,24 @@ function M.show(namespace, bufnr, diagnostics, opts)
diagnostics = diagnostics or get_diagnostics(bufnr, { namespace = namespace }, true)
- if not diagnostics or vim.tbl_isempty(diagnostics) then
+ if vim.tbl_isempty(diagnostics) then
return
end
- opts = get_resolved_options(opts, namespace, bufnr)
+ local opts_res = get_resolved_options(opts, namespace, bufnr)
- if opts.update_in_insert then
+ if opts_res.update_in_insert then
clear_scheduled_display(namespace, bufnr)
else
local mode = api.nvim_get_mode()
if string.sub(mode.mode, 1, 1) == 'i' then
- schedule_display(namespace, bufnr, opts)
+ schedule_display(namespace, bufnr, opts_res)
return
end
end
- if vim.F.if_nil(opts.severity_sort, false) then
- if type(opts.severity_sort) == 'table' and opts.severity_sort.reverse then
+ if if_nil(opts_res.severity_sort, false) then
+ if type(opts_res.severity_sort) == 'table' and opts_res.severity_sort.reverse then
table.sort(diagnostics, function(a, b)
return a.severity < b.severity
end)
@@ -1231,61 +1607,23 @@ function M.show(namespace, bufnr, diagnostics, opts)
end
for handler_name, handler in pairs(M.handlers) do
- if handler.show and opts[handler_name] then
- handler.show(namespace, bufnr, diagnostics, opts)
+ if handler.show and opts_res[handler_name] then
+ handler.show(namespace, bufnr, diagnostics, opts_res)
end
end
end
--- Show diagnostics in a floating window.
---
----@param opts table|nil Configuration table with the same keys
---- as |vim.lsp.util.open_floating_preview()| in addition to the following:
---- - bufnr: (number) Buffer number to show diagnostics from.
---- Defaults to the current buffer.
---- - namespace: (number) Limit diagnostics to the given namespace
---- - scope: (string, default "line") Show diagnostics from the whole buffer ("buffer"),
---- the current cursor line ("line"), or the current cursor position ("cursor").
---- Shorthand versions are also accepted ("c" for "cursor", "l" for "line", "b"
---- for "buffer").
---- - pos: (number or table) If {scope} is "line" or "cursor", use this position rather
---- than the cursor position. If a number, interpreted as a line number;
---- otherwise, a (row, col) tuple.
---- - severity_sort: (default false) Sort diagnostics by severity. Overrides the setting
---- from |vim.diagnostic.config()|.
---- - severity: See |diagnostic-severity|. Overrides the setting
---- from |vim.diagnostic.config()|.
---- - header: (string or table) String to use as the header for the floating window. If a
---- table, it is interpreted as a [text, hl_group] tuple. Overrides the setting
---- from |vim.diagnostic.config()|.
---- - source: (boolean or string) Include the diagnostic source in the message.
---- Use "if_many" to only show sources if there is more than one source of
---- diagnostics in the buffer. Otherwise, any truthy value means to always show
---- the diagnostic source. Overrides the setting from |vim.diagnostic.config()|.
---- - format: (function) A function that takes a diagnostic as input and returns a
---- string. The return value is the text used to display the diagnostic.
---- Overrides the setting from |vim.diagnostic.config()|.
---- - prefix: (function, string, or table) Prefix each diagnostic in the floating
---- window. If a function, it must have the signature (diagnostic, i,
---- total) -> (string, string), where {i} is the index of the diagnostic
---- being evaluated and {total} is the total number of diagnostics
---- displayed in the window. The function should return a string which
---- is prepended to each diagnostic in the window as well as an
---- (optional) highlight group which will be used to highlight the
---- prefix. If {prefix} is a table, it is interpreted as a [text,
---- hl_group] tuple as in |nvim_echo()|; otherwise, if {prefix} is a
---- string, it is prepended to each diagnostic in the window with no
---- highlight.
---- Overrides the setting from |vim.diagnostic.config()|.
---- - suffix: Same as {prefix}, but appends the text to the diagnostic instead of
---- prepending it. Overrides the setting from |vim.diagnostic.config()|.
----@return integer|nil, integer|nil: ({float_bufnr}, {win_id})
+---@param opts vim.diagnostic.Opts.Float?
+---@return integer? float_bufnr
+---@return integer? win_id
function M.open_float(opts, ...)
-- Support old (bufnr, opts) signature
- local bufnr
+ local bufnr --- @type integer?
if opts == nil or type(opts) == 'number' then
bufnr = opts
- opts = ...
+ opts = ... --- @type vim.diagnostic.Opts.Float
else
vim.validate({
opts = { opts, 't', true },
@@ -1307,16 +1645,17 @@ function M.open_float(opts, ...)
end
local scope = ({ l = 'line', c = 'cursor', b = 'buffer' })[opts.scope] or opts.scope or 'line'
- local lnum, col
+ local lnum, col --- @type integer, integer
+ local opts_pos = opts.pos
if scope == 'line' or scope == 'cursor' then
- if not opts.pos then
+ if not opts_pos then
local pos = api.nvim_win_get_cursor(0)
lnum = pos[1] - 1
col = pos[2]
- elseif type(opts.pos) == 'number' then
- lnum = opts.pos
- elseif type(opts.pos) == 'table' then
- lnum, col = unpack(opts.pos)
+ elseif type(opts_pos) == 'number' then
+ lnum = opts_pos
+ elseif type(opts_pos) == 'table' then
+ lnum, col = opts_pos[1], opts_pos[2]
else
error("Invalid value for option 'pos'")
end
@@ -1324,15 +1663,17 @@ function M.open_float(opts, ...)
error("Invalid value for option 'scope'")
end
- local diagnostics = get_diagnostics(bufnr, opts, true)
+ local diagnostics = get_diagnostics(bufnr, opts --[[@as vim.diagnostic.GetOpts]], true)
if scope == 'line' then
+ --- @param d vim.Diagnostic
diagnostics = vim.tbl_filter(function(d)
return d.lnum == lnum
end, diagnostics)
elseif scope == 'cursor' then
-- LSP servers can send diagnostics with `end_col` past the length of the line
local line_length = #api.nvim_buf_get_lines(bufnr, lnum, lnum + 1, true)[1]
+ --- @param d vim.Diagnostic
diagnostics = vim.tbl_filter(function(d)
return d.lnum == lnum
and math.min(d.col, line_length - 1) <= col
@@ -1344,7 +1685,7 @@ function M.open_float(opts, ...)
return
end
- local severity_sort = vim.F.if_nil(opts.severity_sort, global_diagnostic_options.severity_sort)
+ local severity_sort = if_nil(opts.severity_sort, global_diagnostic_options.severity_sort)
if severity_sort then
if type(severity_sort) == 'table' and severity_sort.reverse then
table.sort(diagnostics, function(a, b)
@@ -1357,8 +1698,8 @@ function M.open_float(opts, ...)
end
end
- local lines = {}
- local highlights = {}
+ local lines = {} --- @type string[]
+ local highlights = {} --- @type table[]
local header = if_nil(opts.header, 'Diagnostics:')
if header then
vim.validate({
@@ -1393,7 +1734,7 @@ function M.open_float(opts, ...)
return string.format('%d. ', i)
end)
- local prefix, prefix_hl_group
+ local prefix, prefix_hl_group --- @type string?, string?
if prefix_opt then
vim.validate({
prefix = {
@@ -1413,7 +1754,7 @@ function M.open_float(opts, ...)
return diagnostic.code and string.format(' [%s]', diagnostic.code) or ''
end)
- local suffix, suffix_hl_group
+ local suffix, suffix_hl_group --- @type string?, string?
if suffix_opt then
vim.validate({
suffix = {
@@ -1430,15 +1771,18 @@ function M.open_float(opts, ...)
end
for i, diagnostic in ipairs(diagnostics) do
- if prefix_opt and type(prefix_opt) == 'function' then
- prefix, prefix_hl_group = prefix_opt(diagnostic, i, #diagnostics)
- prefix, prefix_hl_group = prefix or '', prefix_hl_group or 'NormalFloat'
+ if type(prefix_opt) == 'function' then
+ --- @cast prefix_opt fun(...): string?, string?
+ local prefix0, prefix_hl_group0 = prefix_opt(diagnostic, i, #diagnostics)
+ prefix, prefix_hl_group = prefix0 or '', prefix_hl_group0 or 'NormalFloat'
end
- if suffix_opt and type(suffix_opt) == 'function' then
- suffix, suffix_hl_group = suffix_opt(diagnostic, i, #diagnostics)
- suffix, suffix_hl_group = suffix or '', suffix_hl_group or 'NormalFloat'
+ if type(suffix_opt) == 'function' then
+ --- @cast suffix_opt fun(...): string?, string?
+ local suffix0, suffix_hl_group0 = suffix_opt(diagnostic, i, #diagnostics)
+ suffix, suffix_hl_group = suffix0 or '', suffix_hl_group0 or 'NormalFloat'
end
- local hiname = floating_highlight_map[diagnostic.severity]
+ --- @type string?
+ local hiname = floating_highlight_map[assert(diagnostic.severity)]
local message_lines = vim.split(diagnostic.message, '\n')
for j = 1, #message_lines do
local pre = j == 1 and prefix or string.rep(' ', #prefix)
@@ -1462,7 +1806,7 @@ function M.open_float(opts, ...)
if not opts.focus_id then
opts.focus_id = scope
end
- local float_bufnr, winnr = require('vim.lsp.util').open_floating_preview(lines, 'plaintext', opts)
+ local float_bufnr, winnr = vim.lsp.util.open_floating_preview(lines, 'plaintext', opts)
for i, hl in ipairs(highlights) do
local line = lines[i]
local prefix_len = hl.prefix and hl.prefix.length or 0
@@ -1486,10 +1830,10 @@ end
--- simply remove diagnostic decorations in a way that they can be
--- re-displayed, use |vim.diagnostic.hide()|.
---
----@param namespace integer|nil Diagnostic namespace. When omitted, remove
---- diagnostics from all namespaces.
----@param bufnr integer|nil Remove diagnostics for the given buffer. When omitted,
---- diagnostics are removed for all buffers.
+---@param namespace integer? Diagnostic namespace. When omitted, remove
+--- diagnostics from all namespaces.
+---@param bufnr integer? Remove diagnostics for the given buffer. When omitted,
+--- diagnostics are removed for all buffers.
function M.reset(namespace, bufnr)
vim.validate({
namespace = { namespace, 'n', true },
@@ -1516,34 +1860,63 @@ function M.reset(namespace, bufnr)
end
end
+--- Configuration table with the following keys:
+--- @class vim.diagnostic.setqflist.Opts
+--- @inlinedoc
+---
+--- Only add diagnostics from the given namespace.
+--- @field namespace? integer
+---
+--- Open quickfix list after setting.
+--- (default: `true`)
+--- @field open? boolean
+---
+--- Title of quickfix list. Defaults to "Diagnostics".
+--- @field title? string
+---
+--- See |diagnostic-severity|.
+--- @field severity? vim.diagnostic.Severity
+
--- Add all diagnostics to the quickfix list.
---
----@param opts table|nil Configuration table with the following keys:
---- - namespace: (number) Only add diagnostics from the given namespace.
---- - open: (boolean, default true) Open quickfix list after setting.
---- - title: (string) Title of quickfix list. Defaults to "Diagnostics".
---- - severity: See |diagnostic-severity|.
+---@param opts? vim.diagnostic.setqflist.Opts
function M.setqflist(opts)
set_list(false, opts)
end
+---Configuration table with the following keys:
+--- @class vim.diagnostic.setloclist.Opts
+--- @inlinedoc
+---
+--- Only add diagnostics from the given namespace.
+--- @field namespace? integer
+---
+--- Window number to set location list for.
+--- (default: `0`)
+--- @field winnr? integer
+---
+--- Open the location list after setting.
+--- (default: `true`)
+--- @field open? boolean
+---
+--- Title of the location list. Defaults to "Diagnostics".
+--- @field title? string
+---
+--- See |diagnostic-severity|.
+--- @field severity? vim.diagnostic.Severity
+
--- Add buffer diagnostics to the location list.
---
----@param opts table|nil Configuration table with the following keys:
---- - namespace: (number) Only add diagnostics from the given namespace.
---- - winnr: (number, default 0) Window number to set location list for.
---- - open: (boolean, default true) Open the location list after setting.
---- - title: (string) Title of the location list. Defaults to "Diagnostics".
---- - severity: See |diagnostic-severity|.
+---@param opts? vim.diagnostic.setloclist.Opts
function M.setloclist(opts)
set_list(true, opts)
end
--- Disable diagnostics in the given buffer.
---
----@param bufnr integer|nil Buffer number, or 0 for current buffer. When
---- omitted, disable diagnostics in all buffers.
----@param namespace integer|nil Only disable diagnostics for the given namespace.
+---@param bufnr integer? Buffer number, or 0 for current buffer. When
+--- omitted, disable diagnostics in all buffers.
+---@param namespace integer? Only disable diagnostics for the given namespace.
function M.disable(bufnr, namespace)
vim.validate({ bufnr = { bufnr, 'n', true }, namespace = { namespace, 'n', true } })
if bufnr == nil then
@@ -1578,9 +1951,9 @@ end
--- Enable diagnostics in the given buffer.
---
----@param bufnr integer|nil Buffer number, or 0 for current buffer. When
---- omitted, enable diagnostics in all buffers.
----@param namespace integer|nil Only enable diagnostics for the given namespace.
+---@param bufnr integer? Buffer number, or 0 for current buffer. When
+--- omitted, enable diagnostics in all buffers.
+---@param namespace integer? Only enable diagnostics for the given namespace.
function M.enable(bufnr, namespace)
vim.validate({ bufnr = { bufnr, 'n', true }, namespace = { namespace, 'n', true } })
if bufnr == nil then
@@ -1614,8 +1987,7 @@ end
--- WARNING filename:27:3: Variable 'foo' does not exist
--- ```
---
---- This can be parsed into a diagnostic |diagnostic-structure|
---- with:
+--- This can be parsed into |vim.Diagnostic| structure with:
---
--- ```lua
--- local s = "WARNING filename:27:3: Variable 'foo' does not exist"
@@ -1626,14 +1998,14 @@ end
---
---@param str string String to parse diagnostics from.
---@param pat string Lua pattern with capture groups.
----@param groups table List of fields in a |diagnostic-structure| to
+---@param groups string[] List of fields in a |vim.Diagnostic| structure to
--- associate with captures from {pat}.
---@param severity_map table A table mapping the severity field from {groups}
--- with an item from |vim.diagnostic.severity|.
----@param defaults table|nil Table of default values for any fields not listed in {groups}.
---- When omitted, numeric values default to 0 and "severity" defaults to
---- ERROR.
----@return Diagnostic|nil: |diagnostic-structure| or `nil` if {pat} fails to match {str}.
+---@param defaults table? Table of default values for any fields not listed in {groups}.
+--- When omitted, numeric values default to 0 and "severity" defaults to
+--- ERROR.
+---@return vim.Diagnostic?: |vim.Diagnostic| structure or `nil` if {pat} fails to match {str}.
function M.match(str, pat, groups, severity_map, defaults)
vim.validate({
str = { str, 's' },
@@ -1643,14 +2015,16 @@ function M.match(str, pat, groups, severity_map, defaults)
defaults = { defaults, 't', true },
})
+ --- @type table<string,vim.diagnostic.Severity>
severity_map = severity_map or M.severity
- local diagnostic = {}
- local matches = { string.match(str, pat) }
+ local matches = { str:match(pat) } --- @type any[]
if vim.tbl_isempty(matches) then
return
end
+ local diagnostic = {} --- @type type<string,any>
+
for i, match in ipairs(matches) do
local field = groups[i]
if field == 'severity' then
@@ -1658,10 +2032,10 @@ function M.match(str, pat, groups, severity_map, defaults)
elseif field == 'lnum' or field == 'end_lnum' or field == 'col' or field == 'end_col' then
match = assert(tonumber(match)) - 1
end
- diagnostic[field] = match
+ diagnostic[field] = match --- @type any
end
- diagnostic = vim.tbl_extend('keep', diagnostic, defaults or {})
+ diagnostic = vim.tbl_extend('keep', diagnostic, defaults or {}) --- @type vim.Diagnostic
diagnostic.severity = diagnostic.severity or M.severity.ERROR
diagnostic.col = diagnostic.col or 0
diagnostic.end_lnum = diagnostic.end_lnum or diagnostic.lnum
@@ -1679,8 +2053,8 @@ local errlist_type_map = {
--- Convert a list of diagnostics to a list of quickfix items that can be
--- passed to |setqflist()| or |setloclist()|.
---
----@param diagnostics table List of diagnostics |diagnostic-structure|.
----@return table[] of quickfix list items |setqflist-what|
+---@param diagnostics vim.Diagnostic[]
+---@return table[] : Quickfix list items |setqflist-what|
function M.toqflist(diagnostics)
vim.validate({
diagnostics = {
@@ -1690,7 +2064,7 @@ function M.toqflist(diagnostics)
},
})
- local list = {}
+ local list = {} --- @type table[]
for _, v in ipairs(diagnostics) do
local item = {
bufnr = v.bufnr,
@@ -1720,7 +2094,7 @@ end
--- Convert a list of quickfix items to a list of diagnostics.
---
---@param list table[] List of quickfix items from |getqflist()| or |getloclist()|.
----@return Diagnostic[] array of |diagnostic-structure|
+---@return vim.Diagnostic[]
function M.fromqflist(list)
vim.validate({
list = {
@@ -1730,7 +2104,7 @@ function M.fromqflist(list)
},
})
- local diagnostics = {}
+ local diagnostics = {} --- @type vim.Diagnostic[]
for _, item in ipairs(list) do
if item.valid == 1 then
local lnum = math.max(0, item.lnum - 1)
@@ -1738,7 +2112,7 @@ function M.fromqflist(list)
local end_lnum = item.end_lnum > 0 and (item.end_lnum - 1) or lnum
local end_col = item.end_col > 0 and (item.end_col - 1) or col
local severity = item.type ~= '' and M.severity[item.type] or M.severity.ERROR
- table.insert(diagnostics, {
+ diagnostics[#diagnostics + 1] = {
bufnr = item.bufnr,
lnum = lnum,
col = col,
@@ -1746,7 +2120,7 @@ function M.fromqflist(list)
end_col = end_col,
severity = severity,
message = item.text,
- })
+ }
end
end
return diagnostics
diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua
index c6200f16bb..fba76f93b2 100644
--- a/runtime/lua/vim/filetype.lua
+++ b/runtime/lua/vim/filetype.lua
@@ -267,6 +267,7 @@ local extension = {
crdpro = 'chordpro',
cho = 'chordpro',
chordpro = 'chordpro',
+ ck = 'chuck',
eni = 'cl',
icl = 'clean',
cljx = 'clojure',
@@ -341,7 +342,7 @@ local extension = {
decl = detect.decl,
dec = detect.decl,
dcl = detect_seq(detect.decl, 'clean'),
- def = 'def',
+ def = detect.def,
desc = 'desc',
directory = 'desktop',
desktop = 'desktop',
@@ -363,6 +364,8 @@ local extension = {
d = detect.dtrace,
dts = 'dts',
dtsi = 'dts',
+ dtso = 'dts',
+ its = 'dts',
dylan = 'dylan',
intr = 'dylanintr',
lid = 'dylanlid',
@@ -674,8 +677,6 @@ local extension = {
mmp = 'mmp',
mms = detect.mms,
DEF = 'modula2',
- m2 = 'modula2',
- mi = 'modula2',
lm3 = 'modula3',
mojo = 'mojo',
['🔥'] = 'mojo', -- 🙄
@@ -695,6 +696,7 @@ local extension = {
msql = 'msql',
mu = 'mupad',
mush = 'mush',
+ mustache = 'mustache',
mysql = 'mysql',
n1ql = 'n1ql',
nql = 'n1ql',
@@ -908,6 +910,7 @@ local extension = {
sed = 'sed',
sexp = 'sexplib',
bash = detect.bash,
+ bats = detect.bash,
ebuild = detect.bash,
eclass = detect.bash,
env = detect.sh,
@@ -1341,10 +1344,12 @@ local filename = {
['.hintrc'] = 'jsonc',
['.jsfmtrc'] = 'jsonc',
['.jshintrc'] = 'jsonc',
+ ['.luaurc'] = 'jsonc',
['.swrc'] = 'jsonc',
['.justfile'] = 'just',
Kconfig = 'kconfig',
['Kconfig.debug'] = 'kconfig',
+ ['Config.in'] = 'kconfig',
['lftp.conf'] = 'lftp',
['.lftprc'] = 'lftp',
['/.libao'] = 'libao',
@@ -1393,6 +1398,7 @@ local filename = {
octaverc = 'octave',
['octave.conf'] = 'octave',
opam = 'opam',
+ ['pacman.log'] = 'pacmanlog',
['/etc/pam.conf'] = 'pamconf',
['pam_env.conf'] = 'pamenv',
['.pam_environment'] = 'pamenv',
@@ -1654,6 +1660,11 @@ local pattern = {
['.*/dtrace/.*%.d'] = 'dtrace',
['.*esmtprc'] = 'esmtprc',
['.*Eterm/.*%.cfg'] = 'eterm',
+ ['.*s6.*/up'] = 'execline',
+ ['.*s6.*/down'] = 'execline',
+ ['.*s6.*/run'] = 'execline',
+ ['.*s6.*/finish'] = 'execline',
+ ['s6%-.*'] = 'execline',
['[a-zA-Z0-9].*Dict'] = detect.foam,
['[a-zA-Z0-9].*Dict%..*'] = detect.foam,
['[a-zA-Z].*Properties'] = detect.foam,
@@ -1730,6 +1741,7 @@ local pattern = {
['[jt]sconfig.*%.json'] = 'jsonc',
['[jJ]ustfile'] = 'just',
['Kconfig%..*'] = starsetf('kconfig'),
+ ['Config%.in%..*'] = starsetf('kconfig'),
['.*%.[Ss][Uu][Bb]'] = 'krl',
['lilo%.conf.*'] = starsetf('lilo'),
['.*/etc/logcheck/.*%.d.*/.*'] = starsetf('logcheck'),
@@ -1903,7 +1915,7 @@ local pattern = {
['.*baseq[2-3]/.*%.cfg'] = 'quake',
['.*quake[1-3]/.*%.cfg'] = 'quake',
['.*id1/.*%.cfg'] = 'quake',
- ['.*/queries/.*%.scm'] = 'query', -- tree-sitter queries (Neovim only)
+ ['.*/queries/.*%.scm'] = 'query', -- treesitter queries (Neovim only)
['.*,v'] = 'rcs',
['%.reminders.*'] = starsetf('remind'),
['[rR]akefile.*'] = starsetf('ruby'),
@@ -2070,6 +2082,7 @@ local function normalize_path(path, as_pattern)
end
--- @class vim.filetype.add.filetypes
+--- @inlinedoc
--- @field pattern? vim.filetype.mapping
--- @field extension? vim.filetype.mapping
--- @field filename? vim.filetype.mapping
@@ -2260,16 +2273,31 @@ local function match_pattern(name, path, tail, pat)
end
--- @class vim.filetype.match.args
+--- @inlinedoc
+---
+--- Buffer number to use for matching. Mutually exclusive with {contents}
--- @field buf? integer
+---
+--- Filename to use for matching. When {buf} is given,
+--- defaults to the filename of the given buffer number. The
+--- file need not actually exist in the filesystem. When used
+--- without {buf} only the name of the file is used for
+--- filetype matching. This may result in failure to detect
+--- the filetype in cases where the filename alone is not
+--- enough to disambiguate the filetype.
--- @field filename? string
+---
+--- An array of lines representing file contents to use for
+--- matching. Can be used with {filename}. Mutually exclusive
+--- with {buf}.
--- @field contents? string[]
--- Perform filetype detection.
---
--- The filetype can be detected using one of three methods:
---- 1. Using an existing buffer
---- 2. Using only a file name
---- 3. Using only file contents
+--- 1. Using an existing buffer
+--- 2. Using only a file name
+--- 3. Using only file contents
---
--- Of these, option 1 provides the most accurate result as it uses both the buffer's filename and
--- (optionally) the buffer contents. Options 2 and 3 can be used without an existing buffer, but
@@ -2295,18 +2323,6 @@ end
---
---@param args vim.filetype.match.args Table specifying which matching strategy to use.
--- Accepted keys are:
---- * buf (number): Buffer number to use for matching. Mutually exclusive with
---- {contents}
---- * filename (string): Filename to use for matching. When {buf} is given,
---- defaults to the filename of the given buffer number. The
---- file need not actually exist in the filesystem. When used
---- without {buf} only the name of the file is used for
---- filetype matching. This may result in failure to detect
---- the filetype in cases where the filename alone is not
---- enough to disambiguate the filetype.
---- * contents (table): An array of lines representing file contents to use for
---- matching. Can be used with {filename}. Mutually exclusive
---- with {buf}.
---@return string|nil # If a match was found, the matched filetype.
---@return function|nil # A function that modifies buffer state when called (for example, to set some
--- filetype specific buffer variables). The function accepts a buffer number as
diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua
index 9d0f1bd3ab..3db4f2bcdc 100644
--- a/runtime/lua/vim/filetype/detect.lua
+++ b/runtime/lua/vim/filetype/detect.lua
@@ -419,6 +419,55 @@ function M.dtrace(_, bufnr)
return 'd'
end
+--- @param bufnr integer
+--- @return boolean
+local function is_modula2(bufnr)
+ return matchregex(nextnonblank(bufnr, 1), [[\<MODULE\s\+\w\+\s*\%(\[.*]\s*\)\=;\|^\s*(\*]])
+end
+
+--- @param bufnr integer
+--- @return string, fun(b: integer)
+local function modula2(bufnr)
+ local dialect = vim.g.modula2_default_dialect or 'pim'
+ local extension = vim.g.modula2_default_extension or ''
+
+ -- ignore unknown dialects or badly formatted tags
+ for _, line in ipairs(getlines(bufnr, 1, 200)) do
+ local matched_dialect, matched_extension = line:match('%(%*!m2(%w+)%+(%w+)%*%)')
+ if not matched_dialect then
+ matched_dialect = line:match('%(%*!m2(%w+)%*%)')
+ end
+ if matched_dialect then
+ if vim.tbl_contains({ 'iso', 'pim', 'r10' }, matched_dialect) then
+ dialect = matched_dialect
+ end
+ if vim.tbl_contains({ 'gm2' }, matched_extension) then
+ extension = matched_extension
+ end
+ break
+ end
+ end
+
+ return 'modula2',
+ function(b)
+ vim.api.nvim_buf_call(b, function()
+ fn['modula2#SetDialect'](dialect, extension)
+ end)
+ end
+end
+
+--- @type vim.filetype.mapfn
+function M.def(_, bufnr)
+ if vim.g.filetype_def == 'modula2' or is_modula2(bufnr) then
+ return modula2(bufnr)
+ end
+
+ if vim.g.filetype_def then
+ return vim.g.filetype_def
+ end
+ return 'def'
+end
+
--- @type vim.filetype.mapfn
function M.e(_, bufnr)
if vim.g.filetype_euphoria then
@@ -906,14 +955,16 @@ end
--- Determine if *.mod is ABB RAPID, LambdaProlog, Modula-2, Modsim III or go.mod
--- @type vim.filetype.mapfn
function M.mod(path, bufnr)
+ if vim.g.filetype_mod == 'modula2' or is_modula2(bufnr) then
+ return modula2(bufnr)
+ end
+
if vim.g.filetype_mod then
return vim.g.filetype_mod
elseif matchregex(path, [[\c\<go\.mod$]]) then
return 'gomod'
elseif is_lprolog(bufnr) then
return 'lprolog'
- elseif matchregex(nextnonblank(bufnr, 1), [[\%(\<MODULE\s\+\w\+\s*;\|^\s*(\*\)]]) then
- return 'modula2'
elseif is_rapid(bufnr) then
return 'rapid'
end
@@ -1530,12 +1581,26 @@ function M.v(_, bufnr)
-- Filetype was already detected
return
end
+ if vim.g.filetype_v then
+ return vim.g.filetype_v
+ end
+ local in_comment = 0
for _, line in ipairs(getlines(bufnr, 1, 200)) do
- if not line:find('^%s*/') then
- if findany(line, { ';%s*$', ';%s*/' }) then
- return 'verilog'
- elseif findany(line, { '%.%s*$', '%.%s*%(%*' }) then
+ if line:find('^%s*/%*') then
+ in_comment = 1
+ end
+ if in_comment == 1 then
+ if line:find('%*/') then
+ in_comment = 0
+ end
+ elseif not line:find('^%s*//') then
+ if
+ line:find('%.%s*$') and not line:find('/[/*]')
+ or line:find('%(%*') and not line:find('/[/*].*%(%*')
+ then
return 'coq'
+ elseif findany(line, { ';%s*$', ';%s*/[/*]' }) then
+ return 'verilog'
end
end
end
@@ -1661,6 +1726,7 @@ local patterns_hashbang = {
['^\\%(rexx\\|regina\\)\\>'] = { 'rexx', { vim_regex = true } },
['^janet\\>'] = { 'janet', { vim_regex = true } },
['^dart\\>'] = { 'dart', { vim_regex = true } },
+ ['^execlineb\\>'] = { 'execline', { vim_regex = true } },
}
---@private
diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua
index 22612a7255..f9fe122f01 100644
--- a/runtime/lua/vim/fs.lua
+++ b/runtime/lua/vim/fs.lua
@@ -39,8 +39,9 @@ end
--- Return the parent directory of the given path
---
----@param file (string) Path
----@return string|nil Parent directory of {file}
+---@generic T : string|nil
+---@param file T Path
+---@return T Parent directory of {file}
function M.dirname(file)
if file == nil then
return nil
@@ -53,6 +54,7 @@ function M.dirname(file)
elseif file == '/' or file:match('^/[^/]+$') then
return '/'
end
+ ---@type string
local dir = file:match('[/\\]$') and file:sub(1, #file - 1) or file:match('^([/\\]?.+)[/\\]')
if iswin and dir:match('^%w:$') then
return dir .. '/'
@@ -62,8 +64,9 @@ end
--- Return the basename of the given path
---
----@param file string Path
----@return string|nil Basename of {file}
+---@generic T : string|nil
+---@param file T Path
+---@return T Basename of {file}
function M.basename(file)
if file == nil then
return nil
@@ -147,12 +150,30 @@ function M.dir(path, opts)
end)
end
---- @class vim.fs.find.opts
---- @field path string
---- @field upward boolean
---- @field stop string
---- @field type string
---- @field limit number
+--- @class vim.fs.find.Opts
+--- @inlinedoc
+---
+--- Path to begin searching from. If
+--- omitted, the |current-directory| is used.
+--- @field path? string
+---
+--- Search upward through parent directories.
+--- Otherwise, search through child directories (recursively).
+--- (default: `false`)
+--- @field upward? boolean
+---
+--- Stop searching when this directory is reached.
+--- The directory itself is not searched.
+--- @field stop? string
+---
+--- Find only items of the given type.
+--- If omitted, all items that match {names} are included.
+--- @field type? string
+---
+--- Stop the search after finding this many matches.
+--- Use `math.huge` to place no limit on the number of matches.
+--- (default: `1`)
+--- @field limit? number
--- Find files or directories (or other items as specified by `opts.type`) in the given path.
---
@@ -194,23 +215,10 @@ end
--- - path: full path of the current item
--- The function should return `true` if the given item is considered a match.
---
----@param opts (table) Optional keyword arguments:
---- - path (string): Path to begin searching from. If
---- omitted, the |current-directory| is used.
---- - upward (boolean, default false): If true, search
---- upward through parent directories. Otherwise,
---- search through child directories
---- (recursively).
---- - stop (string): Stop searching when this directory is
---- reached. The directory itself is not searched.
---- - type (string): Find only items of the given type.
---- If omitted, all items that match {names} are included.
---- - limit (number, default 1): Stop the search after
---- finding this many matches. Use `math.huge` to
---- place no limit on the number of matches.
+---@param opts vim.fs.find.Opts Optional keyword arguments:
---@return (string[]) # Normalized paths |vim.fs.normalize()| of all matching items
function M.find(names, opts)
- opts = opts or {} --[[@as vim.fs.find.opts]]
+ opts = opts or {}
vim.validate({
names = { names, { 's', 't', 'f' } },
path = { opts.path, 's', true },
@@ -224,7 +232,7 @@ function M.find(names, opts)
names = { names }
end
- local path = opts.path or vim.uv.cwd()
+ local path = opts.path or assert(vim.uv.cwd())
local stop = opts.stop
local limit = opts.limit or 1
@@ -318,9 +326,16 @@ function M.find(names, opts)
return matches
end
+--- @class vim.fs.normalize.Opts
+--- @inlinedoc
+---
+--- Expand environment variables.
+--- (default: `true`)
+--- @field expand_env boolean
+
--- Normalize a path to a standard format. A tilde (~) character at the
--- beginning of the path is expanded to the user's home directory and any
---- backslash (\\) characters are converted to forward slashes (/). Environment
+--- backslash (\) characters are converted to forward slashes (/). Environment
--- variables are also expanded.
---
--- Examples:
@@ -337,9 +352,8 @@ end
--- ```
---
---@param path (string) Path to normalize
----@param opts table|nil Options:
---- - expand_env: boolean Expand environment variables (default: true)
----@return (string) Normalized path
+---@param opts? vim.fs.normalize.Opts
+---@return (string) : Normalized path
function M.normalize(path, opts)
opts = opts or {}
diff --git a/runtime/lua/vim/glob.lua b/runtime/lua/vim/glob.lua
new file mode 100644
index 0000000000..ad4a915a94
--- /dev/null
+++ b/runtime/lua/vim/glob.lua
@@ -0,0 +1,84 @@
+local lpeg = vim.lpeg
+local P, S, V, R, B = lpeg.P, lpeg.S, lpeg.V, lpeg.R, lpeg.B
+local C, Cc, Ct, Cf = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cf
+
+local M = {}
+
+local pathsep = P('/')
+
+--- Parses a raw glob into an |lua-lpeg| pattern.
+---
+--- This uses glob semantics from LSP 3.17.0: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern
+---
+--- Glob patterns can have the following syntax:
+--- - `*` to match one or more characters in a path segment
+--- - `?` to match on one character in a path segment
+--- - `**` to match any number of path segments, including none
+--- - `{}` to group conditions (e.g. `*.{ts,js}` matches TypeScript and JavaScript files)
+--- - `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
+--- - `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
+---
+---@param pattern string The raw glob pattern
+---@return vim.lpeg.Pattern pattern An |lua-lpeg| representation of the pattern
+function M.to_lpeg(pattern)
+ local function class(inv, ranges)
+ local patt = R(unpack(vim.tbl_map(table.concat, ranges)))
+ if inv == '!' then
+ patt = P(1) - patt
+ end
+ return patt
+ end
+
+ local function add(acc, a)
+ return acc + a
+ end
+
+ local function mul(acc, m)
+ return acc * m
+ end
+
+ local function star(stars, after)
+ return (-after * (P(1) - pathsep)) ^ #stars * after
+ end
+
+ local function dstar(after)
+ return (-after * P(1)) ^ 0 * after
+ end
+
+ local p = P({
+ 'Pattern',
+ Pattern = V('Elem') ^ -1 * V('End'),
+ Elem = Cf(
+ (V('DStar') + V('Star') + V('Ques') + V('Class') + V('CondList') + V('Literal'))
+ * (V('Elem') + V('End')),
+ mul
+ ),
+ DStar = (B(pathsep) + -B(P(1)))
+ * P('**')
+ * (pathsep * (V('Elem') + V('End')) + V('End'))
+ / dstar,
+ Star = C(P('*') ^ 1) * (V('Elem') + V('End')) / star,
+ Ques = P('?') * Cc(P(1) - pathsep),
+ Class = P('[')
+ * C(P('!') ^ -1)
+ * Ct(Ct(C(P(1)) * P('-') * C(P(1) - P(']'))) ^ 1 * P(']'))
+ / class,
+ CondList = P('{') * Cf(V('Cond') * (P(',') * V('Cond')) ^ 0, add) * P('}'),
+ -- TODO: '*' inside a {} condition is interpreted literally but should probably have the same
+ -- wildcard semantics it usually has.
+ -- Fixing this is non-trivial because '*' should match non-greedily up to "the rest of the
+ -- pattern" which in all other cases is the entire succeeding part of the pattern, but at the end of a {}
+ -- condition means "everything after the {}" where several other options separated by ',' may
+ -- exist in between that should not be matched by '*'.
+ Cond = Cf((V('Ques') + V('Class') + V('CondList') + (V('Literal') - S(',}'))) ^ 1, mul)
+ + Cc(P(0)),
+ Literal = P(1) / P,
+ End = P(-1) * Cc(P(-1)),
+ })
+
+ local lpeg_pattern = p:match(pattern) --[[@as vim.lpeg.Pattern?]]
+ assert(lpeg_pattern, 'Invalid glob')
+ return lpeg_pattern
+end
+
+return M
diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua
index 6e47a22d03..f6f7abef8f 100644
--- a/runtime/lua/vim/health.lua
+++ b/runtime/lua/vim/health.lua
@@ -1,8 +1,8 @@
local M = {}
-local s_output = {}
+local s_output = {} ---@type string[]
--- Returns the fold text of the current healthcheck section
+--- Returns the fold text of the current healthcheck section
function M.foldtext()
local foldtext = vim.fn.foldtext()
@@ -36,12 +36,13 @@ function M.foldtext()
return vim.b.failedchecks[foldtext] and '+WE' .. foldtext:sub(4) or foldtext
end
--- From a path return a list [{name}, {func}, {type}] representing a healthcheck
+--- @param path string path to search for the healthcheck
+--- @return string[] { name, func, type } representing a healthcheck
local function filepath_to_healthcheck(path)
path = vim.fs.normalize(path)
- local name
- local func
- local filetype
+ local name --- @type string
+ local func --- @type string
+ local filetype --- @type string
if path:find('vim$') then
name = vim.fs.basename(path):gsub('%.vim$', '')
func = 'health#' .. name .. '#check'
@@ -50,10 +51,10 @@ local function filepath_to_healthcheck(path)
local subpath = path:gsub('.*lua/', '')
if vim.fs.basename(subpath) == 'health.lua' then
-- */health.lua
- name = vim.fs.dirname(subpath)
+ name = assert(vim.fs.dirname(subpath))
else
-- */health/init.lua
- name = vim.fs.dirname(vim.fs.dirname(subpath))
+ name = assert(vim.fs.dirname(assert(vim.fs.dirname(subpath))))
end
name = name:gsub('/', '.')
@@ -63,11 +64,12 @@ local function filepath_to_healthcheck(path)
return { name, func, filetype }
end
--- Returns { {name, func, type}, ... } representing healthchecks
+--- @param plugin_names string
+--- @return table<any,string[]> { {name, func, type}, ... } representing healthchecks
local function get_healthcheck_list(plugin_names)
- local healthchecks = {}
- plugin_names = vim.split(plugin_names, ' ')
- for _, p in pairs(plugin_names) do
+ local healthchecks = {} --- @type table<any,string[]>
+ local plugin_names_list = vim.split(plugin_names, ' ')
+ for _, p in pairs(plugin_names_list) do
-- support vim/lsp/health{/init/}.lua as :checkhealth vim.lsp
p = p:gsub('%.', '/')
@@ -83,7 +85,7 @@ local function get_healthcheck_list(plugin_names)
if vim.tbl_count(paths) == 0 then
healthchecks[#healthchecks + 1] = { p, '', '' } -- healthcheck not found
else
- local unique_paths = {}
+ local unique_paths = {} --- @type table<string, boolean>
for _, v in pairs(paths) do
unique_paths[v] = true
end
@@ -100,10 +102,11 @@ local function get_healthcheck_list(plugin_names)
return healthchecks
end
--- Returns {name: [func, type], ..} representing healthchecks
+--- @param plugin_names string
+--- @return table<string, string[]> {name: [func, type], ..} representing healthchecks
local function get_healthcheck(plugin_names)
local health_list = get_healthcheck_list(plugin_names)
- local healthchecks = {}
+ local healthchecks = {} --- @type table<string, string[]>
for _, c in pairs(health_list) do
if c[1] ~= 'vim' then
healthchecks[c[1]] = { c[2], c[3] }
@@ -113,7 +116,11 @@ local function get_healthcheck(plugin_names)
return healthchecks
end
--- Indents lines *except* line 1 of a string if it contains newlines.
+--- Indents lines *except* line 1 of a string if it contains newlines.
+---
+--- @param s string
+--- @param columns integer
+--- @return string
local function indent_after_line1(s, columns)
local lines = vim.split(s, '\n')
local indent = string.rep(' ', columns)
@@ -123,13 +130,20 @@ local function indent_after_line1(s, columns)
return table.concat(lines, '\n')
end
--- Changes ':h clipboard' to ':help |clipboard|'.
+--- Changes ':h clipboard' to ':help |clipboard|'.
+---
+--- @param s string
+--- @return string
local function help_to_link(s)
return vim.fn.substitute(s, [[\v:h%[elp] ([^|][^"\r\n ]+)]], [[:help |\1|]], [[g]])
end
--- Format a message for a specific report item.
--- Variable args: Optional advice (string or list)
+--- Format a message for a specific report item.
+---
+--- @param status string
+--- @param msg string
+--- @param ... string|string[] Optional advice
+--- @return string
local function format_report_message(status, msg, ...)
local output = '- ' .. status
if status ~= '' then
@@ -159,42 +173,54 @@ local function format_report_message(status, msg, ...)
return help_to_link(output)
end
+--- @param output string
local function collect_output(output)
vim.list_extend(s_output, vim.split(output, '\n'))
end
--- Starts a new report.
+--- Starts a new report.
+---
+--- @param name string
function M.start(name)
local input = string.format('\n%s ~', name)
collect_output(input)
end
--- Reports a message in the current section.
+--- Reports a message in the current section.
+---
+--- @param msg string
function M.info(msg)
local input = format_report_message('', msg)
collect_output(input)
end
--- Reports a successful healthcheck.
+--- Reports a successful healthcheck.
+---
+--- @param msg string
function M.ok(msg)
local input = format_report_message('OK', msg)
collect_output(input)
end
--- Reports a health warning.
--- ...: Optional advice (string or table)
+--- Reports a health warning.
+---
+--- @param msg string
+--- @param ... string|string[] Optional advice
function M.warn(msg, ...)
local input = format_report_message('WARNING', msg, ...)
collect_output(input)
end
--- Reports a failed healthcheck.
--- ...: Optional advice (string or table)
+--- Reports a failed healthcheck.
+---
+--- @param msg string
+--- @param ... string|string[] Optional advice
function M.error(msg, ...)
local input = format_report_message('ERROR', msg, ...)
collect_output(input)
end
+--- @param type string
local function deprecate(type)
local before = string.format('vim.health.report_%s()', type)
local after = string.format('vim.health.%s()', type)
@@ -206,27 +232,149 @@ local function deprecate(type)
vim.print('Running healthchecks...')
end
+--- @deprecated
+--- @param name string
function M.report_start(name)
deprecate('start')
M.start(name)
end
+
+--- @deprecated
+--- @param msg string
function M.report_info(msg)
deprecate('info')
M.info(msg)
end
+
+--- @deprecated
+--- @param msg string
function M.report_ok(msg)
deprecate('ok')
M.ok(msg)
end
+
+--- @deprecated
+--- @param msg string
function M.report_warn(msg, ...)
deprecate('warn')
M.warn(msg, ...)
end
+
+--- @deprecated
+--- @param msg string
function M.report_error(msg, ...)
deprecate('error')
M.error(msg, ...)
end
+function M.provider_disabled(provider)
+ local loaded_var = 'loaded_' .. provider .. '_provider'
+ local v = vim.g[loaded_var]
+ if v == 0 then
+ M.info('Disabled (' .. loaded_var .. '=' .. v .. ').')
+ return true
+ end
+ return false
+end
+
+-- Handler for s:system() function.
+local function system_handler(self, _, data, event)
+ if event == 'stderr' then
+ if self.add_stderr_to_output then
+ self.output = self.output .. table.concat(data, '')
+ else
+ self.stderr = self.stderr .. table.concat(data, '')
+ end
+ elseif event == 'stdout' then
+ self.output = self.output .. table.concat(data, '')
+ end
+end
+
+-- Attempts to construct a shell command from an args list.
+-- Only for display, to help users debug a failed command.
+local function shellify(cmd)
+ if type(cmd) ~= 'table' then
+ return cmd
+ end
+ local escaped = {}
+ for i, v in ipairs(cmd) do
+ if v:match('[^A-Za-z_/.-]') then
+ escaped[i] = vim.fn.shellescape(v)
+ else
+ escaped[i] = v
+ end
+ end
+ return table.concat(escaped, ' ')
+end
+
+function M.cmd_ok(cmd)
+ local out = vim.fn.system(cmd)
+ return vim.v.shell_error == 0, out
+end
+
+--- Run a system command and timeout after 30 seconds.
+---
+--- @param cmd table List of command arguments to execute
+--- @param args? table Optional arguments:
+--- - stdin (string): Data to write to the job's stdin
+--- - stderr (boolean): Append stderr to stdout
+--- - ignore_error (boolean): If true, ignore error output
+--- - timeout (number): Number of seconds to wait before timing out (default 30)
+function M.system(cmd, args)
+ args = args or {}
+ local stdin = args.stdin or ''
+ local stderr = vim.F.if_nil(args.stderr, false)
+ local ignore_error = vim.F.if_nil(args.ignore_error, false)
+
+ local shell_error_code = 0
+ local opts = {
+ add_stderr_to_output = stderr,
+ output = '',
+ stderr = '',
+ on_stdout = system_handler,
+ on_stderr = system_handler,
+ on_exit = function(_, data)
+ shell_error_code = data
+ end,
+ }
+ local jobid = vim.fn.jobstart(cmd, opts)
+
+ if jobid < 1 then
+ local message =
+ string.format('Command error (job=%d): %s (in %s)', jobid, shellify(cmd), vim.loop.cwd())
+ error(message)
+ return opts.output, 1
+ end
+
+ if stdin:find('^%s$') then
+ vim.fn.chansend(jobid, stdin)
+ end
+
+ local res = vim.fn.jobwait({ jobid }, vim.F.if_nil(args.timeout, 30) * 1000)
+ if res[1] == -1 then
+ error('Command timed out: ' .. shellify(cmd))
+ vim.fn.jobstop(jobid)
+ elseif shell_error_code ~= 0 and not ignore_error then
+ local emsg = string.format(
+ 'Command error (job=%d, exit code %d): %s (in %s)',
+ jobid,
+ shell_error_code,
+ shellify(cmd),
+ vim.loop.cwd()
+ )
+ if opts.output:find('%S') then
+ emsg = string.format('%s\noutput: %s', emsg, opts.output)
+ end
+ if opts.stderr:find('%S') then
+ emsg = string.format('%s\nstderr: %s', emsg, opts.stderr)
+ end
+ error(emsg)
+ end
+
+ -- return opts.output
+ return vim.trim(vim.fn.system(cmd)), shell_error_code
+end
+
local path2name = function(path)
if path:match('%.lua$') then
-- Lua: transform "../lua/vim/lsp/health.lua" into "vim.lsp"
@@ -251,7 +399,7 @@ local path2name = function(path)
end
local PATTERNS = { '/autoload/health/*.vim', '/lua/**/**/health.lua', '/lua/**/**/health/init.lua' }
--- :checkhealth completion function used by ex_getln.c get_healthcheck_names()
+--- :checkhealth completion function used by cmdexpand.c get_healthcheck_names()
M._complete = function()
local names = vim.tbl_flatten(vim.tbl_map(function(pattern)
return vim.tbl_map(path2name, vim.api.nvim_get_runtime_file(pattern, true))
@@ -266,16 +414,25 @@ M._complete = function()
return vim.tbl_keys(unique)
end
--- Runs the specified healthchecks.
--- Runs all discovered healthchecks if plugin_names is empty.
-function M._check(plugin_names)
+--- Runs the specified healthchecks.
+--- Runs all discovered healthchecks if plugin_names is empty.
+---
+--- @param mods string command modifiers that affect splitting a window.
+--- @param plugin_names string glob of plugin names, split on whitespace. For example, using
+--- `:checkhealth vim.* nvim` will healthcheck `vim.lsp`, `vim.treesitter`
+--- and `nvim` modules.
+function M._check(mods, plugin_names)
local healthchecks = plugin_names == '' and get_healthcheck('*') or get_healthcheck(plugin_names)
- -- Create buffer and open in a tab, unless this is the default buffer when Nvim starts.
local emptybuf = vim.fn.bufnr('$') == 1 and vim.fn.getline(1) == '' and 1 == vim.fn.line('$')
- local mod = emptybuf and 'buffer' or 'tab sbuffer'
+
+ -- When no command modifiers are used:
+ -- - If the current buffer is empty, open healthcheck directly.
+ -- - If not specified otherwise open healthcheck in a tab.
+ local buf_cmd = #mods > 0 and (mods .. ' sbuffer') or emptybuf and 'buffer' or 'tab sbuffer'
+
local bufnr = vim.api.nvim_create_buf(true, true)
- vim.cmd(mod .. ' ' .. bufnr)
+ vim.cmd(buf_cmd .. ' ' .. bufnr)
if vim.fn.bufexists('health://') == 1 then
vim.cmd.bwipe('health://')
@@ -283,7 +440,8 @@ function M._check(plugin_names)
vim.cmd.file('health://')
vim.cmd.setfiletype('checkhealth')
- if healthchecks == nil or next(healthchecks) == nil then
+ -- This should only happen when doing `:checkhealth vim`
+ if next(healthchecks) == nil then
vim.fn.setline(1, 'ERROR: No healthchecks found.')
return
end
@@ -319,7 +477,7 @@ function M._check(plugin_names)
local header = { string.rep('=', 78), name .. ': ' .. func, '' }
-- remove empty line after header from report_start
if s_output[1] == '' then
- local tmp = {}
+ local tmp = {} ---@type string[]
for i = 2, #s_output do
tmp[#tmp + 1] = s_output[i]
end
@@ -339,4 +497,11 @@ function M._check(plugin_names)
vim.print('')
end
+local fn_bool = function(key)
+ return function(...)
+ return vim.fn[key](...) == 1
+ end
+end
+M.executable = fn_bool('executable')
+
return M
diff --git a/runtime/lua/vim/highlight.lua b/runtime/lua/vim/highlight.lua
index fc2fd43c97..effe280dee 100644
--- a/runtime/lua/vim/highlight.lua
+++ b/runtime/lua/vim/highlight.lua
@@ -1,4 +1,4 @@
----@defgroup vim.highlight
+---@brief
---
--- Nvim includes a function for highlighting a selection on yank.
---
@@ -19,18 +19,19 @@
--- ```vim
--- au TextYankPost * silent! lua vim.highlight.on_yank {on_visual=false}
--- ```
+---
local api = vim.api
local M = {}
--- Table with default priorities used for highlighting:
---- - `syntax`: `50`, used for standard syntax highlighting
---- - `treesitter`: `100`, used for tree-sitter-based highlighting
---- - `semantic_tokens`: `125`, used for LSP semantic token highlighting
---- - `diagnostics`: `150`, used for code analysis such as diagnostics
---- - `user`: `200`, used for user-triggered highlights such as LSP document
---- symbols or `on_yank` autocommands
+--- - `syntax`: `50`, used for standard syntax highlighting
+--- - `treesitter`: `100`, used for treesitter-based highlighting
+--- - `semantic_tokens`: `125`, used for LSP semantic token highlighting
+--- - `diagnostics`: `150`, used for code analysis such as diagnostics
+--- - `user`: `200`, used for user-triggered highlights such as LSP document
+--- symbols or `on_yank` autocommands
M.priorities = {
syntax = 50,
treesitter = 100,
@@ -55,6 +56,7 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
local regtype = opts.regtype or 'v'
local inclusive = opts.inclusive or false
local priority = opts.priority or M.priorities.user
+ local scoped = opts._scoped or false
-- TODO: in case of 'v', 'V' (not block), this should calculate equivalent
-- bounds (row, col, end_row, end_col) as multiline regions are natively
@@ -72,12 +74,14 @@ function M.range(bufnr, ns, higroup, start, finish, opts)
end_col = cols[2],
priority = priority,
strict = false,
+ scoped = scoped,
})
end
end
local yank_ns = api.nvim_create_namespace('hlyank')
local yank_timer
+local yank_cancel
--- Highlight the yanked text
---
@@ -120,24 +124,29 @@ function M.on_yank(opts)
local higroup = opts.higroup or 'IncSearch'
local timeout = opts.timeout or 150
- local bufnr = api.nvim_get_current_buf()
- api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1)
+ local bufnr = vim.api.nvim_get_current_buf()
+ local winid = vim.api.nvim_get_current_win()
if yank_timer then
yank_timer:close()
+ yank_cancel()
end
M.range(bufnr, yank_ns, higroup, "'[", "']", {
regtype = event.regtype,
inclusive = event.inclusive,
priority = opts.priority or M.priorities.user,
+ _scoped = true,
})
+ vim.api.nvim_win_add_ns(winid, yank_ns)
- yank_timer = vim.defer_fn(function()
+ yank_cancel = function()
yank_timer = nil
- if api.nvim_buf_is_valid(bufnr) then
- api.nvim_buf_clear_namespace(bufnr, yank_ns, 0, -1)
- end
- end, timeout)
+ yank_cancel = nil
+ pcall(vim.api.nvim_buf_clear_namespace, bufnr, yank_ns, 0, -1)
+ pcall(vim.api.nvim_win_remove_ns, winid, yank_ns)
+ end
+
+ yank_timer = vim.defer_fn(yank_cancel, timeout)
end
return M
diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua
index 874bdfb437..a37b7f7858 100644
--- a/runtime/lua/vim/iter.lua
+++ b/runtime/lua/vim/iter.lua
@@ -1,7 +1,7 @@
----@defgroup vim.iter
+--- @brief
---
---- \*vim.iter()\* is an interface for |iterable|s: it wraps a table or function argument into an
---- \*Iter\* object with methods (such as |Iter:filter()| and |Iter:map()|) that transform the
+--- [vim.iter()]() is an interface for [iterable]s: it wraps a table or function argument into an
+--- [Iter]() object with methods (such as [Iter:filter()] and [Iter:map()]) that transform the
--- underlying source data. These methods can be chained to create iterator "pipelines": the output
--- of each pipeline stage is input to the next stage. The first stage depends on the type passed to
--- `vim.iter()`:
@@ -64,10 +64,16 @@
--- In addition to the |vim.iter()| function, the |vim.iter| module provides
--- convenience functions like |vim.iter.filter()| and |vim.iter.totable()|.
+--- LuaLS is bad at generics which this module mostly deals with
+--- @diagnostic disable:no-unknown
+
+---@nodoc
---@class IterMod
---@operator call:Iter
+
local M = {}
+---@nodoc
---@class Iter
local Iter = {}
Iter.__index = Iter
@@ -76,6 +82,7 @@ Iter.__call = function(self)
end
--- Special case implementations for iterators on list tables.
+---@nodoc
---@class ListIter : Iter
---@field _table table Underlying table data
---@field _head number Index to the front of a table iterator
@@ -112,6 +119,35 @@ local function sanitize(t)
return t
end
+--- Flattens a single list-like table. Errors if it attempts to flatten a
+--- dict-like table
+---@param v table table which should be flattened
+---@param max_depth number depth to which the table should be flattened
+---@param depth number current iteration depth
+---@param result table output table that contains flattened result
+---@return table|nil flattened table if it can be flattened, otherwise nil
+local function flatten(v, max_depth, depth, result)
+ if depth < max_depth and type(v) == 'table' then
+ local i = 0
+ for _ in pairs(v) do
+ i = i + 1
+
+ if v[i] == nil then
+ -- short-circuit: this is not a list like table
+ return nil
+ end
+
+ if flatten(v[i], max_depth, depth + 1, result) == nil then
+ return nil
+ end
+ end
+ else
+ result[#result + 1] = v
+ end
+
+ return result
+end
+
--- Determine if the current iterator stage should continue.
---
--- If any arguments are passed to this function, then return those arguments
@@ -152,11 +188,11 @@ end
--- local bufs = vim.iter(vim.api.nvim_list_bufs()):filter(vim.api.nvim_buf_is_loaded)
--- ```
---
----@param f function(...):bool Takes all values returned from the previous stage
---- in the pipeline and returns false or nil if the
---- current iterator element should be removed.
+---@param f fun(...):boolean Takes all values returned from the previous stage
+--- in the pipeline and returns false or nil if the
+--- current iterator element should be removed.
---@return Iter
-function Iter.filter(self, f)
+function Iter:filter(f)
return self:map(function(...)
if f(...) then
return ...
@@ -165,7 +201,7 @@ function Iter.filter(self, f)
end
---@private
-function ListIter.filter(self, f)
+function ListIter:filter(f)
local inc = self._head < self._tail and 1 or -1
local n = self._head
for i = self._head, self._tail - inc, inc do
@@ -179,6 +215,55 @@ function ListIter.filter(self, f)
return self
end
+--- Flattens a |list-iterator|, un-nesting nested values up to the given {depth}.
+--- Errors if it attempts to flatten a dict-like value.
+---
+--- Examples:
+---
+--- ```lua
+--- vim.iter({ 1, { 2 }, { { 3 } } }):flatten():totable()
+--- -- { 1, 2, { 3 } }
+---
+--- vim.iter({1, { { a = 2 } }, { 3 } }):flatten():totable()
+--- -- { 1, { a = 2 }, 3 }
+---
+--- vim.iter({ 1, { { a = 2 } }, { 3 } }):flatten(math.huge):totable()
+--- -- error: attempt to flatten a dict-like table
+--- ```
+---
+---@param depth? number Depth to which |list-iterator| should be flattened
+--- (defaults to 1)
+---@return Iter
+---@diagnostic disable-next-line:unused-local
+function Iter:flatten(depth) -- luacheck: no unused args
+ error('flatten() requires a list-like table')
+end
+
+---@private
+function ListIter:flatten(depth)
+ depth = depth or 1
+ local inc = self._head < self._tail and 1 or -1
+ local target = {}
+
+ for i = self._head, self._tail - inc, inc do
+ local flattened = flatten(self._table[i], depth, 0, {})
+
+ -- exit early if we try to flatten a dict-like table
+ if flattened == nil then
+ error('flatten() requires a list-like table')
+ end
+
+ for _, v in pairs(flattened) do
+ target[#target + 1] = v
+ end
+ end
+
+ self._head = 1
+ self._tail = #target + 1
+ self._table = target
+ return self
+end
+
--- Maps the items of an iterator pipeline to the values returned by `f`.
---
--- If the map function returns nil, the value is filtered from the iterator.
@@ -195,13 +280,13 @@ end
--- -- { 6, 12 }
--- ```
---
----@param f function(...):any Mapping function. Takes all values returned from
---- the previous stage in the pipeline as arguments
---- and returns one or more new values, which are used
---- in the next pipeline stage. Nil return values
---- are filtered from the output.
+---@param f fun(...):any Mapping function. Takes all values returned from
+--- the previous stage in the pipeline as arguments
+--- and returns one or more new values, which are used
+--- in the next pipeline stage. Nil return values
+--- are filtered from the output.
---@return Iter
-function Iter.map(self, f)
+function Iter:map(f)
-- Implementation note: the reader may be forgiven for observing that this
-- function appears excessively convoluted. The problem to solve is that each
-- stage of the iterator pipeline can return any number of values, and the
@@ -245,7 +330,7 @@ function Iter.map(self, f)
end
---@private
-function ListIter.map(self, f)
+function ListIter:map(f)
local inc = self._head < self._tail and 1 or -1
local n = self._head
for i = self._head, self._tail - inc, inc do
@@ -263,10 +348,10 @@ end
---
--- For functions with side effects. To modify the values in the iterator, use |Iter:map()|.
---
----@param f function(...) Function to execute for each item in the pipeline.
---- Takes all of the values returned by the previous stage
---- in the pipeline as arguments.
-function Iter.each(self, f)
+---@param f fun(...) Function to execute for each item in the pipeline.
+--- Takes all of the values returned by the previous stage
+--- in the pipeline as arguments.
+function Iter:each(f)
local function fn(...)
if select(1, ...) ~= nil then
f(...)
@@ -278,7 +363,7 @@ function Iter.each(self, f)
end
---@private
-function ListIter.each(self, f)
+function ListIter:each(f)
local inc = self._head < self._tail and 1 or -1
for i = self._head, self._tail - inc, inc do
f(unpack(self._table[i]))
@@ -311,7 +396,7 @@ end
---
---
---@return table
-function Iter.totable(self)
+function Iter:totable()
local t = {}
while true do
@@ -326,7 +411,7 @@ function Iter.totable(self)
end
---@private
-function ListIter.totable(self)
+function ListIter:totable()
if self.next ~= ListIter.next or self._head >= self._tail then
return Iter.totable(self)
end
@@ -356,6 +441,18 @@ function ListIter.totable(self)
return self._table
end
+--- Collect the iterator into a delimited string.
+---
+--- Each element in the iterator is joined into a string separated by {delim}.
+---
+--- Consumes the iterator.
+---
+--- @param delim string Delimiter
+--- @return string
+function Iter:join(delim)
+ return table.concat(self:totable(), delim)
+end
+
--- Folds ("reduces") an iterator into a single value.
---
--- Examples:
@@ -375,9 +472,9 @@ end
---@generic A
---
---@param init A Initial value of the accumulator.
----@param f function(acc:A, ...):A Accumulation function.
+---@param f fun(acc:A, ...):A Accumulation function.
---@return A
-function Iter.fold(self, init, f)
+function Iter:fold(init, f)
local acc = init
--- Use a closure to handle var args returned from iterator
@@ -394,7 +491,7 @@ function Iter.fold(self, init, f)
end
---@private
-function ListIter.fold(self, init, f)
+function ListIter:fold(init, f)
local acc = init
local inc = self._head < self._tail and 1 or -1
for i = self._head, self._tail - inc, inc do
@@ -420,13 +517,13 @@ end
--- ```
---
---@return any
-function Iter.next(self) -- luacheck: no unused args
+function Iter:next()
-- This function is provided by the source iterator in Iter.new. This definition exists only for
-- the docstring
end
---@private
-function ListIter.next(self)
+function ListIter:next()
if self._head ~= self._tail then
local v = self._table[self._head]
local inc = self._head < self._tail and 1 or -1
@@ -448,13 +545,12 @@ end
--- ```
---
---@return Iter
-function Iter.rev(self)
+function Iter:rev()
error('rev() requires a list-like table')
- return self
end
---@private
-function ListIter.rev(self)
+function ListIter:rev()
local inc = self._head < self._tail and 1 or -1
self._head, self._tail = self._tail - inc, self._head - inc
return self
@@ -477,12 +573,12 @@ end
--- ```
---
---@return any
-function Iter.peek(self) -- luacheck: no unused args
+function Iter:peek()
error('peek() requires a list-like table')
end
---@private
-function ListIter.peek(self)
+function ListIter:peek()
if self._head ~= self._tail then
return self._table[self._head]
end
@@ -509,9 +605,9 @@ end
--- -- 12
---
--- ```
----
+---@param f any
---@return any
-function Iter.find(self, f)
+function Iter:find(f)
if type(f) ~= 'function' then
local val = f
f = function(v)
@@ -555,13 +651,15 @@ end
---
---@see Iter.find
---
+---@param f any
---@return any
-function Iter.rfind(self, f) -- luacheck: no unused args
+---@diagnostic disable-next-line: unused-local
+function Iter:rfind(f) -- luacheck: no unused args
error('rfind() requires a list-like table')
end
---@private
-function ListIter.rfind(self, f) -- luacheck: no unused args
+function ListIter:rfind(f)
if type(f) ~= 'function' then
local val = f
f = function(v)
@@ -580,6 +678,41 @@ function ListIter.rfind(self, f) -- luacheck: no unused args
self._head = self._tail
end
+--- Transforms an iterator to yield only the first n values.
+---
+--- Example:
+---
+--- ```lua
+--- local it = vim.iter({ 1, 2, 3, 4 }):take(2)
+--- it:next()
+--- -- 1
+--- it:next()
+--- -- 2
+--- it:next()
+--- -- nil
+--- ```
+---
+---@param n integer
+---@return Iter
+function Iter:take(n)
+ local next = self.next
+ local i = 0
+ self.next = function()
+ if i < n then
+ i = i + 1
+ return next(self)
+ end
+ end
+ return self
+end
+
+---@private
+function ListIter:take(n)
+ local inc = self._head < self._tail and 1 or -1
+ self._tail = math.min(self._tail, self._head + n * inc)
+ return self
+end
+
--- "Pops" a value from a |list-iterator| (gets the last value and decrements the tail).
---
--- Example:
@@ -593,11 +726,12 @@ end
--- ```
---
---@return any
-function Iter.nextback(self) -- luacheck: no unused args
+function Iter:nextback()
error('nextback() requires a list-like table')
end
-function ListIter.nextback(self)
+--- @nodoc
+function ListIter:nextback()
if self._head ~= self._tail then
local inc = self._head < self._tail and 1 or -1
self._tail = self._tail - inc
@@ -622,11 +756,12 @@ end
--- ```
---
---@return any
-function Iter.peekback(self) -- luacheck: no unused args
+function Iter:peekback()
error('peekback() requires a list-like table')
end
-function ListIter.peekback(self)
+---@nodoc
+function ListIter:peekback()
if self._head ~= self._tail then
local inc = self._head < self._tail and 1 or -1
return self._table[self._tail - inc]
@@ -647,7 +782,7 @@ end
---
---@param n number Number of values to skip.
---@return Iter
-function Iter.skip(self, n)
+function Iter:skip(n)
for _ = 1, n do
local _ = self:next()
end
@@ -655,7 +790,7 @@ function Iter.skip(self, n)
end
---@private
-function ListIter.skip(self, n)
+function ListIter:skip(n)
local inc = self._head < self._tail and n or -n
self._head = self._head + inc
if (inc > 0 and self._head > self._tail) or (inc < 0 and self._head < self._tail) then
@@ -678,13 +813,13 @@ end
---
---@param n number Number of values to skip.
---@return Iter
-function Iter.skipback(self, n) -- luacheck: no unused args
+---@diagnostic disable-next-line: unused-local
+function Iter:skipback(n) -- luacheck: no unused args
error('skipback() requires a list-like table')
- return self
end
---@private
-function ListIter.skipback(self, n)
+function ListIter:skipback(n)
local inc = self._head < self._tail and n or -n
self._tail = self._tail - inc
if (inc > 0 and self._head > self._tail) or (inc < 0 and self._head < self._tail) then
@@ -709,7 +844,7 @@ end
---
---@param n number The index of the value to return.
---@return any
-function Iter.nth(self, n)
+function Iter:nth(n)
if n > 0 then
return self:skip(n - 1):next()
end
@@ -731,7 +866,7 @@ end
---
---@param n number The index of the value to return.
---@return any
-function Iter.nthback(self, n)
+function Iter:nthback(n)
if n > 0 then
return self:skipback(n - 1):nextback()
end
@@ -744,22 +879,22 @@ end
---@param first number
---@param last number
---@return Iter
-function Iter.slice(self, first, last) -- luacheck: no unused args
+---@diagnostic disable-next-line: unused-local
+function Iter:slice(first, last) -- luacheck: no unused args
error('slice() requires a list-like table')
- return self
end
---@private
-function ListIter.slice(self, first, last)
+function ListIter:slice(first, last)
return self:skip(math.max(0, first - 1)):skipback(math.max(0, self._tail - last - 1))
end
--- Returns true if any of the items in the iterator match the given predicate.
---
----@param pred function(...):bool Predicate function. Takes all values returned from the previous
---- stage in the pipeline as arguments and returns true if the
---- predicate matches.
-function Iter.any(self, pred)
+---@param pred fun(...):boolean Predicate function. Takes all values returned from the previous
+--- stage in the pipeline as arguments and returns true if the
+--- predicate matches.
+function Iter:any(pred)
local any = false
--- Use a closure to handle var args returned from iterator
@@ -780,10 +915,10 @@ end
--- Returns true if all items in the iterator match the given predicate.
---
----@param pred function(...):bool Predicate function. Takes all values returned from the previous
---- stage in the pipeline as arguments and returns true if the
---- predicate matches.
-function Iter.all(self, pred)
+---@param pred fun(...):boolean Predicate function. Takes all values returned from the previous
+--- stage in the pipeline as arguments and returns true if the
+--- predicate matches.
+function Iter:all(pred)
local all = true
local function fn(...)
@@ -818,7 +953,7 @@ end
--- ```
---
---@return any
-function Iter.last(self)
+function Iter:last()
local last = self:next()
local cur = self:next()
while cur do
@@ -829,7 +964,7 @@ function Iter.last(self)
end
---@private
-function ListIter.last(self)
+function ListIter:last()
local inc = self._head < self._tail and 1 or -1
local v = self._table[self._tail - inc]
self._head = self._tail
@@ -865,7 +1000,7 @@ end
--- ```
---
---@return Iter
-function Iter.enumerate(self)
+function Iter:enumerate()
local i = 0
return self:map(function(...)
i = i + 1
@@ -874,7 +1009,7 @@ function Iter.enumerate(self)
end
---@private
-function ListIter.enumerate(self)
+function ListIter:enumerate()
local inc = self._head < self._tail and 1 or -1
for i = self._head, self._tail - inc, inc do
local v = self._table[i]
@@ -978,9 +1113,9 @@ end
---
---@see |Iter:filter()|
---
----@param f function(...):bool Filter function. Accepts the current iterator or table values as
---- arguments and returns true if those values should be kept in the
---- final table
+---@param f fun(...):boolean Filter function. Accepts the current iterator or table values as
+--- arguments and returns true if those values should be kept in the
+--- final table
---@param src table|function Table or iterator function to filter
---@return table
function M.filter(f, src, ...)
@@ -996,18 +1131,17 @@ end
---
---@see |Iter:map()|
---
----@param f function(...):?any Map function. Accepts the current iterator or table values as
---- arguments and returns one or more new values. Nil values are removed
---- from the final table.
+---@param f fun(...): any? Map function. Accepts the current iterator or table values as
+--- arguments and returns one or more new values. Nil values are removed
+--- from the final table.
---@param src table|function Table or iterator function to filter
---@return table
function M.map(f, src, ...)
return Iter.new(src, ...):map(f):totable()
end
----@type IterMod
return setmetatable(M, {
__call = function(_, ...)
return Iter.new(...)
end,
-})
+}) --[[@as IterMod]]
diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua
index bdea95f9ab..84e9b4197d 100644
--- a/runtime/lua/vim/keymap.lua
+++ b/runtime/lua/vim/keymap.lua
@@ -44,7 +44,7 @@ function keymap.set(mode, lhs, rhs, opts)
opts = { opts, 't', true },
})
- opts = vim.deepcopy(opts or {})
+ opts = vim.deepcopy(opts or {}, true)
---@cast mode string[]
mode = type(mode) == 'string' and { mode } or mode
@@ -90,6 +90,8 @@ end
--- vim.keymap.del({'n', 'i', 'v'}, '<leader>w', { buffer = 5 })
--- ```
---
+---@param modes string|string[]
+---@param lhs string
---@param opts table|nil A table of optional arguments:
--- - "buffer": (integer|boolean) Remove a mapping from the given buffer.
--- When `0` or `true`, use the current buffer.
diff --git a/runtime/lua/vim/loader.lua b/runtime/lua/vim/loader.lua
index ee01111337..d3d8948654 100644
--- a/runtime/lua/vim/loader.lua
+++ b/runtime/lua/vim/loader.lua
@@ -1,24 +1,46 @@
+local fs = vim.fs -- "vim.fs" is a dependency, so must be loaded early.
local uv = vim.uv
-local uri_encode = vim.uri_encode
+local uri_encode = vim.uri_encode --- @type function
--- @type (fun(modename: string): fun()|string)[]
local loaders = package.loaders
local M = {}
----@alias CacheHash {mtime: {nsec: integer, sec: integer}, size: integer, type?: uv.aliases.fs_stat_types}
+---@alias CacheHash {mtime: {nsec: integer, sec: integer}, size: integer, type?: string}
---@alias CacheEntry {hash:CacheHash, chunk:string}
----@class ModuleFindOpts
----@field all? boolean Search for all matches (defaults to `false`)
----@field rtp? boolean Search for modname in the runtime path (defaults to `true`)
----@field patterns? string[] Patterns to use (defaults to `{"/init.lua", ".lua"}`)
----@field paths? string[] Extra paths to search for modname
-
----@class ModuleInfo
----@field modpath string Path of the module
----@field modname string Name of the module
----@field stat? uv.uv_fs_t File stat of the module path
+--- @class vim.loader.find.Opts
+--- @inlinedoc
+---
+--- Search for modname in the runtime path.
+--- (default: `true`)
+--- @field rtp? boolean
+---
+--- Extra paths to search for modname
+--- (default: `{}`)
+--- @field paths? string[]
+---
+--- List of patterns to use when searching for modules.
+--- A pattern is a string added to the basename of the Lua module being searched.
+--- (default: `{"/init.lua", ".lua"}`)
+--- @field patterns? string[]
+---
+--- Search for all matches.
+--- (default: `false`)
+--- @field all? boolean
+
+--- @class vim.loader.ModuleInfo
+--- @inlinedoc
+---
+--- Path of the module
+--- @field modpath string
+---
+--- Name of the module
+--- @field modname string
+---
+--- The fs_stat of the module path. Won't be returned for `modname="*"`
+--- @field stat? uv.uv_fs_t
---@alias LoaderStats table<string, {total:number, time:number, [string]:number?}?>
@@ -28,14 +50,14 @@ M.path = vim.fn.stdpath('cache') .. '/luac'
---@nodoc
M.enabled = false
----@class Loader
----@field _rtp string[]
----@field _rtp_pure string[]
----@field _rtp_key string
----@field _hashes? table<string, CacheHash>
+---@class (private) Loader
+---@field private _rtp string[]
+---@field private _rtp_pure string[]
+---@field private _rtp_key string
+---@field private _hashes? table<string, CacheHash>
local Loader = {
VERSION = 4,
- ---@type table<string, table<string,ModuleInfo>>
+ ---@type table<string, table<string,vim.loader.ModuleInfo>>
_indexed = {},
---@type table<string, string[]>
_topmods = {},
@@ -63,7 +85,7 @@ function Loader.get_hash(path)
end
local function normalize(path)
- return vim.fs.normalize(path, { expand_env = false })
+ return fs.normalize(path, { expand_env = false })
end
--- Gets the rtp excluding after directories.
@@ -189,7 +211,6 @@ function Loader.loader_lib(modname)
local sysname = uv.os_uname().sysname:lower() or ''
local is_win = sysname:find('win', 1, true) and not sysname:find('darwin', 1, true)
local ret = M.find(modname, { patterns = is_win and { '.dll' } or { '.so' } })[1]
- ---@type function?, string?
if ret then
-- Making function name in Lua 5.1 (see src/loadlib.c:mkfuncname) is
-- a) strip prefix up to and including the first dash, if any
@@ -207,15 +228,13 @@ end
--- `loadfile` using the cache
--- Note this has the mode and env arguments which is supported by LuaJIT and is 5.1 compatible.
---@param filename? string
----@param mode? "b"|"t"|"bt"
+---@param _mode? "b"|"t"|"bt"
---@param env? table
---@return function?, string? error_message
---@private
--- luacheck: ignore 312
-function Loader.loadfile(filename, mode, env)
+function Loader.loadfile(filename, _mode, env)
-- ignore mode, since we byte-compile the Lua source files
- mode = nil
- return Loader.load(normalize(filename), { mode = mode, env = env })
+ return Loader.load(normalize(filename), { env = env })
end
--- Checks whether two cache hashes are the same based on:
@@ -272,17 +291,8 @@ end
--- Finds Lua modules for the given module name.
---@param modname string Module name, or `"*"` to find the top-level modules instead
----@param opts? ModuleFindOpts (table|nil) Options for finding a module:
---- - rtp: (boolean) Search for modname in the runtime path (defaults to `true`)
---- - paths: (string[]) Extra paths to search for modname (defaults to `{}`)
---- - patterns: (string[]) List of patterns to use when searching for modules.
---- A pattern is a string added to the basename of the Lua module being searched.
---- (defaults to `{"/init.lua", ".lua"}`)
---- - all: (boolean) Return all matches instead of just the first one (defaults to `false`)
----@return ModuleInfo[] (list) A list of results with the following properties:
---- - modpath: (string) the path to the module
---- - modname: (string) the name of the module
---- - stat: (table|nil) the fs_stat of the module path. Won't be returned for `modname="*"`
+---@param opts? vim.loader.find.Opts Options for finding a module:
+---@return vim.loader.ModuleInfo[]
function M.find(modname, opts)
opts = opts or {}
@@ -308,7 +318,7 @@ function M.find(modname, opts)
patterns[p] = '/lua/' .. basename .. pattern
end
- ---@type ModuleInfo[]
+ ---@type vim.loader.ModuleInfo[]
local results = {}
-- Only continue if we haven't found anything yet or we want to find all
@@ -432,7 +442,7 @@ end
function Loader.lsmod(path)
if not Loader._indexed[path] then
Loader._indexed[path] = {}
- for name, t in vim.fs.dir(path .. '/lua') do
+ for name, t in fs.dir(path .. '/lua') do
local modpath = path .. '/lua/' .. name
-- HACK: type is not always returned due to a bug in luv
t = t or Loader.get_hash(modpath).type
@@ -474,12 +484,12 @@ function Loader.track(stat, f)
end
end
----@class ProfileOpts
+---@class (private) vim.loader._profile.Opts
---@field loaders? boolean Add profiling to the loaders
--- Debug function that wraps all loaders and tracks stats
---@private
----@param opts ProfileOpts?
+---@param opts vim.loader._profile.Opts?
function M._profile(opts)
Loader.get_rtp = Loader.track('get_rtp', Loader.get_rtp)
Loader.read = Loader.track('read', Loader.read)
diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua
index 261a3aa5de..d5c376ba44 100644
--- a/runtime/lua/vim/lsp.lua
+++ b/runtime/lua/vim/lsp.lua
@@ -1,39 +1,37 @@
----@diagnostic disable: invisible
-local default_handlers = require('vim.lsp.handlers')
-local log = require('vim.lsp.log')
-local lsp_rpc = require('vim.lsp.rpc')
-local protocol = require('vim.lsp.protocol')
-local ms = protocol.Methods
-local util = require('vim.lsp.util')
-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_exec_autocmds =
- api.nvim_err_writeln, api.nvim_buf_get_lines, api.nvim_command, api.nvim_exec_autocmds
-local uv = vim.uv
local tbl_isempty, tbl_extend = vim.tbl_isempty, vim.tbl_extend
local validate = vim.validate
local if_nil = vim.F.if_nil
-local lsp = {
- protocol = protocol,
-
- handlers = default_handlers,
-
- buf = require('vim.lsp.buf'),
- diagnostic = require('vim.lsp.diagnostic'),
- codelens = require('vim.lsp.codelens'),
- inlay_hint = require('vim.lsp.inlay_hint'),
- semantic_tokens = semantic_tokens,
- util = util,
+local lsp = vim._defer_require('vim.lsp', {
+ _changetracking = ..., --- @module 'vim.lsp._changetracking'
+ _completion = ..., --- @module 'vim.lsp._completion'
+ _dynamic = ..., --- @module 'vim.lsp._dynamic'
+ _snippet_grammar = ..., --- @module 'vim.lsp._snippet_grammar'
+ _tagfunc = ..., --- @module 'vim.lsp._tagfunc'
+ _watchfiles = ..., --- @module 'vim.lsp._watchfiles'
+ buf = ..., --- @module 'vim.lsp.buf'
+ client = ..., --- @module 'vim.lsp.client'
+ codelens = ..., --- @module 'vim.lsp.codelens'
+ diagnostic = ..., --- @module 'vim.lsp.diagnostic'
+ handlers = ..., --- @module 'vim.lsp.handlers'
+ inlay_hint = ..., --- @module 'vim.lsp.inlay_hint'
+ log = ..., --- @module 'vim.lsp.log'
+ protocol = ..., --- @module 'vim.lsp.protocol'
+ rpc = ..., --- @module 'vim.lsp.rpc'
+ semantic_tokens = ..., --- @module 'vim.lsp.semantic_tokens'
+ util = ..., --- @module 'vim.lsp.util'
+})
- -- Allow raw RPC access.
- rpc = lsp_rpc,
+local log = lsp.log
+local protocol = lsp.protocol
+local ms = protocol.Methods
+local util = lsp.util
+local changetracking = lsp._changetracking
- -- Export these directly from rpc.
- rpc_response_error = lsp_rpc.rpc_response_error,
-}
+-- Export these directly from rpc.
+---@nodoc
+lsp.rpc_response_error = lsp.rpc.rpc_response_error
-- maps request name to the required server_capability in the client.
lsp._request_name_to_capability = {
@@ -69,14 +67,6 @@ lsp._request_name_to_capability = {
-- TODO improve handling of scratch buffers with LSP attached.
---- Concatenates and writes a list of strings to the Vim error buffer.
----
----@param ... string List to write to the buffer
-local function err_message(...)
- nvim_err_writeln(table.concat(vim.tbl_flatten({ ... })))
- nvim_command('redraw')
-end
-
--- Returns the buffer number for the given {bufnr}.
---
---@param bufnr (integer|nil) Buffer number to resolve. Defaults to current buffer
@@ -102,57 +92,28 @@ function lsp._unsupported_method(method)
return msg
end
---- Checks whether a given path is a directory.
----
----@param filename (string) path to check
----@return boolean # true if {filename} exists and is a directory, false otherwise
-local function is_dir(filename)
- validate({ filename = { filename, 's' } })
- local stat = uv.fs_stat(filename)
- return stat and stat.type == 'directory' or false
-end
-
local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'error' }
-local valid_encodings = {
- ['utf-8'] = 'utf-8',
- ['utf-16'] = 'utf-16',
- ['utf-32'] = 'utf-32',
- ['utf8'] = 'utf-8',
- ['utf16'] = 'utf-16',
- ['utf32'] = 'utf-32',
- UTF8 = 'utf-8',
- UTF16 = 'utf-16',
- UTF32 = 'utf-32',
-}
-
local format_line_ending = {
['unix'] = '\n',
['dos'] = '\r\n',
['mac'] = '\r',
}
+---@private
---@param bufnr (number)
---@return string
-local function buf_get_line_ending(bufnr)
+function lsp._buf_get_line_ending(bufnr)
return format_line_ending[vim.bo[bufnr].fileformat] or '\n'
end
-local client_index = 0
---- Returns a new, unused client id.
----
----@return integer client_id
-local function next_client_id()
- client_index = client_index + 1
- return client_index
-end
-- Tracks all clients created via lsp.start_client
-local active_clients = {} --- @type table<integer,lsp.Client>
+local active_clients = {} --- @type table<integer,vim.lsp.Client>
local all_buffer_active_clients = {} --- @type table<integer,table<integer,true>>
-local uninitialized_clients = {} --- @type table<integer,lsp.Client>
+local uninitialized_clients = {} --- @type table<integer,vim.lsp.Client>
---@param bufnr? integer
----@param fn fun(client: lsp.Client, client_id: integer, bufnr: integer)
+---@param fn fun(client: vim.lsp.Client, client_id: integer, bufnr: integer)
local function for_each_buffer_client(bufnr, fn, restrict_client_ids)
validate({
fn = { fn, 'f' },
@@ -182,136 +143,36 @@ local function for_each_buffer_client(bufnr, fn, restrict_client_ids)
end
end
+local client_errors_base = table.maxn(lsp.rpc.client_errors)
+local client_errors_offset = 0
+
+local function client_error(name)
+ client_errors_offset = client_errors_offset + 1
+ local index = client_errors_base + client_errors_offset
+ return { [name] = index, [index] = name }
+end
+
--- Error codes to be used with `on_error` from |vim.lsp.start_client|.
--- Can be used to look up the string from a the number or the number
--- from the string.
--- @nodoc
lsp.client_errors = tbl_extend(
'error',
- lsp_rpc.client_errors,
- vim.tbl_add_reverse_lookup({
- BEFORE_INIT_CALLBACK_ERROR = table.maxn(lsp_rpc.client_errors) + 1,
- ON_INIT_CALLBACK_ERROR = table.maxn(lsp_rpc.client_errors) + 2,
- ON_ATTACH_ERROR = table.maxn(lsp_rpc.client_errors) + 3,
- })
+ lsp.rpc.client_errors,
+ client_error('BEFORE_INIT_CALLBACK_ERROR'),
+ client_error('ON_INIT_CALLBACK_ERROR'),
+ client_error('ON_ATTACH_ERROR'),
+ client_error('ON_EXIT_CALLBACK_ERROR')
)
---- Normalizes {encoding} to valid LSP encoding names.
----
----@param encoding (string) Encoding to normalize
----@return string # normalized encoding name
-local function validate_encoding(encoding)
- validate({
- encoding = { encoding, 's' },
- })
- return valid_encodings[encoding:lower()]
- or error(
- string.format(
- "Invalid offset encoding %q. Must be one of: 'utf-8', 'utf-16', 'utf-32'",
- encoding
- )
- )
-end
-
----@internal
---- Parses a command invocation into the command itself and its args. If there
---- are no arguments, an empty table is returned as the second argument.
----
----@param input string[]
----@return string command, string[] args #the command and arguments
-function lsp._cmd_parts(input)
- validate({
- cmd = {
- input,
- function()
- return vim.tbl_islist(input)
- end,
- 'list',
- },
- })
-
- local cmd = input[1]
- local cmd_args = {}
- -- Don't mutate our input.
- for i, v in ipairs(input) do
- validate({ ['cmd argument'] = { v, 's' } })
- if i > 1 then
- table.insert(cmd_args, v)
- end
- end
- return cmd, cmd_args
-end
-
---- Augments a validator function with support for optional (nil) values.
----
----@param fn (fun(v): boolean) The original validator function; should return a
----bool.
----@return fun(v): boolean # The augmented function. Also returns true if {v} is
----`nil`.
-local function optional_validator(fn)
- return function(v)
- return v == nil or fn(v)
- end
-end
-
---- Validates a client configuration as given to |vim.lsp.start_client()|.
----
----@param config (lsp.ClientConfig)
----@return (string|fun(dispatchers:table):table) Command
----@return string[] Arguments
----@return string Encoding.
-local function validate_client_config(config)
- validate({
- config = { config, 't' },
- })
- validate({
- handlers = { config.handlers, 't', true },
- capabilities = { config.capabilities, 't', true },
- cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), 'directory' },
- cmd_env = { config.cmd_env, 't', true },
- detached = { config.detached, 'b', true },
- name = { config.name, 's', true },
- on_error = { config.on_error, 'f', true },
- on_exit = { config.on_exit, 'f', true },
- on_init = { config.on_init, 'f', true },
- settings = { config.settings, 't', true },
- commands = { config.commands, 't', true },
- before_init = { config.before_init, 'f', true },
- offset_encoding = { config.offset_encoding, 's', true },
- flags = { config.flags, 't', true },
- get_language_id = { config.get_language_id, 'f', true },
- })
- assert(
- (
- not config.flags
- or not config.flags.debounce_text_changes
- or type(config.flags.debounce_text_changes) == 'number'
- ),
- 'flags.debounce_text_changes must be a number with the debounce time in milliseconds'
- )
-
- local cmd, cmd_args --- @type (string|fun(dispatchers:table):table), string[]
- local config_cmd = config.cmd
- if type(config_cmd) == 'function' then
- cmd = config_cmd
- else
- cmd, cmd_args = lsp._cmd_parts(config_cmd)
- end
- local offset_encoding = valid_encodings.UTF16
- if config.offset_encoding then
- offset_encoding = validate_encoding(config.offset_encoding)
- end
-
- return cmd, cmd_args, offset_encoding
-end
-
+---@private
--- Returns full text of buffer {bufnr} as a string.
---
---@param bufnr (number) Buffer handle, or 0 for current.
---@return string # Buffer text as string.
-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)
+function lsp._buf_get_full_text(bufnr)
+ local line_ending = lsp._buf_get_line_ending(bufnr)
+ local text = table.concat(api.nvim_buf_get_lines(bufnr, 0, -1, true), line_ending)
if vim.bo[bufnr].eol then
text = text .. line_ending
end
@@ -327,484 +188,26 @@ end
---@param fn (T) Function to run
---@return T
local function once(fn)
- local value --- @type any
+ local value --- @type function
local ran = false
return function(...)
if not ran then
- value = fn(...)
+ value = fn(...) --- @type function
ran = true
end
return value
end
end
-local changetracking = {}
-do
- ---@private
- ---
- --- LSP has 3 different sync modes:
- --- - None (Servers will read the files themselves when needed)
- --- - Full (Client sends the full buffer content on updates)
- --- - Incremental (Client sends only the changed parts)
- ---
- --- Changes are tracked per buffer.
- --- A buffer can have multiple clients attached and each client needs to send the changes
- --- To minimize the amount of changesets to compute, computation is grouped:
- ---
- --- None: One group for all clients
- --- Full: One group for all clients
- --- Incremental: One group per `offset_encoding`
- ---
- --- Sending changes can be debounced per buffer. To simplify the implementation the
- --- smallest debounce interval is used and we don't group clients by different intervals.
- ---
- --- @class CTGroup
- --- @field sync_kind integer TextDocumentSyncKind, considers config.flags.allow_incremental_sync
- --- @field offset_encoding "utf-8"|"utf-16"|"utf-32"
- ---
- --- @class CTBufferState
- --- @field name string name of the buffer
- --- @field lines string[] snapshot of buffer lines from last didChange
- --- @field lines_tmp string[]
- --- @field pending_changes table[] List of debounced changes in incremental sync mode
- --- @field timer nil|uv.uv_timer_t uv_timer
- --- @field last_flush nil|number uv.hrtime of the last flush/didChange-notification
- --- @field needs_flush boolean true if buffer updates haven't been sent to clients/servers yet
- --- @field refs integer how many clients are using this group
- ---
- --- @class CTGroupState
- --- @field buffers table<integer, CTBufferState>
- --- @field debounce integer debounce duration in ms
- --- @field clients table<integer, table> clients using this state. {client_id, client}
-
- ---@param group CTGroup
- ---@return string
- local function group_key(group)
- if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then
- return tostring(group.sync_kind) .. '\0' .. group.offset_encoding
- end
- return tostring(group.sync_kind)
- end
-
- ---@private
- ---@type table<CTGroup, CTGroupState>
- local state_by_group = setmetatable({}, {
- __index = function(tbl, k)
- return rawget(tbl, group_key(k))
- end,
- __newindex = function(tbl, k, v)
- rawset(tbl, group_key(k), v)
- end,
- })
-
- ---@return CTGroup
- local function get_group(client)
- local allow_inc_sync = if_nil(client.config.flags.allow_incremental_sync, true)
- local change_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'change')
- local sync_kind = change_capability or protocol.TextDocumentSyncKind.None
- if not allow_inc_sync and change_capability == protocol.TextDocumentSyncKind.Incremental then
- sync_kind = protocol.TextDocumentSyncKind.Full
- end
- return {
- sync_kind = sync_kind,
- offset_encoding = client.offset_encoding,
- }
- end
-
- ---@param state CTBufferState
- local function incremental_changes(state, encoding, bufnr, firstline, lastline, new_lastline)
- local prev_lines = state.lines
- local curr_lines = state.lines_tmp
-
- local changed_lines = nvim_buf_get_lines(bufnr, firstline, new_lastline, true)
- for i = 1, firstline do
- curr_lines[i] = prev_lines[i]
- end
- for i = firstline + 1, new_lastline do
- curr_lines[i] = changed_lines[i - firstline]
- end
- for i = lastline + 1, #prev_lines do
- curr_lines[i - lastline + new_lastline] = prev_lines[i]
- end
- if tbl_isempty(curr_lines) then
- -- Can happen when deleting the entire contents of a buffer, see https://github.com/neovim/neovim/issues/16259.
- curr_lines[1] = ''
- end
-
- local line_ending = buf_get_line_ending(bufnr)
- local incremental_change = sync.compute_diff(
- state.lines,
- curr_lines,
- firstline,
- lastline,
- new_lastline,
- encoding,
- line_ending
- )
-
- -- Double-buffering of lines tables is used to reduce the load on the garbage collector.
- -- At this point the prev_lines table is useless, but its internal storage has already been allocated,
- -- so let's keep it around for the next didChange event, in which it will become the next
- -- curr_lines table. Note that setting elements to nil doesn't actually deallocate slots in the
- -- internal storage - it merely marks them as free, for the GC to deallocate them.
- for i in ipairs(prev_lines) do
- prev_lines[i] = nil
- end
- state.lines = curr_lines
- state.lines_tmp = prev_lines
-
- return incremental_change
- end
-
- ---@private
- function changetracking.init(client, bufnr)
- assert(client.offset_encoding, 'lsp client must have an offset_encoding')
- local group = get_group(client)
- local state = state_by_group[group]
- if state then
- state.debounce = math.min(state.debounce, client.config.flags.debounce_text_changes or 150)
- state.clients[client.id] = client
- else
- state = {
- buffers = {},
- debounce = client.config.flags.debounce_text_changes or 150,
- clients = {
- [client.id] = client,
- },
- }
- state_by_group[group] = state
- end
- local buf_state = state.buffers[bufnr]
- if buf_state then
- buf_state.refs = buf_state.refs + 1
- else
- buf_state = {
- name = api.nvim_buf_get_name(bufnr),
- lines = {},
- lines_tmp = {},
- pending_changes = {},
- needs_flush = false,
- refs = 1,
- }
- state.buffers[bufnr] = buf_state
- if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then
- buf_state.lines = nvim_buf_get_lines(bufnr, 0, -1, true)
- end
- end
- end
-
- ---@private
- function changetracking._get_and_set_name(client, bufnr, name)
- local state = state_by_group[get_group(client)] or {}
- local buf_state = (state.buffers or {})[bufnr]
- local old_name = buf_state.name
- buf_state.name = name
- return old_name
- end
-
- ---@private
- function changetracking.reset_buf(client, bufnr)
- changetracking.flush(client, bufnr)
- local state = state_by_group[get_group(client)]
- if not state then
- return
- end
- assert(state.buffers, 'CTGroupState must have buffers')
- local buf_state = state.buffers[bufnr]
- buf_state.refs = buf_state.refs - 1
- assert(buf_state.refs >= 0, 'refcount on buffer state must not get negative')
- if buf_state.refs == 0 then
- state.buffers[bufnr] = nil
- changetracking._reset_timer(buf_state)
- end
- end
-
- ---@private
- function changetracking.reset(client)
- local state = state_by_group[get_group(client)]
- if not state then
- return
- end
- state.clients[client.id] = nil
- if vim.tbl_count(state.clients) == 0 then
- for _, buf_state in pairs(state.buffers) do
- changetracking._reset_timer(buf_state)
- end
- state.buffers = {}
- end
- end
-
- -- Adjust debounce time by taking time of last didChange notification into
- -- consideration. If the last didChange happened more than `debounce` time ago,
- -- debounce can be skipped and otherwise maybe reduced.
- --
- -- This turns the debounce into a kind of client rate limiting
- --
- ---@param debounce integer
- ---@param buf_state CTBufferState
- ---@return number
- local function next_debounce(debounce, buf_state)
- if debounce == 0 then
- return 0
- end
- local ns_to_ms = 0.000001
- if not buf_state.last_flush then
- return debounce
- end
- local now = uv.hrtime()
- local ms_since_last_flush = (now - buf_state.last_flush) * ns_to_ms
- return math.max(debounce - ms_since_last_flush, 0)
- end
-
- ---@param bufnr integer
- ---@param sync_kind integer protocol.TextDocumentSyncKind
- ---@param state CTGroupState
- ---@param buf_state CTBufferState
- local function send_changes(bufnr, sync_kind, state, buf_state)
- if not buf_state.needs_flush then
- return
- end
- buf_state.last_flush = uv.hrtime()
- buf_state.needs_flush = false
-
- if not api.nvim_buf_is_valid(bufnr) then
- buf_state.pending_changes = {}
- return
- end
-
- local changes
- if sync_kind == protocol.TextDocumentSyncKind.None then
- return
- elseif sync_kind == protocol.TextDocumentSyncKind.Incremental then
- changes = buf_state.pending_changes
- buf_state.pending_changes = {}
- else
- changes = {
- { text = buf_get_full_text(bufnr) },
- }
- end
- local uri = vim.uri_from_bufnr(bufnr)
- for _, client in pairs(state.clients) do
- if not client.is_stopped() and lsp.buf_is_attached(bufnr, client.id) then
- client.notify(ms.textDocument_didChange, {
- textDocument = {
- uri = uri,
- version = util.buf_versions[bufnr],
- },
- contentChanges = changes,
- })
- end
- end
- end
-
- ---@private
- function changetracking.send_changes(bufnr, firstline, lastline, new_lastline)
- local groups = {} ---@type table<string,CTGroup>
- for _, client in pairs(lsp.get_clients({ bufnr = bufnr })) do
- local group = get_group(client)
- groups[group_key(group)] = group
- end
- for _, group in pairs(groups) do
- local state = state_by_group[group]
- if not state then
- error(
- string.format(
- 'changetracking.init must have been called for all LSP clients. group=%s states=%s',
- vim.inspect(group),
- vim.inspect(vim.tbl_keys(state_by_group))
- )
- )
- end
- local buf_state = state.buffers[bufnr]
- buf_state.needs_flush = true
- changetracking._reset_timer(buf_state)
- local debounce = next_debounce(state.debounce, buf_state)
- if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then
- -- This must be done immediately and cannot be delayed
- -- The contents would further change and startline/endline may no longer fit
- local changes = incremental_changes(
- buf_state,
- group.offset_encoding,
- bufnr,
- firstline,
- lastline,
- new_lastline
- )
- table.insert(buf_state.pending_changes, changes)
- end
- if debounce == 0 then
- send_changes(bufnr, group.sync_kind, state, buf_state)
- else
- local timer = assert(uv.new_timer(), 'Must be able to create timer')
- buf_state.timer = timer
- timer:start(
- debounce,
- 0,
- vim.schedule_wrap(function()
- changetracking._reset_timer(buf_state)
- send_changes(bufnr, group.sync_kind, state, buf_state)
- end)
- )
- end
- end
- end
-
- ---@private
- function changetracking._reset_timer(buf_state)
- local timer = buf_state.timer
- if timer then
- buf_state.timer = nil
- if not timer:is_closing() then
- timer:stop()
- timer:close()
- end
- end
- end
-
- --- Flushes any outstanding change notification.
- ---@private
- function changetracking.flush(client, bufnr)
- local group = get_group(client)
- local state = state_by_group[group]
- if not state then
- return
- end
- if bufnr then
- local buf_state = state.buffers[bufnr] or {}
- changetracking._reset_timer(buf_state)
- send_changes(bufnr, group.sync_kind, state, buf_state)
- else
- for buf, buf_state in pairs(state.buffers) do
- changetracking._reset_timer(buf_state)
- send_changes(buf, group.sync_kind, state, buf_state)
- end
- end
- end
-end
-
---- Default handler for the 'textDocument/didOpen' LSP notification.
----
----@param bufnr integer Number of the buffer, or 0 for current
----@param client table Client object
-local function text_document_did_open_handler(bufnr, client)
- changetracking.init(client, bufnr)
- if not vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then
- return
- end
- if not api.nvim_buf_is_loaded(bufnr) then
- return
- end
- local filetype = vim.bo[bufnr].filetype
-
- local params = {
- textDocument = {
- version = 0,
- uri = vim.uri_from_bufnr(bufnr),
- languageId = client.config.get_language_id(bufnr, filetype),
- text = buf_get_full_text(bufnr),
- },
- }
- client.notify(ms.textDocument_didOpen, params)
- util.buf_versions[bufnr] = params.textDocument.version
-
- -- Next chance we get, we should re-do the diagnostics
- vim.schedule(function()
- -- Protect against a race where the buffer disappears
- -- between `did_open_handler` and the scheduled function firing.
- if api.nvim_buf_is_valid(bufnr) then
- local namespace = vim.lsp.diagnostic.get_namespace(client.id)
- vim.diagnostic.show(namespace, bufnr)
- end
- end)
-end
-
--- FIXME: DOC: Shouldn't need to use a dummy function
---
---- LSP client object. You can get an active client object via
---- |vim.lsp.get_client_by_id()| or |vim.lsp.get_clients()|.
----
---- - Methods:
----
---- - request(method, params, [handler], bufnr)
---- Sends a request to the server.
---- This is a thin wrapper around {client.rpc.request} with some additional
---- checking.
---- If {handler} is not specified, If one is not found there, then an error will occur.
---- Returns: {status}, {[client_id]}. {status} is a boolean indicating if
---- the notification was successful. If it is `false`, then it will always
---- be `false` (the client has shutdown).
---- If {status} is `true`, the function returns {request_id} as the second
---- result. You can use this with `client.cancel_request(request_id)`
---- to cancel the request.
----
---- - request_sync(method, params, timeout_ms, bufnr)
---- Sends a request to the server and synchronously waits for the response.
---- This is a wrapper around {client.request}
---- Returns: { err=err, result=result }, a dictionary, where `err` and `result` come from
---- the |lsp-handler|. On timeout, cancel or error, returns `(nil, err)` where `err` is a
---- string describing the failure reason. If the request was unsuccessful returns `nil`.
----
---- - notify(method, params)
---- Sends a notification to an LSP server.
---- Returns: a boolean to indicate if the notification was successful. If
---- it is false, then it will always be false (the client has shutdown).
----
---- - cancel_request(id)
---- Cancels a request with a given request id.
---- Returns: same as `notify()`.
----
---- - stop([force])
---- Stops a client, optionally with force.
---- By default, it will just ask the server to shutdown without force.
---- If you request to stop a client which has previously been requested to
---- shutdown, it will automatically escalate and force shutdown.
----
---- - is_stopped()
---- Checks whether a client is stopped.
---- Returns: true if the client is fully stopped.
----
---- - on_attach(client, bufnr)
---- Runs the on_attach function from the client's config if it was defined.
---- Useful for buffer-local setup.
+--- @class vim.lsp.start.Opts
+--- @inlinedoc
---
---- - Members
---- - {id} (number): The id allocated to the client.
+--- Predicate used to decide if a client should be re-used. Used on all
+--- running clients. The default implementation re-uses a client if name and
+--- root_dir matches.
+--- @field reuse_client fun(client: vim.lsp.Client, config: table): boolean
---
---- - {name} (string): If a name is specified on creation, that will be
---- used. Otherwise it is just the client id. This is used for
---- logs and messages.
----
---- - {rpc} (table): RPC client object, for low level interaction with the
---- client. See |vim.lsp.rpc.start()|.
----
---- - {offset_encoding} (string): The encoding used for communicating
---- with the server. You can modify this in the `config`'s `on_init` method
---- before text is sent to the server.
----
---- - {handlers} (table): The handlers used by the client as described in |lsp-handler|.
----
---- - {requests} (table): The current pending requests in flight
---- to the server. Entries are key-value pairs with the key
---- being the request ID while the value is a table with `type`,
---- `bufnr`, and `method` key-value pairs. `type` is either "pending"
---- for an active request, or "cancel" for a cancel request. It will
---- be "complete" ephemerally while executing |LspRequest| autocmds
---- when replies are received from the server.
----
---- - {config} (table): copy of the table that was passed by the user
---- to |vim.lsp.start_client()|.
----
---- - {server_capabilities} (table): Response from the server sent on
---- `initialize` describing the server's capabilities.
----
---- - {progress} A ring buffer (|vim.ringbuf()|) containing progress messages
---- sent by the server.
-function lsp.client()
- error()
-end
-
---- @class lsp.StartOpts
---- @field reuse_client fun(client: lsp.Client, config: table): boolean
+--- Buffer handle to attach to if starting or re-using a client (0 for current).
--- @field bufnr integer
--- Create a new LSP client and start a language server or reuses an already
@@ -824,8 +227,7 @@ end
--- See |vim.lsp.start_client()| for all available options. The most important are:
---
--- - `name` arbitrary name for the LSP client. Should be unique per language server.
---- - `cmd` command (in list form) used to start the language server. Must be absolute, or found on
---- `$PATH`. Shell constructs like `~` are not expanded.
+--- - `cmd` command string[] or function, described at |vim.lsp.start_client()|.
--- - `root_dir` path to the project root. By default this is used to decide if an existing client
--- should be re-used. The example above uses |vim.fs.find()| and |vim.fs.dirname()| to detect the
--- root by traversing the file system upwards starting from the current directory until either
@@ -844,30 +246,18 @@ end
--- Either use |:au|, |nvim_create_autocmd()| or put the call in a
--- `ftplugin/<filetype_name>.lua` (See |ftplugin-name|)
---
----@param config table Same configuration as documented in |vim.lsp.start_client()|
----@param opts (nil|lsp.StartOpts) Optional keyword arguments:
---- - reuse_client (fun(client: client, config: table): boolean)
---- Predicate used to decide if a client should be re-used.
---- Used on all running clients.
---- The default implementation re-uses a client if name
---- and root_dir matches.
---- - bufnr (number)
---- Buffer handle to attach to if starting or re-using a
---- client (0 for current).
----@return integer|nil client_id
+--- @param config vim.lsp.ClientConfig Configuration for the server.
+--- @param opts vim.lsp.start.Opts? Optional keyword arguments
+--- @return integer? client_id
function lsp.start(config, opts)
opts = opts or {}
local reuse_client = opts.reuse_client
or function(client, conf)
- return client.config.root_dir == conf.root_dir and client.name == conf.name
+ return client.root_dir == conf.root_dir and client.name == conf.name
end
- if not config.name and type(config.cmd) == 'table' then
- config.name = config.cmd[1] and vim.fs.basename(config.cmd[1]) or nil
- end
- local bufnr = opts.bufnr
- if bufnr == nil or bufnr == 0 then
- bufnr = api.nvim_get_current_buf()
- end
+
+ local bufnr = resolve_bufnr(opts.bufnr)
+
for _, clients in ipairs({ uninitialized_clients, lsp.get_clients() }) do
for _, client in pairs(clients) do
if reuse_client(client, config) then
@@ -876,10 +266,13 @@ function lsp.start(config, opts)
end
end
end
+
local client_id = lsp.start_client(config)
- if client_id == nil then
- return nil -- lsp.start_client will have printed an error
+
+ if not client_id then
+ return -- lsp.start_client will have printed an error
end
+
lsp.buf_attach_client(bufnr, client_id)
return client_id
end
@@ -890,9 +283,11 @@ end
---@return string
function lsp.status()
local percentage = nil
- local messages = {}
+ local messages = {} --- @type string[]
for _, client in ipairs(vim.lsp.get_clients()) do
+ --- @diagnostic disable-next-line:no-unknown
for progress in client.progress do
+ --- @cast progress {token: lsp.ProgressToken, value: lsp.LSPAny}
local value = progress.value
if type(value) == 'table' and value.kind then
local message = value.message and (value.title .. ': ' .. value.message) or value.title
@@ -913,12 +308,15 @@ function lsp.status()
end
-- Determines whether the given option can be set by `set_defaults`.
+---@param bufnr integer
+---@param option string
+---@return boolean
local function is_empty_or_default(bufnr, option)
if vim.bo[bufnr][option] == '' then
return true
end
- local info = vim.api.nvim_get_option_info2(option, { buf = bufnr })
+ local info = api.nvim_get_option_info2(option, { buf = bufnr })
local scriptinfo = vim.tbl_filter(function(e)
return e.sid == info.last_set_sid
end, vim.fn.getscriptinfo())
@@ -931,7 +329,8 @@ local function is_empty_or_default(bufnr, option)
end
---@private
----@param client lsp.Client
+---@param client vim.lsp.Client
+---@param bufnr integer
function lsp._set_defaults(client, bufnr)
if
client.supports_method(ms.textDocument_definition) and is_empty_or_default(bufnr, 'tagfunc')
@@ -964,818 +363,151 @@ function lsp._set_defaults(client, bufnr)
end
end
---- @class lsp.ClientConfig
---- @field cmd (string[]|fun(dispatchers: table):table)
---- @field cmd_cwd string
---- @field cmd_env (table)
---- @field detached boolean
---- @field workspace_folders (table)
---- @field capabilities lsp.ClientCapabilities
---- @field handlers table<string,function>
---- @field settings table
---- @field commands table
---- @field init_options table
---- @field name string
---- @field get_language_id fun(bufnr: integer, filetype: string): string
---- @field offset_encoding string
---- @field on_error fun(code: integer)
---- @field before_init function
---- @field on_init function
---- @field on_exit fun(code: integer, signal: integer, client_id: integer)
---- @field on_attach fun(client: lsp.Client, bufnr: integer)
---- @field trace 'off'|'messages'|'verbose'|nil
---- @field flags table
---- @field root_dir string
-
--- FIXME: DOC: Currently all methods on the `vim.lsp.client` object are
--- documented twice: Here, and on the methods themselves (e.g.
--- `client.request()`). This is a workaround for the vimdoc generator script
--- not handling method names correctly. If you change the documentation on
--- either, please make sure to update the other as well.
---
---- Starts and initializes a client with the given configuration.
----
---- Field `cmd` in {config} is required.
----
----@param config (lsp.ClientConfig) Configuration for the 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`
---- 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 table.
---- Non-string values are coerced to string.
---- Example:
---- <pre>
---- { PORT = 8080; HOST = "0.0.0.0"; }
---- </pre>
----
---- - detached: (boolean, default true) Daemonize the server process so that it runs in a
---- separate process group from Nvim. Nvim will shutdown the process on exit, but if Nvim fails to
---- exit cleanly this could leave behind orphaned server processes.
----
---- - workspace_folders: (table) List of workspace folders passed to the
---- language server. For backwards compatibility rootUri and rootPath will be
---- derived from the first workspace folder in this list. See `workspaceFolders` in
---- the LSP spec.
----
---- - capabilities: Map overriding the default capabilities defined by
---- \|vim.lsp.protocol.make_client_capabilities()|, passed to the language
---- server on initialization. Hint: use make_client_capabilities() and modify
---- its result.
---- - Note: To send an empty dictionary use |vim.empty_dict()|, else it will be encoded as an
---- array.
----
---- - handlers: Map of language server method names to |lsp-handler|
----
---- - settings: Map with language server specific settings. These are
---- returned to the language server if requested via `workspace/configuration`.
---- Keys are case-sensitive.
----
---- - commands: table Table that maps string of clientside commands to user-defined functions.
---- Commands passed to start_client take precedence over the global command registry. Each key
---- must be a unique command name, and the value is a function which is called if any LSP action
---- (code action, code lenses, ...) triggers the command.
----
---- - init_options Values to pass in the initialization request
---- as `initializationOptions`. See `initialize` in the LSP spec.
----
---- - name: (string, default=client-id) Name in log messages.
----
---- - get_language_id: function(bufnr, filetype) -> language ID as string.
---- Defaults to the filetype.
----
---- - offset_encoding: (default="utf-16") One of "utf-8", "utf-16",
---- or "utf-32" which is the encoding that the LSP server expects. Client does
---- not verify this is correct.
----
---- - on_error: Callback with parameters (code, ...), invoked
---- when the client operation throws an error. `code` is a number describing
---- the error. Other arguments may be passed depending on the error kind. See
---- `vim.lsp.rpc.client_errors` for possible errors.
---- Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name.
----
---- - before_init: Callback with parameters (initialize_params, config)
---- invoked before the LSP "initialize" phase, where `params` contains the
---- parameters being sent to the server and `config` is the config that was
---- passed to |vim.lsp.start_client()|. You can use this to modify parameters before
---- they are sent.
----
---- - on_init: Callback (client, initialize_result) invoked after LSP
---- "initialize", where `result` is a table of `capabilities` and anything else
---- the server may send. For example, clangd sends
---- `initialize_result.offsetEncoding` if `capabilities.offsetEncoding` was
---- sent to it. You can only modify the `client.offset_encoding` here before
---- any notifications are sent. Most language servers expect to be sent client specified settings after
---- initialization. Nvim does not make this assumption. A
---- `workspace/didChangeConfiguration` notification should be sent
---- to the server during on_init.
----
---- - on_exit Callback (code, signal, client_id) invoked on client
---- exit.
---- - code: exit code of the process
---- - signal: number describing the signal used to terminate (if any)
---- - client_id: client handle
----
---- - on_attach: Callback (client, bufnr) invoked when client
---- attaches to a buffer.
----
---- - trace: ("off" | "messages" | "verbose" | nil) passed directly to the language
---- server in the initialize request. Invalid/empty values will default to "off"
----
---- - flags: A table with flags for the client. The current (experimental) flags are:
---- - allow_incremental_sync (bool, default true): Allow using incremental sync for buffer edits
---- - debounce_text_changes (number, default 150): Debounce didChange
---- notifications to the server by the given number in milliseconds. No debounce
---- occurs if nil
---- - exit_timeout (number|boolean, default false): Milliseconds to wait for server to
---- exit cleanly after sending the "shutdown" request before sending kill -15.
---- If set to false, nvim exits immediately after sending the "shutdown" request to the server.
----
---- - root_dir: (string) Directory where the LSP
---- server will base its workspaceFolders, rootUri, and rootPath
---- on initialization.
----
----@return integer|nil client_id. |vim.lsp.get_client_by_id()| Note: client may not be
---- fully initialized. Use `on_init` to do any actions once
---- the client has been initialized.
-function lsp.start_client(config)
- local cmd, cmd_args, offset_encoding = validate_client_config(config)
-
- config.flags = config.flags or {}
- config.settings = config.settings or {}
-
- -- By default, get_language_id just returns the exact filetype it is passed.
- -- It is possible to pass in something that will calculate a different filetype,
- -- to be sent by the client.
- config.get_language_id = config.get_language_id or function(_, filetype)
- return filetype
- end
-
- local client_id = next_client_id()
-
- local handlers = config.handlers or {}
- local name = config.name or tostring(client_id)
- local log_prefix = string.format('LSP[%s]', name)
-
- local dispatch = {}
-
- --- Returns the handler associated with an LSP method.
- --- Returns the default handler if the user hasn't set a custom one.
- ---
- ---@param method (string) LSP method name
- ---@return lsp-handler|nil The handler for the given method, if defined, or the default from |vim.lsp.handlers|
- local function resolve_handler(method)
- return handlers[method] or default_handlers[method]
- end
-
- ---@private
- --- Handles a notification sent by an LSP server by invoking the
- --- corresponding handler.
- ---
- ---@param method (string) LSP method name
- ---@param params (table) The parameters for that method.
- function dispatch.notification(method, params)
- if log.trace() then
- log.trace('notification', method, params)
- end
- local handler = resolve_handler(method)
- if handler then
- -- Method name is provided here for convenience.
- handler(nil, params, { method = method, client_id = client_id })
- end
- end
-
- ---@private
- --- Handles a request from an LSP server by invoking the corresponding handler.
- ---
- ---@param method (string) LSP method name
- ---@param params (table) The parameters for that method
- function dispatch.server_request(method, params)
- if log.trace() then
- log.trace('server_request', method, params)
- end
- local handler = resolve_handler(method)
- if handler then
- if log.trace() then
- log.trace('server_request: found handler for', method)
- end
- return handler(nil, params, { method = method, client_id = client_id })
- end
- if log.warn() then
- log.warn('server_request: no handler found for', method)
- end
- return nil, lsp.rpc_response_error(protocol.ErrorCodes.MethodNotFound)
+--- Reset defaults set by `set_defaults`.
+--- Must only be called if the last client attached to a buffer exits.
+local function reset_defaults(bufnr)
+ if vim.bo[bufnr].tagfunc == 'v:lua.vim.lsp.tagfunc' then
+ vim.bo[bufnr].tagfunc = nil
end
-
- --- Logs the given error to the LSP log and to the error buffer.
- --- @param code integer Error code
- --- @param err any Error arguments
- local function write_error(code, err)
- if log.error() then
- log.error(log_prefix, 'on_error', { code = lsp.client_errors[code], err = err })
- end
- err_message(log_prefix, ': Error ', lsp.client_errors[code], ': ', vim.inspect(err))
- end
-
- ---@private
- --- Invoked when the client operation throws an error.
- ---
- ---@param code (integer) Error code
- ---@param err (...) Other arguments may be passed depending on the error kind
- ---@see vim.lsp.rpc.client_errors for possible errors. Use
- ---`vim.lsp.rpc.client_errors[code]` to get a human-friendly name.
- function dispatch.on_error(code, err)
- write_error(code, err)
- if config.on_error then
- local status, usererr = pcall(config.on_error, code, err)
- if not status then
- local _ = log.error() and log.error(log_prefix, 'user on_error failed', { err = usererr })
- err_message(log_prefix, ' user on_error failed: ', tostring(usererr))
- end
- end
+ if vim.bo[bufnr].omnifunc == 'v:lua.vim.lsp.omnifunc' then
+ vim.bo[bufnr].omnifunc = nil
end
-
- --- Reset defaults set by `set_defaults`.
- --- Must only be called if the last client attached to a buffer exits.
- local function reset_defaults(bufnr)
- if vim.bo[bufnr].tagfunc == 'v:lua.vim.lsp.tagfunc' then
- vim.bo[bufnr].tagfunc = nil
- end
- if vim.bo[bufnr].omnifunc == 'v:lua.vim.lsp.omnifunc' then
- vim.bo[bufnr].omnifunc = nil
- end
- if vim.bo[bufnr].formatexpr == 'v:lua.vim.lsp.formatexpr()' then
- vim.bo[bufnr].formatexpr = nil
- end
- api.nvim_buf_call(bufnr, function()
- local keymap = vim.fn.maparg('K', 'n', false, true)
- if keymap and keymap.callback == vim.lsp.buf.hover then
- vim.keymap.del('n', 'K', { buffer = bufnr })
- end
- end)
+ if vim.bo[bufnr].formatexpr == 'v:lua.vim.lsp.formatexpr()' then
+ vim.bo[bufnr].formatexpr = nil
end
-
- ---@private
- --- Invoked on client exit.
- ---
- ---@param code (integer) exit code of the process
- ---@param signal (integer) the signal used to terminate (if any)
- function dispatch.on_exit(code, signal)
- if config.on_exit then
- pcall(config.on_exit, code, signal, client_id)
+ api.nvim_buf_call(bufnr, function()
+ local keymap = vim.fn.maparg('K', 'n', false, true)
+ if keymap and keymap.callback == vim.lsp.buf.hover then
+ vim.keymap.del('n', 'K', { buffer = bufnr })
end
+ end)
+end
- local client = active_clients[client_id] and active_clients[client_id]
- or uninitialized_clients[client_id]
-
- for bufnr, client_ids in pairs(all_buffer_active_clients) do
- if client_ids[client_id] then
- vim.schedule(function()
- if client and client.attached_buffers[bufnr] then
- nvim_exec_autocmds('LspDetach', {
- buffer = bufnr,
- modeline = false,
- data = { client_id = client_id },
- })
- end
-
- local namespace = vim.lsp.diagnostic.get_namespace(client_id)
- vim.diagnostic.reset(namespace, bufnr)
-
- client_ids[client_id] = nil
- if vim.tbl_isempty(client_ids) then
- reset_defaults(bufnr)
- end
- end)
- end
+--- @param client vim.lsp.Client
+local function on_client_init(client)
+ local id = client.id
+ uninitialized_clients[id] = nil
+ -- Only assign after initialized.
+ active_clients[id] = client
+ -- If we had been registered before we start, then send didOpen This can
+ -- happen if we attach to buffers before initialize finishes or if
+ -- someone restarts a client.
+ for bufnr, client_ids in pairs(all_buffer_active_clients) do
+ if client_ids[id] then
+ client.on_attach(bufnr)
end
-
- -- Schedule the deletion of the client object so that it exists in the execution of LspDetach
- -- autocommands
- vim.schedule(function()
- active_clients[client_id] = nil
- uninitialized_clients[client_id] = nil
-
- -- Client can be absent if executable starts, but initialize fails
- -- init/attach won't have happened
- if client then
- changetracking.reset(client)
- end
- if code ~= 0 or (signal ~= 0 and signal ~= 15) then
- local msg = string.format(
- 'Client %s quit with exit code %s and signal %s. Check log for errors: %s',
- name,
- code,
- signal,
- lsp.get_log_path()
- )
- vim.notify(msg, vim.log.levels.WARN)
- end
- end)
- end
-
- -- Start the RPC client.
- local rpc
- if type(cmd) == 'function' then
- rpc = cmd(dispatch)
- else
- rpc = lsp_rpc.start(cmd, cmd_args, dispatch, {
- cwd = config.cmd_cwd,
- env = config.cmd_env,
- detached = config.detached,
- })
end
+end
- -- Return nil if client fails to start
- if not rpc then
- return
- end
-
- ---@class lsp.Client
- local client = {
- id = client_id,
- name = name,
- rpc = rpc,
- offset_encoding = offset_encoding,
- config = config,
- attached_buffers = {},
-
- handlers = handlers,
- commands = config.commands or {},
-
- --- @type table<integer,{ type: string, bufnr: integer, method: string}>
- requests = {},
-
- --- Contains $/progress report messages.
- --- They have the format {token: integer|string, value: any}
- --- For "work done progress", value will be one of:
- --- - lsp.WorkDoneProgressBegin,
- --- - lsp.WorkDoneProgressReport (extended with title from Begin)
- --- - lsp.WorkDoneProgressEnd (extended with title from Begin)
- progress = vim.ringbuf(50),
-
- --- @type lsp.ServerCapabilities
- server_capabilities = {},
-
- ---@deprecated use client.progress instead
- messages = { name = name, messages = {}, progress = {}, status = {} },
- dynamic_capabilities = require('vim.lsp._dynamic').new(client_id),
- }
-
- ---@type table<string|integer, string> title of unfinished progress sequences by token
- client.progress.pending = {}
-
- --- @type lsp.ClientCapabilities
- client.config.capabilities = config.capabilities or protocol.make_client_capabilities()
-
- -- Store the uninitialized_clients for cleanup in case we exit before initialize finishes.
- uninitialized_clients[client_id] = client
-
- local function initialize()
- local valid_traces = {
- off = 'off',
- messages = 'messages',
- verbose = 'verbose',
- }
-
- local workspace_folders --- @type table[]?
- local root_uri --- @type string?
- local root_path --- @type string?
- if config.workspace_folders or config.root_dir then
- if config.root_dir and not config.workspace_folders then
- workspace_folders = {
- {
- uri = vim.uri_from_fname(config.root_dir),
- name = string.format('%s', config.root_dir),
- },
- }
- else
- workspace_folders = config.workspace_folders
- end
- root_uri = workspace_folders[1].uri
- root_path = vim.uri_to_fname(root_uri)
- else
- workspace_folders = nil
- root_uri = nil
- root_path = nil
- end
+--- @param code integer
+--- @param signal integer
+--- @param client_id integer
+local function on_client_exit(code, signal, client_id)
+ local client = active_clients[client_id] or uninitialized_clients[client_id]
- local initialize_params = {
- -- The process Id of the parent process that started the server. Is null if
- -- the process has not been started by another process. If the parent
- -- process is not alive then the server should exit (see exit notification)
- -- its process.
- processId = uv.os_getpid(),
- -- Information about the client
- -- since 3.15.0
- clientInfo = {
- name = 'Neovim',
- version = tostring(vim.version()),
- },
- -- The rootPath of the workspace. Is null if no folder is open.
- --
- -- @deprecated in favour of rootUri.
- rootPath = root_path or vim.NIL,
- -- The rootUri of the workspace. Is null if no folder is open. If both
- -- `rootPath` and `rootUri` are set `rootUri` wins.
- rootUri = root_uri or vim.NIL,
- -- The workspace folders configured in the client when the server starts.
- -- This property is only available if the client supports workspace folders.
- -- It can be `null` if the client supports workspace folders but none are
- -- configured.
- workspaceFolders = workspace_folders or vim.NIL,
- -- User provided initialization options.
- initializationOptions = config.init_options,
- -- The capabilities provided by the client (editor or tool)
- capabilities = config.capabilities,
- -- The initial trace setting. If omitted trace is disabled ("off").
- -- trace = "off" | "messages" | "verbose";
- trace = valid_traces[config.trace] or 'off',
- }
- if config.before_init then
- local status, err = pcall(config.before_init, initialize_params, config)
- if not status then
- write_error(lsp.client_errors.BEFORE_INIT_CALLBACK_ERROR, err)
- end
- end
-
- --- @param method string
- --- @param opts? {bufnr?: number}
- client.supports_method = function(method, opts)
- opts = opts or {}
- local required_capability = lsp._request_name_to_capability[method]
- -- if we don't know about the method, assume that the client supports it.
- if not required_capability then
- return true
- end
- if vim.tbl_get(client.server_capabilities, unpack(required_capability)) then
- return true
- else
- if client.dynamic_capabilities:supports_registration(method) then
- return client.dynamic_capabilities:supports(method, opts)
+ for bufnr, client_ids in pairs(all_buffer_active_clients) do
+ if client_ids[client_id] then
+ vim.schedule(function()
+ if client and client.attached_buffers[bufnr] then
+ api.nvim_exec_autocmds('LspDetach', {
+ buffer = bufnr,
+ modeline = false,
+ data = { client_id = client_id },
+ })
end
- return false
- end
- end
- local _ = log.trace() and log.trace(log_prefix, 'initialize_params', initialize_params)
- rpc.request('initialize', initialize_params, function(init_err, result)
- assert(not init_err, tostring(init_err))
- assert(result, 'server sent empty result')
- rpc.notify('initialized', vim.empty_dict())
- client.initialized = true
- uninitialized_clients[client_id] = nil
- client.workspace_folders = workspace_folders
-
- -- These are the cleaned up capabilities we use for dynamically deciding
- -- when to send certain events to clients.
- client.server_capabilities =
- assert(result.capabilities, "initialize result doesn't contain capabilities")
- client.server_capabilities = protocol.resolve_capabilities(client.server_capabilities)
-
- if client.server_capabilities.positionEncoding then
- client.offset_encoding = client.server_capabilities.positionEncoding
- end
-
- if next(config.settings) then
- client.notify(ms.workspace_didChangeConfiguration, { settings = config.settings })
- end
-
- if config.on_init then
- local status, err = pcall(config.on_init, client, result)
- if not status then
- write_error(lsp.client_errors.ON_INIT_CALLBACK_ERROR, err)
- end
- end
- local _ = log.info()
- and log.info(
- log_prefix,
- 'server_capabilities',
- { server_capabilities = client.server_capabilities }
- )
+ local namespace = vim.lsp.diagnostic.get_namespace(client_id)
+ vim.diagnostic.reset(namespace, bufnr)
- -- Only assign after initialized.
- active_clients[client_id] = client
- -- If we had been registered before we start, then send didOpen This can
- -- happen if we attach to buffers before initialize finishes or if
- -- someone restarts a client.
- for bufnr, client_ids in pairs(all_buffer_active_clients) do
- if client_ids[client_id] then
- client._on_attach(bufnr)
+ client_ids[client_id] = nil
+ if vim.tbl_isempty(client_ids) then
+ reset_defaults(bufnr)
end
- end
- end)
- end
-
- ---@nodoc
- --- Sends a request to the server.
- ---
- --- This is a thin wrapper around {client.rpc.request} with some additional
- --- checks for capabilities and handler availability.
- ---
- ---@param method string LSP method name.
- ---@param params table|nil LSP request params.
- ---@param handler lsp-handler|nil Response |lsp-handler| for this method.
- ---@param bufnr integer Buffer handle (0 for current).
- ---@return boolean status, integer|nil request_id {status} is a bool indicating
- ---whether the request was successful. If it is `false`, then it will
- ---always be `false` (the client has shutdown). If it was
- ---successful, then it will return {request_id} as the
- ---second result. You can use this with `client.cancel_request(request_id)`
- ---to cancel the-request.
- ---@see |vim.lsp.buf_request_all()|
- function client.request(method, params, handler, bufnr)
- if not handler then
- handler = assert(
- resolve_handler(method),
- string.format('not found: %q request handler for client %q.', method, client.name)
- )
- end
- -- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state
- changetracking.flush(client, bufnr)
- local version = util.buf_versions[bufnr]
- bufnr = resolve_bufnr(bufnr)
- if log.debug() then
- log.debug(log_prefix, 'client.request', client_id, method, params, handler, bufnr)
- end
- local success, request_id = rpc.request(method, params, function(err, result)
- local context = {
- method = method,
- client_id = client_id,
- bufnr = bufnr,
- params = params,
- version = version,
- }
- handler(err, result, context)
- end, function(request_id)
- local request = client.requests[request_id]
- request.type = 'complete'
- nvim_exec_autocmds('LspRequest', {
- buffer = api.nvim_buf_is_valid(bufnr) and bufnr or nil,
- modeline = false,
- data = { client_id = client_id, request_id = request_id, request = request },
- })
- client.requests[request_id] = nil
- end)
-
- if success and request_id then
- local request = { type = 'pending', bufnr = bufnr, method = method }
- client.requests[request_id] = request
- nvim_exec_autocmds('LspRequest', {
- buffer = bufnr,
- modeline = false,
- data = { client_id = client_id, request_id = request_id, request = request },
- })
- end
-
- return success, request_id
- end
-
- ---@private
- --- Sends a request to the server and synchronously waits for the response.
- ---
- --- This is a wrapper around {client.request}
- ---
- ---@param method (string) LSP method name.
- ---@param params (table) LSP request params.
- ---@param timeout_ms (integer|nil) Maximum time in milliseconds to wait for
- --- a result. Defaults to 1000
- ---@param bufnr (integer) Buffer handle (0 for current).
- ---@return {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dictionary, where
- --- `err` and `result` come from the |lsp-handler|.
- --- On timeout, cancel or error, returns `(nil, err)` where `err` is a
- --- string describing the failure reason. If the request was unsuccessful
- --- returns `nil`.
- ---@see |vim.lsp.buf_request_sync()|
- function client.request_sync(method, params, timeout_ms, bufnr)
- local request_result = nil
- local function _sync_handler(err, result)
- request_result = { err = err, result = result }
- end
-
- local success, request_id = client.request(method, params, _sync_handler, bufnr)
- if not success then
- return nil
- end
-
- local wait_result, reason = vim.wait(timeout_ms or 1000, function()
- return request_result ~= nil
- end, 10)
-
- if not wait_result then
- if request_id then
- client.cancel_request(request_id)
- end
- return nil, wait_result_reason[reason]
- end
- return request_result
- end
-
- ---@nodoc
- --- Sends a notification to an LSP server.
- ---
- ---@param method string LSP method name.
- ---@param params table|nil LSP request params.
- ---@return boolean status true if the notification was successful.
- ---If it is false, then it will always be false
- ---(the client has shutdown).
- function client.notify(method, params)
- if method ~= ms.textDocument_didChange then
- changetracking.flush(client)
- end
-
- local client_active = rpc.notify(method, params)
-
- if client_active then
- vim.schedule(function()
- nvim_exec_autocmds('LspNotify', {
- modeline = false,
- data = {
- client_id = client.id,
- method = method,
- params = params,
- },
- })
end)
end
-
- return client_active
- end
-
- ---@nodoc
- --- Cancels a request with a given request id.
- ---
- ---@param id (integer) id of request to cancel
- ---@return boolean status true if notification was successful. false otherwise
- ---@see |vim.lsp.client.notify()|
- function client.cancel_request(id)
- validate({ id = { id, 'n' } })
- local request = client.requests[id]
- if request and request.type == 'pending' then
- request.type = 'cancel'
- nvim_exec_autocmds('LspRequest', {
- buffer = request.bufnr,
- modeline = false,
- data = { client_id = client_id, request_id = id, request = request },
- })
- end
- return rpc.notify(ms.dollar_cancelRequest, { id = id })
end
- -- Track this so that we can escalate automatically if we've already tried a
- -- graceful shutdown
- local graceful_shutdown_failed = false
-
- ---@nodoc
- --- Stops a client, optionally with force.
- ---
- ---By default, it will just ask the - server to shutdown without force. If
- --- you request to stop a client which has previously been requested to
- --- shutdown, it will automatically escalate and force shutdown.
- ---
- ---@param force boolean|nil
- function client.stop(force)
- if rpc.is_closing() then
- return
- end
- if force or not client.initialized or graceful_shutdown_failed then
- rpc.terminate()
- return
- end
- -- Sending a signal after a process has exited is acceptable.
- rpc.request(ms.shutdown, nil, function(err, _)
- if err == nil then
- rpc.notify(ms.exit)
- else
- -- If there was an error in the shutdown request, then term to be safe.
- rpc.terminate()
- graceful_shutdown_failed = true
- end
- end)
- end
+ local name = client.name or 'unknown'
- ---@private
- --- Checks whether a client is stopped.
- ---
- ---@return boolean # true if client is stopped or in the process of being
- ---stopped; false otherwise
- function client.is_stopped()
- return rpc.is_closing()
- end
-
- ---@private
- --- Execute a lsp command, either via client command function (if available)
- --- or via workspace/executeCommand (if supported by the server)
- ---
- ---@param command lsp.Command
- ---@param context? {bufnr: integer}
- ---@param handler? lsp-handler only called if a server command
- function client._exec_cmd(command, context, handler)
- context = vim.deepcopy(context or {})
- context.bufnr = context.bufnr or api.nvim_get_current_buf()
- context.client_id = client.id
- local cmdname = command.command
- local fn = client.commands[cmdname] or lsp.commands[cmdname]
- if fn then
- fn(command, context)
- return
- end
+ -- Schedule the deletion of the client object so that it exists in the execution of LspDetach
+ -- autocommands
+ vim.schedule(function()
+ active_clients[client_id] = nil
+ uninitialized_clients[client_id] = nil
- local command_provider = client.server_capabilities.executeCommandProvider
- local commands = type(command_provider) == 'table' and command_provider.commands or {}
- if not vim.list_contains(commands, cmdname) then
- vim.notify_once(
- string.format(
- 'Language server `%s` does not support command `%s`. This command may require a client extension.',
- client.name,
- cmdname
- ),
- vim.log.levels.WARN
+ -- Client can be absent if executable starts, but initialize fails
+ -- init/attach won't have happened
+ if client then
+ changetracking.reset(client)
+ end
+ if code ~= 0 or (signal ~= 0 and signal ~= 15) then
+ local msg = string.format(
+ 'Client %s quit with exit code %s and signal %s. Check log for errors: %s',
+ name,
+ code,
+ signal,
+ lsp.get_log_path()
)
- return
+ vim.notify(msg, vim.log.levels.WARN)
end
- -- Not using command directly to exclude extra properties,
- -- see https://github.com/python-lsp/python-lsp-server/issues/146
- local params = {
- command = command.command,
- arguments = command.arguments,
- }
- client.request(ms.workspace_executeCommand, params, handler, context.bufnr)
- end
-
- ---@private
- --- Runs the on_attach function from the client's config if it was defined.
- ---@param bufnr integer Buffer number
- function client._on_attach(bufnr)
- text_document_did_open_handler(bufnr, client)
-
- lsp._set_defaults(client, bufnr)
+ end)
+end
- nvim_exec_autocmds('LspAttach', {
- buffer = bufnr,
- modeline = false,
- data = { client_id = client.id },
- })
+--- Starts and initializes a client with the given configuration.
+--- @param config vim.lsp.ClientConfig Configuration for the server.
+--- @return integer|nil client_id |vim.lsp.get_client_by_id()| Note: client may not be
+--- fully initialized. Use `on_init` to do any actions once
+--- the client has been initialized.
+function lsp.start_client(config)
+ local client = require('vim.lsp.client').create(config)
- if config.on_attach then
- local status, err = pcall(config.on_attach, client, bufnr)
- if not status then
- write_error(lsp.client_errors.ON_ATTACH_ERROR, err)
- end
- end
+ if not client then
+ return
+ end
- -- schedule the initialization of semantic tokens to give the above
- -- on_attach and LspAttach callbacks the ability to schedule wrap the
- -- opt-out (deleting the semanticTokensProvider from capabilities)
- vim.schedule(function()
- if vim.tbl_get(client.server_capabilities, 'semanticTokensProvider', 'full') then
- semantic_tokens.start(bufnr, client.id)
- end
- end)
+ --- @diagnostic disable-next-line: invisible
+ table.insert(client._on_init_cbs, on_client_init)
+ --- @diagnostic disable-next-line: invisible
+ table.insert(client._on_exit_cbs, on_client_exit)
- client.attached_buffers[bufnr] = true
- end
+ -- Store the uninitialized_clients for cleanup in case we exit before initialize finishes.
+ uninitialized_clients[client.id] = client
- initialize()
+ client:initialize()
- return client_id
+ return client.id
end
----@private
----@fn text_document_did_change_handler(_, bufnr, changedtick, firstline, lastline, new_lastline, old_byte_size, old_utf32_size, old_utf16_size)
--- Notify all attached clients that a buffer has changed.
-local text_document_did_change_handler
-do
- text_document_did_change_handler = function(
- _,
- bufnr,
- changedtick,
- firstline,
- lastline,
- new_lastline
- )
- -- Detach (nvim_buf_attach) via returning True to on_lines if no clients are attached
- if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then
- return true
- end
- util.buf_versions[bufnr] = changedtick
- changetracking.send_changes(bufnr, firstline, lastline, new_lastline)
+---@param _ integer
+---@param bufnr integer
+---@param changedtick integer
+---@param firstline integer
+---@param lastline integer
+---@param new_lastline integer
+---@return true?
+local function text_document_did_change_handler(
+ _,
+ bufnr,
+ changedtick,
+ firstline,
+ lastline,
+ new_lastline
+)
+ -- Detach (nvim_buf_attach) via returning True to on_lines if no clients are attached
+ if tbl_isempty(all_buffer_active_clients[bufnr] or {}) then
+ return true
end
+ util.buf_versions[bufnr] = changedtick
+ changetracking.send_changes(bufnr, firstline, lastline, new_lastline)
end
---Buffer lifecycle handler for textDocument/didSave
+--- @param bufnr integer
local function text_document_did_save_handler(bufnr)
bufnr = resolve_bufnr(bufnr)
local uri = vim.uri_from_bufnr(bufnr)
- local text = once(buf_get_full_text)
+ local text = once(lsp._buf_get_full_text)
for _, client in ipairs(lsp.get_clients({ bufnr = bufnr })) do
local name = api.nvim_buf_get_name(bufnr)
local old_name = changetracking._get_and_set_name(client, bufnr, name)
@@ -1789,15 +521,15 @@ local function text_document_did_save_handler(bufnr)
textDocument = {
version = 0,
uri = uri,
- languageId = client.config.get_language_id(bufnr, vim.bo[bufnr].filetype),
- text = buf_get_full_text(bufnr),
+ languageId = client.get_language_id(bufnr, vim.bo[bufnr].filetype),
+ text = lsp._buf_get_full_text(bufnr),
},
})
util.buf_versions[bufnr] = 0
end
local save_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'save')
if save_capability then
- local included_text
+ local included_text --- @type string?
if type(save_capability) == 'table' and save_capability.includeText then
included_text = text(bufnr)
end
@@ -1826,8 +558,7 @@ function lsp.buf_attach_client(bufnr, client_id)
})
bufnr = resolve_bufnr(bufnr)
if not api.nvim_buf_is_loaded(bufnr) then
- local _ = log.warn()
- and log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr))
+ log.warn(string.format('buf_attach_client called on unloaded buffer (id: %d): ', bufnr))
return false
end
local buffer_client_ids = all_buffer_active_clients[bufnr]
@@ -1884,7 +615,7 @@ function lsp.buf_attach_client(bufnr, client_id)
if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then
client.notify(ms.textDocument_didClose, params)
end
- text_document_did_open_handler(bufnr, client)
+ client:_text_document_did_open_handler(bufnr)
end
end,
on_detach = function()
@@ -1916,7 +647,7 @@ function lsp.buf_attach_client(bufnr, client_id)
-- Send didOpen for the client if it is initialized. If it isn't initialized
-- then it will send didOpen on initialize.
if client then
- client._on_attach(bufnr)
+ client:_on_attach(bufnr)
end
return true
end
@@ -1946,7 +677,7 @@ function lsp.buf_detach_client(bufnr, client_id)
return
end
- nvim_exec_autocmds('LspDetach', {
+ api.nvim_exec_autocmds('LspDetach', {
buffer = bufnr,
modeline = false,
data = { client_id = client_id },
@@ -1985,7 +716,7 @@ end
---
---@param client_id integer client id
---
----@return (nil|lsp.Client) client rpc object
+---@return (nil|vim.lsp.Client) client rpc object
function lsp.get_client_by_id(client_id)
return active_clients[client_id] or uninitialized_clients[client_id]
end
@@ -2001,7 +732,7 @@ end
--- Stops a client(s).
---
---- You can also use the `stop()` function on a |vim.lsp.client| object.
+--- You can also use the `stop()` function on a |vim.lsp.Client| object.
--- To stop all clients:
---
--- ```lua
@@ -2011,7 +742,7 @@ end
--- By default asks the server to shutdown, unless stop was requested
--- already for this client, then force-shutdown is attempted.
---
----@param client_id integer|table id or |vim.lsp.client| object, or list thereof
+---@param client_id integer|vim.lsp.Client id or |vim.lsp.Client| object, or list thereof
---@param force boolean|nil shutdown forcefully
function lsp.stop_client(client_id, force)
local ids = type(client_id) == 'table' and client_id or { client_id }
@@ -2026,28 +757,32 @@ function lsp.stop_client(client_id, force)
end
end
----@class vim.lsp.get_clients.filter
----@field id integer|nil Match clients by id
----@field bufnr integer|nil match clients attached to the given buffer
----@field name string|nil match clients by name
----@field method string|nil match client by supported method name
+--- Key-value pairs used to filter the returned clients.
+--- @class vim.lsp.get_clients.Filter
+--- @inlinedoc
+---
+--- Only return clients with the given id
+--- @field id? integer
+---
+--- Only return clients attached to this buffer
+--- @field bufnr? integer
+---
+--- Only return clients with the given name
+--- @field name? string
+---
+--- Only return clients supporting the given method
+--- @field method? string
--- Get active clients.
---
----@param filter vim.lsp.get_clients.filter|nil (table|nil) A table with
---- key-value pairs used to filter the returned clients.
---- The available keys are:
---- - id (number): Only return clients with the given id
---- - bufnr (number): Only return clients attached to this buffer
---- - name (string): Only return clients with the given name
---- - method (string): Only return clients supporting the given method
----@return lsp.Client[]: List of |vim.lsp.client| objects
+---@param filter? vim.lsp.get_clients.Filter
+---@return vim.lsp.Client[]: List of |vim.lsp.Client| objects
function lsp.get_clients(filter)
validate({ filter = { filter, 't', true } })
filter = filter or {}
- local clients = {} --- @type lsp.Client[]
+ local clients = {} --- @type vim.lsp.Client[]
local t = filter.bufnr and (all_buffer_active_clients[resolve_bufnr(filter.bufnr)] or {})
or active_clients
@@ -2068,7 +803,7 @@ end
---@private
---@deprecated
function lsp.get_active_clients(filter)
- -- TODO: add vim.deprecate call after 0.10 is out for removal in 0.12
+ vim.deprecate('vim.lsp.get_active_clients()', 'vim.lsp.get_clients()', '0.12')
return lsp.get_clients(filter)
end
@@ -2087,12 +822,12 @@ api.nvim_create_autocmd('VimLeavePre', {
client.stop()
end
- local timeouts = {}
+ local timeouts = {} --- @type table<integer,integer>
local max_timeout = 0
local send_kill = false
for client_id, client in pairs(active_clients) do
- local timeout = if_nil(client.config.flags.exit_timeout, false)
+ local timeout = if_nil(client.flags.exit_timeout, false)
if timeout then
send_kill = true
timeouts[client_id] = timeout
@@ -2134,7 +869,7 @@ api.nvim_create_autocmd('VimLeavePre', {
---@param bufnr (integer) Buffer handle, or 0 for current.
---@param method (string) LSP method name
---@param params table|nil Parameters to send to the server
----@param handler? lsp-handler See |lsp-handler|
+---@param handler? lsp.Handler See |lsp-handler|
--- If nil, follows resolution strategy defined in |lsp-handler-configuration|
---
---@return table<integer, integer> client_request_ids Map of client-id:request-id pairs
@@ -2152,7 +887,7 @@ function lsp.buf_request(bufnr, method, params, handler)
bufnr = resolve_bufnr(bufnr)
local method_supported = false
local clients = lsp.get_clients({ bufnr = bufnr })
- local client_request_ids = {}
+ local client_request_ids = {} --- @type table<integer,integer>
for _, client in ipairs(clients) do
if client.supports_method(method, { bufnr = bufnr }) then
method_supported = true
@@ -2169,7 +904,7 @@ function lsp.buf_request(bufnr, method, params, handler)
-- if has client but no clients support the given method, notify the user
if next(clients) and not method_supported then
vim.notify(lsp._unsupported_method(method), vim.log.levels.ERROR)
- nvim_command('redraw')
+ vim.cmd.redraw()
return {}, function() end
end
@@ -2194,7 +929,7 @@ end
--- a `client_id:result` map.
---@return function cancel Function that cancels all requests.
function lsp.buf_request_all(bufnr, method, params, handler)
- local results = {}
+ local results = {} --- @type table<integer,{error:string, result:any}>
local result_count = 0
local expected_result_count = 0
@@ -2225,16 +960,15 @@ end
---
--- Calls |vim.lsp.buf_request_all()| but blocks Nvim while awaiting the result.
--- Parameters are the same as |vim.lsp.buf_request_all()| but the result is
---- different. Waits a maximum of {timeout_ms} (default 1000) ms.
----
----@param bufnr (integer) Buffer handle, or 0 for current.
----@param method (string) LSP method name
----@param params (table|nil) Parameters to send to the server
----@param timeout_ms (integer|nil) Maximum time in milliseconds to wait for a
---- result. Defaults to 1000
----
----@return table<integer, {err: lsp.ResponseError, result: any}>|nil (table) result Map of client_id:request_result.
----@return string|nil err On timeout, cancel, or error, `err` is a string describing the failure reason, and `result` is nil.
+--- different. Waits a maximum of {timeout_ms}.
+---
+---@param bufnr integer Buffer handle, or 0 for current.
+---@param method string LSP method name
+---@param params table? Parameters to send to the server
+---@param timeout_ms integer? Maximum time in milliseconds to wait for a result.
+--- (default: `1000`)
+---@return table<integer, {err: lsp.ResponseError, result: any}>? result Map of client_id:request_result.
+---@return string? err On timeout, cancel, or error, `err` is a string describing the failure reason, and `result` is nil.
function lsp.buf_request_sync(bufnr, method, params, timeout_ms)
local request_results
@@ -2287,21 +1021,24 @@ end
--- - findstart=0: column where the completion starts, or -2 or -3
--- - findstart=1: list of matches (actually just calls |complete()|)
function lsp.omnifunc(findstart, base)
- if log.debug() then
- log.debug('omnifunc.findstart', { findstart = findstart, base = base })
- end
- return require('vim.lsp._completion').omnifunc(findstart, base)
+ log.debug('omnifunc.findstart', { findstart = findstart, base = base })
+ return vim.lsp._completion.omnifunc(findstart, base)
end
+--- @class vim.lsp.formatexpr.Opts
+--- @inlinedoc
+---
+--- The timeout period for the formatting request.
+--- (default: 500ms).
+--- @field timeout_ms integer
+
--- Provides an interface between the built-in client and a `formatexpr` function.
---
--- 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.bo[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:
---- * timeout_ms (default 500ms). The timeout period for the formatting request.
+---@param opts? vim.lsp.formatexpr.Opts
function lsp.formatexpr(opts)
opts = opts or {}
local timeout_ms = opts.timeout_ms or 500
@@ -2324,6 +1061,7 @@ function lsp.formatexpr(opts)
local params = util.make_formatting_params()
local end_line = vim.fn.getline(end_lnum) --[[@as string]]
local end_col = util._str_utfindex_enc(end_line, nil, client.offset_encoding)
+ --- @cast params +lsp.DocumentRangeFormattingParams
params.range = {
start = {
line = start_lnum - 1,
@@ -2337,7 +1075,7 @@ function lsp.formatexpr(opts)
local response =
client.request_sync(ms.textDocument_rangeFormatting, params, timeout_ms, bufnr)
if response and response.result then
- lsp.util.apply_text_edits(response.result, 0, client.offset_encoding)
+ lsp.util.apply_text_edits(response.result, bufnr, client.offset_encoding)
return 0
end
end
@@ -2359,7 +1097,7 @@ end
---
---@return table[] tags A list of matching tags
function lsp.tagfunc(pattern, flags)
- return require('vim.lsp.tagfunc')(pattern, flags)
+ return vim.lsp._tagfunc(pattern, flags)
end
---Checks whether a client is stopped.
@@ -2372,13 +1110,14 @@ function lsp.client_is_stopped(client_id)
end
--- Gets a map of client_id:client pairs for the given buffer, where each value
---- is a |vim.lsp.client| object.
+--- is a |vim.lsp.Client| object.
---
---@param bufnr (integer|nil): Buffer handle, or 0 for current
---@return table result is table of (client_id, client) pairs
---@deprecated Use |vim.lsp.get_clients()| instead.
function lsp.buf_get_clients(bufnr)
- local result = {}
+ vim.deprecate('vim.lsp.buf_get_clients()', 'vim.lsp.get_clients()', '0.12')
+ local result = {} --- @type table<integer,vim.lsp.Client>
for _, client in ipairs(lsp.get_clients({ bufnr = resolve_bufnr(bufnr) })) do
result[client.id] = client
end
@@ -2428,11 +1167,16 @@ end
--- buffer number as arguments.
---@deprecated use lsp.get_clients({ bufnr = bufnr }) with regular loop
function lsp.for_each_buffer_client(bufnr, fn)
+ vim.deprecate(
+ 'vim.lsp.for_each_buffer_client()',
+ 'lsp.get_clients({ bufnr = bufnr }) with regular loop',
+ '0.12'
+ )
return for_each_buffer_client(bufnr, fn)
end
--- Function to manage overriding defaults for LSP handlers.
----@param handler (function) See |lsp-handler|
+---@param handler (lsp.Handler) See |lsp-handler|
---@param override_config (table) Table containing the keys to override behavior of the {handler}
function lsp.with(handler, override_config)
return function(err, result, ctx, config)
@@ -2497,6 +1241,7 @@ end
--- arguments?: any[]
---
--- The second argument is the `ctx` of |lsp-handler|
+--- @type table<string,function>
lsp.commands = setmetatable({}, {
__newindex = function(tbl, key, value)
assert(type(key) == 'string', 'The key for commands in `vim.lsp.commands` must be a string')
diff --git a/runtime/lua/vim/lsp/_changetracking.lua b/runtime/lua/vim/lsp/_changetracking.lua
new file mode 100644
index 0000000000..b2be53269f
--- /dev/null
+++ b/runtime/lua/vim/lsp/_changetracking.lua
@@ -0,0 +1,373 @@
+local protocol = require('vim.lsp.protocol')
+local sync = require('vim.lsp.sync')
+local util = require('vim.lsp.util')
+
+local api = vim.api
+local uv = vim.uv
+
+local M = {}
+
+--- LSP has 3 different sync modes:
+--- - None (Servers will read the files themselves when needed)
+--- - Full (Client sends the full buffer content on updates)
+--- - Incremental (Client sends only the changed parts)
+---
+--- Changes are tracked per buffer.
+--- A buffer can have multiple clients attached and each client needs to send the changes
+--- To minimize the amount of changesets to compute, computation is grouped:
+---
+--- None: One group for all clients
+--- Full: One group for all clients
+--- Incremental: One group per `offset_encoding`
+---
+--- Sending changes can be debounced per buffer. To simplify the implementation the
+--- smallest debounce interval is used and we don't group clients by different intervals.
+---
+--- @class vim.lsp.CTGroup
+--- @field sync_kind integer TextDocumentSyncKind, considers config.flags.allow_incremental_sync
+--- @field offset_encoding "utf-8"|"utf-16"|"utf-32"
+---
+--- @class vim.lsp.CTBufferState
+--- @field name string name of the buffer
+--- @field lines string[] snapshot of buffer lines from last didChange
+--- @field lines_tmp string[]
+--- @field pending_changes table[] List of debounced changes in incremental sync mode
+--- @field timer uv.uv_timer_t? uv_timer
+--- @field last_flush nil|number uv.hrtime of the last flush/didChange-notification
+--- @field needs_flush boolean true if buffer updates haven't been sent to clients/servers yet
+--- @field refs integer how many clients are using this group
+---
+--- @class vim.lsp.CTGroupState
+--- @field buffers table<integer,vim.lsp.CTBufferState>
+--- @field debounce integer debounce duration in ms
+--- @field clients table<integer, table> clients using this state. {client_id, client}
+
+---@param group vim.lsp.CTGroup
+---@return string
+local function group_key(group)
+ if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then
+ return tostring(group.sync_kind) .. '\0' .. group.offset_encoding
+ end
+ return tostring(group.sync_kind)
+end
+
+---@type table<vim.lsp.CTGroup,vim.lsp.CTGroupState>
+local state_by_group = setmetatable({}, {
+ __index = function(tbl, k)
+ return rawget(tbl, group_key(k))
+ end,
+ __newindex = function(tbl, k, v)
+ rawset(tbl, group_key(k), v)
+ end,
+})
+
+---@param client vim.lsp.Client
+---@return vim.lsp.CTGroup
+local function get_group(client)
+ local allow_inc_sync = vim.F.if_nil(client.flags.allow_incremental_sync, true) --- @type boolean
+ local change_capability = vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'change')
+ local sync_kind = change_capability or protocol.TextDocumentSyncKind.None
+ if not allow_inc_sync and change_capability == protocol.TextDocumentSyncKind.Incremental then
+ sync_kind = protocol.TextDocumentSyncKind.Full --[[@as integer]]
+ end
+ return {
+ sync_kind = sync_kind,
+ offset_encoding = client.offset_encoding,
+ }
+end
+
+---@param state vim.lsp.CTBufferState
+---@param encoding string
+---@param bufnr integer
+---@param firstline integer
+---@param lastline integer
+---@param new_lastline integer
+---@return lsp.TextDocumentContentChangeEvent
+local function incremental_changes(state, encoding, bufnr, firstline, lastline, new_lastline)
+ local prev_lines = state.lines
+ local curr_lines = state.lines_tmp
+
+ local changed_lines = api.nvim_buf_get_lines(bufnr, firstline, new_lastline, true)
+ for i = 1, firstline do
+ curr_lines[i] = prev_lines[i]
+ end
+ for i = firstline + 1, new_lastline do
+ curr_lines[i] = changed_lines[i - firstline]
+ end
+ for i = lastline + 1, #prev_lines do
+ curr_lines[i - lastline + new_lastline] = prev_lines[i]
+ end
+ if vim.tbl_isempty(curr_lines) then
+ -- Can happen when deleting the entire contents of a buffer, see https://github.com/neovim/neovim/issues/16259.
+ curr_lines[1] = ''
+ end
+
+ local line_ending = vim.lsp._buf_get_line_ending(bufnr)
+ local incremental_change = sync.compute_diff(
+ state.lines,
+ curr_lines,
+ firstline,
+ lastline,
+ new_lastline,
+ encoding,
+ line_ending
+ )
+
+ -- Double-buffering of lines tables is used to reduce the load on the garbage collector.
+ -- At this point the prev_lines table is useless, but its internal storage has already been allocated,
+ -- so let's keep it around for the next didChange event, in which it will become the next
+ -- curr_lines table. Note that setting elements to nil doesn't actually deallocate slots in the
+ -- internal storage - it merely marks them as free, for the GC to deallocate them.
+ for i in ipairs(prev_lines) do
+ prev_lines[i] = nil
+ end
+ state.lines = curr_lines
+ state.lines_tmp = prev_lines
+
+ return incremental_change
+end
+
+---@param client vim.lsp.Client
+---@param bufnr integer
+function M.init(client, bufnr)
+ assert(client.offset_encoding, 'lsp client must have an offset_encoding')
+ local group = get_group(client)
+ local state = state_by_group[group]
+ if state then
+ state.debounce = math.min(state.debounce, client.flags.debounce_text_changes or 150)
+ state.clients[client.id] = client
+ else
+ state = {
+ buffers = {},
+ debounce = client.flags.debounce_text_changes or 150,
+ clients = {
+ [client.id] = client,
+ },
+ }
+ state_by_group[group] = state
+ end
+ local buf_state = state.buffers[bufnr]
+ if buf_state then
+ buf_state.refs = buf_state.refs + 1
+ else
+ buf_state = {
+ name = api.nvim_buf_get_name(bufnr),
+ lines = {},
+ lines_tmp = {},
+ pending_changes = {},
+ needs_flush = false,
+ refs = 1,
+ }
+ state.buffers[bufnr] = buf_state
+ if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then
+ buf_state.lines = api.nvim_buf_get_lines(bufnr, 0, -1, true)
+ end
+ end
+end
+
+--- @param client vim.lsp.Client
+--- @param bufnr integer
+--- @param name string
+--- @return string
+function M._get_and_set_name(client, bufnr, name)
+ local state = state_by_group[get_group(client)] or {}
+ local buf_state = (state.buffers or {})[bufnr]
+ local old_name = buf_state.name
+ buf_state.name = name
+ return old_name
+end
+
+---@param buf_state vim.lsp.CTBufferState
+local function reset_timer(buf_state)
+ local timer = buf_state.timer
+ if timer then
+ buf_state.timer = nil
+ if not timer:is_closing() then
+ timer:stop()
+ timer:close()
+ end
+ end
+end
+
+--- @param client vim.lsp.Client
+--- @param bufnr integer
+function M.reset_buf(client, bufnr)
+ M.flush(client, bufnr)
+ local state = state_by_group[get_group(client)]
+ if not state then
+ return
+ end
+ assert(state.buffers, 'CTGroupState must have buffers')
+ local buf_state = state.buffers[bufnr]
+ buf_state.refs = buf_state.refs - 1
+ assert(buf_state.refs >= 0, 'refcount on buffer state must not get negative')
+ if buf_state.refs == 0 then
+ state.buffers[bufnr] = nil
+ reset_timer(buf_state)
+ end
+end
+
+--- @param client vim.lsp.Client
+function M.reset(client)
+ local state = state_by_group[get_group(client)]
+ if not state then
+ return
+ end
+ state.clients[client.id] = nil
+ if vim.tbl_count(state.clients) == 0 then
+ for _, buf_state in pairs(state.buffers) do
+ reset_timer(buf_state)
+ end
+ state.buffers = {}
+ end
+end
+
+-- Adjust debounce time by taking time of last didChange notification into
+-- consideration. If the last didChange happened more than `debounce` time ago,
+-- debounce can be skipped and otherwise maybe reduced.
+--
+-- This turns the debounce into a kind of client rate limiting
+--
+---@param debounce integer
+---@param buf_state vim.lsp.CTBufferState
+---@return number
+local function next_debounce(debounce, buf_state)
+ if debounce == 0 then
+ return 0
+ end
+ local ns_to_ms = 0.000001
+ if not buf_state.last_flush then
+ return debounce
+ end
+ local now = uv.hrtime()
+ local ms_since_last_flush = (now - buf_state.last_flush) * ns_to_ms
+ return math.max(debounce - ms_since_last_flush, 0)
+end
+
+---@param bufnr integer
+---@param sync_kind integer protocol.TextDocumentSyncKind
+---@param state vim.lsp.CTGroupState
+---@param buf_state vim.lsp.CTBufferState
+local function send_changes(bufnr, sync_kind, state, buf_state)
+ if not buf_state.needs_flush then
+ return
+ end
+ buf_state.last_flush = uv.hrtime()
+ buf_state.needs_flush = false
+
+ if not api.nvim_buf_is_valid(bufnr) then
+ buf_state.pending_changes = {}
+ return
+ end
+
+ local changes --- @type lsp.TextDocumentContentChangeEvent[]
+ if sync_kind == protocol.TextDocumentSyncKind.None then
+ return
+ elseif sync_kind == protocol.TextDocumentSyncKind.Incremental then
+ changes = buf_state.pending_changes
+ buf_state.pending_changes = {}
+ else
+ changes = {
+ { text = vim.lsp._buf_get_full_text(bufnr) },
+ }
+ end
+ local uri = vim.uri_from_bufnr(bufnr)
+ for _, client in pairs(state.clients) do
+ if not client.is_stopped() and vim.lsp.buf_is_attached(bufnr, client.id) then
+ client.notify(protocol.Methods.textDocument_didChange, {
+ textDocument = {
+ uri = uri,
+ version = util.buf_versions[bufnr],
+ },
+ contentChanges = changes,
+ })
+ end
+ end
+end
+
+--- @param bufnr integer
+--- @param firstline integer
+--- @param lastline integer
+--- @param new_lastline integer
+--- @param group vim.lsp.CTGroup
+local function send_changes_for_group(bufnr, firstline, lastline, new_lastline, group)
+ local state = state_by_group[group]
+ if not state then
+ error(
+ string.format(
+ 'changetracking.init must have been called for all LSP clients. group=%s states=%s',
+ vim.inspect(group),
+ vim.inspect(vim.tbl_keys(state_by_group))
+ )
+ )
+ end
+ local buf_state = state.buffers[bufnr]
+ buf_state.needs_flush = true
+ reset_timer(buf_state)
+ local debounce = next_debounce(state.debounce, buf_state)
+ if group.sync_kind == protocol.TextDocumentSyncKind.Incremental then
+ -- This must be done immediately and cannot be delayed
+ -- The contents would further change and startline/endline may no longer fit
+ local changes = incremental_changes(
+ buf_state,
+ group.offset_encoding,
+ bufnr,
+ firstline,
+ lastline,
+ new_lastline
+ )
+ table.insert(buf_state.pending_changes, changes)
+ end
+ if debounce == 0 then
+ send_changes(bufnr, group.sync_kind, state, buf_state)
+ else
+ local timer = assert(uv.new_timer(), 'Must be able to create timer')
+ buf_state.timer = timer
+ timer:start(
+ debounce,
+ 0,
+ vim.schedule_wrap(function()
+ reset_timer(buf_state)
+ send_changes(bufnr, group.sync_kind, state, buf_state)
+ end)
+ )
+ end
+end
+
+--- @param bufnr integer
+--- @param firstline integer
+--- @param lastline integer
+--- @param new_lastline integer
+function M.send_changes(bufnr, firstline, lastline, new_lastline)
+ local groups = {} ---@type table<string,vim.lsp.CTGroup>
+ for _, client in pairs(vim.lsp.get_clients({ bufnr = bufnr })) do
+ local group = get_group(client)
+ groups[group_key(group)] = group
+ end
+ for _, group in pairs(groups) do
+ send_changes_for_group(bufnr, firstline, lastline, new_lastline, group)
+ end
+end
+
+--- Flushes any outstanding change notification.
+---@param client vim.lsp.Client
+---@param bufnr? integer
+function M.flush(client, bufnr)
+ local group = get_group(client)
+ local state = state_by_group[group]
+ if not state then
+ return
+ end
+ if bufnr then
+ local buf_state = state.buffers[bufnr] or {}
+ reset_timer(buf_state)
+ send_changes(bufnr, group.sync_kind, state, buf_state)
+ else
+ for buf, buf_state in pairs(state.buffers) do
+ reset_timer(buf_state)
+ send_changes(buf, group.sync_kind, state, buf_state)
+ end
+ end
+end
+
+return M
diff --git a/runtime/lua/vim/lsp/_completion.lua b/runtime/lua/vim/lsp/_completion.lua
index 7a607d6c13..a169f96565 100644
--- a/runtime/lua/vim/lsp/_completion.lua
+++ b/runtime/lua/vim/lsp/_completion.lua
@@ -4,11 +4,21 @@ local lsp = vim.lsp
local protocol = lsp.protocol
local ms = protocol.Methods
+--- @alias vim.lsp.CompletionResult lsp.CompletionList | lsp.CompletionItem[]
+
+-- TODO(mariasolos): Remove this declaration once we figure out a better way to handle
+-- literal/anonymous types (see https://github.com/neovim/neovim/pull/27542/files#r1495259331).
+--- @class lsp.ItemDefaults
+--- @field editRange lsp.Range | { insert: lsp.Range, replace: lsp.Range } | nil
+--- @field insertTextFormat lsp.InsertTextFormat?
+--- @field insertTextMode lsp.InsertTextMode?
+--- @field data any
+
---@param input string unparsed snippet
---@return string parsed snippet
local function parse_snippet(input)
local ok, parsed = pcall(function()
- return require('vim.lsp._snippet_grammar').parse(input)
+ return vim.lsp._snippet_grammar.parse(input)
end)
return ok and tostring(parsed) or input
end
@@ -37,19 +47,49 @@ local function get_completion_word(item)
return item.label
end
----@param result lsp.CompletionList|lsp.CompletionItem[]
+--- Applies the given defaults to the completion item, modifying it in place.
+---
+--- @param item lsp.CompletionItem
+--- @param defaults lsp.ItemDefaults?
+local function apply_defaults(item, defaults)
+ if not defaults then
+ return
+ end
+
+ item.insertTextFormat = item.insertTextFormat or defaults.insertTextFormat
+ item.insertTextMode = item.insertTextMode or defaults.insertTextMode
+ item.data = item.data or defaults.data
+ if defaults.editRange then
+ local textEdit = item.textEdit or {}
+ item.textEdit = textEdit
+ textEdit.newText = textEdit.newText or item.textEditText or item.insertText
+ if defaults.editRange.start then
+ textEdit.range = textEdit.range or defaults.editRange
+ elseif defaults.editRange.insert then
+ textEdit.insert = defaults.editRange.insert
+ textEdit.replace = defaults.editRange.replace
+ end
+ end
+end
+
+---@param result vim.lsp.CompletionResult
---@return lsp.CompletionItem[]
local function get_items(result)
if result.items then
+ for _, item in ipairs(result.items) do
+ ---@diagnostic disable-next-line: param-type-mismatch
+ apply_defaults(item, result.itemDefaults)
+ end
return result.items
+ else
+ return result
end
- return result
end
--- Turns the result of a `textDocument/completion` request into vim-compatible
--- |complete-items|.
---
----@param result lsp.CompletionList|lsp.CompletionItem[] Result of `textDocument/completion`
+---@param result vim.lsp.CompletionResult Result of `textDocument/completion`
---@param prefix string prefix to filter the completion items
---@return table[]
---@see complete-items
@@ -130,7 +170,7 @@ end
---@param lnum integer 0-indexed line number
---@param client_start_boundary integer 0-indexed word boundary
---@param server_start_boundary? integer 0-indexed word boundary, based on textEdit.range.start.character
----@param result lsp.CompletionList|lsp.CompletionItem[]
+---@param result vim.lsp.CompletionResult
---@param encoding string
---@return table[] matches
---@return integer? server_start_boundary
@@ -206,7 +246,7 @@ function M.omnifunc(findstart, base)
local params = util.make_position_params(win, client.offset_encoding)
client.request(ms.textDocument_completion, params, function(err, result)
if err then
- require('vim.lsp.log').warn(err.message)
+ vim.lsp.log.warn(err.message)
end
if result and vim.fn.mode() == 'i' then
local matches
diff --git a/runtime/lua/vim/lsp/_dynamic.lua b/runtime/lua/vim/lsp/_dynamic.lua
index 04040e8e28..819b03a63a 100644
--- a/runtime/lua/vim/lsp/_dynamic.lua
+++ b/runtime/lua/vim/lsp/_dynamic.lua
@@ -1,4 +1,4 @@
-local wf = require('vim.lsp._watchfiles')
+local glob = vim.glob
--- @class lsp.DynamicCapabilities
--- @field capabilities table<string, lsp.Registration[]>
@@ -6,6 +6,7 @@ local wf = require('vim.lsp._watchfiles')
local M = {}
--- @param client_id number
+--- @return lsp.DynamicCapabilities
function M.new(client_id)
return setmetatable({
capabilities = {},
@@ -18,12 +19,12 @@ function M:supports_registration(method)
if not client then
return false
end
- local capability = vim.tbl_get(client.config.capabilities, unpack(vim.split(method, '/')))
+ local capability = vim.tbl_get(client.capabilities, unpack(vim.split(method, '/')))
return type(capability) == 'table' and capability.dynamicRegistration
end
--- @param registrations lsp.Registration[]
---- @private
+--- @package
function M:register(registrations)
-- remove duplicates
self:unregister(registrations)
@@ -37,7 +38,7 @@ function M:register(registrations)
end
--- @param unregisterations lsp.Unregistration[]
---- @private
+--- @package
function M:unregister(unregisterations)
for _, unreg in ipairs(unregisterations) do
local method = unreg.method
@@ -55,9 +56,9 @@ function M:unregister(unregisterations)
end
--- @param method string
---- @param opts? {bufnr?: number}
+--- @param opts? {bufnr: integer?}
--- @return lsp.Registration? (table|nil) the registration if found
---- @private
+--- @package
function M:get(method, opts)
opts = opts or {}
opts.bufnr = opts.bufnr or vim.api.nvim_get_current_buf()
@@ -69,15 +70,15 @@ function M:get(method, opts)
if not documentSelector then
return reg
end
- if M.match(opts.bufnr, documentSelector) then
+ if self:match(opts.bufnr, documentSelector) then
return reg
end
end
end
--- @param method string
---- @param opts? {bufnr?: number}
---- @private
+--- @param opts? {bufnr: integer?}
+--- @package
function M:supports(method, opts)
return self:get(method, opts) ~= nil
end
@@ -85,19 +86,23 @@ end
--- @param bufnr number
--- @param documentSelector lsp.DocumentSelector
--- @private
-function M.match(bufnr, documentSelector)
- local ft = vim.bo[bufnr].filetype
+function M:match(bufnr, documentSelector)
+ local client = vim.lsp.get_client_by_id(self.client_id)
+ if not client then
+ return false
+ end
+ local language = client.get_language_id(bufnr, vim.bo[bufnr].filetype)
local uri = vim.uri_from_bufnr(bufnr)
local fname = vim.uri_to_fname(uri)
for _, filter in ipairs(documentSelector) do
local matches = true
- if filter.language and ft ~= filter.language then
+ if filter.language and language ~= filter.language then
matches = false
end
if matches and filter.scheme and not vim.startswith(uri, filter.scheme .. ':') then
matches = false
end
- if matches and filter.pattern and not wf._match(filter.pattern, fname) then
+ if matches and filter.pattern and not glob.to_lpeg(filter.pattern):match(fname) then
matches = false
end
if matches then
diff --git a/runtime/lua/vim/lsp/_meta.lua b/runtime/lua/vim/lsp/_meta.lua
index acf799264e..be3222828d 100644
--- a/runtime/lua/vim/lsp/_meta.lua
+++ b/runtime/lua/vim/lsp/_meta.lua
@@ -1,22 +1,16 @@
---@meta
error('Cannot require a meta file')
----@alias lsp-handler fun(err: lsp.ResponseError|nil, result: any, context: lsp.HandlerContext, config: table|nil): any?
+---@alias lsp.Handler fun(err: lsp.ResponseError?, result: any, context: lsp.HandlerContext, config?: table): ...any
---@class lsp.HandlerContext
---@field method string
---@field client_id integer
---@field bufnr? integer
---@field params? any
+---@field version? integer
---@class lsp.ResponseError
---@field code integer
---@field message string
---@field data string|number|boolean|table[]|table|nil
-
---- @class lsp.DocumentFilter
---- @field language? string
---- @field scheme? string
---- @field pattern? string
-
---- @alias lsp.RegisterOptions any | lsp.StaticRegistrationOptions | lsp.TextDocumentRegistrationOptions
diff --git a/runtime/lua/vim/lsp/_meta/protocol.lua b/runtime/lua/vim/lsp/_meta/protocol.lua
index 72b0f00f65..a5da5ac6b7 100644
--- a/runtime/lua/vim/lsp/_meta/protocol.lua
+++ b/runtime/lua/vim/lsp/_meta/protocol.lua
@@ -1,7 +1,11 @@
--[[
-This file is autogenerated from scripts/gen_lsp.lua
+THIS FILE IS GENERATED by scripts/gen_lsp.lua
+DO NOT EDIT MANUALLY
+
+Based on LSP protocol 3.18
+
Regenerate:
-nvim -l scripts/gen_lsp.lua gen --version 3.18 --runtime/lua/vim/lsp/_meta/protocol.lua
+nvim -l scripts/gen_lsp.lua gen --version 3.18
--]]
---@meta
@@ -9,111 +13,132 @@ error('Cannot require a meta file')
---@alias lsp.null nil
---@alias uinteger integer
----@alias lsp.decimal number
+---@alias decimal number
---@alias lsp.DocumentUri string
---@alias lsp.URI string
----@alias lsp.LSPObject table<string, lsp.LSPAny>
----@alias lsp.LSPArray lsp.LSPAny[]
----@alias lsp.LSPAny lsp.LSPObject|lsp.LSPArray|string|number|boolean|nil
---@class lsp.ImplementationParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams
---Represents a location inside a resource, such as a line
---inside a text file.
---@class lsp.Location
+---
---@field uri lsp.DocumentUri
+---
---@field range lsp.Range
----@class lsp.ImplementationRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
+---@class lsp.ImplementationRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.ImplementationOptions, lsp.StaticRegistrationOptions
---@class lsp.TypeDefinitionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams
----@class lsp.TypeDefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
+---@class lsp.TypeDefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.TypeDefinitionOptions, lsp.StaticRegistrationOptions
---A workspace folder inside a client.
---@class lsp.WorkspaceFolder
+---
---The associated URI for this workspace folder.
---@field uri lsp.URI
+---
---The name of the workspace folder. Used to refer to this
---workspace folder in the user interface.
---@field name string
---The parameters of a `workspace/didChangeWorkspaceFolders` notification.
---@class lsp.DidChangeWorkspaceFoldersParams
+---
---The actual workspace folder change event.
---@field event lsp.WorkspaceFoldersChangeEvent
---The parameters of a configuration request.
---@class lsp.ConfigurationParams
+---
---@field items lsp.ConfigurationItem[]
---Parameters for a {@link DocumentColorRequest}.
----@class lsp.DocumentColorParams
+---@class lsp.DocumentColorParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
---Represents a color range from a document.
---@class lsp.ColorInformation
+---
---The range in the document where this color appears.
---@field range lsp.Range
+---
---The actual color value for this color range.
---@field color lsp.Color
----@class lsp.DocumentColorRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
+---@class lsp.DocumentColorRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentColorOptions, lsp.StaticRegistrationOptions
---Parameters for a {@link ColorPresentationRequest}.
----@class lsp.ColorPresentationParams
+---@class lsp.ColorPresentationParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The color to request presentations for.
---@field color lsp.Color
+---
---The range where the color would be inserted. Serves as a context.
---@field range lsp.Range
---@class lsp.ColorPresentation
+---
---The label of this color presentation. It will be shown on the color
---picker header. By default this is also the text that is inserted when selecting
---this color presentation.
---@field label string
+---
---An {@link TextEdit edit} which is applied to a document when selecting
---this presentation for the color. When `falsy` the {@link ColorPresentation.label label}
---is used.
---@field textEdit? lsp.TextEdit
+---
---An optional array of additional {@link TextEdit text edits} that are applied when
---selecting this color presentation. Edits must not overlap with the main {@link ColorPresentation.textEdit edit} nor with themselves.
---@field additionalTextEdits? lsp.TextEdit[]
---@class lsp.WorkDoneProgressOptions
+---
---@field workDoneProgress? boolean
---General text document registration options.
---@class lsp.TextDocumentRegistrationOptions
+---
---A document selector to identify the scope of the registration. If set to null
---the document selector provided on the client side will be used.
---@field documentSelector lsp.DocumentSelector|lsp.null
---Parameters for a {@link FoldingRangeRequest}.
----@class lsp.FoldingRangeParams
+---@class lsp.FoldingRangeParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
---Represents a folding range. To be valid, start and end line must be bigger than zero and smaller
---than the number of lines in the document. Clients are free to ignore invalid ranges.
---@class lsp.FoldingRange
+---
---The zero-based start line of the range to fold. The folded area starts after the line's last character.
---To be valid, the end must be zero or larger and smaller than the number of lines in the document.
---@field startLine uinteger
+---
---The zero-based character offset from where the folded range starts. If not defined, defaults to the length of the start line.
---@field startCharacter? uinteger
+---
---The zero-based end line of the range to fold. The folded area ends with the line's last character.
---To be valid, the end must be zero or larger and smaller than the number of lines in the document.
---@field endLine uinteger
+---
---The zero-based character offset before the folded range ends. If not defined, defaults to the length of the end line.
---@field endCharacter? uinteger
+---
---Describes the kind of the folding range such as `comment' or 'region'. The kind
---is used to categorize folding ranges and used by commands like 'Fold all comments'.
---See {@link FoldingRangeKind} for an enumeration of standardized kinds.
---@field kind? lsp.FoldingRangeKind
+---
---The text that the client should show when the specified range is
---collapsed. If not defined or not supported by the client, a default
---will be chosen by the client.
@@ -121,34 +146,40 @@ error('Cannot require a meta file')
---@since 3.17.0
---@field collapsedText? string
----@class lsp.FoldingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
+---@class lsp.FoldingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.FoldingRangeOptions, lsp.StaticRegistrationOptions
---@class lsp.DeclarationParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams
----@class lsp.DeclarationRegistrationOptions: lsp.DeclarationOptions, lsp.StaticRegistrationOptions
+---@class lsp.DeclarationRegistrationOptions: lsp.DeclarationOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
---A parameter literal used in selection range requests.
----@class lsp.SelectionRangeParams
+---@class lsp.SelectionRangeParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The positions inside the text document.
---@field positions lsp.Position[]
---A selection range represents a part of a selection hierarchy. A selection range
---may have a parent selection range that contains it.
---@class lsp.SelectionRange
+---
---The {@link Range range} of this selection range.
---@field range lsp.Range
+---
---The parent selection range containing this range. Therefore `parent.range` must contain `this.range`.
---@field parent? lsp.SelectionRange
----@class lsp.SelectionRangeRegistrationOptions: lsp.SelectionRangeOptions, lsp.StaticRegistrationOptions
+---@class lsp.SelectionRangeRegistrationOptions: lsp.SelectionRangeOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
---@class lsp.WorkDoneProgressCreateParams
+---
---The token to be used to report progress.
---@field token lsp.ProgressToken
---@class lsp.WorkDoneProgressCancelParams
+---
---The token to be used to report progress.
---@field token lsp.ProgressToken
@@ -162,21 +193,29 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.CallHierarchyItem
+---
---The name of this item.
---@field name string
+---
---The kind of this item.
---@field kind lsp.SymbolKind
+---
---Tags for this item.
---@field tags? lsp.SymbolTag[]
+---
---More detail for this item, e.g. the signature of a function.
---@field detail? string
+---
---The resource identifier of this item.
---@field uri lsp.DocumentUri
+---
---The range enclosing this symbol not including leading/trailing whitespace but everything else, e.g. comments and code.
---@field range lsp.Range
+---
---The range that should be selected and revealed when this symbol is being picked, e.g. the name of a function.
---Must be contained by the {@link CallHierarchyItem.range `range`}.
---@field selectionRange lsp.Range
+---
---A data entry field that is preserved between a call hierarchy prepare and
---incoming calls or outgoing calls requests.
---@field data? lsp.LSPAny
@@ -184,20 +223,23 @@ error('Cannot require a meta file')
---Call hierarchy options used during static or dynamic registration.
---
---@since 3.16.0
----@class lsp.CallHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
+---@class lsp.CallHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CallHierarchyOptions, lsp.StaticRegistrationOptions
---The parameter of a `callHierarchy/incomingCalls` request.
---
---@since 3.16.0
----@class lsp.CallHierarchyIncomingCallsParams
+---@class lsp.CallHierarchyIncomingCallsParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---@field item lsp.CallHierarchyItem
---Represents an incoming call, e.g. a caller of a method or constructor.
---
---@since 3.16.0
---@class lsp.CallHierarchyIncomingCall
+---
---The item that makes the call.
---@field from lsp.CallHierarchyItem
+---
---The ranges at which the calls appear. This is relative to the caller
---denoted by {@link CallHierarchyIncomingCall.from `this.from`}.
---@field fromRanges lsp.Range[]
@@ -205,64 +247,78 @@ error('Cannot require a meta file')
---The parameter of a `callHierarchy/outgoingCalls` request.
---
---@since 3.16.0
----@class lsp.CallHierarchyOutgoingCallsParams
+---@class lsp.CallHierarchyOutgoingCallsParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---@field item lsp.CallHierarchyItem
---Represents an outgoing call, e.g. calling a getter from a method or a method from a constructor etc.
---
---@since 3.16.0
---@class lsp.CallHierarchyOutgoingCall
+---
---The item that is called.
---@field to lsp.CallHierarchyItem
+---
---The range at which this item is called. This is the range relative to the caller, e.g the item
---passed to {@link CallHierarchyItemProvider.provideCallHierarchyOutgoingCalls `provideCallHierarchyOutgoingCalls`}
---and not {@link CallHierarchyOutgoingCall.to `this.to`}.
---@field fromRanges lsp.Range[]
---@since 3.16.0
----@class lsp.SemanticTokensParams
+---@class lsp.SemanticTokensParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
---@since 3.16.0
---@class lsp.SemanticTokens
+---
---An optional result id. If provided and clients support delta updating
---the client will include the result id in the next semantic token request.
---A server can then instead of computing all semantic tokens again simply
---send a delta.
---@field resultId? string
+---
---The actual tokens.
---@field data uinteger[]
---@since 3.16.0
---@class lsp.SemanticTokensPartialResult
+---
---@field data uinteger[]
---@since 3.16.0
----@class lsp.SemanticTokensRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
+---@class lsp.SemanticTokensRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.SemanticTokensOptions, lsp.StaticRegistrationOptions
---@since 3.16.0
----@class lsp.SemanticTokensDeltaParams
+---@class lsp.SemanticTokensDeltaParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The result id of a previous response. The result Id can either point to a full response
---or a delta response depending on what was received last.
---@field previousResultId string
---@since 3.16.0
---@class lsp.SemanticTokensDelta
+---
---@field resultId? string
+---
---The semantic token edits to transform a previous result into a new result.
---@field edits lsp.SemanticTokensEdit[]
---@since 3.16.0
---@class lsp.SemanticTokensDeltaPartialResult
+---
---@field edits lsp.SemanticTokensEdit[]
---@since 3.16.0
----@class lsp.SemanticTokensRangeParams
+---@class lsp.SemanticTokensRangeParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The range the semantic tokens are requested for.
---@field range lsp.Range
@@ -270,17 +326,21 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.ShowDocumentParams
+---
---The uri to show.
---@field uri lsp.URI
+---
---Indicates to show the resource in an external program.
---To show, for example, `https://code.visualstudio.com/`
---in the default WEB browser set `external` to `true`.
---@field external? boolean
+---
---An optional property to indicate whether the editor
---showing the document should take focus or not.
---Clients might ignore this property if an external
---program is started.
---@field takeFocus? boolean
+---
---An optional selection range if the document is a text
---document. Clients might ignore the property if an
---external program is started or the file is not a text
@@ -291,6 +351,7 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.ShowDocumentResult
+---
---A boolean indicating if the show was successful.
---@field success boolean
@@ -300,21 +361,24 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.LinkedEditingRanges
+---
---A list of ranges that can be edited together. The ranges must have
---identical length and contain identical text content. The ranges cannot overlap.
---@field ranges lsp.Range[]
+---
---An optional word pattern (regular expression) that describes valid contents for
---the given ranges. If no pattern is provided, the client configuration's word
---pattern will be used.
---@field wordPattern? string
----@class lsp.LinkedEditingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
+---@class lsp.LinkedEditingRangeRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.LinkedEditingRangeOptions, lsp.StaticRegistrationOptions
---The parameters sent in notifications/requests for user-initiated creation of
---files.
---
---@since 3.16.0
---@class lsp.CreateFilesParams
+---
---An array of all files/folders created in this operation.
---@field files lsp.FileCreate[]
@@ -331,8 +395,10 @@ error('Cannot require a meta file')
---cause failure of the operation. How the client recovers from the failure is described by
---the client capability: `workspace.workspaceEdit.failureHandling`
---@class lsp.WorkspaceEdit
+---
---Holds changes to existing resources.
---@field changes? table<lsp.DocumentUri, lsp.TextEdit[]>
+---
---Depending on the client capability `workspace.workspaceEdit.resourceOperations` document changes
---are either an array of `TextDocumentEdit`s to express changes to n different text documents
---where each text document edit addresses a specific version of a text document. Or it can contain
@@ -343,7 +409,8 @@ error('Cannot require a meta file')
---
---If a client neither supports `documentChanges` nor `workspace.workspaceEdit.resourceOperations` then
---only plain `TextEdit`s using the `changes` property are supported.
----@field documentChanges? lsp.TextDocumentEdit|lsp.CreateFile|lsp.RenameFile|lsp.DeleteFile[]
+---@field documentChanges? (lsp.TextDocumentEdit|lsp.CreateFile|lsp.RenameFile|lsp.DeleteFile)[]
+---
---A map of change annotations that can be referenced in `AnnotatedTextEdit`s or create, rename and
---delete file / folder operations.
---
@@ -356,6 +423,7 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.FileOperationRegistrationOptions
+---
---The actual filters.
---@field filters lsp.FileOperationFilter[]
@@ -364,6 +432,7 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.RenameFilesParams
+---
---An array of all files/folders renamed in this operation. When a folder is renamed, only
---the folder will be included, and not its children.
---@field files lsp.FileRename[]
@@ -373,6 +442,7 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.DeleteFilesParams
+---
---An array of all files/folders deleted in this operation.
---@field files lsp.FileDelete[]
@@ -382,17 +452,21 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.Moniker
+---
---The scheme of the moniker. For example tsc or .Net
---@field scheme string
+---
---The identifier of the moniker. The value is opaque in LSIF however
---schema owners are allowed to define the structure if they want.
---@field identifier string
+---
---The scope in which the moniker is unique
---@field unique lsp.UniquenessLevel
+---
---The moniker kind if known.
---@field kind? lsp.MonikerKind
----@class lsp.MonikerRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.MonikerRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.MonikerOptions
---The parameter of a `textDocument/prepareTypeHierarchy` request.
---
@@ -401,23 +475,31 @@ error('Cannot require a meta file')
---@since 3.17.0
---@class lsp.TypeHierarchyItem
+---
---The name of this item.
---@field name string
+---
---The kind of this item.
---@field kind lsp.SymbolKind
+---
---Tags for this item.
---@field tags? lsp.SymbolTag[]
+---
---More detail for this item, e.g. the signature of a function.
---@field detail? string
+---
---The resource identifier of this item.
---@field uri lsp.DocumentUri
+---
---The range enclosing this symbol not including leading/trailing whitespace
---but everything else, e.g. comments and code.
---@field range lsp.Range
+---
---The range that should be selected and revealed when this symbol is being
---picked, e.g. the name of a function. Must be contained by the
---{@link TypeHierarchyItem.range `range`}.
---@field selectionRange lsp.Range
+---
---A data entry field that is preserved between a type hierarchy prepare and
---supertypes or subtypes requests. It could also be used to identify the
---type hierarchy in the server, helping improve the performance on
@@ -427,28 +509,33 @@ error('Cannot require a meta file')
---Type hierarchy options used during static or dynamic registration.
---
---@since 3.17.0
----@class lsp.TypeHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
+---@class lsp.TypeHierarchyRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.TypeHierarchyOptions, lsp.StaticRegistrationOptions
---The parameter of a `typeHierarchy/supertypes` request.
---
---@since 3.17.0
----@class lsp.TypeHierarchySupertypesParams
+---@class lsp.TypeHierarchySupertypesParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---@field item lsp.TypeHierarchyItem
---The parameter of a `typeHierarchy/subtypes` request.
---
---@since 3.17.0
----@class lsp.TypeHierarchySubtypesParams
+---@class lsp.TypeHierarchySubtypesParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---@field item lsp.TypeHierarchyItem
---A parameter literal used in inline value requests.
---
---@since 3.17.0
----@class lsp.InlineValueParams
+---@class lsp.InlineValueParams: lsp.WorkDoneProgressParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The document range for which inline values should be computed.
---@field range lsp.Range
+---
---Additional information about the context in which inline values were
---requested.
---@field context lsp.InlineValueContext
@@ -456,14 +543,16 @@ error('Cannot require a meta file')
---Inline value options used during static or dynamic registration.
---
---@since 3.17.0
----@class lsp.InlineValueRegistrationOptions: lsp.InlineValueOptions, lsp.StaticRegistrationOptions
+---@class lsp.InlineValueRegistrationOptions: lsp.InlineValueOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
---A parameter literal used in inlay hint requests.
---
---@since 3.17.0
----@class lsp.InlayHintParams
+---@class lsp.InlayHintParams: lsp.WorkDoneProgressParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The document range for which inlay hints should be computed.
---@field range lsp.Range
@@ -471,36 +560,47 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.InlayHint
+---
---The position of this hint.
+---
+---If multiple hints have the same position, they will be shown in the order
+---they appear in the response.
---@field position lsp.Position
+---
---The label of this hint. A human readable string or an array of
---InlayHintLabelPart label parts.
---
---*Note* that neither the string nor the label part can be empty.
---@field label string|lsp.InlayHintLabelPart[]
+---
---The kind of this hint. Can be omitted in which case the client
---should fall back to a reasonable default.
---@field kind? lsp.InlayHintKind
+---
---Optional text edits that are performed when accepting this inlay hint.
---
---*Note* that edits are expected to change the document so that the inlay
---hint (or its nearest variant) is now part of the document and the inlay
---hint itself is now obsolete.
---@field textEdits? lsp.TextEdit[]
+---
---The tooltip text when you hover over this item.
---@field tooltip? string|lsp.MarkupContent
+---
---Render padding before the hint.
---
---Note: Padding should use the editor's background color, not the
---background color of the hint itself. That means padding can be used
---to visually align/separate an inlay hint.
---@field paddingLeft? boolean
+---
---Render padding after the hint.
---
---Note: Padding should use the editor's background color, not the
---background color of the hint itself. That means padding can be used
---to visually align/separate an inlay hint.
---@field paddingRight? boolean
+---
---A data entry field that is preserved on an inlay hint between
---a `textDocument/inlayHint` and a `inlayHint/resolve` request.
---@field data? lsp.LSPAny
@@ -508,16 +608,19 @@ error('Cannot require a meta file')
---Inlay hint options used during static or dynamic registration.
---
---@since 3.17.0
----@class lsp.InlayHintRegistrationOptions: lsp.InlayHintOptions, lsp.StaticRegistrationOptions
+---@class lsp.InlayHintRegistrationOptions: lsp.InlayHintOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
---Parameters of the document diagnostic request.
---
---@since 3.17.0
----@class lsp.DocumentDiagnosticParams
+---@class lsp.DocumentDiagnosticParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The additional identifier provided during registration.
---@field identifier? string
+---
---The result id of a previous response if provided.
---@field previousResultId? string
@@ -525,25 +628,29 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.DocumentDiagnosticReportPartialResult
+---
---@field relatedDocuments table<lsp.DocumentUri, lsp.FullDocumentDiagnosticReport|lsp.UnchangedDocumentDiagnosticReport>
---Cancellation data returned from a diagnostic request.
---
---@since 3.17.0
---@class lsp.DiagnosticServerCancellationData
+---
---@field retriggerRequest boolean
---Diagnostic registration options.
---
---@since 3.17.0
----@class lsp.DiagnosticRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
+---@class lsp.DiagnosticRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DiagnosticOptions, lsp.StaticRegistrationOptions
---Parameters of the workspace diagnostic request.
---
---@since 3.17.0
----@class lsp.WorkspaceDiagnosticParams
+---@class lsp.WorkspaceDiagnosticParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The additional identifier provided during registration.
---@field identifier? string
+---
---The currently known diagnostic reports with their
---previous result ids.
---@field previousResultIds lsp.PreviousResultId[]
@@ -552,20 +659,24 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.WorkspaceDiagnosticReport
+---
---@field items lsp.WorkspaceDocumentDiagnosticReport[]
---A partial result for a workspace diagnostic report.
---
---@since 3.17.0
---@class lsp.WorkspaceDiagnosticReportPartialResult
+---
---@field items lsp.WorkspaceDocumentDiagnosticReport[]
---The params sent in an open notebook document notification.
---
---@since 3.17.0
---@class lsp.DidOpenNotebookDocumentParams
+---
---The notebook document that got opened.
---@field notebookDocument lsp.NotebookDocument
+---
---The text documents that represent the content
---of a notebook cell.
---@field cellTextDocuments lsp.TextDocumentItem[]
@@ -574,11 +685,13 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.DidChangeNotebookDocumentParams
+---
---The notebook document that did change. The version number points
---to the version after all provided changes have been applied. If
---only the text document content of a cell changes the notebook version
---doesn't necessarily have to change.
---@field notebookDocument lsp.VersionedNotebookDocumentIdentifier
+---
---The actual changes to the notebook document.
---
---The changes describe single state changes to the notebook document.
@@ -598,6 +711,7 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.DidSaveNotebookDocumentParams
+---
---The notebook document that got saved.
---@field notebookDocument lsp.NotebookDocumentIdentifier
@@ -605,8 +719,10 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.DidCloseNotebookDocumentParams
+---
---The notebook document that got closed.
---@field notebookDocument lsp.NotebookDocumentIdentifier
+---
---The text documents that represent the content
---of a notebook cell that got closed.
---@field cellTextDocuments lsp.TextDocumentIdentifier[]
@@ -614,56 +730,71 @@ error('Cannot require a meta file')
---A parameter literal used in inline completion requests.
---
---@since 3.18.0
+---@proposed
---@class lsp.InlineCompletionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams
+---
---Additional information about the context in which inline completions were
---requested.
---@field context lsp.InlineCompletionContext
---Represents a collection of {@link InlineCompletionItem inline completion items} to be presented in the editor.
+---
+---@since 3.18.0
+---@proposed
---@class lsp.InlineCompletionList
+---
---The inline completion items
---@field items lsp.InlineCompletionItem[]
---An inline completion item represents a text snippet that is proposed inline to complete text that is being typed.
---
---@since 3.18.0
+---@proposed
---@class lsp.InlineCompletionItem
+---
---The text to replace the range with. Must be set.
----@field insertText string
----The format of the insert text. The format applies to the `insertText`. If omitted defaults to `InsertTextFormat.PlainText`.
----@field insertTextFormat? lsp.InsertTextFormat
+---@field insertText string|lsp.StringValue
+---
---A text that is used to decide if this inline completion should be shown. When `falsy` the {@link InlineCompletionItem.insertText} is used.
---@field filterText? string
+---
---The range to replace. Must begin and end on the same line.
---@field range? lsp.Range
+---
---An optional {@link Command} that is executed *after* inserting this completion.
---@field command? lsp.Command
---Inline completion options used during static or dynamic registration.
---
---@since 3.18.0
----@class lsp.InlineCompletionRegistrationOptions: lsp.InlineCompletionOptions, lsp.StaticRegistrationOptions
+---@proposed
+---@class lsp.InlineCompletionRegistrationOptions: lsp.InlineCompletionOptions, lsp.TextDocumentRegistrationOptions, lsp.StaticRegistrationOptions
---@class lsp.RegistrationParams
+---
---@field registrations lsp.Registration[]
---@class lsp.UnregistrationParams
+---
---@field unregisterations lsp.Unregistration[]
----@class lsp.InitializeParams: lsp._InitializeParams
+---@class lsp.InitializeParams: lsp._InitializeParams, lsp.WorkspaceFoldersInitializeParams
---The result returned from an initialize request.
---@class lsp.InitializeResult
+---
---The capabilities the language server provides.
---@field capabilities lsp.ServerCapabilities
+---
---Information about the server.
---
---@since 3.15.0
----@field serverInfo? anonym1
+---@field serverInfo? lsp._anonym1.serverInfo
---The data type of the ResponseError if the
---initialize request fails.
---@class lsp.InitializeError
+---
---Indicates whether the client execute the following retry logic:
---(1) show the message provided by the ResponseError to the user
---(2) user selects retry or cancel
@@ -674,49 +805,62 @@ error('Cannot require a meta file')
---The parameters of a change configuration notification.
---@class lsp.DidChangeConfigurationParams
+---
---The actual changed settings
---@field settings lsp.LSPAny
---@class lsp.DidChangeConfigurationRegistrationOptions
+---
---@field section? string|string[]
---The parameters of a notification message.
---@class lsp.ShowMessageParams
+---
---The message type. See {@link MessageType}
---@field type lsp.MessageType
+---
---The actual message.
---@field message string
---@class lsp.ShowMessageRequestParams
+---
---The message type. See {@link MessageType}
---@field type lsp.MessageType
+---
---The actual message.
---@field message string
+---
---The message action items to present.
---@field actions? lsp.MessageActionItem[]
---@class lsp.MessageActionItem
+---
---A short title like 'Retry', 'Open Log' etc.
---@field title string
---The log message parameters.
---@class lsp.LogMessageParams
+---
---The message type. See {@link MessageType}
---@field type lsp.MessageType
+---
---The actual message.
---@field message string
---The parameters sent in an open text document notification
---@class lsp.DidOpenTextDocumentParams
+---
---The document that was opened.
---@field textDocument lsp.TextDocumentItem
---The change text document notification's parameters.
---@class lsp.DidChangeTextDocumentParams
+---
---The document that did change. The version number points
---to the version after all provided content changes have
---been applied.
---@field textDocument lsp.VersionedTextDocumentIdentifier
+---
---The actual content changes. The content changes describe single state changes
---to the document. So if there are two content changes c1 (at array index 0) and
---c2 (at array index 1) for a document in state S then c1 moves the document from
@@ -732,64 +876,78 @@ error('Cannot require a meta file')
---Describe options to be used when registered for text document change events.
---@class lsp.TextDocumentChangeRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---
---How documents are synced to the server.
---@field syncKind lsp.TextDocumentSyncKind
---The parameters sent in a close text document notification
---@class lsp.DidCloseTextDocumentParams
+---
---The document that was closed.
---@field textDocument lsp.TextDocumentIdentifier
---The parameters sent in a save text document notification
---@class lsp.DidSaveTextDocumentParams
+---
---The document that was saved.
---@field textDocument lsp.TextDocumentIdentifier
+---
---Optional the content when saved. Depends on the includeText value
---when the save notification was requested.
---@field text? string
---Save registration options.
----@class lsp.TextDocumentSaveRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.TextDocumentSaveRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.SaveOptions
---The parameters sent in a will save text document notification.
---@class lsp.WillSaveTextDocumentParams
+---
---The document that will be saved.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The 'TextDocumentSaveReason'.
---@field reason lsp.TextDocumentSaveReason
---A text edit applicable to a text document.
---@class lsp.TextEdit
+---
---The range of the text document to be manipulated. To insert
---text into a document create a range where start === end.
---@field range lsp.Range
+---
---The string to be inserted. For delete operations use an
---empty string.
---@field newText string
---The watched files change notification's parameters.
---@class lsp.DidChangeWatchedFilesParams
+---
---The actual file events.
---@field changes lsp.FileEvent[]
---Describe options to be used when registered for text document change events.
---@class lsp.DidChangeWatchedFilesRegistrationOptions
+---
---The watchers to register.
---@field watchers lsp.FileSystemWatcher[]
---The publish diagnostic notification's parameters.
---@class lsp.PublishDiagnosticsParams
+---
---The URI for which diagnostic information is reported.
---@field uri lsp.DocumentUri
+---
---Optional the version number of the document the diagnostics are published for.
---
---@since 3.15.0
---@field version? integer
+---
---An array of diagnostic information items.
---@field diagnostics lsp.Diagnostic[]
---Completion parameters
---@class lsp.CompletionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The completion context. This is only available it the client specifies
---to send this using the client capability `textDocument.completion.contextSupport === true`
---@field context? lsp.CompletionContext
@@ -797,6 +955,7 @@ error('Cannot require a meta file')
---A completion item represents a text snippet that is
---proposed to complete text that is being typed.
---@class lsp.CompletionItem
+---
---The label of this completion item.
---
---The label property is also by default the text that
@@ -805,39 +964,49 @@ error('Cannot require a meta file')
---If label details are provided the label itself should
---be an unqualified name of the completion item.
---@field label string
+---
---Additional details for the label
---
---@since 3.17.0
---@field labelDetails? lsp.CompletionItemLabelDetails
+---
---The kind of this completion item. Based of the kind
---an icon is chosen by the editor.
---@field kind? lsp.CompletionItemKind
+---
---Tags for this completion item.
---
---@since 3.15.0
---@field tags? lsp.CompletionItemTag[]
+---
---A human-readable string with additional information
---about this item, like type or symbol information.
---@field detail? string
+---
---A human-readable string that represents a doc-comment.
---@field documentation? string|lsp.MarkupContent
+---
---Indicates if this item is deprecated.
---@deprecated Use `tags` instead.
---@field deprecated? boolean
+---
---Select this item when showing.
---
---*Note* that only one completion item can be selected and that the
---tool / client decides which item that is. The rule is that the *first*
---item of those that match best is selected.
---@field preselect? boolean
+---
---A string that should be used when comparing this item
---with other items. When `falsy` the {@link CompletionItem.label label}
---is used.
---@field sortText? string
+---
---A string that should be used when filtering a set of
---completion items. When `falsy` the {@link CompletionItem.label label}
---is used.
---@field filterText? string
+---
---A string that should be inserted into a document when selecting
---this completion. When `falsy` the {@link CompletionItem.label label}
---is used.
@@ -850,6 +1019,7 @@ error('Cannot require a meta file')
---recommended to use `textEdit` instead since it avoids additional client
---side interpretation.
---@field insertText? string
+---
---The format of the insert text. The format applies to both the
---`insertText` property and the `newText` property of a provided
---`textEdit`. If omitted defaults to `InsertTextFormat.PlainText`.
@@ -857,12 +1027,14 @@ error('Cannot require a meta file')
---Please note that the insertTextFormat doesn't apply to
---`additionalTextEdits`.
---@field insertTextFormat? lsp.InsertTextFormat
+---
---How whitespace and indentation is handled during completion
---item insertion. If not provided the clients default value depends on
---the `textDocument.completion.insertTextMode` client capability.
---
---@since 3.16.0
---@field insertTextMode? lsp.InsertTextMode
+---
---An {@link TextEdit edit} which is applied to a document when selecting
---this completion. When an edit is provided the value of
---{@link CompletionItem.insertText insertText} is ignored.
@@ -884,6 +1056,7 @@ error('Cannot require a meta file')
---
---@since 3.16.0 additional type `InsertReplaceEdit`
---@field textEdit? lsp.TextEdit|lsp.InsertReplaceEdit
+---
---The edit text used if the completion item is part of a CompletionList and
---CompletionList defines an item default for the text edit range.
---
@@ -895,6 +1068,7 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@field textEditText? string
+---
---An optional array of additional {@link TextEdit text edits} that are applied when
---selecting this completion. Edits must not overlap (including the same insert position)
---with the main {@link CompletionItem.textEdit edit} nor with themselves.
@@ -903,14 +1077,17 @@ error('Cannot require a meta file')
---(for example adding an import statement at the top of the file if the completion item will
---insert an unqualified type).
---@field additionalTextEdits? lsp.TextEdit[]
+---
---An optional set of characters that when pressed while this completion is active will accept it first and
---then type that character. *Note* that all commit characters should have `length=1` and that superfluous
---characters will be ignored.
---@field commitCharacters? string[]
+---
---An optional {@link Command command} that is executed *after* inserting this completion. *Note* that
---additional modifications to the current document should be described with the
---{@link CompletionItem.additionalTextEdits additionalTextEdits}-property.
---@field command? lsp.Command
+---
---A data entry field that is preserved on a completion item between a
---{@link CompletionRequest} and a {@link CompletionResolveRequest}.
---@field data? lsp.LSPAny
@@ -918,11 +1095,13 @@ error('Cannot require a meta file')
---Represents a collection of {@link CompletionItem completion items} to be presented
---in the editor.
---@class lsp.CompletionList
+---
---This list it not complete. Further typing results in recomputing this list.
---
---Recomputed lists have all their items replaced (not appended) in the
---incomplete completion sessions.
---@field isIncomplete boolean
+---
---In many cases the items of an actual completion result share the same
---value for properties like `commitCharacters` or the range of a text
---edit. A completion list can therefore define item defaults which will
@@ -936,29 +1115,33 @@ error('Cannot require a meta file')
---capability.
---
---@since 3.17.0
----@field itemDefaults? anonym3
+---@field itemDefaults? lsp._anonym2.itemDefaults
+---
---The completion items.
---@field items lsp.CompletionItem[]
---Registration options for a {@link CompletionRequest}.
----@class lsp.CompletionRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.CompletionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CompletionOptions
---Parameters for a {@link HoverRequest}.
---@class lsp.HoverParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams
---The result of a hover request.
---@class lsp.Hover
+---
---The hover's content
---@field contents lsp.MarkupContent|lsp.MarkedString|lsp.MarkedString[]
+---
---An optional range inside the text document that is used to
---visualize the hover, e.g. by changing the background color.
---@field range? lsp.Range
---Registration options for a {@link HoverRequest}.
----@class lsp.HoverRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.HoverRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.HoverOptions
---Parameters for a {@link SignatureHelpRequest}.
---@class lsp.SignatureHelpParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams
+---
---The signature help context. This is only available if the client specifies
---to send this using the client capability `textDocument.signatureHelp.contextSupport === true`
---
@@ -969,8 +1152,10 @@ error('Cannot require a meta file')
---callable. There can be multiple signature but only one
---active and only one active parameter.
---@class lsp.SignatureHelp
+---
---One or more signatures.
---@field signatures lsp.SignatureInformation[]
+---
---The active signature. If omitted or the value lies outside the
---range of `signatures` the value defaults to zero or is ignored if
---the `SignatureHelp` has no signatures.
@@ -981,30 +1166,41 @@ error('Cannot require a meta file')
---In future version of the protocol this property might become
---mandatory to better express this.
---@field activeSignature? uinteger
----The active parameter of the active signature. If omitted or the value
----lies outside the range of `signatures[activeSignature].parameters`
----defaults to 0 if the active signature has parameters. If
----the active signature has no parameters it is ignored.
+---
+---The active parameter of the active signature.
+---
+---If `null`, no parameter of the signature is active (for example a named
+---argument that does not match any declared parameters). This is only valid
+---since 3.18.0 and if the client specifies the client capability
+---`textDocument.signatureHelp.noActiveParameterSupport === true`
+---
+---If omitted or the value lies outside the range of
+---`signatures[activeSignature].parameters` defaults to 0 if the active
+---signature has parameters.
+---
+---If the active signature has no parameters it is ignored.
+---
---In future version of the protocol this property might become
----mandatory to better express the active parameter if the
----active signature does have any.
----@field activeParameter? uinteger
+---mandatory (but still nullable) to better express the active parameter if
+---the active signature does have any.
+---@field activeParameter? uinteger|lsp.null
---Registration options for a {@link SignatureHelpRequest}.
----@class lsp.SignatureHelpRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.SignatureHelpRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.SignatureHelpOptions
---Parameters for a {@link DefinitionRequest}.
---@class lsp.DefinitionParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams
---Registration options for a {@link DefinitionRequest}.
----@class lsp.DefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.DefinitionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DefinitionOptions
---Parameters for a {@link ReferencesRequest}.
---@class lsp.ReferenceParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---@field context lsp.ReferenceContext
---Registration options for a {@link ReferencesRequest}.
----@class lsp.ReferenceRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.ReferenceRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.ReferenceOptions
---Parameters for a {@link DocumentHighlightRequest}.
---@class lsp.DocumentHighlightParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams, lsp.PartialResultParams
@@ -1013,26 +1209,31 @@ error('Cannot require a meta file')
---special attention. Usually a document highlight is visualized by changing
---the background color of its range.
---@class lsp.DocumentHighlight
+---
---The range this highlight applies to.
---@field range lsp.Range
+---
---The highlight kind, default is {@link DocumentHighlightKind.Text text}.
---@field kind? lsp.DocumentHighlightKind
---Registration options for a {@link DocumentHighlightRequest}.
----@class lsp.DocumentHighlightRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.DocumentHighlightRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentHighlightOptions
---Parameters for a {@link DocumentSymbolRequest}.
----@class lsp.DocumentSymbolParams
+---@class lsp.DocumentSymbolParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
---Represents information about programming constructs like variables, classes,
---interfaces etc.
---@class lsp.SymbolInformation: lsp.BaseSymbolInformation
+---
---Indicates if this symbol is deprecated.
---
---@deprecated Use tags instead
---@field deprecated? boolean
+---
---The location of this symbol. The location's range is used by a tool
---to reveal the location in the editor. If the symbol is selected in the
---tool the range's start information is used to position the cursor. So
@@ -1049,40 +1250,51 @@ error('Cannot require a meta file')
---have two ranges: one that encloses its definition and one that points to
---its most interesting range, e.g. the range of an identifier.
---@class lsp.DocumentSymbol
+---
---The name of this symbol. Will be displayed in the user interface and therefore must not be
---an empty string or a string only consisting of white spaces.
---@field name string
+---
---More detail for this symbol, e.g the signature of a function.
---@field detail? string
+---
---The kind of this symbol.
---@field kind lsp.SymbolKind
+---
---Tags for this document symbol.
---
---@since 3.16.0
---@field tags? lsp.SymbolTag[]
+---
---Indicates if this symbol is deprecated.
---
---@deprecated Use tags instead
---@field deprecated? boolean
+---
---The range enclosing this symbol not including leading/trailing whitespace but everything else
---like comments. This information is typically used to determine if the clients cursor is
---inside the symbol to reveal in the symbol in the UI.
---@field range lsp.Range
+---
---The range that should be selected and revealed when this symbol is being picked, e.g the name of a function.
---Must be contained by the `range`.
---@field selectionRange lsp.Range
+---
---Children of this symbol, e.g. properties of a class.
---@field children? lsp.DocumentSymbol[]
---Registration options for a {@link DocumentSymbolRequest}.
----@class lsp.DocumentSymbolRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.DocumentSymbolRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentSymbolOptions
---The parameters of a {@link CodeActionRequest}.
----@class lsp.CodeActionParams
+---@class lsp.CodeActionParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The document in which the command was invoked.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The range for which the command was invoked.
---@field range lsp.Range
+---
---Context carrying additional information.
---@field context lsp.CodeActionContext
@@ -1091,10 +1303,13 @@ error('Cannot require a meta file')
---an array of arguments which will be passed to the command handler
---function when invoked.
---@class lsp.Command
+---
---Title of the command, like `save`.
---@field title string
+---
---The identifier of the actual command handler.
---@field command string
+---
---Arguments that the command handler should be
---invoked with.
---@field arguments? lsp.LSPAny[]
@@ -1104,14 +1319,18 @@ error('Cannot require a meta file')
---
---A CodeAction must set either `edit` and/or a `command`. If both are supplied, the `edit` is applied first, then the `command` is executed.
---@class lsp.CodeAction
+---
---A short, human-readable, title for this code action.
---@field title string
+---
---The kind of the code action.
---
---Used to filter code actions.
---@field kind? lsp.CodeActionKind
+---
---The diagnostics that this code action resolves.
---@field diagnostics? lsp.Diagnostic[]
+---
---Marks this as a preferred action. Preferred actions are used by the `auto fix` command and can be targeted
---by keybindings.
---
@@ -1120,6 +1339,7 @@ error('Cannot require a meta file')
---
---@since 3.15.0
---@field isPreferred? boolean
+---
---Marks that the code action cannot currently be applied.
---
---Clients should follow the following guidelines regarding disabled code actions:
@@ -1135,13 +1355,16 @@ error('Cannot require a meta file')
--- error message with `reason` in the editor.
---
---@since 3.16.0
----@field disabled? anonym4
+---@field disabled? lsp._anonym4.disabled
+---
---The workspace edit this code action performs.
---@field edit? lsp.WorkspaceEdit
+---
---A command this code action executes. If a code action
---provides an edit and a command, first the edit is
---executed and then the command.
---@field command? lsp.Command
+---
---A data entry field that is preserved on a code action between
---a `textDocument/codeAction` and a `codeAction/resolve` request.
---
@@ -1149,10 +1372,11 @@ error('Cannot require a meta file')
---@field data? lsp.LSPAny
---Registration options for a {@link CodeActionRequest}.
----@class lsp.CodeActionRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.CodeActionRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CodeActionOptions
---The parameters of a {@link WorkspaceSymbolRequest}.
----@class lsp.WorkspaceSymbolParams
+---@class lsp.WorkspaceSymbolParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---A query string to filter symbols by. Clients may send an empty
---string here to request all symbols.
---@field query string
@@ -1163,12 +1387,14 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.WorkspaceSymbol: lsp.BaseSymbolInformation
+---
---The location of the symbol. Whether a server is allowed to
---return a location without a range depends on the client
---capability `workspace.symbol.resolveSupport`.
---
---See SymbolInformation#location for more details.
----@field location lsp.Location|anonym5
+---@field location lsp.Location|lsp._anonym5.location
+---
---A data entry field that is preserved on a workspace symbol between a
---workspace symbol request and a workspace symbol resolve request.
---@field data? lsp.LSPAny
@@ -1177,7 +1403,8 @@ error('Cannot require a meta file')
---@class lsp.WorkspaceSymbolRegistrationOptions: lsp.WorkspaceSymbolOptions
---The parameters of a {@link CodeLensRequest}.
----@class lsp.CodeLensParams
+---@class lsp.CodeLensParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The document to request code lens for.
---@field textDocument lsp.TextDocumentIdentifier
@@ -1187,30 +1414,36 @@ error('Cannot require a meta file')
---A code lens is _unresolved_ when no command is associated to it. For performance
---reasons the creation of a code lens and resolving should be done in two stages.
---@class lsp.CodeLens
+---
---The range in which this code lens is valid. Should only span a single line.
---@field range lsp.Range
+---
---The command this code lens represents.
---@field command? lsp.Command
+---
---A data entry field that is preserved on a code lens item between
----a {@link CodeLensRequest} and a [CodeLensResolveRequest]
----(#CodeLensResolveRequest)
+---a {@link CodeLensRequest} and a {@link CodeLensResolveRequest}
---@field data? lsp.LSPAny
---Registration options for a {@link CodeLensRequest}.
----@class lsp.CodeLensRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.CodeLensRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.CodeLensOptions
---The parameters of a {@link DocumentLinkRequest}.
----@class lsp.DocumentLinkParams
+---@class lsp.DocumentLinkParams: lsp.WorkDoneProgressParams, lsp.PartialResultParams
+---
---The document to provide document links for.
---@field textDocument lsp.TextDocumentIdentifier
---A document link is a range in a text document that links to an internal or external resource, like another
---text document or a web site.
---@class lsp.DocumentLink
+---
---The range this link applies to.
---@field range lsp.Range
+---
---The uri this link points to. If missing a resolve request is sent later.
---@field target? lsp.URI
+---
---The tooltip text when you hover over this link.
---
---If a tooltip is provided, is will be displayed in a string that includes instructions on how to
@@ -1219,86 +1452,104 @@ error('Cannot require a meta file')
---
---@since 3.15.0
---@field tooltip? string
+---
---A data entry field that is preserved on a document link between a
---DocumentLinkRequest and a DocumentLinkResolveRequest.
---@field data? lsp.LSPAny
---Registration options for a {@link DocumentLinkRequest}.
----@class lsp.DocumentLinkRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.DocumentLinkRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentLinkOptions
---The parameters of a {@link DocumentFormattingRequest}.
----@class lsp.DocumentFormattingParams
+---@class lsp.DocumentFormattingParams: lsp.WorkDoneProgressParams
+---
---The document to format.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The format options.
---@field options lsp.FormattingOptions
---Registration options for a {@link DocumentFormattingRequest}.
----@class lsp.DocumentFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.DocumentFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentFormattingOptions
---The parameters of a {@link DocumentRangeFormattingRequest}.
----@class lsp.DocumentRangeFormattingParams
+---@class lsp.DocumentRangeFormattingParams: lsp.WorkDoneProgressParams
+---
---The document to format.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The range to format
---@field range lsp.Range
+---
---The format options
---@field options lsp.FormattingOptions
---Registration options for a {@link DocumentRangeFormattingRequest}.
----@class lsp.DocumentRangeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.DocumentRangeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentRangeFormattingOptions
---The parameters of a {@link DocumentRangesFormattingRequest}.
---
---@since 3.18.0
---@proposed
----@class lsp.DocumentRangesFormattingParams
+---@class lsp.DocumentRangesFormattingParams: lsp.WorkDoneProgressParams
+---
---The document to format.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The ranges to format
---@field ranges lsp.Range[]
+---
---The format options
---@field options lsp.FormattingOptions
---The parameters of a {@link DocumentOnTypeFormattingRequest}.
---@class lsp.DocumentOnTypeFormattingParams
+---
---The document to format.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The position around which the on type formatting should happen.
---This is not necessarily the exact position where the character denoted
---by the property `ch` got typed.
---@field position lsp.Position
+---
---The character that has been typed that triggered the formatting
---on type request. That is not necessarily the last character that
---got inserted into the document since the client could auto insert
---characters as well (e.g. like automatic brace completion).
---@field ch string
+---
---The formatting options.
---@field options lsp.FormattingOptions
---Registration options for a {@link DocumentOnTypeFormattingRequest}.
----@class lsp.DocumentOnTypeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.DocumentOnTypeFormattingRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.DocumentOnTypeFormattingOptions
---The parameters of a {@link RenameRequest}.
----@class lsp.RenameParams
+---@class lsp.RenameParams: lsp.WorkDoneProgressParams
+---
---The document to rename.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The position at which this request was sent.
---@field position lsp.Position
+---
---The new name of the symbol. If the given name is not valid the
---request must return a {@link ResponseError} with an
---appropriate message set.
---@field newName string
---Registration options for a {@link RenameRequest}.
----@class lsp.RenameRegistrationOptions: lsp.TextDocumentRegistrationOptions
+---@class lsp.RenameRegistrationOptions: lsp.TextDocumentRegistrationOptions, lsp.RenameOptions
---@class lsp.PrepareRenameParams: lsp.TextDocumentPositionParams, lsp.WorkDoneProgressParams
---The parameters of a {@link ExecuteCommandRequest}.
----@class lsp.ExecuteCommandParams
+---@class lsp.ExecuteCommandParams: lsp.WorkDoneProgressParams
+---
---The identifier of the actual command handler.
---@field command string
+---
---Arguments that the command should be invoked with.
---@field arguments? lsp.LSPAny[]
@@ -1307,10 +1558,12 @@ error('Cannot require a meta file')
---The parameters passed via an apply workspace edit request.
---@class lsp.ApplyWorkspaceEditParams
+---
---An optional label of the workspace edit. This label is
---presented in the user interface for example on an undo
---stack to undo the workspace edit.
---@field label? string
+---
---The edits to apply.
---@field edit lsp.WorkspaceEdit
@@ -1318,34 +1571,42 @@ error('Cannot require a meta file')
---
---@since 3.17 renamed from ApplyWorkspaceEditResponse
---@class lsp.ApplyWorkspaceEditResult
+---
---Indicates whether the edit was applied or not.
---@field applied boolean
+---
---An optional textual description for why the edit was not applied.
---This may be used by the server for diagnostic logging or to provide
---a suitable error for a request that triggered the edit.
---@field failureReason? string
+---
---Depending on the client's failure handling strategy `failedChange` might
---contain the index of the change that failed. This property is only available
---if the client signals a `failureHandlingStrategy` in its client capabilities.
---@field failedChange? uinteger
---@class lsp.WorkDoneProgressBegin
+---
---@field kind "begin"
+---
---Mandatory title of the progress operation. Used to briefly inform about
---the kind of operation being performed.
---
---Examples: "Indexing" or "Linking dependencies".
---@field title string
+---
---Controls if a cancel button should show to allow the user to cancel the
---long running operation. Clients that don't support cancellation are allowed
---to ignore the setting.
---@field cancellable? boolean
+---
---Optional, more detailed associated progress message. Contains
---complementary information to the `title`.
---
---Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
---If unset, the previous progress message (if any) is still valid.
---@field message? string
+---
---Optional progress percentage to display (value 100 is considered 100%).
---If not provided infinite progress is assumed and clients are allowed
---to ignore the `percentage` value in subsequent in report notifications.
@@ -1355,18 +1616,22 @@ error('Cannot require a meta file')
---@field percentage? uinteger
---@class lsp.WorkDoneProgressReport
+---
---@field kind "report"
+---
---Controls enablement state of a cancel button.
---
---Clients that don't support cancellation or don't support controlling the button's
---enablement state are allowed to ignore the property.
---@field cancellable? boolean
+---
---Optional, more detailed associated progress message. Contains
---complementary information to the `title`.
---
---Examples: "3/25 files", "project/src/module2", "node_modules/some_dep".
---If unset, the previous progress message (if any) is still valid.
---@field message? string
+---
---Optional progress percentage to display (value 100 is considered 100%).
---If not provided infinite progress is assumed and clients are allowed
---to ignore the `percentage` value in subsequent in report notifications.
@@ -1376,41 +1641,53 @@ error('Cannot require a meta file')
---@field percentage? uinteger
---@class lsp.WorkDoneProgressEnd
+---
---@field kind "end"
+---
---Optional, a final message indicating to for example indicate the outcome
---of the operation.
---@field message? string
---@class lsp.SetTraceParams
+---
---@field value lsp.TraceValues
---@class lsp.LogTraceParams
+---
---@field message string
+---
---@field verbose? string
---@class lsp.CancelParams
+---
---The request id to cancel.
---@field id integer|string
---@class lsp.ProgressParams
+---
---The progress token provided by the client or server.
---@field token lsp.ProgressToken
+---
---The progress data.
---@field value lsp.LSPAny
---A parameter literal used in requests to pass a text document and a position inside that
---document.
---@class lsp.TextDocumentPositionParams
+---
---The text document.
---@field textDocument lsp.TextDocumentIdentifier
+---
---The position inside the text document.
---@field position lsp.Position
---@class lsp.WorkDoneProgressParams
+---
---An optional token that a server can use to report work done progress.
---@field workDoneToken? lsp.ProgressToken
---@class lsp.PartialResultParams
+---
---An optional token that a server can use to report partial results (e.g. streaming) to
---the client.
---@field partialResultToken? lsp.ProgressToken
@@ -1418,17 +1695,21 @@ error('Cannot require a meta file')
---Represents the connection of two locations. Provides additional metadata over normal {@link Location locations},
---including an origin range.
---@class lsp.LocationLink
+---
---Span of the origin of this link.
---
---Used as the underlined span for mouse interaction. Defaults to the word range at
---the definition position.
---@field originSelectionRange? lsp.Range
+---
---The target resource identifier of this link.
---@field targetUri lsp.DocumentUri
+---
---The full target range of this link. If the target for example is a symbol then target range is the
---range enclosing this symbol not including leading/trailing whitespace but everything else
---like comments. This information is typically used to highlight the range in the editor.
---@field targetRange lsp.Range
+---
---The range that should be selected and revealed when this link is being followed, e.g the name of a function.
---Must be contained by the `targetRange`. See also `DocumentSymbol#range`
---@field targetSelectionRange lsp.Range
@@ -1445,56 +1726,68 @@ error('Cannot require a meta file')
---}
---```
---@class lsp.Range
+---
---The range's start position.
---@field start lsp.Position
+---
---The range's end position.
---@field end lsp.Position
----@class lsp.ImplementationOptions
+---@class lsp.ImplementationOptions: lsp.WorkDoneProgressOptions
---Static registration options to be returned in the initialize
---request.
---@class lsp.StaticRegistrationOptions
+---
---The id used to register the request. The id can be used to deregister
---the request again. See also Registration#id.
---@field id? string
----@class lsp.TypeDefinitionOptions
+---@class lsp.TypeDefinitionOptions: lsp.WorkDoneProgressOptions
---The workspace folder change event.
---@class lsp.WorkspaceFoldersChangeEvent
+---
---The array of added workspace folders
---@field added lsp.WorkspaceFolder[]
+---
---The array of the removed workspace folders
---@field removed lsp.WorkspaceFolder[]
---@class lsp.ConfigurationItem
+---
---The scope to get the configuration section for.
----@field scopeUri? string
+---@field scopeUri? lsp.URI
+---
---The configuration section asked for.
---@field section? string
---A literal to identify a text document in the client.
---@class lsp.TextDocumentIdentifier
+---
---The text document's uri.
---@field uri lsp.DocumentUri
---Represents a color in RGBA space.
---@class lsp.Color
+---
---The red component of this color in the range [0-1].
---@field red decimal
+---
---The green component of this color in the range [0-1].
---@field green decimal
+---
---The blue component of this color in the range [0-1].
---@field blue decimal
+---
---The alpha component of this color in the range [0-1].
---@field alpha decimal
----@class lsp.DocumentColorOptions
+---@class lsp.DocumentColorOptions: lsp.WorkDoneProgressOptions
----@class lsp.FoldingRangeOptions
+---@class lsp.FoldingRangeOptions: lsp.WorkDoneProgressOptions
----@class lsp.DeclarationOptions
+---@class lsp.DeclarationOptions: lsp.WorkDoneProgressOptions
---Position in a text document expressed as zero-based line and character
---offset. Prior to 3.17 the offsets were always based on a UTF-16 string
@@ -1503,14 +1796,14 @@ error('Cannot require a meta file')
---offset of b is 3 since `ð€` is represented using two code units in UTF-16.
---Since 3.17 clients and servers can agree on a different string encoding
---representation (e.g. UTF-8). The client announces it's supported encoding
----via the client capability [`general.positionEncodings`](#clientCapabilities).
+---via the client capability [`general.positionEncodings`](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#clientCapabilities).
---The value is an array of position encodings the client supports, with
---decreasing preference (e.g. the encoding at index `0` is the most preferred
---one). To stay backwards compatible the only mandatory encoding is UTF-16
---represented via the string `utf-16`. The server can pick one of the
---encodings offered by the client and signals that encoding back to the
---client via the initialize result's property
----[`capabilities.positionEncoding`](#serverCapabilities). If the string value
+---[`capabilities.positionEncoding`](https://microsoft.github.io/language-server-protocol/specifications/specification-current/#serverCapabilities). If the string value
---`utf-16` is missing from the client's capability `general.positionEncodings`
---servers can safely assume that the client supports UTF-16. If the server
---omits the position encoding in its initialize result the encoding defaults
@@ -1524,11 +1817,13 @@ error('Cannot require a meta file')
---
---@since 3.17.0 - support for negotiated position encoding.
---@class lsp.Position
+---
---Line position in a document (zero-based).
---
---If a line number is greater than the number of lines in a document, it defaults back to the number of lines in the document.
---If a line number is negative, it defaults to 0.
---@field line uinteger
+---
---Character offset on a line in a document (zero-based).
---
---The meaning of this offset is determined by the negotiated
@@ -1538,38 +1833,45 @@ error('Cannot require a meta file')
---line length.
---@field character uinteger
----@class lsp.SelectionRangeOptions
+---@class lsp.SelectionRangeOptions: lsp.WorkDoneProgressOptions
---Call hierarchy options used during static registration.
---
---@since 3.16.0
----@class lsp.CallHierarchyOptions
+---@class lsp.CallHierarchyOptions: lsp.WorkDoneProgressOptions
---@since 3.16.0
----@class lsp.SemanticTokensOptions
+---@class lsp.SemanticTokensOptions: lsp.WorkDoneProgressOptions
+---
---The legend used by the server
---@field legend lsp.SemanticTokensLegend
+---
---Server supports providing semantic tokens for a specific range
---of a document.
----@field range? boolean|anonym6
+---@field range? boolean|lsp._anonym6.range
+---
---Server supports providing semantic tokens for a full document.
----@field full? boolean|anonym7
+---@field full? boolean|lsp._anonym7.full
---@since 3.16.0
---@class lsp.SemanticTokensEdit
+---
---The start offset of the edit.
---@field start uinteger
+---
---The count of elements to remove.
---@field deleteCount uinteger
+---
---The elements to insert.
---@field data? uinteger[]
----@class lsp.LinkedEditingRangeOptions
+---@class lsp.LinkedEditingRangeOptions: lsp.WorkDoneProgressOptions
---Represents information on a file/folder create.
---
---@since 3.16.0
---@class lsp.FileCreate
+---
---A file:// URI for the location of the file/folder being created.
---@field uri string
@@ -1578,40 +1880,52 @@ error('Cannot require a meta file')
---So the creator of a TextDocumentEdit doesn't need to sort the array of edits or do any
---kind of ordering. However the edits must be non overlapping.
---@class lsp.TextDocumentEdit
+---
---The text document to change.
---@field textDocument lsp.OptionalVersionedTextDocumentIdentifier
+---
---The edits to be applied.
---
---@since 3.16.0 - support for AnnotatedTextEdit. This is guarded using a
---client capability.
----@field edits lsp.TextEdit|lsp.AnnotatedTextEdit[]
+---@field edits (lsp.TextEdit|lsp.AnnotatedTextEdit)[]
---Create file operation.
---@class lsp.CreateFile: lsp.ResourceOperation
+---
---A create
---@field kind "create"
+---
---The resource to create.
---@field uri lsp.DocumentUri
+---
---Additional options
---@field options? lsp.CreateFileOptions
---Rename file operation
---@class lsp.RenameFile: lsp.ResourceOperation
+---
---A rename
---@field kind "rename"
+---
---The old (existing) location.
---@field oldUri lsp.DocumentUri
+---
---The new location.
---@field newUri lsp.DocumentUri
+---
---Rename options.
---@field options? lsp.RenameFileOptions
---Delete file operation
---@class lsp.DeleteFile: lsp.ResourceOperation
+---
---A delete
---@field kind "delete"
+---
---The file to delete.
---@field uri lsp.DocumentUri
+---
---Delete options.
---@field options? lsp.DeleteFileOptions
@@ -1619,12 +1933,15 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.ChangeAnnotation
+---
---A human-readable string describing the actual change. The string
---is rendered prominent in the user interface.
---@field label string
+---
---A flag which indicates that user confirmation is needed
---before applying the change.
---@field needsConfirmation? boolean
+---
---A human-readable string which is rendered less prominent in
---the user interface.
---@field description? string
@@ -1634,8 +1951,10 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.FileOperationFilter
+---
---A Uri scheme like `file` or `untitled`.
---@field scheme? string
+---
---The actual file operation pattern.
---@field pattern lsp.FileOperationPattern
@@ -1643,8 +1962,10 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.FileRename
+---
---A file:// URI for the original location of the file/folder being renamed.
---@field oldUri string
+---
---A file:// URI for the new location of the file/folder being renamed.
---@field newUri string
@@ -1652,20 +1973,23 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.FileDelete
+---
---A file:// URI for the location of the file/folder being deleted.
---@field uri string
----@class lsp.MonikerOptions
+---@class lsp.MonikerOptions: lsp.WorkDoneProgressOptions
---Type hierarchy options used during static registration.
---
---@since 3.17.0
----@class lsp.TypeHierarchyOptions
+---@class lsp.TypeHierarchyOptions: lsp.WorkDoneProgressOptions
---@since 3.17.0
---@class lsp.InlineValueContext
+---
---The stack frame (as a DAP Id) where the execution has stopped.
---@field frameId integer
+---
---The document range where execution has stopped.
---Typically the end position of the range denotes the line where the inline values are shown.
---@field stoppedLocation lsp.Range
@@ -1674,8 +1998,10 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.InlineValueText
+---
---The document range for which the inline value applies.
---@field range lsp.Range
+---
---The text of the inline value.
---@field text string
@@ -1685,11 +2011,14 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.InlineValueVariableLookup
+---
---The document range for which the inline value applies.
---The range is used to extract the variable name from the underlying document.
---@field range lsp.Range
+---
---If specified the name of the variable to look up.
---@field variableName? string
+---
---How to perform the lookup.
---@field caseSensitiveLookup boolean
@@ -1699,28 +2028,33 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.InlineValueEvaluatableExpression
+---
---The document range for which the inline value applies.
---The range is used to extract the evaluatable expression from the underlying document.
---@field range lsp.Range
+---
---If specified the expression overrides the extracted expression.
---@field expression? string
---Inline value options used during static registration.
---
---@since 3.17.0
----@class lsp.InlineValueOptions
+---@class lsp.InlineValueOptions: lsp.WorkDoneProgressOptions
---An inlay hint label part allows for interactive and composite labels
---of inlay hints.
---
---@since 3.17.0
---@class lsp.InlayHintLabelPart
+---
---The value of this label part.
---@field value string
+---
---The tooltip text when you hover over this label part. Depending on
---the client capability `inlayHint.resolveSupport` clients might resolve
---this property late using the resolve request.
---@field tooltip? string|lsp.MarkupContent
+---
---An optional source code location that represents this
---label part.
---
@@ -1733,6 +2067,7 @@ error('Cannot require a meta file')
---Depending on the client capability `inlayHint.resolveSupport` clients
---might resolve this property late using the resolve request.
---@field location? lsp.Location
+---
---An optional command for this label part.
---
---Depending on the client capability `inlayHint.resolveSupport` clients
@@ -1762,15 +2097,18 @@ error('Cannot require a meta file')
---*Please Note* that clients might sanitize the return markdown. A client could decide to
---remove HTML from the markdown to avoid script execution.
---@class lsp.MarkupContent
+---
---The type of the Markup
---@field kind lsp.MarkupKind
+---
---The content itself
---@field value string
---Inlay hint options used during static registration.
---
---@since 3.17.0
----@class lsp.InlayHintOptions
+---@class lsp.InlayHintOptions: lsp.WorkDoneProgressOptions
+---
---The server provides support to resolve additional
---information for an inlay hint item.
---@field resolveProvider? boolean
@@ -1779,6 +2117,7 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.RelatedFullDocumentDiagnosticReport: lsp.FullDocumentDiagnosticReport
+---
---Diagnostics of related documents. This information is useful
---in programming languages where code in a file A can generate
---diagnostics in a file B which A depends on. An example of
@@ -1792,6 +2131,7 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.RelatedUnchangedDocumentDiagnosticReport: lsp.UnchangedDocumentDiagnosticReport
+---
---Diagnostics of related documents. This information is useful
---in programming languages where code in a file A can generate
---diagnostics in a file B which A depends on. An example of
@@ -1805,12 +2145,15 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.FullDocumentDiagnosticReport
+---
---A full document diagnostic report.
---@field kind "full"
+---
---An optional result id. If provided it will
---be sent on the next diagnostic request for the
---same document.
---@field resultId? string
+---
---The actual items.
---@field items lsp.Diagnostic[]
@@ -1819,11 +2162,13 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.UnchangedDocumentDiagnosticReport
+---
---A document diagnostic report indicating
---no changes to the last result. A server can
---only return `unchanged` if result ids are
---provided.
---@field kind "unchanged"
+---
---A result id which will be sent on the next
---diagnostic request for the same document.
---@field resultId string
@@ -1831,15 +2176,18 @@ error('Cannot require a meta file')
---Diagnostic options.
---
---@since 3.17.0
----@class lsp.DiagnosticOptions
+---@class lsp.DiagnosticOptions: lsp.WorkDoneProgressOptions
+---
---An optional identifier under which the diagnostics are
---managed by the client.
---@field identifier? string
+---
---Whether the language has inter file dependencies meaning that
---editing code in one file can result in a different diagnostic
---set in another file. Inter file dependencies are common for
---most programming languages and typically uncommon for linters.
---@field interFileDependencies boolean
+---
---The server provides support for workspace diagnostics as well.
---@field workspaceDiagnostics boolean
@@ -1847,9 +2195,11 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.PreviousResultId
+---
---The URI for which the client knowns a
---result id.
---@field uri lsp.DocumentUri
+---
---The value of the previous result id.
---@field value string
@@ -1857,31 +2207,40 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.NotebookDocument
+---
---The notebook document's uri.
---@field uri lsp.URI
+---
---The type of the notebook.
---@field notebookType string
+---
---The version number of this document (it will increase after each
---change, including undo/redo).
---@field version integer
+---
---Additional metadata stored with the notebook
---document.
---
---Note: should always be an object literal (e.g. LSPObject)
---@field metadata? lsp.LSPObject
+---
---The cells of a notebook.
---@field cells lsp.NotebookCell[]
---An item to transfer a text document from the client to the
---server.
---@class lsp.TextDocumentItem
+---
---The text document's uri.
---@field uri lsp.DocumentUri
+---
---The text document's language identifier.
---@field languageId string
+---
---The version number of this document (it will increase after each
---change, including undo/redo).
---@field version integer
+---
---The content of the opened text document.
---@field text string
@@ -1889,8 +2248,10 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.VersionedNotebookDocumentIdentifier
+---
---The version number of this notebook document.
---@field version integer
+---
---The notebook document's uri.
---@field uri lsp.URI
@@ -1898,64 +2259,97 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.NotebookDocumentChangeEvent
+---
---The changed meta data if any.
---
---Note: should always be an object literal (e.g. LSPObject)
---@field metadata? lsp.LSPObject
+---
---Changes to cells
----@field cells? anonym10
+---@field cells? lsp._anonym8.cells
---A literal to identify a notebook document in the client.
---
---@since 3.17.0
---@class lsp.NotebookDocumentIdentifier
+---
---The notebook document's uri.
---@field uri lsp.URI
---Provides information about the context in which an inline completion was requested.
---
---@since 3.18.0
+---@proposed
---@class lsp.InlineCompletionContext
+---
---Describes how the inline completion was triggered.
---@field triggerKind lsp.InlineCompletionTriggerKind
+---
---Provides information about the currently selected item in the autocomplete widget if it is visible.
---@field selectedCompletionInfo? lsp.SelectedCompletionInfo
+---A string value used as a snippet is a template which allows to insert text
+---and to control the editor cursor when insertion happens.
+---
+---A snippet can define tab stops and placeholders with `$1`, `$2`
+---and `${3:foo}`. `$0` defines the final tab stop, it defaults to
+---the end of the snippet. Variables are defined with `$name` and
+---`${name:default value}`.
+---
+---@since 3.18.0
+---@proposed
+---@class lsp.StringValue
+---
+---The kind of string value.
+---@field kind "snippet"
+---
+---The snippet string.
+---@field value string
+
---Inline completion options used during static registration.
---
---@since 3.18.0
----@class lsp.InlineCompletionOptions
+---@proposed
+---@class lsp.InlineCompletionOptions: lsp.WorkDoneProgressOptions
----General parameters to to register for an notification or to register a provider.
+---General parameters to register for a notification or to register a provider.
---@class lsp.Registration
+---
---The id used to register the request. The id can be used to deregister
---the request again.
---@field id string
+---
---The method / capability to register for.
---@field method string
+---
---Options necessary for the registration.
---@field registerOptions? lsp.LSPAny
---General parameters to unregister a request or notification.
---@class lsp.Unregistration
+---
---The id used to unregister the request or notification. Usually an id
---provided during the register request.
---@field id string
+---
---The method to unregister for.
---@field method string
---The initialize parameters
----@class lsp._InitializeParams
+---@class lsp._InitializeParams: lsp.WorkDoneProgressParams
+---
---The process Id of the parent process that started
---the server.
---
---Is `null` if the process has not been started by another process.
---If the parent process is not alive then the server should exit.
---@field processId integer|lsp.null
+---
---Information about the client
---
---@since 3.15.0
----@field clientInfo? anonym11
+---@field clientInfo? lsp._anonym11.clientInfo
+---
---The locale the client is currently showing the user interface
---in. This must not necessarily be the locale of the operating
---system.
@@ -1965,25 +2359,31 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@field locale? string
+---
---The rootPath of the workspace. Is null
---if no folder is open.
---
---@deprecated in favour of rootUri.
---@field rootPath? string|lsp.null
+---
---The rootUri of the workspace. Is null if no
---folder is open. If both `rootPath` and `rootUri` are set
---`rootUri` wins.
---
---@deprecated in favour of workspaceFolders.
---@field rootUri lsp.DocumentUri|lsp.null
+---
---The capabilities provided by the client (editor or tool)
---@field capabilities lsp.ClientCapabilities
+---
---User provided initialization options.
---@field initializationOptions? lsp.LSPAny
+---
---The initial trace setting. If omitted trace is disabled ('off').
---@field trace? lsp.TraceValues
---@class lsp.WorkspaceFoldersInitializeParams
+---
---The workspace folders configured in the client when the server starts.
---
---This property is only available if the client supports workspace folders.
@@ -1996,6 +2396,7 @@ error('Cannot require a meta file')
---Defines the capabilities provided by a language
---server.
---@class lsp.ServerCapabilities
+---
---The position encoding the server picked from the encodings offered
---by the client via the client capability `general.positionEncodings`.
---
@@ -2006,125 +2407,167 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@field positionEncoding? lsp.PositionEncodingKind
+---
---Defines how text documents are synced. Is either a detailed structure
---defining each notification or for backwards compatibility the
---TextDocumentSyncKind number.
---@field textDocumentSync? lsp.TextDocumentSyncOptions|lsp.TextDocumentSyncKind
+---
---Defines how notebook documents are synced.
---
---@since 3.17.0
---@field notebookDocumentSync? lsp.NotebookDocumentSyncOptions|lsp.NotebookDocumentSyncRegistrationOptions
+---
---The server provides completion support.
---@field completionProvider? lsp.CompletionOptions
+---
---The server provides hover support.
---@field hoverProvider? boolean|lsp.HoverOptions
+---
---The server provides signature help support.
---@field signatureHelpProvider? lsp.SignatureHelpOptions
+---
---The server provides Goto Declaration support.
---@field declarationProvider? boolean|lsp.DeclarationOptions|lsp.DeclarationRegistrationOptions
+---
---The server provides goto definition support.
---@field definitionProvider? boolean|lsp.DefinitionOptions
+---
---The server provides Goto Type Definition support.
---@field typeDefinitionProvider? boolean|lsp.TypeDefinitionOptions|lsp.TypeDefinitionRegistrationOptions
+---
---The server provides Goto Implementation support.
---@field implementationProvider? boolean|lsp.ImplementationOptions|lsp.ImplementationRegistrationOptions
+---
---The server provides find references support.
---@field referencesProvider? boolean|lsp.ReferenceOptions
+---
---The server provides document highlight support.
---@field documentHighlightProvider? boolean|lsp.DocumentHighlightOptions
+---
---The server provides document symbol support.
---@field documentSymbolProvider? boolean|lsp.DocumentSymbolOptions
+---
---The server provides code actions. CodeActionOptions may only be
---specified if the client states that it supports
---`codeActionLiteralSupport` in its initial `initialize` request.
---@field codeActionProvider? boolean|lsp.CodeActionOptions
+---
---The server provides code lens.
---@field codeLensProvider? lsp.CodeLensOptions
+---
---The server provides document link support.
---@field documentLinkProvider? lsp.DocumentLinkOptions
+---
---The server provides color provider support.
---@field colorProvider? boolean|lsp.DocumentColorOptions|lsp.DocumentColorRegistrationOptions
+---
---The server provides workspace symbol support.
---@field workspaceSymbolProvider? boolean|lsp.WorkspaceSymbolOptions
+---
---The server provides document formatting.
---@field documentFormattingProvider? boolean|lsp.DocumentFormattingOptions
+---
---The server provides document range formatting.
---@field documentRangeFormattingProvider? boolean|lsp.DocumentRangeFormattingOptions
+---
---The server provides document formatting on typing.
---@field documentOnTypeFormattingProvider? lsp.DocumentOnTypeFormattingOptions
+---
---The server provides rename support. RenameOptions may only be
---specified if the client states that it supports
---`prepareSupport` in its initial `initialize` request.
---@field renameProvider? boolean|lsp.RenameOptions
+---
---The server provides folding provider support.
---@field foldingRangeProvider? boolean|lsp.FoldingRangeOptions|lsp.FoldingRangeRegistrationOptions
+---
---The server provides selection range support.
---@field selectionRangeProvider? boolean|lsp.SelectionRangeOptions|lsp.SelectionRangeRegistrationOptions
+---
---The server provides execute command support.
---@field executeCommandProvider? lsp.ExecuteCommandOptions
+---
---The server provides call hierarchy support.
---
---@since 3.16.0
---@field callHierarchyProvider? boolean|lsp.CallHierarchyOptions|lsp.CallHierarchyRegistrationOptions
+---
---The server provides linked editing range support.
---
---@since 3.16.0
---@field linkedEditingRangeProvider? boolean|lsp.LinkedEditingRangeOptions|lsp.LinkedEditingRangeRegistrationOptions
+---
---The server provides semantic tokens support.
---
---@since 3.16.0
---@field semanticTokensProvider? lsp.SemanticTokensOptions|lsp.SemanticTokensRegistrationOptions
+---
---The server provides moniker support.
---
---@since 3.16.0
---@field monikerProvider? boolean|lsp.MonikerOptions|lsp.MonikerRegistrationOptions
+---
---The server provides type hierarchy support.
---
---@since 3.17.0
---@field typeHierarchyProvider? boolean|lsp.TypeHierarchyOptions|lsp.TypeHierarchyRegistrationOptions
+---
---The server provides inline values.
---
---@since 3.17.0
---@field inlineValueProvider? boolean|lsp.InlineValueOptions|lsp.InlineValueRegistrationOptions
+---
---The server provides inlay hints.
---
---@since 3.17.0
---@field inlayHintProvider? boolean|lsp.InlayHintOptions|lsp.InlayHintRegistrationOptions
+---
---The server has support for pull model diagnostics.
---
---@since 3.17.0
---@field diagnosticProvider? lsp.DiagnosticOptions|lsp.DiagnosticRegistrationOptions
+---
---Inline completion options used during static registration.
---
---@since 3.18.0
+---@proposed
---@field inlineCompletionProvider? boolean|lsp.InlineCompletionOptions
+---
---Workspace specific server capabilities.
----@field workspace? anonym12
+---@field workspace? lsp._anonym12.workspace
+---
---Experimental server capabilities.
---@field experimental? lsp.LSPAny
---A text document identifier to denote a specific version of a text document.
---@class lsp.VersionedTextDocumentIdentifier: lsp.TextDocumentIdentifier
+---
---The version number of this document.
---@field version integer
---Save options.
---@class lsp.SaveOptions
+---
---The client is supposed to include the content on save.
---@field includeText? boolean
---An event describing a file change.
---@class lsp.FileEvent
+---
---The file's uri.
---@field uri lsp.DocumentUri
+---
---The change type.
---@field type lsp.FileChangeType
---@class lsp.FileSystemWatcher
+---
---The glob pattern to watch. See {@link GlobPattern glob pattern} for more detail.
---
---@since 3.17.0 support for relative patterns.
---@field globPattern lsp.GlobPattern
+---
---The kind of events of interest. If omitted it defaults
---to WatchKind.Create | WatchKind.Change | WatchKind.Delete
---which is 7.
@@ -2133,31 +2576,40 @@ error('Cannot require a meta file')
---Represents a diagnostic, such as a compiler error or warning. Diagnostic objects
---are only valid in the scope of a resource.
---@class lsp.Diagnostic
+---
---The range at which the message applies
---@field range lsp.Range
+---
---The diagnostic's severity. Can be omitted. If omitted it is up to the
---client to interpret diagnostics as error, warning, info or hint.
---@field severity? lsp.DiagnosticSeverity
+---
---The diagnostic's code, which usually appear in the user interface.
---@field code? integer|string
+---
---An optional property to describe the error code.
---Requires the code field (above) to be present/not null.
---
---@since 3.16.0
---@field codeDescription? lsp.CodeDescription
+---
---A human-readable string describing the source of this
---diagnostic, e.g. 'typescript' or 'super lint'. It usually
---appears in the user interface.
---@field source? string
+---
---The diagnostic's message. It usually appears in the user interface
---@field message string
+---
---Additional metadata about the diagnostic.
---
---@since 3.15.0
---@field tags? lsp.DiagnosticTag[]
+---
---An array of related diagnostic information, e.g. when symbol-names within
---a scope collide all definitions can be marked via this property.
---@field relatedInformation? lsp.DiagnosticRelatedInformation[]
+---
---A data entry field that is preserved between a `textDocument/publishDiagnostics`
---notification and `textDocument/codeAction` request.
---
@@ -2166,8 +2618,10 @@ error('Cannot require a meta file')
---Contains additional information about the context in which a completion request is triggered.
---@class lsp.CompletionContext
+---
---How the completion was triggered.
---@field triggerKind lsp.CompletionTriggerKind
+---
---The trigger character (a single character) that has trigger code complete.
---Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
---@field triggerCharacter? string
@@ -2176,9 +2630,11 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.CompletionItemLabelDetails
+---
---An optional string which is rendered less prominently directly after {@link CompletionItem.label label},
---without any spacing. Should be used for function signatures and type annotations.
---@field detail? string
+---
---An optional string which is rendered less prominently after {@link CompletionItem.detail}. Should be used
---for fully qualified names and file paths.
---@field description? string
@@ -2187,15 +2643,19 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.InsertReplaceEdit
+---
---The string to be inserted.
---@field newText string
+---
---The range if the insert is requested
---@field insert lsp.Range
+---
---The range if the replace is requested.
---@field replace lsp.Range
---Completion options.
----@class lsp.CompletionOptions
+---@class lsp.CompletionOptions: lsp.WorkDoneProgressOptions
+---
---Most tools trigger completion request automatically without explicitly requesting
---it using a keyboard shortcut (e.g. Ctrl+Space). Typically they do so when the user
---starts to type an identifier. For example if the user types `c` in a JavaScript file
@@ -2205,6 +2665,7 @@ error('Cannot require a meta file')
---If code complete should automatically be trigger on characters not being valid inside
---an identifier (for example `.` in JavaScript) list them in `triggerCharacters`.
---@field triggerCharacters? string[]
+---
---The list of all possible characters that commit a completion. This field can be used
---if clients don't support individual commit characters per completion item. See
---`ClientCapabilities.textDocument.completion.completionItem.commitCharactersSupport`
@@ -2214,33 +2675,39 @@ error('Cannot require a meta file')
---
---@since 3.2.0
---@field allCommitCharacters? string[]
+---
---The server provides support to resolve additional
---information for a completion item.
---@field resolveProvider? boolean
+---
---The server supports the following `CompletionItem` specific
---capabilities.
---
---@since 3.17.0
----@field completionItem? anonym13
+---@field completionItem? lsp._anonym13.completionItem
---Hover options.
----@class lsp.HoverOptions
+---@class lsp.HoverOptions: lsp.WorkDoneProgressOptions
---Additional information about the context in which a signature help request was triggered.
---
---@since 3.15.0
---@class lsp.SignatureHelpContext
+---
---Action that caused signature help to be triggered.
---@field triggerKind lsp.SignatureHelpTriggerKind
+---
---Character that caused signature help to be triggered.
---
---This is undefined when `triggerKind !== SignatureHelpTriggerKind.TriggerCharacter`
---@field triggerCharacter? string
+---
---`true` if signature help was already showing when it was triggered.
---
---Retriggers occurs when the signature help is already active and can be caused by actions such as
---typing a trigger character, a cursor move, or document content changes.
---@field isRetrigger boolean
+---
---The currently active `SignatureHelp`.
---
---The `activeSignatureHelp` has its `SignatureHelp.activeSignature` field updated based on
@@ -2251,25 +2718,37 @@ error('Cannot require a meta file')
---can have a label, like a function-name, a doc-comment, and
---a set of parameters.
---@class lsp.SignatureInformation
+---
---The label of this signature. Will be shown in
---the UI.
---@field label string
+---
---The human-readable doc-comment of this signature. Will be shown
---in the UI but can be omitted.
---@field documentation? string|lsp.MarkupContent
+---
---The parameters of this signature.
---@field parameters? lsp.ParameterInformation[]
+---
---The index of the active parameter.
---
----If provided, this is used in place of `SignatureHelp.activeParameter`.
+---If `null`, no parameter of the signature is active (for example a named
+---argument that does not match any declared parameters). This is only valid
+---since 3.18.0 and if the client specifies the client capability
+---`textDocument.signatureHelp.noActiveParameterSupport === true`
+---
+---If provided (or `null`), this is used in place of
+---`SignatureHelp.activeParameter`.
---
---@since 3.16.0
----@field activeParameter? uinteger
+---@field activeParameter? uinteger|lsp.null
---Server Capabilities for a {@link SignatureHelpRequest}.
----@class lsp.SignatureHelpOptions
+---@class lsp.SignatureHelpOptions: lsp.WorkDoneProgressOptions
+---
---List of characters that trigger signature help automatically.
---@field triggerCharacters? string[]
+---
---List of characters that re-trigger signature help.
---
---These trigger characters are only active when signature help is already showing. All trigger characters
@@ -2279,30 +2758,35 @@ error('Cannot require a meta file')
---@field retriggerCharacters? string[]
---Server Capabilities for a {@link DefinitionRequest}.
----@class lsp.DefinitionOptions
+---@class lsp.DefinitionOptions: lsp.WorkDoneProgressOptions
---Value-object that contains additional information when
---requesting references.
---@class lsp.ReferenceContext
+---
---Include the declaration of the current symbol.
---@field includeDeclaration boolean
---Reference options.
----@class lsp.ReferenceOptions
+---@class lsp.ReferenceOptions: lsp.WorkDoneProgressOptions
---Provider options for a {@link DocumentHighlightRequest}.
----@class lsp.DocumentHighlightOptions
+---@class lsp.DocumentHighlightOptions: lsp.WorkDoneProgressOptions
---A base for all symbol information.
---@class lsp.BaseSymbolInformation
+---
---The name of this symbol.
---@field name string
+---
---The kind of this symbol.
---@field kind lsp.SymbolKind
+---
---Tags for this symbol.
---
---@since 3.16.0
---@field tags? lsp.SymbolTag[]
+---
---The name of the symbol containing this symbol. This information is for
---user interface purposes (e.g. to render a qualifier in the user interface
---if necessary). It can't be used to re-infer a hierarchy for the document
@@ -2310,7 +2794,8 @@ error('Cannot require a meta file')
---@field containerName? string
---Provider options for a {@link DocumentSymbolRequest}.
----@class lsp.DocumentSymbolOptions
+---@class lsp.DocumentSymbolOptions: lsp.WorkDoneProgressOptions
+---
---A human-readable string that is shown when multiple outlines trees
---are shown for the same document.
---
@@ -2320,29 +2805,34 @@ error('Cannot require a meta file')
---Contains additional diagnostic information about the context in which
---a {@link CodeActionProvider.provideCodeActions code action} is run.
---@class lsp.CodeActionContext
+---
---An array of diagnostics known on the client side overlapping the range provided to the
---`textDocument/codeAction` request. They are provided so that the server knows which
---errors are currently presented to the user for the given range. There is no guarantee
---that these accurately reflect the error state of the resource. The primary parameter
---to compute code actions is the provided range.
---@field diagnostics lsp.Diagnostic[]
+---
---Requested kind of actions to return.
---
---Actions not of this kind are filtered out by the client before being shown. So servers
---can omit computing them.
---@field only? lsp.CodeActionKind[]
+---
---The reason why code actions were requested.
---
---@since 3.17.0
---@field triggerKind? lsp.CodeActionTriggerKind
---Provider options for a {@link CodeActionRequest}.
----@class lsp.CodeActionOptions
+---@class lsp.CodeActionOptions: lsp.WorkDoneProgressOptions
+---
---CodeActionKinds that this server may return.
---
---The list of kinds may be generic, such as `CodeActionKind.Refactor`, or the server
---may list out every specific kind they provide.
---@field codeActionKinds? lsp.CodeActionKind[]
+---
---The server provides support to resolve additional
---information for a code action.
---
@@ -2350,7 +2840,8 @@ error('Cannot require a meta file')
---@field resolveProvider? boolean
---Server capabilities for a {@link WorkspaceSymbolRequest}.
----@class lsp.WorkspaceSymbolOptions
+---@class lsp.WorkspaceSymbolOptions: lsp.WorkDoneProgressOptions
+---
---The server provides support to resolve additional
---information for a workspace symbol.
---
@@ -2358,39 +2849,47 @@ error('Cannot require a meta file')
---@field resolveProvider? boolean
---Code Lens provider options of a {@link CodeLensRequest}.
----@class lsp.CodeLensOptions
+---@class lsp.CodeLensOptions: lsp.WorkDoneProgressOptions
+---
---Code lens has a resolve provider as well.
---@field resolveProvider? boolean
---Provider options for a {@link DocumentLinkRequest}.
----@class lsp.DocumentLinkOptions
+---@class lsp.DocumentLinkOptions: lsp.WorkDoneProgressOptions
+---
---Document links have a resolve provider as well.
---@field resolveProvider? boolean
---Value-object describing what options formatting should use.
---@class lsp.FormattingOptions
+---
---Size of a tab in spaces.
---@field tabSize uinteger
+---
---Prefer spaces over tabs.
---@field insertSpaces boolean
+---
---Trim trailing whitespace on a line.
---
---@since 3.15.0
---@field trimTrailingWhitespace? boolean
+---
---Insert a newline character at the end of the file if one does not exist.
---
---@since 3.15.0
---@field insertFinalNewline? boolean
+---
---Trim all newlines after the final newline at the end of the file.
---
---@since 3.15.0
---@field trimFinalNewlines? boolean
---Provider options for a {@link DocumentFormattingRequest}.
----@class lsp.DocumentFormattingOptions
+---@class lsp.DocumentFormattingOptions: lsp.WorkDoneProgressOptions
---Provider options for a {@link DocumentRangeFormattingRequest}.
----@class lsp.DocumentRangeFormattingOptions
+---@class lsp.DocumentRangeFormattingOptions: lsp.WorkDoneProgressOptions
+---
---Whether the server supports formatting multiple ranges at once.
---
---@since 3.18.0
@@ -2399,32 +2898,39 @@ error('Cannot require a meta file')
---Provider options for a {@link DocumentOnTypeFormattingRequest}.
---@class lsp.DocumentOnTypeFormattingOptions
+---
---A character on which formatting should be triggered, like `{`.
---@field firstTriggerCharacter string
+---
---More trigger characters.
---@field moreTriggerCharacter? string[]
---Provider options for a {@link RenameRequest}.
----@class lsp.RenameOptions
+---@class lsp.RenameOptions: lsp.WorkDoneProgressOptions
+---
---Renames should be checked and tested before being executed.
---
---@since version 3.12.0
---@field prepareProvider? boolean
---The server capabilities of a {@link ExecuteCommandRequest}.
----@class lsp.ExecuteCommandOptions
+---@class lsp.ExecuteCommandOptions: lsp.WorkDoneProgressOptions
+---
---The commands to be executed on the server
---@field commands string[]
---@since 3.16.0
---@class lsp.SemanticTokensLegend
+---
---The token types a server uses.
---@field tokenTypes string[]
+---
---The token modifiers a server uses.
---@field tokenModifiers string[]
---A text document identifier to optionally denote a specific version of a text document.
---@class lsp.OptionalVersionedTextDocumentIdentifier: lsp.TextDocumentIdentifier
+---
---The version number of this document. If a versioned text document identifier
---is sent from the server to the client and the file is not open in the editor
---(the server has not received an open notification before) the server can send
@@ -2436,13 +2942,16 @@ error('Cannot require a meta file')
---
---@since 3.16.0.
---@class lsp.AnnotatedTextEdit: lsp.TextEdit
+---
---The actual identifier of the change annotation
---@field annotationId lsp.ChangeAnnotationIdentifier
---A generic resource operation.
---@class lsp.ResourceOperation
+---
---The resource operation kind.
---@field kind string
+---
---An optional annotation identifier describing the operation.
---
---@since 3.16.0
@@ -2450,22 +2959,28 @@ error('Cannot require a meta file')
---Options to create a file.
---@class lsp.CreateFileOptions
+---
---Overwrite existing file. Overwrite wins over `ignoreIfExists`
---@field overwrite? boolean
+---
---Ignore if exists.
---@field ignoreIfExists? boolean
---Rename file options
---@class lsp.RenameFileOptions
+---
---Overwrite target if existing. Overwrite wins over `ignoreIfExists`
---@field overwrite? boolean
+---
---Ignores if target exists.
---@field ignoreIfExists? boolean
---Delete file options
---@class lsp.DeleteFileOptions
+---
---Delete the content recursively if a folder is denoted.
---@field recursive? boolean
+---
---Ignore the operation if the file doesn't exist.
---@field ignoreIfNotExists? boolean
@@ -2474,18 +2989,21 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.FileOperationPattern
+---
---The glob pattern to match. Glob patterns can have the following syntax:
---- `*` to match one or more characters in a path segment
---- `?` to match on one character in a path segment
---- `**` to match any number of path segments, including none
----- `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)
+---- `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files)
---- `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
---- `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
---@field glob string
+---
---Whether to match files or folders with this pattern.
---
---Matches both if undefined.
---@field matches? lsp.FileOperationPatternKind
+---
---Additional options used during matching.
---@field options? lsp.FileOperationPatternOptions
@@ -2493,8 +3011,10 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.WorkspaceFullDocumentDiagnosticReport: lsp.FullDocumentDiagnosticReport
+---
---The URI for which diagnostic information is reported.
---@field uri lsp.DocumentUri
+---
---The version number for which the diagnostics are reported.
---If the document is not marked as open `null` can be provided.
---@field version integer|lsp.null
@@ -2503,8 +3023,10 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.WorkspaceUnchangedDocumentDiagnosticReport: lsp.UnchangedDocumentDiagnosticReport
+---
---The URI for which diagnostic information is reported.
---@field uri lsp.DocumentUri
+---
---The version number for which the diagnostics are reported.
---If the document is not marked as open `null` can be provided.
---@field version integer|lsp.null
@@ -2517,15 +3039,19 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.NotebookCell
+---
---The cell's kind
---@field kind lsp.NotebookCellKind
+---
---The URI of the cell's text document
---content.
---@field document lsp.DocumentUri
+---
---Additional metadata stored with the cell.
---
---Note: should always be an object literal (e.g. LSPObject)
---@field metadata? lsp.LSPObject
+---
---Additional execution summary information
---if supported by the client.
---@field executionSummary? lsp.ExecutionSummary
@@ -2535,54 +3061,71 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.NotebookCellArrayChange
+---
---The start oftest of the cell that changed.
---@field start uinteger
+---
---The deleted cells
---@field deleteCount uinteger
+---
---The new cells, if any
---@field cells? lsp.NotebookCell[]
---Describes the currently selected completion item.
---
---@since 3.18.0
+---@proposed
---@class lsp.SelectedCompletionInfo
+---
---The range that will be replaced if this completion item is accepted.
---@field range lsp.Range
+---
---The text the range will be replaced with if this completion is accepted.
---@field text string
---Defines the capabilities provided by the client.
---@class lsp.ClientCapabilities
+---
---Workspace specific client capabilities.
---@field workspace? lsp.WorkspaceClientCapabilities
+---
---Text document specific client capabilities.
---@field textDocument? lsp.TextDocumentClientCapabilities
+---
---Capabilities specific to the notebook document support.
---
---@since 3.17.0
---@field notebookDocument? lsp.NotebookDocumentClientCapabilities
+---
---Window specific client capabilities.
---@field window? lsp.WindowClientCapabilities
+---
---General client capabilities.
---
---@since 3.16.0
---@field general? lsp.GeneralClientCapabilities
+---
---Experimental client capabilities.
---@field experimental? lsp.LSPAny
---@class lsp.TextDocumentSyncOptions
+---
---Open and close notifications are sent to the server. If omitted open close notification should not
---be sent.
---@field openClose? boolean
+---
---Change notifications are sent to the server. See TextDocumentSyncKind.None, TextDocumentSyncKind.Full
---and TextDocumentSyncKind.Incremental. If omitted it defaults to TextDocumentSyncKind.None.
---@field change? lsp.TextDocumentSyncKind
+---
---If present will save notifications are sent to the server. If omitted the notification should not be
---sent.
---@field willSave? boolean
+---
---If present will save wait until requests are sent to the server. If omitted the request should not be
---sent.
---@field willSaveWaitUntil? boolean
+---
---If present save notifications are sent to the server. If omitted the notification should not be
---sent.
---@field save? boolean|lsp.SaveOptions
@@ -2601,8 +3144,10 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.NotebookDocumentSyncOptions
+---
---The notebooks to be synced
----@field notebookSelector anonym15|anonym17[]
+---@field notebookSelector (lsp._anonym14.notebookSelector|lsp._anonym16.notebookSelector)[]
+---
---Whether save notification should be forwarded to
---the server. Will only be honored if mode === `notebook`.
---@field save? boolean
@@ -2613,8 +3158,10 @@ error('Cannot require a meta file')
---@class lsp.NotebookDocumentSyncRegistrationOptions: lsp.NotebookDocumentSyncOptions, lsp.StaticRegistrationOptions
---@class lsp.WorkspaceFoldersServerCapabilities
+---
---The server has support for workspace folders
---@field supported? boolean
+---
---Whether the server wants to receive workspace folder
---change notifications.
---
@@ -2628,16 +3175,22 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.FileOperationOptions
+---
---The server is interested in receiving didCreateFiles notifications.
---@field didCreate? lsp.FileOperationRegistrationOptions
+---
---The server is interested in receiving willCreateFiles requests.
---@field willCreate? lsp.FileOperationRegistrationOptions
+---
---The server is interested in receiving didRenameFiles notifications.
---@field didRename? lsp.FileOperationRegistrationOptions
+---
---The server is interested in receiving willRenameFiles requests.
---@field willRename? lsp.FileOperationRegistrationOptions
+---
---The server is interested in receiving didDeleteFiles file notifications.
---@field didDelete? lsp.FileOperationRegistrationOptions
+---
---The server is interested in receiving willDeleteFiles file requests.
---@field willDelete? lsp.FileOperationRegistrationOptions
@@ -2645,6 +3198,7 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.CodeDescription
+---
---An URI to open with more information about the diagnostic error.
---@field href lsp.URI
@@ -2652,14 +3206,17 @@ error('Cannot require a meta file')
---used to point to code locations that cause or related to a diagnostics, e.g when duplicating
---a symbol in a scope.
---@class lsp.DiagnosticRelatedInformation
+---
---The location of this related diagnostic information.
---@field location lsp.Location
+---
---The message of this related diagnostic information.
---@field message string
---Represents a parameter of a callable-signature. A parameter can
---have a label and a doc-comment.
---@class lsp.ParameterInformation
+---
---The label of this parameter information.
---
---Either a string or an inclusive start and exclusive end offsets within its containing
@@ -2669,6 +3226,7 @@ error('Cannot require a meta file')
---*Note*: a label of type string should be a substring of its containing signature label.
---Its intended use case is to highlight the parameter label part in the `SignatureInformation.label`.
---@field label string|{ [1]: uinteger, [2]: uinteger }
+---
---The human-readable doc-comment of this parameter. Will be shown
---in the UI but can be omitted.
---@field documentation? string|lsp.MarkupContent
@@ -2678,11 +3236,13 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.NotebookCellTextDocumentFilter
+---
---A filter that matches against the notebook
---containing the notebook cell. If a string
---value is provided it matches against the
---notebook type. '*' matches every notebook.
---@field notebook string|lsp.NotebookDocumentFilter
+---
---A language id like `python`.
---
---Will be matched against the language id of the
@@ -2693,178 +3253,235 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.FileOperationPatternOptions
+---
---The pattern should be matched ignoring casing.
---@field ignoreCase? boolean
---@class lsp.ExecutionSummary
+---
---A strict monotonically increasing value
---indicating the execution order of a cell
---inside a notebook.
---@field executionOrder uinteger
+---
---Whether the execution was successful or
---not if known by the client.
---@field success? boolean
---Workspace specific client capabilities.
---@class lsp.WorkspaceClientCapabilities
+---
---The client supports applying batch edits
---to the workspace by supporting the request
---'workspace/applyEdit'
---@field applyEdit? boolean
+---
---Capabilities specific to `WorkspaceEdit`s.
---@field workspaceEdit? lsp.WorkspaceEditClientCapabilities
+---
---Capabilities specific to the `workspace/didChangeConfiguration` notification.
---@field didChangeConfiguration? lsp.DidChangeConfigurationClientCapabilities
+---
---Capabilities specific to the `workspace/didChangeWatchedFiles` notification.
---@field didChangeWatchedFiles? lsp.DidChangeWatchedFilesClientCapabilities
+---
---Capabilities specific to the `workspace/symbol` request.
---@field symbol? lsp.WorkspaceSymbolClientCapabilities
+---
---Capabilities specific to the `workspace/executeCommand` request.
---@field executeCommand? lsp.ExecuteCommandClientCapabilities
+---
---The client has support for workspace folders.
---
---@since 3.6.0
---@field workspaceFolders? boolean
+---
---The client supports `workspace/configuration` requests.
---
---@since 3.6.0
---@field configuration? boolean
+---
---Capabilities specific to the semantic token requests scoped to the
---workspace.
---
---@since 3.16.0.
---@field semanticTokens? lsp.SemanticTokensWorkspaceClientCapabilities
+---
---Capabilities specific to the code lens requests scoped to the
---workspace.
---
---@since 3.16.0.
---@field codeLens? lsp.CodeLensWorkspaceClientCapabilities
+---
---The client has support for file notifications/requests for user operations on files.
---
---Since 3.16.0
---@field fileOperations? lsp.FileOperationClientCapabilities
+---
---Capabilities specific to the inline values requests scoped to the
---workspace.
---
---@since 3.17.0.
---@field inlineValue? lsp.InlineValueWorkspaceClientCapabilities
+---
---Capabilities specific to the inlay hint requests scoped to the
---workspace.
---
---@since 3.17.0.
---@field inlayHint? lsp.InlayHintWorkspaceClientCapabilities
+---
---Capabilities specific to the diagnostic requests scoped to the
---workspace.
---
---@since 3.17.0.
---@field diagnostics? lsp.DiagnosticWorkspaceClientCapabilities
+---
+---Capabilities specific to the folding range requests scoped to the workspace.
+---
+---@since 3.18.0
+---@proposed
+---@field foldingRange? lsp.FoldingRangeWorkspaceClientCapabilities
---Text document specific client capabilities.
---@class lsp.TextDocumentClientCapabilities
+---
---Defines which synchronization capabilities the client supports.
---@field synchronization? lsp.TextDocumentSyncClientCapabilities
+---
---Capabilities specific to the `textDocument/completion` request.
---@field completion? lsp.CompletionClientCapabilities
+---
---Capabilities specific to the `textDocument/hover` request.
---@field hover? lsp.HoverClientCapabilities
+---
---Capabilities specific to the `textDocument/signatureHelp` request.
---@field signatureHelp? lsp.SignatureHelpClientCapabilities
+---
---Capabilities specific to the `textDocument/declaration` request.
---
---@since 3.14.0
---@field declaration? lsp.DeclarationClientCapabilities
+---
---Capabilities specific to the `textDocument/definition` request.
---@field definition? lsp.DefinitionClientCapabilities
+---
---Capabilities specific to the `textDocument/typeDefinition` request.
---
---@since 3.6.0
---@field typeDefinition? lsp.TypeDefinitionClientCapabilities
+---
---Capabilities specific to the `textDocument/implementation` request.
---
---@since 3.6.0
---@field implementation? lsp.ImplementationClientCapabilities
+---
---Capabilities specific to the `textDocument/references` request.
---@field references? lsp.ReferenceClientCapabilities
+---
---Capabilities specific to the `textDocument/documentHighlight` request.
---@field documentHighlight? lsp.DocumentHighlightClientCapabilities
+---
---Capabilities specific to the `textDocument/documentSymbol` request.
---@field documentSymbol? lsp.DocumentSymbolClientCapabilities
+---
---Capabilities specific to the `textDocument/codeAction` request.
---@field codeAction? lsp.CodeActionClientCapabilities
+---
---Capabilities specific to the `textDocument/codeLens` request.
---@field codeLens? lsp.CodeLensClientCapabilities
+---
---Capabilities specific to the `textDocument/documentLink` request.
---@field documentLink? lsp.DocumentLinkClientCapabilities
+---
---Capabilities specific to the `textDocument/documentColor` and the
---`textDocument/colorPresentation` request.
---
---@since 3.6.0
---@field colorProvider? lsp.DocumentColorClientCapabilities
+---
---Capabilities specific to the `textDocument/formatting` request.
---@field formatting? lsp.DocumentFormattingClientCapabilities
+---
---Capabilities specific to the `textDocument/rangeFormatting` request.
---@field rangeFormatting? lsp.DocumentRangeFormattingClientCapabilities
+---
---Capabilities specific to the `textDocument/onTypeFormatting` request.
---@field onTypeFormatting? lsp.DocumentOnTypeFormattingClientCapabilities
+---
---Capabilities specific to the `textDocument/rename` request.
---@field rename? lsp.RenameClientCapabilities
+---
---Capabilities specific to the `textDocument/foldingRange` request.
---
---@since 3.10.0
---@field foldingRange? lsp.FoldingRangeClientCapabilities
+---
---Capabilities specific to the `textDocument/selectionRange` request.
---
---@since 3.15.0
---@field selectionRange? lsp.SelectionRangeClientCapabilities
+---
---Capabilities specific to the `textDocument/publishDiagnostics` notification.
---@field publishDiagnostics? lsp.PublishDiagnosticsClientCapabilities
+---
---Capabilities specific to the various call hierarchy requests.
---
---@since 3.16.0
---@field callHierarchy? lsp.CallHierarchyClientCapabilities
+---
---Capabilities specific to the various semantic token request.
---
---@since 3.16.0
---@field semanticTokens? lsp.SemanticTokensClientCapabilities
+---
---Capabilities specific to the `textDocument/linkedEditingRange` request.
---
---@since 3.16.0
---@field linkedEditingRange? lsp.LinkedEditingRangeClientCapabilities
+---
---Client capabilities specific to the `textDocument/moniker` request.
---
---@since 3.16.0
---@field moniker? lsp.MonikerClientCapabilities
+---
---Capabilities specific to the various type hierarchy requests.
---
---@since 3.17.0
---@field typeHierarchy? lsp.TypeHierarchyClientCapabilities
+---
---Capabilities specific to the `textDocument/inlineValue` request.
---
---@since 3.17.0
---@field inlineValue? lsp.InlineValueClientCapabilities
+---
---Capabilities specific to the `textDocument/inlayHint` request.
---
---@since 3.17.0
---@field inlayHint? lsp.InlayHintClientCapabilities
+---
---Capabilities specific to the diagnostic pull model.
---
---@since 3.17.0
---@field diagnostic? lsp.DiagnosticClientCapabilities
+---
---Client capabilities specific to inline completions.
---
---@since 3.18.0
+---@proposed
---@field inlineCompletion? lsp.InlineCompletionClientCapabilities
---Capabilities specific to the notebook document support.
---
---@since 3.17.0
---@class lsp.NotebookDocumentClientCapabilities
+---
---Capabilities specific to notebook document synchronization
---
---@since 3.17.0
---@field synchronization lsp.NotebookDocumentSyncClientCapabilities
---@class lsp.WindowClientCapabilities
+---
---It indicates whether the client supports server initiated
---progress using the `window/workDoneProgress/create` request.
---
@@ -2875,10 +3492,12 @@ error('Cannot require a meta file')
---
---@since 3.15.0
---@field workDoneProgress? boolean
+---
---Capabilities specific to the showMessage request.
---
---@since 3.16.0
---@field showMessage? lsp.ShowMessageRequestClientCapabilities
+---
---Capabilities specific to the showDocument request.
---
---@since 3.16.0
@@ -2888,21 +3507,25 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.GeneralClientCapabilities
+---
---Client capability that signals how the client
---handles stale requests (e.g. a request
---for which the client will not process the response
---anymore since the information is outdated).
---
---@since 3.17.0
----@field staleRequestSupport? anonym18
+---@field staleRequestSupport? lsp._anonym18.staleRequestSupport
+---
---Client capabilities specific to regular expressions.
---
---@since 3.16.0
---@field regularExpressions? lsp.RegularExpressionsClientCapabilities
+---
---Client capabilities specific to the client's markdown parser.
---
---@since 3.16.0
---@field markdown? lsp.MarkdownClientCapabilities
+---
---The position encodings supported by the client. Client and server
---have to agree on the same position encoding to ensure that offsets
---(e.g. character position in a line) are interpreted the same on both
@@ -2929,25 +3552,31 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.RelativePattern
+---
---A workspace folder or a base URI to which this pattern will be matched
---against relatively.
---@field baseUri lsp.WorkspaceFolder|lsp.URI
+---
---The actual glob pattern;
---@field pattern lsp.Pattern
---@class lsp.WorkspaceEditClientCapabilities
+---
---The client supports versioned document changes in `WorkspaceEdit`s
---@field documentChanges? boolean
+---
---The resource operations the client supports. Clients should at least
---support 'create', 'rename' and 'delete' files and folders.
---
---@since 3.13.0
---@field resourceOperations? lsp.ResourceOperationKind[]
+---
---The failure handling strategy of a client if applying the workspace edit
---fails.
---
---@since 3.13.0
---@field failureHandling? lsp.FailureHandlingKind
+---
---Whether the client normalizes line endings to the client specific
---setting.
---If set to `true` the client will normalize line ending characters
@@ -2956,21 +3585,25 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@field normalizesLineEndings? boolean
+---
---Whether the client in general supports change annotations on text edits,
---create file, rename file and delete file changes.
---
---@since 3.16.0
----@field changeAnnotationSupport? anonym19
+---@field changeAnnotationSupport? lsp._anonym19.changeAnnotationSupport
---@class lsp.DidChangeConfigurationClientCapabilities
+---
---Did change configuration notification supports dynamic registration.
---@field dynamicRegistration? boolean
---@class lsp.DidChangeWatchedFilesClientCapabilities
+---
---Did change watched files notification supports dynamic registration. Please note
---that the current protocol doesn't support static configuration for file changes
---from the server side.
---@field dynamicRegistration? boolean
+---
---Whether the client has support for {@link RelativePattern relative pattern}
---or not.
---
@@ -2979,29 +3612,35 @@ error('Cannot require a meta file')
---Client capabilities for a {@link WorkspaceSymbolRequest}.
---@class lsp.WorkspaceSymbolClientCapabilities
+---
---Symbol request supports dynamic registration.
---@field dynamicRegistration? boolean
+---
---Specific capabilities for the `SymbolKind` in the `workspace/symbol` request.
----@field symbolKind? anonym20
+---@field symbolKind? lsp._anonym20.symbolKind
+---
---The client supports tags on `SymbolInformation`.
---Clients supporting tags have to handle unknown tags gracefully.
---
---@since 3.16.0
----@field tagSupport? anonym21
+---@field tagSupport? lsp._anonym21.tagSupport
+---
---The client support partial workspace symbols. The client will send the
---request `workspaceSymbol/resolve` to the server to resolve additional
---properties.
---
---@since 3.17.0
----@field resolveSupport? anonym22
+---@field resolveSupport? lsp._anonym22.resolveSupport
---The client capabilities of a {@link ExecuteCommandRequest}.
---@class lsp.ExecuteCommandClientCapabilities
+---
---Execute command supports dynamic registration.
---@field dynamicRegistration? boolean
---@since 3.16.0
---@class lsp.SemanticTokensWorkspaceClientCapabilities
+---
---Whether the client implementation supports a refresh request sent from
---the server to the client.
---
@@ -3013,6 +3652,7 @@ error('Cannot require a meta file')
---@since 3.16.0
---@class lsp.CodeLensWorkspaceClientCapabilities
+---
---Whether the client implementation supports a refresh request sent from the
---server to the client.
---
@@ -3029,18 +3669,25 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.FileOperationClientCapabilities
+---
---Whether the client supports dynamic registration for file requests/notifications.
---@field dynamicRegistration? boolean
+---
---The client has support for sending didCreateFiles notifications.
---@field didCreate? boolean
+---
---The client has support for sending willCreateFiles requests.
---@field willCreate? boolean
+---
---The client has support for sending didRenameFiles notifications.
---@field didRename? boolean
+---
---The client has support for sending willRenameFiles requests.
---@field willRename? boolean
+---
---The client has support for sending didDeleteFiles notifications.
---@field didDelete? boolean
+---
---The client has support for sending willDeleteFiles requests.
---@field willDelete? boolean
@@ -3048,6 +3695,7 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.InlineValueWorkspaceClientCapabilities
+---
---Whether the client implementation supports a refresh request sent from the
---server to the client.
---
@@ -3061,6 +3709,7 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.InlayHintWorkspaceClientCapabilities
+---
---Whether the client implementation supports a refresh request sent from
---the server to the client.
---
@@ -3074,6 +3723,7 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.DiagnosticWorkspaceClientCapabilities
+---
---Whether the client implementation supports a refresh request sent from
---the server to the client.
---
@@ -3083,55 +3733,88 @@ error('Cannot require a meta file')
---change that requires such a calculation.
---@field refreshSupport? boolean
+---Client workspace capabilities specific to folding ranges
+---
+---@since 3.18.0
+---@proposed
+---@class lsp.FoldingRangeWorkspaceClientCapabilities
+---
+---Whether the client implementation supports a refresh request sent from the
+---server to the client.
+---
+---Note that this event is global and will force the client to refresh all
+---folding ranges currently shown. It should be used with absolute care and is
+---useful for situation where a server for example detects a project wide
+---change that requires such a calculation.
+---
+---@since 3.18.0
+---@proposed
+---@field refreshSupport? boolean
+
---@class lsp.TextDocumentSyncClientCapabilities
+---
---Whether text document synchronization supports dynamic registration.
---@field dynamicRegistration? boolean
+---
---The client supports sending will save notifications.
---@field willSave? boolean
+---
---The client supports sending a will save request and
---waits for a response providing text edits which will
---be applied to the document before it is saved.
---@field willSaveWaitUntil? boolean
+---
---The client supports did save notifications.
---@field didSave? boolean
---Completion client capabilities
---@class lsp.CompletionClientCapabilities
+---
---Whether completion supports dynamic registration.
---@field dynamicRegistration? boolean
+---
---The client supports the following `CompletionItem` specific
---capabilities.
----@field completionItem? anonym26
----@field completionItemKind? anonym27
+---@field completionItem? lsp._anonym23.completionItem
+---
+---@field completionItemKind? lsp._anonym27.completionItemKind
+---
---Defines how the client handles whitespace and indentation
---when accepting a completion item that uses multi line
---text in either `insertText` or `textEdit`.
---
---@since 3.17.0
---@field insertTextMode? lsp.InsertTextMode
+---
---The client supports to send additional context information for a
---`textDocument/completion` request.
---@field contextSupport? boolean
+---
---The client supports the following `CompletionList` specific
---capabilities.
---
---@since 3.17.0
----@field completionList? anonym28
+---@field completionList? lsp._anonym28.completionList
---@class lsp.HoverClientCapabilities
+---
---Whether hover supports dynamic registration.
---@field dynamicRegistration? boolean
+---
---Client supports the following content formats for the content
---property. The order describes the preferred format of the client.
---@field contentFormat? lsp.MarkupKind[]
---Client Capabilities for a {@link SignatureHelpRequest}.
---@class lsp.SignatureHelpClientCapabilities
+---
---Whether signature help supports dynamic registration.
---@field dynamicRegistration? boolean
+---
---The client supports the following `SignatureInformation`
---specific properties.
----@field signatureInformation? anonym30
+---@field signatureInformation? lsp._anonym29.signatureInformation
+---
---The client supports to send additional context information for a
---`textDocument/signatureHelp` request. A client that opts into
---contextSupport will also support the `retriggerCharacters` on
@@ -3142,17 +3825,21 @@ error('Cannot require a meta file')
---@since 3.14.0
---@class lsp.DeclarationClientCapabilities
+---
---Whether declaration supports dynamic registration. If this is set to `true`
---the client supports the new `DeclarationRegistrationOptions` return value
---for the corresponding server capability as well.
---@field dynamicRegistration? boolean
+---
---The client supports additional metadata in the form of declaration links.
---@field linkSupport? boolean
---Client Capabilities for a {@link DefinitionRequest}.
---@class lsp.DefinitionClientCapabilities
+---
---Whether definition supports dynamic registration.
---@field dynamicRegistration? boolean
+---
---The client supports additional metadata in the form of definition links.
---
---@since 3.14.0
@@ -3160,10 +3847,12 @@ error('Cannot require a meta file')
---Since 3.6.0
---@class lsp.TypeDefinitionClientCapabilities
+---
---Whether implementation supports dynamic registration. If this is set to `true`
---the client supports the new `TypeDefinitionRegistrationOptions` return value
---for the corresponding server capability as well.
---@field dynamicRegistration? boolean
+---
---The client supports additional metadata in the form of definition links.
---
---Since 3.14.0
@@ -3171,10 +3860,12 @@ error('Cannot require a meta file')
---@since 3.6.0
---@class lsp.ImplementationClientCapabilities
+---
---Whether implementation supports dynamic registration. If this is set to `true`
---the client supports the new `ImplementationRegistrationOptions` return value
---for the corresponding server capability as well.
---@field dynamicRegistration? boolean
+---
---The client supports additional metadata in the form of definition links.
---
---@since 3.14.0
@@ -3182,29 +3873,36 @@ error('Cannot require a meta file')
---Client Capabilities for a {@link ReferencesRequest}.
---@class lsp.ReferenceClientCapabilities
+---
---Whether references supports dynamic registration.
---@field dynamicRegistration? boolean
---Client Capabilities for a {@link DocumentHighlightRequest}.
---@class lsp.DocumentHighlightClientCapabilities
+---
---Whether document highlight supports dynamic registration.
---@field dynamicRegistration? boolean
---Client Capabilities for a {@link DocumentSymbolRequest}.
---@class lsp.DocumentSymbolClientCapabilities
+---
---Whether document symbol supports dynamic registration.
---@field dynamicRegistration? boolean
+---
---Specific capabilities for the `SymbolKind` in the
---`textDocument/documentSymbol` request.
----@field symbolKind? anonym31
+---@field symbolKind? lsp._anonym31.symbolKind
+---
---The client supports hierarchical document symbols.
---@field hierarchicalDocumentSymbolSupport? boolean
+---
---The client supports tags on `SymbolInformation`. Tags are supported on
---`DocumentSymbol` if `hierarchicalDocumentSymbolSupport` is set to true.
---Clients supporting tags have to handle unknown tags gracefully.
---
---@since 3.16.0
----@field tagSupport? anonym32
+---@field tagSupport? lsp._anonym32.tagSupport
+---
---The client supports an additional label presented in the UI when
---registering a document symbol provider.
---
@@ -3213,33 +3911,40 @@ error('Cannot require a meta file')
---The Client Capabilities of a {@link CodeActionRequest}.
---@class lsp.CodeActionClientCapabilities
+---
---Whether code action supports dynamic registration.
---@field dynamicRegistration? boolean
+---
---The client support code action literals of type `CodeAction` as a valid
---response of the `textDocument/codeAction` request. If the property is not
---set the request can only return `Command` literals.
---
---@since 3.8.0
----@field codeActionLiteralSupport? anonym34
+---@field codeActionLiteralSupport? lsp._anonym33.codeActionLiteralSupport
+---
---Whether code action supports the `isPreferred` property.
---
---@since 3.15.0
---@field isPreferredSupport? boolean
+---
---Whether code action supports the `disabled` property.
---
---@since 3.16.0
---@field disabledSupport? boolean
+---
---Whether code action supports the `data` property which is
---preserved between a `textDocument/codeAction` and a
---`codeAction/resolve` request.
---
---@since 3.16.0
---@field dataSupport? boolean
+---
---Whether the client supports resolving additional code action
---properties via a separate `codeAction/resolve` request.
---
---@since 3.16.0
----@field resolveSupport? anonym35
+---@field resolveSupport? lsp._anonym35.resolveSupport
+---
---Whether the client honors the change annotations in
---text edits and resource operations returned via the
---`CodeAction#edit` property by for example presenting
@@ -3251,19 +3956,23 @@ error('Cannot require a meta file')
---The client capabilities of a {@link CodeLensRequest}.
---@class lsp.CodeLensClientCapabilities
+---
---Whether code lens supports dynamic registration.
---@field dynamicRegistration? boolean
---The client capabilities of a {@link DocumentLinkRequest}.
---@class lsp.DocumentLinkClientCapabilities
+---
---Whether document link supports dynamic registration.
---@field dynamicRegistration? boolean
+---
---Whether the client supports the `tooltip` property on `DocumentLink`.
---
---@since 3.15.0
---@field tooltipSupport? boolean
---@class lsp.DocumentColorClientCapabilities
+---
---Whether implementation supports dynamic registration. If this is set to `true`
---the client supports the new `DocumentColorRegistrationOptions` return value
---for the corresponding server capability as well.
@@ -3271,13 +3980,16 @@ error('Cannot require a meta file')
---Client capabilities of a {@link DocumentFormattingRequest}.
---@class lsp.DocumentFormattingClientCapabilities
+---
---Whether formatting supports dynamic registration.
---@field dynamicRegistration? boolean
---Client capabilities of a {@link DocumentRangeFormattingRequest}.
---@class lsp.DocumentRangeFormattingClientCapabilities
+---
---Whether range formatting supports dynamic registration.
---@field dynamicRegistration? boolean
+---
---Whether the client supports formatting multiple ranges at once.
---
---@since 3.18.0
@@ -3286,17 +3998,21 @@ error('Cannot require a meta file')
---Client capabilities of a {@link DocumentOnTypeFormattingRequest}.
---@class lsp.DocumentOnTypeFormattingClientCapabilities
+---
---Whether on type formatting supports dynamic registration.
---@field dynamicRegistration? boolean
---@class lsp.RenameClientCapabilities
+---
---Whether rename supports dynamic registration.
---@field dynamicRegistration? boolean
+---
---Client supports testing for validity of rename operations
---before execution.
---
---@since 3.12.0
---@field prepareSupport? boolean
+---
---Client supports the default behavior result.
---
---The value indicates the default behavior used by the
@@ -3304,6 +4020,7 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@field prepareSupportDefaultBehavior? lsp.PrepareSupportDefaultBehavior
+---
---Whether the client honors the change annotations in
---text edits and resource operations returned via the
---rename request's workspace edit by for example presenting
@@ -3314,29 +4031,35 @@ error('Cannot require a meta file')
---@field honorsChangeAnnotations? boolean
---@class lsp.FoldingRangeClientCapabilities
+---
---Whether implementation supports dynamic registration for folding range
---providers. If this is set to `true` the client supports the new
---`FoldingRangeRegistrationOptions` return value for the corresponding
---server capability as well.
---@field dynamicRegistration? boolean
+---
---The maximum number of folding ranges that the client prefers to receive
---per document. The value serves as a hint, servers are free to follow the
---limit.
---@field rangeLimit? uinteger
+---
---If set, the client signals that it only supports folding complete lines.
---If set, client will ignore specified `startCharacter` and `endCharacter`
---properties in a FoldingRange.
---@field lineFoldingOnly? boolean
+---
---Specific options for the folding range kind.
---
---@since 3.17.0
----@field foldingRangeKind? anonym36
+---@field foldingRangeKind? lsp._anonym36.foldingRangeKind
+---
---Specific options for the folding range.
---
---@since 3.17.0
----@field foldingRange? anonym37
+---@field foldingRange? lsp._anonym37.foldingRange
---@class lsp.SelectionRangeClientCapabilities
+---
---Whether implementation supports dynamic registration for selection range providers. If this is set to `true`
---the client supports the new `SelectionRangeRegistrationOptions` return value for the corresponding server
---capability as well.
@@ -3344,22 +4067,27 @@ error('Cannot require a meta file')
---The publish diagnostic client capabilities.
---@class lsp.PublishDiagnosticsClientCapabilities
+---
---Whether the clients accepts diagnostics with related information.
---@field relatedInformation? boolean
+---
---Client supports the tag property to provide meta data about a diagnostic.
---Clients supporting tags have to handle unknown tags gracefully.
---
---@since 3.15.0
----@field tagSupport? anonym38
+---@field tagSupport? lsp._anonym38.tagSupport
+---
---Whether the client interprets the version property of the
---`textDocument/publishDiagnostics` notification's parameter.
---
---@since 3.15.0
---@field versionSupport? boolean
+---
---Client supports a codeDescription property
---
---@since 3.16.0
---@field codeDescriptionSupport? boolean
+---
---Whether code action supports the `data` property which is
---preserved between a `textDocument/publishDiagnostics` and
---`textDocument/codeAction` request.
@@ -3369,6 +4097,7 @@ error('Cannot require a meta file')
---@since 3.16.0
---@class lsp.CallHierarchyClientCapabilities
+---
---Whether implementation supports dynamic registration. If this is set to `true`
---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
---return value for the corresponding server capability as well.
@@ -3376,10 +4105,12 @@ error('Cannot require a meta file')
---@since 3.16.0
---@class lsp.SemanticTokensClientCapabilities
+---
---Whether implementation supports dynamic registration. If this is set to `true`
---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
---return value for the corresponding server capability as well.
---@field dynamicRegistration? boolean
+---
---Which requests the client supports and might send to the server
---depending on the server's capability. Please note that clients might not
---show semantic tokens or degrade some of the user experience if a range
@@ -3388,17 +4119,23 @@ error('Cannot require a meta file')
---`request.range` are both set to true but the server only provides a
---range provider the client might not render a minimap correctly or might
---even decide to not show any semantic tokens at all.
----@field requests anonym41
+---@field requests lsp._anonym39.requests
+---
---The token types that the client supports.
---@field tokenTypes string[]
+---
---The token modifiers that the client supports.
---@field tokenModifiers string[]
+---
---The token formats the clients supports.
---@field formats lsp.TokenFormat[]
+---
---Whether the client supports tokens that can overlap each other.
---@field overlappingTokenSupport? boolean
+---
---Whether the client supports tokens that can span multiple lines.
---@field multilineTokenSupport? boolean
+---
---Whether the client allows the server to actively cancel a
---semantic token request, e.g. supports returning
---LSPErrorCodes.ServerCancelled. If a server does the client
@@ -3406,6 +4143,7 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@field serverCancelSupport? boolean
+---
---Whether the client uses semantic tokens to augment existing
---syntax tokens. If set to `true` client side created syntax
---tokens and semantic tokens are both used for colorization. If
@@ -3422,6 +4160,7 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.LinkedEditingRangeClientCapabilities
+---
---Whether implementation supports dynamic registration. If this is set to `true`
---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
---return value for the corresponding server capability as well.
@@ -3431,6 +4170,7 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.MonikerClientCapabilities
+---
---Whether moniker supports dynamic registration. If this is set to `true`
---the client supports the new `MonikerRegistrationOptions` return value
---for the corresponding server capability as well.
@@ -3438,6 +4178,7 @@ error('Cannot require a meta file')
---@since 3.17.0
---@class lsp.TypeHierarchyClientCapabilities
+---
---Whether implementation supports dynamic registration. If this is set to `true`
---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
---return value for the corresponding server capability as well.
@@ -3447,6 +4188,7 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.InlineValueClientCapabilities
+---
---Whether implementation supports dynamic registration for inline value providers.
---@field dynamicRegistration? boolean
@@ -3454,27 +4196,33 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.InlayHintClientCapabilities
+---
---Whether inlay hints support dynamic registration.
---@field dynamicRegistration? boolean
+---
---Indicates which properties a client can resolve lazily on an inlay
---hint.
----@field resolveSupport? anonym42
+---@field resolveSupport? lsp._anonym42.resolveSupport
---Client capabilities specific to diagnostic pull requests.
---
---@since 3.17.0
---@class lsp.DiagnosticClientCapabilities
+---
---Whether implementation supports dynamic registration. If this is set to `true`
---the client supports the new `(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
---return value for the corresponding server capability as well.
---@field dynamicRegistration? boolean
+---
---Whether the clients supports related documents for document diagnostic pulls.
---@field relatedDocumentSupport? boolean
---Client capabilities specific to inline completions.
---
---@since 3.18.0
+---@proposed
---@class lsp.InlineCompletionClientCapabilities
+---
---Whether implementation supports dynamic registration for inline completion providers.
---@field dynamicRegistration? boolean
@@ -3482,23 +4230,27 @@ error('Cannot require a meta file')
---
---@since 3.17.0
---@class lsp.NotebookDocumentSyncClientCapabilities
+---
---Whether implementation supports dynamic registration. If this is
---set to `true` the client supports the new
---`(TextDocumentRegistrationOptions & StaticRegistrationOptions)`
---return value for the corresponding server capability as well.
---@field dynamicRegistration? boolean
+---
---The client supports sending execution summary data per cell.
---@field executionSummarySupport? boolean
---Show message request client capabilities
---@class lsp.ShowMessageRequestClientCapabilities
+---
---Capabilities specific to the `MessageActionItem` type.
----@field messageActionItem? anonym43
+---@field messageActionItem? lsp._anonym43.messageActionItem
---Client capabilities for the showDocument request.
---
---@since 3.16.0
---@class lsp.ShowDocumentClientCapabilities
+---
---The client has support for the showDocument
---request.
---@field support boolean
@@ -3507,8 +4259,10 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.RegularExpressionsClientCapabilities
+---
---The engine's name.
---@field engine string
+---
---The engine's version.
---@field version? string
@@ -3516,10 +4270,13 @@ error('Cannot require a meta file')
---
---@since 3.16.0
---@class lsp.MarkdownClientCapabilities
+---
---The name of the parser.
---@field parser string
+---
---The version of the parser.
---@field version? string
+---
---A list of HTML tags that the client allows / supports in
---Markdown.
---
@@ -3662,18 +4419,13 @@ error('Cannot require a meta file')
---| 1 # Type
---| 2 # Parameter
----Defines whether the insert text in a completion item should be interpreted as
----plain text or a snippet.
----@alias lsp.InsertTextFormat
----| 1 # PlainText
----| 2 # Snippet
-
---The message type
---@alias lsp.MessageType
---| 1 # Error
---| 2 # Warning
---| 3 # Info
---| 4 # Log
+---| 5 # Debug
---Defines how the host (editor) should sync
---document changes to the language server.
@@ -3723,6 +4475,12 @@ error('Cannot require a meta file')
---@alias lsp.CompletionItemTag
---| 1 # Deprecated
+---Defines whether the insert text in a completion item should be interpreted as
+---plain text or a snippet.
+---@alias lsp.InsertTextFormat
+---| 1 # PlainText
+---| 2 # Snippet
+
---How whitespace and indentation is handled during completion
---item insertion.
---
@@ -3766,6 +4524,7 @@ error('Cannot require a meta file')
---Describes how an {@link InlineCompletionItemProvider inline completion provider} was triggered.
---
---@since 3.18.0
+---@proposed
---@alias lsp.InlineCompletionTriggerKind
---| 0 # Invoked
---| 1 # Automatic
@@ -3912,11 +4671,11 @@ error('Cannot require a meta file')
---@since 3.17.0
---@alias lsp.DocumentDiagnosticReport lsp.RelatedFullDocumentDiagnosticReport|lsp.RelatedUnchangedDocumentDiagnosticReport
----@alias lsp.PrepareRenameResult lsp.Range|anonym44|anonym45
+---@alias lsp.PrepareRenameResult lsp.Range|lsp._anonym44.PrepareRenameResult|lsp._anonym45.PrepareRenameResult
---A document selector is the combination of one or many document filters.
---
----@sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`;
+---\@sample `let sel:DocumentSelector = [{ language: 'typescript' }, { language: 'json', pattern: '**∕tsconfig.json' }]`;
---
---The use of a string as a document filter is deprecated @since 3.16.0.
---@alias lsp.DocumentSelector lsp.DocumentFilter[]
@@ -3933,7 +4692,7 @@ error('Cannot require a meta file')
---An event describing a change to a text document. If only a text is provided
---it is considered to be the full content of the document.
----@alias lsp.TextDocumentContentChangeEvent anonym46|anonym47
+---@alias lsp.TextDocumentContentChangeEvent lsp._anonym46.TextDocumentContentChangeEvent|lsp._anonym47.TextDocumentContentChangeEvent
---MarkedString can be used to render human readable text. It is either a markdown string
---or a code-block that provides a language and a code snippet. The language identifier
@@ -3947,7 +4706,7 @@ error('Cannot require a meta file')
---
---Note that markdown strings will be sanitized - that means html will be escaped.
---@deprecated use MarkupContent instead.
----@alias lsp.MarkedString string|anonym48
+---@alias lsp.MarkedString string|lsp._anonym48.MarkedString
---A document filter describes a top level text document or
---a notebook cell document.
@@ -3972,120 +4731,145 @@ error('Cannot require a meta file')
---- `*` to match one or more characters in a path segment
---- `?` to match on one character in a path segment
---- `**` to match any number of path segments, including none
----- `{}` to group sub patterns into an OR expression. (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)
+---- `{}` to group sub patterns into an OR expression. (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files)
---- `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
---- `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
---
----@sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }`
----@sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }`
+---\@sample A language filter that applies to typescript files on disk: `{ language: 'typescript', scheme: 'file' }`
+---\@sample A language filter that applies to all package.json paths: `{ language: 'json', pattern: '**package.json' }`
---
---@since 3.17.0
----@alias lsp.TextDocumentFilter anonym49|anonym50|anonym51
+---@alias lsp.TextDocumentFilter lsp._anonym49.TextDocumentFilter|lsp._anonym50.TextDocumentFilter|lsp._anonym51.TextDocumentFilter
---A notebook document filter denotes a notebook document by
---different properties. The properties will be match
---against the notebook's URI (same as with documents)
---
---@since 3.17.0
----@alias lsp.NotebookDocumentFilter anonym52|anonym53|anonym54
+---@alias lsp.NotebookDocumentFilter lsp._anonym52.NotebookDocumentFilter|lsp._anonym53.NotebookDocumentFilter|lsp._anonym54.NotebookDocumentFilter
---The glob pattern to watch relative to the base path. Glob patterns can have the following syntax:
---- `*` to match one or more characters in a path segment
---- `?` to match on one character in a path segment
---- `**` to match any number of path segments, including none
----- `{}` to group conditions (e.g. `**​/*.{ts,js}` matches all TypeScript and JavaScript files)
+---- `{}` to group conditions (e.g. `**/*.{ts,js}` matches all TypeScript and JavaScript files)
---- `[]` to declare a range of characters to match in a path segment (e.g., `example.[0-9]` to match on `example.0`, `example.1`, …)
---- `[!...]` to negate a range of characters to match in a path segment (e.g., `example.[!0-9]` to match on `example.a`, `example.b`, but not `example.0`)
---
---@since 3.17.0
---@alias lsp.Pattern string
----@class anonym1
+---@class lsp._anonym1.serverInfo
+---
---The name of the server as defined by the server.
---@field name string
+---
---The server's version as defined by the server.
---@field version? string
----@class anonym3
+---@class lsp._anonym3.itemDefaults.editRange
+---
---@field insert lsp.Range
+---
---@field replace lsp.Range
----@class anonym2
+---@class lsp._anonym2.itemDefaults
+---
---A default commit character set.
---
---@since 3.17.0
---@field commitCharacters? string[]
+---
---A default edit range.
---
---@since 3.17.0
----@field editRange? lsp.Range|anonym3
+---@field editRange? lsp.Range|lsp._anonym3.itemDefaults.editRange
+---
---A default insert text format.
---
---@since 3.17.0
---@field insertTextFormat? lsp.InsertTextFormat
+---
---A default insert text mode.
---
---@since 3.17.0
---@field insertTextMode? lsp.InsertTextMode
+---
---A default data value.
---
---@since 3.17.0
---@field data? lsp.LSPAny
----@class anonym4
+---@class lsp._anonym4.disabled
+---
---Human readable description of why the code action is currently disabled.
---
---This is displayed in the code actions UI.
---@field reason string
----@class anonym5
+---@class lsp._anonym5.location
+---
---@field uri lsp.DocumentUri
----@class anonym6
+---@class lsp._anonym6.range
----@class anonym7
+---@class lsp._anonym7.full
+---
---The server supports deltas for full documents.
---@field delta? boolean
----@class anonym9
+---@class lsp._anonym9.cells.structure
+---
---The change to the cell array.
---@field array lsp.NotebookCellArrayChange
+---
---Additional opened cell text documents.
---@field didOpen? lsp.TextDocumentItem[]
+---
---Additional closed cell text documents.
---@field didClose? lsp.TextDocumentIdentifier[]
----@class anonym10
+---@class lsp._anonym10.cells.textContent
+---
---@field document lsp.VersionedTextDocumentIdentifier
+---
---@field changes lsp.TextDocumentContentChangeEvent[]
----@class anonym8
+---@class lsp._anonym8.cells
+---
---Changes to the cell structure to add or
---remove cells.
----@field structure? anonym9
+---@field structure? lsp._anonym9.cells.structure
+---
---Changes to notebook cells properties like its
---kind, execution summary or metadata.
---@field data? lsp.NotebookCell[]
+---
---Changes to the text content of notebook cells.
----@field textContent? anonym10[]
+---@field textContent? lsp._anonym10.cells.textContent[]
----@class anonym11
+---@class lsp._anonym11.clientInfo
+---
---The name of the client as defined by the client.
---@field name string
+---
---The client's version as defined by the client.
---@field version? string
----@class anonym12
+---@class lsp._anonym12.workspace
+---
---The server supports workspace folder.
---
---@since 3.6.0
---@field workspaceFolders? lsp.WorkspaceFoldersServerCapabilities
+---
---The server is interested in notifications/requests for operations on files.
---
---@since 3.16.0
---@field fileOperations? lsp.FileOperationOptions
----@class anonym13
+---@class lsp._anonym13.completionItem
+---
---The server has support for completion item label
---details (see also `CompletionItemLabelDetails`) when
---receiving a completion item in a resolve call.
@@ -4093,43 +4877,53 @@ error('Cannot require a meta file')
---@since 3.17.0
---@field labelDetailsSupport? boolean
----@class anonym15
+---@class lsp._anonym15.notebookSelector.cells
+---
---@field language string
----@class anonym14
+---@class lsp._anonym14.notebookSelector
+---
---The notebook to be synced If a string
---value is provided it matches against the
---notebook type. '*' matches every notebook.
---@field notebook string|lsp.NotebookDocumentFilter
+---
---The cells of the matching notebook to be synced.
----@field cells? anonym15[]
+---@field cells? lsp._anonym15.notebookSelector.cells[]
----@class anonym17
+---@class lsp._anonym17.notebookSelector.cells
+---
---@field language string
----@class anonym16
+---@class lsp._anonym16.notebookSelector
+---
---The notebook to be synced If a string
---value is provided it matches against the
---notebook type. '*' matches every notebook.
---@field notebook? string|lsp.NotebookDocumentFilter
+---
---The cells of the matching notebook to be synced.
----@field cells anonym17[]
+---@field cells lsp._anonym17.notebookSelector.cells[]
----@class anonym18
+---@class lsp._anonym18.staleRequestSupport
+---
---The client will actively cancel the request.
---@field cancel boolean
+---
---The list of requests for which the client
---will retry the request if it receives a
---response with error code `ContentModified`
---@field retryOnContentModified string[]
----@class anonym19
+---@class lsp._anonym19.changeAnnotationSupport
+---
---Whether the client groups edits with equal labels into tree nodes,
---for instance all edits labelled with "Changes in Strings" would
---be a tree node.
---@field groupsOnLabel? boolean
----@class anonym20
+---@class lsp._anonym20.symbolKind
+---
---The symbol kind values the client supports. When this
---property exists the client also guarantees that it will
---handle values outside its set gracefully and falls back
@@ -4140,27 +4934,33 @@ error('Cannot require a meta file')
---the initial version of the protocol.
---@field valueSet? lsp.SymbolKind[]
----@class anonym21
+---@class lsp._anonym21.tagSupport
+---
---The tags supported by the client.
---@field valueSet lsp.SymbolTag[]
----@class anonym22
+---@class lsp._anonym22.resolveSupport
+---
---The properties that a client can resolve lazily. Usually
---`location.range`
---@field properties string[]
----@class anonym24
+---@class lsp._anonym24.completionItem.tagSupport
+---
---The tags supported by the client.
---@field valueSet lsp.CompletionItemTag[]
----@class anonym25
+---@class lsp._anonym25.completionItem.resolveSupport
+---
---The properties that a client can resolve lazily.
---@field properties string[]
----@class anonym26
+---@class lsp._anonym26.completionItem.insertTextModeSupport
+---
---@field valueSet lsp.InsertTextMode[]
----@class anonym23
+---@class lsp._anonym23.completionItem
+---
---Client supports snippets as insert text.
---
---A snippet can define tab stops and placeholders with `$1`, `$2`
@@ -4168,46 +4968,56 @@ error('Cannot require a meta file')
---the end of the snippet. Placeholders with equal identifiers are linked,
---that is typing in one will update others too.
---@field snippetSupport? boolean
+---
---Client supports commit characters on a completion item.
---@field commitCharactersSupport? boolean
+---
---Client supports the following content formats for the documentation
---property. The order describes the preferred format of the client.
---@field documentationFormat? lsp.MarkupKind[]
+---
---Client supports the deprecated property on a completion item.
---@field deprecatedSupport? boolean
+---
---Client supports the preselect property on a completion item.
---@field preselectSupport? boolean
+---
---Client supports the tag property on a completion item. Clients supporting
---tags have to handle unknown tags gracefully. Clients especially need to
---preserve unknown tags when sending a completion item back to the server in
---a resolve call.
---
---@since 3.15.0
----@field tagSupport? anonym24
+---@field tagSupport? lsp._anonym24.completionItem.tagSupport
+---
---Client support insert replace edit to control different behavior if a
---completion item is inserted in the text or should replace text.
---
---@since 3.16.0
---@field insertReplaceSupport? boolean
+---
---Indicates which properties a client can resolve lazily on a completion
---item. Before version 3.16.0 only the predefined properties `documentation`
---and `details` could be resolved lazily.
---
---@since 3.16.0
----@field resolveSupport? anonym25
+---@field resolveSupport? lsp._anonym25.completionItem.resolveSupport
+---
---The client supports the `insertTextMode` property on
---a completion item to override the whitespace handling mode
---as defined by the client (see `insertTextMode`).
---
---@since 3.16.0
----@field insertTextModeSupport? anonym26
+---@field insertTextModeSupport? lsp._anonym26.completionItem.insertTextModeSupport
+---
---The client has support for completion item label
---details (see also `CompletionItemLabelDetails`).
---
---@since 3.17.0
---@field labelDetailsSupport? boolean
----@class anonym27
+---@class lsp._anonym27.completionItemKind
+---
---The completion item kind values the client supports. When this
---property exists the client also guarantees that it will
---handle values outside its set gracefully and falls back
@@ -4218,7 +5028,8 @@ error('Cannot require a meta file')
---the initial version of the protocol.
---@field valueSet? lsp.CompletionItemKind[]
----@class anonym28
+---@class lsp._anonym28.completionList
+---
---The client supports the following itemDefaults on
---a completion list.
---
@@ -4229,26 +5040,38 @@ error('Cannot require a meta file')
---@since 3.17.0
---@field itemDefaults? string[]
----@class anonym30
+---@class lsp._anonym30.signatureInformation.parameterInformation
+---
---The client supports processing label offsets instead of a
---simple label string.
---
---@since 3.14.0
---@field labelOffsetSupport? boolean
----@class anonym29
+---@class lsp._anonym29.signatureInformation
+---
---Client supports the following content formats for the documentation
---property. The order describes the preferred format of the client.
---@field documentationFormat? lsp.MarkupKind[]
+---
---Client capabilities specific to parameter information.
----@field parameterInformation? anonym30
+---@field parameterInformation? lsp._anonym30.signatureInformation.parameterInformation
+---
---The client supports the `activeParameter` property on `SignatureInformation`
---literal.
---
---@since 3.16.0
---@field activeParameterSupport? boolean
+---
+---The client supports the `activeParameter` property on
+---`SignatureInformation` being set to `null` to indicate that no
+---parameter should be active.
+---
+---@since 3.18.0
+---@field noActiveParameterSupport? boolean
----@class anonym31
+---@class lsp._anonym31.symbolKind
+---
---The symbol kind values the client supports. When this
---property exists the client also guarantees that it will
---handle values outside its set gracefully and falls back
@@ -4259,138 +5082,177 @@ error('Cannot require a meta file')
---the initial version of the protocol.
---@field valueSet? lsp.SymbolKind[]
----@class anonym32
+---@class lsp._anonym32.tagSupport
+---
---The tags supported by the client.
---@field valueSet lsp.SymbolTag[]
----@class anonym34
+---@class lsp._anonym34.codeActionLiteralSupport.codeActionKind
+---
---The code action kind values the client supports. When this
---property exists the client also guarantees that it will
---handle values outside its set gracefully and falls back
---to a default value when unknown.
---@field valueSet lsp.CodeActionKind[]
----@class anonym33
+---@class lsp._anonym33.codeActionLiteralSupport
+---
---The code action kind is support with the following value
---set.
----@field codeActionKind anonym34
+---@field codeActionKind lsp._anonym34.codeActionLiteralSupport.codeActionKind
----@class anonym35
+---@class lsp._anonym35.resolveSupport
+---
---The properties that a client can resolve lazily.
---@field properties string[]
----@class anonym36
+---@class lsp._anonym36.foldingRangeKind
+---
---The folding range kind values the client supports. When this
---property exists the client also guarantees that it will
---handle values outside its set gracefully and falls back
---to a default value when unknown.
---@field valueSet? lsp.FoldingRangeKind[]
----@class anonym37
+---@class lsp._anonym37.foldingRange
+---
---If set, the client signals that it supports setting collapsedText on
---folding ranges to display custom labels instead of the default text.
---
---@since 3.17.0
---@field collapsedText? boolean
----@class anonym38
+---@class lsp._anonym38.tagSupport
+---
---The tags supported by the client.
---@field valueSet lsp.DiagnosticTag[]
----@class anonym40
+---@class lsp._anonym40.requests.range
----@class anonym41
+---@class lsp._anonym41.requests.full
+---
---The client will send the `textDocument/semanticTokens/full/delta` request if
---the server provides a corresponding handler.
---@field delta? boolean
----@class anonym39
+---@class lsp._anonym39.requests
+---
---The client will send the `textDocument/semanticTokens/range` request if
---the server provides a corresponding handler.
----@field range? boolean|anonym40
+---@field range? boolean|lsp._anonym40.requests.range
+---
---The client will send the `textDocument/semanticTokens/full` request if
---the server provides a corresponding handler.
----@field full? boolean|anonym41
+---@field full? boolean|lsp._anonym41.requests.full
----@class anonym42
+---@class lsp._anonym42.resolveSupport
+---
---The properties that a client can resolve lazily.
---@field properties string[]
----@class anonym43
+---@class lsp._anonym43.messageActionItem
+---
---Whether the client supports additional attributes which
---are preserved and send back to the server in the
---request's response.
---@field additionalPropertiesSupport? boolean
----@class anonym44
+---@class lsp._anonym44.PrepareRenameResult
+---
---@field range lsp.Range
+---
---@field placeholder string
----@class anonym45
+---@class lsp._anonym45.PrepareRenameResult
+---
---@field defaultBehavior boolean
----@class anonym46
+---@class lsp._anonym46.TextDocumentContentChangeEvent
+---
---The range of the document that changed.
---@field range lsp.Range
+---
---The optional length of the range that got replaced.
---
---@deprecated use range instead.
---@field rangeLength? uinteger
+---
---The new text for the provided range.
---@field text string
----@class anonym47
+---@class lsp._anonym47.TextDocumentContentChangeEvent
+---
---The new text of the whole document.
---@field text string
----@class anonym48
+---@class lsp._anonym48.MarkedString
+---
---@field language string
+---
---@field value string
----@class anonym49
+---@class lsp._anonym49.TextDocumentFilter
+---
---A language id, like `typescript`.
---@field language string
+---
---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.
---@field scheme? string
----A glob pattern, like `*.{ts,js}`.
+---
+---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples.
---@field pattern? string
----@class anonym50
+---@class lsp._anonym50.TextDocumentFilter
+---
---A language id, like `typescript`.
---@field language? string
+---
---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.
---@field scheme string
----A glob pattern, like `*.{ts,js}`.
+---
+---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples.
---@field pattern? string
----@class anonym51
+---@class lsp._anonym51.TextDocumentFilter
+---
---A language id, like `typescript`.
---@field language? string
+---
---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.
---@field scheme? string
----A glob pattern, like `*.{ts,js}`.
+---
+---A glob pattern, like **/*.{ts,js}. See TextDocumentFilter for examples.
---@field pattern string
----@class anonym52
+---@class lsp._anonym52.NotebookDocumentFilter
+---
---The type of the enclosing notebook.
---@field notebookType string
+---
---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.
---@field scheme? string
+---
---A glob pattern.
---@field pattern? string
----@class anonym53
+---@class lsp._anonym53.NotebookDocumentFilter
+---
---The type of the enclosing notebook.
---@field notebookType? string
+---
---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.
---@field scheme string
+---
---A glob pattern.
---@field pattern? string
----@class anonym54
+---@class lsp._anonym54.NotebookDocumentFilter
+---
---The type of the enclosing notebook.
---@field notebookType? string
+---
---A Uri {@link Uri.scheme scheme}, like `file` or `untitled`.
---@field scheme? string
+---
---A glob pattern.
---@field pattern string
diff --git a/runtime/lua/vim/lsp/tagfunc.lua b/runtime/lua/vim/lsp/_tagfunc.lua
index 4ad50e4a58..4ad50e4a58 100644
--- a/runtime/lua/vim/lsp/tagfunc.lua
+++ b/runtime/lua/vim/lsp/_tagfunc.lua
diff --git a/runtime/lua/vim/lsp/_watchfiles.lua b/runtime/lua/vim/lsp/_watchfiles.lua
index 1fd112631d..49328fbe9b 100644
--- a/runtime/lua/vim/lsp/_watchfiles.lua
+++ b/runtime/lua/vim/lsp/_watchfiles.lua
@@ -1,95 +1,20 @@
local bit = require('bit')
-local watch = require('vim._watch')
+local glob = vim.glob
+local watch = vim._watch
local protocol = require('vim.lsp.protocol')
local ms = protocol.Methods
local lpeg = vim.lpeg
local M = {}
---- Parses the raw pattern into an |lpeg| pattern. LPeg patterns natively support the "this" or "that"
---- alternative constructions described in the LSP spec that cannot be expressed in a standard Lua pattern.
----
----@param pattern string The raw glob pattern
----@return vim.lpeg.Pattern? pattern An |lpeg| representation of the pattern, or nil if the pattern is invalid.
-local function parse(pattern)
- local l = lpeg
-
- local P, S, V = lpeg.P, lpeg.S, lpeg.V
- local C, Cc, Ct, Cf = lpeg.C, lpeg.Cc, lpeg.Ct, lpeg.Cf
-
- local pathsep = '/'
-
- local function class(inv, ranges)
- for i, r in ipairs(ranges) do
- ranges[i] = r[1] .. r[2]
- end
- local patt = l.R(unpack(ranges))
- if inv == '!' then
- patt = P(1) - patt
- end
- return patt
- end
-
- local function add(acc, a)
- return acc + a
- end
-
- local function mul(acc, m)
- return acc * m
- end
-
- local function star(stars, after)
- return (-after * (l.P(1) - pathsep)) ^ #stars * after
- end
-
- local function dstar(after)
- return (-after * l.P(1)) ^ 0 * after
- end
-
- local p = P({
- 'Pattern',
- Pattern = V('Elem') ^ -1 * V('End'),
- Elem = Cf(
- (V('DStar') + V('Star') + V('Ques') + V('Class') + V('CondList') + V('Literal'))
- * (V('Elem') + V('End')),
- mul
- ),
- DStar = P('**') * (P(pathsep) * (V('Elem') + V('End')) + V('End')) / dstar,
- Star = C(P('*') ^ 1) * (V('Elem') + V('End')) / star,
- Ques = P('?') * Cc(l.P(1) - pathsep),
- Class = P('[') * C(P('!') ^ -1) * Ct(Ct(C(1) * '-' * C(P(1) - ']')) ^ 1 * ']') / class,
- CondList = P('{') * Cf(V('Cond') * (P(',') * V('Cond')) ^ 0, add) * '}',
- -- TODO: '*' inside a {} condition is interpreted literally but should probably have the same
- -- wildcard semantics it usually has.
- -- Fixing this is non-trivial because '*' should match non-greedily up to "the rest of the
- -- pattern" which in all other cases is the entire succeeding part of the pattern, but at the end of a {}
- -- condition means "everything after the {}" where several other options separated by ',' may
- -- exist in between that should not be matched by '*'.
- Cond = Cf((V('Ques') + V('Class') + V('CondList') + (V('Literal') - S(',}'))) ^ 1, mul)
- + Cc(l.P(0)),
- Literal = P(1) / l.P,
- End = P(-1) * Cc(l.P(-1)),
- })
-
- return p:match(pattern) --[[@as vim.lpeg.Pattern?]]
-end
-
----@private
---- Implementation of LSP 3.17.0's pattern matching: https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#pattern
----
----@param pattern string|vim.lpeg.Pattern The glob pattern (raw or parsed) to match.
----@param s string The string to match against pattern.
----@return boolean Whether or not pattern matches s.
-function M._match(pattern, s)
- if type(pattern) == 'string' then
- local p = assert(parse(pattern))
- return p:match(s) ~= nil
- end
- return pattern:match(s) ~= nil
+if vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1 then
+ M._watchfunc = watch.watch
+elseif vim.fn.executable('fswatch') == 1 then
+ M._watchfunc = watch.fswatch
+else
+ M._watchfunc = watch.watchdirs
end
-M._watchfunc = (vim.fn.has('win32') == 1 or vim.fn.has('mac') == 1) and watch.watch or watch.poll
-
---@type table<integer, table<string, function[]>> client id -> registration id -> cancel function
local cancels = vim.defaulttable()
@@ -112,9 +37,9 @@ local to_lsp_change_type = {
--- Default excludes the same as VSCode's `files.watcherExclude` setting.
--- https://github.com/microsoft/vscode/blob/eef30e7165e19b33daa1e15e92fa34ff4a5df0d3/src/vs/workbench/contrib/files/browser/files.contribution.ts#L261
---@type vim.lpeg.Pattern parsed Lpeg pattern
-M._poll_exclude_pattern = parse('**/.git/{objects,subtree-cache}/**')
- + parse('**/node_modules/*/**')
- + parse('**/.hg/store/**')
+M._poll_exclude_pattern = glob.to_lpeg('**/.git/{objects,subtree-cache}/**')
+ + glob.to_lpeg('**/node_modules/*/**')
+ + glob.to_lpeg('**/.hg/store/**')
--- Registers the workspace/didChangeWatchedFiles capability dynamically.
---
@@ -125,12 +50,8 @@ function M.register(reg, ctx)
local client = assert(vim.lsp.get_client_by_id(client_id), 'Client must be running')
-- 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.
- local has_capability = vim.tbl_get(
- client.config.capabilities or {},
- 'workspace',
- 'didChangeWatchedFiles',
- 'dynamicRegistration'
- )
+ local has_capability =
+ vim.tbl_get(client.capabilities, 'workspace', 'didChangeWatchedFiles', 'dynamicRegistration')
if not has_capability or not client.workspace_folders then
return
end
@@ -143,7 +64,7 @@ function M.register(reg, ctx)
local glob_pattern = w.globPattern
if type(glob_pattern) == 'string' then
- local pattern = parse(glob_pattern)
+ local pattern = glob.to_lpeg(glob_pattern)
if not pattern then
error('Cannot parse pattern: ' .. glob_pattern)
end
@@ -155,7 +76,7 @@ function M.register(reg, ctx)
local base_uri = glob_pattern.baseUri
local uri = type(base_uri) == 'string' and base_uri or base_uri.uri
local base_dir = vim.uri_to_fname(uri)
- local pattern = parse(glob_pattern.pattern)
+ local pattern = glob.to_lpeg(glob_pattern.pattern)
if not pattern then
error('Cannot parse pattern: ' .. glob_pattern.pattern)
end
@@ -248,4 +169,13 @@ function M.unregister(unreg, ctx)
end
end
+--- @param client_id integer
+function M.cancel(client_id)
+ for _, reg_cancels in pairs(cancels[client_id]) do
+ for _, cancel in pairs(reg_cancels) do
+ cancel()
+ end
+ end
+end
+
return M
diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua
index cf9acc0808..50121f30b2 100644
--- a/runtime/lua/vim/lsp/buf.lua
+++ b/runtime/lua/vim/lsp/buf.lua
@@ -11,8 +11,8 @@ local M = {}
---
---@param method (string) LSP method name
---@param params (table|nil) Parameters to send to the server
----@param handler (function|nil) See |lsp-handler|. Follows |lsp-handler-resolution|
---
+---@param handler lsp.Handler? See |lsp-handler|. Follows |lsp-handler-resolution|
+---
---@return table<integer, integer> client_request_ids Map of client-id:request-id pairs
---for all successful requests.
---@return function _cancel_all_requests Function which can be used to
@@ -28,16 +28,6 @@ local function request(method, params, handler)
return vim.lsp.buf_request(0, method, params, handler)
end
---- Checks whether the language servers attached to the current buffer are
---- ready.
----
----@return boolean 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
-
--- Displays hover information about the symbol under the cursor in a floating
--- window. Calling the function twice will jump into the floating window.
function M.hover()
@@ -46,10 +36,10 @@ function M.hover()
end
local function request_with_options(name, params, options)
- local req_handler
+ local req_handler --- @type function?
if options then
req_handler = function(err, result, ctx, config)
- local client = vim.lsp.get_client_by_id(ctx.client_id)
+ local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
local handler = client.handlers[name] or vim.lsp.handlers[name]
handler(err, result, ctx, vim.tbl_extend('force', config or {}, options))
end
@@ -57,35 +47,57 @@ local function request_with_options(name, params, options)
request(name, params, req_handler)
end
---- Jumps to the declaration of the symbol under the cursor.
----@note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead.
+--- @class vim.lsp.ListOpts
---
----@param options table|nil additional options
---- - reuse_win: (boolean) Jump to existing window if buffer is already open.
---- - on_list: (function) |lsp-on-list-handler| replacing the default handler.
---- Called for any non-empty result.
+--- list-handler replacing the default handler.
+--- Called for any non-empty result.
+--- This table can be used with |setqflist()| or |setloclist()|. E.g.:
+--- ```lua
+--- local function on_list(options)
+--- vim.fn.setqflist({}, ' ', options)
+--- vim.cmd.cfirst()
+--- end
+---
+--- vim.lsp.buf.definition({ on_list = on_list })
+--- vim.lsp.buf.references(nil, { on_list = on_list })
+--- ```
+---
+--- If you prefer loclist do something like this:
+--- ```lua
+--- local function on_list(options)
+--- vim.fn.setloclist(0, {}, ' ', options)
+--- vim.cmd.lopen()
+--- end
+--- ```
+--- @field on_list? fun(t: vim.lsp.LocationOpts.OnList)
+
+--- @class vim.lsp.LocationOpts.OnList
+--- @field items table[] Structured like |setqflist-what|
+--- @field title? string Title for the list.
+--- @field context? table `ctx` from |lsp-handler|
+
+--- @class vim.lsp.LocationOpts: vim.lsp.ListOpts
+---
+--- Jump to existing window if buffer is already open.
+--- @field reuse_win? boolean
+
+--- Jumps to the declaration of the symbol under the cursor.
+--- @note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead.
+--- @param options? vim.lsp.LocationOpts
function M.declaration(options)
local params = util.make_position_params()
request_with_options(ms.textDocument_declaration, params, options)
end
--- Jumps to the definition of the symbol under the cursor.
----
----@param options table|nil additional options
---- - reuse_win: (boolean) Jump to existing window if buffer is already open.
---- - on_list: (function) |lsp-on-list-handler| replacing the default handler.
---- Called for any non-empty result.
+--- @param options? vim.lsp.LocationOpts
function M.definition(options)
local params = util.make_position_params()
request_with_options(ms.textDocument_definition, params, options)
end
--- Jumps to the definition of the type of the symbol under the cursor.
----
----@param options table|nil additional options
---- - reuse_win: (boolean) Jump to existing window if buffer is already open.
---- - on_list: (function) |lsp-on-list-handler| replacing the default handler.
---- Called for any non-empty result.
+--- @param options? vim.lsp.LocationOpts
function M.type_definition(options)
local params = util.make_position_params()
request_with_options(ms.textDocument_typeDefinition, params, options)
@@ -93,10 +105,7 @@ end
--- Lists all the implementations for the symbol under the cursor in the
--- quickfix window.
----
----@param options table|nil additional options
---- - on_list: (function) |lsp-on-list-handler| replacing the default handler.
---- Called for any non-empty result.
+--- @param options? vim.lsp.LocationOpts
function M.implementation(options)
local params = util.make_position_params()
request_with_options(ms.textDocument_implementation, params, options)
@@ -156,44 +165,55 @@ local function range_from_selection(bufnr, mode)
}
end
+--- @class vim.lsp.buf.format.Opts
+--- @inlinedoc
+---
+--- Can be used to specify FormattingOptions. Some unspecified options will be
+--- automatically derived from the current Nvim options.
+--- See https://microsoft.github.io/language-server-protocol/specification/#formattingOptions
+--- @field formatting_options? table
+---
+--- Time in milliseconds to block for formatting requests. No effect if async=true.
+--- (default: `1000`)
+--- @field timeout_ms? integer
+---
+--- Restrict formatting to the clients attached to the given buffer.
+--- (default: current buffer)
+--- @field bufnr? integer
+---
+--- Predicate used to filter clients. Receives a client as argument and must
+--- return a boolean. Clients matching the predicate are included. Example:
+--- ```lua
+--- -- Never request typescript-language-server for formatting
+--- vim.lsp.buf.format {
+--- filter = function(client) return client.name ~= "tsserver" end
+--- }
+--- ```
+--- @field filter? fun(client: vim.lsp.Client): boolean?
+---
+--- If true the method won't block.
+--- Editing the buffer while formatting asynchronous can lead to unexpected
+--- changes.
+--- (Default: false)
+--- @field async? boolean
+---
+--- Restrict formatting to the client with ID (client.id) matching this field.
+--- @field id? integer
+---
+--- Restrict formatting to the client with name (client.name) matching this field.
+--- @field name? string
+---
+--- Range to format.
+--- Table must contain `start` and `end` keys with {row,col} tuples using
+--- (1,0) indexing.
+--- (Default: current selection in visual mode, `nil` in other modes,
+--- formatting the full buffer)
+--- @field range? {start:integer[],end:integer[]}
+
--- Formats a buffer using the attached (and optionally filtered) language
--- server clients.
---
---- @param options table|nil Optional table which holds the following optional fields:
---- - formatting_options (table|nil):
---- Can be used to specify FormattingOptions. Some unspecified options will be
---- automatically derived from the current Nvim options.
---- See https://microsoft.github.io/language-server-protocol/specification/#formattingOptions
---- - timeout_ms (integer|nil, default 1000):
---- Time in milliseconds to block for formatting requests. No effect if async=true
---- - bufnr (number|nil):
---- Restrict formatting to the clients attached to the given buffer, defaults to the current
---- buffer (0).
----
---- - filter (function|nil):
---- Predicate used to filter clients. Receives a client as argument and must return a
---- boolean. Clients matching the predicate are included. Example: <pre>lua
---- -- Never request typescript-language-server for formatting
---- vim.lsp.buf.format {
---- filter = function(client) return client.name ~= "tsserver" end
---- }
---- </pre>
----
---- - async boolean|nil
---- If true the method won't block. Defaults to false.
---- Editing the buffer while formatting asynchronous can lead to unexpected
---- changes.
----
---- - id (number|nil):
---- Restrict formatting to the client with ID (client.id) matching this field.
---- - name (string|nil):
---- Restrict formatting to the client with name (client.name) matching this field.
----
---- - range (table|nil) Range to format.
---- Table must contain `start` and `end` keys with {row,col} tuples using
---- (1,0) indexing.
---- Defaults to current selection in visual mode
---- Defaults to `nil` in other modes, formatting the full buffer
+--- @param options? vim.lsp.buf.format.Opts
function M.format(options)
options = options or {}
local bufnr = options.bufnr or api.nvim_get_current_buf()
@@ -218,6 +238,9 @@ function M.format(options)
vim.notify('[LSP] Format request failed, no matching language servers.')
end
+ --- @param client vim.lsp.Client
+ --- @param params lsp.DocumentFormattingParams
+ --- @return lsp.DocumentFormattingParams
local function set_range(client, params)
if range then
local range_params =
@@ -228,8 +251,7 @@ function M.format(options)
end
if options.async then
- local do_format
- do_format = function(idx, client)
+ local function do_format(idx, client)
if not client then
return
end
@@ -255,17 +277,25 @@ function M.format(options)
end
end
+--- @class vim.lsp.buf.rename.Opts
+--- @inlinedoc
+---
+--- Predicate used to filter clients. Receives a client as argument and
+--- must return a boolean. Clients matching the predicate are included.
+--- @field filter? fun(client: vim.lsp.Client): boolean?
+---
+--- Restrict clients used for rename to ones where client.name matches
+--- this field.
+--- @field name? string
+---
+--- (default: current buffer)
+--- @field bufnr? integer
+
--- Renames all references to the symbol under the cursor.
---
---@param new_name string|nil If not provided, the user will be prompted for a new
--- name using |vim.ui.input()|.
----@param options table|nil additional options
---- - filter (function|nil):
---- Predicate used to filter clients. Receives a client as argument and
---- must return a boolean. Clients matching the predicate are included.
---- - name (string|nil):
---- Restrict clients used for rename to ones where client.name matches
---- this field.
+---@param options? vim.lsp.buf.rename.Opts Additional options:
function M.rename(new_name, options)
options = options or {}
local bufnr = options.bufnr or api.nvim_get_current_buf()
@@ -299,12 +329,12 @@ function M.rename(new_name, options)
)[1]
end
- local try_use_client
- try_use_client = function(idx, client)
+ local function try_use_client(idx, client)
if not client then
return
end
+ --- @param name string
local function rename(name)
local params = util.make_position_params(win, client.offset_encoding)
params.newName = name
@@ -385,8 +415,7 @@ end
---
---@param context (table|nil) Context for the request
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
----@param options table|nil additional options
---- - on_list: (function) handler for list results. See |lsp-on-list-handler|
+---@param options? vim.lsp.ListOpts
function M.references(context, options)
validate({ context = { context, 't', true } })
local params = util.make_position_params()
@@ -397,14 +426,13 @@ function M.references(context, options)
end
--- Lists all symbols in the current buffer in the quickfix window.
----
----@param options table|nil additional options
---- - on_list: (function) handler for list results. See |lsp-on-list-handler|
+--- @param options? vim.lsp.ListOpts
function M.document_symbol(options)
local params = { textDocument = util.make_text_document_params() }
request_with_options(ms.textDocument_documentSymbol, params, options)
end
+--- @param call_hierarchy_items lsp.CallHierarchyItem[]?
local function pick_call_hierarchy_item(call_hierarchy_items)
if not call_hierarchy_items then
return
@@ -424,8 +452,10 @@ local function pick_call_hierarchy_item(call_hierarchy_items)
return choice
end
+--- @param method string
local function call_hierarchy(method)
local params = util.make_position_params()
+ --- @param result lsp.CallHierarchyItem[]?
request(ms.textDocument_prepareCallHierarchy, params, function(err, result, ctx)
if err then
vim.notify(err.message, vim.log.levels.WARN)
@@ -472,6 +502,7 @@ end
--- Add the folder at path to the workspace folders. If {path} is
--- not provided, the user will be prompted for a path using |input()|.
+--- @param workspace_folder? string
function M.add_workspace_folder(workspace_folder)
workspace_folder = workspace_folder
or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h'), 'dir')
@@ -511,6 +542,7 @@ end
--- Remove the folder at path from the workspace folders. If
--- {path} is not provided, the user will be prompted for
--- a path using |input()|.
+--- @param workspace_folder? string
function M.remove_workspace_folder(workspace_folder)
workspace_folder = workspace_folder
or npcall(vim.fn.input, 'Workspace Folder: ', vim.fn.expand('%:p:h'))
@@ -542,9 +574,8 @@ end
--- call, the user is prompted to enter a string on the command line. An empty
--- string means no filtering is done.
---
----@param query string|nil optional
----@param options table|nil additional options
---- - on_list: (function) handler for list results. See |lsp-on-list-handler|
+--- @param query string? optional
+--- @param options? vim.lsp.ListOpts
function M.workspace_symbol(query, options)
query = query or npcall(vim.fn.input, 'Query: ')
if query == nil then
@@ -579,16 +610,36 @@ function M.clear_references()
util.buf_clear_references()
end
+---@nodoc
---@class vim.lsp.CodeActionResultEntry
---@field error? lsp.ResponseError
---@field result? (lsp.Command|lsp.CodeAction)[]
---@field ctx lsp.HandlerContext
----@class vim.lsp.buf.code_action.opts
----@field context? lsp.CodeActionContext
----@field filter? fun(x: lsp.CodeAction|lsp.Command):boolean
----@field apply? boolean
----@field range? {start: integer[], end: integer[]}
+--- @class vim.lsp.buf.code_action.Opts
+--- @inlinedoc
+---
+--- Corresponds to `CodeActionContext` of the LSP specification:
+--- - {diagnostics}? (`table`) LSP `Diagnostic[]`. Inferred from the current
+--- position if not provided.
+--- - {only}? (`table`) List of LSP `CodeActionKind`s used to filter the code actions.
+--- Most language servers support values like `refactor`
+--- or `quickfix`.
+--- - {triggerKind}? (`integer`) The reason why code actions were requested.
+--- @field context? lsp.CodeActionContext
+---
+--- Predicate taking an `CodeAction` and returning a boolean.
+--- @field filter? fun(x: lsp.CodeAction|lsp.Command):boolean
+---
+--- When set to `true`, and there is just one remaining action
+--- (after filtering), the action is applied without user query.
+--- @field apply? boolean
+---
+--- Range for which code actions should be requested.
+--- If in visual mode this defaults to the active selection.
+--- Table must contain `start` and `end` keys with {row,col} tuples
+--- using mark-like indexing. See |api-indexing|
+--- @field range? {start: integer[], end: integer[]}
--- This is not public because the main extension point is
--- vim.ui.select which can be overridden independently.
@@ -599,7 +650,7 @@ end
--- need to be able to link a `CodeAction|Command` to the right client for
--- `codeAction/resolve`
---@param results table<integer, vim.lsp.CodeActionResultEntry>
----@param opts? vim.lsp.buf.code_action.opts
+---@param opts? vim.lsp.buf.code_action.Opts
local function on_code_action_results(results, opts)
---@param a lsp.Command|lsp.CodeAction
local function action_filter(a)
@@ -644,15 +695,16 @@ local function on_code_action_results(results, opts)
end
---@param action lsp.Command|lsp.CodeAction
- ---@param client lsp.Client
+ ---@param client vim.lsp.Client
---@param ctx lsp.HandlerContext
local function apply_action(action, client, ctx)
if action.edit then
util.apply_workspace_edit(action.edit, client.offset_encoding)
end
- if action.command then
- local command = type(action.command) == 'table' and action.command or action
- client._exec_cmd(command, ctx)
+ local a_cmd = action.command
+ if a_cmd then
+ local command = type(a_cmd) == 'table' and a_cmd or action
+ client:_exec_cmd(command, ctx)
end
end
@@ -673,7 +725,6 @@ local function on_code_action_results(results, opts)
-- command: string
-- arguments?: any[]
--
- ---@type lsp.Client
local client = assert(vim.lsp.get_client_by_id(choice.ctx.client_id))
local action = choice.action
local bufnr = assert(choice.ctx.bufnr, 'Must have buffer number')
@@ -723,29 +774,7 @@ end
--- Selects a code action available at the current
--- cursor position.
---
----@param options table|nil Optional table which holds the following optional fields:
---- - context: (table|nil)
---- Corresponds to `CodeActionContext` of the LSP specification:
---- - diagnostics (table|nil):
---- LSP `Diagnostic[]`. Inferred from the current
---- position if not provided.
---- - only (table|nil):
---- List of LSP `CodeActionKind`s used to filter the code actions.
---- Most language servers support values like `refactor`
---- or `quickfix`.
---- - triggerKind (number|nil): The reason why code actions were requested.
---- - filter: (function|nil)
---- Predicate taking an `CodeAction` and returning a boolean.
---- - apply: (boolean|nil)
---- When set to `true`, and there is just one remaining action
---- (after filtering), the action is applied without user query.
----
---- - range: (table|nil)
---- Range for which code actions should be requested.
---- If in visual mode this defaults to the active selection.
---- Table must contain `start` and `end` keys with {row,col} tuples
---- using mark-like indexing. See |api-indexing|
----
+---@param options? vim.lsp.buf.code_action.Opts
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction
---@see vim.lsp.protocol.CodeActionTriggerKind
function M.code_action(options)
@@ -753,6 +782,7 @@ function M.code_action(options)
options = options or {}
-- Detect old API call code_action(context) which should now be
-- code_action({ context = context} )
+ --- @diagnostic disable-next-line:undefined-field
if options.diagnostics or options.only then
options = { options = options }
end
@@ -811,9 +841,8 @@ function M.code_action(options)
end
--- Executes an LSP server command.
----
----@param command_params table A valid `ExecuteCommandParams` object
----@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
+--- @param command_params lsp.ExecuteCommandParams
+--- @see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
function M.execute_command(command_params)
validate({
command = { command_params.command, 's' },
diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua
new file mode 100644
index 0000000000..ff0db166d5
--- /dev/null
+++ b/runtime/lua/vim/lsp/client.lua
@@ -0,0 +1,1056 @@
+local uv = vim.uv
+local api = vim.api
+local lsp = vim.lsp
+local log = lsp.log
+local ms = lsp.protocol.Methods
+local changetracking = lsp._changetracking
+local validate = vim.validate
+
+--- @alias vim.lsp.client.on_init_cb fun(client: vim.lsp.Client, initialize_result: lsp.InitializeResult)
+--- @alias vim.lsp.client.on_attach_cb fun(client: vim.lsp.Client, bufnr: integer)
+--- @alias vim.lsp.client.on_exit_cb fun(code: integer, signal: integer, client_id: integer)
+--- @alias vim.lsp.client.before_init_cb fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)
+
+--- @class vim.lsp.Client.Flags
+--- @inlinedoc
+---
+--- Allow using incremental sync for buffer edits
+--- (defailt: `true`)
+--- @field allow_incremental_sync? boolean
+---
+--- Debounce `didChange` notifications to the server by the given number in milliseconds.
+--- No debounce occurs if `nil`.
+--- (default: `150`)
+--- @field debounce_text_changes integer
+---
+--- Milliseconds to wait for server to exit cleanly after sending the
+--- "shutdown" request before sending kill -15. If set to false, nvim exits
+--- immediately after sending the "shutdown" request to the server.
+--- (default: `false`)
+--- @field exit_timeout integer|false
+
+--- @class vim.lsp.ClientConfig
+--- command string[] that launches the language
+--- server (treated as in |jobstart()|, must be absolute or on `$PATH`, shell constructs like
+--- "~" are not expanded), or function that creates an RPC client. Function receives
+--- a `dispatchers` table and returns a table with member functions `request`, `notify`,
+--- `is_closing` and `terminate`.
+--- See |vim.lsp.rpc.request()|, |vim.lsp.rpc.notify()|.
+--- For TCP there is a builtin RPC client factory: |vim.lsp.rpc.connect()|
+--- @field cmd string[]|fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient?
+---
+--- Directory to launch the `cmd` process. Not related to `root_dir`.
+--- (default: cwd)
+--- @field cmd_cwd? string
+---
+--- Environment flags to pass to the LSP on spawn.
+--- Must be specified using a table.
+--- Non-string values are coerced to string.
+--- Example:
+--- ```lua
+--- { PORT = 8080; HOST = "0.0.0.0"; }
+--- ```
+--- @field cmd_env? table
+---
+--- Daemonize the server process so that it runs in a separate process group from Nvim.
+--- Nvim will shutdown the process on exit, but if Nvim fails to exit cleanly this could leave
+--- behind orphaned server processes.
+--- (default: true)
+--- @field detached? boolean
+---
+--- List of workspace folders passed to the language server.
+--- For backwards compatibility rootUri and rootPath will be derived from the first workspace
+--- folder in this list. See `workspaceFolders` in the LSP spec.
+--- @field workspace_folders? lsp.WorkspaceFolder[]
+---
+--- Map overriding the default capabilities defined by |vim.lsp.protocol.make_client_capabilities()|,
+--- passed to the language server on initialization. Hint: use make_client_capabilities() and modify
+--- its result.
+--- - Note: To send an empty dictionary use |vim.empty_dict()|, else it will be encoded as an
+--- array.
+--- @field capabilities? lsp.ClientCapabilities
+---
+--- Map of language server method names to |lsp-handler|
+--- @field handlers? table<string,function>
+---
+--- Map with language server specific settings.
+--- See the {settings} in |vim.lsp.Client|.
+--- @field settings? table
+---
+--- Table that maps string of clientside commands to user-defined functions.
+--- Commands passed to start_client take precedence over the global command registry. Each key
+--- must be a unique command name, and the value is a function which is called if any LSP action
+--- (code action, code lenses, ...) triggers the command.
+--- @field commands? table<string,fun(command: lsp.Command, ctx: table)>
+---
+--- Values to pass in the initialization request as `initializationOptions`. See `initialize` in
+--- the LSP spec.
+--- @field init_options? table
+---
+--- Name in log messages.
+--- (default: client-id)
+--- @field name? string
+---
+--- Language ID as string. Defaults to the filetype.
+--- @field get_language_id? fun(bufnr: integer, filetype: string): string
+---
+--- The encoding that the LSP server expects. Client does not verify this is correct.
+--- @field offset_encoding? 'utf-8'|'utf-16'|'utf-32'
+---
+--- Callback invoked when the client operation throws an error. `code` is a number describing the error.
+--- Other arguments may be passed depending on the error kind. See `vim.lsp.rpc.client_errors`
+--- for possible errors. Use `vim.lsp.rpc.client_errors[code]` to get human-friendly name.
+--- @field on_error? fun(code: integer, err: string)
+---
+--- Callback invoked before the LSP "initialize" phase, where `params` contains the parameters
+--- being sent to the server and `config` is the config that was passed to |vim.lsp.start_client()|.
+--- You can use this to modify parameters before they are sent.
+--- @field before_init? fun(params: lsp.InitializeParams, config: vim.lsp.ClientConfig)
+---
+--- Callback invoked after LSP "initialize", where `result` is a table of `capabilities`
+--- and anything else the server may send. For example, clangd sends
+--- `initialize_result.offsetEncoding` if `capabilities.offsetEncoding` was sent to it.
+--- You can only modify the `client.offset_encoding` here before any notifications are sent.
+--- @field on_init? elem_or_list<fun(client: vim.lsp.Client, initialize_result: lsp.InitializeResult)>
+---
+--- Callback invoked on client exit.
+--- - code: exit code of the process
+--- - signal: number describing the signal used to terminate (if any)
+--- - client_id: client handle
+--- @field on_exit? elem_or_list<fun(code: integer, signal: integer, client_id: integer)>
+---
+--- Callback invoked when client attaches to a buffer.
+--- @field on_attach? elem_or_list<fun(client: vim.lsp.Client, bufnr: integer)>
+---
+--- Passed directly to the language server in the initialize request. Invalid/empty values will
+--- (default: "off")
+--- @field trace? 'off'|'messages'|'verbose'
+---
+--- A table with flags for the client. The current (experimental) flags are:
+--- @field flags? vim.lsp.Client.Flags
+---
+--- Directory where the LSP server will base its workspaceFolders, rootUri, and rootPath on initialization.
+--- @field root_dir? string
+
+--- @class vim.lsp.Client.Progress: vim.Ringbuf<{token: integer|string, value: any}>
+--- @field pending table<lsp.ProgressToken,lsp.LSPAny>
+
+--- @class vim.lsp.Client
+---
+--- The id allocated to the client.
+--- @field id integer
+---
+--- If a name is specified on creation, that will be used. Otherwise it is just
+--- the client id. This is used for logs and messages.
+--- @field name string
+---
+--- RPC client object, for low level interaction with the client.
+--- See |vim.lsp.rpc.start()|.
+--- @field rpc vim.lsp.rpc.PublicClient
+---
+--- The encoding used for communicating with the server. You can modify this in
+--- the `config`'s `on_init` method before text is sent to the server.
+--- @field offset_encoding string
+---
+--- The handlers used by the client as described in |lsp-handler|.
+--- @field handlers table<string,lsp.Handler>
+---
+--- The current pending requests in flight to the server. Entries are key-value
+--- pairs with the key being the request id while the value is a table with
+--- `type`, `bufnr`, and `method` key-value pairs. `type` is either "pending"
+--- for an active request, or "cancel" for a cancel request. It will be
+--- "complete" ephemerally while executing |LspRequest| autocmds when replies
+--- are received from the server.
+--- @field requests table<integer,{ type: string, bufnr: integer, method: string}>
+---
+--- copy of the table that was passed by the user
+--- to |vim.lsp.start_client()|.
+--- @field config vim.lsp.ClientConfig
+---
+--- Response from the server sent on `initialize` describing the server's
+--- capabilities.
+--- @field server_capabilities lsp.ServerCapabilities?
+---
+--- A ring buffer (|vim.ringbuf()|) containing progress messages
+--- sent by the server.
+--- @field progress vim.lsp.Client.Progress
+---
+--- @field initialized true?
+---
+--- The workspace folders configured in the client when the server starts.
+--- This property is only available if the client supports workspace folders.
+--- It can be `null` if the client supports workspace folders but none are
+--- configured.
+--- @field workspace_folders lsp.WorkspaceFolder[]?
+--- @field root_dir string
+---
+--- @field attached_buffers table<integer,true>
+--- @field private _log_prefix string
+---
+--- Track this so that we can escalate automatically if we've already tried a
+--- graceful shutdown
+--- @field private _graceful_shutdown_failed true?
+---
+--- The initial trace setting. If omitted trace is disabled ("off").
+--- trace = "off" | "messages" | "verbose";
+--- @field private _trace 'off'|'messages'|'verbose'
+---
+--- Table of command name to function which is called if any LSP action
+--- (code action, code lenses, ...) triggers the command.
+--- Client commands take precedence over the global command registry.
+--- @field commands table<string,fun(command: lsp.Command, ctx: table)>
+---
+--- Map with language server specific settings. These are returned to the
+--- language server if requested via `workspace/configuration`. Keys are
+--- case-sensitive.
+--- @field settings table
+---
+--- A table with flags for the client. The current (experimental) flags are:
+--- @field flags vim.lsp.Client.Flags
+---
+--- @field get_language_id fun(bufnr: integer, filetype: string): string
+---
+--- The capabilities provided by the client (editor or tool)
+--- @field capabilities lsp.ClientCapabilities
+--- @field dynamic_capabilities lsp.DynamicCapabilities
+---
+--- Sends a request to the server.
+--- This is a thin wrapper around {client.rpc.request} with some additional
+--- checking.
+--- If {handler} is not specified and if there's no respective global
+--- handler, then an error will occur.
+--- Returns: {status}, {client_id}?. {status} is a boolean indicating if
+--- the notification was successful. If it is `false`, then it will always
+--- be `false` (the client has shutdown).
+--- If {status} is `true`, the function returns {request_id} as the second
+--- result. You can use this with `client.cancel_request(request_id)` to cancel
+--- the request.
+--- @field request fun(method: string, params: table?, handler: lsp.Handler?, bufnr: integer): boolean, integer?
+---
+--- Sends a request to the server and synchronously waits for the response.
+--- This is a wrapper around {client.request}
+--- Returns: { err=err, result=result }, a dictionary, where `err` and `result`
+--- come from the |lsp-handler|. On timeout, cancel or error, returns `(nil,
+--- err)` where `err` is a string describing the failure reason. If the request
+--- was unsuccessful returns `nil`.
+--- @field request_sync fun(method: string, params: table?, timeout_ms: integer?, bufnr: integer): {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dictionary, where
+---
+--- Sends a notification to an LSP server.
+--- Returns: a boolean to indicate if the notification was successful. If
+--- it is false, then it will always be false (the client has shutdown).
+--- @field notify fun(method: string, params: table?): boolean
+---
+--- Cancels a request with a given request id.
+--- Returns: same as `notify()`.
+--- @field cancel_request fun(id: integer): boolean
+---
+--- Stops a client, optionally with force.
+--- By default, it will just ask the server to shutdown without force.
+--- If you request to stop a client which has previously been requested to
+--- shutdown, it will automatically escalate and force shutdown.
+--- @field stop fun(force?: boolean)
+---
+--- Runs the on_attach function from the client's config if it was defined.
+--- Useful for buffer-local setup.
+--- @field on_attach fun(bufnr: integer)
+---
+--- @field private _before_init_cb? vim.lsp.client.before_init_cb
+--- @field private _on_attach_cbs vim.lsp.client.on_attach_cb[]
+--- @field private _on_init_cbs vim.lsp.client.on_init_cb[]
+--- @field private _on_exit_cbs vim.lsp.client.on_exit_cb[]
+--- @field private _on_error_cb? fun(code: integer, err: string)
+---
+--- Checks if a client supports a given method.
+--- Always returns true for unknown off-spec methods.
+--- {opts} is a optional `{bufnr?: integer}` table.
+--- Some language server capabilities can be file specific.
+--- @field supports_method fun(method: string, opts?: {bufnr: integer?}): boolean
+---
+--- Checks whether a client is stopped.
+--- Returns: true if the client is fully stopped.
+--- @field is_stopped fun(): boolean
+local Client = {}
+Client.__index = Client
+
+--- @param cls table
+--- @param meth any
+--- @return function
+local function method_wrapper(cls, meth)
+ return function(...)
+ return meth(cls, ...)
+ end
+end
+
+local client_index = 0
+
+--- Checks whether a given path is a directory.
+--- @param filename (string) path to check
+--- @return boolean # true if {filename} exists and is a directory, false otherwise
+local function is_dir(filename)
+ validate({ filename = { filename, 's' } })
+ local stat = uv.fs_stat(filename)
+ return stat and stat.type == 'directory' or false
+end
+
+local valid_encodings = {
+ ['utf-8'] = 'utf-8',
+ ['utf-16'] = 'utf-16',
+ ['utf-32'] = 'utf-32',
+ ['utf8'] = 'utf-8',
+ ['utf16'] = 'utf-16',
+ ['utf32'] = 'utf-32',
+ UTF8 = 'utf-8',
+ UTF16 = 'utf-16',
+ UTF32 = 'utf-32',
+}
+
+--- Normalizes {encoding} to valid LSP encoding names.
+--- @param encoding string? Encoding to normalize
+--- @return string # normalized encoding name
+local function validate_encoding(encoding)
+ validate({
+ encoding = { encoding, 's', true },
+ })
+ if not encoding then
+ return valid_encodings.UTF16
+ end
+ return valid_encodings[encoding:lower()]
+ or error(
+ string.format(
+ "Invalid offset encoding %q. Must be one of: 'utf-8', 'utf-16', 'utf-32'",
+ encoding
+ )
+ )
+end
+
+--- Augments a validator function with support for optional (nil) values.
+--- @param fn (fun(v): boolean) The original validator function; should return a
+--- bool.
+--- @return fun(v): boolean # The augmented function. Also returns true if {v} is
+--- `nil`.
+local function optional_validator(fn)
+ return function(v)
+ return v == nil or fn(v)
+ end
+end
+
+--- By default, get_language_id just returns the exact filetype it is passed.
+--- It is possible to pass in something that will calculate a different filetype,
+--- to be sent by the client.
+--- @param _bufnr integer
+--- @param filetype string
+local function default_get_language_id(_bufnr, filetype)
+ return filetype
+end
+
+--- Validates a client configuration as given to |vim.lsp.start_client()|.
+--- @param config vim.lsp.ClientConfig
+local function validate_config(config)
+ validate({
+ config = { config, 't' },
+ })
+ validate({
+ handlers = { config.handlers, 't', true },
+ capabilities = { config.capabilities, 't', true },
+ cmd_cwd = { config.cmd_cwd, optional_validator(is_dir), 'directory' },
+ cmd_env = { config.cmd_env, 't', true },
+ detached = { config.detached, 'b', true },
+ name = { config.name, 's', true },
+ on_error = { config.on_error, 'f', true },
+ on_exit = { config.on_exit, { 'f', 't' }, true },
+ on_init = { config.on_init, { 'f', 't' }, true },
+ on_attach = { config.on_attach, { 'f', 't' }, true },
+ settings = { config.settings, 't', true },
+ commands = { config.commands, 't', true },
+ before_init = { config.before_init, { 'f', 't' }, true },
+ offset_encoding = { config.offset_encoding, 's', true },
+ flags = { config.flags, 't', true },
+ get_language_id = { config.get_language_id, 'f', true },
+ })
+
+ assert(
+ (
+ not config.flags
+ or not config.flags.debounce_text_changes
+ or type(config.flags.debounce_text_changes) == 'number'
+ ),
+ 'flags.debounce_text_changes must be a number with the debounce time in milliseconds'
+ )
+end
+
+--- @param trace string
+--- @return 'off'|'messages'|'verbose'
+local function get_trace(trace)
+ local valid_traces = {
+ off = 'off',
+ messages = 'messages',
+ verbose = 'verbose',
+ }
+ return trace and valid_traces[trace] or 'off'
+end
+
+--- @param id integer
+--- @param config vim.lsp.ClientConfig
+--- @return string
+local function get_name(id, config)
+ local name = config.name
+ if name then
+ return name
+ end
+
+ if type(config.cmd) == 'table' and config.cmd[1] then
+ return assert(vim.fs.basename(config.cmd[1]))
+ end
+
+ return tostring(id)
+end
+
+--- @param workspace_folders lsp.WorkspaceFolder[]?
+--- @param root_dir string?
+--- @return lsp.WorkspaceFolder[]?
+local function get_workspace_folders(workspace_folders, root_dir)
+ if workspace_folders then
+ return workspace_folders
+ end
+ if root_dir then
+ return {
+ {
+ uri = vim.uri_from_fname(root_dir),
+ name = string.format('%s', root_dir),
+ },
+ }
+ end
+end
+
+--- @generic T
+--- @param x elem_or_list<T>?
+--- @return T[]
+local function ensure_list(x)
+ if type(x) == 'table' then
+ return x
+ end
+ return { x }
+end
+
+--- @package
+--- @param config vim.lsp.ClientConfig
+--- @return vim.lsp.Client?
+function Client.create(config)
+ validate_config(config)
+
+ client_index = client_index + 1
+ local id = client_index
+ local name = get_name(id, config)
+
+ --- @class vim.lsp.Client
+ local self = {
+ id = id,
+ config = config,
+ handlers = config.handlers or {},
+ offset_encoding = validate_encoding(config.offset_encoding),
+ name = name,
+ _log_prefix = string.format('LSP[%s]', name),
+ requests = {},
+ attached_buffers = {},
+ server_capabilities = {},
+ dynamic_capabilities = lsp._dynamic.new(id),
+ commands = config.commands or {},
+ settings = config.settings or {},
+ flags = config.flags or {},
+ get_language_id = config.get_language_id or default_get_language_id,
+ capabilities = config.capabilities or lsp.protocol.make_client_capabilities(),
+ workspace_folders = get_workspace_folders(config.workspace_folders, config.root_dir),
+ root_dir = config.root_dir,
+ _before_init_cb = config.before_init,
+ _on_init_cbs = ensure_list(config.on_init),
+ _on_exit_cbs = ensure_list(config.on_exit),
+ _on_attach_cbs = ensure_list(config.on_attach),
+ _on_error_cb = config.on_error,
+ _root_dir = config.root_dir,
+ _trace = get_trace(config.trace),
+
+ --- Contains $/progress report messages.
+ --- They have the format {token: integer|string, value: any}
+ --- For "work done progress", value will be one of:
+ --- - lsp.WorkDoneProgressBegin,
+ --- - lsp.WorkDoneProgressReport (extended with title from Begin)
+ --- - lsp.WorkDoneProgressEnd (extended with title from Begin)
+ progress = vim.ringbuf(50) --[[@as vim.lsp.Client.Progress]],
+
+ --- @deprecated use client.progress instead
+ messages = { name = name, messages = {}, progress = {}, status = {} },
+ }
+
+ self.request = method_wrapper(self, Client._request)
+ self.request_sync = method_wrapper(self, Client._request_sync)
+ self.notify = method_wrapper(self, Client._notify)
+ self.cancel_request = method_wrapper(self, Client._cancel_request)
+ self.stop = method_wrapper(self, Client._stop)
+ self.is_stopped = method_wrapper(self, Client._is_stopped)
+ self.on_attach = method_wrapper(self, Client._on_attach)
+ self.supports_method = method_wrapper(self, Client._supports_method)
+
+ --- @type table<string|integer, string> title of unfinished progress sequences by token
+ self.progress.pending = {}
+
+ --- @type vim.lsp.rpc.Dispatchers
+ local dispatchers = {
+ notification = method_wrapper(self, Client._notification),
+ server_request = method_wrapper(self, Client._server_request),
+ on_error = method_wrapper(self, Client._on_error),
+ on_exit = method_wrapper(self, Client._on_exit),
+ }
+
+ -- Start the RPC client.
+ local rpc --- @type vim.lsp.rpc.PublicClient?
+ local config_cmd = config.cmd
+ if type(config_cmd) == 'function' then
+ rpc = config_cmd(dispatchers)
+ else
+ rpc = lsp.rpc.start(config_cmd, dispatchers, {
+ cwd = config.cmd_cwd,
+ env = config.cmd_env,
+ detached = config.detached,
+ })
+ end
+
+ -- Return nil if the rpc client fails to start
+ if not rpc then
+ return
+ end
+
+ self.rpc = rpc
+
+ setmetatable(self, Client)
+
+ return self
+end
+
+--- @private
+--- @param cbs function[]
+--- @param error_id integer
+--- @param ... any
+function Client:_run_callbacks(cbs, error_id, ...)
+ for _, cb in pairs(cbs) do
+ --- @type boolean, string?
+ local status, err = pcall(cb, ...)
+ if not status then
+ self:write_error(error_id, err)
+ end
+ end
+end
+
+--- @package
+function Client:initialize()
+ local config = self.config
+
+ local root_uri --- @type string?
+ local root_path --- @type string?
+ if self.workspace_folders then
+ root_uri = self.workspace_folders[1].uri
+ root_path = vim.uri_to_fname(root_uri)
+ end
+
+ local initialize_params = {
+ -- The process Id of the parent process that started the server. Is null if
+ -- the process has not been started by another process. If the parent
+ -- process is not alive then the server should exit (see exit notification)
+ -- its process.
+ processId = uv.os_getpid(),
+ -- Information about the client
+ -- since 3.15.0
+ clientInfo = {
+ name = 'Neovim',
+ version = tostring(vim.version()),
+ },
+ -- The rootPath of the workspace. Is null if no folder is open.
+ --
+ -- @deprecated in favour of rootUri.
+ rootPath = root_path or vim.NIL,
+ -- The rootUri of the workspace. Is null if no folder is open. If both
+ -- `rootPath` and `rootUri` are set `rootUri` wins.
+ rootUri = root_uri or vim.NIL,
+ workspaceFolders = self.workspace_folders or vim.NIL,
+ -- User provided initialization options.
+ initializationOptions = config.init_options,
+ capabilities = self.capabilities,
+ trace = self._trace,
+ }
+
+ self:_run_callbacks(
+ { self._before_init_cb },
+ lsp.client_errors.BEFORE_INIT_CALLBACK_ERROR,
+ initialize_params,
+ config
+ )
+
+ log.trace(self._log_prefix, 'initialize_params', initialize_params)
+
+ local rpc = self.rpc
+
+ rpc.request('initialize', initialize_params, function(init_err, result)
+ assert(not init_err, tostring(init_err))
+ assert(result, 'server sent empty result')
+ rpc.notify('initialized', vim.empty_dict())
+ self.initialized = true
+
+ -- These are the cleaned up capabilities we use for dynamically deciding
+ -- when to send certain events to clients.
+ self.server_capabilities =
+ assert(result.capabilities, "initialize result doesn't contain capabilities")
+ self.server_capabilities = assert(lsp.protocol.resolve_capabilities(self.server_capabilities))
+
+ if self.server_capabilities.positionEncoding then
+ self.offset_encoding = self.server_capabilities.positionEncoding
+ end
+
+ if next(self.settings) then
+ self:_notify(ms.workspace_didChangeConfiguration, { settings = self.settings })
+ end
+
+ self:_run_callbacks(self._on_init_cbs, lsp.client_errors.ON_INIT_CALLBACK_ERROR, self, result)
+
+ log.info(
+ self._log_prefix,
+ 'server_capabilities',
+ { server_capabilities = self.server_capabilities }
+ )
+ end)
+end
+
+--- @private
+--- Returns the handler associated with an LSP method.
+--- Returns the default handler if the user hasn't set a custom one.
+---
+--- @param method (string) LSP method name
+--- @return lsp.Handler|nil handler for the given method, if defined, or the default from |vim.lsp.handlers|
+function Client:_resolve_handler(method)
+ return self.handlers[method] or lsp.handlers[method]
+end
+
+--- Returns the buffer number for the given {bufnr}.
+---
+--- @param bufnr (integer|nil) Buffer number to resolve. Defaults to current buffer
+--- @return integer bufnr
+local function resolve_bufnr(bufnr)
+ validate({ bufnr = { bufnr, 'n', true } })
+ if bufnr == nil or bufnr == 0 then
+ return api.nvim_get_current_buf()
+ end
+ return bufnr
+end
+
+--- @private
+--- Sends a request to the server.
+---
+--- This is a thin wrapper around {client.rpc.request} with some additional
+--- checks for capabilities and handler availability.
+---
+--- @param method string LSP method name.
+--- @param params table|nil LSP request params.
+--- @param handler lsp.Handler|nil Response |lsp-handler| for this method.
+--- @param bufnr integer Buffer handle (0 for current).
+--- @return boolean status, integer|nil request_id {status} is a bool indicating
+--- whether the request was successful. If it is `false`, then it will
+--- always be `false` (the client has shutdown). If it was
+--- successful, then it will return {request_id} as the
+--- second result. You can use this with `client.cancel_request(request_id)`
+--- to cancel the-request.
+--- @see |vim.lsp.buf_request_all()|
+function Client:_request(method, params, handler, bufnr)
+ if not handler then
+ handler = assert(
+ self:_resolve_handler(method),
+ string.format('not found: %q request handler for client %q.', method, self.name)
+ )
+ end
+ -- Ensure pending didChange notifications are sent so that the server doesn't operate on a stale state
+ changetracking.flush(self, bufnr)
+ local version = lsp.util.buf_versions[bufnr]
+ bufnr = resolve_bufnr(bufnr)
+ log.debug(self._log_prefix, 'client.request', self.id, method, params, handler, bufnr)
+ local success, request_id = self.rpc.request(method, params, function(err, result)
+ local context = {
+ method = method,
+ client_id = self.id,
+ bufnr = bufnr,
+ params = params,
+ version = version,
+ }
+ handler(err, result, context)
+ end, function(request_id)
+ local request = self.requests[request_id]
+ request.type = 'complete'
+ api.nvim_exec_autocmds('LspRequest', {
+ buffer = api.nvim_buf_is_valid(bufnr) and bufnr or nil,
+ modeline = false,
+ data = { client_id = self.id, request_id = request_id, request = request },
+ })
+ self.requests[request_id] = nil
+ end)
+
+ if success and request_id then
+ local request = { type = 'pending', bufnr = bufnr, method = method }
+ self.requests[request_id] = request
+ api.nvim_exec_autocmds('LspRequest', {
+ buffer = bufnr,
+ modeline = false,
+ data = { client_id = self.id, request_id = request_id, request = request },
+ })
+ end
+
+ return success, request_id
+end
+
+-- TODO(lewis6991): duplicated from lsp.lua
+local wait_result_reason = { [-1] = 'timeout', [-2] = 'interrupted', [-3] = 'error' }
+
+--- Concatenates and writes a list of strings to the Vim error buffer.
+---
+--- @param ... string List to write to the buffer
+local function err_message(...)
+ local message = table.concat(vim.tbl_flatten({ ... }))
+ if vim.in_fast_event() then
+ vim.schedule(function()
+ api.nvim_err_writeln(message)
+ api.nvim_command('redraw')
+ end)
+ else
+ api.nvim_err_writeln(message)
+ api.nvim_command('redraw')
+ end
+end
+
+--- @private
+--- Sends a request to the server and synchronously waits for the response.
+---
+--- This is a wrapper around {client.request}
+---
+--- @param method (string) LSP method name.
+--- @param params (table) LSP request params.
+--- @param timeout_ms (integer|nil) Maximum time in milliseconds to wait for
+--- a result. Defaults to 1000
+--- @param bufnr (integer) Buffer handle (0 for current).
+--- @return {err: lsp.ResponseError|nil, result:any}|nil, string|nil err # a dictionary, where
+--- `err` and `result` come from the |lsp-handler|.
+--- On timeout, cancel or error, returns `(nil, err)` where `err` is a
+--- string describing the failure reason. If the request was unsuccessful
+--- returns `nil`.
+--- @see |vim.lsp.buf_request_sync()|
+function Client:_request_sync(method, params, timeout_ms, bufnr)
+ local request_result = nil
+ local function _sync_handler(err, result)
+ request_result = { err = err, result = result }
+ end
+
+ local success, request_id = self:_request(method, params, _sync_handler, bufnr)
+ if not success then
+ return nil
+ end
+
+ local wait_result, reason = vim.wait(timeout_ms or 1000, function()
+ return request_result ~= nil
+ end, 10)
+
+ if not wait_result then
+ if request_id then
+ self:_cancel_request(request_id)
+ end
+ return nil, wait_result_reason[reason]
+ end
+ return request_result
+end
+
+--- @private
+--- Sends a notification to an LSP server.
+---
+--- @param method string LSP method name.
+--- @param params table|nil LSP request params.
+--- @return boolean status true if the notification was successful.
+--- If it is false, then it will always be false
+--- (the client has shutdown).
+function Client:_notify(method, params)
+ if method ~= ms.textDocument_didChange then
+ changetracking.flush(self)
+ end
+
+ local client_active = self.rpc.notify(method, params)
+
+ if client_active then
+ vim.schedule(function()
+ api.nvim_exec_autocmds('LspNotify', {
+ modeline = false,
+ data = {
+ client_id = self.id,
+ method = method,
+ params = params,
+ },
+ })
+ end)
+ end
+
+ return client_active
+end
+
+--- @private
+--- Cancels a request with a given request id.
+---
+--- @param id (integer) id of request to cancel
+--- @return boolean status true if notification was successful. false otherwise
+--- @see |vim.lsp.client.notify()|
+function Client:_cancel_request(id)
+ validate({ id = { id, 'n' } })
+ local request = self.requests[id]
+ if request and request.type == 'pending' then
+ request.type = 'cancel'
+ api.nvim_exec_autocmds('LspRequest', {
+ buffer = request.bufnr,
+ modeline = false,
+ data = { client_id = self.id, request_id = id, request = request },
+ })
+ end
+ return self.rpc.notify(ms.dollar_cancelRequest, { id = id })
+end
+
+--- @private
+--- Stops a client, optionally with force.
+---
+--- By default, it will just ask the - server to shutdown without force. If
+--- you request to stop a client which has previously been requested to
+--- shutdown, it will automatically escalate and force shutdown.
+---
+--- @param force boolean|nil
+function Client:_stop(force)
+ local rpc = self.rpc
+
+ if rpc.is_closing() then
+ return
+ end
+
+ if force or not self.initialized or self._graceful_shutdown_failed then
+ rpc.terminate()
+ return
+ end
+
+ -- Sending a signal after a process has exited is acceptable.
+ rpc.request(ms.shutdown, nil, function(err, _)
+ if err == nil then
+ rpc.notify(ms.exit)
+ else
+ -- If there was an error in the shutdown request, then term to be safe.
+ rpc.terminate()
+ self._graceful_shutdown_failed = true
+ end
+ vim.lsp._watchfiles.cancel(self.id)
+ end)
+end
+
+--- @private
+--- Checks whether a client is stopped.
+---
+--- @return boolean # true if client is stopped or in the process of being
+--- stopped; false otherwise
+function Client:_is_stopped()
+ return self.rpc.is_closing()
+end
+
+--- @package
+--- Execute a lsp command, either via client command function (if available)
+--- or via workspace/executeCommand (if supported by the server)
+---
+--- @param command lsp.Command
+--- @param context? {bufnr: integer}
+--- @param handler? lsp.Handler only called if a server command
+function Client:_exec_cmd(command, context, handler)
+ context = vim.deepcopy(context or {}, true) --[[@as lsp.HandlerContext]]
+ context.bufnr = context.bufnr or api.nvim_get_current_buf()
+ context.client_id = self.id
+ local cmdname = command.command
+ local fn = self.commands[cmdname] or lsp.commands[cmdname]
+ if fn then
+ fn(command, context)
+ return
+ end
+
+ local command_provider = self.server_capabilities.executeCommandProvider
+ local commands = type(command_provider) == 'table' and command_provider.commands or {}
+ if not vim.list_contains(commands, cmdname) then
+ vim.notify_once(
+ string.format(
+ 'Language server `%s` does not support command `%s`. This command may require a client extension.',
+ self.name,
+ cmdname
+ ),
+ vim.log.levels.WARN
+ )
+ return
+ end
+ -- Not using command directly to exclude extra properties,
+ -- see https://github.com/python-lsp/python-lsp-server/issues/146
+ local params = {
+ command = command.command,
+ arguments = command.arguments,
+ }
+ self.request(ms.workspace_executeCommand, params, handler, context.bufnr)
+end
+
+--- @package
+--- Default handler for the 'textDocument/didOpen' LSP notification.
+---
+--- @param bufnr integer Number of the buffer, or 0 for current
+function Client:_text_document_did_open_handler(bufnr)
+ changetracking.init(self, bufnr)
+ if not vim.tbl_get(self.server_capabilities, 'textDocumentSync', 'openClose') then
+ return
+ end
+ if not api.nvim_buf_is_loaded(bufnr) then
+ return
+ end
+ local filetype = vim.bo[bufnr].filetype
+
+ local params = {
+ textDocument = {
+ version = 0,
+ uri = vim.uri_from_bufnr(bufnr),
+ languageId = self.get_language_id(bufnr, filetype),
+ text = lsp._buf_get_full_text(bufnr),
+ },
+ }
+ self.notify(ms.textDocument_didOpen, params)
+ lsp.util.buf_versions[bufnr] = params.textDocument.version
+
+ -- Next chance we get, we should re-do the diagnostics
+ vim.schedule(function()
+ -- Protect against a race where the buffer disappears
+ -- between `did_open_handler` and the scheduled function firing.
+ if api.nvim_buf_is_valid(bufnr) then
+ local namespace = lsp.diagnostic.get_namespace(self.id)
+ vim.diagnostic.show(namespace, bufnr)
+ end
+ end)
+end
+
+--- @package
+--- Runs the on_attach function from the client's config if it was defined.
+--- @param bufnr integer Buffer number
+function Client:_on_attach(bufnr)
+ self:_text_document_did_open_handler(bufnr)
+
+ lsp._set_defaults(self, bufnr)
+
+ api.nvim_exec_autocmds('LspAttach', {
+ buffer = bufnr,
+ modeline = false,
+ data = { client_id = self.id },
+ })
+
+ self:_run_callbacks(self._on_attach_cbs, lsp.client_errors.ON_ATTACH_ERROR, self, bufnr)
+
+ -- schedule the initialization of semantic tokens to give the above
+ -- on_attach and LspAttach callbacks the ability to schedule wrap the
+ -- opt-out (deleting the semanticTokensProvider from capabilities)
+ vim.schedule(function()
+ if vim.tbl_get(self.server_capabilities, 'semanticTokensProvider', 'full') then
+ lsp.semantic_tokens.start(bufnr, self.id)
+ end
+ end)
+
+ self.attached_buffers[bufnr] = true
+end
+
+--- @private
+--- Logs the given error to the LSP log and to the error buffer.
+--- @param code integer Error code
+--- @param err any Error arguments
+function Client:write_error(code, err)
+ local client_error = lsp.client_errors[code] --- @type string|integer
+ log.error(self._log_prefix, 'on_error', { code = client_error, err = err })
+ err_message(self._log_prefix, ': Error ', client_error, ': ', vim.inspect(err))
+end
+
+--- @private
+--- @param method string
+--- @param opts? {bufnr: integer?}
+function Client:_supports_method(method, opts)
+ local required_capability = lsp._request_name_to_capability[method]
+ -- if we don't know about the method, assume that the client supports it.
+ if not required_capability then
+ return true
+ end
+ if vim.tbl_get(self.server_capabilities, unpack(required_capability)) then
+ return true
+ end
+ if self.dynamic_capabilities:supports_registration(method) then
+ return self.dynamic_capabilities:supports(method, opts)
+ end
+ return false
+end
+
+--- @private
+--- Handles a notification sent by an LSP server by invoking the
+--- corresponding handler.
+---
+--- @param method string LSP method name
+--- @param params table The parameters for that method.
+function Client:_notification(method, params)
+ log.trace('notification', method, params)
+ local handler = self:_resolve_handler(method)
+ if handler then
+ -- Method name is provided here for convenience.
+ handler(nil, params, { method = method, client_id = self.id })
+ end
+end
+
+--- @private
+--- Handles a request from an LSP server by invoking the corresponding handler.
+---
+--- @param method (string) LSP method name
+--- @param params (table) The parameters for that method
+--- @return any result
+--- @return lsp.ResponseError error code and message set in case an exception happens during the request.
+function Client:_server_request(method, params)
+ log.trace('server_request', method, params)
+ local handler = self:_resolve_handler(method)
+ if handler then
+ log.trace('server_request: found handler for', method)
+ return handler(nil, params, { method = method, client_id = self.id })
+ end
+ log.warn('server_request: no handler found for', method)
+ return nil, lsp.rpc_response_error(lsp.protocol.ErrorCodes.MethodNotFound)
+end
+
+--- @private
+--- Invoked when the client operation throws an error.
+---
+--- @param code integer Error code
+--- @param err any Other arguments may be passed depending on the error kind
+--- @see vim.lsp.rpc.client_errors for possible errors. Use
+--- `vim.lsp.rpc.client_errors[code]` to get a human-friendly name.
+function Client:_on_error(code, err)
+ self:write_error(code, err)
+ if self._on_error_cb then
+ --- @type boolean, string
+ local status, usererr = pcall(self._on_error_cb, code, err)
+ if not status then
+ log.error(self._log_prefix, 'user on_error failed', { err = usererr })
+ err_message(self._log_prefix, ' user on_error failed: ', tostring(usererr))
+ end
+ end
+end
+
+--- @private
+--- Invoked on client exit.
+---
+--- @param code integer) exit code of the process
+--- @param signal integer the signal used to terminate (if any)
+function Client:_on_exit(code, signal)
+ self:_run_callbacks(
+ self._on_exit_cbs,
+ lsp.client_errors.ON_EXIT_CALLBACK_ERROR,
+ code,
+ signal,
+ self.id
+ )
+end
+
+return Client
diff --git a/runtime/lua/vim/lsp/codelens.lua b/runtime/lua/vim/lsp/codelens.lua
index 9cccaa1d66..48c096c0c1 100644
--- a/runtime/lua/vim/lsp/codelens.lua
+++ b/runtime/lua/vim/lsp/codelens.lua
@@ -6,7 +6,7 @@ local M = {}
--- bufnr → true|nil
--- to throttle refreshes to at most one at a time
-local active_refreshes = {}
+local active_refreshes = {} --- @type table<integer,true>
---@type table<integer, table<integer, lsp.CodeLens[]>>
--- bufnr -> client_id -> lenses
@@ -48,7 +48,7 @@ local function execute_lens(lens, bufnr, client_id)
local client = vim.lsp.get_client_by_id(client_id)
assert(client, 'Client is required to execute lens, client_id=' .. client_id)
- client._exec_cmd(lens.command, { bufnr = bufnr }, function(...)
+ client:_exec_cmd(lens.command, { bufnr = bufnr }, function(...)
vim.lsp.handlers[ms.workspace_executeCommand](...)
M.refresh()
end)
@@ -75,7 +75,7 @@ end
function M.run()
local line = api.nvim_win_get_cursor(0)[1]
local bufnr = api.nvim_get_current_buf()
- local options = {}
+ local options = {} --- @type {client: integer, lens: lsp.CodeLens}[]
local lenses_by_client = lens_cache_by_buf[bufnr] or {}
for client, lenses in pairs(lenses_by_client) do
for _, lens in pairs(lenses) do
@@ -111,7 +111,7 @@ end
--- Clear the lenses
---
---@param client_id integer|nil filter by client_id. All clients if nil
----@param bufnr integer|nil filter by buffer. All buffers if nil
+---@param bufnr integer|nil filter by buffer. All buffers if nil, 0 for current buffer
function M.clear(client_id, bufnr)
bufnr = bufnr and resolve_bufnr(bufnr)
local buffers = bufnr and { bufnr }
@@ -230,6 +230,7 @@ local function resolve_lenses(lenses, bufnr, client_id, callback)
if lens.command then
countdown()
else
+ assert(client)
client.request('codeLens/resolve', lens, function(_, result)
if api.nvim_buf_is_loaded(bufnr) and result and result.command then
lens.command = result.command
@@ -257,10 +258,13 @@ end
--- |lsp-handler| for the method `textDocument/codeLens`
---
+---@param err lsp.ResponseError?
+---@param result lsp.CodeLens[]
+---@param ctx lsp.HandlerContext
function M.on_codelens(err, result, ctx, _)
if err then
- active_refreshes[ctx.bufnr] = nil
- local _ = log.error() and log.error('codelens', err)
+ active_refreshes[assert(ctx.bufnr)] = nil
+ log.error('codelens', err)
return
end
@@ -270,30 +274,41 @@ function M.on_codelens(err, result, ctx, _)
-- once resolved.
M.display(result, ctx.bufnr, ctx.client_id)
resolve_lenses(result, ctx.bufnr, ctx.client_id, function()
- active_refreshes[ctx.bufnr] = nil
+ active_refreshes[assert(ctx.bufnr)] = nil
M.display(result, ctx.bufnr, ctx.client_id)
end)
end
---- Refresh the codelens for the current buffer
+--- @class vim.lsp.codelens.refresh.Opts
+--- @inlinedoc
+--- @field bufnr integer? filter by buffer. All buffers if nil, 0 for current buffer
+
+--- Refresh the lenses.
---
--- It is recommended to trigger this using an autocmd or via keymap.
---
--- Example:
---
--- ```vim
---- autocmd BufEnter,CursorHold,InsertLeave <buffer> lua vim.lsp.codelens.refresh()
+--- autocmd BufEnter,CursorHold,InsertLeave <buffer> lua vim.lsp.codelens.refresh({ bufnr = 0 })
--- ```
-function M.refresh()
+---
+--- @param opts? vim.lsp.codelens.refresh.Opts Optional fields
+function M.refresh(opts)
+ opts = opts or {}
+ local bufnr = opts.bufnr and resolve_bufnr(opts.bufnr)
+ local buffers = bufnr and { bufnr }
+ or vim.tbl_filter(api.nvim_buf_is_loaded, api.nvim_list_bufs())
local params = {
textDocument = util.make_text_document_params(),
}
- local bufnr = api.nvim_get_current_buf()
- if active_refreshes[bufnr] then
- return
+
+ for _, buf in ipairs(buffers) do
+ if not active_refreshes[buf] then
+ active_refreshes[buf] = true
+ vim.lsp.buf_request(buf, ms.textDocument_codeLens, params, M.on_codelens)
+ end
end
- active_refreshes[bufnr] = true
- vim.lsp.buf_request(0, ms.textDocument_codeLens, params, M.on_codelens)
end
return M
diff --git a/runtime/lua/vim/lsp/diagnostic.lua b/runtime/lua/vim/lsp/diagnostic.lua
index b6f0cfa0b3..08cea13548 100644
--- a/runtime/lua/vim/lsp/diagnostic.lua
+++ b/runtime/lua/vim/lsp/diagnostic.lua
@@ -1,8 +1,4 @@
----@brief lsp-diagnostic
-
-local util = require('vim.lsp.util')
local protocol = require('vim.lsp.protocol')
-local log = require('vim.lsp.log')
local ms = protocol.Methods
local api = vim.api
@@ -24,7 +20,7 @@ end
---@param severity lsp.DiagnosticSeverity
local function severity_lsp_to_vim(severity)
if type(severity) == 'string' then
- severity = protocol.DiagnosticSeverity[severity]
+ severity = protocol.DiagnosticSeverity[severity] --- @type integer
end
return severity
end
@@ -37,6 +33,10 @@ local function severity_vim_to_lsp(severity)
return severity
end
+---@param lines string[]?
+---@param lnum integer
+---@param col integer
+---@param offset_encoding string
---@return integer
local function line_byte_from_position(lines, lnum, col, offset_encoding)
if not lines or offset_encoding == 'utf-8' then
@@ -46,12 +46,14 @@ local function line_byte_from_position(lines, lnum, col, offset_encoding)
local line = lines[lnum + 1]
local ok, result = pcall(vim.str_byteindex, line, col, offset_encoding == 'utf-16')
if ok then
- return result
+ return result --- @type integer
end
return col
end
+---@param bufnr integer
+---@return string[]?
local function get_buf_lines(bufnr)
if vim.api.nvim_buf_is_loaded(bufnr) then
return vim.api.nvim_buf_get_lines(bufnr, 0, -1, false)
@@ -89,7 +91,7 @@ local function tags_lsp_to_vim(diagnostic, client_id)
tags = tags or {}
tags.deprecated = true
else
- log.info(string.format('Unknown DiagnosticTag %d from LSP client %d', tag, client_id))
+ vim.lsp.log.info(string.format('Unknown DiagnosticTag %d from LSP client %d', tag, client_id))
end
end
return tags
@@ -98,16 +100,17 @@ end
---@param diagnostics lsp.Diagnostic[]
---@param bufnr integer
---@param client_id integer
----@return Diagnostic[]
+---@return vim.Diagnostic[]
local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)
local buf_lines = get_buf_lines(bufnr)
local client = vim.lsp.get_client_by_id(client_id)
local offset_encoding = client and client.offset_encoding or 'utf-16'
- ---@diagnostic disable-next-line:no-unknown
+ --- @param diagnostic lsp.Diagnostic
+ --- @return vim.Diagnostic
return vim.tbl_map(function(diagnostic)
- ---@cast diagnostic lsp.Diagnostic
local start = diagnostic.range.start
local _end = diagnostic.range['end']
+ --- @type vim.Diagnostic
return {
lnum = start.line,
col = line_byte_from_position(buf_lines, start.line, start.character, offset_encoding),
@@ -131,12 +134,29 @@ local function diagnostic_lsp_to_vim(diagnostics, bufnr, client_id)
end, diagnostics)
end
---- @param diagnostics Diagnostic[]
+--- @param diagnostic vim.Diagnostic
+--- @return lsp.DiagnosticTag[]?
+local function tags_vim_to_lsp(diagnostic)
+ if not diagnostic._tags then
+ return
+ end
+
+ local tags = {} --- @type lsp.DiagnosticTag[]
+ if diagnostic._tags.unnecessary then
+ tags[#tags + 1] = protocol.DiagnosticTag.Unnecessary
+ end
+ if diagnostic._tags.deprecated then
+ tags[#tags + 1] = protocol.DiagnosticTag.Deprecated
+ end
+ return tags
+end
+
+--- @param diagnostics vim.Diagnostic[]
--- @return lsp.Diagnostic[]
local function diagnostic_vim_to_lsp(diagnostics)
- ---@diagnostic disable-next-line:no-unknown
+ ---@param diagnostic vim.Diagnostic
+ ---@return lsp.Diagnostic
return vim.tbl_map(function(diagnostic)
- ---@cast diagnostic Diagnostic
return vim.tbl_extend('keep', {
-- "keep" the below fields over any duplicate fields in diagnostic.user_data.lsp
range = {
@@ -153,6 +173,7 @@ local function diagnostic_vim_to_lsp(diagnostics)
message = diagnostic.message,
source = diagnostic.source,
code = diagnostic.code,
+ tags = tags_vim_to_lsp(diagnostic),
}, diagnostic.user_data and (diagnostic.user_data.lsp or {}) or {})
end, diagnostics)
end
@@ -198,6 +219,47 @@ function M.get_namespace(client_id, is_pull)
end
end
+local function convert_severity(opt)
+ if type(opt) == 'table' and not opt.severity and opt.severity_limit then
+ vim.deprecate('severity_limit', '{min = severity} See vim.diagnostic.severity', '0.11')
+ opt.severity = { min = severity_lsp_to_vim(opt.severity_limit) }
+ end
+end
+
+--- @param uri string
+--- @param client_id? integer
+--- @param diagnostics vim.Diagnostic[]
+--- @param is_pull boolean
+--- @param config? vim.diagnostic.Opts
+local function handle_diagnostics(uri, client_id, diagnostics, is_pull, config)
+ local fname = vim.uri_to_fname(uri)
+
+ if #diagnostics == 0 and vim.fn.bufexists(fname) == 0 then
+ return
+ end
+
+ local bufnr = vim.fn.bufadd(fname)
+ if not bufnr then
+ return
+ end
+
+ client_id = get_client_id(client_id)
+ local namespace = M.get_namespace(client_id, is_pull)
+
+ if config then
+ --- @cast config table<string, table>
+ for _, opt in pairs(config) do
+ convert_severity(opt)
+ end
+ -- Persist configuration to ensure buffer reloads use the same
+ -- configuration. To make lsp.with configuration work (See :help
+ -- lsp-handler-configuration)
+ vim.diagnostic.config(config, namespace)
+ end
+
+ vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
+end
+
--- |lsp-handler| for the method "textDocument/publishDiagnostics"
---
--- See |vim.diagnostic.config()| for configuration options. Handler-specific
@@ -223,40 +285,12 @@ end
--- )
--- ```
---
----@param config table Configuration table (see |vim.diagnostic.config()|).
+---@param _ lsp.ResponseError?
+---@param result lsp.PublishDiagnosticsParams
+---@param ctx lsp.HandlerContext
+---@param config? vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|).
function M.on_publish_diagnostics(_, result, ctx, config)
- local client_id = ctx.client_id
- local uri = result.uri
- local fname = vim.uri_to_fname(uri)
- local diagnostics = result.diagnostics
- if #diagnostics == 0 and vim.fn.bufexists(fname) == 0 then
- return
- end
- local bufnr = vim.fn.bufadd(fname)
-
- if not bufnr then
- return
- end
-
- client_id = get_client_id(client_id)
- local namespace = M.get_namespace(client_id, false)
-
- if config then
- for _, opt in pairs(config) do
- if type(opt) == 'table' then
- if not opt.severity and opt.severity_limit then
- opt.severity = { min = severity_lsp_to_vim(opt.severity_limit) }
- end
- end
- end
-
- -- Persist configuration to ensure buffer reloads use the same
- -- configuration. To make lsp.with configuration work (See :help
- -- lsp-handler-configuration)
- vim.diagnostic.config(config, namespace)
- end
-
- vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
+ handle_diagnostics(result.uri, ctx.client_id, result.diagnostics, false, config)
end
--- |lsp-handler| for the method "textDocument/diagnostic"
@@ -284,48 +318,16 @@ end
--- )
--- ```
---
----@param config table Configuration table (see |vim.diagnostic.config()|).
+---@param _ lsp.ResponseError?
+---@param result lsp.DocumentDiagnosticReport
+---@param ctx lsp.HandlerContext
+---@param config vim.diagnostic.Opts Configuration table (see |vim.diagnostic.config()|).
function M.on_diagnostic(_, result, ctx, config)
- local client_id = ctx.client_id
- local uri = ctx.params.textDocument.uri
- local fname = vim.uri_to_fname(uri)
-
- if result == nil then
- return
- end
-
- if result.kind == 'unchanged' then
- return
- end
-
- local diagnostics = result.items
- if #diagnostics == 0 and vim.fn.bufexists(fname) == 0 then
+ if result == nil or result.kind == 'unchanged' then
return
end
- local bufnr = vim.fn.bufadd(fname)
-
- if not bufnr then
- return
- end
-
- client_id = get_client_id(client_id)
-
- local namespace = M.get_namespace(client_id, true)
-
- if config then
- for _, opt in pairs(config) do
- if type(opt) == 'table' and not opt.severity and opt.severity_limit then
- opt.severity = { min = severity_lsp_to_vim(opt.severity_limit) }
- end
- end
-
- -- Persist configuration to ensure buffer reloads use the same
- -- configuration. To make lsp.with configuration work (See :help
- -- lsp-handler-configuration)
- vim.diagnostic.config(config, namespace)
- end
- vim.diagnostic.set(namespace, bufnr, diagnostic_lsp_to_vim(diagnostics, bufnr, client_id))
+ handle_diagnostics(ctx.params.textDocument.uri, ctx.client_id, result.items, true, config)
end
--- Clear push diagnostics and diagnostic cache.
@@ -335,7 +337,7 @@ end
--- implementation so it's simply marked @private rather than @deprecated.
---
---@param client_id integer
----@param buffer_client_map table map of buffers to active clients
+---@param buffer_client_map table<integer, table<integer, table>> map of buffers to active clients
---@private
function M.reset(client_id, buffer_client_map)
buffer_client_map = vim.deepcopy(buffer_client_map)
@@ -356,34 +358,28 @@ end
---
---@param bufnr integer|nil The buffer number
---@param line_nr integer|nil The line number
----@param opts table|nil Configuration keys
---- - severity: (DiagnosticSeverity, default nil)
---- - Only return diagnostics with this severity. Overrides severity_limit
---- - severity_limit: (DiagnosticSeverity, default nil)
---- - Limit severity of diagnostics found. E.g. "Warning" means { "Error", "Warning" } will be valid.
+---@param opts {severity?:lsp.DiagnosticSeverity}?
+--- - severity: (lsp.DiagnosticSeverity)
+--- - Only return diagnostics with this severity.
---@param client_id integer|nil the client id
---@return table Table with map of line number to list of diagnostics.
--- Structured: { [1] = {...}, [5] = {.... } }
---@private
function M.get_line_diagnostics(bufnr, line_nr, opts, client_id)
- opts = opts or {}
- if opts.severity then
- opts.severity = severity_lsp_to_vim(opts.severity)
- elseif opts.severity_limit then
- opts.severity = { min = severity_lsp_to_vim(opts.severity_limit) }
- end
+ convert_severity(opts)
+ local diag_opts = {} --- @type vim.diagnostic.GetOpts
- if client_id then
- opts.namespace = M.get_namespace(client_id, false)
+ if opts and opts.severity then
+ diag_opts.severity = severity_lsp_to_vim(opts.severity)
end
- if not line_nr then
- line_nr = vim.api.nvim_win_get_cursor(0)[1] - 1
+ if client_id then
+ diag_opts.namespace = M.get_namespace(client_id, false)
end
- opts.lnum = line_nr
+ diag_opts.lnum = line_nr or (api.nvim_win_get_cursor(0)[1] - 1)
- return diagnostic_vim_to_lsp(vim.diagnostic.get(bufnr, opts))
+ return diagnostic_vim_to_lsp(vim.diagnostic.get(bufnr, diag_opts))
end
--- Clear diagnostics from pull based clients
@@ -394,12 +390,13 @@ local function clear(bufnr)
end
end
----@class lsp.diagnostic.bufstate
+---@class (private) lsp.diagnostic.bufstate
---@field enabled boolean Whether inlay hints are enabled for this buffer
---@type table<integer, lsp.diagnostic.bufstate>
local bufstates = {}
--- Disable pull diagnostics for a buffer
+--- @param bufnr integer
--- @private
local function disable(bufnr)
local bufstate = bufstates[bufnr]
@@ -416,7 +413,7 @@ end
local function _refresh(bufnr, opts)
opts = opts or {}
opts['bufnr'] = bufnr
- util._refresh(ms.textDocument_diagnostic, opts)
+ vim.lsp.util._refresh(ms.textDocument_diagnostic, opts)
end
--- Enable pull diagnostics for a buffer
@@ -440,7 +437,8 @@ function M._enable(bufnr)
return
end
if bufstates[bufnr] and bufstates[bufnr].enabled then
- _refresh(bufnr, { only_visible = true, client_id = opts.data.client_id })
+ local client_id = opts.data.client_id --- @type integer?
+ _refresh(bufnr, { only_visible = true, client_id = client_id })
end
end,
group = augroup,
diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua
index 6fde55cf04..daf4fec8d2 100644
--- a/runtime/lua/vim/lsp/handlers.lua
+++ b/runtime/lua/vim/lsp/handlers.lua
@@ -4,6 +4,7 @@ local ms = protocol.Methods
local util = require('vim.lsp.util')
local api = vim.api
+--- @type table<string,lsp.Handler>
local M = {}
-- FIXME: DOC: Expose in vimdocs
@@ -15,12 +16,12 @@ local function err_message(...)
api.nvim_command('redraw')
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand
M[ms.workspace_executeCommand] = function(_, _, _, _)
-- Error handling is done implicitly by wrapping all handlers; see end of this file
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#progress
---@param result lsp.ProgressParams
---@param ctx lsp.HandlerContext
M[ms.dollar_progress] = function(_, result, ctx)
@@ -56,7 +57,7 @@ M[ms.dollar_progress] = function(_, result, ctx)
})
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_workDoneProgress_create
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_workDoneProgress_create
---@param result lsp.WorkDoneProgressCreateParams
---@param ctx lsp.HandlerContext
M[ms.window_workDoneProgress_create] = function(_, result, ctx)
@@ -69,7 +70,7 @@ M[ms.window_workDoneProgress_create] = function(_, result, ctx)
return vim.NIL
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessageRequest
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessageRequest
---@param result lsp.ShowMessageRequestParams
M[ms.window_showMessageRequest] = function(_, result)
local actions = result.actions or {}
@@ -105,11 +106,11 @@ M[ms.window_showMessageRequest] = function(_, result)
end
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_registerCapability
+--- @param result lsp.RegistrationParams
M[ms.client_registerCapability] = function(_, result, ctx)
local client_id = ctx.client_id
- ---@type lsp.Client
- local client = vim.lsp.get_client_by_id(client_id)
+ local client = assert(vim.lsp.get_client_by_id(client_id))
client.dynamic_capabilities:register(result.registrations)
for bufnr, _ in pairs(client.attached_buffers) do
@@ -120,7 +121,7 @@ M[ms.client_registerCapability] = function(_, result, ctx)
local unsupported = {}
for _, reg in ipairs(result.registrations) do
if reg.method == ms.workspace_didChangeWatchedFiles then
- require('vim.lsp._watchfiles').register(reg, ctx)
+ vim.lsp._watchfiles.register(reg, ctx)
elseif not client.dynamic_capabilities:supports_registration(reg.method) then
unsupported[#unsupported + 1] = reg.method
end
@@ -136,21 +137,22 @@ M[ms.client_registerCapability] = function(_, result, ctx)
return vim.NIL
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#client_unregisterCapability
+--- @param result lsp.UnregistrationParams
M[ms.client_unregisterCapability] = function(_, result, ctx)
local client_id = ctx.client_id
- local client = vim.lsp.get_client_by_id(client_id)
+ local client = assert(vim.lsp.get_client_by_id(client_id))
client.dynamic_capabilities:unregister(result.unregisterations)
for _, unreg in ipairs(result.unregisterations) do
if unreg.method == ms.workspace_didChangeWatchedFiles then
- require('vim.lsp._watchfiles').unregister(unreg, ctx)
+ vim.lsp._watchfiles.unregister(unreg, ctx)
end
end
return vim.NIL
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
M[ms.workspace_applyEdit] = function(_, workspace_edit, ctx)
assert(
workspace_edit,
@@ -158,7 +160,7 @@ M[ms.workspace_applyEdit] = function(_, workspace_edit, ctx)
)
-- TODO(ashkan) Do something more with label?
local client_id = ctx.client_id
- local client = vim.lsp.get_client_by_id(client_id)
+ local client = assert(vim.lsp.get_client_by_id(client_id))
if workspace_edit.label then
print('Workspace edit', workspace_edit.label)
end
@@ -170,7 +172,16 @@ M[ms.workspace_applyEdit] = function(_, workspace_edit, ctx)
}
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_configuration
+---@param table table e.g., { foo = { bar = "z" } }
+---@param section string indicating the field of the table, e.g., "foo.bar"
+---@return any|nil setting value read from the table, or `nil` not found
+local function lookup_section(table, section)
+ local keys = vim.split(section, '.', { plain = true }) --- @type string[]
+ return vim.tbl_get(table, unpack(keys))
+end
+
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_configuration
+--- @param result lsp.ConfigurationParams
M[ms.workspace_configuration] = function(_, result, ctx)
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
@@ -189,10 +200,13 @@ M[ms.workspace_configuration] = function(_, result, ctx)
local response = {}
for _, item in ipairs(result.items) do
if item.section then
- local value = util.lookup_section(client.config.settings, item.section)
+ local value = lookup_section(client.settings, item.section)
-- For empty sections with no explicit '' key, return settings as is
- if value == vim.NIL and item.section == '' then
- value = client.config.settings or vim.NIL
+ if value == nil and item.section == '' then
+ value = client.settings
+ end
+ if value == nil then
+ value = vim.NIL
end
table.insert(response, value)
end
@@ -200,7 +214,7 @@ M[ms.workspace_configuration] = function(_, result, ctx)
return response
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_workspaceFolders
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_workspaceFolders
M[ms.workspace_workspaceFolders] = function(_, _, ctx)
local client_id = ctx.client_id
local client = vim.lsp.get_client_by_id(client_id)
@@ -212,41 +226,42 @@ M[ms.workspace_workspaceFolders] = function(_, _, ctx)
end
M[ms.textDocument_publishDiagnostics] = function(...)
- return require('vim.lsp.diagnostic').on_publish_diagnostics(...)
+ return vim.lsp.diagnostic.on_publish_diagnostics(...)
end
M[ms.textDocument_diagnostic] = function(...)
- return require('vim.lsp.diagnostic').on_diagnostic(...)
+ return vim.lsp.diagnostic.on_diagnostic(...)
end
M[ms.textDocument_codeLens] = function(...)
- return require('vim.lsp.codelens').on_codelens(...)
+ return vim.lsp.codelens.on_codelens(...)
end
M[ms.textDocument_inlayHint] = function(...)
- return require('vim.lsp.inlay_hint').on_inlayhint(...)
+ return vim.lsp.inlay_hint.on_inlayhint(...)
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_references
M[ms.textDocument_references] = function(_, result, ctx, config)
if not result or vim.tbl_isempty(result) then
vim.notify('No references found')
- else
- local client = vim.lsp.get_client_by_id(ctx.client_id)
- config = config or {}
- local title = 'References'
- local items = util.locations_to_items(result, client.offset_encoding)
+ return
+ end
- if config.loclist then
- vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx })
- api.nvim_command('lopen')
- elseif config.on_list then
- assert(type(config.on_list) == 'function', 'on_list is not a function')
- config.on_list({ title = title, items = items, context = ctx })
- else
- vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx })
- api.nvim_command('botright copen')
- end
+ local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
+ config = config or {}
+ local title = 'References'
+ local items = util.locations_to_items(result, client.offset_encoding)
+
+ if config.loclist then
+ vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx })
+ api.nvim_command('lopen')
+ elseif config.on_list then
+ assert(type(config.on_list) == 'function', 'on_list is not a function')
+ config.on_list({ title = title, items = items, context = ctx })
+ else
+ vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx })
+ api.nvim_command('botright copen')
end
end
@@ -259,31 +274,32 @@ end
---
---@param map_result function `((resp, bufnr) -> list)` to convert the response
---@param entity string name of the resource used in a `not found` error message
----@param title_fn function Function to call to generate list title
+---@param title_fn fun(ctx: lsp.HandlerContext): string Function to call to generate list title
+---@return lsp.Handler
local function response_to_list(map_result, entity, title_fn)
return function(_, result, ctx, config)
if not result or vim.tbl_isempty(result) then
vim.notify('No ' .. entity .. ' found')
+ return
+ end
+ config = config or {}
+ local title = title_fn(ctx)
+ local items = map_result(result, ctx.bufnr)
+
+ if config.loclist then
+ vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx })
+ api.nvim_command('lopen')
+ elseif config.on_list then
+ assert(type(config.on_list) == 'function', 'on_list is not a function')
+ config.on_list({ title = title, items = items, context = ctx })
else
- config = config or {}
- local title = title_fn(ctx)
- local items = map_result(result, ctx.bufnr)
-
- if config.loclist then
- vim.fn.setloclist(0, {}, ' ', { title = title, items = items, context = ctx })
- api.nvim_command('lopen')
- elseif config.on_list then
- assert(type(config.on_list) == 'function', 'on_list is not a function')
- config.on_list({ title = title, items = items, context = ctx })
- else
- vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx })
- api.nvim_command('botright copen')
- end
+ vim.fn.setqflist({}, ' ', { title = title, items = items, context = ctx })
+ api.nvim_command('botright copen')
end
end
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentSymbol
M[ms.textDocument_documentSymbol] = response_to_list(
util.symbols_to_items,
'document symbols',
@@ -293,45 +309,46 @@ M[ms.textDocument_documentSymbol] = response_to_list(
end
)
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_symbol
M[ms.workspace_symbol] = response_to_list(util.symbols_to_items, 'symbols', function(ctx)
return string.format("Symbols matching '%s'", ctx.params.query)
end)
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rename
M[ms.textDocument_rename] = function(_, result, ctx, _)
if not result then
vim.notify("Language server couldn't provide rename result", vim.log.levels.INFO)
return
end
- local client = vim.lsp.get_client_by_id(ctx.client_id)
+ local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
util.apply_workspace_edit(result, client.offset_encoding)
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_rangeFormatting
M[ms.textDocument_rangeFormatting] = function(_, result, ctx, _)
if not result then
return
end
- local client = vim.lsp.get_client_by_id(ctx.client_id)
+ local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
util.apply_text_edits(result, ctx.bufnr, client.offset_encoding)
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting
M[ms.textDocument_formatting] = function(_, result, ctx, _)
if not result then
return
end
- local client = vim.lsp.get_client_by_id(ctx.client_id)
+ local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
util.apply_text_edits(result, ctx.bufnr, client.offset_encoding)
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
M[ms.textDocument_completion] = function(_, result, _, _)
if vim.tbl_isempty(result or {}) then
return
end
- local row, col = unpack(api.nvim_win_get_cursor(0))
+ local cursor = api.nvim_win_get_cursor(0)
+ local row, col = cursor[1], cursor[2]
local line = assert(api.nvim_buf_get_lines(0, row - 1, row, false)[1])
local line_to_cursor = line:sub(col + 1)
local textMatch = vim.fn.match(line_to_cursor, '\\k*$')
@@ -354,6 +371,9 @@ end
--- )
--- ```
---
+---@param _ lsp.ResponseError?
+---@param result lsp.Hover
+---@param ctx lsp.HandlerContext
---@param config table Configuration table.
--- - border: (default=nil)
--- - Add borders to the floating window
@@ -388,20 +408,21 @@ function M.hover(_, result, ctx, config)
return util.open_floating_preview(contents, format, config)
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover
M[ms.textDocument_hover] = M.hover
--- Jumps to a location. Used as a handler for multiple LSP methods.
---@param _ nil not used
---@param result (table) result of LSP method; a location or a list of locations.
----@param ctx (table) table containing the context of the request, including the method
+---@param ctx (lsp.HandlerContext) table containing the context of the request, including the method
+---@param config? vim.lsp.LocationOpts
---(`textDocument/definition` can return `Location` or `Location[]`
local function location_handler(_, result, ctx, config)
if result == nil or vim.tbl_isempty(result) then
- local _ = log.info() and log.info(ctx.method, 'No location found')
+ log.info(ctx.method, 'No location found')
return nil
end
- local client = vim.lsp.get_client_by_id(ctx.client_id)
+ local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
config = config or {}
@@ -427,13 +448,13 @@ local function location_handler(_, result, ctx, config)
api.nvim_command('botright copen')
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_declaration
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_declaration
M[ms.textDocument_declaration] = location_handler
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition
M[ms.textDocument_definition] = location_handler
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_typeDefinition
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_typeDefinition
M[ms.textDocument_typeDefinition] = location_handler
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_implementation
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_implementation
M[ms.textDocument_implementation] = location_handler
--- |lsp-handler| for the method "textDocument/signatureHelp".
@@ -449,8 +470,9 @@ M[ms.textDocument_implementation] = location_handler
--- )
--- ```
---
----@param result table Response from the language server
----@param ctx table Client context
+---@param _ lsp.ResponseError?
+---@param result lsp.SignatureHelp Response from the language server
+---@param ctx lsp.HandlerContext Client context
---@param config table Configuration table.
--- - border: (default=nil)
--- - Add borders to the floating window
@@ -470,7 +492,7 @@ function M.signature_help(_, result, ctx, config)
end
return
end
- local client = vim.lsp.get_client_by_id(ctx.client_id)
+ local client = assert(vim.lsp.get_client_by_id(ctx.client_id))
local triggers =
vim.tbl_get(client.server_capabilities, 'signatureHelpProvider', 'triggerCharacters')
local ft = vim.bo[ctx.bufnr].filetype
@@ -490,10 +512,10 @@ function M.signature_help(_, result, ctx, config)
return fbuf, fwin
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_signatureHelp
M[ms.textDocument_signatureHelp] = M.signature_help
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_documentHighlight
M[ms.textDocument_documentHighlight] = function(_, result, ctx, _)
if not result then
return
@@ -506,21 +528,22 @@ M[ms.textDocument_documentHighlight] = function(_, result, ctx, _)
util.buf_highlight_references(ctx.bufnr, result, client.offset_encoding)
end
----@private
+--- @private
---
--- Displays call hierarchy in the quickfix window.
---
----@param direction `"from"` for incoming calls and `"to"` for outgoing calls
----@return function
---- `CallHierarchyIncomingCall[]` if {direction} is `"from"`,
---- `CallHierarchyOutgoingCall[]` if {direction} is `"to"`,
-local make_call_hierarchy_handler = function(direction)
+--- @param direction 'from'|'to' `"from"` for incoming calls and `"to"` for outgoing calls
+--- @overload fun(direction:'from'): fun(_, result: lsp.CallHierarchyIncomingCall[]?)
+--- @overload fun(direction:'to'): fun(_, result: lsp.CallHierarchyOutgoingCall[]?)
+local function make_call_hierarchy_handler(direction)
+ --- @param result lsp.CallHierarchyIncomingCall[]|lsp.CallHierarchyOutgoingCall[]
return function(_, result)
if not result then
return
end
local items = {}
for _, call_hierarchy_call in pairs(result) do
+ --- @type lsp.CallHierarchyItem
local call_hierarchy_item = call_hierarchy_call[direction]
for _, range in pairs(call_hierarchy_call.fromRanges) do
table.insert(items, {
@@ -536,13 +559,14 @@ local make_call_hierarchy_handler = function(direction)
end
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_incomingCalls
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_incomingCalls
M[ms.callHierarchy_incomingCalls] = make_call_hierarchy_handler('from')
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_outgoingCalls
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#callHierarchy_outgoingCalls
M[ms.callHierarchy_outgoingCalls] = make_call_hierarchy_handler('to')
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_logMessage
+--- @see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_logMessage
+--- @param result lsp.LogMessageParams
M[ms.window_logMessage] = function(_, result, ctx, _)
local message_type = result.type
local message = result.message
@@ -564,7 +588,8 @@ M[ms.window_logMessage] = function(_, result, ctx, _)
return result
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessage
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showMessage
+--- @param result lsp.ShowMessageParams
M[ms.window_showMessage] = function(_, result, ctx, _)
local message_type = result.type
local message = result.message
@@ -583,7 +608,8 @@ M[ms.window_showMessage] = function(_, result, ctx, _)
return result
end
---see: https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showDocument
+--- @see # https://microsoft.github.io/language-server-protocol/specifications/specification-current/#window_showDocument
+--- @param result lsp.ShowDocumentParams
M[ms.window_showDocument] = function(_, result, ctx, _)
local uri = result.uri
@@ -626,19 +652,25 @@ end
---@see https://microsoft.github.io/language-server-protocol/specification/#workspace_inlayHint_refresh
M[ms.workspace_inlayHint_refresh] = function(err, result, ctx, config)
- return require('vim.lsp.inlay_hint').on_refresh(err, result, ctx, config)
+ return vim.lsp.inlay_hint.on_refresh(err, result, ctx, config)
+end
+
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#semanticTokens_refreshRequest
+M[ms.workspace_semanticTokens_refresh] = function(err, result, ctx, _config)
+ return vim.lsp.semantic_tokens._refresh(err, result, ctx)
end
-- Add boilerplate error validation and logging for all of these.
for k, fn in pairs(M) do
M[k] = function(err, result, ctx, config)
- local _ = log.trace()
- and log.trace('default_handler', ctx.method, {
+ if log.trace() then
+ log.trace('default_handler', ctx.method, {
err = err,
result = result,
ctx = vim.inspect(ctx),
config = config,
})
+ end
if err then
-- LSP spec:
diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua
index fe06006108..797a1097f9 100644
--- a/runtime/lua/vim/lsp/health.lua
+++ b/runtime/lua/vim/lsp/health.lua
@@ -1,13 +1,12 @@
local M = {}
---- Performs a healthcheck for LSP
-function M.check()
- local report_info = vim.health.info
- local report_warn = vim.health.warn
+local report_info = vim.health.info
+local report_warn = vim.health.warn
- local log = require('vim.lsp.log')
+local function check_log()
+ local log = vim.lsp.log
local current_log_level = log.get_level()
- local log_level_string = log.levels[current_log_level]
+ local log_level_string = log.levels[current_log_level] ---@type string
report_info(string.format('LSP log level : %s', log_level_string))
if current_log_level < log.levels.WARN then
@@ -27,9 +26,11 @@ function M.check()
local report_fn = (log_size / 1000000 > 100 and report_warn or report_info)
report_fn(string.format('Log size: %d KB', log_size / 1000))
+end
- local clients = vim.lsp.get_clients()
+local function check_active_clients()
vim.health.start('vim.lsp: Active Clients')
+ local clients = vim.lsp.get_clients()
if next(clients) then
for _, client in pairs(clients) do
local attached_to = table.concat(vim.tbl_keys(client.attached_buffers or {}), ',')
@@ -38,7 +39,7 @@ function M.check()
'%s (id=%s, root_dir=%s, attached_to=[%s])',
client.name,
client.id,
- vim.fn.fnamemodify(client.config.root_dir, ':~'),
+ vim.fn.fnamemodify(client.root_dir, ':~'),
attached_to
)
)
@@ -48,4 +49,33 @@ function M.check()
end
end
+local function check_watcher()
+ vim.health.start('vim.lsp: File watcher')
+ local watchfunc = vim.lsp._watchfiles._watchfunc
+ assert(watchfunc)
+ local watchfunc_name --- @type string
+ if watchfunc == vim._watch.watch then
+ watchfunc_name = 'libuv-watch'
+ elseif watchfunc == vim._watch.watchdirs then
+ watchfunc_name = 'libuv-watchdirs'
+ elseif watchfunc == vim._watch.fswatch then
+ watchfunc_name = 'fswatch'
+ else
+ local nm = debug.getinfo(watchfunc, 'S').source
+ watchfunc_name = string.format('Custom (%s)', nm)
+ end
+
+ report_info('File watch backend: ' .. watchfunc_name)
+ if watchfunc_name == 'libuv-watchdirs' then
+ report_warn('libuv-watchdirs has known performance issues. Consider installing fswatch.')
+ end
+end
+
+--- Performs a healthcheck for LSP
+function M.check()
+ check_log()
+ check_active_clients()
+ check_watcher()
+end
+
return M
diff --git a/runtime/lua/vim/lsp/inlay_hint.lua b/runtime/lua/vim/lsp/inlay_hint.lua
index 4f7a3b0076..ec676ea97f 100644
--- a/runtime/lua/vim/lsp/inlay_hint.lua
+++ b/runtime/lua/vim/lsp/inlay_hint.lua
@@ -4,12 +4,12 @@ local ms = require('vim.lsp.protocol').Methods
local api = vim.api
local M = {}
----@class lsp.inlay_hint.bufstate
+---@class (private) vim.lsp.inlay_hint.bufstate
---@field version? integer
----@field client_hint? table<integer, table<integer, lsp.InlayHint[]>> client_id -> (lnum -> hints)
+---@field client_hints? table<integer, table<integer, lsp.InlayHint[]>> client_id -> (lnum -> hints)
---@field applied table<integer, integer> Last version of hints applied to this line
---@field enabled boolean Whether inlay hints are enabled for this buffer
----@type table<integer, lsp.inlay_hint.bufstate>
+---@type table<integer, vim.lsp.inlay_hint.bufstate>
local bufstates = {}
local namespace = api.nvim_create_namespace('vim_lsp_inlayhint')
@@ -17,13 +17,15 @@ local augroup = api.nvim_create_augroup('vim_lsp_inlayhint', {})
--- |lsp-handler| for the method `textDocument/inlayHint`
--- Store hints for a specific buffer and client
+---@param result lsp.InlayHint[]?
+---@param ctx lsp.HandlerContext
---@private
function M.on_inlayhint(err, result, ctx, _)
if err then
- local _ = log.error() and log.error('inlayhint', err)
+ log.error('inlayhint', err)
return
end
- local bufnr = ctx.bufnr
+ local bufnr = assert(ctx.bufnr)
if util.buf_versions[bufnr] ~= ctx.version then
return
end
@@ -35,12 +37,12 @@ function M.on_inlayhint(err, result, ctx, _)
if not bufstate or not bufstate.enabled then
return
end
- if not (bufstate.client_hint and bufstate.version) then
- bufstate.client_hint = vim.defaulttable()
+ if not (bufstate.client_hints and bufstate.version) then
+ bufstate.client_hints = vim.defaulttable()
bufstate.version = ctx.version
end
- local hints_by_client = bufstate.client_hint
- local client = vim.lsp.get_client_by_id(client_id)
+ local hints_by_client = bufstate.client_hints
+ local client = assert(vim.lsp.get_client_by_id(client_id))
local new_hints_by_lnum = vim.defaulttable()
local num_unprocessed = #result
@@ -52,6 +54,8 @@ function M.on_inlayhint(err, result, ctx, _)
end
local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false)
+ ---@param position lsp.Position
+ ---@return integer
local function pos_to_byte(position)
local col = position.character
if col > 0 then
@@ -78,6 +82,7 @@ function M.on_inlayhint(err, result, ctx, _)
end
--- |lsp-handler| for the method `textDocument/inlayHint/refresh`
+---@param ctx lsp.HandlerContext
---@private
function M.on_refresh(err, _, ctx, _)
if err then
@@ -98,11 +103,14 @@ function M.on_refresh(err, _, ctx, _)
return vim.NIL
end
---- @class vim.lsp.inlay_hint.get.filter
+--- Optional filters |kwargs|:
+--- @class vim.lsp.inlay_hint.get.Filter
+--- @inlinedoc
--- @field bufnr integer?
--- @field range lsp.Range?
----
+
--- @class vim.lsp.inlay_hint.get.ret
+--- @inlinedoc
--- @field bufnr integer
--- @field client_id integer
--- @field inlay_hint lsp.InlayHint
@@ -125,17 +133,8 @@ end
--- })
--- ```
---
---- @param filter vim.lsp.inlay_hint.get.filter?
---- Optional filters |kwargs|:
---- - bufnr (integer?): 0 for current buffer
---- - range (lsp.Range?)
----
+--- @param filter vim.lsp.inlay_hint.get.Filter?
--- @return vim.lsp.inlay_hint.get.ret[]
---- Each list item is a table with the following fields:
---- - bufnr (integer)
---- - client_id (integer)
---- - inlay_hint (lsp.InlayHint)
----
--- @since 12
function M.get(filter)
vim.validate({ filter = { filter, 'table', true } })
@@ -155,7 +154,7 @@ function M.get(filter)
end
local bufstate = bufstates[bufnr]
- if not (bufstate and bufstate.client_hint) then
+ if not (bufstate and bufstate.client_hints) then
return {}
end
@@ -178,7 +177,7 @@ function M.get(filter)
--- @type vim.lsp.inlay_hint.get.ret[]
local hints = {}
for _, client in pairs(clients) do
- local hints_by_lnum = bufstate.client_hint[client.id]
+ local hints_by_lnum = bufstate.client_hints[client.id]
if hints_by_lnum then
for lnum = range.start.line, range['end'].line do
local line_hints = hints_by_lnum[lnum] or {}
@@ -211,11 +210,11 @@ local function clear(bufnr)
return
end
local bufstate = bufstates[bufnr]
- local client_lens = (bufstate or {}).client_hint or {}
- local client_ids = vim.tbl_keys(client_lens)
+ local client_lens = (bufstate or {}).client_hints or {}
+ local client_ids = vim.tbl_keys(client_lens) --- @type integer[]
for _, iter_client_id in ipairs(client_ids) do
if bufstate then
- bufstate.client_hint[iter_client_id] = {}
+ bufstate.client_hints[iter_client_id] = {}
end
end
api.nvim_buf_clear_namespace(bufnr, namespace, 0, -1)
@@ -236,7 +235,7 @@ end
--- Refresh inlay hints, only if we have attached clients that support it
---@param bufnr (integer) Buffer handle, or 0 for current
----@param opts? table Additional options to pass to util._refresh
+---@param opts? vim.lsp.util._refresh.Opts Additional options to pass to util._refresh
---@private
local function _refresh(bufnr, opts)
opts = opts or {}
@@ -312,7 +311,7 @@ api.nvim_set_decoration_provider(namespace, {
if bufstate.version ~= util.buf_versions[bufnr] then
return
end
- local hints_by_client = bufstate.client_hint
+ local hints_by_client = assert(bufstate.client_hints)
for lnum = topline, botline do
if bufstate.applied[lnum] ~= bufstate.version then
@@ -321,14 +320,15 @@ api.nvim_set_decoration_provider(namespace, {
local line_hints = hints_by_lnum[lnum] or {}
for _, hint in pairs(line_hints) do
local text = ''
- if type(hint.label) == 'string' then
- text = hint.label
+ local label = hint.label
+ if type(label) == 'string' then
+ text = label
else
- for _, part in ipairs(hint.label) do
+ for _, part in ipairs(label) do
text = text .. part.value
end
end
- local vt = {}
+ local vt = {} --- @type {[1]: string, [2]: string?}[]
if hint.paddingLeft then
vt[#vt + 1] = { ' ' }
end
@@ -360,7 +360,13 @@ function M.is_enabled(bufnr)
return bufstates[bufnr] and bufstates[bufnr].enabled or false
end
---- Enable/disable/toggle inlay hints for a buffer
+--- Enables or disables inlay hints for a buffer.
+---
+--- To "toggle", pass the inverse of `is_enabled()`:
+---
+--- ```lua
+--- vim.lsp.inlay_hint.enable(0, not vim.lsp.inlay_hint.is_enabled())
+--- ```
---
--- @param bufnr (integer|nil) Buffer handle, or 0 or nil for current
--- @param enable (boolean|nil) true/nil to enable, false to disable
diff --git a/runtime/lua/vim/lsp/log.lua b/runtime/lua/vim/lsp/log.lua
index 6d2e0bc292..9f2bd71158 100644
--- a/runtime/lua/vim/lsp/log.lua
+++ b/runtime/lua/vim/lsp/log.lua
@@ -2,138 +2,144 @@
local log = {}
+local log_levels = vim.log.levels
+
--- Log level dictionary with reverse lookup as well.
---
--- Can be used to lookup the number from the name or the name from the number.
--- Levels by name: "TRACE", "DEBUG", "INFO", "WARN", "ERROR", "OFF"
--- Level numbers begin with "TRACE" at 0
+--- @type table<string|integer, string|integer>
--- @nodoc
-log.levels = vim.deepcopy(vim.log.levels)
+log.levels = vim.deepcopy(log_levels)
-- Default log level is warn.
-local current_log_level = log.levels.WARN
+local current_log_level = log_levels.WARN
+
local log_date_format = '%F %H:%M:%S'
-local format_func = function(arg)
+
+local function format_func(arg)
return vim.inspect(arg, { newline = '' })
end
-do
- local function notify(msg, level)
- if vim.in_fast_event() then
- vim.schedule(function()
- vim.notify(msg, level)
- end)
- else
+local function notify(msg, level)
+ if vim.in_fast_event() then
+ vim.schedule(function()
vim.notify(msg, level)
- end
+ end)
+ else
+ vim.notify(msg, level)
end
+end
+
+local logfilename = vim.fs.joinpath(vim.fn.stdpath('log'), 'lsp.log')
+
+-- TODO: Ideally the directory should be created in open_logfile(), right
+-- before opening the log file, but open_logfile() can be called from libuv
+-- callbacks, where using fn.mkdir() is not allowed.
+vim.fn.mkdir(vim.fn.stdpath('log'), 'p')
+
+--- Returns the log filename.
+---@return string log filename
+function log.get_filename()
+ return logfilename
+end
- local path_sep = vim.uv.os_uname().version:match('Windows') and '\\' or '/'
- local function path_join(...)
- return table.concat(vim.tbl_flatten({ ... }), path_sep)
+--- @type file*?, string?
+local logfile, openerr
+
+--- Opens log file. Returns true if file is open, false on error
+local function open_logfile()
+ -- Try to open file only once
+ if logfile then
+ return true
+ end
+ if openerr then
+ return false
end
- local logfilename = path_join(vim.fn.stdpath('log'), 'lsp.log')
- -- TODO: Ideally the directory should be created in open_logfile(), right
- -- before opening the log file, but open_logfile() can be called from libuv
- -- callbacks, where using fn.mkdir() is not allowed.
- vim.fn.mkdir(vim.fn.stdpath('log'), 'p')
+ logfile, openerr = io.open(logfilename, 'a+')
+ if not logfile then
+ local err_msg = string.format('Failed to open LSP client log file: %s', openerr)
+ notify(err_msg, log_levels.ERROR)
+ return false
+ end
- --- Returns the log filename.
- ---@return string log filename
- function log.get_filename()
- return logfilename
+ local log_info = vim.uv.fs_stat(logfilename)
+ if log_info and log_info.size > 1e9 then
+ local warn_msg = string.format(
+ 'LSP client log is large (%d MB): %s',
+ log_info.size / (1000 * 1000),
+ logfilename
+ )
+ notify(warn_msg)
end
- local logfile, openerr
- --- Opens log file. Returns true if file is open, false on error
- local function open_logfile()
- -- Try to open file only once
- if logfile then
+ -- Start message for logging
+ logfile:write(string.format('[START][%s] LSP logging initiated\n', os.date(log_date_format)))
+ return true
+end
+
+for level, levelnr in pairs(log_levels) do
+ -- Also export the log level on the root object.
+ log[level] = levelnr
+
+ -- Add a reverse lookup.
+ log.levels[levelnr] = level
+end
+
+--- @param level string
+--- @param levelnr integer
+--- @return fun(...:any): boolean?
+local function create_logger(level, levelnr)
+ return function(...)
+ if levelnr < current_log_level then
+ return false
+ end
+ local argc = select('#', ...)
+ if argc == 0 then
return true
end
- if openerr then
+ if not open_logfile() then
return false
end
-
- logfile, openerr = io.open(logfilename, 'a+')
- if not logfile then
- local err_msg = string.format('Failed to open LSP client log file: %s', openerr)
- notify(err_msg, vim.log.levels.ERROR)
- return false
+ local info = debug.getinfo(2, 'Sl')
+ local header = string.format(
+ '[%s][%s] ...%s:%s',
+ level,
+ os.date(log_date_format),
+ info.short_src:sub(-16),
+ info.currentline
+ )
+ local parts = { header }
+ for i = 1, argc do
+ local arg = select(i, ...)
+ table.insert(parts, arg == nil and 'nil' or format_func(arg))
end
+ assert(logfile)
+ logfile:write(table.concat(parts, '\t'), '\n')
+ logfile:flush()
+ end
+end
- local log_info = vim.uv.fs_stat(logfilename)
- if log_info and log_info.size > 1e9 then
- local warn_msg = string.format(
- 'LSP client log is large (%d MB): %s',
- log_info.size / (1000 * 1000),
- logfilename
- )
- notify(warn_msg)
- end
+-- If called without arguments, it will check whether the log level is
+-- greater than or equal to this one. When called with arguments, it will
+-- log at that level (if applicable, it is checked either way).
- -- Start message for logging
- logfile:write(string.format('[START][%s] LSP logging initiated\n', os.date(log_date_format)))
- return true
- end
+--- @nodoc
+log.debug = create_logger('DEBUG', log_levels.DEBUG)
- for level, levelnr in pairs(log.levels) do
- -- Also export the log level on the root object.
- log[level] = levelnr
- -- FIXME: DOC
- -- Should be exposed in the vim docs.
- --
- -- Set the lowercase name as the main use function.
- -- If called without arguments, it will check whether the log level is
- -- greater than or equal to this one. When called with arguments, it will
- -- log at that level (if applicable, it is checked either way).
- --
- -- Recommended usage:
- -- ```
- -- local _ = log.warn() and log.warn("123")
- -- ```
- --
- -- This way you can avoid string allocations if the log level isn't high enough.
- if level ~= 'OFF' then
- log[level:lower()] = function(...)
- local argc = select('#', ...)
- if levelnr < current_log_level then
- return false
- end
- if argc == 0 then
- return true
- end
- if not open_logfile() then
- return false
- end
- local info = debug.getinfo(2, 'Sl')
- local header = string.format(
- '[%s][%s] ...%s:%s',
- level,
- os.date(log_date_format),
- string.sub(info.short_src, #info.short_src - 15),
- info.currentline
- )
- local parts = { header }
- for i = 1, argc do
- local arg = select(i, ...)
- if arg == nil then
- table.insert(parts, 'nil')
- else
- table.insert(parts, format_func(arg))
- end
- end
- logfile:write(table.concat(parts, '\t'), '\n')
- logfile:flush()
- end
- end
- end
-end
+--- @nodoc
+log.error = create_logger('ERROR', log_levels.ERROR)
--- This is put here on purpose after the loop above so that it doesn't
--- interfere with iterating the levels
-vim.tbl_add_reverse_lookup(log.levels)
+--- @nodoc
+log.info = create_logger('INFO', log_levels.INFO)
+
+--- @nodoc
+log.trace = create_logger('TRACE', log_levels.TRACE)
+
+--- @nodoc
+log.warn = create_logger('WARN', log_levels.WARN)
--- Sets the current log level.
---@param level (string|integer) One of `vim.lsp.log.levels`
@@ -163,7 +169,7 @@ end
--- Checks whether the level is sufficient for logging.
---@param level integer log level
----@returns (bool) true if would log, false if not
+---@return bool : true if would log, false if not
function log.should_log(level)
return level >= current_log_level
end
diff --git a/runtime/lua/vim/lsp/protocol.lua b/runtime/lua/vim/lsp/protocol.lua
index a7c3914834..599f02425e 100644
--- a/runtime/lua/vim/lsp/protocol.lua
+++ b/runtime/lua/vim/lsp/protocol.lua
@@ -1,24 +1,17 @@
--- Protocol for the Microsoft Language Server Protocol (mslsp)
-
-local protocol = {}
+--- @diagnostic disable: duplicate-doc-alias
---[=[
----@private
---- Useful for interfacing with:
---- https://github.com/microsoft/language-server-protocol/raw/gh-pages/_specifications/specification-3-14.md
-function transform_schema_comments()
- nvim.command [[silent! '<,'>g/\/\*\*\|\*\/\|^$/d]]
- nvim.command [[silent! '<,'>s/^\(\s*\) \* \=\(.*\)/\1--\2/]]
-end
----@private
-function transform_schema_to_table()
- transform_schema_comments()
- nvim.command [[silent! '<,'>s/: \S\+//]]
- nvim.command [[silent! '<,'>s/export const //]]
- nvim.command [[silent! '<,'>s/export namespace \(\S*\)\s*{/protocol.\1 = {/]]
- nvim.command [[silent! '<,'>s/namespace \(\S*\)\s*{/protocol.\1 = {/]]
+---@param tbl table<string, string|number>
+local function get_value_set(tbl)
+ local value_set = {}
+ for _, v in pairs(tbl) do
+ table.insert(value_set, v)
+ end
+ table.sort(value_set)
+ return value_set
end
---]=]
+
+-- Protocol for the Microsoft Language Server Protocol (mslsp)
+local protocol = {}
local constants = {
--- @enum lsp.DiagnosticSeverity
@@ -313,10 +306,13 @@ local constants = {
},
}
-for k, v in pairs(constants) do
- local tbl = vim.deepcopy(v)
- vim.tbl_add_reverse_lookup(tbl)
- protocol[k] = tbl
+for k1, v1 in pairs(constants) do
+ local tbl = vim.deepcopy(v1, true)
+ for _, k2 in ipairs(vim.tbl_keys(tbl)) do
+ local v2 = tbl[k2]
+ tbl[v2] = k2
+ end
+ protocol[k1] = tbl
end
--[=[
@@ -722,11 +718,7 @@ function protocol.make_client_capabilities()
codeActionLiteralSupport = {
codeActionKind = {
- valueSet = (function()
- local res = vim.tbl_values(constants.CodeActionKind)
- table.sort(res)
- return res
- end)(),
+ valueSet = get_value_set(constants.CodeActionKind),
},
},
isPreferredSupport = true,
@@ -751,18 +743,18 @@ function protocol.make_client_capabilities()
commitCharactersSupport = false,
preselectSupport = false,
deprecatedSupport = false,
- documentationFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText },
+ documentationFormat = { constants.MarkupKind.Markdown, constants.MarkupKind.PlainText },
},
completionItemKind = {
- valueSet = (function()
- local res = {}
- for k in ipairs(protocol.CompletionItemKind) do
- if type(k) == 'number' then
- table.insert(res, k)
- end
- end
- return res
- end)(),
+ valueSet = get_value_set(constants.CompletionItemKind),
+ },
+ completionList = {
+ itemDefaults = {
+ 'editRange',
+ 'insertTextFormat',
+ 'insertTextMode',
+ 'data',
+ },
},
-- TODO(tjdevries): Implement this
@@ -783,13 +775,13 @@ function protocol.make_client_capabilities()
},
hover = {
dynamicRegistration = true,
- contentFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText },
+ contentFormat = { constants.MarkupKind.Markdown, constants.MarkupKind.PlainText },
},
signatureHelp = {
dynamicRegistration = false,
signatureInformation = {
activeParameterSupport = true,
- documentationFormat = { protocol.MarkupKind.Markdown, protocol.MarkupKind.PlainText },
+ documentationFormat = { constants.MarkupKind.Markdown, constants.MarkupKind.PlainText },
parameterInformation = {
labelOffsetSupport = true,
},
@@ -804,15 +796,7 @@ function protocol.make_client_capabilities()
documentSymbol = {
dynamicRegistration = false,
symbolKind = {
- valueSet = (function()
- local res = {}
- for k in ipairs(protocol.SymbolKind) do
- if type(k) == 'number' then
- table.insert(res, k)
- end
- end
- return res
- end)(),
+ valueSet = get_value_set(constants.SymbolKind),
},
hierarchicalDocumentSymbolSupport = true,
},
@@ -823,15 +807,7 @@ function protocol.make_client_capabilities()
publishDiagnostics = {
relatedInformation = true,
tagSupport = {
- valueSet = (function()
- local res = {}
- for k in ipairs(protocol.DiagnosticTag) do
- if type(k) == 'number' then
- table.insert(res, k)
- end
- end
- return res
- end)(),
+ valueSet = get_value_set(constants.DiagnosticTag),
},
dataSupport = true,
},
@@ -843,15 +819,7 @@ function protocol.make_client_capabilities()
symbol = {
dynamicRegistration = false,
symbolKind = {
- valueSet = (function()
- local res = {}
- for k in ipairs(protocol.SymbolKind) do
- if type(k) == 'number' then
- table.insert(res, k)
- end
- end
- return res
- end)(),
+ valueSet = get_value_set(constants.SymbolKind),
},
},
configuration = true,
@@ -891,9 +859,9 @@ end
--- Creates a normalized object describing LSP server capabilities.
---@param server_capabilities table Table of capabilities supported by the server
----@return table|nil Normalized table of capabilities
+---@return lsp.ServerCapabilities|nil : Normalized table of capabilities
function protocol.resolve_capabilities(server_capabilities)
- local TextDocumentSyncKind = protocol.TextDocumentSyncKind
+ local TextDocumentSyncKind = protocol.TextDocumentSyncKind ---@type table<string|number, string|number>
local textDocumentSync = server_capabilities.textDocumentSync
if textDocumentSync == nil then
-- Defaults if omitted.
@@ -934,7 +902,7 @@ end
-- Generated by gen_lsp.lua, keep at end of file.
--- LSP method names.
---
----@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#metaModel
+---@see https://microsoft.github.io/language-server-protocol/specification/#metaModel
protocol.Methods = {
--- A request to resolve the incoming calls for a given `CallHierarchyItem`.
--- @since 3.16.0
@@ -1021,16 +989,14 @@ protocol.Methods = {
--- `filterText`, `insertText`, and `textEdit`, must not be changed during resolve.
textDocument_completion = 'textDocument/completion',
--- A request to resolve the type definition locations of a symbol at a given text
- --- document position. The request's parameter is of type [TextDocumentPositionParams]
- --- (#TextDocumentPositionParams) the response is of type {@link Declaration}
- --- or a typed array of {@link DeclarationLink} or a Thenable that resolves
- --- to such.
+ --- document position. The request's parameter is of type {@link TextDocumentPositionParams}
+ --- the response is of type {@link Declaration} or a typed array of {@link DeclarationLink}
+ --- or a Thenable that resolves to such.
textDocument_declaration = 'textDocument/declaration',
--- A request to resolve the definition location of a symbol at a given text
- --- document position. The request's parameter is of type [TextDocumentPosition]
- --- (#TextDocumentPosition) the response is of either type {@link Definition}
- --- or a typed array of {@link DefinitionLink} or a Thenable that resolves
- --- to such.
+ --- document position. The request's parameter is of type {@link TextDocumentPosition}
+ --- the response is of either type {@link Definition} or a typed array of
+ --- {@link DefinitionLink} or a Thenable that resolves to such.
textDocument_definition = 'textDocument/definition',
--- The document diagnostic request definition.
--- @since 3.17.0
@@ -1064,9 +1030,9 @@ protocol.Methods = {
--- that resolves to such.
textDocument_documentColor = 'textDocument/documentColor',
--- Request to resolve a {@link DocumentHighlight} for a given
- --- text document position. The request's parameter is of type [TextDocumentPosition]
- --- (#TextDocumentPosition) the request response is of type [DocumentHighlight[]]
- --- (#DocumentHighlight) or a Thenable that resolves to such.
+ --- text document position. The request's parameter is of type {@link TextDocumentPosition}
+ --- the request response is an array of type {@link DocumentHighlight}
+ --- or a Thenable that resolves to such.
textDocument_documentHighlight = 'textDocument/documentHighlight',
--- A request to provide document links
textDocument_documentLink = 'textDocument/documentLink',
@@ -1080,16 +1046,15 @@ protocol.Methods = {
--- response is of type {@link FoldingRangeList} or a Thenable
--- that resolves to such.
textDocument_foldingRange = 'textDocument/foldingRange',
- --- A request to to format a whole document.
+ --- A request to format a whole document.
textDocument_formatting = 'textDocument/formatting',
--- Request to request hover information at a given text document position. The request's
--- parameter is of type {@link TextDocumentPosition} the response is of
--- type {@link Hover} or a Thenable that resolves to such.
textDocument_hover = 'textDocument/hover',
--- A request to resolve the implementation locations of a symbol at a given text
- --- document position. The request's parameter is of type [TextDocumentPositionParams]
- --- (#TextDocumentPositionParams) the response is of type {@link Definition} or a
- --- Thenable that resolves to such.
+ --- document position. The request's parameter is of type {@link TextDocumentPositionParams}
+ --- the response is of type {@link Definition} or a Thenable that resolves to such.
textDocument_implementation = 'textDocument/implementation',
--- A request to provide inlay hints in a document. The request's parameter is of
--- type {@link InlayHintsParams}, the response is of type
@@ -1100,6 +1065,7 @@ protocol.Methods = {
--- type {@link InlineCompletionParams}, the response is of type
--- {@link InlineCompletion InlineCompletion[]} or a Thenable that resolves to such.
--- @since 3.18.0
+ --- @proposed
textDocument_inlineCompletion = 'textDocument/inlineCompletion',
--- A request to provide inline values in a document. The request's parameter is of
--- type {@link InlineValueParams}, the response is of type
@@ -1155,9 +1121,8 @@ protocol.Methods = {
textDocument_semanticTokens_range = 'textDocument/semanticTokens/range',
textDocument_signatureHelp = 'textDocument/signatureHelp',
--- A request to resolve the type definition locations of a symbol at a given text
- --- document position. The request's parameter is of type [TextDocumentPositionParams]
- --- (#TextDocumentPositionParams) the response is of type {@link Definition} or a
- --- Thenable that resolves to such.
+ --- document position. The request's parameter is of type {@link TextDocumentPositionParams}
+ --- the response is of type {@link Definition} or a Thenable that resolves to such.
textDocument_typeDefinition = 'textDocument/typeDefinition',
--- A document will save notification is sent from the client to the server before
--- the document is actually saved.
@@ -1200,14 +1165,14 @@ protocol.Methods = {
--- symbol's location.
--- @since 3.17.0
workspaceSymbol_resolve = 'workspaceSymbol/resolve',
- --- A request sent from the server to the client to modified certain resources.
+ --- A request sent from the server to the client to modify certain resources.
workspace_applyEdit = 'workspace/applyEdit',
--- A request to refresh all code actions
--- @since 3.16.0
workspace_codeLens_refresh = 'workspace/codeLens/refresh',
--- The 'workspace/configuration' request is sent from the server to the client to fetch a certain
--- configuration setting.
- --- This pull model replaces the old push model were the client signaled configuration change via an
+ --- This pull model replaces the old push model where the client signaled configuration change via an
--- event. If the server still needs to react to configuration changes (since the server caches the
--- result of `workspace/configuration` requests) the server should register for an empty configuration
--- change event and empty the cache if such an event is received.
@@ -1240,9 +1205,12 @@ protocol.Methods = {
--- files were renamed from within the client.
--- @since 3.16.0
workspace_didRenameFiles = 'workspace/didRenameFiles',
- --- A request send from the client to the server to execute a command. The request might return
+ --- A request sent from the client to the server to execute a command. The request might return
--- a workspace edit which the client will apply to the workspace.
workspace_executeCommand = 'workspace/executeCommand',
+ --- @since 3.18.0
+ --- @proposed
+ workspace_foldingRange_refresh = 'workspace/foldingRange/refresh',
--- @since 3.17.0
workspace_inlayHint_refresh = 'workspace/inlayHint/refresh',
--- @since 3.17.0
diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua
index 6ab5708721..984e4f040a 100644
--- a/runtime/lua/vim/lsp/rpc.lua
+++ b/runtime/lua/vim/lsp/rpc.lua
@@ -6,7 +6,7 @@ local validate, schedule, schedule_wrap = vim.validate, vim.schedule, vim.schedu
local is_win = uv.os_uname().version:find('Windows')
--- Checks whether a given path exists and is a directory.
----@param filename (string) path to check
+---@param filename string path to check
---@return boolean
local function is_dir(filename)
local stat = uv.fs_stat(filename)
@@ -15,34 +15,39 @@ end
--- Embeds the given string into a table and correctly computes `Content-Length`.
---
----@param encoded_message (string)
----@return string containing encoded message and `Content-Length` attribute
-local function format_message_with_content_length(encoded_message)
+---@param message string
+---@return string message with `Content-Length` attribute
+local function format_message_with_content_length(message)
return table.concat({
'Content-Length: ',
- tostring(#encoded_message),
+ tostring(#message),
'\r\n\r\n',
- encoded_message,
+ message,
})
end
+---@class (private) vim.lsp.rpc.Headers: {string: any}
+---@field content_length integer
+
--- Parses an LSP Message's header
---
----@param header string: The header to parse.
----@return table # parsed headers
+---@param header string The header to parse.
+---@return vim.lsp.rpc.Headers#parsed headers
local function parse_headers(header)
assert(type(header) == 'string', 'header must be a string')
+ --- @type vim.lsp.rpc.Headers
local headers = {}
for line in vim.gsplit(header, '\r\n', { plain = true }) do
if line == '' then
break
end
+ --- @type string?, string?
local key, value = line:match('^%s*(%S+)%s*:%s*(.+)%s*$')
if key then
- key = key:lower():gsub('%-', '_')
+ key = key:lower():gsub('%-', '_') --- @type string
headers[key] = value
else
- local _ = log.error() and log.error('invalid header line %q', line)
+ log.error('invalid header line %q', line)
error(string.format('invalid header line %q', line))
end
end
@@ -73,15 +78,25 @@ local function request_parser_loop()
-- be searching for.
-- TODO(ashkan) I'd like to remove this, but it seems permanent :(
local buffer_start = buffer:find(header_start_pattern)
+ if not buffer_start then
+ error(
+ string.format(
+ "Headers were expected, a different response was received. The server response was '%s'.",
+ buffer
+ )
+ )
+ end
local headers = parse_headers(buffer:sub(buffer_start, start - 1))
local content_length = headers.content_length
-- Use table instead of just string to buffer the message. It prevents
-- a ton of strings allocating.
-- ref. http://www.lua.org/pil/11.6.html
+ ---@type string[]
local body_chunks = { buffer:sub(finish + 1) }
local body_length = #body_chunks[1]
-- Keep waiting for data until we have enough.
while body_length < content_length do
+ ---@type string
local chunk = coroutine.yield()
or error('Expected more data for the body. The server may have died.') -- TODO hmm.
table.insert(body_chunks, chunk)
@@ -96,17 +111,17 @@ local function request_parser_loop()
end
local body = table.concat(body_chunks)
-- Yield our data.
- buffer = rest
- .. (
- coroutine.yield(headers, body)
- or error('Expected more data for the body. The server may have died.')
- ) -- TODO hmm.
+
+ --- @type string
+ local data = coroutine.yield(headers, body)
+ or error('Expected more data for the body. The server may have died.')
+ buffer = rest .. data
else
-- Get more data since we don't have enough.
- buffer = buffer
- .. (
- coroutine.yield() or error('Expected more data for the header. The server may have died.')
- ) -- TODO hmm.
+ --- @type string
+ local data = coroutine.yield()
+ or error('Expected more data for the header. The server may have died.')
+ buffer = buffer .. data
end
end
end
@@ -115,7 +130,7 @@ local M = {}
--- Mapping of error codes used by the client
--- @nodoc
-M.client_errors = {
+local client_errors = {
INVALID_SERVER_MESSAGE = 1,
INVALID_SERVER_JSON = 2,
NO_RESULT_CALLBACK_FOUND = 3,
@@ -125,12 +140,17 @@ M.client_errors = {
SERVER_RESULT_CALLBACK_ERROR = 7,
}
-M.client_errors = vim.tbl_add_reverse_lookup(M.client_errors)
+--- @type table<string|integer, string|integer>
+--- @nodoc
+M.client_errors = vim.deepcopy(client_errors)
+for k, v in pairs(client_errors) do
+ M.client_errors[v] = k
+end
--- Constructs an error message from an LSP error object.
---
----@param err (table) The error object
----@returns (string) The formatted error message
+---@param err table The error object
+---@return string error_message The formatted error message
function M.format_rpc_error(err)
validate({
err = { err, 't' },
@@ -138,7 +158,7 @@ function M.format_rpc_error(err)
-- There is ErrorCodes in the LSP specification,
-- but in ResponseError.code it is not used and the actual type is number.
- local code
+ local code --- @type string
if protocol.ErrorCodes[err.code] then
code = string.format('code_name = %s,', protocol.ErrorCodes[err.code])
else
@@ -157,13 +177,17 @@ function M.format_rpc_error(err)
return table.concat(message_parts, ' ')
end
---- Creates an RPC response object/table.
+--- Creates an RPC response table `error` to be sent to the LSP response.
+---
+---@param code integer RPC error code defined, see `vim.lsp.protocol.ErrorCodes`
+---@param message? string arbitrary message to send to server
+---@param data? any arbitrary data to send to server
---
----@param code integer RPC error code defined in `vim.lsp.protocol.ErrorCodes`
----@param message string|nil arbitrary message to send to server
----@param data any|nil arbitrary data to send to server
+---@see lsp.ErrorCodes See `vim.lsp.protocol.ErrorCodes`
+---@return lsp.ResponseError
function M.rpc_response_error(code, message, data)
-- TODO should this error or just pick a sane error (like InternalError)?
+ ---@type string
local code_name = assert(protocol.ErrorCodes[code], 'Invalid RPC error code')
return setmetatable({
code = code,
@@ -174,52 +198,55 @@ function M.rpc_response_error(code, message, data)
})
end
-local default_dispatchers = {}
-
----@private
---- Default dispatcher for notifications sent to an LSP server.
----
----@param method (string) The invoked LSP method
----@param params (table): Parameters for the invoked LSP method
-function default_dispatchers.notification(method, params)
- local _ = log.debug() and log.debug('notification', method, params)
-end
-
----@private
---- Default dispatcher for requests sent to an LSP server.
----
----@param method (string) The invoked LSP method
----@param params (table): Parameters for the invoked LSP method
----@return nil
----@return table `vim.lsp.protocol.ErrorCodes.MethodNotFound`
-function default_dispatchers.server_request(method, params)
- local _ = log.debug() and log.debug('server_request', method, params)
- return nil, M.rpc_response_error(protocol.ErrorCodes.MethodNotFound)
-end
+--- Dispatchers for LSP message types.
+--- @class vim.lsp.rpc.Dispatchers
+--- @inlinedoc
+--- @field notification fun(method: string, params: table)
+--- @field server_request fun(method: string, params: table): any?, lsp.ResponseError?
+--- @field on_exit fun(code: integer, signal: integer)
+--- @field on_error fun(code: integer, err: any)
+
+--- @type vim.lsp.rpc.Dispatchers
+local default_dispatchers = {
+ --- Default dispatcher for notifications sent to an LSP server.
+ ---
+ ---@param method string The invoked LSP method
+ ---@param params table Parameters for the invoked LSP method
+ notification = function(method, params)
+ log.debug('notification', method, params)
+ end,
----@private
---- Default dispatcher for when a client exits.
----
----@param code (integer): Exit code
----@param signal (integer): Number describing the signal used to terminate (if
----any)
-function default_dispatchers.on_exit(code, signal)
- local _ = log.info() and log.info('client_exit', { code = code, signal = signal })
-end
+ --- Default dispatcher for requests sent to an LSP server.
+ ---
+ ---@param method string The invoked LSP method
+ ---@param params table Parameters for the invoked LSP method
+ ---@return any result (always nil for the default dispatchers)
+ ---@return lsp.ResponseError error `vim.lsp.protocol.ErrorCodes.MethodNotFound`
+ server_request = function(method, params)
+ log.debug('server_request', method, params)
+ return nil, M.rpc_response_error(protocol.ErrorCodes.MethodNotFound)
+ end,
+
+ --- Default dispatcher for when a client exits.
+ ---
+ ---@param code integer Exit code
+ ---@param signal integer Number describing the signal used to terminate (if any)
+ on_exit = function(code, signal)
+ log.info('client_exit', { code = code, signal = signal })
+ end,
----@private
---- Default dispatcher for client errors.
----
----@param code (integer): Error code
----@param err (any): Details about the error
----any)
-function default_dispatchers.on_error(code, err)
- local _ = log.error() and log.error('client_error:', M.client_errors[code], err)
-end
+ --- Default dispatcher for client errors.
+ ---
+ ---@param code integer Error code
+ ---@param err any Details about the error
+ on_error = function(code, err)
+ log.error('client_error:', M.client_errors[code], err)
+ end,
+}
---@private
function M.create_read_loop(handle_body, on_no_chunk, on_error)
- local parse_chunk = coroutine.wrap(request_parser_loop)
+ local parse_chunk = coroutine.wrap(request_parser_loop) --[[@as fun(chunk: string?): vim.lsp.rpc.Headers?, string?]]
parse_chunk()
return function(err, chunk)
if err then
@@ -246,31 +273,32 @@ function M.create_read_loop(handle_body, on_no_chunk, on_error)
end
end
----@class RpcClient
+---@class (private) vim.lsp.rpc.Client
---@field message_index integer
----@field message_callbacks table
----@field notify_reply_callbacks table
----@field transport table
----@field dispatchers table
-
----@class RpcClient
+---@field message_callbacks table<integer, function> dict of message_id to callback
+---@field notify_reply_callbacks table<integer, function> dict of message_id to callback
+---@field transport vim.lsp.rpc.Transport
+---@field dispatchers vim.lsp.rpc.Dispatchers
local Client = {}
---@private
function Client:encode_and_send(payload)
- local _ = log.debug() and log.debug('rpc.send', payload)
+ log.debug('rpc.send', payload)
if self.transport.is_closing() then
return false
end
- local encoded = vim.json.encode(payload)
- self.transport.write(format_message_with_content_length(encoded))
+ local jsonstr = assert(
+ vim.json.encode(payload),
+ string.format("Couldn't encode payload '%s'", vim.inspect(payload))
+ )
+ self.transport.write(format_message_with_content_length(jsonstr))
return true
end
----@private
+---@package
--- Sends a notification to the LSP server.
----@param method (string) The invoked LSP method
----@param params (any): Parameters for the invoked LSP method
+---@param method string The invoked LSP method
+---@param params any Parameters for the invoked LSP method
---@return boolean `true` if notification could be sent, `false` if not
function Client:notify(method, params)
return self:encode_and_send({
@@ -291,14 +319,15 @@ function Client:send_response(request_id, err, result)
})
end
----@private
---- Sends a request to the LSP server and runs {callback} upon response.
+---@package
+--- Sends a request to the LSP server and runs {callback} upon response. |vim.lsp.rpc.request()|
---
----@param method (string) The invoked LSP method
----@param params (table|nil) Parameters for the invoked LSP method
----@param callback fun(err: lsp.ResponseError|nil, result: any) Callback to invoke
----@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending
----@return boolean success, integer|nil request_id true, request_id if request could be sent, `false` if not
+---@param method string The invoked LSP method
+---@param params table? Parameters for the invoked LSP method
+---@param callback fun(err?: lsp.ResponseError, result: any) Callback to invoke
+---@param notify_reply_callback fun(message_id: integer)|nil Callback to invoke as soon as a request is no longer pending
+---@return boolean success `true` if request could be sent, `false` if not
+---@return integer? message_id if request could be sent, `nil` if not
function Client:request(method, params, callback, notify_reply_callback)
validate({
callback = { callback, 'f' },
@@ -318,18 +347,20 @@ function Client:request(method, params, callback, notify_reply_callback)
if message_callbacks then
message_callbacks[message_id] = schedule_wrap(callback)
else
- return false
+ return false, nil
end
if notify_reply_callback and notify_reply_callbacks then
notify_reply_callbacks[message_id] = schedule_wrap(notify_reply_callback)
end
return result, message_id
else
- return false
+ return false, nil
end
end
----@private
+---@package
+---@param errkind integer
+---@param ... any
function Client:on_error(errkind, ...)
assert(M.client_errors[errkind])
-- TODO what to do if this fails?
@@ -337,6 +368,13 @@ function Client:on_error(errkind, ...)
end
---@private
+---@param errkind integer
+---@param status boolean
+---@param head any
+---@param ... any
+---@return boolean status
+---@return any head
+---@return any|nil ...
function Client:pcall_handler(errkind, status, head, ...)
if not status then
self:on_error(errkind, head, ...)
@@ -346,6 +384,12 @@ function Client:pcall_handler(errkind, status, head, ...)
end
---@private
+---@param errkind integer
+---@param fn function
+---@param ... any
+---@return boolean status
+---@return any head
+---@return any|nil ...
function Client:try_call(errkind, fn, ...)
return self:pcall_handler(errkind, pcall(fn, ...))
end
@@ -354,17 +398,17 @@ end
-- time and log them. This would require storing the timestamp. I could call
-- them with an error then, perhaps.
----@private
+---@package
function Client:handle_body(body)
local ok, decoded = pcall(vim.json.decode, body, { luanil = { object = true } })
if not ok then
self:on_error(M.client_errors.INVALID_SERVER_JSON, decoded)
return
end
- local _ = log.debug() and log.debug('rpc.receive', decoded)
+ log.debug('rpc.receive', decoded)
if type(decoded.method) == 'string' and decoded.id then
- local err
+ local err --- @type lsp.ResponseError|nil
-- Schedule here so that the users functions don't trigger an error and
-- we can still use the result.
schedule(function()
@@ -376,11 +420,10 @@ function Client:handle_body(body)
decoded.method,
decoded.params
)
- local _ = log.debug()
- and log.debug(
- 'server_request: callback result',
- { status = status, result = result, err = err }
- )
+ log.debug(
+ 'server_request: callback result',
+ { status = status, result = result, err = err }
+ )
if status then
if result == nil and err == nil then
error(
@@ -391,10 +434,12 @@ function Client:handle_body(body)
)
end
if err then
+ ---@cast err lsp.ResponseError
assert(
type(err) == 'table',
'err must be a table. Use rpc_response_error to help format errors.'
)
+ ---@type string
local code_name = assert(
protocol.ErrorCodes[err.code],
'Errors must use protocol.ErrorCodes. Use rpc_response_error to help format errors.'
@@ -431,7 +476,7 @@ function Client:handle_body(body)
if decoded.error then
local mute_error = false
if decoded.error.code == protocol.ErrorCodes.RequestCancelled then
- local _ = log.debug() and log.debug('Received cancellation ack', decoded)
+ log.debug('Received cancellation ack', decoded)
mute_error = true
end
@@ -457,7 +502,7 @@ function Client:handle_body(body)
if decoded.error then
decoded.error = setmetatable(decoded.error, {
__tostring = M.format_rpc_error,
- })
+ }) --- @type table
end
self:try_call(
M.client_errors.SERVER_RESULT_CALLBACK_ERROR,
@@ -467,7 +512,7 @@ function Client:handle_body(body)
)
else
self:on_error(M.client_errors.NO_RESULT_CALLBACK_FOUND, decoded)
- local _ = log.error() and log.error('No callback found for server response id ' .. result_id)
+ log.error('No callback found for server response id ' .. result_id)
end
elseif type(decoded.method) == 'string' then
-- Notification
@@ -483,7 +528,14 @@ function Client:handle_body(body)
end
end
----@return RpcClient
+---@class (private) vim.lsp.rpc.Transport
+---@field write fun(msg: string)
+---@field is_closing fun(): boolean
+---@field terminate fun()
+
+---@param dispatchers vim.lsp.rpc.Dispatchers
+---@param transport vim.lsp.rpc.Transport
+---@return vim.lsp.rpc.Client
local function new_client(dispatchers, transport)
local state = {
message_index = 0,
@@ -495,8 +547,17 @@ local function new_client(dispatchers, transport)
return setmetatable(state, { __index = Client })
end
----@param client RpcClient
+---@class vim.lsp.rpc.PublicClient
+---@field request fun(method: string, params: table?, callback: fun(err: lsp.ResponseError|nil, result: any), notify_reply_callback: fun(integer)|nil):boolean,integer? see |vim.lsp.rpc.request()|
+---@field notify fun(method: string, params: any):boolean see |vim.lsp.rpc.notify()|
+---@field is_closing fun(): boolean
+---@field terminate fun()
+
+---@param client vim.lsp.rpc.Client
+---@return vim.lsp.rpc.PublicClient
local function public_client(client)
+ ---@type vim.lsp.rpc.PublicClient
+ ---@diagnostic disable-next-line: missing-fields
local result = {}
---@private
@@ -512,17 +573,18 @@ local function public_client(client)
--- Sends a request to the LSP server and runs {callback} upon response.
---
---@param method (string) The invoked LSP method
- ---@param params (table|nil) Parameters for the invoked LSP method
- ---@param callback fun(err: lsp.ResponseError | nil, result: any) Callback to invoke
- ---@param notify_reply_callback (function|nil) Callback to invoke as soon as a request is no longer pending
- ---@return boolean success, integer|nil request_id true, message_id if request could be sent, `false` if not
+ ---@param params (table?) Parameters for the invoked LSP method
+ ---@param callback fun(err: lsp.ResponseError|nil, result: any) Callback to invoke
+ ---@param notify_reply_callback fun(message_id: integer)|nil Callback to invoke as soon as a request is no longer pending
+ ---@return boolean success `true` if request could be sent, `false` if not
+ ---@return integer? message_id if request could be sent, `nil` if not
function result.request(method, params, callback, notify_reply_callback)
return client:request(method, params, callback, notify_reply_callback)
end
--- Sends a notification to the LSP server.
---@param method (string) The invoked LSP method
- ---@param params (table|nil): Parameters for the invoked LSP method
+ ---@param params (table?) Parameters for the invoked LSP method
---@return boolean `true` if notification could be sent, `false` if not
function result.notify(method, params)
return client:notify(method, params)
@@ -531,43 +593,46 @@ local function public_client(client)
return result
end
+---@param dispatchers vim.lsp.rpc.Dispatchers?
+---@return vim.lsp.rpc.Dispatchers
local function merge_dispatchers(dispatchers)
- if dispatchers then
- local user_dispatchers = dispatchers
- dispatchers = {}
- for dispatch_name, default_dispatch in pairs(default_dispatchers) do
- local user_dispatcher = user_dispatchers[dispatch_name]
- if user_dispatcher then
- if type(user_dispatcher) ~= 'function' then
- error(string.format('dispatcher.%s must be a function', dispatch_name))
- end
- -- server_request is wrapped elsewhere.
- if
- not (dispatch_name == 'server_request' or dispatch_name == 'on_exit') -- TODO this blocks the loop exiting for some reason.
- then
- user_dispatcher = schedule_wrap(user_dispatcher)
- end
- dispatchers[dispatch_name] = user_dispatcher
- else
- dispatchers[dispatch_name] = default_dispatch
- end
+ if not dispatchers then
+ return default_dispatchers
+ end
+ ---@diagnostic disable-next-line: no-unknown
+ for name, fn in pairs(dispatchers) do
+ if type(fn) ~= 'function' then
+ error(string.format('dispatcher.%s must be a function', name))
end
- else
- dispatchers = default_dispatchers
end
- return dispatchers
+ ---@type vim.lsp.rpc.Dispatchers
+ local merged = {
+ notification = (
+ dispatchers.notification and vim.schedule_wrap(dispatchers.notification)
+ or default_dispatchers.notification
+ ),
+ on_error = (
+ dispatchers.on_error and vim.schedule_wrap(dispatchers.on_error)
+ or default_dispatchers.on_error
+ ),
+ on_exit = dispatchers.on_exit or default_dispatchers.on_exit,
+ server_request = dispatchers.server_request or default_dispatchers.server_request,
+ }
+ return merged
end
---- Create a LSP RPC client factory that connects via TCP to the given host
---- and port
+--- Create a LSP RPC client factory that connects via TCP to the given host and port.
+---
+--- Return a function that can be passed to the `cmd` field for
+--- |vim.lsp.start_client()| or |vim.lsp.start()|.
---
----@param host string
----@param port integer
----@return function
+---@param host string host to connect to
+---@param port integer port to connect to
+---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient
function M.connect(host, port)
return function(dispatchers)
dispatchers = merge_dispatchers(dispatchers)
- local tcp = uv.new_tcp()
+ local tcp = assert(uv.new_tcp())
local closing = false
local transport = {
write = function(msg)
@@ -608,35 +673,84 @@ function M.connect(host, port)
end
end
+--- Create a LSP RPC client factory that connects via named pipes (Windows)
+--- or unix domain sockets (Unix) to the given pipe_path (file path on
+--- Unix and name on Windows).
+---
+--- Return a function that can be passed to the `cmd` field for
+--- |vim.lsp.start_client()| or |vim.lsp.start()|.
+---
+---@param pipe_path string file path of the domain socket (Unix) or name of the named pipe (Windows) to connect to
+---@return fun(dispatchers: vim.lsp.rpc.Dispatchers): vim.lsp.rpc.PublicClient
+function M.domain_socket_connect(pipe_path)
+ return function(dispatchers)
+ dispatchers = merge_dispatchers(dispatchers)
+ local pipe =
+ assert(uv.new_pipe(false), string.format('pipe with name %s could not be opened.', pipe_path))
+ local closing = false
+ local transport = {
+ write = vim.schedule_wrap(function(msg)
+ pipe:write(msg)
+ end),
+ is_closing = function()
+ return closing
+ end,
+ terminate = function()
+ if not closing then
+ closing = true
+ pipe:shutdown()
+ pipe:close()
+ dispatchers.on_exit(0, 0)
+ end
+ end,
+ }
+ local client = new_client(dispatchers, transport)
+ pipe:connect(pipe_path, function(err)
+ if err then
+ vim.schedule(function()
+ vim.notify(
+ string.format('Could not connect to :%s, reason: %s', pipe_path, vim.inspect(err)),
+ vim.log.levels.WARN
+ )
+ end)
+ return
+ end
+ local handle_body = function(body)
+ client:handle_body(body)
+ end
+ pipe:read_start(M.create_read_loop(handle_body, transport.terminate, function(read_err)
+ client:on_error(M.client_errors.READ_ERROR, read_err)
+ end))
+ end)
+
+ return public_client(client)
+ end
+end
+
+--- Additional context for the LSP server process.
+--- @class vim.lsp.rpc.ExtraSpawnParams
+--- @inlinedoc
+--- @field cwd? string Working directory for the LSP server process
+--- @field detached? boolean Detach the LSP server process from the current process
+--- @field env? table<string,string> Additional environment variables for LSP server process. See |vim.system()|
+
--- Starts an LSP server process and create an LSP RPC client object to
--- interact with it. Communication with the spawned process happens via stdio. For
--- communication via TCP, spawn a process manually and use |vim.lsp.rpc.connect()|
---
----@param cmd (string) Command to start the LSP server.
----@param cmd_args (table) List of additional string arguments to pass to {cmd}.
----@param dispatchers table|nil Dispatchers for LSP message types. Valid
----dispatcher names are:
---- - `"notification"`
---- - `"server_request"`
---- - `"on_error"`
---- - `"on_exit"`
----@param extra_spawn_params table|nil Additional context for the LSP
---- server process. May contain:
---- - {cwd} (string) Working directory for the LSP server process
---- - {env} (table) Additional environment variables for LSP server process
----@return table|nil Client RPC object, with these methods:
---- - `notify()` |vim.lsp.rpc.notify()|
---- - `request()` |vim.lsp.rpc.request()|
---- - `is_closing()` returns a boolean indicating if the RPC is closing.
---- - `terminate()` terminates the RPC client.
-function M.start(cmd, cmd_args, dispatchers, extra_spawn_params)
- if log.info() then
- log.info('Starting RPC client', { cmd = cmd, args = cmd_args, extra = extra_spawn_params })
- end
+--- @param cmd string[] Command to start the LSP server.
+--- @param dispatchers? vim.lsp.rpc.Dispatchers
+--- @param extra_spawn_params? vim.lsp.rpc.ExtraSpawnParams
+--- @return vim.lsp.rpc.PublicClient? : Client RPC object, with these methods:
+--- - `notify()` |vim.lsp.rpc.notify()|
+--- - `request()` |vim.lsp.rpc.request()|
+--- - `is_closing()` returns a boolean indicating if the RPC is closing.
+--- - `terminate()` terminates the RPC client.
+function M.start(cmd, dispatchers, extra_spawn_params)
+ log.info('Starting RPC client', { cmd = cmd, extra = extra_spawn_params })
validate({
- cmd = { cmd, 's' },
- cmd_args = { cmd_args, 't' },
+ cmd = { cmd, 't' },
dispatchers = { dispatchers, 't', true },
})
@@ -671,8 +785,8 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params)
end)
local stderr_handler = function(_, chunk)
- if chunk and log.error() then
- log.error('rpc', cmd, 'stderr', chunk)
+ if chunk then
+ log.error('rpc', cmd[1], 'stderr', chunk)
end
end
@@ -681,10 +795,7 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params)
detached = extra_spawn_params.detached
end
- local cmd1 = { cmd }
- vim.list_extend(cmd1, cmd_args)
-
- local ok, sysobj_or_err = pcall(vim.system, cmd1, {
+ local ok, sysobj_or_err = pcall(vim.system, cmd, {
stdin = true,
stdout = stdout_handler,
stderr = stderr_handler,
@@ -697,15 +808,16 @@ function M.start(cmd, cmd_args, dispatchers, extra_spawn_params)
if not ok then
local err = sysobj_or_err --[[@as string]]
- local msg = string.format('Spawning language server with cmd: `%s` failed', cmd)
+ local sfx --- @type string
if string.match(err, 'ENOENT') then
- msg = msg
- .. '. The language server is either not installed, missing from PATH, or not executable.'
+ sfx = '. The language server is either not installed, missing from PATH, or not executable.'
else
- msg = msg .. string.format(' with error message: %s', err)
+ sfx = string.format(' with error message: %s', err)
end
+ local msg =
+ string.format('Spawning language server with cmd: `%s` failed%s', vim.inspect(cmd), sfx)
vim.notify(msg, vim.log.levels.WARN)
- return
+ return nil
end
sysobj = sysobj_or_err --[[@as vim.SystemObj]]
diff --git a/runtime/lua/vim/lsp/semantic_tokens.lua b/runtime/lua/vim/lsp/semantic_tokens.lua
index a5831c0beb..20ac0a125f 100644
--- a/runtime/lua/vim/lsp/semantic_tokens.lua
+++ b/runtime/lua/vim/lsp/semantic_tokens.lua
@@ -1,35 +1,34 @@
local api = vim.api
local bit = require('bit')
-local handlers = require('vim.lsp.handlers')
local ms = require('vim.lsp.protocol').Methods
local util = require('vim.lsp.util')
local uv = vim.uv
---- @class STTokenRange
+--- @class (private) STTokenRange
--- @field line integer line number 0-based
--- @field start_col integer start column 0-based
--- @field end_col integer end column 0-based
--- @field type string token type as string
---- @field modifiers table token modifiers as a set. E.g., { static = true, readonly = true }
+--- @field modifiers table<string,boolean> token modifiers as a set. E.g., { static = true, readonly = true }
--- @field marked boolean whether this token has had extmarks applied
---
---- @class STCurrentResult
+--- @class (private) STCurrentResult
--- @field version? integer document version associated with this result
--- @field result_id? string resultId from the server; used with delta requests
--- @field highlights? STTokenRange[] cache of highlight ranges for this document version
--- @field tokens? integer[] raw token array as received by the server. used for calculating delta responses
--- @field namespace_cleared? boolean whether the namespace was cleared for this result yet
---
---- @class STActiveRequest
---- @field request_id integer the LSP request ID of the most recent request sent to the server
---- @field version integer the document version associated with the most recent request
+--- @class (private) STActiveRequest
+--- @field request_id? integer the LSP request ID of the most recent request sent to the server
+--- @field version? integer the document version associated with the most recent request
---
---- @class STClientState
+--- @class (private) STClientState
--- @field namespace integer
--- @field active_request STActiveRequest
--- @field current_result STCurrentResult
----@class STHighlighter
+---@class (private) STHighlighter
---@field active table<integer, STHighlighter>
---@field bufnr integer
---@field augroup integer augroup for buffer events
@@ -72,9 +71,11 @@ end
--- Extracts modifier strings from the encoded number in the token array
---
+---@param x integer
+---@param modifiers_table table<integer,string>
---@return table<string, boolean>
local function modifiers_from_number(x, modifiers_table)
- local modifiers = {}
+ local modifiers = {} ---@type table<string,boolean>
local idx = 1
while x > 0 do
if bit.band(x, 1) == 1 then
@@ -89,20 +90,24 @@ end
--- Converts a raw token list to a list of highlight ranges used by the on_win callback
---
+---@param data integer[]
+---@param bufnr integer
+---@param client vim.lsp.Client
+---@param request STActiveRequest
---@return STTokenRange[]
local function tokens_to_ranges(data, bufnr, client, request)
local legend = client.server_capabilities.semanticTokensProvider.legend
local token_types = legend.tokenTypes
local token_modifiers = legend.tokenModifiers
local lines = api.nvim_buf_get_lines(bufnr, 0, -1, false)
- local ranges = {}
+ local ranges = {} ---@type STTokenRange[]
local start = uv.hrtime()
local ms_to_ns = 1000 * 1000
local yield_interval_ns = 5 * ms_to_ns
local co, is_main = coroutine.running()
- local line
+ local line ---@type integer?
local start_char = 0
for i = 1, #data, 5 do
-- if this function is called from the main coroutine, let it run to completion with no yield
@@ -167,6 +172,7 @@ end
---
---@private
---@param bufnr integer
+---@return STHighlighter
function STHighlighter.new(bufnr)
local self = setmetatable({}, { __index = STHighlighter })
@@ -221,7 +227,7 @@ function STHighlighter.new(bufnr)
return self
end
----@private
+---@package
function STHighlighter:destroy()
for client_id, _ in pairs(self.client_state) do
self:detach(client_id)
@@ -231,7 +237,7 @@ function STHighlighter:destroy()
STHighlighter.active[self.bufnr] = nil
end
----@private
+---@package
function STHighlighter:attach(client_id)
local state = self.client_state[client_id]
if not state then
@@ -244,7 +250,7 @@ function STHighlighter:attach(client_id)
end
end
----@private
+---@package
function STHighlighter:detach(client_id)
local state = self.client_state[client_id]
if state then
@@ -267,7 +273,7 @@ end
--- Finally, if the request was successful, the requestId and document version
--- are saved to facilitate document synchronization in the response.
---
----@private
+---@package
function STHighlighter:send_request()
local version = util.buf_versions[self.bufnr]
@@ -303,7 +309,8 @@ function STHighlighter:send_request()
-- look client up again using ctx.client_id instead of using a captured
-- client object
local c = vim.lsp.get_client_by_id(ctx.client_id)
- local highlighter = STHighlighter.active[ctx.bufnr]
+ local bufnr = assert(ctx.bufnr)
+ local highlighter = STHighlighter.active[bufnr]
if not err and c and highlighter then
coroutine.wrap(STHighlighter.process_response)(highlighter, response, c, version)
end
@@ -328,6 +335,7 @@ end
--- Finally, a redraw command is issued to force nvim to redraw the screen to
--- pick up changed highlight tokens.
---
+---@param response lsp.SemanticTokens|lsp.SemanticTokensDelta
---@private
function STHighlighter:process_response(response, client, version)
local state = self.client_state[client.id]
@@ -348,15 +356,15 @@ function STHighlighter:process_response(response, client, version)
-- if we have a response to a delta request, update the state of our tokens
-- appropriately. if it's a full response, just use that
- local tokens
+ local tokens ---@type integer[]
local token_edits = response.edits
if token_edits then
table.sort(token_edits, function(a, b)
return a.start < b.start
end)
- tokens = {}
- local old_tokens = state.current_result.tokens
+ tokens = {} --- @type integer[]
+ local old_tokens = assert(state.current_result.tokens)
local idx = 1
for _, token_edit in ipairs(token_edits) do
vim.list_extend(tokens, old_tokens, idx, token_edit.start)
@@ -404,7 +412,9 @@ end
--- handler to avoid the "blink" that occurs due to the timing between the
--- response handler and the actual redraw.
---
----@private
+---@package
+---@param topline integer
+---@param botline integer
function STHighlighter:on_win(topline, botline)
for client_id, state in pairs(self.client_state) do
local current_result = state.current_result
@@ -450,7 +460,7 @@ function STHighlighter:on_win(topline, botline)
end
local ft = vim.bo[self.bufnr].filetype
- local highlights = current_result.highlights
+ local highlights = assert(current_result.highlights)
local first = lower_bound(highlights, topline, 1, #highlights + 1)
local last = upper_bound(highlights, botline, first, #highlights + 1) - 1
@@ -480,7 +490,7 @@ end
--- Reset the buffer's highlighting state and clears the extmark highlights.
---
----@private
+---@package
function STHighlighter:reset()
for client_id, state in pairs(self.client_state) do
api.nvim_buf_clear_namespace(self.bufnr, state.namespace, 0, -1)
@@ -499,7 +509,7 @@ end
--- in the on_win callback. The rest of the current results are saved
--- in case the server supports delta requests.
---
----@private
+---@package
---@param client_id integer
function STHighlighter:mark_dirty(client_id)
local state = self.client_state[client_id]
@@ -521,7 +531,7 @@ function STHighlighter:mark_dirty(client_id)
end
end
----@private
+---@package
function STHighlighter:on_change()
self:reset_timer()
if self.debounce > 0 then
@@ -562,7 +572,7 @@ local M = {}
---
---@param bufnr integer
---@param client_id integer
----@param opts (nil|table) Optional keyword arguments
+---@param opts? table Optional keyword arguments
--- - debounce (integer, default: 200): Debounce token requests
--- to the server by the given number in milliseconds
function M.start(bufnr, client_id, opts)
@@ -636,6 +646,10 @@ function M.stop(bufnr, client_id)
end
end
+--- @nodoc
+--- @class STTokenRangeInspect : STTokenRange
+--- @field client_id integer
+
--- Return the semantic token(s) at the given position.
--- If called without arguments, returns the token under the cursor.
---
@@ -643,13 +657,14 @@ end
---@param row integer|nil Position row (default cursor position)
---@param col integer|nil Position column (default cursor position)
---
----@return table|nil (table|nil) List of tokens at position. Each token has
+---@return STTokenRangeInspect[]|nil (table|nil) List of tokens at position. Each token has
--- the following fields:
--- - line (integer) line number, 0-based
--- - start_col (integer) start column, 0-based
--- - end_col (integer) end column, 0-based
--- - type (string) token type as string, e.g. "variable"
--- - modifiers (table) token modifiers as a set. E.g., { static = true, readonly = true }
+--- - client_id (integer)
function M.get_at_pos(bufnr, row, col)
if bufnr == nil or bufnr == 0 then
bufnr = api.nvim_get_current_buf()
@@ -665,13 +680,14 @@ function M.get_at_pos(bufnr, row, col)
row, col = cursor[1] - 1, cursor[2]
end
- local tokens = {}
+ local tokens = {} --- @type STTokenRangeInspect[]
for client_id, client in pairs(highlighter.client_state) do
local highlights = client.current_result.highlights
if highlights then
local idx = lower_bound(highlights, row, 1, #highlights + 1)
for i = idx, #highlights do
local token = highlights[i]
+ --- @cast token STTokenRangeInspect
if token.line > row then
break
@@ -712,6 +728,13 @@ function M.force_refresh(bufnr)
end
end
+--- @class vim.lsp.semantic_tokens.highlight_token.Opts
+--- @inlinedoc
+---
+--- Priority for the applied extmark.
+--- (Default: `vim.highlight.priorities.semantic_tokens + 3`)
+--- @field priority? integer
+
--- Highlight a semantic token.
---
--- Apply an extmark with a given highlight group for a semantic token. The
@@ -720,11 +743,9 @@ end
--- use inside |LspTokenUpdate| callbacks.
---@param token (table) a semantic token, found as `args.data.token` in |LspTokenUpdate|.
---@param bufnr (integer) the buffer to highlight
----@param client_id (integer) The ID of the |vim.lsp.client|
+---@param client_id (integer) The ID of the |vim.lsp.Client|
---@param hl_group (string) Highlight group name
----@param opts (table|nil) Optional parameters.
---- - priority: (integer|nil) Priority for the applied extmark. Defaults
---- to `vim.highlight.priorities.semantic_tokens + 3`
+---@param opts? vim.lsp.semantic_tokens.highlight_token.Opts Optional parameters:
function M.highlight_token(token, bufnr, client_id, hl_group, opts)
local highlighter = STHighlighter.active[bufnr]
if not highlighter then
@@ -747,6 +768,7 @@ function M.highlight_token(token, bufnr, client_id, hl_group, opts)
})
end
+--- @package
--- |lsp-handler| for the method `workspace/semanticTokens/refresh`
---
--- Refresh requests are sent by the server to indicate a project-wide change
@@ -754,9 +776,7 @@ end
--- invalidate the current results of all buffers and automatically kick off a
--- new request for buffers that are displayed in a window. For those that aren't, a
--- the BufWinEnter event should take care of it next time it's displayed.
----
----@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#semanticTokens_refreshRequest
-handlers[ms.workspace_semanticTokens_refresh] = function(err, _, ctx)
+function M._refresh(err, _, ctx)
if err then
return vim.NIL
end
diff --git a/runtime/lua/vim/lsp/sync.lua b/runtime/lua/vim/lsp/sync.lua
index ca01cdc08b..936579e003 100644
--- a/runtime/lua/vim/lsp/sync.lua
+++ b/runtime/lua/vim/lsp/sync.lua
@@ -53,13 +53,12 @@ local str_utf_end = vim.str_utf_end
---@param line string the line to index into
---@param byte integer the byte idx
---@param offset_encoding string utf-8|utf-16|utf-32|nil (default: utf-8)
---@returns integer the utf idx for the given encoding
+---@return integer utf_idx for the given encoding
local function byte_to_utf(line, byte, offset_encoding)
-- convert to 0 based indexing for str_utfindex
byte = byte - 1
- local utf_idx
- local _
+ local utf_idx, _ --- @type integer, integer
-- Convert the byte range to utf-{8,16,32} and convert 1-based (lua) indexing to 0-based
if offset_encoding == 'utf-16' then
_, utf_idx = str_utfindex(line, byte)
@@ -73,9 +72,11 @@ local function byte_to_utf(line, byte, offset_encoding)
return utf_idx + 1
end
+---@param line string
+---@param offset_encoding string
+---@return integer
local function compute_line_length(line, offset_encoding)
- local length
- local _
+ local length, _ --- @type integer, integer
if offset_encoding == 'utf-16' then
_, length = str_utfindex(line)
elseif offset_encoding == 'utf-32' then
@@ -94,7 +95,7 @@ end
---@return integer byte_idx of first change position
---@return integer char_idx of first change position
local function align_end_position(line, byte, offset_encoding)
- local char
+ local char --- @type integer
-- If on the first byte, or an empty string: the trivial case
if byte == 1 or #line == 0 then
char = byte
@@ -119,14 +120,19 @@ local function align_end_position(line, byte, offset_encoding)
return byte, char
end
+---@class vim.lsp.sync.Range
+---@field line_idx integer
+---@field byte_idx integer
+---@field char_idx integer
+
--- Finds the first line, byte, and char index of the difference between the previous and current lines buffer normalized to the previous codepoint.
----@param prev_lines table list of lines from previous buffer
----@param curr_lines table list of lines from current buffer
+---@param prev_lines string[] list of lines from previous buffer
+---@param curr_lines string[] list of lines from current buffer
---@param firstline integer firstline from on_lines, adjusted to 1-index
---@param lastline integer lastline from on_lines, adjusted to 1-index
---@param new_lastline integer new_lastline from on_lines, adjusted to 1-index
---@param offset_encoding string utf-8|utf-16|utf-32|nil (fallback to utf-8)
----@return table result table include line_idx, byte_idx, and char_idx of first change position
+---@return vim.lsp.sync.Range result table include line_idx, byte_idx, and char_idx of first change position
local function compute_start_range(
prev_lines,
curr_lines,
@@ -135,14 +141,14 @@ local function compute_start_range(
new_lastline,
offset_encoding
)
- local char_idx
- local byte_idx
+ local char_idx --- @type integer?
+ local byte_idx --- @type integer?
-- If firstline == lastline, no existing text is changed. All edit operations
-- occur on a new line pointed to by lastline. This occurs during insertion of
-- new lines(O), the new newline is inserted at the line indicated by
-- new_lastline.
if firstline == lastline then
- local line_idx
+ local line_idx --- @type integer
local line = prev_lines[firstline - 1]
if line then
line_idx = firstline - 1
@@ -198,15 +204,15 @@ end
--- Normalized to the next codepoint.
--- prev_end_range is the text range sent to the server representing the changed region.
--- curr_end_range is the text that should be collected and sent to the server.
---
----@param prev_lines table list of lines
----@param curr_lines table list of lines
----@param start_range table
+---
+---@param prev_lines string[] list of lines
+---@param curr_lines string[] list of lines
+---@param start_range vim.lsp.sync.Range
+---@param firstline integer
---@param lastline integer
---@param new_lastline integer
---@param offset_encoding string
----@return integer|table end_line_idx and end_col_idx of range
----@return table|nil end_col_idx of range
+---@return vim.lsp.sync.Range, vim.lsp.sync.Range
local function compute_end_range(
prev_lines,
curr_lines,
@@ -250,7 +256,7 @@ local function compute_end_range(
-- Editing the same line
-- If the byte offset is zero, that means there is a difference on the last byte (not newline)
if prev_line_idx == curr_line_idx then
- local max_length
+ local max_length --- @type integer
if start_line_idx == prev_line_idx then
-- Search until beginning of difference
max_length = min(
@@ -283,7 +289,7 @@ local function compute_end_range(
local prev_end_range =
{ line_idx = prev_line_idx, byte_idx = prev_byte_idx, char_idx = prev_char_idx }
- local curr_end_range
+ local curr_end_range ---@type vim.lsp.sync.Range
-- Deletion event, new_range cannot be before start
if curr_line_idx < start_line_idx then
curr_end_range = { line_idx = start_line_idx, byte_idx = 1, char_idx = 1 }
@@ -343,6 +349,12 @@ end
-- codeunits for utf-32
-- Line endings count here as 2 chars for \r\n (dos), 1 char for \n (unix), and 1 char for \r (mac)
-- These correspond to Windows, Linux/macOS (OSX and newer), and macOS (version 9 and prior)
+---@param lines string[]
+---@param start_range vim.lsp.sync.Range
+---@param end_range vim.lsp.sync.Range
+---@param offset_encoding string
+---@param line_ending string
+---@return integer
local function compute_range_length(lines, start_range, end_range, offset_encoding, line_ending)
local line_ending_length = #line_ending
-- Single line case
@@ -351,7 +363,7 @@ local function compute_range_length(lines, start_range, end_range, offset_encodi
end
local start_line = lines[start_range.line_idx]
- local range_length
+ local range_length --- @type integer
if start_line and #start_line > 0 then
range_length = compute_line_length(start_line, offset_encoding)
- start_range.char_idx
@@ -387,7 +399,8 @@ end
---@param lastline integer line to begin search in old_lines for last difference
---@param new_lastline integer line to begin search in new_lines for last difference
---@param offset_encoding string encoding requested by language server
----@return table TextDocumentContentChangeEvent see https://microsoft.github.io/language-server-protocol/specification/#textDocumentContentChangeEvent
+---@param line_ending string
+---@return lsp.TextDocumentContentChangeEvent : see https://microsoft.github.io/language-server-protocol/specification/#textDocumentContentChangeEvent
function M.compute_diff(
prev_lines,
curr_lines,
diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua
index 32b220746f..f8e5b6a90d 100644
--- a/runtime/lua/vim/lsp/util.lua
+++ b/runtime/lua/vim/lsp/util.lua
@@ -3,7 +3,7 @@ local snippet = require('vim.lsp._snippet_grammar')
local validate = vim.validate
local api = vim.api
local list_extend = vim.list_extend
-local highlight = require('vim.highlight')
+local highlight = vim.highlight
local uv = vim.uv
local npcall = vim.F.npcall
@@ -180,6 +180,7 @@ local _str_byteindex_enc = M._str_byteindex_enc
---@param new_lines (table) list of strings to replace the original
---@return table The modified {lines} object
function M.set_lines(lines, A, B, new_lines)
+ vim.deprecate('vim.lsp.util.set_lines()', 'nil', '0.12')
-- 0-indexing to 1-indexing
local i_0 = A[1] + 1
-- If it extends past the end, truncate it to the end. This is because the
@@ -346,7 +347,7 @@ end
---@private
---@deprecated Use vim.lsp.status() or access client.progress directly
function M.get_progress_messages()
- vim.deprecate('vim.lsp.util.get_progress_messages', 'vim.lsp.status', '0.11.0')
+ vim.deprecate('vim.lsp.util.get_progress_messages()', 'vim.lsp.status()', '0.11')
local new_messages = {}
local progress_remove = {}
@@ -418,6 +419,9 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
if not next(text_edits) then
return
end
+
+ assert(bufnr ~= 0, 'Explicit buffer number is required')
+
if not api.nvim_buf_is_loaded(bufnr) then
vim.fn.bufload(bufnr)
end
@@ -456,7 +460,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
-- save and restore local marks since they get deleted by nvim_buf_set_lines
local marks = {}
- for _, m in pairs(vim.fn.getmarklist(bufnr or vim.api.nvim_get_current_buf())) do
+ for _, m in pairs(vim.fn.getmarklist(bufnr)) do
if m.mark:match("^'[a-z]$") then
marks[m.mark:sub(2, 2)] = { m.pos[2], m.pos[3] - 1 } -- api-indexed
end
@@ -515,7 +519,7 @@ function M.apply_text_edits(text_edits, bufnr, offset_encoding)
local max = api.nvim_buf_line_count(bufnr)
-- no need to restore marks that still exist
- for _, m in pairs(vim.fn.getmarklist(bufnr or vim.api.nvim_get_current_buf())) do
+ for _, m in pairs(vim.fn.getmarklist(bufnr)) do
marks[m.mark:sub(2, 2)] = nil
end
-- restore marks
@@ -547,12 +551,16 @@ end
--- Can be used to extract the completion items from a
--- `textDocument/completion` request, which may return one of
--- `CompletionItem[]`, `CompletionList` or null.
+---
+--- Note that this method doesn't apply `itemDefaults` to `CompletionList`s, and hence the returned
+--- results might be incorrect.
+---
---@deprecated
---@param result table The result of a `textDocument/completion` request
---@return lsp.CompletionItem[] List of completion items
---@see https://microsoft.github.io/language-server-protocol/specification#textDocument_completion
function M.extract_completion_items(result)
- vim.deprecate('vim.lsp.util.extract_completion_items', nil, '0.11')
+ vim.deprecate('vim.lsp.util.extract_completion_items()', nil, '0.11')
if type(result) == 'table' and result.items then
-- result is a `CompletionList`
return result.items
@@ -570,6 +578,7 @@ end
---
---@param text_document_edit table: a `TextDocumentEdit` object
---@param index integer: Optional index of the edit, if from a list of edits (or nil, if not from a list)
+---@param offset_encoding? string
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentEdit
function M.apply_text_document_edit(text_document_edit, index, offset_encoding)
local text_document = text_document_edit.textDocument
@@ -612,7 +621,7 @@ end
---@param input string unparsed snippet
---@return string parsed snippet
function M.parse_snippet(input)
- vim.deprecate('vim.lsp.util.parse_snippet', nil, '0.11')
+ vim.deprecate('vim.lsp.util.parse_snippet()', nil, '0.11')
local ok, parsed = pcall(function()
return snippet.parse(input)
end)
@@ -634,76 +643,129 @@ end
---@return table[] items
---@see complete-items
function M.text_document_completion_list_to_complete_items(result, prefix)
- vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items', nil, '0.11')
- return require('vim.lsp._completion')._lsp_to_complete_items(result, prefix)
+ vim.deprecate('vim.lsp.util.text_document_completion_list_to_complete_items()', nil, '0.11')
+ return vim.lsp._completion._lsp_to_complete_items(result, prefix)
end
---- Like vim.fn.bufwinid except it works across tabpages.
-local function bufwinid(bufnr)
- for _, win in ipairs(api.nvim_list_wins()) do
- if api.nvim_win_get_buf(win) == bufnr then
- return win
+local function path_components(path)
+ return vim.split(path, '/', { plain = true })
+end
+
+local function path_under_prefix(path, prefix)
+ for i, c in ipairs(prefix) do
+ if c ~= path[i] then
+ return false
end
end
+ return true
end
---- Get list of buffers for a directory
-local function get_dir_bufs(path)
- path = path:gsub('([^%w])', '%%%1')
+--- Get list of buffers whose filename matches the given path prefix (normalized full path)
+---@return integer[]
+local function get_bufs_with_prefix(prefix)
+ prefix = path_components(prefix)
local buffers = {}
for _, v in ipairs(vim.api.nvim_list_bufs()) do
- local bufname = vim.api.nvim_buf_get_name(v):gsub('buffer://', '')
- if bufname:find(path) then
+ local bname = vim.api.nvim_buf_get_name(v)
+ local path = path_components(vim.fs.normalize(bname, { expand_env = false }))
+ if path_under_prefix(path, prefix) then
table.insert(buffers, v)
end
end
return buffers
end
+local function escape_gsub_repl(s)
+ return (s:gsub('%%', '%%%%'))
+end
+
+--- @class vim.lsp.util.rename.Opts
+--- @inlinedoc
+--- @field overwrite? boolean
+--- @field ignoreIfExists? boolean
+
--- Rename old_fname to new_fname
---
----@param opts (table)
--- overwrite? bool
--- ignoreIfExists? bool
+--- Existing buffers are renamed as well, while maintaining their bufnr.
+---
+--- It deletes existing buffers that conflict with the renamed file name only when
+--- * `opts` requests overwriting; or
+--- * the conflicting buffers are not loaded, so that deleting thme does not result in data loss.
+---
+--- @param old_fname string
+--- @param new_fname string
+--- @param opts? vim.lsp.util.rename.Opts Options:
function M.rename(old_fname, new_fname, opts)
opts = opts or {}
- local target_exists = uv.fs_stat(new_fname) ~= nil
- if target_exists and not opts.overwrite or opts.ignoreIfExists then
- vim.notify('Rename target already exists. Skipping rename.')
+ local skip = not opts.overwrite or opts.ignoreIfExists
+
+ local old_fname_full = vim.uv.fs_realpath(vim.fs.normalize(old_fname, { expand_env = false }))
+ if not old_fname_full then
+ vim.notify('Invalid path: ' .. old_fname, vim.log.levels.ERROR)
return
end
- local oldbufs = {}
- local win = nil
-
- if vim.fn.isdirectory(old_fname) == 1 then
- oldbufs = get_dir_bufs(old_fname)
- else
- local oldbuf = vim.fn.bufadd(old_fname)
- table.insert(oldbufs, oldbuf)
- win = bufwinid(oldbuf)
+ local target_exists = uv.fs_stat(new_fname) ~= nil
+ if target_exists and skip then
+ vim.notify(new_fname .. ' already exists. Skipping rename.', vim.log.levels.ERROR)
+ return
end
- for _, b in ipairs(oldbufs) do
- vim.fn.bufload(b)
- -- The there may be pending changes in the buffer
- api.nvim_buf_call(b, function()
- vim.cmd('w!')
+ local buf_rename = {} ---@type table<integer, {from: string, to: string}>
+ local old_fname_pat = '^' .. vim.pesc(old_fname_full)
+ for b in
+ vim.iter(get_bufs_with_prefix(old_fname_full)):filter(function(b)
+ -- No need to care about unloaded or nofile buffers. Also :saveas won't work for them.
+ return api.nvim_buf_is_loaded(b)
+ and not vim.list_contains({ 'nofile', 'nowrite' }, vim.bo[b].buftype)
end)
+ do
+ -- Renaming a buffer may conflict with another buffer that happens to have the same name. In
+ -- most cases, this would have been already detected by the file conflict check above, but the
+ -- conflicting buffer may not be associated with a file. For example, 'buftype' can be "nofile"
+ -- or "nowrite", or the buffer can be a normal buffer but has not been written to the file yet.
+ -- Renaming should fail in such cases to avoid losing the contents of the conflicting buffer.
+ local old_bname = vim.api.nvim_buf_get_name(b)
+ local new_bname = old_bname:gsub(old_fname_pat, escape_gsub_repl(new_fname))
+ if vim.fn.bufexists(new_bname) == 1 then
+ local existing_buf = vim.fn.bufnr(new_bname)
+ if api.nvim_buf_is_loaded(existing_buf) and skip then
+ vim.notify(
+ new_bname .. ' already exists in the buffer list. Skipping rename.',
+ vim.log.levels.ERROR
+ )
+ return
+ end
+ -- no need to preserve if such a buffer is empty
+ api.nvim_buf_delete(existing_buf, {})
+ end
+
+ buf_rename[b] = { from = old_bname, to = new_bname }
end
- local ok, err = os.rename(old_fname, new_fname)
+ local newdir = assert(vim.fs.dirname(new_fname))
+ vim.fn.mkdir(newdir, 'p')
+
+ local ok, err = os.rename(old_fname_full, new_fname)
assert(ok, err)
- if vim.fn.isdirectory(new_fname) == 0 then
- local newbuf = vim.fn.bufadd(new_fname)
- if win then
- api.nvim_win_set_buf(win, newbuf)
- end
+ local old_undofile = vim.fn.undofile(old_fname_full)
+ if uv.fs_stat(old_undofile) ~= nil then
+ local new_undofile = vim.fn.undofile(new_fname)
+ vim.fn.mkdir(assert(vim.fs.dirname(new_undofile)), 'p')
+ os.rename(old_undofile, new_undofile)
end
- for _, b in ipairs(oldbufs) do
- api.nvim_buf_delete(b, {})
+ for b, rename in pairs(buf_rename) do
+ -- Rename with :saveas. This does two things:
+ -- * Unset BF_WRITE_MASK, so that users don't get E13 when they do :write.
+ -- * Send didClose and didOpen via textDocument/didSave handler.
+ api.nvim_buf_call(b, function()
+ vim.cmd('keepalt saveas! ' .. vim.fn.fnameescape(rename.to))
+ end)
+ -- Delete the new buffer with the old name created by :saveas. nvim_buf_delete and
+ -- :bwipeout are futile because the buffer will be added again somewhere else.
+ vim.cmd('bdelete! ' .. vim.fn.bufnr(rename.from))
end
end
@@ -745,7 +807,7 @@ end
---
---@param workspace_edit table `WorkspaceEdit`
---@param offset_encoding string utf-8|utf-16|utf-32 (required)
---see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
+---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_applyEdit
function M.apply_workspace_edit(workspace_edit, offset_encoding)
if offset_encoding == nil then
vim.notify_once(
@@ -789,7 +851,7 @@ end
--- Note that if the input is of type `MarkupContent` and its kind is `plaintext`,
--- then the corresponding value is returned without further modifications.
---
----@param input (`MarkedString` | `MarkedString[]` | `MarkupContent`)
+---@param input (lsp.MarkedString | lsp.MarkedString[] | lsp.MarkupContent)
---@param contents (table|nil) List of strings to extend with converted lines. Defaults to {}.
---@return string[] extended with lines of converted markdown.
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_hover
@@ -1055,7 +1117,7 @@ function M.show_document(location, offset_encoding, opts)
vim.fn.settagstack(vim.fn.win_getid(), { items = items }, 't')
end
- local win = opts.reuse_win and bufwinid(bufnr)
+ local win = opts.reuse_win and vim.fn.win_findbuf(bufnr)[1]
or focus and api.nvim_get_current_win()
or create_window_without_focus()
@@ -1068,7 +1130,7 @@ function M.show_document(location, offset_encoding, opts)
-- location may be Location or LocationLink
local range = location.range or location.targetSelectionRange
if range then
- --- Jump to new location (adjusting for encoding of characters)
+ -- Jump to new location (adjusting for encoding of characters)
local row = range.start.line
local col = get_line_byte_from_position(bufnr, range.start, offset_encoding)
api.nvim_win_set_cursor(win, { row + 1, col })
@@ -1105,6 +1167,7 @@ end
--- - for LocationLink, targetRange is shown (e.g., body of function definition)
---
---@param location table a single `Location` or `LocationLink`
+---@param opts table
---@return integer|nil buffer id of float window
---@return integer|nil window id of float window
function M.preview_location(location, opts)
@@ -1218,6 +1281,7 @@ end
---
--- If you want to open a popup with fancy markdown, use `open_floating_preview` instead
---
+---@param bufnr integer
---@param contents table of lines to show in window
---@param opts table with optional fields
--- - height of floating window
@@ -1410,7 +1474,7 @@ function M.stylize_markdown(bufnr, contents, opts)
return stripped
end
---- @class lsp.util.NormalizeMarkdownOptions
+--- @class (private) vim.lsp.util._normalize_markdown.Opts
--- @field width integer Thematic breaks are expanded to this size. Defaults to 80.
--- Normalizes Markdown input to a canonical form.
@@ -1426,7 +1490,7 @@ end
---
---@private
---@param contents string[]
----@param opts? lsp.util.NormalizeMarkdownOptions
+---@param opts? vim.lsp.util._normalize_markdown.Opts
---@return string[] table of lines containing normalized Markdown
---@see https://github.github.com/gfm
function M._normalize_markdown(contents, opts)
@@ -1497,7 +1561,7 @@ local function close_preview_autocmd(events, winnr, bufnrs)
end
end
----@internal
+---@private
--- Computes size of float needed to show contents (with optional wrapping)
---
---@param contents table of lines to show in window
@@ -1573,24 +1637,50 @@ function M._make_floating_popup_size(contents, opts)
return width, height
end
+--- @class vim.lsp.util.open_floating_preview.Opts
+--- @inlinedoc
+---
+--- Height of floating window
+--- @field height? integer
+---
+--- Width of floating window
+--- @field width? integer
+---
+--- Wrap long lines
+--- (default: `true`)
+--- @field wrap? boolean
+---
+--- Character to wrap at for computing height when wrap is enabled
+--- @field wrap_at? integer
+---
+--- Maximal width of floating window
+--- @field max_width? integer
+---
+--- Maximal height of floating window
+--- @field max_height? integer
+---
+--- If a popup with this id is opened, then focus it
+--- @field focus_id? string
+---
+--- List of events that closes the floating window
+--- @field close_events? table
+---
+--- Make float focusable.
+--- (default: `true`)
+--- @field focusable? boolean
+---
+--- If `true`, and if {focusable} is also `true`, focus an existing floating
+--- window with the same {focus_id}
+--- (default: `true`)
+--- @field focus? boolean
+
--- Shows contents in a floating window.
---
---@param contents table of lines to show in window
---@param syntax string of syntax to set for opened buffer
----@param opts table with optional fields (additional keys are filtered with |vim.lsp.util.make_floating_popup_options()|
---- before they are passed on to |nvim_open_win()|)
---- - height: (integer) height of floating window
---- - width: (integer) width of floating window
---- - wrap: (boolean, default true) wrap long lines
---- - wrap_at: (integer) character to wrap at for computing height when wrap is enabled
---- - max_width: (integer) maximal width of floating window
---- - max_height: (integer) maximal height of floating window
---- - focus_id: (string) if a popup with this id is opened, then focus it
---- - close_events: (table) list of events that closes the floating window
---- - focusable: (boolean, default true) Make float focusable
---- - focus: (boolean, default true) If `true`, and if {focusable}
---- is also `true`, focus an existing floating window with the same
---- {focus_id}
+---@param opts? vim.lsp.util.open_floating_preview.Opts with optional fields
+--- (additional keys are filtered with |vim.lsp.util.make_floating_popup_options()|
+--- before they are passed on to |nvim_open_win()|)
---@return integer bufnr of newly created float window
---@return integer winid of newly created float window preview window
function M.open_floating_preview(contents, syntax, opts)
@@ -1754,6 +1844,14 @@ local position_sort = sort_by_key(function(v)
return { v.start.line, v.start.character }
end)
+---@class vim.lsp.util.locations_to_items.ret
+---@inlinedoc
+---@field filename string
+---@field lnum integer 1-indexed line number
+---@field col integer 1-indexed column
+---@field text string
+---@field user_data lsp.Location|lsp.LocationLink
+
--- Returns the items with the byte position calculated correctly and in sorted
--- order, for display in quickfix and location lists.
---
@@ -1763,10 +1861,10 @@ end)
--- The result can be passed to the {list} argument of |setqflist()| or
--- |setloclist()|.
---
----@param locations table list of `Location`s or `LocationLink`s
+---@param locations lsp.Location[]|lsp.LocationLink[]
---@param offset_encoding string offset_encoding for locations utf-8|utf-16|utf-32
--- default to first client of buffer
----@return table list of items
+---@return vim.lsp.util.locations_to_items.ret[]
function M.locations_to_items(locations, offset_encoding)
if offset_encoding == nil then
vim.notify_once(
@@ -1777,6 +1875,7 @@ function M.locations_to_items(locations, offset_encoding)
end
local items = {}
+ ---@type table<string, {start: lsp.Position, location: lsp.Location|lsp.LocationLink}[]>
local grouped = setmetatable({}, {
__index = function(t, k)
local v = {}
@@ -1791,6 +1890,7 @@ function M.locations_to_items(locations, offset_encoding)
table.insert(grouped[uri], { start = range.start, location = d })
end
+ ---@type string[]
local keys = vim.tbl_keys(grouped)
table.sort(keys)
-- TODO(ashkan) I wish we could do this lazily.
@@ -1799,16 +1899,13 @@ function M.locations_to_items(locations, offset_encoding)
table.sort(rows, position_sort)
local filename = vim.uri_to_fname(uri)
- -- list of row numbers
- local uri_rows = {}
+ local line_numbers = {}
for _, temp in ipairs(rows) do
- local pos = temp.start
- local row = pos.line
- table.insert(uri_rows, row)
+ table.insert(line_numbers, temp.start.line)
end
-- get all the lines for this uri
- local lines = get_lines(vim.uri_to_bufnr(uri), uri_rows)
+ local lines = get_lines(vim.uri_to_bufnr(uri), line_numbers)
for _, temp in ipairs(rows) do
local pos = temp.start
@@ -1837,6 +1934,7 @@ end
--- Converts symbols to quickfix list items.
---
---@param symbols table DocumentSymbol[] or SymbolInformation[]
+---@param bufnr integer
function M.symbols_to_items(symbols, bufnr)
local function _symbols_to_items(_symbols, _items, _bufnr)
for _, symbol in ipairs(_symbols) do
@@ -1879,6 +1977,7 @@ end
---@param lines table list of lines to trim
---@return table trimmed list of lines
function M.trim_empty_lines(lines)
+ vim.deprecate('vim.lsp.util.trim_empty_lines()', 'vim.split() with `trimempty`', '0.12')
local start = 1
for i = 1, #lines do
if lines[i] ~= nil and #lines[i] > 0 then
@@ -1905,6 +2004,7 @@ end
---@param lines table list of lines
---@return string filetype or "markdown" if it was unchanged.
function M.try_trim_markdown_code_blocks(lines)
+ vim.deprecate('vim.lsp.util.try_trim_markdown_code_blocks()', 'nil', '0.12')
local language_id = lines[1]:match('^```(.*)')
if language_id then
local has_inner_code_fence = false
@@ -2089,7 +2189,7 @@ end
--- Creates a `DocumentFormattingParams` object for the current buffer and cursor position.
---
---@param options table|nil with valid `FormattingOptions` entries
----@return `DocumentFormattingParams` object
+---@return lsp.DocumentFormattingParams object
---@see https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting
function M.make_formatting_params(options)
validate({ options = { options, 't', true } })
@@ -2106,8 +2206,8 @@ end
--- Returns the UTF-32 and UTF-16 offsets for a position in a certain buffer.
---
---@param buf integer buffer number (0 for current)
----@param row 0-indexed line
----@param col 0-indexed byte offset in line
+---@param row integer 0-indexed line
+---@param col integer 0-indexed byte offset in line
---@param offset_encoding string utf-8|utf-16|utf-32 defaults to `offset_encoding` of first client of `buf`
---@return integer `offset_encoding` index of the character in line {row} column {col} in buffer {buf}
function M.character_offset(buf, row, col, offset_encoding)
@@ -2130,8 +2230,10 @@ end
---
---@param settings table language server settings
---@param section string indicating the field of the settings table
----@return table|string The value of settings accessed via section
+---@return table|string|vim.NIL The value of settings accessed via section. `vim.NIL` if not found.
+---@deprecated
function M.lookup_section(settings, section)
+ vim.deprecate('vim.lsp.util.lookup_section()', 'vim.tbl_get() with `vim.split`', '0.12')
for part in vim.gsplit(section, '.', { plain = true }) do
settings = settings[part]
if settings == nil then
@@ -2170,16 +2272,16 @@ local function make_line_range_params(bufnr, start_line, end_line, offset_encodi
}
end
----@private
---- Request updated LSP information for a buffer.
----
----@class lsp.util.RefreshOptions
+---@class (private) vim.lsp.util._refresh.Opts
---@field bufnr integer? Buffer to refresh (default: 0)
---@field only_visible? boolean Whether to only refresh for the visible regions of the buffer (default: false)
---@field client_id? integer Client ID to refresh (default: all clients)
---
+
+---@private
+--- Request updated LSP information for a buffer.
+---
---@param method string LSP method to call
----@param opts? lsp.util.RefreshOptions Options table
+---@param opts? vim.lsp.util._refresh.Opts Options table
function M._refresh(method, opts)
opts = opts or {}
local bufnr = opts.bufnr
@@ -2228,6 +2330,6 @@ end
M._get_line_byte_from_position = get_line_byte_from_position
---@nodoc
-M.buf_versions = {}
+M.buf_versions = {} ---@type table<integer,integer>
return M
diff --git a/runtime/lua/vim/provider.lua b/runtime/lua/vim/provider.lua
new file mode 100644
index 0000000000..08b3fd6cbd
--- /dev/null
+++ b/runtime/lua/vim/provider.lua
@@ -0,0 +1,7 @@
+local M = vim._defer_require('vim.provider', {
+ perl = ..., --- @module 'vim.provider.perl'
+ python = ..., --- @module 'vim.provider.python'
+ ruby = ..., --- @module 'vim.provider.ruby'
+})
+
+return M
diff --git a/runtime/lua/vim/provider/perl.lua b/runtime/lua/vim/provider/perl.lua
new file mode 100644
index 0000000000..da4af0a2a7
--- /dev/null
+++ b/runtime/lua/vim/provider/perl.lua
@@ -0,0 +1,66 @@
+local M = {}
+local s_err ---@type string?
+local s_host ---@type string?
+
+function M.require(host, prog)
+ local args = { prog, '-e', 'use Neovim::Ext; start_host();' }
+
+ -- Collect registered perl plugins into args
+ local perl_plugins = vim.fn['remote#host#PluginsForHost'](host.name) ---@type any
+ ---@param plugin any
+ for _, plugin in ipairs(perl_plugins) do
+ table.insert(args, plugin.path)
+ end
+
+ return vim.fn['provider#Poll'](args, host.orig_name, '$NVIM_PERL_LOG_FILE')
+end
+
+--- @return string? path to detected perl, if any; nil if not found
+--- @return string? error message if perl can't be detected; nil if success
+function M.detect()
+ -- use g:perl_host_prog if set or check if perl is on the path
+ local prog = vim.fn.exepath(vim.g.perl_host_prog or 'perl')
+ if prog == '' then
+ return nil, 'No perl executable found'
+ end
+
+ -- if perl is available, make sure we have 5.22+
+ vim.fn.system({ prog, '-e', 'use v5.22' })
+ if vim.v.shell_error ~= 0 then
+ return nil, 'Perl version is too old, 5.22+ required'
+ end
+
+ -- if perl is available, make sure the required module is available
+ vim.fn.system({ prog, '-W', '-MNeovim::Ext', '-e', '' })
+ if vim.v.shell_error ~= 0 then
+ return nil, '"Neovim::Ext" cpan module is not installed'
+ end
+ return prog, nil
+end
+
+function M.call(method, args)
+ if s_err then
+ return
+ end
+
+ if not s_host then
+ -- Ensure that we can load the Perl host before bootstrapping
+ local ok, result = pcall(vim.fn['remote#host#Require'], 'legacy-perl-provider') ---@type any, any
+ if not ok then
+ s_err = result
+ vim.api.nvim_echo({ { result, 'WarningMsg' } }, true, {})
+ return
+ end
+ s_host = result
+ end
+
+ return vim.fn.rpcrequest(s_host, 'perl_' .. method, unpack(args))
+end
+
+function M.start()
+ -- The perl provider plugin will run in a separate instance of the perl host.
+ vim.fn['remote#host#RegisterClone']('legacy-perl-provider', 'perl')
+ vim.fn['remote#host#RegisterPlugin']('legacy-perl-provider', 'ScriptHost.pm', {})
+end
+
+return M
diff --git a/runtime/lua/vim/provider/python.lua b/runtime/lua/vim/provider/python.lua
new file mode 100644
index 0000000000..8322131238
--- /dev/null
+++ b/runtime/lua/vim/provider/python.lua
@@ -0,0 +1,150 @@
+local M = {}
+local min_version = '3.7'
+local s_err ---@type string?
+local s_host ---@type string?
+
+local python_candidates = {
+ 'python3',
+ 'python3.12',
+ 'python3.11',
+ 'python3.10',
+ 'python3.9',
+ 'python3.8',
+ 'python3.7',
+ 'python',
+}
+
+--- @param prog string
+--- @param module string
+--- @return integer, string
+local function import_module(prog, module)
+ local program = [[
+import sys, importlib.util;
+sys.path = [p for p in sys.path if p != ""];
+sys.stdout.write(str(sys.version_info[0]) + "." + str(sys.version_info[1]));]]
+
+ program = program
+ .. string.format('sys.exit(2 * int(importlib.util.find_spec("%s") is None))', module)
+
+ local out = vim.system({ prog, '-W', 'ignore', '-c', program }):wait()
+ return out.code, assert(out.stdout)
+end
+
+--- @param prog string
+--- @param module string
+--- @return string?
+local function check_for_module(prog, module)
+ local prog_path = vim.fn.exepath(prog)
+ if prog_path == '' then
+ return prog .. ' not found in search path or not executable.'
+ end
+
+ -- Try to load module, and output Python version.
+ -- Exit codes:
+ -- 0 module can be loaded.
+ -- 2 module cannot be loaded.
+ -- Otherwise something else went wrong (e.g. 1 or 127).
+ local prog_exitcode, prog_version = import_module(prog, module)
+ if prog_exitcode == 2 or prog_exitcode == 0 then
+ -- Check version only for expected return codes.
+ if vim.version.lt(prog_version, min_version) then
+ return string.format(
+ '%s is Python %s and cannot provide Python >= %s.',
+ prog_path,
+ prog_version,
+ min_version
+ )
+ end
+ end
+
+ if prog_exitcode == 2 then
+ return string.format('%s does not have the "%s" module.', prog_path, module)
+ elseif prog_exitcode == 127 then
+ -- This can happen with pyenv's shims.
+ return string.format('%s does not exist: %s', prog_path, prog_version)
+ elseif prog_exitcode ~= 0 then
+ return string.format(
+ 'Checking %s caused an unknown error. (%s, output: %s) Report this at https://github.com/neovim/neovim',
+ prog_path,
+ prog_exitcode,
+ prog_version
+ )
+ end
+
+ return nil
+end
+
+--- @param module string
+--- @return string? path to detected python, if any; nil if not found
+--- @return string? error message if python can't be detected by {module}; nil if success
+function M.detect_by_module(module)
+ local python_exe = vim.fn.expand(vim.g.python3_host_prog or '', true)
+
+ if python_exe ~= '' then
+ return vim.fn.exepath(vim.fn.expand(python_exe, true)), nil
+ end
+
+ local errors = {}
+ for _, exe in ipairs(python_candidates) do
+ local error = check_for_module(exe, module)
+ if not error then
+ return exe, error
+ end
+ -- Accumulate errors in case we don't find any suitable Python executable.
+ table.insert(errors, error)
+ end
+
+ -- No suitable Python executable found.
+ return nil, 'Could not load Python :\n' .. table.concat(errors, '\n')
+end
+
+function M.require(host)
+ -- Python host arguments
+ local prog = M.detect_by_module('neovim')
+ local args = {
+ prog,
+ '-c',
+ 'import sys; sys.path = [p for p in sys.path if p != ""]; import neovim; neovim.start_host()',
+ }
+
+ -- Collect registered Python plugins into args
+ local python_plugins = vim.fn['remote#host#PluginsForHost'](host.name) ---@type any
+ ---@param plugin any
+ for _, plugin in ipairs(python_plugins) do
+ table.insert(args, plugin.path)
+ end
+
+ return vim.fn['provider#Poll'](
+ args,
+ host.orig_name,
+ '$NVIM_PYTHON_LOG_FILE',
+ { ['overlapped'] = true }
+ )
+end
+
+function M.call(method, args)
+ if s_err then
+ return
+ end
+
+ if not s_host then
+ -- Ensure that we can load the Python3 host before bootstrapping
+ local ok, result = pcall(vim.fn['remote#host#Require'], 'legacy-python3-provider') ---@type any, any
+ if not ok then
+ s_err = result
+ vim.api.nvim_echo({ { result, 'WarningMsg' } }, true, {})
+ return
+ end
+ s_host = result
+ end
+
+ return vim.fn.rpcrequest(s_host, 'python_' .. method, unpack(args))
+end
+
+function M.start()
+ -- The Python3 provider plugin will run in a separate instance of the Python3 host.
+ vim.fn['remote#host#RegisterClone']('legacy-python3-provider', 'python3')
+ vim.fn['remote#host#RegisterPlugin']('legacy-python3-provider', 'script_host.py', {})
+end
+
+return M
diff --git a/runtime/lua/vim/provider/ruby.lua b/runtime/lua/vim/provider/ruby.lua
new file mode 100644
index 0000000000..3ad86001f3
--- /dev/null
+++ b/runtime/lua/vim/provider/ruby.lua
@@ -0,0 +1,61 @@
+local M = {}
+local s_err ---@type string?
+local s_host ---@type string?
+
+function M.require(host)
+ local prog = M.detect()
+ local args = { prog }
+ local ruby_plugins = vim.fn['remote#host#PluginsForHost'](host.name) ---@type any
+
+ ---@param plugin any
+ for _, plugin in ipairs(ruby_plugins) do
+ table.insert(args, plugin.path)
+ end
+
+ return vim.fn['provider#Poll'](args, host.orig_name, '$NVIM_RUBY_LOG_FILE')
+end
+
+function M.call(method, args)
+ if s_err then
+ return
+ end
+
+ if not s_host then
+ local ok, result = pcall(vim.fn['remote#host#Require'], 'legacy-ruby-provider') ---@type any, any
+ if not ok then
+ s_err = result
+ vim.api.nvim_echo({ { result, 'WarningMsg' } }, true, {})
+ return
+ end
+ s_host = result
+ end
+
+ return vim.fn.rpcrequest(s_host, 'ruby_' .. method, unpack(args))
+end
+
+function M.detect()
+ local prog ---@type string
+ if vim.g.ruby_host_prog then
+ prog = vim.fn.expand(vim.g.ruby_host_prog, true)
+ elseif vim.fn.has('win32') == 1 then
+ prog = vim.fn.exepath('neovim-ruby-host.bat')
+ else
+ local p = vim.fn.exepath('neovim-ruby-host')
+ if p == '' then
+ prog = ''
+ else
+ -- neovim-ruby-host could be an rbenv shim for another Ruby version.
+ vim.fn.system(p)
+ prog = vim.v.shell_error ~= 0 and '' or p
+ end
+ end
+ local err = prog == '' and 'missing ruby or ruby-host' or ''
+ return prog, err
+end
+
+function M.start(plugin_path)
+ vim.fn['remote#host#RegisterClone']('legacy-ruby-provider', 'ruby')
+ vim.fn['remote#host#RegisterPlugin']('legacy-ruby-provider', plugin_path, {})
+end
+
+return M
diff --git a/runtime/lua/vim/re.lua b/runtime/lua/vim/re.lua
index 007eb27ed8..114f74eb80 100644
--- a/runtime/lua/vim/re.lua
+++ b/runtime/lua/vim/re.lua
@@ -3,6 +3,7 @@
-- written by Roberto Ierusalimschy
--
--- vendored from lpeg-1.1.0
+--- documentation available at runtime/lua/vim/_meta/re.lua
-- imported functions and modules
local tonumber, type, print, error = tonumber, type, print, error
diff --git a/runtime/lua/vim/secure.lua b/runtime/lua/vim/secure.lua
index d29c356af3..3992eef78a 100644
--- a/runtime/lua/vim/secure.lua
+++ b/runtime/lua/vim/secure.lua
@@ -108,22 +108,25 @@ function M.read(path)
return contents
end
----@class vim.trust.opts
----@field action string
----@field path? string
----@field bufnr? integer
+--- @class vim.trust.opts
+--- @inlinedoc
+---
+--- - `'allow'` to add a file to the trust database and trust it,
+--- - `'deny'` to add a file to the trust database and deny it,
+--- - `'remove'` to remove file from the trust database
+--- @field action 'allow'|'deny'|'remove'
+---
+--- Path to a file to update. Mutually exclusive with {bufnr}.
+--- Cannot be used when {action} is "allow".
+--- @field path? string
+--- Buffer number to update. Mutually exclusive with {path}.
+--- @field bufnr? integer
--- Manage the trust database.
---
--- The trust database is located at |$XDG_STATE_HOME|/nvim/trust.
---
----@param opts (table):
---- - action (string): "allow" to add a file to the trust database and trust it,
---- "deny" to add a file to the trust database and deny it,
---- "remove" to remove file from the trust database
---- - path (string|nil): Path to a file to update. Mutually exclusive with {bufnr}.
---- Cannot be used when {action} is "allow".
---- - bufnr (number|nil): Buffer number to update. Mutually exclusive with {path}.
+---@param opts? vim.trust.opts
---@return boolean success true if operation was successful
---@return string msg full path if operation was successful, else error message
function M.trust(opts)
diff --git a/runtime/lua/vim/shared.lua b/runtime/lua/vim/shared.lua
index 9542d93789..bd553598c7 100644
--- a/runtime/lua/vim/shared.lua
+++ b/runtime/lua/vim/shared.lua
@@ -6,46 +6,40 @@
-- or the test suite. (Eventually the test suite will be run in a worker process,
-- so this wouldn't be a separate case to consider)
+---@nodoc
---@diagnostic disable-next-line: lowercase-global
vim = vim or {}
-local function _id(v)
- return v
-end
+---@generic T
+---@param orig T
+---@param cache? table<any,any>
+---@return T
+local function deepcopy(orig, cache)
+ if orig == vim.NIL then
+ return vim.NIL
+ elseif type(orig) == 'userdata' or type(orig) == 'thread' then
+ error('Cannot deepcopy object of type ' .. type(orig))
+ elseif type(orig) ~= 'table' then
+ return orig
+ end
-local deepcopy
+ --- @cast orig table<any,any>
-local deepcopy_funcs = {
- table = function(orig, cache)
- if cache[orig] then
- return cache[orig]
- end
- local copy = {}
+ if cache and cache[orig] then
+ return cache[orig]
+ end
+ local copy = {} --- @type table<any,any>
+
+ if cache then
cache[orig] = copy
- local mt = getmetatable(orig)
- for k, v in pairs(orig) do
- copy[deepcopy(k, cache)] = deepcopy(v, cache)
- end
- return setmetatable(copy, mt)
- end,
- number = _id,
- string = _id,
- ['nil'] = _id,
- boolean = _id,
- ['function'] = _id,
-}
-
-deepcopy = function(orig, _cache)
- local f = deepcopy_funcs[type(orig)]
- if f then
- return f(orig, _cache or {})
- else
- if type(orig) == 'userdata' and orig == vim.NIL then
- return vim.NIL
- end
- error('Cannot deepcopy object of type ' .. type(orig))
end
+
+ for k, v in pairs(orig) do
+ copy[deepcopy(k, cache)] = deepcopy(v, cache)
+ end
+
+ return setmetatable(copy, getmetatable(orig))
end
--- Returns a deep copy of the given object. Non-table objects are copied as
@@ -54,13 +48,31 @@ end
--- same functions as those in the input table. Userdata and threads are not
--- copied and will throw an error.
---
+--- Note: `noref=true` is much more performant on tables with unique table
+--- fields, while `noref=false` is more performant on tables that reuse table
+--- fields.
+---
---@generic T: table
---@param orig T Table to copy
+---@param noref? boolean
+--- When `false` (default) a contained table is only copied once and all
+--- references point to this single copy. When `true` every occurrence of a
+--- table results in a new copy. This also means that a cyclic reference can
+--- cause `deepcopy()` to fail.
---@return T Table of copied keys and (nested) values.
-function vim.deepcopy(orig)
- return deepcopy(orig)
+function vim.deepcopy(orig, noref)
+ return deepcopy(orig, not noref and {} or nil)
end
+--- @class vim.gsplit.Opts
+--- @inlinedoc
+---
+--- Use `sep` literally (as in string.find).
+--- @field plain? boolean
+---
+--- Discard empty segments at start and end of the sequence.
+--- @field trimempty? boolean
+
--- Gets an |iterator| that splits a string at each instance of a separator, in "lazy" fashion
--- (as opposed to |vim.split()| which is "eager").
---
@@ -89,12 +101,10 @@ end
---
--- @param s string String to split
--- @param sep string Separator or pattern
---- @param opts (table|nil) Keyword arguments |kwargs|:
---- - plain: (boolean) Use `sep` literally (as in string.find).
---- - trimempty: (boolean) Discard empty segments at start and end of the sequence.
----@return fun():string|nil (function) Iterator over the split components
+--- @param opts? vim.gsplit.Opts Keyword arguments |kwargs|:
+--- @return fun():string? : Iterator over the split components
function vim.gsplit(s, sep, opts)
- local plain
+ local plain --- @type boolean?
local trimempty = false
if type(opts) == 'boolean' then
plain = opts -- For backwards compatibility.
@@ -111,6 +121,11 @@ function vim.gsplit(s, sep, opts)
local segs = {}
local empty_start = true -- Only empty segments seen so far.
+ --- @param i integer?
+ --- @param j integer
+ --- @param ... unknown
+ --- @return string
+ --- @return ...
local function _pass(i, j, ...)
if i then
assert(j + 1 > start, 'Infinite loop detected')
@@ -180,8 +195,8 @@ end
---
---@param s string String to split
---@param sep string Separator or pattern
----@param opts (table|nil) Keyword arguments |kwargs| accepted by |vim.gsplit()|
----@return string[] List of split components
+---@param opts? vim.gsplit.Opts Keyword arguments |kwargs|:
+---@return string[] : List of split components
function vim.split(s, sep, opts)
local t = {}
for c in vim.gsplit(s, sep, opts) do
@@ -195,14 +210,15 @@ end
---
---@see From https://github.com/premake/premake-core/blob/master/src/base/table.lua
---
----@generic T: table
+---@generic T
---@param t table<T, any> (table) Table
----@return T[] (list) List of keys
+---@return T[] : List of keys
function vim.tbl_keys(t)
- assert(type(t) == 'table', string.format('Expected table, got %s', type(t)))
+ vim.validate({ t = { t, 't' } })
+ --- @cast t table<any,any>
local keys = {}
- for k, _ in pairs(t) do
+ for k in pairs(t) do
table.insert(keys, k)
end
return keys
@@ -213,12 +229,14 @@ end
---
---@generic T
---@param t table<any, T> (table) Table
----@return T[] (list) List of values
+---@return T[] : List of values
function vim.tbl_values(t)
- assert(type(t) == 'table', string.format('Expected table, got %s', type(t)))
+ vim.validate({ t = { t, 't' } })
local values = {}
- for _, v in pairs(t) do
+ for _, v in
+ pairs(t --[[@as table<any,any>]])
+ do
table.insert(values, v)
end
return values
@@ -227,13 +245,14 @@ end
--- Apply a function to all values of a table.
---
---@generic T
----@param func fun(value: T): any (function) Function
----@param t table<any, T> (table) Table
----@return table Table of transformed values
+---@param func fun(value: T): any Function
+---@param t table<any, T> Table
+---@return table : Table of transformed values
function vim.tbl_map(func, t)
vim.validate({ func = { func, 'c' }, t = { t, 't' } })
+ --- @cast t table<any,any>
- local rettab = {}
+ local rettab = {} --- @type table<any,any>
for k, v in pairs(t) do
rettab[k] = func(v)
end
@@ -245,19 +264,26 @@ end
---@generic T
---@param func fun(value: T): boolean (function) Function
---@param t table<any, T> (table) Table
----@return T[] (table) Table of filtered values
+---@return T[] : Table of filtered values
function vim.tbl_filter(func, t)
vim.validate({ func = { func, 'c' }, t = { t, 't' } })
+ --- @cast t table<any,any>
- local rettab = {}
+ local rettab = {} --- @type table<any,any>
for _, entry in pairs(t) do
if func(entry) then
- table.insert(rettab, entry)
+ rettab[#rettab + 1] = entry
end
end
return rettab
end
+--- @class vim.tbl_contains.Opts
+--- @inlinedoc
+---
+--- `value` is a function reference to be checked (default false)
+--- @field predicate? boolean
+
--- Checks if a table contains a given value, specified either directly or via
--- a predicate that is checked for each value.
---
@@ -274,13 +300,13 @@ end
---
---@param t table Table to check
---@param value any Value to compare or predicate function reference
----@param opts (table|nil) Keyword arguments |kwargs|:
---- - predicate: (boolean) `value` is a function reference to be checked (default false)
+---@param opts? vim.tbl_contains.Opts Keyword arguments |kwargs|:
---@return boolean `true` if `t` contains `value`
function vim.tbl_contains(t, value, opts)
vim.validate({ t = { t, 't' }, opts = { opts, 't', true } })
+ --- @cast t table<any,any>
- local pred
+ local pred --- @type fun(v: any): boolean?
if opts and opts.predicate then
vim.validate({ value = { value, 'c' } })
pred = value
@@ -307,6 +333,7 @@ end
---@return boolean `true` if `t` contains `value`
function vim.list_contains(t, value)
vim.validate({ t = { t, 't' } })
+ --- @cast t table<any,any>
for _, v in ipairs(t) do
if v == value then
@@ -323,7 +350,7 @@ end
---@param t table Table to check
---@return boolean `true` if `t` is empty
function vim.tbl_isempty(t)
- assert(type(t) == 'table', string.format('Expected table, got %s', type(t)))
+ vim.validate({ t = { t, 't' } })
return next(t) == nil
end
@@ -345,7 +372,7 @@ local function tbl_extend(behavior, deep_extend, ...)
)
end
- local ret = {}
+ local ret = {} --- @type table<any,any>
if vim._empty_dict_mt ~= nil and getmetatable(select(1, ...)) == vim._empty_dict_mt then
ret = vim.empty_dict()
end
@@ -353,6 +380,7 @@ local function tbl_extend(behavior, deep_extend, ...)
for i = 1, select('#', ...) do
local tbl = select(i, ...)
vim.validate({ ['after the second argument'] = { tbl, 't' } })
+ --- @cast tbl table<any,any>
if tbl then
for k, v in pairs(tbl) do
if deep_extend and can_merge(v) and can_merge(ret[k]) then
@@ -379,7 +407,7 @@ end
--- - "keep": use value from the leftmost map
--- - "force": use value from the rightmost map
---@param ... table Two or more tables
----@return table Merged table
+---@return table : Merged table
function vim.tbl_extend(behavior, ...)
return tbl_extend(behavior, false, ...)
end
@@ -415,12 +443,14 @@ function vim.deep_equal(a, b)
return false
end
if type(a) == 'table' then
+ --- @cast a table<any,any>
+ --- @cast b table<any,any>
for k, v in pairs(a) do
if not vim.deep_equal(v, b[k]) then
return false
end
end
- for k, _ in pairs(b) do
+ for k in pairs(b) do
if a[k] == nil then
return false
end
@@ -432,12 +462,17 @@ end
--- Add the reverse lookup values to an existing table.
--- For example:
---- ``tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }``
+--- `tbl_add_reverse_lookup { A = 1 } == { [1] = 'A', A = 1 }`
---
--- Note that this *modifies* the input.
+---@deprecated
---@param o table Table to add the reverse to
---@return table o
function vim.tbl_add_reverse_lookup(o)
+ vim.deprecate('vim.tbl_add_reverse_lookup', nil, '0.12')
+
+ --- @cast o table<any,any>
+ --- @type any[]
local keys = vim.tbl_keys(o)
for _, k in ipairs(keys) do
local v = o[k]
@@ -467,15 +502,14 @@ end
---
---@param o table Table to index
---@param ... any Optional keys (0 or more, variadic) via which to index the table
----
----@return any Nested value indexed by key (if it exists), else nil
+---@return any : Nested value indexed by key (if it exists), else nil
function vim.tbl_get(o, ...)
local keys = { ... }
if #keys == 0 then
return nil
end
for i, k in ipairs(keys) do
- o = o[k]
+ o = o[k] --- @type any
if o == nil then
return nil
elseif type(o) ~= 'table' and next(keys, i) then
@@ -494,8 +528,8 @@ end
---@generic T: table
---@param dst T List which will be modified and appended to
---@param src table List from which values will be inserted
----@param start (integer|nil) Start index on src. Defaults to 1
----@param finish (integer|nil) Final index on src. Defaults to `#src`
+---@param start integer? Start index on src. Defaults to 1
+---@param finish integer? Final index on src. Defaults to `#src`
---@return T dst
function vim.list_extend(dst, src, start, finish)
vim.validate({
@@ -519,6 +553,7 @@ end
---@return table Flattened copy of the given list-like table
function vim.tbl_flatten(t)
local result = {}
+ --- @param _t table<any,any>
local function _tbl_flatten(_t)
local n = #_t
for i = 1, n do
@@ -538,10 +573,13 @@ end
---
---@see Based on https://github.com/premake/premake-core/blob/master/src/base/table.lua
---
----@param t table Dict-like table
----@return function # |for-in| iterator over sorted keys and their values
+---@generic T: table, K, V
+---@param t T Dict-like table
+---@return fun(table: table<K, V>, index?: K):K, V # |for-in| iterator over sorted keys and their values
+---@return T
function vim.spairs(t)
- assert(type(t) == 'table', string.format('Expected table, got %s', type(t)))
+ vim.validate({ t = { t, 't' } })
+ --- @cast t table<any,any>
-- collect the keys
local keys = {}
@@ -557,7 +595,8 @@ function vim.spairs(t)
if keys[i] then
return keys[i], t[keys[i]]
end
- end
+ end,
+ t
end
--- Tests if `t` is an "array": a table indexed _only_ by integers (potentially non-contiguous).
@@ -576,10 +615,12 @@ function vim.tbl_isarray(t)
return false
end
+ --- @cast t table<any,any>
+
local count = 0
for k, _ in pairs(t) do
- --- Check if the number k is an integer
+ -- Check if the number k is an integer
if type(k) == 'number' and k == math.floor(k) then
count = count + 1
else
@@ -614,23 +655,21 @@ function vim.tbl_islist(t)
return false
end
- local num_elem = vim.tbl_count(t)
-
- if num_elem == 0 then
- -- TODO(bfredl): in the future, we will always be inside nvim
- -- then this check can be deleted.
- if vim._empty_dict_mt == nil then
- return nil
- end
+ if next(t) == nil then
return getmetatable(t) ~= vim._empty_dict_mt
- else
- for i = 1, num_elem do
- if t[i] == nil then
- return false
- end
+ end
+
+ local j = 1
+ for _ in
+ pairs(t--[[@as table<any,any>]])
+ do
+ if t[j] == nil then
+ return false
end
- return true
+ j = j + 1
end
+
+ return true
end
--- Counts the number of non-nil values in table `t`.
@@ -642,9 +681,10 @@ end
---
---@see https://github.com/Tieske/Penlight/blob/master/lua/pl/tablex.lua
---@param t table Table
----@return integer Number of non-nil values in table
+---@return integer : Number of non-nil values in table
function vim.tbl_count(t)
vim.validate({ t = { t, 't' } })
+ --- @cast t table<any,any>
local count = 0
for _ in pairs(t) do
@@ -656,12 +696,12 @@ end
--- Creates a copy of a table containing only elements from start to end (inclusive)
---
---@generic T
----@param list T[] (list) Table
+---@param list T[] Table
---@param start integer|nil Start range of slice
---@param finish integer|nil End range of slice
----@return T[] (list) Copy of table sliced from start to finish (inclusive)
+---@return T[] Copy of table sliced from start to finish (inclusive)
function vim.list_slice(list, start, finish)
- local new_list = {}
+ local new_list = {} --- @type `T`[]
for i = start or 1, finish or #list do
new_list[#new_list + 1] = list[i]
end
@@ -710,6 +750,16 @@ function vim.endswith(s, suffix)
end
do
+ --- @alias vim.validate.Type
+ --- | 't' | 'table'
+ --- | 's' | 'string'
+ --- | 'n' | 'number'
+ --- | 'f' | 'function'
+ --- | 'c' | 'callable'
+ --- | 'nil'
+ --- | 'thread'
+ --- | 'userdata
+
local type_names = {
['table'] = 'table',
t = 'table',
@@ -728,10 +778,18 @@ do
['userdata'] = 'userdata',
}
+ --- @nodoc
+ --- @class vim.validate.Spec {[1]: any, [2]: string|string[], [3]: boolean }
+ --- @field [1] any Argument value
+ --- @field [2] string|string[]|fun(v:any):boolean, string? Type name, or callable
+ --- @field [3]? boolean
+
local function _is_type(val, t)
return type(val) == t or (t == 'callable' and vim.is_callable(val))
end
+ --- @param opt table<vim.validate.Type,vim.validate.Spec>
+ --- @return boolean, string?
local function is_valid(opt)
if type(opt) ~= 'table' then
return false, string.format('opt: expected table, got %s', type(opt))
@@ -790,7 +848,7 @@ do
end
end
- return true, nil
+ return true
end
--- Validates a parameter specification (types and values).
@@ -798,41 +856,40 @@ do
--- Usage example:
---
--- ```lua
- --- function user.new(name, age, hobbies)
- --- vim.validate{
- --- name={name, 'string'},
- --- age={age, 'number'},
- --- hobbies={hobbies, 'table'},
- --- }
- --- ...
- --- end
+ --- function user.new(name, age, hobbies)
+ --- vim.validate{
+ --- name={name, 'string'},
+ --- age={age, 'number'},
+ --- hobbies={hobbies, 'table'},
+ --- }
+ --- ...
+ --- end
--- ```
---
--- Examples with explicit argument values (can be run directly):
---
--- ```lua
- --- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}}
- --- --> NOP (success)
+ --- vim.validate{arg1={{'foo'}, 'table'}, arg2={'foo', 'string'}}
+ --- --> NOP (success)
---
- --- vim.validate{arg1={1, 'table'}}
- --- --> error('arg1: expected table, got number')
+ --- vim.validate{arg1={1, 'table'}}
+ --- --> error('arg1: expected table, got number')
---
- --- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
- --- --> error('arg1: expected even number, got 3')
+ --- vim.validate{arg1={3, function(a) return (a % 2) == 0 end, 'even number'}}
+ --- --> error('arg1: expected even number, got 3')
--- ```
---
--- If multiple types are valid they can be given as a list.
---
--- ```lua
- --- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}}
- --- -- NOP (success)
- ---
- --- vim.validate{arg1={1, {'string', 'table'}}}
- --- -- error('arg1: expected string|table, got number')
+ --- vim.validate{arg1={{'foo'}, {'table', 'string'}}, arg2={'foo', {'table', 'string'}}}
+ --- -- NOP (success)
---
+ --- vim.validate{arg1={1, {'string', 'table'}}}
+ --- -- error('arg1: expected string|table, got number')
--- ```
---
- ---@param opt table Names of parameters to validate. Each key is a parameter
+ ---@param opt table<vim.validate.Type,vim.validate.Spec> (table) Names of parameters to validate. Each key is a parameter
--- name; each value is a tuple in one of these forms:
--- 1. (arg_value, type_name, optional)
--- - arg_value: argument value
@@ -878,7 +935,7 @@ end
--- a.b.c = 1
--- ```
---
----@param createfn function?(key:any):any Provides the value for a missing `key`.
+---@param createfn? fun(key:any):any Provides the value for a missing `key`.
---@return table # Empty table with `__index` metamethod.
function vim.defaulttable(createfn)
createfn = createfn or function(_)
@@ -898,6 +955,7 @@ do
---@field private _idx_read integer
---@field private _idx_write integer
---@field private _size integer
+ ---@overload fun(self): table?
local Ringbuf = {}
--- Clear all items
@@ -946,19 +1004,19 @@ do
--- Once the buffer is full, adding a new entry overrides the oldest entry.
---
--- ```lua
- --- local ringbuf = vim.ringbuf(4)
- --- ringbuf:push("a")
- --- ringbuf:push("b")
- --- ringbuf:push("c")
- --- ringbuf:push("d")
- --- ringbuf:push("e") -- overrides "a"
- --- print(ringbuf:pop()) -- returns "b"
- --- print(ringbuf:pop()) -- returns "c"
+ --- local ringbuf = vim.ringbuf(4)
+ --- ringbuf:push("a")
+ --- ringbuf:push("b")
+ --- ringbuf:push("c")
+ --- ringbuf:push("d")
+ --- ringbuf:push("e") -- overrides "a"
+ --- print(ringbuf:pop()) -- returns "b"
+ --- print(ringbuf:pop()) -- returns "c"
---
- --- -- Can be used as iterator. Pops remaining items:
- --- for val in ringbuf do
- --- print(val)
- --- end
+ --- -- Can be used as iterator. Pops remaining items:
+ --- for val in ringbuf do
+ --- print(val)
+ --- end
--- ```
---
--- Returns a Ringbuf instance with the following methods:
@@ -969,7 +1027,7 @@ do
--- - |Ringbuf:clear()|
---
---@param size integer
- ---@return vim.Ringbuf ringbuf (table)
+ ---@return vim.Ringbuf ringbuf
function vim.ringbuf(size)
local ringbuf = {
_items = {},
@@ -986,4 +1044,24 @@ do
end
end
+--- @private
+--- @generic T
+--- @param root string
+--- @param mod T
+--- @return T
+function vim._defer_require(root, mod)
+ return setmetatable({}, {
+ ---@param t table<string, any>
+ ---@param k string
+ __index = function(t, k)
+ if not mod[k] then
+ return
+ end
+ local name = string.format('%s.%s', root, k)
+ t[k] = require(name)
+ return t[k]
+ end,
+ })
+end
+
return vim
diff --git a/runtime/lua/vim/snippet.lua b/runtime/lua/vim/snippet.lua
index 32a8ea0b0d..5e60efa778 100644
--- a/runtime/lua/vim/snippet.lua
+++ b/runtime/lua/vim/snippet.lua
@@ -1,6 +1,7 @@
-local G = require('vim.lsp._snippet_grammar')
+local G = vim.lsp._snippet_grammar
local snippet_group = vim.api.nvim_create_augroup('vim/snippet', {})
local snippet_ns = vim.api.nvim_create_namespace('vim/snippet')
+local hl_group = 'SnippetTabstop'
--- Returns the 0-based cursor position.
---
@@ -42,9 +43,7 @@ local function resolve_variable(var, default)
elseif var == 'TM_FILENAME' then
return expand_or_default('%:t')
elseif var == 'TM_FILENAME_BASE' then
- -- Not using '%:t:r' since we want to remove all extensions.
- local filename_base = expand_or_default('%:t'):gsub('%.[^%.]*$', '')
- return filename_base
+ return expand_or_default('%:t:r')
elseif var == 'TM_DIRECTORY' then
return expand_or_default('%:p:h:t')
elseif var == 'TM_FILEPATH' then
@@ -102,7 +101,7 @@ local function get_extmark_range(bufnr, extmark_id)
return { mark[1], mark[2], mark[3].end_row, mark[3].end_col }
end
---- @class vim.snippet.Tabstop
+--- @class (private) vim.snippet.Tabstop
--- @field extmark_id integer
--- @field bufnr integer
--- @field index integer
@@ -119,11 +118,11 @@ local Tabstop = {}
--- @return vim.snippet.Tabstop
function Tabstop.new(index, bufnr, range, choices)
local extmark_id = vim.api.nvim_buf_set_extmark(bufnr, snippet_ns, range[1], range[2], {
- right_gravity = false,
+ right_gravity = true,
end_right_gravity = true,
end_line = range[3],
end_col = range[4],
- hl_group = 'SnippetTabstop',
+ hl_group = hl_group,
})
local self = setmetatable(
@@ -163,7 +162,22 @@ function Tabstop:set_text(text)
vim.api.nvim_buf_set_text(self.bufnr, range[1], range[2], range[3], range[4], text_to_lines(text))
end
---- @class vim.snippet.Session
+--- Sets the right gravity of the tabstop's extmark.
+---
+--- @package
+--- @param right_gravity boolean
+function Tabstop:set_right_gravity(right_gravity)
+ local range = self:get_range()
+ self.extmark_id = vim.api.nvim_buf_set_extmark(self.bufnr, snippet_ns, range[1], range[2], {
+ right_gravity = right_gravity,
+ end_right_gravity = true,
+ end_line = range[3],
+ end_col = range[4],
+ hl_group = hl_group,
+ })
+end
+
+--- @class (private) vim.snippet.Session
--- @field bufnr integer
--- @field extmark_id integer
--- @field tabstops table<integer, vim.snippet.Tabstop[]>
@@ -220,8 +234,17 @@ function Session:get_dest_index(direction)
end
end
---- @class vim.snippet.Snippet
---- @field private _session? vim.snippet.Session
+--- Sets the right gravity of the tabstop group with the given index.
+---
+--- @package
+--- @param index integer
+--- @param right_gravity boolean
+function Session:set_group_gravity(index, right_gravity)
+ for _, tabstop in ipairs(self.tabstops[index]) do
+ tabstop:set_right_gravity(right_gravity)
+ end
+end
+
local M = { session = nil }
--- Displays the choices for the given tabstop as completion items.
@@ -562,9 +585,15 @@ function M.jump(direction)
-- Clear the autocommands so that we can move the cursor freely while selecting the tabstop.
vim.api.nvim_clear_autocmds({ group = snippet_group, buffer = M._session.bufnr })
+ -- Deactivate expansion of the current tabstop.
+ M._session:set_group_gravity(M._session.current_tabstop.index, true)
+
M._session.current_tabstop = dest
select_tabstop(dest)
+ -- Activate expansion of the destination tabstop.
+ M._session:set_group_gravity(dest.index, false)
+
-- Restore the autocommands.
setup_autocmds(M._session.bufnr)
end
diff --git a/runtime/lua/vim/termcap.lua b/runtime/lua/vim/termcap.lua
index 862cc52149..ec29acca48 100644
--- a/runtime/lua/vim/termcap.lua
+++ b/runtime/lua/vim/termcap.lua
@@ -12,7 +12,10 @@ local M = {}
--- emulator supports the XTGETTCAP sequence.
---
--- @param caps string|table A terminal capability or list of capabilities to query
---- @param cb function(cap:string, seq:string) Function to call when a response is received
+--- @param cb function(cap:string, found:bool, seq:string?) Callback function which is called for
+--- each capability in {caps}. {found} is set to true if the capability was found or false
+--- otherwise. {seq} is the control sequence for the capability if found, or nil for
+--- boolean capabilities.
function M.query(caps, cb)
vim.validate({
caps = { caps, { 'string', 'table' } },
@@ -23,21 +26,40 @@ function M.query(caps, cb)
caps = { caps }
end
- local count = #caps
+ local pending = {} ---@type table<string, boolean>
+ for _, v in ipairs(caps) do
+ pending[v] = true
+ end
+
+ local timer = assert(vim.uv.new_timer())
- vim.api.nvim_create_autocmd('TermResponse', {
+ local id = vim.api.nvim_create_autocmd('TermResponse', {
+ nested = true,
callback = function(args)
local resp = args.data ---@type string
- local k, v = resp:match('^\027P1%+r(%x+)=(%x+)$')
- if k and v then
+ local k, rest = resp:match('^\027P1%+r(%x+)(.*)$')
+ if k and rest then
local cap = vim.text.hexdecode(k)
- local seq =
- vim.text.hexdecode(v):gsub('\\E', '\027'):gsub('%%p%d', ''):gsub('\\(%d+)', string.char)
+ if not pending[cap] then
+ -- Received a response for a capability we didn't request. This can happen if there are
+ -- multiple concurrent XTGETTCAP requests
+ return
+ end
+
+ local seq ---@type string?
+ if rest:match('^=%x+$') then
+ seq = vim.text
+ .hexdecode(rest:sub(2))
+ :gsub('\\E', '\027')
+ :gsub('%%p%d', '')
+ :gsub('\\(%d+)', string.char)
+ end
- cb(cap, seq)
+ cb(cap, true, seq)
- count = count - 1
- if count == 0 then
+ pending[cap] = nil
+
+ if next(pending) == nil then
return true
end
end
@@ -57,6 +79,23 @@ function M.query(caps, cb)
end
io.stdout:write(query)
+
+ timer:start(1000, 0, function()
+ -- Delete the autocommand if no response was received
+ vim.schedule(function()
+ -- Suppress error if autocommand has already been deleted
+ pcall(vim.api.nvim_del_autocmd, id)
+
+ -- Call the callback for all capabilities that were not found
+ for k in pairs(pending) do
+ cb(k, false, nil)
+ end
+ end)
+
+ if not timer:is_closing() then
+ timer:close()
+ end
+ end)
end
return M
diff --git a/runtime/lua/vim/text.lua b/runtime/lua/vim/text.lua
index cfb0f9b821..576b962838 100644
--- a/runtime/lua/vim/text.lua
+++ b/runtime/lua/vim/text.lua
@@ -1,4 +1,4 @@
---- Text processing functions.
+-- Text processing functions.
local M = {}
diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua
index e7a66c00b2..a09619f369 100644
--- a/runtime/lua/vim/treesitter.lua
+++ b/runtime/lua/vim/treesitter.lua
@@ -1,44 +1,21 @@
local api = vim.api
-local LanguageTree = require('vim.treesitter.languagetree')
-local Range = require('vim.treesitter._range')
----@type table<integer,LanguageTree>
+---@type table<integer,vim.treesitter.LanguageTree>
local parsers = setmetatable({}, { __mode = 'v' })
----@class TreesitterModule
----@field highlighter TSHighlighter
----@field query TSQueryModule
----@field language TSLanguageModule
-local M = setmetatable({}, {
- __index = function(t, k)
- ---@diagnostic disable:no-unknown
- if k == 'highlighter' then
- t[k] = require('vim.treesitter.highlighter')
- return t[k]
- elseif k == 'language' then
- t[k] = require('vim.treesitter.language')
- return t[k]
- elseif k == 'query' then
- t[k] = require('vim.treesitter.query')
- return t[k]
- end
-
- local query = require('vim.treesitter.query')
- if query[k] then
- vim.deprecate('vim.treesitter.' .. k .. '()', 'vim.treesitter.query.' .. k .. '()', '0.10')
- t[k] = query[k]
- return t[k]
- end
-
- local language = require('vim.treesitter.language')
- if language[k] then
- vim.deprecate('vim.treesitter.' .. k .. '()', 'vim.treesitter.language.' .. k .. '()', '0.10')
- t[k] = language[k]
- return t[k]
- end
- end,
+local M = vim._defer_require('vim.treesitter', {
+ _fold = ..., --- @module 'vim.treesitter._fold'
+ _query_linter = ..., --- @module 'vim.treesitter._query_linter'
+ _range = ..., --- @module 'vim.treesitter._range'
+ dev = ..., --- @module 'vim.treesitter.dev'
+ highlighter = ..., --- @module 'vim.treesitter.highlighter'
+ language = ..., --- @module 'vim.treesitter.language'
+ languagetree = ..., --- @module 'vim.treesitter.languagetree'
+ query = ..., --- @module 'vim.treesitter.query'
})
+local LanguageTree = M.languagetree
+
--- @nodoc
M.language_version = vim._ts_get_language_version()
@@ -53,7 +30,7 @@ M.minimum_language_version = vim._ts_get_minimum_language_version()
---@param lang string Language of the parser
---@param opts (table|nil) Options to pass to the created language tree
---
----@return LanguageTree object to use for parsing
+---@return vim.treesitter.LanguageTree object to use for parsing
function M._create_parser(bufnr, lang, opts)
if bufnr == 0 then
bufnr = vim.api.nvim_get_current_buf()
@@ -100,10 +77,10 @@ end
--- If needed, this will create the parser.
---
---@param bufnr (integer|nil) Buffer the parser should be tied to (default: current buffer)
----@param lang (string|nil) Filetype of this parser (default: buffer filetype)
+---@param lang (string|nil) Language of this parser (default: from buffer filetype)
---@param opts (table|nil) Options to pass to the created language tree
---
----@return LanguageTree object to use for parsing
+---@return vim.treesitter.LanguageTree object to use for parsing
function M.get_parser(bufnr, lang, opts)
opts = opts or {}
@@ -142,7 +119,7 @@ end
---@param lang string Language of this string
---@param opts (table|nil) Options to pass to the created language tree
---
----@return LanguageTree object to use for parsing
+---@return vim.treesitter.LanguageTree object to use for parsing
function M.get_string_parser(str, lang, opts)
vim.validate({
str = { str, 'string' },
@@ -195,12 +172,12 @@ end
---to get the range with directives applied.
---@param node TSNode
---@param source integer|string|nil Buffer or string from which the {node} is extracted
----@param metadata TSMetadata|nil
+---@param metadata vim.treesitter.query.TSMetadata|nil
---@return Range6
function M.get_range(node, source, metadata)
if metadata and metadata.range then
assert(source)
- return Range.add_bytes(source, metadata.range)
+ return M._range.add_bytes(source, metadata.range)
end
return { node:range(true) }
end
@@ -209,7 +186,7 @@ end
---@param range Range
---@returns string
local function buf_range_get_text(buf, range)
- local start_row, start_col, end_row, end_col = Range.unpack4(range)
+ local start_row, start_col, end_row, end_col = M._range.unpack4(range)
if end_col == 0 then
if start_row == end_row then
start_col = -1
@@ -237,7 +214,7 @@ function M.get_node_text(node, source, opts)
if metadata.text then
return metadata.text
elseif type(source) == 'number' then
- local range = vim.treesitter.get_range(node, source, metadata)
+ local range = M.get_range(node, source, metadata)
return buf_range_get_text(source, range)
end
@@ -266,9 +243,9 @@ function M.node_contains(node, range)
vim.validate({
-- allow a table so nodes can be mocked
node = { node, { 'userdata', 'table' } },
- range = { range, Range.validate, 'integer list with 4 or 6 elements' },
+ range = { range, M._range.validate, 'integer list with 4 or 6 elements' },
})
- return Range.contains({ node:range() }, range)
+ return M._range.contains({ node:range() }, range)
end
--- Returns a list of highlight captures at the given position
@@ -317,6 +294,7 @@ function M.get_captures_at_pos(bufnr, row, col)
for capture, node, metadata in iter do
if M.is_in_node_range(node, row, col) then
+ ---@diagnostic disable-next-line: invisible
local c = q._query.captures[capture] -- name of the capture in the query
if c ~= nil then
table.insert(matches, { capture = c, metadata = metadata, lang = tree:lang() })
@@ -348,6 +326,23 @@ function M.get_captures_at_cursor(winnr)
return captures
end
+--- Optional keyword arguments:
+--- @class vim.treesitter.get_node.Opts
+--- @inlinedoc
+---
+--- Buffer number (nil or 0 for current buffer)
+--- @field bufnr integer?
+---
+--- 0-indexed (row, col) tuple. Defaults to cursor position in the
+--- current window. Required if {bufnr} is not the current buffer
+--- @field pos { [1]: integer, [2]: integer }?
+---
+--- Parser language. (default: from buffer filetype)
+--- @field lang string?
+---
+--- Ignore injected languages (default true)
+--- @field ignore_injections boolean?
+
--- Returns the smallest named node at the given position
---
--- NOTE: Calling this on an unparsed tree can yield an invalid node.
@@ -358,11 +353,7 @@ end
--- vim.treesitter.get_parser(bufnr):parse(range)
--- ```
---
----@param opts table|nil Optional keyword arguments:
---- - bufnr integer|nil Buffer number (nil or 0 for current buffer)
---- - pos table|nil 0-indexed (row, col) tuple. Defaults to cursor position in the
---- current window. Required if {bufnr} is not the current buffer
---- - ignore_injections boolean Ignore injected languages (default true)
+---@param opts vim.treesitter.get_node.Opts?
---
---@return TSNode | nil Node at the given position
function M.get_node(opts)
@@ -374,7 +365,7 @@ function M.get_node(opts)
bufnr = api.nvim_get_current_buf()
end
- local row, col
+ local row, col --- @type integer, integer
if opts.pos then
assert(#opts.pos == 2, 'Position must be a (row, col) tuple')
row, col = opts.pos[1], opts.pos[2]
@@ -392,34 +383,6 @@ function M.get_node(opts)
local ts_range = { row, col, row, col }
- local root_lang_tree = M.get_parser(bufnr)
- if not root_lang_tree then
- return
- end
-
- return root_lang_tree:named_node_for_range(ts_range, opts)
-end
-
---- Returns the smallest named node at the given position
----
----@param bufnr integer Buffer number (0 for current buffer)
----@param row integer Position row
----@param col integer Position column
----@param opts table Optional keyword arguments:
---- - lang string|nil Parser language
---- - ignore_injections boolean Ignore injected languages (default true)
----
----@return TSNode | nil Node at the given position
----@deprecated
-function M.get_node_at_pos(bufnr, row, col, opts)
- vim.deprecate('vim.treesitter.get_node_at_pos()', 'vim.treesitter.get_node()', '0.10')
- if bufnr == 0 then
- bufnr = api.nvim_get_current_buf()
- end
- local ts_range = { row, col, row, col }
-
- opts = opts or {}
-
local root_lang_tree = M.get_parser(bufnr, opts.lang)
if not root_lang_tree then
return
@@ -428,26 +391,12 @@ function M.get_node_at_pos(bufnr, row, col, opts)
return root_lang_tree:named_node_for_range(ts_range, opts)
end
---- Returns the smallest named node under the cursor
----
----@param winnr (integer|nil) Window handle or 0 for current window (default)
----
----@return string Name of node under the cursor
----@deprecated
-function M.get_node_at_cursor(winnr)
- vim.deprecate('vim.treesitter.get_node_at_cursor()', 'vim.treesitter.get_node():type()', '0.10')
- winnr = winnr or 0
- local bufnr = api.nvim_win_get_buf(winnr)
-
- return M.get_node({ bufnr = bufnr, ignore_injections = false }):type()
-end
-
--- Starts treesitter highlighting for a buffer
---
--- Can be used in an ftplugin or FileType autocommand.
---
--- Note: By default, disables regex syntax highlighting, which may be required for some plugins.
---- In this case, add ``vim.bo.syntax = 'on'`` after the call to `start`.
+--- In this case, add `vim.bo.syntax = 'on'` after the call to `start`.
---
--- Example:
---
@@ -461,7 +410,7 @@ end
--- ```
---
---@param bufnr (integer|nil) Buffer to be highlighted (default: current buffer)
----@param lang (string|nil) Language of the parser (default: buffer filetype)
+---@param lang (string|nil) Language of the parser (default: from buffer filetype)
function M.start(bufnr, lang)
bufnr = bufnr or api.nvim_get_current_buf()
local parser = M.get_parser(bufnr, lang)
@@ -483,13 +432,14 @@ end
---
--- While in the window, press "a" to toggle display of anonymous nodes, "I" to toggle the
--- display of the source language of each node, "o" to toggle the query editor, and press
---- <Enter> to jump to the node under the cursor in the source buffer.
+--- [<Enter>] to jump to the node under the cursor in the source buffer. Folding also works
+--- (try |zo|, |zc|, etc.).
---
---- Can also be shown with `:InspectTree`. *:InspectTree*
+--- Can also be shown with `:InspectTree`. [:InspectTree]()
---
---@param opts table|nil Optional options table with the following possible keys:
---- - lang (string|nil): The language of the source buffer. If omitted, the
---- filetype of the source buffer is used.
+--- - lang (string|nil): The language of the source buffer. If omitted, detect
+--- from the filetype of the source buffer.
--- - bufnr (integer|nil): Buffer to draw the tree into. If omitted, a new
--- buffer is created.
--- - winid (integer|nil): Window id to display the tree buffer in. If omitted,
@@ -501,7 +451,7 @@ end
--- argument and should return a string.
function M.inspect_tree(opts)
---@diagnostic disable-next-line: invisible
- require('vim.treesitter.dev').inspect_tree(opts)
+ M.dev.inspect_tree(opts)
end
--- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr':
@@ -513,19 +463,7 @@ end
---@param lnum integer|nil Line number to calculate fold level for
---@return string
function M.foldexpr(lnum)
- return require('vim.treesitter._fold').foldexpr(lnum)
-end
-
---- Returns the highlighted content of the first line of the fold or falls back to |foldtext()|
---- if no treesitter parser is found. Can be set directly to 'foldtext':
----
---- ```lua
---- vim.wo.foldtext = 'v:lua.vim.treesitter.foldtext()'
---- ```
----
----@return { [1]: string, [2]: string[] }[] | string
-function M.foldtext()
- return require('vim.treesitter._fold').foldtext()
+ return M._fold.foldexpr(lnum)
end
return M
diff --git a/runtime/lua/vim/treesitter/_fold.lua b/runtime/lua/vim/treesitter/_fold.lua
index 5c1cc06908..d96cc966de 100644
--- a/runtime/lua/vim/treesitter/_fold.lua
+++ b/runtime/lua/vim/treesitter/_fold.lua
@@ -5,35 +5,20 @@ local Range = require('vim.treesitter._range')
local api = vim.api
---@class TS.FoldInfo
----@field levels table<integer,string>
----@field levels0 table<integer,integer>
----@field private start_counts table<integer,integer>
----@field private stop_counts table<integer,integer>
+---@field levels string[] the foldexpr result for each line
+---@field levels0 integer[] the raw fold levels
+---@field edits? {[1]: integer, [2]: integer} line range edited since the last invocation of the callback scheduled in on_bytes. 0-indexed, end-exclusive.
local FoldInfo = {}
FoldInfo.__index = FoldInfo
---@private
function FoldInfo.new()
return setmetatable({
- start_counts = {},
- stop_counts = {},
levels0 = {},
levels = {},
}, FoldInfo)
end
----@package
----@param srow integer
----@param erow integer
-function FoldInfo:invalidate_range(srow, erow)
- for i = srow, erow do
- self.start_counts[i + 1] = nil
- self.stop_counts[i + 1] = nil
- self.levels0[i + 1] = nil
- self.levels[i + 1] = nil
- end
-end
-
--- Efficiently remove items from middle of a list a list.
---
--- Calling table.remove() in a loop will re-index the tail of the table on
@@ -55,12 +40,10 @@ end
---@package
---@param srow integer
----@param erow integer
+---@param erow integer 0-indexed, exclusive
function FoldInfo:remove_range(srow, erow)
list_remove(self.levels, srow + 1, erow)
list_remove(self.levels0, srow + 1, erow)
- list_remove(self.start_counts, srow + 1, erow)
- list_remove(self.stop_counts, srow + 1, erow)
end
--- Efficiently insert items into the middle of a list.
@@ -91,46 +74,37 @@ end
---@package
---@param srow integer
----@param erow integer
+---@param erow integer 0-indexed, exclusive
function FoldInfo:add_range(srow, erow)
- list_insert(self.levels, srow + 1, erow, '-1')
+ list_insert(self.levels, srow + 1, erow, '=')
list_insert(self.levels0, srow + 1, erow, -1)
- list_insert(self.start_counts, srow + 1, erow, nil)
- list_insert(self.stop_counts, srow + 1, erow, nil)
end
---@package
----@param lnum integer
-function FoldInfo:add_start(lnum)
- self.start_counts[lnum] = (self.start_counts[lnum] or 0) + 1
-end
-
----@package
----@param lnum integer
-function FoldInfo:add_stop(lnum)
- self.stop_counts[lnum] = (self.stop_counts[lnum] or 0) + 1
-end
-
----@package
----@param lnum integer
----@return integer
-function FoldInfo:get_start(lnum)
- return self.start_counts[lnum] or 0
+---@param srow integer
+---@param erow_old integer
+---@param erow_new integer 0-indexed, exclusive
+function FoldInfo:edit_range(srow, erow_old, erow_new)
+ if self.edits then
+ self.edits[1] = math.min(srow, self.edits[1])
+ if erow_old <= self.edits[2] then
+ self.edits[2] = self.edits[2] + (erow_new - erow_old)
+ end
+ self.edits[2] = math.max(self.edits[2], erow_new)
+ else
+ self.edits = { srow, erow_new }
+ end
end
---@package
----@param lnum integer
----@return integer
-function FoldInfo:get_stop(lnum)
- return self.stop_counts[lnum] or 0
-end
-
-local function trim_level(level)
- local max_fold_level = vim.wo.foldnestmax
- if level > max_fold_level then
- return max_fold_level
+---@return integer? srow
+---@return integer? erow 0-indexed, exclusive
+function FoldInfo:flush_edit()
+ if self.edits then
+ local srow, erow = self.edits[1], self.edits[2]
+ self.edits = nil
+ return srow, erow
end
- return level
end
--- If a parser doesn't have any ranges explicitly set, treesitter will
@@ -140,10 +114,10 @@ end
--- TODO(lewis6991): Handle this generally
---
--- @param bufnr integer
---- @param erow integer?
+--- @param erow integer? 0-indexed, exclusive
--- @return integer
local function normalise_erow(bufnr, erow)
- local max_erow = api.nvim_buf_line_count(bufnr) - 1
+ local max_erow = api.nvim_buf_line_count(bufnr)
return math.min(erow or max_erow, max_erow)
end
@@ -152,31 +126,30 @@ end
---@param bufnr integer
---@param info TS.FoldInfo
---@param srow integer?
----@param erow integer?
+---@param erow integer? 0-indexed, exclusive
---@param parse_injections? boolean
local function get_folds_levels(bufnr, info, srow, erow, parse_injections)
srow = srow or 0
erow = normalise_erow(bufnr, erow)
- info:invalidate_range(srow, erow)
-
- local prev_start = -1
- local prev_stop = -1
-
local parser = ts.get_parser(bufnr)
parser:parse(parse_injections and { srow, erow } or nil)
+ local enter_counts = {} ---@type table<integer, integer>
+ local leave_counts = {} ---@type table<integer, integer>
+ local prev_start = -1
+ local prev_stop = -1
+
parser:for_each_tree(function(tree, ltree)
local query = ts.query.get(ltree:lang(), 'folds')
if not query then
return
end
- -- erow in query is end-exclusive
- local q_erow = erow and erow + 1 or -1
-
- for id, node, metadata in query:iter_captures(tree:root(), bufnr, srow, q_erow) do
+ -- Collect folds starting from srow - 1, because we should first subtract the folds that end at
+ -- srow - 1 from the level of srow - 1 to get accurate level of srow.
+ for id, node, metadata in query:iter_captures(tree:root(), bufnr, math.max(srow - 1, 0), erow) do
if query.captures[id] == 'fold' then
local range = ts.get_range(node, bufnr, metadata[id])
local start, _, stop, stop_col = Range.unpack4(range)
@@ -193,8 +166,8 @@ local function get_folds_levels(bufnr, info, srow, erow, parse_injections)
if
fold_length > vim.wo.foldminlines and not (start == prev_start and stop == prev_stop)
then
- info:add_start(start + 1)
- info:add_stop(stop + 1)
+ enter_counts[start + 1] = (enter_counts[start + 1] or 0) + 1
+ leave_counts[stop + 1] = (leave_counts[stop + 1] or 0) + 1
prev_start = start
prev_stop = stop
end
@@ -202,16 +175,15 @@ local function get_folds_levels(bufnr, info, srow, erow, parse_injections)
end
end)
- local current_level = info.levels0[srow] or 0
+ local nestmax = vim.wo.foldnestmax
+ local level0_prev = info.levels0[srow] or 0
+ local leave_prev = leave_counts[srow] or 0
-- We now have the list of fold opening and closing, fill the gaps and mark where fold start
- for lnum = srow + 1, erow + 1 do
- local last_trimmed_level = trim_level(current_level)
- current_level = current_level + info:get_start(lnum)
- info.levels0[lnum] = current_level
-
- local trimmed_level = trim_level(current_level)
- current_level = current_level - info:get_stop(lnum)
+ for lnum = srow + 1, erow do
+ local enter_line = enter_counts[lnum] or 0
+ local leave_line = leave_counts[lnum] or 0
+ local level0 = level0_prev - leave_prev + enter_line
-- Determine if it's the start/end of a fold
-- NB: vim's fold-expr interface does not have a mechanism to indicate that
@@ -219,14 +191,36 @@ local function get_folds_levels(bufnr, info, srow, erow, parse_injections)
-- ( \n ( \n )) \n (( \n ) \n )
-- versus
-- ( \n ( \n ) \n ( \n ) \n )
- -- If it did have such a mechanism, (trimmed_level - last_trimmed_level)
+ -- Both are represented by ['>1', '>2', '2', '>2', '2', '1'], and
+ -- vim interprets as the second case.
+ -- If it did have such a mechanism, (clamped - clamped_prev)
-- would be the correct number of starts to pass on.
+ local adjusted = level0 ---@type integer
local prefix = ''
- if trimmed_level - last_trimmed_level > 0 then
+ if enter_line > 0 then
prefix = '>'
+ if leave_line > 0 then
+ -- If this line ends a fold f1 and starts a fold f2, then move f1's end to the previous line
+ -- so that f2 gets the correct level on this line. This may reduce the size of f1 below
+ -- foldminlines, but we don't handle it for simplicity.
+ adjusted = level0 - leave_line
+ leave_line = 0
+ end
+ end
+
+ -- Clamp at foldnestmax.
+ local clamped = adjusted
+ if adjusted > nestmax then
+ prefix = ''
+ clamped = nestmax
end
- info.levels[lnum] = prefix .. tostring(trimmed_level)
+ -- Record the "real" level, so that it can be used as "base" of later get_folds_levels().
+ info.levels0[lnum] = adjusted
+ info.levels[lnum] = prefix .. tostring(clamped)
+
+ leave_prev = leave_line
+ level0_prev = adjusted
end
end
@@ -296,8 +290,12 @@ end
local function on_changedtree(bufnr, foldinfo, tree_changes)
schedule_if_loaded(bufnr, function()
for _, change in ipairs(tree_changes) do
- local srow, _, erow = Range.unpack4(change)
- get_folds_levels(bufnr, foldinfo, srow, erow)
+ local srow, _, erow, ecol = Range.unpack4(change)
+ if ecol > 0 then
+ erow = erow + 1
+ end
+ -- Start from `srow - foldminlines`, because this edit may have shrunken the fold below limit.
+ get_folds_levels(bufnr, foldinfo, math.max(srow - vim.wo.foldminlines, 0), erow)
end
if #tree_changes > 0 then
foldupdate(bufnr)
@@ -309,19 +307,46 @@ end
---@param foldinfo TS.FoldInfo
---@param start_row integer
---@param old_row integer
+---@param old_col integer
---@param new_row integer
-local function on_bytes(bufnr, foldinfo, start_row, old_row, new_row)
- local end_row_old = start_row + old_row
- local end_row_new = start_row + new_row
+---@param new_col integer
+local function on_bytes(bufnr, foldinfo, start_row, start_col, old_row, old_col, new_row, new_col)
+ -- extend the end to fully include the range
+ local end_row_old = start_row + old_row + 1
+ local end_row_new = start_row + new_row + 1
if new_row ~= old_row then
+ -- foldexpr can be evaluated before the scheduled callback is invoked. So it may observe the
+ -- outdated levels, which may spuriously open the folds that didn't change. So we should shift
+ -- folds as accurately as possible. For this to be perfectly accurate, we should track the
+ -- actual TSNodes that account for each fold, and compare the node's range with the edited
+ -- range. But for simplicity, we just check whether the start row is completely removed (e.g.,
+ -- `dd`) or shifted (e.g., `o`).
if new_row < old_row then
- foldinfo:remove_range(end_row_new, end_row_old)
+ if start_col == 0 and new_row == 0 and new_col == 0 then
+ foldinfo:remove_range(start_row, start_row + (end_row_old - end_row_new))
+ else
+ foldinfo:remove_range(end_row_new, end_row_old)
+ end
else
- foldinfo:add_range(start_row, end_row_new)
+ if start_col == 0 and old_row == 0 and old_col == 0 then
+ foldinfo:add_range(start_row, start_row + (end_row_new - end_row_old))
+ else
+ foldinfo:add_range(end_row_old, end_row_new)
+ end
end
+ foldinfo:edit_range(start_row, end_row_old, end_row_new)
+
+ -- This callback must not use on_bytes arguments, because they can be outdated when the callback
+ -- is invoked. For example, `J` with non-zero count triggers multiple on_bytes before executing
+ -- the scheduled callback. So we should collect the edits.
schedule_if_loaded(bufnr, function()
- get_folds_levels(bufnr, foldinfo, start_row, end_row_new)
+ local srow, erow = foldinfo:flush_edit()
+ if not srow then
+ return
+ end
+ -- Start from `srow - foldminlines`, because this edit may have shrunken the fold below limit.
+ get_folds_levels(bufnr, foldinfo, math.max(srow - vim.wo.foldminlines, 0), erow)
foldupdate(bufnr)
end)
end
@@ -348,8 +373,8 @@ function M.foldexpr(lnum)
on_changedtree(bufnr, foldinfos[bufnr], tree_changes)
end,
- on_bytes = function(_, _, start_row, _, _, old_row, _, _, new_row, _, _)
- on_bytes(bufnr, foldinfos[bufnr], start_row, old_row, new_row)
+ on_bytes = function(_, _, start_row, start_col, _, old_row, old_col, _, new_row, new_col, _)
+ on_bytes(bufnr, foldinfos[bufnr], start_row, start_col, old_row, old_col, new_row, new_col)
end,
on_detach = function()
@@ -361,96 +386,15 @@ function M.foldexpr(lnum)
return foldinfos[bufnr].levels[lnum] or '0'
end
----@package
----@return { [1]: string, [2]: string[] }[]|string
-function M.foldtext()
- local foldstart = vim.v.foldstart
- local bufnr = api.nvim_get_current_buf()
-
- ---@type boolean, LanguageTree
- local ok, parser = pcall(ts.get_parser, bufnr)
- if not ok then
- return vim.fn.foldtext()
- end
-
- local query = ts.query.get(parser:lang(), 'highlights')
- if not query then
- return vim.fn.foldtext()
- end
-
- local tree = parser:parse({ foldstart - 1, foldstart })[1]
-
- local line = api.nvim_buf_get_lines(bufnr, foldstart - 1, foldstart, false)[1]
- if not line then
- return vim.fn.foldtext()
- end
-
- ---@type { [1]: string, [2]: string[], range: { [1]: integer, [2]: integer } }[] | { [1]: string, [2]: string[] }[]
- local result = {}
-
- local line_pos = 0
-
- for id, node, metadata in query:iter_captures(tree:root(), 0, foldstart - 1, foldstart) do
- local name = query.captures[id]
- local start_row, start_col, end_row, end_col = node:range()
-
- local priority = tonumber(metadata.priority or vim.highlight.priorities.treesitter)
-
- if start_row == foldstart - 1 and end_row == foldstart - 1 then
- -- check for characters ignored by treesitter
- if start_col > line_pos then
- table.insert(result, {
- line:sub(line_pos + 1, start_col),
- {},
- range = { line_pos, start_col },
- })
- end
- line_pos = end_col
-
- local text = line:sub(start_col + 1, end_col)
- table.insert(result, { text, { { '@' .. name, priority } }, range = { start_col, end_col } })
- end
- end
-
- local i = 1
- while i <= #result do
- -- find first capture that is not in current range and apply highlights on the way
- local j = i + 1
- while
- j <= #result
- and result[j].range[1] >= result[i].range[1]
- and result[j].range[2] <= result[i].range[2]
- do
- for k, v in ipairs(result[i][2]) do
- if not vim.tbl_contains(result[j][2], v) then
- table.insert(result[j][2], k, v)
- end
- end
- j = j + 1
- end
-
- -- remove the parent capture if it is split into children
- if j > i + 1 then
- table.remove(result, i)
- else
- -- highlights need to be sorted by priority, on equal prio, the deeper nested capture (earlier
- -- in list) should be considered higher prio
- if #result[i][2] > 1 then
- table.sort(result[i][2], function(a, b)
- return a[2] < b[2]
- end)
- end
-
- result[i][2] = vim.tbl_map(function(tbl)
- return tbl[1]
- end, result[i][2])
- result[i] = { result[i][1], result[i][2] }
-
- i = i + 1
+api.nvim_create_autocmd('OptionSet', {
+ pattern = { 'foldminlines', 'foldnestmax' },
+ desc = 'Refresh treesitter folds',
+ callback = function()
+ for _, bufnr in ipairs(vim.tbl_keys(foldinfos)) do
+ foldinfos[bufnr] = FoldInfo.new()
+ get_folds_levels(bufnr, foldinfos[bufnr])
+ foldupdate(bufnr)
end
- end
-
- return result
-end
-
+ end,
+})
return M
diff --git a/runtime/lua/vim/treesitter/_meta.lua b/runtime/lua/vim/treesitter/_meta.lua
index 80c998b555..19d97d2820 100644
--- a/runtime/lua/vim/treesitter/_meta.lua
+++ b/runtime/lua/vim/treesitter/_meta.lua
@@ -1,4 +1,5 @@
---@meta
+error('Cannot require a meta file')
---@class TSNode: userdata
---@field id fun(self: TSNode): string
@@ -33,27 +34,26 @@
---@field byte_length fun(self: TSNode): integer
local TSNode = {}
----@param query userdata
+---@param query TSQuery
---@param captures true
---@param start? integer
---@param end_? integer
---@param opts? table
----@return fun(): integer, TSNode, any
+---@return fun(): integer, TSNode, vim.treesitter.query.TSMatch
function TSNode:_rawquery(query, captures, start, end_, opts) end
----@param query userdata
+---@param query TSQuery
---@param captures false
---@param start? integer
---@param end_? integer
---@param opts? table
----@return fun(): string, any
+---@return fun(): integer, vim.treesitter.query.TSMatch
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: true): TSTree, Range6[]
----@field parse fun(self: TSParser, tree: TSTree?, source: integer|string, include_bytes: false|nil): TSTree, Range4[]
+---@class TSParser: userdata
+---@field parse fun(self: TSParser, tree: TSTree?, source: integer|string, include_bytes: boolean): TSTree, (Range4|Range6)[]
---@field reset fun(self: TSParser)
---@field included_ranges fun(self: TSParser, include_bytes: boolean?): integer[]
---@field set_included_ranges fun(self: TSParser, ranges: (Range6|TSNode)[])
@@ -62,19 +62,31 @@ function TSNode:_rawquery(query, captures, start, end_, opts) end
---@field _set_logger fun(self: TSParser, lex: boolean, parse: boolean, cb: TSLoggerCallback)
---@field _logger fun(self: TSParser): TSLoggerCallback
----@class TSTree
+---@class TSTree: userdata
---@field root fun(self: TSTree): TSNode
---@field edit fun(self: TSTree, _: integer, _: integer, _: integer, _: integer, _: integer, _: integer, _: integer, _: integer, _:integer)
---@field copy fun(self: TSTree): TSTree
---@field included_ranges fun(self: TSTree, include_bytes: true): Range6[]
---@field included_ranges fun(self: TSTree, include_bytes: false): Range4[]
+---@class TSQuery: userdata
+---@field inspect fun(self: TSQuery): TSQueryInfo
+
+---@class (exact) TSQueryInfo
+---@field captures string[]
+---@field patterns table<integer, (integer|string)[][]>
+
---@return integer
vim._ts_get_language_version = function() end
---@return integer
vim._ts_get_minimum_language_version = function() end
+---@param lang string Language to use for the query
+---@param query string Query string in s-expr syntax
+---@return TSQuery
+vim._ts_parse_query = function(lang, query) end
+
---@param lang string
---@return TSParser
vim._create_ts_parser = function(lang) end
diff --git a/runtime/lua/vim/treesitter/_query_linter.lua b/runtime/lua/vim/treesitter/_query_linter.lua
index 87d74789a3..6216d4e891 100644
--- a/runtime/lua/vim/treesitter/_query_linter.lua
+++ b/runtime/lua/vim/treesitter/_query_linter.lua
@@ -17,7 +17,7 @@ local M = {}
--- @field is_first_lang boolean Whether this is the first language of a linter run checking queries for multiple `langs`
--- Adds a diagnostic for node in the query buffer
---- @param diagnostics Diagnostic[]
+--- @param diagnostics vim.Diagnostic[]
--- @param range Range4
--- @param lint string
--- @param lang string?
@@ -45,7 +45,7 @@ local function guess_query_lang(buf)
end
--- @param buf integer
---- @param opts QueryLinterOpts|QueryLinterNormalizedOpts|nil
+--- @param opts vim.treesitter.query.lint.Opts|QueryLinterNormalizedOpts|nil
--- @return QueryLinterNormalizedOpts
local function normalize_opts(buf, opts)
opts = opts or {}
@@ -92,7 +92,7 @@ local function get_error_entry(err, node)
end_col = end_col + #underlined
elseif msg:match('^Invalid') then
-- Use the length of the problematic type/capture/field
- end_col = end_col + #msg:match('"([^"]+)"')
+ end_col = end_col + #(msg:match('"([^"]+)"') or '')
end
return {
@@ -114,7 +114,7 @@ end
--- @return vim.treesitter.ParseError?
local parse = vim.func._memoize(hash_parse, function(node, buf, lang)
local query_text = vim.treesitter.get_node_text(node, buf)
- local ok, err = pcall(vim.treesitter.query.parse, lang, query_text) ---@type boolean|vim.treesitter.ParseError, string|Query
+ local ok, err = pcall(vim.treesitter.query.parse, lang, query_text) ---@type boolean|vim.treesitter.ParseError, string|vim.treesitter.Query
if not ok and type(err) == 'string' then
return get_error_entry(err, node)
@@ -122,28 +122,30 @@ local parse = vim.func._memoize(hash_parse, function(node, buf, lang)
end)
--- @param buf integer
---- @param match table<integer,TSNode>
---- @param query Query
+--- @param match vim.treesitter.query.TSMatch
+--- @param query vim.treesitter.Query
--- @param lang_context QueryLinterLanguageContext
---- @param diagnostics Diagnostic[]
+--- @param diagnostics vim.Diagnostic[]
local function lint_match(buf, match, query, lang_context, diagnostics)
local lang = lang_context.lang
local parser_info = lang_context.parser_info
- for id, node in pairs(match) do
- local cap_id = query.captures[id]
+ for id, nodes in pairs(match) do
+ for _, node in ipairs(nodes) do
+ local cap_id = query.captures[id]
- -- perform language-independent checks only for first lang
- if lang_context.is_first_lang and cap_id == 'error' then
- local node_text = vim.treesitter.get_node_text(node, buf):gsub('\n', ' ')
- add_lint_for_node(diagnostics, { node:range() }, 'Syntax error: ' .. node_text)
- end
+ -- perform language-independent checks only for first lang
+ if lang_context.is_first_lang and cap_id == 'error' then
+ local node_text = vim.treesitter.get_node_text(node, buf):gsub('\n', ' ')
+ add_lint_for_node(diagnostics, { node:range() }, 'Syntax error: ' .. node_text)
+ end
- -- other checks rely on Neovim parser introspection
- if lang and parser_info and cap_id == 'toplevel' then
- local err = parse(node, buf, lang)
- if err then
- add_lint_for_node(diagnostics, err.range, err.msg, lang)
+ -- other checks rely on Neovim parser introspection
+ if lang and parser_info and cap_id == 'toplevel' then
+ local err = parse(node, buf, lang)
+ if err then
+ add_lint_for_node(diagnostics, err.range, err.msg, lang)
+ end
end
end
end
@@ -151,7 +153,7 @@ end
--- @private
--- @param buf integer Buffer to lint
---- @param opts QueryLinterOpts|QueryLinterNormalizedOpts|nil Options for linting
+--- @param opts vim.treesitter.query.lint.Opts|QueryLinterNormalizedOpts|nil Options for linting
function M.lint(buf, opts)
if buf == 0 then
buf = api.nvim_get_current_buf()
@@ -173,7 +175,7 @@ function M.lint(buf, opts)
parser:parse()
parser:for_each_tree(function(tree, ltree)
if ltree:lang() == 'query' then
- for _, match, _ in query:iter_matches(tree:root(), buf, 0, -1) do
+ for _, match, _ in query:iter_matches(tree:root(), buf, 0, -1, { all = true }) do
local lang_context = {
lang = lang,
parser_info = parser_info,
@@ -195,7 +197,7 @@ function M.clear(buf)
end
--- @private
---- @param findstart integer
+--- @param findstart 0|1
--- @param base string
function M.omnifunc(findstart, base)
if findstart == 1 then
diff --git a/runtime/lua/vim/treesitter/dev.lua b/runtime/lua/vim/treesitter/dev.lua
index 69ddc9b558..dc2a14d238 100644
--- a/runtime/lua/vim/treesitter/dev.lua
+++ b/runtime/lua/vim/treesitter/dev.lua
@@ -1,31 +1,29 @@
local api = vim.api
----@class TSDevModule
local M = {}
----@class TSTreeView
+---@class (private) vim.treesitter.dev.TSTreeView
---@field ns integer API namespace
----@field opts table Options table with the following keys:
---- - anon (boolean): If true, display anonymous nodes
---- - lang (boolean): If true, display the language alongside each node
---- - indent (number): Number of spaces to indent nested lines. Default is 2.
----@field nodes TSP.Node[]
----@field named TSP.Node[]
+---@field opts vim.treesitter.dev.TSTreeViewOpts
+---@field nodes vim.treesitter.dev.Node[]
+---@field named vim.treesitter.dev.Node[]
local TSTreeView = {}
----@class TSP.Node
----@field id integer Node id
----@field text string Node text
----@field named boolean True if this is a named (non-anonymous) node
----@field depth integer Depth of the node within the tree
----@field lnum integer Beginning line number of this node in the source buffer
----@field col integer Beginning column number of this node in the source buffer
----@field end_lnum integer Final line number of this node in the source buffer
----@field end_col integer Final column number of this node in the source buffer
+---@private
+---@class (private) vim.treesitter.dev.TSTreeViewOpts
+---@field anon boolean If true, display anonymous nodes.
+---@field lang boolean If true, display the language alongside each node.
+---@field indent number Number of spaces to indent nested lines.
+
+---@class (private) vim.treesitter.dev.Node
+---@field node TSNode Treesitter node
+---@field field string? Node field
+---@field depth integer Depth of this node in the tree
+---@field text string? Text displayed in the inspector for this node. Not computed until the
+--- inspector is drawn.
---@field lang string Source language of this node
----@field root TSNode
----@class TSP.Injection
+---@class (private) vim.treesitter.dev.Injection
---@field lang string Source language of this injection
---@field root TSNode Root node of the injection
@@ -43,48 +41,26 @@ local TSTreeView = {}
---
---@param node TSNode Starting node to begin traversal |tsnode|
---@param depth integer Current recursion depth
+---@param field string|nil The field of the current node
---@param lang string Language of the tree currently being traversed
----@param injections table<string, TSP.Injection> Mapping of node ids to root nodes
+---@param injections table<string, vim.treesitter.dev.Injection> Mapping of node ids to root nodes
--- of injected language trees (see explanation above)
----@param tree TSP.Node[] Output table containing a list of tables each representing a node in the tree
-local function traverse(node, depth, lang, injections, tree)
+---@param tree vim.treesitter.dev.Node[] Output table containing a list of tables each representing a node in the tree
+local function traverse(node, depth, field, lang, injections, tree)
+ table.insert(tree, {
+ node = node,
+ depth = depth,
+ lang = lang,
+ field = field,
+ })
+
local injection = injections[node:id()]
if injection then
- traverse(injection.root, depth, injection.lang, injections, tree)
+ traverse(injection.root, depth + 1, nil, injection.lang, injections, tree)
end
- for child, field in node:iter_children() do
- local type = child:type()
- local lnum, col, end_lnum, end_col = child:range()
- local named = child:named()
- local text ---@type string
- if named then
- if field then
- text = string.format('%s: (%s', field, type)
- else
- text = string.format('(%s', type)
- end
- else
- text = string.format('"%s"', type:gsub('\n', '\\n'):gsub('"', '\\"'))
- end
-
- table.insert(tree, {
- id = child:id(),
- text = text,
- named = named,
- depth = depth,
- lnum = lnum,
- col = col,
- end_lnum = end_lnum,
- end_col = end_col,
- lang = lang,
- })
-
- traverse(child, depth + 1, lang, injections, tree)
-
- if named then
- tree[#tree].text = string.format('%s)', tree[#tree].text)
- end
+ for child, child_field in node:iter_children() do
+ traverse(child, depth + 1, child_field, lang, injections, tree)
end
return tree
@@ -95,44 +71,45 @@ end
---@param bufnr integer Source buffer number
---@param lang string|nil Language of source buffer
---
----@return TSTreeView|nil
+---@return vim.treesitter.dev.TSTreeView|nil
---@return string|nil Error message, if any
---
---@package
function TSTreeView:new(bufnr, lang)
local ok, parser = pcall(vim.treesitter.get_parser, bufnr or 0, lang)
if not ok then
- return nil, 'No parser available for the given buffer'
+ local err = parser --[[ @as string ]]
+ return nil, 'No parser available for the given buffer:\n' .. err
end
-- For each child tree (injected language), find the root of the tree and locate the node within
-- the primary tree that contains that root. Add a mapping from the node in the primary tree to
-- the root in the child tree to the {injections} table.
local root = parser:parse(true)[1]:root()
- local injections = {} ---@type table<string, TSP.Injection>
+ local injections = {} ---@type table<string, vim.treesitter.dev.Injection>
parser:for_each_tree(function(parent_tree, parent_ltree)
local parent = parent_tree:root()
for _, child in pairs(parent_ltree:children()) do
- child:for_each_tree(function(tree, ltree)
+ for _, tree in pairs(child:trees()) do
local r = tree:root()
local node = assert(parent:named_descendant_for_range(r:range()))
local id = node:id()
if not injections[id] or r:byte_length() > injections[id].root:byte_length() then
injections[id] = {
- lang = ltree:lang(),
+ lang = child:lang(),
root = r,
}
end
- end)
+ end
end
end)
- local nodes = traverse(root, 0, parser:lang(), injections, {})
+ local nodes = traverse(root, 0, nil, parser:lang(), injections, {})
- local named = {} ---@type TSP.Node[]
+ local named = {} ---@type vim.treesitter.dev.Node[]
for _, v in ipairs(nodes) do
- if v.named then
+ if v.node:named() then
named[#named + 1] = v
end
end
@@ -141,6 +118,7 @@ function TSTreeView:new(bufnr, lang)
ns = api.nvim_create_namespace('treesitter/dev-inspect'),
nodes = nodes,
named = named,
+ ---@type vim.treesitter.dev.TSTreeViewOpts
opts = {
anon = false,
lang = false,
@@ -155,16 +133,12 @@ end
local decor_ns = api.nvim_create_namespace('ts.dev')
----@param lnum integer
----@param col integer
----@param end_lnum integer
----@param end_col integer
+---@param range Range4
---@return string
-local function get_range_str(lnum, col, end_lnum, end_col)
- if lnum == end_lnum then
- return string.format('[%d:%d - %d]', lnum + 1, col + 1, end_col)
- end
- return string.format('[%d:%d - %d:%d]', lnum + 1, col + 1, end_lnum + 1, end_col)
+local function range_to_string(range)
+ ---@type integer, integer, integer, integer
+ local row, col, end_row, end_col = unpack(range)
+ return string.format('[%d, %d] - [%d, %d]', row, col, end_row, end_col)
end
---@param w integer
@@ -183,7 +157,10 @@ end
local function set_dev_properties(w, b)
vim.wo[w].scrolloff = 5
vim.wo[w].wrap = false
- vim.wo[w].foldmethod = 'manual' -- disable folding
+ vim.wo[w].foldmethod = 'expr'
+ vim.wo[w].foldexpr = 'v:lua.vim.treesitter.foldexpr()' -- explicitly set foldexpr
+ vim.wo[w].foldenable = false -- Don't fold on first open InspectTree
+ vim.wo[w].foldlevel = 99
vim.bo[b].buflisted = false
vim.bo[b].buftype = 'nofile'
vim.bo[b].bufhidden = 'wipe'
@@ -192,7 +169,7 @@ end
--- Updates the cursor position in the inspector to match the node under the cursor.
---
---- @param treeview TSTreeView
+--- @param treeview vim.treesitter.dev.TSTreeView
--- @param lang string
--- @param source_buf integer
--- @param inspect_buf integer
@@ -213,7 +190,7 @@ local function set_inspector_cursor(treeview, lang, source_buf, inspect_buf, ins
local cursor_node_id = cursor_node:id()
for i, v in treeview:iter() do
- if v.id == cursor_node_id then
+ if v.node:id() == cursor_node_id then
local start = v.depth * treeview.opts.indent ---@type integer
local end_col = start + #v.text
api.nvim_buf_set_extmark(inspect_buf, treeview.ns, i - 1, start, {
@@ -228,6 +205,8 @@ end
--- Write the contents of this View into {bufnr}.
---
+--- Calling this function computes the text that is displayed for each node.
+---
---@param bufnr integer Buffer number to write into.
---@package
function TSTreeView:draw(bufnr)
@@ -235,13 +214,35 @@ function TSTreeView:draw(bufnr)
local lines = {} ---@type string[]
local lang_hl_marks = {} ---@type table[]
- for _, item in self:iter() do
- local range_str = get_range_str(item.lnum, item.col, item.end_lnum, item.end_col)
+ for i, item in self:iter() do
+ local range_str = range_to_string({ item.node:range() })
local lang_str = self.opts.lang and string.format(' %s', item.lang) or ''
+
+ local text ---@type string
+ if item.node:named() then
+ if item.field then
+ text = string.format('%s: (%s', item.field, item.node:type())
+ else
+ text = string.format('(%s', item.node:type())
+ end
+ else
+ text = string.format('"%s"', item.node:type():gsub('\n', '\\n'):gsub('"', '\\"'))
+ end
+
+ local next = self:get(i + 1)
+ if not next or next.depth <= item.depth then
+ local parens = item.depth - (next and next.depth or 0) + (item.node:named() and 1 or 0)
+ if parens > 0 then
+ text = string.format('%s%s', text, string.rep(')', parens))
+ end
+ end
+
+ item.text = text
+
local line = string.format(
'%s%s ; %s%s',
string.rep(' ', item.depth * self.opts.indent),
- item.text,
+ text,
range_str,
lang_str
)
@@ -253,7 +254,7 @@ function TSTreeView:draw(bufnr)
}
end
- lines[#lines + 1] = line
+ lines[i] = line
end
api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
@@ -275,7 +276,7 @@ end
--- The node number is dependent on whether or not anonymous nodes are displayed.
---
---@param i integer Node number to get
----@return TSP.Node
+---@return vim.treesitter.dev.Node
---@package
function TSTreeView:get(i)
local t = self.opts.anon and self.nodes or self.named
@@ -284,7 +285,7 @@ end
--- Iterate over all of the nodes in this View.
---
----@return (fun(): integer, TSP.Node) Iterator over all nodes in this View
+---@return (fun(): integer, vim.treesitter.dev.Node) Iterator over all nodes in this View
---@return table
---@return integer
---@package
@@ -292,22 +293,31 @@ function TSTreeView:iter()
return ipairs(self.opts.anon and self.nodes or self.named)
end
---- @class InspectTreeOpts
---- @field lang string? The language of the source buffer. If omitted, the
---- filetype of the source buffer is used.
---- @field bufnr integer? Buffer to draw the tree into. If omitted, a new
---- buffer is created.
---- @field winid integer? Window id to display the tree buffer in. If omitted,
---- a new window is created with {command}.
---- @field command string? Vimscript command to create the window. Default
---- value is "60vnew". Only used when {winid} is nil.
---- @field title (string|fun(bufnr:integer):string|nil) Title of the window. If a
---- function, it accepts the buffer number of the source
---- buffer as its only argument and should return a string.
+--- @class vim.treesitter.dev.inspect_tree.Opts
+--- @inlinedoc
+---
+--- The language of the source buffer. If omitted, the filetype of the source
+--- buffer is used.
+--- @field lang string?
+---
+--- Buffer to draw the tree into. If omitted, a new buffer is created.
+--- @field bufnr integer?
+---
+--- Window id to display the tree buffer in. If omitted, a new window is
+--- created with {command}.
+--- @field winid integer?
+---
+--- Vimscript command to create the window. Default value is "60vnew".
+--- Only used when {winid} is nil.
+--- @field command string?
+---
+--- Title of the window. If a function, it accepts the buffer number of the
+--- source buffer as its only argument and should return a string.
+--- @field title (string|fun(bufnr:integer):string|nil)
--- @private
---
---- @param opts InspectTreeOpts?
+--- @param opts vim.treesitter.dev.inspect_tree.Opts?
function M.inspect_tree(opts)
vim.validate({
opts = { opts, 't', true },
@@ -364,9 +374,9 @@ function M.inspect_tree(opts)
desc = 'Jump to the node under the cursor in the source buffer',
callback = function()
local row = api.nvim_win_get_cursor(w)[1]
- local pos = treeview:get(row)
+ local lnum, col = treeview:get(row).node:start()
api.nvim_set_current_win(win)
- api.nvim_win_set_cursor(win, { pos.lnum + 1, pos.col })
+ api.nvim_win_set_cursor(win, { lnum + 1, col })
end,
})
api.nvim_buf_set_keymap(b, 'n', 'a', '', {
@@ -374,7 +384,7 @@ function M.inspect_tree(opts)
callback = function()
local row, col = unpack(api.nvim_win_get_cursor(w)) ---@type integer, integer
local curnode = treeview:get(row)
- while curnode and not curnode.named do
+ while curnode and not curnode.node:named() do
row = row - 1
curnode = treeview:get(row)
end
@@ -386,9 +396,9 @@ function M.inspect_tree(opts)
return
end
- local id = curnode.id
+ local id = curnode.node:id()
for i, node in treeview:iter() do
- if node.id == id then
+ if node.node:id() == id then
api.nvim_win_set_cursor(w, { i, col })
break
end
@@ -424,20 +434,20 @@ function M.inspect_tree(opts)
api.nvim_buf_clear_namespace(buf, treeview.ns, 0, -1)
local row = api.nvim_win_get_cursor(w)[1]
- local pos = treeview:get(row)
- api.nvim_buf_set_extmark(buf, treeview.ns, pos.lnum, pos.col, {
- end_row = pos.end_lnum,
- end_col = math.max(0, pos.end_col),
+ local lnum, col, end_lnum, end_col = treeview:get(row).node:range()
+ api.nvim_buf_set_extmark(buf, treeview.ns, lnum, col, {
+ end_row = end_lnum,
+ end_col = math.max(0, end_col),
hl_group = 'Visual',
})
local topline, botline = vim.fn.line('w0', win), vim.fn.line('w$', win)
-- Move the cursor if highlighted range is completely out of view
- if pos.lnum < topline and pos.end_lnum < topline then
- api.nvim_win_set_cursor(win, { pos.end_lnum + 1, 0 })
- elseif pos.lnum > botline and pos.end_lnum > botline then
- api.nvim_win_set_cursor(win, { pos.lnum + 1, 0 })
+ if lnum < topline and end_lnum < topline then
+ api.nvim_win_set_cursor(win, { end_lnum + 1, 0 })
+ elseif lnum > botline and end_lnum > botline then
+ api.nvim_win_set_cursor(win, { lnum + 1, 0 })
end
end,
})
@@ -462,7 +472,9 @@ function M.inspect_tree(opts)
return true
end
+ local treeview_opts = treeview.opts
treeview = assert(TSTreeView:new(buf, opts.lang))
+ treeview.opts = treeview_opts
treeview:draw(b)
end,
})
diff --git a/runtime/lua/vim/treesitter/health.lua b/runtime/lua/vim/treesitter/health.lua
index ed1161e97f..a9b066d158 100644
--- a/runtime/lua/vim/treesitter/health.lua
+++ b/runtime/lua/vim/treesitter/health.lua
@@ -1,6 +1,6 @@
local M = {}
local ts = vim.treesitter
-local health = require('vim.health')
+local health = vim.health
--- Performs a healthcheck for treesitter integration
function M.check()
diff --git a/runtime/lua/vim/treesitter/highlighter.lua b/runtime/lua/vim/treesitter/highlighter.lua
index 496193c6ed..388680259a 100644
--- a/runtime/lua/vim/treesitter/highlighter.lua
+++ b/runtime/lua/vim/treesitter/highlighter.lua
@@ -2,50 +2,25 @@ local api = vim.api
local query = vim.treesitter.query
local Range = require('vim.treesitter._range')
----@alias TSHlIter fun(end_line: integer|nil): integer, TSNode, TSMetadata
-
----@class TSHighlightState
----@field next_row integer
----@field iter TSHlIter|nil
-
----@class TSHighlighter
----@field active table<integer,TSHighlighter>
----@field bufnr integer
----@field orig_spelloptions string
----@field _highlight_states table<TSTree,TSHighlightState>
----@field _queries table<string,TSHighlighterQuery>
----@field tree LanguageTree
----@field redraw_count integer
-local TSHighlighter = rawget(vim.treesitter, 'TSHighlighter') or {}
-TSHighlighter.__index = TSHighlighter
+local ns = api.nvim_create_namespace('treesitter/highlighter')
---- @nodoc
-TSHighlighter.active = TSHighlighter.active or {}
+---@alias vim.treesitter.highlighter.Iter fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata
----@class TSHighlighterQuery
----@field _query Query|nil
----@field hl_cache table<integer,integer>
+---@class (private) vim.treesitter.highlighter.Query
+---@field private _query vim.treesitter.Query?
+---@field private lang string
+---@field private hl_cache table<integer,integer>
local TSHighlighterQuery = {}
TSHighlighterQuery.__index = TSHighlighterQuery
-local ns = api.nvim_create_namespace('treesitter/highlighter')
-
---@private
+---@param lang string
+---@param query_string string?
+---@return vim.treesitter.highlighter.Query
function TSHighlighterQuery.new(lang, query_string)
- local self = setmetatable({}, { __index = TSHighlighterQuery })
-
- self.hl_cache = setmetatable({}, {
- __index = function(table, capture)
- local name = self._query.captures[capture]
- local id = 0
- if not vim.startswith(name, '_') then
- id = api.nvim_get_hl_id_by_name('@' .. name .. '.' .. lang)
- end
-
- rawset(table, capture, id)
- return id
- end,
- })
+ local self = setmetatable({}, TSHighlighterQuery)
+ self.lang = lang
+ self.hl_cache = {}
if query_string then
self._query = query.parse(lang, query_string)
@@ -57,18 +32,57 @@ function TSHighlighterQuery.new(lang, query_string)
end
---@package
+---@param capture integer
+---@return integer?
+function TSHighlighterQuery:get_hl_from_capture(capture)
+ if not self.hl_cache[capture] then
+ local name = self._query.captures[capture]
+ local id = 0
+ if not vim.startswith(name, '_') then
+ id = api.nvim_get_hl_id_by_name('@' .. name .. '.' .. self.lang)
+ end
+ self.hl_cache[capture] = id
+ end
+
+ return self.hl_cache[capture]
+end
+
+---@package
function TSHighlighterQuery:query()
return self._query
end
+---@class (private) vim.treesitter.highlighter.State
+---@field tstree TSTree
+---@field next_row integer
+---@field iter vim.treesitter.highlighter.Iter?
+---@field highlighter_query vim.treesitter.highlighter.Query
+
+---@nodoc
+---@class vim.treesitter.highlighter
+---@field active table<integer,vim.treesitter.highlighter>
+---@field bufnr integer
+---@field private orig_spelloptions string
+--- A map of highlight states.
+--- This state is kept during rendering across each line update.
+---@field private _highlight_states vim.treesitter.highlighter.State[]
+---@field private _queries table<string,vim.treesitter.highlighter.Query>
+---@field tree vim.treesitter.LanguageTree
+---@field private redraw_count integer
+local TSHighlighter = {
+ active = {},
+}
+
+TSHighlighter.__index = TSHighlighter
+
---@package
---
--- Creates a highlighter for `tree`.
---
----@param tree LanguageTree parser object to use for highlighting
+---@param tree vim.treesitter.LanguageTree parser object to use for highlighting
---@param opts (table|nil) Configuration of the highlighter:
--- - queries table overwrite queries used by the highlighter
----@return TSHighlighter Created highlighter object
+---@return vim.treesitter.highlighter Created highlighter object
function TSHighlighter.new(tree, opts)
local self = setmetatable({}, TSHighlighter)
@@ -98,15 +112,12 @@ function TSHighlighter.new(tree, opts)
end,
}, true)
- self.bufnr = tree:source() --[[@as integer]]
- self.edit_count = 0
+ local source = tree:source()
+ assert(type(source) == 'number')
+
+ self.bufnr = source
self.redraw_count = 0
- self.line_count = {}
- -- A map of highlight states.
- -- This state is kept during rendering across each line update.
self._highlight_states = {}
-
- ---@type table<string,TSHighlighterQuery>
self._queries = {}
-- Queries for a specific language can be overridden by a custom
@@ -144,11 +155,9 @@ end
--- @nodoc
--- Removes all internal references to the highlighter
function TSHighlighter:destroy()
- if TSHighlighter.active[self.bufnr] then
- TSHighlighter.active[self.bufnr] = nil
- end
+ TSHighlighter.active[self.bufnr] = nil
- if vim.api.nvim_buf_is_loaded(self.bufnr) then
+ if api.nvim_buf_is_loaded(self.bufnr) then
vim.bo[self.bufnr].spelloptions = self.orig_spelloptions
vim.b[self.bufnr].ts_highlight = nil
if vim.g.syntax_on == 1 then
@@ -157,23 +166,49 @@ function TSHighlighter:destroy()
end
end
----@package
----@param tstree TSTree
----@return TSHighlightState
-function TSHighlighter:get_highlight_state(tstree)
- if not self._highlight_states[tstree] then
- self._highlight_states[tstree] = {
+---@param srow integer
+---@param erow integer exclusive
+---@private
+function TSHighlighter:prepare_highlight_states(srow, erow)
+ self._highlight_states = {}
+
+ self.tree:for_each_tree(function(tstree, tree)
+ if not tstree then
+ return
+ end
+
+ local root_node = tstree:root()
+ local root_start_row, _, root_end_row, _ = root_node:range()
+
+ -- Only consider trees within the visible range
+ if root_start_row > erow or root_end_row < srow then
+ return
+ end
+
+ local highlighter_query = self:get_query(tree:lang())
+
+ -- Some injected languages may not have highlight queries.
+ if not highlighter_query:query() then
+ return
+ end
+
+ -- _highlight_states should be a list so that the highlights are added in the same order as
+ -- for_each_tree traversal. This ensures that parents' highlight don't override children's.
+ table.insert(self._highlight_states, {
+ tstree = tstree,
next_row = 0,
iter = nil,
- }
- end
-
- return self._highlight_states[tstree]
+ highlighter_query = highlighter_query,
+ })
+ end)
end
----@private
-function TSHighlighter:reset_highlight_state()
- self._highlight_states = {}
+---@param fn fun(state: vim.treesitter.highlighter.State)
+---@package
+function TSHighlighter:for_each_highlight_state(fn)
+ for _, state in ipairs(self._highlight_states) do
+ fn(state)
+ end
end
---@package
@@ -197,10 +232,9 @@ function TSHighlighter:on_changedtree(changes)
end
--- Gets the query used for @param lang
---
---@package
---@param lang string Language used by the highlighter.
----@return TSHighlighterQuery
+---@return vim.treesitter.highlighter.Query
function TSHighlighter:get_query(lang)
if not self._queries[lang] then
self._queries[lang] = TSHighlighterQuery.new(lang)
@@ -209,35 +243,23 @@ function TSHighlighter:get_query(lang)
return self._queries[lang]
end
----@param self TSHighlighter
+---@param self vim.treesitter.highlighter
---@param buf integer
---@param line integer
---@param is_spell_nav boolean
local function on_line_impl(self, buf, line, is_spell_nav)
- self.tree:for_each_tree(function(tstree, tree)
- if not tstree then
- return
- end
-
- local root_node = tstree:root()
+ self:for_each_highlight_state(function(state)
+ local root_node = state.tstree:root()
local root_start_row, _, root_end_row, _ = root_node:range()
- -- Only worry about trees within the line range
+ -- Only consider trees that contain this line
if root_start_row > line or root_end_row < line then
return
end
- local state = self:get_highlight_state(tstree)
- local highlighter_query = self:get_query(tree:lang())
-
- -- Some injected languages may not have highlight queries.
- if not highlighter_query:query() then
- return
- end
-
if state.iter == nil or state.next_row < line then
state.iter =
- highlighter_query:query():iter_captures(root_node, self.bufnr, line, root_end_row + 1)
+ state.highlighter_query:query():iter_captures(root_node, self.bufnr, line, root_end_row + 1)
end
while line >= state.next_row do
@@ -250,9 +272,9 @@ local function on_line_impl(self, buf, line, is_spell_nav)
local start_row, start_col, end_row, end_col = Range.unpack4(range)
if capture then
- local hl = highlighter_query.hl_cache[capture]
+ local hl = state.highlighter_query:get_hl_from_capture(capture)
- local capture_name = highlighter_query:query().captures[capture]
+ local capture_name = state.highlighter_query:query().captures[capture]
local spell = nil ---@type boolean?
if capture_name == 'spell' then
spell = true
@@ -308,7 +330,7 @@ function TSHighlighter._on_spell_nav(_, _, buf, srow, _, erow, _)
return
end
- self:reset_highlight_state()
+ self:prepare_highlight_states(srow, erow)
for row = srow, erow do
on_line_impl(self, buf, row, true)
@@ -326,7 +348,7 @@ function TSHighlighter._on_win(_, _win, buf, topline, botline)
return false
end
self.tree:parse({ topline, botline + 1 })
- self:reset_highlight_state()
+ self:prepare_highlight_states(topline, botline + 1)
self.redraw_count = self.redraw_count + 1
return true
end
diff --git a/runtime/lua/vim/treesitter/language.lua b/runtime/lua/vim/treesitter/language.lua
index 15bf666a1e..47abf65332 100644
--- a/runtime/lua/vim/treesitter/language.lua
+++ b/runtime/lua/vim/treesitter/language.lua
@@ -1,6 +1,5 @@
local api = vim.api
----@class TSLanguageModule
local M = {}
---@type table<string,string>
@@ -37,6 +36,11 @@ end
---@deprecated
function M.require_language(lang, path, silent, symbol_name)
+ vim.deprecate(
+ 'vim.treesitter.language.require_language()',
+ 'vim.treesitter.language.add()',
+ '0.12'
+ )
local opts = {
silent = silent,
path = path,
@@ -52,10 +56,17 @@ function M.require_language(lang, path, silent, symbol_name)
return true
end
----@class treesitter.RequireLangOpts
----@field path? string
----@field silent? boolean
+---@class vim.treesitter.language.add.Opts
+---@inlinedoc
+---
+---Default filetype the parser should be associated with.
+---(Default: {lang})
---@field filetype? string|string[]
+---
+---Optional path the parser is located at
+---@field path? string
+---
+---Internal symbol name for the language to load
---@field symbol_name? string
--- Load parser with name {lang}
@@ -63,13 +74,8 @@ end
--- Parsers are searched in the `parser` runtime directory, or the provided {path}
---
---@param lang string Name of the parser (alphanumerical and `_` only)
----@param opts (table|nil) Options:
---- - filetype (string|string[]) Default filetype the parser should be associated with.
---- Defaults to {lang}.
---- - path (string|nil) Optional path the parser is located at
---- - symbol_name (string|nil) Internal symbol name for the language to load
+---@param opts? vim.treesitter.language.add.Opts Options:
function M.add(lang, opts)
- ---@cast opts treesitter.RequireLangOpts
opts = opts or {}
local path = opts.path
local filetype = opts.filetype or lang
@@ -114,6 +120,10 @@ local function ensure_list(x)
end
--- Register a parser named {lang} to be used for {filetype}(s).
+---
+--- Note: this adds or overrides the mapping for {filetype}, any existing mappings from other
+--- filetypes to {lang} will be preserved.
+---
--- @param lang string Name of parser
--- @param filetype string|string[] Filetype(s) to associate with lang
function M.register(lang, filetype)
@@ -140,14 +150,4 @@ function M.inspect(lang)
return vim._ts_inspect_language(lang)
end
----@deprecated
-function M.inspect_language(...)
- vim.deprecate(
- 'vim.treesitter.language.inspect_language()',
- 'vim.treesitter.language.inspect()',
- '0.10'
- )
- return M.inspect(...)
-end
-
return M
diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua
index 0171b416cd..62714d3f1b 100644
--- a/runtime/lua/vim/treesitter/languagetree.lua
+++ b/runtime/lua/vim/treesitter/languagetree.lua
@@ -1,6 +1,4 @@
---- @defgroup lua-treesitter-languagetree
----
---- @brief A \*LanguageTree\* contains a tree of parsers: the root treesitter parser for {lang} and
+--- @brief A [LanguageTree]() contains a tree of parsers: the root treesitter parser for {lang} and
--- any "injected" language parsers, which themselves may inject other languages, recursively.
--- For example a Lua buffer containing some Vimscript commands needs multiple parsers to fully
--- understand its contents.
@@ -69,11 +67,12 @@ local TSCallbackNames = {
on_child_removed = 'child_removed',
}
----@class LanguageTree
+---@nodoc
+---@class vim.treesitter.LanguageTree
---@field private _callbacks table<TSCallbackName,function[]> Callback handlers
---@field package _callbacks_rec table<TSCallbackName,function[]> Callback handlers (recursive)
----@field private _children table<string,LanguageTree> Injected languages
----@field private _injection_query Query Queries defining injected languages
+---@field private _children table<string,vim.treesitter.LanguageTree> Injected languages
+---@field private _injection_query vim.treesitter.Query Queries defining injected languages
---@field private _injections_processed boolean
---@field private _opts table Options
---@field private _parser TSParser Parser for language
@@ -91,9 +90,11 @@ local TSCallbackNames = {
---@field private _logfile? file*
local LanguageTree = {}
----@class LanguageTreeOpts
----@field queries table<string,string> -- Deprecated
----@field injections table<string,string>
+---Optional arguments:
+---@class vim.treesitter.LanguageTree.new.Opts
+---@inlinedoc
+---@field queries? table<string,string> -- Deprecated
+---@field injections? table<string,string>
LanguageTree.__index = LanguageTree
@@ -104,14 +105,11 @@ LanguageTree.__index = LanguageTree
---
---@param source (integer|string) Buffer or text string to parse
---@param lang string Root language of this tree
----@param opts (table|nil) Optional arguments:
---- - injections table Map of language to injection query strings. Overrides the
---- built-in runtime file searching for language injections.
+---@param opts vim.treesitter.LanguageTree.new.Opts?
---@param parent_lang? string Parent language name of this tree
----@return LanguageTree parser object
+---@return vim.treesitter.LanguageTree parser object
function LanguageTree.new(source, lang, opts, parent_lang)
language.add(lang)
- ---@type LanguageTreeOpts
opts = opts or {}
if source == 0 then
@@ -120,7 +118,7 @@ function LanguageTree.new(source, lang, opts, parent_lang)
local injections = opts.injections or {}
- --- @type LanguageTree
+ --- @type vim.treesitter.LanguageTree
local self = {
_source = source,
_lang = lang,
@@ -196,7 +194,7 @@ local function tcall(f, ...)
end
---@private
----@vararg any
+---@param ... any
function LanguageTree:_log(...)
if not self._logger then
return
@@ -348,7 +346,13 @@ function LanguageTree:_parse_regions(range)
-- If there are no ranges, set to an empty list
-- so the included ranges in the parser are cleared.
for i, ranges in pairs(self:included_regions()) do
- if not self._valid[i] and intercepts_region(ranges, range) then
+ if
+ not self._valid[i]
+ and (
+ intercepts_region(ranges, range)
+ or (self._trees[i] and intercepts_region(self._trees[i]:included_ranges(false), range))
+ )
+ then
self._parser:set_included_ranges(ranges)
local parse_time, tree, tree_changes =
tcall(self._parser.parse, self._parser, self._trees[i], self._source, true)
@@ -427,7 +431,7 @@ function LanguageTree:parse(range)
local query_time = 0
local total_parse_time = 0
- --- At least 1 region is invalid
+ -- At least 1 region is invalid
if not self:is_valid(true) then
changes, no_regions_parsed, total_parse_time = self:_parse_regions(range)
-- Need to run injections when we parsed something
@@ -460,7 +464,7 @@ end
--- add recursion yourself if needed.
--- Invokes the callback for each |LanguageTree| and its children recursively
---
----@param fn fun(tree: LanguageTree, lang: string)
+---@param fn fun(tree: vim.treesitter.LanguageTree, lang: string)
---@param include_self boolean|nil Whether to include the invoking tree in the results
function LanguageTree:for_each_child(fn, include_self)
vim.deprecate('LanguageTree:for_each_child()', 'LanguageTree:children()', '0.11')
@@ -469,6 +473,7 @@ function LanguageTree:for_each_child(fn, include_self)
end
for _, child in pairs(self._children) do
+ --- @diagnostic disable-next-line:deprecated
child:for_each_child(fn, true)
end
end
@@ -477,7 +482,7 @@ end
---
--- Note: This includes the invoking tree's child trees as well.
---
----@param fn fun(tree: TSTree, ltree: LanguageTree)
+---@param fn fun(tree: TSTree, ltree: vim.treesitter.LanguageTree)
function LanguageTree:for_each_tree(fn)
for _, tree in pairs(self._trees) do
fn(tree, self)
@@ -494,7 +499,7 @@ end
---
---@private
---@param lang string Language to add.
----@return LanguageTree injected
+---@return vim.treesitter.LanguageTree injected
function LanguageTree:add_child(lang)
if self._children[lang] then
self:remove_child(lang)
@@ -664,7 +669,7 @@ end
---@param node TSNode
---@param source string|integer
----@param metadata TSMetadata
+---@param metadata vim.treesitter.query.TSMetadata
---@param include_children boolean
---@return Range6[]
local function get_node_ranges(node, source, metadata, include_children)
@@ -698,13 +703,14 @@ local function get_node_ranges(node, source, metadata, include_children)
return ranges
end
----@class TSInjectionElem
+---@nodoc
+---@class vim.treesitter.languagetree.InjectionElem
---@field combined boolean
---@field regions Range6[][]
----@alias TSInjection table<string,table<integer,TSInjectionElem>>
+---@alias vim.treesitter.languagetree.Injection table<string,table<integer,vim.treesitter.languagetree.InjectionElem>>
----@param t table<integer,TSInjection>
+---@param t table<integer,vim.treesitter.languagetree.Injection>
---@param tree_index integer
---@param pattern integer
---@param lang string
@@ -751,6 +757,11 @@ end)
---@param alias string language or filetype name
---@return string? # resolved parser name
local function resolve_lang(alias)
+ -- validate that `alias` is a legal language
+ if not (alias and alias:match('[%w_]+') == alias) then
+ return
+ end
+
if has_parser(alias) then
return alias
end
@@ -773,8 +784,8 @@ end
---@private
--- Extract injections according to:
--- https://tree-sitter.github.io/tree-sitter/syntax-highlighting#language-injection
----@param match table<integer,TSNode>
----@param metadata TSMetadata
+---@param match table<integer,TSNode[]>
+---@param metadata vim.treesitter.query.TSMetadata
---@return string?, boolean, Range6[]
function LanguageTree:_get_injection(match, metadata)
local ranges = {} ---@type Range6[]
@@ -785,14 +796,16 @@ function LanguageTree:_get_injection(match, metadata)
or (injection_lang and resolve_lang(injection_lang))
local include_children = metadata['injection.include-children'] ~= nil
- for id, node in pairs(match) do
- local name = self._injection_query.captures[id]
- -- Lang should override any other language tag
- if name == 'injection.language' then
- local text = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] })
- lang = resolve_lang(text)
- elseif name == 'injection.content' then
- ranges = get_node_ranges(node, self._source, metadata[id], include_children)
+ for id, nodes in pairs(match) do
+ for _, node in ipairs(nodes) do
+ local name = self._injection_query.captures[id]
+ -- Lang should override any other language tag
+ if name == 'injection.language' then
+ local text = vim.treesitter.get_node_text(node, self._source, { metadata = metadata[id] })
+ lang = resolve_lang(text)
+ elseif name == 'injection.content' then
+ ranges = get_node_ranges(node, self._source, metadata[id], include_children)
+ end
end
end
@@ -825,7 +838,7 @@ function LanguageTree:_get_injections()
return {}
end
- ---@type table<integer,TSInjection>
+ ---@type table<integer,vim.treesitter.languagetree.Injection>
local injections = {}
for index, tree in pairs(self._trees) do
@@ -833,7 +846,13 @@ function LanguageTree:_get_injections()
local start_line, _, end_line, _ = root_node:range()
for pattern, match, metadata in
- self._injection_query:iter_matches(root_node, self._source, start_line, end_line + 1)
+ self._injection_query:iter_matches(
+ root_node,
+ self._source,
+ start_line,
+ end_line + 1,
+ { all = true }
+ )
do
local lang, combined, ranges = self:_get_injection(match, metadata)
if lang then
@@ -1133,7 +1152,7 @@ end
--- Gets the appropriate language that contains {range}.
---
---@param range Range4 `{ start_line, start_col, end_line, end_col }`
----@return LanguageTree Managing {range}
+---@return vim.treesitter.LanguageTree Managing {range}
function LanguageTree:language_for_range(range)
for _, child in pairs(self._children) do
if child:contains(range) then
diff --git a/runtime/lua/vim/treesitter/query.lua b/runtime/lua/vim/treesitter/query.lua
index 8cbbffcd60..a086f5e876 100644
--- a/runtime/lua/vim/treesitter/query.lua
+++ b/runtime/lua/vim/treesitter/query.lua
@@ -1,19 +1,50 @@
local api = vim.api
local language = require('vim.treesitter.language')
----@class Query
----@field captures string[] List of captures used in query
----@field info TSQueryInfo Contains used queries, predicates, directives
----@field query userdata Parsed query
+local M = {}
+
+---@nodoc
+---Parsed query, see |vim.treesitter.query.parse()|
+---
+---@class vim.treesitter.Query
+---@field lang string name of the language for this parser
+---@field captures string[] list of (unique) capture names defined in query
+---@field info vim.treesitter.QueryInfo contains information used in the query (e.g. captures, predicates, directives)
+---@field query TSQuery userdata query object
local Query = {}
Query.__index = Query
----@class TSQueryInfo
----@field captures table
----@field patterns table<string,any[][]>
+---@package
+---@see vim.treesitter.query.parse
+---@param lang string
+---@param ts_query TSQuery
+---@return vim.treesitter.Query
+function Query.new(lang, ts_query)
+ local self = setmetatable({}, Query)
+ local query_info = ts_query:inspect() ---@type TSQueryInfo
+ self.query = ts_query
+ self.lang = lang
+ self.info = {
+ captures = query_info.captures,
+ patterns = query_info.patterns,
+ }
+ self.captures = self.info.captures
+ return self
+end
----@class TSQueryModule
-local M = {}
+---@nodoc
+---Information for Query, see |vim.treesitter.query.parse()|
+---@class vim.treesitter.QueryInfo
+---
+---List of (unique) capture names defined in query.
+---@field captures string[]
+---
+---Contains information about predicates and directives.
+---Key is pattern id, and value is list of predicates or directives defined in the pattern.
+---A predicate or directive is a list of (integer|string); integer represents `capture_id`, and
+---string represents (literal) arguments to predicate/directive. See |treesitter-predicates|
+---and |treesitter-directives| for more details.
+---@field patterns table<integer, (integer|string)[][]>
---@param files string[]
---@return string[]
@@ -53,16 +84,6 @@ local function add_included_lang(base_langs, lang, ilang)
return false
end
----@deprecated
-function M.get_query_files(...)
- vim.deprecate(
- 'vim.treesitter.query.get_query_files()',
- 'vim.treesitter.query.get_files()',
- '0.10'
- )
- return M.get_files(...)
-end
-
--- Gets the list of files used to make up a query
---
---@param lang string Language to get query for
@@ -163,7 +184,7 @@ local function read_query_files(filenames)
end
-- The explicitly set queries from |vim.treesitter.query.set()|
----@type table<string,table<string,Query>>
+---@type table<string,table<string,vim.treesitter.Query>>
local explicit_queries = setmetatable({}, {
__index = function(t, k)
local lang_queries = {}
@@ -173,12 +194,6 @@ local explicit_queries = setmetatable({}, {
end,
})
----@deprecated
-function M.set_query(...)
- vim.deprecate('vim.treesitter.query.set_query()', 'vim.treesitter.query.set()', '0.10')
- M.set(...)
-end
-
--- Sets the runtime query named {query_name} for {lang}
---
--- This allows users to override any runtime files and/or configuration
@@ -191,18 +206,12 @@ function M.set(lang, query_name, text)
explicit_queries[lang][query_name] = M.parse(lang, text)
end
----@deprecated
-function M.get_query(...)
- vim.deprecate('vim.treesitter.query.get_query()', 'vim.treesitter.query.get()', '0.10')
- return M.get(...)
-end
-
--- Returns the runtime query {query_name} for {lang}.
---
---@param lang string Language to use for the query
---@param query_name string Name of the query (e.g. "highlights")
---
----@return Query|nil Parsed query
+---@return vim.treesitter.Query|nil : Parsed query. `nil` if no query files are found.
M.get = vim.func._memoize('concat-2', function(lang, query_name)
if explicit_queries[lang][query_name] then
return explicit_queries[lang][query_name]
@@ -218,92 +227,96 @@ M.get = vim.func._memoize('concat-2', function(lang, query_name)
return M.parse(lang, query_string)
end)
----@deprecated
-function M.parse_query(...)
- vim.deprecate('vim.treesitter.query.parse_query()', 'vim.treesitter.query.parse()', '0.10')
- return M.parse(...)
-end
-
--- Parse {query} as a string. (If the query is in a file, the caller
--- should read the contents into a string before calling).
---
--- Returns a `Query` (see |lua-treesitter-query|) object which can be used to
--- search nodes in the syntax tree for the patterns defined in {query}
---- using `iter_*` methods below.
+--- using the `iter_captures` and `iter_matches` methods.
---
--- Exposes `info` and `captures` with additional context about {query}.
---- - `captures` contains the list of unique capture names defined in
---- {query}.
---- -` info.captures` also points to `captures`.
+--- - `captures` contains the list of unique capture names defined in {query}.
+--- - `info.captures` also points to `captures`.
--- - `info.patterns` contains information about predicates.
---
---@param lang string Language to use for the query
---@param query string Query in s-expr syntax
---
----@return Query Parsed query
+---@return vim.treesitter.Query Parsed query
+---
+---@see |vim.treesitter.query.get()|
M.parse = vim.func._memoize('concat-2', function(lang, query)
language.add(lang)
- local self = setmetatable({}, Query)
- self.query = vim._ts_parse_query(lang, query)
- self.info = self.query:inspect()
- self.captures = self.info.captures
- return self
+ local ts_query = vim._ts_parse_query(lang, query)
+ return Query.new(lang, ts_query)
end)
----@deprecated
-function M.get_range(...)
- vim.deprecate('vim.treesitter.query.get_range()', 'vim.treesitter.get_range()', '0.10')
- return vim.treesitter.get_range(...)
-end
-
----@deprecated
-function M.get_node_text(...)
- vim.deprecate('vim.treesitter.query.get_node_text()', 'vim.treesitter.get_node_text()', '0.10')
- return vim.treesitter.get_node_text(...)
-end
-
----@alias TSMatch table<integer,TSNode>
-
----@alias TSPredicate fun(match: TSMatch, _, _, predicate: any[]): boolean
-
--- Predicate handler receive the following arguments
--- (match, pattern, bufnr, predicate)
----@type table<string,TSPredicate>
-local predicate_handlers = {
- ['eq?'] = function(match, _, source, predicate)
- local node = match[predicate[2]]
- if not node then
+--- Implementations of predicates that can optionally be prefixed with "any-".
+---
+--- These functions contain the implementations for each predicate, correctly
+--- handling the "any" vs "all" semantics. They are called from the
+--- predicate_handlers table with the appropriate arguments for each predicate.
+local impl = {
+ --- @param match vim.treesitter.query.TSMatch
+ --- @param source integer|string
+ --- @param predicate any[]
+ --- @param any boolean
+ ['eq'] = function(match, source, predicate, any)
+ local nodes = match[predicate[2]]
+ if not nodes or #nodes == 0 then
return true
end
- local node_text = vim.treesitter.get_node_text(node, source)
- local str ---@type string
- if type(predicate[3]) == 'string' then
- -- (#eq? @aa "foo")
- str = predicate[3]
- else
- -- (#eq? @aa @bb)
- str = vim.treesitter.get_node_text(match[predicate[3]], source)
- end
+ for _, node in ipairs(nodes) do
+ local node_text = vim.treesitter.get_node_text(node, source)
+
+ local str ---@type string
+ if type(predicate[3]) == 'string' then
+ -- (#eq? @aa "foo")
+ str = predicate[3]
+ else
+ -- (#eq? @aa @bb)
+ local other = assert(match[predicate[3]])
+ assert(#other == 1, '#eq? does not support comparison with captures on multiple nodes')
+ str = vim.treesitter.get_node_text(other[1], source)
+ end
- if node_text ~= str or str == nil then
- return false
+ local res = str ~= nil and node_text == str
+ if any and res then
+ return true
+ elseif not any and not res then
+ return false
+ end
end
- return true
+ return not any
end,
- ['lua-match?'] = function(match, _, source, predicate)
- local node = match[predicate[2]]
- if not node then
+ --- @param match vim.treesitter.query.TSMatch
+ --- @param source integer|string
+ --- @param predicate any[]
+ --- @param any boolean
+ ['lua-match'] = function(match, source, predicate, any)
+ local nodes = match[predicate[2]]
+ if not nodes or #nodes == 0 then
return true
end
- local regex = predicate[3]
- return string.find(vim.treesitter.get_node_text(node, source), regex) ~= nil
+
+ for _, node in ipairs(nodes) do
+ local regex = predicate[3]
+ local res = string.find(vim.treesitter.get_node_text(node, source), regex) ~= nil
+ if any and res then
+ return true
+ elseif not any and not res then
+ return false
+ end
+ end
+
+ return not any
end,
- ['match?'] = (function()
+ ['match'] = (function()
local magic_prefixes = { ['\\v'] = true, ['\\m'] = true, ['\\M'] = true, ['\\V'] = true }
local function check_magic(str)
if string.len(str) < 2 or magic_prefixes[string.sub(str, 1, 2)] then
@@ -320,85 +333,161 @@ local predicate_handlers = {
end,
})
- return function(match, _, source, pred)
- ---@cast match TSMatch
- local node = match[pred[2]]
- if not node then
+ --- @param match vim.treesitter.query.TSMatch
+ --- @param source integer|string
+ --- @param predicate any[]
+ --- @param any boolean
+ return function(match, source, predicate, any)
+ local nodes = match[predicate[2]]
+ if not nodes or #nodes == 0 then
return true
end
- ---@diagnostic disable-next-line no-unknown
- local regex = compiled_vim_regexes[pred[3]]
- return regex:match_str(vim.treesitter.get_node_text(node, source))
+
+ for _, node in ipairs(nodes) do
+ local regex = compiled_vim_regexes[predicate[3]] ---@type vim.regex
+ local res = regex:match_str(vim.treesitter.get_node_text(node, source))
+ if any and res then
+ return true
+ elseif not any and not res then
+ return false
+ end
+ end
+ return not any
end
end)(),
- ['contains?'] = function(match, _, source, predicate)
- local node = match[predicate[2]]
- if not node then
+ --- @param match vim.treesitter.query.TSMatch
+ --- @param source integer|string
+ --- @param predicate any[]
+ --- @param any boolean
+ ['contains'] = function(match, source, predicate, any)
+ local nodes = match[predicate[2]]
+ if not nodes or #nodes == 0 then
return true
end
- local node_text = vim.treesitter.get_node_text(node, source)
- for i = 3, #predicate do
- if string.find(node_text, predicate[i], 1, true) then
- return true
+ for _, node in ipairs(nodes) do
+ local node_text = vim.treesitter.get_node_text(node, source)
+
+ for i = 3, #predicate do
+ local res = string.find(node_text, predicate[i], 1, true)
+ if any and res then
+ return true
+ elseif not any and not res then
+ return false
+ end
end
end
- return false
+ return not any
+ end,
+}
+
+---@nodoc
+---@class vim.treesitter.query.TSMatch
+---@field pattern? integer
+---@field active? boolean
+---@field [integer] TSNode[]
+
+---@alias TSPredicate fun(match: vim.treesitter.query.TSMatch, pattern: integer, source: integer|string, predicate: any[]): boolean
+
+-- Predicate handler receive the following arguments
+-- (match, pattern, bufnr, predicate)
+---@type table<string,TSPredicate>
+local predicate_handlers = {
+ ['eq?'] = function(match, _, source, predicate)
+ return impl['eq'](match, source, predicate, false)
+ end,
+
+ ['any-eq?'] = function(match, _, source, predicate)
+ return impl['eq'](match, source, predicate, true)
+ end,
+
+ ['lua-match?'] = function(match, _, source, predicate)
+ return impl['lua-match'](match, source, predicate, false)
+ end,
+
+ ['any-lua-match?'] = function(match, _, source, predicate)
+ return impl['lua-match'](match, source, predicate, true)
+ end,
+
+ ['match?'] = function(match, _, source, predicate)
+ return impl['match'](match, source, predicate, false)
+ end,
+
+ ['any-match?'] = function(match, _, source, predicate)
+ return impl['match'](match, source, predicate, true)
+ end,
+
+ ['contains?'] = function(match, _, source, predicate)
+ return impl['contains'](match, source, predicate, false)
+ end,
+
+ ['any-contains?'] = function(match, _, source, predicate)
+ return impl['contains'](match, source, predicate, true)
end,
['any-of?'] = function(match, _, source, predicate)
- local node = match[predicate[2]]
- if not node then
+ local nodes = match[predicate[2]]
+ if not nodes or #nodes == 0 then
return true
end
- local node_text = vim.treesitter.get_node_text(node, source)
- -- Since 'predicate' will not be used by callers of this function, use it
- -- to store a string set built from the list of words to check against.
- local string_set = predicate['string_set']
- if not string_set then
- string_set = {}
- for i = 3, #predicate do
- ---@diagnostic disable-next-line:no-unknown
- string_set[predicate[i]] = true
+ for _, node in ipairs(nodes) do
+ local node_text = vim.treesitter.get_node_text(node, source)
+
+ -- Since 'predicate' will not be used by callers of this function, use it
+ -- to store a string set built from the list of words to check against.
+ local string_set = predicate['string_set'] --- @type table<string, boolean>
+ if not string_set then
+ string_set = {}
+ for i = 3, #predicate do
+ string_set[predicate[i]] = true
+ end
+ predicate['string_set'] = string_set
+ end
+
+ if string_set[node_text] then
+ return true
end
- predicate['string_set'] = string_set
end
- return string_set[node_text]
+ return false
end,
['has-ancestor?'] = function(match, _, _, predicate)
- local node = match[predicate[2]]
- if not node then
+ local nodes = match[predicate[2]]
+ if not nodes or #nodes == 0 then
return true
end
- local ancestor_types = {}
- for _, type in ipairs({ unpack(predicate, 3) }) do
- ancestor_types[type] = true
- end
+ for _, node in ipairs(nodes) do
+ local ancestor_types = {} --- @type table<string, boolean>
+ 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
+ local cur = node:parent()
+ while cur do
+ if ancestor_types[cur:type()] then
+ return true
+ end
+ cur = cur:parent()
end
- node = node:parent()
end
return false
end,
['has-parent?'] = function(match, _, _, predicate)
- local node = match[predicate[2]]
- if not node then
+ local nodes = match[predicate[2]]
+ if not nodes or #nodes == 0 then
return true
end
- if vim.list_contains({ unpack(predicate, 3) }, node:parent():type()) then
- return true
+ for _, node in ipairs(nodes) do
+ if vim.list_contains({ unpack(predicate, 3) }, node:parent():type()) then
+ return true
+ end
end
return false
end,
@@ -406,14 +495,16 @@ local predicate_handlers = {
-- As we provide lua-match? also expose vim-match?
predicate_handlers['vim-match?'] = predicate_handlers['match?']
+predicate_handlers['any-vim-match?'] = predicate_handlers['any-match?']
----@class TSMetadata
+---@nodoc
+---@class vim.treesitter.query.TSMetadata
---@field range? Range
---@field conceal? string
----@field [integer] TSMetadata
+---@field [integer] vim.treesitter.query.TSMetadata
---@field [string] integer|string
----@alias TSDirective fun(match: TSMatch, _, _, predicate: (string|integer)[], metadata: TSMetadata)
+---@alias TSDirective fun(match: vim.treesitter.query.TSMatch, _, _, predicate: (string|integer)[], metadata: vim.treesitter.query.TSMetadata)
-- Predicate handler receive the following arguments
-- (match, pattern, bufnr, predicate)
@@ -441,13 +532,17 @@ local directive_handlers = {
-- Shifts the range of a node.
-- Example: (#offset! @_node 0 1 0 -1)
['offset!'] = function(match, _, _, pred, metadata)
- ---@cast pred integer[]
- local capture_id = pred[2]
+ local capture_id = pred[2] --[[@as integer]]
+ local nodes = match[capture_id]
+ assert(#nodes == 1, '#offset! does not support captures on multiple nodes')
+
+ local node = nodes[1]
+
if not metadata[capture_id] then
metadata[capture_id] = {}
end
- local range = metadata[capture_id].range or { match[capture_id]:range() }
+ local range = metadata[capture_id].range or { node:range() }
local start_row_offset = pred[3] or 0
local start_col_offset = pred[4] or 0
local end_row_offset = pred[5] or 0
@@ -471,7 +566,9 @@ local directive_handlers = {
local id = pred[2]
assert(type(id) == 'number')
- local node = match[id]
+ local nodes = match[id]
+ assert(#nodes == 1, '#gsub! does not support captures on multiple nodes')
+ local node = nodes[1]
local text = vim.treesitter.get_node_text(node, bufnr, { metadata = metadata[id] }) or ''
if not metadata[id] then
@@ -491,10 +588,9 @@ local directive_handlers = {
local capture_id = pred[2]
assert(type(capture_id) == 'number')
- local node = match[capture_id]
- if not node then
- return
- end
+ local nodes = match[capture_id]
+ assert(#nodes == 1, '#trim! does not support captures on multiple nodes')
+ local node = nodes[1]
local start_row, start_col, end_row, end_col = node:range()
@@ -525,38 +621,93 @@ local directive_handlers = {
--- Adds a new predicate to be used in queries
---
---@param name string Name of the predicate, without leading #
----@param handler function(match:table<string,TSNode>, pattern:string, bufnr:integer, predicate:string[])
+---@param handler function(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: table)
--- - see |vim.treesitter.query.add_directive()| for argument meanings
----@param force boolean|nil
-function M.add_predicate(name, handler, force)
- if predicate_handlers[name] and not force then
- error(string.format('Overriding %s', name))
+---@param opts table<string, any> Optional options:
+--- - force (boolean): Override an existing
+--- predicate of the same name
+--- - all (boolean): Use the correct
+--- implementation of the match table where
+--- capture IDs map to a list of nodes instead
+--- of a single node. Defaults to false (for
+--- backward compatibility). This option will
+--- eventually become the default and removed.
+function M.add_predicate(name, handler, opts)
+ -- Backward compatibility: old signature had "force" as boolean argument
+ if type(opts) == 'boolean' then
+ opts = { force = opts }
end
- predicate_handlers[name] = handler
+ opts = opts or {}
+
+ if predicate_handlers[name] and not opts.force then
+ error(string.format('Overriding existing predicate %s', name))
+ end
+
+ if opts.all then
+ predicate_handlers[name] = handler
+ else
+ --- @param match table<integer, TSNode[]>
+ local function wrapper(match, ...)
+ local m = {} ---@type table<integer, TSNode>
+ for k, v in pairs(match) do
+ if type(k) == 'number' then
+ m[k] = v[#v]
+ end
+ end
+ return handler(m, ...)
+ end
+ predicate_handlers[name] = wrapper
+ end
end
--- Adds a new directive to be used in queries
---
--- Handlers can set match level data by setting directly on the
---- metadata object `metadata.key = value`, additionally, handlers
+--- metadata object `metadata.key = value`. Additionally, handlers
--- can set node level data by using the capture id on the
--- metadata table `metadata[capture_id].key = value`
---
---@param name string Name of the directive, without leading #
----@param handler function(match:table<string,TSNode>, pattern:string, bufnr:integer, predicate:string[], metadata:table)
---- - match: see |treesitter-query|
---- - node-level data are accessible via `match[capture_id]`
---- - pattern: see |treesitter-query|
+---@param handler function(match: table<integer,TSNode[]>, pattern: integer, source: integer|string, predicate: any[], metadata: table)
+--- - match: A table mapping capture IDs to a list of captured nodes
+--- - pattern: the index of the matching pattern in the query file
--- - predicate: list of strings containing the full directive being called, e.g.
--- `(node (#set! conceal "-"))` would get the predicate `{ "#set!", "conceal", "-" }`
----@param force boolean|nil
-function M.add_directive(name, handler, force)
- if directive_handlers[name] and not force then
- error(string.format('Overriding %s', name))
+---@param opts table<string, any> Optional options:
+--- - force (boolean): Override an existing
+--- predicate of the same name
+--- - all (boolean): Use the correct
+--- implementation of the match table where
+--- capture IDs map to a list of nodes instead
+--- of a single node. Defaults to false (for
+--- backward compatibility). This option will
+--- eventually become the default and removed.
+function M.add_directive(name, handler, opts)
+ -- Backward compatibility: old signature had "force" as boolean argument
+ if type(opts) == 'boolean' then
+ opts = { force = opts }
end
- directive_handlers[name] = handler
+ opts = opts or {}
+
+ if directive_handlers[name] and not opts.force then
+ error(string.format('Overriding existing directive %s', name))
+ end
+
+ if opts.all then
+ directive_handlers[name] = handler
+ else
+ --- @param match table<integer, TSNode[]>
+ local function wrapper(match, ...)
+ local m = {} ---@type table<integer, TSNode>
+ for k, v in pairs(match) do
+ m[k] = v[#v]
+ end
+ handler(m, ...)
+ end
+ directive_handlers[name] = wrapper
+ end
end
--- Lists the currently available directives to use in queries.
@@ -580,8 +731,8 @@ local function is_directive(name)
end
---@private
----@param match TSMatch
----@param pattern string
+---@param match vim.treesitter.query.TSMatch
+---@param pattern integer
---@param source integer|string
function Query:match_preds(match, pattern, source)
local preds = self.info.patterns[pattern]
@@ -591,18 +742,14 @@ function Query:match_preds(match, pattern, source)
-- continue on the other case. This way unknown predicates will not be considered,
-- which allows some testing and easier user extensibility (#12173).
-- Also, tree-sitter strips the leading # from predicates for us.
- local pred_name ---@type string
-
- local is_not ---@type boolean
+ local is_not = false
-- Skip over directives... they will get processed after all the predicates.
if not is_directive(pred[1]) then
- if string.sub(pred[1], 1, 4) == 'not-' then
- pred_name = string.sub(pred[1], 5)
+ local pred_name = pred[1]
+ if pred_name:match('^not%-') then
+ pred_name = pred_name:sub(5)
is_not = true
- else
- pred_name = pred[1]
- is_not = false
end
local handler = predicate_handlers[pred_name]
@@ -623,8 +770,8 @@ function Query:match_preds(match, pattern, source)
end
---@private
----@param match TSMatch
----@param metadata TSMetadata
+---@param match vim.treesitter.query.TSMatch
+---@param metadata vim.treesitter.query.TSMetadata
function Query:apply_directives(match, pattern, source, metadata)
local preds = self.info.patterns[pattern]
@@ -645,14 +792,16 @@ end
--- Returns the start and stop value if set else the node's range.
-- When the node's range is used, the stop is incremented by 1
-- to make the search inclusive.
----@param start integer
----@param stop integer
+---@param start integer|nil
+---@param stop integer|nil
---@param node TSNode
---@return integer, integer
local function value_or_node_range(start, stop, node)
- if start == nil and stop == nil then
- local node_start, _, node_stop, _ = node:range()
- return node_start, node_stop + 1 -- Make stop inclusive
+ if start == nil then
+ start = node:start()
+ end
+ if stop == nil then
+ stop = node:end_() + 1 -- Make stop inclusive
end
return start, stop
@@ -683,10 +832,10 @@ end
---
---@param node TSNode under which the search will occur
---@param source (integer|string) Source buffer or string to extract text from
----@param start integer Starting line for the search
----@param stop integer Stopping line for the search (end-exclusive)
+---@param start? integer Starting line for the search. Defaults to `node:start()`.
+---@param stop? integer Stopping line for the search (end-exclusive). Defaults to `node:end_()`.
---
----@return (fun(end_line: integer|nil): integer, TSNode, TSMetadata):
+---@return (fun(end_line: integer|nil): integer, TSNode, vim.treesitter.query.TSMetadata):
--- capture id, capture node, metadata
function Query:iter_captures(node, source, start, stop)
if type(source) == 'number' and source == 0 then
@@ -695,7 +844,7 @@ function Query:iter_captures(node, source, start, stop)
start, stop = value_or_node_range(start, stop, node)
- local raw_iter = node:_rawquery(self.query, true, start, stop)
+ local raw_iter = node:_rawquery(self.query, true, start, stop) ---@type fun(): integer, TSNode, vim.treesitter.query.TSMatch
local function iter(end_line)
local capture, captured_node, match = raw_iter()
local metadata = {}
@@ -719,46 +868,55 @@ end
--- Iterates the matches of self on a given range.
---
---- Iterate over all matches within a {node}. The arguments are the same as
---- for |Query:iter_captures()| but the iterated values are different:
---- an (1-based) index of the pattern in the query, a table mapping
---- capture indices to nodes, and metadata from any directives processing the match.
---- If the query has more than one pattern, the capture table might be sparse
---- and e.g. `pairs()` method should be used over `ipairs`.
---- Here is an example iterating over all captures in every match:
+--- Iterate over all matches within a {node}. The arguments are the same as for
+--- |Query:iter_captures()| but the iterated values are different: an (1-based)
+--- index of the pattern in the query, a table mapping capture indices to a list
+--- of nodes, and metadata from any directives processing the match.
+---
+--- WARNING: Set `all=true` to ensure all matching nodes in a match are
+--- returned, otherwise only the last node in a match is returned, breaking captures
+--- involving quantifiers such as `(comment)+ @comment`. The default option
+--- `all=false` is only provided for backward compatibility and will be removed
+--- after Nvim 0.10.
+---
+--- Example:
---
--- ```lua
---- for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, first, last) do
---- for id, node in pairs(match) do
+--- for pattern, match, metadata in cquery:iter_matches(tree:root(), bufnr, 0, -1, { all = true }) do
+--- for id, nodes in pairs(match) do
--- local name = query.captures[id]
---- -- `node` was captured by the `name` capture in the match
+--- for _, node in ipairs(nodes) do
+--- -- `node` was captured by the `name` capture in the match
---
---- local node_data = metadata[id] -- Node level metadata
----
---- -- ... use the info here ...
+--- local node_data = metadata[id] -- Node level metadata
+--- ... use the info here ...
+--- end
--- end
--- end
--- ```
---
+---
---@param node TSNode under which the search will occur
---@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:
+---@param start? integer Starting line for the search. Defaults to `node:start()`.
+---@param stop? integer Stopping line for the search (end-exclusive). Defaults to `node:end_()`.
+---@param opts? table Optional keyword arguments:
--- - 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.
+--- - all (boolean) When set, the returned match table maps capture IDs to a list of nodes.
+--- Older versions of iter_matches incorrectly mapped capture IDs to a single node, which is
+--- incorrect behavior. This option will eventually become the default and removed.
---
----@return (fun(): integer, table<integer,TSNode>, table): pattern id, match, metadata
+---@return (fun(): integer, table<integer, TSNode[]>, table): pattern id, match, metadata
function Query:iter_matches(node, source, start, stop, opts)
+ local all = opts and opts.all
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, opts)
- ---@cast raw_iter fun(): string, any
+ local raw_iter = node:_rawquery(self.query, false, start, stop, opts) ---@type fun(): integer, vim.treesitter.query.TSMatch
local function iter()
local pattern, match = raw_iter()
local metadata = {}
@@ -771,14 +929,33 @@ function Query:iter_matches(node, source, start, stop, opts)
self:apply_directives(match, pattern, source, metadata)
end
+
+ if not all then
+ -- Convert the match table into the old buggy version for backward
+ -- compatibility. This is slow. Plugin authors, if you're reading this, set the "all"
+ -- option!
+ local old_match = {} ---@type table<integer, TSNode>
+ for k, v in pairs(match or {}) do
+ old_match[k] = v[#v]
+ end
+ return pattern, old_match, metadata
+ end
+
return pattern, match, metadata
end
return iter
end
----@class QueryLinterOpts
----@field langs (string|string[]|nil)
----@field clear (boolean)
+--- Optional keyword arguments:
+--- @class vim.treesitter.query.lint.Opts
+--- @inlinedoc
+---
+--- Language(s) to use for checking the query.
+--- If multiple languages are specified, queries are validated for all of them
+--- @field langs? string|string[]
+---
+--- Just clear current lint errors
+--- @field clear boolean
--- Lint treesitter queries using installed parser, or clear lint errors.
---
@@ -793,15 +970,12 @@ end
--- of the query file, e.g., if the path ends in `/lua/highlights.scm`, the parser for the
--- `lua` language will be used.
---@param buf (integer) Buffer handle
----@param opts (QueryLinterOpts|nil) Optional keyword arguments:
---- - langs (string|string[]|nil) Language(s) to use for checking the query.
---- If multiple languages are specified, queries are validated for all of them
---- - clear (boolean) if `true`, just clear current lint errors
+---@param opts? vim.treesitter.query.lint.Opts
function M.lint(buf, opts)
if opts and opts.clear then
- require('vim.treesitter._query_linter').clear(buf)
+ vim.treesitter._query_linter.clear(buf)
else
- require('vim.treesitter._query_linter').lint(buf, opts)
+ vim.treesitter._query_linter.lint(buf, opts)
end
end
@@ -813,13 +987,15 @@ end
--- vim.bo.omnifunc = 'v:lua.vim.treesitter.query.omnifunc'
--- ```
---
+--- @param findstart 0|1
+--- @param base string
function M.omnifunc(findstart, base)
- return require('vim.treesitter._query_linter').omnifunc(findstart, base)
+ return vim.treesitter._query_linter.omnifunc(findstart, base)
end
--- Opens a live editor to query the buffer you started from.
---
---- Can also be shown with *:EditQuery*.
+--- Can also be shown with [:EditQuery]().
---
--- If you move the cursor to a capture name ("@foo"), text matching the capture is highlighted in
--- the source buffer. The query editor is a scratch buffer, use `:write` to save it. You can find
@@ -827,7 +1003,7 @@ end
---
--- @param lang? string language to open the query editor for. If omitted, inferred from the current buffer's filetype.
function M.edit(lang)
- require('vim.treesitter.dev').edit_query(lang)
+ vim.treesitter.dev.edit_query(lang)
end
return M
diff --git a/runtime/lua/vim/ui.lua b/runtime/lua/vim/ui.lua
index b6ddf337ce..b0e7ca1a35 100644
--- a/runtime/lua/vim/ui.lua
+++ b/runtime/lua/vim/ui.lua
@@ -20,7 +20,7 @@ local M = {}
--- end)
--- ```
---
----@param items table Arbitrary items
+---@param items any[] Arbitrary items
---@param opts table Additional options
--- - prompt (string|nil)
--- Text of the prompt. Defaults to `Select one of:`
@@ -32,7 +32,7 @@ local M = {}
--- Plugins reimplementing `vim.ui.select` may wish to
--- use this to infer the structure or semantics of
--- `items`, or the context in which select() was called.
----@param on_choice function ((item|nil, idx|nil) -> ())
+---@param on_choice fun(item: any|nil, idx: integer|nil)
--- Called once the user made a choice.
--- `idx` is the 1-based index of `item` within `items`.
--- `nil` if the user aborted the dialog.
@@ -44,7 +44,7 @@ function M.select(items, opts, on_choice)
opts = opts or {}
local choices = { opts.prompt or 'Select one of:' }
local format_item = opts.format_item or tostring
- for i, item in pairs(items) do
+ for i, item in ipairs(items) do
table.insert(choices, string.format('%d: %s', i, format_item(item)))
end
local choice = vim.fn.inputlist(choices)
@@ -66,7 +66,7 @@ end
--- end)
--- ```
---
----@param opts table Additional options. See |input()|
+---@param opts table? Additional options. See |input()|
--- - prompt (string|nil)
--- Text of the prompt
--- - default (string|nil)
@@ -87,6 +87,7 @@ end
--- `nil` if the user aborted the dialog.
function M.input(opts, on_confirm)
vim.validate({
+ opts = { opts, 'table', true },
on_confirm = { on_confirm, 'function', false },
})
@@ -133,7 +134,7 @@ function M.open(path)
path = vim.fn.expand(path)
end
- local cmd
+ local cmd --- @type string[]
if vim.fn.has('mac') == 1 then
cmd = { 'open', path }
@@ -143,12 +144,12 @@ function M.open(path)
else
return nil, 'vim.ui.open: rundll32 not found'
end
- elseif vim.fn.executable('wslview') == 1 then
- cmd = { 'wslview', path }
+ elseif vim.fn.executable('explorer.exe') == 1 then
+ cmd = { 'explorer.exe', path }
elseif vim.fn.executable('xdg-open') == 1 then
cmd = { 'xdg-open', path }
else
- return nil, 'vim.ui.open: no handler found (tried: wslview, xdg-open)'
+ return nil, 'vim.ui.open: no handler found (tried: explorer.exe, xdg-open)'
end
local rv = vim.system(cmd, { text = true, detach = true }):wait()
diff --git a/runtime/lua/vim/ui/clipboard/osc52.lua b/runtime/lua/vim/ui/clipboard/osc52.lua
index 6483f0387d..50afbe63a5 100644
--- a/runtime/lua/vim/ui/clipboard/osc52.lua
+++ b/runtime/lua/vim/ui/clipboard/osc52.lua
@@ -13,7 +13,9 @@ function M.copy(reg)
local clipboard = reg == '+' and 'c' or 'p'
return function(lines)
local s = table.concat(lines, '\n')
- io.stdout:write(osc52(clipboard, vim.base64.encode(s)))
+ -- The data to be written here can be quite long.
+ -- Use nvim_chan_send() as io.stdout:write() doesn't handle EAGAIN. #26688
+ vim.api.nvim_chan_send(2, osc52(clipboard, vim.base64.encode(s)))
end
end
diff --git a/runtime/lua/vim/uri.lua b/runtime/lua/vim/uri.lua
index 2dc817c5c1..b4e4098b91 100644
--- a/runtime/lua/vim/uri.lua
+++ b/runtime/lua/vim/uri.lua
@@ -1,4 +1,4 @@
----TODO: This is implemented only for files currently.
+-- TODO: This is implemented only for files currently.
-- https://tools.ietf.org/html/rfc3986
-- https://tools.ietf.org/html/rfc2732
-- https://tools.ietf.org/html/rfc2396
@@ -10,14 +10,14 @@ local tohex = require('bit').tohex
local URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):.*'
local WINDOWS_URI_SCHEME_PATTERN = '^([a-zA-Z]+[a-zA-Z0-9.+-]*):[a-zA-Z]:.*'
local PATTERNS = {
- ---RFC 2396
- ---https://tools.ietf.org/html/rfc2396#section-2.2
+ -- RFC 2396
+ -- https://tools.ietf.org/html/rfc2396#section-2.2
rfc2396 = "^A-Za-z0-9%-_.!~*'()",
- ---RFC 2732
- ---https://tools.ietf.org/html/rfc2732
+ -- RFC 2732
+ -- https://tools.ietf.org/html/rfc2732
rfc2732 = "^A-Za-z0-9%-_.!~*'()[]",
- ---RFC 3986
- ---https://tools.ietf.org/html/rfc3986#section-2.2
+ -- RFC 3986
+ -- https://tools.ietf.org/html/rfc3986#section-2.2
rfc3986 = "^A-Za-z0-9%-._~!$&'()*+,;=:@/",
}
@@ -104,6 +104,10 @@ function M.uri_to_fname(uri)
if scheme ~= 'file' then
return uri
end
+ local fragment_index = uri:find('#')
+ if fragment_index ~= nil then
+ uri = uri:sub(1, fragment_index - 1)
+ end
uri = M.uri_decode(uri)
--TODO improve this.
if is_windows_file_uri(uri) then
@@ -116,7 +120,6 @@ end
---Gets the buffer for a uri.
---Creates a new unloaded buffer if no buffer for the uri already exists.
---
---@param uri string
---@return integer bufnr
function M.uri_to_bufnr(uri)
diff --git a/runtime/lua/vim/version.lua b/runtime/lua/vim/version.lua
index 306eef90d3..0b149700b5 100644
--- a/runtime/lua/vim/version.lua
+++ b/runtime/lua/vim/version.lua
@@ -1,6 +1,5 @@
---- @defgroup vim.version
----
---- @brief The \`vim.version\` module provides functions for comparing versions and ranges
+--- @brief
+--- The `vim.version` module provides functions for comparing versions and ranges
--- conforming to the https://semver.org spec. Plugins, and plugin managers, can use this to check
--- available tools and dependencies on the current system.
---
@@ -13,9 +12,9 @@
--- end
--- ```
---
---- \*vim.version()\* returns the version of the current Nvim process.
+--- [vim.version()]() returns the version of the current Nvim process.
---
---- VERSION RANGE SPEC \*version-range\*
+--- VERSION RANGE SPEC [version-range]()
---
--- A version "range spec" defines a semantic version range which can be tested against a version,
--- using |vim.version.range()|.
@@ -55,7 +54,8 @@
local M = {}
----@class Version
+---@nodoc
+---@class vim.Version
---@field [1] number
---@field [2] number
---@field [3] number
@@ -69,6 +69,8 @@ Version.__index = Version
--- Compares prerelease strings: per semver, number parts must be must be treated as numbers:
--- "pre1.10" is greater than "pre1.2". https://semver.org/#spec-item-11
+---@param prerel1 string?
+---@param prerel2 string?
local function cmp_prerel(prerel1, prerel2)
if not prerel1 or not prerel2 then
return prerel1 and -1 or (prerel2 and 1 or 0)
@@ -78,8 +80,8 @@ local function cmp_prerel(prerel1, prerel2)
local iter1 = prerel1:gmatch('([^0-9]*)(%d*)')
local iter2 = prerel2:gmatch('([^0-9]*)(%d*)')
while true do
- local word1, n1 = iter1()
- local word2, n2 = iter2()
+ local word1, n1 = iter1() --- @type string?, string|number|nil
+ local word2, n2 = iter2() --- @type string?, string|number|nil
if word1 == nil and word2 == nil then -- Done iterating.
return 0
end
@@ -110,7 +112,7 @@ function Version:__newindex(key, value)
end
end
----@param other Version
+---@param other vim.Version
function Version:__eq(other)
for i = 1, 3 do
if self[i] ~= other[i] then
@@ -131,7 +133,7 @@ function Version:__tostring()
return ret
end
----@param other Version
+---@param other vim.Version
function Version:__lt(other)
for i = 1, 3 do
if self[i] > other[i] then
@@ -143,7 +145,7 @@ function Version:__lt(other)
return -1 == cmp_prerel(self.prerelease, other.prerelease)
end
----@param other Version
+---@param other vim.Version
function Version:__le(other)
return self < other or self == other
end
@@ -152,13 +154,13 @@ end
---
--- Creates a new Version object, or returns `nil` if `version` is invalid.
---
---- @param version string|number[]|Version
+--- @param version string|number[]|vim.Version
--- @param strict? boolean Reject "1.0", "0-x", "3.2a" or other non-conforming version strings
---- @return Version?
+--- @return vim.Version?
function M._version(version, strict) -- Adapted from https://github.com/folke/lazy.nvim
if type(version) == 'table' then
if version.major then
- return setmetatable(vim.deepcopy(version), Version)
+ return setmetatable(vim.deepcopy(version, true), Version)
end
return setmetatable({
major = version[1] or 0,
@@ -168,6 +170,7 @@ function M._version(version, strict) -- Adapted from https://github.com/folke/la
end
if not strict then -- TODO: add more "scrubbing".
+ --- @cast version string
version = version:match('%d[^ ]*')
end
@@ -201,7 +204,7 @@ end
---TODO: generalize this, move to func.lua
---
----@generic T: Version
+---@generic T: vim.Version
---@param versions T[]
---@return T?
function M.last(versions)
@@ -214,21 +217,22 @@ function M.last(versions)
return last
end
----@class VersionRange
----@field from Version
----@field to? Version
+---@class vim.VersionRange
+---@inlinedoc
+---@field from vim.Version
+---@field to? vim.Version
local VersionRange = {}
--- @private
---
----@param version string|Version
+---@param version string|vim.Version
function VersionRange:has(version)
if type(version) == 'string' then
---@diagnostic disable-next-line: cast-local-type
version = M.parse(version)
elseif getmetatable(version) ~= Version then
-- Need metatable to compare versions.
- version = setmetatable(vim.deepcopy(version), Version)
+ version = setmetatable(vim.deepcopy(version, true), Version)
end
if version then
if version.prerelease ~= self.from.prerelease then
@@ -259,16 +263,18 @@ end
--- print(r:has(vim.version())) -- check against current Nvim version
--- ```
---
---- Or use cmp(), eq(), lt(), and gt() to compare `.to` and `.from` directly:
+--- Or use cmp(), le(), lt(), ge(), gt(), and/or eq() to compare a version
+--- against `.to` and `.from` directly:
---
--- ```lua
---- local r = vim.version.range('1.0.0 - 2.0.0')
---- print(vim.version.gt({1,0,3}, r.from) and vim.version.lt({1,0,3}, r.to))
+--- local r = vim.version.range('1.0.0 - 2.0.0') -- >=1.0, <2.0
+--- print(vim.version.ge({1,0,3}, r.from) and vim.version.lt({1,0,3}, r.to))
--- ```
---
--- @see # https://github.com/npm/node-semver#ranges
---
--- @param spec string Version range "spec"
+--- @return vim.VersionRange?
function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim
if spec == '*' or spec == '' then
return setmetatable({ from = M.parse('0.0.0') }, { __index = VersionRange })
@@ -297,8 +303,9 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim
local semver = M.parse(version)
if semver then
- local from = semver
- local to = vim.deepcopy(semver)
+ local from = semver --- @type vim.Version?
+ local to = vim.deepcopy(semver, true) --- @type vim.Version?
+ ---@diagnostic disable: need-check-nil
if mods == '' or mods == '=' then
to.patch = to.patch + 1
elseif mods == '<' then
@@ -308,9 +315,9 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim
to.patch = to.patch + 1
elseif mods == '>' then
from.patch = from.patch + 1
- to = nil ---@diagnostic disable-line: cast-local-type
+ to = nil
elseif mods == '>=' then
- to = nil ---@diagnostic disable-line: cast-local-type
+ to = nil
elseif mods == '~' then
if #parts >= 2 then
to[2] = to[2] + 1
@@ -331,11 +338,12 @@ function M.range(spec) -- Adapted from https://github.com/folke/lazy.nvim
end
end
end
+ ---@diagnostic enable: need-check-nil
return setmetatable({ from = from, to = to }, { __index = VersionRange })
end
end
----@param v string|Version
+---@param v string|vim.Version
---@return string
local function create_err_msg(v)
if type(v) == 'string' then
@@ -364,8 +372,8 @@ end
---
--- @note Per semver, build metadata is ignored when comparing two otherwise-equivalent versions.
---
----@param v1 Version|number[] Version object.
----@param v2 Version|number[] Version to compare with `v1`.
+---@param v1 vim.Version|number[]|string Version object.
+---@param v2 vim.Version|number[]|string Version to compare with `v1`.
---@return integer -1 if `v1 < v2`, 0 if `v1 == v2`, 1 if `v1 > v2`.
function M.cmp(v1, v2)
local v1_parsed = assert(M._version(v1), create_err_msg(v1))
@@ -380,24 +388,40 @@ function M.cmp(v1, v2)
end
---Returns `true` if the given versions are equal. See |vim.version.cmp()| for usage.
----@param v1 Version|number[]
----@param v2 Version|number[]
+---@param v1 vim.Version|number[]|string
+---@param v2 vim.Version|number[]|string
---@return boolean
function M.eq(v1, v2)
return M.cmp(v1, v2) == 0
end
+---Returns `true` if `v1 <= v2`. See |vim.version.cmp()| for usage.
+---@param v1 vim.Version|number[]|string
+---@param v2 vim.Version|number[]|string
+---@return boolean
+function M.le(v1, v2)
+ return M.cmp(v1, v2) <= 0
+end
+
---Returns `true` if `v1 < v2`. See |vim.version.cmp()| for usage.
----@param v1 Version|number[]
----@param v2 Version|number[]
+---@param v1 vim.Version|number[]|string
+---@param v2 vim.Version|number[]|string
---@return boolean
function M.lt(v1, v2)
return M.cmp(v1, v2) == -1
end
+---Returns `true` if `v1 >= v2`. See |vim.version.cmp()| for usage.
+---@param v1 vim.Version|number[]|string
+---@param v2 vim.Version|number[]|string
+---@return boolean
+function M.ge(v1, v2)
+ return M.cmp(v1, v2) >= 0
+end
+
---Returns `true` if `v1 > v2`. See |vim.version.cmp()| for usage.
----@param v1 Version|number[]
----@param v2 Version|number[]
+---@param v1 vim.Version|number[]|string
+---@param v2 vim.Version|number[]|string
---@return boolean
function M.gt(v1, v2)
return M.cmp(v1, v2) == 1
@@ -417,7 +441,7 @@ end
--- - strict (boolean): Default false. If `true`, no coercion is attempted on
--- input not conforming to semver v2.0.0. If `false`, `parse()` attempts to
--- coerce input such as "1.0", "0-x", "tmux 3.2a" into valid versions.
----@return table|nil parsed_version Version object or `nil` if input is invalid.
+---@return vim.Version? parsed_version Version object or `nil` if input is invalid.
function M.parse(version, opts)
assert(type(version) == 'string', create_err_msg(version))
opts = opts or { strict = false }
@@ -426,8 +450,9 @@ end
setmetatable(M, {
--- Returns the current Nvim version.
+ ---@return vim.Version
__call = function()
- local version = vim.fn.api_info().version
+ local version = vim.fn.api_info().version ---@type vim.Version
-- Workaround: vim.fn.api_info().version reports "prerelease" as a boolean.
version.prerelease = version.prerelease and 'dev' or nil
return setmetatable(version, Version)
diff --git a/runtime/lua/vim/vimhelp.lua b/runtime/lua/vim/vimhelp.lua
index a4d6a50b12..4af6866d48 100644
--- a/runtime/lua/vim/vimhelp.lua
+++ b/runtime/lua/vim/vimhelp.lua
@@ -2,26 +2,28 @@
local M = {}
--- Called when editing the doc/syntax.txt file
-function M.highlight_groups()
- local save_cursor = vim.fn.getcurpos()
-
- local start_lnum = vim.fn.search([[\*highlight-groups\*]], 'c')
- if start_lnum == 0 then
- return
- end
- local end_lnum = vim.fn.search('^======')
- if end_lnum == 0 then
- return
- end
-
+--- Apply current colorscheme to lists of default highlight groups
+---
+--- Note: {patterns} is assumed to be sorted by occurrence in the file.
+--- @param patterns {start:string,stop:string,match:string}[]
+function M.highlight_groups(patterns)
local ns = vim.api.nvim_create_namespace('vimhelp')
vim.api.nvim_buf_clear_namespace(0, ns, 0, -1)
- for lnum = start_lnum, end_lnum do
- local word = vim.api.nvim_buf_get_lines(0, lnum - 1, lnum, true)[1]:match('^(%w+)\t')
- if vim.fn.hlexists(word) ~= 0 then
- vim.api.nvim_buf_set_extmark(0, ns, lnum - 1, 0, { end_col = #word, hl_group = word })
+ local save_cursor = vim.fn.getcurpos()
+
+ for _, pat in pairs(patterns) do
+ local start_lnum = vim.fn.search(pat.start, 'c')
+ local end_lnum = vim.fn.search(pat.stop)
+ if start_lnum == 0 or end_lnum == 0 then
+ break
+ end
+
+ for lnum = start_lnum, end_lnum do
+ local word = vim.api.nvim_buf_get_lines(0, lnum - 1, lnum, true)[1]:match(pat.match)
+ if vim.fn.hlexists(word) ~= 0 then
+ vim.api.nvim_buf_set_extmark(0, ns, lnum - 1, 0, { end_col = #word, hl_group = word })
+ end
end
end
diff --git a/runtime/macros/less.vim b/runtime/macros/less.vim
index c99c636e59..8df29d96e6 100644
--- a/runtime/macros/less.vim
+++ b/runtime/macros/less.vim
@@ -1,6 +1,6 @@
" Vim script to work like "less"
" Maintainer: The Vim Project <https://github.com/vim/vim>
-" Last Change: 2023 Aug 10
+" Last Change: 2024 Feb 15
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
" Avoid loading this file twice, allow the user to define his own script.
@@ -227,67 +227,181 @@ noremap q :q<CR>
" Switch to editing (switch off less mode)
map v :silent call <SID>End()<CR>
fun! s:End()
- set ma
+ set modifiable noreadonly
if exists('s:lz')
let &lz = s:lz
endif
- unmap h
- unmap H
- unmap <Space>
- unmap <C-V>
- unmap f
- unmap <C-F>
- unmap z
- unmap <Esc><Space>
- unmap F
- unmap d
- unmap <C-D>
- unmap <CR>
- unmap <C-N>
- unmap e
- unmap <C-E>
- unmap j
- unmap <C-J>
- unmap b
- unmap <C-B>
- unmap w
- unmap <Esc>v
- unmap u
- unmap <C-U>
- unmap k
- unmap y
- unmap <C-Y>
- unmap <C-P>
- unmap <C-K>
- unmap r
- unmap <C-R>
- unmap R
- unmap g
- unmap <
- unmap <Esc><
- unmap G
- unmap >
- unmap <Esc>>
- unmap %
- unmap p
- unmap n
- unmap N
- unmap q
- unmap v
- unmap /
- unmap ?
- unmap <Up>
- unmap <Down>
- unmap <PageDown>
- unmap <kPageDown>
- unmap <PageUp>
- unmap <kPageUp>
- unmap <S-Down>
- unmap <S-Up>
- unmap <Home>
- unmap <kHome>
- unmap <End>
- unmap <kEnd>
+ if !empty(maparg('h'))
+ unmap h
+ endif
+ if !empty(maparg('H'))
+ unmap H
+ endif
+ if !empty(maparg('<Space>'))
+ unmap <Space>
+ endif
+ if !empty(maparg('<C-V>'))
+ unmap <C-V>
+ endif
+ if !empty(maparg('f'))
+ unmap f
+ endif
+ if !empty(maparg('<C-F>'))
+ unmap <C-F>
+ endif
+ if !empty(maparg('z'))
+ unmap z
+ endif
+ if !empty(maparg('<Esc><Space>'))
+ unmap <Esc><Space>
+ endif
+ if !empty(maparg('F'))
+ unmap F
+ endif
+ if !empty(maparg('d'))
+ unmap d
+ endif
+ if !empty(maparg('<C-D>'))
+ unmap <C-D>
+ endif
+ if !empty(maparg('<CR>'))
+ unmap <CR>
+ endif
+ if !empty(maparg('<C-N>'))
+ unmap <C-N>
+ endif
+ if !empty(maparg('e'))
+ unmap e
+ endif
+ if !empty(maparg('<C-E>'))
+ unmap <C-E>
+ endif
+ if !empty(maparg('j'))
+ unmap j
+ endif
+ if !empty(maparg('<C-J>'))
+ unmap <C-J>
+ endif
+ if !empty(maparg('b'))
+ unmap b
+ endif
+ if !empty(maparg('<C-B>'))
+ unmap <C-B>
+ endif
+ if !empty(maparg('w'))
+ unmap w
+ endif
+ if !empty(maparg('<Esc>v'))
+ unmap <Esc>v
+ endif
+ if !empty(maparg('u'))
+ unmap u
+ endif
+ if !empty(maparg('<C-U>'))
+ unmap <C-U>
+ endif
+ if !empty(maparg('k'))
+ unmap k
+ endif
+ if !empty(maparg('y'))
+ unmap y
+ endif
+ if !empty(maparg('<C-Y>'))
+ unmap <C-Y>
+ endif
+ if !empty(maparg('<C-P>'))
+ unmap <C-P>
+ endif
+ if !empty(maparg('<C-K>'))
+ unmap <C-K>
+ endif
+ if !empty(maparg('r'))
+ unmap r
+ endif
+ if !empty(maparg('<C-R>'))
+ unmap <C-R>
+ endif
+ if !empty(maparg('R'))
+ unmap R
+ endif
+ if !empty(maparg('g'))
+ unmap g
+ endif
+ if !empty(maparg('<'))
+ unmap <
+ endif
+ if !empty(maparg('<Esc><'))
+ unmap <Esc><
+ endif
+ if !empty(maparg('G'))
+ unmap G
+ endif
+ if !empty(maparg('>'))
+ unmap >
+ endif
+ if !empty(maparg('<Esc>>'))
+ unmap <Esc>>
+ endif
+ if !empty(maparg('%'))
+ unmap %
+ endif
+ if !empty(maparg('p'))
+ unmap p
+ endif
+ if !empty(maparg('n'))
+ unmap n
+ endif
+ if !empty(maparg('N'))
+ unmap N
+ endif
+ if !empty(maparg('q'))
+ unmap q
+ endif
+ if !empty(maparg('v'))
+ unmap v
+ endif
+ if !empty(maparg('/'))
+ unmap /
+ endif
+ if !empty(maparg('?'))
+ unmap ?
+ endif
+ if !empty(maparg('<Up>'))
+ unmap <Up>
+ endif
+ if !empty(maparg('<Down>'))
+ unmap <Down>
+ endif
+ if !empty(maparg('<PageDown>'))
+ unmap <PageDown>
+ endif
+ if !empty(maparg('<kPageDown>'))
+ unmap <kPageDown>
+ endif
+ if !empty(maparg('<PageUp>'))
+ unmap <PageUp>
+ endif
+ if !empty(maparg('<kPageUp>'))
+ unmap <kPageUp>
+ endif
+ if !empty(maparg('<S-Down>'))
+ unmap <S-Down>
+ endif
+ if !empty(maparg('<S-Up>'))
+ unmap <S-Up>
+ endif
+ if !empty(maparg('<Home>'))
+ unmap <Home>
+ endif
+ if !empty(maparg('<kHome>'))
+ unmap <kHome>
+ endif
+ if !empty(maparg('<End>'))
+ unmap <End>
+ endif
+ if !empty(maparg('<kEnd>'))
+ unmap <kEnd>
+ endif
endfun
" vim: sw=2
diff --git a/runtime/makemenu.vim b/runtime/makemenu.vim
index 5d288e2f40..01f214cfa0 100644
--- a/runtime/makemenu.vim
+++ b/runtime/makemenu.vim
@@ -382,8 +382,10 @@ SynMenu M.MMIX:mmix
SynMenu M.Modconf:modconf
SynMenu M.Model:model
SynMenu M.Modsim\ III:modsim3
-SynMenu M.Modula\ 2:modula2
-SynMenu M.Modula\ 3:modula3
+SynMenu M.Modula-2.R10\ (2010):modula2:r10
+SynMenu M.Modula-2.ISO\ (1994):modula2:iso
+SynMenu M.Modula-2.PIM\ (1985):modula2:pim
+SynMenu M.Modula-3:modula3
SynMenu M.Monk:monk
SynMenu M.Motorola\ S-Record:srec
SynMenu M.Mplayer\ config:mplayerconf
diff --git a/runtime/mswin.vim b/runtime/mswin.vim
index 815667ead9..107a2acc2e 100644
--- a/runtime/mswin.vim
+++ b/runtime/mswin.vim
@@ -1,7 +1,7 @@
" Set options and add mapping such that Vim behaves a lot like MS-Windows
"
" Maintainer: The Vim Project <https://github.com/vim/vim>
-" Last Change: 2023 Aug 10
+" Last Change: 2024 Mar 3
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
" Bail out if this isn't wanted.
@@ -27,7 +27,7 @@ set backspace=indent,eol,start whichwrap+=<,>,[,]
" backspace in Visual mode deletes selection
vnoremap <BS> d
-if has("clipboard")
+if has("clipboard_working")
" CTRL-X and SHIFT-Del are Cut
vnoremap <C-X> "+x
vnoremap <S-Del> "+x
@@ -42,6 +42,23 @@ if has("clipboard")
cmap <C-V> <C-R>+
cmap <S-Insert> <C-R>+
+else
+ " Use unnamed register while clipboard not exist
+
+ " CTRL-X and SHIFT-Del are Cut
+ vnoremap <C-X> x
+ vnoremap <S-Del> x
+
+ " CTRL-C and CTRL-Insert are Copy
+ vnoremap <C-C> y
+ vnoremap <C-Insert> y
+
+ " CTRL-V and SHIFT-Insert are Paste
+ noremap <C-V> gP
+ noremap <S-Insert> gP
+
+ inoremap <C-V> <C-R>"
+ inoremap <S-Insert> <C-R>"
endif
" Pasting blockwise and linewise selections is not possible in Insert and
@@ -50,7 +67,7 @@ endif
" Uses the paste.vim autoload script.
" Use CTRL-G u to have CTRL-Z only undo the paste.
-if 1
+if has("clipboard_working")
exe 'inoremap <script> <C-V> <C-G>u' . paste#paste_cmd['i']
exe 'vnoremap <script> <C-V> ' . paste#paste_cmd['v']
endif
diff --git a/runtime/nvim.appdata.xml b/runtime/nvim.appdata.xml
index 29db9d5ee4..bff8bc4bff 100644
--- a/runtime/nvim.appdata.xml
+++ b/runtime/nvim.appdata.xml
@@ -56,7 +56,7 @@
<launchable type="desktop-id">nvim.desktop</launchable>
<url type="homepage">https://neovim.io/</url>
<url type="bugtracker">https://github.com/neovim/neovim/issues</url>
- <url type="faq">https://github.com/neovim/neovim/wiki/FAQ</url>
+ <url type="faq">https://neovim.io/doc/user/faq.html</url>
<url type="help">https://neovim.io/doc/</url>
<url type="donation">https://neovim.io/#sponsor</url>
<url type="translate">https://github.com/neovim/neovim/tree/master/src/nvim/po</url>
diff --git a/runtime/pack/dist/opt/justify/plugin/justify.vim b/runtime/pack/dist/opt/justify/plugin/justify.vim
index 4ef3bf95fa..57be790423 100644
--- a/runtime/pack/dist/opt/justify/plugin/justify.vim
+++ b/runtime/pack/dist/opt/justify/plugin/justify.vim
@@ -80,7 +80,7 @@
" conformant with :left, :right and :center.
"
" If joinspaces is set, an extra space is added after '.', '?' and '!'.
-" If 'cpooptions' include 'j', extra space is only added after '.'.
+" If 'cpoptions' include 'j', extra space is only added after '.'.
" (This may on occasion conflict with maxspaces.)
diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
index 1b5baa9a8b..a253acc63f 100644
--- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
+++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
@@ -35,21 +35,14 @@
" The communication with gdb uses GDB/MI. See:
" https://sourceware.org/gdb/current/onlinedocs/gdb/GDB_002fMI.html
"
-" For neovim compatibility, the vim specific calls were replaced with neovim
-" specific calls:
-" term_start -> termopen
-" term_sendkeys -> chansend
-" term_getline -> getbufline
-" job_info && term_getjob -> using linux command ps to get the tty
-" balloon -> nvim floating window
+" NEOVIM COMPATIBILITY
"
-" The code for opening the floating window was taken from the beautiful
-" implementation of LanguageClient-Neovim:
-" https://github.com/autozimu/LanguageClient-neovim/blob/0ed9b69dca49c415390a8317b19149f97ae093fa/autoload/LanguageClient.vim#L304
-"
-" Neovim terminal also works seamlessly on windows, which is why the ability
-" Author: Bram Moolenaar
-" Copyright: Vim license applies, see ":help license"
+" The vim specific functionalities were replaced with neovim specific calls:
+" - term_start -> termopen
+" - term_sendkeys -> chansend
+" - term_getline -> getbufline
+" - job_info && term_getjob -> nvim_get_chan_info
+" - balloon -> vim.lsp.util.open_floating_preview
" In case this gets sourced twice.
if exists(':Termdebug')
@@ -985,6 +978,7 @@ func s:InstallCommands()
set cpo&vim
command -nargs=? Break call s:SetBreakpoint(<q-args>)
+ command -nargs=? Tbreak call s:SetBreakpoint(<q-args>, v:true)
command Clear call s:ClearBreakpoint()
command Step call s:SendResumingCommand('-exec-step')
command Over call s:SendResumingCommand('-exec-next')
@@ -1093,6 +1087,7 @@ endfunc
" Delete installed debugger commands in the current window.
func s:DeleteCommands()
delcommand Break
+ delcommand Tbreak
delcommand Clear
delcommand Step
delcommand Over
@@ -1193,7 +1188,7 @@ func s:Until(at)
endfunc
" :Break - Set a breakpoint at the cursor position.
-func s:SetBreakpoint(at)
+func s:SetBreakpoint(at, tbreak=v:false)
" Setting a breakpoint may not work while the program is running.
" Interrupt to make it work.
let do_continue = 0
@@ -1206,7 +1201,12 @@ func s:SetBreakpoint(at)
" Use the fname:lnum format, older gdb can't handle --source.
let at = empty(a:at) ?
\ fnameescape(expand('%:p')) . ':' . line('.') : a:at
- call s:SendCommand('-break-insert ' . at)
+ if a:tbreak
+ let cmd = '-break-insert -t ' . at
+ else
+ let cmd = '-break-insert ' . at
+ endif
+ call s:SendCommand(cmd)
if do_continue
Continue
endif
@@ -1306,7 +1306,14 @@ endfunc
" :Evaluate - evaluate what is specified / under the cursor
func s:Evaluate(range, arg)
+ if s:eval_float_win_id > 0 && nvim_win_is_valid(s:eval_float_win_id)
+ \ && a:range == 0 && empty(a:arg)
+ call nvim_set_current_win(s:eval_float_win_id)
+ return
+ endif
let expr = s:GetEvaluationExpression(a:range, a:arg)
+ let s:evalFromBalloonExpr = 1
+ let s:evalFromBalloonExprResult = ''
let s:ignoreEvalError = 0
call s:SendEval(expr)
endfunc
@@ -1363,6 +1370,8 @@ let s:ignoreEvalError = 0
let s:evalFromBalloonExpr = 0
let s:evalFromBalloonExprResult = ''
+let s:eval_float_win_id = -1
+
" Handle the result of data-evaluate-expression
func s:HandleEvaluate(msg)
let value = a:msg
@@ -1385,9 +1394,15 @@ func s:HandleEvaluate(msg)
else
let s:evalFromBalloonExprResult .= ' = ' . value
endif
- let s:evalFromBalloonExprResult = split(s:evalFromBalloonExprResult, '\\n')
- call s:OpenHoverPreview(s:evalFromBalloonExprResult, v:null)
- let s:evalFromBalloonExprResult = ''
+ " NEOVIM:
+ " - Result pretty-printing is not implemented. Vim prettifies the result
+ " with balloon_split(), which is not ported to nvim.
+ " - Manually implement window focusing. Sometimes the result of pointer
+ " evaluation arrives in two separate messages, one for the address
+ " itself and the other for the value in that address. So with the stock
+ " focus option, the second message will focus the window containing the
+ " first message.
+ let s:eval_float_win_id = luaeval('select(2, vim.lsp.util.open_floating_preview(_A))', [s:evalFromBalloonExprResult])
else
echomsg '"' . s:evalexpr . '": ' . value
endif
@@ -1396,132 +1411,9 @@ func s:HandleEvaluate(msg)
" Looks like a pointer, also display what it points to.
let s:ignoreEvalError = 1
call s:SendEval('*' . s:evalexpr)
- else
- let s:evalFromBalloonExprResult = ''
endif
endfunc
-function! s:ShouldUseFloatWindow() abort
- if exists('*nvim_open_win') && (get(g:, 'termdebug_useFloatingHover', 1) == 1)
- return v:true
- else
- return v:false
- endif
-endfunction
-
-function! s:CloseFloatingHoverOnCursorMove(win_id, opened) abort
- if getpos('.') == a:opened
- " Just after opening floating window, CursorMoved event is run.
- " To avoid closing floating window immediately, check the cursor
- " was really moved
- return
- endif
- autocmd! nvim_termdebug_close_hover
- let winnr = win_id2win(a:win_id)
- if winnr == 0
- return
- endif
- call nvim_win_close(a:win_id, v:true)
-endfunction
-
-function! s:CloseFloatingHoverOnBufEnter(win_id, bufnr) abort
- let winnr = win_id2win(a:win_id)
- if winnr == 0
- " Float window was already closed
- autocmd! nvim_termdebug_close_hover
- return
- endif
- if winnr == winnr()
- " Cursor is moving into floating window. Do not close it
- return
- endif
- if bufnr('%') == a:bufnr
- " When current buffer opened hover window, it's not another buffer. Skipped
- return
- endif
- autocmd! nvim_termdebug_close_hover
- call nvim_win_close(a:win_id, v:true)
-endfunction
-
-" Open preview window. Window is open in:
-" - Floating window on Neovim (0.4.0 or later)
-" - Preview window on Neovim (0.3.0 or earlier) or Vim
-function! s:OpenHoverPreview(lines, filetype) abort
- " Use local variable since parameter is not modifiable
- let lines = a:lines
- let bufnr = bufnr('%')
-
- let use_float_win = s:ShouldUseFloatWindow()
- if use_float_win
- let pos = getpos('.')
-
- " Calculate width and height
- let width = 0
- for index in range(len(lines))
- let line = lines[index]
- let lw = strdisplaywidth(line)
- if lw > width
- let width = lw
- endif
- let lines[index] = line
- endfor
-
- let height = len(lines)
-
- " Calculate anchor
- " Prefer North, but if there is no space, fallback into South
- let bottom_line = line('w0') + winheight(0) - 1
- if pos[1] + height <= bottom_line
- let vert = 'N'
- let row = 1
- else
- let vert = 'S'
- let row = 0
- endif
-
- " Prefer West, but if there is no space, fallback into East
- if pos[2] + width <= &columns
- let hor = 'W'
- let col = 0
- else
- let hor = 'E'
- let col = 1
- endif
-
- let buf = nvim_create_buf(v:false, v:true)
- call nvim_buf_set_lines(buf, 0, -1, v:true, lines)
- " using v:true for second argument of nvim_open_win make the floating
- " window disappear
- let float_win_id = nvim_open_win(buf, v:false, {
- \ 'relative': 'cursor',
- \ 'anchor': vert . hor,
- \ 'row': row,
- \ 'col': col,
- \ 'width': width,
- \ 'height': height,
- \ 'style': 'minimal',
- \ })
-
- if a:filetype isnot v:null
- call nvim_set_option_value('filetype', a:filetype, { 'win' : float_win_id })
- endif
-
- 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.
- let call_after_move = printf('<SID>CloseFloatingHoverOnCursorMove(%d, %s)', float_win_id, string(pos))
- let call_on_bufenter = printf('<SID>CloseFloatingHoverOnBufEnter(%d, %d)', float_win_id, bufnr)
- augroup nvim_termdebug_close_hover
- execute 'autocmd CursorMoved,CursorMovedI,InsertEnter <buffer> call ' . call_after_move
- execute 'autocmd BufEnter * call ' . call_on_bufenter
- augroup END
- else
- echomsg a:lines[0]
- endif
-endfunction
-
" Handle an error.
func s:HandleError(msg)
if s:ignoreEvalError
diff --git a/runtime/plugin/netrwPlugin.vim b/runtime/plugin/netrwPlugin.vim
index a347781e6f..ed6f7dc008 100644
--- a/runtime/plugin/netrwPlugin.vim
+++ b/runtime/plugin/netrwPlugin.vim
@@ -1,7 +1,8 @@
" netrwPlugin.vim: Handles file transfer and remote directory listing across a network
" PLUGIN SECTION
+" Maintainer: This runtime file is looking for a new maintainer.
" Date: Feb 09, 2021
-" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Former Maintainer: Charles E Campbell
" GetLatestVimScripts: 1075 1 :AutoInstall: netrw.vim
" Copyright: Copyright (C) 1999-2021 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
diff --git a/runtime/plugin/osc52.lua b/runtime/plugin/osc52.lua
index 374b70066f..7ffd64342e 100644
--- a/runtime/plugin/osc52.lua
+++ b/runtime/plugin/osc52.lua
@@ -1,12 +1,20 @@
-local tty = vim.iter(vim.api.nvim_list_uis()):any(function(ui)
- return ui.chan == 1 and ui.stdout_tty
-end)
+local tty = false
+for _, ui in ipairs(vim.api.nvim_list_uis()) do
+ if ui.chan == 1 and ui.stdout_tty then
+ tty = true
+ break
+ end
+end
if not tty or vim.g.clipboard ~= nil or vim.o.clipboard ~= '' or not os.getenv('SSH_TTY') then
return
end
-require('vim.termcap').query('Ms', function(cap, seq)
+require('vim.termcap').query('Ms', function(cap, found, seq)
+ if not found then
+ return
+ end
+
assert(cap == 'Ms')
-- Check 'clipboard' and g:clipboard again to avoid a race condition
@@ -16,7 +24,7 @@ require('vim.termcap').query('Ms', function(cap, seq)
-- If the terminal reports a sequence other than OSC 52 for the Ms capability
-- then ignore it. We only support OSC 52 (for now)
- if not seq:match('^\027%]52') then
+ if not seq or not seq:match('^\027%]52') then
return
end
diff --git a/runtime/plugin/tarPlugin.vim b/runtime/plugin/tarPlugin.vim
index 384a3ed823..26a994aee5 100644
--- a/runtime/plugin/tarPlugin.vim
+++ b/runtime/plugin/tarPlugin.vim
@@ -45,7 +45,7 @@ augroup tar
au BufReadCmd *.tar.xz call tar#Browse(expand("<amatch>"))
au BufReadCmd *.txz call tar#Browse(expand("<amatch>"))
au BufReadCmd *.tar.zst call tar#Browse(expand("<amatch>"))
- au BufReadCmd *.tzs call tar#Browse(expand("<amatch>"))
+ au BufReadCmd *.tzst call tar#Browse(expand("<amatch>"))
augroup END
" ---------------------------------------------------------------------
diff --git a/runtime/plugin/tohtml.lua b/runtime/plugin/tohtml.lua
new file mode 100644
index 0000000000..79f2794a40
--- /dev/null
+++ b/runtime/plugin/tohtml.lua
@@ -0,0 +1,12 @@
+if vim.g.loaded_2html_plugin ~= nil then
+ return
+end
+vim.g.loaded_2html_plugin = true
+
+vim.api.nvim_create_user_command('TOhtml', function(args)
+ local outfile = args.args ~= '' and args.args or vim.fn.tempname() .. '.html'
+ local html = require('tohtml').tohtml()
+ vim.fn.writefile(html, outfile)
+ vim.cmd.split(outfile)
+ vim.bo.filetype = 'html'
+end, { bar = true, nargs = '?' })
diff --git a/runtime/plugin/tohtml.vim b/runtime/plugin/tohtml.vim
deleted file mode 100644
index 56eb2c15bf..0000000000
--- a/runtime/plugin/tohtml.vim
+++ /dev/null
@@ -1,254 +0,0 @@
-" Vim plugin for converting a syntax highlighted file to HTML.
-" Maintainer: Ben Fritz <fritzophrenic@gmail.com>
-" Last Change: 2023 Sep 07
-"
-" The core of the code is in $VIMRUNTIME/autoload/tohtml.vim and
-" $VIMRUNTIME/syntax/2html.vim
-"
-if exists('g:loaded_2html_plugin')
- finish
-endif
-let g:loaded_2html_plugin = 'vim9.0_v2'
-
-"
-" Changelog: {{{
-" 9.0_v2 (this version): - Warn if using deprecated g:use_xhtml option
-" - Change default g:html_use_input_for_pc to "none"
-" instead of "fallback". All modern browsers support
-" the "user-select: none" and "content:" CSS
-" properties so the older method relying on extra
-" markup and unspecified browser/app clipboard
-" handling is only needed in rare special cases.
-" - Fix SourceForge issue #33: generate diff filler
-" correctly when new lines have been added to or
-" removed from end of buffer.
-" - Fix SourceForge issue #32/Vim Github issue #8547:
-" use translated highlight ID for styling the
-" special-use group names (e.g. LineNr) used
-" directly by name in the 2html processing.
-" - Fix SourceForge issue #26, refactoring to use
-" :let-heredoc style string assignment and
-" additional fixes for ".." vs. "." style string
-" concatenation. Requires Vim v8.1.1354 or higher.
-" 9.0_v1 (Vim 9.0.1275): - Implement g:html_no_doc and g:html_no_modeline
-" for diff mode. Add tests.
-" (Vim 9.0.1122): NOTE: no version string update for this version!
-" - Bugfix for variable name in g:html_no_doc
-" (Vim 9.0.0819): NOTE: no version string update for this version!
-" - Add options g:html_no_doc, g:html_no_lines,
-" and g:html_no_modeline (partially included in Vim
-" runtime prior to version string update).
-" - Updates for new Vim9 string append style (i.e. use
-" ".." instead of "."). Requires Vim version
-" 8.1.1114 or higher.
-"
-" 8.1 updates: {{{
-" 8.1_v2 (Vim 8.1.2312): - Fix SourceForge issue #19: fix calculation of tab
-" stop position to use in expanding a tab, when that
-" tab occurs after a syntax match which in turn
-" comes after previously expanded tabs.
-" - Set eventignore while splitting a window for the
-" destination file to ignore FileType events;
-" speeds up processing when the destination file
-" already exists and HTML highlight takes too long.
-" - Fix SourceForge issue #20: progress bar could not be
-" seen when DiffDelete background color matched
-" StatusLine background color. Added TOhtmlProgress
-" highlight group for manual user override, but
-" calculate it to be visible compared to StatusLine
-" by default.
-" - Fix SourceForge issue #1: Remove workaround for old
-" browsers which don't support 'ch' CSS unit, since
-" all modern browsers, including IE>=9, support it.
-" - Fix SourceForge issue #10: support termguicolors
-" - Fix SourceForge issue #21: default to using
-" generated content instead of <input> tags for
-" uncopyable text, so that text is correctly
-" prevented from being copied in chrome. Use
-" g:html_use_input_for_pc option to control the
-" method used.
-" - Switch to HTML5 to allow using vnu as a validator
-" in unit test.
-" - Fix fallback sizing of <input> tags for browsers
-" without "ch" support.
-" - Fix cursor on unselectable diff filler text.
-" 8.1_v1 (Vim 8.1.0528): - Fix SourceForge issue #6: Don't generate empty
-" script tag.
-" - Fix SourceForge issue #5: javascript should
-" declare variables with "var".
-" - Fix SourceForge issue #13: errors thrown sourcing
-" 2html.vim directly when plugins not loaded.
-" - Fix SourceForge issue #16: support 'vartabstop'.
-"}}}
-"
-" 7.4 updates: {{{
-" 7.4_v2 (Vim 7.4.0899): Fix error raised when converting a diff containing
-" an empty buffer. Jan Stocker: allow g:html_font to
-" take a list so it is easier to specfiy fallback
-" fonts in the generated CSS.
-" 7.4_v1 (Vim 7.4.0000): Fix modeline mangling for new "Vim:" format, and
-" also for version-specific modelines like "vim>703:".
-"}}}
-"
-" 7.3 updates: {{{
-" 7.3_v14 (Vim 7.3.1246): Allow suppressing line number anchors using
-" g:html_line_ids=0. Allow customizing
-" important IDs (like line IDs and fold IDs) using
-" g:html_id_expr evaluated when the buffer conversion
-" is started.
-" 7.3_v13 (Vim 7.3.1088): Keep foldmethod at manual in the generated file and
-" insert modeline to set it to manual.
-" Fix bug: diff mode with 2 unsaved buffers creates a
-" duplicate of one buffer instead of including both.
-" Add anchors to each line so you can put '#L123'
-" or '#123' at the end of the URL to jump to line 123
-" (idea by Andy Spencer). Add javascript to open folds
-" to show the anchor being jumped to if it is hidden.
-" Fix XML validation error: &nsbp; not part of XML.
-" Allow TOhtml to chain together with other commands
-" using |.
-" 7.3_v12 (Vim 7.3.0616): Fix modeline mangling to also work for when multiple
-" highlight groups make up the start-of-modeline text.
-" Improve render time of page with uncopyable regions
-" by not using one-input-per-char. Change name of
-" uncopyable option from html_unselectable to
-" html_prevent_copy. Added html_no_invalid option and
-" default to inserting invalid markup for uncopyable
-" regions to prevent MS Word from pasting undeletable
-" <input> elements. Fix 'cpo' handling (Thilo Six).
-" 7.3_v12b1: Add html_unselectable option. Rework logic to
-" eliminate post-processing substitute commands in
-" favor of doing the work up front. Remove unnecessary
-" special treatment of 'LineNr' highlight group. Minor
-" speed improvements. Fix modeline mangling in
-" generated output so it works for text in the first
-" column. Fix missing line number and fold column in
-" diff filler lines. Fix that some fonts have a 1px
-" gap (using a dirty hack, improvements welcome). Add
-" "colorscheme" meta tag. Does NOT include support for
-" the new default foldtext added in v11, as the patch
-" adding it has not yet been included in Vim.
-" 7.3_v11 ( unreleased ): Support new default foldtext from patch by Christian
-" Brabandt in
-" http://groups.google.com/d/topic/vim_dev/B6FSGfq9VoI/discussion.
-" This patch has not yet been included in Vim, thus
-" these changes are removed in the next version.
-" 7.3_v10 (Vim 7.3.0227): Fix error E684 when converting a range wholly inside
-" multiple nested folds with dynamic folding on.
-" Also fix problem with foldtext in this situation.
-" 7.3_v9 (Vim 7.3.0170): Add html_pre_wrap option active with html_use_css
-" and without html_no_pre, default value same as
-" 'wrap' option, (Andy Spencer). Don't use
-" 'fileencoding' for converted document encoding if
-" 'buftype' indicates a special buffer which isn't
-" written.
-" 7.3_v8 (Vim 7.3.0100): Add html_expand_tabs option to allow leaving tab
-" characters in generated output (Andy Spencer).
-" Escape text that looks like a modeline so Vim
-" doesn't use anything in the converted HTML as a
-" modeline. Bugfixes: Fix folding when a fold starts
-" before the conversion range. Remove fold column when
-" there are no folds.
-" 7.3_v7 (Vim 7-3-0063): see betas released on vim_dev below:
-" 7.3_v7b3: Fixed bug, convert Unicode to UTF-8 all the way.
-" 7.3_v7b2: Remove automatic detection of encodings that are not
-" supported by all major browsers according to
-" http://wiki.whatwg.org/wiki/Web_Encodings and
-" convert to UTF-8 for all Unicode encodings. Make
-" HTML encoding to Vim encoding detection be
-" case-insensitive for built-in pairs.
-" 7.3_v7b1: Remove use of setwinvar() function which cannot be
-" called in restricted mode (Andy Spencer). Use
-" 'fencoding' instead of 'encoding' to determine by
-" charset, and make sure the 'fenc' of the generated
-" file matches its indicated charset. Add charsets for
-" all of Vim's natively supported encodings.
-" 7.3_v6 (Vim 7.3.0000): Really fix bug with 'nowrapscan', 'magic' and other
-" user settings interfering with diff mode generation,
-" trailing whitespace (e.g. line number column) when
-" using html_no_pre, and bugs when using
-" html_hover_unfold.
-" 7.3_v5 ( unreleased ): Fix bug with 'nowrapscan' and also with out-of-sync
-" folds in diff mode when first line was folded.
-" 7.3_v4 (Vim 7.3.0000): Bugfixes, especially for xhtml markup, and diff mode
-" 7.3_v3 (Vim 7.3.0000): Refactor option handling and make html_use_css
-" default to true when not set to anything. Use strict
-" doctypes where possible. Rename use_xhtml option to
-" html_use_xhtml for consistency. Use .xhtml extension
-" when using this option. Add meta tag for settings.
-" 7.3_v2 (Vim 7.3.0000): Fix syntax highlighting in diff mode to use both the
-" diff colors and the normal syntax colors
-" 7.3_v1 (Vim 7.3.0000): Add conceal support and meta tags in output
-"}}}
-"}}}
-
-" TODO: {{{
-" * Check the issue tracker:
-" https://sourceforge.net/p/vim-tohtml/issues/search/?q=%21status%3Aclosed
-" * Options for generating the CSS in external style sheets. New :TOcss
-" command to convert the current color scheme into a (mostly) generic CSS
-" stylesheet which can be re-used. Alternate stylesheet support? Good start
-" by Erik Falor
-" ( https://groups.google.com/d/topic/vim_use/7XTmC4D22dU/discussion ).
-" * Add optional argument to :TOhtml command to specify mode (gui, cterm,
-" term) to use for the styling. Suggestion by "nacitar".
-" * Add way to override or specify which RGB colors map to the color numbers
-" in cterm. Get better defaults than just guessing? Suggestion by "nacitar".
-" * Disable filetype detection until after all processing is done.
-" * Add option for not generating the hyperlink on stuff that looks like a
-" URL? Or just color the link to fit with the colorscheme (and only special
-" when hovering)?
-" * Bug: Opera does not allow printing more than one page if uncopyable
-" regions is turned on. Possible solution: Add normal text line numbers with
-" display:none, set to display:inline for print style sheets, and hide
-" <input> elements for print, to allow Opera printing multiple pages (and
-" other uncopyable areas?). May need to make the new text invisible to IE
-" with conditional comments to prevent copying it, IE for some reason likes
-" to copy hidden text. Other browsers too?
-" * Bug: still a 1px gap throughout the fold column when html_prevent_copy is
-" "fn" in some browsers. Specifically, in Chromium on Ubuntu (but not Chrome
-" on Windows). Perhaps it is font related?
-" * Bug: still some gaps in the fold column when html_prevent_copy contains
-" 'd' and showing the whole diff (observed in multiple browsers). Only gaps
-" on diff lines though.
-" * Undercurl support via CSS3, with fallback to dotted or something:
-" https://groups.google.com/d/topic/vim_use/BzXA6He1pHg/discussion
-" * Redo updates for modified default foldtext (v11) when/if the patch is
-" accepted to modify it.
-" * Test case +diff_one_file-dynamic_folds+expand_tabs-hover_unfold
-" +ignore_conceal-ignore_folding+no_foldcolumn+no_pre+no_progress
-" +number_lines-pre_wrap-use_css+use_xhtml+whole_filler.xhtml
-" does not show the whole diff filler as it is supposed to?
-" * Bug: when 'isprint' is wrong for the current encoding, will generate
-" invalid content. Can/should anything be done about this? Maybe a separate
-" plugin to correct 'isprint' based on encoding?
-" * Check to see if the windows-125\d encodings actually work in Unix without
-" the 8bit- prefix. Add prefix to autoload dictionaries for Unix if not.
-" * Font auto-detection similar to
-" http://www.vim.org/scripts/script.php?script_id=2384 but for a variety of
-" platforms.
-" * Pull in code from http://www.vim.org/scripts/script.php?script_id=3113 :
-" - listchars support
-" - full-line background highlight
-" - other?
-" * Make it so deleted lines in a diff don't create side-scrolling (get it
-" free with full-line background highlight above).
-" * Restore open/closed folds and cursor position after processing each file
-" with option not to restore for speed increase.
-" * Add extra meta info (generation time, etc.)?
-" * Tidy up so we can use strict doctype in even more situations
-" * Implementation detail: add threshold for writing the lines to the html
-" buffer before we're done (5000 or so lines should do it)
-" * TODO comments for code cleanup scattered throughout
-"}}}
-
-" Define the :TOhtml command when:
-" - 'compatible' is not set
-" - this plugin or user override was not already loaded
-" - user commands are available. {{{
-if !&cp && !exists(":TOhtml") && has("user_commands")
- command -range=% -bar TOhtml :call tohtml#Convert2HTML(<line1>, <line2>)
-endif "}}}
-
-" Make sure any patches will probably use consistent indent
-" vim: ts=8 sw=2 sts=2 noet fdm=marker
diff --git a/runtime/plugin/zipPlugin.vim b/runtime/plugin/zipPlugin.vim
index c3118a361d..2af119bbcb 100644
--- a/runtime/plugin/zipPlugin.vim
+++ b/runtime/plugin/zipPlugin.vim
@@ -1,7 +1,8 @@
" zipPlugin.vim: Handles browsing zipfiles
" PLUGIN PORTION
" Date: Dec 07, 2021
-" Maintainer: Charles E Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E Campbell
" License: Vim License (see vim's :help license)
" Copyright: Copyright (C) 2005-2016 Charles E. Campbell {{{1
" Permission is hereby granted to use and distribute this code,
diff --git a/runtime/queries/bash/folds.scm b/runtime/queries/bash/folds.scm
index 851c67eed4..766dbe598b 100644
--- a/runtime/queries/bash/folds.scm
+++ b/runtime/queries/bash/folds.scm
@@ -5,4 +5,5 @@
(for_statement)
(while_statement)
(c_style_for_statement)
+ (heredoc_redirect)
] @fold
diff --git a/runtime/queries/bash/highlights.scm b/runtime/queries/bash/highlights.scm
index 23bf03e697..b4360ce7e1 100644
--- a/runtime/queries/bash/highlights.scm
+++ b/runtime/queries/bash/highlights.scm
@@ -1,81 +1,108 @@
-(simple_expansion) @none
-(expansion
- "${" @punctuation.special
- "}" @punctuation.special) @none
[
- "("
- ")"
- "(("
- "))"
- "{"
- "}"
- "["
- "]"
- "[["
- "]]"
- ] @punctuation.bracket
+ "("
+ ")"
+ "{"
+ "}"
+ "["
+ "]"
+ "[["
+ "]]"
+ "(("
+ "))"
+] @punctuation.bracket
[
- ";"
- ";;"
- (heredoc_start)
- ] @punctuation.delimiter
+ ";"
+ ";;"
+ ";&"
+ ";;&"
+ "&"
+] @punctuation.delimiter
[
- "$"
-] @punctuation.special
-
+ ">"
+ ">>"
+ "<"
+ "<<"
+ "&&"
+ "|"
+ "|&"
+ "||"
+ "="
+ "+="
+ "=~"
+ "=="
+ "!="
+ "&>"
+ "&>>"
+ "<&"
+ ">&"
+ ">|"
+ "<&-"
+ ">&-"
+ "<<-"
+ "<<<"
+ ".."
+ "!"
+] @operator
+
+; Do *not* spell check strings since they typically have some sort of
+; interpolation in them, or, are typically used for things like filenames, URLs,
+; flags and file content.
[
- ">"
- ">>"
- "<"
- "<<"
- "&"
- "&&"
- "|"
- "||"
- "="
- "=~"
- "=="
- "!="
- ] @operator
+ (string)
+ (raw_string)
+ (ansi_c_string)
+ (heredoc_body)
+] @string
[
- (string)
- (raw_string)
- (ansi_c_string)
- (heredoc_body)
-] @string @spell
+ (heredoc_start)
+ (heredoc_end)
+] @label
+
+(variable_assignment
+ (word) @string)
+
+(command
+ argument: "$" @string) ; bare dollar
-(variable_assignment (word) @string)
+(concatenation
+ [
+ (simple_expansion)
+ (expansion)
+ ]
+ (word) @string)
[
- "if"
- "then"
- "else"
- "elif"
- "fi"
- "case"
- "in"
- "esac"
- ] @conditional
+ "if"
+ "then"
+ "else"
+ "elif"
+ "fi"
+ "case"
+ "in"
+ "esac"
+] @keyword.conditional
[
- "for"
- "do"
- "done"
- "select"
- "until"
- "while"
- ] @repeat
+ "for"
+ "do"
+ "done"
+ "select"
+ "until"
+ "while"
+] @keyword.repeat
[
- "declare"
- "export"
- "local"
- "readonly"
- "unset"
- ] @keyword
+ "declare"
+ "typeset"
+ "export"
+ "readonly"
+ "local"
+ "unset"
+ "unsetenv"
+] @keyword
"function" @keyword.function
@@ -83,28 +110,56 @@
; trap -l
((word) @constant.builtin
- (#match? @constant.builtin "^SIG(HUP|INT|QUIT|ILL|TRAP|ABRT|BUS|FPE|KILL|USR[12]|SEGV|PIPE|ALRM|TERM|STKFLT|CHLD|CONT|STOP|TSTP|TT(IN|OU)|URG|XCPU|XFSZ|VTALRM|PROF|WINCH|IO|PWR|SYS|RTMIN([+]([1-9]|1[0-5]))?|RTMAX(-([1-9]|1[0-4]))?)$"))
+ (#match? @constant.builtin "^SIG(HUP|INT|QUIT|ILL|TRAP|ABRT|BUS|FPE|KILL|USR[12]|SEGV|PIPE|ALRM|TERM|STKFLT|CHLD|CONT|STOP|TSTP|TT(IN|OU)|URG|XCPU|XFSZ|VTALRM|PROF|WINCH|IO|PWR|SYS|RTMIN([+]([1-9]|1[0-5]))?|RTMAX(-([1-9]|1[0-4]))?)$"))
((word) @boolean
(#any-of? @boolean "true" "false"))
(comment) @comment @spell
-(test_operator) @string
+
+(test_operator) @operator
(command_substitution
- [ "$(" ")" ] @punctuation.bracket)
+ "$(" @punctuation.bracket)
(process_substitution
- [ "<(" ")" ] @punctuation.bracket)
+ "<(" @punctuation.bracket)
+
+(arithmetic_expansion
+ [
+ "$(("
+ "(("
+ ] @punctuation.special
+ "))" @punctuation.special)
+
+(arithmetic_expansion
+ "," @punctuation.delimiter)
+
+(ternary_expression
+ [
+ "?"
+ ":"
+ ] @keyword.conditional.ternary)
+
+(binary_expression
+ operator: _ @operator)
+
+(unary_expression
+ operator: _ @operator)
+(postfix_expression
+ operator: _ @operator)
(function_definition
name: (word) @function)
-(command_name (word) @function.call)
+(command_name
+ (word) @function.call)
-((command_name (word) @function.builtin)
- (#any-of? @function.builtin
+((command_name
+ (word) @function.builtin)
+ ; format-ignore
+ (#any-of? @function.builtin
"alias" "bg" "bind" "break" "builtin" "caller" "cd"
"command" "compgen" "complete" "compopt" "continue"
"coproc" "dirs" "disown" "echo" "enable" "eval"
@@ -116,30 +171,59 @@
"ulimit" "umask" "unalias" "wait"))
(command
- argument: [
- (word) @parameter
- (concatenation (word) @parameter)
- ])
+ argument:
+ [
+ (word) @variable.parameter
+ (concatenation
+ (word) @variable.parameter)
+ ])
+
+(number) @number
((word) @number
(#lua-match? @number "^[0-9]+$"))
(file_redirect
- descriptor: (file_descriptor) @operator
- destination: (word) @parameter)
+ destination: (word) @variable.parameter)
+
+(file_descriptor) @operator
+
+(simple_expansion
+ "$" @punctuation.special) @none
+
+(expansion
+ "${" @punctuation.special
+ "}" @punctuation.special) @none
(expansion
- [ "${" "}" ] @punctuation.bracket)
+ operator: _ @punctuation.special)
+
+(expansion
+ "@"
+ .
+ operator: _ @character.special)
+
+((expansion
+ (subscript
+ index: (word) @character.special))
+ (#any-of? @character.special "@" "*"))
+
+"``" @punctuation.special
(variable_name) @variable
((variable_name) @constant
- (#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
+ (#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
(case_item
- value: (word) @parameter)
-
-(regex) @string.regex
+ value: (word) @variable.parameter)
-((program . (comment) @preproc)
- (#lua-match? @preproc "^#!/"))
+[
+ (regex)
+ (extglob_pattern)
+] @string.regexp
+
+((program
+ .
+ (comment) @keyword.directive)
+ (#lua-match? @keyword.directive "^#!/"))
diff --git a/runtime/queries/c/folds.scm b/runtime/queries/c/folds.scm
index 5a35334a24..2e2a6b4d0c 100644
--- a/runtime/queries/c/folds.scm
+++ b/runtime/queries/c/folds.scm
@@ -1,19 +1,21 @@
[
- (for_statement)
- (if_statement)
- (while_statement)
- (switch_statement)
- (case_statement)
- (function_definition)
- (struct_specifier)
- (enum_specifier)
- (comment)
- (preproc_if)
- (preproc_elif)
- (preproc_else)
- (preproc_ifdef)
- (initializer_list)
- (gnu_asm_expression)
+ (for_statement)
+ (if_statement)
+ (while_statement)
+ (do_statement)
+ (switch_statement)
+ (case_statement)
+ (function_definition)
+ (struct_specifier)
+ (enum_specifier)
+ (comment)
+ (preproc_if)
+ (preproc_elif)
+ (preproc_else)
+ (preproc_ifdef)
+ (preproc_function_def)
+ (initializer_list)
+ (gnu_asm_expression)
] @fold
(compound_statement
diff --git a/runtime/queries/c/highlights.scm b/runtime/queries/c/highlights.scm
index 29fb5747ca..c848f68dca 100644
--- a/runtime/queries/c/highlights.scm
+++ b/runtime/queries/c/highlights.scm
@@ -1,6 +1,9 @@
-; Lower priority to prefer @parameter when identifier appears in parameter_declaration.
-((identifier) @variable (#set! "priority" 95))
-(preproc_def (preproc_arg) @variable)
+; Lower priority to prefer @variable.parameter when identifier appears in parameter_declaration.
+((identifier) @variable
+ (#set! "priority" 95))
+
+(preproc_def
+ (preproc_arg) @variable)
[
"default"
@@ -17,7 +20,10 @@
"sizeof"
"offsetof"
] @keyword.operator
-(alignof_expression . _ @keyword.operator)
+
+(alignof_expression
+ .
+ _ @keyword.operator)
"return" @keyword.return
@@ -27,14 +33,14 @@
"do"
"continue"
"break"
-] @repeat
+] @keyword.repeat
[
- "if"
- "else"
- "case"
- "switch"
-] @conditional
+ "if"
+ "else"
+ "case"
+ "switch"
+] @keyword.conditional
[
"#if"
@@ -46,48 +52,54 @@
"#elifdef"
"#elifndef"
(preproc_directive)
-] @preproc
+] @keyword.directive
-"#define" @define
+"#define" @keyword.directive.define
-"#include" @include
+"#include" @keyword.import
-[ ";" ":" "," "::" ] @punctuation.delimiter
+[
+ ";"
+ ":"
+ ","
+ "::"
+] @punctuation.delimiter
"..." @punctuation.special
-[ "(" ")" "[" "]" "{" "}"] @punctuation.bracket
+[
+ "("
+ ")"
+ "["
+ "]"
+ "{"
+ "}"
+] @punctuation.bracket
[
"="
-
"-"
"*"
"/"
"+"
"%"
-
"~"
"|"
"&"
"^"
"<<"
">>"
-
"->"
"."
-
"<"
"<="
">="
">"
"=="
"!="
-
"!"
"&&"
"||"
-
"-="
"+="
"*="
@@ -102,45 +114,57 @@
"++"
] @operator
-;; Make sure the comma operator is given a highlight group after the comma
-;; punctuator so the operator is highlighted properly.
-(comma_expression [ "," ] @operator)
+; Make sure the comma operator is given a highlight group after the comma
+; punctuator so the operator is highlighted properly.
+(comma_expression
+ "," @operator)
[
(true)
(false)
] @boolean
-(conditional_expression [ "?" ":" ] @conditional.ternary)
+(conditional_expression
+ [
+ "?"
+ ":"
+ ] @keyword.conditional.ternary)
(string_literal) @string
+
(system_lib_string) @string
+
(escape_sequence) @string.escape
(null) @constant.builtin
+
(number_literal) @number
+
(char_literal) @character
-((preproc_arg) @function.macro (#set! "priority" 90))
+((preproc_arg) @function.macro
+ (#set! "priority" 90))
+
(preproc_defined) @function.macro
-(((field_expression
- (field_identifier) @property)) @_parent
- (#not-has-parent? @_parent template_method function_declarator call_expression))
+((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))
+
+((field_identifier) @property
+ (#has-ancestor? @property field_declaration)
+ (#not-has-ancestor? @property function_declarator))
(statement_identifier) @label
[
- (type_identifier)
- (type_descriptor)
+ (type_identifier)
+ (type_descriptor)
] @type
-(storage_class_specifier) @storageclass
+(storage_class_specifier) @keyword.storage
[
(type_qualifier)
@@ -149,25 +173,32 @@
] @type.qualifier
(linkage_specification
- "extern" @storageclass)
+ "extern" @keyword.storage)
(type_definition
declarator: (type_identifier) @type.definition)
(primitive_type) @type.builtin
-(sized_type_specifier _ @type.builtin type: _?)
+(sized_type_specifier
+ _ @type.builtin
+ type: _?)
((identifier) @constant
- (#lua-match? @constant "^[A-Z][A-Z0-9_]+$"))
-(preproc_def (preproc_arg) @constant
(#lua-match? @constant "^[A-Z][A-Z0-9_]+$"))
+
+(preproc_def
+ (preproc_arg) @constant
+ (#lua-match? @constant "^[A-Z][A-Z0-9_]+$"))
+
(enumerator
name: (identifier) @constant)
+
(case_statement
value: (identifier) @constant)
((identifier) @constant.builtin
+ ; format-ignore
(#any-of? @constant.builtin
"stderr" "stdin" "stdout"
"__FILE__" "__LINE__" "__DATE__" "__TIME__"
@@ -180,7 +211,10 @@
"__clang_wide_literal_encoding__"
"__FUNCTION__" "__func__" "__PRETTY_FUNCTION__"
"__VA_ARGS__" "__VA_OPT__"))
-(preproc_def (preproc_arg) @constant.builtin
+
+(preproc_def
+ (preproc_arg) @constant.builtin
+ ; format-ignore
(#any-of? @constant.builtin
"stderr" "stdin" "stdout"
"__FILE__" "__LINE__" "__DATE__" "__TIME__"
@@ -195,21 +229,26 @@
"__VA_ARGS__" "__VA_OPT__"))
(attribute_specifier
- (argument_list (identifier) @variable.builtin))
+ (argument_list
+ (identifier) @variable.builtin))
+
((attribute_specifier
- (argument_list (call_expression
- function: (identifier) @variable.builtin))))
+ (argument_list
+ (call_expression
+ function: (identifier) @variable.builtin))))
((call_expression
function: (identifier) @function.builtin)
(#lua-match? @function.builtin "^__builtin_"))
+
((call_expression
- function: (identifier) @function.builtin)
+ function: (identifier) @function.builtin)
(#has-ancestor? @function.builtin attribute_specifier))
-;; Preproc def / undef
+; Preproc def / undef
(preproc_def
name: (_) @constant)
+
(preproc_call
directive: (preproc_directive) @_u
argument: (_) @constant
@@ -217,15 +256,21 @@
(call_expression
function: (identifier) @function.call)
+
(call_expression
- function: (field_expression
- field: (field_identifier) @function.call))
+ function:
+ (field_expression
+ field: (field_identifier) @function.call))
+
(function_declarator
declarator: (identifier) @function)
+
(function_declarator
- declarator: (parenthesized_declarator
- (pointer_declarator
- declarator: (field_identifier) @function)))
+ declarator:
+ (parenthesized_declarator
+ (pointer_declarator
+ declarator: (field_identifier) @function)))
+
(preproc_function_def
name: (identifier) @function.macro)
@@ -234,17 +279,40 @@
((comment) @comment.documentation
(#lua-match? @comment.documentation "^/[*][*][^*].*[*]/$"))
-;; Parameters
+; Parameters
(parameter_declaration
- declarator: (identifier) @parameter)
+ declarator: (identifier) @variable.parameter)
(parameter_declaration
- declarator: (array_declarator) @parameter)
+ declarator: (array_declarator) @variable.parameter)
(parameter_declaration
- declarator: (pointer_declarator) @parameter)
-
-(preproc_params (identifier) @parameter)
+ declarator: (pointer_declarator) @variable.parameter)
+
+; K&R functions
+; To enable support for K&R functions,
+; add the following lines to your own query config and uncomment them.
+; They are commented out as they'll conflict with C++
+; Note that you'll need to have `; extends` at the top of your query file.
+;
+; (parameter_list (identifier) @variable.parameter)
+;
+; (function_definition
+; declarator: _
+; (declaration
+; declarator: (identifier) @variable.parameter))
+;
+; (function_definition
+; declarator: _
+; (declaration
+; declarator: (array_declarator) @variable.parameter))
+;
+; (function_definition
+; declarator: _
+; (declaration
+; declarator: (pointer_declarator) @variable.parameter))
+(preproc_params
+ (identifier) @variable.parameter)
[
"__attribute__"
@@ -259,5 +327,3 @@
(ms_pointer_modifier)
(attribute_declaration)
] @attribute
-
-(ERROR) @error
diff --git a/runtime/queries/c/injections.scm b/runtime/queries/c/injections.scm
index 5a49e20df5..ce2f88a215 100644
--- a/runtime/queries/c/injections.scm
+++ b/runtime/queries/c/injections.scm
@@ -1,21 +1,2 @@
-((preproc_def
- (preproc_arg) @injection.content)
- (#lua-match? @injection.content "\n")
- (#set! injection.language "c"))
-
-(preproc_function_def
- (preproc_arg) @injection.content
- (#set! injection.language "c"))
-
-(preproc_call
- (preproc_arg) @injection.content
- (#set! injection.language "c"))
-
-; ((comment) @injection.content
-; (#set! injection.language "comment"))
-
-; TODO: add when asm is added
-; (gnu_asm_expression assembly_code: (string_literal) @injection.content
-; (#set! injection.language "asm"))
-; (gnu_asm_expression assembly_code: (concatenated_string (string_literal) @injection.content)
-; (#set! injection.language "asm"))
+((preproc_arg) @injection.content
+ (#set! injection.self))
diff --git a/runtime/queries/lua/folds.scm b/runtime/queries/lua/folds.scm
index d8f0b42df3..9dfac3abc6 100644
--- a/runtime/queries/lua/folds.scm
+++ b/runtime/queries/lua/folds.scm
@@ -1,10 +1,12 @@
[
- (do_statement)
- (while_statement)
- (repeat_statement)
- (if_statement)
- (for_statement)
- (function_declaration)
- (function_definition)
- (table_constructor)
+ (do_statement)
+ (while_statement)
+ (repeat_statement)
+ (if_statement)
+ (for_statement)
+ (function_declaration)
+ (function_definition)
+ (parameters)
+ (arguments)
+ (table_constructor)
] @fold
diff --git a/runtime/queries/lua/highlights.scm b/runtime/queries/lua/highlights.scm
index 96ffeae793..0b0bf35a8b 100644
--- a/runtime/queries/lua/highlights.scm
+++ b/runtime/queries/lua/highlights.scm
@@ -1,81 +1,79 @@
-;; Keywords
-
+; Keywords
"return" @keyword.return
[
- "goto"
- "in"
- "local"
+ "goto"
+ "in"
+ "local"
] @keyword
(break_statement) @keyword
(do_statement
-[
- "do"
- "end"
-] @keyword)
+ [
+ "do"
+ "end"
+ ] @keyword)
(while_statement
-[
- "while"
- "do"
- "end"
-] @repeat)
+ [
+ "while"
+ "do"
+ "end"
+ ] @keyword.repeat)
(repeat_statement
-[
- "repeat"
- "until"
-] @repeat)
+ [
+ "repeat"
+ "until"
+ ] @keyword.repeat)
(if_statement
-[
- "if"
- "elseif"
- "else"
- "then"
- "end"
-] @conditional)
+ [
+ "if"
+ "elseif"
+ "else"
+ "then"
+ "end"
+ ] @keyword.conditional)
(elseif_statement
-[
- "elseif"
- "then"
- "end"
-] @conditional)
+ [
+ "elseif"
+ "then"
+ "end"
+ ] @keyword.conditional)
(else_statement
-[
- "else"
- "end"
-] @conditional)
+ [
+ "else"
+ "end"
+ ] @keyword.conditional)
(for_statement
-[
- "for"
- "do"
- "end"
-] @repeat)
+ [
+ "for"
+ "do"
+ "end"
+ ] @keyword.repeat)
(function_declaration
-[
- "function"
- "end"
-] @keyword.function)
+ [
+ "function"
+ "end"
+ ] @keyword.function)
(function_definition
-[
- "function"
- "end"
-] @keyword.function)
-
-;; Operators
+ [
+ "function"
+ "end"
+ ] @keyword.function)
+; Operators
[
- "and"
- "not"
- "or"
+ "and"
+ "not"
+ "or"
] @keyword.operator
[
@@ -102,8 +100,7 @@
".."
] @operator
-;; Punctuations
-
+; Punctuations
[
";"
":"
@@ -112,19 +109,17 @@
"."
] @punctuation.delimiter
-;; Brackets
-
+; Brackets
[
- "("
- ")"
- "["
- "]"
- "{"
- "}"
+ "("
+ ")"
+ "["
+ "]"
+ "{"
+ "}"
] @punctuation.bracket
-;; Variables
-
+; Variables
(identifier) @variable
((identifier) @constant.builtin
@@ -133,27 +128,28 @@
((identifier) @variable.builtin
(#eq? @variable.builtin "self"))
-((identifier) @namespace.builtin
- (#any-of? @namespace.builtin "_G" "debug" "io" "jit" "math" "os" "package" "string" "table" "utf8"))
+((identifier) @module.builtin
+ (#any-of? @module.builtin "_G" "debug" "io" "jit" "math" "os" "package" "string" "table" "utf8"))
((identifier) @keyword.coroutine
(#eq? @keyword.coroutine "coroutine"))
(variable_list
- attribute: (attribute
- (["<" ">"] @punctuation.bracket
- (identifier) @attribute)))
-
-;; Labels
+ (attribute
+ "<" @punctuation.bracket
+ (identifier) @attribute
+ ">" @punctuation.bracket))
-(label_statement (identifier) @label)
+; Labels
+(label_statement
+ (identifier) @label)
-(goto_statement (identifier) @label)
-
-;; Constants
+(goto_statement
+ (identifier) @label)
+; Constants
((identifier) @constant
- (#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
+ (#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
(vararg_expression) @constant
@@ -164,41 +160,49 @@
(true)
] @boolean
-;; Tables
-
-(field name: (identifier) @field)
+; Tables
+(field
+ name: (identifier) @variable.member)
-(dot_index_expression field: (identifier) @field)
+(dot_index_expression
+ field: (identifier) @variable.member)
(table_constructor
-[
- "{"
- "}"
-] @constructor)
+ [
+ "{"
+ "}"
+ ] @constructor)
-;; Functions
+; Functions
+(parameters
+ (identifier) @variable.parameter)
-(parameters (identifier) @parameter)
-
-(function_declaration
- name: [
- (identifier) @function
- (dot_index_expression
- field: (identifier) @function)
- ])
+(vararg_expression) @variable.parameter.builtin
(function_declaration
- name: (method_index_expression
- method: (identifier) @method))
-
-(assignment_statement
- (variable_list .
- name: [
+ name:
+ [
(identifier) @function
(dot_index_expression
field: (identifier) @function)
])
- (expression_list .
+
+(function_declaration
+ name:
+ (method_index_expression
+ method: (identifier) @function.method))
+
+(assignment_statement
+ (variable_list
+ .
+ name:
+ [
+ (identifier) @function
+ (dot_index_expression
+ field: (identifier) @function)
+ ])
+ (expression_list
+ .
value: (function_definition)))
(table_constructor
@@ -207,18 +211,20 @@
value: (function_definition)))
(function_call
- name: [
- (identifier) @function.call
- (dot_index_expression
- field: (identifier) @function.call)
- (method_index_expression
- method: (identifier) @method.call)
- ])
+ name:
+ [
+ (identifier) @function.call
+ (dot_index_expression
+ field: (identifier) @function.call)
+ (method_index_expression
+ method: (identifier) @function.method.call)
+ ])
(function_call
(identifier) @function.builtin
+ ; format-ignore
(#any-of? @function.builtin
- ;; built-in functions in Lua 5.1
+ ; built-in functions in Lua 5.1
"assert" "collectgarbage" "dofile" "error" "getfenv" "getmetatable" "ipairs"
"load" "loadfile" "loadstring" "module" "next" "pairs" "pcall" "print"
"rawequal" "rawget" "rawlen" "rawset" "require" "select" "setfenv" "setmetatable"
@@ -227,8 +233,7 @@
"__idiv" "__index" "__le" "__len" "__lt" "__metatable" "__mod" "__mul" "__name" "__newindex"
"__pairs" "__pow" "__shl" "__shr" "__sub" "__tostring" "__unm"))
-;; Others
-
+; Others
(comment) @comment @spell
((comment) @comment.documentation
@@ -237,13 +242,34 @@
((comment) @comment.documentation
(#lua-match? @comment.documentation "^[-][-](%s?)@"))
-(hash_bang_line) @preproc
+(hash_bang_line) @keyword.directive
(number) @number
-(string) @string @spell
+(string) @string
(escape_sequence) @string.escape
-;; Error
-(ERROR) @error
+; string.match("123", "%d+")
+(function_call
+ (dot_index_expression
+ field: (identifier) @_method
+ (#any-of? @_method "find" "match" "gmatch" "gsub"))
+ arguments:
+ (arguments
+ .
+ (_)
+ .
+ (string
+ content: (string_content) @string.regexp)))
+
+;("123"):match("%d+")
+(function_call
+ (method_index_expression
+ method: (identifier) @_method
+ (#any-of? @_method "find" "match" "gmatch" "gsub"))
+ arguments:
+ (arguments
+ .
+ (string
+ content: (string_content) @string.regexp)))
diff --git a/runtime/queries/lua/injections.scm b/runtime/queries/lua/injections.scm
index dbfe75ae31..c8a1843c84 100644
--- a/runtime/queries/lua/injections.scm
+++ b/runtime/queries/lua/injections.scm
@@ -1,35 +1,130 @@
((function_call
- name: [
- (identifier) @_cdef_identifier
- (_ _ (identifier) @_cdef_identifier)
- ]
+ name:
+ [
+ (identifier) @_cdef_identifier
+ (_
+ _
+ (identifier) @_cdef_identifier)
+ ]
arguments:
(arguments
- (string content: _ @injection.content)))
+ (string
+ content: _ @injection.content)))
(#set! injection.language "c")
(#eq? @_cdef_identifier "cdef"))
((function_call
name: (_) @_vimcmd_identifier
- arguments: (arguments (string content: _ @injection.content)))
+ arguments:
+ (arguments
+ (string
+ content: _ @injection.content)))
(#set! injection.language "vim")
(#any-of? @_vimcmd_identifier "vim.cmd" "vim.api.nvim_command" "vim.api.nvim_command" "vim.api.nvim_exec2"))
((function_call
name: (_) @_vimcmd_identifier
- arguments: (arguments (string content: _ @injection.content) .))
+ arguments:
+ (arguments
+ (string
+ content: _ @injection.content) .))
(#set! injection.language "query")
(#any-of? @_vimcmd_identifier "vim.treesitter.query.set" "vim.treesitter.query.parse"))
((function_call
name: (_) @_vimcmd_identifier
- arguments: (arguments . (_) . (string content: _ @_method) . (string content: _ @injection.content)))
+ arguments:
+ (arguments
+ .
+ (_)
+ .
+ (string
+ content: _ @_method)
+ .
+ (string
+ content: _ @injection.content)))
(#any-of? @_vimcmd_identifier "vim.rpcrequest" "vim.rpcnotify")
(#eq? @_method "nvim_exec_lua")
(#set! injection.language "lua"))
-;; highlight string as query if starts with `;; query`
-(string content: _ @injection.content
- (#lua-match? @injection.content "^%s*;+%s?query")
- (#set! injection.language "query"))
+; vim.api.nvim_create_autocmd("FileType", { command = "injected here" })
+(function_call
+ name: (_) @_vimcmd_identifier
+ arguments:
+ (arguments
+ .
+ (_)
+ .
+ (table_constructor
+ (field
+ name: (identifier) @_command
+ value:
+ (string
+ content: (_) @injection.content))) .)
+ ; limit so only 2-argument functions gets matched before pred handle
+ (#eq? @_vimcmd_identifier "vim.api.nvim_create_autocmd")
+ (#eq? @_command "command")
+ (#set! injection.language "vim"))
+
+(function_call
+ name: (_) @_user_cmd
+ arguments:
+ (arguments
+ .
+ (_)
+ .
+ (string
+ content: (_) @injection.content)
+ .
+ (_) .)
+ (#eq? @_user_cmd "vim.api.nvim_create_user_command")
+ (#set! injection.language "vim"))
+
+(function_call
+ name: (_) @_user_cmd
+ arguments:
+ (arguments
+ .
+ (_)
+ .
+ (_)
+ .
+ (string
+ content: (_) @injection.content)
+ .
+ (_) .)
+ ; Limiting predicate handling to only functions with 4 arguments
+ (#eq? @_user_cmd "vim.api.nvim_buf_create_user_command")
+ (#set! injection.language "vim"))
+; rhs highlighting for vim.keymap.set/vim.api.nvim_set_keymap/vim.api.nvim_buf_set_keymap
+; (function_call
+; name: (_) @_map
+; arguments:
+; (arguments
+; . (_)
+; . (_)
+; .
+; (string
+; content: (_) @injection.content))
+; (#any-of? @_map "vim.api.nvim_set_keymap" "vim.keymap.set")
+; (#set! injection.language "vim"))
+;
+; (function_call
+; name: (_) @_map
+; arguments:
+; (arguments
+; . (_)
+; . (_)
+; . (_)
+; .
+; (string
+; content: (_) @injection.content)
+; . (_) .)
+; (#eq? @_map "vim.api.nvim_buf_set_keymap")
+; (#set! injection.language "vim"))
+; highlight string as query if starts with `;; query`
+(string
+ content: _ @injection.content
+ (#lua-match? @injection.content "^%s*;+%s?query")
+ (#set! injection.language "query"))
diff --git a/runtime/queries/markdown/folds.scm b/runtime/queries/markdown/folds.scm
index 5900f7ffbe..a682e20e00 100644
--- a/runtime/queries/markdown/folds.scm
+++ b/runtime/queries/markdown/folds.scm
@@ -1,9 +1,7 @@
-(
- [
- (fenced_code_block)
- (indented_code_block)
- (list)
- (section)
- ] @fold
- (#trim! @fold)
-)
+([
+ (fenced_code_block)
+ (indented_code_block)
+ (list)
+ (section)
+] @fold
+ (#trim! @fold))
diff --git a/runtime/queries/markdown/highlights.scm b/runtime/queries/markdown/highlights.scm
index 2cc5546bac..7c26fd710c 100644
--- a/runtime/queries/markdown/highlights.scm
+++ b/runtime/queries/markdown/highlights.scm
@@ -1,40 +1,73 @@
;From MDeiml/tree-sitter-markdown & Helix
-(setext_heading (paragraph) @text.title.1 (setext_h1_underline) @text.title.1.marker)
-(setext_heading (paragraph) @text.title.2 (setext_h2_underline) @text.title.2.marker)
+(setext_heading
+ (paragraph) @markup.heading.1
+ (setext_h1_underline) @markup.heading.1.marker)
-(atx_heading (atx_h1_marker) @text.title.1.marker (inline) @text.title.1)
-(atx_heading (atx_h2_marker) @text.title.2.marker (inline) @text.title.2)
-(atx_heading (atx_h3_marker) @text.title.3.marker (inline) @text.title.3)
-(atx_heading (atx_h4_marker) @text.title.4.marker (inline) @text.title.4)
-(atx_heading (atx_h5_marker) @text.title.5.marker (inline) @text.title.5)
-(atx_heading (atx_h6_marker) @text.title.6.marker (inline) @text.title.6)
+(setext_heading
+ (paragraph) @markup.heading.2
+ (setext_h2_underline) @markup.heading.2.marker)
-(link_title) @text.literal
-(indented_code_block) @text.literal.block
-((fenced_code_block) @text.literal.block (#set! "priority" 90))
+(atx_heading
+ (atx_h1_marker) @markup.heading.1.marker
+ (inline) @markup.heading.1)
+
+(atx_heading
+ (atx_h2_marker) @markup.heading.2.marker
+ (inline) @markup.heading.2)
+
+(atx_heading
+ (atx_h3_marker) @markup.heading.3.marker
+ (inline) @markup.heading.3)
+
+(atx_heading
+ (atx_h4_marker) @markup.heading.4.marker
+ (inline) @markup.heading.4)
+
+(atx_heading
+ (atx_h5_marker) @markup.heading.5.marker
+ (inline) @markup.heading.5)
+
+(atx_heading
+ (atx_h6_marker) @markup.heading.6.marker
+ (inline) @markup.heading.6)
(info_string) @label
-(pipe_table_header (pipe_table_cell) @text.title)
+(pipe_table_header
+ (pipe_table_cell) @markup.heading)
+
+(pipe_table_header
+ "|" @punctuation.special)
+
+(pipe_table_row
+ "|" @punctuation.special)
+
+(pipe_table_delimiter_row
+ "|" @punctuation.special)
-(pipe_table_header "|" @punctuation.special)
-(pipe_table_row "|" @punctuation.special)
-(pipe_table_delimiter_row "|" @punctuation.special)
(pipe_table_delimiter_cell) @punctuation.special
-[
- (fenced_code_block_delimiter)
-] @punctuation.delimiter
+; Code blocks (conceal backticks and language annotation)
+(indented_code_block) @markup.raw.block
-(code_fence_content) @none
+((fenced_code_block) @markup.raw.block
+ (#set! "priority" 90))
-[
- (link_destination)
-] @text.uri
+(fenced_code_block
+ (fenced_code_block_delimiter) @markup.raw.delimiter
+ (#set! conceal ""))
+
+(fenced_code_block
+ (info_string
+ (language) @conceal
+ (#set! conceal "")))
+
+(link_destination) @markup.link.url
[
+ (link_title)
(link_label)
-] @text.reference
+] @markup.link.label
[
(list_marker_plus)
@@ -42,30 +75,43 @@
(list_marker_star)
(list_marker_dot)
(list_marker_parenthesis)
- (thematic_break)
-] @punctuation.special
-
-
-(task_list_marker_unchecked) @text.todo.unchecked
-(task_list_marker_checked) @text.todo.checked
-
-(block_quote) @text.quote
+] @markup.list
+
+; NOTE: The following has been commented out due to issues with spaces in the
+; list marker nodes generated by the parser. If those spaces ever get captured
+; by a different node (e.g. block_continuation) we can safely readd these
+; conceals.
+; ;; Conceal bullet points
+; ([(list_marker_plus) (list_marker_star)]
+; @punctuation.special
+; (#offset! @punctuation.special 0 0 0 -1)
+; (#set! conceal "•"))
+; ([(list_marker_plus) (list_marker_star)]
+; @punctuation.special
+; (#any-of? @punctuation.special "+" "*")
+; (#set! conceal "•"))
+; ((list_marker_minus)
+; @punctuation.special
+; (#offset! @punctuation.special 0 0 0 -1)
+; (#set! conceal "—"))
+; ((list_marker_minus)
+; @punctuation.special
+; (#eq? @punctuation.special "-")
+; (#set! conceal "—"))
+(thematic_break) @punctuation.special
+
+(task_list_marker_unchecked) @markup.list.unchecked
+
+(task_list_marker_checked) @markup.list.checked
+
+((block_quote) @markup.quote
+ (#set! "priority" 90))
[
(block_continuation)
(block_quote_marker)
] @punctuation.special
-[
- (backslash_escape)
-] @string.escape
+(backslash_escape) @string.escape
(inline) @spell
-
-;; Conceal backticks
-(fenced_code_block
- (fenced_code_block_delimiter) @conceal
- (#set! conceal ""))
-(fenced_code_block
- (info_string (language) @conceal
- (#set! conceal "")))
diff --git a/runtime/queries/markdown/injections.scm b/runtime/queries/markdown/injections.scm
index fda7036830..1f33c30b63 100644
--- a/runtime/queries/markdown/injections.scm
+++ b/runtime/queries/markdown/injections.scm
@@ -3,23 +3,23 @@
(language) @injection.language)
(code_fence_content) @injection.content)
-((html_block) @injection.content
- (#set! injection.language "html")
- (#set! injection.combined)
- (#set! injection.include-children))
+((html_block) @injection.content
+ (#set! injection.language "html")
+ (#set! injection.combined)
+ (#set! injection.include-children))
-((minus_metadata) @injection.content
- (#set! injection.language "yaml")
- (#offset! @injection.content 1 0 -1 0)
- (#set! injection.include-children))
+((minus_metadata) @injection.content
+ (#set! injection.language "yaml")
+ (#offset! @injection.content 1 0 -1 0)
+ (#set! injection.include-children))
-((plus_metadata) @injection.content
- (#set! injection.language "toml")
- (#offset! @injection.content 1 0 -1 0)
- (#set! injection.include-children))
+((plus_metadata) @injection.content
+ (#set! injection.language "toml")
+ (#offset! @injection.content 1 0 -1 0)
+ (#set! injection.include-children))
([
(inline)
(pipe_table_cell)
- ] @injection.content
- (#set! injection.language "markdown_inline"))
+] @injection.content
+ (#set! injection.language "markdown_inline"))
diff --git a/runtime/queries/markdown_inline/highlights.scm b/runtime/queries/markdown_inline/highlights.scm
index c75da478af..e9b41c31d5 100644
--- a/runtime/queries/markdown_inline/highlights.scm
+++ b/runtime/queries/markdown_inline/highlights.scm
@@ -1,49 +1,26 @@
-;; From MDeiml/tree-sitter-markdown
-[
- (code_span)
- (link_title)
-] @text.literal @nospell
-
-[
- (emphasis_delimiter)
- (code_span_delimiter)
-] @punctuation.delimiter
-
-(emphasis) @text.emphasis
+; From MDeiml/tree-sitter-markdown
+(code_span) @markup.raw @nospell
-(strong_emphasis) @text.strong
+(emphasis) @markup.italic
-(strikethrough) @text.strike
-
-[
- (link_destination)
- (uri_autolink)
-] @text.uri @nospell
+(strong_emphasis) @markup.strong
-(shortcut_link (link_text) @nospell)
+(strikethrough) @markup.strikethrough
-[
- (link_label)
- (link_text)
- (image_description)
-] @text.reference
+(shortcut_link
+ (link_text) @nospell)
[
(backslash_escape)
(hard_line_break)
] @string.escape
-(image "!" @punctuation.special)
-(image ["[" "]" "(" ")"] @punctuation.bracket)
-(inline_link ["[" "]" "(" ")"] @punctuation.bracket)
-(shortcut_link ["[" "]"] @punctuation.bracket)
-
; Conceal codeblock and text style markers
-([
- (code_span_delimiter)
- (emphasis_delimiter)
-] @conceal
-(#set! conceal ""))
+((code_span_delimiter) @markup.raw.delimiter
+ (#set! conceal ""))
+
+((emphasis_delimiter) @conceal
+ (#set! conceal ""))
; Conceal inline links
(inline_link
@@ -53,7 +30,7 @@
"("
(link_destination)
")"
- ] @conceal
+ ] @markup.link
(#set! conceal ""))
; Conceal image links
@@ -65,7 +42,7 @@
"("
(link_destination)
")"
- ] @conceal
+ ] @markup.link
(#set! conceal ""))
; Conceal full reference links
@@ -74,7 +51,7 @@
"["
"]"
(link_label)
- ] @conceal
+ ] @markup.link
(#set! conceal ""))
; Conceal collapsed reference links
@@ -82,7 +59,7 @@
[
"["
"]"
- ] @conceal
+ ] @markup.link
(#set! conceal ""))
; Conceal shortcut links
@@ -90,13 +67,42 @@
[
"["
"]"
- ] @conceal
+ ] @markup.link
(#set! conceal ""))
-;; Replace common HTML entities.
-((entity_reference) @conceal (#eq? @conceal "&nbsp;") (#set! conceal ""))
-((entity_reference) @conceal (#eq? @conceal "&lt;") (#set! conceal "<"))
-((entity_reference) @conceal (#eq? @conceal "&gt;") (#set! conceal ">"))
-((entity_reference) @conceal (#eq? @conceal "&amp;") (#set! conceal "&"))
-((entity_reference) @conceal (#eq? @conceal "&quot;") (#set! conceal "\""))
-((entity_reference) @conceal (#any-of? @conceal "&ensp;" "&emsp;") (#set! conceal " "))
+[
+ (link_destination)
+ (uri_autolink)
+] @markup.link.url @nospell
+
+[
+ (link_label)
+ (link_text)
+ (link_title)
+ (image_description)
+] @markup.link.label
+
+; Replace common HTML entities.
+((entity_reference) @character.special
+ (#eq? @character.special "&nbsp;")
+ (#set! conceal ""))
+
+((entity_reference) @character.special
+ (#eq? @character.special "&lt;")
+ (#set! conceal "<"))
+
+((entity_reference) @character.special
+ (#eq? @character.special "&gt;")
+ (#set! conceal ">"))
+
+((entity_reference) @character.special
+ (#eq? @character.special "&amp;")
+ (#set! conceal "&"))
+
+((entity_reference) @character.special
+ (#eq? @character.special "&quot;")
+ (#set! conceal "\""))
+
+((entity_reference) @character.special
+ (#any-of? @character.special "&ensp;" "&emsp;")
+ (#set! conceal " "))
diff --git a/runtime/queries/markdown_inline/injections.scm b/runtime/queries/markdown_inline/injections.scm
index f7aa19caff..6448b77c1b 100644
--- a/runtime/queries/markdown_inline/injections.scm
+++ b/runtime/queries/markdown_inline/injections.scm
@@ -1,8 +1,7 @@
((html_tag) @injection.content
- (#set! injection.language "html")
- (#set! injection.combined)
- (#set! injection.include-children))
+ (#set! injection.language "html")
+ (#set! injection.combined))
((latex_block) @injection.content
- (#set! injection.language "latex")
- (#set! injection.include-children))
+ (#set! injection.language "latex")
+ (#set! injection.include-children))
diff --git a/runtime/queries/python/folds.scm b/runtime/queries/python/folds.scm
index 78e1e2c00d..7c547db38f 100644
--- a/runtime/queries/python/folds.scm
+++ b/runtime/queries/python/folds.scm
@@ -1,28 +1,23 @@
[
(function_definition)
(class_definition)
-
(while_statement)
(for_statement)
(if_statement)
(with_statement)
(try_statement)
(match_statement)
-
(import_from_statement)
(parameters)
(argument_list)
-
(parenthesized_expression)
(generator_expression)
(list_comprehension)
(set_comprehension)
(dictionary_comprehension)
-
(tuple)
(list)
(set)
(dictionary)
-
(string)
] @fold
diff --git a/runtime/queries/python/highlights.scm b/runtime/queries/python/highlights.scm
index 04398668e9..764521c7be 100644
--- a/runtime/queries/python/highlights.scm
+++ b/runtime/queries/python/highlights.scm
@@ -1,183 +1,223 @@
-;; From tree-sitter-python licensed under MIT License
+; From tree-sitter-python licensed under MIT License
; Copyright (c) 2016 Max Brunsfeld
-
; Variables
(identifier) @variable
; Reset highlighting in f-string interpolations
(interpolation) @none
-;; Identifier naming conventions
+; Identifier naming conventions
((identifier) @type
- (#lua-match? @type "^[A-Z].*[a-z]"))
+ (#lua-match? @type "^[A-Z].*[a-z]"))
+
((identifier) @constant
- (#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
+ (#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
((identifier) @constant.builtin
- (#lua-match? @constant.builtin "^__[a-zA-Z0-9_]*__$"))
+ (#lua-match? @constant.builtin "^__[a-zA-Z0-9_]*__$"))
((identifier) @constant.builtin
- (#any-of? @constant.builtin
- ;; https://docs.python.org/3/library/constants.html
- "NotImplemented"
- "Ellipsis"
- "quit"
- "exit"
- "copyright"
- "credits"
- "license"))
+ ; format-ignore
+ (#any-of? @constant.builtin
+ ; https://docs.python.org/3/library/constants.html
+ "NotImplemented" "Ellipsis"
+ "quit" "exit" "copyright" "credits" "license"))
"_" @constant.builtin ; match wildcard
((attribute
- attribute: (identifier) @field)
- (#lua-match? @field "^[%l_].*$"))
+ attribute: (identifier) @variable.member)
+ (#lua-match? @variable.member "^[%l_].*$"))
((assignment
left: (identifier) @type.definition
- (type (identifier) @_annotation))
- (#eq? @_annotation "TypeAlias"))
+ (type
+ (identifier) @_annotation))
+ (#eq? @_annotation "TypeAlias"))
((assignment
left: (identifier) @type.definition
- right: (call
- function: (identifier) @_func))
- (#any-of? @_func "TypeVar" "NewType"))
+ right:
+ (call
+ function: (identifier) @_func))
+ (#any-of? @_func "TypeVar" "NewType"))
; Function calls
-
(call
function: (identifier) @function.call)
(call
- function: (attribute
- attribute: (identifier) @method.call))
+ function:
+ (attribute
+ attribute: (identifier) @function.method.call))
((call
- function: (identifier) @constructor)
- (#lua-match? @constructor "^%u"))
+ function: (identifier) @constructor)
+ (#lua-match? @constructor "^%u"))
((call
- function: (attribute
- attribute: (identifier) @constructor))
- (#lua-match? @constructor "^%u"))
-
-;; Decorators
+ function:
+ (attribute
+ attribute: (identifier) @constructor))
+ (#lua-match? @constructor "^%u"))
-((decorator "@" @attribute)
- (#set! "priority" 101))
+; Decorators
+((decorator
+ "@" @attribute)
+ (#set! "priority" 101))
(decorator
(identifier) @attribute)
+
(decorator
(attribute
attribute: (identifier) @attribute))
+
(decorator
- (call (identifier) @attribute))
+ (call
+ (identifier) @attribute))
+
(decorator
- (call (attribute
- attribute: (identifier) @attribute)))
+ (call
+ (attribute
+ attribute: (identifier) @attribute)))
((decorator
(identifier) @attribute.builtin)
- (#any-of? @attribute.builtin "classmethod" "property"))
-
-;; Builtin functions
+ (#any-of? @attribute.builtin "classmethod" "property"))
+; Builtin functions
((call
function: (identifier) @function.builtin)
- (#any-of? @function.builtin
- "abs" "all" "any" "ascii" "bin" "bool" "breakpoint" "bytearray" "bytes" "callable" "chr" "classmethod"
- "compile" "complex" "delattr" "dict" "dir" "divmod" "enumerate" "eval" "exec" "filter" "float" "format"
- "frozenset" "getattr" "globals" "hasattr" "hash" "help" "hex" "id" "input" "int" "isinstance" "issubclass"
- "iter" "len" "list" "locals" "map" "max" "memoryview" "min" "next" "object" "oct" "open" "ord" "pow"
- "print" "property" "range" "repr" "reversed" "round" "set" "setattr" "slice" "sorted" "staticmethod" "str"
- "sum" "super" "tuple" "type" "vars" "zip" "__import__"))
-
-;; Function definitions
+ (#any-of? @function.builtin "abs" "all" "any" "ascii" "bin" "bool" "breakpoint" "bytearray" "bytes" "callable" "chr" "classmethod" "compile" "complex" "delattr" "dict" "dir" "divmod" "enumerate" "eval" "exec" "filter" "float" "format" "frozenset" "getattr" "globals" "hasattr" "hash" "help" "hex" "id" "input" "int" "isinstance" "issubclass" "iter" "len" "list" "locals" "map" "max" "memoryview" "min" "next" "object" "oct" "open" "ord" "pow" "print" "property" "range" "repr" "reversed" "round" "set" "setattr" "slice" "sorted" "staticmethod" "str" "sum" "super" "tuple" "type" "vars" "zip" "__import__"))
+; Function definitions
(function_definition
name: (identifier) @function)
-(type (identifier) @type)
+(type
+ (identifier) @type)
+
(type
(subscript
(identifier) @type)) ; type subscript: Tuple[int]
((call
function: (identifier) @_isinstance
- arguments: (argument_list
- (_)
- (identifier) @type))
- (#eq? @_isinstance "isinstance"))
+ arguments:
+ (argument_list
+ (_)
+ (identifier) @type))
+ (#eq? @_isinstance "isinstance"))
-;; Normal parameters
+; Normal parameters
(parameters
- (identifier) @parameter)
-;; Lambda parameters
+ (identifier) @variable.parameter)
+
+; Lambda parameters
(lambda_parameters
- (identifier) @parameter)
+ (identifier) @variable.parameter)
+
(lambda_parameters
(tuple_pattern
- (identifier) @parameter))
+ (identifier) @variable.parameter))
+
; Default parameters
(keyword_argument
- name: (identifier) @parameter)
+ name: (identifier) @variable.parameter)
+
; Naming parameters on call-site
(default_parameter
- name: (identifier) @parameter)
+ name: (identifier) @variable.parameter)
+
(typed_parameter
- (identifier) @parameter)
+ (identifier) @variable.parameter)
+
(typed_default_parameter
- (identifier) @parameter)
+ name: (identifier) @variable.parameter)
+
; Variadic parameters *args, **kwargs
(parameters
(list_splat_pattern ; *args
- (identifier) @parameter))
+ (identifier) @variable.parameter))
+
(parameters
(dictionary_splat_pattern ; **kwargs
- (identifier) @parameter))
+ (identifier) @variable.parameter))
+; Typed variadic parameters
+(parameters
+ (typed_parameter
+ (list_splat_pattern ; *args: type
+ (identifier) @variable.parameter)))
-;; Literals
+(parameters
+ (typed_parameter
+ (dictionary_splat_pattern ; *kwargs: type
+ (identifier) @variable.parameter)))
+
+; Lambda parameters
+(lambda_parameters
+ (list_splat_pattern
+ (identifier) @variable.parameter))
+(lambda_parameters
+ (dictionary_splat_pattern
+ (identifier) @variable.parameter))
+
+; Literals
(none) @constant.builtin
-[(true) (false)] @boolean
+
+[
+ (true)
+ (false)
+] @boolean
+
((identifier) @variable.builtin
- (#eq? @variable.builtin "self"))
+ (#eq? @variable.builtin "self"))
+
((identifier) @variable.builtin
- (#eq? @variable.builtin "cls"))
+ (#eq? @variable.builtin "cls"))
(integer) @number
-(float) @float
+
+(float) @number.float
(comment) @comment @spell
-((module . (comment) @preproc)
- (#lua-match? @preproc "^#!/"))
+((module
+ .
+ (comment) @keyword.directive)
+ (#lua-match? @keyword.directive "^#!/"))
(string) @string
+
[
(escape_sequence)
(escape_interpolation)
] @string.escape
; doc-strings
-
-(module . (expression_statement (string) @string.documentation @spell))
+(module
+ .
+ (expression_statement
+ (string) @string.documentation @spell))
(class_definition
body:
(block
- . (expression_statement (string) @string.documentation @spell)))
+ .
+ (expression_statement
+ (string) @string.documentation @spell)))
(function_definition
body:
(block
- . (expression_statement (string) @string.documentation @spell)))
+ .
+ (expression_statement
+ (string) @string.documentation @spell)))
; Tokens
-
[
"-"
"-="
@@ -227,7 +267,6 @@
"or"
"is not"
"not in"
-
"del"
] @keyword.operator
@@ -258,19 +297,36 @@
"return"
"yield"
] @keyword.return
-(yield "from" @keyword.return)
+
+(yield
+ "from" @keyword.return)
(future_import_statement
- "from" @include
+ "from" @keyword.import
"__future__" @constant.builtin)
-(import_from_statement "from" @include)
-"import" @include
-(aliased_import "as" @include)
+(import_from_statement
+ "from" @keyword.import)
+
+"import" @keyword.import
-["if" "elif" "else" "match" "case"] @conditional
+(aliased_import
+ "as" @keyword.import)
-["for" "while" "break" "continue"] @repeat
+[
+ "if"
+ "elif"
+ "else"
+ "match"
+ "case"
+] @keyword.conditional
+
+[
+ "for"
+ "while"
+ "break"
+ "continue"
+] @keyword.repeat
[
"try"
@@ -278,15 +334,23 @@
"except*"
"raise"
"finally"
-] @exception
+] @keyword.exception
-(raise_statement "from" @exception)
+(raise_statement
+ "from" @keyword.exception)
(try_statement
(else_clause
- "else" @exception))
+ "else" @keyword.exception))
-["(" ")" "[" "]" "{" "}"] @punctuation.bracket
+[
+ "("
+ ")"
+ "["
+ "]"
+ "{"
+ "}"
+] @punctuation.bracket
(interpolation
"{" @punctuation.special
@@ -294,58 +358,80 @@
(type_conversion) @function.macro
-["," "." ":" ";" (ellipsis)] @punctuation.delimiter
-
-;; Class definitions
-
-(class_definition name: (identifier) @type)
+[
+ ","
+ "."
+ ":"
+ ";"
+ (ellipsis)
+] @punctuation.delimiter
+
+; Class definitions
+(class_definition
+ name: (identifier) @type)
(class_definition
- body: (block
- (function_definition
- name: (identifier) @method)))
+ body:
+ (block
+ (function_definition
+ name: (identifier) @function.method)))
(class_definition
- superclasses: (argument_list
- (identifier) @type))
+ superclasses:
+ (argument_list
+ (identifier) @type))
((class_definition
- body: (block
- (expression_statement
- (assignment
- left: (identifier) @field))))
- (#lua-match? @field "^%l.*$"))
+ body:
+ (block
+ (expression_statement
+ (assignment
+ left: (identifier) @variable.member))))
+ (#lua-match? @variable.member "^%l.*$"))
+
((class_definition
- body: (block
- (expression_statement
- (assignment
- left: (_
- (identifier) @field)))))
- (#lua-match? @field "^%l.*$"))
+ body:
+ (block
+ (expression_statement
+ (assignment
+ left:
+ (_
+ (identifier) @variable.member)))))
+ (#lua-match? @variable.member "^%l.*$"))
((class_definition
(block
(function_definition
name: (identifier) @constructor)))
- (#any-of? @constructor "__new__" "__init__"))
+ (#any-of? @constructor "__new__" "__init__"))
((identifier) @type.builtin
- (#any-of? @type.builtin
- ;; https://docs.python.org/3/library/exceptions.html
- "BaseException" "Exception" "ArithmeticError" "BufferError" "LookupError" "AssertionError" "AttributeError"
- "EOFError" "FloatingPointError" "GeneratorExit" "ImportError" "ModuleNotFoundError" "IndexError" "KeyError"
- "KeyboardInterrupt" "MemoryError" "NameError" "NotImplementedError" "OSError" "OverflowError" "RecursionError"
- "ReferenceError" "RuntimeError" "StopIteration" "StopAsyncIteration" "SyntaxError" "IndentationError" "TabError"
- "SystemError" "SystemExit" "TypeError" "UnboundLocalError" "UnicodeError" "UnicodeEncodeError" "UnicodeDecodeError"
- "UnicodeTranslateError" "ValueError" "ZeroDivisionError" "EnvironmentError" "IOError" "WindowsError"
- "BlockingIOError" "ChildProcessError" "ConnectionError" "BrokenPipeError" "ConnectionAbortedError"
- "ConnectionRefusedError" "ConnectionResetError" "FileExistsError" "FileNotFoundError" "InterruptedError"
- "IsADirectoryError" "NotADirectoryError" "PermissionError" "ProcessLookupError" "TimeoutError" "Warning"
- "UserWarning" "DeprecationWarning" "PendingDeprecationWarning" "SyntaxWarning" "RuntimeWarning"
- "FutureWarning" "ImportWarning" "UnicodeWarning" "BytesWarning" "ResourceWarning"
- ;; https://docs.python.org/3/library/stdtypes.html
- "bool" "int" "float" "complex" "list" "tuple" "range" "str"
- "bytes" "bytearray" "memoryview" "set" "frozenset" "dict" "type" "object"))
-
-;; Error
-(ERROR) @error
+ ; format-ignore
+ (#any-of? @type.builtin
+ ; https://docs.python.org/3/library/exceptions.html
+ "BaseException" "Exception" "ArithmeticError" "BufferError" "LookupError" "AssertionError" "AttributeError"
+ "EOFError" "FloatingPointError" "GeneratorExit" "ImportError" "ModuleNotFoundError" "IndexError" "KeyError"
+ "KeyboardInterrupt" "MemoryError" "NameError" "NotImplementedError" "OSError" "OverflowError" "RecursionError"
+ "ReferenceError" "RuntimeError" "StopIteration" "StopAsyncIteration" "SyntaxError" "IndentationError" "TabError"
+ "SystemError" "SystemExit" "TypeError" "UnboundLocalError" "UnicodeError" "UnicodeEncodeError" "UnicodeDecodeError"
+ "UnicodeTranslateError" "ValueError" "ZeroDivisionError" "EnvironmentError" "IOError" "WindowsError"
+ "BlockingIOError" "ChildProcessError" "ConnectionError" "BrokenPipeError" "ConnectionAbortedError"
+ "ConnectionRefusedError" "ConnectionResetError" "FileExistsError" "FileNotFoundError" "InterruptedError"
+ "IsADirectoryError" "NotADirectoryError" "PermissionError" "ProcessLookupError" "TimeoutError" "Warning"
+ "UserWarning" "DeprecationWarning" "PendingDeprecationWarning" "SyntaxWarning" "RuntimeWarning"
+ "FutureWarning" "ImportWarning" "UnicodeWarning" "BytesWarning" "ResourceWarning"
+ ; https://docs.python.org/3/library/stdtypes.html
+ "bool" "int" "float" "complex" "list" "tuple" "range" "str"
+ "bytes" "bytearray" "memoryview" "set" "frozenset" "dict" "type" "object"))
+
+; Regex from the `re` module
+(call
+ function:
+ (attribute
+ object: (identifier) @_re)
+ arguments:
+ (argument_list
+ .
+ (string
+ (string_content) @string.regexp))
+ (#eq? @_re "re"))
diff --git a/runtime/queries/query/highlights.scm b/runtime/queries/query/highlights.scm
index f2d2ef6c7f..cdedb23e29 100644
--- a/runtime/queries/query/highlights.scm
+++ b/runtime/queries/query/highlights.scm
@@ -1,14 +1,30 @@
(string) @string
+
(escape_sequence) @string.escape
-(capture (identifier) @type)
-(anonymous_node (identifier) @string)
-(predicate name: (identifier) @function)
-(named_node name: (identifier) @variable)
-(field_definition name: (identifier) @property)
-(negated_field "!" @operator (identifier) @property)
+
+(capture
+ (identifier) @type)
+
+(anonymous_node
+ (identifier) @string)
+
+(predicate
+ name: (identifier) @function.call)
+
+(named_node
+ name: (identifier) @variable)
+
+(field_definition
+ name: (identifier) @property)
+
+(negated_field
+ "!" @operator
+ (identifier) @property)
+
(comment) @comment @spell
(quantifier) @operator
+
(predicate_type) @punctuation.special
"." @operator
@@ -21,14 +37,51 @@
] @punctuation.bracket
":" @punctuation.delimiter
-["@" "#"] @punctuation.special
+
+[
+ "@"
+ "#"
+] @punctuation.special
+
"_" @constant
-((parameters (identifier) @number)
- (#match? @number "^[-+]?[0-9]+(.[0-9]+)?$"))
+((parameters
+ (identifier) @number)
+ (#match? @number "^[-+]?[0-9]+(.[0-9]+)?$"))
+
+((program
+ .
+ (comment)*
+ .
+ (comment) @keyword.import)
+ (#lua-match? @keyword.import "^;+ *inherits *:"))
+
+((program
+ .
+ (comment)*
+ .
+ (comment) @keyword.directive)
+ (#lua-match? @keyword.directive "^;+ *extends *$"))
+
+((comment) @keyword.directive
+ (#lua-match? @keyword.directive "^;+%s*format%-ignore%s*$"))
-((program . (comment)* . (comment) @include)
- (#lua-match? @include "^;+ *inherits *:"))
+((predicate
+ name: (identifier) @_name
+ parameters:
+ (parameters
+ (string
+ "\"" @string
+ "\"" @string) @string.regexp))
+ (#any-of? @_name "match" "not-match" "vim-match" "not-vim-match" "lua-match" "not-lua-match"))
-((program . (comment)* . (comment) @preproc)
- (#lua-match? @preproc "^;+ *extends"))
+((predicate
+ name: (identifier) @_name
+ parameters:
+ (parameters
+ (string
+ "\"" @string
+ "\"" @string) @string.regexp
+ .
+ (string) .))
+ (#any-of? @_name "gsub" "not-gsub"))
diff --git a/runtime/queries/vim/folds.scm b/runtime/queries/vim/folds.scm
index 4c99735836..0a1fb695f3 100644
--- a/runtime/queries/vim/folds.scm
+++ b/runtime/queries/vim/folds.scm
@@ -1,4 +1,4 @@
[
- (if_statement)
- (function_definition)
+ (if_statement)
+ (function_definition)
] @fold
diff --git a/runtime/queries/vim/highlights.scm b/runtime/queries/vim/highlights.scm
index 09188ddb68..54832ffa56 100644
--- a/runtime/queries/vim/highlights.scm
+++ b/runtime/queries/vim/highlights.scm
@@ -1,15 +1,15 @@
(identifier) @variable
-((identifier) @constant
- (#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
-;; Keywords
+((identifier) @constant
+ (#lua-match? @constant "^[A-Z][A-Z_0-9]*$"))
+; Keywords
[
"if"
"else"
"elseif"
"endif"
-] @conditional
+] @keyword.conditional
[
"try"
@@ -17,7 +17,7 @@
"finally"
"endtry"
"throw"
-] @exception
+] @keyword.exception
[
"for"
@@ -27,31 +27,50 @@
"endwhile"
"break"
"continue"
-] @repeat
+] @keyword.repeat
[
"function"
"endfunction"
] @keyword.function
-;; Function related
-(function_declaration name: (_) @function)
-(call_expression function: (identifier) @function.call)
-(call_expression function: (scoped_identifier (identifier) @function.call))
-(parameters (identifier) @parameter)
-(default_parameter (identifier) @parameter)
+; Function related
+(function_declaration
+ name: (_) @function)
+
+(call_expression
+ function: (identifier) @function.call)
+
+(call_expression
+ function:
+ (scoped_identifier
+ (identifier) @function.call))
-[ (bang) (spread) ] @punctuation.special
+(parameters
+ (identifier) @variable.parameter)
+
+(default_parameter
+ (identifier) @variable.parameter)
+
+[
+ (bang)
+ (spread)
+] @punctuation.special
+
+[
+ (no_option)
+ (inv_option)
+ (default_option)
+ (option_name)
+] @variable.builtin
-[ (no_option) (inv_option) (default_option) (option_name) ] @variable.builtin
[
(scope)
"a:"
"$"
-] @namespace
-
-;; Commands and user defined commands
+] @module
+; Commands and user defined commands
[
"let"
"unlet"
@@ -83,6 +102,7 @@
"delcommand"
"comclear"
"colorscheme"
+ "scriptencoding"
"startinsert"
"stopinsert"
"global"
@@ -106,41 +126,48 @@
"visual"
"view"
"eval"
+ "sign"
] @keyword
-(map_statement cmd: _ @keyword)
+
+(map_statement
+ cmd: _ @keyword)
+
(command_name) @function.macro
-;; Filetype command
-
-(filetype_statement [
- "detect"
- "plugin"
- "indent"
- "on"
- "off"
-] @keyword)
-
-;; Syntax command
-
-(syntax_statement (keyword) @string)
-(syntax_statement [
- "enable"
- "on"
- "off"
- "reset"
- "case"
- "spell"
- "foldlevel"
- "iskeyword"
- "keyword"
- "match"
- "cluster"
- "region"
- "clear"
- "include"
-] @keyword)
-
-(syntax_argument name: _ @keyword)
+; Filetype command
+(filetype_statement
+ [
+ "detect"
+ "plugin"
+ "indent"
+ "on"
+ "off"
+ ] @keyword)
+
+; Syntax command
+(syntax_statement
+ (keyword) @string)
+
+(syntax_statement
+ [
+ "enable"
+ "on"
+ "off"
+ "reset"
+ "case"
+ "spell"
+ "foldlevel"
+ "iskeyword"
+ "keyword"
+ "match"
+ "cluster"
+ "region"
+ "clear"
+ "include"
+ ] @keyword)
+
+(syntax_argument
+ name: _ @keyword)
[
"<buffer>"
@@ -151,70 +178,96 @@
"<unique>"
] @constant.builtin
-(augroup_name) @namespace
+(augroup_name) @module
(au_event) @constant
-(normal_statement (commands) @constant)
-;; Highlight command
+(normal_statement
+ (commands) @constant)
+; Highlight command
(hl_attribute
key: _ @property
val: _ @constant)
(hl_group) @type
-(highlight_statement [
- "default"
- "link"
- "clear"
-] @keyword)
-
-;; Command command
+(highlight_statement
+ [
+ "default"
+ "link"
+ "clear"
+ ] @keyword)
+; Command command
(command) @string
(command_attribute
name: _ @property
- val: (behavior
- name: _ @constant
- val: (identifier)? @function)?)
+ val:
+ (behavior
+ name: _ @constant
+ val: (identifier)? @function)?)
-;; Edit command
+; Edit command
(plus_plus_opt
val: _? @constant) @property
-(plus_cmd "+" @property) @property
-
-;; Runtime command
-(runtime_statement (where) @keyword.operator)
+(plus_cmd
+ "+" @property) @property
-;; Colorscheme command
+; Runtime command
+(runtime_statement
+ (where) @keyword.operator)
-(colorscheme_statement (name) @string)
+; Colorscheme command
+(colorscheme_statement
+ (name) @string)
-;; Literals
+; Scriptencoding command
+(scriptencoding_statement
+ (encoding) @string.special)
+; Literals
(string_literal) @string
+
(integer_literal) @number
-(float_literal) @float
+
+(float_literal) @number.float
+
(comment) @comment @spell
+
(line_continuation_comment) @comment @spell
+
(pattern) @string.special
-(pattern_multi) @string.regex
-(filename) @string
-(heredoc (body) @string)
-(heredoc (parameter) @keyword)
-[ (marker_definition) (endmarker) ] @label
-(literal_dictionary (literal_key) @label)
-((scoped_identifier
- (scope) @_scope . (identifier) @boolean)
- (#eq? @_scope "v:")
- (#any-of? @boolean "true" "false"))
-;; Operators
+(pattern_multi) @string.regexp
+
+(filename) @string.special.path
+
+(heredoc
+ (body) @string)
+
+(heredoc
+ (parameter) @keyword)
[
+ (marker_definition)
+ (endmarker)
+] @label
+
+(literal_dictionary
+ (literal_key) @property)
+
+((scoped_identifier
+ (scope) @_scope
+ .
+ (identifier) @boolean)
+ (#eq? @_scope "v:")
+ (#any-of? @boolean "true" "false"))
+
+; Operators
+[
"||"
"&&"
"&"
@@ -248,12 +301,13 @@
] @operator
; Some characters have different meanings based on the context
-(unary_operation "!" @operator)
-(binary_operation "." @operator)
-
+(unary_operation
+ "!" @operator)
-;; Punctuation
+(binary_operation
+ "." @operator)
+; Punctuation
[
"("
")"
@@ -264,27 +318,31 @@
"#{"
] @punctuation.bracket
-(field_expression "." @punctuation.delimiter)
+(field_expression
+ "." @punctuation.delimiter)
[
","
":"
] @punctuation.delimiter
-(ternary_expression ["?" ":"] @conditional.ternary)
+(ternary_expression
+ [
+ "?"
+ ":"
+ ] @keyword.conditional.ternary)
; Options
((set_value) @number
- (#lua-match? @number "^[%d]+(%.[%d]+)?$"))
+ (#lua-match? @number "^[%d]+(%.[%d]+)?$"))
+
+(inv_option
+ "!" @operator)
-(inv_option "!" @operator)
-(set_item "?" @operator)
+(set_item
+ "?" @operator)
((set_item
- option: (option_name) @_option
- value: (set_value) @function)
- (#any-of? @_option
- "tagfunc" "tfu"
- "completefunc" "cfu"
- "omnifunc" "ofu"
- "operatorfunc" "opfunc"))
+ option: (option_name) @_option
+ value: (set_value) @function)
+ (#any-of? @_option "tagfunc" "tfu" "completefunc" "cfu" "omnifunc" "ofu" "operatorfunc" "opfunc"))
diff --git a/runtime/queries/vim/injections.scm b/runtime/queries/vim/injections.scm
index 50f0190112..16ec57ca99 100644
--- a/runtime/queries/vim/injections.scm
+++ b/runtime/queries/vim/injections.scm
@@ -1,48 +1,32 @@
-((lua_statement (script (body) @injection.content))
- (#set! injection.language "lua"))
+(lua_statement
+ (script
+ (body) @injection.content
+ (#set! injection.language "lua")))
-((lua_statement (chunk) @injection.content)
- (#set! injection.language "lua"))
+(lua_statement
+ (chunk) @injection.content
+ (#set! injection.language "lua"))
-((ruby_statement (script (body) @injection.content))
- (#set! injection.language "ruby"))
+(ruby_statement
+ (script
+ (body) @injection.content
+ (#set! injection.language "ruby")))
-((ruby_statement (chunk) @injection.content)
- (#set! injection.language "ruby"))
+(ruby_statement
+ (chunk) @injection.content
+ (#set! injection.language "ruby"))
-((python_statement (script (body) @injection.content))
- (#set! injection.language "python"))
+(python_statement
+ (script
+ (body) @injection.content
+ (#set! injection.language "python")))
-((python_statement (chunk) @injection.content)
- (#set! injection.language "python"))
-
-;; If we support perl at some point...
-;; ((perl_statement (script (body) @injection.content))
-;; (#set! injection.language "perl"))
-;; ((perl_statement (chunk) @injection.content)
-;; (#set! injection.language "perl"))
-
-((autocmd_statement (pattern) @injection.content)
- (#set! injection.language "regex"))
+(python_statement
+ (chunk) @injection.content
+ (#set! injection.language "python"))
((set_item
- option: (option_name) @_option
- value: (set_value) @injection.content)
- (#any-of? @_option
- "includeexpr" "inex"
- "printexpr" "pexpr"
- "formatexpr" "fex"
- "indentexpr" "inde"
- "foldtext" "fdt"
- "foldexpr" "fde"
- "diffexpr" "dex"
- "patchexpr" "pex"
- "charconvert" "ccv")
+ option: (option_name) @_option
+ value: (set_value) @injection.content)
+ (#any-of? @_option "includeexpr" "inex" "printexpr" "pexpr" "formatexpr" "fex" "indentexpr" "inde" "foldtext" "fdt" "foldexpr" "fde" "diffexpr" "dex" "patchexpr" "pex" "charconvert" "ccv")
(#set! injection.language "vim"))
-
-
-; ((comment) @injection.content
-; (#set! injection.language "comment"))
-
-; ((line_continuation_comment) @injection.content
-; (#set! injection.language "comment"))
diff --git a/runtime/queries/vimdoc/highlights.scm b/runtime/queries/vimdoc/highlights.scm
index e0dce49b2a..294fa94f10 100644
--- a/runtime/queries/vimdoc/highlights.scm
+++ b/runtime/queries/vimdoc/highlights.scm
@@ -1,25 +1,58 @@
-(h1) @text.title.1
-(h2) @text.title.2
-(h3) @text.title.3
-(column_heading) @text.title.4
+(h1) @markup.heading.1
+
+(h2) @markup.heading.2
+
+(h3) @markup.heading.3
+
+(column_heading) @markup.heading.4
+
(column_heading
- "~" @conceal (#set! conceal ""))
+ "~" @markup.heading.4.marker
+ (#set! conceal ""))
+
(tag
- "*" @conceal (#set! conceal "")
- text: (_) @label)
+ "*" @markup.heading.5.marker
+ (#set! conceal "")
+ text: (_) @label)
+
(taglink
- "|" @conceal (#set! conceal "")
- text: (_) @text.reference)
+ "|" @markup.link
+ (#set! conceal "")
+ text: (_) @markup.link)
+
(optionlink
- text: (_) @text.reference)
+ text: (_) @markup.link)
+
(codespan
- "`" @conceal (#set! conceal "")
- text: (_) @text.literal)
-(codeblock) @text.literal
+ "`" @markup.raw.delimiter
+ (#set! conceal "")
+ text: (_) @markup.raw)
+
+((codeblock) @markup.raw.block
+ (#set! "priority" 90))
+
(codeblock
- [">" (language)] @conceal (#set! conceal ""))
+ [
+ ">"
+ (language)
+ ] @markup.raw.delimiter
+ (#set! conceal ""))
+
(block
- "<" @conceal (#set! conceal ""))
-(argument) @parameter
+ "<" @markup.raw.delimiter
+ (#set! conceal ""))
+
+(argument) @variable.parameter
+
(keycode) @string.special
-(url) @text.uri
+
+(url) @string.special.url
+
+((note) @comment.note
+ (#any-of? @comment.note "Note:" "NOTE:" "Notes:"))
+
+((note) @comment.warning
+ (#any-of? @comment.warning "Warning:" "WARNING:"))
+
+((note) @comment.error
+ (#any-of? @comment.error "Deprecated:" "DEPRECATED:"))
diff --git a/runtime/queries/vimdoc/injections.scm b/runtime/queries/vimdoc/injections.scm
index 260a05d863..3b8fbf0f36 100644
--- a/runtime/queries/vimdoc/injections.scm
+++ b/runtime/queries/vimdoc/injections.scm
@@ -1,4 +1,4 @@
((codeblock
(language) @injection.language
(code) @injection.content)
- (#set! injection.include-children))
+ (#set! injection.include-children))
diff --git a/runtime/synmenu.vim b/runtime/synmenu.vim
index 43aae6f88b..edc6eabd1d 100644
--- a/runtime/synmenu.vim
+++ b/runtime/synmenu.vim
@@ -1,8 +1,8 @@
" Vim support file to define the syntax selection menu
" This file is normally sourced from menu.vim.
"
-" Maintainer: The Vim Project <https://github.com/vim/vim>
-" Last Change: 2023 Aug 10
+" Maintainer: The Vim Project <https://github.com/vim/vim>
+" Last Change: 2024 Jan 04
" Former Maintainer: Bram Moolenaar <Bram@vim.org>
" Define the SetSyn function, used for the Syntax menu entries.
@@ -16,6 +16,9 @@ fun! SetSyn(name)
let use_fvwm_2 = 1
let use_fvwm_1 = 0
let name = "fvwm"
+ elseif a:name =~ '^modula2:\w\+$'
+ let [name, dialect] = split(a:name, ":")
+ call modula2#SetDialect(dialect)
else
let name = a:name
endif
@@ -364,25 +367,27 @@ an 50.70.340 &Syntax.M.MMIX :cal SetSyn("mmix")<CR>
an 50.70.350 &Syntax.M.Modconf :cal SetSyn("modconf")<CR>
an 50.70.360 &Syntax.M.Model :cal SetSyn("model")<CR>
an 50.70.370 &Syntax.M.Modsim\ III :cal SetSyn("modsim3")<CR>
-an 50.70.380 &Syntax.M.Modula\ 2 :cal SetSyn("modula2")<CR>
-an 50.70.390 &Syntax.M.Modula\ 3 :cal SetSyn("modula3")<CR>
-an 50.70.400 &Syntax.M.Monk :cal SetSyn("monk")<CR>
-an 50.70.410 &Syntax.M.Motorola\ S-Record :cal SetSyn("srec")<CR>
-an 50.70.420 &Syntax.M.Mplayer\ config :cal SetSyn("mplayerconf")<CR>
-an 50.70.430 &Syntax.M.MOO :cal SetSyn("moo")<CR>
-an 50.70.440 &Syntax.M.Mrxvtrc :cal SetSyn("mrxvtrc")<CR>
-an 50.70.450 &Syntax.M.MS-DOS/Windows.4DOS\ \.bat\ file :cal SetSyn("btm")<CR>
-an 50.70.460 &Syntax.M.MS-DOS/Windows.\.bat\/\.cmd\ file :cal SetSyn("dosbatch")<CR>
-an 50.70.470 &Syntax.M.MS-DOS/Windows.\.ini\ file :cal SetSyn("dosini")<CR>
-an 50.70.480 &Syntax.M.MS-DOS/Windows.Message\ text :cal SetSyn("msmessages")<CR>
-an 50.70.490 &Syntax.M.MS-DOS/Windows.Module\ Definition :cal SetSyn("def")<CR>
-an 50.70.500 &Syntax.M.MS-DOS/Windows.Registry :cal SetSyn("registry")<CR>
-an 50.70.510 &Syntax.M.MS-DOS/Windows.Resource\ file :cal SetSyn("rc")<CR>
-an 50.70.520 &Syntax.M.Msql :cal SetSyn("msql")<CR>
-an 50.70.530 &Syntax.M.MuPAD :cal SetSyn("mupad")<CR>
-an 50.70.540 &Syntax.M.Murphi :cal SetSyn("murphi")<CR>
-an 50.70.550 &Syntax.M.MUSHcode :cal SetSyn("mush")<CR>
-an 50.70.560 &Syntax.M.Muttrc :cal SetSyn("muttrc")<CR>
+an 50.70.380 &Syntax.M.Modula-2.R10\ (2010) :cal SetSyn("modula2:r10")<CR>
+an 50.70.390 &Syntax.M.Modula-2.ISO\ (1994) :cal SetSyn("modula2:iso")<CR>
+an 50.70.400 &Syntax.M.Modula-2.PIM\ (1985) :cal SetSyn("modula2:pim")<CR>
+an 50.70.410 &Syntax.M.Modula-3 :cal SetSyn("modula3")<CR>
+an 50.70.420 &Syntax.M.Monk :cal SetSyn("monk")<CR>
+an 50.70.430 &Syntax.M.Motorola\ S-Record :cal SetSyn("srec")<CR>
+an 50.70.440 &Syntax.M.Mplayer\ config :cal SetSyn("mplayerconf")<CR>
+an 50.70.450 &Syntax.M.MOO :cal SetSyn("moo")<CR>
+an 50.70.460 &Syntax.M.Mrxvtrc :cal SetSyn("mrxvtrc")<CR>
+an 50.70.470 &Syntax.M.MS-DOS/Windows.4DOS\ \.bat\ file :cal SetSyn("btm")<CR>
+an 50.70.480 &Syntax.M.MS-DOS/Windows.\.bat\/\.cmd\ file :cal SetSyn("dosbatch")<CR>
+an 50.70.490 &Syntax.M.MS-DOS/Windows.\.ini\ file :cal SetSyn("dosini")<CR>
+an 50.70.500 &Syntax.M.MS-DOS/Windows.Message\ text :cal SetSyn("msmessages")<CR>
+an 50.70.510 &Syntax.M.MS-DOS/Windows.Module\ Definition :cal SetSyn("def")<CR>
+an 50.70.520 &Syntax.M.MS-DOS/Windows.Registry :cal SetSyn("registry")<CR>
+an 50.70.530 &Syntax.M.MS-DOS/Windows.Resource\ file :cal SetSyn("rc")<CR>
+an 50.70.540 &Syntax.M.Msql :cal SetSyn("msql")<CR>
+an 50.70.550 &Syntax.M.MuPAD :cal SetSyn("mupad")<CR>
+an 50.70.560 &Syntax.M.Murphi :cal SetSyn("murphi")<CR>
+an 50.70.570 &Syntax.M.MUSHcode :cal SetSyn("mush")<CR>
+an 50.70.580 &Syntax.M.Muttrc :cal SetSyn("muttrc")<CR>
an 50.80.100 &Syntax.NO.N1QL :cal SetSyn("n1ql")<CR>
an 50.80.110 &Syntax.NO.Nanorc :cal SetSyn("nanorc")<CR>
an 50.80.120 &Syntax.NO.Nastran\ input/DMAP :cal SetSyn("nastran")<CR>
@@ -650,7 +655,7 @@ an 50.170.390 &Syntax.WXYZ.XFree86\ Config :cal SetSyn("xf86conf")<CR>
an 50.170.410 &Syntax.WXYZ.YAML :cal SetSyn("yaml")<CR>
an 50.170.420 &Syntax.WXYZ.Yacc :cal SetSyn("yacc")<CR>
an 50.170.440 &Syntax.WXYZ.Zimbu :cal SetSyn("zimbu")<CR>
-an 50.170.440 &Syntax.WXYZ.Zserio:cal SetSyn("zserio")<CR>
+an 50.170.450 &Syntax.WXYZ.Zserio :cal SetSyn("zserio")<CR>
" The End Of The Syntax Menu
diff --git a/runtime/syntax/2html.vim b/runtime/syntax/2html.vim
deleted file mode 100644
index 5fbdad90f3..0000000000
--- a/runtime/syntax/2html.vim
+++ /dev/null
@@ -1,2068 +0,0 @@
-" Vim syntax support file
-" Maintainer: Ben Fritz <fritzophrenic@gmail.com>
-" Last Change: 2023 Sep 05
-"
-" Additional contributors:
-"
-" Original by Bram Moolenaar <Bram@vim.org>
-" Modified by David Ne\v{c}as (Yeti) <yeti@physics.muni.cz>
-" XHTML support by Panagiotis Issaris <takis@lumumba.luc.ac.be>
-" Made w3 compliant by Edd Barrett <vext01@gmail.com>
-" Added html_font. Edd Barrett <vext01@gmail.com>
-" Progress bar based off code from "progressbar widget" plugin by
-" Andreas Politz, heavily modified:
-" http://www.vim.org/scripts/script.php?script_id=2006
-"
-" See Mercurial change logs for more!
-
-" Transform a file into HTML, using the current syntax highlighting.
-
-" this file uses line continuations
-let s:cpo_sav = &cpo
-let s:ls = &ls
-let s:ei_sav = &eventignore
-set cpo&vim
-
-" HTML filetype can take a while to load/highlight if the destination file
-" already exists.
-set eventignore+=FileType
-
-let s:end=line('$')
-
-" Font
-if exists("g:html_font")
- if type(g:html_font) == type([])
- let s:htmlfont = "'".. join(g:html_font,"','") .. "', monospace"
- else
- let s:htmlfont = "'".. g:html_font .. "', monospace"
- endif
-else
- let s:htmlfont = "monospace"
-endif
-
-let s:settings = tohtml#GetUserSettings()
-
-if s:settings.use_xhtml
- let s:html5 = 0
-elseif s:settings.use_css && !s:settings.no_pre
- let s:html5 = 1
-else
- let s:html5 = 0
-endif
-
-if !exists('s:FOLDED_ID')
- let s:FOLDED_ID = hlID("Folded") | lockvar s:FOLDED_ID
- let s:FOLD_C_ID = hlID("FoldColumn") | lockvar s:FOLD_C_ID
- let s:LINENR_ID = hlID('LineNr') | lockvar s:LINENR_ID
- let s:DIFF_D_ID = hlID("DiffDelete") | lockvar s:DIFF_D_ID
- let s:DIFF_A_ID = hlID("DiffAdd") | lockvar s:DIFF_A_ID
- let s:DIFF_C_ID = hlID("DiffChange") | lockvar s:DIFF_C_ID
- let s:DIFF_T_ID = hlID("DiffText") | lockvar s:DIFF_T_ID
- let s:CONCEAL_ID = hlID('Conceal') | lockvar s:CONCEAL_ID
-endif
-
-" Whitespace
-if s:settings.pre_wrap
- let s:whitespace = "white-space: pre-wrap; "
-else
- let s:whitespace = ""
-endif
-
-if !empty(s:settings.prevent_copy)
- if s:settings.no_invalid
- " User has decided they don't want invalid markup. Still works in
- " OpenOffice, and for text editors, but when pasting into Microsoft Word the
- " input elements get pasted too and they cannot be deleted (at least not
- " easily).
- let s:unselInputType = ""
- else
- " Prevent from copy-pasting the input elements into Microsoft Word where
- " they cannot be deleted easily by deliberately inserting invalid markup.
- let s:unselInputType = " type='invalid_input_type'"
- endif
-endif
-
-" When gui colors are not supported, we can only guess the colors.
-" TODO - is this true anymore? Is there a way to ask the terminal what colors
-" each number means or read them from some file?
-if &termguicolors || has("gui_running")
- let s:whatterm = "gui"
-else
- let s:whatterm = "cterm"
- if &t_Co == 8
- let s:cterm_color = {
- \ 0: "#808080", 1: "#ff6060", 2: "#00ff00", 3: "#ffff00",
- \ 4: "#8080ff", 5: "#ff40ff", 6: "#00ffff", 7: "#ffffff"
- \ }
- else
- let s:cterm_color = {
- \ 0: "#000000", 1: "#c00000", 2: "#008000", 3: "#804000",
- \ 4: "#0000c0", 5: "#c000c0", 6: "#008080", 7: "#c0c0c0",
- \ 8: "#808080", 9: "#ff6060", 10: "#00ff00", 11: "#ffff00",
- \ 12: "#8080ff", 13: "#ff40ff", 14: "#00ffff", 15: "#ffffff"
- \ }
-
- " Colors for 88 and 256 come from xterm.
- if &t_Co == 88
- call extend(s:cterm_color, {
- \ 16: "#000000", 17: "#00008b", 18: "#0000cd", 19: "#0000ff",
- \ 20: "#008b00", 21: "#008b8b", 22: "#008bcd", 23: "#008bff",
- \ 24: "#00cd00", 25: "#00cd8b", 26: "#00cdcd", 27: "#00cdff",
- \ 28: "#00ff00", 29: "#00ff8b", 30: "#00ffcd", 31: "#00ffff",
- \ 32: "#8b0000", 33: "#8b008b", 34: "#8b00cd", 35: "#8b00ff",
- \ 36: "#8b8b00", 37: "#8b8b8b", 38: "#8b8bcd", 39: "#8b8bff",
- \ 40: "#8bcd00", 41: "#8bcd8b", 42: "#8bcdcd", 43: "#8bcdff",
- \ 44: "#8bff00", 45: "#8bff8b", 46: "#8bffcd", 47: "#8bffff",
- \ 48: "#cd0000", 49: "#cd008b", 50: "#cd00cd", 51: "#cd00ff",
- \ 52: "#cd8b00", 53: "#cd8b8b", 54: "#cd8bcd", 55: "#cd8bff",
- \ 56: "#cdcd00", 57: "#cdcd8b", 58: "#cdcdcd", 59: "#cdcdff",
- \ 60: "#cdff00", 61: "#cdff8b", 62: "#cdffcd", 63: "#cdffff",
- \ 64: "#ff0000"
- \ })
- call extend(s:cterm_color, {
- \ 65: "#ff008b", 66: "#ff00cd", 67: "#ff00ff", 68: "#ff8b00",
- \ 69: "#ff8b8b", 70: "#ff8bcd", 71: "#ff8bff", 72: "#ffcd00",
- \ 73: "#ffcd8b", 74: "#ffcdcd", 75: "#ffcdff", 76: "#ffff00",
- \ 77: "#ffff8b", 78: "#ffffcd", 79: "#ffffff", 80: "#2e2e2e",
- \ 81: "#5c5c5c", 82: "#737373", 83: "#8b8b8b", 84: "#a2a2a2",
- \ 85: "#b9b9b9", 86: "#d0d0d0", 87: "#e7e7e7"
- \ })
- elseif &t_Co == 256
- call extend(s:cterm_color, {
- \ 16: "#000000", 17: "#00005f", 18: "#000087", 19: "#0000af",
- \ 20: "#0000d7", 21: "#0000ff", 22: "#005f00", 23: "#005f5f",
- \ 24: "#005f87", 25: "#005faf", 26: "#005fd7", 27: "#005fff",
- \ 28: "#008700", 29: "#00875f", 30: "#008787", 31: "#0087af",
- \ 32: "#0087d7", 33: "#0087ff", 34: "#00af00", 35: "#00af5f",
- \ 36: "#00af87", 37: "#00afaf", 38: "#00afd7", 39: "#00afff",
- \ 40: "#00d700", 41: "#00d75f", 42: "#00d787", 43: "#00d7af",
- \ 44: "#00d7d7", 45: "#00d7ff", 46: "#00ff00", 47: "#00ff5f",
- \ 48: "#00ff87", 49: "#00ffaf", 50: "#00ffd7", 51: "#00ffff",
- \ 52: "#5f0000", 53: "#5f005f", 54: "#5f0087", 55: "#5f00af",
- \ 56: "#5f00d7", 57: "#5f00ff", 58: "#5f5f00", 59: "#5f5f5f",
- \ 60: "#5f5f87", 61: "#5f5faf", 62: "#5f5fd7", 63: "#5f5fff",
- \ 64: "#5f8700"
- \ })
- call extend(s:cterm_color, {
- \ 65: "#5f875f", 66: "#5f8787", 67: "#5f87af", 68: "#5f87d7",
- \ 69: "#5f87ff", 70: "#5faf00", 71: "#5faf5f", 72: "#5faf87",
- \ 73: "#5fafaf", 74: "#5fafd7", 75: "#5fafff", 76: "#5fd700",
- \ 77: "#5fd75f", 78: "#5fd787", 79: "#5fd7af", 80: "#5fd7d7",
- \ 81: "#5fd7ff", 82: "#5fff00", 83: "#5fff5f", 84: "#5fff87",
- \ 85: "#5fffaf", 86: "#5fffd7", 87: "#5fffff", 88: "#870000",
- \ 89: "#87005f", 90: "#870087", 91: "#8700af", 92: "#8700d7",
- \ 93: "#8700ff", 94: "#875f00", 95: "#875f5f", 96: "#875f87",
- \ 97: "#875faf", 98: "#875fd7", 99: "#875fff", 100: "#878700",
- \ 101: "#87875f", 102: "#878787", 103: "#8787af", 104: "#8787d7",
- \ 105: "#8787ff", 106: "#87af00", 107: "#87af5f", 108: "#87af87",
- \ 109: "#87afaf", 110: "#87afd7", 111: "#87afff", 112: "#87d700"
- \ })
- call extend(s:cterm_color, {
- \ 113: "#87d75f", 114: "#87d787", 115: "#87d7af", 116: "#87d7d7",
- \ 117: "#87d7ff", 118: "#87ff00", 119: "#87ff5f", 120: "#87ff87",
- \ 121: "#87ffaf", 122: "#87ffd7", 123: "#87ffff", 124: "#af0000",
- \ 125: "#af005f", 126: "#af0087", 127: "#af00af", 128: "#af00d7",
- \ 129: "#af00ff", 130: "#af5f00", 131: "#af5f5f", 132: "#af5f87",
- \ 133: "#af5faf", 134: "#af5fd7", 135: "#af5fff", 136: "#af8700",
- \ 137: "#af875f", 138: "#af8787", 139: "#af87af", 140: "#af87d7",
- \ 141: "#af87ff", 142: "#afaf00", 143: "#afaf5f", 144: "#afaf87",
- \ 145: "#afafaf", 146: "#afafd7", 147: "#afafff", 148: "#afd700",
- \ 149: "#afd75f", 150: "#afd787", 151: "#afd7af", 152: "#afd7d7",
- \ 153: "#afd7ff", 154: "#afff00", 155: "#afff5f", 156: "#afff87",
- \ 157: "#afffaf", 158: "#afffd7"
- \ })
- call extend(s:cterm_color, {
- \ 159: "#afffff", 160: "#d70000", 161: "#d7005f", 162: "#d70087",
- \ 163: "#d700af", 164: "#d700d7", 165: "#d700ff", 166: "#d75f00",
- \ 167: "#d75f5f", 168: "#d75f87", 169: "#d75faf", 170: "#d75fd7",
- \ 171: "#d75fff", 172: "#d78700", 173: "#d7875f", 174: "#d78787",
- \ 175: "#d787af", 176: "#d787d7", 177: "#d787ff", 178: "#d7af00",
- \ 179: "#d7af5f", 180: "#d7af87", 181: "#d7afaf", 182: "#d7afd7",
- \ 183: "#d7afff", 184: "#d7d700", 185: "#d7d75f", 186: "#d7d787",
- \ 187: "#d7d7af", 188: "#d7d7d7", 189: "#d7d7ff", 190: "#d7ff00",
- \ 191: "#d7ff5f", 192: "#d7ff87", 193: "#d7ffaf", 194: "#d7ffd7",
- \ 195: "#d7ffff", 196: "#ff0000", 197: "#ff005f", 198: "#ff0087",
- \ 199: "#ff00af", 200: "#ff00d7", 201: "#ff00ff", 202: "#ff5f00",
- \ 203: "#ff5f5f", 204: "#ff5f87"
- \ })
- call extend(s:cterm_color, {
- \ 205: "#ff5faf", 206: "#ff5fd7", 207: "#ff5fff", 208: "#ff8700",
- \ 209: "#ff875f", 210: "#ff8787", 211: "#ff87af", 212: "#ff87d7",
- \ 213: "#ff87ff", 214: "#ffaf00", 215: "#ffaf5f", 216: "#ffaf87",
- \ 217: "#ffafaf", 218: "#ffafd7", 219: "#ffafff", 220: "#ffd700",
- \ 221: "#ffd75f", 222: "#ffd787", 223: "#ffd7af", 224: "#ffd7d7",
- \ 225: "#ffd7ff", 226: "#ffff00", 227: "#ffff5f", 228: "#ffff87",
- \ 229: "#ffffaf", 230: "#ffffd7", 231: "#ffffff", 232: "#080808",
- \ 233: "#121212", 234: "#1c1c1c", 235: "#262626", 236: "#303030",
- \ 237: "#3a3a3a", 238: "#444444", 239: "#4e4e4e", 240: "#585858",
- \ 241: "#626262", 242: "#6c6c6c", 243: "#767676", 244: "#808080",
- \ 245: "#8a8a8a", 246: "#949494", 247: "#9e9e9e", 248: "#a8a8a8",
- \ 249: "#b2b2b2", 250: "#bcbcbc", 251: "#c6c6c6", 252: "#d0d0d0",
- \ 253: "#dadada", 254: "#e4e4e4", 255: "#eeeeee"
- \ })
- endif
- endif
-endif
-
-" Return good color specification: in GUI no transformation is done, in
-" terminal return RGB values of known colors and empty string for unknown
-if s:whatterm == "gui"
- function! s:HtmlColor(color)
- return a:color
- endfun
-else
- function! s:HtmlColor(color)
- if has_key(s:cterm_color, a:color)
- return s:cterm_color[a:color]
- else
- return ""
- endif
- endfun
-endif
-
-" Find out the background and foreground color for use later
-let s:fgc = s:HtmlColor(synIDattr(hlID("Normal")->synIDtrans(), "fg#", s:whatterm))
-let s:bgc = s:HtmlColor(synIDattr(hlID("Normal")->synIDtrans(), "bg#", s:whatterm))
-if s:fgc == ""
- let s:fgc = ( &background == "dark" ? "#ffffff" : "#000000" )
-endif
-if s:bgc == ""
- let s:bgc = ( &background == "dark" ? "#000000" : "#ffffff" )
-endif
-
-if !s:settings.use_css
- " Return opening HTML tag for given highlight id
- function! s:HtmlOpening(id, extra_attrs)
- let a = ""
- let translated_ID = synIDtrans(a:id)
- if synIDattr(translated_ID, "inverse")
- " For inverse, we always must set both colors (and exchange them)
- let x = s:HtmlColor(synIDattr(translated_ID, "fg#", s:whatterm))
- let a = a .. '<span '..a:extra_attrs..'style="background-color: ' .. ( x != "" ? x : s:fgc ) .. '">'
- let x = s:HtmlColor(synIDattr(translated_ID, "bg#", s:whatterm))
- let a = a .. '<font color="' .. ( x != "" ? x : s:bgc ) .. '">'
- else
- let x = s:HtmlColor(synIDattr(translated_ID, "bg#", s:whatterm))
- if x != ""
- let a = a .. '<span '..a:extra_attrs..'style="background-color: ' .. x .. '">'
- elseif !empty(a:extra_attrs)
- let a = a .. '<span '..a:extra_attrs..'>'
- endif
- let x = s:HtmlColor(synIDattr(translated_ID, "fg#", s:whatterm))
- if x != "" | let a = a .. '<font color="' .. x .. '">' | endif
- endif
- if synIDattr(translated_ID, "bold") | let a = a .. "<b>" | endif
- if synIDattr(translated_ID, "italic") | let a = a .. "<i>" | endif
- if synIDattr(translated_ID, "underline") | let a = a .. "<u>" | endif
- return a
- endfun
-
- " Return closing HTML tag for given highlight id
- function! s:HtmlClosing(id, has_extra_attrs)
- let a = ""
- let translated_ID = synIDtrans(a:id)
- if synIDattr(translated_ID, "underline") | let a = a .. "</u>" | endif
- if synIDattr(translated_ID, "italic") | let a = a .. "</i>" | endif
- if synIDattr(translated_ID, "bold") | let a = a .. "</b>" | endif
- if synIDattr(translated_ID, "inverse")
- let a = a .. '</font></span>'
- else
- let x = s:HtmlColor(synIDattr(translated_ID, "fg#", s:whatterm))
- if x != "" | let a = a .. '</font>' | endif
- let x = s:HtmlColor(synIDattr(translated_ID, "bg#", s:whatterm))
- if x != "" || a:has_extra_attrs | let a = a .. '</span>' | endif
- endif
- return a
- endfun
-endif
-
-" Use a different function for formatting based on user options. This way we
-" can avoid a lot of logic during the actual execution.
-"
-" Build the function line by line containing only what is needed for the options
-" in use for maximum code sharing with minimal branch logic for greater speed.
-"
-" Note, 'exec' commands do not recognize line continuations, so must concatenate
-" lines rather than continue them.
-if s:settings.use_css
- " save CSS to a list of rules to add to the output at the end of processing
-
- " first, get the style names we need
- let s:wrapperfunc_lines = []
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
- function! s:BuildStyleWrapper(style_id, diff_style_id, extra_attrs, text, make_unselectable, unformatted)
-
- let l:style_name = synIDattr(a:style_id, "name", s:whatterm)
- ENDLET
- if &diff
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
- let l:diff_style_name = synIDattr(a:diff_style_id, "name", s:whatterm)
- ENDLET
-
- " Add normal groups and diff groups to separate lists so we can order them to
- " allow diff highlight to override normal highlight
-
- " if primary style IS a diff style, grab it from the diff cache instead
- " (always succeeds because we pre-populate it)
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
-
- if a:style_id == s:DIFF_D_ID || a:style_id == s:DIFF_A_ID || a:style_id == s:DIFF_C_ID || a:style_id == s:DIFF_T_ID
- let l:saved_style = get(s:diffstylelist,a:style_id)
- else
- ENDLET
- endif
-
- " get primary style info from cache or build it on the fly if not found
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
- let l:saved_style = get(s:stylelist,a:style_id)
- if type(l:saved_style) == type(0)
- unlet l:saved_style
- let l:saved_style = s:CSS1(a:style_id)
- if l:saved_style != ""
- let l:saved_style = "." .. l:style_name .. " { " .. l:saved_style .. "}"
- endif
- let s:stylelist[a:style_id] = l:saved_style
- endif
- ENDLET
- if &diff
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
- endif
- ENDLET
- endif
-" Ignore this comment, just bypassing a highlighting issue: if
-
- " Build the wrapper tags around the text. It turns out that caching these
- " gives pretty much zero performance gain and adds a lot of logic.
-
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
-
- if l:saved_style == "" && empty(a:extra_attrs)
- ENDLET
- if &diff
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
- if a:diff_style_id <= 0
- ENDLET
- endif
- " no surroundings if neither primary nor diff style has any info
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
- return a:text
- ENDLET
- if &diff
- " no primary style, but diff style
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
- else
- return '<span class="' ..l:diff_style_name .. '">'..a:text.."</span>"
- endif
- ENDLET
- endif
- " Ignore this comment, just bypassing a highlighting issue: if
-
- " open tag for non-empty primary style
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
- else
- ENDLET
- " non-empty primary style. handle either empty or non-empty diff style.
- "
- " separate the two classes by a space to apply them both if there is a diff
- " style name, unless the primary style is empty, then just use the diff style
- " name
- let s:diffstyle =
- \ (&diff ? '(a:diff_style_id <= 0 ? "" : " " .. l:diff_style_name)..'
- \ : '')
- if s:settings.prevent_copy == ""
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim eval ENDLET
- return "<span "..a:extra_attrs..'class="' .. l:style_name ..{s:diffstyle}'">'..a:text.."</span>"
- ENDLET
- else
-
- " New method: use generated content in the CSS. The only thing needed here
- " is a span with no content, with an attribute holding the desired text.
- "
- " Old method: use an <input> element when text is unsectable. This is still
- " used in conditional comments for Internet Explorer, where the new method
- " doesn't work.
- "
- " Wrap the <input> in a <span> to allow fixing the stupid bug in some fonts
- " which cause browsers to display a 1px gap between lines when these
- " <input>s have a background color (maybe not really a bug, this isn't
- " well-defined)
- "
- " use strwidth, because we care only about how many character boxes are
- " needed to size the input, we don't care how many characters (including
- " separately counted composing chars, from strchars()) or bytes (from
- " len())the string contains. strdisplaywidth() is not needed because none of
- " the unselectable groups can contain tab characters (fold column, fold
- " text, line number).
- "
- " Note, if maxlength property needs to be added in the future, it will need
- " to use strchars(), because HTML specifies that the maxlength parameter
- " uses the number of unique codepoints for its limit.
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim eval ENDLET
- if a:make_unselectable
- let return_span = "<span "..a:extra_attrs..'class="' .. l:style_name ..{s:diffstyle}'"'
- ENDLET
- if s:settings.use_input_for_pc !=# 'all'
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
- let return_span ..= " data-" .. l:style_name .. '-content="'..a:text..'"'
- ENDLET
- endif
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
- let return_span ..= '>'
- ENDLET
- if s:settings.use_input_for_pc !=# 'none'
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim eval ENDLET
- let return_span ..= '<input'..s:unselInputType..' class="' .. l:style_name ..{s:diffstyle}'"'
- let return_span ..= ' value="'..substitute(a:unformatted,'\s\+$',"","")..'"'
- let return_span ..= " onselect='this.blur(); return false;'"
- let return_span ..= " onmousedown='this.blur(); return false;'"
- let return_span ..= " onclick='this.blur(); return false;'"
- let return_span ..= " readonly='readonly'"
- let return_span ..= ' size="'..strwidth(a:unformatted)..'"'
- let return_span ..= (s:settings.use_xhtml ? '/>' : '>')
- ENDLET
- endif
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim eval ENDLET
- return return_span..'</span>'
- else
- return "<span "..a:extra_attrs..'class="' .. l:style_name .. {s:diffstyle}'">'..a:text.."</span>"
- endif
- ENDLET
- endif
- call add(s:wrapperfunc_lines, [])
- let s:wrapperfunc_lines[-1] =<< trim ENDLET
- endif
- endfun
- ENDLET
-else
- " Non-CSS method just needs the wrapper.
- "
- " Functions used to get opening/closing automatically return null strings if
- " no styles exist.
- if &diff
- let s:wrapperfunc_lines =<< trim ENDLET
- function! s:BuildStyleWrapper(style_id, diff_style_id, extra_attrs, text, unusedarg, unusedarg2)
- if a:diff_style_id <= 0
- let l:diff_opening = s:HtmlOpening(a:diff_style_id, "")
- let l:diff_closing = s:HtmlClosing(a:diff_style_id, 0)
- else
- let l:diff_opening = ""
- let l:diff_closing = ""
- endif
- return s:HtmlOpening(a:style_id, a:extra_attrs)..l:diff_opening..a:text..l:diff_closing..s:HtmlClosing(a:style_id, !empty(a:extra_attrs))
- endfun
- ENDLET
- else
- let s:wrapperfunc_lines =<< trim ENDLET
- function! s:BuildStyleWrapper(style_id, diff_style_id, extra_attrs, text, unusedarg, unusedarg2)
- return s:HtmlOpening(a:style_id, a:extra_attrs)..a:text..s:HtmlClosing(a:style_id, !empty(a:extra_attrs))
- endfun
- ENDLET
- endif
-endif
-
-" create the function we built line by line above
-exec join(flatten(s:wrapperfunc_lines), "\n")
-
-let s:diff_mode = &diff
-
-" Return HTML valid characters enclosed in a span of class style_name with
-" unprintable characters expanded and double spaces replaced as necessary.
-"
-" TODO: eliminate unneeded logic like done for BuildStyleWrapper
-function! s:HtmlFormat(text, style_id, diff_style_id, extra_attrs, make_unselectable)
- " Replace unprintable characters
- let unformatted = strtrans(a:text)
-
- let formatted = unformatted
-
- " Replace the reserved html characters
- let formatted = substitute(formatted, '&', '\&amp;', 'g')
- let formatted = substitute(formatted, '<', '\&lt;', 'g')
- let formatted = substitute(formatted, '>', '\&gt;', 'g')
- let formatted = substitute(formatted, '"', '\&quot;', 'g')
- " &apos; is not valid in HTML but it is in XHTML, so just use the numeric
- " reference for it instead. Needed because it could appear in quotes
- " especially if unselectable regions is turned on.
- let formatted = substitute(formatted, '"', '\&#0039;', 'g')
-
- " Replace a "form feed" character with HTML to do a page break
- " TODO: need to prevent this in unselectable areas? Probably it should never
- " BE in an unselectable area...
- let formatted = substitute(formatted, "\x0c", '<hr class="PAGE-BREAK">', 'g')
-
- " Replace double spaces, leading spaces, and trailing spaces if needed
- if ' ' != s:HtmlSpace
- let formatted = substitute(formatted, ' ', s:HtmlSpace .. s:HtmlSpace, 'g')
- let formatted = substitute(formatted, '^ ', s:HtmlSpace, 'g')
- let formatted = substitute(formatted, ' \+$', s:HtmlSpace, 'g')
- endif
-
- " Enclose in the correct format
- return s:BuildStyleWrapper(a:style_id, a:diff_style_id, a:extra_attrs, formatted, a:make_unselectable, unformatted)
-endfun
-
-" set up functions to call HtmlFormat in certain ways based on whether the
-" element is supposed to be unselectable or not
-if s:settings.prevent_copy =~# 'n'
- if s:settings.number_lines
- if s:settings.line_ids
- function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr)
- if a:lnr > 0
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 'id="'..(exists('g:html_diff_win_num') ? 'W'..g:html_diff_win_num : "")..'L'..a:lnr..s:settings.id_suffix..'" ', 1)
- else
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1)
- endif
- endfun
- else
- function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1)
- endfun
- endif
- elseif s:settings.line_ids
- " if lines are not being numbered the only reason this function gets called
- " is to put the line IDs on each line; "text" will be empty but lnr will
- " always be non-zero, however we don't want to use the <input> because that
- " won't work as nice for empty text
- function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 'id="'..(exists('g:html_diff_win_num') ? 'W'..g:html_diff_win_num : "")..'L'..a:lnr..s:settings.id_suffix..'" ', 0)
- endfun
- endif
-else
- if s:settings.line_ids
- function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr)
- if a:lnr > 0
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, 'id="'..(exists('g:html_diff_win_num') ? 'W'..g:html_diff_win_num : "")..'L'..a:lnr..s:settings.id_suffix..'" ', 0)
- else
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 0)
- endif
- endfun
- else
- function! s:HtmlFormat_n(text, style_id, diff_style_id, lnr)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 0)
- endfun
- endif
-endif
-if s:settings.prevent_copy =~# 'd'
- function! s:HtmlFormat_d(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1)
- endfun
-else
- function! s:HtmlFormat_d(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 0)
- endfun
-endif
-if s:settings.prevent_copy =~# 'f'
- if s:settings.use_input_for_pc ==# 'none'
- " Simply space-pad to the desired width inside the generated content (note
- " that the FoldColumn definition includes a whitespace:pre rule)
- function! s:FoldColumn_build(char, len, numfill, char2, class, click)
- return "<a href='#' class='"..a:class.."' onclick='"..a:click.."' data-FoldColumn-content='".
- \ repeat(a:char, a:len)..a:char2..repeat(' ', a:numfill).
- \ "'></a>"
- endfun
- function! s:FoldColumn_fill()
- return s:HtmlFormat(repeat(' ', s:foldcolumn), s:FOLD_C_ID, 0, "", 1)
- endfun
- else
- " Note the <input> elements for fill spaces will have a single space for
- " content, to allow active cursor CSS selection to work.
- "
- " Wrap the whole thing in a span for the 1px padding workaround for gaps.
- "
- " Build the function line by line containing only what is needed for the
- " options in use for maximum code sharing with minimal branch logic for
- " greater speed.
- "
- " Note, 'exec' commands do not recognize line continuations, so must
- " concatenate lines rather than continue them.
- let s:build_fun_lines = []
- call add(s:build_fun_lines, [])
- let s:build_fun_lines[-1] =<< trim ENDLET
- function! s:FoldColumn_build(char, len, numfill, char2, class, click)
- let l:input_open = "<input readonly='readonly'"..s:unselInputType
- let l:input_open ..= " onselect='this.blur(); return false;'"
- let l:input_open ..= " onmousedown='this.blur(); "..a:click.." return false;'"
- let l:input_open ..= " onclick='return false;' size='"
- let l:input_open ..= string(a:len + (empty(a:char2) ? 0 : 1) + a:numfill) .. "' "
- let l:common_attrs = "class='FoldColumn' value='"
- let l:input_close = (s:settings.use_xhtml ? "' />" : "'>")
- let l:return_span = "<span class='"..a:class.."'>"
- let l:return_span ..= l:input_open..l:common_attrs..repeat(a:char, a:len)..(a:char2)
- let l:return_span ..= l:input_close
- ENDLET
- if s:settings.use_input_for_pc ==# 'fallback'
- call add(s:build_fun_lines, [])
- let s:build_fun_lines[-1] =<< trim ENDLET
- let l:return_span ..= "<a href='#' class='FoldColumn' onclick='"..a:click.."'"
- let l:return_span ..= " data-FoldColumn-content='"
- let l:return_span ..= repeat(a:char, a:len)..a:char2..repeat(' ', a:numfill)
- let l:return_span ..= "'></a>"
- ENDLET
- endif
- call add(s:build_fun_lines, [])
- let s:build_fun_lines[-1] =<< trim ENDLET
- let l:return_span ..= "</span>"
- return l:return_span
- endfun
- ENDLET
- " create the function we built line by line above
- exec join(flatten(s:build_fun_lines), "\n")
-
- function! s:FoldColumn_fill()
- return s:FoldColumn_build(' ', s:foldcolumn, 0, '', 'FoldColumn', '')
- endfun
- endif
-else
- " For normal fold columns, simply space-pad to the desired width (note that
- " the FoldColumn definition includes a whitespace:pre rule)
- function! s:FoldColumn_build(char, len, numfill, char2, class, click)
- return "<a href='#' class='"..a:class.."' onclick='"..a:click.."'>".
- \ repeat(a:char, a:len)..a:char2..repeat(' ', a:numfill).
- \ "</a>"
- endfun
- function! s:FoldColumn_fill()
- return s:HtmlFormat(repeat(' ', s:foldcolumn), s:FOLD_C_ID, 0, "", 0)
- endfun
-endif
-if s:settings.prevent_copy =~# 't'
- " put an extra empty span at the end for dynamic folds, so the linebreak can
- " be surrounded. Otherwise do it as normal.
- "
- " TODO: isn't there a better way to do this, than placing it here and using a
- " substitute later?
- if s:settings.dynamic_folds
- function! s:HtmlFormat_t(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1) .
- \ s:HtmlFormat("", a:style_id, 0, "", 0)
- endfun
- else
- function! s:HtmlFormat_t(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 1)
- endfun
- endif
-else
- function! s:HtmlFormat_t(text, style_id, diff_style_id)
- return s:HtmlFormat(a:text, a:style_id, a:diff_style_id, "", 0)
- endfun
-endif
-
-" Return CSS style describing given highlight id (can be empty)
-function! s:CSS1(id)
- let a = ""
- let translated_ID = synIDtrans(a:id)
- if synIDattr(translated_ID, "inverse")
- " For inverse, we always must set both colors (and exchange them)
- let x = s:HtmlColor(synIDattr(translated_ID, "bg#", s:whatterm))
- let a = a .. "color: " .. ( x != "" ? x : s:bgc ) .. "; "
- let x = s:HtmlColor(synIDattr(translated_ID, "fg#", s:whatterm))
- let a = a .. "background-color: " .. ( x != "" ? x : s:fgc ) .. "; "
- else
- let x = s:HtmlColor(synIDattr(translated_ID, "fg#", s:whatterm))
- if x != "" | let a = a .. "color: " .. x .. "; " | endif
- let x = s:HtmlColor(synIDattr(translated_ID, "bg#", s:whatterm))
- if x != ""
- let a = a .. "background-color: " .. x .. "; "
- " stupid hack because almost every browser seems to have at least one font
- " which shows 1px gaps between lines which have background
- let a = a .. "padding-bottom: 1px; "
- elseif (translated_ID == s:FOLDED_ID || translated_ID == s:LINENR_ID || translated_ID == s:FOLD_C_ID) && !empty(s:settings.prevent_copy)
- " input elements default to a different color than the rest of the page
- let a = a .. "background-color: " .. s:bgc .. "; "
- endif
- endif
- if synIDattr(translated_ID, "bold") | let a = a .. "font-weight: bold; " | endif
- if synIDattr(translated_ID, "italic") | let a = a .. "font-style: italic; " | endif
- if synIDattr(translated_ID, "underline") | let a = a .. "text-decoration: underline; " | endif
- return a
-endfun
-
-if s:settings.dynamic_folds
- " compares two folds as stored in our list of folds
- " A fold is "less" than another if it starts at an earlier line number,
- " or ends at a later line number, ties broken by fold level
- function! s:FoldCompare(f1, f2)
- if a:f1.firstline != a:f2.firstline
- " put it before if it starts earlier
- return a:f1.firstline - a:f2.firstline
- elseif a:f1.lastline != a:f2.lastline
- " put it before if it ends later
- return a:f2.lastline - a:f1.lastline
- else
- " if folds begin and end on the same lines, put lowest fold level first
- return a:f1.level - a:f2.level
- endif
- endfunction
-
-endif
-
-
-" Set some options to make it work faster.
-" Don't report changes for :substitute, there will be many of them.
-" Don't change other windows; turn off scroll bind temporarily
-let s:old_title = &title
-let s:old_icon = &icon
-let s:old_et = &l:et
-let s:old_bind = &l:scrollbind
-let s:old_report = &report
-let s:old_search = @/
-let s:old_more = &more
-set notitle noicon
-setlocal et
-set nomore
-set report=1000000
-setlocal noscrollbind
-
-if exists(':ownsyntax') && exists('w:current_syntax')
- let s:current_syntax = w:current_syntax
-elseif exists('b:current_syntax')
- let s:current_syntax = b:current_syntax
-else
- let s:current_syntax = 'none'
-endif
-
-if s:current_syntax == ''
- let s:current_syntax = 'none'
-endif
-
-" If the user is sourcing this script directly then the plugin version isn't
-" known because the main plugin script didn't load. In the usual case where the
-" user still has the full Vim runtime installed, or has this full plugin
-" installed in a package or something, then we can extract the version from the
-" main plugin file at it's usual spot relative to this file. Otherwise the user
-" is assembling their runtime piecemeal and we have no idea what versions of
-" other files may be present so don't even try to make a guess or assume the
-" presence of other specific files with specific meaning.
-"
-" We don't want to actually source the main plugin file here because the user
-" may have a good reason not to (e.g. they define their own TOhtml command or
-" something).
-"
-" If this seems way too complicated and convoluted, it is. Probably I should
-" have put the version information in the autoload file from the start. But the
-" version has been in the global variable for so long that changing it could
-" break a lot of user scripts.
-if exists("g:loaded_2html_plugin")
- let s:pluginversion = g:loaded_2html_plugin
-else
- if !exists("g:unloaded_tohtml_plugin")
- let s:main_plugin_path = expand("<sfile>:p:h:h").."/plugin/tohtml.vim"
- if filereadable(s:main_plugin_path)
- let s:lines = readfile(s:main_plugin_path, "", 20)
- call filter(s:lines, 'v:val =~ "loaded_2html_plugin = "')
- if empty(s:lines)
- let g:unloaded_tohtml_plugin = "unknown"
- else
- let g:unloaded_tohtml_plugin = substitute(s:lines[0], '.*loaded_2html_plugin = \([''"]\)\(\%(\1\@!.\)\+\)\1', '\2', '')
- endif
- unlet s:lines
- else
- let g:unloaded_tohtml_plugin = "unknown"
- endif
- unlet s:main_plugin_path
- endif
- let s:pluginversion = g:unloaded_tohtml_plugin
-endif
-
-" Split window to create a buffer with the HTML file.
-let s:orgbufnr = winbufnr(0)
-let s:origwin_stl = &l:stl
-if expand("%") == ""
- if exists('g:html_diff_win_num')
- exec 'new Untitled_win'..g:html_diff_win_num..'.'.(s:settings.use_xhtml ? 'xhtml' : 'html')
- else
- exec 'new Untitled.'..(s:settings.use_xhtml ? 'xhtml' : 'html')
- endif
-else
- exec 'new %.'..(s:settings.use_xhtml ? 'xhtml' : 'html')
-endif
-
-" Resize the new window to very small in order to make it draw faster
-let s:old_winheight = winheight(0)
-let s:old_winfixheight = &l:winfixheight
-if s:old_winheight > 2
- resize 1 " leave enough room to view one line at a time
- norm! G
- norm! zt
-endif
-setlocal winfixheight
-
-let s:newwin_stl = &l:stl
-
-" on the new window, set the least time-consuming fold method
-let s:old_fen = &foldenable
-setlocal foldmethod=manual
-setlocal nofoldenable
-
-let s:newwin = winnr()
-let s:orgwin = bufwinnr(s:orgbufnr)
-
-setlocal modifiable
-%d
-let s:old_paste = &paste
-set paste
-let s:old_magic = &magic
-set magic
-
-" set the fileencoding to match the charset we'll be using
-let &l:fileencoding=s:settings.vim_encoding
-
-" According to http://www.w3.org/TR/html4/charset.html#doc-char-set, the byte
-" order mark is highly recommend on the web when using multibyte encodings. But,
-" it is not a good idea to include it on UTF-8 files. Otherwise, let Vim
-" determine when it is actually inserted.
-if s:settings.vim_encoding == 'utf-8'
- setlocal nobomb
-else
- setlocal bomb
-endif
-
-let s:lines = []
-
-if s:settings.use_xhtml
- if s:settings.encoding != ""
- call add(s:lines, "<?xml version=\"1.0\" encoding=\"" .. s:settings.encoding .. "\"?>")
- else
- call add(s:lines, "<?xml version=\"1.0\"?>")
- endif
- let s:tag_close = ' />'
-else
- let s:tag_close = '>'
-endif
-
-let s:HtmlSpace = ' '
-let s:LeadingSpace = ' '
-let s:HtmlEndline = ''
-if s:settings.no_pre
- let s:HtmlEndline = '<br' .. s:tag_close
- let s:LeadingSpace = s:settings.use_xhtml ? '&#160;' : '&nbsp;'
- let s:HtmlSpace = '\' .. s:LeadingSpace
-endif
-
-" HTML header, with the title and generator ;-). Left free space for the CSS,
-" to be filled at the end.
-if !s:settings.no_doc
- call extend(s:lines, [
- \ "<html>",
- \ "<head>"])
- " include encoding as close to the top as possible, but only if not already
- " contained in XML information (to avoid haggling over content type)
- if s:settings.encoding != "" && !s:settings.use_xhtml
- if s:html5
- call add(s:lines, '<meta charset="' .. s:settings.encoding .. '"' .. s:tag_close)
- else
- call add(s:lines, "<meta http-equiv=\"content-type\" content=\"text/html; charset=" .. s:settings.encoding .. '"' .. s:tag_close)
- endif
- endif
- call extend(s:lines, [
- \ ("<title>"..expand("%:p:~").."</title>"),
- \ ("<meta name=\"Generator\" content=\"Vim/"..v:version/100.."."..v:version%100..'"'..s:tag_close),
- \ ("<meta name=\"plugin-version\" content=\""..s:pluginversion..'"'..s:tag_close)
- \ ])
- call add(s:lines, '<meta name="syntax" content="'..s:current_syntax..'"'..s:tag_close)
- call add(s:lines, '<meta name="settings" content="'..
- \ join(filter(keys(s:settings),'s:settings[v:val]'),',')..
- \ ',prevent_copy='..s:settings.prevent_copy..
- \ ',use_input_for_pc='..s:settings.use_input_for_pc..
- \ '"'..s:tag_close)
- call add(s:lines, '<meta name="colorscheme" content="'..
- \ (exists('g:colors_name')
- \ ? g:colors_name
- \ : 'none').. '"'..s:tag_close)
-
- if s:settings.use_css
- call extend(s:lines, [
- \ "<style" .. (s:html5 ? "" : " type=\"text/css\"") .. ">",
- \ s:settings.use_xhtml ? "" : "<!--"])
- let s:ieonly = []
- if s:settings.dynamic_folds
- if s:settings.hover_unfold
- " if we are doing hover_unfold, use css 2 with css 1 fallback for IE6
- call extend(s:lines, [
- \ ".FoldColumn { text-decoration: none; white-space: pre; }",
- \ "",
- \ "body * { margin: 0; padding: 0; }", "",
- \ ".open-fold > span.Folded { display: none; }",
- \ ".open-fold > .fulltext { display: inline; }",
- \ ".closed-fold > .fulltext { display: none; }",
- \ ".closed-fold > span.Folded { display: inline; }",
- \ "",
- \ ".open-fold > .toggle-open { display: none; }",
- \ ".open-fold > .toggle-closed { display: inline; }",
- \ ".closed-fold > .toggle-open { display: inline; }",
- \ ".closed-fold > .toggle-closed { display: none; }",
- \ "", "",
- \ '/* opening a fold while hovering won''t be supported by IE6 and other',
- \ "similar browsers, but it should fail gracefully. */",
- \ ".closed-fold:hover > .fulltext { display: inline; }",
- \ ".closed-fold:hover > .toggle-filler { display: none; }",
- \ ".closed-fold:hover > .Folded { display: none; }"])
- " TODO: IE6 is REALLY old and I can't even test it anymore. Maybe we
- " should remove this? Leave it in for now, it was working at one point,
- " and doesn't affect any modern browsers. Even newer IE versions should
- " support the above code and ignore the following.
- let s:ieonly = [
- \ "<!--[if lt IE 7]><style type=\"text/css\">",
- \ ".open-fold .fulltext { display: inline; }",
- \ ".open-fold span.Folded { display: none; }",
- \ ".open-fold .toggle-open { display: none; }",
- \ ".open-fold .toggle-closed { display: inline; }",
- \ "",
- \ ".closed-fold .fulltext { display: none; }",
- \ ".closed-fold span.Folded { display: inline; }",
- \ ".closed-fold .toggle-open { display: inline; }",
- \ ".closed-fold .toggle-closed { display: none; }",
- \ "</style>",
- \ "<![endif]-->",
- \]
- else
- " if we aren't doing hover_unfold, use CSS 1 only
- call extend(s:lines, [
- \ ".FoldColumn { text-decoration: none; white-space: pre; }",
- \ ".open-fold .fulltext { display: inline; }",
- \ ".open-fold span.Folded { display: none; }",
- \ ".open-fold .toggle-open { display: none; }",
- \ ".open-fold .toggle-closed { display: inline; }",
- \ "",
- \ ".closed-fold .fulltext { display: none; }",
- \ ".closed-fold span.Folded { display: inline; }",
- \ ".closed-fold .toggle-open { display: inline; }",
- \ ".closed-fold .toggle-closed { display: none; }",
- \])
- endif
- endif
- " else we aren't doing any dynamic folding, no need for any special rules
-
- call extend(s:lines, [
- \ s:settings.use_xhtml ? "" : '-->',
- \ "</style>",
- \])
- call extend(s:lines, s:ieonly)
- unlet s:ieonly
- endif
-
- let s:uses_script = s:settings.dynamic_folds || s:settings.line_ids
-
- " insert script tag if needed
- if s:uses_script
- call extend(s:lines, [
- \ "",
- \ "<script" .. (s:html5 ? "" : " type='text/javascript'") .. ">",
- \ s:settings.use_xhtml ? '//<![CDATA[' : "<!--"])
- endif
-
- " insert javascript to toggle folds open and closed
- if s:settings.dynamic_folds
- call extend(s:lines, [
- \ "",
- \ "function toggleFold(objID)",
- \ "{",
- \ " var fold;",
- \ " fold = document.getElementById(objID);",
- \ " if (fold.className == 'closed-fold')",
- \ " {",
- \ " fold.className = 'open-fold';",
- \ " }",
- \ " else if (fold.className == 'open-fold')",
- \ " {",
- \ " fold.className = 'closed-fold';",
- \ " }",
- \ "}"
- \ ])
- endif
-
- if s:settings.line_ids
- " insert javascript to get IDs from line numbers, and to open a fold before
- " jumping to any lines contained therein
- call extend(s:lines, [
- \ "",
- \ "/* function to open any folds containing a jumped-to line before jumping to it */",
- \ "function JumpToLine()",
- \ "{",
- \ " var lineNum;",
- \ " lineNum = window.location.hash;",
- \ " lineNum = lineNum.substr(1); /* strip off '#' */",
- \ "",
- \ " if (lineNum.indexOf('L') == -1) {",
- \ " lineNum = 'L'+lineNum;",
- \ " }",
- \ " var lineElem = document.getElementById(lineNum);"
- \ ])
-
- if s:settings.dynamic_folds
- call extend(s:lines, [
- \ "",
- \ " /* navigate upwards in the DOM tree to open all folds containing the line */",
- \ " var node = lineElem;",
- \ " while (node && node.id != 'vimCodeElement"..s:settings.id_suffix.."')",
- \ " {",
- \ " if (node.className == 'closed-fold')",
- \ " {",
- \ " node.className = 'open-fold';",
- \ " }",
- \ " node = node.parentNode;",
- \ " }",
- \ ])
- endif
- call extend(s:lines, [
- \ " /* Always jump to new location even if the line was hidden inside a fold, or",
- \ " * we corrected the raw number to a line ID.",
- \ " */",
- \ " if (lineElem) {",
- \ " lineElem.scrollIntoView(true);",
- \ " }",
- \ " return true;",
- \ "}",
- \ "if ('onhashchange' in window) {",
- \ " window.onhashchange = JumpToLine;",
- \ "}"
- \ ])
- endif
-
- " insert script closing tag if needed
- if s:uses_script
- call extend(s:lines, [
- \ '',
- \ s:settings.use_xhtml ? '//]]>' : '-->',
- \ "</script>"
- \ ])
- endif
-
- call extend(s:lines, ["</head>",
- \ "<body"..(s:settings.line_ids ? " onload='JumpToLine();'" : "")..">"])
-endif
-
-if s:settings.no_pre
- " if we're not using CSS we use a font tag which can't have a div inside
- if s:settings.use_css
- call extend(s:lines, ["<div id='vimCodeElement" .. s:settings.id_suffix .. "'>"])
- endif
-else
- call extend(s:lines, ["<pre id='vimCodeElement" .. s:settings.id_suffix .. "'>"])
-endif
-
-exe s:orgwin .. "wincmd w"
-
-" caches of style data
-" initialize to include line numbers if using them
-if s:settings.number_lines
- let s:stylelist = { s:LINENR_ID : ".LineNr { " .. s:CSS1( s:LINENR_ID ) .. "}" }
-else
- let s:stylelist = {}
-endif
-let s:diffstylelist = {
- \ s:DIFF_A_ID : ".DiffAdd { " .. s:CSS1( s:DIFF_A_ID ) .. "}",
- \ s:DIFF_C_ID : ".DiffChange { " .. s:CSS1( s:DIFF_C_ID ) .. "}",
- \ s:DIFF_D_ID : ".DiffDelete { " .. s:CSS1( s:DIFF_D_ID ) .. "}",
- \ s:DIFF_T_ID : ".DiffText { " .. s:CSS1( s:DIFF_T_ID ) .. "}"
- \ }
-
-" set up progress bar in the status line
-if !s:settings.no_progress
- " ProgressBar Indicator
- let s:progressbar={}
-
- " Progressbar specific functions
-
- func! s:SetProgbarColor()
- if hlID("TOhtmlProgress") != 0
- hi! link TOhtmlProgress_auto TOhtmlProgress
- elseif hlID("TOhtmlProgress_auto")==0 ||
- \ !exists("s:last_colors_name") || !exists("g:colors_name") ||
- \ g:colors_name != s:last_colors_name
- let s:last_colors_name = exists("g:colors_name") ? g:colors_name : "none"
-
- let l:diffatr = synIDattr(hlID("DiffDelete")->synIDtrans(), "reverse", s:whatterm) ? "fg#" : "bg#"
- let l:stlatr = synIDattr(hlID("StatusLine")->synIDtrans(), "reverse", s:whatterm) ? "fg#" : "bg#"
-
- let l:progbar_color = synIDattr(hlID("DiffDelete")->synIDtrans(), l:diffatr, s:whatterm)
- let l:stl_color = synIDattr(hlID("StatusLine")->synIDtrans(), l:stlatr, s:whatterm)
-
- if "" == l:progbar_color
- let l:progbar_color = synIDattr(hlID("DiffDelete")->synIDtrans(), "reverse", s:whatterm) ? s:fgc : s:bgc
- endif
- if "" == l:stl_color
- let l:stl_color = synIDattr(hlID("StatusLine")->synIDtrans(), "reverse", s:whatterm) ? s:fgc : s:bgc
- endif
-
- if l:progbar_color == l:stl_color
- if s:whatterm == 'cterm'
- if l:progbar_color >= (&t_Co/2)
- let l:progbar_color-=1
- else
- let l:progbar_color+=1
- endif
- else
- let l:rgb = map(matchlist(l:progbar_color, '#\zs\x\x\ze\(\x\x\)\(\x\x\)')[:2], 'str2nr(v:val, 16)')
- let l:avg = (l:rgb[0] + l:rgb[1] + l:rgb[2])/3
- if l:avg >= 128
- let l:avg_new = l:avg
- while l:avg - l:avg_new < 0x15
- let l:rgb = map(l:rgb, 'v:val * 3 / 4')
- let l:avg_new = (l:rgb[0] + l:rgb[1] + l:rgb[2])/3
- endwhile
- else
- let l:avg_new = l:avg
- while l:avg_new - l:avg < 0x15
- let l:rgb = map(l:rgb, 'min([max([v:val, 4]) * 5 / 4, 255])')
- let l:avg_new = (l:rgb[0] + l:rgb[1] + l:rgb[2])/3
- endwhile
- endif
- let l:progbar_color = printf("#%02x%02x%02x", l:rgb[0], l:rgb[1], l:rgb[2])
- endif
- echomsg "diff detected progbar color set to" l:progbar_color
- endif
- exe "hi TOhtmlProgress_auto" s:whatterm.."bg="..l:progbar_color
- endif
- endfun
-
- func! s:ProgressBar(title, max_value, winnr)
- let pgb=copy(s:progressbar)
- let pgb.title = a:title..' '
- let pgb.max_value = a:max_value
- let pgb.winnr = a:winnr
- let pgb.cur_value = 0
-
- let pgb.items = { 'title' : { 'color' : 'Statusline' },
- \'bar' : { 'color' : 'Statusline' , 'fillcolor' : 'TOhtmlProgress_auto' , 'bg' : 'Statusline' } ,
- \'counter' : { 'color' : 'Statusline' } }
- let pgb.last_value = 0
- let pgb.needs_redraw = 0
- " Note that you must use len(split) instead of len() if you want to use
- " unicode in title.
- "
- " Subtract 3 for spacing around the title.
- " Subtract 4 for the percentage display.
- " Subtract 2 for spacing before this.
- " Subtract 2 more for the '|' on either side of the progress bar
- let pgb.subtractedlen=len(split(pgb.title, '\zs'))+3+4+2+2
- let pgb.max_len = 0
- set laststatus=2
- return pgb
- endfun
-
- " Function: progressbar.calculate_ticks() {{{1
- func! s:progressbar.calculate_ticks(pb_len)
- if a:pb_len<=0
- let pb_len = 100
- else
- let pb_len = a:pb_len
- endif
- let self.progress_ticks = map(range(pb_len+1), "v:val * self.max_value / pb_len")
- endfun
-
- "Function: progressbar.paint()
- func! s:progressbar.paint()
- " Recalculate widths.
- let max_len = winwidth(self.winnr)
- let pb_len = 0
- " always true on first call because of initial value of self.max_len
- if max_len != self.max_len
- let self.max_len = max_len
-
- " Progressbar length
- let pb_len = max_len - self.subtractedlen
-
- call self.calculate_ticks(pb_len)
-
- let self.needs_redraw = 1
- let cur_value = 0
- let self.pb_len = pb_len
- else
- " start searching at the last found index to make the search for the
- " appropriate tick value normally take 0 or 1 comparisons
- let cur_value = self.last_value
- let pb_len = self.pb_len
- endif
-
- let cur_val_max = pb_len > 0 ? pb_len : 100
-
- " find the current progress bar position based on precalculated thresholds
- while cur_value < cur_val_max && self.cur_value > self.progress_ticks[cur_value]
- let cur_value += 1
- endwhile
-
- " update progress bar
- if self.last_value != cur_value || self.needs_redraw || self.cur_value == self.max_value
- let self.needs_redraw = 1
- let self.last_value = cur_value
-
- let t_color = self.items.title.color
- let b_fcolor = self.items.bar.fillcolor
- let b_color = self.items.bar.color
- let c_color = self.items.counter.color
-
- let stl = "%#".t_color."#%-( ".self.title." %)".
- \"%#".b_color."#".
- \(pb_len>0 ?
- \ ('|%#'.b_fcolor."#%-(".repeat(" ",cur_value)."%)".
- \ '%#'.b_color."#".repeat(" ",pb_len-cur_value)."|"):
- \ ('')).
- \"%=%#".c_color."#%( ".printf("%3.d ",100*self.cur_value/self.max_value)."%% %)"
- call setwinvar(self.winnr, '&stl', stl)
- endif
- endfun
-
- func! s:progressbar.incr( ... )
- let self.cur_value += (a:0 ? a:1 : 1)
- " if we were making a general-purpose progress bar, we'd need to limit to a
- " lower limit as well, but since we always increment with a positive value
- " in this script, we only need limit the upper value
- let self.cur_value = (self.cur_value > self.max_value ? self.max_value : self.cur_value)
- call self.paint()
- endfun
- " }}}
- if s:settings.dynamic_folds
- " to process folds we make two passes through each line
- let s:pgb = s:ProgressBar("Processing folds:", line('$')*2, s:orgwin)
- endif
-
- call s:SetProgbarColor()
-endif
-
-let s:build_fun_lines = []
-call add(s:build_fun_lines, [])
-let s:build_fun_lines[-1] =<< trim ENDLET
- func! s:Add_diff_fill(lnum)
- let l:filler = diff_filler(a:lnum)
- if l:filler > 0
- let l:to_insert = l:filler
- while l:to_insert > 0
- let l:new = repeat(s:difffillchar, 3)
-
- if l:to_insert > 2 && l:to_insert < l:filler && !s:settings.whole_filler
- let l:new = l:new .. " " .. l:filler .. " inserted lines "
- let l:to_insert = 2
- endif
-ENDLET
-call add(s:build_fun_lines, [])
-if !s:settings.no_pre
- let s:build_fun_lines[-1] =<< trim ENDLET
- " HTML line wrapping is off--go ahead and fill to the margin
- " TODO: what about when CSS wrapping is turned on?
- let l:new = l:new .. repeat(s:difffillchar, &columns - strlen(l:new) - s:margin)
- ENDLET
-else
- let s:build_fun_lines[-1] =<< trim ENDLET
- let l:new = l:new .. repeat(s:difffillchar, 3)
- ENDLET
-endif
-call add(s:build_fun_lines, [])
-let s:build_fun_lines[-1] =<< trim ENDLET
- let l:new = s:HtmlFormat_d(l:new, s:DIFF_D_ID, 0)
-ENDLET
-if s:settings.number_lines
- call add(s:build_fun_lines, [])
- let s:build_fun_lines[-1] =<< trim ENDLET
- " Indent if line numbering is on. Indent gets style of line number
- " column.
- let l:new = s:HtmlFormat_n(repeat(' ', s:margin), s:LINENR_ID, 0, 0) .. l:new
- ENDLET
-endif
-if s:settings.dynamic_folds && !s:settings.no_foldcolumn
- call add(s:build_fun_lines, [])
- let s:build_fun_lines[-1] =<< trim ENDLET
- if s:foldcolumn > 0
- " Indent for foldcolumn if there is one. Assume it's empty, there should
- " not be a fold for deleted lines in diff mode.
- let l:new = s:FoldColumn_fill() .. l:new
- endif
- ENDLET
-endif
-" Ignore this comment, just bypassing a highlighting issue: if
-call add(s:build_fun_lines, [])
-let s:build_fun_lines[-1] =<< trim ENDLET
- call add(s:lines, l:new..s:HtmlEndline)
- let l:to_insert = l:to_insert - 1
- endwhile
- endif
- endfun
-ENDLET
-exec join(flatten(s:build_fun_lines), "\n")
-
-" First do some preprocessing for dynamic folding. Do this for the entire file
-" so we don't accidentally start within a closed fold or something.
-let s:allfolds = []
-
-if s:settings.dynamic_folds
- let s:lnum = 1
- let s:end = line('$')
- " save the fold text and set it to the default so we can find fold levels
- let s:foldtext_save = &foldtext
- setlocal foldtext&
-
- " we will set the foldcolumn in the html to the greater of the maximum fold
- " level and the current foldcolumn setting
- let s:foldcolumn = &foldcolumn
-
- " get all info needed to describe currently closed folds
- while s:lnum <= s:end
- if foldclosed(s:lnum) == s:lnum
- " default fold text has '+-' and then a number of dashes equal to fold
- " level, so subtract 2 from index of first non-dash after the dashes
- " in order to get the fold level of the current fold
- let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2
- " store fold info for later use
- let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"}
- call add(s:allfolds, s:newfold)
- " open the fold so we can find any contained folds
- execute s:lnum.."foldopen"
- else
- if !s:settings.no_progress
- call s:pgb.incr()
- if s:pgb.needs_redraw
- redrawstatus
- let s:pgb.needs_redraw = 0
- endif
- endif
- let s:lnum = s:lnum + 1
- endif
- endwhile
-
- " close all folds to get info for originally open folds
- silent! %foldclose!
- let s:lnum = 1
-
- " the originally open folds will be all folds we encounter that aren't
- " already in the list of closed folds
- while s:lnum <= s:end
- if foldclosed(s:lnum) == s:lnum
- " default fold text has '+-' and then a number of dashes equal to fold
- " level, so subtract 2 from index of first non-dash after the dashes
- " in order to get the fold level of the current fold
- let s:level = match(foldtextresult(s:lnum), '+-*\zs[^-]') - 2
- let s:newfold = {'firstline': s:lnum, 'lastline': foldclosedend(s:lnum), 'level': s:level,'type': "closed-fold"}
- " only add the fold if we don't already have it
- if empty(s:allfolds) || index(s:allfolds, s:newfold) == -1
- let s:newfold.type = "open-fold"
- call add(s:allfolds, s:newfold)
- endif
- " open the fold so we can find any contained folds
- execute s:lnum.."foldopen"
- else
- if !s:settings.no_progress
- call s:pgb.incr()
- if s:pgb.needs_redraw
- redrawstatus
- let s:pgb.needs_redraw = 0
- endif
- endif
- let s:lnum = s:lnum + 1
- endif
- endwhile
-
- " sort the folds so that we only ever need to look at the first item in the
- " list of folds
- call sort(s:allfolds, "s:FoldCompare")
-
- let &l:foldtext = s:foldtext_save
- unlet s:foldtext_save
-
- " close all folds again so we can get the fold text as we go
- silent! %foldclose!
-
- " Go through and remove folds we don't need to (or cannot) process in the
- " current conversion range
- "
- " If a fold is removed which contains other folds, which are included, we need
- " to adjust the level of the included folds as used by the conversion logic
- " (avoiding special cases is good)
- "
- " Note any time we remove a fold, either all of the included folds are in it,
- " or none of them, because we only remove a fold if neither its start nor its
- " end are within the conversion range.
- let leveladjust = 0
- for afold in s:allfolds
- let removed = 0
- if exists("g:html_start_line") && exists("g:html_end_line")
- if afold.firstline < g:html_start_line
- if afold.lastline <= g:html_end_line && afold.lastline >= g:html_start_line
- " if a fold starts before the range to convert but stops within the
- " range, we need to include it. Make it start on the first converted
- " line.
- let afold.firstline = g:html_start_line
- else
- " if the fold lies outside the range or the start and stop enclose
- " the entire range, don't bother parsing it
- call remove(s:allfolds, index(s:allfolds, afold))
- let removed = 1
- if afold.lastline > g:html_end_line
- let leveladjust += 1
- endif
- endif
- elseif afold.firstline > g:html_end_line
- " If the entire fold lies outside the range we need to remove it.
- call remove(s:allfolds, index(s:allfolds, afold))
- let removed = 1
- endif
- elseif exists("g:html_start_line")
- if afold.firstline < g:html_start_line
- " if there is no last line, but there is a first line, the end of the
- " fold will always lie within the region of interest, so keep it
- let afold.firstline = g:html_start_line
- endif
- elseif exists("g:html_end_line")
- " if there is no first line we default to the first line in the buffer so
- " the fold start will always be included if the fold itself is included.
- " If however the entire fold lies outside the range we need to remove it.
- if afold.firstline > g:html_end_line
- call remove(s:allfolds, index(s:allfolds, afold))
- let removed = 1
- endif
- endif
- if !removed
- let afold.level -= leveladjust
- if afold.level+1 > s:foldcolumn
- let s:foldcolumn = afold.level+1
- endif
- endif
- endfor
-
- " if we've removed folds containing the conversion range from processing,
- " getting foldtext as we go won't know to open the removed folds, so the
- " foldtext would be wrong; open them now.
- "
- " Note that only when a start and an end line is specified will a fold
- " containing the current range ever be removed.
- while leveladjust > 0
- exe g:html_start_line.."foldopen"
- let leveladjust -= 1
- endwhile
-endif
-
-" Now loop over all lines in the original text to convert to html.
-" Use html_start_line and html_end_line if they are set.
-if exists("g:html_start_line")
- let s:lnum = html_start_line
- if s:lnum < 1 || s:lnum > line("$")
- let s:lnum = 1
- endif
-else
- let s:lnum = 1
-endif
-if exists("g:html_end_line")
- let s:end = html_end_line
- if s:end < s:lnum || s:end > line("$")
- let s:end = line("$")
- endif
-else
- let s:end = line("$")
-endif
-
-" stack to keep track of all the folds containing the current line
-let s:foldstack = []
-
-if !s:settings.no_progress
- let s:pgb = s:ProgressBar("Processing lines:", s:end - s:lnum + 1, s:orgwin)
-endif
-
-if s:settings.number_lines
- let s:margin = strlen(s:end) + 1
-else
- let s:margin = 0
-endif
-
-if has('folding') && !s:settings.ignore_folding
- let s:foldfillchar = &fillchars[matchend(&fillchars, 'fold:')]
- if s:foldfillchar == ''
- let s:foldfillchar = '-'
- endif
-endif
-let s:difffillchar = &fillchars[matchend(&fillchars, 'diff:')]
-if s:difffillchar == ''
- let s:difffillchar = '-'
-endif
-
-let s:foldId = 0
-
-if !s:settings.expand_tabs
- " If keeping tabs, add them to printable characters so we keep them when
- " formatting text (strtrans() doesn't replace printable chars)
- let s:old_isprint = &isprint
- setlocal isprint+=9
-endif
-
-while s:lnum <= s:end
-
- " If there are filler lines for diff mode, show these above the line.
- call s:Add_diff_fill(s:lnum)
-
- " Start the line with the line number.
- if s:settings.number_lines
- let s:numcol = repeat(' ', s:margin - 1 - strlen(s:lnum)) .. s:lnum .. ' '
- endif
-
- let s:new = ""
-
- if has('folding') && !s:settings.ignore_folding && foldclosed(s:lnum) > -1 && !s:settings.dynamic_folds
- "
- " This is the beginning of a folded block (with no dynamic folding)
- let s:new = foldtextresult(s:lnum)
- if !s:settings.no_pre
- " HTML line wrapping is off--go ahead and fill to the margin
- let s:new = s:new .. repeat(s:foldfillchar, &columns - strlen(s:new))
- endif
-
- " put numcol in a separate group for sake of unselectable text
- let s:new = (s:settings.number_lines ? s:HtmlFormat_n(s:numcol, s:FOLDED_ID, 0, s:lnum): "") .. s:HtmlFormat_t(s:new, s:FOLDED_ID, 0)
-
- " Skip to the end of the fold
- let s:new_lnum = foldclosedend(s:lnum)
-
- if !s:settings.no_progress
- call s:pgb.incr(s:new_lnum - s:lnum)
- endif
-
- let s:lnum = s:new_lnum
-
- else
- "
- " A line that is not folded, or doing dynamic folding.
- "
- let s:line = getline(s:lnum)
- let s:len = strlen(s:line)
-
- if s:settings.dynamic_folds
- " First insert a closing for any open folds that end on this line
- while !empty(s:foldstack) && get(s:foldstack,0).lastline == s:lnum-1
- let s:new = s:new.."</span></span>"
- call remove(s:foldstack, 0)
- endwhile
-
- " Now insert an opening for any new folds that start on this line
- let s:firstfold = 1
- while !empty(s:allfolds) && get(s:allfolds,0).firstline == s:lnum
- let s:foldId = s:foldId + 1
- let s:new ..= "<span id='"
- let s:new ..= (exists('g:html_diff_win_num') ? "win"..g:html_diff_win_num : "")
- let s:new ..= "fold"..s:foldId..s:settings.id_suffix.."' class='"..s:allfolds[0].type.."'>"
-
-
- " Unless disabled, add a fold column for the opening line of a fold.
- "
- " Note that dynamic folds require using css so we just use css to take
- " care of the leading spaces rather than using &nbsp; in the case of
- " html_no_pre to make it easier
- if !s:settings.no_foldcolumn
- " add fold column that can open the new fold
- if s:allfolds[0].level > 1 && s:firstfold
- let s:new = s:new .. s:FoldColumn_build('|', s:allfolds[0].level - 1, 0, "",
- \ 'toggle-open FoldColumn','javascript:toggleFold("fold'..s:foldstack[0].id..s:settings.id_suffix..'");')
- endif
- " add the filler spaces separately from the '+' char so that it can be
- " shown/hidden separately during a hover unfold
- let s:new = s:new .. s:FoldColumn_build("+", 1, 0, "",
- \ 'toggle-open FoldColumn', 'javascript:toggleFold("fold'..s:foldId..s:settings.id_suffix..'");')
- " If this is not the last fold we're opening on this line, we need
- " to keep the filler spaces hidden if the fold is opened by mouse
- " hover. If it is the last fold to open in the line, we shouldn't hide
- " them, so don't apply the toggle-filler class.
- let s:new = s:new .. s:FoldColumn_build(" ", 1, s:foldcolumn - s:allfolds[0].level - 1, "",
- \ 'toggle-open FoldColumn'.. (get(s:allfolds, 1, {'firstline': 0}).firstline == s:lnum ?" toggle-filler" :""),
- \ 'javascript:toggleFold("fold'..s:foldId..s:settings.id_suffix..'");')
-
- " add fold column that can close the new fold
- " only add extra blank space if we aren't opening another fold on the
- " same line
- if get(s:allfolds, 1, {'firstline': 0}).firstline != s:lnum
- let s:extra_space = s:foldcolumn - s:allfolds[0].level
- else
- let s:extra_space = 0
- endif
- if s:firstfold
- " the first fold in a line has '|' characters from folds opened in
- " previous lines, before the '-' for this fold
- let s:new ..= s:FoldColumn_build('|', s:allfolds[0].level - 1, s:extra_space, '-',
- \ 'toggle-closed FoldColumn', 'javascript:toggleFold("fold'..s:foldId..s:settings.id_suffix..'");')
- else
- " any subsequent folds in the line only add a single '-'
- let s:new = s:new .. s:FoldColumn_build("-", 1, s:extra_space, "",
- \ 'toggle-closed FoldColumn', 'javascript:toggleFold("fold'..s:foldId..s:settings.id_suffix..'");')
- endif
- let s:firstfold = 0
- endif
-
- " Add fold text, moving the span ending to the next line so collapsing
- " of folds works correctly.
- " Put numcol in a separate group for sake of unselectable text.
- let s:new = s:new .. (s:settings.number_lines ? s:HtmlFormat_n(s:numcol, s:FOLDED_ID, 0, 0) : "") .. substitute(s:HtmlFormat_t(foldtextresult(s:lnum), s:FOLDED_ID, 0), '</span>', s:HtmlEndline..'\n\0', '')
- let s:new = s:new .. "<span class='fulltext'>"
-
- " open the fold now that we have the fold text to allow retrieval of
- " fold text for subsequent folds
- execute s:lnum.."foldopen"
- call insert(s:foldstack, remove(s:allfolds,0))
- let s:foldstack[0].id = s:foldId
- endwhile
-
- " Unless disabled, add a fold column for other lines.
- "
- " Note that dynamic folds require using css so we just use css to take
- " care of the leading spaces rather than using &nbsp; in the case of
- " html_no_pre to make it easier
- if !s:settings.no_foldcolumn
- if empty(s:foldstack)
- " add the empty foldcolumn for unfolded lines if there is a fold
- " column at all
- if s:foldcolumn > 0
- let s:new = s:new .. s:FoldColumn_fill()
- endif
- else
- " add the fold column for folds not on the opening line
- if get(s:foldstack, 0).firstline < s:lnum
- let s:new = s:new .. s:FoldColumn_build('|', s:foldstack[0].level, s:foldcolumn - s:foldstack[0].level, "",
- \ 'FoldColumn', 'javascript:toggleFold("fold'..s:foldstack[0].id..s:settings.id_suffix..'");')
- endif
- endif
- endif
- endif
-
- " Now continue with the unfolded line text
- if s:settings.number_lines
- let s:new = s:new .. s:HtmlFormat_n(s:numcol, s:LINENR_ID, 0, s:lnum)
- elseif s:settings.line_ids
- let s:new = s:new .. s:HtmlFormat_n("", s:LINENR_ID, 0, s:lnum)
- endif
-
- " Get the diff attribute, if any.
- let s:diffattr = diff_hlID(s:lnum, 1)
-
- " initialize conceal info to act like not concealed, just in case
- let s:concealinfo = [0, '']
-
- " Loop over each character in the line
- let s:col = 1
-
- " most of the time we won't use the diff_id, initialize to zero
- let s:diff_id = 0
-
- while s:col <= s:len || (s:col == 1 && s:diffattr)
- let s:startcol = s:col " The start column for processing text
- if !s:settings.ignore_conceal && has('conceal')
- let s:concealinfo = synconcealed(s:lnum, s:col)
- endif
- if !s:settings.ignore_conceal && s:concealinfo[0]
- let s:col = s:col + 1
- " Speed loop (it's small - that's the trick)
- " Go along till we find a change in the match sequence number (ending
- " the specific concealed region) or until there are no more concealed
- " characters.
- while s:col <= s:len && s:concealinfo == synconcealed(s:lnum, s:col) | let s:col = s:col + 1 | endwhile
- elseif s:diffattr
- let s:diff_id = diff_hlID(s:lnum, s:col)
- let s:id = synID(s:lnum, s:col, 1)
- let s:col = s:col + 1
- " Speed loop (it's small - that's the trick)
- " Go along till we find a change in hlID
- while s:col <= s:len && s:id == synID(s:lnum, s:col, 1)
- \ && s:diff_id == diff_hlID(s:lnum, s:col) |
- \ let s:col = s:col + 1 |
- \ endwhile
- if s:len < &columns && !s:settings.no_pre
- " Add spaces at the end of the raw text line to extend the changed
- " line to the full width.
- let s:line = s:line .. repeat(' ', &columns - virtcol([s:lnum, s:len]) - s:margin)
- let s:len = &columns
- endif
- else
- let s:id = synID(s:lnum, s:col, 1)
- let s:col = s:col + 1
- " Speed loop (it's small - that's the trick)
- " Go along till we find a change in synID
- while s:col <= s:len && s:id == synID(s:lnum, s:col, 1) | let s:col = s:col + 1 | endwhile
- endif
-
- if s:settings.ignore_conceal || !s:concealinfo[0]
- " Expand tabs if needed
- let s:expandedtab = strpart(s:line, s:startcol - 1, s:col - s:startcol)
- if s:settings.expand_tabs
- let s:offset = 0
- let s:idx = stridx(s:expandedtab, "\t")
- let s:tablist = exists("+vts") ? split(&vts,',') : []
- if empty(s:tablist)
- let s:tablist = [ &ts ]
- endif
- let s:tabidx = 0
- let s:tabwidth = 0
- while s:idx >= 0
- if s:startcol + s:idx == 1
- let s:i = s:tablist[0]
- else
- " Get the character, which could be multiple bytes, which falls
- " immediately before the found tab. Extract it by matching a
- " character just prior to the column where the tab matches.
- " We'll use this to get the byte index of the character
- " immediately preceding the tab, so we can then look up the
- " virtual column that character appears in, to determine how
- " much of the current tabstop has been used up.
- if s:idx == 0
- " if the found tab is the first character in the text being
- " processed, we need to get the character prior to the text,
- " given by startcol.
- let s:prevc = matchstr(s:line, '.\%' .. (s:startcol + s:offset) .. 'c')
- else
- " Otherwise, the byte index of the tab into s:expandedtab is
- " given by s:idx.
- let s:prevc = matchstr(s:expandedtab, '.\%' .. (s:idx + 1) .. 'c')
- endif
- let s:vcol = virtcol([s:lnum, s:startcol + s:idx + s:offset - len(s:prevc)])
-
- " find the tabstop interval to use for the tab we just found. Keep
- " adding tabstops (which could be variable) until we would exceed
- " the virtual screen position of the start of the found tab.
- while s:vcol >= s:tabwidth + s:tablist[s:tabidx]
- let s:tabwidth += s:tablist[s:tabidx]
- if s:tabidx < len(s:tablist)-1
- let s:tabidx = s:tabidx+1
- endif
- endwhile
- let s:i = s:tablist[s:tabidx] - (s:vcol - s:tabwidth)
- endif
- " update offset to keep the index within the line corresponding to
- " actual tab characters instead of replaced spaces; s:idx reflects
- " replaced spaces in s:expandedtab, s:offset cancels out all but
- " the tab character itself.
- let s:offset -= s:i - 1
- let s:expandedtab = substitute(s:expandedtab, '\t', repeat(' ', s:i), '')
- let s:idx = stridx(s:expandedtab, "\t")
- endwhile
- end
-
- " get the highlight group name to use
- let s:id = synIDtrans(s:id)
- else
- " use Conceal highlighting for concealed text
- let s:id = s:CONCEAL_ID
- let s:expandedtab = s:concealinfo[1]
- endif
-
- " Output the text with the same synID, with class set to the highlight ID
- " name, unless it has been concealed completely.
- if strlen(s:expandedtab) > 0
- let s:new = s:new .. s:HtmlFormat(s:expandedtab, s:id, s:diff_id, "", 0)
- endif
- endwhile
- endif
-
- call extend(s:lines, split(s:new..s:HtmlEndline, '\n', 1))
- if !s:settings.no_progress && s:pgb.needs_redraw
- redrawstatus
- let s:pgb.needs_redraw = 0
- endif
- let s:lnum = s:lnum + 1
-
- if !s:settings.no_progress
- call s:pgb.incr()
- endif
-endwhile
-
-" Diff filler is returned based on what needs inserting *before* the given line.
-" So to get diff filler at the end of the buffer, we need to use last line + 1
-call s:Add_diff_fill(s:end+1)
-
-if s:settings.dynamic_folds
- " finish off any open folds
- while !empty(s:foldstack)
- let s:lines[-1]..="</span></span>"
- call remove(s:foldstack, 0)
- endwhile
-
- " add fold column to the style list if not already there
- let s:id = s:FOLD_C_ID
- if !has_key(s:stylelist, s:id)
- let s:stylelist[s:id] = '.FoldColumn { ' .. s:CSS1(s:id) .. '}'
- endif
-endif
-
-if s:settings.no_pre
- if !s:settings.use_css
- " Close off the font tag that encapsulates the whole <body>
- call extend(s:lines, ["</font>"])
- else
- call extend(s:lines, ["</div>"])
- endif
-else
- call extend(s:lines, ["</pre>"])
-endif
-if !s:settings.no_doc
- call extend(s:lines, ["</body>", "</html>"])
-endif
-
-exe s:newwin .. "wincmd w"
-call setline(1, s:lines)
-unlet s:lines
-
-" Mangle modelines so Vim doesn't try to use HTML text as a modeline if editing
-" this file in the future; need to do this after generating all the text in case
-" the modeline text has different highlight groups which all turn out to be
-" stripped from the final output.
-%s!\v(%(^|\s+)%([Vv]i%(m%([<=>]?\d+)?)?|ex)):!\1\&#0058;!ge
-
-" The generated HTML is admittedly ugly and takes a LONG time to fold.
-" Make sure the user doesn't do syntax folding when loading a generated file,
-" using a modeline.
-if !s:settings.no_modeline
- call append(line('$'), "<!-- vim: set foldmethod=manual : -->")
-endif
-
-" Now, when we finally know which, we define the colors and styles
-if s:settings.use_css && !s:settings.no_doc
- 1;/<style\>/+1
-
- " Normal/global attributes
- if s:settings.no_pre
- call append('.', "body { color: " .. s:fgc .. "; background-color: " .. s:bgc .. "; font-family: ".. s:htmlfont .."; }")
- +
- else
- call append('.', "pre { " .. s:whitespace .. "font-family: ".. s:htmlfont .."; color: " .. s:fgc .. "; background-color: " .. s:bgc .. "; }")
- +
- yank
- put
- execute "normal! ^cwbody\e"
- " body should not have the wrap formatting, only the pre section
- if s:whitespace != ''
- exec 's#'..s:whitespace
- endif
- endif
- " fix browser inconsistencies (sometimes within the same browser) of different
- " default font size for different elements
- call append('.', '* { font-size: 1em; }')
- +
- " if we use any input elements for unselectable content, make sure they look
- " like normal text
- if !empty(s:settings.prevent_copy)
- if s:settings.use_input_for_pc !=# "none"
- call append('.', 'input { border: none; margin: 0; padding: 0; font-family: '..s:htmlfont..'; }')
- +
- " ch units for browsers which support them, em units for a somewhat
- " reasonable fallback.
- for w in range(1, 20, 1)
- call append('.', [
- \ "input[size='"..w.."'] { width: "..w.."em; width: "..w.."ch; }"
- \ ])
- +
- endfor
- endif
-
- if s:settings.use_input_for_pc !=# 'all'
- let s:unselectable_styles = []
- if s:settings.prevent_copy =~# 'f'
- call add(s:unselectable_styles, 'FoldColumn')
- endif
- if s:settings.prevent_copy =~# 'n'
- call add(s:unselectable_styles, 'LineNr')
- endif
- if s:settings.prevent_copy =~# 't' && !s:settings.ignore_folding
- call add(s:unselectable_styles, 'Folded')
- endif
- if s:settings.prevent_copy =~# 'd'
- call add(s:unselectable_styles, 'DiffDelete')
- endif
- if s:settings.use_input_for_pc !=# 'none'
- call append('.', [
- \ '/* Note: IE does not support @supports conditionals, but also does not fully support',
- \ ' "content:" with custom content, so we *want* the check to fail */',
- \ '@supports ( content: attr(data-custom-content) ) {'
- \ ])
- +3
- endif
- " The line number column inside the foldtext is styled just like the fold
- " text in Vim, but it should use the prevent_copy settings of line number
- " rather than fold text. Apply the prevent_copy styles to foldtext
- " specifically for line numbers, which always come after the fold column,
- " or at the beginning of the line.
- if s:settings.prevent_copy =~# 'n' && !s:settings.ignore_folding
- call append('.', [
- \ ' .FoldColumn + .Folded, .Folded:first-child { user-select: none; }',
- \ ' .FoldColumn + [data-Folded-content]::before, [data-Folded-content]:first-child::before { content: attr(data-Folded-content); }',
- \ ' .FoldColumn + [data-Folded-content]::before, [data-Folded-content]:first-child::before { padding-bottom: 1px; display: inline-block; /* match the 1-px padding of standard items with background */ }',
- \ ' .FoldColumn + span[data-Folded-content]::before, [data-Folded-content]:first-child::before { cursor: default; }',
- \ ])
- +4
- endif
- for s:style_name in s:unselectable_styles
- call append('.', [
- \ ' .'..s:style_name..' { user-select: none; }',
- \ ' [data-'..s:style_name..'-content]::before { content: attr(data-'..s:style_name..'-content); }',
- \ ' [data-'..s:style_name..'-content]::before { padding-bottom: 1px; display: inline-block; /* match the 1-px padding of standard items with background */ }',
- \ ' span[data-'..s:style_name..'-content]::before { cursor: default; }',
- \ ])
- +4
- endfor
- if s:settings.use_input_for_pc !=# 'none'
- " Note, the extra '}' is to match the "@supports" above
- call append('.', [
- \ ' input { display: none; }',
- \ '}'
- \ ])
- +2
- endif
- unlet s:unselectable_styles
- endif
-
- " Fix mouse cursor shape for the fallback <input> method of uncopyable text
- if s:settings.use_input_for_pc !=# 'none'
- if s:settings.prevent_copy =~# 'f'
- " Make the cursor show active fold columns as active areas, and empty fold
- " columns as not interactive.
- call append('.', ['input.FoldColumn { cursor: pointer; }',
- \ 'input.FoldColumn[value="'..repeat(' ', s:foldcolumn)..'"] { cursor: default; }'
- \ ])
- +2
- if s:settings.use_input_for_pc !=# 'all'
- call append('.', [
- \ 'a[data-FoldColumn-content="'..repeat(' ', s:foldcolumn)..'"] { cursor: default; }'
- \ ])
- +1
- end
- endif
- " make line number column show as non-interactive if not selectable
- if s:settings.prevent_copy =~# 'n'
- call append('.', 'input.LineNr { cursor: default; }')
- +
- endif
- " make fold text and line number column within fold text show as
- " non-interactive if not selectable
- if (s:settings.prevent_copy =~# 'n' || s:settings.prevent_copy =~# 't') && !s:settings.ignore_folding
- call append('.', 'input.Folded { cursor: default; }')
- +
- endif
- " make diff filler show as non-interactive if not selectable
- if s:settings.prevent_copy =~# 'd'
- call append('.', 'input.DiffDelete { cursor: default; }')
- +
- endif
- endif
- endif
-endif
-
-if !s:settings.use_css && !s:settings.no_doc
- " For Netscape 4, set <body> attributes too, though, strictly speaking, it's
- " incorrect.
- execute '%s:<body\([^>]*\):<body bgcolor="' .. s:bgc .. '" text="' .. s:fgc .. '"\1>\r<font face="'.. s:htmlfont ..'"'
-endif
-
-" Gather attributes for all other classes. Do diff first so that normal
-" highlight groups are inserted before it.
-if s:settings.use_css && !s:settings.no_doc
- if s:diff_mode
- call append('.', filter(map(keys(s:diffstylelist), "s:diffstylelist[v:val]"), 'v:val != ""'))
- endif
- if !empty(s:stylelist)
- call append('.', filter(map(keys(s:stylelist), "s:stylelist[v:val]"), 'v:val != ""'))
- endif
-endif
-
-" Add hyperlinks
-if !s:settings.no_links
- %s+\(https\=://\S\{-}\)\(\([.,;:}]\=\(\s\|$\)\)\|[\\"'<>]\|&gt;\|&lt;\|&quot;\)+<a href="\1">\1</a>\2+ge
-endif
-
-" The DTD
-if !s:settings.no_doc
- if s:settings.use_xhtml
- exe "normal! gg$a\n<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
- elseif s:html5
- exe "normal! gg0i<!DOCTYPE html>\n"
- else
- exe "normal! gg0i<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\n"
- endif
-endif
-
-if s:settings.use_xhtml && !s:settings.no_doc
- exe "normal! gg/<html/e\na xmlns=\"http://www.w3.org/1999/xhtml\"\e"
-endif
-
-" Cleanup
-%s:\s\+$::e
-
-" Restore old settings (new window first)
-"
-" Don't bother restoring foldmethod in case it was syntax because the markup is
-" so weirdly formatted it can take a LONG time.
-let &l:foldenable = s:old_fen
-let &report = s:old_report
-let &title = s:old_title
-let &icon = s:old_icon
-let &paste = s:old_paste
-let &magic = s:old_magic
-let @/ = s:old_search
-let &more = s:old_more
-
-" switch to original window to restore those settings
-exe s:orgwin .. "wincmd w"
-
-if !s:settings.expand_tabs
- let &l:isprint = s:old_isprint
-endif
-let &l:stl = s:origwin_stl
-let &l:et = s:old_et
-let &l:scrollbind = s:old_bind
-
-" and back to the new window again to end there
-exe s:newwin .. "wincmd w"
-
-let &l:stl = s:newwin_stl
-exec 'resize' s:old_winheight
-let &l:winfixheight = s:old_winfixheight
-
-let &ls=s:ls
-let &eventignore=s:ei_sav
-
-" Save a little bit of memory (worth doing?)
-unlet s:htmlfont s:whitespace
-unlet s:old_et s:old_paste s:old_icon s:old_report s:old_title s:old_search
-unlet s:old_magic s:old_more s:old_fen s:old_winheight
-unlet! s:old_isprint
-unlet s:whatterm s:stylelist s:diffstylelist s:lnum s:end s:margin s:fgc s:bgc s:old_winfixheight
-unlet! s:col s:id s:attr s:len s:line s:new s:expandedtab s:concealinfo s:diff_mode
-unlet! s:orgwin s:newwin s:orgbufnr s:idx s:i s:offset s:ls s:ei_sav s:origwin_stl
-unlet! s:newwin_stl s:current_syntax
-if !v:profiling
- delfunc s:HtmlColor
- delfunc s:HtmlFormat
- delfunc s:CSS1
- delfunc s:BuildStyleWrapper
- if !s:settings.use_css
- delfunc s:HtmlOpening
- delfunc s:HtmlClosing
- endif
- if s:settings.dynamic_folds
- delfunc s:FoldCompare
- endif
-
- if !s:settings.no_progress
- delfunc s:ProgressBar
- delfunc s:progressbar.paint
- delfunc s:progressbar.incr
- unlet s:pgb s:progressbar
- endif
-
- delfunc s:Add_diff_fill
-endif
-
-unlet! s:new_lnum s:diffattr s:difffillchar s:foldfillchar s:HtmlSpace s:diffstyle
-unlet! s:LeadingSpace s:HtmlEndline s:firstfold s:numcol s:foldcolumn
-unlet! s:wrapperfunc_lines s:build_fun_lines
-unlet s:foldstack s:allfolds s:foldId s:settings
-
-let &cpo = s:cpo_sav
-unlet! s:cpo_sav
-
-" Make sure any patches will probably use consistent indent
-" vim: ts=8 sw=2 sts=2 noet
diff --git a/runtime/syntax/8th.vim b/runtime/syntax/8th.vim
index 643c9cb095..a88a5a294a 100644
--- a/runtime/syntax/8th.vim
+++ b/runtime/syntax/8th.vim
@@ -1,26 +1,26 @@
" Vim syntax file
" Language: 8th
-" Version: 21.08
-" Last Change: 2021 Sep 20
+" Version: 23.09.01
+" Last Change: 2023 Dec 19
" Maintainer: Ron Aaron <ron@aaron-tech.com>
" URL: https://8th-dev.com/
" Filetypes: *.8th
" NOTE: You should also have the ftplugin/8th.vim file to set 'isk'
-if version < 600
- syntax clear
- finish
-elseif exists("b:current_syntax")
+if exists("b:current_syntax")
finish
endif
let s:cpo_save = &cpo
set cpo&vim
syn clear
-" Synchronization method
+
syn sync ccomment
-syn sync maxlines=100
+syn sync maxlines=200
+
syn case match
+syn iskeyword 33-255
+
syn match eighthColonName "\S\+" contained
syn match eighthColonDef ":\s\+\S\+" contains=eighthColonName
@@ -34,230 +34,257 @@ syn keyword eighthDefine var var,
" Built in words:
com! -nargs=+ Builtin syn keyword eighthBuiltin <args>
-Builtin args #:args b #:b dhm #:dhm exec# #:exec# id2ns #:id2ns id? #:id? idd #:idd key #:key oa #:oa
-Builtin oid #:oid okey #:okey with #:with with! #:with! zip #:zip gen-secret 2fa:gen-secret gen-url 2fa:gen-url
-Builtin validate-code 2fa:validate-code ! G:! #! G:#! ## G:## #> G:#> #if G:#if ' G:' ( G:( (* G:(*
-Builtin (:) G:(:) (code) G:(code) (defer) G:(defer) (dump) G:(dump) (getc) G:(getc) (gets) G:(gets)
+
+Builtin gen-secret 2fa:gen-secret gen-url 2fa:gen-url validate-code 2fa:validate-code cb AWS:cb cli AWS:cli
+Builtin cmd AWS:cmd cp AWS:cp rc AWS:rc call DBUS:call init DBUS:init + DOM:+ - DOM:- attr! DOM:attr!
+Builtin attr@ DOM:attr@ attrs DOM:attrs children DOM:children css-parse DOM:css-parse each DOM:each
+Builtin find DOM:find new DOM:new type DOM:type ! G:! !if G:!if #! G:#! ## G:## #if G:#if ' G:' ( G:(
+Builtin (* G:(* (:) G:(:) (code) G:(code) (defer) G:(defer) (dump) G:(dump) (getc) G:(getc) (gets) G:(gets)
Builtin (interp) G:(interp) (log) G:(log) (needs) G:(needs) (parseln) G:(parseln) (putc) G:(putc) (puts) G:(puts)
-Builtin (putslim) G:(putslim) (stat) G:(stat) (with) G:(with) ) G:) +hook G:+hook +listener G:+listener
-Builtin +ref G:+ref ,# G:,# -- G:-- -----BEGIN G:-----BEGIN -Inf G:-Inf -Inf? G:-Inf? -hook G:-hook
-Builtin -listener G:-listener -ref G:-ref -rot G:-rot . G:. .# G:.# .hook G:.hook .needs G:.needs .r G:.r
-Builtin .s G:.s .s-truncate G:.s-truncate .stats G:.stats .ver G:.ver .with G:.with 0; G:0; 2dip G:2dip
-Builtin 2drop G:2drop 2dup G:2dup 2over G:2over 2swap G:2swap 3drop G:3drop 3rev G:3rev 4drop G:4drop
-Builtin 8thdt? G:8thdt? 8thsku G:8thsku 8thver? G:8thver? 8thvernum? G:8thvernum? : G:: ; G:; ;; G:;;
-Builtin ;;; G:;;; ;with G:;with <# G:<# <#> G:<#> >clip G:>clip >json G:>json >kind G:>kind >n G:>n
-Builtin >r G:>r >s G:>s ?: G:?: @ G:@ BITMAP: G:BITMAP: ENUM: G:ENUM: FLAG: G:FLAG: Inf G:Inf Inf? G:Inf?
-Builtin NaN G:NaN NaN? G:NaN? SED-CHECK G:SED-CHECK SED: G:SED: SED: G:SED: \ G:\ _dup G:_dup _swap G:_swap
-Builtin actor: G:actor: again G:again ahead G:ahead and G:and appname G:appname apropos G:apropos argc G:argc
-Builtin args G:args array? G:array? assert G:assert base G:base bi G:bi bits G:bits break G:break break? G:break?
-Builtin breakif G:breakif build? G:build? buildver? G:buildver? bye G:bye c# G:c# c/does G:c/does case: G:case:
-Builtin catch G:catch chdir G:chdir clip> G:clip> clone G:clone clone-shallow G:clone-shallow cold G:cold
-Builtin compile G:compile compile? G:compile? compiling? G:compiling? conflict G:conflict const G:const
-Builtin container? G:container? counting-allocations G:counting-allocations cr G:cr curlang G:curlang
-Builtin curry G:curry curry: G:curry: decimal G:decimal default: G:default: defer: G:defer: deferred: G:deferred:
-Builtin deg>rad G:deg>rad depth G:depth die G:die dip G:dip drop G:drop dstack G:dstack dump G:dump
-Builtin dup G:dup dup>r G:dup>r dup? G:dup? e# G:e# enum: G:enum: error? G:error? eval G:eval eval! G:eval!
-Builtin eval0 G:eval0 execnull G:execnull expect G:expect extra! G:extra! extra@ G:extra@ false G:false
-Builtin fnv G:fnv fourth G:fourth free G:free func: G:func: getc G:getc getcwd G:getcwd getenv G:getenv
-Builtin gets G:gets handler G:handler header G:header help G:help hex G:hex i: G:i: i; G:i; isa? G:isa?
-Builtin items-used G:items-used jcall G:jcall jclass G:jclass jmethod G:jmethod json! G:json! json-8th> G:json-8th>
-Builtin json-nesting G:json-nesting json-pretty G:json-pretty json-throw G:json-throw json> G:json>
-Builtin json@ G:json@ k32 G:k32 keep G:keep l: G:l: last G:last lib G:lib libbin G:libbin libc G:libc
-Builtin listener@ G:listener@ literal G:literal locals: G:locals: lock G:lock lock-to G:lock-to locked? G:locked?
-Builtin log G:log log-syslog G:log-syslog log-task G:log-task log-time G:log-time log-time-local G:log-time-local
-Builtin long-days G:long-days long-months G:long-months longjmp G:longjmp lookup G:lookup loop G:loop
-Builtin loop- G:loop- map? G:map? mark G:mark mark? G:mark? memfree G:memfree mobile? G:mobile? n# G:n#
-Builtin name>os G:name>os name>sem G:name>sem ndrop G:ndrop needs G:needs new G:new next-arg G:next-arg
-Builtin nip G:nip noop G:noop not G:not nothrow G:nothrow ns G:ns ns: G:ns: ns>ls G:ns>ls ns>s G:ns>s
-Builtin ns? G:ns? null G:null null; G:null; null? G:null? number? G:number? of: G:of: off G:off on G:on
-Builtin onexit G:onexit only G:only op! G:op! or G:or os G:os os-names G:os-names os>long-name G:os>long-name
-Builtin os>name G:os>name over G:over p: G:p: pack G:pack parse G:parse parse-csv G:parse-csv parsech G:parsech
-Builtin parseln G:parseln parsews G:parsews pick G:pick poke G:poke pool-clear G:pool-clear pool-clear-all G:pool-clear-all
+Builtin (stat) G:(stat) (with) G:(with) ) G:) +hook G:+hook +ref G:+ref ,# G:,# -- G:-- -----BEGIN G:-----BEGIN
+Builtin -Inf G:-Inf -Inf? G:-Inf? -hook G:-hook -ref G:-ref -rot G:-rot . G:. .# G:.# .hook G:.hook
+Builtin .needs G:.needs .r G:.r .s G:.s .s-truncate G:.s-truncate .stats G:.stats .ver G:.ver .with G:.with
+Builtin 0; G:0; 2dip G:2dip 2drop G:2drop 2dup G:2dup 2nip G:2nip 2over G:2over 2swap G:2swap 2tuck G:2tuck
+Builtin 3drop G:3drop 3drop G:3drop 3dup G:3dup 3rev G:3rev 4drop G:4drop 8thdt? G:8thdt? 8thsku G:8thsku
+Builtin 8thver? G:8thver? 8thvernum? G:8thvernum? : G:: ; G:; ;; G:;; ;;; G:;;; ;with G:;with >clip G:>clip
+Builtin >json G:>json >kind G:>kind >n G:>n >r G:>r >s G:>s ?: G:?: ?@ G:?@ @ G:@ BITMAP: G:BITMAP:
+Builtin ENUM: G:ENUM: FLAG: G:FLAG: I G:I Inf G:Inf Inf? G:Inf? J G:J K G:K NaN G:NaN NaN? G:NaN? SED-CHECK G:SED-CHECK
+Builtin SED: G:SED: SED: G:SED: X G:X \ G:\ _dup G:_dup _swap G:_swap actor: G:actor: again G:again
+Builtin ahead G:ahead and G:and apropos G:apropos argc G:argc args G:args array? G:array? assert G:assert
+Builtin base G:base base>n G:base>n bi G:bi bits G:bits break G:break break? G:break? breakif G:breakif
+Builtin build? G:build? buildver? G:buildver? bye G:bye c/does G:c/does case: G:case: catch G:catch
+Builtin chdir G:chdir clip> G:clip> clone G:clone clone-shallow G:clone-shallow cold G:cold compile G:compile
+Builtin compile? G:compile? compiling? G:compiling? conflict G:conflict const G:const container? G:container?
+Builtin counting-allocations G:counting-allocations cr G:cr critical: G:critical: critical; G:critical;
+Builtin curlang G:curlang curry G:curry curry: G:curry: decimal G:decimal default: G:default: defer: G:defer:
+Builtin deferred: G:deferred: deg>rad G:deg>rad depth G:depth die G:die dip G:dip drop G:drop dstack G:dstack
+Builtin dump G:dump dup G:dup dup>r G:dup>r dup? G:dup? e# G:e# enum: G:enum: error? G:error? eval G:eval
+Builtin eval! G:eval! eval0 G:eval0 expect G:expect extra! G:extra! extra@ G:extra@ false G:false fnv G:fnv
+Builtin fourth G:fourth free G:free func: G:func: getc G:getc getcwd G:getcwd getenv G:getenv gets G:gets
+Builtin handler G:handler header G:header help G:help hex G:hex i: G:i: i; G:i; isa? G:isa? items-used G:items-used
+Builtin jcall G:jcall jclass G:jclass jmethod G:jmethod json! G:json! json-8th> G:json-8th> json-nesting G:json-nesting
+Builtin json-pretty G:json-pretty json-throw G:json-throw json> G:json> json@ G:json@ k32 G:k32 keep G:keep
+Builtin l: G:l: last G:last lib G:lib libbin G:libbin libc G:libc literal G:literal locals: G:locals:
+Builtin lock G:lock lock-to G:lock-to locked? G:locked? log G:log log-syslog G:log-syslog log-task G:log-task
+Builtin log-time G:log-time log-time-local G:log-time-local long-days G:long-days long-months G:long-months
+Builtin longjmp G:longjmp lookup G:lookup loop G:loop loop- G:loop- map? G:map? mark G:mark mark? G:mark?
+Builtin mobile? G:mobile? n# G:n# name>os G:name>os name>sem G:name>sem ndrop G:ndrop needs G:needs
+Builtin new G:new next-arg G:next-arg nip G:nip noop G:noop not G:not nothrow G:nothrow ns G:ns ns: G:ns:
+Builtin ns>ls G:ns>ls ns>s G:ns>s ns? G:ns? null G:null null; G:null; null? G:null? nullvar G:nullvar
+Builtin number? G:number? of: G:of: off G:off on G:on onexit G:onexit only G:only op! G:op! or G:or
+Builtin os G:os os-names G:os-names os>long-name G:os>long-name os>name G:os>name over G:over p: G:p:
+Builtin pack G:pack parse G:parse parse-csv G:parse-csv parse-date G:parse-date parsech G:parsech parseln G:parseln
+Builtin parsews G:parsews pick G:pick poke G:poke pool-clear G:pool-clear pool-clear-all G:pool-clear-all
Builtin prior G:prior private G:private process-args G:process-args process-args-fancy G:process-args-fancy
Builtin process-args-help G:process-args-help process-args-vars G:process-args-vars prompt G:prompt
-Builtin public G:public putc G:putc puts G:puts putslim G:putslim quote G:quote r! G:r! r> G:r> r@ G:r@
-Builtin rad>deg G:rad>deg rand-jit G:rand-jit rand-jsf G:rand-jsf rand-native G:rand-native rand-normal G:rand-normal
+Builtin public G:public putc G:putc puts G:puts quote G:quote r! G:r! r> G:r> r@ G:r@ rad>deg G:rad>deg
+Builtin rand-jit G:rand-jit rand-jsf G:rand-jsf rand-native G:rand-native rand-normal G:rand-normal
Builtin rand-pcg G:rand-pcg rand-pcg-seed G:rand-pcg-seed rand-range G:rand-range rand-select G:rand-select
Builtin randbuf-pcg G:randbuf-pcg random G:random rdrop G:rdrop recurse G:recurse recurse-stack G:recurse-stack
Builtin ref@ G:ref@ reg! G:reg! reg@ G:reg@ regbin@ G:regbin@ remaining-args G:remaining-args repeat G:repeat
Builtin required? G:required? requires G:requires reset G:reset roll G:roll rop! G:rop! rot G:rot rpick G:rpick
-Builtin rroll G:rroll rstack G:rstack rswap G:rswap rusage G:rusage s>ns G:s>ns same? G:same? scriptdir G:scriptdir
-Builtin scriptfile G:scriptfile sem G:sem sem-post G:sem-post sem-rm G:sem-rm sem-wait G:sem-wait sem-wait? G:sem-wait?
-Builtin sem>name G:sem>name semi-throw G:semi-throw set-wipe G:set-wipe setenv G:setenv setjmp G:setjmp
-Builtin settings! G:settings! settings![] G:settings![] settings@ G:settings@ settings@? G:settings@?
-Builtin settings@[] G:settings@[] sh G:sh sh$ G:sh$ short-days G:short-days short-months G:short-months
-Builtin sleep G:sleep sleep-until G:sleep-until slog G:slog space G:space stack-check G:stack-check
-Builtin stack-size G:stack-size step G:step sthrow G:sthrow string? G:string? struct: G:struct: swap G:swap
-Builtin tab-hook G:tab-hook tell-conflict G:tell-conflict tempdir G:tempdir tempfilename G:tempfilename
-Builtin third G:third throw G:throw thrownull G:thrownull times G:times tlog G:tlog tri G:tri true G:true
-Builtin tuck G:tuck type-check G:type-check typeassert G:typeassert uid G:uid uname G:uname unlock G:unlock
-Builtin unpack G:unpack until G:until until! G:until! while G:while while! G:while! with: G:with: word? G:word?
-Builtin words G:words words-like G:words-like words/ G:words/ xchg G:xchg xor G:xor >auth HTTP:>auth
-Builtin (curry) I:(curry) notimpl I:notimpl sh I:sh trace-word I:trace-word call JSONRPC:call auth-string OAuth:auth-string
-Builtin gen-nonce OAuth:gen-nonce params OAuth:params call SOAP:call ! a:! + a:+ - a:- / a:/ 2each a:2each
-Builtin 2map a:2map 2map+ a:2map+ 2map= a:2map= = a:= @ a:@ @? a:@? _@ a:_@ all a:all any a:any bsearch a:bsearch
-Builtin centroid a:centroid clear a:clear close a:close diff a:diff dot a:dot each a:each each! a:each!
-Builtin each-slice a:each-slice exists? a:exists? filter a:filter generate a:generate group a:group
-Builtin indexof a:indexof insert a:insert intersect a:intersect join a:join len a:len map a:map map+ a:map+
-Builtin map= a:map= mean a:mean mean&variance a:mean&variance merge a:merge new a:new op! a:op! open a:open
-Builtin pop a:pop push a:push qsort a:qsort randeach a:randeach reduce a:reduce reduce+ a:reduce+ remove a:remove
-Builtin rev a:rev shift a:shift shuffle a:shuffle slice a:slice slice+ a:slice+ slide a:slide smear a:smear
-Builtin sort a:sort union a:union x a:x x-each a:x-each xchg a:xchg y a:y zip a:zip 8thdir app:8thdir
-Builtin asset app:asset atrun app:atrun atrun app:atrun atrun app:atrun basedir app:basedir current app:current
-Builtin datadir app:datadir exename app:exename lowmem app:lowmem main app:main name app:name oncrash app:oncrash
+Builtin rreset G:rreset rroll G:rroll rstack G:rstack rswap G:rswap rusage G:rusage s>ns G:s>ns same? G:same?
+Builtin scriptdir G:scriptdir scriptfile G:scriptfile sem G:sem sem-post G:sem-post sem-rm G:sem-rm
+Builtin sem-wait G:sem-wait sem-wait? G:sem-wait? sem>name G:sem>name semi-throw G:semi-throw set-wipe G:set-wipe
+Builtin setenv G:setenv setjmp G:setjmp settings! G:settings! settings![] G:settings![] settings@ G:settings@
+Builtin settings@? G:settings@? settings@[] G:settings@[] sh G:sh sh$ G:sh$ short-days G:short-days
+Builtin short-months G:short-months sleep G:sleep sleep-msec G:sleep-msec sleep-until G:sleep-until
+Builtin slog G:slog space G:space stack-check G:stack-check stack-size G:stack-size step G:step sthrow G:sthrow
+Builtin string? G:string? struct: G:struct: swap G:swap tab-hook G:tab-hook tell-conflict G:tell-conflict
+Builtin tempdir G:tempdir tempfilename G:tempfilename third G:third throw G:throw thrownull G:thrownull
+Builtin times G:times tlog G:tlog tri G:tri true G:true tuck G:tuck type-check G:type-check typeassert G:typeassert
+Builtin uid G:uid uname G:uname unlock G:unlock unpack G:unpack until G:until until! G:until! while G:while
+Builtin while! G:while! with: G:with: word? G:word? words G:words words-like G:words-like words/ G:words/
+Builtin xchg G:xchg xor G:xor >auth HTTP:>auth (curry) I:(curry) notimpl I:notimpl sh I:sh trace-word I:trace-word
+Builtin call JSONRPC:call auth-string OAuth:auth-string gen-nonce OAuth:gen-nonce params OAuth:params
+Builtin call SOAP:call ! a:! + a:+ - a:- / a:/ 2each a:2each 2map a:2map 2map+ a:2map+ 2map= a:2map=
+Builtin <> a:<> = a:= @ a:@ @? a:@? _@ a:_@ all a:all any a:any bsearch a:bsearch centroid a:centroid
+Builtin clear a:clear close a:close cmp a:cmp diff a:diff dot a:dot each a:each each! a:each! each-par a:each-par
+Builtin each-slice a:each-slice exists? a:exists? filter a:filter filter-par a:filter-par generate a:generate
+Builtin group a:group indexof a:indexof insert a:insert intersect a:intersect join a:join len a:len
+Builtin map a:map map+ a:map+ map-par a:map-par map= a:map= maxlen a:maxlen mean a:mean mean&variance a:mean&variance
+Builtin merge a:merge new a:new op! a:op! open a:open pigeon a:pigeon pivot a:pivot pop a:pop push a:push
+Builtin qsort a:qsort randeach a:randeach reduce a:reduce reduce+ a:reduce+ remove a:remove rev a:rev
+Builtin rindexof a:rindexof shift a:shift shuffle a:shuffle slice a:slice slice+ a:slice+ slide a:slide
+Builtin smear a:smear sort a:sort split a:split squash a:squash switch a:switch union a:union uniq a:uniq
+Builtin unzip a:unzip x a:x x-each a:x-each xchg a:xchg y a:y zip a:zip 8thdir app:8thdir asset app:asset
+Builtin atrun app:atrun atrun app:atrun atrun app:atrun basedir app:basedir basename app:basename config-file-name app:config-file-name
+Builtin current app:current datadir app:datadir display-moved app:display-moved exename app:exename
+Builtin localechanged app:localechanged lowmem app:lowmem main app:main name app:name oncrash app:oncrash
Builtin opts! app:opts! opts@ app:opts@ orientation app:orientation orientation! app:orientation! pid app:pid
-Builtin post-main app:post-main pre-main app:pre-main raise app:raise request-perm app:request-perm
+Builtin post-main app:post-main pre-main app:pre-main privdir app:privdir raise app:raise read-config app:read-config
+Builtin read-config-map app:read-config-map read-config-var app:read-config-var request-perm app:request-perm
Builtin restart app:restart resumed app:resumed signal app:signal standalone app:standalone subdir app:subdir
-Builtin suspended app:suspended sysquit app:sysquit terminated app:terminated trap app:trap (here) asm:(here)
-Builtin >n asm:>n avail asm:avail c, asm:c, here! asm:here! n> asm:n> used asm:used w, asm:w, ! b:!
-Builtin + b:+ / b:/ 1+ b:1+ 1- b:1- = b:= >base16 b:>base16 >base32 b:>base32 >base64 b:>base64 >base85 b:>base85
-Builtin >hex b:>hex >mpack b:>mpack @ b:@ append b:append base16> b:base16> base32> b:base32> base64> b:base64>
-Builtin base85> b:base85> bit! b:bit! bit@ b:bit@ clear b:clear compress b:compress conv b:conv each b:each
-Builtin each! b:each! each-slice b:each-slice expand b:expand fill b:fill getb b:getb hex> b:hex> len b:len
-Builtin mem> b:mem> move b:move mpack-compat b:mpack-compat mpack-date b:mpack-date mpack-ignore b:mpack-ignore
-Builtin mpack> b:mpack> n! b:n! n+ b:n+ n@ b:n@ new b:new op b:op pad b:pad rev b:rev search b:search
-Builtin shmem b:shmem slice b:slice splice b:splice ungetb b:ungetb unpad b:unpad writable b:writable
-Builtin xor b:xor +block bc:+block .blocks bc:.blocks add-block bc:add-block block-hash bc:block-hash
-Builtin block@ bc:block@ first-block bc:first-block hash bc:hash last-block bc:last-block load bc:load
-Builtin new bc:new save bc:save set-sql bc:set-sql validate bc:validate validate-block bc:validate-block
-Builtin add bloom:add filter bloom:filter in? bloom:in? accept bt:accept ch! bt:ch! ch@ bt:ch@ connect bt:connect
-Builtin disconnect bt:disconnect init bt:init leconnect bt:leconnect lescan bt:lescan listen bt:listen
-Builtin on? bt:on? read bt:read scan bt:scan service? bt:service? services? bt:services? write bt:write
-Builtin * c:* * c:* + c:+ + c:+ = c:= = c:= >ri c:>ri >ri c:>ri abs c:abs abs c:abs arg c:arg arg c:arg
-Builtin conj c:conj conj c:conj im c:im n> c:n> new c:new new c:new re c:re >redir con:>redir accept con:accept
-Builtin accept-pwd con:accept-pwd ansi? con:ansi? black con:black blue con:blue clreol con:clreol cls con:cls
-Builtin cyan con:cyan down con:down free con:free getxy con:getxy gotoxy con:gotoxy green con:green
-Builtin key con:key key? con:key? left con:left load-history con:load-history magenta con:magenta onBlack con:onBlack
-Builtin onBlue con:onBlue onCyan con:onCyan onGreen con:onGreen onMagenta con:onMagenta onRed con:onRed
-Builtin onWhite con:onWhite onYellow con:onYellow print con:print red con:red redir> con:redir> redir? con:redir?
-Builtin right con:right save-history con:save-history size? con:size? up con:up white con:white yellow con:yellow
-Builtin >aes128gcm cr:>aes128gcm >aes256gcm cr:>aes256gcm >cp cr:>cp >cpe cr:>cpe >decrypt cr:>decrypt
-Builtin >edbox cr:>edbox >encrypt cr:>encrypt >nbuf cr:>nbuf >rsabox cr:>rsabox >uuid cr:>uuid CBC cr:CBC
-Builtin CFB cr:CFB CTR cr:CTR ECB cr:ECB GCM cr:GCM OFB cr:OFB aad? cr:aad? aes128box-sig cr:aes128box-sig
-Builtin aes128gcm> cr:aes128gcm> aes256box-sig cr:aes256box-sig aes256gcm> cr:aes256gcm> aesgcm cr:aesgcm
-Builtin blakehash cr:blakehash chacha20box-sig cr:chacha20box-sig chachapoly cr:chachapoly cipher! cr:cipher!
-Builtin cipher@ cr:cipher@ cp> cr:cp> cpe> cr:cpe> decrypt cr:decrypt decrypt+ cr:decrypt+ decrypt> cr:decrypt>
-Builtin dh-genkey cr:dh-genkey dh-secret cr:dh-secret dh-sign cr:dh-sign dh-verify cr:dh-verify ebox-sig cr:ebox-sig
-Builtin ecc-genkey cr:ecc-genkey ecc-secret cr:ecc-secret ecc-sign cr:ecc-sign ecc-verify cr:ecc-verify
-Builtin edbox-sig cr:edbox-sig edbox> cr:edbox> encrypt cr:encrypt encrypt+ cr:encrypt+ encrypt> cr:encrypt>
-Builtin ensurekey cr:ensurekey gcm-tag-size cr:gcm-tag-size genkey cr:genkey hash cr:hash hash! cr:hash!
-Builtin hash+ cr:hash+ hash>b cr:hash>b hash>s cr:hash>s hash@ cr:hash@ hmac cr:hmac hotp cr:hotp iv? cr:iv?
-Builtin mode cr:mode mode@ cr:mode@ rand cr:rand randbuf cr:randbuf randkey cr:randkey restore cr:restore
+Builtin suspended app:suspended sysquit app:sysquit terminated app:terminated timeout app:timeout trap app:trap
+Builtin dawn astro:dawn do-dawn astro:do-dawn do-dusk astro:do-dusk do-rise astro:do-rise dusk astro:dusk
+Builtin latitude astro:latitude location! astro:location! longitude astro:longitude sunrise astro:sunrise
+Builtin genkeys auth:genkeys secret auth:secret session-id auth:session-id session-key auth:session-key
+Builtin validate auth:validate ! b:! + b:+ / b:/ 1+ b:1+ 1- b:1- <> b:<> = b:= >base16 b:>base16 >base32 b:>base32
+Builtin >base64 b:>base64 >base85 b:>base85 >hex b:>hex >mpack b:>mpack @ b:@ append b:append base16> b:base16>
+Builtin base32> b:base32> base64> b:base64> base85> b:base85> bit! b:bit! bit@ b:bit@ clear b:clear
+Builtin compress b:compress conv b:conv each b:each each! b:each! each-slice b:each-slice expand b:expand
+Builtin fill b:fill getb b:getb hex> b:hex> len b:len mem> b:mem> move b:move mpack-compat b:mpack-compat
+Builtin mpack-date b:mpack-date mpack-ignore b:mpack-ignore mpack> b:mpack> n! b:n! n+ b:n+ n@ b:n@
+Builtin new b:new op b:op op! b:op! pad b:pad rev b:rev search b:search shmem b:shmem slice b:slice
+Builtin splice b:splice ungetb b:ungetb unpad b:unpad writable b:writable xor b:xor +block bc:+block
+Builtin .blocks bc:.blocks add-block bc:add-block block-hash bc:block-hash block@ bc:block@ first-block bc:first-block
+Builtin hash bc:hash last-block bc:last-block load bc:load new bc:new save bc:save set-sql bc:set-sql
+Builtin validate bc:validate validate-block bc:validate-block add bloom:add filter bloom:filter in? bloom:in?
+Builtin parse bson:parse accept bt:accept ch! bt:ch! ch@ bt:ch@ connect bt:connect disconnect bt:disconnect
+Builtin init bt:init leconnect bt:leconnect lescan bt:lescan listen bt:listen on? bt:on? read bt:read
+Builtin scan bt:scan service? bt:service? services? bt:services? write bt:write * c:* * c:* + c:+ + c:+
+Builtin = c:= = c:= >ri c:>ri >ri c:>ri abs c:abs abs c:abs arg c:arg arg c:arg conj c:conj conj c:conj
+Builtin im c:im n> c:n> new c:new new c:new re c:re (.hebrew) cal:(.hebrew) (.islamic) cal:(.islamic)
+Builtin .hebrew cal:.hebrew .islamic cal:.islamic >hebepoch cal:>hebepoch >jdn cal:>jdn Adar cal:Adar
+Builtin Adar2 cal:Adar2 Adar2 cal:Adar2 Av cal:Av Elul cal:Elul Heshvan cal:Heshvan Iyar cal:Iyar Kislev cal:Kislev
+Builtin Nissan cal:Nissan Shevat cal:Shevat Sivan cal:Sivan Tammuz cal:Tammuz Tevet cal:Tevet Tishrei cal:Tishrei
+Builtin days-in-hebrew-year cal:days-in-hebrew-year displaying-hebrew cal:displaying-hebrew fixed>hebrew cal:fixed>hebrew
+Builtin fixed>islamic cal:fixed>islamic gershayim cal:gershayim hanukkah cal:hanukkah hebrew-epoch cal:hebrew-epoch
+Builtin hebrew>fixed cal:hebrew>fixed hebrewtoday cal:hebrewtoday hmonth-name cal:hmonth-name islamic.epoch cal:islamic.epoch
+Builtin islamic>fixed cal:islamic>fixed islamictoday cal:islamictoday jdn> cal:jdn> last-day-of-hebrew-month cal:last-day-of-hebrew-month
+Builtin number>hebrew cal:number>hebrew omer cal:omer pesach cal:pesach purim cal:purim rosh-chodesh? cal:rosh-chodesh?
+Builtin rosh-hashanah cal:rosh-hashanah shavuot cal:shavuot taanit-esther cal:taanit-esther tisha-beav cal:tisha-beav
+Builtin yom-haatsmaut cal:yom-haatsmaut yom-kippur cal:yom-kippur >redir con:>redir accept con:accept
+Builtin accept-nl con:accept-nl accept-pwd con:accept-pwd alert con:alert ansi? con:ansi? black con:black
+Builtin blue con:blue clreol con:clreol cls con:cls ctrld-empty con:ctrld-empty cyan con:cyan down con:down
+Builtin file>history con:file>history free con:free getxy con:getxy gotoxy con:gotoxy green con:green
+Builtin history-handler con:history-handler history>file con:history>file key con:key key? con:key?
+Builtin left con:left load-history con:load-history magenta con:magenta max-history con:max-history
+Builtin onBlack con:onBlack onBlue con:onBlue onCyan con:onCyan onGreen con:onGreen onMagenta con:onMagenta
+Builtin onRed con:onRed onWhite con:onWhite onYellow con:onYellow print con:print red con:red redir> con:redir>
+Builtin redir? con:redir? right con:right save-history con:save-history size? con:size? up con:up white con:white
+Builtin yellow con:yellow >aes128gcm cr:>aes128gcm >aes256gcm cr:>aes256gcm >cp cr:>cp >cpe cr:>cpe
+Builtin >decrypt cr:>decrypt >edbox cr:>edbox >encrypt cr:>encrypt >nbuf cr:>nbuf >rsabox cr:>rsabox
+Builtin >uuid cr:>uuid aad? cr:aad? aes128box-sig cr:aes128box-sig aes128gcm> cr:aes128gcm> aes256box-sig cr:aes256box-sig
+Builtin aes256gcm> cr:aes256gcm> aesgcm cr:aesgcm blakehash cr:blakehash chacha20box-sig cr:chacha20box-sig
+Builtin chachapoly cr:chachapoly cipher! cr:cipher! cipher@ cr:cipher@ ciphers cr:ciphers cp> cr:cp>
+Builtin cpe> cr:cpe> decrypt cr:decrypt decrypt+ cr:decrypt+ decrypt> cr:decrypt> ebox-sig cr:ebox-sig
+Builtin ecc-curves cr:ecc-curves ecc-genkey cr:ecc-genkey ecc-secret cr:ecc-secret ecc-sign cr:ecc-sign
+Builtin ecc-verify cr:ecc-verify ed25519 cr:ed25519 ed25519-secret cr:ed25519-secret ed25519-sign cr:ed25519-sign
+Builtin ed25519-verify cr:ed25519-verify edbox-sig cr:edbox-sig edbox> cr:edbox> encrypt cr:encrypt
+Builtin encrypt+ cr:encrypt+ encrypt> cr:encrypt> ensurekey cr:ensurekey genkey cr:genkey hash cr:hash
+Builtin hash! cr:hash! hash+ cr:hash+ hash>b cr:hash>b hash>s cr:hash>s hash@ cr:hash@ hashes cr:hashes
+Builtin hmac cr:hmac hotp cr:hotp iv? cr:iv? pem-read cr:pem-read pem-write cr:pem-write pwd-valid? cr:pwd-valid?
+Builtin pwd/ cr:pwd/ pwd>hash cr:pwd>hash rand cr:rand randbuf cr:randbuf randkey cr:randkey restore cr:restore
Builtin root-certs cr:root-certs rsa_decrypt cr:rsa_decrypt rsa_encrypt cr:rsa_encrypt rsa_sign cr:rsa_sign
Builtin rsa_verify cr:rsa_verify rsabox-sig cr:rsabox-sig rsabox> cr:rsabox> rsagenkey cr:rsagenkey
Builtin save cr:save sbox-sig cr:sbox-sig sha1-hmac cr:sha1-hmac shard cr:shard tag? cr:tag? totp cr:totp
Builtin totp-epoch cr:totp-epoch totp-time-step cr:totp-time-step unshard cr:unshard uuid cr:uuid uuid> cr:uuid>
-Builtin validate-pgp-sig cr:validate-pgp-sig (.hebrew) d:(.hebrew) (.islamic) d:(.islamic) + d:+ +day d:+day
-Builtin +hour d:+hour +min d:+min +msec d:+msec - d:- .hebrew d:.hebrew .islamic d:.islamic .time d:.time
-Builtin / d:/ = d:= >fixed d:>fixed >hebepoch d:>hebepoch >jdn d:>jdn >msec d:>msec >unix d:>unix >ymd d:>ymd
-Builtin ?= d:?= Adar d:Adar Adar2 d:Adar2 Adar2 d:Adar2 Av d:Av Elul d:Elul Fri d:Fri Heshvan d:Heshvan
-Builtin Iyar d:Iyar Kislev d:Kislev Mon d:Mon Nissan d:Nissan Sat d:Sat Shevat d:Shevat Sivan d:Sivan
-Builtin Sun d:Sun Tammuz d:Tammuz Tevet d:Tevet Thu d:Thu Tishrei d:Tishrei Tue d:Tue Wed d:Wed adjust-dst d:adjust-dst
-Builtin approx! d:approx! approx? d:approx? approximates! d:approximates! between d:between d. d:d.
-Builtin dawn d:dawn days-in-hebrew-year d:days-in-hebrew-year displaying-hebrew d:displaying-hebrew
-Builtin do-dawn d:do-dawn do-dusk d:do-dusk do-rise d:do-rise doy d:doy dst? d:dst? dstquery d:dstquery
-Builtin dstzones? d:dstzones? dusk d:dusk elapsed-timer d:elapsed-timer elapsed-timer-seconds d:elapsed-timer-seconds
-Builtin first-dow d:first-dow fixed> d:fixed> fixed>dow d:fixed>dow fixed>hebrew d:fixed>hebrew fixed>islamic d:fixed>islamic
-Builtin format d:format hanukkah d:hanukkah hebrew-epoch d:hebrew-epoch hebrew>fixed d:hebrew>fixed
-Builtin hebrewtoday d:hebrewtoday hmonth-name d:hmonth-name islamic.epoch d:islamic.epoch islamic>fixed d:islamic>fixed
-Builtin islamictoday d:islamictoday jdn> d:jdn> join d:join last-day-of-hebrew-month d:last-day-of-hebrew-month
-Builtin last-dow d:last-dow last-month d:last-month last-week d:last-week last-year d:last-year latitude d:latitude
-Builtin longitude d:longitude longitude d:longitude msec d:msec msec> d:msec> new d:new next-dow d:next-dow
-Builtin next-month d:next-month next-week d:next-week next-year d:next-year number>hebrew d:number>hebrew
-Builtin omer d:omer parse d:parse parse-approx d:parse-approx parse-range d:parse-range pesach d:pesach
-Builtin prev-dow d:prev-dow purim d:purim rosh-chodesh? d:rosh-chodesh? rosh-hashanah d:rosh-hashanah
-Builtin shavuot d:shavuot start-timer d:start-timer sunrise d:sunrise taanit-esther d:taanit-esther
-Builtin ticks d:ticks ticks/sec d:ticks/sec timer d:timer timer-ctrl d:timer-ctrl tisha-beav d:tisha-beav
-Builtin tzadjust d:tzadjust unix> d:unix> unknown d:unknown unknown? d:unknown? updatetz d:updatetz
-Builtin year@ d:year@ ymd d:ymd ymd> d:ymd> yom-haatsmaut d:yom-haatsmaut yom-kippur d:yom-kippur add-func db:add-func
-Builtin aes! db:aes! begin db:begin bind db:bind bind-exec db:bind-exec bind-exec[] db:bind-exec[]
-Builtin close db:close col db:col col[] db:col[] col{} db:col{} commit db:commit each db:each exec db:exec
-Builtin exec-cb db:exec-cb exec-name db:exec-name get db:get get-sub db:get-sub key db:key kind? db:kind?
-Builtin last-rowid db:last-rowid mysql? db:mysql? odbc? db:odbc? open db:open open? db:open? prep-name db:prep-name
-Builtin prepare db:prepare query db:query query-all db:query-all rekey db:rekey rollback db:rollback
-Builtin set db:set set-sub db:set-sub sql@ db:sql@ bp dbg:bp except-task@ dbg:except-task@ go dbg:go
-Builtin line-info dbg:line-info prompt dbg:prompt stop dbg:stop trace dbg:trace trace-enter dbg:trace-enter
-Builtin trace-leave dbg:trace-leave / f:/ abspath f:abspath absrel f:absrel append f:append associate f:associate
-Builtin atime f:atime canwrite? f:canwrite? chmod f:chmod close f:close copy f:copy copydir f:copydir
+Builtin validate-pgp-sig cr:validate-pgp-sig validate-pwd cr:validate-pwd + d:+ +day d:+day +hour d:+hour
+Builtin +min d:+min +msec d:+msec - d:- .time d:.time / d:/ = d:= >fixed d:>fixed >hmds d:>hmds >hmds: d:>hmds:
+Builtin >msec d:>msec >unix d:>unix >ymd d:>ymd ?= d:?= Fri d:Fri Mon d:Mon Sat d:Sat Sun d:Sun Thu d:Thu
+Builtin Tue d:Tue Wed d:Wed adjust-dst d:adjust-dst alarm d:alarm approx! d:approx! approx? d:approx?
+Builtin approximates! d:approximates! between d:between cmp d:cmp d. d:d. default-now d:default-now
+Builtin doy d:doy dst-ofs d:dst-ofs dst? d:dst? dstinfo d:dstinfo dstquery d:dstquery dstzones? d:dstzones?
+Builtin elapsed-timer d:elapsed-timer elapsed-timer-hmds d:elapsed-timer-hmds elapsed-timer-msec d:elapsed-timer-msec
+Builtin elapsed-timer-seconds d:elapsed-timer-seconds first-dow d:first-dow fixed> d:fixed> fixed>dow d:fixed>dow
+Builtin format d:format join d:join last-dow d:last-dow last-month d:last-month last-week d:last-week
+Builtin last-year d:last-year msec d:msec msec> d:msec> new d:new next-dow d:next-dow next-month d:next-month
+Builtin next-week d:next-week next-year d:next-year parse d:parse parse-approx d:parse-approx parse-range d:parse-range
+Builtin prev-dow d:prev-dow rfc5322 d:rfc5322 start-timer d:start-timer ticks d:ticks ticks/sec d:ticks/sec
+Builtin timer d:timer timer-ctrl d:timer-ctrl tzadjust d:tzadjust unix> d:unix> unknown d:unknown unknown? d:unknown?
+Builtin updatetz d:updatetz year@ d:year@ ymd d:ymd ymd> d:ymd> add-func db:add-func aes! db:aes! again? db:again?
+Builtin begin db:begin bind db:bind bind-exec db:bind-exec bind-exec{} db:bind-exec{} close db:close
+Builtin col db:col col{} db:col{} commit db:commit db db:db dbpush db:dbpush disuse db:disuse each db:each
+Builtin err-handler db:err-handler exec db:exec exec-cb db:exec-cb exec-name db:exec-name exec{} db:exec{}
+Builtin get db:get get-sub db:get-sub key db:key kind? db:kind? last-rowid db:last-rowid mysql? db:mysql?
+Builtin odbc? db:odbc? open db:open open? db:open? prep-name db:prep-name prepare db:prepare query db:query
+Builtin query-all db:query-all rekey db:rekey rollback db:rollback set db:set set-sub db:set-sub sql@ db:sql@
+Builtin sql[] db:sql[] sql[np] db:sql[np] sql{np} db:sql{np} sql{} db:sql{} use db:use zip db:zip bp dbg:bp
+Builtin bt dbg:bt except-task@ dbg:except-task@ go dbg:go line-info dbg:line-info prompt dbg:prompt
+Builtin stop dbg:stop trace dbg:trace trace-enter dbg:trace-enter trace-leave dbg:trace-leave / f:/
+Builtin >posix f:>posix abspath f:abspath absrel f:absrel append f:append associate f:associate atime f:atime
+Builtin autodel f:autodel canwrite? f:canwrite? chmod f:chmod close f:close copy f:copy copydir f:copydir
Builtin create f:create ctime f:ctime dir? f:dir? dname f:dname eachbuf f:eachbuf eachline f:eachline
-Builtin enssep f:enssep eof? f:eof? exists? f:exists? flush f:flush fname f:fname getb f:getb getc f:getc
-Builtin getline f:getline getmod f:getmod glob f:glob glob-nocase f:glob-nocase homedir f:homedir homedir! f:homedir!
-Builtin include f:include ioctl f:ioctl join f:join launch f:launch link f:link link> f:link> link? f:link?
-Builtin mkdir f:mkdir mmap f:mmap mmap-range f:mmap-range mmap-range? f:mmap-range? mtime f:mtime mv f:mv
-Builtin name@ f:name@ open f:open open-ro f:open-ro popen f:popen print f:print read f:read read? f:read?
-Builtin relpath f:relpath rglob f:rglob rm f:rm rmdir f:rmdir seek f:seek sep f:sep size f:size slurp f:slurp
-Builtin sparse? f:sparse? spit f:spit stderr f:stderr stdin f:stdin stdout f:stdout tell f:tell times f:times
-Builtin tmpspit f:tmpspit trash f:trash truncate f:truncate ungetb f:ungetb ungetc f:ungetc unzip f:unzip
-Builtin unzip-entry f:unzip-entry watch f:watch write f:write writen f:writen zip+ f:zip+ zip@ f:zip@
-Builtin zipentry f:zipentry zipnew f:zipnew zipopen f:zipopen zipsave f:zipsave atlas! font:atlas!
-Builtin atlas@ font:atlas@ default-size font:default-size info font:info ls font:ls measure font:measure
-Builtin new font:new oversample font:oversample pixels font:pixels pixels? font:pixels? +edge gr:+edge
-Builtin +edge+w gr:+edge+w +node gr:+node connect gr:connect edges gr:edges edges! gr:edges! m! gr:m!
-Builtin m@ gr:m@ neighbors gr:neighbors new gr:new node-edges gr:node-edges nodes gr:nodes traverse gr:traverse
-Builtin weight! gr:weight! + h:+ clear h:clear cmp! h:cmp! len h:len max! h:max! new h:new peek h:peek
-Builtin pop h:pop push h:push unique h:unique arm? hw:arm? camera hw:camera camera-img hw:camera-img
-Builtin camera-limits hw:camera-limits camera? hw:camera? cpu? hw:cpu? device? hw:device? displays? hw:displays?
-Builtin displaysize? hw:displaysize? finger-match hw:finger-match finger-support hw:finger-support
-Builtin gpio hw:gpio gpio! hw:gpio! gpio-mmap hw:gpio-mmap gpio@ hw:gpio@ i2c hw:i2c i2c! hw:i2c! i2c!reg hw:i2c!reg
-Builtin i2c@ hw:i2c@ i2c@reg hw:i2c@reg isround? hw:isround? iswatch? hw:iswatch? mac? hw:mac? mem? hw:mem?
-Builtin model? hw:model? poll hw:poll sensor hw:sensor start hw:start stop hw:stop uid? hw:uid? fetch-full imap:fetch-full
-Builtin fetch-uid-mail imap:fetch-uid-mail login imap:login logout imap:logout new imap:new search imap:search
-Builtin select-inbox imap:select-inbox >file img:>file >fmt img:>fmt copy img:copy crop img:crop data img:data
-Builtin desat img:desat fill img:fill fillrect img:fillrect filter img:filter flip img:flip from-svg img:from-svg
-Builtin new img:new pix! img:pix! pix@ img:pix@ qr-gen img:qr-gen qr-parse img:qr-parse rotate img:rotate
-Builtin scale img:scale scroll img:scroll size img:size countries iso:countries find loc:find sort loc:sort
-Builtin ! m:! !? m:!? + m:+ +? m:+? - m:- >arr m:>arr @ m:@ @? m:@? _! m:_! _@ m:_@ arr> m:arr> bitmap m:bitmap
-Builtin clear m:clear data m:data each m:each exists? m:exists? filter m:filter iter m:iter iter-all m:iter-all
-Builtin keys m:keys len m:len map m:map merge m:merge new m:new op! m:op! open m:open slice m:slice
-Builtin vals m:vals xchg m:xchg zip m:zip ! mat:! * mat:* + mat:+ = mat:= @ mat:@ affine mat:affine
-Builtin col mat:col data mat:data det mat:det dim? mat:dim? get-n mat:get-n ident mat:ident inv mat:inv
-Builtin m. mat:m. minor mat:minor n* mat:n* new mat:new new-minor mat:new-minor rotate mat:rotate row mat:row
-Builtin same-size? mat:same-size? scale mat:scale shear mat:shear trans mat:trans translate mat:translate
-Builtin xform mat:xform 2console md:2console 2html md:2html 2nk md:2nk bounds meta:bounds color meta:color
-Builtin console meta:console end meta:end ffi meta:ffi ! n:! * n:* */ n:*/ + n:+ +! n:+! - n:- / n:/
-Builtin /mod n:/mod 1+ n:1+ 1- n:1- < n:< = n:= > n:> BIGE n:BIGE BIGPI n:BIGPI E n:E PI n:PI ^ n:^
-Builtin _mod n:_mod abs n:abs acos n:acos acos n:acos asin n:asin asin n:asin atan n:atan atan n:atan
-Builtin atan2 n:atan2 band n:band between n:between bfloat n:bfloat bic n:bic bint n:bint binv n:binv
-Builtin bnot n:bnot bor n:bor bxor n:bxor cast n:cast ceil n:ceil clamp n:clamp cmp n:cmp comb n:comb
-Builtin cos n:cos cosd n:cosd emod n:emod exp n:exp expm1 n:expm1 expmod n:expmod float n:float floor n:floor
-Builtin fmod n:fmod frac n:frac gcd n:gcd int n:int invmod n:invmod kind? n:kind? lcm n:lcm ln n:ln
-Builtin ln1p n:ln1p max n:max median n:median min n:min mod n:mod neg n:neg odd? n:odd? perm n:perm
-Builtin prime? n:prime? quantize n:quantize quantize! n:quantize! r+ n:r+ range n:range rot32l n:rot32l
-Builtin rot32r n:rot32r round n:round round2 n:round2 rounding n:rounding running-variance n:running-variance
-Builtin running-variance-finalize n:running-variance-finalize sgn n:sgn shl n:shl shr n:shr sin n:sin
-Builtin sind n:sind sqr n:sqr sqrt n:sqrt tan n:tan tand n:tand trunc n:trunc ~= n:~= ! net:! !? net:!?
-Builtin - net:- >url net:>url @ net:@ @? net:@? DGRAM net:DGRAM INET4 net:INET4 INET6 net:INET6 PROTO_TCP net:PROTO_TCP
-Builtin PROTO_UDP net:PROTO_UDP STREAM net:STREAM accept net:accept addrinfo>o net:addrinfo>o again? net:again?
-Builtin alloc-and-read net:alloc-and-read alloc-buf net:alloc-buf bind net:bind close net:close closed? net:closed?
-Builtin connect net:connect debug? net:debug? delete net:delete get net:get getaddrinfo net:getaddrinfo
-Builtin getpeername net:getpeername head net:head ifaces? net:ifaces? listen net:listen map>url net:map>url
-Builtin net-socket net:net-socket opts net:opts port-is-ssl? net:port-is-ssl? post net:post proxy! net:proxy!
-Builtin put net:put read net:read read-all net:read-all recvfrom net:recvfrom s>url net:s>url sendto net:sendto
-Builtin server net:server setsockopt net:setsockopt socket net:socket tlshello net:tlshello url> net:url>
-Builtin user-agent net:user-agent wait net:wait write net:write (begin) nk:(begin) (chart-begin) nk:(chart-begin)
-Builtin (chart-begin-colored) nk:(chart-begin-colored) (chart-end) nk:(chart-end) (end) nk:(end) (group-begin) nk:(group-begin)
-Builtin (group-end) nk:(group-end) (property) nk:(property) >img nk:>img addfont nk:addfont anti-alias nk:anti-alias
-Builtin any-clicked? nk:any-clicked? bounds nk:bounds bounds! nk:bounds! button nk:button button-color nk:button-color
-Builtin button-label nk:button-label button-set-behavior nk:button-set-behavior button-symbol nk:button-symbol
-Builtin button-symbol-label nk:button-symbol-label chart-add-slot nk:chart-add-slot chart-add-slot-colored nk:chart-add-slot-colored
-Builtin chart-push nk:chart-push chart-push-slot nk:chart-push-slot checkbox nk:checkbox clicked? nk:clicked?
-Builtin close-this! nk:close-this! close-this? nk:close-this? close? nk:close? color-picker nk:color-picker
-Builtin combo nk:combo combo-begin-color nk:combo-begin-color combo-begin-label nk:combo-begin-label
+Builtin enssep f:enssep eof? f:eof? exec f:exec exists? f:exists? flush f:flush fname f:fname getb f:getb
+Builtin getc f:getc getline f:getline getmod f:getmod glob f:glob glob-links f:glob-links glob-nocase f:glob-nocase
+Builtin gunz f:gunz homedir f:homedir homedir! f:homedir! include f:include ioctl f:ioctl join f:join
+Builtin launch f:launch link f:link link> f:link> link? f:link? lock f:lock mkdir f:mkdir mmap f:mmap
+Builtin mmap-range f:mmap-range mmap-range? f:mmap-range? mtime f:mtime mv f:mv name@ f:name@ open f:open
+Builtin open! f:open! open-ro f:open-ro popen f:popen popen3 f:popen3 print f:print read f:read read-buf f:read-buf
+Builtin read? f:read? relpath f:relpath rglob f:rglob rm f:rm rmdir f:rmdir seek f:seek sep f:sep size f:size
+Builtin slurp f:slurp sparse? f:sparse? spit f:spit stderr f:stderr stdin f:stdin stdout f:stdout tell f:tell
+Builtin tempfile f:tempfile times f:times tmpspit f:tmpspit trash f:trash truncate f:truncate ungetb f:ungetb
+Builtin ungetc f:ungetc unzip f:unzip unzip-entry f:unzip-entry watch f:watch write f:write writen f:writen
+Builtin zip+ f:zip+ zip@ f:zip@ zipentry f:zipentry zipnew f:zipnew zipopen f:zipopen zipsave f:zipsave
+Builtin atlas! font:atlas! atlas@ font:atlas@ default-size font:default-size default-size@ font:default-size@
+Builtin info font:info ls font:ls measure font:measure new font:new oversample font:oversample pixels font:pixels
+Builtin pixels? font:pixels? system font:system system font:system distance geo:distance km/deg-lat geo:km/deg-lat
+Builtin km/deg-lon geo:km/deg-lon nearest geo:nearest +edge gr:+edge +edge+w gr:+edge+w +node gr:+node
+Builtin connect gr:connect edges gr:edges edges! gr:edges! m! gr:m! m@ gr:m@ neighbors gr:neighbors
+Builtin new gr:new node-edges gr:node-edges nodes gr:nodes traverse gr:traverse weight! gr:weight!
+Builtin + h:+ clear h:clear cmp! h:cmp! len h:len max! h:max! new h:new peek h:peek pop h:pop push h:push
+Builtin unique h:unique parse html:parse arm? hw:arm? camera hw:camera camera-img hw:camera-img camera-limits hw:camera-limits
+Builtin camera? hw:camera? cpu? hw:cpu? device? hw:device? displays? hw:displays? displaysize? hw:displaysize?
+Builtin finger-match hw:finger-match finger-support hw:finger-support gpio hw:gpio gpio! hw:gpio! gpio-mmap hw:gpio-mmap
+Builtin gpio@ hw:gpio@ i2c hw:i2c i2c! hw:i2c! i2c!reg hw:i2c!reg i2c@ hw:i2c@ i2c@reg hw:i2c@reg isround? hw:isround?
+Builtin iswatch? hw:iswatch? mac? hw:mac? mem? hw:mem? model? hw:model? poll hw:poll sensor hw:sensor
+Builtin start hw:start stop hw:stop uid? hw:uid? fetch-full imap:fetch-full fetch-uid-mail imap:fetch-uid-mail
+Builtin login imap:login logout imap:logout new imap:new search imap:search select-inbox imap:select-inbox
+Builtin >file img:>file >fmt img:>fmt copy img:copy crop img:crop data img:data desat img:desat draw img:draw
+Builtin draw-sub img:draw-sub fill img:fill fillrect img:fillrect filter img:filter flip img:flip from-svg img:from-svg
+Builtin line img:line new img:new pikchr img:pikchr pix! img:pix! pix@ img:pix@ qr-gen img:qr-gen qr-parse img:qr-parse
+Builtin rect img:rect rotate img:rotate scale img:scale scroll img:scroll size img:size countries iso:countries
+Builtin languages iso:languages utils/help library:utils/help find loc:find sort loc:sort ! m:! !? m:!?
+Builtin + m:+ +? m:+? - m:- <> m:<> = m:= >arr m:>arr @ m:@ @? m:@? _! m:_! _@ m:_@ alias m:alias arr> m:arr>
+Builtin bitmap m:bitmap clear m:clear data m:data each m:each exists? m:exists? filter m:filter ic m:ic
+Builtin iter m:iter iter-all m:iter-all keys m:keys len m:len map m:map merge m:merge new m:new op! m:op!
+Builtin open m:open slice m:slice vals m:vals xchg m:xchg zip m:zip ! mat:! * mat:* + mat:+ = mat:=
+Builtin @ mat:@ affine mat:affine col mat:col data mat:data det mat:det dim? mat:dim? get-n mat:get-n
+Builtin ident mat:ident inv mat:inv m. mat:m. minor mat:minor n* mat:n* new mat:new new-minor mat:new-minor
+Builtin rotate mat:rotate row mat:row same-size? mat:same-size? scale mat:scale shear mat:shear trans mat:trans
+Builtin translate mat:translate xform mat:xform 2console md:2console 2html md:2html 2nk md:2nk color meta:color
+Builtin console meta:console gui meta:gui meta meta:meta ! n:! * n:* */ n:*/ + n:+ +! n:+! - n:- / n:/
+Builtin /mod n:/mod 1+ n:1+ 1- n:1- < n:< = n:= > n:> >bool n:>bool BIGE n:BIGE BIGPI n:BIGPI E n:E
+Builtin PI n:PI ^ n:^ _mod n:_mod abs n:abs acos n:acos acos n:acos andor n:andor asin n:asin asin n:asin
+Builtin atan n:atan atan n:atan atan2 n:atan2 band n:band between n:between bfloat n:bfloat bic n:bic
+Builtin bint n:bint binv n:binv bnot n:bnot bor n:bor bxor n:bxor cast n:cast ceil n:ceil clamp n:clamp
+Builtin cmp n:cmp comb n:comb cos n:cos cosd n:cosd emod n:emod exp n:exp expm1 n:expm1 expmod n:expmod
+Builtin float n:float floor n:floor fmod n:fmod frac n:frac gcd n:gcd int n:int invmod n:invmod kind? n:kind?
+Builtin lcm n:lcm lerp n:lerp ln n:ln ln1p n:ln1p lnerp n:lnerp max n:max median n:median min n:min
+Builtin mod n:mod neg n:neg odd? n:odd? perm n:perm prime? n:prime? quantize n:quantize quantize! n:quantize!
+Builtin r+ n:r+ range n:range rot32l n:rot32l rot32r n:rot32r round n:round round2 n:round2 rounding n:rounding
+Builtin running-variance n:running-variance running-variance-finalize n:running-variance-finalize sgn n:sgn
+Builtin shl n:shl shr n:shr sin n:sin sind n:sind sqr n:sqr sqrt n:sqrt tan n:tan tand n:tand trunc n:trunc
+Builtin ~= n:~= ! net:! !? net:!? - net:- >base64url net:>base64url >url net:>url @ net:@ @? net:@?
+Builtin CGI net:CGI DGRAM net:DGRAM INET4 net:INET4 INET6 net:INET6 PROTO_TCP net:PROTO_TCP PROTO_UDP net:PROTO_UDP
+Builtin REMOTE_IP net:REMOTE_IP STREAM net:STREAM accept net:accept active? net:active? addrinfo>o net:addrinfo>o
+Builtin again? net:again? alloc-and-read net:alloc-and-read alloc-buf net:alloc-buf base64url> net:base64url>
+Builtin bind net:bind cgi-get net:cgi-get cgi-http-header net:cgi-http-header cgi-init net:cgi-init
+Builtin cgi-init-stunnel net:cgi-init-stunnel cgi-out net:cgi-out close net:close closed? net:closed?
+Builtin connect net:connect curnet net:curnet debug? net:debug? delete net:delete get net:get getaddrinfo net:getaddrinfo
+Builtin getpeername net:getpeername head net:head ifaces? net:ifaces? ipv6? net:ipv6? listen net:listen
+Builtin map>url net:map>url mime-type net:mime-type net-socket net:net-socket opts net:opts port-is-ssl? net:port-is-ssl?
+Builtin post net:post proxy! net:proxy! put net:put read net:read read-all net:read-all read-buf net:read-buf
+Builtin recvfrom net:recvfrom s>url net:s>url sendto net:sendto server net:server setsockopt net:setsockopt
+Builtin socket net:socket tcp-connect net:tcp-connect tlserr net:tlserr tlshello net:tlshello udp-connect net:udp-connect
+Builtin url> net:url> user-agent net:user-agent vpncheck net:vpncheck wait net:wait webserver net:webserver
+Builtin write net:write (begin) nk:(begin) (chart-begin) nk:(chart-begin) (chart-begin-colored) nk:(chart-begin-colored)
+Builtin (chart-end) nk:(chart-end) (end) nk:(end) (group-begin) nk:(group-begin) (group-end) nk:(group-end)
+Builtin (property) nk:(property) >img nk:>img addfont nk:addfont anti-alias nk:anti-alias any-clicked? nk:any-clicked?
+Builtin bounds nk:bounds bounds! nk:bounds! button nk:button button-color nk:button-color button-label nk:button-label
+Builtin button-set-behavior nk:button-set-behavior button-symbol nk:button-symbol button-symbol-label nk:button-symbol-label
+Builtin center-rect nk:center-rect chart-add-slot nk:chart-add-slot chart-add-slot-colored nk:chart-add-slot-colored
+Builtin chart-push nk:chart-push chart-push-slot nk:chart-push-slot checkbox nk:checkbox circle nk:circle
+Builtin clicked? nk:clicked? close-this! nk:close-this! close-this? nk:close-this? close? nk:close?
+Builtin color-picker nk:color-picker combo nk:combo combo-begin-color nk:combo-begin-color combo-begin-label nk:combo-begin-label
Builtin combo-cb nk:combo-cb combo-end nk:combo-end contextual-begin nk:contextual-begin contextual-close nk:contextual-close
Builtin contextual-end nk:contextual-end contextual-item-image-text nk:contextual-item-image-text contextual-item-symbol-text nk:contextual-item-symbol-text
-Builtin contextual-item-text nk:contextual-item-text cp! nk:cp! cp@ nk:cp@ display-info nk:display-info
-Builtin display@ nk:display@ do nk:do down? nk:down? draw-image nk:draw-image draw-image-at nk:draw-image-at
-Builtin draw-image-centered nk:draw-image-centered draw-sub-image nk:draw-sub-image draw-text nk:draw-text
-Builtin draw-text-high nk:draw-text-high draw-text-wrap nk:draw-text-wrap edit-focus nk:edit-focus
+Builtin contextual-item-text nk:contextual-item-text cp! nk:cp! cp@ nk:cp@ curpos nk:curpos cursor-load nk:cursor-load
+Builtin cursor-set nk:cursor-set cursor-show nk:cursor-show display-info nk:display-info display@ nk:display@
+Builtin do nk:do down? nk:down? draw-image nk:draw-image draw-image-at nk:draw-image-at draw-image-centered nk:draw-image-centered
+Builtin draw-sub-image nk:draw-sub-image draw-text nk:draw-text draw-text-centered nk:draw-text-centered
+Builtin draw-text-high nk:draw-text-high draw-text-wrap nk:draw-text-wrap drivers nk:drivers edit-focus nk:edit-focus
Builtin edit-string nk:edit-string event nk:event event-boost nk:event-boost event-msec nk:event-msec
-Builtin event-wait nk:event-wait fill-arc nk:fill-arc fill-circle nk:fill-circle fill-poly nk:fill-poly
-Builtin fill-rect nk:fill-rect fill-rect-color nk:fill-rect-color fill-triangle nk:fill-triangle flags! nk:flags!
-Builtin flags@ nk:flags@ fullscreen nk:fullscreen get nk:get get-row-height nk:get-row-height getfont nk:getfont
-Builtin getmap nk:getmap gl? nk:gl? grid nk:grid grid-push nk:grid-push group-scroll-ofs nk:group-scroll-ofs
-Builtin group-scroll-ofs! nk:group-scroll-ofs! hovered? nk:hovered? image nk:image init nk:init input-button nk:input-button
-Builtin input-key nk:input-key input-motion nk:input-motion input-scroll nk:input-scroll input-string nk:input-string
-Builtin key-down? nk:key-down? key-pressed? nk:key-pressed? key-released? nk:key-released? label nk:label
-Builtin label-colored nk:label-colored label-wrap nk:label-wrap label-wrap-colored nk:label-wrap-colored
+Builtin event-wait nk:event-wait event? nk:event? fill-arc nk:fill-arc fill-circle nk:fill-circle fill-color nk:fill-color
+Builtin fill-poly nk:fill-poly fill-rect nk:fill-rect fill-rect-color nk:fill-rect-color fill-triangle nk:fill-triangle
+Builtin finger nk:finger flags! nk:flags! flags@ nk:flags@ flash nk:flash fullscreen nk:fullscreen
+Builtin gesture nk:gesture get nk:get get-row-height nk:get-row-height getfont nk:getfont getmap nk:getmap
+Builtin getmap! nk:getmap! gl? nk:gl? grid nk:grid grid-push nk:grid-push group-scroll-ofs nk:group-scroll-ofs
+Builtin group-scroll-ofs! nk:group-scroll-ofs! hovered? nk:hovered? hrule nk:hrule image nk:image init nk:init
+Builtin input-button nk:input-button input-key nk:input-key input-motion nk:input-motion input-scroll nk:input-scroll
+Builtin input-string nk:input-string key-down? nk:key-down? key-pressed? nk:key-pressed? key-released? nk:key-released?
+Builtin label nk:label label-colored nk:label-colored label-wrap nk:label-wrap label-wrap-colored nk:label-wrap-colored
Builtin layout-bounds nk:layout-bounds layout-grid-begin nk:layout-grid-begin layout-grid-end nk:layout-grid-end
Builtin layout-push-dynamic nk:layout-push-dynamic layout-push-static nk:layout-push-static layout-push-variable nk:layout-push-variable
Builtin layout-ratio-from-pixel nk:layout-ratio-from-pixel layout-reset-row-height nk:layout-reset-row-height
@@ -266,79 +293,94 @@ Builtin layout-row-end nk:layout-row-end layout-row-height nk:layout-row-height
Builtin layout-row-static nk:layout-row-static layout-row-template-begin nk:layout-row-template-begin
Builtin layout-row-template-end nk:layout-row-template-end layout-space-begin nk:layout-space-begin
Builtin layout-space-end nk:layout-space-end layout-space-push nk:layout-space-push layout-widget-bounds nk:layout-widget-bounds
-Builtin list-begin nk:list-begin list-end nk:list-end list-new nk:list-new list-range nk:list-range
-Builtin m! nk:m! m@ nk:m@ make-style nk:make-style max-vertex-element nk:max-vertex-element measure nk:measure
-Builtin measure-font nk:measure-font menu-begin nk:menu-begin menu-close nk:menu-close menu-end nk:menu-end
-Builtin menu-item-image nk:menu-item-image menu-item-label nk:menu-item-label menu-item-symbol nk:menu-item-symbol
-Builtin menubar-begin nk:menubar-begin menubar-end nk:menubar-end mouse-pos nk:mouse-pos msgdlg nk:msgdlg
-Builtin option nk:option plot nk:plot plot-fn nk:plot-fn pop-font nk:pop-font popup-begin nk:popup-begin
-Builtin popup-close nk:popup-close popup-end nk:popup-end popup-scroll-ofs nk:popup-scroll-ofs popup-scroll-ofs! nk:popup-scroll-ofs!
-Builtin progress nk:progress prop-int nk:prop-int pt>local nk:pt>local pt>screen nk:pt>screen pts>rect nk:pts>rect
-Builtin push-font nk:push-font rect-center nk:rect-center rect-intersect nk:rect-intersect rect-ofs nk:rect-ofs
-Builtin rect-pad nk:rect-pad rect-shrink nk:rect-shrink rect-union nk:rect-union rect/high nk:rect/high
-Builtin rect/wide nk:rect/wide rect>center nk:rect>center rect>local nk:rect>local rect>pos nk:rect>pos
-Builtin rect>pts nk:rect>pts rect>screen nk:rect>screen rect>size nk:rect>size released? nk:released?
-Builtin render nk:render restore nk:restore rotate nk:rotate save nk:save scale nk:scale scancode? nk:scancode?
-Builtin screen-saver nk:screen-saver screen-size nk:screen-size screen-win-close nk:screen-win-close
-Builtin selectable nk:selectable set nk:set set-font nk:set-font set-num-vertices nk:set-num-vertices
-Builtin setpos nk:setpos setwin nk:setwin slider nk:slider slider-int nk:slider-int space nk:space
-Builtin spacing nk:spacing stroke-arc nk:stroke-arc stroke-circle nk:stroke-circle stroke-curve nk:stroke-curve
-Builtin stroke-line nk:stroke-line stroke-polygon nk:stroke-polygon stroke-polyline nk:stroke-polyline
-Builtin stroke-rect nk:stroke-rect stroke-tri nk:stroke-tri style-from-table nk:style-from-table sw-gl nk:sw-gl
-Builtin text? nk:text? tooltip nk:tooltip translate nk:translate tree-pop nk:tree-pop tree-state-push nk:tree-state-push
-Builtin use-style nk:use-style vsync nk:vsync widget nk:widget widget-bounds nk:widget-bounds widget-fitting nk:widget-fitting
-Builtin widget-high nk:widget-high widget-hovered? nk:widget-hovered? widget-mouse-click-down? nk:widget-mouse-click-down?
-Builtin widget-mouse-clicked? nk:widget-mouse-clicked? widget-pos nk:widget-pos widget-size nk:widget-size
-Builtin widget-wide nk:widget-wide win nk:win win-bounds nk:win-bounds win-bounds! nk:win-bounds! win-close nk:win-close
-Builtin win-closed? nk:win-closed? win-collapse nk:win-collapse win-collapsed? nk:win-collapsed? win-content-bounds nk:win-content-bounds
+Builtin line-rel nk:line-rel line-to nk:line-to list-begin nk:list-begin list-end nk:list-end list-new nk:list-new
+Builtin list-range nk:list-range m! nk:m! m@ nk:m@ make-style nk:make-style max-vertex-element nk:max-vertex-element
+Builtin maximize nk:maximize measure nk:measure measure-font nk:measure-font menu-begin nk:menu-begin
+Builtin menu-close nk:menu-close menu-end nk:menu-end menu-item-image nk:menu-item-image menu-item-label nk:menu-item-label
+Builtin menu-item-symbol nk:menu-item-symbol menubar-begin nk:menubar-begin menubar-end nk:menubar-end
+Builtin minimize nk:minimize mouse-pos nk:mouse-pos move-back nk:move-back move-rel nk:move-rel move-to nk:move-to
+Builtin msg nk:msg msgdlg nk:msgdlg ontop nk:ontop option nk:option pen-color nk:pen-color pen-width nk:pen-width
+Builtin plot nk:plot plot-fn nk:plot-fn pop-font nk:pop-font popup-begin nk:popup-begin popup-close nk:popup-close
+Builtin popup-end nk:popup-end popup-scroll-ofs nk:popup-scroll-ofs popup-scroll-ofs! nk:popup-scroll-ofs!
+Builtin progress nk:progress prop-int nk:prop-int pt-in? nk:pt-in? pt-open nk:pt-open pt>local nk:pt>local
+Builtin pt>rect nk:pt>rect pt>screen nk:pt>screen pt>x nk:pt>x pts>rect nk:pts>rect push-font nk:push-font
+Builtin raise nk:raise rect! nk:rect! rect-center nk:rect-center rect-intersect nk:rect-intersect rect-ofs nk:rect-ofs
+Builtin rect-open nk:rect-open rect-pad nk:rect-pad rect-rel nk:rect-rel rect-shrink nk:rect-shrink
+Builtin rect-to nk:rect-to rect-union nk:rect-union rect/high nk:rect/high rect/wide nk:rect/wide rect= nk:rect=
+Builtin rect>local nk:rect>local rect>pos nk:rect>pos rect>pts nk:rect>pts rect>pts4 nk:rect>pts4 rect>screen nk:rect>screen
+Builtin rect>size nk:rect>size rect>x nk:rect>x rect@ nk:rect@ released? nk:released? render nk:render
+Builtin render-timed nk:render-timed restore nk:restore rotate nk:rotate rotate-rel nk:rotate-rel save nk:save
+Builtin scale nk:scale scancode? nk:scancode? screen-saver nk:screen-saver screen-size nk:screen-size
+Builtin screen-win-close nk:screen-win-close selectable nk:selectable set nk:set set-font nk:set-font
+Builtin set-num-vertices nk:set-num-vertices set-radius nk:set-radius setpos nk:setpos setwin nk:setwin
+Builtin show nk:show slider nk:slider slider-int nk:slider-int space nk:space spacing nk:spacing stroke-arc nk:stroke-arc
+Builtin stroke-circle nk:stroke-circle stroke-curve nk:stroke-curve stroke-line nk:stroke-line stroke-polygon nk:stroke-polygon
+Builtin stroke-polyline nk:stroke-polyline stroke-rect nk:stroke-rect stroke-tri nk:stroke-tri style-from-table nk:style-from-table
+Builtin swipe nk:swipe swipe-dir-threshold nk:swipe-dir-threshold swipe-threshold nk:swipe-threshold
+Builtin text nk:text text-align nk:text-align text-font nk:text-font text-pad nk:text-pad text? nk:text?
+Builtin timer-delay nk:timer-delay timer? nk:timer? tooltip nk:tooltip translate nk:translate tree-pop nk:tree-pop
+Builtin tree-state-push nk:tree-state-push use-style nk:use-style vsync nk:vsync widget nk:widget widget-bounds nk:widget-bounds
+Builtin widget-disable nk:widget-disable widget-fitting nk:widget-fitting widget-high nk:widget-high
+Builtin widget-hovered? nk:widget-hovered? widget-mouse-click-down? nk:widget-mouse-click-down? widget-mouse-clicked? nk:widget-mouse-clicked?
+Builtin widget-pos nk:widget-pos widget-size nk:widget-size widget-size nk:widget-size widget-wide nk:widget-wide
+Builtin win nk:win win-bounds nk:win-bounds win-bounds! nk:win-bounds! win-close nk:win-close win-closed? nk:win-closed?
+Builtin win-collapse nk:win-collapse win-collapsed? nk:win-collapsed? win-content-bounds nk:win-content-bounds
Builtin win-focus nk:win-focus win-focused? nk:win-focused? win-hidden? nk:win-hidden? win-high nk:win-high
Builtin win-hovered? nk:win-hovered? win-pos nk:win-pos win-scroll-ofs nk:win-scroll-ofs win-scroll-ofs! nk:win-scroll-ofs!
-Builtin win-show nk:win-show win-size nk:win-size win-wide nk:win-wide win? nk:win? MAX ns:MAX ! o:!
-Builtin + o:+ +? o:+? ??? o:??? @ o:@ class o:class exec o:exec isa o:isa method o:method mutate o:mutate
-Builtin new o:new super o:super devname os:devname env os:env lang os:lang mem-arenas os:mem-arenas
-Builtin notify os:notify region os:region cast ptr:cast len ptr:len null? ptr:null? pack ptr:pack unpack ptr:unpack
-Builtin unpack_orig ptr:unpack_orig publish pubsub:publish qsize pubsub:qsize subscribe pubsub:subscribe
-Builtin + q:+ clear q:clear len q:len new q:new notify q:notify overwrite q:overwrite peek q:peek pick q:pick
-Builtin pop q:pop push q:push remove q:remove shift q:shift size q:size slide q:slide throwing q:throwing
-Builtin wait q:wait ++match r:++match +/ r:+/ +match r:+match / r:/ @ r:@ len r:len match r:match new r:new
-Builtin rx r:rx str r:str * rat:* + rat:+ - rat:- / rat:/ >n rat:>n >s rat:>s new rat:new proper rat:proper
-Builtin ! s:! * s:* + s:+ - s:- / s:/ /scripts s:/scripts <+ s:<+ = s:= =ic s:=ic >base64 s:>base64
-Builtin >ucs2 s:>ucs2 @ s:@ append s:append base64> s:base64> clear s:clear cmp s:cmp cmpi s:cmpi compress s:compress
-Builtin days! s:days! dist s:dist each s:each each! s:each! eachline s:eachline escape s:escape expand s:expand
-Builtin fill s:fill fmt s:fmt fold s:fold gershayim s:gershayim globmatch s:globmatch hexupr s:hexupr
-Builtin insert s:insert intl s:intl intl! s:intl! lang s:lang lc s:lc lc? s:lc? len s:len lsub s:lsub
-Builtin ltrim s:ltrim map s:map months! s:months! new s:new norm s:norm reduce s:reduce repinsert s:repinsert
-Builtin replace s:replace replace! s:replace! rev s:rev rsearch s:rsearch rsub s:rsub rtrim s:rtrim
-Builtin script? s:script? search s:search size s:size slice s:slice soundex s:soundex strfmap s:strfmap
-Builtin strfmt s:strfmt text-wrap s:text-wrap trim s:trim tsub s:tsub uc s:uc uc? s:uc? ucs2> s:ucs2>
-Builtin utf8? s:utf8? zt s:zt close sio:close enum sio:enum open sio:open opts! sio:opts! opts@ sio:opts@
-Builtin read sio:read write sio:write @ slv:@ auto slv:auto build slv:build constraint slv:constraint
+Builtin win-show nk:win-show win-size nk:win-size win-wide nk:win-wide win? nk:win? x>pt nk:x>pt x>rect nk:x>rect
+Builtin MAX ns:MAX ! o:! + o:+ +? o:+? ??? o:??? @ o:@ class o:class exec o:exec isa o:isa method o:method
+Builtin mutate o:mutate new o:new super o:super chroot os:chroot devname os:devname docker? os:docker?
+Builtin env os:env lang os:lang locales os:locales notify os:notify power-state os:power-state region os:region
+Builtin waitpid os:waitpid bezier pdf:bezier bezierq pdf:bezierq circle pdf:circle color pdf:color
+Builtin ellipse pdf:ellipse font pdf:font img pdf:img line pdf:line new pdf:new page pdf:page page-size pdf:page-size
+Builtin rect pdf:rect save pdf:save size pdf:size text pdf:text text-rotate pdf:text-rotate text-size pdf:text-size
+Builtin text-width pdf:text-width text-wrap pdf:text-wrap text-wrap-rotate pdf:text-wrap-rotate cast ptr:cast
+Builtin len ptr:len null? ptr:null? pack ptr:pack unpack ptr:unpack unpack_orig ptr:unpack_orig publish pubsub:publish
+Builtin qsize pubsub:qsize subscribe pubsub:subscribe + q:+ clear q:clear len q:len new q:new notify q:notify
+Builtin overwrite q:overwrite peek q:peek pick q:pick pop q:pop push q:push remove q:remove shift q:shift
+Builtin size q:size slide q:slide throwing q:throwing wait q:wait ++match r:++match +/ r:+/ +match r:+match
+Builtin / r:/ @ r:@ len r:len match r:match new r:new rx r:rx str r:str * rat:* + rat:+ - rat:- / rat:/
+Builtin >n rat:>n >s rat:>s new rat:new proper rat:proper ! s:! * s:* + s:+ - s:- / s:/ /scripts s:/scripts
+Builtin <+ s:<+ <> s:<> = s:= =ic s:=ic >base64 s:>base64 >ucs2 s:>ucs2 @ s:@ append s:append base64> s:base64>
+Builtin clear s:clear cmp s:cmp cmpi s:cmpi compress s:compress count-match s:count-match days! s:days!
+Builtin dist s:dist each s:each each! s:each! eachline s:eachline escape s:escape expand s:expand fill s:fill
+Builtin fold s:fold globmatch s:globmatch hexupr s:hexupr insert s:insert intl s:intl intl! s:intl!
+Builtin lang s:lang lc s:lc lc? s:lc? len s:len lsub s:lsub ltrim s:ltrim map s:map months! s:months!
+Builtin n> s:n> new s:new norm s:norm reduce s:reduce repinsert s:repinsert replace s:replace replace! s:replace!
+Builtin rev s:rev rsearch s:rsearch rsub s:rsub rtrim s:rtrim scan-match s:scan-match script? s:script?
+Builtin search s:search size s:size slice s:slice soundex s:soundex strfmap s:strfmap strfmt s:strfmt
+Builtin term s:term text-wrap s:text-wrap tr s:tr translate s:translate trim s:trim tsub s:tsub uc s:uc
+Builtin uc? s:uc? ucs2> s:ucs2> utf8? s:utf8? zt s:zt close sio:close enum sio:enum open sio:open opts! sio:opts!
+Builtin opts@ sio:opts@ read sio:read write sio:write @ slv:@ auto slv:auto build slv:build constraint slv:constraint
Builtin dump slv:dump edit slv:edit named-variable slv:named-variable new slv:new relation slv:relation
Builtin reset slv:reset suggest slv:suggest term slv:term update slv:update v[] slv:v[] variable slv:variable
Builtin v{} slv:v{} new smtp:new send smtp:send apply-filter snd:apply-filter devices? snd:devices?
-Builtin end-record snd:end-record filter snd:filter formats? snd:formats? freq snd:freq gain snd:gain
-Builtin gain? snd:gain? init snd:init len snd:len loop snd:loop loop? snd:loop? mix snd:mix new snd:new
-Builtin pause snd:pause play snd:play played snd:played rate snd:rate ready? snd:ready? record snd:record
-Builtin resume snd:resume seek snd:seek stop snd:stop stopall snd:stopall volume snd:volume volume? snd:volume?
-Builtin + st:+ . st:. clear st:clear len st:len ndrop st:ndrop new st:new op! st:op! peek st:peek pick st:pick
-Builtin pop st:pop push st:push roll st:roll shift st:shift size st:size slide st:slide swap st:swap
-Builtin throwing st:throwing >buf struct:>buf arr> struct:arr> buf struct:buf buf> struct:buf> byte struct:byte
-Builtin double struct:double field! struct:field! field@ struct:field@ float struct:float ignore struct:ignore
-Builtin int struct:int long struct:long struct; struct:struct; word struct:word ! t:! @ t:@ by-name t:by-name
-Builtin cor t:cor cor-drop t:cor-drop curtask t:curtask def-queue t:def-queue def-stack t:def-stack
-Builtin done? t:done? err! t:err! err? t:err? errno? t:errno? getq t:getq handler t:handler handler@ t:handler@
+Builtin end-record snd:end-record filter snd:filter freq snd:freq gain snd:gain gain? snd:gain? init snd:init
+Builtin len snd:len loop snd:loop loop? snd:loop? mix snd:mix new snd:new pause snd:pause play snd:play
+Builtin played snd:played rate snd:rate ready? snd:ready? record snd:record resume snd:resume seek snd:seek
+Builtin stop snd:stop stopall snd:stopall volume snd:volume volume? snd:volume? + st:+ . st:. clear st:clear
+Builtin len st:len ndrop st:ndrop new st:new op! st:op! peek st:peek pick st:pick pop st:pop push st:push
+Builtin roll st:roll shift st:shift size st:size slide st:slide swap st:swap throwing st:throwing >buf struct:>buf
+Builtin arr> struct:arr> buf struct:buf buf> struct:buf> byte struct:byte double struct:double field! struct:field!
+Builtin field@ struct:field@ float struct:float ignore struct:ignore int struct:int long struct:long
+Builtin struct; struct:struct; word struct:word ! t:! @ t:@ by-name t:by-name cor t:cor cor-drop t:cor-drop
+Builtin curtask t:curtask def-queue t:def-queue def-stack t:def-stack done? t:done? dtor t:dtor err! t:err!
+Builtin err? t:err? errno? t:errno? extra t:extra getq t:getq handler t:handler handler@ t:handler@
Builtin kill t:kill list t:list main t:main max-exceptions t:max-exceptions name! t:name! name@ t:name@
-Builtin notify t:notify parent t:parent pop t:pop priority t:priority push t:push q-notify t:q-notify
+Builtin notify t:notify parent t:parent pop t:pop priority t:priority push t:push push! t:push! q-notify t:q-notify
Builtin q-wait t:q-wait qlen t:qlen result t:result set-affinity t:set-affinity setq t:setq start t:start
-Builtin task t:task task-n t:task-n task-stop t:task-stop wait t:wait yield t:yield yield! t:yield!
+Builtin task t:task task-n t:task-n task-stop t:task-stop ticks t:ticks wait t:wait yield t:yield yield! t:yield!
Builtin add tree:add binary tree:binary bk tree:bk btree tree:btree cmp! tree:cmp! data tree:data del tree:del
Builtin find tree:find iter tree:iter next tree:next nodes tree:nodes parent tree:parent parse tree:parse
Builtin prev tree:prev root tree:root search tree:search trie tree:trie ! w:! (is) w:(is) @ w:@ alias: w:alias:
Builtin cb w:cb deprecate w:deprecate dlcall w:dlcall dlopen w:dlopen dlsym w:dlsym exec w:exec exec? w:exec?
-Builtin ffifail w:ffifail find w:find forget w:forget is w:is name w:name undo w:undo >s xml:>s >txt xml:>txt
-Builtin md-init xml:md-init md-parse xml:md-parse parse xml:parse parse-html xml:parse-html parse-stream xml:parse-stream
+Builtin ffifail w:ffifail find w:find forget w:forget is w:is name w:name undo w:undo close ws:close
+Builtin decode ws:decode encode ws:encode encode-nomask ws:encode-nomask gen-accept-header ws:gen-accept-header
+Builtin gen-accept-key ws:gen-accept-key opcodes ws:opcodes open ws:open >s xml:>s >txt xml:>txt md-init xml:md-init
+Builtin md-parse xml:md-parse parse xml:parse parse-html xml:parse-html parse-stream xml:parse-stream
Builtin getmsg[] zmq:getmsg[] sendmsg[] zmq:sendmsg[]
+
" numbers
syn keyword eighthMath decimal hex base@ base!
syn match eighthInteger '\<-\=[0-9.]*[0-9.]\+\>'
@@ -349,6 +391,11 @@ syn match eighthInteger '\<\x*\d\x*\>' " *2* --- this order!
syn match eighthInteger '\<%[0-1]*[0-1]\+\>'
syn match eighthInteger "\<'.\>"
+syn include @SQL syntax/sql.vim
+syn region eightSQL matchgroup=Define start=/\<SQL\[\s/ end=/\<]\>/ contains=@SQL keepend
+syn region eightSQL matchgroup=Define start=/\<SQL{\s/ end=/\<}\>/ contains=@SQL keepend
+syn region eightSQL matchgroup=Define start=/\<SQL!\s/ end=/\<!\>/ contains=@SQL keepend
+
" Strings
syn region eighthString start=+\.\?\"+ skip=+"+ end=+$+
syn keyword jsonNull null
@@ -356,49 +403,57 @@ syn keyword jsonBool /\(true\|false\)/
syn region eighthString start=/\<"/ end=/"\>/
syn match jsonObjEntry /"\"[^"]\+\"\ze\s*:/
-" Include files
-syn region eighthComment start="\zs\\" end="$" contains=eighthTodo
+syn region eighthNeeds start=+needs\[+ end=+]+ matchgroup=eighthNeeds2 transparent
+syn match eighthNeeds2 /\<needs\[/
+syn match eighthNeeds2 /]\>/
-" Define the default highlighting.
-if !exists("did_eighth_syntax_inits")
- let did_eighth_syntax_inits=1
+syn match eighthBuiltin /m:\[]!/
+syn match eighthBuiltin /v:\[]/
+syn match eighthBuiltin /db:bind-exec\[]/
+syn match eighthBuiltin /db:exec\[]/
+syn match eighthBuiltin /db:col\[]/
- " The default methods for highlighting. Can be overridden later.
- hi def link eighthTodo Todo
- hi def link eighthOperators Operator
- hi def link eighthMath Number
- hi def link eighthInteger Number
- hi def link eighthStack Special
- hi def link eighthFStack Special
- hi def link eighthSP Special
- hi def link eighthColonDef Define
- hi def link eighthColonName Operator
- hi def link eighthEndOfColonDef Define
- hi def link eighthDefine Define
- hi def link eighthDebug Debug
- hi def link eighthCharOps Character
- hi def link eighthConversion String
- hi def link eighthForth Statement
- hi def link eighthVocs Statement
- hi def link eighthString String
- hi def link eighthComment Comment
- hi def link eighthClassDef Define
- hi def link eighthEndOfClassDef Define
- hi def link eighthObjectDef Define
- hi def link eighthEndOfObjectDef Define
- hi def link eighthInclude Include
- hi def link eighthBuiltin Define
- hi def link eighthClasses Define
- hi def link eighthClassWord Keyword
- hi def link jsonObject Delimiter
- hi def link jsonObjEntry Label
- hi def link jsonArray Special
- hi def link jsonNull Function
- hi def link jsonBool Boolean
-endif
+" TODO
+syn region eighthComment start="\zs\\" end="$" contains=eighthTodo
+
+" The default methods for highlighting. Can be overriden later.
+hi def link eighthTodo Todo
+hi def link eighthNeeds2 Include
+hi def link eighthNeeds Error
+hi def link eighthOperators Operator
+hi def link eighthMath Number
+hi def link eighthInteger Number
+hi def link eighthStack Special
+hi def link eighthFStack Special
+hi def link eighthFname Operator
+hi def link eighthSP Special
+hi def link eighthColonDef Define
+hi def link eighthColonName Operator
+hi def link eighthEndOfColonDef Define
+hi def link eighthDefine Define
+hi def link eighthDebug Debug
+hi def link eighthCharOps Character
+hi def link eighthConversion String
+hi def link eighthForth Statement
+hi def link eighthVocs Statement
+hi def link eighthString String
+hi def link eighthComment Comment
+hi def link eighthClassDef Define
+hi def link eighthEndOfClassDef Define
+hi def link eighthObjectDef Define
+hi def link eighthEndOfObjectDef Define
+hi def link eighthInclude Include
+hi def link eighthBuiltin Define
+hi def link eighthClasses Define
+hi def link eighthClassWord Keyword
+hi def link jsonObject Delimiter
+hi def link jsonObjEntry Label
+hi def link jsonArray Special
+hi def link jsonNull Function
+hi def link jsonBool Boolean
let b:current_syntax = "8th"
let &cpo = s:cpo_save
unlet s:cpo_save
-" vim: ft=vim:ts=8:sw=4:nocindent:smartindent:
+" vim: ft=vim ts=4 sw=4 nocin:si
diff --git a/runtime/syntax/amiga.vim b/runtime/syntax/amiga.vim
index 5a664c4f60..9402196482 100644
--- a/runtime/syntax/amiga.vim
+++ b/runtime/syntax/amiga.vim
@@ -1,9 +1,10 @@
" Vim syntax file
" Language: AmigaDos
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Aug 31, 2016
" Version: 10
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_AMIGA
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_AMIGA
" quit when a syntax file was already loaded
if exists("b:current_syntax")
diff --git a/runtime/syntax/ant.vim b/runtime/syntax/ant.vim
index 6696f96eb1..b0231236dd 100644
--- a/runtime/syntax/ant.vim
+++ b/runtime/syntax/ant.vim
@@ -1,9 +1,9 @@
" Vim syntax file
-" Language: ANT build file (xml)
-" Maintainer: Johannes Zellner <johannes@zellner.org>
-" Last Change: Tue Apr 27 13:05:59 CEST 2004
-" Filenames: build.xml
-" $Id: ant.vim,v 1.1 2004/06/13 18:13:18 vimboss Exp $
+" Language: ANT build file (xml)
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: Johannes Zellner <johannes@zellner.org>
+" Last Change: 2024 Jan 27
+" Filenames: build.xml
" Quit when a syntax file was already loaded
if exists("b:current_syntax")
@@ -44,48 +44,48 @@ call AntSyntaxScript('jpython', 'python.vim')
syn cluster xmlTagHook add=antElement
-syn keyword antElement display WsdlToDotnet addfiles and ant antcall antstructure apply archives arg argument
-syn keyword antElement display assertions attrib attribute available basename bcc blgenclient bootclasspath
-syn keyword antElement display borland bottom buildnumber buildpath buildpathelement bunzip2 bzip2 cab
-syn keyword antElement display catalogpath cc cccheckin cccheckout cclock ccmcheckin ccmcheckintask ccmcheckout
-syn keyword antElement display ccmcreatetask ccmkattr ccmkbl ccmkdir ccmkelem ccmklabel ccmklbtype
-syn keyword antElement display ccmreconfigure ccrmtype ccuncheckout ccunlock ccupdate checksum chgrp chmod
-syn keyword antElement display chown classconstants classes classfileset classpath commandline comment
-syn keyword antElement display compilerarg compilerclasspath concat concatfilter condition copy copydir
-syn keyword antElement display copyfile coveragepath csc custom cvs cvschangelog cvspass cvstagdiff cvsversion
-syn keyword antElement display daemons date defaultexcludes define delete deletecharacters deltree depend
-syn keyword antElement display depends dependset depth description different dirname dirset disable dname
-syn keyword antElement display doclet doctitle dtd ear echo echoproperties ejbjar element enable entity entry
-syn keyword antElement display env equals escapeunicode exclude excludepackage excludesfile exec execon
-syn keyword antElement display existing expandproperties extdirs extension extensionSet extensionset factory
-syn keyword antElement display fail filelist filename filepath fileset filesmatch filetokenizer filter
-syn keyword antElement display filterchain filterreader filters filterset filtersfile fixcrlf footer format
-syn keyword antElement display from ftp generic genkey get gjdoc grant group gunzip gzip header headfilter http
-syn keyword antElement display ignoreblank ilasm ildasm import importtypelib include includesfile input iplanet
-syn keyword antElement display iplanet-ejbc isfalse isreference isset istrue jar jarlib-available
-syn keyword antElement display jarlib-manifest jarlib-resolve java javac javacc javadoc javadoc2 jboss jdepend
-syn keyword antElement display jjdoc jjtree jlink jonas jpcoverage jpcovmerge jpcovreport jsharpc jspc
-syn keyword antElement display junitreport jvmarg lib libfileset linetokenizer link loadfile loadproperties
-syn keyword antElement display location macrodef mail majority manifest map mapper marker mergefiles message
-syn keyword antElement display metainf method mimemail mkdir mmetrics modified move mparse none not options or
-syn keyword antElement display os outputproperty package packageset parallel param patch path pathconvert
-syn keyword antElement display pathelement patternset permissions prefixlines present presetdef project
-syn keyword antElement display property propertyfile propertyref propertyset pvcs pvcsproject record reference
-syn keyword antElement display regexp rename renameext replace replacefilter replaceregex replaceregexp
-syn keyword antElement display replacestring replacetoken replacetokens replacevalue replyto report resource
-syn keyword antElement display revoke rmic root rootfileset rpm scp section selector sequential serverdeploy
-syn keyword antElement display setproxy signjar size sleep socket soscheckin soscheckout sosget soslabel source
-syn keyword antElement display sourcepath sql src srcfile srcfilelist srcfiles srcfileset sshexec stcheckin
-syn keyword antElement display stcheckout stlabel stlist stringtokenizer stripjavacomments striplinebreaks
-syn keyword antElement display striplinecomments style subant substitution support symlink sync sysproperty
-syn keyword antElement display syspropertyset tabstospaces tag taglet tailfilter tar tarfileset target
-syn keyword antElement display targetfile targetfilelist targetfileset taskdef tempfile test testlet text title
-syn keyword antElement display to token tokenfilter touch transaction translate triggers trim tstamp type
-syn keyword antElement display typedef unjar untar unwar unzip uptodate url user vbc vssadd vsscheckin
-syn keyword antElement display vsscheckout vsscp vsscreate vssget vsshistory vsslabel waitfor war wasclasspath
-syn keyword antElement display webapp webinf weblogic weblogictoplink websphere whichresource wlclasspath
-syn keyword antElement display wljspc wsdltodotnet xmlcatalog xmlproperty xmlvalidate xslt zip zipfileset
-syn keyword antElement display zipgroupfileset
+syn keyword antElement WsdlToDotnet addfiles and ant antcall antstructure apply archives arg argument
+syn keyword antElement assertions attrib attribute available basename bcc blgenclient bootclasspath
+syn keyword antElement borland bottom buildnumber buildpath buildpathelement bunzip2 bzip2 cab
+syn keyword antElement catalogpath cc cccheckin cccheckout cclock ccmcheckin ccmcheckintask ccmcheckout
+syn keyword antElement ccmcreatetask ccmkattr ccmkbl ccmkdir ccmkelem ccmklabel ccmklbtype
+syn keyword antElement ccmreconfigure ccrmtype ccuncheckout ccunlock ccupdate checksum chgrp chmod
+syn keyword antElement chown classconstants classes classfileset classpath commandline comment
+syn keyword antElement compilerarg compilerclasspath concat concatfilter condition copy copydir
+syn keyword antElement copyfile coveragepath csc custom cvs cvschangelog cvspass cvstagdiff cvsversion
+syn keyword antElement daemons date defaultexcludes define delete deletecharacters deltree depend
+syn keyword antElement depends dependset depth description different dirname dirset disable dname
+syn keyword antElement doclet doctitle dtd ear echo echoproperties ejbjar element enable entity entry
+syn keyword antElement env equals escapeunicode exclude excludepackage excludesfile exec execon
+syn keyword antElement existing expandproperties extdirs extension extensionSet extensionset factory
+syn keyword antElement fail filelist filename filepath fileset filesmatch filetokenizer filter
+syn keyword antElement filterchain filterreader filters filterset filtersfile fixcrlf footer format
+syn keyword antElement from ftp generic genkey get gjdoc grant group gunzip gzip header headfilter http
+syn keyword antElement ignoreblank ilasm ildasm import importtypelib include includesfile input iplanet
+syn keyword antElement iplanet-ejbc isfalse isreference isset istrue jar jarlib-available
+syn keyword antElement jarlib-manifest jarlib-resolve java javac javacc javadoc javadoc2 jboss jdepend
+syn keyword antElement jjdoc jjtree jlink jonas jpcoverage jpcovmerge jpcovreport jsharpc jspc
+syn keyword antElement junitreport jvmarg lib libfileset linetokenizer link loadfile loadproperties
+syn keyword antElement location macrodef mail majority manifest map mapper marker mergefiles message
+syn keyword antElement metainf method mimemail mkdir mmetrics modified move mparse none not options or
+syn keyword antElement os outputproperty package packageset parallel param patch path pathconvert
+syn keyword antElement pathelement patternset permissions prefixlines present presetdef project
+syn keyword antElement property propertyfile propertyref propertyset pvcs pvcsproject record reference
+syn keyword antElement regexp rename renameext replace replacefilter replaceregex replaceregexp
+syn keyword antElement replacestring replacetoken replacetokens replacevalue replyto report resource
+syn keyword antElement revoke rmic root rootfileset rpm scp section selector sequential serverdeploy
+syn keyword antElement setproxy signjar size sleep socket soscheckin soscheckout sosget soslabel source
+syn keyword antElement sourcepath sql src srcfile srcfilelist srcfiles srcfileset sshexec stcheckin
+syn keyword antElement stcheckout stlabel stlist stringtokenizer stripjavacomments striplinebreaks
+syn keyword antElement striplinecomments style subant substitution support symlink sync sysproperty
+syn keyword antElement syspropertyset tabstospaces tag taglet tailfilter tar tarfileset target
+syn keyword antElement targetfile targetfilelist targetfileset taskdef tempfile test testlet text title
+syn keyword antElement to token tokenfilter touch transaction translate triggers trim tstamp type
+syn keyword antElement typedef unjar untar unwar unzip uptodate url user vbc vssadd vsscheckin
+syn keyword antElement vsscheckout vsscp vsscreate vssget vsshistory vsslabel waitfor war wasclasspath
+syn keyword antElement webapp webinf weblogic weblogictoplink websphere whichresource wlclasspath
+syn keyword antElement wljspc wsdltodotnet xmlcatalog xmlproperty xmlvalidate xslt zip zipfileset
+syn keyword antElement zipgroupfileset
hi def link antElement Statement
diff --git a/runtime/syntax/c.vim b/runtime/syntax/c.vim
index 5ed8fdc847..30db9438d0 100644
--- a/runtime/syntax/c.vim
+++ b/runtime/syntax/c.vim
@@ -252,7 +252,7 @@ if exists("c_gnu")
syn keyword cOperator typeof __typeof__
syn keyword cOperator __real__ __imag__
syn keyword cStorageClass __attribute__ __const__ __extension__
- syn keyword cStorageClass inline __inline__
+ syn keyword cStorageClass inline __inline __inline__
syn keyword cStorageClass __restrict__ __volatile__ __noreturn__
endif
syn keyword cType int long short char void
@@ -444,6 +444,14 @@ syn match cUserLabel display "\I\i*" contained
syn match cBitField display "^\s*\zs\I\i*\s*:\s*[1-9]"me=e-1 contains=cType
syn match cBitField display ";\s*\zs\I\i*\s*:\s*[1-9]"me=e-1 contains=cType
+if exists("c_functions")
+ syn match cFunction "\<\h\w*\ze\_s*("
+ endif
+
+if exists("c_function_pointers")
+ syn match cFunctionPointer "\%((\s*\*\s*\)\@<=\h\w*\ze\s*)\_s*(.*)"
+endif
+
if exists("c_minlines")
let b:c_minlines = c_minlines
else
@@ -513,6 +521,8 @@ hi def link cCppOutSkip cCppOutIf2
hi def link cCppInElse2 cCppOutIf2
hi def link cCppOutIf2 cCppOut
hi def link cCppOut Comment
+hi def link cFunction Function
+hi def link cFunctionPointer Function
let b:current_syntax = "c"
diff --git a/runtime/syntax/chuck.vim b/runtime/syntax/chuck.vim
new file mode 100644
index 0000000000..6fcf40ca8b
--- /dev/null
+++ b/runtime/syntax/chuck.vim
@@ -0,0 +1,187 @@
+" Vim syntax file
+" Language: ChucK
+" Maintainer: Andrea Callea
+" URL: https://github.com/gacallea/chuck.vim
+" Last Change: 2024 Jan 21 by Andrea Callea
+
+" Sources used for this syntax
+" https://chuck.cs.princeton.edu/doc/language/
+" https://chuck.cs.princeton.edu/doc/reference/
+
+" HISTORY:
+" 2024 Jan 21 - Initial revision
+
+" quit when a syntax file was already loaded
+if exists("b:current_syntax")
+ finish
+endif
+
+" https://chuck.cs.princeton.edu/doc/language/type.html
+syn keyword chuckPrimitiveType int float time dur void vec3 vec4
+syn keyword chuckComplexType complex polar
+syn keyword chuckReferenceType Object Event UGen array string
+syn keyword chuckBoolean true false maybe
+syn keyword chuckBoolean null NULL
+
+" https://chuck.cs.princeton.edu/doc/language/oper.html
+syn match chuckOperator "=>"
+syn match chuckOperator "@=>"
+
+syn match chuckOperator "=^"
+
+syn match chuckOperator "+"
+syn match chuckOperator "-"
+syn match chuckOperator "*"
+syn match chuckOperator "/"
+syn match chuckOperator "%"
+syn match chuckOperator "!"
+syn match chuckOperator "&"
+syn match chuckOperator "|"
+syn match chuckOperator "\^"
+
+syn match chuckOperator "+=>"
+syn match chuckOperator "-=>"
+syn match chuckOperator "*=>"
+syn match chuckOperator "/=>"
+syn match chuckOperator "%=>"
+syn match chuckOperator "!=>"
+syn match chuckOperator "&=>"
+syn match chuckOperator "|=>"
+syn match chuckOperator "\^=>"
+
+syn match chuckOperator "&&"
+syn match chuckOperator "||"
+syn match chuckOperator "=="
+syn match chuckOperator "!="
+syn match chuckOperator ">"
+syn match chuckOperator ">="
+syn match chuckOperator "<"
+syn match chuckOperator "<="
+
+syn match chuckOperator ">>"
+syn match chuckOperator "<<"
+
+syn match chuckOperator "++"
+syn match chuckOperator "--"
+syn match chuckOperator "<<<"
+syn match chuckOperator ">>>"
+
+syn keyword chuckOperator new
+
+" https://chuck.cs.princeton.edu/doc/language/ctrl.html
+syn keyword chuckConditional if else
+syn keyword chuckRepeat while do until for each
+
+" https://chuck.cs.princeton.edu/doc/language/time.html
+syn keyword chuckTimeAndDuration samp ms second minute hour day week
+syn keyword chuckTimeAndDuration now later
+
+" these may need some additional keywords I missed, for a future revision
+syn keyword chuckKeyword dac adc
+syn keyword chuckKeyword fun function
+syn keyword chuckKeyword return
+syn keyword chuckKeyword const
+syn match chuckKeyword "@"
+syn keyword chuckKeyword pi
+syn keyword chuckKeyword me
+syn keyword chuckKeyword repeat break continue
+syn keyword chuckKeyword class extends public private static pure this
+syn keyword chuckKeyword spork
+syn keyword chuckKeyword cherr chout
+
+" https://chuck.cs.princeton.edu/doc/reference/
+syn keyword chuckBaseClasses Shred Math Machine Std
+
+" https://chuck.cs.princeton.edu/doc/reference/
+syn keyword chuckBasicUGen Gain Impulse Step SndBuf SndBuf2
+syn keyword chuckBasicUGen ADSR Envelope Delay DelayL DelayA Echo
+syn keyword chuckBasicUGen Noise CNoise Osc SinOsc TriOsc SawOsc PulseOsc SqrOsc
+syn keyword chuckBasicUGen Phasor HalfRect FullRect
+syn keyword chuckBasicUGen Chugraph Chugen UGen_Multi UGen_Stereo Mix2 Pan2
+
+" https://chuck.cs.princeton.edu/doc/reference/
+syn keyword chuckFilterUGen FilterBasic LPF HPF BPF BRF BiQuad ResonZ
+syn keyword chuckFilterUGen OnePole OneZero TwoPole TwoZero PoleZero
+
+" https://chuck.cs.princeton.edu/doc/reference/
+syn keyword chuckSTKUGen JCRev NRev PRCRev
+syn keyword chuckSTKUGen Chorus Modulate PitShift SubNoise
+syn keyword chuckSTKUGen BLT Blit BlitSaw BlitSquare FilterStk
+syn keyword chuckSTKUGen WvIn WaveLoop WvOut WvOut2 StkInstrument
+syn keyword chuckSTKUGen BandedWG BlowBotl BlowHole
+syn keyword chuckSTKUGen Bowed Brass Clarinet Flute Mandolin
+syn keyword chuckSTKUGen ModalBar Moog Saxofony Shakers Sitar StifKarp
+syn keyword chuckSTKUGen VoicForm KrstlChr FM BeeThree FMVoices
+syn keyword chuckSTKUGen HevyMetl HnkyTonk FrencHrn PercFlut Rhodey TubeBell Wurley
+
+" https://chuck.cs.princeton.edu/doc/reference/
+syn keyword chuckAdvancedUGen LiSa LiSa2 LiSa6 LiSa8 LiSa10
+syn keyword chuckAdvancedUGen LiSa16 GenX Gen5 Gen7 Gen9 Gen10 Gen17
+syn keyword chuckAdvancedUGen CurveTable WarpTable Dyno
+
+" https://chuck.cs.princeton.edu/doc/reference/
+syn keyword chuckChugin ABSaturator AmbPan3 Bitcrusher Elliptic ExpDelay ExpEnv FIR
+syn keyword chuckChugin FoldbackSaturator GVerb KasFilter MagicSine Mesh2D
+syn keyword chuckChugin Multicomb Pan4 Pan8 Pan16 PitchTrack PowerADSR RegEx
+syn keyword chuckChugin Sigmund Spectacle WinFuncEnv WPDiodeLadder WPKorg35
+
+" https://chuck.cs.princeton.edu/doc/reference/
+syn keyword chuckUnitAnalyzer UAna UAnaBlob Windowing
+syn keyword chuckUnitAnalyzer FFT IFFT DCT IDCT
+syn keyword chuckUnitAnalyzer Centroid Flux RMS RollOff
+syn keyword chuckUnitAnalyzer Flip UnFlip XCorr
+syn keyword chuckUnitAnalyzer Chroma Kurtosis MFCC SFM ZeroX AutoCorr FeatureCollector
+
+" https://chuck.cs.princeton.edu/doc/reference/
+syn keyword chuckChAI MLP KNN KNN2 HMM SVM Word2Vec PCA Wekinator AI
+
+" https://chuck.cs.princeton.edu/doc/reference/
+syn keyword chuckInputOutput IO FileIO OscIn OscOut OscMsg
+syn keyword chuckInputOutput Hid HidMsg KBHit SerialIO
+syn keyword chuckInputOutput MidiIn MidiOut MidiMsg MidiFileIn
+
+" https://chuck.cs.princeton.edu/doc/reference/
+syn keyword chuckUtilities CKDoc StringTokenizer ConsoleInput
+
+" https://github.com/wilsaj/chuck.vim/blob/master/syntax/chuck.vim
+syn match chuckNumber /\%(\i\|\$\)\@<![-]\?\d\+/ display
+syn match chuckHex /\<0[xX]\x\+[lL]\=\>/ display
+syn match chuckFloat /\%(\i\|\$\)\@<![-]\?\%(\d*\.\d\+\|\d\+\.\)/ display
+
+" this may need fixing/improvements
+syn match chuckComment "//.*$"
+syn region chuckComment start="/\*" end="\*/"
+syn match chuckSpecialChar contained "\\n"
+syn match chuckSpecialChar contained "\\t"
+syn match chuckSpecialChar contained "\\a"
+syn match chuckSpecialChar contained /\\"/
+syn match chuckSpecialChar contained "\\0"
+syn region chuckString start=/"/ end=/"/ display contains=chuckSpecialChar
+
+hi def link chuckPrimitiveType Type
+hi def link chuckComplexType Type
+hi def link chuckReferenceType Type
+hi def link chuckBoolean Boolean
+hi def link chuckOperator Operator
+hi def link chuckConditional Conditional
+hi def link chuckRepeat Repeat
+hi def link chuckTimeAndDuration Keyword
+hi def link chuckKeyword Keyword
+hi def link chuckBaseClasses Special
+hi def link chuckBasicUGen Structure
+hi def link chuckFilterUGen Structure
+hi def link chuckSTKUGen Structure
+hi def link chuckAdvancedUGen Structure
+hi def link chuckChugin Structure
+hi def link chuckUnitAnalyzer Structure
+hi def link chuckChAI Structure
+hi def link chuckInputOutput Special
+hi def link chuckUtilities Special
+hi def link chuckNumber Number
+hi def link chuckHex Number
+hi def link chuckFloat Float
+hi def link chuckComment Comment
+hi def link chuckSpecialChar SpecialChar
+hi def link chuckString String
+
+let b:current_syntax = "chuck"
diff --git a/runtime/syntax/cmake.vim b/runtime/syntax/cmake.vim
index 7340ac238e..c95503beb5 100644
--- a/runtime/syntax/cmake.vim
+++ b/runtime/syntax/cmake.vim
@@ -1,15 +1,15 @@
" Vim syntax file
" Program: CMake - Cross-Platform Makefile Generator
-" Version: cmake version 3.9.20170830-ge0713
+" Version: cmake version 3.27.20230713-gdc88dd5
" Language: CMake
" Author: Andy Cedilnik <andy.cedilnik@kitware.com>,
" Nicholas Hutchinson <nshutchinson@gmail.com>,
" Patrick Boettcher <patrick.boettcher@posteo.de>
" Maintainer: Dimitri Merejkowsky <d.merej@gmail.com>
" Former Maintainer: Karthik Krishnan <karthik.krishnan@kitware.com>
-" Last Change: 2017 Aug 30
+" Last Change: 2023 Jul 13
"
-" Licence: The CMake license applies to this file. See
+" License: The CMake license applies to this file. See
" https://cmake.org/licensing
" This implies that distribution with Vim is allowed
@@ -19,335 +19,4799 @@ endif
let s:keepcpo= &cpo
set cpo&vim
-syn region cmakeComment start="#" end="$" contains=cmakeTodo,cmakeLuaComment,@Spell
-syn region cmakeLuaComment start="\[\z(=*\)\[" end="\]\z1\]" contains=cmakeTodo,@Spell
+syn region cmakeBracketArgument start="\[\z(=*\)\[" end="\]\z1\]" contains=cmakeTodo,@Spell
+
+syn region cmakeComment start="#\(\[=*\[\)\@!" end="$" contains=cmakeTodo,@Spell
+syn region cmakeBracketComment start="#\[\z(=*\)\[" end="\]\z1\]" contains=cmakeTodo,@Spell
syn match cmakeEscaped /\(\\\\\|\\"\|\\n\|\\t\)/ contained
syn region cmakeRegistry start="\[" end="]" contained oneline contains=cmakeTodo,cmakeEscaped
syn region cmakeGeneratorExpression start="$<" end=">" contained oneline contains=cmakeVariableValue,cmakeProperty,cmakeGeneratorExpressions,cmakeTodo
-syn region cmakeString start='"' end='"' contained contains=cmakeTodo,cmakeVariableValue,cmakeEscaped
+syn region cmakeString start='"' end='"' contained contains=cmakeTodo,cmakeVariableValue,cmakeEscaped,@Spell
-syn region cmakeVariableValue start="${" end="}" contained oneline contains=cmakeVariable,cmakeTodo
+syn region cmakeVariableValue start="${" end="}" contained oneline contains=cmakeVariable,cmakeTodo,cmakeVariableValue
syn region cmakeEnvironment start="$ENV{" end="}" contained oneline contains=cmakeTodo
-syn region cmakeArguments start="(" end=")" contains=ALLBUT,cmakeCommand,cmakeCommandConditional,cmakeCommandRepeat,cmakeCommandDeprecated,cmakeArguments,cmakeTodo
+syn region cmakeArguments start="(" end=")" contains=ALLBUT,cmakeGeneratorExpressions,cmakeCommand,cmakeCommandConditional,cmakeCommandRepeat,cmakeCommandDeprecated,cmakeCommandManuallyAdded,cmakeArguments,cmakeTodo,@Spell
syn case match
syn keyword cmakeProperty contained
- \ ABSTRACT ADDITIONAL_MAKE_CLEAN_FILES ADVANCED ALIASED_TARGET ALLOW_DUPLICATE_CUSTOM_TARGETS ANDROID_ANT_ADDITIONAL_OPTIONS ANDROID_API ANDROID_API_MIN ANDROID_ARCH ANDROID_ASSETS_DIRECTORIES ANDROID_GUI ANDROID_JAR_DEPENDENCIES ANDROID_JAR_DIRECTORIES ANDROID_JAVA_SOURCE_DIR ANDROID_NATIVE_LIB_DEPENDENCIES ANDROID_NATIVE_LIB_DIRECTORIES ANDROID_PROCESS_MAX ANDROID_PROGUARD ANDROID_PROGUARD_CONFIG_PATH ANDROID_SECURE_PROPS_PATH ANDROID_SKIP_ANT_STEP ANDROID_STL_TYPE ARCHIVE_OUTPUT_DIRECTORY ARCHIVE_OUTPUT_NAME ATTACHED_FILES ATTACHED_FILES_ON_FAIL AUTOGEN_BUILD_DIR AUTOGEN_SOURCE_GROUP AUTOGEN_TARGETS_FOLDER AUTOGEN_TARGET_DEPENDS AUTOMOC AUTOMOC_DEPEND_FILTERS AUTOMOC_MACRO_NAMES AUTOMOC_MOC_OPTIONS AUTOMOC_SOURCE_GROUP AUTOMOC_TARGETS_FOLDER AUTORCC AUTORCC_OPTIONS AUTORCC_SOURCE_GROUP AUTOUIC AUTOUIC_OPTIONS AUTOUIC_SEARCH_PATHS BINARY_DIR BUILDSYSTEM_TARGETS BUILD_RPATH BUILD_WITH_INSTALL_NAME_DIR BUILD_WITH_INSTALL_RPATH BUNDLE BUNDLE_EXTENSION CACHE_VARIABLES CLEAN_NO_CUSTOM CMAKE_CONFIGURE_DEPENDS CMAKE_CXX_KNOWN_FEATURES CMAKE_C_KNOWN_FEATURES COMPATIBLE_INTERFACE_BOOL COMPATIBLE_INTERFACE_NUMBER_MAX COMPATIBLE_INTERFACE_NUMBER_MIN COMPATIBLE_INTERFACE_STRING COMPILE_DEFINITIONS COMPILE_FEATURES COMPILE_FLAGS COMPILE_OPTIONS COMPILE_PDB_NAME COMPILE_PDB_OUTPUT_DIRECTORY COST CPACK_DESKTOP_SHORTCUTS CPACK_NEVER_OVERWRITE CPACK_PERMANENT CPACK_STARTUP_SHORTCUTS CPACK_START_MENU_SHORTCUTS CPACK_WIX_ACL CROSSCOMPILING_EMULATOR CUDA_EXTENSIONS CUDA_PTX_COMPILATION CUDA_RESOLVE_DEVICE_SYMBOLS CUDA_SEPARABLE_COMPILATION CUDA_STANDARD CUDA_STANDARD_REQUIRED CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED DEBUG_CONFIGURATIONS DEBUG_POSTFIX DEFINE_SYMBOL DEFINITIONS DEPENDS DEPLOYMENT_REMOTE_DIRECTORY DISABLED DISABLED_FEATURES ECLIPSE_EXTRA_NATURES ENABLED_FEATURES ENABLED_LANGUAGES ENABLE_EXPORTS ENVIRONMENT EXCLUDE_FROM_ALL EXCLUDE_FROM_DEFAULT_BUILD EXPORT_NAME EXTERNAL_OBJECT EchoString FAIL_REGULAR_EXPRESSION FIND_LIBRARY_USE_LIB32_PATHS FIND_LIBRARY_USE_LIB64_PATHS FIND_LIBRARY_USE_LIBX32_PATHS FIND_LIBRARY_USE_OPENBSD_VERSIONING FIXTURES_CLEANUP FIXTURES_REQUIRED FIXTURES_SETUP FOLDER FRAMEWORK FRAMEWORK_VERSION Fortran_FORMAT Fortran_MODULE_DIRECTORY GENERATED GENERATOR_FILE_NAME GENERATOR_IS_MULTI_CONFIG GLOBAL_DEPENDS_DEBUG_MODE GLOBAL_DEPENDS_NO_CYCLES GNUtoMS HAS_CXX HEADER_FILE_ONLY HELPSTRING IMPLICIT_DEPENDS_INCLUDE_TRANSFORM IMPORTED IMPORTED_CONFIGURATIONS IMPORTED_IMPLIB IMPORTED_LIBNAME IMPORTED_LINK_DEPENDENT_LIBRARIES IMPORTED_LINK_INTERFACE_LANGUAGES IMPORTED_LINK_INTERFACE_LIBRARIES IMPORTED_LINK_INTERFACE_MULTIPLICITY IMPORTED_LOCATION IMPORTED_NO_SONAME IMPORTED_OBJECTS IMPORTED_SONAME IMPORT_PREFIX IMPORT_SUFFIX INCLUDE_DIRECTORIES INCLUDE_REGULAR_EXPRESSION INSTALL_NAME_DIR INSTALL_RPATH INSTALL_RPATH_USE_LINK_PATH INTERFACE_AUTOUIC_OPTIONS INTERFACE_COMPILE_DEFINITIONS INTERFACE_COMPILE_FEATURES INTERFACE_COMPILE_OPTIONS INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_POSITION_INDEPENDENT_CODE INTERFACE_SOURCES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES INTERPROCEDURAL_OPTIMIZATION IN_TRY_COMPILE IOS_INSTALL_COMBINED JOB_POOLS JOB_POOL_COMPILE JOB_POOL_LINK KEEP_EXTENSION LABELS LANGUAGE LIBRARY_OUTPUT_DIRECTORY LIBRARY_OUTPUT_NAME LINKER_LANGUAGE LINK_DEPENDS LINK_DEPENDS_NO_SHARED LINK_DIRECTORIES LINK_FLAGS LINK_INTERFACE_LIBRARIES LINK_INTERFACE_MULTIPLICITY LINK_LIBRARIES LINK_SEARCH_END_STATIC LINK_SEARCH_START_STATIC LINK_WHAT_YOU_USE LISTFILE_STACK LOCATION MACOSX_BUNDLE MACOSX_BUNDLE_INFO_PLIST MACOSX_FRAMEWORK_INFO_PLIST MACOSX_PACKAGE_LOCATION MACOSX_RPATH MACROS MANUALLY_ADDED_DEPENDENCIES MEASUREMENT MODIFIED NAME NO_SONAME NO_SYSTEM_FROM_IMPORTED OBJECT_DEPENDS OBJECT_OUTPUTS OSX_ARCHITECTURES OUTPUT_NAME PACKAGES_FOUND PACKAGES_NOT_FOUND PARENT_DIRECTORY PASS_REGULAR_EXPRESSION PDB_NAME PDB_OUTPUT_DIRECTORY POSITION_INDEPENDENT_CODE POST_INSTALL_SCRIPT PREDEFINED_TARGETS_FOLDER PREFIX PRE_INSTALL_SCRIPT PRIVATE_HEADER PROCESSORS PROJECT_LABEL PUBLIC_HEADER REPORT_UNDEFINED_PROPERTIES REQUIRED_FILES RESOURCE RESOURCE_LOCK RULE_LAUNCH_COMPILE RULE_LAUNCH_CUSTOM RULE_LAUNCH_LINK RULE_MESSAGES RUNTIME_OUTPUT_DIRECTORY RUNTIME_OUTPUT_NAME RUN_SERIAL SKIP_AUTOGEN SKIP_AUTOMOC SKIP_AUTORCC SKIP_AUTOUIC SKIP_BUILD_RPATH SKIP_RETURN_CODE SOURCES SOURCE_DIR SOVERSION STATIC_LIBRARY_FLAGS STRINGS SUBDIRECTORIES SUFFIX SYMBOLIC TARGET_ARCHIVES_MAY_BE_SHARED_LIBS TARGET_MESSAGES TARGET_SUPPORTS_SHARED_LIBS TEST_INCLUDE_FILE TEST_INCLUDE_FILES TIMEOUT TIMEOUT_AFTER_MATCH TYPE USE_FOLDERS VALUE VARIABLES VERSION VISIBILITY_INLINES_HIDDEN VS_CONFIGURATION_TYPE VS_COPY_TO_OUT_DIR VS_DEBUGGER_WORKING_DIRECTORY VS_DEPLOYMENT_CONTENT VS_DEPLOYMENT_LOCATION VS_DESKTOP_EXTENSIONS_VERSION VS_DOTNET_REFERENCES VS_DOTNET_REFERENCES_COPY_LOCAL VS_DOTNET_TARGET_FRAMEWORK_VERSION VS_GLOBAL_KEYWORD VS_GLOBAL_PROJECT_TYPES VS_GLOBAL_ROOTNAMESPACE VS_INCLUDE_IN_VSIX VS_IOT_EXTENSIONS_VERSION VS_IOT_STARTUP_TASK VS_KEYWORD VS_MOBILE_EXTENSIONS_VERSION VS_RESOURCE_GENERATOR VS_SCC_AUXPATH VS_SCC_LOCALPATH VS_SCC_PROJECTNAME VS_SCC_PROVIDER VS_SDK_REFERENCES VS_SHADER_ENTRYPOINT VS_SHADER_FLAGS VS_SHADER_MODEL VS_SHADER_TYPE VS_STARTUP_PROJECT VS_TOOL_OVERRIDE VS_USER_PROPS VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION VS_WINRT_COMPONENT VS_WINRT_EXTENSIONS VS_WINRT_REFERENCES VS_XAML_TYPE WILL_FAIL WIN32_EXECUTABLE WINDOWS_EXPORT_ALL_SYMBOLS WORKING_DIRECTORY WRAP_EXCLUDE XCODE_EMIT_EFFECTIVE_PLATFORM_NAME XCODE_EXPLICIT_FILE_TYPE XCODE_FILE_ATTRIBUTES XCODE_LAST_KNOWN_FILE_TYPE XCODE_PRODUCT_TYPE XCTEST
+ \ ABSTRACT
+ \ ADDITIONAL_CLEAN_FILES
+ \ ADDITIONAL_MAKE_CLEAN_FILES
+ \ ADVANCED
+ \ AIX_EXPORT_ALL_SYMBOLS
+ \ ALIASED_TARGET
+ \ ALIAS_GLOBAL
+ \ ALLOW_DUPLICATE_CUSTOM_TARGETS
+ \ ANDROID_ANT_ADDITIONAL_OPTIONS
+ \ ANDROID_API
+ \ ANDROID_API_MIN
+ \ ANDROID_ARCH
+ \ ANDROID_ASSETS_DIRECTORIES
+ \ ANDROID_GUI
+ \ ANDROID_JAR_DEPENDENCIES
+ \ ANDROID_JAR_DIRECTORIES
+ \ ANDROID_JAVA_SOURCE_DIR
+ \ ANDROID_NATIVE_LIB_DEPENDENCIES
+ \ ANDROID_NATIVE_LIB_DIRECTORIES
+ \ ANDROID_PROCESS_MAX
+ \ ANDROID_PROGUARD
+ \ ANDROID_PROGUARD_CONFIG_PATH
+ \ ANDROID_SECURE_PROPS_PATH
+ \ ANDROID_SKIP_ANT_STEP
+ \ ANDROID_STL_TYPE
+ \ ARCHIVE_OUTPUT_DIRECTORY
+ \ ARCHIVE_OUTPUT_NAME
+ \ ATTACHED_FILES
+ \ ATTACHED_FILES_ON_FAIL
+ \ AUTOGEN_BUILD_DIR
+ \ AUTOGEN_COMMAND_LINE_LENGTH_MAX
+ \ AUTOGEN_ORIGIN_DEPENDS
+ \ AUTOGEN_PARALLEL
+ \ AUTOGEN_SOURCE_GROUP
+ \ AUTOGEN_USE_SYSTEM_INCLUDE
+ \ AUTOGEN_TARGETS_FOLDER
+ \ AUTOGEN_TARGET_DEPENDS
+ \ AUTOGEN_USE_SYSTEM_INCLUDE
+ \ AUTOMOC
+ \ AUTOMOC_COMPILER_PREDEFINES
+ \ AUTOMOC_DEPEND_FILTERS
+ \ AUTOMOC_EXECUTABLE
+ \ AUTOMOC_MACRO_NAMES
+ \ AUTOMOC_MOC_OPTIONS
+ \ AUTOMOC_PATH_PREFIX
+ \ AUTOMOC_SOURCE_GROUP
+ \ AUTOMOC_TARGETS_FOLDER
+ \ AUTORCC
+ \ AUTORCC_EXECUTABLE
+ \ AUTORCC_OPTIONS
+ \ AUTORCC_SOURCE_GROUP
+ \ AUTOUIC
+ \ AUTOUIC_EXECUTABLE
+ \ AUTOUIC_OPTIONS
+ \ AUTOUIC_SEARCH_PATHS
+ \ AUTOUIC_SOURCE_GROUP
+ \ BINARY_DIR
+ \ BUILDSYSTEM_TARGETS
+ \ BUILD_RPATH
+ \ BUILD_RPATH_USE_ORIGIN
+ \ BUILD_WITH_INSTALL_NAME_DIR
+ \ BUILD_WITH_INSTALL_RPATH
+ \ BUNDLE
+ \ BUNDLE_EXTENSION
+ \ CACHE_VARIABLES
+ \ CLEAN_NO_CUSTOM
+ \ CMAKE_CONFIGURE_DEPENDS
+ \ CMAKE_CUDA_KNOWN_FEATURES
+ \ CMAKE_CXX_KNOWN_FEATURES
+ \ CMAKE_C_KNOWN_FEATURES
+ \ CMAKE_ROLE
+ \ COMMON_LANGUAGE_RUNTIME
+ \ COMPATIBLE_INTERFACE_BOOL
+ \ COMPATIBLE_INTERFACE_NUMBER_MAX
+ \ COMPATIBLE_INTERFACE_NUMBER_MIN
+ \ COMPATIBLE_INTERFACE_STRING
+ \ COMPILE_DEFINITIONS
+ \ COMPILE_FEATURES
+ \ COMPILE_FLAGS
+ \ COMPILE_OPTIONS
+ \ COMPILE_PDB_NAME
+ \ COMPILE_PDB_OUTPUT_DIRECTORY
+ \ COMPILE_WARNING_AS_ERROR
+ \ COST
+ \ CPACK_DESKTOP_SHORTCUTS
+ \ CPACK_NEVER_OVERWRITE
+ \ CPACK_PERMANENT
+ \ CPACK_STARTUP_SHORTCUTS
+ \ CPACK_START_MENU_SHORTCUTS
+ \ CPACK_WIX_ACL
+ \ CROSSCOMPILING_EMULATOR
+ \ CUDA_ARCHITECTURES
+ \ CUDA_CUBIN_COMPILATION
+ \ CUDA_EXTENSIONS
+ \ CUDA_FATBIN_COMPILATION
+ \ CUDA_OPTIX_COMPILATION
+ \ CUDA_PTX_COMPILATION
+ \ CUDA_RESOLVE_DEVICE_SYMBOLS
+ \ CUDA_RUNTIME_LIBRARY
+ \ CUDA_SEPARABLE_COMPILATION
+ \ CUDA_STANDARD
+ \ CUDA_STANDARD_REQUIRED
+ \ CXX_EXTENSIONS
+ \ CXX_MODULE_DIRS
+ \ CXX_MODULE_SET
+ \ CXX_MODULE_SETS
+ \ CXX_SCAN_FOR_MODULES
+ \ CXX_STANDARD
+ \ CXX_STANDARD_REQUIRED
+ \ C_EXTENSIONS
+ \ C_STANDARD
+ \ C_STANDARD_REQUIRED
+ \ DEBUG_CONFIGURATIONS
+ \ DEBUG_POSTFIX
+ \ DEFINE_SYMBOL
+ \ DEFINITIONS
+ \ DEPENDS
+ \ DEPLOYMENT_ADDITIONAL_FILES
+ \ DEPLOYMENT_REMOTE_DIRECTORY
+ \ DEPRECATION
+ \ DISABLED
+ \ DISABLED_FEATURES
+ \ DISABLE_PRECOMPILE_HEADERS
+ \ DLL_NAME_WITH_SOVERSION
+ \ DOTNET_SDK
+ \ DOTNET_TARGET_FRAMEWORK
+ \ DOTNET_TARGET_FRAMEWORK_VERSION
+ \ ECLIPSE_EXTRA_CPROJECT_CONTENTS
+ \ ECLIPSE_EXTRA_NATURES
+ \ ENABLED_FEATURES
+ \ ENABLED_LANGUAGES
+ \ ENABLE_EXPORTS
+ \ ENVIRONMENT
+ \ ENVIRONMENT_MODIFICATION
+ \ EXCLUDE_FROM_ALL
+ \ EXCLUDE_FROM_DEFAULT_BUILD
+ \ EXPORT_COMPILE_COMMANDS
+ \ EXPORT_NAME
+ \ EXPORT_NO_SYSTEM
+ \ EXPORT_PROPERTIES
+ \ EXTERNAL_OBJECT
+ \ EchoString
+ \ FAIL_REGULAR_EXPRESSION
+ \ FIND_LIBRARY_USE_LIB32_PATHS
+ \ FIND_LIBRARY_USE_LIB64_PATHS
+ \ FIND_LIBRARY_USE_LIBX32_PATHS
+ \ FIND_LIBRARY_USE_OPENBSD_VERSIONING
+ \ FIXTURES_CLEANUP
+ \ FIXTURES_REQUIRED
+ \ FIXTURES_SETUP
+ \ FOLDER
+ \ FRAMEWORK
+ \ FRAMEWORK_VERSION
+ \ Fortran_BUILDING_INSTRINSIC_MODULES
+ \ Fortran_FORMAT
+ \ Fortran_MODULE_DIRECTORY
+ \ Fortran_PREPROCESS
+ \ GENERATED
+ \ GENERATOR_FILE_NAME
+ \ GENERATOR_IS_MULTI_CONFIG
+ \ GHS_INTEGRITY_APP
+ \ GHS_NO_SOURCE_GROUP_FILE
+ \ GLOBAL_DEPENDS_DEBUG_MODE
+ \ GLOBAL_DEPENDS_NO_CYCLES
+ \ GNUtoMS
+ \ HAS_CXX
+ \ HEADER_DIRS
+ \ HEADER_FILE_ONLY
+ \ HEADER_SET
+ \ HEADER_SETS
+ \ HELPSTRING
+ \ HIP_ARCHITECTURES
+ \ HIP_EXTENSIONS
+ \ HIP_STANDARD
+ \ HIP_STANDARD_REQUIRED
+ \ IMPLICIT_DEPENDS_INCLUDE_TRANSFORM
+ \ IMPORTED
+ \ IMPORTED_COMMON_LANGUAGE_RUNTIME
+ \ IMPORTED_CONFIGURATIONS
+ \ IMPORTED_GLOBAL
+ \ IMPORTED_IMPLIB
+ \ IMPORTED_LIBNAME
+ \ IMPORTED_LINK_DEPENDENT_LIBRARIES
+ \ IMPORTED_LINK_INTERFACE_LANGUAGES
+ \ IMPORTED_LINK_INTERFACE_LIBRARIES
+ \ IMPORTED_LINK_INTERFACE_MULTIPLICITY
+ \ IMPORTED_LOCATION
+ \ IMPORTED_NO_SONAME
+ \ IMPORTED_NO_SYSTEM
+ \ IMPORTED_OBJECTS
+ \ IMPORTED_SONAME
+ \ IMPORTED_TARGETS
+ \ IMPORT_PREFIX
+ \ IMPORT_SUFFIX
+ \ INCLUDE_DIRECTORIES
+ \ INCLUDE_REGULAR_EXPRESSION
+ \ INSTALL_NAME_DIR
+ \ INSTALL_REMOVE_ENVIRONMENT_RPATH
+ \ INSTALL_RPATH
+ \ INSTALL_RPATH_USE_LINK_PATH
+ \ INTERFACE_AUTOMOC_MACRO_NAMES
+ \ INTERFACE_AUTOUIC_OPTIONS
+ \ INTERFACE_AUTOMOC_MACRO_NAMES
+ \ INTERFACE_COMPILE_DEFINITIONS
+ \ INTERFACE_COMPILE_FEATURES
+ \ INTERFACE_COMPILE_OPTIONS
+ \ INTERFACE_CXX_MODULE_SETS
+ \ INTERFACE_HEADER_SETS
+ \ INTERFACE_HEADER_SETS_TO_VERIFY
+ \ INTERFACE_INCLUDE_DIRECTORIES
+ \ INTERFACE_LINK_DEPENDS
+ \ INTERFACE_LINK_DIRECTORIES
+ \ INTERFACE_LINK_LIBRARIES
+ \ INTERFACE_LINK_LIBRARIES_DIRECT
+ \ INTERFACE_LINK_LIBRARIES_DIRECT_EXCLUDE
+ \ INTERFACE_LINK_OPTIONS
+ \ INTERFACE_POSITION_INDEPENDENT_CODE
+ \ INTERFACE_PRECOMPILE_HEADERS
+ \ INTERFACE_SOURCES
+ \ INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
+ \ INTERPROCEDURAL_OPTIMIZATION
+ \ IN_TRY_COMPILE
+ \ IOS_INSTALL_COMBINED
+ \ ISPC_HEADER_DIRECTORY
+ \ ISPC_HEADER_SUFFIX
+ \ ISPC_INSTRUCTION_SETS
+ \ JOB_POOLS
+ \ JOB_POOL_COMPILE
+ \ JOB_POOL_LINK
+ \ JOB_POOL_PRECOMPILE_HEADER
+ \ KEEP_EXTENSION
+ \ LABELS
+ \ LANGUAGE
+ \ LIBRARY_OUTPUT_DIRECTORY
+ \ LIBRARY_OUTPUT_NAME
+ \ LINKER_LANGUAGE
+ \ LINK_DEPENDS
+ \ LINK_DEPENDS_NO_SHARED
+ \ LINK_DIRECTORIES
+ \ LINK_FLAGS
+ \ LINK_INTERFACE_LIBRARIES
+ \ LINK_INTERFACE_MULTIPLICITY
+ \ LINK_LIBRARIES
+ \ LINK_LIBRARIES_ONLY_TARGETS
+ \ LINK_LIBRARY_OVERRIDE
+ \ LINK_OPTIONS
+ \ LINK_SEARCH_END_STATIC
+ \ LINK_SEARCH_START_STATIC
+ \ LINK_WHAT_YOU_USE
+ \ LISTFILE_STACK
+ \ LOCATION
+ \ MACHO_COMPATIBILITY_VERSION
+ \ MACHO_CURRENT_VERSION
+ \ MACOSX_BUNDLE
+ \ MACOSX_BUNDLE_INFO_PLIST
+ \ MACOSX_FRAMEWORK_INFO_PLIST
+ \ MACOSX_PACKAGE_LOCATION
+ \ MACOSX_RPATH
+ \ MACROS
+ \ MANUALLY_ADDED_DEPENDENCIES
+ \ MEASUREMENT
+ \ MODIFIED
+ \ MSVC_DEBUG_INFORMATION_FORMAT
+ \ MSVC_RUNTIME_LIBRARY
+ \ NAME
+ \ NO_SONAME
+ \ NO_SYSTEM_FROM_IMPORTED
+ \ OBJCXX_EXTENSIONS
+ \ OBJCXX_STANDARD
+ \ OBJCXX_STANDARD_REQUIRED
+ \ OBJC_EXTENSIONS
+ \ OBJC_STANDARD
+ \ OBJC_STANDARD_REQUIRED
+ \ OBJECT_DEPENDS
+ \ OBJECT_OUTPUTS
+ \ OPTIMIZE_DEPENDENCIES
+ \ OSX_ARCHITECTURES
+ \ OUTPUT_NAME
+ \ PACKAGES_FOUND
+ \ PACKAGES_NOT_FOUND
+ \ PARENT_DIRECTORY
+ \ PASS_REGULAR_EXPRESSION
+ \ PCH_INSTANTIATE_TEMPLATES
+ \ PCH_WARN_INVALID
+ \ PDB_NAME
+ \ PDB_OUTPUT_DIRECTORY
+ \ POSITION_INDEPENDENT_CODE
+ \ POST_INSTALL_SCRIPT
+ \ PRECOMPILE_HEADERS
+ \ PRECOMPILE_HEADERS_REUSE_FROM
+ \ PREDEFINED_TARGETS_FOLDER
+ \ PREFIX
+ \ PRE_INSTALL_SCRIPT
+ \ PRIVATE_HEADER
+ \ PROCESSORS
+ \ PROCESSOR_AFFINITY
+ \ PROJECT_LABEL
+ \ PUBLIC_HEADER
+ \ REPORT_UNDEFINED_PROPERTIES
+ \ REQUIRED_FILES
+ \ RESOURCE
+ \ RESOURCE_GROUPS
+ \ RESOURCE_LOCK
+ \ RULE_LAUNCH_COMPILE
+ \ RULE_LAUNCH_CUSTOM
+ \ RULE_LAUNCH_LINK
+ \ RULE_MESSAGES
+ \ RUNTIME_OUTPUT_DIRECTORY
+ \ RUNTIME_OUTPUT_NAME
+ \ RUN_SERIAL
+ \ SKIP_AUTOGEN
+ \ SKIP_AUTOMOC
+ \ SKIP_AUTORCC
+ \ SKIP_AUTOUIC
+ \ SKIP_BUILD_RPATH
+ \ SKIP_LINTING
+ \ SKIP_PRECOMPILE_HEADERS
+ \ SKIP_REGULAR_EXPRESSION
+ \ SKIP_RETURN_CODE
+ \ SKIP_UNITY_BUILD_INCLUSION
+ \ SOURCES
+ \ SOURCE_DIR
+ \ SOVERSION
+ \ STATIC_LIBRARY_FLAGS
+ \ STATIC_LIBRARY_OPTIONS
+ \ STRINGS
+ \ SUBDIRECTORIES
+ \ SUFFIX
+ \ SYMBOLIC
+ \ SYSTEM
+ \ Swift_DEPENDENCIES_FILE
+ \ Swift_DIAGNOSTICS_FILE
+ \ Swift_LANGUAGE_VERSION
+ \ Swift_MODULE_DIRECTORY
+ \ Swift_MODULE_NAME
+ \ Swift_COMPILATION_MODE
+ \ TARGET_ARCHIVES_MAY_BE_SHARED_LIBS
+ \ TARGET_MESSAGES
+ \ TARGET_SUPPORTS_SHARED_LIBS
+ \ TESTS
+ \ TEST_INCLUDE_FILE
+ \ TEST_INCLUDE_FILES
+ \ TIMEOUT
+ \ TIMEOUT_AFTER_MATCH
+ \ TIMEOUT_SIGNAL_GRACE_PERIOD
+ \ TIMEOUT_SIGNAL_NAME
+ \ TYPE
+ \ UNITY_BUILD
+ \ UNITY_BUILD_BATCH_SIZE
+ \ UNITY_BUILD_CODE_AFTER_INCLUDE
+ \ UNITY_BUILD_CODE_BEFORE_INCLUDE
+ \ UNITY_BUILD_MODE
+ \ UNITY_BUILD_UNIQUE_ID
+ \ UNITY_GROUP
+ \ USE_FOLDERS
+ \ VALUE
+ \ VARIABLES
+ \ VERIFY_INTERFACE_HEADER_SETS
+ \ VERSION
+ \ VISIBILITY_INLINES_HIDDEN
+ \ VS_CONFIGURATION_TYPE
+ \ VS_COPY_TO_OUT_DIR
+ \ VS_DEBUGGER_COMMAND
+ \ VS_DEBUGGER_COMMAND_ARGUMENTS
+ \ VS_DEBUGGER_ENVIRONMENT
+ \ VS_DEBUGGER_WORKING_DIRECTORY
+ \ VS_DEPLOYMENT_CONTENT
+ \ VS_DEPLOYMENT_LOCATION
+ \ VS_DESKTOP_EXTENSIONS_VERSION
+ \ VS_DOTNET_DOCUMENTATION_FILE
+ \ VS_DOTNET_REFERENCES
+ \ VS_DOTNET_REFERENCES_COPY_LOCAL
+ \ VS_DOTNET_STARTUP_OBJECT
+ \ VS_DOTNET_TARGET_FRAMEWORK_VERSION
+ \ VS_DPI_AWARE
+ \ VS_GLOBAL_KEYWORD
+ \ VS_GLOBAL_PROJECT_TYPES
+ \ VS_GLOBAL_ROOTNAMESPACE
+ \ VS_INCLUDE_IN_VSIX
+ \ VS_IOT_EXTENSIONS_VERSION
+ \ VS_IOT_STARTUP_TASK
+ \ VS_JUST_MY_CODE_DEBUGGING
+ \ VS_KEYWORD
+ \ VS_MOBILE_EXTENSIONS_VERSION
+ \ VS_NO_COMPILE_BATCHING
+ \ VS_NO_SOLUTION_DEPLOY
+ \ VS_PACKAGE_REFERENCES
+ \ VS_PLATFORM_TOOLSET
+ \ VS_PROJECT_IMPORT
+ \ VS_RESOURCE_GENERATOR
+ \ VS_SCC_AUXPATH
+ \ VS_SCC_LOCALPATH
+ \ VS_SCC_PROJECTNAME
+ \ VS_SCC_PROVIDER
+ \ VS_SDK_REFERENCES
+ \ VS_SETTINGS
+ \ VS_SHADER_DISABLE_OPTIMIZATIONS
+ \ VS_SHADER_ENABLE_DEBUG
+ \ VS_SHADER_ENTRYPOINT
+ \ VS_SHADER_FLAGS
+ \ VS_SHADER_MODEL
+ \ VS_SHADER_OBJECT_FILE_NAME
+ \ VS_SHADER_OUTPUT_HEADER_FILE
+ \ VS_SHADER_TYPE
+ \ VS_SHADER_VARIABLE_NAME
+ \ VS_SOLUTION_DEPLOY
+ \ VS_STARTUP_PROJECT
+ \ VS_TOOL_OVERRIDE
+ \ VS_USER_PROPS
+ \ VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION
+ \ VS_WINRT_COMPONENT
+ \ VS_WINRT_EXTENSIONS
+ \ VS_WINRT_REFERENCES
+ \ VS_XAML_TYPE
+ \ WATCOM_RUNTIME_LIBRARY
+ \ WILL_FAIL
+ \ WIN32_EXECUTABLE
+ \ WINDOWS_EXPORT_ALL_SYMBOLS
+ \ WORKING_DIRECTORY
+ \ WRAP_EXCLUDE
+ \ XCODE_EMBED_FRAMEWORKS_CODE_SIGN_ON_COPY
+ \ XCODE_EMBED_FRAMEWORKS_REMOVE_HEADERS_ON_COPY
+ \ XCODE_EMIT_EFFECTIVE_PLATFORM_NAME
+ \ XCODE_EXPLICIT_FILE_TYPE
+ \ XCODE_FILE_ATTRIBUTES
+ \ XCODE_GENERATE_SCHEME
+ \ XCODE_LAST_KNOWN_FILE_TYPE
+ \ XCODE_LINK_BUILD_PHASE_MODE
+ \ XCODE_PRODUCT_TYPE
+ \ XCODE_SCHEME_ADDRESS_SANITIZER
+ \ XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
+ \ XCODE_SCHEME_ARGUMENTS
+ \ XCODE_SCHEME_DEBUG_AS_ROOT
+ \ XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING
+ \ XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE
+ \ XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
+ \ XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
+ \ XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
+ \ XCODE_SCHEME_ENABLE_GPU_API_VALIDATION
+ \ XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE
+ \ XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION
+ \ XCODE_SCHEME_ENVIRONMENT
+ \ XCODE_SCHEME_EXECUTABLE
+ \ XCODE_SCHEME_GUARD_MALLOC
+ \ XCODE_SCHEME_LAUNCH_CONFIGURATION
+ \ XCODE_SCHEME_LAUNCH_MODE
+ \ XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
+ \ XCODE_SCHEME_MALLOC_GUARD_EDGES
+ \ XCODE_SCHEME_MALLOC_SCRIBBLE
+ \ XCODE_SCHEME_MALLOC_STACK
+ \ XCODE_SCHEME_THREAD_SANITIZER
+ \ XCODE_SCHEME_THREAD_SANITIZER_STOP
+ \ XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
+ \ XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+ \ XCODE_SCHEME_ENABLE_GPU_API_VALIDATION
+ \ XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION
+ \ XCODE_SCHEME_LAUNCH_CONFIGURATION
+ \ XCODE_SCHEME_WORKING_DIRECTORY
+ \ XCODE_SCHEME_ZOMBIE_OBJECTS
+ \ XCODE_XCCONFIG
+ \ XCTEST
syn keyword cmakeVariable contained
- \ ANDROID APPLE BORLAND BUILD_SHARED_LIBS CMAKE_ABSOLUTE_DESTINATION_FILES CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS CMAKE_ANDROID_API CMAKE_ANDROID_API_MIN CMAKE_ANDROID_ARCH CMAKE_ANDROID_ARCH_ABI CMAKE_ANDROID_ARM_MODE CMAKE_ANDROID_ARM_NEON CMAKE_ANDROID_ASSETS_DIRECTORIES CMAKE_ANDROID_GUI CMAKE_ANDROID_JAR_DEPENDENCIES CMAKE_ANDROID_JAR_DIRECTORIES CMAKE_ANDROID_JAVA_SOURCE_DIR CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES CMAKE_ANDROID_NDK CMAKE_ANDROID_NDK_DEPRECATED_HEADERS CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION CMAKE_ANDROID_PROCESS_MAX CMAKE_ANDROID_PROGUARD CMAKE_ANDROID_PROGUARD_CONFIG_PATH CMAKE_ANDROID_SECURE_PROPS_PATH CMAKE_ANDROID_SKIP_ANT_STEP CMAKE_ANDROID_STANDALONE_TOOLCHAIN CMAKE_ANDROID_STL_TYPE CMAKE_APPBUNDLE_PATH CMAKE_AR CMAKE_ARCHIVE_OUTPUT_DIRECTORY CMAKE_ARGC CMAKE_ARGV0 CMAKE_AUTOMOC CMAKE_AUTOMOC_DEPEND_FILTERS CMAKE_AUTOMOC_MACRO_NAMES CMAKE_AUTOMOC_MOC_OPTIONS CMAKE_AUTOMOC_RELAXED_MODE CMAKE_AUTORCC CMAKE_AUTORCC_OPTIONS CMAKE_AUTOUIC CMAKE_AUTOUIC_OPTIONS CMAKE_AUTOUIC_SEARCH_PATHS CMAKE_BACKWARDS_COMPATIBILITY CMAKE_BINARY_DIR CMAKE_BUILD_RPATH CMAKE_BUILD_TOOL CMAKE_BUILD_TYPE CMAKE_BUILD_WITH_INSTALL_NAME_DIR CMAKE_BUILD_WITH_INSTALL_RPATH CMAKE_CACHEFILE_DIR CMAKE_CACHE_MAJOR_VERSION CMAKE_CACHE_MINOR_VERSION CMAKE_CACHE_PATCH_VERSION CMAKE_CFG_INTDIR CMAKE_CL_64 CMAKE_CODELITE_USE_TARGETS CMAKE_COLOR_MAKEFILE CMAKE_COMMAND CMAKE_COMPILER_2005 CMAKE_COMPILER_IS_GNUCC CMAKE_COMPILER_IS_GNUCXX CMAKE_COMPILER_IS_GNUG77 CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY CMAKE_CONFIGURATION_TYPES CMAKE_CROSSCOMPILING CMAKE_CROSSCOMPILING_EMULATOR CMAKE_CTEST_COMMAND CMAKE_CUDA_EXTENSIONS CMAKE_CUDA_STANDARD CMAKE_CUDA_STANDARD_REQUIRED CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES CMAKE_CURRENT_BINARY_DIR CMAKE_CURRENT_LIST_DIR CMAKE_CURRENT_LIST_FILE CMAKE_CURRENT_LIST_LINE CMAKE_CURRENT_SOURCE_DIR CMAKE_CXX_COMPILE_FEATURES CMAKE_CXX_EXTENSIONS CMAKE_CXX_STANDARD CMAKE_CXX_STANDARD_REQUIRED CMAKE_C_COMPILE_FEATURES CMAKE_C_EXTENSIONS CMAKE_C_STANDARD CMAKE_C_STANDARD_REQUIRED CMAKE_DEBUG_POSTFIX CMAKE_DEBUG_TARGET_PROPERTIES CMAKE_DEPENDS_IN_PROJECT_ONLY CMAKE_DIRECTORY_LABELS CMAKE_DL_LIBS CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT CMAKE_ECLIPSE_MAKE_ARGUMENTS CMAKE_ECLIPSE_VERSION CMAKE_EDIT_COMMAND CMAKE_ENABLE_EXPORTS CMAKE_ERROR_DEPRECATED CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION CMAKE_EXECUTABLE_SUFFIX CMAKE_EXE_LINKER_FLAGS CMAKE_EXE_LINKER_FLAGS_INIT CMAKE_EXPORT_COMPILE_COMMANDS CMAKE_EXPORT_NO_PACKAGE_REGISTRY CMAKE_EXTRA_GENERATOR CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES CMAKE_FIND_APPBUNDLE CMAKE_FIND_FRAMEWORK CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX CMAKE_FIND_LIBRARY_PREFIXES CMAKE_FIND_LIBRARY_SUFFIXES CMAKE_FIND_NO_INSTALL_PREFIX CMAKE_FIND_PACKAGE_NAME CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY CMAKE_FIND_PACKAGE_SORT_DIRECTION CMAKE_FIND_PACKAGE_SORT_ORDER CMAKE_FIND_PACKAGE_WARN_NO_MODULE CMAKE_FIND_ROOT_PATH CMAKE_FIND_ROOT_PATH_MODE_INCLUDE CMAKE_FIND_ROOT_PATH_MODE_LIBRARY CMAKE_FIND_ROOT_PATH_MODE_PACKAGE CMAKE_FIND_ROOT_PATH_MODE_PROGRAM CMAKE_FRAMEWORK_PATH CMAKE_Fortran_FORMAT CMAKE_Fortran_MODDIR_DEFAULT CMAKE_Fortran_MODDIR_FLAG CMAKE_Fortran_MODOUT_FLAG CMAKE_Fortran_MODULE_DIRECTORY CMAKE_GENERATOR CMAKE_GENERATOR_PLATFORM CMAKE_GENERATOR_TOOLSET CMAKE_GNUtoMS CMAKE_HOME_DIRECTORY CMAKE_HOST_APPLE CMAKE_HOST_SOLARIS CMAKE_HOST_SYSTEM CMAKE_HOST_SYSTEM_NAME CMAKE_HOST_SYSTEM_PROCESSOR CMAKE_HOST_SYSTEM_VERSION CMAKE_HOST_UNIX CMAKE_HOST_WIN32 CMAKE_IGNORE_PATH CMAKE_IMPORT_LIBRARY_PREFIX CMAKE_IMPORT_LIBRARY_SUFFIX CMAKE_INCLUDE_CURRENT_DIR CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE CMAKE_INCLUDE_DIRECTORIES_BEFORE CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE CMAKE_INCLUDE_PATH CMAKE_INSTALL_DEFAULT_COMPONENT_NAME CMAKE_INSTALL_MESSAGE CMAKE_INSTALL_NAME_DIR CMAKE_INSTALL_PREFIX CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT CMAKE_INSTALL_RPATH CMAKE_INSTALL_RPATH_USE_LINK_PATH CMAKE_INTERNAL_PLATFORM_ABI CMAKE_INTERPROCEDURAL_OPTIMIZATION CMAKE_IOS_INSTALL_COMBINED CMAKE_JOB_POOL_COMPILE CMAKE_JOB_POOL_LINK CMAKE_LIBRARY_ARCHITECTURE CMAKE_LIBRARY_ARCHITECTURE_REGEX CMAKE_LIBRARY_OUTPUT_DIRECTORY CMAKE_LIBRARY_PATH CMAKE_LIBRARY_PATH_FLAG CMAKE_LINK_DEF_FILE_FLAG CMAKE_LINK_DEPENDS_NO_SHARED CMAKE_LINK_INTERFACE_LIBRARIES CMAKE_LINK_LIBRARY_FILE_FLAG CMAKE_LINK_LIBRARY_FLAG CMAKE_LINK_LIBRARY_SUFFIX CMAKE_LINK_SEARCH_END_STATIC CMAKE_LINK_SEARCH_START_STATIC CMAKE_LINK_WHAT_YOU_USE CMAKE_MACOSX_BUNDLE CMAKE_MACOSX_RPATH CMAKE_MAJOR_VERSION CMAKE_MAKE_PROGRAM CMAKE_MATCH_COUNT CMAKE_MFC_FLAG CMAKE_MINIMUM_REQUIRED_VERSION CMAKE_MINOR_VERSION CMAKE_MODULE_LINKER_FLAGS CMAKE_MODULE_LINKER_FLAGS_INIT CMAKE_MODULE_PATH CMAKE_MSVCIDE_RUN_PATH CMAKE_NINJA_OUTPUT_PATH_PREFIX CMAKE_NOT_USING_CONFIG_FLAGS CMAKE_NO_BUILTIN_CHRPATH CMAKE_NO_SYSTEM_FROM_IMPORTED CMAKE_OBJECT_PATH_MAX CMAKE_OSX_ARCHITECTURES CMAKE_OSX_DEPLOYMENT_TARGET CMAKE_OSX_SYSROOT CMAKE_PARENT_LIST_FILE CMAKE_PATCH_VERSION CMAKE_PDB_OUTPUT_DIRECTORY CMAKE_POSITION_INDEPENDENT_CODE CMAKE_PREFIX_PATH CMAKE_PROGRAM_PATH CMAKE_PROJECT_DESCRIPTION CMAKE_PROJECT_NAME CMAKE_RANLIB CMAKE_ROOT CMAKE_RUNTIME_OUTPUT_DIRECTORY CMAKE_SCRIPT_MODE_FILE CMAKE_SHARED_LIBRARY_PREFIX CMAKE_SHARED_LIBRARY_SUFFIX CMAKE_SHARED_LINKER_FLAGS CMAKE_SHARED_LINKER_FLAGS_INIT CMAKE_SHARED_MODULE_PREFIX CMAKE_SHARED_MODULE_SUFFIX CMAKE_SIZEOF_VOID_P CMAKE_SKIP_BUILD_RPATH CMAKE_SKIP_INSTALL_ALL_DEPENDENCY CMAKE_SKIP_INSTALL_RPATH CMAKE_SKIP_INSTALL_RULES CMAKE_SKIP_RPATH CMAKE_SOURCE_DIR CMAKE_STAGING_PREFIX CMAKE_STATIC_LIBRARY_PREFIX CMAKE_STATIC_LIBRARY_SUFFIX CMAKE_STATIC_LINKER_FLAGS CMAKE_STATIC_LINKER_FLAGS_INIT CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE CMAKE_SYSROOT CMAKE_SYSROOT_COMPILE CMAKE_SYSROOT_LINK CMAKE_SYSTEM CMAKE_SYSTEM_APPBUNDLE_PATH CMAKE_SYSTEM_FRAMEWORK_PATH CMAKE_SYSTEM_IGNORE_PATH CMAKE_SYSTEM_INCLUDE_PATH CMAKE_SYSTEM_LIBRARY_PATH CMAKE_SYSTEM_NAME CMAKE_SYSTEM_PREFIX_PATH CMAKE_SYSTEM_PROCESSOR CMAKE_SYSTEM_PROGRAM_PATH CMAKE_SYSTEM_VERSION CMAKE_Swift_LANGUAGE_VERSION CMAKE_TOOLCHAIN_FILE CMAKE_TRY_COMPILE_CONFIGURATION CMAKE_TRY_COMPILE_PLATFORM_VARIABLES CMAKE_TRY_COMPILE_TARGET_TYPE CMAKE_TWEAK_VERSION CMAKE_USER_MAKE_RULES_OVERRIDE CMAKE_USE_RELATIVE_PATHS CMAKE_VERBOSE_MAKEFILE CMAKE_VERSION CMAKE_VISIBILITY_INLINES_HIDDEN CMAKE_VS_DEVENV_COMMAND CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD CMAKE_VS_INTEL_Fortran_PROJECT_VERSION CMAKE_VS_MSBUILD_COMMAND CMAKE_VS_NsightTegra_VERSION CMAKE_VS_PLATFORM_NAME CMAKE_VS_PLATFORM_TOOLSET CMAKE_VS_PLATFORM_TOOLSET_CUDA CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION CMAKE_WARN_DEPRECATED CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION CMAKE_WIN32_EXECUTABLE CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS CMAKE_XCODE_GENERATE_SCHEME CMAKE_XCODE_PLATFORM_TOOLSET CPACK_ABSOLUTE_DESTINATION_FILES CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION CPACK_INCLUDE_TOPLEVEL_DIRECTORY CPACK_INSTALL_SCRIPT CPACK_PACKAGING_INSTALL_PREFIX CPACK_SET_DESTDIR CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION CTEST_BINARY_DIRECTORY CTEST_BUILD_COMMAND CTEST_BUILD_NAME CTEST_BZR_COMMAND CTEST_BZR_UPDATE_OPTIONS CTEST_CHANGE_ID CTEST_CHECKOUT_COMMAND CTEST_CONFIGURATION_TYPE CTEST_CONFIGURE_COMMAND CTEST_COVERAGE_COMMAND CTEST_COVERAGE_EXTRA_FLAGS CTEST_CURL_OPTIONS CTEST_CUSTOM_COVERAGE_EXCLUDE CTEST_CUSTOM_ERROR_EXCEPTION CTEST_CUSTOM_ERROR_MATCH CTEST_CUSTOM_ERROR_POST_CONTEXT CTEST_CUSTOM_ERROR_PRE_CONTEXT CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE CTEST_CUSTOM_MEMCHECK_IGNORE CTEST_CUSTOM_POST_MEMCHECK CTEST_CUSTOM_POST_TEST CTEST_CUSTOM_PRE_MEMCHECK CTEST_CUSTOM_PRE_TEST CTEST_CUSTOM_TEST_IGNORE CTEST_CUSTOM_WARNING_EXCEPTION CTEST_CUSTOM_WARNING_MATCH CTEST_CVS_CHECKOUT CTEST_CVS_COMMAND CTEST_CVS_UPDATE_OPTIONS CTEST_DROP_LOCATION CTEST_DROP_METHOD CTEST_DROP_SITE CTEST_DROP_SITE_CDASH CTEST_DROP_SITE_PASSWORD CTEST_DROP_SITE_USER CTEST_EXTRA_COVERAGE_GLOB CTEST_GIT_COMMAND CTEST_GIT_INIT_SUBMODULES CTEST_GIT_UPDATE_CUSTOM CTEST_GIT_UPDATE_OPTIONS CTEST_HG_COMMAND CTEST_HG_UPDATE_OPTIONS CTEST_LABELS_FOR_SUBPROJECTS CTEST_MEMORYCHECK_COMMAND CTEST_MEMORYCHECK_COMMAND_OPTIONS CTEST_MEMORYCHECK_SANITIZER_OPTIONS CTEST_MEMORYCHECK_SUPPRESSIONS_FILE CTEST_MEMORYCHECK_TYPE CTEST_NIGHTLY_START_TIME CTEST_P4_CLIENT CTEST_P4_COMMAND CTEST_P4_OPTIONS CTEST_P4_UPDATE_OPTIONS CTEST_SCP_COMMAND CTEST_SITE CTEST_SOURCE_DIRECTORY CTEST_SVN_COMMAND CTEST_SVN_OPTIONS CTEST_SVN_UPDATE_OPTIONS CTEST_TEST_LOAD CTEST_TEST_TIMEOUT CTEST_TRIGGER_SITE CTEST_UPDATE_COMMAND CTEST_UPDATE_OPTIONS CTEST_UPDATE_VERSION_ONLY CTEST_USE_LAUNCHERS CYGWIN ENV EXECUTABLE_OUTPUT_PATH GHS-MULTI LIBRARY_OUTPUT_PATH MINGW MSVC MSVC10 MSVC11 MSVC12 MSVC14 MSVC60 MSVC70 MSVC71 MSVC80 MSVC90 MSVC_IDE MSVC_VERSION PROJECT_BINARY_DIR PROJECT_DESCRIPTION PROJECT_NAME PROJECT_SOURCE_DIR PROJECT_VERSION PROJECT_VERSION_MAJOR PROJECT_VERSION_MINOR PROJECT_VERSION_PATCH PROJECT_VERSION_TWEAK UNIX WIN32 WINCE WINDOWS_PHONE WINDOWS_STORE XCODE XCODE_VERSION
+ \ ANDROID
+ \ APPLE
+ \ BORLAND
+ \ BSD
+ \ BUILD_SHARED_LIBS
+ \ CACHE
+ \ CMAKE_ABSOLUTE_DESTINATION_FILES
+ \ CMAKE_ADD_CUSTOM_COMMAND_DEPENDS_EXPLICIT_ONLY
+ \ CMAKE_ADSP_ROOT
+ \ CMAKE_AIX_EXPORT_ALL_SYMBOLS
+ \ CMAKE_ANDROID_ANT_ADDITIONAL_OPTIONS
+ \ CMAKE_ANDROID_API
+ \ CMAKE_ANDROID_API_MIN
+ \ CMAKE_ANDROID_ARCH
+ \ CMAKE_ANDROID_ARCH_ABI
+ \ CMAKE_ANDROID_ARM_MODE
+ \ CMAKE_ANDROID_ARM_NEON
+ \ CMAKE_ANDROID_ASSETS_DIRECTORIES
+ \ CMAKE_ANDROID_EXCEPTIONS
+ \ CMAKE_ANDROID_GUI
+ \ CMAKE_ANDROID_JAR_DEPENDENCIES
+ \ CMAKE_ANDROID_JAR_DIRECTORIES
+ \ CMAKE_ANDROID_JAVA_SOURCE_DIR
+ \ CMAKE_ANDROID_NATIVE_LIB_DEPENDENCIES
+ \ CMAKE_ANDROID_NATIVE_LIB_DIRECTORIES
+ \ CMAKE_ANDROID_NDK
+ \ CMAKE_ANDROID_NDK_DEPRECATED_HEADERS
+ \ CMAKE_ANDROID_NDK_TOOLCHAIN_HOST_TAG
+ \ CMAKE_ANDROID_NDK_TOOLCHAIN_VERSION
+ \ CMAKE_ANDROID_NDK_VERSION
+ \ CMAKE_ANDROID_PROCESS_MAX
+ \ CMAKE_ANDROID_PROGUARD
+ \ CMAKE_ANDROID_PROGUARD_CONFIG_PATH
+ \ CMAKE_ANDROID_RTTI
+ \ CMAKE_ANDROID_SECURE_PROPS_PATH
+ \ CMAKE_ANDROID_SKIP_ANT_STEP
+ \ CMAKE_ANDROID_STANDALONE_TOOLCHAIN
+ \ CMAKE_ANDROID_STL_TYPE
+ \ CMAKE_APPBUNDLE_PATH
+ \ CMAKE_APPLE_SILICON_PROCESSOR
+ \ CMAKE_AR
+ \ CMAKE_ARCHIVE_OUTPUT_DIRECTORY
+ \ CMAKE_ARGC
+ \ CMAKE_ARGV0
+ \ CMAKE_ASM
+ \ CMAKE_ASM_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_ASM_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_ASM_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_ASM_ARCHIVE_APPEND
+ \ CMAKE_ASM_ARCHIVE_CREATE
+ \ CMAKE_ASM_ARCHIVE_FINISH
+ \ CMAKE_ASM_BYTE_ORDER
+ \ CMAKE_ASM_CLANG_TIDY
+ \ CMAKE_ASM_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_ASM_COMPILER
+ \ CMAKE_ASM_COMPILER_ABI
+ \ CMAKE_ASM_COMPILER_AR
+ \ CMAKE_ASM_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_ASM_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_ASM_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_ASM_COMPILER_ID
+ \ CMAKE_ASM_COMPILER_LAUNCHER
+ \ CMAKE_ASM_COMPILER_LOADED
+ \ CMAKE_ASM_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_ASM_COMPILER_RANLIB
+ \ CMAKE_ASM_COMPILER_TARGET
+ \ CMAKE_ASM_COMPILER_VERSION
+ \ CMAKE_ASM_COMPILER_VERSION_INTERNAL
+ \ CMAKE_ASM_COMPILE_OBJECT
+ \ CMAKE_ASM_CPPCHECK
+ \ CMAKE_ASM_CPPLINT
+ \ CMAKE_ASM_CREATE_SHARED_LIBRARY
+ \ CMAKE_ASM_CREATE_SHARED_MODULE
+ \ CMAKE_ASM_CREATE_STATIC_LIBRARY
+ \ CMAKE_ASM_EXTENSIONS
+ \ CMAKE_ASM_EXTENSIONS_DEFAULT
+ \ CMAKE_ASM_FLAGS
+ \ CMAKE_ASM_FLAGS_DEBUG
+ \ CMAKE_ASM_FLAGS_DEBUG_INIT
+ \ CMAKE_ASM_FLAGS_INIT
+ \ CMAKE_ASM_FLAGS_MINSIZEREL
+ \ CMAKE_ASM_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_ASM_FLAGS_RELEASE
+ \ CMAKE_ASM_FLAGS_RELEASE_INIT
+ \ CMAKE_ASM_FLAGS_RELWITHDEBINFO
+ \ CMAKE_ASM_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_ASM_IGNORE_EXTENSIONS
+ \ CMAKE_ASM_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_ASM_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_ASM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_ASM_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_ASM_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_ASM_INIT
+ \ CMAKE_ASM_LIBRARY_ARCHITECTURE
+ \ CMAKE_ASM_LINKER_LAUNCHER
+ \ CMAKE_ASM_LINKER_PREFERENCE
+ \ CMAKE_ASM_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_ASM_LINKER_WRAPPER_FLAG
+ \ CMAKE_ASM_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_ASM_LINK_EXECUTABLE
+ \ CMAKE_ASM_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_ASM_LINK_LIBRARY_FLAG
+ \ CMAKE_ASM_LINK_LIBRARY_SUFFIX
+ \ CMAKE_ASM_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_ASM_MASM
+ \ CMAKE_ASM_MASM_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_ASM_MASM_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_ASM_MASM_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_ASM_MASM_ARCHIVE_APPEND
+ \ CMAKE_ASM_MASM_ARCHIVE_CREATE
+ \ CMAKE_ASM_MASM_ARCHIVE_FINISH
+ \ CMAKE_ASM_MASM_BYTE_ORDER
+ \ CMAKE_ASM_MASM_CLANG_TIDY
+ \ CMAKE_ASM_MASM_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_ASM_MASM_COMPILER
+ \ CMAKE_ASM_MASM_COMPILER_ABI
+ \ CMAKE_ASM_MASM_COMPILER_AR
+ \ CMAKE_ASM_MASM_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_ASM_MASM_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_ASM_MASM_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_ASM_MASM_COMPILER_ID
+ \ CMAKE_ASM_MASM_COMPILER_LAUNCHER
+ \ CMAKE_ASM_MASM_COMPILER_LOADED
+ \ CMAKE_ASM_MASM_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_ASM_MASM_COMPILER_RANLIB
+ \ CMAKE_ASM_MASM_COMPILER_TARGET
+ \ CMAKE_ASM_MASM_COMPILER_VERSION
+ \ CMAKE_ASM_MASM_COMPILER_VERSION_INTERNAL
+ \ CMAKE_ASM_MASM_COMPILE_OBJECT
+ \ CMAKE_ASM_MASM_CPPCHECK
+ \ CMAKE_ASM_MASM_CPPLINT
+ \ CMAKE_ASM_MASM_CREATE_SHARED_LIBRARY
+ \ CMAKE_ASM_MASM_CREATE_SHARED_MODULE
+ \ CMAKE_ASM_MASM_CREATE_STATIC_LIBRARY
+ \ CMAKE_ASM_MASM_EXTENSIONS
+ \ CMAKE_ASM_MASM_EXTENSIONS_DEFAULT
+ \ CMAKE_ASM_MASM_FLAGS
+ \ CMAKE_ASM_MASM_FLAGS_DEBUG
+ \ CMAKE_ASM_MASM_FLAGS_DEBUG_INIT
+ \ CMAKE_ASM_MASM_FLAGS_INIT
+ \ CMAKE_ASM_MASM_FLAGS_MINSIZEREL
+ \ CMAKE_ASM_MASM_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_ASM_MASM_FLAGS_RELEASE
+ \ CMAKE_ASM_MASM_FLAGS_RELEASE_INIT
+ \ CMAKE_ASM_MASM_FLAGS_RELWITHDEBINFO
+ \ CMAKE_ASM_MASM_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_ASM_MASM_IGNORE_EXTENSIONS
+ \ CMAKE_ASM_MASM_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_ASM_MASM_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_ASM_MASM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_ASM_MASM_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_ASM_MASM_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_ASM_MASM_INIT
+ \ CMAKE_ASM_MASM_LIBRARY_ARCHITECTURE
+ \ CMAKE_ASM_MASM_LINKER_LAUNCHER
+ \ CMAKE_ASM_MASM_LINKER_PREFERENCE
+ \ CMAKE_ASM_MASM_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_ASM_MASM_LINKER_WRAPPER_FLAG
+ \ CMAKE_ASM_MASM_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_ASM_MASM_LINK_EXECUTABLE
+ \ CMAKE_ASM_MASM_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_ASM_MASM_LINK_LIBRARY_FLAG
+ \ CMAKE_ASM_MASM_LINK_LIBRARY_SUFFIX
+ \ CMAKE_ASM_MASM_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_ASM_MASM_OUTPUT_EXTENSION
+ \ CMAKE_ASM_MASM_PLATFORM_ID
+ \ CMAKE_ASM_MASM_SIMULATE_ID
+ \ CMAKE_ASM_MASM_SIMULATE_VERSION
+ \ CMAKE_ASM_MASM_SIZEOF_DATA_PTR
+ \ CMAKE_ASM_MASM_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_ASM_MASM_STANDARD
+ \ CMAKE_ASM_MASM_STANDARD_DEFAULT
+ \ CMAKE_ASM_MASM_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_ASM_MASM_STANDARD_LIBRARIES
+ \ CMAKE_ASM_MASM_STANDARD_REQUIRED
+ \ CMAKE_ASM_MASM_SUPPORTED
+ \ CMAKE_ASM_MASM_VISIBILITY_PRESET
+ \ CMAKE_ASM_NASM
+ \ CMAKE_ASM_NASM_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_ASM_NASM_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_ASM_NASM_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_ASM_NASM_ARCHIVE_APPEND
+ \ CMAKE_ASM_NASM_ARCHIVE_CREATE
+ \ CMAKE_ASM_NASM_ARCHIVE_FINISH
+ \ CMAKE_ASM_NASM_BYTE_ORDER
+ \ CMAKE_ASM_NASM_CLANG_TIDY
+ \ CMAKE_ASM_NASM_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_ASM_NASM_COMPILER
+ \ CMAKE_ASM_NASM_COMPILER_ABI
+ \ CMAKE_ASM_NASM_COMPILER_AR
+ \ CMAKE_ASM_NASM_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_ASM_NASM_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_ASM_NASM_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_ASM_NASM_COMPILER_ID
+ \ CMAKE_ASM_NASM_COMPILER_LAUNCHER
+ \ CMAKE_ASM_NASM_COMPILER_LOADED
+ \ CMAKE_ASM_NASM_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_ASM_NASM_COMPILER_RANLIB
+ \ CMAKE_ASM_NASM_COMPILER_TARGET
+ \ CMAKE_ASM_NASM_COMPILER_VERSION
+ \ CMAKE_ASM_NASM_COMPILER_VERSION_INTERNAL
+ \ CMAKE_ASM_NASM_COMPILE_OBJECT
+ \ CMAKE_ASM_NASM_CPPCHECK
+ \ CMAKE_ASM_NASM_CPPLINT
+ \ CMAKE_ASM_NASM_CREATE_SHARED_LIBRARY
+ \ CMAKE_ASM_NASM_CREATE_SHARED_MODULE
+ \ CMAKE_ASM_NASM_CREATE_STATIC_LIBRARY
+ \ CMAKE_ASM_NASM_EXTENSIONS
+ \ CMAKE_ASM_NASM_EXTENSIONS_DEFAULT
+ \ CMAKE_ASM_NASM_FLAGS
+ \ CMAKE_ASM_NASM_FLAGS_DEBUG
+ \ CMAKE_ASM_NASM_FLAGS_DEBUG_INIT
+ \ CMAKE_ASM_NASM_FLAGS_INIT
+ \ CMAKE_ASM_NASM_FLAGS_MINSIZEREL
+ \ CMAKE_ASM_NASM_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_ASM_NASM_FLAGS_RELEASE
+ \ CMAKE_ASM_NASM_FLAGS_RELEASE_INIT
+ \ CMAKE_ASM_NASM_FLAGS_RELWITHDEBINFO
+ \ CMAKE_ASM_NASM_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_ASM_NASM_IGNORE_EXTENSIONS
+ \ CMAKE_ASM_NASM_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_ASM_NASM_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_ASM_NASM_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_ASM_NASM_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_ASM_NASM_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_ASM_NASM_INIT
+ \ CMAKE_ASM_NASM_LIBRARY_ARCHITECTURE
+ \ CMAKE_ASM_NASM_LINKER_LAUNCHER
+ \ CMAKE_ASM_NASM_LINKER_PREFERENCE
+ \ CMAKE_ASM_NASM_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_ASM_NASM_LINKER_WRAPPER_FLAG
+ \ CMAKE_ASM_NASM_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_ASM_NASM_LINK_EXECUTABLE
+ \ CMAKE_ASM_NASM_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_ASM_NASM_LINK_LIBRARY_FLAG
+ \ CMAKE_ASM_NASM_LINK_LIBRARY_SUFFIX
+ \ CMAKE_ASM_NASM_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_ASM_NASM_OUTPUT_EXTENSION
+ \ CMAKE_ASM_NASM_PLATFORM_ID
+ \ CMAKE_ASM_NASM_SIMULATE_ID
+ \ CMAKE_ASM_NASM_SIMULATE_VERSION
+ \ CMAKE_ASM_NASM_SIZEOF_DATA_PTR
+ \ CMAKE_ASM_NASM_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_ASM_NASM_STANDARD
+ \ CMAKE_ASM_NASM_STANDARD_DEFAULT
+ \ CMAKE_ASM_NASM_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_ASM_NASM_STANDARD_LIBRARIES
+ \ CMAKE_ASM_NASM_STANDARD_REQUIRED
+ \ CMAKE_ASM_NASM_SUPPORTED
+ \ CMAKE_ASM_NASM_VISIBILITY_PRESET
+ \ CMAKE_ASM_OUTPUT_EXTENSION
+ \ CMAKE_ASM_PLATFORM_ID
+ \ CMAKE_ASM_SIMULATE_ID
+ \ CMAKE_ASM_SIMULATE_VERSION
+ \ CMAKE_ASM_SIZEOF_DATA_PTR
+ \ CMAKE_ASM_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_ASM_STANDARD
+ \ CMAKE_ASM_STANDARD_DEFAULT
+ \ CMAKE_ASM_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_ASM_STANDARD_LIBRARIES
+ \ CMAKE_ASM_STANDARD_REQUIRED
+ \ CMAKE_ASM_SUPPORTED
+ \ CMAKE_ASM_VISIBILITY_PRESET
+ \ CMAKE_AUTOGEN_COMMAND_LINE_LENGTH_MAX
+ \ CMAKE_AUTOGEN_ORIGIN_DEPENDS
+ \ CMAKE_AUTOGEN_PARALLEL
+ \ CMAKE_AUTOGEN_USE_SYSTEM_INCLUDE
+ \ CMAKE_AUTOGEN_VERBOSE
+ \ CMAKE_AUTOMOC
+ \ CMAKE_AUTOMOC_COMPILER_PREDEFINES
+ \ CMAKE_AUTOMOC_DEPEND_FILTERS
+ \ CMAKE_AUTOMOC_EXECUTABLE
+ \ CMAKE_AUTOMOC_MACRO_NAMES
+ \ CMAKE_AUTOMOC_MOC_OPTIONS
+ \ CMAKE_AUTOMOC_PATH_PREFIX
+ \ CMAKE_AUTOMOC_RELAXED_MODE
+ \ CMAKE_AUTOMOC_EXECUTABLE
+ \ CMAKE_AUTORCC
+ \ CMAKE_AUTORCC_EXECUTABLE
+ \ CMAKE_AUTORCC_OPTIONS
+ \ CMAKE_AUTORCC_EXECUTABLE
+ \ CMAKE_AUTOUIC
+ \ CMAKE_AUTOUIC_EXECUTABLE
+ \ CMAKE_AUTOUIC_OPTIONS
+ \ CMAKE_AUTOUIC_SEARCH_PATHS
+ \ CMAKE_AUTOUIC_EXECUTABLE
+ \ CMAKE_BACKWARDS_COMPATIBILITY
+ \ CMAKE_BINARY_DIR
+ \ CMAKE_BUILD_RPATH
+ \ CMAKE_BUILD_RPATH_USE_ORIGIN
+ \ CMAKE_BUILD_TOOL
+ \ CMAKE_BUILD_TYPE
+ \ CMAKE_BUILD_WITH_INSTALL_NAME_DIR
+ \ CMAKE_BUILD_WITH_INSTALL_RPATH
+ \ CMAKE_C
+ \ CMAKE_CACHEFILE_DIR
+ \ CMAKE_CACHE_MAJOR_VERSION
+ \ CMAKE_CACHE_MINOR_VERSION
+ \ CMAKE_CACHE_PATCH_VERSION
+ \ CMAKE_CFG_INTDIR
+ \ CMAKE_CLANG_VFS_OVERLAY
+ \ CMAKE_CL_64
+ \ CMAKE_CODEBLOCKS_COMPILER_ID
+ \ CMAKE_CODEBLOCKS_EXCLUDE_EXTERNAL_FILES
+ \ CMAKE_CODELITE_USE_TARGETS
+ \ CMAKE_COLOR_DIAGNOSTICS
+ \ CMAKE_COLOR_MAKEFILE
+ \ CMAKE_COMMAND
+ \ CMAKE_COMPILER_2005
+ \ CMAKE_COMPILER_IS_GNUCC
+ \ CMAKE_COMPILER_IS_GNUCXX
+ \ CMAKE_COMPILER_IS_GNUG77
+ \ CMAKE_COMPILE_PDB_OUTPUT_DIRECTORY
+ \ CMAKE_COMPILE_WARNING_AS_ERROR
+ \ CMAKE_CONFIGURATION_TYPES
+ \ CMAKE_CPACK_COMMAND
+ \ CMAKE_CROSSCOMPILING
+ \ CMAKE_CROSSCOMPILING_EMULATOR
+ \ CMAKE_CROSS_CONFIGS
+ \ CMAKE_CSharp
+ \ CMAKE_CSharp_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_CSharp_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_CSharp_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_CSharp_ARCHIVE_APPEND
+ \ CMAKE_CSharp_ARCHIVE_CREATE
+ \ CMAKE_CSharp_ARCHIVE_FINISH
+ \ CMAKE_CSharp_BYTE_ORDER
+ \ CMAKE_CSharp_CLANG_TIDY
+ \ CMAKE_CSharp_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_CSharp_COMPILER
+ \ CMAKE_CSharp_COMPILER_ABI
+ \ CMAKE_CSharp_COMPILER_AR
+ \ CMAKE_CSharp_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_CSharp_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_CSharp_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_CSharp_COMPILER_ID
+ \ CMAKE_CSharp_COMPILER_LAUNCHER
+ \ CMAKE_CSharp_COMPILER_LOADED
+ \ CMAKE_CSharp_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_CSharp_COMPILER_RANLIB
+ \ CMAKE_CSharp_COMPILER_TARGET
+ \ CMAKE_CSharp_COMPILER_VERSION
+ \ CMAKE_CSharp_COMPILER_VERSION_INTERNAL
+ \ CMAKE_CSharp_COMPILE_OBJECT
+ \ CMAKE_CSharp_CPPCHECK
+ \ CMAKE_CSharp_CPPLINT
+ \ CMAKE_CSharp_CREATE_SHARED_LIBRARY
+ \ CMAKE_CSharp_CREATE_SHARED_MODULE
+ \ CMAKE_CSharp_CREATE_STATIC_LIBRARY
+ \ CMAKE_CSharp_EXTENSIONS
+ \ CMAKE_CSharp_EXTENSIONS_DEFAULT
+ \ CMAKE_CSharp_FLAGS
+ \ CMAKE_CSharp_FLAGS_DEBUG
+ \ CMAKE_CSharp_FLAGS_DEBUG_INIT
+ \ CMAKE_CSharp_FLAGS_INIT
+ \ CMAKE_CSharp_FLAGS_MINSIZEREL
+ \ CMAKE_CSharp_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_CSharp_FLAGS_RELEASE
+ \ CMAKE_CSharp_FLAGS_RELEASE_INIT
+ \ CMAKE_CSharp_FLAGS_RELWITHDEBINFO
+ \ CMAKE_CSharp_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_CSharp_IGNORE_EXTENSIONS
+ \ CMAKE_CSharp_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_CSharp_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_CSharp_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_CSharp_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_CSharp_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_CSharp_INIT
+ \ CMAKE_CSharp_LIBRARY_ARCHITECTURE
+ \ CMAKE_CSharp_LINKER_LAUNCHER
+ \ CMAKE_CSharp_LINKER_PREFERENCE
+ \ CMAKE_CSharp_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_CSharp_LINKER_WRAPPER_FLAG
+ \ CMAKE_CSharp_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_CSharp_LINK_EXECUTABLE
+ \ CMAKE_CSharp_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_CSharp_LINK_LIBRARY_FLAG
+ \ CMAKE_CSharp_LINK_LIBRARY_SUFFIX
+ \ CMAKE_CSharp_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_CSharp_OUTPUT_EXTENSION
+ \ CMAKE_CSharp_PLATFORM_ID
+ \ CMAKE_CSharp_SIMULATE_ID
+ \ CMAKE_CSharp_SIMULATE_VERSION
+ \ CMAKE_CSharp_SIZEOF_DATA_PTR
+ \ CMAKE_CSharp_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_CSharp_STANDARD
+ \ CMAKE_CSharp_STANDARD_DEFAULT
+ \ CMAKE_CSharp_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_CSharp_STANDARD_LIBRARIES
+ \ CMAKE_CSharp_STANDARD_REQUIRED
+ \ CMAKE_CSharp_SUPPORTED
+ \ CMAKE_CSharp_VISIBILITY_PRESET
+ \ CMAKE_CTEST_ARGUMENTS
+ \ CMAKE_CTEST_COMMAND
+ \ CMAKE_CUDA
+ \ CMAKE_CUDA_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_CUDA_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_CUDA_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_CUDA_ARCHITECTURES
+ \ CMAKE_CUDA_ARCHIVE_APPEND
+ \ CMAKE_CUDA_ARCHIVE_CREATE
+ \ CMAKE_CUDA_ARCHIVE_FINISH
+ \ CMAKE_CUDA_BYTE_ORDER
+ \ CMAKE_CUDA_CLANG_TIDY
+ \ CMAKE_CUDA_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_CUDA_COMPILER
+ \ CMAKE_CUDA_COMPILER_ABI
+ \ CMAKE_CUDA_COMPILER_AR
+ \ CMAKE_CUDA_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_CUDA_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_CUDA_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_CUDA_COMPILER_ID
+ \ CMAKE_CUDA_COMPILER_LAUNCHER
+ \ CMAKE_CUDA_COMPILER_LOADED
+ \ CMAKE_CUDA_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_CUDA_COMPILER_RANLIB
+ \ CMAKE_CUDA_COMPILER_TARGET
+ \ CMAKE_CUDA_COMPILER_VERSION
+ \ CMAKE_CUDA_COMPILER_VERSION_INTERNAL
+ \ CMAKE_CUDA_COMPILE_FEATURES
+ \ CMAKE_CUDA_COMPILE_OBJECT
+ \ CMAKE_CUDA_CPPCHECK
+ \ CMAKE_CUDA_CPPLINT
+ \ CMAKE_CUDA_CREATE_SHARED_LIBRARY
+ \ CMAKE_CUDA_CREATE_SHARED_MODULE
+ \ CMAKE_CUDA_CREATE_STATIC_LIBRARY
+ \ CMAKE_CUDA_EXTENSIONS
+ \ CMAKE_CUDA_EXTENSIONS_DEFAULT
+ \ CMAKE_CUDA_FLAGS
+ \ CMAKE_CUDA_FLAGS_DEBUG
+ \ CMAKE_CUDA_FLAGS_DEBUG_INIT
+ \ CMAKE_CUDA_FLAGS_INIT
+ \ CMAKE_CUDA_FLAGS_MINSIZEREL
+ \ CMAKE_CUDA_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_CUDA_FLAGS_RELEASE
+ \ CMAKE_CUDA_FLAGS_RELEASE_INIT
+ \ CMAKE_CUDA_FLAGS_RELWITHDEBINFO
+ \ CMAKE_CUDA_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_CUDA_HOST_COMPILER
+ \ CMAKE_CUDA_IGNORE_EXTENSIONS
+ \ CMAKE_CUDA_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_CUDA_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_CUDA_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_CUDA_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_CUDA_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_CUDA_INIT
+ \ CMAKE_CUDA_LIBRARY_ARCHITECTURE
+ \ CMAKE_CUDA_LINKER_LAUNCHER
+ \ CMAKE_CUDA_LINKER_PREFERENCE
+ \ CMAKE_CUDA_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_CUDA_LINKER_WRAPPER_FLAG
+ \ CMAKE_CUDA_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_CUDA_LINK_EXECUTABLE
+ \ CMAKE_CUDA_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_CUDA_LINK_LIBRARY_FLAG
+ \ CMAKE_CUDA_LINK_LIBRARY_SUFFIX
+ \ CMAKE_CUDA_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_CUDA_OUTPUT_EXTENSION
+ \ CMAKE_CUDA_PLATFORM_ID
+ \ CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS
+ \ CMAKE_CUDA_RUNTIME_LIBRARY
+ \ CMAKE_CUDA_SEPARABLE_COMPILATION
+ \ CMAKE_CUDA_SIMULATE_ID
+ \ CMAKE_CUDA_SIMULATE_VERSION
+ \ CMAKE_CUDA_SIZEOF_DATA_PTR
+ \ CMAKE_CUDA_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_CUDA_STANDARD
+ \ CMAKE_CUDA_STANDARD_DEFAULT
+ \ CMAKE_CUDA_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_CUDA_STANDARD_LIBRARIES
+ \ CMAKE_CUDA_STANDARD_REQUIRED
+ \ CMAKE_CUDA_SUPPORTED
+ \ CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES
+ \ CMAKE_CUDA_VISIBILITY_PRESET
+ \ CMAKE_CURRENT_BINARY_DIR
+ \ CMAKE_CURRENT_FUNCTION
+ \ CMAKE_CURRENT_FUNCTION_LIST_DIR
+ \ CMAKE_CURRENT_FUNCTION_LIST_FILE
+ \ CMAKE_CURRENT_FUNCTION_LIST_LINE
+ \ CMAKE_CURRENT_LIST_DIR
+ \ CMAKE_CURRENT_LIST_FILE
+ \ CMAKE_CURRENT_LIST_LINE
+ \ CMAKE_CURRENT_SOURCE_DIR
+ \ CMAKE_CXX
+ \ CMAKE_CXX_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_CXX_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_CXX_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_CXX_ARCHIVE_APPEND
+ \ CMAKE_CXX_ARCHIVE_CREATE
+ \ CMAKE_CXX_ARCHIVE_FINISH
+ \ CMAKE_CXX_BYTE_ORDER
+ \ CMAKE_CXX_CLANG_TIDY
+ \ CMAKE_CXX_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_CXX_COMPILER
+ \ CMAKE_CXX_COMPILER_ABI
+ \ CMAKE_CXX_COMPILER_AR
+ \ CMAKE_CXX_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_CXX_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_CXX_COMPILER_ID
+ \ CMAKE_CXX_COMPILER_LAUNCHER
+ \ CMAKE_CXX_COMPILER_LOADED
+ \ CMAKE_CXX_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_CXX_COMPILER_RANLIB
+ \ CMAKE_CXX_COMPILER_TARGET
+ \ CMAKE_CXX_COMPILER_VERSION
+ \ CMAKE_CXX_COMPILER_VERSION_INTERNAL
+ \ CMAKE_CXX_COMPILE_FEATURES
+ \ CMAKE_CXX_COMPILE_OBJECT
+ \ CMAKE_CXX_CPPCHECK
+ \ CMAKE_CXX_CPPLINT
+ \ CMAKE_CXX_CREATE_SHARED_LIBRARY
+ \ CMAKE_CXX_CREATE_SHARED_MODULE
+ \ CMAKE_CXX_CREATE_STATIC_LIBRARY
+ \ CMAKE_CXX_EXTENSIONS
+ \ CMAKE_CXX_EXTENSIONS_DEFAULT
+ \ CMAKE_CXX_FLAGS
+ \ CMAKE_CXX_FLAGS_DEBUG
+ \ CMAKE_CXX_FLAGS_DEBUG_INIT
+ \ CMAKE_CXX_FLAGS_INIT
+ \ CMAKE_CXX_FLAGS_MINSIZEREL
+ \ CMAKE_CXX_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_CXX_FLAGS_RELEASE
+ \ CMAKE_CXX_FLAGS_RELEASE_INIT
+ \ CMAKE_CXX_FLAGS_RELWITHDEBINFO
+ \ CMAKE_CXX_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_CXX_IGNORE_EXTENSIONS
+ \ CMAKE_CXX_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_CXX_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_CXX_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_CXX_INIT
+ \ CMAKE_CXX_LIBRARY_ARCHITECTURE
+ \ CMAKE_CXX_LINKER_LAUNCHER
+ \ CMAKE_CXX_LINKER_PREFERENCE
+ \ CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_CXX_LINKER_WRAPPER_FLAG
+ \ CMAKE_CXX_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_CXX_LINK_EXECUTABLE
+ \ CMAKE_CXX_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_CXX_LINK_LIBRARY_FLAG
+ \ CMAKE_CXX_LINK_LIBRARY_SUFFIX
+ \ CMAKE_CXX_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_CXX_OUTPUT_EXTENSION
+ \ CMAKE_CXX_PLATFORM_ID
+ \ CMAKE_CXX_SCAN_FOR_MODULES
+ \ CMAKE_CXX_SIMULATE_ID
+ \ CMAKE_CXX_SIMULATE_VERSION
+ \ CMAKE_CXX_SIZEOF_DATA_PTR
+ \ CMAKE_CXX_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_CXX_STANDARD
+ \ CMAKE_CXX_STANDARD_DEFAULT
+ \ CMAKE_CXX_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_CXX_STANDARD_LIBRARIES
+ \ CMAKE_CXX_STANDARD_REQUIRED
+ \ CMAKE_CXX_SUPPORTED
+ \ CMAKE_CXX_VISIBILITY_PRESET
+ \ CMAKE_C_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_C_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_C_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_C_ARCHIVE_APPEND
+ \ CMAKE_C_ARCHIVE_CREATE
+ \ CMAKE_C_ARCHIVE_FINISH
+ \ CMAKE_C_BYTE_ORDER
+ \ CMAKE_C_CLANG_TIDY
+ \ CMAKE_C_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_C_COMPILER
+ \ CMAKE_C_COMPILER_ABI
+ \ CMAKE_C_COMPILER_AR
+ \ CMAKE_C_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_C_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_C_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_C_COMPILER_ID
+ \ CMAKE_C_COMPILER_LAUNCHER
+ \ CMAKE_C_COMPILER_LOADED
+ \ CMAKE_C_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_C_COMPILER_RANLIB
+ \ CMAKE_C_COMPILER_TARGET
+ \ CMAKE_C_COMPILER_VERSION
+ \ CMAKE_C_COMPILER_VERSION_INTERNAL
+ \ CMAKE_C_COMPILE_FEATURES
+ \ CMAKE_C_COMPILE_OBJECT
+ \ CMAKE_C_CPPCHECK
+ \ CMAKE_C_CPPLINT
+ \ CMAKE_C_CREATE_SHARED_LIBRARY
+ \ CMAKE_C_CREATE_SHARED_MODULE
+ \ CMAKE_C_CREATE_STATIC_LIBRARY
+ \ CMAKE_C_EXTENSIONS
+ \ CMAKE_C_EXTENSIONS_DEFAULT
+ \ CMAKE_C_FLAGS
+ \ CMAKE_C_FLAGS_DEBUG
+ \ CMAKE_C_FLAGS_DEBUG_INIT
+ \ CMAKE_C_FLAGS_INIT
+ \ CMAKE_C_FLAGS_MINSIZEREL
+ \ CMAKE_C_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_C_FLAGS_RELEASE
+ \ CMAKE_C_FLAGS_RELEASE_INIT
+ \ CMAKE_C_FLAGS_RELWITHDEBINFO
+ \ CMAKE_C_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_C_IGNORE_EXTENSIONS
+ \ CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_C_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_C_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_C_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_C_INIT
+ \ CMAKE_C_LIBRARY_ARCHITECTURE
+ \ CMAKE_C_LINKER_LAUNCHER
+ \ CMAKE_C_LINKER_PREFERENCE
+ \ CMAKE_C_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_C_LINKER_WRAPPER_FLAG
+ \ CMAKE_C_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_C_LINK_EXECUTABLE
+ \ CMAKE_C_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_C_LINK_LIBRARY_FLAG
+ \ CMAKE_C_LINK_LIBRARY_SUFFIX
+ \ CMAKE_C_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_C_OUTPUT_EXTENSION
+ \ CMAKE_C_PLATFORM_ID
+ \ CMAKE_C_SIMULATE_ID
+ \ CMAKE_C_SIMULATE_VERSION
+ \ CMAKE_C_SIZEOF_DATA_PTR
+ \ CMAKE_C_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_C_STANDARD
+ \ CMAKE_C_STANDARD_DEFAULT
+ \ CMAKE_C_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_C_STANDARD_LIBRARIES
+ \ CMAKE_C_STANDARD_REQUIRED
+ \ CMAKE_C_SUPPORTED
+ \ CMAKE_C_VISIBILITY_PRESET
+ \ CMAKE_DEBUG_POSTFIX
+ \ CMAKE_DEBUG_TARGET_PROPERTIES
+ \ CMAKE_DEFAULT_BUILD_TYPE
+ \ CMAKE_DEFAULT_CONFIGS
+ \ CMAKE_DEPENDS_IN_PROJECT_ONLY
+ \ CMAKE_DEPENDS_USE_COMPILER
+ \ CMAKE_DIRECTORY_LABELS
+ \ CMAKE_DISABLE_PRECOMPILE_HEADERS
+ \ CMAKE_DLL_NAME_WITH_SOVERSION
+ \ CMAKE_DL_LIBS
+ \ CMAKE_DOTNET_SDK
+ \ CMAKE_DOTNET_TARGET_FRAMEWORK
+ \ CMAKE_DOTNET_TARGET_FRAMEWORK_VERSION
+ \ CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES
+ \ CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT
+ \ CMAKE_ECLIPSE_MAKE_ARGUMENTS
+ \ CMAKE_ECLIPSE_RESOURCE_ENCODING
+ \ CMAKE_ECLIPSE_VERSION
+ \ CMAKE_EDIT_COMMAND
+ \ CMAKE_ENABLE_EXPORTS
+ \ CMAKE_ERROR_DEPRECATED
+ \ CMAKE_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
+ \ CMAKE_EXECUTABLE_ENABLE_EXPORTS
+ \ CMAKE_EXECUTABLE_SUFFIX
+ \ CMAKE_EXECUTABLE_SUFFIX_ASM
+ \ CMAKE_EXECUTABLE_SUFFIX_ASM_MASM
+ \ CMAKE_EXECUTABLE_SUFFIX_ASM_NASM
+ \ CMAKE_EXECUTABLE_SUFFIX_C
+ \ CMAKE_EXECUTABLE_SUFFIX_CSharp
+ \ CMAKE_EXECUTABLE_SUFFIX_CUDA
+ \ CMAKE_EXECUTABLE_SUFFIX_CXX
+ \ CMAKE_EXECUTABLE_SUFFIX_Fortran
+ \ CMAKE_EXECUTABLE_SUFFIX_HIP
+ \ CMAKE_EXECUTABLE_SUFFIX_Java
+ \ CMAKE_EXECUTABLE_SUFFIX_RC
+ \ CMAKE_EXECUTABLE_SUFFIX_Swift
+ \ CMAKE_EXECUTE_PROCESS_COMMAND_ECHO
+ \ CMAKE_EXE_LINKER_FLAGS
+ \ CMAKE_EXE_LINKER_FLAGS_INIT
+ \ CMAKE_EXPORT_COMPILE_COMMANDS
+ \ CMAKE_EXPORT_NO_PACKAGE_REGISTRY
+ \ CMAKE_EXPORT_PACKAGE_REGISTRY
+ \ CMAKE_EXTRA_GENERATOR
+ \ CMAKE_EXTRA_SHARED_LIBRARY_SUFFIXES
+ \ CMAKE_FIND_APPBUNDLE
+ \ CMAKE_FIND_DEBUG_MODE
+ \ CMAKE_FIND_FRAMEWORK
+ \ CMAKE_FIND_LIBRARY_CUSTOM_LIB_SUFFIX
+ \ CMAKE_FIND_LIBRARY_PREFIXES
+ \ CMAKE_FIND_LIBRARY_SUFFIXES
+ \ CMAKE_FIND_NO_INSTALL_PREFIX
+ \ CMAKE_FIND_PACKAGE_NAME
+ \ CMAKE_FIND_PACKAGE_NO_PACKAGE_REGISTRY
+ \ CMAKE_FIND_PACKAGE_NO_SYSTEM_PACKAGE_REGISTRY
+ \ CMAKE_FIND_PACKAGE_PREFER_CONFIG
+ \ CMAKE_FIND_PACKAGE_REDIRECTS_DIR
+ \ CMAKE_FIND_PACKAGE_RESOLVE_SYMLINKS
+ \ CMAKE_FIND_PACKAGE_SORT_DIRECTION
+ \ CMAKE_FIND_PACKAGE_SORT_ORDER
+ \ CMAKE_FIND_PACKAGE_TARGETS_GLOBAL
+ \ CMAKE_FIND_PACKAGE_WARN_NO_MODULE
+ \ CMAKE_FIND_ROOT_PATH
+ \ CMAKE_FIND_ROOT_PATH_MODE_INCLUDE
+ \ CMAKE_FIND_ROOT_PATH_MODE_LIBRARY
+ \ CMAKE_FIND_ROOT_PATH_MODE_PACKAGE
+ \ CMAKE_FIND_ROOT_PATH_MODE_PROGRAM
+ \ CMAKE_FIND_USE_CMAKE_ENVIRONMENT_PATH
+ \ CMAKE_FIND_USE_INSTALL_PREFIX
+ \ CMAKE_FIND_USE_CMAKE_PATH
+ \ CMAKE_FIND_USE_CMAKE_SYSTEM_PATH
+ \ CMAKE_FIND_USE_INSTALL_PREFIX
+ \ CMAKE_FIND_USE_PACKAGE_REGISTRY
+ \ CMAKE_FIND_USE_PACKAGE_ROOT_PATH
+ \ CMAKE_FIND_USE_SYSTEM_ENVIRONMENT_PATH
+ \ CMAKE_FIND_USE_SYSTEM_PACKAGE_REGISTRY
+ \ CMAKE_FOLDER
+ \ CMAKE_FRAMEWORK
+ \ CMAKE_FRAMEWORK_PATH
+ \ CMAKE_Fortran
+ \ CMAKE_Fortran_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_Fortran_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_Fortran_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_Fortran_ARCHIVE_APPEND
+ \ CMAKE_Fortran_ARCHIVE_CREATE
+ \ CMAKE_Fortran_ARCHIVE_FINISH
+ \ CMAKE_Fortran_BYTE_ORDER
+ \ CMAKE_Fortran_CLANG_TIDY
+ \ CMAKE_Fortran_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_Fortran_COMPILER
+ \ CMAKE_Fortran_COMPILER_ABI
+ \ CMAKE_Fortran_COMPILER_AR
+ \ CMAKE_Fortran_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_Fortran_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_Fortran_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_Fortran_COMPILER_ID
+ \ CMAKE_Fortran_COMPILER_LAUNCHER
+ \ CMAKE_Fortran_COMPILER_LOADED
+ \ CMAKE_Fortran_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_Fortran_COMPILER_RANLIB
+ \ CMAKE_Fortran_COMPILER_TARGET
+ \ CMAKE_Fortran_COMPILER_VERSION
+ \ CMAKE_Fortran_COMPILER_VERSION_INTERNAL
+ \ CMAKE_Fortran_COMPILE_OBJECT
+ \ CMAKE_Fortran_CPPCHECK
+ \ CMAKE_Fortran_CPPLINT
+ \ CMAKE_Fortran_CREATE_SHARED_LIBRARY
+ \ CMAKE_Fortran_CREATE_SHARED_MODULE
+ \ CMAKE_Fortran_CREATE_STATIC_LIBRARY
+ \ CMAKE_Fortran_EXTENSIONS
+ \ CMAKE_Fortran_EXTENSIONS_DEFAULT
+ \ CMAKE_Fortran_FLAGS
+ \ CMAKE_Fortran_FLAGS_DEBUG
+ \ CMAKE_Fortran_FLAGS_DEBUG_INIT
+ \ CMAKE_Fortran_FLAGS_INIT
+ \ CMAKE_Fortran_FLAGS_MINSIZEREL
+ \ CMAKE_Fortran_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_Fortran_FLAGS_RELEASE
+ \ CMAKE_Fortran_FLAGS_RELEASE_INIT
+ \ CMAKE_Fortran_FLAGS_RELWITHDEBINFO
+ \ CMAKE_Fortran_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_Fortran_FORMAT
+ \ CMAKE_Fortran_IGNORE_EXTENSIONS
+ \ CMAKE_Fortran_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_Fortran_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_Fortran_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_Fortran_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_Fortran_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_Fortran_INIT
+ \ CMAKE_Fortran_LIBRARY_ARCHITECTURE
+ \ CMAKE_Fortran_LINKER_LAUNCHER
+ \ CMAKE_Fortran_LINKER_PREFERENCE
+ \ CMAKE_Fortran_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_Fortran_LINKER_WRAPPER_FLAG
+ \ CMAKE_Fortran_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_Fortran_LINK_EXECUTABLE
+ \ CMAKE_Fortran_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_Fortran_LINK_LIBRARY_FLAG
+ \ CMAKE_Fortran_LINK_LIBRARY_SUFFIX
+ \ CMAKE_Fortran_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_Fortran_MODDIR_DEFAULT
+ \ CMAKE_Fortran_MODDIR_FLAG
+ \ CMAKE_Fortran_MODOUT_FLAG
+ \ CMAKE_Fortran_MODULE_DIRECTORY
+ \ CMAKE_Fortran_OUTPUT_EXTENSION
+ \ CMAKE_Fortran_PLATFORM_ID
+ \ CMAKE_Fortran_PREPROCESS
+ \ CMAKE_Fortran_SIMULATE_ID
+ \ CMAKE_Fortran_SIMULATE_VERSION
+ \ CMAKE_Fortran_SIZEOF_DATA_PTR
+ \ CMAKE_Fortran_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_Fortran_STANDARD
+ \ CMAKE_Fortran_STANDARD_DEFAULT
+ \ CMAKE_Fortran_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_Fortran_STANDARD_LIBRARIES
+ \ CMAKE_Fortran_STANDARD_REQUIRED
+ \ CMAKE_Fortran_SUPPORTED
+ \ CMAKE_Fortran_VISIBILITY_PRESET
+ \ CMAKE_GENERATOR
+ \ CMAKE_GENERATOR_INSTANCE
+ \ CMAKE_GENERATOR_PLATFORM
+ \ CMAKE_GENERATOR_TOOLSET
+ \ CMAKE_GHS_NO_SOURCE_GROUP_FILE
+ \ CMAKE_GLOBAL_AUTOGEN_TARGET
+ \ CMAKE_GLOBAL_AUTOGEN_TARGET_NAME
+ \ CMAKE_GLOBAL_AUTORCC_TARGET
+ \ CMAKE_GLOBAL_AUTORCC_TARGET_NAME
+ \ CMAKE_GNUtoMS
+ \ CMAKE_HIP
+ \ CMAKE_HIP_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_HIP_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_HIP_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_HIP_ARCHITECTURES
+ \ CMAKE_HIP_ARCHIVE_APPEND
+ \ CMAKE_HIP_ARCHIVE_CREATE
+ \ CMAKE_HIP_ARCHIVE_FINISH
+ \ CMAKE_HIP_BYTE_ORDER
+ \ CMAKE_HIP_CLANG_TIDY
+ \ CMAKE_HIP_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_HIP_COMPILER
+ \ CMAKE_HIP_COMPILER_ABI
+ \ CMAKE_HIP_COMPILER_AR
+ \ CMAKE_HIP_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_HIP_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_HIP_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_HIP_COMPILER_ID
+ \ CMAKE_HIP_COMPILER_LAUNCHER
+ \ CMAKE_HIP_COMPILER_LOADED
+ \ CMAKE_HIP_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_HIP_COMPILER_RANLIB
+ \ CMAKE_HIP_COMPILER_TARGET
+ \ CMAKE_HIP_COMPILER_VERSION
+ \ CMAKE_HIP_COMPILER_VERSION_INTERNAL
+ \ CMAKE_HIP_COMPILE_FEATURES
+ \ CMAKE_HIP_COMPILE_OBJECT
+ \ CMAKE_HIP_CPPCHECK
+ \ CMAKE_HIP_CPPLINT
+ \ CMAKE_HIP_CREATE_SHARED_LIBRARY
+ \ CMAKE_HIP_CREATE_SHARED_MODULE
+ \ CMAKE_HIP_CREATE_STATIC_LIBRARY
+ \ CMAKE_HIP_EXTENSIONS
+ \ CMAKE_HIP_EXTENSIONS_DEFAULT
+ \ CMAKE_HIP_FLAGS
+ \ CMAKE_HIP_FLAGS_DEBUG
+ \ CMAKE_HIP_FLAGS_DEBUG_INIT
+ \ CMAKE_HIP_FLAGS_INIT
+ \ CMAKE_HIP_FLAGS_MINSIZEREL
+ \ CMAKE_HIP_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_HIP_FLAGS_RELEASE
+ \ CMAKE_HIP_FLAGS_RELEASE_INIT
+ \ CMAKE_HIP_FLAGS_RELWITHDEBINFO
+ \ CMAKE_HIP_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_HIP_IGNORE_EXTENSIONS
+ \ CMAKE_HIP_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_HIP_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_HIP_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_HIP_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_HIP_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_HIP_INIT
+ \ CMAKE_HIP_LIBRARY_ARCHITECTURE
+ \ CMAKE_HIP_LINKER_LAUNCHER
+ \ CMAKE_HIP_LINKER_PREFERENCE
+ \ CMAKE_HIP_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_HIP_LINKER_WRAPPER_FLAG
+ \ CMAKE_HIP_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_HIP_LINK_EXECUTABLE
+ \ CMAKE_HIP_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_HIP_LINK_LIBRARY_FLAG
+ \ CMAKE_HIP_LINK_LIBRARY_SUFFIX
+ \ CMAKE_HIP_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_HIP_OUTPUT_EXTENSION
+ \ CMAKE_HIP_PLATFORM_ID
+ \ CMAKE_HIP_SIMULATE_ID
+ \ CMAKE_HIP_SIMULATE_VERSION
+ \ CMAKE_HIP_SIZEOF_DATA_PTR
+ \ CMAKE_HIP_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_HIP_STANDARD
+ \ CMAKE_HIP_STANDARD_DEFAULT
+ \ CMAKE_HIP_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_HIP_STANDARD_LIBRARIES
+ \ CMAKE_HIP_STANDARD_REQUIRED
+ \ CMAKE_HIP_SUPPORTED
+ \ CMAKE_HIP_VISIBILITY_PRESET
+ \ CMAKE_HOME_DIRECTORY
+ \ CMAKE_HOST_APPLE
+ \ CMAKE_HOST_BSD
+ \ CMAKE_HOST_LINUX
+ \ CMAKE_HOST_SOLARIS
+ \ CMAKE_HOST_SYSTEM
+ \ CMAKE_HOST_SYSTEM_NAME
+ \ CMAKE_HOST_SYSTEM_PROCESSOR
+ \ CMAKE_HOST_SYSTEM_VERSION
+ \ CMAKE_HOST_UNIX
+ \ CMAKE_HOST_WIN32
+ \ CMAKE_IGNORE_PATH
+ \ CMAKE_IGNORE_PREFIX_PATH
+ \ CMAKE_IMPORT_LIBRARY_PREFIX
+ \ CMAKE_IMPORT_LIBRARY_SUFFIX
+ \ CMAKE_INCLUDE_CURRENT_DIR
+ \ CMAKE_INCLUDE_CURRENT_DIR_IN_INTERFACE
+ \ CMAKE_INCLUDE_DIRECTORIES_BEFORE
+ \ CMAKE_INCLUDE_DIRECTORIES_PROJECT_BEFORE
+ \ CMAKE_INCLUDE_PATH
+ \ CMAKE_INSTALL_DEFAULT_COMPONENT_NAME
+ \ CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
+ \ CMAKE_INSTALL_MESSAGE
+ \ CMAKE_INSTALL_NAME_DIR
+ \ CMAKE_INSTALL_PREFIX
+ \ CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT
+ \ CMAKE_INSTALL_REMOVE_ENVIRONMENT_RPATH
+ \ CMAKE_INSTALL_RPATH
+ \ CMAKE_INSTALL_RPATH_USE_LINK_PATH
+ \ CMAKE_INTERNAL_PLATFORM_ABI
+ \ CMAKE_INTERPROCEDURAL_OPTIMIZATION
+ \ CMAKE_IOS_INSTALL_COMBINED
+ \ CMAKE_ISPC_HEADER_DIRECTORY
+ \ CMAKE_ISPC_HEADER_SUFFIX
+ \ CMAKE_ISPC_INSTRUCTION_SETS
+ \ CMAKE_JOB_POOLS
+ \ CMAKE_JOB_POOL_COMPILE
+ \ CMAKE_JOB_POOL_LINK
+ \ CMAKE_JOB_POOL_PRECOMPILE_HEADER
+ \ CMAKE_Java
+ \ CMAKE_Java_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_Java_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_Java_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_Java_ARCHIVE_APPEND
+ \ CMAKE_Java_ARCHIVE_CREATE
+ \ CMAKE_Java_ARCHIVE_FINISH
+ \ CMAKE_Java_BYTE_ORDER
+ \ CMAKE_Java_CLANG_TIDY
+ \ CMAKE_Java_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_Java_COMPILER
+ \ CMAKE_Java_COMPILER_ABI
+ \ CMAKE_Java_COMPILER_AR
+ \ CMAKE_Java_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_Java_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_Java_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_Java_COMPILER_ID
+ \ CMAKE_Java_COMPILER_LAUNCHER
+ \ CMAKE_Java_COMPILER_LOADED
+ \ CMAKE_Java_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_Java_COMPILER_RANLIB
+ \ CMAKE_Java_COMPILER_TARGET
+ \ CMAKE_Java_COMPILER_VERSION
+ \ CMAKE_Java_COMPILER_VERSION_INTERNAL
+ \ CMAKE_Java_COMPILE_OBJECT
+ \ CMAKE_Java_CPPCHECK
+ \ CMAKE_Java_CPPLINT
+ \ CMAKE_Java_CREATE_SHARED_LIBRARY
+ \ CMAKE_Java_CREATE_SHARED_MODULE
+ \ CMAKE_Java_CREATE_STATIC_LIBRARY
+ \ CMAKE_Java_EXTENSIONS
+ \ CMAKE_Java_EXTENSIONS_DEFAULT
+ \ CMAKE_Java_FLAGS
+ \ CMAKE_Java_FLAGS_DEBUG
+ \ CMAKE_Java_FLAGS_DEBUG_INIT
+ \ CMAKE_Java_FLAGS_INIT
+ \ CMAKE_Java_FLAGS_MINSIZEREL
+ \ CMAKE_Java_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_Java_FLAGS_RELEASE
+ \ CMAKE_Java_FLAGS_RELEASE_INIT
+ \ CMAKE_Java_FLAGS_RELWITHDEBINFO
+ \ CMAKE_Java_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_Java_IGNORE_EXTENSIONS
+ \ CMAKE_Java_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_Java_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_Java_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_Java_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_Java_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_Java_INIT
+ \ CMAKE_Java_LIBRARY_ARCHITECTURE
+ \ CMAKE_Java_LINKER_LAUNCHER
+ \ CMAKE_Java_LINKER_PREFERENCE
+ \ CMAKE_Java_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_Java_LINKER_WRAPPER_FLAG
+ \ CMAKE_Java_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_Java_LINK_EXECUTABLE
+ \ CMAKE_Java_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_Java_LINK_LIBRARY_FLAG
+ \ CMAKE_Java_LINK_LIBRARY_SUFFIX
+ \ CMAKE_Java_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_Java_OUTPUT_EXTENSION
+ \ CMAKE_Java_PLATFORM_ID
+ \ CMAKE_Java_SIMULATE_ID
+ \ CMAKE_Java_SIMULATE_VERSION
+ \ CMAKE_Java_SIZEOF_DATA_PTR
+ \ CMAKE_Java_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_Java_STANDARD
+ \ CMAKE_Java_STANDARD_DEFAULT
+ \ CMAKE_Java_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_Java_STANDARD_LIBRARIES
+ \ CMAKE_Java_STANDARD_REQUIRED
+ \ CMAKE_Java_SUPPORTED
+ \ CMAKE_Java_VISIBILITY_PRESET
+ \ CMAKE_KATE_FILES_MODE
+ \ CMAKE_KATE_MAKE_ARGUMENTS
+ \ CMAKE_LIBRARY_ARCHITECTURE
+ \ CMAKE_LIBRARY_ARCHITECTURE_REGEX
+ \ CMAKE_LIBRARY_OUTPUT_DIRECTORY
+ \ CMAKE_LIBRARY_PATH
+ \ CMAKE_LIBRARY_PATH_FLAG
+ \ CMAKE_LINK_DEF_FILE_FLAG
+ \ CMAKE_LINK_DEPENDS_NO_SHARED
+ \ CMAKE_LINK_DEPENDS_USE_LINKER
+ \ CMAKE_LINK_DIRECTORIES_BEFORE
+ \ CMAKE_LINK_INTERFACE_LIBRARIES
+ \ CMAKE_LINK_LIBRARIES_ONLY_TARGETS
+ \ CMAKE_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_LINK_LIBRARY_FLAG
+ \ CMAKE_LINK_LIBRARY_SUFFIX
+ \ CMAKE_LINK_SEARCH_END_STATIC
+ \ CMAKE_LINK_SEARCH_START_STATIC
+ \ CMAKE_LINK_WHAT_YOU_USE
+ \ CMAKE_LINK_WHAT_YOU_USE_CHECK
+ \ CMAKE_MACOSX_BUNDLE
+ \ CMAKE_MACOSX_RPATH
+ \ CMAKE_MAJOR_VERSION
+ \ CMAKE_MAKE_PROGRAM
+ \ CMAKE_MATCH_COUNT
+ \ CMAKE_MAXIMUM_RECURSION_DEPTH
+ \ CMAKE_MESSAGE_CONTEXT
+ \ CMAKE_MESSAGE_CONTEXT_SHOW
+ \ CMAKE_MESSAGE_INDENT
+ \ CMAKE_MESSAGE_LOG_LEVEL
+ \ CMAKE_MFC_FLAG
+ \ CMAKE_MINIMUM_REQUIRED_VERSION
+ \ CMAKE_MINOR_VERSION
+ \ CMAKE_MODULE_LINKER_FLAGS
+ \ CMAKE_MODULE_LINKER_FLAGS_INIT
+ \ CMAKE_MODULE_PATH
+ \ CMAKE_MSVCIDE_RUN_PATH
+ \ CMAKE_MSVC_DEBUG_INFORMATION_FORMAT
+ \ CMAKE_MSVC_RUNTIME_LIBRARY
+ \ CMAKE_NETRC
+ \ CMAKE_NETRC_FILE
+ \ CMAKE_NINJA_OUTPUT_PATH_PREFIX
+ \ CMAKE_NOT_USING_CONFIG_FLAGS
+ \ CMAKE_NO_BUILTIN_CHRPATH
+ \ CMAKE_NO_SYSTEM_FROM_IMPORTED
+ \ CMAKE_OBJCXX_CLANG_TIDY
+ \ CMAKE_OBJCXX_EXTENSIONS
+ \ CMAKE_OBJCXX_LINKER_LAUNCHER
+ \ CMAKE_OBJCXX_STANDARD
+ \ CMAKE_OBJCXX_STANDARD_REQUIRED
+ \ CMAKE_OBJC_CLANG_TIDY
+ \ CMAKE_OBJC_EXTENSIONS
+ \ CMAKE_OBJC_LINKER_LAUNCHER
+ \ CMAKE_OBJC_STANDARD
+ \ CMAKE_OBJC_STANDARD_REQUIRED
+ \ CMAKE_OBJECT_PATH_MAX
+ \ CMAKE_OPTIMIZE_DEPENDENCIES
+ \ CMAKE_OSX_ARCHITECTURES
+ \ CMAKE_OSX_DEPLOYMENT_TARGET
+ \ CMAKE_OSX_SYSROOT
+ \ CMAKE_PARENT_LIST_FILE
+ \ CMAKE_PATCH_VERSION
+ \ CMAKE_PCH_INSTANTIATE_TEMPLATES
+ \ CMAKE_PCH_WARN_INVALID
+ \ CMAKE_PDB_OUTPUT_DIRECTORY
+ \ CMAKE_PLATFORM_NO_VERSIONED_SONAME
+ \ CMAKE_POSITION_INDEPENDENT_CODE
+ \ CMAKE_PREFIX_PATH
+ \ CMAKE_PROGRAM_PATH
+ \ CMAKE_PROJECT_DESCRIPTION
+ \ CMAKE_PROJECT_HOMEPAGE_URL
+ \ CMAKE_PROJECT_INCLUDE
+ \ CMAKE_PROJECT_INCLUDE_BEFORE
+ \ CMAKE_PROJECT_NAME
+ \ CMAKE_PROJECT_TOP_LEVEL_INCLUDES
+ \ CMAKE_PROJECT_VERSION
+ \ CMAKE_PROJECT_VERSION_MAJOR
+ \ CMAKE_PROJECT_VERSION_MINOR
+ \ CMAKE_PROJECT_VERSION_PATCH
+ \ CMAKE_PROJECT_VERSION_TWEAK
+ \ CMAKE_RANLIB
+ \ CMAKE_RC
+ \ CMAKE_RC_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_RC_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_RC_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_RC_ARCHIVE_APPEND
+ \ CMAKE_RC_ARCHIVE_CREATE
+ \ CMAKE_RC_ARCHIVE_FINISH
+ \ CMAKE_RC_BYTE_ORDER
+ \ CMAKE_RC_CLANG_TIDY
+ \ CMAKE_RC_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_RC_COMPILER
+ \ CMAKE_RC_COMPILER_ABI
+ \ CMAKE_RC_COMPILER_AR
+ \ CMAKE_RC_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_RC_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_RC_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_RC_COMPILER_ID
+ \ CMAKE_RC_COMPILER_LAUNCHER
+ \ CMAKE_RC_COMPILER_LOADED
+ \ CMAKE_RC_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_RC_COMPILER_RANLIB
+ \ CMAKE_RC_COMPILER_TARGET
+ \ CMAKE_RC_COMPILER_VERSION
+ \ CMAKE_RC_COMPILER_VERSION_INTERNAL
+ \ CMAKE_RC_COMPILE_OBJECT
+ \ CMAKE_RC_CPPCHECK
+ \ CMAKE_RC_CPPLINT
+ \ CMAKE_RC_CREATE_SHARED_LIBRARY
+ \ CMAKE_RC_CREATE_SHARED_MODULE
+ \ CMAKE_RC_CREATE_STATIC_LIBRARY
+ \ CMAKE_RC_EXTENSIONS
+ \ CMAKE_RC_EXTENSIONS_DEFAULT
+ \ CMAKE_RC_FLAGS
+ \ CMAKE_RC_FLAGS_DEBUG
+ \ CMAKE_RC_FLAGS_DEBUG_INIT
+ \ CMAKE_RC_FLAGS_INIT
+ \ CMAKE_RC_FLAGS_MINSIZEREL
+ \ CMAKE_RC_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_RC_FLAGS_RELEASE
+ \ CMAKE_RC_FLAGS_RELEASE_INIT
+ \ CMAKE_RC_FLAGS_RELWITHDEBINFO
+ \ CMAKE_RC_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_RC_IGNORE_EXTENSIONS
+ \ CMAKE_RC_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_RC_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_RC_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_RC_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_RC_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_RC_INIT
+ \ CMAKE_RC_LIBRARY_ARCHITECTURE
+ \ CMAKE_RC_LINKER_LAUNCHER
+ \ CMAKE_RC_LINKER_PREFERENCE
+ \ CMAKE_RC_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_RC_LINKER_WRAPPER_FLAG
+ \ CMAKE_RC_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_RC_LINK_EXECUTABLE
+ \ CMAKE_RC_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_RC_LINK_LIBRARY_FLAG
+ \ CMAKE_RC_LINK_LIBRARY_SUFFIX
+ \ CMAKE_RC_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_RC_OUTPUT_EXTENSION
+ \ CMAKE_RC_PLATFORM_ID
+ \ CMAKE_RC_SIMULATE_ID
+ \ CMAKE_RC_SIMULATE_VERSION
+ \ CMAKE_RC_SIZEOF_DATA_PTR
+ \ CMAKE_RC_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_RC_STANDARD
+ \ CMAKE_RC_STANDARD_DEFAULT
+ \ CMAKE_RC_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_RC_STANDARD_LIBRARIES
+ \ CMAKE_RC_STANDARD_REQUIRED
+ \ CMAKE_RC_SUPPORTED
+ \ CMAKE_RC_VISIBILITY_PRESET
+ \ CMAKE_ROOT
+ \ CMAKE_RULE_MESSAGES
+ \ CMAKE_RUNTIME_OUTPUT_DIRECTORY
+ \ CMAKE_SCRIPT_MODE_FILE
+ \ CMAKE_SHARED_LIBRARY_ENABLE_EXPORTS
+ \ CMAKE_SHARED_LIBRARY_PREFIX
+ \ CMAKE_SHARED_LIBRARY_SUFFIX
+ \ CMAKE_SHARED_LINKER_FLAGS
+ \ CMAKE_SHARED_LINKER_FLAGS_INIT
+ \ CMAKE_SHARED_MODULE_PREFIX
+ \ CMAKE_SHARED_MODULE_SUFFIX
+ \ CMAKE_SIZEOF_VOID_P
+ \ CMAKE_SKIP_BUILD_RPATH
+ \ CMAKE_SKIP_INSTALL_ALL_DEPENDENCY
+ \ CMAKE_SKIP_INSTALL_RPATH
+ \ CMAKE_SKIP_INSTALL_RULES
+ \ CMAKE_SKIP_RPATH
+ \ CMAKE_SKIP_TEST_ALL_DEPENDENCY
+ \ CMAKE_SOURCE_DIR
+ \ CMAKE_STAGING_PREFIX
+ \ CMAKE_STATIC_LIBRARY_PREFIX
+ \ CMAKE_STATIC_LIBRARY_SUFFIX
+ \ CMAKE_STATIC_LINKER_FLAGS
+ \ CMAKE_STATIC_LINKER_FLAGS_INIT
+ \ CMAKE_SUBLIME_TEXT_2_ENV_SETTINGS
+ \ CMAKE_SUBLIME_TEXT_2_EXCLUDE_BUILD_TREE
+ \ CMAKE_SUPPRESS_REGENERATION
+ \ CMAKE_SYSROOT
+ \ CMAKE_SYSROOT_COMPILE
+ \ CMAKE_SYSROOT_LINK
+ \ CMAKE_SYSTEM
+ \ CMAKE_SYSTEM_APPBUNDLE_PATH
+ \ CMAKE_SYSTEM_FRAMEWORK_PATH
+ \ CMAKE_SYSTEM_IGNORE_PATH
+ \ CMAKE_SYSTEM_IGNORE_PREFIX_PATH
+ \ CMAKE_SYSTEM_INCLUDE_PATH
+ \ CMAKE_SYSTEM_LIBRARY_PATH
+ \ CMAKE_SYSTEM_NAME
+ \ CMAKE_SYSTEM_PREFIX_PATH
+ \ CMAKE_SYSTEM_PROCESSOR
+ \ CMAKE_SYSTEM_PROGRAM_PATH
+ \ CMAKE_SYSTEM_VERSION
+ \ CMAKE_Swift
+ \ CMAKE_Swift_ANDROID_TOOLCHAIN_MACHINE
+ \ CMAKE_Swift_ANDROID_TOOLCHAIN_PREFIX
+ \ CMAKE_Swift_ANDROID_TOOLCHAIN_SUFFIX
+ \ CMAKE_Swift_ARCHIVE_APPEND
+ \ CMAKE_Swift_ARCHIVE_CREATE
+ \ CMAKE_Swift_ARCHIVE_FINISH
+ \ CMAKE_Swift_BYTE_ORDER
+ \ CMAKE_Swift_CLANG_TIDY
+ \ CMAKE_Swift_CLANG_TIDY_EXPORT_FIXES_DIR
+ \ CMAKE_Swift_COMPILER
+ \ CMAKE_Swift_COMPILER_ABI
+ \ CMAKE_Swift_COMPILER_AR
+ \ CMAKE_Swift_COMPILER_ARCHITECTURE_ID
+ \ CMAKE_Swift_COMPILER_EXTERNAL_TOOLCHAIN
+ \ CMAKE_Swift_COMPILER_FRONTEND_VARIANT
+ \ CMAKE_Swift_COMPILER_ID
+ \ CMAKE_Swift_COMPILER_LAUNCHER
+ \ CMAKE_Swift_COMPILER_LOADED
+ \ CMAKE_Swift_COMPILER_PREDEFINES_COMMAND
+ \ CMAKE_Swift_COMPILER_RANLIB
+ \ CMAKE_Swift_COMPILER_TARGET
+ \ CMAKE_Swift_COMPILER_VERSION
+ \ CMAKE_Swift_COMPILER_VERSION_INTERNAL
+ \ CMAKE_Swift_COMPILE_OBJECT
+ \ CMAKE_Swift_CPPCHECK
+ \ CMAKE_Swift_CPPLINT
+ \ CMAKE_Swift_CREATE_SHARED_LIBRARY
+ \ CMAKE_Swift_CREATE_SHARED_MODULE
+ \ CMAKE_Swift_CREATE_STATIC_LIBRARY
+ \ CMAKE_Swift_EXTENSIONS
+ \ CMAKE_Swift_EXTENSIONS_DEFAULT
+ \ CMAKE_Swift_FLAGS
+ \ CMAKE_Swift_FLAGS_DEBUG
+ \ CMAKE_Swift_FLAGS_DEBUG_INIT
+ \ CMAKE_Swift_FLAGS_INIT
+ \ CMAKE_Swift_FLAGS_MINSIZEREL
+ \ CMAKE_Swift_FLAGS_MINSIZEREL_INIT
+ \ CMAKE_Swift_FLAGS_RELEASE
+ \ CMAKE_Swift_FLAGS_RELEASE_INIT
+ \ CMAKE_Swift_FLAGS_RELWITHDEBINFO
+ \ CMAKE_Swift_FLAGS_RELWITHDEBINFO_INIT
+ \ CMAKE_Swift_IGNORE_EXTENSIONS
+ \ CMAKE_Swift_IMPLICIT_INCLUDE_DIRECTORIES
+ \ CMAKE_Swift_IMPLICIT_LINK_DIRECTORIES
+ \ CMAKE_Swift_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES
+ \ CMAKE_Swift_IMPLICIT_LINK_LIBRARIES
+ \ CMAKE_Swift_INCLUDE_WHAT_YOU_USE
+ \ CMAKE_Swift_INIT
+ \ CMAKE_Swift_LANGUAGE_VERSION
+ \ CMAKE_Swift_LIBRARY_ARCHITECTURE
+ \ CMAKE_Swift_LINKER_LAUNCHER
+ \ CMAKE_Swift_LINKER_PREFERENCE
+ \ CMAKE_Swift_LINKER_PREFERENCE_PROPAGATES
+ \ CMAKE_Swift_LINKER_WRAPPER_FLAG
+ \ CMAKE_Swift_LINKER_WRAPPER_FLAG_SEP
+ \ CMAKE_Swift_LINK_EXECUTABLE
+ \ CMAKE_Swift_LINK_LIBRARY_FILE_FLAG
+ \ CMAKE_Swift_LINK_LIBRARY_FLAG
+ \ CMAKE_Swift_LINK_LIBRARY_SUFFIX
+ \ CMAKE_Swift_LINK_WHAT_YOU_USE_FLAG
+ \ CMAKE_Swift_MODULE_DIRECTORY
+ \ CMAKE_Swift_NUM_THREADS
+ \ CMAKE_Swift_OUTPUT_EXTENSION
+ \ CMAKE_Swift_PLATFORM_ID
+ \ CMAKE_Swift_SIMULATE_ID
+ \ CMAKE_Swift_SIMULATE_VERSION
+ \ CMAKE_Swift_SIZEOF_DATA_PTR
+ \ CMAKE_Swift_SOURCE_FILE_EXTENSIONS
+ \ CMAKE_Swift_STANDARD
+ \ CMAKE_Swift_STANDARD_DEFAULT
+ \ CMAKE_Swift_STANDARD_INCLUDE_DIRECTORIES
+ \ CMAKE_Swift_STANDARD_LIBRARIES
+ \ CMAKE_Swift_STANDARD_REQUIRED
+ \ CMAKE_Swift_SUPPORTED
+ \ CMAKE_Swift_VISIBILITY_PRESET
+ \ CMAKE_TASKING_TOOLSET
+ \ CMAKE_TLS_CAINFO
+ \ CMAKE_TLS_VERIFY
+ \ CMAKE_TOOLCHAIN_FILE
+ \ CMAKE_TRY_COMPILE_CONFIGURATION
+ \ CMAKE_TRY_COMPILE_NO_PLATFORM_VARIABLES
+ \ CMAKE_TRY_COMPILE_PLATFORM_VARIABLES
+ \ CMAKE_TRY_COMPILE_TARGET_TYPE
+ \ CMAKE_TWEAK_VERSION
+ \ CMAKE_UNITY_BUILD
+ \ CMAKE_UNITY_BUILD_BATCH_SIZE
+ \ CMAKE_UNITY_BUILD_UNIQUE_ID
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_ASM
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_ASM_MASM
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_ASM_NASM
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_C
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_CSharp
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_CUDA
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_CXX
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_Fortran
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_HIP
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_Java
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_RC
+ \ CMAKE_USER_MAKE_RULES_OVERRIDE_Swift
+ \ CMAKE_USE_RELATIVE_PATHS
+ \ CMAKE_VERBOSE_MAKEFILE
+ \ CMAKE_VERIFY_INTERFACE_HEADER_SETS
+ \ CMAKE_VERSION
+ \ CMAKE_VISIBILITY_INLINES_HIDDEN
+ \ CMAKE_VS_DEBUGGER_COMMAND
+ \ CMAKE_VS_DEBUGGER_COMMAND_ARGUMENTS
+ \ CMAKE_VS_DEBUGGER_ENVIRONMENT
+ \ CMAKE_VS_DEBUGGER_WORKING_DIRECTORY
+ \ CMAKE_VS_DEVENV_COMMAND
+ \ CMAKE_VS_GLOBALS
+ \ CMAKE_VS_INCLUDE_INSTALL_TO_DEFAULT_BUILD
+ \ CMAKE_VS_INCLUDE_PACKAGE_TO_DEFAULT_BUILD
+ \ CMAKE_VS_INTEL_Fortran_PROJECT_VERSION
+ \ CMAKE_VS_JUST_MY_CODE_DEBUGGING
+ \ CMAKE_VS_MSBUILD_COMMAND
+ \ CMAKE_VS_NO_COMPILE_BATCHING
+ \ CMAKE_VS_NUGET_PACKAGE_RESTORE
+ \ CMAKE_VS_NsightTegra_VERSION
+ \ CMAKE_VS_PLATFORM_NAME
+ \ CMAKE_VS_PLATFORM_NAME_DEFAULT
+ \ CMAKE_VS_PLATFORM_TOOLSET
+ \ CMAKE_VS_PLATFORM_TOOLSET_CUDA
+ \ CMAKE_VS_PLATFORM_TOOLSET_CUDA_CUSTOM_DIR
+ \ CMAKE_VS_PLATFORM_TOOLSET_HOST_ARCHITECTURE
+ \ CMAKE_VS_PLATFORM_TOOLSET_VERSION
+ \ CMAKE_VS_SDK_EXCLUDE_DIRECTORIES
+ \ CMAKE_VS_SDK_EXECUTABLE_DIRECTORIES
+ \ CMAKE_VS_SDK_INCLUDE_DIRECTORIES
+ \ CMAKE_VS_SDK_LIBRARY_DIRECTORIES
+ \ CMAKE_VS_SDK_LIBRARY_WINRT_DIRECTORIES
+ \ CMAKE_VS_SDK_REFERENCE_DIRECTORIES
+ \ CMAKE_VS_SDK_SOURCE_DIRECTORIES
+ \ CMAKE_VS_TARGET_FRAMEWORK_IDENTIFIER
+ \ CMAKE_VS_TARGET_FRAMEWORK_TARGETS_VERSION
+ \ CMAKE_VS_TARGET_FRAMEWORK_VERSION
+ \ CMAKE_VS_VERSION_BUILD_NUMBER
+ \ CMAKE_VS_WINDOWS_TARGET_PLATFORM_MIN_VERSION
+ \ CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION
+ \ CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM
+ \ CMAKE_VS_WINRT_BY_DEFAULT
+ \ CMAKE_WARN_DEPRECATED
+ \ CMAKE_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
+ \ CMAKE_WATCOM_RUNTIME_LIBRARY
+ \ CMAKE_WIN32_EXECUTABLE
+ \ CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS
+ \ CMAKE_XCODE_BUILD_SYSTEM
+ \ CMAKE_XCODE_GENERATE_SCHEME
+ \ CMAKE_XCODE_GENERATE_TOP_LEVEL_PROJECT_ONLY
+ \ CMAKE_XCODE_LINK_BUILD_PHASE_MODE
+ \ CMAKE_XCODE_PLATFORM_TOOLSET
+ \ CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER
+ \ CMAKE_XCODE_SCHEME_ADDRESS_SANITIZER_USE_AFTER_RETURN
+ \ CMAKE_XCODE_SCHEME_DEBUG_DOCUMENT_VERSIONING
+ \ CMAKE_XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE
+ \ CMAKE_XCODE_SCHEME_DISABLE_MAIN_THREAD_CHECKER
+ \ CMAKE_XCODE_SCHEME_DYNAMIC_LIBRARY_LOADS
+ \ CMAKE_XCODE_SCHEME_DYNAMIC_LINKER_API_USAGE
+ \ CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION
+ \ CMAKE_XCODE_SCHEME_ENABLE_GPU_FRAME_CAPTURE_MODE
+ \ CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION
+ \ CMAKE_XCODE_SCHEME_ENVIRONMENT
+ \ CMAKE_XCODE_SCHEME_GUARD_MALLOC
+ \ CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION
+ \ CMAKE_XCODE_SCHEME_LAUNCH_MODE
+ \ CMAKE_XCODE_SCHEME_MAIN_THREAD_CHECKER_STOP
+ \ CMAKE_XCODE_SCHEME_MALLOC_GUARD_EDGES
+ \ CMAKE_XCODE_SCHEME_MALLOC_SCRIBBLE
+ \ CMAKE_XCODE_SCHEME_MALLOC_STACK
+ \ CMAKE_XCODE_SCHEME_THREAD_SANITIZER
+ \ CMAKE_XCODE_SCHEME_THREAD_SANITIZER_STOP
+ \ CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER
+ \ CMAKE_XCODE_SCHEME_UNDEFINED_BEHAVIOUR_SANITIZER_STOP
+ \ CMAKE_XCODE_SCHEME_ENABLE_GPU_API_VALIDATION
+ \ CMAKE_XCODE_SCHEME_ENABLE_GPU_SHADER_VALIDATION
+ \ CMAKE_XCODE_SCHEME_LAUNCH_CONFIGURATION
+ \ CMAKE_XCODE_SCHEME_WORKING_DIRECTORY
+ \ CMAKE_XCODE_SCHEME_ZOMBIE_OBJECTS
+ \ CMAKE_XCODE_XCCONFIG
+ \ CPACK_ABSOLUTE_DESTINATION_FILES
+ \ CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY
+ \ CPACK_CUSTOM_INSTALL_VARIABLES
+ \ CPACK_ERROR_ON_ABSOLUTE_INSTALL_DESTINATION
+ \ CPACK_INCLUDE_TOPLEVEL_DIRECTORY
+ \ CPACK_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS
+ \ CPACK_PACKAGING_INSTALL_PREFIX
+ \ CPACK_SET_DESTDIR
+ \ CPACK_WARN_ON_ABSOLUTE_INSTALL_DESTINATION
+ \ CTEST_BINARY_DIRECTORY
+ \ CTEST_BUILD_COMMAND
+ \ CTEST_BUILD_NAME
+ \ CTEST_BZR_COMMAND
+ \ CTEST_BZR_UPDATE_OPTIONS
+ \ CTEST_CHANGE_ID
+ \ CTEST_CHECKOUT_COMMAND
+ \ CTEST_CONFIGURATION_TYPE
+ \ CTEST_CONFIGURE_COMMAND
+ \ CTEST_COVERAGE_COMMAND
+ \ CTEST_COVERAGE_EXTRA_FLAGS
+ \ CTEST_CURL_OPTIONS
+ \ CTEST_CUSTOM_COVERAGE_EXCLUDE
+ \ CTEST_CUSTOM_ERROR_EXCEPTION
+ \ CTEST_CUSTOM_ERROR_MATCH
+ \ CTEST_CUSTOM_ERROR_POST_CONTEXT
+ \ CTEST_CUSTOM_ERROR_PRE_CONTEXT
+ \ CTEST_CUSTOM_MAXIMUM_FAILED_TEST_OUTPUT_SIZE
+ \ CTEST_CUSTOM_MAXIMUM_NUMBER_OF_ERRORS
+ \ CTEST_CUSTOM_MAXIMUM_NUMBER_OF_WARNINGS
+ \ CTEST_CUSTOM_MAXIMUM_PASSED_TEST_OUTPUT_SIZE
+ \ CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION
+ \ CTEST_CUSTOM_MEMCHECK_IGNORE
+ \ CTEST_CUSTOM_POST_MEMCHECK
+ \ CTEST_CUSTOM_POST_TEST
+ \ CTEST_CUSTOM_PRE_MEMCHECK
+ \ CTEST_CUSTOM_PRE_TEST
+ \ CTEST_CUSTOM_TESTS_IGNORE
+ \ CTEST_CUSTOM_TEST_OUTPUT_TRUNCATION
+ \ CTEST_CUSTOM_WARNING_EXCEPTION
+ \ CTEST_CUSTOM_WARNING_MATCH
+ \ CTEST_CVS_CHECKOUT
+ \ CTEST_CVS_COMMAND
+ \ CTEST_CVS_UPDATE_OPTIONS
+ \ CTEST_DROP_LOCATION
+ \ CTEST_DROP_METHOD
+ \ CTEST_DROP_SITE
+ \ CTEST_DROP_SITE_CDASH
+ \ CTEST_DROP_SITE_PASSWORD
+ \ CTEST_DROP_SITE_USER
+ \ CTEST_EXTRA_COVERAGE_GLOB
+ \ CTEST_GIT_COMMAND
+ \ CTEST_GIT_INIT_SUBMODULES
+ \ CTEST_GIT_UPDATE_CUSTOM
+ \ CTEST_GIT_UPDATE_OPTIONS
+ \ CTEST_HG_COMMAND
+ \ CTEST_HG_UPDATE_OPTIONS
+ \ CTEST_LABELS_FOR_SUBPROJECTS
+ \ CTEST_MEMORYCHECK_COMMAND
+ \ CTEST_MEMORYCHECK_COMMAND_OPTIONS
+ \ CTEST_MEMORYCHECK_SANITIZER_OPTIONS
+ \ CTEST_MEMORYCHECK_SUPPRESSIONS_FILE
+ \ CTEST_MEMORYCHECK_TYPE
+ \ CTEST_NIGHTLY_START_TIME
+ \ CTEST_P4_CLIENT
+ \ CTEST_P4_COMMAND
+ \ CTEST_P4_OPTIONS
+ \ CTEST_P4_UPDATE_OPTIONS
+ \ CTEST_RESOURCE_SPEC_FILE
+ \ CTEST_RUN_CURRENT_SCRIPT
+ \ CTEST_SCP_COMMAND
+ \ CTEST_SCRIPT_DIRECTORY
+ \ CTEST_SITE
+ \ CTEST_SOURCE_DIRECTORY
+ \ CTEST_SUBMIT_INACTIVITY_TIMEOUT
+ \ CTEST_SUBMIT_URL
+ \ CTEST_SVN_COMMAND
+ \ CTEST_SVN_OPTIONS
+ \ CTEST_SVN_UPDATE_OPTIONS
+ \ CTEST_TEST_LOAD
+ \ CTEST_TEST_TIMEOUT
+ \ CTEST_TRIGGER_SITE
+ \ CTEST_UPDATE_COMMAND
+ \ CTEST_UPDATE_OPTIONS
+ \ CTEST_UPDATE_VERSION_ONLY
+ \ CTEST_UPDATE_VERSION_OVERRIDE
+ \ CTEST_USE_LAUNCHERS
+ \ CYGWIN
+ \ DOXYGEN_ABBREVIATE_BRIEF
+ \ DOXYGEN_ALIASES
+ \ DOXYGEN_ALLEXTERNALS
+ \ DOXYGEN_ALLOW_UNICODE_NAMES
+ \ DOXYGEN_ALPHABETICAL_INDEX
+ \ DOXYGEN_ALWAYS_DETAILED_SEC
+ \ DOXYGEN_AUTOLINK_SUPPORT
+ \ DOXYGEN_BINARY_TOC
+ \ DOXYGEN_BRIEF_MEMBER_DESC
+ \ DOXYGEN_BUILTIN_STL_SUPPORT
+ \ DOXYGEN_CALLER_GRAPH
+ \ DOXYGEN_CALL_GRAPH
+ \ DOXYGEN_CASE_SENSE_NAMES
+ \ DOXYGEN_CHM_FILE
+ \ DOXYGEN_CHM_INDEX_ENCODING
+ \ DOXYGEN_CITE_BIB_FILES
+ \ DOXYGEN_CLANG_ASSISTED_PARSING
+ \ DOXYGEN_CLANG_DATABASE_PATH
+ \ DOXYGEN_CLANG_OPTIONS
+ \ DOXYGEN_CLASS_DIAGRAMS
+ \ DOXYGEN_CLASS_GRAPH
+ \ DOXYGEN_COLLABORATION_GRAPH
+ \ DOXYGEN_COLS_IN_ALPHA_INDEX
+ \ DOXYGEN_COMPACT_LATEX
+ \ DOXYGEN_COMPACT_RTF
+ \ DOXYGEN_CPP_CLI_SUPPORT
+ \ DOXYGEN_CREATE_SUBDIRS
+ \ DOXYGEN_DIAFILE_DIRS
+ \ DOXYGEN_DIA_PATH
+ \ DOXYGEN_DIRECTORY_GRAPH
+ \ DOXYGEN_DISABLE_INDEX
+ \ DOXYGEN_DISTRIBUTE_GROUP_DOC
+ \ DOXYGEN_DOCBOOK_OUTPUT
+ \ DOXYGEN_DOCBOOK_PROGRAMLISTING
+ \ DOXYGEN_DOCSET_BUNDLE_ID
+ \ DOXYGEN_DOCSET_FEEDNAME
+ \ DOXYGEN_DOCSET_PUBLISHER_ID
+ \ DOXYGEN_DOCSET_PUBLISHER_NAME
+ \ DOXYGEN_DOTFILE_DIRS
+ \ DOXYGEN_DOT_CLEANUP
+ \ DOXYGEN_DOT_FONTNAME
+ \ DOXYGEN_DOT_FONTPATH
+ \ DOXYGEN_DOT_FONTSIZE
+ \ DOXYGEN_DOT_GRAPH_MAX_NODES
+ \ DOXYGEN_DOT_IMAGE_FORMAT
+ \ DOXYGEN_DOT_MULTI_TARGETS
+ \ DOXYGEN_DOT_NUM_THREADS
+ \ DOXYGEN_DOT_PATH
+ \ DOXYGEN_DOT_TRANSPARENT
+ \ DOXYGEN_DOXYFILE_ENCODING
+ \ DOXYGEN_ECLIPSE_DOC_ID
+ \ DOXYGEN_ENABLED_SECTIONS
+ \ DOXYGEN_ENABLE_PREPROCESSING
+ \ DOXYGEN_ENUM_VALUES_PER_LINE
+ \ DOXYGEN_EXAMPLE_PATH
+ \ DOXYGEN_EXAMPLE_PATTERNS
+ \ DOXYGEN_EXAMPLE_RECURSIVE
+ \ DOXYGEN_EXCLUDE
+ \ DOXYGEN_EXCLUDE_PATTERNS
+ \ DOXYGEN_EXCLUDE_SYMBOLS
+ \ DOXYGEN_EXCLUDE_SYMLINKS
+ \ DOXYGEN_EXPAND_AS_DEFINED
+ \ DOXYGEN_EXPAND_ONLY_PREDEF
+ \ DOXYGEN_EXTENSION_MAPPING
+ \ DOXYGEN_EXTERNAL_GROUPS
+ \ DOXYGEN_EXTERNAL_PAGES
+ \ DOXYGEN_EXTERNAL_SEARCH
+ \ DOXYGEN_EXTERNAL_SEARCH_ID
+ \ DOXYGEN_EXTRACT_ALL
+ \ DOXYGEN_EXTRACT_ANON_NSPACES
+ \ DOXYGEN_EXTRACT_LOCAL_CLASSES
+ \ DOXYGEN_EXTRACT_LOCAL_METHODS
+ \ DOXYGEN_EXTRACT_PACKAGE
+ \ DOXYGEN_EXTRACT_PRIVATE
+ \ DOXYGEN_EXTRACT_PRIV_VIRTUAL
+ \ DOXYGEN_EXTRACT_STATIC
+ \ DOXYGEN_EXTRA_PACKAGES
+ \ DOXYGEN_EXTRA_SEARCH_MAPPINGS
+ \ DOXYGEN_EXT_LINKS_IN_WINDOW
+ \ DOXYGEN_FILE_PATTERNS
+ \ DOXYGEN_FILE_VERSION_FILTER
+ \ DOXYGEN_FILTER_PATTERNS
+ \ DOXYGEN_FILTER_SOURCE_FILES
+ \ DOXYGEN_FILTER_SOURCE_PATTERNS
+ \ DOXYGEN_FORCE_LOCAL_INCLUDES
+ \ DOXYGEN_FORMULA_FONTSIZE
+ \ DOXYGEN_FORMULA_TRANSPARENT
+ \ DOXYGEN_FULL_PATH_NAMES
+ \ DOXYGEN_GENERATE_AUTOGEN_DEF
+ \ DOXYGEN_GENERATE_BUGLIST
+ \ DOXYGEN_GENERATE_CHI
+ \ DOXYGEN_GENERATE_DEPRECATEDLIST
+ \ DOXYGEN_GENERATE_DOCBOOK
+ \ DOXYGEN_GENERATE_DOCSET
+ \ DOXYGEN_GENERATE_ECLIPSEHELP
+ \ DOXYGEN_GENERATE_HTML
+ \ DOXYGEN_GENERATE_HTMLHELP
+ \ DOXYGEN_GENERATE_LATEX
+ \ DOXYGEN_GENERATE_LEGEND
+ \ DOXYGEN_GENERATE_MAN
+ \ DOXYGEN_GENERATE_PERLMOD
+ \ DOXYGEN_GENERATE_QHP
+ \ DOXYGEN_GENERATE_RTF
+ \ DOXYGEN_GENERATE_TAGFILE
+ \ DOXYGEN_GENERATE_TESTLIST
+ \ DOXYGEN_GENERATE_TODOLIST
+ \ DOXYGEN_GENERATE_TREEVIEW
+ \ DOXYGEN_GENERATE_XML
+ \ DOXYGEN_GRAPHICAL_HIERARCHY
+ \ DOXYGEN_GROUP_GRAPHS
+ \ DOXYGEN_GROUP_NESTED_COMPOUNDS
+ \ DOXYGEN_HAVE_DOT
+ \ DOXYGEN_HHC_LOCATION
+ \ DOXYGEN_HIDE_COMPOUND_REFERENCE
+ \ DOXYGEN_HIDE_FRIEND_COMPOUNDS
+ \ DOXYGEN_HIDE_IN_BODY_DOCS
+ \ DOXYGEN_HIDE_SCOPE_NAMES
+ \ DOXYGEN_HIDE_UNDOC_CLASSES
+ \ DOXYGEN_HIDE_UNDOC_MEMBERS
+ \ DOXYGEN_HIDE_UNDOC_RELATIONS
+ \ DOXYGEN_HTML_COLORSTYLE_GAMMA
+ \ DOXYGEN_HTML_COLORSTYLE_HUE
+ \ DOXYGEN_HTML_COLORSTYLE_SAT
+ \ DOXYGEN_HTML_DYNAMIC_MENUS
+ \ DOXYGEN_HTML_DYNAMIC_SECTIONS
+ \ DOXYGEN_HTML_EXTRA_FILES
+ \ DOXYGEN_HTML_EXTRA_STYLESHEET
+ \ DOXYGEN_HTML_FILE_EXTENSION
+ \ DOXYGEN_HTML_FOOTER
+ \ DOXYGEN_HTML_HEADER
+ \ DOXYGEN_HTML_INDEX_NUM_ENTRIES
+ \ DOXYGEN_HTML_OUTPUT
+ \ DOXYGEN_HTML_STYLESHEET
+ \ DOXYGEN_HTML_TIMESTAMP
+ \ DOXYGEN_IDL_PROPERTY_SUPPORT
+ \ DOXYGEN_IGNORE_PREFIX
+ \ DOXYGEN_IMAGE_PATH
+ \ DOXYGEN_INCLUDED_BY_GRAPH
+ \ DOXYGEN_INCLUDE_FILE_PATTERNS
+ \ DOXYGEN_INCLUDE_GRAPH
+ \ DOXYGEN_INCLUDE_PATH
+ \ DOXYGEN_INHERIT_DOCS
+ \ DOXYGEN_INLINE_GROUPED_CLASSES
+ \ DOXYGEN_INLINE_INFO
+ \ DOXYGEN_INLINE_INHERITED_MEMB
+ \ DOXYGEN_INLINE_SIMPLE_STRUCTS
+ \ DOXYGEN_INLINE_SOURCES
+ \ DOXYGEN_INPUT
+ \ DOXYGEN_INPUT_ENCODING
+ \ DOXYGEN_INPUT_FILTER
+ \ DOXYGEN_INTERACTIVE_SVG
+ \ DOXYGEN_INTERNAL_DOCS
+ \ DOXYGEN_JAVADOC_AUTOBRIEF
+ \ DOXYGEN_JAVADOC_BANNER
+ \ DOXYGEN_LATEX_BATCHMODE
+ \ DOXYGEN_LATEX_BIB_STYLE
+ \ DOXYGEN_LATEX_CMD_NAME
+ \ DOXYGEN_LATEX_EMOJI_DIRECTORY
+ \ DOXYGEN_LATEX_EXTRA_FILES
+ \ DOXYGEN_LATEX_EXTRA_STYLESHEET
+ \ DOXYGEN_LATEX_FOOTER
+ \ DOXYGEN_LATEX_HEADER
+ \ DOXYGEN_LATEX_HIDE_INDICES
+ \ DOXYGEN_LATEX_MAKEINDEX_CMD
+ \ DOXYGEN_LATEX_OUTPUT
+ \ DOXYGEN_LATEX_SOURCE_CODE
+ \ DOXYGEN_LATEX_TIMESTAMP
+ \ DOXYGEN_LAYOUT_FILE
+ \ DOXYGEN_LOOKUP_CACHE_SIZE
+ \ DOXYGEN_MACRO_EXPANSION
+ \ DOXYGEN_MAKEINDEX_CMD_NAME
+ \ DOXYGEN_MAN_EXTENSION
+ \ DOXYGEN_MAN_LINKS
+ \ DOXYGEN_MAN_OUTPUT
+ \ DOXYGEN_MAN_SUBDIR
+ \ DOXYGEN_MARKDOWN_SUPPORT
+ \ DOXYGEN_MATHJAX_CODEFILE
+ \ DOXYGEN_MATHJAX_EXTENSIONS
+ \ DOXYGEN_MATHJAX_FORMAT
+ \ DOXYGEN_MATHJAX_RELPATH
+ \ DOXYGEN_MAX_DOT_GRAPH_DEPTH
+ \ DOXYGEN_MAX_INITIALIZER_LINES
+ \ DOXYGEN_MSCFILE_DIRS
+ \ DOXYGEN_MULTILINE_CPP_IS_BRIEF
+ \ DOXYGEN_OPTIMIZE_FOR_FORTRAN
+ \ DOXYGEN_OPTIMIZE_OUTPUT_FOR_C
+ \ DOXYGEN_OPTIMIZE_OUTPUT_JAVA
+ \ DOXYGEN_OPTIMIZE_OUTPUT_SLICE
+ \ DOXYGEN_OPTIMIZE_OUTPUT_VHDL
+ \ DOXYGEN_OUTPUT_DIRECTORY
+ \ DOXYGEN_OUTPUT_LANGUAGE
+ \ DOXYGEN_OUTPUT_TEXT_DIRECTION
+ \ DOXYGEN_PAPER_TYPE
+ \ DOXYGEN_PDF_HYPERLINKS
+ \ DOXYGEN_PERLMOD_LATEX
+ \ DOXYGEN_PERLMOD_MAKEVAR_PREFIX
+ \ DOXYGEN_PERLMOD_PRETTY
+ \ DOXYGEN_PLANTUML_CFG_FILE
+ \ DOXYGEN_PLANTUML_INCLUDE_PATH
+ \ DOXYGEN_PLANTUML_JAR_PATH
+ \ DOXYGEN_PREDEFINED
+ \ DOXYGEN_PROJECT_BRIEF
+ \ DOXYGEN_PROJECT_LOGO
+ \ DOXYGEN_PROJECT_NAME
+ \ DOXYGEN_PROJECT_NUMBER
+ \ DOXYGEN_QCH_FILE
+ \ DOXYGEN_QHG_LOCATION
+ \ DOXYGEN_QHP_CUST_FILTER_ATTRS
+ \ DOXYGEN_QHP_CUST_FILTER_NAME
+ \ DOXYGEN_QHP_NAMESPACE
+ \ DOXYGEN_QHP_SECT_FILTER_ATTRS
+ \ DOXYGEN_QHP_VIRTUAL_FOLDER
+ \ DOXYGEN_QT_AUTOBRIEF
+ \ DOXYGEN_QUIET
+ \ DOXYGEN_RECURSIVE
+ \ DOXYGEN_REFERENCED_BY_RELATION
+ \ DOXYGEN_REFERENCES_LINK_SOURCE
+ \ DOXYGEN_REFERENCES_RELATION
+ \ DOXYGEN_REPEAT_BRIEF
+ \ DOXYGEN_RTF_EXTENSIONS_FILE
+ \ DOXYGEN_RTF_HYPERLINKS
+ \ DOXYGEN_RTF_OUTPUT
+ \ DOXYGEN_RTF_SOURCE_CODE
+ \ DOXYGEN_RTF_STYLESHEET_FILE
+ \ DOXYGEN_SEARCHDATA_FILE
+ \ DOXYGEN_SEARCHENGINE
+ \ DOXYGEN_SEARCHENGINE_URL
+ \ DOXYGEN_SEARCH_INCLUDES
+ \ DOXYGEN_SEPARATE_MEMBER_PAGES
+ \ DOXYGEN_SERVER_BASED_SEARCH
+ \ DOXYGEN_SHORT_NAMES
+ \ DOXYGEN_SHOW_FILES
+ \ DOXYGEN_SHOW_GROUPED_MEMB_INC
+ \ DOXYGEN_SHOW_INCLUDE_FILES
+ \ DOXYGEN_SHOW_NAMESPACES
+ \ DOXYGEN_SHOW_USED_FILES
+ \ DOXYGEN_SIP_SUPPORT
+ \ DOXYGEN_SKIP_FUNCTION_MACROS
+ \ DOXYGEN_SORT_BRIEF_DOCS
+ \ DOXYGEN_SORT_BY_SCOPE_NAME
+ \ DOXYGEN_SORT_GROUP_NAMES
+ \ DOXYGEN_SORT_MEMBERS_CTORS_1ST
+ \ DOXYGEN_SORT_MEMBER_DOCS
+ \ DOXYGEN_SOURCE_BROWSER
+ \ DOXYGEN_SOURCE_TOOLTIPS
+ \ DOXYGEN_STRICT_PROTO_MATCHING
+ \ DOXYGEN_STRIP_CODE_COMMENTS
+ \ DOXYGEN_STRIP_FROM_INC_PATH
+ \ DOXYGEN_STRIP_FROM_PATH
+ \ DOXYGEN_SUBGROUPING
+ \ DOXYGEN_TAB_SIZE
+ \ DOXYGEN_TAGFILES
+ \ DOXYGEN_TCL_SUBST
+ \ DOXYGEN_TEMPLATE_RELATIONS
+ \ DOXYGEN_TOC_EXPAND
+ \ DOXYGEN_TOC_INCLUDE_HEADINGS
+ \ DOXYGEN_TREEVIEW_WIDTH
+ \ DOXYGEN_TYPEDEF_HIDES_STRUCT
+ \ DOXYGEN_UML_LIMIT_NUM_FIELDS
+ \ DOXYGEN_UML_LOOK
+ \ DOXYGEN_USE_HTAGS
+ \ DOXYGEN_USE_MATHJAX
+ \ DOXYGEN_USE_MDFILE_AS_MAINPAGE
+ \ DOXYGEN_USE_PDFLATEX
+ \ DOXYGEN_VERBATIM_HEADERS
+ \ DOXYGEN_VERBATIM_VARS
+ \ DOXYGEN_VERSION
+ \ DOXYGEN_WARNINGS
+ \ DOXYGEN_WARN_AS_ERROR
+ \ DOXYGEN_WARN_FORMAT
+ \ DOXYGEN_WARN_IF_DOC_ERROR
+ \ DOXYGEN_WARN_IF_UNDOCUMENTED
+ \ DOXYGEN_WARN_LOGFILE
+ \ DOXYGEN_WARN_NO_PARAMDOC
+ \ DOXYGEN_XML_NS_MEMB_FILE_SCOPE
+ \ DOXYGEN_XML_OUTPUT
+ \ DOXYGEN_XML_PROGRAMLISTING
+ \ ENV
+ \ EXECUTABLE_OUTPUT_PATH
+ \ GHSMULTI
+ \ IOS
+ \ LIBRARY_OUTPUT_PATH
+ \ LINUX
+ \ MINGW
+ \ MSVC
+ \ MSVC10
+ \ MSVC11
+ \ MSVC12
+ \ MSVC14
+ \ MSVC60
+ \ MSVC70
+ \ MSVC71
+ \ MSVC80
+ \ MSVC90
+ \ MSVC_IDE
+ \ MSVC_TOOLSET_VERSION
+ \ MSVC_VERSION
+ \ MSYS
+ \ PROJECT_BINARY_DIR
+ \ PROJECT_DESCRIPTION
+ \ PROJECT_HOMEPAGE_URL
+ \ PROJECT_IS_TOP_LEVEL
+ \ PROJECT_NAME
+ \ PROJECT_SOURCE_DIR
+ \ PROJECT_VERSION
+ \ PROJECT_VERSION_MAJOR
+ \ PROJECT_VERSION_MINOR
+ \ PROJECT_VERSION_PATCH
+ \ PROJECT_VERSION_TWEAK
+ \ UNIX
+ \ WIN32
+ \ WINCE
+ \ WINDOWS_PHONE
+ \ WINDOWS_STORE
+ \ XCODE
+ \ XCODE_VERSION
syn keyword cmakeModule contained
\ ExternalProject
+ \ FetchContent
syn keyword cmakeKWExternalProject contained
- \ ALGO AWS BINARY_DIR BUILD_ALWAYS BUILD_BYPRODUCTS BUILD_COMMAND BUILD_IN_SOURCE CMAKE_ARGS CMAKE_CACHE_ARGS CMAKE_CACHE_DEFAULT_ARGS CMAKE_TLS_CAINFO CMAKE_TLS_VERIFY COMMENT CONFIGURE_COMMAND CVS CVSROOT CVS_MODULE CVS_REPOSITORY CVS_TAG DEPENDEES DEPENDERS DEPENDS DOWNLOADED_FILE DOWNLOAD_COMMAND DOWNLOAD_DIR DOWNLOAD_NAME DOWNLOAD_NO_EXTRACT DOWNLOAD_NO_PROGRESS EP_BASE EP_INDEPENDENT_STEP_TARGETS EP_PREFIX EP_STEP_TARGETS EP_UPDATE_DISCONNECTED EXCLUDE_FROM_ALL FORCE GIT_CONFIG GIT_PROGRESS GIT_REMOTE_NAME GIT_REPOSITORY GIT_SHALLOW GIT_SUBMODULES GIT_TAG HG_REPOSITORY HG_TAG HTTP_HEADER HTTP_PASSWORD HTTP_USERNAME INDEPENDENT_STEP_TARGETS INSTALL_COMMAND INSTALL_DIR JOB_POOLS LIST_SEPARATOR LOG_ LOG_BUILD LOG_CONFIGURE LOG_DOWNLOAD LOG_INSTALL LOG_TEST LOG_UPDATE MAKE_EXE NAMES NOTE NO_DEPENDS PATCH_COMMAND PREFIX PROPERTY SOURCE_DIR SOURCE_SUBDIR STAMP_DIR STEP_TARGETS STRING SVN_PASSWORD SVN_REPOSITORY SVN_REVISION SVN_TRUST_CERT SVN_USERNAME TEST_AFTER_INSTALL TEST_BEFORE_INSTALL TEST_COMMAND TEST_EXCLUDE_FROM_MAIN TIMEOUT TLS_CAINFO TLS_VERIFY TMP_DIR TRUE UPDATE_COMMAND UPDATE_DISCONNECTED URL URL_HASH USES_TERMINAL_BUILD USES_TERMINAL_CONFIGURE USES_TERMINAL_DOWNLOAD USES_TERMINAL_INSTALL USES_TERMINAL_TEST USES_TERMINAL_UPDATE WORKING_DIRECTORY
+ \ AWS
+ \ BINARY_DIR
+ \ BUILD_ALWAYS
+ \ BUILD_BYPRODUCTS
+ \ BUILD_COMMAND
+ \ BUILD_IN_SOURCE
+ \ CHECKOUT
+ \ CMAKE_ARGS
+ \ CMAKE_CACHE_ARGS
+ \ CMAKE_CACHE_DEFAULT_ARGS
+ \ CMAKE_EP_GIT_REMOTE_UPDATE_STRATEGY
+ \ CMAKE_INSTALL_MODE
+ \ COMMENT
+ \ CONFIGURE_COMMAND
+ \ CONFIGURE_HANDLED_BY_BUILD
+ \ CVS
+ \ CVSROOT
+ \ CVS_MODULE
+ \ CVS_REPOSITORY
+ \ CVS_TAG
+ \ DEPENDEES
+ \ DEPENDERS
+ \ DEPENDS
+ \ DOWNLOADED_FILE
+ \ DOWNLOAD_COMMAND
+ \ DOWNLOAD_DIR
+ \ DOWNLOAD_EXTRACT_TIMESTAMP
+ \ DOWNLOAD_NAME
+ \ DOWNLOAD_NO_EXTRACT
+ \ DOWNLOAD_NO_PROGRESS
+ \ EP_BASE
+ \ EP_INDEPENDENT_STEP_TARGETS
+ \ EP_PREFIX
+ \ EP_STEP_TARGETS
+ \ EP_UPDATE_DISCONNECTED
+ \ EXCLUDE_FROM_ALL
+ \ FALSE
+ \ FORCE
+ \ GHS
+ \ GIT_CONFIG
+ \ GIT_PROGRESS
+ \ GIT_REMOTE_NAME
+ \ GIT_REMOTE_UPDATE_STRATEGY
+ \ GIT_REPOSITORY
+ \ GIT_SHALLOW
+ \ GIT_SUBMODULES
+ \ GIT_SUBMODULES_RECURSE
+ \ GIT_TAG
+ \ HG_REPOSITORY
+ \ HG_TAG
+ \ HTTP_HEADER
+ \ HTTP_PASSWORD
+ \ HTTP_USERNAME
+ \ IGNORED
+ \ INACTIVITY_TIMEOUT
+ \ INDEPENDENT_STEP_TARGETS
+ \ INSTALL_BYPRODUCTS
+ \ INSTALL_COMMAND
+ \ INSTALL_DIR
+ \ JOB_POOLS
+ \ LIST_SEPARATOR
+ \ LOG_BUILD
+ \ LOG_CONFIGURE
+ \ LOG_DIR
+ \ LOG_DOWNLOAD
+ \ LOG_INSTALL
+ \ LOG_MERGED_STDOUTERR
+ \ LOG_OUTPUT_ON_FAILURE
+ \ LOG_PATCH
+ \ LOG_TEST
+ \ LOG_UPDATE
+ \ MAKE_EXE
+ \ MULTI
+ \ NAMES
+ \ NETRC
+ \ NETRC_FILE
+ \ NOTE
+ \ NO_DEPENDS
+ \ OPTIONAL
+ \ PATCH_COMMAND
+ \ PREFIX
+ \ PROPERTY
+ \ REBASE
+ \ REBASE_CHECKOUT
+ \ REQUIRED
+ \ SOURCE_DIR
+ \ SOURCE_SUBDIR
+ \ STAMP_DIR
+ \ STEP_TARGETS
+ \ STRING
+ \ SVN_PASSWORD
+ \ SVN_REPOSITORY
+ \ SVN_REVISION
+ \ SVN_TRUST_CERT
+ \ SVN_USERNAME
+ \ TEST_AFTER_INSTALL
+ \ TEST_BEFORE_INSTALL
+ \ TEST_COMMAND
+ \ TEST_EXCLUDE_FROM_MAIN
+ \ TIMEOUT
+ \ TLS_CAINFO
+ \ TLS_VERIFY
+ \ TMP_DIR
+ \ TRUE
+ \ UPDATE_COMMAND
+ \ UPDATE_DISCONNECTED
+ \ URL
+ \ URL_HASH
+ \ URL_MD5
+ \ USES_TERMINAL_BUILD
+ \ USES_TERMINAL_CONFIGURE
+ \ USES_TERMINAL_DOWNLOAD
+ \ USES_TERMINAL_INSTALL
+ \ USES_TERMINAL_PATCH
+ \ USES_TERMINAL_TEST
+ \ USES_TERMINAL_UPDATE
+ \ WORKING_DIRECTORY
+
+syn keyword cmakeKWFetchContent contained
+ \ ALWAYS
+ \ BINARY_DIR
+ \ BUILD_COMMAND
+ \ BYPASS_PROVIDER
+ \ CMAKE_PROJECT_
+ \ CONFIGURE_COMMAND
+ \ COPY
+ \ CORRECT
+ \ DCMAKE_TOOLCHAIN_FILE
+ \ DESTINATION
+ \ DOWNLOAD_NO_EXTRACT
+ \ EXISTS
+ \ FETCHCONTENT_BASE_DIR
+ \ FETCHCONTENT_FULLY_DISCONNECTED
+ \ FETCHCONTENT_MAKEAVAILABLE_SERIAL
+ \ FETCHCONTENT_QUIET
+ \ FETCHCONTENT_SOURCE_DIR_
+ \ FETCHCONTENT_TRY_FIND_PACKAGE_MODE
+ \ FETCHCONTENT_UPDATES_DISCONNECTED
+ \ FETCHCONTENT_UPDATES_DISCONNECTED_
+ \ FIND_PACKAGE_ARGS
+ \ GIT_REPOSITORY
+ \ GIT_TAG
+ \ GLOBAL
+ \ GTEST_BOTH_LIBRARIES
+ \ GTEST_LIBRARIES
+ \ GTEST_MAIN_LIBRARIES
+ \ INSTALL_COMMAND
+ \ INTERNAL
+ \ NAME
+ \ NAMES
+ \ NEVER
+ \ NOTE
+ \ OFF
+ \ OPTIONAL
+ \ OPT_IN
+ \ OVERRIDE_FIND_PACKAGE
+ \ PACKAGE_VERSION_COMPATIBLE
+ \ PACKAGE_VERSION_EXACT
+ \ QUIET
+ \ SOURCE_SUBDIR
+ \ STREQUAL
+ \ SUBBUILD_DIR
+ \ SVN_REPOSITORY
+ \ SVN_REVISION
+ \ SYSTEM
+ \ TARGET
+ \ TEST_COMMAND
+ \ TRUE
+ \ URL
+ \ URL_HASH
+ \ VERIFY_INTERFACE_HEADER_SETS
+ \ WRITE
+ \ WRONG
+ \ _BINARY_DIR
+ \ _INCLUDE
+ \ _POPULATED
+ \ _SOURCE_DIR
+
+syn keyword cmakeKWadd_compile_definitions contained
+ \ COMPILE_DEFINITIONS
+ \ VAR
syn keyword cmakeKWadd_compile_options contained
+ \ CMAKE_
+ \ COMPILE_LANGUAGE
\ COMPILE_OPTIONS
+ \ CONFIG
+ \ SHELL
+ \ UNIX_COMMAND
+ \ _FLAGS
+ \ _FLAGS_
syn keyword cmakeKWadd_custom_command contained
- \ APPEND ARGS BYPRODUCTS CC COMMAND COMMAND_EXPAND_LISTS COMMENT CROSSCOMPILING_EMULATOR DEPENDS DEPFILE GENERATED IMPLICIT_DEPENDS INCLUDE_DIRECTORIES JOIN MAIN_DEPENDENCY NOT OUTPUT POST_BUILD PRE_BUILD PRE_LINK SYMBOLIC TARGET_FILE TARGET_PROPERTY USES_TERMINAL VERBATIM WORKING_DIRECTORY
+ \ APPEND
+ \ ARGS
+ \ BNF
+ \ BYPRODUCTS
+ \ CC
+ \ COMMAND
+ \ COMMAND_EXPAND_LISTS
+ \ COMMENT
+ \ CONFIG
+ \ CROSSCOMPILING_EMULATOR
+ \ DEPENDS
+ \ DEPENDS_EXPLICIT_ONLY
+ \ DEPFILE
+ \ GENERATED
+ \ IMPLICIT_DEPENDS
+ \ INCLUDE_DIRECTORIES
+ \ JOB_POOL
+ \ JOB_POOLS
+ \ JOIN
+ \ MAIN_DEPENDENCY
+ \ MODULE
+ \ NOT
+ \ OUTPUT
+ \ PATH
+ \ POST_BUILD
+ \ PRE_BUILD
+ \ PRE_LINK
+ \ SYMBOLIC
+ \ TARGET_FILE
+ \ TARGET_LINKER_FILE
+ \ TARGET_PDB_FILE
+ \ TARGET_PROPERTY
+ \ TARGET_SONAME_FILE
+ \ USES_TERMINAL
+ \ VERBATIM
+ \ WORKING_DIRECTORY
syn keyword cmakeKWadd_custom_target contained
- \ ALL BYPRODUCTS CC COMMAND COMMAND_EXPAND_LISTS COMMENT CROSSCOMPILING_EMULATOR DEPENDS GENERATED INCLUDE_DIRECTORIES JOIN SOURCES TARGET_PROPERTY USES_TERMINAL VERBATIM WORKING_DIRECTORY
+ \ ALL
+ \ BYPRODUCTS
+ \ CC
+ \ COMMAND
+ \ COMMAND_EXPAND_LISTS
+ \ COMMENT
+ \ CROSSCOMPILING_EMULATOR
+ \ DEPENDS
+ \ GENERATED
+ \ INCLUDE_DIRECTORIES
+ \ JOB_POOL
+ \ JOB_POOLS
+ \ JOIN
+ \ PATH
+ \ SOURCES
+ \ TARGET_FILE
+ \ TARGET_LINKER_FILE
+ \ TARGET_PDB_FILE
+ \ TARGET_PROPERTY
+ \ TARGET_SONAME_FILE
+ \ USES_TERMINAL
+ \ VERBATIM
+ \ WORKING_DIRECTORY
syn keyword cmakeKWadd_definitions contained
\ COMPILE_DEFINITIONS
syn keyword cmakeKWadd_dependencies contained
- \ DEPENDS OBJECT_DEPENDS
+ \ DEPENDS
+ \ OBJECT_DEPENDS
syn keyword cmakeKWadd_executable contained
- \ ALIAS CONFIG EXCLUDE_FROM_ALL GLOBAL HEADER_FILE_ONLY IMPORTED IMPORTED_ IMPORTED_LOCATION IMPORTED_LOCATION_ MACOSX_BUNDLE OUTPUT_NAME RUNTIME_OUTPUT_DIRECTORY TARGET
+ \ ALIAS
+ \ ALIAS_GLOBAL
+ \ CONFIG
+ \ EXCLUDE_FROM_ALL
+ \ GLOBAL
+ \ HEADER_FILE_ONLY
+ \ IMPORTED
+ \ IMPORTED_
+ \ IMPORTED_LOCATION
+ \ IMPORTED_LOCATION_
+ \ MACOSX_BUNDLE
+ \ OUTPUT_NAME
+ \ RUNTIME_OUTPUT_DIRECTORY
+ \ TARGET
syn keyword cmakeKWadd_library contained
- \ ALIAS ARCHIVE_OUTPUT_DIRECTORY CLI CONFIG DLL EXCLUDE_FROM_ALL FRAMEWORK GLOBAL HEADER_FILE_ONLY IMPORTED IMPORTED_ IMPORTED_LOCATION IMPORTED_LOCATION_ INTERFACE_ LIBRARY_OUTPUT_DIRECTORY MODULE OBJECT ON OUTPUT_NAME POSITION_INDEPENDENT_CODE POST_BUILD PRE_BUILD PRE_LINK RUNTIME_OUTPUT_DIRECTORY SHARED STATIC TARGET_OBJECTS UNKNOWN
+ \ ALIAS
+ \ ALIAS_GLOBAL
+ \ ARCHIVE_OUTPUT_DIRECTORY
+ \ CLI
+ \ CONFIG
+ \ DLL
+ \ EXCLUDE_FROM_ALL
+ \ FRAMEWORK
+ \ GLOBAL
+ \ HEADER_FILE_ONLY
+ \ HEADER_SETS
+ \ IMPORTED
+ \ IMPORTED_
+ \ IMPORTED_IMPLIB
+ \ IMPORTED_IMPLIB_
+ \ IMPORTED_LOCATION
+ \ IMPORTED_LOCATION_
+ \ IMPORTED_NO_SONAME
+ \ IMPORTED_OBJECTS
+ \ IMPORTED_OBJECTS_
+ \ IMPORTED_SONAME
+ \ INTERFACE
+ \ INTERFACE_
+ \ INTERFACE_SOURCES
+ \ LC_ID_DYLIB
+ \ LIBRARY_OUTPUT_DIRECTORY
+ \ MODULE
+ \ OBJECT
+ \ ON
+ \ OUTPUT_NAME
+ \ POSITION_INDEPENDENT_CODE
+ \ POST_BUILD
+ \ PRE_BUILD
+ \ PRE_LINK
+ \ PRIVATE_HEADER
+ \ PUBLIC_HEADER
+ \ RUNTIME_OUTPUT_DIRECTORY
+ \ SHARED
+ \ SONAME
+ \ SOURCES
+ \ STATIC
+ \ TARGETS
+ \ TARGET_OBJECTS
+ \ TARGET_RUNTIME_DLLS
+ \ UNKNOWN
+
+syn keyword cmakeKWadd_link_options contained
+ \ CMAKE_
+ \ CONFIG
+ \ CUDA_RESOLVE_DEVICE_SYMBOLS
+ \ CUDA_SEPARABLE_COMPILATION
+ \ DEVICE_LINK
+ \ GCC
+ \ HOST_LINK
+ \ LANG
+ \ LINKER
+ \ LINK_OPTIONS
+ \ SHELL
+ \ STATIC_LIBRARY_OPTIONS
+ \ UNIX_COMMAND
+ \ _FLAGS
+ \ _FLAGS_
+ \ _LINKER_WRAPPER_FLAG
+ \ _LINKER_WRAPPER_FLAG_SEP
syn keyword cmakeKWadd_subdirectory contained
\ EXCLUDE_FROM_ALL
+ \ SYSTEM
syn keyword cmakeKWadd_test contained
- \ BUILD_TESTING COMMAND CONFIGURATIONS FAIL_REGULAR_EXPRESSION NAME PASS_REGULAR_EXPRESSION TARGET_FILE WILL_FAIL WORKING_DIRECTORY
+ \ BUILD_TESTING
+ \ COMMAND
+ \ COMMAND_EXPAND_LISTS
+ \ CONFIGURATIONS
+ \ FAIL_REGULAR_EXPRESSION
+ \ NAME
+ \ OFF
+ \ PASS_REGULAR_EXPRESSION
+ \ SKIP_REGULAR_EXPRESSION
+ \ TARGET_FILE
+ \ WILL_FAIL
+ \ WILL_FALL
+ \ WORKING_DIRECTORY
+
+syn keyword cmakeKWblock contained
+ \ PARENT_SCOPE
+ \ POLICIES
+ \ PROPAGATE
+ \ PUSH
+ \ SCOPE_FOR
+ \ TRUE
+ \ VARIABLES
syn keyword cmakeKWbuild_command contained
- \ CONFIGURATION TARGET
+ \ CONFIGURATION
+ \ PARALLEL_LEVEL
+ \ TARGET
-syn keyword cmakeKWbuild_name contained
- \ CMAKE_CXX_COMPILER
+syn keyword cmakeKWcmake_file_api contained
+ \ API
+ \ API_VERSION
+ \ BUILD_DIR
+ \ CMAKEFILES
+ \ CODEMODEL
+ \ COMMAND
+ \ CONFIG
+ \ QUERY
+ \ TOOLCHAINS
syn keyword cmakeKWcmake_host_system_information contained
- \ AVAILABLE_PHYSICAL_MEMORY AVAILABLE_VIRTUAL_MEMORY FQDN HAS_FPU HAS_MMX HAS_MMX_PLUS HAS_SERIAL_NUMBER HAS_SSE HAS_SSE_FP HAS_SSE_MMX HOSTNAME ID NUMBER_OF_LOGICAL_CORES NUMBER_OF_PHYSICAL_CORES OS_NAME OS_PLATFORM OS_RELEASE OS_VERSION PROCESSOR_DESCRIPTION PROCESSOR_NAME PROCESSOR_SERIAL_NUMBER QUERY RESULT TOTAL_PHYSICAL_MEMORY TOTAL_VIRTUAL_MEMORY
+ \ APPEND
+ \ AVAILABLE_PHYSICAL_MEMORY
+ \ AVAILABLE_VIRTUAL_MEMORY
+ \ BOTH
+ \ CMAKE_GET_OS_RELEASE_FALLBACK_CONTENT
+ \ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_
+ \ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_ID
+ \ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_NAME
+ \ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_PRETTY_NAME
+ \ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION
+ \ CMAKE_GET_OS_RELEASE_FALLBACK_RESULT_VERSION_ID
+ \ CMAKE_GET_OS_RELEASE_FALLBACK_SCRIPTS
+ \ DISTRIB_INFO
+ \ DISTRIB_PRETTY_NAME
+ \ DISTRO
+ \ DISTRO_BUG_REPORT_URL
+ \ DISTRO_HOME_URL
+ \ DISTRO_ID
+ \ DISTRO_ID_LIKE
+ \ DISTRO_NAME
+ \ DISTRO_PRETTY_NAME
+ \ DISTRO_PRIVACY_POLICY_URL
+ \ DISTRO_SUPPORT_URL
+ \ DISTRO_UBUNTU_CODENAME
+ \ DISTRO_VERSION
+ \ DISTRO_VERSION_CODENAME
+ \ DISTRO_VERSION_ID
+ \ ERROR_VARIABLE
+ \ EXISTS
+ \ FQDN
+ \ HAS_FPU
+ \ HAS_MMX
+ \ HAS_MMX_PLUS
+ \ HAS_SERIAL_NUMBER
+ \ HAS_SSE
+ \ HAS_SSE_FP
+ \ HAS_SSE_MMX
+ \ HKCC
+ \ HKCR
+ \ HKCU
+ \ HKEY_CLASSES_ROOT
+ \ HKEY_CURRENT_CONFIG
+ \ HKEY_CURRENT_USER
+ \ HKEY_LOCAL_MACHINE
+ \ HKEY_USERS
+ \ HKLM
+ \ HKU
+ \ HOSTNAME
+ \ ID
+ \ LIMIT_COUNT
+ \ LISTS
+ \ LTS
+ \ MATCHES
+ \ NNN
+ \ NOT
+ \ NUMBER_OF_LOGICAL_CORES
+ \ NUMBER_OF_PHYSICAL_CORES
+ \ OS_NAME
+ \ OS_PLATFORM
+ \ OS_RELEASE
+ \ OS_VERSION
+ \ PRETTY_NAME
+ \ PROCESSOR_DESCRIPTION
+ \ PROCESSOR_NAME
+ \ PROCESSOR_SERIAL_NUMBER
+ \ QUERY
+ \ REG_DWORD
+ \ REG_EXPAND_SZ
+ \ REG_MULTI_SZ
+ \ REG_QWORD
+ \ REG_SZ
+ \ RESULT
+ \ SEPARATOR
+ \ SOFTWARE
+ \ STATUS
+ \ STRINGS
+ \ SUBKEYS
+ \ TARGET
+ \ TOTAL_PHYSICAL_MEMORY
+ \ TOTAL_VIRTUAL_MEMORY
+ \ VALUE_NAMES
+ \ VAR
+ \ VIEW
+ \ WINDOWS_REGISTRY
+
+syn keyword cmakeKWcmake_language contained
+ \ AND
+ \ ANY
+ \ APPEND
+ \ ARGN
+ \ BINARY_DIR
+ \ BYPASS_PROVIDER
+ \ CALL
+ \ CANCEL_CALL
+ \ CODE
+ \ COMMAND
+ \ COMMAND_ERROR_IS_FATAL
+ \ DCMAKE_PROJECT_TOP_LEVEL_INCLUDES
+ \ DEFER
+ \ DIRECTORY
+ \ EVAL
+ \ FALSE
+ \ FETCHCONTENT_MAKEAVAILABE_SERIAL
+ \ FETCHCONTENT_MAKEAVAILABLE_SERIAL
+ \ FETCHCONTENT_SOURCE_DIR_
+ \ FETCHCONTENT_TRY_FIND_PACKAGE_MODE
+ \ FIND_PACKAGE
+ \ FIND_PACKAGE_ARGS
+ \ GET_CALL_IDS
+ \ GET_MESSAGE_LOG_LEVEL
+ \ GIT_REPOSITORY
+ \ GIT_SUBMODULES
+ \ GIT_TAG
+ \ ID_VAR
+ \ MATCHES
+ \ MYCOMP_PROVIDER_INSTALL_DIR
+ \ NEVER
+ \ NOT
+ \ OVERRIDE_FIND_PACKAGE
+ \ PATH
+ \ POP_BACK
+ \ QUIET
+ \ SET_DEPENDENCY_PROVIDER
+ \ SOURCE_DIR
+ \ STATUS
+ \ STREQUAL
+ \ SUPPORTED_METHODS
+ \ TRUE
+ \ VERSION
+ \ WRITE
+ \ _FOUND
+ \ _PATH
syn keyword cmakeKWcmake_minimum_required contained
- \ FATAL_ERROR VERSION
+ \ FATAL_ERROR
+ \ VERSION
syn keyword cmakeKWcmake_parse_arguments contained
- \ ARGN CONFIGURATIONS DESTINATION FALSE FAST FILES MY_INSTALL MY_INSTALL_CONFIGURATIONS MY_INSTALL_DESTINATION MY_INSTALL_FAST MY_INSTALL_OPTIONAL MY_INSTALL_RENAME MY_INSTALL_TARGETS MY_INSTALL_UNPARSED_ARGUMENTS OPTIONAL PARSE_ARGV RENAME TARGETS TRUE _UNPARSED_ARGUMENTS
+ \ ARGN
+ \ CONFIGURATIONS
+ \ DESTINATION
+ \ FALSE
+ \ FAST
+ \ FILES
+ \ MY_INSTALL
+ \ MY_INSTALL_CONFIGURATIONS
+ \ MY_INSTALL_DESTINATION
+ \ MY_INSTALL_FAST
+ \ MY_INSTALL_KEYWORDS_MISSING_VALUES
+ \ MY_INSTALL_OPTIONAL
+ \ MY_INSTALL_RENAME
+ \ MY_INSTALL_TARGETS
+ \ MY_INSTALL_UNPARSED_ARGUMENTS
+ \ OPTIONAL
+ \ PARSE_ARGV
+ \ RENAME
+ \ TARGETS
+ \ TRUE
+ \ UNDEFINED
+ \ _KEYWORDS_MISSING_VALUES
+ \ _UNPARSED_ARGUMENTS
+
+syn keyword cmakeKWcmake_path contained
+ \ ABSOLUTE_PATH
+ \ AND
+ \ APPEND
+ \ APPEND_STRING
+ \ BASE_DIRECTORY
+ \ COMPARE
+ \ CONVERT
+ \ EQUAL
+ \ EXTENSION
+ \ EXTENSION_DEF
+ \ FALSE
+ \ FILENAME
+ \ FILENAME_DEF
+ \ GET
+ \ GET_EXTENSION
+ \ GET_FILENAME
+ \ GET_PARENT_PATH
+ \ GET_RELATIVE_PART
+ \ GET_ROOT_DIRECTORY
+ \ GET_ROOT_NAME
+ \ GET_ROOT_PATH
+ \ GET_STEM
+ \ HASH
+ \ HAS_EXTENSION
+ \ HAS_FILENAME
+ \ HAS_PARENT_PATH
+ \ HAS_RELATIVE_PART
+ \ HAS_ROOT_DIRECTORY
+ \ HAS_ROOT_NAME
+ \ HAS_ROOT_PATH
+ \ HAS_STEM
+ \ IS_ABSOLUTE
+ \ IS_PREFIX
+ \ IS_RELATIVE
+ \ LAST_ONLY
+ \ MATCHES
+ \ NATIVE_PATH
+ \ NORMALIZE
+ \ NORMAL_PATH
+ \ NOT_EQUAL
+ \ OP
+ \ OUTPUT_VARIABLE
+ \ PARENT_PATH
+ \ REAL_PATH
+ \ RELATIVE_PART
+ \ RELATIVE_PATH
+ \ REMOVE_EXTENSION
+ \ REMOVE_FILENAME
+ \ REPLACE_EXTENSION
+ \ REPLACE_FILENAME
+ \ ROOT_DIRECTORY
+ \ ROOT_NAME
+ \ ROOT_PATH
+ \ SET
+ \ STEM
+ \ STREQUAL
+ \ TO_CMAKE_PATH_LIST
+ \ TO_NATIVE_PATH_LIST
+ \ TRUE
+ \ XOR
syn keyword cmakeKWcmake_policy contained
- \ CMAKE_POLICY_DEFAULT_CMP CMP GET NNNN NO_POLICY_SCOPE OLD POP PUSH SET VERSION
+ \ CMAKE_POLICY_DEFAULT_CMP
+ \ CMP
+ \ GET
+ \ NNNN
+ \ NO_POLICY_SCOPE
+ \ OLD
+ \ POLICIES
+ \ POP
+ \ PUSH
+ \ SCOPE_FOR
+ \ SET
+ \ VERSION
syn keyword cmakeKWconfigure_file contained
- \ COPYONLY CRLF DOS ESCAPE_QUOTES FOO_ENABLE FOO_STRING LF NEWLINE_STYLE VAR
+ \ COPYONLY
+ \ CRLF
+ \ DOS
+ \ ESCAPE_QUOTES
+ \ FILE_PERMISSIONS
+ \ FOO_ENABLE
+ \ FOO_STRING
+ \ GENERATE
+ \ INTERFACE
+ \ LF
+ \ NEWLINE_STYLE
+ \ NO_SOURCE_PERMISSIONS
+ \ PRIVATE
+ \ PUBLIC
+ \ SYSTEM
+ \ USE_SOURCE_PERMISSIONS
+ \ VAR
syn keyword cmakeKWcreate_test_sourcelist contained
- \ CMAKE_TESTDRIVER_AFTER_TESTMAIN CMAKE_TESTDRIVER_BEFORE_TESTMAIN EXTRA_INCLUDE FUNCTION
+ \ CMAKE_TESTDRIVER_AFTER_TESTMAIN
+ \ CMAKE_TESTDRIVER_BEFORE_TESTMAIN
+ \ EXTRA_INCLUDE
+ \ FUNCTION
syn keyword cmakeKWctest_build contained
- \ ALL_BUILD APPEND BUILD CAPTURE_CMAKE_ERROR CONFIGURATION CTEST_BUILD_CONFIGURATION CTEST_BUILD_FLAGS CTEST_BUILD_TARGET CTEST_PROJECT_NAME FLAGS NUMBER_ERRORS NUMBER_WARNINGS QUIET RETURN_VALUE TARGET
+ \ ALL_BUILD
+ \ APPEND
+ \ BUILD
+ \ CAPTURE_CMAKE_ERROR
+ \ CMAKE_BUILD_PARALLEL_LEVEL
+ \ CONFIGURATION
+ \ CTEST_BUILD_CONFIGURATION
+ \ CTEST_BUILD_FLAGS
+ \ CTEST_BUILD_TARGET
+ \ FLAGS
+ \ NUMBER_ERRORS
+ \ NUMBER_WARNINGS
+ \ PARALLEL_LEVEL
+ \ QUIET
+ \ RETURN_VALUE
+ \ TARGET
syn keyword cmakeKWctest_configure contained
- \ APPEND BUILD CAPTURE_CMAKE_ERROR OPTIONS QUIET RETURN_VALUE SOURCE
+ \ APPEND
+ \ BUILD
+ \ CAPTURE_CMAKE_ERROR
+ \ OPTIONS
+ \ QUIET
+ \ RETURN_VALUE
+ \ SOURCE
syn keyword cmakeKWctest_coverage contained
- \ APPEND BUILD CAPTURE_CMAKE_ERROR LABELS QUIET RETURN_VALUE
+ \ APPEND
+ \ BUILD
+ \ CAPTURE_CMAKE_ERROR
+ \ LABELS
+ \ QUIET
+ \ RETURN_VALUE
syn keyword cmakeKWctest_memcheck contained
- \ APPEND BUILD DEFECT_COUNT EXCLUDE EXCLUDE_FIXTURE EXCLUDE_FIXTURE_CLEANUP EXCLUDE_FIXTURE_SETUP EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD
+ \ APPEND
+ \ BUILD
+ \ CAPTURE_CMAKE_ERROR
+ \ DEFECT_COUNT
+ \ EXCLUDE
+ \ EXCLUDE_FIXTURE
+ \ EXCLUDE_FIXTURE_CLEANUP
+ \ EXCLUDE_FIXTURE_SETUP
+ \ EXCLUDE_LABEL
+ \ INCLUDE
+ \ INCLUDE_LABEL
+ \ OFF
+ \ ON
+ \ OUTPUT_JUNIT
+ \ PARALLEL_LEVEL
+ \ QUIET
+ \ REPEAT
+ \ RESOURCE_SPEC_FILE
+ \ RETURN_VALUE
+ \ SCHEDULE_RANDOM
+ \ START
+ \ STOP_ON_FAILURE
+ \ STOP_TIME
+ \ STRIDE
+ \ TEST_LOAD
syn keyword cmakeKWctest_run_script contained
- \ NEW_PROCESS RETURN_VALUE
+ \ NEW_PROCESS
+ \ RETURN_VALUE
syn keyword cmakeKWctest_start contained
- \ APPEND QUIET TAG TRACK
+ \ APPEND
+ \ GROUP
+ \ QUIET
+ \ TAG
+ \ TRACK
syn keyword cmakeKWctest_submit contained
- \ API CDASH_UPLOAD CDASH_UPLOAD_TYPE CTEST_EXTRA_SUBMIT_FILES CTEST_NOTES_FILES FILES HTTPHEADER PARTS QUIET RETRY_COUNT RETRY_DELAY RETURN_VALUE
+ \ API
+ \ BUILD_ID
+ \ CAPTURE_CMAKE_ERROR
+ \ CDASH_UPLOAD
+ \ CDASH_UPLOAD_TYPE
+ \ CTEST_EXTRA_SUBMIT_FILES
+ \ CTEST_NOTES_FILES
+ \ FILES
+ \ HTTPHEADER
+ \ PARTS
+ \ QUIET
+ \ RETRY_COUNT
+ \ RETRY_DELAY
+ \ RETURN_VALUE
+ \ SUBMIT_URL
syn keyword cmakeKWctest_test contained
- \ APPEND BUILD CAPTURE_CMAKE_ERROR CPU EXCLUDE EXCLUDE_FIXTURE EXCLUDE_FIXTURE_CLEANUP EXCLUDE_FIXTURE_SETUP EXCLUDE_LABEL INCLUDE INCLUDE_LABEL OFF ON PARALLEL_LEVEL QUIET RETURN_VALUE SCHEDULE_RANDOM START STOP_TIME STRIDE TEST_LOAD
+ \ AFTER_TIMEOUT
+ \ APPEND
+ \ ATTACHED_FILES
+ \ ATTACHED_FILES_ON_FAIL
+ \ BUILD
+ \ CAPTURE_CMAKE_ERROR
+ \ CPU
+ \ EXCLUDE
+ \ EXCLUDE_FIXTURE
+ \ EXCLUDE_FIXTURE_CLEANUP
+ \ EXCLUDE_FIXTURE_SETUP
+ \ EXCLUDE_LABEL
+ \ INCLUDE
+ \ INCLUDE_LABEL
+ \ LABELS
+ \ OFF
+ \ ON
+ \ OUTPUT_JUNIT
+ \ PARALLEL_LEVEL
+ \ QUIET
+ \ REPEAT
+ \ RESOURCE_SPEC_FILE
+ \ RETURN_VALUE
+ \ SCHEDULE_RANDOM
+ \ START
+ \ STOP_ON_FAILURE
+ \ STOP_TIME
+ \ STRIDE
+ \ TEST_LOAD
+ \ UNTIL_FAIL
+ \ UNTIL_PASS
+ \ URL
+ \ XML
syn keyword cmakeKWctest_update contained
- \ QUIET RETURN_VALUE SOURCE
+ \ CAPTURE_CMAKE_ERROR
+ \ QUIET
+ \ RETURN_VALUE
+ \ SOURCE
syn keyword cmakeKWctest_upload contained
- \ CAPTURE_CMAKE_ERROR FILES QUIET
+ \ CAPTURE_CMAKE_ERROR
+ \ FILES
+ \ QUIET
syn keyword cmakeKWdefine_property contained
- \ BRIEF_DOCS CACHED_VARIABLE DIRECTORY FULL_DOCS GLOBAL INHERITED PROPERTY SOURCE TARGET TEST VARIABLE
+ \ APPEND
+ \ APPEND_STRING
+ \ BRIEF_DOCS
+ \ CACHED_VARIABLE
+ \ CMAKE_
+ \ DIRECTORY
+ \ FULL_DOCS
+ \ GLOBAL
+ \ INHERITED
+ \ INITIALIZE_FROM_VARIABLE
+ \ PROPERTY
+ \ SOURCE
+ \ TARGET
+ \ TEST
+ \ VARIABLE
+ \ _CMAKE_
+
+syn keyword cmakeKWdoxygen_add_docs contained
+ \ ALL
+ \ COMMENT
+ \ USE_STAMP_FILE
+ \ WORKING_DIRECTORY
syn keyword cmakeKWenable_language contained
+ \ ASM
+ \ ASM_MARMASM
+ \ ASM_MASM
+ \ ASM_NASM
+ \ ATT
+ \ CUDA
+ \ HIP
+ \ ISPC
+ \ OBJC
+ \ OBJCXX
\ OPTIONAL
+syn keyword cmakeKWenable_testing contained
+ \ BUILD_TESTING
+
syn keyword cmakeKWexec_program contained
- \ ARGS OUTPUT_VARIABLE RETURN_VALUE
+ \ ARGS
+ \ OUTPUT_VARIABLE
+ \ RETURN_VALUE
syn keyword cmakeKWexecute_process contained
- \ ANSI AUTO COMMAND ENCODING ERROR_FILE ERROR_QUIET ERROR_STRIP_TRAILING_WHITESPACE ERROR_VARIABLE INPUT_FILE NONE OEM OUTPUT_FILE OUTPUT_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE OUTPUT_VARIABLE RESULTS_VARIABLE RESULT_VARIABLE TIMEOUT UTF VERBATIM WORKING_DIRECTORY
+ \ ANSI
+ \ ANY
+ \ AUTO
+ \ COMMAND
+ \ COMMAND_ECHO
+ \ COMMAND_ERROR_IS_FATAL
+ \ ECHO_ERROR_VARIABLE
+ \ ECHO_OUTPUT_VARIABLE
+ \ ENCODING
+ \ ERROR_FILE
+ \ ERROR_QUIET
+ \ ERROR_STRIP_TRAILING_WHITESPACE
+ \ ERROR_VARIABLE
+ \ INPUT_FILE
+ \ LAST
+ \ NONE
+ \ OEM
+ \ OUTPUT_FILE
+ \ OUTPUT_QUIET
+ \ OUTPUT_STRIP_TRAILING_WHITESPACE
+ \ OUTPUT_VARIABLE
+ \ POSIX
+ \ RESULTS_VARIABLE
+ \ RESULT_VARIABLE
+ \ RFC
+ \ STDERR
+ \ STDOUT
+ \ TIMEOUT
+ \ UTF
+ \ WORKING_DIRECTORY
syn keyword cmakeKWexport contained
- \ ANDROID_MK APPEND CONFIG EXPORT EXPORT_LINK_INTERFACE_LIBRARIES FILE IMPORTED IMPORTED_ NAMESPACE NDK OLD PACKAGE TARGETS
+ \ ANDROID_MK
+ \ APPEND
+ \ CONFIG
+ \ CXX_MODULES_DIRECTORY
+ \ EXPORT
+ \ EXPORT_LINK_INTERFACE_LIBRARIES
+ \ FILE
+ \ IMPORTED_
+ \ NAMESPACE
+ \ NDK
+ \ OLD
+ \ PACKAGE
+ \ TARGETS
syn keyword cmakeKWexport_library_dependencies contained
- \ APPEND EXPORT INCLUDE LINK_INTERFACE_LIBRARIES SET
+ \ APPEND
+ \ EXPORT
+ \ INCLUDE
+ \ LINK_INTERFACE_LIBRARIES
+ \ SET
syn keyword cmakeKWfile contained
- \ ALGO APPEND ASCII CMAKE_TLS_CAINFO CMAKE_TLS_VERIFY CONDITION CONFIG CONTENT COPY CR DESTINATION DIRECTORY_PERMISSIONS DOWNLOAD ENCODING EXCLUDE EXPECTED_HASH FILES_MATCHING FILE_PERMISSIONS FOLLOW_SYMLINKS FUNCTION GENERATE GLOB GLOB_RECURSE GUARD HASH HEX HTTPHEADER INACTIVITY_TIMEOUT INSTALL LENGTH_MAXIMUM LENGTH_MINIMUM LF LIMIT LIMIT_COUNT LIMIT_INPUT LIMIT_OUTPUT LIST_DIRECTORIES LOCK LOG MAKE_DIRECTORY NEWLINE_CONSUME NO_HEX_CONVERSION NO_SOURCE_PERMISSIONS OFFSET OLD PATTERN PROCESS READ REGEX RELATIVE RELATIVE_PATH RELEASE REMOVE REMOVE_RECURSE RENAME RESULT_VARIABLE SHOW_PROGRESS SSL STATUS STRINGS TIMESTAMP TLS_CAINFO TLS_VERIFY TO_CMAKE_PATH TO_NATIVE_PATH UPLOAD USERPWD USE_SOURCE_PERMISSIONS UTC UTF WRITE
+ \ APPEND
+ \ ARCHIVE_CREATE
+ \ ARCHIVE_EXTRACT
+ \ ASCII
+ \ BASE_DIRECTORY
+ \ BUNDLE_EXECUTABLE
+ \ CHMOD
+ \ CHMOD_RECURSE
+ \ CMAKE_GET_RUNTIME_DEPENDENCIES_COMMAND
+ \ CMAKE_GET_RUNTIME_DEPENDENCIES_PLATFORM
+ \ CMAKE_GET_RUNTIME_DEPENDENCIES_TOOL
+ \ CMAKE_INSTALL_MODE
+ \ CMAKE_OBJDUMP
+ \ CODE
+ \ COMPILE_FEATURES
+ \ COMPRESSION
+ \ COMPRESSION_LEVEL
+ \ CONDITION
+ \ CONFIGURE
+ \ CONFIGURE_DEPENDS
+ \ CONFLICTING_DEPENDENCIES_PREFIX
+ \ CONTENT
+ \ CONVERT
+ \ COPYONLY
+ \ COPY_FILE
+ \ COPY_ON_ERROR
+ \ CREATE_LINK
+ \ CRLF
+ \ DESTINATION
+ \ DIRECTORIES
+ \ DIRECTORY_PERMISSIONS
+ \ DLL
+ \ DOS
+ \ DOWNLOAD
+ \ ENCODING
+ \ ESCAPE_QUOTES
+ \ EXECUTABLES
+ \ EXPAND_TILDE
+ \ EXPECTED_HASH
+ \ FILES_MATCHING
+ \ FILE_PERMISSIONS
+ \ FOLLOW_SYMLINKS
+ \ FOLLOW_SYMLINK_CHAIN
+ \ FORMAT
+ \ FUNCTION
+ \ GENERATE
+ \ GET_RUNTIME_DEPENDENCIES
+ \ GLOB
+ \ GLOB_RECURSE
+ \ GROUP_EXECUTE
+ \ GROUP_READ
+ \ GROUP_WRITE
+ \ GUARD
+ \ HASH
+ \ HEX
+ \ HOME
+ \ HTTPHEADER
+ \ IGNORED
+ \ INACTIVITY_TIMEOUT
+ \ INPUT
+ \ INPUT_MAY_BE_RECENT
+ \ INSTALL
+ \ IS_ABSOLUTE
+ \ LENGTH_MAXIMUM
+ \ LENGTH_MINIMUM
+ \ LF
+ \ LIBRARIES
+ \ LIMIT
+ \ LIMIT_COUNT
+ \ LIMIT_INPUT
+ \ LIMIT_OUTPUT
+ \ LIST_DIRECTORIES
+ \ LIST_ONLY
+ \ LOCK
+ \ LOG
+ \ MAKE_DIRECTORY
+ \ MODULES
+ \ MTIME
+ \ MYLIBRARY
+ \ NETRC
+ \ NETRC_FILE
+ \ NEWLINE_CONSUME
+ \ NEWLINE_STYLE
+ \ NOT
+ \ NO_HEX_CONVERSION
+ \ NO_REPLACE
+ \ NO_SOURCE_PERMISSIONS
+ \ OFFSET
+ \ ONLY
+ \ ONLY_IF_DIFFERENT
+ \ OPTIONAL
+ \ OUTPUT
+ \ OWNER_EXECUTE
+ \ OWNER_READ
+ \ OWNER_WRITE
+ \ PATHS
+ \ PATTERN
+ \ PATTERNS
+ \ PERMISSIONS
+ \ POST_EXCLUDE_FILES
+ \ POST_EXCLUDE_REGEXES
+ \ POST_INCLUDE_FILES
+ \ POST_INCLUDE_REGEXES
+ \ PRE_EXCLUDE_REGEXES
+ \ PRE_INCLUDE_REGEXES
+ \ PROCESS
+ \ RANGE_END
+ \ RANGE_START
+ \ READ
+ \ READ_SYMLINK
+ \ REAL_PATH
+ \ REGEX
+ \ RELATIVE
+ \ RELATIVE_PATH
+ \ RELEASE
+ \ REMOVE
+ \ REMOVE_RECURSE
+ \ RENAME
+ \ REQUIRED
+ \ RESOLVED_DEPENDENCIES_VAR
+ \ RESULT
+ \ RESULT_VARIABLE
+ \ RPATH
+ \ RUNPATH
+ \ RUNTIME_DEPENDENCY_SET
+ \ SCRIPT
+ \ SETGID
+ \ SETUID
+ \ SHARED
+ \ SHOW_PROGRESS
+ \ SIZE
+ \ SSL
+ \ STATIC
+ \ STATUS
+ \ STRINGS
+ \ SYMBOLIC
+ \ TARGET
+ \ TARGET_PROPERTY
+ \ TIMESTAMP
+ \ TLS_CAINFO
+ \ TLS_VERIFY
+ \ TOUCH
+ \ TOUCH_NOCREATE
+ \ TO_CMAKE_PATH
+ \ TO_CMAKE_PATH_LIST
+ \ TO_NATIVE_PATH
+ \ TO_NATIVE_PATH_LIST
+ \ UNRESOLVED_DEPENDENCIES_VAR
+ \ UPLOAD
+ \ URL
+ \ USERPROFILE
+ \ USERPWD
+ \ USE_SOURCE_PERMISSIONS
+ \ UTC
+ \ UTF
+ \ VERBOSE
+ \ WORLD_EXECUTE
+ \ WORLD_READ
+ \ WORLD_WRITE
+ \ WRITE
+ \ XZ
+ \ _FILENAMES
syn keyword cmakeKWfind_file contained
- \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS INCLUDE NAMES NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR
+ \ BOTH
+ \ CATEGORY
+ \ CMAKE_FIND_ROOT_PATH_BOTH
+ \ CMAKE_FIND_USE_
+ \ DOC
+ \ DVAR
+ \ FALSE
+ \ FIND_XXX_REGISTRY_VIEW
+ \ HINTS
+ \ HOST
+ \ INCLUDE
+ \ MATCHES
+ \ NAMES
+ \ NOT
+ \ NO_CACHE
+ \ NO_CMAKE_ENVIRONMENT_PATH
+ \ NO_CMAKE_FIND_ROOT_PATH
+ \ NO_CMAKE_INSTALL_PREFIX
+ \ NO_CMAKE_PATH
+ \ NO_CMAKE_SYSTEM_PATH
+ \ NO_DEFAULT_PATH
+ \ NO_PACKAGE_ROOT_PATH
+ \ NO_SYSTEM_ENVIRONMENT_PATH
+ \ ONLY_CMAKE_FIND_ROOT_PATH
+ \ PACKAGENAME
+ \ PARENT_SCOPE
+ \ PATHS
+ \ PATH_SUFFIXES
+ \ REGISTRY_VIEW
+ \ REQUIRED
+ \ TARGET
+ \ VALIDATOR
+ \ VAR
syn keyword cmakeKWfind_library contained
- \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS LIB NAMES NAMES_PER_DIR NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR
+ \ BOTH
+ \ CATEGORY
+ \ CMAKE_FIND_ROOT_PATH_BOTH
+ \ CMAKE_FIND_USE_
+ \ DOC
+ \ DVAR
+ \ FALSE
+ \ FIND_XXX_REGISTRY_VIEW
+ \ HINTS
+ \ HOST
+ \ LIB
+ \ MATCHES
+ \ NAMES
+ \ NAMES_PER_DIR
+ \ NOT
+ \ NO_CACHE
+ \ NO_CMAKE_ENVIRONMENT_PATH
+ \ NO_CMAKE_FIND_ROOT_PATH
+ \ NO_CMAKE_INSTALL_PREFIX
+ \ NO_CMAKE_PATH
+ \ NO_CMAKE_SYSTEM_PATH
+ \ NO_DEFAULT_PATH
+ \ NO_PACKAGE_ROOT_PATH
+ \ NO_SYSTEM_ENVIRONMENT_PATH
+ \ ONLY_CMAKE_FIND_ROOT_PATH
+ \ PACKAGENAME
+ \ PARENT_SCOPE
+ \ PATHS
+ \ PATH_SUFFIXES
+ \ REGISTRY_VIEW
+ \ REQUIRED
+ \ TARGET
+ \ VALIDATOR
+ \ VAR
syn keyword cmakeKWfind_package contained
- \ CMAKE_DISABLE_FIND_PACKAGE_ CMAKE_FIND_ROOT_PATH_BOTH COMPONENTS CONFIG CONFIGS DEC DVAR EXACT HINTS MODULE NAMES NATURAL NO_CMAKE_BUILDS_PATH NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PACKAGE_REGISTRY NO_CMAKE_PATH NO_CMAKE_SYSTEM_PACKAGE_REGISTRY NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_MODULE NO_POLICY_SCOPE NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OPTIONAL_COMPONENTS OS PACKAGE_FIND_NAME PACKAGE_FIND_VERSION PACKAGE_FIND_VERSION_COUNT PACKAGE_FIND_VERSION_MAJOR PACKAGE_FIND_VERSION_MINOR PACKAGE_FIND_VERSION_PATCH PACKAGE_FIND_VERSION_TWEAK PACKAGE_VERSION PACKAGE_VERSION_COMPATIBLE PACKAGE_VERSION_EXACT PACKAGE_VERSION_UNSUITABLE PATHS PATH_SUFFIXES QUIET REQUIRED SET TRUE _CONFIG _CONSIDERED_CONFIGS _CONSIDERED_VERSIONS _DIR _FIND_COMPONENTS _FIND_QUIETLY _FIND_REQUIRED _FIND_REQUIRED_ _FIND_VERSION_EXACT _FOUND
+ \ ABI
+ \ BOTH
+ \ BUNDLE
+ \ BYPASS_PROVIDER
+ \ CATEGORY
+ \ CMAKE_DISABLE_FIND_PACKAGE_
+ \ CMAKE_REQUIRE_FIND_PACKAGE_
+ \ CMAKE_FIND_ROOT_PATH_BOTH
+ \ CMAKE_FIND_USE_
+ \ CMAKE_REQUIRE_FIND_PACKAGE_
+ \ COMPONENTS
+ \ CONFIG
+ \ CONFIGS
+ \ DEC
+ \ DVAR
+ \ EXACT
+ \ EXCLUDE
+ \ FALSE
+ \ FIND_PACKAGE_VERSION_FORMAT
+ \ FRAMEWORK
+ \ GLOBAL
+ \ HINTS
+ \ HOST
+ \ INCLUDE
+ \ MODULE
+ \ NAMES
+ \ NATURAL
+ \ NO_CMAKE_BUILDS_PATH
+ \ NO_CMAKE_ENVIRONMENT_PATH
+ \ NO_CMAKE_FIND_ROOT_PATH
+ \ NO_CMAKE_INSTALL_PREFIX
+ \ NO_CMAKE_PACKAGE_REGISTRY
+ \ NO_CMAKE_PATH
+ \ NO_CMAKE_SYSTEM_PACKAGE_REGISTRY
+ \ NO_CMAKE_SYSTEM_PATH
+ \ NO_DEFAULT_PATH
+ \ NO_MODULE
+ \ NO_PACKAGE_ROOT_PATH
+ \ NO_POLICY_SCOPE
+ \ NO_SYSTEM_ENVIRONMENT_PATH
+ \ OLD
+ \ ONLY_CMAKE_FIND_ROOT_PATH
+ \ OPTIONAL_COMPONENTS
+ \ PACKAGENAME
+ \ PACKAGE_FIND_NAME
+ \ PACKAGE_FIND_VERSION
+ \ PACKAGE_FIND_VERSION_COMPLETE
+ \ PACKAGE_FIND_VERSION_COUNT
+ \ PACKAGE_FIND_VERSION_MAJOR
+ \ PACKAGE_FIND_VERSION_MAX
+ \ PACKAGE_FIND_VERSION_MAX_COUNT
+ \ PACKAGE_FIND_VERSION_MAX_MAJOR
+ \ PACKAGE_FIND_VERSION_MAX_MINOR
+ \ PACKAGE_FIND_VERSION_MAX_PATCH
+ \ PACKAGE_FIND_VERSION_MAX_TWEAK
+ \ PACKAGE_FIND_VERSION_MINOR
+ \ PACKAGE_FIND_VERSION_MIN_COUNT
+ \ PACKAGE_FIND_VERSION_MIN_MAJOR
+ \ PACKAGE_FIND_VERSION_MIN_MINOR
+ \ PACKAGE_FIND_VERSION_MIN_PATCH
+ \ PACKAGE_FIND_VERSION_MIN_TWEAK
+ \ PACKAGE_FIND_VERSION_PATCH
+ \ PACKAGE_FIND_VERSION_RANGE
+ \ PACKAGE_FIND_VERSION_RANGE_MAX
+ \ PACKAGE_FIND_VERSION_RANGE_MIN
+ \ PACKAGE_FIND_VERSION_TWEAK
+ \ PACKAGE_VERSION_COMPATIBLE
+ \ PACKAGE_VERSION_EXACT
+ \ PACKAGE_VERSION_UNSUITABLE
+ \ PATHS
+ \ PATH_SUFFIXES
+ \ QUIET
+ \ REGISTRY_VIEW
+ \ REQUIRED
+ \ SET
+ \ TARGET
+ \ TRUE
+ \ VALUE
+ \ _CONFIG
+ \ _CONSIDERED_CONFIGS
+ \ _CONSIDERED_VERSIONS
+ \ _DIR
+ \ _FIND_COMPONENTS
+ \ _FIND_QUIETLY
+ \ _FIND_REGISTRY_VIEW
+ \ _FIND_REQUIRED
+ \ _FIND_REQUIRED_
+ \ _FIND_VERSION_EXACT
+ \ _FOUND
syn keyword cmakeKWfind_path contained
- \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS INCLUDE NAMES NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR
+ \ BOTH
+ \ CATEGORY
+ \ CMAKE_FIND_ROOT_PATH_BOTH
+ \ CMAKE_FIND_USE_
+ \ DOC
+ \ DVAR
+ \ FALSE
+ \ FIND_XXX_REGISTRY_VIEW
+ \ HINTS
+ \ HOST
+ \ INCLUDE
+ \ MATCHES
+ \ NAMES
+ \ NOT
+ \ NO_CACHE
+ \ NO_CMAKE_ENVIRONMENT_PATH
+ \ NO_CMAKE_FIND_ROOT_PATH
+ \ NO_CMAKE_INSTALL_PREFIX
+ \ NO_CMAKE_PATH
+ \ NO_CMAKE_SYSTEM_PATH
+ \ NO_DEFAULT_PATH
+ \ NO_PACKAGE_ROOT_PATH
+ \ NO_SYSTEM_ENVIRONMENT_PATH
+ \ ONLY_CMAKE_FIND_ROOT_PATH
+ \ PACKAGENAME
+ \ PARENT_SCOPE
+ \ PATHS
+ \ PATH_SUFFIXES
+ \ REGISTRY_VIEW
+ \ REQUIRED
+ \ TARGET
+ \ VALIDATOR
+ \ VAR
syn keyword cmakeKWfind_program contained
- \ CMAKE_FIND_ROOT_PATH_BOTH DOC DVAR HINTS NAMES NAMES_PER_DIR NO_CMAKE_ENVIRONMENT_PATH NO_CMAKE_FIND_ROOT_PATH NO_CMAKE_PATH NO_CMAKE_SYSTEM_PATH NO_DEFAULT_PATH NO_SYSTEM_ENVIRONMENT_PATH ONLY_CMAKE_FIND_ROOT_PATH OS PATHS PATH_SUFFIXES VAR
+ \ BOTH
+ \ CATEGORY
+ \ CMAKE_FIND_ROOT_PATH_BOTH
+ \ CMAKE_FIND_USE_
+ \ DOC
+ \ DVAR
+ \ FALSE
+ \ FIND_XXX_REGISTRY_VIEW
+ \ HINTS
+ \ HOST
+ \ MATCHES
+ \ NAMES
+ \ NAMES_PER_DIR
+ \ NOT
+ \ NO_CACHE
+ \ NO_CMAKE_ENVIRONMENT_PATH
+ \ NO_CMAKE_FIND_ROOT_PATH
+ \ NO_CMAKE_INSTALL_PREFIX
+ \ NO_CMAKE_PATH
+ \ NO_CMAKE_SYSTEM_PATH
+ \ NO_DEFAULT_PATH
+ \ NO_PACKAGE_ROOT_PATH
+ \ NO_SYSTEM_ENVIRONMENT_PATH
+ \ ONLY_CMAKE_FIND_ROOT_PATH
+ \ PACKAGENAME
+ \ PARENT_SCOPE
+ \ PATHS
+ \ PATH_SUFFIXES
+ \ REGISTRY_VIEW
+ \ REQUIRED
+ \ TARGET
+ \ VALIDATOR
+ \ VAR
syn keyword cmakeKWfltk_wrap_ui contained
\ FLTK
syn keyword cmakeKWforeach contained
- \ ARGS IN ITEMS LISTS RANGE
+ \ APPEND
+ \ IN
+ \ ITEMS
+ \ LISTS
+ \ RANGE
+ \ STATUS
+ \ ZIP_LISTS
syn keyword cmakeKWfunction contained
- \ ARGC ARGN ARGS ARGV PARENT_SCOPE
+ \ ARGC
+ \ ARGN
+ \ ARGV
+ \ CALL
+ \ FOO
+ \ PARENT_SCOPE
syn keyword cmakeKWget_cmake_property contained
- \ COMPONENTS GLOBAL MACROS VAR VARIABLES
+ \ COMPONENTS
+ \ GLOBAL
+ \ MACROS
+ \ VARIABLES
syn keyword cmakeKWget_directory_property contained
- \ DEFINITION DIRECTORY
+ \ DEFINITION
+ \ DIRECTORY
+ \ INHERITED
syn keyword cmakeKWget_filename_component contained
- \ ABSOLUTE ARG_VAR BASE_DIR CACHE COMP DIRECTORY EXT NAME NAME_WE PATH PROGRAM PROGRAM_ARGS REALPATH VAR
+ \ ABSOLUTE
+ \ BASE_DIR
+ \ DIRECTORY
+ \ EXT
+ \ LAST_EXT
+ \ NAME
+ \ NAME_WE
+ \ NAME_WLE
+ \ PROGRAM
+ \ PROGRAM_ARGS
+ \ QUERY
+ \ REALPATH
+ \ REAL_PATH
+ \ WINDOWS_REGISTRY
syn keyword cmakeKWget_property contained
- \ BRIEF_DOCS CACHE DEFINED DIRECTORY FULL_DOCS GLOBAL INSTALL PROPERTY SET SOURCE TARGET TEST VARIABLE
+ \ BRIEF_DOCS
+ \ DEFINED
+ \ DIRECTORY
+ \ FULL_DOCS
+ \ GENERATED
+ \ GLOBAL
+ \ INSTALL
+ \ PROPERTY
+ \ SET
+ \ SOURCE
+ \ TARGET
+ \ TARGET_DIRECTORY
+ \ TEST
+ \ VARIABLE
syn keyword cmakeKWget_source_file_property contained
- \ LOCATION VAR
+ \ DIRECTORY
+ \ GENERATED
+ \ INHERITED
+ \ LOCATION
+ \ TARGET_DIRECTORY
syn keyword cmakeKWget_target_property contained
+ \ INHERITED
\ VAR
syn keyword cmakeKWget_test_property contained
+ \ INHERITED
\ VAR
syn keyword cmakeKWif contained
- \ ARGS CMAKE_MATCH_ CMP COMMAND DEFINED EQUAL EXISTS FALSE GREATER GREATER_EQUAL IGNORE IN_LIST IS_ABSOLUTE IS_DIRECTORY IS_NEWER_THAN IS_SYMLINK LESS LESS_EQUAL MATCHES NNNN NOT OFF OR POLICY STREQUAL STRGREATER STRGREATER_EQUAL STRLESS STRLESS_EQUAL TARGET TEST THEN TRUE VERSION_EQUAL VERSION_GREATER VERSION_GREATER_EQUAL VERSION_LESS VERSION_LESS_EQUAL YES
+ \ CMAKE_MATCH_
+ \ CMP
+ \ COMMAND
+ \ COMPARE
+ \ DEFINED
+ \ EQUAL
+ \ EXISTS
+ \ FALSE
+ \ GREATER
+ \ GREATER_EQUAL
+ \ IGNORE
+ \ IN_LIST
+ \ IS_ABSOLUTE
+ \ IS_DIRECTORY
+ \ IS_NEWER_THAN
+ \ IS_SYMLINK
+ \ LESS
+ \ LESS_EQUAL
+ \ MATCHES
+ \ NNNN
+ \ NOT
+ \ OFF
+ \ OR
+ \ PATH_EQUAL
+ \ POLICY
+ \ STREQUAL
+ \ STRGREATER
+ \ STRGREATER_EQUAL
+ \ STRLESS
+ \ STRLESS_EQUAL
+ \ TARGET
+ \ TEST
+ \ TRUE
+ \ VERSION_EQUAL
+ \ VERSION_GREATER
+ \ VERSION_GREATER_EQUAL
+ \ VERSION_LESS
+ \ VERSION_LESS_EQUAL
+ \ YES
syn keyword cmakeKWinclude contained
- \ NO_POLICY_SCOPE OPTIONAL RESULT_VARIABLE
+ \ NO_POLICY_SCOPE
+ \ OPTIONAL
+ \ RESULT_VARIABLE
syn keyword cmakeKWinclude_directories contained
- \ AFTER BEFORE INCLUDE_DIRECTORIES ON SYSTEM
+ \ AFTER
+ \ BEFORE
+ \ INCLUDE_DIRECTORIES
+ \ ON
+ \ SYSTEM
syn keyword cmakeKWinclude_external_msproject contained
- \ GUID MAP_IMPORTED_CONFIG_ PLATFORM TYPE WIX
+ \ GUID
+ \ MAP_IMPORTED_CONFIG_
+ \ PLATFORM
+ \ TYPE
+ \ WIX
syn keyword cmakeKWinclude_guard contained
- \ DIRECTORY GLOBAL TRUE __CURRENT_FILE_VAR__
+ \ DIRECTORY
+ \ GLOBAL
+ \ TRUE
+ \ __CURRENT_FILE_VAR__
syn keyword cmakeKWinstall contained
- \ ARCHIVE BUNDLE CODE COMPONENT CONFIGURATIONS CVS DESTDIR DESTINATION DIRECTORY DIRECTORY_PERMISSIONS DLL EXCLUDE_FROM_ALL EXPORT EXPORT_ANDROID_MK EXPORT_LINK_INTERFACE_LIBRARIES FILES FILES_MATCHING FILE_PERMISSIONS FRAMEWORK GROUP_EXECUTE GROUP_READ GROUP_WRITE IMPORTED_ INCLUDES INSTALL_PREFIX INTERFACE_INCLUDE_DIRECTORIES LIBRARY MACOSX_BUNDLE MESSAGE_NEVER NAMELINK_ONLY NAMELINK_SKIP NAMESPACE NDK OBJECTS OPTIONAL OWNER_EXECUTE OWNER_READ OWNER_WRITE PATTERN PERMISSIONS POST_INSTALL_SCRIPT PRE_INSTALL_SCRIPT PRIVATE_HEADER PROGRAMS PUBLIC_HEADER REGEX RENAME RESOURCE RUNTIME SCRIPT SETGID SETUID SOVERSION TARGETS TRUE USE_SOURCE_PERMISSIONS VERSION WORLD_EXECUTE WORLD_READ WORLD_WRITE
+ \ AFTER
+ \ AIX
+ \ ALL_COMPONENTS
+ \ APT
+ \ ARCHIVE
+ \ BEFORE
+ \ BUILD_TYPE
+ \ BUNDLE
+ \ BUNDLE_EXECUTABLE
+ \ CMAKE_INSTALL_BINDIR
+ \ CMAKE_INSTALL_DATADIR
+ \ CMAKE_INSTALL_DATAROOTDIR
+ \ CMAKE_INSTALL_DOCDIR
+ \ CMAKE_INSTALL_INCLUDEDIR
+ \ CMAKE_INSTALL_INFODIR
+ \ CMAKE_INSTALL_LIBDIR
+ \ CMAKE_INSTALL_LOCALEDIR
+ \ CMAKE_INSTALL_LOCALSTATEDIR
+ \ CMAKE_INSTALL_MANDIR
+ \ CMAKE_INSTALL_MODE
+ \ CMAKE_INSTALL_RUNSTATEDIR
+ \ CMAKE_INSTALL_SBINDIR
+ \ CMAKE_INSTALL_SHARESTATEDIR
+ \ CMAKE_INSTALL_SYSCONFDIR
+ \ CODE
+ \ COMPONENT
+ \ CONFIGURATIONS
+ \ CVS
+ \ CXX_MODULES_BMI
+ \ CXX_MODULES_DIRECTORY
+ \ DATA
+ \ DATAROOT
+ \ DBUILD_TYPE
+ \ DCOMPONENT
+ \ DESTDIR
+ \ DESTINATION
+ \ DIRECTORY
+ \ DIRECTORY_PERMISSIONS
+ \ DLL
+ \ DOC
+ \ ENABLE_EXPORTS
+ \ EXCLUDE_FROM_ALL
+ \ EXECUTABLES
+ \ EXPORT
+ \ EXPORT_ANDROID_MK
+ \ EXPORT_LINK_INTERFACE_LIBRARIES
+ \ EXPORT_NAME
+ \ FILES
+ \ FILES_MATCHING
+ \ FILE_PERMISSIONS
+ \ FILE_SET
+ \ FRAMEWORK
+ \ GET_RUNTIME_DEPENDENCIES
+ \ GROUP_EXECUTE
+ \ GROUP_READ
+ \ GROUP_WRITE
+ \ HEADERS
+ \ IMPORTED_RUNTIME_ARTIFACTS
+ \ INCLUDES
+ \ INFO
+ \ INSTALL_PREFIX
+ \ INTERFACE
+ \ INTERFACE_INCLUDE_DIRECTORIES
+ \ LIBRARY
+ \ LOCALE
+ \ LOCALSTATE
+ \ MACOSX_BUNDLE
+ \ MAN
+ \ MESSAGE_NEVER
+ \ NAMELINK_COMPONENT
+ \ NAMELINK_ONLY
+ \ NAMELINK_SKIP
+ \ NAMESPACE
+ \ NDK
+ \ OBJECTS
+ \ OPTIONAL
+ \ OWNER_EXECUTE
+ \ OWNER_READ
+ \ OWNER_WRITE
+ \ PATTERN
+ \ PERMISSIONS
+ \ POST_EXCLUDE_FILES
+ \ POST_EXCLUDE_REGEXES
+ \ POST_INCLUDE_FILES
+ \ POST_INCLUDE_REGEXES
+ \ POST_INSTALL_SCRIPT
+ \ PRE_EXCLUDE_REGEXES
+ \ PRE_INCLUDE_REGEXES
+ \ PRE_INSTALL_SCRIPT
+ \ PRIVATE_HEADER
+ \ PROGRAMS
+ \ PROPERTIES
+ \ PUBLIC_HEADER
+ \ RENAME
+ \ RESOURCE
+ \ RPM
+ \ RUNSTATE
+ \ RUNTIME_DEPENDENCIES
+ \ RUNTIME_DEPENDENCY_SET
+ \ SBIN
+ \ SCRIPT
+ \ SETGID
+ \ SETUID
+ \ SHAREDSTATE
+ \ SOVERSION
+ \ STATIC
+ \ SYSCONF
+ \ TARGETS
+ \ TRUE
+ \ TYPE
+ \ USE_SOURCE_PERMISSIONS
+ \ VERSION
+ \ WORLD_EXECUTE
+ \ WORLD_READ
+ \ WORLD_WRITE
syn keyword cmakeKWinstall_files contained
- \ FILES GLOB
+ \ FILES
+ \ GLOB
syn keyword cmakeKWinstall_programs contained
- \ FILES GLOB PROGRAMS TARGETS
+ \ FILES
+ \ GLOB
+ \ PROGRAMS
+ \ TARGETS
syn keyword cmakeKWinstall_targets contained
- \ DLL RUNTIME_DIRECTORY TARGETS
+ \ DLL
+ \ RUNTIME_DIRECTORY
+
+syn keyword cmakeKWlink_directories contained
+ \ AFTER
+ \ BEFORE
+ \ LINK_DIRECTORIES
+ \ ON
+ \ ORIGIN
+ \ RPATH
syn keyword cmakeKWlist contained
- \ APPEND CACHE EXCLUDE FILTER FIND GET INCLUDE INSERT INTERNAL LENGTH LIST NOTES PARENT_SCOPE REGEX REMOVE_AT REMOVE_DUPLICATES REMOVE_ITEM REVERSE SORT
+ \ ACTION
+ \ APPEND
+ \ ASCENDING
+ \ CASE
+ \ COMPARE
+ \ DESCENDING
+ \ EXCLUDE
+ \ FILE_BASENAME
+ \ FILTER
+ \ FIND
+ \ GENEX_STRIP
+ \ GET
+ \ INCLUDE
+ \ INSENSITIVE
+ \ INSERT
+ \ INTERNAL
+ \ JOIN
+ \ LENGTH
+ \ NATURAL
+ \ ORDER
+ \ OUTPUT_VARIABLE
+ \ PARENT_SCOPE
+ \ POP_BACK
+ \ POP_FRONT
+ \ PREPEND
+ \ REGEX
+ \ REMOVE_AT
+ \ REMOVE_DUPLICATES
+ \ REMOVE_ITEM
+ \ REPLACE
+ \ REVERSE
+ \ SELECTOR
+ \ SENSITIVE
+ \ SORT
+ \ STRING
+ \ STRIP
+ \ SUBLIST
+ \ TOLOWER
+ \ TOUPPER
+ \ TRANSFORM
+ \ TRANSFORM_APPEND
+ \ TRANSFORM_GENEX_STRIP
+ \ TRANSFORM_REPLACE
+ \ TRANSFORM_STRIP
+ \ TRANSFORM_TOLOWER
syn keyword cmakeKWload_cache contained
- \ EXCLUDE INCLUDE_INTERNALS READ_WITH_PREFIX
+ \ EXCLUDE
+ \ INCLUDE_INTERNALS
+ \ READ_WITH_PREFIX
syn keyword cmakeKWload_command contained
- \ CMAKE_LOADED_COMMAND_ COMMAND_NAME
+ \ CMAKE_LOADED_COMMAND_
+ \ COMMAND_NAME
syn keyword cmakeKWmacro contained
- \ ARGC ARGN ARGS ARGV DEFINED GREATER LISTS NOT _BAR _FOO
-
-syn keyword cmakeKWmake_directory contained
- \ MAKE_DIRECTORY
+ \ ARGC
+ \ ARGN
+ \ ARGV
+ \ CALL
+ \ DEFINED
+ \ FOO
+ \ GREATER
+ \ LISTS
+ \ NOT
syn keyword cmakeKWmark_as_advanced contained
- \ CLEAR FORCE VAR
+ \ CLEAR
+ \ FORCE
syn keyword cmakeKWmath contained
\ EXPR
+ \ HEXADECIMAL
+ \ OUTPUT_FORMAT
syn keyword cmakeKWmessage contained
- \ AUTHOR_WARNING DEPRECATION FATAL_ERROR GUI SEND_ERROR STATUS WARNING
+ \ APPEND
+ \ AUTHOR_WARNING
+ \ CHECK_
+ \ CHECK_FAIL
+ \ CHECK_PASS
+ \ CHECK_START
+ \ CONFIGURE_LOG
+ \ DEBUG
+ \ DEFINED
+ \ DEPRECATION
+ \ FATAL_ERROR
+ \ GET_MESSAGE_LOG_LEVEL
+ \ GUI
+ \ INTERNAL
+ \ MY_CHECK_RESULT
+ \ NOTICE
+ \ POP_BACK
+ \ SEND_ERROR
+ \ STATUS
+ \ TRACE
+ \ VERBOSE
+ \ WARNING
syn keyword cmakeKWoption contained
- \ OFF ON
+ \ OFF
syn keyword cmakeKWproject contained
- \ CMAKE_PROJECT_ DESCRIPTION LANGUAGES NAME NONE PROJECT VERSION _BINARY_DIR _INCLUDE _SOURCE_DIR _VERSION _VERSION_MAJOR _VERSION_MINOR _VERSION_PATCH _VERSION_TWEAK
+ \ ASM
+ \ ASM_MARMASM
+ \ ASM_MASM
+ \ ASM_NASM
+ \ ATT
+ \ CMAKE_PROJECT_
+ \ CUDA
+ \ DESCRIPTION
+ \ HIP
+ \ HOMEPAGE_URL
+ \ ISPC
+ \ LANGUAGES
+ \ NAME
+ \ NONE
+ \ OBJC
+ \ OBJCXX
+ \ PROJECT
+ \ VERSION
+ \ _BINARY_DIR
+ \ _DESCRIPTION
+ \ _HOMEPAGE_URL
+ \ _INCLUDE_BEFORE
+ \ _IS_TOP_LEVEL
+ \ _SOURCE_DIR
+ \ _VERSION
+ \ _VERSION_MAJOR
+ \ _VERSION_MINOR
+ \ _VERSION_PATCH
+ \ _VERSION_TWEAK
+
+syn keyword cmakeKWqt_wrap_cpp contained
+ \ AUTOMOC
+
+syn keyword cmakeKWqt_wrap_ui contained
+ \ AUTOUIC
syn keyword cmakeKWremove contained
- \ REMOVE_ITEM VALUE VAR
+ \ VALUE
+ \ VAR
+
+syn keyword cmakeKWreturn contained
+ \ DEFER
+ \ PARENT_SCOPE
+ \ PROPAGATE
+ \ SCOPE_FOR
+ \ VARIABLES
+ \ VERSION
syn keyword cmakeKWseparate_arguments contained
- \ MSDN NATIVE NATIVE_COMMAND UNIX_COMMAND WINDOWS WINDOWS_COMMAND _COMMAND
+ \ MSDN
+ \ NATIVE_COMMAND
+ \ PROGRAM
+ \ SEPARATE_ARGS
+ \ UNIX_COMMAND
+ \ WINDOWS_COMMAND
syn keyword cmakeKWset contained
- \ BOOL CACHE FILEPATH FORCE INTERNAL OFF ON PARENT_SCOPE STRING STRINGS
+ \ BOOL
+ \ FILEPATH
+ \ FORCE
+ \ INTERNAL
+ \ OFF
+ \ OLD
+ \ ON
+ \ PARENT_SCOPE
+ \ PROPAGATE
+ \ STRING
+ \ STRINGS
+ \ VAR
syn keyword cmakeKWset_directory_properties contained
+ \ DIRECTORY
\ PROPERTIES
syn keyword cmakeKWset_property contained
- \ APPEND APPEND_STRING CACHE DIRECTORY GLOBAL INSTALL PROPERTY SOURCE TARGET TEST WIX
+ \ APPEND
+ \ APPEND_STRING
+ \ DIRECTORY
+ \ GENERATED
+ \ GLOBAL
+ \ INHERITED
+ \ INSTALL
+ \ NAME
+ \ PROPERTY
+ \ SOURCE
+ \ TARGET
+ \ TARGET_DIRECTORY
+ \ TEST
+ \ WIX
syn keyword cmakeKWset_source_files_properties contained
+ \ DIRECTORY
+ \ GENERATED
\ PROPERTIES
+ \ SOURCE
+ \ TARGET_DIRECTORY
syn keyword cmakeKWset_target_properties contained
\ PROPERTIES
syn keyword cmakeKWset_tests_properties contained
+ \ NAME
\ PROPERTIES
+syn keyword cmakeKWsite_name contained
+ \ HOSTNAME
+
syn keyword cmakeKWsource_group contained
- \ FILES PREFIX REGULAR_EXPRESSION TREE
+ \ FILES
+ \ PREFIX
+ \ REGULAR_EXPRESSION
+ \ TREE
syn keyword cmakeKWstring contained
- \ ALPHABET APPEND ASCII CMAKE_MATCH_ COMPARE CONCAT CONFIGURE EQUAL ESCAPE_QUOTES FIND GENEX_STRIP GREATER GREATER_EQUAL GUID HASH LENGTH LESS LESS_EQUAL MAKE_C_IDENTIFIER MATCH MATCHALL MATCHES NAMESPACE NOTEQUAL ONLY PREPEND RANDOM RANDOM_SEED REGEX REPLACE REVERSE RFC SHA SOURCE_DATE_EPOCH STRIP SUBSTRING SZ TIMESTAMP TOLOWER TOUPPER TYPE US UTC UUID
+ \ ALPHABET
+ \ APPEND
+ \ ARRAY
+ \ ASCII
+ \ BOOLEAN
+ \ CMAKE_MATCH_
+ \ COMPARE
+ \ CONCAT
+ \ CONFIGURE
+ \ EQUAL
+ \ ERROR_VARIABLE
+ \ ESCAPE_QUOTES
+ \ FIND
+ \ GENEX_STRIP
+ \ GET
+ \ GREATER
+ \ GREATER_EQUAL
+ \ GUID
+ \ HASH
+ \ HEX
+ \ ISO
+ \ JOIN
+ \ JSON
+ \ LENGTH
+ \ LESS
+ \ LESS_EQUAL
+ \ MAKE_C_IDENTIFIER
+ \ MATCH
+ \ MATCHALL
+ \ MATCHES
+ \ MEMBER
+ \ NAMESPACE
+ \ NOTEQUAL
+ \ NULL
+ \ NUMBER
+ \ OBJECT
+ \ OFF
+ \ ONLY
+ \ PREPEND
+ \ RANDOM
+ \ RANDOM_SEED
+ \ REGEX
+ \ REMOVE
+ \ REPEAT
+ \ REPLACE
+ \ REVERSE
+ \ RFC
+ \ SET
+ \ SHA
+ \ SOURCE_DATE_EPOCH
+ \ STRIP
+ \ SUBSTRING
+ \ SZ
+ \ TIMESTAMP
+ \ TOLOWER
+ \ TOUPPER
+ \ TYPE
+ \ US
+ \ UTC
+ \ UUID
syn keyword cmakeKWsubdirs contained
- \ EXCLUDE_FROM_ALL PREORDER
+ \ EXCLUDE_FROM_ALL
+ \ PREORDER
syn keyword cmakeKWtarget_compile_definitions contained
- \ COMPILE_DEFINITIONS INTERFACE INTERFACE_COMPILE_DEFINITIONS PRIVATE PUBLIC
+ \ ALIAS
+ \ COMPILE_DEFINITIONS
+ \ FOO
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_COMPILE_DEFINITIONS
+ \ PRIVATE
+ \ PUBLIC
syn keyword cmakeKWtarget_compile_features contained
- \ COMPILE_FEATURES IMPORTED INTERFACE INTERFACE_COMPILE_FEATURES PRIVATE PUBLIC
+ \ ALIAS
+ \ COMPILE_FEATURES
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_COMPILE_FEATURES
+ \ PRIVATE
+ \ PUBLIC
syn keyword cmakeKWtarget_compile_options contained
- \ BEFORE COMPILE_OPTIONS IMPORTED INTERFACE INTERFACE_COMPILE_OPTIONS PRIVATE PUBLIC
+ \ ALIAS
+ \ BEFORE
+ \ CMAKE_
+ \ COMPILE_LANGUAGE
+ \ COMPILE_OPTIONS
+ \ CONFIG
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_COMPILE_OPTIONS
+ \ PRIVATE
+ \ PUBLIC
+ \ SHELL
+ \ UNIX_COMMAND
+ \ _FLAGS
+ \ _FLAGS_
syn keyword cmakeKWtarget_include_directories contained
- \ BEFORE BUILD_INTERFACE IMPORTED INCLUDE_DIRECTORIES INSTALL_INTERFACE INTERFACE INTERFACE_INCLUDE_DIRECTORIES INTERFACE_LINK_LIBRARIES INTERFACE_SYSTEM_INCLUDE_DIRECTORIES PRIVATE PUBLIC SYSTEM
+ \ AFTER
+ \ ALIAS
+ \ BEFORE
+ \ BUILD_INTERFACE
+ \ IMPORTED
+ \ INCLUDE_DIRECTORIES
+ \ INSTALL_INTERFACE
+ \ INTERFACE
+ \ INTERFACE_INCLUDE_DIRECTORIES
+ \ INTERFACE_LINK_LIBRARIES
+ \ INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
+ \ PRIVATE
+ \ PUBLIC
+ \ SYSTEM
+
+syn keyword cmakeKWtarget_link_directories contained
+ \ ALIAS
+ \ BEFORE
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_LINK_DIRECTORIES
+ \ LINK_DIRECTORIES
+ \ ORIGIN
+ \ PRIVATE
+ \ PUBLIC
+ \ RPATH
syn keyword cmakeKWtarget_link_libraries contained
- \ ALIAS DAG DEBUG_CONFIGURATIONS IMPORTED IMPORTED_NO_SONAME INTERFACE INTERFACE_LINK_LIBRARIES LINK_FLAGS LINK_INTERFACE_LIBRARIES LINK_INTERFACE_LIBRARIES_DEBUG LINK_INTERFACE_MULTIPLICITY LINK_PRIVATE LINK_PUBLIC OLD OSX PRIVATE PUBLIC STATIC
+ \ ALIAS
+ \ DA
+ \ DAG
+ \ DEBUG_CONFIGURATIONS
+ \ DOBJ
+ \ IMPORTED
+ \ IMPORTED_NO_SONAME
+ \ INTERFACE
+ \ INTERFACE_LINK_LIBRARIES
+ \ LINK_FLAGS
+ \ LINK_INTERFACE_LIBRARIES
+ \ LINK_INTERFACE_LIBRARIES_DEBUG
+ \ LINK_INTERFACE_MULTIPLICITY
+ \ LINK_OPTIONS
+ \ LINK_PRIVATE
+ \ LINK_PUBLIC
+ \ OBJECT
+ \ OLD
+ \ PRIVATE
+ \ PUBLIC
+ \ SHARED
+ \ STATIC
+ \ TARGET_OBJECTS
+
+syn keyword cmakeKWtarget_link_options contained
+ \ ALIAS
+ \ BEFORE
+ \ CMAKE_
+ \ CONFIG
+ \ CUDA_RESOLVE_DEVICE_SYMBOLS
+ \ CUDA_SEPARABLE_COMPILATION
+ \ DEVICE_LINK
+ \ GCC
+ \ HOST_LINK
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_LINK_OPTIONS
+ \ LANG
+ \ LINKER
+ \ LINK_OPTIONS
+ \ PRIVATE
+ \ PUBLIC
+ \ SHELL
+ \ STATIC_LIBRARY_OPTIONS
+ \ UNIX_COMMAND
+ \ _FLAGS
+ \ _FLAGS_
+ \ _LINKER_WRAPPER_FLAG
+ \ _LINKER_WRAPPER_FLAG_SEP
+
+syn keyword cmakeKWtarget_precompile_headers contained
+ \ ALIAS
+ \ ANGLE
+ \ BUILD_INTERFACE
+ \ COMPILE_LANGUAGE
+ \ DISABLE_PRECOMPILE_HEADERS
+ \ EXPORT
+ \ FI
+ \ GCC
+ \ IMPORTED
+ \ INTERFACE
+ \ INTERFACE_PRECOMPILE_HEADERS
+ \ PRECOMPILE_HEADERS
+ \ PRECOMPILE_HEADERS_REUSE_FROM
+ \ PRIVATE
+ \ PUBLIC
+ \ REUSE_FROM
+ \ SKIP_PRECOMPILE_HEADERS
syn keyword cmakeKWtarget_sources contained
- \ IMPORTED INTERFACE INTERFACE_SOURCES PRIVATE PUBLIC SOURCES
+ \ ALIAS
+ \ BASE_DIRS
+ \ BUILD_INTERFACE
+ \ CONFIG
+ \ CORRECT
+ \ CXX_MODULES
+ \ CXX_MODULE_DIRS
+ \ CXX_MODULE_DIRS_
+ \ CXX_MODULE_SETS
+ \ CXX_MODULE_SET_
+ \ EXPORT
+ \ FILES
+ \ FILE_SET
+ \ FRAMEWORK
+ \ HEADERS
+ \ HEADER_DIRS
+ \ HEADER_DIRS_
+ \ HEADER_FILE_ONLY
+ \ HEADER_SETS
+ \ HEADER_SET_
+ \ IMPORTED
+ \ INCLUDE_DIRECTORIES
+ \ INTERFACE
+ \ INTERFACE_CXX_MODULE_SETS
+ \ INTERFACE_HEADER_SETS
+ \ INTERFACE_INCLUDE_DIRECTORIES
+ \ INTERFACE_SOURCES
+ \ NAME
+ \ PRIVATE
+ \ PUBLIC
+ \ SOURCES
+ \ SOURCE_DIR
+ \ TARGETS
+ \ TRUE
+ \ TYPE
+ \ WRONG
syn keyword cmakeKWtry_compile contained
- \ ALL_BUILD CMAKE_FLAGS COMPILE_DEFINITIONS COPY_FILE COPY_FILE_ERROR CUDA_EXTENSIONS CUDA_STANDARD CUDA_STANDARD_REQUIRED CXX_EXTENSIONS CXX_STANDARD CXX_STANDARD_REQUIRED C_EXTENSIONS C_STANDARD C_STANDARD_REQUIRED DEFINED DLINK_LIBRARIES DVAR FALSE INCLUDE_DIRECTORIES LANG LINK_DIRECTORIES LINK_LIBRARIES NOT OUTPUT_VARIABLE RESULT_VAR SOURCES TRUE TYPE VALUE _EXTENSIONS _STANDARD _STANDARD_REQUIRED
+ \ ALL_BUILD
+ \ BINARY_DIR
+ \ CMAKE_FLAGS
+ \ COMPILE_DEFINITIONS
+ \ COPY_FILE
+ \ COPY_FILE_ERROR
+ \ CUDA_EXTENSIONS
+ \ CUDA_STANDARD
+ \ CUDA_STANDARD_REQUIRED
+ \ CXX_EXTENSIONS
+ \ CXX_STANDARD
+ \ CXX_STANDARD_REQUIRED
+ \ C_EXTENSIONS
+ \ C_STANDARD
+ \ C_STANDARD_REQUIRED
+ \ DEFINED
+ \ DLINK_LIBRARIES
+ \ DVAR
+ \ EXECUTABLE
+ \ FALSE
+ \ GHS
+ \ HIP_EXTENSIONS
+ \ HIP_STANDARD
+ \ HIP_STANDARD_REQUIRED
+ \ INCLUDE_DIRECTORIES
+ \ LANG
+ \ LINK_DIRECTORIES
+ \ LINK_LIBRARIES
+ \ LINK_OPTIONS
+ \ LOG_DESCRIPTION
+ \ MULTI
+ \ NOT
+ \ NO_CACHE
+ \ NO_LOG
+ \ OBJCXX_EXTENSIONS
+ \ OBJCXX_STANDARD
+ \ OBJCXX_STANDARD_REQUIRED
+ \ OBJC_EXTENSIONS
+ \ OBJC_STANDARD
+ \ OBJC_STANDARD_REQUIRED
+ \ OUTPUT_VARIABLE
+ \ PRIVATE
+ \ PROJECT
+ \ RESULTVAR
+ \ SOURCES
+ \ SOURCE_DIR
+ \ SOURCE_FROM_CONTENT
+ \ SOURCE_FROM_FILE
+ \ SOURCE_FROM_VAR
+ \ STATIC_LIBRARY
+ \ STATIC_LIBRARY_OPTIONS
+ \ TARGET
+ \ TRUE
+ \ TYPE
+ \ VALUE
+ \ _EXTENSIONS
+ \ _STANDARD
+ \ _STANDARD_REQUIRED
syn keyword cmakeKWtry_run contained
- \ ARGS CMAKE_FLAGS COMPILE_DEFINITIONS COMPILE_OUTPUT_VARIABLE COMPILE_RESULT_VAR DLINK_LIBRARIES DVAR FAILED_TO_RUN FALSE INCLUDE_DIRECTORIES LINK_DIRECTORIES LINK_LIBRARIES RUN_OUTPUT_VARIABLE RUN_RESULT_VAR TRUE TYPE VALUE __TRYRUN_OUTPUT
+ \ ARGS
+ \ CMAKE_FLAGS
+ \ COMPILE_DEFINITIONS
+ \ COMPILE_OUTPUT_VARIABLE
+ \ COPY_FILE
+ \ COPY_FILE_ERROR
+ \ FAILED_TO_RUN
+ \ FALSE
+ \ LANG
+ \ LINK_LIBRARIES
+ \ LINK_OPTIONS
+ \ LOG_DESCRIPTION
+ \ NO_CACHE
+ \ NO_LOG
+ \ RUN_OUTPUT_STDERR_VARIABLE
+ \ RUN_OUTPUT_STDOUT_VARIABLE
+ \ RUN_OUTPUT_VARIABLE
+ \ SOURCES
+ \ SOURCE_FROM_CONTENT
+ \ SOURCE_FROM_FILE
+ \ SOURCE_FROM_VAR
+ \ TRUE
+ \ WORKING_DIRECTORY
+ \ _EXTENSIONS
+ \ _STANDARD
+ \ _STANDARD_REQUIRED
+ \ __TRYRUN_OUTPUT
syn keyword cmakeKWunset contained
- \ CACHE LD_LIBRARY_PATH PARENT_SCOPE
+ \ PARENT_SCOPE
+ \ VAR
syn keyword cmakeKWuse_mangled_mesa contained
- \ GL OUTPUT_DIRECTORY PATH_TO_MESA
+ \ GL
+ \ OUTPUT_DIRECTORY
+ \ PATH_TO_MESA
syn keyword cmakeKWvariable_requires contained
- \ RESULT_VARIABLE TEST_VARIABLE
+ \ RESULT_VARIABLE
+ \ TEST_VARIABLE
syn keyword cmakeKWvariable_watch contained
+ \ APPEND
\ COMMAND
-
-syn keyword cmakeKWwhile contained
- \ ARGS
+ \ DEFINED
+ \ MODIFIED_ACCESS
+ \ READ_ACCESS
+ \ REMOVED_ACCESS
+ \ UNKNOWN_MODIFIED_ACCESS
+ \ UNKNOWN_READ_ACCESS
syn keyword cmakeKWwrite_file contained
- \ APPEND CONFIGURE_FILE NOTE WRITE
+ \ APPEND
+ \ CONFIGURE_FILE
+ \ NOTE
+ \ WRITE
syn keyword cmakeGeneratorExpressions contained
- \ LINK_LIBRARIES INCLUDE_DIRECTORIES COMPILE_DEFINITIONS CONFIG DEBUG_MODE BOOL AND NOT IF STREQUAL MAP_IMPORTED_CONFIG_ PLATFORM_ID C_COMPILER_ID CXX_COMPILER_ID VERSION_LESS VERSION_GREATER VERSION_EQUAL VERSION_LESS_EQUAL VERSION_GREATER_EQUAL C_COMPILER_VERSION CXX_COMPILER_VERSION TARGET_POLICY COMPILE_FEATURES C_STANDARD CXX_STANDARD COMPILE_LANGUAGE PRIVATE PUBLIC COMPILING_CXX GNU OLD_COMPILER CMAKE_CXX_COMPILER_VERSION CONFIGURATION TARGET_FILE TARGET_FILE_NAME TARGET_FILE_DIR TARGET_LINKER_FILE TARGET_LINKER_FILE_NAME TARGET_LINKER_FILE_DIR TARGET_SONAME_FILE TARGET_SONAME_FILE_NAME TARGET_SONAME_FILE_DIR TARGET_PDB_FILE PDB_NAME PDB_OUTPUT_DIRECTORY PDB_NAME_ PDB_OUTPUT_DIRECTORY_ TARGET_PDB_FILE_NAME TARGET_PDB_FILE_DIR TARGET_BUNDLE_DIR TARGET_BUNDLE_CONTENT_DIR SDK TARGET_PROPERTY INSTALL_PREFIX EXPORT JOIN ANGLE COMMA SEMICOLON TARGET_NAME LINK_ONLY INTERFACE_LINK_LIBRARIES INSTALL_INTERFACE BUILD_INTERFACE LOWER_CASE UPPER_CASE MAKE_C_IDENTIFIER TARGET_OBJECTS OBJECT_LIBRARY SHELL_PATH MSYS
+ \ ABSOLUTE_PATH
+ \ ACTION
+ \ AIX
+ \ ANGLE
+ \ APPEND
+ \ ARCHIVE_OUTPUT_NAME
+ \ ARCHIVE_OUTPUT_NAME_
+ \ ASCENDING
+ \ BAR
+ \ BOOL
+ \ BUILD_INTERFACE
+ \ BUILD_LOCAL_INTERFACE
+ \ CMAKE_LINK_GROUP_USING_
+ \ CMAKE_LINK_LIBRARY_USING_
+ \ CMAKE_PATH
+ \ CODE
+ \ COMMAND_CONFIG
+ \ COMMAND_EXPAND_LISTS
+ \ COMPARE
+ \ COMPILE_DEFINITIONS
+ \ COMPILE_FEATURES
+ \ COMPILE_LANGUAGE
+ \ COMPILE_LANG_AND_ID
+ \ COMPILE_ONLY
+ \ COMPILING_CUDA
+ \ COMPILING_CXX
+ \ COMPILING_CXX_WITH_CLANG
+ \ COMPILING_CXX_WITH_INTEL
+ \ COMPILING_C_WITH_CLANG
+ \ CONFIG
+ \ CONFIGURATION
+ \ CONTENT
+ \ CUDA_COMPILER_ID
+ \ CUDA_COMPILER_VERSION
+ \ CUDA_RESOLVE_DEVICE_SYMBOLS
+ \ CUDA_SEPARABLE_COMPILATION
+ \ CUSTOM_KEYS
+ \ CXX_COMPILER_ID
+ \ CXX_COMPILER_VERSION
+ \ CXX_CONFIG
+ \ CXX_STANDARD
+ \ C_COMPILER_ID
+ \ C_COMPILER_VERSION
+ \ C_STANDARD
+ \ DEBUG_MODE
+ \ DEBUG_POSTFIX
+ \ DENABLE_SOME_FEATURE
+ \ DESCENDING
+ \ DEVICE_LINK
+ \ DLL
+ \ ENABLE_EXPORTS
+ \ EXCLUDE
+ \ EXPORT
+ \ EXTENSION_DEF
+ \ FALSE
+ \ FILENAME_DEF
+ \ FILE_BASENAME
+ \ FILTER
+ \ FIND
+ \ FOO_EXTRA_THINGS
+ \ GENERATE
+ \ GENEX_EVAL
+ \ GET_EXTENSION
+ \ GET_FILENAME
+ \ GET_PARENT_PATH
+ \ GET_RELATIVE_PART
+ \ GET_ROOT_DIRECTORY
+ \ GET_ROOT_NAME
+ \ GET_ROOT_PATH
+ \ GET_STEM
+ \ HAS_
+ \ HAS_EXTENSION
+ \ HAS_FILENAME
+ \ HAS_PARENT_PATH
+ \ HAS_RELATIVE_PART
+ \ HAS_ROOT_DIRECTORY
+ \ HAS_ROOT_NAME
+ \ HAS_ROOT_PATH
+ \ HAS_STEM
+ \ HAVE_SOME_FEATURE
+ \ HIP_COMPILER_ID
+ \ HIP_COMPILER_VERSION
+ \ HIP_STANDARD
+ \ HOST_LINK
+ \ IF
+ \ IGNORE
+ \ IMPORTED_LOCATION
+ \ IMPORT_PREFIX
+ \ IMPORT_SUFFIX
+ \ INCLUDE_DIRECTORIES
+ \ INSENSITIVE
+ \ INSERT
+ \ INSTALL_INTERFACE
+ \ INSTALL_NAME_DIR
+ \ INSTALL_PREFIX
+ \ INSTALL_RPATH
+ \ INTERFACE_LINK_LIBRARIES
+ \ INTERFACE_LINK_LIBRARIES_DIRECT
+ \ IN_LIST
+ \ ISPC_COMPILER_ID
+ \ ISPC_COMPILER_VERSION
+ \ IS_ABSOLUTE
+ \ IS_PREFIX
+ \ IS_RELATIVE
+ \ JOIN
+ \ LANG
+ \ LANG_COMPILER_ID
+ \ LAST_ONLY
+ \ LENGTH
+ \ LIBRARY_OUTPUT_NAME
+ \ LIBRARY_OUTPUT_NAME_
+ \ LINK_GROUP
+ \ LINK_GROUP_PREDEFINED_FEATURES
+ \ LINK_LANGUAGE
+ \ LINK_LANG_AND_ID
+ \ LINK_LIBRARIES
+ \ LINK_LIBRARY
+ \ LINK_LIBRARY_OVERRIDE
+ \ LINK_LIBRARY_OVERRIDE_
+ \ LINK_LIBRARY_PREDEFINED_FEATURES
+ \ LINK_ONLY
+ \ LOWER_CASE
+ \ MAKE_C_IDENTIFIER
+ \ MAP_IMPORTED_CONFIG_
+ \ MODULE
+ \ NATURAL
+ \ NO
+ \ NORMALIZE
+ \ NORMAL_PATH
+ \ NOT
+ \ OBJCXX_COMPILER_ID
+ \ OBJCXX_COMPILER_VERSION
+ \ OBJC_COMPILER_ID
+ \ OBJC_COMPILER_VERSION
+ \ OBJECT
+ \ OFF
+ \ OLD_COMPILER
+ \ ORDER
+ \ OUTPUT
+ \ OUTPUT_CONFIG
+ \ OUTPUT_NAME
+ \ OUTPUT_NAME_
+ \ PATH
+ \ PATH_EQUAL
+ \ PDB_NAME
+ \ PDB_NAME_
+ \ PDB_OUTPUT_DIRECTORY
+ \ PDB_OUTPUT_DIRECTORY_
+ \ PLATFORM_ID
+ \ POP_BACK
+ \ POP_FRONT
+ \ POSIX
+ \ POST_BUILD
+ \ PREPEND
+ \ PRIVATE
+ \ PUBLIC
+ \ REGEX
+ \ RELATIVE_PATH
+ \ REMOVE_AT
+ \ REMOVE_DUPLICATES
+ \ REMOVE_EXTENSION
+ \ REMOVE_FILENAME
+ \ REMOVE_ITEM
+ \ REPLACE
+ \ REPLACE_EXTENSION
+ \ REPLACE_FILENAME
+ \ REQUIRED
+ \ RESCAN
+ \ REVERSE
+ \ RPATH
+ \ RUNTIME_DEPENDENCY_SET
+ \ RUNTIME_OUTPUT_NAME
+ \ RUNTIME_OUTPUT_NAME_
+ \ SCRIPT
+ \ SDK
+ \ SELECTOR
+ \ SEMICOLON
+ \ SENSITIVE
+ \ SHARED
+ \ SHELL_PATH
+ \ SORT
+ \ STATIC
+ \ STREQUAL
+ \ STRING
+ \ STRIP
+ \ SUBLIST
+ \ TARGET_BUNDLE_CONTENT_DIR
+ \ TARGET_BUNDLE_DIR
+ \ TARGET_BUNDLE_DIR_NAME
+ \ TARGET_EXISTS
+ \ TARGET_FILE
+ \ TARGET_FILE_BASE_NAME
+ \ TARGET_FILE_DIR
+ \ TARGET_FILE_NAME
+ \ TARGET_FILE_PREFIX
+ \ TARGET_FILE_SUFFIX
+ \ TARGET_GENEX_EVAL
+ \ TARGET_IMPORT_FILE
+ \ TARGET_IMPORT_FILE_BASE_NAME
+ \ TARGET_IMPORT_FILE_DIR
+ \ TARGET_IMPORT_FILE_NAME
+ \ TARGET_IMPORT_FILE_PREFIX
+ \ TARGET_IMPORT_FILE_SUFFIX
+ \ TARGET_LINKER_FILE
+ \ TARGET_LINKER_FILE_BASE_NAME
+ \ TARGET_LINKER_FILE_DIR
+ \ TARGET_LINKER_FILE_NAME
+ \ TARGET_LINKER_FILE_PREFIX
+ \ TARGET_LINKER_FILE_SUFFIX
+ \ TARGET_LINKER_IMPORT_FILE
+ \ TARGET_LINKER_IMPORT_FILE_BASE_NAME
+ \ TARGET_LINKER_IMPORT_FILE_DIR
+ \ TARGET_LINKER_IMPORT_FILE_NAME
+ \ TARGET_LINKER_IMPORT_FILE_PREFIX
+ \ TARGET_LINKER_IMPORT_FILE_SUFFIX
+ \ TARGET_LINKER_LIBRARY_FILE
+ \ TARGET_LINKER_LIBRARY_FILE_BASE_NAME
+ \ TARGET_LINKER_LIBRARY_FILE_DIR
+ \ TARGET_LINKER_LIBRARY_FILE_NAME
+ \ TARGET_LINKER_LIBRARY_FILE_PREFIX
+ \ TARGET_LINKER_LIBRARY_FILE_SUFFIX
+ \ TARGET_NAME_IF_EXISTS
+ \ TARGET_OBJECTS
+ \ TARGET_PDB_FILE
+ \ TARGET_PDB_FILE_BASE_NAME
+ \ TARGET_PDB_FILE_DIR
+ \ TARGET_PDB_FILE_NAME
+ \ TARGET_POLICY
+ \ TARGET_PROPERTY
+ \ TARGET_RUNTIME_DLLS
+ \ TARGET_RUNTIME_DLL_DIRS
+ \ TARGET_SONAME_FILE
+ \ TARGET_SONAME_FILE_DIR
+ \ TARGET_SONAME_FILE_NAME
+ \ TARGET_SONAME_IMPORT_FILE
+ \ TARGET_SONAME_IMPORT_FILE_DIR
+ \ TARGET_SONAME_IMPORT_FILE_NAME
+ \ TOLOWER
+ \ TOUPPER
+ \ TRANSFORM
+ \ TRANSFORM_APPEND
+ \ TRANSFORM_REPLACE
+ \ TRANSFORM_STRIP
+ \ TRANSFORM_TOLOWER
+ \ UNKNOWN
+ \ UPPER_CASE
+ \ VERBATIM
+ \ VERSION_EQUAL
+ \ VERSION_GREATER_EQUAL
+ \ VERSION_LESS
+ \ VERSION_LESS_EQUAL
+ \ WHOLE_ARCHIVE
+ \ WRONG
+ \ _LINK_GROUP_USING_
+ \ _LINK_LIBRARY_USING_
+ \ _POSTFIX
+ \ _SUPPORTED
syn case ignore
syn keyword cmakeCommand
- \ add_compile_options add_compile_definitions add_custom_command add_custom_target add_definitions add_dependencies add_executable add_library add_subdirectory add_test aux_source_directory break build_command cmake_host_system_information cmake_minimum_required cmake_parse_arguments cmake_policy configure_file continue create_test_sourcelist ctest_build ctest_configure ctest_coverage ctest_empty_binary_directory ctest_memcheck ctest_read_custom_files ctest_run_script ctest_sleep ctest_start ctest_submit ctest_test ctest_update ctest_upload define_property enable_language enable_testing endfunction endmacro execute_process export file find_file find_library find_package find_path find_program fltk_wrap_ui function get_cmake_property get_directory_property get_filename_component get_property get_source_file_property get_target_property get_test_property include include_directories include_external_msproject include_guard include_regular_expression install link_directories list load_cache load_command macro mark_as_advanced math message option project qt_wrap_cpp qt_wrap_ui remove_definitions return separate_arguments set set_directory_properties set_property set_source_files_properties set_target_properties set_tests_properties site_name source_group string target_compile_definitions target_compile_features target_compile_options target_include_directories target_link_libraries target_sources try_compile try_run unset variable_watch
+ \ add_compile_definitions
+ \ add_compile_options
+ \ add_custom_command
+ \ add_custom_target
+ \ add_definitions
+ \ add_dependencies
+ \ add_executable
+ \ add_library
+ \ add_link_options
+ \ add_subdirectory
+ \ add_test
+ \ aux_source_directory
+ \ block
+ \ break
+ \ build_command
+ \ cmake_file_api
+ \ cmake_host_system_information
+ \ cmake_language
+ \ cmake_minimum_required
+ \ cmake_parse_arguments
+ \ cmake_path
+ \ cmake_policy
+ \ configure_file
+ \ continue
+ \ create_test_sourcelist
+ \ ctest_build
+ \ ctest_configure
+ \ ctest_coverage
+ \ ctest_empty_binary_directory
+ \ ctest_memcheck
+ \ ctest_read_custom_files
+ \ ctest_run_script
+ \ ctest_sleep
+ \ ctest_start
+ \ ctest_submit
+ \ ctest_test
+ \ ctest_update
+ \ ctest_upload
+ \ define_property
+ \ enable_language
+ \ enable_testing
+ \ endblock
+ \ endfunction
+ \ endmacro
+ \ execute_process
+ \ export
+ \ file
+ \ find_file
+ \ find_library
+ \ find_package
+ \ find_path
+ \ find_program
+ \ fltk_wrap_ui
+ \ function
+ \ get_cmake_property
+ \ get_directory_property
+ \ get_filename_component
+ \ get_property
+ \ get_source_file_property
+ \ get_target_property
+ \ get_test_property
+ \ include
+ \ include_directories
+ \ include_external_msproject
+ \ include_guard
+ \ include_regular_expression
+ \ install
+ \ link_directories
+ \ list
+ \ load_cache
+ \ load_command
+ \ macro
+ \ mark_as_advanced
+ \ math
+ \ message
+ \ option
+ \ project
+ \ qt_wrap_cpp
+ \ qt_wrap_ui
+ \ remove_definitions
+ \ return
+ \ separate_arguments
+ \ set
+ \ set_directory_properties
+ \ set_property
+ \ set_source_files_properties
+ \ set_target_properties
+ \ set_tests_properties
+ \ site_name
+ \ source_group
+ \ string
+ \ target_compile_definitions
+ \ target_compile_features
+ \ target_compile_options
+ \ target_include_directories
+ \ target_link_directories
+ \ target_link_libraries
+ \ target_link_options
+ \ target_precompile_headers
+ \ target_sources
+ \ try_compile
+ \ try_run
+ \ unset
+ \ variable_watch
\ nextgroup=cmakeArguments
syn keyword cmakeCommandConditional
- \ else elseif endif if
+ \ else
+ \ elseif
+ \ endif
+ \ if
\ nextgroup=cmakeArguments
syn keyword cmakeCommandRepeat
- \ endforeach endwhile foreach while
+ \ endforeach
+ \ endwhile
+ \ foreach
+ \ while
\ nextgroup=cmakeArguments
syn keyword cmakeCommandDeprecated
- \ build_name exec_program export_library_dependencies install_files install_programs install_targets link_libraries make_directory output_required_files remove subdir_depends subdirs use_mangled_mesa utility_source variable_requires write_file
+ \ build_name
+ \ exec_program
+ \ export_library_dependencies
+ \ install_files
+ \ install_programs
+ \ install_targets
+ \ link_libraries
+ \ make_directory
+ \ output_required_files
+ \ remove
+ \ subdir_depends
+ \ subdirs
+ \ use_mangled_mesa
+ \ utility_source
+ \ variable_requires
+ \ write_file
\ nextgroup=cmakeArguments
syn case match
@@ -356,6 +4820,8 @@ syn keyword cmakeTodo
\ TODO FIXME XXX
\ contained
+hi def link cmakeBracketArgument String
+hi def link cmakeBracketComment Comment
hi def link cmakeCommand Function
hi def link cmakeCommandConditional Conditional
hi def link cmakeCommandDeprecated WarningMsg
@@ -365,7 +4831,6 @@ hi def link cmakeEnvironment Special
hi def link cmakeEscaped Special
hi def link cmakeGeneratorExpression WarningMsg
hi def link cmakeGeneratorExpressions Constant
-hi def link cmakeLuaComment Comment
hi def link cmakeModule Include
hi def link cmakeProperty Constant
hi def link cmakeRegistry Underlined
@@ -375,6 +4840,8 @@ hi def link cmakeVariableValue Type
hi def link cmakeVariable Identifier
hi def link cmakeKWExternalProject ModeMsg
+hi def link cmakeKWFetchContent ModeMsg
+hi def link cmakeKWadd_compile_definitions ModeMsg
hi def link cmakeKWadd_compile_options ModeMsg
hi def link cmakeKWadd_custom_command ModeMsg
hi def link cmakeKWadd_custom_target ModeMsg
@@ -382,13 +4849,17 @@ hi def link cmakeKWadd_definitions ModeMsg
hi def link cmakeKWadd_dependencies ModeMsg
hi def link cmakeKWadd_executable ModeMsg
hi def link cmakeKWadd_library ModeMsg
+hi def link cmakeKWadd_link_options ModeMsg
hi def link cmakeKWadd_subdirectory ModeMsg
hi def link cmakeKWadd_test ModeMsg
+hi def link cmakeKWblock ModeMsg
hi def link cmakeKWbuild_command ModeMsg
-hi def link cmakeKWbuild_name ModeMsg
+hi def link cmakeKWcmake_file_api ModeMsg
hi def link cmakeKWcmake_host_system_information ModeMsg
+hi def link cmakeKWcmake_language ModeMsg
hi def link cmakeKWcmake_minimum_required ModeMsg
hi def link cmakeKWcmake_parse_arguments ModeMsg
+hi def link cmakeKWcmake_path ModeMsg
hi def link cmakeKWcmake_policy ModeMsg
hi def link cmakeKWconfigure_file ModeMsg
hi def link cmakeKWcreate_test_sourcelist ModeMsg
@@ -403,7 +4874,9 @@ hi def link cmakeKWctest_test ModeMsg
hi def link cmakeKWctest_update ModeMsg
hi def link cmakeKWctest_upload ModeMsg
hi def link cmakeKWdefine_property ModeMsg
+hi def link cmakeKWdoxygen_add_docs ModeMsg
hi def link cmakeKWenable_language ModeMsg
+hi def link cmakeKWenable_testing ModeMsg
hi def link cmakeKWexec_program ModeMsg
hi def link cmakeKWexecute_process ModeMsg
hi def link cmakeKWexport ModeMsg
@@ -433,17 +4906,20 @@ hi def link cmakeKWinstall ModeMsg
hi def link cmakeKWinstall_files ModeMsg
hi def link cmakeKWinstall_programs ModeMsg
hi def link cmakeKWinstall_targets ModeMsg
+hi def link cmakeKWlink_directories ModeMsg
hi def link cmakeKWlist ModeMsg
hi def link cmakeKWload_cache ModeMsg
hi def link cmakeKWload_command ModeMsg
hi def link cmakeKWmacro ModeMsg
-hi def link cmakeKWmake_directory ModeMsg
hi def link cmakeKWmark_as_advanced ModeMsg
hi def link cmakeKWmath ModeMsg
hi def link cmakeKWmessage ModeMsg
hi def link cmakeKWoption ModeMsg
hi def link cmakeKWproject ModeMsg
+hi def link cmakeKWqt_wrap_cpp ModeMsg
+hi def link cmakeKWqt_wrap_ui ModeMsg
hi def link cmakeKWremove ModeMsg
+hi def link cmakeKWreturn ModeMsg
hi def link cmakeKWseparate_arguments ModeMsg
hi def link cmakeKWset ModeMsg
hi def link cmakeKWset_directory_properties ModeMsg
@@ -451,6 +4927,7 @@ hi def link cmakeKWset_property ModeMsg
hi def link cmakeKWset_source_files_properties ModeMsg
hi def link cmakeKWset_target_properties ModeMsg
hi def link cmakeKWset_tests_properties ModeMsg
+hi def link cmakeKWsite_name ModeMsg
hi def link cmakeKWsource_group ModeMsg
hi def link cmakeKWstring ModeMsg
hi def link cmakeKWsubdirs ModeMsg
@@ -458,7 +4935,10 @@ hi def link cmakeKWtarget_compile_definitions ModeMsg
hi def link cmakeKWtarget_compile_features ModeMsg
hi def link cmakeKWtarget_compile_options ModeMsg
hi def link cmakeKWtarget_include_directories ModeMsg
+hi def link cmakeKWtarget_link_directories ModeMsg
hi def link cmakeKWtarget_link_libraries ModeMsg
+hi def link cmakeKWtarget_link_options ModeMsg
+hi def link cmakeKWtarget_precompile_headers ModeMsg
hi def link cmakeKWtarget_sources ModeMsg
hi def link cmakeKWtry_compile ModeMsg
hi def link cmakeKWtry_run ModeMsg
@@ -466,9 +4946,32 @@ hi def link cmakeKWunset ModeMsg
hi def link cmakeKWuse_mangled_mesa ModeMsg
hi def link cmakeKWvariable_requires ModeMsg
hi def link cmakeKWvariable_watch ModeMsg
-hi def link cmakeKWwhile ModeMsg
hi def link cmakeKWwrite_file ModeMsg
+" Manually added - difficult to parse out of documentation
+syn case ignore
+
+syn keyword cmakeCommandManuallyAdded
+ \ configure_package_config_file write_basic_package_version_file
+ \ nextgroup=cmakeArguments
+
+syn case match
+
+syn keyword cmakeKWconfigure_package_config_file contained
+ \ INSTALL_DESTINATION PATH_VARS NO_SET_AND_CHECK_MACRO NO_CHECK_REQUIRED_COMPONENTS_MACRO INSTALL_PREFIX
+
+syn keyword cmakeKWconfigure_package_config_file_constants contained
+ \ AnyNewerVersion SameMajorVersion SameMinorVersion ExactVersion
+
+syn keyword cmakeKWwrite_basic_package_version_file contained
+ \ VERSION COMPATIBILITY
+
+hi def link cmakeCommandManuallyAdded Function
+
+hi def link cmakeKWconfigure_package_config_file ModeMsg
+hi def link cmakeKWwrite_basic_package_version_file ModeMsg
+hi def link cmakeKWconfigure_package_config_file_constants Constant
+
let b:current_syntax = "cmake"
let &cpo = s:keepcpo
diff --git a/runtime/syntax/cpp.vim b/runtime/syntax/cpp.vim
index 5437580a0a..8daf90a33c 100644
--- a/runtime/syntax/cpp.vim
+++ b/runtime/syntax/cpp.vim
@@ -2,7 +2,7 @@
" Language: C++
" Current Maintainer: vim-jp (https://github.com/vim-jp/vim-cpp)
" Previous Maintainer: Ken Shan <ccshan@post.harvard.edu>
-" Last Change: 2021 Aug 23
+" Last Change: 2023 Dec 08
" quit when a syntax file was already loaded
if exists("b:current_syntax")
@@ -15,6 +15,7 @@ let b:filetype_in_cpp_family = 1
" Read the C syntax to start with
runtime! syntax/c.vim
unlet b:current_syntax
+unlet b:filetype_in_cpp_family
" C++ extensions
syn keyword cppStatement new delete this friend using
diff --git a/runtime/syntax/csh.vim b/runtime/syntax/csh.vim
index 6a056c7004..0ad85adfc7 100644
--- a/runtime/syntax/csh.vim
+++ b/runtime/syntax/csh.vim
@@ -1,9 +1,10 @@
" Vim syntax file
" Language: C-shell (csh)
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Aug 31, 2016
" Version: 14
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_CSH
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_CSH
" quit when a syntax file was already loaded
if exists("b:current_syntax")
diff --git a/runtime/syntax/css.vim b/runtime/syntax/css.vim
index f8104ea2c5..f4d09cfa4e 100644
--- a/runtime/syntax/css.vim
+++ b/runtime/syntax/css.vim
@@ -7,7 +7,7 @@
" Nikolai Weibull (Add CSS2 support)
" URL: https://github.com/vim-language-dept/css-syntax.vim
" Maintainer: Jay Sitter <jay@jaysitter.com>
-" Last Change: 2021 Oct 20
+" Last Change: 2024 Mar 2
" quit when a syntax file was already loaded
if !exists("main_syntax")
@@ -127,7 +127,7 @@ syn match cssColor contained "#\x\{8\}\>" contains=cssUnitDecorators
syn region cssURL contained matchgroup=cssFunctionName start="\<\(uri\|url\|local\|format\)\s*(" end=")" contains=cssStringQ,cssStringQQ oneline
syn region cssMathGroup contained matchgroup=cssMathParens start="(" end=")" containedin=cssFunction,cssMathGroup contains=cssCustomProp,cssValue.*,cssFunction,cssColor,cssStringQ,cssStringQQ oneline
-syn region cssFunction contained matchgroup=cssFunctionName start="\<\(var\|calc\)\s*(" end=")" contains=cssCustomProp,cssValue.*,cssFunction,cssColor,cssStringQ,cssStringQQ oneline
+syn region cssFunction contained matchgroup=cssFunctionName start="\<\(var\|calc\)\s*(" end=")" contains=cssCustomProp,cssValue.*,cssFunction,cssURL,cssColor,cssStringQ,cssStringQQ oneline
syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgb\|clip\|attr\|counter\|rect\|cubic-bezier\|steps\)\s*(" end=")" oneline contains=cssValueInteger,cssValueNumber,cssValueLength,cssFunctionComma
syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgba\|hsl\|hsla\|color-stop\|from\|to\)\s*(" end=")" oneline contains=cssColor,cssValueInteger,cssValueNumber,cssValueLength,cssFunctionComma,cssFunction
syn region cssFunction contained matchgroup=cssFunctionName start="\<\(linear-\|radial-\|conic-\)\=\gradient\s*(" end=")" oneline contains=cssColor,cssValueInteger,cssValueNumber,cssValueLength,cssFunction,cssGradientAttr,cssFunctionComma
@@ -176,6 +176,8 @@ syn keyword cssBackgroundAttr contained cover contain
syn match cssBorderProp contained "\<border\(-\(top\|right\|bottom\|left\)\)\=\(-\(width\|color\|style\)\)\=\>"
syn match cssBorderProp contained "\<border\(-\(top\|bottom\)-\(left\|right\)\)\=-radius\>"
+syn match cssBorderProp contained "\<border-\(inline\|block\)\(-\(start\|end\)\)\=\(-\(style\|width\|color\)\)\=\>"
+syn match cssBorderProp contained "\<border-\(start\|end\)-\(start\|end\)-radius\>"
syn match cssBorderProp contained "\<border-image\(-\(outset\|repeat\|slice\|source\|width\)\)\=\>"
syn match cssBorderProp contained "\<box-decoration-break\>"
syn match cssBorderProp contained "\<box-shadow\>"
@@ -195,6 +197,7 @@ syn keyword cssBorderAttr contained clone slice
syn match cssBoxProp contained "\<padding\(-\(top\|right\|bottom\|left\)\)\=\>"
syn match cssBoxProp contained "\<margin\(-\(top\|right\|bottom\|left\)\)\=\>"
+syn match cssBoxProp contained "\<\(margin\|padding\)\(-\(inline\|block\)\(-\(start\|end\)\)\)\=\>"
syn match cssBoxProp contained "\<overflow\(-\(x\|y\|style\)\)\=\>"
syn match cssBoxProp contained "\<rotation\(-point\)\=\>"
syn keyword cssBoxAttr contained visible hidden scroll auto
@@ -227,7 +230,7 @@ syn match cssFlexibleBoxAttr contained "\<space\(-\(between\|around\|evenly\)\)\
" CSS Fonts Module Level 3
" http://www.w3.org/TR/css-fonts-3/
-syn match cssFontProp contained "\<font\(-\(family\|\|feature-settings\|kerning\|language-override\|size\(-adjust\)\=\|stretch\|style\|synthesis\|variant\(-\(alternates\|caps\|east-asian\|ligatures\|numeric\|position\)\)\=\|weight\)\)\=\>"
+syn match cssFontProp contained "\<font\(-\(display\|family\|feature-settings\|kerning\|language-override\|size\(-adjust\)\=\|stretch\|style\|synthesis\|variant\(-\(alternates\|caps\|east-asian\|ligatures\|numeric\|position\)\)\=\|weight\)\)\=\>"
" font attributes
syn keyword cssFontAttr contained icon menu caption
@@ -248,6 +251,8 @@ syn keyword cssFontAttr contained italic oblique
syn keyword cssFontAttr contained weight style
" font-weight attributes
syn keyword cssFontAttr contained bold bolder lighter
+" font-display attributes
+syn keyword cssFontAttr contained auto block swap fallback optional
" TODO: font-variant-* attributes
"------------------------------------------------
@@ -282,7 +287,7 @@ syn match cssGeneratedContentAttr contained "\<\(no-\)\=\(open\|close\)-quote\>"
" https://www.w3.org/TR/css-grid-1/
syn match cssGridProp contained "\<grid\>"
syn match cssGridProp contained "\<grid-template\(-\(columns\|rows\|areas\)\)\=\>"
-syn match cssGridProp contained "\<grid-\(column\|row\)\(-\(start\|end\|gap\)\)\=\>"
+syn match cssGridProp contained "\<\(grid-\)\=\(column\|row\)\(-\(start\|end\|gap\)\)\=\>"
syn match cssGridProp contained "\<grid-\(area\|gap\)\>"
syn match cssGridProp contained "\<gap\>"
syn match cssGridProp contained "\<grid-auto-\(flow\|rows\|columns\)\>"
@@ -452,12 +457,12 @@ syn match cssAttrComma ","
" Pseudo class
" https://www.w3.org/TR/selectors-4/
syn match cssPseudoClass ":[A-Za-z0-9_-]*" contains=cssNoise,cssPseudoClassId,cssUnicodeEscape,cssVendor,cssPseudoClassFn
-syn keyword cssPseudoClassId contained link visited active hover before after left right any-link
-syn keyword cssPseudoClassId contained root empty target enabled disabled checked invalid default defined autofill fullscreen host indeterminate in-range modal optional out-of-range picture-in-picture placeholder-shown paused playing read-only read-write required scope
+syn keyword cssPseudoClassId contained link visited active hover before after left right
+syn keyword cssPseudoClassId contained root empty target enabled disabled checked invalid
syn match cssPseudoClassId contained "\<first-\(line\|letter\)\>"
syn match cssPseudoClassId contained "\<\(first\|last\|only\)-\(of-type\|child\)\>"
syn match cssPseudoClassId contained "\<focus\(-within\|-visible\)\=\>"
-syn region cssPseudoClassFn contained matchgroup=cssFunctionName start="\<\(where\|has\|host\|not\|is\|lang\|\(nth\|nth-last\)-\(of-type\|child\)\)(" end=")" contains=cssStringQ,cssStringQQ,cssTagName,cssAttributeSelector,cssClassName,cssIdentifier
+syn region cssPseudoClassFn contained matchgroup=cssFunctionName start="\<\(not\|is\|lang\|\(nth\|nth-last\)-\(of-type\|child\)\)(" end=")" contains=cssStringQ,cssStringQQ,cssTagName,cssAttributeSelector,cssClassName,cssIdentifier
" ------------------------------------
" Vendor specific properties
syn match cssPseudoClassId contained "\<selection\>"
diff --git a/runtime/syntax/cucumber.vim b/runtime/syntax/cucumber.vim
index f1ef2992ec..90fdbfaf4f 100644
--- a/runtime/syntax/cucumber.vim
+++ b/runtime/syntax/cucumber.vim
@@ -2,7 +2,7 @@
" Language: Cucumber
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
" Filenames: *.feature
-" Last Change: 2013 May 30
+" Last Change: 2023 Dec 28
if exists("b:current_syntax")
finish
@@ -14,60 +14,84 @@ syn case match
syn sync minlines=20
let g:cucumber_languages = {
- \"en": {"and": "And\\>", "background": "Background\\>", "but": "But\\>", "examples": "Scenarios\\>\\|Examples\\>", "feature": "Business Need\\>\\|Feature\\>\\|Ability\\>", "given": "Given\\>", "scenario": "Scenario\\>", "scenario_outline": "Scenario Template\\>\\|Scenario Outline\\>", "then": "Then\\>", "when": "When\\>"},
- \"ar": {"and": "\\%u0648\\>", "background": "\\%u0627\\%u0644\\%u062e\\%u0644\\%u0641\\%u064a\\%u0629\\>", "but": "\\%u0644\\%u0643\\%u0646\\>", "examples": "\\%u0627\\%u0645\\%u062b\\%u0644\\%u0629\\>", "feature": "\\%u062e\\%u0627\\%u0635\\%u064a\\%u0629\\>", "given": "\\%u0628\\%u0641\\%u0631\\%u0636\\>", "scenario": "\\%u0633\\%u064a\\%u0646\\%u0627\\%u0631\\%u064a\\%u0648\\>", "scenario_outline": "\\%u0633\\%u064a\\%u0646\\%u0627\\%u0631\\%u064a\\%u0648 \\%u0645\\%u062e\\%u0637\\%u0637\\>", "then": "\\%u0627\\%u0630\\%u0627\\%u064b\\>\\|\\%u062b\\%u0645\\>", "when": "\\%u0639\\%u0646\\%u062f\\%u0645\\%u0627\\>\\|\\%u0645\\%u062a\\%u0649\\>"},
- \"bg": {"and": "\\%u0418\\>", "background": "\\%u041f\\%u0440\\%u0435\\%u0434\\%u0438\\%u0441\\%u0442\\%u043e\\%u0440\\%u0438\\%u044f\\>", "but": "\\%u041d\\%u043e\\>", "examples": "\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440\\%u0438\\>", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u043e\\%u043d\\%u0430\\%u043b\\%u043d\\%u043e\\%u0441\\%u0442\\>", "given": "\\%u0414\\%u0430\\%u0434\\%u0435\\%u043d\\%u043e\\>", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439\\>", "scenario_outline": "\\%u0420\\%u0430\\%u043c\\%u043a\\%u0430 \\%u043d\\%u0430 \\%u0441\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439\\>", "then": "\\%u0422\\%u043e\\>", "when": "\\%u041a\\%u043e\\%u0433\\%u0430\\%u0442\\%u043e\\>"},
- \"bm": {"and": "Dan\\>", "background": "Latar Belakang\\>", "but": "Tetapi\\>", "examples": "Contoh \\>", "feature": "Fungsi\\>", "given": "Bagi\\>", "scenario": "Senario\\>", "scenario_outline": "Menggariskan Senario \\>", "then": "Kemudian\\>", "when": "Apabila\\>"},
- \"ca": {"and": "I\\>", "background": "Antecedents\\>\\|Rerefons\\>", "but": "Per\\%u00f2\\>", "examples": "Exemples\\>", "feature": "Caracter\\%u00edstica\\>\\|Funcionalitat\\>", "given": "At\\%u00e8s\\>\\|Donada\\>\\|Donat\\>\\|Atesa\\>", "scenario": "Escenari\\>", "scenario_outline": "Esquema de l'escenari\\>", "then": "Aleshores\\>\\|Cal\\>", "when": "Quan\\>"},
- \"cs": {"and": "A tak\\%u00e9\\>\\|A\\>", "background": "Pozad\\%u00ed\\>\\|Kontext\\>", "but": "Ale\\>", "examples": "P\\%u0159\\%u00edklady\\>", "feature": "Po\\%u017eadavek\\>", "given": "Za p\\%u0159edpokladu\\>\\|Pokud\\>", "scenario": "Sc\\%u00e9n\\%u00e1\\%u0159\\>", "scenario_outline": "N\\%u00e1\\%u010drt Sc\\%u00e9n\\%u00e1\\%u0159e\\>\\|Osnova sc\\%u00e9n\\%u00e1\\%u0159e\\>", "then": "Pak\\>", "when": "Kdy\\%u017e\\>"},
- \"cy-GB": {"and": "A\\>", "background": "Cefndir\\>", "but": "Ond\\>", "examples": "Enghreifftiau\\>", "feature": "Arwedd\\>", "given": "Anrhegedig a\\>", "scenario": "Scenario\\>", "scenario_outline": "Scenario Amlinellol\\>", "then": "Yna\\>", "when": "Pryd\\>"},
- \"da": {"and": "Og\\>", "background": "Baggrund\\>", "but": "Men\\>", "examples": "Eksempler\\>", "feature": "Egenskab\\>", "given": "Givet\\>", "scenario": "Scenarie\\>", "scenario_outline": "Abstrakt Scenario\\>", "then": "S\\%u00e5\\>", "when": "N\\%u00e5r\\>"},
- \"de": {"and": "Und\\>", "background": "Grundlage\\>", "but": "Aber\\>", "examples": "Beispiele\\>", "feature": "Funktionalit\\%u00e4t\\>", "given": "Gegeben sei\\>\\|Angenommen\\>", "scenario": "Szenario\\>", "scenario_outline": "Szenariogrundriss\\>", "then": "Dann\\>", "when": "Wenn\\>"},
- \"el": {"and": "\\%u039a\\%u03b1\\%u03b9\\>", "background": "\\%u03a5\\%u03c0\\%u03cc\\%u03b2\\%u03b1\\%u03b8\\%u03c1\\%u03bf\\>", "but": "\\%u0391\\%u03bb\\%u03bb\\%u03ac\\>", "examples": "\\%u03a0\\%u03b1\\%u03c1\\%u03b1\\%u03b4\\%u03b5\\%u03af\\%u03b3\\%u03bc\\%u03b1\\%u03c4\\%u03b1\\>\\|\\%u03a3\\%u03b5\\%u03bd\\%u03ac\\%u03c1\\%u03b9\\%u03b1\\>", "feature": "\\%u0394\\%u03c5\\%u03bd\\%u03b1\\%u03c4\\%u03cc\\%u03c4\\%u03b7\\%u03c4\\%u03b1\\>\\|\\%u039b\\%u03b5\\%u03b9\\%u03c4\\%u03bf\\%u03c5\\%u03c1\\%u03b3\\%u03af\\%u03b1\\>", "given": "\\%u0394\\%u03b5\\%u03b4\\%u03bf\\%u03bc\\%u03ad\\%u03bd\\%u03bf\\%u03c5 \\%u03cc\\%u03c4\\%u03b9\\>\\|\\%u0394\\%u03b5\\%u03b4\\%u03bf\\%u03bc\\%u03ad\\%u03bd\\%u03bf\\%u03c5\\>", "scenario": "\\%u03a3\\%u03b5\\%u03bd\\%u03ac\\%u03c1\\%u03b9\\%u03bf\\>", "scenario_outline": "\\%u03a0\\%u03b5\\%u03c1\\%u03b9\\%u03b3\\%u03c1\\%u03b1\\%u03c6\\%u03ae \\%u03a3\\%u03b5\\%u03bd\\%u03b1\\%u03c1\\%u03af\\%u03bf\\%u03c5\\>", "then": "\\%u03a4\\%u03cc\\%u03c4\\%u03b5\\>", "when": "\\%u038c\\%u03c4\\%u03b1\\%u03bd\\>"},
- \"en-Scouse": {"and": "An\\>", "background": "Dis is what went down\\>", "but": "Buh\\>", "examples": "Examples\\>", "feature": "Feature\\>", "given": "Youse know when youse got\\>\\|Givun\\>", "scenario": "The thing of it is\\>", "scenario_outline": "Wharrimean is\\>", "then": "Den youse gotta\\>\\|Dun\\>", "when": "Youse know like when\\>\\|Wun\\>"},
- \"en-au": {"and": "Too right\\>", "background": "First off\\>", "but": "Yeah nah\\>", "examples": "You'll wanna\\>", "feature": "Pretty much\\>", "given": "Y'know\\>", "scenario": "Awww, look mate\\>", "scenario_outline": "Reckon it's like\\>", "then": "But at the end of the day I reckon\\>", "when": "It's just unbelievable\\>"},
- \"en-lol": {"and": "AN\\>", "background": "B4\\>", "but": "BUT\\>", "examples": "EXAMPLZ\\>", "feature": "OH HAI\\>", "given": "I CAN HAZ\\>", "scenario": "MISHUN\\>", "scenario_outline": "MISHUN SRSLY\\>", "then": "DEN\\>", "when": "WEN\\>"},
- \"en-old": {"and": "Ond\\>\\|7\\>", "background": "\\%u00c6r\\>\\|Aer\\>", "but": "Ac\\>", "examples": "Se \\%u00f0e\\>\\|Se \\%u00fee\\>\\|Se the\\>", "feature": "Hw\\%u00e6t\\>\\|Hwaet\\>", "given": "\\%u00d0urh\\>\\|\\%u00deurh\\>\\|Thurh\\>", "scenario": "Swa\\>", "scenario_outline": "Swa hw\\%u00e6r swa\\>\\|Swa hwaer swa\\>", "then": "\\%u00d0a \\%u00f0e\\>\\|\\%u00dea \\%u00fee\\>\\|\\%u00dea\\>\\|\\%u00d0a\\>\\|Tha the\\>\\|Tha\\>", "when": "\\%u00d0a\\>\\|\\%u00dea\\>\\|Tha\\>"},
- \"en-pirate": {"and": "Aye\\>", "background": "Yo-ho-ho\\>", "but": "Avast!\\>", "examples": "Dead men tell no tales\\>", "feature": "Ahoy matey!\\>", "given": "Gangway!\\>", "scenario": "Heave to\\>", "scenario_outline": "Shiver me timbers\\>", "then": "Let go and haul\\>", "when": "Blimey!\\>"},
- \"en-tx": {"and": "And y'all\\>", "background": "Background\\>", "but": "But y'all\\>", "examples": "Examples\\>", "feature": "Feature\\>", "given": "Given y'all\\>", "scenario": "Scenario\\>", "scenario_outline": "All y'all\\>", "then": "Then y'all\\>", "when": "When y'all\\>"},
- \"eo": {"and": "Kaj\\>", "background": "Fono\\>", "but": "Sed\\>", "examples": "Ekzemploj\\>", "feature": "Trajto\\>", "given": "Donita\\%u0135o\\>", "scenario": "Scenaro\\>", "scenario_outline": "Konturo de la scenaro\\>", "then": "Do\\>", "when": "Se\\>"},
- \"es": {"and": "Y\\>", "background": "Antecedentes\\>", "but": "Pero\\>", "examples": "Ejemplos\\>", "feature": "Caracter\\%u00edstica\\>", "given": "Dadas\\>\\|Dados\\>\\|Dada\\>\\|Dado\\>", "scenario": "Escenario\\>", "scenario_outline": "Esquema del escenario\\>", "then": "Entonces\\>", "when": "Cuando\\>"},
- \"et": {"and": "Ja\\>", "background": "Taust\\>", "but": "Kuid\\>", "examples": "Juhtumid\\>", "feature": "Omadus\\>", "given": "Eeldades\\>", "scenario": "Stsenaarium\\>", "scenario_outline": "Raamstsenaarium\\>", "then": "Siis\\>", "when": "Kui\\>"},
- \"fa": {"and": "\\%u0648\\>", "background": "\\%u0632\\%u0645\\%u06cc\\%u0646\\%u0647\\>", "but": "\\%u0627\\%u0645\\%u0627\\>", "examples": "\\%u0646\\%u0645\\%u0648\\%u0646\\%u0647 \\%u0647\\%u0627\\>", "feature": "\\%u0648\\%u0650\\%u06cc\\%u0698\\%u06af\\%u06cc\\>", "given": "\\%u0628\\%u0627 \\%u0641\\%u0631\\%u0636\\>", "scenario": "\\%u0633\\%u0646\\%u0627\\%u0631\\%u06cc\\%u0648\\>", "scenario_outline": "\\%u0627\\%u0644\\%u06af\\%u0648\\%u06cc \\%u0633\\%u0646\\%u0627\\%u0631\\%u06cc\\%u0648\\>", "then": "\\%u0622\\%u0646\\%u06af\\%u0627\\%u0647\\>", "when": "\\%u0647\\%u0646\\%u06af\\%u0627\\%u0645\\%u06cc\\>"},
- \"fi": {"and": "Ja\\>", "background": "Tausta\\>", "but": "Mutta\\>", "examples": "Tapaukset\\>", "feature": "Ominaisuus\\>", "given": "Oletetaan\\>", "scenario": "Tapaus\\>", "scenario_outline": "Tapausaihio\\>", "then": "Niin\\>", "when": "Kun\\>"},
- \"fr": {"and": "Et\\>", "background": "Contexte\\>", "but": "Mais\\>", "examples": "Exemples\\>", "feature": "Fonctionnalit\\%u00e9\\>", "given": "\\%u00c9tant donn\\%u00e9es\\>\\|\\%u00c9tant donn\\%u00e9s\\>\\|\\%u00c9tant donn\\%u00e9e\\>\\|\\%u00c9tant donn\\%u00e9\\>\\|Etant donn\\%u00e9es\\>\\|Etant donn\\%u00e9s\\>\\|Etant donn\\%u00e9e\\>\\|Etant donn\\%u00e9\\>\\|Soit\\>", "scenario": "Sc\\%u00e9nario\\>", "scenario_outline": "Plan du sc\\%u00e9nario\\>\\|Plan du Sc\\%u00e9nario\\>", "then": "Alors\\>", "when": "Lorsqu'\\|Lorsque\\>\\|Quand\\>"},
- \"gl": {"and": "E\\>", "background": "Contexto\\>", "but": "Mais\\>\\|Pero\\>", "examples": "Exemplos\\>", "feature": "Caracter\\%u00edstica\\>", "given": "Dadas\\>\\|Dados\\>\\|Dada\\>\\|Dado\\>", "scenario": "Escenario\\>", "scenario_outline": "Esbozo do escenario\\>", "then": "Ent\\%u00f3n\\>\\|Logo\\>", "when": "Cando\\>"},
- \"he": {"and": "\\%u05d5\\%u05d2\\%u05dd\\>", "background": "\\%u05e8\\%u05e7\\%u05e2\\>", "but": "\\%u05d0\\%u05d1\\%u05dc\\>", "examples": "\\%u05d3\\%u05d5\\%u05d2\\%u05de\\%u05d0\\%u05d5\\%u05ea\\>", "feature": "\\%u05ea\\%u05db\\%u05d5\\%u05e0\\%u05d4\\>", "given": "\\%u05d1\\%u05d4\\%u05d9\\%u05e0\\%u05ea\\%u05df\\>", "scenario": "\\%u05ea\\%u05e8\\%u05d7\\%u05d9\\%u05e9\\>", "scenario_outline": "\\%u05ea\\%u05d1\\%u05e0\\%u05d9\\%u05ea \\%u05ea\\%u05e8\\%u05d7\\%u05d9\\%u05e9\\>", "then": "\\%u05d0\\%u05d6\\%u05d9\\>\\|\\%u05d0\\%u05d6\\>", "when": "\\%u05db\\%u05d0\\%u05e9\\%u05e8\\>"},
- \"hi": {"and": "\\%u0924\\%u0925\\%u093e\\>\\|\\%u0914\\%u0930\\>", "background": "\\%u092a\\%u0943\\%u0937\\%u094d\\%u0920\\%u092d\\%u0942\\%u092e\\%u093f\\>", "but": "\\%u092a\\%u0930\\>", "examples": "\\%u0909\\%u0926\\%u093e\\%u0939\\%u0930\\%u0923\\>", "feature": "\\%u0930\\%u0942\\%u092a \\%u0932\\%u0947\\%u0916\\>", "given": "\\%u091a\\%u0942\\%u0902\\%u0915\\%u093f\\>\\|\\%u092f\\%u0926\\%u093f\\>\\|\\%u0905\\%u0917\\%u0930\\>", "scenario": "\\%u092a\\%u0930\\%u093f\\%u0926\\%u0943\\%u0936\\%u094d\\%u092f\\>", "scenario_outline": "\\%u092a\\%u0930\\%u093f\\%u0926\\%u0943\\%u0936\\%u094d\\%u092f \\%u0930\\%u0942\\%u092a\\%u0930\\%u0947\\%u0916\\%u093e\\>", "then": "\\%u0924\\%u092c\\>", "when": "\\%u091c\\%u092c\\>"},
- \"hr": {"and": "I\\>", "background": "Pozadina\\>", "but": "Ali\\>", "examples": "Scenariji\\>\\|Primjeri\\>", "feature": "Mogu\\%u0107nost\\>\\|Mogucnost\\>\\|Osobina\\>", "given": "Zadano\\>\\|Zadani\\>\\|Zadan\\>", "scenario": "Scenarij\\>", "scenario_outline": "Koncept\\>\\|Skica\\>", "then": "Onda\\>", "when": "Kada\\>\\|Kad\\>"},
- \"hu": {"and": "\\%u00c9s\\>", "background": "H\\%u00e1tt\\%u00e9r\\>", "but": "De\\>", "examples": "P\\%u00e9ld\\%u00e1k\\>", "feature": "Jellemz\\%u0151\\>", "given": "Amennyiben\\>\\|Adott\\>", "scenario": "Forgat\\%u00f3k\\%u00f6nyv\\>", "scenario_outline": "Forgat\\%u00f3k\\%u00f6nyv v\\%u00e1zlat\\>", "then": "Akkor\\>", "when": "Amikor\\>\\|Majd\\>\\|Ha\\>"},
- \"id": {"and": "Dan\\>", "background": "Dasar\\>", "but": "Tapi\\>", "examples": "Contoh\\>", "feature": "Fitur\\>", "given": "Dengan\\>", "scenario": "Skenario\\>", "scenario_outline": "Skenario konsep\\>", "then": "Maka\\>", "when": "Ketika\\>"},
- \"is": {"and": "Og\\>", "background": "Bakgrunnur\\>", "but": "En\\>", "examples": "Atbur\\%u00f0ar\\%u00e1sir\\>\\|D\\%u00e6mi\\>", "feature": "Eiginleiki\\>", "given": "Ef\\>", "scenario": "Atbur\\%u00f0ar\\%u00e1s\\>", "scenario_outline": "L\\%u00fdsing Atbur\\%u00f0ar\\%u00e1sar\\>\\|L\\%u00fdsing D\\%u00e6ma\\>", "then": "\\%u00de\\%u00e1\\>", "when": "\\%u00deegar\\>"},
- \"it": {"and": "E\\>", "background": "Contesto\\>", "but": "Ma\\>", "examples": "Esempi\\>", "feature": "Funzionalit\\%u00e0\\>", "given": "Dato\\>\\|Data\\>\\|Dati\\>\\|Date\\>", "scenario": "Scenario\\>", "scenario_outline": "Schema dello scenario\\>", "then": "Allora\\>", "when": "Quando\\>"},
- \"ja": {"and": "\\%u304b\\%u3064", "background": "\\%u80cc\\%u666f\\>", "but": "\\%u3057\\%u304b\\%u3057\\|\\%u305f\\%u3060\\%u3057\\|\\%u4f46\\%u3057", "examples": "\\%u30b5\\%u30f3\\%u30d7\\%u30eb\\>\\|\\%u4f8b\\>", "feature": "\\%u30d5\\%u30a3\\%u30fc\\%u30c1\\%u30e3\\>\\|\\%u6a5f\\%u80fd\\>", "given": "\\%u524d\\%u63d0", "scenario": "\\%u30b7\\%u30ca\\%u30ea\\%u30aa\\>", "scenario_outline": "\\%u30b7\\%u30ca\\%u30ea\\%u30aa\\%u30a2\\%u30a6\\%u30c8\\%u30e9\\%u30a4\\%u30f3\\>\\|\\%u30b7\\%u30ca\\%u30ea\\%u30aa\\%u30c6\\%u30f3\\%u30d7\\%u30ec\\%u30fc\\%u30c8\\>\\|\\%u30b7\\%u30ca\\%u30ea\\%u30aa\\%u30c6\\%u30f3\\%u30d7\\%u30ec\\>\\|\\%u30c6\\%u30f3\\%u30d7\\%u30ec\\>", "then": "\\%u306a\\%u3089\\%u3070", "when": "\\%u3082\\%u3057"},
- \"ko": {"and": "\\%uadf8\\%ub9ac\\%uace0", "background": "\\%ubc30\\%uacbd\\>", "but": "\\%ud558\\%uc9c0\\%ub9cc\\|\\%ub2e8", "examples": "\\%uc608\\>", "feature": "\\%uae30\\%ub2a5\\>", "given": "\\%uc870\\%uac74\\|\\%uba3c\\%uc800", "scenario": "\\%uc2dc\\%ub098\\%ub9ac\\%uc624\\>", "scenario_outline": "\\%uc2dc\\%ub098\\%ub9ac\\%uc624 \\%uac1c\\%uc694\\>", "then": "\\%uadf8\\%ub7ec\\%uba74", "when": "\\%ub9cc\\%uc77c\\|\\%ub9cc\\%uc57d"},
- \"lt": {"and": "Ir\\>", "background": "Kontekstas\\>", "but": "Bet\\>", "examples": "Pavyzd\\%u017eiai\\>\\|Scenarijai\\>\\|Variantai\\>", "feature": "Savyb\\%u0117\\>", "given": "Duota\\>", "scenario": "Scenarijus\\>", "scenario_outline": "Scenarijaus \\%u0161ablonas\\>", "then": "Tada\\>", "when": "Kai\\>"},
- \"lu": {"and": "an\\>\\|a\\>", "background": "Hannergrond\\>", "but": "m\\%u00e4\\>\\|awer\\>", "examples": "Beispiller\\>", "feature": "Funktionalit\\%u00e9it\\>", "given": "ugeholl\\>", "scenario": "Szenario\\>", "scenario_outline": "Plang vum Szenario\\>", "then": "dann\\>", "when": "wann\\>"},
- \"lv": {"and": "Un\\>", "background": "Situ\\%u0101cija\\>\\|Konteksts\\>", "but": "Bet\\>", "examples": "Piem\\%u0113ri\\>\\|Paraugs\\>", "feature": "Funkcionalit\\%u0101te\\>\\|F\\%u012b\\%u010da\\>", "given": "Kad\\>", "scenario": "Scen\\%u0101rijs\\>", "scenario_outline": "Scen\\%u0101rijs p\\%u0113c parauga\\>", "then": "Tad\\>", "when": "Ja\\>"},
- \"nl": {"and": "En\\>", "background": "Achtergrond\\>", "but": "Maar\\>", "examples": "Voorbeelden\\>", "feature": "Functionaliteit\\>", "given": "Gegeven\\>\\|Stel\\>", "scenario": "Scenario\\>", "scenario_outline": "Abstract Scenario\\>", "then": "Dan\\>", "when": "Als\\>"},
- \"no": {"and": "Og\\>", "background": "Bakgrunn\\>", "but": "Men\\>", "examples": "Eksempler\\>", "feature": "Egenskap\\>", "given": "Gitt\\>", "scenario": "Scenario\\>", "scenario_outline": "Abstrakt Scenario\\>\\|Scenariomal\\>", "then": "S\\%u00e5\\>", "when": "N\\%u00e5r\\>"},
- \"pl": {"and": "Oraz\\>\\|I\\>", "background": "Za\\%u0142o\\%u017cenia\\>", "but": "Ale\\>", "examples": "Przyk\\%u0142ady\\>", "feature": "W\\%u0142a\\%u015bciwo\\%u015b\\%u0107\\>\\|Potrzeba biznesowa\\>\\|Funkcja\\>\\|Aspekt\\>", "given": "Zak\\%u0142adaj\\%u0105c\\>\\|Maj\\%u0105c\\>", "scenario": "Scenariusz\\>", "scenario_outline": "Szablon scenariusza\\>", "then": "Wtedy\\>", "when": "Je\\%u017celi\\>\\|Je\\%u015bli\\>\\|Kiedy\\>\\|Gdy\\>"},
- \"pt": {"and": "E\\>", "background": "Cen\\%u00e1rio de Fundo\\>\\|Cenario de Fundo\\>\\|Contexto\\>\\|Fundo\\>", "but": "Mas\\>", "examples": "Cen\\%u00e1rios\\>\\|Exemplos\\>\\|Cenarios\\>", "feature": "Caracter\\%u00edstica\\>\\|Funcionalidade\\>\\|Caracteristica\\>", "given": "Dadas\\>\\|Dados\\>\\|Dada\\>\\|Dado\\>", "scenario": "Cen\\%u00e1rio\\>\\|Cenario\\>", "scenario_outline": "Delinea\\%u00e7\\%u00e3o do Cen\\%u00e1rio\\>\\|Esquema do Cen\\%u00e1rio\\>\\|Delineacao do Cenario\\>\\|Esquema do Cenario\\>", "then": "Ent\\%u00e3o\\>\\|Entao\\>", "when": "Quando\\>"},
- \"ro": {"and": "\\%u015ei\\>\\|\\%u0218i\\>\\|Si\\>", "background": "Context\\>", "but": "Dar\\>", "examples": "Exemple\\>", "feature": "Func\\%u0163ionalitate\\>\\|Func\\%u021bionalitate\\>\\|Functionalitate\\>", "given": "Da\\%u0163i fiind\\>\\|Da\\%u021bi fiind\\>\\|Dati fiind\\>\\|Date fiind\\>\\|Dat fiind\\>", "scenario": "Scenariu\\>", "scenario_outline": "Structur\\%u0103 scenariu\\>\\|Structura scenariu\\>", "then": "Atunci\\>", "when": "C\\%u00e2nd\\>\\|Cand\\>"},
- \"ru": {"and": "\\%u041a \\%u0442\\%u043e\\%u043c\\%u0443 \\%u0436\\%u0435\\>\\|\\%u0422\\%u0430\\%u043a\\%u0436\\%u0435\\>\\|\\%u0418\\>", "background": "\\%u041f\\%u0440\\%u0435\\%u0434\\%u044b\\%u0441\\%u0442\\%u043e\\%u0440\\%u0438\\%u044f\\>\\|\\%u041a\\%u043e\\%u043d\\%u0442\\%u0435\\%u043a\\%u0441\\%u0442\\>", "but": "\\%u041d\\%u043e\\>\\|\\%u0410\\>", "examples": "\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440\\%u044b\\>", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u043e\\%u043d\\%u0430\\%u043b\\>\\|\\%u0421\\%u0432\\%u043e\\%u0439\\%u0441\\%u0442\\%u0432\\%u043e\\>\\|\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u044f\\>", "given": "\\%u0414\\%u043e\\%u043f\\%u0443\\%u0441\\%u0442\\%u0438\\%u043c\\>\\|\\%u041f\\%u0443\\%u0441\\%u0442\\%u044c\\>\\|\\%u0414\\%u0430\\%u043d\\%u043e\\>", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439\\>", "scenario_outline": "\\%u0421\\%u0442\\%u0440\\%u0443\\%u043a\\%u0442\\%u0443\\%u0440\\%u0430 \\%u0441\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u044f\\>", "then": "\\%u0422\\%u043e\\%u0433\\%u0434\\%u0430\\>\\|\\%u0422\\%u043e\\>", "when": "\\%u041a\\%u043e\\%u0433\\%u0434\\%u0430\\>\\|\\%u0415\\%u0441\\%u043b\\%u0438\\>"},
- \"sk": {"and": "A z\\%u00e1rove\\%u0148\\>\\|A taktie\\%u017e\\>\\|A tie\\%u017e\\>\\|A\\>", "background": "Pozadie\\>", "but": "Ale\\>", "examples": "Pr\\%u00edklady\\>", "feature": "Po\\%u017eiadavka\\>\\|Vlastnos\\%u0165\\>\\|Funkcia\\>", "given": "Za predpokladu\\>\\|Pokia\\%u013e\\>", "scenario": "Scen\\%u00e1r\\>", "scenario_outline": "N\\%u00e1\\%u010drt Scen\\%u00e1ru\\>\\|N\\%u00e1\\%u010drt Scen\\%u00e1ra\\>\\|Osnova Scen\\%u00e1ra\\>", "then": "Potom\\>\\|Tak\\>", "when": "Ke\\%u010f\\>\\|Ak\\>"},
- \"sr-Cyrl": {"and": "\\%u0418\\>", "background": "\\%u041a\\%u043e\\%u043d\\%u0442\\%u0435\\%u043a\\%u0441\\%u0442\\>\\|\\%u041f\\%u043e\\%u0437\\%u0430\\%u0434\\%u0438\\%u043d\\%u0430\\>\\|\\%u041e\\%u0441\\%u043d\\%u043e\\%u0432\\%u0430\\>", "but": "\\%u0410\\%u043b\\%u0438\\>", "examples": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0458\\%u0438\\>\\|\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440\\%u0438\\>", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u043e\\%u043d\\%u0430\\%u043b\\%u043d\\%u043e\\%u0441\\%u0442\\>\\|\\%u041c\\%u043e\\%u0433\\%u0443\\%u045b\\%u043d\\%u043e\\%u0441\\%u0442\\>\\|\\%u041e\\%u0441\\%u043e\\%u0431\\%u0438\\%u043d\\%u0430\\>", "given": "\\%u0417\\%u0430\\%u0434\\%u0430\\%u0442\\%u043e\\>\\|\\%u0417\\%u0430\\%u0434\\%u0430\\%u0442\\%u0435\\>\\|\\%u0417\\%u0430\\%u0434\\%u0430\\%u0442\\%u0438\\>", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u043e\\>\\|\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440\\>", "scenario_outline": "\\%u0421\\%u0442\\%u0440\\%u0443\\%u043a\\%u0442\\%u0443\\%u0440\\%u0430 \\%u0441\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0458\\%u0430\\>\\|\\%u041a\\%u043e\\%u043d\\%u0446\\%u0435\\%u043f\\%u0442\\>\\|\\%u0421\\%u043a\\%u0438\\%u0446\\%u0430\\>", "then": "\\%u041e\\%u043d\\%u0434\\%u0430\\>", "when": "\\%u041a\\%u0430\\%u0434\\%u0430\\>\\|\\%u041a\\%u0430\\%u0434\\>"},
- \"sr-Latn": {"and": "I\\>", "background": "Kontekst\\>\\|Pozadina\\>\\|Osnova\\>", "but": "Ali\\>", "examples": "Scenariji\\>\\|Primeri\\>", "feature": "Mogu\\%u0107nost\\>\\|Funkcionalnost\\>\\|Mogucnost\\>\\|Osobina\\>", "given": "Zadato\\>\\|Zadate\\>\\|Zatati\\>", "scenario": "Scenario\\>\\|Primer\\>", "scenario_outline": "Struktura scenarija\\>\\|Koncept\\>\\|Skica\\>", "then": "Onda\\>", "when": "Kada\\>\\|Kad\\>"},
- \"sv": {"and": "Och\\>", "background": "Bakgrund\\>", "but": "Men\\>", "examples": "Exempel\\>", "feature": "Egenskap\\>", "given": "Givet\\>", "scenario": "Scenario\\>", "scenario_outline": "Abstrakt Scenario\\>\\|Scenariomall\\>", "then": "S\\%u00e5\\>", "when": "N\\%u00e4r\\>"},
- \"th": {"and": "\\%u0e41\\%u0e25\\%u0e30\\>", "background": "\\%u0e41\\%u0e19\\%u0e27\\%u0e04\\%u0e34\\%u0e14\\>", "but": "\\%u0e41\\%u0e15\\%u0e48\\>", "examples": "\\%u0e0a\\%u0e38\\%u0e14\\%u0e02\\%u0e2d\\%u0e07\\%u0e40\\%u0e2b\\%u0e15\\%u0e38\\%u0e01\\%u0e32\\%u0e23\\%u0e13\\%u0e4c\\>\\|\\%u0e0a\\%u0e38\\%u0e14\\%u0e02\\%u0e2d\\%u0e07\\%u0e15\\%u0e31\\%u0e27\\%u0e2d\\%u0e22\\%u0e48\\%u0e32\\%u0e07\\>", "feature": "\\%u0e04\\%u0e27\\%u0e32\\%u0e21\\%u0e15\\%u0e49\\%u0e2d\\%u0e07\\%u0e01\\%u0e32\\%u0e23\\%u0e17\\%u0e32\\%u0e07\\%u0e18\\%u0e38\\%u0e23\\%u0e01\\%u0e34\\%u0e08\\>\\|\\%u0e04\\%u0e27\\%u0e32\\%u0e21\\%u0e2a\\%u0e32\\%u0e21\\%u0e32\\%u0e23\\%u0e16\\>\\|\\%u0e42\\%u0e04\\%u0e23\\%u0e07\\%u0e2b\\%u0e25\\%u0e31\\%u0e01\\>", "given": "\\%u0e01\\%u0e33\\%u0e2b\\%u0e19\\%u0e14\\%u0e43\\%u0e2b\\%u0e49\\>", "scenario": "\\%u0e40\\%u0e2b\\%u0e15\\%u0e38\\%u0e01\\%u0e32\\%u0e23\\%u0e13\\%u0e4c\\>", "scenario_outline": "\\%u0e42\\%u0e04\\%u0e23\\%u0e07\\%u0e2a\\%u0e23\\%u0e49\\%u0e32\\%u0e07\\%u0e02\\%u0e2d\\%u0e07\\%u0e40\\%u0e2b\\%u0e15\\%u0e38\\%u0e01\\%u0e32\\%u0e23\\%u0e13\\%u0e4c\\>\\|\\%u0e2a\\%u0e23\\%u0e38\\%u0e1b\\%u0e40\\%u0e2b\\%u0e15\\%u0e38\\%u0e01\\%u0e32\\%u0e23\\%u0e13\\%u0e4c\\>", "then": "\\%u0e14\\%u0e31\\%u0e07\\%u0e19\\%u0e31\\%u0e49\\%u0e19\\>", "when": "\\%u0e40\\%u0e21\\%u0e37\\%u0e48\\%u0e2d\\>"},
- \"tl": {"and": "\\%u0c2e\\%u0c30\\%u0c3f\\%u0c2f\\%u0c41\\>", "background": "\\%u0c28\\%u0c47\\%u0c2a\\%u0c25\\%u0c4d\\%u0c2f\\%u0c02\\>", "but": "\\%u0c15\\%u0c3e\\%u0c28\\%u0c3f\\>", "examples": "\\%u0c09\\%u0c26\\%u0c3e\\%u0c39\\%u0c30\\%u0c23\\%u0c32\\%u0c41\\>", "feature": "\\%u0c17\\%u0c41\\%u0c23\\%u0c2e\\%u0c41\\>", "given": "\\%u0c1a\\%u0c46\\%u0c2a\\%u0c4d\\%u0c2a\\%u0c2c\\%u0c21\\%u0c3f\\%u0c28\\%u0c26\\%u0c3f\\>", "scenario": "\\%u0c38\\%u0c28\\%u0c4d\\%u0c28\\%u0c3f\\%u0c35\\%u0c47\\%u0c36\\%u0c02\\>", "scenario_outline": "\\%u0c15\\%u0c25\\%u0c28\\%u0c02\\>", "then": "\\%u0c05\\%u0c2a\\%u0c4d\\%u0c2a\\%u0c41\\%u0c21\\%u0c41\\>", "when": "\\%u0c08 \\%u0c2a\\%u0c30\\%u0c3f\\%u0c38\\%u0c4d\\%u0c25\\%u0c3f\\%u0c24\\%u0c3f\\%u0c32\\%u0c4b\\>"},
- \"tr": {"and": "Ve\\>", "background": "Ge\\%u00e7mi\\%u015f\\>", "but": "Fakat\\>\\|Ama\\>", "examples": "\\%u00d6rnekler\\>", "feature": "\\%u00d6zellik\\>", "given": "Diyelim ki\\>", "scenario": "Senaryo\\>", "scenario_outline": "Senaryo tasla\\%u011f\\%u0131\\>", "then": "O zaman\\>", "when": "E\\%u011fer ki\\>"},
- \"tt": {"and": "\\%u04ba\\%u04d9\\%u043c\\>\\|\\%u0412\\%u04d9\\>", "background": "\\%u041a\\%u0435\\%u0440\\%u0435\\%u0448\\>", "but": "\\%u041b\\%u04d9\\%u043a\\%u0438\\%u043d\\>\\|\\%u04d8\\%u043c\\%u043c\\%u0430\\>", "examples": "\\%u04ae\\%u0440\\%u043d\\%u04d9\\%u043a\\%u043b\\%u04d9\\%u0440\\>\\|\\%u041c\\%u0438\\%u0441\\%u0430\\%u043b\\%u043b\\%u0430\\%u0440\\>", "feature": "\\%u04ae\\%u0437\\%u0435\\%u043d\\%u0447\\%u04d9\\%u043b\\%u0435\\%u043a\\%u043b\\%u0435\\%u043b\\%u0435\\%u043a\\>\\|\\%u041c\\%u04e9\\%u043c\\%u043a\\%u0438\\%u043d\\%u043b\\%u0435\\%u043a\\>", "given": "\\%u04d8\\%u0439\\%u0442\\%u0438\\%u043a\\>", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439\\>", "scenario_outline": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439\\%u043d\\%u044b\\%u04a3 \\%u0442\\%u04e9\\%u0437\\%u0435\\%u043b\\%u0435\\%u0448\\%u0435\\>", "then": "\\%u041d\\%u04d9\\%u0442\\%u0438\\%u0497\\%u04d9\\%u0434\\%u04d9\\>", "when": "\\%u04d8\\%u0433\\%u04d9\\%u0440\\>"},
- \"uk": {"and": "\\%u0410 \\%u0442\\%u0430\\%u043a\\%u043e\\%u0436\\>\\|\\%u0422\\%u0430\\>\\|\\%u0406\\>", "background": "\\%u041f\\%u0435\\%u0440\\%u0435\\%u0434\\%u0443\\%u043c\\%u043e\\%u0432\\%u0430\\>", "but": "\\%u0410\\%u043b\\%u0435\\>", "examples": "\\%u041f\\%u0440\\%u0438\\%u043a\\%u043b\\%u0430\\%u0434\\%u0438\\>", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0456\\%u043e\\%u043d\\%u0430\\%u043b\\>", "given": "\\%u041f\\%u0440\\%u0438\\%u043f\\%u0443\\%u0441\\%u0442\\%u0438\\%u043c\\%u043e, \\%u0449\\%u043e\\>\\|\\%u041f\\%u0440\\%u0438\\%u043f\\%u0443\\%u0441\\%u0442\\%u0438\\%u043c\\%u043e\\>\\|\\%u041d\\%u0435\\%u0445\\%u0430\\%u0439\\>\\|\\%u0414\\%u0430\\%u043d\\%u043e\\>", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0456\\%u0439\\>", "scenario_outline": "\\%u0421\\%u0442\\%u0440\\%u0443\\%u043a\\%u0442\\%u0443\\%u0440\\%u0430 \\%u0441\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0456\\%u044e\\>", "then": "\\%u0422\\%u043e\\%u0434\\%u0456\\>\\|\\%u0422\\%u043e\\>", "when": "\\%u042f\\%u043a\\%u0449\\%u043e\\>\\|\\%u041a\\%u043e\\%u043b\\%u0438\\>"},
- \"uz": {"and": "\\%u0412\\%u0430\\>", "background": "\\%u0422\\%u0430\\%u0440\\%u0438\\%u0445\\>", "but": "\\%u041b\\%u0435\\%u043a\\%u0438\\%u043d\\>\\|\\%u0411\\%u0438\\%u0440\\%u043e\\%u043a\\>\\|\\%u0410\\%u043c\\%u043c\\%u043e\\>", "examples": "\\%u041c\\%u0438\\%u0441\\%u043e\\%u043b\\%u043b\\%u0430\\%u0440\\>", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u043e\\%u043d\\%u0430\\%u043b\\>", "given": "\\%u0410\\%u0433\\%u0430\\%u0440\\>", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439\\>", "scenario_outline": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439 \\%u0441\\%u0442\\%u0440\\%u0443\\%u043a\\%u0442\\%u0443\\%u0440\\%u0430\\%u0441\\%u0438\\>", "then": "\\%u0423\\%u043d\\%u0434\\%u0430\\>", "when": "\\%u0410\\%u0433\\%u0430\\%u0440\\>"},
- \"vi": {"and": "V\\%u00e0\\>", "background": "B\\%u1ed1i c\\%u1ea3nh\\>", "but": "Nh\\%u01b0ng\\>", "examples": "D\\%u1eef li\\%u1ec7u\\>", "feature": "T\\%u00ednh n\\%u0103ng\\>", "given": "Bi\\%u1ebft\\>\\|Cho\\>", "scenario": "T\\%u00ecnh hu\\%u1ed1ng\\>\\|K\\%u1ecbch b\\%u1ea3n\\>", "scenario_outline": "Khung t\\%u00ecnh hu\\%u1ed1ng\\>\\|Khung k\\%u1ecbch b\\%u1ea3n\\>", "then": "Th\\%u00ec\\>", "when": "Khi\\>"},
- \"zh-CN": {"and": "\\%u800c\\%u4e14\\|\\%u5e76\\%u4e14\\|\\%u540c\\%u65f6", "background": "\\%u80cc\\%u666f\\>", "but": "\\%u4f46\\%u662f", "examples": "\\%u4f8b\\%u5b50\\>", "feature": "\\%u529f\\%u80fd\\>", "given": "\\%u5047\\%u5982\\|\\%u5047\\%u8bbe\\|\\%u5047\\%u5b9a", "scenario": "\\%u573a\\%u666f\\>\\|\\%u5267\\%u672c\\>", "scenario_outline": "\\%u573a\\%u666f\\%u5927\\%u7eb2\\>\\|\\%u5267\\%u672c\\%u5927\\%u7eb2\\>", "then": "\\%u90a3\\%u4e48", "when": "\\%u5f53"},
- \"zh-TW": {"and": "\\%u800c\\%u4e14\\|\\%u4e26\\%u4e14\\|\\%u540c\\%u6642", "background": "\\%u80cc\\%u666f\\>", "but": "\\%u4f46\\%u662f", "examples": "\\%u4f8b\\%u5b50\\>", "feature": "\\%u529f\\%u80fd\\>", "given": "\\%u5047\\%u5982\\|\\%u5047\\%u8a2d\\|\\%u5047\\%u5b9a", "scenario": "\\%u5834\\%u666f\\>\\|\\%u5287\\%u672c\\>", "scenario_outline": "\\%u5834\\%u666f\\%u5927\\%u7db1\\>\\|\\%u5287\\%u672c\\%u5927\\%u7db1\\>", "then": "\\%u90a3\\%u9ebc", "when": "\\%u7576"}}
+ \"en": {"and": "And\\>", "background": "Background", "but": "But\\>", "examples": "Scenarios\\|Examples", "feature": "Business Need\\|Feature\\|Ability", "given": "Given\\>", "rule": "Rule", "scenario": "Scenario\\|Example", "scenario_outline": "Scenario Template\\|Scenario Outline", "then": "Then\\>", "when": "When\\>"},
+ \"af": {"and": "En\\>", "background": "Agtergrond", "but": "Maar\\>", "examples": "Voorbeelde", "feature": "Besigheid Behoefte\\|Funksie\\|Vermo\\%u00eb", "given": "Gegewe\\>", "rule": "Regel", "scenario": "Voorbeeld\\|Situasie", "scenario_outline": "Situasie Uiteensetting", "then": "Dan\\>", "when": "Wanneer\\>"},
+ \"am": {"and": "\\%u0535\\%u057e\\>", "background": "\\%u053f\\%u0578\\%u0576\\%u057f\\%u0565\\%u0584\\%u057d\\%u057f", "but": "\\%u0532\\%u0561\\%u0575\\%u0581\\>", "examples": "\\%u0555\\%u0580\\%u056b\\%u0576\\%u0561\\%u056f\\%u0576\\%u0565\\%u0580", "feature": "\\%u0556\\%u0578\\%u0582\\%u0576\\%u056f\\%u0581\\%u056b\\%u0578\\%u0576\\%u0561\\%u056c\\%u0578\\%u0582\\%u0569\\%u0575\\%u0578\\%u0582\\%u0576\\|\\%u0540\\%u0561\\%u057f\\%u056f\\%u0578\\%u0582\\%u0569\\%u0575\\%u0578\\%u0582\\%u0576", "given": "\\%u0534\\%u056b\\%u0581\\%u0578\\%u0582\\%u0584\\>", "rule": "Rule", "scenario": "\\%u0555\\%u0580\\%u056b\\%u0576\\%u0561\\%u056f\\|\\%u054d\\%u0581\\%u0565\\%u0576\\%u0561\\%u0580", "scenario_outline": "\\%u054d\\%u0581\\%u0565\\%u0576\\%u0561\\%u0580\\%u056b \\%u056f\\%u0561\\%u057c\\%u0578\\%u0582\\%u0581\\%u057e\\%u0561\\%u0581\\%u0584\\%u0568", "then": "\\%u0531\\%u057a\\%u0561\\>", "when": "\\%u0535\\%u0569\\%u0565\\>\\|\\%u0535\\%u0580\\%u0562\\>"},
+ \"amh": {"and": "\\%u12a5\\%u1293\\>", "background": "\\%u1245\\%u12f5\\%u1218 \\%u1201\\%u1294\\%u1273\\|\\%u1218\\%u1290\\%u123b \\%u1200\\%u1233\\%u1265\\|\\%u1218\\%u1290\\%u123b", "but": "\\%u130d\\%u1295\\>", "examples": "\\%u121d\\%u1233\\%u120c\\%u12ce\\%u127d\\|\\%u1201\\%u1293\\%u1274\\%u12ce\\%u127d", "feature": "\\%u12e8\\%u121a\\%u1348\\%u1208\\%u1308\\%u12cd \\%u12f5\\%u122d\\%u130a\\%u1275\\|\\%u12e8\\%u1270\\%u1348\\%u1208\\%u1308\\%u12cd \\%u1235\\%u122b\\|\\%u1235\\%u122b", "given": "\\%u12e8\\%u1270\\%u1230\\%u1320\\>", "rule": "\\%u1205\\%u130d", "scenario": "\\%u121d\\%u1233\\%u120c\\|\\%u1201\\%u1293\\%u1274", "scenario_outline": "\\%u1201\\%u1293\\%u1274 \\%u12dd\\%u122d\\%u12dd\\%u122d\\|\\%u1201\\%u1293\\%u1274 \\%u12a0\\%u1265\\%u1290\\%u1275", "then": "\\%u12a8\\%u12da\\%u12eb\\>", "when": "\\%u1218\\%u127c\\>"},
+ \"an": {"and": "Y\\>\\|E\\>", "background": "Antecedents", "but": "Pero\\>", "examples": "Eixemplos", "feature": "Caracteristica", "given": "Dadas\\>\\|Dada\\>\\|Daus\\>\\|Dau\\>", "rule": "Rule", "scenario": "Eixemplo\\|Caso", "scenario_outline": "Esquema del caso", "then": "Antonces\\>\\|Alavez\\>\\|Allora\\>", "when": "Cuan\\>"},
+ \"ar": {"and": "\\%u0648\\>", "background": "\\%u0627\\%u0644\\%u062e\\%u0644\\%u0641\\%u064a\\%u0629", "but": "\\%u0644\\%u0643\\%u0646\\>", "examples": "\\%u0627\\%u0645\\%u062b\\%u0644\\%u0629", "feature": "\\%u062e\\%u0627\\%u0635\\%u064a\\%u0629", "given": "\\%u0628\\%u0641\\%u0631\\%u0636\\>", "rule": "Rule", "scenario": "\\%u0633\\%u064a\\%u0646\\%u0627\\%u0631\\%u064a\\%u0648\\|\\%u0645\\%u062b\\%u0627\\%u0644", "scenario_outline": "\\%u0633\\%u064a\\%u0646\\%u0627\\%u0631\\%u064a\\%u0648 \\%u0645\\%u062e\\%u0637\\%u0637", "then": "\\%u0627\\%u0630\\%u0627\\%u064b\\>\\|\\%u062b\\%u0645\\>", "when": "\\%u0639\\%u0646\\%u062f\\%u0645\\%u0627\\>\\|\\%u0645\\%u062a\\%u0649\\>"},
+ \"ast": {"and": "Ya\\>\\|Y\\>", "background": "Antecedentes", "but": "Peru\\>", "examples": "Exemplos", "feature": "Carauter\\%u00edstica", "given": "Dada\\>\\|Daos\\>\\|Daes\\>\\|D\\%u00e1u\\>", "rule": "Rule", "scenario": "Exemplo\\|Casu", "scenario_outline": "Esbozu del casu", "then": "Ent\\%u00f3s\\>", "when": "Cuando\\>"},
+ \"az": {"and": "H\\%u0259m\\>\\|V\\%u0259\\>", "background": "Kontekst\\|Ke\\%u00e7mi\\%u015f", "but": "Ancaq\\>\\|Amma\\>", "examples": "N\\%u00fcmun\\%u0259l\\%u0259r", "feature": "\\%u00d6z\\%u0259llik", "given": "Tutaq ki\\>\\|Verilir\\>", "rule": "Rule", "scenario": "Ssenari\\|N\\%u00fcmun\\%u0259", "scenario_outline": "Ssenarinin strukturu", "then": "O halda\\>", "when": "N\\%u0259 vaxt ki\\>\\|\\%u018fg\\%u0259r\\>"},
+ \"bg": {"and": "\\%u0418\\>", "background": "\\%u041f\\%u0440\\%u0435\\%u0434\\%u0438\\%u0441\\%u0442\\%u043e\\%u0440\\%u0438\\%u044f", "but": "\\%u041d\\%u043e\\>", "examples": "\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440\\%u0438", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u043e\\%u043d\\%u0430\\%u043b\\%u043d\\%u043e\\%u0441\\%u0442", "given": "\\%u0414\\%u0430\\%u0434\\%u0435\\%u043d\\%u043e\\>", "rule": "\\%u041f\\%u0440\\%u0430\\%u0432\\%u0438\\%u043b\\%u043e", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439\\|\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440", "scenario_outline": "\\%u0420\\%u0430\\%u043c\\%u043a\\%u0430 \\%u043d\\%u0430 \\%u0441\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439", "then": "\\%u0422\\%u043e\\>", "when": "\\%u041a\\%u043e\\%u0433\\%u0430\\%u0442\\%u043e\\>"},
+ \"bm": {"and": "Dan\\>", "background": "Latar Belakang", "but": "Tetapi\\>\\|Tapi\\>", "examples": "Contoh", "feature": "Fungsi", "given": "Diberi\\>\\|Bagi\\>", "rule": "Rule", "scenario": "Senario\\|Situasi\\|Keadaan", "scenario_outline": "Garis Panduan Senario\\|Kerangka Senario\\|Kerangka Situasi\\|Kerangka Keadaan", "then": "Kemudian\\>\\|Maka\\>", "when": "Apabila\\>"},
+ \"bs": {"and": "I\\>\\|A\\>", "background": "Pozadina", "but": "Ali\\>", "examples": "Primjeri", "feature": "Karakteristika", "given": "Dato\\>", "rule": "Rule", "scenario": "Scenariju\\|Scenario\\|Primjer", "scenario_outline": "Scenario-outline\\|Scenariju-obris", "then": "Zatim\\>", "when": "Kada\\>"},
+ \"ca": {"and": "I\\>", "background": "Antecedents\\|Rerefons", "but": "Per\\%u00f2\\>", "examples": "Exemples", "feature": "Caracter\\%u00edstica\\|Funcionalitat", "given": "Donada\\>\\|Donat\\>\\|Atesa\\>\\|At\\%u00e8s\\>", "rule": "Rule", "scenario": "Escenari\\|Exemple", "scenario_outline": "Esquema de l'escenari", "then": "Aleshores\\>\\|Cal\\>", "when": "Quan\\>"},
+ \"cs": {"and": "A tak\\%u00e9\\>\\|A\\>", "background": "Kontext\\|Pozad\\%u00ed", "but": "Ale\\>", "examples": "P\\%u0159\\%u00edklady", "feature": "Po\\%u017eadavek", "given": "Za p\\%u0159edpokladu\\>\\|Pokud\\>", "rule": "Pravidlo", "scenario": "P\\%u0159\\%u00edklad\\|Sc\\%u00e9n\\%u00e1\\%u0159", "scenario_outline": "Osnova sc\\%u00e9n\\%u00e1\\%u0159e\\|N\\%u00e1\\%u010drt Sc\\%u00e9n\\%u00e1\\%u0159e", "then": "Pak\\>", "when": "Kdy\\%u017e\\>"},
+ \"cy-GB": {"and": "A\\>", "background": "Cefndir", "but": "Ond\\>", "examples": "Enghreifftiau", "feature": "Arwedd", "given": "Anrhegedig a\\>", "rule": "Rule", "scenario": "Enghraifft\\|Scenario", "scenario_outline": "Scenario Amlinellol", "then": "Yna\\>", "when": "Pryd\\>"},
+ \"da": {"and": "Og\\>", "background": "Baggrund", "but": "Men\\>", "examples": "Eksempler", "feature": "Egenskab", "given": "Givet\\>", "rule": "Rule", "scenario": "Eksempel\\|Scenarie", "scenario_outline": "Abstrakt Scenario", "then": "S\\%u00e5\\>", "when": "N\\%u00e5r\\>"},
+ \"de": {"and": "Und\\>", "background": "Voraussetzungen\\|Vorbedingungen\\|Hintergrund\\|Grundlage", "but": "Aber\\>", "examples": "Beispiele", "feature": "Funktionalit\\%u00e4t\\|Funktion", "given": "Gegeben seien\\>\\|Gegeben sei\\>\\|Angenommen\\>", "rule": "Regel\\|Rule", "scenario": "Beispiel\\|Szenario", "scenario_outline": "Szenariogrundriss\\|Szenarien", "then": "Dann\\>", "when": "Wenn\\>"},
+ \"el": {"and": "\\%u039a\\%u03b1\\%u03b9\\>", "background": "\\%u03a5\\%u03c0\\%u03cc\\%u03b2\\%u03b1\\%u03b8\\%u03c1\\%u03bf", "but": "\\%u0391\\%u03bb\\%u03bb\\%u03ac\\>", "examples": "\\%u03a0\\%u03b1\\%u03c1\\%u03b1\\%u03b4\\%u03b5\\%u03af\\%u03b3\\%u03bc\\%u03b1\\%u03c4\\%u03b1\\|\\%u03a3\\%u03b5\\%u03bd\\%u03ac\\%u03c1\\%u03b9\\%u03b1", "feature": "\\%u0394\\%u03c5\\%u03bd\\%u03b1\\%u03c4\\%u03cc\\%u03c4\\%u03b7\\%u03c4\\%u03b1\\|\\%u039b\\%u03b5\\%u03b9\\%u03c4\\%u03bf\\%u03c5\\%u03c1\\%u03b3\\%u03af\\%u03b1", "given": "\\%u0394\\%u03b5\\%u03b4\\%u03bf\\%u03bc\\%u03ad\\%u03bd\\%u03bf\\%u03c5\\>", "rule": "Rule", "scenario": "\\%u03a0\\%u03b1\\%u03c1\\%u03ac\\%u03b4\\%u03b5\\%u03b9\\%u03b3\\%u03bc\\%u03b1\\|\\%u03a3\\%u03b5\\%u03bd\\%u03ac\\%u03c1\\%u03b9\\%u03bf", "scenario_outline": "\\%u03a0\\%u03b5\\%u03c1\\%u03af\\%u03b3\\%u03c1\\%u03b1\\%u03bc\\%u03bc\\%u03b1 \\%u03a3\\%u03b5\\%u03bd\\%u03b1\\%u03c1\\%u03af\\%u03bf\\%u03c5\\|\\%u03a0\\%u03b5\\%u03c1\\%u03b9\\%u03b3\\%u03c1\\%u03b1\\%u03c6\\%u03ae \\%u03a3\\%u03b5\\%u03bd\\%u03b1\\%u03c1\\%u03af\\%u03bf\\%u03c5", "then": "\\%u03a4\\%u03cc\\%u03c4\\%u03b5\\>", "when": "\\%u038c\\%u03c4\\%u03b1\\%u03bd\\>"},
+ \"em": {"and": "\\%u1f602", "background": "\\%u1f4a4", "but": "\\%u1f614", "examples": "\\%u1f4d3", "feature": "\\%u1f4da", "given": "\\%u1f610", "rule": "Rule", "scenario": "\\%u1f952\\|\\%u1f4d5", "scenario_outline": "\\%u1f4d6", "then": "\\%u1f64f", "when": "\\%u1f3ac"},
+ \"en-Scouse": {"and": "An\\>", "background": "Dis is what went down", "but": "Buh\\>", "examples": "Examples", "feature": "Feature", "given": "Youse know when youse got\\>\\|Givun\\>", "rule": "Rule", "scenario": "The thing of it is", "scenario_outline": "Wharrimean is", "then": "Den youse gotta\\>\\|Dun\\>", "when": "Youse know like when\\>\\|Wun\\>"},
+ \"en-au": {"and": "Too right\\>", "background": "First off", "but": "Yeah nah\\>", "examples": "You'll wanna", "feature": "Pretty much", "given": "Y'know\\>", "rule": "Rule", "scenario": "Awww, look mate", "scenario_outline": "Reckon it's like", "then": "But at the end of the day I reckon\\>", "when": "It's just unbelievable\\>"},
+ \"en-lol": {"and": "AN\\>", "background": "B4", "but": "BUT\\>", "examples": "EXAMPLZ", "feature": "OH HAI", "given": "I CAN HAZ\\>", "rule": "Rule", "scenario": "MISHUN", "scenario_outline": "MISHUN SRSLY", "then": "DEN\\>", "when": "WEN\\>"},
+ \"en-old": {"and": "Ond\\>\\|7\\>", "background": "Aer\\|\\%u00c6r", "but": "Ac\\>", "examples": "Se the\\|Se \\%u00fee\\|Se \\%u00f0e", "feature": "Hwaet\\|Hw\\%u00e6t", "given": "Thurh\\>\\|\\%u00deurh\\>\\|\\%u00d0urh\\>", "rule": "Rule", "scenario": "Swa", "scenario_outline": "Swa hwaer swa\\|Swa hw\\%u00e6r swa", "then": "Tha the\\>\\|\\%u00dea \\%u00fee\\>\\|\\%u00d0a \\%u00f0e\\>\\|Tha\\>\\|\\%u00dea\\>\\|\\%u00d0a\\>", "when": "B\\%u00e6\\%u00fesealfa\\>\\|B\\%u00e6\\%u00fesealfe\\>\\|B\\%u00e6\\%u00fesealf\\>\\|Ciric\\%u00e6we\\>\\|Ciric\\%u00e6wa\\>\\|Ciric\\%u00e6w\\>"},
+ \"en-pirate": {"and": "Aye\\>", "background": "Yo-ho-ho", "but": "Avast!\\>", "examples": "Dead men tell no tales", "feature": "Ahoy matey!", "given": "Gangway!\\>", "rule": "Rule", "scenario": "Heave to", "scenario_outline": "Shiver me timbers", "then": "Let go and haul\\>", "when": "Blimey!\\>"},
+ \"en-tx": {"and": "Come hell or high water\\>", "background": "Lemme tell y'all a story", "but": "Well now hold on, I'll you what\\>", "examples": "Now that's a story longer than a cattle drive in July", "feature": "This ain\\%u2019t my first rodeo\\|All gussied up", "given": "All git out\\>\\|Fixin' to\\>", "rule": "Rule\\>", "scenario": "All hat and no cattle", "scenario_outline": "Busy as a hound in flea season\\|Serious as a snake bite", "then": "There\\%u2019s no tree but bears some fruit\\>", "when": "Quick out of the chute\\>"},
+ \"eo": {"and": "Kaj\\>", "background": "Fono", "but": "Sed\\>", "examples": "Ekzemploj", "feature": "Trajto", "given": "Donita\\%u0135o\\>\\|Komence\\>", "rule": "Rule", "scenario": "Ekzemplo\\|Scenaro\\|Kazo", "scenario_outline": "Konturo de la scenaro\\|Kazo-skizo\\|Skizo", "then": "Do\\>", "when": "Se\\>"},
+ \"es": {"and": "Y\\>\\|E\\>", "background": "Antecedentes", "but": "Pero\\>", "examples": "Ejemplos", "feature": "Necesidad del negocio\\|Caracter\\%u00edstica\\|Requisito", "given": "Dados\\>\\|Dadas\\>\\|Dado\\>\\|Dada\\>", "rule": "Regla de negocio\\|Regla", "scenario": "Escenario\\|Ejemplo", "scenario_outline": "Esquema del escenario", "then": "Entonces\\>", "when": "Cuando\\>"},
+ \"et": {"and": "Ja\\>", "background": "Taust", "but": "Kuid\\>", "examples": "Juhtumid", "feature": "Omadus", "given": "Eeldades\\>", "rule": "Reegel", "scenario": "Stsenaarium\\|Juhtum", "scenario_outline": "Raamstsenaarium\\|Raamjuhtum", "then": "Siis\\>", "when": "Kui\\>"},
+ \"fa": {"and": "\\%u0648\\>", "background": "\\%u0632\\%u0645\\%u06cc\\%u0646\\%u0647", "but": "\\%u0627\\%u0645\\%u0627\\>", "examples": "\\%u0646\\%u0645\\%u0648\\%u0646\\%u0647 \\%u0647\\%u0627", "feature": "\\%u0648\\%u0650\\%u06cc\\%u0698\\%u06af\\%u06cc", "given": "\\%u0628\\%u0627 \\%u0641\\%u0631\\%u0636\\>", "rule": "Rule", "scenario": "\\%u0633\\%u0646\\%u0627\\%u0631\\%u06cc\\%u0648\\|\\%u0645\\%u062b\\%u0627\\%u0644", "scenario_outline": "\\%u0627\\%u0644\\%u06af\\%u0648\\%u06cc \\%u0633\\%u0646\\%u0627\\%u0631\\%u06cc\\%u0648", "then": "\\%u0622\\%u0646\\%u06af\\%u0627\\%u0647\\>", "when": "\\%u0647\\%u0646\\%u06af\\%u0627\\%u0645\\%u06cc\\>"},
+ \"fi": {"and": "Ja\\>", "background": "Tausta", "but": "Mutta\\>", "examples": "Tapaukset", "feature": "Ominaisuus", "given": "Oletetaan\\>", "rule": "Rule", "scenario": "Tapaus", "scenario_outline": "Tapausaihio", "then": "Niin\\>", "when": "Kun\\>"},
+ \"fr": {"and": "Et que\\>\\|Et qu'\\|Et\\>", "background": "Contexte", "but": "Mais que\\>\\|Mais qu'\\|Mais\\>", "examples": "Exemples", "feature": "Fonctionnalit\\%u00e9", "given": "Etant donn\\%u00e9 que\\>\\|\\%u00c9tant donn\\%u00e9 que\\>\\|Etant donn\\%u00e9 qu'\\|\\%u00c9tant donn\\%u00e9 qu'\\|Etant donn\\%u00e9es\\>\\|\\%u00c9tant donn\\%u00e9es\\>\\|Etant donn\\%u00e9e\\>\\|Etant donn\\%u00e9s\\>\\|\\%u00c9tant donn\\%u00e9e\\>\\|\\%u00c9tant donn\\%u00e9s\\>\\|Sachant que\\>\\|Etant donn\\%u00e9\\>\\|\\%u00c9tant donn\\%u00e9\\>\\|Sachant qu'\\|Sachant\\>\\|Soit\\>", "rule": "R\\%u00e8gle", "scenario": "Sc\\%u00e9nario\\|Exemple", "scenario_outline": "Plan du sc\\%u00e9nario\\|Plan du Sc\\%u00e9nario", "then": "Alors\\>\\|Donc\\>", "when": "Lorsque\\>\\|Lorsqu'\\|Quand\\>"},
+ \"ga": {"and": "Agus", "background": "C\\%u00falra", "but": "Ach", "examples": "Sampla\\%u00ed", "feature": "Gn\\%u00e9", "given": "Cuir i gc\\%u00e1s nach\\|Cuir i gc\\%u00e1s gur\\|Cuir i gc\\%u00e1s n\\%u00e1r\\|Cuir i gc\\%u00e1s go", "rule": "Rule", "scenario": "Sampla\\|C\\%u00e1s", "scenario_outline": "C\\%u00e1s Achomair", "then": "Ansin", "when": "Nuair nach\\|Nuair n\\%u00e1r\\|Nuair ba\\|Nuair a"},
+ \"gj": {"and": "\\%u0a85\\%u0aa8\\%u0ac7\\>", "background": "\\%u0aac\\%u0ac7\\%u0a95\\%u0a97\\%u0acd\\%u0ab0\\%u0abe\\%u0a89\\%u0aa8\\%u0acd\\%u0aa1", "but": "\\%u0aaa\\%u0aa3\\>", "examples": "\\%u0a89\\%u0aa6\\%u0abe\\%u0ab9\\%u0ab0\\%u0aa3\\%u0acb", "feature": "\\%u0ab5\\%u0acd\\%u0aaf\\%u0abe\\%u0aaa\\%u0abe\\%u0ab0 \\%u0a9c\\%u0ab0\\%u0ac2\\%u0ab0\\|\\%u0a95\\%u0acd\\%u0ab7\\%u0aae\\%u0aa4\\%u0abe\\|\\%u0ab2\\%u0a95\\%u0acd\\%u0ab7\\%u0aa3", "given": "\\%u0a86\\%u0aaa\\%u0ac7\\%u0ab2 \\%u0a9b\\%u0ac7\\>", "rule": "Rule", "scenario": "\\%u0a89\\%u0aa6\\%u0abe\\%u0ab9\\%u0ab0\\%u0aa3\\|\\%u0ab8\\%u0acd\\%u0aa5\\%u0abf\\%u0aa4\\%u0abf", "scenario_outline": "\\%u0aaa\\%u0ab0\\%u0abf\\%u0aa6\\%u0acd\\%u0aa6\\%u0ab6\\%u0acd\\%u0aaf \\%u0ab0\\%u0ac2\\%u0aaa\\%u0ab0\\%u0ac7\\%u0a96\\%u0abe\\|\\%u0aaa\\%u0ab0\\%u0abf\\%u0aa6\\%u0acd\\%u0aa6\\%u0ab6\\%u0acd\\%u0aaf \\%u0aa2\\%u0abe\\%u0a82\\%u0a9a\\%u0acb", "then": "\\%u0aaa\\%u0a9b\\%u0ac0\\>", "when": "\\%u0a95\\%u0acd\\%u0aaf\\%u0abe\\%u0ab0\\%u0ac7\\>"},
+ \"gl": {"and": "E\\>", "background": "Contexto", "but": "Mais\\>\\|Pero\\>", "examples": "Exemplos", "feature": "Caracter\\%u00edstica", "given": "Dados\\>\\|Dadas\\>\\|Dado\\>\\|Dada\\>", "rule": "Rule", "scenario": "Escenario\\|Exemplo", "scenario_outline": "Esbozo do escenario", "then": "Ent\\%u00f3n\\>\\|Logo\\>", "when": "Cando\\>"},
+ \"he": {"and": "\\%u05d5\\%u05d2\\%u05dd\\>", "background": "\\%u05e8\\%u05e7\\%u05e2", "but": "\\%u05d0\\%u05d1\\%u05dc\\>", "examples": "\\%u05d3\\%u05d5\\%u05d2\\%u05de\\%u05d0\\%u05d5\\%u05ea", "feature": "\\%u05ea\\%u05db\\%u05d5\\%u05e0\\%u05d4", "given": "\\%u05d1\\%u05d4\\%u05d9\\%u05e0\\%u05ea\\%u05df\\>", "rule": "\\%u05db\\%u05dc\\%u05dc", "scenario": "\\%u05d3\\%u05d5\\%u05d2\\%u05de\\%u05d0\\|\\%u05ea\\%u05e8\\%u05d7\\%u05d9\\%u05e9", "scenario_outline": "\\%u05ea\\%u05d1\\%u05e0\\%u05d9\\%u05ea \\%u05ea\\%u05e8\\%u05d7\\%u05d9\\%u05e9", "then": "\\%u05d0\\%u05d6\\%u05d9\\>\\|\\%u05d0\\%u05d6\\>", "when": "\\%u05db\\%u05d0\\%u05e9\\%u05e8\\>"},
+ \"hi": {"and": "\\%u0924\\%u0925\\%u093e\\>\\|\\%u0914\\%u0930\\>", "background": "\\%u092a\\%u0943\\%u0937\\%u094d\\%u0920\\%u092d\\%u0942\\%u092e\\%u093f", "but": "\\%u092a\\%u0930\\%u0928\\%u094d\\%u0924\\%u0941\\>\\|\\%u0915\\%u093f\\%u0928\\%u094d\\%u0924\\%u0941\\>\\|\\%u092a\\%u0930\\>", "examples": "\\%u0909\\%u0926\\%u093e\\%u0939\\%u0930\\%u0923", "feature": "\\%u0930\\%u0942\\%u092a \\%u0932\\%u0947\\%u0916", "given": "\\%u091a\\%u0942\\%u0902\\%u0915\\%u093f\\>\\|\\%u0905\\%u0917\\%u0930\\>\\|\\%u092f\\%u0926\\%u093f\\>", "rule": "\\%u0928\\%u093f\\%u092f\\%u092e", "scenario": "\\%u092a\\%u0930\\%u093f\\%u0926\\%u0943\\%u0936\\%u094d\\%u092f", "scenario_outline": "\\%u092a\\%u0930\\%u093f\\%u0926\\%u0943\\%u0936\\%u094d\\%u092f \\%u0930\\%u0942\\%u092a\\%u0930\\%u0947\\%u0916\\%u093e", "then": "\\%u0924\\%u0926\\%u093e\\>\\|\\%u0924\\%u092c\\>", "when": "\\%u0915\\%u0926\\%u093e\\>\\|\\%u091c\\%u092c\\>"},
+ \"hr": {"and": "I\\>", "background": "Pozadina", "but": "Ali\\>", "examples": "Scenariji\\|Primjeri", "feature": "Mogu\\%u0107nost\\|Mogucnost\\|Osobina", "given": "Ukoliko\\>\\|Zadani\\>\\|Zadano\\>\\|Zadan\\>", "rule": "Rule", "scenario": "Scenarij\\|Primjer", "scenario_outline": "Koncept\\|Skica", "then": "Onda\\>", "when": "Kada\\>\\|Kad\\>"},
+ \"ht": {"and": "Epi\\>\\|Ak\\>\\|E\\>", "background": "Kont\\%u00e8ks\\|Istorik", "but": "Men\\>", "examples": "Egzanp", "feature": "Karakteristik\\|Fonksyonalite\\|Mak", "given": "Sipoze ke\\>\\|Sipoze Ke\\>\\|Sipoze\\>", "rule": "Rule", "scenario": "Senaryo", "scenario_outline": "Senaryo deskripsyon\\|Senaryo Deskripsyon\\|Dyagram senaryo\\|Dyagram Senaryo\\|Plan senaryo\\|Plan Senaryo", "then": "L\\%u00e8 sa a\\>\\|Le sa a\\>", "when": "L\\%u00e8\\>\\|Le\\>"},
+ \"hu": {"and": "\\%u00c9s\\>", "background": "H\\%u00e1tt\\%u00e9r", "but": "De\\>", "examples": "P\\%u00e9ld\\%u00e1k", "feature": "Jellemz\\%u0151", "given": "Amennyiben\\>\\|Adott\\>", "rule": "Szab\\%u00e1ly", "scenario": "Forgat\\%u00f3k\\%u00f6nyv\\|P\\%u00e9lda", "scenario_outline": "Forgat\\%u00f3k\\%u00f6nyv v\\%u00e1zlat", "then": "Akkor\\>", "when": "Amikor\\>\\|Majd\\>\\|Ha\\>"},
+ \"id": {"and": "Dan\\>", "background": "Latar Belakang\\|Dasar", "but": "Tetapi\\>\\|Tapi\\>", "examples": "Contoh\\|Misal", "feature": "Fitur", "given": "Diasumsikan\\>\\|Diketahui\\>\\|Dengan\\>\\|Bila\\>\\|Jika\\>", "rule": "Aturan\\|Rule", "scenario": "Skenario", "scenario_outline": "Garis-Besar Skenario\\|Skenario konsep", "then": "Kemudian\\>\\|Maka\\>", "when": "Ketika\\>"},
+ \"is": {"and": "Og\\>", "background": "Bakgrunnur", "but": "En\\>", "examples": "Atbur\\%u00f0ar\\%u00e1sir\\|D\\%u00e6mi", "feature": "Eiginleiki", "given": "Ef\\>", "rule": "Rule", "scenario": "Atbur\\%u00f0ar\\%u00e1s", "scenario_outline": "L\\%u00fdsing Atbur\\%u00f0ar\\%u00e1sar\\|L\\%u00fdsing D\\%u00e6ma", "then": "\\%u00de\\%u00e1\\>", "when": "\\%u00deegar\\>"},
+ \"it": {"and": "E\\>", "background": "Contesto", "but": "Ma\\>", "examples": "Esempi", "feature": "Esigenza di Business\\|Funzionalit\\%u00e0\\|Abilit\\%u00e0", "given": "Dato\\>\\|Data\\>\\|Dati\\>\\|Date\\>", "rule": "Regola", "scenario": "Scenario\\|Esempio", "scenario_outline": "Schema dello scenario", "then": "Allora\\>", "when": "Quando\\>"},
+ \"ja": {"and": "\\%u4e14\\%u3064\\|\\%u304b\\%u3064", "background": "\\%u80cc\\%u666f", "but": "\\%u3057\\%u304b\\%u3057\\|\\%u305f\\%u3060\\%u3057\\|\\%u7136\\%u3057\\|\\%u4f46\\%u3057", "examples": "\\%u30b5\\%u30f3\\%u30d7\\%u30eb\\|\\%u4f8b", "feature": "\\%u30d5\\%u30a3\\%u30fc\\%u30c1\\%u30e3\\|\\%u6a5f\\%u80fd", "given": "\\%u524d\\%u63d0", "rule": "\\%u30eb\\%u30fc\\%u30eb", "scenario": "\\%u30b7\\%u30ca\\%u30ea\\%u30aa", "scenario_outline": "\\%u30b7\\%u30ca\\%u30ea\\%u30aa\\%u30a2\\%u30a6\\%u30c8\\%u30e9\\%u30a4\\%u30f3\\|\\%u30b7\\%u30ca\\%u30ea\\%u30aa\\%u30c6\\%u30f3\\%u30d7\\%u30ec\\%u30fc\\%u30c8\\|\\%u30b7\\%u30ca\\%u30ea\\%u30aa\\%u30c6\\%u30f3\\%u30d7\\%u30ec\\|\\%u30c6\\%u30f3\\%u30d7\\%u30ec", "then": "\\%u306a\\%u3089\\%u3070", "when": "\\%u3082\\%u3057"},
+ \"jv": {"and": "Lan\\>", "background": "Dasar", "but": "Ananging\\>\\|Nanging\\>\\|Tapi\\>", "examples": "Contone\\|Conto", "feature": "Fitur", "given": "Nalikaning\\>\\|Nalika\\>", "rule": "Rule", "scenario": "Skenario", "scenario_outline": "Konsep skenario", "then": "Banjur\\>\\|Njuk\\>", "when": "Manawa\\>\\|Menawa\\>"},
+ \"ka": {"and": "\\%u10d0\\%u10e1\\%u10d4\\%u10d5\\%u10d4\\>\\|\\%u10d3\\%u10d0\\>", "background": "\\%u10d9\\%u10dd\\%u10dc\\%u10e2\\%u10d4\\%u10e5\\%u10e1\\%u10e2\\%u10d8", "but": "\\%u10db\\%u10d0\\%u10d2\\%u10e0\\%u10d0\\%u10db\\>\\|\\%u10d7\\%u10e3\\%u10db\\%u10ea\\%u10d0\\>", "examples": "\\%u10db\\%u10d0\\%u10d2\\%u10d0\\%u10da\\%u10d8\\%u10d7\\%u10d4\\%u10d1\\%u10d8", "feature": "\\%u10db\\%u10dd\\%u10d7\\%u10ee\\%u10dd\\%u10d5\\%u10dc\\%u10d0\\|\\%u10d7\\%u10d5\\%u10d8\\%u10e1\\%u10d4\\%u10d1\\%u10d0", "given": "\\%u10db\\%u10dd\\%u10ea\\%u10d4\\%u10db\\%u10e3\\%u10da\\%u10d8\\%u10d0\\>\\|\\%u10db\\%u10dd\\%u10ea\\%u10d4\\%u10db\\%u10e3\\%u10da\\%u10d8\\>\\|\\%u10d5\\%u10d7\\%u10e5\\%u10d5\\%u10d0\\%u10d7\\>", "rule": "\\%u10ec\\%u10d4\\%u10e1\\%u10d8", "scenario": "\\%u10db\\%u10d0\\%u10d2\\%u10d0\\%u10da\\%u10d8\\%u10d7\\%u10d0\\%u10d3\\|\\%u10db\\%u10d0\\%u10d2\\%u10d0\\%u10da\\%u10d8\\%u10d7\\%u10d8\\|\\%u10e1\\%u10ea\\%u10d4\\%u10dc\\%u10d0\\%u10e0\\%u10d8\\|\\%u10db\\%u10d0\\%u10d2", "scenario_outline": "\\%u10e1\\%u10ea\\%u10d4\\%u10dc\\%u10d0\\%u10e0\\%u10d8\\%u10e1 \\%u10e8\\%u10d0\\%u10d1\\%u10da\\%u10dd\\%u10dc\\%u10d8\\|\\%u10e1\\%u10ea\\%u10d4\\%u10dc\\%u10d0\\%u10e0\\%u10d8\\%u10e1 \\%u10dc\\%u10d8\\%u10db\\%u10e3\\%u10e8\\%u10d8\\|\\%u10e8\\%u10d0\\%u10d1\\%u10da\\%u10dd\\%u10dc\\%u10d8\\|\\%u10dc\\%u10d8\\%u10db\\%u10e3\\%u10e8\\%u10d8", "then": "\\%u10db\\%u10d0\\%u10e8\\%u10d8\\%u10dc\\>", "when": "\\%u10e0\\%u10dd\\%u10d2\\%u10dd\\%u10e0\\%u10ea \\%u10d9\\%u10d8\\>\\|\\%u10e0\\%u10dd\\%u10d3\\%u10d4\\%u10e1\\%u10d0\\%u10ea\\>\\|\\%u10e0\\%u10dd\\%u10ea\\%u10d0\\>\\|\\%u10d7\\%u10e3\\>"},
+ \"kn": {"and": "\\%u0cae\\%u0ca4\\%u0ccd\\%u0ca4\\%u0cc1\\>", "background": "\\%u0cb9\\%u0cbf\\%u0ca8\\%u0ccd\\%u0ca8\\%u0cc6\\%u0cb2\\%u0cc6", "but": "\\%u0c86\\%u0ca6\\%u0cb0\\%u0cc6\\>", "examples": "\\%u0c89\\%u0ca6\\%u0cbe\\%u0cb9\\%u0cb0\\%u0ca3\\%u0cc6\\%u0c97\\%u0cb3\\%u0cc1", "feature": "\\%u0cb9\\%u0cc6\\%u0c9a\\%u0ccd\\%u0c9a\\%u0cb3", "given": "\\%u0ca8\\%u0cbf\\%u0cd5\\%u0ca1\\%u0cbf\\%u0ca6\\>", "rule": "Rule", "scenario": "\\%u0c95\\%u0ca5\\%u0cbe\\%u0cb8\\%u0cbe\\%u0cb0\\%u0cbe\\%u0c82\\%u0cb6\\|\\%u0c89\\%u0ca6\\%u0cbe\\%u0cb9\\%u0cb0\\%u0ca3\\%u0cc6", "scenario_outline": "\\%u0cb5\\%u0cbf\\%u0cb5\\%u0cb0\\%u0ca3\\%u0cc6", "then": "\\%u0ca8\\%u0c82\\%u0ca4\\%u0cb0\\>", "when": "\\%u0cb8\\%u0ccd\\%u0ca5\\%u0cbf\\%u0ca4\\%u0cbf\\%u0caf\\%u0ca8\\%u0ccd\\%u0ca8\\%u0cc1\\>"},
+ \"ko": {"and": "\\%uadf8\\%ub9ac\\%uace0", "background": "\\%ubc30\\%uacbd", "but": "\\%ud558\\%uc9c0\\%ub9cc\\|\\%ub2e8", "examples": "\\%uc608", "feature": "\\%uae30\\%ub2a5", "given": "\\%uc870\\%uac74\\|\\%uba3c\\%uc800", "rule": "Rule", "scenario": "\\%uc2dc\\%ub098\\%ub9ac\\%uc624", "scenario_outline": "\\%uc2dc\\%ub098\\%ub9ac\\%uc624 \\%uac1c\\%uc694", "then": "\\%uadf8\\%ub7ec\\%uba74", "when": "\\%ub9cc\\%uc77c\\|\\%ub9cc\\%uc57d"},
+ \"lt": {"and": "Ir\\>", "background": "Kontekstas", "but": "Bet\\>", "examples": "Pavyzd\\%u017eiai\\|Scenarijai\\|Variantai", "feature": "Savyb\\%u0117", "given": "Duota\\>", "rule": "Rule", "scenario": "Scenarijus\\|Pavyzdys", "scenario_outline": "Scenarijaus \\%u0161ablonas", "then": "Tada\\>", "when": "Kai\\>"},
+ \"lu": {"and": "an\\>\\|a\\>", "background": "Hannergrond", "but": "awer\\>\\|m\\%u00e4\\>", "examples": "Beispiller", "feature": "Funktionalit\\%u00e9it", "given": "ugeholl\\>", "rule": "Rule", "scenario": "Beispill\\|Szenario", "scenario_outline": "Plang vum Szenario", "then": "dann\\>", "when": "wann\\>"},
+ \"lv": {"and": "Un\\>", "background": "Konteksts\\|Situ\\%u0101cija", "but": "Bet\\>", "examples": "Piem\\%u0113ri\\|Paraugs", "feature": "Funkcionalit\\%u0101te\\|F\\%u012b\\%u010da", "given": "Kad\\>", "rule": "Rule", "scenario": "Scen\\%u0101rijs\\|Piem\\%u0113rs", "scenario_outline": "Scen\\%u0101rijs p\\%u0113c parauga", "then": "Tad\\>", "when": "Ja\\>"},
+ \"mk-Cyrl": {"and": "\\%u0418\\>", "background": "\\%u041a\\%u043e\\%u043d\\%u0442\\%u0435\\%u043a\\%u0441\\%u0442\\|\\%u0421\\%u043e\\%u0434\\%u0440\\%u0436\\%u0438\\%u043d\\%u0430", "but": "\\%u041d\\%u043e\\>", "examples": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0458\\%u0430\\|\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440\\%u0438", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u043e\\%u043d\\%u0430\\%u043b\\%u043d\\%u043e\\%u0441\\%u0442\\|\\%u0411\\%u0438\\%u0437\\%u043d\\%u0438\\%u0441 \\%u043f\\%u043e\\%u0442\\%u0440\\%u0435\\%u0431\\%u0430\\|\\%u041c\\%u043e\\%u0436\\%u043d\\%u043e\\%u0441\\%u0442", "given": "\\%u0414\\%u0430\\%u0434\\%u0435\\%u043d\\%u043e\\>\\|\\%u0414\\%u0430\\%u0434\\%u0435\\%u043d\\%u0430\\>", "rule": "Rule", "scenario": "\\%u041d\\%u0430 \\%u043f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440\\|\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u043e\\|\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440", "scenario_outline": "\\%u041f\\%u0440\\%u0435\\%u0433\\%u043b\\%u0435\\%u0434 \\%u043d\\%u0430 \\%u0441\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0458\\%u0430\\|\\%u041a\\%u043e\\%u043d\\%u0446\\%u0435\\%u043f\\%u0442\\|\\%u0421\\%u043a\\%u0438\\%u0446\\%u0430", "then": "\\%u0422\\%u043e\\%u0433\\%u0430\\%u0448\\>", "when": "\\%u041a\\%u043e\\%u0433\\%u0430\\>"},
+ \"mk-Latn": {"and": "I\\>", "background": "Sodrzhina\\|Kontekst", "but": "No\\>", "examples": "Scenaria\\|Primeri", "feature": "Funkcionalnost\\|Biznis potreba\\|Mozhnost", "given": "Dadeno\\>\\|Dadena\\>", "rule": "Rule", "scenario": "Na primer\\|Scenario", "scenario_outline": "Pregled na scenarija\\|Koncept\\|Skica", "then": "Togash\\>", "when": "Koga\\>"},
+ \"mn": {"and": "\\%u0422\\%u044d\\%u0433\\%u044d\\%u044d\\%u0434\\>\\|\\%u041c\\%u04e9\\%u043d\\>", "background": "\\%u0410\\%u0433\\%u0443\\%u0443\\%u043b\\%u0433\\%u0430", "but": "\\%u0413\\%u044d\\%u0445\\%u0434\\%u044d\\%u044d\\>\\|\\%u0425\\%u0430\\%u0440\\%u0438\\%u043d\\>", "examples": "\\%u0422\\%u0443\\%u0445\\%u0430\\%u0439\\%u043b\\%u0431\\%u0430\\%u043b", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u043e\\%u043d\\%u0430\\%u043b\\|\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446", "given": "\\%u04e8\\%u0433\\%u04e9\\%u0433\\%u0434\\%u0441\\%u04e9\\%u043d \\%u043d\\%u044c\\>\\|\\%u0410\\%u043d\\%u0445\\>", "rule": "Rule", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440", "scenario_outline": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u044b\\%u043d \\%u0442\\%u04e9\\%u043b\\%u04e9\\%u0432\\%u043b\\%u04e9\\%u0433\\%u04e9\\%u04e9", "then": "\\%u04ae\\%u04af\\%u043d\\%u0438\\%u0439 \\%u0434\\%u0430\\%u0440\\%u0430\\%u0430\\>\\|\\%u0422\\%u044d\\%u0433\\%u044d\\%u0445\\%u044d\\%u0434\\>", "when": "\\%u0425\\%u044d\\%u0440\\%u044d\\%u0432\\>"},
+ \"mr": {"and": "\\%u0924\\%u0938\\%u0947\\%u091a\\>\\|\\%u0906\\%u0923\\%u093f\\>", "background": "\\%u092a\\%u093e\\%u0930\\%u094d\\%u0936\\%u094d\\%u0935\\%u092d\\%u0942\\%u092e\\%u0940", "but": "\\%u092a\\%u0930\\%u0902\\%u0924\\%u0941\\>\\|\\%u092a\\%u0923\\>", "examples": "\\%u0909\\%u0926\\%u093e\\%u0939\\%u0930\\%u0923", "feature": "\\%u0935\\%u0948\\%u0936\\%u093f\\%u0937\\%u094d\\%u091f\\%u094d\\%u092f\\|\\%u0938\\%u0941\\%u0935\\%u093f\\%u0927\\%u093e", "given": "\\%u0926\\%u093f\\%u0932\\%u0947\\%u0932\\%u094d\\%u092f\\%u093e \\%u092a\\%u094d\\%u0930\\%u092e\\%u093e\\%u0923\\%u0947\\>\\|\\%u091c\\%u0930", "rule": "\\%u0928\\%u093f\\%u092f\\%u092e", "scenario": "\\%u092a\\%u0930\\%u093f\\%u0926\\%u0943\\%u0936\\%u094d\\%u092f", "scenario_outline": "\\%u092a\\%u0930\\%u093f\\%u0926\\%u0943\\%u0936\\%u094d\\%u092f \\%u0930\\%u0942\\%u092a\\%u0930\\%u0947\\%u0916\\%u093e", "then": "\\%u0924\\%u0947\\%u0935\\%u094d\\%u0939\\%u093e\\>\\|\\%u092e\\%u0917\\>", "when": "\\%u091c\\%u0947\\%u0935\\%u094d\\%u0939\\%u093e\\>"},
+ \"ne": {"and": "\\%u0905\\%u0928\\%u093f\\>\\|\\%u0930\\>", "background": "\\%u092a\\%u0943\\%u0937\\%u094d\\%u0920\\%u092d\\%u0942\\%u092e\\%u0940", "but": "\\%u0924\\%u0930\\>", "examples": "\\%u0909\\%u0926\\%u093e\\%u0939\\%u0930\\%u0923\\%u0939\\%u0930\\%u0941\\|\\%u0909\\%u0926\\%u093e\\%u0939\\%u0930\\%u0923", "feature": "\\%u0935\\%u093f\\%u0936\\%u0947\\%u0937\\%u0924\\%u093e\\|\\%u0938\\%u0941\\%u0935\\%u093f\\%u0927\\%u093e", "given": "\\%u0926\\%u093f\\%u0907\\%u090f\\%u0915\\%u094b\\>\\|\\%u0926\\%u093f\\%u090f\\%u0915\\%u094b\\>\\|\\%u092f\\%u0926\\%u093f\\>", "rule": "\\%u0928\\%u093f\\%u092f\\%u092e", "scenario": "\\%u092a\\%u0930\\%u093f\\%u0926\\%u0943\\%u0936\\%u094d\\%u092f", "scenario_outline": "\\%u092a\\%u0930\\%u093f\\%u0926\\%u0943\\%u0936\\%u094d\\%u092f \\%u0930\\%u0942\\%u092a\\%u0930\\%u0947\\%u0916\\%u093e", "then": "\\%u0924\\%u094d\\%u092f\\%u0938\\%u092a\\%u091b\\%u093f\\>\\|\\%u0905\\%u0928\\%u0940\\>", "when": "\\%u091c\\%u092c\\>"},
+ \"nl": {"and": "En\\>", "background": "Achtergrond", "but": "Maar\\>", "examples": "Voorbeelden", "feature": "Functionaliteit", "given": "Gegeven\\>\\|Stel\\>", "rule": "Rule", "scenario": "Voorbeeld\\|Scenario", "scenario_outline": "Abstract Scenario", "then": "Dan\\>", "when": "Wanneer\\>\\|Als\\>"},
+ \"no": {"and": "Og\\>", "background": "Bakgrunn", "but": "Men\\>", "examples": "Eksempler", "feature": "Egenskap", "given": "Gitt\\>", "rule": "Regel", "scenario": "Eksempel\\|Scenario", "scenario_outline": "Abstrakt Scenario\\|Scenariomal", "then": "S\\%u00e5\\>", "when": "N\\%u00e5r\\>"},
+ \"pa": {"and": "\\%u0a05\\%u0a24\\%u0a47\\>", "background": "\\%u0a2a\\%u0a3f\\%u0a1b\\%u0a4b\\%u0a15\\%u0a5c", "but": "\\%u0a2a\\%u0a30\\>", "examples": "\\%u0a09\\%u0a26\\%u0a3e\\%u0a39\\%u0a30\\%u0a28\\%u0a3e\\%u0a02", "feature": "\\%u0a28\\%u0a15\\%u0a36 \\%u0a28\\%u0a41\\%u0a39\\%u0a3e\\%u0a30\\|\\%u0a2e\\%u0a41\\%u0a39\\%u0a3e\\%u0a02\\%u0a26\\%u0a30\\%u0a3e\\|\\%u0a16\\%u0a3e\\%u0a38\\%u0a40\\%u0a05\\%u0a24", "given": "\\%u0a1c\\%u0a3f\\%u0a35\\%u0a47\\%u0a02 \\%u0a15\\%u0a3f\\>\\|\\%u0a1c\\%u0a47\\%u0a15\\%u0a30\\>", "rule": "Rule", "scenario": "\\%u0a09\\%u0a26\\%u0a3e\\%u0a39\\%u0a30\\%u0a28\\|\\%u0a2a\\%u0a1f\\%u0a15\\%u0a25\\%u0a3e", "scenario_outline": "\\%u0a2a\\%u0a1f\\%u0a15\\%u0a25\\%u0a3e \\%u0a30\\%u0a42\\%u0a2a \\%u0a30\\%u0a47\\%u0a16\\%u0a3e\\|\\%u0a2a\\%u0a1f\\%u0a15\\%u0a25\\%u0a3e \\%u0a22\\%u0a3e\\%u0a02\\%u0a1a\\%u0a3e", "then": "\\%u0a24\\%u0a26\\>", "when": "\\%u0a1c\\%u0a26\\%u0a4b\\%u0a02\\>"},
+ \"pl": {"and": "Oraz\\>\\|I\\>", "background": "Za\\%u0142o\\%u017cenia", "but": "Ale\\>", "examples": "Przyk\\%u0142ady", "feature": "Potrzeba biznesowa\\|W\\%u0142a\\%u015bciwo\\%u015b\\%u0107\\|Funkcja\\|Aspekt", "given": "Zak\\%u0142adaj\\%u0105c, \\%u017ce\\>\\|Zak\\%u0142adaj\\%u0105c\\>\\|Maj\\%u0105c\\>", "rule": "Zasada\\|Regu\\%u0142a", "scenario": "Scenariusz\\|Przyk\\%u0142ad", "scenario_outline": "Szablon scenariusza", "then": "Wtedy\\>", "when": "Je\\%u017celi\\>\\|Je\\%u015bli\\>\\|Kiedy\\>\\|Gdy\\>"},
+ \"pt": {"and": "E\\>", "background": "Cen\\%u00e1rio de Fundo\\|Cenario de Fundo\\|Contexto\\|Fundo", "but": "Mas\\>", "examples": "Exemplos\\|Cen\\%u00e1rios\\|Cenarios", "feature": "Funcionalidade\\|Caracter\\%u00edstica\\|Caracteristica", "given": "Dados\\>\\|Dadas\\>\\|Dado\\>\\|Dada\\>", "rule": "Regra", "scenario": "Exemplo\\|Cen\\%u00e1rio\\|Cenario", "scenario_outline": "Delinea\\%u00e7\\%u00e3o do Cen\\%u00e1rio\\|Delineacao do Cenario\\|Esquema do Cen\\%u00e1rio\\|Esquema do Cenario", "then": "Ent\\%u00e3o\\>\\|Entao\\>", "when": "Quando\\>"},
+ \"ro": {"and": "Si\\>\\|\\%u0218i\\>\\|\\%u015ei\\>", "background": "Context", "but": "Dar\\>", "examples": "Exemple", "feature": "Functionalitate\\|Func\\%u021bionalitate\\|Func\\%u0163ionalitate", "given": "Date fiind\\>\\|Dati fiind\\>\\|Da\\%u021bi fiind\\>\\|Da\\%u0163i fiind\\>\\|Dat fiind\\>\\|Dat\\%u0103 fiind", "rule": "Rule", "scenario": "Scenariu\\|Exemplu", "scenario_outline": "Structura scenariu\\|Structur\\%u0103 scenariu", "then": "Atunci\\>", "when": "Cand\\>\\|C\\%u00e2nd\\>"},
+ \"ru": {"and": "\\%u041a \\%u0442\\%u043e\\%u043c\\%u0443 \\%u0436\\%u0435\\>\\|\\%u0422\\%u0430\\%u043a\\%u0436\\%u0435\\>\\|\\%u0418\\>", "background": "\\%u041f\\%u0440\\%u0435\\%u0434\\%u044b\\%u0441\\%u0442\\%u043e\\%u0440\\%u0438\\%u044f\\|\\%u041a\\%u043e\\%u043d\\%u0442\\%u0435\\%u043a\\%u0441\\%u0442", "but": "\\%u0418\\%u043d\\%u0430\\%u0447\\%u0435\\>\\|\\%u041d\\%u043e\\>\\|\\%u0410\\>", "examples": "\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440\\%u044b", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u043e\\%u043d\\%u0430\\%u043b\\%u044c\\%u043d\\%u043e\\%u0441\\%u0442\\%u044c\\|\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u043e\\%u043d\\%u0430\\%u043b\\|\\%u0421\\%u0432\\%u043e\\%u0439\\%u0441\\%u0442\\%u0432\\%u043e\\|\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u044f\\|\\%u0424\\%u0438\\%u0447\\%u0430", "given": "\\%u0414\\%u043e\\%u043f\\%u0443\\%u0441\\%u0442\\%u0438\\%u043c\\>\\|\\%u041f\\%u0443\\%u0441\\%u0442\\%u044c\\>\\|\\%u0414\\%u0430\\%u043d\\%u043e\\>", "rule": "\\%u041f\\%u0440\\%u0430\\%u0432\\%u0438\\%u043b\\%u043e", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439\\|\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440", "scenario_outline": "\\%u0421\\%u0442\\%u0440\\%u0443\\%u043a\\%u0442\\%u0443\\%u0440\\%u0430 \\%u0441\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u044f\\|\\%u0428\\%u0430\\%u0431\\%u043b\\%u043e\\%u043d \\%u0441\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u044f", "then": "\\%u0417\\%u0430\\%u0442\\%u0435\\%u043c\\>\\|\\%u0422\\%u043e\\%u0433\\%u0434\\%u0430\\>\\|\\%u0422\\%u043e\\>", "when": "\\%u041a\\%u043e\\%u0433\\%u0434\\%u0430\\>\\|\\%u0415\\%u0441\\%u043b\\%u0438\\>"},
+ \"sk": {"and": "A taktie\\%u017e\\>\\|A z\\%u00e1rove\\%u0148\\>\\|A tie\\%u017e\\>\\|A\\>", "background": "Pozadie", "but": "Ale\\>", "examples": "Pr\\%u00edklady", "feature": "Po\\%u017eiadavka\\|Vlastnos\\%u0165\\|Funkcia", "given": "Za predpokladu\\>\\|Pokia\\%u013e\\>", "rule": "Rule", "scenario": "Pr\\%u00edklad\\|Scen\\%u00e1r", "scenario_outline": "Osnova Scen\\%u00e1ra\\|N\\%u00e1\\%u010drt Scen\\%u00e1ru\\|N\\%u00e1\\%u010drt Scen\\%u00e1ra", "then": "Potom\\>\\|Tak\\>", "when": "Ke\\%u010f\\>\\|Ak\\>"},
+ \"sl": {"and": "Ter\\>\\|In\\>", "background": "Kontekst\\|Osnova\\|Ozadje", "but": "Vendar\\>\\|Ampak\\>\\|Toda\\>", "examples": "Scenariji\\|Primeri", "feature": "Funkcionalnost\\|Zna\\%u010dilnost\\|Funkcija\\|Mo\\%u017enosti\\|Moznosti\\|Lastnost", "given": "Privzeto\\>\\|Podano\\>\\|Zaradi\\>\\|Dano\\>", "rule": "Rule", "scenario": "Scenarij\\|Primer", "scenario_outline": "Struktura scenarija\\|Oris scenarija\\|Koncept\\|Osnutek\\|Skica", "then": "Takrat\\>\\|Potem\\>\\|Nato\\>", "when": "Kadar\\>\\|Ko\\>\\|Ce\\>\\|\\%u010ce\\>"},
+ \"sr-Cyrl": {"and": "\\%u0418\\>", "background": "\\%u041a\\%u043e\\%u043d\\%u0442\\%u0435\\%u043a\\%u0441\\%u0442\\|\\%u041f\\%u043e\\%u0437\\%u0430\\%u0434\\%u0438\\%u043d\\%u0430\\|\\%u041e\\%u0441\\%u043d\\%u043e\\%u0432\\%u0430", "but": "\\%u0410\\%u043b\\%u0438\\>", "examples": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0458\\%u0438\\|\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440\\%u0438", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u043e\\%u043d\\%u0430\\%u043b\\%u043d\\%u043e\\%u0441\\%u0442\\|\\%u041c\\%u043e\\%u0433\\%u0443\\%u045b\\%u043d\\%u043e\\%u0441\\%u0442\\|\\%u041e\\%u0441\\%u043e\\%u0431\\%u0438\\%u043d\\%u0430", "given": "\\%u0417\\%u0430 \\%u0434\\%u0430\\%u0442\\%u043e\\>\\|\\%u0417\\%u0430 \\%u0434\\%u0430\\%u0442\\%u0435\\>\\|\\%u0417\\%u0430 \\%u0434\\%u0430\\%u0442\\%u0438\\>", "rule": "\\%u041f\\%u0440\\%u0430\\%u0432\\%u0438\\%u043b\\%u043e", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u043e\\|\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440\\|\\%u041f\\%u0440\\%u0438\\%u043c\\%u0435\\%u0440", "scenario_outline": "\\%u0421\\%u0442\\%u0440\\%u0443\\%u043a\\%u0442\\%u0443\\%u0440\\%u0430 \\%u0441\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0458\\%u0430\\|\\%u041a\\%u043e\\%u043d\\%u0446\\%u0435\\%u043f\\%u0442\\|\\%u0421\\%u043a\\%u0438\\%u0446\\%u0430", "then": "\\%u041e\\%u043d\\%u0434\\%u0430\\>", "when": "\\%u041a\\%u0430\\%u0434\\%u0430\\>\\|\\%u041a\\%u0430\\%u0434\\>"},
+ \"sr-Latn": {"and": "I\\>", "background": "Kontekst\\|Pozadina\\|Osnova", "but": "Ali\\>", "examples": "Scenariji\\|Primeri", "feature": "Funkcionalnost\\|Mogu\\%u0107nost\\|Mogucnost\\|Osobina", "given": "Za dato\\>\\|Za date\\>\\|Za dati\\>", "rule": "Pravilo", "scenario": "Scenario\\|Primer", "scenario_outline": "Struktura scenarija\\|Koncept\\|Skica", "then": "Onda\\>", "when": "Kada\\>\\|Kad\\>"},
+ \"sv": {"and": "Och\\>", "background": "Bakgrund", "but": "Men\\>", "examples": "Exempel", "feature": "Egenskap", "given": "Givet\\>", "rule": "Regel", "scenario": "Scenario", "scenario_outline": "Abstrakt Scenario\\|Scenariomall", "then": "S\\%u00e5\\>", "when": "N\\%u00e4r\\>"},
+ \"ta": {"and": "\\%u0bae\\%u0bc7\\%u0bb2\\%u0bc1\\%u0bae\\%u0bcd \\>\\|\\%u0bae\\%u0bb1\\%u0bcd\\%u0bb1\\%u0bc1\\%u0bae\\%u0bcd\\>", "background": "\\%u0baa\\%u0bbf\\%u0ba9\\%u0bcd\\%u0ba9\\%u0ba3\\%u0bbf", "but": "\\%u0b86\\%u0ba9\\%u0bbe\\%u0bb2\\%u0bcd \\>", "examples": "\\%u0b8e\\%u0b9f\\%u0bc1\\%u0ba4\\%u0bcd\\%u0ba4\\%u0bc1\\%u0b95\\%u0bcd\\%u0b95\\%u0bbe\\%u0b9f\\%u0bcd\\%u0b9f\\%u0bc1\\%u0b95\\%u0bb3\\%u0bcd\\|\\%u0ba8\\%u0bbf\\%u0bb2\\%u0bc8\\%u0bae\\%u0bc8\\%u0b95\\%u0bb3\\%u0bbf\\%u0bb2\\%u0bcd\\|\\%u0b95\\%u0bbe\\%u0b9f\\%u0bcd\\%u0b9a\\%u0bbf\\%u0b95\\%u0bb3\\%u0bcd", "feature": "\\%u0bb5\\%u0ba3\\%u0bbf\\%u0b95 \\%u0ba4\\%u0bc7\\%u0bb5\\%u0bc8\\|\\%u0b85\\%u0bae\\%u0bcd\\%u0b9a\\%u0bae\\%u0bcd\\|\\%u0ba4\\%u0bbf\\%u0bb1\\%u0ba9\\%u0bcd", "given": "\\%u0b95\\%u0bc6\\%u0bbe\\%u0b9f\\%u0bc1\\%u0b95\\%u0bcd\\%u0b95\\%u0baa\\%u0bcd\\%u0baa\\%u0b9f\\%u0bcd\\%u0b9f\\>", "rule": "Rule", "scenario": "\\%u0b89\\%u0ba4\\%u0bbe\\%u0bb0\\%u0ba3\\%u0bae\\%u0bbe\\%u0b95\\|\\%u0b95\\%u0bbe\\%u0b9f\\%u0bcd\\%u0b9a\\%u0bbf", "scenario_outline": "\\%u0b95\\%u0bbe\\%u0b9f\\%u0bcd\\%u0b9a\\%u0bbf \\%u0bb5\\%u0bbe\\%u0bb0\\%u0bcd\\%u0baa\\%u0bcd\\%u0baa\\%u0bc1\\%u0bb0\\%u0bc1\\|\\%u0b95\\%u0bbe\\%u0b9f\\%u0bcd\\%u0b9a\\%u0bbf \\%u0b9a\\%u0bc1\\%u0bb0\\%u0bc1\\%u0b95\\%u0bcd\\%u0b95\\%u0bae\\%u0bcd", "then": "\\%u0b85\\%u0baa\\%u0bcd\\%u0baa\\%u0bc6\\%u0bbe\\%u0bb4\\%u0bc1\\%u0ba4\\%u0bc1\\>", "when": "\\%u0b8e\\%u0baa\\%u0bcd\\%u0baa\\%u0bc7\\%u0bbe\\%u0ba4\\%u0bc1\\>"},
+ \"te": {"and": "\\%u0c2e\\%u0c30\\%u0c3f\\%u0c2f\\%u0c41\\>", "background": "\\%u0c28\\%u0c47\\%u0c2a\\%u0c25\\%u0c4d\\%u0c2f\\%u0c02", "but": "\\%u0c15\\%u0c3e\\%u0c28\\%u0c3f\\>", "examples": "\\%u0c09\\%u0c26\\%u0c3e\\%u0c39\\%u0c30\\%u0c23\\%u0c32\\%u0c41", "feature": "\\%u0c17\\%u0c41\\%u0c23\\%u0c2e\\%u0c41", "given": "\\%u0c1a\\%u0c46\\%u0c2a\\%u0c4d\\%u0c2a\\%u0c2c\\%u0c21\\%u0c3f\\%u0c28\\%u0c26\\%u0c3f\\>", "rule": "Rule", "scenario": "\\%u0c38\\%u0c28\\%u0c4d\\%u0c28\\%u0c3f\\%u0c35\\%u0c47\\%u0c36\\%u0c02\\|\\%u0c09\\%u0c26\\%u0c3e\\%u0c39\\%u0c30\\%u0c23", "scenario_outline": "\\%u0c15\\%u0c25\\%u0c28\\%u0c02", "then": "\\%u0c05\\%u0c2a\\%u0c4d\\%u0c2a\\%u0c41\\%u0c21\\%u0c41\\>", "when": "\\%u0c08 \\%u0c2a\\%u0c30\\%u0c3f\\%u0c38\\%u0c4d\\%u0c25\\%u0c3f\\%u0c24\\%u0c3f\\%u0c32\\%u0c4b\\>"},
+ \"th": {"and": "\\%u0e41\\%u0e25\\%u0e30\\>", "background": "\\%u0e41\\%u0e19\\%u0e27\\%u0e04\\%u0e34\\%u0e14", "but": "\\%u0e41\\%u0e15\\%u0e48\\>", "examples": "\\%u0e0a\\%u0e38\\%u0e14\\%u0e02\\%u0e2d\\%u0e07\\%u0e40\\%u0e2b\\%u0e15\\%u0e38\\%u0e01\\%u0e32\\%u0e23\\%u0e13\\%u0e4c\\|\\%u0e0a\\%u0e38\\%u0e14\\%u0e02\\%u0e2d\\%u0e07\\%u0e15\\%u0e31\\%u0e27\\%u0e2d\\%u0e22\\%u0e48\\%u0e32\\%u0e07", "feature": "\\%u0e04\\%u0e27\\%u0e32\\%u0e21\\%u0e15\\%u0e49\\%u0e2d\\%u0e07\\%u0e01\\%u0e32\\%u0e23\\%u0e17\\%u0e32\\%u0e07\\%u0e18\\%u0e38\\%u0e23\\%u0e01\\%u0e34\\%u0e08\\|\\%u0e04\\%u0e27\\%u0e32\\%u0e21\\%u0e2a\\%u0e32\\%u0e21\\%u0e32\\%u0e23\\%u0e16\\|\\%u0e42\\%u0e04\\%u0e23\\%u0e07\\%u0e2b\\%u0e25\\%u0e31\\%u0e01", "given": "\\%u0e01\\%u0e33\\%u0e2b\\%u0e19\\%u0e14\\%u0e43\\%u0e2b\\%u0e49\\>", "rule": "Rule", "scenario": "\\%u0e40\\%u0e2b\\%u0e15\\%u0e38\\%u0e01\\%u0e32\\%u0e23\\%u0e13\\%u0e4c", "scenario_outline": "\\%u0e42\\%u0e04\\%u0e23\\%u0e07\\%u0e2a\\%u0e23\\%u0e49\\%u0e32\\%u0e07\\%u0e02\\%u0e2d\\%u0e07\\%u0e40\\%u0e2b\\%u0e15\\%u0e38\\%u0e01\\%u0e32\\%u0e23\\%u0e13\\%u0e4c\\|\\%u0e2a\\%u0e23\\%u0e38\\%u0e1b\\%u0e40\\%u0e2b\\%u0e15\\%u0e38\\%u0e01\\%u0e32\\%u0e23\\%u0e13\\%u0e4c", "then": "\\%u0e14\\%u0e31\\%u0e07\\%u0e19\\%u0e31\\%u0e49\\%u0e19\\>", "when": "\\%u0e40\\%u0e21\\%u0e37\\%u0e48\\%u0e2d\\>"},
+ \"tlh": {"and": "latlh\\>\\|'ej\\>", "background": "mo'", "but": "'ach\\>\\|'a\\>", "examples": "ghantoH\\|lutmey", "feature": "poQbogh malja'\\|Qu'meH 'ut\\|perbogh\\|Qap\\|laH", "given": "DaH ghu' bejlu'\\>\\|ghu' noblu'\\>", "rule": "Rule", "scenario": "lut", "scenario_outline": "lut chovnatlh", "then": "vaj\\>", "when": "qaSDI'\\>"},
+ \"tr": {"and": "Ve\\>", "background": "Ge\\%u00e7mi\\%u015f", "but": "Fakat\\>\\|Ama\\>", "examples": "\\%u00d6rnekler", "feature": "\\%u00d6zellik", "given": "Diyelim ki\\>", "rule": "Kural", "scenario": "Senaryo\\|\\%u00d6rnek", "scenario_outline": "Senaryo tasla\\%u011f\\%u0131", "then": "O zaman\\>", "when": "E\\%u011fer ki\\>"},
+ \"tt": {"and": "\\%u04ba\\%u04d9\\%u043c\\>\\|\\%u0412\\%u04d9\\>", "background": "\\%u041a\\%u0435\\%u0440\\%u0435\\%u0448", "but": "\\%u041b\\%u04d9\\%u043a\\%u0438\\%u043d\\>\\|\\%u04d8\\%u043c\\%u043c\\%u0430\\>", "examples": "\\%u04ae\\%u0440\\%u043d\\%u04d9\\%u043a\\%u043b\\%u04d9\\%u0440\\|\\%u041c\\%u0438\\%u0441\\%u0430\\%u043b\\%u043b\\%u0430\\%u0440", "feature": "\\%u04ae\\%u0437\\%u0435\\%u043d\\%u0447\\%u04d9\\%u043b\\%u0435\\%u043a\\%u043b\\%u0435\\%u043b\\%u0435\\%u043a\\|\\%u041c\\%u04e9\\%u043c\\%u043a\\%u0438\\%u043d\\%u043b\\%u0435\\%u043a", "given": "\\%u04d8\\%u0439\\%u0442\\%u0438\\%u043a\\>", "rule": "Rule", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439", "scenario_outline": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439\\%u043d\\%u044b\\%u04a3 \\%u0442\\%u04e9\\%u0437\\%u0435\\%u043b\\%u0435\\%u0448\\%u0435", "then": "\\%u041d\\%u04d9\\%u0442\\%u0438\\%u0497\\%u04d9\\%u0434\\%u04d9\\>", "when": "\\%u04d8\\%u0433\\%u04d9\\%u0440\\>"},
+ \"uk": {"and": "\\%u0410 \\%u0442\\%u0430\\%u043a\\%u043e\\%u0436\\>\\|\\%u0422\\%u0430\\>\\|\\%u0406\\>", "background": "\\%u041f\\%u0435\\%u0440\\%u0435\\%u0434\\%u0443\\%u043c\\%u043e\\%u0432\\%u0430", "but": "\\%u0410\\%u043b\\%u0435\\>", "examples": "\\%u041f\\%u0440\\%u0438\\%u043a\\%u043b\\%u0430\\%u0434\\%u0438", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0456\\%u043e\\%u043d\\%u0430\\%u043b", "given": "\\%u041f\\%u0440\\%u0438\\%u043f\\%u0443\\%u0441\\%u0442\\%u0438\\%u043c\\%u043e, \\%u0449\\%u043e\\>\\|\\%u041f\\%u0440\\%u0438\\%u043f\\%u0443\\%u0441\\%u0442\\%u0438\\%u043c\\%u043e\\>\\|\\%u041d\\%u0435\\%u0445\\%u0430\\%u0439\\>\\|\\%u0414\\%u0430\\%u043d\\%u043e\\>", "rule": "Rule", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0456\\%u0439\\|\\%u041f\\%u0440\\%u0438\\%u043a\\%u043b\\%u0430\\%u0434", "scenario_outline": "\\%u0421\\%u0442\\%u0440\\%u0443\\%u043a\\%u0442\\%u0443\\%u0440\\%u0430 \\%u0441\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0456\\%u044e", "then": "\\%u0422\\%u043e\\%u0434\\%u0456\\>\\|\\%u0422\\%u043e\\>", "when": "\\%u042f\\%u043a\\%u0449\\%u043e\\>\\|\\%u041a\\%u043e\\%u043b\\%u0438\\>"},
+ \"ur": {"and": "\\%u0627\\%u0648\\%u0631\\>", "background": "\\%u067e\\%u0633 \\%u0645\\%u0646\\%u0638\\%u0631", "but": "\\%u0644\\%u06cc\\%u06a9\\%u0646\\>", "examples": "\\%u0645\\%u062b\\%u0627\\%u0644\\%u06cc\\%u06ba", "feature": "\\%u06a9\\%u0627\\%u0631\\%u0648\\%u0628\\%u0627\\%u0631 \\%u06a9\\%u06cc \\%u0636\\%u0631\\%u0648\\%u0631\\%u062a\\|\\%u0635\\%u0644\\%u0627\\%u062d\\%u06cc\\%u062a\\|\\%u062e\\%u0635\\%u0648\\%u0635\\%u06cc\\%u062a", "given": "\\%u0641\\%u0631\\%u0636 \\%u06a9\\%u06cc\\%u0627\\>\\|\\%u0628\\%u0627\\%u0644\\%u0641\\%u0631\\%u0636\\>\\|\\%u0627\\%u06af\\%u0631\\>", "rule": "Rule", "scenario": "\\%u0645\\%u0646\\%u0638\\%u0631\\%u0646\\%u0627\\%u0645\\%u06c1", "scenario_outline": "\\%u0645\\%u0646\\%u0638\\%u0631 \\%u0646\\%u0627\\%u0645\\%u06d2 \\%u06a9\\%u0627 \\%u062e\\%u0627\\%u06a9\\%u06c1", "then": "\\%u067e\\%u06be\\%u0631\\>\\|\\%u062a\\%u0628\\>", "when": "\\%u062c\\%u0628\\>"},
+ \"uz": {"and": "\\%u0412\\%u0430\\>", "background": "\\%u0422\\%u0430\\%u0440\\%u0438\\%u0445", "but": "\\%u041b\\%u0435\\%u043a\\%u0438\\%u043d\\>\\|\\%u0411\\%u0438\\%u0440\\%u043e\\%u043a\\>\\|\\%u0410\\%u043c\\%u043c\\%u043e\\>", "examples": "\\%u041c\\%u0438\\%u0441\\%u043e\\%u043b\\%u043b\\%u0430\\%u0440", "feature": "\\%u0424\\%u0443\\%u043d\\%u043a\\%u0446\\%u0438\\%u043e\\%u043d\\%u0430\\%u043b", "given": "Belgilangan\\>", "rule": "Rule", "scenario": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439", "scenario_outline": "\\%u0421\\%u0446\\%u0435\\%u043d\\%u0430\\%u0440\\%u0438\\%u0439 \\%u0441\\%u0442\\%u0440\\%u0443\\%u043a\\%u0442\\%u0443\\%u0440\\%u0430\\%u0441\\%u0438", "then": "\\%u0423\\%u043d\\%u0434\\%u0430\\>", "when": "\\%u0410\\%u0433\\%u0430\\%u0440\\>"},
+ \"vi": {"and": "V\\%u00e0\\>", "background": "B\\%u1ed1i c\\%u1ea3nh", "but": "Nh\\%u01b0ng\\>", "examples": "D\\%u1eef li\\%u1ec7u", "feature": "T\\%u00ednh n\\%u0103ng", "given": "Bi\\%u1ebft\\>\\|Cho\\>", "rule": "Rule", "scenario": "T\\%u00ecnh hu\\%u1ed1ng\\|K\\%u1ecbch b\\%u1ea3n", "scenario_outline": "Khung t\\%u00ecnh hu\\%u1ed1ng\\|Khung k\\%u1ecbch b\\%u1ea3n", "then": "Th\\%u00ec\\>", "when": "Khi\\>"},
+ \"zh-CN": {"and": "\\%u800c\\%u4e14\\|\\%u5e76\\%u4e14\\|\\%u540c\\%u65f6", "background": "\\%u80cc\\%u666f", "but": "\\%u4f46\\%u662f", "examples": "\\%u4f8b\\%u5b50", "feature": "\\%u529f\\%u80fd", "given": "\\%u5047\\%u5982\\|\\%u5047\\%u8bbe\\|\\%u5047\\%u5b9a", "rule": "Rule\\|\\%u89c4\\%u5219", "scenario": "\\%u573a\\%u666f\\|\\%u5267\\%u672c", "scenario_outline": "\\%u573a\\%u666f\\%u5927\\%u7eb2\\|\\%u5267\\%u672c\\%u5927\\%u7eb2", "then": "\\%u90a3\\%u4e48", "when": "\\%u5f53"},
+ \"zh-TW": {"and": "\\%u800c\\%u4e14\\|\\%u4e26\\%u4e14\\|\\%u540c\\%u6642", "background": "\\%u80cc\\%u666f", "but": "\\%u4f46\\%u662f", "examples": "\\%u4f8b\\%u5b50", "feature": "\\%u529f\\%u80fd", "given": "\\%u5047\\%u5982\\|\\%u5047\\%u8a2d\\|\\%u5047\\%u5b9a", "rule": "Rule", "scenario": "\\%u5834\\%u666f\\|\\%u5287\\%u672c", "scenario_outline": "\\%u5834\\%u666f\\%u5927\\%u7db1\\|\\%u5287\\%u672c\\%u5927\\%u7db1", "then": "\\%u90a3\\%u9ebc", "when": "\\%u7576"}}
function! s:pattern(key)
let language = matchstr(getline(1),'#\s*language:\s*\zs\S\+')
@@ -83,16 +107,18 @@ function! s:pattern(key)
endfunction
function! s:Add(name)
- let next = " skipempty skipwhite nextgroup=".join(map(["Region","AndRegion","ButRegion","Comment","String","Table"],'"cucumber".a:name.v:val'),",")
+ let next = " skipempty skipwhite nextgroup=".join(map(["Region","AndRegion","ButRegion","StarRegion","Comment","String","Table"],'"cucumber".a:name.v:val'),",")
exe "syn region cucumber".a:name.'Region matchgroup=cucumber'.a:name.' start="\%(^\s*\)\@<=\%('.s:pattern(tolower(a:name)).'\)" end="$"'.next
exe 'syn region cucumber'.a:name.'AndRegion matchgroup=cucumber'.a:name.'And start="\%(^\s*\)\@<='.s:pattern('and').'" end="$" contained'.next
exe 'syn region cucumber'.a:name.'ButRegion matchgroup=cucumber'.a:name.'But start="\%(^\s*\)\@<='.s:pattern('but').'" end="$" contained'.next
+ exe 'syn region cucumber'.a:name.'StarRegion matchgroup=cucumber'.a:name.'Star start="\%(^\s*\)\@<=\*\S\@!" end="$" contained'.next
exe 'syn match cucumber'.a:name.'Comment "\%(^\s*\)\@<=#.*" contained'.next
exe 'syn region cucumber'.a:name.'String start=+\%(^\s*\)\@<="""+ end=+"""+ contained'.next
exe 'syn match cucumber'.a:name.'Table "\%(^\s*\)\@<=|.*" contained contains=cucumberDelimiter'.next
exe 'hi def link cucumber'.a:name.'Comment cucumberComment'
exe 'hi def link cucumber'.a:name.'String cucumberString'
exe 'hi def link cucumber'.a:name.'But cucumber'.a:name.'And'
+ exe 'hi def link cucumber'.a:name.'Star cucumber'.a:name.'And'
exe 'hi def link cucumber'.a:name.'And cucumber'.a:name
exe 'syn cluster cucumberStepRegions add=cucumber'.a:name.'Region,cucumber'.a:name.'AndRegion,cucumber'.a:name.'ButRegion'
endfunction
@@ -100,12 +126,13 @@ endfunction
syn match cucumberComment "\%(^\s*\)\@<=#.*"
syn match cucumberComment "\%(\%^\s*\)\@<=#.*" contains=cucumberLanguage
syn match cucumberLanguage "\%(#\s*\)\@<=language:" contained
-syn match cucumberUnparsed "\S.*" nextgroup=cucumberUnparsedComment,cucumberUnparsed,cucumberTags,cucumberBackground,cucumberScenario,cucumberScenarioOutline,cucumberExamples skipwhite skipempty contained
-syn match cucumberUnparsedComment "#.*" nextgroup=cucumberUnparsedComment,cucumberUnparsed,cucumberTags,cucumberBackground,cucumberScenario,cucumberScenarioOutline,cucumberExamples skipwhite skipempty contained
+syn match cucumberUnparsed "\S.*" nextgroup=cucumberUnparsedComment,cucumberUnparsed,cucumberTags,cucumberBackground,cucumberRule,cucumberScenario,cucumberScenarioOutline,cucumberExamples skipwhite skipempty contained
+syn match cucumberUnparsedComment "#.*" nextgroup=cucumberUnparsedComment,cucumberUnparsed,cucumberTags,cucumberBackground,cucumberRule,cucumberScenario,cucumberScenarioOutline,cucumberExamples skipwhite skipempty contained
-exe 'syn match cucumberFeature "\%(^\s*\)\@<='.s:pattern('feature').':" nextgroup=cucumberUnparsedComment,cucumberUnparsed,cucumberBackground,cucumberScenario,cucumberScenarioOutline,cucumberExamples skipwhite skipempty'
+exe 'syn match cucumberFeature "\%(^\s*\)\@<='.s:pattern('feature').':" nextgroup=cucumberUnparsedComment,cucumberUnparsed,cucumberBackground,cucumberRule,cucumberScenario,cucumberScenarioOutline,cucumberExamples skipwhite skipempty'
exe 'syn match cucumberBackground "\%(^\s*\)\@<='.s:pattern('background').':"'
exe 'syn match cucumberScenario "\%(^\s*\)\@<='.s:pattern('scenario').':"'
+exe 'syn match cucumberRule "\%(^\s*\)\@<='.s:pattern('rule').':"'
exe 'syn match cucumberScenarioOutline "\%(^\s*\)\@<='.s:pattern('scenario_outline').':"'
exe 'syn match cucumberExamples "\%(^\s*\)\@<='.s:pattern('examples').':" nextgroup=cucumberExampleTable skipempty skipwhite'
@@ -123,6 +150,7 @@ hi def link cucumberComment Comment
hi def link cucumberLanguage SpecialComment
hi def link cucumberFeature Macro
hi def link cucumberBackground Define
+hi def link cucumberRule Define
hi def link cucumberScenario Define
hi def link cucumberScenarioOutline Define
hi def link cucumberExamples Define
diff --git a/runtime/syntax/dcl.vim b/runtime/syntax/dcl.vim
index 7e9741efc7..547fdcb9f7 100644
--- a/runtime/syntax/dcl.vim
+++ b/runtime/syntax/dcl.vim
@@ -1,9 +1,10 @@
" Vim syntax file
" Language: DCL (Digital Command Language - vms)
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Mar 26, 2019
" Version: 13
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_DCL
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_DCL
" quit when a syntax file was already loaded
if exists("b:current_syntax")
diff --git a/runtime/syntax/deb822sources.vim b/runtime/syntax/deb822sources.vim
index 81113610e8..f7d337fce9 100644
--- a/runtime/syntax/deb822sources.vim
+++ b/runtime/syntax/deb822sources.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: Debian deb822-format source list file
" Maintainer: Debian Vim Maintainers
-" Last Change: 2023 May 25
+" Last Change: 2024 Jan 30
" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/deb822sources.vim
" Standard syntax initialization
@@ -12,19 +12,19 @@ endif
" case insensitive
syn case ignore
+" A bunch of useful keywords
+syn match deb822sourcesType /\<\(deb-src\|deb\)\ */ contained
+syn match deb822sourcesFreeComponent /\<\(main\|universe\)\> */ contained
+syn match deb822sourcesNonFreeComponent /\<\(contrib\|non-free-firmware\|non-free\|restricted\|multiverse\)\> */ contained
+
" Comments are matched from the first character of a line to the end-of-line
syn region deb822sourcesComment start="^#" end="$"
-" A bunch of useful keywords
-syn match deb822sourcesType /\(deb-src\|deb\)/
-syn match deb822sourcesFreeComponent /\(main\|universe\)/
-syn match deb822sourcesNonFreeComponent /\(contrib\|non-free-firmware\|non-free\|restricted\|multiverse\)/
-
" Include Debian versioning information
runtime! syntax/shared/debversions.vim
-exe 'syn match deb822sourcesSupportedSuites contained + *\([[:alnum:]_./]*\)\<\('. join(g:debSharedSupportedVersions, '\|'). '\)\>\([-[:alnum:]_./]*\)+'
-exe 'syn match deb822sourcesUnsupportedSuites contained + *\([[:alnum:]_./]*\)\<\('. join(g:debSharedUnsupportedVersions, '\|'). '\)\>\([-[:alnum:]_./]*\)+'
+exe 'syn match deb822sourcesSupportedSuites contained + *\([[:alnum:]_./]*\)\<\('. join(g:debSharedSupportedVersions, '\|'). '\)\>\([-[:alnum:]_./]*\) *+'
+exe 'syn match deb822sourcesUnsupportedSuites contained + *\([[:alnum:]_./]*\)\<\('. join(g:debSharedUnsupportedVersions, '\|'). '\)\>\([-[:alnum:]_./]*\) *+'
unlet g:debSharedSupportedVersions
unlet g:debSharedUnsupportedVersions
@@ -37,13 +37,13 @@ syn keyword deb822sourcesYesNo contained yes no
" Match uri's
syn match deb822sourcesUri '\(https\?://\|ftp://\|[rs]sh://\|debtorrent://\|\(cdrom\|copy\|file\):\)[^' <>"]\+'
-syn match deb822sourcesEntryField "^\%(Types\|URIs\|Suites\|Components\): *"
-syn match deb822sourcesOptionField "^\%(Signed-By\|Check-Valid-Until\|Valid-Until-Min\|Valid-Until-Max\|Date-Max-Future\|InRelease-Path\): *"
-syn match deb822sourcesMultiValueOptionField "^\%(Architectures\|Languages\|Targets\)\%(-Add\|-Remove\)\?: *"
-
+syn region deb822sourcesStrictField matchgroup=deb822sourcesEntryField start="^\%(Types\|URIs\|Suites\|Components\): *" end="$" contains=deb822sourcesType,deb822sourcesUri,deb822sourcesSupportedSuites,deb822sourcesUnsupportedSuites,deb822sourcesFreeComponent,deb822sourcesNonFreeComponent oneline
+syn region deb822sourcesField matchgroup=deb822sourcesOptionField start="^\%(Signed-By\|Check-Valid-Until\|Valid-Until-Min\|Valid-Until-Max\|Date-Max-Future\|InRelease-Path\): *" end="$" oneline
+syn region deb822sourcesField matchgroup=deb822sourcesMultiValueOptionField start="^\%(Architectures\|Languages\|Targets\)\%(-Add\|-Remove\)\?: *" end="$" oneline
syn region deb822sourcesStrictField matchgroup=deb822sourcesBooleanOptionField start="^\%(PDiffs\|Allow-Insecure\|Allow-Weak\|Allow-Downgrade-To-Insecure\|Trusted\|Check-Date\): *" end="$" contains=deb822sourcesYesNo oneline
syn region deb822sourcesStrictField matchgroup=deb822sourcesForceBooleanOptionField start="^\%(By-Hash\): *" end="$" contains=deb822sourcesForce,deb822sourcesYesNo oneline
+hi def link deb822sourcesField Default
hi def link deb822sourcesComment Comment
hi def link deb822sourcesEntryField Keyword
hi def link deb822sourcesOptionField Special
diff --git a/runtime/syntax/debcontrol.vim b/runtime/syntax/debcontrol.vim
index af78ebc3ae..b173a7b3f7 100644
--- a/runtime/syntax/debcontrol.vim
+++ b/runtime/syntax/debcontrol.vim
@@ -3,7 +3,7 @@
" Maintainer: Debian Vim Maintainers
" Former Maintainers: Gerfried Fuchs <alfie@ist.org>
" Wichert Akkerman <wakkerma@debian.org>
-" Last Change: 2023 Jan 16
+" Last Change: 2023 Dec 22
" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/debcontrol.vim
" Standard syntax initialization
@@ -29,7 +29,7 @@ syn match debControlSpace "[ \t]"
let s:kernels = ['linux', 'hurd', 'kfreebsd', 'knetbsd', 'kopensolaris', 'netbsd']
let s:archs = [
\ 'alpha', 'amd64', 'armeb', 'armel', 'armhf', 'arm64', 'avr32', 'hppa'
- \, 'i386', 'ia64', 'lpia', 'm32r', 'm68k', 'mipsel', 'mips64el', 'mips'
+ \, 'i386', 'ia64', 'loong64', 'lpia', 'm32r', 'm68k', 'mipsel', 'mips64el', 'mips'
\, 'powerpcspe', 'powerpc', 'ppc64el', 'ppc64', 'riscv64', 's390x', 's390', 'sh3eb'
\, 'sh3', 'sh4eb', 'sh4', 'sh', 'sparc64', 'sparc', 'x32'
\ ]
diff --git a/runtime/syntax/debsources.vim b/runtime/syntax/debsources.vim
index 9846cfdef0..76b52cfaa4 100644
--- a/runtime/syntax/debsources.vim
+++ b/runtime/syntax/debsources.vim
@@ -2,7 +2,7 @@
" Language: Debian sources.list
" Maintainer: Debian Vim Maintainers
" Former Maintainer: Matthijs Mohlmann <matthijs@cacholong.nl>
-" Last Change: 2023 Oct 11
+" Last Change: 2024 Jan 30
" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/debsources.vim
" Standard syntax initialization
@@ -14,9 +14,9 @@ endif
syn case match
" A bunch of useful keywords
-syn match debsourcesType /\(deb-src\|deb\)/
-syn match debsourcesFreeComponent /\(main\|universe\)/
-syn match debsourcesNonFreeComponent /\(contrib\|non-free-firmware\|non-free\|restricted\|multiverse\)/
+syn match debsourcesType /\<\(deb-src\|deb\)\>/ contained
+syn match debsourcesFreeComponent /\<\(main\|universe\)\>/ contained
+syn match debsourcesNonFreeComponent /\<\(contrib\|non-free-firmware\|non-free\|restricted\|multiverse\)\>/ contained
" Match comments
syn match debsourcesComment /#.*/ contains=@Spell
@@ -34,7 +34,6 @@ unlet g:debSharedUnsupportedVersions
syn match debsourcesUri '\(https\?://\|ftp://\|[rs]sh://\|debtorrent://\|\(cdrom\|copy\|file\):\)[^' <>"]\+'
syn region debsourcesLine start="^" end="$" contains=debsourcesType,debsourcesFreeComponent,debsourcesNonFreeComponent,debsourcesComment,debsourcesUri,debsourcesDistrKeyword,debsourcesUnsupportedDistrKeyword oneline
-
" Associate our matches and regions with pretty colours
hi def link debsourcesType Statement
hi def link debsourcesFreeComponent Statement
diff --git a/runtime/syntax/diff.vim b/runtime/syntax/diff.vim
index 4cadf5dae8..b0a8594def 100644
--- a/runtime/syntax/diff.vim
+++ b/runtime/syntax/diff.vim
@@ -378,9 +378,9 @@ hi def link diffBDiffer Constant
hi def link diffIsA Constant
hi def link diffNoEOL Constant
hi def link diffCommon Constant
-hi def link diffRemoved Special
-hi def link diffChanged PreProc
-hi def link diffAdded Identifier
+hi def link diffRemoved Removed
+hi def link diffChanged Changed
+hi def link diffAdded Added
hi def link diffLine Statement
hi def link diffSubname PreProc
hi def link diffComment Comment
diff --git a/runtime/syntax/dosbatch.vim b/runtime/syntax/dosbatch.vim
index a75771bd2d..55601996ad 100644
--- a/runtime/syntax/dosbatch.vim
+++ b/runtime/syntax/dosbatch.vim
@@ -2,11 +2,11 @@
" Language: MS-DOS/Windows batch file (with NT command extensions)
" Maintainer: Mike Williams <mrmrdubya@gmail.com>
" Filenames: *.bat
-" Last Change: 12th February 2023
+" Last Change: 3rd February 2024
"
" Options Flags:
" dosbatch_cmdextversion - 1 = Windows NT, 2 = Windows 2000 [default]
-" dosbatch_colons_comment - any value to treat :: as comment line
+" dosbatch_colons_comment - any value to allow :: comments in code blocks
"
" quit when a syntax file was already loaded
@@ -88,18 +88,22 @@ syn match dosbatchLabel "\<goto\s\+\h\w*\>"lc=4
syn match dosbatchLabel ":\h\w*\>"
" Comments - usual rem but also two colons as first non-space is an idiom
-syn match dosbatchComment "^rem\($\|\s.*$\)"lc=3 contains=dosbatchTodo,dosbatchSpecialChar,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell
-syn match dosbatchComment "^@rem\($\|\s.*$\)"lc=4 contains=dosbatchTodo,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell
-syn match dosbatchComment "\srem\($\|\s.*$\)"lc=4 contains=dosbatchTodo,dosbatchSpecialChar,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell
-syn match dosbatchComment "\s@rem\($\|\s.*$\)"lc=5 contains=dosbatchTodo,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell
+syn match dosbatchRemComment "^rem\($\|\s.*$\)"lc=3 contains=dosbatchTodo,dosbatchSpecialChar,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell
+syn match dosbatchRemComment "^@rem\($\|\s.*$\)"lc=4 contains=dosbatchTodo,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell
+syn match dosbatchRemComment "\srem\($\|\s.*$\)"lc=4 contains=dosbatchTodo,dosbatchSpecialChar,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell
+syn match dosbatchRemComment "\s@rem\($\|\s.*$\)"lc=5 contains=dosbatchTodo,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell
+syn match dosbatchColonComment "\s*:\s*:.*$" contains=dosbatchTodo,dosbatchSpecialChar,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell
+
+" Commands code blocks
+syn cluster dosbatchCodeBlockComment contains=dosbatchRemComment
if exists("dosbatch_colons_comment")
- syn match dosbatchComment "\s*:\s*:.*$" contains=dosbatchTodo,dosbatchSpecialChar,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell
+ syn cluster dosbatchCodeBlockComment add=dosbatchColonComment
else
- syn match dosbatchError "\s*:\s*:.*$"
+ syn match dosbatchColonCommentErr contained "\s*:\s*:.*$"
endif
-
-" Comments in ()'s - still to handle spaces before rem
-syn match dosbatchComment "(rem\([^)]\|\^\@<=)\)*"lc=4 contains=dosbatchTodo,@dosbatchNumber,dosbatchVariable,dosbatchArgument,@Spell
+syn match dosbatchColonCommentErr contained "\s*:\s*:[^)]*\(\(\n\s*\)\?)\)\@="
+syn region dosbatchCodeBlock transparent start=+(+ end=+)+ contains=dosbatchString,dosbatchVariable,dosBatchArgument,@dosbatchNumber,dosbatchImplicit,dosbatchStatement,dosbatchConditional,dosbatchRepeat,dosbatchOperator,@dosbatchCodeBlockComment,dosbatchColonCommentErr,dosbatchCodeBlock
+syn match dosbatchCodeBlockErr ")"
syn keyword dosbatchImplicit append assoc at attrib break cacls cd chcp chdir
syn keyword dosbatchImplicit chkdsk chkntfs cls cmd color comp compact convert copy
@@ -116,6 +120,8 @@ syn keyword dosbatchImplicit vol xcopy
hi def link dosbatchTodo Todo
hi def link dosbatchError Error
+hi def link dosbatchCodeBlockErr dosbatchError
+hi def link dosbatchColonCommentErr dosbatchError
hi def link dosbatchStatement Statement
hi def link dosbatchCommands dosbatchStatement
@@ -140,6 +146,9 @@ hi def link dosbatchBinary dosbatchNumber
hi def link dosbatchOctal dosbatchNumber
hi def link dosbatchComment Comment
+hi def link dosbatchRemComment dosbatchComment
+hi def link dosbatchColonComment dosbatchComment
+
hi def link dosbatchImplicit Function
hi def link dosbatchSwitch Special
diff --git a/runtime/syntax/elmfilt.vim b/runtime/syntax/elmfilt.vim
index d995853e8e..aa1b57cbfe 100644
--- a/runtime/syntax/elmfilt.vim
+++ b/runtime/syntax/elmfilt.vim
@@ -1,9 +1,10 @@
" Vim syntax file
" Language: Elm Filter rules
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Aug 31, 2016
" Version: 9
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_ELMFILT
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_ELMFILT
" quit when a syntax file was already loaded
if exists("b:current_syntax")
diff --git a/runtime/syntax/exports.vim b/runtime/syntax/exports.vim
index 05a3f1acfe..00b7d80dfa 100644
--- a/runtime/syntax/exports.vim
+++ b/runtime/syntax/exports.vim
@@ -1,10 +1,11 @@
" Vim syntax file
" Language: exports
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Aug 31, 2016
" Version: 8
" Notes: This file includes both SysV and BSD 'isms
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_EXPORTS
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_EXPORTS
" quit when a syntax file was already loaded
if exists("b:current_syntax")
diff --git a/runtime/syntax/fortran.vim b/runtime/syntax/fortran.vim
index fc6c82b480..8167e4d737 100644
--- a/runtime/syntax/fortran.vim
+++ b/runtime/syntax/fortran.vim
@@ -1,7 +1,8 @@
" Vim syntax file
-" Language: Fortran 2008 (and older: Fortran 2003, 95, 90, and 77)
-" Version: (v105) 2023 August 14
-" Maintainer: Ajit J. Thakkar <ajit@unb.ca>; <http://www2.unb.ca/~ajit/>
+" Language: Fortran 2023 (and Fortran 2018, 2008, 2003, 95, 90, and 77)
+" Version: (v113) 2024 February 01
+" Maintainers: Ajit J. Thakkar <ajit@unb.ca>; <https://ajit.ext.unb.ca/>
+" Joshua Hollett <j.hollett@uwinnipeg.ca>
" Usage: For instructions, do :help fortran-syntax from Vim
" Credits:
" Version 0.1 for Fortran 95 was created in April 2000 by Ajit Thakkar from an
@@ -11,7 +12,8 @@
" Walter Dieudonne, Alexander Wagner, Roman Bertle, Charles Rendleman,
" Andrew Griffiths, Joe Krahn, Hendrik Merx, Matt Thompson, Jan Hermann,
" Stefano Zaghi, Vishnu V. Krishnan, Judicael Grasset, Takuma Yoshida,
-" Eisuke Kawashima, Andre Chalella, Fritz Reese, and Karl D. Hammond.
+" Eisuke Kawashima, Andre Chalella, Fritz Reese, Karl D. Hammond,
+" and Michele Esposito Marzino.
if exists("b:current_syntax")
finish
@@ -20,35 +22,10 @@ endif
let s:cpo_save = &cpo
set cpo&vim
-" Choose fortran_dialect using the priority:
-" source file directive > buffer-local value > global value > file extension
-" first try using directive in first three lines of file
-let b:fortran_retype = getline(1)." ".getline(2)." ".getline(3)
-if b:fortran_retype =~? '\<fortran_dialect\s*=\s*F\>'
- let b:fortran_dialect = "F"
-elseif b:fortran_retype =~? '\<fortran_dialect\s*=\s*f08\>'
- let b:fortran_dialect = "f08"
-elseif !exists("b:fortran_dialect")
- if exists("g:fortran_dialect") && g:fortran_dialect =~# '\<F\|f08\>'
- " try global variable
- let b:fortran_dialect = g:fortran_dialect
- else " nothing found, so use default
- let b:fortran_dialect = "f08"
- endif
-endif
-unlet! b:fortran_retype
-" make sure buffer-local value is not invalid
-if b:fortran_dialect !~# '\<F\|f08\>'
- let b:fortran_dialect = "f08"
-endif
-
" Choose between fixed and free source form if this hasn't been done yet
if !exists("b:fortran_fixed_source")
- if b:fortran_dialect == "F"
- " F requires free source form
- let b:fortran_fixed_source = 0
- elseif exists("fortran_free_source")
- " User guarantees free source form for all fortran files
+ if exists("fortran_free_source")
+ " User guarantees free source form for all Fortran files
let b:fortran_fixed_source = 0
elseif exists("fortran_fixed_source")
" User guarantees fixed source form for all fortran files
@@ -60,7 +37,7 @@ if !exists("b:fortran_fixed_source")
" Fixed-form file extension defaults
let b:fortran_fixed_source = 1
else
- " Modern fortran still allows both free and fixed source form.
+ " Modern Fortran compilers still allow both free and fixed source form.
" Assume fixed source form unless signs of free source form
" are detected in the first five columns of the first s:lmax lines.
" Detection becomes more accurate and time-consuming if more lines
@@ -84,6 +61,9 @@ if !exists("b:fortran_fixed_source")
endif
endif
+" Group names ending in 'Del' and 'Ob', respectively, indicate features deleted and obsolescent in Fortran 2018 and later
+" Deleted features are highlighted as errors
+" Obsolescent features are highlighted as todo items
syn case ignore
if b:fortran_fixed_source == 1
@@ -91,46 +71,107 @@ if b:fortran_fixed_source == 1
else
syn match fortranConstructName "^\s*\zs\a\w*\ze\s*:"
endif
-if exists("fortran_more_precise")
- syn match fortranConstructName "\(\<end\s*do\s\+\)\@11<=\a\w*"
- syn match fortranConstructName "\(\<end\s*if\s\+\)\@11<=\a\w*"
- syn match fortranConstructName "\(\<end\s*select\s\+\)\@15<=\a\w*"
- syn match fortranConstructName "\(\<\%(exit\|cycle\)\s\+\)\@11<=\a\w*"
+syn match fortranConstructName "\%(\<end\s*do\s\+\)\@11<=\a\w*"
+syn match fortranConstructName "\%(\<end\s*if\s\+\)\@11<=\a\w*"
+syn match fortranConstructName "\%(\<end\s*select\s\+\)\@15<=\a\w*"
+syn match fortranConstructName "\%(\<end\s*where\s\+\)\@14<=\a\w*"
+syn match fortranConstructName "\%(\<end\s*block\s\+\)\@14<=\a\w*"
+syn match fortranConstructName "\%(\<\%(exit\|cycle\)\s\+\)\@11<=\a\w*"
+syn match fortranConstructName "\%(\<end\s*forall\s\+\)\@15<=\a\w*\>"
+syn match fortranConstructName "\%(\<end\s*critical\s\+\)\@17<=\a\w*\>"
+syn match fortranConstructName "\%(\<end\s*associate\s\+\)\@18<=\a\w*\>"
+
+syn match fortranUnitName "\%(\<\%(end\s*\)\?\%(subroutine\|function\|module\|program\|submodule\)\s\+\)\@12<=\a\w*"
+syn match fortranUnitHeader "\<end\>\ze\s*\%(!.*\)\?$"
+
+syn keyword fortranIntrinsic abs acos aimag aint anint asin atan atan2 cmplx conjg cos cosh exp ichar index int log log10 max min nint sin sinh sqrt tan tanh
+syn keyword fortranIntrinsicR achar iachar transfer dble dprod dim lge lgt lle llt mod
+syn keyword fortranIntrinsic command_argument_count get_command get_command_argument get_environment_variable is_iostat_end is_iostat_eor move_alloc new_line same_type_as extends_type_of
+syn keyword fortranIntrinsic selected_real_kind selected_int_kind selected_logical_kind selected_char_kind next previous
+syn keyword fortranIntrinsic acosh asinh atanh bessel_j0 bessel_j1 bessel_jn bessel_y0 bessel_y1 bessel_yn erf erfc erfc_scaled gamma log_gamma hypot norm2
+syn keyword fortranIntrinsic adjustl adjustr all allocated any associated bit_size btest ceiling cshift date_and_time digits
+syn keyword fortranIntrinsic dot_product eoshift exponent floor fraction iand ibclr ibits ibset ieor ior ishft ishftc lbound len_trim matmul maxexponent maxloc merge minexponent minloc
+syn keyword fortranIntrinsic modulo mvbits nearest pack precision present radix random_number random_seed range repeat reshape rrspacing scale scan set_exponent shape spacing
+" intrinsic names often used for variables in older Fortran code
+syn match fortranIntrinsic '\<\%(count\|epsilon\|maxval\|minval\|product\|sum\|huge\|tiny\|char\)\>\ze\s*('
+syn keyword fortranIntrinsic spread system_clock transpose trim ubound unpack verify is_contiguous event_query
+syn keyword fortranIntrinsic atomic_define atomic_ref execute_command_line leadz trailz storage_size merge_bits
+syn keyword fortranIntrinsic bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr num_images parity popcnt poppar shifta shiftl shiftr this_image
+syn keyword fortranIntrinsic null cpu_time failed_images stopped_images image_status co_broadcast co_max co_min co_sum co_reduce
+syn keyword fortranIntrinsic atomic_add atomic_and atomic_or atomic_xor atomic_fetch_add atomic_fetch_and atomic_fetch_or atomic_fetch_xor atomic_cas
+syn keyword fortranIntrinsic ieee_arithmetic ieee_features ieee_exceptions
+syn keyword fortranIntrinsic ieee_class ieee_copy_sign ieee_fma ieee_get_rounding_mode ieee_get_underflow_mode ieee_int ieee_is_finite
+syn keyword fortranIntrinsic ieee_is_nan ieee_is_negative ieee_is_normal ieee_logb ieee_max ieee_max_mag ieee_max_num ieee_max_num_mag
+syn keyword fortranIntrinsic ieee_min ieee_min_mag ieee_min_num ieee_min_num_mag ieee_next_after ieee_next_down ieee_next_up ieee_quiet_eq
+syn keyword fortranIntrinsic ieee_quiet_ge ieee_quiet_gt ieee_quiet_le ieee_quiet_lt ieee_quiet_ne ieee_real ieee_rem ieee_rint ieee_scalb
+syn keyword fortranIntrinsic ieee_selected_real_kind ieee_set_rounding_mode ieee_set_underflow_mode ieee_signaling_eq ieee_signaling_ge
+syn keyword fortranIntrinsic ieee_signaling_gt ieee_signaling_le ieee_signaling_lt ieee_signaling_ne ieee_signbit ieee_support_datatype
+syn keyword fortranIntrinsic ieee_support_denormal ieee_support_divide ieee_support_inf ieee_support_io ieee_support_nan ieee_support_rounding
+syn keyword fortranIntrinsic ieee_support_sqrt ieee_support_subnormal ieee_support_standard ieee_support_underflow_control
+syn keyword fortranIntrinsic ieee_unordered ieee_value ieee_get_flag ieee_get_halting_mode ieee_get_modes ieee_get_status
+syn keyword fortranIntrinsic ieee_set_flag ieee_set_halting_mode ieee_set_modes ieee_set_status ieee_support_flag ieee_support_halting
+syn keyword fortranIntrinsic iso_c_binding c_loc c_funloc c_sizeof c_associated c_f_pointer c_f_procpointer c_f_strpointer f_c_string
+syn keyword fortranIntrinsic iso_fortran_env compiler_options compiler_version
+syn keyword fortranIntrinsic out_of_range reduce random_init coshape get_team split tokenize
+syn keyword fortranIntrinsic acosd asind atand atan2d cosd sind tand acospi asinpi atanpi atan2pi cospi sinpi tanpi
+syn match fortranIntrinsic "\%(^\s*\|type *is *(\s*\)\@12<!\<real\ze\s*("
+syn match fortranIntrinsic '\<\%(logical\|not\|len\|kind\|rank\)\>\ze\s*('
+syn match fortranIntrinsic '\<\%(sign\|size\|team_number\)\>\ze\s*('
+" Obsolescent type-specific intrinsics
+syn keyword fortranIntrinsicOb alog alog10 amax0 amax1 amin0 amin1 amod cabs ccos cexp clog csin csqrt dabs dacos dasin datan datan2 dcos dcosh ddim dexp dint dlog dlog10 dmax1 dmin1 dmod dnint dsign dsin dsinh dsqrt dtan dtanh float iabs idim idint idnint ifix isign max0 max1 min0 min1 sngl
+if exists("fortran_vendor_intrinsics")
+ syn keyword fortranIntrinsicVen algama cdabs cdcos cdexp cdlog cdsin cdsqrt cqabs cqcos cqexp cqlog cqsin cqsqrt dcmplx dconjg derf derfc dfloat dgamma dimag dlgama iqint qabs qacos qasin qatan qatan2 qcmplx qconjg qcos qcosh qdim qerf qerfc qexp qgamma qimag qlgama qlog qlog10 qmax1 qmin1 qmod qnint qsign qsin qsinh qsqrt qtan qtanh
endif
-syn match fortranUnitHeader "\<end\>"
-syn match fortranType "\<character\((\s*kind\s*=\w\+)\)\?\>"
-syn match fortranType "\<complex\((\s*kind\s*=\w\+)\)\?\>"
-syn keyword fortranType intrinsic
-syn match fortranType "\<implicit\>\s\+\(none\)\?"
-syn keyword fortranStructure dimension
-syn keyword fortranStorageClass parameter save
-syn match fortranUnitHeader "\<subroutine\>"
-syn keyword fortranCall call
-syn match fortranUnitHeader "\<function\>"
-syn match fortranUnitHeader "\<program\>"
-syn match fortranUnitHeader "\<block\>"
-syn keyword fortranKeyword return stop
-syn keyword fortranConditional else then
-syn match fortranConditional "\<if\>"
-syn match fortranConditionalOb "\<if\s*(.*)\s*\d\+\s*,\s*\d\+\s*,\s*\d\+\s*$"
+syn keyword fortranType generic final enumerator import classof typeof team_type event_type lock_type notify_type
+syn keyword fortranType ieee_flag_type ieee_modes_type ieee_status_type ieee_class_type ieee_round_type ieee_features_type
+syn keyword fortranType c_ptr c_funptr elemental pure impure recursive non_recursive simple
+syn match fortranType "^\s*\%(implicit\s\+\)\?\%(real\|double\s*precision\|integer\|logical\|complex\|character\|type\)\>"
+syn match fortranTypeOb "^\s*\%(character\s*\)\@15<=\*"
+syn match fortranType "^\s*\zsimplicit\s\+none\>"
+syn match fortranType "\<class\>"
+syn match fortranType "\%(\<type\s\+is\s\+[(]\s*\)\@15<=\%(real\|double\s*precision\|integer\|logical\|complex\|character\)\>"
+syn match fortranType "\<\%(end\s*\)\?interface\>"
+syn match fortranType "\<enum\s*,\s*bind\s*(\s*c\s*)"
+syn match fortranType "\<end\s*\%(enum\|type\)\>"
+syn match fortranType "\<\%(end\s*\)\?enumeration\s\+type\>"
+syn match fortranType "\<\%(end\s*\)\?\%(module\s\+\)\?procedure\>"
+syn match fortranType "\%(simple \|pure \|impure \|recursive \|non_recursive \|elemental \|module \)\@17<=\%(real\|double precision\|integer\|logical\|complex\|character\)"
+syn match fortranTypeR display "\<double\s*precision\>"
+syn match fortranTypeR display "\<double\s\+complex\>"
+syn keyword fortranAttribute abstract allocatable bind codimension contiguous deferred dimension extends
+syn keyword fortranAttribute external intent intrinsic non_intrinsic non_overridable nopass optional parameter pass
+syn keyword fortranAttribute pointer private protected public save sequence target value volatile
+syn match fortranAttribute "\<asynchronous\>\ze\s*\%(::\|,\|(\)"
+
+syn keyword fortranUnitHeader result operator assignment
+syn match fortranUnitHeader "\<\%(end\s*\)\?\%(subroutine\|function\|module\|program\|submodule\)\>"
+syn match fortranBlock "\<\%(end\s*\)\?\%(block\|critical\|associate\)\>"
+syn match fortranCalled "\<\%(call\s\+\)\@7<=\a\w*"
syn match fortranRepeat "\<do\>"
+syn keyword fortranRepeat concurrent
+syn keyword fortranRepeatR while
+syn match fortranRepeat "\<end\s*do\>"
+syn keyword fortranRepeatOb forall
+syn match fortranRepeatOb "\<end\s*forall\>"
-syn keyword fortranTodo contained todo fixme
+syn keyword fortranTodo contained bug note debug todo fixme
"Catch errors caused by too many right parentheses
syn region fortranParen transparent start="(" end=")" contains=ALLBUT,fortranParenError,@fortranCommentGroup,cIncluded,@spell
syn match fortranParenError ")"
-syn match fortranOperator "\.\s*n\=eqv\s*\."
-syn match fortranOperator "\.\s*\(and\|or\|not\)\s*\."
-syn match fortranOperator "\(+\|-\|/\|\*\)"
-syn match fortranTypeOb "\<character\s*\*"
-
-syn match fortranBoolean "\.\s*\(true\|false\)\s*\."
+syn match fortranOperator "\.\s*n\?eqv\s*\."
+syn match fortranOperator "\.\s*\%(and\|or\|not\)\s*\."
+syn match fortranOperator "\%(+\|-\|/\|\*\)"
+syn match fortranOperator "\%(\%(>\|<\)=\?\|==\|/=\|=\)"
+syn match fortranOperator "\%(%\|?\|=>\)"
+syn match fortranOperator "\%([\|]\)"
+syn match fortranOperatorR "\.\s*[gl][et]\s*\."
+syn match fortranOperatorR "\.\s*\%(eq\|ne\)\s*\."
-syn keyword fortranReadWrite print
-syn match fortranReadWrite '\<\(backspace\|close\|endfile\|inquire\|open\|read\|rewind\|write\)\ze\s*('
+syn keyword fortranReadWrite print flush
+syn match fortranReadWrite '\<\%(backspace\|close\|endfile\|inquire\|open\|read\|rewind\|wait\|write\)\ze\s*('
"If tabs are allowed then the left margin checks do not work
if exists("fortran_have_tabs")
@@ -139,34 +180,19 @@ else
syn match fortranTab "\t"
endif
-syn match fortranIO '\%(\((\|,\|, *&\n\)\s*\)\@<=\(access\|blank\|direct\|exist\|file\|fmt\|form\|formatted\|iostat\|name\|named\|nextrec\|number\|opened\|rec\|recl\|sequential\|status\|unformatted\|unit\)\ze\s*='
-
-syn keyword fortranIntrinsicR alog alog10 amax0 amax1 amin0 amin1 amod cabs ccos cexp clog csin csqrt dabs dacos dasin datan datan2 dcos dcosh ddim dexp dint dlog dlog10 dmax1 dmin1 dmod dnint dsign dsin dsinh dsqrt dtan dtanh float iabs idim idint idnint ifix isign max0 max1 min0 min1 sngl
-
-" Intrinsics provided by some vendors
-syn keyword fortranExtraIntrinsic algama cdabs cdcos cdexp cdlog cdsin cdsqrt cqabs cqcos cqexp cqlog cqsin cqsqrt dcmplx dconjg derf derfc dfloat dgamma dimag dlgama iqint qabs qacos qasin qatan qatan2 qcmplx qconjg qcos qcosh qdim qerf qerfc qexp qgamma qimag qlgama qlog qlog10 qmax1 qmin1 qmod qnint qsign qsin qsinh qsqrt qtan qtanh
-
-syn keyword fortranIntrinsic abs acos aimag aint anint asin atan atan2 char cmplx conjg cos cosh exp ichar index int log log10 max min nint sign sin sinh sqrt tan tanh
-syn match fortranIntrinsic "\<len\s*[(,]"me=s+3
-syn match fortranIntrinsic "\<real\s*("me=s+4
-syn match fortranIntrinsic "\<logical\s*("me=s+7
-syn match fortranType "\<type\>\(\s\+is\>\)\?"
-syn match fortranType "^\s*\(type\s\+\(is\)\? \)\?\s*\(real\|integer\|logical\|complex\|character\)\>"
-syn match fortranType "^\s*\(implicit \)\?\s*\(real\|integer\|logical\|complex\|character\)\>"
-
"Numbers of various sorts
" Integers
-syn match fortranNumber display "\<\d\+\(_\a\w*\)\=\>"
+syn match fortranNumber display "\<\d\+\%(_\a\w*\)\?\>"
" floating point number, without a decimal point
-syn match fortranFloatIll display "\<\d\+[deq][-+]\=\d\+\(_\a\w*\)\=\>"
+syn match fortranFloatIll display "\<\d\+[deq][-+]\?\d\+\%(_\a\w*\)\?\>"
" floating point number, starting with a decimal point
-syn match fortranFloatIll display "\.\d\+\([deq][-+]\=\d\+\)\=\(_\a\w*\)\=\>"
+syn match fortranFloatIll display "\.\d\+\%([deq][-+]\?\d\+\)\?\%(_\a\w*\)\?\>"
" floating point number, no digits after decimal
-syn match fortranFloatIll display "\<\d\+\.\([deq][-+]\=\d\+\)\=\(_\a\w*\)\=\>"
+syn match fortranFloatIll display "\<\d\+\.\%([deq][-+]\?\d\+\)\?\%(_\a\w*\)\?\>"
" floating point number, D or Q exponents
-syn match fortranFloatIll display "\<\d\+\.\d\+\([dq][-+]\=\d\+\)\=\(_\a\w*\)\=\>"
+syn match fortranFloatIll display "\<\d\+\.\d\+\%([dq][-+]\?\d\+\)\?\%(_\a\w*\)\?\>"
" floating point number
-syn match fortranFloat display "\<\d\+\.\d\+\(e[-+]\=\d\+\)\=\(_\a\w*\)\=\>"
+syn match fortranFloat display "\<\d\+\.\d\+\%(e[-+]\?\d\+\)\?\%(_\a\w*\)\?\>"
" binary number
syn match fortranBinary display "b["'][01]\+["']"
" octal number
@@ -175,151 +201,95 @@ syn match fortranOctal display "o["'][0-7]\+["']"
syn match fortranHex display "z["'][0-9A-F]\+["']"
" Numbers in formats
syn match fortranFormatSpec display "\d*f\d\+\.\d\+"
-syn match fortranFormatSpec display "\d*e[sn]\=\d\+\.\d\+\(e\d+\>\)\="
-syn match fortranFormatSpec display "\d*\(d\|q\|g\)\d\+\.\d\+\(e\d+\)\="
+syn match fortranFormatSpec display "\d*e[sn]\?\d\+\.\d\+\%(e\d+\>\)\?"
+syn match fortranFormatSpec display "\d*\%(d\|q\|g\)\d\+\.\d\+\%(e\d+\)\?"
syn match fortranFormatSpec display "\d\+x\>"
" The next match cannot be used because it would pick up identifiers as well
-" syn match fortranFormatSpec display "\<\(a\|i\)\d\+"
-
+" syn match fortranFormatSpec display "\<\%(a\|i\)\d\+"
" Numbers as labels
-syn match fortranLabelNumber display "^\d\{1,5}\s"me=e-1
-syn match fortranLabelNumber display "^ \d\{1,4}\s"ms=s+1,me=e-1
-syn match fortranLabelNumber display "^ \d\{1,3}\s"ms=s+2,me=e-1
-syn match fortranLabelNumber display "^ \d\d\=\s"ms=s+3,me=e-1
-syn match fortranLabelNumber display "^ \d\s"ms=s+4,me=e-1
-
-if exists("fortran_more_precise")
- " Numbers as targets
- syn match fortranTarget display "\(\<if\s*(.\+)\s*\)\@<=\(\d\+\s*,\s*\)\{2}\d\+\>"
- syn match fortranTarget display "\(\<do\s\+\)\@11<=\d\+\>"
- syn match fortranTarget display "\(\<go\s*to\s*(\=\)\@11<=\(\d\+\s*,\s*\)*\d\+\>"
+if (b:fortran_fixed_source == 1)
+ syn match fortranLabelNumber display "^\zs\d\{1,5}\ze\s"
+ syn match fortranLabelNumber display "^ \zs\d\{1,4}\ze\s"
+ syn match fortranLabelNumber display "^ \zs\d\{1,3}\ze\s"
+ syn match fortranLabelNumber display "^ \zs\d\d\?\ze\s"
+ syn match fortranLabelNumber display "^ \zs\d\ze\s"
+else
+ syn match fortranLabelNumber display "^\s*\zs\d\{1,5}\ze\s*\a"
+ syn match fortranLabelNumberOb display "^\s*\zs\d\{1,5}\ze *end\s*\%(do\|if\)\>\ze"
endif
+" Numbers as targets
+syn match fortranTarget display "\%(\<if\s*(.\+)\s*\)\@<=\%(\d\+\s*,\s*\)\{2}\d\+\>"
+syn match fortranTargetOb display "\%(\<do\s*,\?\s*\)\@11<=\d\+\>"
+syn match fortranTarget display "\%(\<go\s*to\s*(\?\)\@11<=\%(\d\+\s*,\s*\)*\d\+\>"
-syn keyword fortranTypeR external
-syn keyword fortranIOR format
-syn match fortranKeywordR "\<continue\>"
-syn match fortranKeyword "^\s*\d\+\s\+continue\>"
+syn match fortranBoolean "\.\s*\%(true\|false\)\s*\."
+
+syn keyword fortranKeyword call use only continue allocate deallocate nullify return cycle exit contains
+syn match fortranKeyword "\<fail\s\+image\>"
+syn match fortranKeyword "\<\%(error\s\+\)\?stop\>"
syn match fortranKeyword "\<go\s*to\>"
syn match fortranKeywordDel "\<go\s*to\ze\s\+.*,\s*(.*$"
syn match fortranKeywordOb "\<go\s*to\ze\s*(\d\+.*$"
-syn region fortranStringR start=+'+ end=+'+ contains=fortranContinueMark,fortranLeftMargin,fortranSerialNumber
-syn keyword fortranIntrinsicR dim lge lgt lle llt mod
-syn keyword fortranKeywordDel assign pause
-
-syn keyword fortranStructure private public intent optional
-syn keyword fortranStructure pointer target allocatable
-syn keyword fortranStorageClass in out
-syn match fortranStorageClass "\<kind\s*="me=s+4
-syn match fortranStorageClass "\<len\s*="me=s+3
-
-syn match fortranUnitHeader "\<module\>"
-syn match fortranUnitHeader "\<submodule\>"
-syn keyword fortranUnitHeader use only contains
-syn keyword fortranUnitHeader result operator assignment
-syn match fortranUnitHeader "\<interface\>"
-syn keyword fortranKeyword allocate deallocate nullify cycle exit
-syn match fortranConditional "\<select\>"
-syn match fortranConditional "\<case\s\+default\>"
-syn keyword fortranConditional where elsewhere
-
-syn match fortranOperator "\(\(>\|<\)=\=\|==\|/=\|=\)"
-syn match fortranOperator "=>"
+syn keyword fortranKeywordDel pause
+syn match fortranKeywordDel "assign\s*\d\+\s*to\s\+\a\w*"
+syn match fortranStringDel display "[/(,] *\d\+H"
+syn region fortranString start=+'+ end=+'+ contains=fortranLeftMargin,fortranContinueMark,fortranSerialNumber
syn region fortranString start=+"+ end=+"+ contains=fortranLeftMargin,fortranContinueMark,fortranSerialNumber
-syn keyword fortranIO pad position action delim readwrite
-syn keyword fortranIO eor advance nml
-
-syn match fortranIntrinsic '\<\(adjustl\|adjustr\|all\|allocated\|any\|associated\|bit_size\|btest\|ceiling\|count\|cshift\|date_and_time\|digits\|dot_product\|eoshift\|epsilon\|exponent\|floor\|fraction\|huge\|iand\|ibclr\|ibits\|ibset\|ieor\|ior\|ishft\|ishftc\|lbound\|len_trim\|matmul\|maxexponent\|maxloc\|maxval\|merge\|minexponent\|minloc\|minval\|modulo\|mvbits\|nearest\|pack\|precision\|present\|product\|radix\|random_number\|random_seed\|range\|repeat\|reshape\|rrspacing\|scale\|scan\|selected_int_kind\|selected_real_kind\|set_exponent\|shape\|size\|spacing\|spread\|sum\|system_clock\|tiny\|transpose\|trim\|ubound\|unpack\|verify\)\>\ze\s*('
-syn match fortranIntrinsic "\<not\>\(\s*\.\)\@!"me=s+3
-syn match fortranIntrinsic "\<kind\>\s*[(,]"me=s+4
-
-syn match fortranUnitHeader "\<end\s*function"
-syn match fortranUnitHeader "\<end\s*interface"
-syn match fortranUnitHeader "\<end\s*module"
-syn match fortranUnitHeader "\<end\s*submodule"
-syn match fortranUnitHeader "\<end\s*program"
-syn match fortranUnitHeader "\<end\s*subroutine"
-syn match fortranUnitHeader "\<end\s*block"
-syn match fortranRepeat "\<end\s*do"
-syn match fortranConditional "\<end\s*where"
-syn match fortranConditional "\<select\s*case"
-syn match fortranConditional "\<end\s*select"
-syn match fortranType "\<end\s*type"
-syn match fortranType "\<in\s*out"
-
-syn keyword fortranType procedure
-syn match fortranType "\<module\ze\s\+procedure\>"
-syn keyword fortranIOR namelist
-syn keyword fortranConditionalR while
-syn keyword fortranIntrinsicR achar iachar transfer
+
+syn match fortranSpecifier '\%(\%((\|,\|, *&\n\)\s*\)\@<=\%(access\|acquired_lock\|action\|advance\|asynchronous\|blank\|decimal\|delim\|direct\|encoding\|end\|eor\|err\)\ze\s*='
+syn match fortranSpecifier '\%(\%((\|,\|, *&\n\)\s*\)\@<=\%(errmsg\|exist\|file\|fmt\|form\|formatted\|id\|iolength\|iomsg\|iostat\|leading_zero\|mold\|name\|named\)\ze\s*='
+syn match fortranSpecifier '\%(\%((\|,\|, *&\n\)\s*\)\@<=\%(new_index\|newunit\|nextrec\|nml\|notify\|number\|opened\|pad\|pending\|pos\|position\|quiet\)\ze\s*='
+syn match fortranSpecifier '\%(\%((\|,\|, *&\n\)\s*\)\@<=\%(read\|readwrite\|rec\|recl\|round\|sequential\|sign\|size\)\ze\s*='
+syn match fortranSpecifier '\%(\%((\|,\|, *&\n\)\s*\)\@<=\%(source\|stat\|status\|stream\|team\|team_number\|unformatted\|unit\|until_count\|write\)\ze\s*='
+syn match fortranSpecifier "\%((\s*\)\@<=\%(un\)\?formatted\ze\s*)"
+syn match fortranSpecifier "\%(local\|local_init\|reduce\|shared\)\ze\s*("
+syn match fortranSpecifier "\<default\s*(\s*none\s*)"
+syn keyword fortranIOR format namelist
+
+syn keyword fortranConditional else then where elsewhere
+syn match fortranConditional "\<\%(else\s*\)\?if\>"
+syn match fortranConditional "\<\%(end\s*\)\?\%(if\|where\|select\)\>"
+syn match fortranConditional "\<select\s*\%(case\|rank\|type\)\>"
+syn match fortranConditional "\<\%(case\|rank\|class\)\s\+default\>"
+syn match fortranConditional "^\s*\zs\%(case\|rank\)\ze\s\+("
+syn match fortranConditional "\<\%(class\|type\)\s\+is\>"
+syn match fortranConditionalDel "\<if\s*(.*)\s*\d\+\s*,\s*\d\+\s*,\s*\d\+\s*$"
syn keyword fortranInclude include
-syn keyword fortranStorageClassR sequence
-syn match fortranConditional "\<end\s*if"
-syn match fortranIO contains=fortranOperator "\<e\(nd\|rr\)\s*=\s*\d\+"
-syn match fortranConditional "\<else\s*if"
+syn match fortranImageControl "\<sync\s\+\%(all\|images\|memory\|team\)\>"
+syn match fortranImageControl "\<\%(change\|form\|end\)\s\+team\>"
+syn match fortranImageControl "\<event\s\+\%(post\|wait\)"
+syn match fortranImageControl "\<\%(un\)\?lock\ze\s*("
+syn match fortranImageControl "\<notify\s\+wait\ze\s*("
syn keyword fortranUnitHeaderOb entry
-syn match fortranTypeR display "double\s\+precision"
-syn match fortranTypeR display "double\s\+complex"
-syn match fortranUnitHeaderR display "block\s\+data"
-syn keyword fortranStorageClassR common equivalence data
-syn keyword fortranIntrinsicR dble dprod
-syn match fortranOperatorR "\.\s*[gl][et]\s*\."
-syn match fortranOperatorR "\.\s*\(eq\|ne\)\s*\."
-
-syn keyword fortranRepeat forall
-syn match fortranRepeat "\<end\s*forall"
-syn keyword fortranIntrinsic null cpu_time
-syn match fortranType "\<elemental\>"
-syn match fortranType "\<pure\>"
-syn match fortranType "\<impure\>"
-syn match fortranType "\<recursive\>"
-if exists("fortran_more_precise")
- syn match fortranConstructName "\(\<end\s*forall\s\+\)\@15<=\a\w*\>"
-endif
-
-if b:fortran_dialect == "f08"
- " F2003
- syn keyword fortranIntrinsic command_argument_count get_command get_command_argument get_environment_variable is_iostat_end is_iostat_eor move_alloc new_line selected_char_kind same_type_as extends_type_of
- " ISO_C_binding
- syn keyword fortranConstant c_null_char c_alert c_backspace c_form_feed c_new_line c_carriage_return c_horizontal_tab c_vertical_tab
- syn keyword fortranConstant c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr
- syn keyword fortranIntrinsic iso_c_binding c_loc c_funloc c_associated c_f_pointer c_f_procpointer
- syn keyword fortranType c_ptr c_funptr
- " ISO_Fortran_env
- syn keyword fortranConstant iso_fortran_env character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor numeric_storage_size output_unit
- " IEEE_arithmetic
- syn keyword fortranIntrinsic ieee_arithmetic ieee_support_underflow_control ieee_get_underflow_mode ieee_set_underflow_mode
-
- syn keyword fortranReadWrite flush wait
- syn keyword fortranIO decimal round iomsg
- syn keyword fortranType asynchronous nopass non_overridable pass protected volatile extends import
- syn keyword fortranType non_intrinsic value bind deferred generic final enumerator
- syn match fortranType "\<abstract\>"
- syn match fortranType "\<class\>"
- syn match fortranType "\<associate\>"
- syn match fortranType "\<end\s*associate"
- syn match fortranType "\<enum\s*,\s*bind\s*(\s*c\s*)"
- syn match fortranType "\<end\s*enum"
- syn match fortranConditional "\<select\s*type"
- syn match fortranConditional "\<class\s*is\>"
- syn match fortranConditional "\<class\s*default\>"
- syn match fortranUnitHeader "\<abstract\s*interface\>"
- syn match fortranOperator "\([\|]\)"
-
- " F2008
- syn keyword fortranIntrinsic acosh asinh atanh bessel_j0 bessel_j1 bessel_jn bessel_y0 bessel_y1 bessel_yn erf erfc erfc_scaled gamma log_gamma hypot norm2
- syn keyword fortranIntrinsic atomic_define atomic_ref execute_command_line leadz trailz storage_size merge_bits
- syn keyword fortranIntrinsic bge bgt ble blt dshiftl dshiftr findloc iall iany iparity image_index lcobound ucobound maskl maskr num_images parity popcnt poppar shifta shiftl shiftr this_image
- syn keyword fortranIO newunit
- syn keyword fortranType contiguous
- syn keyword fortranRepeat concurrent
-
-" CUDA fortran
+syn match fortranUnitHeaderOb display "\<block\s*data\>"
+
+syn keyword fortranStorageClass in out inout
+syn match fortranStorageClass '\<\%(kind\|len\)\>\ze\s*='
+syn match fortranStorageClass "^\s*data\>\ze\%(\s\+\a\)\@="
+syn match fortranStorageClassOb "\<common\>\%(\s*\%(/\|\a\)\)\@="
+syn match fortranStorageClassOb "\<equivalence\>\%(\s*(\)\@="
+
+syn keyword fortranConstant c_null_char c_alert c_backspace c_form_feed c_new_line c_carriage_return c_horizontal_tab c_vertical_tab c_ptrdiff_t
+syn keyword fortranConstant c_int c_short c_long c_long_long c_signed_char c_size_t c_int8_t c_int16_t c_int32_t c_int64_t c_int_least8_t c_int_least16_t c_int_least32_t c_int_least64_t c_int_fast8_t c_int_fast16_t c_int_fast32_t c_int_fast64_t c_intmax_t C_intptr_t c_float c_double c_long_double c_float_complex c_double_complex c_long_double_complex c_bool c_char c_null_ptr c_null_funptr
+syn keyword fortranConstant character_storage_size error_unit file_storage_size input_unit iostat_end iostat_eor numeric_storage_size output_unit stat_failed_image stat_locked stat_locked_other_image stat_stopped_image stat_unlocked stat_unlocked_failed_image
+syn keyword fortranConstant int8 int16 int32 int64 real16 real32 real64 real128 character_kinds integer_kinds logical_kinds real_kinds iostat_inquire_internal_unit initial_team current_team parent_team
+syn keyword fortranConstant ieee_invalid ieee_overflow ieee_divide_by_zero ieee_underflow ieee_inexact ieee_usual ieee_all
+syn keyword fortranConstant ieee_signaling_nan ieee_quiet_nan ieee_negative_inf ieee_negative_normal ieee_negative_subnormal
+syn keyword fortranConstant ieee_negative_zero ieee_positive_zero ieee_positive_subnormal ieee_positive_normal ieee_positive_inf
+syn keyword fortranConstant ieee_other_value ieee_negative_denormal ieee_positive_denormal ieee_negative_subnormal
+syn keyword fortranConstant ieee_positive_subnormal ieee_nearest ieee_to_zero ieee_up ieee_down ieee_away ieee_other ieee_datatype
+syn keyword fortranConstant ieee_denormal ieee_divide ieee_halting ieee_inexact_flag ieee_inf ieee_invalid_flag ieee_nan
+syn keyword fortranConstant ieee_rounding ieee_sqrt ieee_subnormal ieee_underflow_flag
+syn match fortranConstant "\.\s*nil\s*\."
+
+" CUDA Fortran
+if exists("fortran_CUDA")
syn match fortranTypeCUDA "\<attributes\>"
- syn keyword fortranTypeCUDA host global device value
+ syn keyword fortranTypeCUDA host global device
syn keyword fortranTypeCUDA shared constant pinned texture
syn keyword fortranTypeCUDA dim1 dim2 dim3 dim4
syn keyword fortranTypeCUDA cudadeviceprop cuda_count_kind cuda_stream_kind
@@ -336,10 +306,10 @@ if b:fortran_dialect == "f08"
syn keyword fortranTypeCUDA cudaErrorNotReady cudaSuccess cudaErrorInvalidValue
syn keyword fortranTypeCUDA c_devptr
- syn match fortranStringCUDA "blockidx%[xyz]"
- syn match fortranStringCUDA "blockdim%[xyz]"
- syn match fortranStringCUDA "griddim%[xyz]"
- syn match fortranStringCUDA "threadidx%[xyz]"
+ syn match fortranStringCUDA "\<blockidx%[xyz]\>"
+ syn match fortranStringCUDA "\<blockdim%[xyz]\>"
+ syn match fortranStringCUDA "\<griddim%[xyz]\>"
+ syn match fortranStringCUDA "\<threadidx%[xyz]\>"
syn keyword fortranIntrinsicCUDA warpsize syncthreads syncthreads_and syncthreads_count syncthreads_or threadfence threadfence_block threadfence_system gpu_time allthreads anythread ballot
syn keyword fortranIntrinsicCUDA atomicadd atomicsub atomicmax atomicmin atomicand atomicor atomicxor atomicexch atomicinc atomicdec atomiccas sizeof __shfl __shfl_up __shfl_down __shfl_xor
@@ -349,22 +319,21 @@ if b:fortran_dialect == "f08"
syn keyword fortranIntrinsicCUDA cudaHostAlloc cudaHostGetDevicePointer cudaHostGetFlags cudaHostRegister cudaHostUnregister cudaMalloc cudaMallocArray cudaMallocHost cudaMallocPitch cudaMalloc3D cudaMalloc3DArray
syn keyword fortranIntrinsicCUDA cudaMemcpy cudaMemcpyArraytoArray cudaMemcpyAsync cudaMemcpyFromArray cudaMemcpyFromSymbol cudaMemcpyFromSymbolAsync cudaMemcpyPeer cudaMemcpyPeerAsync cudaMemcpyToArray cudaMemcpyToSymbol cudaMemcpyToSymbolAsync cudaMemcpy2D cudaMemcpy2DArrayToArray cudaMemcpy2DAsync cudaMemcpy2DFromArray cudaMemcpy2DToArray cudaMemcpy3D cudaMemcpy3DAsync
syn keyword fortranIntrinsicCUDA cudaMemGetInfo cudaMemset cudaMemset2D cudaMemset3D cudaDeviceCanAccessPeer cudaDeviceDisablePeerAccess cudaDeviceEnablePeerAccess cudaPointerGetAttributes cudaDriverGetVersion cudaRuntimeGetVersion
-
- syn region none matchgroup=fortranType start="<<<" end=">>>" contains=ALLBUT,none
endif
+syn region none matchgroup=fortranType start="<<<" end=">>>" contains=ALLBUT,none
+
syn cluster fortranCommentGroup contains=fortranTodo
if (b:fortran_fixed_source == 1)
if !exists("fortran_have_tabs")
- " Fixed format requires a textwidth of 72 for code,
- " but some vendor extensions allow longer lines
if exists("fortran_extended_line_length")
+ " Vendor extensions allow lines with a text width of 132
syn match fortranSerialNumber excludenl "^.\{133,}$"lc=132
- elseif exists("fortran_cardimage_line_length")
- syn match fortranSerialNumber excludenl "^.\{81,}$"lc=80
else
- syn match fortranSerialNumber excludenl "^.\{73,}$"lc=72
+ " Standard requires fixed format to have a text width of 72,
+ " but all current compilers use 80 instead
+ syn match fortranSerialNumber excludenl "^.\{81,}$"lc=80
endif
"Flag left margin errors
syn match fortranLabelError "^.\{-,4}[^0-9 ]" contains=fortranTab
@@ -378,20 +347,20 @@ else
endif
syn match fortranComment excludenl "!.*$" contains=@fortranCommentGroup,@spell
-syn match fortranOpenMP excludenl "^\s*!\$\(OMP\)\=&\=\s.*$"
+syn match fortranOpenMP excludenl "^\s*\zs!\$\%(OMP\)\?&\?\s.*$"
+syn match fortranEndStatement display ";"
"cpp is often used with Fortran
-syn match cPreProc "^\s*#\s*\(define\|ifdef\)\>.*"
-syn match cPreProc "^\s*#\s*\(elif\|if\)\>.*"
-syn match cPreProc "^\s*#\s*\(ifndef\|undef\)\>.*"
-syn match cPreCondit "^\s*#\s*\(else\|endif\)\>.*"
+syn match cPreProc "^\s*#\s*\%(define\|ifdef\)\>.*"
+syn match cPreProc "^\s*#\s*\%(elif\|if\)\>.*"
+syn match cPreProc "^\s*#\s*\%(ifndef\|undef\)\>.*"
+syn match cPreCondit "^\s*#\s*\%(else\|endif\)\>.*"
syn region cIncluded contained start=+"[^("]+ skip=+\\\\\|\\"+ end=+"+ contains=fortranLeftMargin,fortranContinueMark,fortranSerialNumber
-"syn region cIncluded contained start=+"[^("]+ skip=+\\\\\|\\"+ end=+"+
syn match cIncluded contained "<[^>]*>"
syn match cInclude "^\s*#\s*include\>\s*["<]" contains=cIncluded
"Synchronising limits assume that comment and continuation lines are not mixed
-if exists("fortran_fold") || exists("fortran_more_precise")
+if exists("fortran_fold")
syn sync fromstart
elseif (b:fortran_fixed_source == 0)
syn sync linecont "&" minlines=30
@@ -401,149 +370,118 @@ endif
if exists("fortran_fold")
+ if has("folding")
+ setlocal foldmethod=syntax
+ endif
if (b:fortran_fixed_source == 1)
- syn region fortranProgram transparent fold keepend start="^\s*program\s\+\z(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\(program\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranModule
- syn region fortranModule transparent fold keepend start="^\s*submodule\s\+(\a\w*\s*\(:\a\w*\s*\)*)\s*\z\(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\(submodule\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranProgram,fortranModule
- syn region fortranModule transparent fold keepend start="^\s*module\s\+\(procedure\)\@!\z(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\(module\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranProgram
- syn region fortranFunction transparent fold keepend extend start="^\s*\(elemental \|pure \|impure \|module \|recursive \)\=\s*\(\(\(real \|integer \|logical \|complex \|double \s*precision \)\s*\((\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\|type\s\+(\s*\w\+\s*) \|character \((\(\s*len\s*=\)\=\s*\d\+\s*)\|(\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\=\s*function\s\+\z(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\($\|function\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule
- syn region fortranSubroutine transparent fold keepend extend start="^\s*\(elemental \|pure \|impure \|module \|recursive \)\=\s*subroutine\s\+\z(\a\w*\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\($\|subroutine\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule
- syn region fortranBlockData transparent fold keepend start="\<block\s*data\(\s\+\z(\a\w*\)\)\=" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*\($\|block\s*data\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock
- syn region fortranAssociate transparent fold keepend start="^\s*\<associate\s\+" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*associate" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction
- syn region fortranInterface transparent fold keepend extend start="^\s*\(abstract \)\=\s*interface\>" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*interface\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock
- syn region fortranTypeDef transparent fold keepend extend start="^\s*type\s*\(,\s*\(public\|private\|abstract\)\)\=\s*::" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*type\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock,fortranInterface
+ syn region fortranProgram transparent fold keepend start="^\s*program\s\+\z(\a\w*\)" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*\%(program\%(\s\+\z1\>\)\?\|$\)" contains=ALLBUT,fortranModule
+ syn region fortranModule transparent fold keepend start="^\s*submodule\s\+(\a\w*\s*\%(:\a\w*\s*\)*)\s*\z\(\a\w*\)" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*\%(submodule\%(\s\+\z1\>\)\?\|$\)" contains=ALLBUT,fortranProgram,fortranModule
+ syn region fortranModule transparent fold keepend start="^\s*module\s\+\%(procedure\)\@9!\z(\a\w*\)" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*\%(module\%(\s\+\z1\>\)\?\|$\)" contains=ALLBUT,fortranProgram
+ syn region fortranFunction transparent fold keepend extend start="\<function\s\+\z(\a\w*\)" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*\%($\|function\%(\s\+\z1\>\)\?\)" contains=ALLBUT,fortranProgram,fortranModule
+ syn region fortranSubroutine transparent fold keepend extend start="\<subroutine\s\+\z(\a\w*\)" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*\%($\|subroutine\%(\s\+\z1\>\)\?\)" contains=ALLBUT,fortranProgram,fortranModule
+ syn region fortranBlockData transparent fold keepend start="\<block\>" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*block\>" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock
+ syn region fortranAssociate transparent fold keepend start="\<associate\s\+" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*associate" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction
+ syn region fortranCritical transparent fold keepend start="\<critical\s\+" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*critical" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction
+ syn region fortranTeam transparent fold keepend start="\<change\s\+team\>" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*team\>" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction
+ syn region fortranInterface transparent fold keepend extend start="\<\%(abstract \)\?\s*interface\>" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*interface\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock
+ syn region fortranTypeDef transparent fold keepend extend start="^\s*type\s*\%(,\s*\%(abstract\|private\|public\|bind(c)\|extends(\a\w*)\)\)\{0,4}\s*::\s*\z(\a\w*\)" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*type\>\%(\s\+\z1\>\)\?" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction
+ syn region fortranMultiComments fold start="^\zs[!c*].*\_s*[!c*]" skip="^[!c*]" end='^\ze\s*[^!c*]'
else
- syn region fortranProgram transparent fold keepend start="^\s*program\s\+\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\(program\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranModule
- syn region fortranModule transparent fold keepend start="^\s*submodule\s\+(\a\w*\s*\(:\a\w*\s*\)*)\s*\z\(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\(submodule\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranProgram,fortranModule
- syn region fortranModule transparent fold keepend start="^\s*module\s\+\(procedure\)\@!\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\(module\(\s\+\z1\>\)\=\|$\)" contains=ALLBUT,fortranProgram
- syn region fortranFunction transparent fold keepend extend start="^\s*\(elemental \|pure \|impure \|module \|recursive \)\=\s*\(\(\(real \|integer \|logical \|complex \|double \s*precision \)\s*\((\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\|type\s\+(\s*\w\+\s*) \|character \((\(\s*len\s*=\)\=\s*\d\+\s*)\|(\(\s*kind\s*=\)\=\s*\w\+\s*)\)\=\)\=\s*function\s\+\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\($\|function\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule
- syn region fortranSubroutine transparent fold keepend extend start="^\s*\(elemental \|pure \|impure \|module \|recursive \)\=\s*subroutine\s\+\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\($\|subroutine\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule
- syn region fortranBlockData transparent fold keepend start="\<block\s*data\(\s\+\z(\a\w*\)\)\=" skip="^\s*[!#].*$" excludenl end="\<end\s*\($\|block\s*data\(\s\+\z1\>\)\=\)" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock
- syn region fortranAssociate transparent fold keepend start="^\s*\<associate\s\+" skip="^\s*[!#].*$" excludenl end="\<end\s*associate" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction
- syn region fortranInterface transparent fold keepend extend start="^\s*\(abstract \)\=\s*interface\>" skip="^\s*[!#].*$" excludenl end="\<end\s*interface\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock
- syn region fortranTypeDef transparent fold keepend extend start="^\s*type\s*\(,\s*\(public\|private\|abstract\)\)\=\s*::" skip="^\s*[!#].*$" excludenl end="\<end\s*type\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock,fortranInterface
+ syn region fortranProgram transparent fold keepend start="^\s*program\s\+\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\%(program\%(\s\+\z1\>\)\?\|$\)" contains=ALLBUT,fortranModule
+ syn region fortranModule transparent fold keepend start="^\s*submodule\s\+(\a\w*\s*\%(:\a\w*\s*\)*)\s*\z\(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\%(submodule\%(\s\+\z1\>\)\?\|$\)" contains=ALLBUT,fortranProgram,fortranModule
+ syn region fortranModule transparent fold keepend start="^\s*module\s\+\%(procedure\)\@9!\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\%(module\%(\s\+\z1\>\)\?\|$\)" contains=ALLBUT,fortranProgram
+ syn region fortranFunction transparent fold keepend extend start="\<function\s\+\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\%($\|function\%(\s\+\z1\>\)\?\)" contains=ALLBUT,fortranProgram,fortranModule
+ syn region fortranSubroutine transparent fold keepend extend start="\<subroutine\s\+\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*\%($\|subroutine\%(\s\+\z1\>\)\?\)" contains=ALLBUT,fortranProgram,fortranModule
+ syn region fortranBlockData transparent fold keepend start="\<block\>" skip="^\s*[!#].*$" excludenl end="\<end\s*block\>" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock
+ syn region fortranAssociate transparent fold keepend start="\<associate\>" skip="^\s*[!#].*$" excludenl end="\<end\s*associate\>" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction
+ syn region fortranCritical transparent fold keepend start="\<critical\>" skip="^\s*[!#].*$" excludenl end="\<end\s*critical\>" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction
+ syn region fortranTeam transparent fold keepend start="\<change\s\+team\>" skip="^\s*[!#].*$" excludenl end="\<end\s*team\>" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction
+ syn region fortranInterface transparent fold keepend extend start="\<\%(abstract \)\?\s*interface\>" skip="^\s*[!#].*$" excludenl end="\<end\s*interface\>" contains=ALLBUT,fortranProgram,fortranModule,fortran77Loop,fortranCase,fortran90Loop,fortranIfBlock
+ syn region fortranTypeDef transparent fold keepend extend start="^\s*type\s*\%(,\s*\%(abstract\|private\|public\|bind(c)\|extends(\a\w*)\)\)\{0,4}\s*::\s*\z(\a\w*\)" skip="^\s*[!#].*$" excludenl end="\<end\s*type\>\%(\s\+\z1\>\)\?" contains=ALLBUT,fortranProgram,fortranModule,fortranSubroutine,fortranFunction
+ syn region fortranMultiComments fold start="^\zs\s*!.*\_s*!" skip="^\s*!" end='^\ze\s*[^!]'
endif
if exists("fortran_fold_conditionals")
if (b:fortran_fixed_source == 1)
- syn region fortran77Loop transparent fold keepend start="\<do\s\+\z(\d\+\)" end="^\s*\z1\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
- syn region fortran90Loop transparent fold keepend extend start="\(\<end\s\+\)\@<!\<do\(\s\+\a\|\s*$\)" skip="^\([!c*]\|\s*#\).*$" excludenl end="\<end\s*do\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
- syn region fortranIfBlock transparent fold keepend extend start="\(\<e\(nd\|lse\)\s\+\)\@<!\<if\s*(.\+)\s*then\>" skip="^\([!c*]\|\s*#\).*$" end="\<end\s*if\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
- syn region fortranCase transparent fold keepend extend start="\<select\s*\(case\|type\)\>" skip="^\([!c*]\|\s*#\).*$" end="\<end\s*select\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
+ syn region fortran77Loop transparent fold keepend start="\<do\s\+\z(\d\+\)" end="^\s*\z1\>" contains=ALLBUT,fortranUnitHeader,fortranAttribute,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
+ syn region fortran90Loop transparent fold keepend extend start="\%(\<end\s\+\)\@5<!\<do\%(\s\+\a\|\s*$\)" skip="^\%([!c*]\|\s*#\).*$" excludenl end="\<end\s*do\>" contains=ALLBUT,fortranUnitHeader,fortranAttribute,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
+ syn region fortranIfBlock transparent fold keepend extend start="\%(\<e\%(nd\|lse\)\s\+\)\@6<!\<if\s*(.\+)\s*then\>" skip="^\%([!c*]\|\s*#\).*$" end="\<end\s*if\>" contains=ALLBUT,fortranUnitHeader,fortranAttribute,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
+ syn region fortranCase transparent fold keepend extend start="\<select\s*\%(case\|type\|rank\)\>" skip="^\%([!c*]\|\s*#\).*$" end="\<end\s*select\>" contains=ALLBUT,fortranUnitHeader,fortranAttribute,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
else
- syn region fortran77Loop transparent fold keepend start="\<do\s\+\z(\d\+\)" end="^\s*\z1\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
- syn region fortran90Loop transparent fold keepend extend start="\(\<end\s\+\)\@<!\<do\(\s\+\a\|\s*$\)" skip="^\s*[!#].*$" excludenl end="\<end\s*do\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
- syn region fortranIfBlock transparent fold keepend extend start="\(\<e\(nd\|lse\)\s\+\)\@<!\<if\s*(\(.\|&\s*\n\)\+)\(\s\|&\s*\n\)*then\>" skip="^\s*[!#].*$" end="\<end\s*if\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
- syn region fortranCase transparent fold keepend extend start="\<select\s*\(case\|type\)\>" skip="^\s*[!#].*$" end="\<end\s*select\>" contains=ALLBUT,fortranUnitHeader,fortranStructure,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
+ syn region fortran77Loop transparent fold keepend start="\<do\s\+\z(\d\+\)" end="^\s*\z1\>" contains=ALLBUT,fortranUnitHeader,fortranAttribute,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
+ syn region fortran90Loop transparent fold keepend extend start="\%(\<end\s\+\)\@5<!\<do\%(\s\+\a\|\s*$\)" skip="^\s*[!#].*$" excludenl end="\<end\s*do\>" contains=ALLBUT,fortranUnitHeader,fortranAttribute,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
+ syn region fortranIfBlock transparent fold keepend extend start="\%(\<e\%(nd\|lse\)\s\+\)\@6<!\<if\s*(\%(.\|&\s*\n\)\+)\%(\s\|&\s*\n\)*then\>" skip="^\s*[!#].*$" end="\<end\s*if\>" contains=ALLBUT,fortranUnitHeader,fortranAttribute,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
+ syn region fortranCase transparent fold keepend extend start="\<select\s*\%(case\|type\|rank\)\>" skip="^\s*[!#].*$" end="\<end\s*select\>" contains=ALLBUT,fortranUnitHeader,fortranAttribute,fortranStorageClass,fortranType,fortranProgram,fortranModule,fortranSubroutine,fortranFunction,fortranBlockData
endif
endif
- if exists("fortran_fold_multilinecomments")
- if (b:fortran_fixed_source == 1)
- syn match fortranMultiLineComments transparent fold "\(^[!c*].*\(\n\|\%$\)\)\{4,}" contains=ALLBUT,fortranMultiCommentLines
- else
- syn match fortranMultiLineComments transparent fold "\(^\s*!.*\(\n\|\%$\)\)\{4,}" contains=ALLBUT,fortranMultiCommentLines
- endif
- endif
endif
" Define the default highlighting.
-" The default highlighting differs for each dialect.
-" Transparent groups:
-" fortranParen, fortranLeftMargin
-" fortranProgram, fortranModule, fortranSubroutine, fortranFunction,
-" fortranBlockData
-" fortran77Loop, fortran90Loop, fortranIfBlock, fortranCase
-" fortranMultiCommentLines
-hi def link fortranKeyword Keyword
+hi def link fortranBoolean Boolean
+hi def link fortranComment Comment
+hi def link fortranMultiComments Comment
+hi def link fortranBlock Conditional
+hi def link fortranConditional Conditional
+hi def link fortranConstant Constant
+hi def link fortranConditionalDel Error
+hi def link fortranKeywordDel Error
+hi def link fortranLabelError Error
+hi def link fortranParenError Error
+hi def link fortranStringDel Error
+hi def link fortranTab Error
+hi def link fortranFloat Float
+hi def link fortranFloatIll Float
+hi def link fortranCalled Function
+hi def link fortranIntrinsic Function
+hi def link fortranIntrinsicCUDA Function
+hi def link fortranIntrinsicR Function
+hi def link fortranIntrinsicVen Function
+hi def link fortranUnitName Function
hi def link fortranConstructName Identifier
-hi def link fortranConditional Conditional
-hi def link fortranRepeat Repeat
-hi def link fortranTodo Todo
-hi def link fortranContinueMark Special
-hi def link fortranString String
-hi def link fortranNumber Number
-hi def link fortranBinary Number
-hi def link fortranOctal Number
-hi def link fortranHex Number
-hi def link fortranOperator Operator
-hi def link fortranBoolean Boolean
-hi def link fortranLabelError Error
-hi def link fortranObsolete Todo
-hi def link fortranType Type
-hi def link fortranStructure Type
-hi def link fortranStorageClass StorageClass
-hi def link fortranCall Function
-hi def link fortranUnitHeader fortranPreCondit
-hi def link fortranReadWrite Keyword
-hi def link fortranIO Keyword
-hi def link fortranIntrinsic Function
-hi def link fortranConstant Constant
-
-" To stop deleted & obsolescent features being highlighted as Todo items,
-" comment out the next 5 lines and uncomment the 5 lines after that
-hi def link fortranUnitHeaderOb fortranObsolete
-hi def link fortranKeywordOb fortranObsolete
-hi def link fortranConditionalOb fortranObsolete
-hi def link fortranTypeOb fortranObsolete
-hi def link fortranKeywordDel fortranObsolete
-"hi def link fortranUnitHeaderOb fortranUnitHeader
-"hi def link fortranKeywordOb fortranKeyword
-"hi def link fortranConditionalOb fortranConditional
-"hi def link fortranTypeOb fortranType
-"hi def link fortranKeywordDel fortranKeyword
-
-if b:fortran_dialect == "F"
- hi! def link fortranIntrinsicR fortranObsolete
- hi! def link fortranUnitHeaderR fortranObsolete
- hi! def link fortranTypeR fortranObsolete
- hi! def link fortranStorageClassR fortranObsolete
- hi! def link fortranOperatorR fortranObsolete
- hi! def link fortranInclude fortranObsolete
- hi! def link fortranLabelNumber fortranObsolete
- hi! def link fortranTarget fortranObsolete
- hi! def link fortranFloatIll fortranObsolete
- hi! def link fortranIOR fortranObsolete
- hi! def link fortranKeywordR fortranObsolete
- hi! def link fortranStringR fortranObsolete
- hi! def link fortranConditionalR fortranObsolete
-else
- hi! def link fortranIntrinsicR fortranIntrinsic
- hi! def link fortranUnitHeaderR fortranPreCondit
- hi! def link fortranTypeR fortranType
- hi! def link fortranStorageClassR fortranStorageClass
- hi! def link fortranOperatorR fortranOperator
- hi! def link fortranInclude Include
- hi! def link fortranLabelNumber Special
- hi! def link fortranTarget Special
- hi! def link fortranFloatIll fortranFloat
- hi! def link fortranIOR fortranIO
- hi! def link fortranKeywordR fortranKeyword
- hi! def link fortranStringR fortranString
- hi! def link fortranConditionalR fortranConditional
-endif
-
-hi def link fortranFormatSpec Identifier
-hi def link fortranFloat Float
-hi def link fortranPreCondit PreCondit
-hi def link cIncluded fortranString
-hi def link cInclude Include
-hi def link cPreProc PreProc
-hi def link cPreCondit PreCondit
-hi def link fortranOpenMP PreProc
-hi def link fortranParenError Error
-hi def link fortranComment Comment
-hi def link fortranSerialNumber Todo
-hi def link fortranTab Error
-
-if exists("fortran_CUDA")
- hi def link fortranIntrinsicCUDA fortranIntrinsic
- hi def link fortranTypeCUDA fortranType
- hi def link fortranStringCUDA fortranString
-endif
-
-if exists("fortran_vendor_intrinsics")
- hi def link fortranExtraIntrinsic Function
-endif
+hi def link fortranFormatSpec Identifier
+hi def link cInclude Include
+hi def link fortranInclude Include
+hi def link fortranIOR Keyword
+hi def link fortranImageControl Keyword
+hi def link fortranKeyword Keyword
+hi def link fortranReadWrite Keyword
+hi def link fortranSpecifier Keyword
+hi def link fortranBinary Number
+hi def link fortranHex Number
+hi def link fortranNumber Number
+hi def link fortranBinary Number
+hi def link fortranOctal Number
+hi def link fortranOperator Operator
+hi def link fortranOperatorR Operator
+hi def link cPreCondit PreCondit
+hi def link fortranUnitHeader PreCondit
+hi def link fortranOpenMP PreProc
+hi def link cPreProc PreProc
+hi def link fortranRepeat Repeat
+hi def link fortranRepeatR Repeat
+hi def link fortranContinueMark Special
+hi def link fortranEndStatement Special
+hi def link fortranLabelNumber Special
+hi def link fortranTarget Special
+hi def link fortranStorageClass StorageClass
+hi def link cIncluded String
+hi def link fortranString String
+hi def link fortranStringCUDA String
+hi def link fortranIntrinsicOb Todo
+hi def link fortranKeywordOb Todo
+hi def link fortranLabelNumberOb Todo
+hi def link fortranRepeatOb Todo
+hi def link fortranSerialNumber Todo
+hi def link fortranStorageClassOb Todo
+hi def link fortranTargetOb Todo
+hi def link fortranTodo Todo
+hi def link fortranTypeOb Todo
+hi def link fortranUnitHeaderOb Todo
+hi def link fortranAttribute Type
+hi def link fortranType Type
+hi def link fortranTypeCUDA Type
+hi def link fortranTypeR Type
let b:current_syntax = "fortran"
diff --git a/runtime/syntax/git.vim b/runtime/syntax/git.vim
index bf013ce195..51eb8127dd 100644
--- a/runtime/syntax/git.vim
+++ b/runtime/syntax/git.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: generic git output
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
-" Last Change: 2022 Jan 05
+" Last Change: 2023 Dec 28
if exists("b:current_syntax")
finish
@@ -38,7 +38,7 @@ syn match gitReflog /^\x\{40,\} \x\{40,\} .\{-\}\d\+\s-\d\{4\}\t.*/ skipwhite c
syn region gitDiff start=/^\%(diff --git \)\@=/ end=/^\%(diff --\|$\)\@=/ contains=@gitDiff fold
syn region gitDiff start=/^\%(@@ -\)\@=/ end=/^\%(diff --\%(git\|cc\|combined\) \|$\)\@=/ contains=@gitDiff
-syn region gitDiffMerge start=/^\%(diff --\%(cc\|combined\) \)\@=/ end=/^\%(diff --\|$\)\@=/ contains=@gitDiff
+syn region gitDiffMerge start=/^\%(diff --\%(cc\|combined\) \)\@=/ end=/^\%(diff --\|$\)\@=/ contains=@gitDiff fold
syn region gitDiffMerge start=/^\%(@@@@* -\)\@=/ end=/^\%(diff --\|$\)\@=/ contains=@gitDiff
syn match gitDiffAdded "^ \++.*" contained containedin=gitDiffMerge
syn match gitDiffAdded "{+[^}]*+}" contained containedin=gitDiff
diff --git a/runtime/syntax/gitcommit.vim b/runtime/syntax/gitcommit.vim
index 42c8d4414f..bce6772762 100644
--- a/runtime/syntax/gitcommit.vim
+++ b/runtime/syntax/gitcommit.vim
@@ -2,7 +2,7 @@
" Language: git commit file
" Maintainer: Tim Pope <vimNOSPAM@tpope.org>
" Filenames: *.git/COMMIT_EDITMSG
-" Last Change: 2022 Jan 05
+" Last Change: 2023 Dec 28
if exists("b:current_syntax")
finish
@@ -21,7 +21,11 @@ endif
syn include @gitcommitDiff syntax/diff.vim
syn region gitcommitDiff start=/\%(^diff --\%(git\|cc\|combined\) \)\@=/ end=/^\%(diff --\|$\|@@\@!\|[^[:alnum:]\ +-]\S\@!\)\@=/ fold contains=@gitcommitDiff
-syn match gitcommitSummary "^.*\%<51v." contained containedin=gitcommitFirstLine nextgroup=gitcommitOverflow contains=@Spell
+if get(g:, 'gitcommit_summary_length') < 0
+ syn match gitcommitSummary "^.*$" contained containedin=gitcommitFirstLine nextgroup=gitcommitOverflow contains=@Spell
+elseif get(g:, 'gitcommit_summary_length', 1) > 0
+ exe 'syn match gitcommitSummary "^.*\%<' . (get(g:, 'gitcommit_summary_length', 50) + 1) . 'v." contained containedin=gitcommitFirstLine nextgroup=gitcommitOverflow contains=@Spell'
+endif
syn match gitcommitOverflow ".*" contained contains=@Spell
syn match gitcommitBlank "^.\+" contained contains=@Spell
syn match gitcommitFirstLine "\%^.*" nextgroup=gitcommitBlank,gitcommitComment skipnl
diff --git a/runtime/syntax/go.vim b/runtime/syntax/go.vim
index 4272e807f3..ba776f949c 100644
--- a/runtime/syntax/go.vim
+++ b/runtime/syntax/go.vim
@@ -5,7 +5,7 @@
" go.vim: Vim syntax file for Go.
" Language: Go
" Maintainer: Billie Cleek <bhcleek@gmail.com>
-" Latest Revision: 2023-08-21
+" Latest Revision: 2024-01-21
" License: BSD-style. See LICENSE file in source repository.
" Repository: https://github.com/fatih/vim-go
@@ -230,21 +230,31 @@ endif
" import
if s:FoldEnable('import')
syn region goImport start='import (' end=')' transparent fold contains=goImport,goImportString,goComment
+ syn match goImport /^import ()/ transparent fold contains=goImport
else
syn region goImport start='import (' end=')' transparent contains=goImport,goImportString,goComment
+ syn match goImport /^import ()/ transparent contains=goImport
endif
" var, const
if s:FoldEnable('varconst')
syn region goVar start='var (' end='^\s*)$' transparent fold
- \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator
+ \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator
+ syn match goVar /var ()/ transparent fold
+ \ contains=goVar
syn region goConst start='const (' end='^\s*)$' transparent fold
- \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator
+ \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator
+ syn match goConst /const ()/ transparent fold
+ \ contains=goConst
else
syn region goVar start='var (' end='^\s*)$' transparent
- \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator
+ \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator
+ syn match goVar /var ()/ transparent
+ \ contains=goVar
syn region goConst start='const (' end='^\s*)$' transparent
- \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator
+ \ contains=ALLBUT,goParen,goBlock,goFunction,goTypeName,goReceiverType,goReceiverVar,goParamName,goParamType,goSimpleParams,goPointerOperator
+ syn match goConst /const ()/ transparent
+ \ contains=goConst
endif
" Single-line var, const, and import.
diff --git a/runtime/syntax/gpg.vim b/runtime/syntax/gpg.vim
index c7f3584ff0..f132a52705 100644
--- a/runtime/syntax/gpg.vim
+++ b/runtime/syntax/gpg.vim
@@ -1,9 +1,13 @@
" Vim syntax file
" Language: gpg(1) configuration file
+" Maintainer: This runtime file is looking for a maintainer.
" Previous Maintainer: Nikolai Weibull <now@bitwi.se>
-" Latest Revision: 2010-10-14
-" Updated: 2023-01-23 @ObserverOfTime: added a couple of keywords
+" Latest Revision: 2024-02-11
+" Updated:
+" 2023-01-23 @ObserverOfTime: added a couple of keywords
" 2023-03-21 Todd Zullinger <tmz@pobox.com>: sync with gnupg-2.4.0
+" 2024-02-10 Daniel Kahn Gillmor <dkg@fifthhorseman.net>:
+" mark use-embedded-filename as warning for security reasons
if exists("b:current_syntax")
finish
@@ -21,7 +25,7 @@ syn region gpgComment contained display oneline start='#' end='$'
syn match gpgID contained display '\<\(0x\)\=\x\{8,}\>'
-syn match gpgBegin display '^' skipwhite nextgroup=gpgComment,gpgOption,gpgCommand
+syn match gpgBegin display '^' skipwhite nextgroup=gpgComment,gpgOption,gpgOptionDeprecated,gpgCommand
syn keyword gpgCommand contained skipwhite nextgroup=gpgArg
\ change-passphrase check-sig check-signatures
@@ -41,6 +45,7 @@ syn keyword gpgCommand contained skipwhite nextgroup=gpgArg
\ quick-set-expire quick-set-primary-uid quick-sign-key
\ quick-update-pref receive-keys recv-keys refresh-keys
\ search-keys show-key show-keys sign-key tofu-policy
+
syn keyword gpgCommand contained skipwhite nextgroup=gpgArgError
\ card-edit card-status change-pin check-trustdb
\ clear-sign clearsign dearmor dearmour decrypt
@@ -97,6 +102,7 @@ syn keyword gpgOption contained skipwhite nextgroup=gpgArg
\ trusted-key trust-model try-secret-key ttyname
\ ttytype ungroup user verify-options weak-digest
\ xauthority
+
syn keyword gpgOption contained skipwhite nextgroup=gpgArgError
\ allow-freeform-uid allow-multiple-messages
\ allow-multisig-verification allow-non-selfsigned-uid
@@ -145,7 +151,7 @@ syn keyword gpgOption contained skipwhite nextgroup=gpgArgError
\ no-sk-comments no-skip-hidden-recipients
\ no-symkey-cache not-dash-escaped no-textmode
\ no-throw-keyids no-tty no-use-agent
- \ no-use-embedded-filename no-utf8-strings no-verbose
+ \ no-utf8-strings no-verbose
\ no-version only-sign-text-ids openpgp
\ override-compliance-check pgp6 pgp7 pgp8
\ preserve-permissions print-dane-records quiet
@@ -155,7 +161,7 @@ syn keyword gpgOption contained skipwhite nextgroup=gpgArgError
\ show-notation show-photos show-policy-url
\ show-session-key sk-comments skip-hidden-recipients
\ skip-verify textmode throw-keyids try-all-secrets
- \ unwrap use-agent use-embedded-filename use-keyboxd
+ \ unwrap use-agent use-keyboxd
\ use-only-openpgp-card utf8-strings verbose version
\ warranty with-colons with-fingerprint
\ with-icao-spelling with-key-data with-keygrip
@@ -164,6 +170,10 @@ syn keyword gpgOption contained skipwhite nextgroup=gpgArgError
\ with-subkey-fingerprints with-tofu-info with-wkd-hash
\ yes
+" depcrated for security reasons
+syn keyword gpgOptionDeprecated contained skipwhite nextgroup=gpgArgError
+ \ use-embedded-filename no-use-embedded-filename
+
syn match gpgArg contained display '\S\+\(\s\+\S\+\)*' contains=gpgID
syn match gpgArgError contained display '\S\+\(\s\+\S\+\)*'
@@ -171,6 +181,7 @@ hi def link gpgComment Comment
hi def link gpgTodo Todo
hi def link gpgID Number
hi def link gpgOption Keyword
+hi def link gpgOptionDeprecated WarningMsg
hi def link gpgCommand Error
hi def link gpgArgError Error
diff --git a/runtime/syntax/help.vim b/runtime/syntax/help.vim
index f1e650b2fb..fced5e7dd1 100644
--- a/runtime/syntax/help.vim
+++ b/runtime/syntax/help.vim
@@ -136,6 +136,10 @@ syn match helpTodo "\t[* ]Todo\t\+[a-z].*"
syn match helpURL `\v<(((https?|ftp|gopher)://|(mailto|file|news):)[^' <>"]+|(www|web|w3)[a-z0-9_-]*\.[a-z0-9._-]+\.[^' <>"]+)[a-zA-Z0-9/]`
+syn match helpDiffAdded "\t[* ]Added\t\+[a-z].*"
+syn match helpDiffChanged "\t[* ]Changed\t\+[a-z].*"
+syn match helpDiffRemoved "\t[* ]Removed\t\+[a-z].*"
+
" Additionally load a language-specific syntax file "help_ab.vim".
let s:i = match(expand("%"), '\.\a\ax$')
if s:i > 0
@@ -209,6 +213,9 @@ hi def link helpUnderlined Underlined
hi def link helpError Error
hi def link helpTodo Todo
hi def link helpURL String
+hi def link helpDiffAdded Added
+hi def link helpDiffChanged Changed
+hi def link helpDiffRemoved Removed
let b:current_syntax = "help"
diff --git a/runtime/syntax/html.vim b/runtime/syntax/html.vim
index 82c829a2e1..c975ae8620 100644
--- a/runtime/syntax/html.vim
+++ b/runtime/syntax/html.vim
@@ -3,9 +3,9 @@
" Maintainer: Doug Kearns <dougkearns@gmail.com>
" Previous Maintainers: Jorge Maldonado Ventura <jorgesumle@freakspot.net>
" Claudio Fleiner <claudio@fleiner.com>
-" Last Change: 2023 Feb 20
+" Last Change: 2023 Nov 28
-" Please check :help html.vim for some comments and a description of the options
+" See :help html.vim for some comments and a description of the options
" quit when a syntax file was already loaded
if !exists("main_syntax")
@@ -28,7 +28,6 @@ syn case ignore
" mark illegal characters
syn match htmlError "[<>&]"
-
" tags
syn region htmlString contained start=+"+ end=+"+ contains=htmlSpecialChar,javaScriptExpression,@htmlPreproc
syn region htmlString contained start=+'+ end=+'+ contains=htmlSpecialChar,javaScriptExpression,@htmlPreproc
@@ -39,7 +38,6 @@ syn match htmlTagN contained +<\s*[-a-zA-Z0-9]\++hs=s+1 contains=htmlTagName,
syn match htmlTagN contained +</\s*[-a-zA-Z0-9]\++hs=s+2 contains=htmlTagName,htmlSpecialTagName,@htmlTagNameCluster
syn match htmlTagError contained "[^>]<"ms=s+1
-
" tag names
syn keyword htmlTagName contained address applet area a base basefont
syn keyword htmlTagName contained big blockquote br caption center
@@ -61,7 +59,7 @@ syn keyword htmlTagName contained article aside audio bdi canvas data
syn keyword htmlTagName contained datalist details dialog embed figcaption
syn keyword htmlTagName contained figure footer header hgroup keygen main
syn keyword htmlTagName contained mark menuitem meter nav output picture
-syn keyword htmlTagName contained progress rb rp rt rtc ruby section
+syn keyword htmlTagName contained progress rb rp rt rtc ruby search section
syn keyword htmlTagName contained slot source summary template time track
syn keyword htmlTagName contained video wbr
@@ -88,19 +86,72 @@ syn keyword htmlArg contained size src start target text type url
syn keyword htmlArg contained usemap ismap valign value vlink vspace width wrap
syn match htmlArg contained "\<\%(http-equiv\|href\|title\)="me=e-1
-" aria attributes
-exe 'syn match htmlArg contained "\<aria-\%(' . join([
- \ 'activedescendant', 'atomic', 'autocomplete', 'busy', 'checked', 'colcount',
- \ 'colindex', 'colspan', 'controls', 'current', 'describedby', 'details',
- \ 'disabled', 'dropeffect', 'errormessage', 'expanded', 'flowto', 'grabbed',
- \ 'haspopup', 'hidden', 'invalid', 'keyshortcuts', 'label', 'labelledby', 'level',
- \ 'live', 'modal', 'multiline', 'multiselectable', 'orientation', 'owns',
- \ 'placeholder', 'posinset', 'pressed', 'readonly', 'relevant', 'required',
- \ 'roledescription', 'rowcount', 'rowindex', 'rowspan', 'selected', 'setsize',
- \ 'sort', 'valuemax', 'valuemin', 'valuenow', 'valuetext'
- \ ], '\|') . '\)\>"'
syn keyword htmlArg contained role
+" ARIA attributes {{{1
+let s:aria =<< trim END
+ activedescendant
+ atomic
+ autocomplete
+ braillelabel
+ brailleroledescription
+ busy
+ checked
+ colcount
+ colindex
+ colindextext
+ colspan
+ controls
+ current
+ describedby
+ description
+ details
+ disabled
+ errormessage
+ expanded
+ flowto
+ haspopup
+ hidden
+ invalid
+ keyshortcuts
+ label
+ labelledby
+ level
+ live
+ modal
+ multiline
+ multiselectable
+ orientation
+ owns
+ placeholder
+ posinset
+ pressed
+ readonly
+ relevant
+ required
+ roledescription
+ rowcount
+ rowindex
+ rowindextext
+ rowspan
+ selected
+ setsize
+ sort
+ valuemax
+ valuemin
+ valuenow
+ valuetext
+END
+let s:aria_deprecated =<< trim END
+ dropeffect
+ grabbed
+END
+
+call extend(s:aria, s:aria_deprecated)
+exe 'syn match htmlArg contained "\%#=1\<aria-\%(' .. s:aria->join('\|') .. '\)\>"'
+unlet s:aria s:aria_deprecated
+" }}}
+
" Netscape extensions
syn keyword htmlTagName contained frame noframes frameset nobr blink
syn keyword htmlTagName contained layer ilayer nolayer spacer
@@ -321,9 +372,9 @@ if !exists("html_no_rendering")
hi def htmlUnderlineItalic term=italic,underline cterm=italic,underline gui=italic,underline
hi def htmlItalic term=italic cterm=italic gui=italic
if v:version > 800 || v:version == 800 && has("patch1038")
- hi def htmlStrike term=strikethrough cterm=strikethrough gui=strikethrough
+ hi def htmlStrike term=strikethrough cterm=strikethrough gui=strikethrough
else
- hi def htmlStrike term=underline cterm=underline gui=underline
+ hi def htmlStrike term=underline cterm=underline gui=underline
endif
endif
endif
@@ -356,4 +407,5 @@ endif
let &cpo = s:cpo_save
unlet s:cpo_save
-" vim: ts=8
+
+" vim: nowrap sw=2 sts=2 ts=8 noet fdm=marker:
diff --git a/runtime/syntax/i3config.vim b/runtime/syntax/i3config.vim
index d4512525f9..8131639a11 100644
--- a/runtime/syntax/i3config.vim
+++ b/runtime/syntax/i3config.vim
@@ -2,8 +2,8 @@
" Language: i3 config file
" Original Author: Josef Litos (JosefLitos/i3config.vim)
" Maintainer: Quentin Hibon (github user hiqua)
-" Version: 1.0.0
-" Last Change: 2023-11-11
+" Version: 1.0.2
+" Last Change: 2023-12-28
" References:
" http://i3wm.org/docs/userguide.html#configuring
@@ -137,8 +137,7 @@ syn match i3ConfigIpcKeyword /ipc-socket/ contained
syn match i3ConfigParamLine /^ipc-socket .*$/ contains=i3ConfigIpcKeyword
" 4.24 Focus follows mouse
-syn keyword i3ConfigFocusFollowsMouseOpts always contained
-syn match i3ConfigKeyword /^focus_follows_mouse \(yes\|no\|always\)$/ contains=i3ConfigBoolean,i3ConfigFocusFollowsMouseOpts
+syn match i3ConfigKeyword /^focus_follows_mouse \(yes\|no\)$/ contains=i3ConfigBoolean
" 4.25 Mouse warping
syn keyword i3ConfigMouseWarpingOpts output container none contained
@@ -298,7 +297,6 @@ hi def link i3ConfigWorkspaceDir i3ConfigOption
hi def link i3ConfigDotOperator i3ConfigOperator
hi def link i3ConfigClientOpts i3ConfigOption
hi def link i3ConfigIpcKeyword i3ConfigKeyword
-hi def link i3ConfigFocusFollowsMouseOpts i3ConfigOption
hi def link i3ConfigMouseWarpingOpts i3ConfigOption
hi def link i3ConfigPopupFullscreenOpts i3ConfigOption
hi def link i3ConfigFocusWrappingOpts i3ConfigOption
diff --git a/runtime/syntax/java.vim b/runtime/syntax/java.vim
index 00d6071944..f6d2660277 100644
--- a/runtime/syntax/java.vim
+++ b/runtime/syntax/java.vim
@@ -2,7 +2,7 @@
" Language: Java
" Maintainer: Claudio Fleiner <claudio@fleiner.com>
" URL: https://github.com/fleiner/vim/blob/master/runtime/syntax/java.vim
-" Last Change: 2022 Jun 08
+" Last Change: 2024 Mar 02
" Please check :help java.vim for comments on some of the options available.
@@ -37,6 +37,14 @@ syn keyword javaBoolean true false
syn keyword javaConstant null
syn keyword javaTypedef this super
syn keyword javaOperator var new instanceof
+" Since the yield statement, which could take a parenthesised operand,
+" and _qualified_ yield methods get along within the switch block
+" (JLS-17, §3.8), it seems futile to make a region definition for this
+" block; instead look for the _yield_ word alone, and if found,
+" backtrack (arbitrarily) 80 bytes, at most, on the matched line and,
+" if necessary, on the line before that (h: \@<=), trying to match
+" neither a method reference nor a qualified method invocation.
+syn match javaOperator "\%(\%(::\|\.\)[[:space:]\n]*\)\@80<!\<yield\>"
syn keyword javaType boolean char byte short int long float double
syn keyword javaType void
syn keyword javaStatement return
@@ -56,6 +64,7 @@ syn keyword javaBranch break continue nextgroup=javaUserLabelRef skipwhite
syn match javaUserLabelRef "\k\+" contained
syn match javaVarArg "\.\.\."
syn keyword javaScopeDecl public protected private abstract
+syn match javaConceptKind "\<default\>\%(\s*\%(:\|->\)\)\@!"
function s:isModuleInfoDeclarationCurrentBuffer() abort
return fnamemodify(bufname("%"), ":t") =~ '^module-info\%(\.class\>\)\@!'
@@ -142,28 +151,46 @@ if exists("java_space_errors")
endif
endif
-syn region javaLabelRegion transparent matchgroup=javaLabel start="\<case\>" end="->" matchgroup=NONE end=":" contains=javaNumber,javaCharacter,javaString
-syn match javaUserLabel "^\s*[_$a-zA-Z][_$a-zA-Z0-9_]*\s*:"he=e-1 contains=javaLabel
-syn keyword javaLabel default
+syn match javaUserLabel "^\s*\<\K\k*\>\%(\<default\>\)\@<!\s*:"he=e-1
+syn region javaLabelRegion transparent matchgroup=javaLabel start="\<case\>" matchgroup=NONE end=":\|->" contains=javaLabelCastType,javaLabelNumber,javaCharacter,javaString,javaConstant,@javaClasses,javaLabelDefault,javaLabelVarType,javaLabelWhenClause
+syn region javaLabelRegion transparent matchgroup=javaLabel start="\<default\>\%(\s*\%(:\|->\)\)\@=" matchgroup=NONE end=":\|->" oneline
+" Consider grouped _default_ _case_ labels, i.e.
+" case null, default ->
+" case null: default:
+syn keyword javaLabelDefault contained default
+syn keyword javaLabelVarType contained var
+syn keyword javaLabelCastType contained char byte short int
+" Allow for the contingency of the enclosing region not being able to
+" _keep_ its _end_, e.g. case ':':.
+syn region javaLabelWhenClause contained transparent matchgroup=javaLabel start="\<when\>" matchgroup=NONE end=":"me=e-1 end="->"me=e-2 contains=TOP,javaExternal
+syn match javaLabelNumber contained "\<0\>[lL]\@!"
+syn match javaLabelNumber contained "\<\%(0\%([xX]\x\%(_*\x\)*\|_*\o\%(_*\o\)*\|[bB][01]\%(_*[01]\)*\)\|[1-9]\%(_*\d\)*\)\>[lL]\@!"
+hi def link javaLabelDefault javaLabel
+hi def link javaLabelVarType javaOperator
+hi def link javaLabelNumber javaNumber
+hi def link javaLabelCastType javaType
" highlighting C++ keywords as errors removed, too many people find it
" annoying. Was: if !exists("java_allow_cpp_keywords")
" The following cluster contains all java groups except the contained ones
-syn cluster javaTop add=javaExternal,javaError,javaBranch,javaLabelRegion,javaLabel,javaConditional,javaRepeat,javaBoolean,javaConstant,javaTypedef,javaOperator,javaType,javaStatement,javaStorageClass,javaAssert,javaExceptions,javaMethodDecl,javaClassDecl,javaScopeDecl,javaError2,javaUserLabel,javaLangObject,javaAnnotation,javaVarArg
+syn cluster javaTop add=javaExternal,javaError,javaBranch,javaLabelRegion,javaConditional,javaRepeat,javaBoolean,javaConstant,javaTypedef,javaOperator,javaType,javaStatement,javaStorageClass,javaAssert,javaExceptions,javaMethodDecl,javaClassDecl,javaScopeDecl,javaConceptKind,javaError2,javaUserLabel,javaLangObject,javaAnnotation,javaVarArg
" Comments
syn keyword javaTodo contained TODO FIXME XXX
+
if exists("java_comment_strings")
syn region javaCommentString contained start=+"+ end=+"+ end=+$+ end=+\*/+me=s-1,he=s-1 contains=javaSpecial,javaCommentStar,javaSpecialChar,@Spell
- syn region javaComment2String contained start=+"+ end=+$\|"+ contains=javaSpecial,javaSpecialChar,@Spell
+ syn region javaCommentString contained start=+"""[ \t\x0c\r]*$+hs=e+1 end=+"""+he=s-1 contains=javaSpecial,javaCommentStar,javaSpecialChar,@Spell,javaSpecialError,javaTextBlockError
+ syn region javaComment2String contained start=+"+ end=+$\|"+ contains=javaSpecial,javaSpecialChar,@Spell
syn match javaCommentCharacter contained "'\\[^']\{1,6\}'" contains=javaSpecialChar
syn match javaCommentCharacter contained "'\\''" contains=javaSpecialChar
syn match javaCommentCharacter contained "'[^\\]'"
syn cluster javaCommentSpecial add=javaCommentString,javaCommentCharacter,javaNumber
syn cluster javaCommentSpecial2 add=javaComment2String,javaCommentCharacter,javaNumber
endif
+
syn region javaComment start="/\*" end="\*/" contains=@javaCommentSpecial,javaTodo,@Spell
syn match javaCommentStar contained "^\s*\*[^/]"me=e-1
syn match javaCommentStar contained "^\s*\*$"
@@ -202,22 +229,32 @@ syn match javaComment "/\*\*/"
" Strings and constants
syn match javaSpecialError contained "\\."
syn match javaSpecialCharError contained "[^']"
-syn match javaSpecialChar contained "\\\([4-9]\d\|[0-3]\d\d\|[\"\\'ntbrf]\|u\x\{4\}\)"
+" Escape Sequences (JLS-17, §3.10.7):
+syn match javaSpecialChar contained "\\\%(u\x\x\x\x\|[0-3]\o\o\|\o\o\=\|[bstnfr"'\\]\)"
syn region javaString start=+"+ end=+"+ end=+$+ contains=javaSpecialChar,javaSpecialError,@Spell
-" next line disabled, it can cause a crash for a long line
-"syn match javaStringError +"\([^"\\]\|\\.\)*$+
+syn region javaString start=+"""[ \t\x0c\r]*$+hs=e+1 end=+"""+he=s-1 contains=javaSpecialChar,javaSpecialError,javaTextBlockError,@Spell
+syn match javaTextBlockError +"""\s*"""+
+" The next line is commented out, it can cause a crash for a long line
+"syn match javaStringError +"\%([^"\\]\|\\.\)*$+
syn match javaCharacter "'[^']*'" contains=javaSpecialChar,javaSpecialCharError
syn match javaCharacter "'\\''" contains=javaSpecialChar
syn match javaCharacter "'[^\\]'"
-syn match javaNumber "\<\(0[bB][0-1]\+\|0[0-7]*\|0[xX]\x\+\|\d\(\d\|_\d\)*\)[lL]\=\>"
-syn match javaNumber "\(\<\d\(\d\|_\d\)*\.\(\d\(\d\|_\d\)*\)\=\|\.\d\(\d\|_\d\)*\)\([eE][-+]\=\d\(\d\|_\d\)*\)\=[fFdD]\="
-syn match javaNumber "\<\d\(\d\|_\d\)*[eE][-+]\=\d\(\d\|_\d\)*[fFdD]\=\>"
-syn match javaNumber "\<\d\(\d\|_\d\)*\([eE][-+]\=\d\(\d\|_\d\)*\)\=[fFdD]\>"
-
-" unicode characters
-syn match javaSpecial "\\u\d\{4\}"
-
-syn cluster javaTop add=javaString,javaCharacter,javaNumber,javaSpecial,javaStringError
+" Integer literals (JLS-17, §3.10.1):
+syn keyword javaNumber 0 0l 0L
+syn match javaNumber "\<\%(0\%([xX]\x\%(_*\x\)*\|_*\o\%(_*\o\)*\|[bB][01]\%(_*[01]\)*\)\|[1-9]\%(_*\d\)*\)[lL]\=\>"
+" Decimal floating-point literals (JLS-17, §3.10.2):
+" Against "\<\d\+\>\.":
+syn match javaNumber "\<\d\%(_*\d\)*\."
+syn match javaNumber "\%(\<\d\%(_*\d\)*\.\%(\d\%(_*\d\)*\)\=\|\.\d\%(_*\d\)*\)\%([eE][-+]\=\d\%(_*\d\)*\)\=[fFdD]\=\>"
+syn match javaNumber "\<\d\%(_*\d\)*[eE][-+]\=\d\%(_*\d\)*[fFdD]\=\>"
+syn match javaNumber "\<\d\%(_*\d\)*\%([eE][-+]\=\d\%(_*\d\)*\)\=[fFdD]\>"
+" Hexadecimal floating-point literals (JLS-17, §3.10.2):
+syn match javaNumber "\<0[xX]\%(\x\%(_*\x\)*\.\=\|\%(\x\%(_*\x\)*\)\=\.\x\%(_*\x\)*\)[pP][-+]\=\d\%(_*\d\)*[fFdD]\=\>"
+
+" Unicode characters
+syn match javaSpecial "\\u\x\x\x\x"
+
+syn cluster javaTop add=javaString,javaCharacter,javaNumber,javaSpecial,javaStringError,javaTextBlockError
if exists("java_highlight_functions")
if java_highlight_functions == "indent"
@@ -231,26 +268,31 @@ if exists("java_highlight_functions")
" 1. class names are always capitalized (ie: Button)
" 2. method names are never capitalized (except constructors, of course)
"syn region javaFuncDef start=+^\s\+\(\(public\|protected\|private\|static\|abstract\|final\|native\|synchronized\)\s\+\)*\(\(void\|boolean\|char\|byte\|short\|int\|long\|float\|double\|\([A-Za-z_][A-Za-z0-9_$]*\.\)*[A-Z][A-Za-z0-9_$]*\)\(<[^>]*>\)\=\(\[\]\)*\s\+[a-z][A-Za-z0-9_$]*\|[A-Z][A-Za-z0-9_$]*\)\s*([^0-9]+ end=+)+ contains=javaScopeDecl,javaType,javaStorageClass,javaComment,javaLineComment,@javaClasses
- syn region javaFuncDef start=+^\s\+\(\(public\|protected\|private\|static\|abstract\|final\|native\|synchronized\)\s\+\)*\(<.*>\s\+\)\?\(\(void\|boolean\|char\|byte\|short\|int\|long\|float\|double\|\([A-Za-z_][A-Za-z0-9_$]*\.\)*[A-Z][A-Za-z0-9_$]*\)\(<[^(){}]*>\)\=\(\[\]\)*\s\+[a-z][A-Za-z0-9_$]*\|[A-Z][A-Za-z0-9_$]*\)\s*(+ end=+)+ contains=javaScopeDecl,javaType,javaStorageClass,javaComment,javaLineComment,@javaClasses,javaAnnotation
+ syn region javaFuncDef start=+^\s\+\%(\%(public\|protected\|private\|static\|\%(abstract\|default\)\|final\|native\|synchronized\)\s\+\)*\%(<.*>\s\+\)\?\%(\%(void\|boolean\|char\|byte\|short\|int\|long\|float\|double\|\%([A-Za-z_][A-Za-z0-9_$]*\.\)*[A-Z][A-Za-z0-9_$]*\)\%(<[^(){}]*>\)\=\%(\[\]\)*\s\+[a-z][A-Za-z0-9_$]*\|[A-Z][A-Za-z0-9_$]*\)\s*(+ end=+)+ contains=javaScopeDecl,javaType,javaStorageClass,javaComment,javaLineComment,@javaClasses,javaAnnotation
endif
- syn match javaLambdaDef "[a-zA-Z_][a-zA-Z0-9_]*\s*->"
+ syn match javaLambdaDef "\<\K\k*\>\%(\<default\>\)\@<!\s*->"
syn match javaBraces "[{}]"
syn cluster javaTop add=javaFuncDef,javaBraces,javaLambdaDef
endif
if exists("java_highlight_debug")
-
" Strings and constants
- syn match javaDebugSpecial contained "\\\d\d\d\|\\."
+ syn match javaDebugSpecial contained "\\\%(u\x\x\x\x\|[0-3]\o\o\|\o\o\=\|[bstnfr"'\\]\)"
syn region javaDebugString contained start=+"+ end=+"+ contains=javaDebugSpecial
- syn match javaDebugStringError +"\([^"\\]\|\\.\)*$+
+ syn region javaDebugString contained start=+"""[ \t\x0c\r]*$+hs=e+1 end=+"""+he=s-1 contains=javaDebugSpecial,javaDebugTextBlockError
+" The next line is commented out, it can cause a crash for a long line
+" syn match javaDebugStringError contained +"\%([^"\\]\|\\.\)*$+
+ syn match javaDebugTextBlockError contained +"""\s*"""+
syn match javaDebugCharacter contained "'[^\\]'"
syn match javaDebugSpecialCharacter contained "'\\.'"
syn match javaDebugSpecialCharacter contained "'\\''"
- syn match javaDebugNumber contained "\<\(0[0-7]*\|0[xX]\x\+\|\d\+\)[lL]\=\>"
- syn match javaDebugNumber contained "\(\<\d\+\.\d*\|\.\d\+\)\([eE][-+]\=\d\+\)\=[fFdD]\="
- syn match javaDebugNumber contained "\<\d\+[eE][-+]\=\d\+[fFdD]\=\>"
- syn match javaDebugNumber contained "\<\d\+\([eE][-+]\=\d\+\)\=[fFdD]\>"
+ syn keyword javaDebugNumber contained 0 0l 0L
+ syn match javaDebugNumber contained "\<\d\%(_*\d\)*\."
+ syn match javaDebugNumber contained "\<\%(0\%([xX]\x\%(_*\x\)*\|_*\o\%(_*\o\)*\|[bB][01]\%(_*[01]\)*\)\|[1-9]\%(_*\d\)*\)[lL]\=\>"
+ syn match javaDebugNumber contained "\%(\<\d\%(_*\d\)*\.\%(\d\%(_*\d\)*\)\=\|\.\d\%(_*\d\)*\)\%([eE][-+]\=\d\%(_*\d\)*\)\=[fFdD]\=\>"
+ syn match javaDebugNumber contained "\<\d\%(_*\d\)*[eE][-+]\=\d\%(_*\d\)*[fFdD]\=\>"
+ syn match javaDebugNumber contained "\<\d\%(_*\d\)*\%([eE][-+]\=\d\%(_*\d\)*\)\=[fFdD]\>"
+ syn match javaDebugNumber contained "\<0[xX]\%(\x\%(_*\x\)*\.\=\|\%(\x\%(_*\x\)*\)\=\.\x\%(_*\x\)*\)[pP][-+]\=\d\%(_*\d\)*[fFdD]\=\>"
syn keyword javaDebugBoolean contained true false
syn keyword javaDebugType contained null this super
syn region javaDebugParen start=+(+ end=+)+ contained contains=javaDebug.*,javaDebugParen
@@ -266,6 +308,7 @@ if exists("java_highlight_debug")
hi def link javaDebug Debug
hi def link javaDebugString DebugString
hi def link javaDebugStringError javaError
+ hi def link javaDebugTextBlockError javaDebugStringError
hi def link javaDebugType DebugType
hi def link javaDebugBoolean DebugBoolean
hi def link javaDebugNumber Debug
@@ -326,6 +369,7 @@ hi def link javaStorageClass StorageClass
hi def link javaMethodDecl javaStorageClass
hi def link javaClassDecl javaStorageClass
hi def link javaScopeDecl javaStorageClass
+hi def link javaConceptKind NonText
hi def link javaBoolean Boolean
hi def link javaSpecial Special
@@ -337,6 +381,7 @@ hi def link javaSpecialChar SpecialChar
hi def link javaNumber Number
hi def link javaError Error
hi def link javaStringError Error
+hi def link javaTextBlockError javaStringError
hi def link javaStatement Statement
hi def link javaOperator Operator
hi def link javaComment Comment
diff --git a/runtime/syntax/json5.vim b/runtime/syntax/json5.vim
index 5b01d33aad..dc0d11b2a1 100644
--- a/runtime/syntax/json5.vim
+++ b/runtime/syntax/json5.vim
@@ -49,9 +49,11 @@ syn match json5Key /@\?\%(\I\|\$\)\%(\i\|\$\)*\s*\ze::\@!/ contains=@Spell
syn match json5Key /"\([^"]\|\\"\)\{-}"\ze\s*:/ contains=json5Escape,@Spell
" Comment
-syn region json5LineComment start=+\/\/+ end=+$+ keepend contains=@Spell
-syn region json5LineComment start=+^\s*\/\/+ skip=+\n\s*\/\/+ end=+$+ keepend fold contains=@Spell
-syn region json5Comment start="/\*" end="\*/" fold contains=@Spell
+syn region json5LineComment start=+\/\/+ end=+$+ keepend contains=@Spell,json5Todo
+syn region json5LineComment start=+^\s*\/\/+ skip=+\n\s*\/\/+ end=+$+ keepend fold contains=@Spell,json5Todo
+syn region json5Comment start="/\*" end="\*/" fold contains=@Spell,json5Todo
+
+syn keyword json5Todo contained TODO FIXME XXX
" Define the default highlighting
hi def link json5String String
@@ -66,6 +68,7 @@ hi def link json5Boolean Boolean
hi def link json5LineComment Comment
hi def link json5Comment Comment
hi def link json5NumError Error
+hi def link json5Todo Todo
if !exists('b:current_syntax')
let b:current_syntax = 'json5'
diff --git a/runtime/syntax/lex.vim b/runtime/syntax/lex.vim
index 82197adbed..b05148e88f 100644
--- a/runtime/syntax/lex.vim
+++ b/runtime/syntax/lex.vim
@@ -1,9 +1,11 @@
" Vim syntax file
" Language: Lex and Flex
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Contributor: Robert A. van Engelen <engelen@acm.org>
-" Last Change: Apr 24, 2020
" Version: 18
+" Last Change: Apr 24, 2020
+" 2024 Feb 19 by Vim Project (announce adoption)
" quit when a syntax file was already loaded
if exists("b:current_syntax")
diff --git a/runtime/syntax/lisp.vim b/runtime/syntax/lisp.vim
index 90513e3a00..5350b4dc51 100644
--- a/runtime/syntax/lisp.vim
+++ b/runtime/syntax/lisp.vim
@@ -1,9 +1,11 @@
" Vim syntax file
" Language: Lisp
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Nov 10, 2021
+" 2024 Feb 19 by Vim Project (announce adoption)
" Version: 31
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_LISP
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_LISP
"
" Thanks to F Xavier Noria for a list of 978 Common Lisp symbols taken from HyperSpec
" Clisp additions courtesy of http://clisp.cvs.sourceforge.net/*checkout*/clisp/clisp/emacs/lisp.vim
diff --git a/runtime/syntax/logtalk.vim b/runtime/syntax/logtalk.vim
index bc70ef41b4..2c6c82aaa0 100644
--- a/runtime/syntax/logtalk.vim
+++ b/runtime/syntax/logtalk.vim
@@ -1,8 +1,9 @@
" Vim syntax file
"
" Language: Logtalk
-" Maintainer: Paulo Moura <pmoura@logtalk.org>
-" Last Change: August 3, 2018
+" Maintainer: Paulo Moura <pmoura@logtalk.org>
+" Last Change: December 16, 2023
+
" quit when a syntax file was already loaded
@@ -30,7 +31,7 @@ syn match logtalkOperator ":-"
" Logtalk quoted atoms and strings
-syn region logtalkString start=+"+ skip=+\\"+ end=+"+
+syn region logtalkString start=+"+ skip=+\\"+ end=+"+ contains=logtalkEscapeSequence
syn region logtalkAtom start=+'+ skip=+\\'+ end=+'+ contains=logtalkEscapeSequence
syn match logtalkEscapeSequence contained "\\\([\\abfnrtv\"\']\|\(x[a-fA-F0-9]\+\|[0-7]\+\)\\\)"
@@ -39,7 +40,7 @@ syn match logtalkEscapeSequence contained "\\\([\\abfnrtv\"\']\|\(x[a-fA-F0-9]\+
" Logtalk message sending operators
syn match logtalkOperator "::"
-syn match logtalkOperator ":"
+syn match logtalkOperator "\(0'\)\@<!:"
syn match logtalkOperator "\^\^"
@@ -138,7 +139,7 @@ syn match logtalkBuiltIn "\<logtalk_make\>"
syn match logtalkBuiltIn "\<\(for\|retract\)all\ze("
-syn match logtalkBuiltIn "\<threaded\(_\(call\|once\|ignore\|exit\|peek\|wait\|notify\)\)\?\ze("
+syn match logtalkBuiltIn "\<threaded\(_\(ca\(ll\|ncel\)\|once\|ignore\|exit\|peek\|wait\|notify\)\)\?\ze("
syn match logtalkBuiltIn "\<threaded_engine\(_\(create\|destroy\|self\|next\|next_reified\|yield\|post\|fetch\)\)\?\ze("
@@ -171,8 +172,8 @@ syn match logtalkBuiltInMethod "\<phrase\ze("
" Mode operators
-syn match logtalkOperator "?"
-syn match logtalkOperator "@"
+syn match logtalkOperator "\(0'\)\@<!?"
+syn match logtalkOperator "\(0'\)\@<!@"
" Control constructs
@@ -181,19 +182,19 @@ syn match logtalkKeyword "\<true\>"
syn match logtalkKeyword "\<fail\>"
syn match logtalkKeyword "\<false\>"
syn match logtalkKeyword "\<ca\(ll\|tch\)\ze("
-syn match logtalkOperator "!"
-" syn match logtalkOperator ","
-syn match logtalkOperator ";"
+syn match logtalkOperator "\(0'\)\@<!!"
+" syn match logtalkOperator "\(0'\)\@<!,"
+syn match logtalkOperator "\(0'\)\@<!;"
syn match logtalkOperator "-->"
syn match logtalkOperator "->"
syn match logtalkKeyword "\<throw\ze("
syn match logtalkKeyword "\<\(instantiation\|system\)_error\>"
-syn match logtalkKeyword "\<\(type\|domain\|existence\|permission\|representation\|evaluation\|resource\|syntax\)_error\ze("
+syn match logtalkKeyword "\<\(uninstantiation\|type\|domain\|existence\|permission\|representation\|evaluation\|resource\|syntax\)_error\ze("
" Term unification
-syn match logtalkOperator "="
+syn match logtalkOperator "\(0'\)\@<!="
syn match logtalkKeyword "\<subsumes_term\ze("
syn match logtalkKeyword "\<unify_with_occurs_check\ze("
syn match logtalkOperator "\\="
@@ -246,9 +247,9 @@ syn match logtalkOperator "\<is\>"
syn match logtalkOperator "=:="
syn match logtalkOperator "=\\="
-syn match logtalkOperator "<"
+syn match logtalkOperator "\(0'\)\@<!<"
syn match logtalkOperator "=<"
-syn match logtalkOperator ">"
+syn match logtalkOperator "\(0'\)\@<!>"
syn match logtalkOperator ">="
@@ -310,11 +311,11 @@ syn match logtalkKeyword "\<\(key\)\?sort\ze("
" Evaluable functors
-syn match logtalkOperator "+"
-syn match logtalkOperator "-"
-syn match logtalkOperator "\*"
+syn match logtalkOperator "\(0'\)\@<![+]"
+syn match logtalkOperator "\(0'\)\@<![-]"
+syn match logtalkOperator "\(0'\)\@<!\*"
syn match logtalkOperator "//"
-syn match logtalkOperator "/"
+syn match logtalkOperator "\(0'\)\@<!/"
syn match logtalkKeyword "\<div\ze("
syn match logtalkKeyword "\<r\(ound\|em\)\ze("
syn match logtalkKeyword "\<e\>"
@@ -330,7 +331,7 @@ syn match logtalkKeyword "\<t\(an\|runcate\)\ze("
syn match logtalkKeyword "\<ceiling\ze("
-" Other arithmetic functors
+" Other arithemtic functors
syn match logtalkOperator "\*\*"
syn match logtalkKeyword "\<s\(in\|qrt\)\ze("
@@ -346,18 +347,18 @@ syn match logtalkOperator ">>"
syn match logtalkOperator "<<"
syn match logtalkOperator "/\\"
syn match logtalkOperator "\\/"
-syn match logtalkOperator "\\"
+syn match logtalkOperator "0'\@<!\\"
syn match logtalkKeyword "\<xor\ze("
" Logtalk list operator
-syn match logtalkOperator "|"
+syn match logtalkOperator "\(0'\)\@<!|"
" Logtalk existential quantifier operator
-syn match logtalkOperator "\^"
+syn match logtalkOperator "\(0'\)\@<!^"
" Logtalk numbers
@@ -366,7 +367,7 @@ syn match logtalkNumber "\<\d\+\>"
syn match logtalkNumber "\<\d\+\.\d\+\>"
syn match logtalkNumber "\<\d\+[eE][-+]\=\d\+\>"
syn match logtalkNumber "\<\d\+\.\d\+[eE][-+]\=\d\+\>"
-syn match logtalkNumber "\<0'[\\]\?.\|0''\|0'\"\>"
+syn match logtalkNumber "0'[\\]\?."
syn match logtalkNumber "\<0b[0-1]\+\>"
syn match logtalkNumber "\<0o\o\+\>"
syn match logtalkNumber "\<0x\x\+\>"
@@ -374,13 +375,13 @@ syn match logtalkNumber "\<0x\x\+\>"
" Logtalk end-of-clause
-syn match logtalkOperator "\."
+syn match logtalkOperator "\(0'\)\@<!\."
" Logtalk comments
syn region logtalkBlockComment start="/\*" end="\*/" fold
-syn match logtalkLineComment "%.*"
+syn match logtalkLineComment "%.*$"
syn cluster logtalkComment contains=logtalkBlockComment,logtalkLineComment
diff --git a/runtime/syntax/mail.vim b/runtime/syntax/mail.vim
index 0cd48fc77a..9beeba69e2 100644
--- a/runtime/syntax/mail.vim
+++ b/runtime/syntax/mail.vim
@@ -2,7 +2,7 @@
" Language: Mail file
" Previous Maintainer: Felix von Leitner <leitner@math.fu-berlin.de>
" Maintainer: GI <a@b.c>, where a='gi1242+vim', b='gmail', c='com'
-" Last Change: Wed 14 Aug 2013 08:24:52 AM PDT
+" Last Change: Thu 25 Jan 2024 10:34:02 AM EST
" Quit when a syntax file was already loaded
if exists("b:current_syntax")
@@ -12,6 +12,8 @@ endif
let s:cpo_save = &cpo
set cpo&vim
+syn spell toplevel
+
" The mail header is recognized starting with a "keyword:" line and ending
" with an empty line or other line that can't be in the header. All lines of
" the header are highlighted. Headers of quoted messages (quoted with >) are
@@ -61,6 +63,9 @@ syn region mailVerbatim contains=@mailQuoteExps,@NoSpell keepend start="^\z(\(>
syn match mailURL contains=@NoSpell `\v<(((https?|ftp|gopher)://|(mailto|file|news):)[^' <>"]+|(www|web|w3)[a-z0-9_-]*\.[a-z0-9._-]+\.[^' <>"]+)[a-z0-9/]`
syn match mailEmail contains=@NoSpell "\v[_=a-z\./+0-9-]+\@[a-z0-9._-]+\a{2}"
+" Don't spell emojis
+syn match mailEmoji contains=@NoSpell "\%#=2\v[\U1f300-\U1f64f\U1f900-\U1f9ff]"
+
" Make sure quote markers in regions (header / signature) have correct color
syn match mailQuoteExp1 contained "\v^(\> ?)"
syn match mailQuoteExp2 contained "\v^(\> ?){2}"
@@ -86,14 +91,14 @@ endif
" Define the default highlighting.
hi def link mailVerbatim Special
-hi def link mailHeader Statement
+hi def link mailHeader PreProc
hi def link mailHeaderKey Type
-hi def link mailSignature PreProc
+hi def link mailSignature Comment
hi def link mailHeaderEmail mailEmail
-hi def link mailEmail Special
-hi def link mailURL String
-hi def link mailSubject Title
-hi def link mailQuoted1 Comment
+hi def link mailEmail String
+hi def link mailURL Constant
+hi def link mailSubject Statement
+hi def link mailQuoted1 Function
hi def link mailQuoted3 mailQuoted1
hi def link mailQuoted5 mailQuoted1
hi def link mailQuoted2 Identifier
diff --git a/runtime/syntax/maple.vim b/runtime/syntax/maple.vim
index 78f2b4e09e..b0bd9aaef9 100644
--- a/runtime/syntax/maple.vim
+++ b/runtime/syntax/maple.vim
@@ -1,9 +1,11 @@
" Vim syntax file
" Language: Maple V (based on release 4)
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer:Charles E. Campbell
" Last Change: Mar 26, 2019
+" 2024 Feb 19 by Vim Project (announce adoption)
" Version: 17
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_MAPLE
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_MAPLE
"
" Package Function Selection: {{{1
" Because there are a lot of packages, and because of the potential for namespace
diff --git a/runtime/syntax/masm.vim b/runtime/syntax/masm.vim
index 85e457106d..dc9a292cce 100644
--- a/runtime/syntax/masm.vim
+++ b/runtime/syntax/masm.vim
@@ -2,7 +2,7 @@
" Language: Microsoft Macro Assembler (80x86)
" Orig Author: Rob Brady <robb@datatone.com>
" Maintainer: Wu Yongwei <wuyongwei@gmail.com>
-" Last Change: 2023-09-09 20:48:26 +0800
+" Last Change: 2023-12-20 10:20:04 +0800
" Quit when a syntax file was already loaded
if exists("b:current_syntax")
@@ -459,8 +459,9 @@ syn keyword masmOpcode VMOVAPD VMOVAPS VMOVD VMOVQ VMOVDDUP
syn keyword masmOpcode VMOVHLPS VMOVHPD VMOVHPS VMOVLHPS VMOVLPD
syn keyword masmOpcode VMOVLPS VMOVNTDQA VMOVNTDQ VMOVNTPD VMOVNTPS
syn keyword masmOpcode VMOVSD VMOVSHDUP VMOVSLDUP VMOVSS VMOVUPD
-syn keyword masmOpcode VMOVUPS VMOVDQA32 VMOVDQA64 VMOVDQU8
-syn keyword masmOpcode VMOVDQU16 VMOVDQU32 VMOVDQU64 VMULPD VMULPS
+syn keyword masmOpcode VMOVUPS VMOVDQA VMOVDQA32 VMOVDQA64
+syn keyword masmOpcode VMOVDQU VMOVDQU8 VMOVDQU16 VMOVDQU32 VMOVDQU64
+syn keyword masmOpcode VMULPD VMULPS
syn keyword masmOpcode VMULSD VMULSS VORPD VORPS VSQRTPD VSQRTPS
syn keyword masmOpcode VSQRTSD VSQRTSS VSUBPD VSUBPS VSUBSD VSUBSS
syn keyword masmOpcode VUCOMISD VUCOMISS VUNPCKHPD VUNPCKHPS VUNPCKLPD
@@ -468,8 +469,8 @@ syn keyword masmOpcode VUNPCKLPS VXORPD VXORPS VEXTRACTPS VINSERTPS
syn keyword masmOpcode VPEXTRB VPEXTRW VPEXTRD VPEXTRQ VPINSRB VPINSRW
syn keyword masmOpcode VPINSRD VPINSRQ VPACKSSWB VPACKSSDW VPACKUSDW
syn keyword masmOpcode VPACKUSWB VPADDB VPADDW VPADDD VPADDQ VPADDSB
-syn keyword masmOpcode VPADDSW VPADDUSB VPADDUSW VPANDD VPANDQ VPANDND
-syn keyword masmOpcode VPANDNQ VPAVGB VPAVGW VPCMPEQB VPCMPEQW
+syn keyword masmOpcode VPADDSW VPADDUSB VPADDUSW VPAND VPANDD VPANDQ
+syn keyword masmOpcode VPANDND VPANDNQ VPAVGB VPAVGW VPCMPEQB VPCMPEQW
syn keyword masmOpcode VPCMPEQD VPCMPEQQ VPCMPGTB VPCMPGTW VPCMPGTD
syn keyword masmOpcode VPCMPGTQ VPMAXSB VPMAXSW VPMAXSD VPMAXSQ
syn keyword masmOpcode VPMAXUB VPMAXUW VPMAXUD VPMAXUQ VPMINSB VPMINSW
@@ -482,7 +483,8 @@ syn keyword masmOpcode VPMULLQ VPMULLW VPORD VPORQ VPSUBB VPSUBW
syn keyword masmOpcode VPSUBD VPSUBQ VPSUBSB VPSUBSW VPSUBUSB VPSUBUSW
syn keyword masmOpcode VPUNPCKHBW VPUNPCKHWD VPUNPCKHDQ VPUNPCKHQDQ
syn keyword masmOpcode VPUNPCKLBW VPUNPCKLWD VPUNPCKLDQ VPUNPCKLQDQ
-syn keyword masmOpcode VPXORD VPXORQ VPSADBW VPSHUFB VPSHUFHW VPSHUFLW
+syn keyword masmOpcode VPXOR VPXORD VPXORQ
+syn keyword masmOpcode VPSADBW VPSHUFB VPSHUFHW VPSHUFLW
syn keyword masmOpcode VPSHUFD VPSLLDQ VPSLLW VPSLLD VPSLLQ VPSRAW
syn keyword masmOpcode VPSRAD VPSRAQ VPSRLDQ VPSRLW VPSRLD VPSRLQ
syn keyword masmOpcode VPSLLVW VPSRLVW VPSHUFPD VPSHUFPS VEXTRACTF32X4
@@ -516,7 +518,7 @@ syn keyword masmOpcode VFNMSUB132SS VFNMSUB213SS VFNMSUB231SS
syn keyword masmOpcode VPSRAVW VPSRAVQ
" Other opcodes in Pentium and later processors
-syn keyword masmOpcode CMPXCHG8B CPUID UD2
+syn keyword masmOpcode CMPXCHG8B CPUID UD2 MOVSXD
syn keyword masmOpcode RSM RDMSR WRMSR RDPMC RDTSC SYSENTER SYSEXIT
syn match masmOpcode "CMOV\(P[EO]\|\(N\?\([ABGL]E\?\|[CEOPSZ]\)\)\)\>"
diff --git a/runtime/syntax/mermaid.vim b/runtime/syntax/mermaid.vim
index afdbcc3d62..5a9a217337 100644
--- a/runtime/syntax/mermaid.vim
+++ b/runtime/syntax/mermaid.vim
@@ -2,7 +2,7 @@
" Language: Mermaid
" Maintainer: Craig MacEahern <https://github.com/craigmac/vim-mermaid>
" Filenames: *.mmd
-" Last Change: 2022 Nov 22
+" Last Change: 2023 Dec 26
if exists("b:current_syntax")
finish
@@ -85,54 +85,30 @@ syntax keyword mermaidKeyword
highlight link mermaidKeyword Keyword
syntax match mermaidStatement "|"
-syntax match mermaidStatement "--\?[>x)]>\?+\?-\?"
syntax match mermaidStatement "\~\~\~"
syntax match mermaidStatement "--"
-syntax match mermaidStatement "---"
-syntax match mermaidStatement "-->"
+syntax match mermaidStatement "\%(<|\|[<*o]\)\?\%(--\|\.\.\)\%(|>\|[>*o]\)\?"
+syntax match mermaidStatement "-\{2,4}[>ox-]"
+syntax match mermaidStatement "\.-[>ox]"
syntax match mermaidStatement "-\."
-syntax match mermaidStatement "\.->"
-syntax match mermaidStatement "-\.-"
-syntax match mermaidStatement "-\.\.-"
-syntax match mermaidStatement "-\.\.\.-"
+syntax match mermaidStatement "-\.\{1,3}-"
syntax match mermaidStatement "=="
-syntax match mermaidStatement "==>"
-syntax match mermaidStatement "===>"
-syntax match mermaidStatement "====>"
+syntax match mermaidStatement "=\{2,4}[>ox=]"
syntax match mermaidStatement "&"
-syntax match mermaidStatement "--o"
-syntax match mermaidStatement "--x"
+syntax match mermaidStatement "--\?[>x)]>\?[+-]\?"
syntax match mermaidStatement "x--x"
-syntax match mermaidStatement "-----"
-syntax match mermaidStatement "---->"
-syntax match mermaidStatement "==="
-syntax match mermaidStatement "===="
-syntax match mermaidStatement "====="
+syntax match mermaidStatement "o--o\?"
+syntax match mermaidStatement "<-->\?"
syntax match mermaidStatement ":::"
-syntax match mermaidStatement "<|--"
-syntax match mermaidStatement "\*--"
-syntax match mermaidStatement "o--"
-syntax match mermaidStatement "o--o"
-syntax match mermaidStatement "<--"
-syntax match mermaidStatement "<-->"
-syntax match mermaidStatement "\.\."
-syntax match mermaidStatement "<\.\."
-syntax match mermaidStatement "<|\.\."
-syntax match mermaidStatement "--|>"
-syntax match mermaidStatement "--\*"
-syntax match mermaidStatement "--o"
-syntax match mermaidStatement "\.\.>"
-syntax match mermaidStatement "\.\.|>"
-syntax match mermaidStatement "<|--|>"
syntax match mermaidStatement "||--o{"
highlight link mermaidStatement Statement
-syntax match mermaidIdentifier "[\+-]\?\w\+(.*)[\$\*]\?"
-highlight link mermaidIdentifier Identifier
+" FIXME: This unexpectedly matches flow chart node `id1(text)` or others.
+"syntax match mermaidIdentifier "[\+-]\?\w\+(.*)[\$\*]\?"
+"highlight link mermaidIdentifier Identifier
-syntax match mermaidType "[\+-\#\~]\?\cint\>"
-syntax match mermaidType "[\+-\#\~]\?\cString\>"
-syntax match mermaidType "[\+-\#\~]\?\cbool\>"
+syntax match mermaidType "[\+-\#\~]\?\c\%(const\s\+\|\*\s*\)*\%(unsigned\s\+\)\?\%(int\|u\?int\%(8\|16\|32\|64\)_t\|char\|long\|long\s\+long\)\>\%(\s\+const\|\s*[\*&]\)*"
+syntax match mermaidType "[\+-\#\~]\?\c\%(const\s\+\|\*\s*\)*\%(double\|float\|String\|bool\)\>\%(\s\+const\|\s*[\*&]\)*"
syntax match mermaidType "[\+-\#\~]\?\cBigDecimal\>"
syntax match mermaidType "[\+-\#\~]\?\cList\~.\+\~"
syntax match mermaidType "<<\w\+>>"
diff --git a/runtime/syntax/modula2.vim b/runtime/syntax/modula2.vim
index 4a14cf1f6f..6a9f4af6aa 100644
--- a/runtime/syntax/modula2.vim
+++ b/runtime/syntax/modula2.vim
@@ -1,73 +1,16 @@
" Vim syntax file
-" Language: Modula 2
-" Maintainer: pf@artcom0.north.de (Peter Funk)
-" based on original work of Bram Moolenaar <Bram@vim.org>
-" Last Change: 2001 May 09
+" Language: Modula-2
+" Maintainer: Doug Kearns <dougkearns@gmail.com>
+" Previous Maintainer: pf@artcom0.north.de (Peter Funk)
+" Last Change: 2024 Jan 04
-" quit when a syntax file was already loaded
if exists("b:current_syntax")
finish
endif
-" Don't ignore case (Modula-2 is case significant). This is the default in vim
-
-" Especially emphasize headers of procedures and modules:
-syn region modula2Header matchgroup=modula2Header start="PROCEDURE " end="(" contains=modula2Ident oneline
-syn region modula2Header matchgroup=modula2Header start="MODULE " end=";" contains=modula2Ident oneline
-syn region modula2Header matchgroup=modula2Header start="BEGIN (\*" end="\*)" contains=modula2Ident oneline
-syn region modula2Header matchgroup=modula2Header start="END " end=";" contains=modula2Ident oneline
-syn region modula2Keyword start="END" end=";" contains=ALLBUT,modula2Ident oneline
-
-" Some very important keywords which should be emphasized more than others:
-syn keyword modula2AttKeyword CONST EXIT HALT RETURN TYPE VAR
-" All other keywords in alphabetical order:
-syn keyword modula2Keyword AND ARRAY BY CASE DEFINITION DIV DO ELSE
-syn keyword modula2Keyword ELSIF EXPORT FOR FROM IF IMPLEMENTATION IMPORT
-syn keyword modula2Keyword IN LOOP MOD NOT OF OR POINTER QUALIFIED RECORD
-syn keyword modula2Keyword SET THEN TO UNTIL WHILE WITH
-
-syn keyword modula2Type ADDRESS BITSET BOOLEAN CARDINAL CHAR INTEGER REAL WORD
-syn keyword modula2StdFunc ABS CAP CHR DEC EXCL INC INCL ORD SIZE TSIZE VAL
-syn keyword modula2StdConst FALSE NIL TRUE
-" The following may be discussed, since NEW and DISPOSE are some kind of
-" special builtin macro functions:
-syn keyword modula2StdFunc NEW DISPOSE
-" The following types are added later on and may be missing from older
-" Modula-2 Compilers (they are at least missing from the original report
-" by N.Wirth from March 1980 ;-) Highlighting should apply nevertheless:
-syn keyword modula2Type BYTE LONGCARD LONGINT LONGREAL PROC SHORTCARD SHORTINT
-" same note applies to min and max, which were also added later to m2:
-syn keyword modula2StdFunc MAX MIN
-" The underscore was originally disallowed in m2 ids, it was also added later:
-syn match modula2Ident " [A-Z,a-z][A-Z,a-z,0-9,_]*" contained
-
-" Comments may be nested in Modula-2:
-syn region modula2Comment start="(\*" end="\*)" contains=modula2Comment,modula2Todo
-syn keyword modula2Todo contained TODO FIXME XXX
-
-" Strings
-syn region modula2String start=+"+ end=+"+
-syn region modula2String start="'" end="'"
-syn region modula2Set start="{" end="}"
-
-" Define the default highlighting.
-" Only when an item doesn't have highlighting yet
-
-hi def link modula2Ident Identifier
-hi def link modula2StdConst Boolean
-hi def link modula2Type Identifier
-hi def link modula2StdFunc Identifier
-hi def link modula2Header Type
-hi def link modula2Keyword Statement
-hi def link modula2AttKeyword PreProc
-hi def link modula2Comment Comment
-" The following is just a matter of taste (you want to try this instead):
-" hi modula2Comment term=bold ctermfg=DarkBlue guifg=Blue gui=bold
-hi def link modula2Todo Todo
-hi def link modula2String String
-hi def link modula2Set String
-
+let dialect = modula2#GetDialect()
+exe "runtime! syntax/modula2/opt/" .. dialect .. ".vim"
let b:current_syntax = "modula2"
-" vim: ts=8
+" vim: nowrap sw=2 sts=2 ts=8 noet:
diff --git a/runtime/syntax/modula2/opt/iso.vim b/runtime/syntax/modula2/opt/iso.vim
new file mode 100644
index 0000000000..5bd24f6885
--- /dev/null
+++ b/runtime/syntax/modula2/opt/iso.vim
@@ -0,0 +1,380 @@
+" Vim syntax file
+" Language: Modula-2 (ISO)
+" Maintainer: B.Kowarsch <trijezdci@moc.liamg>
+" Last Change: 2016 August 22
+
+" ----------------------------------------------------
+" THIS FILE IS LICENSED UNDER THE VIM LICENSE
+" see https://github.com/vim/vim/blob/master/LICENSE
+" ----------------------------------------------------
+
+" Remarks:
+" Vim Syntax files are available for the following Modula-2 dialects:
+" * for the PIM dialect : m2pim.vim
+" * for the ISO dialect : m2iso.vim (this file)
+" * for the R10 dialect : m2r10.vim
+
+" -----------------------------------------------------------------------------
+" This syntax description follows ISO standard IS-10514 (aka ISO Modula-2)
+" with the addition of the following language extensions:
+" * non-standard types LONGCARD and LONGBITSET
+" * non-nesting code disabling tags ?< and >? at the start of a line
+" -----------------------------------------------------------------------------
+
+" Parameters:
+"
+" Vim's filetype script recognises Modula-2 dialect tags within the first 200
+" lines of Modula-2 .def and .mod input files. The script sets filetype and
+" dialect automatically when a valid dialect tag is found in the input file.
+" The dialect tag for the ISO dialect is (*!m2iso*). It is recommended to put
+" the tag immediately after the module header in the Modula-2 input file.
+"
+" Example:
+" DEFINITION MODULE Foolib; (*!m2iso*)
+"
+" Variable g:modula2_default_dialect sets the default Modula-2 dialect when the
+" dialect cannot be determined from the contents of the Modula-2 input file:
+" if defined and set to 'm2iso', the default dialect is ISO.
+"
+" Variable g:modula2_iso_allow_lowline controls support for lowline in identifiers:
+" if defined and set to a non-zero value, they are recognised, otherwise not
+"
+" Variable g:modula2_iso_disallow_octals controls the rendering of octal literals:
+" if defined and set to a non-zero value, they are rendered as errors.
+"
+" Variable g:modula2_iso_disallow_synonyms controls the rendering of @, & and ~:
+" if defined and set to a non-zero value, they are rendered as errors.
+"
+" Variables may be defined in Vim startup file .vimrc
+"
+" Examples:
+" let g:modula2_default_dialect = 'm2iso'
+" let g:modula2_iso_allow_lowline = 1
+" let g:modula2_iso_disallow_octals = 1
+" let g:modula2_iso_disallow_synonyms = 1
+
+
+if exists("b:current_syntax")
+ finish
+endif
+
+" Modula-2 is case sensitive
+syn case match
+
+
+" -----------------------------------------------------------------------------
+" Reserved Words
+" -----------------------------------------------------------------------------
+syn keyword modula2Resword AND ARRAY BEGIN BY CASE CONST DEFINITION DIV DO ELSE
+syn keyword modula2Resword ELSIF EXCEPT EXIT EXPORT FINALLY FOR FORWARD FROM IF
+syn keyword modula2Resword IMPLEMENTATION IMPORT IN LOOP MOD NOT OF OR PACKEDSET
+syn keyword modula2Resword POINTER QUALIFIED RECORD REPEAT REM RETRY RETURN SET
+syn keyword modula2Resword THEN TO TYPE UNTIL VAR WHILE WITH
+
+
+" -----------------------------------------------------------------------------
+" Builtin Constant Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2ConstIdent FALSE NIL TRUE INTERRUPTIBLE UNINTERRUPTIBLE
+
+
+" -----------------------------------------------------------------------------
+" Builtin Type Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2TypeIdent BITSET BOOLEAN CHAR PROC
+syn keyword modula2TypeIdent CARDINAL INTEGER LONGINT REAL LONGREAL
+syn keyword modula2TypeIdent COMPLEX LONGCOMPLEX PROTECTION
+
+
+" -----------------------------------------------------------------------------
+" Builtin Procedure and Function Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2ProcIdent CAP DEC EXCL HALT INC INCL
+syn keyword modula2FuncIdent ABS CHR CMPLX FLOAT HIGH IM INT LENGTH LFLOAT MAX MIN
+syn keyword modula2FuncIdent ODD ORD RE SIZE TRUNC VAL
+
+
+" -----------------------------------------------------------------------------
+" Wirthian Macro Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2MacroIdent NEW DISPOSE
+
+
+" -----------------------------------------------------------------------------
+" Unsafe Facilities via Pseudo-Module SYSTEM
+" -----------------------------------------------------------------------------
+syn keyword modula2UnsafeIdent ADDRESS BYTE LOC WORD
+syn keyword modula2UnsafeIdent ADR CAST TSIZE SYSTEM
+syn keyword modula2UnsafeIdent MAKEADR ADDADR SUBADR DIFADR ROTATE SHIFT
+
+
+" -----------------------------------------------------------------------------
+" Non-Portable Language Extensions
+" -----------------------------------------------------------------------------
+syn keyword modula2NonPortableIdent LONGCARD LONGBITSET
+
+
+" -----------------------------------------------------------------------------
+" User Defined Identifiers
+" -----------------------------------------------------------------------------
+syn match modula2Ident "[a-zA-Z][a-zA-Z0-9]*\(_\)\@!"
+syn match modula2LowLineIdent "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)\+"
+
+
+" -----------------------------------------------------------------------------
+" String Literals
+" -----------------------------------------------------------------------------
+syn region modula2String start=/"/ end=/"/ oneline
+syn region modula2String start=/'/ end=/'/ oneline
+
+
+" -----------------------------------------------------------------------------
+" Numeric Literals
+" -----------------------------------------------------------------------------
+syn match modula2Num
+ \ "\(\([0-7]\+\)[BC]\@!\|[89]\)[0-9]*\(\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?\)\?"
+syn match modula2Num "[0-9A-F]\+H"
+syn match modula2Octal "[0-7]\+[BC]"
+
+
+" -----------------------------------------------------------------------------
+" Punctuation
+" -----------------------------------------------------------------------------
+syn match modula2Punctuation
+ \ "\.\|[,:;]\|\*\|[/+-]\|\#\|[=<>]\|\^\|\[\|\]\|(\(\*\)\@!\|[){}]"
+syn match modula2Synonym "[@&~]"
+
+
+" -----------------------------------------------------------------------------
+" Pragmas
+" -----------------------------------------------------------------------------
+syn region modula2Pragma start="<\*" end="\*>"
+syn match modula2DialectTag "(\*!m2iso\(+[a-z0-9]\+\)\?\*)"
+
+" -----------------------------------------------------------------------------
+" Block Comments
+" -----------------------------------------------------------------------------
+syn region modula2Comment start="(\*\(!m2iso\(+[a-z0-9]\+\)\?\*)\)\@!" end="\*)"
+ \ contains = modula2Comment, modula2CommentKey, modula2TechDebtMarker
+syn match modula2CommentKey "[Aa]uthor[s]\?\|[Cc]opyright\|[Ll]icense\|[Ss]ynopsis"
+syn match modula2CommentKey "\([Pp]re\|[Pp]ost\|[Ee]rror\)\-condition[s]\?:"
+
+
+" -----------------------------------------------------------------------------
+" Technical Debt Markers
+" -----------------------------------------------------------------------------
+syn keyword modula2TechDebtMarker contained DEPRECATED FIXME
+syn match modula2TechDebtMarker "TODO[:]\?" contained
+
+" -----------------------------------------------------------------------------
+" Disabled Code Sections
+" -----------------------------------------------------------------------------
+syn region modula2DisabledCode start="^?<" end="^>?"
+
+
+" -----------------------------------------------------------------------------
+" Headers
+" -----------------------------------------------------------------------------
+" !!! this section must be second last !!!
+
+" new module header
+syn match modula2ModuleHeader
+ \ "MODULE\( [A-Z][a-zA-Z0-9]*\)\?"
+ \ contains = modula2ReswordModule, modula2ModuleIdent
+
+syn match modula2ModuleIdent
+ \ "[A-Z][a-zA-Z0-9]*" contained
+
+syn match modula2ModuleTail
+ \ "END [A-Z][a-zA-Z0-9]*\.$"
+ \ contains = modula2ReswordEnd, modula2ModuleIdent, modula2Punctuation
+
+" new procedure header
+syn match modula2ProcedureHeader
+ \ "PROCEDURE\( [a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*\)\?"
+ \ contains = modula2ReswordProcedure,
+ \ modula2ProcedureIdent, modula2ProcedureLowlineIdent, modula2IllegalChar, modula2IllegalIdent
+
+syn match modula2ProcedureIdent
+ \ "\([a-zA-Z]\)\([a-zA-Z0-9]*\)" contained
+
+syn match modula2ProcedureLowlineIdent
+ \ "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)\+" contained
+
+syn match modula2ProcedureTail
+ \ "END\( \([a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*\)[.;]$\)\?"
+ \ contains = modula2ReswordEnd,
+ \ modula2ProcedureIdent, modula2ProcedureLowLineIdent,
+ \ modula2Punctuation, modula2IllegalChar, modula2IllegalIdent
+
+syn keyword modula2ReswordModule contained MODULE
+syn keyword modula2ReswordProcedure contained PROCEDURE
+syn keyword modula2ReswordEnd contained END
+
+
+" -----------------------------------------------------------------------------
+" Illegal Symbols
+" -----------------------------------------------------------------------------
+" !!! this section must be last !!!
+
+" any '`' '!' '$' '%' or '\'
+syn match modula2IllegalChar "[`!$%\\]"
+
+" any solitary sequence of '_'
+syn match modula2IllegalChar "\<_\+\>"
+
+" any '?' at start of line if not followed by '<'
+syn match modula2IllegalChar "^?\(<\)\@!"
+
+" any '?' not following '>' at start of line
+syn match modula2IllegalChar "\(\(^>\)\|\(^\)\)\@<!?"
+
+" any identifiers with leading occurrences of '_'
+syn match modula2IllegalIdent "_\+[a-zA-Z][a-zA-Z0-9]*\(_\+[a-zA-Z0-9]*\)*"
+
+" any identifiers containing consecutive occurences of '_'
+syn match modula2IllegalIdent
+ \ "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*\(__\+[a-zA-Z0-9]\+\(_[a-zA-Z0-9]\+\)*\)\+"
+
+" any identifiers with trailing occurrences of '_'
+syn match modula2IllegalIdent "[a-zA-Z][a-zA-Z0-9]*\(_\+[a-zA-Z0-9]\+\)*_\+\>"
+
+
+" -----------------------------------------------------------------------------
+" Define Rendering Styles
+" -----------------------------------------------------------------------------
+
+" highlight default link modula2PredefIdentStyle Keyword
+" highlight default link modula2ConstIdentStyle modula2PredefIdentStyle
+" highlight default link modula2TypeIdentStyle modula2PredefIdentStyle
+" highlight default link modula2ProcIdentStyle modula2PredefIdentStyle
+" highlight default link modula2FuncIdentStyle modula2PredefIdentStyle
+" highlight default link modula2MacroIdentStyle modula2PredefIdentStyle
+
+highlight default link modula2ConstIdentStyle Constant
+highlight default link modula2TypeIdentStyle Type
+highlight default link modula2ProcIdentStyle Function
+highlight default link modula2FuncIdentStyle Function
+highlight default link modula2MacroIdentStyle Function
+highlight default link modula2UnsafeIdentStyle Question
+highlight default link modula2NonPortableIdentStyle Question
+highlight default link modula2StringLiteralStyle String
+highlight default link modula2CommentStyle Comment
+highlight default link modula2PragmaStyle PreProc
+highlight default link modula2DialectTagStyle SpecialComment
+highlight default link modula2TechDebtMarkerStyle SpecialComment
+highlight default link modula2ReswordStyle Keyword
+highlight default link modula2HeaderIdentStyle Function
+highlight default link modula2UserDefIdentStyle Normal
+highlight default link modula2NumericLiteralStyle Number
+highlight default link modula2PunctuationStyle Delimiter
+highlight default link modula2CommentKeyStyle SpecialComment
+highlight default link modula2DisabledCodeStyle NonText
+
+" -----------------------------------------------------------------------------
+" Assign Rendering Styles
+" -----------------------------------------------------------------------------
+
+" headers
+highlight default link modula2ModuleIdent modula2HeaderIdentStyle
+highlight default link modula2ProcedureIdent modula2HeaderIdentStyle
+highlight default link modula2ModuleHeader Normal
+highlight default link modula2ModuleTail Normal
+highlight default link modula2ProcedureHeader Normal
+highlight default link modula2ProcedureTail Normal
+
+" lowline identifiers are rendered as errors if g:modula2_iso_allow_lowline is unset
+if exists("g:modula2_iso_allow_lowline")
+ if g:modula2_iso_allow_lowline != 0
+ highlight default link modula2ProcedureLowlineIdent modula2HeaderIdentStyle
+ else
+ highlight default link modula2ProcedureLowlineIdent Error
+ endif
+else
+ highlight default link modula2ProcedureLowlineIdent modula2HeaderIdentStyle
+endif
+
+" reserved words
+highlight default link modula2Resword modula2ReswordStyle
+highlight default link modula2ReswordModule modula2ReswordStyle
+highlight default link modula2ReswordProcedure modula2ReswordStyle
+highlight default link modula2ReswordEnd modula2ReswordStyle
+
+" predefined identifiers
+highlight default link modula2ConstIdent modula2ConstIdentStyle
+highlight default link modula2TypeIdent modula2TypeIdentStyle
+highlight default link modula2ProcIdent modula2ProcIdentStyle
+highlight default link modula2FuncIdent modula2FuncIdentStyle
+highlight default link modula2MacroIdent modula2MacroIdentStyle
+
+" unsafe and non-portable identifiers
+highlight default link modula2UnsafeIdent modula2UnsafeIdentStyle
+highlight default link modula2NonPortableIdent modula2NonPortableIdentStyle
+
+" user defined identifiers
+highlight default link modula2Ident modula2UserDefIdentStyle
+
+" lowline identifiers are rendered as errors if g:modula2_iso_allow_lowline is unset
+if exists("g:modula2_iso_allow_lowline")
+ if g:modula2_iso_allow_lowline != 0
+ highlight default link modula2LowLineIdent modula2UserDefIdentStyle
+ else
+ highlight default link modula2LowLineIdent Error
+ endif
+else
+ highlight default link modula2LowLineIdent modula2UserDefIdentStyle
+endif
+
+" literals
+highlight default link modula2String modula2StringLiteralStyle
+highlight default link modula2Num modula2NumericLiteralStyle
+
+" octal literals are rendered as errors if g:modula2_iso_disallow_octals is set
+if exists("g:modula2_iso_disallow_octals")
+ if g:modula2_iso_disallow_octals != 0
+ highlight default link modula2Octal Error
+ else
+ highlight default link modula2Octal modula2NumericLiteralStyle
+ endif
+else
+ highlight default link modula2Octal modula2NumericLiteralStyle
+endif
+
+" punctuation
+highlight default link modula2Punctuation modula2PunctuationStyle
+
+" synonyms & and ~ are rendered as errors if g:modula2_iso_disallow_synonyms is set
+if exists("g:modula2_iso_disallow_synonyms")
+ if g:modula2_iso_disallow_synonyms != 0
+ highlight default link modula2Synonym Error
+ else
+ highlight default link modula2Synonym modula2PunctuationStyle
+ endif
+else
+ highlight default link modula2Synonym modula2PunctuationStyle
+endif
+
+" pragmas
+highlight default link modula2Pragma modula2PragmaStyle
+highlight default link modula2DialectTag modula2DialectTagStyle
+
+" comments
+highlight default link modula2Comment modula2CommentStyle
+highlight default link modula2CommentKey modula2CommentKeyStyle
+
+" technical debt markers
+highlight default link modula2TechDebtMarker modula2TechDebtMarkerStyle
+
+" disabled code
+highlight default link modula2DisabledCode modula2DisabledCodeStyle
+
+" illegal symbols
+highlight default link modula2IllegalChar Error
+highlight default link modula2IllegalIdent Error
+
+
+let b:current_syntax = "modula2"
+
+" vim: ts=4
+
+" END OF FILE
diff --git a/runtime/syntax/modula2/opt/pim.vim b/runtime/syntax/modula2/opt/pim.vim
new file mode 100644
index 0000000000..1626db91cf
--- /dev/null
+++ b/runtime/syntax/modula2/opt/pim.vim
@@ -0,0 +1,377 @@
+" Vim syntax file
+" Language: Modula-2 (PIM)
+" Maintainer: B.Kowarsch <trijezdci@moc.liamg>
+" Last Change: 2016 August 22
+
+" ----------------------------------------------------
+" THIS FILE IS LICENSED UNDER THE VIM LICENSE
+" see https://github.com/vim/vim/blob/master/LICENSE
+" ----------------------------------------------------
+
+" Remarks:
+" Vim Syntax files are available for the following Modula-2 dialects:
+" * for the PIM dialect : m2pim.vim (this file)
+" * for the ISO dialect : m2iso.vim
+" * for the R10 dialect : m2r10.vim
+
+" -----------------------------------------------------------------------------
+" This syntax description follows the 3rd and 4th editions of N.Wirth's Book
+" Programming in Modula-2 (aka PIM) plus the following language extensions:
+" * non-leading, non-trailing, non-consecutive lowlines _ in identifiers
+" * widely supported non-standard types BYTE, LONGCARD and LONGBITSET
+" * non-nesting code disabling tags ?< and >? at the start of a line
+" -----------------------------------------------------------------------------
+
+" Parameters:
+"
+" Vim's filetype script recognises Modula-2 dialect tags within the first 200
+" lines of Modula-2 .def and .mod input files. The script sets filetype and
+" dialect automatically when a valid dialect tag is found in the input file.
+" The dialect tag for the PIM dialect is (*!m2pim*). It is recommended to put
+" the tag immediately after the module header in the Modula-2 input file.
+"
+" Example:
+" DEFINITION MODULE Foolib; (*!m2pim*)
+"
+" Variable g:modula2_default_dialect sets the default Modula-2 dialect when the
+" dialect cannot be determined from the contents of the Modula-2 input file:
+" if defined and set to 'm2pim', the default dialect is PIM.
+"
+" Variable g:modula2_pim_allow_lowline controls support for lowline in identifiers:
+" if defined and set to a non-zero value, they are recognised, otherwise not
+"
+" Variable g:modula2_pim_disallow_octals controls the rendering of octal literals:
+" if defined and set to a non-zero value, they are rendered as errors.
+"
+" Variable g:modula2_pim_disallow_synonyms controls the rendering of & and ~:
+" if defined and set to a non-zero value, they are rendered as errors.
+"
+" Variables may be defined in Vim startup file .vimrc
+"
+" Examples:
+" let g:modula2_default_dialect = 'm2pim'
+" let g:modula2_pim_allow_lowline = 1
+" let g:modula2_pim_disallow_octals = 1
+" let g:modula2_pim_disallow_synonyms = 1
+
+
+if exists("b:current_syntax")
+ finish
+endif
+
+" Modula-2 is case sensitive
+syn case match
+
+
+" -----------------------------------------------------------------------------
+" Reserved Words
+" -----------------------------------------------------------------------------
+syn keyword modula2Resword AND ARRAY BEGIN BY CASE CONST DEFINITION DIV DO ELSE
+syn keyword modula2Resword ELSIF EXIT EXPORT FOR FROM IF IMPLEMENTATION IMPORT
+syn keyword modula2Resword IN LOOP MOD NOT OF OR POINTER QUALIFIED RECORD REPEAT
+syn keyword modula2Resword RETURN SET THEN TO TYPE UNTIL VAR WHILE WITH
+
+
+" -----------------------------------------------------------------------------
+" Builtin Constant Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2ConstIdent FALSE NIL TRUE
+
+
+" -----------------------------------------------------------------------------
+" Builtin Type Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2TypeIdent BITSET BOOLEAN CHAR PROC
+syn keyword modula2TypeIdent CARDINAL INTEGER LONGINT REAL LONGREAL
+
+
+" -----------------------------------------------------------------------------
+" Builtin Procedure and Function Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2ProcIdent CAP DEC EXCL HALT INC INCL
+syn keyword modula2FuncIdent ABS CHR FLOAT HIGH MAX MIN ODD ORD SIZE TRUNC VAL
+
+
+" -----------------------------------------------------------------------------
+" Wirthian Macro Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2MacroIdent NEW DISPOSE
+
+
+" -----------------------------------------------------------------------------
+" Unsafe Facilities via Pseudo-Module SYSTEM
+" -----------------------------------------------------------------------------
+syn keyword modula2UnsafeIdent ADDRESS PROCESS WORD
+syn keyword modula2UnsafeIdent ADR TSIZE NEWPROCESS TRANSFER SYSTEM
+
+
+" -----------------------------------------------------------------------------
+" Non-Portable Language Extensions
+" -----------------------------------------------------------------------------
+syn keyword modula2NonPortableIdent BYTE LONGCARD LONGBITSET
+
+
+" -----------------------------------------------------------------------------
+" User Defined Identifiers
+" -----------------------------------------------------------------------------
+syn match modula2Ident "[a-zA-Z][a-zA-Z0-9]*\(_\)\@!"
+syn match modula2LowLineIdent "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)\+"
+
+
+" -----------------------------------------------------------------------------
+" String Literals
+" -----------------------------------------------------------------------------
+syn region modula2String start=/"/ end=/"/ oneline
+syn region modula2String start=/'/ end=/'/ oneline
+
+
+" -----------------------------------------------------------------------------
+" Numeric Literals
+" -----------------------------------------------------------------------------
+syn match modula2Num
+ \ "\(\([0-7]\+\)[BC]\@!\|[89]\)[0-9]*\(\.[0-9]\+\([eE][+-]\?[0-9]\+\)\?\)\?"
+syn match modula2Num "[0-9A-F]\+H"
+syn match modula2Octal "[0-7]\+[BC]"
+
+
+" -----------------------------------------------------------------------------
+" Punctuation
+" -----------------------------------------------------------------------------
+syn match modula2Punctuation
+ \ "\.\|[,:;]\|\*\|[/+-]\|\#\|[=<>]\|\^\|\[\|\]\|(\(\*\)\@!\|[){}]"
+syn match modula2Synonym "[&~]"
+
+
+" -----------------------------------------------------------------------------
+" Pragmas
+" -----------------------------------------------------------------------------
+syn region modula2Pragma start="(\*\$" end="\*)"
+syn match modula2DialectTag "(\*!m2pim\(+[a-z0-9]\+\)\?\*)"
+
+" -----------------------------------------------------------------------------
+" Block Comments
+" -----------------------------------------------------------------------------
+syn region modula2Comment start="(\*\(\$\|!m2pim\(+[a-z0-9]\+\)\?\*)\)\@!" end="\*)"
+ \ contains = modula2Comment, modula2CommentKey, modula2TechDebtMarker
+syn match modula2CommentKey "[Aa]uthor[s]\?\|[Cc]opyright\|[Ll]icense\|[Ss]ynopsis"
+syn match modula2CommentKey "\([Pp]re\|[Pp]ost\|[Ee]rror\)\-condition[s]\?:"
+
+
+" -----------------------------------------------------------------------------
+" Technical Debt Markers
+" -----------------------------------------------------------------------------
+syn keyword modula2TechDebtMarker contained DEPRECATED FIXME
+syn match modula2TechDebtMarker "TODO[:]\?" contained
+
+" -----------------------------------------------------------------------------
+" Disabled Code Sections
+" -----------------------------------------------------------------------------
+syn region modula2DisabledCode start="^?<" end="^>?"
+
+
+" -----------------------------------------------------------------------------
+" Headers
+" -----------------------------------------------------------------------------
+" !!! this section must be second last !!!
+
+" new module header
+syn match modula2ModuleHeader
+ \ "MODULE\( [A-Z][a-zA-Z0-9]*\)\?"
+ \ contains = modula2ReswordModule, modula2ModuleIdent
+
+syn match modula2ModuleIdent
+ \ "[A-Z][a-zA-Z0-9]*" contained
+
+syn match modula2ModuleTail
+ \ "END [A-Z][a-zA-Z0-9]*\.$"
+ \ contains = modula2ReswordEnd, modula2ModuleIdent, modula2Punctuation
+
+" new procedure header
+syn match modula2ProcedureHeader
+ \ "PROCEDURE\( [a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*\)\?"
+ \ contains = modula2ReswordProcedure,
+ \ modula2ProcedureIdent, modula2ProcedureLowlineIdent, modula2IllegalChar, modula2IllegalIdent
+
+syn match modula2ProcedureIdent
+ \ "\([a-zA-Z]\)\([a-zA-Z0-9]*\)" contained
+
+syn match modula2ProcedureLowlineIdent
+ \ "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)\+" contained
+
+syn match modula2ProcedureTail
+ \ "END\( \([a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*\)[.;]$\)\?"
+ \ contains = modula2ReswordEnd,
+ \ modula2ProcedureIdent, modula2ProcedureLowLineIdent,
+ \ modula2Punctuation, modula2IllegalChar, modula2IllegalIdent
+
+syn keyword modula2ReswordModule contained MODULE
+syn keyword modula2ReswordProcedure contained PROCEDURE
+syn keyword modula2ReswordEnd contained END
+
+
+" -----------------------------------------------------------------------------
+" Illegal Symbols
+" -----------------------------------------------------------------------------
+" !!! this section must be last !!!
+
+" any '`' '!' '@ ''$' '%' or '\'
+syn match modula2IllegalChar "[`!@$%\\]"
+
+" any solitary sequence of '_'
+syn match modula2IllegalChar "\<_\+\>"
+
+" any '?' at start of line if not followed by '<'
+syn match modula2IllegalChar "^?\(<\)\@!"
+
+" any '?' not following '>' at start of line
+syn match modula2IllegalChar "\(\(^>\)\|\(^\)\)\@<!?"
+
+" any identifiers with leading occurrences of '_'
+syn match modula2IllegalIdent "_\+[a-zA-Z][a-zA-Z0-9]*\(_\+[a-zA-Z0-9]*\)*"
+
+" any identifiers containing consecutive occurences of '_'
+syn match modula2IllegalIdent
+ \ "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*\(__\+[a-zA-Z0-9]\+\(_[a-zA-Z0-9]\+\)*\)\+"
+
+" any identifiers with trailing occurrences of '_'
+syn match modula2IllegalIdent "[a-zA-Z][a-zA-Z0-9]*\(_\+[a-zA-Z0-9]\+\)*_\+\>"
+
+
+" -----------------------------------------------------------------------------
+" Define Rendering Styles
+" -----------------------------------------------------------------------------
+
+" highlight default link modula2PredefIdentStyle Keyword
+" highlight default link modula2ConstIdentStyle modula2PredefIdentStyle
+" highlight default link modula2TypeIdentStyle modula2PredefIdentStyle
+" highlight default link modula2ProcIdentStyle modula2PredefIdentStyle
+" highlight default link modula2FuncIdentStyle modula2PredefIdentStyle
+" highlight default link modula2MacroIdentStyle modula2PredefIdentStyle
+
+highlight default link modula2ConstIdentStyle Constant
+highlight default link modula2TypeIdentStyle Type
+highlight default link modula2ProcIdentStyle Function
+highlight default link modula2FuncIdentStyle Function
+highlight default link modula2MacroIdentStyle Function
+highlight default link modula2UnsafeIdentStyle Question
+highlight default link modula2NonPortableIdentStyle Question
+highlight default link modula2StringLiteralStyle String
+highlight default link modula2CommentStyle Comment
+highlight default link modula2PragmaStyle PreProc
+highlight default link modula2DialectTagStyle SpecialComment
+highlight default link modula2TechDebtMarkerStyle SpecialComment
+highlight default link modula2ReswordStyle Keyword
+highlight default link modula2HeaderIdentStyle Function
+highlight default link modula2UserDefIdentStyle Normal
+highlight default link modula2NumericLiteralStyle Number
+highlight default link modula2PunctuationStyle Delimiter
+highlight default link modula2CommentKeyStyle SpecialComment
+highlight default link modula2DisabledCodeStyle NonText
+
+" -----------------------------------------------------------------------------
+" Assign Rendering Styles
+" -----------------------------------------------------------------------------
+
+" headers
+highlight default link modula2ModuleIdent modula2HeaderIdentStyle
+highlight default link modula2ProcedureIdent modula2HeaderIdentStyle
+highlight default link modula2ModuleHeader Normal
+highlight default link modula2ModuleTail Normal
+highlight default link modula2ProcedureHeader Normal
+highlight default link modula2ProcedureTail Normal
+
+" lowline identifiers are rendered as errors if g:modula2_pim_allow_lowline is unset
+if exists("g:modula2_pim_allow_lowline")
+ if g:modula2_pim_allow_lowline != 0
+ highlight default link modula2ProcedureLowlineIdent modula2HeaderIdentStyle
+ else
+ highlight default link modula2ProcedureLowlineIdent Error
+ endif
+else
+ highlight default link modula2ProcedureLowlineIdent Error
+endif
+
+" reserved words
+highlight default link modula2Resword modula2ReswordStyle
+highlight default link modula2ReswordModule modula2ReswordStyle
+highlight default link modula2ReswordProcedure modula2ReswordStyle
+highlight default link modula2ReswordEnd modula2ReswordStyle
+
+" predefined identifiers
+highlight default link modula2ConstIdent modula2ConstIdentStyle
+highlight default link modula2TypeIdent modula2TypeIdentStyle
+highlight default link modula2ProcIdent modula2ProcIdentStyle
+highlight default link modula2FuncIdent modula2FuncIdentStyle
+highlight default link modula2MacroIdent modula2MacroIdentStyle
+
+" unsafe and non-portable identifiers
+highlight default link modula2UnsafeIdent modula2UnsafeIdentStyle
+highlight default link modula2NonPortableIdent modula2NonPortableIdentStyle
+
+" user defined identifiers
+highlight default link modula2Ident modula2UserDefIdentStyle
+
+" lowline identifiers are rendered as errors if g:modula2_pim_allow_lowline is unset
+if exists("g:modula2_pim_allow_lowline")
+ if g:modula2_pim_allow_lowline != 0
+ highlight default link modula2LowLineIdent modula2UserDefIdentStyle
+ else
+ highlight default link modula2LowLineIdent Error
+ endif
+else
+ highlight default link modula2LowLineIdent Error
+endif
+
+" literals
+highlight default link modula2String modula2StringLiteralStyle
+highlight default link modula2Num modula2NumericLiteralStyle
+
+" octal literals are rendered as errors if g:modula2_pim_disallow_octals is set
+if exists("g:modula2_pim_disallow_octals")
+ if g:modula2_pim_disallow_octals != 0
+ highlight default link modula2Octal Error
+ else
+ highlight default link modula2Octal modula2NumericLiteralStyle
+ endif
+else
+ highlight default link modula2Octal modula2NumericLiteralStyle
+endif
+
+" punctuation
+highlight default link modula2Punctuation modula2PunctuationStyle
+
+" synonyms & and ~ are rendered as errors if g:modula2_pim_disallow_synonyms is set
+if exists("g:modula2_pim_disallow_synonyms")
+ if g:modula2_pim_disallow_synonyms != 0
+ highlight default link modula2Synonym Error
+ else
+ highlight default link modula2Synonym modula2PunctuationStyle
+ endif
+else
+ highlight default link modula2Synonym modula2PunctuationStyle
+endif
+
+" pragmas
+highlight default link modula2Pragma modula2PragmaStyle
+highlight default link modula2DialectTag modula2DialectTagStyle
+
+" comments
+highlight default link modula2Comment modula2CommentStyle
+highlight default link modula2CommentKey modula2CommentKeyStyle
+
+" technical debt markers
+highlight default link modula2TechDebtMarker modula2TechDebtMarkerStyle
+
+" disabled code
+highlight default link modula2DisabledCode modula2DisabledCodeStyle
+
+" illegal symbols
+highlight default link modula2IllegalChar Error
+highlight default link modula2IllegalIdent Error
+
+
+let b:current_syntax = "modula2"
+
+" vim: ts=4
+
+" END OF FILE
diff --git a/runtime/syntax/modula2/opt/r10.vim b/runtime/syntax/modula2/opt/r10.vim
new file mode 100644
index 0000000000..775f498dfb
--- /dev/null
+++ b/runtime/syntax/modula2/opt/r10.vim
@@ -0,0 +1,452 @@
+" Vim syntax file
+" Language: Modula-2 (R10)
+" Maintainer: B.Kowarsch <trijezdci@moc.liamg>
+" Last Change: 2020 June 18 (moved repository from bb to github)
+
+" ----------------------------------------------------
+" THIS FILE IS LICENSED UNDER THE VIM LICENSE
+" see https://github.com/vim/vim/blob/master/LICENSE
+" ----------------------------------------------------
+
+" Remarks:
+" Vim Syntax files are available for the following Modula-2 dialects:
+" * for the PIM dialect : m2pim.vim
+" * for the ISO dialect : m2iso.vim
+" * for the R10 dialect : m2r10.vim (this file)
+
+" -----------------------------------------------------------------------------
+" This syntax description follows the Modula-2 Revision 2010 language report
+" (Kowarsch and Sutcliffe, 2015) available at http://modula-2.info/m2r10.
+" -----------------------------------------------------------------------------
+
+" Parameters:
+"
+" Vim's filetype script recognises Modula-2 dialect tags within the first 200
+" lines of Modula-2 .def and .mod input files. The script sets filetype and
+" dialect automatically when a valid dialect tag is found in the input file.
+" The dialect tag for the R10 dialect is (*!m2r10*). It is recommended to put
+" the tag immediately after the module header in the Modula-2 input file.
+"
+" Example:
+" DEFINITION MODULE Foolib; (*!m2r10*)
+"
+" Variable g:modula2_default_dialect sets the default Modula-2 dialect when the
+" dialect cannot be determined from the contents of the Modula-2 input file:
+" if defined and set to 'm2r10', the default dialect is R10.
+"
+" Variable g:modula2_r10_allow_lowline controls support for lowline in identifiers:
+" if defined and set to a non-zero value, they are recognised, otherwise not
+"
+" Variables may be defined in Vim startup file .vimrc
+"
+" Examples:
+" let g:modula2_default_dialect = 'm2r10'
+" let g:modula2_r10_allow_lowline = 1
+
+
+if exists("b:current_syntax")
+ finish
+endif
+
+" Modula-2 is case sensitive
+syn case match
+
+
+" -----------------------------------------------------------------------------
+" Reserved Words
+" -----------------------------------------------------------------------------
+" Note: MODULE, PROCEDURE and END are defined separately further below
+syn keyword modula2Resword ALIAS AND ARGLIST ARRAY BEGIN CASE CONST COPY DEFINITION
+syn keyword modula2Resword DIV DO ELSE ELSIF EXIT FOR FROM GENLIB IF IMPLEMENTATION
+syn keyword modula2Resword IMPORT IN LOOP MOD NEW NOT OF OPAQUE OR POINTER READ
+syn keyword modula2Resword RECORD RELEASE REPEAT RETAIN RETURN SET THEN TO TYPE
+syn keyword modula2Resword UNTIL VAR WHILE WRITE YIELD
+
+
+" -----------------------------------------------------------------------------
+" Schroedinger's Tokens
+" -----------------------------------------------------------------------------
+syn keyword modula2SchroedToken CAPACITY COROUTINE LITERAL
+
+
+" -----------------------------------------------------------------------------
+" Builtin Constant Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2ConstIdent NIL FALSE TRUE
+
+
+" -----------------------------------------------------------------------------
+" Builtin Type Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2TypeIdent BOOLEAN CHAR UNICHAR OCTET
+syn keyword modula2TypeIdent CARDINAL LONGCARD INTEGER LONGINT REAL LONGREAL
+
+
+" -----------------------------------------------------------------------------
+" Builtin Procedure and Function Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2ProcIdent APPEND INSERT REMOVE SORT SORTNEW
+syn keyword modula2FuncIdent CHR ORD ODD ABS SGN MIN MAX LOG2 POW2 ENTIER
+syn keyword modula2FuncIdent PRED SUCC PTR COUNT LENGTH
+
+
+" -----------------------------------------------------------------------------
+" Builtin Macro Identifiers
+" -----------------------------------------------------------------------------
+syn keyword modula2MacroIdent NOP TMIN TMAX TSIZE TLIMIT
+
+
+" -----------------------------------------------------------------------------
+" Builtin Primitives
+" -----------------------------------------------------------------------------
+syn keyword modula2PrimitiveIdent SXF VAL STORE VALUE SEEK SUBSET
+
+
+" -----------------------------------------------------------------------------
+" Unsafe Facilities via Pseudo-Module UNSAFE
+" -----------------------------------------------------------------------------
+syn keyword modula2UnsafeIdent UNSAFE BYTE WORD LONGWORD OCTETSEQ
+syn keyword modula2UnsafeIdent ADD SUB INC DEC SETBIT HALT
+syn keyword modula2UnsafeIdent ADR CAST BIT SHL SHR BWNOT BWAND BWOR
+
+
+" -----------------------------------------------------------------------------
+" Non-Portable Language Extensions
+" -----------------------------------------------------------------------------
+syn keyword modula2NonPortableIdent ASSEMBLER ASM REG
+
+
+" -----------------------------------------------------------------------------
+" User Defined Identifiers
+" -----------------------------------------------------------------------------
+syn match modula2Ident "[a-zA-Z][a-zA-Z0-9]*\(_\)\@!"
+syn match modula2LowLineIdent "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)\+"
+
+syn match modula2ReswordDo "\(TO\)\@<!DO"
+syn match modula2ReswordTo "TO\(\sDO\)\@!"
+
+" TODO: support for OpenVMS reswords and identifiers which may include $ and %
+
+
+" -----------------------------------------------------------------------------
+" String Literals
+" -----------------------------------------------------------------------------
+syn region modula2String start=/"/ end=/"/ oneline
+syn region modula2String start="\(^\|\s\|[({=<>&#,]\|\[\)\@<='" end=/'/ oneline
+
+
+" -----------------------------------------------------------------------------
+" Numeric Literals
+" -----------------------------------------------------------------------------
+syn match modula2Base2Num "0b[01]\+\('[01]\+\)*"
+syn match modula2Base16Num "0[ux][0-9A-F]\+\('[0-9A-F]\+\)*"
+
+"| *** VMSCRIPT BUG ALERT ***
+"| The regular expression below causes errors when split into separate strings
+"|
+"| syn match modula2Base10Num
+"| \ "\(\(0[bux]\@!\|[1-9]\)[0-9]*\('[0-9]\+\)*\)" .
+"| \ "\(\.[0-9]\+\('[0-9]\+\)*\(e[+-]\?[0-9]\+\('[0-9]\+\)*\)\?\)\?"
+"|
+"| E475: Invalid argument: modula2Base10Num "\(\(0[bux]\@!\|[1-9]\)[0-9]*\('[0-9]\+\)*\)"
+"| . "\(\.[0-9]\+\('[0-9]\+\)*\(e[+-]\?[0-9]\+\('[0-9]\+\)*\)\?\)\?"
+"|
+"| However, the same regular expression works just fine as a sole string.
+"|
+"| As a consequence, we have no choice but to put it all into a single line
+"| which greatly diminishes readability and thereby increases the opportunity
+"| for error during maintenance. Ideally, regular expressions should be split
+"| into small human readable pieces with interleaved comments that explain
+"| precisely what each piece is doing. Vimscript imposes poor design. :-(
+
+syn match modula2Base10Num
+ \ "\(\(0[bux]\@!\|[1-9]\)[0-9]*\('[0-9]\+\)*\)\(\.[0-9]\+\('[0-9]\+\)*\(e[+-]\?[0-9]\+\('[0-9]\+\)*\)\?\)\?"
+
+
+" -----------------------------------------------------------------------------
+" Punctuation
+" -----------------------------------------------------------------------------
+syn match modula2Punctuation
+ \ "\.\|[,:;]\|\*\|[/+-]\|\#\|[=<>&]\|\^\|\[\|\]\|(\(\*\)\@!\|[){}]"
+
+
+" -----------------------------------------------------------------------------
+" Pragmas
+" -----------------------------------------------------------------------------
+syn region modula2Pragma start="<\*" end="\*>"
+ \ contains = modula2PragmaKey, modula2TechDebtPragma
+syn keyword modula2PragmaKey contained MSG IF ELSIF ELSE END INLINE NOINLINE OUT
+syn keyword modula2PragmaKey contained GENERATED ENCODING ALIGN PADBITS NORETURN
+syn keyword modula2PragmaKey contained PURITY SINGLEASSIGN LOWLATENCY VOLATILE
+syn keyword modula2PragmaKey contained FORWARD ADDR FFI FFIDENT
+
+syn match modula2DialectTag "(\*!m2r10\(+[a-z0-9]\+\)\?\*)"
+
+
+" -----------------------------------------------------------------------------
+" Line Comments
+" -----------------------------------------------------------------------------
+syn region modula2Comment start=/^!/ end=/$/ oneline
+
+
+" -----------------------------------------------------------------------------
+" Block Comments
+" -----------------------------------------------------------------------------
+syn region modula2Comment
+ \ start="\(END\s\)\@<!(\*\(!m2r10\(+[a-z0-9]\+\)\?\*)\)\@!" end="\*)"
+ \ contains = modula2Comment, modula2CommentKey, modula2TechDebtMarker
+
+syn match modula2CommentKey
+ \ "[Aa]uthor[s]\?\|[Cc]opyright\|[Ll]icense\|[Ss]ynopsis" contained
+syn match modula2CommentKey
+ \ "\([Pp]re\|[Pp]ost\|[Ee]rror\)\-condition[s]\?:" contained
+
+
+" -----------------------------------------------------------------------------
+" Block Statement Tails
+" -----------------------------------------------------------------------------
+syn match modula2ReswordEnd
+ \ "END" nextgroup = modula2StmtTailComment skipwhite
+syn match modula2StmtTailComment
+ \ "(\*\s\(IF\|CASE\|FOR\|LOOP\|WHILE\)\s\*)" contained
+
+
+" -----------------------------------------------------------------------------
+" Technical Debt Markers
+" -----------------------------------------------------------------------------
+syn match modula2ToDoHeader "TO DO"
+
+syn match modula2ToDoTail
+ \ "END\(\s(\*\sTO DO\s\*)\)\@=" nextgroup = modula2ToDoTailComment skipwhite
+syntax match modula2ToDoTailComment "(\*\sTO DO\s\*)" contained
+
+" contained within pragma
+syn keyword modula2TechDebtPragma contained DEPRECATED
+
+" contained within comment
+syn keyword modula2TechDebtMarker contained FIXME
+
+
+" -----------------------------------------------------------------------------
+" Disabled Code Sections
+" -----------------------------------------------------------------------------
+syn region modula2DisabledCode start="^?<" end="^>?"
+
+
+" -----------------------------------------------------------------------------
+" Headers
+" -----------------------------------------------------------------------------
+" !!! this section must be second last !!!
+
+" module header
+syn match modula2ModuleHeader
+ \ "\(MODULE\|BLUEPRINT\)\( [A-Z][a-zA-Z0-9]*\)\?"
+ \ contains = modula2ReswordModule, modula2ReswordBlueprint, modula2ModuleIdent
+
+syn match modula2ModuleIdent
+ \ "[A-Z][a-zA-Z0-9]*" contained
+
+syn match modula2ModuleTail
+ \ "END [A-Z][a-zA-Z0-9]*\.$"
+ \ contains = modula2ReswordEnd, modula2ModuleIdent, modula2Punctuation
+
+" procedure, sole occurrence
+syn match modula2ProcedureHeader
+ \ "PROCEDURE\(\s\[\|\s[a-zA-Z]\)\@!" contains = modula2ReswordProcedure
+
+" procedure header
+syn match modula2ProcedureHeader
+ \ "PROCEDURE [a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*"
+ \ contains = modula2ReswordProcedure,
+ \ modula2ProcedureIdent, modula2ProcedureLowlineIdent, modula2IllegalChar, modula2IllegalIdent
+
+" procedure binding to operator
+syn match modula2ProcedureHeader
+ \ "PROCEDURE \[[+-\*/\\=<>]\] [a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*"
+ \ contains = modula2ReswordProcedure, modula2Punctuation,
+ \ modula2ProcedureIdent, modula2ProcedureLowlineIdent, modula2IllegalChar, modula2IllegalIdent
+
+" procedure binding to builtin
+syn match modula2ProcedureHeader
+ \ "PROCEDURE \[[A-Z]\+\(:\([#\*,]\|++\|--\)\?\)\?\] [a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*"
+ \ contains = modula2ReswordProcedure,
+ \ modula2Punctuation, modula2Resword, modula2SchroedToken,
+ \ modula2ProcIdent, modula2FuncIdent, modula2PrimitiveIdent,
+ \ modula2ProcedureIdent, modula2ProcedureLowlineIdent, modula2IllegalChar, modula2IllegalIdent
+
+syn match modula2ProcedureIdent
+ \ "\([a-zA-Z]\)\([a-zA-Z0-9]*\)" contained
+
+syn match modula2ProcedureLowlineIdent
+ \ "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)\+" contained
+
+syn match modula2ProcedureTail
+ \ "END [a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*;$"
+ \ contains = modula2ReswordEnd,
+ \ modula2ProcedureIdent, modula2ProcedureLowLineIdent,
+ \ modula2Punctuation, modula2IllegalChar, modula2IllegalIdent
+
+syn keyword modula2ReswordModule contained MODULE
+syn keyword modula2ReswordBlueprint contained BLUEPRINT
+syn keyword modula2ReswordProcedure contained PROCEDURE
+syn keyword modula2ReswordEnd contained END
+
+
+" -----------------------------------------------------------------------------
+" Illegal Symbols
+" -----------------------------------------------------------------------------
+" !!! this section must be last !!!
+
+" any '`' '~' '@' '$' '%'
+syn match modula2IllegalChar "[`~@$%]"
+
+" any solitary sequence of '_'
+syn match modula2IllegalChar "\<_\+\>"
+
+" any '?' at start of line if not followed by '<'
+syn match modula2IllegalChar "^?\(<\)\@!"
+
+" any '?' not following '>' at start of line
+syn match modula2IllegalChar "\(\(^>\)\|\(^\)\)\@<!?"
+
+" any identifiers with leading occurrences of '_'
+syn match modula2IllegalIdent "_\+[a-zA-Z][a-zA-Z0-9]*\(_\+[a-zA-Z0-9]*\)*"
+
+" any identifiers containing consecutive occurences of '_'
+syn match modula2IllegalIdent
+ \ "[a-zA-Z][a-zA-Z0-9]*\(_[a-zA-Z0-9]\+\)*\(__\+[a-zA-Z0-9]\+\(_[a-zA-Z0-9]\+\)*\)\+"
+
+" any identifiers with trailing occurrences of '_'
+syn match modula2IllegalIdent "[a-zA-Z][a-zA-Z0-9]*\(_\+[a-zA-Z0-9]\+\)*_\+\>"
+
+
+" -----------------------------------------------------------------------------
+" Define Rendering Styles
+" -----------------------------------------------------------------------------
+
+" highlight default link modula2PredefIdentStyle Keyword
+" highlight default link modula2ConstIdentStyle modula2PredefIdentStyle
+" highlight default link modula2TypeIdentStyle modula2PredefIdentStyle
+" highlight default link modula2ProcIdentStyle modula2PredefIdentStyle
+" highlight default link modula2FuncIdentStyle modula2PredefIdentStyle
+" highlight default link modula2MacroIdentStyle modula2PredefIdentStyle
+
+highlight default link modula2ConstIdentStyle Constant
+highlight default link modula2TypeIdentStyle Type
+highlight default link modula2ProcIdentStyle Function
+highlight default link modula2FuncIdentStyle Function
+highlight default link modula2MacroIdentStyle Function
+highlight default link modula2PrimitiveIdentStyle Function
+highlight default link modula2UnsafeIdentStyle Question
+highlight default link modula2NonPortableIdentStyle Question
+highlight default link modula2StringLiteralStyle String
+highlight default link modula2CommentStyle Comment
+highlight default link modula2PragmaStyle PreProc
+highlight default link modula2PragmaKeyStyle PreProc
+highlight default link modula2DialectTagStyle SpecialComment
+highlight default link modula2TechDebtMarkerStyle SpecialComment
+highlight default link modula2ReswordStyle Keyword
+highlight default link modula2HeaderIdentStyle Function
+highlight default link modula2UserDefIdentStyle Normal
+highlight default link modula2NumericLiteralStyle Number
+highlight default link modula2PunctuationStyle Delimiter
+highlight default link modula2CommentKeyStyle SpecialComment
+highlight default link modula2DisabledCodeStyle NonText
+
+
+" -----------------------------------------------------------------------------
+" Assign Rendering Styles
+" -----------------------------------------------------------------------------
+
+" headers
+highlight default link modula2ModuleIdent modula2HeaderIdentStyle
+highlight default link modula2ProcedureIdent modula2HeaderIdentStyle
+highlight default link modula2ModuleHeader modula2HeaderIdentStyle
+highlight default link modula2ModuleTail Normal
+highlight default link modula2ProcedureHeader Normal
+highlight default link modula2ProcedureTail Normal
+
+" lowline identifiers are rendered as errors if g:modula2_r10_allow_lowline is unset
+if exists("g:modula2_r10_allow_lowline")
+ if g:modula2_r10_allow_lowline != 0
+ highlight default link modula2ProcedureLowlineIdent modula2HeaderIdentStyle
+ else
+ highlight default link modula2ProcedureLowlineIdent Error
+ endif
+else
+ highlight default link modula2ProcedureLowlineIdent modula2HeaderIdentStyle
+endif
+
+" reserved words
+highlight default link modula2Resword modula2ReswordStyle
+highlight default link modula2ReswordModule modula2ReswordStyle
+highlight default link modula2ReswordProcedure modula2ReswordStyle
+highlight default link modula2ReswordEnd modula2ReswordStyle
+highlight default link modula2ReswordDo modula2ReswordStyle
+highlight default link modula2ReswordTo modula2ReswordStyle
+highlight default link modula2SchroedToken modula2ReswordStyle
+
+" predefined identifiers
+highlight default link modula2ConstIdent modula2ConstIdentStyle
+highlight default link modula2TypeIdent modula2TypeIdentStyle
+highlight default link modula2ProcIdent modula2ProcIdentStyle
+highlight default link modula2FuncIdent modula2FuncIdentStyle
+highlight default link modula2MacroIdent modula2MacroIdentStyle
+highlight default link modula2PrimitiveIdent modula2PrimitiveIdentStyle
+
+" unsafe and non-portable identifiers
+highlight default link modula2UnsafeIdent modula2UnsafeIdentStyle
+highlight default link modula2NonPortableIdent modula2NonPortableIdentStyle
+
+" user defined identifiers
+highlight default link modula2Ident modula2UserDefIdentStyle
+
+" lowline identifiers are rendered as errors if g:modula2_r10_allow_lowline is unset
+if exists("g:modula2_r10_allow_lowline")
+ if g:modula2_r10_allow_lowline != 0
+ highlight default link modula2LowLineIdent modula2UserDefIdentStyle
+ else
+ highlight default link modula2LowLineIdent Error
+ endif
+else
+ highlight default link modula2LowLineIdent modula2UserDefIdentStyle
+endif
+
+" literals
+highlight default link modula2String modula2StringLiteralStyle
+highlight default link modula2Base2Num modula2NumericLiteralStyle
+highlight default link modula2Base10Num modula2NumericLiteralStyle
+highlight default link modula2Base16Num modula2NumericLiteralStyle
+
+" punctuation
+highlight default link modula2Punctuation modula2PunctuationStyle
+
+" pragmas
+highlight default link modula2Pragma modula2PragmaStyle
+highlight default link modula2PragmaKey modula2PragmaKeyStyle
+highlight default link modula2DialectTag modula2DialectTagStyle
+
+" comments
+highlight default link modula2Comment modula2CommentStyle
+highlight default link modula2CommentKey modula2CommentKeyStyle
+highlight default link modula2ToDoTailComment modula2CommentStyle
+highlight default link modula2StmtTailComment modula2CommentStyle
+
+" technical debt markers
+highlight default link modula2ToDoHeader modula2TechDebtMarkerStyle
+highlight default link modula2ToDoTail modula2TechDebtMarkerStyle
+highlight default link modula2TechDebtPragma modula2TechDebtMarkerStyle
+
+" disabled code
+highlight default link modula2DisabledCode modula2DisabledCodeStyle
+
+" illegal symbols
+highlight default link modula2IllegalChar Error
+highlight default link modula2IllegalIdent Error
+
+
+let b:current_syntax = "modula2"
+
+" vim: ts=4
+
+" END OF FILE
diff --git a/runtime/syntax/netrw.vim b/runtime/syntax/netrw.vim
index 1f02bbef78..f5b7fdc2c6 100644
--- a/runtime/syntax/netrw.vim
+++ b/runtime/syntax/netrw.vim
@@ -1,6 +1,8 @@
" Language : Netrw Listing Syntax
-" Maintainer : Charles E. Campbell
-" Last change: Nov 07, 2019
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
+" Last Change: Nov 07, 2019
+" 2024 Feb 19 by Vim Project (announce adoption)
" Version : 20
" ---------------------------------------------------------------------
if exists("b:current_syntax")
diff --git a/runtime/syntax/odin.vim b/runtime/syntax/odin.vim
new file mode 100644
index 0000000000..4169ebb7d9
--- /dev/null
+++ b/runtime/syntax/odin.vim
@@ -0,0 +1,109 @@
+" Vim indent plugin file
+" Language: Odin
+" Maintainer: Maxim Kim <habamax@gmail.com>
+" Website: https://github.com/habamax/vim-odin
+" Last Change: 2024-01-15
+"
+" This file has been manually translated from Vim9 script.
+
+if exists("b:current_syntax")
+ finish
+endif
+
+let s:cpo_save = &cpo
+set cpo&vim
+
+syntax keyword odinKeyword using transmute cast distinct opaque where dynamic
+syntax keyword odinKeyword struct enum union const bit_field bit_set
+syntax keyword odinKeyword package proc map import export foreign
+syntax keyword odinKeyword size_of offset_of type_info_of typeid_of type_of align_of
+syntax keyword odinKeyword return defer
+syntax keyword odinKeyword or_return or_else
+syntax keyword odinKeyword inline no_inline
+
+syntax keyword odinConditional if when else do for switch case continue break
+syntax keyword odinType string cstring bool b8 b16 b32 b64 rune any rawptr
+syntax keyword odinType f16 f32 f64 f16le f16be f32le f32be f64le f64be
+syntax keyword odinType u8 u16 u32 u64 u128 u16le u32le u64le u128le u16be
+syntax keyword odinType u32be u64be u128be uint uintptr i8 i16 i32 i64 i128
+syntax keyword odinType i16le i32le i64le i128le i16be i32be i64be i128be
+syntax keyword odinType int complex complex32 complex64 complex128 matrix typeid
+syntax keyword odinType quaternion quaternion64 quaternion128 quaternion256
+syntax keyword odinBool true false
+syntax keyword odinNull nil
+syntax match odinUninitialized '\s\+---\(\s\|$\)'
+
+syntax keyword odinOperator in notin not_in
+syntax match odinOperator "?" display
+syntax match odinOperator "->" display
+
+syntax match odinTodo "TODO" contained
+syntax match odinTodo "XXX" contained
+syntax match odinTodo "FIXME" contained
+syntax match odinTodo "HACK" contained
+
+syntax region odinRawString start=+`+ end=+`+
+syntax region odinChar start=+'+ skip=+\\\\\|\\'+ end=+'+
+syntax region odinString start=+"+ skip=+\\\\\|\\'+ end=+"+ contains=odinEscape
+syntax match odinEscape display contained /\\\([nrt\\'"]\|x\x\{2}\)/
+
+syntax match odinProcedure "\v<\w*>(\s*::\s*proc)@="
+
+syntax match odinAttribute "@\ze\<\w\+\>" display
+syntax region odinAttribute
+ \ matchgroup=odinAttribute
+ \ start="@\ze(" end="\ze)"
+ \ transparent oneline
+
+syntax match odinInteger "\-\?\<\d\+\>" display
+syntax match odinFloat "\-\?\<[0-9][0-9_]*\%(\.[0-9][0-9_]*\)\%([eE][+-]\=[0-9_]\+\)\=" display
+syntax match odinHex "\<0[xX][0-9A-Fa-f]\+\>" display
+syntax match odinDoz "\<0[zZ][0-9a-bA-B]\+\>" display
+syntax match odinOct "\<0[oO][0-7]\+\>" display
+syntax match odinBin "\<0[bB][01]\+\>" display
+
+syntax match odinAddressOf "&" display
+syntax match odinDeref "\^" display
+
+syntax match odinMacro "#\<\w\+\>" display
+
+syntax match odinTemplate "$\<\w\+\>"
+
+syntax region odinLineComment start=/\/\// end=/$/ contains=@Spell,odinTodo
+syntax region odinBlockComment start=/\/\*/ end=/\*\// contains=@Spell,odinTodo,odinBlockComment
+syn sync ccomment odinBlockComment
+
+highlight def link odinKeyword Statement
+highlight def link odinConditional Conditional
+highlight def link odinOperator Operator
+
+highlight def link odinString String
+highlight def link odinRawString String
+highlight def link odinChar Character
+highlight def link odinEscape Special
+
+highlight def link odinProcedure Function
+
+highlight def link odinMacro PreProc
+
+highlight def link odinLineComment Comment
+highlight def link odinBlockComment Comment
+
+highlight def link odinTodo Todo
+
+highlight def link odinAttribute Statement
+highlight def link odinType Type
+highlight def link odinBool Boolean
+highlight def link odinNull Constant
+highlight def link odinUninitialized Constant
+highlight def link odinInteger Number
+highlight def link odinFloat Float
+highlight def link odinHex Number
+highlight def link odinOct Number
+highlight def link odinBin Number
+highlight def link odinDoz Number
+
+let b:current_syntax = "odin"
+
+let &cpo = s:cpo_save
+unlet s:cpo_save
diff --git a/runtime/syntax/pacmanlog.vim b/runtime/syntax/pacmanlog.vim
new file mode 100644
index 0000000000..98abd58685
--- /dev/null
+++ b/runtime/syntax/pacmanlog.vim
@@ -0,0 +1,41 @@
+" Vim syntax file
+" Language: pacman.log
+" Maintainer: Ronan Pigott <ronan@rjp.ie>
+" Last Change: 2023 Dec 04
+
+if exists("b:current_syntax")
+ finish
+endif
+
+syn sync maxlines=1
+syn region pacmanlogMsg start='\S' end='$' keepend contains=pacmanlogTransaction,pacmanlogALPMMsg
+syn region pacmanlogTag start='\['hs=s+1 end='\]'he=e-1 keepend nextgroup=pacmanlogMsg
+syn region pacmanlogTime start='^\['hs=s+1 end='\]'he=e-1 keepend nextgroup=pacmanlogTag
+
+syn match pacmanlogPackageName '\v[a-z0-9@_+.-]+' contained skipwhite nextgroup=pacmanlogPackageVersion
+syn match pacmanlogPackageVersion '(.*)' contained
+
+syn match pacmanlogTransaction 'transaction \v(started|completed)$' contained
+syn match pacmanlogInstalled '\v(re)?installed' contained nextgroup=pacmanlogPackageName
+syn match pacmanlogUpgraded 'upgraded' contained nextgroup=pacmanlogPackageName
+syn match pacmanlogDowngraded 'downgraded' contained nextgroup=pacmanlogPackageName
+syn match pacmanlogRemoved 'removed' contained nextgroup=pacmanlogPackageName
+syn match pacmanlogWarning 'warning:.*$' contained
+
+syn region pacmanlogALPMMsg start='\v(\[ALPM\] )@<=(transaction|(re)?installed|upgraded|downgraded|removed|warning)>' end='$' contained
+ \ contains=pacmanlogTransaction,pacmanlogInstalled,pacmanlogUpgraded,pacmanlogDowngraded,pacmanlogRemoved,pacmanlogWarning,pacmanlogPackageName,pacmanlogPackgeVersion
+
+hi def link pacmanlogTime String
+hi def link pacmanlogTag Type
+
+hi def link pacmanlogTransaction Special
+hi def link pacmanlogInstalled Identifier
+hi def link pacmanlogRemoved Repeat
+hi def link pacmanlogUpgraded pacmanlogInstalled
+hi def link pacmanlogDowngraded pacmanlogRemoved
+hi def link pacmanlogWarning WarningMsg
+
+hi def link pacmanlogPackageName Normal
+hi def link pacmanlogPackageVersion Comment
+
+let b:current_syntax = "pacmanlog"
diff --git a/runtime/syntax/qf.vim b/runtime/syntax/qf.vim
index 6f2ea6a92e..3131caccd8 100644
--- a/runtime/syntax/qf.vim
+++ b/runtime/syntax/qf.vim
@@ -15,6 +15,12 @@ syn match qfSeparator "|" nextgroup=qfLineNr contained
syn match qfLineNr "[^|]*" contained contains=qfError
syn match qfError "error" contained
+" Hide file name and line number for help outline (TOC).
+if has_key(w:, 'qf_toc') || get(w:, 'quickfix_title') =~# '\<TOC$'
+ setlocal conceallevel=3 concealcursor=nc
+ syn match Ignore "^[^|]*|[^|]*| " conceal
+endif
+
" The default highlighting.
hi def link qfFileName Directory
hi def link qfLineNr LineNr
diff --git a/runtime/syntax/quarto.vim b/runtime/syntax/quarto.vim
index d5d4ee257d..f83071dd7f 100644
--- a/runtime/syntax/quarto.vim
+++ b/runtime/syntax/quarto.vim
@@ -1,7 +1,9 @@
" Language: Quarto (Markdown with chunks of R, Python and other languages)
-" Provisory Maintainer: Jakson Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Fri Feb 24, 2023 08:26AM
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2023 Feb 24 08:26AM
+" 2024 Feb 19 by Vim Project (announce adoption)
"
" The developers of tools for Quarto maintain Vim runtime files in their
" Github repository and, if required, I will hand over the maintenance of
diff --git a/runtime/syntax/query.lua b/runtime/syntax/query.lua
index 8f40b1cb8a..1e129dbeff 100644
--- a/runtime/syntax/query.lua
+++ b/runtime/syntax/query.lua
@@ -1,5 +1,5 @@
-- Neovim syntax file
--- Language: Tree-sitter query
+-- Language: Treesitter query
-- Last Change: 2022 Apr 13
-- it's a lisp!
diff --git a/runtime/syntax/r.vim b/runtime/syntax/r.vim
index 9b3754ae23..fa73194332 100644
--- a/runtime/syntax/r.vim
+++ b/runtime/syntax/r.vim
@@ -1,12 +1,14 @@
" Vim syntax file
" Language: R (GNU S)
-" Maintainer: Jakson Aquino <jalvesaq@gmail.com>
-" Former Maintainers: Vaidotas Zemlys <zemlys@gmail.com>
-" Tom Payne <tom@tompayne.org>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainers: Jakson Aquino <jalvesaq@gmail.com>
+" Vaidotas Zemlys <zemlys@gmail.com>
+" Tom Payne <tom@tompayne.org>
" Contributor: Johannes Ranke <jranke@uni-bremen.de>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Thu Nov 17, 2022 10:13PM
-" Filenames: *.R *.r *.Rhistory *.Rt
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Filenames: *.R *.r *.Rhistory *.Rt
+" Last Change: 2023 Dec 24 08:05AM
+" 2024 Feb 19 by Vim Project (announce adoption)
"
" NOTE: The highlighting of R functions might be defined in
" runtime files created by a filetype plugin, if installed.
@@ -26,11 +28,7 @@ if exists("b:current_syntax")
finish
endif
-if has("patch-7.4.1142")
- syn iskeyword @,48-57,_,.
-else
- setlocal iskeyword=@,48-57,_,.
-endif
+syn iskeyword @,48-57,_,.
" The variables g:r_hl_roxygen and g:r_syn_minlines were renamed on April 8, 2017.
if exists("g:r_hl_roxygen")
diff --git a/runtime/syntax/racket.vim b/runtime/syntax/racket.vim
index b1ed2b454c..fcd64a7c9b 100644
--- a/runtime/syntax/racket.vim
+++ b/runtime/syntax/racket.vim
@@ -4,7 +4,7 @@
" Previous Maintainer: Will Langstroth <will@langstroth.com>
" URL: https://github.com/benknoble/vim-racket
" Description: Contains all of the keywords in #lang racket
-" Last Change: 2022 Aug 12
+" Last Change: 2023 Sep 22
" Initializing:
if exists("b:current_syntax")
@@ -514,13 +514,13 @@ syntax region racketString start=/\%(\\\)\@<!"/ skip=/\\[\\"]/ end=/"/ contains=
syntax region racketString start=/#"/ skip=/\\[\\"]/ end=/"/ contains=racketStringEscapeError,racketStringEscape
if exists("racket_no_string_fold")
- syn region racketString start=/#<<\z(.*\)$/ end=/^\z1$/
+ syn region racketHereString start=/#<<\z(.*\)$/ end=/^\z1$/
else
- syn region racketString start=/#<<\z(.*\)$/ end=/^\z1$/ fold
+ syn region racketHereString start=/#<<\z(.*\)$/ end=/^\z1$/ fold
endif
-syntax cluster racketTop add=racketError,racketConstant,racketStruc,racketString
+syntax cluster racketTop add=racketError,racketConstant,racketStruc,racketString,racketHereString
" Numbers
@@ -623,6 +623,7 @@ highlight default link racketFunc Function
highlight default link racketString String
highlight default link racketStringEscape Special
+highlight default link racketHereString String
highlight default link racketUStringEscape Special
highlight default link racketStringEscapeError Error
highlight default link racketChar Character
diff --git a/runtime/syntax/rhelp.vim b/runtime/syntax/rhelp.vim
index 8cac585bb0..7407538e4c 100644
--- a/runtime/syntax/rhelp.vim
+++ b/runtime/syntax/rhelp.vim
@@ -1,9 +1,11 @@
" Vim syntax file
" Language: R Help File
-" Maintainer: Jakson Aquino <jalvesaq@gmail.com>
-" Former Maintainer: Johannes Ranke <jranke@uni-bremen.de>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Tue Jun 28, 2016 08:53AM
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainers: Jakson Aquino <jalvesaq@gmail.com>
+" Johannes Ranke <jranke@uni-bremen.de>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2016 Jun 28 08:53AM
+" 2024 Feb 19 by Vim Project (announce adoption)
" Remarks: - Includes R syntax highlighting in the appropriate
" sections if an r.vim file is in the same directory or in the
" default debian location.
diff --git a/runtime/syntax/rmd.vim b/runtime/syntax/rmd.vim
index 93343dd729..4b4db1e783 100644
--- a/runtime/syntax/rmd.vim
+++ b/runtime/syntax/rmd.vim
@@ -1,7 +1,9 @@
" Language: Markdown with chunks of R, Python and other languages
-" Maintainer: Jakson Aquino <jalvesaq@gmail.com>
-" Homepage: https://github.com/jalvesaq/R-Vim-runtime
-" Last Change: Wed May 17, 2023 06:34AM
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Jakson Alves de Aquino <jalvesaq@gmail.com>
+" Former Repository: https://github.com/jalvesaq/R-Vim-runtime
+" Last Change: 2023 Dec 24 07:21AM
+" 2024 Feb 19 by Vim Project (announce adoption)
"
" For highlighting pandoc extensions to markdown like citations and TeX and
" many other advanced features like folding of markdown sections, it is
@@ -16,6 +18,13 @@ endif
let s:cpo_save = &cpo
set cpo&vim
+let g:rmd_include_latex = get(g:, 'rmd_include_latex', 1)
+if g:rmd_include_latex == 0 || g:rmd_include_latex == 1
+ let b:rmd_has_LaTeX = v:false
+elseif g:rmd_include_latex == 2
+ let b:rmd_has_LaTeX = v:true
+endif
+
" Highlight the header of the chunks as R code
let g:rmd_syn_hl_chunk = get(g:, 'rmd_syn_hl_chunk', 0)
@@ -136,7 +145,7 @@ syn match knitrBodyVar '| \zs\S\{-}\ze:' contained containedin=knitrBodyOptions
let g:rmd_fenced_languages = get(g:, 'rmd_fenced_languages', ['r'])
let s:no_syntax_vim = []
-function IncludeLanguage(lng)
+function s:IncludeLanguage(lng)
if a:lng =~ '='
let ftpy = substitute(a:lng, '.*=', '', '')
let lnm = substitute(a:lng, '=.*', '', '')
@@ -171,11 +180,23 @@ function IncludeLanguage(lng)
endfunction
for s:type in g:rmd_fenced_languages
- call IncludeLanguage(s:type)
+ call s:IncludeLanguage(s:type)
endfor
unlet! s:type
-function CheckRmdFencedLanguages()
+let s:LaTeX_included = v:false
+function s:IncludeLaTeX()
+ let s:LaTeX_included = v:true
+ unlet! b:current_syntax
+ syn include @RmdLaTeX syntax/tex.vim
+ " From vim-pandoc-syntax
+ syn region rmdLaTeXInlineMath start=/\v\\@<!\$\S@=/ end=/\v\\@<!\$\d@!/ keepend contains=@RmdLaTeX
+ syn match rmdLaTeXCmd /\\[[:alpha:]]\+\(\({.\{-}}\)\=\(\[.\{-}\]\)\=\)*/ contains=@RmdLaTeX
+ syn region rmdLaTeX start='\$\$' end='\$\$' keepend contains=@RmdLaTeX
+ syn region rmdLaTeX start=/\\begin{\z(.\{-}\)}/ end=/\\end{\z1}/ keepend contains=@RmdLaTeX
+endfunction
+
+function s:CheckRmdFencedLanguages()
let alines = getline(1, '$')
call filter(alines, "v:val =~ '^```{'")
call map(alines, "substitute(v:val, '^```{', '', '')")
@@ -193,16 +214,31 @@ function CheckRmdFencedLanguages()
endfor
if has_lng == 0
let g:rmd_fenced_languages += [tpy]
- call IncludeLanguage(tpy)
+ call s:IncludeLanguage(tpy)
endif
endfor
+
+ if hlexists('pandocLaTeXCommand')
+ return
+ endif
+ if g:rmd_include_latex
+ if !b:rmd_has_LaTeX && (search('\$\$', 'wn') > 0 ||
+ \ search('\\begin{', 'wn') > 0) ||
+ \ search('\\[[:alpha:]]\+', 'wn') ||
+ \ search('\$[^\$]\+\$', 'wn')
+ let b:rmd_has_LaTeX = v:true
+ endif
+ if b:rmd_has_LaTeX && !s:LaTeX_included
+ call s:IncludeLaTeX()
+ endif
+ endif
endfunction
if g:rmd_dynamic_fenced_languages
- call CheckRmdFencedLanguages()
+ call s:CheckRmdFencedLanguages()
augroup RmdSyntax
autocmd!
- autocmd BufWritePost <buffer> call CheckRmdFencedLanguages()
+ autocmd BufWritePost <buffer> call s:CheckRmdFencedLanguages()
augroup END
endif
@@ -225,6 +261,8 @@ unlet s:save_pandoc_lngs
let &cpo = s:cpo_save
unlet s:cpo_save
+syntax iskeyword clear
+
let b:current_syntax = "rmd"
" vim: ts=8 sw=2
diff --git a/runtime/syntax/rpcgen.vim b/runtime/syntax/rpcgen.vim
index 60c9b8cdda..e5a0b0b56f 100644
--- a/runtime/syntax/rpcgen.vim
+++ b/runtime/syntax/rpcgen.vim
@@ -1,9 +1,11 @@
" Vim syntax file
" Language: rpcgen
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Aug 31, 2016
+" 2024 Feb 19 by Vim Project (announce adoption)
" Version: 13
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_RPCGEN
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_RPCGEN
if exists("b:current_syntax")
finish
diff --git a/runtime/syntax/sh.vim b/runtime/syntax/sh.vim
index e2b1947197..97e74d205f 100644
--- a/runtime/syntax/sh.vim
+++ b/runtime/syntax/sh.vim
@@ -1,10 +1,11 @@
" Vim syntax file
" Language: shell (sh) Korn shell (ksh) bash (sh)
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
-" Previous Maintainer: Lennart Schultz <Lennart.Schultz@ecmwf.int>
-" Last Change: Feb 28, 2023
+" Maintainer: This runtime file is looking for a new maintainer.
+" Previous Maintainers: Charles E. Campbell
+" Lennart Schultz <Lennart.Schultz@ecmwf.int>
+" Last Change: 2024 Mar 04 by Vim Project
" Version: 208
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SH
" For options and settings, please use: :help ft-sh-syntax
" This file includes many ideas from Eric Brunet (eric.brunet@ens.fr) and heredoc fixes from Felipe Contreras
@@ -138,17 +139,17 @@ endif
syn cluster shArithParenList contains=shArithmetic,shArithParen,shCaseEsac,shComment,shDeref,shDo,shDerefSimple,shEcho,shEscape,shNumber,shOperator,shPosnParm,shExSingleQuote,shExDoubleQuote,shHereString,shRedir,shSingleQuote,shDoubleQuote,shStatement,shVariable,shAlias,shTest,shCtrlSeq,shSpecial,shParen,bashSpecialVariables,bashStatement,shIf,shFor,shFunctionKey,shFunctionOne,shFunctionTwo
syn cluster shArithList contains=@shArithParenList,shParenError
syn cluster shCaseEsacList contains=shCaseStart,shCaseLabel,shCase,shCaseBar,shCaseIn,shComment,shDeref,shDerefSimple,shCaseCommandSub,shCaseExSingleQuote,shCaseSingleQuote,shCaseDoubleQuote,shCtrlSeq,@shErrorList,shStringSpecial,shCaseRange
-syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSubBQ,shComment,shDblBrace,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq
+syn cluster shCaseList contains=@shCommandSubList,shCaseEsac,shColon,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shComment,shDblBrace,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq
if exists("b:is_kornshell") || exists("b:is_bash")
syn cluster shCaseList add=shForPP,shDblParen
endif
syn cluster shCommandSubList contains=shAlias,shArithmetic,shCmdParenRegion,shCommandSub,shComment,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shHereDoc,shNumber,shOperator,shOption,shPosnParm,shHereString,shRedir,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable
syn cluster shCurlyList contains=shNumber,shComma,shDeref,shDerefSimple,shDerefSpecial
" COMBAK: removing shEscape from shDblQuoteList fails ksh04:43 -- Jun 09, 2022: I don't see the problem with ksh04, so am reinstating shEscape
-syn cluster shDblQuoteList contains=shArithmetic,shCommandSub,shCommandSubBQ,shDeref,shDerefSimple,shEscape,shPosnParm,shCtrlSeq,shSpecial,shSpecialDQ
+syn cluster shDblQuoteList contains=shArithmetic,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shDeref,shDerefSimple,shEscape,shPosnParm,shCtrlSeq,shSpecial,shSpecialDQ
syn cluster shDerefList contains=shDeref,shDerefSimple,shDerefVar,shDerefSpecial,shDerefWordError,shDerefPSR,shDerefPPS
syn cluster shDerefVarList contains=shDerefOffset,shDerefOp,shDerefVarArray,shDerefOpError
-syn cluster shEchoList contains=shArithmetic,shCommandSub,shCommandSubBQ,shDeref,shDerefSimple,shEscape,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote
+syn cluster shEchoList contains=shArithmetic,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shDeref,shDerefSimple,shEscape,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shCtrlSeq,shEchoQuote
syn cluster shExprList1 contains=shCharClass,shNumber,shOperator,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shDblBrace,shDeref,shDerefSimple,shCtrlSeq
syn cluster shExprList2 contains=@shExprList1,@shCaseList,shTest
syn cluster shFunctionList contains=@shCommandSubList,shCaseEsac,shColon,shComment,shDo,shEcho,shExpr,shFor,shHereDoc,shIf,shOption,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shOperator,shCtrlSeq
@@ -159,24 +160,29 @@ endif
syn cluster shHereBeginList contains=@shCommandSubList
syn cluster shHereList contains=shBeginHere,shHerePayload
syn cluster shHereListDQ contains=shBeginHere,@shDblQuoteList,shHerePayload
-syn cluster shIdList contains=shArithmetic,shCommandSub,shCommandSubBQ,shWrapLineOperator,shSetOption,shComment,shDeref,shDerefSimple,shHereString,shNumber,shOperator,shRedir,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq,shStringSpecial,shAtExpr
+syn cluster shIdList contains=shArithmetic,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shWrapLineOperator,shSetOption,shComment,shDeref,shDerefSimple,shHereString,shNumber,shOperator,shRedir,shExSingleQuote,shExDoubleQuote,shSingleQuote,shDoubleQuote,shExpr,shCtrlSeq,shStringSpecial,shAtExpr
syn cluster shIfList contains=@shLoopList,shDblBrace,shDblParen,shFunctionKey,shFunctionOne,shFunctionTwo
syn cluster shLoopList contains=@shCaseList,@shErrorList,shCaseEsac,shConditional,shDblBrace,shExpr,shFor,shIf,shOption,shSet,shTest,shTestOpr,shTouch
if exists("b:is_kornshell") || exists("b:is_bash")
syn cluster shLoopList add=shForPP,shDblParen
endif
-syn cluster shPPSLeftList contains=shAlias,shArithmetic,shCmdParenRegion,shCommandSub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shHereDoc,shNumber,shOperator,shOption,shPosnParm,shHereString,shRedir,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable
+syn cluster shPPSLeftList contains=shAlias,shArithmetic,shCmdParenRegion,shCommandSub,shSubshare,shValsub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shEcho,shEscape,shExDoubleQuote,shExpr,shExSingleQuote,shHereDoc,shNumber,shOperator,shOption,shPosnParm,shHereString,shRedir,shSingleQuote,shSpecial,shStatement,shSubSh,shTest,shVariable
syn cluster shPPSRightList contains=shDeref,shDerefSimple,shEscape,shPosnParm
-syn cluster shSubShList contains=@shCommandSubList,shCommandSubBQ,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator
-syn cluster shTestList contains=shArithmetic,shCharClass,shCommandSub,shCommandSubBQ,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shSpecialDQ,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr
+syn cluster shSubShList contains=@shCommandSubList,shCommandSubBQ,shSubshare,shValsub,shCaseEsac,shColon,shCommandSub,shComment,shDo,shEcho,shExpr,shFor,shIf,shHereString,shRedir,shSetList,shSource,shStatement,shVariable,shCtrlSeq,shOperator
+syn cluster shTestList contains=shArithmetic,shCharClass,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shCtrlSeq,shDeref,shDerefSimple,shDoubleQuote,shSpecialDQ,shExDoubleQuote,shExpr,shExSingleQuote,shNumber,shOperator,shSingleQuote,shTest,shTestOpr
syn cluster shNoZSList contains=shSpecialNoZS
-syn cluster shForList contains=shTestOpr,shNumber,shDerefSimple,shDeref,shCommandSub,shCommandSubBQ,shArithmetic
+syn cluster shForList contains=shTestOpr,shNumber,shDerefSimple,shDeref,shCommandSub,shCommandSubBQ,shSubshare,shValsub,shArithmetic
" Echo: {{{1
" ====
" This one is needed INSIDE a CommandSub, so that `echo bla` be correct
-syn region shEcho matchgroup=shStatement start="\<echo\>" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment
-syn region shEcho matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment
+if exists("b:is_kornshell")
+ syn region shEcho matchgroup=shStatement start="\<echo\>" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 end="\ze[ \t\n;]}" contains=@shEchoList skipwhite nextgroup=shQuickComment
+ syn region shEcho matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 end="\ze[ \t\n;]}" contains=@shEchoList skipwhite nextgroup=shQuickComment
+else
+ syn region shEcho matchgroup=shStatement start="\<echo\>" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment
+ syn region shEcho matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shEchoDelim end="$" matchgroup=NONE end="[<>;&|()`]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment
+endif
if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix")
syn region shEchoDeref contained matchgroup=shStatement start="\<echo\>" skip="\\$" matchgroup=shEchoDelim end="$" end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment
syn region shEchoDeref contained matchgroup=shStatement start="\<print\>" skip="\\$" matchgroup=shEchoDelim end="$" end="[<>;&|()`}]"me=e-1 end="\d[<>]"me=e-2 end="#"me=e-1 contains=@shEchoList skipwhite nextgroup=shQuickComment
@@ -336,6 +342,10 @@ syn match shEscape contained '\%(^\)\@!\%(\\\\\)*\\.' nextgroup=shComment
" an Error under /bin/sh. By consensus of vimdev'ers!
if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix")
syn region shCommandSub matchgroup=shCmdSubRegion start="\$(\ze[^(]" skip='\\\\\|\\.' end=")" contains=@shCommandSubList
+ if exists("b:is_kornshell")
+ syn region shSubshare matchgroup=shCmdSubRegion start="\${\ze[ \t\n<]" skip='\\\\\|\\.' end="\zs[ \t\n;]}" contains=@shCommandSubList
+ syn region shValsub matchgroup=shCmdSubRegion start="\${|" skip='\\\\\|\\.' end="}" contains=@shCommandSubList
+ endif
syn region shArithmetic matchgroup=shArithRegion start="\$((" skip='\\\\\|\\.' end="))" contains=@shArithList
syn region shArithmetic matchgroup=shArithRegion start="\$\[" skip='\\\\\|\\.' end="\]" contains=@shArithList
syn match shSkipInitWS contained "^\s\+"
@@ -343,7 +353,7 @@ if exists("b:is_kornshell") || exists("b:is_bash") || exists("b:is_posix")
elseif !exists("g:sh_no_error")
syn region shCommandSub matchgroup=Error start="\$(" end=")" contains=@shCommandSubList
endif
-syn region shCmdParenRegion matchgroup=shCmdSubRegion start="(\ze[^(]" skip='\\\\\|\\.' end=")" contains=@shCommandSubList
+syn region shCmdParenRegion matchgroup=shCmdSubRegion start="((\@!" skip='\\\\\|\\.' end=")" contains=@shCommandSubList
if exists("b:is_bash")
syn cluster shCommandSubList add=bashSpecialVariables,bashStatement
@@ -491,7 +501,11 @@ if !exists("g:sh_no_error")
syn match shDerefWordError "[^}$[~]" contained
endif
syn match shDerefSimple "\$\%(\h\w*\|\d\)" nextgroup=@shNoZSList
-syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart
+if exists("b:is_kornshell")
+ syn region shDeref matchgroup=PreProc start="\${\ze[^ \t\n<|]" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart
+else
+ syn region shDeref matchgroup=PreProc start="\${" end="}" contains=@shDerefList,shDerefVarArray nextgroup=shSpecialStart
+endif
syn match shDerefSimple "\$[-#*@!?]" nextgroup=@shNoZSList
syn match shDerefSimple "\$\$" nextgroup=@shNoZSList
syn match shDerefSimple "\${\d}" nextgroup=@shNoZSList nextgroup=shSpecialStart
@@ -620,7 +634,7 @@ elseif exists("b:is_bash")
syn keyword shStatement bg builtin disown export false fg getopts jobs let printf sleep true unalias
syn keyword shStatement typeset nextgroup=shSetOption
syn keyword shStatement fc hash history source suspend times type
- syn keyword shStatement bind builtin caller compopt declare dirs disown enable export help logout mapfile popd pushd readarray shopt source typeset
+ syn keyword shStatement bind builtin caller compopt declare dirs disown enable export help logout local mapfile popd pushd readarray shopt source typeset
else
syn keyword shStatement login newgrp
endif
@@ -754,6 +768,8 @@ if !exists("skip_sh_syntax_inits")
hi def link shSnglCase Statement
hi def link shCommandSub Special
hi def link shCommandSubBQ shCommandSub
+ hi def link shSubshare shCommandSub
+ hi def link shValsub shCommandSub
hi def link shComment Comment
hi def link shConditional Conditional
hi def link shCtrlSeq Special
diff --git a/runtime/syntax/shared/debversions.vim b/runtime/syntax/shared/debversions.vim
index 6c944cd4e1..4aec246e27 100644
--- a/runtime/syntax/shared/debversions.vim
+++ b/runtime/syntax/shared/debversions.vim
@@ -1,7 +1,7 @@
" Vim syntax file
" Language: Debian version information
" Maintainer: Debian Vim Maintainers
-" Last Change: 2023 Nov 01
+" Last Change: 2024 Jan 25
" URL: https://salsa.debian.org/vim-team/vim-debian/blob/main/syntax/shared/debversions.vim
let s:cpo = &cpo
@@ -11,7 +11,7 @@ let g:debSharedSupportedVersions = [
\ 'oldstable', 'stable', 'testing', 'unstable', 'experimental', 'sid', 'rc-buggy',
\ 'bullseye', 'bookworm', 'trixie', 'forky',
\
- \ 'trusty', 'xenial', 'bionic', 'focal', 'jammy', 'lunar', 'mantic', 'noble',
+ \ 'trusty', 'xenial', 'bionic', 'focal', 'jammy', 'mantic', 'noble',
\ 'devel'
\ ]
let g:debSharedUnsupportedVersions = [
@@ -23,7 +23,7 @@ let g:debSharedUnsupportedVersions = [
\ 'gutsy', 'hardy', 'intrepid', 'jaunty', 'karmic', 'lucid',
\ 'maverick', 'natty', 'oneiric', 'precise', 'quantal', 'raring', 'saucy',
\ 'utopic', 'vivid', 'wily', 'yakkety', 'zesty', 'artful', 'cosmic',
- \ 'disco', 'eoan', 'hirsute', 'impish', 'kinetic', 'groovy'
+ \ 'disco', 'eoan', 'hirsute', 'impish', 'kinetic', 'lunar', 'groovy'
\ ]
let &cpo=s:cpo
diff --git a/runtime/syntax/sm.vim b/runtime/syntax/sm.vim
index a16575c519..13a5bf117e 100644
--- a/runtime/syntax/sm.vim
+++ b/runtime/syntax/sm.vim
@@ -1,9 +1,11 @@
" Vim syntax file
" Language: sendmail
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Oct 25, 2016
+" 2024 Feb 19 by Vim Project (announce adoption)
" Version: 9
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SM
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_SM
if exists("b:current_syntax")
finish
endif
diff --git a/runtime/syntax/spec.vim b/runtime/syntax/spec.vim
index aed04bc900..12ce8d5ac1 100644
--- a/runtime/syntax/spec.vim
+++ b/runtime/syntax/spec.vim
@@ -102,7 +102,7 @@ syn case ignore
"%% PreAmble Section %%
"Copyright and Serial were deprecated by License and Epoch
syn region specPreAmbleDeprecated oneline matchgroup=specError start='^\(Copyright\|Serial\)' end='$' contains=specEmail,specURL,specURLMacro,specLicense,specColon,specVariables,specSpecialChar,specMacroIdentifier
-syn region specPreAmble oneline matchgroup=specCommand start='^\(Prereq\|Summary\|Name\|Version\|Packager\|Requires\|Recommends\|Suggests\|Supplements\|Enhances\|Icon\|URL\|Source\d*\|Patch\d*\|Prefix\|Packager\|Group\|License\|Release\|BuildRoot\|Distribution\|Vendor\|Provides\|ExclusiveArch\|ExcludeArch\|ExclusiveOS\|Obsoletes\|BuildArch\|BuildArchitectures\|BuildRequires\|BuildConflicts\|BuildPreReq\|Conflicts\|AutoRequires\|AutoReq\|AutoReqProv\|AutoProv\|Epoch\)' end='$' contains=specEmail,specURL,specURLMacro,specLicense,specColon,specVariables,specSpecialChar,specMacroIdentifier
+syn region specPreAmble oneline matchgroup=specCommand start='^\(Prereq\|Summary\|Name\|Version\|Packager\|Requires\|Recommends\|Suggests\|Supplements\|Enhances\|Icon\|URL\|SourceLicense\|Source\d*\|Patch\d*\|Prefix\|Packager\|Group\|License\|Release\|BuildRoot\|Distribution\|Vendor\|Provides\|ExclusiveArch\|ExcludeArch\|ExclusiveOS\|Obsoletes\|BuildArch\|BuildArchitectures\|BuildRequires\|BuildConflicts\|BuildPreReq\|Conflicts\|AutoRequires\|AutoReq\|AutoReqProv\|AutoProv\|Epoch\)' end='$' contains=specEmail,specURL,specURLMacro,specLicense,specColon,specVariables,specSpecialChar,specMacroIdentifier
"%% Description Section %%
syn region specDescriptionArea matchgroup=specSection start='^%description' end='^%'me=e-1 contains=specDescriptionOpts,specEmail,specURL,specNumber,specMacroIdentifier,specComment
diff --git a/runtime/syntax/squirrel.vim b/runtime/syntax/squirrel.vim
index 81d59cc986..85bdd87d9e 100644
--- a/runtime/syntax/squirrel.vim
+++ b/runtime/syntax/squirrel.vim
@@ -2,7 +2,7 @@
" Language: squirrel
" Current Maintainer: Matt Dunford (zenmatic@gmail.com)
" URL: https://github.com/zenmatic/vim-syntax-squirrel
-" Last Change: 2021 Nov 28
+" Last Change: 2023 Dec 08
" http://squirrel-lang.org/
@@ -17,6 +17,7 @@ let b:filetype_in_cpp_family = 1
" Read the C syntax to start with
runtime! syntax/c.vim
unlet b:current_syntax
+unlet b:filetype_in_cpp_family
" squirrel extensions
syn keyword squirrelStatement delete this in yield resume base clone
diff --git a/runtime/syntax/swayconfig.vim b/runtime/syntax/swayconfig.vim
index 7b1c889d6d..69fe26d370 100644
--- a/runtime/syntax/swayconfig.vim
+++ b/runtime/syntax/swayconfig.vim
@@ -2,8 +2,8 @@
" Language: sway config file
" Original Author: Josef Litos (JosefLitos/i3config.vim)
" Maintainer: James Eapen <james.eapen@vai.org>
-" Version: 1.0.0
-" Last Change: 2023-09-14
+" Version: 1.0.2
+" Last Change: 2023-12-28
" References:
" http://i3wm.org/docs/userguide.html#configuring
@@ -43,6 +43,12 @@ syn region swayConfigExecBlock start=/exec\(_always\)\? {/ end=/^}$/ contains=i3
syn keyword swayConfigFloatingModifierOpts normal inverse contained
syn match i3ConfigKeyword /^floating_modifier [$a-zA-Z0-9+]\+ \(normal\|inverse\)$/ contains=i3ConfigVariable,i3ConfigBindModkey,swayConfigFloatingModifierOpts
+syn keyword swayConfigSmartGapsOpts toggle contained
+syn match i3ConfigKeyword /^smart_gaps toggle$/ contains=i3ConfigSmartGapOpts,i3ConfigBoolean,swayConfigSmartGapsOpts
+
+syn keyword swayConfigFocusFollowsMouseOpts always contained
+syn match i3ConfigKeyword /^focus_follows_mouse always$/ contains=i3ConfigBoolean,swayConfigFocusFollowsMouseOpts
+
syn match i3ConfigKeyword /^hide_edge_borders --i3 \w*$/ contains=i3ConfigEdgeKeyword,i3ConfigShParam
syn keyword i3ConfigBarOpts swaybar_command gaps height pango_markup status_edge_padding status_padding wrap_scroll tray_bindcode tray_bindsym icon_theme contained
@@ -118,7 +124,9 @@ syn region swayConfigOutput start=/^output/ skip=/\\$/ end=/$/ contains=swayCon
syn region swayConfigOutput start=/^output .* {$/ end=/}$/ contains=swayConfigOutputKeyword,swayConfigOutputMode,swayConfigOutputOpts,swayConfigOutputOptVals,i3ConfigVariable,i3ConfigNumber,i3ConfigString,i3ConfigColor,i3ConfigBoolean,swayConfigDeviceOps,i3ConfigParen keepend extend
" Define the highlighting.
+hi def link swayConfigSmartGapsOpts i3ConfigOption
hi def link swayConfigFloatingModifierOpts i3ConfigOption
+hi def link swayConfigFocusFollowsMouseOpts i3ConfigOption
hi def link swayConfigBindKeyword i3ConfigBindKeyword
hi def link swayConfigXOpt i3ConfigOption
hi def link swayConfigInhibitKeyword i3ConfigCommand
diff --git a/runtime/syntax/tags.vim b/runtime/syntax/tags.vim
index 4c06dc1df8..e87e3fcf61 100644
--- a/runtime/syntax/tags.vim
+++ b/runtime/syntax/tags.vim
@@ -1,8 +1,10 @@
" Language: tags
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Oct 26, 2016
+" 2024 Feb 19 by Vim Project (announce adoption)
" Version: 8
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TAGS
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TAGS
" quit when a syntax file was already loaded
if exists("b:current_syntax")
diff --git a/runtime/syntax/tex.vim b/runtime/syntax/tex.vim
index 5544fb63fc..d782bd4845 100644
--- a/runtime/syntax/tex.vim
+++ b/runtime/syntax/tex.vim
@@ -1,9 +1,11 @@
" Vim syntax file
" Language: TeX
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Apr 22, 2022
+" 2024 Feb 19 by Vim Project (announce adoption)
" Version: 121
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TEX
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_TEX
"
" Notes: {{{1
"
diff --git a/runtime/syntax/tmux.vim b/runtime/syntax/tmux.vim
index 042b96e872..9766ed55d7 100644
--- a/runtime/syntax/tmux.vim
+++ b/runtime/syntax/tmux.vim
@@ -1,5 +1,5 @@
" Language: tmux(1) configuration file
-" Version: 3.3-rc (git-964deae4)
+" Version: 3.4 (git-608d1134)
" URL: https://github.com/ericpruitt/tmux.vim/
" Maintainer: Eric Pruitt <eric.pruitt@gmail.com>
" License: 2-Clause BSD (http://opensource.org/licenses/BSD-2-Clause)
@@ -17,8 +17,9 @@ let b:current_syntax = "tmux"
syntax iskeyword @,48-57,_,192-255,-
syntax case match
-syn keyword tmuxAction none any current other
-syn keyword tmuxBoolean off on yes no
+" The values "yes" and "no" are synonyms for "on" and "off", so they do not
+" appear in the option table file.
+syn keyword tmuxEnums yes no
syn keyword tmuxTodo FIXME NOTE TODO XXX contained
@@ -27,12 +28,20 @@ syn match tmuxKey /\(C-\|M-\|\^\)\+\S\+/ display
syn match tmuxNumber /\<\d\+\>/ display
syn match tmuxFlags /\s-\a\+/ display
syn match tmuxVariableExpansion /\$\({[A-Za-z_]\w*}\|[A-Za-z_]\w*\)/ display
-syn match tmuxControl /^\s*%\(if\|elif\|else\|endif\)\>/
+syn match tmuxControl /\(^\|\s\)%\(if\|elif\|else\|endif\)\($\|\s\)/ display
syn match tmuxEscape /\\\(u\x\{4\}\|U\x\{8\}\|\o\{3\}\|[\\ernt$]\)/ display
+" Missing closing bracket.
+syn match tmuxInvalidVariableExpansion /\${[^}]*$/ display
+" Starts with invalid character.
+syn match tmuxInvalidVariableExpansion /\${[^A-Za-z_][^}]*}/ display
+syn match tmuxInvalidVariableExpansion /\$[^A-Za-z_{ \t]/ display
+" Contains invalid character.
+syn match tmuxInvalidVariableExpansion /\${[^}]*[^A-Za-z0-9_][^}]*}/ display
+
syn region tmuxComment start=/#/ skip=/\\\@<!\\$/ end=/$/ contains=tmuxTodo,@Spell
-syn region tmuxString start=+"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=tmuxFormatString,tmuxEscape,tmuxVariableExpansion,@Spell
+syn region tmuxString start=+"+ skip=+\\\\\|\\"\|\\$+ excludenl end=+"+ end='$' contains=tmuxFormatString,tmuxEscape,tmuxVariableExpansion,tmuxInvalidVariableExpansion,@Spell
syn region tmuxUninterpolatedString start=+'+ skip=+\\$+ excludenl end=+'+ end='$' contains=tmuxFormatString,@Spell
" TODO: Figure out how escaping works inside of #(...) and #{...} blocks.
@@ -43,7 +52,7 @@ syn region tmuxFormatString start=/#(/ skip=/#(.\{-})/ end=/)/ contained keepend
" At the time of this writing, the latest tmux release will parse a line
" reading "abc=xyz set-option ..." as an assignment followed by a command
" hence the presence of "\s" in the "end" argument.
-syn region tmuxAssignment matchgroup=tmuxVariable start=/^\s*[A-Za-z_]\w*=\@=/ skip=/\\$\|\\\s/ end=/\s\|$/ contains=tmuxString,tmuxUninterpolatedString,tmuxVariableExpansion,tmuxControl,tmuxEscape
+syn region tmuxAssignment matchgroup=tmuxVariable start=/^\s*[A-Za-z_]\w*=\@=/ skip=/\\$\|\\\s/ end=/\s\|$/ contains=tmuxString,tmuxUninterpolatedString,tmuxVariableExpansion,tmuxControl,tmuxEscape,tmuxInvalidVariableExpansion
hi def link tmuxFormatString Identifier
hi def link tmuxAction Boolean
@@ -51,8 +60,11 @@ hi def link tmuxBoolean Boolean
hi def link tmuxCommands Keyword
hi def link tmuxControl PreCondit
hi def link tmuxComment Comment
+hi def link tmuxEnums Boolean
hi def link tmuxEscape Special
hi def link tmuxEscapeUnquoted Special
+hi def link tmuxInvalidVariableExpansion
+\ Error
hi def link tmuxKey Special
hi def link tmuxNumber Number
hi def link tmuxFlags Identifier
@@ -77,78 +89,84 @@ endif
syn keyword tmuxOptions
\ activity-action after-bind-key after-capture-pane after-copy-mode
-\ after-display-message after-display-panes after-kill-pane
-\ after-list-buffers after-list-clients after-list-keys after-list-panes
-\ after-list-sessions after-list-windows after-load-buffer after-lock-server
-\ after-new-session after-new-window after-paste-buffer after-pipe-pane
-\ after-queue after-refresh-client after-rename-session after-rename-window
-\ after-resize-pane after-resize-window after-save-buffer
-\ after-select-layout after-select-pane after-select-window after-send-keys
-\ after-set-buffer after-set-environment after-set-hook after-set-option
-\ after-show-environment after-show-messages after-show-options
-\ after-split-window after-unbind-key aggressive-resize alert-activity
-\ alert-bell alert-silence allow-passthrough allow-rename alternate-screen
-\ assume-paste-time automatic-rename automatic-rename-format backspace
-\ base-index bell-action buffer-limit client-active client-attached
-\ client-detached client-focus-in client-focus-out client-resized
-\ client-session-changed clock-mode-colour clock-mode-style command-alias
-\ copy-command copy-mode-current-match-style copy-mode-mark-style
-\ copy-mode-match-style cursor-colour cursor-style default-command
-\ default-shell default-size default-terminal destroy-unattached
-\ detach-on-destroy display-panes-active-colour display-panes-colour
-\ display-panes-time display-time editor escape-time exit-empty
-\ exit-unattached extended-keys fill-character focus-events history-file
-\ history-limit key-table lock-after-time lock-command main-pane-height
-\ main-pane-width message-command-style message-limit message-style
-\ mode-keys mode-style monitor-activity monitor-bell monitor-silence mouse
-\ other-pane-height other-pane-width pane-active-border-style
-\ pane-base-index pane-border-format pane-border-indicators
-\ pane-border-lines pane-border-status pane-border-style pane-colours
-\ pane-died pane-exited pane-focus-in pane-focus-out pane-mode-changed
-\ pane-set-clipboard pane-title-changed popup-border-lines
+\ after-display-message after-display-panes after-kill-pane after-list-buffers
+\ after-list-clients after-list-keys after-list-panes after-list-sessions
+\ after-list-windows after-load-buffer after-lock-server after-new-session
+\ after-new-window after-paste-buffer after-pipe-pane after-queue
+\ after-refresh-client after-rename-session after-rename-window
+\ after-resize-pane after-resize-window after-save-buffer after-select-layout
+\ after-select-pane after-select-window after-send-keys after-set-buffer
+\ after-set-environment after-set-hook after-set-option after-show-environment
+\ after-show-messages after-show-options after-split-window after-unbind-key
+\ aggressive-resize alert-activity alert-bell alert-silence allow-passthrough
+\ allow-rename alternate-screen assume-paste-time automatic-rename
+\ automatic-rename-format backspace base-index bell-action buffer-limit
+\ client-active client-attached client-detached client-focus-in
+\ client-focus-out client-resized client-session-changed clock-mode-color
+\ clock-mode-colour clock-mode-style command-alias copy-command
+\ copy-mode-current-match-style copy-mode-mark-style copy-mode-match-style
+\ cursor-color cursor-colour cursor-style default-command default-shell
+\ default-size default-terminal destroy-unattached detach-on-destroy
+\ display-panes-active-color display-panes-active-colour display-panes-color
+\ display-panes-colour display-panes-time display-time editor escape-time
+\ exit-empty exit-unattached extended-keys fill-character focus-events
+\ history-file history-limit key-table lock-after-time lock-command
+\ main-pane-height main-pane-width menu-border-lines menu-border-style
+\ menu-selected-style menu-style message-command-style message-limit
+\ message-line message-style mode-keys mode-style monitor-activity monitor-bell
+\ monitor-silence mouse other-pane-height other-pane-width
+\ pane-active-border-style pane-base-index pane-border-format
+\ pane-border-indicators pane-border-lines pane-border-status pane-border-style
+\ pane-colors pane-colours pane-died pane-exited pane-focus-in pane-focus-out
+\ pane-mode-changed pane-set-clipboard pane-title-changed popup-border-lines
\ popup-border-style popup-style prefix prefix2 prompt-history-limit
\ remain-on-exit remain-on-exit-format renumber-windows repeat-time
\ scroll-on-clear session-closed session-created session-renamed
\ session-window-changed set-clipboard set-titles set-titles-string
\ silence-action status status-bg status-fg status-format status-interval
-\ status-justify status-keys status-left status-left-length
-\ status-left-style status-position status-right status-right-length
-\ status-right-style status-style synchronize-panes terminal-features
-\ terminal-overrides update-environment user-keys visual-activity
-\ visual-bell visual-silence window-active-style window-layout-changed
-\ window-linked window-pane-changed window-renamed window-resized
-\ window-size window-status-activity-style window-status-bell-style
-\ window-status-current-format window-status-current-style
-\ window-status-format window-status-last-style window-status-separator
-\ window-status-style window-style window-unlinked word-separators
-\ wrap-search xterm-keys
+\ status-justify status-keys status-left status-left-length status-left-style
+\ status-position status-right status-right-length status-right-style
+\ status-style synchronize-panes terminal-features terminal-overrides
+\ update-environment user-keys visual-activity visual-bell visual-silence
+\ window-active-style window-layout-changed window-linked window-pane-changed
+\ window-renamed window-resized window-size window-status-activity-style
+\ window-status-bell-style window-status-current-format
+\ window-status-current-style window-status-format window-status-last-style
+\ window-status-separator window-status-style window-style window-unlinked
+\ word-separators wrap-search xterm-keys
syn keyword tmuxCommands
-\ attach attach-session bind bind-key break-pane breakp capture-pane
-\ capturep choose-buffer choose-client choose-session choose-tree
-\ choose-window clear-history clear-prompt-history clearhist clearphist
-\ clock-mode command-prompt confirm confirm-before copy-mode customize-mode
-\ delete-buffer deleteb detach detach-client display display-menu
-\ display-message display-panes display-popup displayp find-window findw has
-\ has-session if if-shell info join-pane joinp kill-pane kill-server
-\ kill-session kill-window killp killw last last-pane last-window lastp
-\ link-window linkw list-buffers list-clients list-commands list-keys
-\ list-panes list-sessions list-windows load-buffer loadb lock lock-client
-\ lock-server lock-session lockc locks ls lsb lsc lscm lsk lsp lsw menu
-\ move-pane move-window movep movew new new-session new-window neww next
-\ next-layout next-window nextl paste-buffer pasteb pipe-pane pipep popup
-\ prev previous-layout previous-window prevl refresh refresh-client rename
-\ rename-session rename-window renamew resize-pane resize-window resizep
-\ resizew respawn-pane respawn-window respawnp respawnw rotate-window
-\ rotatew run run-shell save-buffer saveb select-layout select-pane
-\ select-window selectl selectp selectw send send-keys send-prefix
-\ server-info set set-buffer set-environment set-hook set-option
-\ set-window-option setb setenv setw show show-buffer show-environment
-\ show-hooks show-messages show-options show-prompt-history
-\ show-window-options showb showenv showmsgs showphist showw source
-\ source-file split-pane split-window splitp splitw start start-server
-\ suspend-client suspendc swap-pane swap-window swapp swapw switch-client
-\ switchc unbind unbind-key unlink-window unlinkw wait wait-for
+\ attach attach-session bind bind-key break-pane breakp capture-pane capturep
+\ choose-buffer choose-client choose-session choose-tree choose-window
+\ clear-history clear-prompt-history clearhist clearphist clock-mode
+\ command-prompt confirm confirm-before copy-mode customize-mode delete-buffer
+\ deleteb detach detach-client display display-menu display-message
+\ display-panes display-popup displayp find-window findw has has-session if
+\ if-shell info join-pane joinp kill-pane kill-server kill-session kill-window
+\ killp killw last last-pane last-window lastp link-window linkw list-buffers
+\ list-clients list-commands list-keys list-panes list-sessions list-windows
+\ load-buffer loadb lock lock-client lock-server lock-session lockc locks ls
+\ lsb lsc lscm lsk lsp lsw menu move-pane move-window movep movew new
+\ new-session new-window neww next next-layout next-window nextl paste-buffer
+\ pasteb pipe-pane pipep popup prev previous-layout previous-window prevl
+\ refresh refresh-client rename rename-session rename-window renamew
+\ resize-pane resize-window resizep resizew respawn-pane respawn-window
+\ respawnp respawnw rotate-window rotatew run run-shell save-buffer saveb
+\ select-layout select-pane select-window selectl selectp selectw send
+\ send-keys send-prefix server-access server-info set set-buffer
+\ set-environment set-hook set-option set-window-option setb setenv setw show
+\ show-buffer show-environment show-hooks show-messages show-options
+\ show-prompt-history show-window-options showb showenv showmsgs showphist
+\ showw source source-file split-pane split-window splitp splitw start
+\ start-server suspend-client suspendc swap-pane swap-window swapp swapw
+\ switch-client switchc unbind unbind-key unlink-window unlinkw wait wait-for
+
+syn keyword tmuxEnums
+\ absolute-centre all always any arrows bar blinking-bar blinking-block
+\ blinking-underline block both bottom centre color colour current default
+\ double emacs external failed heavy keep-group keep-last largest latest left
+\ manual next no-detached none number off on other padded previous right
+\ rounded simple single smallest top underline vi
let &cpo = s:original_cpo
unlet! s:original_cpo s:bg s:i
diff --git a/runtime/syntax/vim.vim b/runtime/syntax/vim.vim
index fcd50bccd2..2857146949 100644
--- a/runtime/syntax/vim.vim
+++ b/runtime/syntax/vim.vim
@@ -23,7 +23,7 @@ syn cluster vimCommentGroup contains=vimTodo,@Spell
" Special and plugin vim commands {{{2
syn match vimCommand contained "\<z[-+^.=]\=\>"
syn keyword vimOnlyCommand contained fix[del] op[en] sh[ell] P[rint]
-syn keyword vimStdPlugin contained Arguments Asm Break Cfilter Clear Continue DiffOrig Evaluate Finish Gdb Lfilter Man N[ext] Over P[rint] Program Run S Source Step Stop Termdebug TermdebugCommand TOhtml Until Winbar XMLent XMLns
+syn keyword vimStdPlugin contained Arguments Asm Break Cfilter Clear Continue DiffOrig Evaluate Finish Gdb Lfilter Man Over Program Run S Source Step Stop Termdebug TermdebugCommand TOhtml Until Winbar XMLent XMLns
" Vim-specific options {{{2
syn keyword vimOnlyOption contained biosk bioskey cp compatible consk conskey cm cryptmethod edcompatible guipty key macatsui mzq mzquantum osfiletype oft renderoptions rop st shelltype sn shortname tenc termencoding ta textauto tx textmode tf ttyfast ttym ttymouse tbi ttybuiltin wiv weirdinvert
@@ -34,8 +34,10 @@ syn keyword vimOnlyOption contained nobiosk nobioskey noconsk noconskey nocp noc
" Invertible setting variants
syn keyword vimOnlyOption contained invbiosk invbioskey invconsk invconskey invcp invcompatible invguipty invmacatsui invsn invshortname invta invtextauto invtx invtextmode invtf invttyfast invtbi invttybuiltin invwiv invweirdinvert
" termcap codes (which can also be set) {{{2
-syn keyword vimTermOption contained t_8b t_AB t_al t_bc t_ce t_cl t_Co t_Cs t_CV t_db t_DL t_Ds t_F1 t_F2 t_F3 t_F4 t_F5 t_F6 t_F7 t_F8 t_F9 t_fs t_IE t_IS t_k1 t_K1 t_k2 t_k3 t_K3 t_k4 t_K4 t_k5 t_K5 t_k6 t_K6 t_k7 t_K7 t_k8 t_K8 t_k9 t_K9 t_KA t_kb t_kB t_KB t_KC t_kd t_kD t_KD t_ke t_KE t_KF t_KG t_KH t_KI t_KJ t_KK t_kl t_KL t_kN t_kP t_kr t_ks t_ku t_le t_mb t_md t_me t_mr t_ms t_nd t_op t_RB t_RI t_RV t_Sb t_se t_Sf t_SI t_so t_sr t_SR t_te t_ti t_ts t_u7 t_ue t_us t_Us t_ut t_vb t_ve t_vi t_vs t_WP t_WS t_xn t_xs t_ZH t_ZR
-syn keyword vimTermOption contained t_8f t_AF t_AL t_cd t_Ce t_cm t_cs t_CS t_da t_dl t_ds t_EI t_kh t_kI
+" GEN_SYN_VIM: vimOption term output code, START_STR='syn keyword vimOption contained', END_STR=''
+syn keyword vimOption contained t_AB t_AF t_AU t_AL t_al t_bc t_BE t_BD t_cd t_ce t_Ce t_CF t_cl t_cm t_Co t_CS t_Cs t_cs t_CV t_da t_db t_DL t_dl t_ds t_Ds t_EC t_EI t_fs t_fd t_fe t_GP t_IE t_IS t_ke t_ks t_le t_mb t_md t_me t_mr t_ms t_nd t_op t_RF t_RB t_RC t_RI t_Ri t_RK t_RS t_RT t_RV t_Sb t_SC t_se t_Sf t_SH t_SI t_Si t_so t_SR t_sr t_ST t_Te t_te t_TE t_ti t_TI t_Ts t_ts t_u7 t_ue t_us t_Us t_ut t_vb t_ve t_vi t_VS t_vs t_WP t_WS t_XM t_xn t_xs t_ZH t_ZR t_8f t_8b t_8u
+" term key codes
+syn keyword vimOption contained t_F1 t_F2 t_F3 t_F4 t_F5 t_F6 t_F7 t_F8 t_F9 t_k1 t_K1 t_k2 t_k3 t_K3 t_k4 t_K4 t_k5 t_K5 t_k6 t_K6 t_k7 t_K7 t_k8 t_K8 t_k9 t_K9 t_KA t_kb t_kB t_KB t_KC t_kd t_kD t_KD t_KE t_KF t_KG t_kh t_KH t_kI t_KI t_KJ t_KK t_kl t_KL t_kN t_kP t_kr t_ku
syn match vimTermOption contained "t_%1"
syn match vimTermOption contained "t_#2"
syn match vimTermOption contained "t_#4"
@@ -46,19 +48,22 @@ syn match vimTermOption contained "t_%i"
syn match vimTermOption contained "t_k;"
" unsupported settings: these are supported by vi but don't do anything in vim {{{2
-syn keyword vimErrSetting contained hardtabs ht w1200 w300 w9600
+" GEN_SYN_VIM: Missing vimOption, START_STR='syn keyword vimErrSetting contained', END_STR=''
+syn keyword vimErrSetting contained akm altkeymap anti antialias ap autoprint bf beautify biosk bioskey consk conskey fk fkmap fl flash gr graphic ht hardtabs macatsui mesg novice open opt optimize oft osfiletype redraw slow slowopen sourceany w1200 w300 w9600
+syn keyword vimErrSetting contained noakm noaltkeymap noanti noantialias noap noautoprint nobf nobeautify nobiosk nobioskey noconsk noconskey nofk nofkmap nofl noflash nogr nographic nomacatsui nomesg nonovice noopen noopt nooptimize noredraw noslow noslowopen nosourceany
+syn keyword vimErrSetting contained invakm invaltkeymap invanti invantialias invap invautoprint invbf invbeautify invbiosk invbioskey invconsk invconskey invfk invfkmap invfl invflash invgr invgraphic invmacatsui invmesg invnovice invopen invopt invoptimize invredraw invslow invslowopen invsourceany
"}}}2
syn case ignore
" Highlight commonly used Groupnames {{{2
syn keyword vimGroup contained Comment Constant String Character Number Boolean Float Identifier Function Statement Conditional Repeat Label Operator Keyword Exception PreProc Include Define Macro PreCondit Type StorageClass Structure Typedef Special SpecialChar Tag Delimiter SpecialComment Debug Underlined Ignore Error Todo
" Default highlighting groups {{{2
-syn keyword vimHLGroup contained ColorColumn Cursor CursorColumn CursorIM CursorLine CursorLineFold CursorLineNr CursorLineSign DiffAdd DiffChange DiffDelete DiffText Directory EndOfBuffer ErrorMsg FoldColumn Folded IncSearch LineNr MatchParen Menu MessageWindow ModeMsg MoreMsg NonText Normal Pmenu PmenuExtra PmenuExtraSel PmenuKind PmenuKindSel PmenuSbar PmenuSel PmenuThumb Question QuickFixLine Scrollbar Search SignColumn SpecialKey SpellBad SpellCap SpellLocal SpellRare StatusLine StatusLineNC TabLine TabLineFill TabLineSel Title Tooltip VertSplit Visual WarningMsg WildMenu
-syn match vimHLGroup contained "Conceal"
-syn keyword vimOnlyHLGroup contained LineNrAbove LineNrBelow StatusLineTerm Terminal VisualNOS
-syn keyword nvimHLGroup contained Substitute TermCursor TermCursorNC
+syn keyword vimHLGroup contained ErrorMsg IncSearch ModeMsg NonText StatusLine StatusLineNC EndOfBuffer VertSplit DiffText PmenuSbar TabLineSel TabLineFill Cursor lCursor QuickFixLine CursorLineSign CursorLineFold CurSearch PmenuKind PmenuKindSel PmenuExtra PmenuExtraSel Normal Directory LineNr CursorLineNr MoreMsg Question Search SpellBad SpellCap SpellRare SpellLocal PmenuThumb Pmenu PmenuSel SpecialKey Title WarningMsg WildMenu Folded FoldColumn SignColumn Visual DiffAdd DiffChange DiffDelete TabLine CursorColumn CursorLine ColorColumn Conceal MatchParen CursorIM LineNrAbove LineNrBelow
+syn keyword vimOnlyHLGroup contained Menu Scrollbar StatusLineTerm StatusLineTermNC ToolbarButton ToolbarLine Tooltip VisualNOS
+syn keyword nvimHLGroup contained FloatBorder FloatFooter FloatTitle MsgSeparator NormalFloat NormalNC Substitute TermCursor TermCursorNC VisualNC Whitespace WinBar WinBarNC WinSeparator
"}}}2
syn case match
+
" Special Vim Highlighting (not automatic) {{{1
" Set up folding commands for this syntax highlighting file {{{2
@@ -140,23 +145,28 @@ endif
" Numbers {{{2
" =======
-syn match vimNumber '\<\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '-\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '\<0[xX]\x\+' skipwhite nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '\%(^\|\A\)\zs#\x\{6}' skipwhite nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '\<0[zZ][a-zA-Z0-9.]\+' skipwhite nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '0[0-7]\+' skipwhite nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
-syn match vimNumber '0[bB][01]\+' skipwhite nextgroup=vimGlobal,vimSubst,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\<\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '-\d\+\%(\.\d\+\%([eE][+-]\=\d\+\)\=\)\=' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\<0[xX]\x\+' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\%(^\|\A\)\zs#\x\{6}' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '\<0[zZ][a-zA-Z0-9.]\+' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '0[0-7]\+' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
+syn match vimNumber '0[bB][01]\+' skipwhite nextgroup=vimGlobal,vimSubst1,vimCommand,vimComment,vim9Comment
" All vimCommands are contained by vimIsCommand. {{{2
-syn match vimCmdSep "[:|]\+" skipwhite nextgroup=vimAddress,vimAutoCmd,vimEcho,vimIsCommand,vimExtCmd,vimFilter,vimLet,vimMap,vimMark,vimSet,vimSyntax,vimUserCmd
-syn match vimIsCommand "\<\h\w*\>" contains=vimCommand
+syn cluster vimCmdList contains=vimAbb,vimAddress,vimAutoCmd,vimAugroup,vimBehave,vimEcho,vimEchoHL,vimExecute,vimIsCommand,vimExtCmd,vimFunction,vimGlobal,vimHighlight,vimLet,vimMap,vimMark,vimNotFunc,vimNorm,vimSet,vimSyntax,vimUnlet,vimUnmap,vimUserCmd
+syn match vimCmdSep "[:|]\+" skipwhite nextgroup=@vimCmdList,vimSubst1
+syn match vimIsCommand "\<\%(\h\w*\|[23]mat\%[ch]\)\>" contains=vimCommand
syn match vimVar contained "\<\h[a-zA-Z0-9#_]*\>"
syn match vimVar "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>"
-syn match vimVar "\s\zs&\a\+\>"
+syn match vimVar "\s\zs&\%([lg]:\)\=\a\+\>"
+syn match vimVar "\s\zs&t_\S[a-zA-Z0-9]\>"
+syn match vimVar "\s\zs&t_k;"
syn match vimFBVar contained "\<[bwglstav]:\h[a-zA-Z0-9#_]*\>"
syn keyword vimCommand contained in
+syn cluster vimExprList contains=vimEnvvar,vimFunc,vimFuncVar,vimNumber,vimOper,vimOperParen,vimLetRegister,vimString,vimVar
+
" Insertions And Appends: insert append {{{2
" (buftype != nofile test avoids having append, change, insert show up in the command window)
" =======================
@@ -168,11 +178,12 @@ endif
" Behave! {{{2
" =======
-syn match vimBehave "\<be\%[have]\>" skipwhite nextgroup=vimBehaveModel,vimBehaveError
-syn keyword vimBehaveModel contained mswin xterm
if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_nobehaveerror")
syn match vimBehaveError contained "[^ ]\+"
endif
+syn match vimBehave "\<be\%[have]\>" nextgroup=vimBehaveBang,vimBehaveModel,vimBehaveError skipwhite
+syn match vimBehaveBang contained "\a\@1<=!" nextgroup=vimBehaveModel skipwhite
+syn keyword vimBehaveModel contained mswin xterm
" Filetypes {{{2
" =========
@@ -185,22 +196,26 @@ syn keyword vimFTOption contained detect indent off on plugin
" Augroup : vimAugroupError removed because long augroups caused sync'ing problems. {{{2
" ======= : Trade-off: Increasing synclines with slower editing vs augroup END error checking.
-syn cluster vimAugroupList contains=vimAugroup,vimIsCommand,vimUserCmd,vimExecute,vimNotFunc,vimFuncName,vimFunction,vimFunctionError,vimLineComment,vimNotFunc,vimMap,vimSpecFile,vimOper,vimNumber,vimOperParen,vimComment,vim9Comment,vimString,vimSubst,vimMark,vimRegister,vimAddress,vimFilter,vimCmplxRepeat,vimComment,vim9Comment,vimLet,vimSet,vimAutoCmd,vimRegion,vimSynLine,vimNotation,vimCtrlChar,vimFuncVar,vimContinue,vimSetEqual,vimOption
+syn cluster vimAugroupList contains=@vimCmdList,vimFilter,vimFunc,vimLineComment,vimSpecFile,vimOper,vimNumber,vimOperParen,vimComment,vim9Comment,vimString,vimSubst,vimRegister,vimCmplxRepeat,vimRegion,vimNotation,vimCtrlChar,vimFuncVar,vimContinue
+syn match vimAugroup "\<aug\%[roup]\>" contains=vimAugroupKey,vimAugroupBang skipwhite nextgroup=vimAugroupBang,vimAutoCmdGroup
if exists("g:vimsyn_folding") && g:vimsyn_folding =~# 'a'
- syn region vimAugroup fold matchgroup=vimAugroupKey start="\<aug\%[roup]\>\ze\s\+\K\k*" end="\<aug\%[roup]\>\ze\s\+[eE][nN][dD]\>" contains=vimAutoCmd,@vimAugroupList
+ syn region vimAugroup fold start="\<aug\%[roup]\>\ze\s\+\%([eE][nN][dD]\)\@!\S\+" matchgroup=vimAugroupKey end="\<aug\%[roup]\>\ze\s\+[eE][nN][dD]\>" contains=vimAutoCmd,@vimAugroupList,vimAugroupkey skipwhite nextgroup=vimAugroupEnd
else
- syn region vimAugroup matchgroup=vimAugroupKey start="\<aug\%[roup]\>\ze\s\+\K\k*" end="\<aug\%[roup]\>\ze\s\+[eE][nN][dD]\>" contains=vimAutoCmd,@vimAugroupList
+ syn region vimAugroup start="\<aug\%[roup]\>\ze\s\+\%([eE][nN][dD]\)\@!\S\+" matchgroup=vimAugroupKey end="\<aug\%[roup]\>\ze\s\+[eE][nN][dD]\>" contains=vimAutoCmd,@vimAugroupList,vimAugroupkey skipwhite nextgroup=vimAugroupEnd
endif
-syn match vimAugroup "aug\%[roup]!" contains=vimAugroupKey
if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_noaugrouperror")
- syn match vimAugroupError "\<aug\%[roup]\>\s\+[eE][nN][dD]\>"
+ syn match vimAugroupError "\<aug\%[roup]\>\s\+[eE][nN][dD]\>"
endif
-syn keyword vimAugroupKey contained aug[roup]
+
+syn match vimAutoCmdGroup contained "\S\+"
+syn match vimAugroupEnd contained "\c\<END\>"
+syn match vimAugroupBang contained "\a\@1<=!" skipwhite nextgroup=vimAutoCmdGroup
+syn keyword vimAugroupKey contained aug[roup] skipwhite nextgroup=vimAugroupBang,vimAutoCmdGroup,vimAugroupEnd
" Operators: {{{2
" =========
-syn cluster vimOperGroup contains=vimEnvvar,vimFunc,vimFuncVar,vimOper,vimOperParen,vimNumber,vimString,vimType,vimRegister,vimContinue,vim9Comment,vimVar
-syn match vimOper "||\|&&\|[-+.!]" skipwhite nextgroup=vimString,vimSpecFile
+syn cluster vimOperGroup contains=vimEnvvar,vimFunc,vimFuncVar,vimOper,vimOperParen,vimNumber,vimString,vimType,vimRegister,@vimContinue,vim9Comment,vimVar
+syn match vimOper "||\|&&\|[-+*/%.!]" skipwhite nextgroup=vimString,vimSpecFile
syn match vimOper "\%#=1\(==\|!=\|>=\|<=\|=\~\|!\~\|>\|<\|=\|!\~#\)[?#]\{0,2}" skipwhite nextgroup=vimString,vimSpecFile
syn match vimOper "\(\<is\|\<isnot\)[?#]\{0,2}\>" skipwhite nextgroup=vimString,vimSpecFile
syn region vimOperParen matchgroup=vimParenSep start="(" end=")" contains=vimoperStar,@vimOperGroup
@@ -212,9 +227,9 @@ endif
" Functions : Tag is provided for those who wish to highlight tagged functions {{{2
" =========
syn cluster vimFuncList contains=vimCommand,vimFunctionError,vimFuncKey,Tag,vimFuncSID
-syn cluster vimFuncBodyList contains=vimAbb,vimAddress,vimAugroupKey,vimAutoCmd,vimCmplxRepeat,vimComment,vim9Comment,vimContinue,vimCtrlChar,vimEcho,vimEchoHL,vimEnvvar,vimExecute,vimIsCommand,vimFBVar,vimFunc,vimFunction,vimFuncVar,vimGlobal,vimHighlight,vimIsCommand,vimLet,vimLetHereDoc,vimLineComment,vimMap,vimMark,vimNorm,vimNotation,vimNotFunc,vimNumber,vimOper,vimOperParen,vimRegion,vimRegister,vimSearch,vimSet,vimSpecFile,vimString,vimSubst,vimSynLine,vimUnmap,vimUserCommand
+syn cluster vimFuncBodyList contains=@vimCmdList,vimCmplxRepeat,vimComment,vim9Comment,vimContinue,vimCtrlChar,vimEnvvar,vimFBVar,vimFunc,vimFunction,vimFuncVar,vimLetHereDoc,vimLineComment,vimNotation,vimNotFunc,vimNumber,vimOper,vimOperParen,vimRegion,vimRegister,vimSearch,vimSpecFile,vimString,vimSubst
syn match vimFunction "\<\(fu\%[nction]\)!\=\s\+\%(<[sS][iI][dD]>\|[sSgGbBwWtTlL]:\)\=\%(\i\|[#.]\|{.\{-1,}}\)*\ze\s*(" contains=@vimFuncList nextgroup=vimFuncBody
- syn match vimFunction "\<def!\=\ze\s*(" contains=@vimFuncList nextgroup=vimFuncBody
+syn match vimFunction "\<def!\=\ze\s*(" contains=@vimFuncList nextgroup=vimFuncBody
if exists("g:vimsyn_folding") && g:vimsyn_folding =~# 'f'
syn region vimFuncBody contained fold start="\ze\s*(" matchgroup=vimCommand end="\<\(endf\>\|endfu\%[nction]\>\|enddef\>\)" contains=@vimFuncBodyList
@@ -229,21 +244,34 @@ syn match vimFuncBlank contained "\s\+"
syn keyword vimPattern contained start skip end
" vimTypes : new for vim9
- syn match vimType ":\s*\zs\<\(bool\|number\|float\|string\|blob\|list<\|dict<\|job\|channel\|func\)\>"
+syn match vimType ":\s*\zs\<\(bool\|number\|float\|string\|blob\|list<\|dict<\|job\|channel\|func\)\>"
+
+" Keymaps: (Vim Project Addition) {{{2
+" =======
+
+" TODO: autogenerated vimCommand keyword list does not handle all abbreviations
+" : handle Vim9 script comments when something like #13104 is merged
+syn match vimKeymapStart "^" contained skipwhite nextgroup=vimKeymapLhs,vimKeymapLineComment
+syn match vimKeymapLhs "\S\+" contained skipwhite nextgroup=vimKeymapRhs contains=vimNotation
+syn match vimKeymapRhs "\S\+" contained skipwhite nextgroup=vimKeymapTailComment contains=vimNotation
+syn match vimKeymapTailComment "\S.*" contained
+syn match vimKeymapLineComment +".*+ contained contains=@vimCommentGroup,vimCommentString,vimCommentTitle
+
+syn region vimKeymap matchgroup=vimCommand start="\<loadk\%[eymap]\>" end="\%$" contains=vimKeymapStart
" Special Filenames, Modifiers, Extension Removal: {{{2
" ===============================================
-syn match vimSpecFile "<c\(word\|WORD\)>" nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "<\([acs]file\|amatch\|abuf\)>" nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "\s%[ \t:]"ms=s+1,me=e-1 nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "\s%$"ms=s+1 nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "\s%<"ms=s+1,me=e-1 nextgroup=vimSpecFileMod,vimSubst
-syn match vimSpecFile "#\d\+\|[#%]<\>" nextgroup=vimSpecFileMod,vimSubst
+syn match vimSpecFile "<c\(word\|WORD\)>" nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "<\([acs]file\|amatch\|abuf\)>" nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "\s%[ \t:]"ms=s+1,me=e-1 nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "\s%$"ms=s+1 nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "\s%<"ms=s+1,me=e-1 nextgroup=vimSpecFileMod,vimSubst1
+syn match vimSpecFile "#\d\+\|[#%]<\>" nextgroup=vimSpecFileMod,vimSubst1
syn match vimSpecFileMod "\(:[phtre]\)\+" contained
" User-Specified Commands: {{{2
" =======================
-syn cluster vimUserCmdList contains=vimAddress,vimSyntax,vimHighlight,vimAutoCmd,vimCmplxRepeat,vimComment,vim9Comment,vimCtrlChar,vimEscapeBrace,vimFunc,vimFuncName,vimFunction,vimFunctionError,vimIsCommand,vimMark,vimNotation,vimNumber,vimOper,vimRegion,vimRegister,vimLet,vimSet,vimSetEqual,vimSetString,vimSpecFile,vimString,vimSubst,vimSubstRep,vimSubstRange,vimSynLine
+syn cluster vimUserCmdList contains=@vimCmdList,vimCmplxRepeat,vimComment,vim9Comment,vimCtrlChar,vimEscapeBrace,vimFunc,vimNotation,vimNumber,vimOper,vimRegion,vimRegister,vimSpecFile,vimString,vimSubst,vimSubstRep,vimSubstRange
syn keyword vimUserCommand contained com[mand]
syn match vimUserCmd "\<com\%[mand]!\=\>.*$" contains=vimUserAttrb,vimUserAttrbError,vimUserCommand,@vimUserCmdList,vimComFilter
syn match vimUserAttrbError contained "-\a\+\ze\s"
@@ -260,9 +288,10 @@ if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_nousercmderror")
endif
syn case ignore
syn keyword vimUserAttrbKey contained bar ban[g] cou[nt] ra[nge] com[plete] n[args] re[gister]
-syn keyword vimUserAttrbCmplt contained augroup buffer behave color command compiler cscope dir environment event expression file file_in_path filetype function help highlight history locale mapping menu option packadd shellcmd sign syntax syntime tag tag_listfiles user var
+" GEN_SYN_VIM: vimUserAttrbCmplt, START_STR='syn keyword vimUserAttrbCmplt contained', END_STR=''
+syn keyword vimUserAttrbCmplt contained arglist augroup behave buffer color command compiler cscope diff_buffer dir environment event expression file file_in_path filetype function help highlight history keymap locale mapclear mapping menu messages syntax syntime option packadd runtime shellcmd sign tag tag_listfiles user var breakpoint scriptnames
syn keyword vimUserAttrbCmplt contained custom customlist nextgroup=vimUserAttrbCmpltFunc,vimUserCmdError
-syn match vimUserAttrbCmpltFunc contained ",\%([sS]:\|<[sS][iI][dD]>\)\=\%(\h\w*\%(#\h\w*\)\+\|\h\w*\)"hs=s+1 nextgroup=vimUserCmdError
+syn match vimUserAttrbCmpltFunc contained ",\%([sS]:\|<[sS][iI][dD]>\)\=\%(\h\w*\%([.#]\h\w*\)\+\|\h\w*\)"hs=s+1 nextgroup=vimUserCmdError
syn case match
syn match vimUserAttrbCmplt contained "custom,\u\w*"
@@ -299,45 +328,54 @@ syn match vimNotPatSep contained "\\\\"
syn cluster vimStringGroup contains=vimEscape,vimEscapeBrace,vimPatSep,vimNotPatSep,vimPatSepErr,vimPatSepZone,@Spell
syn region vimString oneline keepend start=+[^a-zA-Z>!\\@]"+lc=1 skip=+\\\\\|\\"+ matchgroup=vimStringEnd end=+"+ contains=@vimStringGroup
syn region vimString oneline keepend start=+[^a-zA-Z>!\\@]'+lc=1 end=+'+
-syn region vimString oneline start=+=!+lc=1 skip=+\\\\\|\\!+ end=+!+ contains=@vimStringGroup
-syn region vimString oneline start="=+"lc=1 skip="\\\\\|\\+" end="+" contains=@vimStringGroup
"syn region vimString oneline start="\s/\s*\A"lc=1 skip="\\\\\|\\+" end="/" contains=@vimStringGroup " see tst45.vim
syn match vimString contained +"[^"]*\\$+ skipnl nextgroup=vimStringCont
syn match vimStringCont contained +\(\\\\\|.\)\{-}[^\\]"+
syn match vimEscape contained "\\."
+" syn match vimEscape contained +\\[befnrt\"]+
+syn match vimEscape contained "\\\o\{1,3}\|\\[xX]\x\{1,2}\|\\u\x\{1,4}\|\\U\x\{1,8}"
+syn match vimEscape contained "\\<" contains=vimNotation
+syn match vimEscape contained "\\<\*[^>]*>\=>"
+
+syn region vimString oneline start=+$'+ skip=+''+ end=+'+ contains=vimStringInterpolationBrace,vimStringInterpolationExpr
+syn region vimString oneline start=+$"+ end=+"+ contains=@vimStringGroup,vimStringInterpolationBrace,vimStringInterpolationExpr
+syn region vimStringInterpolationExpr oneline contained matchgroup=vimSep start=+{+ end=+}+ contains=@vimExprList
+syn match vimStringInterpolationBrace contained "{{"
+syn match vimStringInterpolationBrace contained "}}"
" Substitutions: {{{2
" =============
syn cluster vimSubstList contains=vimPatSep,vimPatRegion,vimPatSepErr,vimSubstTwoBS,vimSubstRange,vimNotation
syn cluster vimSubstRepList contains=vimSubstSubstr,vimSubstTwoBS,vimNotation
syn cluster vimSubstList add=vimCollection
-syn match vimSubst "\(:\+\s*\|^\s*\||\s*\)\<\%(\<s\%[ubstitute]\>\|\<sm\%[agic]\>\|\<sno\%[magic]\>\)[:#[:alpha:]]\@!" nextgroup=vimSubstPat
-"syn match vimSubst "\%(^\|[^\\]\)\<s\%[ubstitute]\>[:#[:alpha:]]\@!" nextgroup=vimSubstPat contained
-syn match vimSubst "\%(^\|[^\\\"']\)\<s\%[ubstitute]\>[:#[:alpha:]\"']\@!" nextgroup=vimSubstPat contained
-syn match vimSubst "/\zs\<s\%[ubstitute]\>\ze/" nextgroup=vimSubstPat
-syn match vimSubst "\(:\+\s*\|^\s*\)s\ze#.\{-}#.\{-}#" nextgroup=vimSubstPat
-syn match vimSubst1 contained "\<s\%[ubstitute]\>" nextgroup=vimSubstPat
-syn match vimSubst2 contained "s\%[ubstitute]\>" nextgroup=vimSubstPat
-syn region vimSubstPat contained matchgroup=vimSubstDelim start="\z([^a-zA-Z( \t[\]&]\)"rs=s+1 skip="\\\\\|\\\z1" end="\z1"re=e-1,me=e-1 contains=@vimSubstList nextgroup=vimSubstRep4 oneline
-syn region vimSubstRep4 contained matchgroup=vimSubstDelim start="\z(.\)" skip="\\\\\|\\\z1" end="\z1" matchgroup=vimNotation end="<[cC][rR]>" contains=@vimSubstRepList nextgroup=vimSubstFlagErr oneline
-syn region vimCollection contained transparent start="\\\@<!\[" skip="\\\[" end="\]" contains=vimCollClass
-syn match vimCollClassErr contained "\[:.\{-\}:\]"
-syn match vimCollClass contained transparent "\%#=1\[:\(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|xdigit\|return\|tab\|escape\|backspace\):\]"
-syn match vimSubstSubstr contained "\\z\=\d"
-syn match vimSubstTwoBS contained "\\\\"
-syn match vimSubstFlagErr contained "[^< \t\r|]\+" contains=vimSubstFlags
-syn match vimSubstFlags contained "[&cegiIlnpr#]\+"
+syn match vimSubst "^\s*\%(s\%[ubstitute]\|sm\%[agic]\|sno\%[magic]\)\>[\"#|]\@!" nextgroup=vimSubstPat
+syn match vimSubst "^\s*\%(s\%[ubstitute]\|sm\%[agic]\|sno\%[magic]\)_\@=" nextgroup=vimSubstPat
+syn match vimSubst "^\s*\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)\ze#.\{-}#.\{-}#" nextgroup=vimSubstPat
+syn match vimSubst1 contained "\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)\>[\"#|]\@!" nextgroup=vimSubstPat
+syn match vimSubst1 contained "\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)_\@=" nextgroup=vimSubstPat
+syn match vimSubst1 contained "\%(s\%[ubstitute]\|sm\%[agic]\>\|sno\%[magic]\)\ze#.\{-}#.\{-}#" nextgroup=vimSubstPat
+" TODO: Vim9 illegal separators for abbreviated :s form are [-.:], :su\%[...] required
+" : # is allowed but "not recommended" (see :h pattern-delimiter)
+syn region vimSubstPat contained matchgroup=vimSubstDelim start="\z([!#$%&'()*+,-./:;<=>?@[\]^_`{}~]\)"rs=s+1 skip="\\\\\|\\\z1" end="\z1"re=e-1,me=e-1 contains=@vimSubstList nextgroup=vimSubstRep4 oneline
+syn region vimSubstRep4 contained matchgroup=vimSubstDelim start="\z(.\)" skip="\\\\\|\\\z1" end="\z1" matchgroup=vimNotation end="<[cC][rR]>" contains=@vimSubstRepList nextgroup=vimSubstFlagErr oneline
+syn region vimCollection contained transparent start="\\\@<!\[" skip="\\\[" end="\]" contains=vimCollClass
+syn match vimCollClassErr contained "\[:.\{-\}:\]"
+syn match vimCollClass contained transparent "\%#=1\[:\(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|space\|upper\|xdigit\|retu\%[rn]\|tab\|escape\|backspace\):\]"
+syn match vimSubstSubstr contained "\\z\=\d"
+syn match vimSubstTwoBS contained "\\\\"
+syn match vimSubstFlagErr contained "[^< \t\r|]\+" contains=vimSubstFlags
+syn match vimSubstFlags contained "[&cegiIlnpr#]\+"
" 'String': {{{2
syn match vimString "[^(,]'[^']\{-}\zs'"
" Marks, Registers, Addresses, Filters: {{{2
-syn match vimMark "'[a-zA-Z0-9]\ze[-+,!]" nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark "'[<>]\ze[-+,!]" nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark ",\zs'[<>]\ze" nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark "[!,:]\zs'[a-zA-Z0-9]" nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMark "\<norm\%[al]\s\zs'[a-zA-Z0-9]" nextgroup=vimFilter,vimMarkNumber,vimSubst
-syn match vimMarkNumber "[-+]\d\+" contained contains=vimOper nextgroup=vimSubst2
+syn match vimMark "'[a-zA-Z0-9]\ze[-+,!]" nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark "'[<>]\ze[-+,!]" nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark ",\zs'[<>]\ze" nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark "[!,:]\zs'[a-zA-Z0-9]" nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMark "\<norm\%[al]\s\zs'[a-zA-Z0-9]" nextgroup=vimFilter,vimMarkNumber,vimSubst1
+syn match vimMarkNumber "[-+]\d\+" contained contains=vimOper nextgroup=vimSubst1
syn match vimPlainMark contained "'[a-zA-Z0-9]"
syn match vimRange "[`'][a-zA-Z0-9],[`'][a-zA-Z0-9]" contains=vimMark skipwhite nextgroup=vimFilter
@@ -346,6 +384,7 @@ syn match vimRegister '\<norm\s\+\zs"[a-zA-Z0-9]'
syn match vimRegister '\<normal\s\+\zs"[a-zA-Z0-9]'
syn match vimRegister '@"'
syn match vimPlainRegister contained '"[a-zA-Z0-9\-:.%#*+=]'
+syn match vimLetRegister contained '@["0-9\-a-zA-Z#=*+_/]'
syn match vimAddress ",\zs[.$]" skipwhite nextgroup=vimSubst1
syn match vimAddress "%\ze\a" skipwhite nextgroup=vimString,vimSubst1
@@ -355,24 +394,36 @@ syn match vimFilter contained "!!\=[^"]\{-}\(|\|\ze\"\|$\)" contains=vimOper,
syn match vimComFilter contained "|!!\=[^"]\{-}\(|\|\ze\"\|$\)" contains=vimOper,vimSpecFile
" Complex Repeats: (:h complex-repeat) {{{2
+" ===============
syn match vimCmplxRepeat '[^a-zA-Z_/\\()]q[0-9a-zA-Z"]\>'lc=1
syn match vimCmplxRepeat '@[0-9a-z".=@:]\ze\($\|[^a-zA-Z]\>\)'
" Set command and associated set-options (vimOptions) with comment {{{2
syn region vimSet matchgroup=vimCommand start="\<\%(setl\%[ocal]\|setg\%[lobal]\|se\%[t]\)\>" skip="\%(\\\\\)*\\.\n\@!" end="$" end="|" matchgroup=vimNotation end="<[cC][rR]>" keepend contains=vimSetEqual,vimOption,vimErrSetting,vimComment,vim9Comment,vimSetString,vimSetMod
- syn region vimSetEqual contained start="[=:]\|[-+^]=" skip="\\\\\|\\\s" end="[| \t]"me=e-1 end="$" contains=vimCtrlChar,vimSetSep,vimNotation,vimEnvvar
+syn region vimSetEqual contained start="[=:]\|[-+^]=" skip="\\\\\|\\\s" end="[| \t]"me=e-1 end="$" contains=vimCtrlChar,vimSetSep,vimNotation,vimEnvvar
syn region vimSetString contained start=+="+hs=s+1 skip=+\\\\\|\\"+ end=+"+ contains=vimCtrlChar
syn match vimSetSep contained "[,:]"
syn match vimSetMod contained "&vim\=\|[!&?<]\|all&"
" Let: {{{2
" ===
-syn keyword vimLet let unl[et] skipwhite nextgroup=vimVar,vimFuncVar,vimLetHereDoc
+syn keyword vimLet let skipwhite nextgroup=vimVar,vimFuncVar,vimLetHereDoc,vimLetRegister,vimVarList
+syn keyword vimConst cons[t] skipwhite nextgroup=vimVar,vimLetHereDoc,vimVarList
+syn region vimVarList contained start="\[" end="]" contains=vimVar,vimContinue
+
+syn keyword vimUnlet unl[et] skipwhite nextgroup=vimUnletBang,vimUnletVars
+syn match vimUnletBang contained "!" skipwhite nextgroup=vimUnletVars
+syn region vimUnletVars contained start="$\I\|\h" skip="\n\s*\\" end="$" end="|" contains=vimVar,vimEnvvar,vimContinue,vimString,vimNumber
+
VimFoldh syn region vimLetHereDoc matchgroup=vimLetHereDocStart start='=<<\s*\%(trim\s\+\%(eval\s\+\)\=\|eval\s\+\%(trim\s\+\)\=\)\=\z(\L\S*\)' matchgroup=vimLetHereDocStop end='^\s*\z1\s*$'
+" For: {{{2
+" ===
+syn keyword vimFor for skipwhite nextgroup=vimVar,vimVarList
" Abbreviations: {{{2
" =============
-syn keyword vimAbb ab[breviate] ca[bbrev] inorea[bbrev] cnorea[bbrev] norea[bbrev] ia[bbrev] skipwhite nextgroup=vimMapMod,vimMapLhs
+" GEN_SYN_VIM: vimCommand abbrev, START_STR='syn keyword vimAbb', END_STR='skipwhite nextgroup=vimMapMod,vimMapLhs'
+syn keyword vimAbb ab[breviate] ca[bbrev] cnorea[bbrev] cuna[bbrev] ia[bbrev] inorea[bbrev] iuna[bbrev] norea[bbrev] una[bbreviate] skipwhite nextgroup=vimMapMod,vimMapLhs
" Autocmd: {{{2
" =======
@@ -382,25 +433,32 @@ syn match vimAutoCmdSfxList contained "\S*" skipwhite nextgroup=vimAutoCmdMod
syn keyword vimAutoCmd au[tocmd] do[autocmd] doautoa[ll] skipwhite nextgroup=vimAutoEventList
syn match vimAutoCmdMod "\(++\)\=\(once\|nested\)"
-" Echo and Execute: -- prefer strings! {{{2
+" Echo And Execute: -- prefer strings! {{{2
" ================
-syn region vimEcho oneline excludenl matchgroup=vimCommand start="\<ec\%[ho]\>" skip="\(\\\\\)*\\|" end="$\||" contains=vimFunc,vimFuncVar,vimString,vimVar
-syn region vimExecute oneline excludenl matchgroup=vimCommand start="\<exe\%[cute]\>" skip="\(\\\\\)*\\|" end="$\||\|<[cC][rR]>" contains=vimFuncVar,vimIsCommand,vimOper,vimNotation,vimOperParen,vimString,vimVar
-syn match vimEchoHL "echohl\=" skipwhite nextgroup=vimGroup,vimHLGroup,vimEchoHLNone,vimOnlyHLGroup,nvimHLGroup
+" GEN_SYN_VIM: vimCommand echo, START_STR='syn keyword vimEcho', END_STR='skipwhite nextgroup=vimEchoExpr'
+syn keyword vimEcho ec[ho] echoe[rr] echom[sg] echoc[onsole] echon echow[indow] skipwhite nextgroup=vimEchoExpr
+syn region vimEchoExpr contained start="[^[:space:]|]" skip=+\\\\\|\\|\|\n\s*\\\|\n\s*"\\ + matchgroup=vimCmdSep end="|" end="$" contains=@vimContinue,@vimExprList
+
+syn match vimEchoHL "\<echohl\=\>" skipwhite nextgroup=vimGroup,vimHLGroup,vimEchoHLNone,vimOnlyHLGroup,nvimHLGroup
syn case ignore
syn keyword vimEchoHLNone none
syn case match
+syn region vimExecute oneline excludenl matchgroup=vimCommand start="\<exe\%[cute]\>" skip="\(\\\\\)*\\|" end="$\||\|<[cC][rR]>" contains=vimFuncVar,vimIsCommand,vimOper,vimNotation,vimOperParen,vimString,vimVar
+
" Maps: {{{2
" ====
-syn match vimMap "\<map\>!\=\ze\s*[^(]" skipwhite nextgroup=vimMapMod,vimMapLhs
-syn keyword vimMap cm[ap] cno[remap] im[ap] ino[remap] lm[ap] ln[oremap] nm[ap] nn[oremap] no[remap] om[ap] ono[remap] smap snor[emap] tno[remap] tm[ap] vm[ap] vmapc[lear] vn[oremap] xm[ap] xn[oremap] skipwhite nextgroup=vimMapBang,vimMapMod,vimMapLhs
-syn keyword nvimMap tn[oremap] tm[ap] skipwhite nextgroup=vimMapBang,vimMapMod,vimMapLhs
-syn keyword vimMap mapc[lear] smapc[lear]
-syn keyword vimUnmap cu[nmap] iu[nmap] lu[nmap] nun[map] ou[nmap] sunm[ap] unm[ap] unm[ap] vu[nmap] xu[nmap] skipwhite nextgroup=vimMapBang,vimMapMod,vimMapLhs
-syn keyword nvimUnmap tunm[ap] skipwhite nextgroup=vimMapBang,vimMapMod,vimMapLhs
+syn match vimMap "\<map\>\ze\s*(\@!" skipwhite nextgroup=vimMapMod,vimMapLhs
+syn match vimMap "\<map!" contains=vimMapBang skipwhite nextgroup=vimMapMod,vimMapLhs
+" GEN_SYN_VIM: vimCommand map, START_STR='syn keyword vimMap', END_STR='skipwhite nextgroup=vimMapBang,vimMapMod,vimMapLhs'
+syn keyword vimMap cm[ap] cno[remap] im[ap] ino[remap] lm[ap] ln[oremap] nm[ap] nn[oremap] no[remap] om[ap] ono[remap] smap snor[emap] tma[p] tno[remap] vm[ap] vn[oremap] xm[ap] xn[oremap] skipwhite nextgroup=vimMapBang,vimMapMod,vimMapLhs
+" GEN_SYN_VIM: vimCommand mapclear, START_STR='syn keyword vimMap', END_STR='skipwhite nextgroup=vimMapMod'
+syn keyword vimMap cmapc[lear] imapc[lear] lmapc[lear] nmapc[lear] omapc[lear] smapc[lear] tmapc[lear] vmapc[lear] xmapc[lear] skipwhite nextgroup=vimMapMod
+syn keyword vimMap mapc[lear] skipwhite nextgroup=vimMapBang,vimMapMod
+" GEN_SYN_VIM: vimCommand unmap, START_STR='syn keyword vimUnmap', END_STR='skipwhite nextgroup=vimMapBang,vimMapMod,vimMapLhs'
+syn keyword vimUnmap cu[nmap] iu[nmap] lu[nmap] nun[map] ou[nmap] sunm[ap] tunma[p] unm[ap] vu[nmap] xu[nmap] skipwhite nextgroup=vimMapBang,vimMapMod,vimMapLhs
syn match vimMapLhs contained "\S\+" contains=vimNotation,vimCtrlChar skipwhite nextgroup=vimMapRhs
-syn match vimMapBang contained "!" skipwhite nextgroup=vimMapMod,vimMapLhs
+syn match vimMapBang contained "\a\@1<=!" skipwhite nextgroup=vimMapMod,vimMapLhs
syn match vimMapMod contained "\%#=1\c<\(buffer\|expr\|\(local\)\=leader\|nowait\|plug\|script\|sid\|unique\|silent\)\+>" contains=vimMapModKey,vimMapModErr skipwhite nextgroup=vimMapMod,vimMapLhs
syn match vimMapRhs contained ".*" contains=vimNotation,vimCtrlChar skipnl nextgroup=vimMapRhsExtend
syn match vimMapRhsExtend contained "^\s*\\.*$" contains=vimContinue
@@ -411,7 +469,8 @@ syn case match
" Menus: {{{2
" =====
syn cluster vimMenuList contains=vimMenuBang,vimMenuPriority,vimMenuName,vimMenuMod
-syn keyword vimCommand am[enu] an[oremenu] aun[menu] cme[nu] cnoreme[nu] cunme[nu] ime[nu] inoreme[nu] iunme[nu] me[nu] nme[nu] nnoreme[nu] noreme[nu] nunme[nu] ome[nu] onoreme[nu] ounme[nu] tlm[enu] tln[oremenu] tlu[nmenu] unme[nu] vme[nu] vnoreme[nu] vunme[nu] skipwhite nextgroup=@vimMenuList
+" GEN_SYN_VIM: vimCommand menu, START_STR='syn keyword vimCommand', END_STR='skipwhite nextgroup=@vimMenuList'
+syn keyword vimCommand am[enu] an[oremenu] aun[menu] cme[nu] cnoreme[nu] cunme[nu] ime[nu] inoreme[nu] iunme[nu] me[nu] nme[nu] nnoreme[nu] noreme[nu] nunme[nu] ome[nu] onoreme[nu] ounme[nu] sme[nu] snoreme[nu] sunme[nu] tlm[enu] tln[oremenu] tlu[nmenu] unme[nu] vme[nu] vnoreme[nu] vunme[nu] xme[nu] xnoreme[nu] xunme[nu] skipwhite nextgroup=@vimMenuList
syn match vimMenuName "[^ \t\\<]\+" contained nextgroup=vimMenuNameMore,vimMenuMap
syn match vimMenuPriority "\d\+\(\.\d\+\)*" contained skipwhite nextgroup=vimMenuName
syn match vimMenuNameMore "\c\\\s\|<tab>\|\\\." contained nextgroup=vimMenuName,vimMenuNameMore contains=vimNotation
@@ -423,12 +482,23 @@ syn match vimMenuBang "!" contained skipwhite nextgroup=@vimMenuList
" Angle-Bracket Notation: (tnx to Michael Geddes) {{{2
" ======================
syn case ignore
-syn match vimNotation "\%#=1\(\\\|<lt>\)\=<\([scamd]-\)\{0,4}x\=\(f\d\{1,2}\|[^ \t:]\|cmd\|cr\|lf\|linefeed\|return\|enter\|k\=del\%[ete]\|bs\|backspace\|tab\|esc\|right\|left\|help\|undo\|insert\|ins\|mouse\|k\=home\|k\=end\|kplus\|kminus\|kdivide\|kmultiply\|kenter\|kpoint\|space\|k\=\(page\)\=\(\|down\|up\|k\d\>\)\)>" contains=vimBracket
-syn match vimNotation "\%#=1\(\\\|<lt>\)\=<\([scam2-4]-\)\{0,4}\(right\|left\|middle\)\(mouse\)\=\(drag\|release\)\=>" contains=vimBracket
-syn match vimNotation "\%#=1\(\\\|<lt>\)\=<\(bslash\|plug\|sid\|space\|bar\|nop\|nul\|lt\)>" contains=vimBracket
-syn match vimNotation '\(\\\|<lt>\)\=<C-R>[0-9a-z"%#:.\-=]'he=e-1 contains=vimBracket
-syn match vimNotation '\%#=1\(\\\|<lt>\)\=<\%(q-\)\=\(line[12]\|count\|bang\|reg\|args\|mods\|f-args\|f-mods\|lt\)>' contains=vimBracket
-syn match vimNotation "\%#=1\(\\\|<lt>\)\=<\([cas]file\|abuf\|amatch\|cword\|cWORD\|client\)>" contains=vimBracket
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd]-\)\{0,4}x\=\%(f\d\{1,2}\|[^ \t:]\|space\|bar\|bslash\|nl\|newline\|lf\|linefeed\|cr\|retu\%[rn]\|enter\|k\=del\%[ete]\|bs\|backspace\|tab\|esc\|csi\|right\|paste\%(start\|end\)\|left\|help\|undo\|k\=insert\|ins\|mouse\|[kz]\=home\|[kz]\=end\|kplus\|kminus\|kdivide\|kmultiply\|kenter\|kpoint\|space\|k\=\%(page\)\=\%(\|down\|up\|k\d\>\)\)>" contains=vimBracket
+
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}\%(net\|dec\|jsb\|pterm\|urxvt\|sgr\)mouse>" contains=vimBracket
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}\%(left\|middle\|right\)\%(mouse\|drag\|release\)>" contains=vimBracket
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}left\%(mouse\|release\)nm>" contains=vimBracket
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}x[12]\%(mouse\|drag\|release\)>" contains=vimBracket
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}sgrmouserelease>" contains=vimBracket
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}mouse\%(up\|down\|move\)>" contains=vimBracket
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd2-4]-\)\{0,4}scrollwheel\%(up\|down\|right\|left\)>" contains=vimBracket
+
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%(sid\|nop\|nul\|lt\|drop\)>" contains=vimBracket
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%(snr\|plug\|cursorhold\|ignore\|cmd\|scriptcmd\|focus\%(gained\|lost\)\)>" contains=vimBracket
+syn match vimNotation '\%(\\\|<lt>\)\=<C-R>[0-9a-z"%#:.\-=]'he=e-1 contains=vimBracket
+syn match vimNotation '\%#=1\%(\\\|<lt>\)\=<\%(q-\)\=\%(line[12]\|count\|bang\|reg\|args\|mods\|f-args\|f-mods\|lt\)>' contains=vimBracket
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([cas]file\|abuf\|amatch\|cexpr\|cword\|cWORD\|client\|stack\|script\|sf\=lnum\)>" contains=vimBracket
+syn match vimNotation "\%#=1\%(\\\|<lt>\)\=<\%([scamd]-\)\{0,4}char-\%(\d\+\|0\o\+\|0x\x\+\)>" contains=vimBracket
+
syn match vimBracket contained "[\\<>]"
syn case match
@@ -460,16 +530,22 @@ syn match vimNormCmds contained ".*$"
" Syntax: {{{2
"=======
-syn match vimGroupList contained "@\=[^ \t,]*" contains=vimGroupSpecial,vimPatSep
-syn match vimGroupList contained "@\=[^ \t,]*," nextgroup=vimGroupList contains=vimGroupSpecial,vimPatSep
+syn match vimGroupList contained "[^[:space:],]\+\%(\s*,\s*[^[:space:],]\+\)*" contains=vimGroupSpecial
+syn region vimGroupList contained start=/^\s*["#]\\ \|^\s*\\\|[^[:space:],]\+\s*,/ skip=/\s*\n\s*\\\|\s*\n\s*["#]\\ \|^\s*\\\|^\s*["#]\\ / end=/[^[:space:],]\s*$\|[^[:space:],]\ze\s\+\w/ contains=@vimContinue,vimGroupSpecial
syn keyword vimGroupSpecial contained ALL ALLBUT CONTAINED TOP
+
if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_novimsynerror")
syn match vimSynError contained "\i\+"
syn match vimSynError contained "\i\+=" nextgroup=vimGroupList
endif
-syn match vimSynContains contained "\<contain\(s\|edin\)=" nextgroup=vimGroupList
-syn match vimSynKeyContainedin contained "\<containedin=" nextgroup=vimGroupList
-syn match vimSynNextgroup contained "nextgroup=" nextgroup=vimGroupList
+syn match vimSynContains contained "\<contain\%(s\|edin\)=" skipwhite skipnl nextgroup=vimGroupList
+syn match vimSynKeyContainedin contained "\<containedin=" skipwhite skipnl nextgroup=vimGroupList
+syn match vimSynNextgroup contained "\<nextgroup=" skipwhite skipnl nextgroup=vimGroupList
+if has("conceal")
+ " no whitespace allowed after '='
+ syn match vimSynCchar contained "\<cchar=" nextgroup=vimSynCcharValue
+ syn match vimSynCcharValue contained "\S"
+endif
syn match vimSyntax "\<sy\%[ntax]\>" contains=vimCommand skipwhite nextgroup=vimSynType,vimComment,vim9Comment
syn match vimAuSyntax contained "\s+sy\%[ntax]" contains=vimCommand skipwhite nextgroup=vimSynType,vimComment,vim9Comment
@@ -487,10 +563,16 @@ syn keyword vimSynType contained clear skipwhite nextgroup=vimGroupList
" Syntax: cluster {{{2
syn keyword vimSynType contained cluster skipwhite nextgroup=vimClusterName
-syn region vimClusterName contained matchgroup=vimGroupName start="\h\w*" skip="\\\\\|\\|" matchgroup=vimSep end="$\||" contains=vimGroupAdd,vimGroupRem,vimSynContains,vimSynError
-syn match vimGroupAdd contained "add=" nextgroup=vimGroupList
-syn match vimGroupRem contained "remove=" nextgroup=vimGroupList
-syn cluster vimFuncBodyList add=vimSynType,vimGroupAdd,vimGroupRem
+syn region vimClusterName contained keepend matchgroup=vimGroupName start="\h\w*\>" skip=+\\\\\|\\\|\n\s*\\\|\n\s*"\\ + matchgroup=vimCmdSep end="$\||" contains=@vimContinue,vimGroupAdd,vimGroupRem,vimSynContains,vimSynError
+syn match vimGroupAdd contained keepend "\<add=" skipwhite skipnl nextgroup=vimGroupList
+syn match vimGroupRem contained keepend "\<remove=" skipwhite skipnl nextgroup=vimGroupList
+
+" Syntax: foldlevel {{{2
+syn keyword vimSynType contained foldlevel skipwhite nextgroup=vimSynFoldMethod,vimSynFoldMethodError
+if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_novimsynfoldmethoderror")
+ syn match vimSynFoldMethodError contained "\i\+"
+endif
+syn keyword vimSynFoldMethod contained start minimum
" Syntax: iskeyword {{{2
syn keyword vimSynType contained iskeyword skipwhite nextgroup=vimIskList
@@ -499,38 +581,31 @@ syn match vimIskSep contained ','
" Syntax: include {{{2
syn keyword vimSynType contained include skipwhite nextgroup=vimGroupList
-syn cluster vimFuncBodyList add=vimSynType
" Syntax: keyword {{{2
-syn cluster vimSynKeyGroup contains=vimSynNextgroup,vimSynKeyOpt,vimSynKeyContainedin
+syn cluster vimSynKeyGroup contains=@vimContinue,vimSynCchar,vimSynNextgroup,vimSynKeyOpt,vimSynKeyContainedin
syn keyword vimSynType contained keyword skipwhite nextgroup=vimSynKeyRegion
-syn region vimSynKeyRegion contained oneline keepend matchgroup=vimGroupName start="\h\w*" skip="\\\\\|\\|" matchgroup=vimSep end="|\|$" contains=@vimSynKeyGroup
+syn region vimSynKeyRegion contained keepend matchgroup=vimGroupName start="\h\w*\>" skip=+\\\\\|\\|\|\n\s*\\\|\n\s*"\\ + matchgroup=vimCmdSep end="|\|$" contains=@vimSynKeyGroup
syn match vimSynKeyOpt contained "\%#=1\<\(conceal\|contained\|transparent\|skipempty\|skipwhite\|skipnl\)\>"
-syn cluster vimFuncBodyList add=vimSynType
" Syntax: match {{{2
-syn cluster vimSynMtchGroup contains=vimMtchComment,vimSynContains,vimSynError,vimSynMtchOpt,vimSynNextgroup,vimSynRegPat,vimNotation,vim9Comment
+syn cluster vimSynMtchGroup contains=@vimContinue,vimSynCchar,vimSynContains,vimSynError,vimSynMtchOpt,vimSynNextgroup,vimSynRegPat,vimNotation,vimMtchComment
syn keyword vimSynType contained match skipwhite nextgroup=vimSynMatchRegion
-syn region vimSynMatchRegion contained keepend matchgroup=vimGroupName start="\h\w*" matchgroup=vimSep end="|\|$" contains=@vimSynMtchGroup
+syn region vimSynMatchRegion contained keepend matchgroup=vimGroupName start="\h\w*\>" skip=+\\\\\|\\|\|\n\s*\\\|\n\s*"\\ + matchgroup=vimCmdSep end="|\|$" contains=@vimSynMtchGroup
syn match vimSynMtchOpt contained "\%#=1\<\(conceal\|transparent\|contained\|excludenl\|keepend\|skipempty\|skipwhite\|display\|extend\|skipnl\|fold\)\>"
-if has("conceal")
- syn match vimSynMtchOpt contained "\<cchar=" nextgroup=vimSynMtchCchar
- syn match vimSynMtchCchar contained "\S"
-endif
-syn cluster vimFuncBodyList add=vimSynMtchGroup
" Syntax: off and on {{{2
syn keyword vimSynType contained enable list manual off on reset
" Syntax: region {{{2
-syn cluster vimSynRegPatGroup contains=vimPatSep,vimNotPatSep,vimSynPatRange,vimSynNotPatRange,vimSubstSubstr,vimPatRegion,vimPatSepErr,vimNotation
-syn cluster vimSynRegGroup contains=vimSynContains,vimSynNextgroup,vimSynRegOpt,vimSynReg,vimSynMtchGrp
+syn cluster vimSynRegPatGroup contains=@vimContinue,vimPatSep,vimNotPatSep,vimSynPatRange,vimSynNotPatRange,vimSubstSubstr,vimPatRegion,vimPatSepErr,vimNotation
+syn cluster vimSynRegGroup contains=@vimContinue,vimSynCchar,vimSynContains,vimSynNextgroup,vimSynRegOpt,vimSynReg,vimSynMtchGrp
syn keyword vimSynType contained region skipwhite nextgroup=vimSynRegion
-syn region vimSynRegion contained keepend matchgroup=vimGroupName start="\h\w*" skip="\\\\\|\\|" end="|\|$" contains=@vimSynRegGroup
+syn region vimSynRegion contained keepend matchgroup=vimGroupName start="\h\w*" skip=+\\\\\|\\\|\n\s*\\\|\n\s*"\\ + end="|\|$" contains=@vimSynRegGroup
syn match vimSynRegOpt contained "\%#=1\<\(conceal\(ends\)\=\|transparent\|contained\|excludenl\|skipempty\|skipwhite\|display\|keepend\|oneline\|extend\|skipnl\|fold\)\>"
-syn match vimSynReg contained "\(start\|skip\|end\)="he=e-1 nextgroup=vimSynRegPat
+syn match vimSynReg contained "\<\%(start\|skip\|end\)=" nextgroup=vimSynRegPat
syn match vimSynMtchGrp contained "matchgroup=" nextgroup=vimGroup,vimHLGroup,vimOnlyHLGroup,nvimHLGroup
-syn region vimSynRegPat contained extend start="\z([-`~!@#$%^&*_=+;:'",./?]\)" skip="\\\\\|\\\z1" end="\z1" contains=@vimSynRegPatGroup skipwhite nextgroup=vimSynPatMod,vimSynReg
+syn region vimSynRegPat contained extend start="\z([-`~!@#$%^&*_=+;:'",./?]\)" skip=/\\\\\|\\\z1\|\n\s*\\\|\n\s*"\\ / end="\z1" contains=@vimSynRegPatGroup skipwhite nextgroup=vimSynPatMod,vimSynReg
syn match vimSynPatMod contained "\%#=1\(hs\|ms\|me\|hs\|he\|rs\|re\)=[se]\([-+]\d\+\)\="
syn match vimSynPatMod contained "\%#=1\(hs\|ms\|me\|hs\|he\|rs\|re\)=[se]\([-+]\d\+\)\=," nextgroup=vimSynPatMod
syn match vimSynPatMod contained "lc=\d\+"
@@ -538,7 +613,6 @@ syn match vimSynPatMod contained "lc=\d\+," nextgroup=vimSynPatMod
syn region vimSynPatRange contained start="\[" skip="\\\\\|\\]" end="]"
syn match vimSynNotPatRange contained "\\\\\|\\\["
syn match vimMtchComment contained '"[^"]\+$'
-syn cluster vimFuncBodyList add=vimSynType
" Syntax: sync {{{2
" ============
@@ -572,7 +646,7 @@ syn match vimHiBang contained "!" skipwhite nextgroup=@vimHighlightCluster
syn match vimHiGroup contained "\i\+"
syn case ignore
-syn keyword vimHiAttrib contained none bold inverse italic nocombine reverse standout strikethrough underline undercurl underdouble underdotted underdashed
+syn keyword vimHiAttrib contained none bold inverse italic nocombine reverse standout strikethrough underline undercurl underdashed underdotted underdouble
syn keyword vimFgBgAttrib contained none bg background fg foreground
syn case match
syn match vimHiAttribList contained "\i\+" contains=vimHiAttrib
@@ -587,7 +661,7 @@ syn match vimHiGuiFontname contained "'[a-zA-Z\-* ]\+'"
syn match vimHiGuiRgb contained "#\x\{6}"
" Highlighting: hi group key=arg ... {{{2
-syn cluster vimHiCluster contains=vimGroup,vimHiBlend,vimHiGroup,vimHiTerm,vimHiCTerm,vimHiStartStop,vimHiCtermFgBg,vimHiCtermul,vimHiGui,vimHiGuiFont,vimHiGuiFgBg,vimHiKeyError,vimNotation
+syn cluster vimHiCluster contains=vimGroup,vimHiBlend,vimHiGroup,vimHiTerm,vimHiCTerm,vimHiStartStop,vimHiCtermFgBg,vimHiCtermul,vimHiGui,vimHiGuiFont,vimHiGuiFgBg,vimHiKeyError,vimNotation,vimComment,vim9comment
syn region vimHiKeyList contained oneline start="\i\+" skip="\\\\\|\\|" end="$\||" contains=@vimHiCluster
if !exists("g:vimsyn_noerror") && !exists("g:vimsyn_vimhikeyerror")
syn match vimHiKeyError contained "\i\+="he=e-1
@@ -611,7 +685,6 @@ syn keyword vimHiClear contained clear nextgroup=vimHiGroup
" see tst24 (hi def vs hi) (Jul 06, 2018)
"syn region vimHiLink contained oneline matchgroup=vimCommand start="\(\<hi\%[ghlight]\s\+\)\@<=\(\(def\%[ault]\s\+\)\=link\>\|\<def\>\)" end="$" contains=vimHiGroup,vimGroup,vimHLGroup,vimNotation
syn region vimHiLink contained oneline matchgroup=vimCommand start="\(\<hi\%[ghlight]\s\+\)\@<=\(\(def\%[ault]\s\+\)\=link\>\|\<def\>\)" end="$" contains=@vimHiCluster
-syn cluster vimFuncBodyList add=vimHiLink
" Control Characters: {{{2
" ==================
@@ -619,10 +692,14 @@ syn match vimCtrlChar "[- -]"
" Beginners - Patterns that involve ^ {{{2
" =========
-syn match vimLineComment +^[ \t:]*".*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle
+syn match vimLineComment +^[ \t:]*".*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle,vimComment
+syn match vimLineComment +^[ \t:]*"\("[^"]*"\|[^"]\)*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle
syn match vim9LineComment +^[ \t:]\+#.*$+ contains=@vimCommentGroup,vimCommentString,vimCommentTitle
syn match vimCommentTitle '"\s*\%([sS]:\|\h\w*#\)\=\u\w*\(\s\+\u\w*\)*:'hs=s+1 contained contains=vimCommentTitleLeader,vimTodo,@vimCommentGroup
-syn match vimContinue "^\s*\\"
+" Note: Look-behind to work around nextgroup skipnl consuming leading whitespace and preventing a match
+syn match vimContinue "^\s*\zs\\"
+syn match vimContinueComment '^\s*\zs["#]\\ .*' contained
+syn cluster vimContinue contains=vimContinue,vimContinueComment
syn region vimString start="^\s*\\\z(['"]\)" skip='\\\\\|\\\z1' end="\z1" oneline keepend contains=@vimStringGroup,vimContinue
syn match vimCommentTitleLeader '"\s\+'ms=s+1 contained
@@ -630,8 +707,8 @@ syn match vimCommentTitleLeader '"\s\+'ms=s+1 contained
" ====================
syn match vimSearch '^\s*[/?].*' contains=vimSearchDelim
syn match vimSearchDelim '^\s*\zs[/?]\|[/?]$' contained
-syn region vimGlobal matchgroup=Statement start='\<g\%[lobal]!\=/' skip='\\.' end='/' skipwhite nextgroup=vimSubst
-syn region vimGlobal matchgroup=Statement start='\<v\%[global]!\=/' skip='\\.' end='/' skipwhite nextgroup=vimSubst
+syn region vimGlobal matchgroup=Statement start='\<g\%[lobal]!\=/' skip='\\.' end='/' skipwhite nextgroup=vimSubst1
+syn region vimGlobal matchgroup=Statement start='\<v\%[global]!\=/' skip='\\.' end='/' skipwhite nextgroup=vimSubst1
" Embedded Scripts: {{{2
" ================
@@ -840,11 +917,13 @@ if !exists("skip_vim_syntax_inits")
hi def link vimMapModErr vimError
hi def link vimSubstFlagErr vimError
hi def link vimSynCaseError vimError
+ hi def link vimSynFoldMethodError vimError
hi def link vimBufnrWarn vimWarn
endif
hi def link vimAbb vimCommand
hi def link vimAddress vimMark
+ hi def link vimAugroupBang vimBang
hi def link vimAugroupError vimError
hi def link vimAugroupKey vimCommand
hi def link vimAuHighlight vimHighlight
@@ -853,6 +932,8 @@ if !exists("skip_vim_syntax_inits")
hi def link vimAutoEvent Type
hi def link vimAutoCmdMod Special
hi def link vimAutoSet vimCommand
+ hi def link vimBang vimOper
+ hi def link vimBehaveBang vimBang
hi def link vimBehaveModel vimBehave
hi def link vimBehave vimCommand
hi def link vimBracket Delimiter
@@ -863,8 +944,11 @@ if !exists("skip_vim_syntax_inits")
hi def link vimCommentString vimString
hi def link vimCommentTitle PreProc
hi def link vimCondHL vimCommand
+ hi def link vimConst vimCommand
hi def link vimContinue Special
+ hi def link vimContinueComment vimComment
hi def link vimCtrlChar SpecialChar
+ hi def link vimEcho vimCommand
hi def link vimEchoHLNone vimGroup
hi def link vimEchoHL vimCommand
hi def link vimElseIfErr Error
@@ -877,6 +961,7 @@ if !exists("skip_vim_syntax_inits")
hi def link vimFuncEcho vimCommand
hi def link vimHiCtermul vimHiTerm
hi def link vimFold Folded
+ hi def link vimFor vimCommand
hi def link vimFTCmd vimCommand
hi def link vimFTOption vimSynType
hi def link vimFuncKey vimCommand
@@ -889,6 +974,7 @@ if !exists("skip_vim_syntax_inits")
hi def link vimGroupSpecial Special
hi def link vimGroup Type
hi def link vimHiAttrib PreProc
+ hi def link vimHiBang vimBang
hi def link vimHiBlend vimHiTerm
hi def link vimHiClear vimHighlight
hi def link vimHiCtermFgBg vimHiTerm
@@ -907,19 +993,23 @@ if !exists("skip_vim_syntax_inits")
hi def link vimInsert vimString
hi def link vimIskSep Delimiter
hi def link vimKeyCode vimSpecFile
+ hi def link vimKeymapLineComment vimComment
+ hi def link vimKeymapTailComment vimComment
hi def link vimKeyword Statement
hi def link vimLet vimCommand
hi def link vimLetHereDoc vimString
hi def link vimLetHereDocStart Special
hi def link vimLetHereDocStop Special
+ hi def link vimLetRegister Special
hi def link vimLineComment vimComment
hi def link vim9LineComment vimComment
- hi def link vimMapBang vimCommand
+ hi def link vimMapBang vimBang
hi def link vimMapModKey vimFuncSID
hi def link vimMapMod vimBracket
hi def link vimMap vimCommand
hi def link vimMark Number
hi def link vimMarkNumber vimNumber
+ hi def link vimMenuBang vimBang
hi def link vimMenuMod vimMapMod
hi def link vimMenuNameMore vimMenuName
hi def link vimMenuName PreProc
@@ -957,6 +1047,7 @@ if !exists("skip_vim_syntax_inits")
hi def link vimStringCont vimString
hi def link vimString String
hi def link vimStringEnd vimString
+ hi def link vimStringInterpolationBrace vimEscape
hi def link vimSubst1 vimSubst
hi def link vimSubstDelim Delimiter
hi def link vimSubstFlags Special
@@ -973,8 +1064,12 @@ if !exists("skip_vim_syntax_inits")
hi def link vimSyncNone Type
hi def link vimSynContains vimSynOption
hi def link vimSynError Error
+ hi def link vimSynFoldMethodError Error
+ hi def link vimSynFoldMethod Type
hi def link vimSynKeyContainedin vimSynContains
hi def link vimSynKeyOpt vimSynOption
+ hi def link vimSynCchar vimSynOption
+ hi def link vimSynCcharValue Character
hi def link vimSynMtchGrp vimSynOption
hi def link vimSynMtchOpt vimSynOption
hi def link vimSynNextgroup vimSynOption
@@ -988,6 +1083,8 @@ if !exists("skip_vim_syntax_inits")
hi def link vimSynType vimSpecial
hi def link vimTodo Todo
hi def link vimType Type
+ hi def link vimUnlet vimCommand
+ hi def link vimUnletBang vimBang
hi def link vimUnmap vimMap
hi def link vimUserAttrbCmpltFunc Special
hi def link vimUserAttrbCmplt vimSpecial
@@ -1002,8 +1099,6 @@ if !exists("skip_vim_syntax_inits")
hi def link nvimAutoEvent vimAutoEvent
hi def link nvimHLGroup vimHLGroup
- hi def link nvimMap vimMap
- hi def link nvimUnmap vimUnmap
endif
" Current Syntax Variable: {{{2
diff --git a/runtime/syntax/xmath.vim b/runtime/syntax/xmath.vim
index 37ae951112..466c1159c7 100644
--- a/runtime/syntax/xmath.vim
+++ b/runtime/syntax/xmath.vim
@@ -1,9 +1,11 @@
" Vim syntax file
" Language: xmath (a simulation tool)
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Aug 31, 2016
+" 2024 Feb 19 by Vim Project (announce adoption)
" Version: 10
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_XMATH
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_XMATH
" For version 5.x: Clear all syntax items
" For version 6.x: Quit when a syntax file was already loaded
diff --git a/runtime/syntax/xxd.vim b/runtime/syntax/xxd.vim
index 2f90b6b0bd..1c06b4296f 100644
--- a/runtime/syntax/xxd.vim
+++ b/runtime/syntax/xxd.vim
@@ -1,10 +1,12 @@
" Vim syntax file
" Language: bin using xxd
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Maintainer: This runtime file is looking for a new maintainer.
+" Former Maintainer: Charles E. Campbell
" Last Change: Aug 31, 2016
" Version: 11
+" 2024 Feb 19 by Vim Project (announce adoption)
" Notes: use :help xxd to see how to invoke it
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_XXD
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_XXD
" quit when a syntax file was already loaded
if exists("b:current_syntax")
diff --git a/runtime/syntax/yacc.vim b/runtime/syntax/yacc.vim
index 459873e3dc..79dcf0eccc 100644
--- a/runtime/syntax/yacc.vim
+++ b/runtime/syntax/yacc.vim
@@ -1,9 +1,10 @@
" Vim syntax file
" Language: Yacc
-" Maintainer: Charles E. Campbell <NcampObell@SdrPchip.AorgM-NOSPAM>
+" Former Maintainer: Charles E. Campbell
" Last Change: Mar 25, 2019
" Version: 17
-" URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_YACC
+" 2024 Feb 19 by Vim Project (announce adoption)
+" Former URL: http://www.drchip.org/astronaut/vim/index.html#SYNTAX_YACC
"
" Options: {{{1
" g:yacc_uses_cpp : if this variable exists, then C++ is loaded rather than C
diff --git a/runtime/tutor/en/vim-01-beginner.tutor b/runtime/tutor/en/vim-01-beginner.tutor
index 2824f7ae83..c3decdef11 100644
--- a/runtime/tutor/en/vim-01-beginner.tutor
+++ b/runtime/tutor/en/vim-01-beginner.tutor
@@ -967,17 +967,17 @@ There are also countless great tutorials and videos to be found online.
Here's a bunch of them:
- *Learn Vim Progressively*:
- http://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/
-- *Learning Vim in 2013*:
- http://benmccormick.org/learning-vim-in-2014/
+ https://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/
+- *Learning Vim in 2014*:
+ https://benmccormick.org/learning-vim-in-2014/
- *Vimcasts*:
http://vimcasts.org/
- *Vim Video-Tutorials by Derek Wyatt*:
http://derekwyatt.org/vim/tutorials/
- *Learn Vimscript the Hard Way*:
- http://learnvimscriptthehardway.stevelosh.com/
+ https://learnvimscriptthehardway.stevelosh.com/
- *7 Habits of Effective Text Editing*:
- http://www.moolenaar.net/habits.html
+ https://www.moolenaar.net/habits.html
- *vim-galore*:
https://github.com/mhinz/vim-galore
diff --git a/runtime/tutor/ja/vim-01-beginner.tutor b/runtime/tutor/ja/vim-01-beginner.tutor
new file mode 100644
index 0000000000..411ebc04f8
--- /dev/null
+++ b/runtime/tutor/ja/vim-01-beginner.tutor
@@ -0,0 +1,995 @@
+# Neovimã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã¸ã‚ˆã†ã“ã
+
+Neovim ã¯ã€ã“ã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã§èª¬æ˜Žã™ã‚‹ã«ã¯å¤šã™ãŽã‚‹ç¨‹ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’å‚™ãˆãŸéžå¸¸ã«
+強力ãªã‚¨ãƒ‡ã‚£ã‚¿ãƒ¼ã§ã™ã€‚ã“ã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã¯ã€ã‚ãªãŸãŒ Neovim を万能エディターã¨ã—ã¦
+使ã„ã“ãªã›ã‚‹ã‚ˆã†ã«ãªã‚‹ã®ã«å分ãªã‚³ãƒžãƒ³ãƒ‰ã«ã¤ã„ã¦èª¬æ˜Žã‚’ã™ã‚‹ã‚ˆã†ã«ãªã£ã¦ã„ã¾ã™ã€‚
+
+ã“ã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ãŒã€ä½“を使ã†ã“ã¨ã§è¦šãˆã‚‰ã‚Œã‚‹ä»•組ã¿ã«ãªã£ã¦ã„ã‚‹ã“ã¨ã‚’ã€
+心ã—ã¦ãŠã‹ãªã‘れã°ãªã‚Šã¾ã›ã‚“。正ã—ã学習ã™ã‚‹ã«ã¯å®Ÿéš›ã«ã‚„ã£ã¦ãªã‘れã°ãªã‚‰ãªã„
+ã®ã§ã™ã€‚テキストをãŸã èª­ã‚€ã ã‘ã§ã¯ã€ä½•ãŒãŒé‡è¦ã ã£ãŸã‹å¿˜ã‚Œã¦ã—ã¾ã†ã§ã—ょã†!
+
+ãれã§ã¯ã€CapsLockã‚­ãƒ¼ãŒæŠ¼ã•れã¦ã„ãªã„ã“ã¨ã‚’確èªã—ãŸå¾Œã€ç”»é¢ã«ãƒ¬ãƒƒã‚¹ãƒ³ 0ãŒ
+全部表示ã•れるã¨ã“ã‚ã¾ã§ã€`j`{normal} キーを押ã—ã¦ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+# レッスン 0
+
+NOTE: 以下ã®ç·´ç¿’用コマンドã«ã¯ã“ã®æ–‡ç« ã‚’変更ã™ã‚‹ã‚‚ã®ã‚‚ã‚りã¾ã™ãŒã€ãれらã®
+変更ã¯ä¿å­˜ã•れã¾ã›ã‚“。失敗をæã‚Œã‚‹å¿…è¦ã¯ã‚りã¾ã›ã‚“〠[<Esc>](<Esc>) キーを押ã—ãŸå¾Œã€
+ [u](u) キーを押ã™ã“ã¨ã§æœ€å¾Œã®æ“ä½œã‚’å…ƒã«æˆ»ã›ã‚‹äº‹ã‚’覚ãˆã¦ãŠã„ã¦ãã ã•ã„。
+
+ã“ã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã¯ã‚¤ãƒ³ã‚¿ãƒ©ã‚¯ãƒ†ã‚£ãƒ–ãªè¨­è¨ˆã«ãªã£ã¦ãŠã‚Šã€
+ã‚ãªãŸãŒçŸ¥ã£ã¦ãŠãã¹ãã“ã¨ãŒã„ãã¤ã‹ã‚りã¾ã™ã€‚
+-[ã“ã®ã‚ˆã†ãªãƒªãƒ³ã‚¯](holy-grail )ã®ä¸Šã§ [<Enter>](<Enter>) キーを押ã™ã“ã¨ã§ã€ãƒªãƒ³ã‚¯ã•れãŸãƒ˜ãƒ«ãƒ—ã‚’é–‹ãã“ã¨ãŒã§ãã¾ã™ã€‚
+-ã‚‚ã—ãã¯ã€ãƒ‰ã‚­ãƒ¥ãƒ¡ãƒ³ãƒˆã§æ¤œç´¢ã—ãŸã„å˜èªžã®ä¸Šã§ [K](K) キー(大文字)を押ã—ã¦ã¿ã¾ã—ょã†ã€‚
+(注: ç¾åœ¨ã€æ—¥æœ¬èªžã®å˜èªžã«ã¯å¯¾å¿œã—ã¦ã„ã¾ã›ã‚“。)
+-ヘルプウィンドウ㯠`:q`{vim} `<Enter>`{normal} ã§é–‰ã˜ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+ç”»é¢ã®å·¦ç«¯ã« ✗ ãŒè¡¨ç¤ºã•れã¦ã„ã‚‹å ´åˆã€ãã®è¡Œã®ãƒ†ã‚­ã‚¹ãƒˆã‚’編集ã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“。
+æ­£ã—ã„ãƒ†ã‚­ã‚¹ãƒˆã«æ›¸ãæ›ãˆã‚‹ã“ã¨ã§ã€å·¦ç«¯ã® ✗ 㯠✓ ã«å¤‰ã‚りã¾ã™ã€‚
+Neovim ãŒã„ã‹ã«å„ªã‚Œã¦ã„ã‚‹ã‹ã€ãŠã‚ã‹ã‚Šã„ãŸã ã‘ã‚‹ã§ã—ょã†ã‹?
+
+ã¾ãŸã€æ¬¡ã®ã‚ˆã†ã«ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã™ã‚‹ã‚ˆã†æ±‚ã‚られるã“ã¨ã‚„ã€(後ã§è©³ã—ã説明ã—ã¾ã™ã€‚)
+
+ `:help`{vim} `<Enter>`{normal}
+
+キーシークエンスを押ã™ã“ã¨ã‚‚ã‚りã¾ã™ã€‚
+~~~ normal
+ <Esc>0f<Space>d3wP$P
+~~~
+< 㨠> ã®é–“ã«å›²ã¾ã‚ŒãŸãƒ†ã‚­ã‚¹ãƒˆ(例ãˆã° `<Enter>`{normal})ã¯ã€
+ãã®ãƒ†ã‚­ã‚¹ãƒˆã‚’タイプã™ã‚‹ã®ã§ã¯ãªãã€ãã®ã‚­ãƒ¼ã‚’押ã™ã“ã¨ã‚’表ã—ã¦ã„ã¾ã™ã€‚
+
+ã§ã¯ã€æ¬¡ã®ãƒ¬ãƒƒã‚¹ãƒ³ã«å‘ã‹ã„ã¾ã—ょã†ã€‚( `j`{normal} キーã§ã‚¹ã‚¯ãƒ­ãƒ¼ãƒ«ãƒ€ã‚¦ãƒ³ã—ã¾ã™ã€‚)
+
+# レッスン 1.1: カーソルã®ç§»å‹•
+
+** カーソルを移動ã™ã‚‹ã«ã¯ã€ç¤ºã•れる様㫠`h`, `j`, `k`, `l` を押ã—ã¾ã™ã€‚ **
+
+ ↑
+ k ヒント: h キーã¯å·¦æ–¹å‘ã«ç§»å‹•ã—ã¾ã™ã€‚
+ ↠h l → l キーã¯å³æ–¹å‘ã«ç§»å‹•ã—ã¾ã™ã€‚
+ j j キーã¯ä¸‹çŸ¢å°ã‚­ãƒ¼ã®ã‚ˆã†ãªã‚­ãƒ¼ã§ã™ã€‚
+ ↓
+
+ 1. ç§»å‹•ã«æ…£ã‚Œã‚‹ã¾ã§ã€ã‚¹ã‚¯ãƒªãƒ¼ãƒ³ã§ã‚«ãƒ¼ã‚½ãƒ«ç§»å‹•ã•ã›ã¾ã—ょã†ã€‚
+
+ 2. 下ã¸ã®ã‚­ãƒ¼(j)を押ã—ã¤ã¥ã‘ã‚‹ã¨ã€é€£ç¶šã—ã¦ç§»å‹•ã§ãã¾ã™ã€‚
+ ã“ã‚Œã§æ¬¡ã®ãƒ¬ãƒƒã‚¹ãƒ³ã«ç§»å‹•ã™ã‚‹æ–¹æ³•ãŒã‚ã‹ã‚Šã¾ã—ãŸã­ã€‚
+
+ 3. 下ã¸ã®ã‚­ãƒ¼ã‚’使ã£ã¦ã€ãƒ¬ãƒƒã‚¹ãƒ³1.2 ã«ç§»å‹•ã—ã¾ã—ょã†ã€‚
+
+NOTE: 何をタイプã—ã¦ã„ã‚‹ã‹åˆ¤ã‚‰ãªããªã£ãŸã‚‰ã€`<Esc>`{normal} を押ã—ã¦ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã«ã—ã¾ã™ã€‚
+ ãれã‹ã‚‰å…¥åŠ›ã—よã†ã¨ã—ã¦ã„ãŸã‚³ãƒžãƒ³ãƒ‰ã‚’å†å…¥åŠ›ã—ã¾ã—ょã†ã€‚
+
+NOTE: カーソルキーã§ã‚‚移動ã§ãã¾ã™ã€‚ã—ã‹ã— hjkl ã«ä¸€åº¦æ…£ã‚Œã¦ã—ã¾ãˆã°ã€
+ ã¯ã‚‹ã‹ã«é€Ÿã移動ã™ã‚‹ã“ã¨ãŒã§ãã‚‹ã§ã—ょã†ã€‚
+
+# レッスン 1.2: NEOVIM ã®èµ·å‹•ã¨çµ‚了
+
+!! NOTE: 以下ã®ã‚らゆるステップを行ã†å‰ã«ã€ã“ã®ãƒ¬ãƒƒã‚¹ãƒ³ã‚’全部読ã¿ã¾ã—ょã†!!
+
+ 1. `<Esc>`{normal} キーを押ã—ã¾ã—ょã†ã€‚(確実ã«ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã«ã™ã‚‹ãŸã‚)
+
+ 2. 次ã®ã‚ˆã†ã«ã‚¿ã‚¤ãƒ—:
+
+ `:q!`{vim} `<Enter>`{normal}
+
+ ã“れã«ã‚ˆã‚Šç·¨é›†ã—ãŸå†…容をä¿å­˜ã›ãšã«ã‚¨ãƒ‡ã‚£ã‚¿ãŒçµ‚了ã—ã¾ã™ã€‚
+
+ 3. Neovim ã‚’é–‹ã„ã¦ã€ã“ã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã‚’å§‹ã‚る為ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’実行ã—ã€
+ ã“ã“ã«æˆ»ã£ã¦ãã¾ã™ã€‚ãã®ã‚³ãƒžãƒ³ãƒ‰ã¯:
+
+ `:Tutor`{vim} `<Enter>`{normal}
+
+ 4. ã“れã¾ã§ã®ã‚¹ãƒ†ãƒƒãƒ—を覚ãˆè‡ªä¿¡ãŒã¤ã„ãŸãªã‚‰ã°ã€ã‚¹ãƒ†ãƒƒãƒ— 1 ã‹ã‚‰ 3 ã¾ã§ã‚’実際ã«è©¦ã—ã¦ã€
+ エディタを1度終了ã—ã¦ã‹ã‚‰å†ã³èµ·å‹•ã—ã¾ã—ょã†ã€‚
+
+NOTE: [:q!](:q) `<Enter>`{normal} ã¯å…¨ã¦ã®å¤‰æ›´ã‚’破棄ã—ã¾ã™ã€‚
+ 後ã«å¤‰æ›´ã‚’ファイルã«ä¿å­˜ã™ã‚‹æ–¹æ³•ã«ã¤ã„ã¦ã‚‚勉強ã—ã¦ã„ãã¾ã—ょã†ã€‚
+
+ 5. 1.3ã¾ã§ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã•ã›ã¾ã—ょã†ã€‚
+
+# レッスン 1.3: テキスト編集 - 削除
+
+** カーソルã®ä¸‹ã®æ–‡å­—を削除ã™ã‚‹ã«ã¯ `x`{normal} を押ã—ã¾ã™ã€‚ **
+
+ 1. 以下㮠✗ ã¨ç¤ºã•れãŸè¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 2. é–“é•ã„を修正ã™ã‚‹ãŸã‚ã«ã€å‰Šé™¤ã™ã‚‹æœ€åˆã®æ–‡å­—ã¾ã§ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã™ã€‚
+
+ 3. ä¸å¿…è¦ãªæ–‡å­—ã‚’ [x キー](x) を押ã—ã¦å‰Šé™¤ã—ã¾ã—ょã†ã€‚
+
+ 4. æ–‡ãŒæ­£ã—ããªã‚‹ã¾ã§ ステップ 2 ã‹ã‚‰ 4 を繰り返ã—ã¾ã—ょã†ã€‚
+
+ãã® ã†ã†ã•㎠㯠ã¤ã¤ãã ã‚’ ã“ãˆãˆã¦ã¦ ã¨ã³ã¯ã­ãŸãŸ
+
+ 5. è¡ŒãŒæ­£ã—ããªã£ãŸã‚‰ã€ãƒ¬ãƒƒã‚¹ãƒ³ 1.4 ã¸é€²ã¿ã¾ã—ょã†ã€‚
+
+NOTE: å…¨ã¦ã®ãƒ¬ãƒƒã‚¹ãƒ³ã‚’通ã˜ã¦ã€é ­ã§è¦šãˆã‚ˆã†ã¨ã—ãªã„ã§ãã ã•ã„。
+ å®Ÿéš›ã«æ‰‹ã‚’å‹•ã‹ã™ã“ã¨ã§ã€ã‚ãªãŸã® Neovim ã«å¯¾ã™ã‚‹ç†è§£åº¦ã¯åºƒãŒã£ã¦ã„ãã¾ã™ã€‚
+ 復習ã®ãŸã‚ã«ã‚‚ã€ãŸã¾ã«ã“ã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã‚’やり直ã—ã¦ã¿ã¦ãã ã•ã„。
+
+# レッスン 1.4: テキスト編集 - 挿入
+
+** テキストを挿入(Insert)ã™ã‚‹ã«ã¯ `i`{normal} を押ã—ã¾ã™ã€‚ **
+
+ 1. 以下㮠✗ ã¨ç¤ºã•ã‚ŒãŸæœ€åˆã®è¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 2. 1行目を2行目ã¨åŒã˜æ§˜ã«ã™ã‚‹ãŸã‚ã«ã€ãƒ†ã‚­ã‚¹ãƒˆã‚’挿入ã—ãªã‘れã°
+ ãªã‚‰ãªã„ä½ç½®ã®æ¬¡ã®æ–‡å­—ã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã™ã€‚
+
+ 3. `i`{normal} キーを押ã—ã¦ã‹ã‚‰ã€è¿½åŠ ãŒå¿…è¦ãªæ–‡å­—をタイプã—ã¾ã—ょã†ã€‚
+
+ 4. é–“é•ã„を修正ã—ãŸã‚‰ `<Esc>`{normal} を押ã—ã¦ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã«æˆ»ã‚Šã€
+ æ­£ã—ã„æ–‡ã«ãªã‚‹æ§˜ã«ã‚¹ãƒ†ãƒƒãƒ— 2 ã‹ã‚‰ 4 を繰り返ã—ã¾ã—ょã†ã€‚
+
+ã“ã® ã«ã¯ 足り テキスト ㌠。
+ã“㮠行 ã«ã¯ å¹¾ã¤ã‹ 足りãªã„ テキスト ㌠ã‚る。
+
+ 5. æŒ¿å…¥ã®æ–¹æ³•ãŒã‚ã‹ã£ãŸã‚‰ãƒ¬ãƒƒã‚¹ãƒ³ 1.5 ã¸é€²ã¿ã¾ã—ょã†ã€‚
+
+# レッスン 1.5: テキスト編集 - 追加
+
+** テキストを追加(Append)ã™ã‚‹ã«ã¯ `A`{normal} を押ã—ã¾ã—ょã†ã€‚ **
+
+ 1. 以下㮠✗ ã¨ç¤ºã•ã‚ŒãŸæœ€åˆã®è¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+ カーソルãŒãã®è¡Œã®ã©ã®æ–‡å­—上ã«ã‚ã£ã¦ã‚‚ã‹ã¾ã„ã¾ã›ã‚“。
+
+ 2. [A](A) キー(大文字)を押ã—ã¦ã‹ã‚‰ã€è¿½åŠ ãŒå¿…è¦ãªæ–‡å­—をタイプã—ã¾ã—ょã†ã€‚
+
+ 3. テキストを追加ã—終ãˆãŸã‚‰ã€ `<Esc>`{normal} を押ã—ã¦ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã«æˆ»ã‚Šã¾ã—ょã†ã€‚
+
+ 4. 2行目㮠✗ ã¨ç¤ºã•れãŸå ´æ‰€ã¸ç§»å‹•ã—ã€ã‚¹ãƒ†ãƒƒãƒ— 2 ã‹ã‚‰ 3 を繰り返ã—ã¦
+ 文法を修正ã—ã¾ã—ょã†ã€‚
+
+ã“㮠行 ã«ã¯ é–“é•ã£ãŸ テキスト ㌠ã‚り
+ã“㮠行 ã«ã¯ é–“é•ã£ãŸ テキスト ㌠ã‚りã¾ã™ã€‚
+ã“ã“ ã«ã‚‚ é–“é•ã£ãŸ テキス
+ã“ã“ ã«ã‚‚ é–“é•ã£ãŸ テキスト ㌠ã‚りã¾ã™ã€‚
+
+ 5. テキストã®è¿½åŠ ãŒè»½å¿«ã«ãªã£ã¦ããŸã‚‰ãƒ¬ãƒƒã‚¹ãƒ³ 1.6 ã¸é€²ã¿ã¾ã—ょã†ã€‚
+
+# レッスン 1.6: ファイルã®ç·¨é›†
+
+** ファイルをä¿å­˜ã—ã¦çµ‚了ã™ã‚‹ã«ã¯ `:wq`{vim} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚ **
+
+
+!! NOTE: 以下ã®ã‚らゆるステップを行ã†å‰ã«ã€ã“ã®ãƒ¬ãƒƒã‚¹ãƒ³ã‚’全部読ã¿ã¾ã—ょã†!!
+
+ 1. レッスン 1.2 ã§ã‚„ã£ãŸã‚ˆã†ã« `:q!`{vim} をタイプã—ã¦ã€ã“ã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã‚’終了ã—ã¾ã™ã€‚
+ ã‚‚ã—ãã¯ã€åˆ¥ã®ã‚¿ãƒ¼ãƒŸãƒŠãƒ«ã«ã‚¢ã‚¯ã‚»ã‚¹ã§ãã‚‹å ´åˆã€ãã“ã§ä»¥ä¸‹ã®å†…容を行ã£ã¦ãã ã•ã„。
+
+ 2. シェルプロンプトã§ã“ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’タイプã—ã¾ã™:
+~~~ sh
+ $ nvim tutor
+~~~
+ 'nvim' ㌠Nvim エディタを起動ã™ã‚‹ã‚³ãƒžãƒ³ãƒ‰ã€'tutor' ã¯ç·¨é›†ã—ãŸã„
+ ファイルã®åå‰ã§ã™ã€‚変更ã§ãるファイルã®åå‰ã‚’使ã„ã¾ã—ょã†ã€‚
+
+ 3. å‰ã®ãƒ¬ãƒƒã‚¹ãƒ³ã§å­¦ã‚“ã ã‚ˆã†ã«ã€ãƒ†ã‚­ã‚¹ãƒˆã‚’挿入ã€å‰Šé™¤ã—ã¾ã™ã€‚
+
+ 4. 次ã®ã‚³ãƒžãƒ³ãƒ‰ã§å¤‰æ›´ã‚’ファイルã«ä¿å­˜ã—ã€Neovim を終了ã—ã¾ã™:
+~~~ cmd
+ :wq
+~~~
+ コマンドを実行ã™ã‚‹ã«ã¯ `<Enter>`{normal} を押ã•ãªã‘れã°ãªã‚Šã¾ã›ã‚“。
+
+ 5. ステップ 1 ã§ã“ã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã‚’終了ã—ãŸå ´åˆã¯
+ å†åº¦èµ·å‹•ã—ãŸå¾Œã€ä»¥ä¸‹ã®è¦ç´„ã¸é€²ã¿ã¾ã—ょã†ã€‚
+
+ 6. 以上ã®ã‚¹ãƒ†ãƒƒãƒ—を読んã§ç†è§£ã—ãŸä¸Šã§ã“れを実行ã—ã¾ã—ょã†ã€‚
+
+# レッスン 1 è¦ç´„
+
+ 1. カーソルã¯çŸ¢å°ã‚­ãƒ¼ã‚‚ã—ã㯠hjkl キーã§ç§»å‹•ã—ã¾ã™ã€‚
+ h (å·¦) j (下) k (上) l (å³)
+
+ 2. シェルプロンプトã‹ã‚‰Neovimã‚’èµ·å‹•ã™ã‚‹ã«ã¯ã“ã®ã‚ˆã†ã«ã‚¿ã‚¤ãƒ—ã—ã¾ã™:
+~~~ sh
+ $ nvim FILENAME
+~~~
+ 3. Vim を終了ã™ã‚‹ã«ã¯: `<Esc>`{normal} `:q!`{vim} `<Enter>`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™(変更を破棄)。
+ ã‚‚ã—ãã¯: `<Esc>`{normal} `:wq`{vim} `<Enter>`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™(変更をä¿å­˜)。
+
+ 4. カーソルã®ä¸‹ã®æ–‡å­—を削除ã™ã‚‹ã«ã¯ã€ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã§ `x`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚
+
+ 5. カーソルã®ä½ç½®ã«æ–‡å­—を挿入ã™ã‚‹ã«ã¯ã€ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã§ i ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚
+ `i`{normal} テキストã®ã‚¿ã‚¤ãƒ— `<Esc>`{normal} カーソルä½ç½®ã«è¿½åŠ 
+ `A`{normal} テキストã®è¿½åŠ  `<Esc>`{normal} 行末ã«è¿½åŠ 
+
+NOTE: `<Esc>`{normal} キーを押ã™ã¨ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã«ç§»è¡Œã—ã¾ã™ã€‚
+ ãã®éš›é–“é•ã£ãŸã‚Šã€å…¥åЛ途䏭ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’å–り消ã™ã“ã¨ãŒã§ãã¾ã™ã€‚
+
+ã•ã¦ã€ç¶šã‘ã¦ãƒ¬ãƒƒã‚¹ãƒ³ 2 ã‚’å§‹ã‚ã¾ã—ょã†ã€‚
+
+# レッスン 2.1: 削除コマンド
+
+** å˜èªžã®æœ«å°¾ã¾ã§ã‚’削除ã™ã‚‹ã«ã¯ `dw`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã—ょã†ã€‚ **
+
+ 1. 確実ã«ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã«ã™ã‚‹ãŸã‚ `<Esc>`{normal} を押ã—ã¾ã—ょã†ã€‚
+
+ 2. 以下㮠✗ ã¨ç¤ºã•れãŸè¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 3. 消ã—ãŸã„å˜èªžã®å…ˆé ­ã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 4. å˜èªžã‚’削除ã™ã‚‹ãŸã‚ã« [d](d)[w](w) ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã—ょã†ã€‚
+
+ã“ã® æ–‡ ç´™ ã«ã¯ ã„ãã¤ã‹ã® ãŸã®ã—ã„ å¿…è¦ã®ãªã„ å˜èªž ㌠å«ã¾ã‚Œã¦ ã„ã¾ã™ã€‚
+
+ 5. 3 ã‹ã‚‰ 4 ã¾ã§ã‚’æ–‡ãŒæ­£ã—ããªã‚‹ã¾ã§ç¹°ã‚Šè¿”ã—ã€ãƒ¬ãƒƒã‚¹ãƒ³ 2.2 ã¸é€²ã¿ã¾ã—ょã†ã€‚
+
+# レッスン 2.2: ãã®ä»–ã®å‰Šé™¤ã‚³ãƒžãƒ³ãƒ‰
+
+** è¡Œã®æœ«å°¾ã¾ã§ã‚’削除ã™ã‚‹ã«ã¯ `d$`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã—ょã†ã€‚ **
+
+ 1. 確実ã«ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã«ã™ã‚‹ãŸã‚ `<Esc>`{normal} を押ã—ã¾ã—ょã†ã€‚
+
+ 2. 以下㮠✗ ã¨ç¤ºã•れãŸè¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 3. æ­£ã—ã„æ–‡ã®æœ«å°¾ã¸ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†(最åˆã® 。 ã®å¾Œã§ã™)。
+
+ 4. 行末ã¾ã§å‰Šé™¤ã™ã‚‹ãŸã‚ã« `d$`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã—ょã†ã€‚
+
+誰ã‹ãŒã“ã®è¡Œã®æœ€å¾Œã‚’2度タイプã—ã¾ã—ãŸã€‚ 2度タイプã—ã¾ã—ãŸã€‚
+
+ 5. ã©ã†ã„ã†ã“ã¨ã‹ç†è§£ã™ã‚‹ãŸã‚ã«ã€ãƒ¬ãƒƒã‚¹ãƒ³ 2.3 ã¸é€²ã¿ã¾ã—ょã†ã€‚
+
+# レッスン 2.3: オペレータã¨ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³
+
+テキストã«å¤‰æ›´ã‚’加ãˆã‚‹å¤šãã®ã‚³ãƒžãƒ³ãƒ‰ã¯[オペレータ](operator)ã¨[モーション](navigation)ã‹ã‚‰ãªã‚Šã¾ã™ã€‚
+削除(Delete)コマンド [d](d) ã®ã‚ªãƒšãƒ¬ãƒ¼ã‚¿ã¯æ¬¡ã®æ§˜ã«ãªã£ã¦ã„ã¾ã™:
+
+ d モーション
+
+ ãれãžã‚Œ:
+ d - 削除コマンド。
+ モーション - 何ã«å¯¾ã—ã¦åƒãã‹ã‘ã‚‹ã‹(ä»¥ä¸‹ã«æŒ™ã’ã¾ã™)。
+
+ モーション一覧ã®ä¸€éƒ¨:
+ [w](w) - 次ã®å˜èªžã®å…ˆé ­ã¾ã§ã€‚(カーソルä½ç½®ã®å˜èªžã®å…ˆé ­ã‚’除ã)
+ [e](e) - 次ã®å˜èªžã®æœ«å°¾ã¾ã§ã€‚(カーソルä½ç½®ã®å˜èªžã®æœ«å°¾ã‚’å«ã‚€)
+ [$]($) - 行末ã¾ã§ã€‚(カーソルä½ç½®ã®å˜èªžã®æœ«å°¾ã‚’å«ã‚€)
+
+ ã¤ã¾ã‚Š `de`{normal} ã¨ã‚¿ã‚¤ãƒ—ã™ã‚‹ã¨ã€ã‚«ãƒ¼ã‚½ãƒ«ä½ç½®ã‹ã‚‰å˜èªžã®çµ‚ã‚りã¾ã§ã‚’削除ã—ã¾ã™ã€‚
+
+NOTE: 冒険ã—ãŸã„人ã¯ã€ãƒŽãƒ¼ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã«ã¦ã‚ªãƒšãƒ¬ãƒ¼ã‚¿ãªã—ã«ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ã‚’押ã—ã¦ã¿ã¾ã—ょã†ã€‚
+ カーソルãŒç›®çš„語一覧ã§ç¤ºã•れるä½ç½®ã«ç§»å‹•ã™ã‚‹ã¯ãšã§ã™ã€‚
+
+# レッスン 2.4: モーションã«ã‚«ã‚¦ãƒ³ãƒˆã‚’使用ã™ã‚‹
+
+** 何回も繰り返ã—行ã„ãŸã„ã®ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ã®å‰ã«ãã®å›žæ•°ã‚’タイプã—ã¾ã™ã€‚ **
+
+ 1. 以下㮠✓ ã¨ç¤ºã•れãŸè¡Œã®å…ˆé ­ã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã™ã€‚
+
+ 2. `2w`{normal} をタイプã—ã¦å˜èªž2ã¤åˆ†å…ˆã«ç§»å‹•ã—ã¾ã™ã€‚
+
+ 3. `3e`{normal} をタイプã—ã¦3ã¤ç›®ã®å˜èªžã®çµ‚端ã«ç§»å‹•ã—ã¾ã™ã€‚
+
+ 4. `0`{normal} ([ゼロ](0))をタイプã—ã¦è¡Œé ­ã«ç§»å‹•ã—ã¾ã™ã€‚
+
+ 5. ステップ 2 㨠3 ã‚’é•ã†æ•°å€¤ã‚’使ã£ã¦ç¹°ã‚Šè¿”ã—ã¾ã™ã€‚
+
+This is just a line with words you can move around in.
+
+ 6. レッスン 2.5 ã«é€²ã¿ã¾ã—ょã†ã€‚
+
+# レッスン 2.5: より多ãを削除ã™ã‚‹ãŸã‚ã«ã‚«ã‚¦ãƒ³ãƒˆã‚’使用ã™ã‚‹
+
+** オペレータã¨ã‚«ã‚¦ãƒ³ãƒˆã‚’タイプã™ã‚‹ã¨ã€ãã®æ“作ãŒè¤‡æ•°å›žç¹°ã‚Šè¿”ã•れã¾ã™ã€‚ **
+
+既述ã®å‰Šé™¤ã®ã‚ªãƒšãƒ¬ãƒ¼ã‚¿ã¨ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ã®çµ„ã¿åˆã‚ã›ã«ã‚«ã‚¦ãƒ³ãƒˆã‚’追加ã™ã‚‹ã“ã¨ã§ã€
+より多ãã®å‰Šé™¤ãŒè¡Œãˆã¾ã™:
+ d 数値 モーション
+
+ 1. ✗ ã¨ç¤ºã•れãŸè¡Œã®æœ€åˆã®å¤§æ–‡å­—ã®å˜èªžã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 2. 大文字ã®å˜èªž2ã¤ã‚’ `d2w`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¦å‰Šé™¤ã—ã¾ã™ã€‚
+
+ 3. 連続ã—ãŸå¤§æ–‡å­—ã®å˜èªžã‚’ã€ç•°ãªã‚‹ã‚«ã‚¦ãƒ³ãƒˆã‚’指定ã—ãŸ1ã¤ã®ã‚³ãƒžãƒ³ãƒ‰ã§å‰Šé™¤ã—ã€
+ ステップ 1 㨠2 を繰り返ã—ã¾ã™ã€‚
+
+ã“ã®ABC DE行ã®FGHI JK LMN OPå˜èªžã¯Q RS TUV綺麗ã«ãªã£ãŸã€‚
+
+# レッスン 2.6: è¡Œã®æ“作
+
+** 行全体を削除ã™ã‚‹ã«ã¯ `dd`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚ **
+
+行全体を削除ã™ã‚‹é »åº¦ãŒå¤šã„ã®ã§ã€Viã®ãƒ‡ã‚¶ã‚¤ãƒŠãƒ¼ã¯è¡Œã®
+削除を d ã®2回タイプã¨ã„ã†ç°¡å˜ãªã‚‚ã®ã«æ±ºã‚ã¾ã—ãŸã€‚
+
+ 1. 以下ã®è©©ã®2行目ã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã™ã€‚
+
+ 2. [dd](dd) ã¨ã‚¿ã‚¤ãƒ—ã—ã¦è¡Œã‚’削除ã—ã¾ã™ã€‚
+
+ 3. ã•らã«4行目ã«ç§»å‹•ã—ã¾ã™ã€‚
+
+ 4. `2dd`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¦2行を削除ã—ã¾ã™ã€‚
+
+1) 薔薇ã¯èµ¤ã
+2) æ³¥ã¯æ¥½ã—ã„
+3) è«ã¯é’ã
+4) ç§ã¯è»Šã‚’ã‚‚ã£ã¦ã„ã‚‹
+5) æ™‚è¨ˆãŒæ™‚刻を告ã’ã‚‹
+6) ç ‚ç³–ã¯ç”˜ã
+7) ãã—ã¦è²´æ–¹ã‚‚
+
+# Lesson 2.7: THE UNDO COMMAND
+
+** 最後ã®ã‚³ãƒžãƒ³ãƒ‰ã‚’å–り消ã™(Undo)ã«ã¯ `u`{normal} を押ã—ã¾ã™ã€‚`U`{normal} ã¯è¡Œå…¨ä½“ã®å–り消ã—ã§ã™ã€‚ **
+
+ 1. 以下㮠✗ ã¨ç¤ºã•れãŸè¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã€æœ€åˆã®é–“é•ã„ã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 2. `x`{normal} をタイプã—ã¦æœ€åˆã®ã„らãªã„文字を削除ã—ã¾ã—ょã†ã€‚
+
+ 3. ã§ã¯ã€`u`{normal} をタイプã—ã¦æœ€å¾Œã«å®Ÿè¡Œã—ãŸã‚³ãƒžãƒ³ãƒ‰ã‚’å–り消ã—ã¦ã—ã¾ã„ã—ょã†ã€‚
+
+ 4. 今度ã¯ã€`x`{normal} を使用ã—ã¦è¡Œå†…ã®èª¤ã‚Šã‚’å…¨ã¦ä¿®æ­£ã—ã¾ã—ょã†ã€‚
+
+ 5. 大文字㮠`U`{normal} をタイプã—ã¦ã€è¡Œã‚’å…ƒã®çŠ¶æ…‹ã«æˆ»ã—ã¾ã—ょã†ã€‚
+
+ 6. `u`{normal} をタイプã—ã¦ç›´å‰ã® `U`{normal} コマンドをå–り消ã—ã¾ã—ょã†ã€‚
+
+ 7. ã§ã¯ã‚³ãƒžãƒ³ãƒ‰ã‚’å†å®Ÿè¡Œã™ã‚‹ã®ã« `<C-r>`{normal} (Ctrl + R)を数回
+ タイプã—ã¦ã¿ã¾ã—ょã†(å–り消ã—ã®å–り消ã—)。
+
+ã“ã®ã®è¡Œã®ã®é–“é•ã„を修正々ã—ã€å¾Œã§ãれらã®ä¿®æ­£ã‚’ã‚’å–り消ã—ã¾ã¾ã™ã™ã€‚
+
+ 8. ã“れã¯ã¨ã¦ã‚‚便利ãªã‚³ãƒžãƒ³ãƒ‰ã§ã™ã€‚ã•ãレッスン 2 è¦ç´„ã¸é€²ã¿ã¾ã—ょã†ã€‚
+
+# レッスン 2 è¦ç´„
+
+ 1. カーソルä½ç½®ã‹ã‚‰æ¬¡ã®å˜èªžã¾ã§ã‚’削除: `dw`{normal}
+
+ 2. カーソルä½ç½®ã‹ã‚‰è¡Œã®æœ«å°¾ã¾ã§ã‚’削除: `d$`{normal}
+
+ 3. 行全体を削除: `dd`{normal}
+
+ 4. モーションを繰り返ã™ã«ã¯æ•°å€¤ã‚’付与: `2w`{normal}
+
+ 5. 変更ã«ç”¨ã„るコマンドã®å½¢å¼ã¯:
+
+ オペレータ [数値] モーション
+
+ ãれãžã‚Œ:
+
+ オペレータ - オペレータ - 削除 d ã®é¡žã§ä½•ã‚’ã™ã‚‹ã‹
+ [数値] - ãã®ã‚³ãƒžãƒ³ãƒ‰ã‚’何回繰り返ã™ã‹
+ モーション - テキストã®ä½•ã«å¯¾ã—ã¦åƒãã‹ã‘ã‚‹ã‹ã€ä¾‹ãˆã°:
+ [w](w) (å˜èªž),
+ [$]($) (行末), ãªã©ã€‚
+
+ 6. 行ã®å…ˆé ­ã«ç§»å‹•ã™ã‚‹ã«ã¯ã‚¼ãƒ­ã‚’使用ã—ã¾ã™: [0](0)
+
+ 7. å‰å›žã®å‹•作をå–り消ã—: `u`{normal} (å°æ–‡å­— u)
+ 行全体ã®å¤‰æ›´ã‚’å–り消ã—: `U`{normal} (大文字 U)
+ å–り消ã—ã®å–り消ã—: `<C-r>`{normal} (Ctrl + R)
+
+# レッスン 3.1: 貼り付ã‘コマンド
+
+** 最後ã«å‰Šé™¤ã•れãŸè¡Œã‚’カーソルã®å¾Œã«è²¼ã‚Šä»˜ã‘ã‚‹(Put)ã«ã¯ `p`{normal} をタイプã—ã¾ã™ã€‚ **
+
+ 1. ✓ ã¨ç¤ºã•れãŸä»¥ä¸‹ã®æœ€åˆã®è¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 2. `dd`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¦è¡Œã‚’削除ã—ã€Neovim ã®ãƒ¬ã‚¸ã‚¹ã‚¿ã«æ ¼ç´ã—ã¾ã—ょã†ã€‚
+
+ 3. 削除ã—ãŸè¡ŒãŒæœ¬æ¥ã‚ã‚‹ã¹ãä½ç½®ã®ä¸Šã®è¡Œã§ã‚ã‚‹ c) 行ã¾ã§ã€ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã•ã›ã¾ã—ょã†ã€‚
+
+ 4. `p`{normal} をタイプã—ã¦æ ¼ç´ã—ãŸè¡Œã‚’カーソルã®ä¸‹ã«æˆ»ã—ã¾ã™ã€‚
+
+ 5. é †ç•ªãŒæ­£ã—ããªã‚‹æ§˜ã«ã‚¹ãƒ†ãƒƒãƒ— 2 ã‹ã‚‰ 4 を繰り返ã—ã¾ã—ょã†ã€‚
+
+d) 貴方も学ã¶ã“ã¨ãŒã§ãã‚‹ã‹?
+b) è«ã¯é’ã
+c) 知æµã¨ã¯å­¦ã¶ã‚‚ã®
+a) 薔薇ã¯èµ¤ã
+
+NOTE: `P`{normal} (大文字 P)ã¨ã‚¿ã‚¤ãƒ—ã™ã‚‹ã“ã¨ã§ã€ã‚«ãƒ¼ã‚½ãƒ«ã®å‰ã«è²¼ã‚Šä»˜ã‘る事もã§ãã¾ã™ã€‚
+
+# レッスン 3.2: ç½®ãæ›ãˆã‚³ãƒžãƒ³ãƒ‰
+
+** カーソルã®ä¸‹ã®æ–‡å­—ã‚’ x ã«ç½®ãæ›ãˆã‚‹(Replace)ã«ã¯ `rx`{normal} をタイプã—ã¾ã™ã€‚ **
+
+ 1. 以下㮠✗ ã¨ç¤ºã•ã‚ŒãŸæœ€åˆã®è¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 2. 最åˆã®é–“é•ã„ã®å…ˆé ­ã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 3. `r`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã€é–“é•ã£ã¦ã„ã‚‹æ–‡å­—ã‚’ç½®ãæ›ãˆã‚‹ã€æ­£ã—ã„æ–‡å­—をタイプã—ã¾ã—ょã†ã€‚
+
+ 4. 最åˆã®è¡ŒãŒæ­£ã—ããªã‚‹ã¾ã§ã‚¹ãƒ†ãƒƒãƒ— 2 ã‹ã‚‰ 3 を繰り返ã—ã¾ã—ょã†ã€‚
+
+ã“ã®åˆã‚’人力ã—ãŸæ™‚ã­ã€ãã®äººã¯å¹¾ã¤ã‹å•é•ã£ãŸã‚­ãƒ¼ã‚’押ã—ã‚‚ã—ãŸ!
+ã“ã®è¡Œã‚’入力ã—ãŸæ™‚ã«ã€ãã®äººã¯å¹¾ã¤ã‹é–“é•ã£ãŸã‚­ãƒ¼ã‚’押ã—ã¾ã—ãŸ!
+
+ 5. ã•ãã€ãƒ¬ãƒƒã‚¹ãƒ³ 3.3 ã¸é€²ã¿ã¾ã—ょã†ã€‚
+
+NOTE: 実際ã«è©¦ã—ã¾ã—ょã†ã€‚決ã—ã¦è¦šãˆã‚‹ã ã‘ã«ã¯ã—ãªã„ã“ã¨ã€‚
+
+# レッスン 3.3: 変更オペレータ
+
+** å˜èªžã®æœ«å°¾ã¾ã§ã‚’変更(Change)ã™ã‚‹ã«ã¯ `ce`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚ **
+
+ 1. 以下㮠✗ ã¨ç¤ºã•ã‚ŒãŸæœ€åˆã®è¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 2. "lubw" ã® "u" ã®ä½ç½®ã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 3. `ce`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã€æ­£ã—ã„å˜èªžã‚’タイプã—ã¾ã—ょã†(ã“ã®å ´åˆ "ine" ã¨ã‚¿ã‚¤ãƒ—)。
+
+ 4. `<Esc>`{normal} をタイプã—ã¦ã‹ã‚‰æ¬¡ã®é–“é•ã„(変更ã™ã¹ã文字ã®å…ˆé ­)ã«ç§»å‹•ã—ã¾ã™ã€‚
+
+ 5. 最åˆã®è¡ŒãŒæ¬¡ã®è¡Œã®æ§˜ã«ãªã‚‹ã¾ã§ã‚¹ãƒ†ãƒƒãƒ— 3 㨠4 を繰り返ã—ã¾ã™ã€‚
+
+This lubw has a few wptfd that mrrf changing usf the change operator.
+This line has a few words that need changing using the change operator.
+
+ce ã¯å˜èªžã‚’削除ã—ãŸå¾Œã€æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã«å…¥ã‚‹ã“ã¨ã«æ³¨æ„ã—ã¾ã—ょã†ã€‚
+
+# レッスン 3.4: `c`{normal} を使用ã—ãŸãã®ä»–ã®å¤‰æ›´
+
+** 変更オペレータã¯ã€å‰Šé™¤ã¨åŒã˜æ§˜ã«ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ã‚’使用ã—ã¾ã™ã€‚ **
+
+ 1. 変更オペレータã¯ã€å‰Šé™¤ã¨åŒã˜ã‚ˆã†ãªå‹•作をã—ã¾ã™ã€‚ãã®å½¢å¼ã¯
+
+ c [数値] モーション
+
+ 2. モーションもåŒã˜ã§ã€`w`{normal} (å˜èªž) ã‚„ `$`{normal} (行末ã¾ã§)ã¨ã„ã£ãŸã‚‚ã®ã§ã™ã€‚
+
+ 3. 以下㮠✗ ã¨ç¤ºã•ã‚ŒãŸæœ€åˆã®è¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 4. 最åˆã®é–“é•ã„ã¸ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 5. `c$`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¦è¡Œã®æ®‹ã‚Šã‚’ï¼’è¡Œç›®ã®æ§˜ã«ã—ã€`<Esc>`{normal} を押ã—ã¾ã—ょã†ã€‚
+
+The end of this line needs some help to make it like the second.
+The end of this line needs to be corrected using the c$ command.
+
+NOTE: タイプ中ã®é–“é•ã„ã¯ãƒãƒƒã‚¯ã‚¹ãƒšãƒ¼ã‚¹ã‚­ãƒ¼ã‚’使ã£ã¦ç›´ã™ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+
+# レッスン 3 è¦ç´„
+
+ 1. æ—¢ã«å‰Šé™¤ã•れãŸãƒ†ã‚­ã‚¹ãƒˆã‚’å†é…ç½®ã™ã‚‹ã«ã¯ã€[p](p) をタイプã—ã¾ã™ã€‚
+ ã“れã¯å‰Šé™¤ã•れãŸãƒ†ã‚­ã‚¹ãƒˆã‚’カーソルã®å¾Œã«æŒ¿å…¥ã—ã¾ã™(行å˜ä½ã§å‰Šé™¤ã•れãŸã®ãªã‚‰ã°ã€
+ カーソルã®ã‚る次ã®è¡Œã«æŒ¿å…¥ã•れã¾ã™)。
+
+ 2. カーソルã®ä¸‹ã®æ–‡å­—ã‚’ç½®ãæ›ãˆã‚‹ã«ã¯ã€[r](r) をタイプã—ãŸå¾Œã€
+ ãã‚Œã‚’ç½®ãæ›ãˆã‚‹æ–‡å­—をタイプã—ã¾ã™ã€‚
+
+ 3. [変更オペレータ](c)ã§ã¯ã‚«ãƒ¼ã‚½ãƒ«ä½ç½®ã‹ã‚‰ç‰¹å®šã®ãƒ¢ãƒ¼ã‚·ãƒ§ãƒ³ã§æŒ‡å®šã•れる終端ã¾ã§ã‚’
+ 変更ã™ã‚‹ã“ã¨ãŒå¯èƒ½ã§ã™ã€‚例ãˆã° `ce`{normal} ãªã‚‰ã°ã‚«ãƒ¼ã‚½ãƒ«ä½ç½®ã‹ã‚‰å˜èªžã®
+ 終ã‚りã¾ã§ã€`c$`{normal} ãªã‚‰ã°è¡Œã®çµ‚ã‚りã¾ã§ã‚’変更ã—ã¾ã™ã€‚
+
+ 4. 変更コマンドã®å½¢å¼ã¯
+
+ c [数値] モーション
+
+ã•ãã€æ¬¡ã®ãƒ¬ãƒƒã‚¹ãƒ³ã¸é€²ã¿ã¾ã—ょã†ã€‚
+
+# レッスン 4.1: ä½ç½®ã¨ãƒ•ã‚¡ã‚¤ãƒ«ã®æƒ…å ±
+
+** ファイル内ã§ã®ä½ç½®ã¨ãƒ•ァイルã®çŠ¶æ…‹ã‚’è¡¨ç¤ºã™ã‚‹ã«ã¯ `<C-g>`{normal} をタイプã—ã¾ã™ã€‚
+ ファイル内ã®ã‚る行ã«ç§»å‹•ã™ã‚‹ã«ã¯ `G`{normal} をタイプã—ã¾ã™ã€‚ **
+
+NOTE: ステップを実行ã™ã‚‹å‰ã«ã€ã“ã®ãƒ¬ãƒƒã‚¹ãƒ³å…¨ã¦ã«ç›®ã‚’通ã—ã¾ã—ょã†!!
+
+ 1. `<Ctrl>`{normal} を押ã—ãŸã¾ã¾ `g`{normal} を押ã—ã¾ã—ょã†ã€‚ã“ã®æ“作を `<C-g>`{normal} ã¨å‘¼ã‚“ã§ã„ã¾ã™ã€‚
+ ページã®ä¸€ç•ªä¸‹ã«ãƒ•ァイルåã¨è¡Œç•ªå·ãŒè¡¨ç¤ºã•れるã¯ãšã§ã™ã€‚
+ ステップ 3ã®ãŸã‚ã«è¡Œç•ªå·ã‚’覚ãˆã¦ãŠãã¾ã—ょã†ã€‚
+
+NOTE: ç”»é¢ã®å³ä¸‹éš…ã«ã‚«ãƒ¼ã‚½ãƒ«ã®ä½ç½®ãŒè¡¨ç¤ºã•れã¦ã„ã‚‹ã‹ã‚‚ã—れã¾ã›ã‚“。
+ ã“れ㯠['ruler']('ruler') オプションを設定ã™ã‚‹ã“ã¨ã§è¡¨ç¤ºã•れã¾ã™ã€‚
+
+ 2. ãƒ•ã‚¡ã‚¤ãƒ«ã®æœ€ä¸‹è¡Œã«ç§»å‹•ã™ã‚‹ãŸã‚ã« [G](G) をタイプã—ã¾ã—ょã†ã€‚
+ ファイルã®å…ˆé ­ã«ç§»å‹•ã™ã‚‹ã«ã¯ [gg](gg) ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã—ょã†ã€‚
+
+ 3. å…ˆã»ã©ã®è¡Œã®ç•ªå·ã‚’タイプ㗠`G`{normal} をタイプã—ã¾ã—ょã†ã€‚
+ 最åˆã« `<C-g>`{normal} を押ã—ãŸè¡Œã«æˆ»ã£ã¦æ¥ã‚‹ã¯ãšã§ã™ã€‚
+
+ 4. è‡ªä¿¡ãŒæŒã¦ãŸã‚‰ã‚¹ãƒ†ãƒƒãƒ— 1 ã‹ã‚‰ 3 を実行ã—ã¾ã—ょã†ã€‚
+
+# レッスン 4.2: 検索コマンド
+
+** 語å¥ã‚’検索ã™ã‚‹ã«ã¯ `/`{normal} ã¨ã€å‰æ–¹æ¤œç´¢ã™ã‚‹èªžå¥ã‚’タイプã—ã¾ã™ã€‚ **
+
+ 1. ノーマルモード㧠`/`{normal} ã¨ã„ã†æ–‡å­—をタイプã—ã¾ã™ã€‚ç”»é¢ä¸€ç•ªä¸‹ã« `:`{normal} コマンドã¨
+ åŒã˜æ§˜ã« カーソルãŒç¾ã‚Œã‚‹ã“ã¨ã«æ°—ã¥ãã§ã—ょã†ã€‚
+
+ 2. ã§ã¯ã€'errroor' `<Enter>`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã—ょã†ã€‚ã“ã‚ŒãŒæ¤œç´¢ã—ãŸã„å˜èªžã§ã™ã€‚
+
+ 3. åŒã˜èªžå¥ã‚’ã‚‚ã†ä¸€åº¦æ¤œç´¢ã™ã‚‹ã¨ã㯠å˜ã« [n](n) をタイプã—ã¾ã™ã€‚
+ 逆方å‘ã«èªžå¥ã‚’検索ã™ã‚‹ã¨ã㯠[N](N) をタイプã—ã¾ã™ã€‚
+
+ 4. 逆方å‘ã«èªžå¥ã‚’検索ã™ã‚‹å ´åˆã¯ã€`/`{normal} ã®ä»£ã‚り㫠[?](?) コマンドを使用ã—ã¾ã™ã€‚
+
+ 5. å…ƒã®å ´æ‰€ã«æˆ»ã‚‹ã«ã¯ `<C-o>`{normal} (`<Ctrl>`{normal} を押ã—ç¶šã‘ãªãŒã‚‰ `o`{normal} をタイプ)ã‚’
+ タイプã—ã¾ã™ã€‚ã•ã‚‰ã«æˆ»ã‚‹ã«ã¯ã“れを繰り返ã—ã¾ã™ã€‚`<C-i>`{normal} ã¯å‰æ–¹å‘ã§ã™ã€‚
+
+"errroor" 㯠error ã¨ã‚¹ãƒšãƒ«ãŒé•ã„ã¾ã™; errroor ã¯ã„ã‚ゆる error ã§ã™ã€‚
+
+NOTE: 検索ãŒãƒ•ァイルã®çµ‚ã‚りã«é”ã™ã‚‹ã¨ã€ã‚ªãƒ—ション ['wrapscan']('wrapscan') ãŒè¨­å®šã•れã¦ã„ã‚‹å ´åˆã¯ã€
+ ファイルã®å…ˆé ­ã‹ã‚‰æ¤œç´¢ã‚’続行ã—ã¾ã™ã€‚
+
+# レッスン 4.3: 対応ã™ã‚‹æ‹¬å¼§ã‚’検索
+
+** 対応ã™ã‚‹ ),] ã‚„ } を検索ã™ã‚‹ã«ã¯ `%`{normal} をタイプã—ã¾ã™ã€‚ **
+
+ 1. 下㮠✓ ã§ç¤ºã•れãŸè¡Œã§ (,[ ã‹ { ã®ã©ã‚Œã‹ã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 2. ãã“ã§ [%](%) ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã—ょã†ã€‚
+
+ 3. カーソルã¯å¯¾å¿œã™ã‚‹æ‹¬å¼§ã«ç§»å‹•ã™ã‚‹ã¯ãšã§ã™ã€‚
+
+ 4. 最åˆã®æ‹¬å¼§ã«ç§»å‹•ã™ã‚‹ã«ã¯ `%`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã—ょã†ã€‚
+
+ 5. ä»–ã® (,),[,],{ ã‚„ } ã§ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã€`%`{normal} ãŒä½•ã‚’ã—ã¦ã„ã‚‹ã‹ç¢ºèªã—ã¾ã—ょã†ã€‚
+
+This ( is a test line with ('s, ['s ] and {'s } in it. ))
+
+NOTE: ã“ã®æ©Ÿèƒ½ã¯æ‹¬å¼§ãŒä¸€è‡´ã—ã¦ã„ãªã„プログラムをデãƒãƒƒã‚°ã™ã‚‹ã®ã«ã¨ã¦ã‚‚役立ã¡ã¾ã™!
+
+# レッスン 4.4: 代替コマンド
+
+** "old" ã‚’ "new" ã«ç½®æ›(Substitute)ã™ã‚‹ã«ã¯ `:s/old/new/g` ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚ **
+
+ 1. 以下㮠✗ ã¨ç¤ºã•れãŸè¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 2. 次ã®ã‚ˆã†ã«ã‚¿ã‚¤ãƒ—ã—ã¾ã™
+~~~ cmd
+ :s/thee/the/
+~~~
+ NOTE: [:s](:s) コマンドã¯ãã®è¡Œã§æœ€åˆã«è¦‹ã¤ã‹ã£ãŸã‚‚ã®ã«ã ã‘
+ 行ã‚れるã“ã¨ã«æ°—ã‚’ã¤ã‘ã¾ã—ょã†ã€‚
+
+ 3. ã•らã«ã€æ¬¡ã®ã‚ˆã†ã«ã‚¿ã‚¤ãƒ—ã—ã¾ã™
+~~~ cmd
+ :s/thee/the/g
+~~~
+ 追加ã—㟠g [フラグ](:s_flags)ã¯è¡Œå…¨ä½“ã‚’ç½®æ›ã™ã‚‹ã“ã¨ã‚’æ„味ã—ã¾ã™ã€‚
+ ã“ã®å¤‰æ›´ã¯ãã®è¡Œã§è¦‹ã¤ã‹ã£ãŸå…¨ã¦ã®ç®‡æ‰€ã«å¯¾ã—ã¦è¡Œã‚れã¾ã™ã€‚
+
+Usually thee best time to see thee flowers is in thee spring.
+
+ 4. 複数行ã‹ã‚‰è¦‹ã¤ã‹ã‚‹æ–‡å­—ã®å…¨ã¦ã®ç®‡æ‰€ã‚’変更ã™ã‚‹ã«ã¯
+~~~ cmd
+ :#,#s/old/new/g
+~~~
+ #,# ã«ã¯ç½®ãæ›ãˆã‚‹ç¯„囲ã®é–‹å§‹ã¨çµ‚了ã®è¡Œç•ªå·ã‚’指定ã™ã‚‹ã€‚
+ (例ãˆã°ã€`1,3`ã¯1行目ã‹ã‚‰3行目をæ„味ã—ã¾ã™ã€‚)
+
+~~~ cmd
+ :%s/old/new/g
+~~~
+ ファイル全体ã§è¦‹ã¤ã‹ã‚‹ã‚‚ã®ã«å¯¾ã—ã¦å¤‰æ›´ã™ã‚‹ã€‚
+~~~ cmd
+ :%s/old/new/gc
+~~~
+ ファイル全体ã§è¦‹ã¤ã‹ã‚‹ã‚‚ã®ã«å¯¾ã—ã¦ã€1ã¤1ã¤ç¢ºèªã‚’ã¨ã‚ŠãªãŒã‚‰å¤‰æ›´ã™ã‚‹ã€‚
+
+NOTE: ç½®ãæ›ãˆãŸã„テキストをビジュアルモードã§é¸æŠžã™ã‚‹ã“ã¨ã‚‚ã§ãã¾ã™ã€‚
+ ã“れã«ã¤ã„ã¦ã¯å°‘ã—後ã®ãƒ¬ãƒƒã‚¹ãƒ³ã§èª¬æ˜Žã—ã¾ã™ã€‚
+
+# レッスン 4 è¦ç´„
+
+ 1. `<C-g>`{normal} ã¯ãƒ•ァイルã§ã®ä½ç½®ã¨ãƒ•ァイルã®è©³ç´°ã‚’表示ã—ã¾ã™ã€‚
+ `G`{normal} ã¯ãƒ•ã‚¡ã‚¤ãƒ«ã®æœ€ä¸‹è¡Œã«ç§»å‹•ã—ã¾ã™ã€‚
+ 数値 `G`{normal} ã¯ãã®è¡Œã«ç§»å‹•ã—ã¾ã™ã€‚
+ `gg`{normal} ã¯å…ˆé ­è¡Œã«ç§»å‹•ã—ã¾ã™ã€‚
+
+ 2. `/`{normal} ã®å¾Œã«èªžå¥ã‚’タイプã™ã‚‹ã¨å‰æ–¹ã«èªžå¥ã‚’検索ã—ã¾ã™ã€‚
+ `?`{normal} ã®å¾Œã«èªžå¥ã‚’タイプã™ã‚‹ã¨å¾Œæ–¹ã«èªžå¥ã‚’検索ã—ã¾ã™ã€‚
+ 検索ã®å¾Œã® `n`{normal} ã¯åŒã˜æ–¹å‘ã®æ¬¡ã®æ¤œç´¢ã‚’ã€`N`{normal} ã¯é€†æ–¹å‘ã®æ¤œç´¢ã‚’ã—ã¾ã™ã€‚
+ `<C-o>`{normal} ã¯å ´æ‰€ã‚’å‰ã«ç§»ã—ã€`<C-i>`{normal} ã¯å ´æ‰€ã‚’次ã«ç§»å‹•ã—ã¾ã™ã€‚
+
+ 3. (,),[,],{, ã‚‚ã—ã㯠} 上ã«ã‚«ãƒ¼ã‚½ãƒ«ãŒã‚る状態㧠`%`{normal} をタイプã™ã‚‹ã¨
+ 対ã«ãªã‚‹æ–‡å­—ã¸ç§»å‹•ã—ã¾ã™ã€‚
+
+ 4. ç¾åœ¨è¡Œã®æœ€åˆã® old ã‚’ new ã«ç½®æ›ã™ã‚‹ã€‚
+~~~ cmd
+ :s/old/new
+~~~
+ ç¾åœ¨è¡Œã®å…¨ã¦ã® old ã‚’ new ã«ç½®æ›ã™ã‚‹ã€‚
+~~~ cmd
+ :s/old/new/g
+~~~
+ 2ã¤ã® # 行ã®é–“ã§èªžå¥ã‚’ç½®æ›ã™ã‚‹ã€‚
+~~~ cmd
+ :#,#s/old/new/g
+~~~
+ ファイルã®ä¸­ã®å…¨ã¦ã®æ¤œç´¢èªžå¥ã‚’ç½®æ›ã™ã‚‹ã€‚
+~~~ cmd
+ :%s/old/new/g
+~~~
+ 'c' を加ãˆã‚‹ã¨ç½®æ›ã®åº¦ã«ç¢ºèªã‚’求ã‚る。
+~~~ cmd
+ :%s/old/new/gc
+~~~
+
+# レッスン 5.1: 外部コマンドを実行ã™ã‚‹æ–¹æ³•
+
+** `:!`{vim} ã®å¾Œã«å®Ÿè¡Œã™ã‚‹å¤–部コマンドをタイプã—ã¾ã™ã€‚ **
+
+ 1. ç”»é¢ã®æœ€ä¸‹éƒ¨ã«ã‚«ãƒ¼ã‚½ãƒ«ãŒç§»å‹•ã™ã‚‹ã‚ˆã†ã€æ…£ã‚Œè¦ªã—ã‚“ã  `:`{normal} をタイプã—ã¾ã—ょã†ã€‚
+ ã“れã§ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³å‘½ä»¤ãŒã‚¿ã‚¤ãƒ—ã§ãる様ã«ãªã‚Šã¾ã™ã€‚
+
+ 2. ã“ã“ã§ [!](!cmd) ã¨ã„ã†æ–‡å­—(感嘆符)をタイプã—ã¾ã—ょã†ã€‚
+ ã“れã§å¤–部シェルコマンドãŒå®Ÿè¡Œã§ãる様ã«ãªã‚Šã¾ã™ã€‚
+
+ 3. 例ã¨ã—㦠"!" ã«ç¶šã‘㦠"ls" ã¨ã‚¿ã‚¤ãƒ—ã— `<Enter>`{normal} を押ã—ã¾ã—ょã†ã€‚
+ シェルプロンプトã®ã‚ˆã†ã«ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã®ä¸€è¦§ãŒè¡¨ç¤ºã•れるã¯ãšã§ã™ã€‚
+
+NOTE: ã“ã®æ–¹æ³•ã«ã‚ˆã£ã¦ã‚らゆるコマンドãŒå®Ÿè¡Œã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+ ã‚‚ã¡ã‚ん引数も与ãˆã‚‰ã‚Œã¾ã™ã€‚
+
+NOTE: å…¨ã¦ã® `:`{vim} コマンド㯠`<Enter>`{normal} を押ã—ã¦çµ‚了ã—ãªã‘れã°ãªã‚Šã¾ã›ã‚“。
+
+# レッスン 5.2: ãã®ä»–ã®ãƒ•ã‚¡ã‚¤ãƒ«ã¸æ›¸ãè¾¼ã¿
+
+** ファイルã¸å¤‰æ›´ã‚’ä¿å­˜ã™ã‚‹ã«ã¯ `:w`{vim} ファイルå ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚ **
+
+ 1. ディレクトリã®ä¸€è¦§ã‚’å¾—ã‚‹ãŸã‚ã« `:!{unix:(ls),win:(dir)}`{vim} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã—ょã†ã€‚
+ ã“ã®ã‚㨠`<Enter>`{normal} を押ã™ã®ã¯æ—¢ã«ã”存知ã§ã™ã­ã€‚
+
+ 2. TEST ã®ã‚ˆã†ã«ã€ãã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«ç„¡ã„ファイルåを一ã¤é¸ã³ã¾ã™ã€‚
+
+ 3. 次ã®ã‚ˆã†ã«ã‚¿ã‚¤ãƒ—ã—ã¾ã—ょã†:
+~~~ cmd
+ :w TEST
+~~~
+ (TEST ã¯ã€é¸ã‚“ã ãƒ•ァイルåã§ã™ã€‚)
+
+ 4. ã“れã«ã‚ˆã‚Šãƒ•ァイル全体㌠TEST ã¨ã„ã†åå‰ã§ä¿å­˜ã•れã¾ã™ã€‚
+ ã‚‚ã†ä¸€åº¦ `:!{unix:(ls),win:(dir)}`{vim} ã¨ã‚¿ã‚¤ãƒ—ã—ã¦ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã‚’確èªã—ã¦ã¿ã¾ã—ょã†ã€‚
+
+NOTE: ã“ã“ã§ Neovim を終了ã—ã€`nvim TEST` ã§èµ·å‹•ã™ã‚‹ã¨ã€ä¿å­˜ã—ãŸæ™‚ã®
+ ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã®è¤‡è£½ãŒã§ã上ãŒã‚‹ã¯ãšã§ã™ã€‚
+
+ 5. ã•らã«ã€æ¬¡ã®ã‚ˆã†ã«ã‚¿ã‚¤ãƒ—ã—ã¦ãƒ•ァイルを消ã—ã¾ã—ょã†:
+~~~ cmd
+ :!{unix:(rm),win:(del)} TEST
+~~~
+# レッスン 5.3: é¸æŠžã—ãŸæ›¸ãè¾¼ã¿
+
+** ファイルã®ä¸€éƒ¨ã‚’ä¿å­˜ã™ã‚‹ã«ã¯ã€`v`{normal} モーション㨠`:w ファイルå`{vim} をタイプã—ã¾ã™ã€‚ **
+
+ 1. ã“ã®è¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã™ã€‚
+
+ 2. [v](v) を押ã—ã€ä»¥ä¸‹ã®ç¬¬5é …ç›®ã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã™ã€‚
+ テキストãŒå¼·èª¿è¡¨ç¤ºã•れるã®ã«æ³¨ç›®ã—ã¦ä¸‹ã•ã„。
+
+ 3. 文字 : を押ã™ã¨ã€ç”»é¢ã®æœ€ä¸‹éƒ¨ã«
+
+ `:'<,'>`{vim}
+
+ ãŒç¾ã‚Œã¾ã™ã€‚
+
+ 4. 次ã®ã‚ˆã†ã«ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚
+
+ `:w TEST`{vim}
+
+ TEST ã¯å­˜åœ¨ã—ãªã„ファイルåã§ã™ã€‚`<Enter>`{normal} を押ã™å‰ã«
+
+ `:'<,'>w TEST`{vim}
+
+ ã¨ãªã£ã¦ã„ã‚‹ã“ã¨ã‚’確èªã—ã¦ä¸‹ã•ã„。
+
+ 5. Vim 㯠TEST ã¨ã„ã†ãƒ•ァイルã«é¸æŠžã•れãŸè¡Œã‚’書ã込むã§ã—ょã†ã€‚
+ :`:!{unix:(ls),win:(dir)}`{vim} ã§ãれを確èªã—ã¾ã™ã€‚
+ ãれã¯å‰Šé™¤ã—ãªã„ã§ãŠã„ã¦ä¸‹ã•ã„。次ã®ãƒ¬ãƒƒã‚¹ãƒ³ã§ä½¿ç”¨ã—ã¾ã™ã€‚
+
+NOTE: [v](v) を押ã™ã¨ã€ãƒ“ジュアル(Visual)é¸æŠžãŒå§‹ã¾ã‚Šã¾ã™ã€‚カーソルを動ã‹ã™ã“ã¨ã§ã€
+ é¸æŠžç¯„å›²ã‚’å¤§ããã‚‚å°ã•ãã‚‚ã§ãã¾ã™ã€‚ã•らã«ã€ãã®é¸æŠžç¯„囲ã«å¯¾ã—ã¦
+ オペレータをé©ç”¨ã§ãã¾ã™ã€‚例ãˆã° `d`{normal} ã¯ãƒ†ã‚­ã‚¹ãƒˆã‚’削除ã—ã¾ã™ã€‚
+
+# レッスン 5.4: ファイルã®å–è¾¼ã¨åˆä½µ
+
+** ファイルã®ä¸­èº«ã‚’挿入ã™ã‚‹ã«ã¯ `:r ファイルå`{vim} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚ **
+
+ 1. カーソルをã“ã®è¡Œã®ã™ã上ã«åˆã‚ã›ã¾ã™ã€‚
+
+NOTE: ステップ 2 ã®å®Ÿè¡Œå¾Œã€ãƒ¬ãƒƒã‚¹ãƒ³ 5.3 ã®ãƒ†ã‚­ã‚¹ãƒˆãŒç¾ã‚Œã¾ã™ã€‚
+ 下ã«ä¸‹ãŒã£ã¦ã“ã®ãƒ¬ãƒƒã‚¹ãƒ³ã«ç§»å‹•ã—ã¾ã—ょã†ã€‚
+
+ 2. ã§ã¯ TEST ã¨ã„ã†ãƒ•ァイルを 次ã®ã‚³ãƒžãƒ³ãƒ‰ã§èª­ã¿è¾¼ã¿ã¾ã™ã€‚
+
+ `:r TEST`{vim}
+
+ ã“ã“ã§ã„ㆠTEST ã¯ä½¿ã†ãƒ•ァイルã®åå‰ã®ã“ã¨ã§ã™ã€‚
+ 読ã¿è¾¼ã¾ã‚ŒãŸãƒ•ァイルã¯ã€ã‚«ãƒ¼ã‚½ãƒ«è¡Œã®ä¸‹ã«ã‚りã¾ã™ã€‚
+
+ 3. å–り込んã ãƒ•ァイルを確èªã—ã¦ã¿ã¾ã—ょã†ã€‚カーソルを戻ã™ã¨ã€ãƒ¬ãƒƒã‚¹ãƒ³5.3 ã®
+ オリジナルã¨ãƒ•ァイルã«ã‚ˆã‚‹ã‚‚ã®ã®2ã¤ãŒã‚ã‚‹ã“ã¨ãŒã‚ã‹ã‚Šã¾ã™ã€‚
+
+ 4. 残りã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã®ç‚ºã«ã€`u`{normal} を押ã—ã¦æœ€å¾Œã®ã‚³ãƒžãƒ³ãƒ‰ã‚’å–り消ã—ã¾ã™ã€‚
+
+NOTE: 外部コマンドã®å‡ºåŠ›ã‚’èª­ã¿è¾¼ã‚€ã“ã¨ã‚‚ã§ãã¾ã™ã€‚例ãˆã°ã€
+
+ `:r !{unix:(ls),win:(dir)}`{vim}
+
+ 㯠`ls` コマンドã®å‡ºåŠ›ã‚’ã‚«ãƒ¼ã‚½ãƒ«ä»¥ä¸‹ã«èª­ã¿è¾¼ã¿ã¾ã™ã€‚
+
+# レッスン 5 è¦ç´„
+
+ 1. [:!command](:!cmd) ã«ã‚ˆã£ã¦ã€å¤–部コマンドを実行ã™ã‚‹ã€‚
+
+ よã使ã†ä¾‹:
+ `:!{unix:(ls ),win:(dir)}`{vim} - ディレクトリ内ã®ä¸€è¦§ã‚’見る。
+ `:!{unix:(rm ),win:(del)} ファイルå`{vim} - ファイルを削除ã™ã‚‹ã€‚
+
+ 2. [:w](:w) ファイルå ファイルå ã«ã‚ˆã£ã¦ãƒ•ァイルåã¨ã„ã†ãƒ•ァイルãŒãƒ‡ã‚£ã‚¹ã‚¯ã«æ›¸ãè¾¼ã¾ã‚Œã‚‹ã€‚
+
+ 3. [v](v) モーション ã§ :w ファイルå ã¨ã™ã‚‹ã¨ã€ãƒ“ã‚¸ãƒ¥ã‚¢ãƒ«é¸æŠžè¡ŒãŒãƒ•ァイルã«ä¿å­˜ã•れる。
+
+ 4. [:r](:r) ファイルå ã«ã‚ˆã‚Šãƒ•ァイルåã¨ã„ã†ãƒ•ァイルãŒãƒ‡ã‚£ã‚¹ã‚¯ã‚ˆã‚Šå–り込ã¾ã‚Œã€
+ カーソルä½ç½®ã®ä¸‹ã«æŒ¿å…¥ã•れる。
+
+ 5. {unix:([:r !ls](:r!) ),win:([:r !dir](:r!))} 㯠{unix:(ls),win:(dir)} コマンドã®
+ 出力をカーソルä½ç½®ä»¥ä¸‹ã«èª­ã¿è¾¼ã‚€ã€‚
+
+# レッスン 6.1: オープンコマンド
+
+** `o`{normal} をタイプã™ã‚‹ã¨ã€ã‚«ãƒ¼ã‚½ãƒ«ã®ä¸‹ã®è¡ŒãŒé–‹ã(Open)ã€æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã«å…¥ã‚Šã¾ã™ã€‚ **
+
+ 1. 以下㮠✓ ã¨ç¤ºã•ã‚ŒãŸæœ€åˆã®è¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã—ょã†ã€‚
+
+ 2. `o`{normal} (å°æ–‡å­—) をタイプã—ã¦ã€ã‚«ãƒ¼ã‚½ãƒ«ã®ä¸‹ã®è¡Œã‚’[é–‹ã](o)ã€æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã«å…¥ã‚Šã¾ã™ã€‚
+
+ 3. ã„ãã¤ã‹æ–‡å­—をタイプã—ã¦ã‹ã‚‰ã€æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã‚’終了ã™ã‚‹ç‚ºã« `<Esc>`{normal} ã‚’
+ タイプã—ã¾ã™ã€‚
+
+ `o`{normal} をタイプã™ã‚‹ã¨ã‚«ãƒ¼ã‚½ãƒ«ã¯é–‹ã„ãŸè¡Œã¸ç§»å‹•ã—æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã«å…¥ã‚Šã¾ã™ã€‚
+
+ 4. カーソルã®ä¸Šã®è¡Œã«æŒ¿å…¥ã™ã‚‹ã«ã¯ã€å°æ–‡å­—ã® `o`{normal} ã§ã¯ãªãã€
+ å˜ç´”ã«[大文字㮠O](O)をタイプã—ã¾ã™ã€‚次ã®è¡Œã§è©¦ã—ã¦ã¿ã¾ã—ょã†ã€‚
+
+ã“ã®è¡Œã®ä¸Šã¸æŒ¿å…¥ã™ã‚‹ã«ã¯ã€ã“ã®è¡Œã¸ã‚«ãƒ¼ã‚½ãƒ«ã‚’ç½®ã„㦠`O`{normal} をタイプã—ã¾ã™ã€‚
+
+# レッスン 6.2: 追加コマンド
+
+** ã‚«ãƒ¼ã‚½ãƒ«ã®æ¬¡ã®ä½ç½®ã‹ã‚‰ãƒ†ã‚­ã‚¹ãƒˆã‚’追加(Append)ã™ã‚‹ã«ã¯ `a`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚ **
+
+ 1. カーソルを ✗ ã§ç¤ºã•ã‚ŒãŸæœ€åˆã®è¡Œã¸ç§»å‹•ã—ã¾ã—ょã†ã€‚
+
+ 2. `e`{normal} を押ã—㦠"li" ã®çµ‚端部ã¾ã§ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã™ã€‚
+
+ 3. カーソルã®å¾Œã‚ã«ãƒ†ã‚­ã‚¹ãƒˆã‚’[追加](a)ã™ã‚‹ãŸã‚ã« `a`{normal} (å°æ–‡å­—) をタイプã—ã¾ã™ã€‚
+
+ 4. ãã®ä¸‹ã®è¡Œã®ã‚ˆã†ãªå˜èªžã«å®Œæˆã•ã›ã¾ã™ã€‚挿入モードを抜ã‘る為㫠`<Esc>`{normal} を押ã—ã¾ã™ã€‚
+
+ 5. `e`{normal} を使ã£ã¦æ¬¡ã®ä¸å®Œå…¨ãªå˜èªžã¸ç§»å‹•ã—ã€ã‚¹ãƒ†ãƒƒãƒ— 3 㨠4 を繰り返ã—ã¾ã™ã€‚
+
+This li will allow you to pract appendi text to a line.
+This line will allow you to practice appending text to a line.
+
+NOTE: [a](a), [i](i) 㨠[A](A) ã¯åŒã˜æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã¸ç§»ã‚Šã¾ã™ãŒã€æ–‡å­—ãŒæŒ¿å…¥ã•れるä½ç½®ã ã‘ãŒç•°ãªã‚Šã¾ã™ã€‚
+
+# レッスン 6.3: ãã®ä»–ã®ç½®æ›æ–¹æ³•
+
+** 1æ–‡å­—ä»¥ä¸Šã‚’ç½®ãæ›ãˆã‚‹(Replace)ã«ã¯å¤§æ–‡å­—ã® `R`{normal} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã—ょã†ã€‚ **
+
+ 1. 以下㮠✗ ã¨ç¤ºã•れãŸè¡Œã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã™ã€‚最åˆã® "xxx" ã®å…ˆé ­ã«ç§»å‹•ã—ã¾ã™ã€‚
+
+ 2. `R`{normal} ([大文字 R](R)) を押ã—ã¦ã€2è¡Œç›®ã®æ•°å€¤ã‚’タイプã™ã‚‹ã“ã¨ã§ã€"xxx" ãŒç½®æ›ã•れã¾ã™ã€‚
+
+ 3. ç½®æ›ãƒ¢ãƒ¼ãƒ‰ã‚’抜ã‘ã‚‹ã«ã¯ `<Esc>`{normal} を押ã—ã¾ã™ã€‚è¡Œã®æ®‹ã‚ŠãŒå¤‰æ›´ã•れã¦ã„ãªã„ã¾ã¾ã«
+ ãªã‚‹ã“ã¨ã«æ³¨æ„ã—ã¦ãã ã•ã„。
+
+ 4. 残ã£ãŸ "xxx" をステップを繰り返ã—ã¦ç½®æ›ã—ã¾ã—ょã†ã€‚
+
+Adding 123 to xxx gives you xxx.
+Adding 123 to 456 gives you 579.
+
+NOTE: ç½®æ›ãƒ¢ãƒ¼ãƒ‰ã¯æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã«ä¼¼ã¦ã„ã¾ã™ãŒã€å…¨ã¦ã®ã‚¿ã‚¤ãƒ—ã•ã‚ŒãŸæ–‡å­—ã¯
+ æ—¢å­˜ã®æ–‡å­—を削除ã—ã¾ã™ã€‚
+
+# レッスン 6.4: テキストã®ã‚³ãƒ”ーã¨ãƒšãƒ¼ã‚¹ãƒˆ
+
+** テキストã®ã‚³ãƒ”ー(Yank)ã«ã¯ã‚ªãƒšãƒ¬ãƒ¼ã‚¿ `y`{normal} ã‚’ã€ãƒšãƒ¼ã‚¹ãƒˆã«ã¯ `p`{normal} を使ã„ã¾ã™ã€‚ **
+
+ 1. ✓ ã¨ç¤ºã•れãŸè¡Œã¸ç§»å‹•ã—ã€ã‚«ãƒ¼ã‚½ãƒ«ã‚’ "a)" ã®å¾Œã«ç½®ã„ã¦ãŠãã¾ã™ã€‚
+
+ 2. `v`{normal} ã§ãƒ“ジュアルモードを開始ã—ã€"first" ã®æ‰‹å‰ã¾ã§ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã™ã€‚
+
+ 3. `y`{normal} をタイプã—ã¦å¼·èª¿è¡¨ç¤ºã•れãŸãƒ†ã‚­ã‚¹ãƒˆã‚’ [yank](yank) (コピー)ã—ã¾ã™ã€‚
+
+ 4. 次ã®è¡Œã®è¡Œæœ«ã¾ã§ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã—ã¾ã™: `j$`{normal}
+
+ 5. `p`{normal} を押ã—ã¦è²¼ã‚Šä»˜ã‘([put](put))ã¦ã‹ã‚‰ã€æ¬¡ã‚’タイプã—ã¾ã™: a second <ESC>
+
+ 6. `a`{normal} を押ã—ã¦ã‹ã‚‰ã€ "second" ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚ãã®å¾Œã€`<Esc>`{normal}ã‚’
+ 押ã—ã¦æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã‚’終了ã—ã¾ã™ã€‚
+
+ 7. ビジュアルモード㧠" item." ã‚’é¸æŠžã—ã€`y`{normal} ã§ yankã€æ¬¡ã®è¡Œã®è¡Œæœ«ã¾ã§ `j$`{normal} ã§
+ 移動ã—〠`p`{normal} ã§ãƒ†ã‚­ã‚¹ãƒˆã‚’ãã“ã« put ã—ã¾ã™ã€‚
+
+a) This is the first item.
+b)
+
+NOTE: `y`{normal} をオペレータã¨ã—ã¦ä½¿ã†ã“ã¨ã‚‚ã§ãã¾ã™ã€‚`yw`{normal} ã¯å˜èªžã‚’1㤠yank ã—ã¾ã™ã€‚
+
+NOTE: `P`{normal} を使用ã™ã‚‹ã¨ã‚«ãƒ¼ã‚½ãƒ«ã®å¾Œã§ã¯ãªãå‰ã« put ã§ãã¾ã™ã€‚
+
+# レッスン 6.5: オプションã®è¨­å®š
+
+** 検索や置æ›ã®éš›ã«å¤§æ–‡å­—/å°æ–‡å­—を無視ã™ã‚‹ã«ã¯ã€ã‚ªãƒ—ションを設定ã—ã¾ã™ã€‚ **
+
+Neovim ã«ã¯ã‚ãªãŸã®å¿…è¦ã«å¿œã˜ã¦è¨­å®šã§ãã‚‹ã€æ§˜ã€…ãªã‚ªãƒ—ションãŒç”¨æ„ã•れã¦ã„ã¾ã™ã€‚
+
+ 1. æ¬¡ã®æ§˜ã«å…¥åŠ›ã—㦠'ignore' を検索ã—ã¾ã—ょã†: `/ignore`
+ `n`{normal} を押ã—ã¦ä½•åº¦ã‹æ¤œç´¢ã‚’繰り返ã—ã¾ã™ã€‚
+
+ 2. æ¬¡ã®æ§˜ã«å…¥åŠ›ã—㦠'ic' (Ignore Case ã®ç•¥) オプションを設定ã—ã¾ã™:
+~~~ cmd
+ :set ic
+~~~
+ 3. ã§ã¯ `n`{normal} ã«ã‚ˆã£ã¦ã‚‚ã†1度 'ignore' を検索ã—ã¾ã™ã€‚
+ "Ignore"ã‚„"IGNORE"も見ã¤ã‘られるã“ã¨ã«æ°—ã¥ãã§ã—ょã†ã€‚
+
+ 4. 'hlsearch' 㨠'incsearch' オプションを設定ã—ã¾ã—ょã†:
+~~~ cmd
+ :set hls is
+~~~
+ 5. 検索コマンドをå†å…¥åŠ›ã—ã¦ã€ä½•ãŒèµ·ã“ã‚‹ã‹è¦‹ã¦ã¿ã¾ã—ょã†: /ignore <Enter>
+
+ 6. å¤§æ–‡å­—å°æ–‡å­—ã®åŒºåˆ¥ã‚’無効ã«ã™ã‚‹ã«ã¯æ¬¡ã®æ§˜ã«å…¥åŠ›ã—ã¾ã™:
+~~~ cmd
+ :set noic
+~~~
+ 7. オプションã®å€¤ã‚’å転ã™ã‚‹ã«ã¯ã€å…ˆé ­ã« "inv"を追加ã—ã¾ã™:
+~~~ cmd
+ :set invic
+~~~
+NOTE: マッãƒã®å¼·èª¿è¡¨ç¤ºã‚’ã‚„ã‚ã‚‹ã«ã¯æ¬¡ã®æ§˜ã«å…¥åŠ›ã—ã¾ã™:
+~~~ cmd
+ :nohlsearch
+~~~
+NOTE: 1ã¤ã®æ¤œç´¢ã‚³ãƒžãƒ³ãƒ‰ã ã‘å¤§æ–‡å­—å°æ–‡å­—ã®åŒºåˆ¥ã‚’ã‚„ã‚ãŸã„ãªã‚‰ã°ã€
+ 語å¥å†…ã§ [\c](/\c) を使用ã—ã¾ã™: /ignore\c <Enter>
+
+# レッスン 6 è¦ç´„
+
+ 1. `o`{normal} をタイプã™ã‚‹ã¨ã‚«ãƒ¼ã‚½ãƒ«ã®ä¸‹ã®è¡Œã‚’é–‹ã‘ã¦ã€ãã“ã§æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã«ãªã‚‹ã€‚
+ `O`{normal} をタイプã™ã‚‹ã¨ã‚«ãƒ¼ã‚½ãƒ«ã®ä¸Šã®è¡Œã§æŒ¿å…¥ãƒ¢ãƒ¼ãƒ‰ã«ãªã‚‹ã€‚
+
+ 2. ã‚«ãƒ¼ã‚½ãƒ«ä¸Šã®æ–‡å­—ã®æ¬¡ã‹ã‚‰ãƒ†ã‚­ã‚¹ãƒˆã‚’追加ã™ã‚‹ã«ã¯ `a`{normal} ã¨ã‚¿ã‚¤ãƒ—ã™ã‚‹ã€‚
+ 行末ã«ãƒ†ã‚­ã‚¹ãƒˆã‚’挿入ã™ã‚‹ã«ã¯ `A`{normal} をタイプã™ã‚‹ã€‚
+
+ 3. `e`{normal} コマンドã¯å˜èªžã®çµ‚端ã«ã‚«ãƒ¼ã‚½ãƒ«ã‚’移動ã™ã‚‹ã€‚
+
+ 4. `y`{normal} オペレータã¯ãƒ†ã‚­ã‚¹ãƒˆã‚’ yank (コピー)ã—ã€`p`{normal} ã¯ãれを put (ペースト)ã™ã‚‹ã€‚
+
+ 5. 大文字㮠`R`{normal} をタイプã™ã‚‹ã¨ç½®æ›ãƒ¢ãƒ¼ãƒ‰ã«å…¥ã‚Šã€`<Esc>`{normal} を押ã™ã¨æŠœã‘る。
+
+ 6. "[:set](:set) xxx" ã¨ã‚¿ã‚¤ãƒ—ã™ã‚‹ã¨ã‚ªãƒ—ション "xxx" ãŒè¨­å®šã•れる。
+
+ 'ic' 'ignorecase' 検索時ã«å¤§æ–‡å­—å°æ–‡å­—ã®åŒºåˆ¥ã—ãªã„
+ 'is' 'incsearch' 検索フレーズã«éƒ¨åˆ†ãƒžãƒƒãƒã—ã¦ã„る部分を表示ã™ã‚‹
+ 'hls' 'hlsearch' マッãƒã™ã‚‹ã™ã¹ã¦ã‚’強調表示ã™ã‚‹
+
+ 正称ã€çœç•¥å½¢ã€ã©ã¡ã‚‰ã®ã‚ªãƒ—ションåã§ã‚‚使用ã§ãる。
+
+ 7. オプションを無効ã«ã™ã‚‹ã«ã¯ "no" を付与ã™ã‚‹:
+~~~ cmd
+ :set noic
+~~~
+ 8. 先頭㫠"inv" オプションをå転ã™ã‚‹:
+~~~ cmd
+ :set invic
+~~~
+# レッスン 7.1: ヘルプコマンド
+
+** Use the online help system. **
+
+Neovim ã«ã¯åºƒç¯„ã«ã‚ãŸã‚‹ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ãƒ˜ãƒ«ãƒ—システムãŒã‚りã¾ã™ã€‚
+
+ヘルプを開始ã™ã‚‹ã«ã¯ã€æ¬¡ã®ä¸­ã§ã©ã‚Œã‹1ã¤ã‚’試ã—ã¦ã¿ã¾ã—ょã†:
+ - `<F1>`{normal} キーを押ã™(ã‚‚ã—ã‚ã‚‹ãªã‚‰ã°)。
+ - `:help`{vim} ã¨ã‚¿ã‚¤ãƒ—ã™ã‚‹ã€‚
+
+ヘルプウィンドウã®ãƒ†ã‚­ã‚¹ãƒˆã‚’読むã¨ã€ãƒ˜ãƒ«ãƒ—ã®å‹•作ãŒç†è§£ã§ãã¾ã™ã€‚
+ `<C-w><C-w>`{normal} ã¨ã‚¿ã‚¤ãƒ—ã™ã‚‹ã¨ ヘルプウィンドウã¸ã‚¸ãƒ£ãƒ³ãƒ—ã—ã¾ã™ã€‚
+ `:q`{vim} ã¨ã‚¿ã‚¤ãƒ—ã™ã‚‹ã¨ ヘルプウィンドウを閉ã˜ã‚‰ã‚Œã¾ã™ã€‚
+
+":help" コマンドã«å¼•数を与ãˆã‚‹ã“ã¨ã«ã‚ˆã‚Šã€ã‚らゆる題åã®ãƒ˜ãƒ«ãƒ—を見ã¤ã‘ã‚‹ã“ã¨
+ãŒã§ãã¾ã™ã€‚ã“れらを試ã—ã¦ã¿ã¾ã—ょã†(`<Enter>`{normal} をタイプã—忘れãªã„よã†ã«):
+~~~ cmd
+ :help w
+ :help c_CTRL-D
+ :help insert-index
+ :help user-manual
+~~~
+
+# レッスン 7.2: 起動スクリプトã®ä½œæˆ
+
+** Neovim ã®ç‰¹å¾´ã‚’発æ®ã™ã‚‹ **
+
+Neovim ã¯ã¨ã¦ã‚‚自由度ã®é«˜ã„エディタã§ã™ã€‚ã‚ãªãŸã®å¥½ããªã‚ˆã†ã«
+カスタマイズã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚より多ãã®æ©Ÿèƒ½ã‚’使ã„ã¯ã˜ã‚ã‚‹ã«ã¯
+"init.vim" ファイルを作æˆã—ã¾ã™ã€‚
+
+ 1. "init.vim" ファイルã®ç·¨é›†ã‚’é–‹å§‹ã—ã¾ã™ã€‚
+
+ `:call mkdir(stdpath('config'),'p')`{vim}
+ `:exe 'edit' stdpath('config').'/init.vim'`{vim}
+
+ 3. 以下ã®ã‚ˆã†ã«ãƒ•ã‚¡ã‚¤ãƒ«ã¸æ›¸ãè¾¼ã¿ã¾ã™ã€‚
+
+ `:w`{vim}
+
+ ã“ã® "init.vim" ファイルã¸ã€ãŠå¥½ã¿ã®è¨­å®šã‚’追加ã™ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚
+ より多ãã®æƒ…報を得るã«ã¯ `:help init.vim`{vim} ã¨ã‚¿ã‚¤ãƒ—ã—ã¾ã™ã€‚
+
+# レッスン 7.3: 補完
+
+** `<C-d>`{normal} 㨠`<Tab>`{normal} ã§ã‚³ãƒžãƒ³ãƒ‰ãƒ©ã‚¤ãƒ³ã‚’補完ã™ã‚‹ **
+
+ 1. ç¾åœ¨ã®ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã«åœ¨ã‚‹ã‚‚ã®ã‚’表示ã—ã¾ã™: `:!{unix:(ls),win:(dir)}`{vim}
+
+ 2. コマンドã®å…ˆé ­ã‚’タイプã—ã¾ã™: :e
+
+ 3. `<C-d>`{normal} を押ã™ã¨ Neovim 㯠"e" ã‹ã‚‰å§‹ã¾ã‚‹ã‚³ãƒžãƒ³ãƒ‰ã®ä¸€è¦§ã‚’表示ã—ã¾ã™ã€‚
+
+ 4. `<Tab>`{normal} ã¨ã‚¿ã‚¤ãƒ—ã™ã‚‹ã¨ Neoim 㯠":edit" ã¨ã„ã†ã‚³ãƒžãƒ³ãƒ‰åを補完ã—ã¾ã™ã€‚
+
+ 5. ã•らã«ç©ºç™½ã¨ã€æ—¢å­˜ã®ãƒ•ァイルåã®å§‹ã¾ã‚Šã‚’加ãˆã¾ã™: `:edit FIL`{vim}
+
+ 6. `<Tab>`{normal} を押ã™ã¨ Neovim ã¯åå‰ã‚’補完ã—ã¾ã™ã€‚("FIL" -> "FILE"ã€é‡è¤‡ã—ãªã„å ´åˆ)
+
+NOTE: 補完ã¯å¤šãã®ã‚³ãƒžãƒ³ãƒ‰ã§å‹•作ã—ã¾ã™ã€‚特㫠`:help`{vim} ã®éš›ã«å½¹ç«‹ã¡ã¾ã™ã€‚
+
+# レッスン 7 è¦ç´„
+
+ 1. ヘルプウィンドウを開ãã«ã¯ `:help`{vim} ã¨ã™ã‚‹ã‹ `<F1>`{normal} を押ã™ã€‚
+
+ 2. '知りãŸã„事' ã®ãƒ˜ãƒ«ãƒ—を検索ã™ã‚‹ã«ã¯ `:help '知りãŸã„事'`{vim} ã¨ã‚¿ã‚¤ãƒ—ã™ã‚‹ã€‚
+
+ 3. 別ã®ã‚¦ã‚£ãƒ³ãƒ‰ã‚¦ã¸ã‚¸ãƒ£ãƒ³ãƒ—ã™ã‚‹ã«ã¯ `<C-w><C-w>`{normal} ã¨ã‚¿ã‚¤ãƒ—ã™ã‚‹ã€‚
+
+ 4. ヘルプウィンドウを閉ã˜ã‚‹ã«ã¯ `:q`{vim} ã¨ã‚¿ã‚¤ãƒ—ã™ã‚‹ã€‚
+
+ 5. ãŠå¥½ã¿ã®è¨­å®šã‚’ä¿ã¤ã«ã¯ init.vim 起動スクリプトを作æˆã™ã‚‹ã€‚
+
+ 6. : command ã§å¯èƒ½ãªè£œå®Œã‚’見るã«ã¯ `<C-d>`{normal} をタイプã™ã‚‹ã€‚
+ 補完を使用ã™ã‚‹ã«ã¯ `<Tab>`{normal} を押ã™ã€‚
+
+# ãŠã‚りã«
+
+ã“れã«ã¦ Neovim ã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã‚’終ã‚りã¾ã™ã€‚エディタを簡å˜ã«ã€ã—ã‹ã‚‚充分ã«
+使ã†ã“ã¨ãŒã§ãるよã†ã«ã¨ã€Neovim ã®æŒã¤æ¦‚念ã®è¦ç‚¹ã®ã¿ã‚’ä¼ãˆã‚ˆã†ã¨ã—ã¾ã—ãŸã€‚
+Neovim ã«ã¯ã•らã«å¤šãã®ã‚³ãƒžãƒ³ãƒ‰ãŒã‚りã€ã“ã“ã§å…¨ã¦ã‚’説明ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“。
+ヘルプを沢山活用ã—ã¦ãã ã•ã„。オンライン上ã«ã‚‚æ•°å¤šã®æ•™æã‚„動画を
+見ã¤ã‘ã‚‹ã“ã¨ãŒã§ãã¾ã™ã€‚ã“ã“ã«ã„ãã¤ã‹ç´¹ä»‹ã—ã¾ã™:
+
+- *Learn Vim Progressively*:
+ https://yannesposito.com/Scratch/en/blog/Learn-Vim-Progressively/
+- *Learning Vim in 2014*:
+ https://benmccormick.org/learning-vim-in-2014/
+- *Vimcasts*:
+ http://vimcasts.org/
+- *Vim Video-Tutorials by Derek Wyatt*:
+ http://derekwyatt.org/vim/tutorials/
+- *Learn Vimscript the Hard Way*:
+ https://learnvimscriptthehardway.stevelosh.com/
+- *7 Habits of Effective Text Editing*:
+ https://www.moolenaar.net/habits.html
+- *vim-galore*:
+ https://github.com/mhinz/vim-galore
+- *vim-jp Vim日本語ドキュメント*
+ https://vim-jp.org/vimdoc-ja/
+
+ã‚‚ã—ã‚ãªãŸãŒæœ¬ãŒå¥½ããªã‚‰ã°ã€*Practical Vim* by Drew Neil ã‚’ãŠå‹§ã‚ã—ã¾ã™ã€‚
+(ç¶šç·¨ã§ã‚ã‚‹ *Modern Vim* ã«ã¯ Neovimã«ã¤ã„ã¦ã®å†…容もå«ã¾ã‚Œã¦ã„ã¾ã™ã€‚)
+
+ã“ã®ãƒãƒ¥ãƒ¼ãƒˆãƒªã‚¢ãƒ«ã¯ Colorado State University ã® Charles Smith ã®ã‚¢ã‚¤ãƒ‡ã‚¢
+を基ã«ã€Colorado School of Mines ã® Michael C. Pierce 㨠Robert K. Ware ã®
+両åã«ã‚ˆã£ã¦æ›¸ã‹ã‚Œã¾ã—ãŸã€‚ E-mail: bware@mines.colorado.edu.
+
+Modified for Vim by Bram Moolenaar.
+Modified for vim-tutor-mode by Felipe Morales.
+Modified for Neovim by Rory Nesbitt.
+
+Vim Tutor 翻訳
+ 日本語訳 æ¾æœ¬ 泰弘 <mattn.jp@gmail.com>
+ vim-jpãƒãƒ¼ãƒ  <https://github.com/vim-jp/lang-ja>
+ 監修 æ‘岡 太郎 <koron.kaoriya@gmail.com>
+Neovim Tutor 翻訳
+ 監修 ite-usagi <https://github.com/ite-usagi>
+
+// vim: nowrap
diff --git a/runtime/tutor/ja/vim-01-beginner.tutor.json b/runtime/tutor/ja/vim-01-beginner.tutor.json
new file mode 100644
index 0000000000..5af4d5da94
--- /dev/null
+++ b/runtime/tutor/ja/vim-01-beginner.tutor.json
@@ -0,0 +1,44 @@
+{
+ "expect": {
+ "104": "ãã® ã†ã•㎠㯠ã¤ã ã‚’ ã“ãˆã¦ ã¨ã³ã¯ã­ãŸ",
+ "126": "ã“㮠行 ã«ã¯ å¹¾ã¤ã‹ 足りãªã„ テキスト ㌠ã‚る。",
+ "127": "ã“㮠行 ã«ã¯ å¹¾ã¤ã‹ 足りãªã„ テキスト ㌠ã‚る。",
+ "145": "ã“㮠行 ã«ã¯ é–“é•ã£ãŸ テキスト ㌠ã‚りã¾ã™ã€‚",
+ "146": "ã“㮠行 ã«ã¯ é–“é•ã£ãŸ テキスト ㌠ã‚りã¾ã™ã€‚",
+ "147": "ã“ã“ ã«ã‚‚ é–“é•ã£ãŸ テキスト ㌠ã‚りã¾ã™ã€‚",
+ "148": "ã“ã“ ã«ã‚‚ é–“é•ã£ãŸ テキスト ㌠ã‚りã¾ã™ã€‚",
+ "217": "ã“ã® æ–‡ ã«ã¯ ã„ãã¤ã‹ã® å¿…è¦ã®ãªã„ å˜èªž ㌠å«ã¾ã‚Œã¦ ã„ã¾ã™ã€‚",
+ "233": "誰ã‹ãŒã“ã®è¡Œã®æœ€å¾Œã‚’2度タイプã—ã¾ã—ãŸã€‚",
+ "272": -1,
+ "291": "ã“ã®è¡Œã®å˜èªžã¯ç¶ºéº—ã«ãªã£ãŸã€‚",
+ "308": -1,
+ "309": -1,
+ "310": -1,
+ "311": -1,
+ "312": -1,
+ "313": -1,
+ "314": -1,
+ "335": "ã“ã®è¡Œã®é–“é•ã„を修正ã—ã€å¾Œã§ãれらã®ä¿®æ­£ã‚’ã‚’å–り消ã—ã¾ã™ã€‚",
+ "381": -1,
+ "382": -1,
+ "383": -1,
+ "384": -1,
+ "400": "ã“ã®è¡Œã‚’入力ã—ãŸæ™‚ã«ã€ãã®äººã¯å¹¾ã¤ã‹é–“é•ã£ãŸã‚­ãƒ¼ã‚’押ã—ã¾ã—ãŸ!",
+ "401": "ã“ã®è¡Œã‚’入力ã—ãŸæ™‚ã«ã€ãã®äººã¯å¹¾ã¤ã‹é–“é•ã£ãŸã‚­ãƒ¼ã‚’押ã—ã¾ã—ãŸ!",
+ "421": "This line has a few words that need changing using the change operator.",
+ "422": "This line has a few words that need changing using the change operator.",
+ "442": "The end of this line needs to be corrected using the c$ command.",
+ "443": "The end of this line needs to be corrected using the c$ command.",
+ "505": -1,
+ "524": -1,
+ "548": "Usually the best time to see the flowers is in the spring.",
+ "737": -1,
+ "742": -1,
+ "758": "This line will allow you to practice appending text to a line.",
+ "759": "This line will allow you to practice appending text to a line.",
+ "776": "Adding 123 to 456 gives you 579.",
+ "777": "Adding 123 to 456 gives you 579.",
+ "802": "a) This is the first item.",
+ "803": "b) This is the second item."
+ }
+}
diff --git a/scripts/bump_deps.lua b/scripts/bump_deps.lua
index 076ad374cf..c5294893e0 100755
--- a/scripts/bump_deps.lua
+++ b/scripts/bump_deps.lua
@@ -138,9 +138,10 @@ local function get_archive_info(repo, ref)
'Failed to download archive from GitHub'
)
- local shacmd = (vim.fn.executable('sha256sum') == 1
- and{ 'sha256sum', archive_path }
- or { 'shasum', '-a', '256', archive_path })
+ local shacmd = (
+ vim.fn.executable('sha256sum') == 1 and { 'sha256sum', archive_path }
+ or { 'shasum', '-a', '256', archive_path }
+ )
local archive_sha = run(shacmd):gmatch('%w+')()
return { url = archive_url, sha = archive_sha }
end
@@ -152,18 +153,7 @@ local function write_cmakelists_line(symbol, kind, value)
'sed',
'-i',
'-e',
- 's/'
- .. symbol
- .. '_'
- .. kind
- .. '.*$'
- .. '/'
- .. symbol
- .. '_'
- .. kind
- .. ' '
- .. value
- .. '/',
+ 's/' .. symbol .. '_' .. kind .. '.*$' .. '/' .. symbol .. '_' .. kind .. ' ' .. value .. '/',
deps_file,
}, 'Failed to write ' .. deps_file)
end
@@ -203,16 +193,13 @@ local function update_cmakelists(dependency, archive, comment)
p('Updating ' .. dependency.name .. ' to ' .. archive.url .. '\n')
write_cmakelists_line(dependency.symbol, 'URL', archive.url:gsub('/', '\\/'))
write_cmakelists_line(dependency.symbol, 'SHA256', archive.sha)
- run_die(
- {
- 'git',
- 'commit',
- deps_file,
- '-m',
- commit_prefix .. 'bump ' .. dependency.name .. ' to ' .. comment,
- },
- 'git failed to commit'
- )
+ run_die({
+ 'git',
+ 'commit',
+ deps_file,
+ '-m',
+ commit_prefix .. 'bump ' .. dependency.name .. ' to ' .. comment,
+ }, 'git failed to commit')
end
local function verify_cmakelists_committed()
@@ -318,9 +305,9 @@ function M.commit(dependency_name, commit)
end
function M.version(dependency_name, version)
- vim.validate{
- dependency_name={dependency_name,'s'},
- version={version,'s'},
+ vim.validate {
+ dependency_name = { dependency_name, 's' },
+ version = { version, 's' },
}
local dependency = assert(get_dependency(dependency_name))
verify_cmakelists_committed()
@@ -384,7 +371,7 @@ function M.submit_pr()
end
local function usage()
- local this_script = _G.arg[0]:match("[^/]*.lua$")
+ local this_script = _G.arg[0]:match('[^/]*.lua$')
print(([=[
Bump Nvim dependencies
@@ -421,13 +408,13 @@ local function parseargs()
elseif _G.arg[i] == '--pr' then
args.pr = true
elseif _G.arg[i] == '--branch' then
- args.branch = _G.arg[i+1]
+ args.branch = _G.arg[i + 1]
elseif _G.arg[i] == '--dep' then
- args.dep = _G.arg[i+1]
+ args.dep = _G.arg[i + 1]
elseif _G.arg[i] == '--version' then
- args.version = _G.arg[i+1]
+ args.version = _G.arg[i + 1]
elseif _G.arg[i] == '--commit' then
- args.commit = _G.arg[i+1]
+ args.commit = _G.arg[i + 1]
elseif _G.arg[i] == '--head' then
args.head = true
end
diff --git a/scripts/cdoc_grammar.lua b/scripts/cdoc_grammar.lua
new file mode 100644
index 0000000000..6a7610883b
--- /dev/null
+++ b/scripts/cdoc_grammar.lua
@@ -0,0 +1,87 @@
+--[[!
+LPEG grammar for C doc comments
+]]
+
+--- @class nvim.cdoc.Param
+--- @field kind 'param'
+--- @field name string
+--- @field desc? string
+
+--- @class nvim.cdoc.Return
+--- @field kind 'return'
+--- @field desc string
+
+--- @class nvim.cdoc.Note
+--- @field desc? string
+
+--- @alias nvim.cdoc.grammar.result
+--- | nvim.cdoc.Param
+--- | nvim.cdoc.Return
+--- | nvim.cdoc.Note
+
+--- @class nvim.cdoc.grammar
+--- @field match fun(self, input: string): nvim.cdoc.grammar.result?
+
+local lpeg = vim.lpeg
+local P, R, S = lpeg.P, lpeg.R, lpeg.S
+local Ct, Cg = lpeg.Ct, lpeg.Cg
+
+--- @param x vim.lpeg.Pattern
+local function rep(x)
+ return x ^ 0
+end
+
+--- @param x vim.lpeg.Pattern
+local function rep1(x)
+ return x ^ 1
+end
+
+--- @param x vim.lpeg.Pattern
+local function opt(x)
+ return x ^ -1
+end
+
+local nl = P('\r\n') + P('\n')
+local ws = rep1(S(' \t') + nl)
+
+local any = P(1) -- (consume one character)
+local letter = R('az', 'AZ') + S('_$')
+local ident = letter * rep(letter + R('09'))
+
+local io = P('[') * (P('in') + P('out') + P('inout')) * P(']')
+
+--- @param x string
+local function Pf(x)
+ return opt(ws) * P(x) * opt(ws)
+end
+
+--- @type table<string,vim.lpeg.Pattern>
+local v = setmetatable({}, {
+ __index = function(_, k)
+ return lpeg.V(k)
+ end,
+})
+
+local grammar = P {
+ rep1(P('@') * v.ats),
+
+ ats = v.at_param + v.at_return + v.at_deprecated + v.at_see + v.at_brief + v.at_note + v.at_nodoc,
+
+ at_param = Ct(
+ Cg(P('param'), 'kind') * opt(io) * ws * Cg(ident, 'name') * opt(ws * Cg(rep(any), 'desc'))
+ ),
+
+ at_return = Ct(Cg(P('return'), 'kind') * opt(S('s')) * opt(ws * Cg(rep(any), 'desc'))),
+
+ at_deprecated = Ct(Cg(P('deprecated'), 'kind')),
+
+ at_see = Ct(Cg(P('see'), 'kind') * ws * opt(Pf('#')) * Cg(rep(any), 'desc')),
+
+ at_brief = Ct(Cg(P('brief'), 'kind') * ws * Cg(rep(any), 'desc')),
+
+ at_note = Ct(Cg(P('note'), 'kind') * ws * Cg(rep(any), 'desc')),
+
+ at_nodoc = Ct(Cg(P('nodoc'), 'kind')),
+}
+
+return grammar --[[@as nvim.cdoc.grammar]]
diff --git a/scripts/cdoc_parser.lua b/scripts/cdoc_parser.lua
new file mode 100644
index 0000000000..5f0dc7be2c
--- /dev/null
+++ b/scripts/cdoc_parser.lua
@@ -0,0 +1,223 @@
+local cdoc_grammar = require('scripts.cdoc_grammar')
+local c_grammar = require('src.nvim.generators.c_grammar')
+
+--- @class nvim.cdoc.parser.param
+--- @field name string
+--- @field type string
+--- @field desc string
+
+--- @class nvim.cdoc.parser.return
+--- @field name string
+--- @field type string
+--- @field desc string
+
+--- @class nvim.cdoc.parser.note
+--- @field desc string
+
+--- @class nvim.cdoc.parser.brief
+--- @field kind 'brief'
+--- @field desc string
+
+--- @class nvim.cdoc.parser.fun
+--- @field name string
+--- @field params nvim.cdoc.parser.param[]
+--- @field returns nvim.cdoc.parser.return[]
+--- @field desc string
+--- @field deprecated? true
+--- @field since? string
+--- @field attrs? string[]
+--- @field nodoc? true
+--- @field notes? nvim.cdoc.parser.note[]
+--- @field see? nvim.cdoc.parser.note[]
+
+--- @class nvim.cdoc.parser.State
+--- @field doc_lines? string[]
+--- @field cur_obj? nvim.cdoc.parser.obj
+--- @field last_doc_item? nvim.cdoc.parser.param|nvim.cdoc.parser.return|nvim.cdoc.parser.note
+--- @field last_doc_item_indent? integer
+
+--- @alias nvim.cdoc.parser.obj
+--- | nvim.cdoc.parser.fun
+--- | nvim.cdoc.parser.brief
+
+--- If we collected any `---` lines. Add them to the existing (or new) object
+--- Used for function/class descriptions and multiline param descriptions.
+--- @param state nvim.cdoc.parser.State
+local function add_doc_lines_to_obj(state)
+ if state.doc_lines then
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+ local txt = table.concat(state.doc_lines, '\n')
+ if cur_obj.desc then
+ cur_obj.desc = cur_obj.desc .. '\n' .. txt
+ else
+ cur_obj.desc = txt
+ end
+ state.doc_lines = nil
+ end
+end
+
+--- @param line string
+--- @param state nvim.cdoc.parser.State
+local function process_doc_line(line, state)
+ line = line:gsub('^%s+@', '@')
+
+ local parsed = cdoc_grammar:match(line)
+
+ if not parsed then
+ if line:match('^ ') then
+ line = line:sub(2)
+ end
+
+ if state.last_doc_item then
+ if not state.last_doc_item_indent then
+ state.last_doc_item_indent = #line:match('^%s*') + 1
+ end
+ state.last_doc_item.desc = (state.last_doc_item.desc or '')
+ .. '\n'
+ .. line:sub(state.last_doc_item_indent or 1)
+ else
+ state.doc_lines = state.doc_lines or {}
+ table.insert(state.doc_lines, line)
+ end
+ return
+ end
+
+ state.last_doc_item_indent = nil
+ state.last_doc_item = nil
+
+ local kind = parsed.kind
+
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+
+ if kind == 'brief' then
+ state.cur_obj = {
+ kind = 'brief',
+ desc = parsed.desc,
+ }
+ elseif kind == 'param' then
+ state.last_doc_item_indent = nil
+ cur_obj.params = cur_obj.params or {}
+ state.last_doc_item = {
+ name = parsed.name,
+ desc = parsed.desc,
+ }
+ table.insert(cur_obj.params, state.last_doc_item)
+ elseif kind == 'return' then
+ cur_obj.returns = { {
+ desc = parsed.desc,
+ } }
+ state.last_doc_item_indent = nil
+ state.last_doc_item = cur_obj.returns[1]
+ elseif kind == 'deprecated' then
+ cur_obj.deprecated = true
+ elseif kind == 'nodoc' then
+ cur_obj.nodoc = true
+ elseif kind == 'since' then
+ cur_obj.since = parsed.desc
+ elseif kind == 'see' then
+ cur_obj.see = cur_obj.see or {}
+ table.insert(cur_obj.see, { desc = parsed.desc })
+ elseif kind == 'note' then
+ state.last_doc_item_indent = nil
+ state.last_doc_item = {
+ desc = parsed.desc,
+ }
+ cur_obj.notes = cur_obj.notes or {}
+ table.insert(cur_obj.notes, state.last_doc_item)
+ else
+ error('Unhandled' .. vim.inspect(parsed))
+ end
+end
+
+--- @param item table
+--- @param state nvim.cdoc.parser.State
+local function process_proto(item, state)
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+ cur_obj.name = item.name
+ cur_obj.params = cur_obj.params or {}
+
+ for _, p in ipairs(item.parameters) do
+ local param = { name = p[2], type = p[1] }
+ local added = false
+ for _, cp in ipairs(cur_obj.params) do
+ if cp.name == param.name then
+ cp.type = param.type
+ added = true
+ break
+ end
+ end
+
+ if not added then
+ table.insert(cur_obj.params, param)
+ end
+ end
+
+ cur_obj.returns = cur_obj.returns or { {} }
+ cur_obj.returns[1].type = item.return_type
+
+ for _, a in ipairs({
+ 'fast',
+ 'remote_only',
+ 'lua_only',
+ 'textlock',
+ 'textlock_allow_cmdwin',
+ }) do
+ if item[a] then
+ cur_obj.attrs = cur_obj.attrs or {}
+ table.insert(cur_obj.attrs, a)
+ end
+ end
+
+ cur_obj.deprecated_since = item.deprecated_since
+
+ -- Remove some arguments
+ for i = #cur_obj.params, 1, -1 do
+ local p = cur_obj.params[i]
+ if p.name == 'channel_id' or vim.tbl_contains({ 'lstate', 'arena', 'error' }, p.type) then
+ table.remove(cur_obj.params, i)
+ end
+ end
+end
+
+local M = {}
+
+--- @param filename string
+--- @return {} classes
+--- @return nvim.cdoc.parser.fun[] funs
+--- @return string[] briefs
+function M.parse(filename)
+ local funs = {} --- @type nvim.cdoc.parser.fun[]
+ local briefs = {} --- @type string[]
+ local state = {} --- @type nvim.cdoc.parser.State
+
+ local txt = assert(io.open(filename, 'r')):read('*all')
+
+ local parsed = c_grammar.grammar:match(txt)
+ for _, item in ipairs(parsed) do
+ if item.comment then
+ process_doc_line(item.comment, state)
+ else
+ add_doc_lines_to_obj(state)
+ if item[1] == 'proto' then
+ process_proto(item, state)
+ table.insert(funs, state.cur_obj)
+ end
+ local cur_obj = state.cur_obj
+ if cur_obj and not item.static then
+ if cur_obj.kind == 'brief' then
+ table.insert(briefs, cur_obj.desc)
+ end
+ end
+ state = {}
+ end
+ end
+
+ return {}, funs, briefs
+end
+
+-- M.parse('src/nvim/api/vim.c')
+
+return M
diff --git a/scripts/gen_eval_files.lua b/scripts/gen_eval_files.lua
index e331dd996e..f1bba5c0a2 100755
--- a/scripts/gen_eval_files.lua
+++ b/scripts/gen_eval_files.lua
@@ -1,7 +1,8 @@
+#!/usr/bin/env -S nvim -l
+
-- Generator for various vimdoc and Lua type files
-local DEP_API_METADATA = 'build/api_metadata.mpack'
-local DEP_API_DOC = 'runtime/doc/api.mpack'
+local DEP_API_METADATA = 'build/funcs_metadata.mpack'
--- @class vim.api.metadata
--- @field name string
@@ -17,6 +18,31 @@ local DEP_API_DOC = 'runtime/doc/api.mpack'
--- @field remote boolean
--- @field since integer
+local LUA_API_RETURN_OVERRIDES = {
+ nvim_buf_get_command = 'table<string,vim.api.keyset.command_info>',
+ nvim_buf_get_extmark_by_id = 'vim.api.keyset.get_extmark_item',
+ nvim_buf_get_extmarks = 'vim.api.keyset.get_extmark_item[]',
+ nvim_buf_get_keymap = 'vim.api.keyset.keymap[]',
+ nvim_get_autocmds = 'vim.api.keyset.get_autocmds.ret[]',
+ nvim_get_color_map = 'table<string,integer>',
+ nvim_get_command = 'table<string,vim.api.keyset.command_info>',
+ nvim_get_keymap = 'vim.api.keyset.keymap[]',
+ nvim_get_mark = 'vim.api.keyset.get_mark',
+
+ -- Can also return table<string,vim.api.keyset.hl_info>, however we need to
+ -- pick one to get some benefit.
+ -- REVISIT lewrus01 (26/01/24): we can maybe add
+ -- @overload fun(ns: integer, {}): table<string,vim.api.keyset.hl_info>
+ nvim_get_hl = 'vim.api.keyset.hl_info',
+
+ nvim_get_mode = 'vim.api.keyset.get_mode',
+ nvim_get_namespaces = 'table<string,integer>',
+ nvim_get_option_info = 'vim.api.keyset.get_option_info',
+ nvim_get_option_info2 = 'vim.api.keyset.get_option_info',
+ nvim_parse_cmd = 'vim.api.keyset.parse_cmd',
+ nvim_win_get_config = 'vim.api.keyset.win_config',
+}
+
local LUA_META_HEADER = {
'--- @meta _',
'-- THIS FILE IS GENERATED',
@@ -48,6 +74,16 @@ local LUA_OPTION_META_HEADER = {
'vim.wo = vim.wo',
}
+local LUA_VVAR_META_HEADER = {
+ '--- @meta _',
+ '-- THIS FILE IS GENERATED',
+ '-- DO NOT EDIT',
+ "error('Cannot require a meta file')",
+ '',
+ '--- @class vim.v',
+ 'vim.v = ...',
+}
+
local LUA_KEYWORDS = {
['and'] = true,
['end'] = true,
@@ -56,10 +92,12 @@ local LUA_KEYWORDS = {
['if'] = true,
['while'] = true,
['repeat'] = true,
+ ['true'] = true,
+ ['false'] = true,
}
local OPTION_TYPES = {
- bool = 'boolean',
+ boolean = 'boolean',
number = 'integer',
string = 'string',
}
@@ -76,6 +114,7 @@ local API_TYPES = {
LuaRef = 'function',
Dictionary = 'table<string,any>',
Float = 'number',
+ HLGroupID = 'number|string',
void = '',
}
@@ -170,44 +209,65 @@ end
--- @return table<string, vim.EvalFn>
local function get_api_meta()
- local mpack_f = assert(io.open(DEP_API_METADATA, 'rb'))
- local metadata = vim.mpack.decode(mpack_f:read('*all')) --[[@as vim.api.metadata[] ]]
local ret = {} --- @type table<string, vim.EvalFn>
- local doc_mpack_f = assert(io.open(DEP_API_DOC, 'rb'))
- local doc_metadata = vim.mpack.decode(doc_mpack_f:read('*all')) --[[@as table<string,vim.gen_vim_doc_fun>]]
-
- for _, fun in ipairs(metadata) do
- if fun.lua then
- local fdoc = doc_metadata[fun.name]
-
- local params = {} --- @type {[1]:string,[2]:string}[]
- for _, p in ipairs(fun.parameters) do
- local ptype, pname = p[1], p[2]
- params[#params + 1] = {
- pname,
- api_type(ptype),
- fdoc and fdoc.parameters_doc[pname] or nil,
- }
- end
+ local cdoc_parser = require('scripts.cdoc_parser')
- local r = {
- signature = 'NA',
- name = fun.name,
- params = params,
- returns = api_type(fun.return_type),
- deprecated = fun.deprecated_since ~= nil,
- }
+ local f = 'src/nvim/api'
- if fdoc then
- if #fdoc.doc > 0 then
- r.desc = table.concat(fdoc.doc, '\n')
+ local function include(fun)
+ if not vim.startswith(fun.name, 'nvim_') then
+ return false
+ end
+ if vim.tbl_contains(fun.attrs or {}, 'lua_only') then
+ return true
+ end
+ if vim.tbl_contains(fun.attrs or {}, 'remote_only') then
+ return false
+ end
+ return true
+ end
+
+ --- @type table<string,nvim.cdoc.parser.fun>
+ local functions = {}
+ for path, ty in vim.fs.dir(f) do
+ if ty == 'file' then
+ local filename = vim.fs.joinpath(f, path)
+ local _, funs = cdoc_parser.parse(filename)
+ for _, fn in ipairs(funs) do
+ if include(fn) then
+ functions[fn.name] = fn
end
- r.return_desc = (fdoc['return'] or {})[1]
end
+ end
+ end
- ret[fun.name] = r
+ for _, fun in pairs(functions) do
+ local deprecated = fun.deprecated_since ~= nil
+
+ local params = {} --- @type {[1]:string,[2]:string}[]
+ for _, p in ipairs(fun.params) do
+ params[#params + 1] = {
+ p.name,
+ api_type(p.type),
+ not deprecated and p.desc or nil,
+ }
end
+
+ local r = {
+ signature = 'NA',
+ name = fun.name,
+ params = params,
+ returns = api_type(fun.returns[1].type),
+ deprecated = deprecated,
+ }
+
+ if not deprecated then
+ r.desc = fun.desc
+ r.return_desc = fun.returns[1].desc
+ end
+
+ ret[fun.name] = r
end
return ret
end
@@ -235,12 +295,10 @@ end
--- @param fun vim.EvalFn
--- @param write fun(line: string)
local function render_api_meta(_f, fun, write)
- if not vim.startswith(fun.name, 'nvim_') then
- return
- end
-
write('')
+ local text_utils = require('scripts.text_utils')
+
if vim.startswith(fun.name, 'nvim__') then
write('--- @private')
end
@@ -251,10 +309,10 @@ local function render_api_meta(_f, fun, write)
local desc = fun.desc
if desc then
+ desc = text_utils.md_to_vimdoc(desc, 0, 0, 74)
for _, l in ipairs(split(norm_text(desc))) do
write('--- ' .. l)
end
- write('---')
end
local param_names = {} --- @type string[]
@@ -263,8 +321,11 @@ local function render_api_meta(_f, fun, write)
param_names[#param_names + 1] = p[1]
local pdesc = p[3]
if pdesc then
- local pdesc_a = split(norm_text(pdesc))
- write('--- @param ' .. p[1] .. ' ' .. p[2] .. ' ' .. pdesc_a[1])
+ local s = '--- @param ' .. p[1] .. ' ' .. p[2] .. ' '
+ local indent = #('@param ' .. p[1] .. ' ')
+ pdesc = text_utils.md_to_vimdoc(pdesc, #s, indent, 74, true)
+ local pdesc_a = split(vim.trim(norm_text(pdesc)))
+ write(s .. pdesc_a[1])
for i = 2, #pdesc_a do
if not pdesc_a[i] then
break
@@ -276,11 +337,10 @@ local function render_api_meta(_f, fun, write)
end
end
if fun.returns ~= '' then
- if fun.returns_desc then
- write('--- @return ' .. fun.returns .. ' : ' .. fun.returns_desc)
- else
- write('--- @return ' .. fun.returns)
- end
+ local ret_desc = fun.returns_desc and ' : ' .. fun.returns_desc or ''
+ ret_desc = text_utils.md_to_vimdoc(ret_desc, 0, 0, 74)
+ local ret = LUA_API_RETURN_OVERRIDES[fun.name] or fun.returns
+ write('--- @return ' .. ret .. ret_desc)
end
local param_str = table.concat(param_names, ', ')
@@ -290,8 +350,6 @@ end
--- @return table<string, vim.EvalFn>
local function get_api_keysets_meta()
local mpack_f = assert(io.open(DEP_API_METADATA, 'rb'))
-
- --- @diagnostic disable-next-line:no-unknown
local metadata = assert(vim.mpack.decode(mpack_f:read('*all')))
local ret = {} --- @type table<string, vim.EvalFn>
@@ -302,7 +360,7 @@ local function get_api_keysets_meta()
for _, k in ipairs(keysets) do
local params = {}
for _, key in ipairs(k.keys) do
- table.insert(params, {key..'?', api_type(k.types[key] or 'any')})
+ table.insert(params, { key .. '?', api_type(k.types[key] or 'any') })
end
ret[k.name] = {
signature = 'NA',
@@ -342,50 +400,45 @@ local function render_eval_meta(f, fun, write)
local params = process_params(fun.params)
- if fun.signature then
- write('')
- if fun.deprecated then
- write('--- @deprecated')
- end
-
- local desc = fun.desc
-
- if desc then
- --- @type string
- desc = desc:gsub('\n%s*\n%s*$', '\n')
- for _, l in ipairs(split(desc)) do
- l = l:gsub('^ ', ''):gsub('\t', ' '):gsub('@', '\\@')
- write('--- ' .. l)
- end
- end
+ write('')
+ if fun.deprecated then
+ write('--- @deprecated')
+ end
- local req_args = type(fun.args) == 'table' and fun.args[1] or fun.args or 0
+ local desc = fun.desc
- for i, param in ipairs(params) do
- local pname, ptype = param[1], param[2]
- local optional = (pname ~= '...' and i > req_args) and '?' or ''
- write(string.format('--- @param %s%s %s', pname, optional, ptype))
+ if desc then
+ --- @type string
+ desc = desc:gsub('\n%s*\n%s*$', '\n')
+ for _, l in ipairs(split(desc)) do
+ l = l:gsub('^ ', ''):gsub('\t', ' '):gsub('@', '\\@')
+ write('--- ' .. l)
end
+ end
- if fun.returns ~= false then
- write('--- @return ' .. (fun.returns or 'any'))
- end
+ local req_args = type(fun.args) == 'table' and fun.args[1] or fun.args or 0
- write(render_fun_sig(funname, params))
+ for i, param in ipairs(params) do
+ local pname, ptype = param[1], param[2]
+ local optional = (pname ~= '...' and i > req_args) and '?' or ''
+ write(string.format('--- @param %s%s %s', pname, optional, ptype))
+ end
- return
+ if fun.returns ~= false then
+ write('--- @return ' .. (fun.returns or 'any'))
end
- print('no doc for', funname)
+ write(render_fun_sig(funname, params))
end
---- @type table<string,true>
-local rendered_tags = {}
-
--- @param name string
--- @param fun vim.EvalFn
--- @param write fun(line: string)
local function render_sig_and_tag(name, fun, write)
+ if not fun.signature then
+ return
+ end
+
local tags = { '*' .. name .. '()*' }
if fun.tags then
@@ -396,7 +449,7 @@ local function render_sig_and_tag(name, fun, write)
local tag = table.concat(tags, ' ')
local siglen = #fun.signature
- local conceal_offset = 2*(#tags - 1)
+ local conceal_offset = 2 * (#tags - 1)
local tag_pad_len = math.max(1, 80 - #tag + conceal_offset)
if siglen + #tag > 80 then
@@ -419,24 +472,17 @@ local function render_eval_doc(f, fun, write)
return
end
- local desc = fun.desc
-
- if not desc then
+ if f:find('__%d+$') then
write(fun.signature)
- return
+ else
+ render_sig_and_tag(fun.name or f, fun, write)
end
- local name = fun.name or f
-
- if rendered_tags[name] then
- write(fun.signature)
- else
- render_sig_and_tag(name, fun, write)
- rendered_tags[name] = true
+ if not fun.desc then
+ return
end
- desc = vim.trim(desc)
- local desc_l = split(desc)
+ local desc_l = split(vim.trim(fun.desc))
for _, l in ipairs(desc_l) do
l = l:gsub('^ ', '')
if vim.startswith(l, '<') and not l:match('^<[^ \t]+>') then
@@ -473,7 +519,7 @@ local function render_option_default(d, vimdoc)
end
end
- if dt == "" or dt == nil or type(dt) == 'function' then
+ if dt == '' or dt == nil or type(dt) == 'function' then
dt = d.meta
end
@@ -481,22 +527,22 @@ local function render_option_default(d, vimdoc)
if not vimdoc then
v = vim.inspect(dt) --[[@as string]]
else
- v = type(dt) == 'string' and '"'..dt..'"' or tostring(dt)
+ v = type(dt) == 'string' and '"' .. dt .. '"' or tostring(dt)
end
--- @type table<string, string|false>
local envvars = {
TMPDIR = false,
VIMRUNTIME = false,
- XDG_CONFIG_HOME = vim.env.HOME..'/.local/config',
- XDG_DATA_HOME = vim.env.HOME..'/.local/share',
- XDG_STATE_HOME = vim.env.HOME..'/.local/state',
+ XDG_CONFIG_HOME = vim.env.HOME .. '/.local/config',
+ XDG_DATA_HOME = vim.env.HOME .. '/.local/share',
+ XDG_STATE_HOME = vim.env.HOME .. '/.local/state',
}
for name, default in pairs(envvars) do
local value = vim.env[name] or default
if value then
- v = v:gsub(vim.pesc(value), '$'..name)
+ v = v:gsub(vim.pesc(value), '$' .. name)
end
end
@@ -509,31 +555,55 @@ end
local function render_option_meta(_f, opt, write)
write('')
for _, l in ipairs(split(norm_text(opt.desc))) do
- write('--- '..l)
+ write('--- ' .. l)
end
- write('--- @type '..OPTION_TYPES[opt.type])
- write('vim.o.'..opt.full_name..' = '..render_option_default(opt.defaults))
+ write('--- @type ' .. OPTION_TYPES[opt.type])
+ write('vim.o.' .. opt.full_name .. ' = ' .. render_option_default(opt.defaults))
if opt.abbreviation then
- write('vim.o.'..opt.abbreviation..' = vim.o.'..opt.full_name)
+ write('vim.o.' .. opt.abbreviation .. ' = vim.o.' .. opt.full_name)
end
for _, s in pairs {
- {'wo', 'window'},
- {'bo', 'buffer'},
- {'go', 'global'},
+ { 'wo', 'window' },
+ { 'bo', 'buffer' },
+ { 'go', 'global' },
} do
local id, scope = s[1], s[2]
if vim.list_contains(opt.scope, scope) or (id == 'go' and #opt.scope > 1) then
- local pfx = 'vim.'..id..'.'
- write(pfx..opt.full_name..' = vim.o.'..opt.full_name)
+ local pfx = 'vim.' .. id .. '.'
+ write(pfx .. opt.full_name .. ' = vim.o.' .. opt.full_name)
if opt.abbreviation then
- write(pfx..opt.abbreviation..' = '..pfx..opt.full_name)
+ write(pfx .. opt.abbreviation .. ' = ' .. pfx .. opt.full_name)
end
end
end
end
+--- @param _f string
+--- @param opt vim.option_meta
+--- @param write fun(line: string)
+local function render_vvar_meta(_f, opt, write)
+ write('')
+
+ local desc = split(norm_text(opt.desc))
+ while desc[#desc]:match('^%s*$') do
+ desc[#desc] = nil
+ end
+
+ for _, l in ipairs(desc) do
+ write('--- ' .. l)
+ end
+
+ write('--- @type ' .. (opt.type or 'any'))
+
+ if LUA_KEYWORDS[opt.full_name] then
+ write("vim.v['" .. opt.full_name .. "'] = ...")
+ else
+ write('vim.v.' .. opt.full_name .. ' = ...')
+ end
+end
+
--- @param s string[]
--- @return string
local function scope_to_doc(s)
@@ -541,14 +611,14 @@ local function scope_to_doc(s)
global = 'global',
buffer = 'local to buffer',
window = 'local to window',
- tab = 'local to tab page'
+ tab = 'local to tab page',
}
if #s == 1 then
return m[s[1]]
end
assert(s[1] == 'global')
- return 'global or '..m[s[2]]..' |global-local|'
+ return 'global or ' .. m[s[2]] .. ' |global-local|'
end
-- @param o vim.option_meta
@@ -574,6 +644,21 @@ local function scope_more_doc(o)
return ''
end
+--- @param x string
+--- @return string
+local function dedent(x)
+ local xs = split(x)
+ local leading_ws = xs[1]:match('^%s*') --[[@as string]]
+ local leading_ws_pat = '^' .. leading_ws
+
+ for i in ipairs(xs) do
+ local strip_pat = xs[i]:match(leading_ws_pat) and leading_ws_pat or '^%s*'
+ xs[i] = xs[i]:gsub(strip_pat, '')
+ end
+
+ return table.concat(xs, '\n')
+end
+
--- @return table<string,vim.option_meta>
local function get_option_meta()
local opts = require('src/nvim/options').options
@@ -596,29 +681,41 @@ local function get_option_meta()
return ret
end
+--- @return table<string,vim.option_meta>
+local function get_vvar_meta()
+ local info = require('src/nvim/vvars').vars
+ local ret = {} --- @type table<string,vim.option_meta>
+ for name, o in pairs(info) do
+ o.desc = dedent(o.desc)
+ o.full_name = name
+ ret[name] = o
+ end
+ return ret
+end
+
--- @param opt vim.option_meta
--- @return string[]
local function build_option_tags(opt)
--- @type string[]
local tags = { opt.full_name }
- tags[#tags+1] = opt.abbreviation
- if opt.type == 'bool' then
+ tags[#tags + 1] = opt.abbreviation
+ if opt.type == 'boolean' then
for i = 1, #tags do
- tags[#tags+1] = 'no'..tags[i]
+ tags[#tags + 1] = 'no' .. tags[i]
end
end
for i, t in ipairs(tags) do
- tags[i] = "'"..t.."'"
+ tags[i] = "'" .. t .. "'"
end
for _, t in ipairs(opt.tags or {}) do
- tags[#tags+1] = t
+ tags[#tags + 1] = t
end
for i, t in ipairs(tags) do
- tags[i] = "*"..t.."*"
+ tags[i] = '*' .. t .. '*'
end
return tags
@@ -630,10 +727,10 @@ end
local function render_option_doc(_f, opt, write)
local tags = build_option_tags(opt)
local tag_str = table.concat(tags, ' ')
- local conceal_offset = 2*(#tags - 1)
+ local conceal_offset = 2 * (#tags - 1)
local tag_pad = string.rep('\t', math.ceil((64 - #tag_str + conceal_offset) / 8))
-- local pad = string.rep(' ', 80 - #tag_str + conceal_offset)
- write(tag_pad..tag_str)
+ write(tag_pad .. tag_str)
local name_str --- @type string
if opt.abbreviation then
@@ -642,26 +739,65 @@ local function render_option_doc(_f, opt, write)
name_str = string.format("'%s'", opt.full_name)
end
- local otype = opt.type == 'bool' and 'boolean' or opt.type
+ local otype = opt.type == 'boolean' and 'boolean' or opt.type
if opt.defaults.doc or opt.defaults.if_true ~= nil or opt.defaults.meta ~= nil then
local v = render_option_default(opt.defaults, true)
local pad = string.rep('\t', math.max(1, math.ceil((24 - #name_str) / 8)))
if opt.defaults.doc then
local deflen = #string.format('%s%s%s (', name_str, pad, otype)
--- @type string
- v = v:gsub('\n', '\n'..string.rep(' ', deflen - 2))
+ v = v:gsub('\n', '\n' .. string.rep(' ', deflen - 2))
end
write(string.format('%s%s%s\t(default %s)', name_str, pad, otype, v))
else
write(string.format('%s\t%s', name_str, otype))
end
- write('\t\t\t'..scope_to_doc(opt.scope)..scope_more_doc(opt))
+ write('\t\t\t' .. scope_to_doc(opt.scope) .. scope_more_doc(opt))
for _, l in ipairs(split(opt.desc)) do
if l == '<' or l:match('^<%s') then
write(l)
else
- write('\t'..l:gsub('\\<', '<'))
+ write('\t' .. l:gsub('\\<', '<'))
+ end
+ end
+end
+
+--- @param _f string
+--- @param vvar vim.option_meta
+--- @param write fun(line: string)
+local function render_vvar_doc(_f, vvar, write)
+ local name = vvar.full_name
+
+ local tags = { 'v:' .. name, name .. '-variable' }
+ if vvar.tags then
+ vim.list_extend(tags, vvar.tags)
+ end
+
+ for i, t in ipairs(tags) do
+ tags[i] = '*' .. t .. '*'
+ end
+
+ local tag_str = table.concat(tags, ' ')
+ local conceal_offset = 2 * (#tags - 1)
+
+ local tag_pad = string.rep('\t', math.ceil((64 - #tag_str + conceal_offset) / 8))
+ write(tag_pad .. tag_str)
+
+ local desc = split(vvar.desc)
+
+ if (#desc == 1 or #desc == 2 and desc[2]:match('^%s*$')) and #name < 10 then
+ -- single line
+ write('v:' .. name .. '\t' .. desc[1]:gsub('^%s*', ''))
+ write('')
+ else
+ write('v:' .. name)
+ for _, l in ipairs(desc) do
+ if l == '<' or l:match('^<%s') then
+ write(l)
+ else
+ write('\t\t' .. l:gsub('\\<', '<'))
+ end
end
end
end
@@ -751,21 +887,37 @@ local CONFIG = {
header = { '' },
from = 'A jump table for the options with a short description can be found at |Q_op|.',
footer = {
- ' vim:tw=78:ts=8:noet:ft=help:norl:'
+ ' vim:tw=78:ts=8:noet:ft=help:norl:',
},
funcs = get_option_meta,
render = render_option_doc,
- }
+ },
+ {
+ path = 'runtime/lua/vim/_meta/vvars.lua',
+ header = LUA_VVAR_META_HEADER,
+ funcs = get_vvar_meta,
+ render = render_vvar_meta,
+ },
+ {
+ path = 'runtime/doc/vvars.txt',
+ header = { '' },
+ from = 'Type |gO| to see the table of contents.',
+ footer = {
+ ' vim:tw=78:ts=8:noet:ft=help:norl:',
+ },
+ funcs = get_vvar_meta,
+ render = render_vvar_doc,
+ },
}
--- @param elem nvim.gen_eval_files.elem
local function render(elem)
- print('Rendering '..elem.path)
- local from_lines = {} --- @type string[]
+ print('Rendering ' .. elem.path)
+ local from_lines = {} --- @type string[]
local from = elem.from
if from then
for line in io.lines(elem.path) do
- from_lines[#from_lines+1] = line
+ from_lines[#from_lines + 1] = line
if line:match(from) then
break
end
diff --git a/scripts/gen_filetype.lua b/scripts/gen_filetype.lua
index 42478a1082..18b53f1ea4 100644
--- a/scripts/gen_filetype.lua
+++ b/scripts/gen_filetype.lua
@@ -8,18 +8,18 @@ if do_not_run then
return
end
-local filetype_vim = "runtime/filetype.vim"
-local filetype_lua = "runtime/lua/vim/filetype.lua"
+local filetype_vim = 'runtime/filetype.vim'
+local filetype_lua = 'runtime/lua/vim/filetype.lua'
local keywords = {
- ["for"] = true,
- ["or"] = true,
- ["and"] = true,
- ["end"] = true,
- ["do"] = true,
- ["if"] = true,
- ["while"] = true,
- ["repeat"] = true,
+ ['for'] = true,
+ ['or'] = true,
+ ['and'] = true,
+ ['end'] = true,
+ ['do'] = true,
+ ['if'] = true,
+ ['while'] = true,
+ ['repeat'] = true,
}
local sections = {
@@ -28,42 +28,42 @@ local sections = {
pattern = { str = {}, func = {} },
}
-local specialchars = "%*%?\\%$%[%]%{%}"
+local specialchars = '%*%?\\%$%[%]%{%}'
local function add_pattern(pat, ft)
local ok = true
-- Patterns that start or end with { or } confuse splitting on commas and make parsing harder, so just skip those
- if not string.find(pat, "^%{") and not string.find(pat, "%}$") then
- for part in string.gmatch(pat, "[^,]+") do
- if not string.find(part, "[" .. specialchars .. "]") then
- if type(ft) == "string" then
+ if not string.find(pat, '^%{') and not string.find(pat, '%}$') then
+ for part in string.gmatch(pat, '[^,]+') do
+ if not string.find(part, '[' .. specialchars .. ']') then
+ if type(ft) == 'string' then
sections.filename.str[part] = ft
else
sections.filename.func[part] = ft
end
- elseif string.match(part, "^%*%.[^%./" .. specialchars .. "]+$") then
- if type(ft) == "string" then
+ elseif string.match(part, '^%*%.[^%./' .. specialchars .. ']+$') then
+ if type(ft) == 'string' then
sections.extension.str[part:sub(3)] = ft
else
sections.extension.func[part:sub(3)] = ft
end
else
- if string.match(part, "^%*/[^" .. specialchars .. "]+$") then
+ if string.match(part, '^%*/[^' .. specialchars .. ']+$') then
-- For patterns matching */some/pattern we want to easily match files
-- with path /some/pattern, so include those in filename detection
- if type(ft) == "string" then
+ if type(ft) == 'string' then
sections.filename.str[part:sub(2)] = ft
else
sections.filename.func[part:sub(2)] = ft
end
end
- if string.find(part, "^[%w-_.*?%[%]/]+$") then
- local p = part:gsub("%.", "%%."):gsub("%*", ".*"):gsub("%?", ".")
+ if string.find(part, '^[%w-_.*?%[%]/]+$') then
+ local p = part:gsub('%.', '%%.'):gsub('%*', '.*'):gsub('%?', '.')
-- Insert into array to maintain order rather than setting
-- key-value directly
- if type(ft) == "string" then
+ if type(ft) == 'string' then
sections.pattern.str[p] = ft
else
sections.pattern.func[p] = ft
@@ -80,14 +80,16 @@ end
local function parse_line(line)
local pat, ft
- pat, ft = line:match("^%s*au%a* Buf[%a,]+%s+(%S+)%s+setf%s+(%S+)")
+ pat, ft = line:match('^%s*au%a* Buf[%a,]+%s+(%S+)%s+setf%s+(%S+)')
if pat then
return add_pattern(pat, ft)
else
local func
- pat, func = line:match("^%s*au%a* Buf[%a,]+%s+(%S+)%s+call%s+(%S+)")
+ pat, func = line:match('^%s*au%a* Buf[%a,]+%s+(%S+)%s+call%s+(%S+)')
if pat then
- return add_pattern(pat, function() return func end)
+ return add_pattern(pat, function()
+ return func
+ end)
end
end
end
@@ -95,12 +97,12 @@ end
local unparsed = {}
local full_line
for line in io.lines(filetype_vim) do
- local cont = string.match(line, "^%s*\\%s*(.*)$")
+ local cont = string.match(line, '^%s*\\%s*(.*)$')
if cont then
- full_line = full_line .. " " .. cont
+ full_line = full_line .. ' ' .. cont
else
if full_line then
- if not parse_line(full_line) and string.find(full_line, "^%s*au%a* Buf") then
+ if not parse_line(full_line) and string.find(full_line, '^%s*au%a* Buf') then
table.insert(unparsed, full_line)
end
end
@@ -109,40 +111,46 @@ for line in io.lines(filetype_vim) do
end
if #unparsed > 0 then
- print("Failed to parse the following patterns:")
+ print('Failed to parse the following patterns:')
for _, v in ipairs(unparsed) do
print(v)
end
end
local function add_item(indent, key, ft)
- if type(ft) == "string" then
- if string.find(key, "%A") or keywords[key] then
- key = string.format("[\"%s\"]", key)
+ if type(ft) == 'string' then
+ if string.find(key, '%A') or keywords[key] then
+ key = string.format('["%s"]', key)
end
return string.format([[%s%s = "%s",]], indent, key, ft)
- elseif type(ft) == "function" then
+ elseif type(ft) == 'function' then
local func = ft()
- if string.find(key, "%A") or keywords[key] then
- key = string.format("[\"%s\"]", key)
+ if string.find(key, '%A') or keywords[key] then
+ key = string.format('["%s"]', key)
end
-- Right now only a single argument is supported, which covers
-- everything in filetype.vim as of this writing
- local arg = string.match(func, "%((.*)%)$")
- func = string.gsub(func, "%(.*$", "")
- if arg == "" then
+ local arg = string.match(func, '%((.*)%)$')
+ func = string.gsub(func, '%(.*$', '')
+ if arg == '' then
-- Function with no arguments, call the function directly
return string.format([[%s%s = function() vim.fn["%s"]() end,]], indent, key, func)
elseif string.match(arg, [[^(["']).*%1$]]) then
-- String argument
- if func == "s:StarSetf" then
+ if func == 's:StarSetf' then
return string.format([[%s%s = starsetf(%s),]], indent, key, arg)
else
return string.format([[%s%s = function() vim.fn["%s"](%s) end,]], indent, key, func, arg)
end
- elseif string.find(arg, "%(") then
+ elseif string.find(arg, '%(') then
-- Function argument
- return string.format([[%s%s = function() vim.fn["%s"](vim.fn.%s) end,]], indent, key, func, arg)
+ return string.format(
+ [[%s%s = function() vim.fn["%s"](vim.fn.%s) end,]],
+ indent,
+ key,
+ func,
+ arg
+ )
else
assert(false, arg)
end
@@ -153,7 +161,7 @@ do
local lines = {}
local start = false
for line in io.lines(filetype_lua) do
- if line:match("^%s+-- END [A-Z]+$") then
+ if line:match('^%s+-- END [A-Z]+$') then
start = false
end
@@ -161,14 +169,14 @@ do
table.insert(lines, line)
end
- local indent, section = line:match("^(%s+)-- BEGIN ([A-Z]+)$")
+ local indent, section = line:match('^(%s+)-- BEGIN ([A-Z]+)$')
if section then
start = true
local t = sections[string.lower(section)]
local sorted = {}
for k, v in pairs(t.str) do
- table.insert(sorted, {[k] = v})
+ table.insert(sorted, { [k] = v })
end
table.sort(sorted, function(a, b)
@@ -182,7 +190,7 @@ do
sorted = {}
for k, v in pairs(t.func) do
- table.insert(sorted, {[k] = v})
+ table.insert(sorted, { [k] = v })
end
table.sort(sorted, function(a, b)
@@ -195,7 +203,7 @@ do
end
end
end
- local f = io.open(filetype_lua, "w")
- f:write(table.concat(lines, "\n") .. "\n")
+ local f = io.open(filetype_lua, 'w')
+ f:write(table.concat(lines, '\n') .. '\n')
f:close()
end
diff --git a/scripts/gen_help_html.lua b/scripts/gen_help_html.lua
index 633207e018..43040151eb 100644
--- a/scripts/gen_help_html.lua
+++ b/scripts/gen_help_html.lua
@@ -2,32 +2,38 @@
--
-- NOTE: :helptags checks for duplicate tags, whereas this script checks _links_ (to tags).
--
+-- USAGE (For CI/local testing purposes): Simply `make lintdoc` or `scripts/lintdoc.lua`, which
+-- basically does the following:
+-- 1. :helptags ALL
+-- 2. nvim -V1 -es +"lua require('scripts.gen_help_html').run_validate()" +q
+-- 3. nvim -V1 -es +"lua require('scripts.gen_help_html').test_gen()" +q
+--
-- USAGE (GENERATE HTML):
--- 1. Run `make helptags` first; this script depends on vim.fn.taglist().
--- 2. nvim -V1 -es --clean +"lua require('scripts.gen_help_html').gen('./build/runtime/doc/', 'target/dir/')"
+-- 1. `:helptags ALL` first; this script depends on vim.fn.taglist().
+-- 2. nvim -V1 -es --clean +"lua require('scripts.gen_help_html').gen('./runtime/doc', 'target/dir/')" +q
-- - Read the docstring at gen().
-- 3. cd target/dir/ && jekyll serve --host 0.0.0.0
-- 4. Visit http://localhost:4000/…/help.txt.html
--
-- USAGE (VALIDATE):
--- 1. nvim -V1 -es +"lua require('scripts.gen_help_html').validate()"
+-- 1. nvim -V1 -es +"lua require('scripts.gen_help_html').validate('./runtime/doc')" +q
-- - validate() is 10x faster than gen(), so it is used in CI.
--
-- SELF-TEST MODE:
--- 1. nvim -V1 -es +"lua require('scripts.gen_help_html')._test()"
+-- 1. nvim -V1 -es +"lua require('scripts.gen_help_html')._test()" +q
--
-- NOTES:
--- * gen() and validate() are the primary entrypoints. validate() only exists because gen() is too
--- slow (~1 min) to run in per-commit CI.
+-- * gen() and validate() are the primary (programmatic) entrypoints. validate() only exists
+-- because gen() is too slow (~1 min) to run in per-commit CI.
-- * visit_node() is the core function used by gen() to traverse the document tree and produce HTML.
-- * visit_validate() is the core function used by validate().
-- * Files in `new_layout` will be generated with a "flow" layout instead of preformatted/fixed-width layout.
-local tagmap = nil
-local helpfiles = nil
-local invalid_links = {}
-local invalid_urls = {}
-local invalid_spelling = {}
+local tagmap = nil ---@type table<string, string>
+local helpfiles = nil ---@type string[]
+local invalid_links = {} ---@type table<string, any>
+local invalid_urls = {} ---@type table<string, any>
+local invalid_spelling = {} ---@type table<string, table<string, string>>
local spell_dict = {
Neovim = 'Nvim',
NeoVim = 'Nvim',
@@ -36,6 +42,14 @@ local spell_dict = {
VimL = 'Vimscript',
vimL = 'Vimscript',
viml = 'Vimscript',
+ ['tree-sitter'] = 'treesitter',
+ ['Tree-sitter'] = 'Treesitter',
+}
+--- specify the list of keywords to ignore (i.e. allow), or true to disable spell check completely.
+--- @type table<string, true|string[]>
+local spell_ignore_files = {
+ ['backers.txt'] = true,
+ ['news.txt'] = { 'tree-sitter' }, -- in news, may refer to the upstream "tree-sitter" library
}
local language = nil
@@ -60,31 +74,33 @@ local new_layout = {
-- TODO: These known invalid |links| require an update to the relevant docs.
local exclude_invalid = {
- ["'string'"] = "eval.txt",
+ ["'string'"] = 'eval.txt',
Query = 'treesitter.txt',
matchit = 'vim_diff.txt',
- ["set!"] = "treesitter.txt",
+ ['set!'] = 'treesitter.txt',
}
-- False-positive "invalid URLs".
local exclude_invalid_urls = {
- ["http://"] = "usr_23.txt",
- ["http://."] = "usr_23.txt",
- ["http://aspell.net/man-html/Affix-Compression.html"] = "spell.txt",
- ["http://aspell.net/man-html/Phonetic-Code.html"] = "spell.txt",
- ["http://canna.sourceforge.jp/"] = "mbyte.txt",
- ["http://gnuada.sourceforge.net"] = "ft_ada.txt",
- ["http://lua-users.org/wiki/StringLibraryTutorial"] = "lua.txt",
- ["http://michael.toren.net/code/"] = "pi_tar.txt",
- ["http://papp.plan9.de"] = "syntax.txt",
- ["http://wiki.services.openoffice.org/wiki/Dictionaries"] = "spell.txt",
- ["http://www.adapower.com"] = "ft_ada.txt",
- ["http://www.jclark.com/"] = "quickfix.txt",
+ ['http://'] = 'usr_23.txt',
+ ['http://.'] = 'usr_23.txt',
+ ['http://aspell.net/man-html/Affix-Compression.html'] = 'spell.txt',
+ ['http://aspell.net/man-html/Phonetic-Code.html'] = 'spell.txt',
+ ['http://canna.sourceforge.jp/'] = 'mbyte.txt',
+ ['http://gnuada.sourceforge.net'] = 'ft_ada.txt',
+ ['http://lua-users.org/wiki/StringLibraryTutorial'] = 'lua.txt',
+ ['http://michael.toren.net/code/'] = 'pi_tar.txt',
+ ['http://papp.plan9.de'] = 'syntax.txt',
+ ['http://wiki.services.openoffice.org/wiki/Dictionaries'] = 'spell.txt',
+ ['http://www.adapower.com'] = 'ft_ada.txt',
+ ['http://www.jclark.com/'] = 'quickfix.txt',
+ ['http://oldblog.antirez.com/post/redis-and-scripting.html'] = 'faq.txt',
}
-- Deprecated, brain-damaged files that I don't care about.
local ignore_errors = {
['pi_netrw.txt'] = true,
+ ['backers.txt'] = true,
}
local function tofile(fname, text)
@@ -97,24 +113,24 @@ local function tofile(fname, text)
end
end
+---@type fun(s: string): string
local function html_esc(s)
- return s:gsub(
- '&', '&amp;'):gsub(
- '<', '&lt;'):gsub(
- '>', '&gt;')
+ return (s:gsub('&', '&amp;'):gsub('<', '&lt;'):gsub('>', '&gt;'))
end
local function url_encode(s)
-- Credit: tpope / vim-unimpaired
-- NOTE: these chars intentionally *not* escaped: ' ( )
- return vim.fn.substitute(vim.fn.iconv(s, 'latin1', 'utf-8'),
+ return vim.fn.substitute(
+ vim.fn.iconv(s, 'latin1', 'utf-8'),
[=[[^A-Za-z0-9()'_.~-]]=],
[=[\="%".printf("%02X",char2nr(submatch(0)))]=],
- 'g')
+ 'g'
+ )
end
local function expandtabs(s)
- return s:gsub('\t', (' '):rep(8))
+ return s:gsub('\t', (' '):rep(8)) --[[ @as string ]]
end
local function to_titlecase(s)
@@ -131,13 +147,14 @@ local function to_heading_tag(text)
end
local function basename_noext(f)
- return vim.fs.basename(f:gsub('%.txt', ''))
+ return vim.fs.basename(f:gsub('%.txt', ''))
end
local function is_blank(s)
return not not s:find([[^[\t ]*$]])
end
+---@type fun(s: string, dir?:0|1|2): string
local function trim(s, dir)
return vim.fn.trim(s, '\r\t\n ', dir or 0)
end
@@ -146,12 +163,13 @@ end
---
--- TODO: fix this in the parser instead... https://github.com/neovim/tree-sitter-vimdoc
---
---- @returns (fixed_url, removed_chars) where `removed_chars` is in the order found in the input.
+--- @param url string
+--- @return string, string (fixed_url, removed_chars) where `removed_chars` is in the order found in the input.
local function fix_url(url)
local removed_chars = ''
local fixed_url = url
-- Remove up to one of each char from end of the URL, in this order.
- for _, c in ipairs({ '.', ')', }) do
+ for _, c in ipairs({ '.', ')' }) do
if fixed_url:sub(-1) == c then
removed_chars = c .. removed_chars
fixed_url = fixed_url:sub(1, -2)
@@ -162,7 +180,7 @@ end
--- Checks if a given line is a "noise" line that doesn't look good in HTML form.
local function is_noise(line, noise_lines)
- if (
+ if
-- First line is always noise.
(noise_lines ~= nil and vim.tbl_count(noise_lines) == 0)
or line:find('Type .*gO.* to see the table of contents')
@@ -177,7 +195,7 @@ local function is_noise(line, noise_lines)
or line:find('^%s*vim?%:.*ft=help')
or line:find('^%s*vim?%:.*filetype=help')
or line:find('[*>]local%-additions[*<]')
- ) then
+ then
-- table.insert(stats.noise_lines, getbuflinestr(root, opt.buf, 0))
table.insert(noise_lines or {}, line)
return true
@@ -188,28 +206,32 @@ end
--- Creates a github issue URL at neovim/tree-sitter-vimdoc with prefilled content.
local function get_bug_url_vimdoc(fname, to_fname, sample_text)
local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname))
- local bug_url = ('https://github.com/neovim/tree-sitter-vimdoc/issues/new?labels=bug&title=parse+error%3A+'
- ..vim.fs.basename(fname)
- ..'+&body=Found+%60tree-sitter-vimdoc%60+parse+error+at%3A+'
- ..this_url
- ..'%0D%0DContext%3A%0D%0D%60%60%60%0D'
- ..url_encode(sample_text)
- ..'%0D%60%60%60')
+ local bug_url = (
+ 'https://github.com/neovim/tree-sitter-vimdoc/issues/new?labels=bug&title=parse+error%3A+'
+ .. vim.fs.basename(fname)
+ .. '+&body=Found+%60tree-sitter-vimdoc%60+parse+error+at%3A+'
+ .. this_url
+ .. '%0D%0DContext%3A%0D%0D%60%60%60%0D'
+ .. url_encode(sample_text)
+ .. '%0D%60%60%60'
+ )
return bug_url
end
--- Creates a github issue URL at neovim/neovim with prefilled content.
local function get_bug_url_nvim(fname, to_fname, sample_text, token_name)
local this_url = string.format('https://neovim.io/doc/user/%s', vim.fs.basename(to_fname))
- local bug_url = ('https://github.com/neovim/neovim/issues/new?labels=bug&title=user+docs+HTML%3A+'
- ..vim.fs.basename(fname)
- ..'+&body=%60gen_help_html.lua%60+problem+at%3A+'
- ..this_url
- ..'%0D'
- ..(token_name and '+unhandled+token%3A+%60'..token_name..'%60' or '')
- ..'%0DContext%3A%0D%0D%60%60%60%0D'
- ..url_encode(sample_text)
- ..'%0D%60%60%60')
+ local bug_url = (
+ 'https://github.com/neovim/neovim/issues/new?labels=bug&title=user+docs+HTML%3A+'
+ .. vim.fs.basename(fname)
+ .. '+&body=%60gen_help_html.lua%60+problem+at%3A+'
+ .. this_url
+ .. '%0D'
+ .. (token_name and '+unhandled+token%3A+%60' .. token_name .. '%60' or '')
+ .. '%0DContext%3A%0D%0D%60%60%60%0D'
+ .. url_encode(sample_text)
+ .. '%0D%60%60%60'
+ )
return bug_url
end
@@ -254,6 +276,9 @@ local function trim_indent(s)
end
--- Gets raw buffer text in the node's range (+/- an offset), as a newline-delimited string.
+---@param node TSNode
+---@param bufnr integer
+---@param offset integer
local function getbuflinestr(node, bufnr, offset)
local line1, _, line2, _ = node:range()
line1 = line1 - offset
@@ -264,8 +289,12 @@ end
--- Gets the whitespace just before `node` from the raw buffer text.
--- Needed for preformatted `old` lines.
+---@param node TSNode
+---@param bufnr integer
+---@return string
local function getws(node, bufnr)
local line1, c1, line2, _ = node:range()
+ ---@type string
local raw = vim.fn.getbufline(bufnr, line1 + 1, line2 + 1)[1]
local text_before = raw:sub(1, c1)
local leading_ws = text_before:match('%s+$') or ''
@@ -274,9 +303,11 @@ end
local function get_tagname(node, bufnr)
local text = vim.treesitter.get_node_text(node, bufnr)
- local tag = (node:type() == 'optionlink' or node:parent():type() == 'optionlink') and ("'%s'"):format(text) or text
- local helpfile = vim.fs.basename(tagmap[tag]) or nil -- "api.txt"
- local helppage = get_helppage(helpfile) -- "api.html"
+ local tag = (node:type() == 'optionlink' or node:parent():type() == 'optionlink')
+ and ("'%s'"):format(text)
+ or text
+ local helpfile = vim.fs.basename(tagmap[tag]) or nil -- "api.txt"
+ local helppage = get_helppage(helpfile) -- "api.html"
return helppage, tag
end
@@ -295,16 +326,15 @@ local function ignore_parse_error(fname, s)
if ignore_errors[vim.fs.basename(fname)] then
return true
end
- return (
- -- Ignore parse errors for unclosed tag.
- -- This is common in vimdocs and is treated as plaintext by :help.
- s:find("^[`'|*]")
- )
+ -- Ignore parse errors for unclosed tag.
+ -- This is common in vimdocs and is treated as plaintext by :help.
+ return s:find("^[`'|*]")
end
+---@param node TSNode
local function has_ancestor(node, ancestor_name)
- local p = node
- while true do
+ local p = node ---@type TSNode?
+ while p do
p = p:parent()
if not p or p:type() == 'help_file' then
break
@@ -316,6 +346,7 @@ local function has_ancestor(node, ancestor_name)
end
--- Gets the first matching child node matching `name`.
+---@param node TSNode
local function first(node, name)
for c, _ in node:iter_children() do
if c:named() and c:type() == name then
@@ -349,6 +380,11 @@ local function validate_url(text, fname)
end
--- Traverses the tree at `root` and checks that |tag| links point to valid helptags.
+---@param root TSNode
+---@param level integer
+---@param lang_tree TSTree
+---@param opt table
+---@param stats table
local function visit_validate(root, level, lang_tree, opt, stats)
level = level or 0
local node_name = (root.named and root:named()) and root:type() or nil
@@ -377,13 +413,24 @@ local function visit_validate(root, level, lang_tree, opt, stats)
-- Flatten the sample text to a single, truncated line.
sample_text = vim.trim(sample_text):gsub('[\t\n]', ' '):sub(1, 80)
table.insert(stats.parse_errors, sample_text)
- elseif (node_name == 'word' or node_name == 'uppercase_name')
- and (not vim.tbl_contains({'codespan', 'taglink', 'tag'}, parent))
+ elseif
+ (node_name == 'word' or node_name == 'uppercase_name')
+ and (not vim.tbl_contains({ 'codespan', 'taglink', 'tag' }, parent))
then
- local text_nopunct = vim.fn.trim(text, '.,', 0) -- Ignore some punctuation.
+ local text_nopunct = vim.fn.trim(text, '.,', 0) -- Ignore some punctuation.
+ local fname_basename = assert(vim.fs.basename(opt.fname))
if spell_dict[text_nopunct] then
- invalid_spelling[text_nopunct] = invalid_spelling[text_nopunct] or {}
- invalid_spelling[text_nopunct][vim.fs.basename(opt.fname)] = node_text(root:parent())
+ local should_ignore = (
+ spell_ignore_files[fname_basename] == true
+ or vim.tbl_contains(
+ (spell_ignore_files[fname_basename] or {}) --[[ @as string[] ]],
+ text_nopunct
+ )
+ )
+ if not should_ignore then
+ invalid_spelling[text_nopunct] = invalid_spelling[text_nopunct] or {}
+ invalid_spelling[text_nopunct][fname_basename] = node_text(root:parent())
+ end
end
elseif node_name == 'url' then
local fixed_url, _ = fix_url(trim(text))
@@ -395,29 +442,47 @@ end
-- Fix tab alignment issues caused by concealed characters like |, `, * in tags
-- and code blocks.
+---@param text string
+---@param next_node_text string
local function fix_tab_after_conceal(text, next_node_text)
-- Vim tabs take into account the two concealed characters even though they
-- are invisible, so we need to add back in the two spaces if this is
-- followed by a tab to make the tab alignment to match Vim's behavior.
- if string.sub(next_node_text,1,1) == '\t' then
+ if string.sub(next_node_text, 1, 1) == '\t' then
text = text .. ' '
end
return text
end
+---@class (exact) nvim.gen_help_html.heading
+---@field name string
+---@field subheadings nvim.gen_help_html.heading[]
+---@field tag string
+
-- Generates HTML from node `root` recursively.
+---@param root TSNode
+---@param level integer
+---@param lang_tree TSTree
+---@param headings nvim.gen_help_html.heading[]
+---@param opt table
+---@param stats table
local function visit_node(root, level, lang_tree, headings, opt, stats)
level = level or 0
local node_name = (root.named and root:named()) and root:type() or nil
-- Previous sibling kind (string).
- local prev = root:prev_sibling() and (root:prev_sibling().named and root:prev_sibling():named()) and root:prev_sibling():type() or nil
+ local prev = root:prev_sibling()
+ and (root:prev_sibling().named and root:prev_sibling():named())
+ and root:prev_sibling():type()
+ or nil
-- Next sibling kind (string).
- local next_ = root:next_sibling() and (root:next_sibling().named and root:next_sibling():named()) and root:next_sibling():type() or nil
+ local next_ = root:next_sibling()
+ and (root:next_sibling().named and root:next_sibling():named())
+ and root:next_sibling():type()
+ or nil
-- Parent kind (string).
local parent = root:parent() and root:parent():type() or nil
local text = ''
- local trimmed
-- Gets leading whitespace of `node`.
local function ws(node)
node = node or root
@@ -435,6 +500,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
return string.format('%s%s', ws_, vim.treesitter.get_node_text(node, opt.buf))
end
+ local trimmed ---@type string
if root:named_child_count() == 0 or node_name == 'ERROR' then
text = node_text()
trimmed = html_esc(trim(text))
@@ -450,7 +516,7 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
trimmed = trim(text)
end
- if node_name == 'help_file' then -- root node
+ if node_name == 'help_file' then -- root node
return text
elseif node_name == 'url' then
local fixed_url, removed_chars = fix_url(trimmed)
@@ -459,18 +525,24 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
return text
elseif node_name == 'h1' or node_name == 'h2' or node_name == 'h3' then
if is_noise(text, stats.noise_lines) then
- return '' -- Discard common "noise" lines.
+ return '' -- Discard common "noise" lines.
end
-- Remove "===" and tags from ToC text.
local hname = (node_text():gsub('%-%-%-%-+', ''):gsub('%=%=%=%=+', ''):gsub('%*.*%*', ''))
-- Use the first *tag* node as the heading anchor, if any.
local tagnode = first(root, 'tag')
-- Use the *tag* as the heading anchor id, if possible.
- local tagname = tagnode and url_encode(node_text(tagnode:child(1), false)) or to_heading_tag(hname)
+ local tagname = tagnode and url_encode(node_text(tagnode:child(1), false))
+ or to_heading_tag(hname)
if node_name == 'h1' or #headings == 0 then
- table.insert(headings, { name = hname, subheadings = {}, tag = tagname })
+ ---@type nvim.gen_help_html.heading
+ local heading = { name = hname, subheadings = {}, tag = tagname }
+ headings[#headings + 1] = heading
else
- table.insert(headings[#headings].subheadings, { name = hname, subheadings = {}, tag = tagname })
+ table.insert(
+ headings[#headings].subheadings,
+ { name = hname, subheadings = {}, tag = tagname }
+ )
end
local el = node_name == 'h1' and 'h2' or 'h3'
return ('<%s id="%s" class="help-heading">%s</%s>\n'):format(el, tagname, text, el)
@@ -490,11 +562,16 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
end
return string.format('<div class="help-para">\n%s\n</div>\n', text)
elseif node_name == 'line' then
- if (parent ~= 'codeblock' or parent ~= 'code') and (is_blank(text) or is_noise(text, stats.noise_lines)) then
- return '' -- Discard common "noise" lines.
+ if
+ (parent ~= 'codeblock' or parent ~= 'code')
+ and (is_blank(text) or is_noise(text, stats.noise_lines))
+ then
+ return '' -- Discard common "noise" lines.
end
-- XXX: Avoid newlines (too much whitespace) after block elements in old (preformatted) layout.
- local div = opt.old and root:child(0) and vim.list_contains({'column_heading', 'h1', 'h2', 'h3'}, root:child(0):type())
+ local div = opt.old
+ and root:child(0)
+ and vim.list_contains({ 'column_heading', 'h1', 'h2', 'h3' }, root:child(0):type())
return string.format('%s%s', div and trim(text) or text, div and '' or '\n')
elseif node_name == 'line_li' then
local sib = root:prev_sibling()
@@ -520,12 +597,17 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
if ignored then
return text
end
- local s = ('%s<a href="%s#%s">%s</a>'):format(ws(), helppage, url_encode(tagname), html_esc(tagname))
+ local s = ('%s<a href="%s#%s">%s</a>'):format(
+ ws(),
+ helppage,
+ url_encode(tagname),
+ html_esc(tagname)
+ )
if opt.old and node_name == 'taglink' then
s = fix_tab_after_conceal(s, node_text(root:next_sibling()))
end
return s
- elseif vim.list_contains({'codespan', 'keycode'}, node_name) then
+ elseif vim.list_contains({ 'codespan', 'keycode' }, node_name) then
if root:has_error() then
return text
end
@@ -541,24 +623,28 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
elseif node_name == 'language' then
language = node_text(root)
return ''
- elseif node_name == 'code' then -- Highlighted codeblock (child).
+ elseif node_name == 'code' then -- Highlighted codeblock (child).
if is_blank(text) then
return ''
end
- local code
+ local code ---@type string
if language then
- code = ('<pre><code class="language-%s">%s</code></pre>'):format(language,trim(trim_indent(text), 2))
+ code = ('<pre><code class="language-%s">%s</code></pre>'):format(
+ language,
+ trim(trim_indent(text), 2)
+ )
language = nil
else
code = ('<pre>%s</pre>'):format(trim(trim_indent(text), 2))
end
return code
- elseif node_name == 'tag' then -- anchor
+ elseif node_name == 'tag' then -- anchor
if root:has_error() then
return text
end
- local in_heading = vim.list_contains({'h1', 'h2', 'h3'}, parent)
- local cssclass = (not in_heading and get_indent(node_text()) > 8) and 'help-tag-right' or 'help-tag'
+ local in_heading = vim.list_contains({ 'h1', 'h2', 'h3' }, parent)
+ local cssclass = (not in_heading and get_indent(node_text()) > 8) and 'help-tag-right'
+ or 'help-tag'
local tagname = node_text(root:child(1), false)
if vim.tbl_count(stats.first_tags) < 2 then
-- Force the first 2 tags in the doc to be anchored at the main heading.
@@ -567,14 +653,29 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
end
local el = in_heading and 'span' or 'code'
local encoded_tagname = url_encode(tagname)
- local s = ('%s<%s id="%s" class="%s"><a href="#%s">%s</a></%s>'):format(ws(), el, encoded_tagname, cssclass, encoded_tagname, trimmed, el)
+ local s = ('%s<%s id="%s" class="%s"><a href="#%s">%s</a></%s>'):format(
+ ws(),
+ el,
+ encoded_tagname,
+ cssclass,
+ encoded_tagname,
+ trimmed,
+ el
+ )
if opt.old then
- s = fix_tab_after_conceal(s, node_text(root:next_sibling()))
+ s = fix_tab_after_conceal(s, node_text(root:next_sibling()))
end
if in_heading and prev ~= 'tag' then
-- Don't set "id", let the heading use the tag as its "id" (used by search engines).
- s = ('%s<%s class="%s"><a href="#%s">%s</a></%s>'):format(ws(), el, cssclass, encoded_tagname, trimmed, el)
+ s = ('%s<%s class="%s"><a href="#%s">%s</a></%s>'):format(
+ ws(),
+ el,
+ cssclass,
+ encoded_tagname,
+ trimmed,
+ el
+ )
-- Start the <span> container for tags in a heading.
-- This makes "justify-content:space-between" right-align the tags.
-- <h2>foo bar<span>tag1 tag2</span></h2>
@@ -593,21 +694,31 @@ local function visit_node(root, level, lang_tree, headings, opt, stats)
local sample_text = level > 0 and getbuflinestr(root, opt.buf, 3) or '[top level!]'
table.insert(stats.parse_errors, sample_text)
return ('<a class="parse-error" target="_blank" title="Report bug... (parse error)" href="%s">%s</a>'):format(
- get_bug_url_vimdoc(opt.fname, opt.to_fname, sample_text), trimmed)
- else -- Unknown token.
+ get_bug_url_vimdoc(opt.fname, opt.to_fname, sample_text),
+ trimmed
+ )
+ else -- Unknown token.
local sample_text = level > 0 and getbuflinestr(root, opt.buf, 3) or '[top level!]'
return ('<a class="unknown-token" target="_blank" title="Report bug... (unhandled token "%s")" href="%s">%s</a>'):format(
- node_name, get_bug_url_nvim(opt.fname, opt.to_fname, sample_text, node_name), trimmed), ('unknown-token:"%s"'):format(node_name)
+ node_name,
+ get_bug_url_nvim(opt.fname, opt.to_fname, sample_text, node_name),
+ trimmed
+ ),
+ ('unknown-token:"%s"'):format(node_name)
end
end
-local function get_helpfiles(include)
- local dir = './build/runtime/doc'
+--- @param dir string e.g. '$VIMRUNTIME/doc'
+--- @param include string[]|nil
+--- @return string[]
+local function get_helpfiles(dir, include)
local rv = {}
for f, type in vim.fs.dir(dir) do
- if (vim.endswith(f, '.txt')
- and type == 'file'
- and (not include or vim.list_contains(include, f))) then
+ if
+ vim.endswith(f, '.txt')
+ and type == 'file'
+ and (not include or vim.list_contains(include, f))
+ then
local fullpath = vim.fn.fnamemodify(('%s/%s'):format(dir, f), ':p')
table.insert(rv, fullpath)
end
@@ -633,7 +744,7 @@ end
--- Use the vimdoc parser defined in the build, not whatever happens to be installed on the system.
local function ensure_runtimepath()
if not vim.o.runtimepath:find('build/lib/nvim/') then
- vim.cmd[[set runtimepath^=./build/lib/nvim/]]
+ vim.cmd [[set runtimepath^=./build/lib/nvim/]]
end
end
@@ -641,15 +752,17 @@ end
---
--- @param fname string help file to parse
--- @param parser_path string? path to non-default vimdoc.so
---- @returns lang_tree, bufnr
+--- @return vim.treesitter.LanguageTree, integer (lang_tree, bufnr)
local function parse_buf(fname, parser_path)
- local buf
+ local buf ---@type integer
if type(fname) == 'string' then
- vim.cmd('split '..vim.fn.fnameescape(fname)) -- Filename.
+ vim.cmd('split ' .. vim.fn.fnameescape(fname)) -- Filename.
buf = vim.api.nvim_get_current_buf()
else
+ -- Left for debugging
+ ---@diagnostic disable-next-line: no-unknown
buf = fname
- vim.cmd('sbuffer '..tostring(fname)) -- Buffer number.
+ vim.cmd('sbuffer ' .. tostring(fname)) -- Buffer number.
end
if parser_path then
vim.treesitter.language.add('vimdoc', { path = parser_path })
@@ -664,14 +777,14 @@ end
---
--- @param fname string help file to validate
--- @param parser_path string? path to non-default vimdoc.so
---- @returns { invalid_links: number, parse_errors: string[] }
+--- @return { invalid_links: number, parse_errors: string[] }
local function validate_one(fname, parser_path)
local stats = {
parse_errors = {},
}
local lang_tree, buf = parse_buf(fname, parser_path)
for _, tree in ipairs(lang_tree:trees()) do
- visit_validate(tree:root(), 0, tree, { buf = buf, fname = fname, }, stats)
+ visit_validate(tree:root(), 0, tree, { buf = buf, fname = fname }, stats)
end
lang_tree:destroy()
vim.cmd.close()
@@ -685,15 +798,17 @@ end
--- @param old boolean Preformat paragraphs (for old :help files which are full of arbitrary whitespace)
--- @param parser_path string? path to non-default vimdoc.so
---
---- @returns html, stats
+--- @return string html
+--- @return table stats
local function gen_one(fname, to_fname, old, commit, parser_path)
local stats = {
noise_lines = {},
parse_errors = {},
- first_tags = {}, -- Track the first few tags in doc.
+ first_tags = {}, -- Track the first few tags in doc.
}
local lang_tree, buf = parse_buf(fname, parser_path)
- local headings = {} -- Headings (for ToC). 2-dimensional: h1 contains h2/h3.
+ ---@type nvim.gen_help_html.heading[]
+ local headings = {} -- Headings (for ToC). 2-dimensional: h1 contains h2/h3.
local title = to_titlecase(basename_noext(fname))
local html = ([[
@@ -777,9 +892,17 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
local main = ''
for _, tree in ipairs(lang_tree:trees()) do
- main = main .. (visit_node(tree:root(), 0, tree, headings,
- { buf = buf, old = old, fname = fname, to_fname = to_fname, indent = 1, },
- stats))
+ main = main
+ .. (
+ visit_node(
+ tree:root(),
+ 0,
+ tree,
+ headings,
+ { buf = buf, old = old, fname = fname, to_fname = to_fname, indent = 1 },
+ stats
+ )
+ )
end
main = ([[
@@ -809,8 +932,16 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
<hr/>
%s
</div>
- ]]):format(logo_svg, stats.first_tags[2] or '', stats.first_tags[1] or '', title, vim.fs.basename(fname), main)
+ ]]):format(
+ logo_svg,
+ stats.first_tags[2] or '',
+ stats.first_tags[1] or '',
+ title,
+ vim.fs.basename(fname),
+ main
+ )
+ ---@type string
local toc = [[
<div class="col-narrow toc">
<div><a href="index.html">Main</a></div>
@@ -819,13 +950,17 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
<hr/>
]]
- local n = 0 -- Count of all headings + subheadings.
- for _, h1 in ipairs(headings) do n = n + 1 + #h1.subheadings end
+ local n = 0 -- Count of all headings + subheadings.
for _, h1 in ipairs(headings) do
+ n = n + 1 + #h1.subheadings
+ end
+ for _, h1 in ipairs(headings) do
+ ---@type string
toc = toc .. ('<div class="help-toc-h1"><a href="#%s">%s</a>\n'):format(h1.tag, h1.name)
- if n < 30 or #headings < 10 then -- Show subheadings only if there aren't too many.
+ if n < 30 or #headings < 10 then -- Show subheadings only if there aren't too many.
for _, h2 in ipairs(h1.subheadings) do
- toc = toc .. ('<div class="help-toc-h2"><a href="#%s">%s</a></div>\n'):format(h2.tag, h2.name)
+ toc = toc
+ .. ('<div class="help-toc-h2"><a href="#%s">%s</a></div>\n'):format(h2.tag, h2.name)
end
end
toc = toc .. '</div>'
@@ -859,11 +994,16 @@ local function gen_one(fname, to_fname, old, commit, parser_path)
</footer>
]]):format(
- os.date('%Y-%m-%d %H:%M'), commit, commit:sub(1, 7), #stats.parse_errors, bug_link,
- html_esc(table.concat(stats.noise_lines, '\n')), #stats.noise_lines)
+ os.date('%Y-%m-%d %H:%M'),
+ commit,
+ commit:sub(1, 7),
+ #stats.parse_errors,
+ bug_link,
+ html_esc(table.concat(stats.noise_lines, '\n')),
+ #stats.noise_lines
+ )
- html = ('%s%s%s</div>\n%s</body>\n</html>\n'):format(
- html, main, toc, footer)
+ html = ('%s%s%s</div>\n%s</body>\n</html>\n'):format(html, main, toc, footer)
vim.cmd('q!')
lang_tree:destroy()
return html, stats
@@ -1033,24 +1173,41 @@ local function gen_css(fname)
tofile(fname, css)
end
-function M._test()
- tagmap = get_helptags('./build/runtime/doc')
- helpfiles = get_helpfiles()
+-- Testing
- local function ok(cond, expected, actual)
- assert((not expected and not actual) or (expected and actual), 'if "expected" is given, "actual" is also required')
- if expected then
- return assert(cond, ('expected %s, got: %s'):format(vim.inspect(expected), vim.inspect(actual)))
- else
- return assert(cond)
- end
- end
- local function eq(expected, actual)
- return ok(expected == actual, expected, actual)
+local function ok(cond, expected, actual, message)
+ assert(
+ (not expected and not actual) or (expected and actual),
+ 'if "expected" is given, "actual" is also required'
+ )
+ if expected then
+ assert(
+ cond,
+ ('%sexpected %s, got: %s'):format(
+ message and (message .. '\n') or '',
+ vim.inspect(expected),
+ vim.inspect(actual)
+ )
+ )
+ return cond
+ else
+ return assert(cond)
end
+end
+local function eq(expected, actual, message)
+ return ok(vim.deep_equal(expected, actual), expected, actual, message)
+end
+
+function M._test()
+ tagmap = get_helptags('$VIMRUNTIME/doc')
+ helpfiles = get_helpfiles(vim.fn.expand('$VIMRUNTIME/doc'))
ok(vim.tbl_count(tagmap) > 3000, '>3000', vim.tbl_count(tagmap))
- ok(vim.endswith(tagmap['vim.diagnostic.set()'], 'diagnostic.txt'), tagmap['vim.diagnostic.set()'], 'diagnostic.txt')
+ ok(
+ vim.endswith(tagmap['vim.diagnostic.set()'], 'diagnostic.txt'),
+ tagmap['vim.diagnostic.set()'],
+ 'diagnostic.txt'
+ )
ok(vim.endswith(tagmap['%:s'], 'cmdline.txt'), tagmap['%:s'], 'cmdline.txt')
ok(is_noise([[vim:tw=78:isk=!-~,^*,^\|,^\":ts=8:noet:ft=help:norl:]]))
ok(is_noise([[ NVIM REFERENCE MANUAL by Thiago de Arruda ]]))
@@ -1060,7 +1217,10 @@ function M._test()
eq(1, get_indent(' a'))
eq(2, get_indent(' a\n b\n c\n'))
eq(5, get_indent(' a\n \n b\n c\n d\n e\n'))
- eq('a\n \n b\n c\n d\n e\n', trim_indent(' a\n \n b\n c\n d\n e\n'))
+ eq(
+ 'a\n \n b\n c\n d\n e\n',
+ trim_indent(' a\n \n b\n c\n d\n e\n')
+ )
local fixed_url, removed_chars = fix_url('https://example.com).')
eq('https://example.com', fixed_url)
@@ -1078,33 +1238,50 @@ function M._test()
eq('https://example.com', fixed_url)
eq('', removed_chars)
- print('all tests passed')
+ print('all tests passed.\n')
end
+--- @class nvim.gen_help_html.gen_result
+--- @field helpfiles string[] list of generated HTML files, from the source docs {include}
+--- @field err_count integer number of parse errors in :help docs
+--- @field invalid_links table<string, any>
+
--- Generates HTML from :help docs located in `help_dir` and writes the result in `to_dir`.
---
--- Example:
---
---- gen('./build/runtime/doc', '/path/to/neovim.github.io/_site/doc/', {'api.txt', 'autocmd.txt', 'channel.txt'}, nil)
+--- gen('$VIMRUNTIME/doc', '/path/to/neovim.github.io/_site/doc/', {'api.txt', 'autocmd.txt', 'channel.txt'}, nil)
---
--- @param help_dir string Source directory containing the :help files. Must run `make helptags` first.
--- @param to_dir string Target directory where the .html files will be written.
---- @param include table|nil Process only these filenames. Example: {'api.txt', 'autocmd.txt', 'channel.txt'}
+--- @param include string[]|nil Process only these filenames. Example: {'api.txt', 'autocmd.txt', 'channel.txt'}
---
---- @returns info dict
+--- @return nvim.gen_help_html.gen_result result
function M.gen(help_dir, to_dir, include, commit, parser_path)
- vim.validate{
- help_dir={help_dir, function(d) return vim.fn.isdirectory(vim.fn.expand(d)) == 1 end, 'valid directory'},
- to_dir={to_dir, 's'},
- include={include, 't', true},
- commit={commit, 's', true},
- parser_path={parser_path, function(f) return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1 end, 'valid vimdoc.{so,dll} filepath'},
+ vim.validate {
+ help_dir = {
+ help_dir,
+ function(d)
+ return vim.fn.isdirectory(vim.fn.expand(d)) == 1
+ end,
+ 'valid directory',
+ },
+ to_dir = { to_dir, 's' },
+ include = { include, 't', true },
+ commit = { commit, 's', true },
+ parser_path = {
+ parser_path,
+ function(f)
+ return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1
+ end,
+ 'valid vimdoc.{so,dll} filepath',
+ },
}
local err_count = 0
ensure_runtimepath()
tagmap = get_helptags(vim.fn.expand(help_dir))
- helpfiles = get_helpfiles(include)
+ helpfiles = get_helpfiles(help_dir, include)
to_dir = vim.fn.expand(to_dir)
parser_path = parser_path and vim.fn.expand(parser_path) or nil
@@ -1117,13 +1294,20 @@ function M.gen(help_dir, to_dir, include, commit, parser_path)
local to_fname = ('%s/%s'):format(to_dir, get_helppage(helpfile))
local html, stats = gen_one(f, to_fname, not new_layout[helpfile], commit or '?', parser_path)
tofile(to_fname, html)
- print(('generated (%-4s errors): %-15s => %s'):format(#stats.parse_errors, helpfile, vim.fs.basename(to_fname)))
+ print(
+ ('generated (%-4s errors): %-15s => %s'):format(
+ #stats.parse_errors,
+ helpfile,
+ vim.fs.basename(to_fname)
+ )
+ )
err_count = err_count + #stats.parse_errors
end
print(('generated %d html pages'):format(#helpfiles))
print(('total errors: %d'):format(err_count))
print(('invalid tags:\n%s'):format(vim.inspect(invalid_links)))
+ --- @type nvim.gen_help_html.gen_result
return {
helpfiles = helpfiles,
err_count = err_count,
@@ -1131,45 +1315,118 @@ function M.gen(help_dir, to_dir, include, commit, parser_path)
}
end
--- Validates all :help files found in `help_dir`:
--- - checks that |tag| links point to valid helptags.
--- - recursively counts parse errors ("ERROR" nodes)
---
--- This is 10x faster than gen(), for use in CI.
---
--- @returns results dict
+--- @class nvim.gen_help_html.validate_result
+--- @field helpfiles integer number of generated helpfiles
+--- @field err_count integer number of parse errors
+--- @field parse_errors table<string, string[]>
+--- @field invalid_links table<string, any> invalid tags in :help docs
+--- @field invalid_urls table<string, any> invalid URLs in :help docs
+--- @field invalid_spelling table<string, table<string, string>> invalid spelling in :help docs
+
+--- Validates all :help files found in `help_dir`:
+--- - checks that |tag| links point to valid helptags.
+--- - recursively counts parse errors ("ERROR" nodes)
+---
+--- This is 10x faster than gen(), for use in CI.
+---
+--- @return nvim.gen_help_html.validate_result result
function M.validate(help_dir, include, parser_path)
- vim.validate{
- help_dir={help_dir, function(d) return vim.fn.isdirectory(vim.fn.expand(d)) == 1 end, 'valid directory'},
- include={include, 't', true},
- parser_path={parser_path, function(f) return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1 end, 'valid vimdoc.{so,dll} filepath'},
+ vim.validate {
+ help_dir = {
+ help_dir,
+ function(d)
+ return vim.fn.isdirectory(vim.fn.expand(d)) == 1
+ end,
+ 'valid directory',
+ },
+ include = { include, 't', true },
+ parser_path = {
+ parser_path,
+ function(f)
+ return f == nil or vim.fn.filereadable(vim.fn.expand(f)) == 1
+ end,
+ 'valid vimdoc.{so,dll} filepath',
+ },
}
- local err_count = 0
- local files_to_errors = {}
+ local err_count = 0 ---@type integer
+ local files_to_errors = {} ---@type table<string, string[]>
ensure_runtimepath()
tagmap = get_helptags(vim.fn.expand(help_dir))
- helpfiles = get_helpfiles(include)
+ helpfiles = get_helpfiles(help_dir, include)
parser_path = parser_path and vim.fn.expand(parser_path) or nil
for _, f in ipairs(helpfiles) do
- local helpfile = vim.fs.basename(f)
+ local helpfile = assert(vim.fs.basename(f))
local rv = validate_one(f, parser_path)
print(('validated (%-4s errors): %s'):format(#rv.parse_errors, helpfile))
if #rv.parse_errors > 0 then
files_to_errors[helpfile] = rv.parse_errors
- vim.print(('%s'):format(vim.iter(rv.parse_errors):fold('', function(s, v) return s..'\n '..v end)))
+ vim.print(('%s'):format(vim.iter(rv.parse_errors):fold('', function(s, v)
+ return s .. '\n ' .. v
+ end)))
end
err_count = err_count + #rv.parse_errors
end
+ ---@type nvim.gen_help_html.validate_result
return {
helpfiles = #helpfiles,
err_count = err_count,
+ parse_errors = files_to_errors,
invalid_links = invalid_links,
invalid_urls = invalid_urls,
invalid_spelling = invalid_spelling,
- parse_errors = files_to_errors,
}
end
+--- Validates vimdoc files on $VIMRUNTIME. and print human-readable error messages if fails.
+---
+--- If this fails, try these steps (in order):
+--- 1. Fix/cleanup the :help docs.
+--- 2. Fix the parser: https://github.com/neovim/tree-sitter-vimdoc
+--- 3. File a parser bug, and adjust the tolerance of this test in the meantime.
+---
+--- @param help_dir? string e.g. '$VIMRUNTIME/doc' or './runtime/doc'
+function M.run_validate(help_dir)
+ help_dir = vim.fn.expand(help_dir or '$VIMRUNTIME/doc')
+ print('doc path = ' .. vim.uv.fs_realpath(help_dir))
+
+ local rv = M.validate(help_dir)
+
+ -- Check that we actually found helpfiles.
+ ok(rv.helpfiles > 100, '>100 :help files', rv.helpfiles)
+
+ eq({}, rv.parse_errors, 'no parse errors')
+ eq(0, rv.err_count, 'no parse errors')
+ eq({}, rv.invalid_links, 'invalid tags in :help docs')
+ eq({}, rv.invalid_urls, 'invalid URLs in :help docs')
+ eq(
+ {},
+ rv.invalid_spelling,
+ 'invalid spelling in :help docs (see spell_dict in scripts/gen_help_html.lua)'
+ )
+end
+
+--- Test-generates HTML from docs.
+---
+--- 1. Test that gen_help_html.lua actually works.
+--- 2. Test that parse errors did not increase wildly. Because we explicitly test only a few
+--- :help files, we can be precise about the tolerances here.
+--- @param help_dir? string e.g. '$VIMRUNTIME/doc' or './runtime/doc'
+function M.test_gen(help_dir)
+ local tmpdir = assert(vim.fs.dirname(vim.fn.tempname()))
+ help_dir = vim.fn.expand(help_dir or '$VIMRUNTIME/doc')
+ print('doc path = ' .. vim.uv.fs_realpath(help_dir))
+
+ local rv = M.gen(
+ help_dir,
+ tmpdir,
+ -- Because gen() is slow (~30s), this test is limited to a few files.
+ { 'pi_health.txt', 'help.txt', 'index.txt', 'nvim.txt' }
+ )
+ eq(4, #rv.helpfiles)
+ eq(0, rv.err_count, 'parse errors in :help docs')
+ eq({}, rv.invalid_links, 'invalid tags in :help docs')
+end
+
return M
diff --git a/scripts/gen_lsp.lua b/scripts/gen_lsp.lua
index 6ff8dcb3f4..19fad7bab4 100644
--- a/scripts/gen_lsp.lua
+++ b/scripts/gen_lsp.lua
@@ -1,11 +1,15 @@
---[[
-Generates lua-ls annotations for lsp
+-- Generates lua-ls annotations for lsp.
+
+local USAGE = [[
+Generates lua-ls annotations for lsp.
+
USAGE:
-nvim -l scripts/gen_lsp.lua gen # this will overwrite runtime/lua/vim/lsp/_meta/protocol.lua
-nvim -l scripts/gen_lsp.lua gen --version 3.18 --build/new_lsp_types.lua
+nvim -l scripts/gen_lsp.lua gen # by default, this will overwrite runtime/lua/vim/lsp/_meta/protocol.lua
nvim -l scripts/gen_lsp.lua gen --version 3.18 --out runtime/lua/vim/lsp/_meta/protocol.lua
nvim -l scripts/gen_lsp.lua gen --version 3.18 --methods
---]]
+]]
+
+local DEFAULT_LSP_VERSION = '3.18'
local M = {}
@@ -14,15 +18,28 @@ local function tofile(fname, text)
if not f then
error(('failed to write: %s'):format(f))
else
+ print(('Written to: %s'):format(fname))
f:write(text)
f:close()
end
end
+--- The LSP protocol JSON data (it's partial, non-exhaustive).
+--- https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/lsp/3.18/metaModel/metaModel.schema.json
+--- @class vim._gen_lsp.Protocol
+--- @field requests vim._gen_lsp.Request[]
+--- @field notifications vim._gen_lsp.Notification[]
+--- @field structures vim._gen_lsp.Structure[]
+--- @field enumerations vim._gen_lsp.Enumeration[]
+--- @field typeAliases vim._gen_lsp.TypeAlias[]
+
+---@param opt vim._gen_lsp.opt
+---@return vim._gen_lsp.Protocol
local function read_json(opt)
local uri = 'https://raw.githubusercontent.com/microsoft/language-server-protocol/gh-pages/_specifications/lsp/'
.. opt.version
.. '/metaModel/metaModel.json'
+ print('Reading ' .. uri)
local res = vim.system({ 'curl', '--no-progress-meter', uri, '-o', '-' }):wait()
if res.code ~= 0 or (res.stdout or ''):len() < 999 then
@@ -34,11 +51,12 @@ local function read_json(opt)
end
-- Gets the Lua symbol for a given fully-qualified LSP method name.
-local function name(s)
+local function to_luaname(s)
-- "$/" prefix is special: https://microsoft.github.io/language-server-protocol/specification/#dollarRequests
return s:gsub('^%$', 'dollar'):gsub('/', '_')
end
+---@param protocol vim._gen_lsp.Protocol
local function gen_methods(protocol)
local output = {
'-- Generated by gen_lsp.lua, keep at end of file.',
@@ -49,9 +67,35 @@ local function gen_methods(protocol)
}
local indent = (' '):rep(2)
+ --- @class vim._gen_lsp.Request
+ --- @field deprecated? string
+ --- @field documentation? string
+ --- @field messageDirection string
+ --- @field method string
+ --- @field params? any
+ --- @field proposed? boolean
+ --- @field registrationMethod? string
+ --- @field registrationOptions? any
+ --- @field since? string
+
+ --- @class vim._gen_lsp.Notification
+ --- @field deprecated? string
+ --- @field documentation? string
+ --- @field errorData? any
+ --- @field messageDirection string
+ --- @field method string
+ --- @field params? any[]
+ --- @field partialResult? any
+ --- @field proposed? boolean
+ --- @field registrationMethod? string
+ --- @field registrationOptions? any
+ --- @field result any
+ --- @field since? string
+
+ ---@type (vim._gen_lsp.Request|vim._gen_lsp.Notification)[]
local all = vim.list_extend(protocol.requests, protocol.notifications)
table.sort(all, function(a, b)
- return name(a.method) < name(b.method)
+ return to_luaname(a.method) < to_luaname(b.method)
end)
for _, item in ipairs(all) do
if item.method then
@@ -61,7 +105,7 @@ local function gen_methods(protocol)
output[#output + 1] = indent .. '--- ' .. docstring
end
end
- output[#output + 1] = ("%s%s = '%s',"):format(indent, name(item.method), item.method)
+ output[#output + 1] = ("%s%s = '%s',"):format(indent, to_luaname(item.method), item.method)
end
end
output[#output + 1] = '}'
@@ -99,7 +143,14 @@ return protocol
vim.cmd.write()
end
+---@class vim._gen_lsp.opt
+---@field output_file string
+---@field version string
+---@field methods boolean
+
+---@param opt vim._gen_lsp.opt
function M.gen(opt)
+ --- @type vim._gen_lsp.Protocol
local protocol = read_json(opt)
if opt.methods then
@@ -107,25 +158,30 @@ function M.gen(opt)
end
local output = {
- '--[[',
- 'This file is autogenerated from scripts/gen_lsp.lua',
+ '--' .. '[[',
+ 'THIS FILE IS GENERATED by scripts/gen_lsp.lua',
+ 'DO NOT EDIT MANUALLY',
+ '',
+ 'Based on LSP protocol ' .. opt.version,
+ '',
'Regenerate:',
- [=[nvim -l scripts/gen_lsp.lua gen --version 3.18 --runtime/lua/vim/lsp/_meta/protocol.lua]=],
- '--]]',
+ ([=[nvim -l scripts/gen_lsp.lua gen --version %s]=]):format(DEFAULT_LSP_VERSION),
+ '--' .. ']]',
+ '',
+ '---@meta',
+ "error('Cannot require a meta file')",
'',
'---@alias lsp.null nil',
'---@alias uinteger integer',
- '---@alias lsp.decimal number',
+ '---@alias decimal number',
'---@alias lsp.DocumentUri string',
'---@alias lsp.URI string',
- '---@alias lsp.LSPObject table<string, lsp.LSPAny>',
- '---@alias lsp.LSPArray lsp.LSPAny[]',
- '---@alias lsp.LSPAny lsp.LSPObject|lsp.LSPArray|string|number|boolean|nil',
'',
}
local anonymous_num = 0
+ ---@type string[]
local anonym_classes = {}
local simple_types = {
@@ -136,95 +192,181 @@ function M.gen(opt)
'decimal',
}
- local function parse_type(type)
+ ---@param documentation string
+ local _process_documentation = function(documentation)
+ documentation = documentation:gsub('\n', '\n---')
+ -- Remove <200b> (zero-width space) unicode characters: e.g., `**/<200b>*`
+ documentation = documentation:gsub('\226\128\139', '')
+ -- Escape annotations that are not recognized by lua-ls
+ documentation = documentation:gsub('%^---@sample', '---\\@sample')
+ return '---' .. documentation
+ end
+
+ --- @class vim._gen_lsp.Type
+ --- @field kind string a common field for all Types.
+ --- @field name? string for ReferenceType, BaseType
+ --- @field element? any for ArrayType
+ --- @field items? vim._gen_lsp.Type[] for OrType, AndType
+ --- @field key? vim._gen_lsp.Type for MapType
+ --- @field value? string|vim._gen_lsp.Type for StringLiteralType, MapType, StructureLiteralType
+
+ ---@param type vim._gen_lsp.Type
+ ---@param prefix? string Optional prefix associated with the this type, made of (nested) field name.
+ --- Used to generate class name for structure literal types.
+ ---@return string
+ local function parse_type(type, prefix)
+ -- ReferenceType | BaseType
if type.kind == 'reference' or type.kind == 'base' then
if vim.tbl_contains(simple_types, type.name) then
return type.name
end
return 'lsp.' .. type.name
+
+ -- ArrayType
elseif type.kind == 'array' then
- return parse_type(type.element) .. '[]'
+ local parsed_items = parse_type(type.element, prefix)
+ if type.element.items and #type.element.items > 1 then
+ parsed_items = '(' .. parsed_items .. ')'
+ end
+ return parsed_items .. '[]'
+
+ -- OrType
elseif type.kind == 'or' then
local val = ''
for _, item in ipairs(type.items) do
- val = val .. parse_type(item) .. '|'
+ val = val .. parse_type(item, prefix) .. '|' --[[ @as string ]]
end
val = val:sub(0, -2)
return val
+
+ -- StringLiteralType
elseif type.kind == 'stringLiteral' then
return '"' .. type.value .. '"'
+
+ -- MapType
elseif type.kind == 'map' then
- return 'table<' .. parse_type(type.key) .. ', ' .. parse_type(type.value) .. '>'
+ local key = assert(type.key)
+ local value = type.value --[[ @as vim._gen_lsp.Type ]]
+ return 'table<' .. parse_type(key, prefix) .. ', ' .. parse_type(value, prefix) .. '>'
+
+ -- StructureLiteralType
elseif type.kind == 'literal' then
-- can I use ---@param disabled? {reason: string}
-- use | to continue the inline class to be able to add docs
-- https://github.com/LuaLS/lua-language-server/issues/2128
anonymous_num = anonymous_num + 1
- local anonym = { '---@class anonym' .. anonymous_num }
- for _, field in ipairs(type.value.properties) do
+ local anonymous_classname = 'lsp._anonym' .. anonymous_num
+ if prefix then
+ anonymous_classname = anonymous_classname .. '.' .. prefix
+ end
+ local anonym = vim.tbl_flatten { -- remove nil
+ anonymous_num > 1 and '' or nil,
+ '---@class ' .. anonymous_classname,
+ }
+
+ --- @class vim._gen_lsp.StructureLiteral translated to anonymous @class.
+ --- @field deprecated? string
+ --- @field description? string
+ --- @field properties vim._gen_lsp.Property[]
+ --- @field proposed? boolean
+ --- @field since? string
+
+ ---@type vim._gen_lsp.StructureLiteral
+ local structural_literal = assert(type.value) --[[ @as vim._gen_lsp.StructureLiteral ]]
+ for _, field in ipairs(structural_literal.properties) do
+ anonym[#anonym + 1] = '---'
if field.documentation then
- field.documentation = field.documentation:gsub('\n', '\n---')
- anonym[#anonym + 1] = '---' .. field.documentation
+ anonym[#anonym + 1] = _process_documentation(field.documentation)
end
anonym[#anonym + 1] = '---@field '
.. field.name
.. (field.optional and '?' or '')
.. ' '
- .. parse_type(field.type)
+ .. parse_type(field.type, prefix .. '.' .. field.name)
end
- anonym[#anonym + 1] = ''
+ -- anonym[#anonym + 1] = ''
for _, line in ipairs(anonym) do
- anonym_classes[#anonym_classes + 1] = line
+ if line then
+ anonym_classes[#anonym_classes + 1] = line
+ end
end
- return 'anonym' .. anonymous_num
+ return anonymous_classname
+
+ -- TupleType
elseif type.kind == 'tuple' then
local tuple = '{ '
for i, value in ipairs(type.items) do
- tuple = tuple .. '[' .. i .. ']: ' .. parse_type(value) .. ', '
+ tuple = tuple .. '[' .. i .. ']: ' .. parse_type(value, prefix) .. ', '
end
-- remove , at the end
tuple = tuple:sub(0, -3)
return tuple .. ' }'
end
- vim.print(type)
+
+ vim.print('WARNING: Unknown type ', type)
return ''
end
+ --- @class vim._gen_lsp.Structure translated to @class
+ --- @field deprecated? string
+ --- @field documentation? string
+ --- @field extends? { kind: string, name: string }[]
+ --- @field mixins? { kind: string, name: string }[]
+ --- @field name string
+ --- @field properties? vim._gen_lsp.Property[] members, translated to @field
+ --- @field proposed? boolean
+ --- @field since? string
for _, structure in ipairs(protocol.structures) do
+ -- output[#output + 1] = ''
if structure.documentation then
- structure.documentation = structure.documentation:gsub('\n', '\n---')
- output[#output + 1] = '---' .. structure.documentation
+ output[#output + 1] = _process_documentation(structure.documentation)
end
- if structure.extends then
- local class_string = '---@class lsp.'
- .. structure.name
- .. ': '
- .. parse_type(structure.extends[1])
- for _, mixin in ipairs(structure.mixins or {}) do
- class_string = class_string .. ', ' .. parse_type(mixin)
- end
- output[#output + 1] = class_string
- else
- output[#output + 1] = '---@class lsp.' .. structure.name
+ local class_string = ('---@class lsp.%s'):format(structure.name)
+ if structure.extends or structure.mixins then
+ local inherits_from = table.concat(
+ vim.list_extend(
+ vim.tbl_map(parse_type, structure.extends or {}),
+ vim.tbl_map(parse_type, structure.mixins or {})
+ ),
+ ', '
+ )
+ class_string = class_string .. ': ' .. inherits_from
end
+ output[#output + 1] = class_string
+
+ --- @class vim._gen_lsp.Property translated to @field
+ --- @field deprecated? string
+ --- @field documentation? string
+ --- @field name string
+ --- @field optional? boolean
+ --- @field proposed? boolean
+ --- @field since? string
+ --- @field type { kind: string, name: string }
for _, field in ipairs(structure.properties or {}) do
+ output[#output + 1] = '---' -- Insert a single newline between @fields (and after @class)
if field.documentation then
- field.documentation = field.documentation:gsub('\n', '\n---')
- output[#output + 1] = '---' .. field.documentation
+ output[#output + 1] = _process_documentation(field.documentation)
end
output[#output + 1] = '---@field '
.. field.name
.. (field.optional and '?' or '')
.. ' '
- .. parse_type(field.type)
+ .. parse_type(field.type, field.name)
end
output[#output + 1] = ''
end
+ --- @class vim._gen_lsp.Enumeration translated to @enum
+ --- @field deprecated string?
+ --- @field documentation string?
+ --- @field name string?
+ --- @field proposed boolean?
+ --- @field since string?
+ --- @field suportsCustomValues boolean?
+ --- @field values { name: string, value: string, documentation?: string, since?: string }[]
for _, enum in ipairs(protocol.enumerations) do
if enum.documentation then
- enum.documentation = enum.documentation:gsub('\n', '\n---')
- output[#output + 1] = '---' .. enum.documentation
+ output[#output + 1] = _process_documentation(enum.documentation)
end
local enum_type = '---@alias lsp.' .. enum.name
for _, value in ipairs(enum.values) do
@@ -238,53 +380,77 @@ function M.gen(opt)
output[#output + 1] = ''
end
+ --- @class vim._gen_lsp.TypeAlias translated to @alias
+ --- @field deprecated? string?
+ --- @field documentation? string
+ --- @field name string
+ --- @field proposed? boolean
+ --- @field since? string
+ --- @field type vim._gen_lsp.Type
for _, alias in ipairs(protocol.typeAliases) do
if alias.documentation then
- alias.documentation = alias.documentation:gsub('\n', '\n---')
- output[#output + 1] = '---' .. alias.documentation
+ output[#output + 1] = _process_documentation(alias.documentation)
end
if alias.type.kind == 'or' then
local alias_type = '---@alias lsp.' .. alias.name .. ' '
for _, item in ipairs(alias.type.items) do
- alias_type = alias_type .. parse_type(item) .. '|'
+ alias_type = alias_type .. parse_type(item, alias.name) .. '|'
end
alias_type = alias_type:sub(0, -2)
output[#output + 1] = alias_type
else
- output[#output + 1] = '---@alias lsp.' .. alias.name .. ' ' .. parse_type(alias.type)
+ output[#output + 1] = '---@alias lsp.'
+ .. alias.name
+ .. ' '
+ .. parse_type(alias.type, alias.name)
end
output[#output + 1] = ''
end
+ -- anonymous classes
for _, line in ipairs(anonym_classes) do
output[#output + 1] = line
end
- tofile(opt.output_file, table.concat(output, '\n'))
+ tofile(opt.output_file, table.concat(output, '\n') .. '\n')
end
+---@type vim._gen_lsp.opt
local opt = {
output_file = 'runtime/lua/vim/lsp/_meta/protocol.lua',
- version = nil,
- methods = nil,
+ version = DEFAULT_LSP_VERSION,
+ methods = false,
}
-for i = 1, #_G.arg do
+local command = nil
+local i = 1
+while i <= #_G.arg do
if _G.arg[i] == '--out' then
- opt.output_file = _G.arg[i + 1]
+ opt.output_file = assert(_G.arg[i + 1], '--out <outfile> needed')
+ i = i + 1
elseif _G.arg[i] == '--version' then
- opt.version = _G.arg[i + 1]
+ opt.version = assert(_G.arg[i + 1], '--version <version> needed')
+ i = i + 1
elseif _G.arg[i] == '--methods' then
opt.methods = true
- elseif vim.startswith(_G.arg[i], '--') then
- opt.output_file = _G.arg[i]:sub(3)
+ elseif vim.startswith(_G.arg[i], '-') then
+ error('Unrecognized args: ' .. _G.arg[i])
+ else
+ if command then
+ error('More than one command was given: ' .. _G.arg[i])
+ else
+ command = _G.arg[i]
+ end
end
+ i = i + 1
end
-for _, a in ipairs(arg) do
- if M[a] then
- M[a](opt)
- end
+if not command then
+ print(USAGE)
+elseif M[command] then
+ M[command](opt) -- see M.gen()
+else
+ error('Unknown command: ' .. command)
end
return M
diff --git a/scripts/gen_vimdoc.lua b/scripts/gen_vimdoc.lua
new file mode 100755
index 0000000000..22df411a35
--- /dev/null
+++ b/scripts/gen_vimdoc.lua
@@ -0,0 +1,953 @@
+#!/usr/bin/env -S nvim -l
+--- Generates Nvim :help docs from Lua/C docstrings
+---
+--- The generated :help text for each function is formatted as follows:
+--- - Max width of 78 columns (`TEXT_WIDTH`).
+--- - Indent with spaces (not tabs).
+--- - Indent of 4 columns for body text (`INDENTATION`).
+--- - Function signature and helptag (right-aligned) on the same line.
+--- - Signature and helptag must have a minimum of 8 spaces between them.
+--- - If the signature is too long, it is placed on the line after the helptag.
+--- Signature wraps with subsequent lines indented to the open parenthesis.
+--- - Subsection bodies are indented an additional 4 spaces.
+--- - Body consists of function description, parameters, return description, and
+--- C declaration (`INCLUDE_C_DECL`).
+--- - Parameters are omitted for the `void` and `Error *` types, or if the
+--- parameter is marked as [out].
+--- - Each function documentation is separated by a single line.
+
+local luacats_parser = require('scripts.luacats_parser')
+local cdoc_parser = require('scripts.cdoc_parser')
+local text_utils = require('scripts.text_utils')
+
+local fmt = string.format
+
+local wrap = text_utils.wrap
+local md_to_vimdoc = text_utils.md_to_vimdoc
+
+local TEXT_WIDTH = 78
+local INDENTATION = 4
+
+--- @class (exact) nvim.gen_vimdoc.Config
+---
+--- Generated documentation target, e.g. api.txt
+--- @field filename string
+---
+--- @field section_order string[]
+---
+--- List of files/directories for doxygen to read, relative to `base_dir`.
+--- @field files string[]
+---
+--- @field exclude_types? true
+---
+--- Section name overrides. Key: filename (e.g., vim.c)
+--- @field section_name? table<string,string>
+---
+--- @field fn_name_pat? string
+---
+--- @field fn_xform? fun(fun: nvim.luacats.parser.fun)
+---
+--- For generated section names.
+--- @field section_fmt fun(name: string): string
+---
+--- @field helptag_fmt fun(name: string): string
+---
+--- Per-function helptag.
+--- @field fn_helptag_fmt? fun(fun: nvim.luacats.parser.fun): string
+---
+--- @field append_only? string[]
+
+local function contains(t, xs)
+ return vim.tbl_contains(xs, t)
+end
+
+--- @type {level:integer, prerelease:boolean}?
+local nvim_api_info_
+
+--- @return {level: integer, prerelease:boolean}
+local function nvim_api_info()
+ if not nvim_api_info_ then
+ --- @type integer?, boolean?
+ local level, prerelease
+ for l in io.lines('CMakeLists.txt') do
+ --- @cast l string
+ if level and prerelease then
+ break
+ end
+ local m1 = l:match('^set%(NVIM_API_LEVEL%s+(%d+)%)')
+ if m1 then
+ level = tonumber(m1) --[[@as integer]]
+ end
+ local m2 = l:match('^set%(NVIM_API_PRERELEASE%s+(%w+)%)')
+ if m2 then
+ prerelease = m2 == 'true'
+ end
+ end
+ nvim_api_info_ = { level = level, prerelease = prerelease }
+ end
+
+ return nvim_api_info_
+end
+
+--- @param fun nvim.luacats.parser.fun
+--- @return string
+local function fn_helptag_fmt_common(fun)
+ local fn_sfx = fun.table and '' or '()'
+ if fun.classvar then
+ return fmt('*%s:%s%s*', fun.classvar, fun.name, fn_sfx)
+ end
+ if fun.module then
+ return fmt('*%s.%s%s*', fun.module, fun.name, fn_sfx)
+ end
+ return fmt('*%s%s*', fun.name, fn_sfx)
+end
+
+--- @type table<string,nvim.gen_vimdoc.Config>
+local config = {
+ api = {
+ filename = 'api.txt',
+ section_order = {
+ 'vim.c',
+ 'vimscript.c',
+ 'command.c',
+ 'options.c',
+ 'buffer.c',
+ 'extmark.c',
+ 'window.c',
+ 'win_config.c',
+ 'tabpage.c',
+ 'autocmd.c',
+ 'ui.c',
+ },
+ exclude_types = true,
+ fn_name_pat = 'nvim_.*',
+ files = { 'src/nvim/api' },
+ section_name = {
+ ['vim.c'] = 'Global',
+ },
+ section_fmt = function(name)
+ return name .. ' Functions'
+ end,
+ helptag_fmt = function(name)
+ return fmt('*api-%s*', name:lower())
+ end,
+ },
+ lua = {
+ filename = 'lua.txt',
+ section_order = {
+ 'highlight.lua',
+ 'diff.lua',
+ 'mpack.lua',
+ 'json.lua',
+ 'base64.lua',
+ 'spell.lua',
+ 'builtin.lua',
+ '_options.lua',
+ '_editor.lua',
+ '_inspector.lua',
+ 'shared.lua',
+ 'loader.lua',
+ 'uri.lua',
+ 'ui.lua',
+ 'filetype.lua',
+ 'keymap.lua',
+ 'fs.lua',
+ 'glob.lua',
+ 'lpeg.lua',
+ 're.lua',
+ 'regex.lua',
+ 'secure.lua',
+ 'version.lua',
+ 'iter.lua',
+ 'snippet.lua',
+ 'text.lua',
+ 'tohtml.lua',
+ },
+ files = {
+ 'runtime/lua/vim/iter.lua',
+ 'runtime/lua/vim/_editor.lua',
+ 'runtime/lua/vim/_options.lua',
+ 'runtime/lua/vim/shared.lua',
+ 'runtime/lua/vim/loader.lua',
+ 'runtime/lua/vim/uri.lua',
+ 'runtime/lua/vim/ui.lua',
+ 'runtime/lua/vim/filetype.lua',
+ 'runtime/lua/vim/keymap.lua',
+ 'runtime/lua/vim/fs.lua',
+ 'runtime/lua/vim/highlight.lua',
+ 'runtime/lua/vim/secure.lua',
+ 'runtime/lua/vim/version.lua',
+ 'runtime/lua/vim/_inspector.lua',
+ 'runtime/lua/vim/snippet.lua',
+ 'runtime/lua/vim/text.lua',
+ 'runtime/lua/vim/glob.lua',
+ 'runtime/lua/vim/_meta/builtin.lua',
+ 'runtime/lua/vim/_meta/diff.lua',
+ 'runtime/lua/vim/_meta/mpack.lua',
+ 'runtime/lua/vim/_meta/json.lua',
+ 'runtime/lua/vim/_meta/base64.lua',
+ 'runtime/lua/vim/_meta/regex.lua',
+ 'runtime/lua/vim/_meta/lpeg.lua',
+ 'runtime/lua/vim/_meta/re.lua',
+ 'runtime/lua/vim/_meta/spell.lua',
+ 'runtime/lua/tohtml.lua',
+ },
+ fn_xform = function(fun)
+ if contains(fun.module, { 'vim.uri', 'vim.shared', 'vim._editor' }) then
+ fun.module = 'vim'
+ end
+
+ if fun.module == 'vim' and contains(fun.name, { 'cmd', 'inspect' }) then
+ fun.table = nil
+ end
+
+ if fun.classvar or vim.startswith(fun.name, 'vim.') or fun.module == 'vim.iter' then
+ return
+ end
+
+ fun.name = fmt('%s.%s', fun.module, fun.name)
+ end,
+ section_name = {
+ ['_inspector.lua'] = 'inspector',
+ },
+ section_fmt = function(name)
+ name = name:lower()
+ if name == '_editor' then
+ return 'Lua module: vim'
+ elseif name == '_options' then
+ return 'LUA-VIMSCRIPT BRIDGE'
+ elseif name == 'builtin' then
+ return 'VIM'
+ end
+ if
+ contains(name, {
+ 'highlight',
+ 'mpack',
+ 'json',
+ 'base64',
+ 'diff',
+ 'spell',
+ 'regex',
+ 'lpeg',
+ 're',
+ })
+ then
+ return 'VIM.' .. name:upper()
+ end
+ if name == 'tohtml' then
+ return 'Lua module: tohtml'
+ end
+ return 'Lua module: vim.' .. name
+ end,
+ helptag_fmt = function(name)
+ if name == '_editor' then
+ return '*lua-vim*'
+ elseif name == '_options' then
+ return '*lua-vimscript*'
+ elseif name == 'tohtml' then
+ return '*tohtml*'
+ end
+ return '*vim.' .. name:lower() .. '*'
+ end,
+ fn_helptag_fmt = function(fun)
+ local name = fun.name
+
+ if vim.startswith(name, 'vim.') then
+ local fn_sfx = fun.table and '' or '()'
+ return fmt('*%s%s*', name, fn_sfx)
+ elseif fun.classvar == 'Option' then
+ return fmt('*vim.opt:%s()*', name)
+ end
+
+ return fn_helptag_fmt_common(fun)
+ end,
+ append_only = {
+ 'shared.lua',
+ },
+ },
+ lsp = {
+ filename = 'lsp.txt',
+ section_order = {
+ 'lsp.lua',
+ 'client.lua',
+ 'buf.lua',
+ 'diagnostic.lua',
+ 'codelens.lua',
+ 'inlay_hint.lua',
+ 'tagfunc.lua',
+ 'semantic_tokens.lua',
+ 'handlers.lua',
+ 'util.lua',
+ 'log.lua',
+ 'rpc.lua',
+ 'protocol.lua',
+ },
+ files = {
+ 'runtime/lua/vim/lsp',
+ 'runtime/lua/vim/lsp.lua',
+ },
+ fn_xform = function(fun)
+ fun.name = fun.name:gsub('result%.', '')
+ end,
+ section_fmt = function(name)
+ if name:lower() == 'lsp' then
+ return 'Lua module: vim.lsp'
+ end
+ return 'Lua module: vim.lsp.' .. name:lower()
+ end,
+ helptag_fmt = function(name)
+ if name:lower() == 'lsp' then
+ return '*lsp-core*'
+ end
+ return fmt('*lsp-%s*', name:lower())
+ end,
+ },
+ diagnostic = {
+ filename = 'diagnostic.txt',
+ section_order = {
+ 'diagnostic.lua',
+ },
+ files = { 'runtime/lua/vim/diagnostic.lua' },
+ section_fmt = function()
+ return 'Lua module: vim.diagnostic'
+ end,
+ helptag_fmt = function()
+ return '*diagnostic-api*'
+ end,
+ },
+ treesitter = {
+ filename = 'treesitter.txt',
+ section_order = {
+ 'treesitter.lua',
+ 'language.lua',
+ 'query.lua',
+ 'highlighter.lua',
+ 'languagetree.lua',
+ 'dev.lua',
+ },
+ files = {
+ 'runtime/lua/vim/treesitter.lua',
+ 'runtime/lua/vim/treesitter/',
+ },
+ section_fmt = function(name)
+ if name:lower() == 'treesitter' then
+ return 'Lua module: vim.treesitter'
+ end
+ return 'Lua module: vim.treesitter.' .. name:lower()
+ end,
+ helptag_fmt = function(name)
+ if name:lower() == 'treesitter' then
+ return '*lua-treesitter-core*'
+ end
+ return '*lua-treesitter-' .. name:lower() .. '*'
+ end,
+ },
+}
+
+--- @param ty string
+--- @param generics table<string,string>
+--- @return string
+local function replace_generics(ty, generics)
+ if ty:sub(-2) == '[]' then
+ local ty0 = ty:sub(1, -3)
+ if generics[ty0] then
+ return generics[ty0] .. '[]'
+ end
+ elseif ty:sub(-1) == '?' then
+ local ty0 = ty:sub(1, -2)
+ if generics[ty0] then
+ return generics[ty0] .. '?'
+ end
+ end
+
+ return generics[ty] or ty
+end
+
+--- @param name string
+local function fmt_field_name(name)
+ local name0, opt = name:match('^([^?]*)(%??)$')
+ return fmt('{%s}%s', name0, opt)
+end
+
+--- @param ty string
+--- @param generics? table<string,string>
+--- @param default? string
+local function render_type(ty, generics, default)
+ if generics then
+ ty = replace_generics(ty, generics)
+ end
+ ty = ty:gsub('%s*|%s*nil', '?')
+ ty = ty:gsub('nil%s*|%s*(.*)', '%1?')
+ ty = ty:gsub('%s*|%s*', '|')
+ if default then
+ return fmt('(`%s`, default: %s)', ty, default)
+ end
+ return fmt('(`%s`)', ty)
+end
+
+--- @param p nvim.luacats.parser.param|nvim.luacats.parser.field
+local function should_render_param(p)
+ return not p.access and not contains(p.name, { '_', 'self' })
+end
+
+--- @param desc? string
+--- @return string?, string?
+local function get_default(desc)
+ if not desc then
+ return
+ end
+
+ local default = desc:match('\n%s*%([dD]efault: ([^)]+)%)')
+ if default then
+ desc = desc:gsub('\n%s*%([dD]efault: [^)]+%)', '')
+ end
+
+ return desc, default
+end
+
+--- @param ty string
+--- @param classes? table<string,nvim.luacats.parser.class>
+--- @return nvim.luacats.parser.class?
+local function get_class(ty, classes)
+ if not classes then
+ return
+ end
+
+ local cty = ty:gsub('%s*|%s*nil', '?'):gsub('?$', ''):gsub('%[%]$', '')
+
+ return classes[cty]
+end
+
+--- @param obj nvim.luacats.parser.param|nvim.luacats.parser.return|nvim.luacats.parser.field
+--- @param classes? table<string,nvim.luacats.parser.class>
+local function inline_type(obj, classes)
+ local ty = obj.type
+ if not ty then
+ return
+ end
+
+ local cls = get_class(ty, classes)
+
+ if not cls or cls.nodoc then
+ return
+ end
+
+ if not cls.inlinedoc then
+ -- Not inlining so just add a: "See |tag|."
+ local tag = fmt('|%s|', cls.name)
+ if obj.desc and obj.desc:find(tag) then
+ -- Tag already there
+ return
+ end
+
+ -- TODO(lewis6991): Aim to remove this. Need this to prevent dead
+ -- references to types defined in runtime/lua/vim/lsp/_meta/protocol.lua
+ if not vim.startswith(cls.name, 'vim.') then
+ return
+ end
+
+ obj.desc = obj.desc or ''
+ local period = (obj.desc == '' or vim.endswith(obj.desc, '.')) and '' or '.'
+ obj.desc = obj.desc .. fmt('%s See %s.', period, tag)
+ return
+ end
+
+ local ty_isopt = (ty:match('%?$') or ty:match('%s*|%s*nil')) ~= nil
+ local ty_islist = (ty:match('%[%]$')) ~= nil
+ ty = ty_isopt and 'table?' or ty_islist and 'table[]' or 'table'
+
+ local desc = obj.desc or ''
+ if cls.desc then
+ desc = desc .. cls.desc
+ elseif desc == '' then
+ if ty_islist then
+ desc = desc .. 'A list of objects with the following fields:'
+ else
+ desc = desc .. 'A table with the following fields:'
+ end
+ end
+
+ local desc_append = {}
+ for _, f in ipairs(cls.fields) do
+ local fdesc, default = get_default(f.desc)
+ local fty = render_type(f.type, nil, default)
+ local fnm = fmt_field_name(f.name)
+ table.insert(desc_append, table.concat({ '-', fnm, fty, fdesc }, ' '))
+ end
+
+ desc = desc .. '\n' .. table.concat(desc_append, '\n')
+ obj.type = ty
+ obj.desc = desc
+end
+
+--- @param xs (nvim.luacats.parser.param|nvim.luacats.parser.field)[]
+--- @param generics? table<string,string>
+--- @param classes? table<string,nvim.luacats.parser.class>
+--- @param exclude_types? true
+local function render_fields_or_params(xs, generics, classes, exclude_types)
+ local ret = {} --- @type string[]
+
+ xs = vim.tbl_filter(should_render_param, xs)
+
+ local indent = 0
+ for _, p in ipairs(xs) do
+ if p.type or p.desc then
+ indent = math.max(indent, #p.name + 3)
+ end
+ if exclude_types then
+ p.type = nil
+ end
+ end
+
+ for _, p in ipairs(xs) do
+ local pdesc, default = get_default(p.desc)
+ p.desc = pdesc
+
+ inline_type(p, classes)
+ local nm, ty, desc = p.name, p.type, p.desc
+
+ local fnm = p.kind == 'operator' and fmt('op(%s)', nm) or fmt_field_name(nm)
+ local pnm = fmt(' • %-' .. indent .. 's', fnm)
+
+ if ty then
+ local pty = render_type(ty, generics, default)
+
+ if desc then
+ table.insert(ret, pnm)
+ if #pty > TEXT_WIDTH - indent then
+ vim.list_extend(ret, { ' ', pty, '\n' })
+ table.insert(ret, md_to_vimdoc(desc, 9 + indent, 9 + indent, TEXT_WIDTH, true))
+ else
+ desc = fmt('%s %s', pty, desc)
+ table.insert(ret, md_to_vimdoc(desc, 1, 9 + indent, TEXT_WIDTH, true))
+ end
+ else
+ table.insert(ret, fmt('%s %s\n', pnm, pty))
+ end
+ else
+ if desc then
+ table.insert(ret, pnm)
+ table.insert(ret, md_to_vimdoc(desc, 1, 9 + indent, TEXT_WIDTH, true))
+ end
+ end
+ end
+
+ return table.concat(ret)
+end
+
+--- @param class nvim.luacats.parser.class
+--- @param classes table<string,nvim.luacats.parser.class>
+local function render_class(class, classes)
+ if class.access or class.nodoc or class.inlinedoc then
+ return
+ end
+
+ local ret = {} --- @type string[]
+
+ table.insert(ret, fmt('*%s*\n', class.name))
+
+ if class.parent then
+ local txt = fmt('Extends: |%s|', class.parent)
+ table.insert(ret, md_to_vimdoc(txt, INDENTATION, INDENTATION, TEXT_WIDTH))
+ table.insert(ret, '\n')
+ end
+
+ if class.desc then
+ table.insert(ret, md_to_vimdoc(class.desc, INDENTATION, INDENTATION, TEXT_WIDTH))
+ end
+
+ local fields_txt = render_fields_or_params(class.fields, nil, classes)
+ if not fields_txt:match('^%s*$') then
+ table.insert(ret, '\n Fields: ~\n')
+ table.insert(ret, fields_txt)
+ end
+ table.insert(ret, '\n')
+
+ return table.concat(ret)
+end
+
+--- @param classes table<string,nvim.luacats.parser.class>
+local function render_classes(classes)
+ local ret = {} --- @type string[]
+
+ for _, class in vim.spairs(classes) do
+ ret[#ret + 1] = render_class(class, classes)
+ end
+
+ return table.concat(ret)
+end
+
+--- @param fun nvim.luacats.parser.fun
+--- @param cfg nvim.gen_vimdoc.Config
+local function render_fun_header(fun, cfg)
+ local ret = {} --- @type string[]
+
+ local args = {} --- @type string[]
+ for _, p in ipairs(fun.params or {}) do
+ if p.name ~= 'self' then
+ args[#args + 1] = fmt_field_name(p.name)
+ end
+ end
+
+ local nm = fun.name
+ if fun.classvar then
+ nm = fmt('%s:%s', fun.classvar, nm)
+ end
+
+ local proto = fun.table and nm or nm .. '(' .. table.concat(args, ', ') .. ')'
+
+ if not cfg.fn_helptag_fmt then
+ cfg.fn_helptag_fmt = fn_helptag_fmt_common
+ end
+
+ local tag = cfg.fn_helptag_fmt(fun)
+
+ if #proto + #tag > TEXT_WIDTH - 8 then
+ table.insert(ret, fmt('%78s\n', tag))
+ local name, pargs = proto:match('([^(]+%()(.*)')
+ table.insert(ret, name)
+ table.insert(ret, wrap(pargs, 0, #name, TEXT_WIDTH))
+ else
+ local pad = TEXT_WIDTH - #proto - #tag
+ table.insert(ret, proto .. string.rep(' ', pad) .. tag)
+ end
+
+ return table.concat(ret)
+end
+
+--- @param returns nvim.luacats.parser.return[]
+--- @param generics? table<string,string>
+--- @param classes? table<string,nvim.luacats.parser.class>
+--- @param exclude_types boolean
+local function render_returns(returns, generics, classes, exclude_types)
+ local ret = {} --- @type string[]
+
+ returns = vim.deepcopy(returns)
+ if exclude_types then
+ for _, r in ipairs(returns) do
+ r.type = nil
+ end
+ end
+
+ if #returns > 1 then
+ table.insert(ret, ' Return (multiple): ~\n')
+ elseif #returns == 1 and next(returns[1]) then
+ table.insert(ret, ' Return: ~\n')
+ end
+
+ for _, p in ipairs(returns) do
+ inline_type(p, classes)
+ local rnm, ty, desc = p.name, p.type, p.desc
+
+ local blk = {} --- @type string[]
+ if ty then
+ blk[#blk + 1] = render_type(ty, generics)
+ end
+ blk[#blk + 1] = rnm
+ blk[#blk + 1] = desc
+
+ table.insert(ret, md_to_vimdoc(table.concat(blk, ' '), 8, 8, TEXT_WIDTH, true))
+ end
+
+ return table.concat(ret)
+end
+
+--- @param fun nvim.luacats.parser.fun
+--- @param classes table<string,nvim.luacats.parser.class>
+--- @param cfg nvim.gen_vimdoc.Config
+local function render_fun(fun, classes, cfg)
+ if fun.access or fun.deprecated or fun.nodoc then
+ return
+ end
+
+ if cfg.fn_name_pat and not fun.name:match(cfg.fn_name_pat) then
+ return
+ end
+
+ if vim.startswith(fun.name, '_') or fun.name:find('[:.]_') then
+ return
+ end
+
+ local ret = {} --- @type string[]
+
+ table.insert(ret, render_fun_header(fun, cfg))
+ table.insert(ret, '\n')
+
+ if fun.desc then
+ table.insert(ret, md_to_vimdoc(fun.desc, INDENTATION, INDENTATION, TEXT_WIDTH))
+ end
+
+ if fun.since then
+ local since = tonumber(fun.since)
+ local info = nvim_api_info()
+ if since and (since > info.level or since == info.level and info.prerelease) then
+ fun.notes = fun.notes or {}
+ table.insert(fun.notes, { desc = 'This API is pre-release (unstable).' })
+ end
+ end
+
+ if fun.notes then
+ table.insert(ret, '\n Note: ~\n')
+ for _, p in ipairs(fun.notes) do
+ table.insert(ret, ' • ' .. md_to_vimdoc(p.desc, 0, 8, TEXT_WIDTH, true))
+ end
+ end
+
+ if fun.attrs then
+ table.insert(ret, '\n Attributes: ~\n')
+ for _, attr in ipairs(fun.attrs) do
+ local attr_str = ({
+ textlock = 'not allowed when |textlock| is active or in the |cmdwin|',
+ textlock_allow_cmdwin = 'not allowed when |textlock| is active',
+ fast = '|api-fast|',
+ remote_only = '|RPC| only',
+ lua_only = 'Lua |vim.api| only',
+ })[attr] or attr
+ table.insert(ret, fmt(' %s\n', attr_str))
+ end
+ end
+
+ if fun.params and #fun.params > 0 then
+ local param_txt = render_fields_or_params(fun.params, fun.generics, classes, cfg.exclude_types)
+ if not param_txt:match('^%s*$') then
+ table.insert(ret, '\n Parameters: ~\n')
+ ret[#ret + 1] = param_txt
+ end
+ end
+
+ if fun.returns then
+ local txt = render_returns(fun.returns, fun.generics, classes, cfg.exclude_types)
+ if not txt:match('^%s*$') then
+ table.insert(ret, '\n')
+ ret[#ret + 1] = txt
+ end
+ end
+
+ if fun.see then
+ table.insert(ret, '\n See also: ~\n')
+ for _, p in ipairs(fun.see) do
+ table.insert(ret, ' • ' .. md_to_vimdoc(p.desc, 0, 8, TEXT_WIDTH, true))
+ end
+ end
+
+ table.insert(ret, '\n')
+ return table.concat(ret)
+end
+
+--- @param funs nvim.luacats.parser.fun[]
+--- @param classes table<string,nvim.luacats.parser.class>
+--- @param cfg nvim.gen_vimdoc.Config
+local function render_funs(funs, classes, cfg)
+ local ret = {} --- @type string[]
+
+ for _, f in ipairs(funs) do
+ if cfg.fn_xform then
+ cfg.fn_xform(f)
+ end
+ ret[#ret + 1] = render_fun(f, classes, cfg)
+ end
+
+ -- Sort via prototype
+ table.sort(ret, function(a, b)
+ local a1 = ('\n' .. a):match('\n[a-zA-Z_][^\n]+\n')
+ local b1 = ('\n' .. b):match('\n[a-zA-Z_][^\n]+\n')
+ return a1:lower() < b1:lower()
+ end)
+
+ return table.concat(ret)
+end
+
+--- @return string
+local function get_script_path()
+ local str = debug.getinfo(2, 'S').source:sub(2)
+ return str:match('(.*[/\\])') or './'
+end
+
+local script_path = get_script_path()
+local base_dir = vim.fs.dirname(assert(vim.fs.dirname(script_path)))
+
+local function delete_lines_below(doc_file, tokenstr)
+ local lines = {} --- @type string[]
+ local found = false
+ for line in io.lines(doc_file) do
+ if line:find(vim.pesc(tokenstr)) then
+ found = true
+ break
+ end
+ lines[#lines + 1] = line
+ end
+ if not found then
+ error(fmt('not found: %s in %s', tokenstr, doc_file))
+ end
+ lines[#lines] = nil
+ local fp = assert(io.open(doc_file, 'w'))
+ fp:write(table.concat(lines, '\n'))
+ fp:write('\n')
+ fp:close()
+end
+
+--- @param x string
+local function mktitle(x)
+ if x == 'ui' then
+ return 'UI'
+ end
+ return x:sub(1, 1):upper() .. x:sub(2)
+end
+
+--- @class nvim.gen_vimdoc.Section
+--- @field name string
+--- @field title string
+--- @field help_tag string
+--- @field funs_txt string
+--- @field doc? string[]
+
+--- @param filename string
+--- @param cfg nvim.gen_vimdoc.Config
+--- @param section_docs table<string,nvim.gen_vimdoc.Section>
+--- @param funs_txt string
+--- @return nvim.gen_vimdoc.Section?
+local function make_section(filename, cfg, section_docs, funs_txt)
+ -- filename: e.g., 'autocmd.c'
+ -- name: e.g. 'autocmd'
+ local name = filename:match('(.*)%.[a-z]+')
+
+ -- Formatted (this is what's going to be written in the vimdoc)
+ -- e.g., "Autocmd Functions"
+ local sectname = cfg.section_name and cfg.section_name[filename] or mktitle(name)
+
+ -- section tag: e.g., "*api-autocmd*"
+ local help_tag = cfg.helptag_fmt(sectname)
+
+ if funs_txt == '' and #section_docs == 0 then
+ return
+ end
+
+ return {
+ name = sectname,
+ title = cfg.section_fmt(sectname),
+ help_tag = help_tag,
+ funs_txt = funs_txt,
+ doc = section_docs,
+ }
+end
+
+--- @param section nvim.gen_vimdoc.Section
+--- @param add_header? boolean
+local function render_section(section, add_header)
+ local doc = {} --- @type string[]
+
+ if add_header ~= false then
+ vim.list_extend(doc, {
+ string.rep('=', TEXT_WIDTH),
+ '\n',
+ section.title,
+ fmt('%' .. (TEXT_WIDTH - section.title:len()) .. 's', section.help_tag),
+ })
+ end
+
+ if section.doc and #section.doc > 0 then
+ table.insert(doc, '\n\n')
+ vim.list_extend(doc, section.doc)
+ end
+
+ if section.funs_txt then
+ table.insert(doc, '\n\n')
+ table.insert(doc, section.funs_txt)
+ end
+
+ return table.concat(doc)
+end
+
+local parsers = {
+ lua = luacats_parser.parse,
+ c = cdoc_parser.parse,
+ h = cdoc_parser.parse,
+}
+
+--- @param files string[]
+local function expand_files(files)
+ for k, f in pairs(files) do
+ if vim.fn.isdirectory(f) == 1 then
+ table.remove(files, k)
+ for path, ty in vim.fs.dir(f) do
+ if ty == 'file' then
+ table.insert(files, vim.fs.joinpath(f, path))
+ end
+ end
+ end
+ end
+end
+
+--- @param cfg nvim.gen_vimdoc.Config
+local function gen_target(cfg)
+ local sections = {} --- @type table<string,nvim.gen_vimdoc.Section>
+
+ expand_files(cfg.files)
+
+ --- @type table<string,{[1]:table<string,nvim.luacats.parser.class>, [2]: nvim.luacats.parser.fun[], [3]: string[]}>
+ local file_results = {}
+
+ --- @type table<string,nvim.luacats.parser.class>
+ local all_classes = {}
+
+ --- First pass so we can collect all classes
+ for _, f in pairs(cfg.files) do
+ local ext = assert(f:match('%.([^.]+)$')) --[[@as 'h'|'c'|'lua']]
+ local parser = assert(parsers[ext])
+ local classes, funs, briefs = parser(f)
+ file_results[f] = { classes, funs, briefs }
+ all_classes = vim.tbl_extend('error', all_classes, classes)
+ end
+
+ for f, r in pairs(file_results) do
+ local classes, funs, briefs = r[1], r[2], r[3]
+
+ local briefs_txt = {} --- @type string[]
+ for _, b in ipairs(briefs) do
+ briefs_txt[#briefs_txt + 1] = md_to_vimdoc(b, 0, 0, TEXT_WIDTH)
+ end
+ local funs_txt = render_funs(funs, all_classes, cfg)
+ if next(classes) then
+ local classes_txt = render_classes(classes)
+ if vim.trim(classes_txt) ~= '' then
+ funs_txt = classes_txt .. '\n' .. funs_txt
+ end
+ end
+ -- FIXME: Using f_base will confuse `_meta/protocol.lua` with `protocol.lua`
+ local f_base = assert(vim.fs.basename(f))
+ sections[f_base] = make_section(f_base, cfg, briefs_txt, funs_txt)
+ end
+
+ local first_section_tag = sections[cfg.section_order[1]].help_tag
+ local docs = {} --- @type string[]
+ for _, f in ipairs(cfg.section_order) do
+ local section = sections[f]
+ if section then
+ local add_sep_and_header = not vim.tbl_contains(cfg.append_only or {}, f)
+ table.insert(docs, render_section(section, add_sep_and_header))
+ end
+ end
+
+ table.insert(
+ docs,
+ fmt(' vim:tw=78:ts=8:sw=%d:sts=%d:et:ft=help:norl:\n', INDENTATION, INDENTATION)
+ )
+
+ local doc_file = vim.fs.joinpath(base_dir, 'runtime', 'doc', cfg.filename)
+
+ if vim.uv.fs_stat(doc_file) then
+ delete_lines_below(doc_file, first_section_tag)
+ end
+
+ local fp = assert(io.open(doc_file, 'a'))
+ fp:write(table.concat(docs, '\n'))
+ fp:close()
+end
+
+local function run()
+ for _, cfg in pairs(config) do
+ gen_target(cfg)
+ end
+end
+
+run()
diff --git a/scripts/gen_vimdoc.py b/scripts/gen_vimdoc.py
deleted file mode 100755
index 8ed88cb8f5..0000000000
--- a/scripts/gen_vimdoc.py
+++ /dev/null
@@ -1,1447 +0,0 @@
-#!/usr/bin/env python3
-"""Generates Nvim :help docs from C/Lua docstrings, using Doxygen.
-
-Also generates *.mpack files. To inspect the *.mpack structure:
- :new | put=v:lua.vim.inspect(v:lua.vim.mpack.decode(readfile('runtime/doc/api.mpack','B')))
-
-Flow:
- main
- extract_from_xml
- fmt_node_as_vimhelp \
- para_as_map } recursive
- update_params_map /
- render_node
-
-TODO: eliminate this script and use Lua+treesitter (requires parsers for C and
-Lua markdown-style docstrings).
-
-The generated :help text for each function is formatted as follows:
-
- - Max width of 78 columns (`text_width`).
- - Indent with spaces (not tabs).
- - Indent of 4 columns for body text (`indentation`).
- - Function signature and helptag (right-aligned) on the same line.
- - Signature and helptag must have a minimum of 8 spaces between them.
- - If the signature is too long, it is placed on the line after the helptag.
- Signature wraps at `text_width - 8` characters with subsequent
- lines indented to the open parenthesis.
- - Subsection bodies are indented an additional 4 spaces.
- - Body consists of function description, parameters, return description, and
- C declaration (`INCLUDE_C_DECL`).
- - Parameters are omitted for the `void` and `Error *` types, or if the
- parameter is marked as [out].
- - Each function documentation is separated by a single line.
-"""
-import argparse
-import os
-import re
-import sys
-import shutil
-import textwrap
-import subprocess
-import collections
-import msgpack
-import logging
-from typing import Tuple
-from pathlib import Path
-
-from xml.dom import minidom
-Element = minidom.Element
-Document = minidom.Document
-
-MIN_PYTHON_VERSION = (3, 6)
-MIN_DOXYGEN_VERSION = (1, 9, 0)
-
-if sys.version_info < MIN_PYTHON_VERSION:
- print("requires Python {}.{}+".format(*MIN_PYTHON_VERSION))
- sys.exit(1)
-
-doxygen_version = tuple((int(i) for i in subprocess.check_output(["doxygen", "-v"],
- universal_newlines=True).split()[0].split('.')))
-
-if doxygen_version < MIN_DOXYGEN_VERSION:
- print("\nRequires doxygen {}.{}.{}+".format(*MIN_DOXYGEN_VERSION))
- print("Your doxygen version is {}.{}.{}\n".format(*doxygen_version))
- sys.exit(1)
-
-
-# Need a `nvim` that supports `-l`, try the local build
-nvim_path = Path(__file__).parent / "../build/bin/nvim"
-if nvim_path.exists():
- nvim = str(nvim_path)
-else:
- # Until 0.9 is released, use this hacky way to check that "nvim -l foo.lua" works.
- nvim_out = subprocess.check_output(['nvim', '-h'], universal_newlines=True)
- nvim_version = [line for line in nvim_out.split('\n')
- if '-l ' in line]
- if len(nvim_version) == 0:
- print((
- "\nYou need to have a local Neovim build or a `nvim` version 0.9 for `-l` "
- "support to build the documentation."))
- sys.exit(1)
- nvim = 'nvim'
-
-
-# DEBUG = ('DEBUG' in os.environ)
-INCLUDE_C_DECL = ('INCLUDE_C_DECL' in os.environ)
-INCLUDE_DEPRECATED = ('INCLUDE_DEPRECATED' in os.environ)
-
-log = logging.getLogger(__name__)
-
-LOG_LEVELS = {
- logging.getLevelName(level): level for level in [
- logging.DEBUG, logging.INFO, logging.ERROR
- ]
-}
-
-text_width = 78
-indentation = 4
-script_path = os.path.abspath(__file__)
-base_dir = os.path.dirname(os.path.dirname(script_path))
-out_dir = os.path.join(base_dir, 'tmp-{target}-doc')
-filter_cmd = '%s %s' % (sys.executable, script_path)
-msgs = [] # Messages to show on exit.
-lua2dox = os.path.join(base_dir, 'scripts', 'lua2dox.lua')
-
-CONFIG = {
- 'api': {
- 'mode': 'c',
- 'filename': 'api.txt',
- # Section ordering.
- 'section_order': [
- 'vim.c',
- 'vimscript.c',
- 'command.c',
- 'options.c',
- 'buffer.c',
- 'extmark.c',
- 'window.c',
- 'win_config.c',
- 'tabpage.c',
- 'autocmd.c',
- 'ui.c',
- ],
- # List of files/directories for doxygen to read, relative to `base_dir`
- 'files': ['src/nvim/api'],
- # file patterns used by doxygen
- 'file_patterns': '*.h *.c',
- # Only function with this prefix are considered
- 'fn_name_prefix': 'nvim_',
- # Section name overrides.
- 'section_name': {
- 'vim.c': 'Global',
- },
- # For generated section names.
- 'section_fmt': lambda name: f'{name} Functions',
- # Section helptag.
- 'helptag_fmt': lambda name: f'*api-{name.lower()}*',
- # Per-function helptag.
- 'fn_helptag_fmt': lambda fstem, name, istbl: f'*{name}()*',
- # Module name overrides (for Lua).
- 'module_override': {},
- # Append the docs for these modules, do not start a new section.
- 'append_only': [],
- },
- 'lua': {
- 'mode': 'lua',
- 'filename': 'lua.txt',
- 'section_order': [
- 'highlight.lua',
- 'regex.lua',
- 'diff.lua',
- 'mpack.lua',
- 'json.lua',
- 'base64.lua',
- 'spell.lua',
- 'builtin.lua',
- '_options.lua',
- '_editor.lua',
- '_inspector.lua',
- 'shared.lua',
- 'loader.lua',
- 'uri.lua',
- 'ui.lua',
- 'filetype.lua',
- 'keymap.lua',
- 'fs.lua',
- 'secure.lua',
- 'version.lua',
- 'iter.lua',
- 'snippet.lua',
- 'text.lua',
- ],
- 'files': [
- 'runtime/lua/vim/iter.lua',
- 'runtime/lua/vim/_editor.lua',
- 'runtime/lua/vim/_options.lua',
- 'runtime/lua/vim/shared.lua',
- 'runtime/lua/vim/loader.lua',
- 'runtime/lua/vim/uri.lua',
- 'runtime/lua/vim/ui.lua',
- 'runtime/lua/vim/filetype.lua',
- 'runtime/lua/vim/keymap.lua',
- 'runtime/lua/vim/fs.lua',
- 'runtime/lua/vim/highlight.lua',
- 'runtime/lua/vim/secure.lua',
- 'runtime/lua/vim/version.lua',
- 'runtime/lua/vim/_inspector.lua',
- 'runtime/lua/vim/snippet.lua',
- 'runtime/lua/vim/text.lua',
- 'runtime/lua/vim/_meta/builtin.lua',
- 'runtime/lua/vim/_meta/diff.lua',
- 'runtime/lua/vim/_meta/mpack.lua',
- 'runtime/lua/vim/_meta/json.lua',
- 'runtime/lua/vim/_meta/base64.lua',
- 'runtime/lua/vim/_meta/regex.lua',
- 'runtime/lua/vim/_meta/spell.lua',
- ],
- 'file_patterns': '*.lua',
- 'fn_name_prefix': '',
- 'fn_name_fmt': lambda fstem, name: (
- name if fstem in [ 'vim.iter' ] else
- f'vim.{name}' if fstem in [ '_editor', 'vim.regex'] else
- f'vim.{name}' if fstem == '_options' and not name[0].isupper() else
- f'{fstem}.{name}' if fstem.startswith('vim') else
- name
- ),
- 'section_name': {
- 'lsp.lua': 'core',
- '_inspector.lua': 'inspector',
- },
- 'section_fmt': lambda name: (
- 'Lua module: vim' if name.lower() == '_editor' else
- 'LUA-VIMSCRIPT BRIDGE' if name.lower() == '_options' else
- f'VIM.{name.upper()}' if name.lower() in [ 'highlight', 'mpack', 'json', 'base64', 'diff', 'spell', 'regex' ] else
- 'VIM' if name.lower() == 'builtin' else
- f'Lua module: vim.{name.lower()}'),
- 'helptag_fmt': lambda name: (
- '*lua-vim*' if name.lower() == '_editor' else
- '*lua-vimscript*' if name.lower() == '_options' else
- f'*vim.{name.lower()}*'),
- 'fn_helptag_fmt': lambda fstem, name, istbl: (
- f'*vim.opt:{name.split(":")[-1]}()*' if ':' in name and name.startswith('Option') else
- # Exclude fstem for methods
- f'*{name}()*' if ':' in name else
- f'*vim.{name}()*' if fstem.lower() == '_editor' else
- f'*vim.{name}*' if fstem.lower() == '_options' and istbl else
- # Prevents vim.regex.regex
- f'*{fstem}()*' if fstem.endswith('.' + name) else
- f'*{fstem}.{name}{"" if istbl else "()"}*'
- ),
- 'module_override': {
- # `shared` functions are exposed on the `vim` module.
- 'shared': 'vim',
- '_inspector': 'vim',
- 'uri': 'vim',
- 'ui': 'vim.ui',
- 'loader': 'vim.loader',
- 'filetype': 'vim.filetype',
- 'keymap': 'vim.keymap',
- 'fs': 'vim.fs',
- 'highlight': 'vim.highlight',
- 'secure': 'vim.secure',
- 'version': 'vim.version',
- 'iter': 'vim.iter',
- 'diff': 'vim',
- 'builtin': 'vim',
- 'mpack': 'vim.mpack',
- 'json': 'vim.json',
- 'base64': 'vim.base64',
- 'regex': 'vim.regex',
- 'spell': 'vim.spell',
- 'snippet': 'vim.snippet',
- 'text': 'vim.text',
- },
- 'append_only': [
- 'shared.lua',
- ],
- },
- 'lsp': {
- 'mode': 'lua',
- 'filename': 'lsp.txt',
- 'section_order': [
- 'lsp.lua',
- 'buf.lua',
- 'diagnostic.lua',
- 'codelens.lua',
- 'inlay_hint.lua',
- 'tagfunc.lua',
- 'semantic_tokens.lua',
- 'handlers.lua',
- 'util.lua',
- 'log.lua',
- 'rpc.lua',
- 'protocol.lua',
- ],
- 'files': [
- 'runtime/lua/vim/lsp',
- 'runtime/lua/vim/lsp.lua',
- ],
- 'file_patterns': '*.lua',
- 'fn_name_prefix': '',
- 'section_name': {'lsp.lua': 'lsp'},
- 'section_fmt': lambda name: (
- 'Lua module: vim.lsp'
- if name.lower() == 'lsp'
- else f'Lua module: vim.lsp.{name.lower()}'),
- 'helptag_fmt': lambda name: (
- '*lsp-core*'
- if name.lower() == 'lsp'
- else f'*lsp-{name.lower()}*'),
- 'fn_helptag_fmt': lambda fstem, name, istbl: (
- f'*vim.lsp.{name}{"" if istbl else "()"}*' if fstem == 'lsp' and name != 'client' else
- # HACK. TODO(justinmk): class/structure support in lua2dox
- '*vim.lsp.client*' if 'lsp.client' == f'{fstem}.{name}' else
- f'*vim.lsp.{fstem}.{name}{"" if istbl else "()"}*'),
- 'module_override': {},
- 'append_only': [],
- },
- 'diagnostic': {
- 'mode': 'lua',
- 'filename': 'diagnostic.txt',
- 'section_order': [
- 'diagnostic.lua',
- ],
- 'files': ['runtime/lua/vim/diagnostic.lua'],
- 'file_patterns': '*.lua',
- 'fn_name_prefix': '',
- 'include_tables': False,
- 'section_name': {'diagnostic.lua': 'diagnostic'},
- 'section_fmt': lambda _: 'Lua module: vim.diagnostic',
- 'helptag_fmt': lambda _: '*diagnostic-api*',
- 'fn_helptag_fmt': lambda fstem, name, istbl: f'*vim.{fstem}.{name}{"" if istbl else "()"}*',
- 'module_override': {},
- 'append_only': [],
- },
- 'treesitter': {
- 'mode': 'lua',
- 'filename': 'treesitter.txt',
- 'section_order': [
- 'treesitter.lua',
- 'language.lua',
- 'query.lua',
- 'highlighter.lua',
- 'languagetree.lua',
- 'dev.lua',
- ],
- 'files': [
- 'runtime/lua/vim/treesitter.lua',
- 'runtime/lua/vim/treesitter/',
- ],
- 'file_patterns': '*.lua',
- 'fn_name_prefix': '',
- 'section_name': {},
- 'section_fmt': lambda name: (
- 'Lua module: vim.treesitter'
- if name.lower() == 'treesitter'
- else f'Lua module: vim.treesitter.{name.lower()}'),
- 'helptag_fmt': lambda name: (
- '*lua-treesitter-core*'
- if name.lower() == 'treesitter'
- else f'*lua-treesitter-{name.lower()}*'),
- 'fn_helptag_fmt': lambda fstem, name, istbl: (
- f'*vim.{fstem}.{name}()*'
- if fstem == 'treesitter'
- else f'*{name}()*'
- if name[0].isupper()
- else f'*vim.treesitter.{fstem}.{name}()*'),
- 'module_override': {},
- 'append_only': [],
- }
-}
-
-param_exclude = (
- 'channel_id',
-)
-
-# Annotations are displayed as line items after API function descriptions.
-annotation_map = {
- 'FUNC_API_FAST': '|api-fast|',
- 'FUNC_API_TEXTLOCK': 'not allowed when |textlock| is active or in the |cmdwin|',
- 'FUNC_API_TEXTLOCK_ALLOW_CMDWIN': 'not allowed when |textlock| is active',
- 'FUNC_API_REMOTE_ONLY': '|RPC| only',
- 'FUNC_API_LUA_ONLY': 'Lua |vim.api| only',
-}
-
-
-def nvim_api_info() -> Tuple[int, bool]:
- """Returns NVIM_API_LEVEL, NVIM_API_PRERELEASE from CMakeLists.txt"""
- if not hasattr(nvim_api_info, 'LEVEL'):
- script_dir = os.path.dirname(os.path.abspath(__file__))
- cmake_file_path = os.path.join(script_dir, '..', 'CMakeLists.txt')
- with open(cmake_file_path, 'r') as cmake_file:
- cmake_content = cmake_file.read()
-
- api_level_match = re.search(r'set\(NVIM_API_LEVEL (\d+)\)', cmake_content)
- api_prerelease_match = re.search(
- r'set\(NVIM_API_PRERELEASE (\w+)\)', cmake_content
- )
-
- if not api_level_match or not api_prerelease_match:
- raise RuntimeError(
- 'Could not find NVIM_API_LEVEL or NVIM_API_PRERELEASE in CMakeLists.txt'
- )
-
- nvim_api_info.LEVEL = int(api_level_match.group(1))
- nvim_api_info.PRERELEASE = api_prerelease_match.group(1).lower() == 'true'
-
- return nvim_api_info.LEVEL, nvim_api_info.PRERELEASE
-
-
-# Raises an error with details about `o`, if `cond` is in object `o`,
-# or if `cond()` is callable and returns True.
-def debug_this(o, cond=True):
- name = ''
- if cond is False:
- return
- if not isinstance(o, str):
- try:
- name = o.nodeName
- o = o.toprettyxml(indent=' ', newl='\n')
- except Exception:
- pass
- if (cond is True
- or (callable(cond) and cond())
- or (not callable(cond) and cond in o)):
- raise RuntimeError('xxx: {}\n{}'.format(name, o))
-
-
-# Appends a message to a list which will be printed on exit.
-def msg(s):
- msgs.append(s)
-
-
-# Print all collected messages.
-def msg_report():
- for m in msgs:
- print(f' {m}')
-
-
-# Print collected messages, then throw an exception.
-def fail(s):
- msg_report()
- raise RuntimeError(s)
-
-
-def find_first(parent, name):
- """Finds the first matching node within parent."""
- sub = parent.getElementsByTagName(name)
- if not sub:
- return None
- return sub[0]
-
-
-def iter_children(parent, name):
- """Yields matching child nodes within parent."""
- for child in parent.childNodes:
- if child.nodeType == child.ELEMENT_NODE and child.nodeName == name:
- yield child
-
-
-def get_child(parent, name):
- """Gets the first matching child node."""
- for child in iter_children(parent, name):
- return child
- return None
-
-
-def self_or_child(n):
- """Gets the first child node, or self."""
- if len(n.childNodes) == 0:
- return n
- return n.childNodes[0]
-
-
-def align_tags(line):
- tag_regex = r"\s(\*.+?\*)(?:\s|$)"
- tags = re.findall(tag_regex, line)
-
- if len(tags) > 0:
- line = re.sub(tag_regex, "", line)
- tags = " " + " ".join(tags)
- line = line + (" " * (78 - len(line) - len(tags))) + tags
- return line
-
-
-def clean_lines(text):
- """Removes superfluous lines.
-
- The beginning and end of the string is trimmed. Empty lines are collapsed.
- """
- return re.sub(r'\A\n\s*\n*|\n\s*\n*\Z', '', re.sub(r'(\n\s*\n+)+', '\n\n', text))
-
-
-def is_blank(text):
- return '' == clean_lines(text)
-
-
-def get_text(n):
- """Recursively concatenates all text in a node tree."""
- text = ''
- if n.nodeType == n.TEXT_NODE:
- return n.data
- if n.nodeName == 'computeroutput':
- for node in n.childNodes:
- text += get_text(node)
- return '`{}`'.format(text)
- if n.nodeName == 'sp': # space, used in "programlisting" nodes
- return ' '
- for node in n.childNodes:
- if node.nodeType == node.TEXT_NODE:
- text += node.data
- elif node.nodeType == node.ELEMENT_NODE:
- text += get_text(node)
- return text
-
-
-# Gets the length of the last line in `text`, excluding newline ("\n") char.
-def len_lastline(text):
- lastnl = text.rfind('\n')
- if -1 == lastnl:
- return len(text)
- if '\n' == text[-1]:
- return lastnl - (1 + text.rfind('\n', 0, lastnl))
- return len(text) - (1 + lastnl)
-
-
-def len_lastline_withoutindent(text, indent):
- n = len_lastline(text)
- return (n - len(indent)) if n > len(indent) else 0
-
-
-# Returns True if node `n` contains only inline (not block-level) elements.
-def is_inline(n):
- # if len(n.childNodes) == 0:
- # return n.nodeType == n.TEXT_NODE or n.nodeName == 'computeroutput'
- for c in n.childNodes:
- if c.nodeType != c.TEXT_NODE and c.nodeName != 'computeroutput':
- return False
- if not is_inline(c):
- return False
- return True
-
-
-def doc_wrap(text, prefix='', width=70, func=False, indent=None):
- """Wraps text to `width`.
-
- First line is prefixed with `prefix`, subsequent lines are aligned.
- If `func` is True, only wrap at commas.
- """
- if not width:
- # return prefix + text
- return text
-
- # Whitespace used to indent all lines except the first line.
- indent = ' ' * len(prefix) if indent is None else indent
- indent_only = (prefix == '' and indent is not None)
-
- if func:
- lines = [prefix]
- for part in text.split(', '):
- if part[-1] not in ');':
- part += ', '
- if len(lines[-1]) + len(part) > width:
- lines.append(indent)
- lines[-1] += part
- return '\n'.join(x.rstrip() for x in lines).rstrip()
-
- # XXX: Dummy prefix to force TextWrapper() to wrap the first line.
- if indent_only:
- prefix = indent
-
- tw = textwrap.TextWrapper(break_long_words=False,
- break_on_hyphens=False,
- width=width,
- initial_indent=prefix,
- subsequent_indent=indent)
- result = '\n'.join(tw.wrap(text.strip()))
-
- # XXX: Remove the dummy prefix.
- if indent_only:
- result = result[len(indent):]
-
- return result
-
-
-def max_name(names):
- if len(names) == 0:
- return 0
- return max(len(name) for name in names)
-
-
-def update_params_map(parent, ret_map, width=text_width - indentation):
- """Updates `ret_map` with name:desc key-value pairs extracted
- from Doxygen XML node `parent`.
- """
- params = collections.OrderedDict()
- for node in parent.childNodes:
- if node.nodeType == node.TEXT_NODE:
- continue
- name_node = find_first(node, 'parametername')
- if name_node.getAttribute('direction') == 'out':
- continue
- name = get_text(name_node)
- if name in param_exclude:
- continue
- params[name.strip()] = node
- max_name_len = max_name(params.keys()) + 8
- # `ret_map` is a name:desc map.
- for name, node in params.items():
- desc = ''
- desc_node = get_child(node, 'parameterdescription')
- if desc_node:
- desc = fmt_node_as_vimhelp(
- desc_node, width=width, indent=(' ' * max_name_len))
- ret_map[name] = desc
- return ret_map
-
-
-def render_node(n, text, prefix='', indent='', width=text_width - indentation,
- fmt_vimhelp=False):
- """Renders a node as Vim help text, recursively traversing all descendants."""
-
- def ind(s):
- return s if fmt_vimhelp else ''
-
- text = ''
- # space_preceding = (len(text) > 0 and ' ' == text[-1][-1])
- # text += (int(not space_preceding) * ' ')
-
- if n.nodeName == 'preformatted':
- o = get_text(n)
- ensure_nl = '' if o[-1] == '\n' else '\n'
- if o[0:4] == 'lua\n':
- text += '>lua{}{}\n<'.format(ensure_nl, o[3:-1])
- elif o[0:4] == 'vim\n':
- text += '>vim{}{}\n<'.format(ensure_nl, o[3:-1])
- elif o[0:5] == 'help\n':
- text += o[4:-1]
- else:
- text += '>{}{}\n<'.format(ensure_nl, o)
- elif n.nodeName == 'programlisting': # codeblock (```)
- o = get_text(n)
- text += '>'
- if 'filename' in n.attributes:
- filename = n.attributes['filename'].value
- text += filename.lstrip('.')
-
- text += '\n{}\n<'.format(textwrap.indent(o, ' ' * 4))
- elif is_inline(n):
- text = doc_wrap(get_text(n), prefix=prefix, indent=indent, width=width)
- elif n.nodeName == 'verbatim':
- # TODO: currently we don't use this. The "[verbatim]" hint is there as
- # a reminder that we must decide how to format this if we do use it.
- text += ' [verbatim] {}'.format(get_text(n))
- elif n.nodeName == 'listitem':
- for c in n.childNodes:
- result = render_node(
- c,
- text,
- indent=indent + (' ' * len(prefix)),
- width=width
- )
- if is_blank(result):
- continue
- text += indent + prefix + result
- elif n.nodeName in ('para', 'heading'):
- did_prefix = False
- for c in n.childNodes:
- if (is_inline(c)
- and '' != get_text(c).strip()
- and text
- and ' ' != text[-1]):
- text += ' '
- text += render_node(c, text, prefix=(prefix if not did_prefix else ''), indent=indent, width=width)
- did_prefix = True
- elif n.nodeName == 'itemizedlist':
- for c in n.childNodes:
- text += '{}\n'.format(render_node(c, text, prefix='• ',
- indent=indent, width=width))
- elif n.nodeName == 'orderedlist':
- i = 1
- for c in n.childNodes:
- if is_blank(get_text(c)):
- text += '\n'
- continue
- text += '{}\n'.format(render_node(c, text, prefix='{}. '.format(i),
- indent=indent, width=width))
- i = i + 1
- elif n.nodeName == 'simplesect' and 'note' == n.getAttribute('kind'):
- text += ind(' ')
- for c in n.childNodes:
- if is_blank(render_node(c, text, prefix='• ', indent=' ', width=width)):
- continue
- text += render_node(c, text, prefix='• ', indent=' ', width=width)
- # text += '\n'
- elif n.nodeName == 'simplesect' and 'warning' == n.getAttribute('kind'):
- text += 'Warning:\n '
- for c in n.childNodes:
- text += render_node(c, text, indent=' ', width=width)
- text += '\n'
- elif n.nodeName == 'simplesect' and 'see' == n.getAttribute('kind'):
- text += ind(' ')
- # Example:
- # <simplesect kind="see">
- # <para>|autocommand|</para>
- # </simplesect>
- for c in n.childNodes:
- text += render_node(c, text, prefix='• ', indent=' ', width=width)
- elif n.nodeName == 'simplesect' and 'return' == n.getAttribute('kind'):
- text += ind(' ')
- for c in n.childNodes:
- text += render_node(c, text, indent=' ', width=width)
- elif n.nodeName == 'computeroutput':
- return get_text(n)
- else:
- raise RuntimeError('unhandled node type: {}\n{}'.format(
- n.nodeName, n.toprettyxml(indent=' ', newl='\n')))
-
- return text
-
-
-def para_as_map(parent, indent='', width=text_width - indentation, fmt_vimhelp=False):
- """Extracts a Doxygen XML <para> node to a map.
-
- Keys:
- 'text': Text from this <para> element
- 'note': List of @note strings
- 'params': <parameterlist> map
- 'return': List of @return strings
- 'seealso': List of @see strings
- 'xrefs': ?
- """
- chunks = {
- 'text': '',
- 'note': [],
- 'params': collections.OrderedDict(),
- 'return': [],
- 'seealso': [],
- 'prerelease': False,
- 'xrefs': []
- }
-
- # Ordered dict of ordered lists.
- groups = collections.OrderedDict([
- ('note', []),
- ('params', []),
- ('return', []),
- ('seealso', []),
- ('xrefs', []),
- ])
-
- # Gather nodes into groups. Mostly this is because we want "parameterlist"
- # nodes to appear together.
- text = ''
- kind = ''
- if is_inline(parent):
- # Flatten inline text from a tree of non-block nodes.
- text = doc_wrap(render_node(parent, "", fmt_vimhelp=fmt_vimhelp),
- indent=indent, width=width)
- else:
- prev = None # Previous node
- for child in parent.childNodes:
- if child.nodeName == 'parameterlist':
- groups['params'].append(child)
- elif child.nodeName == 'xrefsect':
- groups['xrefs'].append(child)
- elif child.nodeName == 'simplesect':
- kind = child.getAttribute('kind')
- if kind == 'note':
- groups['note'].append(child)
- elif kind == 'return':
- groups['return'].append(child)
- elif kind == 'see':
- groups['seealso'].append(child)
- elif kind == 'warning':
- text += render_node(child, text, indent=indent,
- width=width, fmt_vimhelp=fmt_vimhelp)
- elif kind == 'since':
- since_match = re.match(r'^(\d+)', get_text(child))
- since = int(since_match.group(1)) if since_match else 0
- NVIM_API_LEVEL, NVIM_API_PRERELEASE = nvim_api_info()
- if since > NVIM_API_LEVEL or (
- since == NVIM_API_LEVEL and NVIM_API_PRERELEASE
- ):
- chunks['prerelease'] = True
- else:
- raise RuntimeError('unhandled simplesect: {}\n{}'.format(
- child.nodeName, child.toprettyxml(indent=' ', newl='\n')))
- else:
- if (prev is not None
- and is_inline(self_or_child(prev))
- and is_inline(self_or_child(child))
- and '' != get_text(self_or_child(child)).strip()
- and text
- and ' ' != text[-1]):
- text += ' '
-
- text += render_node(child, text, indent=indent, width=width,
- fmt_vimhelp=fmt_vimhelp)
- prev = child
-
- chunks['text'] += text
-
- # Generate map from the gathered items.
- if len(groups['params']) > 0:
- for child in groups['params']:
- update_params_map(child, ret_map=chunks['params'], width=width)
- for child in groups['note']:
- chunks['note'].append(render_node(
- child, '', indent=indent, width=width, fmt_vimhelp=fmt_vimhelp).rstrip())
- for child in groups['return']:
- chunks['return'].append(render_node(
- child, '', indent=indent, width=width, fmt_vimhelp=fmt_vimhelp))
- for child in groups['seealso']:
- # Example:
- # <simplesect kind="see">
- # <para>|autocommand|</para>
- # </simplesect>
- chunks['seealso'].append(render_node(
- child, '', indent=indent, width=width, fmt_vimhelp=fmt_vimhelp))
-
- xrefs = set()
- for child in groups['xrefs']:
- # XXX: Add a space (or any char) to `title` here, otherwise xrefs
- # ("Deprecated" section) acts very weird...
- title = get_text(get_child(child, 'xreftitle')) + ' '
- xrefs.add(title)
- xrefdesc = get_text(get_child(child, 'xrefdescription'))
- chunks['xrefs'].append(doc_wrap(xrefdesc, prefix='{}: '.format(title),
- width=width) + '\n')
-
- return chunks, xrefs
-
-def is_program_listing(para):
- """
- Return True if `para` contains a "programlisting" (i.e. a Markdown code
- block ```).
-
- Sometimes a <para> element will have only a single "programlisting" child
- node, but othertimes it will have extra whitespace around the
- "programlisting" node.
-
- @param para XML <para> node
- @return True if <para> is a programlisting
- """
-
- # Remove any child text nodes that are only whitespace
- children = [
- n for n in para.childNodes
- if n.nodeType != n.TEXT_NODE or n.data.strip() != ''
- ]
-
- return len(children) == 1 and children[0].nodeName == 'programlisting'
-
-def fmt_node_as_vimhelp(parent: Element, width=text_width - indentation, indent='',
- fmt_vimhelp=False):
- """Renders (nested) Doxygen <para> nodes as Vim :help text.
-
- NB: Blank lines in a docstring manifest as <para> tags.
- """
- rendered_blocks = []
-
- def fmt_param_doc(m):
- """Renders a params map as Vim :help text."""
- max_name_len = max_name(m.keys()) + 4
- out = ''
- for name, desc in m.items():
- if name == 'self':
- continue
- name = ' • {}'.format('{{{}}}'.format(name).ljust(max_name_len))
- out += '{}{}\n'.format(name, desc)
- return out.rstrip()
-
- def has_nonexcluded_params(m):
- """Returns true if any of the given params has at least
- one non-excluded item."""
- if fmt_param_doc(m) != '':
- return True
-
- for child in parent.childNodes:
- para, _ = para_as_map(child, indent, width, fmt_vimhelp)
-
- # 'programlisting' blocks are Markdown code blocks. Do not include
- # these as a separate paragraph, but append to the last non-empty line
- # in the text
- if is_program_listing(child):
- while rendered_blocks and rendered_blocks[-1] == '':
- rendered_blocks.pop()
- rendered_blocks[-1] += ' ' + para['text']
- continue
-
- # Generate text from the gathered items.
- chunks = [para['text']]
- notes = [" This API is pre-release (unstable)."] if para['prerelease'] else []
- notes += para['note']
- if len(notes) > 0:
- chunks.append('\nNote: ~')
- for s in notes:
- chunks.append(s)
- if len(para['params']) > 0 and has_nonexcluded_params(para['params']):
- chunks.append('\nParameters: ~')
- chunks.append(fmt_param_doc(para['params']))
- if len(para['return']) > 0:
- chunks.append('\nReturn (multiple): ~' if len(para['return']) > 1 else '\nReturn: ~')
- for s in para['return']:
- chunks.append(s)
- if len(para['seealso']) > 0:
- chunks.append('\nSee also: ~')
- for s in para['seealso']:
- chunks.append(s)
- for s in para['xrefs']:
- chunks.append(s)
-
- rendered_blocks.append(clean_lines('\n'.join(chunks).strip()))
- rendered_blocks.append('')
-
- return clean_lines('\n'.join(rendered_blocks).strip())
-
-
-def extract_from_xml(filename, target, width, fmt_vimhelp):
- """Extracts Doxygen info as maps without formatting the text.
-
- Returns two maps:
- 1. Functions
- 2. Deprecated functions
-
- The `fmt_vimhelp` variable controls some special cases for use by
- fmt_doxygen_xml_as_vimhelp(). (TODO: ugly :)
- """
- fns = {} # Map of func_name:docstring.
- deprecated_fns = {} # Map of func_name:docstring.
-
- dom = minidom.parse(filename)
- compoundname = get_text(dom.getElementsByTagName('compoundname')[0])
- for member in dom.getElementsByTagName('memberdef'):
- if member.getAttribute('static') == 'yes' or \
- member.getAttribute('kind') != 'function' or \
- member.getAttribute('prot') == 'private' or \
- get_text(get_child(member, 'name')).startswith('_'):
- continue
-
- loc = find_first(member, 'location')
- if 'private' in loc.getAttribute('file'):
- continue
-
- return_type = get_text(get_child(member, 'type'))
- if return_type == '':
- continue
-
- if 'local_function' in return_type: # Special from lua2dox.lua.
- continue
-
- istbl = return_type.startswith('table') # Special from lua2dox.lua.
- if istbl and not CONFIG[target].get('include_tables', True):
- continue
-
- if return_type.startswith(('ArrayOf', 'DictionaryOf')):
- parts = return_type.strip('_').split('_')
- return_type = '{}({})'.format(parts[0], ', '.join(parts[1:]))
-
- name = get_text(get_child(member, 'name'))
-
- annotations = get_text(get_child(member, 'argsstring'))
- if annotations and ')' in annotations:
- annotations = annotations.rsplit(')', 1)[-1].strip()
- # XXX: (doxygen 1.8.11) 'argsstring' only includes attributes of
- # non-void functions. Special-case void functions here.
- if name == 'nvim_get_mode' and len(annotations) == 0:
- annotations += 'FUNC_API_FAST'
- annotations = filter(None, map(lambda x: annotation_map.get(x),
- annotations.split()))
-
- params = []
- type_length = 0
-
- for param in iter_children(member, 'param'):
- param_type = get_text(get_child(param, 'type')).strip()
- param_name = ''
- declname = get_child(param, 'declname')
- if declname:
- param_name = get_text(declname).strip()
- elif CONFIG[target]['mode'] == 'lua':
- # XXX: this is what lua2dox gives us...
- param_name = param_type
- param_type = ''
-
- if param_name in param_exclude:
- continue
-
- if fmt_vimhelp and param_type.endswith('*'):
- param_type = param_type.strip('* ')
- param_name = '*' + param_name
-
- type_length = max(type_length, len(param_type))
- params.append((param_type, param_name))
-
- # Handle Object Oriented style functions here.
- # We make sure they have "self" in the parameters,
- # and a parent function
- if return_type.startswith('function') \
- and len(return_type.split(' ')) >= 2 \
- and any(x[1] == 'self' for x in params):
- split_return = return_type.split(' ')
- name = f'{split_return[1]}:{name}'
- params = [x for x in params if x[1] != 'self']
-
- c_args = []
- for param_type, param_name in params:
- c_args.append((' ' if fmt_vimhelp else '') + (
- '%s %s' % (param_type.ljust(type_length), param_name)).strip())
-
- if not fmt_vimhelp:
- pass
- else:
- fstem = '?'
- if '.' in compoundname:
- fstem = compoundname.split('.')[0]
- fstem = CONFIG[target]['module_override'].get(fstem, fstem)
- vimtag = CONFIG[target]['fn_helptag_fmt'](fstem, name, istbl)
-
- if 'fn_name_fmt' in CONFIG[target]:
- name = CONFIG[target]['fn_name_fmt'](fstem, name)
-
- if istbl:
- aopen, aclose = '', ''
- else:
- aopen, aclose = '(', ')'
-
- prefix = name + aopen
- suffix = ', '.join('{%s}' % a[1] for a in params
- if a[0] not in ('void', 'Error', 'Arena',
- 'lua_State')) + aclose
-
- if not fmt_vimhelp:
- c_decl = '%s %s(%s);' % (return_type, name, ', '.join(c_args))
- signature = prefix + suffix
- else:
- c_decl = textwrap.indent('%s %s(\n%s\n);' % (return_type, name,
- ',\n'.join(c_args)),
- ' ')
-
- # Minimum 8 chars between signature and vimtag
- lhs = (width - 8) - len(vimtag)
-
- if len(prefix) + len(suffix) > lhs:
- signature = vimtag.rjust(width) + '\n'
- signature += doc_wrap(suffix, width=width, prefix=prefix,
- func=True)
- else:
- signature = prefix + suffix
- signature += vimtag.rjust(width - len(signature))
-
- # Tracks `xrefsect` titles. As of this writing, used only for separating
- # deprecated functions.
- xrefs_all = set()
- paras = []
- brief_desc = find_first(member, 'briefdescription')
- if brief_desc:
- for child in brief_desc.childNodes:
- para, xrefs = para_as_map(child)
- xrefs_all.update(xrefs)
-
- desc = find_first(member, 'detaileddescription')
- if desc:
- for child in desc.childNodes:
- para, xrefs = para_as_map(child)
- paras.append(para)
- xrefs_all.update(xrefs)
- log.debug(
- textwrap.indent(
- re.sub(r'\n\s*\n+', '\n',
- desc.toprettyxml(indent=' ', newl='\n')),
- ' ' * indentation))
-
- fn = {
- 'annotations': list(annotations),
- 'signature': signature,
- 'parameters': params,
- 'parameters_doc': collections.OrderedDict(),
- 'doc': [],
- 'return': [],
- 'seealso': [],
- }
- if fmt_vimhelp:
- fn['desc_node'] = desc
- fn['brief_desc_node'] = brief_desc
-
- for m in paras:
- if 'text' in m:
- if not m['text'] == '':
- fn['doc'].append(m['text'])
- if 'params' in m:
- # Merge OrderedDicts.
- fn['parameters_doc'].update(m['params'])
- if 'return' in m and len(m['return']) > 0:
- fn['return'] += m['return']
- if 'seealso' in m and len(m['seealso']) > 0:
- fn['seealso'] += m['seealso']
-
- if INCLUDE_C_DECL:
- fn['c_decl'] = c_decl
-
- if 'Deprecated' in str(xrefs_all):
- deprecated_fns[name] = fn
- elif name.startswith(CONFIG[target]['fn_name_prefix']):
- fns[name] = fn
-
- fns = collections.OrderedDict(sorted(
- fns.items(),
- key=lambda key_item_tuple: key_item_tuple[0].lower()))
- deprecated_fns = collections.OrderedDict(sorted(deprecated_fns.items()))
- return fns, deprecated_fns
-
-
-def fmt_doxygen_xml_as_vimhelp(filename, target):
- """Entrypoint for generating Vim :help from from Doxygen XML.
-
- Returns 2 items:
- 1. Vim help text for functions found in `filename`.
- 2. Vim help text for deprecated functions.
- """
- fns_txt = {} # Map of func_name:vim-help-text.
- deprecated_fns_txt = {} # Map of func_name:vim-help-text.
- fns, _ = extract_from_xml(filename, target, text_width, True)
-
- for name, fn in fns.items():
- # Generate Vim :help for parameters.
- if fn['desc_node']:
- doc = fmt_node_as_vimhelp(fn['desc_node'], fmt_vimhelp=True)
- if not doc and fn['brief_desc_node']:
- doc = fmt_node_as_vimhelp(fn['brief_desc_node'])
- if not doc and name.startswith("nvim__"):
- continue
- if not doc:
- doc = 'TODO: Documentation'
-
- annotations = '\n'.join(fn['annotations'])
- if annotations:
- annotations = ('\n\nAttributes: ~\n' +
- textwrap.indent(annotations, ' '))
- i = doc.rfind('Parameters: ~')
- if i == -1:
- doc += annotations
- else:
- doc = doc[:i] + annotations + '\n\n' + doc[i:]
-
- if INCLUDE_C_DECL:
- doc += '\n\nC Declaration: ~\n>\n'
- doc += fn['c_decl']
- doc += '\n<'
-
- func_doc = fn['signature'] + '\n'
- func_doc += textwrap.indent(clean_lines(doc), ' ' * indentation)
-
- # Verbatim handling.
- func_doc = re.sub(r'^\s+([<>])$', r'\1', func_doc, flags=re.M)
-
- split_lines = func_doc.split('\n')
- start = 0
- while True:
- try:
- start = split_lines.index('>', start)
- except ValueError:
- break
-
- try:
- end = split_lines.index('<', start)
- except ValueError:
- break
-
- split_lines[start + 1:end] = [
- (' ' + x).rstrip()
- for x in textwrap.dedent(
- "\n".join(
- split_lines[start+1:end]
- )
- ).split("\n")
- ]
-
- start = end
-
- func_doc = "\n".join(map(align_tags, split_lines))
-
- if (name.startswith(CONFIG[target]['fn_name_prefix'])
- and name != "nvim_error_event"):
- fns_txt[name] = func_doc
-
- return ('\n\n'.join(list(fns_txt.values())),
- '\n\n'.join(list(deprecated_fns_txt.values())))
-
-
-def delete_lines_below(filename, tokenstr):
- """Deletes all lines below the line containing `tokenstr`, the line itself,
- and one line above it.
- """
- lines = open(filename).readlines()
- i = 0
- found = False
- for i, line in enumerate(lines, 1):
- if tokenstr in line:
- found = True
- break
- if not found:
- raise RuntimeError(f'not found: "{tokenstr}"')
- i = max(0, i - 2)
- with open(filename, 'wt') as fp:
- fp.writelines(lines[0:i])
-
-
-def extract_defgroups(base: str, dom: Document):
- '''Generate module-level (section) docs (@defgroup).'''
- section_docs = {}
-
- for compound in dom.getElementsByTagName('compound'):
- if compound.getAttribute('kind') != 'group':
- continue
-
- # Doxygen "@defgroup" directive.
- groupname = get_text(find_first(compound, 'name'))
- groupxml = os.path.join(base, '%s.xml' %
- compound.getAttribute('refid'))
-
- group_parsed = minidom.parse(groupxml)
- doc_list = []
- brief_desc = find_first(group_parsed, 'briefdescription')
- if brief_desc:
- for child in brief_desc.childNodes:
- doc_list.append(fmt_node_as_vimhelp(child))
-
- desc = find_first(group_parsed, 'detaileddescription')
- if desc:
- doc = fmt_node_as_vimhelp(desc)
-
- if doc:
- doc_list.append(doc)
-
- # Can't use '.' in @defgroup, so convert to '--'
- # "vim.json" => "vim-dot-json"
- groupname = groupname.replace('-dot-', '.')
-
- section_docs[groupname] = "\n".join(doc_list)
-
- return section_docs
-
-
-def main(doxygen_config, args):
- """Generates:
-
- 1. Vim :help docs
- 2. *.mpack files for use by API clients
-
- Doxygen is called and configured through stdin.
- """
- for target in CONFIG:
- if args.target is not None and target != args.target:
- continue
- mpack_file = os.path.join(
- base_dir, 'runtime', 'doc',
- CONFIG[target]['filename'].replace('.txt', '.mpack'))
- if os.path.exists(mpack_file):
- os.remove(mpack_file)
-
- output_dir = out_dir.format(target=target)
- log.info("Generating documentation for %s in folder %s",
- target, output_dir)
- debug = args.log_level >= logging.DEBUG
- p = subprocess.Popen(
- ['doxygen', '-'],
- stdin=subprocess.PIPE,
- # silence warnings
- # runtime/lua/vim/lsp.lua:209: warning: argument 'foo' not found
- stderr=(subprocess.STDOUT if debug else subprocess.DEVNULL))
- p.communicate(
- doxygen_config.format(
- input=' '.join(
- [f'"{file}"' for file in CONFIG[target]['files']]),
- output=output_dir,
- filter=filter_cmd,
- file_patterns=CONFIG[target]['file_patterns'])
- .encode('utf8')
- )
- if p.returncode:
- sys.exit(p.returncode)
-
- fn_map_full = {} # Collects all functions as each module is processed.
- sections = {}
- sep = '=' * text_width
-
- base = os.path.join(output_dir, 'xml')
- dom = minidom.parse(os.path.join(base, 'index.xml'))
-
- section_docs = extract_defgroups(base, dom)
-
- # Generate docs for all functions in the current module.
- for compound in dom.getElementsByTagName('compound'):
- if compound.getAttribute('kind') != 'file':
- continue
-
- filename = get_text(find_first(compound, 'name'))
- if filename.endswith('.c') or filename.endswith('.lua'):
- xmlfile = os.path.join(base, '{}.xml'.format(compound.getAttribute('refid')))
- # Extract unformatted (*.mpack).
- fn_map, _ = extract_from_xml(xmlfile, target, 9999, False)
- # Extract formatted (:help).
- functions_text, deprecated_text = fmt_doxygen_xml_as_vimhelp(
- os.path.join(base, '{}.xml'.format(compound.getAttribute('refid'))), target)
-
- if not functions_text and not deprecated_text:
- continue
- else:
- filename = os.path.basename(filename)
- name = os.path.splitext(filename)[0].lower()
- sectname = name.upper() if name == 'ui' else name.title()
- sectname = CONFIG[target]['section_name'].get(filename, sectname)
- title = CONFIG[target]['section_fmt'](sectname)
- section_tag = CONFIG[target]['helptag_fmt'](sectname)
- # Module/Section id matched against @defgroup.
- # "*api-buffer*" => "api-buffer"
- section_id = section_tag.strip('*')
-
- doc = ''
- section_doc = section_docs.get(section_id)
- if section_doc:
- doc += '\n\n' + section_doc
-
- if functions_text:
- doc += '\n\n' + functions_text
-
- if INCLUDE_DEPRECATED and deprecated_text:
- doc += f'\n\n\nDeprecated {sectname} Functions: ~\n\n'
- doc += deprecated_text
-
- if doc:
- sections[filename] = (title, section_tag, doc)
- fn_map_full.update(fn_map)
-
- if len(sections) == 0:
- fail(f'no sections for target: {target} (look for errors near "Preprocessing" log lines above)')
- if len(sections) > len(CONFIG[target]['section_order']):
- raise RuntimeError(
- 'found new modules "{}"; update the "section_order" map'.format(
- set(sections).difference(CONFIG[target]['section_order'])))
- first_section_tag = sections[CONFIG[target]['section_order'][0]][1]
-
- docs = ''
-
- for filename in CONFIG[target]['section_order']:
- try:
- title, section_tag, section_doc = sections.pop(filename)
- except KeyError:
- msg(f'warning: empty docs, skipping (target={target}): {filename}')
- msg(f' existing docs: {sections.keys()}')
- continue
- if filename not in CONFIG[target]['append_only']:
- docs += sep
- docs += '\n{}{}'.format(title, section_tag.rjust(text_width - len(title)))
- docs += section_doc
- docs += '\n\n\n'
-
- docs = docs.rstrip() + '\n\n'
- docs += f' vim:tw=78:ts=8:sw={indentation}:sts={indentation}:et:ft=help:norl:\n'
-
- doc_file = os.path.join(base_dir, 'runtime', 'doc',
- CONFIG[target]['filename'])
-
- if os.path.exists(doc_file):
- delete_lines_below(doc_file, first_section_tag)
- with open(doc_file, 'ab') as fp:
- fp.write(docs.encode('utf8'))
-
- fn_map_full = collections.OrderedDict(sorted(fn_map_full.items()))
- with open(mpack_file, 'wb') as fp:
- fp.write(msgpack.packb(fn_map_full, use_bin_type=True))
-
- if not args.keep_tmpfiles:
- shutil.rmtree(output_dir)
-
- msg_report()
-
-
-def filter_source(filename, keep_tmpfiles):
- output_dir = out_dir.format(target='lua2dox')
- name, extension = os.path.splitext(filename)
- if extension == '.lua':
- args = [str(nvim), '-l', lua2dox, filename] + (['--outdir', output_dir] if keep_tmpfiles else [])
- p = subprocess.run(args, stdout=subprocess.PIPE)
- op = ('?' if 0 != p.returncode else p.stdout.decode('utf-8'))
- print(op)
- else:
- """Filters the source to fix macros that confuse Doxygen."""
- with open(filename, 'rt') as fp:
- print(re.sub(r'^(ArrayOf|DictionaryOf)(\(.*?\))',
- lambda m: m.group(1)+'_'.join(
- re.split(r'[^\w]+', m.group(2))),
- fp.read(), flags=re.M))
-
-
-def parse_args():
- targets = ', '.join(CONFIG.keys())
- ap = argparse.ArgumentParser(
- description="Generate helpdoc from source code")
- ap.add_argument(
- "--log-level", "-l", choices=LOG_LEVELS.keys(),
- default=logging.getLevelName(logging.ERROR), help="Set log verbosity"
- )
- ap.add_argument('source_filter', nargs='*',
- help="Filter source file(s)")
- ap.add_argument('-k', '--keep-tmpfiles', action='store_true',
- help="Keep temporary files (tmp-xx-doc/ directories, including tmp-lua2dox-doc/ for lua2dox.lua quasi-C output)")
- ap.add_argument('-t', '--target',
- help=f'One of ({targets}), defaults to "all"')
- return ap.parse_args()
-
-
-Doxyfile = textwrap.dedent('''
- OUTPUT_DIRECTORY = {output}
- INPUT = {input}
- INPUT_ENCODING = UTF-8
- FILE_PATTERNS = {file_patterns}
- RECURSIVE = YES
- INPUT_FILTER = "{filter}"
- EXCLUDE =
- EXCLUDE_SYMLINKS = NO
- EXCLUDE_PATTERNS = */private/* */health.lua */_*.lua
- EXCLUDE_SYMBOLS =
- EXTENSION_MAPPING = lua=C
- EXTRACT_PRIVATE = NO
-
- GENERATE_HTML = NO
- GENERATE_DOCSET = NO
- GENERATE_HTMLHELP = NO
- GENERATE_QHP = NO
- GENERATE_TREEVIEW = NO
- GENERATE_LATEX = NO
- GENERATE_RTF = NO
- GENERATE_MAN = NO
- GENERATE_DOCBOOK = NO
- GENERATE_AUTOGEN_DEF = NO
-
- GENERATE_XML = YES
- XML_OUTPUT = xml
- XML_PROGRAMLISTING = NO
-
- ENABLE_PREPROCESSING = YES
- MACRO_EXPANSION = YES
- EXPAND_ONLY_PREDEF = NO
- MARKDOWN_SUPPORT = YES
-''')
-
-if __name__ == "__main__":
- args = parse_args()
- print("Setting log level to %s" % args.log_level)
- args.log_level = LOG_LEVELS[args.log_level]
- log.setLevel(args.log_level)
- log.addHandler(logging.StreamHandler())
-
- # When invoked as a filter, args won't be passed, so use an env var.
- if args.keep_tmpfiles:
- os.environ['NVIM_KEEP_TMPFILES'] = '1'
- keep_tmpfiles = ('NVIM_KEEP_TMPFILES' in os.environ)
-
- if len(args.source_filter) > 0:
- filter_source(args.source_filter[0], keep_tmpfiles)
- else:
- main(Doxyfile, args)
-
-# vim: set ft=python ts=4 sw=4 tw=79 et :
diff --git a/scripts/genappimage.sh b/scripts/genappimage.sh
index b0bf186f85..e8aac42a9c 100755
--- a/scripts/genappimage.sh
+++ b/scripts/genappimage.sh
@@ -26,8 +26,8 @@ APP_DIR="$APP.AppDir"
########################################################################
# Build and install nvim into the AppImage
-make CMAKE_BUILD_TYPE="${NVIM_BUILD_TYPE}" CMAKE_EXTRA_FLAGS="-DCMAKE_INSTALL_PREFIX=${APP_DIR}/usr -DCMAKE_INSTALL_MANDIR=man"
-make install
+make CMAKE_BUILD_TYPE="${CMAKE_BUILD_TYPE}"
+cmake --install build --prefix="$APP_BUILD_DIR/${APP_DIR}/usr"
########################################################################
# Get helper functions and move to AppDir
@@ -52,7 +52,7 @@ fi
chmod +x "$APP_BUILD_DIR"/linuxdeploy-x86_64.AppImage
# metainfo is not packaged automatically by linuxdeploy
-mkdir "$APP_DIR/usr/share/metainfo/"
+mkdir -p "$APP_DIR/usr/share/metainfo/"
cp "$ROOT_DIR/runtime/nvim.appdata.xml" "$APP_DIR/usr/share/metainfo/"
cd "$APP_DIR" || exit
diff --git a/scripts/lintcommit.lua b/scripts/lintcommit.lua
index d2c8601c25..96f6304247 100644
--- a/scripts/lintcommit.lua
+++ b/scripts/lintcommit.lua
@@ -16,7 +16,7 @@ local _trace = false
-- Print message
local function p(s)
vim.cmd('set verbose=1')
- vim.api.nvim_echo({{s, ''}}, false, {})
+ vim.api.nvim_echo({ { s, '' } }, false, {})
vim.cmd('set verbose=0')
end
@@ -25,7 +25,7 @@ end
-- Prints `cmd` if `trace` is enabled.
local function run(cmd, or_die)
if _trace then
- p('run: '..vim.inspect(cmd))
+ p('run: ' .. vim.inspect(cmd))
end
local rv = vim.trim(vim.fn.system(cmd)) or ''
if vim.v.shell_error ~= 0 then
@@ -43,14 +43,14 @@ end
local function validate_commit(commit_message)
-- Return nil if the commit message starts with "fixup" as it signifies it's
-- a work in progress and shouldn't be linted yet.
- if vim.startswith(commit_message, "fixup") then
+ if vim.startswith(commit_message, 'fixup') then
return nil
end
- local commit_split = vim.split(commit_message, ":", {plain = true})
+ local commit_split = vim.split(commit_message, ':', { plain = true })
-- Return nil if the type is vim-patch since most of the normal rules don't
-- apply.
- if commit_split[1] == "vim-patch" then
+ if commit_split[1] == 'vim-patch' then
return nil
end
@@ -74,35 +74,41 @@ local function validate_commit(commit_message)
if after_idx > vim.tbl_count(commit_split) then
return [[Commit message does not include colons.]]
end
- local after_colon = commit_split[after_idx]
+ local after_colon = ''
+ while after_idx <= vim.tbl_count(commit_split) do
+ after_colon = after_colon .. commit_split[after_idx]
+ after_idx = after_idx + 1
+ end
-- Check if commit introduces a breaking change.
- if vim.endswith(before_colon, "!") then
+ if vim.endswith(before_colon, '!') then
before_colon = before_colon:sub(1, -2)
end
-- Check if type is correct
- local type = vim.split(before_colon, "(", {plain = true})[1]
- local allowed_types = {'build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'test', 'vim-patch'}
+ local type = vim.split(before_colon, '(', { plain = true })[1]
+ local allowed_types =
+ { 'build', 'ci', 'docs', 'feat', 'fix', 'perf', 'refactor', 'revert', 'test', 'vim-patch' }
if not vim.tbl_contains(allowed_types, type) then
return string.format(
[[Invalid commit type "%s". Allowed types are:
%s.
If none of these seem appropriate then use "fix"]],
type,
- vim.inspect(allowed_types))
+ vim.inspect(allowed_types)
+ )
end
-- Check if scope is appropriate
- if before_colon:match("%(") then
- local scope = vim.trim(commit_message:match("%((.-)%)"))
+ if before_colon:match('%(') then
+ local scope = vim.trim(commit_message:match('%((.-)%)'))
if scope == '' then
return [[Scope can't be empty]]
end
- if vim.startswith(scope, "nvim_") then
- return [[Scope should be "api" instead of "nvim_..."]]
+ if vim.startswith(scope, 'nvim_') then
+ return [[Scope should be "api" instead of "nvim_..."]]
end
local alternative_scope = {
@@ -119,17 +125,17 @@ local function validate_commit(commit_message)
end
-- Check that description doesn't end with a period
- if vim.endswith(after_colon, ".") then
+ if vim.endswith(after_colon, '.') then
return [[Description ends with a period (".").]]
end
-- Check that description starts with a whitespace.
- if after_colon:sub(1,1) ~= " " then
+ if after_colon:sub(1, 1) ~= ' ' then
return [[There should be a whitespace after the colon.]]
end
-- Check that description doesn't start with multiple whitespaces.
- if after_colon:sub(1,2) == " " then
+ if after_colon:sub(1, 2) == ' ' then
return [[There should only be one whitespace after the colon.]]
end
@@ -139,7 +145,7 @@ local function validate_commit(commit_message)
end
-- Check that description isn't just whitespaces
- if vim.trim(after_colon) == "" then
+ if vim.trim(after_colon) == '' then
return [[Description shouldn't be empty.]]
end
@@ -150,25 +156,25 @@ end
function M.main(opt)
_trace = not opt or not not opt.trace
- local branch = run({'git', 'rev-parse', '--abbrev-ref', 'HEAD'}, true)
+ local branch = run({ 'git', 'rev-parse', '--abbrev-ref', 'HEAD' }, true)
-- TODO(justinmk): check $GITHUB_REF
- local ancestor = run({'git', 'merge-base', 'origin/master', branch})
+ local ancestor = run({ 'git', 'merge-base', 'origin/master', branch })
if not ancestor then
- ancestor = run({'git', 'merge-base', 'upstream/master', branch})
+ ancestor = run({ 'git', 'merge-base', 'upstream/master', branch })
end
- local commits_str = run({'git', 'rev-list', ancestor..'..'..branch}, true)
+ local commits_str = run({ 'git', 'rev-list', ancestor .. '..' .. branch }, true)
assert(commits_str)
local commits = {} --- @type string[]
- for substring in commits_str:gmatch("%S+") do
- table.insert(commits, substring)
+ for substring in commits_str:gmatch('%S+') do
+ table.insert(commits, substring)
end
local failed = 0
for _, commit_id in ipairs(commits) do
- local msg = run({'git', 'show', '-s', '--format=%s' , commit_id})
+ local msg = run({ 'git', 'show', '-s', '--format=%s', commit_id })
if vim.v.shell_error ~= 0 then
- p('Invalid commit-id: '..commit_id..'"')
+ p('Invalid commit-id: ' .. commit_id .. '"')
else
local invalid_msg = validate_commit(msg)
if invalid_msg then
@@ -179,20 +185,22 @@ function M.main(opt)
p('\n')
end
- p(string.format([[
+ p(string.format(
+ [[
Invalid commit message: "%s"
Commit: %s
%s
]],
msg,
commit_id,
- invalid_msg))
+ invalid_msg
+ ))
end
end
end
if failed > 0 then
- p([[
+ p([[
See also:
https://github.com/neovim/neovim/blob/master/CONTRIBUTING.md#commit-messages
@@ -239,11 +247,14 @@ function M._test()
['refactor(): empty scope'] = false,
['ci( ): whitespace as scope'] = false,
['ci: period at end of sentence.'] = false,
+ ['ci: period: at end of sentence.'] = false,
['ci: Capitalized first word'] = false,
['ci: UPPER_CASE First Word'] = true,
['unknown: using unknown type'] = false,
['feat: foo:bar'] = true,
+ ['feat: :foo:bar'] = true,
['feat(something): foo:bar'] = true,
+ ['feat(something): :foo:bar'] = true,
['feat(:grep): read from pipe'] = true,
['feat(:grep/:make): read from pipe'] = true,
['feat(:grep): foo:bar'] = true,
@@ -252,7 +263,7 @@ function M._test()
['feat(:grep/:make)'] = false,
['feat(:grep'] = false,
['feat(:grep/:make'] = false,
- ['ci: you\'re saying this commit message just goes on and on and on and on and on and on for way too long?'] = false,
+ ["ci: you're saying this commit message just goes on and on and on and on and on and on for way too long?"] = false,
}
local failed = 0
@@ -260,14 +271,15 @@ function M._test()
local is_valid = (nil == validate_commit(message))
if is_valid ~= expected then
failed = failed + 1
- p(string.format('[ FAIL ]: expected=%s, got=%s\n input: "%s"', expected, is_valid, message))
+ p(
+ string.format('[ FAIL ]: expected=%s, got=%s\n input: "%s"', expected, is_valid, message)
+ )
end
end
if failed > 0 then
os.exit(1)
end
-
end
--- @class LintcommitOptions
diff --git a/scripts/lintdoc.lua b/scripts/lintdoc.lua
new file mode 100755
index 0000000000..5e78b4cdcb
--- /dev/null
+++ b/scripts/lintdoc.lua
@@ -0,0 +1,20 @@
+#!/usr/bin/env -S nvim -l
+
+-- Validate vimdoc files on $VIMRUNTIME/doc, and test generating HTML docs.
+-- Checks for duplicate/missing tags, parse errors, and invalid links/urls/spellings.
+-- See also `make lintdoc`.
+--
+-- Usage:
+-- $ nvim -l scripts/lintdoc.lua
+-- $ make lintdoc
+
+print('Running lintdoc ...')
+
+-- gen_help_html requires :helptags to be generated on $VIMRUNTIME/doc
+-- :helptags checks for duplicate tags.
+vim.cmd [[ helptags ALL ]]
+
+require('scripts.gen_help_html').run_validate()
+require('scripts.gen_help_html').test_gen()
+
+print('lintdoc PASSED.')
diff --git a/scripts/lua2dox.lua b/scripts/lua2dox.lua
deleted file mode 100644
index 1c8bc5a3cb..0000000000
--- a/scripts/lua2dox.lua
+++ /dev/null
@@ -1,475 +0,0 @@
------------------------------------------------------------------------------
--- Copyright (C) 2012 by Simon Dales --
--- simon@purrsoft.co.uk --
--- --
--- This program is free software; you can redistribute it and/or modify --
--- it under the terms of the GNU General Public License as published by --
--- the Free Software Foundation; either version 2 of the License, or --
--- (at your option) any later version. --
--- --
--- This program is distributed in the hope that it will be useful, --
--- but WITHOUT ANY WARRANTY; without even the implied warranty of --
--- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the --
--- GNU General Public License for more details. --
--- --
--- You should have received a copy of the GNU General Public License --
--- along with this program; if not, write to the --
--- Free Software Foundation, Inc., --
--- 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. --
------------------------------------------------------------------------------
-
---[[!
-Lua-to-Doxygen converter
-
-Partially from lua2dox
-http://search.cpan.org/~alec/Doxygen-Lua-0.02/lib/Doxygen/Lua.pm
-
-RUNNING
--------
-
-This script "lua2dox.lua" gets called by "gen_vimdoc.py".
-
-DEBUGGING/DEVELOPING
----------------------
-
-1. To debug, run gen_vimdoc.py with --keep-tmpfiles:
- python3 scripts/gen_vimdoc.py -t treesitter --keep-tmpfiles
-2. The filtered result will be written to ./tmp-lua2dox-doc/….lua.c
-
-Doxygen must be on your system. You can experiment like so:
-
-- Run "doxygen -g" to create a default Doxyfile.
-- Then alter it to let it recognise lua. Add the following line:
- FILE_PATTERNS = *.lua
-- Then run "doxygen".
-
-The core function reads the input file (filename or stdin) and outputs some pseudo C-ish language.
-It only has to be good enough for doxygen to see it as legal.
-
-One limitation is that each line is treated separately (except for long comments).
-The implication is that class and function declarations must be on the same line.
-
-There is hack that will insert the "missing" close paren.
-The effect is that you will get the function documented, but not with the parameter list you might expect.
-]]
-
-local TYPES = { 'integer', 'number', 'string', 'table', 'list', 'boolean', 'function' }
-
-local TAGGED_TYPES = { 'TSNode', 'LanguageTree' }
-
--- Document these as 'table'
-local ALIAS_TYPES = {
- 'Range', 'Range4', 'Range6', 'TSMetadata',
- 'vim.filetype.add.filetypes',
- 'vim.filetype.match.args'
-}
-
-local debug_outfile = nil --- @type string?
-local debug_output = {}
-
---- write to stdout
---- @param str? string
-local function write(str)
- if not str then
- return
- end
-
- io.write(str)
- if debug_outfile then
- table.insert(debug_output, str)
- end
-end
-
---- write to stdout
---- @param str? string
-local function writeln(str)
- write(str)
- write('\n')
-end
-
---- an input file buffer
---- @class StreamRead
---- @field currentLine string?
---- @field contentsLen integer
---- @field currentLineNo integer
---- @field filecontents string[]
-local StreamRead = {}
-
---- @return StreamRead
---- @param filename string
-function StreamRead.new(filename)
- assert(filename, ('invalid file: %s'):format(filename))
- -- get lines from file
- -- syphon lines to our table
- local filecontents = {} --- @type string[]
- for line in io.lines(filename) do
- filecontents[#filecontents+1] = line
- end
-
- return setmetatable({
- filecontents = filecontents,
- contentsLen = #filecontents,
- currentLineNo = 1,
- }, { __index = StreamRead })
-end
-
--- get a line
-function StreamRead:getLine()
- if self.currentLine then
- self.currentLine = nil
- return self.currentLine
- end
-
- -- get line
- if self.currentLineNo <= self.contentsLen then
- local line = self.filecontents[self.currentLineNo]
- self.currentLineNo = self.currentLineNo + 1
- return line
- end
-
- return ''
-end
-
--- save line fragment
---- @param line_fragment string
-function StreamRead:ungetLine(line_fragment)
- self.currentLine = line_fragment
-end
-
--- is it eof?
-function StreamRead:eof()
- return not self.currentLine and self.currentLineNo > self.contentsLen
-end
-
--- input filter
---- @class Lua2DoxFilter
-local Lua2DoxFilter = {}
-setmetatable(Lua2DoxFilter, { __index = Lua2DoxFilter })
-
---- trim comment off end of string
----
---- @param line string
---- @return string, string?
-local function removeCommentFromLine(line)
- local pos_comment = line:find('%-%-')
- if not pos_comment then
- return line
- end
- return line:sub(1, pos_comment - 1), line:sub(pos_comment)
-end
-
---- Processes "@…" directives in a docstring line.
----
---- @param line string
---- @param generics table<string,string>
---- @return string?
-local function process_magic(line, generics)
- line = line:gsub('^%s+@', '@')
- line = line:gsub('@package', '@private')
- line = line:gsub('@nodoc', '@private')
-
- if not vim.startswith(line, '@') then -- it's a magic comment
- return '/// ' .. line
- end
-
- local magic = line:sub(2)
- local magic_split = vim.split(magic, ' ', { plain = true })
- local directive = magic_split[1]
-
- if vim.list_contains({
- 'cast', 'diagnostic', 'overload', 'meta', 'type'
- }, directive) then
- -- Ignore LSP directives
- return '// gg:"' .. line .. '"'
- end
-
- if directive == 'defgroup' or directive == 'addtogroup' then
- -- Can't use '.' in defgroup, so convert to '--'
- return '/// @' .. magic:gsub('%.', '-dot-')
- end
-
- if directive == 'generic' then
- local generic_name, generic_type = line:match('@generic%s*(%w+)%s*:?%s*(.*)')
- if generic_type == '' then
- generic_type = 'any'
- end
- generics[generic_name] = generic_type
- return
- end
-
- local type_index = 2
-
- if directive == 'param' then
- for _, type in ipairs(TYPES) do
- magic = magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. ')%)', 'param %1 %2')
- magic =
- magic:gsub('^param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '|nil)%)', 'param %1 %2')
- end
- magic_split = vim.split(magic, ' ', { plain = true })
- type_index = 3
- elseif directive == 'return' then
- for _, type in ipairs(TYPES) do
- magic = magic:gsub('^return%s+.*%((' .. type .. ')%)', 'return %1')
- magic = magic:gsub('^return%s+.*%((' .. type .. '|nil)%)', 'return %1')
- end
- -- Remove first "#" comment char, if any. https://github.com/LuaLS/lua-language-server/wiki/Annotations#return
- magic = magic:gsub('# ', '', 1)
- -- handle the return of vim.spell.check
- magic = magic:gsub('({.*}%[%])', '`%1`')
- magic_split = vim.split(magic, ' ', { plain = true })
- end
-
- local ty = magic_split[type_index]
-
- if ty then
- -- fix optional parameters
- if magic_split[2]:find('%?$') then
- if not ty:find('nil') then
- ty = ty .. '|nil'
- end
- magic_split[2] = magic_split[2]:sub(1, -2)
- end
-
- -- replace generic types
- for k, v in pairs(generics) do
- ty = ty:gsub(k, v) --- @type string
- end
-
- for _, type in ipairs(TAGGED_TYPES) do
- ty = ty:gsub(type, '|%1|')
- end
-
- for _, type in ipairs(ALIAS_TYPES) do
- ty = ty:gsub('^'..type..'$', 'table') --- @type string
- end
-
- -- surround some types by ()
- for _, type in ipairs(TYPES) do
- ty = ty
- :gsub('^(' .. type .. '|nil):?$', '(%1)')
- :gsub('^(' .. type .. '):?$', '(%1)')
- end
-
- magic_split[type_index] = ty
-
- end
-
- magic = table.concat(magic_split, ' ')
-
- return '/// @' .. magic
-end
-
---- @param line string
---- @param in_stream StreamRead
---- @return string
-local function process_block_comment(line, in_stream)
- local comment_parts = {} --- @type string[]
- local done --- @type boolean?
-
- while not done and not in_stream:eof() do
- local thisComment --- @type string?
- local closeSquare = line:find(']]')
- if not closeSquare then -- need to look on another line
- thisComment = line .. '\n'
- line = in_stream:getLine()
- else
- thisComment = line:sub(1, closeSquare - 1)
- done = true
-
- -- unget the tail of the line
- -- in most cases it's empty. This may make us less efficient but
- -- easier to program
- in_stream:ungetLine(vim.trim(line:sub(closeSquare + 2)))
- end
- comment_parts[#comment_parts+1] = thisComment
- end
-
- local comment = table.concat(comment_parts)
-
- if comment:sub(1, 1) == '@' then -- it's a long magic comment
- return '/*' .. comment .. '*/ '
- end
-
- -- discard
- return '/* zz:' .. comment .. '*/ '
-end
-
---- @param line string
---- @return string
-local function process_function_header(line)
- local pos_fn = assert(line:find('function'))
- -- we've got a function
- local fn = removeCommentFromLine(vim.trim(line:sub(pos_fn + 8)))
-
- if fn:sub(1, 1) == '(' then
- -- it's an anonymous function
- return '// ZZ: '..line
- end
- -- fn has a name, so is interesting
-
- -- want to fix for iffy declarations
- if fn:find('[%({]') then
- -- we might have a missing close paren
- if not fn:find('%)') then
- fn = fn .. ' ___MissingCloseParenHere___)'
- end
- end
-
- -- Big hax
- if fn:find(':') then
- fn = fn:gsub(':', '.', 1)
-
- local paren_start = fn:find('(', 1, true)
- local paren_finish = fn:find(')', 1, true)
-
- -- Nothing in between the parens
- local comma --- @type string
- if paren_finish == paren_start + 1 then
- comma = ''
- else
- comma = ', '
- end
-
- fn = fn:sub(1, paren_start)
- .. 'self'
- .. comma
- .. fn:sub(paren_start + 1)
- end
-
- if line:match('local') then
- -- Special: tell gen_vimdoc.py this is a local function.
- return 'local_function ' .. fn .. '{}'
- end
-
- -- add vanilla function
- return 'function ' .. fn .. '{}'
-end
-
---- @param line string
---- @param in_stream StreamRead
---- @param generics table<string,string>>
---- @return string?
-local function process_line(line, in_stream, generics)
- local line_raw = line
- line = vim.trim(line)
-
- if vim.startswith(line, '---') then
- return process_magic(line:sub(4), generics)
- end
-
- if vim.startswith(line, '--'..'[[') then -- it's a long comment
- return process_block_comment(line:sub(5), in_stream)
- end
-
- -- Hax... I'm sorry
- -- M.fun = vim.memoize(function(...)
- -- ->
- -- function M.fun(...)
- line = line:gsub('^(.+) = .*_memoize%([^,]+, function%((.*)%)$', 'function %1(%2)')
-
- if line:find('^function') or line:find('^local%s+function') then
- return process_function_header(line)
- end
-
- if not line:match('^local') then
- local v = line_raw:match('^([A-Za-z][.a-zA-Z_]*)%s+%=')
- if v and v:match('%.') then
- -- Special: this lets gen_vimdoc.py handle tables.
- return 'table '..v..'() {}'
- end
- end
-
- if #line > 0 then -- we don't know what this line means, so just comment it out
- return '// zz: ' .. line
- end
-
- return ''
-end
-
--- Processes the file and writes filtered output to stdout.
----@param filename string
-function Lua2DoxFilter:filter(filename)
- local in_stream = StreamRead.new(filename)
-
- local generics = {} --- @type table<string,string>
-
- while not in_stream:eof() do
- local line = in_stream:getLine()
-
- local out_line = process_line(line, in_stream, generics)
-
- if not vim.startswith(vim.trim(line), '---') then
- generics = {}
- end
-
- if out_line then
- writeln(out_line)
- end
- end
-end
-
---- @class TApp
---- @field timestamp string|osdate
---- @field name string
---- @field version string
---- @field copyright string
---- this application
-local TApp = {
- timestamp = os.date('%c %Z', os.time()),
- name = 'Lua2DoX',
- version = '0.2 20130128',
- copyright = 'Copyright (c) Simon Dales 2012-13'
-}
-
-setmetatable(TApp, { __index = TApp })
-
-function TApp:getRunStamp()
- return self.name .. ' (' .. self.version .. ') ' .. self.timestamp
-end
-
-function TApp:getVersion()
- return self.name .. ' (' .. self.version .. ') '
-end
-
---main
-
-if arg[1] == '--help' then
- writeln(TApp:getVersion())
- writeln(TApp.copyright)
- writeln([[
- run as:
- nvim -l scripts/lua2dox.lua <param>
- --------------
- Param:
- <filename> : interprets filename
- --version : show version/copyright info
- --help : this help text]])
-elseif arg[1] == '--version' then
- writeln(TApp:getVersion())
- writeln(TApp.copyright)
-else -- It's a filter.
- local filename = arg[1]
-
- if arg[2] == '--outdir' then
- local outdir = arg[3]
- if type(outdir) ~= 'string' or (0 ~= vim.fn.filereadable(outdir) and 0 == vim.fn.isdirectory(outdir)) then
- error(('invalid --outdir: "%s"'):format(tostring(outdir)))
- end
- vim.fn.mkdir(outdir, 'p')
- debug_outfile = string.format('%s/%s.c', outdir, vim.fs.basename(filename))
- end
-
- Lua2DoxFilter:filter(filename)
-
- -- output the tail
- writeln('// #######################')
- writeln('// app run:' .. TApp:getRunStamp())
- writeln('// #######################')
- writeln()
-
- if debug_outfile then
- local f = assert(io.open(debug_outfile, 'w'))
- f:write(table.concat(debug_output))
- f:close()
- end
-end
diff --git a/scripts/luacats_grammar.lua b/scripts/luacats_grammar.lua
new file mode 100644
index 0000000000..ca26c70156
--- /dev/null
+++ b/scripts/luacats_grammar.lua
@@ -0,0 +1,184 @@
+--[[!
+LPEG grammar for LuaCATS
+]]
+
+local lpeg = vim.lpeg
+local P, R, S = lpeg.P, lpeg.R, lpeg.S
+local Ct, Cg = lpeg.Ct, lpeg.Cg
+
+--- @param x vim.lpeg.Pattern
+local function rep(x)
+ return x ^ 0
+end
+
+--- @param x vim.lpeg.Pattern
+local function rep1(x)
+ return x ^ 1
+end
+
+--- @param x vim.lpeg.Pattern
+local function opt(x)
+ return x ^ -1
+end
+
+local ws = rep1(S(' \t'))
+local fill = opt(ws)
+
+local any = P(1) -- (consume one character)
+local letter = R('az', 'AZ') + S('_$')
+local num = R('09')
+local ident = letter * rep(letter + num + S '-.')
+local string_single = P "'" * rep(any - P "'") * P "'"
+local string_double = P('"') * rep(any - P('"')) * P('"')
+
+local literal = (string_single + string_double + (opt(P('-')) * num) + P('false') + P('true'))
+
+local lname = (ident + P('...')) * opt(P('?'))
+
+--- @param x string
+local function Pf(x)
+ return fill * P(x) * fill
+end
+
+--- @param x string
+local function Sf(x)
+ return fill * S(x) * fill
+end
+
+--- @param x vim.lpeg.Pattern
+local function paren(x)
+ return Pf('(') * x * fill * P(')')
+end
+
+--- @param x vim.lpeg.Pattern
+local function parenOpt(x)
+ return paren(x) + x
+end
+
+--- @param x vim.lpeg.Pattern
+local function comma1(x)
+ return parenOpt(x * rep(Pf(',') * x))
+end
+
+--- @param x vim.lpeg.Pattern
+local function comma(x)
+ return opt(comma1(x))
+end
+
+--- @type table<string,vim.lpeg.Pattern>
+local v = setmetatable({}, {
+ __index = function(_, k)
+ return lpeg.V(k)
+ end,
+})
+
+local colon = Pf(':')
+local opt_exact = opt(Cg(Pf('(exact)'), 'access'))
+local access = P('private') + P('protected') + P('package')
+local caccess = Cg(access, 'access')
+local desc_delim = Sf '#:' + ws
+local desc = Cg(rep(any), 'desc')
+local opt_desc = opt(desc_delim * desc)
+local cname = Cg(ident, 'name')
+local opt_parent = opt(colon * Cg(ident, 'parent'))
+
+--- @class nvim.luacats.Param
+--- @field kind 'param'
+--- @field name string
+--- @field type string
+--- @field desc? string
+
+--- @class nvim.luacats.Return
+--- @field kind 'return'
+--- @field [integer] { type: string, name?: string}
+--- @field desc? string
+
+--- @class nvim.luacats.Generic
+--- @field kind 'generic'
+--- @field name string
+--- @field type? string
+
+--- @class nvim.luacats.Class
+--- @field kind 'class'
+--- @field name string
+--- @field parent? string
+--- @field access? 'private'|'protected'|'package'
+
+--- @class nvim.luacats.Field
+--- @field kind 'field'
+--- @field name string
+--- @field type string
+--- @field desc? string
+--- @field access? 'private'|'protected'|'package'
+
+--- @class nvim.luacats.Note
+--- @field desc? string
+
+--- @alias nvim.luacats.grammar.result
+--- | nvim.luacats.Param
+--- | nvim.luacats.Return
+--- | nvim.luacats.Generic
+--- | nvim.luacats.Class
+--- | nvim.luacats.Field
+--- | nvim.luacats.Note
+
+--- @class nvim.luacats.grammar
+--- @field match fun(self, input: string): nvim.luacats.grammar.result?
+
+local function annot(nm, pat)
+ if type(nm) == 'string' then
+ nm = P(nm)
+ end
+ if pat then
+ return Ct(Cg(P(nm), 'kind') * fill * pat)
+ end
+ return Ct(Cg(P(nm), 'kind'))
+end
+
+local grammar = P {
+ rep1(P('@') * (v.ats + v.ext_ats)),
+
+ ats = annot('param', Cg(lname, 'name') * ws * v.ctype * opt_desc)
+ + annot('return', comma1(Ct(v.ctype * opt(ws * cname))) * opt_desc)
+ + annot('type', comma1(Ct(v.ctype)) * opt_desc)
+ + annot('cast', cname * ws * opt(Sf('+-')) * v.ctype)
+ + annot('generic', cname * opt(colon * v.ctype))
+ + annot('class', opt_exact * opt(paren(caccess)) * fill * cname * opt_parent)
+ + annot('field', opt(caccess * ws) * v.field_name * ws * v.ctype * opt_desc)
+ + annot('operator', cname * opt(paren(Cg(v.ltype, 'argtype'))) * colon * v.ctype)
+ + annot(access)
+ + annot('deprecated')
+ + annot('alias', cname * opt(ws * v.ctype))
+ + annot('enum', cname)
+ + annot('overload', v.ctype)
+ + annot('see', opt(desc_delim) * desc)
+ + annot('diagnostic', opt(desc_delim) * desc)
+ + annot('meta'),
+
+ --- Custom extensions
+ ext_ats = (
+ annot('note', desc)
+ + annot('since', desc)
+ + annot('nodoc')
+ + annot('inlinedoc')
+ + annot('brief', desc)
+ ),
+
+ field_name = Cg(lname + (v.ty_index * opt(P('?'))), 'name'),
+
+ ctype = parenOpt(Cg(v.ltype, 'type')),
+ ltype = parenOpt(v.ty_union),
+
+ ty_union = v.ty_opt * rep(Pf('|') * v.ty_opt),
+ ty = v.ty_fun + ident + v.ty_table + literal + paren(v.ty),
+ ty_param = Pf('<') * comma1(v.ltype) * fill * P('>'),
+ ty_opt = v.ty * opt(v.ty_param) * opt(P('[]')) * opt(P('?')),
+ ty_index = (Pf('[') * (v.ltype + ident + rep1(num)) * fill * P(']')),
+ table_key = v.ty_index + lname,
+ table_elem = v.table_key * colon * v.ltype,
+ ty_table = Pf('{') * comma1(v.table_elem) * fill * P('}'),
+ fun_param = lname * opt(colon * v.ltype),
+ ty_fun = Pf('fun') * paren(comma(lname * opt(colon * v.ltype))) * opt(colon * comma1(v.ltype)),
+}
+
+return grammar --[[@as nvim.luacats.grammar]]
diff --git a/scripts/luacats_parser.lua b/scripts/luacats_parser.lua
new file mode 100644
index 0000000000..cd671fb9dc
--- /dev/null
+++ b/scripts/luacats_parser.lua
@@ -0,0 +1,537 @@
+local luacats_grammar = require('scripts.luacats_grammar')
+
+--- @class nvim.luacats.parser.param
+--- @field name string
+--- @field type string
+--- @field desc string
+
+--- @class nvim.luacats.parser.return
+--- @field name string
+--- @field type string
+--- @field desc string
+
+--- @class nvim.luacats.parser.note
+--- @field desc string
+
+--- @class nvim.luacats.parser.brief
+--- @field kind 'brief'
+--- @field desc string
+
+--- @class nvim.luacats.parser.alias
+--- @field kind 'alias'
+--- @field type string[]
+--- @field desc string
+
+--- @class nvim.luacats.parser.fun
+--- @field name string
+--- @field params nvim.luacats.parser.param[]
+--- @field returns nvim.luacats.parser.return[]
+--- @field desc string
+--- @field access? 'private'|'package'|'protected'
+--- @field class? string
+--- @field module? string
+--- @field modvar? string
+--- @field classvar? string
+--- @field deprecated? true
+--- @field since? string
+--- @field attrs? string[]
+--- @field nodoc? true
+--- @field generics? table<string,string>
+--- @field table? true
+--- @field notes? nvim.luacats.parser.note[]
+--- @field see? nvim.luacats.parser.note[]
+
+--- @class nvim.luacats.parser.field
+--- @field name string
+--- @field type string
+--- @field desc string
+--- @field access? 'private'|'package'|'protected'
+
+--- @class nvim.luacats.parser.class
+--- @field kind 'class'
+--- @field parent? string
+--- @field name string
+--- @field desc string
+--- @field nodoc? true
+--- @field inlinedoc? true
+--- @field access? 'private'|'package'|'protected'
+--- @field fields nvim.luacats.parser.field[]
+--- @field notes? string[]
+
+--- @class nvim.luacats.parser.State
+--- @field doc_lines? string[]
+--- @field cur_obj? nvim.luacats.parser.obj
+--- @field last_doc_item? nvim.luacats.parser.param|nvim.luacats.parser.return|nvim.luacats.parser.note
+--- @field last_doc_item_indent? integer
+
+--- @alias nvim.luacats.parser.obj
+--- | nvim.luacats.parser.class
+--- | nvim.luacats.parser.fun
+--- | nvim.luacats.parser.brief
+--- | nvim.luacats.parser.alias
+
+-- Remove this when we document classes properly
+--- Some doc lines have the form:
+--- param name some.complex.type (table) description
+--- if so then transform the line to remove the complex type:
+--- param name (table) description
+--- @param line string
+local function use_type_alt(line)
+ for _, type in ipairs({ 'table', 'function' }) do
+ line = line:gsub('@param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. ')%)', '@param %1 %2')
+ line = line:gsub('@param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '|nil)%)', '@param %1 %2')
+ line = line:gsub('@param%s+([a-zA-Z_?]+)%s+.*%((' .. type .. '%?)%)', '@param %1 %2')
+
+ line = line:gsub('@return%s+.*%((' .. type .. ')%)', '@return %1')
+ line = line:gsub('@return%s+.*%((' .. type .. '|nil)%)', '@return %1')
+ line = line:gsub('@return%s+.*%((' .. type .. '%?)%)', '@return %1')
+ end
+ return line
+end
+
+--- If we collected any `---` lines. Add them to the existing (or new) object
+--- Used for function/class descriptions and multiline param descriptions.
+--- @param state nvim.luacats.parser.State
+local function add_doc_lines_to_obj(state)
+ if state.doc_lines then
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+ local txt = table.concat(state.doc_lines, '\n')
+ if cur_obj.desc then
+ cur_obj.desc = cur_obj.desc .. '\n' .. txt
+ else
+ cur_obj.desc = txt
+ end
+ state.doc_lines = nil
+ end
+end
+
+--- @param line string
+--- @param state nvim.luacats.parser.State
+local function process_doc_line(line, state)
+ line = line:sub(4):gsub('^%s+@', '@')
+ line = use_type_alt(line)
+
+ local parsed = luacats_grammar:match(line)
+
+ if not parsed then
+ if line:match('^ ') then
+ line = line:sub(2)
+ end
+
+ if state.last_doc_item then
+ if not state.last_doc_item_indent then
+ state.last_doc_item_indent = #line:match('^%s*') + 1
+ end
+ state.last_doc_item.desc = (state.last_doc_item.desc or '')
+ .. '\n'
+ .. line:sub(state.last_doc_item_indent or 1)
+ else
+ state.doc_lines = state.doc_lines or {}
+ table.insert(state.doc_lines, line)
+ end
+ return
+ end
+
+ state.last_doc_item_indent = nil
+ state.last_doc_item = nil
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+
+ local kind = parsed.kind
+
+ if kind == 'brief' then
+ state.cur_obj = {
+ kind = 'brief',
+ desc = parsed.desc,
+ }
+ elseif kind == 'class' then
+ --- @cast parsed nvim.luacats.Class
+ cur_obj.kind = 'class'
+ cur_obj.name = parsed.name
+ cur_obj.parent = parsed.parent
+ cur_obj.access = parsed.access
+ cur_obj.desc = state.doc_lines and table.concat(state.doc_lines, '\n') or nil
+ state.doc_lines = nil
+ cur_obj.fields = {}
+ elseif kind == 'field' then
+ --- @cast parsed nvim.luacats.Field
+ parsed.desc = parsed.desc or state.doc_lines and table.concat(state.doc_lines, '\n') or nil
+ if parsed.desc then
+ parsed.desc = vim.trim(parsed.desc)
+ end
+ table.insert(cur_obj.fields, parsed)
+ state.doc_lines = nil
+ elseif kind == 'operator' then
+ parsed.desc = parsed.desc or state.doc_lines and table.concat(state.doc_lines, '\n') or nil
+ if parsed.desc then
+ parsed.desc = vim.trim(parsed.desc)
+ end
+ table.insert(cur_obj.fields, parsed)
+ state.doc_lines = nil
+ elseif kind == 'param' then
+ state.last_doc_item_indent = nil
+ cur_obj.params = cur_obj.params or {}
+ if vim.endswith(parsed.name, '?') then
+ parsed.name = parsed.name:sub(1, -2)
+ parsed.type = parsed.type .. '?'
+ end
+ state.last_doc_item = {
+ name = parsed.name,
+ type = parsed.type,
+ desc = parsed.desc,
+ }
+ table.insert(cur_obj.params, state.last_doc_item)
+ elseif kind == 'return' then
+ cur_obj.returns = cur_obj.returns or {}
+ for _, t in ipairs(parsed) do
+ table.insert(cur_obj.returns, {
+ name = t.name,
+ type = t.type,
+ desc = parsed.desc,
+ })
+ end
+ state.last_doc_item_indent = nil
+ state.last_doc_item = cur_obj.returns[#cur_obj.returns]
+ elseif kind == 'private' then
+ cur_obj.access = 'private'
+ elseif kind == 'package' then
+ cur_obj.access = 'package'
+ elseif kind == 'protected' then
+ cur_obj.access = 'protected'
+ elseif kind == 'deprecated' then
+ cur_obj.deprecated = true
+ elseif kind == 'inlinedoc' then
+ cur_obj.inlinedoc = true
+ elseif kind == 'nodoc' then
+ cur_obj.nodoc = true
+ elseif kind == 'since' then
+ cur_obj.since = parsed.desc
+ elseif kind == 'see' then
+ cur_obj.see = cur_obj.see or {}
+ table.insert(cur_obj.see, { desc = parsed.desc })
+ elseif kind == 'note' then
+ state.last_doc_item_indent = nil
+ state.last_doc_item = {
+ desc = parsed.desc,
+ }
+ cur_obj.notes = cur_obj.notes or {}
+ table.insert(cur_obj.notes, state.last_doc_item)
+ elseif kind == 'type' then
+ cur_obj.desc = parsed.desc
+ parsed.desc = nil
+ parsed.kind = nil
+ cur_obj.type = parsed
+ elseif kind == 'alias' then
+ state.cur_obj = {
+ kind = 'alias',
+ desc = parsed.desc,
+ }
+ elseif kind == 'enum' then
+ -- TODO
+ state.doc_lines = nil
+ elseif
+ vim.tbl_contains({
+ 'diagnostic',
+ 'cast',
+ 'overload',
+ 'meta',
+ }, kind)
+ then
+ -- Ignore
+ return
+ elseif kind == 'generic' then
+ cur_obj.generics = cur_obj.generics or {}
+ cur_obj.generics[parsed.name] = parsed.type or 'any'
+ else
+ error('Unhandled' .. vim.inspect(parsed))
+ end
+end
+
+--- @param fun nvim.luacats.parser.fun
+--- @return nvim.luacats.parser.field
+local function fun2field(fun)
+ local parts = { 'fun(' }
+ for _, p in ipairs(fun.params or {}) do
+ parts[#parts + 1] = string.format('%s: %s', p.name, p.type)
+ end
+ parts[#parts + 1] = ')'
+ if fun.returns then
+ parts[#parts + 1] = ': '
+ local tys = {} --- @type string[]
+ for _, p in ipairs(fun.returns) do
+ tys[#tys + 1] = p.type
+ end
+ parts[#parts + 1] = table.concat(tys, ', ')
+ end
+
+ return {
+ name = fun.name,
+ type = table.concat(parts, ''),
+ access = fun.access,
+ desc = fun.desc,
+ }
+end
+
+--- Function to normalize known form for declaring functions and normalize into a more standard
+--- form.
+--- @param line string
+--- @return string
+local function filter_decl(line)
+ -- M.fun = vim._memoize(function(...)
+ -- ->
+ -- function M.fun(...)
+ line = line:gsub('^local (.+) = .*_memoize%([^,]+, function%((.*)%)$', 'local function %1(%2)')
+ line = line:gsub('^(.+) = .*_memoize%([^,]+, function%((.*)%)$', 'function %1(%2)')
+ return line
+end
+
+--- @param line string
+--- @param state nvim.luacats.parser.State
+--- @param classes table<string,nvim.luacats.parser.class>
+--- @param classvars table<string,string>
+--- @param has_indent boolean
+local function process_lua_line(line, state, classes, classvars, has_indent)
+ line = filter_decl(line)
+
+ if state.cur_obj and state.cur_obj.kind == 'class' then
+ local nm = line:match('^local%s+([a-zA-Z0-9_]+)%s*=')
+ if nm then
+ classvars[nm] = state.cur_obj.name
+ end
+ return
+ end
+
+ do
+ local parent_tbl, sep, fun_or_meth_nm =
+ line:match('^function%s+([a-zA-Z0-9_]+)([.:])([a-zA-Z0-9_]+)%s*%(')
+ if parent_tbl then
+ -- Have a decl. Ensure cur_obj
+ state.cur_obj = state.cur_obj or {}
+ local cur_obj = assert(state.cur_obj)
+
+ -- Match `Class:foo` methods for defined classes
+ local class = classvars[parent_tbl]
+ if class then
+ --- @cast cur_obj nvim.luacats.parser.fun
+ cur_obj.name = fun_or_meth_nm
+ cur_obj.class = class
+ cur_obj.classvar = parent_tbl
+ -- Add self param to methods
+ if sep == ':' then
+ cur_obj.params = cur_obj.params or {}
+ table.insert(cur_obj.params, 1, {
+ name = 'self',
+ type = class,
+ })
+ end
+
+ -- Add method as the field to the class
+ table.insert(classes[class].fields, fun2field(cur_obj))
+ return
+ end
+
+ -- Match `M.foo`
+ if cur_obj and parent_tbl == cur_obj.modvar then
+ cur_obj.name = fun_or_meth_nm
+ return
+ end
+ end
+ end
+
+ do
+ -- Handle: `function A.B.C.foo(...)`
+ local fn_nm = line:match('^function%s+([.a-zA-Z0-9_]+)%s*%(')
+ if fn_nm then
+ state.cur_obj = state.cur_obj or {}
+ state.cur_obj.name = fn_nm
+ return
+ end
+ end
+
+ do
+ -- Handle: `M.foo = {...}` where `M` is the modvar
+ local parent_tbl, tbl_nm = line:match('([a-zA-Z_]+)%.([a-zA-Z0-9_]+)%s*=')
+ if state.cur_obj and parent_tbl and parent_tbl == state.cur_obj.modvar then
+ state.cur_obj.name = tbl_nm
+ state.cur_obj.table = true
+ return
+ end
+ end
+
+ do
+ -- Handle: `foo = {...}`
+ local tbl_nm = line:match('^([a-zA-Z0-9_]+)%s*=')
+ if tbl_nm and not has_indent then
+ state.cur_obj = state.cur_obj or {}
+ state.cur_obj.name = tbl_nm
+ state.cur_obj.table = true
+ return
+ end
+ end
+
+ do
+ -- Handle: `vim.foo = {...}`
+ local tbl_nm = line:match('^(vim%.[a-zA-Z0-9_]+)%s*=')
+ if state.cur_obj and tbl_nm and not has_indent then
+ state.cur_obj.name = tbl_nm
+ state.cur_obj.table = true
+ return
+ end
+ end
+
+ if state.cur_obj then
+ if line:find('^%s*%-%- luacheck:') then
+ state.cur_obj = nil
+ elseif line:find('^%s*local%s+') then
+ state.cur_obj = nil
+ elseif line:find('^%s*return%s+') then
+ state.cur_obj = nil
+ elseif line:find('^%s*[a-zA-Z_.]+%(%s+') then
+ state.cur_obj = nil
+ end
+ end
+end
+
+--- Determine the table name used to export functions of a module
+--- Usually this is `M`.
+--- @param str string
+--- @return string?
+local function determine_modvar(str)
+ local modvar --- @type string?
+ for line in vim.gsplit(str, '\n') do
+ do
+ --- @type string?
+ local m = line:match('^return%s+([a-zA-Z_]+)')
+ if m then
+ modvar = m
+ end
+ end
+ do
+ --- @type string?
+ local m = line:match('^return%s+setmetatable%(([a-zA-Z_]+),')
+ if m then
+ modvar = m
+ end
+ end
+ end
+ return modvar
+end
+
+--- @param obj nvim.luacats.parser.obj
+--- @param funs nvim.luacats.parser.fun[]
+--- @param classes table<string,nvim.luacats.parser.class>
+--- @param briefs string[]
+--- @param uncommitted nvim.luacats.parser.obj[]
+local function commit_obj(obj, classes, funs, briefs, uncommitted)
+ local commit = false
+ if obj.kind == 'class' then
+ --- @cast obj nvim.luacats.parser.class
+ if not classes[obj.name] then
+ classes[obj.name] = obj
+ commit = true
+ end
+ elseif obj.kind == 'alias' then
+ -- Just pretend
+ commit = true
+ elseif obj.kind == 'brief' then
+ --- @cast obj nvim.luacats.parser.brief`
+ briefs[#briefs + 1] = obj.desc
+ commit = true
+ else
+ --- @cast obj nvim.luacats.parser.fun`
+ if obj.name then
+ funs[#funs + 1] = obj
+ commit = true
+ end
+ end
+ if not commit then
+ table.insert(uncommitted, obj)
+ end
+ return commit
+end
+
+--- @param filename string
+--- @param uncommitted nvim.luacats.parser.obj[]
+-- luacheck: no unused
+local function dump_uncommitted(filename, uncommitted)
+ local out_path = 'luacats-uncommited/' .. filename:gsub('/', '%%') .. '.txt'
+ if #uncommitted > 0 then
+ print(string.format('Could not commit %d objects in %s', #uncommitted, filename))
+ vim.fn.mkdir(assert(vim.fs.dirname(out_path)), 'p')
+ local f = assert(io.open(out_path, 'w'))
+ for i, x in ipairs(uncommitted) do
+ f:write(i)
+ f:write(': ')
+ f:write(vim.inspect(x))
+ f:write('\n')
+ end
+ f:close()
+ else
+ vim.fn.delete(out_path)
+ end
+end
+
+local M = {}
+
+function M.parse_str(str, filename)
+ local funs = {} --- @type nvim.luacats.parser.fun[]
+ local classes = {} --- @type table<string,nvim.luacats.parser.class>
+ local briefs = {} --- @type string[]
+
+ local mod_return = determine_modvar(str)
+
+ --- @type string
+ local module = filename:match('.*/lua/([a-z_][a-z0-9_/]+)%.lua') or filename
+ module = module:gsub('/', '.')
+
+ local classvars = {} --- @type table<string,string>
+
+ local state = {} --- @type nvim.luacats.parser.State
+
+ -- Keep track of any partial objects we don't commit
+ local uncommitted = {} --- @type nvim.luacats.parser.obj[]
+
+ for line in vim.gsplit(str, '\n') do
+ local has_indent = line:match('^%s+') ~= nil
+ line = vim.trim(line)
+ if vim.startswith(line, '---') then
+ process_doc_line(line, state)
+ else
+ add_doc_lines_to_obj(state)
+
+ if state.cur_obj then
+ state.cur_obj.modvar = mod_return
+ state.cur_obj.module = module
+ end
+
+ process_lua_line(line, state, classes, classvars, has_indent)
+
+ -- Commit the object
+ local cur_obj = state.cur_obj
+ if cur_obj then
+ if not commit_obj(cur_obj, classes, funs, briefs, uncommitted) then
+ --- @diagnostic disable-next-line:inject-field
+ cur_obj.line = line
+ end
+ end
+
+ state = {}
+ end
+ end
+
+ -- dump_uncommitted(filename, uncommitted)
+
+ return classes, funs, briefs, uncommitted
+end
+
+--- @param filename string
+function M.parse(filename)
+ local f = assert(io.open(filename, 'r'))
+ local txt = f:read('*all')
+ f:close()
+
+ return M.parse_str(txt, filename)
+end
+
+return M
diff --git a/scripts/text_utils.lua b/scripts/text_utils.lua
new file mode 100644
index 0000000000..937408c546
--- /dev/null
+++ b/scripts/text_utils.lua
@@ -0,0 +1,361 @@
+local fmt = string.format
+
+--- @class nvim.text_utils.MDNode
+--- @field [integer] nvim.text_utils.MDNode
+--- @field type string
+--- @field text? string
+
+local INDENTATION = 4
+
+local NBSP = string.char(160)
+
+local M = {}
+
+local function contains(t, xs)
+ return vim.tbl_contains(xs, t)
+end
+
+--- @param txt string
+--- @param srow integer
+--- @param scol integer
+--- @param erow? integer
+--- @param ecol? integer
+--- @return string
+local function slice_text(txt, srow, scol, erow, ecol)
+ local lines = vim.split(txt, '\n')
+
+ if srow == erow then
+ return lines[srow + 1]:sub(scol + 1, ecol)
+ end
+
+ if erow then
+ -- Trim the end
+ for _ = erow + 2, #lines do
+ table.remove(lines, #lines)
+ end
+ end
+
+ -- Trim the start
+ for _ = 1, srow do
+ table.remove(lines, 1)
+ end
+
+ lines[1] = lines[1]:sub(scol + 1)
+ lines[#lines] = lines[#lines]:sub(1, ecol)
+
+ return table.concat(lines, '\n')
+end
+
+--- @param text string
+--- @return nvim.text_utils.MDNode
+local function parse_md_inline(text)
+ local parser = vim.treesitter.languagetree.new(text, 'markdown_inline')
+ local root = parser:parse(true)[1]:root()
+
+ --- @param node TSNode
+ --- @return nvim.text_utils.MDNode?
+ local function extract(node)
+ local ntype = node:type()
+
+ if ntype:match('^%p$') then
+ return
+ end
+
+ --- @type table<any,any>
+ local ret = { type = ntype }
+ ret.text = vim.treesitter.get_node_text(node, text)
+
+ local row, col = 0, 0
+
+ for child, child_field in node:iter_children() do
+ local e = extract(child)
+ if e and ntype == 'inline' then
+ local srow, scol = child:start()
+ if (srow == row and scol > col) or srow > row then
+ local t = slice_text(ret.text, row, col, srow, scol)
+ if t and t ~= '' then
+ table.insert(ret, { type = 'text', j = true, text = t })
+ end
+ end
+ row, col = child:end_()
+ end
+
+ if child_field then
+ ret[child_field] = e
+ else
+ table.insert(ret, e)
+ end
+ end
+
+ if ntype == 'inline' and (row > 0 or col > 0) then
+ local t = slice_text(ret.text, row, col)
+ if t and t ~= '' then
+ table.insert(ret, { type = 'text', text = t })
+ end
+ end
+
+ return ret
+ end
+
+ return extract(root) or {}
+end
+
+--- @param text string
+--- @return nvim.text_utils.MDNode
+local function parse_md(text)
+ local parser = vim.treesitter.languagetree.new(text, 'markdown', {
+ injections = { markdown = '' },
+ })
+
+ local root = parser:parse(true)[1]:root()
+
+ local EXCLUDE_TEXT_TYPE = {
+ list = true,
+ list_item = true,
+ section = true,
+ document = true,
+ fenced_code_block = true,
+ fenced_code_block_delimiter = true,
+ }
+
+ --- @param node TSNode
+ --- @return nvim.text_utils.MDNode?
+ local function extract(node)
+ local ntype = node:type()
+
+ if ntype:match('^%p$') or contains(ntype, { 'block_continuation' }) then
+ return
+ end
+
+ --- @type table<any,any>
+ local ret = { type = ntype }
+
+ if not EXCLUDE_TEXT_TYPE[ntype] then
+ ret.text = vim.treesitter.get_node_text(node, text)
+ end
+
+ if ntype == 'inline' then
+ ret = parse_md_inline(ret.text)
+ end
+
+ for child, child_field in node:iter_children() do
+ local e = extract(child)
+ if child_field then
+ ret[child_field] = e
+ else
+ table.insert(ret, e)
+ end
+ end
+
+ return ret
+ end
+
+ return extract(root) or {}
+end
+
+--- @param x string
+--- @param start_indent integer
+--- @param indent integer
+--- @param text_width integer
+--- @return string
+function M.wrap(x, start_indent, indent, text_width)
+ local words = vim.split(vim.trim(x), '%s+')
+ local parts = { string.rep(' ', start_indent) } --- @type string[]
+ local count = indent
+
+ for i, w in ipairs(words) do
+ if count > indent and count + #w > text_width - 1 then
+ parts[#parts + 1] = '\n'
+ parts[#parts + 1] = string.rep(' ', indent)
+ count = indent
+ elseif i ~= 1 then
+ parts[#parts + 1] = ' '
+ count = count + 1
+ end
+ count = count + #w
+ parts[#parts + 1] = w
+ end
+
+ return (table.concat(parts):gsub('%s+\n', '\n'):gsub('\n+$', ''))
+end
+
+--- @param node nvim.text_utils.MDNode
+--- @param start_indent integer
+--- @param indent integer
+--- @param text_width integer
+--- @param level integer
+--- @return string[]
+local function render_md(node, start_indent, indent, text_width, level, is_list)
+ local parts = {} --- @type string[]
+
+ -- For debugging
+ local add_tag = false
+ -- local add_tag = true
+
+ local ntype = node.type
+
+ if add_tag then
+ parts[#parts + 1] = '<' .. ntype .. '>'
+ end
+
+ if ntype == 'text' then
+ parts[#parts + 1] = node.text
+ elseif ntype == 'html_tag' then
+ error('html_tag: ' .. node.text)
+ elseif ntype == 'inline_link' then
+ vim.list_extend(parts, { '*', node[1].text, '*' })
+ elseif ntype == 'shortcut_link' then
+ if node[1].text:find('^<.*>$') then
+ parts[#parts + 1] = node[1].text
+ else
+ vim.list_extend(parts, { '|', node[1].text, '|' })
+ end
+ elseif ntype == 'backslash_escape' then
+ parts[#parts + 1] = node.text
+ elseif ntype == 'emphasis' then
+ parts[#parts + 1] = node.text:sub(2, -2)
+ elseif ntype == 'code_span' then
+ vim.list_extend(parts, { '`', node.text:sub(2, -2):gsub(' ', NBSP), '`' })
+ elseif ntype == 'inline' then
+ if #node == 0 then
+ local text = assert(node.text)
+ parts[#parts + 1] = M.wrap(text, start_indent, indent, text_width)
+ else
+ for _, child in ipairs(node) do
+ vim.list_extend(parts, render_md(child, start_indent, indent, text_width, level + 1))
+ end
+ end
+ elseif ntype == 'paragraph' then
+ local pparts = {}
+ for _, child in ipairs(node) do
+ vim.list_extend(pparts, render_md(child, start_indent, indent, text_width, level + 1))
+ end
+ parts[#parts + 1] = M.wrap(table.concat(pparts), start_indent, indent, text_width)
+ parts[#parts + 1] = '\n'
+ elseif ntype == 'code_fence_content' then
+ local lines = vim.split(node.text:gsub('\n%s*$', ''), '\n')
+
+ local cindent = indent + INDENTATION
+ if level > 3 then
+ -- The tree-sitter markdown parser doesn't parse the code blocks indents
+ -- correctly in lists. Fudge it!
+ lines[1] = ' ' .. lines[1] -- ¯\_(ツ)_/¯
+ cindent = indent - level
+ local _, initial_indent = lines[1]:find('^%s*')
+ initial_indent = initial_indent + cindent
+ if initial_indent < indent then
+ cindent = indent - INDENTATION
+ end
+ end
+
+ for _, l in ipairs(lines) do
+ if #l > 0 then
+ parts[#parts + 1] = string.rep(' ', cindent)
+ parts[#parts + 1] = l
+ end
+ parts[#parts + 1] = '\n'
+ end
+ elseif ntype == 'fenced_code_block' then
+ parts[#parts + 1] = '>'
+ for _, child in ipairs(node) do
+ if child.type == 'info_string' then
+ parts[#parts + 1] = child.text
+ break
+ end
+ end
+ parts[#parts + 1] = '\n'
+ for _, child in ipairs(node) do
+ if child.type ~= 'info_string' then
+ vim.list_extend(parts, render_md(child, start_indent, indent, text_width, level + 1))
+ end
+ end
+ parts[#parts + 1] = '<\n'
+ elseif ntype == 'html_block' then
+ local text = node.text:gsub('^<pre>help', '')
+ text = text:gsub('</pre>%s*$', '')
+ parts[#parts + 1] = text
+ elseif ntype == 'list_marker_dot' then
+ parts[#parts + 1] = node.text
+ elseif contains(ntype, { 'list_marker_minus', 'list_marker_star' }) then
+ parts[#parts + 1] = '• '
+ elseif ntype == 'list_item' then
+ parts[#parts + 1] = string.rep(' ', indent)
+ local offset = node[1].type == 'list_marker_dot' and 3 or 2
+ for i, child in ipairs(node) do
+ local sindent = i <= 2 and 0 or (indent + offset)
+ vim.list_extend(
+ parts,
+ render_md(child, sindent, indent + offset, text_width, level + 1, true)
+ )
+ end
+ else
+ if node.text then
+ error(fmt('cannot render:\n%s', vim.inspect(node)))
+ end
+ for i, child in ipairs(node) do
+ local start_indent0 = i == 1 and start_indent or indent
+ vim.list_extend(
+ parts,
+ render_md(child, start_indent0, indent, text_width, level + 1, is_list)
+ )
+ if ntype ~= 'list' and i ~= #node then
+ if (node[i + 1] or {}).type ~= 'list' then
+ parts[#parts + 1] = '\n'
+ end
+ end
+ end
+ end
+
+ if add_tag then
+ parts[#parts + 1] = '</' .. ntype .. '>'
+ end
+
+ return parts
+end
+
+--- @param text_width integer
+local function align_tags(text_width)
+ --- @param line string
+ --- @return string
+ return function(line)
+ local tag_pat = '%s+(%*[^ ]+%*)%s*$'
+ local tags = {}
+ for m in line:gmatch(tag_pat) do
+ table.insert(tags, m)
+ end
+
+ if #tags > 0 then
+ line = line:gsub(tag_pat, '')
+ local tags_str = ' ' .. table.concat(tags, ' ')
+ local pad = string.rep(' ', text_width - #line - #tags_str)
+ return line .. pad .. tags_str
+ end
+
+ return line
+ end
+end
+
+--- @param text string
+--- @param start_indent integer
+--- @param indent integer
+--- @param is_list? boolean
+--- @return string
+function M.md_to_vimdoc(text, start_indent, indent, text_width, is_list)
+ -- Add an extra newline so the parser can properly capture ending ```
+ local parsed = parse_md(text .. '\n')
+ local ret = render_md(parsed, start_indent, indent, text_width, 0, is_list)
+
+ local lines = vim.split(table.concat(ret):gsub(NBSP, ' '), '\n')
+
+ lines = vim.tbl_map(align_tags(text_width), lines)
+
+ local s = table.concat(lines, '\n')
+
+ -- Reduce whitespace in code-blocks
+ s = s:gsub('\n+%s*>([a-z]+)\n?\n', ' >%1\n')
+ s = s:gsub('\n+%s*>\n?\n', ' >\n')
+
+ return s
+end
+
+return M
diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh
index 47c6d293bc..45dd7f5fee 100755
--- a/scripts/vim-patch.sh
+++ b/scripts/vim-patch.sh
@@ -24,7 +24,7 @@ CREATED_FILES=()
usage() {
echo "Port Vim patches to Neovim"
- echo "https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim"
+ echo "https://neovim.io/doc/user/dev_vimpatch.html"
echo
echo "Usage: ${BASENAME} [-h | -l | -p vim-revision | -r pr-number]"
echo
@@ -174,7 +174,7 @@ assign_commit_details() {
vim_commit_url="https://github.com/vim/vim/commit/${vim_commit}"
vim_message="$(git -C "${VIM_SOURCE_DIR}" log -1 --pretty='format:%B' "${vim_commit}" \
- | sed -Ee 's/(#[0-9]{1,})/vim\/vim\1/g')"
+ | sed -Ee 's/([^A-Za-z0-9])(#[0-9]{1,})/\1vim\/vim\2/g')"
local vim_coauthor0
vim_coauthor0="$(git -C "${VIM_SOURCE_DIR}" log -1 --pretty='format:Co-authored-by: %an <%ae>' "${vim_commit}")"
# Extract co-authors from the commit message.
@@ -427,7 +427,7 @@ stage_patch() {
or "%s -s --draft" to create a draft pull request.
See the wiki for more information:
- * https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim
+ * https://neovim.io/doc/user/dev_vimpatch.html
' "${vim_version}" "${BASENAME}" "${BASENAME}" "${BASENAME}"
return $ret
}
diff --git a/scripts/vimpatch.lua b/scripts/vimpatch.lua
index 836f672f6e..cbec50fc17 100755
--- a/scripts/vimpatch.lua
+++ b/scripts/vimpatch.lua
@@ -10,13 +10,13 @@ local function systemlist(...)
local err = nvim.nvim_get_vvar('shell_error')
local args_str = nvim.nvim_call_function('string', ...)
if 0 ~= err then
- error('command failed: '..args_str)
+ error('command failed: ' .. args_str)
end
return rv
end
local function vimpatch_sh_list_numbers()
- return systemlist( { { 'bash', '-c', 'scripts/vim-patch.sh -M', } } )
+ return systemlist({ { 'bash', '-c', 'scripts/vim-patch.sh -M' } })
end
-- Generates the lines to be inserted into the src/version.c
@@ -55,9 +55,9 @@ local function patch_version_c()
nvim.nvim_command('silent normal! j0d/};\rk')
-- Insert the lines.
nvim.nvim_call_function('append', {
- nvim.nvim_eval('line(".")'),
- lines,
- })
+ nvim.nvim_eval('line(".")'),
+ lines,
+ })
nvim.nvim_command('silent write')
end
diff --git a/scripts/windows.ti b/scripts/windows.ti
index c3a367e6d4..34028b8e00 100644
--- a/scripts/windows.ti
+++ b/scripts/windows.ti
@@ -34,7 +34,7 @@ conemu|ANIS X3.64 and Xterm 256 colors for ConEmu with libuv,
smcup=\E[?1049h, rmir@, rmkx@, rmm@, rs1@, rs2@,
setab=\E[48;5;%p1%dm, setaf=\E[38;5;%p1%dm,
sgr=\E[0%?%p1%p3%|%t;7%;%?%p2%t;4%;%?%p6%t;1%;m,
- sgr0=\E[0m, smam@, smglr@, smir@, smkx@, smm@, tbc@, u6@, u7@, u8@, u9@,
+ sgr0=\E[0m, smam@, smglp@, smgrp@, smglr@, smir@, smkx@, smm@, tbc@, u6@, u7@, u8@, u9@,
Cr@, Cs@, Ms@, XM@, kDC3@, kDC4@, kDC5@, kDC6@, kDC7@,
kDN@, kDN3@, kDN4@, kDN5@, kDN6@, kDN7@,
kEND3@, kEND4@, kEND5@, kEND6@, kEND7@,
@@ -57,7 +57,7 @@ vtpcon|ANIS emulation for console virtual terminal sequence with libuv,
mc0@, mc4@, mc5@, meml@, memu@, oc@, rmam@, rmcup=\E[?1049l,
smcup=\E[?1049h, rmir@, rmkx@, rmm@, rs1@, rs2@,
sgr=\E[0%?%p1%p3%|%t;7%;%?%p2%t;4%;%?%p6%t;1%;m,
- sgr0=\E[0m, smam@, smglr@, smir@, smkx@, smm@, tbc@, u6@, u7@, u8@, u9@,
+ sgr0=\E[0m, smam@, smglp@, smgrp@, smglr@, smir@, smkx@, smm@, tbc@, u6@, u7@, u8@, u9@,
Cr@, Cs@, Ms@, XM@, kDC3@, kDC4@, kDC5@, kDC6@, kDC7@,
kDN@, kDN3@, kDN4@, kDN5@, kDN6@, kDN7@,
kEND3@, kEND4@, kEND5@, kEND6@, kEND7@,
@@ -68,4 +68,4 @@ vtpcon|ANIS emulation for console virtual terminal sequence with libuv,
kPRV3@, kPRV4@, kPRV5@, kPRV6@, kPRV7@,
kRIT3@, kRIT4@, kRIT5@, kRIT6@, kRIT7@,
kUP3@, kUP4@, kUP5@, kUP6@, kUP7@, rmxx@, smxx@, xm@,
- use=libuv+basekey, use=libuv+exkey, use=xterm+256color, use=xterm-new,
+ use=libuv+basekey, use=libuv+exkey, use=xterm+256color, use=xterm+sl, use=xterm-new,
diff --git a/src/clint.py b/src/clint.py
index 1f588322f3..062901b43a 100755
--- a/src/clint.py
+++ b/src/clint.py
@@ -152,8 +152,10 @@ _ERROR_CATEGORIES = [
'build/endif_comment',
'build/header_guard',
'build/include_defs',
+ 'build/defs_header',
'build/printf_format',
'build/storage_class',
+ 'build/init_macro',
'readability/bool',
'readability/multiline_comment',
'readability/multiline_string',
@@ -749,53 +751,6 @@ BRACES = {
}
-CLOSING_BRACES = {v: k for k, v in BRACES.items()}
-
-
-def GetExprBracesPosition(clean_lines, linenum, pos):
- """List positions of all kinds of braces
-
- If input points to ( or { or [ then function proceeds until finding the
- position which closes it.
-
- Args:
- clean_lines: A CleansedLines instance containing the file.
- linenum: Current line number.
- pos: A position on the line.
-
- Yields:
- A tuple (linenum, pos, brace, depth) that points to each brace.
- Additionally each new line (linenum, pos, 's', depth) is yielded, for each
- line end (linenum, pos, 'e', depth) is yielded and at the very end it
- yields (linenum, pos, None, None).
- """
- depth = 0
- yielded_line_start = True
- startpos = pos
- while linenum < clean_lines.NumLines() - 1:
- line = clean_lines.elided_with_space_strings[linenum]
- if not line.startswith('#') or yielded_line_start:
- # Ignore #ifdefs, but not if it is macros that are checked
- for i, brace in enumerate(line[startpos:]):
- pos = i + startpos
- if brace != ' ' and not yielded_line_start:
- yield (linenum, pos, 's', depth)
- yielded_line_start = True
- if brace in BRACES:
- depth += 1
- yield (linenum, pos, brace, depth)
- elif brace in CLOSING_BRACES:
- yield (linenum, pos, brace, depth)
- depth -= 1
- if depth == 0:
- yield (linenum, pos, None, None)
- return
- yield (linenum, len(line) - 1, 'e', depth)
- yielded_line_start = False
- startpos = 0
- linenum += 1
-
-
def FindEndOfExpressionInLine(line, startpos, depth, startchar, endchar):
"""Find the position just after the matching endchar.
@@ -880,112 +835,51 @@ def CheckForHeaderGuard(filename, lines, error):
error(filename, 0, 'build/header_guard', 5,
'No "#pragma once" found in header')
+
def CheckIncludes(filename, lines, error):
- """Checks that headers only include _defs headers
+ """Checks that headers only include _defs headers.
Args:
filename: The name of the C++ header file.
lines: An array of strings, each representing a line of the file.
error: The function to call with any errors found.
"""
- if filename.endswith('.c.h') or filename.endswith('.in.h') or FileInfo(filename).RelativePath() in {
+ if (filename.endswith('.c.h')
+ or filename.endswith('.in.h')
+ or FileInfo(filename).RelativePath() in {
'func_attr.h',
'os/pty_process.h',
- }:
+ }):
return
- # These should be synced with the ignored headers in the `iwyu` target in
- # the Makefile.
check_includes_ignore = [
- "src/nvim/api/extmark.h",
- "src/nvim/api/private/dispatch.h",
- "src/nvim/api/private/helpers.h",
"src/nvim/api/private/validate.h",
- "src/nvim/api/ui.h",
- "src/nvim/ascii_defs.h",
"src/nvim/assert_defs.h",
- "src/nvim/autocmd.h",
- "src/nvim/autocmd_defs.h",
- "src/nvim/buffer.h",
- "src/nvim/buffer_defs.h",
"src/nvim/channel.h",
"src/nvim/charset.h",
- "src/nvim/cmdexpand.h",
- "src/nvim/cmdhist.h",
- "src/nvim/decoration.h",
- "src/nvim/diff.h",
- "src/nvim/drawline.h",
- "src/nvim/drawscreen.h",
- "src/nvim/eval.h",
- "src/nvim/eval/encode.h",
"src/nvim/eval/typval.h",
- "src/nvim/eval/typval_defs.h",
- "src/nvim/eval/userfunc.h",
- "src/nvim/eval/window.h",
- "src/nvim/event/libuv_process.h",
- "src/nvim/event/loop.h",
"src/nvim/event/multiqueue.h",
- "src/nvim/event/process.h",
- "src/nvim/event/rstream.h",
- "src/nvim/event/signal.h",
- "src/nvim/event/socket.h",
- "src/nvim/event/stream.h",
- "src/nvim/event/time.h",
- "src/nvim/event/wstream.h",
- "src/nvim/ex_cmds.h",
- "src/nvim/ex_cmds_defs.h",
- "src/nvim/ex_docmd.h",
- "src/nvim/extmark.h",
- "src/nvim/file_search.h",
- "src/nvim/fileio.h",
- "src/nvim/fold.h",
"src/nvim/garray.h",
- "src/nvim/getchar.h",
"src/nvim/globals.h",
- "src/nvim/grid.h",
"src/nvim/highlight.h",
- "src/nvim/highlight_group.h",
- "src/nvim/input.h",
- "src/nvim/insexpand.h",
- "src/nvim/keycodes.h",
- "src/nvim/log.h",
"src/nvim/lua/executor.h",
"src/nvim/main.h",
"src/nvim/mark.h",
- "src/nvim/mouse.h",
- "src/nvim/move.h",
- "src/nvim/msgpack_rpc/channel.h",
"src/nvim/msgpack_rpc/channel_defs.h",
- "src/nvim/msgpack_rpc/helpers.h",
"src/nvim/msgpack_rpc/unpacker.h",
"src/nvim/option.h",
- "src/nvim/os/fileio.h",
- "src/nvim/os/input.h",
"src/nvim/os/pty_conpty_win.h",
- "src/nvim/os/pty_process_unix.h",
"src/nvim/os/pty_process_win.h",
- "src/nvim/path.h",
- "src/nvim/plines.h",
- "src/nvim/popupmenu.h",
- "src/nvim/search.h",
- "src/nvim/spell.h",
- "src/nvim/syntax.h",
- "src/nvim/textobject.h",
- "src/nvim/tui/input.h",
- "src/nvim/tui/tui.h",
- "src/nvim/ui.h",
- "src/nvim/ui_client.h",
- "src/nvim/ui_compositor.h",
- "src/nvim/viml/parser/expressions.h",
- "src/nvim/viml/parser/parser.h",
- "src/nvim/window.h",
]
skip_headers = [
- "klib/kvec.h",
- "klib/klist.h",
"auto/config.h",
- "nvim/func_attr.h"
+ "klib/klist.h",
+ "klib/kvec.h",
+ "mpack/mpack_core.h",
+ "mpack/object.h",
+ "nvim/func_attr.h",
+ "termkey/termkey.h",
]
for i in check_includes_ignore:
@@ -999,12 +893,29 @@ def CheckIncludes(filename, lines, error):
if name in skip_headers:
continue
if (not name.endswith('.h.generated.h') and
+ not name.endswith('/defs.h') and
not name.endswith('_defs.h') and
- not name.endswith('/defs.h')):
+ not name.endswith('_defs.generated.h') and
+ not name.endswith('_enum.generated.h')):
error(filename, i, 'build/include_defs', 5,
'Headers should not include non-"_defs" headers')
+def CheckNonSymbols(filename, lines, error):
+ """Checks that a _defs.h header only contains non-symbols.
+
+ Args:
+ filename: The name of the C++ header file.
+ lines: An array of strings, each representing a line of the file.
+ error: The function to call with any errors found.
+ """
+ for i, line in enumerate(lines):
+ # Only a check against extern variables for now.
+ if line.startswith('EXTERN ') or line.startswith('extern '):
+ error(filename, i, 'build/defs_header', 5,
+ '"_defs" headers should not contain extern variables')
+
+
def CheckForBadCharacters(filename, lines, error):
"""Logs an error for each line containing bad characters.
@@ -1703,8 +1614,7 @@ def CheckSpacing(filename, clean_lines, linenum, error):
line[commentpos - 1] not in string.whitespace) or
(commentpos >= 2 and
line[commentpos - 2] not in string.whitespace))):
- error(filename, linenum, 'whitespace/comments', 2,
- 'At least two spaces is best between code and comments')
+ return
# There should always be a space between the // and the comment
commentend = commentpos + 2
if commentend < len(line) and not line[commentend] == ' ':
@@ -1815,8 +1725,7 @@ def CheckSpacing(filename, clean_lines, linenum, error):
# There shouldn't be space around unary operators
match = Search(r'(!\s|~\s|[\s]--[\s;]|[\s]\+\+[\s;])', line)
if match:
- error(filename, linenum, 'whitespace/operators', 4,
- 'Extra space for operator %s' % match.group(1))
+ return
# For if/for/while/switch, the left and right parens should be
# consistent about how many spaces are inside the parens, and
@@ -2098,7 +2007,7 @@ def CheckLanguage(filename, clean_lines, linenum, error):
if match:
error(filename, linenum, 'runtime/deprecated', 4,
'Accessing list_T internals directly is prohibited; '
- 'see https://github.com/neovim/neovim/wiki/List-management-in-Neovim')
+ 'see https://neovim.io/doc/user/dev_vimpatch.html#dev-vimpatch-list-management')
# Check for suspicious usage of "if" like
# } if (a == b) {
@@ -2179,6 +2088,11 @@ def CheckLanguage(filename, clean_lines, linenum, error):
" named ('k' followed by CamelCase) compile-time constant for"
" the size.")
+ # INIT() macro should only be used in header files.
+ if not filename.endswith('.h') and Search(r' INIT\(', line):
+ error(filename, linenum, 'build/init_macro', 4,
+ 'INIT() macro should only be used in header files.')
+
# Detect TRUE and FALSE.
match = Search(r'\b(TRUE|FALSE)\b', line)
if match:
@@ -2292,6 +2206,8 @@ def ProcessFileData(filename, file_extension, lines, error,
if file_extension == 'h':
CheckForHeaderGuard(filename, lines, error)
CheckIncludes(filename, lines, error)
+ if filename.endswith('/defs.h') or filename.endswith('_defs.h'):
+ CheckNonSymbols(filename, lines, error)
RemoveMultiLineComments(filename, lines, error)
clean_lines = CleansedLines(lines, init_lines)
diff --git a/src/klib/kbtree.h b/src/klib/kbtree.h
deleted file mode 100644
index 99f79952d7..0000000000
--- a/src/klib/kbtree.h
+++ /dev/null
@@ -1,477 +0,0 @@
-/*-
- * Copyright 1997-1999, 2001, John-Mark Gurney.
- * 2008-2009, Attractive Chaos <attractor@live.co.uk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-// Gotchas
-// -------
-//
-// if you delete from a kbtree while iterating over it you must use
-// kb_del_itr and not kb_del otherwise the iterator might point to freed memory.
-
-#ifndef NVIM_LIB_KBTREE_H
-#define NVIM_LIB_KBTREE_H
-
-#include <assert.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "nvim/memory.h"
-
-#define KB_MAX_DEPTH 64
-
-#define __KB_KEY(type, x) (x->key)
-#define __KB_PTR(btr, x) (x->ptr)
-
-#define __KB_TREE_T(name, key_t, T) \
- typedef struct kbnode_##name##_s kbnode_##name##_t; \
- struct kbnode_##name##_s { \
- int32_t n; \
- bool is_internal; \
- key_t key[2*T - 1]; \
- kbnode_##name##_t *ptr[]; \
- }; \
- typedef struct { \
- kbnode_##name##_t *root; \
- int n_keys, n_nodes; \
- } kbtree_##name##_t; \
- typedef struct { \
- kbnode_##name##_t *x; \
- int i; \
- } kbpos_##name##_t; \
- typedef struct { \
- kbpos_##name##_t stack[KB_MAX_DEPTH], *p; \
- } kbitr_##name##_t; \
-
-
-#define __kb_destroy(kbnode_t, b) do { \
- int i; \
- unsigned int max = 8; \
- kbnode_t *x, **top, **stack = 0; \
- if (b->root) { \
- top = stack = (kbnode_t **)xcalloc(max, sizeof(kbnode_t *)); \
- *top++ = (b)->root; \
- while (top != stack) { \
- x = *--top; \
- if (x->is_internal == 0) { XFREE_CLEAR(x); continue; } \
- for (i = 0; i <= x->n; ++i) \
- if (__KB_PTR(b, x)[i]) { \
- if (top - stack == (int)max) { \
- max <<= 1; \
- stack = (kbnode_t **)xrealloc(stack, max * sizeof(kbnode_t *)); \
- top = stack + (max>>1); \
- } \
- *top++ = __KB_PTR(b, x)[i]; \
- } \
- XFREE_CLEAR(x); \
- } \
- } \
- XFREE_CLEAR(stack); \
-} while (0)
-
-#define __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \
- static inline int __kb_getp_aux_##name(const kbnode_t * __restrict x, key_t * __restrict k, \
- int *r) \
- { \
- int tr, *rr, begin = 0, end = x->n; \
- if (x->n == 0) return -1; \
- rr = r? r : &tr; \
- while (begin < end) { \
- int mid = (begin + end) >> 1; \
- if (__cmp(__KB_KEY(key_t, x)[mid], *k) < 0) begin = mid + 1; \
- else end = mid; \
- } \
- if (begin == x->n) { *rr = 1; return x->n - 1; } \
- if ((*rr = __cmp(*k, __KB_KEY(key_t, x)[begin])) < 0) --begin; \
- return begin; \
- }
-
-#define __KB_GET(name, key_t, kbnode_t) \
- static key_t *kb_getp_##name(kbtree_##name##_t *b, key_t * __restrict k) \
- { \
- if (!b->root) { \
- return 0; \
- } \
- int i, r = 0; \
- kbnode_t *x = b->root; \
- while (x) { \
- i = __kb_getp_aux_##name(x, k, &r); \
- if (i >= 0 && r == 0) return &__KB_KEY(key_t, x)[i]; \
- if (x->is_internal == 0) return 0; \
- x = __KB_PTR(b, x)[i + 1]; \
- } \
- return 0; \
- } \
- static inline key_t *kb_get_##name(kbtree_##name##_t *b, key_t k) \
- { \
- return kb_getp_##name(b, &k); \
- }
-
-#define __KB_INTERVAL(name, key_t, kbnode_t) \
- static inline void kb_intervalp_##name(kbtree_##name##_t *b, key_t * __restrict k, key_t **lower, \
- key_t **upper) \
- { \
- if (!b->root) { \
- return; \
- } \
- int i, r = 0; \
- kbnode_t *x = b->root; \
- *lower = *upper = 0; \
- while (x) { \
- i = __kb_getp_aux_##name(x, k, &r); \
- if (i >= 0 && r == 0) { \
- *lower = *upper = &__KB_KEY(key_t, x)[i]; \
- return; \
- } \
- if (i >= 0) *lower = &__KB_KEY(key_t, x)[i]; \
- if (i < x->n - 1) *upper = &__KB_KEY(key_t, x)[i + 1]; \
- if (x->is_internal == 0) return; \
- x = __KB_PTR(b, x)[i + 1]; \
- } \
- } \
- static inline void kb_interval_##name(kbtree_##name##_t *b, key_t k, key_t **lower, key_t **upper) \
- { \
- kb_intervalp_##name(b, &k, lower, upper); \
- }
-
-#define __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \
- /* x must be an internal node */ \
- static inline void __kb_split_##name(kbtree_##name##_t *b, kbnode_t *x, int i, kbnode_t *y) \
- { \
- kbnode_t *z; \
- z = (kbnode_t *)xcalloc(1, y->is_internal? ILEN : sizeof(kbnode_##name##_t)); \
- ++b->n_nodes; \
- z->is_internal = y->is_internal; \
- z->n = T - 1; \
- memcpy(__KB_KEY(key_t, z), &__KB_KEY(key_t, y)[T], sizeof(key_t) * (T - 1)); \
- if (y->is_internal) memcpy(__KB_PTR(b, z), &__KB_PTR(b, y)[T], sizeof(void *) * T); \
- y->n = T - 1; \
- memmove(&__KB_PTR(b, x)[i + 2], &__KB_PTR(b, \
- x)[i + 1], sizeof(void *) * (unsigned int)(x->n - i)); \
- __KB_PTR(b, x)[i + 1] = z; \
- memmove(&__KB_KEY(key_t, x)[i + 1], &__KB_KEY(key_t, x)[i], \
- sizeof(key_t) * (unsigned int)(x->n - i)); \
- __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[T - 1]; \
- ++x->n; \
- } \
- static inline key_t *__kb_putp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k) \
- { \
- int i = x->n - 1; \
- key_t *ret; \
- if (x->is_internal == 0) { \
- i = __kb_getp_aux_##name(x, k, 0); \
- if (i != x->n - 1) \
- memmove(&__KB_KEY(key_t, x)[i + 2], &__KB_KEY(key_t, \
- x)[i + 1], \
- (unsigned int)(x->n - i - 1) * sizeof(key_t)); \
- ret = &__KB_KEY(key_t, x)[i + 1]; \
- *ret = *k; \
- ++x->n; \
- } else { \
- i = __kb_getp_aux_##name(x, k, 0) + 1; \
- if (__KB_PTR(b, x)[i]->n == 2 * T - 1) { \
- __kb_split_##name(b, x, i, __KB_PTR(b, x)[i]); \
- if (__cmp(*k, __KB_KEY(key_t, x)[i]) > 0) ++i; \
- } \
- ret = __kb_putp_aux_##name(b, __KB_PTR(b, x)[i], k); \
- } \
- return ret; \
- } \
- static inline key_t *kb_putp_##name(kbtree_##name##_t *b, key_t * __restrict k) \
- { \
- if (!b->root) { \
- b->root = (kbnode_t *)xcalloc(1, ILEN); \
- ++b->n_nodes; \
- } \
- kbnode_t *r, *s; \
- ++b->n_keys; \
- r = b->root; \
- if (r->n == 2 * T - 1) { \
- ++b->n_nodes; \
- s = (kbnode_t *)xcalloc(1, ILEN); \
- b->root = s; s->is_internal = 1; s->n = 0; \
- __KB_PTR(b, s)[0] = r; \
- __kb_split_##name(b, s, 0, r); \
- r = s; \
- } \
- return __kb_putp_aux_##name(b, r, k); \
- } \
- static inline void kb_put_##name(kbtree_##name##_t *b, key_t k) \
- { \
- kb_putp_##name(b, &k); \
- }
-
-#define __KB_DEL(name, key_t, kbnode_t, T) \
- static inline key_t __kb_delp_aux_##name(kbtree_##name##_t *b, kbnode_t *x, key_t * __restrict k, \
- int s) \
- { \
- int yn, zn, i, r = 0; \
- kbnode_t *xp, *y, *z; \
- key_t kp; \
- if (x == 0) return *k; \
- if (s) { /* s can only be 0, 1 or 2 */ \
- r = x->is_internal == 0? 0 : s == 1? 1 : -1; \
- i = s == 1? x->n - 1 : -1; \
- } else i = __kb_getp_aux_##name(x, k, &r); \
- if (x->is_internal == 0) { \
- if (s == 2) ++i; \
- kp = __KB_KEY(key_t, x)[i]; \
- memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, \
- x)[i + 1], \
- (unsigned int)(x->n - i - 1) * sizeof(key_t)); \
- --x->n; \
- return kp; \
- } \
- if (r == 0) { \
- if ((yn = __KB_PTR(b, x)[i]->n) >= T) { \
- xp = __KB_PTR(b, x)[i]; \
- kp = __KB_KEY(key_t, x)[i]; \
- __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 1); \
- return kp; \
- } else if ((zn = __KB_PTR(b, x)[i + 1]->n) >= T) { \
- xp = __KB_PTR(b, x)[i + 1]; \
- kp = __KB_KEY(key_t, x)[i]; \
- __KB_KEY(key_t, x)[i] = __kb_delp_aux_##name(b, xp, 0, 2); \
- return kp; \
- } else if (yn == T - 1 && zn == T - 1) { \
- y = __KB_PTR(b, x)[i]; z = __KB_PTR(b, x)[i + 1]; \
- __KB_KEY(key_t, y)[y->n++] = *k; \
- memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, z), (unsigned int)z->n * sizeof(key_t)); \
- if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, \
- z), \
- (unsigned int)(z->n + 1) * sizeof(void *)); \
- y->n += z->n; \
- memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, \
- x)[i + 1], \
- (unsigned int)(x->n - i - 1) * sizeof(key_t)); \
- memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, \
- x)[i + 2], \
- (unsigned int)(x->n - i - 1) * sizeof(void *)); \
- --x->n; \
- XFREE_CLEAR(z); \
- return __kb_delp_aux_##name(b, y, k, s); \
- } \
- } \
- ++i; \
- if ((xp = __KB_PTR(b, x)[i])->n == T - 1) { \
- if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n >= T) { \
- memmove(&__KB_KEY(key_t, xp)[1], __KB_KEY(key_t, xp), (unsigned int)xp->n * sizeof(key_t)); \
- if (xp->is_internal) memmove(&__KB_PTR(b, xp)[1], __KB_PTR(b, \
- xp), \
- (unsigned int)(xp->n + 1) * sizeof(void *)); \
- __KB_KEY(key_t, xp)[0] = __KB_KEY(key_t, x)[i - 1]; \
- __KB_KEY(key_t, x)[i - 1] = __KB_KEY(key_t, y)[y->n - 1]; \
- if (xp->is_internal) __KB_PTR(b, xp)[0] = __KB_PTR(b, y)[y->n]; \
- --y->n; ++xp->n; \
- } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n >= T) { \
- __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \
- __KB_KEY(key_t, x)[i] = __KB_KEY(key_t, y)[0]; \
- if (xp->is_internal) __KB_PTR(b, xp)[xp->n] = __KB_PTR(b, y)[0]; \
- --y->n; \
- memmove(__KB_KEY(key_t, y), &__KB_KEY(key_t, y)[1], (unsigned int)y->n * sizeof(key_t)); \
- if (y->is_internal) memmove(__KB_PTR(b, y), &__KB_PTR(b, \
- y)[1], \
- (unsigned int)(y->n + 1) * sizeof(void *)); \
- } else if (i > 0 && (y = __KB_PTR(b, x)[i - 1])->n == T - 1) { \
- __KB_KEY(key_t, y)[y->n++] = __KB_KEY(key_t, x)[i - 1]; \
- memmove(&__KB_KEY(key_t, y)[y->n], __KB_KEY(key_t, xp), \
- (unsigned int)xp->n * sizeof(key_t)); \
- if (y->is_internal) memmove(&__KB_PTR(b, y)[y->n], __KB_PTR(b, \
- xp), \
- (unsigned int)(xp->n + 1) * sizeof(void *)); \
- y->n += xp->n; \
- memmove(&__KB_KEY(key_t, x)[i - 1], &__KB_KEY(key_t, \
- x)[i], \
- (unsigned int)(x->n - i) * sizeof(key_t)); \
- memmove(&__KB_PTR(b, x)[i], &__KB_PTR(b, \
- x)[i + 1], (unsigned int)(x->n - i) * sizeof(void *)); \
- --x->n; \
- XFREE_CLEAR(xp); \
- xp = y; \
- } else if (i < x->n && (y = __KB_PTR(b, x)[i + 1])->n == T - 1) { \
- __KB_KEY(key_t, xp)[xp->n++] = __KB_KEY(key_t, x)[i]; \
- memmove(&__KB_KEY(key_t, xp)[xp->n], __KB_KEY(key_t, y), \
- (unsigned int)y->n * sizeof(key_t)); \
- if (xp->is_internal) memmove(&__KB_PTR(b, xp)[xp->n], __KB_PTR(b, y), \
- (unsigned int)(y->n + 1) * sizeof(void *)); \
- xp->n += y->n; \
- memmove(&__KB_KEY(key_t, x)[i], &__KB_KEY(key_t, \
- x)[i + 1], \
- (unsigned int)(x->n - i - 1) * sizeof(key_t)); \
- memmove(&__KB_PTR(b, x)[i + 1], &__KB_PTR(b, \
- x)[i + 2], \
- (unsigned int)(x->n - i - 1) * sizeof(void *)); \
- --x->n; \
- XFREE_CLEAR(y); \
- } \
- } \
- return __kb_delp_aux_##name(b, xp, k, s); \
- } \
- static inline key_t kb_delp_##name(kbtree_##name##_t *b, key_t * __restrict k) \
- { \
- kbnode_t *x; \
- key_t ret; \
- ret = __kb_delp_aux_##name(b, b->root, k, 0); \
- --b->n_keys; \
- if (b->root->n == 0 && b->root->is_internal) { \
- --b->n_nodes; \
- x = b->root; \
- b->root = __KB_PTR(b, x)[0]; \
- XFREE_CLEAR(x); \
- } \
- return ret; \
- } \
- static inline key_t kb_del_##name(kbtree_##name##_t *b, key_t k) \
- { \
- return kb_delp_##name(b, &k); \
- }
-
-#define __KB_ITR(name, key_t, kbnode_t) \
- static inline void kb_itr_first_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \
- { \
- itr->p = NULL; \
- if (b->n_keys == 0) return; \
- itr->p = itr->stack; \
- itr->p->x = b->root; itr->p->i = 0; \
- while (itr->p->x->is_internal && __KB_PTR(b, itr->p->x)[0] != 0) { \
- kbnode_t *x = itr->p->x; \
- ++itr->p; \
- itr->p->x = __KB_PTR(b, x)[0]; itr->p->i = 0; \
- } \
- } \
- static inline int kb_itr_next_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \
- { \
- if (itr->p == NULL) return 0; \
- for (;;) { \
- ++itr->p->i; \
- assert(itr->p->i <= 21); \
- while (itr->p->x && itr->p->i <= itr->p->x->n) { \
- itr->p[1].i = 0; \
- itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \
- ++itr->p; \
- } \
- if (itr->p == itr->stack) { \
- itr->p = NULL; \
- return 0; \
- } \
- --itr->p; \
- if (itr->p->x && itr->p->i < itr->p->x->n) return 1; \
- } \
- } \
- static inline int kb_itr_prev_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \
- { \
- if (itr->p == NULL) return 0; \
- for (;;) { \
- while (itr->p->x && itr->p->i >= 0) { \
- itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[itr->p->i] : 0; \
- itr->p[1].i = itr->p[1].x ? itr->p[1].x->n : -1; \
- ++itr->p; \
- } \
- if (itr->p == itr->stack) { \
- itr->p = NULL; \
- return 0; \
- } \
- --itr->p; \
- --itr->p->i; \
- if (itr->p->x && itr->p->i >= 0) return 1; \
- } \
- } \
- static inline int kb_itr_getp_##name(kbtree_##name##_t *b, key_t * __restrict k, \
- kbitr_##name##_t *itr) \
- { \
- if (b->n_keys == 0) { \
- itr->p = NULL; \
- return 0; \
- } \
- int i, r = 0; \
- itr->p = itr->stack; \
- itr->p->x = b->root; \
- while (itr->p->x) { \
- i = __kb_getp_aux_##name(itr->p->x, k, &r); \
- itr->p->i = i; \
- if (i >= 0 && r == 0) return 1; \
- ++itr->p->i; \
- assert(itr->p->i <= 21); \
- itr->p[1].x = itr->p->x->is_internal? __KB_PTR(b, itr->p->x)[i + 1] : 0; \
- ++itr->p; \
- } \
- itr->p->i = 0; \
- return 0; \
- } \
- static inline int kb_itr_get_##name(kbtree_##name##_t *b, key_t k, kbitr_##name##_t *itr) \
- { \
- return kb_itr_getp_##name(b, &k, itr); \
- } \
- static inline void kb_del_itr_##name(kbtree_##name##_t *b, kbitr_##name##_t *itr) \
- { \
- key_t k = kb_itr_key(itr); \
- kb_delp_##name(b, &k); \
- kb_itr_getp_##name(b, &k, itr); \
- }
-
-#define KBTREE_INIT(name, key_t, __cmp, T) \
- KBTREE_INIT_IMPL(name, key_t, kbnode_##name##_t, __cmp, T, \
- (sizeof(kbnode_##name##_t) + (2*T)*sizeof(void *)))
-
-#define KBTREE_INIT_IMPL(name, key_t, kbnode_t, __cmp, T, ILEN) \
- __KB_TREE_T(name, key_t, T) \
- __KB_GET_AUX1(name, key_t, kbnode_t, __cmp) \
- __KB_GET(name, key_t, kbnode_t) \
- __KB_INTERVAL(name, key_t, kbnode_t) \
- __KB_PUT(name, key_t, kbnode_t, __cmp, T, ILEN) \
- __KB_DEL(name, key_t, kbnode_t, T) \
- __KB_ITR(name, key_t, kbnode_t)
-
-#define KB_DEFAULT_SIZE 512
-
-#define kbtree_t(name) kbtree_##name##_t
-#define kbitr_t(name) kbitr_##name##_t
-#define kb_init(b) ((b)->n_keys = (b)->n_nodes = 0, (b)->root = 0)
-#define kb_destroy(name, b) __kb_destroy(kbnode_##name##_t, b)
-#define kb_get(name, b, k) kb_get_##name(b, k)
-#define kb_put(name, b, k) kb_put_##name(b, k)
-#define kb_del(name, b, k) kb_del_##name(b, k)
-#define kb_interval(name, b, k, l, u) kb_interval_##name(b, k, l, u)
-#define kb_getp(name, b, k) kb_getp_##name(b, k)
-#define kb_putp(name, b, k) kb_putp_##name(b, k)
-#define kb_delp(name, b, k) kb_delp_##name(b, k)
-#define kb_intervalp(name, b, k, l, u) kb_intervalp_##name(b, k, l, u)
-
-#define kb_itr_first(name, b, i) kb_itr_first_##name(b, i)
-#define kb_itr_get(name, b, k, i) kb_itr_get_##name(b, k, i)
-#define kb_itr_getp(name, b, k, i) kb_itr_getp_##name(b, k, i)
-#define kb_itr_next(name, b, i) kb_itr_next_##name(b, i)
-#define kb_itr_prev(name, b, i) kb_itr_prev_##name(b, i)
-#define kb_del_itr(name, b, i) kb_del_itr_##name(b, i)
-#define kb_itr_key(itr) __KB_KEY(dummy, (itr)->p->x)[(itr)->p->i]
-#define kb_itr_valid(itr) ((itr)->p >= (itr)->stack)
-
-#define kb_size(b) ((b)->n_keys)
-
-#define kb_generic_cmp(a, b) (((b) < (a)) - ((a) < (b)))
-#define kb_str_cmp(a, b) strcmp(a, b)
-
-#endif // NVIM_LIB_KBTREE_H
diff --git a/src/klib/kvec.h b/src/klib/kvec.h
index 5677a93b1b..a32b35a14c 100644
--- a/src/klib/kvec.h
+++ b/src/klib/kvec.h
@@ -105,11 +105,12 @@
} while (0)
#define kv_concat_len(v, data, len) \
- do { \
+ if (len > 0) { \
kv_ensure_space(v, len); \
+ assert((v).items); \
memcpy((v).items + (v).size, data, sizeof((v).items[0]) * len); \
(v).size = (v).size + len; \
- } while (0)
+ }
#define kv_concat(v, str) kv_concat_len(v, str, strlen(str))
#define kv_splice(v1, v0) kv_concat_len(v1, (v0).items, (v0).size)
@@ -160,10 +161,12 @@
(v).size = 0, \
(v).items = (v).init_array)
+static inline void *_memcpy_free(void *restrict dest, void *restrict src, size_t size)
+ REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_ALWAYS_INLINE;
+
/// Move data to a new destination and free source
static inline void *_memcpy_free(void *const restrict dest, void *const restrict src,
const size_t size)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET FUNC_ATTR_ALWAYS_INLINE
{
memcpy(dest, src, size);
XFREE_CLEAR(src);
diff --git a/src/mpack/lmpack.c b/src/mpack/lmpack.c
index ff21e29789..4ce4b5f3e5 100644
--- a/src/mpack/lmpack.c
+++ b/src/mpack/lmpack.c
@@ -882,7 +882,9 @@ static int lmpack_session_receive(lua_State *L)
luaL_argcheck(L, (size_t)startpos <= len, 3,
"start position must be less than or equal to the input string length");
- str += (size_t)startpos - 1;
+ size_t offset = (size_t)startpos - 1 ;
+ str += offset;
+ len -= offset;
if (session->unpacker != LUA_REFNIL) {
lmpack_geti(L, session->reg, session->unpacker);
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 3505f8be4f..047b22edcc 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -1,65 +1,57 @@
add_library(main_lib INTERFACE)
-add_executable(nvim main.c)
-set_target_properties(nvim
+# Internally we need to make a distinction between "nvim without runtime files"
+# (nvim_bin) and "nvim with runtime files" (nvim).
+add_executable(nvim_bin EXCLUDE_FROM_ALL)
+
+set_target_properties(nvim_bin
PROPERTIES
EXPORT_COMPILE_COMMANDS ON
- ENABLE_EXPORTS TRUE)
+ ENABLE_EXPORTS TRUE
+ OUTPUT_NAME nvim)
#-------------------------------------------------------------------------------
# Dependencies
#-------------------------------------------------------------------------------
-add_library(libuv INTERFACE)
-find_package(libuv CONFIG QUIET)
-if(TARGET libuv::uv_a)
- target_link_libraries(libuv INTERFACE libuv::uv_a)
- mark_as_advanced(libuv_DIR)
-else()
- # Fall back to find module for libuv versions older than v1.45.0 which don't
- # provide a config file
- find_package(Libuv 1.28.0 REQUIRED MODULE)
- target_include_directories(libuv SYSTEM BEFORE INTERFACE ${LIBUV_INCLUDE_DIR})
- target_link_libraries(libuv INTERFACE ${LIBUV_LIBRARIES})
-endif()
-
add_library(nlua0 MODULE)
if(WIN32)
target_compile_definitions(nlua0 PUBLIC LUA_BUILD_AS_DLL LUA_LIB)
set_target_properties(nlua0 PROPERTIES ENABLE_EXPORTS TRUE)
elseif(APPLE)
- set_target_properties(nlua0 PROPERTIES LINK_FLAGS "-undefined dynamic_lookup")
+ target_link_options(nlua0 PRIVATE -undefined dynamic_lookup)
endif()
+# TODO(dundargoc): unittest stops working if I create an pseudo-imported
+# library "luv" as with the other dependencies. Figure out why and fix.
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)
-find_package(Libtermkey 0.22 REQUIRED)
+find_package(Libuv 1.28.0 REQUIRED)
find_package(Libvterm 0.3.3 REQUIRED)
+find_package(Lpeg REQUIRED)
find_package(Msgpack 1.0.0 REQUIRED)
-find_package(Treesitter 0.20.8 REQUIRED)
+find_package(Treesitter 0.20.9 REQUIRED)
find_package(Unibilium 2.0 REQUIRED)
target_link_libraries(main_lib INTERFACE
iconv
- libtermkey
libvterm
+ lpeg
msgpack
treesitter
- unibilium
- lpeg)
+ unibilium)
target_link_libraries(nlua0 PUBLIC lpeg)
-# Libintl (not Intl) selects our FindLibintl.cmake script. #8464
-find_package(Libintl REQUIRED)
-target_include_directories(main_lib SYSTEM BEFORE INTERFACE ${LIBINTL_INCLUDE_DIR})
-if (LIBINTL_LIBRARY)
- target_link_libraries(main_lib INTERFACE ${LIBINTL_LIBRARY})
+if(ENABLE_LIBINTL)
+ find_package(Libintl REQUIRED) # Libintl (not Intl) selects our FindLibintl.cmake script. #8464
+ target_link_libraries(main_lib INTERFACE libintl)
endif()
+target_compile_definitions(main_lib INTERFACE HAVE_UNIBILIUM)
+
# The unit test lib requires LuaJIT; it will be skipped if LuaJIT is missing.
option(PREFER_LUA "Prefer Lua over LuaJIT in the nvim executable." OFF)
if(PREFER_LUA)
@@ -127,9 +119,11 @@ elseif(MINGW)
target_compile_definitions(main_lib INTERFACE __USE_MINGW_ANSI_STDIO)
# Enable wmain
- target_link_libraries(nvim PRIVATE -municode)
+ target_link_libraries(nvim_bin PRIVATE -municode)
elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU")
- target_compile_options(main_lib INTERFACE -fno-common
+ target_compile_options(main_lib INTERFACE
+ -Wno-conversion
+ -fno-common
$<$<CONFIG:Release>:-Wno-unused-result>
$<$<CONFIG:RelWithDebInfo>:-Wno-unused-result>
$<$<CONFIG:MinSizeRel>:-Wno-unused-result>)
@@ -142,7 +136,7 @@ elseif(CMAKE_C_COMPILER_ID MATCHES "Clang")
# workaround for clang-11 on macOS, supported on later versions
if(NOT APPLE)
- target_link_libraries(nvim PRIVATE -Wl,--no-undefined)
+ target_link_libraries(nvim_bin PRIVATE -Wl,--no-undefined)
endif()
endif()
@@ -158,16 +152,16 @@ if(CMAKE_SYSTEM_NAME MATCHES "Windows")
target_compile_definitions(main_lib INTERFACE _WIN32_WINNT=0x0602 MSWIN)
target_link_libraries(main_lib INTERFACE netapi32)
elseif(CMAKE_SYSTEM_NAME MATCHES "Darwin")
- target_link_libraries(nvim PRIVATE "-framework CoreServices")
+ target_link_libraries(nvim_bin PRIVATE "-framework CoreServices")
# Actually export symbols - symbols may not be visible even though
# ENABLE_EXPORTS is set to true. See
# https://github.com/neovim/neovim/issues/25295
- set_target_properties(nvim PROPERTIES LINK_FLAGS "-Wl,-export_dynamic")
+ target_link_options(nvim_bin PRIVATE "-Wl,-export_dynamic")
elseif(CMAKE_SYSTEM_NAME MATCHES "OpenBSD")
target_link_libraries(main_lib INTERFACE pthread c++abi)
elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS")
- target_link_libraries(nvim PRIVATE -lsocket)
+ target_link_libraries(nvim_bin PRIVATE -lsocket)
endif()
check_c_compiler_flag(-Wimplicit-fallthrough HAVE_WIMPLICIT_FALLTHROUGH_FLAG)
@@ -213,31 +207,35 @@ if(ENABLE_ASAN_UBSAN)
if(NOT MSVC)
if(CI_BUILD)
# Try to recover from all sanitize issues so we get reports about all failures
- target_compile_options(nvim PRIVATE -fsanitize-recover=all)
+ target_compile_options(nvim_bin PRIVATE -fsanitize-recover=all)
else()
- target_compile_options(nvim PRIVATE -fno-sanitize-recover=all)
+ target_compile_options(nvim_bin PRIVATE -fno-sanitize-recover=all)
endif()
- target_compile_options(nvim PRIVATE
+ target_compile_options(nvim_bin PRIVATE
-fno-omit-frame-pointer
-fno-optimize-sibling-calls
-fsanitize=undefined)
endif()
- target_compile_options(nvim PRIVATE -fsanitize=address)
- target_link_libraries(nvim PRIVATE -fsanitize=address -fsanitize=undefined)
- target_compile_definitions(nvim PRIVATE ENABLE_ASAN_UBSAN)
-elseif(ENABLE_MSAN)
+ target_compile_options(nvim_bin PRIVATE -fsanitize=address)
+ target_link_libraries(nvim_bin PRIVATE -fsanitize=address -fsanitize=undefined)
+ target_compile_definitions(nvim_bin PRIVATE ENABLE_ASAN_UBSAN)
+endif()
+
+if(ENABLE_MSAN)
message(STATUS "Enabling memory sanitizer for nvim.")
- target_compile_options(nvim PRIVATE
+ target_compile_options(nvim_bin PRIVATE
-fsanitize=memory
-fsanitize-memory-track-origins
-fno-omit-frame-pointer
-fno-optimize-sibling-calls)
- target_link_libraries(nvim PRIVATE -fsanitize=memory -fsanitize-memory-track-origins)
-elseif(ENABLE_TSAN)
+ target_link_libraries(nvim_bin PRIVATE -fsanitize=memory -fsanitize-memory-track-origins)
+endif()
+
+if(ENABLE_TSAN)
message(STATUS "Enabling thread sanitizer for nvim.")
- target_compile_options(nvim PRIVATE -fsanitize=thread -fPIE)
- target_link_libraries(nvim PRIVATE -fsanitize=thread)
+ target_compile_options(nvim_bin PRIVATE -fsanitize=thread -fPIE)
+ target_link_libraries(nvim_bin PRIVATE -fsanitize=thread)
endif()
option(CI_BUILD "CI, extra flags will be set" OFF)
@@ -252,42 +250,23 @@ endif()
option(ENABLE_IWYU "Run include-what-you-use with the compiler." OFF)
if(ENABLE_IWYU)
- find_program(IWYU_PRG NAMES include-what-you-use iwyu)
- if(NOT IWYU_PRG)
- message(FATAL_ERROR "ENABLE_IWYU is ON but include-what-you-use is not found!")
- endif()
-
+ find_program(IWYU_PRG NAMES include-what-you-use iwyu REQUIRED)
set(iwyu_flags "${IWYU_PRG};")
string(APPEND iwyu_flags "-Xiwyu;--no_default_mappings;")
string(APPEND iwyu_flags "-Xiwyu;--no_fwd_decls;")
string(APPEND iwyu_flags "-Xiwyu;--mapping_file=${PROJECT_SOURCE_DIR}/cmake.config/iwyu/mapping.imp")
- set_target_properties(nvim PROPERTIES C_INCLUDE_WHAT_YOU_USE "${iwyu_flags}")
+ set_target_properties(nvim_bin PROPERTIES C_INCLUDE_WHAT_YOU_USE "${iwyu_flags}")
target_compile_definitions(main_lib INTERFACE EXITFREE)
endif()
option(ENABLE_COMPILER_SUGGESTIONS "Enable -Wsuggest compiler warnings" OFF)
if(ENABLE_COMPILER_SUGGESTIONS)
- # Clang doesn't have -Wsuggest-attribute so check for each one.
- check_c_compiler_flag(-Wsuggest-attribute=pure HAVE_WSUGGEST_ATTRIBUTE_PURE)
- if(HAVE_WSUGGEST_ATTRIBUTE_PURE)
- target_compile_options(main_lib INTERFACE -Wsuggest-attribute=pure)
- endif()
-
- check_c_compiler_flag(-Wsuggest-attribute=const HAVE_WSUGGEST_ATTRIBUTE_CONST)
- if(HAVE_WSUGGEST_ATTRIBUTE_CONST)
- target_compile_options(main_lib INTERFACE -Wsuggest-attribute=const)
- endif()
-
- check_c_compiler_flag(-Wsuggest-attribute=malloc HAVE_WSUGGEST_ATTRIBUTE_MALLOC)
- if(HAVE_WSUGGEST_ATTRIBUTE_MALLOC)
- target_compile_options(main_lib INTERFACE -Wsuggest-attribute=malloc)
- endif()
-
- check_c_compiler_flag(-Wsuggest-attribute=cold HAVE_WSUGGEST_ATTRIBUTE_COLD)
- if(HAVE_WSUGGEST_ATTRIBUTE_COLD)
- target_compile_options(main_lib INTERFACE -Wsuggest-attribute=cold)
- endif()
+ target_compile_options(main_lib INTERFACE
+ -Wsuggest-attribute=cold
+ -Wsuggest-attribute=const
+ -Wsuggest-attribute=malloc
+ -Wsuggest-attribute=pure)
endif()
option(ENABLE_GCOV "Enable gcov support" OFF)
@@ -306,80 +285,88 @@ endif()
# Variables
#-------------------------------------------------------------------------------
-set(GENERATOR_DIR ${CMAKE_CURRENT_LIST_DIR}/generators)
+set(FUNCS_METADATA ${PROJECT_BINARY_DIR}/funcs_metadata.mpack)
+set(UI_METADATA ${PROJECT_BINARY_DIR}/ui_metadata.mpack)
+set(BINARY_LIB_DIR ${PROJECT_BINARY_DIR}/lib/nvim)
set(GENERATED_DIR ${PROJECT_BINARY_DIR}/src/nvim/auto)
-set(BINARY_LIB_DIR ${PROJECT_BINARY_DIR}/lib/nvim/)
+set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include)
+set(GENERATOR_DIR ${CMAKE_CURRENT_LIST_DIR}/generators)
+set(GEN_EVAL_TOUCH ${TOUCHES_DIR}/gen_doc_eval)
+set(LUAJIT_RUNTIME_DIR ${DEPS_PREFIX}/share/luajit-2.1/jit)
+set(NVIM_RUNTIME_DIR ${PROJECT_SOURCE_DIR}/runtime)
+set(UNICODE_DIR ${PROJECT_SOURCE_DIR}/src/unicode)
+
+# GENERATOR_DIR
set(API_DISPATCH_GENERATOR ${GENERATOR_DIR}/gen_api_dispatch.lua)
set(API_UI_EVENTS_GENERATOR ${GENERATOR_DIR}/gen_api_ui_events.lua)
-set(GENERATOR_PRELOAD ${GENERATOR_DIR}/preload.lua)
+set(CHAR_BLOB_GENERATOR ${GENERATOR_DIR}/gen_char_blob.lua)
+set(EVENTS_GENERATOR ${GENERATOR_DIR}/gen_events.lua)
+set(EX_CMDS_GENERATOR ${GENERATOR_DIR}/gen_ex_cmds.lua)
+set(FUNCS_GENERATOR ${GENERATOR_DIR}/gen_eval.lua)
set(GENERATOR_C_GRAMMAR ${GENERATOR_DIR}/c_grammar.lua)
set(GENERATOR_HASHY ${GENERATOR_DIR}/hashy.lua)
-set(API_METADATA ${PROJECT_BINARY_DIR}/api_metadata.mpack)
-set(FUNCS_DATA ${PROJECT_BINARY_DIR}/funcs_data.mpack)
-set(LUA_API_C_BINDINGS ${GENERATED_DIR}/lua_api_c_bindings.generated.c)
+set(GENERATOR_PRELOAD ${GENERATOR_DIR}/preload.lua)
set(HEADER_GENERATOR ${GENERATOR_DIR}/gen_declarations.lua)
-set(GENERATED_INCLUDES_DIR ${PROJECT_BINARY_DIR}/include)
+set(OPTIONS_ENUM_GENERATOR ${GENERATOR_DIR}/gen_options_enum.lua)
+set(OPTIONS_GENERATOR ${GENERATOR_DIR}/gen_options.lua)
+set(UNICODE_TABLES_GENERATOR ${GENERATOR_DIR}/gen_unicode_tables.lua)
+
+# GENERATED_DIR and GENERATED_INCLUDES_DIR
set(GENERATED_API_DISPATCH ${GENERATED_DIR}/api/private/dispatch_wrappers.generated.h)
-set(GENERATED_FUNCS_METADATA ${GENERATED_DIR}/api/private/funcs_metadata.generated.h)
-set(GENERATED_UI_EVENTS_CALL ${GENERATED_DIR}/ui_events_call.generated.h)
-set(GENERATED_UI_EVENTS_REMOTE ${GENERATED_DIR}/ui_events_remote.generated.h)
-set(GENERATED_UI_EVENTS_CLIENT ${GENERATED_DIR}/ui_events_client.generated.h)
-set(GENERATED_UI_EVENTS_METADATA ${GENERATED_DIR}/api/private/ui_events_metadata.generated.h)
-set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h)
+set(GENERATED_EVENTS_ENUM ${GENERATED_INCLUDES_DIR}/auevents_enum.generated.h)
+set(GENERATED_EVENTS_NAMES_MAP ${GENERATED_DIR}/auevents_name_map.generated.h)
set(GENERATED_EX_CMDS_DEFS ${GENERATED_DIR}/ex_cmds_defs.generated.h)
+set(GENERATED_EX_CMDS_ENUM ${GENERATED_INCLUDES_DIR}/ex_cmds_enum.generated.h)
set(GENERATED_FUNCS ${GENERATED_DIR}/funcs.generated.h)
+set(GENERATED_API_METADATA ${GENERATED_DIR}/api/private/api_metadata.generated.h)
set(GENERATED_KEYSETS_DEFS ${GENERATED_DIR}/keysets_defs.generated.h)
-set(GENERATED_EVENTS_ENUM ${GENERATED_INCLUDES_DIR}/auevents_enum.generated.h)
-set(GENERATED_EVENTS_NAMES_MAP ${GENERATED_DIR}/auevents_name_map.generated.h)
set(GENERATED_OPTIONS ${GENERATED_DIR}/options.generated.h)
-set(EX_CMDS_GENERATOR ${GENERATOR_DIR}/gen_ex_cmds.lua)
-set(FUNCS_GENERATOR ${GENERATOR_DIR}/gen_eval.lua)
-set(EVENTS_GENERATOR ${GENERATOR_DIR}/gen_events.lua)
-set(OPTIONS_GENERATOR ${GENERATOR_DIR}/gen_options.lua)
-set(UNICODE_TABLES_GENERATOR ${GENERATOR_DIR}/gen_unicode_tables.lua)
-set(UNICODE_DIR ${PROJECT_SOURCE_DIR}/src/unicode)
+set(GENERATED_OPTIONS_ENUM ${GENERATED_DIR}/options_enum.generated.h)
+set(GENERATED_OPTIONS_MAP ${GENERATED_DIR}/options_map.generated.h)
+set(GENERATED_UI_EVENTS_CALL ${GENERATED_DIR}/ui_events_call.generated.h)
+set(GENERATED_UI_EVENTS_CLIENT ${GENERATED_DIR}/ui_events_client.generated.h)
+set(GENERATED_UI_EVENTS_REMOTE ${GENERATED_DIR}/ui_events_remote.generated.h)
set(GENERATED_UNICODE_TABLES ${GENERATED_DIR}/unicode_tables.generated.h)
+set(LUA_API_C_BINDINGS ${GENERATED_DIR}/lua_api_c_bindings.generated.c)
set(VIM_MODULE_FILE ${GENERATED_DIR}/lua/vim_module.generated.h)
-set(NVIM_RUNTIME_DIR ${PROJECT_SOURCE_DIR}/runtime)
+
+# NVIM_RUNTIME_DIR
+set(LUA_DEFAULTS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_defaults.lua)
set(LUA_EDITOR_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_editor.lua)
-set(LUA_SHARED_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/shared.lua)
-set(LUA_LOADER_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/loader.lua)
-set(LUA_INSPECT_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/inspect.lua)
+set(LUA_FILETYPE_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/filetype.lua)
set(LUA_FS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/fs.lua)
set(LUA_F_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/F.lua)
-set(LUA_DEFAULTS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_defaults.lua)
-set(LUA_OPTIONS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_options.lua)
-set(LUA_FILETYPE_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/filetype.lua)
set(LUA_INIT_PACKAGES_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_init_packages.lua)
+set(LUA_INSPECT_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/inspect.lua)
set(LUA_KEYMAP_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/keymap.lua)
-set(CHAR_BLOB_GENERATOR ${GENERATOR_DIR}/gen_char_blob.lua)
-set(LUAJIT_RUNTIME_DIR ${DEPS_PREFIX}/share/luajit-2.1/jit)
+set(LUA_LOADER_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/loader.lua)
+set(LUA_OPTIONS_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/_options.lua)
+set(LUA_SHARED_MODULE_SOURCE ${NVIM_RUNTIME_DIR}/lua/vim/shared.lua)
-glob_wrapper(UNICODE_FILES ${UNICODE_DIR}/*.txt)
-glob_wrapper(API_HEADERS api/*.h)
+file(GLOB UNICODE_FILES CONFIGURE_DEPENDS ${UNICODE_DIR}/*.txt)
+file(GLOB API_HEADERS CONFIGURE_DEPENDS api/*.h)
list(REMOVE_ITEM API_HEADERS ${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h)
-glob_wrapper(MSGPACK_RPC_HEADERS msgpack_rpc/*.h)
+file(GLOB MSGPACK_RPC_HEADERS CONFIGURE_DEPENDS msgpack_rpc/*.h)
-target_include_directories(main_lib INTERFACE ${GENERATED_DIR})
-target_include_directories(main_lib INTERFACE ${CACHED_GENERATED_DIR})
-target_include_directories(main_lib INTERFACE ${GENERATED_INCLUDES_DIR})
-target_include_directories(main_lib INTERFACE "${PROJECT_BINARY_DIR}/cmake.config")
-target_include_directories(main_lib INTERFACE "${PROJECT_SOURCE_DIR}/src")
+target_include_directories(main_lib INTERFACE
+ ${GENERATED_DIR}
+ ${GENERATED_INCLUDES_DIR}
+ "${PROJECT_BINARY_DIR}/cmake.config"
+ "${PROJECT_SOURCE_DIR}/src")
-target_include_directories(nlua0 PUBLIC "${PROJECT_SOURCE_DIR}/src")
-target_include_directories(nlua0 PUBLIC "${PROJECT_BINARY_DIR}/cmake.config")
-target_include_directories(nlua0 PUBLIC ${GENERATED_INCLUDES_DIR})
+target_include_directories(nlua0 PUBLIC
+ "${PROJECT_SOURCE_DIR}/src"
+ "${PROJECT_BINARY_DIR}/cmake.config"
+ ${GENERATED_INCLUDES_DIR})
-file(MAKE_DIRECTORY ${TOUCHES_DIR})
-file(MAKE_DIRECTORY ${GENERATED_DIR})
-file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR})
+file(MAKE_DIRECTORY ${TOUCHES_DIR} ${GENERATED_DIR} ${GENERATED_INCLUDES_DIR})
-glob_wrapper(NVIM_SOURCES *.c)
-glob_wrapper(NVIM_HEADERS *.h)
-glob_wrapper(EXTERNAL_SOURCES ../xdiff/*.c ../mpack/*.c ../cjson/*.c ../klib/*.c)
-glob_wrapper(EXTERNAL_HEADERS ../xdiff/*.h ../mpack/*.h ../cjson/*.h ../klib/*.h)
+file(GLOB NVIM_SOURCES CONFIGURE_DEPENDS *.c)
+file(GLOB NVIM_HEADERS CONFIGURE_DEPENDS *.h)
+file(GLOB EXTERNAL_SOURCES CONFIGURE_DEPENDS ../xdiff/*.c ../mpack/*.c ../cjson/*.c ../klib/*.c ../termkey/*.c)
+file(GLOB EXTERNAL_HEADERS CONFIGURE_DEPENDS ../xdiff/*.h ../mpack/*.h ../cjson/*.h ../klib/*.h ../termkey/*.h)
-glob_wrapper(NLUA0_SOURCES ../mpack/*.c)
+file(GLOB NLUA0_SOURCES CONFIGURE_DEPENDS ../mpack/*.c)
if(PREFER_LUA)
# luajit not used, use a vendored copy of the bit module
@@ -405,8 +392,8 @@ foreach(subdir
file(MAKE_DIRECTORY ${GENERATED_DIR}/${subdir})
file(MAKE_DIRECTORY ${GENERATED_INCLUDES_DIR}/${subdir})
- glob_wrapper(sources ${subdir}/*.c)
- glob_wrapper(headers ${subdir}/*.h)
+ file(GLOB sources CONFIGURE_DEPENDS ${subdir}/*.c)
+ file(GLOB headers CONFIGURE_DEPENDS ${subdir}/*.h)
list(APPEND NVIM_SOURCES ${sources})
list(APPEND NVIM_HEADERS ${headers})
endforeach()
@@ -436,13 +423,13 @@ endforeach()
list(REMOVE_ITEM NVIM_SOURCES ${to_remove})
-# xdiff, mpack, lua-cjson: inlined external project, we don't maintain it. #9306
+# xdiff, mpack, lua-cjson, termkey: inlined external project, we don't maintain it. #9306
if(MSVC)
set_source_files_properties(
- ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -wd4090 -wd4244 -wd4267")
+ ${EXTERNAL_SOURCES} PROPERTIES COMPILE_OPTIONS "-wd4090;-wd4244;-wd4267")
else()
set_source_files_properties(
- ${EXTERNAL_SOURCES} PROPERTIES COMPILE_FLAGS "${COMPILE_FLAGS} -Wno-conversion -Wno-missing-noreturn -Wno-missing-format-attribute -Wno-double-promotion -Wno-strict-prototypes -Wno-misleading-indentation")
+ ${EXTERNAL_SOURCES} PROPERTIES COMPILE_OPTIONS "-Wno-conversion;-Wno-missing-noreturn;-Wno-missing-format-attribute;-Wno-double-promotion;-Wno-strict-prototypes;-Wno-misleading-indentation;-Wno-sign-compare;-Wno-implicit-fallthrough;-Wno-missing-prototypes;-Wno-missing-field-initializers")
endif()
# Log level (NVIM_LOG_DEBUG in log.h)
@@ -451,7 +438,7 @@ if(CI_BUILD)
# TODO(bfredl): debug log level also exposes some errors with EXITFREE in ASAN build.
else()
# Minimize logging for release-type builds.
- target_compile_definitions(nvim PRIVATE $<$<CONFIG:Debug>:NVIM_LOG_DEBUG>)
+ target_compile_definitions(nvim_bin PRIVATE $<$<CONFIG:Debug>:NVIM_LOG_DEBUG>)
endif()
if(ENABLE_ASAN_UBSAN OR ENABLE_MSAN OR ENABLE_TSAN)
@@ -463,7 +450,7 @@ endif()
#-------------------------------------------------------------------------------
get_target_property(prop main_lib INTERFACE_COMPILE_DEFINITIONS)
-foreach(gen_cdef DO_NOT_DEFINE_EMPTY_ATTRIBUTES ${prop})
+foreach(gen_cdef ${prop})
if(NOT ${gen_cdef} MATCHES "INCLUDE_GENERATED_DECLARATIONS")
list(APPEND gen_cflags "-D${gen_cdef}")
endif()
@@ -506,7 +493,7 @@ add_custom_command(
"${NVIM_VERSION_DEF_H}"
DEPENDS "${PROJECT_BINARY_DIR}/cmake.config/auto/versiondef-$<CONFIG>.h")
-set(LUA_GEN ${LUA_GEN_PRG} ${GENERATOR_PRELOAD} ${PROJECT_SOURCE_DIR} $<TARGET_FILE:nlua0>)
+set(LUA_GEN ${LUA_GEN_PRG} ${GENERATOR_PRELOAD} ${PROJECT_SOURCE_DIR} $<TARGET_FILE:nlua0> ${PROJECT_BINARY_DIR})
set(LUA_GEN_DEPS ${GENERATOR_PRELOAD} $<TARGET_FILE:nlua0>)
# NVIM_GENERATED_FOR_HEADERS: generated headers to be included in headers
@@ -566,14 +553,19 @@ add_custom_command(OUTPUT ${GENERATED_UNICODE_TABLES}
${UNICODE_FILES}
)
+set(NVIM_VERSION_LUA ${PROJECT_BINARY_DIR}/nvim_version.lua)
+configure_file(${GENERATOR_DIR}/nvim_version.lua.in ${NVIM_VERSION_LUA})
+
add_custom_command(
- OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_FUNCS_METADATA}
- ${API_METADATA} ${LUA_API_C_BINDINGS} ${GENERATED_KEYSETS_DEFS}
+ OUTPUT ${GENERATED_API_DISPATCH} ${GENERATED_API_METADATA}
+ ${FUNCS_METADATA} ${LUA_API_C_BINDINGS} ${GENERATED_KEYSETS_DEFS}
COMMAND ${LUA_GEN} ${API_DISPATCH_GENERATOR}
${GENERATED_API_DISPATCH}
- ${GENERATED_FUNCS_METADATA} ${API_METADATA}
+ ${GENERATED_API_METADATA} ${FUNCS_METADATA}
${LUA_API_C_BINDINGS}
${GENERATED_KEYSETS_DEFS}
+ ${UI_METADATA}
+ ${NVIM_VERSION_GIT_H}
${API_HEADERS}
DEPENDS
${LUA_GEN_DEPS}
@@ -581,6 +573,9 @@ add_custom_command(
${MSGPACK_RPC_HEADERS}
${API_DISPATCH_GENERATOR}
${GENERATOR_C_GRAMMAR}
+ ${UI_METADATA}
+ ${NVIM_VERSION_LUA}
+ ${NVIM_VERSION_GIT_H}
${CMAKE_CURRENT_LIST_DIR}/api/dispatch_deprecated.lua
)
@@ -625,13 +620,13 @@ list(APPEND NVIM_GENERATED_SOURCES
add_custom_command(
OUTPUT ${GENERATED_UI_EVENTS_CALL}
${GENERATED_UI_EVENTS_REMOTE}
- ${GENERATED_UI_EVENTS_METADATA}
+ ${UI_METADATA}
${GENERATED_UI_EVENTS_CLIENT}
COMMAND ${LUA_GEN} ${API_UI_EVENTS_GENERATOR}
${CMAKE_CURRENT_LIST_DIR}/api/ui_events.in.h
${GENERATED_UI_EVENTS_CALL}
${GENERATED_UI_EVENTS_REMOTE}
- ${GENERATED_UI_EVENTS_METADATA}
+ ${UI_METADATA}
${GENERATED_UI_EVENTS_CLIENT}
DEPENDS
${LUA_GEN_DEPS}
@@ -644,6 +639,7 @@ list(APPEND NVIM_GENERATED_FOR_HEADERS
"${GENERATED_EX_CMDS_ENUM}"
"${GENERATED_EVENTS_ENUM}"
"${GENERATED_KEYSETS_DEFS}"
+ "${GENERATED_OPTIONS_ENUM}"
)
list(APPEND NVIM_GENERATED_FOR_SOURCES
@@ -651,6 +647,7 @@ list(APPEND NVIM_GENERATED_FOR_SOURCES
"${GENERATED_EX_CMDS_DEFS}"
"${GENERATED_EVENTS_NAMES_MAP}"
"${GENERATED_OPTIONS}"
+ "${GENERATED_OPTIONS_MAP}"
"${GENERATED_UNICODE_TABLES}"
"${VIM_MODULE_FILE}"
)
@@ -665,8 +662,8 @@ add_custom_command(OUTPUT ${GENERATED_EX_CMDS_ENUM} ${GENERATED_EX_CMDS_DEFS}
)
add_custom_command(OUTPUT ${GENERATED_FUNCS} ${FUNCS_DATA}
- COMMAND ${LUA_GEN} ${FUNCS_GENERATOR} ${GENERATED_DIR} ${API_METADATA} ${FUNCS_DATA}
- DEPENDS ${LUA_GEN_DEPS} ${FUNCS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/eval.lua ${API_METADATA}
+ COMMAND ${LUA_GEN} ${FUNCS_GENERATOR} ${GENERATED_DIR} ${FUNCS_METADATA} ${FUNCS_DATA}
+ DEPENDS ${LUA_GEN_DEPS} ${FUNCS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/eval.lua ${FUNCS_METADATA}
)
list(APPEND NVIM_GENERATED_FOR_SOURCES
"${GENERATED_FUNCS}")
@@ -681,6 +678,11 @@ add_custom_command(OUTPUT ${GENERATED_OPTIONS}
DEPENDS ${LUA_GEN_DEPS} ${OPTIONS_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/options.lua
)
+add_custom_command(OUTPUT ${GENERATED_OPTIONS_ENUM} ${GENERATED_OPTIONS_MAP}
+ COMMAND ${LUA_GEN} ${OPTIONS_ENUM_GENERATOR} ${GENERATED_OPTIONS_ENUM} ${GENERATED_OPTIONS_MAP}
+ DEPENDS ${LUA_GEN_DEPS} ${OPTIONS_ENUM_GENERATOR} ${CMAKE_CURRENT_LIST_DIR}/options.lua
+)
+
# NVIM_GENERATED_FOR_SOURCES and NVIM_GENERATED_FOR_HEADERS must be mutually exclusive.
foreach(hfile ${NVIM_GENERATED_FOR_HEADERS})
list(FIND NVIM_GENERATED_FOR_SOURCES ${hfile} hfile_idx)
@@ -692,9 +694,9 @@ endforeach()
if(PREFER_LUA)
message(STATUS "luajit not used, skipping unit tests")
else()
- glob_wrapper(UNIT_TEST_FIXTURES ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
- target_sources(nvim PRIVATE ${UNIT_TEST_FIXTURES})
- target_compile_definitions(nvim PRIVATE UNIT_TESTING)
+ file(GLOB UNIT_TEST_FIXTURES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/test/unit/fixtures/*.c)
+ target_sources(nvim_bin PRIVATE ${UNIT_TEST_FIXTURES})
+ target_compile_definitions(nvim_bin PRIVATE UNIT_TESTING)
endif()
target_sources(main_lib INTERFACE
@@ -708,32 +710,33 @@ target_sources(main_lib INTERFACE
target_sources(nlua0 PUBLIC ${NLUA0_SOURCES})
-target_link_libraries(nvim PRIVATE main_lib PUBLIC libuv)
-install_helper(TARGETS nvim)
+target_link_libraries(nvim_bin PRIVATE main_lib PUBLIC libuv)
+install_helper(TARGETS nvim_bin)
if(MSVC)
- install(FILES $<TARGET_PDB_FILE:nvim> DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL)
+ install(FILES $<TARGET_PDB_FILE:nvim_bin> DESTINATION ${CMAKE_INSTALL_BINDIR} OPTIONAL)
endif()
if(ENABLE_LTO)
include(CheckIPOSupported)
check_ipo_supported(RESULT IPO_SUPPORTED)
if(IPO_SUPPORTED)
- set_target_properties(nvim PROPERTIES
+ set_target_properties(nvim_bin PROPERTIES
INTERPROCEDURAL_OPTIMIZATION_RELEASE TRUE
INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO TRUE
INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL TRUE)
endif()
endif()
+add_custom_target(nvim_runtime_deps)
if(WIN32)
# Copy DLLs and third-party tools to bin/ and install them along with nvim
- add_custom_target(nvim_runtime_deps ALL
- COMMAND ${CMAKE_COMMAND} -E copy_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps/
+ add_custom_command(TARGET nvim_runtime_deps
+ COMMAND ${CMAKE_COMMAND} -E ${COPY_DIRECTORY} ${PROJECT_BINARY_DIR}/windows_runtime_deps/
${CMAKE_RUNTIME_OUTPUT_DIRECTORY})
install(DIRECTORY ${PROJECT_BINARY_DIR}/windows_runtime_deps/
DESTINATION ${CMAKE_INSTALL_BINDIR})
- add_custom_target(nvim_dll_deps DEPENDS nvim
+ add_custom_target(nvim_dll_deps DEPENDS nvim_bin
COMMAND ${CMAKE_COMMAND} -E make_directory ${PROJECT_BINARY_DIR}/windows_runtime_deps
COMMAND ${CMAKE_COMMAND}
-D CMAKE_PREFIX_PATH=${CMAKE_PREFIX_PATH}
@@ -763,22 +766,17 @@ if(WIN32)
add_custom_target(external_blobs
COMMAND ${CMAKE_COMMAND} -P ${PROJECT_BINARY_DIR}/external_blobs.cmake)
add_dependencies(nvim_runtime_deps external_blobs)
-else()
- add_custom_target(nvim_runtime_deps) # Stub target to avoid CMP0046.
endif()
file(MAKE_DIRECTORY ${BINARY_LIB_DIR})
# install treesitter parser if bundled
if(EXISTS ${DEPS_PREFIX}/lib/nvim/parser)
- glob_wrapper(TREESITTER_PARSERS ${DEPS_PREFIX}/lib/nvim/parser/*)
- foreach(parser_lib ${TREESITTER_PARSERS})
- file(COPY ${parser_lib} DESTINATION ${BINARY_LIB_DIR}/parser)
- endforeach()
+ add_custom_command(TARGET nvim_runtime_deps COMMAND ${CMAKE_COMMAND} -E ${COPY_DIRECTORY} ${DEPS_PREFIX}/lib/nvim/parser ${BINARY_LIB_DIR}/parser)
endif()
install(DIRECTORY ${BINARY_LIB_DIR}
- DESTINATION ${CMAKE_INSTALL_LIBDIR}/nvim/
+ DESTINATION ${CMAKE_INSTALL_LIBDIR}
USE_SOURCE_PERMISSIONS)
if(NOT PREFER_LUA)
@@ -850,7 +848,7 @@ add_glob_target(
add_custom_target(copy_compile_commands
COMMAND ${CMAKE_COMMAND} -E copy ${PROJECT_BINARY_DIR}/compile_commands.json ${PROJECT_SOURCE_DIR}/compile_commands.json)
-add_dependencies(copy_compile_commands nvim)
+add_dependencies(copy_compile_commands nvim_bin)
add_dependencies(lintc-clang-tidy copy_compile_commands)
add_dependencies(clang-analyzer copy_compile_commands)
@@ -879,12 +877,11 @@ add_glob_target(
FLAGS -c ${UNCRUSTIFY_CONFIG} -q --check
FILES ${LINT_NVIM_SOURCES})
-add_custom_target(formatc
- COMMAND ${CMAKE_COMMAND}
- -D FORMAT_PRG=${UNCRUSTIFY_PRG}
- -D LANG=c
- -P ${PROJECT_SOURCE_DIR}/cmake/Format.cmake
- WORKING_DIRECTORY ${PROJECT_SOURCE_DIR})
+add_glob_target(
+ TARGET formatc
+ COMMAND ${UNCRUSTIFY_PRG}
+ FLAGS -c ${UNCRUSTIFY_CONFIG} --replace --no-backup
+ FILES ${LINT_NVIM_SOURCES})
add_dependencies(lintc-uncrustify uncrustify_update_config)
add_dependencies(formatc uncrustify_update_config)
@@ -893,35 +890,31 @@ add_dependencies(uncrustify_update_config uncrustify)
add_custom_target(lintc)
add_dependencies(lintc lintc-clint lintc-uncrustify lintc-clang-tidy)
+#-------------------------------------------------------------------------------
+# Docs
+#-------------------------------------------------------------------------------
+
+add_subdirectory(po)
+
add_custom_target(generated-sources DEPENDS
- ${NVIM_GENERATED_FOR_SOURCES}
${NVIM_GENERATED_FOR_HEADERS}
+ ${NVIM_GENERATED_FOR_SOURCES}
${NVIM_GENERATED_SOURCES}
)
-add_subdirectory(po)
-
-#-------------------------------------------------------------------------------
-# Docs
-#-------------------------------------------------------------------------------
-
set(VIMDOC_FILES
- ${NVIM_RUNTIME_DIR}/doc/api.mpack
${NVIM_RUNTIME_DIR}/doc/api.txt
- ${NVIM_RUNTIME_DIR}/doc/diagnostic.mpack
${NVIM_RUNTIME_DIR}/doc/diagnostic.txt
- ${NVIM_RUNTIME_DIR}/doc/lsp.mpack
${NVIM_RUNTIME_DIR}/doc/lsp.txt
- ${NVIM_RUNTIME_DIR}/doc/lua.mpack
${NVIM_RUNTIME_DIR}/doc/lua.txt
- ${NVIM_RUNTIME_DIR}/doc/treesitter.mpack
${NVIM_RUNTIME_DIR}/doc/treesitter.txt
)
-glob_wrapper(API_SOURCES ${PROJECT_SOURCE_DIR}/src/nvim/api/*.c)
+file(GLOB API_SOURCES CONFIGURE_DEPENDS ${PROJECT_SOURCE_DIR}/src/nvim/api/*.c)
-glob_wrapper(LUA_SOURCES
+file(GLOB LUA_SOURCES CONFIGURE_DEPENDS
${NVIM_RUNTIME_DIR}/lua/vim/*.lua
+ ${NVIM_RUNTIME_DIR}/lua/vim/_meta/*.lua
${NVIM_RUNTIME_DIR}/lua/vim/filetype/*.lua
${NVIM_RUNTIME_DIR}/lua/vim/lsp/*.lua
${NVIM_RUNTIME_DIR}/lua/vim/treesitter/*.lua
@@ -929,36 +922,44 @@ glob_wrapper(LUA_SOURCES
add_custom_command(
OUTPUT ${VIMDOC_FILES}
- COMMAND ${PROJECT_SOURCE_DIR}/scripts/gen_vimdoc.py
+ COMMAND ${CMAKE_COMMAND} -E env "VIMRUNTIME=${NVIM_RUNTIME_DIR}"
+ $<TARGET_FILE:nvim_bin> -l scripts/gen_vimdoc.lua
DEPENDS
nvim
${API_SOURCES}
${LUA_SOURCES}
+ ${PROJECT_SOURCE_DIR}/scripts/gen_vimdoc.lua
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
)
-set(GEN_EVAL_FILES
- ${NVIM_RUNTIME_DIR}/lua/vim/_meta/vimfn.lua
- ${NVIM_RUNTIME_DIR}/lua/vim/_meta/api.lua
- ${NVIM_RUNTIME_DIR}/lua/vim/_meta/api_keysets.lua
- ${NVIM_RUNTIME_DIR}/doc/builtin.txt
- ${NVIM_RUNTIME_DIR}/lua/vim/_meta/options.lua
- ${NVIM_RUNTIME_DIR}/doc/options.txt
-)
-
add_custom_command(
- OUTPUT ${GEN_EVAL_FILES}
- COMMAND $<TARGET_FILE:nvim> -l ${PROJECT_SOURCE_DIR}/scripts/gen_eval_files.lua
+ OUTPUT ${GEN_EVAL_TOUCH}
+ COMMAND ${CMAKE_COMMAND} -E touch ${GEN_EVAL_TOUCH}
+ COMMAND ${CMAKE_COMMAND} -E env "VIMRUNTIME=${NVIM_RUNTIME_DIR}"
+ $<TARGET_FILE:nvim_bin> -l ${PROJECT_SOURCE_DIR}/scripts/gen_eval_files.lua
DEPENDS
- ${API_METADATA}
+ nvim
+ ${FUNCS_METADATA}
${PROJECT_SOURCE_DIR}/scripts/gen_eval_files.lua
${PROJECT_SOURCE_DIR}/src/nvim/eval.lua
${PROJECT_SOURCE_DIR}/src/nvim/options.lua
- ${NVIM_RUNTIME_DIR}/doc/api.mpack
+ ${PROJECT_SOURCE_DIR}/src/nvim/vvars.lua
WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
)
-add_custom_target(doc-eval DEPENDS ${GEN_EVAL_FILES})
+add_custom_target(doc-eval DEPENDS ${GEN_EVAL_TOUCH})
add_custom_target(doc-vim DEPENDS ${VIMDOC_FILES})
add_custom_target(doc)
add_dependencies(doc doc-vim doc-eval)
+
+set(lintdoc_touch ${TOUCHES_DIR}/lintdoc)
+add_custom_command(
+ OUTPUT ${lintdoc_touch}
+ COMMAND ${CMAKE_COMMAND} -E touch ${lintdoc_touch}
+ COMMAND ${CMAKE_COMMAND} -E env "VIMRUNTIME=${NVIM_RUNTIME_DIR}"
+ $<TARGET_FILE:nvim_bin> --clean -l scripts/lintdoc.lua
+ WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}
+ DEPENDS ${DOCFILES}
+ USES_TERMINAL)
+add_custom_target(lintdoc DEPENDS ${lintdoc_touch})
+add_dependencies(lintdoc nvim)
diff --git a/src/nvim/README.md b/src/nvim/README.md
index b484d59cb3..9ef39cc90f 100644
--- a/src/nvim/README.md
+++ b/src/nvim/README.md
@@ -255,6 +255,12 @@ region is repainted internally. To also highlight excess internal redraws, use
- http://bazaar.launchpad.net/~libvterm/libvterm/trunk/view/head:/doc/seqs.txt
- http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
+Data structures
+---------------
+
+Buffer text is stored as a tree of line segments, defined in [memline.c](https://github.com/neovim/neovim/blob/v0.9.5/src/nvim/memline.c#L8-L35).
+The central idea is found in [ml_find_line](https://github.com/neovim/neovim/blob/v0.9.5/src/nvim/memline.c#L2800).
+
Nvim lifecycle
--------------
@@ -392,6 +398,68 @@ modes managed by the `state_enter` loop:
- insert mode: `insert_{enter,check,execute}()`(`edit.c`)
- terminal mode: `terminal_{enter,execute}()`(`terminal.c`)
+## Important variables
+
+The current mode is stored in `State`. The values it can have are `MODE_NORMAL`,
+`MODE_INSERT`, `MODE_CMDLINE`, and a few others.
+
+The current window is `curwin`. The current buffer is `curbuf`. These point
+to structures with the cursor position in the window, option values, the file
+name, etc.
+
+All the global variables are declared in `globals.h`.
+
+### The main loop
+
+The main loop is implemented in state_enter. The basic idea is that Vim waits
+for the user to type a character and processes it until another character is
+needed. Thus there are several places where Vim waits for a character to be
+typed. The `vgetc()` function is used for this. It also handles mapping.
+
+Updating the screen is mostly postponed until a command or a sequence of
+commands has finished. The work is done by `update_screen()`, which calls
+`win_update()` for every window, which calls `win_line()` for every line.
+See the start of [drawscreen.c](drawscreen.c) for more explanations.
+
+### Command-line mode
+
+When typing a `:`, `normal_cmd()` will call `getcmdline()` to obtain a line with
+an Ex command. `getcmdline()` calls a loop that will handle each typed
+character. It returns when hitting `<CR>` or `<Esc>` or some other character that
+ends the command line mode.
+
+### Ex commands
+
+Ex commands are handled by the function `do_cmdline()`. It does the generic
+parsing of the `:` command line and calls `do_one_cmd()` for each separate
+command. It also takes care of while loops.
+
+`do_one_cmd()` parses the range and generic arguments and puts them in the
+exarg_t and passes it to the function that handles the command.
+
+The `:` commands are listed in [ex_cmds.lua](ex_cmds.lua).
+
+### Normal mode commands
+
+The Normal mode commands are handled by the `normal_cmd()` function. It also
+handles the optional count and an extra character for some commands. These
+are passed in a `cmdarg_T` to the function that handles the command.
+
+There is a table `nv_cmds` in [normal.c](normal.c) which
+lists the first character of every
+command. The second entry of each item is the name of the function that
+handles the command.
+
+### Insert mode commands
+
+When doing an `i` or `a` command, `normal_cmd()` will call the `edit()` function.
+It contains a loop that waits for the next character and handles it. It
+returns when leaving Insert mode.
+
+### Options
+
+There is a list with all option names in [options.lua](options.lua).
+
Async event support
-------------------
diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c
index 08d9d8e117..d71bcc4bcf 100644
--- a/src/nvim/api/autocmd.c
+++ b/src/nvim/api/autocmd.c
@@ -14,13 +14,17 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.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/func_attr.h"
#include "nvim/globals.h"
#include "nvim/lua/executor.h"
#include "nvim/memory.h"
+#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -30,12 +34,12 @@
#define AUCMD_MAX_PATTERNS 256
// Copy string or array of strings into an empty array.
-// Get the event number, unless it is an error. Then goto `goto_name`.
-#define GET_ONE_EVENT(event_nr, event_str, goto_name) \
+// Get the event number, unless it is an error. Then do `or_else`.
+#define GET_ONE_EVENT(event_nr, event_str, or_else) \
event_T event_nr = \
event_name2nr_str(event_str.data.string); \
VALIDATE_S((event_nr < NUM_EVENTS), "event", event_str.data.string.data, { \
- goto goto_name; \
+ or_else; \
});
// ID for associating autocmds created via nvim_create_autocmd
@@ -71,7 +75,7 @@ static int64_t next_autocmd_id = 1;
/// - buffer: Buffer number or list of buffer numbers for buffer local autocommands
/// |autocmd-buflocal|. Cannot be used with {pattern}
/// @return Array of autocommands matching the criteria, with each item
-/// containing the following fields:
+/// containing the following fields:
/// - id (number): the autocommand id (only when defined with the API).
/// - group (integer): the autocommand group id.
/// - group_name (string): the autocommand group name.
@@ -79,20 +83,20 @@ static int64_t next_autocmd_id = 1;
/// - event (string): the autocommand event.
/// - command (string): the autocommand command. Note: this will be empty if a callback is set.
/// - callback (function|string|nil): Lua function or name of a Vim script function
-/// which is executed when this autocommand is triggered.
+/// which is executed when this autocommand is triggered.
/// - once (boolean): whether the autocommand is only run once.
/// - pattern (string): the autocommand pattern.
-/// If the autocommand is buffer local |autocmd-buffer-local|:
+/// If the autocommand is buffer local |autocmd-buffer-local|:
/// - buflocal (boolean): true if the autocommand is buffer local.
/// - buffer (number): the buffer number.
-Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
+Array nvim_get_autocmds(Dict(get_autocmds) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(9)
{
// TODO(tjdevries): Would be cool to add nvim_get_autocmds({ id = ... })
- Array autocmd_list = ARRAY_DICT_INIT;
+ ArrayBuilder autocmd_list = KV_INITIAL_VALUE;
+ kvi_init(autocmd_list);
char *pattern_filters[AUCMD_MAX_PATTERNS];
- char pattern_buflocal[BUFLOCAL_PAT_LEN];
Array buffers = ARRAY_DICT_INIT;
@@ -128,7 +132,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
Object v = opts->event;
if (v.type == kObjectTypeString) {
- GET_ONE_EVENT(event_nr, v, cleanup);
+ GET_ONE_EVENT(event_nr, v, goto cleanup);
event_set[event_nr] = true;
} else if (v.type == kObjectTypeArray) {
FOREACH_ITEM(v.data.array, event_v, {
@@ -136,7 +140,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
goto cleanup;
});
- GET_ONE_EVENT(event_nr, event_v, cleanup);
+ GET_ONE_EVENT(event_nr, event_v, goto cleanup);
event_set[event_nr] = true;
})
} else {
@@ -184,8 +188,9 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
goto cleanup;
}
- snprintf(pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
- ADD(buffers, CSTR_TO_OBJ(pattern_buflocal));
+ String pat = arena_printf(arena, "<buffer=%d>", (int)buf->handle);
+ buffers = arena_array(arena, 1);
+ ADD_C(buffers, STRING_OBJ(pat));
} else if (opts->buffer.type == kObjectTypeArray) {
if (opts->buffer.data.array.size > AUCMD_MAX_PATTERNS) {
api_set_error(err, kErrorTypeValidation, "Too many buffers (maximum of %d)",
@@ -193,6 +198,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
goto cleanup;
}
+ buffers = arena_array(arena, kv_size(opts->buffer.data.array));
FOREACH_ITEM(opts->buffer.data.array, bufnr, {
VALIDATE_EXP((bufnr.type == kObjectTypeInteger || bufnr.type == kObjectTypeBuffer),
"buffer", "Integer", api_typename(bufnr.type), {
@@ -204,8 +210,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
goto cleanup;
}
- snprintf(pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
- ADD(buffers, CSTR_TO_OBJ(pattern_buflocal));
+ ADD_C(buffers, STRING_OBJ(arena_printf(arena, "<buffer=%d>", (int)buf->handle)));
});
} else if (HAS_KEY(opts, get_autocmds, buffer)) {
VALIDATE_EXP(false, "buffer", "Integer or Array", api_typename(opts->buffer.type), {
@@ -247,6 +252,7 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
char *pat = pattern_filters[j];
int patlen = (int)strlen(pat);
+ char pattern_buflocal[BUFLOCAL_PAT_LEN];
if (aupat_is_buflocal(pat, patlen)) {
aupat_normalize_buflocal_pat(pattern_buflocal, pat, patlen,
aupat_get_buflocal_nr(pat, patlen));
@@ -264,51 +270,51 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
}
}
- Dictionary autocmd_info = ARRAY_DICT_INIT;
+ Dictionary autocmd_info = arena_dict(arena, 11);
if (ap->group != AUGROUP_DEFAULT) {
- PUT(autocmd_info, "group", INTEGER_OBJ(ap->group));
- PUT(autocmd_info, "group_name", CSTR_TO_OBJ(augroup_name(ap->group)));
+ PUT_C(autocmd_info, "group", INTEGER_OBJ(ap->group));
+ PUT_C(autocmd_info, "group_name", CSTR_AS_OBJ(augroup_name(ap->group)));
}
if (ac->id > 0) {
- PUT(autocmd_info, "id", INTEGER_OBJ(ac->id));
+ PUT_C(autocmd_info, "id", INTEGER_OBJ(ac->id));
}
if (ac->desc != NULL) {
- PUT(autocmd_info, "desc", CSTR_TO_OBJ(ac->desc));
+ PUT_C(autocmd_info, "desc", CSTR_AS_OBJ(ac->desc));
}
if (ac->exec.type == CALLABLE_CB) {
- PUT(autocmd_info, "command", STRING_OBJ(STRING_INIT));
+ PUT_C(autocmd_info, "command", STRING_OBJ(STRING_INIT));
Callback *cb = &ac->exec.callable.cb;
switch (cb->type) {
case kCallbackLua:
if (nlua_ref_is_function(cb->data.luaref)) {
- PUT(autocmd_info, "callback", LUAREF_OBJ(api_new_luaref(cb->data.luaref)));
+ PUT_C(autocmd_info, "callback", LUAREF_OBJ(api_new_luaref(cb->data.luaref)));
}
break;
case kCallbackFuncref:
case kCallbackPartial:
- PUT(autocmd_info, "callback", CSTR_AS_OBJ(callback_to_string(cb)));
+ PUT_C(autocmd_info, "callback", CSTR_AS_OBJ(callback_to_string(cb, arena)));
break;
case kCallbackNone:
abort();
}
} else {
- PUT(autocmd_info, "command", CSTR_TO_OBJ(ac->exec.callable.cmd));
+ PUT_C(autocmd_info, "command", CSTR_AS_OBJ(ac->exec.callable.cmd));
}
- 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));
+ PUT_C(autocmd_info, "pattern", CSTR_AS_OBJ(ap->pat));
+ PUT_C(autocmd_info, "event", CSTR_AS_OBJ(event_nr2name(event)));
+ PUT_C(autocmd_info, "once", BOOLEAN_OBJ(ac->once));
if (ap->buflocal_nr) {
- PUT(autocmd_info, "buflocal", BOOLEAN_OBJ(true));
- PUT(autocmd_info, "buffer", INTEGER_OBJ(ap->buflocal_nr));
+ PUT_C(autocmd_info, "buflocal", BOOLEAN_OBJ(true));
+ PUT_C(autocmd_info, "buffer", INTEGER_OBJ(ap->buflocal_nr));
} else {
- PUT(autocmd_info, "buflocal", BOOLEAN_OBJ(false));
+ PUT_C(autocmd_info, "buflocal", BOOLEAN_OBJ(false));
}
// TODO(sctx): It would be good to unify script_ctx to actually work with lua
@@ -325,16 +331,15 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err)
// Once we do that, we can put these into the autocmd_info, but I don't think it's
// useful to do that at this time.
//
- // PUT(autocmd_info, "sid", INTEGER_OBJ(ac->script_ctx.sc_sid));
- // PUT(autocmd_info, "lnum", INTEGER_OBJ(ac->script_ctx.sc_lnum));
+ // PUT_C(autocmd_info, "sid", INTEGER_OBJ(ac->script_ctx.sc_sid));
+ // PUT_C(autocmd_info, "lnum", INTEGER_OBJ(ac->script_ctx.sc_lnum));
- ADD(autocmd_list, DICTIONARY_OBJ(autocmd_info));
+ kvi_push(autocmd_list, DICTIONARY_OBJ(autocmd_info));
}
}
cleanup:
- api_free_array(buffers);
- return autocmd_list;
+ return arena_take_arraybuilder(arena, &autocmd_list);
}
/// Creates an |autocommand| event handler, defined by `callback` (Lua function or Vimscript
@@ -375,15 +380,16 @@ cleanup:
/// |autocmd-buflocal|. Cannot be used with {pattern}.
/// - desc (string) optional: description (for documentation and troubleshooting).
/// - callback (function|string) optional: Lua function (or Vimscript function name, if
-/// string) called when the event(s) is triggered. Lua callback can return true to
-/// delete the autocommand, and receives a table argument with these keys:
+/// string) called when the event(s) is triggered. Lua callback can return a truthy
+/// value (not `false` or `nil`) to delete the autocommand. Receives a table argument
+/// with these keys:
/// - id: (number) autocommand id
/// - event: (string) name of the triggered event |autocmd-events|
/// - group: (number|nil) autocommand group id, if any
-/// - match: (string) expanded value of |<amatch>|
-/// - buf: (number) expanded value of |<abuf>|
-/// - file: (string) expanded value of |<afile>|
-/// - data: (any) arbitrary data passed from |nvim_exec_autocmds()|
+/// - match: (string) expanded value of [<amatch>]
+/// - buf: (number) expanded value of [<abuf>]
+/// - file: (string) expanded value of [<afile>]
+/// - data: (any) arbitrary data passed from [nvim_exec_autocmds()]
/// - command (string) optional: Vim command to execute on event. Cannot be used with
/// {callback}
/// - once (boolean) optional: defaults to false. Run the autocommand
@@ -395,17 +401,16 @@ cleanup:
/// @see |autocommand|
/// @see |nvim_del_autocmd()|
Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autocmd) *opts,
- Error *err)
+ Arena *arena, Error *err)
FUNC_API_SINCE(9)
{
int64_t autocmd_id = -1;
char *desc = NULL;
- Array patterns = ARRAY_DICT_INIT;
- Array event_array = ARRAY_DICT_INIT;
AucmdExecutable aucmd = AUCMD_EXECUTABLE_INIT;
Callback cb = CALLBACK_NONE;
- if (!unpack_string_or_array(&event_array, &event, "event", true, err)) {
+ Array event_array = unpack_string_or_array(event, "event", true, arena, err);
+ if (ERROR_SET(err)) {
goto cleanup;
}
@@ -428,7 +433,8 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
});
cb.type = kCallbackLua;
- cb.data.luaref = api_new_luaref(callback->data.luaref);
+ cb.data.luaref = callback->data.luaref;
+ callback->data.luaref = LUA_NOREF;
break;
case kObjectTypeString:
cb.type = kCallbackFuncref;
@@ -464,7 +470,9 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
goto cleanup;
});
- if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, has_buffer, opts->buffer, err)) {
+ Array patterns = get_patterns_from_pattern_or_buf(opts->pattern, has_buffer, opts->buffer, "*",
+ arena, err);
+ if (ERROR_SET(err)) {
goto cleanup;
}
@@ -472,17 +480,13 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
desc = opts->desc.data;
}
- if (patterns.size == 0) {
- ADD(patterns, STATIC_CSTR_TO_OBJ("*"));
- }
-
VALIDATE_R((event_array.size > 0), "event", {
goto cleanup;
});
autocmd_id = next_autocmd_id++;
FOREACH_ITEM(event_array, event_str, {
- GET_ONE_EVENT(event_nr, event_str, cleanup);
+ GET_ONE_EVENT(event_nr, event_str, goto cleanup);
int retval;
@@ -509,8 +513,6 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc
cleanup:
aucmd_exec_free(&aucmd);
- api_free_array(event_array);
- api_free_array(patterns);
return autocmd_id;
}
@@ -534,9 +536,9 @@ void nvim_del_autocmd(Integer id, Error *err)
/// @param opts Parameters
/// - event: (string|table)
/// Examples:
-/// - event: "pat1"
-/// - event: { "pat1" }
-/// - event: { "pat1", "pat2", "pat3" }
+/// - event: "pat1"
+/// - event: { "pat1" }
+/// - event: { "pat1", "pat2", "pat3" }
/// - pattern: (string|table)
/// - pattern or patterns to match exactly.
/// - For example, if you have `*.py` as that pattern for the autocmd,
@@ -550,7 +552,7 @@ void nvim_del_autocmd(Integer id, Error *err)
/// - group: (string|int) The augroup name or id.
/// - NOTE: If not passed, will only delete autocmds *not* in any group.
///
-void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Error *err)
+void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(9)
{
// TODO(tjdevries): Future improvements:
@@ -559,33 +561,29 @@ void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Error *err)
// - group: Allow passing "*" or true or something like that to force doing all
// autocmds, regardless of their group.
- Array patterns = ARRAY_DICT_INIT;
- Array event_array = ARRAY_DICT_INIT;
-
- if (!unpack_string_or_array(&event_array, &opts->event, "event", false, err)) {
- goto cleanup;
+ Array event_array = unpack_string_or_array(opts->event, "event", false, arena, err);
+ if (ERROR_SET(err)) {
+ return;
}
bool has_buffer = HAS_KEY(opts, clear_autocmds, buffer);
VALIDATE((!HAS_KEY(opts, clear_autocmds, pattern) || !has_buffer),
"%s", "Cannot use both 'pattern' and 'buffer'", {
- goto cleanup;
+ return;
});
int au_group = get_augroup_from_object(opts->group, err);
if (au_group == AUGROUP_ERROR) {
- goto cleanup;
- }
-
- if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, has_buffer, opts->buffer, err)) {
- goto cleanup;
+ return;
}
// 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, STATIC_CSTR_TO_OBJ(""));
+ Array patterns = get_patterns_from_pattern_or_buf(opts->pattern, has_buffer, opts->buffer, "",
+ arena, err);
+ if (ERROR_SET(err)) {
+ return;
}
// If we didn't pass any events, that means clear all events.
@@ -594,26 +592,22 @@ void nvim_clear_autocmds(Dict(clear_autocmds) *opts, Error *err)
FOREACH_ITEM(patterns, pat_object, {
char *pat = pat_object.data.string.data;
if (!clear_autocmd(event, pat, au_group, err)) {
- goto cleanup;
+ return;
}
});
}
} else {
FOREACH_ITEM(event_array, event_str, {
- GET_ONE_EVENT(event_nr, event_str, cleanup);
+ GET_ONE_EVENT(event_nr, event_str, return );
FOREACH_ITEM(patterns, pat_object, {
char *pat = pat_object.data.string.data;
if (!clear_autocmd(event_nr, pat, au_group, err)) {
- goto cleanup;
+ return;
}
});
});
}
-
-cleanup:
- api_free_array(event_array);
- api_free_array(patterns);
}
/// Create or get an autocommand group |autocmd-groups|.
@@ -700,11 +694,11 @@ void nvim_del_augroup_by_name(String name, Error *err)
/// - buffer (integer) optional: buffer number |autocmd-buflocal|. Cannot be used with
/// {pattern}.
/// - modeline (bool) optional: defaults to true. Process the
-/// modeline after the autocommands |<nomodeline>|.
+/// modeline after the autocommands [<nomodeline>].
/// - data (any): arbitrary data to send to the autocommand callback. See
/// |nvim_create_autocmd()| for details.
/// @see |:doautocmd|
-void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
+void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(9)
{
int au_group = AUGROUP_ALL;
@@ -712,13 +706,11 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
buf_T *buf = curbuf;
- Array patterns = ARRAY_DICT_INIT;
- Array event_array = ARRAY_DICT_INIT;
-
Object *data = NULL;
- if (!unpack_string_or_array(&event_array, &event, "event", true, err)) {
- goto cleanup;
+ Array event_array = unpack_string_or_array(event, "event", true, arena, err);
+ if (ERROR_SET(err)) {
+ return;
}
switch (opts->group.type) {
@@ -727,19 +719,19 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
case kObjectTypeString:
au_group = augroup_find(opts->group.data.string.data);
VALIDATE_S((au_group != AUGROUP_ERROR), "group", opts->group.data.string.data, {
- goto cleanup;
+ return;
});
break;
case kObjectTypeInteger:
au_group = (int)opts->group.data.integer;
char *name = au_group == 0 ? NULL : augroup_name(au_group);
VALIDATE_INT(augroup_exists(name), "group", (int64_t)au_group, {
- goto cleanup;
+ return;
});
break;
default:
VALIDATE_EXP(false, "group", "String or Integer", api_typename(opts->group.type), {
- goto cleanup;
+ return;
});
}
@@ -747,23 +739,21 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
if (HAS_KEY(opts, exec_autocmds, buffer)) {
VALIDATE((!HAS_KEY(opts, exec_autocmds, pattern)),
"%s", "Cannot use both 'pattern' and 'buffer' for the same autocmd", {
- goto cleanup;
+ return;
});
has_buffer = true;
buf = find_buffer_by_handle(opts->buffer, err);
if (ERROR_SET(err)) {
- goto cleanup;
+ return;
}
}
- if (!get_patterns_from_pattern_or_buf(&patterns, opts->pattern, has_buffer, opts->buffer, err)) {
- goto cleanup;
- }
-
- if (patterns.size == 0) {
- ADD(patterns, STATIC_CSTR_TO_OBJ(""));
+ Array patterns = get_patterns_from_pattern_or_buf(opts->pattern, has_buffer, opts->buffer, "",
+ arena, err);
+ if (ERROR_SET(err)) {
+ return;
}
if (HAS_KEY(opts, exec_autocmds, data)) {
@@ -774,7 +764,7 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
bool did_aucmd = false;
FOREACH_ITEM(event_array, event_str, {
- GET_ONE_EVENT(event_nr, event_str, cleanup)
+ GET_ONE_EVENT(event_nr, event_str, return )
FOREACH_ITEM(patterns, pat, {
char *fname = !has_buffer ? pat.data.string.data : NULL;
@@ -785,28 +775,26 @@ void nvim_exec_autocmds(Object event, Dict(exec_autocmds) *opts, Error *err)
if (did_aucmd && modeline) {
do_modelines(0);
}
-
-cleanup:
- api_free_array(event_array);
- api_free_array(patterns);
}
-static bool unpack_string_or_array(Array *array, Object *v, char *k, bool required, Error *err)
+static Array unpack_string_or_array(Object v, char *k, bool required, Arena *arena, Error *err)
{
- if (v->type == kObjectTypeString) {
- ADD(*array, copy_object(*v, NULL));
- } else if (v->type == kObjectTypeArray) {
- if (!check_string_array(v->data.array, k, true, err)) {
- return false;
+ if (v.type == kObjectTypeString) {
+ Array arr = arena_array(arena, 1);
+ ADD_C(arr, v);
+ return arr;
+ } else if (v.type == kObjectTypeArray) {
+ if (!check_string_array(v.data.array, k, true, err)) {
+ return (Array)ARRAY_DICT_INIT;
}
- *array = copy_array(v->data.array, NULL);
+ return v.data.array;
} else {
- VALIDATE_EXP(!required, k, "Array or String", api_typename(v->type), {
- return false;
+ VALIDATE_EXP(!required, k, "Array or String", api_typename(v.type), {
+ return (Array)ARRAY_DICT_INIT;
});
}
- return true;
+ return (Array)ARRAY_DICT_INIT;
}
// Returns AUGROUP_ERROR if there was a problem with {group}
@@ -838,55 +826,57 @@ static int get_augroup_from_object(Object group, Error *err)
}
}
-static bool get_patterns_from_pattern_or_buf(Array *patterns, Object pattern, bool has_buffer,
- Buffer buffer, Error *err)
+static Array get_patterns_from_pattern_or_buf(Object pattern, bool has_buffer, Buffer buffer,
+ char *fallback, Arena *arena, Error *err)
{
- const char pattern_buflocal[BUFLOCAL_PAT_LEN];
+ ArrayBuilder patterns = ARRAY_DICT_INIT;
+ kvi_init(patterns);
if (pattern.type != kObjectTypeNil) {
- Object *v = &pattern;
-
- if (v->type == kObjectTypeString) {
- const char *pat = v->data.string.data;
+ if (pattern.type == kObjectTypeString) {
+ const char *pat = pattern.data.string.data;
size_t patlen = aucmd_pattern_length(pat);
while (patlen) {
- ADD(*patterns, STRING_OBJ(cbuf_to_string(pat, patlen)));
+ kvi_push(patterns, CBUF_TO_ARENA_OBJ(arena, pat, patlen));
pat = aucmd_next_pattern(pat, patlen);
patlen = aucmd_pattern_length(pat);
}
- } else if (v->type == kObjectTypeArray) {
- if (!check_string_array(v->data.array, "pattern", true, err)) {
- return false;
+ } else if (pattern.type == kObjectTypeArray) {
+ if (!check_string_array(pattern.data.array, "pattern", true, err)) {
+ return (Array)ARRAY_DICT_INIT;
}
- Array array = v->data.array;
+ Array array = pattern.data.array;
FOREACH_ITEM(array, entry, {
const char *pat = entry.data.string.data;
size_t patlen = aucmd_pattern_length(pat);
while (patlen) {
- ADD(*patterns, STRING_OBJ(cbuf_to_string(pat, patlen)));
+ kvi_push(patterns, CBUF_TO_ARENA_OBJ(arena, pat, patlen));
pat = aucmd_next_pattern(pat, patlen);
patlen = aucmd_pattern_length(pat);
}
})
} else {
- VALIDATE_EXP(false, "pattern", "String or Table", api_typename(v->type), {
- return false;
+ VALIDATE_EXP(false, "pattern", "String or Table", api_typename(pattern.type), {
+ return (Array)ARRAY_DICT_INIT;
});
}
} else if (has_buffer) {
buf_T *buf = find_buffer_by_handle(buffer, err);
if (ERROR_SET(err)) {
- return false;
+ return (Array)ARRAY_DICT_INIT;
}
- snprintf((char *)pattern_buflocal, BUFLOCAL_PAT_LEN, "<buffer=%d>", (int)buf->handle);
- ADD(*patterns, CSTR_TO_OBJ(pattern_buflocal));
+ kvi_push(patterns, STRING_OBJ(arena_printf(arena, "<buffer=%d>", (int)buf->handle)));
}
- return true;
+ if (kv_size(patterns) == 0 && fallback) {
+ kvi_push(patterns, CSTR_AS_OBJ(fallback));
+ }
+
+ return arena_take_arraybuilder(arena, &patterns);
}
static bool clear_autocmd(event_T event, char *pat, int au_group, Error *err)
diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c
index 0df231868d..7f195de959 100644
--- a/src/nvim/api/buffer.c
+++ b/src/nvim/api/buffer.c
@@ -12,10 +12,12 @@
#include "nvim/api/buffer.h"
#include "nvim/api/keysets_defs.h"
#include "nvim/api/private/defs.h"
+#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
@@ -24,28 +26,32 @@
#include "nvim/drawscreen.h"
#include "nvim/ex_cmds.h"
#include "nvim/extmark.h"
-#include "nvim/func_attr.h"
+#include "nvim/extmark_defs.h"
#include "nvim/globals.h"
#include "nvim/lua/executor.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
+#include "nvim/marktree_defs.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/move.h"
#include "nvim/ops.h"
#include "nvim/pos_defs.h"
#include "nvim/state_defs.h"
#include "nvim/types_defs.h"
#include "nvim/undo.h"
+#include "nvim/undo_defs.h"
#include "nvim/vim_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/buffer.c.generated.h"
#endif
-/// \defgroup api-buffer
-///
-/// \brief For more information on buffers, see |buffers|
+/// @brief <pre>help
+/// For more information on buffers, see |buffers|.
///
/// Unloaded Buffers: ~
///
@@ -57,6 +63,7 @@
///
/// You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()| to check
/// whether a buffer is loaded.
+/// </pre>
/// Returns the number of lines in the given buffer.
///
@@ -105,7 +112,7 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
/// Not for Lua callbacks.
/// @param opts Optional parameters.
/// - on_lines: Lua callback invoked on change.
-/// Return `true` to detach. Args:
+/// Return a truthy value (not `false` or `nil`) to detach. Args:
/// - the string "lines"
/// - buffer handle
/// - b:changedtick
@@ -118,8 +125,7 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
/// - on_bytes: Lua callback invoked on change.
/// This callback receives more granular information about the
/// change compared to on_lines.
-/// Return `true` to detach.
-/// Args:
+/// Return a truthy value (not `false` or `nil`) to detach. Args:
/// - the string "bytes"
/// - buffer handle
/// - b:changedtick
@@ -127,11 +133,13 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
/// - start column of the changed text
/// - byte offset of the changed text (from the start of
/// the buffer)
-/// - old end row of the changed text
+/// - old end row of the changed text (offset from start row)
/// - old end column of the changed text
+/// (if old end row = 0, offset from start column)
/// - old end byte length of the changed text
-/// - new end row of the changed text
+/// - new end row of the changed text (offset from start row)
/// - new end column of the changed text
+/// (if new end row = 0, offset from start column)
/// - new end byte length of the changed text
/// - on_changedtick: Lua callback invoked on changedtick
/// increment without text change. Args:
@@ -153,7 +161,7 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
/// @return False if attach failed (invalid parameter, or buffer isn't loaded);
/// otherwise True. TODO: LUA_API_NO_EVAL
Boolean nvim_buf_attach(uint64_t channel_id, Buffer buffer, Boolean send_buffer,
- DictionaryOf(LuaRef) opts, Error *err)
+ Dict(buf_attach) *opts, Error *err)
FUNC_API_SINCE(4)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -162,64 +170,40 @@ Boolean nvim_buf_attach(uint64_t channel_id, Buffer buffer, Boolean send_buffer,
return false;
}
- bool is_lua = (channel_id == LUA_INTERNAL_CALL);
BufUpdateCallbacks cb = BUF_UPDATE_CALLBACKS_INIT;
- struct {
- const char *name;
- LuaRef *dest;
- } cbs[] = {
- { "on_lines", &cb.on_lines },
- { "on_bytes", &cb.on_bytes },
- { "on_changedtick", &cb.on_changedtick },
- { "on_detach", &cb.on_detach },
- { "on_reload", &cb.on_reload },
- { NULL, NULL },
- };
-
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object *v = &opts.items[i].value;
- bool key_used = false;
- if (is_lua) {
- for (size_t j = 0; cbs[j].name; j++) {
- if (strequal(cbs[j].name, k.data)) {
- VALIDATE_T(cbs[j].name, kObjectTypeLuaRef, v->type, {
- goto error;
- });
- *(cbs[j].dest) = v->data.luaref;
- v->data.luaref = LUA_NOREF;
- key_used = true;
- break;
- }
- }
- if (key_used) {
- continue;
- } else if (strequal("utf_sizes", k.data)) {
- VALIDATE_T("utf_sizes", kObjectTypeBoolean, v->type, {
- goto error;
- });
- cb.utf_sizes = v->data.boolean;
- key_used = true;
- } else if (strequal("preview", k.data)) {
- VALIDATE_T("preview", kObjectTypeBoolean, v->type, {
- goto error;
- });
- cb.preview = v->data.boolean;
- key_used = true;
- }
+ if (channel_id == LUA_INTERNAL_CALL) {
+ if (HAS_KEY(opts, buf_attach, on_lines)) {
+ cb.on_lines = opts->on_lines;
+ opts->on_lines = LUA_NOREF;
}
- VALIDATE_S(key_used, "'opts' key", k.data, {
- goto error;
- });
+ if (HAS_KEY(opts, buf_attach, on_bytes)) {
+ cb.on_bytes = opts->on_bytes;
+ opts->on_bytes = LUA_NOREF;
+ }
+
+ if (HAS_KEY(opts, buf_attach, on_changedtick)) {
+ cb.on_changedtick = opts->on_changedtick;
+ opts->on_changedtick = LUA_NOREF;
+ }
+
+ if (HAS_KEY(opts, buf_attach, on_detach)) {
+ cb.on_detach = opts->on_detach;
+ opts->on_detach = LUA_NOREF;
+ }
+
+ if (HAS_KEY(opts, buf_attach, on_reload)) {
+ cb.on_reload = opts->on_reload;
+ opts->on_reload = LUA_NOREF;
+ }
+
+ cb.utf_sizes = opts->utf_sizes;
+
+ cb.preview = opts->preview;
}
return buf_updates_register(buf, channel_id, cb, send_buffer);
-
-error:
- buffer_update_callbacks_free(cb);
- return false;
}
/// Deactivates buffer-update events on the channel.
@@ -245,6 +229,7 @@ Boolean nvim_buf_detach(uint64_t channel_id, Buffer buffer, Error *err)
return true;
}
+/// @nodoc
void nvim__buf_redraw_range(Buffer buffer, Integer first, Integer last, Error *err)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -279,6 +264,7 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id,
Integer start,
Integer end,
Boolean strict_indexing,
+ Arena *arena,
lua_State *lstate,
Error *err)
FUNC_API_SINCE(1)
@@ -310,18 +296,10 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id,
size_t size = (size_t)(end - start);
- init_line_array(lstate, &rv, size);
-
- if (!buf_collect_lines(buf, size, (linenr_T)start, 0, (channel_id != VIML_INTERNAL_CALL), &rv,
- lstate, err)) {
- goto end;
- }
+ init_line_array(lstate, &rv, size, arena);
-end:
- if (ERROR_SET(err)) {
- api_free_array(rv);
- rv.items = NULL;
- }
+ buf_collect_lines(buf, size, (linenr_T)start, 0, (channel_id != VIML_INTERNAL_CALL), &rv,
+ lstate, arena);
return rv;
}
@@ -348,7 +326,8 @@ end:
/// @param replacement Array of lines to use as replacement
/// @param[out] err Error details, if any
void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integer end,
- Boolean strict_indexing, ArrayOf(String) replacement, Error *err)
+ Boolean strict_indexing, ArrayOf(String) replacement, Arena *arena,
+ Error *err)
FUNC_API_SINCE(1)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
@@ -358,12 +337,10 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ
return;
}
- // load buffer first if it's not loaded
- if (buf->b_ml.ml_mfp == NULL) {
- if (!buf_ensure_loaded(buf)) {
- api_set_error(err, kErrorTypeException, "Failed to load buffer");
- return;
- }
+ // Load buffer if necessary. #22670
+ if (!buf_ensure_loaded(buf)) {
+ api_set_error(err, kErrorTypeException, "Failed to load buffer");
+ return;
}
bool oob = false;
@@ -385,14 +362,14 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ
size_t new_len = replacement.size;
size_t old_len = (size_t)(end - start);
ptrdiff_t extra = 0; // lines added to text, can be negative
- char **lines = (new_len != 0) ? xcalloc(new_len, sizeof(char *)) : NULL;
+ char **lines = (new_len != 0) ? arena_alloc(arena, new_len * sizeof(char *), true) : NULL;
for (size_t i = 0; i < new_len; i++) {
const String l = replacement.items[i].data.string;
// Fill lines[i] with l's contents. Convert NULs to newlines as required by
// NL-used-for-NUL.
- lines[i] = xmemdupz(l.data, l.size);
+ lines[i] = arena_memdupz(arena, l.data, l.size);
memchrsub(lines[i], NUL, NL, l.size);
}
@@ -437,15 +414,12 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ
goto end;
});
- if (ml_replace_buf(buf, (linenr_T)lnum, lines[i], false) == FAIL) {
+ if (ml_replace_buf(buf, (linenr_T)lnum, lines[i], false, true) == FAIL) {
api_set_error(err, kErrorTypeException, "Failed to replace line");
goto end;
}
inserted_bytes += (bcount_t)strlen(lines[i]) + 1;
- // Mark lines that haven't been passed to the buffer as they need
- // to be freed later
- lines[i] = NULL;
}
// Now we may need to insert the remaining new old_len
@@ -463,9 +437,6 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ
inserted_bytes += (bcount_t)strlen(lines[i]) + 1;
- // Same as with replacing, but we also need to free lines
- xfree(lines[i]);
- lines[i] = NULL;
extra++;
}
@@ -488,11 +459,6 @@ void nvim_buf_set_lines(uint64_t channel_id, Buffer buffer, Integer start, Integ
}
end:
- for (size_t i = 0; i < new_len; i++) {
- xfree(lines[i]);
- }
-
- xfree(lines);
try_end(err);
}
@@ -525,7 +491,8 @@ end:
/// @param replacement Array of lines to use as replacement
/// @param[out] err Error details, if any
void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, Integer start_col,
- Integer end_row, Integer end_col, ArrayOf(String) replacement, Error *err)
+ Integer end_row, Integer end_col, ArrayOf(String) replacement, Arena *arena,
+ Error *err)
FUNC_API_SINCE(7)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
@@ -540,12 +507,10 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
return;
}
- // load buffer first if it's not loaded
- if (buf->b_ml.ml_mfp == NULL) {
- if (!buf_ensure_loaded(buf)) {
- api_set_error(err, kErrorTypeException, "Failed to load buffer");
- return;
- }
+ // Load buffer if necessary. #22670
+ if (!buf_ensure_loaded(buf)) {
+ api_set_error(err, kErrorTypeException, "Failed to load buffer");
+ return;
}
bool oob = false;
@@ -562,33 +527,31 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
return;
});
- char *str_at_start = NULL;
- char *str_at_end = NULL;
-
- // Another call to ml_get_buf() may free the line, so make a copy.
- str_at_start = xstrdup(ml_get_buf(buf, (linenr_T)start_row));
+ // Another call to ml_get_buf() may free the lines, so we make copies
+ char *str_at_start = ml_get_buf(buf, (linenr_T)start_row);
size_t len_at_start = strlen(str_at_start);
+ str_at_start = arena_memdupz(arena, str_at_start, len_at_start);
start_col = start_col < 0 ? (int64_t)len_at_start + start_col + 1 : start_col;
VALIDATE_RANGE((start_col >= 0 && (size_t)start_col <= len_at_start), "start_col", {
- goto early_end;
+ return;
});
- // Another call to ml_get_buf() may free the line, so make a copy.
- str_at_end = xstrdup(ml_get_buf(buf, (linenr_T)end_row));
+ char *str_at_end = ml_get_buf(buf, (linenr_T)end_row);
size_t len_at_end = strlen(str_at_end);
+ str_at_end = arena_memdupz(arena, str_at_end, len_at_end);
end_col = end_col < 0 ? (int64_t)len_at_end + end_col + 1 : end_col;
VALIDATE_RANGE((end_col >= 0 && (size_t)end_col <= len_at_end), "end_col", {
- goto early_end;
+ return;
});
VALIDATE((start_row <= end_row && !(end_row == start_row && start_col > end_col)),
"%s", "'start' is higher than 'end'", {
- goto early_end;
+ return;
});
bool disallow_nl = (channel_id != VIML_INTERNAL_CALL);
if (!check_string_array(replacement, "replacement string", disallow_nl, err)) {
- goto early_end;
+ return;
}
size_t new_len = replacement.size;
@@ -618,7 +581,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
if (replacement.size == 1) {
firstlen += last_part_len;
}
- char *first = xmallocz(firstlen);
+ char *first = arena_allocz(arena, firstlen);
char *last = NULL;
memcpy(first, str_at_start, (size_t)start_col);
memcpy(first + start_col, first_item.data, first_item.size);
@@ -626,13 +589,13 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
if (replacement.size == 1) {
memcpy(first + start_col + first_item.size, str_at_end + end_col, last_part_len);
} else {
- last = xmallocz(last_item.size + last_part_len);
+ last = arena_allocz(arena, last_item.size + last_part_len);
memcpy(last, last_item.data, last_item.size);
memchrsub(last, NUL, NL, last_item.size);
memcpy(last + last_item.size, str_at_end + end_col, last_part_len);
}
- char **lines = xcalloc(new_len, sizeof(char *));
+ char **lines = arena_alloc(arena, new_len * sizeof(char *), true);
lines[0] = first;
new_byte += (bcount_t)(first_item.size);
for (size_t i = 1; i < new_len - 1; i++) {
@@ -640,7 +603,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
// Fill lines[i] with l's contents. Convert NULs to newlines as required by
// NL-used-for-NUL.
- lines[i] = xmemdupz(l.data, l.size);
+ lines[i] = arena_memdupz(arena, l.data, l.size);
memchrsub(lines[i], NUL, NL, l.size);
new_byte += (bcount_t)(l.size) + 1;
}
@@ -692,13 +655,10 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
goto end;
});
- if (ml_replace_buf(buf, (linenr_T)lnum, lines[i], false) == FAIL) {
+ if (ml_replace_buf(buf, (linenr_T)lnum, lines[i], false, true) == FAIL) {
api_set_error(err, kErrorTypeException, "Failed to replace line");
goto end;
}
- // Mark lines that haven't been passed to the buffer as they need
- // to be freed later
- lines[i] = NULL;
}
// Now we may need to insert the remaining new old_len
@@ -714,9 +674,6 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
goto end;
}
- // Same as with replacing, but we also need to free lines
- xfree(lines[i]);
- lines[i] = NULL;
extra++;
}
@@ -749,15 +706,7 @@ void nvim_buf_set_text(uint64_t channel_id, Buffer buffer, Integer start_row, In
}
end:
- for (size_t i = 0; i < new_len; i++) {
- xfree(lines[i]);
- }
- xfree(lines);
try_end(err);
-
-early_end:
- xfree(str_at_start);
- xfree(str_at_end);
}
/// Gets a range from the buffer.
@@ -782,16 +731,12 @@ early_end:
ArrayOf(String) nvim_buf_get_text(uint64_t channel_id, Buffer buffer,
Integer start_row, Integer start_col,
Integer end_row, Integer end_col,
- Dictionary opts, lua_State *lstate,
- Error *err)
+ Dict(empty) *opts,
+ Arena *arena, lua_State *lstate, Error *err)
FUNC_API_SINCE(9)
{
Array rv = ARRAY_DICT_INIT;
- VALIDATE((opts.size == 0), "%s", "opts dict isn't empty", {
- return rv;
- });
-
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
@@ -822,44 +767,38 @@ ArrayOf(String) nvim_buf_get_text(uint64_t channel_id, Buffer buffer,
size_t size = (size_t)(end_row - start_row) + 1;
- init_line_array(lstate, &rv, size);
+ init_line_array(lstate, &rv, size, arena);
if (start_row == end_row) {
String line = buf_get_text(buf, start_row, start_col, end_col, err);
if (ERROR_SET(err)) {
goto end;
}
- push_linestr(lstate, &rv, line.data, line.size, 0, replace_nl);
+ push_linestr(lstate, &rv, line.data, line.size, 0, replace_nl, arena);
return rv;
}
String str = buf_get_text(buf, start_row, start_col, MAXCOL - 1, err);
-
- push_linestr(lstate, &rv, str.data, str.size, 0, replace_nl);
-
if (ERROR_SET(err)) {
goto end;
}
+ push_linestr(lstate, &rv, str.data, str.size, 0, replace_nl, arena);
+
if (size > 2) {
- if (!buf_collect_lines(buf, size - 2, (linenr_T)start_row + 1, 1, replace_nl, &rv, lstate,
- err)) {
- goto end;
- }
+ buf_collect_lines(buf, size - 2, (linenr_T)start_row + 1, 1, replace_nl, &rv, lstate, arena);
}
str = buf_get_text(buf, end_row, 0, end_col, err);
- push_linestr(lstate, &rv, str.data, str.size, (int)(size - 1), replace_nl);
-
if (ERROR_SET(err)) {
goto end;
}
+ push_linestr(lstate, &rv, str.data, str.size, (int)(size - 1), replace_nl, arena);
+
end:
if (ERROR_SET(err)) {
- api_free_array(rv);
- rv.size = 0;
- rv.items = NULL;
+ return (Array)ARRAY_DICT_INIT;
}
return rv;
@@ -905,7 +844,7 @@ Integer nvim_buf_get_offset(Buffer buffer, Integer index, Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Variable value
-Object nvim_buf_get_var(Buffer buffer, String name, Error *err)
+Object nvim_buf_get_var(Buffer buffer, String name, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -914,7 +853,7 @@ Object nvim_buf_get_var(Buffer buffer, String name, Error *err)
return (Object)OBJECT_INIT;
}
- return dict_get_value(buf->b_vars, name, err);
+ return dict_get_value(buf->b_vars, name, arena, err);
}
/// Gets a changed tick of a buffer
@@ -937,12 +876,12 @@ Integer nvim_buf_get_changedtick(Buffer buffer, Error *err)
/// Gets a list of buffer-local |mapping| definitions.
///
-/// @param mode Mode short-name ("n", "i", "v", ...)
/// @param buffer Buffer handle, or 0 for current buffer
+/// @param mode Mode short-name ("n", "i", "v", ...)
/// @param[out] err Error details, if any
/// @returns Array of |maparg()|-like dictionaries describing mappings.
/// The "buffer" key holds the associated buffer handle.
-ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err)
+ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Arena *arena, Error *err)
FUNC_API_SINCE(3)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -951,7 +890,7 @@ ArrayOf(Dictionary) nvim_buf_get_keymap(Buffer buffer, String mode, Error *err)
return (Array)ARRAY_DICT_INIT;
}
- return keymap_array(mode, buf);
+ return keymap_array(mode, buf, arena);
}
/// Sets a buffer-local |mapping| for the given mode.
@@ -993,7 +932,7 @@ void nvim_buf_set_var(Buffer buffer, String name, Object value, Error *err)
return;
}
- dict_set_var(buf->b_vars, name, value, false, false, err);
+ dict_set_var(buf->b_vars, name, value, false, false, NULL, err);
}
/// Removes a buffer-scoped (b:) variable
@@ -1010,7 +949,7 @@ void nvim_buf_del_var(Buffer buffer, String name, Error *err)
return;
}
- dict_set_var(buf->b_vars, name, NIL, true, false, err);
+ dict_set_var(buf->b_vars, name, NIL, true, false, NULL, err);
}
/// Gets the full file name for the buffer
@@ -1018,7 +957,7 @@ void nvim_buf_del_var(Buffer buffer, String name, Error *err)
/// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any
/// @return Buffer name
-String nvim_buf_get_name(Buffer buffer, Arena *arena, Error *err)
+String nvim_buf_get_name(Buffer buffer, Error *err)
FUNC_API_SINCE(1)
{
String rv = STRING_INIT;
@@ -1082,7 +1021,7 @@ Boolean nvim_buf_is_loaded(Buffer buffer)
/// @param opts Optional parameters. Keys:
/// - force: Force deletion and ignore unsaved changes.
/// - unload: Unloaded only, do not delete. See |:bunload|
-void nvim_buf_delete(Buffer buffer, Dictionary opts, Error *err)
+void nvim_buf_delete(Buffer buffer, Dict(buf_delete) *opts, Error *err)
FUNC_API_SINCE(7)
FUNC_API_TEXTLOCK
{
@@ -1092,25 +1031,9 @@ void nvim_buf_delete(Buffer buffer, Dictionary opts, Error *err)
return;
}
- bool force = false;
- bool unload = false;
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object v = opts.items[i].value;
- if (strequal("force", k.data)) {
- force = api_object_to_bool(v, "force", false, err);
- } else if (strequal("unload", k.data)) {
- unload = api_object_to_bool(v, "unload", false, err);
- } else {
- VALIDATE_S(false, "'opts' key", k.data, {
- return;
- });
- }
- }
+ bool force = opts->force;
- if (ERROR_SET(err)) {
- return;
- }
+ bool unload = opts->unload;
int result = do_buffer(unload ? DOBUF_UNLOAD : DOBUF_WIPE,
DOBUF_FIRST,
@@ -1194,7 +1117,7 @@ Boolean nvim_buf_del_mark(Buffer buffer, String name, Error *err)
/// @return true if the mark was set, else false.
/// @see |nvim_buf_del_mark()|
/// @see |nvim_buf_get_mark()|
-Boolean nvim_buf_set_mark(Buffer buffer, String name, Integer line, Integer col, Dictionary opts,
+Boolean nvim_buf_set_mark(Buffer buffer, String name, Integer line, Integer col, Dict(empty) *opts,
Error *err)
FUNC_API_SINCE(8)
{
@@ -1227,7 +1150,7 @@ Boolean nvim_buf_set_mark(Buffer buffer, String name, Integer line, Integer col,
/// uppercase/file mark set in another buffer.
/// @see |nvim_buf_set_mark()|
/// @see |nvim_buf_del_mark()|
-ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
+ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
@@ -1257,8 +1180,9 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
pos = fm->mark;
}
- ADD(rv, INTEGER_OBJ(pos.lnum));
- ADD(rv, INTEGER_OBJ(pos.col));
+ rv = arena_array(arena, 2);
+ ADD_C(rv, INTEGER_OBJ(pos.lnum));
+ ADD_C(rv, INTEGER_OBJ(pos.col));
return rv;
}
@@ -1279,8 +1203,7 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
/// @param fun Function to call inside the buffer (currently Lua callable
/// only)
/// @param[out] err Error details, if any
-/// @return Return value of function. NB: will deepcopy Lua values
-/// currently, use upvalues to send Lua references in and out.
+/// @return Return value of function.
Object nvim_buf_call(Buffer buffer, LuaRef fun, Error *err)
FUNC_API_SINCE(7)
FUNC_API_LUA_ONLY
@@ -1294,35 +1217,35 @@ Object nvim_buf_call(Buffer buffer, LuaRef fun, Error *err)
aucmd_prepbuf(&aco, buf);
Array args = ARRAY_DICT_INIT;
- Object res = nlua_call_ref(fun, NULL, args, true, err);
+ Object res = nlua_call_ref(fun, NULL, args, kRetLuaref, NULL, err);
aucmd_restbuf(&aco);
try_end(err);
return res;
}
-Dictionary nvim__buf_stats(Buffer buffer, Error *err)
+/// @nodoc
+Dictionary nvim__buf_stats(Buffer buffer, Arena *arena, Error *err)
{
- Dictionary rv = ARRAY_DICT_INIT;
-
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
- return rv;
+ return (Dictionary)ARRAY_DICT_INIT;
}
+ Dictionary rv = arena_dict(arena, 7);
// Number of times the cached line was flushed.
// This should generally not increase while editing the same
// line in the same mode.
- PUT(rv, "flush_count", INTEGER_OBJ(buf->flush_count));
+ PUT_C(rv, "flush_count", INTEGER_OBJ(buf->flush_count));
// lnum of current line
- PUT(rv, "current_lnum", INTEGER_OBJ(buf->b_ml.ml_line_lnum));
+ PUT_C(rv, "current_lnum", INTEGER_OBJ(buf->b_ml.ml_line_lnum));
// whether the line has unflushed changes.
- PUT(rv, "line_dirty", BOOLEAN_OBJ(buf->b_ml.ml_flags & ML_LINE_DIRTY));
+ PUT_C(rv, "line_dirty", BOOLEAN_OBJ(buf->b_ml.ml_flags & ML_LINE_DIRTY));
// NB: this should be zero at any time API functions are called,
// this exists to debug issues
- PUT(rv, "dirty_bytes", INTEGER_OBJ((Integer)buf->deleted_bytes));
- PUT(rv, "dirty_bytes2", INTEGER_OBJ((Integer)buf->deleted_bytes2));
- PUT(rv, "virt_blocks", INTEGER_OBJ((Integer)buf->b_virt_line_blocks));
+ PUT_C(rv, "dirty_bytes", INTEGER_OBJ((Integer)buf->deleted_bytes));
+ PUT_C(rv, "dirty_bytes2", INTEGER_OBJ((Integer)buf->deleted_bytes2));
+ PUT_C(rv, "virt_blocks", INTEGER_OBJ((Integer)buf_meta_total(buf, kMTMetaLines)));
u_header_T *uhp = NULL;
if (buf->b_u_curhead != NULL) {
@@ -1331,7 +1254,7 @@ Dictionary nvim__buf_stats(Buffer buffer, Error *err)
uhp = buf->b_u_newhead;
}
if (uhp) {
- PUT(rv, "uhp_extmark_size", INTEGER_OBJ((Integer)kv_size(uhp->uh_extmark)));
+ PUT_C(rv, "uhp_extmark_size", INTEGER_OBJ((Integer)kv_size(uhp->uh_extmark)));
}
return rv;
@@ -1434,13 +1357,12 @@ static void fix_cursor_cols(win_T *win, linenr_T start_row, colnr_T start_col, l
/// @param lstate Lua state. When NULL the Array is initialized instead.
/// @param a Array to initialize
/// @param size Size of array
-static inline void init_line_array(lua_State *lstate, Array *a, size_t size)
+static inline void init_line_array(lua_State *lstate, Array *a, size_t size, Arena *arena)
{
if (lstate) {
lua_createtable(lstate, (int)size, 0);
} else {
- a->size = size;
- a->items = xcalloc(a->size, sizeof(Object));
+ *a = arena_array(arena, size);
}
}
@@ -1453,14 +1375,15 @@ static inline void init_line_array(lua_State *lstate, Array *a, size_t size)
/// @param a Array to push onto when not using Lua
/// @param s String to push
/// @param len Size of string
-/// @param idx 0-based index to place s
+/// @param idx 0-based index to place s (only used for Lua)
/// @param replace_nl Replace newlines ('\n') with null ('\0')
static void push_linestr(lua_State *lstate, Array *a, const char *s, size_t len, int idx,
- bool replace_nl)
+ bool replace_nl, Arena *arena)
{
if (lstate) {
// Vim represents NULs as NLs
if (s && replace_nl && strchr(s, '\n')) {
+ // TODO(bfredl): could manage scratch space in the arena, for the NUL case
char *tmp = xmemdupz(s, len);
strchrsub(tmp, '\n', '\0');
lua_pushlstring(lstate, tmp, len);
@@ -1471,15 +1394,15 @@ static void push_linestr(lua_State *lstate, Array *a, const char *s, size_t len,
lua_rawseti(lstate, -2, idx + 1);
} else {
String str = STRING_INIT;
- if (s) {
- str = cbuf_to_string(s, len);
+ if (len > 0) {
+ str = CBUF_TO_ARENA_STR(arena, s, len);
if (replace_nl) {
// Vim represents NULs as NLs, but this may confuse clients.
strchrsub(str.data, '\n', '\0');
}
}
- a->items[idx] = STRING_OBJ(str);
+ ADD_C(*a, STRING_OBJ(str));
}
}
@@ -1490,27 +1413,17 @@ static void push_linestr(lua_State *lstate, Array *a, const char *s, size_t len,
/// @param n Number of lines to collect
/// @param replace_nl Replace newlines ("\n") with NUL
/// @param start Line number to start from
-/// @param start_idx First index to push to
+/// @param start_idx First index to push to (only used for Lua)
/// @param[out] l If not NULL, Lines are copied here
/// @param[out] lstate If not NULL, Lines are pushed into a table onto the stack
/// @param err[out] Error, if any
/// @return true unless `err` was set
-bool buf_collect_lines(buf_T *buf, size_t n, linenr_T start, int start_idx, bool replace_nl,
- Array *l, lua_State *lstate, Error *err)
+void buf_collect_lines(buf_T *buf, size_t n, linenr_T start, int start_idx, bool replace_nl,
+ Array *l, lua_State *lstate, Arena *arena)
{
for (size_t i = 0; i < n; i++) {
linenr_T lnum = start + (linenr_T)i;
-
- if (lnum >= MAXLNUM) {
- if (err != NULL) {
- api_set_error(err, kErrorTypeValidation, "Line index is too high");
- }
- return false;
- }
-
char *bufstr = ml_get_buf(buf, lnum);
- push_linestr(lstate, l, bufstr, strlen(bufstr), start_idx + (int)i, replace_nl);
+ push_linestr(lstate, l, bufstr, strlen(bufstr), start_idx + (int)i, replace_nl, arena);
}
-
- return true;
}
diff --git a/src/nvim/api/buffer.h b/src/nvim/api/buffer.h
index f3971c1d30..fe2d104058 100644
--- a/src/nvim/api/buffer.h
+++ b/src/nvim/api/buffer.h
@@ -5,7 +5,8 @@
#include "nvim/api/keysets_defs.h" // IWYU pragma: keep
#include "nvim/api/private/defs.h" // IWYU pragma: keep
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
+#include "nvim/pos_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/buffer.h.generated.h"
diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c
index 2a57ce9a19..779e216c74 100644
--- a/src/nvim/api/command.c
+++ b/src/nvim/api/command.c
@@ -13,13 +13,14 @@
#include "nvim/api/private/validate.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/cmdexpand_defs.h"
-#include "nvim/ex_cmds.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/globals.h"
#include "nvim/lua/executor.h"
#include "nvim/macros_defs.h"
@@ -47,16 +48,16 @@
/// @param[out] err Error details, if any.
/// @return Dictionary containing command information, with these keys:
/// - cmd: (string) Command name.
-/// - range: (array) (optional) Command range (|<line1>| |<line2>|).
+/// - range: (array) (optional) Command range ([<line1>] [<line2>]).
/// Omitted if command doesn't accept a range.
/// Otherwise, has no elements if no range was specified, one element if
/// only a single range item was specified, or two elements if both range
/// items were specified.
-/// - count: (number) (optional) Command |<count>|.
+/// - count: (number) (optional) Command [<count>].
/// Omitted if command cannot take a count.
-/// - reg: (string) (optional) Command |<register>|.
+/// - reg: (string) (optional) Command [<register>].
/// Omitted if command cannot take a register.
-/// - bang: (boolean) Whether command contains a |<bang>| (!) modifier.
+/// - bang: (boolean) Whether command contains a [<bang>] (!) modifier.
/// - args: (array) Command arguments.
/// - addr: (string) Value of |:command-addr|. Uses short name or "line" for -addr=lines.
/// - nargs: (string) Value of |:command-nargs|.
@@ -66,7 +67,7 @@
/// - file: (boolean) The command expands filenames. Which means characters such as "%",
/// "#" and wildcards are expanded.
/// - bar: (boolean) The "|" character is treated as a command separator and the double
-/// quote character (\") is treated as the start of a comment.
+/// quote character (") is treated as the start of a comment.
/// - mods: (dictionary) |:command-modifiers|.
/// - filter: (dictionary) |:filter|.
/// - pattern: (string) Filter pattern. Empty string if there is no filter.
@@ -95,19 +96,15 @@
/// - "belowright": |:belowright|.
/// - "topleft": |:topleft|.
/// - "botright": |:botright|.
-Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
+Dict(cmd) nvim_parse_cmd(String str, Dict(empty) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(10) FUNC_API_FAST
{
- Dictionary result = ARRAY_DICT_INIT;
-
- VALIDATE((opts.size == 0), "%s", "opts dict isn't empty", {
- return result;
- });
+ Dict(cmd) result = KEYDICT_INIT;
// Parse command line
exarg_T ea;
CmdParseInfo cmdinfo;
- char *cmdline = string_to_cstr(str);
+ char *cmdline = arena_memdupz(arena, str.data, str.size);
const char *errormsg = NULL;
if (!parse_cmdline(cmdline, &ea, &cmdinfo, &errormsg)) {
@@ -127,22 +124,23 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
// otherwise split arguments by whitespace.
if (ea.argt & EX_NOSPC) {
if (*ea.arg != NUL) {
- ADD(args, STRING_OBJ(cstrn_to_string(ea.arg, length)));
+ args = arena_array(arena, 1);
+ ADD_C(args, STRING_OBJ(cstrn_as_string(ea.arg, length)));
}
} else {
size_t end = 0;
size_t len = 0;
- char *buf = xcalloc(length, sizeof(char));
+ char *buf = arena_alloc(arena, length + 1, false);
bool done = false;
+ args = arena_array(arena, uc_nargs_upper_bound(ea.arg, length));
while (!done) {
done = uc_split_args_iter(ea.arg, length, &end, buf, &len);
if (len > 0) {
- ADD(args, STRING_OBJ(cstrn_to_string(buf, len)));
+ ADD_C(args, STRING_OBJ(cstrn_as_string(buf, len)));
+ buf += len + 1;
}
}
-
- xfree(buf);
}
ucmd_T *cmd = NULL;
@@ -152,40 +150,32 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
cmd = USER_CMD_GA(&curbuf->b_ucmds, ea.useridx);
}
- if (cmd != NULL) {
- PUT(result, "cmd", CSTR_TO_OBJ(cmd->uc_name));
- } else {
- PUT(result, "cmd", CSTR_TO_OBJ(get_command_name(NULL, ea.cmdidx)));
- }
+ char *name = (cmd != NULL ? cmd->uc_name : get_command_name(NULL, ea.cmdidx));
+ PUT_KEY(result, cmd, cmd, cstr_as_string(name));
if (ea.argt & EX_RANGE) {
- Array range = ARRAY_DICT_INIT;
+ Array range = arena_array(arena, 2);
if (ea.addr_count > 0) {
if (ea.addr_count > 1) {
- ADD(range, INTEGER_OBJ(ea.line1));
+ ADD_C(range, INTEGER_OBJ(ea.line1));
}
- ADD(range, INTEGER_OBJ(ea.line2));
+ ADD_C(range, INTEGER_OBJ(ea.line2));
}
- PUT(result, "range", ARRAY_OBJ(range));
+ PUT_KEY(result, cmd, range, range);
}
if (ea.argt & EX_COUNT) {
- if (ea.addr_count > 0) {
- PUT(result, "count", INTEGER_OBJ(ea.line2));
- } else if (cmd != NULL) {
- PUT(result, "count", INTEGER_OBJ(cmd->uc_def));
- } else {
- PUT(result, "count", INTEGER_OBJ(0));
- }
+ Integer count = ea.addr_count > 0 ? ea.line2 : (cmd != NULL ? cmd->uc_def : 0);
+ PUT_KEY(result, cmd, count, count);
}
if (ea.argt & EX_REGSTR) {
char reg[2] = { (char)ea.regname, NUL };
- PUT(result, "reg", CSTR_TO_OBJ(reg));
+ PUT_KEY(result, cmd, reg, CSTR_TO_ARENA_STR(arena, reg));
}
- PUT(result, "bang", BOOLEAN_OBJ(ea.forceit));
- PUT(result, "args", ARRAY_OBJ(args));
+ PUT_KEY(result, cmd, bang, ea.forceit);
+ PUT_KEY(result, cmd, args, args);
char nargs[2];
if (ea.argt & EX_EXTRA) {
@@ -204,9 +194,9 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
nargs[0] = '0';
}
nargs[1] = '\0';
- PUT(result, "nargs", CSTR_TO_OBJ(nargs));
+ PUT_KEY(result, cmd, nargs, CSTR_TO_ARENA_OBJ(arena, nargs));
- const char *addr;
+ char *addr;
switch (ea.addr_type) {
case ADDR_LINES:
addr = "line";
@@ -236,38 +226,37 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
addr = "?";
break;
}
- PUT(result, "addr", CSTR_TO_OBJ(addr));
- PUT(result, "nextcmd", CSTR_TO_OBJ(ea.nextcmd));
-
- Dictionary mods = ARRAY_DICT_INIT;
-
- Dictionary filter = ARRAY_DICT_INIT;
- PUT(filter, "pattern", cmdinfo.cmdmod.cmod_filter_pat
- ? CSTR_TO_OBJ(cmdinfo.cmdmod.cmod_filter_pat)
- : STATIC_CSTR_TO_OBJ(""));
- PUT(filter, "force", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_filter_force));
- PUT(mods, "filter", DICTIONARY_OBJ(filter));
-
- PUT(mods, "silent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_SILENT));
- PUT(mods, "emsg_silent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_ERRSILENT));
- PUT(mods, "unsilent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_UNSILENT));
- PUT(mods, "sandbox", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_SANDBOX));
- PUT(mods, "noautocmd", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOAUTOCMD));
- PUT(mods, "tab", INTEGER_OBJ(cmdinfo.cmdmod.cmod_tab - 1));
- PUT(mods, "verbose", INTEGER_OBJ(cmdinfo.cmdmod.cmod_verbose - 1));
- PUT(mods, "browse", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_BROWSE));
- PUT(mods, "confirm", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_CONFIRM));
- PUT(mods, "hide", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_HIDE));
- PUT(mods, "keepalt", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPALT));
- PUT(mods, "keepjumps", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPJUMPS));
- PUT(mods, "keepmarks", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPMARKS));
- PUT(mods, "keeppatterns", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPPATTERNS));
- PUT(mods, "lockmarks", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_LOCKMARKS));
- PUT(mods, "noswapfile", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOSWAPFILE));
- PUT(mods, "vertical", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_VERT));
- PUT(mods, "horizontal", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_HOR));
-
- const char *split;
+ PUT_KEY(result, cmd, addr, CSTR_AS_OBJ(addr));
+ PUT_KEY(result, cmd, nextcmd, CSTR_AS_OBJ(ea.nextcmd));
+
+ // TODO(bfredl): nested keydict would be nice..
+ Dictionary mods = arena_dict(arena, 20);
+
+ Dictionary filter = arena_dict(arena, 2);
+ PUT_C(filter, "pattern", CSTR_TO_ARENA_OBJ(arena, cmdinfo.cmdmod.cmod_filter_pat));
+ PUT_C(filter, "force", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_filter_force));
+ PUT_C(mods, "filter", DICTIONARY_OBJ(filter));
+
+ PUT_C(mods, "silent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_SILENT));
+ PUT_C(mods, "emsg_silent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_ERRSILENT));
+ PUT_C(mods, "unsilent", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_UNSILENT));
+ PUT_C(mods, "sandbox", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_SANDBOX));
+ PUT_C(mods, "noautocmd", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOAUTOCMD));
+ PUT_C(mods, "tab", INTEGER_OBJ(cmdinfo.cmdmod.cmod_tab - 1));
+ PUT_C(mods, "verbose", INTEGER_OBJ(cmdinfo.cmdmod.cmod_verbose - 1));
+ PUT_C(mods, "browse", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_BROWSE));
+ PUT_C(mods, "confirm", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_CONFIRM));
+ PUT_C(mods, "hide", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_HIDE));
+ PUT_C(mods, "keepalt", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPALT));
+ PUT_C(mods, "keepjumps", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPJUMPS));
+ PUT_C(mods, "keepmarks", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPMARKS));
+ PUT_C(mods, "keeppatterns", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_KEEPPATTERNS));
+ PUT_C(mods, "lockmarks", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_LOCKMARKS));
+ PUT_C(mods, "noswapfile", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_flags & CMOD_NOSWAPFILE));
+ PUT_C(mods, "vertical", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_VERT));
+ PUT_C(mods, "horizontal", BOOLEAN_OBJ(cmdinfo.cmdmod.cmod_split & WSP_HOR));
+
+ char *split;
if (cmdinfo.cmdmod.cmod_split & WSP_BOT) {
split = "botright";
} else if (cmdinfo.cmdmod.cmod_split & WSP_TOP) {
@@ -279,18 +268,17 @@ Dictionary nvim_parse_cmd(String str, Dictionary opts, Error *err)
} else {
split = "";
}
- PUT(mods, "split", CSTR_TO_OBJ(split));
+ PUT_C(mods, "split", CSTR_AS_OBJ(split));
- PUT(result, "mods", DICTIONARY_OBJ(mods));
+ PUT_KEY(result, cmd, mods, mods);
- Dictionary magic = ARRAY_DICT_INIT;
- PUT(magic, "file", BOOLEAN_OBJ(cmdinfo.magic.file));
- PUT(magic, "bar", BOOLEAN_OBJ(cmdinfo.magic.bar));
- PUT(result, "magic", DICTIONARY_OBJ(magic));
+ Dictionary magic = arena_dict(arena, 2);
+ PUT_C(magic, "file", BOOLEAN_OBJ(cmdinfo.magic.file));
+ PUT_C(magic, "bar", BOOLEAN_OBJ(cmdinfo.magic.bar));
+ PUT_KEY(result, cmd, magic, magic);
undo_cmdmod(&cmdinfo.cmdmod);
end:
- xfree(cmdline);
return result;
}
@@ -317,7 +305,7 @@ end:
/// - output: (boolean, default false) Whether to return command output.
/// @param[out] err Error details, if any.
/// @return Command output (non-error, non-shell |:!|) if `output` is true, else empty string.
-String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error *err)
+String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(10)
{
exarg_T ea;
@@ -355,7 +343,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
goto end;
});
- cmdname = string_to_cstr(cmd->cmd);
+ cmdname = arena_string(arena, cmd->cmd).data;
ea.cmd = cmdname;
char *p = find_ex_command(&ea, NULL);
@@ -364,9 +352,8 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
// autocommands defined, trigger the matching autocommands.
if (p != NULL && ea.cmdidx == CMD_SIZE && ASCII_ISUPPER(*ea.cmd)
&& has_event(EVENT_CMDUNDEFINED)) {
- p = xstrdup(cmdname);
+ p = arena_string(arena, cmd->cmd).data;
int ret = apply_autocmds(EVENT_CMDUNDEFINED, p, p, true, NULL);
- xfree(p);
// If the autocommands did something and didn't cause an error, try
// finding the command again.
p = (ret && !aborting()) ? find_ex_command(&ea, NULL) : ea.cmd;
@@ -395,28 +382,31 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
if (HAS_KEY(cmd, cmd, args)) {
// Process all arguments. Convert non-String arguments to String and check if String arguments
// have non-whitespace characters.
+ args = arena_array(arena, cmd->args.size);
for (size_t i = 0; i < cmd->args.size; i++) {
Object elem = cmd->args.items[i];
char *data_str;
switch (elem.type) {
case kObjectTypeBoolean:
- data_str = xcalloc(2, sizeof(char));
+ data_str = arena_alloc(arena, 2, false);
data_str[0] = elem.data.boolean ? '1' : '0';
data_str[1] = '\0';
+ ADD_C(args, CSTR_AS_OBJ(data_str));
break;
case kObjectTypeBuffer:
case kObjectTypeWindow:
case kObjectTypeTabpage:
case kObjectTypeInteger:
- data_str = xcalloc(NUMBUFLEN, sizeof(char));
+ data_str = arena_alloc(arena, NUMBUFLEN, false);
snprintf(data_str, NUMBUFLEN, "%" PRId64, elem.data.integer);
+ ADD_C(args, CSTR_AS_OBJ(data_str));
break;
case kObjectTypeString:
VALIDATE_EXP(!string_iswhite(elem.data.string), "command arg", "non-whitespace", NULL, {
goto end;
});
- data_str = string_to_cstr(elem.data.string);
+ ADD_C(args, elem);
break;
default:
VALIDATE_EXP(false, "command arg", "valid type", api_typename(elem.type), {
@@ -424,8 +414,6 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
});
break;
}
-
- ADD(args, CSTR_AS_OBJ(data_str));
}
bool argc_valid;
@@ -526,7 +514,7 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
VALIDATE_MOD((!ea.forceit || (ea.argt & EX_BANG)), "bang", cmd->cmd.data);
if (HAS_KEY(cmd, cmd, magic)) {
- Dict(cmd_magic) magic[1] = { 0 };
+ Dict(cmd_magic) magic[1] = KEYDICT_INIT;
if (!api_dict_to_keydict(magic, KeyDict_cmd_magic_get_field, cmd->magic, err)) {
goto end;
}
@@ -544,13 +532,13 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
}
if (HAS_KEY(cmd, cmd, mods)) {
- Dict(cmd_mods) mods[1] = { 0 };
+ Dict(cmd_mods) mods[1] = KEYDICT_INIT;
if (!api_dict_to_keydict(mods, KeyDict_cmd_mods_get_field, cmd->mods, err)) {
goto end;
}
if (HAS_KEY(mods, cmd_mods, filter)) {
- Dict(cmd_mods_filter) filter[1] = { 0 };
+ Dict(cmd_mods_filter) filter[1] = KEYDICT_INIT;
if (!api_dict_to_keydict(&filter, KeyDict_cmd_mods_filter_get_field,
mods->filter, err)) {
@@ -678,26 +666,20 @@ String nvim_cmd(uint64_t channel_id, Dict(cmd) *cmd, Dict(cmd_opts) *opts, Error
}
if (opts->output && capture_local.ga_len > 1) {
- retv = (String){
- .data = capture_local.ga_data,
- .size = (size_t)capture_local.ga_len,
- };
+ // TODO(bfredl): if there are more cases like this we might want custom xfree-list in arena
+ retv = CBUF_TO_ARENA_STR(arena, capture_local.ga_data, (size_t)capture_local.ga_len);
// redir usually (except :echon) prepends a newline.
if (retv.data[0] == '\n') {
- memmove(retv.data, retv.data + 1, retv.size - 1);
- retv.data[retv.size - 1] = '\0';
- retv.size = retv.size - 1;
+ retv.data++;
+ retv.size--;
}
- goto end;
}
clear_ga:
if (opts->output) {
ga_clear(&capture_local);
}
end:
- api_free_array(args);
xfree(cmdline);
- xfree(cmdname);
xfree(ea.args);
xfree(ea.arglens);
@@ -871,17 +853,17 @@ static void build_cmdline_str(char **cmdlinep, exarg_T *eap, CmdParseInfo *cmdin
/// from Lua, the command can also be a Lua function. The function is called with a
/// single table argument that contains the following keys:
/// - name: (string) Command name
-/// - args: (string) The args passed to the command, if any |<args>|
+/// - 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>|
+/// 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>|
-/// - range: (number) The number of items in the command range: 0, 1, or 2 |<range>|
-/// - count: (number) Any count supplied |<count>|
-/// - reg: (string) The optional register, if specified |<reg>|
-/// - mods: (string) Command modifiers, if any |<mods>|
+/// - 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>]
+/// - range: (number) The number of items in the command range: 0, 1, or 2 [<range>]
+/// - count: (number) Any count supplied [<count>]
+/// - reg: (string) The optional register, if specified [<reg>]
+/// - mods: (string) Command modifiers, if any [<mods>]
/// - smods: (table) Command modifiers in a structured format. Has the same
/// structure as the "mods" key of |nvim_parse_cmd()|.
/// @param opts Optional |command-attributes|.
@@ -1115,7 +1097,8 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
if (opts->complete.type == kObjectTypeLuaRef) {
context = EXPAND_USER_LUA;
- compl_luaref = api_new_luaref(opts->complete.data.luaref);
+ compl_luaref = opts->complete.data.luaref;
+ opts->complete.data.luaref = LUA_NOREF;
} else if (opts->complete.type == kObjectTypeString) {
VALIDATE_S(OK == parse_compl_arg(opts->complete.data.string.data,
(int)opts->complete.data.string.size, &context, &argt,
@@ -1135,7 +1118,8 @@ void create_user_command(uint64_t channel_id, String name, Object command, Dict(
});
argt |= EX_PREVIEW;
- preview_luaref = api_new_luaref(opts->preview.data.luaref);
+ preview_luaref = opts->preview.data.luaref;
+ opts->preview.data.luaref = LUA_NOREF;
}
switch (command.type) {
@@ -1182,10 +1166,10 @@ err:
/// @param[out] err Error details, if any.
///
/// @returns Map of maps describing commands.
-Dictionary nvim_get_commands(Dict(get_commands) *opts, Error *err)
+Dictionary nvim_get_commands(Dict(get_commands) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
- return nvim_buf_get_commands(-1, opts, err);
+ return nvim_buf_get_commands(-1, opts, arena, err);
}
/// Gets a map of buffer-local |user-commands|.
@@ -1195,7 +1179,7 @@ Dictionary nvim_get_commands(Dict(get_commands) *opts, Error *err)
/// @param[out] err Error details, if any.
///
/// @returns Map of maps describing commands.
-Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Error *err)
+Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
bool global = (buffer == -1);
@@ -1208,12 +1192,12 @@ Dictionary nvim_buf_get_commands(Buffer buffer, Dict(get_commands) *opts, Error
api_set_error(err, kErrorTypeValidation, "builtin=true not implemented");
return (Dictionary)ARRAY_DICT_INIT;
}
- return commands_array(NULL);
+ return commands_array(NULL, arena);
}
buf_T *buf = find_buffer_by_handle(buffer, err);
if (opts->builtin || !buf) {
return (Dictionary)ARRAY_DICT_INIT;
}
- return commands_array(buf);
+ return commands_array(buf, arena);
}
diff --git a/src/nvim/api/deprecated.c b/src/nvim/api/deprecated.c
index 2ec11236d7..6254e9fbd8 100644
--- a/src/nvim/api/deprecated.c
+++ b/src/nvim/api/deprecated.c
@@ -6,22 +6,24 @@
#include "nvim/api/deprecated.h"
#include "nvim/api/extmark.h"
#include "nvim/api/keysets_defs.h"
-#include "nvim/api/options.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
#include "nvim/api/vimscript.h"
#include "nvim/buffer_defs.h"
#include "nvim/decoration.h"
+#include "nvim/decoration_defs.h"
#include "nvim/extmark.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/pos_defs.h"
+#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/deprecated.c.generated.h"
@@ -30,8 +32,8 @@
/// @deprecated Use nvim_exec2() instead.
/// @see nvim_exec2
String nvim_exec(uint64_t channel_id, String src, Boolean output, Error *err)
- FUNC_API_SINCE(7)
- FUNC_API_DEPRECATED_SINCE(11)
+ FUNC_API_SINCE(7) FUNC_API_DEPRECATED_SINCE(11)
+ FUNC_API_RET_ALLOC
{
Dict(exec_opts) opts = { .output = output };
return exec_impl(channel_id, src, &opts, err);
@@ -40,8 +42,8 @@ String nvim_exec(uint64_t channel_id, String src, Boolean output, Error *err)
/// @deprecated
/// @see nvim_exec2
String nvim_command_output(uint64_t channel_id, String command, Error *err)
- FUNC_API_SINCE(1)
- FUNC_API_DEPRECATED_SINCE(7)
+ FUNC_API_SINCE(1) FUNC_API_DEPRECATED_SINCE(7)
+ FUNC_API_RET_ALLOC
{
Dict(exec_opts) opts = { .output = true };
return exec_impl(channel_id, command, &opts, err);
@@ -49,18 +51,17 @@ String nvim_command_output(uint64_t channel_id, String command, Error *err)
/// @deprecated Use nvim_exec_lua() instead.
/// @see nvim_exec_lua
-Object nvim_execute_lua(String code, Array args, Error *err)
+Object nvim_execute_lua(String code, Array args, Arena *arena, Error *err)
FUNC_API_SINCE(3)
FUNC_API_DEPRECATED_SINCE(7)
FUNC_API_REMOTE_ONLY
{
- return nlua_exec(code, args, err);
+ return nlua_exec(code, args, kRetObject, arena, err);
}
/// Gets the buffer number
///
-/// @deprecated The buffer number now is equal to the object id,
-/// so there is no need to use this function.
+/// @deprecated The buffer number now is equal to the object id
///
/// @param buffer Buffer handle, or 0 for current buffer
/// @param[out] err Error details, if any
@@ -98,8 +99,7 @@ void nvim_buf_clear_highlight(Buffer buffer, Integer ns_id, Integer line_start,
/// Set the virtual text (annotation) for a buffer line.
///
-/// @deprecated use nvim_buf_set_extmark to use full virtual text
-/// functionality.
+/// @deprecated use nvim_buf_set_extmark to use full virtual text functionality.
///
/// The text will be placed after the buffer text. Virtual text will never
/// cause reflow, rather virtual text will be truncated at the end of the screen
@@ -117,7 +117,7 @@ void nvim_buf_clear_highlight(Buffer buffer, Integer ns_id, Integer line_start,
/// virtual text, the allocated id is then returned.
///
/// @param buffer Buffer handle, or 0 for current buffer
-/// @param ns_id Namespace to use or 0 to create a namespace,
+/// @param src_id Namespace to use or 0 to create a namespace,
/// or -1 for a ungrouped annotation
/// @param line Line to annotate with virtual text (zero-indexed)
/// @param chunks A list of [text, hl_group] arrays, each representing a
@@ -127,7 +127,7 @@ void nvim_buf_clear_highlight(Buffer buffer, Integer ns_id, Integer line_start,
/// @param[out] err Error details, if any
/// @return The ns_id that was used
Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, Array chunks,
- Dictionary opts, Error *err)
+ Dict(empty) *opts, Error *err)
FUNC_API_SINCE(5)
FUNC_API_DEPRECATED_SINCE(8)
{
@@ -141,11 +141,6 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, A
return 0;
}
- if (opts.size > 0) {
- api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
- return 0;
- }
-
uint32_t ns_id = src2ns(&src_id);
int width;
@@ -172,7 +167,7 @@ Integer nvim_buf_set_virtual_text(Buffer buffer, Integer src_id, Integer line, A
DecorInline decor = { .ext = true, .data.ext.vt = vt, .data.ext.sh_idx = DECOR_ID_INVALID };
extmark_set(buf, ns_id, NULL, (int)line, 0, -1, -1, decor, 0, true,
- false, false, false, NULL);
+ false, false, false, false, NULL);
return src_id;
}
@@ -228,12 +223,12 @@ Dictionary nvim_get_hl_by_name(String name, Boolean rgb, Arena *arena, Error *er
/// the end of the buffer.
/// @param lines Array of lines
/// @param[out] err Error details, if any
-void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Error *err)
+void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
// "lnum" will be the index of the line after inserting,
// no matter if it is negative or not
- nvim_buf_set_lines(0, buffer, lnum, lnum, true, lines, err);
+ nvim_buf_set_lines(0, buffer, lnum, lnum, true, lines, arena, err);
}
/// Gets a buffer line
@@ -248,20 +243,18 @@ void buffer_insert(Buffer buffer, Integer lnum, ArrayOf(String) lines, Error *er
/// @param index Line index
/// @param[out] err Error details, if any
/// @return Line string
-String buffer_get_line(Buffer buffer, Integer index, Error *err)
+String buffer_get_line(Buffer buffer, Integer index, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
String rv = { .size = 0 };
index = convert_index(index);
- Array slice = nvim_buf_get_lines(0, buffer, index, index + 1, true, NULL, err);
+ Array slice = nvim_buf_get_lines(0, buffer, index, index + 1, true, arena, NULL, err);
if (!ERROR_SET(err) && slice.size) {
rv = slice.items[0].data.string;
}
- xfree(slice.items);
-
return rv;
}
@@ -277,13 +270,13 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err)
/// @param index Line index
/// @param line Contents of the new line
/// @param[out] err Error details, if any
-void buffer_set_line(Buffer buffer, Integer index, String line, Error *err)
+void buffer_set_line(Buffer buffer, Integer index, String line, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
Object l = STRING_OBJ(line);
Array array = { .items = &l, .size = 1 };
index = convert_index(index);
- nvim_buf_set_lines(0, buffer, index, index + 1, true, array, err);
+ nvim_buf_set_lines(0, buffer, index, index + 1, true, array, arena, err);
}
/// Deletes a buffer line
@@ -296,12 +289,12 @@ void buffer_set_line(Buffer buffer, Integer index, String line, Error *err)
/// @param buffer buffer handle
/// @param index line index
/// @param[out] err Error details, if any
-void buffer_del_line(Buffer buffer, Integer index, Error *err)
+void buffer_del_line(Buffer buffer, Integer index, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
Array array = ARRAY_DICT_INIT;
index = convert_index(index);
- nvim_buf_set_lines(0, buffer, index, index + 1, true, array, err);
+ nvim_buf_set_lines(0, buffer, index, index + 1, true, array, arena, err);
}
/// Retrieves a line range from the buffer
@@ -322,12 +315,13 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
Integer end,
Boolean include_start,
Boolean include_end,
+ Arena *arena,
Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
start = convert_index(start) + !include_start;
end = convert_index(end) + include_end;
- return nvim_buf_get_lines(0, buffer, start, end, false, NULL, err);
+ return nvim_buf_get_lines(0, buffer, start, end, false, arena, NULL, err);
}
/// Replaces a line range on the buffer
@@ -346,12 +340,13 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
// array will delete the line range)
/// @param[out] err Error details, if any
void buffer_set_line_slice(Buffer buffer, Integer start, Integer end, Boolean include_start,
- Boolean include_end, ArrayOf(String) replacement, Error *err)
+ Boolean include_end, ArrayOf(String) replacement, Arena *arena,
+ Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
start = convert_index(start) + !include_start;
end = convert_index(end) + include_end;
- nvim_buf_set_lines(0, buffer, start, end, false, replacement, err);
+ nvim_buf_set_lines(0, buffer, start, end, false, replacement, arena, err);
}
/// Sets a buffer-scoped (b:) variable
@@ -366,7 +361,7 @@ void buffer_set_line_slice(Buffer buffer, Integer start, Integer end, Boolean in
///
/// @warning It may return nil if there was no previous value
/// or if previous value was `v:null`.
-Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
+Object buffer_set_var(Buffer buffer, String name, Object value, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -375,7 +370,7 @@ Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
return NIL;
}
- return dict_set_var(buf->b_vars, name, value, false, true, err);
+ return dict_set_var(buf->b_vars, name, value, false, true, arena, err);
}
/// Removes a buffer-scoped (b:) variable
@@ -386,7 +381,7 @@ Object buffer_set_var(Buffer buffer, String name, Object value, Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Old value
-Object buffer_del_var(Buffer buffer, String name, Error *err)
+Object buffer_del_var(Buffer buffer, String name, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -395,7 +390,7 @@ Object buffer_del_var(Buffer buffer, String name, Error *err)
return NIL;
}
- return dict_set_var(buf->b_vars, name, NIL, true, true, err);
+ return dict_set_var(buf->b_vars, name, NIL, true, true, arena, err);
}
/// Sets a window-scoped (w:) variable
@@ -410,7 +405,7 @@ Object buffer_del_var(Buffer buffer, String name, Error *err)
///
/// @warning It may return nil if there was no previous value
/// or if previous value was `v:null`.
-Object window_set_var(Window window, String name, Object value, Error *err)
+Object window_set_var(Window window, String name, Object value, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -419,7 +414,7 @@ Object window_set_var(Window window, String name, Object value, Error *err)
return NIL;
}
- return dict_set_var(win->w_vars, name, value, false, true, err);
+ return dict_set_var(win->w_vars, name, value, false, true, arena, err);
}
/// Removes a window-scoped (w:) variable
@@ -430,7 +425,7 @@ Object window_set_var(Window window, String name, Object value, Error *err)
/// @param name variable name
/// @param[out] err Error details, if any
/// @return Old value
-Object window_del_var(Window window, String name, Error *err)
+Object window_del_var(Window window, String name, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -439,7 +434,7 @@ Object window_del_var(Window window, String name, Error *err)
return NIL;
}
- return dict_set_var(win->w_vars, name, NIL, true, true, err);
+ return dict_set_var(win->w_vars, name, NIL, true, true, arena, err);
}
/// Sets a tab-scoped (t:) variable
@@ -454,7 +449,7 @@ Object window_del_var(Window window, String name, Error *err)
///
/// @warning It may return nil if there was no previous value
/// or if previous value was `v:null`.
-Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
+Object tabpage_set_var(Tabpage tabpage, String name, Object value, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -463,7 +458,7 @@ Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
return NIL;
}
- return dict_set_var(tab->tp_vars, name, value, false, true, err);
+ return dict_set_var(tab->tp_vars, name, value, false, true, arena, err);
}
/// Removes a tab-scoped (t:) variable
@@ -474,7 +469,7 @@ Object tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Old value
-Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
+Object tabpage_del_var(Tabpage tabpage, String name, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -483,7 +478,7 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
return NIL;
}
- return dict_set_var(tab->tp_vars, name, NIL, true, true, err);
+ return dict_set_var(tab->tp_vars, name, NIL, true, true, arena, err);
}
/// @deprecated
@@ -491,18 +486,18 @@ Object tabpage_del_var(Tabpage tabpage, String name, Error *err)
/// @warning May return nil if there was no previous value
/// OR if previous value was `v:null`.
/// @return Old value or nil if there was no previous value.
-Object vim_set_var(String name, Object value, Error *err)
+Object vim_set_var(String name, Object value, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
- return dict_set_var(&globvardict, name, value, false, true, err);
+ return dict_set_var(&globvardict, name, value, false, true, arena, err);
}
/// @deprecated
/// @see nvim_del_var
-Object vim_del_var(String name, Error *err)
+Object vim_del_var(String name, Arena *arena, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
- return dict_set_var(&globvardict, name, NIL, true, true, err);
+ return dict_set_var(&globvardict, name, NIL, true, true, arena, err);
}
static int64_t convert_index(int64_t index)
@@ -517,11 +512,11 @@ static int64_t convert_index(int64_t index)
/// @param name Option name
/// @param[out] err Error details, if any
/// @return Option Information
-Dictionary nvim_get_option_info(String name, Error *err)
+Dictionary nvim_get_option_info(String name, Arena *arena, Error *err)
FUNC_API_SINCE(7)
FUNC_API_DEPRECATED_SINCE(11)
{
- return get_vimoption(name, OPT_GLOBAL, curbuf, curwin, err);
+ return get_vimoption(name, OPT_GLOBAL, curbuf, curwin, arena, err);
}
/// Sets the global value of an option.
@@ -544,7 +539,7 @@ void nvim_set_option(uint64_t channel_id, String name, Object value, Error *err)
/// @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)
+Object nvim_get_option(String name, Error *err)
FUNC_API_SINCE(1)
FUNC_API_DEPRECATED_SINCE(11)
{
@@ -558,7 +553,7 @@ Object nvim_get_option(String name, Arena *arena, Error *err)
/// @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)
+Object nvim_buf_get_option(Buffer buffer, String name, Error *err)
FUNC_API_SINCE(1)
FUNC_API_DEPRECATED_SINCE(11)
{
@@ -600,7 +595,7 @@ void nvim_buf_set_option(uint64_t channel_id, Buffer buffer, String name, Object
/// @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)
+Object nvim_win_get_option(Window window, String name, Error *err)
FUNC_API_SINCE(1)
FUNC_API_DEPRECATED_SINCE(11)
{
@@ -649,7 +644,7 @@ static Object get_option_from(void *from, OptReqScope req_scope, String name, Er
return (Object)OBJECT_INIT;
});
- OptVal value = get_option_value_strict(name.data, req_scope, from, err);
+ OptVal value = get_option_value_strict(find_option(name.data), req_scope, from, err);
if (ERROR_SET(err)) {
return (Object)OBJECT_INIT;
}
@@ -675,8 +670,8 @@ static void set_option_to(uint64_t channel_id, void *to, OptReqScope req_scope,
return;
});
- int flags = get_option_attrs(name.data);
- VALIDATE_S(flags != 0, "option name", name.data, {
+ OptIndex opt_idx = find_option(name.data);
+ VALIDATE_S(opt_idx != kOptInvalid, "option name", name.data, {
return;
});
@@ -691,13 +686,14 @@ static void set_option_to(uint64_t channel_id, void *to, OptReqScope req_scope,
return;
});
+ int attrs = get_option_attrs(opt_idx);
// For global-win-local options -> setlocal
// For win-local options -> setglobal and setlocal (opt_flags == 0)
- const int opt_flags = (req_scope == kOptReqWin && !(flags & SOPT_GLOBAL))
+ const int opt_flags = (req_scope == kOptReqWin && !(attrs & SOPT_GLOBAL))
? 0
: (req_scope == kOptReqGlobal) ? OPT_GLOBAL : OPT_LOCAL;
WITH_SCRIPT_CONTEXT(channel_id, {
- set_option_value_for(name.data, optval, opt_flags, req_scope, to, err);
+ set_option_value_for(name.data, opt_idx, optval, opt_flags, req_scope, to, err);
});
}
diff --git a/src/nvim/api/deprecated.h b/src/nvim/api/deprecated.h
index e20d8304e0..c879794bb3 100644
--- a/src/nvim/api/deprecated.h
+++ b/src/nvim/api/deprecated.h
@@ -2,6 +2,7 @@
#include <stdint.h> // IWYU pragma: keep
+#include "nvim/api/keysets_defs.h" // IWYU pragma: keep
#include "nvim/api/private/defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/api/dispatch_deprecated.lua b/src/nvim/api/dispatch_deprecated.lua
index 5650a77ac0..7a92789f79 100644
--- a/src/nvim/api/dispatch_deprecated.lua
+++ b/src/nvim/api/dispatch_deprecated.lua
@@ -1,69 +1,69 @@
local deprecated_aliases = {
- nvim_buf_add_highlight="buffer_add_highlight",
- nvim_buf_clear_highlight="buffer_clear_highlight",
- nvim_buf_get_lines="buffer_get_lines",
- nvim_buf_get_mark="buffer_get_mark",
- nvim_buf_get_name="buffer_get_name",
- nvim_buf_get_number="buffer_get_number",
- nvim_buf_get_option="buffer_get_option",
- nvim_buf_get_var="buffer_get_var",
- nvim_buf_is_valid="buffer_is_valid",
- nvim_buf_line_count="buffer_line_count",
- nvim_buf_set_lines="buffer_set_lines",
- nvim_buf_set_name="buffer_set_name",
- nvim_buf_set_option="buffer_set_option",
- nvim_call_function="vim_call_function",
- nvim_command="vim_command",
- nvim_command_output="vim_command_output",
- nvim_del_current_line="vim_del_current_line",
- nvim_err_write="vim_err_write",
- nvim_err_writeln="vim_report_error",
- nvim_eval="vim_eval",
- nvim_feedkeys="vim_feedkeys",
- nvim_get_api_info="vim_get_api_info",
- nvim_get_color_by_name="vim_name_to_color",
- nvim_get_color_map="vim_get_color_map",
- nvim_get_current_buf="vim_get_current_buffer",
- nvim_get_current_line="vim_get_current_line",
- nvim_get_current_tabpage="vim_get_current_tabpage",
- nvim_get_current_win="vim_get_current_window",
- nvim_get_option="vim_get_option",
- nvim_get_var="vim_get_var",
- nvim_get_vvar="vim_get_vvar",
- nvim_input="vim_input",
- nvim_list_bufs="vim_get_buffers",
- nvim_list_runtime_paths="vim_list_runtime_paths",
- nvim_list_tabpages="vim_get_tabpages",
- nvim_list_wins="vim_get_windows",
- nvim_out_write="vim_out_write",
- nvim_replace_termcodes="vim_replace_termcodes",
- nvim_set_current_buf="vim_set_current_buffer",
- nvim_set_current_dir="vim_change_directory",
- nvim_set_current_line="vim_set_current_line",
- nvim_set_current_tabpage="vim_set_current_tabpage",
- nvim_set_current_win="vim_set_current_window",
- nvim_set_option="vim_set_option",
- nvim_strwidth="vim_strwidth",
- nvim_subscribe="vim_subscribe",
- nvim_tabpage_get_var="tabpage_get_var",
- nvim_tabpage_get_win="tabpage_get_window",
- nvim_tabpage_is_valid="tabpage_is_valid",
- nvim_tabpage_list_wins="tabpage_get_windows",
- nvim_ui_detach="ui_detach",
- nvim_ui_try_resize="ui_try_resize",
- nvim_unsubscribe="vim_unsubscribe",
- nvim_win_get_buf="window_get_buffer",
- nvim_win_get_cursor="window_get_cursor",
- nvim_win_get_height="window_get_height",
- nvim_win_get_option="window_get_option",
- nvim_win_get_position="window_get_position",
- nvim_win_get_tabpage="window_get_tabpage",
- nvim_win_get_var="window_get_var",
- nvim_win_get_width="window_get_width",
- nvim_win_is_valid="window_is_valid",
- nvim_win_set_cursor="window_set_cursor",
- nvim_win_set_height="window_set_height",
- nvim_win_set_option="window_set_option",
- nvim_win_set_width="window_set_width",
+ nvim_buf_add_highlight = 'buffer_add_highlight',
+ nvim_buf_clear_highlight = 'buffer_clear_highlight',
+ nvim_buf_get_lines = 'buffer_get_lines',
+ nvim_buf_get_mark = 'buffer_get_mark',
+ nvim_buf_get_name = 'buffer_get_name',
+ nvim_buf_get_number = 'buffer_get_number',
+ nvim_buf_get_option = 'buffer_get_option',
+ nvim_buf_get_var = 'buffer_get_var',
+ nvim_buf_is_valid = 'buffer_is_valid',
+ nvim_buf_line_count = 'buffer_line_count',
+ nvim_buf_set_lines = 'buffer_set_lines',
+ nvim_buf_set_name = 'buffer_set_name',
+ nvim_buf_set_option = 'buffer_set_option',
+ nvim_call_function = 'vim_call_function',
+ nvim_command = 'vim_command',
+ nvim_command_output = 'vim_command_output',
+ nvim_del_current_line = 'vim_del_current_line',
+ nvim_err_write = 'vim_err_write',
+ nvim_err_writeln = 'vim_report_error',
+ nvim_eval = 'vim_eval',
+ nvim_feedkeys = 'vim_feedkeys',
+ nvim_get_api_info = 'vim_get_api_info',
+ nvim_get_color_by_name = 'vim_name_to_color',
+ nvim_get_color_map = 'vim_get_color_map',
+ nvim_get_current_buf = 'vim_get_current_buffer',
+ nvim_get_current_line = 'vim_get_current_line',
+ nvim_get_current_tabpage = 'vim_get_current_tabpage',
+ nvim_get_current_win = 'vim_get_current_window',
+ nvim_get_option = 'vim_get_option',
+ nvim_get_var = 'vim_get_var',
+ nvim_get_vvar = 'vim_get_vvar',
+ nvim_input = 'vim_input',
+ nvim_list_bufs = 'vim_get_buffers',
+ nvim_list_runtime_paths = 'vim_list_runtime_paths',
+ nvim_list_tabpages = 'vim_get_tabpages',
+ nvim_list_wins = 'vim_get_windows',
+ nvim_out_write = 'vim_out_write',
+ nvim_replace_termcodes = 'vim_replace_termcodes',
+ nvim_set_current_buf = 'vim_set_current_buffer',
+ nvim_set_current_dir = 'vim_change_directory',
+ nvim_set_current_line = 'vim_set_current_line',
+ nvim_set_current_tabpage = 'vim_set_current_tabpage',
+ nvim_set_current_win = 'vim_set_current_window',
+ nvim_set_option = 'vim_set_option',
+ nvim_strwidth = 'vim_strwidth',
+ nvim_subscribe = 'vim_subscribe',
+ nvim_tabpage_get_var = 'tabpage_get_var',
+ nvim_tabpage_get_win = 'tabpage_get_window',
+ nvim_tabpage_is_valid = 'tabpage_is_valid',
+ nvim_tabpage_list_wins = 'tabpage_get_windows',
+ nvim_ui_detach = 'ui_detach',
+ nvim_ui_try_resize = 'ui_try_resize',
+ nvim_unsubscribe = 'vim_unsubscribe',
+ nvim_win_get_buf = 'window_get_buffer',
+ nvim_win_get_cursor = 'window_get_cursor',
+ nvim_win_get_height = 'window_get_height',
+ nvim_win_get_option = 'window_get_option',
+ nvim_win_get_position = 'window_get_position',
+ nvim_win_get_tabpage = 'window_get_tabpage',
+ nvim_win_get_var = 'window_get_var',
+ nvim_win_get_width = 'window_get_width',
+ nvim_win_is_valid = 'window_is_valid',
+ nvim_win_set_cursor = 'window_set_cursor',
+ nvim_win_set_height = 'window_set_height',
+ nvim_win_set_option = 'window_set_option',
+ nvim_win_set_width = 'window_set_width',
}
return deprecated_aliases
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index d71498d6ed..1b03a97edb 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -14,16 +14,19 @@
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/decoration.h"
+#include "nvim/decoration_defs.h"
#include "nvim/decoration_provider.h"
#include "nvim/drawscreen.h"
#include "nvim/extmark.h"
-#include "nvim/func_attr.h"
#include "nvim/grid.h"
#include "nvim/highlight_group.h"
+#include "nvim/map_defs.h"
#include "nvim/marktree.h"
+#include "nvim/marktree_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/move.h"
#include "nvim/pos_defs.h"
#include "nvim/sign.h"
@@ -40,7 +43,7 @@ void api_extmark_free_all_mem(void)
map_destroy(String, &namespace_ids);
}
-/// Creates a new namespace or gets an existing one. \*namespace\*
+/// Creates a new namespace or gets an existing one. [namespace]()
///
/// Namespaces are used for buffer highlights and virtual text, see
/// |nvim_buf_add_highlight()| and |nvim_buf_set_extmark()|.
@@ -69,15 +72,15 @@ Integer nvim_create_namespace(String name)
/// Gets existing, non-anonymous |namespace|s.
///
/// @return dict that maps from names to namespace ids.
-Dictionary nvim_get_namespaces(void)
+Dictionary nvim_get_namespaces(Arena *arena)
FUNC_API_SINCE(5)
{
- Dictionary retval = ARRAY_DICT_INIT;
+ Dictionary retval = arena_dict(arena, map_size(&namespace_ids));
String name;
handle_T id;
map_foreach(&namespace_ids, name, id, {
- PUT(retval, name.data, INTEGER_OBJ(id));
+ PUT_C(retval, name.data, INTEGER_OBJ(id));
})
return retval;
@@ -104,73 +107,85 @@ bool ns_initialized(uint32_t ns)
return ns < (uint32_t)next_namespace_id;
}
-Array virt_text_to_array(VirtText vt, bool hl_name)
+Array virt_text_to_array(VirtText vt, bool hl_name, Arena *arena)
{
- Array chunks = ARRAY_DICT_INIT;
- Array hl_array = ARRAY_DICT_INIT;
+ Array chunks = arena_array(arena, kv_size(vt));
for (size_t i = 0; i < kv_size(vt); i++) {
- char *text = kv_A(vt, i).text;
- int hl_id = kv_A(vt, i).hl_id;
- if (text == NULL) {
+ size_t j = i;
+ for (; j < kv_size(vt); j++) {
+ if (kv_A(vt, j).text != NULL) {
+ break;
+ }
+ }
+
+ Array hl_array = arena_array(arena, i < j ? j - i + 1 : 0);
+ for (; i < j; i++) {
+ int hl_id = kv_A(vt, i).hl_id;
if (hl_id > 0) {
- ADD(hl_array, hl_group_name(hl_id, hl_name));
+ ADD_C(hl_array, hl_group_name(hl_id, hl_name));
}
- continue;
}
- Array chunk = ARRAY_DICT_INIT;
- ADD(chunk, CSTR_TO_OBJ(text));
+
+ char *text = kv_A(vt, i).text;
+ int hl_id = kv_A(vt, i).hl_id;
+ Array chunk = arena_array(arena, 2);
+ ADD_C(chunk, CSTR_AS_OBJ(text));
if (hl_array.size > 0) {
if (hl_id > 0) {
- ADD(hl_array, hl_group_name(hl_id, hl_name));
+ ADD_C(hl_array, hl_group_name(hl_id, hl_name));
}
- ADD(chunk, ARRAY_OBJ(hl_array));
- hl_array = (Array)ARRAY_DICT_INIT;
+ ADD_C(chunk, ARRAY_OBJ(hl_array));
} else if (hl_id > 0) {
- ADD(chunk, hl_group_name(hl_id, hl_name));
+ ADD_C(chunk, hl_group_name(hl_id, hl_name));
}
- ADD(chunks, ARRAY_OBJ(chunk));
+ ADD_C(chunks, ARRAY_OBJ(chunk));
}
- assert(hl_array.size == 0);
return chunks;
}
-static Array extmark_to_array(MTPair extmark, bool id, bool add_dict, bool hl_name)
+static Array extmark_to_array(MTPair extmark, bool id, bool add_dict, bool hl_name, Arena *arena)
{
MTKey start = extmark.start;
- Array rv = ARRAY_DICT_INIT;
+ Array rv = arena_array(arena, 4);
if (id) {
- ADD(rv, INTEGER_OBJ((Integer)start.id));
+ ADD_C(rv, INTEGER_OBJ((Integer)start.id));
}
- ADD(rv, INTEGER_OBJ(start.pos.row));
- ADD(rv, INTEGER_OBJ(start.pos.col));
+ ADD_C(rv, INTEGER_OBJ(start.pos.row));
+ ADD_C(rv, INTEGER_OBJ(start.pos.col));
if (add_dict) {
- Dictionary dict = ARRAY_DICT_INIT;
+ // TODO(bfredl): coding the size like this is a bit fragile.
+ // We want ArrayOf(Dict(set_extmark)) as the return type..
+ Dictionary dict = arena_dict(arena, ARRAY_SIZE(set_extmark_table));
- PUT(dict, "ns_id", INTEGER_OBJ((Integer)start.ns));
+ PUT_C(dict, "ns_id", INTEGER_OBJ((Integer)start.ns));
- PUT(dict, "right_gravity", BOOLEAN_OBJ(mt_right(start)));
+ PUT_C(dict, "right_gravity", BOOLEAN_OBJ(mt_right(start)));
- if (extmark.end_pos.row >= 0) {
- PUT(dict, "end_row", INTEGER_OBJ(extmark.end_pos.row));
- PUT(dict, "end_col", INTEGER_OBJ(extmark.end_pos.col));
- PUT(dict, "end_right_gravity", BOOLEAN_OBJ(extmark.end_right_gravity));
+ if (mt_paired(start)) {
+ PUT_C(dict, "end_row", INTEGER_OBJ(extmark.end_pos.row));
+ PUT_C(dict, "end_col", INTEGER_OBJ(extmark.end_pos.col));
+ PUT_C(dict, "end_right_gravity", BOOLEAN_OBJ(extmark.end_right_gravity));
}
if (mt_no_undo(start)) {
- PUT(dict, "undo_restore", BOOLEAN_OBJ(false));
+ PUT_C(dict, "undo_restore", BOOLEAN_OBJ(false));
}
if (mt_invalidate(start)) {
- PUT(dict, "invalidate", BOOLEAN_OBJ(true));
+ PUT_C(dict, "invalidate", BOOLEAN_OBJ(true));
}
if (mt_invalid(start)) {
- PUT(dict, "invalid", BOOLEAN_OBJ(true));
+ PUT_C(dict, "invalid", BOOLEAN_OBJ(true));
+ }
+
+ if (mt_scoped(start)) {
+ PUT_C(dict, "scoped", BOOLEAN_OBJ(true));
}
- decor_to_dict_legacy(&dict, mt_decor(start), hl_name);
+ decor_to_dict_legacy(&dict, mt_decor(start), hl_name, arena);
- ADD(rv, DICTIONARY_OBJ(dict));
+ ADD_C(rv, DICTIONARY_OBJ(dict));
}
return rv;
@@ -188,8 +203,8 @@ static Array extmark_to_array(MTPair extmark, bool id, bool add_dict, bool hl_na
/// @return 0-indexed (row, col) tuple or empty list () if extmark id was
/// absent
ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
- Integer id, Dictionary opts,
- Error *err)
+ Integer id, Dict(get_extmark) *opts,
+ Arena *arena, Error *err)
FUNC_API_SINCE(7)
{
Array rv = ARRAY_DICT_INIT;
@@ -204,37 +219,19 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
return rv;
});
- bool details = false;
- bool hl_name = true;
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object *v = &opts.items[i].value;
- if (strequal("details", k.data)) {
- details = api_object_to_bool(*v, "details", false, err);
- if (ERROR_SET(err)) {
- return rv;
- }
- } else if (strequal("hl_name", k.data)) {
- hl_name = api_object_to_bool(*v, "hl_name", false, err);
- if (ERROR_SET(err)) {
- return rv;
- }
- } else {
- VALIDATE_S(false, "'opts' key", k.data, {
- return rv;
- });
- }
- }
+ bool details = opts->details;
+
+ bool hl_name = GET_BOOL_OR_TRUE(opts, get_extmark, hl_name);
MTPair extmark = extmark_from_id(buf, (uint32_t)ns_id, (uint32_t)id);
if (extmark.start.pos.row < 0) {
return rv;
}
- return extmark_to_array(extmark, false, details, hl_name);
+ return extmark_to_array(extmark, false, details, hl_name, arena);
}
-/// Gets |extmarks| (including |signs|) in "traversal order" from a |charwise|
-/// region defined by buffer positions (inclusive, 0-indexed |api-indexing|).
+/// Gets |extmarks| in "traversal order" from a |charwise| region defined by
+/// buffer positions (inclusive, 0-indexed |api-indexing|).
///
/// Region can be given as (row,col) tuples, or valid extmark ids (whose
/// positions define the bounds). 0 and -1 are understood as (0,0) and (-1,-1)
@@ -252,6 +249,10 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
/// the `overlap` option might be useful. Otherwise only the start position
/// of an extmark will be considered.
///
+/// Note: legacy signs placed through the |:sign| commands are implemented
+/// as extmarks and will show up here. Their details array will contain a
+/// `sign_name` field.
+///
/// Example:
///
/// ```lua
@@ -283,9 +284,9 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
/// their start position is less than `start`
/// - type: Filter marks by type: "highlight", "sign", "virt_text" and "virt_lines"
/// @param[out] err Error details, if any
-/// @return List of [extmark_id, row, col] tuples in "traversal order".
+/// @return List of `[extmark_id, row, col]` tuples in "traversal order".
Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object end,
- Dict(get_extmarks) *opts, Error *err)
+ Dict(get_extmarks) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(7)
{
Array rv = ARRAY_DICT_INIT;
@@ -349,8 +350,9 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
ExtmarkInfoArray marks = extmark_get(buf, (uint32_t)ns_id, l_row, l_col, u_row,
u_col, (int64_t)limit, reverse, type, opts->overlap);
+ rv = arena_array(arena, kv_size(marks));
for (size_t i = 0; i < kv_size(marks); i++) {
- ADD(rv, ARRAY_OBJ(extmark_to_array(kv_A(marks, i), true, details, hl_name)));
+ ADD_C(rv, ARRAY_OBJ(extmark_to_array(kv_A(marks, i), true, details, hl_name, arena)));
}
kv_destroy(marks);
@@ -388,7 +390,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// of the screen line (just like for diff and
/// cursorline highlight).
/// - virt_text : virtual text to link to this mark.
-/// A list of [text, highlight] tuples, each representing a
+/// A list of `[text, highlight]` tuples, each representing a
/// text chunk with specified highlight. `highlight` element
/// can either be a single highlight group, or an array of
/// multiple highlight groups that will be stacked
@@ -410,6 +412,8 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// text is selected or hidden because of
/// scrolling with 'nowrap' or 'smoothscroll'.
/// Currently only affects "overlay" virt_text.
+/// - virt_text_repeat_linebreak : repeat the virtual text on
+/// wrapped lines.
/// - hl_mode : control how highlights are combined with the
/// highlights of the text. Currently only affects
/// virt_text highlights, but might affect `hl_group`
@@ -421,7 +425,7 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
///
/// - virt_lines : virtual lines to add next to this mark
/// This should be an array over lines, where each line in
-/// turn is an array over [text, highlight] tuples. In
+/// turn is an array over `[text, highlight]` tuples. In
/// general, buffer and window options do not affect the
/// display of the text. In particular 'wrap'
/// and 'linebreak' options do not take effect, so
@@ -450,35 +454,28 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// if text around the mark was deleted and then restored by undo.
/// Defaults to true.
/// - invalidate : boolean that indicates whether to hide the
-/// extmark if the entirety of its range is deleted. If
+/// extmark if the entirety of its range is deleted. For
+/// hidden marks, an "invalid" key is added to the "details"
+/// array of |nvim_buf_get_extmarks()| and family. If
/// "undo_restore" is false, the extmark is deleted instead.
-/// - priority: a priority value for the highlight group or sign
-/// attribute. For example treesitter highlighting uses a
-/// value of 100.
+/// - priority: a priority value for the highlight group, sign
+/// attribute or virtual text. For virtual text, item with
+/// highest priority is drawn last. For example treesitter
+/// highlighting uses a value of 100.
/// - strict: boolean that indicates extmark should not be placed
/// if the line or column value is past the end of the
/// buffer or end of the line respectively. Defaults to true.
/// - sign_text: string of length 1-2 used to display in the
/// sign column.
-/// Note: ranges are unsupported and decorations are only
-/// applied to start_row
/// - sign_hl_group: name of the highlight group used to
/// highlight the sign column text.
-/// Note: ranges are unsupported and decorations are only
-/// applied to start_row
/// - number_hl_group: name of the highlight group used to
/// highlight the number column.
-/// Note: ranges are unsupported and decorations are only
-/// applied to start_row
/// - line_hl_group: name of the highlight group used to
/// highlight the whole line.
-/// Note: ranges are unsupported and decorations are only
-/// applied to start_row
/// - cursorline_hl_group: name of the highlight group used to
-/// highlight the line when the cursor is on the same line
-/// as the mark and 'cursorline' is enabled.
-/// Note: ranges are unsupported and decorations are only
-/// applied to start_row
+/// highlight the sign column text when the cursor is on
+/// the same line as the mark and 'cursorline' is enabled.
/// - conceal: string which should be either empty or a single
/// character. Enable concealing similar to |:syn-conceal|.
/// When a character is supplied it is used as |:syn-cchar|.
@@ -490,6 +487,10 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// by a UI. When set, the UI will receive win_extmark events.
/// Note: the mark is positioned by virt_text attributes. Can be
/// used together with virt_text.
+/// - url: A URL to associate with this extmark. In the TUI, the OSC 8 control
+/// sequence is used to generate a clickable hyperlink to this URL.
+/// - scoped: boolean that indicates that the extmark should only be
+/// displayed in the namespace scope. (experimental)
///
/// @param[out] err Error details, if any
/// @return Id of the created/updated extmark
@@ -503,6 +504,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
DecorSignHighlight sign = DECOR_SIGN_HIGHLIGHT_INIT;
DecorVirtText virt_text = DECOR_VIRT_TEXT_INIT;
DecorVirtText virt_lines = DECOR_VIRT_LINES_INIT;
+ char *url = NULL;
bool has_hl = false;
buf_T *buf = find_buffer_by_handle(buffer, err);
@@ -556,36 +558,15 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
col2 = (int)val;
}
- // uncrustify:off
+ hl.hl_id = (int)opts->hl_group;
+ has_hl = hl.hl_id > 0;
+ sign.hl_id = (int)opts->sign_hl_group;
+ sign.cursorline_hl_id = (int)opts->cursorline_hl_group;
+ sign.number_hl_id = (int)opts->number_hl_group;
+ sign.line_hl_id = (int)opts->line_hl_group;
- // TODO(bfredl): keyset type alias for hl_group? (nil|int|string)
- struct {
- const char *name;
- Object *opt;
- int *dest;
- } hls[] = {
- { "hl_group" , &opts->hl_group , &hl.hl_id },
- { "sign_hl_group" , &opts->sign_hl_group , &sign.hl_id },
- { "number_hl_group" , &opts->number_hl_group , &sign.number_hl_id },
- { "line_hl_group" , &opts->line_hl_group , &sign.line_hl_id },
- { "cursorline_hl_group", &opts->cursorline_hl_group, &sign.cursorline_hl_id },
- { NULL, NULL, NULL },
- };
-
- // uncrustify:on
-
- for (int j = 0; hls[j].name && hls[j].dest; j++) {
- if (hls[j].opt->type != kObjectTypeNil) {
- if (j > 0) {
- sign.flags |= kSHIsSign;
- } else {
- has_hl = true;
- }
- *hls[j].dest = object_to_hl_id(*hls[j].opt, hls[j].name, err);
- if (ERROR_SET(err)) {
- goto error;
- }
- }
+ if (sign.hl_id || sign.cursorline_hl_id || sign.number_hl_id || sign.line_hl_id) {
+ sign.flags |= kSHIsSign;
}
if (HAS_KEY(opts, set_extmark, conceal)) {
@@ -632,7 +613,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
hl.flags |= opts->hl_eol ? kSHHlEol : 0;
- virt_text.flags |= opts->virt_text_hide ? kVTHide : 0;
+ virt_text.flags |= ((opts->virt_text_hide ? kVTHide : 0)
+ | (opts->virt_text_repeat_linebreak ? kVTRepeatLinebreak : 0));
if (HAS_KEY(opts, set_extmark, hl_mode)) {
String str = opts->hl_mode;
@@ -684,9 +666,8 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
if (HAS_KEY(opts, set_extmark, sign_text)) {
- sign.text.ptr = NULL;
- VALIDATE_S(init_sign_text(NULL, &sign.text.ptr, opts->sign_text.data),
- "sign_text", "", {
+ sign.text[0] = 0;
+ VALIDATE_S(init_sign_text(NULL, sign.text, opts->sign_text.data), "sign_text", "", {
goto error;
});
sign.flags |= kSHIsSign;
@@ -708,6 +689,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
has_hl = true;
}
+ if (HAS_KEY(opts, set_extmark, url)) {
+ url = string_to_cstr(opts->url);
+ }
+
if (opts->ui_watched) {
hl.flags |= kSHUIWatched;
if (virt_text.pos == kVPosOverlay) {
@@ -764,6 +749,11 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
if (opts->ephemeral && decor_state.win && decor_state.win->w_buffer == buf) {
+ if (opts->scoped) {
+ api_set_error(err, kErrorTypeException, "not yet implemented");
+ goto error;
+ }
+
int r = (int)line;
int c = (int)col;
if (line2 == -1) {
@@ -771,15 +761,32 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
col2 = c;
}
+ DecorPriority subpriority = DECOR_PRIORITY_BASE;
+ if (HAS_KEY(opts, set_extmark, _subpriority)) {
+ VALIDATE_RANGE((opts->_subpriority >= 0 && opts->_subpriority <= UINT16_MAX),
+ "_subpriority", {
+ goto error;
+ });
+ subpriority = (DecorPriority)opts->_subpriority;
+ }
+
if (kv_size(virt_text.data.virt_text)) {
- decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_text, NULL), true);
+ decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_text, NULL), true,
+ subpriority);
}
if (kv_size(virt_lines.data.virt_lines)) {
- decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_lines, NULL), true);
+ decor_range_add_virt(&decor_state, r, c, line2, col2, decor_put_vt(virt_lines, NULL), true,
+ subpriority);
+ }
+ if (url != NULL) {
+ DecorSignHighlight sh = DECOR_SIGN_HIGHLIGHT_INIT;
+ sh.url = url;
+ decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, 0, 0, subpriority);
}
if (has_hl) {
DecorSignHighlight sh = decor_sh_from_inline(hl);
- decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, (uint32_t)ns_id, id);
+ decor_range_add_sh(&decor_state, r, c, line2, col2, &sh, true, (uint32_t)ns_id, id,
+ subpriority);
}
} else {
if (opts->ephemeral) {
@@ -802,9 +809,16 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
uint32_t decor_indexed = DECOR_ID_INVALID;
+ if (url != NULL) {
+ DecorSignHighlight sh = DECOR_SIGN_HIGHLIGHT_INIT;
+ sh.url = url;
+ sh.next = decor_indexed;
+ decor_indexed = decor_put_sh(sh);
+ }
if (sign.flags & kSHIsSign) {
+ sign.next = decor_indexed;
decor_indexed = decor_put_sh(sign);
- if (sign.text.ptr != NULL) {
+ if (sign.text[0]) {
decor_flags |= MT_FLAG_DECOR_SIGNTEXT;
}
if (sign.number_hl_id || sign.line_hl_id || sign.cursorline_hl_id) {
@@ -832,7 +846,7 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
extmark_set(buf, (uint32_t)ns_id, &id, (int)line, (colnr_T)col, line2, col2,
decor, decor_flags, right_gravity, opts->end_right_gravity,
!GET_BOOL_OR_TRUE(opts, set_extmark, undo_restore),
- opts->invalidate, err);
+ opts->invalidate, opts->scoped, err);
if (ERROR_SET(err)) {
decor_free(decor);
return 0;
@@ -844,6 +858,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
error:
clear_virttext(&virt_text.data.virt_text);
clear_virtlines(&virt_lines.data.virt_lines);
+ if (url != NULL) {
+ xfree(url);
+ }
+
return 0;
}
@@ -954,7 +972,7 @@ Integer nvim_buf_add_highlight(Buffer buffer, Integer ns_id, String hl_group, In
decor.data.hl.hl_id = hl_id;
extmark_set(buf, ns, NULL, (int)line, (colnr_T)col_start, end_line, (colnr_T)col_end,
- decor, MT_FLAG_DECOR_HL, true, false, false, false, NULL);
+ decor, MT_FLAG_DECOR_HL, true, false, false, false, false, NULL);
return ns_id;
}
@@ -1022,19 +1040,27 @@ void nvim_buf_clear_namespace(Buffer buffer, Integer ns_id, Integer line_start,
/// @param ns_id Namespace id from |nvim_create_namespace()|
/// @param opts Table of callbacks:
/// - on_start: called first on each screen redraw
+/// ```
/// ["start", tick]
+/// ```
/// - on_buf: called for each buffer being redrawn (before
-/// window callbacks)
+/// window callbacks)
+/// ```
/// ["buf", bufnr, tick]
-/// - on_win: called when starting to redraw a
-/// specific window. botline_guess is an approximation
-/// that does not exceed the last line number.
-/// ["win", winid, bufnr, topline, botline_guess]
+/// ```
+/// - on_win: called when starting to redraw a specific window.
+/// ```
+/// ["win", winid, bufnr, topline, botline]
+/// ```
/// - on_line: called for each buffer line being redrawn.
/// (The interaction with fold lines is subject to change)
-/// ["win", winid, bufnr, row]
+/// ```
+/// ["line", winid, bufnr, row]
+/// ```
/// - on_end: called at the end of a redraw cycle
+/// ```
/// ["end", tick]
+/// ```
void nvim_set_decoration_provider(Integer ns_id, Dict(set_decoration_provider) *opts, Error *err)
FUNC_API_SINCE(7) FUNC_API_LUA_ONLY
{
@@ -1070,7 +1096,7 @@ void nvim_set_decoration_provider(Integer ns_id, Dict(set_decoration_provider) *
*v = LUA_NOREF;
}
- p->active = true;
+ p->state = kDecorProviderActive;
p->hl_valid++;
p->hl_cached = false;
}
@@ -1189,8 +1215,9 @@ free_exit:
return virt_text;
}
+/// @nodoc
String nvim__buf_debug_extmarks(Buffer buffer, Boolean keys, Boolean dot, Error *err)
- FUNC_API_SINCE(7)
+ FUNC_API_SINCE(7) FUNC_API_RET_ALLOC
{
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
@@ -1199,3 +1226,72 @@ String nvim__buf_debug_extmarks(Buffer buffer, Boolean keys, Boolean dot, Error
return mt_inspect(buf->b_marktree, keys, dot);
}
+
+/// Adds the namespace scope to the window.
+///
+/// @param window Window handle, or 0 for current window
+/// @param ns_id the namespace to add
+/// @return true if the namespace was added, else false
+Boolean nvim_win_add_ns(Window window, Integer ns_id, Error *err)
+ FUNC_API_SINCE(12)
+{
+ win_T *win = find_window_by_handle(window, err);
+ if (!win) {
+ return false;
+ }
+
+ VALIDATE_INT(ns_initialized((uint32_t)ns_id), "ns_id", ns_id, {
+ return false;
+ });
+
+ set_put(uint32_t, &win->w_ns_set, (uint32_t)ns_id);
+
+ changed_window_setting_win(win);
+
+ return true;
+}
+
+/// Gets all the namespaces scopes associated with a window.
+///
+/// @param window Window handle, or 0 for current window
+/// @return a list of namespaces ids
+ArrayOf(Integer) nvim_win_get_ns(Window window, Arena *arena, Error *err)
+ FUNC_API_SINCE(12)
+{
+ win_T *win = find_window_by_handle(window, err);
+ if (!win) {
+ return (Array)ARRAY_DICT_INIT;
+ }
+
+ Array rv = arena_array(arena, set_size(&win->w_ns_set));
+ uint32_t i;
+ set_foreach(&win->w_ns_set, i, {
+ ADD_C(rv, INTEGER_OBJ((Integer)(i)));
+ });
+
+ return rv;
+}
+
+/// Removes the namespace scope from the window.
+///
+/// @param window Window handle, or 0 for current window
+/// @param ns_id the namespace to remove
+/// @return true if the namespace was removed, else false
+Boolean nvim_win_remove_ns(Window window, Integer ns_id, Error *err)
+ FUNC_API_SINCE(12)
+{
+ win_T *win = find_window_by_handle(window, err);
+ if (!win) {
+ return false;
+ }
+
+ if (!set_has(uint32_t, &win->w_ns_set, (uint32_t)ns_id)) {
+ return false;
+ }
+
+ set_del(uint32_t, &win->w_ns_set, (uint32_t)ns_id);
+
+ changed_window_setting_win(win);
+
+ return true;
+}
diff --git a/src/nvim/api/keysets_defs.h b/src/nvim/api/keysets_defs.h
index e59eda5686..fe91d9760d 100644
--- a/src/nvim/api/keysets_defs.h
+++ b/src/nvim/api/keysets_defs.h
@@ -3,6 +3,10 @@
#include "nvim/api/private/defs.h"
typedef struct {
+ OptionalKeys is_set__empty_;
+} Dict(empty);
+
+typedef struct {
OptionalKeys is_set__context_;
Array types;
} Dict(context);
@@ -24,11 +28,12 @@ typedef struct {
Integer end_line;
Integer end_row;
Integer end_col;
- Object hl_group;
+ HLGroupID hl_group;
Array virt_text;
String virt_text_pos;
Integer virt_text_win_col;
Boolean virt_text_hide;
+ Boolean virt_text_repeat_linebreak;
Boolean hl_eol;
String hl_mode;
Boolean invalidate;
@@ -41,17 +46,27 @@ typedef struct {
Boolean virt_lines_leftcol;
Boolean strict;
String sign_text;
- Object sign_hl_group;
- Object number_hl_group;
- Object line_hl_group;
- Object cursorline_hl_group;
+ HLGroupID sign_hl_group;
+ HLGroupID number_hl_group;
+ HLGroupID line_hl_group;
+ HLGroupID cursorline_hl_group;
String conceal;
Boolean spell;
Boolean ui_watched;
Boolean undo_restore;
+ String url;
+ Boolean scoped;
+
+ Integer _subpriority;
} Dict(set_extmark);
typedef struct {
+ OptionalKeys is_set__get_extmark_;
+ Boolean details;
+ Boolean hl_name;
+} Dict(get_extmark);
+
+typedef struct {
OptionalKeys is_set__get_extmarks_;
Integer limit;
Boolean details;
@@ -94,17 +109,19 @@ typedef struct {
} Dict(user_command);
typedef struct {
- OptionalKeys is_set__float_config_;
+ OptionalKeys is_set__win_config_;
Float row;
Float col;
Integer width;
Integer height;
String anchor;
String relative;
+ String split;
Window win;
Array bufpos;
Boolean external;
Boolean focusable;
+ Boolean vertical;
Integer zindex;
Object border;
Object title;
@@ -115,7 +132,7 @@ typedef struct {
Boolean noautocmd;
Boolean fixed;
Boolean hide;
-} Dict(float_config);
+} Dict(win_config);
typedef struct {
Boolean is_lua;
@@ -172,6 +189,7 @@ typedef struct {
Boolean fg_indexed;
Boolean bg_indexed;
Boolean force;
+ String url;
} Dict(highlight);
typedef struct {
@@ -313,3 +331,47 @@ typedef struct {
typedef struct {
Boolean output;
} Dict(exec_opts);
+
+typedef struct {
+ OptionalKeys is_set__buf_attach_;
+ LuaRef on_lines;
+ LuaRef on_bytes;
+ LuaRef on_changedtick;
+ LuaRef on_detach;
+ LuaRef on_reload;
+ Boolean utf_sizes;
+ Boolean preview;
+} Dict(buf_attach);
+
+typedef struct {
+ OptionalKeys is_set__buf_delete_;
+ Boolean force;
+ Boolean unload;
+} Dict(buf_delete);
+
+typedef struct {
+ OptionalKeys is_set__open_term_;
+ LuaRef on_input;
+ Boolean force_crlf;
+} Dict(open_term);
+
+typedef struct {
+ OptionalKeys is_set__complete_set_;
+ String info;
+} Dict(complete_set);
+
+typedef struct {
+ OptionalKeys is_set__xdl_diff_;
+ LuaRef on_hunk;
+ String result_type;
+ String algorithm;
+ Integer ctxlen;
+ Integer interhunkctxlen;
+ Object linematch;
+ Boolean ignore_whitespace;
+ Boolean ignore_whitespace_change;
+ Boolean ignore_whitespace_change_at_eol;
+ Boolean ignore_cr_at_eol;
+ Boolean ignore_blank_lines;
+ Boolean indent_heuristic;
+} Dict(xdl_diff);
diff --git a/src/nvim/api/options.c b/src/nvim/api/options.c
index c012a69c7b..d9bc0ccc92 100644
--- a/src/nvim/api/options.c
+++ b/src/nvim/api/options.c
@@ -9,24 +9,22 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
-#include "nvim/eval/window.h"
-#include "nvim/func_attr.h"
+#include "nvim/buffer_defs.h"
#include "nvim/globals.h"
-#include "nvim/macros_defs.h"
#include "nvim/memory.h"
#include "nvim/option.h"
-#include "nvim/option_vars.h"
+#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
-#include "nvim/window.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/options.c.generated.h"
#endif
-static int validate_option_value_args(Dict(option) *opts, char *name, int *scope,
- OptReqScope *req_scope, void **from, char **filetype,
- Error *err)
+static int validate_option_value_args(Dict(option) *opts, char *name, OptIndex *opt_idxp,
+ int *scope, OptReqScope *req_scope, void **from,
+ char **filetype, Error *err)
{
#define HAS_KEY_X(d, v) HAS_KEY(d, option, v)
if (HAS_KEY_X(opts, scope)) {
@@ -80,7 +78,8 @@ static int validate_option_value_args(Dict(option) *opts, char *name, int *scope
return FAIL;
});
- int flags = get_option_attrs(name);
+ *opt_idxp = find_option(name);
+ int flags = get_option_attrs(*opt_idxp);
if (flags == 0) {
// hidden or unknown option
api_set_error(err, kErrorTypeValidation, "Unknown option '%s'", name);
@@ -120,10 +119,10 @@ static buf_T *do_ft_buf(char *filetype, aco_save_T *aco, Error *err)
aucmd_prepbuf(aco, ftbuf);
TRY_WRAP(err, {
- set_option_value("bufhidden", STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL);
- set_option_value("buftype", STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL);
- set_option_value("swapfile", BOOLEAN_OPTVAL(false), OPT_LOCAL);
- set_option_value("modeline", BOOLEAN_OPTVAL(false), OPT_LOCAL); // 'nomodeline'
+ set_option_value(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL);
+ set_option_value(kOptBuftype, STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL);
+ set_option_value(kOptSwapfile, BOOLEAN_OPTVAL(false), OPT_LOCAL);
+ set_option_value(kOptModeline, BOOLEAN_OPTVAL(false), OPT_LOCAL); // 'nomodeline'
ftbuf->b_p_ft = xstrdup(filetype);
do_filetype_autocmd(ftbuf, false);
@@ -151,25 +150,24 @@ static buf_T *do_ft_buf(char *filetype, aco_save_T *aco, Error *err)
/// @param[out] err Error details, if any
/// @return Option value
Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
- FUNC_API_SINCE(9)
+ FUNC_API_SINCE(9) FUNC_API_RET_ALLOC
{
- Object rv = OBJECT_INIT;
- OptVal value = NIL_OPTVAL;
-
+ OptIndex opt_idx = 0;
int scope = 0;
OptReqScope req_scope = kOptReqGlobal;
void *from = NULL;
char *filetype = NULL;
- if (!validate_option_value_args(opts, name.data, &scope, &req_scope, &from, &filetype, err)) {
- goto err;
+ if (!validate_option_value_args(opts, name.data, &opt_idx, &scope, &req_scope, &from, &filetype,
+ err)) {
+ return (Object)OBJECT_INIT;
}
aco_save_T aco;
buf_T *ftbuf = do_ft_buf(filetype, &aco, err);
if (ERROR_SET(err)) {
- goto err;
+ return (Object)OBJECT_INIT;
}
if (ftbuf != NULL) {
@@ -177,8 +175,8 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
from = ftbuf;
}
- bool hidden;
- value = get_option_value_for(name.data, NULL, scope, &hidden, req_scope, from, err);
+ OptVal value = get_option_value_for(opt_idx, scope, req_scope, from, err);
+ bool hidden = is_option_hidden(opt_idx);
if (ftbuf != NULL) {
// restore curwin/curbuf and a few other things
@@ -199,7 +197,7 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err)
return optval_as_object(value);
err:
optval_free(value);
- return rv;
+ return (Object)OBJECT_INIT;
}
/// Sets the value of an option. The behavior of this function matches that of
@@ -220,10 +218,11 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict(
Error *err)
FUNC_API_SINCE(9)
{
+ OptIndex opt_idx = 0;
int scope = 0;
OptReqScope req_scope = kOptReqGlobal;
void *to = NULL;
- if (!validate_option_value_args(opts, name.data, &scope, &req_scope, &to, NULL, err)) {
+ if (!validate_option_value_args(opts, name.data, &opt_idx, &scope, &req_scope, &to, NULL, err)) {
return;
}
@@ -234,7 +233,7 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict(
//
// Then force scope to local since we don't want to change the global option
if (req_scope == kOptReqWin && scope == 0) {
- int flags = get_option_attrs(name.data);
+ int flags = get_option_attrs(opt_idx);
if (flags & SOPT_GLOBAL) {
scope = OPT_LOCAL;
}
@@ -252,7 +251,7 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict(
});
WITH_SCRIPT_CONTEXT(channel_id, {
- set_option_value_for(name.data, optval, scope, req_scope, to, err);
+ set_option_value_for(name.data, opt_idx, optval, scope, req_scope, to, err);
});
}
@@ -264,30 +263,30 @@ void nvim_set_option_value(uint64_t channel_id, String name, Object value, Dict(
/// @see |nvim_get_commands()|
///
/// @return dictionary of all options
-Dictionary nvim_get_all_options_info(Error *err)
+Dictionary nvim_get_all_options_info(Arena *arena, Error *err)
FUNC_API_SINCE(7)
{
- return get_all_vimoptions();
+ return get_all_vimoptions(arena);
}
/// Gets the option information for one option from arbitrary buffer or window
///
/// Resulting dictionary has keys:
-/// - name: Name of the option (like 'filetype')
-/// - shortname: Shortened name of the option (like 'ft')
-/// - type: type of option ("string", "number" or "boolean")
-/// - default: The default value for the option
-/// - was_set: Whether the option was set.
+/// - name: Name of the option (like 'filetype')
+/// - shortname: Shortened name of the option (like 'ft')
+/// - type: type of option ("string", "number" or "boolean")
+/// - default: The default value for the option
+/// - was_set: Whether the option was set.
///
-/// - last_set_sid: Last set script id (if any)
-/// - last_set_linenr: line number where option was set
-/// - last_set_chan: Channel where option was set (0 for local)
+/// - last_set_sid: Last set script id (if any)
+/// - last_set_linenr: line number where option was set
+/// - last_set_chan: Channel where option was set (0 for local)
///
-/// - scope: one of "global", "win", or "buf"
-/// - global_local: whether win or buf option has a global value
+/// - scope: one of "global", "win", or "buf"
+/// - global_local: whether win or buf option has a global value
///
-/// - commalist: List of comma separated values
-/// - flaglist: List of single char flags
+/// - commalist: List of comma separated values
+/// - flaglist: List of single char flags
///
/// When {scope} is not provided, the last set information applies to the local
/// value in the current buffer or window if it is available, otherwise the
@@ -303,275 +302,20 @@ Dictionary nvim_get_all_options_info(Error *err)
/// Implies {scope} is "local".
/// @param[out] err Error details, if any
/// @return Option Information
-Dictionary nvim_get_option_info2(String name, Dict(option) *opts, Error *err)
+Dictionary nvim_get_option_info2(String name, Dict(option) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(11)
{
+ OptIndex opt_idx = 0;
int scope = 0;
OptReqScope req_scope = kOptReqGlobal;
void *from = NULL;
- if (!validate_option_value_args(opts, name.data, &scope, &req_scope, &from, NULL, err)) {
+ if (!validate_option_value_args(opts, name.data, &opt_idx, &scope, &req_scope, &from, NULL,
+ err)) {
return (Dictionary)ARRAY_DICT_INIT;
}
buf_T *buf = (req_scope == kOptReqBuf) ? (buf_T *)from : curbuf;
win_T *win = (req_scope == kOptReqWin) ? (win_T *)from : curwin;
- return get_vimoption(name, scope, buf, win, err);
-}
-
-/// Switch current context to get/set option value for window/buffer.
-///
-/// @param[out] ctx Current context. switchwin_T for window and aco_save_T for buffer.
-/// @param req_scope Requested option scope. See OptReqScope in option.h.
-/// @param[in] from Target buffer/window.
-/// @param[out] err Error message, if any.
-///
-/// @return true if context was switched, false otherwise.
-static bool switch_option_context(void *const ctx, OptReqScope req_scope, void *const from,
- Error *err)
-{
- switch (req_scope) {
- case kOptReqWin: {
- win_T *const win = (win_T *)from;
- switchwin_T *const switchwin = (switchwin_T *)ctx;
-
- if (win == curwin) {
- return false;
- }
-
- if (switch_win_noblock(switchwin, win, win_find_tabpage(win), true)
- == FAIL) {
- restore_win_noblock(switchwin, true);
-
- if (try_end(err)) {
- return false;
- }
- api_set_error(err, kErrorTypeException, "Problem while switching windows");
- return false;
- }
- return true;
- }
- case kOptReqBuf: {
- buf_T *const buf = (buf_T *)from;
- aco_save_T *const aco = (aco_save_T *)ctx;
-
- if (buf == curbuf) {
- return false;
- }
- aucmd_prepbuf(aco, buf);
- return true;
- }
- case kOptReqGlobal:
- return false;
- }
- UNREACHABLE;
-}
-
-/// Restore context after getting/setting option for window/buffer. See switch_option_context() for
-/// params.
-static void restore_option_context(void *const ctx, OptReqScope req_scope)
-{
- switch (req_scope) {
- case kOptReqWin:
- restore_win_noblock((switchwin_T *)ctx, true);
- break;
- case kOptReqBuf:
- aucmd_restbuf((aco_save_T *)ctx);
- break;
- case kOptReqGlobal:
- break;
- }
-}
-
-/// Get attributes for an option.
-///
-/// @param name Option name.
-///
-/// @return Option attributes.
-/// 0 for hidden or unknown option.
-/// See SOPT_* in option_defs.h for other flags.
-int get_option_attrs(char *name)
-{
- int opt_idx = findoption(name);
-
- if (opt_idx < 0) {
- return 0;
- }
-
- vimoption_T *opt = get_option(opt_idx);
-
- if (is_tty_option(opt->fullname)) {
- return SOPT_STRING | SOPT_GLOBAL;
- }
-
- // Hidden option
- if (opt->var == NULL) {
- return 0;
- }
-
- int attrs = 0;
-
- if (opt->flags & P_BOOL) {
- attrs |= SOPT_BOOL;
- } else if (opt->flags & P_NUM) {
- attrs |= SOPT_NUM;
- } else if (opt->flags & P_STRING) {
- attrs |= SOPT_STRING;
- }
-
- if (opt->indir == PV_NONE || (opt->indir & PV_BOTH)) {
- attrs |= SOPT_GLOBAL;
- }
- if (opt->indir & PV_WIN) {
- attrs |= SOPT_WIN;
- } else if (opt->indir & PV_BUF) {
- attrs |= SOPT_BUF;
- }
-
- return attrs;
-}
-
-/// Check if option has a value in the requested scope.
-///
-/// @param name Option name.
-/// @param req_scope Requested option scope. See OptReqScope in option.h.
-///
-/// @return true if option has a value in the requested scope, false otherwise.
-static bool option_has_scope(char *name, OptReqScope req_scope)
-{
- int opt_idx = findoption(name);
-
- if (opt_idx < 0) {
- return false;
- }
-
- vimoption_T *opt = get_option(opt_idx);
-
- // Hidden option.
- if (opt->var == NULL) {
- return false;
- }
- // TTY option.
- if (is_tty_option(opt->fullname)) {
- return req_scope == kOptReqGlobal;
- }
-
- switch (req_scope) {
- case kOptReqGlobal:
- return opt->var != VAR_WIN;
- case kOptReqBuf:
- return opt->indir & PV_BUF;
- case kOptReqWin:
- return opt->indir & PV_WIN;
- }
- UNREACHABLE;
-}
-
-/// Get the option value in the requested scope.
-///
-/// @param name Option name.
-/// @param req_scope Requested option scope. See OptReqScope in option.h.
-/// @param[in] from Pointer to buffer or window for local option value.
-/// @param[out] err Error message, if any.
-///
-/// @return Option value in the requested scope. Returns a Nil option value if option is not found,
-/// hidden or if it isn't present in the requested scope. (i.e. has no global, window-local or
-/// buffer-local value depending on opt_scope).
-OptVal get_option_value_strict(char *name, OptReqScope req_scope, void *from, Error *err)
-{
- OptVal retv = NIL_OPTVAL;
-
- if (!option_has_scope(name, req_scope)) {
- return retv;
- }
- if (get_tty_option(name, &retv.data.string.data)) {
- retv.type = kOptValTypeString;
- return retv;
- }
-
- int opt_idx = findoption(name);
- assert(opt_idx != 0); // option_has_scope() already verifies if option name is valid.
-
- vimoption_T *opt = get_option(opt_idx);
- switchwin_T switchwin;
- aco_save_T aco;
- void *ctx = req_scope == kOptReqWin ? (void *)&switchwin
- : (req_scope == kOptReqBuf ? (void *)&aco : NULL);
- bool switched = switch_option_context(ctx, req_scope, from, err);
- if (ERROR_SET(err)) {
- return retv;
- }
-
- char *varp = get_varp_scope(opt, req_scope == kOptReqGlobal ? OPT_GLOBAL : OPT_LOCAL);
- retv = optval_from_varp(opt_idx, varp);
-
- if (switched) {
- restore_option_context(ctx, req_scope);
- }
-
- return retv;
-}
-
-/// Get option value for buffer / window.
-///
-/// @param[in] name Option name.
-/// @param[out] flagsp Set to the option flags (P_xxxx) (if not NULL).
-/// @param[in] scope Option scope (can be OPT_LOCAL, OPT_GLOBAL or a combination).
-/// @param[out] hidden Whether option is hidden.
-/// @param req_scope Requested option scope. See OptReqScope in option.h.
-/// @param[in] from Target buffer/window.
-/// @param[out] err Error message, if any.
-///
-/// @return Option value. Must be freed by caller.
-OptVal get_option_value_for(const char *const name, uint32_t *flagsp, int scope, bool *hidden,
- const OptReqScope req_scope, void *const from, Error *err)
-{
- switchwin_T switchwin;
- aco_save_T aco;
- void *ctx = req_scope == kOptReqWin ? (void *)&switchwin
- : (req_scope == kOptReqBuf ? (void *)&aco : NULL);
-
- bool switched = switch_option_context(ctx, req_scope, from, err);
- if (ERROR_SET(err)) {
- return NIL_OPTVAL;
- }
-
- OptVal retv = get_option_value(name, flagsp, scope, hidden);
-
- if (switched) {
- restore_option_context(ctx, req_scope);
- }
-
- return retv;
-}
-
-/// Set option value for buffer / window.
-///
-/// @param[in] name Option name.
-/// @param[in] value Option value.
-/// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both).
-/// @param req_scope Requested option scope. See OptReqScope in option.h.
-/// @param[in] from Target buffer/window.
-/// @param[out] err Error message, if any.
-void set_option_value_for(const char *const name, OptVal value, const int opt_flags,
- const OptReqScope req_scope, void *const from, Error *err)
-{
- switchwin_T switchwin;
- aco_save_T aco;
- void *ctx = req_scope == kOptReqWin ? (void *)&switchwin
- : (req_scope == kOptReqBuf ? (void *)&aco : NULL);
-
- bool switched = switch_option_context(ctx, req_scope, from, err);
- if (ERROR_SET(err)) {
- return;
- }
-
- const char *const errmsg = set_option_value(name, value, opt_flags);
- if (errmsg) {
- api_set_error(err, kErrorTypeException, "%s", errmsg);
- }
-
- if (switched) {
- restore_option_context(ctx, req_scope);
- }
+ return get_vimoption(name, scope, buf, win, arena, err);
}
diff --git a/src/nvim/api/private/converter.c b/src/nvim/api/private/converter.c
index 90023171e5..a70ef1e50b 100644
--- a/src/nvim/api/private/converter.c
+++ b/src/nvim/api/private/converter.c
@@ -11,7 +11,6 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
-#include "nvim/func_attr.h"
#include "nvim/lua/executor.h"
#include "nvim/memory.h"
#include "nvim/types_defs.h"
@@ -20,6 +19,8 @@
/// Helper structure for vim_to_object
typedef struct {
kvec_withinit_t(Object, 2) stack; ///< Object stack.
+ Arena *arena; ///< arena where objects will be allocated
+ bool reuse_strdata;
} EncodedData;
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -42,12 +43,21 @@ typedef struct {
#define TYPVAL_ENCODE_CONV_FLOAT(tv, flt) \
kvi_push(edata->stack, FLOAT_OBJ((Float)(flt)))
+static Object typval_cbuf_to_obj(EncodedData *edata, const char *data, size_t len)
+{
+ if (edata->reuse_strdata) {
+ return STRING_OBJ(cbuf_as_string((char *)(len ? data : ""), len));
+ } else {
+ return CBUF_TO_ARENA_OBJ(edata->arena, data, len);
+ }
+}
+
#define TYPVAL_ENCODE_CONV_STRING(tv, str, len) \
do { \
const size_t len_ = (size_t)(len); \
const char *const str_ = (str); \
assert(len_ == 0 || str_ != NULL); \
- kvi_push(edata->stack, STRING_OBJ(cbuf_to_string((len_ ? str_ : ""), len_))); \
+ kvi_push(edata->stack, typval_cbuf_to_obj(edata, str_, len_)); \
} while (0)
#define TYPVAL_ENCODE_CONV_STR_STRING TYPVAL_ENCODE_CONV_STRING
@@ -59,10 +69,7 @@ typedef struct {
do { \
const size_t len_ = (size_t)(len); \
const blob_T *const blob_ = (blob); \
- kvi_push(edata->stack, STRING_OBJ(((String) { \
- .data = len_ != 0 ? xmemdupz(blob_->bv_ga.ga_data, len_) : xstrdup(""), \
- .size = len_ \
- }))); \
+ kvi_push(edata->stack, typval_cbuf_to_obj(edata, len_ ? blob_->bv_ga.ga_data : "", len_)); \
} while (0)
#define TYPVAL_ENCODE_CONV_FUNC_START(tv, fun) \
@@ -91,11 +98,7 @@ typedef struct {
static inline void typval_encode_list_start(EncodedData *const edata, const size_t len)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
{
- kvi_push(edata->stack, ARRAY_OBJ(((Array) {
- .capacity = len,
- .size = 0,
- .items = xmalloc(len * sizeof(*((Object)OBJECT_INIT).data.array.items)),
- })));
+ kvi_push(edata->stack, ARRAY_OBJ(arena_array(edata->arena, len)));
}
#define TYPVAL_ENCODE_CONV_LIST_START(tv, len) \
@@ -110,7 +113,7 @@ static inline void typval_encode_between_list_items(EncodedData *const edata)
Object *const list = &kv_last(edata->stack);
assert(list->type == kObjectTypeArray);
assert(list->data.array.size < list->data.array.capacity);
- list->data.array.items[list->data.array.size++] = item;
+ ADD_C(list->data.array, item);
}
#define TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS(tv) \
@@ -132,11 +135,7 @@ static inline void typval_encode_list_end(EncodedData *const edata)
static inline void typval_encode_dict_start(EncodedData *const edata, const size_t len)
FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL
{
- kvi_push(edata->stack, DICTIONARY_OBJ(((Dictionary) {
- .capacity = len,
- .size = 0,
- .items = xmalloc(len * sizeof(*((Object)OBJECT_INIT).data.dictionary.items)),
- })));
+ kvi_push(edata->stack, DICTIONARY_OBJ(arena_dict(edata->arena, len)));
}
#define TYPVAL_ENCODE_CONV_DICT_START(tv, dict, len) \
@@ -157,9 +156,8 @@ static inline void typval_encode_after_key(EncodedData *const edata)
dict->data.dictionary.items[dict->data.dictionary.size].key
= key.data.string;
} else {
- api_free_object(key);
dict->data.dictionary.items[dict->data.dictionary.size].key
- = STATIC_CSTR_TO_STRING("__INVALID_KEY__");
+ = STATIC_CSTR_AS_STRING("__INVALID_KEY__");
}
}
@@ -234,17 +232,22 @@ static inline void typval_encode_dict_end(EncodedData *const edata)
#undef TYPVAL_ENCODE_CONV_RECURSE
#undef TYPVAL_ENCODE_ALLOW_SPECIALS
-/// Convert a vim object to an `Object` instance, recursively expanding
+/// Convert a vim object to an `Object` instance, recursively converting
/// Arrays/Dictionaries.
///
/// @param obj The source object
+/// @param arena if NULL, use direct allocation
+/// @param reuse_strdata when true, don't copy string data to Arena but reference
+/// typval strings directly. takes no effect when arena is
+/// NULL
/// @return The converted value
-Object vim_to_object(typval_T *obj)
+Object vim_to_object(typval_T *obj, Arena *arena, bool reuse_strdata)
{
EncodedData edata;
kvi_init(edata.stack);
- const int evo_ret = encode_vim_to_object(&edata, obj,
- "vim_to_object argument");
+ edata.arena = arena;
+ edata.reuse_strdata = reuse_strdata;
+ const int evo_ret = encode_vim_to_object(&edata, obj, "vim_to_object argument");
(void)evo_ret;
assert(evo_ret == OK);
Object ret = kv_A(edata.stack, 0);
@@ -259,14 +262,20 @@ Object vim_to_object(typval_T *obj)
/// @param tv Conversion result is placed here. On failure member v_type is
/// set to VAR_UNKNOWN (no allocation was made for this variable).
/// @param err Error object.
+void object_to_vim(Object obj, typval_T *tv, Error *err)
+{
+ object_to_vim_take_luaref(&obj, tv, false, err);
+}
+
+/// same as object_to_vim but consumes all luarefs (nested) in `obj`
///
-/// @returns true if conversion is successful, otherwise false.
-bool object_to_vim(Object obj, typval_T *tv, Error *err)
+/// useful when `obj` is allocated on an arena
+void object_to_vim_take_luaref(Object *obj, typval_T *tv, bool take_luaref, Error *err)
{
tv->v_type = VAR_UNKNOWN;
tv->v_lock = VAR_UNLOCKED;
- switch (obj.type) {
+ switch (obj->type) {
case kObjectTypeNil:
tv->v_type = VAR_SPECIAL;
tv->vval.v_special = kSpecialVarNull;
@@ -274,46 +283,40 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
case kObjectTypeBoolean:
tv->v_type = VAR_BOOL;
- tv->vval.v_bool = obj.data.boolean ? kBoolVarTrue : kBoolVarFalse;
+ tv->vval.v_bool = obj->data.boolean ? kBoolVarTrue : kBoolVarFalse;
break;
case kObjectTypeBuffer:
case kObjectTypeWindow:
case kObjectTypeTabpage:
case kObjectTypeInteger:
- STATIC_ASSERT(sizeof(obj.data.integer) <= sizeof(varnumber_T),
+ STATIC_ASSERT(sizeof(obj->data.integer) <= sizeof(varnumber_T),
"Integer size must be <= Vimscript number size");
tv->v_type = VAR_NUMBER;
- tv->vval.v_number = (varnumber_T)obj.data.integer;
+ tv->vval.v_number = (varnumber_T)obj->data.integer;
break;
case kObjectTypeFloat:
tv->v_type = VAR_FLOAT;
- tv->vval.v_float = obj.data.floating;
+ tv->vval.v_float = obj->data.floating;
break;
case kObjectTypeString:
tv->v_type = VAR_STRING;
- if (obj.data.string.data == NULL) {
+ if (obj->data.string.data == NULL) {
tv->vval.v_string = NULL;
} else {
- tv->vval.v_string = xmemdupz(obj.data.string.data,
- obj.data.string.size);
+ tv->vval.v_string = xmemdupz(obj->data.string.data,
+ obj->data.string.size);
}
break;
case kObjectTypeArray: {
- list_T *const list = tv_list_alloc((ptrdiff_t)obj.data.array.size);
+ list_T *const list = tv_list_alloc((ptrdiff_t)obj->data.array.size);
- for (uint32_t i = 0; i < obj.data.array.size; i++) {
- Object item = obj.data.array.items[i];
+ for (uint32_t i = 0; i < obj->data.array.size; i++) {
typval_T li_tv;
-
- if (!object_to_vim(item, &li_tv, err)) {
- tv_list_free(list);
- return false;
- }
-
+ object_to_vim_take_luaref(&obj->data.array.items[i], &li_tv, take_luaref, err);
tv_list_append_owned_tv(list, li_tv);
}
tv_list_ref(list);
@@ -326,27 +329,11 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
case kObjectTypeDictionary: {
dict_T *const dict = tv_dict_alloc();
- for (uint32_t i = 0; i < obj.data.dictionary.size; i++) {
- KeyValuePair item = obj.data.dictionary.items[i];
- String key = item.key;
-
- if (key.size == 0) {
- api_set_error(err, kErrorTypeValidation,
- "Empty dictionary keys aren't allowed");
- // cleanup
- tv_dict_free(dict);
- return false;
- }
-
+ for (uint32_t i = 0; i < obj->data.dictionary.size; i++) {
+ KeyValuePair *item = &obj->data.dictionary.items[i];
+ String key = item->key;
dictitem_T *const di = tv_dict_item_alloc(key.data);
-
- if (!object_to_vim(item.value, &di->di_tv, err)) {
- // cleanup
- tv_dict_item_free(di);
- tv_dict_free(dict);
- return false;
- }
-
+ object_to_vim_take_luaref(&item->value, &di->di_tv, take_luaref, err);
tv_dict_add(dict, di);
}
dict->dv_refcount++;
@@ -357,12 +344,16 @@ bool object_to_vim(Object obj, typval_T *tv, Error *err)
}
case kObjectTypeLuaRef: {
- char *name = register_luafunc(api_new_luaref(obj.data.luaref));
+ LuaRef ref = obj->data.luaref;
+ if (take_luaref) {
+ obj->data.luaref = LUA_NOREF;
+ } else {
+ ref = api_new_luaref(ref);
+ }
+ char *name = register_luafunc(ref);
tv->v_type = VAR_FUNC;
tv->vval.v_string = xstrdup(name);
break;
}
}
-
- return true;
}
diff --git a/src/nvim/api/private/defs.h b/src/nvim/api/private/defs.h
index 25c8377518..ca088d7a55 100644
--- a/src/nvim/api/private/defs.h
+++ b/src/nvim/api/private/defs.h
@@ -105,6 +105,14 @@ typedef enum {
kObjectTypeTabpage,
} ObjectType;
+/// Value by which objects represented as EXT type are shifted
+///
+/// Subtracted when packing, added when unpacking. Used to allow moving
+/// buffer/window/tabpage block inside ObjectType enum. This block yet cannot be
+/// split or reordered.
+#define EXT_OBJECT_TYPE_SHIFT kObjectTypeBuffer
+#define EXT_OBJECT_TYPE_MAX (kObjectTypeTabpage - EXT_OBJECT_TYPE_SHIFT)
+
struct object {
ObjectType type;
union {
@@ -124,6 +132,7 @@ struct key_value_pair {
};
typedef uint64_t OptionalKeys;
+typedef Integer HLGroupID;
// this is the prefix of all keysets with optional keys
typedef struct {
@@ -135,6 +144,7 @@ typedef struct {
size_t ptr_off;
ObjectType type; // kObjectTypeNil == untyped
int opt_index;
+ bool is_hlgroup;
} KeySetLink;
typedef KeySetLink *(*FieldHashfn)(const char *str, size_t len);
diff --git a/src/nvim/api/private/dispatch.h b/src/nvim/api/private/dispatch.h
index 6a2c9eaf54..288f368fba 100644
--- a/src/nvim/api/private/dispatch.h
+++ b/src/nvim/api/private/dispatch.h
@@ -3,7 +3,7 @@
#include <stdbool.h>
#include <stdint.h>
-#include "nvim/api/private/defs.h"
+#include "nvim/api/private/defs.h" // IWYU pragma: keep
#include "nvim/memory_defs.h"
#include "nvim/types_defs.h"
@@ -14,18 +14,18 @@ typedef Object (*ApiDispatchWrapper)(uint64_t channel_id, Array args, Arena *are
struct MsgpackRpcRequestHandler {
const char *name;
ApiDispatchWrapper fn;
- bool fast; // Function is safe to be executed immediately while running the
- // uv loop (the loop is run very frequently due to breakcheck).
- // If "fast" is false, the function is deferred, i e the call will
- // be put in the event queue, for safe handling later.
- bool arena_return; // return value is allocated in the arena (or statically)
- // and should not be freed as such.
+ bool fast; ///< Function is safe to be executed immediately while running the
+ ///< uv loop (the loop is run very frequently due to breakcheck).
+ ///< If "fast" is false, the function is deferred, i e the call will
+ ///< be put in the event queue, for safe handling later.
+ bool ret_alloc; ///< return value is allocated and should be freed using api_free_object
+ ///< otherwise it uses arena and/or static memory
};
extern const MsgpackRpcRequestHandler method_handlers[];
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/private/dispatch.h.generated.h"
-# include "api/private/dispatch_wrappers.h.generated.h" // IWYU pragma: export
+# include "api/private/dispatch_wrappers.h.generated.h"
# include "keysets_defs.generated.h"
#endif
diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c
index be39836a5b..1cd98aa0c4 100644
--- a/src/nvim/api/private/helpers.c
+++ b/src/nvim/api/private/helpers.c
@@ -17,11 +17,9 @@
#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/eval/typval.h"
-#include "nvim/eval/typval_defs.h"
#include "nvim/eval/vars.h"
#include "nvim/ex_eval.h"
-#include "nvim/func_attr.h"
-#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight_group.h"
#include "nvim/lua/executor.h"
@@ -29,17 +27,18 @@
#include "nvim/mark.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
-#include "nvim/msgpack_rpc/helpers.h"
+#include "nvim/msgpack_rpc/unpacker.h"
#include "nvim/pos_defs.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/version.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "api/private/funcs_metadata.generated.h"
+# include "api/private/api_metadata.generated.h"
# include "api/private/helpers.c.generated.h"
-# include "api/private/ui_events_metadata.generated.h"
#endif
/// Start block that may cause Vimscript exceptions while evaluating another code
@@ -140,7 +139,7 @@ bool try_end(Error *err)
api_set_error(err, kErrorTypeException, "Keyboard interrupt");
got_int = false;
} else if (msg_list != NULL && *msg_list != NULL) {
- int should_free;
+ bool should_free;
char *msg = get_exception_string(*msg_list,
ET_ERROR,
NULL,
@@ -151,7 +150,7 @@ bool try_end(Error *err)
if (should_free) {
xfree(msg);
}
- } else if (did_throw) {
+ } else if (did_throw || need_rethrow) {
if (*current_exception->throw_name != NUL) {
if (current_exception->throw_lnum != 0) {
api_set_error(err, kErrorTypeException, "%s, line %" PRIdLINENR ": %s",
@@ -175,7 +174,7 @@ bool try_end(Error *err)
/// @param dict The vimscript dict
/// @param key The key
/// @param[out] err Details of an error that may have occurred
-Object dict_get_value(dict_T *dict, String key, Error *err)
+Object dict_get_value(dict_T *dict, String key, Arena *arena, Error *err)
{
dictitem_T *const di = tv_dict_find(dict, key.data, (ptrdiff_t)key.size);
@@ -184,7 +183,7 @@ Object dict_get_value(dict_T *dict, String key, Error *err)
return (Object)OBJECT_INIT;
}
- return vim_to_object(&di->di_tv);
+ return vim_to_object(&di->di_tv, arena, true);
}
dictitem_T *dict_check_writable(dict_T *dict, String key, bool del, Error *err)
@@ -221,7 +220,8 @@ dictitem_T *dict_check_writable(dict_T *dict, String key, bool del, Error *err)
/// @param retval If true the old value will be converted and returned.
/// @param[out] err Details of an error that may have occurred
/// @return The old value if `retval` is true and the key was present, else NIL
-Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retval, Error *err)
+Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retval, Arena *arena,
+ Error *err)
{
Object rv = OBJECT_INIT;
dictitem_T *di = dict_check_writable(dict, key, del, err);
@@ -244,7 +244,7 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
}
// Return the old value
if (retval) {
- rv = vim_to_object(&di->di_tv);
+ rv = vim_to_object(&di->di_tv, arena, false);
}
// Delete the entry
tv_dict_item_remove(dict, di);
@@ -254,9 +254,7 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
typval_T tv;
// Convert the object to a vimscript type in the temporary variable
- if (!object_to_vim(value, &tv, err)) {
- return rv;
- }
+ object_to_vim(value, &tv, err);
typval_T oldtv = TV_INITIAL_VALUE;
@@ -267,7 +265,7 @@ Object dict_set_var(dict_T *dict, String key, Object value, bool del, bool retva
} else {
// Return the old value
if (retval) {
- rv = vim_to_object(&di->di_tv);
+ rv = vim_to_object(&di->di_tv, arena, false);
}
bool type_error = false;
if (dict == &vimvardict
@@ -427,12 +425,12 @@ String cstrn_as_string(char *str, size_t maxsize)
/// @param str the C string to use
/// @return The resulting String, or an empty String if
/// str was NULL
-String cstr_as_string(char *str) FUNC_ATTR_PURE
+String cstr_as_string(const char *str) FUNC_ATTR_PURE
{
if (str == NULL) {
return (String)STRING_INIT;
}
- return (String){ .data = str, .size = strlen(str) };
+ return (String){ .data = (char *)str, .size = strlen(str) };
}
/// Return the owned memory of a ga as a String
@@ -456,9 +454,10 @@ String ga_take_string(garray_T *ga)
/// @param input Binary string
/// @param crlf Also break lines at CR and CRLF.
/// @return [allocated] String array
-Array string_to_array(const String input, bool crlf)
+Array string_to_array(const String input, bool crlf, Arena *arena)
{
- Array ret = ARRAY_DICT_INIT;
+ ArrayBuilder ret = ARRAY_DICT_INIT;
+ kvi_init(ret);
for (size_t i = 0; i < input.size; i++) {
const char *start = input.data + i;
const char *end = start;
@@ -473,20 +472,17 @@ Array string_to_array(const String input, bool crlf)
if (crlf && *end == CAR && i + 1 < input.size && *(end + 1) == NL) {
i += 1; // Advance past CRLF.
}
- String s = {
- .size = line_len,
- .data = xmemdupz(start, line_len),
- };
+ String s = CBUF_TO_ARENA_STR(arena, start, line_len);
memchrsub(s.data, NUL, NL, line_len);
- ADD(ret, STRING_OBJ(s));
+ kvi_push(ret, STRING_OBJ(s));
// If line ends at end-of-buffer, add empty final item.
// This is "readfile()-style", see also ":help channel-lines".
if (i + 1 == input.size && (*end == NL || (crlf && *end == CAR))) {
- ADD(ret, STRING_OBJ(STRING_INIT));
+ kvi_push(ret, STRING_OBJ(STRING_INIT));
}
}
- return ret;
+ return arena_take_arraybuilder(arena, &ret);
}
/// Normalizes 0-based indexes to buffer line numbers.
@@ -578,10 +574,19 @@ String arena_string(Arena *arena, String str)
if (str.size) {
return cbuf_as_string(arena_memdupz(arena, str.data, str.size), str.size);
} else {
- return (String)STRING_INIT;
+ return (String){ .data = arena ? "" : xstrdup(""), .size = 0 };
}
}
+Array arena_take_arraybuilder(Arena *arena, ArrayBuilder *arr)
+{
+ Array ret = arena_array(arena, kv_size(*arr));
+ ret.size = kv_size(*arr);
+ memcpy(ret.items, arr->items, sizeof(ret.items[0]) * ret.size);
+ kvi_destroy(*arr);
+ return ret;
+}
+
void api_free_object(Object value)
{
switch (value.type) {
@@ -642,102 +647,30 @@ void api_clear_error(Error *value)
value->type = kErrorTypeNone;
}
-/// @returns a shared value. caller must not modify it!
-Dictionary api_metadata(void)
-{
- static Dictionary metadata = ARRAY_DICT_INIT;
-
- if (!metadata.size) {
- PUT(metadata, "version", DICTIONARY_OBJ(version_dict()));
- init_function_metadata(&metadata);
- init_ui_event_metadata(&metadata);
- init_error_type_metadata(&metadata);
- init_type_metadata(&metadata);
- }
-
- return metadata;
-}
+// initialized once, never freed
+static ArenaMem mem_for_metadata = NULL;
-static void init_function_metadata(Dictionary *metadata)
+/// @returns a shared value. caller must not modify it!
+Object api_metadata(void)
{
- msgpack_unpacked unpacked;
- msgpack_unpacked_init(&unpacked);
- if (msgpack_unpack_next(&unpacked,
- (const char *)funcs_metadata,
- sizeof(funcs_metadata),
- NULL) != MSGPACK_UNPACK_SUCCESS) {
- abort();
- }
- Object functions;
- msgpack_rpc_to_object(&unpacked.data, &functions);
- msgpack_unpacked_destroy(&unpacked);
- PUT(*metadata, "functions", functions);
-}
+ static Object metadata = OBJECT_INIT;
-static void init_ui_event_metadata(Dictionary *metadata)
-{
- msgpack_unpacked unpacked;
- msgpack_unpacked_init(&unpacked);
- if (msgpack_unpack_next(&unpacked,
- (const char *)ui_events_metadata,
- sizeof(ui_events_metadata),
- NULL) != MSGPACK_UNPACK_SUCCESS) {
- abort();
- }
- Object ui_events;
- msgpack_rpc_to_object(&unpacked.data, &ui_events);
- msgpack_unpacked_destroy(&unpacked);
- PUT(*metadata, "ui_events", ui_events);
- Array ui_options = ARRAY_DICT_INIT;
- ADD(ui_options, CSTR_TO_OBJ("rgb"));
- for (UIExtension i = 0; i < kUIExtCount; i++) {
- if (ui_ext_names[i][0] != '_') {
- ADD(ui_options, CSTR_TO_OBJ(ui_ext_names[i]));
+ if (metadata.type == kObjectTypeNil) {
+ Arena arena = ARENA_EMPTY;
+ Error err = ERROR_INIT;
+ metadata = unpack((char *)packed_api_metadata, sizeof(packed_api_metadata), &arena, &err);
+ if (ERROR_SET(&err) || metadata.type != kObjectTypeDictionary) {
+ abort();
}
+ mem_for_metadata = arena_finish(&arena);
}
- PUT(*metadata, "ui_options", ARRAY_OBJ(ui_options));
-}
-
-static void init_error_type_metadata(Dictionary *metadata)
-{
- Dictionary types = ARRAY_DICT_INIT;
-
- Dictionary exception_metadata = ARRAY_DICT_INIT;
- PUT(exception_metadata, "id", INTEGER_OBJ(kErrorTypeException));
-
- Dictionary validation_metadata = ARRAY_DICT_INIT;
- PUT(validation_metadata, "id", INTEGER_OBJ(kErrorTypeValidation));
- PUT(types, "Exception", DICTIONARY_OBJ(exception_metadata));
- PUT(types, "Validation", DICTIONARY_OBJ(validation_metadata));
-
- PUT(*metadata, "error_types", DICTIONARY_OBJ(types));
+ return metadata;
}
-static void init_type_metadata(Dictionary *metadata)
+String api_metadata_raw(void)
{
- Dictionary types = ARRAY_DICT_INIT;
-
- Dictionary buffer_metadata = ARRAY_DICT_INIT;
- PUT(buffer_metadata, "id",
- INTEGER_OBJ(kObjectTypeBuffer - EXT_OBJECT_TYPE_SHIFT));
- 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", 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", CSTR_TO_OBJ("nvim_tabpage_"));
-
- PUT(types, "Buffer", DICTIONARY_OBJ(buffer_metadata));
- PUT(types, "Window", DICTIONARY_OBJ(window_metadata));
- PUT(types, "Tabpage", DICTIONARY_OBJ(tabpage_metadata));
-
- PUT(*metadata, "types", DICTIONARY_OBJ(types));
+ return cbuf_as_string((char *)packed_api_metadata, sizeof(packed_api_metadata));
}
// all the copy_[object] functions allow arena=NULL,
@@ -938,13 +871,26 @@ bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dictionary dict, Error
char *mem = ((char *)retval + field->ptr_off);
Object *value = &dict.items[i].value;
+
if (field->type == kObjectTypeNil) {
*(Object *)mem = *value;
} else if (field->type == kObjectTypeInteger) {
- VALIDATE_T(field->str, kObjectTypeInteger, value->type, {
- return false;
- });
- *(Integer *)mem = value->data.integer;
+ if (field->is_hlgroup) {
+ int hl_id = 0;
+ if (value->type != kObjectTypeNil) {
+ hl_id = object_to_hl_id(*value, k.data, err);
+ if (ERROR_SET(err)) {
+ return false;
+ }
+ }
+ *(Integer *)mem = hl_id;
+ } else {
+ VALIDATE_T(field->str, kObjectTypeInteger, value->type, {
+ return false;
+ });
+
+ *(Integer *)mem = value->data.integer;
+ }
} else if (field->type == kObjectTypeFloat) {
Float *val = (Float *)mem;
if (value->type == kObjectTypeInteger) {
@@ -1003,24 +949,104 @@ bool api_dict_to_keydict(void *retval, FieldHashfn hashy, Dictionary dict, Error
return true;
}
-void api_free_keydict(void *dict, KeySetLink *table)
+Dictionary api_keydict_to_dict(void *value, KeySetLink *table, size_t max_size, Arena *arena)
+{
+ Dictionary rv = arena_dict(arena, max_size);
+ for (size_t i = 0; table[i].str; i++) {
+ KeySetLink *field = &table[i];
+ bool is_set = true;
+ if (field->opt_index >= 0) {
+ OptKeySet *ks = (OptKeySet *)value;
+ is_set = ks->is_set_ & (1ULL << field->opt_index);
+ }
+
+ if (!is_set) {
+ continue;
+ }
+
+ char *mem = ((char *)value + field->ptr_off);
+ Object val = NIL;
+
+ if (field->type == kObjectTypeNil) {
+ val = *(Object *)mem;
+ } else if (field->type == kObjectTypeInteger) {
+ val = INTEGER_OBJ(*(Integer *)mem);
+ } else if (field->type == kObjectTypeFloat) {
+ val = FLOAT_OBJ(*(Float *)mem);
+ } else if (field->type == kObjectTypeBoolean) {
+ val = BOOLEAN_OBJ(*(Boolean *)mem);
+ } else if (field->type == kObjectTypeString) {
+ val = STRING_OBJ(*(String *)mem);
+ } else if (field->type == kObjectTypeArray) {
+ val = ARRAY_OBJ(*(Array *)mem);
+ } else if (field->type == kObjectTypeDictionary) {
+ val = DICTIONARY_OBJ(*(Dictionary *)mem);
+ } else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow
+ || field->type == kObjectTypeTabpage) {
+ val.data.integer = *(handle_T *)mem;
+ val.type = field->type;
+ } else if (field->type == kObjectTypeLuaRef) {
+ // do nothing
+ } else {
+ abort();
+ }
+
+ PUT_C(rv, field->str, val);
+ }
+
+ return rv;
+}
+
+void api_luarefs_free_object(Object value)
+{
+ // TODO(bfredl): this is more complicated than it needs to be.
+ // we should be able to lock down more specifically where luarefs can be
+ switch (value.type) {
+ case kObjectTypeLuaRef:
+ api_free_luaref(value.data.luaref);
+ break;
+
+ case kObjectTypeArray:
+ api_luarefs_free_array(value.data.array);
+ break;
+
+ case kObjectTypeDictionary:
+ api_luarefs_free_dict(value.data.dictionary);
+ break;
+
+ default:
+ break;
+ }
+}
+
+void api_luarefs_free_keydict(void *dict, KeySetLink *table)
{
for (size_t i = 0; table[i].str; i++) {
char *mem = ((char *)dict + table[i].ptr_off);
if (table[i].type == kObjectTypeNil) {
- api_free_object(*(Object *)mem);
- } else if (table[i].type == kObjectTypeString) {
- api_free_string(*(String *)mem);
- } else if (table[i].type == kObjectTypeArray) {
- api_free_array(*(Array *)mem);
- } else if (table[i].type == kObjectTypeDictionary) {
- api_free_dictionary(*(Dictionary *)mem);
+ api_luarefs_free_object(*(Object *)mem);
} else if (table[i].type == kObjectTypeLuaRef) {
api_free_luaref(*(LuaRef *)mem);
+ } else if (table[i].type == kObjectTypeDictionary) {
+ api_luarefs_free_dict(*(Dictionary *)mem);
}
}
}
+void api_luarefs_free_array(Array value)
+{
+ for (size_t i = 0; i < value.size; i++) {
+ api_luarefs_free_object(value.items[i]);
+ }
+}
+
+void api_luarefs_free_dict(Dictionary value)
+{
+ for (size_t i = 0; i < value.size; i++) {
+ api_luarefs_free_object(value.items[i].value);
+ }
+}
+
/// Set a named mark
/// buffer and mark name must be validated already
/// @param buffer Buffer to set the mark on
@@ -1048,7 +1074,7 @@ bool set_mark(buf_T *buf, String name, Integer line, Integer col, Error *err)
}
}
assert(INT32_MIN <= line && line <= INT32_MAX);
- pos_T pos = { (linenr_T)line, (int)col, (int)col };
+ pos_T pos = { (linenr_T)line, (int)col, 0 };
res = setmark_pos(*name.data, &pos, buf->handle, NULL);
if (!res) {
if (deleting) {
diff --git a/src/nvim/api/private/helpers.h b/src/nvim/api/private/helpers.h
index e61dd5f992..7eda8ffaf6 100644
--- a/src/nvim/api/private/helpers.h
+++ b/src/nvim/api/private/helpers.h
@@ -2,21 +2,15 @@
#include <stdbool.h>
#include <stddef.h>
-#include <stdint.h>
#include "klib/kvec.h"
-#include "nvim/api/private/defs.h"
-#include "nvim/api/private/dispatch.h"
-#include "nvim/decoration.h"
-#include "nvim/eval/typval_defs.h"
+#include "nvim/api/private/defs.h" // IWYU pragma: keep
+#include "nvim/buffer_defs.h" // IWYU pragma: keep
+#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/ex_eval_defs.h"
-#include "nvim/getchar.h"
-#include "nvim/gettext.h"
-#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/map_defs.h"
-#include "nvim/memory.h"
-#include "nvim/message.h"
+#include "nvim/message_defs.h" // IWYU pragma: keep
#define OBJECT_OBJ(o) o
@@ -38,6 +32,10 @@
#define CSTR_AS_OBJ(s) STRING_OBJ(cstr_as_string(s))
#define CSTR_TO_OBJ(s) STRING_OBJ(cstr_to_string(s))
+#define CSTR_TO_ARENA_STR(arena, s) arena_string(arena, cstr_as_string(s))
+#define CSTR_TO_ARENA_OBJ(arena, s) STRING_OBJ(CSTR_TO_ARENA_STR(arena, s))
+#define CBUF_TO_ARENA_STR(arena, s, len) arena_string(arena, cbuf_as_string((char *)(s), len))
+#define CBUF_TO_ARENA_OBJ(arena, s, len) STRING_OBJ(CBUF_TO_ARENA_STR(arena, s, len))
#define BUFFER_OBJ(s) ((Object) { \
.type = kObjectTypeBuffer, \
@@ -76,6 +74,9 @@
#define PUT_C(dict, k, v) \
kv_push_c(dict, ((KeyValuePair) { .key = cstr_as_string(k), .value = v }))
+#define PUT_KEY(d, typ, key, v) \
+ do { (d).is_set__##typ##_ |= (1 << KEYSET_OPTIDX_##typ##__##key); (d).key = v; } while (0)
+
#define ADD(array, item) \
kv_push(array, item)
@@ -94,6 +95,8 @@
name.capacity = maxsize; \
name.items = name##__items; \
+typedef kvec_withinit_t(Object, 16) ArrayBuilder;
+
#define cbuf_as_string(d, s) ((String) { .data = d, .size = s })
#define STATIC_CSTR_AS_STRING(s) ((String) { .data = s, .size = sizeof("" s) - 1 })
@@ -120,12 +123,7 @@
#define api_init_array = ARRAY_DICT_INIT
#define api_init_dictionary = ARRAY_DICT_INIT
-#define api_free_boolean(value)
-#define api_free_integer(value)
-#define api_free_float(value)
-#define api_free_buffer(value)
-#define api_free_window(value)
-#define api_free_tabpage(value)
+#define KEYDICT_INIT { 0 }
EXTERN PMap(int) buffer_handles INIT( = MAP_INIT);
EXTERN PMap(int) window_handles INIT( = MAP_INIT);
diff --git a/src/nvim/api/private/validate.h b/src/nvim/api/private/validate.h
index d1c977cd6e..2c1d1a241d 100644
--- a/src/nvim/api/private/validate.h
+++ b/src/nvim/api/private/validate.h
@@ -3,7 +3,7 @@
#include <stdbool.h>
#include <stddef.h>
-#include "nvim/api/private/defs.h"
+#include "nvim/api/private/defs.h" // IWYU pragma: keep
#include "nvim/api/private/helpers.h"
#include "nvim/assert_defs.h"
#include "nvim/macros_defs.h"
diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c
index c854a22477..040abb1e3f 100644
--- a/src/nvim/api/tabpage.c
+++ b/src/nvim/api/tabpage.c
@@ -6,17 +6,20 @@
#include "nvim/api/tabpage.h"
#include "nvim/api/vim.h"
#include "nvim/buffer_defs.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/memory.h"
#include "nvim/window.h"
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "api/tabpage.c.generated.h"
+#endif
+
/// Gets the windows in a tabpage
///
/// @param tabpage Tabpage handle, or 0 for current tabpage
/// @param[out] err Error details, if any
/// @return List of windows in `tabpage`
-ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err)
+ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
@@ -26,15 +29,15 @@ ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err)
return rv;
}
+ size_t n = 0;
FOR_ALL_WINDOWS_IN_TAB(wp, tab) {
- rv.size++;
+ n++;
}
- rv.items = xmalloc(sizeof(Object) * rv.size);
- size_t i = 0;
+ rv = arena_array(arena, n);
FOR_ALL_WINDOWS_IN_TAB(wp, tab) {
- rv.items[i++] = WINDOW_OBJ(wp->handle);
+ ADD_C(rv, WINDOW_OBJ(wp->handle));
}
return rv;
@@ -46,7 +49,7 @@ ArrayOf(Window) nvim_tabpage_list_wins(Tabpage tabpage, Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Variable value
-Object nvim_tabpage_get_var(Tabpage tabpage, String name, Error *err)
+Object nvim_tabpage_get_var(Tabpage tabpage, String name, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
tabpage_T *tab = find_tab_by_handle(tabpage, err);
@@ -55,7 +58,7 @@ Object nvim_tabpage_get_var(Tabpage tabpage, String name, Error *err)
return (Object)OBJECT_INIT;
}
- return dict_get_value(tab->tp_vars, name, err);
+ return dict_get_value(tab->tp_vars, name, arena, err);
}
/// Sets a tab-scoped (t:) variable
@@ -73,7 +76,7 @@ void nvim_tabpage_set_var(Tabpage tabpage, String name, Object value, Error *err
return;
}
- dict_set_var(tab->tp_vars, name, value, false, false, err);
+ dict_set_var(tab->tp_vars, name, value, false, false, NULL, err);
}
/// Removes a tab-scoped (t:) variable
@@ -90,7 +93,7 @@ void nvim_tabpage_del_var(Tabpage tabpage, String name, Error *err)
return;
}
- dict_set_var(tab->tp_vars, name, NIL, true, false, err);
+ dict_set_var(tab->tp_vars, name, NIL, true, false, NULL, err);
}
/// Gets the current window in a tabpage
@@ -119,6 +122,37 @@ Window nvim_tabpage_get_win(Tabpage tabpage, Error *err)
abort();
}
+/// Sets the current window in a tabpage
+///
+/// @param tabpage Tabpage handle, or 0 for current tabpage
+/// @param win Window handle, must already belong to {tabpage}
+/// @param[out] err Error details, if any
+void nvim_tabpage_set_win(Tabpage tabpage, Window win, Error *err)
+ FUNC_API_SINCE(12)
+{
+ tabpage_T *tp = find_tab_by_handle(tabpage, err);
+ if (!tp) {
+ return;
+ }
+
+ win_T *wp = find_window_by_handle(win, err);
+ if (!wp) {
+ return;
+ }
+
+ if (!tabpage_win_valid(tp, wp)) {
+ api_set_error(err, kErrorTypeException, "Window does not belong to tabpage %d", tp->handle);
+ return;
+ }
+
+ if (tp == curtab) {
+ win_enter(wp, true);
+ } else if (tp->tp_curwin != wp) {
+ tp->tp_prevwin = tp->tp_curwin;
+ tp->tp_curwin = wp;
+ }
+}
+
/// Gets the tabpage number
///
/// @param tabpage Tabpage handle, or 0 for current tabpage
diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c
index 836a68546c..692e3f95fc 100644
--- a/src/nvim/api/ui.c
+++ b/src/nvim/api/ui.c
@@ -12,27 +12,34 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
#include "nvim/api/ui.h"
+#include "nvim/assert_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/channel.h"
+#include "nvim/channel_defs.h"
#include "nvim/eval.h"
+#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/event/wstream.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight.h"
#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/map_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/msgpack_rpc/channel.h"
-#include "nvim/msgpack_rpc/helpers.h"
+#include "nvim/msgpack_rpc/channel_defs.h"
+#include "nvim/msgpack_rpc/packer.h"
#include "nvim/option.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
-#define BUF_POS(data) ((size_t)((data)->buf_wptr - (data)->buf))
+#define BUF_POS(ui) ((size_t)((ui)->packer.ptr - (ui)->packer.startptr))
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/ui.c.generated.h"
@@ -41,55 +48,6 @@
static PMap(uint64_t) connected_uis = MAP_INIT;
-#define mpack_w(b, byte) *(*b)++ = (char)(byte);
-static void mpack_w2(char **b, uint32_t v)
-{
- *(*b)++ = (char)((v >> 8) & 0xff);
- *(*b)++ = (char)(v & 0xff);
-}
-
-static void mpack_w4(char **b, uint32_t v)
-{
- *(*b)++ = (char)((v >> 24) & 0xff);
- *(*b)++ = (char)((v >> 16) & 0xff);
- *(*b)++ = (char)((v >> 8) & 0xff);
- *(*b)++ = (char)(v & 0xff);
-}
-
-static void mpack_uint(char **buf, uint32_t val)
-{
- if (val > 0xffff) {
- mpack_w(buf, 0xce);
- mpack_w4(buf, val);
- } else if (val > 0xff) {
- mpack_w(buf, 0xcd);
- mpack_w2(buf, val);
- } else if (val > 0x7f) {
- mpack_w(buf, 0xcc);
- mpack_w(buf, val);
- } else {
- mpack_w(buf, val);
- }
-}
-
-static void mpack_bool(char **buf, bool val)
-{
- mpack_w(buf, 0xc2 | (val ? 1 : 0));
-}
-
-static void mpack_array(char **buf, uint32_t len)
-{
- if (len < 0x10) {
- mpack_w(buf, 0x90 | len);
- } else if (len < 0x10000) {
- mpack_w(buf, 0xdc);
- mpack_w2(buf, len);
- } else {
- mpack_w(buf, 0xdd);
- mpack_w4(buf, len);
- }
-}
-
static char *mpack_array_dyn16(char **buf)
{
mpack_w(buf, 0xdc);
@@ -98,30 +56,44 @@ static char *mpack_array_dyn16(char **buf)
return pos;
}
-static void mpack_str(char **buf, const char *str)
+static void mpack_str_small(char **buf, const char *str, size_t len)
{
- assert(sizeof(schar_T) - 1 < 0x20);
- size_t len = strlen(str);
+ assert(len < 0x20);
mpack_w(buf, 0xa0 | len);
memcpy(*buf, str, len);
*buf += len;
}
+static void remote_ui_destroy(RemoteUI *ui)
+ FUNC_ATTR_NONNULL_ALL
+{
+ kv_destroy(ui->call_buf);
+ xfree(ui->packer.startptr);
+ XFREE_CLEAR(ui->term_name);
+ xfree(ui);
+}
+
void remote_ui_disconnect(uint64_t channel_id)
{
- UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
+ RemoteUI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
if (!ui) {
return;
}
- UIData *data = ui->data;
- kv_destroy(data->call_buf);
pmap_del(uint64_t)(&connected_uis, channel_id, NULL);
ui_detach_impl(ui, channel_id);
+ remote_ui_destroy(ui);
+}
- // Destroy `ui`.
- XFREE_CLEAR(ui->term_name);
- xfree(ui);
+#ifdef EXITFREE
+void remote_ui_free_all_mem(void)
+{
+ RemoteUI *ui;
+ map_foreach_value(&connected_uis, ui, {
+ remote_ui_destroy(ui);
+ });
+ map_destroy(uint64_t, &connected_uis);
}
+#endif
/// Wait until ui has connected on stdio channel if only_stdio
/// is true, otherwise any channel.
@@ -145,7 +117,7 @@ void remote_ui_wait_for_attach(bool only_stdio)
/// Activates UI events on the channel.
///
-/// Entry point of all UI clients. Allows |\-\-embed| to continue startup.
+/// Entry point of all UI clients. Allows |--embed| to continue startup.
/// Implies that the client is ready to show the UI. Adds the client to the
/// list of UIs. |nvim_list_uis()|
///
@@ -173,7 +145,7 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
"Expected width > 0 and height > 0");
return;
}
- UI *ui = xcalloc(1, sizeof(UI));
+ RemoteUI *ui = xcalloc(1, sizeof(RemoteUI));
ui->width = (int)width;
ui->height = (int)height;
ui->pum_row = -1.0;
@@ -200,22 +172,26 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
ui->ui_ext[kUICmdline] = true;
}
- UIData *data = ui->data;
- data->channel_id = channel_id;
- data->cur_event = NULL;
- data->hl_id = 0;
- data->client_col = -1;
- data->nevents_pos = NULL;
- data->nevents = 0;
- data->flushed_events = false;
- data->ncalls_pos = NULL;
- data->ncalls = 0;
- data->ncells_pending = 0;
- data->buf_wptr = data->buf;
- data->temp_buf = NULL;
- data->wildmenu_active = false;
- data->call_buf = (Array)ARRAY_DICT_INIT;
- kv_ensure_space(data->call_buf, 16);
+ ui->channel_id = channel_id;
+ ui->cur_event = NULL;
+ ui->hl_id = 0;
+ ui->client_col = -1;
+ ui->nevents_pos = NULL;
+ ui->nevents = 0;
+ ui->flushed_events = false;
+ ui->ncalls_pos = NULL;
+ ui->ncalls = 0;
+ ui->ncells_pending = 0;
+ ui->packer = (PackerBuffer) {
+ .startptr = NULL,
+ .ptr = NULL,
+ .endptr = NULL,
+ .packer_flush = ui_flush_callback,
+ .anydata = ui,
+ };
+ ui->wildmenu_active = false;
+ ui->call_buf = (Array)ARRAY_DICT_INIT;
+ kv_ensure_space(ui->call_buf, 16);
pmap_put(uint64_t)(&connected_uis, channel_id, ui);
ui_attach_impl(ui, channel_id);
@@ -227,10 +203,9 @@ void nvim_ui_attach(uint64_t channel_id, Integer width, Integer height, Dictiona
void ui_attach(uint64_t channel_id, Integer width, Integer height, Boolean enable_rgb, Error *err)
FUNC_API_DEPRECATED_SINCE(1)
{
- Dictionary opts = ARRAY_DICT_INIT;
- PUT(opts, "rgb", BOOLEAN_OBJ(enable_rgb));
+ MAXSIZE_TEMP_DICT(opts, 1);
+ PUT_C(opts, "rgb", BOOLEAN_OBJ(enable_rgb));
nvim_ui_attach(channel_id, width, height, opts, err);
- api_free_dictionary(opts);
}
/// Tells the nvim server if focus was gained or lost by the GUI
@@ -268,7 +243,7 @@ void nvim_ui_detach(uint64_t channel_id, Error *err)
}
// TODO(bfredl): use me to detach a specific ui from the server
-void remote_ui_stop(UI *ui)
+void remote_ui_stop(RemoteUI *ui)
{
}
@@ -287,7 +262,7 @@ void nvim_ui_try_resize(uint64_t channel_id, Integer width, Integer height, Erro
return;
}
- UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
+ RemoteUI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
ui->width = (int)width;
ui->height = (int)height;
ui_refresh();
@@ -301,12 +276,12 @@ void nvim_ui_set_option(uint64_t channel_id, String name, Object value, Error *e
"UI not attached to channel: %" PRId64, channel_id);
return;
}
- UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
+ RemoteUI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
ui_set_option(ui, false, name, value, error);
}
-static void ui_set_option(UI *ui, bool init, String name, Object value, Error *err)
+static void ui_set_option(RemoteUI *ui, bool init, String name, Object value, Error *err)
{
if (strequal(name.data, "override")) {
VALIDATE_T("override", kObjectTypeBoolean, value.type, {
@@ -435,7 +410,7 @@ void nvim_ui_try_resize_grid(uint64_t channel_id, Integer grid, Integer width, I
}
/// Tells Nvim the number of elements displaying in the popupmenu, to decide
-/// <PageUp> and <PageDown> movement.
+/// [<PageUp>] and [<PageDown>] movement.
///
/// @param channel_id
/// @param height Popupmenu height, must be greater than zero.
@@ -454,7 +429,7 @@ void nvim_ui_pum_set_height(uint64_t channel_id, Integer height, Error *err)
return;
}
- UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
+ RemoteUI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
if (!ui->ui_ext[kUIPopupmenu]) {
api_set_error(err, kErrorTypeValidation,
"It must support the ext_popupmenu option");
@@ -490,7 +465,7 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, Floa
return;
}
- UI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
+ RemoteUI *ui = pmap_get(uint64_t)(&connected_uis, channel_id);
if (!ui->ui_ext[kUIPopupmenu]) {
api_set_error(err, kErrorTypeValidation,
"UI must support the ext_popupmenu option");
@@ -522,7 +497,7 @@ void nvim_ui_pum_set_bounds(uint64_t channel_id, Float width, Float height, Floa
///
/// @param channel_id
/// @param event Event name
-/// @param payload Event payload
+/// @param value Event payload
/// @param[out] err Error details, if any.
void nvim_ui_term_event(uint64_t channel_id, String event, Object value, Error *err)
FUNC_API_SINCE(12) FUNC_API_REMOTE_ONLY
@@ -539,126 +514,75 @@ void nvim_ui_term_event(uint64_t channel_id, String event, Object value, Error *
}
}
-static void flush_event(UIData *data)
+static void flush_event(RemoteUI *ui)
{
- if (data->cur_event) {
- mpack_w2(&data->ncalls_pos, data->ncalls);
- data->cur_event = NULL;
- }
- if (!data->nevents_pos) {
- assert(BUF_POS(data) == 0);
- char **buf = &data->buf_wptr;
- // [2, "redraw", [...]]
- mpack_array(buf, 3);
- mpack_uint(buf, 2);
- mpack_str(buf, "redraw");
- data->nevents_pos = mpack_array_dyn16(buf);
+ if (ui->cur_event) {
+ mpack_w2(&ui->ncalls_pos, 1 + ui->ncalls);
+ ui->cur_event = NULL;
+ ui->ncalls_pos = NULL;
+ ui->ncalls = 0;
}
}
-static inline int write_cb(void *vdata, const char *buf, size_t len)
+static void ui_alloc_buf(RemoteUI *ui)
{
- UIData *data = (UIData *)vdata;
- if (!buf) {
- return 0;
- }
-
- data->pack_totlen += len;
- if (!data->temp_buf && UI_BUF_SIZE - BUF_POS(data) < len) {
- data->buf_overflow = true;
- return 0;
- }
-
- memcpy(data->buf_wptr, buf, len);
- data->buf_wptr += len;
-
- return 0;
+ ui->packer.startptr = alloc_block();
+ ui->packer.ptr = ui->packer.startptr;
+ ui->packer.endptr = ui->packer.startptr + UI_BUF_SIZE;
}
-static bool prepare_call(UI *ui, const char *name)
+static void prepare_call(RemoteUI *ui, const char *name)
{
- UIData *data = ui->data;
+ if (ui->packer.startptr && BUF_POS(ui) > UI_BUF_SIZE - EVENT_BUF_SIZE) {
+ ui_flush_buf(ui);
+ }
- if (BUF_POS(data) > UI_BUF_SIZE - EVENT_BUF_SIZE) {
- remote_ui_flush_buf(ui);
+ if (ui->packer.startptr == NULL) {
+ ui_alloc_buf(ui);
}
// To optimize data transfer(especially for "grid_line"), we bundle adjacent
// calls to same method together, so only add a new call entry if the last
// method call is different from "name"
- if (!data->cur_event || !strequal(data->cur_event, name)) {
- flush_event(data);
- data->cur_event = name;
- char **buf = &data->buf_wptr;
- data->ncalls_pos = mpack_array_dyn16(buf);
- mpack_str(buf, name);
- data->nevents++;
- data->ncalls = 1;
- return true;
+ if (!ui->cur_event || !strequal(ui->cur_event, name)) {
+ char **buf = &ui->packer.ptr;
+ if (!ui->nevents_pos) {
+ // [2, "redraw", [...]]
+ mpack_array(buf, 3);
+ mpack_uint(buf, 2);
+ mpack_str_small(buf, S_LEN("redraw"));
+ ui->nevents_pos = mpack_array_dyn16(buf);
+ assert(ui->cur_event == NULL);
+ }
+ flush_event(ui);
+ ui->cur_event = name;
+ ui->ncalls_pos = mpack_array_dyn16(buf);
+ mpack_str_small(buf, name, strlen(name));
+ ui->nevents++;
+ ui->ncalls = 1;
+ } else {
+ ui->ncalls++;
}
-
- return false;
}
-/// Pushes data into UI.UIData, to be consumed later by remote_ui_flush().
-static void push_call(UI *ui, const char *name, Array args)
+/// Pushes data into RemoteUI, to be consumed later by remote_ui_flush().
+static void push_call(RemoteUI *ui, const char *name, Array args)
{
- UIData *data = ui->data;
- bool pending = data->nevents_pos;
- char *buf_pos_save = data->buf_wptr;
-
- bool new_event = prepare_call(ui, name);
-
- msgpack_packer pac;
- data->pack_totlen = 0;
- data->buf_overflow = false;
- msgpack_packer_init(&pac, data, write_cb);
- msgpack_rpc_from_array(args, &pac);
- if (data->buf_overflow) {
- data->buf_wptr = buf_pos_save;
- if (new_event) {
- data->cur_event = NULL;
- data->nevents--;
- }
- if (pending) {
- remote_ui_flush_buf(ui);
- }
+ prepare_call(ui, name);
+ mpack_object_array(args, &ui->packer);
+}
- if (data->pack_totlen > UI_BUF_SIZE - strlen(name) - 20) {
- // TODO(bfredl): manually testable by setting UI_BUF_SIZE to 1024 (mode_info_set)
- data->temp_buf = xmalloc(20 + strlen(name) + data->pack_totlen);
- data->buf_wptr = data->temp_buf;
- char **buf = &data->buf_wptr;
- mpack_array(buf, 3);
- mpack_uint(buf, 2);
- mpack_str(buf, "redraw");
- mpack_array(buf, 1);
- mpack_array(buf, 2);
- mpack_str(buf, name);
- } else {
- prepare_call(ui, name);
- }
- data->pack_totlen = 0;
- data->buf_overflow = false;
- msgpack_rpc_from_array(args, &pac);
-
- if (data->temp_buf) {
- size_t size = (size_t)(data->buf_wptr - data->temp_buf);
- WBuffer *buf = wstream_new_buffer(data->temp_buf, size, 1, xfree);
- rpc_write_raw(data->channel_id, buf);
- data->temp_buf = NULL;
- data->buf_wptr = data->buf;
- data->nevents_pos = NULL;
- }
- }
- data->ncalls++;
+static void ui_flush_callback(PackerBuffer *packer)
+{
+ RemoteUI *ui = packer->anydata;
+ ui_flush_buf(ui);
+ ui_alloc_buf(ui);
}
-void remote_ui_grid_clear(UI *ui, Integer grid)
+void remote_ui_grid_clear(RemoteUI *ui, Integer grid)
{
- UIData *data = ui->data;
- Array args = data->call_buf;
+ Array args = ui->call_buf;
if (ui->ui_ext[kUILinegrid]) {
ADD_C(args, INTEGER_OBJ(grid));
}
@@ -666,14 +590,13 @@ void remote_ui_grid_clear(UI *ui, Integer grid)
push_call(ui, name, args);
}
-void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height)
+void remote_ui_grid_resize(RemoteUI *ui, Integer grid, Integer width, Integer height)
{
- UIData *data = ui->data;
- Array args = data->call_buf;
+ Array args = ui->call_buf;
if (ui->ui_ext[kUILinegrid]) {
ADD_C(args, INTEGER_OBJ(grid));
} else {
- data->client_col = -1; // force cursor update
+ ui->client_col = -1; // force cursor update
}
ADD_C(args, INTEGER_OBJ(width));
ADD_C(args, INTEGER_OBJ(height));
@@ -681,12 +604,11 @@ void remote_ui_grid_resize(UI *ui, Integer grid, Integer width, Integer height)
push_call(ui, name, args);
}
-void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integer left,
+void remote_ui_grid_scroll(RemoteUI *ui, Integer grid, Integer top, Integer bot, Integer left,
Integer right, Integer rows, Integer cols)
{
- UIData *data = ui->data;
if (ui->ui_ext[kUILinegrid]) {
- Array args = data->call_buf;
+ Array args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(grid));
ADD_C(args, INTEGER_OBJ(top));
ADD_C(args, INTEGER_OBJ(bot));
@@ -696,20 +618,20 @@ void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integ
ADD_C(args, INTEGER_OBJ(cols));
push_call(ui, "grid_scroll", args);
} else {
- Array args = data->call_buf;
+ Array args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(top));
ADD_C(args, INTEGER_OBJ(bot - 1));
ADD_C(args, INTEGER_OBJ(left));
ADD_C(args, INTEGER_OBJ(right - 1));
push_call(ui, "set_scroll_region", args);
- args = data->call_buf;
+ args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(rows));
push_call(ui, "scroll", args);
// some clients have "clear" being affected by scroll region,
// so reset it.
- args = data->call_buf;
+ args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(0));
ADD_C(args, INTEGER_OBJ(ui->height - 1));
ADD_C(args, INTEGER_OBJ(0));
@@ -718,14 +640,13 @@ void remote_ui_grid_scroll(UI *ui, Integer grid, Integer top, Integer bot, Integ
}
}
-void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
+void remote_ui_default_colors_set(RemoteUI *ui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
Integer cterm_fg, Integer cterm_bg)
{
if (!ui->ui_ext[kUITermColors]) {
HL_SET_DEFAULT_COLORS(rgb_fg, rgb_bg, rgb_sp);
}
- UIData *data = ui->data;
- Array args = data->call_buf;
+ Array args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(rgb_fg));
ADD_C(args, INTEGER_OBJ(rgb_bg));
ADD_C(args, INTEGER_OBJ(rgb_sp));
@@ -735,34 +656,41 @@ void remote_ui_default_colors_set(UI *ui, Integer rgb_fg, Integer rgb_bg, Intege
// Deprecated
if (!ui->ui_ext[kUILinegrid]) {
- args = data->call_buf;
+ args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_fg : cterm_fg - 1));
push_call(ui, "update_fg", args);
- args = data->call_buf;
+ args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_bg : cterm_bg - 1));
push_call(ui, "update_bg", args);
- args = data->call_buf;
+ args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(ui->rgb ? rgb_sp : -1));
push_call(ui, "update_sp", args);
}
}
-void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs,
+void remote_ui_hl_attr_define(RemoteUI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cterm_attrs,
Array info)
{
if (!ui->ui_ext[kUILinegrid]) {
return;
}
- UIData *data = ui->data;
- Array args = data->call_buf;
+ Array args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(id));
MAXSIZE_TEMP_DICT(rgb, HLATTRS_DICT_SIZE);
MAXSIZE_TEMP_DICT(cterm, HLATTRS_DICT_SIZE);
hlattrs2dict(&rgb, NULL, rgb_attrs, true, false);
hlattrs2dict(&cterm, NULL, rgb_attrs, false, false);
+
+ // URLs are not added in hlattrs2dict since they are used only by UIs and not by the highlight
+ // system. So we add them here.
+ if (rgb_attrs.url >= 0) {
+ const char *url = hl_get_url((uint32_t)rgb_attrs.url);
+ PUT_C(rgb, "url", CSTR_AS_OBJ(url));
+ }
+
ADD_C(args, DICTIONARY_OBJ(rgb));
ADD_C(args, DICTIONARY_OBJ(cterm));
@@ -775,15 +703,14 @@ void remote_ui_hl_attr_define(UI *ui, Integer id, HlAttrs rgb_attrs, HlAttrs cte
push_call(ui, "hl_attr_define", args);
}
-void remote_ui_highlight_set(UI *ui, int id)
+void remote_ui_highlight_set(RemoteUI *ui, int id)
{
- UIData *data = ui->data;
- Array args = data->call_buf;
+ Array args = ui->call_buf;
- if (data->hl_id == id) {
+ if (ui->hl_id == id) {
return;
}
- data->hl_id = id;
+ ui->hl_id = id;
MAXSIZE_TEMP_DICT(dict, HLATTRS_DICT_SIZE);
hlattrs2dict(&dict, NULL, syn_attr2entry(id), ui->rgb, false);
ADD_C(args, DICTIONARY_OBJ(dict));
@@ -791,57 +718,55 @@ void remote_ui_highlight_set(UI *ui, int id)
}
/// "true" cursor used only for input focus
-void remote_ui_grid_cursor_goto(UI *ui, Integer grid, Integer row, Integer col)
+void remote_ui_grid_cursor_goto(RemoteUI *ui, Integer grid, Integer row, Integer col)
{
if (ui->ui_ext[kUILinegrid]) {
- UIData *data = ui->data;
- Array args = data->call_buf;
+ Array args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(grid));
ADD_C(args, INTEGER_OBJ(row));
ADD_C(args, INTEGER_OBJ(col));
push_call(ui, "grid_cursor_goto", args);
} else {
- UIData *data = ui->data;
- data->cursor_row = row;
- data->cursor_col = col;
+ ui->cursor_row = row;
+ ui->cursor_col = col;
remote_ui_cursor_goto(ui, row, col);
}
}
/// emulated cursor used both for drawing and for input focus
-void remote_ui_cursor_goto(UI *ui, Integer row, Integer col)
+void remote_ui_cursor_goto(RemoteUI *ui, Integer row, Integer col)
{
- UIData *data = ui->data;
- if (data->client_row == row && data->client_col == col) {
+ if (ui->client_row == row && ui->client_col == col) {
return;
}
- data->client_row = row;
- data->client_col = col;
- Array args = data->call_buf;
+ ui->client_row = row;
+ ui->client_col = col;
+ Array args = ui->call_buf;
ADD_C(args, INTEGER_OBJ(row));
ADD_C(args, INTEGER_OBJ(col));
push_call(ui, "cursor_goto", args);
}
-void remote_ui_put(UI *ui, const char *cell)
+void remote_ui_put(RemoteUI *ui, const char *cell)
{
- UIData *data = ui->data;
- data->client_col++;
- Array args = data->call_buf;
- ADD_C(args, CSTR_AS_OBJ((char *)cell));
+ ui->client_col++;
+ Array args = ui->call_buf;
+ ADD_C(args, CSTR_AS_OBJ(cell));
push_call(ui, "put", args);
}
-void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Integer endcol,
+void remote_ui_raw_line(RemoteUI *ui, Integer grid, Integer row, Integer startcol, Integer endcol,
Integer clearcol, Integer clearattr, LineFlags flags, const schar_T *chunk,
const sattr_T *attrs)
{
- UIData *data = ui->data;
+ // If MAX_SCHAR_SIZE is made larger, we need to refactor implementation below
+ // to not only use FIXSTR (only up to 0x20 bytes)
+ STATIC_ASSERT(MAX_SCHAR_SIZE - 1 < 0x20, "SCHAR doesn't fit in fixstr");
+
if (ui->ui_ext[kUILinegrid]) {
prepare_call(ui, "grid_line");
- data->ncalls++;
- char **buf = &data->buf_wptr;
+ char **buf = &ui->packer.ptr;
mpack_array(buf, 5);
mpack_uint(buf, (uint32_t)grid);
mpack_uint(buf, (uint32_t)row);
@@ -856,7 +781,7 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
for (size_t i = 0; i < ncells; i++) {
repeat++;
if (i == ncells - 1 || attrs[i] != attrs[i + 1] || chunk[i] != chunk[i + 1]) {
- if (UI_BUF_SIZE - BUF_POS(data) < 2 * (1 + 2 + sizeof(schar_T) + 5 + 5) + 1) {
+ if (UI_BUF_SIZE - BUF_POS(ui) < 2 * (1 + 2 + sizeof(schar_T) + 5 + 5) + 1) {
// close to overflowing the redraw buffer. finish this event,
// flush, and start a new "grid_line" event at the current position.
// For simplicity leave place for the final "clear" element
@@ -865,10 +790,9 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
// We only ever set the wrap field on the final "grid_line" event for the line.
mpack_bool(buf, false);
- remote_ui_flush_buf(ui);
+ ui_flush_buf(ui);
prepare_call(ui, "grid_line");
- data->ncalls++;
mpack_array(buf, 5);
mpack_uint(buf, (uint32_t)grid);
mpack_uint(buf, (uint32_t)row);
@@ -880,16 +804,16 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
uint32_t csize = (repeat > 1) ? 3 : ((attrs[i] != last_hl) ? 2 : 1);
nelem++;
mpack_array(buf, csize);
- char sc_buf[MAX_SCHAR_SIZE];
- schar_get(sc_buf, chunk[i]);
- mpack_str(buf, sc_buf);
+ char *size_byte = (*buf)++;
+ size_t len = schar_get_adv(buf, chunk[i]);
+ *size_byte = (char)(0xa0 | len);
if (csize >= 2) {
mpack_uint(buf, (uint32_t)attrs[i]);
if (csize >= 3) {
mpack_uint(buf, repeat);
}
}
- data->ncells_pending += MIN(repeat, 2);
+ ui->ncells_pending += MIN(repeat, 2);
last_hl = attrs[i];
repeat = 0;
was_space = chunk[i] == schar_from_ascii(' ');
@@ -899,18 +823,18 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
// no more cells to clear, so there is no ambiguity about what to clear.
if (endcol < clearcol || was_space) {
nelem++;
- data->ncells_pending += 1;
+ ui->ncells_pending += 1;
mpack_array(buf, 3);
- mpack_str(buf, " ");
+ mpack_str_small(buf, S_LEN(" "));
mpack_uint(buf, (uint32_t)clearattr);
mpack_uint(buf, (uint32_t)(clearcol - endcol));
}
mpack_w2(&lenpos, nelem);
mpack_bool(buf, flags & kLineFlagWrap);
- if (data->ncells_pending > 500) {
+ if (ui->ncells_pending > 500) {
// pass off cells to UI to let it start processing them
- remote_ui_flush_buf(ui);
+ ui_flush_buf(ui);
}
} else {
for (int i = 0; i < endcol - startcol; i++) {
@@ -920,7 +844,7 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
schar_get(sc_buf, chunk[i]);
remote_ui_put(ui, sc_buf);
if (utf_ambiguous_width(utf_ptr2char(sc_buf))) {
- data->client_col = -1; // force cursor update
+ ui->client_col = -1; // force cursor update
}
}
if (endcol < clearcol) {
@@ -944,49 +868,47 @@ void remote_ui_raw_line(UI *ui, Integer grid, Integer row, Integer startcol, Int
///
/// This might happen multiple times before the actual ui_flush, if the
/// total redraw size is large!
-void remote_ui_flush_buf(UI *ui)
+static void ui_flush_buf(RemoteUI *ui)
{
- UIData *data = ui->data;
- if (!data->nevents_pos) {
+ if (!ui->packer.startptr || !BUF_POS(ui)) {
return;
}
- if (data->cur_event) {
- flush_event(data);
+
+ flush_event(ui);
+ if (ui->nevents_pos != NULL) {
+ mpack_w2(&ui->nevents_pos, ui->nevents);
+ ui->nevents = 0;
+ ui->nevents_pos = NULL;
}
- mpack_w2(&data->nevents_pos, data->nevents);
- data->nevents = 0;
- data->nevents_pos = NULL;
-
- // TODO(bfredl): elide copy by a length one free-list like the arena
- size_t size = BUF_POS(data);
- WBuffer *buf = wstream_new_buffer(xmemdup(data->buf, size), size, 1, xfree);
- rpc_write_raw(data->channel_id, buf);
- data->buf_wptr = data->buf;
- // we have sent events to the client, but possibly not yet the final "flush"
- // event.
- data->flushed_events = true;
-
- data->ncells_pending = 0;
+
+ WBuffer *buf = wstream_new_buffer(ui->packer.startptr, BUF_POS(ui), 1, free_block);
+ rpc_write_raw(ui->channel_id, buf);
+
+ ui->packer.startptr = NULL;
+ ui->packer.ptr = NULL;
+
+ // we have sent events to the client, but possibly not yet the final "flush" event.
+ ui->flushed_events = true;
+ ui->ncells_pending = 0;
}
/// An intentional flush (vsync) when Nvim is finished redrawing the screen
///
/// Clients can know this happened by a final "flush" event at the end of the
/// "redraw" batch.
-void remote_ui_flush(UI *ui)
+void remote_ui_flush(RemoteUI *ui)
{
- UIData *data = ui->data;
- if (data->nevents > 0 || data->flushed_events) {
+ if (ui->nevents > 0 || ui->flushed_events) {
if (!ui->ui_ext[kUILinegrid]) {
- remote_ui_cursor_goto(ui, data->cursor_row, data->cursor_col);
+ remote_ui_cursor_goto(ui, ui->cursor_row, ui->cursor_col);
}
push_call(ui, "flush", (Array)ARRAY_DICT_INIT);
- remote_ui_flush_buf(ui);
- data->flushed_events = false;
+ ui_flush_buf(ui);
+ ui->flushed_events = false;
}
}
-static Array translate_contents(UI *ui, Array contents, Arena *arena)
+static Array translate_contents(RemoteUI *ui, Array contents, Arena *arena)
{
Array new_contents = arena_array(arena, contents.size);
for (size_t i = 0; i < contents.size; i++) {
@@ -996,32 +918,31 @@ static Array translate_contents(UI *ui, Array contents, Arena *arena)
if (attr) {
Dictionary rgb_attrs = arena_dict(arena, HLATTRS_DICT_SIZE);
hlattrs2dict(&rgb_attrs, NULL, syn_attr2entry(attr), ui->rgb, false);
- ADD(new_item, DICTIONARY_OBJ(rgb_attrs));
+ ADD_C(new_item, DICTIONARY_OBJ(rgb_attrs));
} else {
- ADD(new_item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
+ ADD_C(new_item, DICTIONARY_OBJ((Dictionary)ARRAY_DICT_INIT));
}
- ADD(new_item, item.items[1]);
- ADD(new_contents, ARRAY_OBJ(new_item));
+ ADD_C(new_item, item.items[1]);
+ ADD_C(new_contents, ARRAY_OBJ(new_item));
}
return new_contents;
}
-static Array translate_firstarg(UI *ui, Array args, Arena *arena)
+static Array translate_firstarg(RemoteUI *ui, Array args, Arena *arena)
{
Array new_args = arena_array(arena, args.size);
Array contents = args.items[0].data.array;
ADD_C(new_args, ARRAY_OBJ(translate_contents(ui, contents, arena)));
for (size_t i = 1; i < args.size; i++) {
- ADD(new_args, args.items[i]);
+ ADD_C(new_args, args.items[i]);
}
return new_args;
}
-void remote_ui_event(UI *ui, char *name, Array args)
+void remote_ui_event(RemoteUI *ui, char *name, Array args)
{
Arena arena = ARENA_EMPTY;
- UIData *data = ui->data;
if (!ui->ui_ext[kUILinegrid]) {
// the representation of highlights in cmdline changed, translate back
// never consumes args
@@ -1030,7 +951,7 @@ void remote_ui_event(UI *ui, char *name, Array args)
push_call(ui, name, new_args);
goto free_ret;
} else if (strequal(name, "cmdline_block_show")) {
- Array new_args = data->call_buf;
+ Array new_args = ui->call_buf;
Array block = args.items[0].data.array;
Array new_block = arena_array(&arena, block.size);
for (size_t i = 0; i < block.size; i++) {
@@ -1049,10 +970,10 @@ void remote_ui_event(UI *ui, char *name, Array args)
// Back-compat: translate popupmenu_xx to legacy wildmenu_xx.
if (ui->ui_ext[kUIWildmenu]) {
if (strequal(name, "popupmenu_show")) {
- data->wildmenu_active = (args.items[4].data.integer == -1)
- || !ui->ui_ext[kUIPopupmenu];
- if (data->wildmenu_active) {
- Array new_args = data->call_buf;
+ ui->wildmenu_active = (args.items[4].data.integer == -1)
+ || !ui->ui_ext[kUIPopupmenu];
+ if (ui->wildmenu_active) {
+ Array new_args = ui->call_buf;
Array items = args.items[0].data.array;
Array new_items = arena_array(&arena, items.size);
for (size_t i = 0; i < items.size; i++) {
@@ -1061,18 +982,18 @@ void remote_ui_event(UI *ui, char *name, Array args)
ADD_C(new_args, ARRAY_OBJ(new_items));
push_call(ui, "wildmenu_show", new_args);
if (args.items[1].data.integer != -1) {
- Array new_args2 = data->call_buf;
+ Array new_args2 = ui->call_buf;
ADD_C(new_args2, args.items[1]);
push_call(ui, "wildmenu_select", new_args2);
}
goto free_ret;
}
} else if (strequal(name, "popupmenu_select")) {
- if (data->wildmenu_active) {
+ if (ui->wildmenu_active) {
name = "wildmenu_select";
}
} else if (strequal(name, "popupmenu_hide")) {
- if (data->wildmenu_active) {
+ if (ui->wildmenu_active) {
name = "wildmenu_hide";
}
}
@@ -1084,9 +1005,3 @@ void remote_ui_event(UI *ui, char *name, Array args)
free_ret:
arena_mem_free(arena_finish(&arena));
}
-
-void remote_ui_inspect(UI *ui, Dictionary *info)
-{
- UIData *data = ui->data;
- PUT(*info, "chan", INTEGER_OBJ((Integer)data->channel_id));
-}
diff --git a/src/nvim/api/ui.h b/src/nvim/api/ui.h
index 26a91d0dbc..cdccc27ba4 100644
--- a/src/nvim/api/ui.h
+++ b/src/nvim/api/ui.h
@@ -4,11 +4,24 @@
#include "nvim/api/private/defs.h" // IWYU pragma: keep
#include "nvim/highlight_defs.h" // IWYU pragma: keep
-#include "nvim/map_defs.h"
#include "nvim/types_defs.h" // IWYU pragma: keep
-#include "nvim/ui.h"
+#include "nvim/ui_defs.h" // IWYU pragma: keep
+
+/// Keep in sync with UIExtension in ui_defs.h
+EXTERN const char *ui_ext_names[] INIT( = {
+ "ext_cmdline",
+ "ext_popupmenu",
+ "ext_tabline",
+ "ext_wildmenu",
+ "ext_messages",
+ "ext_linegrid",
+ "ext_multigrid",
+ "ext_hlstate",
+ "ext_termcolors",
+ "_debug_float",
+});
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/ui.h.generated.h"
-# include "ui_events_remote.h.generated.h" // IWYU pragma: export
+# include "ui_events_remote.h.generated.h"
#endif
diff --git a/src/nvim/api/ui_events.in.h b/src/nvim/api/ui_events.in.h
index bda0c72423..c2f02c34f8 100644
--- a/src/nvim/api/ui_events.in.h
+++ b/src/nvim/api/ui_events.in.h
@@ -39,6 +39,8 @@ void screenshot(String path)
FUNC_API_SINCE(7);
void option_set(String name, Object value)
FUNC_API_SINCE(4);
+void chdir(String path)
+ FUNC_API_SINCE(12);
// Stop event is not exported as such, represented by EOF in the msgpack stream.
void stop(void)
FUNC_API_NOEXPORT;
diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c
index d631b10af9..84a2f24dbc 100644
--- a/src/nvim/api/vim.c
+++ b/src/nvim/api/vim.c
@@ -21,21 +21,26 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/channel.h"
+#include "nvim/channel_defs.h"
#include "nvim/context.h"
#include "nvim/cursor.h"
#include "nvim/decoration.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
+#include "nvim/getchar_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/keycodes.h"
#include "nvim/log.h"
@@ -43,25 +48,33 @@
#include "nvim/macros_defs.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
+#include "nvim/message_defs.h"
#include "nvim/move.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/msgpack_rpc/unpacker.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/input.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/process.h"
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
#include "nvim/runtime.h"
-#include "nvim/sign.h"
+#include "nvim/sign_defs.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/statusline.h"
+#include "nvim/statusline_defs.h"
#include "nvim/strings.h"
#include "nvim/terminal.h"
#include "nvim/types_defs.h"
@@ -110,7 +123,7 @@ Dictionary nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, E
///
/// @note Unlike the `:highlight` command which can update a highlight group,
/// this function completely replaces the definition. For example:
-/// ``nvim_set_hl(0, 'Visual', {})`` will clear the highlight group
+/// `nvim_set_hl(0, 'Visual', {})` will clear the highlight group
/// 'Visual'.
///
/// @note The fg and bg keys also accept the string values `"fg"` or `"bg"`
@@ -128,9 +141,9 @@ Dictionary nvim_get_hl(Integer ns_id, Dict(get_highlight) *opts, Arena *arena, E
/// |nvim_set_hl_ns()| or |nvim_win_set_hl_ns()| to activate them.
/// @param name Highlight group name, e.g. "ErrorMsg"
/// @param val Highlight definition map, accepts the following keys:
-/// - fg (or foreground): color name or "#RRGGBB", see note.
-/// - bg (or background): color name or "#RRGGBB", see note.
-/// - sp (or special): color name or "#RRGGBB"
+/// - fg: color name or "#RRGGBB", see note.
+/// - bg: color name or "#RRGGBB", see note.
+/// - sp: color name or "#RRGGBB"
/// - blend: integer between 0 and 100
/// - bold: boolean
/// - standout: boolean
@@ -163,6 +176,12 @@ void nvim_set_hl(Integer ns_id, String name, Dict(highlight) *val, Error *err)
});
int link_id = -1;
+ // Setting URLs directly through highlight attributes is not supported
+ if (HAS_KEY(val, highlight, url)) {
+ api_free_string(val->url);
+ val->url = NULL_STRING;
+ }
+
HlAttrs attrs = dict2hlattrs(val, true, &link_id, err);
if (!ERROR_SET(err)) {
ns_hl_def((NS)ns_id, hl_id, attrs, link_id, val);
@@ -230,7 +249,7 @@ void nvim_set_hl_ns_fast(Integer ns_id, Error *err)
///
/// On execution error: does not fail, but updates v:errmsg.
///
-/// To input sequences like <C-o> use |nvim_replace_termcodes()| (typically
+/// To input sequences like [<C-o>] use |nvim_replace_termcodes()| (typically
/// with escape_ks=false) to replace |keycodes|, then pass the result to
/// nvim_feedkeys().
///
@@ -318,11 +337,11 @@ void nvim_feedkeys(String keys, String mode, Boolean escape_ks)
///
/// On execution error: does not fail, but updates v:errmsg.
///
-/// @note |keycodes| like <CR> are translated, so "<" is special.
-/// To input a literal "<", send <LT>.
+/// @note |keycodes| like [<CR>] are translated, so "<" is special.
+/// To input a literal "<", send [<LT>].
///
/// @note For mouse events use |nvim_input_mouse()|. The pseudokey form
-/// "<LeftMouse><col,row>" is deprecated since |api-level| 6.
+/// `<LeftMouse><col,row>` is deprecated since |api-level| 6.
///
/// @param keys to be typed
/// @return Number of bytes actually written (can be fewer than
@@ -343,9 +362,10 @@ Integer nvim_input(String keys)
/// by calling it multiple times in a loop: the intermediate mouse
/// positions will be ignored. It should be used to implement real-time
/// mouse input in a GUI. The deprecated pseudokey form
-/// ("<LeftMouse><col,row>") of |nvim_input()| has the same limitation.
+/// (`<LeftMouse><col,row>`) of |nvim_input()| has the same limitation.
///
-/// @param button Mouse button: one of "left", "right", "middle", "wheel", "move".
+/// @param button Mouse button: one of "left", "right", "middle", "wheel", "move",
+/// "x1", "x2".
/// @param action For ordinary buttons, one of "press", "drag", "release".
/// For the wheel, one of "up", "down", "left", "right". Ignored for "move".
/// @param modifier String of modifiers each represented by a single char.
@@ -376,6 +396,10 @@ void nvim_input_mouse(String button, String action, String modifier, Integer gri
code = KE_RIGHTMOUSE;
} else if (strequal(button.data, "wheel")) {
code = KE_MOUSEDOWN;
+ } else if (strequal(button.data, "x1")) {
+ code = KE_X1MOUSE;
+ } else if (strequal(button.data, "x2")) {
+ code = KE_X2MOUSE;
} else if (strequal(button.data, "move")) {
code = KE_MOUSEMOVE;
} else {
@@ -427,17 +451,17 @@ error:
"invalid button or action");
}
-/// Replaces terminal codes and |keycodes| (<CR>, <Esc>, ...) in a string with
+/// Replaces terminal codes and |keycodes| ([<CR>], [<Esc>], ...) in a string with
/// the internal representation.
///
/// @param str String to be converted.
/// @param from_part Legacy Vim parameter. Usually true.
-/// @param do_lt Also translate <lt>. Ignored if `special` is false.
-/// @param special Replace |keycodes|, e.g. <CR> becomes a "\r" char.
+/// @param do_lt Also translate [<lt>]. Ignored if `special` is false.
+/// @param special Replace |keycodes|, e.g. [<CR>] becomes a "\r" char.
/// @see replace_termcodes
/// @see cpoptions
String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Boolean special)
- FUNC_API_SINCE(1)
+ FUNC_API_SINCE(1) FUNC_API_RET_ALLOC
{
if (str.size == 0) {
// Empty string
@@ -456,7 +480,7 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Bool
}
char *ptr = NULL;
- replace_termcodes(str.data, str.size, &ptr, 0, flags, NULL, CPO_TO_CPO_FLAGS);
+ replace_termcodes(str.data, str.size, &ptr, 0, flags, NULL, p_cpo);
return cstr_as_string(ptr);
}
@@ -472,11 +496,12 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, Bool
/// or executing the Lua code.
///
/// @return Return value of Lua code if present or NIL.
-Object nvim_exec_lua(String code, Array args, Error *err)
+Object nvim_exec_lua(String code, Array args, Arena *arena, Error *err)
FUNC_API_SINCE(7)
FUNC_API_REMOTE_ONLY
{
- return nlua_exec(code, args, err);
+ // TODO(bfredl): convert directly from msgpack to lua and then back again
+ return nlua_exec(code, args, kRetObject, arena, err);
}
/// Notify the user with a message
@@ -488,7 +513,7 @@ Object nvim_exec_lua(String code, Array args, Error *err)
/// @param log_level The log level
/// @param opts Reserved for future use.
/// @param[out] err Error details, if any
-Object nvim_notify(String msg, Integer log_level, Dictionary opts, Error *err)
+Object nvim_notify(String msg, Integer log_level, Dictionary opts, Arena *arena, Error *err)
FUNC_API_SINCE(7)
{
MAXSIZE_TEMP_ARRAY(args, 3);
@@ -496,11 +521,11 @@ Object nvim_notify(String msg, Integer log_level, Dictionary opts, Error *err)
ADD_C(args, INTEGER_OBJ(log_level));
ADD_C(args, DICTIONARY_OBJ(opts));
- return NLUA_EXEC_STATIC("return vim.notify(...)", args, err);
+ return NLUA_EXEC_STATIC("return vim.notify(...)", args, kRetObject, arena, err);
}
/// Calculates the number of display cells occupied by `text`.
-/// Control characters including <Tab> count as one cell.
+/// Control characters including [<Tab>] count as one cell.
///
/// @param text Some text
/// @param[out] err Error details, if any
@@ -518,17 +543,23 @@ Integer nvim_strwidth(String text, Error *err)
/// Gets the paths contained in |runtime-search-path|.
///
/// @return List of paths
-ArrayOf(String) nvim_list_runtime_paths(Error *err)
+ArrayOf(String) nvim_list_runtime_paths(Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
- return nvim_get_runtime_file(NULL_STRING, true, err);
+ return nvim_get_runtime_file(NULL_STRING, true, arena, err);
}
-Array nvim__runtime_inspect(void)
+/// @nodoc
+Array nvim__runtime_inspect(Arena *arena)
{
- return runtime_inspect();
+ return runtime_inspect(arena);
}
+typedef struct {
+ ArrayBuilder rv;
+ Arena *arena;
+} RuntimeCookie;
+
/// Find files in runtime directories
///
/// "name" can contain wildcards. For example
@@ -541,25 +572,27 @@ Array nvim__runtime_inspect(void)
/// @param name pattern of files to search for
/// @param all whether to return all matches or only the first
/// @return list of absolute paths to the found files
-ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Error *err)
+ArrayOf(String) nvim_get_runtime_file(String name, Boolean all, Arena *arena, Error *err)
FUNC_API_SINCE(7)
FUNC_API_FAST
{
- Array rv = ARRAY_DICT_INIT;
+ RuntimeCookie cookie = { .rv = ARRAY_DICT_INIT, .arena = arena, };
+ kvi_init(cookie.rv);
int flags = DIP_DIRFILE | (all ? DIP_ALL : 0);
TRY_WRAP(err, {
- do_in_runtimepath((name.size ? name.data : ""), flags, find_runtime_cb, &rv);
+ do_in_runtimepath((name.size ? name.data : ""), flags, find_runtime_cb, &cookie);
});
- return rv;
+ return arena_take_arraybuilder(arena, &cookie.rv);
}
-static bool find_runtime_cb(int num_fnames, char **fnames, bool all, void *cookie)
+static bool find_runtime_cb(int num_fnames, char **fnames, bool all, void *c)
{
- Array *rv = (Array *)cookie;
+ RuntimeCookie *cookie = (RuntimeCookie *)c;
for (int i = 0; i < num_fnames; i++) {
- ADD(*rv, CSTR_TO_OBJ(fnames[i]));
+ // TODO(bfredl): consider memory management of gen_expand_wildcards() itself
+ kvi_push(cookie->rv, CSTR_TO_ARENA_OBJ(cookie->arena, fnames[i]));
if (!all) {
return true;
}
@@ -568,7 +601,9 @@ static bool find_runtime_cb(int num_fnames, char **fnames, bool all, void *cooki
return num_fnames > 0;
}
+/// @nodoc
String nvim__get_lib_dir(void)
+ FUNC_API_RET_ALLOC
{
return cstr_as_string(get_lib_dir());
}
@@ -579,7 +614,8 @@ String nvim__get_lib_dir(void)
/// @param all whether to return all matches or only the first
/// @param opts is_lua: only search Lua subdirs
/// @return list of absolute paths to the found files
-ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, Error *err)
+ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, Arena *arena,
+ Error *err)
FUNC_API_SINCE(8)
FUNC_API_FAST
{
@@ -589,12 +625,12 @@ ArrayOf(String) nvim__get_runtime(Array pat, Boolean all, Dict(runtime) *opts, E
return (Array)ARRAY_DICT_INIT;
}
- ArrayOf(String) res = runtime_get_named(opts->is_lua, pat, all);
+ ArrayOf(String) res = runtime_get_named(opts->is_lua, pat, all, arena);
if (opts->do_source) {
for (size_t i = 0; i < res.size; i++) {
String name = res.items[i].data.string;
- (void)do_source(name.data, false, DOSO_NONE, NULL);
+ do_source(name.data, false, DOSO_NONE, NULL);
}
}
@@ -632,31 +668,31 @@ void nvim_set_current_dir(String dir, Error *err)
///
/// @param[out] err Error details, if any
/// @return Current line string
-String nvim_get_current_line(Error *err)
+String nvim_get_current_line(Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
- return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, err);
+ return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, arena, err);
}
/// Sets the current line.
///
/// @param line Line contents
/// @param[out] err Error details, if any
-void nvim_set_current_line(String line, Error *err)
+void nvim_set_current_line(String line, Arena *arena, Error *err)
FUNC_API_SINCE(1)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
- buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, err);
+ buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, arena, err);
}
/// Deletes the current line.
///
/// @param[out] err Error details, if any
-void nvim_del_current_line(Error *err)
+void nvim_del_current_line(Arena *arena, Error *err)
FUNC_API_SINCE(1)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
- buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, err);
+ buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, arena, err);
}
/// Gets a global (g:) variable.
@@ -664,7 +700,7 @@ void nvim_del_current_line(Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Variable value
-Object nvim_get_var(String name, Error *err)
+Object nvim_get_var(String name, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
dictitem_T *di = tv_dict_find(&globvardict, name.data, (ptrdiff_t)name.size);
@@ -678,7 +714,7 @@ Object nvim_get_var(String name, Error *err)
VALIDATE((di != NULL), "Key not found: %s", name.data, {
return (Object)OBJECT_INIT;
});
- return vim_to_object(&di->di_tv);
+ return vim_to_object(&di->di_tv, arena, true);
}
/// Sets a global (g:) variable.
@@ -689,7 +725,7 @@ Object nvim_get_var(String name, Error *err)
void nvim_set_var(String name, Object value, Error *err)
FUNC_API_SINCE(1)
{
- dict_set_var(&globvardict, name, value, false, false, err);
+ dict_set_var(&globvardict, name, value, false, false, NULL, err);
}
/// Removes a global (g:) variable.
@@ -699,7 +735,7 @@ void nvim_set_var(String name, Object value, Error *err)
void nvim_del_var(String name, Error *err)
FUNC_API_SINCE(1)
{
- dict_set_var(&globvardict, name, NIL, true, false, err);
+ dict_set_var(&globvardict, name, NIL, true, false, NULL, err);
}
/// Gets a v: variable.
@@ -707,10 +743,10 @@ void nvim_del_var(String name, Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Variable value
-Object nvim_get_vvar(String name, Error *err)
+Object nvim_get_vvar(String name, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
- return dict_get_value(&vimvardict, name, err);
+ return dict_get_value(&vimvardict, name, arena, err);
}
/// Sets a v: variable, if it is not readonly.
@@ -721,12 +757,12 @@ Object nvim_get_vvar(String name, Error *err)
void nvim_set_vvar(String name, Object value, Error *err)
FUNC_API_SINCE(6)
{
- dict_set_var(&vimvardict, name, value, false, false, err);
+ dict_set_var(&vimvardict, name, value, false, false, NULL, err);
}
/// Echo a message.
///
-/// @param chunks A list of [text, hl_group] arrays, each representing a
+/// @param chunks A list of `[text, hl_group]` arrays, each representing a
/// text chunk with specified highlight. `hl_group` element
/// can be omitted for no highlight.
/// @param history if true, add to |message-history|.
@@ -799,20 +835,19 @@ void nvim_err_writeln(String str)
/// Use |nvim_buf_is_loaded()| to check if a buffer is loaded.
///
/// @return List of buffer handles
-ArrayOf(Buffer) nvim_list_bufs(void)
+ArrayOf(Buffer) nvim_list_bufs(Arena *arena)
FUNC_API_SINCE(1)
{
- Array rv = ARRAY_DICT_INIT;
+ size_t n = 0;
FOR_ALL_BUFFERS(b) {
- rv.size++;
+ n++;
}
- rv.items = xmalloc(sizeof(Object) * rv.size);
- size_t i = 0;
+ Array rv = arena_array(arena, n);
FOR_ALL_BUFFERS(b) {
- rv.items[i++] = BUFFER_OBJ(b->handle);
+ ADD_C(rv, BUFFER_OBJ(b->handle));
}
return rv;
@@ -854,20 +889,19 @@ void nvim_set_current_buf(Buffer buffer, Error *err)
/// Gets the current list of window handles.
///
/// @return List of window handles
-ArrayOf(Window) nvim_list_wins(void)
+ArrayOf(Window) nvim_list_wins(Arena *arena)
FUNC_API_SINCE(1)
{
- Array rv = ARRAY_DICT_INIT;
+ size_t n = 0;
FOR_ALL_TAB_WINDOWS(tp, wp) {
- rv.size++;
+ n++;
}
- rv.items = xmalloc(sizeof(Object) * rv.size);
- size_t i = 0;
+ Array rv = arena_array(arena, n);
FOR_ALL_TAB_WINDOWS(tp, wp) {
- rv.items[i++] = WINDOW_OBJ(wp->handle);
+ ADD_C(rv, WINDOW_OBJ(wp->handle));
}
return rv;
@@ -949,8 +983,8 @@ Buffer nvim_create_buf(Boolean listed, Boolean scratch, Error *err)
buf_copy_options(buf, BCO_ENTER | BCO_NOHELP);
if (scratch) {
- set_string_option_direct_in_buf(buf, "bufhidden", -1, "hide", OPT_LOCAL, 0);
- set_string_option_direct_in_buf(buf, "buftype", -1, "nofile", OPT_LOCAL, 0);
+ set_string_option_direct_in_buf(buf, kOptBufhidden, "hide", OPT_LOCAL, 0);
+ set_string_option_direct_in_buf(buf, kOptBuftype, "nofile", OPT_LOCAL, 0);
assert(buf->b_ml.ml_mfp->mf_fd < 0); // ml_open() should not have opened swapfile already
buf->b_p_swf = false;
buf->b_p_ml = false;
@@ -985,10 +1019,11 @@ fail:
/// master end. For instance, a carriage return is sent
/// as a "\r", not as a "\n". |textlock| applies. It is possible
/// to call |nvim_chan_send()| directly in the callback however.
-/// ["input", term, bufnr, data]
+/// `["input", term, bufnr, data]`
+/// - force_crlf: (boolean, default true) Convert "\n" to "\r\n".
/// @param[out] err Error details, if any
/// @return Channel id, or 0 on error
-Integer nvim_open_term(Buffer buffer, DictionaryOf(LuaRef) opts, Error *err)
+Integer nvim_open_term(Buffer buffer, Dict(open_term) *opts, Error *err)
FUNC_API_SINCE(7)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
@@ -997,39 +1032,31 @@ Integer nvim_open_term(Buffer buffer, DictionaryOf(LuaRef) opts, Error *err)
return 0;
}
- if (cmdwin_type != 0 && buf == curbuf) {
+ if (buf == cmdwin_buf) {
api_set_error(err, kErrorTypeException, "%s", e_cmdwin);
return 0;
}
LuaRef cb = LUA_NOREF;
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object *v = &opts.items[i].value;
- if (strequal("on_input", k.data)) {
- VALIDATE_T("on_input", kObjectTypeLuaRef, v->type, {
- return 0;
- });
- cb = v->data.luaref;
- v->data.luaref = LUA_NOREF;
- break;
- } else {
- VALIDATE_S(false, "'opts' key", k.data, {});
- }
+ if (HAS_KEY(opts, open_term, on_input)) {
+ cb = opts->on_input;
+ opts->on_input = LUA_NOREF;
}
- TerminalOptions topts;
Channel *chan = channel_alloc(kChannelStreamInternal);
chan->stream.internal.cb = cb;
chan->stream.internal.closed = false;
- topts.data = chan;
- // NB: overridden in terminal_check_size if a window is already
- // displaying the buffer
- topts.width = (uint16_t)MAX(curwin->w_width_inner - win_col_off(curwin), 0);
- topts.height = (uint16_t)curwin->w_height_inner;
- topts.write_cb = term_write;
- topts.resize_cb = term_resize;
- topts.close_cb = term_close;
+ TerminalOptions topts = {
+ .data = chan,
+ // NB: overridden in terminal_check_size if a window is already
+ // displaying the buffer
+ .width = (uint16_t)MAX(curwin->w_width_inner - win_col_off(curwin), 0),
+ .height = (uint16_t)curwin->w_height_inner,
+ .write_cb = term_write,
+ .resize_cb = term_resize,
+ .close_cb = term_close,
+ .force_crlf = GET_BOOL_OR_TRUE(opts, open_term, force_crlf),
+ };
channel_incref(chan);
terminal_open(&chan->term, buf, topts);
if (chan->term != NULL) {
@@ -1039,7 +1066,7 @@ Integer nvim_open_term(Buffer buffer, DictionaryOf(LuaRef) opts, Error *err)
return (Integer)chan->id;
}
-static void term_write(char *buf, size_t size, void *data) // NOLINT(readability-non-const-parameter)
+static void term_write(const char *buf, size_t size, void *data)
{
Channel *chan = data;
LuaRef cb = chan->stream.internal.cb;
@@ -1049,9 +1076,9 @@ static void term_write(char *buf, size_t size, void *data) // NOLINT(readabilit
MAXSIZE_TEMP_ARRAY(args, 3);
ADD_C(args, INTEGER_OBJ((Integer)chan->id));
ADD_C(args, BUFFER_OBJ(terminal_buf(chan->term)));
- ADD_C(args, STRING_OBJ(((String){ .data = buf, .size = size })));
+ ADD_C(args, STRING_OBJ(((String){ .data = (char *)buf, .size = size })));
textlock++;
- nlua_call_ref(cb, "input", args, false, NULL);
+ nlua_call_ref(cb, "input", args, kRetNilBool, NULL, NULL);
textlock--;
}
@@ -1098,20 +1125,19 @@ void nvim_chan_send(Integer chan, String data, Error *err)
/// Gets the current list of tabpage handles.
///
/// @return List of tabpage handles
-ArrayOf(Tabpage) nvim_list_tabpages(void)
+ArrayOf(Tabpage) nvim_list_tabpages(Arena *arena)
FUNC_API_SINCE(1)
{
- Array rv = ARRAY_DICT_INIT;
+ size_t n = 0;
FOR_ALL_TABS(tp) {
- rv.size++;
+ n++;
}
- rv.items = xmalloc(sizeof(Object) * rv.size);
- size_t i = 0;
+ Array rv = arena_array(arena, n);
FOR_ALL_TABS(tp) {
- rv.items[i++] = TABPAGE_OBJ(tp->handle);
+ ADD_C(rv, TABPAGE_OBJ(tp->handle));
}
return rv;
@@ -1172,7 +1198,7 @@ void nvim_set_current_tabpage(Tabpage tabpage, Error *err)
/// @return
/// - true: Client may continue pasting.
/// - false: Client must cancel the paste.
-Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
+Boolean nvim_paste(String data, Boolean crlf, Integer phase, Arena *arena, Error *err)
FUNC_API_SINCE(6)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
@@ -1182,19 +1208,17 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
VALIDATE_INT((phase >= -1 && phase <= 3), "phase", phase, {
return false;
});
- Array args = ARRAY_DICT_INIT;
- Object rv = OBJECT_INIT;
if (phase == -1 || phase == 1) { // Start of paste-stream.
draining = false;
} else if (draining) {
// Skip remaining chunks. Report error only once per "stream".
goto theend;
}
- Array lines = string_to_array(data, crlf);
- ADD(args, ARRAY_OBJ(lines));
- ADD(args, INTEGER_OBJ(phase));
- rv = nvim_exec_lua(STATIC_CSTR_AS_STRING("return vim.paste(...)"), args,
- err);
+ Array lines = string_to_array(data, crlf, arena);
+ MAXSIZE_TEMP_ARRAY(args, 2);
+ ADD_C(args, ARRAY_OBJ(lines));
+ ADD_C(args, INTEGER_OBJ(phase));
+ Object rv = NLUA_EXEC_STATIC("return vim.paste(...)", args, kRetNilBool, arena, err);
if (ERROR_SET(err)) {
draining = true;
goto theend;
@@ -1221,8 +1245,6 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
AppendCharToRedobuff(ESC); // Dot-repeat.
}
theend:
- api_free_object(rv);
- api_free_array(args);
if (cancel || phase == -1 || phase == 3) { // End of paste-stream.
draining = false;
}
@@ -1243,24 +1265,27 @@ theend:
/// @param after If true insert after cursor (like |p|), or before (like |P|).
/// @param follow If true place cursor at end of inserted text.
/// @param[out] err Error details, if any
-void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Error *err)
+void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow, Arena *arena,
+ Error *err)
FUNC_API_SINCE(6)
FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
- yankreg_T *reg = xcalloc(1, sizeof(yankreg_T));
+ yankreg_T reg[1] = { 0 };
VALIDATE_S((prepare_yankreg_from_object(reg, type, lines.size)), "type", type.data, {
- goto cleanup;
+ return;
});
if (lines.size == 0) {
- goto cleanup; // Nothing to do.
+ return; // Nothing to do.
}
+ reg->y_array = arena_alloc(arena, lines.size * sizeof(uint8_t *), true);
+ reg->y_size = lines.size;
for (size_t i = 0; i < lines.size; i++) {
VALIDATE_T("line", kObjectTypeString, lines.items[i].type, {
- goto cleanup;
+ return;
});
String line = lines.items[i].data.string;
- reg->y_array[i] = xmemdupz(line.data, line.size);
+ reg->y_array[i] = arena_memdupz(arena, line.data, line.size);
memchrsub(reg->y_array[i], NUL, NL, line.size);
}
@@ -1273,10 +1298,6 @@ void nvim_put(ArrayOf(String) lines, String type, Boolean after, Boolean follow,
msg_silent--;
VIsual_active = VIsual_was_active;
});
-
-cleanup:
- free_register(reg);
- xfree(reg);
}
/// Subscribes to event broadcasts.
@@ -1334,14 +1355,13 @@ Integer nvim_get_color_by_name(String name)
/// (e.g. 65535).
///
/// @return Map of color names and RGB values.
-Dictionary nvim_get_color_map(void)
+Dictionary nvim_get_color_map(Arena *arena)
FUNC_API_SINCE(1)
{
- Dictionary colors = ARRAY_DICT_INIT;
+ Dictionary colors = arena_dict(arena, ARRAY_SIZE(color_name_table));
for (int i = 0; color_name_table[i].name != NULL; i++) {
- PUT(colors, color_name_table[i].name,
- INTEGER_OBJ(color_name_table[i].color));
+ PUT_C(colors, color_name_table[i].name, INTEGER_OBJ(color_name_table[i].color));
}
return colors;
}
@@ -1354,7 +1374,7 @@ Dictionary nvim_get_color_map(void)
/// @param[out] err Error details, if any
///
/// @return map of global |context|.
-Dictionary nvim_get_context(Dict(context) *opts, Error *err)
+Dictionary nvim_get_context(Dict(context) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(6)
{
Array types = ARRAY_DICT_INIT;
@@ -1390,7 +1410,7 @@ Dictionary nvim_get_context(Dict(context) *opts, Error *err)
Context ctx = CONTEXT_INIT;
ctx_save(&ctx, int_types);
- Dictionary dict = ctx_to_dict(&ctx);
+ Dictionary dict = ctx_to_dict(&ctx, arena);
ctx_free(&ctx);
return dict;
}
@@ -1421,16 +1441,16 @@ Object nvim_load_context(Dictionary dict, Error *err)
/// "blocking" is true if Nvim is waiting for input.
///
/// @returns Dictionary { "mode": String, "blocking": Boolean }
-Dictionary nvim_get_mode(void)
+Dictionary nvim_get_mode(Arena *arena)
FUNC_API_SINCE(2) FUNC_API_FAST
{
- Dictionary rv = ARRAY_DICT_INIT;
- char modestr[MODE_MAX_LENGTH];
+ Dictionary rv = arena_dict(arena, 2);
+ char *modestr = arena_alloc(arena, MODE_MAX_LENGTH, false);
get_mode(modestr);
bool blocked = input_blocking();
- PUT(rv, "mode", CSTR_TO_OBJ(modestr));
- PUT(rv, "blocking", BOOLEAN_OBJ(blocked));
+ PUT_C(rv, "mode", CSTR_AS_OBJ(modestr));
+ PUT_C(rv, "blocking", BOOLEAN_OBJ(blocked));
return rv;
}
@@ -1440,10 +1460,10 @@ Dictionary nvim_get_mode(void)
/// @param mode Mode short-name ("n", "i", "v", ...)
/// @returns Array of |maparg()|-like dictionaries describing mappings.
/// The "buffer" key is always zero.
-ArrayOf(Dictionary) nvim_get_keymap(String mode)
+ArrayOf(Dictionary) nvim_get_keymap(String mode, Arena *arena)
FUNC_API_SINCE(3)
{
- return keymap_array(mode, NULL);
+ return keymap_array(mode, NULL, arena);
}
/// Sets a global |mapping| for the given mode.
@@ -1451,7 +1471,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode)
/// To set a buffer-local mapping, use |nvim_buf_set_keymap()|.
///
/// Unlike |:map|, leading/trailing whitespace is accepted as part of the {lhs} or {rhs}.
-/// Empty {rhs} is |<Nop>|. |keycodes| are replaced as usual.
+/// Empty {rhs} is [<Nop>]. |keycodes| are replaced as usual.
///
/// Example:
///
@@ -1471,7 +1491,7 @@ ArrayOf(Dictionary) nvim_get_keymap(String mode)
/// "ia", "ca" or "!a" for abbreviation in Insert mode, Cmdline mode, or both, respectively
/// @param lhs Left-hand-side |{lhs}| of the mapping.
/// @param rhs Right-hand-side |{rhs}| of the mapping.
-/// @param opts Optional parameters map: Accepts all |:map-arguments| as keys except |<buffer>|,
+/// @param opts Optional parameters map: Accepts all |:map-arguments| as keys except [<buffer>],
/// values are booleans (default false). Also:
/// - "noremap" disables |recursive_mapping|, like |:noremap|
/// - "desc" human-readable description.
@@ -1501,7 +1521,7 @@ void nvim_del_keymap(uint64_t channel_id, String mode, String lhs, Error *err)
/// Returns a 2-tuple (Array), where item 0 is the current channel id and item
/// 1 is the |api-metadata| map (Dictionary).
///
-/// @returns 2-tuple [{channel-id}, {api-metadata}]
+/// @returns 2-tuple `[{channel-id}, {api-metadata}]`
Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
FUNC_API_SINCE(1) FUNC_API_FAST FUNC_API_REMOTE_ONLY
{
@@ -1509,7 +1529,7 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
assert(channel_id <= INT64_MAX);
ADD_C(rv, INTEGER_OBJ((int64_t)channel_id));
- ADD_C(rv, DICTIONARY_OBJ(api_metadata()));
+ ADD_C(rv, api_metadata());
return rv;
}
@@ -1529,14 +1549,14 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
/// @param channel_id
/// @param name Short name for the connected client
/// @param version Dictionary describing the version, with these
-/// (optional) keys:
+/// (optional) keys:
/// - "major" major version (defaults to 0 if not set, for no release yet)
/// - "minor" minor version
/// - "patch" patch number
/// - "prerelease" string describing a prerelease, like "dev" or "beta1"
/// - "commit" hash or similar identifier of commit
/// @param type Must be one of the following values. Client libraries should
-/// default to "remote" unless overridden by the user.
+/// default to "remote" unless overridden by the user.
/// - "remote" remote client connected "Nvim flavored" MessagePack-RPC (responses
/// must be in reverse order of requests). |msgpack-rpc|
/// - "msgpack-rpc" remote client connected to Nvim via fully MessagePack-RPC
@@ -1547,12 +1567,12 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
/// - "host" plugin host, typically started by nvim
/// - "plugin" single plugin, started by nvim
/// @param methods Builtin methods in the client. For a host, this does not
-/// include plugin methods which will be discovered later.
-/// The key should be the method name, the values are dicts with
-/// these (optional) keys (more keys may be added in future
-/// versions of Nvim, thus unknown keys are ignored. Clients
-/// must only use keys defined in this or later versions of
-/// Nvim):
+/// include plugin methods which will be discovered later.
+/// The key should be the method name, the values are dicts with
+/// these (optional) keys (more keys may be added in future
+/// versions of Nvim, thus unknown keys are ignored. Clients
+/// must only use keys defined in this or later versions of
+/// Nvim):
/// - "async" if true, send as a notification. If false or unspecified,
/// use a blocking request
/// - "nargs" Number of arguments. Could be a single integer or an array
@@ -1567,13 +1587,12 @@ Array nvim_get_api_info(uint64_t channel_id, Arena *arena)
///
/// @param[out] err Error details, if any
void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version, String type,
- Dictionary methods, Dictionary attributes, Error *err)
+ Dictionary methods, Dictionary attributes, Arena *arena, Error *err)
FUNC_API_SINCE(4) FUNC_API_REMOTE_ONLY
{
- Dictionary info = ARRAY_DICT_INIT;
- PUT(info, "name", copy_object(STRING_OBJ(name), NULL));
+ MAXSIZE_TEMP_DICT(info, 5);
+ PUT_C(info, "name", STRING_OBJ(name));
- version = copy_dictionary(version, NULL);
bool has_major = false;
for (size_t i = 0; i < version.size; i++) {
if (strequal(version.items[i].key.data, "major")) {
@@ -1582,19 +1601,26 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version,
}
}
if (!has_major) {
- PUT(version, "major", INTEGER_OBJ(0));
+ Dictionary v = arena_dict(arena, version.size + 1);
+ if (version.size) {
+ memcpy(v.items, version.items, version.size * sizeof(v.items[0]));
+ v.size = version.size;
+ }
+ PUT_C(v, "major", INTEGER_OBJ(0));
+ version = v;
}
- PUT(info, "version", DICTIONARY_OBJ(version));
+ PUT_C(info, "version", DICTIONARY_OBJ(version));
- PUT(info, "type", copy_object(STRING_OBJ(type), NULL));
- PUT(info, "methods", DICTIONARY_OBJ(copy_dictionary(methods, NULL)));
- PUT(info, "attributes", DICTIONARY_OBJ(copy_dictionary(attributes, NULL)));
+ PUT_C(info, "type", STRING_OBJ(type));
+ PUT_C(info, "methods", DICTIONARY_OBJ(methods));
+ PUT_C(info, "attributes", DICTIONARY_OBJ(attributes));
- rpc_set_client_info(channel_id, info);
+ rpc_set_client_info(channel_id, copy_dictionary(info, NULL));
}
/// Gets information about a channel.
///
+/// @param chan channel_id, or 0 for current channel
/// @returns Dictionary describing a channel, with these keys:
/// - "id" Channel id.
/// - "argv" (optional) Job arguments list.
@@ -1616,23 +1642,28 @@ void nvim_set_client_info(uint64_t channel_id, String name, Dictionary version,
/// the RPC channel), if provided by it via
/// |nvim_set_client_info()|.
///
-Dictionary nvim_get_chan_info(Integer chan, Error *err)
+Dictionary nvim_get_chan_info(uint64_t channel_id, Integer chan, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
if (chan < 0) {
return (Dictionary)ARRAY_DICT_INIT;
}
- return channel_info((uint64_t)chan);
+
+ if (chan == 0 && !is_internal_call(channel_id)) {
+ assert(channel_id <= INT64_MAX);
+ chan = (Integer)channel_id;
+ }
+ return channel_info((uint64_t)chan, arena);
}
/// Get information about all open channels.
///
/// @returns Array of Dictionaries, each describing a channel with
/// the format specified at |nvim_get_chan_info()|.
-Array nvim_list_chans(void)
+Array nvim_list_chans(Arena *arena)
FUNC_API_SINCE(4)
{
- return channel_all_info();
+ return channel_all_info(arena);
}
/// Calls many API methods atomically.
@@ -1698,7 +1729,7 @@ Array nvim_call_atomic(uint64_t channel_id, Array calls, Arena *arena, Error *er
// directly here. But `result` might become invalid when next api function
// is called in the loop.
ADD_C(results, copy_object(result, arena));
- if (!handler.arena_return) {
+ if (handler.ret_alloc) {
api_free_object(result);
}
}
@@ -1778,9 +1809,9 @@ static void write_msg(String message, bool to_err, bool writeln)
/// @param[in] obj Object to return.
///
/// @return its argument.
-Object nvim__id(Object obj)
+Object nvim__id(Object obj, Arena *arena)
{
- return copy_object(obj, NULL);
+ return copy_object(obj, arena);
}
/// Returns array given as argument.
@@ -1791,9 +1822,9 @@ Object nvim__id(Object obj)
/// @param[in] arr Array to return.
///
/// @return its argument.
-Array nvim__id_array(Array arr)
+Array nvim__id_array(Array arr, Arena *arena)
{
- return copy_array(arr, NULL);
+ return copy_array(arr, arena);
}
/// Returns dictionary given as argument.
@@ -1804,9 +1835,9 @@ Array nvim__id_array(Array arr)
/// @param[in] dct Dictionary to return.
///
/// @return its argument.
-Dictionary nvim__id_dictionary(Dictionary dct)
+Dictionary nvim__id_dictionary(Dictionary dct, Arena *arena)
{
- return copy_dictionary(dct, NULL);
+ return copy_dictionary(dct, arena);
}
/// Returns floating-point value given as argument.
@@ -1825,14 +1856,14 @@ Float nvim__id_float(Float flt)
/// Gets internal stats.
///
/// @return Map of various internal stats.
-Dictionary nvim__stats(void)
-{
- Dictionary rv = ARRAY_DICT_INIT;
- PUT(rv, "fsync", INTEGER_OBJ(g_stats.fsync));
- PUT(rv, "log_skip", INTEGER_OBJ(g_stats.log_skip));
- PUT(rv, "lua_refcount", INTEGER_OBJ(nlua_get_global_ref_count()));
- PUT(rv, "redraw", INTEGER_OBJ(g_stats.redraw));
- PUT(rv, "arena_alloc_count", INTEGER_OBJ((Integer)arena_alloc_count));
+Dictionary nvim__stats(Arena *arena)
+{
+ Dictionary rv = arena_dict(arena, 5);
+ PUT_C(rv, "fsync", INTEGER_OBJ(g_stats.fsync));
+ PUT_C(rv, "log_skip", INTEGER_OBJ(g_stats.log_skip));
+ PUT_C(rv, "lua_refcount", INTEGER_OBJ(nlua_get_global_ref_count()));
+ PUT_C(rv, "redraw", INTEGER_OBJ(g_stats.redraw));
+ PUT_C(rv, "arena_alloc_count", INTEGER_OBJ((Integer)arena_alloc_count));
return rv;
}
@@ -1844,16 +1875,16 @@ Dictionary nvim__stats(void)
/// - "rgb" true if the UI uses RGB colors (false implies |cterm-colors|)
/// - "ext_..." Requested UI extensions, see |ui-option|
/// - "chan" |channel-id| of remote UI
-Array nvim_list_uis(void)
+Array nvim_list_uis(Arena *arena)
FUNC_API_SINCE(4)
{
- return ui_array();
+ return ui_array(arena);
}
/// Gets the immediate children of process `pid`.
///
/// @return Array of child process ids, empty if process not found.
-Array nvim_get_proc_children(Integer pid, Error *err)
+Array nvim_get_proc_children(Integer pid, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
Array rvobj = ARRAY_DICT_INIT;
@@ -1869,8 +1900,8 @@ Array nvim_get_proc_children(Integer pid, Error *err)
// syscall failed (possibly because of kernel options), try shelling out.
DLOG("fallback to vim._os_proc_children()");
MAXSIZE_TEMP_ARRAY(a, 1);
- ADD(a, INTEGER_OBJ(pid));
- Object o = NLUA_EXEC_STATIC("return vim._os_proc_children(...)", a, err);
+ ADD_C(a, INTEGER_OBJ(pid));
+ Object o = NLUA_EXEC_STATIC("return vim._os_proc_children(...)", a, kRetObject, arena, err);
if (o.type == kObjectTypeArray) {
rvobj = o.data.array;
} else if (!ERROR_SET(err)) {
@@ -1878,11 +1909,11 @@ Array nvim_get_proc_children(Integer pid, Error *err)
"Failed to get process children. pid=%" PRId64 " error=%d",
pid, rv);
}
- goto end;
- }
-
- for (size_t i = 0; i < proc_count; i++) {
- ADD(rvobj, INTEGER_OBJ(proc_list[i]));
+ } else {
+ rvobj = arena_array(arena, proc_count);
+ for (size_t i = 0; i < proc_count; i++) {
+ ADD_C(rvobj, INTEGER_OBJ(proc_list[i]));
+ }
}
end:
@@ -1893,19 +1924,17 @@ end:
/// Gets info describing process `pid`.
///
/// @return Map of process properties, or NIL if process not found.
-Object nvim_get_proc(Integer pid, Error *err)
+Object nvim_get_proc(Integer pid, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
- Object rvobj = OBJECT_INIT;
- rvobj.data.dictionary = (Dictionary)ARRAY_DICT_INIT;
- rvobj.type = kObjectTypeDictionary;
+ Object rvobj = NIL;
VALIDATE_INT((pid > 0 && pid <= INT_MAX), "pid", pid, {
return NIL;
});
#ifdef MSWIN
- rvobj.data.dictionary = os_proc_info((int)pid);
+ rvobj = DICTIONARY_OBJ(os_proc_info((int)pid, arena));
if (rvobj.data.dictionary.size == 0) { // Process not found.
return NIL;
}
@@ -1913,11 +1942,11 @@ Object nvim_get_proc(Integer pid, Error *err)
// Cross-platform process info APIs are miserable, so use `ps` instead.
MAXSIZE_TEMP_ARRAY(a, 1);
ADD(a, INTEGER_OBJ(pid));
- Object o = NLUA_EXEC_STATIC("return vim._os_proc_info(...)", a, err);
+ Object o = NLUA_EXEC_STATIC("return vim._os_proc_info(...)", a, kRetObject, arena, err);
if (o.type == kObjectTypeArray && o.data.array.size == 0) {
return NIL; // Process not found.
} else if (o.type == kObjectTypeDictionary) {
- rvobj.data.dictionary = o.data.dictionary;
+ rvobj = o;
} else if (!ERROR_SET(err)) {
api_set_error(err, kErrorTypeException,
"Failed to get process info. pid=%" PRId64, pid);
@@ -1931,7 +1960,7 @@ Object nvim_get_proc(Integer pid, Error *err)
/// If neither |ins-completion| nor |cmdline-completion| popup menu is active
/// this API call is silently ignored.
/// Useful for an external UI using |ui-popupmenu| to control the popup menu with the mouse.
-/// Can also be used in a mapping; use <Cmd> |:map-cmd| or a Lua mapping to ensure the mapping
+/// Can also be used in a mapping; use [<Cmd>] |:map-cmd| or a Lua mapping to ensure the mapping
/// doesn't end completion mode.
///
/// @param item Index (zero-based) of the item to select. Value of -1 selects nothing
@@ -1941,14 +1970,10 @@ Object nvim_get_proc(Integer pid, Error *err)
/// @param finish Finish the completion and dismiss the popup menu. Implies {insert}.
/// @param opts Optional parameters. Reserved for future use.
/// @param[out] err Error details, if any
-void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Dictionary opts,
+void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Dict(empty) *opts,
Error *err)
FUNC_API_SINCE(6)
{
- VALIDATE((opts.size == 0), "%s", "opts dict isn't empty", {
- return;
- });
-
if (finish) {
insert = true;
}
@@ -1956,7 +1981,7 @@ void nvim_select_popupmenu_item(Integer item, Boolean insert, Boolean finish, Di
pum_ext_select_item((int)item, insert, finish);
}
-/// NB: if your UI doesn't use hlstate, this will not return hlstate first time
+/// NB: if your UI doesn't use hlstate, this will not return hlstate first time.
Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, Error *err)
{
Array ret = ARRAY_DICT_INIT;
@@ -1987,11 +2012,12 @@ Array nvim__inspect_cell(Integer grid, Integer row, Integer col, Arena *arena, E
ADD_C(ret, DICTIONARY_OBJ(hl_get_attr_by_id(attr, true, arena, err)));
// will not work first time
if (!highlight_use_hlstate()) {
- ADD_C(ret, ARRAY_OBJ(hl_inspect(attr)));
+ ADD_C(ret, ARRAY_OBJ(hl_inspect(attr, arena)));
}
return ret;
}
+/// @nodoc
void nvim__screenshot(String path)
FUNC_API_FAST
{
@@ -2006,10 +2032,11 @@ void nvim__invalidate_glyph_cache(void)
must_redraw = UPD_CLEAR;
}
-Object nvim__unpack(String str, Error *err)
+/// @nodoc
+Object nvim__unpack(String str, Arena *arena, Error *err)
FUNC_API_FAST
{
- return unpack(str.data, str.size, err);
+ return unpack(str.data, str.size, arena, err);
}
/// Deletes an uppercase/file named mark. See |mark-motions|.
@@ -2049,7 +2076,7 @@ Boolean nvim_del_mark(String name, Error *err)
/// not set.
/// @see |nvim_buf_set_mark()|
/// @see |nvim_del_mark()|
-Array nvim_get_mark(String name, Dictionary opts, Error *err)
+Array nvim_get_mark(String name, Dict(empty) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(8)
{
Array rv = ARRAY_DICT_INIT;
@@ -2097,10 +2124,11 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err)
col = pos.col;
}
- ADD(rv, INTEGER_OBJ(row));
- ADD(rv, INTEGER_OBJ(col));
- ADD(rv, INTEGER_OBJ(bufnr));
- ADD(rv, CSTR_TO_OBJ(filename));
+ rv = arena_array(arena, 4);
+ ADD_C(rv, INTEGER_OBJ(row));
+ ADD_C(rv, INTEGER_OBJ(col));
+ ADD_C(rv, INTEGER_OBJ(bufnr));
+ ADD_C(rv, CSTR_TO_ARENA_OBJ(arena, filename));
if (allocated) {
xfree(filename);
@@ -2132,15 +2160,14 @@ Array nvim_get_mark(String name, Dictionary opts, Error *err)
/// |Dictionary| with these keys:
/// - start: (number) Byte index (0-based) of first character that uses the highlight.
/// - group: (string) Name of highlight group.
-Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *err)
+Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Arena *arena, Error *err)
FUNC_API_SINCE(8) FUNC_API_FAST
{
Dictionary result = ARRAY_DICT_INIT;
int maxwidth;
- int fillchar = 0;
+ schar_T fillchar = 0;
int statuscol_lnum = 0;
- Window window = 0;
if (str.size < 2 || memcmp(str.data, "%!", 2) != 0) {
const char *const errmsg = check_stl_option(str.data);
@@ -2149,16 +2176,17 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
});
}
- if (HAS_KEY(opts, eval_statusline, winid)) {
- window = opts->winid;
- }
+ Window window = opts->winid;
+
if (HAS_KEY(opts, eval_statusline, fillchar)) {
VALIDATE_EXP((*opts->fillchar.data != 0
- && ((size_t)utf_ptr2len(opts->fillchar.data) == opts->fillchar.size)),
+ && ((size_t)utfc_ptr2len(opts->fillchar.data) == opts->fillchar.size)),
"fillchar", "single character", NULL, {
return result;
});
- fillchar = utf_ptr2char(opts->fillchar.data);
+ int c;
+ fillchar = utfc_ptr2schar(opts->fillchar.data, &c);
+ // TODO(bfredl): actually check c is single width
}
int use_bools = (int)opts->use_winbar + (int)opts->use_tabline;
@@ -2186,50 +2214,44 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
statuscol_T statuscol = { 0 };
SignTextAttrs sattrs[SIGN_SHOW_MAX] = { 0 };
- if (opts->use_tabline) {
- fillchar = ' ';
- } else {
- if (fillchar == 0) {
- if (opts->use_winbar) {
- fillchar = wp->w_p_fcs_chars.wbr;
- } else {
- int attr;
- fillchar = fillchar_status(&attr, wp);
+ if (statuscol_lnum) {
+ int line_id = 0;
+ int cul_id = 0;
+ int num_id = 0;
+ linenr_T lnum = statuscol_lnum;
+ decor_redraw_signs(wp, wp->w_buffer, lnum - 1, sattrs, &line_id, &cul_id, &num_id);
+
+ statuscol.sattrs = sattrs;
+ statuscol.foldinfo = fold_info(wp, lnum);
+ wp->w_cursorline = win_cursorline_standout(wp) ? wp->w_cursor.lnum : 0;
+
+ if (wp->w_p_cul) {
+ if (statuscol.foldinfo.fi_level != 0 && statuscol.foldinfo.fi_lines > 0) {
+ wp->w_cursorline = statuscol.foldinfo.fi_lnum;
}
+ statuscol.use_cul = lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR);
}
- if (statuscol_lnum) {
- int line_id = 0;
- int cul_id = 0;
- int num_id = 0;
- linenr_T lnum = statuscol_lnum;
- wp->w_scwidth = win_signcol_count(wp);
- decor_redraw_signs(wp, wp->w_buffer, lnum - 1, sattrs, &line_id, &cul_id, &num_id);
-
- statuscol.sattrs = sattrs;
- statuscol.foldinfo = fold_info(wp, lnum);
- wp->w_cursorline = win_cursorline_standout(wp) ? wp->w_cursor.lnum : 0;
-
- if (wp->w_p_cul) {
- if (statuscol.foldinfo.fi_level != 0 && statuscol.foldinfo.fi_lines > 0) {
- wp->w_cursorline = statuscol.foldinfo.fi_lnum;
- }
- statuscol.use_cul = lnum == wp->w_cursorline && (wp->w_p_culopt_flags & CULOPT_NBR);
- }
- statuscol.sign_cul_id = statuscol.use_cul ? cul_id : 0;
- if (num_id) {
- stc_hl_id = num_id;
- } else if (statuscol.use_cul) {
- stc_hl_id = HLF_CLN + 1;
- } else if (wp->w_p_rnu) {
- stc_hl_id = (lnum < wp->w_cursor.lnum ? HLF_LNA : HLF_LNB) + 1;
- } else {
- stc_hl_id = HLF_N + 1;
- }
+ statuscol.sign_cul_id = statuscol.use_cul ? cul_id : 0;
+ if (num_id) {
+ stc_hl_id = num_id;
+ } else if (statuscol.use_cul) {
+ stc_hl_id = HLF_CLN + 1;
+ } else if (wp->w_p_rnu) {
+ stc_hl_id = (lnum < wp->w_cursor.lnum ? HLF_LNA : HLF_LNB) + 1;
+ } else {
+ stc_hl_id = HLF_N + 1;
+ }
- set_vim_var_nr(VV_LNUM, lnum);
- set_vim_var_nr(VV_RELNUM, labs(get_cursor_rel_lnum(wp, lnum)));
- set_vim_var_nr(VV_VIRTNUM, 0);
+ set_vim_var_nr(VV_LNUM, lnum);
+ set_vim_var_nr(VV_RELNUM, labs(get_cursor_rel_lnum(wp, lnum)));
+ set_vim_var_nr(VV_VIRTNUM, 0);
+ } else if (fillchar == 0 && !opts->use_tabline) {
+ if (opts->use_winbar) {
+ fillchar = wp->w_p_fcs_chars.wbr;
+ } else {
+ int attr;
+ fillchar = fillchar_status(&attr, wp);
}
}
@@ -2242,70 +2264,66 @@ Dictionary nvim_eval_statusline(String str, Dict(eval_statusline) *opts, Error *
&& global_stl_height() > 0)) ? Columns : wp->w_width;
}
- char buf[MAXPATHL];
+ result = arena_dict(arena, 3);
+ char *buf = arena_alloc(arena, MAXPATHL, false);
stl_hlrec_t *hltab;
+ size_t hltab_len = 0;
// Temporarily reset 'cursorbind' to prevent side effects from moving the cursor away and back.
int p_crb_save = wp->w_p_crb;
wp->w_p_crb = false;
- int width = build_stl_str_hl(wp,
- buf,
- sizeof(buf),
- str.data,
- NULL,
- 0,
- fillchar,
- maxwidth,
- opts->highlights ? &hltab : NULL,
- NULL,
+ int width = build_stl_str_hl(wp, buf, MAXPATHL, str.data, -1, 0, fillchar, maxwidth,
+ opts->highlights ? &hltab : NULL, &hltab_len, NULL,
statuscol_lnum ? &statuscol : NULL);
- PUT(result, "width", INTEGER_OBJ(width));
+ PUT_C(result, "width", INTEGER_OBJ(width));
// Restore original value of 'cursorbind'
wp->w_p_crb = p_crb_save;
if (opts->highlights) {
- Array hl_values = ARRAY_DICT_INIT;
- const char *grpname;
+ Array hl_values = arena_array(arena, hltab_len + 1);
char user_group[15]; // strlen("User") + strlen("2147483647") + NUL
// If first character doesn't have a defined highlight,
// add the default highlight at the beginning of the highlight list
if (hltab->start == NULL || (hltab->start - buf) != 0) {
- Dictionary hl_info = ARRAY_DICT_INIT;
- grpname = get_default_stl_hl(opts->use_tabline ? NULL : wp, opts->use_winbar, stc_hl_id);
+ Dictionary hl_info = arena_dict(arena, 2);
+ const char *grpname = get_default_stl_hl(opts->use_tabline ? NULL : wp,
+ opts->use_winbar, stc_hl_id);
- PUT(hl_info, "start", INTEGER_OBJ(0));
- PUT(hl_info, "group", CSTR_TO_OBJ(grpname));
+ PUT_C(hl_info, "start", INTEGER_OBJ(0));
+ PUT_C(hl_info, "group", CSTR_AS_OBJ(grpname));
- ADD(hl_values, DICTIONARY_OBJ(hl_info));
+ ADD_C(hl_values, DICTIONARY_OBJ(hl_info));
}
for (stl_hlrec_t *sp = hltab; sp->start != NULL; sp++) {
- Dictionary hl_info = ARRAY_DICT_INIT;
+ Dictionary hl_info = arena_dict(arena, 2);
- PUT(hl_info, "start", INTEGER_OBJ(sp->start - buf));
+ PUT_C(hl_info, "start", INTEGER_OBJ(sp->start - buf));
+ const char *grpname;
if (sp->userhl == 0) {
grpname = get_default_stl_hl(opts->use_tabline ? NULL : wp, opts->use_winbar, stc_hl_id);
} else if (sp->userhl < 0) {
grpname = syn_id2name(-sp->userhl);
} else {
snprintf(user_group, sizeof(user_group), "User%d", sp->userhl);
- grpname = user_group;
+ grpname = arena_memdupz(arena, user_group, strlen(user_group));
}
- PUT(hl_info, "group", CSTR_TO_OBJ(grpname));
- ADD(hl_values, DICTIONARY_OBJ(hl_info));
+ PUT_C(hl_info, "group", CSTR_AS_OBJ(grpname));
+ ADD_C(hl_values, DICTIONARY_OBJ(hl_info));
}
- PUT(result, "highlights", ARRAY_OBJ(hl_values));
+ PUT_C(result, "highlights", ARRAY_OBJ(hl_values));
}
- PUT(result, "str", CSTR_TO_OBJ(buf));
+ PUT_C(result, "str", CSTR_AS_OBJ(buf));
return result;
}
+/// @nodoc
void nvim_error_event(uint64_t channel_id, Integer lvl, String data)
FUNC_API_REMOTE_ONLY
{
@@ -2313,3 +2331,29 @@ void nvim_error_event(uint64_t channel_id, Integer lvl, String data)
// if we fork nvim processes as async workers
ELOG("async error on channel %" PRId64 ": %s", channel_id, data.size ? data.data : "");
}
+
+/// Set info for the completion candidate index.
+/// if the info was shown in a window, then the
+/// window and buffer ids are returned for further
+/// customization. If the text was not shown, an
+/// empty dict is returned.
+///
+/// @param index the completion candidate index
+/// @param opts Optional parameters.
+/// - info: (string) info text.
+/// @return Dictionary containing these keys:
+/// - winid: (number) floating window id
+/// - bufnr: (number) buffer id in floating window
+Dictionary nvim_complete_set(Integer index, Dict(complete_set) *opts, Arena *arena)
+ FUNC_API_SINCE(12)
+{
+ Dictionary rv = arena_dict(arena, 2);
+ if (HAS_KEY(opts, complete_set, info)) {
+ win_T *wp = pum_set_info((int)index, opts->info.data);
+ if (wp) {
+ PUT_C(rv, "winid", WINDOW_OBJ(wp->handle));
+ PUT_C(rv, "bufnr", BUFFER_OBJ(wp->w_buffer->handle));
+ }
+ }
+ return rv;
+}
diff --git a/src/nvim/api/vimscript.c b/src/nvim/api/vimscript.c
index c75bf21572..477cbe2428 100644
--- a/src/nvim/api/vimscript.c
+++ b/src/nvim/api/vimscript.c
@@ -11,18 +11,21 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/vimscript.h"
#include "nvim/ascii_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
#include "nvim/ex_docmd.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/globals.h"
#include "nvim/memory.h"
#include "nvim/runtime.h"
#include "nvim/vim_defs.h"
#include "nvim/viml/parser/expressions.h"
#include "nvim/viml/parser/parser.h"
+#include "nvim/viml/parser/parser_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "api/vimscript.c.generated.h"
@@ -48,7 +51,7 @@
/// @return Dictionary containing information about execution, with these keys:
/// - output: (string|nil) Output if `opts.output` is true.
Dictionary nvim_exec2(uint64_t channel_id, String src, Dict(exec_opts) *opts, Error *err)
- FUNC_API_SINCE(11)
+ FUNC_API_SINCE(11) FUNC_API_RET_ALLOC
{
Dictionary result = ARRAY_DICT_INIT;
@@ -145,7 +148,7 @@ void nvim_command(String command, Error *err)
/// @param expr Vimscript expression string
/// @param[out] err Error details, if any
/// @return Evaluation result or expanded object
-Object nvim_eval(String expr, Error *err)
+Object nvim_eval(String expr, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
static int recursive = 0; // recursion depth
@@ -176,7 +179,7 @@ Object nvim_eval(String expr, Error *err)
api_set_error(err, kErrorTypeException,
"Failed to evaluate expression: '%.*s'", 256, expr.data);
} else {
- rv = vim_to_object(&rettv);
+ rv = vim_to_object(&rettv, arena, false);
}
}
@@ -193,7 +196,7 @@ Object nvim_eval(String expr, Error *err)
/// @param self `self` dict, or NULL for non-dict functions
/// @param[out] err Error details, if any
/// @return Result of the function call
-static Object _call_function(String fn, Array args, dict_T *self, Error *err)
+static Object _call_function(String fn, Array args, dict_T *self, Arena *arena, Error *err)
{
static int recursive = 0; // recursion depth
Object rv = OBJECT_INIT;
@@ -208,9 +211,7 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err)
typval_T vim_args[MAX_FUNC_ARGS + 1];
size_t i = 0; // also used for freeing the variables
for (; i < args.size; i++) {
- if (!object_to_vim(args.items[i], &vim_args[i], err)) {
- goto free_vim_args;
- }
+ object_to_vim(args.items[i], &vim_args[i], err);
}
// Initialize `force_abort` and `suppress_errthrow` at the top level.
@@ -233,18 +234,17 @@ static Object _call_function(String fn, Array args, dict_T *self, Error *err)
TRY_WRAP(err, {
// call_func() retval is deceptive, ignore it. Instead we set `msg_list`
// (see above) to capture abort-causing non-exception errors.
- (void)call_func(fn.data, (int)fn.size, &rettv, (int)args.size,
- vim_args, &funcexe);
+ call_func(fn.data, (int)fn.size, &rettv, (int)args.size,
+ vim_args, &funcexe);
});
if (!ERROR_SET(err)) {
- rv = vim_to_object(&rettv);
+ rv = vim_to_object(&rettv, arena, false);
}
tv_clear(&rettv);
recursive--;
-free_vim_args:
while (i > 0) {
tv_clear(&vim_args[--i]);
}
@@ -260,10 +260,10 @@ free_vim_args:
/// @param args Function arguments packed in an Array
/// @param[out] err Error details, if any
/// @return Result of the function call
-Object nvim_call_function(String fn, Array args, Error *err)
+Object nvim_call_function(String fn, Array args, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
- return _call_function(fn, args, NULL, err);
+ return _call_function(fn, args, NULL, arena, err);
}
/// Calls a Vimscript |Dictionary-function| with the given arguments.
@@ -275,7 +275,7 @@ Object nvim_call_function(String fn, Array args, Error *err)
/// @param args Function arguments packed in an Array
/// @param[out] err Error details, if any
/// @return Result of the function call
-Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err)
+Object nvim_call_dict_function(Object dict, String fn, Array args, Arena *arena, Error *err)
FUNC_API_SINCE(4)
{
Object rv = OBJECT_INIT;
@@ -298,9 +298,7 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err)
mustfree = true;
break;
case kObjectTypeDictionary:
- if (!object_to_vim(dict, &rettv, err)) {
- goto end;
- }
+ object_to_vim(dict, &rettv, err);
break;
default:
api_set_error(err, kErrorTypeValidation,
@@ -339,7 +337,7 @@ Object nvim_call_dict_function(Object dict, String fn, Array args, Error *err)
goto end;
}
- rv = _call_function(fn, args, self_dict, err);
+ rv = _call_function(fn, args, self_dict, arena, err);
end:
if (mustfree) {
tv_clear(&rettv);
@@ -353,9 +351,7 @@ typedef struct {
Object *ret_node_p;
} ExprASTConvStackItem;
-/// @cond DOXYGEN_NOT_A_FUNCTION
typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
-/// @endcond
/// Parse a Vimscript expression.
///
@@ -369,8 +365,8 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// - "l" when needing to start parsing with lvalues for
/// ":let" or ":for".
/// Common flag sets:
-/// - "m" to parse like for ":echo".
-/// - "E" to parse like for "<C-r>=".
+/// - "m" to parse like for `":echo"`.
+/// - "E" to parse like for `"<C-r>="`.
/// - empty string for ":call".
/// - "lm" to parse for ":let".
/// @param[in] highlight If true, return value will also include "highlight"
@@ -389,12 +385,12 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// - "arg": String, error message argument.
/// - "len": Amount of bytes successfully parsed. With flags equal to ""
/// that should be equal to the length of expr string.
-/// (“Successfully parsed†here means “participated in AST
-/// creationâ€, not “till the first errorâ€.)
+/// ("Successfully parsed" here means "participated in AST
+/// creation", not "till the first error".)
/// - "ast": AST, either nil or a dictionary with these keys:
/// - "type": node type, one of the value names from ExprASTNodeType
/// stringified without "kExprNode" prefix.
-/// - "start": a pair [line, column] describing where node is "started"
+/// - "start": a pair `[line, column]` describing where node is "started"
/// where "line" is always 0 (will not be 0 if you will be
/// using this API on e.g. ":let", but that is not
/// present yet). Both elements are Integers.
@@ -431,7 +427,8 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// - "svalue": String, value for "SingleQuotedString" and
/// "DoubleQuotedString" nodes.
/// @param[out] err Error details, if any
-Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Error *err)
+Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, Arena *arena,
+ Error *err)
FUNC_API_SINCE(4) FUNC_API_FAST
{
int pflags = 0;
@@ -473,82 +470,40 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
+ (size_t)(east.err.msg != NULL) // "error"
+ (size_t)highlight // "highlight"
+ 0);
- Dictionary ret = {
- .items = xmalloc(ret_size * sizeof(ret.items[0])),
- .size = 0,
- .capacity = ret_size,
- };
- ret.items[ret.size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("ast"),
- .value = NIL,
- };
- ret.items[ret.size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("len"),
- .value = INTEGER_OBJ((Integer)(pstate.pos.line == 1
- ? parser_lines[0].size
- : pstate.pos.col)),
- };
+
+ Dictionary ret = arena_dict(arena, ret_size);
+ PUT_C(ret, "len", INTEGER_OBJ((Integer)(pstate.pos.line == 1
+ ? parser_lines[0].size
+ : pstate.pos.col)));
if (east.err.msg != NULL) {
- Dictionary err_dict = {
- .items = xmalloc(2 * sizeof(err_dict.items[0])),
- .size = 2,
- .capacity = 2,
- };
- err_dict.items[0] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("message"),
- .value = CSTR_TO_OBJ(east.err.msg),
- };
- if (east.err.arg == NULL) {
- err_dict.items[1] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("arg"),
- .value = STRING_OBJ(STRING_INIT),
- };
- } else {
- err_dict.items[1] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("arg"),
- .value = STRING_OBJ(((String) {
- .data = xmemdupz(east.err.arg, (size_t)east.err.arg_len),
- .size = (size_t)east.err.arg_len,
- })),
- };
- }
- ret.items[ret.size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("error"),
- .value = DICTIONARY_OBJ(err_dict),
- };
+ Dictionary err_dict = arena_dict(arena, 2);
+ PUT_C(err_dict, "message", CSTR_TO_ARENA_OBJ(arena, east.err.msg));
+ PUT_C(err_dict, "arg", CBUF_TO_ARENA_OBJ(arena, east.err.arg, (size_t)east.err.arg_len));
+ PUT_C(ret, "error", DICTIONARY_OBJ(err_dict));
}
if (highlight) {
- Array hl = (Array) {
- .items = xmalloc(kv_size(colors) * sizeof(hl.items[0])),
- .capacity = kv_size(colors),
- .size = kv_size(colors),
- };
+ Array hl = arena_array(arena, kv_size(colors));
for (size_t i = 0; i < kv_size(colors); i++) {
const ParserHighlightChunk chunk = kv_A(colors, i);
- Array chunk_arr = (Array) {
- .items = xmalloc(4 * sizeof(chunk_arr.items[0])),
- .capacity = 4,
- .size = 4,
- };
- 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] = CSTR_TO_OBJ(chunk.group);
- hl.items[i] = ARRAY_OBJ(chunk_arr);
+ Array chunk_arr = arena_array(arena, 4);
+ ADD_C(chunk_arr, INTEGER_OBJ((Integer)chunk.start.line));
+ ADD_C(chunk_arr, INTEGER_OBJ((Integer)chunk.start.col));
+ ADD_C(chunk_arr, INTEGER_OBJ((Integer)chunk.end_col));
+ ADD_C(chunk_arr, CSTR_AS_OBJ(chunk.group));
+
+ ADD_C(hl, ARRAY_OBJ(chunk_arr));
}
- ret.items[ret.size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("highlight"),
- .value = ARRAY_OBJ(hl),
- };
+ PUT_C(ret, "highlight", ARRAY_OBJ(hl));
}
kvi_destroy(colors);
// Walk over the AST, freeing nodes in process.
ExprASTConvStack ast_conv_stack;
kvi_init(ast_conv_stack);
+ Object ast = NIL;
kvi_push(ast_conv_stack, ((ExprASTConvStackItem) {
.node_p = &east.root,
- .ret_node_p = &ret.items[0].value,
+ .ret_node_p = &ast,
}));
while (kv_size(ast_conv_stack)) {
ExprASTConvStackItem cur_item = kv_last(ast_conv_stack);
@@ -575,28 +530,17 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
|| node->type == kExprNodeSingleQuotedString) // "svalue"
+ (node->type == kExprNodeAssignment) // "augmentation"
+ 0);
- Dictionary ret_node = {
- .items = xmalloc(items_size * sizeof(ret_node.items[0])),
- .capacity = items_size,
- .size = 0,
- };
+ Dictionary ret_node = arena_dict(arena, items_size);
*cur_item.ret_node_p = DICTIONARY_OBJ(ret_node);
}
Dictionary *ret_node = &cur_item.ret_node_p->data.dictionary;
if (node->children != NULL) {
const size_t num_children = 1 + (node->children->next != NULL);
- Array children_array = {
- .items = xmalloc(num_children * sizeof(children_array.items[0])),
- .capacity = num_children,
- .size = num_children,
- };
+ Array children_array = arena_array(arena, num_children);
for (size_t i = 0; i < num_children; i++) {
- children_array.items[i] = NIL;
+ ADD_C(children_array, NIL);
}
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("children"),
- .value = ARRAY_OBJ(children_array),
- };
+ PUT_C(*ret_node, "children", ARRAY_OBJ(children_array));
kvi_push(ast_conv_stack, ((ExprASTConvStackItem) {
.node_p = &node->children,
.ret_node_p = &children_array.items[0],
@@ -608,126 +552,60 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
}));
} else {
kv_drop(ast_conv_stack, 1);
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("type"),
- .value = CSTR_TO_OBJ(east_node_type_tab[node->type]),
- };
- Array start_array = {
- .items = xmalloc(2 * sizeof(start_array.items[0])),
- .capacity = 2,
- .size = 2,
- };
- start_array.items[0] = INTEGER_OBJ((Integer)node->start.line);
- start_array.items[1] = INTEGER_OBJ((Integer)node->start.col);
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("start"),
- .value = ARRAY_OBJ(start_array),
- };
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("len"),
- .value = INTEGER_OBJ((Integer)node->len),
- };
+ PUT_C(*ret_node, "type", CSTR_AS_OBJ(east_node_type_tab[node->type]));
+ Array start_array = arena_array(arena, 2);
+ ADD_C(start_array, INTEGER_OBJ((Integer)node->start.line));
+ ADD_C(start_array, INTEGER_OBJ((Integer)node->start.col));
+ PUT_C(*ret_node, "start", ARRAY_OBJ(start_array));
+
+ PUT_C(*ret_node, "len", INTEGER_OBJ((Integer)node->len));
switch (node->type) {
case kExprNodeDoubleQuotedString:
- case kExprNodeSingleQuotedString:
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("svalue"),
- .value = STRING_OBJ(((String) {
- .data = node->data.str.value,
- .size = node->data.str.size,
- })),
- };
+ case kExprNodeSingleQuotedString: {
+ Object str = CBUF_TO_ARENA_OBJ(arena, node->data.str.value, node->data.str.size);
+ PUT_C(*ret_node, "svalue", str);
+ xfree(node->data.str.value);
break;
+ }
case kExprNodeOption:
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("scope"),
- .value = INTEGER_OBJ(node->data.opt.scope),
- };
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("ident"),
- .value = STRING_OBJ(((String) {
- .data = xmemdupz(node->data.opt.ident,
- node->data.opt.ident_len),
- .size = node->data.opt.ident_len,
- })),
- };
+ PUT_C(*ret_node, "scope", INTEGER_OBJ(node->data.opt.scope));
+ PUT_C(*ret_node, "ident", CBUF_TO_ARENA_OBJ(arena, node->data.opt.ident,
+ node->data.opt.ident_len));
break;
case kExprNodePlainIdentifier:
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("scope"),
- .value = INTEGER_OBJ(node->data.var.scope),
- };
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("ident"),
- .value = STRING_OBJ(((String) {
- .data = xmemdupz(node->data.var.ident,
- node->data.var.ident_len),
- .size = node->data.var.ident_len,
- })),
- };
+ PUT_C(*ret_node, "scope", INTEGER_OBJ(node->data.var.scope));
+ PUT_C(*ret_node, "ident", CBUF_TO_ARENA_OBJ(arena, node->data.var.ident,
+ node->data.var.ident_len));
break;
case kExprNodePlainKey:
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("ident"),
- .value = STRING_OBJ(((String) {
- .data = xmemdupz(node->data.var.ident,
- node->data.var.ident_len),
- .size = node->data.var.ident_len,
- })),
- };
+ PUT_C(*ret_node, "ident", CBUF_TO_ARENA_OBJ(arena, node->data.var.ident,
+ node->data.var.ident_len));
break;
case kExprNodeEnvironment:
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("ident"),
- .value = STRING_OBJ(((String) {
- .data = xmemdupz(node->data.env.ident,
- node->data.env.ident_len),
- .size = node->data.env.ident_len,
- })),
- };
+ PUT_C(*ret_node, "ident", CBUF_TO_ARENA_OBJ(arena, node->data.env.ident,
+ node->data.env.ident_len));
break;
case kExprNodeRegister:
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("name"),
- .value = INTEGER_OBJ(node->data.reg.name),
- };
+ PUT_C(*ret_node, "name", INTEGER_OBJ(node->data.reg.name));
break;
case kExprNodeComparison:
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("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 = CSTR_TO_OBJ(ccs_tab[node->data.cmp.ccs]),
- };
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("invert"),
- .value = BOOLEAN_OBJ(node->data.cmp.inv),
- };
+ PUT_C(*ret_node, "cmp_type", CSTR_AS_OBJ(eltkn_cmp_type_tab[node->data.cmp.type]));
+ PUT_C(*ret_node, "ccs_strategy", CSTR_AS_OBJ(ccs_tab[node->data.cmp.ccs]));
+ PUT_C(*ret_node, "invert", BOOLEAN_OBJ(node->data.cmp.inv));
break;
case kExprNodeFloat:
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("fvalue"),
- .value = FLOAT_OBJ(node->data.flt.value),
- };
+ PUT_C(*ret_node, "fvalue", FLOAT_OBJ(node->data.flt.value));
break;
case kExprNodeInteger:
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("ivalue"),
- .value = INTEGER_OBJ((Integer)(node->data.num.value > API_INTEGER_MAX
- ? API_INTEGER_MAX
- : (Integer)node->data.num.value)),
- };
+ PUT_C(*ret_node, "ivalue", INTEGER_OBJ((Integer)(node->data.num.value > API_INTEGER_MAX
+ ? API_INTEGER_MAX
+ : (Integer)node->data.num.value)));
break;
case kExprNodeAssignment: {
const ExprAssignmentType asgn_type = node->data.ass.type;
- ret_node->items[ret_node->size++] = (KeyValuePair) {
- .key = STATIC_CSTR_TO_STRING("augmentation"),
- .value = STRING_OBJ(asgn_type == kExprAsgnPlain
- ? (String)STRING_INIT
- : cstr_to_string(expr_asgn_type_tab[asgn_type])),
- };
+ String str = (asgn_type == kExprAsgnPlain
+ ? (String)STRING_INIT : cstr_as_string(expr_asgn_type_tab[asgn_type]));
+ PUT_C(*ret_node, "augmentation", STRING_OBJ(str));
break;
}
case kExprNodeMissing:
@@ -768,6 +646,7 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight, E
}
}
kvi_destroy(ast_conv_stack);
+ PUT_C(ret, "ast", ast);
assert(ret.size == ret.capacity);
// Should be a no-op actually, leaving it in case non-nodes will need to be
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index 4e23717dc6..543c7b8113 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -7,24 +7,33 @@
#include "nvim/api/private/defs.h"
#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/api/tabpage.h"
#include "nvim/api/win_config.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/decoration.h"
+#include "nvim/decoration_defs.h"
#include "nvim/drawscreen.h"
-#include "nvim/func_attr.h"
+#include "nvim/eval/window.h"
+#include "nvim/extmark_defs.h"
#include "nvim/globals.h"
-#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/option.h"
+#include "nvim/option_vars.h"
#include "nvim/pos_defs.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_compositor.h"
+#include "nvim/ui_defs.h"
+#include "nvim/vim_defs.h"
#include "nvim/window.h"
#include "nvim/winfloat.h"
@@ -32,9 +41,9 @@
# include "api/win_config.c.generated.h"
#endif
-/// Open a new window.
+/// Opens a new split window, or a floating window if `relative` is specified,
+/// or an external window (managed by the UI) if `external` is specified.
///
-/// Currently this is used to open floating and external windows.
/// Floats are windows that are drawn above the split layout, at some anchor
/// position in some other window. Floats can be drawn internally or by external
/// GUI with the |ui-multigrid| extension. External windows are only supported
@@ -42,8 +51,17 @@
///
/// For a general overview of floats, see |api-floatwin|.
///
-/// Exactly one of `external` and `relative` must be specified. The `width` and
-/// `height` of the new window must be specified.
+/// The `width` and `height` of the new window must be specified when opening
+/// a floating window, but are optional for normal windows.
+///
+/// If `relative` and `external` are omitted, a normal "split" window is created.
+/// The `win` property determines which window will be split. If no `win` is
+/// provided or `win == 0`, a window will be created adjacent to the current window.
+/// If -1 is provided, a top-level split will be created. `vertical` and `split` are
+/// only valid for normal windows, and are used to control split direction. For `vertical`,
+/// the exact direction is determined by |'splitright'| and |'splitbelow'|.
+/// Split windows cannot have `bufpos`/`row`/`col`/`border`/`title`/`footer`
+/// properties.
///
/// With relative=editor (row=0,col=0) refers to the top-left corner of the
/// screen-grid and (row=Lines-1,col=Columns-1) refers to the bottom-right
@@ -68,6 +86,14 @@
/// ```lua
/// vim.api.nvim_open_win(0, false,
/// {relative='win', width=12, height=3, bufpos={100,10}})
+/// ```
+///
+/// Example (Lua): vertical split left of the current window
+///
+/// ```lua
+/// vim.api.nvim_open_win(0, false, {
+/// split = 'left',
+/// win = 0
/// })
/// ```
///
@@ -80,7 +106,8 @@
/// - "win" Window given by the `win` field, or current window.
/// - "cursor" Cursor position in current window.
/// - "mouse" Mouse position
-/// - win: |window-ID| for relative="win".
+/// - win: |window-ID| window to split, or relative window when creating a
+/// float (relative="win").
/// - anchor: Decides which corner of the float to place at (row,col):
/// - "NW" northwest (default)
/// - "NE" northeast
@@ -89,12 +116,12 @@
/// - width: Window width (in character cells). Minimum of 1.
/// - height: Window height (in character cells). Minimum of 1.
/// - bufpos: Places float relative to buffer text (only when
-/// relative="win"). Takes a tuple of zero-indexed [line, column].
-/// `row` and `col` if given are applied relative to this
-/// position, else they default to:
-/// - `row=1` and `col=0` if `anchor` is "NW" or "NE"
-/// - `row=0` and `col=0` if `anchor` is "SW" or "SE"
-/// (thus like a tooltip near the buffer text).
+/// relative="win"). Takes a tuple of zero-indexed `[line, column]`.
+/// `row` and `col` if given are applied relative to this
+/// position, else they default to:
+/// - `row=1` and `col=0` if `anchor` is "NW" or "NE"
+/// - `row=0` and `col=0` if `anchor` is "SW" or "SE"
+/// (thus like a tooltip near the buffer text).
/// - row: Row position in units of "screen cell height", may be fractional.
/// - col: Column position in units of "screen cell width", may be
/// fractional.
@@ -126,7 +153,7 @@
/// 'fillchars' to a space char, and clearing the
/// |hl-EndOfBuffer| region in 'winhighlight'.
/// - border: Style of (optional) window border. This can either be a string
-/// or an array. The string values are
+/// or an array. The string values are
/// - "none": No border (default).
/// - "single": A single line box.
/// - "double": A double line box.
@@ -134,21 +161,31 @@
/// - "solid": Adds padding by a single whitespace cell.
/// - "shadow": A drop shadow effect by blending with the background.
/// - If it is an array, it should have a length of eight or any divisor of
-/// eight. The array will specify the eight chars building up the border
-/// in a clockwise fashion starting with the top-left corner. As an
-/// example, the double box style could be specified as
+/// eight. The array will specify the eight chars building up the border
+/// in a clockwise fashion starting with the top-left corner. As an
+/// example, the double box style could be specified as:
+/// ```
/// [ "â•”", "â•" ,"â•—", "â•‘", "â•", "â•", "╚", "â•‘" ].
-/// If the number of chars are less than eight, they will be repeated. Thus
-/// an ASCII border could be specified as
+/// ```
+/// If the number of chars are less than eight, they will be repeated. Thus
+/// an ASCII border could be specified as
+/// ```
/// [ "/", "-", \"\\\\\", "|" ],
-/// or all chars the same as
+/// ```
+/// or all chars the same as
+/// ```
/// [ "x" ].
+/// ```
/// An empty string can be used to turn off a specific border, for instance,
+/// ```
/// [ "", "", "", ">", "", "", "", "<" ]
+/// ```
/// will only make vertical borders but not horizontal ones.
/// By default, `FloatBorder` highlight is used, which links to `WinSeparator`
/// when not defined. It could also be specified by character:
+/// ```
/// [ ["+", "MyCorner"], ["x", "MyBorder"] ].
+/// ```
/// - title: Title (optional) in window border, string or list.
/// List should consist of `[text, highlight]` tuples.
/// If string, the default highlight group is `FloatTitle`.
@@ -167,43 +204,90 @@
/// - fixed: If true when anchor is NW or SW, the float window
/// would be kept fixed even if the window would be truncated.
/// - hide: If true the floating window will be hidden.
+/// - vertical: Split vertically |:vertical|.
+/// - split: Split direction: "left", "right", "above", "below".
///
/// @param[out] err Error details, if any
///
/// @return Window handle, or 0 on error
-Window nvim_open_win(Buffer buffer, Boolean enter, Dict(float_config) *config, Error *err)
- FUNC_API_SINCE(6)
- FUNC_API_TEXTLOCK_ALLOW_CMDWIN
+Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Error *err)
+ FUNC_API_SINCE(6) FUNC_API_TEXTLOCK_ALLOW_CMDWIN
{
+#define HAS_KEY_X(d, key) HAS_KEY(d, win_config, key)
buf_T *buf = find_buffer_by_handle(buffer, err);
if (!buf) {
return 0;
}
- if (cmdwin_type != 0 && (enter || buf == curbuf)) {
+ if ((cmdwin_type != 0 && enter) || buf == cmdwin_buf) {
api_set_error(err, kErrorTypeException, "%s", e_cmdwin);
return 0;
}
- FloatConfig fconfig = FLOAT_CONFIG_INIT;
+ WinConfig fconfig = WIN_CONFIG_INIT;
if (!parse_float_config(config, &fconfig, false, true, err)) {
return 0;
}
- win_T *wp = win_new_float(NULL, false, fconfig, err);
+
+ bool is_split = HAS_KEY_X(config, split) || HAS_KEY_X(config, vertical);
+
+ win_T *wp = NULL;
+ tabpage_T *tp = curtab;
+ if (is_split) {
+ win_T *parent = NULL;
+ if (config->win != -1) {
+ parent = find_window_by_handle(fconfig.window, err);
+ if (!parent) {
+ // find_window_by_handle has already set the error
+ return 0;
+ } else if (parent->w_floating) {
+ api_set_error(err, kErrorTypeException, "Cannot split a floating window");
+ return 0;
+ }
+ }
+
+ if (HAS_KEY_X(config, vertical) && !HAS_KEY_X(config, split)) {
+ if (config->vertical) {
+ fconfig.split = p_spr ? kWinSplitRight : kWinSplitLeft;
+ } else {
+ fconfig.split = p_sb ? kWinSplitBelow : kWinSplitAbove;
+ }
+ }
+ int flags = win_split_flags(fconfig.split, parent == NULL) | WSP_NOENTER;
+
+ if (parent == NULL) {
+ wp = win_split_ins(0, flags, NULL, 0);
+ } else {
+ tp = win_find_tabpage(parent);
+ switchwin_T switchwin;
+ // `parent` is valid in `tp`, so switch_win should not fail.
+ const int result = switch_win(&switchwin, parent, tp, true);
+ (void)result;
+ assert(result == OK);
+ wp = win_split_ins(0, flags, NULL, 0);
+ restore_win(&switchwin, true);
+ }
+ if (wp) {
+ wp->w_config = fconfig;
+ }
+ } else {
+ wp = win_new_float(NULL, false, fconfig, err);
+ }
if (!wp) {
+ api_set_error(err, kErrorTypeException, "Failed to create window");
return 0;
}
+ switchwin_T switchwin;
+ if (switch_win_noblock(&switchwin, wp, tp, true) == OK) {
+ apply_autocmds(EVENT_WINNEW, NULL, NULL, false, curbuf);
+ }
+ restore_win_noblock(&switchwin, true);
if (enter) {
- win_enter(wp, false);
+ goto_tabpage_win(tp, wp);
}
- // autocmds in win_enter or win_set_buf below may close the window
- if (win_valid(wp) && buffer > 0) {
- Boolean noautocmd = !enter || fconfig.noautocmd;
- win_set_buf(wp, buf, noautocmd, err);
- if (!fconfig.noautocmd) {
- apply_autocmds(EVENT_WINNEW, NULL, NULL, false, buf);
- }
+ if (win_valid_any_tab(wp) && buf != wp->w_buffer) {
+ win_set_buf(wp, buf, !enter || fconfig.noautocmd, err);
}
- if (!win_valid(wp)) {
+ if (!win_valid_any_tab(wp)) {
api_set_error(err, kErrorTypeException, "Window was closed immediately");
return 0;
}
@@ -213,6 +297,37 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(float_config) *config, E
didset_window_options(wp, true);
}
return wp->handle;
+#undef HAS_KEY_X
+}
+
+static WinSplit win_split_dir(win_T *win)
+{
+ if (win->w_frame == NULL || win->w_frame->fr_parent == NULL) {
+ return kWinSplitLeft;
+ }
+
+ char layout = win->w_frame->fr_parent->fr_layout;
+ if (layout == FR_COL) {
+ return win->w_frame->fr_next ? kWinSplitAbove : kWinSplitBelow;
+ } else {
+ return win->w_frame->fr_next ? kWinSplitLeft : kWinSplitRight;
+ }
+}
+
+static int win_split_flags(WinSplit split, bool toplevel)
+{
+ int flags = 0;
+ if (split == kWinSplitAbove || split == kWinSplitBelow) {
+ flags |= WSP_HOR;
+ } else {
+ flags |= WSP_VERT;
+ }
+ if (split == kWinSplitAbove || split == kWinSplitLeft) {
+ flags |= toplevel ? WSP_TOP : WSP_ABOVE;
+ } else {
+ flags |= toplevel ? WSP_BOT : WSP_BELOW;
+ }
+ return flags;
}
/// Configures window layout. Currently only for floating and external windows
@@ -227,61 +342,231 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(float_config) *config, E
/// @param config Map defining the window configuration,
/// see |nvim_open_win()|
/// @param[out] err Error details, if any
-void nvim_win_set_config(Window window, Dict(float_config) *config, Error *err)
+void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
FUNC_API_SINCE(6)
{
+#define HAS_KEY_X(d, key) HAS_KEY(d, win_config, key)
win_T *win = find_window_by_handle(window, err);
if (!win) {
return;
}
- bool new_float = !win->w_floating;
+ tabpage_T *win_tp = win_find_tabpage(win);
+ bool was_split = !win->w_floating;
+ bool has_split = HAS_KEY_X(config, split);
+ bool has_vertical = HAS_KEY_X(config, vertical);
// reuse old values, if not overridden
- FloatConfig fconfig = new_float ? FLOAT_CONFIG_INIT : win->w_float_config;
+ WinConfig fconfig = win->w_config;
- if (!parse_float_config(config, &fconfig, !new_float, false, err)) {
+ bool to_split = config->relative.size == 0
+ && !(HAS_KEY_X(config, external) ? config->external : fconfig.external)
+ && (has_split || has_vertical || was_split);
+
+ if (!parse_float_config(config, &fconfig, !was_split || to_split, false, err)) {
return;
}
- if (new_float) {
+ if (was_split && !to_split) {
if (!win_new_float(win, false, fconfig, err)) {
return;
}
redraw_later(win, UPD_NOT_VALID);
+ } else if (to_split) {
+ win_T *parent = NULL;
+ if (config->win != -1) {
+ parent = find_window_by_handle(fconfig.window, err);
+ if (!parent) {
+ return;
+ } else if (parent->w_floating) {
+ api_set_error(err, kErrorTypeException, "Cannot split a floating window");
+ return;
+ }
+ }
+
+ WinSplit old_split = win_split_dir(win);
+ if (has_vertical && !has_split) {
+ if (config->vertical) {
+ if (old_split == kWinSplitRight || p_spr) {
+ fconfig.split = kWinSplitRight;
+ } else {
+ fconfig.split = kWinSplitLeft;
+ }
+ } else {
+ if (old_split == kWinSplitBelow || p_sb) {
+ fconfig.split = kWinSplitBelow;
+ } else {
+ fconfig.split = kWinSplitAbove;
+ }
+ }
+ }
+ win->w_config = fconfig;
+
+ // If there's no "vertical" or "split" set, or if "split" is unchanged,
+ // then we can just change the size of the window.
+ if ((!has_vertical && !has_split)
+ || (was_split && !HAS_KEY_X(config, win) && old_split == fconfig.split)) {
+ if (HAS_KEY_X(config, width)) {
+ win_setwidth_win(fconfig.width, win);
+ }
+ if (HAS_KEY_X(config, height)) {
+ win_setheight_win(fconfig.height, win);
+ }
+ redraw_later(win, UPD_NOT_VALID);
+ return;
+ }
+
+ if (was_split) {
+ win_T *new_curwin = NULL;
+
+ // If the window is the last in the tabpage or `fconfig.win` is
+ // a handle to itself, we can't split it.
+ if (win->w_frame->fr_parent == NULL) {
+ // FIXME(willothy): if the window is the last in the tabpage but there is another tabpage
+ // and the target window is in that other tabpage, should we move the window to that
+ // tabpage and close the previous one, or just error?
+ api_set_error(err, kErrorTypeValidation, "Cannot move last window");
+ return;
+ } else if (parent != NULL && parent->handle == win->handle) {
+ int n_frames = 0;
+ for (frame_T *fr = win->w_frame->fr_parent->fr_child; fr != NULL; fr = fr->fr_next) {
+ n_frames++;
+ }
+
+ win_T *neighbor = NULL;
+
+ if (n_frames > 2) {
+ // There are three or more windows in the frame, we need to split a neighboring window.
+ frame_T *frame = win->w_frame->fr_parent;
+
+ if (frame->fr_parent) {
+ // ┌──────────────â”
+ // │ A │
+ // ├────┬────┬────┤
+ // │ B │ C │ D │
+ // └────┴────┴────┘
+ // ||
+ // \/
+ // ┌───────────────────â”
+ // │ A │
+ // ├─────────┬─────────┤
+ // │ │ C │
+ // │ B ├─────────┤
+ // │ │ D │
+ // └─────────┴─────────┘
+ if (fconfig.split == kWinSplitAbove || fconfig.split == kWinSplitLeft) {
+ neighbor = win->w_next;
+ } else {
+ neighbor = win->w_prev;
+ }
+ }
+ // If the frame doesn't have a parent, the old frame
+ // was the root frame and we need to create a top-level split.
+ int dir;
+ new_curwin = winframe_remove(win, &dir, win_tp == curtab ? NULL : win_tp);
+ } else if (n_frames == 2) {
+ // There are two windows in the frame, we can just rotate it.
+ int dir;
+ neighbor = winframe_remove(win, &dir, win_tp == curtab ? NULL : win_tp);
+ new_curwin = neighbor;
+ } else {
+ // There is only one window in the frame, we can't split it.
+ api_set_error(err, kErrorTypeValidation, "Cannot split window into itself");
+ return;
+ }
+ // Set the parent to whatever the correct
+ // neighbor window was determined to be.
+ parent = neighbor;
+ } else {
+ int dir;
+ new_curwin = winframe_remove(win, &dir, win_tp == curtab ? NULL : win_tp);
+ }
+ // move to neighboring window if we're moving the current window to a new tabpage
+ if (curwin == win && parent != NULL && new_curwin != NULL
+ && win_tp != win_find_tabpage(parent)) {
+ win_enter(new_curwin, true);
+ }
+ win_remove(win, win_tp == curtab ? NULL : win_tp);
+ } else {
+ win_remove(win, win_tp == curtab ? NULL : win_tp);
+ ui_comp_remove_grid(&win->w_grid_alloc);
+ if (win->w_config.external) {
+ for (tabpage_T *tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
+ if (tp == curtab) {
+ continue;
+ }
+ if (tp->tp_curwin == win) {
+ tp->tp_curwin = tp->tp_firstwin;
+ }
+ }
+ }
+ win->w_pos_changed = true;
+ }
+
+ int flags = win_split_flags(fconfig.split, parent == NULL);
+
+ if (parent == NULL) {
+ if (!win_split_ins(0, flags, win, 0)) {
+ // TODO(willothy): What should this error message say?
+ api_set_error(err, kErrorTypeException, "Failed to split window");
+ return;
+ }
+ } else {
+ win_execute_T args;
+
+ tabpage_T *tp = win_find_tabpage(parent);
+ if (!win_execute_before(&args, parent, tp)) {
+ // TODO(willothy): how should we handle this / what should the message be?
+ api_set_error(err, kErrorTypeException, "Failed to switch to tabpage %d", tp->handle);
+ win_execute_after(&args);
+ return;
+ }
+ // This should return the same ptr to `win`, but we check for
+ // NULL to detect errors.
+ win_T *res = win_split_ins(0, flags, win, 0);
+ win_execute_after(&args);
+ if (!res) {
+ // TODO(willothy): What should this error message say?
+ api_set_error(err, kErrorTypeException, "Failed to split window");
+ return;
+ }
+ }
+ if (HAS_KEY_X(config, width)) {
+ win_setwidth_win(fconfig.width, win);
+ }
+ if (HAS_KEY_X(config, height)) {
+ win_setheight_win(fconfig.height, win);
+ }
+ redraw_later(win, UPD_NOT_VALID);
+ return;
} else {
win_config_float(win, fconfig);
win->w_pos_changed = true;
}
- if (HAS_KEY(config, float_config, style)) {
+ if (HAS_KEY_X(config, style)) {
if (fconfig.style == kWinStyleMinimal) {
win_set_minimal_style(win);
didset_window_options(win, true);
}
}
+#undef HAS_KEY_X
}
-static Dictionary config_put_bordertext(Dictionary config, FloatConfig *fconfig,
- BorderTextType bordertext_type)
+#define PUT_KEY_X(d, key, value) PUT_KEY(d, win_config, key, value)
+static void config_put_bordertext(Dict(win_config) *config, WinConfig *fconfig,
+ BorderTextType bordertext_type, Arena *arena)
{
VirtText vt;
AlignTextPos align;
- char *field_name;
- char *field_pos_name;
switch (bordertext_type) {
case kBorderTextTitle:
vt = fconfig->title_chunks;
align = fconfig->title_pos;
- field_name = "title";
- field_pos_name = "title_pos";
break;
case kBorderTextFooter:
vt = fconfig->footer_chunks;
align = fconfig->footer_pos;
- field_name = "footer";
- field_pos_name = "footer_pos";
break;
}
- Array bordertext = virt_text_to_array(vt, true);
- PUT(config, field_name, ARRAY_OBJ(bordertext));
+ Array bordertext = virt_text_to_array(vt, true, arena);
char *pos;
switch (align) {
@@ -295,9 +580,16 @@ static Dictionary config_put_bordertext(Dictionary config, FloatConfig *fconfig,
pos = "right";
break;
}
- PUT(config, field_pos_name, CSTR_TO_OBJ(pos));
- return config;
+ switch (bordertext_type) {
+ case kBorderTextTitle:
+ PUT_KEY_X(*config, title, ARRAY_OBJ(bordertext));
+ PUT_KEY_X(*config, title_pos, cstr_as_string(pos));
+ break;
+ case kBorderTextFooter:
+ PUT_KEY_X(*config, footer, ARRAY_OBJ(bordertext));
+ PUT_KEY_X(*config, footer_pos, cstr_as_string(pos));
+ }
}
/// Gets window configuration.
@@ -309,70 +601,80 @@ static Dictionary config_put_bordertext(Dictionary config, FloatConfig *fconfig,
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
/// @return Map defining the window configuration, see |nvim_open_win()|
-Dictionary nvim_win_get_config(Window window, Error *err)
+Dict(win_config) nvim_win_get_config(Window window, Arena *arena, Error *err)
FUNC_API_SINCE(6)
{
- Dictionary rv = ARRAY_DICT_INIT;
+ /// Keep in sync with FloatRelative in buffer_defs.h
+ static const char *const float_relative_str[] = { "editor", "win", "cursor", "mouse" };
+
+ /// Keep in sync with WinSplit in buffer_defs.h
+ static const char *const win_split_str[] = { "left", "right", "above", "below" };
+
+ Dict(win_config) rv = KEYDICT_INIT;
win_T *wp = find_window_by_handle(window, err);
if (!wp) {
return rv;
}
- FloatConfig *config = &wp->w_float_config;
+ WinConfig *config = &wp->w_config;
- PUT(rv, "focusable", BOOLEAN_OBJ(config->focusable));
- PUT(rv, "external", BOOLEAN_OBJ(config->external));
- PUT(rv, "hide", BOOLEAN_OBJ(config->hide));
+ PUT_KEY_X(rv, focusable, config->focusable);
+ PUT_KEY_X(rv, external, config->external);
+ PUT_KEY_X(rv, hide, config->hide);
if (wp->w_floating) {
- PUT(rv, "width", INTEGER_OBJ(config->width));
- PUT(rv, "height", INTEGER_OBJ(config->height));
+ PUT_KEY_X(rv, width, config->width);
+ PUT_KEY_X(rv, height, config->height);
if (!config->external) {
if (config->relative == kFloatRelativeWindow) {
- PUT(rv, "win", INTEGER_OBJ(config->window));
+ PUT_KEY_X(rv, win, config->window);
if (config->bufpos.lnum >= 0) {
- Array pos = ARRAY_DICT_INIT;
- ADD(pos, INTEGER_OBJ(config->bufpos.lnum));
- ADD(pos, INTEGER_OBJ(config->bufpos.col));
- PUT(rv, "bufpos", ARRAY_OBJ(pos));
+ Array pos = arena_array(arena, 2);
+ ADD_C(pos, INTEGER_OBJ(config->bufpos.lnum));
+ ADD_C(pos, INTEGER_OBJ(config->bufpos.col));
+ PUT_KEY_X(rv, bufpos, pos);
}
}
- 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));
+ PUT_KEY_X(rv, anchor, cstr_as_string(float_anchor_str[config->anchor]));
+ PUT_KEY_X(rv, row, config->row);
+ PUT_KEY_X(rv, col, config->col);
+ PUT_KEY_X(rv, zindex, config->zindex);
}
if (config->border) {
- Array border = ARRAY_DICT_INIT;
+ Array border = arena_array(arena, 8);
for (size_t i = 0; i < 8; i++) {
- Array tuple = ARRAY_DICT_INIT;
-
- String s = cstrn_to_string(config->border_chars[i], MAX_SCHAR_SIZE);
+ String s = cstrn_as_string(config->border_chars[i], MAX_SCHAR_SIZE);
int hi_id = config->border_hl_ids[i];
char *hi_name = syn_id2name(hi_id);
if (hi_name[0]) {
- ADD(tuple, STRING_OBJ(s));
- ADD(tuple, CSTR_TO_OBJ(hi_name));
- ADD(border, ARRAY_OBJ(tuple));
+ Array tuple = arena_array(arena, 2);
+ ADD_C(tuple, STRING_OBJ(s));
+ ADD_C(tuple, CSTR_AS_OBJ(hi_name));
+ ADD_C(border, ARRAY_OBJ(tuple));
} else {
- ADD(border, STRING_OBJ(s));
+ ADD_C(border, STRING_OBJ(s));
}
}
- PUT(rv, "border", ARRAY_OBJ(border));
+ PUT_KEY_X(rv, border, ARRAY_OBJ(border));
if (config->title) {
- rv = config_put_bordertext(rv, config, kBorderTextTitle);
+ config_put_bordertext(&rv, config, kBorderTextTitle, arena);
}
if (config->footer) {
- rv = config_put_bordertext(rv, config, kBorderTextFooter);
+ config_put_bordertext(&rv, config, kBorderTextFooter, arena);
}
}
+ } else if (!config->external) {
+ PUT_KEY_X(rv, width, wp->w_width);
+ PUT_KEY_X(rv, height, wp->w_height);
+ WinSplit split = win_split_dir(wp);
+ PUT_KEY_X(rv, split, cstr_as_string(win_split_str[split]));
}
const char *rel = (wp->w_floating && !config->external
? float_relative_str[config->relative] : "");
- PUT(rv, "relative", CSTR_TO_OBJ(rel));
+ PUT_KEY_X(rv, relative, cstr_as_string(rel));
return rv;
}
@@ -414,10 +716,26 @@ static bool parse_float_relative(String relative, FloatRelative *out)
return true;
}
+static bool parse_config_split(String split, WinSplit *out)
+{
+ char *str = split.data;
+ if (striequal(str, "left")) {
+ *out = kWinSplitLeft;
+ } else if (striequal(str, "right")) {
+ *out = kWinSplitRight;
+ } else if (striequal(str, "above")) {
+ *out = kWinSplitAbove;
+ } else if (striequal(str, "below")) {
+ *out = kWinSplitBelow;
+ } else {
+ return false;
+ }
+ return true;
+}
+
static bool parse_float_bufpos(Array bufpos, lpos_T *out)
{
- if (bufpos.size != 2
- || bufpos.items[0].type != kObjectTypeInteger
+ if (bufpos.size != 2 || bufpos.items[0].type != kObjectTypeInteger
|| bufpos.items[1].type != kObjectTypeInteger) {
return false;
}
@@ -426,21 +744,39 @@ static bool parse_float_bufpos(Array bufpos, lpos_T *out)
return true;
}
-static void parse_bordertext(Object bordertext, BorderTextType bordertext_type,
- FloatConfig *fconfig, Error *err)
+static void parse_bordertext(Object bordertext, BorderTextType bordertext_type, WinConfig *fconfig,
+ Error *err)
{
+ if (bordertext.type != kObjectTypeString && bordertext.type != kObjectTypeArray) {
+ api_set_error(err, kErrorTypeValidation, "title/footer must be string or array");
+ return;
+ }
+
+ if (bordertext.type == kObjectTypeArray && bordertext.data.array.size == 0) {
+ api_set_error(err, kErrorTypeValidation, "title/footer cannot be an empty array");
+ return;
+ }
+
bool *is_present;
VirtText *chunks;
int *width;
int default_hl_id;
switch (bordertext_type) {
case kBorderTextTitle:
+ if (fconfig->title) {
+ clear_virttext(&fconfig->title_chunks);
+ }
+
is_present = &fconfig->title;
chunks = &fconfig->title_chunks;
width = &fconfig->title_width;
default_hl_id = syn_check_group(S_LEN("FloatTitle"));
break;
case kBorderTextFooter:
+ if (fconfig->footer) {
+ clear_virttext(&fconfig->footer_chunks);
+ }
+
is_present = &fconfig->footer;
chunks = &fconfig->footer_chunks;
width = &fconfig->footer_width;
@@ -460,16 +796,6 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type,
return;
}
- if (bordertext.type != kObjectTypeArray) {
- api_set_error(err, kErrorTypeValidation, "title must be string or array");
- return;
- }
-
- if (bordertext.data.array.size == 0) {
- api_set_error(err, kErrorTypeValidation, "title cannot be an empty array");
- return;
- }
-
*width = 0;
*chunks = parse_virt_text(bordertext.data.array, err, width);
@@ -477,7 +803,7 @@ static void parse_bordertext(Object bordertext, BorderTextType bordertext_type,
}
static bool parse_bordertext_pos(String bordertext_pos, BorderTextType bordertext_type,
- FloatConfig *fconfig, Error *err)
+ WinConfig *fconfig, Error *err)
{
AlignTextPos *align;
switch (bordertext_type) {
@@ -516,7 +842,7 @@ static bool parse_bordertext_pos(String bordertext_pos, BorderTextType bordertex
return true;
}
-static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
+static void parse_border_style(Object style, WinConfig *fconfig, Error *err)
{
struct {
const char *name;
@@ -531,7 +857,7 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
{ NULL, { { NUL } }, false },
};
- char (*chars)[MAX_SCHAR_SIZE] = fconfig->border_chars;
+ char(*chars)[MAX_SCHAR_SIZE] = fconfig->border_chars;
int *hl_ids = fconfig->border_hl_ids;
fconfig->border = true;
@@ -540,8 +866,7 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
Array arr = style.data.array;
size_t size = arr.size;
if (!size || size > 8 || (size & (size - 1))) {
- api_set_error(err, kErrorTypeValidation,
- "invalid number of border chars");
+ api_set_error(err, kErrorTypeValidation, "invalid number of border chars");
return;
}
for (size_t i = 0; i < size; i++) {
@@ -571,10 +896,8 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
api_set_error(err, kErrorTypeValidation, "invalid border char");
return;
}
- if (string.size
- && mb_string2cells_len(string.data, string.size) > 1) {
- api_set_error(err, kErrorTypeValidation,
- "border chars must be one cell");
+ if (string.size && mb_string2cells_len(string.data, string.size) > 1) {
+ api_set_error(err, kErrorTypeValidation, "border chars must be one cell");
return;
}
size_t len = MIN(string.size, sizeof(*chars) - 1);
@@ -593,8 +916,7 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
|| (chars[1][0] && chars[3][0] && !chars[2][0])
|| (chars[3][0] && chars[5][0] && !chars[4][0])
|| (chars[5][0] && chars[7][0] && !chars[6][0])) {
- api_set_error(err, kErrorTypeValidation,
- "corner between used edges must be specified");
+ api_set_error(err, kErrorTypeValidation, "corner between used edges must be specified");
}
} else if (style.type == kObjectTypeString) {
String str = style.data.string;
@@ -621,26 +943,24 @@ static void parse_border_style(Object style, FloatConfig *fconfig, Error *err)
return;
}
}
- api_set_error(err, kErrorTypeValidation,
- "invalid border style \"%s\"", str.data);
+ api_set_error(err, kErrorTypeValidation, "invalid border style \"%s\"", str.data);
}
}
-static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig, bool reconf,
+static bool parse_float_config(Dict(win_config) *config, WinConfig *fconfig, bool reconf,
bool new_win, Error *err)
{
-#define HAS_KEY_X(d, key) HAS_KEY(d, float_config, key)
- bool has_relative = false, relative_is_win = false;
- // ignore empty string, to match nvim_win_get_config
- if (HAS_KEY_X(config, relative) && config->relative.size > 0) {
+#define HAS_KEY_X(d, key) HAS_KEY(d, win_config, key)
+ bool has_relative = false, relative_is_win = false, is_split = false;
+ if (config->relative.size > 0) {
if (!parse_float_relative(config->relative, &fconfig->relative)) {
api_set_error(err, kErrorTypeValidation, "Invalid value of 'relative' key");
return false;
}
- if (!(HAS_KEY_X(config, row) && HAS_KEY_X(config, col)) && !HAS_KEY_X(config, bufpos)) {
- api_set_error(err, kErrorTypeValidation,
- "'relative' requires 'row'/'col' or 'bufpos'");
+ if (config->relative.size > 0 && !(HAS_KEY_X(config, row) && HAS_KEY_X(config, col))
+ && !HAS_KEY_X(config, bufpos)) {
+ api_set_error(err, kErrorTypeValidation, "'relative' requires 'row'/'col' or 'bufpos'");
return false;
}
@@ -650,6 +970,32 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
relative_is_win = true;
fconfig->bufpos.lnum = -1;
}
+ } else if (!config->external) {
+ if (HAS_KEY_X(config, vertical) || HAS_KEY_X(config, split)) {
+ is_split = true;
+ } else if (new_win) {
+ api_set_error(err, kErrorTypeValidation,
+ "Must specify 'relative' or 'external' when creating a float");
+ return false;
+ }
+ }
+
+ if (HAS_KEY_X(config, vertical)) {
+ if (!is_split) {
+ api_set_error(err, kErrorTypeValidation, "floating windows cannot have 'vertical'");
+ return false;
+ }
+ }
+
+ if (HAS_KEY_X(config, split)) {
+ if (!is_split) {
+ api_set_error(err, kErrorTypeValidation, "floating windows cannot have 'split'");
+ return false;
+ }
+ if (!parse_config_split(config->split, &fconfig->split)) {
+ api_set_error(err, kErrorTypeValidation, "Invalid value of 'split' key");
+ return false;
+ }
}
if (HAS_KEY_X(config, anchor)) {
@@ -660,7 +1006,7 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
}
if (HAS_KEY_X(config, row)) {
- if (!has_relative) {
+ if (!has_relative || is_split) {
api_set_error(err, kErrorTypeValidation, "non-float cannot have 'row'");
return false;
}
@@ -668,7 +1014,7 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
}
if (HAS_KEY_X(config, col)) {
- if (!has_relative) {
+ if (!has_relative || is_split) {
api_set_error(err, kErrorTypeValidation, "non-float cannot have 'col'");
return false;
}
@@ -676,7 +1022,7 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
}
if (HAS_KEY_X(config, bufpos)) {
- if (!has_relative) {
+ if (!has_relative || is_split) {
api_set_error(err, kErrorTypeValidation, "non-float cannot have 'bufpos'");
return false;
} else {
@@ -701,7 +1047,7 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
api_set_error(err, kErrorTypeValidation, "'width' key must be a positive Integer");
return false;
}
- } else if (!reconf) {
+ } else if (!reconf && !is_split) {
api_set_error(err, kErrorTypeValidation, "Must specify 'width'");
return false;
}
@@ -713,21 +1059,22 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
api_set_error(err, kErrorTypeValidation, "'height' key must be a positive Integer");
return false;
}
- } else if (!reconf) {
+ } else if (!reconf && !is_split) {
api_set_error(err, kErrorTypeValidation, "Must specify 'height'");
return false;
}
- if (relative_is_win) {
+ if (relative_is_win || is_split) {
fconfig->window = curwin->handle;
if (HAS_KEY_X(config, win)) {
if (config->win > 0) {
fconfig->window = config->win;
}
}
- } else {
+ } else if (has_relative) {
if (HAS_KEY_X(config, win)) {
- api_set_error(err, kErrorTypeValidation, "'win' key is only valid with relative='win'");
+ api_set_error(err, kErrorTypeValidation,
+ "'win' key is only valid with relative='win' and relative=''");
return false;
}
}
@@ -740,23 +1087,20 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
return false;
}
if (fconfig->external && !ui_has(kUIMultigrid)) {
- api_set_error(err, kErrorTypeValidation,
- "UI doesn't support external windows");
+ api_set_error(err, kErrorTypeValidation, "UI doesn't support external windows");
return false;
}
}
- if (!reconf && (!has_relative && !fconfig->external)) {
- api_set_error(err, kErrorTypeValidation,
- "One of 'relative' and 'external' must be used");
- return false;
- }
-
if (HAS_KEY_X(config, focusable)) {
fconfig->focusable = config->focusable;
}
if (HAS_KEY_X(config, zindex)) {
+ if (is_split) {
+ api_set_error(err, kErrorTypeValidation, "non-float cannot have 'zindex'");
+ return false;
+ }
if (config->zindex > 0) {
fconfig->zindex = (int)config->zindex;
} else {
@@ -766,16 +1110,16 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
}
if (HAS_KEY_X(config, title)) {
+ if (is_split) {
+ api_set_error(err, kErrorTypeValidation, "non-float cannot have 'title'");
+ return false;
+ }
// title only work with border
if (!HAS_KEY_X(config, border) && !fconfig->border) {
api_set_error(err, kErrorTypeException, "title requires border to be set");
return false;
}
- if (fconfig->title) {
- clear_virttext(&fconfig->title_chunks);
- }
-
parse_bordertext(config->title, kBorderTextTitle, fconfig, err);
if (ERROR_SET(err)) {
return false;
@@ -793,16 +1137,16 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
}
if (HAS_KEY_X(config, footer)) {
+ if (is_split) {
+ api_set_error(err, kErrorTypeValidation, "non-float cannot have 'footer'");
+ return false;
+ }
// footer only work with border
if (!HAS_KEY_X(config, border) && !fconfig->border) {
api_set_error(err, kErrorTypeException, "footer requires border to be set");
return false;
}
- if (fconfig->footer) {
- clear_virttext(&fconfig->footer_chunks);
- }
-
parse_bordertext(config->footer, kBorderTextFooter, fconfig, err);
if (ERROR_SET(err)) {
return false;
@@ -820,6 +1164,10 @@ static bool parse_float_config(Dict(float_config) *config, FloatConfig *fconfig,
}
if (HAS_KEY_X(config, border)) {
+ if (is_split) {
+ api_set_error(err, kErrorTypeValidation, "non-float cannot have 'border'");
+ return false;
+ }
parse_border_style(config->border, fconfig, err);
if (ERROR_SET(err)) {
return false;
diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c
index de5b40940f..ed51eedf1b 100644
--- a/src/nvim/api/window.c
+++ b/src/nvim/api/window.c
@@ -15,11 +15,10 @@
#include "nvim/drawscreen.h"
#include "nvim/eval/window.h"
#include "nvim/ex_docmd.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/lua/executor.h"
-#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/plines.h"
@@ -27,6 +26,10 @@
#include "nvim/types_defs.h"
#include "nvim/window.h"
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "api/window.c.generated.h"
+#endif
+
/// Gets the current buffer in a window
///
/// @param window Window handle, or 0 for current window
@@ -58,7 +61,7 @@ void nvim_win_set_buf(Window window, Buffer buffer, Error *err)
if (!win || !buf) {
return;
}
- if (cmdwin_type != 0 && (win == curwin || win == cmdwin_old_curwin || buf == curbuf)) {
+ if (win == cmdwin_win || win == cmdwin_old_curwin || buf == cmdwin_buf) {
api_set_error(err, kErrorTypeException, "%s", e_cmdwin);
return;
}
@@ -74,15 +77,16 @@ void nvim_win_set_buf(Window window, Buffer buffer, Error *err)
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
/// @return (row, col) tuple
-ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Error *err)
+ArrayOf(Integer, 2) nvim_win_get_cursor(Window window, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
win_T *win = find_window_by_handle(window, err);
if (win) {
- ADD(rv, INTEGER_OBJ(win->w_cursor.lnum));
- ADD(rv, INTEGER_OBJ(win->w_cursor.col));
+ rv = arena_array(arena, 2);
+ ADD_C(rv, INTEGER_OBJ(win->w_cursor.lnum));
+ ADD_C(rv, INTEGER_OBJ(win->w_cursor.col));
}
return rv;
@@ -234,7 +238,7 @@ void nvim_win_set_width(Window window, Integer width, Error *err)
/// @param name Variable name
/// @param[out] err Error details, if any
/// @return Variable value
-Object nvim_win_get_var(Window window, String name, Error *err)
+Object nvim_win_get_var(Window window, String name, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
win_T *win = find_window_by_handle(window, err);
@@ -243,7 +247,7 @@ Object nvim_win_get_var(Window window, String name, Error *err)
return (Object)OBJECT_INIT;
}
- return dict_get_value(win->w_vars, name, err);
+ return dict_get_value(win->w_vars, name, arena, err);
}
/// Sets a window-scoped (w:) variable
@@ -261,7 +265,7 @@ void nvim_win_set_var(Window window, String name, Object value, Error *err)
return;
}
- dict_set_var(win->w_vars, name, value, false, false, err);
+ dict_set_var(win->w_vars, name, value, false, false, NULL, err);
}
/// Removes a window-scoped (w:) variable
@@ -278,7 +282,7 @@ void nvim_win_del_var(Window window, String name, Error *err)
return;
}
- dict_set_var(win->w_vars, name, NIL, true, false, err);
+ dict_set_var(win->w_vars, name, NIL, true, false, NULL, err);
}
/// Gets the window position in display cells. First position is zero.
@@ -286,15 +290,16 @@ void nvim_win_del_var(Window window, String name, Error *err)
/// @param window Window handle, or 0 for current window
/// @param[out] err Error details, if any
/// @return (row, col) tuple with the window position
-ArrayOf(Integer, 2) nvim_win_get_position(Window window, Error *err)
+ArrayOf(Integer, 2) nvim_win_get_position(Window window, Arena *arena, Error *err)
FUNC_API_SINCE(1)
{
Array rv = ARRAY_DICT_INIT;
win_T *win = find_window_by_handle(window, err);
if (win) {
- ADD(rv, INTEGER_OBJ(win->w_winrow));
- ADD(rv, INTEGER_OBJ(win->w_wincol));
+ rv = arena_array(arena, 2);
+ ADD_C(rv, INTEGER_OBJ(win->w_winrow));
+ ADD_C(rv, INTEGER_OBJ(win->w_wincol));
}
return rv;
@@ -418,8 +423,7 @@ void nvim_win_close(Window window, Boolean force, Error *err)
/// @param fun Function to call inside the window (currently Lua callable
/// only)
/// @param[out] err Error details, if any
-/// @return Return value of function. NB: will deepcopy Lua values
-/// currently, use upvalues to send Lua references in and out.
+/// @return Return value of function.
Object nvim_win_call(Window window, LuaRef fun, Error *err)
FUNC_API_SINCE(7)
FUNC_API_LUA_ONLY
@@ -432,10 +436,12 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err)
try_start();
Object res = OBJECT_INIT;
- WIN_EXECUTE(win, tabpage, {
+ win_execute_T win_execute_args;
+ if (win_execute_before(&win_execute_args, win, tabpage)) {
Array args = ARRAY_DICT_INIT;
- res = nlua_call_ref(fun, NULL, args, true, err);
- });
+ res = nlua_call_ref(fun, NULL, args, kRetLuaref, NULL, err);
+ }
+ win_execute_after(&win_execute_args);
try_end(err);
return res;
}
@@ -446,6 +452,7 @@ Object nvim_win_call(Window window, LuaRef fun, Error *err)
///
/// This takes precedence over the 'winhighlight' option.
///
+/// @param window
/// @param ns_id the namespace to use
/// @param[out] err Error details, if any
void nvim_win_set_hl_ns(Window window, Integer ns_id, Error *err)
diff --git a/src/nvim/arabic.c b/src/nvim/arabic.c
index 84f4297c99..4587415c3b 100644
--- a/src/nvim/arabic.c
+++ b/src/nvim/arabic.c
@@ -22,7 +22,6 @@
#include "nvim/arabic.h"
#include "nvim/ascii_defs.h"
-#include "nvim/func_attr.h"
#include "nvim/macros_defs.h"
#include "nvim/option_vars.h"
@@ -258,6 +257,7 @@ bool arabic_maycombine(int two)
}
/// Check whether we are dealing with Arabic combining characters.
+/// Returns false for negative values.
/// Note: these are NOT really composing characters!
///
/// @param one First character.
@@ -271,22 +271,22 @@ bool arabic_combine(int one, int two)
return false;
}
-/// A_is_iso returns true if 'c' is an Arabic ISO-8859-6 character
+/// @return true if 'c' is an Arabic ISO-8859-6 character
/// (alphabet/number/punctuation)
-static int A_is_iso(int c)
+static bool A_is_iso(int c)
{
return find_achar(c) != NULL;
}
-/// A_is_ok returns true if 'c' is an Arabic 10646 (8859-6 or Form-B)
-static int A_is_ok(int c)
+/// @return true if 'c' is an Arabic 10646 (8859-6 or Form-B)
+static bool A_is_ok(int c)
{
return (A_is_iso(c) || c == a_BYTE_ORDER_MARK);
}
-/// A_is_valid returns true if 'c' is an Arabic 10646 (8859-6 or Form-B)
-/// with some exceptions/exclusions
-static int A_is_valid(int c)
+/// @return true if 'c' is an Arabic 10646 (8859-6 or Form-B)
+/// with some exceptions/exclusions
+static bool A_is_valid(int c)
{
return (A_is_ok(c) && c != a_HAMZA);
}
@@ -305,8 +305,8 @@ int arabic_shape(int c, int *c1p, int prev_c, int prev_c1, int next_c)
}
int curr_c;
- int curr_laa = arabic_combine(c, *c1p);
- int prev_laa = arabic_combine(prev_c, prev_c1);
+ bool curr_laa = arabic_combine(c, *c1p);
+ bool prev_laa = arabic_combine(prev_c, prev_c1);
if (curr_laa) {
if (A_is_valid(prev_c) && can_join(prev_c, a_LAM) && !prev_laa) {
diff --git a/src/nvim/arglist.c b/src/nvim/arglist.c
index d2734e6c5a..a02c22deae 100644
--- a/src/nvim/arglist.c
+++ b/src/nvim/arglist.c
@@ -10,6 +10,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand_defs.h"
#include "nvim/eval/typval.h"
@@ -20,9 +21,9 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/mark.h"
@@ -35,6 +36,7 @@
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/types_defs.h"
#include "nvim/undo.h"
#include "nvim/version.h"
@@ -282,7 +284,7 @@ static char *do_one_arg(char *str)
/// Separate the arguments in "str" and return a list of pointers in the
/// growarray "gap".
-static void get_arglist(garray_T *gap, char *str, int escaped)
+static void get_arglist(garray_T *gap, char *str, bool escaped)
{
ga_init(gap, (int)sizeof(char *), 20);
while (*str != NUL) {
@@ -428,7 +430,7 @@ static int do_arglist(char *str, int what, int after, bool will_edit)
garray_T new_ga;
int exp_count;
char **exp_files;
- int arg_escaped = true;
+ bool arg_escaped = true;
if (check_arglist_locked() == FAIL) {
return FAIL;
@@ -475,7 +477,7 @@ static int do_arglist(char *str, int what, int after, bool will_edit)
/// Redefine the argument list.
void set_arglist(char *str)
{
- do_arglist(str, AL_SET, 0, false);
+ do_arglist(str, AL_SET, 0, true);
}
/// @return true if window "win" is editing the file at the current argument
@@ -852,6 +854,9 @@ static void arg_all_close_unused_windows(arg_all_state_T *aall)
if (aall->had_tab > 0) {
goto_tabpage_tp(first_tabpage, true, true);
}
+
+ // moving tabpages around in an autocommand may cause an endless loop
+ tabpage_move_disallowed++;
while (true) {
win_T *wpnext = NULL;
tabpage_T *tpnext = curtab->tp_next;
@@ -917,7 +922,7 @@ static void arg_all_close_unused_windows(arg_all_state_T *aall)
if (!buf_hide(buf) && buf->b_nwindows <= 1 && bufIsChanged(buf)) {
bufref_T bufref;
set_bufref(&bufref, buf);
- (void)autowrite(buf, false);
+ autowrite(buf, false);
// Check if autocommands removed the window.
if (!win_valid(wp) || !bufref_valid(&bufref)) {
wpnext = lastwin->w_floating ? lastwin : firstwin; // Start all over...
@@ -951,6 +956,7 @@ static void arg_all_close_unused_windows(arg_all_state_T *aall)
}
goto_tabpage_tp(tpnext, true, true);
}
+ tabpage_move_disallowed--;
}
/// Open up to "count" windows for the files in the argument list "aall->alist".
@@ -1016,10 +1022,10 @@ static void arg_all_open_windows(arg_all_state_T *aall, int count)
aall->new_curwin = curwin;
aall->new_curtab = curtab;
}
- (void)do_ecmd(0, alist_name(&AARGLIST(aall->alist)[i]), NULL, NULL, ECMD_ONE,
- ((buf_hide(curwin->w_buffer)
- || bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0) + ECMD_OLDBUF,
- curwin);
+ do_ecmd(0, alist_name(&AARGLIST(aall->alist)[i]), NULL, NULL, ECMD_ONE,
+ ((buf_hide(curwin->w_buffer)
+ || bufIsChanged(curwin->w_buffer)) ? ECMD_HIDE : 0) + ECMD_OLDBUF,
+ curwin);
if (tab_drop_empty_window && i == count - 1) {
autocmd_no_enter++;
}
@@ -1087,11 +1093,6 @@ static void do_arg_all(int count, int forceit, int keep_tabs)
// When the ":tab" modifier was used do this for all tab pages.
arg_all_close_unused_windows(&aall);
- // Now set the last used tabpage to where we started.
- if (valid_tabpage(new_lu_tp)) {
- lastused_tabpage = new_lu_tp;
- }
-
// Open a window for files in the argument list that don't have one.
// ARGCOUNT may change while doing this, because of autocommands.
if (count > aall.opened_len || count <= 0) {
@@ -1128,6 +1129,12 @@ static void do_arg_all(int count, int forceit, int keep_tabs)
if (valid_tabpage(aall.new_curtab)) {
goto_tabpage_tp(aall.new_curtab, true, true);
}
+
+ // Now set the last used tabpage to where we started.
+ if (valid_tabpage(new_lu_tp)) {
+ lastused_tabpage = new_lu_tp;
+ }
+
if (win_valid(aall.new_curwin)) {
win_enter(aall.new_curwin, false);
}
diff --git a/src/nvim/arglist.h b/src/nvim/arglist.h
index 97729f466c..5b49423c18 100644
--- a/src/nvim/arglist.h
+++ b/src/nvim/arglist.h
@@ -1,10 +1,8 @@
#pragma once
-#include "nvim/arglist_defs.h" // IWYU pragma: export
+#include "nvim/arglist_defs.h" // IWYU pragma: keep
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
-#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
-#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "arglist.h.generated.h"
diff --git a/src/nvim/arglist_defs.h b/src/nvim/arglist_defs.h
index a79d540a6e..51f184e3b3 100644
--- a/src/nvim/arglist_defs.h
+++ b/src/nvim/arglist_defs.h
@@ -4,7 +4,7 @@
/// Argument list: Array of file names.
/// Used for the global argument list and the argument lists local to a window.
-typedef struct arglist {
+typedef struct {
garray_T al_ga; ///< growarray with the array of file names
int al_refcount; ///< number of windows using this arglist
int id; ///< id of this arglist
@@ -13,7 +13,7 @@ typedef struct arglist {
/// For each argument remember the file name as it was given, and the buffer
/// number that contains the expanded file name (required for when ":cd" is
/// used).
-typedef struct argentry {
+typedef struct {
char *ae_fname; ///< file name as specified
int ae_fnum; ///< buffer number with expanded file name
} aentry_T;
diff --git a/src/nvim/ascii_defs.h b/src/nvim/ascii_defs.h
index 4125336796..0cd7ccfec4 100644
--- a/src/nvim/ascii_defs.h
+++ b/src/nvim/ascii_defs.h
@@ -3,7 +3,6 @@
#include <stdbool.h>
#include "nvim/func_attr.h"
-#include "nvim/macros_defs.h"
#include "nvim/os/os_defs.h"
// Definitions of various common control characters.
@@ -86,31 +85,6 @@
static inline bool ascii_iswhite(int c)
REAL_FATTR_CONST
REAL_FATTR_ALWAYS_INLINE;
-
-static inline bool ascii_iswhite_or_nul(int c)
- REAL_FATTR_CONST
- REAL_FATTR_ALWAYS_INLINE;
-
-static inline bool ascii_isdigit(int c)
- REAL_FATTR_CONST
- REAL_FATTR_ALWAYS_INLINE;
-
-static inline bool ascii_isxdigit(int c)
- REAL_FATTR_CONST
- REAL_FATTR_ALWAYS_INLINE;
-
-static inline bool ascii_isident(int c)
- REAL_FATTR_CONST
- REAL_FATTR_ALWAYS_INLINE;
-
-static inline bool ascii_isbdigit(int c)
- REAL_FATTR_CONST
- REAL_FATTR_ALWAYS_INLINE;
-
-static inline bool ascii_isspace(int c)
- REAL_FATTR_CONST
- REAL_FATTR_ALWAYS_INLINE;
-
/// Checks if `c` is a space or tab character.
///
/// @see {ascii_isdigit}
@@ -119,6 +93,9 @@ static inline bool ascii_iswhite(int c)
return c == ' ' || c == '\t';
}
+static inline bool ascii_iswhite_or_nul(int c)
+ REAL_FATTR_CONST
+ REAL_FATTR_ALWAYS_INLINE;
/// Checks if `c` is a space or tab character or NUL.
///
/// @see {ascii_isdigit}
@@ -127,6 +104,9 @@ static inline bool ascii_iswhite_or_nul(int c)
return ascii_iswhite(c) || c == NUL;
}
+static inline bool ascii_isdigit(int c)
+ REAL_FATTR_CONST
+ REAL_FATTR_ALWAYS_INLINE;
/// Check whether character is a decimal digit.
///
/// Library isdigit() function is officially locale-dependent and, for
@@ -141,6 +121,9 @@ static inline bool ascii_isdigit(int c)
return c >= '0' && c <= '9';
}
+static inline bool ascii_isxdigit(int c)
+ REAL_FATTR_CONST
+ REAL_FATTR_ALWAYS_INLINE;
/// Checks if `c` is a hexadecimal digit, that is, one of 0-9, a-f, A-F.
///
/// @see {ascii_isdigit}
@@ -151,6 +134,9 @@ static inline bool ascii_isxdigit(int c)
|| (c >= 'A' && c <= 'F');
}
+static inline bool ascii_isident(int c)
+ REAL_FATTR_CONST
+ REAL_FATTR_ALWAYS_INLINE;
/// Checks if `c` is an “identifier†character
///
/// That is, whether it is alphanumeric character or underscore.
@@ -159,6 +145,9 @@ static inline bool ascii_isident(int c)
return ASCII_ISALNUM(c) || c == '_';
}
+static inline bool ascii_isbdigit(int c)
+ REAL_FATTR_CONST
+ REAL_FATTR_ALWAYS_INLINE;
/// Checks if `c` is a binary digit, that is, 0-1.
///
/// @see {ascii_isdigit}
@@ -167,6 +156,9 @@ static inline bool ascii_isbdigit(int c)
return (c == '0' || c == '1');
}
+static inline bool ascii_isodigit(int c)
+ REAL_FATTR_CONST
+ REAL_FATTR_ALWAYS_INLINE;
/// Checks if `c` is an octal digit, that is, 0-7.
///
/// @see {ascii_isdigit}
@@ -175,6 +167,9 @@ static inline bool ascii_isodigit(int c)
return (c >= '0' && c <= '7');
}
+static inline bool ascii_isspace(int c)
+ REAL_FATTR_CONST
+ REAL_FATTR_ALWAYS_INLINE;
/// Checks if `c` is a white-space character, that is,
/// one of \f, \n, \r, \t, \v.
///
diff --git a/src/nvim/assert_defs.h b/src/nvim/assert_defs.h
index cfc27ee994..5a6474862c 100644
--- a/src/nvim/assert_defs.h
+++ b/src/nvim/assert_defs.h
@@ -61,7 +61,7 @@
# define STATIC_ASSERT_STATEMENT(cond, msg) _Static_assert(cond, msg)
// if we're dealing with gcc >= 4.6 in C99 mode, we can still use
// _Static_assert but we need to suppress warnings, this is pretty ugly.
-#elif (!defined(__clang__) && !defined(__INTEL_COMPILER)) && /* NOLINT(whitespace/parens)*/ \
+#elif (!defined(__clang__) && !defined(__INTEL_COMPILER)) && \
(__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
# define STATIC_ASSERT_STATEMENT(cond, msg) _Static_assert(cond, msg)
diff --git a/src/nvim/auevents.lua b/src/nvim/auevents.lua
index e50ca76d0e..ca438e87b4 100644
--- a/src/nvim/auevents.lua
+++ b/src/nvim/auevents.lua
@@ -1,173 +1,175 @@
return {
events = {
- 'BufAdd', -- after adding a buffer to the buffer list
- 'BufDelete', -- deleting a buffer from the buffer list
- 'BufEnter', -- after entering a buffer
- 'BufFilePost', -- after renaming a buffer
- 'BufFilePre', -- before renaming a buffer
- 'BufHidden', -- just after buffer becomes hidden
- 'BufLeave', -- before leaving a buffer
- 'BufModifiedSet', -- after the 'modified' state of a buffer changes
- 'BufNew', -- after creating any buffer
- 'BufNewFile', -- when creating a buffer for a new file
- 'BufReadCmd', -- read buffer using command
- 'BufReadPost', -- after reading a buffer
- 'BufReadPre', -- before reading a buffer
- 'BufUnload', -- just before unloading a buffer
- 'BufWinEnter', -- after showing a buffer in a window
- 'BufWinLeave', -- just after buffer removed from window
- 'BufWipeout', -- just before really deleting a buffer
- 'BufWriteCmd', -- write buffer using command
- 'BufWritePost', -- after writing a buffer
- 'BufWritePre', -- before writing a buffer
- 'ChanInfo', -- info was received about channel
- 'ChanOpen', -- channel was opened
- 'CmdUndefined', -- command undefined
- 'CmdWinEnter', -- after entering the cmdline window
- 'CmdWinLeave', -- before leaving the cmdline window
- 'CmdlineChanged', -- command line was modified
- 'CmdlineEnter', -- after entering cmdline mode
- 'CmdlineLeave', -- before leaving cmdline mode
- 'ColorScheme', -- after loading a colorscheme
- 'ColorSchemePre', -- before loading a colorscheme
- 'CompleteChanged', -- after popup menu changed
- 'CompleteDone', -- after finishing insert complete
- 'CompleteDonePre', -- idem, before clearing info
- 'CursorHold', -- cursor in same position for a while
- 'CursorHoldI', -- idem, in Insert mode
- 'CursorMoved', -- cursor was moved
- 'CursorMovedI', -- cursor was moved in Insert mode
- 'DiagnosticChanged', -- diagnostics in a buffer were modified
- 'DiffUpdated', -- diffs have been updated
- 'DirChanged', -- directory changed
- 'DirChangedPre', -- directory is going to change
- 'EncodingChanged', -- after changing the 'encoding' option
- 'ExitPre', -- before exiting
- 'FileAppendCmd', -- append to a file using command
- 'FileAppendPost', -- after appending to a file
- 'FileAppendPre', -- before appending to a file
- 'FileChangedRO', -- before first change to read-only file
- 'FileChangedShell', -- after shell command that changed file
- 'FileChangedShellPost', -- after (not) reloading changed file
- 'FileReadCmd', -- read from a file using command
- 'FileReadPost', -- after reading a file
- 'FileReadPre', -- before reading a file
- 'FileType', -- new file type detected (user defined)
- 'FileWriteCmd', -- write to a file using command
- 'FileWritePost', -- after writing a file
- 'FileWritePre', -- before writing a file
- 'FilterReadPost', -- after reading from a filter
- 'FilterReadPre', -- before reading from a filter
- 'FilterWritePost', -- after writing to a filter
- 'FilterWritePre', -- before writing to a filter
- 'FocusGained', -- got the focus
- 'FocusLost', -- lost the focus to another app
- 'FuncUndefined', -- if calling a function which doesn't exist
- 'GUIEnter', -- after starting the GUI
- 'GUIFailed', -- after starting the GUI failed
- 'InsertChange', -- when changing Insert/Replace mode
- 'InsertCharPre', -- before inserting a char
- 'InsertEnter', -- when entering Insert mode
- 'InsertLeave', -- just after leaving Insert mode
- 'InsertLeavePre', -- just before leaving Insert mode
- 'LspAttach', -- after an LSP client attaches to a buffer
- 'LspDetach', -- after an LSP client detaches from a buffer
- 'LspRequest', -- after an LSP request is started, canceled, or completed
- 'LspNotify', -- after an LSP notice has been sent to the server
- 'LspTokenUpdate', -- after a visible LSP token is updated
- 'LspProgress', -- after a LSP progress update
- 'MenuPopup', -- just before popup menu is displayed
- 'ModeChanged', -- after changing the mode
- 'OptionSet', -- after setting any option
- 'QuickFixCmdPost', -- after :make, :grep etc.
- 'QuickFixCmdPre', -- before :make, :grep etc.
- 'QuitPre', -- before :quit
- 'RecordingEnter', -- when starting to record a macro
- 'RecordingLeave', -- just before a macro stops recording
- 'RemoteReply', -- upon string reception from a remote vim
- 'SafeState', -- going to wait for a character
- 'SearchWrapped', -- after the search wrapped around
- 'SessionLoadPost', -- after loading a session file
- 'ShellCmdPost', -- after ":!cmd"
- 'ShellFilterPost', -- after ":1,2!cmd", ":w !cmd", ":r !cmd".
- 'Signal', -- after nvim process received a signal
- 'SourceCmd', -- sourcing a Vim script using command
- 'SourcePost', -- after sourcing a Vim script
- 'SourcePre', -- before sourcing a Vim script
- 'SpellFileMissing', -- spell file missing
- 'StdinReadPost', -- after reading from stdin
- 'StdinReadPre', -- before reading from stdin
- 'SwapExists', -- found existing swap file
- 'Syntax', -- syntax selected
- 'TabClosed', -- a tab has closed
- 'TabEnter', -- after entering a tab page
- 'TabLeave', -- before leaving a tab page
- 'TabNew', -- when creating a new tab
- 'TabNewEntered', -- after entering a new tab
- 'TermChanged', -- after changing 'term'
- 'TermClose', -- after the process exits
- 'TermEnter', -- after entering Terminal mode
- 'TermLeave', -- after leaving Terminal mode
- 'TermOpen', -- after opening a terminal buffer
- 'TermResponse', -- after setting "v:termresponse"
- 'TextChanged', -- text was modified
- 'TextChangedI', -- text was modified in Insert mode(no popup)
- 'TextChangedP', -- text was modified in Insert mode(popup)
- 'TextChangedT', -- text was modified in Terminal mode
- 'TextYankPost', -- after a yank or delete was done (y, d, c)
- 'TextPutPost', -- after a put was done (p, P)
- 'UIEnter', -- after UI attaches
- 'UILeave', -- after UI detaches
- 'User', -- user defined autocommand
- 'VimEnter', -- after starting Vim
- 'VimLeave', -- before exiting Vim
- 'VimLeavePre', -- before exiting Vim and writing ShaDa file
- 'VimResized', -- after Vim window was resized
- 'VimResume', -- after Nvim is resumed
- 'VimSuspend', -- before Nvim is suspended
- 'WinClosed', -- after closing a window
- 'WinEnter', -- after entering a window
- 'WinLeave', -- before leaving a window
- 'WinNew', -- when entering a new window
- 'WinResized', -- after a window was resized
- 'WinScrolled', -- after a window was scrolled or resized
+ 'BufAdd', -- after adding a buffer to the buffer list
+ 'BufDelete', -- deleting a buffer from the buffer list
+ 'BufEnter', -- after entering a buffer
+ 'BufFilePost', -- after renaming a buffer
+ 'BufFilePre', -- before renaming a buffer
+ 'BufHidden', -- just after buffer becomes hidden
+ 'BufLeave', -- before leaving a buffer
+ 'BufModifiedSet', -- after the 'modified' state of a buffer changes
+ 'BufNew', -- after creating any buffer
+ 'BufNewFile', -- when creating a buffer for a new file
+ 'BufReadCmd', -- read buffer using command
+ 'BufReadPost', -- after reading a buffer
+ 'BufReadPre', -- before reading a buffer
+ 'BufUnload', -- just before unloading a buffer
+ 'BufWinEnter', -- after showing a buffer in a window
+ 'BufWinLeave', -- just after buffer removed from window
+ 'BufWipeout', -- just before really deleting a buffer
+ 'BufWriteCmd', -- write buffer using command
+ 'BufWritePost', -- after writing a buffer
+ 'BufWritePre', -- before writing a buffer
+ 'ChanInfo', -- info was received about channel
+ 'ChanOpen', -- channel was opened
+ 'CmdUndefined', -- command undefined
+ 'CmdWinEnter', -- after entering the cmdline window
+ 'CmdWinLeave', -- before leaving the cmdline window
+ 'CmdlineChanged', -- command line was modified
+ 'CmdlineEnter', -- after entering cmdline mode
+ 'CmdlineLeave', -- before leaving cmdline mode
+ 'ColorScheme', -- after loading a colorscheme
+ 'ColorSchemePre', -- before loading a colorscheme
+ 'CompleteChanged', -- after popup menu changed
+ 'CompleteDone', -- after finishing insert complete
+ 'CompleteDonePre', -- idem, before clearing info
+ 'CursorHold', -- cursor in same position for a while
+ 'CursorHoldI', -- idem, in Insert mode
+ 'CursorMoved', -- cursor was moved
+ 'CursorMovedI', -- cursor was moved in Insert mode
+ 'DiagnosticChanged', -- diagnostics in a buffer were modified
+ 'DiffUpdated', -- diffs have been updated
+ 'DirChanged', -- directory changed
+ 'DirChangedPre', -- directory is going to change
+ 'EncodingChanged', -- after changing the 'encoding' option
+ 'ExitPre', -- before exiting
+ 'FileAppendCmd', -- append to a file using command
+ 'FileAppendPost', -- after appending to a file
+ 'FileAppendPre', -- before appending to a file
+ 'FileChangedRO', -- before first change to read-only file
+ 'FileChangedShell', -- after shell command that changed file
+ 'FileChangedShellPost', -- after (not) reloading changed file
+ 'FileReadCmd', -- read from a file using command
+ 'FileReadPost', -- after reading a file
+ 'FileReadPre', -- before reading a file
+ 'FileType', -- new file type detected (user defined)
+ 'FileWriteCmd', -- write to a file using command
+ 'FileWritePost', -- after writing a file
+ 'FileWritePre', -- before writing a file
+ 'FilterReadPost', -- after reading from a filter
+ 'FilterReadPre', -- before reading from a filter
+ 'FilterWritePost', -- after writing to a filter
+ 'FilterWritePre', -- before writing to a filter
+ 'FocusGained', -- got the focus
+ 'FocusLost', -- lost the focus to another app
+ 'FuncUndefined', -- if calling a function which doesn't exist
+ 'GUIEnter', -- after starting the GUI
+ 'GUIFailed', -- after starting the GUI failed
+ 'InsertChange', -- when changing Insert/Replace mode
+ 'InsertCharPre', -- before inserting a char
+ 'InsertEnter', -- when entering Insert mode
+ 'InsertLeave', -- just after leaving Insert mode
+ 'InsertLeavePre', -- just before leaving Insert mode
+ 'LspAttach', -- after an LSP client attaches to a buffer
+ 'LspDetach', -- after an LSP client detaches from a buffer
+ 'LspRequest', -- after an LSP request is started, canceled, or completed
+ 'LspNotify', -- after an LSP notice has been sent to the server
+ 'LspTokenUpdate', -- after a visible LSP token is updated
+ 'LspProgress', -- after a LSP progress update
+ 'MenuPopup', -- just before popup menu is displayed
+ 'ModeChanged', -- after changing the mode
+ 'OptionSet', -- after setting any option
+ 'QuickFixCmdPost', -- after :make, :grep etc.
+ 'QuickFixCmdPre', -- before :make, :grep etc.
+ 'QuitPre', -- before :quit
+ 'RecordingEnter', -- when starting to record a macro
+ 'RecordingLeave', -- just before a macro stops recording
+ 'RemoteReply', -- upon string reception from a remote vim
+ 'SafeState', -- going to wait for a character
+ 'SearchWrapped', -- after the search wrapped around
+ 'SessionLoadPost', -- after loading a session file
+ 'ShellCmdPost', -- after ":!cmd"
+ 'ShellFilterPost', -- after ":1,2!cmd", ":w !cmd", ":r !cmd".
+ 'Signal', -- after nvim process received a signal
+ 'SourceCmd', -- sourcing a Vim script using command
+ 'SourcePost', -- after sourcing a Vim script
+ 'SourcePre', -- before sourcing a Vim script
+ 'SpellFileMissing', -- spell file missing
+ 'StdinReadPost', -- after reading from stdin
+ 'StdinReadPre', -- before reading from stdin
+ 'SwapExists', -- found existing swap file
+ 'Syntax', -- syntax selected
+ 'TabClosed', -- a tab has closed
+ 'TabEnter', -- after entering a tab page
+ 'TabLeave', -- before leaving a tab page
+ 'TabNew', -- when creating a new tab
+ 'TabNewEntered', -- after entering a new tab
+ 'TermChanged', -- after changing 'term'
+ 'TermClose', -- after the process exits
+ 'TermEnter', -- after entering Terminal mode
+ 'TermLeave', -- after leaving Terminal mode
+ 'TermOpen', -- after opening a terminal buffer
+ 'TermRequest', -- after an unhandled OSC sequence is emitted
+ 'TermResponse', -- after setting "v:termresponse"
+ 'TextChanged', -- text was modified
+ 'TextChangedI', -- text was modified in Insert mode(no popup)
+ 'TextChangedP', -- text was modified in Insert mode(popup)
+ 'TextChangedT', -- text was modified in Terminal mode
+ 'TextYankPost', -- after a yank or delete was done (y, d, c)
+ 'TextPutPost', -- after a put was done (p, P)
+ 'UIEnter', -- after UI attaches
+ 'UILeave', -- after UI detaches
+ 'User', -- user defined autocommand
+ 'VimEnter', -- after starting Vim
+ 'VimLeave', -- before exiting Vim
+ 'VimLeavePre', -- before exiting Vim and writing ShaDa file
+ 'VimResized', -- after Vim window was resized
+ 'VimResume', -- after Nvim is resumed
+ 'VimSuspend', -- before Nvim is suspended
+ 'WinClosed', -- after closing a window
+ 'WinEnter', -- after entering a window
+ 'WinLeave', -- before leaving a window
+ 'WinNew', -- when entering a new window
+ 'WinResized', -- after a window was resized
+ 'WinScrolled', -- after a window was scrolled or resized
},
aliases = {
{
'BufCreate',
- 'BufAdd'
+ 'BufAdd',
},
{
'BufRead',
- 'BufReadPost'
+ 'BufReadPost',
},
{
'BufWrite',
- 'BufWritePre'
+ 'BufWritePre',
},
{
'FileEncoding',
- 'EncodingChanged'
+ 'EncodingChanged',
},
},
-- List of nvim-specific events or aliases for the purpose of generating
-- syntax file
nvim_specific = {
- BufModifiedSet=true,
- DiagnosticChanged=true,
- LspAttach=true,
- LspDetach=true,
- LspNotify=true,
- LspRequest=true,
- LspProgress=true,
- LspTokenUpdate=true,
- RecordingEnter=true,
- RecordingLeave=true,
- Signal=true,
- TabNewEntered=true,
- TermClose=true,
- TermOpen=true,
- UIEnter=true,
- UILeave=true,
+ BufModifiedSet = true,
+ DiagnosticChanged = true,
+ LspAttach = true,
+ LspDetach = true,
+ LspNotify = true,
+ LspRequest = true,
+ LspProgress = true,
+ LspTokenUpdate = true,
+ RecordingEnter = true,
+ RecordingLeave = true,
+ Signal = true,
+ TabNewEntered = true,
+ TermClose = true,
+ TermOpen = true,
+ TermRequest = true,
+ UIEnter = true,
+ UILeave = true,
},
}
diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c
index 74a1dbdbc3..3f93906942 100644
--- a/src/nvim/autocmd.c
+++ b/src/nvim/autocmd.c
@@ -19,17 +19,19 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/userfunc.h"
#include "nvim/eval/vars.h"
+#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/getchar_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/hashtab.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/insexpand.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
@@ -37,17 +39,22 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/time.h"
+#include "nvim/os/time_defs.h"
#include "nvim/path.h"
#include "nvim/profile.h"
#include "nvim/regexp.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/search.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
@@ -114,7 +121,7 @@ static void augroup_map_del(int id, const char *name)
{
if (name != NULL) {
String key;
- map_del(String, int)(&map_augroup_name_to_id, cstr_as_string((char *)name), &key);
+ map_del(String, int)(&map_augroup_name_to_id, cstr_as_string(name), &key);
api_free_string(key);
}
if (id > 0) {
@@ -469,7 +476,7 @@ void augroup_del(char *name, bool stupid_legacy_mode)
int augroup_find(const char *name)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- int existing_id = map_get(String, int)(&map_augroup_name_to_id, cstr_as_string((char *)name));
+ int existing_id = map_get(String, int)(&map_augroup_name_to_id, cstr_as_string(name));
if (existing_id == AUGROUP_DELETED) {
return existing_id;
}
@@ -530,7 +537,7 @@ bool augroup_exists(const char *name)
}
/// ":augroup {name}".
-void do_augroup(char *arg, int del_group)
+void do_augroup(char *arg, bool del_group)
{
if (del_group) {
if (*arg == NUL) {
@@ -705,7 +712,7 @@ char *au_event_disable(char *what)
} else {
STRCAT(new_ei, what);
}
- set_string_option_direct("ei", -1, new_ei, OPT_FREE, SID_NONE);
+ set_string_option_direct(kOptEventignore, new_ei, 0, SID_NONE);
xfree(new_ei);
return save_ei;
}
@@ -713,7 +720,7 @@ char *au_event_disable(char *what)
void au_event_restore(char *old_ei)
{
if (old_ei != NULL) {
- set_string_option_direct("ei", -1, old_ei, OPT_FREE, SID_NONE);
+ set_string_option_direct(kOptEventignore, old_ei, 0, SID_NONE);
xfree(old_ei);
}
}
@@ -755,7 +762,7 @@ void do_autocmd(exarg_T *eap, char *arg_in, int forceit)
char *arg = arg_in;
char *envpat = NULL;
char *cmd;
- int need_free = false;
+ bool need_free = false;
bool nested = false;
bool once = false;
int group;
@@ -914,7 +921,7 @@ int do_autocmd_event(event_T event, const char *pat, bool once, int nested, char
int patlen = (int)aucmd_pattern_length(pat);
while (patlen) {
// detect special <buffer[=X]> buffer-local patterns
- int is_buflocal = aupat_is_buflocal(pat, patlen);
+ bool is_buflocal = aupat_is_buflocal(pat, patlen);
if (is_buflocal) {
const int buflocal_nr = aupat_get_buflocal_nr(pat, patlen);
@@ -978,7 +985,7 @@ int autocmd_register(int64_t id, event_T event, const char *pat, int patlen, int
const int findgroup = group == AUGROUP_ALL ? current_augroup : group;
// detect special <buffer[=X]> buffer-local patterns
- const int is_buflocal = aupat_is_buflocal(pat, patlen);
+ const bool is_buflocal = aupat_is_buflocal(pat, patlen);
int buflocal_nr = 0;
char buflocal_pat[BUFLOCAL_PAT_LEN]; // for "<buffer=X>"
@@ -1222,7 +1229,7 @@ void ex_doautoall(exarg_T *eap)
// Execute autocommands for the current buffer last.
if (retval == OK) {
- (void)do_doautocmd(arg, false, &did_aucmd);
+ do_doautocmd(arg, false, &did_aucmd);
if (call_do_modelines && did_aucmd) {
do_modelines(0);
}
@@ -1295,9 +1302,11 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
}
aco->save_curwin_handle = curwin->handle;
- aco->save_curbuf = curbuf;
aco->save_prevwin_handle = prevwin == NULL ? 0 : prevwin->handle;
aco->save_State = State;
+ if (bt_prompt(curbuf)) {
+ aco->save_prompt_insert = curbuf->b_prompt_insert;
+ }
if (win != NULL) {
// There is a window for "buf" in the current tab page, make it the
@@ -1326,7 +1335,7 @@ void aucmd_prepbuf(aco_save_T *aco, buf_T *buf)
if (need_append) {
win_append(lastwin, auc_win);
pmap_put(int)(&window_handles, auc_win->handle, auc_win);
- win_config_float(auc_win, auc_win->w_float_config);
+ win_config_float(auc_win, auc_win->w_config);
}
// Prevent chdir() call in win_enter_ext(), through do_autochdir()
int save_acd = p_acd;
@@ -1410,6 +1419,9 @@ win_found:
curbuf = curwin->w_buffer;
// May need to restore insert mode for a prompt buffer.
entering_window(curwin);
+ if (bt_prompt(curbuf)) {
+ curbuf->b_prompt_insert = aco->save_prompt_insert;
+ }
prevwin = win_find_by_handle(aco->save_prevwin_handle);
vars_clear(&awp->w_vars->dv_hashtab); // free all w: variables
@@ -1568,12 +1580,11 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
bool retval = false;
static int nesting = 0;
char *save_cmdarg;
- varnumber_T save_cmdbang;
- static int filechangeshell_busy = false;
+ static bool filechangeshell_busy = false;
proftime_T wait_time;
bool did_save_redobuff = false;
save_redo_T save_redo;
- const bool save_KeyTyped = KeyTyped; // NOLINT
+ const bool save_KeyTyped = KeyTyped;
// Quickly return if there are no autocommands for this event or
// autocommands are blocked.
@@ -1782,7 +1793,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
patcmd.data = data;
// set v:cmdarg (only when there is a matching pattern)
- save_cmdbang = get_vim_var_nr(VV_CMDBANG);
+ varnumber_T save_cmdbang = get_vim_var_nr(VV_CMDBANG);
if (eap != NULL) {
save_cmdarg = set_cmdarg(eap, NULL);
set_vim_var_nr(VV_CMDBANG, eap->forceit);
@@ -1815,7 +1826,7 @@ bool apply_autocmds_group(event_T event, char *fname, char *fname_io, bool force
}
if (eap != NULL) {
- (void)set_cmdarg(NULL, save_cmdarg);
+ set_cmdarg(NULL, save_cmdarg);
set_vim_var_nr(VV_CMDBANG, save_cmdbang);
}
// delete from active_apc_list
@@ -1991,15 +2002,15 @@ static bool call_autocmd_callback(const AutoCmd *ac, const AutoPatCmd *apc)
{
Callback callback = ac->exec.callable.cb;
if (callback.type == kCallbackLua) {
- Dictionary data = ARRAY_DICT_INIT;
- PUT(data, "id", INTEGER_OBJ(ac->id));
- PUT(data, "event", CSTR_TO_OBJ(event_nr2name(apc->event)));
- PUT(data, "match", CSTR_TO_OBJ(autocmd_match));
- PUT(data, "file", CSTR_TO_OBJ(autocmd_fname));
- PUT(data, "buf", INTEGER_OBJ(autocmd_bufnr));
+ MAXSIZE_TEMP_DICT(data, 7);
+ PUT_C(data, "id", INTEGER_OBJ(ac->id));
+ PUT_C(data, "event", CSTR_AS_OBJ(event_nr2name(apc->event)));
+ PUT_C(data, "match", CSTR_AS_OBJ(autocmd_match));
+ PUT_C(data, "file", CSTR_AS_OBJ(autocmd_fname));
+ PUT_C(data, "buf", INTEGER_OBJ(autocmd_bufnr));
if (apc->data) {
- PUT(data, "data", copy_object(*apc->data, NULL));
+ PUT_C(data, "data", *apc->data);
}
int group = ac->pat->group;
@@ -2012,21 +2023,15 @@ static bool call_autocmd_callback(const AutoCmd *ac, const AutoPatCmd *apc)
// omit group in these cases
break;
default:
- PUT(data, "group", INTEGER_OBJ(group));
+ PUT_C(data, "group", INTEGER_OBJ(group));
break;
}
MAXSIZE_TEMP_ARRAY(args, 1);
ADD_C(args, DICTIONARY_OBJ(data));
- Object result = nlua_call_ref(callback.data.luaref, NULL, args, true, NULL);
- bool ret = false;
- if (result.type == kObjectTypeBoolean) {
- ret = result.data.boolean;
- }
- api_free_dictionary(data);
- api_free_object(result);
- return ret;
+ Object result = nlua_call_ref(callback.data.luaref, NULL, args, kRetNilBool, NULL, NULL);
+ return LUARET_TRUTHY(result);
} else {
typval_T argsin = TV_INITIAL_VALUE;
typval_T rettv = TV_INITIAL_VALUE;
@@ -2164,7 +2169,7 @@ char *expand_get_augroup_name(expand_T *xp, int idx)
}
/// @param doautocmd true for :doauto*, false for :autocmd
-char *set_context_in_autocmd(expand_T *xp, char *arg, int doautocmd)
+char *set_context_in_autocmd(expand_T *xp, char *arg, bool doautocmd)
{
// check for a group name, skip it if present
autocmd_include_groups = false;
@@ -2424,7 +2429,7 @@ char *aucmd_exec_to_string(AutoCmd *ac, AucmdExecutable acc)
case CALLABLE_EX:
return xstrdup(acc.callable.cmd);
case CALLABLE_CB:
- return callback_to_string(&acc.callable.cb);
+ return callback_to_string(&acc.callable.cb, NULL);
case CALLABLE_NONE:
return "This is not possible";
}
@@ -2478,7 +2483,7 @@ bool au_event_is_empty(event_T event)
/// Scan over the events. "*" stands for all events.
/// true when group name was found
-static char *arg_event_skip(char *arg, int have_group)
+static char *arg_event_skip(char *arg, bool have_group)
{
char *pat;
char *p;
@@ -2565,7 +2570,7 @@ void may_trigger_vim_suspend_resume(bool suspend)
pending_vimresume = kTrue;
} else if (!suspend && pending_vimresume == kTrue) {
pending_vimresume = kNone;
- multiqueue_put(main_loop.events, vimresume_event, 0);
+ multiqueue_put(main_loop.events, vimresume_event, NULL);
}
}
@@ -2574,6 +2579,11 @@ void do_autocmd_uienter(uint64_t chanid, bool attached)
{
static bool recursive = false;
+#ifdef EXITFREE
+ if (entered_free_all_mem) {
+ return;
+ }
+#endif
if (starting == NO_SCREEN) {
return; // user config hasn't been sourced yet
}
diff --git a/src/nvim/autocmd.h b/src/nvim/autocmd.h
index 259a56cf5c..8019cb7145 100644
--- a/src/nvim/autocmd.h
+++ b/src/nvim/autocmd.h
@@ -1,11 +1,12 @@
#pragma once
#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
+#include <stddef.h> // IWYU pragma: keep
+#include <stdint.h> // IWYU pragma: keep
+#include "klib/kvec.h"
#include "nvim/api/private/defs.h" // IWYU pragma: keep
-#include "nvim/autocmd_defs.h" // IWYU pragma: export
+#include "nvim/autocmd_defs.h" // IWYU pragma: keep
#include "nvim/buffer_defs.h"
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
@@ -27,18 +28,57 @@ EXTERN win_T *last_cursormoved_win INIT( = NULL);
/// For CursorMoved event, only used when last_cursormoved_win == curwin
EXTERN pos_T last_cursormoved INIT( = { 0, 0, 0 });
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "autocmd.h.generated.h"
-#endif
+EXTERN bool autocmd_busy INIT( = false); ///< Is apply_autocmds() busy?
+EXTERN int autocmd_no_enter INIT( = false); ///< Buf/WinEnter autocmds disabled
+EXTERN int autocmd_no_leave INIT( = false); ///< Buf/WinLeave autocmds disabled
+EXTERN bool did_filetype INIT( = false); ///< FileType event found
+/// value for did_filetype when starting to execute autocommands
+EXTERN bool keep_filetype INIT( = false);
+
+/// When deleting the current buffer, another one must be loaded.
+/// If we know which one is preferred, au_new_curbuf is set to it.
+EXTERN bufref_T au_new_curbuf INIT( = { NULL, 0, 0 });
+
+// When deleting a buffer/window and autocmd_busy is true, do not free the
+// buffer/window. but link it in the list starting with
+// au_pending_free_buf/ap_pending_free_win, using b_next/w_next.
+// Free the buffer/window when autocmd_busy is being set to false.
+EXTERN buf_T *au_pending_free_buf INIT( = NULL);
+EXTERN win_T *au_pending_free_win INIT( = NULL);
+
+EXTERN char *autocmd_fname INIT( = NULL); ///< fname for <afile> on cmdline
+EXTERN bool autocmd_fname_full INIT( = false); ///< autocmd_fname is full path
+EXTERN int autocmd_bufnr INIT( = 0); ///< fnum for <abuf> on cmdline
+EXTERN char *autocmd_match INIT( = NULL); ///< name for <amatch> on cmdline
+EXTERN bool did_cursorhold INIT( = false); ///< set when CursorHold t'gerd
-#define AUGROUP_DEFAULT (-1) // default autocmd group
-#define AUGROUP_ERROR (-2) // erroneous autocmd group
-#define AUGROUP_ALL (-3) // all autocmd groups
-#define AUGROUP_DELETED (-4) // all autocmd groups
-// #define AUGROUP_NS -5 // TODO(tjdevries): Support namespaced based augroups
+typedef struct {
+ win_T *auc_win; ///< Window used in aucmd_prepbuf(). When not NULL the
+ ///< window has been allocated.
+ bool auc_win_used; ///< This auc_win is being used.
+} aucmdwin_T;
-#define BUFLOCAL_PAT_LEN 25
+/// When executing autocommands for a buffer that is not in any window, a
+/// special window is created to handle the side effects. When autocommands
+/// nest we may need more than one.
+EXTERN kvec_t(aucmdwin_T) aucmd_win_vec INIT( = KV_INITIAL_VALUE);
+#define aucmd_win (aucmd_win_vec.items)
+#define AUCMD_WIN_COUNT ((int)aucmd_win_vec.size)
+
+enum {
+ AUGROUP_DEFAULT = -1, ///< default autocmd group
+ AUGROUP_ERROR = -2, ///< erroneous autocmd group
+ AUGROUP_ALL = -3, ///< all autocmd groups
+ AUGROUP_DELETED = -4, ///< all autocmd groups
+ // AUGROUP_NS = -5, // TODO(tjdevries): Support namespaced based augroups
+};
+
+enum { BUFLOCAL_PAT_LEN = 25, };
/// Iterates over all the events for auto commands
#define FOR_ALL_AUEVENTS(event) \
- for (event_T event = (event_T)0; (int)event < (int)NUM_EVENTS; event = (event_T)((int)event + 1)) // NOLINT
+ for (event_T event = (event_T)0; (int)event < (int)NUM_EVENTS; event = (event_T)((int)event + 1))
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "autocmd.h.generated.h"
+#endif
diff --git a/src/nvim/autocmd_defs.h b/src/nvim/autocmd_defs.h
index 4639ec2731..6535f8a7ea 100644
--- a/src/nvim/autocmd_defs.h
+++ b/src/nvim/autocmd_defs.h
@@ -4,15 +4,9 @@
#include <stddef.h>
#include <stdint.h>
-#include "klib/kvec.h"
-#include "nvim/api/private/defs.h"
#include "nvim/buffer_defs.h"
-#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
-#include "nvim/regexp_defs.h"
-#include "nvim/types_defs.h"
-// event_T definition
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "auevents_enum.generated.h"
#endif
@@ -20,7 +14,6 @@
/// Struct to save values in before executing autocommands for a buffer that is
/// not the current buffer.
typedef struct {
- buf_T *save_curbuf; ///< saved curbuf
int use_aucmd_win_idx; ///< index in aucmd_win[] if >= 0
handle_T save_curwin_handle; ///< ID of saved curwin
handle_T new_curwin_handle; ///< ID of new curwin
@@ -29,6 +22,7 @@ typedef struct {
char *globaldir; ///< saved value of globaldir
bool save_VIsual_active; ///< saved VIsual_active
int save_State; ///< saved State
+ int save_prompt_insert; ///< saved b_prompt_insert
} aco_save_T;
typedef struct {
diff --git a/src/nvim/base64.c b/src/nvim/base64.c
index 295dedd8d3..d461b7e3ff 100644
--- a/src/nvim/base64.c
+++ b/src/nvim/base64.c
@@ -12,7 +12,7 @@
#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "base64.c.generated.h" // IWYU pragma: export
+# include "base64.c.generated.h"
#endif
static const char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -65,6 +65,7 @@ static inline uint32_t htobe32(uint32_t host_32bits)
/// @param src_len Length of the string
/// @return Base64 encoded string
char *base64_encode(const char *src, size_t src_len)
+ FUNC_ATTR_NONNULL_ALL
{
assert(src != NULL);
diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c
index 8a594dea92..f6c7229485 100644
--- a/src/nvim/buffer.c
+++ b/src/nvim/buffer.c
@@ -32,6 +32,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/assert_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_updates.h"
#include "nvim/change.h"
@@ -39,28 +40,30 @@
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
#include "nvim/cursor.h"
-#include "nvim/decoration.h"
#include "nvim/diff.h"
#include "nvim/digraph.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
-#include "nvim/eval/typval_defs.h"
+#include "nvim/eval/typval.h"
#include "nvim/eval/vars.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
+#include "nvim/ex_eval_defs.h"
#include "nvim/ex_getln.h"
#include "nvim/extmark.h"
#include "nvim/file_search.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/help.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
@@ -68,26 +71,33 @@
#include "nvim/map_defs.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memfile_defs.h"
+#include "nvim/memline.h"
#include "nvim/memline_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
#include "nvim/plines.h"
#include "nvim/pos_defs.h"
#include "nvim/quickfix.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/search.h"
#include "nvim/spell.h"
#include "nvim/state_defs.h"
@@ -95,7 +105,6 @@
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/terminal.h"
-#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/usercmd.h"
@@ -133,7 +142,7 @@ int get_highest_fnum(void)
/// @param read_stdin read file from stdin, otherwise fifo
/// @param eap for forced 'ff' and 'fenc' or NULL
/// @param flags extra flags for readfile()
-static int read_buffer(int read_stdin, exarg_T *eap, int flags)
+static int read_buffer(bool read_stdin, exarg_T *eap, int flags)
{
int retval = OK;
bool silent = shortmess(SHM_FILEINFO);
@@ -202,13 +211,13 @@ bool buf_ensure_loaded(buf_T *buf)
/// @param flags_arg extra flags for readfile()
///
/// @return FAIL for failure, OK otherwise.
-int open_buffer(int read_stdin, exarg_T *eap, int flags_arg)
+int open_buffer(bool read_stdin, exarg_T *eap, int flags_arg)
{
int flags = flags_arg;
int retval = OK;
bufref_T old_curbuf;
OptInt old_tw = curbuf->b_p_tw;
- int read_fifo = false;
+ bool read_fifo = false;
bool silent = shortmess(SHM_FILEINFO);
// The 'readonly' flag is only set when BF_NEVERLOADED is being reset.
@@ -274,16 +283,14 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg)
if (curbuf->b_ffname != NULL) {
#ifdef UNIX
int save_bin = curbuf->b_p_bin;
- int perm;
-
- perm = os_getperm(curbuf->b_ffname);
+ int perm = os_getperm(curbuf->b_ffname);
if (perm >= 0 && (0 || S_ISFIFO(perm)
|| S_ISSOCK(perm)
# ifdef OPEN_CHR_FILES
|| (S_ISCHR(perm)
&& is_dev_fd_file(curbuf->b_ffname))
# endif
- )) { // NOLINT(whitespace/parens)
+ )) {
read_fifo = true;
}
if (read_fifo) {
@@ -303,9 +310,9 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg)
}
#endif
- // Help buffer is filtered.
+ // Help buffer: populate *local-additions* in help.txt
if (bt_help(curbuf)) {
- fix_help_buffer();
+ get_local_additions();
}
} else if (read_stdin) {
int save_bin = curbuf->b_p_bin;
@@ -332,7 +339,7 @@ int open_buffer(int read_stdin, exarg_T *eap, int flags_arg)
// if first time loading this buffer, init b_chartab[]
if (curbuf->b_flags & BF_NEVERLOADED) {
- (void)buf_init_chartab(curbuf, false);
+ buf_init_chartab(curbuf, false);
parse_cino(curbuf);
}
@@ -836,8 +843,9 @@ void buf_freeall(buf_T *buf, int flags)
ml_close(buf, true); // close and delete the memline/memfile
buf->b_ml.ml_line_count = 0; // no lines in buffer
if ((flags & BFA_KEEP_UNDO) == 0) {
- u_blockfree(buf); // free the memory allocated for undo
- u_clearall(buf); // reset all undo information
+ // free the memory allocated for undo
+ // and reset all undo information
+ u_clearallandblockfree(buf);
}
syntax_clear(&buf->b_s); // reset syntax info
buf->b_flags &= ~BF_READERR; // a read error is no longer relevant
@@ -938,8 +946,8 @@ void goto_buffer(exarg_T *eap, int start, int dir, int count)
if (swap_exists_action == SEA_NONE) {
swap_exists_action = SEA_DIALOG;
}
- (void)do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
- start, dir, count, eap->forceit);
+ do_buffer(*eap->cmd == 's' ? DOBUF_SPLIT : DOBUF_GOTO,
+ start, dir, count, eap->forceit);
if (swap_exists_action == SEA_QUIT && *eap->cmd == 's') {
cleanup_T cs;
@@ -1047,7 +1055,7 @@ char *do_bufdel(int command, char *arg, int addr_count, int start_bnr, int end_b
int bnr; // buffer number
if (addr_count == 0) {
- (void)do_buffer(command, DOBUF_CURRENT, FORWARD, 0, forceit);
+ do_buffer(command, DOBUF_CURRENT, FORWARD, 0, forceit);
} else {
if (addr_count == 2) {
if (*arg) { // both range and argument is not allowed
@@ -1126,7 +1134,7 @@ char *do_bufdel(int command, char *arg, int addr_count, int start_bnr, int end_b
/// Make the current buffer empty.
/// Used when it is wiped out and it's the last buffer.
-static int empty_curbuf(int close_others, int forceit, int action)
+static int empty_curbuf(bool close_others, int forceit, int action)
{
buf_T *buf = curbuf;
@@ -1176,6 +1184,32 @@ static int empty_curbuf(int close_others, int forceit, int action)
return retval;
}
+/// Remove every jump list entry referring to a given buffer.
+/// This function will also adjust the current jump list index.
+void buf_remove_from_jumplist(buf_T *deleted_buf)
+{
+ // Remove all jump list entries that match the deleted buffer.
+ for (int i = curwin->w_jumplistlen - 1; i >= 0; i--) {
+ buf_T *buf = buflist_findnr(curwin->w_jumplist[i].fmark.fnum);
+
+ if (buf == deleted_buf) {
+ // Found an entry that we want to delete.
+ curwin->w_jumplistlen -= 1;
+
+ // If the current jump list index behind the entry we want to
+ // delete, move it back by one.
+ if (curwin->w_jumplistidx > i && curwin->w_jumplistidx > 0) {
+ curwin->w_jumplistidx -= 1;
+ }
+
+ // Actually remove the entry from the jump list.
+ for (int d = i; d < curwin->w_jumplistlen; d++) {
+ curwin->w_jumplist[d] = curwin->w_jumplist[d + 1];
+ }
+ }
+ }
+}
+
/// Implementation of the commands for the buffer list.
///
/// action == DOBUF_GOTO go to specified buffer
@@ -1198,8 +1232,9 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
{
buf_T *buf;
buf_T *bp;
- int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
- || action == DOBUF_WIPE);
+ bool update_jumplist = true;
+ bool unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
+ || action == DOBUF_WIPE);
switch (start) {
case DOBUF_FIRST:
@@ -1355,7 +1390,11 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
// If the buffer to be deleted is not the current one, delete it here.
if (buf != curbuf) {
+ // Remove the buffer to be deleted from the jump list.
+ buf_remove_from_jumplist(buf);
+
close_windows(buf, false);
+
if (buf != curbuf && bufref_valid(&bufref) && buf->b_nwindows <= 0) {
close_buffer(NULL, buf, action, false, false);
}
@@ -1375,42 +1414,53 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
if (au_new_curbuf.br_buf != NULL && bufref_valid(&au_new_curbuf)) {
buf = au_new_curbuf.br_buf;
} else if (curwin->w_jumplistlen > 0) {
- int jumpidx;
-
- jumpidx = curwin->w_jumplistidx - 1;
- if (jumpidx < 0) {
- jumpidx = curwin->w_jumplistlen - 1;
- }
+ // Remove the current buffer from the jump list.
+ buf_remove_from_jumplist(curbuf);
+
+ // It's possible that we removed all jump list entries, in that case we need to try another
+ // approach
+ if (curwin->w_jumplistlen > 0) {
+ // If the index is the same as the length, the current position was not yet added to the jump
+ // list. So we can safely go back to the last entry and search from there.
+ if (curwin->w_jumplistidx == curwin->w_jumplistlen) {
+ curwin->w_jumplistidx = curwin->w_jumplistlen - 1;
+ }
- forward = jumpidx;
- while (jumpidx != curwin->w_jumplistidx) {
- buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum);
- if (buf != NULL) {
- // Skip current and unlisted bufs. Also skip a quickfix
- // buffer, it might be deleted soon.
- if (buf == curbuf || !buf->b_p_bl || bt_quickfix(buf)) {
- buf = NULL;
- } else if (buf->b_ml.ml_mfp == NULL) {
- // skip unloaded buf, but may keep it for later
- if (bp == NULL) {
- bp = buf;
+ int jumpidx = curwin->w_jumplistidx;
+
+ forward = jumpidx;
+ do {
+ buf = buflist_findnr(curwin->w_jumplist[jumpidx].fmark.fnum);
+
+ if (buf != NULL) {
+ // Skip unlisted bufs. Also skip a quickfix
+ // buffer, it might be deleted soon.
+ if (!buf->b_p_bl || bt_quickfix(buf)) {
+ buf = NULL;
+ } else if (buf->b_ml.ml_mfp == NULL) {
+ // skip unloaded buf, but may keep it for later
+ if (bp == NULL) {
+ bp = buf;
+ }
+ buf = NULL;
}
- buf = NULL;
}
- }
- if (buf != NULL) { // found a valid buffer: stop searching
- break;
- }
- // advance to older entry in jump list
- if (!jumpidx && curwin->w_jumplistidx == curwin->w_jumplistlen) {
- break;
- }
- if (--jumpidx < 0) {
- jumpidx = curwin->w_jumplistlen - 1;
- }
- if (jumpidx == forward) { // List exhausted for sure
- break;
- }
+ if (buf != NULL) { // found a valid buffer: stop searching
+ curwin->w_jumplistidx = jumpidx;
+ update_jumplist = false;
+ break;
+ }
+ // advance to older entry in jump list
+ if (!jumpidx && curwin->w_jumplistidx == curwin->w_jumplistlen) {
+ break;
+ }
+ if (--jumpidx < 0) {
+ jumpidx = curwin->w_jumplistlen - 1;
+ }
+ if (jumpidx == forward) { // List exhausted for sure
+ break;
+ }
+ } while (jumpidx != curwin->w_jumplistidx);
}
}
@@ -1506,7 +1556,7 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
}
// Go to the other buffer.
- set_curbuf(buf, action);
+ set_curbuf(buf, action, update_jumplist);
if (action == DOBUF_SPLIT) {
RESET_BINDING(curwin); // reset 'scrollbind' and 'cursorbind'
@@ -1528,14 +1578,18 @@ int do_buffer(int action, int start, int dir, int count, int forceit)
/// DOBUF_UNLOAD unload it
/// DOBUF_DEL delete it
/// DOBUF_WIPE wipe it out
-void set_curbuf(buf_T *buf, int action)
+void set_curbuf(buf_T *buf, int action, bool update_jumplist)
{
buf_T *prevbuf;
int unload = (action == DOBUF_UNLOAD || action == DOBUF_DEL
|| action == DOBUF_WIPE);
OptInt old_tw = curbuf->b_p_tw;
+ const int last_winid = get_last_winid();
+
+ if (update_jumplist) {
+ setpcmark();
+ }
- setpcmark();
if ((cmdmod.cmod_flags & CMOD_KEEPALT) == 0) {
curwin->w_alt_fnum = curbuf->b_fnum; // remember alternate file
}
@@ -1559,7 +1613,11 @@ void set_curbuf(buf_T *buf, int action)
if (prevbuf == curwin->w_buffer) {
reset_synblock(curwin);
}
- if (unload) {
+ // autocommands may have opened a new window
+ // with prevbuf, grr
+ if (unload
+ || (last_winid != get_last_winid()
+ && strchr("wdu", prevbuf->b_p_bh[0]) != NULL)) {
close_windows(prevbuf, false);
}
if (bufref_valid(&prevbufref) && !aborting()) {
@@ -1589,6 +1647,11 @@ void set_curbuf(buf_T *buf, int action)
// If curwin->w_buffer is null, enter_buffer() will make it valid again
bool valid = buf_valid(buf);
if ((valid && buf != curbuf && !aborting()) || curwin->w_buffer == NULL) {
+ // autocommands changed curbuf and we will move to another
+ // buffer soon, so decrement curbuf->b_nwindows
+ if (curbuf != NULL && prevbuf != curbuf) {
+ curbuf->b_nwindows--;
+ }
// If the buffer is not valid but curwin->w_buffer is NULL we must
// enter some buffer. Using the last one is hopefully OK.
if (!valid) {
@@ -1666,7 +1729,7 @@ void enter_buffer(buf_T *buf)
need_fileinfo = true; // display file info after redraw
}
// check if file changed
- (void)buf_check_timestamp(curbuf);
+ buf_check_timestamp(curbuf);
curwin->w_topline = 1;
curwin->w_topfill = 0;
@@ -1691,12 +1754,12 @@ void enter_buffer(buf_T *buf)
do_autochdir();
if (curbuf->b_kmap_state & KEYMAP_INIT) {
- (void)keymap_init();
+ keymap_init();
}
// May need to set the spell language. Can only do this after the buffer
// has been properly setup.
if (!curbuf->b_help && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) {
- (void)parse_spelllang(curwin);
+ parse_spelllang(curwin);
}
curbuf->b_last_used = time(NULL);
@@ -1844,7 +1907,6 @@ buf_T *buflist_new(char *ffname_arg, char *sfname_arg, linenr_T lnum, int flags)
buf = xcalloc(1, sizeof(buf_T));
// init b: variables
buf->b_vars = tv_dict_alloc();
- buf->b_signcols.sentinel = 0;
init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE);
buf_init_changedtick(buf);
}
@@ -1963,7 +2025,7 @@ bool curbuf_reusable(void)
/// Free the memory for the options of a buffer.
/// If "free_p_ff" is true also free 'fileformat', 'buftype' and
/// 'fileencoding'.
-void free_buf_options(buf_T *buf, int free_p_ff)
+void free_buf_options(buf_T *buf, bool free_p_ff)
{
if (free_p_ff) {
clear_string_option(&buf->b_p_fenc);
@@ -2151,7 +2213,7 @@ buf_T *buflist_findname_exp(char *fname)
#else
false
#endif
- ); // NOLINT(whitespace/parens)
+ );
if (ffname != NULL) {
buf = buflist_findname(ffname);
xfree(ffname);
@@ -2226,7 +2288,7 @@ int buflist_findpat(const char *pattern, const char *pattern_end, bool unlisted,
return -1;
}
char *patend = pat + strlen(pat) - 1;
- int toggledollar = (patend > pat && *patend == '$');
+ bool toggledollar = (patend > pat && *patend == '$');
// First try finding a listed buffer. If not found and "unlisted"
// is true, try finding an unlisted buffer.
@@ -2325,10 +2387,8 @@ static int buf_time_compare(const void *s1, const void *s2)
/// @return OK if matches found, FAIL otherwise.
int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
{
- int count = 0;
- int round;
- char *p;
bufmatch_T *matches = NULL;
+ bool to_free = false;
*num_file = 0; // return values in case of FAIL
*file = NULL;
@@ -2340,125 +2400,115 @@ int ExpandBufnames(char *pat, int *num_file, char ***file, int options)
const bool fuzzy = cmdline_fuzzy_complete(pat);
char *patc = NULL;
+ fuzmatch_str_T *fuzmatch = NULL;
+ regmatch_T regmatch;
+
// Make a copy of "pat" and change "^" to "\(^\|[\/]\)" (if doing regular
// expression matching)
if (!fuzzy) {
- if (*pat == '^') {
- patc = xmalloc(strlen(pat) + 11);
- STRCPY(patc, "\\(^\\|[\\/]\\)");
- STRCPY(patc + 11, pat + 1);
+ if (*pat == '^' && pat[1] != NUL) {
+ patc = xstrdup(pat + 1);
+ to_free = true;
+ } else if (*pat == '^') {
+ patc = "";
} else {
patc = pat;
}
+ regmatch.regprog = vim_regcomp(patc, RE_MAGIC);
}
- fuzmatch_str_T *fuzmatch = NULL;
- // attempt == 0: try match with '\<', match at start of word
- // attempt == 1: try match without '\<', match anywhere
- for (int attempt = 0; attempt <= (fuzzy ? 0 : 1); attempt++) {
- regmatch_T regmatch;
- if (!fuzzy) {
- if (attempt > 0 && patc == pat) {
- break; // there was no anchor, no need to try again
+ int count = 0;
+ int score = 0;
+ // round == 1: Count the matches.
+ // round == 2: Build the array to keep the matches.
+ for (int round = 1; round <= 2; round++) {
+ count = 0;
+ FOR_ALL_BUFFERS(buf) {
+ if (!buf->b_p_bl) { // skip unlisted buffers
+ continue;
}
- regmatch.regprog = vim_regcomp(patc + attempt * 11, RE_MAGIC);
- }
-
- int score = 0;
- // round == 1: Count the matches.
- // round == 2: Build the array to keep the matches.
- for (round = 1; round <= 2; round++) {
- count = 0;
- FOR_ALL_BUFFERS(buf) {
- if (!buf->b_p_bl) { // skip unlisted buffers
+ if (options & BUF_DIFF_FILTER) {
+ // Skip buffers not suitable for
+ // :diffget or :diffput completion.
+ if (buf == curbuf || !diff_mode_buf(buf)) {
continue;
}
- if (options & BUF_DIFF_FILTER) {
- // Skip buffers not suitable for
- // :diffget or :diffput completion.
- if (buf == curbuf || !diff_mode_buf(buf)) {
- continue;
- }
- }
+ }
- if (!fuzzy) {
- if (regmatch.regprog == NULL) {
- // invalid pattern, possibly after recompiling
- if (patc != pat) {
- xfree(patc);
- }
- return FAIL;
- }
- p = buflist_match(&regmatch, buf, p_wic);
- } else {
- p = NULL;
- // first try matching with the short file name
- if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0) {
- p = buf->b_sfname;
- }
- if (p == NULL) {
- // next try matching with the full path file name
- if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0) {
- p = buf->b_ffname;
- }
+ char *p = NULL;
+ if (!fuzzy) {
+ if (regmatch.regprog == NULL) {
+ // invalid pattern, possibly after recompiling
+ if (to_free) {
+ xfree(patc);
}
+ return FAIL;
}
-
- if (p == NULL) {
- continue;
- }
-
- if (round == 1) {
- count++;
- continue;
- }
-
- if (options & WILD_HOME_REPLACE) {
- p = home_replace_save(buf, p);
- } else {
- p = xstrdup(p);
+ p = buflist_match(&regmatch, buf, p_wic);
+ } else {
+ p = NULL;
+ // first try matching with the short file name
+ if ((score = fuzzy_match_str(buf->b_sfname, pat)) != 0) {
+ p = buf->b_sfname;
}
-
- if (!fuzzy) {
- if (matches != NULL) {
- matches[count].buf = buf;
- matches[count].match = p;
- count++;
- } else {
- (*file)[count++] = p;
+ if (p == NULL) {
+ // next try matching with the full path file name
+ if ((score = fuzzy_match_str(buf->b_ffname, pat)) != 0) {
+ p = buf->b_ffname;
}
- } else {
- fuzmatch[count].idx = count;
- fuzmatch[count].str = p;
- fuzmatch[count].score = score;
- count++;
}
}
- if (count == 0) { // no match found, break here
- break;
+
+ if (p == NULL) {
+ continue;
}
+
if (round == 1) {
- if (!fuzzy) {
- *file = xmalloc((size_t)count * sizeof(**file));
- if (options & WILD_BUFLASTUSED) {
- matches = xmalloc((size_t)count * sizeof(*matches));
- }
+ count++;
+ continue;
+ }
+
+ if (options & WILD_HOME_REPLACE) {
+ p = home_replace_save(buf, p);
+ } else {
+ p = xstrdup(p);
+ }
+
+ if (!fuzzy) {
+ if (matches != NULL) {
+ matches[count].buf = buf;
+ matches[count].match = p;
+ count++;
} else {
- fuzmatch = xmalloc((size_t)count * sizeof(fuzmatch_str_T));
+ (*file)[count++] = p;
}
+ } else {
+ fuzmatch[count].idx = count;
+ fuzmatch[count].str = p;
+ fuzmatch[count].score = score;
+ count++;
}
}
-
- if (!fuzzy) {
- vim_regfree(regmatch.regprog);
- if (count) { // match(es) found, break here
- break;
+ if (count == 0) { // no match found, break here
+ break;
+ }
+ if (round == 1) {
+ if (!fuzzy) {
+ *file = xmalloc((size_t)count * sizeof(**file));
+ if (options & WILD_BUFLASTUSED) {
+ matches = xmalloc((size_t)count * sizeof(*matches));
+ }
+ } else {
+ fuzmatch = xmalloc((size_t)count * sizeof(fuzmatch_str_T));
}
}
}
- if (!fuzzy && patc != pat) {
- xfree(patc);
+ if (!fuzzy) {
+ vim_regfree(regmatch.regprog);
+ if (to_free) {
+ xfree(patc);
+ }
}
if (!fuzzy) {
@@ -2722,7 +2772,7 @@ void get_winopts(buf_T *buf)
curwin->w_changelistidx = wip->wi_changelistidx;
}
- if (curwin->w_float_config.style == kWinStyleMinimal) {
+ if (curwin->w_config.style == kWinStyleMinimal) {
didset_window_options(curwin, false);
win_set_minimal_style(curwin);
}
@@ -2757,8 +2807,6 @@ linenr_T buflist_findlnum(buf_T *buf)
void buflist_list(exarg_T *eap)
{
buf_T *buf = firstbuf;
- int len;
- int i;
garray_T buflist;
buf_T **buflist_data = NULL;
@@ -2823,21 +2871,21 @@ void buflist_list(exarg_T *eap)
}
msg_putchar('\n');
- len = vim_snprintf(IObuff, IOSIZE - 20, "%3d%c%c%c%c%c \"%s\"",
- buf->b_fnum,
- buf->b_p_bl ? ' ' : 'u',
- buf == curbuf ? '%' : (curwin->w_alt_fnum == buf->b_fnum ? '#' : ' '),
- buf->b_ml.ml_mfp == NULL ? ' ' : (buf->b_nwindows == 0 ? 'h' : 'a'),
- ro_char,
- changed_char,
- NameBuff);
+ int len = vim_snprintf(IObuff, IOSIZE - 20, "%3d%c%c%c%c%c \"%s\"",
+ buf->b_fnum,
+ buf->b_p_bl ? ' ' : 'u',
+ buf == curbuf ? '%' : (curwin->w_alt_fnum == buf->b_fnum ? '#' : ' '),
+ buf->b_ml.ml_mfp == NULL ? ' ' : (buf->b_nwindows == 0 ? 'h' : 'a'),
+ ro_char,
+ changed_char,
+ NameBuff);
if (len > IOSIZE - 20) {
len = IOSIZE - 20;
}
// put "line 999" in column 40 or after the file name
- i = 40 - vim_strsize(IObuff);
+ int i = 40 - vim_strsize(IObuff);
do {
IObuff[len++] = ' ';
} while (--i > 0 && len < IOSIZE - 18);
@@ -3136,7 +3184,7 @@ static bool buf_same_file_id(buf_T *buf, FileID *file_id)
/// Print info about the current buffer.
///
/// @param fullname when non-zero print full path
-void fileinfo(int fullname, int shorthelp, int dont_truncate)
+void fileinfo(int fullname, int shorthelp, bool dont_truncate)
{
char *name;
int n;
@@ -3210,7 +3258,7 @@ void fileinfo(int fullname, int shorthelp, int dont_truncate)
(int)curwin->w_cursor.col + 1, (int)curwin->w_virtcol + 1);
}
- (void)append_arg_number(curwin, buffer, IOSIZE);
+ append_arg_number(curwin, buffer, IOSIZE);
if (dont_truncate) {
// Temporarily set msg_scroll to avoid the message being truncated.
@@ -3253,7 +3301,6 @@ void maketitle(void)
char *title_str = NULL;
char *icon_str = NULL;
int maxlen = 0;
- int len;
char buf[IOSIZE];
if (!redrawing()) {
@@ -3278,7 +3325,7 @@ void maketitle(void)
if (*p_titlestring != NUL) {
if (stl_syntax & STL_IN_TITLE) {
build_stl_str_hl(curwin, buf, sizeof(buf), p_titlestring,
- "titlestring", 0, 0, maxlen, NULL, NULL, NULL);
+ kOptTitlestring, 0, 0, maxlen, NULL, NULL, NULL, NULL);
title_str = buf;
} else {
title_str = p_titlestring;
@@ -3376,14 +3423,14 @@ void maketitle(void)
#undef SPACE_FOR_ARGNR
}
}
- int mustset = value_change(title_str, &lasttitle);
+ bool mustset = value_change(title_str, &lasttitle);
if (p_icon) {
icon_str = buf;
if (*p_iconstring != NUL) {
if (stl_syntax & STL_IN_ICON) {
build_stl_str_hl(curwin, icon_str, sizeof(buf), p_iconstring,
- "iconstring", 0, 0, 0, NULL, NULL, NULL);
+ kOptIconstring, 0, 0, 0, NULL, NULL, NULL, NULL);
} else {
icon_str = p_iconstring;
}
@@ -3396,10 +3443,10 @@ void maketitle(void)
}
*icon_str = NUL;
// Truncate name at 100 bytes.
- len = (int)strlen(buf_p);
+ int len = (int)strlen(buf_p);
if (len > 100) {
len -= 100;
- len += utf_cp_tail_off(buf_p, buf_p + len) + 1;
+ len += utf_cp_bounds(buf_p, buf_p + len).end_off;
buf_p += len;
}
STRCPY(icon_str, buf_p);
@@ -3558,16 +3605,12 @@ bool bt_prompt(buf_T *buf)
/// Open a window for a number of buffers.
void ex_buffer_all(exarg_T *eap)
{
- buf_T *buf;
win_T *wp, *wpnext;
int split_ret = OK;
- bool p_ea_save;
int open_wins = 0;
- int r;
linenr_T count; // Maximum number of windows to open.
int all; // When true also load inactive buffers.
int had_tab = cmdmod.cmod_tab;
- tabpage_T *tpnext;
if (eap->addr_count == 0) { // make as many windows as possible
count = 9999;
@@ -3592,7 +3635,7 @@ void ex_buffer_all(exarg_T *eap)
goto_tabpage_tp(first_tabpage, true, true);
}
while (true) {
- tpnext = curtab->tp_next;
+ tabpage_T *tpnext = curtab->tp_next;
// Try to close floating windows first
for (wp = lastwin->w_floating ? lastwin : firstwin; wp != NULL; wp = wpnext) {
wpnext = wp->w_floating
@@ -3637,7 +3680,7 @@ void ex_buffer_all(exarg_T *eap)
// lastwin may be aucmd_win
win_enter(lastwin_nofloating(), false);
autocmd_no_leave++;
- for (buf = firstbuf; buf != NULL && open_wins < count; buf = buf->b_next) {
+ for (buf_T *buf = firstbuf; buf != NULL && open_wins < count; buf = buf->b_next) {
// Check if this buffer needs a window
if ((!all && buf->b_ml.ml_mfp == NULL) || !buf->b_p_bl) {
continue;
@@ -3667,7 +3710,7 @@ void ex_buffer_all(exarg_T *eap)
bufref_T bufref;
set_bufref(&bufref, buf);
// Split the window and put the buffer in it.
- p_ea_save = p_ea;
+ bool p_ea_save = p_ea;
p_ea = true; // use space from all windows
split_ret = win_split(0, WSP_ROOM | WSP_BELOW);
open_wins++;
@@ -3678,7 +3721,7 @@ void ex_buffer_all(exarg_T *eap)
// Open the buffer in this window.
swap_exists_action = SEA_DIALOG;
- set_curbuf(buf, DOBUF_GOTO);
+ set_curbuf(buf, DOBUF_GOTO, false);
if (!bufref_valid(&bufref)) {
// Autocommands deleted the buffer.
swap_exists_action = SEA_NONE;
@@ -3708,7 +3751,7 @@ void ex_buffer_all(exarg_T *eap)
os_breakcheck();
if (got_int) {
- (void)vgetc(); // only break the file loading, not the rest
+ vgetc(); // only break the file loading, not the rest
break;
}
// Autocommands deleted the buffer or aborted script processing!!!
@@ -3726,8 +3769,8 @@ void ex_buffer_all(exarg_T *eap)
// Close superfluous windows.
for (wp = lastwin; open_wins > count;) {
- r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
- || autowrite(wp->w_buffer, false) == OK) && !is_aucmd_win(wp);
+ bool r = (buf_hide(wp->w_buffer) || !bufIsChanged(wp->w_buffer)
+ || autowrite(wp->w_buffer, false) == OK) && !is_aucmd_win(wp);
if (!win_valid(wp)) {
// BufWrite Autocommands made the window invalid, start over
wp = lastwin;
@@ -3800,8 +3843,8 @@ static int chk_modeline(linenr_T lnum, int flags)
int prev = -1;
for (s = ml_get(lnum); *s != NUL; s++) {
if (prev == -1 || ascii_isspace(prev)) {
- if ((prev != -1 && strncmp(s, "ex:", (size_t)3) == 0)
- || strncmp(s, "vi:", (size_t)3) == 0) {
+ if ((prev != -1 && strncmp(s, "ex:", 3) == 0)
+ || strncmp(s, "vi:", 3) == 0) {
break;
}
// Accept both "vim" and "Vim".
@@ -3866,8 +3909,8 @@ static int chk_modeline(linenr_T lnum, int flags)
// "vi:set opt opt opt: foo" -- foo not interpreted
// "vi:opt opt opt: foo" -- foo interpreted
// Accept "se" for compatibility with Elvis.
- if (strncmp(s, "set ", (size_t)4) == 0
- || strncmp(s, "se ", (size_t)3) == 0) {
+ if (strncmp(s, "set ", 4) == 0
+ || strncmp(s, "se ", 3) == 0) {
if (*e != ':') { // no terminating ':'?
break;
}
@@ -4015,6 +4058,9 @@ char *buf_spname(buf_T *buf)
if (buf->b_fname != NULL) {
return buf->b_fname;
}
+ if (buf == cmdwin_buf) {
+ return _("[Command Line]");
+ }
if (bt_prompt(buf)) {
return _("[Prompt]");
}
@@ -4026,67 +4072,6 @@ char *buf_spname(buf_T *buf)
return NULL;
}
-/// Invalidate the signcolumn if needed after deleting a sign ranging from line1 to line2.
-void buf_signcols_del_check(buf_T *buf, linenr_T line1, linenr_T line2)
-{
- linenr_T sent = buf->b_signcols.sentinel;
- if (sent >= line1 && sent <= line2) {
- // When removed sign overlaps the sentinel line, entire buffer needs to be checked.
- buf->b_signcols.sentinel = buf->b_signcols.size = 0;
- }
-}
-
-/// Invalidate the signcolumn if needed after adding a sign ranging from line1 to line2.
-void buf_signcols_add_check(buf_T *buf, linenr_T line1, linenr_T line2)
-{
- if (!buf->b_signcols.sentinel) {
- return;
- }
-
- linenr_T sent = buf->b_signcols.sentinel;
- if (sent >= line1 && sent <= line2) {
- // If added sign overlaps sentinel line, increment without invalidating.
- if (buf->b_signcols.size == buf->b_signcols.max) {
- buf->b_signcols.max++;
- }
- buf->b_signcols.size++;
- return;
- }
-
- if (line1 < buf->b_signcols.invalid_top) {
- buf->b_signcols.invalid_top = line1;
- }
- if (line2 > buf->b_signcols.invalid_bot) {
- buf->b_signcols.invalid_bot = line2;
- }
-}
-
-int buf_signcols(buf_T *buf, int max)
-{
- if (!buf->b_signs_with_text) {
- buf->b_signcols.size = 0;
- } else if (max <= 1 && buf->b_signs_with_text >= (size_t)max) {
- buf->b_signcols.size = max;
- } else {
- linenr_T sent = buf->b_signcols.sentinel;
- if (!sent || max > buf->b_signcols.max) {
- // Recheck if the window scoped maximum 'signcolumn' is greater than the
- // previous maximum or if there is no sentinel line yet.
- buf->b_signcols.invalid_top = sent ? sent : 1;
- buf->b_signcols.invalid_bot = sent ? sent : buf->b_ml.ml_line_count;
- }
-
- if (buf->b_signcols.invalid_bot) {
- decor_validate_signcols(buf, max);
- }
- }
-
- buf->b_signcols.max = max;
- buf->b_signcols.invalid_top = MAXLNUM;
- buf->b_signcols.invalid_bot = 0;
- return buf->b_signcols.size;
-}
-
/// Get "buf->b_fname", use "[No Name]" if it is NULL.
char *buf_get_fname(const buf_T *buf)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
@@ -4193,6 +4178,7 @@ void wipe_buffer(buf_T *buf, bool aucmd)
/// - Always considered 'nomodified'
///
/// @param bufnr Buffer to switch to, or 0 to create a new buffer.
+/// @param bufname Buffer name, or NULL.
///
/// @see curbufIsChanged()
///
@@ -4202,12 +4188,60 @@ int buf_open_scratch(handle_T bufnr, char *bufname)
if (do_ecmd((int)bufnr, NULL, NULL, NULL, ECMD_ONE, ECMD_HIDE, NULL) == FAIL) {
return FAIL;
}
- apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf);
- (void)setfname(curbuf, bufname, NULL, true);
- apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf);
- set_option_value_give_err("bh", STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL);
- set_option_value_give_err("bt", STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL);
- set_option_value_give_err("swf", BOOLEAN_OPTVAL(false), OPT_LOCAL);
+ if (bufname != NULL) {
+ apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf);
+ setfname(curbuf, bufname, NULL, true);
+ apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf);
+ }
+ set_option_value_give_err(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL);
+ set_option_value_give_err(kOptBuftype, STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL);
+ set_option_value_give_err(kOptSwapfile, BOOLEAN_OPTVAL(false), OPT_LOCAL);
RESET_BINDING(curwin);
return OK;
}
+
+bool buf_is_empty(buf_T *buf)
+{
+ return buf->b_ml.ml_line_count == 1 && *ml_get_buf(buf, 1) == '\0';
+}
+
+/// Increment b:changedtick value
+///
+/// Also checks b: for consistency in case of debug build.
+///
+/// @param[in,out] buf Buffer to increment value in.
+void buf_inc_changedtick(buf_T *const buf)
+ FUNC_ATTR_NONNULL_ALL
+{
+ buf_set_changedtick(buf, buf_get_changedtick(buf) + 1);
+}
+
+/// Set b:changedtick, also checking b: for consistency in debug build
+///
+/// @param[out] buf Buffer to set changedtick in.
+/// @param[in] changedtick New value.
+void buf_set_changedtick(buf_T *const buf, const varnumber_T changedtick)
+ FUNC_ATTR_NONNULL_ALL
+{
+ typval_T old_val = buf->changedtick_di.di_tv;
+
+#ifndef NDEBUG
+ dictitem_T *const changedtick_di = tv_dict_find(buf->b_vars, S_LEN("changedtick"));
+ assert(changedtick_di != NULL);
+ assert(changedtick_di->di_tv.v_type == VAR_NUMBER);
+ assert(changedtick_di->di_tv.v_lock == VAR_FIXED);
+ // For some reason formatc does not like the below.
+# ifndef UNIT_TESTING_LUA_PREPROCESSING
+ assert(changedtick_di->di_flags == (DI_FLAGS_RO|DI_FLAGS_FIX));
+# endif
+ assert(changedtick_di == (dictitem_T *)&buf->changedtick_di);
+#endif
+ buf->changedtick_di.di_tv.vval.v_number = changedtick;
+
+ if (tv_dict_is_watched(buf->b_vars)) {
+ tv_dict_watcher_notify(buf->b_vars,
+ (char *)buf->changedtick_di.di_key,
+ &buf->changedtick_di.di_tv,
+ &old_val);
+ }
+}
diff --git a/src/nvim/buffer.h b/src/nvim/buffer.h
index 36e70d1927..4c5023d39a 100644
--- a/src/nvim/buffer.h
+++ b/src/nvim/buffer.h
@@ -1,18 +1,15 @@
#pragma once
-#include <assert.h>
-#include <stdbool.h>
-#include <stddef.h>
+#include <stdint.h>
-#include "nvim/buffer_defs.h" // IWYU pragma: export
-#include "nvim/eval/typval.h"
+#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h"
-#include "nvim/ex_cmds_defs.h"
+#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/func_attr.h"
+#include "nvim/gettext_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
-#include "nvim/memline.h"
-#include "nvim/memline_defs.h"
-#include "nvim/pos_defs.h"
+#include "nvim/marktree_defs.h"
+#include "nvim/types_defs.h"
/// Values for buflist_getfile()
enum getf_values {
@@ -74,38 +71,6 @@ EXTERN char *msg_qflist INIT( = N_("[Quickfix List]"));
# include "buffer.h.generated.h"
#endif
-static inline void buf_set_changedtick(buf_T *buf, varnumber_T changedtick)
- REAL_FATTR_NONNULL_ALL REAL_FATTR_ALWAYS_INLINE;
-
-/// Set b:changedtick, also checking b: for consistency in debug build
-///
-/// @param[out] buf Buffer to set changedtick in.
-/// @param[in] changedtick New value.
-static inline void buf_set_changedtick(buf_T *const buf, const varnumber_T changedtick)
-{
- typval_T old_val = buf->changedtick_di.di_tv;
-
-#ifndef NDEBUG
- dictitem_T *const changedtick_di = tv_dict_find(buf->b_vars, S_LEN("changedtick"));
- assert(changedtick_di != NULL);
- assert(changedtick_di->di_tv.v_type == VAR_NUMBER);
- assert(changedtick_di->di_tv.v_lock == VAR_FIXED);
- // For some reason formatc does not like the below.
-# ifndef UNIT_TESTING_LUA_PREPROCESSING
- assert(changedtick_di->di_flags == (DI_FLAGS_RO|DI_FLAGS_FIX));
-# endif
- assert(changedtick_di == (dictitem_T *)&buf->changedtick_di);
-#endif
- buf->changedtick_di.di_tv.vval.v_number = changedtick;
-
- if (tv_dict_is_watched(buf->b_vars)) {
- tv_dict_watcher_notify(buf->b_vars,
- (char *)buf->changedtick_di.di_key,
- &buf->changedtick_di.di_tv,
- &old_val);
- }
-}
-
static inline varnumber_T buf_get_changedtick(const buf_T *buf)
REAL_FATTR_NONNULL_ALL REAL_FATTR_ALWAYS_INLINE REAL_FATTR_PURE
REAL_FATTR_WARN_UNUSED_RESULT;
@@ -120,20 +85,7 @@ static inline varnumber_T buf_get_changedtick(const buf_T *const buf)
return buf->changedtick_di.di_tv.vval.v_number;
}
-static inline void buf_inc_changedtick(buf_T *buf)
- REAL_FATTR_NONNULL_ALL REAL_FATTR_ALWAYS_INLINE;
-
-/// Increment b:changedtick value
-///
-/// Also checks b: for consistency in case of debug build.
-///
-/// @param[in,out] buf Buffer to increment value in.
-static inline void buf_inc_changedtick(buf_T *const buf)
-{
- buf_set_changedtick(buf, buf_get_changedtick(buf) + 1);
-}
-
-static inline bool buf_is_empty(buf_T *buf)
+static inline uint32_t buf_meta_total(const buf_T *b, MetaIndex m)
{
- return buf->b_ml.ml_line_count == 1 && *ml_get_buf(buf, 1) == '\0';
+ return b->b_marktree->meta_root[m];
}
diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h
index e59539f900..1e5086309c 100644
--- a/src/nvim/buffer_defs.h
+++ b/src/nvim/buffer_defs.h
@@ -4,7 +4,15 @@
#include <stdint.h>
#include <stdio.h>
-typedef struct file_buffer buf_T;
+#include "nvim/arglist_defs.h"
+#include "nvim/grid_defs.h"
+#include "nvim/mapping_defs.h"
+#include "nvim/marktree_defs.h"
+#include "nvim/memline_defs.h"
+#include "nvim/option_defs.h"
+#include "nvim/os/fs_defs.h"
+#include "nvim/statusline_defs.h"
+#include "nvim/undo_defs.h"
/// Reference to a buffer that stores the value of buf_free_count.
/// bufref_valid() only needs to check "buf" when the count differs.
@@ -14,24 +22,6 @@ typedef struct {
int br_buf_free_count;
} bufref_T;
-#include "klib/kvec.h"
-#include "nvim/api/private/defs.h"
-#include "nvim/arglist_defs.h"
-#include "nvim/eval/typval_defs.h"
-#include "nvim/extmark_defs.h"
-#include "nvim/garray_defs.h"
-#include "nvim/grid_defs.h"
-#include "nvim/hashtab_defs.h"
-#include "nvim/highlight_defs.h"
-#include "nvim/map_defs.h"
-#include "nvim/mapping_defs.h"
-#include "nvim/mark_defs.h"
-#include "nvim/marktree.h"
-#include "nvim/option_vars.h"
-#include "nvim/pos_defs.h"
-#include "nvim/statusline_defs.h"
-#include "nvim/undo_defs.h"
-
#define GETFILE_SUCCESS(x) ((x) <= 0)
#define MODIFIABLE(buf) (buf->b_p_ma)
@@ -80,20 +70,12 @@ typedef struct {
// Mask to check for flags that prevent normal writing
#define BF_WRITE_MASK (BF_NOTEDITED + BF_NEW + BF_READERR)
-typedef struct window_S win_T;
typedef struct wininfo_S wininfo_T;
typedef struct frame_S frame_T;
typedef uint64_t disptick_T; // display tick type
-#include "nvim/memline_defs.h"
-#include "nvim/os/fs_defs.h"
-#include "nvim/regexp_defs.h"
-#include "nvim/sign_defs.h"
-#include "nvim/syntax_defs.h"
-#include "nvim/terminal.h"
-
// The taggy struct is used to store the information about a :tag command.
-typedef struct taggy {
+typedef struct {
char *tagname; // tag name
fmark_T fmark; // cursor position BEFORE ":tag"
int cur_match; // match number
@@ -357,8 +339,6 @@ typedef struct {
#define BUF_UPDATE_CALLBACKS_INIT { LUA_NOREF, LUA_NOREF, LUA_NOREF, \
LUA_NOREF, LUA_NOREF, false, false }
-EXTERN int curbuf_splice_pending INIT( = 0);
-
#define BUF_HAS_QF_ENTRY 1
#define BUF_HAS_LL_ENTRY 2
@@ -705,11 +685,12 @@ struct file_buffer {
// may use a different synblock_T.
struct {
- int size; // last calculated number of sign columns
- int max; // maximum value size is valid for.
- linenr_T sentinel; // a line number which is holding up the signcolumn
- linenr_T invalid_top; // first invalid line number that needs to be checked
- linenr_T invalid_bot; // last invalid line number that needs to be checked
+ int max; // maximum number of signs on a single line
+ int count[SIGN_SHOW_MAX]; // number of lines with number of signs
+ bool resized; // whether max changed at start of redraw
+ bool autom; // whether 'signcolumn' is displayed in "auto:n>1"
+ // configured window. "b_signcols" calculation
+ // is skipped if false.
} b_signcols;
Terminal *terminal; // Terminal instance associated with the buffer
@@ -720,10 +701,6 @@ 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
// array of channel_id:s which have asked to receive updates for this
// buffer.
@@ -736,7 +713,7 @@ struct file_buffer {
// Measurements of the deleted or replaced region since the last update
// event. Some consumers of buffer changes need to know the byte size (like
- // tree-sitter) or the corresponding UTF-32/UTF-16 size (like LSP) of the
+ // treesitter) or the corresponding UTF-32/UTF-16 size (like LSP) of the
// deleted text.
size_t deleted_bytes;
size_t deleted_bytes2;
@@ -816,7 +793,7 @@ struct tabpage_S {
// may not reflect what is actually in the buffer. When wl_valid is false,
// the entries can only be used to count the number of displayed lines used.
// wl_lnum and wl_lastlnum are invalid too.
-typedef struct w_line {
+typedef struct {
linenr_T wl_lnum; // buffer line number for logical line
uint16_t wl_size; // height in screen lines
char wl_valid; // true values are valid for text in buffer
@@ -904,12 +881,7 @@ enum {
kFloatAnchorSouth = 2,
};
-// NW -> 0
-// NE -> kFloatAnchorEast
-// SW -> kFloatAnchorSouth
-// SE -> kFloatAnchorSouth | kFloatAnchorEast
-EXTERN const char *const float_anchor_str[] INIT( = { "NW", "NE", "SW", "SE" });
-
+/// Keep in sync with float_relative_str[] in nvim_win_get_config()
typedef enum {
kFloatRelativeEditor = 0,
kFloatRelativeWindow = 1,
@@ -917,8 +889,13 @@ typedef enum {
kFloatRelativeMouse = 3,
} FloatRelative;
-EXTERN const char *const float_relative_str[] INIT( = { "editor", "win",
- "cursor", "mouse" });
+/// Keep in sync with win_split_str[] in nvim_win_get_config() (api/win_config.c)
+typedef enum {
+ kWinSplitLeft = 0,
+ kWinSplitRight = 1,
+ kWinSplitAbove = 2,
+ kWinSplitBelow = 3,
+} WinSplit;
typedef enum {
kWinStyleUnused = 0,
@@ -936,6 +913,7 @@ typedef enum {
kBorderTextFooter = 1,
} BorderTextType;
+/// See ":help nvim_open_win()" for documentation.
typedef struct {
Window window;
lpos_T bufpos;
@@ -945,6 +923,7 @@ typedef struct {
FloatRelative relative;
bool external;
bool focusable;
+ WinSplit split;
int zindex;
WinStyle style;
bool border;
@@ -963,18 +942,19 @@ typedef struct {
bool noautocmd;
bool fixed;
bool hide;
-} FloatConfig;
-
-#define FLOAT_CONFIG_INIT ((FloatConfig){ .height = 0, .width = 0, \
- .bufpos = { -1, 0 }, \
- .row = 0, .col = 0, .anchor = 0, \
- .relative = 0, .external = false, \
- .focusable = true, \
- .zindex = kZIndexFloatDefault, \
- .style = kWinStyleUnused, \
- .noautocmd = false, \
- .hide = false, \
- .fixed = false })
+} WinConfig;
+
+#define WIN_CONFIG_INIT ((WinConfig){ .height = 0, .width = 0, \
+ .bufpos = { -1, 0 }, \
+ .row = 0, .col = 0, .anchor = 0, \
+ .relative = 0, .external = false, \
+ .focusable = true, \
+ .split = 0, \
+ .zindex = kZIndexFloatDefault, \
+ .style = kWinStyleUnused, \
+ .noautocmd = false, \
+ .hide = false, \
+ .fixed = false })
// Structure to store last cursor position and topline. Used by check_lnums()
// and reset_lnums().
@@ -987,41 +967,41 @@ typedef struct {
/// Characters from the 'listchars' option.
typedef struct {
- int eol;
- int ext;
- int prec;
- int nbsp;
- int space;
- int tab1; ///< first tab character
- int tab2; ///< second tab character
- int tab3; ///< third tab character
- int lead;
- int trail;
- int *multispace;
- int *leadmultispace;
- int conceal;
+ schar_T eol;
+ schar_T ext;
+ schar_T prec;
+ schar_T nbsp;
+ schar_T space;
+ schar_T tab1; ///< first tab character
+ schar_T tab2; ///< second tab character
+ schar_T tab3; ///< third tab character
+ schar_T lead;
+ schar_T trail;
+ schar_T *multispace;
+ schar_T *leadmultispace;
+ schar_T conceal;
} lcs_chars_T;
/// Characters from the 'fillchars' option.
typedef struct {
- int stl;
- int stlnc;
- int wbr;
- int horiz;
- int horizup;
- int horizdown;
- int vert;
- int vertleft;
- int vertright;
- int verthoriz;
- int fold;
- int foldopen; ///< when fold is open
- int foldclosed; ///< when fold is closed
- int foldsep; ///< continuous fold marker
- int diff;
- int msgsep;
- int eob;
- int lastline;
+ schar_T stl;
+ schar_T stlnc;
+ schar_T wbr;
+ schar_T horiz;
+ schar_T horizup;
+ schar_T horizdown;
+ schar_T vert;
+ schar_T vertleft;
+ schar_T vertright;
+ schar_T verthoriz;
+ schar_T fold;
+ schar_T foldopen; ///< when fold is open
+ schar_T foldclosed; ///< when fold is closed
+ schar_T foldsep; ///< continuous fold marker
+ schar_T diff;
+ schar_T msgsep;
+ schar_T eob;
+ schar_T lastline;
} fcs_chars_T;
/// Structure which contains all information that belongs to a window.
@@ -1040,6 +1020,8 @@ struct window_S {
int w_ns_hl_active;
int *w_ns_hl_attr;
+ Set(uint32_t) w_ns_set;
+
int w_hl_id_normal; ///< 'winhighlight' normal id
int w_hl_attr_normal; ///< 'winhighlight' normal final attrs
int w_hl_attr_normalnc; ///< 'winhighlight' NormalNC final attrs
@@ -1297,8 +1279,9 @@ struct window_S {
ScreenGrid w_grid; // the grid specific to the window
ScreenGrid w_grid_alloc; // the grid specific to the window
bool w_pos_changed; // true if window position changed
- bool w_floating; ///< whether the window is floating
- FloatConfig w_float_config;
+ bool w_floating; ///< whether the window is floating
+ bool w_float_is_info; // the floating window is info float
+ WinConfig w_config;
// w_fraction is the fractional row of the cursor within the window, from
// 0 at the top row to FRACTION_MULT at the last row.
@@ -1331,9 +1314,3 @@ struct window_S {
// Size of the w_statuscol_click_defs array
size_t w_statuscol_click_defs_size;
};
-
-/// Macros defined in Vim, but not in Neovim
-// uncrustify:off
-#define CHANGEDTICK(buf) \
- (=== Include buffer.h & use buf_(get|set|inc) _changedtick ===)
-// uncrustify:on
diff --git a/src/nvim/buffer_updates.c b/src/nvim/buffer_updates.c
index 01bcb9d7be..e725678937 100644
--- a/src/nvim/buffer_updates.c
+++ b/src/nvim/buffer_updates.c
@@ -11,7 +11,6 @@
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
@@ -22,7 +21,7 @@
#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "buffer_updates.c.generated.h" // IWYU pragma: export
+# include "buffer_updates.c.generated.h"
#endif
// Register a channel. Return True if the channel was added, or already added.
@@ -56,36 +55,33 @@ bool buf_updates_register(buf_T *buf, uint64_t channel_id, BufUpdateCallbacks cb
kv_push(buf->update_channels, channel_id);
if (send_buffer) {
- Array args = ARRAY_DICT_INIT;
- args.size = 6;
- args.items = xcalloc(args.size, sizeof(Object));
+ MAXSIZE_TEMP_ARRAY(args, 6);
// the first argument is always the buffer handle
- args.items[0] = BUFFER_OBJ(buf->handle);
- args.items[1] = INTEGER_OBJ(buf_get_changedtick(buf));
+ ADD_C(args, BUFFER_OBJ(buf->handle));
+ ADD_C(args, INTEGER_OBJ(buf_get_changedtick(buf)));
// the first line that changed (zero-indexed)
- args.items[2] = INTEGER_OBJ(0);
+ ADD_C(args, INTEGER_OBJ(0));
// the last line that was changed
- args.items[3] = INTEGER_OBJ(-1);
- Array linedata = ARRAY_DICT_INIT;
+ ADD_C(args, INTEGER_OBJ(-1));
// collect buffer contents
STATIC_ASSERT(SIZE_MAX >= MAXLNUM, "size_t smaller than MAXLNUM");
size_t line_count = (size_t)buf->b_ml.ml_line_count;
- if (line_count >= 1) {
- linedata.size = line_count;
- linedata.items = xcalloc(line_count, sizeof(Object));
-
- buf_collect_lines(buf, line_count, 1, 0, true, &linedata, NULL, NULL);
+ Array linedata = ARRAY_DICT_INIT;
+ Arena arena = ARENA_EMPTY;
+ if (line_count > 0) {
+ linedata = arena_array(&arena, line_count);
+ buf_collect_lines(buf, line_count, 1, 0, true, &linedata, NULL, &arena);
}
- args.items[4] = ARRAY_OBJ(linedata);
- args.items[5] = BOOLEAN_OBJ(false);
+ ADD_C(args, ARRAY_OBJ(linedata));
+ ADD_C(args, BOOLEAN_OBJ(false));
rpc_send_event(channel_id, "nvim_buf_lines_event", args);
- api_free_array(args); // TODO(bfredl): no
+ arena_mem_free(arena_finish(&arena));
} else {
buf_updates_changedtick_single(buf, channel_id);
}
@@ -177,16 +173,13 @@ void buf_updates_unload(buf_T *buf, bool can_reload)
}
if (thecb != LUA_NOREF) {
- Array args = ARRAY_DICT_INIT;
- Object items[1];
- args.size = 1;
- args.items = items;
+ MAXSIZE_TEMP_ARRAY(args, 1);
// the first argument is always the buffer handle
- args.items[0] = BUFFER_OBJ(buf->handle);
+ ADD_C(args, BUFFER_OBJ(buf->handle));
TEXTLOCK_WRAP({
- nlua_call_ref(thecb, keep ? "reload" : "detach", args, false, NULL);
+ nlua_call_ref(thecb, keep ? "reload" : "detach", args, false, NULL, NULL);
});
}
@@ -220,45 +213,43 @@ void buf_updates_send_changes(buf_T *buf, linenr_T firstline, int64_t num_added,
// if one the channels doesn't work, put its ID here so we can remove it later
uint64_t badchannelid = 0;
+ Arena arena = ARENA_EMPTY;
+ Array linedata = ARRAY_DICT_INIT;
+ if (num_added > 0 && kv_size(buf->update_channels)) {
+ STATIC_ASSERT(SIZE_MAX >= MAXLNUM, "size_t smaller than MAXLNUM");
+ linedata = arena_array(&arena, (size_t)num_added);
+ buf_collect_lines(buf, (size_t)num_added, firstline, 0, true, &linedata,
+ NULL, &arena);
+ }
+
// notify each of the active channels
for (size_t i = 0; i < kv_size(buf->update_channels); i++) {
uint64_t channelid = kv_A(buf->update_channels, i);
// send through the changes now channel contents now
- Array args = ARRAY_DICT_INIT;
- args.size = 6;
- args.items = xcalloc(args.size, sizeof(Object));
+ MAXSIZE_TEMP_ARRAY(args, 6);
// the first argument is always the buffer handle
- args.items[0] = BUFFER_OBJ(buf->handle);
+ ADD_C(args, BUFFER_OBJ(buf->handle));
// next argument is b:changedtick
- args.items[1] = send_tick ? INTEGER_OBJ(buf_get_changedtick(buf)) : NIL;
+ ADD_C(args, send_tick ? INTEGER_OBJ(buf_get_changedtick(buf)) : NIL);
// the first line that changed (zero-indexed)
- args.items[2] = INTEGER_OBJ(firstline - 1);
+ ADD_C(args, INTEGER_OBJ(firstline - 1));
// the last line that was changed
- args.items[3] = INTEGER_OBJ(firstline - 1 + num_removed);
+ ADD_C(args, INTEGER_OBJ(firstline - 1 + num_removed));
// linedata of lines being swapped in
- Array linedata = ARRAY_DICT_INIT;
- if (num_added > 0) {
- STATIC_ASSERT(SIZE_MAX >= MAXLNUM, "size_t smaller than MAXLNUM");
- linedata.size = (size_t)num_added;
- linedata.items = xcalloc((size_t)num_added, sizeof(Object));
- buf_collect_lines(buf, (size_t)num_added, firstline, 0, true, &linedata,
- NULL, NULL);
- }
- args.items[4] = ARRAY_OBJ(linedata);
- args.items[5] = BOOLEAN_OBJ(false);
+ ADD_C(args, ARRAY_OBJ(linedata));
+ ADD_C(args, BOOLEAN_OBJ(false));
if (!rpc_send_event(channelid, "nvim_buf_lines_event", args)) {
// We can't unregister the channel while we're iterating over the
// update_channels array, so we remember its ID to unregister it at
// the end.
badchannelid = channelid;
}
- api_free_array(args); // TODO(bfredl): no
}
// We can only ever remove one dead channel at a time. This is OK because the
@@ -269,46 +260,45 @@ void buf_updates_send_changes(buf_T *buf, linenr_T firstline, int64_t num_added,
buf_updates_unregister(buf, badchannelid);
}
- // notify each of the active channels
+ // callbacks don't use linedata
+ arena_mem_free(arena_finish(&arena));
+
+ // notify each of the active callbacks
size_t j = 0;
for (size_t i = 0; i < kv_size(buf->update_callbacks); i++) {
BufUpdateCallbacks cb = kv_A(buf->update_callbacks, i);
bool keep = true;
if (cb.on_lines != LUA_NOREF && (cb.preview || !cmdpreview)) {
- Array args = ARRAY_DICT_INIT;
- Object items[8];
- args.size = 6; // may be increased to 8 below
- args.items = items;
+ MAXSIZE_TEMP_ARRAY(args, 8); // 6 or 8 used
// the first argument is always the buffer handle
- args.items[0] = BUFFER_OBJ(buf->handle);
+ ADD_C(args, BUFFER_OBJ(buf->handle));
// next argument is b:changedtick
- args.items[1] = send_tick ? INTEGER_OBJ(buf_get_changedtick(buf)) : NIL;
+ ADD_C(args, send_tick ? INTEGER_OBJ(buf_get_changedtick(buf)) : NIL);
// the first line that changed (zero-indexed)
- args.items[2] = INTEGER_OBJ(firstline - 1);
+ ADD_C(args, INTEGER_OBJ(firstline - 1));
// the last line that was changed
- args.items[3] = INTEGER_OBJ(firstline - 1 + num_removed);
+ ADD_C(args, INTEGER_OBJ(firstline - 1 + num_removed));
// the last line in the updated range
- args.items[4] = INTEGER_OBJ(firstline - 1 + num_added);
+ ADD_C(args, INTEGER_OBJ(firstline - 1 + num_added));
// byte count of previous contents
- args.items[5] = INTEGER_OBJ((Integer)deleted_bytes);
+ ADD_C(args, INTEGER_OBJ((Integer)deleted_bytes));
if (cb.utf_sizes) {
- args.size = 8;
- args.items[6] = INTEGER_OBJ((Integer)deleted_codepoints);
- args.items[7] = INTEGER_OBJ((Integer)deleted_codeunits);
+ ADD_C(args, INTEGER_OBJ((Integer)deleted_codepoints));
+ ADD_C(args, INTEGER_OBJ((Integer)deleted_codeunits));
}
Object res;
TEXTLOCK_WRAP({
- res = nlua_call_ref(cb.on_lines, "lines", args, false, NULL);
+ res = nlua_call_ref(cb.on_lines, "lines", args, kRetNilBool, NULL, NULL);
});
- if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
+ if (LUARET_TRUTHY(res)) {
buffer_update_callbacks_free(cb);
keep = false;
}
@@ -355,10 +345,10 @@ void buf_updates_send_splice(buf_T *buf, int start_row, colnr_T start_col, bcoun
Object res;
TEXTLOCK_WRAP({
- res = nlua_call_ref(cb.on_bytes, "bytes", args, false, NULL);
+ res = nlua_call_ref(cb.on_bytes, "bytes", args, kRetNilBool, NULL, NULL);
});
- if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
+ if (LUARET_TRUTHY(res)) {
buffer_update_callbacks_free(cb);
keep = false;
}
@@ -391,10 +381,10 @@ void buf_updates_changedtick(buf_T *buf)
Object res;
TEXTLOCK_WRAP({
- res = nlua_call_ref(cb.on_changedtick, "changedtick", args, false, NULL);
+ res = nlua_call_ref(cb.on_changedtick, "changedtick", args, kRetNilBool, NULL, NULL);
});
- if (res.type == kObjectTypeBoolean && res.data.boolean == true) {
+ if (LUARET_TRUTHY(res)) {
buffer_update_callbacks_free(cb);
keep = false;
}
diff --git a/src/nvim/bufwrite.c b/src/nvim/bufwrite.c
index f774fcb057..94a6604fc1 100644
--- a/src/nvim/bufwrite.c
+++ b/src/nvim/bufwrite.c
@@ -12,6 +12,7 @@
#include "auto/config.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/bufwrite.h"
@@ -23,21 +24,24 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_eval.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/iconv_defs.h"
#include "nvim/input.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/sha256.h"
@@ -45,6 +49,7 @@
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
+#include "nvim/undo_defs.h"
#include "nvim/vim_defs.h"
static const char *err_readonly = "is read-only (cannot override: \"W\" in 'cpoptions')";
@@ -187,7 +192,7 @@ static int buf_write_convert_with_iconv(struct bw_info *ip, char **bufp, int *le
size_t save_len = tolen;
// output the initial shift state sequence
- (void)iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
+ iconv(ip->bw_iconv_fd, NULL, NULL, &to, &tolen);
// There is a bug in iconv() on Linux (which appears to be
// wide-spread) which sets "to" to NULL and messes up "tolen".
@@ -379,7 +384,7 @@ static int make_bom(char *buf_in, char *name)
return 3;
}
char *p = (char *)buf;
- (void)ucs2bytes(0xfeff, &p, flags);
+ ucs2bytes(0xfeff, &p, flags);
return (int)((uint8_t *)p - buf);
}
@@ -481,8 +486,7 @@ static int buf_write_do_autocmds(buf_T *buf, char **fnamep, char **sfnamep, char
semsg(_(e_no_matching_autocommands_for_buftype_str_buffer), curbuf->b_p_bt);
}
- if (nofile_err
- || aborting()) {
+ if (nofile_err || aborting()) {
// An aborting error, interrupt or exception in the
// autocommands.
return FAIL;
@@ -721,7 +725,7 @@ static int get_fileinfo(buf_T *buf, char *fname, bool overwriting, bool forceit,
static int buf_write_make_backup(char *fname, bool append, FileInfo *file_info_old, vim_acl_T acl,
int perm, unsigned bkc, bool file_readonly, bool forceit,
- int *backup_copyp, char **backupp, Error_T *err)
+ bool *backup_copyp, char **backupp, Error_T *err)
{
FileInfo file_info;
const bool no_prepend_dot = false;
@@ -799,7 +803,7 @@ static int buf_write_make_backup(char *fname, bool append, FileInfo *file_info_o
char *backup_ext = *p_bex == NUL ? ".bak" : p_bex;
if (*backup_copyp) {
- int some_error = false;
+ bool some_error = false;
// Try to make the backup in each directory in the 'bdir' option.
//
@@ -898,7 +902,7 @@ static int buf_write_make_backup(char *fname, bool append, FileInfo *file_info_o
// set file protection same as original file, but
// strip s-bit.
- (void)os_setperm(*backupp, perm & 0777);
+ os_setperm(*backupp, perm & 0777);
#ifdef UNIX
//
@@ -1059,14 +1063,14 @@ nobackup:
///
/// @return FAIL for failure, OK otherwise
int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T end, exarg_T *eap,
- int append, int forceit, int reset_changed, int filtering)
+ bool append, bool forceit, bool reset_changed, bool filtering)
{
int retval = OK;
int msg_save = msg_scroll;
- int prev_got_int = got_int;
+ bool prev_got_int = got_int;
// writing everything
- int whole = (start == 1 && end == buf->b_ml.ml_line_count);
- int write_undo_file = false;
+ bool whole = (start == 1 && end == buf->b_ml.ml_line_count);
+ bool write_undo_file = false;
context_sha256_T sha_ctx;
unsigned bkc = get_bkc_value(buf);
@@ -1135,8 +1139,8 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
fname = sfname;
#endif
-// true if writing over original
- int overwriting = buf->b_ffname != NULL && path_fnamecmp(ffname, buf->b_ffname) == 0;
+ // true if writing over original
+ bool overwriting = buf->b_ffname != NULL && path_fnamecmp(ffname, buf->b_ffname) == 0;
no_wait_return++; // don't wait for return yet
@@ -1219,7 +1223,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
dobackup = false;
}
- int backup_copy = false; // copy the original file?
+ bool backup_copy = false; // copy the original file?
// Save the value of got_int and reset it. We don't want a previous
// interruption cancel writing, only hitting CTRL-C while writing should
@@ -1245,14 +1249,14 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
#if defined(UNIX)
- int made_writable = false; // 'w' bit has been set
+ bool made_writable = false; // 'w' bit has been set
// When using ":w!" and the file was read-only: make it writable
if (forceit && perm >= 0 && !(perm & 0200)
&& file_info_old.stat.st_uid == getuid()
&& vim_strchr(p_cpo, CPO_FWRITE) == NULL) {
perm |= 0200;
- (void)os_setperm(fname, perm);
+ os_setperm(fname, perm);
made_writable = true;
}
#endif
@@ -1279,8 +1283,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
// This makes all block numbers positive so that recovery does not need
// the original file.
// Don't do this if there is a backup file and we are exiting.
- if (reset_changed && !newfile && overwriting
- && !(exiting && backup != NULL)) {
+ if (reset_changed && !newfile && overwriting && !(exiting && backup != NULL)) {
ml_preserve(buf, false, !!p_fs);
if (got_int) {
err = set_err(_(e_interr));
@@ -1304,7 +1307,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
// Check if the file needs to be converted.
- int converted = need_conversion(fenc);
+ bool converted = need_conversion(fenc);
int wb_flags = 0;
// Check if UTF-8 to UCS-2/4 or Latin1 conversion needs to be done. Or
@@ -1352,7 +1355,7 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
}
}
- int notconverted = false;
+ bool notconverted = false;
if (converted && wb_flags == 0
&& write_info.bw_iconv_fd == (iconv_t)-1
@@ -1364,11 +1367,11 @@ int buf_write(buf_T *buf, char *fname, char *sfname, linenr_T start, linenr_T en
notconverted = true;
}
- int no_eol = false; // no end-of-line written
+ bool no_eol = false; // no end-of-line written
int nchars;
linenr_T lnum;
int fileformat;
- int checking_conversion;
+ bool checking_conversion;
int fd;
@@ -1606,7 +1609,7 @@ restore_backup:
if (!buf->b_p_fixeol && buf->b_p_eof) {
// write trailing CTRL-Z
- (void)write_eintr(write_info.bw_fd, "\x1a", 1);
+ write_eintr(write_info.bw_fd, "\x1a", 1);
}
// Stop when writing done or an error was encountered.
@@ -1655,7 +1658,7 @@ restore_backup:
|| file_info.stat.st_gid != file_info_old.stat.st_gid) {
os_fchown(fd, (uv_uid_t)file_info_old.stat.st_uid, (uv_gid_t)file_info_old.stat.st_gid);
if (perm >= 0) { // Set permission again, may have changed.
- (void)os_setperm(wfname, perm);
+ os_setperm(wfname, perm);
}
}
buf_set_file_id(buf);
@@ -1676,7 +1679,7 @@ restore_backup:
}
#endif
if (perm >= 0) { // Set perm. of new file same as old file.
- (void)os_setperm(wfname, perm);
+ os_setperm(wfname, perm);
}
// Probably need to set the ACL before changing the user (can't set the
// ACL on a file the user doesn't own).
diff --git a/src/nvim/bufwrite.h b/src/nvim/bufwrite.h
index 9ed6216847..ce9e04d2b1 100644
--- a/src/nvim/bufwrite.h
+++ b/src/nvim/bufwrite.h
@@ -1,8 +1,8 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "bufwrite.h.generated.h"
diff --git a/src/nvim/change.c b/src/nvim/change.c
index 81a55b92ee..1c7724f010 100644
--- a/src/nvim/change.c
+++ b/src/nvim/change.c
@@ -8,6 +8,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/assert_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
@@ -20,18 +21,23 @@
#include "nvim/eval.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/extmark.h"
+#include "nvim/extmark_defs.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/insexpand.h"
#include "nvim/macros_defs.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
+#include "nvim/marktree_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
@@ -43,8 +49,10 @@
#include "nvim/search.h"
#include "nvim/spell.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/textformat.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
@@ -86,7 +94,7 @@ void change_warning(buf_T *buf, int col)
msg_puts_attr(_(w_readonly), HL_ATTR(HLF_W) | MSG_HIST);
set_vim_var_string(VV_WARNINGMSG, _(w_readonly), -1);
msg_clr_eos();
- (void)msg_end();
+ msg_end();
if (msg_silent == 0 && !silent_mode && ui_active()) {
ui_flush();
os_delay(1002, true); // give the user time to think about it
@@ -155,6 +163,71 @@ void changed_internal(buf_T *buf)
need_maketitle = true; // set window title later
}
+/// Invalidate a window's w_valid flags and w_lines[] entries after changing lines.
+static void changed_lines_invalidate_win(win_T *wp, linenr_T lnum, colnr_T col, linenr_T lnume,
+ linenr_T xtra)
+{
+ // If the changed line is in a range of previously folded lines,
+ // compare with the first line in that range.
+ if (wp->w_cursor.lnum <= lnum) {
+ int i = find_wl_entry(wp, lnum);
+ if (i >= 0 && wp->w_cursor.lnum > wp->w_lines[i].wl_lnum) {
+ changed_line_abv_curs_win(wp);
+ }
+ }
+
+ if (wp->w_cursor.lnum > lnum) {
+ changed_line_abv_curs_win(wp);
+ } else if (wp->w_cursor.lnum == lnum && wp->w_cursor.col >= col) {
+ changed_cline_bef_curs(wp);
+ }
+ if (wp->w_botline >= lnum) {
+ // Assume that botline doesn't change (inserted lines make
+ // other lines scroll down below botline).
+ approximate_botline_win(wp);
+ }
+
+ // Check if any w_lines[] entries have become invalid.
+ // For entries below the change: Correct the lnums for inserted/deleted lines.
+ // Makes it possible to stop displaying after the change.
+ for (int i = 0; i < wp->w_lines_valid; i++) {
+ if (wp->w_lines[i].wl_valid) {
+ if (wp->w_lines[i].wl_lnum >= lnum) {
+ // Do not change wl_lnum at index zero, it is used to compare with w_topline.
+ // Invalidate it instead.
+ // If lines haven been inserted/deleted and the buffer has virt_lines,
+ // invalidate the line after the changed lines as some virt_lines may
+ // now be drawn above a different line.
+ if (i == 0 || wp->w_lines[i].wl_lnum < lnume
+ || (xtra != 0 && wp->w_lines[i].wl_lnum == lnume
+ && buf_meta_total(wp->w_buffer, kMTMetaLines) > 0)) {
+ // line included in change
+ wp->w_lines[i].wl_valid = false;
+ } else if (xtra != 0) {
+ // line below change
+ wp->w_lines[i].wl_lnum += xtra;
+ wp->w_lines[i].wl_lastlnum += xtra;
+ }
+ } else if (wp->w_lines[i].wl_lastlnum >= lnum) {
+ // change somewhere inside this range of folded lines,
+ // may need to be redrawn
+ wp->w_lines[i].wl_valid = false;
+ }
+ }
+ }
+}
+
+/// Line changed_lines_invalidate_win(), but for all windows displaying a buffer.
+void changed_lines_invalidate_buf(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnume,
+ linenr_T xtra)
+{
+ FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
+ if (wp->w_buffer == buf) {
+ changed_lines_invalidate_win(wp, lnum, col, lnume, xtra);
+ }
+ }
+}
+
/// Common code for when a change was made.
/// See changed_lines() for the arguments.
/// Careful: may trigger autocommands that reload the buffer.
@@ -185,7 +258,7 @@ static void changed_common(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnum
// Create a new entry if a new undo-able change was started or we
// don't have an entry yet.
if (buf->b_new_change || buf->b_changelistlen == 0) {
- int add;
+ bool add;
if (buf->b_changelistlen == 0) {
add = true;
} else {
@@ -249,10 +322,17 @@ static void changed_common(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnum
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (wp->w_buffer == buf) {
// Mark this window to be redrawn later.
- if (wp->w_redr_type < UPD_VALID) {
+ if (!redraw_not_allowed && wp->w_redr_type < UPD_VALID) {
wp->w_redr_type = UPD_VALID;
}
+ // When inserting/deleting lines and the window has specific lines
+ // to be redrawn, w_redraw_top and w_redraw_bot may now be invalid,
+ // so just redraw everything.
+ if (xtra != 0 && wp->w_redraw_top != 0) {
+ redraw_later(wp, UPD_NOT_VALID);
+ }
+
linenr_T last = lnume + xtra - 1; // last line after the change
// Reset "w_skipcol" if the topline length has become smaller to
@@ -288,55 +368,7 @@ static void changed_common(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnum
wp->w_cline_folded = folded;
}
- // If the changed line is in a range of previously folded lines,
- // compare with the first line in that range.
- if (wp->w_cursor.lnum <= lnum) {
- int i = find_wl_entry(wp, lnum);
- if (i >= 0 && wp->w_cursor.lnum > wp->w_lines[i].wl_lnum) {
- changed_line_abv_curs_win(wp);
- }
- }
-
- if (wp->w_cursor.lnum > lnum) {
- changed_line_abv_curs_win(wp);
- } else if (wp->w_cursor.lnum == lnum && wp->w_cursor.col >= col) {
- changed_cline_bef_curs(wp);
- }
- if (wp->w_botline >= lnum) {
- // Assume that botline doesn't change (inserted lines make
- // other lines scroll down below botline).
- approximate_botline_win(wp);
- }
-
- // Check if any w_lines[] entries have become invalid.
- // For entries below the change: Correct the lnums for
- // inserted/deleted lines. Makes it possible to stop displaying
- // after the change.
- for (int i = 0; i < wp->w_lines_valid; i++) {
- if (wp->w_lines[i].wl_valid) {
- if (wp->w_lines[i].wl_lnum >= lnum) {
- // Do not change wl_lnum at index zero, it is used to
- // compare with w_topline. Invalidate it instead.
- // If the buffer has virt_lines, invalidate the line
- // after the changed lines as the virt_lines for a
- // changed line may become invalid.
- if (i == 0 || wp->w_lines[i].wl_lnum < lnume
- || (wp->w_lines[i].wl_lnum == lnume
- && wp->w_buffer->b_virt_line_blocks > 0)) {
- // line included in change
- wp->w_lines[i].wl_valid = false;
- } else if (xtra != 0) {
- // line below change
- wp->w_lines[i].wl_lnum += xtra;
- wp->w_lines[i].wl_lastlnum += xtra;
- }
- } else if (wp->w_lines[i].wl_lastlnum >= lnum) {
- // change somewhere inside this range of folded lines,
- // may need to be redrawn
- wp->w_lines[i].wl_valid = false;
- }
- }
- }
+ changed_lines_invalidate_win(wp, lnum, col, lnume, xtra);
// Take care of side effects for setting w_topline when folds have
// changed. Esp. when the buffer was changed in another window.
@@ -345,20 +377,19 @@ static void changed_common(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnum
}
// If lines have been added or removed, relative numbering always
- // requires a redraw.
+ // requires an update even if cursor didn't move.
if (wp->w_p_rnu && xtra != 0) {
wp->w_last_cursor_lnum_rnu = 0;
- redraw_later(wp, UPD_VALID);
}
- // Cursor line highlighting probably need to be updated with
- // "UPD_VALID" if it's below the change.
- // If the cursor line is inside the change we need to redraw more.
- if (wp->w_p_cul) {
- if (xtra == 0) {
- redraw_later(wp, UPD_VALID);
- } else if (lnum <= wp->w_last_cursorline) {
- redraw_later(wp, UPD_SOME_VALID);
+ if (wp->w_p_cul && wp->w_last_cursorline >= lnum) {
+ if (wp->w_last_cursorline < lnume) {
+ // If 'cursorline' was inside the change, it has already
+ // been invalidated in w_lines[] by the loop above.
+ wp->w_last_cursorline = 0;
+ } else {
+ // If 'cursorline' was below the change, adjust its lnum.
+ wp->w_last_cursorline += xtra;
}
}
}
@@ -366,9 +397,7 @@ static void changed_common(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnum
// Call update_screen() later, which checks out what needs to be redrawn,
// since it notices b_mod_set and then uses b_mod_*.
- if (must_redraw < UPD_VALID) {
- must_redraw = UPD_VALID;
- }
+ set_must_redraw(UPD_VALID);
// when the cursor line is changed always trigger CursorMoved
if (last_cursormoved_win == curwin && curwin->w_buffer == buf
@@ -481,13 +510,13 @@ void deleted_lines_mark(linenr_T lnum, int count)
}
/// Marks the area to be redrawn after a change.
-/// Consider also calling changed_line_display_buf().
+/// Consider also calling changed_lines_invalidate_buf().
///
/// @param buf the buffer where lines were changed
/// @param lnum first line with change
/// @param lnume line below last changed line
/// @param xtra number of extra lines (negative when deleting)
-void buf_redraw_changed_lines_later(buf_T *buf, linenr_T lnum, linenr_T lnume, linenr_T xtra)
+void changed_lines_redraw_buf(buf_T *buf, linenr_T lnum, linenr_T lnume, linenr_T xtra)
{
if (buf->b_mod_set) {
// find the maximum area that must be redisplayed
@@ -535,7 +564,7 @@ void buf_redraw_changed_lines_later(buf_T *buf, linenr_T lnum, linenr_T lnume, l
void changed_lines(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnume, linenr_T xtra,
bool do_buf_event)
{
- buf_redraw_changed_lines_later(buf, lnum, lnume, xtra);
+ changed_lines_redraw_buf(buf, lnum, lnume, xtra);
if (xtra == 0 && curwin->w_p_diff && curwin->w_buffer == buf && !diff_internal()) {
// When the number of lines doesn't change then mark_adjust() isn't
@@ -548,8 +577,7 @@ void changed_lines(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnume, linen
redraw_later(wp, UPD_VALID);
wlnum = diff_lnum_win(lnum, wp);
if (wlnum > 0) {
- buf_redraw_changed_lines_later(wp->w_buffer, wlnum,
- lnume - lnum + wlnum, 0);
+ changed_lines_redraw_buf(wp->w_buffer, wlnum, lnume - lnum + wlnum, 0);
}
}
}
@@ -568,7 +596,7 @@ void changed_lines(buf_T *buf, linenr_T lnum, colnr_T col, linenr_T lnume, linen
/// When `ff` is true also reset 'fileformat'.
/// When `always_inc_changedtick` is true b:changedtick is incremented even
/// when the changed flag was off.
-void unchanged(buf_T *buf, int ff, bool always_inc_changedtick)
+void unchanged(buf_T *buf, bool ff, bool always_inc_changedtick)
{
if (buf->b_changed || (ff && file_ff_differs(buf, false))) {
buf->b_changed = false;
@@ -923,8 +951,9 @@ int del_bytes(colnr_T count, bool fixpos_arg, bool use_delcombine)
/// Copy the indent from ptr to the current line (and fill to size).
/// Leaves the cursor on the first non-blank in the line.
+///
/// @return true if the line was changed.
-int copy_indent(int size, char *src)
+bool copy_indent(int size, char *src)
{
char *p = NULL;
char *line = NULL;
@@ -1054,7 +1083,7 @@ int copy_indent(int size, char *src)
/// @param dir FORWARD or BACKWARD
///
/// @return true on success, false on failure
-int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
+bool open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
{
char *next_line = NULL; // copy of the next line
char *p_extra = NULL; // what goes to next line
@@ -1075,7 +1104,6 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
char saved_char = NUL; // init for GCC
pos_T *pos;
bool do_si = may_do_si();
- bool do_cindent;
bool no_si = false; // reset did_si afterwards
int first_char = NUL; // init for GCC
int vreplace_mode;
@@ -1142,9 +1170,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// indent to use for the new line.
if (curbuf->b_p_ai || do_si) {
// count white space on current line
- newindent = get_indent_str_vtab(saved_line,
- curbuf->b_p_ts,
- curbuf->b_p_vts_array, false);
+ newindent = indent_size_ts(saved_line, curbuf->b_p_ts, curbuf->b_p_vts_array);
if (newindent == 0 && !(flags & OPENLINE_COM_LIST)) {
newindent = second_line_indent; // for ^^D command in insert mode
}
@@ -1156,10 +1182,8 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// "if (condition) {"
if (!trunc_line && do_si && *saved_line != NUL
&& (p_extra == NULL || first_char != '{')) {
- char *ptr;
-
old_cursor = curwin->w_cursor;
- ptr = saved_line;
+ char *ptr = saved_line;
if (flags & OPENLINE_DO_COM) {
lead_len = get_leader_len(ptr, NULL, false, true);
} else {
@@ -1289,9 +1313,9 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
}
// May do indenting after opening a new line.
- do_cindent = !p_paste && (curbuf->b_p_cin || *curbuf->b_p_inde != NUL)
- && in_cinkeys(dir == FORWARD ? KEY_OPEN_FORW : KEY_OPEN_BACK,
- ' ', linewhite(curwin->w_cursor.lnum));
+ bool do_cindent = !p_paste && (curbuf->b_p_cin || *curbuf->b_p_inde != NUL)
+ && in_cinkeys(dir == FORWARD ? KEY_OPEN_FORW : KEY_OPEN_BACK,
+ ' ', linewhite(curwin->w_cursor.lnum));
// Find out if the current line starts with a comment leader.
// This may then be inserted in front of the new line.
@@ -1322,8 +1346,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
char lead_end[COM_MAX_LEN]; // end-comment string
char *comment_end = NULL; // where lead_end has been found
int extra_space = false; // append extra space
- int current_flag;
- int require_blank = false; // requires blank after middle
+ bool require_blank = false; // requires blank after middle
char *p2;
// If the comment leader has the start, middle or end flag, it may not
@@ -1334,7 +1357,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
continue;
}
if (*p == COM_START || *p == COM_MIDDLE) {
- current_flag = (unsigned char)(*p);
+ int current_flag = (unsigned char)(*p);
if (*p == COM_START) {
// Doing "O" on a start of comment does not insert leader.
if (dir == BACKWARD) {
@@ -1343,7 +1366,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
}
// find start of middle part
- (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
+ copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
require_blank = false;
}
@@ -1354,7 +1377,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
}
p++;
}
- (void)copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
+ copy_option_part(&p, lead_middle, COM_MAX_LEN, ",");
while (*p && p[-1] != ':') { // find end of end flags
// Check whether we allow automatic ending of comments
@@ -1499,13 +1522,12 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
int repl_size = vim_strnsize(lead_repl, lead_repl_len);
int old_size = 0;
char *endp = p;
- int l;
while (old_size < repl_size && p > leader) {
MB_PTR_BACK(leader, p);
old_size += ptr2cells(p);
}
- l = lead_repl_len - (int)(endp - p);
+ int l = lead_repl_len - (int)(endp - p);
if (l != 0) {
memmove(endp + l, endp,
(size_t)((leader + lead_len) - endp));
@@ -1590,9 +1612,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
// Recompute the indent, it may have changed.
if (curbuf->b_p_ai || do_si) {
- newindent = get_indent_str_vtab(leader,
- curbuf->b_p_ts,
- curbuf->b_p_vts_array, false);
+ newindent = indent_size_ts(leader, curbuf->b_p_ts, curbuf->b_p_vts_array);
}
// Add the indent offset
@@ -1732,7 +1752,7 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
if (curwin->w_cursor.lnum >= Insstart.lnum + vr_lines_changed) {
// In case we NL to a new line, BS to the previous one, and NL
// again, we don't want to save the new line for undo twice.
- (void)u_save_cursor(); // errors are ignored!
+ u_save_cursor(); // errors are ignored!
vr_lines_changed++;
}
ml_replace(curwin->w_cursor.lnum, p_extra, true);
@@ -1755,14 +1775,14 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
}
// Copy the indent
if (curbuf->b_p_ci) {
- (void)copy_indent(newindent, saved_line);
+ copy_indent(newindent, saved_line);
// Set the 'preserveindent' option so that any further screwing
// with the line doesn't entirely destroy our efforts to preserve
// it. It gets restored at the function end.
curbuf->b_p_pi = true;
} else {
- (void)set_indent(newindent, SIN_INSERT|SIN_NOMARK);
+ set_indent(newindent, SIN_INSERT|SIN_NOMARK);
}
less_cols -= curwin->w_cursor.col;
@@ -1840,11 +1860,11 @@ int open_line(int dir, int flags, int second_line_indent, bool *did_do_comment)
curwin->w_cursor.lnum = old_cursor.lnum + 1;
}
if (did_append) {
- changed_lines(curbuf, curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1, true);
// bail out and just get the final length of the line we just manipulated
bcount_t extra = (bcount_t)strlen(ml_get(curwin->w_cursor.lnum));
extmark_splice(curbuf, (int)curwin->w_cursor.lnum - 1, 0,
0, 0, 0, 1, 0, 1 + extra, kExtmarkUndo);
+ changed_lines(curbuf, curwin->w_cursor.lnum, 0, curwin->w_cursor.lnum, 1, true);
}
curbuf_splice_pending--;
@@ -1980,7 +2000,7 @@ void del_lines(linenr_T nlines, bool undo)
int get_leader_len(char *line, char **flags, bool backward, bool include_space)
{
int j;
- int got_com = false;
+ bool got_com = false;
char part_buf[COM_MAX_LEN]; // buffer for one option part
char *string; // pointer to comment string
int middle_match_len = 0;
@@ -1995,7 +2015,7 @@ int get_leader_len(char *line, char **flags, bool backward, bool include_space)
// Repeat to match several nested comment strings.
while (line[i] != NUL) {
// scan through the 'comments' option for a match
- int found_one = false;
+ bool found_one = false;
for (char *list = curbuf->b_p_com; *list;) {
// Get one option part into part_buf[]. Advance "list" to next
// one. Put "string" at start of string.
@@ -2003,7 +2023,7 @@ int get_leader_len(char *line, char **flags, bool backward, bool include_space)
*flags = list; // remember where flags started
}
char *prev_list = list;
- (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
+ copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
string = vim_strchr(part_buf, ':');
if (string == NULL) { // missing ':', ignore this part
continue;
@@ -2122,24 +2142,22 @@ int get_last_leader_offset(char *line, char **flags)
int result = -1;
int j;
int lower_check_bound = 0;
- char *string;
char *com_leader;
char *com_flags;
- char *list;
char part_buf[COM_MAX_LEN]; // buffer for one option part
// Repeat to match several nested comment strings.
int i = (int)strlen(line);
while (--i >= lower_check_bound) {
// scan through the 'comments' option for a match
- int found_one = false;
- for (list = curbuf->b_p_com; *list;) {
+ bool found_one = false;
+ for (char *list = curbuf->b_p_com; *list;) {
char *flags_save = list;
// Get one option part into part_buf[]. Advance list to next one.
// put string at start of string.
- (void)copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
- string = vim_strchr(part_buf, ':');
+ copy_option_part(&list, part_buf, COM_MAX_LEN, ",");
+ char *string = vim_strchr(part_buf, ':');
if (string == NULL) { // If everything is fine, this cannot actually
// happen.
continue;
@@ -2217,14 +2235,14 @@ int get_last_leader_offset(char *line, char **flags)
}
int len1 = (int)strlen(com_leader);
- for (list = curbuf->b_p_com; *list;) {
+ for (char *list = curbuf->b_p_com; *list;) {
char *flags_save = list;
- (void)copy_option_part(&list, part_buf2, COM_MAX_LEN, ",");
+ copy_option_part(&list, part_buf2, COM_MAX_LEN, ",");
if (flags_save == com_flags) {
continue;
}
- string = vim_strchr(part_buf2, ':');
+ char *string = vim_strchr(part_buf2, ':');
string++;
while (ascii_iswhite(*string)) {
string++;
diff --git a/src/nvim/change.h b/src/nvim/change.h
index 06155b6da6..bd1094d57e 100644
--- a/src/nvim/change.h
+++ b/src/nvim/change.h
@@ -1,7 +1,9 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
+#include <stddef.h> // IWYU pragma: keep
+
#include "nvim/pos_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
/// flags for open_line()
enum {
diff --git a/src/nvim/channel.c b/src/nvim/channel.c
index e8fe80a3b6..ebeaffe5a1 100644
--- a/src/nvim/channel.c
+++ b/src/nvim/channel.c
@@ -10,16 +10,21 @@
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/channel.h"
#include "nvim/eval.h"
#include "nvim/eval/encode.h"
#include "nvim/eval/typval.h"
+#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
+#include "nvim/event/process.h"
#include "nvim/event/rstream.h"
#include "nvim/event/socket.h"
+#include "nvim/event/stream.h"
#include "nvim/event/wstream.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
@@ -28,10 +33,14 @@
#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/server.h"
+#include "nvim/os/fs.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/shell.h"
#include "nvim/path.h"
#include "nvim/rbuffer.h"
+#include "nvim/rbuffer_defs.h"
+#include "nvim/terminal.h"
+#include "nvim/types_defs.h"
#ifdef MSWIN
# include "nvim/os/fs.h"
@@ -53,12 +62,24 @@ static uint64_t next_chan_id = CHAN_STDERR + 1;
/// Teardown the module
void channel_teardown(void)
{
- Channel *channel;
+ Channel *chan;
+ map_foreach_value(&channels, chan, {
+ channel_close(chan->id, kChannelPartAll, NULL);
+ });
+}
- map_foreach_value(&channels, channel, {
- channel_close(channel->id, kChannelPartAll, NULL);
+#ifdef EXITFREE
+void channel_free_all_mem(void)
+{
+ Channel *chan;
+ map_foreach_value(&channels, chan, {
+ channel_destroy(chan);
});
+ map_destroy(uint64_t, &channels);
+
+ callback_free(&on_print);
}
+#endif
/// Closes a channel
///
@@ -217,16 +238,17 @@ void channel_create_event(Channel *chan, const char *ext_source)
}
assert(chan->id <= VARNUMBER_MAX);
- Dictionary info = channel_info(chan->id);
+ Arena arena = ARENA_EMPTY;
+ Dictionary info = channel_info(chan->id, &arena);
typval_T tv = TV_INITIAL_VALUE;
// TODO(bfredl): do the conversion in one step. Also would be nice
// to pretty print top level dict in defined order
- (void)object_to_vim(DICTIONARY_OBJ(info), &tv, NULL);
+ object_to_vim(DICTIONARY_OBJ(info), &tv, NULL);
assert(tv.v_type == VAR_DICT);
char *str = encode_tv2json(&tv, NULL);
ILOG("new channel %" PRIu64 " (%s) : %s", chan->id, source, str);
xfree(str);
- api_free_dictionary(info);
+ arena_mem_free(arena_finish(&arena));
#else
(void)ext_source;
@@ -244,7 +266,7 @@ void channel_decref(Channel *chan)
{
if (!(--chan->refcount)) {
// delay free, so that libuv is done with the handles
- multiqueue_put(main_loop.events, free_channel_event, 1, chan);
+ multiqueue_put(main_loop.events, free_channel_event, chan);
}
}
@@ -260,9 +282,8 @@ void callback_reader_start(CallbackReader *reader, const char *type)
reader->type = type;
}
-static void free_channel_event(void **argv)
+static void channel_destroy(Channel *chan)
{
- Channel *chan = argv[0];
if (chan->is_rpc) {
rpc_free(chan);
}
@@ -275,11 +296,17 @@ 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, NULL);
multiqueue_free(chan->events);
xfree(chan);
}
+static void free_channel_event(void **argv)
+{
+ Channel *chan = argv[0];
+ pmap_del(uint64_t)(&channels, chan->id, NULL);
+ channel_destroy(chan);
+}
+
static void channel_destroy_early(Channel *chan)
{
if ((chan->id != --next_chan_id)) {
@@ -293,7 +320,7 @@ static void channel_destroy_early(Channel *chan)
}
// uv will keep a reference to handles until next loop tick, so delay free
- multiqueue_put(main_loop.events, free_channel_event, 1, chan);
+ multiqueue_put(main_loop.events, free_channel_event, chan);
}
static void close_cb(Stream *stream, void *data)
@@ -553,7 +580,10 @@ size_t channel_send(uint64_t id, char *data, size_t len, bool data_owned, const
goto retfree;
}
// unbuffered write
- written = len * fwrite(data, len, 1, stderr);
+ ptrdiff_t wres = os_write(STDERR_FILENO, data, len, false);
+ if (wres >= 0) {
+ written = (size_t)wres;
+ }
goto retfree;
}
@@ -657,7 +687,7 @@ static void schedule_channel_event(Channel *chan)
{
if (!chan->callback_scheduled) {
if (!chan->callback_busy) {
- multiqueue_put(chan->events, on_channel_event, 1, chan);
+ multiqueue_put(chan->events, on_channel_event, chan);
channel_incref(chan);
}
chan->callback_scheduled = true;
@@ -682,7 +712,7 @@ static void on_channel_event(void **args)
chan->callback_busy = false;
if (chan->callback_scheduled) {
// further callback was deferred to avoid recursion.
- multiqueue_put(chan->events, on_channel_event, 1, chan);
+ multiqueue_put(chan->events, on_channel_event, chan);
channel_incref(chan);
}
@@ -777,19 +807,21 @@ static void channel_callback_call(Channel *chan, CallbackReader *reader)
/// and `buf` is assumed to be a new, unmodified buffer.
void channel_terminal_open(buf_T *buf, Channel *chan)
{
- TerminalOptions topts;
- topts.data = chan;
- topts.width = chan->stream.pty.width;
- topts.height = chan->stream.pty.height;
- topts.write_cb = term_write;
- topts.resize_cb = term_resize;
- topts.close_cb = term_close;
+ TerminalOptions topts = {
+ .data = chan,
+ .width = chan->stream.pty.width,
+ .height = chan->stream.pty.height,
+ .write_cb = term_write,
+ .resize_cb = term_resize,
+ .close_cb = term_close,
+ .force_crlf = false,
+ };
buf->b_p_channel = (OptInt)chan->id; // 'channel' option
channel_incref(chan);
terminal_open(&chan->term, buf, topts);
}
-static void term_write(char *buf, size_t size, void *data)
+static void term_write(const char *buf, size_t size, void *data)
{
Channel *chan = data;
if (chan->stream.proc.in.closed) {
@@ -812,7 +844,7 @@ static inline void term_delayed_free(void **argv)
{
Channel *chan = argv[0];
if (chan->stream.proc.in.pending_reqs || chan->stream.proc.out.pending_reqs) {
- multiqueue_put(chan->events, term_delayed_free, 1, chan);
+ multiqueue_put(chan->events, term_delayed_free, chan);
return;
}
@@ -826,7 +858,7 @@ static void term_close(void *data)
{
Channel *chan = data;
process_stop(&chan->stream.proc);
- multiqueue_put(chan->events, term_delayed_free, 1, data);
+ multiqueue_put(chan->events, term_delayed_free, data);
}
void channel_info_changed(Channel *chan, bool new_chan)
@@ -834,7 +866,7 @@ void channel_info_changed(Channel *chan, bool new_chan)
event_T event = new_chan ? EVENT_CHANOPEN : EVENT_CHANINFO;
if (has_event(event)) {
channel_incref(chan);
- multiqueue_put(main_loop.events, set_info_event, 2, chan, event);
+ multiqueue_put(main_loop.events, set_info_event, chan, (void *)(intptr_t)event);
}
}
@@ -845,9 +877,10 @@ static void set_info_event(void **argv)
save_v_event_T save_v_event;
dict_T *dict = get_v_event(&save_v_event);
- Dictionary info = channel_info(chan->id);
+ Arena arena = ARENA_EMPTY;
+ Dictionary info = channel_info(chan->id, &arena);
typval_T retval;
- (void)object_to_vim(DICTIONARY_OBJ(info), &retval, NULL);
+ object_to_vim(DICTIONARY_OBJ(info), &retval, NULL);
assert(retval.v_type == VAR_DICT);
tv_dict_add_dict(dict, S_LEN("info"), retval.vval.v_dict);
tv_dict_set_keys_readonly(dict);
@@ -855,7 +888,7 @@ static void set_info_event(void **argv)
apply_autocmds(event, NULL, NULL, false, curbuf);
restore_v_event(dict, &save_v_event);
- api_free_dictionary(info);
+ arena_mem_free(arena_finish(&arena));
channel_decref(chan);
}
@@ -867,15 +900,15 @@ bool channel_job_running(uint64_t id)
&& !process_is_stopped(&chan->stream.proc));
}
-Dictionary channel_info(uint64_t id)
+Dictionary channel_info(uint64_t id, Arena *arena)
{
Channel *chan = find_channel(id);
if (!chan) {
return (Dictionary)ARRAY_DICT_INIT;
}
- Dictionary info = ARRAY_DICT_INIT;
- PUT(info, "id", INTEGER_OBJ((Integer)chan->id));
+ Dictionary info = arena_dict(arena, 8);
+ PUT_C(info, "id", INTEGER_OBJ((Integer)chan->id));
const char *stream_desc, *mode_desc;
switch (chan->streamtype) {
@@ -883,18 +916,20 @@ 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", CSTR_TO_OBJ(name));
+ PUT_C(info, "pty", CSTR_TO_ARENA_OBJ(arena, name));
}
- char **p = chan->stream.proc.argv;
+ char **args = chan->stream.proc.argv;
Array argv = ARRAY_DICT_INIT;
- if (p != NULL) {
- while (*p != NULL) {
- ADD(argv, CSTR_TO_OBJ(*p));
- p++;
+ if (args != NULL) {
+ size_t n;
+ for (n = 0; args[n] != NULL; n++) {}
+ argv = arena_array(arena, n);
+ for (size_t i = 0; i < n; i++) {
+ ADD_C(argv, CSTR_AS_OBJ(args[i]));
}
}
- PUT(info, "argv", ARRAY_OBJ(argv));
+ PUT_C(info, "argv", ARRAY_OBJ(argv));
break;
}
@@ -907,51 +942,51 @@ Dictionary channel_info(uint64_t id)
break;
case kChannelStreamInternal:
- PUT(info, "internal", BOOLEAN_OBJ(true));
+ PUT_C(info, "internal", BOOLEAN_OBJ(true));
FALLTHROUGH;
case kChannelStreamSocket:
stream_desc = "socket";
break;
}
- PUT(info, "stream", CSTR_TO_OBJ(stream_desc));
+ PUT_C(info, "stream", CSTR_AS_OBJ(stream_desc));
if (chan->is_rpc) {
mode_desc = "rpc";
- PUT(info, "client", DICTIONARY_OBJ(rpc_client_info(chan)));
+ PUT_C(info, "client", DICTIONARY_OBJ(chan->rpc.info));
} else if (chan->term) {
mode_desc = "terminal";
- PUT(info, "buffer", BUFFER_OBJ(terminal_buf(chan->term)));
+ PUT_C(info, "buffer", BUFFER_OBJ(terminal_buf(chan->term)));
} else {
mode_desc = "bytes";
}
- PUT(info, "mode", CSTR_TO_OBJ(mode_desc));
+ PUT_C(info, "mode", CSTR_AS_OBJ(mode_desc));
return info;
}
/// Simple int64_t comparison function for use with qsort()
-static int int64_t_cmp(const void *a, const void *b)
+static int int64_t_cmp(const void *pa, const void *pb)
{
- int64_t diff = *(int64_t *)a - *(int64_t *)b;
- return (diff < 0) ? -1 : (diff > 0);
+ const int64_t a = *(const int64_t *)pa;
+ const int64_t b = *(const int64_t *)pb;
+ return a == b ? 0 : a > b ? 1 : -1;
}
-Array channel_all_info(void)
+Array channel_all_info(Arena *arena)
{
// order the items in the array by channel number, for Determinismâ„¢
kvec_t(int64_t) ids = KV_INITIAL_VALUE;
- kv_resize(ids, map_size(&channels));
+ kv_fixsize_arena(arena, ids, map_size(&channels));
uint64_t id;
map_foreach_key(&channels, id, {
kv_push(ids, (int64_t)id);
});
qsort(ids.items, ids.size, sizeof ids.items[0], int64_t_cmp);
- Array ret = ARRAY_DICT_INIT;
+ Array ret = arena_array(arena, ids.size);
for (size_t i = 0; i < ids.size; i++) {
- ADD(ret, DICTIONARY_OBJ(channel_info((uint64_t)ids.items[i])));
+ ADD_C(ret, DICTIONARY_OBJ(channel_info((uint64_t)ids.items[i], arena)));
}
- kv_destroy(ids);
return ret;
}
diff --git a/src/nvim/channel.h b/src/nvim/channel.h
index 5c9d708ac2..35d369e513 100644
--- a/src/nvim/channel.h
+++ b/src/nvim/channel.h
@@ -4,75 +4,17 @@
#include <stdint.h>
#include <stdlib.h>
+#include "nvim/channel_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h"
+#include "nvim/event/defs.h"
#include "nvim/event/libuv_process.h"
-#include "nvim/event/multiqueue.h"
-#include "nvim/event/process.h"
-#include "nvim/event/socket.h"
-#include "nvim/event/stream.h"
-#include "nvim/garray_defs.h"
+#include "nvim/func_attr.h"
#include "nvim/macros_defs.h"
-#include "nvim/main.h"
#include "nvim/map_defs.h"
#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/os/pty_process.h"
-#include "nvim/terminal.h"
#include "nvim/types_defs.h"
-#define CHAN_STDIO 1
-#define CHAN_STDERR 2
-
-typedef enum {
- kChannelStreamProc,
- kChannelStreamSocket,
- kChannelStreamStdio,
- kChannelStreamStderr,
- kChannelStreamInternal,
-} ChannelStreamType;
-
-typedef enum {
- kChannelPartStdin,
- kChannelPartStdout,
- kChannelPartStderr,
- kChannelPartRpc,
- kChannelPartAll,
-} ChannelPart;
-
-typedef enum {
- kChannelStdinPipe,
- kChannelStdinNull,
-} ChannelStdinMode;
-
-typedef struct {
- Stream in;
- Stream out;
-} StdioPair;
-
-typedef struct {
- bool closed;
-} StderrState;
-
-typedef struct {
- LuaRef cb;
- bool closed;
-} InternalState;
-
-typedef struct {
- Callback cb;
- dict_T *self;
- garray_T buffer;
- bool eof;
- bool buffered;
- bool fwd_err;
- const char *type;
-} CallbackReader;
-
-#define CALLBACK_READER_INIT ((CallbackReader){ .cb = CALLBACK_NONE, \
- .self = NULL, \
- .buffer = GA_EMPTY_INIT_VALUE, \
- .buffered = false, \
- .fwd_err = false, \
- .type = NULL })
static inline bool callback_reader_set(CallbackReader reader)
{
return reader.cb.type != kCallbackNone || reader.self;
@@ -122,7 +64,9 @@ static inline Channel *find_channel(uint64_t id)
}
static inline Stream *channel_instream(Channel *chan)
- FUNC_ATTR_NONNULL_ALL
+ REAL_FATTR_NONNULL_ALL;
+
+static inline Stream *channel_instream(Channel *chan)
{
switch (chan->streamtype) {
case kChannelStreamProc:
@@ -142,7 +86,9 @@ static inline Stream *channel_instream(Channel *chan)
}
static inline Stream *channel_outstream(Channel *chan)
- FUNC_ATTR_NONNULL_ALL
+ REAL_FATTR_NONNULL_ALL;
+
+static inline Stream *channel_outstream(Channel *chan)
{
switch (chan->streamtype) {
case kChannelStreamProc:
diff --git a/src/nvim/channel_defs.h b/src/nvim/channel_defs.h
new file mode 100644
index 0000000000..d4f1895420
--- /dev/null
+++ b/src/nvim/channel_defs.h
@@ -0,0 +1,61 @@
+#pragma once
+#include <stdbool.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "nvim/event/defs.h"
+
+#define CHAN_STDIO 1
+#define CHAN_STDERR 2
+
+typedef enum {
+ kChannelStreamProc,
+ kChannelStreamSocket,
+ kChannelStreamStdio,
+ kChannelStreamStderr,
+ kChannelStreamInternal,
+} ChannelStreamType;
+
+typedef enum {
+ kChannelPartStdin,
+ kChannelPartStdout,
+ kChannelPartStderr,
+ kChannelPartRpc,
+ kChannelPartAll,
+} ChannelPart;
+
+typedef enum {
+ kChannelStdinPipe,
+ kChannelStdinNull,
+} ChannelStdinMode;
+
+typedef struct {
+ Stream in;
+ Stream out;
+} StdioPair;
+
+typedef struct {
+ bool closed;
+} StderrState;
+
+typedef struct {
+ LuaRef cb;
+ bool closed;
+} InternalState;
+
+typedef struct {
+ Callback cb;
+ dict_T *self;
+ garray_T buffer;
+ bool eof;
+ bool buffered;
+ bool fwd_err;
+ const char *type;
+} CallbackReader;
+
+#define CALLBACK_READER_INIT ((CallbackReader){ .cb = CALLBACK_NONE, \
+ .self = NULL, \
+ .buffer = GA_EMPTY_INIT_VALUE, \
+ .buffered = false, \
+ .fwd_err = false, \
+ .type = NULL })
diff --git a/src/nvim/charset.c b/src/nvim/charset.c
index 48a9808b31..20bd364c7e 100644
--- a/src/nvim/charset.c
+++ b/src/nvim/charset.c
@@ -8,7 +8,7 @@
#include <limits.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include "auto/config.h"
#include "klib/kvec.h"
@@ -18,6 +18,7 @@
#include "nvim/cursor.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/globals.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
@@ -27,6 +28,7 @@
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -84,7 +86,7 @@ int init_chartab(void)
///
/// @return FAIL if 'iskeyword', 'isident', 'isfname' or 'isprint' option has
/// an error, OK otherwise.
-int buf_init_chartab(buf_T *buf, int global)
+int buf_init_chartab(buf_T *buf, bool global)
{
int c;
@@ -489,7 +491,7 @@ char *str_foldcase(char *str, int orglen, char *buf, int buflen)
}
}
}
- (void)utf_char2bytes(lc, STR_PTR(i));
+ utf_char2bytes(lc, STR_PTR(i));
}
// skip to next multi-byte char
@@ -847,11 +849,11 @@ bool vim_isfilec(int c)
}
/// Check if "c" is a valid file-name character, including characters left
-/// out of 'isfname' to make "gf" work, such as comma, space, '@', etc.
+/// out of 'isfname' to make "gf" work, such as ',', ' ', '@', ':', etc.
bool vim_is_fname_char(int c)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- return vim_isfilec(c) || c == ',' || c == ' ' || c == '@';
+ return vim_isfilec(c) || c == ',' || c == ' ' || c == '@' || c == ':';
}
/// Check that "c" is a valid file-name character or a wildcard character
@@ -1445,9 +1447,9 @@ bool rem_backslash(const char *str)
&& str[1] != '?'
&& !vim_isfilec((uint8_t)str[1])));
-#else // ifdef BACKSLASH_IN_FILENAME
+#else
return str[0] == '\\' && str[1] != NUL;
-#endif // ifdef BACKSLASH_IN_FILENAME
+#endif
}
/// Halve the number of backslashes in a file name argument.
diff --git a/src/nvim/charset.h b/src/nvim/charset.h
index cfab0f8517..62a38660a8 100644
--- a/src/nvim/charset.h
+++ b/src/nvim/charset.h
@@ -3,12 +3,9 @@
#include <stdbool.h>
#include <stdint.h>
-#include "nvim/buffer_defs.h"
-#include "nvim/eval/typval_defs.h"
-#include "nvim/option_defs.h"
+#include "nvim/func_attr.h"
#include "nvim/option_vars.h"
-#include "nvim/pos_defs.h"
-#include "nvim/strings.h"
+#include "nvim/strings.h" // IWYU pragma: keep
/// Return the folded-case equivalent of the given character
///
diff --git a/src/nvim/cmdexpand.c b/src/nvim/cmdexpand.c
index 367b86ec55..f172646edf 100644
--- a/src/nvim/cmdexpand.c
+++ b/src/nvim/cmdexpand.c
@@ -6,7 +6,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
@@ -14,6 +14,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
#include "nvim/cmdhist.h"
@@ -24,18 +25,20 @@
#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
#include "nvim/ex_cmds.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/help.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/keycodes.h"
#include "nvim/log.h"
@@ -43,6 +46,7 @@
#include "nvim/macros_defs.h"
#include "nvim/mapping.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memory.h"
#include "nvim/menu.h"
#include "nvim/message.h"
@@ -51,11 +55,13 @@
#include "nvim/os/fs.h"
#include "nvim/os/lang.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/popupmenu.h"
#include "nvim/profile.h"
#include "nvim/regexp.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/search.h"
#include "nvim/sign.h"
#include "nvim/statusline.h"
@@ -64,6 +70,7 @@
#include "nvim/tag.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/usercmd.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -75,7 +82,7 @@ typedef void *(*user_expand_func_T)(const char *, int, typval_T *);
# include "cmdexpand.c.generated.h"
#endif
-static int cmd_showtail; ///< Only show path tail in lists ?
+static bool cmd_showtail; ///< Only show path tail in lists ?
/// "compl_match_array" points the currently displayed list of entries in the
/// popup menu. It is NULL when there is no popup menu.
@@ -101,6 +108,7 @@ static bool cmdline_fuzzy_completion_supported(const expand_T *const xp)
&& xp->xp_context != EXPAND_FILES_IN_PATH
&& xp->xp_context != EXPAND_FILETYPE
&& xp->xp_context != EXPAND_HELP
+ && xp->xp_context != EXPAND_KEYMAP
&& xp->xp_context != EXPAND_LUA
&& xp->xp_context != EXPAND_OLD_SETTING
&& xp->xp_context != EXPAND_STRING_SETTING
@@ -327,7 +335,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
beep_flush();
} else if (xp->xp_numfiles == 1) {
// free expanded pattern
- (void)ExpandOne(xp, NULL, NULL, 0, WILD_FREE);
+ ExpandOne(xp, NULL, NULL, 0, WILD_FREE);
}
return OK;
@@ -336,7 +344,7 @@ int nextwild(expand_T *xp, int type, int options, bool escape)
/// Create and display a cmdline completion popup menu with items from
/// "matches".
static int cmdline_pum_create(CmdlineInfo *ccline, expand_T *xp, char **matches, int numMatches,
- int showtail)
+ bool showtail)
{
assert(numMatches >= 0);
// Add all the completion matches
@@ -443,7 +451,7 @@ static int wildmenu_match_len(expand_T *xp, char *s)
/// If inversion is possible we use it. Else '=' characters are used.
///
/// @param matches list of matches
-static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int match, int showtail)
+static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int match, bool showtail)
{
int len;
int clen; // length in screen cells
@@ -509,7 +517,7 @@ static void redraw_wildmenu(expand_T *xp, int num_matches, char **matches, int m
}
}
- int fillchar = fillchar_status(&attr, curwin);
+ schar_T fillchar = fillchar_status(&attr, curwin);
if (first_match == 0) {
*buf = NUL;
@@ -842,7 +850,7 @@ static char *find_longest_match(expand_T *xp, int options)
char *ExpandOne(expand_T *xp, char *str, char *orig, int options, int mode)
{
char *ss = NULL;
- int orig_saved = false;
+ bool orig_saved = false;
// first handle the case of using an old match
if (mode == WILD_NEXT || mode == WILD_PREV
@@ -966,7 +974,7 @@ void ExpandCleanup(expand_T *xp)
/// @param showtail display only the tail of the full path of a file name
/// @param dir_attr highlight attribute to use for directory names
static void showmatches_oneline(expand_T *xp, char **matches, int numMatches, int lines, int linenr,
- int maxlen, int showtail, int dir_attr)
+ int maxlen, bool showtail, int dir_attr)
{
char *p;
int lastlen = 999;
@@ -1025,7 +1033,7 @@ static void showmatches_oneline(expand_T *xp, char **matches, int numMatches, in
/// Show all matches for completion on the command line.
/// Returns EXPAND_NOTHING when the character that triggered expansion should
/// be inserted like a normal character.
-int showmatches(expand_T *xp, int wildmenu)
+int showmatches(expand_T *xp, bool wildmenu)
{
CmdlineInfo *const ccline = get_cmdline_info();
int numMatches;
@@ -1034,8 +1042,7 @@ int showmatches(expand_T *xp, int wildmenu)
int maxlen;
int lines;
int columns;
- int attr;
- int showtail;
+ bool showtail;
if (xp->xp_numfiles == -1) {
set_expand_context(xp);
@@ -1104,7 +1111,7 @@ int showmatches(expand_T *xp, int wildmenu)
lines = (numMatches + columns - 1) / columns;
}
- attr = HL_ATTR(HLF_D); // find out highlighting for directories
+ int attr = HL_ATTR(HLF_D); // find out highlighting for directories
if (xp->xp_context == EXPAND_TAGS_LISTFILES) {
msg_puts_attr(_("tagname"), HL_ATTR(HLF_T));
@@ -1218,6 +1225,7 @@ char *addstar(char *fname, size_t len, int context)
|| context == EXPAND_COMPILER
|| context == EXPAND_OWNSYNTAX
|| context == EXPAND_FILETYPE
+ || context == EXPAND_KEYMAP
|| context == EXPAND_PACKADD
|| context == EXPAND_RUNTIME
|| ((context == EXPAND_TAGS_LISTFILES || context == EXPAND_TAGS)
@@ -2583,7 +2591,7 @@ static char *get_healthcheck_names(expand_T *xp FUNC_ATTR_UNUSED, int idx)
if (last_gen != get_cmdline_last_prompt_id() || last_gen == 0) {
Array a = ARRAY_DICT_INIT;
Error err = ERROR_INIT;
- Object res = nlua_exec(STATIC_CSTR_AS_STRING("return vim.health._complete()"), a, &err);
+ Object res = NLUA_EXEC_STATIC("return vim.health._complete()", a, kRetObject, NULL, &err);
api_clear_error(&err);
api_free_object(names);
names = res;
@@ -2744,6 +2752,10 @@ static int ExpandFromContext(expand_T *xp, char *pat, char ***matches, int *numM
char *directories[] = { "syntax", "indent", "ftplugin", NULL };
return ExpandRTDir(pat, 0, numMatches, matches, directories);
}
+ if (xp->xp_context == EXPAND_KEYMAP) {
+ char *directories[] = { "keymap", NULL };
+ return ExpandRTDir(pat, 0, numMatches, matches, directories);
+ }
if (xp->xp_context == EXPAND_USER_LIST) {
return ExpandUserList(xp, matches, numMatches);
}
@@ -3242,11 +3254,11 @@ void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dir
copy_option_part(&path, buf, MAXPATHL, ",");
if (strlen(buf) + strlen(file) + 2 < MAXPATHL) {
add_pathsep(buf);
- STRCAT(buf, file); // NOLINT
+ STRCAT(buf, file);
char **p;
int num_p = 0;
- (void)ExpandFromContext(&xpc, buf, &p, &num_p, WILD_SILENT | expand_options);
+ ExpandFromContext(&xpc, buf, &p, &num_p, WILD_SILENT | expand_options);
if (num_p > 0) {
ExpandEscape(&xpc, buf, num_p, p, WILD_SILENT | expand_options);
@@ -3266,7 +3278,7 @@ void globpath(char *path, char *file, garray_T *ga, int expand_options, bool dir
}
/// Translate some keys pressed when 'wildmenu' is used.
-int wildmenu_translate_key(CmdlineInfo *cclp, int key, expand_T *xp, int did_wild_list)
+int wildmenu_translate_key(CmdlineInfo *cclp, int key, expand_T *xp, bool did_wild_list)
{
int c = key;
@@ -3312,7 +3324,7 @@ static int wildmenu_process_key_menunames(CmdlineInfo *cclp, int key, expand_T *
} else if (key == K_UP) {
// Hitting <Up>: Remove one submenu name in front of the
// cursor
- int found = false;
+ bool found = false;
int j = (int)(xp->xp_pattern - cclp->cmdbuff);
int i = 0;
@@ -3368,7 +3380,7 @@ static int wildmenu_process_key_filenames(CmdlineInfo *cclp, int key, expand_T *
KeyTyped = true; // in case the key was mapped
} else if (strncmp(xp->xp_pattern, upseg + 1, 3) == 0 && key == K_DOWN) {
// If in a direct ancestor, strip off one ../ to go down
- int found = false;
+ bool found = false;
int j = cclp->cmdpos;
int i = (int)(xp->xp_pattern - cclp->cmdbuff);
@@ -3389,7 +3401,7 @@ static int wildmenu_process_key_filenames(CmdlineInfo *cclp, int key, expand_T *
}
} else if (key == K_UP) {
// go up a directory
- int found = false;
+ bool found = false;
int j = cclp->cmdpos - 1;
int i = (int)(xp->xp_pattern - cclp->cmdbuff);
diff --git a/src/nvim/cmdexpand.h b/src/nvim/cmdexpand.h
index b0772d26a3..33ff787589 100644
--- a/src/nvim/cmdexpand.h
+++ b/src/nvim/cmdexpand.h
@@ -1,9 +1,10 @@
#pragma once
-#include "nvim/cmdexpand_defs.h" // IWYU pragma: export
+#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
-#include "nvim/ex_getln.h"
+#include "nvim/ex_getln_defs.h" // IWYU pragma: keep
#include "nvim/garray_defs.h" // IWYU pragma: keep
+#include "nvim/regexp_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
// Values for nextwild() and ExpandOne(). See ExpandOne() for meaning.
diff --git a/src/nvim/cmdexpand_defs.h b/src/nvim/cmdexpand_defs.h
index 97307c4e50..c1fb85859c 100644
--- a/src/nvim/cmdexpand_defs.h
+++ b/src/nvim/cmdexpand_defs.h
@@ -4,7 +4,6 @@
#include <stddef.h>
#include "nvim/eval/typval_defs.h"
-#include "nvim/types_defs.h"
typedef enum {
XP_PREFIX_NONE, ///< prefix not used
@@ -15,7 +14,7 @@ typedef enum {
enum { EXPAND_BUF_LEN = 256, };
/// used for completion on the command line
-typedef struct expand {
+typedef struct {
char *xp_pattern; ///< start of item to expand, guaranteed
///< to be part of xp_line
int xp_context; ///< type of expansion
@@ -105,6 +104,7 @@ enum {
EXPAND_STRING_SETTING,
EXPAND_SETTING_SUBTRACT,
EXPAND_ARGOPT,
+ EXPAND_KEYMAP,
EXPAND_CHECKHEALTH,
EXPAND_LUA,
};
diff --git a/src/nvim/cmdhist.c b/src/nvim/cmdhist.c
index 4556b74396..6a9290270a 100644
--- a/src/nvim/cmdhist.c
+++ b/src/nvim/cmdhist.c
@@ -15,14 +15,15 @@
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_getln.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option_vars.h"
+#include "nvim/os/time.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
@@ -374,7 +375,7 @@ static int calc_hist_idx(int histype, int num)
histentry_T *hist = history[histype];
if (num > 0) {
- int wrapped = false;
+ bool wrapped = false;
while (hist[i].hisnum > num) {
if (--i < 0) {
if (wrapped) {
diff --git a/src/nvim/cmdhist.h b/src/nvim/cmdhist.h
index cce0f92898..43be397cee 100644
--- a/src/nvim/cmdhist.h
+++ b/src/nvim/cmdhist.h
@@ -1,10 +1,10 @@
#pragma once
-#include "nvim/cmdexpand_defs.h" // IWYU pragma: export
+#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h"
-#include "nvim/ex_cmds_defs.h" // IWYU pragma: export
-#include "nvim/os/time.h"
-#include "nvim/types_defs.h"
+#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
+#include "nvim/os/time_defs.h"
+#include "nvim/types_defs.h" // IWYU pragma: keep
/// Present history tables
typedef enum {
@@ -17,11 +17,10 @@ typedef enum {
HIST_DEBUG, ///< Debug commands.
} HistoryType;
-/// Number of history tables
-#define HIST_COUNT (HIST_DEBUG + 1)
+enum { HIST_COUNT = HIST_DEBUG + 1, }; ///< Number of history tables
/// History entry definition
-typedef struct hist_entry {
+typedef struct {
int hisnum; ///< Entry identifier number.
char *hisstr; ///< Actual entry, separator char after the NUL.
Timestamp timestamp; ///< Time when entry was added.
diff --git a/src/nvim/context.c b/src/nvim/context.c
index 59309fcf16..95e2618f62 100644
--- a/src/nvim/context.c
+++ b/src/nvim/context.c
@@ -14,13 +14,14 @@
#include "nvim/context.h"
#include "nvim/eval/encode.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
#include "nvim/ex_docmd.h"
-#include "nvim/func_attr.h"
#include "nvim/hashtab.h"
#include "nvim/keycodes.h"
#include "nvim/memory.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/shada.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -139,8 +140,8 @@ bool ctx_restore(Context *ctx, const int flags)
free_ctx = true;
}
- OptVal op_shada = get_option_value("shada", NULL, OPT_GLOBAL, NULL);
- set_option_value("shada", STATIC_CSTR_AS_OPTVAL("!,'100,%"), OPT_GLOBAL);
+ OptVal op_shada = get_option_value(kOptShada, OPT_GLOBAL);
+ set_option_value(kOptShada, STATIC_CSTR_AS_OPTVAL("!,'100,%"), OPT_GLOBAL);
if (flags & kCtxRegs) {
ctx_restore_regs(ctx);
@@ -166,7 +167,7 @@ bool ctx_restore(Context *ctx, const int flags)
ctx_free(ctx);
}
- set_option_value("shada", op_shada, OPT_GLOBAL);
+ set_option_value(kOptShada, op_shada, OPT_GLOBAL);
optval_free(op_shada);
return true;
@@ -295,7 +296,7 @@ static inline void ctx_restore_funcs(Context *ctx)
/// @param[in] sbuf msgpack_sbuffer to convert.
///
/// @return readfile()-style array representation of "sbuf".
-static inline Array sbuf_to_array(msgpack_sbuffer sbuf)
+static inline Array sbuf_to_array(msgpack_sbuffer sbuf, Arena *arena)
{
list_T *const list = tv_list_alloc(kListLenMayKnow);
tv_list_append_string(list, "", 0);
@@ -309,7 +310,7 @@ static inline Array sbuf_to_array(msgpack_sbuffer sbuf)
.vval.v_list = list
};
- Array array = vim_to_object(&list_tv).data.array;
+ Array array = vim_to_object(&list_tv, arena, false).data.array;
tv_clear(&list_tv);
return array;
}
@@ -327,9 +328,7 @@ static inline msgpack_sbuffer array_to_sbuf(Array array, Error *err)
msgpack_sbuffer_init(&sbuf);
typval_T list_tv;
- if (!object_to_vim(ARRAY_OBJ(array), &list_tv, err)) {
- return sbuf;
- }
+ object_to_vim(ARRAY_OBJ(array), &list_tv, err);
assert(list_tv.v_type == VAR_LIST);
if (!encode_vim_list_to_buf(list_tv.vval.v_list, &sbuf.size, &sbuf.data)) {
@@ -347,18 +346,18 @@ static inline msgpack_sbuffer array_to_sbuf(Array array, Error *err)
/// @param[in] ctx Context to convert.
///
/// @return Dictionary representing "ctx".
-Dictionary ctx_to_dict(Context *ctx)
+Dictionary ctx_to_dict(Context *ctx, Arena *arena)
FUNC_ATTR_NONNULL_ALL
{
assert(ctx != NULL);
- Dictionary rv = ARRAY_DICT_INIT;
+ Dictionary rv = arena_dict(arena, 5);
- PUT(rv, "regs", ARRAY_OBJ(sbuf_to_array(ctx->regs)));
- PUT(rv, "jumps", ARRAY_OBJ(sbuf_to_array(ctx->jumps)));
- PUT(rv, "bufs", ARRAY_OBJ(sbuf_to_array(ctx->bufs)));
- PUT(rv, "gvars", ARRAY_OBJ(sbuf_to_array(ctx->gvars)));
- PUT(rv, "funcs", ARRAY_OBJ(copy_array(ctx->funcs, NULL)));
+ PUT_C(rv, "regs", ARRAY_OBJ(sbuf_to_array(ctx->regs, arena)));
+ PUT_C(rv, "jumps", ARRAY_OBJ(sbuf_to_array(ctx->jumps, arena)));
+ PUT_C(rv, "bufs", ARRAY_OBJ(sbuf_to_array(ctx->bufs, arena)));
+ PUT_C(rv, "gvars", ARRAY_OBJ(sbuf_to_array(ctx->gvars, arena)));
+ PUT_C(rv, "funcs", ARRAY_OBJ(copy_array(ctx->funcs, arena)));
return rv;
}
diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c
index 1110fe1e64..e93e658f1e 100644
--- a/src/nvim/cursor.c
+++ b/src/nvim/cursor.c
@@ -11,9 +11,9 @@
#include "nvim/drawscreen.h"
#include "nvim/fold.h"
#include "nvim/globals.h"
-#include "nvim/macros_defs.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/move.h"
@@ -22,6 +22,8 @@
#include "nvim/plines.h"
#include "nvim/pos_defs.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
+#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -140,17 +142,18 @@ static int coladvance2(pos_T *pos, bool addspaces, bool finetune, colnr_T wcol_a
}
}
- chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
- while (cts.cts_vcol <= wcol && *cts.cts_ptr != NUL) {
- // Count a tab for what it's worth (if list mode not on)
- csize = win_lbr_chartabsize(&cts, &head);
- MB_PTR_ADV(cts.cts_ptr);
- cts.cts_vcol += csize;
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, curwin, pos->lnum, line);
+ StrCharInfo ci = utf_ptr2StrCharInfo(line);
+ col = 0;
+ while (col <= wcol && *ci.ptr != NUL) {
+ CharSize cs = win_charsize(cstype, col, ci.ptr, ci.chr.value, &csarg);
+ csize = cs.width;
+ head = cs.head;
+ col += cs.width;
+ ci = utfc_next(ci);
}
- col = cts.cts_vcol;
- idx = (int)(cts.cts_ptr - line);
- clear_chartabsize_arg(&cts);
+ idx = (int)(ci.ptr - line);
// Handle all the special cases. The virtual_active() check
// is needed to ensure that a virtual position off the end of
@@ -291,7 +294,7 @@ linenr_T get_cursor_rel_lnum(win_T *wp, linenr_T lnum)
// Loop until we reach to_line, skipping folds.
for (; from_line < to_line; from_line++, retval++) {
// If from_line is in a fold, set it to the last line of that fold.
- (void)hasFoldingWin(wp, from_line, NULL, &from_line, true, NULL);
+ hasFoldingWin(wp, from_line, NULL, &from_line, true, NULL);
}
// If to_line is in a closed fold, the line count is off by +1. Correct it.
diff --git a/src/nvim/cursor.h b/src/nvim/cursor.h
index d50976b598..19107dfec9 100644
--- a/src/nvim/cursor.h
+++ b/src/nvim/cursor.h
@@ -1,7 +1,7 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "cursor.h.generated.h"
diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c
index 5aff3b5598..67bb34d4ea 100644
--- a/src/nvim/cursor_shape.c
+++ b/src/nvim/cursor_shape.c
@@ -8,8 +8,7 @@
#include "nvim/charset.h"
#include "nvim/cursor_shape.h"
#include "nvim/ex_getln.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight_group.h"
#include "nvim/log.h"
@@ -102,16 +101,10 @@ Array mode_style_array(Arena *arena)
/// @returns error message for an illegal option, NULL otherwise.
const char *parse_shape_opt(int what)
{
- char *colonp;
- char *commap;
- char *slashp;
char *p = NULL;
- char *endp;
int idx = 0; // init for GCC
- int all_idx;
int len;
- int i;
- int found_ve = false; // found "ve" flag
+ bool found_ve = false; // found "ve" flag
// First round: check for errors; second round: do it for real.
for (int round = 1; round <= 2; round++) {
@@ -127,8 +120,8 @@ const char *parse_shape_opt(int what)
// Repeat for all comma separated parts.
char *modep = p_guicursor;
while (modep != NULL && *modep != NUL) {
- colonp = vim_strchr(modep, ':');
- commap = vim_strchr(modep, ',');
+ char *colonp = vim_strchr(modep, ':');
+ char *commap = vim_strchr(modep, ',');
if (colonp == NULL || (commap != NULL && commap < colonp)) {
return N_("E545: Missing colon");
@@ -139,7 +132,7 @@ const char *parse_shape_opt(int what)
// Repeat for all modes before the colon.
// For the 'a' mode, we loop to handle all the modes.
- all_idx = -1;
+ int all_idx = -1;
while (modep < colonp || all_idx >= 0) {
if (all_idx < 0) {
// Find the mode
@@ -176,7 +169,7 @@ const char *parse_shape_opt(int what)
for (p = colonp + 1; *p && *p != ',';) {
{
// First handle the ones with a number argument.
- i = (uint8_t)(*p);
+ int i = (uint8_t)(*p);
len = 0;
if (STRNICMP(p, "ver", 3) == 0) {
len = 3;
@@ -222,7 +215,7 @@ const char *parse_shape_opt(int what)
}
p += 5;
} else { // must be a highlight group name then
- endp = vim_strchr(p, '-');
+ char *endp = vim_strchr(p, '-');
if (commap == NULL) { // last part
if (endp == NULL) {
endp = p + strlen(p); // find end of part
@@ -230,7 +223,7 @@ const char *parse_shape_opt(int what)
} else if (endp > commap || endp == NULL) {
endp = commap;
}
- slashp = vim_strchr(p, '/');
+ char *slashp = vim_strchr(p, '/');
if (slashp != NULL && slashp < endp) {
// "group/langmap_group"
i = syn_check_group(p, (size_t)(slashp - p));
diff --git a/src/nvim/cursor_shape.h b/src/nvim/cursor_shape.h
index 4c1d6d4eec..21967a81f4 100644
--- a/src/nvim/cursor_shape.h
+++ b/src/nvim/cursor_shape.h
@@ -38,7 +38,7 @@ typedef enum {
#define SHAPE_MOUSE 1 // used for mouse pointer shape
#define SHAPE_CURSOR 2 // used for text cursor shape
-typedef struct cursor_entry {
+typedef struct {
char *full_name; ///< mode description
CursorShape shape; ///< cursor shape: one of the SHAPE_ defines
int mshape; ///< mouse shape: one of the MSHAPE defines
diff --git a/src/nvim/debugger.c b/src/nvim/debugger.c
index a343c1ad6b..7d87b61ce5 100644
--- a/src/nvim/debugger.c
+++ b/src/nvim/debugger.c
@@ -8,31 +8,37 @@
#include <string.h>
#include "nvim/ascii_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand_defs.h"
#include "nvim/debugger.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/getchar_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/state_defs.h"
+#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
/// batch mode debugging: don't save and restore typeahead.
@@ -284,7 +290,7 @@ void do_debug(char *cmd)
// don't debug this command
n = debug_break_level;
debug_break_level = -1;
- (void)do_cmdline(cmdline, getexline, NULL, DOCMD_VERBOSE|DOCMD_EXCRESET);
+ do_cmdline(cmdline, getexline, NULL, DOCMD_VERBOSE|DOCMD_EXCRESET);
debug_break_level = n;
}
lines_left = Rows - 1;
@@ -407,7 +413,7 @@ static linenr_T debug_breakpoint_lnum;
/// debug_skipped_name is then set to the source name in the breakpoint case. If
/// a skipped command decides itself that a debug prompt should be displayed, it
/// can do so by calling dbg_check_skipped().
-static int debug_skipped;
+static bool debug_skipped;
static char *debug_skipped_name;
/// Go to debug mode when a breakpoint was encountered or "ex_nesting_level" is
@@ -462,7 +468,7 @@ bool dbg_check_skipped(exarg_T *eap)
// Save the value of got_int and reset it. We don't want a previous
// interruption cause flushing the input buffer.
- int prev_got_int = got_int;
+ bool prev_got_int = got_int;
got_int = false;
debug_breakpoint_name = debug_skipped_name;
// eap->skip is true
@@ -787,7 +793,6 @@ static linenr_T debuggy_find(bool file, char *fname, linenr_T after, garray_T *g
struct debuggy *bp;
linenr_T lnum = 0;
char *name = fname;
- int prev_got_int;
// Return quickly when there are no breakpoints.
if (GA_EMPTY(gap)) {
@@ -812,7 +817,7 @@ static linenr_T debuggy_find(bool file, char *fname, linenr_T after, garray_T *g
// Save the value of got_int and reset it. We don't want a
// previous interruption cancel matching, only hitting CTRL-C
// while matching should abort it.
- prev_got_int = got_int;
+ bool prev_got_int = got_int;
got_int = false;
if (vim_regexec_prog(&bp->dbg_prog, false, name, 0)) {
lnum = bp->dbg_lnum;
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index 11204a1b31..51d5d08f78 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -2,18 +2,24 @@
#include <limits.h>
#include <stddef.h>
#include <stdlib.h>
+#include <string.h>
#include "nvim/api/extmark.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/ascii_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
+#include "nvim/change.h"
#include "nvim/decoration.h"
#include "nvim/drawscreen.h"
#include "nvim/extmark.h"
#include "nvim/fold.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
+#include "nvim/marktree.h"
#include "nvim/memory.h"
#include "nvim/move.h"
#include "nvim/option_vars.h"
@@ -82,26 +88,22 @@ void bufhl_add_hl_pos_offset(buf_T *buf, int src_id, int hl_id, lpos_T pos_start
extmark_set(buf, (uint32_t)src_id, NULL,
(int)lnum - 1, hl_start, (int)lnum - 1 + end_off, hl_end,
- decor, MT_FLAG_DECOR_HL, true, false, true, false, NULL);
+ decor, MT_FLAG_DECOR_HL, true, false, true, false, false, NULL);
}
}
-void decor_redraw(buf_T *buf, int row1, int row2, DecorInline decor)
+void decor_redraw(buf_T *buf, int row1, int row2, int col1, DecorInline decor)
{
- if (row2 >= row1) {
- redraw_buf_range_later(buf, row1 + 1, row2 + 1);
- }
-
if (decor.ext) {
DecorVirtText *vt = decor.data.ext.vt;
while (vt) {
- if (vt->flags & kVTIsLines) {
- redraw_buf_line_later(buf, row1 + 1 + ((vt->flags & kVTLinesAbove) ? 0 : 1), true);
- changed_line_display_buf(buf);
- } else {
- if (vt->pos == kVPosInline) {
- changed_line_display_buf(buf);
- }
+ bool below = (vt->flags & kVTIsLines) && !(vt->flags & kVTLinesAbove);
+ linenr_T vt_lnum = row1 + 1 + below;
+ redraw_buf_line_later(buf, vt_lnum, true);
+ if (vt->flags & kVTIsLines || vt->pos == kVPosInline) {
+ // changed_lines_redraw_buf(buf, vt_lnum, vt_lnum + 1, 0);
+ colnr_T vt_col = vt->flags & kVTIsLines ? 0 : col1;
+ changed_lines_invalidate_buf(buf, vt_lnum, vt_col, vt_lnum + 1, 0);
}
vt = vt->next;
}
@@ -119,7 +121,8 @@ void decor_redraw(buf_T *buf, int row1, int row2, DecorInline decor)
void decor_redraw_sh(buf_T *buf, int row1, int row2, DecorSignHighlight sh)
{
- if (sh.hl_id || (sh.flags & (kSHIsSign|kSHSpellOn|kSHSpellOff))) {
+ if (sh.hl_id || (sh.url != NULL)
+ || (sh.flags & (kSHIsSign | kSHSpellOn | kSHSpellOff | kSHConceal))) {
if (row2 >= row1) {
redraw_buf_range_later(buf, row1 + 1, row2 + 1);
}
@@ -158,7 +161,7 @@ DecorSignHighlight decor_sh_from_inline(DecorHighlightInline item)
DecorSignHighlight conv = {
.flags = item.flags,
.priority = item.priority,
- .text.sc[0] = item.conceal_char,
+ .text[0] = item.conceal_char,
.hl_id = item.hl_id,
.number_hl_id = 0,
.line_hl_id = 0,
@@ -172,12 +175,6 @@ DecorSignHighlight decor_sh_from_inline(DecorHighlightInline item)
void buf_put_decor(buf_T *buf, DecorInline decor, int row, int row2)
{
if (decor.ext) {
- DecorVirtText *vt = decor.data.ext.vt;
- while (vt) {
- buf_put_decor_virt(buf, vt);
- vt = vt->next;
- }
-
uint32_t idx = decor.data.ext.sh_idx;
while (idx != DECOR_ID_INVALID) {
DecorSignHighlight *sh = &kv_A(decor_items, idx);
@@ -187,46 +184,25 @@ void buf_put_decor(buf_T *buf, DecorInline decor, int row, int row2)
}
}
-void buf_put_decor_virt(buf_T *buf, DecorVirtText *vt)
-{
- if (vt->flags &kVTIsLines) {
- buf->b_virt_line_blocks++;
- } else {
- if (vt->pos == kVPosInline) {
- buf->b_virt_text_inline++;
- }
- }
- if (vt->next) {
- buf_put_decor_virt(buf, vt->next);
- }
-}
-
static int sign_add_id = 0;
-void buf_put_decor_sh(buf_T *buf, DecorSignHighlight *sh, int row, int row2)
+void buf_put_decor_sh(buf_T *buf, DecorSignHighlight *sh, int row1, int row2)
{
if (sh->flags & kSHIsSign) {
sh->sign_add_id = sign_add_id++;
- buf->b_signs++;
- if (sh->text.ptr) {
- buf->b_signs_with_text++;
- buf_signcols_add_check(buf, row + 1, row2 + 1);
+ if (sh->text[0]) {
+ buf_signcols_count_range(buf, row1, row2, 1, kFalse);
}
}
}
-void buf_decor_remove(buf_T *buf, int row, int row2, DecorInline decor, bool free)
+void buf_decor_remove(buf_T *buf, int row1, int row2, int col1, DecorInline decor, bool free)
{
- decor_redraw(buf, row, row2, decor);
+ decor_redraw(buf, row1, row2, col1, decor);
if (decor.ext) {
- DecorVirtText *vt = decor.data.ext.vt;
- while (vt) {
- buf_remove_decor_virt(buf, vt);
- vt = vt->next;
- }
uint32_t idx = decor.data.ext.sh_idx;
while (idx != DECOR_ID_INVALID) {
DecorSignHighlight *sh = &kv_A(decor_items, idx);
- buf_remove_decor_sh(buf, row, row2, sh);
+ buf_remove_decor_sh(buf, row1, row2, sh);
idx = sh->next;
}
if (free) {
@@ -235,29 +211,15 @@ void buf_decor_remove(buf_T *buf, int row, int row2, DecorInline decor, bool fre
}
}
-void buf_remove_decor_virt(buf_T *buf, DecorVirtText *vt)
-{
- if (vt->flags &kVTIsLines) {
- assert(buf->b_virt_line_blocks > 0);
- buf->b_virt_line_blocks--;
- } else {
- if (vt->pos == kVPosInline) {
- assert(buf->b_virt_text_inline > 0);
- buf->b_virt_text_inline--;
- }
- }
-}
-
-void buf_remove_decor_sh(buf_T *buf, int row, int row2, DecorSignHighlight *sh)
+void buf_remove_decor_sh(buf_T *buf, int row1, int row2, DecorSignHighlight *sh)
{
if (sh->flags & kSHIsSign) {
- assert(buf->b_signs > 0);
- buf->b_signs--;
- if (sh->text.ptr) {
- assert(buf->b_signs_with_text > 0);
- buf->b_signs_with_text--;
- if (row2 >= row) {
- buf_signcols_del_check(buf, row + 1, row2 + 1);
+ if (sh->text[0]) {
+ if (buf_meta_total(buf, kMTMetaSignText)) {
+ buf_signcols_count_range(buf, row1, row2, -1, kFalse);
+ } else {
+ buf->b_signcols.resized = true;
+ buf->b_signcols.max = buf->b_signcols.count[0] = 0;
}
}
}
@@ -295,7 +257,7 @@ void decor_free(DecorInline decor)
}
}
-void decor_free_inner(DecorVirtText *vt, uint32_t first_idx)
+static void decor_free_inner(DecorVirtText *vt, uint32_t first_idx)
{
while (vt) {
if (vt->flags & kVTIsLines) {
@@ -312,12 +274,12 @@ void decor_free_inner(DecorVirtText *vt, uint32_t first_idx)
while (idx != DECOR_ID_INVALID) {
DecorSignHighlight *sh = &kv_A(decor_items, idx);
if (sh->flags & kSHIsSign) {
- xfree(sh->text.ptr);
- }
- if (sh->flags & kSHIsSign) {
xfree(sh->sign_name);
}
sh->flags = 0;
+ if (sh->url != NULL) {
+ XFREE_CLEAR(sh->url);
+ }
if (sh->next == DECOR_ID_INVALID) {
sh->next = decor_freelist;
decor_freelist = first_idx;
@@ -362,8 +324,11 @@ void decor_check_invalid_glyphs(void)
{
for (size_t i = 0; i < kv_size(decor_items); i++) {
DecorSignHighlight *it = &kv_A(decor_items, i);
- if ((it->flags & kSHConceal) && schar_high(it->text.sc[0])) {
- it->text.sc[0] = schar_from_char(schar_get_first_codepoint(it->text.sc[0]));
+ int width = (it->flags & kSHIsSign) ? SIGN_WIDTH : ((it->flags & kSHConceal) ? 1 : 0);
+ for (int j = 0; j < width; j++) {
+ if (schar_high(it->text[j])) {
+ it->text[j] = schar_from_char(schar_get_first_codepoint(it->text[j]));
+ }
}
}
}
@@ -394,10 +359,10 @@ DecorVirtText *decor_find_virttext(buf_T *buf, int row, uint64_t ns_id)
MTKey mark = marktree_itr_current(itr);
if (mark.pos.row < 0 || mark.pos.row > row) {
break;
- } else if (mt_invalid(mark) || !(mark.flags & MT_FLAG_DECOR_EXT)) {
+ } else if (mt_invalid(mark)) {
goto next_mark;
}
- DecorVirtText *decor = mark.decor_data.ext.vt;
+ DecorVirtText *decor = mt_decor_virt(mark);
while (decor && (decor->flags & kVTIsLines)) {
decor = decor->next;
}
@@ -489,18 +454,21 @@ static void decor_range_add_from_inline(DecorState *state, int start_row, int st
if (decor.ext) {
DecorVirtText *vt = decor.data.ext.vt;
while (vt) {
- decor_range_add_virt(state, start_row, start_col, end_row, end_col, vt, owned);
+ decor_range_add_virt(state, start_row, start_col, end_row, end_col, vt, owned,
+ DECOR_PRIORITY_BASE);
vt = vt->next;
}
uint32_t idx = decor.data.ext.sh_idx;
while (idx != DECOR_ID_INVALID) {
DecorSignHighlight *sh = &kv_A(decor_items, idx);
- decor_range_add_sh(state, start_row, start_col, end_row, end_col, sh, owned, ns, mark_id);
+ decor_range_add_sh(state, start_row, start_col, end_row, end_col, sh, owned, ns, mark_id,
+ DECOR_PRIORITY_BASE);
idx = sh->next;
}
} else {
DecorSignHighlight sh = decor_sh_from_inline(decor.data.hl);
- decor_range_add_sh(state, start_row, start_col, end_row, end_col, &sh, owned, ns, mark_id);
+ decor_range_add_sh(state, start_row, start_col, end_row, end_col, &sh, owned, ns, mark_id,
+ DECOR_PRIORITY_BASE);
}
}
@@ -510,7 +478,8 @@ static void decor_range_insert(DecorState *state, DecorRange range)
size_t index;
for (index = kv_size(state->active) - 1; index > 0; index--) {
DecorRange item = kv_A(state->active, index - 1);
- if (item.priority <= range.priority) {
+ if ((item.priority < range.priority)
+ || ((item.priority == range.priority) && (item.subpriority <= range.subpriority))) {
break;
}
kv_A(state->active, index) = kv_A(state->active, index - 1);
@@ -519,7 +488,7 @@ static void decor_range_insert(DecorState *state, DecorRange range)
}
void decor_range_add_virt(DecorState *state, int start_row, int start_col, int end_row, int end_col,
- DecorVirtText *vt, bool owned)
+ DecorVirtText *vt, bool owned, DecorPriority subpriority)
{
bool is_lines = vt->flags & kVTIsLines;
DecorRange range = {
@@ -529,13 +498,15 @@ void decor_range_add_virt(DecorState *state, int start_row, int start_col, int e
.attr_id = 0,
.owned = owned,
.priority = vt->priority,
+ .subpriority = subpriority,
.draw_col = -10,
};
decor_range_insert(state, range);
}
void decor_range_add_sh(DecorState *state, int start_row, int start_col, int end_row, int end_col,
- DecorSignHighlight *sh, bool owned, uint32_t ns, uint32_t mark_id)
+ DecorSignHighlight *sh, bool owned, uint32_t ns, uint32_t mark_id,
+ DecorPriority subpriority)
{
if (sh->flags & kSHIsSign) {
return;
@@ -548,10 +519,12 @@ void decor_range_add_sh(DecorState *state, int start_row, int start_col, int end
.attr_id = 0,
.owned = owned,
.priority = sh->priority,
+ .subpriority = subpriority,
.draw_col = -10,
};
- if (sh->hl_id || (sh->flags & (kSHConceal | kSHSpellOn | kSHSpellOff))) {
+ if (sh->hl_id || (sh->url != NULL)
+ || (sh->flags & (kSHConceal | kSHSpellOn | kSHSpellOff))) {
if (sh->hl_id) {
range.attr_id = syn_id2attr(sh->hl_id);
}
@@ -568,7 +541,7 @@ void decor_range_add_sh(DecorState *state, int start_row, int start_col, int end
}
/// Initialize the draw_col of a newly-added virtual text item.
-static void decor_init_draw_col(int win_col, bool hidden, DecorRange *item)
+void decor_init_draw_col(int win_col, bool hidden, DecorRange *item)
{
DecorVirtText *vt = item->kind == kDecorKindVirtText ? item->data.vt : NULL;
VirtTextPos pos = decor_virt_pos_kind(item);
@@ -609,15 +582,15 @@ int decor_redraw_col(win_T *wp, int col, int win_col, bool hidden, DecorState *s
break;
}
- if (mt_invalid(mark) || mt_end(mark) || !mt_decor_any(mark)) {
+ if (!mt_scoped_in_win(mark, wp)) {
goto next_mark;
}
- MTPos endpos = marktree_get_altpos(buf->b_marktree, mark, NULL);
- if (endpos.row == -1) {
- endpos = mark.pos;
+ if (mt_invalid(mark) || mt_end(mark) || !mt_decor_any(mark)) {
+ goto next_mark;
}
+ MTPos endpos = marktree_get_altpos(buf->b_marktree, mark, NULL);
decor_range_add_from_inline(state, mark.pos.row, mark.pos.col, endpos.row, endpos.col,
mt_decor(mark), false, mark.ns, mark.id);
@@ -661,7 +634,7 @@ next_mark:
if (item.start_row == state->row && item.start_col == col) {
DecorSignHighlight *sh = &item.data.sh;
conceal = 2;
- conceal_char = sh->text.sc[0];
+ conceal_char = sh->text[0];
state->col_until = MIN(state->col_until, item.start_col);
conceal_attr = item.attr_id;
}
@@ -672,6 +645,9 @@ next_mark:
} else if (item.data.sh.flags & kSHSpellOff) {
spell = kFalse;
}
+ if (item.data.sh.url != NULL) {
+ attr = hl_add_url(attr, item.data.sh.url);
+ }
}
if (item.start_row == state->row && item.start_col <= col
&& decor_virt_pos(&item) && item.draw_col == -10) {
@@ -679,9 +655,13 @@ next_mark:
}
if (keep) {
kv_A(state->active, j++) = item;
- } else if (item.owned && item.kind == kDecorKindVirtText) {
- clear_virttext(&item.data.vt->data.virt_text);
- xfree(item.data.vt);
+ } else if (item.owned) {
+ if (item.kind == kDecorKindVirtText) {
+ clear_virttext(&item.data.vt->data.virt_text);
+ xfree(item.data.vt);
+ } else if (item.kind == kDecorKindHighlight) {
+ xfree((void *)item.data.sh.url);
+ }
}
}
kv_size(state->active) = j;
@@ -693,21 +673,29 @@ next_mark:
return attr;
}
-typedef struct {
- DecorSignHighlight *sh;
- uint32_t id;
-} SignItem;
-
int sign_item_cmp(const void *p1, const void *p2)
{
const SignItem *s1 = (SignItem *)p1;
const SignItem *s2 = (SignItem *)p2;
- int n = s2->sh->priority - s1->sh->priority;
- return n ? n : (n = (int)(s2->id - s1->id))
- ? n : (s2->sh->sign_add_id - s1->sh->sign_add_id);
+ if (s1->sh->priority != s2->sh->priority) {
+ return s1->sh->priority < s2->sh->priority ? 1 : -1;
+ }
+
+ if (s1->id != s2->id) {
+ return s1->id < s2->id ? 1 : -1;
+ }
+
+ if (s1->sh->sign_add_id != s2->sh->sign_add_id) {
+ return s1->sh->sign_add_id < s2->sh->sign_add_id ? 1 : -1;
+ }
+
+ return 0;
}
+static const uint32_t sign_filter[4] = {[kMTMetaSignText] = kMTFilterSelect,
+ [kMTMetaSignHL] = kMTFilterSelect };
+
/// Return the sign attributes on the currently refreshed row.
///
/// @param[out] sattrs Output array for sign text and texthl id
@@ -717,35 +705,39 @@ int sign_item_cmp(const void *p1, const void *p2)
void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[], int *line_id,
int *cul_id, int *num_id)
{
- MarkTreeIter itr[1];
- if (!buf->b_signs || !marktree_itr_get_overlap(buf->b_marktree, row, 0, itr)) {
+ if (!buf_has_signs(buf)) {
return;
}
MTPair pair;
int num_text = 0;
+ MarkTreeIter itr[1];
kvec_t(SignItem) signs = KV_INITIAL_VALUE;
// TODO(bfredl): integrate with main decor loop.
+ marktree_itr_get_overlap(buf->b_marktree, row, 0, itr);
while (marktree_itr_step_overlap(buf->b_marktree, itr, &pair)) {
if (!mt_invalid(pair.start) && mt_decor_sign(pair.start)) {
DecorSignHighlight *sh = decor_find_sign(mt_decor(pair.start));
- num_text += (sh->text.ptr != NULL);
+ num_text += (sh->text[0] != NUL);
kv_push(signs, ((SignItem){ sh, pair.start.id }));
}
}
+ marktree_itr_step_out_filter(buf->b_marktree, itr, sign_filter);
+
while (itr->x) {
MTKey mark = marktree_itr_current(itr);
if (mark.pos.row != row) {
break;
}
- if (!mt_end(mark) && !mt_invalid(mark) && mt_decor_sign(mark)) {
+ if (!mt_end(mark) && !mt_invalid(mark) && mt_decor_sign(mark)
+ && mt_scoped_in_win(mark, wp)) {
DecorSignHighlight *sh = decor_find_sign(mt_decor(mark));
- num_text += (sh->text.ptr != NULL);
+ num_text += (sh->text[0] != NUL);
kv_push(signs, ((SignItem){ sh, mark.id }));
}
- marktree_itr_next(buf->b_marktree, itr);
+ marktree_itr_next_filter(buf->b_marktree, itr, row + 1, 0, sign_filter);
}
if (kv_size(signs)) {
@@ -755,8 +747,8 @@ void decor_redraw_signs(win_T *wp, buf_T *buf, int row, SignTextAttrs sattrs[],
for (size_t i = 0; i < kv_size(signs); i++) {
DecorSignHighlight *sh = kv_A(signs, i).sh;
- if (idx >= 0 && sh->text.ptr) {
- sattrs[idx].text = sh->text.ptr;
+ if (idx >= 0 && sh->text[0]) {
+ memcpy(sattrs[idx].text, sh->text, SIGN_WIDTH * sizeof(sattr_T));
sattrs[idx--].hl_id = sh->hl_id;
}
if (*num_id == 0) {
@@ -791,50 +783,74 @@ DecorSignHighlight *decor_find_sign(DecorInline decor)
}
}
-// Increase the signcolumn size and update the sentinel line if necessary for
-// the invalidated range.
-void decor_validate_signcols(buf_T *buf, int max)
+static const uint32_t signtext_filter[4] = {[kMTMetaSignText] = kMTFilterSelect };
+
+/// Count the number of signs in a range after adding/removing a sign, or to
+/// (re-)initialize a range in "b_signcols.count".
+///
+/// @param add 1, -1 or 0 for an added, deleted or initialized range.
+/// @param clear kFalse, kTrue or kNone for an, added/deleted, cleared, or initialized range.
+void buf_signcols_count_range(buf_T *buf, int row1, int row2, int add, TriState clear)
{
- int signcols = 0; // highest value of count
- int currow = buf->b_signcols.invalid_top - 1;
- // TODO(bfredl): only need to use marktree_itr_get_overlap once.
- // then we can process both start and end events and update state for each row
- for (; currow < buf->b_signcols.invalid_bot; currow++) {
- MarkTreeIter itr[1];
- if (!marktree_itr_get_overlap(buf->b_marktree, currow, 0, itr)) {
- continue;
- }
+ if (!buf->b_signcols.autom || !buf_meta_total(buf, kMTMetaSignText)) {
+ return;
+ }
+
+ // Allocate an array of integers holding the number of signs in the range.
+ assert(row2 >= row1);
+ int *count = xcalloc(sizeof(int), (size_t)(row2 + 1 - row1));
+ MarkTreeIter itr[1];
+ MTPair pair = { 0 };
- int count = 0;
- MTPair pair;
- while (marktree_itr_step_overlap(buf->b_marktree, itr, &pair)) {
- if (!mt_invalid(pair.start) && (pair.start.flags & MT_FLAG_DECOR_SIGNTEXT)) {
- count++;
+ // Increment count array for signs that start before "row1" but do overlap the range.
+ marktree_itr_get_overlap(buf->b_marktree, row1, 0, itr);
+ while (marktree_itr_step_overlap(buf->b_marktree, itr, &pair)) {
+ if ((pair.start.flags & MT_FLAG_DECOR_SIGNTEXT) && !mt_invalid(pair.start)) {
+ for (int i = row1; i <= MIN(row2, pair.end_pos.row); i++) {
+ count[i - row1]++;
}
}
+ }
- while (itr->x) {
- MTKey mark = marktree_itr_current(itr);
- if (mark.pos.row != currow) {
- break;
- }
- if (!mt_invalid(mark) && !mt_end(mark) && (mark.flags & MT_FLAG_DECOR_SIGNTEXT)) {
- count++;
+ marktree_itr_step_out_filter(buf->b_marktree, itr, signtext_filter);
+
+ // Continue traversing the marktree until beyond "row2".
+ while (itr->x) {
+ MTKey mark = marktree_itr_current(itr);
+ if (mark.pos.row > row2) {
+ break;
+ }
+ if ((mark.flags & MT_FLAG_DECOR_SIGNTEXT) && !mt_invalid(mark) && !mt_end(mark)) {
+ // Increment count array for the range of a paired sign mark.
+ MTPos end = marktree_get_altpos(buf->b_marktree, mark, NULL);
+ for (int i = mark.pos.row; i <= MIN(row2, end.row); i++) {
+ count[i - row1]++;
}
- marktree_itr_next(buf->b_marktree, itr);
}
- if (count > signcols) {
- if (count >= buf->b_signcols.size) {
- buf->b_signcols.size = count;
- buf->b_signcols.sentinel = currow + 1;
- }
- if (count >= max) {
- return;
+ marktree_itr_next_filter(buf->b_marktree, itr, row2 + 1, 0, signtext_filter);
+ }
+
+ // For each row increment "b_signcols.count" at the number of counted signs,
+ // and decrement at the previous number of signs. These two operations are
+ // split in separate calls if "clear" is not kFalse (surrounding a marktree splice).
+ for (int i = 0; i < row2 + 1 - row1; i++) {
+ int prevwidth = MIN(SIGN_SHOW_MAX, count[i] - add);
+ if (clear != kNone && prevwidth > 0) {
+ buf->b_signcols.count[prevwidth - 1]--;
+ assert(buf->b_signcols.count[prevwidth - 1] >= 0);
+ }
+ int width = MIN(SIGN_SHOW_MAX, count[i]);
+ if (clear != kTrue && width > 0) {
+ buf->b_signcols.count[width - 1]++;
+ if (width > buf->b_signcols.max) {
+ buf->b_signcols.resized = true;
+ buf->b_signcols.max = width;
}
- signcols = count;
}
}
+
+ xfree(count);
}
void decor_redraw_end(DecorState *state)
@@ -861,11 +877,13 @@ bool decor_redraw_eol(win_T *wp, DecorState *state, int *eol_attr, int eol_col)
return has_virt_pos;
}
+static const uint32_t lines_filter[4] = {[kMTMetaLines] = kMTFilterSelect };
+
/// @param has_fold whether line "lnum" has a fold, or kNone when not calculated yet
int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines, TriState has_fold)
{
buf_T *buf = wp->w_buffer;
- if (!buf->b_virt_line_blocks) {
+ if (!buf_meta_total(buf, kMTMetaLines)) {
// Only pay for what you use: in case virt_lines feature is not active
// in a buffer, plines do not need to access the marktree at all
return 0;
@@ -884,39 +902,43 @@ int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines, TriState has_fo
return 0;
}
- int virt_lines = 0;
MarkTreeIter itr[1] = { 0 };
- marktree_itr_get(buf->b_marktree, start_row, 0, itr);
+ if (!marktree_itr_get_filter(buf->b_marktree, start_row, 0, end_row, 0, lines_filter, itr)) {
+ return 0;
+ }
+
+ int virt_lines = 0;
while (true) {
MTKey mark = marktree_itr_current(itr);
- if (mark.pos.row < 0 || mark.pos.row >= end_row) {
- break;
- } else if (mt_end(mark) || !(mark.flags & MT_FLAG_DECOR_VIRT_LINES)) {
- goto next_mark;
- }
- DecorVirtText *vt = mark.decor_data.ext.vt;
- while (vt) {
- if (vt->flags & kVTIsLines) {
- bool above = vt->flags & kVTLinesAbove;
- int draw_row = mark.pos.row + (above ? 0 : 1);
- if (draw_row == row) {
- virt_lines += (int)kv_size(vt->data.virt_lines);
- if (lines) {
- kv_splice(*lines, vt->data.virt_lines);
+ DecorVirtText *vt = mt_decor_virt(mark);
+ if (mt_scoped_in_win(mark, wp)) {
+ while (vt) {
+ if (vt->flags & kVTIsLines) {
+ bool above = vt->flags & kVTLinesAbove;
+ int draw_row = mark.pos.row + (above ? 0 : 1);
+ if (draw_row == row) {
+ virt_lines += (int)kv_size(vt->data.virt_lines);
+ if (lines) {
+ kv_splice(*lines, vt->data.virt_lines);
+ }
}
}
+ vt = vt->next;
}
- vt = vt->next;
}
-next_mark:
- marktree_itr_next(buf->b_marktree, itr);
+
+ if (!marktree_itr_next_filter(buf->b_marktree, itr, end_row, 0, lines_filter)) {
+ break;
+ }
}
return virt_lines;
}
/// This assumes maximum one entry of each kind, which will not always be the case.
-void decor_to_dict_legacy(Dictionary *dict, DecorInline decor, bool hl_name)
+///
+/// NB: assumes caller has allocated enough space in dict for all fields!
+void decor_to_dict_legacy(Dictionary *dict, DecorInline decor, bool hl_name, Arena *arena)
{
DecorSignHighlight sh_hl = DECOR_SIGN_HIGHLIGHT_INIT;
DecorSignHighlight sh_sign = DECOR_SIGN_HIGHLIGHT_INIT;
@@ -950,64 +972,70 @@ void decor_to_dict_legacy(Dictionary *dict, DecorInline decor, bool hl_name)
}
if (sh_hl.hl_id) {
- PUT(*dict, "hl_group", hl_group_name(sh_hl.hl_id, hl_name));
- PUT(*dict, "hl_eol", BOOLEAN_OBJ(sh_hl.flags & kSHHlEol));
- if (sh_hl.flags & kSHConceal) {
- char buf[MAX_SCHAR_SIZE];
- schar_get(buf, sh_hl.text.sc[0]);
- PUT(*dict, "conceal", CSTR_TO_OBJ(buf));
- }
+ PUT_C(*dict, "hl_group", hl_group_name(sh_hl.hl_id, hl_name));
+ PUT_C(*dict, "hl_eol", BOOLEAN_OBJ(sh_hl.flags & kSHHlEol));
+ priority = sh_hl.priority;
+ }
- if (sh_hl.flags & kSHSpellOn) {
- PUT(*dict, "spell", BOOLEAN_OBJ(true));
- } else if (sh_hl.flags & kSHSpellOff) {
- PUT(*dict, "spell", BOOLEAN_OBJ(false));
- }
+ if (sh_hl.flags & kSHConceal) {
+ char buf[MAX_SCHAR_SIZE];
+ schar_get(buf, sh_hl.text[0]);
+ PUT_C(*dict, "conceal", CSTR_TO_ARENA_OBJ(arena, buf));
+ }
- priority = sh_hl.priority;
+ if (sh_hl.flags & kSHSpellOn) {
+ PUT_C(*dict, "spell", BOOLEAN_OBJ(true));
+ } else if (sh_hl.flags & kSHSpellOff) {
+ PUT_C(*dict, "spell", BOOLEAN_OBJ(false));
}
if (sh_hl.flags & kSHUIWatched) {
- PUT(*dict, "ui_watched", BOOLEAN_OBJ(true));
+ PUT_C(*dict, "ui_watched", BOOLEAN_OBJ(true));
+ }
+
+ if (sh_hl.url != NULL) {
+ PUT_C(*dict, "url", STRING_OBJ(cstr_as_string(sh_hl.url)));
}
if (virt_text) {
if (virt_text->hl_mode) {
- PUT(*dict, "hl_mode", CSTR_TO_OBJ(hl_mode_str[virt_text->hl_mode]));
+ PUT_C(*dict, "hl_mode", CSTR_AS_OBJ(hl_mode_str[virt_text->hl_mode]));
}
- Array chunks = virt_text_to_array(virt_text->data.virt_text, hl_name);
- PUT(*dict, "virt_text", ARRAY_OBJ(chunks));
- PUT(*dict, "virt_text_hide", BOOLEAN_OBJ(virt_text->flags & kVTHide));
+ Array chunks = virt_text_to_array(virt_text->data.virt_text, hl_name, arena);
+ PUT_C(*dict, "virt_text", ARRAY_OBJ(chunks));
+ PUT_C(*dict, "virt_text_hide", BOOLEAN_OBJ(virt_text->flags & kVTHide));
+ PUT_C(*dict, "virt_text_repeat_linebreak", BOOLEAN_OBJ(virt_text->flags & kVTRepeatLinebreak));
if (virt_text->pos == kVPosWinCol) {
- PUT(*dict, "virt_text_win_col", INTEGER_OBJ(virt_text->col));
+ PUT_C(*dict, "virt_text_win_col", INTEGER_OBJ(virt_text->col));
}
- PUT(*dict, "virt_text_pos",
- CSTR_TO_OBJ(virt_text_pos_str[virt_text->pos]));
+ PUT_C(*dict, "virt_text_pos", CSTR_AS_OBJ(virt_text_pos_str[virt_text->pos]));
priority = virt_text->priority;
}
if (virt_lines) {
- Array all_chunks = ARRAY_DICT_INIT;
+ Array all_chunks = arena_array(arena, kv_size(virt_lines->data.virt_lines));
bool virt_lines_leftcol = false;
for (size_t i = 0; i < kv_size(virt_lines->data.virt_lines); i++) {
virt_lines_leftcol = kv_A(virt_lines->data.virt_lines, i).left_col;
- Array chunks = virt_text_to_array(kv_A(virt_lines->data.virt_lines, i).line, hl_name);
+ Array chunks = virt_text_to_array(kv_A(virt_lines->data.virt_lines, i).line, hl_name, arena);
ADD(all_chunks, ARRAY_OBJ(chunks));
}
- PUT(*dict, "virt_lines", ARRAY_OBJ(all_chunks));
- PUT(*dict, "virt_lines_above", BOOLEAN_OBJ(virt_lines->flags & kVTLinesAbove));
- PUT(*dict, "virt_lines_leftcol", BOOLEAN_OBJ(virt_lines_leftcol));
+ PUT_C(*dict, "virt_lines", ARRAY_OBJ(all_chunks));
+ PUT_C(*dict, "virt_lines_above", BOOLEAN_OBJ(virt_lines->flags & kVTLinesAbove));
+ PUT_C(*dict, "virt_lines_leftcol", BOOLEAN_OBJ(virt_lines_leftcol));
priority = virt_lines->priority;
}
if (sh_sign.flags & kSHIsSign) {
- if (sh_sign.text.ptr) {
- PUT(*dict, "sign_text", CSTR_TO_OBJ(sh_sign.text.ptr));
+ if (sh_sign.text[0]) {
+ char buf[SIGN_WIDTH * MAX_SCHAR_SIZE];
+ describe_sign_text(buf, sh_sign.text);
+ PUT_C(*dict, "sign_text", CSTR_TO_ARENA_OBJ(arena, buf));
}
if (sh_sign.sign_name) {
- PUT(*dict, "sign_name", CSTR_TO_OBJ(sh_sign.sign_name));
+ PUT_C(*dict, "sign_name", CSTR_AS_OBJ(sh_sign.sign_name));
}
// uncrustify:off
@@ -1024,14 +1052,14 @@ void decor_to_dict_legacy(Dictionary *dict, DecorInline decor, bool hl_name)
for (int j = 0; hls[j].name; j++) {
if (hls[j].val) {
- PUT(*dict, hls[j].name, hl_group_name(hls[j].val, hl_name));
+ PUT_C(*dict, hls[j].name, hl_group_name(hls[j].val, hl_name));
}
}
priority = sh_sign.priority;
}
if (priority != -1) {
- PUT(*dict, "priority", INTEGER_OBJ(priority));
+ PUT_C(*dict, "priority", INTEGER_OBJ(priority));
}
}
@@ -1059,7 +1087,7 @@ uint16_t decor_type_flags(DecorInline decor)
Object hl_group_name(int hl_id, bool hl_name)
{
if (hl_name) {
- return CSTR_TO_OBJ(syn_id2name(hl_id));
+ return CSTR_AS_OBJ(syn_id2name(hl_id));
} else {
return INTEGER_OBJ(hl_id);
}
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index f5448c051b..a63cc7afc0 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -5,18 +5,20 @@
#include <stdint.h>
#include "klib/kvec.h"
-#include "nvim/buffer_defs.h"
-#include "nvim/decoration_defs.h" // IWYU pragma: export
+#include "nvim/decoration_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
-#include "nvim/marktree.h"
+#include "nvim/marktree_defs.h"
#include "nvim/pos_defs.h" // IWYU pragma: keep
+#include "nvim/sign_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h"
// actual Decor* data is in decoration_defs.h
-EXTERN const char *const virt_text_pos_str[] INIT( = { "eol", "overlay", "win_col", "right_align",
- "inline" });
+/// Keep in sync with VirtTextPos in decoration_defs.h
+EXTERN const char *const virt_text_pos_str[]
+INIT( = { "eol", "overlay", "win_col", "right_align", "inline" });
+/// Keep in sync with HlMode in decoration_defs.h
EXTERN const char *const hl_mode_str[] INIT( = { "", "replace", "combine", "blend" });
typedef enum {
@@ -43,15 +45,17 @@ typedef struct {
VirtTextPos pos;
} ui;
} data;
- int attr_id; // cached lookup of inl.hl_id if it was a highlight
- bool owned; // ephemeral decoration, free memory immediately
+ int attr_id; ///< cached lookup of inl.hl_id if it was a highlight
+ bool owned; ///< ephemeral decoration, free memory immediately
DecorPriority priority;
+ DecorPriority subpriority; ///< Secondary priority value used for ordering (#27131).
+ ///< Reflects the order of patterns/captures in the query file.
DecorRangeKind kind;
/// Screen column to draw the virtual text.
- /// When -1, the virtual text may be drawn after deciding where.
- /// When -3, the virtual text should be drawn on the next screen line.
- /// When -10, the virtual text has just been added.
- /// When INT_MIN, the virtual text should no longer be drawn.
+ /// When -1, it should be drawn on the current screen line after deciding where.
+ /// When -3, it may be drawn at a position yet to be assigned.
+ /// When -10, it has just been added.
+ /// When INT_MIN, it should no longer be drawn.
int draw_col;
} DecorRange;
diff --git a/src/nvim/decoration_defs.h b/src/nvim/decoration_defs.h
index dc5d7b9ae4..8d0075b169 100644
--- a/src/nvim/decoration_defs.h
+++ b/src/nvim/decoration_defs.h
@@ -3,6 +3,7 @@
#include <stdint.h>
#include "klib/kvec.h"
+#include "nvim/api/private/defs.h"
#include "nvim/types_defs.h"
#define DECOR_ID_INVALID UINT32_MAX
@@ -15,6 +16,7 @@ typedef struct {
typedef kvec_t(VirtTextChunk) VirtText;
#define VIRTTEXT_EMPTY ((VirtText)KV_INITIAL_VALUE)
+/// Keep in sync with virt_text_pos_str[] in decoration.h
typedef enum {
kVPosEndOfLine,
kVPosOverlay,
@@ -28,6 +30,7 @@ typedef kvec_t(struct virt_line { VirtText line; bool left_col; }) VirtLines;
typedef uint16_t DecorPriority;
#define DECOR_PRIORITY_BASE 0x1000
+/// Keep in sync with hl_mode_str[] in decoration.h
typedef enum {
kHlModeUnknown,
kHlModeReplace,
@@ -57,11 +60,7 @@ typedef struct {
uint16_t flags;
DecorPriority priority;
int hl_id; // if sign: highlight of sign text
- // TODO(bfredl): Later signs should use sc[2] as well.
- union {
- char *ptr; // sign
- schar_T sc[2]; // conceal text (only sc[0] used)
- } text;
+ schar_T text[SIGN_WIDTH]; // conceal text only uses text[0]
// NOTE: if more functionality is added to a Highlight these should be overloaded
// or restructured
char *sign_name;
@@ -70,15 +69,17 @@ typedef struct {
int line_hl_id;
int cursorline_hl_id;
uint32_t next;
+ const char *url;
} DecorSignHighlight;
-#define DECOR_SIGN_HIGHLIGHT_INIT { 0, DECOR_PRIORITY_BASE, 0, { .ptr = NULL }, NULL, 0, 0, 0, 0, \
- DECOR_ID_INVALID }
+#define DECOR_SIGN_HIGHLIGHT_INIT { 0, DECOR_PRIORITY_BASE, 0, { 0, 0 }, NULL, 0, 0, 0, 0, \
+ DECOR_ID_INVALID, NULL }
enum {
kVTIsLines = 1,
kVTHide = 2,
kVTLinesAbove = 4,
+ kVTRepeatLinebreak = 8,
};
typedef struct DecorVirtText DecorVirtText;
@@ -123,3 +124,26 @@ typedef struct {
// initializes in a valid state for the DecorHighlightInline branch
#define DECOR_INLINE_INIT { .ext = false, .data.hl = DECOR_HIGHLIGHT_INLINE_INIT }
+
+typedef struct {
+ NS ns_id;
+
+ enum {
+ kDecorProviderActive = 1,
+ kDecorProviderWinDisabled = 2,
+ kDecorProviderRedrawDisabled = 3,
+ kDecorProviderDisabled = 4,
+ } state;
+
+ LuaRef redraw_start;
+ LuaRef redraw_buf;
+ LuaRef redraw_win;
+ LuaRef redraw_line;
+ LuaRef redraw_end;
+ LuaRef hl_def;
+ LuaRef spell_nav;
+ int hl_valid;
+ bool hl_cached;
+
+ uint8_t error_count;
+} DecorProvider;
diff --git a/src/nvim/decoration_provider.c b/src/nvim/decoration_provider.c
index 172eb569c9..2417c14f7f 100644
--- a/src/nvim/decoration_provider.c
+++ b/src/nvim/decoration_provider.c
@@ -1,5 +1,6 @@
#include <assert.h>
#include <lauxlib.h>
+#include <stdint.h>
#include <string.h>
#include "klib/kvec.h"
@@ -8,18 +9,26 @@
#include "nvim/api/private/helpers.h"
#include "nvim/buffer_defs.h"
#include "nvim/decoration.h"
+#include "nvim/decoration_defs.h"
#include "nvim/decoration_provider.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/log.h"
#include "nvim/lua/executor.h"
#include "nvim/message.h"
+#include "nvim/move.h"
#include "nvim/pos_defs.h"
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "decoration_provider.c.generated.h"
+#endif
+
+enum { DP_MAX_ERROR = 3, };
+
static kvec_t(DecorProvider) decor_providers = KV_INITIAL_VALUE;
#define DECORATION_PROVIDER_INIT(ns_id) (DecorProvider) \
- { ns_id, false, LUA_NOREF, LUA_NOREF, \
+ { ns_id, kDecorProviderDisabled, LUA_NOREF, LUA_NOREF, \
LUA_NOREF, LUA_NOREF, LUA_NOREF, \
LUA_NOREF, -1, false, false, 0 }
@@ -30,17 +39,23 @@ static void decor_provider_error(DecorProvider *provider, const char *name, cons
msg_schedule_semsg_multiline("Error in decoration provider %s.%s:\n%s", ns_name, name, msg);
}
-static bool decor_provider_invoke(DecorProvider *provider, const char *name, LuaRef ref, Array args,
+// Note we pass in a provider index as this function may cause decor_providers providers to be
+// reallocated so we need to be careful with DecorProvider pointers
+static bool decor_provider_invoke(int provider_idx, const char *name, LuaRef ref, Array args,
bool default_true)
{
Error err = ERROR_INIT;
textlock++;
provider_active = true;
- Object ret = nlua_call_ref(ref, name, args, true, &err);
+ Object ret = nlua_call_ref(ref, name, args, kRetNilBool, NULL, &err);
provider_active = false;
textlock--;
+ // We get the provider here via an index in case the above call to nlua_call_ref causes
+ // decor_providers to be reallocated.
+ DecorProvider *provider = &kv_A(decor_providers, provider_idx);
+
if (!ERROR_SET(&err)
&& api_object_to_bool(ret, "provider %s retval", default_true, &err)) {
provider->error_count = 0;
@@ -52,7 +67,7 @@ static bool decor_provider_invoke(DecorProvider *provider, const char *name, Lua
provider->error_count++;
if (provider->error_count >= DP_MAX_ERROR) {
- provider->active = false;
+ provider->state = kDecorProviderDisabled;
}
}
@@ -65,11 +80,7 @@ void decor_providers_invoke_spell(win_T *wp, int start_row, int start_col, int e
{
for (size_t i = 0; i < kv_size(decor_providers); i++) {
DecorProvider *p = &kv_A(decor_providers, i);
- if (!p->active) {
- continue;
- }
-
- if (p->spell_nav != LUA_NOREF) {
+ if (p->state != kDecorProviderDisabled && p->spell_nav != LUA_NOREF) {
MAXSIZE_TEMP_ARRAY(args, 6);
ADD_C(args, INTEGER_OBJ(wp->handle));
ADD_C(args, INTEGER_OBJ(wp->w_buffer->handle));
@@ -77,7 +88,7 @@ void decor_providers_invoke_spell(win_T *wp, int start_row, int start_col, int e
ADD_C(args, INTEGER_OBJ(start_col));
ADD_C(args, INTEGER_OBJ(end_row));
ADD_C(args, INTEGER_OBJ(end_col));
- decor_provider_invoke(p, "spell", p->spell_nav, args, true);
+ decor_provider_invoke((int)i, "spell", p->spell_nav, args, true);
}
}
}
@@ -86,27 +97,15 @@ void decor_providers_invoke_spell(win_T *wp, int start_row, int start_col, int e
///
/// @param[out] providers Decoration providers
/// @param[out] err Provider err
-void decor_providers_start(DecorProviders *providers)
+void decor_providers_start(void)
{
- kvi_init(*providers);
-
for (size_t i = 0; i < kv_size(decor_providers); i++) {
DecorProvider *p = &kv_A(decor_providers, i);
- if (!p->active) {
- continue;
- }
-
- bool active;
- if (p->redraw_start != LUA_NOREF) {
+ if (p->state != kDecorProviderDisabled && p->redraw_start != LUA_NOREF) {
MAXSIZE_TEMP_ARRAY(args, 2);
ADD_C(args, INTEGER_OBJ((int)display_tick));
- active = decor_provider_invoke(p, "start", p->redraw_start, args, true);
- } else {
- active = true;
- }
-
- if (active) {
- kvi_push(*providers, p);
+ bool active = decor_provider_invoke((int)i, "start", p->redraw_start, args, true);
+ kv_A(decor_providers, i).state = active ? kDecorProviderActive : kDecorProviderRedrawDisabled;
}
}
}
@@ -118,30 +117,32 @@ void decor_providers_start(DecorProviders *providers)
/// @param providers Decoration providers
/// @param[out] line_providers Enabled line providers to invoke in win_line
/// @param[out] err Provider error
-void decor_providers_invoke_win(win_T *wp, DecorProviders *providers,
- DecorProviders *line_providers)
+void decor_providers_invoke_win(win_T *wp)
{
- kvi_init(*line_providers);
// this might change in the future
// then we would need decor_state.running_decor_provider just like "on_line" below
assert(kv_size(decor_state.active) == 0);
- linenr_T knownmax = MIN(wp->w_buffer->b_ml.ml_line_count,
- ((wp->w_valid & VALID_BOTLINE)
- ? wp->w_botline
- : MAX(wp->w_topline + wp->w_height_inner, wp->w_botline)));
+ if (kv_size(decor_providers) > 0) {
+ validate_botline(wp);
+ }
+ linenr_T botline = MIN(wp->w_botline, wp->w_buffer->b_ml.ml_line_count);
- for (size_t k = 0; k < kv_size(*providers); k++) {
- DecorProvider *p = kv_A(*providers, k);
- if (p && p->redraw_win != LUA_NOREF) {
+ for (size_t i = 0; i < kv_size(decor_providers); i++) {
+ DecorProvider *p = &kv_A(decor_providers, i);
+ if (p->state == kDecorProviderWinDisabled) {
+ p->state = kDecorProviderActive;
+ }
+
+ if (p->state == kDecorProviderActive && p->redraw_win != LUA_NOREF) {
MAXSIZE_TEMP_ARRAY(args, 4);
ADD_C(args, WINDOW_OBJ(wp->handle));
ADD_C(args, BUFFER_OBJ(wp->w_buffer->handle));
// TODO(bfredl): we are not using this, but should be first drawn line?
ADD_C(args, INTEGER_OBJ(wp->w_topline - 1));
- ADD_C(args, INTEGER_OBJ(knownmax - 1));
- if (decor_provider_invoke(p, "win", p->redraw_win, args, true)) {
- kvi_push(*line_providers, p);
+ ADD_C(args, INTEGER_OBJ(botline - 1));
+ if (!decor_provider_invoke((int)i, "win", p->redraw_win, args, true)) {
+ kv_A(decor_providers, i).state = kDecorProviderWinDisabled;
}
}
}
@@ -154,21 +155,21 @@ void decor_providers_invoke_win(win_T *wp, DecorProviders *providers,
/// @param row Row to invoke line callback for
/// @param[out] has_decor Set when at least one provider invokes a line callback
/// @param[out] err Provider error
-void decor_providers_invoke_line(win_T *wp, DecorProviders *providers, int row, bool *has_decor)
+void decor_providers_invoke_line(win_T *wp, int row, bool *has_decor)
{
decor_state.running_decor_provider = true;
- for (size_t k = 0; k < kv_size(*providers); k++) {
- DecorProvider *p = kv_A(*providers, k);
- if (p && p->redraw_line != LUA_NOREF) {
+ for (size_t i = 0; i < kv_size(decor_providers); i++) {
+ DecorProvider *p = &kv_A(decor_providers, i);
+ if (p->state == kDecorProviderActive && p->redraw_line != LUA_NOREF) {
MAXSIZE_TEMP_ARRAY(args, 3);
ADD_C(args, WINDOW_OBJ(wp->handle));
ADD_C(args, BUFFER_OBJ(wp->w_buffer->handle));
ADD_C(args, INTEGER_OBJ(row));
- if (decor_provider_invoke(p, "line", p->redraw_line, args, true)) {
+ if (decor_provider_invoke((int)i, "line", p->redraw_line, args, true)) {
*has_decor = true;
} else {
// return 'false' or error: skip rest of this window
- kv_A(*providers, k) = NULL;
+ kv_A(decor_providers, i).state = kDecorProviderWinDisabled;
}
hl_check_ns();
@@ -182,15 +183,15 @@ void decor_providers_invoke_line(win_T *wp, DecorProviders *providers, int row,
/// @param buf Buffer
/// @param providers Decoration providers
/// @param[out] err Provider error
-void decor_providers_invoke_buf(buf_T *buf, DecorProviders *providers)
+void decor_providers_invoke_buf(buf_T *buf)
{
- for (size_t i = 0; i < kv_size(*providers); i++) {
- DecorProvider *p = kv_A(*providers, i);
- if (p && p->redraw_buf != LUA_NOREF) {
+ for (size_t i = 0; i < kv_size(decor_providers); i++) {
+ DecorProvider *p = &kv_A(decor_providers, i);
+ if (p->state == kDecorProviderActive && p->redraw_buf != LUA_NOREF) {
MAXSIZE_TEMP_ARRAY(args, 2);
ADD_C(args, BUFFER_OBJ(buf->handle));
ADD_C(args, INTEGER_OBJ((int64_t)display_tick));
- decor_provider_invoke(p, "buf", p->redraw_buf, args, true);
+ decor_provider_invoke((int)i, "buf", p->redraw_buf, args, true);
}
}
}
@@ -200,14 +201,15 @@ void decor_providers_invoke_buf(buf_T *buf, DecorProviders *providers)
/// @param providers Decoration providers
/// @param displaytick Display tick
/// @param[out] err Provider error
-void decor_providers_invoke_end(DecorProviders *providers)
+void decor_providers_invoke_end(void)
{
- for (size_t i = 0; i < kv_size(*providers); i++) {
- DecorProvider *p = kv_A(*providers, i);
- if (p && p->active && p->redraw_end != LUA_NOREF) {
+ for (size_t i = 0; i < kv_size(decor_providers); i++) {
+ DecorProvider *p = &kv_A(decor_providers, i);
+ if (p->state != kDecorProviderDisabled && p->redraw_end != LUA_NOREF) {
MAXSIZE_TEMP_ARRAY(args, 1);
ADD_C(args, INTEGER_OBJ((int)display_tick));
- decor_provider_invoke(p, "end", p->redraw_end, args, true);
+ decor_provider_invoke((int)i, "end", p->redraw_end, args, true);
+ kv_A(decor_providers, i).state = kDecorProviderActive;
}
}
decor_check_to_be_deleted();
@@ -220,10 +222,8 @@ void decor_providers_invoke_end(DecorProviders *providers)
/// like highlight_changed() (throttled to the next redraw or mode change)
void decor_provider_invalidate_hl(void)
{
- size_t len = kv_size(decor_providers);
- for (size_t i = 0; i < len; i++) {
- DecorProvider *item = &kv_A(decor_providers, i);
- item->hl_cached = false;
+ for (size_t i = 0; i < kv_size(decor_providers); i++) {
+ kv_A(decor_providers, i).hl_cached = false;
}
if (ns_hl_active) {
@@ -235,14 +235,11 @@ void decor_provider_invalidate_hl(void)
DecorProvider *get_decor_provider(NS ns_id, bool force)
{
assert(ns_id > 0);
- size_t i;
size_t len = kv_size(decor_providers);
- for (i = 0; i < len; i++) {
- DecorProvider *item = &kv_A(decor_providers, i);
- if (item->ns_id == ns_id) {
- return item;
- } else if (item->ns_id > ns_id) {
- break;
+ for (size_t i = 0; i < len; i++) {
+ DecorProvider *p = &kv_A(decor_providers, i);
+ if (p->ns_id == ns_id) {
+ return p;
}
}
@@ -250,16 +247,7 @@ DecorProvider *get_decor_provider(NS ns_id, bool force)
return NULL;
}
- // Adding a new provider, so allocate room in the vector
- (void)kv_a(decor_providers, len);
- if (i < len) {
- // New ns_id needs to be inserted between existing providers to maintain
- // ordering, so shift other providers with larger ns_id
- memmove(&kv_A(decor_providers, i + 1),
- &kv_A(decor_providers, i),
- (len - i) * sizeof(kv_a(decor_providers, i)));
- }
- DecorProvider *item = &kv_a(decor_providers, i);
+ DecorProvider *item = &kv_a(decor_providers, len);
*item = DECORATION_PROVIDER_INIT(ns_id);
return item;
@@ -276,7 +264,7 @@ void decor_provider_clear(DecorProvider *p)
NLUA_CLEAR_REF(p->redraw_line);
NLUA_CLEAR_REF(p->redraw_end);
NLUA_CLEAR_REF(p->spell_nav);
- p->active = false;
+ p->state = kDecorProviderDisabled;
}
void decor_free_all_mem(void)
diff --git a/src/nvim/decoration_provider.h b/src/nvim/decoration_provider.h
index e0dd67a6f7..ad6fb7ac19 100644
--- a/src/nvim/decoration_provider.h
+++ b/src/nvim/decoration_provider.h
@@ -1,32 +1,10 @@
#pragma once
#include <stdbool.h>
-#include <stdint.h>
-#include "klib/kvec.h"
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
+#include "nvim/decoration_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
-#include "nvim/types_defs.h"
-
-#define DP_MAX_ERROR 3
-
-typedef struct {
- NS ns_id;
- bool active;
- LuaRef redraw_start;
- LuaRef redraw_buf;
- LuaRef redraw_win;
- LuaRef redraw_line;
- LuaRef redraw_end;
- LuaRef hl_def;
- LuaRef spell_nav;
- int hl_valid;
- bool hl_cached;
-
- uint8_t error_count;
-} DecorProvider;
-
-typedef kvec_withinit_t(DecorProvider *, 4) DecorProviders;
+#include "nvim/types_defs.h" // IWYU pragma: keep
EXTERN bool provider_active INIT( = false);
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 0b7f6f266b..2b3010e063 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -18,6 +18,7 @@
#include "auto/config.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/bufwrite.h"
#include "nvim/change.h"
@@ -30,25 +31,30 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/extmark.h"
+#include "nvim/extmark_defs.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/linematch.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/normal.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/shell.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
@@ -60,7 +66,7 @@
#include "nvim/window.h"
#include "xdiff/xdiff.h"
-static int diff_busy = false; // using diff structs, don't change them
+static bool diff_busy = false; // using diff structs, don't change them
static bool diff_need_update = false; // ex_diffupdate needs to be called
// Flags obtained from the 'diffopt' option
@@ -385,7 +391,7 @@ static void diff_mark_adjust_tp(tabpage_T *tp, int idx, linenr_T line1, linenr_T
}
dp->df_lnum[idx] += amount_after;
} else {
- int check_unchanged = false;
+ bool check_unchanged = false;
// 2. 3. 4. 5.: inserted/deleted lines touching this diff.
if (deleted > 0) {
@@ -1004,7 +1010,7 @@ theend:
static int check_external_diff(diffio_T *diffio)
{
// May try twice, first with "-a" and then without.
- int io_error = false;
+ bool io_error = false;
TriState ok = kFalse;
while (true) {
ok = kFalse;
@@ -1013,7 +1019,7 @@ static int check_external_diff(diffio_T *diffio)
if (fd == NULL) {
io_error = true;
} else {
- if (fwrite("line1\n", (size_t)6, (size_t)1, fd) != 1) {
+ if (fwrite("line1\n", 6, 1, fd) != 1) {
io_error = true;
}
fclose(fd);
@@ -1022,7 +1028,7 @@ static int check_external_diff(diffio_T *diffio)
if (fd == NULL) {
io_error = true;
} else {
- if (fwrite("line2\n", (size_t)6, (size_t)1, fd) != 1) {
+ if (fwrite("line2\n", 6, 1, fd) != 1) {
io_error = true;
}
fclose(fd);
@@ -1167,9 +1173,9 @@ static int diff_file(diffio_T *dio)
tmp_orig, tmp_new);
append_redir(cmd, len, p_srr, tmp_diff);
block_autocmds(); // Avoid ShellCmdPost stuff
- (void)call_shell(cmd,
- kShellOptFilter | kShellOptSilent | kShellOptDoOut,
- NULL);
+ call_shell(cmd,
+ kShellOptFilter | kShellOptSilent | kShellOptDoOut,
+ NULL);
unblock_autocmds();
xfree(cmd);
return OK;
@@ -1251,7 +1257,7 @@ void ex_diffpatch(exarg_T *eap)
vim_snprintf(buf, buflen, "patch -o %s %s < %s",
tmp_new, tmp_orig, esc_name);
block_autocmds(); // Avoid ShellCmdPost stuff
- (void)call_shell(buf, kShellOptFilter, NULL);
+ call_shell(buf, kShellOptFilter, NULL);
unblock_autocmds();
}
@@ -1390,7 +1396,7 @@ static void set_diff_option(win_T *wp, bool value)
curwin = wp;
curbuf = curwin->w_buffer;
curbuf->b_ro_locked++;
- set_option_value_give_err("diff", BOOLEAN_OPTVAL(value), OPT_LOCAL);
+ set_option_value_give_err(kOptDiff, BOOLEAN_OPTVAL(value), OPT_LOCAL);
curbuf->b_ro_locked--;
curwin = old_curwin;
curbuf = curwin->w_buffer;
@@ -1399,7 +1405,7 @@ static void set_diff_option(win_T *wp, bool value)
/// Set options in window "wp" for diff mode.
///
/// @param addbuf Add buffer to diff.
-void diff_win_options(win_T *wp, int addbuf)
+void diff_win_options(win_T *wp, bool addbuf)
{
win_T *old_curwin = curwin;
@@ -1431,7 +1437,7 @@ void diff_win_options(win_T *wp, int addbuf)
}
wp->w_p_fdm_save = xstrdup(wp->w_p_fdm);
}
- set_string_option_direct_in_win(wp, "fdm", -1, "diff", OPT_LOCAL | OPT_FREE, 0);
+ set_string_option_direct_in_win(wp, kOptFoldmethod, "diff", OPT_LOCAL, 0);
if (!wp->w_p_diff) {
wp->w_p_fen_save = wp->w_p_fen;
@@ -1473,7 +1479,7 @@ void diff_win_options(win_T *wp, int addbuf)
/// @param eap
void ex_diffoff(exarg_T *eap)
{
- int diffwin = false;
+ bool diffwin = false;
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (eap->forceit ? wp->w_p_diff : (wp == curwin)) {
@@ -1889,7 +1895,7 @@ static void count_filler_lines_and_topline(int *curlinenum_to, int *linesfiller,
{
const diff_T *curdif = thistopdiff;
int ch_virtual_lines = 0;
- int isfiller = 0;
+ bool isfiller = false;
while (virtual_lines_passed > 0) {
if (ch_virtual_lines) {
virtual_lines_passed--;
@@ -1902,7 +1908,7 @@ static void count_filler_lines_and_topline(int *curlinenum_to, int *linesfiller,
} else {
(*linesfiller) = 0;
ch_virtual_lines = get_max_diff_length(curdif);
- isfiller = (curdif->df_count[toidx] ? 0 : 1);
+ isfiller = (curdif->df_count[toidx] ? false : true);
if (isfiller) {
while (curdif && curdif->df_next && curdif->df_lnum[toidx] ==
curdif->df_next->df_lnum[toidx]
@@ -2156,12 +2162,12 @@ int diff_check_with_linestatus(win_T *wp, linenr_T lnum, int *linestatus)
}
if (lnum < dp->df_lnum[idx] + dp->df_count[idx]) {
- int zero = false;
+ bool zero = false;
// Changed or inserted line. If the other buffers have a count of
// zero, the lines were inserted. If the other buffers have the same
// count, check if the lines are identical.
- int cmp = false;
+ bool cmp = false;
for (int i = 0; i < DB_COUNT; i++) {
if ((i != idx) && (curtab->tp_diffbuf[i] != NULL)) {
@@ -2196,7 +2202,7 @@ int diff_check_with_linestatus(win_T *wp, linenr_T lnum, int *linestatus)
// the difference. Can't remove the entry here, we might be halfway
// through updating the window. Just report the text as unchanged.
// Other windows might still show the change though.
- if (zero == false) {
+ if (!zero) {
return 0;
}
return -2;
@@ -2445,8 +2451,8 @@ void diff_set_topline(win_T *fromwin, win_T *towin)
changed_line_abv_curs_win(towin);
check_topfill(towin, false);
- (void)hasFoldingWin(towin, towin->w_topline, &towin->w_topline,
- NULL, true, NULL);
+ hasFoldingWin(towin, towin->w_topline, &towin->w_topline,
+ NULL, true, NULL);
}
/// This is called when 'diffopt' is changed.
@@ -2846,7 +2852,7 @@ void ex_diffgetput(exarg_T *eap)
}
if (*eap->arg == NUL) {
- int found_not_ma = false;
+ bool found_not_ma = false;
// No argument: Find the other buffer in the list of diff buffers.
for (idx_other = 0; idx_other < DB_COUNT; idx_other++) {
if ((curtab->tp_diffbuf[idx_other] != curbuf)
diff --git a/src/nvim/diff.h b/src/nvim/diff.h
index 8b58887890..fd897498df 100644
--- a/src/nvim/diff.h
+++ b/src/nvim/diff.h
@@ -2,16 +2,17 @@
#include <stdbool.h>
-#include "nvim/ex_cmds_defs.h"
+#include "nvim/buffer_defs.h" // IWYU pragma: keep
+#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
-#include "nvim/pos_defs.h"
+#include "nvim/pos_defs.h" // IWYU pragma: keep
// Value set from 'diffopt'.
-EXTERN int diff_context INIT( = 6); // context for folds
-EXTERN int diff_foldcolumn INIT( = 2); // 'foldcolumn' for diff mode
+EXTERN int diff_context INIT( = 6); ///< context for folds
+EXTERN int diff_foldcolumn INIT( = 2); ///< 'foldcolumn' for diff mode
EXTERN bool diff_need_scrollbind INIT( = false);
-EXTERN bool need_diff_redraw INIT( = false); // need to call diff_redraw()
+EXTERN bool need_diff_redraw INIT( = false); ///< need to call diff_redraw()
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "diff.h.generated.h"
diff --git a/src/nvim/digraph.c b/src/nvim/digraph.c
index 99d5cf1035..f91ff9274b 100644
--- a/src/nvim/digraph.c
+++ b/src/nvim/digraph.c
@@ -17,15 +17,16 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/keycodes.h"
#include "nvim/mapping.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/normal.h"
@@ -39,7 +40,7 @@
typedef int result_T;
-typedef struct digraph {
+typedef struct {
uint8_t char1;
uint8_t char2;
result_T result;
@@ -2043,13 +2044,10 @@ char *keymap_init(void)
keymap_unload();
do_cmdline_cmd("unlet! b:keymap_name");
} else {
- char *buf;
- size_t buflen;
-
// Source the keymap file. It will contain a ":loadkeymap" command
// which will call ex_loadkeymap() below.
- buflen = strlen(curbuf->b_p_keymap) + strlen(p_enc) + 14;
- buf = xmalloc(buflen);
+ size_t buflen = strlen(curbuf->b_p_keymap) + strlen(p_enc) + 14;
+ char *buf = xmalloc(buflen);
// try finding "keymap/'keymap'_'encoding'.vim" in 'runtimepath'
vim_snprintf(buf, buflen, "keymap/%s_%s.vim",
@@ -2131,7 +2129,7 @@ void ex_loadkeymap(exarg_T *eap)
vim_snprintf(buf, sizeof(buf), "<buffer> %s %s",
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].from,
((kmap_T *)curbuf->b_kmap_ga.ga_data)[i].to);
- (void)do_map(MAPTYPE_MAP, buf, MODE_LANGMAP, false);
+ do_map(MAPTYPE_MAP, buf, MODE_LANGMAP, false);
}
p_cpo = save_cpo;
@@ -2168,7 +2166,7 @@ static void keymap_unload(void)
for (int i = 0; i < curbuf->b_kmap_ga.ga_len; i++) {
vim_snprintf(buf, sizeof(buf), "<buffer> %s", kp[i].from);
- (void)do_map(MAPTYPE_UNMAP, buf, MODE_LANGMAP, false);
+ do_map(MAPTYPE_UNMAP, buf, MODE_LANGMAP, false);
}
keymap_ga_clear(&curbuf->b_kmap_ga);
@@ -2194,13 +2192,12 @@ bool get_keymap_str(win_T *wp, char *fmt, char *buf, int len)
buf_T *old_curbuf = curbuf;
win_T *old_curwin = curwin;
- char *s;
curbuf = wp->w_buffer;
curwin = wp;
STRCPY(buf, "b:keymap_name"); // must be writable
emsg_skip++;
- s = p = eval_to_string(buf, false);
+ char *s = p = eval_to_string(buf, false);
emsg_skip--;
curbuf = old_curbuf;
curwin = old_curwin;
diff --git a/src/nvim/digraph.h b/src/nvim/digraph.h
index 267004124b..a3782cdd58 100644
--- a/src/nvim/digraph.h
+++ b/src/nvim/digraph.h
@@ -1,6 +1,5 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/garray_defs.h" // IWYU pragma: keep
diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c
index e0887ed1d0..4281cdff33 100644
--- a/src/nvim/drawline.c
+++ b/src/nvim/drawline.c
@@ -11,10 +11,12 @@
#include "nvim/ascii_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/cursor_shape.h"
#include "nvim/decoration.h"
+#include "nvim/decoration_defs.h"
#include "nvim/decoration_provider.h"
#include "nvim/diff.h"
#include "nvim/drawline.h"
@@ -24,59 +26,53 @@
#include "nvim/fold_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
-#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
+#include "nvim/marktree_defs.h"
#include "nvim/match.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/move.h"
#include "nvim/option.h"
#include "nvim/option_vars.h"
+#include "nvim/os/os_defs.h"
#include "nvim/plines.h"
#include "nvim/pos_defs.h"
#include "nvim/quickfix.h"
-#include "nvim/sign.h"
+#include "nvim/sign_defs.h"
#include "nvim/spell.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/statusline.h"
+#include "nvim/statusline_defs.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/terminal.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/vim_defs.h"
#define MB_FILLER_CHAR '<' // character used when a double-width character doesn't fit.
-/// possible draw states in win_line(), drawn in sequence.
-typedef enum {
- WL_START = 0, // nothing done yet
- WL_CMDLINE, // cmdline window column
- WL_FOLD, // 'foldcolumn'
- WL_SIGN, // column for signs
- WL_NR, // line number
- WL_STC, // 'statuscolumn'
- WL_BRI, // 'breakindent'
- WL_SBR, // 'showbreak' or 'diff'
- WL_LINE, // text in the line
-} LineDrawState;
-
/// structure with variables passed between win_line() and other functions
typedef struct {
- LineDrawState draw_state; ///< what to draw next
-
- linenr_T lnum; ///< line number to be drawn
- foldinfo_T foldinfo; ///< fold info for this line
+ const linenr_T lnum; ///< line number to be drawn
+ const foldinfo_T foldinfo; ///< fold info for this line
- int startrow; ///< first row in the window to be drawn
+ const int startrow; ///< first row in the window to be drawn
int row; ///< row in the window, excl w_winrow
colnr_T vcol; ///< virtual column, before wrapping
int col; ///< visual column on screen, after wrapping
int boguscols; ///< nonexistent columns added to "col" to force wrapping
+ int old_boguscols; ///< bogus boguscols
int vcol_off; ///< offset for concealed characters
int off; ///< offset relative start of line
@@ -96,24 +92,14 @@ typedef struct {
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
+ ///< when sc_extra and sc_final are NUL
int extra_attr; ///< attributes for p_extra
- int c_extra; ///< extra chars, all the same
- int c_final; ///< final char, mandatory if set
-
- int n_closing; ///< number of chars in fdc which will be closing
+ schar_T sc_extra; ///< extra chars, all the same
+ schar_T sc_final; ///< final char, mandatory if set
bool extra_for_extmark; ///< n_extra set for inline virtual text
- // 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;
-
- char extra[57]; ///< sign, line number and 'fdc' must fit in here
+ char extra[11]; ///< must be as large as transchar_charbuf[] in charset.c
hlf_T diff_hlf; ///< type of diff highlighting
@@ -135,6 +121,8 @@ typedef struct {
///< or w_skipcol or concealing
int skipped_cells; ///< nr of skipped cells for virtual text
///< to be added to wlv.vcol later
+
+ int *color_cols; ///< if not NULL, highlight colorcolumn using according columns array
} winlinevars_T;
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -162,15 +150,17 @@ void drawline_free_all_mem(void)
}
#endif
-/// Advance **color_cols
-///
-/// @return true when there are columns to draw.
-static bool advance_color_col(int vcol, int **color_cols)
+/// Advance wlv->color_cols if not NULL
+static void advance_color_col(winlinevars_T *wlv, int vcol)
{
- while (**color_cols >= 0 && vcol > **color_cols) {
- (*color_cols)++;
+ if (wlv->color_cols) {
+ while (*wlv->color_cols >= 0 && vcol > *wlv->color_cols) {
+ wlv->color_cols++;
+ }
+ if (*wlv->color_cols < 0) {
+ wlv->color_cols = NULL;
+ }
}
- return **color_cols >= 0;
}
/// Used when 'cursorlineopt' contains "screenline": compute the margins between
@@ -224,6 +214,9 @@ static void margin_columns_win(win_T *wp, int *left_col, int *right_col)
/// Handles composing chars
static int line_putchar(buf_T *buf, const char **pp, schar_T *dest, int maxcells, int vcol)
{
+ // Caller should handle overwriting the right half of a double-width char.
+ assert(dest[0] != 0);
+
const char *p = *pp;
int cells = utf_ptr2cells(p);
int c_len = utfc_ptr2len(p);
@@ -237,6 +230,7 @@ static int line_putchar(buf_T *buf, const char **pp, schar_T *dest, int maxcells
cells = MIN(tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array), maxcells);
}
+ // When overwriting the left half of a double-width char, clear the right half.
if (cells < maxcells && dest[cells] == 0) {
dest[cells] = schar_from_ascii(' ');
}
@@ -305,10 +299,12 @@ static void draw_virt_text(win_T *wp, buf_T *buf, int col_off, int *end_col, int
int vcol = item->draw_col - col_off;
col = draw_virt_text_item(buf, item->draw_col, vt->data.virt_text,
vt->hl_mode, max_col, vcol);
+ if (vt->pos == kVPosEndOfLine && do_eol) {
+ state->eol_col = col + 1;
+ }
}
- item->draw_col = INT_MIN; // deactivate
- if (vt && vt->pos == kVPosEndOfLine && do_eol) {
- state->eol_col = col + 1;
+ if (!vt || !(vt->flags & kVTRepeatLinebreak)) {
+ item->draw_col = INT_MIN; // deactivate
}
*end_col = MAX(*end_col, col);
@@ -346,8 +342,15 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode,
} else {
attr = virt_attr;
}
- schar_T dummy[2];
+ schar_T dummy[2] = { schar_from_ascii(' '), schar_from_ascii(' ') };
int maxcells = max_col - col;
+ // When overwriting the right half of a double-width char, clear the left half.
+ if (!through && linebuf_char[col] == 0) {
+ assert(col > 0);
+ linebuf_char[col - 1] = schar_from_ascii(' ');
+ // Clear the right half as well for the assertion in line_putchar().
+ linebuf_char[col] = schar_from_ascii(' ');
+ }
int cells = line_putchar(buf, &p, through ? dummy : &linebuf_char[col],
maxcells, vcol);
for (int c = 0; c < cells; c++) {
@@ -359,6 +362,38 @@ static int draw_virt_text_item(buf_T *buf, int col, VirtText vt, HlMode hl_mode,
return col;
}
+// TODO(bfredl): integrate with grid.c linebuf code? madness?
+static void draw_col_buf(win_T *wp, winlinevars_T *wlv, const char *text, size_t len, int attr,
+ bool vcol)
+{
+ const char *ptr = text;
+ while (ptr < text + len && wlv->off < wp->w_grid.cols) {
+ int cells = line_putchar(wp->w_buffer, &ptr, &linebuf_char[wlv->off],
+ wp->w_grid.cols - wlv->off, wlv->off);
+ int myattr = attr;
+ if (vcol) {
+ advance_color_col(wlv, wlv->vcol);
+ if (wlv->color_cols && wlv->vcol == *wlv->color_cols) {
+ myattr = hl_combine_attr(win_hl_attr(wp, HLF_MC), myattr);
+ }
+ }
+ for (int c = 0; c < cells; c++) {
+ linebuf_attr[wlv->off] = myattr;
+ linebuf_vcol[wlv->off] = vcol ? wlv->vcol++ : -1;
+ wlv->off++;
+ }
+ }
+}
+
+static void draw_col_fill(winlinevars_T *wlv, schar_T fillchar, int width, int attr)
+{
+ for (int i = 0; i < width; i++) {
+ linebuf_char[wlv->off] = fillchar;
+ linebuf_attr[wlv->off] = attr;
+ wlv->off++;
+ }
+}
+
/// Return true if CursorLineSign highlight is to be used.
static bool use_cursor_line_highlight(win_T *wp, linenr_T lnum)
{
@@ -367,129 +402,78 @@ static bool use_cursor_line_highlight(win_T *wp, linenr_T lnum)
&& (wp->w_p_culopt_flags & CULOPT_NBR);
}
-static char fdc_buf[MB_MAXCHAR * 10 + 1];
-
/// Setup for drawing the 'foldcolumn', if there is one.
-static void handle_foldcolumn(win_T *wp, winlinevars_T *wlv)
+static void draw_foldcolumn(win_T *wp, winlinevars_T *wlv)
{
int fdc = compute_foldcolumn(wp, 0);
- if (fdc <= 0) {
- return;
- }
-
- // Use a separate buffer as `extra_buf` might be in use.
- wlv->n_extra = (int)fill_foldcolumn(fdc_buf, wp, wlv->foldinfo, wlv->lnum,
- &wlv->n_closing);
- fdc_buf[wlv->n_extra] = NUL;
- wlv->p_extra = fdc_buf;
- wlv->c_extra = NUL;
- wlv->c_final = NUL;
- if (use_cursor_line_highlight(wp, wlv->lnum)) {
- wlv->char_attr = win_hl_attr(wp, HLF_CLF);
- } else {
- wlv->char_attr = win_hl_attr(wp, HLF_FC);
+ if (fdc > 0) {
+ int attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLF : HLF_FC);
+ fill_foldcolumn(wp, wlv->foldinfo, wlv->lnum, attr, fdc, &wlv->off, NULL);
}
}
-/// Fills the foldcolumn at "p" for window "wp".
-/// Only to be called when 'foldcolumn' > 0.
-///
-/// @param[out] p Char array to write into
-/// @param lnum Absolute current line number
-/// @param closed Whether it is in 'foldcolumn' mode
+/// Draw the foldcolumn or fill "out_buffer". Assume monocell characters.
///
-/// Assume monocell characters
-/// @return number of chars added to \param p
-size_t fill_foldcolumn(char *p, win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int *n_closing)
+/// @param fdc Current width of the foldcolumn
+/// @param[out] wlv_off Pointer to linebuf offset, incremented for default column
+/// @param[out] out_buffer Char array to fill, only used for 'statuscolumn'
+void fill_foldcolumn(win_T *wp, foldinfo_T foldinfo, linenr_T lnum, int attr, int fdc, int *wlv_off,
+ schar_T *out_buffer)
{
- int i = 0;
- int fdc = compute_foldcolumn(wp, 0); // available cell width
- size_t char_counter = 0;
- int symbol = 0;
- int len = 0;
bool closed = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
- // Init to all spaces.
- memset(p, ' ', MB_MAXCHAR * (size_t)fdc + 1);
-
int level = foldinfo.fi_level;
// If the column is too narrow, we start at the lowest level that
// fits and use numbers to indicate the depth.
- int first_level = level - fdc - closed + 1;
- if (first_level < 1) {
- first_level = 1;
- }
-
- for (i = 0; i < MIN(fdc, level); i++) {
- if (foldinfo.fi_lnum == lnum
- && first_level + i >= foldinfo.fi_low_level) {
+ int first_level = MAX(level - fdc - closed + 1, 1);
+ int closedcol = MIN(fdc, level);
+
+ for (int i = 0; i < fdc; i++) {
+ schar_T symbol = 0;
+ if (i >= level) {
+ symbol = schar_from_ascii(' ');
+ } else if (i == closedcol - 1 && closed) {
+ symbol = wp->w_p_fcs_chars.foldclosed;
+ } else if (foldinfo.fi_lnum == lnum && first_level + i >= foldinfo.fi_low_level) {
symbol = wp->w_p_fcs_chars.foldopen;
} else if (first_level == 1) {
symbol = wp->w_p_fcs_chars.foldsep;
} else if (first_level + i <= 9) {
- symbol = '0' + first_level + i;
+ symbol = schar_from_ascii('0' + first_level + i);
} else {
- symbol = '>';
- }
-
- len = utf_char2bytes(symbol, &p[char_counter]);
- char_counter += (size_t)len;
- if (first_level + i >= level) {
- i++;
- break;
+ symbol = schar_from_ascii('>');
}
- }
- int n_closing_val = i;
-
- if (closed) {
- if (symbol != 0) {
- // rollback previous write
- char_counter -= (size_t)len;
- memset(&p[char_counter], ' ', (size_t)len);
- n_closing_val--;
+ if (out_buffer) {
+ out_buffer[i] = symbol;
+ } else {
+ linebuf_vcol[*wlv_off] = i >= level ? -1 : (i == closedcol - 1 && closed) ? -2 : -3;
+ linebuf_attr[*wlv_off] = attr;
+ linebuf_char[(*wlv_off)++] = symbol;
}
- len = utf_char2bytes(wp->w_p_fcs_chars.foldclosed, &p[char_counter]);
- char_counter += (size_t)len;
- }
-
- if (n_closing) {
- *n_closing = n_closing_val;
}
-
- return MAX(char_counter + (size_t)(fdc - i), (size_t)fdc);
}
/// Get information needed to display the sign in line "wlv->lnum" in window "wp".
/// If "nrcol" is true, the sign is going to be displayed in the number column.
/// Otherwise the sign is going to be displayed in the sign column. If there is no
/// sign, draw blank cells instead.
-static void get_sign_display_info(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx,
- int sign_cul_attr)
+static void draw_sign(bool nrcol, win_T *wp, winlinevars_T *wlv, int sign_idx, int sign_cul_attr)
{
SignTextAttrs sattr = wlv->sattrs[sign_idx];
- wlv->c_final = NUL;
-
- if (sattr.text && wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) {
- size_t fill = nrcol ? (size_t)number_width(wp) - SIGN_WIDTH : 0;
- size_t sign_len = strlen(sattr.text);
-
- // Spaces + sign: " " + ">>" + ' '
- wlv->n_extra = (int)(fill + sign_len + nrcol);
- if (nrcol) {
- memset(wlv->extra, ' ', (size_t)wlv->n_extra);
- }
- memcpy(wlv->extra + fill, sattr.text, sign_len);
- wlv->p_extra = wlv->extra;
- wlv->c_extra = NUL;
- wlv->char_attr = (use_cursor_line_highlight(wp, wlv->lnum) && sign_cul_attr)
- ? sign_cul_attr : sattr.hl_id ? syn_id2attr(sattr.hl_id) : 0;
+
+ if (sattr.text[0] && wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) {
+ int attr = (use_cursor_line_highlight(wp, wlv->lnum) && sign_cul_attr)
+ ? sign_cul_attr : sattr.hl_id ? syn_id2attr(sattr.hl_id) : 0;
+ int fill = nrcol ? number_width(wp) + 1 : SIGN_WIDTH;
+ draw_col_fill(wlv, schar_from_ascii(' '), fill, attr);
+ int sign_pos = wlv->off - SIGN_WIDTH - (int)nrcol;
+ linebuf_char[sign_pos] = sattr.text[0];
+ linebuf_char[sign_pos + 1] = sattr.text[1];
} else {
- wlv->c_extra = ' ';
- wlv->n_extra = nrcol ? number_width(wp) + 1 : SIGN_WIDTH;
- if (!nrcol) {
- wlv->char_attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC);
- }
+ assert(!nrcol); // handled in draw_lnum_col()
+ int attr = win_hl_attr(wp, use_cursor_line_highlight(wp, wlv->lnum) ? HLF_CLS : HLF_SC);
+ draw_col_fill(wlv, schar_from_ascii(' '), SIGN_WIDTH, attr);
}
}
@@ -556,7 +540,7 @@ static int get_line_number_attr(win_T *wp, winlinevars_T *wlv)
/// Display the absolute or relative line number. After the first row fill with
/// blanks when the 'n' flag isn't in 'cpo'.
-static void handle_lnum_col(win_T *wp, winlinevars_T *wlv, int sign_num_attr, int sign_cul_attr)
+static void draw_lnum_col(win_T *wp, winlinevars_T *wlv, int sign_num_attr, int sign_cul_attr)
{
bool has_cpo_n = vim_strchr(p_cpo, CPO_NUMCOL) != NULL;
@@ -567,221 +551,186 @@ static void handle_lnum_col(win_T *wp, winlinevars_T *wlv, int sign_num_attr, in
&& !((has_cpo_n && !wp->w_p_bri) && wp->w_skipcol > 0 && wlv->lnum == wp->w_topline)) {
// If 'signcolumn' is set to 'number' and a sign is present in "lnum",
// then display the sign instead of the line number.
- if (wp->w_minscwidth == SCL_NUM && wlv->sattrs[0].text) {
- get_sign_display_info(true, wp, wlv, 0, sign_cul_attr);
+ if (wp->w_minscwidth == SCL_NUM && wlv->sattrs[0].text[0]
+ && wlv->row == wlv->startrow + wlv->filler_lines && wlv->filler_todo <= 0) {
+ draw_sign(true, wp, wlv, 0, sign_cul_attr);
} else {
// Draw the line number (empty space after wrapping).
+ int width = number_width(wp) + 1;
+ int attr = (sign_num_attr > 0 && wlv->filler_todo <= 0)
+ ? sign_num_attr : get_line_number_attr(wp, wlv);
if (wlv->row == wlv->startrow + wlv->filler_lines
&& (wp->w_skipcol == 0 || wlv->row > 0 || (wp->w_p_nu && wp->w_p_rnu))) {
- get_line_number_str(wp, wlv->lnum, wlv->extra, sizeof(wlv->extra));
+ char buf[32];
+ get_line_number_str(wp, wlv->lnum, buf, sizeof(buf));
if (wp->w_skipcol > 0 && wlv->startrow == 0) {
- for (wlv->p_extra = wlv->extra; *wlv->p_extra == ' '; wlv->p_extra++) {
- *wlv->p_extra = '-';
+ for (char *c = buf; *c == ' '; c++) {
+ *c = '-';
}
}
if (wp->w_p_rl) { // reverse line numbers
- char *num = skipwhite(wlv->extra);
+ char *num = skipwhite(buf);
rl_mirror_ascii(num, skiptowhite(num));
}
- wlv->p_extra = wlv->extra;
- wlv->c_extra = NUL;
- } else {
- wlv->c_extra = ' ';
- }
- wlv->c_final = NUL;
- wlv->n_extra = number_width(wp) + 1;
- if (sign_num_attr > 0) {
- wlv->char_attr = sign_num_attr;
+ draw_col_buf(wp, wlv, buf, (size_t)width, attr, false);
} else {
- wlv->char_attr = get_line_number_attr(wp, wlv);
+ draw_col_fill(wlv, schar_from_ascii(' '), width, attr);
}
}
}
}
-/// Prepare and build the 'statuscolumn' string for line "lnum" in window "wp".
-/// Fill "stcp" with the built status column string and attributes.
-/// This can be called three times per win_line(), once for virt_lines, once for
-/// the start of the buffer line "lnum" and once for the wrapped lines.
-///
-/// @param[out] stcp Status column attributes
-static void get_statuscol_str(win_T *wp, linenr_T lnum, int virtnum, statuscol_T *stcp)
+/// Build and draw the 'statuscolumn' string for line "lnum" in window "wp".
+static void draw_statuscol(win_T *wp, winlinevars_T *wlv, linenr_T lnum, int virtnum, int col_rows,
+ statuscol_T *stcp)
{
// When called for the first non-filler row of line "lnum" set num v:vars
linenr_T relnum = virtnum == 0 ? abs(get_cursor_rel_lnum(wp, lnum)) : -1;
+ char buf[MAXPATHL];
// When a buffer's line count has changed, make a best estimate for the full
// width of the status column by building with "w_nrwidth_line_count". Add
// potentially truncated width and rebuild before drawing anything.
if (wp->w_statuscol_line_count != wp->w_nrwidth_line_count) {
wp->w_statuscol_line_count = wp->w_nrwidth_line_count;
set_vim_var_nr(VV_VIRTNUM, 0);
- build_statuscol_str(wp, wp->w_nrwidth_line_count, 0, stcp);
- if (stcp->truncate > 0) {
- // Add truncated width to avoid unnecessary redraws
- int addwidth = MIN(stcp->truncate, MAX_NUMBERWIDTH - wp->w_nrwidth);
- stcp->truncate = 0;
- stcp->width += addwidth;
+ int width = build_statuscol_str(wp, wp->w_nrwidth_line_count, 0, buf, stcp);
+ if (width > stcp->width) {
+ int addwidth = MIN(width - stcp->width, MAX_STCWIDTH - stcp->width);
wp->w_nrwidth += addwidth;
wp->w_nrwidth_width = wp->w_nrwidth;
+ if (col_rows > 0) {
+ // If only column is being redrawn, we now need to redraw the text as well
+ wp->w_redr_statuscol = true;
+ return;
+ }
+ stcp->width += addwidth;
wp->w_valid &= ~VALID_WCOL;
}
}
set_vim_var_nr(VV_VIRTNUM, virtnum);
- int width = build_statuscol_str(wp, lnum, relnum, stcp);
+ int width = build_statuscol_str(wp, lnum, relnum, buf, stcp);
// Force a redraw in case of error or when truncated
- if (*wp->w_p_stc == NUL || (stcp->truncate > 0 && wp->w_nrwidth < MAX_NUMBERWIDTH)) {
- if (stcp->truncate > 0) { // Avoid truncating 'statuscolumn'
- wp->w_nrwidth = MIN(MAX_NUMBERWIDTH, wp->w_nrwidth + stcp->truncate);
- wp->w_nrwidth_width = wp->w_nrwidth;
- } else { // 'statuscolumn' reset due to error
+ if (*wp->w_p_stc == NUL || (width > stcp->width && stcp->width < MAX_STCWIDTH)) {
+ if (*wp->w_p_stc == NUL) { // 'statuscolumn' reset due to error
wp->w_nrwidth_line_count = 0;
wp->w_nrwidth = (wp->w_p_nu || wp->w_p_rnu) * number_width(wp);
+ } else { // Avoid truncating 'statuscolumn'
+ wp->w_nrwidth += MIN(width - stcp->width, MAX_STCWIDTH - stcp->width);
+ wp->w_nrwidth_width = wp->w_nrwidth;
}
wp->w_redr_statuscol = true;
return;
}
- // Reset text/highlight pointer and current attr for new line
- stcp->textp = stcp->text;
- stcp->hlrecp = stcp->hlrec;
- stcp->cur_attr = stcp->num_attr;
- stcp->text_end = stcp->text + strlen(stcp->text);
-
- int fill = stcp->width - width;
- if (fill > 0) {
- // Fill up with ' '
- memset(stcp->text_end, ' ', (size_t)fill);
- *(stcp->text_end += fill) = NUL;
- }
-}
-
-/// Get information needed to display the next segment in the 'statuscolumn'.
-/// If not yet at the end, prepare for next segment and decrement "wlv->draw_state".
-///
-/// @param stcp Status column attributes
-/// @param[in,out] wlv
-static void get_statuscol_display_info(statuscol_T *stcp, winlinevars_T *wlv)
-{
- wlv->c_extra = NUL;
- wlv->c_final = NUL;
- do {
- wlv->draw_state = WL_STC;
- wlv->char_attr = stcp->cur_attr;
- wlv->p_extra = stcp->textp;
- char *const section_end = stcp->hlrecp->start ? stcp->hlrecp->start : stcp->text_end;
- wlv->n_extra = (int)(section_end - stcp->textp);
- // Prepare for next highlight section if not yet at the end
- if (section_end < stcp->text_end) {
- int hl = stcp->hlrecp->userhl;
- stcp->textp = stcp->hlrecp->start;
- stcp->cur_attr = hl < 0 ? syn_id2attr(-hl) : stcp->num_attr;
- stcp->hlrecp++;
- wlv->draw_state = WL_STC - 1;
- }
- // Skip over empty highlight sections
- } while (wlv->n_extra == 0 && stcp->textp < stcp->text_end);
- if (wlv->n_extra > 0) {
- static char transbuf[(MAX_NUMBERWIDTH + 9 + 9 * 2) * MB_MAXBYTES + 1];
- wlv->n_extra = (int)transstr_buf(wlv->p_extra, wlv->n_extra, transbuf, sizeof transbuf, true);
- wlv->p_extra = transbuf;
+ char *p = buf;
+ char transbuf[MAXPATHL];
+ int attr = stcp->num_attr;
+ size_t len = strlen(buf);
+
+ // Draw each segment with the specified highlighting.
+ for (stl_hlrec_t *sp = stcp->hlrec; sp->start != NULL; sp++) {
+ ptrdiff_t textlen = sp->start - p;
+ // Make all characters printable.
+ size_t translen = transstr_buf(p, textlen, transbuf, MAXPATHL, true);
+ draw_col_buf(wp, wlv, transbuf, translen, attr, false);
+ p = sp->start;
+ int hl = sp->userhl;
+ attr = hl < 0 ? syn_id2attr(-hl) : stcp->num_attr;
}
+ size_t translen = transstr_buf(p, buf + len - p, transbuf, MAXPATHL, true);
+ draw_col_buf(wp, wlv, transbuf, translen, attr, false);
+ draw_col_fill(wlv, schar_from_ascii(' '), stcp->width - width, stcp->num_attr);
}
static void handle_breakindent(win_T *wp, winlinevars_T *wlv)
{
- if (wp->w_briopt_sbr && wlv->draw_state == WL_BRI - 1
- && *get_showbreak_value(wp) != NUL) {
- // draw indent after showbreak value
- wlv->draw_state = WL_BRI;
- } else if (wp->w_briopt_sbr && wlv->draw_state == WL_SBR) {
- // after the showbreak, draw the breakindent
- wlv->draw_state = WL_BRI - 1;
- }
-
// draw 'breakindent': indent wrapped text accordingly
- if (wlv->draw_state == WL_BRI - 1 && wlv->n_extra == 0) {
- wlv->draw_state = WL_BRI;
- // if wlv->need_showbreak is set, breakindent also applies
- if (wp->w_p_bri && (wlv->row != wlv->startrow || wlv->need_showbreak)
- && wlv->filler_lines == 0) {
- wlv->char_attr = 0;
- if (wlv->diff_hlf != (hlf_T)0) {
- wlv->char_attr = win_hl_attr(wp, (int)wlv->diff_hlf);
- }
- wlv->p_extra = NULL;
- wlv->c_extra = ' ';
- wlv->c_final = NUL;
- wlv->n_extra = get_breakindent_win(wp, ml_get_buf(wp->w_buffer, wlv->lnum));
- if (wlv->row == wlv->startrow) {
- wlv->n_extra -= win_col_off2(wp);
- if (wlv->n_extra < 0) {
- wlv->n_extra = 0;
- }
- }
- if (wp->w_skipcol > 0 && wlv->startrow == 0 && wp->w_p_wrap && wp->w_briopt_sbr) {
- wlv->need_showbreak = false;
+ // if wlv->need_showbreak is set, breakindent also applies
+ if (wp->w_p_bri && (wlv->row > wlv->startrow + wlv->filler_lines
+ || wlv->need_showbreak)) {
+ int attr = 0;
+ if (wlv->diff_hlf != (hlf_T)0) {
+ attr = win_hl_attr(wp, (int)wlv->diff_hlf);
+ }
+ int num = get_breakindent_win(wp, ml_get_buf(wp->w_buffer, wlv->lnum));
+ if (wlv->row == wlv->startrow) {
+ num -= win_col_off2(wp);
+ if (wlv->n_extra < 0) {
+ num = 0;
}
- // Correct end of highlighted area for 'breakindent',
- // required wen 'linebreak' is also set.
- if (wlv->tocol == wlv->vcol) {
- wlv->tocol += wlv->n_extra;
+ }
+
+ colnr_T vcol_before = wlv->vcol;
+
+ for (int i = 0; i < num; i++) {
+ linebuf_char[wlv->off] = schar_from_ascii(' ');
+
+ advance_color_col(wlv, wlv->vcol);
+ int myattr = attr;
+ if (wlv->color_cols && wlv->vcol == *wlv->color_cols) {
+ myattr = hl_combine_attr(win_hl_attr(wp, HLF_MC), myattr);
}
+ linebuf_attr[wlv->off] = myattr;
+ linebuf_vcol[wlv->off] = wlv->vcol++; // These are vcols, sorry I don't make the rules
+ wlv->off++;
}
+
+ // Correct start of highlighted area for 'breakindent',
+ if (wlv->fromcol >= vcol_before && wlv->fromcol < wlv->vcol) {
+ wlv->fromcol = wlv->vcol;
+ }
+
+ // Correct end of highlighted area for 'breakindent',
+ // required wen 'linebreak' is also set.
+ if (wlv->tocol == vcol_before) {
+ wlv->tocol = wlv->vcol;
+ }
+ }
+
+ if (wp->w_skipcol > 0 && wlv->startrow == 0 && wp->w_p_wrap && wp->w_briopt_sbr) {
+ wlv->need_showbreak = false;
}
}
static void handle_showbreak_and_filler(win_T *wp, winlinevars_T *wlv)
{
+ int remaining = wp->w_grid.cols - wlv->off;
if (wlv->filler_todo > wlv->filler_lines - wlv->n_virt_lines) {
// TODO(bfredl): check this doesn't inhibit TUI-style
// clear-to-end-of-line.
- wlv->c_extra = ' ';
- wlv->c_final = NUL;
- wlv->n_extra = wp->w_grid.cols - wlv->col;
- wlv->char_attr = 0;
+ draw_col_fill(wlv, schar_from_ascii(' '), remaining, 0);
} else if (wlv->filler_todo > 0) {
// Draw "deleted" diff line(s)
- if (char2cells(wp->w_p_fcs_chars.diff) > 1) {
- wlv->c_extra = '-';
- wlv->c_final = NUL;
- } else {
- wlv->c_extra = wp->w_p_fcs_chars.diff;
- wlv->c_final = NUL;
- }
- wlv->n_extra = wp->w_grid.cols - wlv->col;
- wlv->char_attr = win_hl_attr(wp, HLF_DED);
+ schar_T c = wp->w_p_fcs_chars.diff;
+ draw_col_fill(wlv, c, remaining, win_hl_attr(wp, HLF_DED));
}
char *const sbr = get_showbreak_value(wp);
if (*sbr != NUL && wlv->need_showbreak) {
// Draw 'showbreak' at the start of each broken line.
- wlv->p_extra = sbr;
- wlv->c_extra = NUL;
- wlv->c_final = NUL;
- wlv->n_extra = (int)strlen(sbr);
- wlv->char_attr = win_hl_attr(wp, HLF_AT);
- if (wp->w_skipcol == 0 || wlv->startrow != 0 || !wp->w_p_wrap) {
- wlv->need_showbreak = false;
- }
- wlv->vcol_sbr = wlv->vcol + mb_charlen(sbr);
+ // Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'.
+ int attr = hl_combine_attr(wlv->cul_attr, win_hl_attr(wp, HLF_AT));
+ colnr_T vcol_before = wlv->vcol;
+ draw_col_buf(wp, wlv, sbr, strlen(sbr), attr, true);
+ wlv->vcol_sbr = wlv->vcol;
// Correct start of highlighted area for 'showbreak'.
- if (wlv->fromcol >= wlv->vcol && wlv->fromcol < wlv->vcol_sbr) {
- wlv->fromcol = wlv->vcol_sbr;
+ if (wlv->fromcol >= vcol_before && wlv->fromcol < wlv->vcol) {
+ wlv->fromcol = wlv->vcol;
}
// Correct end of highlighted area for 'showbreak',
// required when 'linebreak' is also set.
- if (wlv->tocol == wlv->vcol) {
- wlv->tocol += wlv->n_extra;
- }
- // Combine 'showbreak' with 'cursorline', prioritizing 'showbreak'.
- if (wlv->cul_attr) {
- wlv->char_attr = hl_combine_attr(wlv->cul_attr, wlv->char_attr);
+ if (wlv->tocol == vcol_before) {
+ wlv->tocol = wlv->vcol;
}
}
+
+ if (wp->w_skipcol == 0 || wlv->startrow > 0 || !wp->w_p_wrap || !wp->w_briopt_sbr) {
+ wlv->need_showbreak = false;
+ }
}
static void apply_cursorline_highlight(win_T *wp, winlinevars_T *wlv)
@@ -825,7 +774,7 @@ static bool has_more_inline_virt(winlinevars_T *wlv, ptrdiff_t v)
return false;
}
-static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t v)
+static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t v, bool selected)
{
while (wlv->n_extra == 0) {
if (wlv->virt_inline_i >= kv_size(wlv->virt_inline)) {
@@ -835,6 +784,11 @@ static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t
DecorState *state = &decor_state;
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange *item = &kv_A(state->active, i);
+ if (item->draw_col == -3) {
+ // No more inline virtual text before this non-inline virtual text item,
+ // so its position can be decided now.
+ decor_init_draw_col(wlv->off, selected, item);
+ }
if (item->start_row != state->row
|| item->kind != kDecorKindVirtText
|| item->data.vt->pos != kVPosInline
@@ -864,8 +818,8 @@ static void handle_inline_virtual_text(win_T *wp, winlinevars_T *wlv, ptrdiff_t
if (wlv->n_extra == 0) {
continue;
}
- wlv->c_extra = NUL;
- wlv->c_final = NUL;
+ wlv->sc_extra = NUL;
+ wlv->sc_final = NUL;
wlv->extra_attr = attr;
wlv->n_attr = mb_charlen(text);
// If the text didn't reach until the first window
@@ -937,42 +891,46 @@ static colnr_T get_leadcol(win_T *wp, const char *ptr, const char *line)
}
/// Start a screen line at column zero.
-static void win_line_start(win_T *wp, winlinevars_T *wlv, bool save_extra)
+static void win_line_start(win_T *wp, winlinevars_T *wlv)
{
wlv->col = 0;
wlv->off = 0;
wlv->need_lbr = false;
-
- if (save_extra) {
- // reset the drawing state for the start of a wrapped line
- 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->need_lbr = true;
- wlv->saved_char_attr = wlv->char_attr;
-
- wlv->n_extra = 0;
+ for (int i = 0; i < wp->w_grid.cols; i++) {
+ linebuf_char[i] = schar_from_ascii(' ');
+ linebuf_attr[i] = -1;
+ linebuf_vcol[i] = -1;
}
}
-/// Called when wlv->draw_state is set to WL_LINE.
-static void win_line_continue(winlinevars_T *wlv)
+static void fix_for_boguscols(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->c_extra = wlv->saved_c_extra;
- wlv->c_final = wlv->saved_c_final;
- wlv->p_extra = wlv->saved_p_extra;
- wlv->extra_for_extmark = wlv->saved_extra_for_extmark;
- wlv->char_attr = wlv->saved_char_attr;
- } else {
- wlv->char_attr = 0;
+ wlv->n_extra += wlv->vcol_off;
+ wlv->vcol -= wlv->vcol_off;
+ wlv->vcol_off = 0;
+ wlv->col -= wlv->boguscols;
+ wlv->old_boguscols = wlv->boguscols;
+ wlv->boguscols = 0;
+}
+
+static int get_rightmost_vcol(win_T *wp, const int *color_cols)
+{
+ int ret = 0;
+
+ if (wp->w_p_cuc) {
+ ret = wp->w_virtcol;
}
+
+ if (color_cols) {
+ // determine rightmost colorcolumn to possibly draw
+ for (int i = 0; color_cols[i] >= 0; i++) {
+ if (ret < color_cols[i]) {
+ ret = color_cols[i];
+ }
+ }
+ }
+
+ return ret;
}
/// Display line "lnum" of window "wp" on the screen.
@@ -981,7 +939,8 @@ 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 number_only only update the number column
+/// @param col_rows set to the height of the line when only updating the columns,
+/// otherwise set to 0
/// @param spv 'spell' related variables kept between calls for "wp"
/// @param foldinfo fold info for this line
/// @param[in, out] providers decoration providers active this line
@@ -989,19 +948,17 @@ 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 number_only, spellvars_T *spv,
- foldinfo_T foldinfo, DecorProviders *providers)
+int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, spellvars_T *spv,
+ foldinfo_T foldinfo)
{
- winlinevars_T wlv; // variables passed between functions
-
colnr_T vcol_prev = -1; // "wlv.vcol" of previous character
- char *line; // current line
- char *ptr; // current position in "line"
ScreenGrid *grid = &wp->w_grid; // grid specific to the window
- static char *at_end_str = ""; // used for p_extra when displaying curwin->w_p_lcs_chars.eol
- // at end-of-line
const bool has_fold = foldinfo.fi_level != 0 && foldinfo.fi_lines > 0;
+ const bool has_foldtext = has_fold && *wp->w_p_fdt != NUL;
+
+ const bool is_wrapped = wp->w_p_wrap
+ && !has_fold; // Never wrap folded lines
int saved_attr2 = 0; // char_attr saved for n_attr
int n_attr3 = 0; // chars with overruling special attr
@@ -1010,8 +967,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
int fromcol_prev = -2; // start of inverting after cursor
bool noinvcur = false; // don't invert the cursor
bool lnum_in_visual_area = false;
- pos_T pos;
- ptrdiff_t v;
bool attr_pri = false; // char_attr has priority
bool area_highlighting = false; // Visual or incsearch highlighting in this line
@@ -1022,10 +977,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
int decor_attr = 0; // attributes desired by syntax and extmarks
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
- int *color_cols = NULL; // pointer to according columns array
#define SPWORDLEN 150
char nextline[SPWORDLEN * 2]; // text with start of the next line
int nextlinecol = 0; // column where nextline[] starts
@@ -1034,17 +986,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
int spell_attr = 0; // attributes desired by spelling
int word_end = 0; // last byte with same spell_attr
int cur_checked_col = 0; // checked column for current line
- int extra_check = 0; // has syntax or linebreak
+ bool extra_check = 0; // has syntax or linebreak
int multi_attr = 0; // attributes desired by multibyte
int mb_l = 1; // multi-byte byte length
int mb_c = 0; // decoded multi-byte character
- schar_T mb_schar; // complete screen char
+ schar_T mb_schar = 0; // complete screen char
int change_start = MAXCOL; // first col of changed area
int change_end = -1; // last col of changed area
bool in_multispace = false; // in multiple consecutive spaces
int multispace_pos = 0; // position in lcs-multispace string
- int line_attr_save;
- int line_attr_lowprio_save;
bool search_attr_from_match = false; // if search_attr is from :match
bool has_decor = false; // this buffer has decoration
@@ -1076,43 +1026,35 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
int prev_syntax_id = 0;
int conceal_attr = win_hl_attr(wp, HLF_CONCEAL);
bool is_concealing = false;
- int did_wcol = false;
- int old_boguscols = 0;
-#define VCOL_HLC (wlv.vcol - wlv.vcol_off)
-#define FIX_FOR_BOGUSCOLS \
- { \
- wlv.n_extra += wlv.vcol_off; \
- wlv.vcol -= wlv.vcol_off; \
- wlv.vcol_off = 0; \
- wlv.col -= wlv.boguscols; \
- old_boguscols = wlv.boguscols; \
- wlv.boguscols = 0; \
- }
+ bool did_wcol = false;
+#define vcol_hlc(wlv) ((wlv).vcol - (wlv).vcol_off)
assert(startrow < endrow);
- CLEAR_FIELD(wlv);
-
- wlv.lnum = lnum;
- wlv.foldinfo = foldinfo;
- wlv.startrow = startrow;
- wlv.row = startrow;
- wlv.fromcol = -10;
- wlv.tocol = MAXCOL;
- wlv.vcol_sbr = -1;
+ // variables passed between functions
+ winlinevars_T wlv = {
+ .lnum = lnum,
+ .foldinfo = foldinfo,
+ .startrow = startrow,
+ .row = startrow,
+ .fromcol = -10,
+ .tocol = MAXCOL,
+ .vcol_sbr = -1,
+ .old_boguscols = 0,
+ };
buf_T *buf = wp->w_buffer;
const bool end_fill = (lnum == buf->b_ml.ml_line_count + 1);
- if (!number_only) {
+ if (col_rows == 0) {
// To speed up the loop below, set extra_check when there is linebreak,
// trailing white space and/or syntax processing to be done.
extra_check = wp->w_p_lbr;
if (syntax_present(wp) && !wp->w_s->b_syn_error && !wp->w_s->b_syn_slow
- && !has_fold && !end_fill) {
+ && !has_foldtext && !end_fill) {
// Prepare for syntax highlighting in this line. When there is an
// error, stop syntax highlighting.
- save_did_emsg = did_emsg;
+ int save_did_emsg = did_emsg;
did_emsg = false;
syntax_start(wp, lnum);
if (did_emsg) {
@@ -1128,17 +1070,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
has_decor = decor_redraw_line(wp, lnum - 1, &decor_state);
- decor_providers_invoke_line(wp, providers, lnum - 1, &has_decor);
+ decor_providers_invoke_line(wp, lnum - 1, &has_decor);
if (has_decor) {
extra_check = true;
}
// Check for columns to display for 'colorcolumn'.
- color_cols = wp->w_buffer->terminal ? NULL : wp->w_p_cc_cols;
- if (color_cols != NULL) {
- draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
- }
+ wlv.color_cols = wp->w_buffer->terminal ? NULL : wp->w_p_cc_cols;
+ advance_color_col(&wlv, vcol_hlc(wlv));
// handle Visual active in this window
if (VIsual_active && wp->w_buffer == curwin->w_buffer) {
@@ -1182,7 +1122,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
} else if (bot->col == MAXCOL) {
wlv.tocol = MAXCOL;
} else {
- pos = *bot;
+ pos_T pos = *bot;
if (*p_sel == 'e') {
getvvcol(wp, &pos, (colnr_T *)&wlv.tocol, NULL, NULL);
} else {
@@ -1207,7 +1147,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// handle 'incsearch' and ":s///c" highlighting
} else if (highlight_match
&& wp == curwin
- && !has_fold
+ && !has_foldtext
&& lnum >= curwin->w_cursor.lnum
&& lnum <= curwin->w_cursor.lnum + search_match_lines) {
if (lnum == curwin->w_cursor.lnum) {
@@ -1217,8 +1157,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
wlv.fromcol = 0;
}
if (lnum == curwin->w_cursor.lnum + search_match_lines) {
- pos.lnum = lnum;
- pos.col = search_match_endcol;
+ pos_T pos = {
+ .lnum = lnum,
+ .col = search_match_endcol,
+ };
getvcol(curwin, &pos, (colnr_T *)&wlv.tocol, NULL, NULL);
}
// do at least one character; happens when past end of line
@@ -1265,7 +1207,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// Do not show the cursor line in the text when Visual mode is active,
// because it's not clear what is selected then.
&& !(wp == curwin && VIsual_active)) {
- cul_screenline = (wp->w_p_wrap && (wp->w_p_culopt_flags & CULOPT_SCRLINE));
+ cul_screenline = (is_wrapped && (wp->w_p_culopt_flags & CULOPT_SCRLINE));
if (!cul_screenline) {
apply_cursorline_highlight(wp, &wlv);
} else {
@@ -1286,7 +1228,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
statuscol.draw = true;
statuscol.sattrs = wlv.sattrs;
statuscol.foldinfo = foldinfo;
- statuscol.width = win_col_off(wp) - (cmdwin_type != 0 && wp == curwin);
+ statuscol.width = win_col_off(wp) - (wp == cmdwin_win);
statuscol.use_cul = use_cursor_line_highlight(wp, lnum);
statuscol.sign_cul_id = statuscol.use_cul ? sign_cul_attr : 0;
statuscol.num_attr = sign_num_attr > 0 ? syn_id2attr(sign_num_attr) : 0;
@@ -1311,12 +1253,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
area_highlighting = true;
}
- if (cul_screenline) {
- line_attr_save = wlv.line_attr;
- line_attr_lowprio_save = wlv.line_attr_lowprio;
- }
+ int line_attr_save = wlv.line_attr;
+ int line_attr_lowprio_save = wlv.line_attr_lowprio;
- if (spv->spv_has_spell && !number_only) {
+ if (spv->spv_has_spell && col_rows == 0) {
// Prepare for spell checking.
extra_check = true;
@@ -1339,14 +1279,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// Trick: skip a few chars for C/shell/Vim comments
nextline[SPWORDLEN] = NUL;
if (lnum < wp->w_buffer->b_ml.ml_line_count) {
- line = ml_get_buf(wp->w_buffer, lnum + 1);
+ char *line = ml_get_buf(wp->w_buffer, lnum + 1);
spell_cat_line(nextline + SPWORDLEN, line, SPWORDLEN);
}
assert(!end_fill);
- line = ml_get_buf(wp->w_buffer, lnum);
+ char *line = ml_get_buf(wp->w_buffer, lnum);
// If current line is empty, check first word in next line for capital.
- ptr = skipwhite(line);
+ char *ptr = skipwhite(line);
if (*ptr == NUL) {
spv->spv_cap_col = 0;
spv->spv_capcol_lnum = lnum + 1;
@@ -1361,33 +1301,36 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
nextlinecol = MAXCOL;
nextline_idx = 0;
} else {
- v = (ptrdiff_t)strlen(line);
- if (v < SPWORDLEN) {
+ const size_t line_len = strlen(line);
+ if (line_len < SPWORDLEN) {
// Short line, use it completely and append the start of the
// next line.
nextlinecol = 0;
- memmove(nextline, line, (size_t)v);
- STRMOVE(nextline + v, nextline + SPWORDLEN);
- nextline_idx = (int)v + 1;
+ memmove(nextline, line, line_len);
+ STRMOVE(nextline + line_len, nextline + SPWORDLEN);
+ nextline_idx = (int)line_len + 1;
} else {
// Long line, use only the last SPWORDLEN bytes.
- nextlinecol = (int)v - SPWORDLEN;
+ nextlinecol = (int)line_len - SPWORDLEN;
memmove(nextline, line + nextlinecol, SPWORDLEN);
nextline_idx = SPWORDLEN + 1;
}
}
}
- line = end_fill ? "" : ml_get_buf(wp->w_buffer, lnum);
- ptr = line;
+ // current line
+ char *line = end_fill ? "" : ml_get_buf(wp->w_buffer, lnum);
+ // current position in "line"
+ char *ptr = line;
colnr_T trailcol = MAXCOL; // start of trailing spaces
colnr_T leadcol = 0; // start of leading spaces
- int lcs_eol_one = wp->w_p_lcs_chars.eol; // 'eol' until it's been used
- int lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used
+ bool lcs_eol_todo = true; // need to keep track of this even if lcs_eol is NUL
+ const schar_T lcs_eol = wp->w_p_lcs_chars.eol; // 'eol' value
+ schar_T lcs_prec_todo = wp->w_p_lcs_chars.prec; // 'prec' until it's been used, then NUL
- if (wp->w_p_list && !has_fold && !end_fill) {
+ if (wp->w_p_list && !has_foldtext && !end_fill) {
if (wp->w_p_lcs_chars.space
|| wp->w_p_lcs_chars.multispace != NULL
|| wp->w_p_lcs_chars.leadmultispace != NULL
@@ -1402,37 +1345,36 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// 'nowrap' or 'wrap' and a single line that doesn't fit: Advance to the
// first character to be displayed.
- if (wp->w_p_wrap) {
- v = startrow == 0 ? wp->w_skipcol : 0;
- } else {
- v = wp->w_leftcol;
- }
- if (v > 0 && !number_only) {
+ const int start_col = wp->w_p_wrap
+ ? (startrow == 0 ? wp->w_skipcol : 0)
+ : wp->w_leftcol;
+
+ if (start_col > 0 && col_rows == 0) {
char *prev_ptr = ptr;
- chartabsize_T cts;
- int charsize = 0;
- int head = 0;
-
- init_chartabsize_arg(&cts, wp, lnum, wlv.vcol, line, ptr);
- cts.cts_max_head_vcol = (int)v;
- while (cts.cts_vcol < v && *cts.cts_ptr != NUL) {
- head = 0;
- charsize = win_lbr_chartabsize(&cts, &head);
- cts.cts_vcol += charsize;
- prev_ptr = cts.cts_ptr;
- MB_PTR_ADV(cts.cts_ptr);
+ CharSize cs = { 0 };
+
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, wp, lnum, line);
+ csarg.max_head_vcol = start_col;
+ int vcol = wlv.vcol;
+ StrCharInfo ci = utf_ptr2StrCharInfo(ptr);
+ while (vcol < start_col && *ci.ptr != NUL) {
+ cs = win_charsize(cstype, vcol, ci.ptr, ci.chr.value, &csarg);
+ vcol += cs.width;
+ prev_ptr = ci.ptr;
+ ci = utfc_next(ci);
if (wp->w_p_list) {
- in_multispace = *prev_ptr == ' ' && (*cts.cts_ptr == ' '
+ in_multispace = *prev_ptr == ' ' && (*ci.ptr == ' '
|| (prev_ptr > line && prev_ptr[-1] == ' '));
if (!in_multispace) {
multispace_pos = 0;
- } else if (cts.cts_ptr >= line + leadcol
+ } else if (ci.ptr >= line + leadcol
&& wp->w_p_lcs_chars.multispace != NULL) {
multispace_pos++;
if (wp->w_p_lcs_chars.multispace[multispace_pos] == NUL) {
multispace_pos = 0;
}
- } else if (cts.cts_ptr < line + leadcol
+ } else if (ci.ptr < line + leadcol
&& wp->w_p_lcs_chars.leadmultispace != NULL) {
multispace_pos++;
if (wp->w_p_lcs_chars.leadmultispace[multispace_pos] == NUL) {
@@ -1441,9 +1383,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
}
}
- wlv.vcol = cts.cts_vcol;
- ptr = cts.cts_ptr;
- clear_chartabsize_arg(&cts);
+ wlv.vcol = vcol;
+ ptr = ci.ptr;
+ int charsize = cs.width;
+ int head = cs.head;
// When:
// - 'cuc' is set, or
@@ -1451,22 +1394,22 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// - 'virtualedit' is set, or
// - the visual mode is active,
// the end of the line may be before the start of the displayed part.
- if (wlv.vcol < v && (wp->w_p_cuc
- || draw_color_col
- || virtual_active()
- || (VIsual_active && wp->w_buffer == curwin->w_buffer))) {
- wlv.vcol = (colnr_T)v;
+ if (wlv.vcol < start_col && (wp->w_p_cuc
+ || wlv.color_cols
+ || virtual_active()
+ || (VIsual_active && wp->w_buffer == curwin->w_buffer))) {
+ wlv.vcol = start_col;
}
// Handle a character that's not completely on the screen: Put ptr at
// that character but skip the first few screen characters.
- if (wlv.vcol > v) {
+ if (wlv.vcol > start_col) {
wlv.vcol -= charsize;
ptr = prev_ptr;
}
- if (v > wlv.vcol) {
- wlv.skip_cells = (int)v - wlv.vcol - head;
+ if (start_col > wlv.vcol) {
+ wlv.skip_cells = start_col - wlv.vcol - head;
}
// Adjust for when the inverted text is before the screen,
@@ -1484,14 +1427,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// When spell checking a word we need to figure out the start of the
// word and if it's badly spelled or not.
if (spv->spv_has_spell) {
- size_t len;
colnr_T linecol = (colnr_T)(ptr - line);
hlf_T spell_hlf = HLF_COUNT;
- pos = wp->w_cursor;
+ pos_T pos = wp->w_cursor;
wp->w_cursor.lnum = lnum;
wp->w_cursor.col = linecol;
- len = spell_move_to(wp, FORWARD, true, true, &spell_hlf);
+ size_t len = spell_move_to(wp, FORWARD, true, true, &spell_hlf);
// spell_move_to() may call ml_get() and make "line" invalid
line = ml_get_buf(wp->w_buffer, lnum);
@@ -1540,15 +1482,17 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
}
- if (!number_only && !has_fold && !end_fill) {
- v = ptr - line;
- area_highlighting |= prepare_search_hl_line(wp, lnum, (colnr_T)v,
+ if (col_rows == 0 && !has_foldtext && !end_fill) {
+ const int v = (int)(ptr - line);
+ area_highlighting |= prepare_search_hl_line(wp, lnum, v,
&line, &screen_search_hl, &search_attr,
&search_attr_from_match);
ptr = line + v; // "line" may have been updated
}
- win_line_start(wp, &wlv, false);
+ win_line_start(wp, &wlv);
+ bool draw_cols = true;
+ int leftcols_width = 0;
// won't highlight after TERM_ATTRS_MAX columns
int term_attrs[TERM_ATTRS_MAX] = { 0 };
@@ -1557,7 +1501,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
extra_check = true;
}
- int sign_idx = 0;
+ const bool may_have_inline_virt
+ = !has_foldtext && buf_meta_total(wp->w_buffer, kMTMetaInline) > 0;
int virt_line_index;
int virt_line_offset = -1;
// Repeat for the whole displayed line.
@@ -1568,129 +1513,116 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
bool did_decrement_ptr = false;
// Skip this quickly when working on the text.
- if (wlv.draw_state != WL_LINE) {
+ if (draw_cols) {
if (cul_screenline) {
wlv.cul_attr = 0;
wlv.line_attr = line_attr_save;
wlv.line_attr_lowprio = line_attr_lowprio_save;
}
- if (wlv.draw_state == WL_CMDLINE - 1 && wlv.n_extra == 0) {
- wlv.draw_state = WL_CMDLINE;
- if (cmdwin_type != 0 && wp == curwin) {
- // Draw the cmdline character.
- wlv.n_extra = 1;
- wlv.c_extra = cmdwin_type;
- wlv.c_final = NUL;
- wlv.char_attr = win_hl_attr(wp, HLF_AT);
- }
+ assert(wlv.off == 0);
+
+ if (wp == cmdwin_win) {
+ // Draw the cmdline character.
+ draw_col_fill(&wlv, schar_from_ascii(cmdwin_type), 1, win_hl_attr(wp, HLF_AT));
}
- if (wlv.draw_state == WL_FOLD - 1 && wlv.n_extra == 0) {
- if (wlv.filler_todo > 0) {
- int index = wlv.filler_todo - (wlv.filler_lines - wlv.n_virt_lines);
- if (index > 0) {
- virt_line_index = (int)kv_size(virt_lines) - index;
- assert(virt_line_index >= 0);
- virt_line_offset = kv_A(virt_lines, virt_line_index).left_col ? 0 : win_col_off(wp);
- }
- }
- if (virt_line_offset == 0) {
- // Skip the column states if there is a "virt_left_col" line.
- wlv.draw_state = WL_BRI - 1;
- } else if (statuscol.draw) {
- // Skip fold, sign and number states if 'statuscolumn' is set.
- wlv.draw_state = WL_STC - 1;
+ if (wlv.filler_todo > 0) {
+ int index = wlv.filler_todo - (wlv.filler_lines - wlv.n_virt_lines);
+ if (index > 0) {
+ virt_line_index = (int)kv_size(virt_lines) - index;
+ assert(virt_line_index >= 0);
+ virt_line_offset = kv_A(virt_lines, virt_line_index).left_col ? 0 : win_col_off(wp);
}
}
- if (wlv.draw_state == WL_FOLD - 1 && wlv.n_extra == 0) {
- wlv.draw_state = WL_FOLD;
- handle_foldcolumn(wp, &wlv);
- }
+ if (virt_line_offset == 0) {
+ // skip columns
+ } else if (statuscol.draw) {
+ // Draw 'statuscolumn' if it is set.
+ if (sign_num_attr == 0) {
+ statuscol.num_attr = get_line_number_attr(wp, &wlv);
+ }
+ const int v = (int)(ptr - line);
+ draw_statuscol(wp, &wlv, lnum, wlv.row - startrow - wlv.filler_lines, col_rows, &statuscol);
+ if (wp->w_redr_statuscol) {
+ break;
+ }
+ if (!end_fill) {
+ // Get the line again as evaluating 'statuscolumn' may free it.
+ line = ml_get_buf(wp->w_buffer, lnum);
+ ptr = line + v;
+ }
+ } else {
+ // draw builtin info columns: fold, sign, number
+ draw_foldcolumn(wp, &wlv);
- // sign column, this is hit until sign_idx reaches count
- if (wlv.draw_state == WL_SIGN - 1 && wlv.n_extra == 0) {
- // Show the sign column when desired.
- wlv.draw_state = WL_SIGN;
- if (wp->w_scwidth > 0) {
- get_sign_display_info(false, wp, &wlv, sign_idx, sign_cul_attr);
- if (++sign_idx < wp->w_scwidth) {
- wlv.draw_state = WL_SIGN - 1;
- } else {
- sign_idx = 0;
- }
+ // wp->w_scwidth is zero if signcol=number is used
+ for (int sign_idx = 0; sign_idx < wp->w_scwidth; sign_idx++) {
+ draw_sign(false, wp, &wlv, sign_idx, sign_cul_attr);
}
- }
- if (wlv.draw_state == WL_NR - 1 && wlv.n_extra == 0) {
- // Show the line number, if desired.
- wlv.draw_state = WL_NR;
- handle_lnum_col(wp, &wlv, sign_num_attr, sign_cul_attr);
+ draw_lnum_col(wp, &wlv, sign_num_attr, sign_cul_attr);
}
- if (wlv.draw_state == WL_STC - 1 && wlv.n_extra == 0) {
- wlv.draw_state = WL_STC;
- // Draw the 'statuscolumn' if option is set.
- if (statuscol.draw) {
- if (sign_num_attr == 0) {
- statuscol.num_attr = get_line_number_attr(wp, &wlv);
+ win_col_offset = wlv.off;
+
+ // When only updating the columns and that's done, stop here.
+ if (col_rows > 0) {
+ win_put_linebuf(wp, wlv.row, 0, wlv.off, wlv.off, bg_attr, false);
+ // Need to update more screen lines if:
+ // - 'statuscolumn' needs to be drawn, or
+ // - LineNrAbove or LineNrBelow is used, or
+ // - still drawing filler lines.
+ if ((wlv.row + 1 - wlv.startrow < col_rows
+ && (statuscol.draw
+ || win_hl_attr(wp, HLF_LNA) != win_hl_attr(wp, HLF_N)
+ || win_hl_attr(wp, HLF_LNB) != win_hl_attr(wp, HLF_N)))
+ || wlv.filler_todo > 0) {
+ wlv.row++;
+ if (wlv.row == endrow) {
+ break;
}
- 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.
- line = ml_get_buf(wp->w_buffer, lnum);
- ptr = line + v;
- }
- if (wp->w_redr_statuscol) {
- break;
- }
+ wlv.filler_todo--;
+ if (wlv.filler_todo == 0 && (wp->w_botfill || end_fill)) {
+ break;
}
- get_statuscol_display_info(&statuscol, &wlv);
+ // win_line_start(wp, &wlv);
+ wlv.col = 0;
+ wlv.off = 0;
+ continue;
+ } else {
+ break;
}
}
- if (wlv.draw_state == WL_STC && wlv.n_extra == 0) {
- win_col_offset = wlv.off;
- }
-
// Check if 'breakindent' applies and show it.
- // May change wlv.draw_state to WL_BRI or WL_BRI - 1.
- if (wlv.n_extra == 0) {
+ if (!wp->w_briopt_sbr) {
handle_breakindent(wp, &wlv);
}
-
- if (wlv.draw_state == WL_SBR - 1 && wlv.n_extra == 0) {
- wlv.draw_state = WL_SBR;
- handle_showbreak_and_filler(wp, &wlv);
+ handle_showbreak_and_filler(wp, &wlv);
+ if (wp->w_briopt_sbr) {
+ handle_breakindent(wp, &wlv);
}
- if (wlv.draw_state == WL_LINE - 1 && wlv.n_extra == 0) {
- sign_idx = 0;
- wlv.draw_state = WL_LINE;
- if (has_decor && wlv.row == startrow + wlv.filler_lines) {
- // hide virt_text on text hidden by 'nowrap' or 'smoothscroll'
- decor_redraw_col(wp, (colnr_T)(ptr - line) - 1, wlv.off, true, &decor_state);
- }
- win_line_continue(&wlv); // use wlv.saved_ values
+ wlv.col = wlv.off;
+ draw_cols = false;
+ if (wlv.filler_todo <= 0) {
+ leftcols_width = wlv.off;
+ }
+ if (has_decor && wlv.row == startrow + wlv.filler_lines) {
+ // hide virt_text on text hidden by 'nowrap' or 'smoothscroll'
+ decor_redraw_col(wp, (colnr_T)(ptr - line) - 1, wlv.off, true, &decor_state);
}
}
- if (cul_screenline && wlv.draw_state == WL_LINE
- && wlv.vcol >= left_curline_col
- && wlv.vcol < right_curline_col) {
+ if (cul_screenline && wlv.vcol >= left_curline_col && wlv.vcol < right_curline_col) {
apply_cursorline_highlight(wp, &wlv);
}
- // When still displaying '$' of change command, stop at cursor
- if (((dollar_vcol >= 0
- && wp == curwin
- && lnum == wp->w_cursor.lnum
- && wlv.vcol >= wp->w_virtcol)
- || (number_only && wlv.draw_state > WL_STC))
- && wlv.filler_todo <= 0) {
+ // When still displaying '$' of change command, stop at cursor.
+ if (dollar_vcol >= 0 && wp == curwin
+ && lnum == wp->w_cursor.lnum && wlv.vcol >= wp->w_virtcol) {
draw_virt_text(wp, buf, win_col_offset, &wlv.col, wlv.row);
// don't clear anything after wlv.col
win_put_linebuf(wp, wlv.row, 0, wlv.col, wlv.col, bg_attr, false);
@@ -1704,15 +1636,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
break;
}
- const bool draw_folded = wlv.draw_state == WL_LINE && has_fold
- && wlv.row == startrow + wlv.filler_lines;
+ const bool draw_folded = has_fold && wlv.row == startrow + wlv.filler_lines;
if (draw_folded && wlv.n_extra == 0) {
wlv.char_attr = folded_attr = win_hl_attr(wp, HLF_FL);
+ decor_attr = 0;
}
int extmark_attr = 0;
- if (wlv.draw_state == WL_LINE
- && (area_highlighting || spv->spv_has_spell || extra_check)) {
+ if (area_highlighting || spv->spv_has_spell || extra_check) {
if (wlv.n_extra == 0 || !wlv.extra_for_extmark) {
wlv.reset_extra_attr = false;
}
@@ -1735,14 +1666,21 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
bool selected = (area_active || (area_highlighting && noinvcur
&& wlv.vcol == wp->w_virtcol));
+ // When there may be inline virtual text, position of non-inline virtual text
+ // can only be decided after drawing inline virtual text with lower priority.
if (decor_need_recheck) {
- decor_recheck_draw_col(wlv.off, selected, &decor_state);
+ if (!may_have_inline_virt) {
+ decor_recheck_draw_col(wlv.off, selected, &decor_state);
+ }
decor_need_recheck = false;
}
- extmark_attr = decor_redraw_col(wp, (colnr_T)v, wlv.off, selected, &decor_state);
-
- if (!has_fold && wp->w_buffer->b_virt_text_inline > 0) {
- handle_inline_virtual_text(wp, &wlv, v);
+ if (wlv.filler_todo <= 0) {
+ extmark_attr = decor_redraw_col(wp, (colnr_T)(ptr - line),
+ may_have_inline_virt ? -3 : wlv.off,
+ selected, &decor_state);
+ }
+ if (may_have_inline_virt) {
+ handle_inline_virtual_text(wp, &wlv, ptr - line, selected);
if (wlv.n_extra > 0 && wlv.virt_inline_hl_mode <= kHlModeReplace) {
// 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.
@@ -1758,9 +1696,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
}
- int *area_attr_p
- = wlv.extra_for_extmark && wlv.virt_inline_hl_mode <= kHlModeReplace
- ? &saved_area_attr : &area_attr;
+ int *area_attr_p = wlv.extra_for_extmark && wlv.virt_inline_hl_mode <= kHlModeReplace
+ ? &saved_area_attr : &area_attr;
// handle Visual or match highlighting in this line
if (wlv.vcol == wlv.fromcol
@@ -1780,13 +1717,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
area_active = false;
}
- if (!has_fold && wlv.n_extra == 0) {
+ if (!has_foldtext && 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,
+ const int v = (int)(ptr - line);
+ search_attr = update_search_hl(wp, lnum, v, &line, &screen_search_hl,
+ &has_match_conc, &match_conc, lcs_eol_todo,
&on_last_col, &search_attr_from_match);
ptr = line + v; // "line" may have been changed
@@ -1847,7 +1784,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
}
- if (draw_folded && wlv.n_extra == 0 && wlv.col == win_col_offset) {
+ if (draw_folded && has_foldtext && wlv.n_extra == 0 && wlv.col == win_col_offset) {
+ const int v = (int)(ptr - line);
linenr_T lnume = lnum + foldinfo.fi_lines - 1;
memset(buf_fold, ' ', FOLD_TEXT_LEN);
wlv.p_extra = get_foldtext(wp, lnum, lnume, foldinfo, buf_fold, &fold_vt);
@@ -1856,8 +1794,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
if (wlv.p_extra != buf_fold) {
foldtext_free = wlv.p_extra;
}
- wlv.c_extra = NUL;
- wlv.c_final = NUL;
+ wlv.sc_extra = NUL;
+ wlv.sc_final = NUL;
wlv.p_extra[wlv.n_extra] = NUL;
// Get the line again as evaluating 'foldtext' may free it.
@@ -1865,10 +1803,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
ptr = line + v;
}
- if (draw_folded && wlv.n_extra == 0 && wlv.col < grid->cols) {
+ if (draw_folded && wlv.n_extra == 0 && wlv.col < grid->cols && (has_foldtext || *ptr == NUL)) {
// Fill rest of line with 'fold'.
- wlv.c_extra = wp->w_p_fcs_chars.fold;
- wlv.c_final = NUL;
+ wlv.sc_extra = wp->w_p_fcs_chars.fold;
+ wlv.sc_final = NUL;
wlv.n_extra = grid->cols - wlv.col;
}
@@ -1881,15 +1819,15 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
//
// The "p_extra" points to the extra stuff that is inserted to
// represent special characters (non-printable stuff) and other
- // things. When all characters are the same, c_extra is used.
- // If c_final is set, it will compulsorily be used at the end.
+ // things. When all characters are the same, sc_extra is used.
+ // If sc_final is set, it will compulsorily be used at the end.
// "p_extra" must end in a NUL to avoid utfc_ptr2len() reads past
// "p_extra[n_extra]".
// For the '$' of the 'list' option, n_extra == 1, p_extra == "".
if (wlv.n_extra > 0) {
- if (wlv.c_extra != NUL || (wlv.n_extra == 1 && wlv.c_final != NUL)) {
- mb_c = (wlv.n_extra == 1 && wlv.c_final != NUL) ? wlv.c_final : wlv.c_extra;
- mb_schar = schar_from_char(mb_c);
+ if (wlv.sc_extra != NUL || (wlv.n_extra == 1 && wlv.sc_final != NUL)) {
+ mb_schar = (wlv.n_extra == 1 && wlv.sc_final != NUL) ? wlv.sc_final : wlv.sc_extra;
+ mb_c = schar_get_first_codepoint(mb_schar);
wlv.n_extra--;
} else {
assert(wlv.p_extra != NULL);
@@ -1923,33 +1861,36 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// 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;
- saved_search_attr = 0;
- }
- if (area_attr == 0 && *ptr != NUL) {
- area_attr = saved_area_attr;
- saved_area_attr = 0;
- }
- if (decor_attr == 0) {
- decor_attr = saved_decor_attr;
- saved_decor_attr = 0;
- }
+ if (search_attr == 0) {
+ search_attr = saved_search_attr;
+ saved_search_attr = 0;
+ }
+ if (area_attr == 0 && *ptr != NUL) {
+ area_attr = saved_area_attr;
+ saved_area_attr = 0;
+ }
+ if (decor_attr == 0) {
+ decor_attr = saved_decor_attr;
+ saved_decor_attr = 0;
+ }
- if (wlv.extra_for_extmark) {
- // wlv.extra_attr should be used at this position but not
- // any further.
- wlv.reset_extra_attr = true;
- }
+ 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 (has_fold) {
+ } else if (wlv.filler_todo > 0) {
+ // Wait with reading text until filler lines are done. Still need to
+ // initialize these.
+ mb_c = ' ';
+ mb_schar = schar_from_ascii(' ');
+ } else if (has_foldtext || (has_fold && wlv.col >= grid->cols)) {
// skip writing the buffer line itself
- mb_c = NUL;
+ mb_schar = NUL;
} else {
- char *prev_ptr = ptr;
+ const char *prev_ptr = ptr;
// first byte of next char
int c0 = (uint8_t)(*ptr);
@@ -1982,8 +1923,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
mb_c = mb_ptr2char_adv((const char **)&wlv.p_extra);
mb_schar = schar_from_char(mb_c);
wlv.n_extra = (int)strlen(wlv.p_extra);
- wlv.c_extra = NUL;
- wlv.c_final = NUL;
+ wlv.sc_extra = NUL;
+ wlv.sc_final = NUL;
if (area_attr == 0 && search_attr == 0) {
wlv.n_attr = wlv.n_extra + 1;
wlv.extra_attr = win_hl_attr(wp, HLF_8);
@@ -1996,9 +1937,9 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// last column; the character is displayed at the start of the
// next line.
if (wlv.col >= grid->cols - 1 && utf_char2cells(mb_c) == 2) {
+ mb_schar = schar_from_ascii('>');
mb_c = '>';
mb_l = 1;
- mb_schar = schar_from_ascii(mb_c);
multi_attr = win_hl_attr(wp, HLF_AT);
// Put pointer back so that the character will be
// displayed at the start of the next line.
@@ -2012,11 +1953,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// the first column. Don't do this for unprintable characters.
if (wlv.skip_cells > 0 && mb_l > 1 && wlv.n_extra == 0) {
wlv.n_extra = 1;
- wlv.c_extra = MB_FILLER_CHAR;
- wlv.c_final = NUL;
+ wlv.sc_extra = schar_from_ascii(MB_FILLER_CHAR);
+ wlv.sc_final = NUL;
+ mb_schar = schar_from_ascii(' ');
mb_c = ' ';
mb_l = 1;
- mb_schar = schar_from_ascii(mb_c);
if (area_attr == 0 && search_attr == 0) {
wlv.n_attr = wlv.n_extra + 1;
wlv.extra_attr = win_hl_attr(wp, HLF_AT);
@@ -2027,20 +1968,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
decor_attr = 0;
if (extra_check) {
- bool no_plain_buffer = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) != 0;
+ const bool no_plain_buffer = (wp->w_s->b_p_spo_flags & SPO_NPBUFFER) != 0;
bool can_spell = !no_plain_buffer;
// Get extmark and syntax attributes, unless still at the start of the line
// (double-wide char that doesn't fit).
- v = (ptr - line);
+ const int v = (int)(ptr - line);
+ const ptrdiff_t prev_v = prev_ptr - line;
if (has_syntax && v > 0) {
// Get the syntax attribute for the character. If there
// is an error, disable syntax highlighting.
- save_did_emsg = did_emsg;
+ int save_did_emsg = did_emsg;
did_emsg = false;
- decor_attr = get_syntax_attr((colnr_T)v - 1,
- spv->spv_has_spell ? &can_spell : NULL, false);
+ decor_attr = get_syntax_attr(v - 1, spv->spv_has_spell ? &can_spell : NULL, false);
if (did_emsg) {
wp->w_s->b_syn_error = true;
@@ -2057,10 +1998,11 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// have made it invalid.
line = ml_get_buf(wp->w_buffer, lnum);
ptr = line + v;
+ prev_ptr = line + prev_v;
// no concealing past the end of the line, it interferes
// with line highlighting.
- syntax_flags = (mb_c == 0) ? 0 : get_syntax_info(&syntax_seqnr);
+ syntax_flags = (mb_schar == 0) ? 0 : get_syntax_info(&syntax_seqnr);
}
if (has_decor && v > 0) {
@@ -2070,6 +2012,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
can_spell = TRISTATE_TO_BOOL(decor_state.spell, can_spell);
}
+ if (folded_attr) {
+ decor_attr = hl_combine_attr(folded_attr, decor_attr);
+ }
+
if (decor_attr) {
if (!attr_pri) {
if (wlv.cul_attr) {
@@ -2090,28 +2036,28 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// Only do this when there is no syntax highlighting, the
// @Spell cluster is not used or the current syntax item
// contains the @Spell cluster.
- v = (ptr - line);
- if (spv->spv_has_spell && v >= word_end && v > cur_checked_col) {
+ int v1 = (int)(ptr - line);
+ if (spv->spv_has_spell && v1 >= word_end && v1 > cur_checked_col) {
spell_attr = 0;
// do not calculate cap_col at the end of the line or when
// only white space is following
- if (mb_c != 0 && (*skipwhite(prev_ptr) != NUL) && can_spell) {
+ if (mb_schar != 0 && (*skipwhite(prev_ptr) != NUL) && can_spell) {
char *p;
hlf_T spell_hlf = HLF_COUNT;
- v -= mb_l - 1;
+ v1 -= mb_l - 1;
// Use nextline[] if possible, it has the start of the
// next line concatenated.
if ((prev_ptr - line) - nextlinecol >= 0) {
p = nextline + ((prev_ptr - line) - nextlinecol);
} else {
- p = prev_ptr;
+ p = (char *)prev_ptr;
}
spv->spv_cap_col -= (int)(prev_ptr - line);
size_t tmplen = spell_check(wp, p, &spell_hlf, &spv->spv_cap_col, spv->spv_unchanged);
assert(tmplen <= INT_MAX);
int len = (int)tmplen;
- word_end = (int)v + len;
+ word_end = v1 + len;
// In Insert mode only highlight a word that
// doesn't touch the cursor.
@@ -2169,7 +2115,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
//
// So only allow to linebreak, once we have found chars not in
// 'breakat' in the line.
- if (wp->w_p_lbr && !wlv.need_lbr && mb_c != NUL
+ if (wp->w_p_lbr && !wlv.need_lbr && mb_schar != NUL
&& !vim_isbreak((uint8_t)(*ptr))) {
wlv.need_lbr = true;
}
@@ -2178,13 +2124,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
&& vim_isbreak(mb_c) && !vim_isbreak((uint8_t)(*ptr))) {
int mb_off = utf_head_off(line, ptr - 1);
char *p = ptr - (mb_off + 1);
- 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);
+ CharsizeArg csarg;
+ // lnum == 0, do not want virtual text to be counted here
+ CSType cstype = init_charsize_arg(&csarg, wp, 0, line);
+ wlv.n_extra = win_charsize(cstype, wlv.vcol, p, utf_ptr2CharInfo(p).value,
+ &csarg).width - 1;
if (on_last_col && mb_c != TAB) {
// Do not continue search/match highlighting over the
@@ -2197,12 +2142,12 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
wlv.n_extra = tabstop_padding(wlv.vcol, wp->w_buffer->b_p_ts,
wp->w_buffer->b_p_vts_array) - 1;
}
- wlv.c_extra = mb_off > 0 ? MB_FILLER_CHAR : ' ';
- wlv.c_final = NUL;
+ wlv.sc_extra = schar_from_ascii(mb_off > 0 ? MB_FILLER_CHAR : ' ');
+ wlv.sc_final = NUL;
if (mb_c < 128 && ascii_iswhite(mb_c)) {
if (mb_c == TAB) {
// See "Tab alignment" below.
- FIX_FOR_BOGUSCOLS;
+ fix_for_boguscols(&wlv);
}
if (!wp->w_p_list) {
mb_c = ' ';
@@ -2231,39 +2176,39 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
&& ptr - line >= leadcol
&& ptr - line <= trailcol))) {
if (in_multispace && wp->w_p_lcs_chars.multispace != NULL) {
- mb_c = wp->w_p_lcs_chars.multispace[multispace_pos++];
+ mb_schar = wp->w_p_lcs_chars.multispace[multispace_pos++];
if (wp->w_p_lcs_chars.multispace[multispace_pos] == NUL) {
multispace_pos = 0;
}
} else {
- mb_c = (mb_c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp;
+ mb_schar = (mb_c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp;
}
wlv.n_attr = 1;
wlv.extra_attr = win_hl_attr(wp, HLF_0);
saved_attr2 = wlv.char_attr; // save current attr
- mb_schar = schar_from_char(mb_c);
+ mb_c = schar_get_first_codepoint(mb_schar);
}
if (mb_c == ' ' && mb_l == 1 && ((trailcol != MAXCOL && ptr > line + trailcol)
|| (leadcol != 0 && ptr < line + leadcol))) {
if (leadcol != 0 && in_multispace && ptr < line + leadcol
&& wp->w_p_lcs_chars.leadmultispace != NULL) {
- mb_c = wp->w_p_lcs_chars.leadmultispace[multispace_pos++];
+ mb_schar = wp->w_p_lcs_chars.leadmultispace[multispace_pos++];
if (wp->w_p_lcs_chars.leadmultispace[multispace_pos] == NUL) {
multispace_pos = 0;
}
} else if (ptr > line + trailcol && wp->w_p_lcs_chars.trail) {
- mb_c = wp->w_p_lcs_chars.trail;
+ mb_schar = wp->w_p_lcs_chars.trail;
} else if (ptr < line + leadcol && wp->w_p_lcs_chars.lead) {
- mb_c = wp->w_p_lcs_chars.lead;
+ mb_schar = wp->w_p_lcs_chars.lead;
} else if (leadcol != 0 && wp->w_p_lcs_chars.space) {
- mb_c = wp->w_p_lcs_chars.space;
+ mb_schar = wp->w_p_lcs_chars.space;
}
wlv.n_attr = 1;
wlv.extra_attr = win_hl_attr(wp, HLF_0);
saved_attr2 = wlv.char_attr; // save current attr
- mb_schar = schar_from_char(mb_c);
+ mb_c = schar_get_first_codepoint(mb_schar);
}
}
@@ -2289,15 +2234,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
if (!wp->w_p_lbr || !wp->w_p_list) {
wlv.n_extra = tab_len;
} else {
- char *p;
int saved_nextra = wlv.n_extra;
if (wlv.vcol_off > 0) {
// there are characters to conceal
tab_len += wlv.vcol_off;
}
- // boguscols before FIX_FOR_BOGUSCOLS macro from above.
- if (wp->w_p_lcs_chars.tab1 && old_boguscols > 0
+ // boguscols before fix_for_boguscols() from above.
+ if (wp->w_p_lcs_chars.tab1 && wlv.old_boguscols > 0
&& wlv.n_extra > tab_len) {
tab_len += wlv.n_extra - tab_len;
}
@@ -2306,17 +2250,18 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// If wlv.n_extra > 0, it gives the number of chars
// to use for a tab, else we need to calculate the
// width for a tab.
- int tab2_len = utf_char2len(wp->w_p_lcs_chars.tab2);
- int len = tab_len * tab2_len;
+ size_t tab2_len = schar_len(wp->w_p_lcs_chars.tab2);
+ size_t len = (size_t)tab_len * tab2_len;
if (wp->w_p_lcs_chars.tab3) {
- len += utf_char2len(wp->w_p_lcs_chars.tab3) - tab2_len;
+ len += schar_len(wp->w_p_lcs_chars.tab3) - tab2_len;
}
if (wlv.n_extra > 0) {
- len += wlv.n_extra - tab_len;
+ len += (size_t)(wlv.n_extra - tab_len);
}
- mb_c = wp->w_p_lcs_chars.tab1;
- p = get_extra_buf((size_t)len + 1);
- memset(p, ' ', (size_t)len);
+ mb_schar = wp->w_p_lcs_chars.tab1;
+ mb_c = schar_get_first_codepoint(mb_schar);
+ char *p = get_extra_buf(len + 1);
+ memset(p, ' ', len);
p[len] = NUL;
wlv.p_extra = p;
for (int i = 0; i < tab_len; i++) {
@@ -2324,17 +2269,17 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
tab_len = i;
break;
}
- int lcs = wp->w_p_lcs_chars.tab2;
+ schar_T lcs = wp->w_p_lcs_chars.tab2;
// if tab3 is given, use it for the last char
if (wp->w_p_lcs_chars.tab3 && i == tab_len - 1) {
lcs = wp->w_p_lcs_chars.tab3;
}
- p += utf_char2bytes(lcs, p);
- wlv.n_extra += utf_char2len(lcs) - (saved_nextra > 0 ? 1 : 0);
+ size_t slen = schar_get_adv(&p, lcs);
+ wlv.n_extra += (int)slen - (saved_nextra > 0 ? 1 : 0);
}
- // n_extra will be increased by FIX_FOX_BOGUSCOLS
+ // n_extra will be increased by fix_for_boguscols()
// macro below, so need to adjust for that here
if (wlv.vcol_off > 0) {
wlv.n_extra -= wlv.vcol_off;
@@ -2351,7 +2296,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// vcol_off and boguscols accumulated so far in the
// line. Note that the tab can be longer than
// 'tabstop' when there are concealed characters.
- FIX_FOR_BOGUSCOLS;
+ fix_for_boguscols(&wlv);
// Make sure, the highlighting for the tab char will be
// correctly set further below (effectively reverts the
@@ -2363,24 +2308,24 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
if (wp->w_p_list) {
- mb_c = (wlv.n_extra == 0 && wp->w_p_lcs_chars.tab3)
- ? wp->w_p_lcs_chars.tab3 : wp->w_p_lcs_chars.tab1;
+ mb_schar = (wlv.n_extra == 0 && wp->w_p_lcs_chars.tab3)
+ ? wp->w_p_lcs_chars.tab3 : wp->w_p_lcs_chars.tab1;
if (wp->w_p_lbr && wlv.p_extra != NULL && *wlv.p_extra != NUL) {
- wlv.c_extra = NUL; // using p_extra from above
+ wlv.sc_extra = NUL; // using p_extra from above
} else {
- wlv.c_extra = wp->w_p_lcs_chars.tab2;
+ wlv.sc_extra = wp->w_p_lcs_chars.tab2;
}
- wlv.c_final = wp->w_p_lcs_chars.tab3;
+ wlv.sc_final = wp->w_p_lcs_chars.tab3;
wlv.n_attr = tab_len + 1;
wlv.extra_attr = win_hl_attr(wp, HLF_0);
saved_attr2 = wlv.char_attr; // save current attr
} else {
- wlv.c_final = NUL;
- wlv.c_extra = ' ';
- mb_c = ' ';
+ wlv.sc_final = NUL;
+ wlv.sc_extra = schar_from_ascii(' ');
+ mb_schar = schar_from_ascii(' ');
}
- mb_schar = schar_from_char(mb_c);
- } else if (mb_c == NUL
+ mb_c = schar_get_first_codepoint(mb_schar);
+ } else if (mb_schar == NUL
&& (wp->w_p_list
|| ((wlv.fromcol >= 0 || fromcol_prev >= 0)
&& wlv.tocol > wlv.vcol
@@ -2389,7 +2334,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
&& !(noinvcur
&& lnum == wp->w_cursor.lnum
&& wlv.vcol == wp->w_virtcol)))
- && lcs_eol_one > 0) {
+ && lcs_eol_todo && lcs_eol != NUL) {
// Display a '$' after the line or highlight an extra
// character if the line break is included.
// For a diff line the highlighting continues after the "$".
@@ -2399,21 +2344,21 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// In virtualedit, visual selections may extend beyond end of line
if (!(area_highlighting && virtual_active()
&& wlv.tocol != MAXCOL && wlv.vcol < wlv.tocol)) {
- wlv.p_extra = at_end_str;
+ wlv.p_extra = "";
}
wlv.n_extra = 0;
}
if (wp->w_p_list && wp->w_p_lcs_chars.eol > 0) {
- mb_c = wp->w_p_lcs_chars.eol;
+ mb_schar = wp->w_p_lcs_chars.eol;
} else {
- mb_c = ' ';
+ mb_schar = schar_from_ascii(' ');
}
- lcs_eol_one = -1;
+ lcs_eol_todo = false;
ptr--; // put it back at the NUL
wlv.extra_attr = win_hl_attr(wp, HLF_AT);
wlv.n_attr = 1;
- mb_schar = schar_from_char(mb_c);
- } else if (mb_c != NUL) {
+ mb_c = schar_get_first_codepoint(mb_schar);
+ } else if (mb_schar != NUL) {
wlv.p_extra = transchar_buf(wp->w_buffer, mb_c);
if (wlv.n_extra == 0) {
wlv.n_extra = byte2cells(mb_c) - 1;
@@ -2421,17 +2366,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
if ((dy_flags & DY_UHEX) && wp->w_p_rl) {
rl_mirror_ascii(wlv.p_extra, NULL); // reverse "<12>"
}
- wlv.c_extra = NUL;
- wlv.c_final = NUL;
+ wlv.sc_extra = NUL;
+ wlv.sc_final = NUL;
if (wp->w_p_lbr) {
- char *p;
-
mb_c = (uint8_t)(*wlv.p_extra);
- p = get_extra_buf((size_t)wlv.n_extra + 1);
+ char *p = get_extra_buf((size_t)wlv.n_extra + 1);
memset(p, ' ', (size_t)wlv.n_extra);
- strncpy(p, // NOLINT(runtime/printf)
- wlv.p_extra + 1,
- (size_t)strlen(wlv.p_extra) - 1);
+ memcpy(p, wlv.p_extra + 1, strlen(wlv.p_extra) - 1);
p[wlv.n_extra] = NUL;
wlv.p_extra = p;
} else {
@@ -2459,7 +2400,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
&& ((syntax_flags & HL_CONCEAL) != 0 || has_match_conc > 0 || decor_conceal > 0)
&& !(lnum_in_visual_area && vim_strchr(wp->w_p_cocu, 'v') == NULL)) {
wlv.char_attr = conceal_attr;
- bool is_conceal_char = false;
if (((prev_syntax_id != syntax_seqnr && (syntax_flags & HL_CONCEAL) != 0)
|| has_match_conc > 1 || decor_conceal > 1)
&& (syn_get_sub_char() != NUL
@@ -2470,21 +2410,20 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// First time at this concealed item: display one
// character.
if (has_match_conc && match_conc) {
- mb_c = match_conc;
+ mb_schar = schar_from_char(match_conc);
} else if (decor_conceal && decor_state.conceal_char) {
mb_schar = decor_state.conceal_char;
- mb_c = schar_get_first_codepoint(mb_schar);
- is_conceal_char = true;
if (decor_state.conceal_attr) {
wlv.char_attr = decor_state.conceal_attr;
}
} else if (syn_get_sub_char() != NUL) {
- mb_c = syn_get_sub_char();
+ mb_schar = schar_from_char(syn_get_sub_char());
} else if (wp->w_p_lcs_chars.conceal != NUL) {
- mb_c = wp->w_p_lcs_chars.conceal;
+ mb_schar = wp->w_p_lcs_chars.conceal;
} else {
- mb_c = ' ';
+ mb_schar = schar_from_ascii(' ');
}
+ mb_c = schar_get_first_codepoint(mb_schar);
prev_syntax_id = syntax_seqnr;
@@ -2492,7 +2431,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
wlv.vcol_off += wlv.n_extra;
}
wlv.vcol += wlv.n_extra;
- if (wp->w_p_wrap && wlv.n_extra > 0) {
+ if (is_wrapped && wlv.n_extra > 0) {
wlv.boguscols += wlv.n_extra;
wlv.col += wlv.n_extra;
}
@@ -2502,9 +2441,6 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
is_concealing = true;
wlv.skip_cells = 1;
}
- if (!is_conceal_char) {
- mb_schar = schar_from_char(mb_c);
- }
} else {
prev_syntax_id = 0;
is_concealing = false;
@@ -2518,7 +2454,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// In the cursor line and we may be concealing characters: correct
// the cursor column when we reach its position.
- if (!did_wcol && wlv.draw_state == WL_LINE
+ if (!did_wcol
&& wp == curwin && lnum == wp->w_cursor.lnum
&& conceal_cursor_line(wp)
&& (int)wp->w_virtcol <= wlv.vcol + wlv.skip_cells) {
@@ -2529,7 +2465,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
// Don't override visual selection highlighting.
- if (wlv.n_attr > 0 && wlv.draw_state == WL_LINE && !search_attr_from_match) {
+ if (wlv.n_attr > 0 && !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;
@@ -2546,37 +2482,36 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
&& wp->w_p_list
&& (wp->w_p_wrap ? (wp->w_skipcol > 0 && wlv.row == 0) : wp->w_leftcol > 0)
&& wlv.filler_todo <= 0
- && wlv.draw_state > WL_STC
- && mb_c != NUL) {
- mb_c = wp->w_p_lcs_chars.prec;
+ && mb_schar != NUL) {
+ mb_schar = wp->w_p_lcs_chars.prec;
lcs_prec_todo = NUL;
if (utf_char2cells(mb_c) > 1) {
// Double-width character being overwritten by the "precedes"
// character, need to fill up half the character.
- wlv.c_extra = MB_FILLER_CHAR;
- wlv.c_final = NUL;
+ wlv.sc_extra = schar_from_ascii(MB_FILLER_CHAR);
+ wlv.sc_final = NUL;
wlv.n_extra = 1;
wlv.n_attr = 2;
wlv.extra_attr = win_hl_attr(wp, HLF_AT);
}
- mb_schar = schar_from_char(mb_c);
+ mb_c = schar_get_first_codepoint(mb_schar);
saved_attr3 = wlv.char_attr; // save current attr
wlv.char_attr = win_hl_attr(wp, HLF_AT); // overwriting char_attr
n_attr3 = 1;
}
// At end of the text line or just after the last character.
- if (mb_c == NUL && eol_hl_off == 0) {
+ if (mb_schar == NUL && eol_hl_off == 0) {
// flag to indicate whether prevcol equals startcol of search_hl or
// one of the matches
- bool prevcol_hl_flag = get_prevcol_hl_flag(wp, &screen_search_hl,
- (colnr_T)(ptr - line) - 1);
+ const bool prevcol_hl_flag = get_prevcol_hl_flag(wp, &screen_search_hl,
+ (colnr_T)(ptr - line) - 1);
// Invert at least one char, used for Visual and empty line or
// highlight match at end of line. If it's beyond the last
// char on the screen, just overwrite that one (tricky!) Not
// needed when a '$' was displayed for 'list'.
- if (wp->w_p_lcs_chars.eol == lcs_eol_one
+ if (lcs_eol_todo
&& ((area_attr != 0 && wlv.vcol == wlv.fromcol
&& (VIsual_mode != Ctrl_V
|| lnum == VIsual.lnum
@@ -2597,7 +2532,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
// Add a blank character to highlight.
linebuf_char[wlv.off] = schar_from_ascii(' ');
}
- if (area_attr == 0 && !has_fold) {
+ if (area_attr == 0 && !has_foldtext) {
// Use attributes from match with highest priority among
// 'search_hl' and the match list.
get_search_match_hl(wp,
@@ -2606,10 +2541,10 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
&wlv.char_attr);
}
- int eol_attr = wlv.char_attr;
- if (wlv.cul_attr) {
- eol_attr = hl_combine_attr(wlv.cul_attr, eol_attr);
- }
+ const int eol_attr = wlv.cul_attr
+ ? hl_combine_attr(wlv.cul_attr, wlv.char_attr)
+ : wlv.char_attr;
+
linebuf_attr[wlv.off] = eol_attr;
linebuf_vcol[wlv.off] = MAXCOL;
wlv.col++;
@@ -2620,70 +2555,48 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
// At end of the text line.
- if (mb_c == NUL) {
+ if (mb_schar == NUL) {
// Highlight 'cursorcolumn' & 'colorcolumn' past end of the line.
- if (wp->w_p_wrap) {
- v = wlv.startrow == 0 ? wp->w_skipcol : 0;
- } else {
- v = wp->w_leftcol;
- }
// check if line ends before left margin
- if (wlv.vcol < v + wlv.col - win_col_off(wp)) {
- wlv.vcol = (colnr_T)v + wlv.col - win_col_off(wp);
+ if (wlv.vcol < start_col + wlv.col - win_col_off(wp)) {
+ wlv.vcol = start_col + wlv.col - win_col_off(wp);
}
// Get rid of the boguscols now, we want to draw until the right
// edge for 'cursorcolumn'.
wlv.col -= wlv.boguscols;
wlv.boguscols = 0;
- if (draw_color_col) {
- draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
- }
+ advance_color_col(&wlv, vcol_hlc(wlv));
bool has_virttext = false;
// Make sure alignment is the same regardless
// if listchars=eol:X is used or not.
- int eol_skip = (wp->w_p_lcs_chars.eol == lcs_eol_one && eol_hl_off == 0
- ? 1 : 0);
+ const int eol_skip = (lcs_eol_todo && eol_hl_off == 0 ? 1 : 0);
if (has_decor) {
has_virttext = decor_redraw_eol(wp, &decor_state, &wlv.line_attr, wlv.col + eol_skip);
}
if (((wp->w_p_cuc
- && wp->w_virtcol >= VCOL_HLC - eol_hl_off
- && wp->w_virtcol < grid->cols * (ptrdiff_t)(wlv.row - startrow + 1) + v
+ && wp->w_virtcol >= vcol_hlc(wlv) - eol_hl_off
+ && wp->w_virtcol < grid->cols * (ptrdiff_t)(wlv.row - startrow + 1) + start_col
&& lnum != wp->w_cursor.lnum)
- || draw_color_col || wlv.line_attr_lowprio || wlv.line_attr
+ || wlv.color_cols || wlv.line_attr_lowprio || wlv.line_attr
|| wlv.diff_hlf != 0 || has_virttext)) {
- int rightmost_vcol = 0;
-
- if (wp->w_p_cuc) {
- rightmost_vcol = wp->w_virtcol;
- }
-
- if (draw_color_col) {
- // determine rightmost colorcolumn to possibly draw
- for (int i = 0; color_cols[i] >= 0; i++) {
- if (rightmost_vcol < color_cols[i]) {
- rightmost_vcol = color_cols[i];
- }
- }
- }
+ int rightmost_vcol = get_rightmost_vcol(wp, wlv.color_cols);
+ const int cuc_attr = win_hl_attr(wp, HLF_CUC);
+ const int mc_attr = win_hl_attr(wp, HLF_MC);
- int cuc_attr = win_hl_attr(wp, HLF_CUC);
- int mc_attr = win_hl_attr(wp, HLF_MC);
-
- int diff_attr = 0;
if (wlv.diff_hlf == HLF_TXD) {
wlv.diff_hlf = HLF_CHD;
}
- if (wlv.diff_hlf != 0) {
- diff_attr = win_hl_attr(wp, (int)wlv.diff_hlf);
- }
- int base_attr = hl_combine_attr(wlv.line_attr_lowprio, diff_attr);
+ const int diff_attr = wlv.diff_hlf != 0
+ ? win_hl_attr(wp, (int)wlv.diff_hlf)
+ : 0;
+
+ const int base_attr = hl_combine_attr(wlv.line_attr_lowprio, diff_attr);
if (base_attr || wlv.line_attr || has_virttext) {
rightmost_vcol = INT_MAX;
}
@@ -2692,15 +2605,13 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
linebuf_char[wlv.off] = schar_from_ascii(' ');
linebuf_vcol[wlv.off] = MAXCOL;
wlv.col++;
- if (draw_color_col) {
- draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
- }
+ advance_color_col(&wlv, vcol_hlc(wlv));
int col_attr = base_attr;
- if (wp->w_p_cuc && VCOL_HLC == wp->w_virtcol) {
+ if (wp->w_p_cuc && vcol_hlc(wlv) == wp->w_virtcol) {
col_attr = cuc_attr;
- } else if (draw_color_col && VCOL_HLC == *color_cols) {
+ } else if (wlv.color_cols && vcol_hlc(wlv) == *wlv.color_cols) {
col_attr = hl_combine_attr(wlv.line_attr_lowprio, mc_attr);
}
@@ -2709,7 +2620,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
linebuf_attr[wlv.off] = col_attr;
wlv.off++;
- if (VCOL_HLC >= rightmost_vcol) {
+ if (vcol_hlc(wlv) >= rightmost_vcol) {
break;
}
@@ -2746,73 +2657,72 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
curwin->w_valid |= (VALID_CHEIGHT|VALID_CROW);
conceal_cursor_used = conceal_cursor_line(curwin);
}
+
+ // When the window is too narrow draw all "@" lines.
+ if (leftcols_width >= wp->w_grid.cols && is_wrapped) {
+ win_draw_end(wp, schar_from_ascii('@'), true, wlv.row, wp->w_grid.rows, HLF_AT);
+ set_empty_rows(wp, wlv.row);
+ wlv.row = endrow;
+ }
+
break;
}
// Show "extends" character from 'listchars' if beyond the line end and
// 'list' is set.
+ // Don't show this with 'wrap' as the line can't be scrolled horizontally.
if (wp->w_p_lcs_chars.ext != NUL
- && wlv.draw_state == WL_LINE
&& wp->w_p_list
&& !wp->w_p_wrap
&& wlv.filler_todo <= 0
&& wlv.col == grid->cols - 1
- && !has_fold) {
- if (has_decor && *ptr == NUL && lcs_eol_one == 0) {
+ && !has_foldtext) {
+ if (has_decor && *ptr == NUL && lcs_eol == 0 && lcs_eol_todo) {
// Tricky: there might be a virtual text just _after_ the last char
- decor_redraw_col(wp, (colnr_T)v, wlv.off, false, &decor_state);
+ decor_redraw_col(wp, (colnr_T)(ptr - line), -1, false, &decor_state);
}
if (*ptr != NUL
- || lcs_eol_one > 0
- || (wlv.n_extra > 0 && (wlv.c_extra != NUL || *wlv.p_extra != NUL))
- || has_more_inline_virt(&wlv, v)) {
- mb_c = wp->w_p_lcs_chars.ext;
+ || (lcs_eol > 0 && lcs_eol_todo)
+ || (wlv.n_extra > 0 && (wlv.sc_extra != NUL || *wlv.p_extra != NUL))
+ || (may_have_inline_virt && has_more_inline_virt(&wlv, ptr - line))) {
+ mb_schar = wp->w_p_lcs_chars.ext;
wlv.char_attr = win_hl_attr(wp, HLF_AT);
- mb_schar = schar_from_char(mb_c);
+ mb_c = schar_get_first_codepoint(mb_schar);
}
}
- // advance to the next 'colorcolumn'
- if (draw_color_col) {
- draw_color_col = advance_color_col(VCOL_HLC, &color_cols);
- }
+ advance_color_col(&wlv, vcol_hlc(wlv));
// Highlight the cursor column if 'cursorcolumn' is set. But don't
// highlight the cursor position itself.
// Also highlight the 'colorcolumn' if it is different than
// 'cursorcolumn'
- // Also highlight the 'colorcolumn' if 'breakindent' and/or 'showbreak'
- // options are set
vcol_save_attr = -1;
- if ((wlv.draw_state == WL_LINE
- || wlv.draw_state == WL_BRI
- || wlv.draw_state == WL_SBR)
- && !lnum_in_visual_area
+ if (!lnum_in_visual_area
&& search_attr == 0
&& area_attr == 0
&& wlv.filler_todo <= 0) {
- if (wp->w_p_cuc && VCOL_HLC == wp->w_virtcol
+ if (wp->w_p_cuc && vcol_hlc(wlv) == wp->w_virtcol
&& lnum != wp->w_cursor.lnum) {
vcol_save_attr = wlv.char_attr;
wlv.char_attr = hl_combine_attr(win_hl_attr(wp, HLF_CUC), wlv.char_attr);
- } else if (draw_color_col && VCOL_HLC == *color_cols) {
+ } else if (wlv.color_cols && vcol_hlc(wlv) == *wlv.color_cols) {
vcol_save_attr = wlv.char_attr;
wlv.char_attr = hl_combine_attr(win_hl_attr(wp, HLF_MC), wlv.char_attr);
}
}
// Apply lowest-priority line attr now, so everything can override it.
- if (wlv.draw_state == WL_LINE) {
- wlv.char_attr = hl_combine_attr(wlv.line_attr_lowprio, wlv.char_attr);
- }
+ wlv.char_attr = hl_combine_attr(wlv.line_attr_lowprio, wlv.char_attr);
- if (wlv.draw_state == WL_LINE) {
- vcol_prev = wlv.vcol;
- }
+ vcol_prev = wlv.vcol;
// Store character to be displayed.
// Skip characters that are left of the screen for 'nowrap'.
- if (wlv.draw_state < WL_LINE || wlv.skip_cells <= 0) {
+ if (wlv.filler_todo > 0) {
+ // TODO(bfredl): the main render loop should get called also with the virtual
+ // lines chunks, so we get line wrapping and other Nice Things.
+ } else if (wlv.skip_cells <= 0) {
// Store the character.
linebuf_char[wlv.off] = mb_schar;
if (multi_attr) {
@@ -2822,18 +2732,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
linebuf_attr[wlv.off] = wlv.char_attr;
}
- if (wlv.draw_state > WL_STC && wlv.filler_todo <= 0) {
- linebuf_vcol[wlv.off] = wlv.vcol;
- } else if (wlv.draw_state == WL_FOLD) {
- if (wlv.n_closing > 0) {
- linebuf_vcol[wlv.off] = -3;
- wlv.n_closing--;
- } else {
- linebuf_vcol[wlv.off] = -2;
- }
- } else {
- linebuf_vcol[wlv.off] = -1;
- }
+ linebuf_vcol[wlv.off] = wlv.vcol;
if (utf_char2cells(mb_c) > 1) {
// Need to fill two screen columns.
@@ -2843,11 +2742,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
linebuf_char[wlv.off] = 0;
linebuf_attr[wlv.off] = linebuf_attr[wlv.off - 1];
- if (wlv.draw_state > WL_STC && wlv.filler_todo <= 0) {
- linebuf_vcol[wlv.off] = ++wlv.vcol;
- } else {
- linebuf_vcol[wlv.off] = -1;
- }
+ linebuf_vcol[wlv.off] = ++wlv.vcol;
// When "wlv.tocol" is halfway through a character, set it to the end
// of the character, otherwise highlighting won't stop.
@@ -2863,7 +2758,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
if (wlv.n_extra > 0) {
wlv.vcol_off += wlv.n_extra;
}
- if (wp->w_p_wrap) {
+ if (is_wrapped) {
// Special voodoo required if 'wrap' is on.
//
// Advance the column indicator to force the line
@@ -2903,15 +2798,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
// The skipped cells need to be accounted for in vcol.
- if (wlv.draw_state > WL_STC && wlv.skipped_cells > 0) {
+ if (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
- && wlv.filler_todo <= 0) {
+ if (wlv.filler_todo <= 0) {
wlv.vcol++;
}
@@ -2920,46 +2814,45 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
}
// restore attributes after "predeces" in 'listchars'
- if (wlv.draw_state > WL_STC && n_attr3 > 0 && --n_attr3 == 0) {
+ if (n_attr3 > 0 && --n_attr3 == 0) {
wlv.char_attr = saved_attr3;
}
// restore attributes after last 'listchars' or 'number' char
- if (wlv.n_attr > 0 && wlv.draw_state == WL_LINE && --wlv.n_attr == 0) {
+ if (wlv.n_attr > 0 && --wlv.n_attr == 0) {
wlv.char_attr = saved_attr2;
}
if (has_decor && wlv.filler_todo <= 0 && wlv.col >= grid->cols) {
// At the end of screen line: might need to peek for decorations just after
// this position.
- if (!has_fold && wp->w_p_wrap && wlv.n_extra == 0) {
- decor_redraw_col(wp, (int)(ptr - line), -3, false, &decor_state);
+ if (is_wrapped && wlv.n_extra == 0) {
+ decor_redraw_col(wp, (colnr_T)(ptr - line), -3, false, &decor_state);
// Check position/hiding of virtual text again on next screen line.
decor_need_recheck = true;
- } else if (has_fold || !wp->w_p_wrap) {
+ } else if (!is_wrapped) {
// Without wrapping, we might need to display right_align and win_col
// virt_text for the entire text line.
+ decor_recheck_draw_col(-1, true, &decor_state);
decor_redraw_col(wp, MAXCOL, -1, true, &decor_state);
}
}
// At end of screen line and there is more to come: Display the line
// so far. If there is no more to display it is caught above.
- if (wlv.col >= grid->cols && (!has_fold || virt_line_offset >= 0)
- && (wlv.draw_state != WL_LINE
- || *ptr != NUL
+ if (wlv.col >= grid->cols && (!has_foldtext || virt_line_offset >= 0)
+ && (*ptr != NUL
|| wlv.filler_todo > 0
- || (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL
- && wlv.p_extra != at_end_str)
- || (wlv.n_extra != 0 && (wlv.c_extra != NUL || *wlv.p_extra != NUL))
- || has_more_inline_virt(&wlv, v))) {
- bool wrap = wp->w_p_wrap // Wrapping enabled.
- && wlv.filler_todo <= 0 // Not drawing diff filler lines.
- && lcs_eol_one != -1 // Haven't printed the lcs_eol character.
- && wlv.row != endrow - 1 // Not the last line being displayed.
- && (grid->cols == Columns // Window spans the width of the screen,
- || ui_has(kUIMultigrid)) // or has dedicated grid.
- && !wp->w_p_rl; // Not right-to-left.
+ || (wp->w_p_list && wp->w_p_lcs_chars.eol != NUL && lcs_eol_todo)
+ || (wlv.n_extra != 0 && (wlv.sc_extra != NUL || *wlv.p_extra != NUL))
+ || (may_have_inline_virt && has_more_inline_virt(&wlv, ptr - line)))) {
+ const bool wrap = is_wrapped // Wrapping enabled (not a folded line).
+ && wlv.filler_todo <= 0 // Not drawing diff filler lines.
+ && lcs_eol_todo // Haven't printed the lcs_eol character.
+ && wlv.row != endrow - 1 // Not the last line being displayed.
+ && (grid->cols == Columns // Window spans the width of the screen,
+ || ui_has(kUIMultigrid)) // or has dedicated grid.
+ && !wp->w_p_rl; // Not right-to-left.
int draw_col = wlv.col - wlv.boguscols;
if (virt_line_offset >= 0) {
@@ -2984,15 +2877,14 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
wlv.vcol_off = 0;
wlv.row++;
- // When not wrapping and finished diff lines, or when displayed
- // '$' and highlighting until last column, break here.
- if ((!wp->w_p_wrap && wlv.filler_todo <= 0) || lcs_eol_one == -1) {
+ // When not wrapping and finished diff lines, break here.
+ if (!is_wrapped && wlv.filler_todo <= 0) {
break;
}
// When the window is too narrow draw all "@" lines.
- if (wlv.draw_state != WL_LINE && wlv.filler_todo <= 0) {
- win_draw_end(wp, '@', ' ', true, wlv.row, wp->w_grid.rows, HLF_AT);
+ if (wlv.col <= leftcols_width) {
+ win_draw_end(wp, schar_from_ascii('@'), true, wlv.row, wp->w_grid.rows, HLF_AT);
set_empty_rows(wp, wlv.row);
wlv.row = endrow;
}
@@ -3003,18 +2895,16 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool number_onl
break;
}
- win_line_start(wp, &wlv, true);
+ win_line_start(wp, &wlv);
+ draw_cols = true;
lcs_prec_todo = wp->w_p_lcs_chars.prec;
if (wlv.filler_todo <= 0) {
wlv.need_showbreak = true;
}
- if (statuscol.draw) {
- if (vim_strchr(p_cpo, CPO_NUMCOL) && wlv.row > startrow + wlv.filler_lines) {
- statuscol.draw = false; // don't draw status column if "n" is in 'cpo'
- } else {
- statuscol.textp = NULL; // re-evaluate with new v:virtnum
- }
+ if (statuscol.draw && vim_strchr(p_cpo, CPO_NUMCOL)
+ && wlv.row > startrow + wlv.filler_lines) {
+ statuscol.draw = false; // don't draw status column if "n" is in 'cpo'
}
wlv.filler_todo--;
virt_line_offset = -1;
@@ -3040,8 +2930,7 @@ static void win_put_linebuf(win_T *wp, int row, int coloff, int endcol, int clea
int start_col = 0;
if (wp->w_p_rl) {
- linebuf_mirror(&start_col, &clear_width, grid->cols);
- endcol = grid->cols - 1 - endcol;
+ linebuf_mirror(&start_col, &endcol, &clear_width, grid->cols);
}
// Take care of putting "<<<" on the first line for 'smoothscroll'.
diff --git a/src/nvim/drawline.h b/src/nvim/drawline.h
index 5a7f220a13..9112deddb3 100644
--- a/src/nvim/drawline.h
+++ b/src/nvim/drawline.h
@@ -4,14 +4,12 @@
#include <stdint.h>
#include "klib/kvec.h"
-#include "nvim/decoration_provider.h"
-#include "nvim/fold_defs.h"
+#include "nvim/fold_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
#include "nvim/pos_defs.h"
#include "nvim/types_defs.h"
-// Maximum columns for terminal highlight attributes
-#define TERM_ATTRS_MAX 1024
+enum { TERM_ATTRS_MAX = 1024, }; ///< Maximum columns for terminal highlight attributes
typedef struct {
NS ns_id;
@@ -23,7 +21,7 @@ EXTERN kvec_t(WinExtmark) win_extmark_arr INIT( = KV_INITIAL_VALUE);
EXTERN bool conceal_cursor_used INIT( = false);
-// Spell checking variables passed from win_update() to win_line().
+/// Spell checking variables passed from win_update() to win_line().
typedef struct {
bool spv_has_spell; ///< drawn window has spell checking
bool spv_unchanged; ///< not updating for changed text
diff --git a/src/nvim/drawscreen.c b/src/nvim/drawscreen.c
index 6cc623cb72..1626e46cf6 100644
--- a/src/nvim/drawscreen.c
+++ b/src/nvim/drawscreen.c
@@ -1,5 +1,5 @@
// drawscreen.c: Code for updating all the windows on the screen.
-// This is the top level, drawline.c is the middle and grid.c/screen.c the lower level.
+// This is the top level, drawline.c is the middle and grid.c the lower level.
// update_screen() is the function that updates all windows and status lines.
// It is called from the main loop when must_redraw is non-zero. It may be
@@ -63,11 +63,13 @@
#include "nvim/api/private/defs.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
#include "nvim/cursor.h"
#include "nvim/decoration.h"
+#include "nvim/decoration_defs.h"
#include "nvim/decoration_provider.h"
#include "nvim/diff.h"
#include "nvim/digraph.h"
@@ -76,31 +78,36 @@
#include "nvim/eval.h"
#include "nvim/ex_getln.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
+#include "nvim/fold_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/insexpand.h"
+#include "nvim/marktree_defs.h"
#include "nvim/match.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/normal.h"
+#include "nvim/normal_defs.h"
#include "nvim/option.h"
#include "nvim/option_vars.h"
+#include "nvim/os/os_defs.h"
#include "nvim/plines.h"
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/regexp.h"
#include "nvim/search.h"
-#include "nvim/sign_defs.h"
#include "nvim/spell.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
@@ -108,6 +115,7 @@
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/ui_compositor.h"
+#include "nvim/ui_defs.h"
#include "nvim/version.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -151,8 +159,8 @@ void conceal_check_cursor_line(void)
/// There may be some time between setting Rows and Columns and (re)allocating
/// default_grid arrays. This happens when starting up and when
/// (manually) changing the screen size. Always use default_grid.rows and
-/// default_grid.Columns to access items in default_grid.chars[]. Use Rows
-/// and Columns for positioning text etc. where the final size of the screen is
+/// default_grid.cols to access items in default_grid.chars[]. Use Rows and
+/// Columns for positioning text etc. where the final size of the screen is
/// needed.
///
/// @return whether resizing has been done
@@ -443,7 +451,7 @@ int update_screen(void)
// will be redrawn later or in win_update().
must_redraw = 0;
- updating_screen = 1;
+ updating_screen = true;
display_tick++; // let syntax code know we're in a next round of
// display updating
@@ -547,13 +555,12 @@ int update_screen(void)
// might need to clear space on default_grid for the message area.
if (type == UPD_NOT_VALID && clear_cmdline && !ui_has(kUIMessages)) {
- grid_fill(&default_grid, Rows - (int)p_ch, Rows, 0, Columns, ' ', ' ', 0);
+ grid_clear(&default_grid, Rows - (int)p_ch, Rows, 0, Columns, 0);
}
ui_comp_set_screen_valid(true);
- DecorProviders providers;
- decor_providers_start(&providers);
+ decor_providers_start();
// "start" callback could have changed highlights for global elements
if (win_check_ns_hl(NULL)) {
@@ -600,19 +607,10 @@ int update_screen(void)
}
if (buf->b_mod_tick_decor < display_tick) {
- decor_providers_invoke_buf(buf, &providers);
+ decor_providers_invoke_buf(buf);
buf->b_mod_tick_decor = display_tick;
}
}
-
- // Reset 'statuscolumn' if there is no dedicated signcolumn but it is invalid.
- if (*wp->w_p_stc != NUL && wp->w_minscwidth <= SCL_NO
- && (wp->w_buffer->b_signcols.invalid_bot || !wp->w_buffer->b_signcols.sentinel)) {
- wp->w_nrwidth_line_count = 0;
- wp->w_valid &= ~VALID_WCOL;
- wp->w_redr_type = UPD_NOT_VALID;
- wp->w_buffer->b_signcols.invalid_bot = 0;
- }
}
// Go from top to bottom through the windows, redrawing the ones that need it.
@@ -639,7 +637,7 @@ int update_screen(void)
did_one = true;
start_search_hl();
}
- win_update(wp, &providers);
+ win_update(wp);
}
// redraw status line and window bar after the window to minimize cursor movement
@@ -659,13 +657,14 @@ int update_screen(void)
win_check_ns_hl(NULL);
- // Reset b_mod_set flags. Going through all windows is probably faster
- // than going through all buffers (there could be many buffers).
+ // Reset b_mod_set and b_signcols.resized flags. Going through all windows is
+ // probably faster than going through all buffers (there could be many buffers).
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
wp->w_buffer->b_mod_set = false;
+ wp->w_buffer->b_signcols.resized = false;
}
- updating_screen = 0;
+ updating_screen = false;
// Clear or redraw the command line. Done last, because scrolling may
// mess up the command line.
@@ -679,8 +678,7 @@ int update_screen(void)
}
did_intro = true;
- decor_providers_invoke_end(&providers);
- kvi_destroy(providers);
+ decor_providers_invoke_end();
// either cmdline is cleared, not drawn or mode is last drawn
cmdline_was_last_drawn = false;
@@ -740,7 +738,7 @@ int win_get_bordertext_col(int total_col, int text_width, AlignTextPos align)
static void win_redr_border(win_T *wp)
{
wp->w_redr_border = false;
- if (!(wp->w_floating && wp->w_float_config.border)) {
+ if (!(wp->w_floating && wp->w_config.border)) {
return;
}
@@ -748,9 +746,9 @@ static void win_redr_border(win_T *wp)
schar_T chars[8];
for (int i = 0; i < 8; i++) {
- chars[i] = schar_from_str(wp->w_float_config.border_chars[i]);
+ chars[i] = schar_from_str(wp->w_config.border_chars[i]);
}
- int *attrs = wp->w_float_config.border_attr;
+ int *attrs = wp->w_config.border_attr;
int *adj = wp->w_border_adj;
int irow = wp->w_height_inner + wp->w_winbar_height;
@@ -766,10 +764,10 @@ static void win_redr_border(win_T *wp)
grid_line_put_schar(i + adj[3], chars[1], attrs[1]);
}
- if (wp->w_float_config.title) {
- int title_col = win_get_bordertext_col(icol, wp->w_float_config.title_width,
- wp->w_float_config.title_pos);
- win_redr_bordertext(wp, wp->w_float_config.title_chunks, title_col);
+ if (wp->w_config.title) {
+ int title_col = win_get_bordertext_col(icol, wp->w_config.title_width,
+ wp->w_config.title_pos);
+ win_redr_bordertext(wp, wp->w_config.title_chunks, title_col);
}
if (adj[1]) {
grid_line_put_schar(icol + adj[3], chars[2], attrs[2]);
@@ -802,10 +800,10 @@ static void win_redr_border(win_T *wp)
grid_line_put_schar(i + adj[3], chars[ic], attrs[ic]);
}
- if (wp->w_float_config.footer) {
- int footer_col = win_get_bordertext_col(icol, wp->w_float_config.footer_width,
- wp->w_float_config.footer_pos);
- win_redr_bordertext(wp, wp->w_float_config.footer_chunks, footer_col);
+ if (wp->w_config.footer) {
+ int footer_col = win_get_bordertext_col(icol, wp->w_config.footer_width,
+ wp->w_config.footer_pos);
+ win_redr_bordertext(wp, wp->w_config.footer_chunks, footer_col);
}
if (adj[1]) {
grid_line_put_schar(icol + adj[3], chars[4], attrs[4]);
@@ -928,15 +926,14 @@ int showmode(void)
msg_grid_validate();
- int do_mode = ((p_smd && msg_silent == 0)
- && ((State & MODE_TERMINAL)
- || (State & MODE_INSERT)
- || restart_edit != NUL
- || VIsual_active));
+ bool do_mode = ((p_smd && msg_silent == 0)
+ && ((State & MODE_TERMINAL)
+ || (State & MODE_INSERT)
+ || restart_edit != NUL
+ || VIsual_active));
bool can_show_mode = (p_ch != 0 || ui_has(kUIMessages));
if ((do_mode || reg_recording != 0) && can_show_mode) {
- int sub_attr;
if (skip_showmode()) {
return 0; // show mode later
}
@@ -989,7 +986,8 @@ int showmode(void)
}
if (edit_submode_extra != NULL) {
msg_puts_attr(" ", attr); // Add a space in between.
- if ((int)edit_submode_highl < HLF_COUNT) {
+ int sub_attr;
+ if (edit_submode_highl < HLF_COUNT) {
sub_attr = win_hl_attr(curwin, (int)edit_submode_highl);
} else {
sub_attr = attr;
@@ -1151,11 +1149,11 @@ void clearmode(void)
static void recording_mode(int attr)
{
- msg_puts_attr(_("recording"), attr);
if (shortmess(SHM_RECORDING)) {
return;
}
+ msg_puts_attr(_("recording"), attr);
char s[4];
snprintf(s, ARRAY_SIZE(s), " @%c", reg_recording);
msg_puts_attr(s, attr);
@@ -1180,7 +1178,7 @@ void comp_col(void)
sc_col = ru_col;
}
}
- if (p_sc) {
+ if (p_sc && *p_sloc == 'l') {
sc_col += SHOWCMD_COLS;
if (!p_ru || last_has_status) { // no need for separating space
sc_col++;
@@ -1201,17 +1199,34 @@ void comp_col(void)
set_vim_var_nr(VV_ECHOSPACE, sc_col - 1);
}
-static void redraw_win_signcol(win_T *wp)
+/// Redraw entire window "wp" if "auto" 'signcolumn' width has changed.
+static bool win_redraw_signcols(win_T *wp)
{
- // If we can compute a change in the automatic sizing of the sign column
- // under 'signcolumn=auto:X' and signs currently placed in the buffer, better
- // figuring it out here so we can redraw the entire screen for it.
- int scwidth = wp->w_scwidth;
- wp->w_scwidth = win_signcol_count(wp);
- if (wp->w_scwidth != scwidth) {
- changed_line_abv_curs_win(wp);
- redraw_later(wp, UPD_NOT_VALID);
+ buf_T *buf = wp->w_buffer;
+
+ if (!buf->b_signcols.autom
+ && (*wp->w_p_stc != NUL || (wp->w_maxscwidth > 1 && wp->w_minscwidth != wp->w_maxscwidth))) {
+ buf->b_signcols.autom = true;
+ buf_signcols_count_range(buf, 0, buf->b_ml.ml_line_count, MAXLNUM, kFalse);
}
+
+ while (buf->b_signcols.max > 0 && buf->b_signcols.count[buf->b_signcols.max - 1] == 0) {
+ buf->b_signcols.resized = true;
+ buf->b_signcols.max--;
+ }
+
+ int width = MIN(wp->w_maxscwidth, buf->b_signcols.max);
+ bool rebuild_stc = buf->b_signcols.resized && *wp->w_p_stc != NUL;
+
+ if (rebuild_stc) {
+ wp->w_nrwidth_line_count = 0;
+ } else if (wp->w_minscwidth == 0 && wp->w_maxscwidth == 1) {
+ width = buf_meta_total(buf, kMTMetaSignText) > 0;
+ }
+
+ int scwidth = wp->w_scwidth;
+ wp->w_scwidth = MAX(MAX(0, wp->w_minscwidth), width);
+ return (wp->w_scwidth != scwidth || rebuild_stc);
}
/// Check if horizontal separator of window "wp" at specified window corner is connected to the
@@ -1293,10 +1308,11 @@ static void draw_vsep_win(win_T *wp)
}
// draw the vertical separator right of this window
- int hl = win_hl_attr(wp, HLF_C);
- int c = wp->w_p_fcs_chars.vert;
- grid_fill(&default_grid, wp->w_winrow, W_ENDROW(wp),
- W_ENDCOL(wp), W_ENDCOL(wp) + 1, c, ' ', hl);
+ for (int row = wp->w_winrow; row < W_ENDROW(wp); row++) {
+ grid_line_start(&default_grid, row);
+ grid_line_put_schar(W_ENDCOL(wp), wp->w_p_fcs_chars.vert, win_hl_attr(wp, HLF_C));
+ grid_line_flush();
+ }
}
/// Draw the horizontal separator below window "wp"
@@ -1307,10 +1323,9 @@ static void draw_hsep_win(win_T *wp)
}
// draw the horizontal separator below this window
- int hl = win_hl_attr(wp, HLF_C);
- int c = wp->w_p_fcs_chars.horiz;
- grid_fill(&default_grid, W_ENDROW(wp), W_ENDROW(wp) + 1,
- wp->w_wincol, W_ENDCOL(wp), c, c, hl);
+ grid_line_start(&default_grid, W_ENDROW(wp));
+ grid_line_fill(wp->w_wincol, W_ENDCOL(wp), wp->w_p_fcs_chars.horiz, win_hl_attr(wp, HLF_C));
+ grid_line_flush();
}
/// Get the separator connector for specified window corner of window "wp"
@@ -1318,21 +1333,19 @@ static schar_T get_corner_sep_connector(win_T *wp, WindowCorner corner)
{
// It's impossible for windows to be connected neither vertically nor horizontally
// So if they're not vertically connected, assume they're horizontally connected
- int c;
if (vsep_connected(wp, corner)) {
if (hsep_connected(wp, corner)) {
- c = wp->w_p_fcs_chars.verthoriz;
+ return wp->w_p_fcs_chars.verthoriz;
} else if (corner == WC_TOP_LEFT || corner == WC_BOTTOM_LEFT) {
- c = wp->w_p_fcs_chars.vertright;
+ return wp->w_p_fcs_chars.vertright;
} else {
- c = wp->w_p_fcs_chars.vertleft;
+ return wp->w_p_fcs_chars.vertleft;
}
} else if (corner == WC_TOP_LEFT || corner == WC_TOP_RIGHT) {
- c = wp->w_p_fcs_chars.horizdown;
+ return wp->w_p_fcs_chars.horizdown;
} else {
- c = wp->w_p_fcs_chars.horizup;
+ return wp->w_p_fcs_chars.horizup;
}
- return schar_from_char(c);
}
/// Draw separator connecting characters on the corners of window "wp"
@@ -1414,14 +1427,14 @@ static void draw_sep_connectors_win(win_T *wp)
/// - if wp->w_buffer->b_mod_set set, update lines between
/// b_mod_top and b_mod_bot.
/// - if wp->w_redraw_top non-zero, redraw lines between
-/// wp->w_redraw_top and wp->w_redr_bot.
+/// wp->w_redraw_top and wp->w_redraw_bot.
/// - continue redrawing when syntax status is invalid.
/// 4. if scrolled up, update lines at the bottom.
/// This results in three areas that may need updating:
/// top: from first row to top_end (when scrolled down)
/// mid: from mid_start to mid_end (update inversion or changed text)
/// bot: from bot_start to last row (when scrolled up)
-static void win_update(win_T *wp, DecorProviders *providers)
+static void win_update(win_T *wp)
{
int top_end = 0; // Below last row of the top area that needs
// updating. 0 when no top area updating.
@@ -1488,10 +1501,13 @@ static void win_update(win_T *wp, DecorProviders *providers)
decor_redraw_reset(wp, &decor_state);
- DecorProviders line_providers;
- decor_providers_invoke_win(wp, providers, &line_providers);
+ decor_providers_invoke_win(wp);
- redraw_win_signcol(wp);
+ if (win_redraw_signcols(wp)) {
+ wp->w_lines_valid = 0;
+ wp->w_redr_type = UPD_NOT_VALID;
+ changed_line_abv_curs_win(wp);
+ }
init_search_hl(wp, &screen_search_hl);
@@ -1521,13 +1537,6 @@ static void win_update(win_T *wp, DecorProviders *providers)
if (wp->w_nrwidth != nrwidth_new) {
type = UPD_NOT_VALID;
wp->w_nrwidth = nrwidth_new;
- } else if (buf->b_mod_set
- && buf->b_mod_xlines != 0
- && wp->w_redraw_top != 0) {
- // When there are both inserted/deleted lines and specific lines to be
- // redrawn, w_redraw_top and w_redraw_bot may be invalid, just redraw
- // everything (only happens when redrawing is off for while).
- type = UPD_NOT_VALID;
} else {
// Set mod_top to the first line that needs displaying because of
// changes. Set mod_bot to the first line after the changes.
@@ -1602,14 +1611,14 @@ static void win_update(win_T *wp, DecorProviders *providers)
}
}
- (void)hasFoldingWin(wp, mod_top, &mod_top, NULL, true, NULL);
+ hasFoldingWin(wp, mod_top, &mod_top, NULL, true, NULL);
if (mod_top > lnumt) {
mod_top = lnumt;
}
// Now do the same for the bottom line (one above mod_bot).
mod_bot--;
- (void)hasFoldingWin(wp, mod_bot, NULL, &mod_bot, true, NULL);
+ hasFoldingWin(wp, mod_bot, NULL, &mod_bot, true, NULL);
mod_bot++;
if (mod_bot < lnumb) {
mod_bot = lnumb;
@@ -1627,12 +1636,6 @@ static void win_update(win_T *wp, DecorProviders *providers)
top_end = 1;
}
}
-
- // When line numbers are displayed need to redraw all lines below
- // inserted/deleted lines.
- if (mod_top != 0 && buf->b_mod_xlines != 0 && wp->w_p_nu) {
- mod_bot = MAXLNUM;
- }
}
wp->w_redraw_top = 0; // reset for next time
@@ -1680,17 +1683,15 @@ static void win_update(win_T *wp, DecorProviders *providers)
// New topline is above old topline: May scroll down.
int j;
if (hasAnyFolding(wp)) {
- linenr_T ln;
-
// count the number of lines we are off, counting a sequence
// of folded lines as one
j = 0;
- for (ln = wp->w_topline; ln < wp->w_lines[0].wl_lnum; ln++) {
+ for (linenr_T ln = wp->w_topline; ln < wp->w_lines[0].wl_lnum; ln++) {
j++;
if (j >= wp->w_grid.rows - 2) {
break;
}
- (void)hasFoldingWin(wp, ln, NULL, &ln, true, NULL);
+ hasFoldingWin(wp, ln, NULL, &ln, true, NULL);
}
} else {
j = wp->w_lines[0].wl_lnum - wp->w_topline;
@@ -2270,23 +2271,28 @@ static void win_update(win_T *wp, DecorProviders *providers)
syntax_end_parsing(wp, syntax_last_parsed + 1);
}
+ bool display_buf_line = (foldinfo.fi_lines == 0 || *wp->w_p_fdt == NUL);
+
// Display one line
spellvars_T zero_spv = { 0 };
- row = win_line(wp, lnum, srow, wp->w_grid.rows, false,
- foldinfo.fi_lines > 0 ? &zero_spv : &spv,
- foldinfo, &line_providers);
+ row = win_line(wp, lnum, srow, wp->w_grid.rows, 0,
+ display_buf_line ? &spv : &zero_spv, foldinfo);
+
+ if (display_buf_line) {
+ syntax_last_parsed = lnum;
+ } else {
+ spv.spv_capcol_lnum = 0;
+ }
if (foldinfo.fi_lines == 0) {
wp->w_lines[idx].wl_folded = false;
wp->w_lines[idx].wl_lastlnum = lnum;
did_update = DID_LINE;
- syntax_last_parsed = lnum;
} else {
foldinfo.fi_lines--;
wp->w_lines[idx].wl_folded = true;
wp->w_lines[idx].wl_lastlnum = lnum + foldinfo.fi_lines;
did_update = DID_FOLD;
- spv.spv_capcol_lnum = 0;
}
}
@@ -2307,12 +2313,15 @@ static void win_update(win_T *wp, DecorProviders *providers)
idx++;
lnum += foldinfo.fi_lines + 1;
} else {
- if (wp->w_p_rnu && wp->w_last_cursor_lnum_rnu != wp->w_cursor.lnum) {
- // 'relativenumber' set and cursor moved vertically: The
- // text doesn't need to be drawn, but the number column does.
+ // If:
+ // - 'number' is set and below inserted/deleted lines, or
+ // - 'relativenumber' is set and cursor moved vertically,
+ // the text doesn't need to be redrawn, but the number column does.
+ if ((wp->w_p_nu && mod_top != 0 && lnum >= mod_bot && buf->b_mod_xlines != 0)
+ || (wp->w_p_rnu && wp->w_last_cursor_lnum_rnu != wp->w_cursor.lnum)) {
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, &spv, info, &line_providers);
+ win_line(wp, lnum, srow, wp->w_grid.rows, wp->w_lines[idx].wl_size, &spv, info);
}
// This line does not need to be drawn, advance to the next one.
@@ -2327,6 +2336,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// 'statuscolumn' width has changed or errored, start from the top.
if (wp->w_redr_statuscol) {
+redr_statuscol:
wp->w_redr_statuscol = false;
idx = 0;
row = 0;
@@ -2334,7 +2344,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
wp->w_lines_valid = 0;
wp->w_valid &= ~VALID_WCOL;
decor_redraw_reset(wp, &decor_state);
- decor_providers_invoke_win(wp, providers, &line_providers);
+ decor_providers_invoke_win(wp);
continue;
}
@@ -2380,7 +2390,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// Last line isn't finished: Display "@@@" in the last screen line.
grid_line_start(&wp->w_grid, wp->w_grid.rows - 1);
grid_line_fill(0, MIN(wp->w_grid.cols, 3), wp->w_p_fcs_chars.lastline, at_attr);
- grid_line_fill(3, wp->w_grid.cols, ' ', at_attr);
+ grid_line_fill(3, wp->w_grid.cols, schar_from_ascii(' '), at_attr);
grid_line_flush();
set_empty_rows(wp, srow);
wp->w_botline = lnum;
@@ -2395,7 +2405,8 @@ static void win_update(win_T *wp, DecorProviders *providers)
set_empty_rows(wp, srow);
wp->w_botline = lnum;
} else {
- win_draw_end(wp, wp->w_p_fcs_chars.lastline, ' ', true, srow, wp->w_grid.rows, HLF_AT);
+ win_draw_end(wp, wp->w_p_fcs_chars.lastline, true, srow,
+ wp->w_grid.rows, HLF_AT);
set_empty_rows(wp, srow);
wp->w_botline = lnum;
}
@@ -2408,8 +2419,11 @@ static void win_update(win_T *wp, DecorProviders *providers)
// for ml_line_count+1 and only draw filler lines
spellvars_T zero_spv = { 0 };
foldinfo_T zero_foldinfo = { 0 };
- row = win_line(wp, wp->w_botline, row, wp->w_grid.rows, false, &zero_spv,
- zero_foldinfo, &line_providers);
+ row = win_line(wp, wp->w_botline, row, wp->w_grid.rows, 0, &zero_spv, zero_foldinfo);
+ if (wp->w_redr_statuscol) {
+ eof = false;
+ goto redr_statuscol;
+ }
}
} else if (dollar_vcol == -1) {
wp->w_botline = lnum;
@@ -2428,13 +2442,12 @@ static void win_update(win_T *wp, DecorProviders *providers)
lastline = 0;
}
- win_draw_end(wp, wp->w_p_fcs_chars.eob, ' ', false, MAX(lastline, row), wp->w_grid.rows,
+ win_draw_end(wp, wp->w_p_fcs_chars.eob, false, MAX(lastline, row),
+ wp->w_grid.rows,
HLF_EOB);
set_empty_rows(wp, row);
}
- kvi_destroy(line_providers);
-
if (wp->w_redr_type >= UPD_REDRAW_TOP) {
draw_vsep_win(wp);
draw_hsep_win(wp);
@@ -2475,7 +2488,7 @@ static void win_update(win_T *wp, DecorProviders *providers)
// Don't update for changes in buffer again.
int mod_set = curbuf->b_mod_set;
curbuf->b_mod_set = false;
- win_update(curwin, providers);
+ win_update(curwin);
must_redraw = 0;
curbuf->b_mod_set = mod_set;
}
@@ -2517,63 +2530,43 @@ void win_scroll_lines(win_T *wp, int row, int line_count)
}
}
-/// Call grid_fill() with columns adjusted for 'rightleft' if needed.
-/// Return the new offset.
-static int win_fill_end(win_T *wp, int c1, int c2, int off, int width, int row, int endrow,
- int attr)
-{
- int nn = off + width;
- const int endcol = wp->w_grid.cols;
-
- if (nn > endcol) {
- nn = endcol;
- }
-
- if (wp->w_p_rl) {
- grid_fill(&wp->w_grid, row, endrow, endcol - nn, endcol - off, c1, c2, attr);
- } else {
- grid_fill(&wp->w_grid, row, endrow, off, nn, c1, c2, attr);
- }
-
- return nn;
-}
-
/// Clear lines near the end of the window and mark the unused lines with "c1".
-/// Use "c2" as filler character.
/// When "draw_margin" is true, then draw the sign/fold/number columns.
-void win_draw_end(win_T *wp, int c1, int c2, bool draw_margin, int row, int endrow, hlf_T hl)
+void win_draw_end(win_T *wp, schar_T c1, bool draw_margin, int startrow, int endrow, hlf_T hl)
{
assert(hl >= 0 && hl < HLF_COUNT);
- int n = 0;
-
- if (draw_margin) {
- // draw the fold column
- int fdc = compute_foldcolumn(wp, 0);
- if (fdc > 0) {
- n = win_fill_end(wp, ' ', ' ', n, fdc, row, endrow,
- win_hl_attr(wp, HLF_FC));
- }
- // draw the sign column
- int count = wp->w_scwidth;
- if (count > 0) {
- n = win_fill_end(wp, ' ', ' ', n, SIGN_WIDTH * count, row,
- endrow, win_hl_attr(wp, HLF_SC));
+ for (int row = startrow; row < endrow; row++) {
+ grid_line_start(&wp->w_grid, row);
+
+ int n = 0;
+ if (draw_margin) {
+ // draw the fold column
+ int fdc = MAX(0, compute_foldcolumn(wp, 0));
+ n = grid_line_fill(n, n + fdc, schar_from_ascii(' '), win_hl_attr(wp, HLF_FC));
+
+ // draw the sign column
+ n = grid_line_fill(n, n + wp->w_scwidth, schar_from_ascii(' '), win_hl_attr(wp, HLF_FC));
+
+ // draw the number column
+ if ((wp->w_p_nu || wp->w_p_rnu) && vim_strchr(p_cpo, CPO_NUMCOL) == NULL) {
+ int width = number_width(wp) + 1;
+ n = grid_line_fill(n, n + width, schar_from_ascii(' '), win_hl_attr(wp, HLF_N));
+ }
}
- // draw the number column
- if ((wp->w_p_nu || wp->w_p_rnu) && vim_strchr(p_cpo, CPO_NUMCOL) == NULL) {
- n = win_fill_end(wp, ' ', ' ', n, number_width(wp) + 1, row, endrow,
- win_hl_attr(wp, HLF_N));
+
+ int attr = hl_combine_attr(win_bg_attr(wp), win_hl_attr(wp, (int)hl));
+
+ if (n < wp->w_grid.cols) {
+ grid_line_put_schar(n, c1, 0); // base attr is inherited from clear
+ n++;
}
- }
- int attr = hl_combine_attr(win_bg_attr(wp), win_hl_attr(wp, (int)hl));
+ grid_line_clear_end(n, wp->w_grid.cols, attr);
- const int endcol = wp->w_grid.cols;
- if (wp->w_p_rl) {
- grid_fill(&wp->w_grid, row, endrow, 0, endcol - 1 - n, c2, c2, attr);
- grid_fill(&wp->w_grid, row, endrow, endcol - 1 - n, endcol - n, c1, c2, attr);
- } else {
- grid_fill(&wp->w_grid, row, endrow, n, endcol, c1, c2, attr);
+ if (wp->w_p_rl) {
+ grid_line_mirror();
+ }
+ grid_line_flush();
}
}
@@ -2631,7 +2624,7 @@ int number_width(win_T *wp)
// If 'signcolumn' is set to 'number' and there is a sign to display, then
// the minimal width for the number column is 2.
- if (n < 2 && wp->w_buffer->b_signs_with_text && wp->w_minscwidth == SCL_NUM) {
+ if (n < 2 && buf_meta_total(wp->w_buffer, kMTMetaSignText) && wp->w_minscwidth == SCL_NUM) {
n = 2;
}
@@ -2644,9 +2637,10 @@ int number_width(win_T *wp)
/// Set must_redraw only if not already set to a higher value.
/// e.g. if must_redraw is UPD_CLEAR, type UPD_NOT_VALID will do nothing.
void redraw_later(win_T *wp, int type)
- FUNC_ATTR_NONNULL_ALL
{
- if (!exiting && wp->w_redr_type < type) {
+ // curwin may have been set to NULL when exiting
+ assert(wp != NULL || exiting);
+ if (!exiting && !redraw_not_allowed && wp->w_redr_type < type) {
wp->w_redr_type = type;
if (type >= UPD_NOT_VALID) {
wp->w_lines_valid = 0;
@@ -2664,7 +2658,14 @@ void redraw_all_later(int type)
redraw_later(wp, type);
}
// This may be needed when switching tabs.
- if (must_redraw < type) {
+ set_must_redraw(type);
+}
+
+/// Set "must_redraw" to "type" unless it already has a higher value
+/// or it is currently not allowed.
+void set_must_redraw(int type)
+{
+ if (!redraw_not_allowed && must_redraw < type) {
must_redraw = type;
}
}
@@ -2729,9 +2730,7 @@ void redraw_buf_status_later(buf_T *buf)
|| (wp == curwin && global_stl_height())
|| wp->w_winbar_height)) {
wp->w_redr_status = true;
- if (must_redraw < UPD_VALID) {
- must_redraw = UPD_VALID;
- }
+ set_must_redraw(UPD_VALID);
}
}
}
@@ -2865,15 +2864,3 @@ bool win_cursorline_standout(const win_T *wp)
{
return wp->w_p_cul || (wp->w_p_cole > 0 && !conceal_cursor_line(wp));
}
-
-/// Redraw when w_cline_row changes and 'relativenumber' or 'cursorline' is set.
-/// Also when concealing is on and 'concealcursor' is not active.
-void redraw_for_cursorline(win_T *wp)
- FUNC_ATTR_NONNULL_ALL
-{
- if ((wp->w_valid & VALID_CROW) == 0 && !pum_visible()
- && (wp->w_p_rnu || win_cursorline_standout(wp))) {
- // win_line() will redraw the number column and cursorline only.
- redraw_later(wp, UPD_VALID);
- }
-}
diff --git a/src/nvim/drawscreen.h b/src/nvim/drawscreen.h
index 565b01bcd1..f804345bca 100644
--- a/src/nvim/drawscreen.h
+++ b/src/nvim/drawscreen.h
@@ -3,7 +3,6 @@
#include <stdbool.h>
#include "nvim/buffer_defs.h"
-#include "nvim/drawline.h"
#include "nvim/macros_defs.h"
/// flags for update_screen()
@@ -20,9 +19,13 @@ enum {
/// While redrawing the screen this flag is set. It means the screen size
/// ('lines' and 'rows') must not be changed.
-EXTERN bool updating_screen INIT( = 0);
+EXTERN bool updating_screen INIT( = false);
-EXTERN match_T screen_search_hl INIT( = { 0 }); // used for 'hlsearch' highlight matching
+/// While computing a statusline and the like we do not want any w_redr_type or
+/// must_redraw to be set.
+EXTERN bool redraw_not_allowed INIT( = false);
+
+EXTERN match_T screen_search_hl INIT( = { 0 }); ///< used for 'hlsearch' highlight matching
#define W_ENDCOL(wp) ((wp)->w_wincol + (wp)->w_width)
#define W_ENDROW(wp) ((wp)->w_winrow + (wp)->w_height)
diff --git a/src/nvim/edit.c b/src/nvim/edit.c
index 71a12ea1b0..b7b32883c2 100644
--- a/src/nvim/edit.c
+++ b/src/nvim/edit.c
@@ -5,12 +5,13 @@
#include <inttypes.h>
#include <stdbool.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/change.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
@@ -22,14 +23,15 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/extmark.h"
+#include "nvim/extmark_defs.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
@@ -38,13 +40,17 @@
#include "nvim/macros_defs.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
+#include "nvim/marktree_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"
+#include "nvim/normal_defs.h"
#include "nvim/ops.h"
#include "nvim/option.h"
#include "nvim/option_vars.h"
@@ -54,6 +60,7 @@
#include "nvim/pos_defs.h"
#include "nvim/search.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/terminal.h"
@@ -61,11 +68,12 @@
#include "nvim/textobject.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
-typedef struct insert_state {
+typedef struct {
VimState state;
cmdarg_T *ca;
int mincol;
@@ -113,7 +121,7 @@ static int did_restart_edit; // "restart_edit" when calling edit()
static bool can_cindent; // may do cindenting on this line
-static int revins_on; // reverse insert mode on
+static bool revins_on; // reverse insert mode on
static int revins_chars; // how much to skip after edit
static int revins_legal; // was the last char 'legal'?
static int revins_scol; // start column of revins session
@@ -233,7 +241,7 @@ static void insert_enter(InsertState *s)
// need to position cursor again when on a TAB and
// when on a char with inline virtual text
- if (gchar_cursor() == TAB || curbuf->b_virt_text_inline > 0) {
+ if (gchar_cursor() == TAB || buf_meta_total(curbuf, kMTMetaInline) > 0) {
curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
}
@@ -355,7 +363,13 @@ static void insert_enter(InsertState *s)
ins_apply_autocmds(EVENT_INSERTLEAVE);
}
did_cursorhold = false;
- curbuf->b_last_changedtick = buf_get_changedtick(curbuf);
+
+ // ins_redraw() triggers TextChangedI only when no characters
+ // are in the typeahead buffer, so only reset curbuf->b_last_changedtick
+ // if the TextChangedI was not blocked by char_avail() (e.g. using :norm!)
+ if (!char_avail()) {
+ curbuf->b_last_changedtick = buf_get_changedtick(curbuf);
+ }
}
static int insert_check(VimState *state)
@@ -395,7 +409,7 @@ static int insert_check(VimState *state)
Insstart_orig = Insstart;
}
- if (curbuf->terminal) {
+ if (curbuf->terminal && !stop_insert_mode) {
// Exit Insert mode and go to Terminal mode.
stop_insert_mode = true;
restart_edit = 'I';
@@ -445,8 +459,11 @@ static int insert_check(VimState *state)
// is detected when the cursor column is smaller after inserting something.
// Don't do this when the topline changed already, it has already been
// adjusted (by insertchar() calling open_line())).
+ // Also don't do this when 'smoothscroll' is set, as the window should then
+ // be scrolled by screen lines.
if (curbuf->b_mod_set
&& curwin->w_p_wrap
+ && !curwin->w_p_sms
&& !s->did_backspace
&& curwin->w_topline == s->old_topline
&& curwin->w_topfill == s->old_topfill) {
@@ -456,8 +473,7 @@ static int insert_check(VimState *state)
if (curwin->w_wcol < s->mincol - tabstop_at(get_nolist_virtcol(),
curbuf->b_p_ts,
curbuf->b_p_vts_array)
- && curwin->w_wrow == curwin->w_winrow
- + curwin->w_height_inner - 1 - get_scrolloff_value(curwin)
+ && curwin->w_wrow == curwin->w_height_inner - 1 - get_scrolloff_value(curwin)
&& (curwin->w_cursor.lnum != curwin->w_topline
|| curwin->w_topfill > 0)) {
if (curwin->w_topfill > 0) {
@@ -1429,50 +1445,52 @@ static int pc_col;
void edit_putchar(int c, bool highlight)
{
- if (curwin->w_grid_alloc.chars != NULL || default_grid.chars != NULL) {
- int attr;
- update_topline(curwin); // just in case w_topline isn't valid
- validate_cursor();
- if (highlight) {
- attr = HL_ATTR(HLF_8);
- } else {
- attr = 0;
- }
- pc_row = curwin->w_wrow;
- pc_status = PC_STATUS_UNSET;
- grid_line_start(&curwin->w_grid, pc_row);
- if (curwin->w_p_rl) {
- pc_col = curwin->w_grid.cols - 1 - curwin->w_wcol;
-
- if (grid_line_getchar(pc_col, NULL) == NUL) {
- grid_line_put_schar(pc_col - 1, schar_from_ascii(' '), attr);
- curwin->w_wcol--;
- pc_status = PC_STATUS_RIGHT;
- }
- } else {
- pc_col = curwin->w_wcol;
+ if (curwin->w_grid_alloc.chars == NULL && default_grid.chars == NULL) {
+ return;
+ }
- if (grid_line_getchar(pc_col + 1, NULL) == NUL) {
- // pc_col is the left half of a double-width char
- pc_status = PC_STATUS_LEFT;
- }
+ int attr;
+ update_topline(curwin); // just in case w_topline isn't valid
+ validate_cursor();
+ if (highlight) {
+ attr = HL_ATTR(HLF_8);
+ } else {
+ attr = 0;
+ }
+ pc_row = curwin->w_wrow;
+ pc_status = PC_STATUS_UNSET;
+ grid_line_start(&curwin->w_grid, pc_row);
+ if (curwin->w_p_rl) {
+ pc_col = curwin->w_grid.cols - 1 - curwin->w_wcol;
+
+ if (grid_line_getchar(pc_col, NULL) == NUL) {
+ grid_line_put_schar(pc_col - 1, schar_from_ascii(' '), attr);
+ curwin->w_wcol--;
+ pc_status = PC_STATUS_RIGHT;
}
+ } else {
+ pc_col = curwin->w_wcol;
- // save the character to be able to put it back
- if (pc_status == PC_STATUS_UNSET) {
- pc_schar = grid_line_getchar(pc_col, &pc_attr);
- pc_status = PC_STATUS_SET;
+ if (grid_line_getchar(pc_col + 1, NULL) == NUL) {
+ // pc_col is the left half of a double-width char
+ pc_status = PC_STATUS_LEFT;
}
+ }
- char buf[MB_MAXCHAR + 1];
- grid_line_puts(pc_col, buf, utf_char2bytes(c, buf), attr);
- grid_line_flush();
+ // save the character to be able to put it back
+ if (pc_status == PC_STATUS_UNSET) {
+ pc_schar = grid_line_getchar(pc_col, &pc_attr);
+ pc_status = PC_STATUS_SET;
}
+
+ char buf[MB_MAXCHAR + 1];
+ grid_line_puts(pc_col, buf, utf_char2bytes(c, buf), attr);
+ grid_line_flush();
}
/// @return the effective prompt for the specified buffer.
char *buf_prompt_text(const buf_T *const buf)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
{
if (buf->b_prompt_text == NULL) {
return "% ";
@@ -1581,10 +1599,12 @@ void display_dollar(colnr_T col_arg)
// in insert mode.
void undisplay_dollar(void)
{
- if (dollar_vcol >= 0) {
- dollar_vcol = -1;
- redrawWinline(curwin, curwin->w_cursor.lnum);
+ if (dollar_vcol < 0) {
+ return;
}
+
+ dollar_vcol = -1;
+ redrawWinline(curwin, curwin->w_cursor.lnum);
}
/// Insert an indent (for <Tab> or CTRL-T) or delete an indent (for CTRL-D).
@@ -1596,7 +1616,7 @@ void undisplay_dollar(void)
/// @param round if true, round the indent to 'shiftwidth' (only with _INC and _Dec).
/// @param replaced replaced character, put on replace stack
/// @param call_changed_bytes call changed_bytes()
-void change_indent(int type, int amount, int round, int replaced, int call_changed_bytes)
+void change_indent(int type, int amount, int round, int replaced, bool call_changed_bytes)
{
int insstart_less; // reduction for Insstart.col
colnr_T orig_col = 0; // init for GCC
@@ -1638,7 +1658,7 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
// Set the new indent. The cursor will be put on the first non-blank.
if (type == INDENT_SET) {
- (void)set_indent(amount, call_changed_bytes ? SIN_CHANGED : 0);
+ set_indent(amount, call_changed_bytes ? SIN_CHANGED : 0);
} else {
int save_State = State;
@@ -1670,33 +1690,37 @@ void change_indent(int type, int amount, int round, int replaced, int call_chang
} else {
// Compute the screen column where the cursor should be.
vcol = get_indent() - vcol;
- curwin->w_virtcol = (colnr_T)((vcol < 0) ? 0 : vcol);
+ int const end_vcol = (colnr_T)((vcol < 0) ? 0 : vcol);
+ curwin->w_virtcol = end_vcol;
// Advance the cursor until we reach the right screen column.
- int last_vcol = 0;
- char *ptr = get_cursor_line_ptr();
- chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, 0, 0, ptr, ptr);
- while (cts.cts_vcol <= (int)curwin->w_virtcol) {
- last_vcol = cts.cts_vcol;
- if (cts.cts_vcol > 0) {
- MB_PTR_ADV(cts.cts_ptr);
- }
- if (*cts.cts_ptr == NUL) {
- break;
+ new_cursor_col = 0;
+ char *const line = get_cursor_line_ptr();
+ vcol = 0;
+ if (*line != NUL) {
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, curwin, 0, line);
+ StrCharInfo ci = utf_ptr2StrCharInfo(line);
+ while (true) {
+ int next_vcol = vcol + win_charsize(cstype, vcol, ci.ptr, ci.chr.value, &csarg).width;
+ if (next_vcol > end_vcol) {
+ break;
+ }
+ vcol = next_vcol;
+ ci = utfc_next(ci);
+ if (*ci.ptr == NUL) {
+ break;
+ }
}
- cts.cts_vcol += lbr_chartabsize(&cts);
+ new_cursor_col = (int)(ci.ptr - line);
}
- vcol = last_vcol;
- new_cursor_col = (int)(cts.cts_ptr - cts.cts_line);
- clear_chartabsize_arg(&cts);
// May need to insert spaces to be able to position the cursor on
// the right screen column.
if (vcol != (int)curwin->w_virtcol) {
curwin->w_cursor.col = (colnr_T)new_cursor_col;
size_t i = (size_t)(curwin->w_virtcol - vcol);
- ptr = xmallocz(i);
+ char *ptr = xmallocz(i);
memset(ptr, ' ', i);
new_cursor_col += (int)i;
ins_str(ptr);
@@ -2136,11 +2160,10 @@ void insertchar(int c, int flags, int second_indent)
&& !p_ri) {
#define INPUT_BUFLEN 100
char buf[INPUT_BUFLEN + 1];
- int i;
colnr_T virtcol = 0;
buf[0] = (char)c;
- i = 1;
+ int i = 1;
if (textwidth > 0) {
virtcol = get_nolist_virtcol();
}
@@ -2454,9 +2477,7 @@ void beginline(int flags)
curwin->w_cursor.coladd = 0;
if (flags & (BL_WHITE | BL_SOL)) {
- char *ptr;
-
- for (ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr)
+ for (char *ptr = get_cursor_line_ptr(); ascii_iswhite(*ptr)
&& !((flags & BL_FIX) && ptr[1] == NUL); ptr++) {
curwin->w_cursor.col++;
}
@@ -2569,7 +2590,7 @@ void cursor_up_inner(win_T *wp, linenr_T n)
// Count each sequence of folded lines as one logical line.
// go to the start of the current fold
- (void)hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL);
+ hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL);
while (n--) {
// move up one line
@@ -2581,7 +2602,7 @@ void cursor_up_inner(win_T *wp, linenr_T n)
// Insert mode or when 'foldopen' contains "all": it will open
// in a moment.
if (n > 0 || !((State & MODE_INSERT) || (fdo_flags & FDO_ALL))) {
- (void)hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL);
+ hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL);
}
}
if (lnum < 1) {
@@ -2595,7 +2616,7 @@ void cursor_up_inner(win_T *wp, linenr_T n)
}
/// @param upd_topline When true: update topline
-int cursor_up(linenr_T n, int upd_topline)
+int cursor_up(linenr_T n, bool upd_topline)
{
// This fails if the cursor is already in the first line.
if (n > 0 && curwin->w_cursor.lnum <= 1) {
@@ -2648,7 +2669,7 @@ void cursor_down_inner(win_T *wp, int n)
}
/// @param upd_topline When true: update topline
-int cursor_down(int n, int upd_topline)
+int cursor_down(int n, bool upd_topline)
{
// This fails if the cursor is already in the last line.
if (n > 0 && curwin->w_cursor.lnum >= curwin->w_buffer->b_ml.ml_line_count) {
@@ -2945,7 +2966,7 @@ static void replace_do_bs(int limit_col)
getvcol(curwin, &curwin->w_cursor, NULL, &start_vcol, NULL);
orig_vcols = win_chartabsize(curwin, get_cursor_pos_ptr(), start_vcol);
}
- (void)del_char_after_col(limit_col);
+ del_char_after_col(limit_col);
if (l_State & VREPLACE_FLAG) {
orig_len = (int)strlen(get_cursor_pos_ptr());
}
@@ -2976,7 +2997,7 @@ static void replace_do_bs(int limit_col)
// mark the buffer as changed and prepare for displaying
changed_bytes(curwin->w_cursor.lnum, curwin->w_cursor.col);
} else if (cc == 0) {
- (void)del_char_after_col(limit_col);
+ del_char_after_col(limit_col);
}
}
@@ -3003,10 +3024,9 @@ bool cindent_on(void)
bool in_cinkeys(int keytyped, int when, bool line_is_empty)
{
char *look;
- int try_match;
- int try_match_word;
+ bool try_match;
+ bool try_match_word;
char *p;
- char *line;
bool icase;
if (keytyped == NUL) {
@@ -3148,7 +3168,7 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
// Just completed a word, check if it starts with "look".
// search back for the start of a word.
- line = get_cursor_line_ptr();
+ char *line = get_cursor_line_ptr();
for (s = line + curwin->w_cursor.col; s > line; s = n) {
n = mb_prevptr(line, s);
if (!vim_iswordp(n)) {
@@ -3165,9 +3185,9 @@ bool in_cinkeys(int keytyped, int when, bool line_is_empty)
} else {
// TODO(@brammool): multi-byte
if (keytyped == (int)(uint8_t)p[-1]
- || (icase && keytyped < 256
+ || (icase && keytyped < 256 && keytyped >= 0
&& TOLOWER_LOC(keytyped) == TOLOWER_LOC((uint8_t)p[-1]))) {
- line = get_cursor_pos_ptr();
+ char *line = get_cursor_pos_ptr();
assert(p >= look && (uintmax_t)(p - look) <= SIZE_MAX);
if ((curwin->w_cursor.col == (colnr_T)(p - look)
|| !vim_iswordc((uint8_t)line[-(p - look) - 1]))
@@ -3411,7 +3431,7 @@ static bool ins_esc(int *count, int cmdchar, bool nomove)
State &= ~REPLACE_FLAG;
}
- (void)start_redo_ins();
+ start_redo_ins();
if (cmdchar == 'r' || cmdchar == 'v') {
stuffRedoReadbuff(ESC_STR); // No ESC in redo buffer
}
@@ -3463,7 +3483,7 @@ static bool ins_esc(int *count, int cmdchar, bool nomove)
may_trigger_modechanged();
// need to position cursor again when on a TAB and
// when on a char with inline virtual text
- if (gchar_cursor() == TAB || curbuf->b_virt_text_inline > 0) {
+ if (gchar_cursor() == TAB || buf_meta_total(curbuf, kMTMetaInline) > 0) {
curwin->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL);
}
@@ -3601,7 +3621,7 @@ static void ins_shift(int c, int lastc)
if (c == Ctrl_D && (lastc == '0' || lastc == '^')
&& curwin->w_cursor.col > 0) {
curwin->w_cursor.col--;
- (void)del_char(false); // delete the '^' or '0'
+ del_char(false); // delete the '^' or '0'
// In Replace mode, restore the characters that '^' or '0' replaced.
if (State & REPLACE_FLAG) {
replace_pop_ins();
@@ -3666,7 +3686,7 @@ static void ins_bs_one(colnr_T *vcolp)
replace_do_bs(-1);
}
} else {
- (void)del_char(false);
+ del_char(false);
}
}
@@ -3707,7 +3727,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
if (stop_arrow() == FAIL) {
return false;
}
- int in_indent = inindent(0);
+ bool in_indent = inindent(0);
if (in_indent) {
can_cindent = false;
}
@@ -3765,9 +3785,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
if (has_format_option(FO_AUTO)
&& has_format_option(FO_WHITE_PAR)) {
char *ptr = ml_get_buf_mut(curbuf, curwin->w_cursor.lnum);
- int len;
-
- len = (int)strlen(ptr);
+ int len = (int)strlen(ptr);
if (len > 0 && ptr[len - 1] == ' ') {
ptr[len - 1] = NUL;
}
@@ -3917,7 +3935,7 @@ static bool ins_bs(int c, int mode, int *inserted_space_p)
char *p0 = get_cursor_pos_ptr();
has_composing = utf_composinglike(p0, p0 + utf_ptr2len(p0));
}
- (void)del_char(false);
+ del_char(false);
// If there are combining characters and 'delcombine' is set
// move the cursor back. Don't back up before the base character.
if (has_composing) {
@@ -4061,7 +4079,7 @@ static void ins_s_left(void)
if (!end_change) {
AppendCharToRedobuff(K_S_LEFT);
}
- (void)bck_word(1, false, false);
+ bck_word(1, false, false);
curwin->w_set_curswant = true;
} else {
vim_beep(BO_CRSR);
@@ -4120,7 +4138,7 @@ static void ins_s_right(void)
if (!end_change) {
AppendCharToRedobuff(K_S_RIGHT);
}
- (void)fwd_word(1, false, 0);
+ fwd_word(1, false, 0);
curwin->w_set_curswant = true;
} else {
vim_beep(BO_CRSR);
@@ -4233,7 +4251,7 @@ static bool ins_tab(void)
return false;
}
- int ind = inindent(0);
+ bool ind = inindent(0);
if (ind) {
can_cindent = false;
}
@@ -4344,14 +4362,16 @@ static bool ins_tab(void)
getvcol(curwin, cursor, &want_vcol, NULL, NULL);
char *tab = "\t";
- chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, 0, vcol, tab, tab);
+ int32_t tab_v = (uint8_t)(*tab);
+
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, curwin, 0, tab);
// Use as many TABs as possible. Beware of 'breakindent', 'showbreak'
// and 'linebreak' adding extra virtual columns.
while (ascii_iswhite(*ptr)) {
- int i = lbr_chartabsize(&cts);
- if (cts.cts_vcol + i > want_vcol) {
+ int i = win_charsize(cstype, vcol, tab, tab_v, &csarg).width;
+ if (vcol + i > want_vcol) {
break;
}
if (*ptr != TAB) {
@@ -4366,23 +4386,18 @@ static bool ins_tab(void)
}
fpos.col++;
ptr++;
- cts.cts_vcol += i;
+ vcol += i;
}
- vcol = cts.cts_vcol;
- clear_chartabsize_arg(&cts);
if (change_col >= 0) {
int repl_off = 0;
// Skip over the spaces we need.
- init_chartabsize_arg(&cts, curwin, 0, vcol, ptr, ptr);
- while (cts.cts_vcol < want_vcol && *cts.cts_ptr == ' ') {
- cts.cts_vcol += lbr_chartabsize(&cts);
- cts.cts_ptr++;
+ cstype = init_charsize_arg(&csarg, curwin, 0, ptr);
+ while (vcol < want_vcol && *ptr == ' ') {
+ vcol += win_charsize(cstype, vcol, ptr, (uint8_t)(' '), &csarg).width;
+ ptr++;
repl_off++;
}
- ptr = cts.cts_ptr;
- vcol = cts.cts_vcol;
- clear_chartabsize_arg(&cts);
if (vcol > want_vcol) {
// Must have a char with 'showbreak' just before it.
@@ -4553,8 +4568,6 @@ static int ins_digraph(void)
// Returns the char to be inserted, or NUL if none found.
int ins_copychar(linenr_T lnum)
{
- char *ptr;
-
if (lnum < 1 || lnum > curbuf->b_ml.ml_line_count) {
vim_beep(BO_COPY);
return NUL;
@@ -4562,24 +4575,22 @@ int ins_copychar(linenr_T lnum)
// try to advance to the cursor column
validate_virtcol();
+ int const end_vcol = curwin->w_virtcol;
char *line = ml_get(lnum);
- char *prev_ptr = line;
- chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, lnum, 0, line, line);
- while (cts.cts_vcol < curwin->w_virtcol && *cts.cts_ptr != NUL) {
- prev_ptr = cts.cts_ptr;
- cts.cts_vcol += lbr_chartabsize_adv(&cts);
- }
-
- if (cts.cts_vcol > curwin->w_virtcol) {
- ptr = prev_ptr;
- } else {
- ptr = cts.cts_ptr;
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, curwin, lnum, line);
+ StrCharInfo ci = utf_ptr2StrCharInfo(line);
+ int vcol = 0;
+ while (vcol < end_vcol && *ci.ptr != NUL) {
+ vcol += win_charsize(cstype, vcol, ci.ptr, ci.chr.value, &csarg).width;
+ if (vcol > end_vcol) {
+ break;
+ }
+ ci = utfc_next(ci);
}
- clear_chartabsize_arg(&cts);
- int c = utf_ptr2char(ptr);
+ int c = ci.chr.value < 0 ? (uint8_t)(*ci.ptr) : ci.chr.value;
if (c == NUL) {
vim_beep(BO_COPY);
}
@@ -4656,7 +4667,7 @@ static void ins_try_si(int c)
if (State & VREPLACE_FLAG) {
change_indent(INDENT_SET, i, false, NUL, true);
} else {
- (void)set_indent(i, SIN_CHANGED);
+ set_indent(i, SIN_CHANGED);
}
} else if (curwin->w_cursor.col > 0) {
// when inserting '{' after "O" reduce indent, but not
@@ -4688,7 +4699,7 @@ static void ins_try_si(int c)
if (curwin->w_cursor.col > 0 && can_si && c == '#' && inindent(0)) {
// remember current indent for next line
old_indent = get_indent();
- (void)set_indent(0, SIN_CHANGED);
+ set_indent(0, SIN_CHANGED);
}
// Adjust ai_col, the char at this position can be deleted.
@@ -4722,6 +4733,10 @@ static char *do_insert_char_pre(int c)
char buf[MB_MAXBYTES + 1];
const int save_State = State;
+ if (c == Ctrl_RSB) {
+ return NULL;
+ }
+
// Return quickly when there is nothing to do.
if (!has_event(EVENT_INSERTCHARPRE)) {
return NULL;
diff --git a/src/nvim/edit.h b/src/nvim/edit.h
index 434b653f7b..2f15e737be 100644
--- a/src/nvim/edit.h
+++ b/src/nvim/edit.h
@@ -1,8 +1,8 @@
#pragma once
#include "nvim/autocmd_defs.h" // IWYU pragma: keep
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
/// Values for in_cinkeys()
enum {
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index f4479d06a6..3d224bfa0f 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -7,13 +7,14 @@
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
-#include <sys/types.h>
+#include <uv.h>
#include "auto/config.h"
#include "nvim/api/private/converter.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
+#include "nvim/autocmd.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/channel.h"
@@ -29,29 +30,31 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/userfunc.h"
#include "nvim/eval/vars.h"
+#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
+#include "nvim/event/time.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
-#include "nvim/ex_session.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid_defs.h"
#include "nvim/hashtab.h"
#include "nvim/highlight_group.h"
#include "nvim/insexpand.h"
#include "nvim/keycodes.h"
-#include "nvim/lib/queue.h"
+#include "nvim/lib/queue_defs.h"
#include "nvim/lua/executor.h"
#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/map_defs.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
@@ -64,8 +67,10 @@
#include "nvim/optionstr.h"
#include "nvim/os/fileio.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/lang.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/shell.h"
#include "nvim/os/stdpaths_defs.h"
#include "nvim/path.h"
@@ -73,13 +78,16 @@
#include "nvim/profile.h"
#include "nvim/quickfix.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/ui_compositor.h"
+#include "nvim/ui_defs.h"
#include "nvim/usercmd.h"
#include "nvim/version.h"
#include "nvim/vim_defs.h"
@@ -89,8 +97,6 @@
#define DICT_MAXNEST 100 // maximum nesting of lists and dicts
-#define MAX_CALLBACK_DEPTH 20
-
static const char *e_missbrac = N_("E111: Missing ']'");
static const char *e_list_end = N_("E697: Missing end of List ']': %s");
static const char e_cannot_slice_dictionary[]
@@ -188,6 +194,7 @@ static struct vimvar {
VV(VV_VERSION, "version", VAR_NUMBER, VV_COMPAT + VV_RO),
VV(VV_LNUM, "lnum", VAR_NUMBER, VV_RO_SBX),
VV(VV_TERMRESPONSE, "termresponse", VAR_STRING, VV_RO),
+ VV(VV_TERMREQUEST, "termrequest", VAR_STRING, VV_RO),
VV(VV_FNAME, "fname", VAR_STRING, VV_RO),
VV(VV_LANG, "lang", VAR_STRING, VV_RO),
VV(VV_LC_TIME, "lc_time", VAR_STRING, VV_RO),
@@ -301,11 +308,12 @@ static partial_T *vvlua_partial;
/// v: hashtab
#define vimvarht vimvardict.dv_hashtab
-/// Enum used by filter(), map() and mapnew()
+/// Enum used by filter(), map(), mapnew() and foreach()
typedef enum {
FILTERMAP_FILTER,
FILTERMAP_MAP,
FILTERMAP_MAPNEW,
+ FILTERMAP_FOREACH,
} filtermap_T;
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -500,6 +508,10 @@ static void evalvars_clear(void)
p->vv_list = NULL;
}
}
+
+ partial_unref(vvlua_partial);
+ vimvars[VV_LUA].vv_partial = vvlua_partial = NULL;
+
hash_clear(&vimvarht);
hash_init(&vimvarht); // garbage_collect() will access it
hash_clear(&compat_hashtab);
@@ -528,7 +540,7 @@ void eval_clear(void)
free_autoload_scriptnames();
// unreferenced lists and dicts
- (void)garbage_collect(false);
+ garbage_collect(false);
// functions not garbage collected
free_all_functions();
@@ -559,7 +571,7 @@ static char *redir_varname = NULL;
/// @param append append to an existing variable
///
/// @return OK if successfully completed the setup. FAIL otherwise.
-int var_redir_start(char *name, int append)
+int var_redir_start(char *name, bool append)
{
// Catch a bad name early.
if (!eval_isnamec1(*name)) {
@@ -677,7 +689,7 @@ int eval_charconvert(const char *const enc_from, const char *const enc_to,
set_vim_var_string(VV_CC_TO, enc_to, -1);
set_vim_var_string(VV_FNAME_IN, fname_from, -1);
set_vim_var_string(VV_FNAME_OUT, fname_to, -1);
- sctx_T *ctx = get_option_sctx("charconvert");
+ sctx_T *ctx = get_option_sctx(kOptCharconvert);
if (ctx != NULL) {
current_sctx = *ctx;
}
@@ -706,7 +718,7 @@ void eval_diff(const char *const origfile, const char *const newfile, const char
set_vim_var_string(VV_FNAME_NEW, newfile, -1);
set_vim_var_string(VV_FNAME_OUT, outfile, -1);
- sctx_T *ctx = get_option_sctx("diffexpr");
+ sctx_T *ctx = get_option_sctx(kOptDiffexpr);
if (ctx != NULL) {
current_sctx = *ctx;
}
@@ -728,7 +740,7 @@ void eval_patch(const char *const origfile, const char *const difffile, const ch
set_vim_var_string(VV_FNAME_DIFF, difffile, -1);
set_vim_var_string(VV_FNAME_OUT, outfile, -1);
- sctx_T *ctx = get_option_sctx("patchexpr");
+ sctx_T *ctx = get_option_sctx(kOptPatchexpr);
if (ctx != NULL) {
current_sctx = *ctx;
}
@@ -746,11 +758,14 @@ void eval_patch(const char *const origfile, const char *const difffile, const ch
void fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, bool skip)
{
*evalarg = (evalarg_T){ .eval_flags = skip ? 0 : EVAL_EVALUATE };
- if (eap != NULL) {
- if (getline_equal(eap->getline, eap->cookie, getsourceline)) {
- evalarg->eval_getline = eap->getline;
- evalarg->eval_cookie = eap->cookie;
- }
+
+ if (eap == NULL) {
+ return;
+ }
+
+ if (getline_equal(eap->getline, eap->cookie, getsourceline)) {
+ evalarg->eval_getline = eap->getline;
+ evalarg->eval_cookie = eap->cookie;
}
}
@@ -760,7 +775,7 @@ void fill_evalarg_from_eap(evalarg_T *evalarg, exarg_T *eap, bool skip)
/// @param skip only parse, don't execute
///
/// @return true or false.
-int eval_to_bool(char *arg, bool *error, exarg_T *eap, int skip)
+bool eval_to_bool(char *arg, bool *error, exarg_T *eap, bool skip)
{
typval_T tv;
bool retval = false;
@@ -1084,17 +1099,19 @@ bool is_compatht(const hashtab_T *ht)
}
/// Prepare v: variable "idx" to be used.
-/// Save the current typeval in "save_tv".
+/// Save the current typeval in "save_tv" and clear it.
/// When not used yet add the variable to the v: hashtable.
void prepare_vimvar(int idx, typval_T *save_tv)
{
*save_tv = vimvars[idx].vv_tv;
+ vimvars[idx].vv_str = NULL; // don't free it now
if (vimvars[idx].vv_type == VAR_UNKNOWN) {
hash_add(&vimvarht, vimvars[idx].vv_di.di_key);
}
}
/// Restore v: variable "idx" to typeval "save_tv".
+/// Note that the v: variable must have been cleared already.
/// When no longer defined, remove the variable from the v: hashtable.
void restore_vimvar(int idx, typval_T *save_tv)
{
@@ -1130,7 +1147,7 @@ list_T *eval_spell_expr(char *badword, char *expr)
if (p_verbose == 0) {
emsg_off++;
}
- sctx_T *ctx = get_option_sctx("spellsuggest");
+ sctx_T *ctx = get_option_sctx(kOptSpellsuggest);
if (ctx != NULL) {
current_sctx = *ctx;
}
@@ -1274,7 +1291,7 @@ void *call_func_retlist(const char *func, int argc, typval_T *argv)
int eval_foldexpr(win_T *wp, int *cp)
{
const sctx_T saved_sctx = current_sctx;
- const bool use_sandbox = was_set_insecurely(wp, "foldexpr", OPT_LOCAL);
+ const bool use_sandbox = was_set_insecurely(wp, kOptFoldexpr, OPT_LOCAL);
char *arg = wp->w_p_fde;
current_sctx = wp->w_p_script_ctx[WV_FDE].script_ctx;
@@ -1322,7 +1339,7 @@ int eval_foldexpr(win_T *wp, int *cp)
/// Evaluate 'foldtext', returning an Array or a String (NULL_STRING on failure).
Object eval_foldtext(win_T *wp)
{
- const bool use_sandbox = was_set_insecurely(wp, "foldtext", OPT_LOCAL);
+ const bool use_sandbox = was_set_insecurely(wp, kOptFoldtext, OPT_LOCAL);
char *arg = wp->w_p_fdt;
funccal_entry_T funccal_entry;
@@ -1338,7 +1355,7 @@ Object eval_foldtext(win_T *wp)
retval = STRING_OBJ(NULL_STRING);
} else {
if (tv.v_type == VAR_LIST) {
- retval = vim_to_object(&tv);
+ retval = vim_to_object(&tv, NULL, false);
} else {
retval = STRING_OBJ(cstr_to_string(tv_get_string(&tv)));
}
@@ -1725,7 +1742,7 @@ void clear_lval(lval_T *lp)
/// @param endp points to just after the parsed name.
/// @param op NULL, "+" for "+=", "-" for "-=", "*" for "*=", "/" for "/=",
/// "%" for "%=", "." for ".=" or "=" for "=".
-void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool is_const,
+void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, bool copy, const bool is_const,
const char *op)
{
int cc;
@@ -1794,8 +1811,8 @@ void set_var_lval(lval_T *lp, char *endp, typval_T *rettv, int copy, const bool
return;
}
- (void)tv_list_assign_range(lp->ll_list, rettv->vval.v_list,
- lp->ll_n1, lp->ll_n2, lp->ll_empty2, op, lp->ll_name);
+ tv_list_assign_range(lp->ll_list, rettv->vval.v_list,
+ lp->ll_n1, lp->ll_n2, lp->ll_empty2, op, lp->ll_name);
} else {
typval_T oldtv = TV_INITIAL_VALUE;
dict_T *dict = lp->ll_dict;
@@ -2312,20 +2329,22 @@ static int eval_func(char **const arg, evalarg_T *const evalarg, char *const nam
/// After using "evalarg" filled from "eap": free the memory.
void clear_evalarg(evalarg_T *evalarg, exarg_T *eap)
{
- if (evalarg != NULL) {
- if (evalarg->eval_tofree != NULL) {
- if (eap != NULL) {
- // We may need to keep the original command line, e.g. for
- // ":let" it has the variable names. But we may also need the
- // new one, "nextcmd" points into it. Keep both.
- xfree(eap->cmdline_tofree);
- eap->cmdline_tofree = *eap->cmdlinep;
- *eap->cmdlinep = evalarg->eval_tofree;
- } else {
- xfree(evalarg->eval_tofree);
- }
- evalarg->eval_tofree = NULL;
+ if (evalarg == NULL) {
+ return;
+ }
+
+ if (evalarg->eval_tofree != NULL) {
+ if (eap != NULL) {
+ // We may need to keep the original command line, e.g. for
+ // ":let" it has the variable names. But we may also need the
+ // new one, "nextcmd" points into it. Keep both.
+ xfree(eap->cmdline_tofree);
+ eap->cmdline_tofree = *eap->cmdlinep;
+ *eap->cmdlinep = evalarg->eval_tofree;
+ } else {
+ xfree(evalarg->eval_tofree);
}
+ evalarg->eval_tofree = NULL;
}
}
@@ -2858,7 +2877,8 @@ static int eval5(char **arg, typval_T *rettv, evalarg_T *const evalarg)
} else {
bool error = false;
varnumber_T n1, n2;
- float_T f1 = 0, f2 = 0;
+ float_T f1 = 0;
+ float_T f2 = 0;
if (rettv->v_type == VAR_FLOAT) {
f1 = rettv->vval.v_float;
@@ -2949,7 +2969,8 @@ static int eval6(char **arg, typval_T *rettv, evalarg_T *const evalarg, bool wan
}
varnumber_T n1, n2;
- float_T f1 = 0, f2 = 0;
+ float_T f1 = 0;
+ float_T f2 = 0;
bool error = false;
const bool evaluate = evalarg == NULL ? 0 : (evalarg->eval_flags & EVAL_EVALUATE);
if (evaluate) {
@@ -3217,6 +3238,13 @@ static int eval7(char **arg, typval_T *rettv, evalarg_T *const evalarg, bool wan
} else {
// skip the name
check_vars(s, (size_t)len);
+ // If evaluate is false rettv->v_type was not set, but it's needed
+ // in handle_subscript() to parse v:lua, so set it here.
+ if (rettv->v_type == VAR_UNKNOWN && !evaluate && strnequal(s, "v:lua.", 6)) {
+ rettv->v_type = VAR_PARTIAL;
+ rettv->vval.v_partial = vvlua_partial;
+ rettv->vval.v_partial->pt_refcount++;
+ }
ret = OK;
}
}
@@ -3421,7 +3449,7 @@ static int eval_method(char **const arg, typval_T *const rettv, evalarg_T *const
int len;
char *name = *arg;
char *lua_funcname = NULL;
- if (strncmp(name, "v:lua.", 6) == 0) {
+ if (strnequal(name, "v:lua.", 6)) {
lua_funcname = name + 6;
*arg = (char *)skip_luafunc_name(lua_funcname);
*arg = skipwhite(*arg); // to detect trailing whitespace later
@@ -3610,12 +3638,14 @@ static int check_can_index(typval_T *rettv, bool evaluate, bool verbose)
/// slice() function
void f_slice(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- if (check_can_index(argvars, true, false) == OK) {
- tv_copy(argvars, rettv);
- eval_index_inner(rettv, true, argvars + 1,
- argvars[2].v_type == VAR_UNKNOWN ? NULL : argvars + 2,
- true, NULL, 0, false);
+ if (check_can_index(argvars, true, false) != OK) {
+ return;
}
+
+ tv_copy(argvars, rettv);
+ eval_index_inner(rettv, true, argvars + 1,
+ argvars[2].v_type == VAR_UNKNOWN ? NULL : argvars + 2,
+ true, NULL, 0, false);
}
/// Apply index or range to "rettv".
@@ -3731,7 +3761,11 @@ static int eval_index_inner(typval_T *rettv, bool is_range, typval_T *var1, typv
dictitem_T *const item = tv_dict_find(rettv->vval.v_dict, key, keylen);
if (item == NULL && verbose) {
- semsg(_(e_dictkey), key);
+ if (keylen > 0) {
+ semsg(_(e_dictkey_len), keylen, key);
+ } else {
+ semsg(_(e_dictkey), key);
+ }
}
if (item == NULL || tv_is_luafunc(&item->di_tv)) {
return FAIL;
@@ -3759,10 +3793,12 @@ int eval_option(const char **const arg, typval_T *const rettv, const bool evalua
FUNC_ATTR_NONNULL_ARG(1)
{
const bool working = (**arg == '+'); // has("+option")
+ OptIndex opt_idx;
int scope;
// Isolate the option name and find its value.
- char *option_end = (char *)find_option_end(arg, &scope);
+ char *const option_end = (char *)find_option_var_end(arg, &opt_idx, &scope);
+
if (option_end == NULL) {
if (rettv != NULL) {
semsg(_("E112: Option name missing: %s"), *arg);
@@ -3775,38 +3811,26 @@ int eval_option(const char **const arg, typval_T *const rettv, const bool evalua
return OK;
}
- int ret = OK;
- bool hidden;
char c = *option_end;
*option_end = NUL;
- OptVal value = get_option_value(*arg, NULL, scope, &hidden);
- if (rettv != NULL) {
- switch (value.type) {
- case kOptValTypeNil:
+ int ret = OK;
+ bool is_tty_opt = is_tty_option(*arg);
+
+ if (opt_idx == kOptInvalid && !is_tty_opt) {
+ // Only give error if result is going to be used.
+ if (rettv != NULL) {
semsg(_("E113: Unknown option: %s"), *arg);
- ret = FAIL;
- break;
- case kOptValTypeBoolean:
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = value.data.boolean;
- break;
- case kOptValTypeNumber:
- rettv->v_type = VAR_NUMBER;
- rettv->vval.v_number = value.data.number;
- break;
- case kOptValTypeString:
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = value.data.string.data;
- break;
}
- } else {
- // Value isn't being used, free it.
- optval_free(value);
- if (value.type == kOptValTypeNil || (working && hidden)) {
- ret = FAIL;
- }
+ ret = FAIL;
+ } else if (rettv != NULL) {
+ OptVal value = is_tty_opt ? get_tty_option(*arg) : get_option_value(opt_idx, scope);
+ assert(value.type != kOptValTypeNil);
+
+ *rettv = optval_as_tv(value, true);
+ } else if (working && !is_tty_opt && is_option_hidden(opt_idx)) {
+ ret = FAIL;
}
*option_end = c; // put back for error messages
@@ -4238,7 +4262,11 @@ static void partial_free(partial_T *pt)
/// becomes zero.
void partial_unref(partial_T *pt)
{
- if (pt != NULL && --pt->pt_refcount <= 0) {
+ if (pt == NULL) {
+ return;
+ }
+
+ if (--pt->pt_refcount <= 0) {
partial_free(pt);
}
}
@@ -4548,7 +4576,7 @@ bool garbage_collect(bool testing)
// history items (ShaDa additional elements)
if (p_hi) {
- for (HistoryType i = 0; i < HIST_COUNT; i++) {
+ for (int i = 0; i < HIST_COUNT; i++) {
const void *iter = NULL;
do {
histentry_T hist;
@@ -4707,7 +4735,7 @@ bool set_ref_in_ht(hashtab_T *ht, int copyID, list_stack_T **list_stack)
/// @param ht_stack Used to add hashtabs to be marked. Can be NULL.
///
/// @returns true if setting references failed somehow.
-bool set_ref_in_list(list_T *l, int copyID, ht_stack_T **ht_stack)
+bool set_ref_in_list_items(list_T *l, int copyID, ht_stack_T **ht_stack)
FUNC_ATTR_WARN_UNUSED_RESULT
{
bool abort = false;
@@ -4784,7 +4812,7 @@ bool set_ref_in_item(typval_T *tv, int copyID, ht_stack_T **ht_stack, list_stack
// Didn't see this list yet.
ll->lv_copyID = copyID;
if (list_stack == NULL) {
- abort = set_ref_in_list(ll, copyID, ht_stack);
+ abort = set_ref_in_list_items(ll, copyID, ht_stack);
} else {
list_stack_T *const newitem = xmalloc(sizeof(list_stack_T));
newitem->list = ll;
@@ -5026,7 +5054,7 @@ size_t string2float(const char *const text, float_T *const ret_value)
return 3;
}
if (STRNICMP(text, "-inf", 3) == 0) {
- *ret_value = (float_T) - INFINITY;
+ *ret_value = (float_T)(-INFINITY);
return 4;
}
if (STRNICMP(text, "nan", 3) == 0) {
@@ -5089,7 +5117,8 @@ void assert_error(garray_T *gap)
tv_list_append_string(vimvars[VV_ERRORS].vv_list, gap->ga_data, (ptrdiff_t)gap->ga_len);
}
-/// Implementation of map() and filter() for a Dict.
+/// Implementation of map(), filter(), foreach() for a Dict. Apply "expr" to
+/// every item in Dict "d" and return the result in "rettv".
static void filter_map_dict(dict_T *d, filtermap_T filtermap, const char *func_name,
const char *arg_errmsg, typval_T *expr, typval_T *rettv)
{
@@ -5157,7 +5186,7 @@ static void filter_map_dict(dict_T *d, filtermap_T filtermap, const char *func_n
d->dv_lock = prev_lock;
}
-/// Implementation of map() and filter() for a Blob.
+/// Implementation of map(), filter(), foreach() for a Blob.
static void filter_map_blob(blob_T *blob_arg, filtermap_T filtermap, typval_T *expr,
const char *arg_errmsg, typval_T *rettv)
{
@@ -5200,20 +5229,22 @@ static void filter_map_blob(blob_T *blob_arg, filtermap_T filtermap, typval_T *e
|| did_emsg) {
break;
}
- if (newtv.v_type != VAR_NUMBER && newtv.v_type != VAR_BOOL) {
- tv_clear(&newtv);
- emsg(_(e_invalblob));
- break;
- }
- if (filtermap != FILTERMAP_FILTER) {
- if (newtv.vval.v_number != val) {
- tv_blob_set(b_ret, i, (uint8_t)newtv.vval.v_number);
+ if (filtermap != FILTERMAP_FOREACH) {
+ if (newtv.v_type != VAR_NUMBER && newtv.v_type != VAR_BOOL) {
+ tv_clear(&newtv);
+ emsg(_(e_invalblob));
+ break;
+ }
+ if (filtermap != FILTERMAP_FILTER) {
+ if (newtv.vval.v_number != val) {
+ tv_blob_set(b_ret, i, (uint8_t)newtv.vval.v_number);
+ }
+ } else if (rem) {
+ char *const p = (char *)blob_arg->bv_ga.ga_data;
+ memmove(p + i, p + i + 1, (size_t)(b->bv_ga.ga_len - i - 1));
+ b->bv_ga.ga_len--;
+ i--;
}
- } else if (rem) {
- char *const p = (char *)blob_arg->bv_ga.ga_data;
- memmove(p + i, p + i + 1, (size_t)(b->bv_ga.ga_len - i - 1));
- b->bv_ga.ga_len--;
- i--;
}
idx++;
}
@@ -5221,7 +5252,7 @@ static void filter_map_blob(blob_T *blob_arg, filtermap_T filtermap, typval_T *e
b->bv_lock = prev_lock;
}
-/// Implementation of map() and filter() for a String.
+/// Implementation of map(), filter(), foreach() for a String.
static void filter_map_string(const char *str, filtermap_T filtermap, typval_T *expr,
typval_T *rettv)
{
@@ -5250,7 +5281,8 @@ static void filter_map_string(const char *str, filtermap_T filtermap, typval_T *
tv_clear(&newtv);
tv_clear(&tv);
break;
- } else if (filtermap != FILTERMAP_FILTER) {
+ }
+ if (filtermap == FILTERMAP_MAP || filtermap == FILTERMAP_MAPNEW) {
if (newtv.v_type != VAR_STRING) {
tv_clear(&newtv);
tv_clear(&tv);
@@ -5259,7 +5291,7 @@ static void filter_map_string(const char *str, filtermap_T filtermap, typval_T *
} else {
ga_concat(&ga, newtv.vval.v_string);
}
- } else if (!rem) {
+ } else if (filtermap == FILTERMAP_FOREACH || !rem) {
ga_concat(&ga, tv.vval.v_string);
}
@@ -5272,7 +5304,8 @@ static void filter_map_string(const char *str, filtermap_T filtermap, typval_T *
rettv->vval.v_string = ga.ga_data;
}
-/// Implementation of map() and filter() for a List.
+/// Implementation of map(), filter(), foreach() for a List. Apply "expr" to
+/// every item in List "l" and return the result in "rettv".
static void filter_map_list(list_T *l, filtermap_T filtermap, const char *func_name,
const char *arg_errmsg, typval_T *expr, typval_T *rettv)
{
@@ -5336,21 +5369,25 @@ static void filter_map_list(list_T *l, filtermap_T filtermap, const char *func_n
tv_list_set_lock(l, prev_lock);
}
-/// Implementation of map() and filter().
+/// Implementation of map(), filter() and foreach().
static void filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap)
{
const char *const func_name = (filtermap == FILTERMAP_MAP
? "map()"
: (filtermap == FILTERMAP_MAPNEW
? "mapnew()"
- : "filter()"));
+ : (filtermap == FILTERMAP_FILTER
+ ? "filter()"
+ : "foreach()")));
const char *const arg_errmsg = (filtermap == FILTERMAP_MAP
? N_("map() argument")
: (filtermap == FILTERMAP_MAPNEW
? N_("mapnew() argument")
- : N_("filter() argument")));
+ : (filtermap == FILTERMAP_FILTER
+ ? N_("filter() argument")
+ : N_("foreach() argument"))));
- // map() and filter() return the first argument, also on failure.
+ // map(), filter(), foreach() return the first argument, also on failure.
if (filtermap != FILTERMAP_MAPNEW && argvars[0].v_type != VAR_STRING) {
tv_copy(&argvars[0], rettv);
}
@@ -5367,38 +5404,40 @@ static void filter_map(typval_T *argvars, typval_T *rettv, filtermap_T filtermap
// On type errors, the preceding call has already displayed an error
// message. Avoid a misleading error message for an empty string that
// was not passed as argument.
- if (expr->v_type != VAR_UNKNOWN) {
- typval_T save_val;
- prepare_vimvar(VV_VAL, &save_val);
-
- // We reset "did_emsg" to be able to detect whether an error
- // occurred during evaluation of the expression.
- int save_did_emsg = did_emsg;
- did_emsg = false;
-
- typval_T save_key;
- prepare_vimvar(VV_KEY, &save_key);
- if (argvars[0].v_type == VAR_DICT) {
- filter_map_dict(argvars[0].vval.v_dict, filtermap, func_name,
- arg_errmsg, expr, rettv);
- } else if (argvars[0].v_type == VAR_BLOB) {
- filter_map_blob(argvars[0].vval.v_blob, filtermap, expr, arg_errmsg, rettv);
- } else if (argvars[0].v_type == VAR_STRING) {
- filter_map_string(tv_get_string(&argvars[0]), filtermap, expr, rettv);
- } else {
- assert(argvars[0].v_type == VAR_LIST);
- filter_map_list(argvars[0].vval.v_list, filtermap, func_name,
- arg_errmsg, expr, rettv);
- }
+ if (expr->v_type == VAR_UNKNOWN) {
+ return;
+ }
+
+ typval_T save_val;
+ prepare_vimvar(VV_VAL, &save_val);
- restore_vimvar(VV_KEY, &save_key);
- restore_vimvar(VV_VAL, &save_val);
+ // We reset "did_emsg" to be able to detect whether an error
+ // occurred during evaluation of the expression.
+ int save_did_emsg = did_emsg;
+ did_emsg = false;
- did_emsg |= save_did_emsg;
+ typval_T save_key;
+ prepare_vimvar(VV_KEY, &save_key);
+ if (argvars[0].v_type == VAR_DICT) {
+ filter_map_dict(argvars[0].vval.v_dict, filtermap, func_name,
+ arg_errmsg, expr, rettv);
+ } else if (argvars[0].v_type == VAR_BLOB) {
+ filter_map_blob(argvars[0].vval.v_blob, filtermap, expr, arg_errmsg, rettv);
+ } else if (argvars[0].v_type == VAR_STRING) {
+ filter_map_string(tv_get_string(&argvars[0]), filtermap, expr, rettv);
+ } else {
+ assert(argvars[0].v_type == VAR_LIST);
+ filter_map_list(argvars[0].vval.v_list, filtermap, func_name,
+ arg_errmsg, expr, rettv);
}
+
+ restore_vimvar(VV_KEY, &save_key);
+ restore_vimvar(VV_VAL, &save_val);
+
+ did_emsg |= save_did_emsg;
}
-/// Handle one item for map() and filter().
+/// Handle one item for map(), filter(), foreach().
/// Sets v:val to "tv". Caller must set v:key.
///
/// @param tv original value
@@ -5413,6 +5452,17 @@ static int filter_map_one(typval_T *tv, typval_T *expr, const filtermap_T filter
int retval = FAIL;
tv_copy(tv, &vimvars[VV_VAL].vv_tv);
+
+ newtv->v_type = VAR_UNKNOWN;
+ if (filtermap == FILTERMAP_FOREACH && expr->v_type == VAR_STRING) {
+ // foreach() is not limited to an expression
+ do_cmdline_cmd(expr->vval.v_string);
+ if (!did_emsg) {
+ retval = OK;
+ }
+ goto theend;
+ }
+
argv[0] = vimvars[VV_KEY].vv_tv;
argv[1] = vimvars[VV_VAL].vv_tv;
if (eval_expr_typval(expr, false, argv, 2, newtv) == FAIL) {
@@ -5429,6 +5479,8 @@ static int filter_map_one(typval_T *tv, typval_T *expr, const filtermap_T filter
if (error) {
goto theend;
}
+ } else if (filtermap == FILTERMAP_FOREACH) {
+ tv_clear(newtv);
}
retval = OK;
theend:
@@ -5454,6 +5506,12 @@ void f_mapnew(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
filter_map(argvars, rettv, FILTERMAP_MAPNEW);
}
+/// "foreach()" function
+void f_foreach(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ filter_map(argvars, rettv, FILTERMAP_FOREACH);
+}
+
/// "function()" function
/// "funcref()" function
void common_function(typval_T *argvars, typval_T *rettv, bool is_funcref)
@@ -6061,7 +6119,7 @@ bool callback_call(Callback *const callback, const int argcount_in, typval_T *co
typval_T *const rettv)
FUNC_ATTR_NONNULL_ALL
{
- if (callback_depth > MAX_CALLBACK_DEPTH) {
+ if (callback_depth > p_mfd) {
emsg(_(e_command_too_recursive));
return false;
}
@@ -6092,8 +6150,8 @@ bool callback_call(Callback *const callback, const int argcount_in, typval_T *co
break;
case kCallbackLua:
- rv = nlua_call_ref(callback->data.luaref, NULL, args, false, NULL);
- return (rv.type == kObjectTypeBoolean && rv.data.boolean == true);
+ rv = nlua_call_ref(callback->data.luaref, NULL, args, kRetNilBool, NULL, NULL);
+ return LUARET_TRUTHY(rv);
case kCallbackNone:
return false;
@@ -7563,6 +7621,10 @@ int handle_subscript(const char **const arg, typval_T *rettv, evalarg_T *const e
const char *lua_funcname = NULL;
if (tv_is_luafunc(rettv)) {
+ if (!evaluate) {
+ tv_clear(rettv);
+ }
+
if (**arg != '.') {
tv_clear(rettv);
ret = FAIL;
@@ -8135,13 +8197,14 @@ void ex_execute(exarg_T *eap)
eap->nextcmd = check_nextcmd(arg);
}
-/// Skip over the name of an option: "&option", "&g:option" or "&l:option".
+/// Skip over the name of an option variable: "&option", "&g:option" or "&l:option".
///
-/// @param arg points to the "&" or '+' when called, to "option" when returning.
+/// @param[in,out] arg Points to the "&" or '+' when called, to "option" when returning.
+/// @param[out] opt_idxp Set to option index in options[] table.
+/// @param[out] scope Set to option scope.
///
-/// @return NULL when no option name found. Otherwise pointer to the char
-/// after the option name.
-const char *find_option_end(const char **const arg, int *const scope)
+/// @return NULL when no option name found. Otherwise pointer to the char after the option name.
+const char *find_option_var_end(const char **const arg, OptIndex *const opt_idxp, int *const scope)
{
const char *p = *arg;
@@ -8156,22 +8219,12 @@ const char *find_option_end(const char **const arg, int *const scope)
*scope = 0;
}
- if (!ASCII_ISALPHA(*p)) {
- return NULL;
- }
- *arg = p;
-
- if (p[0] == 't' && p[1] == '_' && p[2] != NUL && p[3] != NUL) {
- p += 4; // t_xx/termcap option
- } else {
- while (ASCII_ISALPHA(*p)) {
- p++;
- }
- }
- return p;
+ const char *end = find_option_end(p, opt_idxp);
+ *arg = end == NULL ? *arg : p;
+ return end;
}
-static var_flavour_T var_flavour(char *varname)
+var_flavour_T var_flavour(char *varname)
FUNC_ATTR_PURE
{
char *p = varname;
@@ -8187,48 +8240,6 @@ static var_flavour_T var_flavour(char *varname)
return VAR_FLAVOUR_DEFAULT;
}
-/// Iterate over global variables
-///
-/// @warning No modifications to global variable dictionary must be performed
-/// while iteration is in progress.
-///
-/// @param[in] iter Iterator. Pass NULL to start iteration.
-/// @param[out] name Variable name.
-/// @param[out] rettv Variable value.
-///
-/// @return Pointer that needs to be passed to next `var_shada_iter` invocation
-/// or NULL to indicate that iteration is over.
-const void *var_shada_iter(const void *const iter, const char **const name, typval_T *rettv,
- var_flavour_T flavour)
- FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2, 3)
-{
- const hashitem_T *hi;
- const hashitem_T *hifirst = globvarht.ht_array;
- const size_t hinum = (size_t)globvarht.ht_mask + 1;
- *name = NULL;
- if (iter == NULL) {
- hi = globvarht.ht_array;
- while ((size_t)(hi - hifirst) < hinum
- && (HASHITEM_EMPTY(hi)
- || !(var_flavour(hi->hi_key) & flavour))) {
- hi++;
- }
- if ((size_t)(hi - hifirst) == hinum) {
- return NULL;
- }
- } else {
- hi = (const hashitem_T *)iter;
- }
- *name = TV_DICT_HI2DI(hi)->di_key;
- tv_copy(&TV_DICT_HI2DI(hi)->di_tv, rettv);
- while ((size_t)(++hi - hifirst) < hinum) {
- if (!HASHITEM_EMPTY(hi) && (var_flavour(hi->hi_key) & flavour)) {
- return hi;
- }
- }
- return NULL;
-}
-
void var_set_global(const char *const name, typval_T vartv)
{
funccal_entry_T funccall_entry;
@@ -8238,50 +8249,6 @@ void var_set_global(const char *const name, typval_T vartv)
restore_funccal();
}
-int store_session_globals(FILE *fd)
-{
- TV_DICT_ITER(&globvardict, this_var, {
- if ((this_var->di_tv.v_type == VAR_NUMBER
- || this_var->di_tv.v_type == VAR_STRING)
- && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) {
- // Escape special characters with a backslash. Turn a LF and
- // CR into \n and \r.
- char *const p = vim_strsave_escaped(tv_get_string(&this_var->di_tv), "\\\"\n\r");
- for (char *t = p; *t != NUL; t++) {
- if (*t == '\n') {
- *t = 'n';
- } else if (*t == '\r') {
- *t = 'r';
- }
- }
- if ((fprintf(fd, "let %s = %c%s%c",
- this_var->di_key,
- ((this_var->di_tv.v_type == VAR_STRING) ? '"' : ' '),
- p,
- ((this_var->di_tv.v_type == VAR_STRING) ? '"' : ' ')) < 0)
- || put_eol(fd) == FAIL) {
- xfree(p);
- return FAIL;
- }
- xfree(p);
- } else if (this_var->di_tv.v_type == VAR_FLOAT
- && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) {
- float_T f = this_var->di_tv.vval.v_float;
- int sign = ' ';
-
- if (f < 0) {
- f = -f;
- sign = '-';
- }
- if ((fprintf(fd, "let %s = %c%f", this_var->di_key, sign, f) < 0)
- || put_eol(fd) == FAIL) {
- return FAIL;
- }
- }
- });
- return OK;
-}
-
/// Display script name where an item was last set.
/// Should only be invoked when 'verbose' is non-zero.
void last_set_msg(sctx_T script_ctx)
@@ -8298,21 +8265,24 @@ void last_set_msg(sctx_T script_ctx)
/// Should only be invoked when 'verbose' is non-zero.
void option_last_set_msg(LastSet last_set)
{
- if (last_set.script_ctx.sc_sid != 0) {
- bool should_free;
- char *p = get_scriptname(last_set, &should_free);
- verbose_enter();
- msg_puts(_("\n\tLast set from "));
- msg_puts(p);
- if (last_set.script_ctx.sc_lnum > 0) {
- msg_puts(_(line_msg));
- msg_outnum(last_set.script_ctx.sc_lnum);
- }
- if (should_free) {
- xfree(p);
- }
- verbose_leave();
+ if (last_set.script_ctx.sc_sid == 0) {
+ return;
+ }
+
+ bool should_free;
+ char *p = get_scriptname(last_set, &should_free);
+
+ verbose_enter();
+ msg_puts(_("\n\tLast set from "));
+ msg_puts(p);
+ if (last_set.script_ctx.sc_lnum > 0) {
+ msg_puts(_(line_msg));
+ msg_outnum(last_set.script_ctx.sc_lnum);
+ }
+ if (should_free) {
+ xfree(p);
}
+ verbose_leave();
}
// reset v:option_new, v:option_old, v:option_oldlocal, v:option_oldglobal,
@@ -8683,9 +8653,9 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char
int i = (int)(regmatch.startp[0] - tail);
memmove((char *)ga.ga_data + ga.ga_len, tail, (size_t)i);
// add the substituted text
- (void)vim_regsub(&regmatch, sub, expr,
- (char *)ga.ga_data + ga.ga_len + i, sublen,
- REGSUB_COPY | REGSUB_MAGIC);
+ vim_regsub(&regmatch, sub, expr,
+ (char *)ga.ga_data + ga.ga_len + i, sublen,
+ REGSUB_COPY | REGSUB_MAGIC);
ga.ga_len += i + sublen - 1;
tail = regmatch.endp[0];
if (*tail == NUL) {
@@ -8712,7 +8682,7 @@ char *do_string_sub(char *str, char *pat, char *sub, typval_T *expr, const char
// If it's still empty it was changed and restored, need to restore in
// the complicated way.
if (*p_cpo == NUL) {
- set_option_value_give_err("cpo", CSTR_AS_OPTVAL(save_cpo), 0);
+ set_option_value_give_err(kOptCpoptions, CSTR_AS_OPTVAL(save_cpo), 0);
}
free_string_option(save_cpo);
}
@@ -8825,7 +8795,7 @@ typval_T eval_call_provider(char *provider, char *method, list_T *arguments, boo
funcexe.fe_firstline = curwin->w_cursor.lnum;
funcexe.fe_lastline = curwin->w_cursor.lnum;
funcexe.fe_evaluate = true;
- (void)call_func(func, name_len, &rettv, 2, argvars, &funcexe);
+ call_func(func, name_len, &rettv, 2, argvars, &funcexe);
tv_list_unref(arguments);
// Restore caller scope information
@@ -8908,32 +8878,6 @@ void eval_fmt_source_name_line(char *buf, size_t bufsize)
}
}
-/// ":checkhealth [plugins]"
-void ex_checkhealth(exarg_T *eap)
-{
- Error err = ERROR_INIT;
- MAXSIZE_TEMP_ARRAY(args, 1);
- ADD_C(args, CSTR_AS_OBJ(eap->arg));
- NLUA_EXEC_STATIC("return vim.health._check(...)", args, &err);
- if (!ERROR_SET(&err)) {
- return;
- }
-
- const char *vimruntime_env = os_getenv("VIMRUNTIME");
- if (vimruntime_env == NULL) {
- emsg(_("E5009: $VIMRUNTIME is empty or unset"));
- } else {
- bool rtp_ok = NULL != strstr(p_rtp, vimruntime_env);
- if (rtp_ok) {
- semsg(_("E5009: Invalid $VIMRUNTIME: %s"), vimruntime_env);
- } else {
- emsg(_("E5009: Invalid 'runtimepath'"));
- }
- }
- semsg_multiline(err.msg);
- api_clear_error(&err);
-}
-
void invoke_prompt_callback(void)
{
typval_T rettv;
diff --git a/src/nvim/eval.h b/src/nvim/eval.h
index 1fc2891917..d83af70ef7 100644
--- a/src/nvim/eval.h
+++ b/src/nvim/eval.h
@@ -4,17 +4,22 @@
#include <stddef.h>
#include <stdint.h>
-#include "nvim/buffer_defs.h"
-#include "nvim/channel.h"
-#include "nvim/cmdexpand_defs.h"
+#include "nvim/channel_defs.h" // IWYU pragma: keep
+#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h"
-#include "nvim/event/time.h"
-#include "nvim/ex_cmds_defs.h"
-#include "nvim/globals.h"
+#include "nvim/eval_defs.h" // IWYU pragma: keep
+#include "nvim/event/defs.h"
+#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
+#include "nvim/grid_defs.h" // IWYU pragma: keep
#include "nvim/hashtab_defs.h"
#include "nvim/macros_defs.h"
-#include "nvim/os/fileio.h"
-#include "nvim/os/stdpaths_defs.h"
+#include "nvim/mbyte_defs.h" // IWYU pragma: keep
+#include "nvim/msgpack_rpc/channel_defs.h" // IWYU pragma: keep
+#include "nvim/option_defs.h" // IWYU pragma: keep
+#include "nvim/os/fileio_defs.h" // IWYU pragma: keep
+#include "nvim/os/stdpaths_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
+#include "nvim/vim_defs.h" // IWYU pragma: keep
#define COPYID_INC 2
#define COPYID_MASK (~0x1)
@@ -44,7 +49,7 @@
// "exp_name" NULL or non-NULL, to be freed later.
// "tv" points to the Dictionary typval_T
// "newkey" is the key for the new item.
-typedef struct lval_S {
+typedef struct {
const char *ll_name; ///< Start of variable name (can be NULL).
size_t ll_name_len; ///< Length of the .ll_name.
char *ll_exp_name; ///< NULL or expanded name in allocated memory.
@@ -81,6 +86,7 @@ typedef enum {
VV_THIS_SESSION,
VV_VERSION,
VV_LNUM,
+ VV_TERMREQUEST,
VV_TERMRESPONSE,
VV_FNAME,
VV_LANG,
@@ -173,24 +179,8 @@ typedef enum {
VV_VIRTNUM,
} VimVarIndex;
-/// All recognized msgpack types
-typedef enum {
- kMPNil,
- kMPBoolean,
- kMPInteger,
- kMPFloat,
- kMPString,
- kMPBinary,
- kMPArray,
- kMPMap,
- kMPExt,
-} MessagePackType;
-#define LAST_MSGPACK_TYPE kMPExt
-
/// Array mapping values from MessagePackType to corresponding list pointers
-extern const list_T *eval_msgpack_type_lists[LAST_MSGPACK_TYPE + 1];
-
-#undef LAST_MSGPACK_TYPE
+extern const list_T *eval_msgpack_type_lists[NUM_MSGPACK_TYPES];
// Struct passed to get_v_event() and restore_v_event().
typedef struct {
@@ -254,32 +244,17 @@ typedef enum {
kDictListItems, ///< List dictionary contents: [keys, values].
} DictListType;
-typedef int (*ex_unletlock_callback)(lval_T *, char *, exarg_T *, int);
-
// Used for checking if local variables or arguments used in a lambda.
extern bool *eval_lavars_used;
-/// Struct passed through eval() functions.
-/// See EVALARG_EVALUATE for a fixed value with eval_flags set to EVAL_EVALUATE.
-typedef struct {
- int eval_flags; ///< EVAL_ flag values below
-
- /// copied from exarg_T when "getline" is "getsourceline". Can be NULL.
- LineGetter eval_getline;
- void *eval_cookie; ///< argument for eval_getline()
-
- /// pointer to the last line obtained with getsourceline()
- char *eval_tofree;
-} evalarg_T;
+// Character used as separated in autoload function/variable names.
+#define AUTOLOAD_CHAR '#'
/// Flag for expression evaluation.
enum {
EVAL_EVALUATE = 1, ///< when missing don't actually evaluate
};
-// Character used as separated in autoload function/variable names.
-#define AUTOLOAD_CHAR '#'
-
/// Passed to an eval() function to enable evaluation.
EXTERN evalarg_T EVALARG_EVALUATE INIT( = { EVAL_EVALUATE, NULL, NULL, NULL });
diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua
index 55f4721c3a..b7120d5dd5 100644
--- a/src/nvim/eval.lua
+++ b/src/nvim/eval.lua
@@ -17,7 +17,7 @@
--- @field deprecated? true
--- @field returns? string|false
--- @field returns_desc? string
---- @field signature string
+--- @field signature? string
--- @field desc? string
--- @field params {[1]:string, [2]:string, [3]:string}[]
--- @field lua? false Do not render type information
@@ -809,7 +809,7 @@ M.funcs = {
<
]=],
name = 'bufname',
- params = { { 'buf', 'any' } },
+ params = { { 'buf', 'integer|string' } },
returns = 'string',
signature = 'bufname([{buf}])',
},
@@ -832,7 +832,7 @@ M.funcs = {
]=],
name = 'bufnr',
- params = { { 'buf', 'any' }, { 'create', 'any' } },
+ params = { { 'buf', 'integer|string' }, { 'create', 'any' } },
returns = 'integer',
signature = 'bufnr([{buf} [, {create}]])',
},
@@ -1373,6 +1373,8 @@ M.funcs = {
no item is selected when using the <Up> or
<Down> keys)
inserted Inserted string. [NOT IMPLEMENTED YET]
+ preview_winid Info floating preview window id.
+ preview_bufnr Info floating preview buffer id.
*complete_info_mode*
mode values are:
@@ -2114,7 +2116,7 @@ M.funcs = {
name = 'execute',
params = {
{ 'command', 'string|string[]' },
- { 'silent', "''|'silent'|'silent!'" }
+ { 'silent', "''|'silent'|'silent!'" },
},
returns = 'string',
signature = 'execute({command} [, {silent}])',
@@ -2200,6 +2202,7 @@ M.funcs = {
echo exists("*strftime")
echo exists("*s:MyFunc")
echo exists("*MyFunc")
+ echo exists("*v:lua.Func")
echo exists("bufcount")
echo exists(":Make")
echo exists("#CursorHold")
@@ -2346,9 +2349,20 @@ M.funcs = {
]=],
name = 'expand',
- params = { { 'string', 'string' }, { 'nosuf', 'boolean' }, { 'list', 'any' } },
- returns = 'string|string[]',
+ params = { { 'string', 'string' }, { 'nosuf', 'boolean' }, { 'list', 'nil|false' } },
signature = 'expand({string} [, {nosuf} [, {list}]])',
+ returns = 'string',
+ },
+ expand__1 = {
+ args = { 3 },
+ base = 1,
+ name = 'expand',
+ params = {
+ { 'string', 'string' },
+ { 'nosuf', 'boolean' },
+ { 'list', 'true|number|string|table' },
+ },
+ returns = 'string|string[]',
},
expandcmd = {
args = { 1, 2 },
@@ -2910,10 +2924,51 @@ M.funcs = {
returns = 'string',
signature = 'foldtextresult({lnum})',
},
+ foreach = {
+ args = 2,
+ base = 1,
+ desc = [=[
+ {expr1} must be a |List|, |String|, |Blob| or |Dictionary|.
+ For each item in {expr1} execute {expr2}. {expr1} is not
+ modified; its values may be, as with |:lockvar| 1. |E741|
+ See |map()| and |filter()| to modify {expr1}.
+
+ {expr2} must be a |string| or |Funcref|.
+
+ If {expr2} is a |string|, inside {expr2} |v:val| has the value
+ of the current item. For a |Dictionary| |v:key| has the key
+ of the current item and for a |List| |v:key| has the index of
+ the current item. For a |Blob| |v:key| has the index of the
+ current byte. For a |String| |v:key| has the index of the
+ current character.
+ Examples: >vim
+ call foreach(mylist, 'let used[v:val] = v:true')
+ <This records the items that are in the {expr1} list.
+
+ Note that {expr2} is the result of expression and is then used
+ as a command. Often it is good to use a |literal-string| to
+ avoid having to double backslashes.
+
+ If {expr2} is a |Funcref| it must take two arguments:
+ 1. the key or the index of the current item.
+ 2. the value of the current item.
+ With a lambda you don't get an error if it only accepts one
+ argument.
+ If the function returns a value, it is ignored.
+
+ Returns {expr1} in all cases.
+ When an error is encountered while executing {expr2} no
+ further items in {expr1} are processed.
+ When {expr2} is a Funcref errors inside a function are ignored,
+ unless it was defined with the "abort" flag.
+ ]=],
+ name = 'foreach',
+ params = { { 'expr1', 'any' }, { 'expr2', 'any' } },
+ signature = 'foreach({expr1}, {expr2})',
+ },
foreground = {
args = 0,
params = {},
- signature = '',
lua = false,
},
fullcommand = {
@@ -3164,6 +3219,8 @@ M.funcs = {
bufnr Buffer number.
changed TRUE if the buffer is modified.
changedtick Number of changes made to the buffer.
+ command TRUE if the buffer belongs to the
+ command-line window |cmdwin|.
hidden TRUE if the buffer is hidden.
lastused Timestamp in seconds, like
|localtime()|, when the buffer was
@@ -3406,7 +3463,7 @@ M.funcs = {
32 mouse double click
64 mouse triple click
96 mouse quadruple click (== 32 + 64)
- 128 command (Macintosh only)
+ 128 command (Mac) or super
Only the modifiers that have not been included in the
character itself are obtained. Thus Shift-a results in "A"
without a modifier. Returns 0 if no modifiers are used.
@@ -3607,6 +3664,7 @@ M.funcs = {
help help subjects
highlight highlight groups
history |:history| suboptions
+ keymap keyboard mappings
locale locale names (as output of locale -a)
mapclear buffer argument
mapping mapping name
@@ -3915,9 +3973,16 @@ M.funcs = {
|getbufoneline()|
]=],
name = 'getline',
- params = { { 'lnum', 'integer' }, { 'end', 'any' } },
- returns = 'string|string[]',
+ params = { { 'lnum', 'integer|string' }, { 'end', 'nil|false' } },
signature = 'getline({lnum} [, {end}])',
+ returns = 'string',
+ },
+ getline__1 = {
+ args = { 2 },
+ base = 1,
+ name = 'getline',
+ params = { { 'lnum', 'integer' }, { 'end', 'true|number|string|table' } },
+ returns = 'string|string[]',
},
getloclist = {
args = { 1, 2 },
@@ -4246,9 +4311,16 @@ M.funcs = {
]=],
name = 'getreg',
- params = { { 'regname', 'string' }, { 'list', 'any' } },
- returns = 'string|string[]',
+ params = { { 'regname', 'string' }, { 'list', 'nil|false' } },
signature = 'getreg([{regname} [, 1 [, {list}]]])',
+ returns = 'string',
+ },
+ getreg__1 = {
+ args = { 3 },
+ base = 1,
+ name = 'getreg',
+ params = { { 'regname', 'string' }, { 'list', 'true|number|string|table' } },
+ returns = 'string|string[]',
},
getreginfo = {
args = { 0, 1 },
@@ -4283,6 +4355,65 @@ M.funcs = {
returns = 'table',
signature = 'getreginfo([{regname}])',
},
+ getregion = {
+ args = { 2, 3 },
+ base = 1,
+ desc = [=[
+ Returns the list of strings from {pos1} to {pos2} from a
+ buffer.
+
+ {pos1} and {pos2} must both be |List|s with four numbers.
+ See |getpos()| for the format of the list. It's possible
+ to specify positions from a different buffer, but please
+ note the limitations at |getregion-notes|.
+
+ The optional argument {opts} is a Dict and supports the
+ following items:
+
+ type Specify the region's selection type
+ (default: "v"):
+ "v" for |charwise| mode
+ "V" for |linewise| mode
+ "<CTRL-V>" for |blockwise-visual| mode
+
+ exclusive If |TRUE|, use exclusive selection
+ for the end position
+ (default: follow 'selection')
+
+ You can get the last selection type by |visualmode()|.
+ If Visual mode is active, use |mode()| to get the Visual mode
+ (e.g., in a |:vmap|).
+ This function is useful to get text starting and ending in
+ different columns, such as a |charwise-visual| selection.
+
+ *getregion-notes*
+ Note that:
+ - Order of {pos1} and {pos2} doesn't matter, it will always
+ return content from the upper left position to the lower
+ right position.
+ - If 'virtualedit' is enabled and the region is past the end
+ of the lines, resulting lines are padded with spaces.
+ - If the region is blockwise and it starts or ends in the
+ middle of a multi-cell character, it is not included but
+ its selected part is substituted with spaces.
+ - If {pos1} and {pos2} are not in the same buffer, an empty
+ list is returned.
+ - {pos1} and {pos2} must belong to a |bufloaded()| buffer.
+ - It is evaluated in current window context, which makes a
+ difference if the buffer is displayed in a window with
+ different 'virtualedit' or 'list' values.
+
+ Examples: >
+ :xnoremap <CR>
+ \ <Cmd>echom getregion(
+ \ getpos('v'), getpos('.'), #{ type: mode() })<CR>
+ <
+ ]=],
+ name = 'getregion',
+ params = { { 'pos1', 'table' }, { 'pos2', 'table' }, { 'opts', 'table' } },
+ returns = 'string[]',
+ signature = 'getregion({pos1}, {pos2} [, {opts}])',
+ },
getregtype = {
args = { 0, 1 },
base = 1,
@@ -4519,7 +4650,7 @@ M.funcs = {
name = 'getwininfo',
params = { { 'winid', 'integer' } },
signature = 'getwininfo([{winid}])',
- returns = 'vim.fn.getwininfo.ret.item[]'
+ returns = 'vim.fn.getwininfo.ret.item[]',
},
getwinpos = {
args = { 0, 1 },
@@ -5095,7 +5226,7 @@ M.funcs = {
]=],
name = 'indent',
- params = { { 'lnum', 'integer' } },
+ params = { { 'lnum', 'integer|string' } },
returns = 'integer',
signature = 'indent({lnum})',
},
@@ -5735,8 +5866,7 @@ M.funcs = {
Vim value. In the following cases it will output
|msgpack-special-dict|:
1. Dictionary contains duplicate key.
- 2. Dictionary contains empty key.
- 3. String contains NUL byte. Two special dictionaries: for
+ 2. String contains NUL byte. Two special dictionaries: for
dictionary and for string will be emitted in case string
with NUL byte was a dictionary key.
@@ -6216,10 +6346,22 @@ M.funcs = {
{ 'name', 'string' },
{ 'mode', 'string' },
{ 'abbr', 'boolean' },
- { 'dict', 'boolean' },
+ { 'dict', 'false' },
},
- returns = 'string|table<string,any>',
signature = 'maparg({name} [, {mode} [, {abbr} [, {dict}]]])',
+ returns = 'string',
+ },
+ maparg__1 = {
+ args = { 4 },
+ base = 1,
+ name = 'maparg',
+ params = {
+ { 'name', 'string' },
+ { 'mode', 'string' },
+ { 'abbr', 'boolean' },
+ { 'dict', 'true' },
+ },
+ returns = 'string|table<string,any>',
},
mapcheck = {
args = { 1, 3 },
@@ -6297,7 +6439,7 @@ M.funcs = {
]],
name = 'maplist',
params = {},
- signature = 'maplist([{abbr}])'
+ signature = 'maplist([{abbr}])',
},
mapnew = {
args = 2,
@@ -6315,6 +6457,13 @@ M.funcs = {
mapset = {
args = { 1, 3 },
base = 1,
+ name = 'mapset',
+ params = { { 'mode', 'string' }, { 'abbr', 'any' }, { 'dict', 'any' } },
+ signature = 'mapset({mode}, {abbr}, {dict})',
+ },
+ mapset__1 = {
+ args = { 1, 3 },
+ base = 1,
desc = [=[
Restore a mapping from a dictionary, possibly returned by
|maparg()| or |maplist()|. A buffer mapping, when dict.buffer
@@ -6352,8 +6501,8 @@ M.funcs = {
endfor
]=],
name = 'mapset',
- params = { { 'mode', 'string' }, { 'abbr', 'any' }, { 'dict', 'any' } },
- signature = 'mapset({mode}, {abbr}, {dict})',
+ params = { { 'dict', 'any' } },
+ signature = 'mapset({dict})',
},
match = {
args = { 2, 4 },
@@ -6411,6 +6560,7 @@ M.funcs = {
Note that when {count} is added the way {start} works changes,
see above.
+ *match-pattern*
See |pattern| for the patterns that are accepted.
The 'ignorecase' option is used to set the ignore-caseness of
the pattern. 'smartcase' is NOT used. The matching is always
@@ -6569,6 +6719,63 @@ M.funcs = {
params = { { 'nr', 'integer' } },
signature = 'matcharg({nr})',
},
+ matchbufline = {
+ args = { 4, 5 },
+ base = 1,
+ desc = [=[
+ Returns the |List| of matches in lines from {lnum} to {end} in
+ buffer {buf} where {pat} matches.
+
+ {lnum} and {end} can either be a line number or the string "$"
+ to refer to the last line in {buf}.
+
+ The {dict} argument supports following items:
+ submatches include submatch information (|/\(|)
+
+ For each match, a |Dict| with the following items is returned:
+ byteidx starting byte index of the match
+ lnum line number where there is a match
+ text matched string
+ Note that there can be multiple matches in a single line.
+
+ This function works only for loaded buffers. First call
+ |bufload()| if needed.
+
+ See |match-pattern| for information about the effect of some
+ option settings on the pattern.
+
+ When {buf} is not a valid buffer, the buffer is not loaded or
+ {lnum} or {end} is not valid then an error is given and an
+ empty |List| is returned.
+
+ Examples: >vim
+ " Assuming line 3 in buffer 5 contains "a"
+ :echo matchbufline(5, '\<\k\+\>', 3, 3)
+ [{'lnum': 3, 'byteidx': 0, 'text': 'a'}]
+ " Assuming line 4 in buffer 10 contains "tik tok"
+ :echo matchbufline(10, '\<\k\+\>', 1, 4)
+ [{'lnum': 4, 'byteidx': 0, 'text': 'tik'}, {'lnum': 4, 'byteidx': 4, 'text': 'tok'}]
+ <
+ If {submatch} is present and is v:true, then submatches like
+ "\1", "\2", etc. are also returned. Example: >vim
+ " Assuming line 2 in buffer 2 contains "acd"
+ :echo matchbufline(2, '\(a\)\?\(b\)\?\(c\)\?\(.*\)', 2, 2
+ \ {'submatches': v:true})
+ [{'lnum': 2, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
+ <The "submatches" List always contains 9 items. If a submatch
+ is not found, then an empty string is returned for that
+ submatch.
+ ]=],
+ name = 'matchbufline',
+ params = {
+ { 'buf', 'string|integer' },
+ { 'pat', 'string' },
+ { 'lnum', 'string|integer' },
+ { 'end', 'string|integer' },
+ { 'dict', 'table' },
+ },
+ signature = 'matchbufline({buf}, {pat}, {lnum}, {end}, [, {dict}])',
+ },
matchdelete = {
args = { 1, 2 },
base = 1,
@@ -6753,6 +6960,46 @@ M.funcs = {
params = { { 'expr', 'any' }, { 'pat', 'any' }, { 'start', 'any' }, { 'count', 'any' } },
signature = 'matchstr({expr}, {pat} [, {start} [, {count}]])',
},
+ matchstrlist = {
+ args = { 2, 3 },
+ base = 1,
+ desc = [=[
+ Returns the |List| of matches in {list} where {pat} matches.
+ {list} is a |List| of strings. {pat} is matched against each
+ string in {list}.
+
+ The {dict} argument supports following items:
+ submatches include submatch information (|/\(|)
+
+ For each match, a |Dict| with the following items is returned:
+ byteidx starting byte index of the match.
+ idx index in {list} of the match.
+ text matched string
+ submatches a List of submatches. Present only if
+ "submatches" is set to v:true in {dict}.
+
+ See |match-pattern| for information about the effect of some
+ option settings on the pattern.
+
+ Example: >vim
+ :echo matchstrlist(['tik tok'], '\<\k\+\>')
+ [{'idx': 0, 'byteidx': 0, 'text': 'tik'}, {'idx': 0, 'byteidx': 4, 'text': 'tok'}]
+ :echo matchstrlist(['a', 'b'], '\<\k\+\>')
+ [{'idx': 0, 'byteidx': 0, 'text': 'a'}, {'idx': 1, 'byteidx': 0, 'text': 'b'}]
+ <
+ If "submatches" is present and is v:true, then submatches like
+ "\1", "\2", etc. are also returned. Example: >vim
+ :echo matchstrlist(['acd'], '\(a\)\?\(b\)\?\(c\)\?\(.*\)',
+ \ #{submatches: v:true})
+ [{'idx': 0, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}]
+ <The "submatches" List always contains 9 items. If a submatch
+ is not found, then an empty string is returned for that
+ submatch.
+ ]=],
+ name = 'matchstrlist',
+ params = { { 'list', 'string[]' }, { 'pat', 'string' }, { 'dict', 'table' } },
+ signature = 'matchstrlist({list}, {pat} [, {dict}])',
+ },
matchstrpos = {
args = { 2, 4 },
base = 1,
@@ -6790,7 +7037,7 @@ M.funcs = {
it returns the maximum of all values in the Dictionary.
If {expr} is neither a List nor a Dictionary, or one of the
items in {expr} cannot be used as a Number this results in
- an error. An empty |List| or |Dictionary| results in zero.
+ an error. An empty |List| or |Dictionary| results in zero.
]=],
name = 'max',
@@ -7056,7 +7303,7 @@ M.funcs = {
]=],
name = 'mode',
- params = {},
+ params = { { 'expr', 'any' } },
signature = 'mode([expr])',
},
msgpackdump = {
@@ -7155,7 +7402,6 @@ M.funcs = {
are binary strings).
2. String with NUL byte inside.
3. Duplicate key.
- 4. Empty key.
ext |List| with two values: first is a signed integer
representing extension type. Second is
|readfile()|-style list of strings.
@@ -7445,9 +7691,9 @@ M.funcs = {
<This limits the length of the text used from "line" to
"width" bytes.
- If the argument to be formatted is specified using a posional
- argument specifier, and a '*' is used to indicate that a
- number argument is to be used to specify the width or
+ If the argument to be formatted is specified using a
+ positional argument specifier, and a '*' is used to indicate
+ that a number argument is to be used to specify the width or
precision, the argument(s) to be used must also be specified
using a {n$} positional argument specifier. See |printf-$|.
@@ -9524,7 +9770,7 @@ M.funcs = {
]=],
name = 'setreg',
- params = { { 'regname', 'string' }, { 'value', 'any' }, { 'options', 'table' } },
+ params = { { 'regname', 'string' }, { 'value', 'any' }, { 'options', 'string' } },
signature = 'setreg({regname}, {value} [, {options}])',
},
settabvar = {
@@ -9905,7 +10151,7 @@ M.funcs = {
name = 'sign_jump',
params = { { 'id', 'integer' }, { 'group', 'string' }, { 'buf', 'integer|string' } },
signature = 'sign_jump({id}, {group}, {buf})',
- returns = 'integer'
+ returns = 'integer',
},
sign_place = {
args = { 4, 5 },
@@ -9968,7 +10214,7 @@ M.funcs = {
{ 'dict', 'vim.fn.sign_place.dict' },
},
signature = 'sign_place({id}, {group}, {name}, {buf} [, {dict}])',
- returns = 'integer'
+ returns = 'integer',
},
sign_placelist = {
args = 1,
@@ -10035,7 +10281,7 @@ M.funcs = {
name = 'sign_placelist',
params = { { 'list', 'vim.fn.sign_placelist.list.item[]' } },
signature = 'sign_placelist({list})',
- returns = 'integer[]'
+ returns = 'integer[]',
},
sign_undefine = {
args = { 0, 1 },
@@ -10570,7 +10816,7 @@ M.funcs = {
signature = 'stdpath({what})',
},
state = {
- args = {0, 1},
+ args = { 0, 1 },
base = 1,
desc = [=[
Return a string which contains characters indicating the
@@ -11112,9 +11358,16 @@ M.funcs = {
]=],
name = 'submatch',
+ params = { { 'nr', 'integer' }, { 'list', 'nil' } },
+ signature = 'submatch({nr} [, {list}])',
+ returns = 'string',
+ },
+ submatch__1 = {
+ args = { 2 },
+ base = 1,
+ name = 'submatch',
params = { { 'nr', 'integer' }, { 'list', 'integer' } },
returns = 'string|string[]',
- signature = 'submatch({nr} [, {list}])',
},
substitute = {
args = 4,
@@ -11365,7 +11618,7 @@ M.funcs = {
]=],
name = 'synconcealed',
params = { { 'lnum', 'integer' }, { 'col', 'integer' } },
- returns = '{[1]: integer, [2]: string, [3]: integer}[]',
+ returns = '{[1]: integer, [2]: string, [3]: integer}',
signature = 'synconcealed({lnum}, {col})',
},
synstack = {
@@ -11702,7 +11955,6 @@ M.funcs = {
test_write_list_log = {
args = 1,
params = { { 'fname', 'string' } },
- signature = '',
lua = false,
},
timer_info = {
@@ -12698,7 +12950,7 @@ M.funcs = {
name = 'winsaveview',
params = {},
signature = 'winsaveview()',
- returns = 'vim.fn.winsaveview.ret'
+ returns = 'vim.fn.winsaveview.ret',
},
winwidth = {
args = 1,
diff --git a/src/nvim/eval/buffer.c b/src/nvim/eval/buffer.c
index c60a104381..7b8f71ef3f 100644
--- a/src/nvim/eval/buffer.c
+++ b/src/nvim/eval/buffer.c
@@ -5,6 +5,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/change.h"
@@ -14,7 +15,6 @@
#include "nvim/eval/funcs.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/memline.h"
@@ -494,6 +494,7 @@ static dict_T *get_buffer_info(buf_T *buf)
tv_dict_add_nr(dict, S_LEN("changed"), bufIsChanged(buf));
tv_dict_add_nr(dict, S_LEN("changedtick"), buf_get_changedtick(buf));
tv_dict_add_nr(dict, S_LEN("hidden"), buf->b_ml.ml_mfp != NULL && buf->b_nwindows == 0);
+ tv_dict_add_nr(dict, S_LEN("command"), buf == cmdwin_buf);
// Get a reference to buffer variables
tv_dict_add_dict(dict, S_LEN("variables"), buf->b_vars);
@@ -507,7 +508,7 @@ static dict_T *get_buffer_info(buf_T *buf)
}
tv_dict_add_list(dict, S_LEN("windows"), windows);
- if (buf->b_signs) {
+ if (buf_has_signs(buf)) {
// List of signs placed in this buffer
tv_dict_add_list(dict, S_LEN("signs"), get_buffer_signs(buf));
}
@@ -584,7 +585,8 @@ void f_getbufinfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
///
/// @return range (from start to end) of lines in rettv from the specified
/// buffer.
-static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, int retlist, typval_T *rettv)
+static void get_buffer_lines(buf_T *buf, linenr_T start, linenr_T end, bool retlist,
+ typval_T *rettv)
{
rettv->v_type = (retlist ? VAR_LIST : VAR_STRING);
rettv->vval.v_string = NULL;
diff --git a/src/nvim/eval/decode.c b/src/nvim/eval/decode.c
index 03f79fca84..d7df7bb150 100644
--- a/src/nvim/eval/decode.c
+++ b/src/nvim/eval/decode.c
@@ -14,9 +14,9 @@
#include "nvim/eval/encode.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
-#include "nvim/func_attr.h"
+#include "nvim/eval_defs.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
@@ -142,9 +142,7 @@ static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack
ValuesStackItem key = kv_pop(*stack);
if (last_container.special_val == NULL) {
// These cases should have already been handled.
- assert(!(key.is_special_string
- || key.val.vval.v_string == NULL
- || *key.val.vval.v_string == NUL));
+ assert(!(key.is_special_string || key.val.vval.v_string == NULL));
dictitem_T *const obj_di = tv_dict_item_alloc(key.val.vval.v_string);
tv_clear(&key.val);
if (tv_dict_add(last_container.container.vval.v_dict, obj_di)
@@ -171,11 +169,10 @@ static inline int json_decoder_pop(ValuesStackItem obj, ValuesStack *const stack
tv_clear(&obj.val);
return FAIL;
}
- // Handle empty key and key represented as special dictionary
+ // Handle special dictionaries
if (last_container.special_val == NULL
&& (obj.is_special_string
|| obj.val.vval.v_string == NULL
- || *obj.val.vval.v_string == NUL
|| tv_dict_find(last_container.container.vval.v_dict, obj.val.vval.v_string, -1))) {
tv_clear(&obj.val);
@@ -405,13 +402,6 @@ static inline int parse_json_string(const char *const buf, const size_t buf_len,
semsg(_("E474: Expected string end: %.*s"), (int)buf_len, buf);
goto parse_json_string_fail;
}
- if (len == 0) {
- POP(((typval_T) {
- .v_type = VAR_STRING,
- .vval = { .v_string = NULL },
- }), false);
- goto parse_json_string_ret;
- }
char *str = xmalloc(len + 1);
int fst_in_pair = 0;
char *str_end = str;
diff --git a/src/nvim/eval/encode.c b/src/nvim/eval/encode.c
index 8505c30fad..d35ac4eb7b 100644
--- a/src/nvim/eval/encode.c
+++ b/src/nvim/eval/encode.c
@@ -20,7 +20,8 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_encode.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
+#include "nvim/globals.h"
#include "nvim/hashtab.h"
#include "nvim/macros_defs.h"
#include "nvim/math.h"
@@ -1055,3 +1056,17 @@ char *encode_tv2json(typval_T *tv, size_t *len)
#undef TYPVAL_ENCODE_CONV_LIST_BETWEEN_ITEMS
#undef TYPVAL_ENCODE_CONV_RECURSE
#undef TYPVAL_ENCODE_ALLOW_SPECIALS
+
+/// Initialize ListReaderState structure
+ListReaderState encode_init_lrstate(const list_T *const list)
+ FUNC_ATTR_NONNULL_ALL
+{
+ return (ListReaderState) {
+ .list = list,
+ .li = tv_list_first(list),
+ .offset = 0,
+ .li_length = (TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string == NULL
+ ? 0
+ : strlen(TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string)),
+ };
+}
diff --git a/src/nvim/eval/encode.h b/src/nvim/eval/encode.h
index 26a3286f2b..6d1c0b61c5 100644
--- a/src/nvim/eval/encode.h
+++ b/src/nvim/eval/encode.h
@@ -1,12 +1,8 @@
#pragma once
-#include <msgpack.h>
#include <msgpack/pack.h>
-#include <stddef.h>
#include <string.h>
-#include "nvim/eval.h"
-#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/garray_defs.h"
@@ -36,20 +32,6 @@ typedef struct {
size_t li_length; ///< Length of the string inside the read item.
} ListReaderState;
-/// Initialize ListReaderState structure
-static inline ListReaderState encode_init_lrstate(const list_T *const list)
- FUNC_ATTR_NONNULL_ALL
-{
- return (ListReaderState) {
- .list = list,
- .li = tv_list_first(list),
- .offset = 0,
- .li_length = (TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string == NULL
- ? 0
- : strlen(TV_LIST_ITEM_TV(tv_list_first(list))->vval.v_string)),
- };
-}
-
/// Array mapping values from SpecialVarValue enum to names
extern const char *const encode_bool_var_names[];
extern const char *const encode_special_var_names[];
diff --git a/src/nvim/eval/executor.c b/src/nvim/eval/executor.c
index dc23fcdc72..1b8c057d7c 100644
--- a/src/nvim/eval/executor.c
+++ b/src/nvim/eval/executor.c
@@ -5,9 +5,8 @@
#include "nvim/eval/executor.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/message.h"
#include "nvim/strings.h"
@@ -15,7 +14,7 @@
#include "nvim/vim_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "eval/executor.c.generated.h" // IWYU pragma: export
+# include "eval/executor.c.generated.h"
#endif
char *e_list_index_out_of_range_nr
diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c
index 13425b21d1..2f9472f158 100644
--- a/src/nvim/eval/funcs.c
+++ b/src/nvim/eval/funcs.c
@@ -14,7 +14,6 @@
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
-#include <sys/types.h>
#include <time.h>
#include <uv.h>
@@ -27,9 +26,11 @@
#include "nvim/ascii_defs.h"
#include "nvim/assert_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/channel.h"
+#include "nvim/channel_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
#include "nvim/cmdexpand_defs.h"
@@ -48,22 +49,26 @@
#include "nvim/eval/userfunc.h"
#include "nvim/eval/vars.h"
#include "nvim/eval/window.h"
+#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
#include "nvim/event/time.h"
#include "nvim/ex_cmds.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
#include "nvim/file_search.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/getchar_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
@@ -75,24 +80,34 @@
#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/math.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/menu.h"
+#include "nvim/menu_defs.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/msgpack_rpc/server.h"
#include "nvim/normal.h"
+#include "nvim/normal_defs.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/dl.h"
#include "nvim/os/fileio.h"
+#include "nvim/os/fileio_defs.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/pty_process.h"
#include "nvim/os/shell.h"
#include "nvim/os/stdpaths_defs.h"
@@ -103,15 +118,19 @@
#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/search.h"
#include "nvim/sha256.h"
#include "nvim/spell.h"
#include "nvim/spellsuggest.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/version.h"
#include "nvim/vim_defs.h"
@@ -305,7 +324,7 @@ int call_internal_method(const char *const fname, const int argcount, typval_T *
}
/// @return true for a non-zero Number and a non-empty String.
-static int non_zero_arg(typval_T *argvars)
+static bool non_zero_arg(typval_T *argvars)
{
return ((argvars[0].v_type == VAR_NUMBER
&& argvars[0].vval.v_number != 0)
@@ -341,33 +360,28 @@ static void api_wrapper(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
MsgpackRpcRequestHandler handler = *fptr.api_handler;
- Array args = ARRAY_DICT_INIT;
+ MAXSIZE_TEMP_ARRAY(args, MAX_FUNC_ARGS);
+ Arena arena = ARENA_EMPTY;
for (typval_T *tv = argvars; tv->v_type != VAR_UNKNOWN; tv++) {
- ADD(args, vim_to_object(tv));
+ ADD_C(args, vim_to_object(tv, &arena, false));
}
Error err = ERROR_INIT;
- Arena res_arena = ARENA_EMPTY;
- Object result = handler.fn(VIML_INTERNAL_CALL, args, &res_arena, &err);
+ Object result = handler.fn(VIML_INTERNAL_CALL, args, &arena, &err);
if (ERROR_SET(&err)) {
semsg_multiline(e_api_error, err.msg);
goto end;
}
- if (!object_to_vim(result, rettv, &err)) {
- assert(ERROR_SET(&err));
- semsg(_("Error converting the call result: %s"), err.msg);
- }
+ object_to_vim_take_luaref(&result, rettv, true, &err);
end:
- api_free_array(args);
- if (handler.arena_return) {
- arena_mem_free(arena_finish(&res_arena));
- } else {
+ if (handler.ret_alloc) {
api_free_object(result);
}
+ arena_mem_free(arena_finish(&arena));
api_clear_error(&err);
}
@@ -428,8 +442,7 @@ static void f_and(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "api_info()" function
static void f_api_info(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- Dictionary metadata = api_metadata();
- (void)object_to_vim(DICTIONARY_OBJ(metadata), rettv, NULL);
+ object_to_vim(api_metadata(), rettv, NULL);
}
/// "atan2()" function
@@ -1022,10 +1035,11 @@ static void f_ctxget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
- Dictionary ctx_dict = ctx_to_dict(ctx);
+ Arena arena = ARENA_EMPTY;
+ Dictionary ctx_dict = ctx_to_dict(ctx, &arena);
Error err = ERROR_INIT;
- (void)object_to_vim(DICTIONARY_OBJ(ctx_dict), rettv, &err);
- api_free_dictionary(ctx_dict);
+ object_to_vim(DICTIONARY_OBJ(ctx_dict), rettv, &err);
+ arena_mem_free(arena_finish(&arena));
api_clear_error(&err);
}
@@ -1093,7 +1107,8 @@ static void f_ctxset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const int save_did_emsg = did_emsg;
did_emsg = false;
- Dictionary dict = vim_to_object(&argvars[0]).data.dictionary;
+ Arena arena = ARENA_EMPTY;
+ Dictionary dict = vim_to_object(&argvars[0], &arena, true).data.dictionary;
Context tmp = CONTEXT_INIT;
Error err = ERROR_INIT;
ctx_from_dict(dict, &tmp, &err);
@@ -1106,7 +1121,7 @@ static void f_ctxset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
*ctx = tmp;
}
- api_free_dictionary(dict);
+ arena_mem_free(arena_finish(&arena));
api_clear_error(&err);
did_emsg = save_did_emsg;
}
@@ -1675,7 +1690,7 @@ static void f_exepath(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
char *path = NULL;
- (void)os_can_exe(tv_get_string(&argvars[0]), &path, true);
+ os_can_exe(tv_get_string(&argvars[0]), &path, true);
#ifdef BACKSLASH_IN_FILENAME
if (path != NULL) {
@@ -1711,7 +1726,7 @@ static void f_exists(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
n = false; // Trailing garbage.
}
} else if (*p == '*') { // Internal or user defined function.
- n = function_exists(p + 1, false);
+ n = strnequal(p, "*v:lua.", 7) ? nlua_func_exists(p + 7) : function_exists(p + 1, false);
} else if (*p == ':') {
n = cmd_exists(p + 1);
} else if (*p == '#') {
@@ -1922,44 +1937,47 @@ static void extend_list(typval_T *argvars, const char *arg_errmsg, bool is_new,
list_T *l1 = argvars[0].vval.v_list;
list_T *const l2 = argvars[1].vval.v_list;
- if (is_new || !value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) {
- if (is_new) {
- l1 = tv_list_copy(NULL, l1, false, get_copyID());
- if (l1 == NULL) {
- return;
- }
- }
- listitem_T *item;
- if (argvars[2].v_type != VAR_UNKNOWN) {
- int before = (int)tv_get_number_chk(&argvars[2], &error);
- if (error) {
- return; // Type error; errmsg already given.
- }
+ if (!is_new && value_check_lock(tv_list_locked(l1), arg_errmsg, TV_TRANSLATE)) {
+ return;
+ }
- if (before == tv_list_len(l1)) {
- item = NULL;
- } else {
- item = tv_list_find(l1, before);
- if (item == NULL) {
- semsg(_(e_list_index_out_of_range_nr), (int64_t)before);
- return;
- }
- }
- } else {
- item = NULL;
+ if (is_new) {
+ l1 = tv_list_copy(NULL, l1, false, get_copyID());
+ if (l1 == NULL) {
+ return;
}
- tv_list_extend(l1, l2, item);
+ }
- if (is_new) {
- *rettv = (typval_T){
- .v_type = VAR_LIST,
- .v_lock = VAR_UNLOCKED,
- .vval.v_list = l1,
- };
+ listitem_T *item;
+ if (argvars[2].v_type != VAR_UNKNOWN) {
+ int before = (int)tv_get_number_chk(&argvars[2], &error);
+ if (error) {
+ return; // Type error; errmsg already given.
+ }
+
+ if (before == tv_list_len(l1)) {
+ item = NULL;
} else {
- tv_copy(&argvars[0], rettv);
+ item = tv_list_find(l1, before);
+ if (item == NULL) {
+ semsg(_(e_list_index_out_of_range_nr), (int64_t)before);
+ return;
+ }
}
+ } else {
+ item = NULL;
+ }
+ tv_list_extend(l1, l2, item);
+
+ if (is_new) {
+ *rettv = (typval_T){
+ .v_type = VAR_LIST,
+ .v_lock = VAR_UNLOCKED,
+ .vval.v_list = l1,
+ };
+ } else {
+ tv_copy(&argvars[0], rettv);
}
}
@@ -1970,54 +1988,61 @@ static void extend_list(typval_T *argvars, const char *arg_errmsg, bool is_new,
static void extend_dict(typval_T *argvars, const char *arg_errmsg, bool is_new, typval_T *rettv)
{
dict_T *d1 = argvars[0].vval.v_dict;
- dict_T *const d2 = argvars[1].vval.v_dict;
if (d1 == NULL) {
const bool locked = value_check_lock(VAR_FIXED, arg_errmsg, TV_TRANSLATE);
(void)locked;
assert(locked == true);
- } else if (d2 == NULL) {
+ return;
+ }
+ dict_T *const d2 = argvars[1].vval.v_dict;
+ if (d2 == NULL) {
// Do nothing
tv_copy(&argvars[0], rettv);
- } else if (is_new || !value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) {
- if (is_new) {
- d1 = tv_dict_copy(NULL, d1, false, get_copyID());
- if (d1 == NULL) {
- return;
- }
+ return;
+ }
+
+ if (!is_new && value_check_lock(d1->dv_lock, arg_errmsg, TV_TRANSLATE)) {
+ return;
+ }
+
+ if (is_new) {
+ d1 = tv_dict_copy(NULL, d1, false, get_copyID());
+ if (d1 == NULL) {
+ return;
}
+ }
- const char *action = "force";
- // Check the third argument.
- if (argvars[2].v_type != VAR_UNKNOWN) {
- const char *const av[] = { "keep", "force", "error" };
+ const char *action = "force";
+ // Check the third argument.
+ if (argvars[2].v_type != VAR_UNKNOWN) {
+ const char *const av[] = { "keep", "force", "error" };
- action = tv_get_string_chk(&argvars[2]);
- if (action == NULL) {
- return; // Type error; error message already given.
- }
- size_t i;
- for (i = 0; i < ARRAY_SIZE(av); i++) {
- if (strcmp(action, av[i]) == 0) {
- break;
- }
- }
- if (i == 3) {
- semsg(_(e_invarg2), action);
- return;
+ action = tv_get_string_chk(&argvars[2]);
+ if (action == NULL) {
+ return; // Type error; error message already given.
+ }
+ size_t i;
+ for (i = 0; i < ARRAY_SIZE(av); i++) {
+ if (strcmp(action, av[i]) == 0) {
+ break;
}
}
+ if (i == 3) {
+ semsg(_(e_invarg2), action);
+ return;
+ }
+ }
- tv_dict_extend(d1, d2, action);
+ tv_dict_extend(d1, d2, action);
- if (is_new) {
- *rettv = (typval_T){
- .v_type = VAR_DICT,
- .v_lock = VAR_UNLOCKED,
- .vval.v_dict = d1,
- };
- } else {
- tv_copy(&argvars[0], rettv);
- }
+ if (is_new) {
+ *rettv = (typval_T){
+ .v_type = VAR_DICT,
+ .v_lock = VAR_UNLOCKED,
+ .vval.v_dict = d1,
+ };
+ } else {
+ tv_copy(&argvars[0], rettv);
}
}
@@ -2068,8 +2093,8 @@ static void f_feedkeys(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
flags = tv_get_string_buf(&argvars[1], nbuf);
}
- nvim_feedkeys(cstr_as_string((char *)keys),
- cstr_as_string((char *)flags), true);
+ nvim_feedkeys(cstr_as_string(keys),
+ cstr_as_string(flags), true);
}
/// "filereadable()" function
@@ -2175,7 +2200,7 @@ static void f_float2nr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
- if (f <= (float_T) - VARNUMBER_MAX + DBL_EPSILON) {
+ if (f <= (float_T)(-VARNUMBER_MAX) + DBL_EPSILON) {
rettv->vval.v_number = -VARNUMBER_MAX;
} else if (f >= (float_T)VARNUMBER_MAX - DBL_EPSILON) {
rettv->vval.v_number = VARNUMBER_MAX;
@@ -2219,8 +2244,8 @@ static void f_fnamemodify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
len = strlen(fname);
if (*mods != NUL) {
size_t usedlen = 0;
- (void)modify_fname((char *)mods, false, &usedlen,
- (char **)&fname, &fbuf, &len);
+ modify_fname((char *)mods, false, &usedlen,
+ (char **)&fname, &fbuf, &len);
}
}
@@ -2444,7 +2469,7 @@ static void getpos_both(typval_T *argvars, typval_T *rettv, bool getcurpos, bool
: (varnumber_T)0));
tv_list_append_number(l, (fp != NULL) ? (varnumber_T)fp->coladd : (varnumber_T)0);
if (getcurpos) {
- const int save_set_curswant = curwin->w_set_curswant;
+ const bool save_set_curswant = curwin->w_set_curswant;
const colnr_T save_curswant = curwin->w_curswant;
const colnr_T save_virtcol = curwin->w_virtcol;
@@ -2776,6 +2801,167 @@ static void f_getpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
getpos_both(argvars, rettv, false, false);
}
+/// Convert from block_def to string
+static char *block_def2str(struct block_def *bd)
+{
+ size_t size = (size_t)bd->startspaces + (size_t)bd->endspaces + (size_t)bd->textlen;
+ char *ret = xmalloc(size + 1);
+ char *p = ret;
+ memset(p, ' ', (size_t)bd->startspaces);
+ p += bd->startspaces;
+ memmove(p, bd->textstart, (size_t)bd->textlen);
+ p += bd->textlen;
+ memset(p, ' ', (size_t)bd->endspaces);
+ *(p + bd->endspaces) = NUL;
+ return ret;
+}
+
+/// "getregion()" function
+static void f_getregion(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ tv_list_alloc_ret(rettv, kListLenMayKnow);
+
+ if (tv_check_for_list_arg(argvars, 0) == FAIL
+ || tv_check_for_list_arg(argvars, 1) == FAIL
+ || tv_check_for_opt_dict_arg(argvars, 2) == FAIL) {
+ return;
+ }
+
+ int fnum1 = -1;
+ int fnum2 = -1;
+ pos_T p1, p2;
+ if (list2fpos(&argvars[0], &p1, &fnum1, NULL, false) != OK
+ || list2fpos(&argvars[1], &p2, &fnum2, NULL, false) != OK
+ || fnum1 != fnum2) {
+ return;
+ }
+
+ bool is_select_exclusive;
+ char *type;
+ char default_type[] = "v";
+ if (argvars[2].v_type == VAR_DICT) {
+ is_select_exclusive = tv_dict_get_bool(argvars[2].vval.v_dict, "exclusive",
+ *p_sel == 'e');
+ type = tv_dict_get_string(argvars[2].vval.v_dict, "type", false);
+ if (type == NULL) {
+ type = default_type;
+ }
+ } else {
+ is_select_exclusive = *p_sel == 'e';
+ type = default_type;
+ }
+
+ MotionType region_type = kMTUnknown;
+ if (type[0] == 'v' && type[1] == NUL) {
+ region_type = kMTCharWise;
+ } else if (type[0] == 'V' && type[1] == NUL) {
+ region_type = kMTLineWise;
+ } else if (type[0] == Ctrl_V && type[1] == NUL) {
+ region_type = kMTBlockWise;
+ } else {
+ return;
+ }
+
+ buf_T *const save_curbuf = curbuf;
+
+ if (fnum1 != 0) {
+ buf_T *findbuf = buflist_findnr(fnum1);
+ // buffer not loaded
+ if (findbuf == NULL || findbuf->b_ml.ml_mfp == NULL) {
+ return;
+ }
+ curbuf = findbuf;
+ }
+
+ const TriState save_virtual = virtual_op;
+ virtual_op = virtual_active();
+
+ // NOTE: Adjust is needed.
+ p1.col--;
+ p2.col--;
+
+ if (!lt(p1, p2)) {
+ // swap position
+ pos_T p = p1;
+ p1 = p2;
+ p2 = p;
+ }
+
+ oparg_T oa;
+ bool inclusive = true;
+
+ if (region_type == kMTCharWise) {
+ // handle 'selection' == "exclusive"
+ if (is_select_exclusive && !equalpos(p1, p2)) {
+ if (p2.coladd > 0) {
+ p2.coladd--;
+ } else if (p2.col > 0) {
+ p2.col--;
+ mark_mb_adjustpos(curbuf, &p2);
+ } else if (p2.lnum > 1) {
+ p2.lnum--;
+ p2.col = (colnr_T)strlen(ml_get(p2.lnum));
+ if (p2.col > 0) {
+ p2.col--;
+ mark_mb_adjustpos(curbuf, &p2);
+ }
+ }
+ }
+ // if fp2 is on NUL (empty line) inclusive becomes false
+ if (*ml_get_pos(&p2) == NUL && !virtual_op) {
+ inclusive = false;
+ }
+ } else if (region_type == kMTBlockWise) {
+ colnr_T sc1, ec1, sc2, ec2;
+ getvvcol(curwin, &p1, &sc1, NULL, &ec1);
+ getvvcol(curwin, &p2, &sc2, NULL, &ec2);
+ oa.motion_type = kMTBlockWise;
+ oa.inclusive = true;
+ oa.op_type = OP_NOP;
+ oa.start = p1;
+ oa.end = p2;
+ oa.start_vcol = MIN(sc1, sc2);
+ if (is_select_exclusive && ec1 < sc2 && 0 < sc2 && ec2 > ec1) {
+ oa.end_vcol = sc2 - 1;
+ } else {
+ oa.end_vcol = MAX(ec1, ec2);
+ }
+ }
+
+ // Include the trailing byte of a multi-byte char.
+ int l = utfc_ptr2len(ml_get_pos(&p2));
+ if (l > 1) {
+ p2.col += l - 1;
+ }
+
+ for (linenr_T lnum = p1.lnum; lnum <= p2.lnum; lnum++) {
+ char *akt = NULL;
+
+ if (region_type == kMTLineWise) {
+ akt = xstrdup(ml_get(lnum));
+ } else if (region_type == kMTBlockWise) {
+ struct block_def bd;
+ block_prep(&oa, &bd, lnum, false);
+ akt = block_def2str(&bd);
+ } else if (p1.lnum < lnum && lnum < p2.lnum) {
+ akt = xstrdup(ml_get(lnum));
+ } else {
+ struct block_def bd;
+ charwise_block_prep(p1, p2, &bd, lnum, inclusive);
+ akt = block_def2str(&bd);
+ }
+
+ assert(akt != NULL);
+ tv_list_append_allocated_string(rettv->vval.v_list, akt);
+ }
+
+ if (curbuf != save_curbuf) {
+ curbuf = save_curbuf;
+ }
+
+ virtual_op = save_virtual;
+}
+
/// Common between getreg(), getreginfo() and getregtype(): get the register
/// name from the first argument.
/// Returns zero on error.
@@ -3140,7 +3326,6 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
"path_extra",
"persistent_undo",
"profile",
- "pythonx",
"reltime",
"quickfix",
"rightleft",
@@ -3231,6 +3416,8 @@ static void f_has(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
n = syntax_present(curwin);
} else if (STRICMP(name, "clipboard_working") == 0) {
n = eval_has_provider("clipboard");
+ } else if (STRICMP(name, "pythonx") == 0) {
+ n = eval_has_provider("python3");
} else if (STRICMP(name, "wsl") == 0) {
n = has_wsl();
#ifdef UNIX
@@ -3253,13 +3440,11 @@ static bool has_wsl(void)
static TriState has_wsl = kNone;
if (has_wsl == kNone) {
Error err = ERROR_INIT;
- Object o = nlua_exec(STATIC_CSTR_AS_STRING("return vim.uv.os_uname()['release']:lower()"
- ":match('microsoft') and true or false"),
- (Array)ARRAY_DICT_INIT, &err);
+ Object o = NLUA_EXEC_STATIC("return vim.uv.os_uname()['release']:lower()"
+ ":match('microsoft')",
+ (Array)ARRAY_DICT_INIT, kRetNilBool, NULL, &err);
assert(!ERROR_SET(&err));
- assert(o.type == kObjectTypeBoolean);
- has_wsl = o.data.boolean ? kTrue : kFalse;
- api_free_object(o);
+ has_wsl = LUARET_TRUTHY(o) ? kTrue : kFalse;
}
return has_wsl == kTrue;
}
@@ -3639,7 +3824,7 @@ static void f_inputlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
});
// Ask for choice.
- int mouse_used;
+ bool mouse_used;
int selected = prompt_for_number(&mouse_used);
if (mouse_used) {
selected -= lines_left;
@@ -3899,13 +4084,16 @@ static void f_jobresize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = 1;
}
-static const char *ignored_env_vars[] = {
+static const char *pty_ignored_env_vars[] = {
#ifndef MSWIN
"COLUMNS",
"LINES",
"TERMCAP",
"COLORFGBG",
+ "COLORTERM",
#endif
+ "VIM",
+ "VIMRUNTIME",
NULL
};
@@ -3944,9 +4132,9 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en
// child process. We're removing them here so the user can still decide
// they want to explicitly set them.
for (size_t i = 0;
- i < ARRAY_SIZE(ignored_env_vars) && ignored_env_vars[i];
+ i < ARRAY_SIZE(pty_ignored_env_vars) && pty_ignored_env_vars[i];
i++) {
- dictitem_T *dv = tv_dict_find(env, ignored_env_vars[i], -1);
+ dictitem_T *dv = tv_dict_find(env, pty_ignored_env_vars[i], -1);
if (dv) {
tv_dict_item_remove(env, dv);
}
@@ -3954,10 +4142,6 @@ static dict_T *create_environment(const dictitem_T *job_env, const bool clear_en
#ifndef MSWIN
// Set COLORTERM to "truecolor" if termguicolors is set
if (p_tgc) {
- dictitem_T *dv = tv_dict_find(env, S_LEN("COLORTERM"));
- if (dv) {
- tv_dict_item_remove(env, dv);
- }
tv_dict_add_str(env, S_LEN("COLORTERM"), "truecolor");
}
#endif
@@ -4056,8 +4240,8 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
bool clear_env = false;
bool overlapped = false;
ChannelStdinMode stdin_mode = kChannelStdinPipe;
- CallbackReader on_stdout = CALLBACK_READER_INIT,
- on_stderr = CALLBACK_READER_INIT;
+ CallbackReader on_stdout = CALLBACK_READER_INIT;
+ CallbackReader on_stderr = CALLBACK_READER_INIT;
Callback on_exit = CALLBACK_NONE;
char *cwd = NULL;
dictitem_T *job_env = NULL;
@@ -4120,7 +4304,8 @@ static void f_jobstart(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
}
- uint16_t width = 0, height = 0;
+ uint16_t width = 0;
+ uint16_t height = 0;
char *term_name = NULL;
if (pty) {
@@ -4168,7 +4353,7 @@ static void f_jobstop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
const char *error = NULL;
if (data->is_rpc) {
// Ignore return code, but show error later.
- (void)channel_close(data->id, kChannelPartRpc, &error);
+ channel_close(data->id, kChannelPartRpc, &error);
}
process_stop(&data->stream.proc);
rettv->vval.v_number = 1;
@@ -4503,7 +4688,7 @@ static void f_luaeval(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
- nlua_typval_eval(cstr_as_string((char *)str), &argvars[1], rettv);
+ nlua_typval_eval(cstr_as_string(str), &argvars[1], rettv);
}
static void find_some_match(typval_T *const argvars, typval_T *const rettv,
@@ -4714,6 +4899,151 @@ theend:
p_cpo = save_cpo;
}
+/// Return all the matches in string "str" for pattern "rmp".
+/// The matches are returned in the List "mlist".
+/// If "submatches" is true, then submatch information is also returned.
+/// "matchbuf" is true when called for matchbufline().
+static void get_matches_in_str(const char *str, regmatch_T *rmp, list_T *mlist, int idx,
+ bool submatches, bool matchbuf)
+{
+ size_t len = strlen(str);
+ int match = 0;
+ colnr_T startidx = 0;
+
+ while (true) {
+ match = vim_regexec_nl(rmp, str, startidx);
+ if (!match) {
+ break;
+ }
+
+ dict_T *d = tv_dict_alloc();
+ tv_list_append_dict(mlist, d);
+
+ if (matchbuf) {
+ tv_dict_add_nr(d, S_LEN("lnum"), idx);
+ } else {
+ tv_dict_add_nr(d, S_LEN("idx"), idx);
+ }
+
+ tv_dict_add_nr(d, S_LEN("byteidx"),
+ (colnr_T)(rmp->startp[0] - str));
+
+ tv_dict_add_str_len(d, S_LEN("text"), rmp->startp[0],
+ (int)(rmp->endp[0] - rmp->startp[0]));
+
+ if (submatches) {
+ list_T *sml = tv_list_alloc(NSUBEXP - 1);
+
+ tv_dict_add_list(d, S_LEN("submatches"), sml);
+
+ // return a list with the submatches
+ for (int i = 1; i < NSUBEXP; i++) {
+ if (rmp->endp[i] == NULL) {
+ tv_list_append_string(sml, "", 0);
+ } else {
+ tv_list_append_string(sml, rmp->startp[i], rmp->endp[i] - rmp->startp[i]);
+ }
+ }
+ }
+ startidx = (colnr_T)(rmp->endp[0] - str);
+ if (startidx >= (colnr_T)len || str + startidx <= rmp->startp[0]) {
+ break;
+ }
+ }
+}
+
+/// "matchbufline()" function
+static void f_matchbufline(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ rettv->vval.v_number = -1;
+ tv_list_alloc_ret(rettv, kListLenUnknown);
+ list_T *retlist = rettv->vval.v_list;
+
+ if (tv_check_for_buffer_arg(argvars, 0) == FAIL
+ || tv_check_for_string_arg(argvars, 1) == FAIL
+ || tv_check_for_lnum_arg(argvars, 2) == FAIL
+ || tv_check_for_lnum_arg(argvars, 3) == FAIL
+ || tv_check_for_opt_dict_arg(argvars, 4) == FAIL) {
+ return;
+ }
+
+ const int prev_did_emsg = did_emsg;
+ buf_T *buf = tv_get_buf(&argvars[0], false);
+ if (buf == NULL) {
+ if (did_emsg == prev_did_emsg) {
+ semsg(_(e_invalid_buffer_name_str), tv_get_string(&argvars[0]));
+ }
+ return;
+ }
+ if (buf->b_ml.ml_mfp == NULL) {
+ emsg(_(e_buffer_is_not_loaded));
+ return;
+ }
+
+ char patbuf[NUMBUFLEN];
+ const char *pat = tv_get_string_buf(&argvars[1], patbuf);
+
+ const int did_emsg_before = did_emsg;
+ linenr_T slnum = tv_get_lnum_buf(&argvars[2], buf);
+ if (did_emsg > did_emsg_before) {
+ return;
+ }
+ if (slnum < 1) {
+ semsg(_(e_invargval), "lnum");
+ return;
+ }
+
+ linenr_T elnum = tv_get_lnum_buf(&argvars[3], buf);
+ if (did_emsg > did_emsg_before) {
+ return;
+ }
+ if (elnum < 1 || elnum < slnum) {
+ semsg(_(e_invargval), "end_lnum");
+ return;
+ }
+
+ if (elnum > buf->b_ml.ml_line_count) {
+ elnum = buf->b_ml.ml_line_count;
+ }
+
+ bool submatches = false;
+ if (argvars[4].v_type != VAR_UNKNOWN) {
+ dict_T *d = argvars[4].vval.v_dict;
+ if (d != NULL) {
+ dictitem_T *di = tv_dict_find(d, S_LEN("submatches"));
+ if (di != NULL) {
+ if (di->di_tv.v_type != VAR_BOOL) {
+ semsg(_(e_invargval), "submatches");
+ return;
+ }
+ submatches = tv_get_bool(&di->di_tv);
+ }
+ }
+ }
+
+ // Make 'cpoptions' empty, the 'l' flag should not be used here.
+ char *const save_cpo = p_cpo;
+ p_cpo = empty_string_option;
+
+ regmatch_T regmatch;
+ regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
+ if (regmatch.regprog == NULL) {
+ goto theend;
+ }
+ regmatch.rm_ic = p_ic;
+
+ while (slnum <= elnum) {
+ const char *str = ml_get_buf(buf, slnum);
+ get_matches_in_str(str, &regmatch, retlist, slnum, submatches, true);
+ slnum++;
+ }
+
+ vim_regfree(regmatch.regprog);
+
+theend:
+ p_cpo = save_cpo;
+}
+
/// "match()" function
static void f_match(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
@@ -4738,6 +5068,73 @@ static void f_matchstr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
find_some_match(argvars, rettv, kSomeMatchStr);
}
+/// "matchstrlist()" function
+static void f_matchstrlist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
+{
+ rettv->vval.v_number = -1;
+ tv_list_alloc_ret(rettv, kListLenUnknown);
+ list_T *retlist = rettv->vval.v_list;
+
+ if (tv_check_for_list_arg(argvars, 0) == FAIL
+ || tv_check_for_string_arg(argvars, 1) == FAIL
+ || tv_check_for_opt_dict_arg(argvars, 2) == FAIL) {
+ return;
+ }
+
+ list_T *l = NULL;
+ if ((l = argvars[0].vval.v_list) == NULL) {
+ return;
+ }
+
+ char patbuf[NUMBUFLEN];
+ const char *pat = tv_get_string_buf_chk(&argvars[1], patbuf);
+ if (pat == NULL) {
+ return;
+ }
+
+ // Make 'cpoptions' empty, the 'l' flag should not be used here.
+ char *const save_cpo = p_cpo;
+ p_cpo = empty_string_option;
+
+ regmatch_T regmatch;
+ regmatch.regprog = vim_regcomp(pat, RE_MAGIC + RE_STRING);
+ if (regmatch.regprog == NULL) {
+ goto theend;
+ }
+ regmatch.rm_ic = p_ic;
+
+ bool submatches = false;
+ if (argvars[2].v_type != VAR_UNKNOWN) {
+ dict_T *d = argvars[2].vval.v_dict;
+ if (d != NULL) {
+ dictitem_T *di = tv_dict_find(d, S_LEN("submatches"));
+ if (di != NULL) {
+ if (di->di_tv.v_type != VAR_BOOL) {
+ semsg(_(e_invargval), "submatches");
+ goto cleanup;
+ }
+ submatches = tv_get_bool(&di->di_tv);
+ }
+ }
+ }
+
+ int idx = 0;
+ TV_LIST_ITER_CONST(l, li, {
+ const typval_T *const li_tv = TV_LIST_ITEM_TV(li);
+ if (li_tv->v_type == VAR_STRING && li_tv->vval.v_string != NULL) {
+ const char *str = li_tv->vval.v_string;
+ get_matches_in_str(str, &regmatch, retlist, idx, submatches, false);
+ }
+ idx++;
+ });
+
+cleanup:
+ vim_regfree(regmatch.regprog);
+
+theend:
+ p_cpo = save_cpo;
+}
+
/// "matchstrpos()" function
static void f_matchstrpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
@@ -5216,7 +5613,7 @@ static void f_printf(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (!did_emsg) {
char *s = xmalloc((size_t)len + 1);
rettv->vval.v_string = s;
- (void)vim_vsnprintf_typval(s, (size_t)len + 1, fmt, dummy_ap, argvars + 1);
+ vim_vsnprintf_typval(s, (size_t)len + 1, fmt, dummy_ap, argvars + 1);
}
did_emsg |= saved_did_emsg;
}
@@ -5620,6 +6017,12 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl
}
}
+ if (blob) {
+ tv_blob_alloc_ret(rettv);
+ } else {
+ tv_list_alloc_ret(rettv, kListLenUnknown);
+ }
+
// Always open the file in binary mode, library functions have a mind of
// their own about CR-LF conversion.
const char *const fname = tv_get_string(&argvars[0]);
@@ -5634,7 +6037,6 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl
}
if (blob) {
- tv_blob_alloc_ret(rettv);
if (read_blob(fd, rettv, offset, size) == FAIL) {
semsg(_(e_notread), fname);
}
@@ -5642,7 +6044,7 @@ static void read_file_or_blob(typval_T *argvars, typval_T *rettv, bool always_bl
return;
}
- list_T *const l = tv_list_alloc_ret(rettv, kListLenUnknown);
+ list_T *const l = rettv->vval.v_list;
while (maxline < 0 || tv_list_len(l) < maxline) {
int readlen = (int)fread(buf, 1, (size_t)io_size, fd);
@@ -5807,7 +6209,7 @@ static void f_getreginfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (list == NULL) {
return;
}
- (void)tv_dict_add_list(dict, S_LEN("regcontents"), list);
+ tv_dict_add_list(dict, S_LEN("regcontents"), list);
char buf[NUMBUFLEN + 2];
buf[0] = NUL;
@@ -5826,15 +6228,15 @@ static void f_getreginfo(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
case kMTUnknown:
abort();
}
- (void)tv_dict_add_str(dict, S_LEN("regtype"), buf);
+ tv_dict_add_str(dict, S_LEN("regtype"), buf);
buf[0] = (char)get_register_name(get_unname_register());
buf[1] = NUL;
if (regname == '"') {
- (void)tv_dict_add_str(dict, S_LEN("points_to"), buf);
+ tv_dict_add_str(dict, S_LEN("points_to"), buf);
} else {
- (void)tv_dict_add_bool(dict, S_LEN("isunnamed"),
- regname == buf[0] ? kBoolVarTrue : kBoolVarFalse);
+ tv_dict_add_bool(dict, S_LEN("isunnamed"),
+ regname == buf[0] ? kBoolVarTrue : kBoolVarFalse);
}
}
@@ -6648,16 +7050,17 @@ static void f_rpcnotify(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
- Array args = ARRAY_DICT_INIT;
+ MAXSIZE_TEMP_ARRAY(args, MAX_FUNC_ARGS);
+ Arena arena = ARENA_EMPTY;
for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) {
- ADD(args, vim_to_object(tv));
+ ADD_C(args, vim_to_object(tv, &arena, true));
}
bool ok = rpc_send_event((uint64_t)argvars[0].vval.v_number,
tv_get_string(&argvars[1]), args);
- api_free_array(args);
+ arena_mem_free(arena_finish(&arena));
if (!ok) {
semsg(_(e_invarg2), "Channel doesn't exist");
@@ -6687,10 +7090,11 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
- Array args = ARRAY_DICT_INIT;
+ MAXSIZE_TEMP_ARRAY(args, MAX_FUNC_ARGS);
+ Arena arena = ARENA_EMPTY;
for (typval_T *tv = argvars + 2; tv->v_type != VAR_UNKNOWN; tv++) {
- ADD(args, vim_to_object(tv));
+ ADD_C(args, vim_to_object(tv, &arena, true));
}
sctx_T save_current_sctx;
@@ -6726,6 +7130,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
ArenaMem res_mem = NULL;
Object result = rpc_send_call(chan_id, method, args, &res_mem, &err);
+ arena_mem_free(arena_finish(&arena));
if (l_provider_call_nesting) {
current_sctx = save_current_sctx;
@@ -6755,10 +7160,7 @@ static void f_rpcrequest(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
goto end;
}
- if (!object_to_vim(result, rettv, &err)) {
- assert(ERROR_SET(&err));
- semsg(_("Error converting the call result: %s"), err.msg);
- }
+ object_to_vim(result, rettv, &err);
end:
arena_mem_free(res_mem);
@@ -6889,15 +7291,8 @@ static void f_screenchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
ScreenGrid *grid;
screenchar_adjust(&grid, &row, &col);
- int c;
- if (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols) {
- c = -1;
- } else {
- char buf[MAX_SCHAR_SIZE + 1];
- schar_get(buf, grid_getchar(grid, row, col, NULL));
- c = utf_ptr2char(buf);
- }
- rettv->vval.v_number = c;
+ rettv->vval.v_number = (row < 0 || row >= grid->rows || col < 0 || col >= grid->cols)
+ ? -1 : schar_get_first_codepoint(grid_getchar(grid, row, col, NULL));
}
/// "screenchars()" function
@@ -7247,7 +7642,7 @@ int do_searchpair(const char *spat, const char *mpat, const char *epat, int dir,
// If it's still empty it was changed and restored, need to restore in
// the complicated way.
if (*p_cpo == NUL) {
- set_option_value_give_err("cpo", CSTR_AS_OPTVAL(save_cpo), 0);
+ set_option_value_give_err(kOptCpoptions, CSTR_AS_OPTVAL(save_cpo), 0);
}
free_string_option(save_cpo);
}
@@ -8090,7 +8485,7 @@ static void f_str2float(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (*p == '+' || *p == '-') {
p = skipwhite(p + 1);
}
- (void)string2float(p, &rettv->vval.v_float);
+ string2float(p, &rettv->vval.v_float);
if (isneg) {
rettv->vval.v_float *= -1;
}
@@ -8391,7 +8786,6 @@ static void f_synIDtrans(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
int syntax_flags = 0;
- int cchar;
int matchid = 0;
char str[NUMBUFLEN];
@@ -8405,19 +8799,18 @@ static void f_synconcealed(typval_T *argvars, typval_T *rettv, EvalFuncData fptr
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count && col >= 0
&& (size_t)col <= strlen(ml_get(lnum)) && curwin->w_p_cole > 0) {
- (void)syn_get_id(curwin, lnum, col, false, NULL, false);
+ syn_get_id(curwin, lnum, col, false, NULL, false);
syntax_flags = get_syntax_info(&matchid);
// get the conceal character
if ((syntax_flags & HL_CONCEAL) && curwin->w_p_cole < 3) {
- cchar = syn_get_sub_char();
+ schar_T cchar = schar_from_char(syn_get_sub_char());
if (cchar == NUL && curwin->w_p_cole == 1) {
cchar = (curwin->w_p_lcs_chars.conceal == NUL)
- ? ' '
- : curwin->w_p_lcs_chars.conceal;
+ ? schar_from_ascii(' ') : curwin->w_p_lcs_chars.conceal;
}
if (cchar != NUL) {
- utf_char2bytes(cchar, str);
+ schar_get(str, cchar);
}
}
}
@@ -8443,7 +8836,7 @@ static void f_synstack(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
&& col >= 0
&& (size_t)col <= strlen(ml_get(lnum))) {
tv_list_alloc_ret(rettv, kListLenMayKnow);
- (void)syn_get_id(curwin, lnum, col, false, NULL, true);
+ syn_get_id(curwin, lnum, col, false, NULL, true);
int id;
int i = 0;
@@ -8517,8 +8910,8 @@ static void f_taglist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
if (argvars[1].v_type != VAR_UNKNOWN) {
fname = tv_get_string(&argvars[1]);
}
- (void)get_tags(tv_list_alloc_ret(rettv, kListLenUnknown),
- (char *)tag_pattern, (char *)fname);
+ get_tags(tv_list_alloc_ret(rettv, kListLenUnknown),
+ (char *)tag_pattern, (char *)fname);
}
/// "tempname()" function
@@ -8558,8 +8951,8 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
- CallbackReader on_stdout = CALLBACK_READER_INIT,
- on_stderr = CALLBACK_READER_INIT;
+ CallbackReader on_stdout = CALLBACK_READER_INIT;
+ CallbackReader on_stderr = CALLBACK_READER_INIT;
Callback on_exit = CALLBACK_NONE;
dict_T *job_opts = NULL;
const char *cwd = ".";
@@ -8637,17 +9030,17 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
curbuf->b_p_swf = false;
apply_autocmds(EVENT_BUFFILEPRE, NULL, NULL, false, curbuf);
- (void)setfname(curbuf, NameBuff, NULL, true);
+ setfname(curbuf, NameBuff, NULL, true);
apply_autocmds(EVENT_BUFFILEPOST, NULL, NULL, false, curbuf);
// Save the job id and pid in b:terminal_job_{id,pid}
Error err = ERROR_INIT;
// deprecated: use 'channel' buffer option
dict_set_var(curbuf->b_vars, cstr_as_string("terminal_job_id"),
- INTEGER_OBJ((Integer)chan->id), false, false, &err);
+ INTEGER_OBJ((Integer)chan->id), false, false, NULL, &err);
api_clear_error(&err);
dict_set_var(curbuf->b_vars, cstr_as_string("terminal_job_pid"),
- INTEGER_OBJ(pid), false, false, &err);
+ INTEGER_OBJ(pid), false, false, NULL, &err);
api_clear_error(&err);
channel_incref(chan);
diff --git a/src/nvim/eval/funcs.h b/src/nvim/eval/funcs.h
index 0c345dacb4..e3a574b233 100644
--- a/src/nvim/eval/funcs.h
+++ b/src/nvim/eval/funcs.h
@@ -3,7 +3,6 @@
#include <stdbool.h>
#include <stdint.h>
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h"
#include "nvim/pos_defs.h" // IWYU pragma: keep
diff --git a/src/nvim/eval/gc.h b/src/nvim/eval/gc.h
index 36149ec060..ea91952fff 100644
--- a/src/nvim/eval/gc.h
+++ b/src/nvim/eval/gc.h
@@ -6,5 +6,5 @@ extern dict_T *gc_first_dict;
extern list_T *gc_first_list;
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "eval/gc.h.generated.h" // IWYU pragma: export
+# include "eval/gc.h.generated.h"
#endif
diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c
index 069cdced34..9328f53dbd 100644
--- a/src/nvim/eval/typval.c
+++ b/src/nvim/eval/typval.c
@@ -5,7 +5,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include "nvim/ascii_defs.h"
#include "nvim/assert_defs.h"
@@ -20,10 +20,11 @@
#include "nvim/eval/vars.h"
#include "nvim/garray.h"
#include "nvim/garray_defs.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
-#include "nvim/lib/queue.h"
+#include "nvim/hashtab_defs.h"
+#include "nvim/lib/queue_defs.h"
#include "nvim/lua/executor.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
@@ -622,13 +623,14 @@ tv_list_copy_error:
listitem_T *tv_list_check_range_index_one(list_T *const l, int *const n1, const bool quiet)
{
listitem_T *li = tv_list_find_index(l, n1);
- if (li == NULL) {
- if (!quiet) {
- semsg(_(e_list_index_out_of_range_nr), (int64_t)(*n1));
- }
- return NULL;
+ if (li != NULL) {
+ return li;
}
- return li;
+
+ if (!quiet) {
+ semsg(_(e_list_index_out_of_range_nr), (int64_t)(*n1));
+ }
+ return NULL;
}
/// Check that "n2" can be used as the second index in a range of list "l".
@@ -1633,11 +1635,13 @@ static listitem_T *tv_list_find_index(list_T *const l, int *const idx)
FUNC_ATTR_WARN_UNUSED_RESULT
{
listitem_T *li = tv_list_find(l, *idx);
- if (li == NULL) {
- if (*idx < 0) {
- *idx = 0;
- li = tv_list_find(l, *idx);
- }
+ if (li != NULL) {
+ return li;
+ }
+
+ if (*idx < 0) {
+ *idx = 0;
+ li = tv_list_find(l, *idx);
}
return li;
}
@@ -1801,10 +1805,10 @@ void callback_copy(Callback *dest, Callback *src)
}
/// Generate a string description of a callback
-char *callback_to_string(Callback *cb)
+char *callback_to_string(Callback *cb, Arena *arena)
{
if (cb->type == kCallbackLua) {
- return nlua_funcref_str(cb->data.luaref);
+ return nlua_funcref_str(cb->data.luaref, arena);
}
const size_t msglen = 100;
@@ -2129,10 +2133,12 @@ void tv_dict_free_dict(dict_T *const d)
void tv_dict_free(dict_T *const d)
FUNC_ATTR_NONNULL_ALL
{
- if (!tv_in_free_unref_items) {
- tv_dict_free_contents(d);
- tv_dict_free_dict(d);
+ if (tv_in_free_unref_items) {
+ return;
}
+
+ tv_dict_free_contents(d);
+ tv_dict_free_dict(d);
}
/// Unreference a dictionary
@@ -2910,7 +2916,7 @@ static int tv_blob_index(const blob_T *blob, int len, varnumber_T idx, typval_T
return OK;
}
-int tv_blob_slice_or_index(const blob_T *blob, int is_range, varnumber_T n1, varnumber_T n2,
+int tv_blob_slice_or_index(const blob_T *blob, bool is_range, varnumber_T n1, varnumber_T n2,
bool exclusive, typval_T *rettv)
{
int len = tv_blob_len(rettv->vval.v_blob);
@@ -4345,6 +4351,22 @@ int tv_check_for_string_or_number_arg(const typval_T *const args, const int idx)
return OK;
}
+/// Give an error and return FAIL unless "args[idx]" is a buffer number.
+/// Buffer number can be a number or a string.
+int tv_check_for_buffer_arg(const typval_T *const args, const int idx)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
+{
+ return tv_check_for_string_or_number_arg(args, idx);
+}
+
+/// Give an error and return FAIL unless "args[idx]" is a line number.
+/// Line number can be a number or a string.
+int tv_check_for_lnum_arg(const typval_T *const args, const int idx)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
+{
+ return tv_check_for_string_or_number_arg(args, idx);
+}
+
/// Give an error and return FAIL unless "args[idx]" is a string or a list.
int tv_check_for_string_or_list_arg(const typval_T *const args, const int idx)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
diff --git a/src/nvim/eval/typval.h b/src/nvim/eval/typval.h
index 58f74a9796..f9ebd2f778 100644
--- a/src/nvim/eval/typval.h
+++ b/src/nvim/eval/typval.h
@@ -6,14 +6,13 @@
#include <stdint.h>
#include <string.h>
-#include "nvim/eval/typval_defs.h" // IWYU pragma: export
+#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/func_attr.h"
-#include "nvim/garray_defs.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/hashtab.h"
-#include "nvim/lib/queue.h"
+#include "nvim/lib/queue_defs.h"
#include "nvim/macros_defs.h"
-#include "nvim/mbyte_defs.h"
+#include "nvim/mbyte_defs.h" // IWYU pragma: keep
#include "nvim/message.h"
#include "nvim/types_defs.h"
@@ -85,6 +84,9 @@ static inline void tv_list_set_lock(list_T *const l, const VarLockStatus lock)
l->lv_lock = lock;
}
+static inline void tv_list_set_copyid(list_T *l, int copyid)
+ REAL_FATTR_NONNULL_ALL;
+
/// Set list copyID
///
/// Does not expect NULL list, be careful.
@@ -92,7 +94,6 @@ static inline void tv_list_set_lock(list_T *const l, const VarLockStatus lock)
/// @param[out] l List to modify.
/// @param[in] copyid New copyID.
static inline void tv_list_set_copyid(list_T *const l, const int copyid)
- FUNC_ATTR_NONNULL_ALL
{
l->lv_copyID = copyid;
}
@@ -359,7 +360,7 @@ extern bool tv_in_free_unref_items;
/// @param li Name of the variable with current listitem_T entry.
/// @param code Cycle body.
#define TV_LIST_ITER(l, li, code) \
- TV_LIST_ITER_MOD( , l, li, code) // NOLINT(whitespace/parens)
+ TV_LIST_ITER_MOD( , l, li, code)
/// Iterate over a list
///
@@ -442,22 +443,20 @@ static inline bool tv_get_float_chk(const typval_T *const tv, float_T *const ret
}
static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
- REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET REAL_FATTR_PURE
- REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE
- FUNC_ATTR_NO_SANITIZE_ADDRESS;
+ REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL REAL_FATTR_NONNULL_RET
+ REAL_FATTR_NO_SANITIZE_ADDRESS REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
/// Compute the `DictWatcher` address from a QUEUE node.
///
/// This only exists for .asan-blacklist (ASAN doesn't handle QUEUE_DATA pointer
/// arithmetic).
static inline DictWatcher *tv_dict_watcher_node_data(QUEUE *q)
- FUNC_ATTR_NO_SANITIZE_ADDRESS
{
return QUEUE_DATA(q, DictWatcher, node);
}
static inline bool tv_is_func(typval_T tv)
- FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_CONST;
+ REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE REAL_FATTR_CONST;
/// Check whether given typval_T contains a function
///
diff --git a/src/nvim/eval/typval_defs.h b/src/nvim/eval/typval_defs.h
index c6bd11ccdb..0d6ee28adc 100644
--- a/src/nvim/eval/typval_defs.h
+++ b/src/nvim/eval/typval_defs.h
@@ -2,10 +2,11 @@
#include <inttypes.h>
#include <limits.h>
+#include <stdbool.h>
#include "nvim/garray_defs.h"
#include "nvim/hashtab_defs.h"
-#include "nvim/lib/queue.h"
+#include "nvim/lib/queue_defs.h"
#include "nvim/pos_defs.h"
#include "nvim/types_defs.h"
@@ -13,8 +14,10 @@
typedef int64_t varnumber_T;
typedef uint64_t uvarnumber_T;
-/// Refcount for dict or list that should not be freed
-enum { DO_NOT_FREE_CNT = (INT_MAX / 2), };
+enum {
+ /// Refcount for dict or list that should not be freed
+ DO_NOT_FREE_CNT = (INT_MAX / 2),
+};
/// Additional values for tv_list_alloc() len argument
enum ListLenSpecials {
@@ -72,7 +75,7 @@ typedef struct {
#define CALLBACK_NONE ((Callback)CALLBACK_INIT)
/// Structure holding dictionary watcher
-typedef struct dict_watcher {
+typedef struct {
Callback callback;
char *key_pattern;
size_t key_pattern_len;
@@ -291,12 +294,9 @@ typedef struct {
uint64_t channel_id; /// Only used when script_id is SID_API_CLIENT.
} LastSet;
-/// Maximum number of function arguments
-enum { MAX_FUNC_ARGS = 20, };
-/// Short variable name length
-enum { VAR_SHORT_LEN = 20, };
-/// Number of fixed variables used for arguments
-enum { FIXVAR_CNT = 12, };
+enum { MAX_FUNC_ARGS = 20, }; ///< Maximum number of function arguments
+enum { VAR_SHORT_LEN = 20, }; ///< Short variable name length
+enum { FIXVAR_CNT = 12, }; ///< Number of fixed variables used for arguments
/// Structure to hold info for a function that is currently being executed.
typedef struct funccall_S funccall_T;
diff --git a/src/nvim/eval/typval_encode.c.h b/src/nvim/eval/typval_encode.c.h
index 2e0b68d486..c0cd0ce557 100644
--- a/src/nvim/eval/typval_encode.c.h
+++ b/src/nvim/eval/typval_encode.c.h
@@ -246,11 +246,12 @@
#include <inttypes.h>
#include <stddef.h>
+#include "klib/kvec.h"
+#include "nvim/eval.h"
#include "nvim/eval/encode.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_encode.h"
#include "nvim/func_attr.h"
-#include "klib/kvec.h"
/// Dummy variable used because some macros need lvalue
///
diff --git a/src/nvim/eval/userfunc.c b/src/nvim/eval/userfunc.c
index 23b3c4e1b2..fe10d56d49 100644
--- a/src/nvim/eval/userfunc.c
+++ b/src/nvim/eval/userfunc.c
@@ -10,6 +10,8 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand_defs.h"
#include "nvim/debugger.h"
@@ -22,11 +24,13 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
+#include "nvim/ex_eval_defs.h"
#include "nvim/ex_getln.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/getchar_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
#include "nvim/insexpand.h"
@@ -41,11 +45,13 @@
#include "nvim/path.h"
#include "nvim/profile.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/vim_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -105,8 +111,6 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int *
bool mustend = false;
char *arg = *argp;
char *p = arg;
- uint8_t c;
- int i;
if (newargs != NULL) {
ga_init(newargs, (int)sizeof(char *), 3);
@@ -143,12 +147,12 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int *
}
if (newargs != NULL) {
ga_grow(newargs, 1);
- c = (uint8_t)(*p);
+ uint8_t c = (uint8_t)(*p);
*p = NUL;
arg = xstrdup(arg);
// Check for duplicate argument name.
- for (i = 0; i < newargs->ga_len; i++) {
+ for (int i = 0; i < newargs->ga_len; i++) {
if (strcmp(((char **)(newargs->ga_data))[i], arg) == 0) {
semsg(_("E853: Duplicate argument name: %s"), arg);
xfree(arg);
@@ -174,7 +178,7 @@ static int get_function_args(char **argp, char endchar, garray_T *newargs, int *
while (p > expr && ascii_iswhite(p[-1])) {
p--;
}
- c = (uint8_t)(*p);
+ uint8_t c = (uint8_t)(*p);
*p = NUL;
expr = xstrdup(expr);
((char **)(default_args->ga_data))[default_args->ga_len] = expr;
@@ -326,7 +330,6 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg)
if (evaluate) {
int flags = 0;
- char *p;
garray_T newlines;
char *name = get_lambda_name();
@@ -339,7 +342,7 @@ int get_lambda_tv(char **arg, typval_T *rettv, evalarg_T *evalarg)
// Add "return " before the expression.
size_t len = (size_t)(7 + end - start + 1);
- p = xmalloc(len);
+ char *p = xmalloc(len);
((char **)(newlines.ga_data))[newlines.ga_len++] = p;
STRCPY(p, "return ");
xstrlcpy(p + 7, start, (size_t)(end - start) + 1);
@@ -919,11 +922,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
FUNC_ATTR_NONNULL_ARG(1, 3, 4)
{
bool using_sandbox = false;
- int save_did_emsg;
static int depth = 0;
dictitem_T *v;
int fixvar_idx = 0; // index in fc_fixvar[]
- int ai;
bool islambda = false;
char numbuf[NUMBUFLEN];
char *name;
@@ -931,7 +932,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
int tv_to_free_len = 0;
proftime_T wait_start;
proftime_T call_start;
- int started_profiling = false;
+ bool started_profiling = false;
bool did_save_redo = false;
save_redo_T save_redo;
@@ -1026,7 +1027,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
bool isdefault = false;
typval_T def_rettv;
- ai = i - fp->uf_args.ga_len;
+ int ai = i - fp->uf_args.ga_len;
if (ai < 0) {
// named argument a:name
name = FUNCARG(fp, i);
@@ -1169,7 +1170,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
const sctx_T save_current_sctx = current_sctx;
current_sctx = fp->uf_script_ctx;
- save_did_emsg = did_emsg;
+ int save_did_emsg = did_emsg;
did_emsg = false;
if (default_arg_err && (fp->uf_flags & FC_ABORT)) {
@@ -1180,7 +1181,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rett
// A Lambda always has the command "return {expr}". It is much faster
// to evaluate {expr} directly.
ex_nesting_level++;
- (void)eval1(&p, rettv, &EVALARG_EVALUATE);
+ eval1(&p, rettv, &EVALARG_EVALUATE);
ex_nesting_level--;
} else {
// call do_cmdline() to execute the lines
@@ -2074,7 +2075,7 @@ char *save_function_name(char **name, bool skip, int flags, funcdict_T *fudi)
if (strncmp(p, "<lambda>", 8) == 0) {
p += 8;
- (void)getdigits(&p, false, 0);
+ getdigits(&p, false, 0);
saved = xmemdupz(*name, (size_t)(p - *name));
if (fudi != NULL) {
CLEAR_POINTER(fudi);
@@ -3038,7 +3039,7 @@ static inline bool fc_referenced(const funccall_T *const fc)
/// @return true if items in "fc" do not have "copyID". That means they are not
/// referenced from anywhere that is in use.
-static int can_free_funccal(funccall_T *fc, int copyID)
+static bool can_free_funccal(funccall_T *fc, int copyID)
{
return fc->fc_l_varlist.lv_copyID != copyID
&& fc->fc_l_vars.dv_copyID != copyID
@@ -3051,7 +3052,7 @@ void ex_return(exarg_T *eap)
{
char *arg = eap->arg;
typval_T rettv;
- int returning = false;
+ bool returning = false;
if (current_funccal == NULL) {
emsg(_("E133: :return not inside a function"));
@@ -3398,7 +3399,7 @@ end:
///
/// @return true when the return can be carried out,
/// false when the return gets pending.
-int do_return(exarg_T *eap, int reanimate, int is_cmd, void *rettv)
+bool do_return(exarg_T *eap, bool reanimate, bool is_cmd, void *rettv)
{
cstack_T *const cstack = eap->cstack;
@@ -3663,7 +3664,7 @@ bool free_unref_funccal(int copyID, int testing)
if (did_free_funccal) {
// When a funccal was freed some more items might be garbage
// collected, so run again.
- (void)garbage_collect(testing);
+ garbage_collect(testing);
}
return did_free;
}
@@ -3819,7 +3820,7 @@ bool set_ref_in_previous_funccal(int copyID)
fc->fc_copyID = copyID + 1;
if (set_ref_in_ht(&fc->fc_l_vars.dv_hashtab, copyID + 1, NULL)
|| set_ref_in_ht(&fc->fc_l_avars.dv_hashtab, copyID + 1, NULL)
- || set_ref_in_list(&fc->fc_l_varlist, copyID + 1, NULL)) {
+ || set_ref_in_list_items(&fc->fc_l_varlist, copyID + 1, NULL)) {
return true;
}
}
@@ -3832,7 +3833,7 @@ static bool set_ref_in_funccal(funccall_T *fc, int copyID)
fc->fc_copyID = copyID;
if (set_ref_in_ht(&fc->fc_l_vars.dv_hashtab, copyID, NULL)
|| set_ref_in_ht(&fc->fc_l_avars.dv_hashtab, copyID, NULL)
- || set_ref_in_list(&fc->fc_l_varlist, copyID, NULL)
+ || set_ref_in_list_items(&fc->fc_l_varlist, copyID, NULL)
|| set_ref_in_func(NULL, fc->fc_func, copyID)) {
return true;
}
diff --git a/src/nvim/eval/userfunc.h b/src/nvim/eval/userfunc.h
index 8050caab2b..b3488b15a7 100644
--- a/src/nvim/eval/userfunc.h
+++ b/src/nvim/eval/userfunc.h
@@ -4,15 +4,13 @@
#include <stddef.h>
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
-#include "nvim/eval.h"
#include "nvim/eval/typval_defs.h"
+#include "nvim/eval_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/hashtab_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h"
#include "nvim/types_defs.h" // IWYU pragma: keep
-struct funccal_entry;
-
// From user function to hashitem and back.
#define UF2HIKEY(fp) ((fp)->uf_name)
#define HIKEY2UF(p) ((ufunc_T *)((p) - offsetof(ufunc_T, uf_name)))
diff --git a/src/nvim/eval/vars.c b/src/nvim/eval/vars.c
index 2968f75f4d..e016c65d90 100644
--- a/src/nvim/eval/vars.c
+++ b/src/nvim/eval/vars.c
@@ -7,10 +7,11 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/drawscreen.h"
@@ -18,16 +19,17 @@
#include "nvim/eval/encode.h"
#include "nvim/eval/funcs.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
#include "nvim/eval/vars.h"
#include "nvim/eval/window.h"
+#include "nvim/eval_defs.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
#include "nvim/macros_defs.h"
@@ -44,6 +46,8 @@
#include "nvim/vim_defs.h"
#include "nvim/window.h"
+typedef int (*ex_unletlock_callback)(lval_T *, char *, exarg_T *, int);
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/vars.c.generated.h"
#endif
@@ -377,7 +381,7 @@ void ex_let(exarg_T *eap)
if (!eap->skip) {
op[0] = '=';
op[1] = NUL;
- (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op);
+ ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op);
}
tv_clear(&rettv);
}
@@ -414,7 +418,7 @@ void ex_let(exarg_T *eap)
clear_evalarg(&evalarg, eap);
if (!eap->skip && eval_res != FAIL) {
- (void)ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op);
+ ex_let_vars(eap->arg, &rettv, false, semicolon, var_count, is_const, op);
}
if (eval_res != FAIL) {
tv_clear(&rettv);
@@ -617,7 +621,7 @@ static void list_tab_vars(int *first)
/// List variables in "arg".
static const char *list_arg_vars(exarg_T *eap, const char *arg, int *first)
{
- int error = false;
+ bool error = false;
int len;
const char *name;
const char *name_start;
@@ -762,11 +766,12 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const,
// Find the end of the name.
char *arg_end = NULL;
+ OptIndex opt_idx;
int scope;
- char *const p = (char *)find_option_end((const char **)&arg, &scope);
- if (p == NULL
- || (endchars != NULL
- && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL)) {
+
+ char *const p = (char *)find_option_var_end((const char **)&arg, &opt_idx, &scope);
+
+ if (p == NULL || (endchars != NULL && vim_strchr(endchars, (uint8_t)(*skipwhite(p))) == NULL)) {
emsg(_(e_letunexp));
return NULL;
}
@@ -774,11 +779,12 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const,
const char c1 = *p;
*p = NUL;
- uint32_t opt_p_flags;
- bool hidden;
- OptVal curval = get_option_value(arg, &opt_p_flags, scope, &hidden);
+ bool is_tty_opt = is_tty_option(arg);
+ bool hidden = is_option_hidden(opt_idx);
+ OptVal curval = is_tty_opt ? get_tty_option(arg) : get_option_value(opt_idx, scope);
OptVal newval = NIL_OPTVAL;
- if (curval.type == kOptValTypeNil && arg[0] != 't' && arg[1] != '_') {
+
+ if (curval.type == kOptValTypeNil) {
semsg(_(e_unknown_option2), arg);
goto theend;
}
@@ -790,7 +796,7 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const,
}
bool error;
- newval = tv_to_optval(tv, arg, opt_p_flags, &error);
+ newval = tv_to_optval(tv, opt_idx, arg, &error);
if (error) {
goto theend;
}
@@ -832,7 +838,7 @@ static char *ex_let_option(char *arg, typval_T *const tv, const bool is_const,
}
}
- const char *err = set_option_value(arg, newval, scope);
+ const char *err = set_option_value_handle_tty(arg, opt_idx, newval, scope);
arg_end = p;
if (err != NULL) {
emsg(_(err));
@@ -1300,7 +1306,7 @@ void vars_clear(hashtab_T *ht)
}
/// Like vars_clear(), but only free the value if "free_val" is true.
-void vars_clear_ext(hashtab_T *ht, int free_val)
+void vars_clear_ext(hashtab_T *ht, bool free_val)
{
int todo;
hashitem_T *hi;
@@ -1847,22 +1853,27 @@ static void getwinvar(typval_T *argvars, typval_T *rettv, int off)
///
/// @return Typval converted to OptVal. Must be freed by caller.
/// Returns NIL_OPTVAL for invalid option name.
-static OptVal tv_to_optval(typval_T *tv, const char *option, uint32_t flags, bool *error)
+///
+/// TODO(famiu): Refactor this to support multitype options.
+static OptVal tv_to_optval(typval_T *tv, OptIndex opt_idx, const char *option, bool *error)
{
OptVal value = NIL_OPTVAL;
char nbuf[NUMBUFLEN];
bool err = false;
+ const bool is_tty_opt = is_tty_option(option);
+ const bool option_has_bool = !is_tty_opt && option_has_type(opt_idx, kOptValTypeBoolean);
+ const bool option_has_num = !is_tty_opt && option_has_type(opt_idx, kOptValTypeNumber);
+ const bool option_has_str = is_tty_opt || option_has_type(opt_idx, kOptValTypeString);
- if ((flags & P_FUNC) && tv_is_func(*tv)) {
+ if (!is_tty_opt && (get_option(opt_idx)->flags & P_FUNC) && tv_is_func(*tv)) {
// If the option can be set to a function reference or a lambda
// and the passed value is a function reference, then convert it to
// the name (string) of the function reference.
char *strval = encode_tv2string(tv, NULL);
err = strval == NULL;
value = CSTR_AS_OPTVAL(strval);
- } else if (flags & (P_NUM | P_BOOL)) {
- varnumber_T n = (flags & P_NUM) ? tv_get_number_chk(tv, &err)
- : tv_get_bool_chk(tv, &err);
+ } else if (option_has_bool || option_has_num) {
+ varnumber_T n = option_has_num ? tv_get_number_chk(tv, &err) : tv_get_bool_chk(tv, &err);
// This could be either "0" or a string that's not a number.
// So we need to check if it's actually a number.
if (!err && tv->v_type == VAR_STRING && n == 0) {
@@ -1875,14 +1886,14 @@ static OptVal tv_to_optval(typval_T *tv, const char *option, uint32_t flags, boo
semsg(_("E521: Number required: &%s = '%s'"), option, tv->vval.v_string);
}
}
- value = (flags & P_NUM) ? NUMBER_OPTVAL((OptInt)n) : BOOLEAN_OPTVAL(TRISTATE_FROM_INT(n));
- } else if ((flags & P_STRING) || is_tty_option(option)) {
+ value = option_has_num ? NUMBER_OPTVAL((OptInt)n) : BOOLEAN_OPTVAL(TRISTATE_FROM_INT(n));
+ } else if (option_has_str) {
// Avoid setting string option to a boolean or a special value.
if (tv->v_type != VAR_BOOL && tv->v_type != VAR_SPECIAL) {
const char *strval = tv_get_string_buf_chk(tv, nbuf);
err = strval == NULL;
value = CSTR_TO_OPTVAL(strval);
- } else if (flags & P_STRING) {
+ } else if (!is_tty_opt) {
err = true;
emsg(_(e_stringreq));
}
@@ -1898,10 +1909,12 @@ static OptVal tv_to_optval(typval_T *tv, const char *option, uint32_t flags, boo
/// Convert an option value to typval.
///
-/// @param[in] value Option value to convert.
+/// @param[in] value Option value to convert.
+/// @param numbool Whether to convert boolean values to number.
+/// Used for backwards compatibility.
///
/// @return OptVal converted to typval.
-typval_T optval_as_tv(OptVal value)
+typval_T optval_as_tv(OptVal value, bool numbool)
{
typval_T rettv = { .v_type = VAR_SPECIAL, .vval = { .v_special = kSpecialVarNull } };
@@ -1909,19 +1922,16 @@ typval_T optval_as_tv(OptVal value)
case kOptValTypeNil:
break;
case kOptValTypeBoolean:
- switch (value.data.boolean) {
- case kTrue:
- rettv.v_type = VAR_BOOL;
- rettv.vval.v_bool = kBoolVarTrue;
- break;
- case kFalse:
- rettv.v_type = VAR_BOOL;
- rettv.vval.v_bool = kBoolVarFalse;
- break;
- case kNone:
- break; // return v:null for None boolean value
+ if (value.data.boolean != kNone) {
+ if (numbool) {
+ rettv.v_type = VAR_NUMBER;
+ rettv.vval.v_number = value.data.boolean == kTrue;
+ } else {
+ rettv.v_type = VAR_BOOL;
+ rettv.vval.v_bool = value.data.boolean == kTrue;
+ }
}
- break;
+ break; // return v:null for None boolean value.
case kOptValTypeNumber:
rettv.v_type = VAR_NUMBER;
rettv.vval.v_number = value.data.number;
@@ -1938,25 +1948,27 @@ typval_T optval_as_tv(OptVal value)
/// Set option "varname" to the value of "varp" for the current buffer/window.
static void set_option_from_tv(const char *varname, typval_T *varp)
{
- int opt_idx = findoption(varname);
- if (opt_idx < 0) {
+ OptIndex opt_idx = find_option(varname);
+ if (opt_idx == kOptInvalid) {
semsg(_(e_unknown_option2), varname);
return;
}
- uint32_t opt_p_flags = get_option(opt_idx)->flags;
bool error = false;
- OptVal value = tv_to_optval(varp, varname, opt_p_flags, &error);
+ OptVal value = tv_to_optval(varp, opt_idx, varname, &error);
if (!error) {
- set_option_value_give_err(varname, value, OPT_LOCAL);
- }
+ const char *errmsg = set_option_value_handle_tty(varname, opt_idx, value, OPT_LOCAL);
+ if (errmsg) {
+ emsg(errmsg);
+ }
+ }
optval_free(value);
}
/// "setwinvar()" and "settabwinvar()" functions
-static void setwinvar(typval_T *argvars, typval_T *rettv, int off)
+static void setwinvar(typval_T *argvars, int off)
{
if (check_secure()) {
return;
@@ -2065,8 +2077,6 @@ void f_getbufvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
/// "settabvar()" function
void f_settabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- rettv->vval.v_number = 0;
-
if (check_secure()) {
return;
}
@@ -2080,6 +2090,7 @@ void f_settabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
}
tabpage_T *const save_curtab = curtab;
+ tabpage_T *const save_lu_tp = lastused_tabpage;
goto_tabpage_tp(tp, false, false);
const size_t varname_len = strlen(varname);
@@ -2089,22 +2100,25 @@ void f_settabvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
set_var(tabvarname, varname_len + 2, varp, true);
xfree(tabvarname);
- // Restore current tabpage.
+ // Restore current tabpage and last accessed tabpage.
if (valid_tabpage(save_curtab)) {
goto_tabpage_tp(save_curtab, false, false);
+ if (valid_tabpage(save_lu_tp)) {
+ lastused_tabpage = save_lu_tp;
+ }
}
}
/// "settabwinvar()" function
void f_settabwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- setwinvar(argvars, rettv, 1);
+ setwinvar(argvars, 1);
}
/// "setwinvar()" function
void f_setwinvar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- setwinvar(argvars, rettv, 0);
+ setwinvar(argvars, 0);
}
/// "setbufvar()" function
diff --git a/src/nvim/eval/window.c b/src/nvim/eval/window.c
index e0abbad477..b8aa0c9641 100644
--- a/src/nvim/eval/window.c
+++ b/src/nvim/eval/window.c
@@ -9,19 +9,22 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
-#include "nvim/buffer_defs.h"
#include "nvim/cursor.h"
#include "nvim/eval/funcs.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/eval/window.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
+#include "nvim/mark_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
+#include "nvim/option_vars.h"
+#include "nvim/os/fs.h"
#include "nvim/pos_defs.h"
#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
@@ -480,6 +483,68 @@ void f_tabpagewinnr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_number = nr;
}
+/// Switch to a window for executing user code.
+/// Caller must call win_execute_after() later regardless of return value.
+///
+/// @return whether switching the window succeeded.
+bool win_execute_before(win_execute_T *args, win_T *wp, tabpage_T *tp)
+{
+ args->wp = wp;
+ args->curpos = wp->w_cursor;
+ args->cwd_status = FAIL;
+ args->apply_acd = false;
+
+ // Getting and setting directory can be slow on some systems, only do
+ // this when the current or target window/tab have a local directory or
+ // 'acd' is set.
+ if (curwin != wp
+ && (curwin->w_localdir != NULL || wp->w_localdir != NULL
+ || (curtab != tp && (curtab->tp_localdir != NULL || tp->tp_localdir != NULL))
+ || p_acd)) {
+ args->cwd_status = os_dirname(args->cwd, MAXPATHL);
+ }
+
+ // If 'acd' is set, check we are using that directory. If yes, then
+ // apply 'acd' afterwards, otherwise restore the current directory.
+ if (args->cwd_status == OK && p_acd) {
+ do_autochdir();
+ char autocwd[MAXPATHL];
+ if (os_dirname(autocwd, MAXPATHL) == OK) {
+ args->apply_acd = strcmp(args->cwd, autocwd) == 0;
+ }
+ }
+
+ if (switch_win_noblock(&args->switchwin, wp, tp, true) == OK) {
+ check_cursor();
+ return true;
+ }
+ return false;
+}
+
+/// Restore the previous window after executing user code.
+void win_execute_after(win_execute_T *args)
+{
+ restore_win_noblock(&args->switchwin, true);
+
+ if (args->apply_acd) {
+ do_autochdir();
+ } else if (args->cwd_status == OK) {
+ os_chdir(args->cwd);
+ }
+
+ // Update the status line if the cursor moved.
+ if (win_valid(args->wp) && !equalpos(args->curpos, args->wp->w_cursor)) {
+ args->wp->w_redr_status = true;
+ }
+
+ // In case the command moved the cursor or changed the Visual area,
+ // check it is valid.
+ check_cursor();
+ if (VIsual_active) {
+ check_pos(curbuf, &VIsual);
+ }
+}
+
/// "win_execute(win_id, command)" function
void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
@@ -494,7 +559,11 @@ void f_win_execute(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
- WIN_EXECUTE(wp, tp, execute_common(argvars, rettv, 1));
+ win_execute_T win_execute_args;
+ if (win_execute_before(&win_execute_args, wp, tp)) {
+ execute_common(argvars, rettv, 1);
+ }
+ win_execute_after(&win_execute_args);
}
/// "win_findbuf()" function
@@ -607,13 +676,13 @@ static void win_move_into_split(win_T *wp, win_T *targetwin, int size, int flags
// Remove the old window and frame from the tree of frames
int dir;
- (void)winframe_remove(wp, &dir, NULL);
+ winframe_remove(wp, &dir, NULL);
win_remove(wp, NULL);
last_status(false); // may need to remove last status line
- (void)win_comp_pos(); // recompute window positions
+ win_comp_pos(); // recompute window positions
// Split a window on the desired side and put the old window there
- (void)win_split_ins(size, flags, wp, dir);
+ win_split_ins(size, flags, wp, dir);
// If splitting horizontally, try to preserve height
if (size == 0 && !(flags & WSP_VERT)) {
@@ -642,7 +711,8 @@ void f_win_splitmove(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
return;
}
- int flags = 0, size = 0;
+ int flags = 0;
+ int size = 0;
if (argvars[2].v_type != VAR_UNKNOWN) {
dict_T *d;
@@ -685,7 +755,7 @@ void f_win_gettype(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
rettv->vval.v_string = xstrdup("preview");
} else if (wp->w_floating) {
rettv->vval.v_string = xstrdup("popup");
- } else if (wp == curwin && cmdwin_type != 0) {
+ } else if (wp == cmdwin_win) {
rettv->vval.v_string = xstrdup("command");
} else if (bt_quickfix(wp->w_buffer)) {
rettv->vval.v_string = xstrdup((wp->w_llist_ref != NULL ? "loclist" : "quickfix"));
@@ -914,16 +984,16 @@ int switch_win_noblock(switchwin_T *switchwin, win_T *win, tabpage_T *tp, bool n
return OK;
}
-// Restore current tabpage and window saved by switch_win(), if still valid.
-// When "no_display" is true the display won't be affected, no redraw is
-// triggered.
+/// Restore current tabpage and window saved by switch_win(), if still valid.
+/// When "no_display" is true the display won't be affected, no redraw is
+/// triggered.
void restore_win(switchwin_T *switchwin, bool no_display)
{
restore_win_noblock(switchwin, no_display);
unblock_autocmds();
}
-// As restore_win() but without unblocking autocommands.
+/// As restore_win() but without unblocking autocommands.
void restore_win_noblock(switchwin_T *switchwin, bool no_display)
{
if (switchwin->sw_curtab != NULL && valid_tabpage(switchwin->sw_curtab)) {
diff --git a/src/nvim/eval/window.h b/src/nvim/eval/window.h
index ed879c895a..37cb138404 100644
--- a/src/nvim/eval/window.h
+++ b/src/nvim/eval/window.h
@@ -1,20 +1,12 @@
#pragma once
#include <stdbool.h>
-#include <string.h>
-#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
-#include "nvim/cursor.h"
-#include "nvim/eval/typval_defs.h"
-#include "nvim/globals.h"
-#include "nvim/mark.h"
-#include "nvim/option_defs.h"
-#include "nvim/option_vars.h"
-#include "nvim/os/fs.h"
+#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
+#include "nvim/os/os_defs.h"
#include "nvim/pos_defs.h"
-#include "nvim/vim_defs.h"
-#include "nvim/window.h"
+#include "nvim/types_defs.h"
/// Structure used by switch_win() to pass values to restore_win()
typedef struct {
@@ -24,53 +16,15 @@ typedef struct {
bool sw_visual_active;
} switchwin_T;
-/// Execute a block of code in the context of window `wp` in tabpage `tp`.
-/// Ensures the status line is redrawn and cursor position is valid if it is moved.
-#define WIN_EXECUTE(wp, tp, block) \
- do { \
- win_T *const wp_ = (wp); \
- const pos_T curpos_ = wp_->w_cursor; \
- char cwd_[MAXPATHL]; \
- char autocwd_[MAXPATHL]; \
- bool apply_acd_ = false; \
- int cwd_status_ = FAIL; \
- /* Getting and setting directory can be slow on some systems, only do */ \
- /* this when the current or target window/tab have a local directory or */ \
- /* 'acd' is set. */ \
- if (curwin != wp \
- && (curwin->w_localdir != NULL || wp->w_localdir != NULL \
- || (curtab != tp && (curtab->tp_localdir != NULL || tp->tp_localdir != NULL)) \
- || p_acd)) { \
- cwd_status_ = os_dirname(cwd_, MAXPATHL); \
- } \
- /* If 'acd' is set, check we are using that directory. If yes, then */ \
- /* apply 'acd' afterwards, otherwise restore the current directory. */ \
- if (cwd_status_ == OK && p_acd) { \
- do_autochdir(); \
- apply_acd_ = os_dirname(autocwd_, MAXPATHL) == OK && strcmp(cwd_, autocwd_) == 0; \
- } \
- switchwin_T switchwin_; \
- if (switch_win_noblock(&switchwin_, wp_, (tp), true) == OK) { \
- check_cursor(); \
- block; \
- } \
- restore_win_noblock(&switchwin_, true); \
- if (apply_acd_) { \
- do_autochdir(); \
- } else if (cwd_status_ == OK) { \
- os_chdir(cwd_); \
- } \
- /* Update the status line if the cursor moved. */ \
- if (win_valid(wp_) && !equalpos(curpos_, wp_->w_cursor)) { \
- wp_->w_redr_status = true; \
- } \
- /* In case the command moved the cursor or changed the Visual area, */ \
- /* check it is valid. */ \
- check_cursor(); \
- if (VIsual_active) { \
- check_pos(curbuf, &VIsual); \
- } \
- } while (false)
+/// Structure used by win_execute_before() to pass values to win_execute_after()
+typedef struct {
+ win_T *wp;
+ pos_T curpos;
+ char cwd[MAXPATHL];
+ int cwd_status;
+ bool apply_acd;
+ switchwin_T switchwin;
+} win_execute_T;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "eval/window.h.generated.h"
diff --git a/src/nvim/eval_defs.h b/src/nvim/eval_defs.h
new file mode 100644
index 0000000000..4bbebb14f5
--- /dev/null
+++ b/src/nvim/eval_defs.h
@@ -0,0 +1,30 @@
+#pragma once
+
+#include "nvim/ex_cmds_defs.h"
+
+/// All recognized msgpack types
+typedef enum {
+ kMPNil,
+ kMPBoolean,
+ kMPInteger,
+ kMPFloat,
+ kMPString,
+ kMPBinary,
+ kMPArray,
+ kMPMap,
+ kMPExt,
+} MessagePackType;
+#define NUM_MSGPACK_TYPES (kMPExt + 1)
+
+/// Struct passed through eval() functions.
+/// See EVALARG_EVALUATE for a fixed value with eval_flags set to EVAL_EVALUATE.
+typedef struct {
+ int eval_flags; ///< EVAL_ flag values below
+
+ /// copied from exarg_T when "getline" is "getsourceline". Can be NULL.
+ LineGetter eval_getline;
+ void *eval_cookie; ///< argument for eval_getline()
+
+ /// pointer to the last line obtained with getsourceline()
+ char *eval_tofree;
+} evalarg_T;
diff --git a/src/nvim/event/defs.h b/src/nvim/event/defs.h
index 571f61dfdb..9b7d8708be 100644
--- a/src/nvim/event/defs.h
+++ b/src/nvim/event/defs.h
@@ -2,34 +2,155 @@
#include <assert.h>
#include <stdarg.h>
+#include <stdbool.h>
+#include <uv.h>
-#define EVENT_HANDLER_MAX_ARGC 10
+#include "nvim/eval/typval_defs.h"
+#include "nvim/rbuffer_defs.h"
+#include "nvim/types_defs.h"
+
+enum { EVENT_HANDLER_MAX_ARGC = 10, };
typedef void (*argv_callback)(void **argv);
-typedef struct message {
+typedef struct {
argv_callback handler;
void *argv[EVENT_HANDLER_MAX_ARGC];
} Event;
-typedef void (*event_scheduler)(Event event, void *data);
-
-#define VA_EVENT_INIT(event, h, a) \
- do { \
- assert(a <= EVENT_HANDLER_MAX_ARGC); \
- (event)->handler = h; \
- if (a) { \
- va_list args; \
- va_start(args, a); \
- for (int i = 0; i < a; i++) { \
- (event)->argv[i] = va_arg(args, void *); \
- } \
- va_end(args); \
- } \
- } while (0)
-
-static inline Event event_create(argv_callback cb, int argc, ...)
-{
- assert(argc <= EVENT_HANDLER_MAX_ARGC);
- Event event;
- VA_EVENT_INIT(&event, cb, argc);
- return event;
-}
+
+#define event_create(cb, ...) ((Event){ .handler = cb, .argv = { __VA_ARGS__ } })
+
+typedef struct multiqueue MultiQueue;
+typedef void (*PutCallback)(MultiQueue *multiq, void *data);
+
+typedef struct signal_watcher SignalWatcher;
+typedef void (*signal_cb)(SignalWatcher *watcher, int signum, void *data);
+typedef void (*signal_close_cb)(SignalWatcher *watcher, void *data);
+
+struct signal_watcher {
+ uv_signal_t uv;
+ void *data;
+ signal_cb cb;
+ signal_close_cb close_cb;
+ MultiQueue *events;
+};
+
+typedef struct time_watcher TimeWatcher;
+typedef void (*time_cb)(TimeWatcher *watcher, void *data);
+
+struct time_watcher {
+ uv_timer_t uv;
+ void *data;
+ time_cb cb, close_cb;
+ MultiQueue *events;
+ bool blockable;
+};
+
+typedef struct wbuffer WBuffer;
+typedef void (*wbuffer_data_finalizer)(void *data);
+
+struct wbuffer {
+ size_t size, refcount;
+ char *data;
+ wbuffer_data_finalizer cb;
+};
+
+typedef struct stream Stream;
+/// Type of function called when the Stream buffer is filled with data
+///
+/// @param stream The Stream instance
+/// @param buf The associated RBuffer instance
+/// @param count Number of bytes that was read.
+/// @param data User-defined data
+/// @param eof If the stream reached EOF.
+typedef void (*stream_read_cb)(Stream *stream, RBuffer *buf, size_t count, void *data, bool eof);
+
+/// Type of function called when the Stream has information about a write
+/// request.
+///
+/// @param stream The Stream instance
+/// @param data User-defined data
+/// @param status 0 on success, anything else indicates failure
+typedef void (*stream_write_cb)(Stream *stream, void *data, int status);
+typedef void (*stream_close_cb)(Stream *stream, void *data);
+
+struct stream {
+ bool closed;
+ bool did_eof;
+ union {
+ uv_pipe_t pipe;
+ uv_tcp_t tcp;
+ uv_idle_t idle;
+#ifdef MSWIN
+ uv_tty_t tty;
+#endif
+ } uv;
+ uv_stream_t *uvstream;
+ uv_buf_t uvbuf;
+ RBuffer *buffer;
+ uv_file fd;
+ stream_read_cb read_cb;
+ stream_write_cb write_cb;
+ void *cb_data;
+ stream_close_cb close_cb, internal_close_cb;
+ void *close_cb_data, *internal_data;
+ size_t fpos;
+ size_t curmem;
+ size_t maxmem;
+ size_t pending_reqs;
+ size_t num_bytes;
+ MultiQueue *events;
+};
+
+#define ADDRESS_MAX_SIZE 256
+
+typedef struct socket_watcher SocketWatcher;
+typedef void (*socket_cb)(SocketWatcher *watcher, int result, void *data);
+typedef void (*socket_close_cb)(SocketWatcher *watcher, void *data);
+
+struct socket_watcher {
+ // Pipe/socket path, or TCP address string
+ char addr[ADDRESS_MAX_SIZE];
+ // TCP server or unix socket (named pipe on Windows)
+ union {
+ struct {
+ uv_tcp_t handle;
+ struct addrinfo *addrinfo;
+ } tcp;
+ struct {
+ uv_pipe_t handle;
+ } pipe;
+ } uv;
+ uv_stream_t *stream;
+ void *data;
+ socket_cb cb;
+ socket_close_cb close_cb;
+ MultiQueue *events;
+};
+
+typedef enum {
+ kProcessTypeUv,
+ kProcessTypePty,
+} ProcessType;
+
+typedef struct process Process;
+typedef void (*process_exit_cb)(Process *proc, int status, void *data);
+typedef void (*internal_process_cb)(Process *proc);
+
+struct process {
+ ProcessType type;
+ Loop *loop;
+ void *data;
+ int pid, status, refcount;
+ uint8_t exit_signal; // Signal used when killing (on Windows).
+ uint64_t stopped_time; // process_stop() timestamp
+ const char *cwd;
+ char **argv;
+ const char *exepath;
+ dict_T *env;
+ Stream in, out, err;
+ /// Exit handler. If set, user must call process_free().
+ process_exit_cb cb;
+ internal_process_cb internal_exit_cb, internal_close_cb;
+ bool closed, detach, overlapped, fwd_err;
+ MultiQueue *events;
+};
diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c
index be48b39af1..a7966994e0 100644
--- a/src/nvim/event/libuv_process.c
+++ b/src/nvim/event/libuv_process.c
@@ -4,12 +4,14 @@
#include <uv.h>
#include "nvim/eval/typval.h"
+#include "nvim/event/defs.h"
#include "nvim/event/libuv_process.h"
+#include "nvim/event/loop.h"
#include "nvim/event/process.h"
-#include "nvim/event/stream.h"
-#include "nvim/func_attr.h"
#include "nvim/log.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
+#include "nvim/types_defs.h"
#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -127,3 +129,11 @@ static void exit_cb(uv_process_t *handle, int64_t status, int term_signal)
proc->status = term_signal ? 128 + term_signal : (int)status;
proc->internal_exit_cb(proc);
}
+
+LibuvProcess libuv_process_init(Loop *loop, void *data)
+{
+ LibuvProcess rv = {
+ .process = process_init(loop, kProcessTypeUv, data)
+ };
+ return rv;
+}
diff --git a/src/nvim/event/libuv_process.h b/src/nvim/event/libuv_process.h
index e3e2bfeb76..12401dbb35 100644
--- a/src/nvim/event/libuv_process.h
+++ b/src/nvim/event/libuv_process.h
@@ -2,24 +2,15 @@
#include <uv.h>
-#include "nvim/event/loop.h"
-#include "nvim/event/process.h"
+#include "nvim/event/defs.h"
-typedef struct libuv_process {
+typedef struct {
Process process;
uv_process_t uv;
uv_process_options_t uvopts;
uv_stdio_container_t uvstdio[4];
} LibuvProcess;
-static inline LibuvProcess libuv_process_init(Loop *loop, void *data)
-{
- LibuvProcess rv = {
- .process = process_init(loop, kProcessTypeUv, data)
- };
- return rv;
-}
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/libuv_process.h.generated.h"
#endif
diff --git a/src/nvim/event/loop.c b/src/nvim/event/loop.c
index d61666e6d4..93948d3eaa 100644
--- a/src/nvim/event/loop.c
+++ b/src/nvim/event/loop.c
@@ -3,11 +3,12 @@
#include <stdlib.h>
#include <uv.h>
-#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/log.h"
#include "nvim/memory.h"
#include "nvim/os/time.h"
+#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/loop.c.generated.h"
@@ -111,7 +112,7 @@ void loop_schedule_deferred(Loop *loop, Event event)
{
Event *eventp = xmalloc(sizeof(*eventp));
*eventp = event;
- loop_schedule_fast(loop, event_create(loop_deferred_event, 2, loop, eventp));
+ loop_schedule_fast(loop, event_create(loop_deferred_event, loop, eventp));
}
static void loop_deferred_event(void **argv)
{
diff --git a/src/nvim/event/loop.h b/src/nvim/event/loop.h
index 5665332e95..6ecc7cb781 100644
--- a/src/nvim/event/loop.h
+++ b/src/nvim/event/loop.h
@@ -1,19 +1,18 @@
#pragma once
#include <stdbool.h>
-#include <stdint.h>
#include <uv.h>
#include "klib/klist.h"
-#include "nvim/event/multiqueue.h"
-#include "nvim/os/time.h"
+#include "nvim/event/defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
typedef void *WatcherPtr;
#define _NOOP(x)
KLIST_INIT(WatcherPtr, WatcherPtr, _NOOP)
-typedef struct loop {
+struct loop {
uv_loop_t uv;
MultiQueue *events;
MultiQueue *thread_events;
@@ -42,46 +41,7 @@ typedef struct loop {
uv_mutex_t mutex;
int recursive;
bool closing; ///< Set to true if loop_close() has been called
-} Loop;
-
-#define CREATE_EVENT(multiqueue, handler, argc, ...) \
- do { \
- if (multiqueue) { \
- multiqueue_put((multiqueue), (handler), argc, __VA_ARGS__); \
- } else { \
- void *argv[argc] = { __VA_ARGS__ }; \
- (handler)(argv); \
- } \
- } while (0)
-
-// Poll for events until a condition or timeout
-#define LOOP_PROCESS_EVENTS_UNTIL(loop, multiqueue, timeout, condition) \
- do { \
- int64_t remaining = timeout; \
- uint64_t before = (remaining > 0) ? os_hrtime() : 0; \
- while (!(condition)) { \
- LOOP_PROCESS_EVENTS(loop, multiqueue, remaining); \
- if (remaining == 0) { \
- break; \
- } else if (remaining > 0) { \
- uint64_t now = os_hrtime(); \
- remaining -= (int64_t)((now - before) / 1000000); \
- before = now; \
- if (remaining <= 0) { \
- break; \
- } \
- } \
- } \
- } while (0)
-
-#define LOOP_PROCESS_EVENTS(loop, multiqueue, timeout) \
- do { \
- if (multiqueue && !multiqueue_empty(multiqueue)) { \
- multiqueue_process_events(multiqueue); \
- } else { \
- loop_poll_events(loop, timeout); \
- } \
- } while (0)
+};
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/loop.h.generated.h"
diff --git a/src/nvim/event/multiqueue.c b/src/nvim/event/multiqueue.c
index 3ab41bd299..8646173776 100644
--- a/src/nvim/event/multiqueue.c
+++ b/src/nvim/event/multiqueue.c
@@ -48,8 +48,7 @@
#include "nvim/event/defs.h"
#include "nvim/event/multiqueue.h"
-#include "nvim/func_attr.h"
-#include "nvim/lib/queue.h"
+#include "nvim/lib/queue_defs.h"
#include "nvim/memory.h"
typedef struct multiqueue_item MultiQueueItem;
@@ -157,7 +156,7 @@ void multiqueue_purge_events(MultiQueue *self)
{
assert(self);
while (!multiqueue_empty(self)) {
- (void)multiqueue_remove(self);
+ multiqueue_remove(self);
}
}
@@ -261,7 +260,7 @@ Event event_create_oneshot(Event ev, int num)
data->event = ev;
data->fired = false;
data->refcount = num;
- return event_create(multiqueue_oneshot_event, 1, data);
+ return event_create(multiqueue_oneshot_event, data);
}
static void multiqueue_oneshot_event(void **argv)
{
diff --git a/src/nvim/event/multiqueue.h b/src/nvim/event/multiqueue.h
index e01ee1e710..24aaa34ef7 100644
--- a/src/nvim/event/multiqueue.h
+++ b/src/nvim/event/multiqueue.h
@@ -1,16 +1,54 @@
#pragma once
-#include <uv.h>
+#include <stddef.h> // IWYU pragma: keep
-#include "nvim/event/defs.h"
-#include "nvim/lib/queue.h"
-
-typedef struct multiqueue MultiQueue;
-typedef void (*PutCallback)(MultiQueue *multiq, void *data);
-
-#define multiqueue_put(q, h, ...) \
- multiqueue_put_event(q, event_create(h, __VA_ARGS__));
+#include "nvim/event/defs.h" // IWYU pragma: keep
+#include "nvim/os/time.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/multiqueue.h.generated.h"
#endif
+
+#define multiqueue_put(q, h, ...) \
+ do { \
+ multiqueue_put_event(q, event_create(h, __VA_ARGS__)); \
+ } while (0)
+
+#define CREATE_EVENT(multiqueue, handler, ...) \
+ do { \
+ if (multiqueue) { \
+ multiqueue_put((multiqueue), (handler), __VA_ARGS__); \
+ } else { \
+ void *argv[] = { __VA_ARGS__ }; \
+ (handler)(argv); \
+ } \
+ } while (0)
+
+// Poll for events until a condition or timeout
+#define LOOP_PROCESS_EVENTS_UNTIL(loop, multiqueue, timeout, condition) \
+ do { \
+ int64_t remaining = timeout; \
+ uint64_t before = (remaining > 0) ? os_hrtime() : 0; \
+ while (!(condition)) { \
+ LOOP_PROCESS_EVENTS(loop, multiqueue, remaining); \
+ if (remaining == 0) { \
+ break; \
+ } else if (remaining > 0) { \
+ uint64_t now = os_hrtime(); \
+ remaining -= (int64_t)((now - before) / 1000000); \
+ before = now; \
+ if (remaining <= 0) { \
+ break; \
+ } \
+ } \
+ } \
+ } while (0)
+
+#define LOOP_PROCESS_EVENTS(loop, multiqueue, timeout) \
+ do { \
+ if (multiqueue && !multiqueue_empty(multiqueue)) { \
+ multiqueue_process_events(multiqueue); \
+ } else { \
+ loop_poll_events(loop, timeout); \
+ } \
+ } while (0)
diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c
index 864fc2c1d8..7460e92766 100644
--- a/src/nvim/event/process.c
+++ b/src/nvim/event/process.c
@@ -6,8 +6,9 @@
#include "klib/klist.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
-#include "nvim/func_attr.h"
+#include "nvim/event/stream.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/main.h"
@@ -15,7 +16,7 @@
#include "nvim/os/pty_process.h"
#include "nvim/os/shell.h"
#include "nvim/os/time.h"
-#include "nvim/rbuffer.h"
+#include "nvim/rbuffer_defs.h"
#include "nvim/ui_client.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -133,7 +134,7 @@ void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL
Process *proc = (*current)->data;
if (proc->detach || proc->type == kProcessTypePty) {
// Close handles to process without killing it.
- CREATE_EVENT(loop->events, process_close_handles, 1, proc);
+ CREATE_EVENT(loop->events, process_close_handles, proc);
} else {
process_stop(proc);
}
@@ -301,7 +302,7 @@ static void decref(Process *proc)
}
assert(node);
kl_shift_at(WatcherPtr, loop->children, node);
- CREATE_EVENT(proc->events, process_close_event, 1, proc);
+ CREATE_EVENT(proc->events, process_close_event, proc);
}
static void process_close(Process *proc)
@@ -396,7 +397,7 @@ static void process_close_handles(void **argv)
static void exit_delay_cb(uv_timer_t *handle)
{
uv_timer_stop(&main_loop.exit_delay_timer);
- multiqueue_put(main_loop.fast_events, exit_event, 1, main_loop.exit_delay_timer.data);
+ multiqueue_put(main_loop.fast_events, exit_event, main_loop.exit_delay_timer.data);
}
static void exit_event(void **argv)
@@ -421,7 +422,7 @@ static void exit_event(void **argv)
void exit_from_channel(int status)
{
- multiqueue_put(main_loop.fast_events, exit_event, 1, status);
+ multiqueue_put(main_loop.fast_events, exit_event, (void *)(intptr_t)status);
}
static void on_process_exit(Process *proc)
@@ -439,7 +440,7 @@ static void on_process_exit(Process *proc)
// more data directly. Instead delay the reading after the libuv loop by
// queueing process_close_handles() as an event.
MultiQueue *queue = proc->events ? proc->events : loop->events;
- CREATE_EVENT(queue, process_close_handles, 1, proc);
+ CREATE_EVENT(queue, process_close_handles, proc);
}
static void on_process_stream_close(Stream *stream, void *data)
diff --git a/src/nvim/event/process.h b/src/nvim/event/process.h
index 234fc815af..421a470244 100644
--- a/src/nvim/event/process.h
+++ b/src/nvim/event/process.h
@@ -2,44 +2,9 @@
#include <stdbool.h>
#include <stddef.h>
-#include <stdint.h>
-#include "nvim/eval/typval_defs.h"
-#include "nvim/event/loop.h"
-#include "nvim/event/multiqueue.h"
-#include "nvim/event/rstream.h"
-#include "nvim/event/stream.h"
-#include "nvim/event/wstream.h"
-
-struct process;
-
-typedef enum {
- kProcessTypeUv,
- kProcessTypePty,
-} ProcessType;
-
-typedef struct process Process;
-typedef void (*process_exit_cb)(Process *proc, int status, void *data);
-typedef void (*internal_process_cb)(Process *proc);
-
-struct process {
- ProcessType type;
- Loop *loop;
- void *data;
- int pid, status, refcount;
- uint8_t exit_signal; // Signal used when killing (on Windows).
- uint64_t stopped_time; // process_stop() timestamp
- const char *cwd;
- char **argv;
- const char *exepath;
- dict_T *env;
- Stream in, out, err;
- /// Exit handler. If set, user must call process_free().
- process_exit_cb cb;
- internal_process_cb internal_exit_cb, internal_close_cb;
- bool closed, detach, overlapped, fwd_err;
- MultiQueue *events;
-};
+#include "nvim/event/defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h"
static inline Process process_init(Loop *loop, ProcessType type, void *data)
{
diff --git a/src/nvim/event/rstream.c b/src/nvim/event/rstream.c
index 73828a2271..f50c8a0e5a 100644
--- a/src/nvim/event/rstream.c
+++ b/src/nvim/event/rstream.c
@@ -2,18 +2,18 @@
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
-#include <sys/types.h>
#include <uv.h>
-#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/event/rstream.h"
#include "nvim/event/stream.h"
-#include "nvim/func_attr.h"
#include "nvim/log.h"
#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/os/os_defs.h"
#include "nvim/rbuffer.h"
+#include "nvim/rbuffer_defs.h"
+#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/rstream.c.generated.h"
@@ -201,10 +201,6 @@ static void invoke_read_cb(Stream *stream, size_t count, bool eof)
// Don't let the stream be closed before the event is processed.
stream->pending_reqs++;
- CREATE_EVENT(stream->events,
- read_event,
- 3,
- stream,
- (void *)(uintptr_t *)count,
- (void *)(uintptr_t)eof);
+ CREATE_EVENT(stream->events, read_event,
+ stream, (void *)(uintptr_t *)count, (void *)(uintptr_t)eof);
}
diff --git a/src/nvim/event/rstream.h b/src/nvim/event/rstream.h
index b2a62acf83..4e2893bf88 100644
--- a/src/nvim/event/rstream.h
+++ b/src/nvim/event/rstream.h
@@ -1,11 +1,7 @@
#pragma once
-#include <stdbool.h>
-#include <stddef.h>
-#include <uv.h>
-
-#include "nvim/event/loop.h"
-#include "nvim/event/stream.h"
+#include "nvim/event/defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/rstream.h.generated.h"
diff --git a/src/nvim/event/signal.c b/src/nvim/event/signal.c
index e64d526856..57241e79b2 100644
--- a/src/nvim/event/signal.c
+++ b/src/nvim/event/signal.c
@@ -1,9 +1,11 @@
#include <stddef.h>
#include <uv.h>
+#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/event/signal.h"
-#include "nvim/func_attr.h"
+#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/signal.c.generated.h"
@@ -48,7 +50,7 @@ static void signal_event(void **argv)
static void signal_watcher_cb(uv_signal_t *handle, int signum)
{
SignalWatcher *watcher = handle->data;
- CREATE_EVENT(watcher->events, signal_event, 1, watcher);
+ CREATE_EVENT(watcher->events, signal_event, watcher);
}
static void close_cb(uv_handle_t *handle)
diff --git a/src/nvim/event/signal.h b/src/nvim/event/signal.h
index 946de1b4f0..16cd2be951 100644
--- a/src/nvim/event/signal.h
+++ b/src/nvim/event/signal.h
@@ -1,23 +1,7 @@
#pragma once
-#include <uv.h>
-
-#include "nvim/event/loop.h"
-#include "nvim/event/multiqueue.h"
-
-struct signal_watcher;
-
-typedef struct signal_watcher SignalWatcher;
-typedef void (*signal_cb)(SignalWatcher *watcher, int signum, void *data);
-typedef void (*signal_close_cb)(SignalWatcher *watcher, void *data);
-
-struct signal_watcher {
- uv_signal_t uv;
- void *data;
- signal_cb cb;
- signal_close_cb close_cb;
- MultiQueue *events;
-};
+#include "nvim/event/defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/signal.h.generated.h"
diff --git a/src/nvim/event/socket.c b/src/nvim/event/socket.c
index e787e023f0..4e878a2ecf 100644
--- a/src/nvim/event/socket.c
+++ b/src/nvim/event/socket.c
@@ -7,17 +7,19 @@
#include "nvim/ascii_defs.h"
#include "nvim/charset.h"
+#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/event/socket.h"
#include "nvim/event/stream.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/memory.h"
#include "nvim/os/fs.h"
-#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
+#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/socket.c.generated.h"
@@ -175,8 +177,7 @@ static void connection_event(void **argv)
static void connection_cb(uv_stream_t *handle, int status)
{
SocketWatcher *watcher = handle->data;
- CREATE_EVENT(watcher->events, connection_event, 2, watcher,
- (void *)(uintptr_t)status);
+ CREATE_EVENT(watcher->events, connection_event, watcher, (void *)(uintptr_t)status);
}
static void close_cb(uv_handle_t *handle)
diff --git a/src/nvim/event/socket.h b/src/nvim/event/socket.h
index 504af3c7a8..64a77a9a06 100644
--- a/src/nvim/event/socket.h
+++ b/src/nvim/event/socket.h
@@ -1,39 +1,7 @@
#pragma once
-#include <uv.h>
-
-#include "nvim/event/loop.h"
-#include "nvim/event/multiqueue.h"
-#include "nvim/event/rstream.h"
-#include "nvim/event/wstream.h"
-
-struct socket_watcher;
-
-#define ADDRESS_MAX_SIZE 256
-
-typedef struct socket_watcher SocketWatcher;
-typedef void (*socket_cb)(SocketWatcher *watcher, int result, void *data);
-typedef void (*socket_close_cb)(SocketWatcher *watcher, void *data);
-
-struct socket_watcher {
- // Pipe/socket path, or TCP address string
- char addr[ADDRESS_MAX_SIZE];
- // TCP server or unix socket (named pipe on Windows)
- union {
- struct {
- uv_tcp_t handle;
- struct addrinfo *addrinfo;
- } tcp;
- struct {
- uv_pipe_t handle;
- } pipe;
- } uv;
- uv_stream_t *stream;
- void *data;
- socket_cb cb;
- socket_close_cb close_cb;
- MultiQueue *events;
-};
+#include "nvim/event/defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/socket.h.generated.h"
diff --git a/src/nvim/event/stream.c b/src/nvim/event/stream.c
index aff116bad9..0b9ed4f25b 100644
--- a/src/nvim/event/stream.c
+++ b/src/nvim/event/stream.c
@@ -4,11 +4,12 @@
#include <uv.h>
#include <uv/version.h>
+#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/stream.h"
-#include "nvim/func_attr.h"
#include "nvim/log.h"
#include "nvim/rbuffer.h"
+#include "nvim/types_defs.h"
#ifdef MSWIN
# include "nvim/os/os_win_console.h"
#endif
@@ -129,15 +130,22 @@ void stream_may_close(Stream *stream)
void stream_close_handle(Stream *stream)
FUNC_ATTR_NONNULL_ALL
{
+ uv_handle_t *handle = NULL;
if (stream->uvstream) {
if (uv_stream_get_write_queue_size(stream->uvstream) > 0) {
WLOG("closed Stream (%p) with %zu unwritten bytes",
(void *)stream,
uv_stream_get_write_queue_size(stream->uvstream));
}
- uv_close((uv_handle_t *)stream->uvstream, close_cb);
+ handle = (uv_handle_t *)stream->uvstream;
} else {
- uv_close((uv_handle_t *)&stream->uv.idle, close_cb);
+ handle = (uv_handle_t *)&stream->uv.idle;
+ }
+
+ assert(handle != NULL);
+
+ if (!uv_is_closing(handle)) {
+ uv_close(handle, close_cb);
}
}
diff --git a/src/nvim/event/stream.h b/src/nvim/event/stream.h
index d02707dc45..9bdfc421d6 100644
--- a/src/nvim/event/stream.h
+++ b/src/nvim/event/stream.h
@@ -1,61 +1,7 @@
#pragma once
-#include <stdbool.h>
-#include <stddef.h>
-#include <uv.h>
-
-#include "nvim/event/loop.h"
-#include "nvim/event/multiqueue.h"
-#include "nvim/rbuffer.h"
-
-struct stream;
-
-typedef struct stream Stream;
-/// Type of function called when the Stream buffer is filled with data
-///
-/// @param stream The Stream instance
-/// @param buf The associated RBuffer instance
-/// @param count Number of bytes that was read.
-/// @param data User-defined data
-/// @param eof If the stream reached EOF.
-typedef void (*stream_read_cb)(Stream *stream, RBuffer *buf, size_t count, void *data, bool eof);
-
-/// Type of function called when the Stream has information about a write
-/// request.
-///
-/// @param stream The Stream instance
-/// @param data User-defined data
-/// @param status 0 on success, anything else indicates failure
-typedef void (*stream_write_cb)(Stream *stream, void *data, int status);
-typedef void (*stream_close_cb)(Stream *stream, void *data);
-
-struct stream {
- bool closed;
- bool did_eof;
- union {
- uv_pipe_t pipe;
- uv_tcp_t tcp;
- uv_idle_t idle;
-#ifdef MSWIN
- uv_tty_t tty;
-#endif
- } uv;
- uv_stream_t *uvstream;
- uv_buf_t uvbuf;
- RBuffer *buffer;
- uv_file fd;
- stream_read_cb read_cb;
- stream_write_cb write_cb;
- void *cb_data;
- stream_close_cb close_cb, internal_close_cb;
- void *close_cb_data, *internal_data;
- size_t fpos;
- size_t curmem;
- size_t maxmem;
- size_t pending_reqs;
- size_t num_bytes;
- MultiQueue *events;
-};
+#include "nvim/event/defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/stream.h.generated.h"
diff --git a/src/nvim/event/time.c b/src/nvim/event/time.c
index f678f25f3f..861b15f6dd 100644
--- a/src/nvim/event/time.c
+++ b/src/nvim/event/time.c
@@ -1,9 +1,12 @@
+#include <stdbool.h>
#include <stdint.h>
#include <uv.h>
+#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/event/time.h"
-#include "nvim/func_attr.h"
+#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/time.c.generated.h"
@@ -53,7 +56,7 @@ static void time_watcher_cb(uv_timer_t *handle)
// the timer blocked and there already is an unprocessed event waiting
return;
}
- CREATE_EVENT(watcher->events, time_event, 1, watcher);
+ CREATE_EVENT(watcher->events, time_event, watcher);
}
static void close_event(void **argv)
@@ -67,6 +70,6 @@ static void close_cb(uv_handle_t *handle)
{
TimeWatcher *watcher = handle->data;
if (watcher->close_cb) {
- CREATE_EVENT(watcher->events, close_event, 1, watcher);
+ CREATE_EVENT(watcher->events, close_event, watcher);
}
}
diff --git a/src/nvim/event/time.h b/src/nvim/event/time.h
index 3514566901..d1f92a3c0e 100644
--- a/src/nvim/event/time.h
+++ b/src/nvim/event/time.h
@@ -1,23 +1,7 @@
#pragma once
-#include <stdbool.h>
-#include <uv.h>
-
-#include "nvim/event/loop.h"
-#include "nvim/event/multiqueue.h"
-
-struct time_watcher;
-
-typedef struct time_watcher TimeWatcher;
-typedef void (*time_cb)(TimeWatcher *watcher, void *data);
-
-struct time_watcher {
- uv_timer_t uv;
- void *data;
- time_cb cb, close_cb;
- MultiQueue *events;
- bool blockable;
-};
+#include "nvim/event/defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/time.h.generated.h"
diff --git a/src/nvim/event/wstream.c b/src/nvim/event/wstream.c
index e8f757874b..406ff1620d 100644
--- a/src/nvim/event/wstream.c
+++ b/src/nvim/event/wstream.c
@@ -1,13 +1,14 @@
#include <assert.h>
#include <stdbool.h>
+#include <stddef.h>
#include <uv.h>
-#include "nvim/event/loop.h"
+#include "nvim/event/defs.h"
#include "nvim/event/stream.h"
#include "nvim/event/wstream.h"
-#include "nvim/func_attr.h"
#include "nvim/macros_defs.h"
#include "nvim/memory.h"
+#include "nvim/types_defs.h"
#define DEFAULT_MAXMEM 1024 * 1024 * 2000
diff --git a/src/nvim/event/wstream.h b/src/nvim/event/wstream.h
index 4cba7bde8f..a431f940d2 100644
--- a/src/nvim/event/wstream.h
+++ b/src/nvim/event/wstream.h
@@ -1,23 +1,7 @@
#pragma once
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <uv.h>
-
-#include "nvim/event/loop.h"
-#include "nvim/event/stream.h"
-
-struct wbuffer;
-
-typedef struct wbuffer WBuffer;
-typedef void (*wbuffer_data_finalizer)(void *data);
-
-struct wbuffer {
- size_t size, refcount;
- char *data;
- wbuffer_data_finalizer cb;
-};
+#include "nvim/event/defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "event/wstream.h.generated.h"
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index e369397047..74ad8e95a2 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -18,6 +18,7 @@
#include "nvim/arglist.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
@@ -25,6 +26,7 @@
#include "nvim/change.h"
#include "nvim/channel.h"
#include "nvim/charset.h"
+#include "nvim/cmdexpand_defs.h"
#include "nvim/cmdhist.h"
#include "nvim/cursor.h"
#include "nvim/decoration.h"
@@ -34,6 +36,7 @@
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_cmds_defs.h"
@@ -41,22 +44,25 @@
#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
#include "nvim/extmark.h"
+#include "nvim/extmark_defs.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/help.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/input.h"
#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
@@ -64,11 +70,14 @@
#include "nvim/normal.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/shell.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
@@ -77,6 +86,7 @@
#include "nvim/profile.h"
#include "nvim/quickfix.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/search.h"
#include "nvim/spell.h"
#include "nvim/state_defs.h"
@@ -84,6 +94,7 @@
#include "nvim/terminal.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -284,12 +295,12 @@ void ex_align(exarg_T *eap)
// to the right.
if (has_tab) {
while (new_indent > 0) {
- (void)set_indent(new_indent, 0);
+ set_indent(new_indent, 0);
if (linelen(NULL) <= width) {
// Now try to move the line as much as possible to
// the right. Stop when it moves too far.
do {
- (void)set_indent(++new_indent, 0);
+ set_indent(++new_indent, 0);
} while (linelen(NULL) <= width);
new_indent--;
break;
@@ -302,7 +313,7 @@ void ex_align(exarg_T *eap)
if (new_indent < 0) {
new_indent = 0;
}
- (void)set_indent(new_indent, 0); // set indent
+ set_indent(new_indent, 0); // set indent
}
changed_lines(curbuf, eap->line1, 0, eap->line2 + 1, 0, true);
curwin->w_cursor = save_curpos;
@@ -342,13 +353,13 @@ static int linelen(int *has_tab)
static char *sortbuf1;
static char *sortbuf2;
-static int sort_lc; ///< sort using locale
-static int sort_ic; ///< ignore case
-static int sort_nr; ///< sort on number
-static int sort_rx; ///< sort on regex instead of skipping it
-static int sort_flt; ///< sort on floating number
+static bool sort_lc; ///< sort using locale
+static bool sort_ic; ///< ignore case
+static bool sort_nr; ///< sort on number
+static bool sort_rx; ///< sort on regex instead of skipping it
+static bool sort_flt; ///< sort on floating number
-static int sort_abort; ///< flag to indicate if sorting has been interrupted
+static bool sort_abort; ///< flag to indicate if sorting has been interrupted
/// Struct to store info to be sorted.
typedef struct {
@@ -395,18 +406,16 @@ static int sort_compare(const void *s1, const void *s2)
// number.
if (sort_nr) {
if (l1.st_u.num.is_number != l2.st_u.num.is_number) {
- result = l1.st_u.num.is_number - l2.st_u.num.is_number;
+ result = l1.st_u.num.is_number > l2.st_u.num.is_number ? 1 : -1;
} else {
result = l1.st_u.num.value == l2.st_u.num.value
? 0
- : l1.st_u.num.value > l2.st_u.num.value
- ? 1
- : -1;
+ : l1.st_u.num.value > l2.st_u.num.value ? 1 : -1;
}
} else if (sort_flt) {
result = l1.st_u.value_flt == l2.st_u.value_flt
- ? 0 : l1.st_u.value_flt > l2.st_u.value_flt
- ? 1 : -1;
+ ? 0
+ : l1.st_u.value_flt > l2.st_u.value_flt ? 1 : -1;
} else {
// We need to copy one line into "sortbuf1", because there is no
// guarantee that the first pointer becomes invalid when obtaining the
@@ -451,7 +460,7 @@ void ex_sort(exarg_T *eap)
regmatch.regprog = NULL;
sorti_T *nrs = xmalloc(count * sizeof(sorti_T));
- sort_abort = sort_ic = sort_lc = sort_rx = sort_nr = sort_flt = 0;
+ sort_abort = sort_ic = sort_lc = sort_rx = sort_nr = sort_flt = false;
size_t format_found = 0;
bool change_occurred = false; // Buffer contents changed.
@@ -465,10 +474,10 @@ void ex_sort(exarg_T *eap)
} else if (*p == 'r') {
sort_rx = true;
} else if (*p == 'n') {
- sort_nr = 1;
+ sort_nr = true;
format_found++;
} else if (*p == 'f') {
- sort_flt = 1;
+ sort_flt = true;
format_found++;
} else if (*p == 'b') {
sort_what = STR2NR_BIN + STR2NR_FORCE;
@@ -522,7 +531,7 @@ void ex_sort(exarg_T *eap)
// From here on "sort_nr" is used as a flag for any integer number
// sorting.
- sort_nr += sort_what;
+ sort_nr |= sort_what;
// Make an array with all line numbers. This avoids having to copy all
// the lines into allocated memory.
@@ -619,7 +628,8 @@ void ex_sort(exarg_T *eap)
goto sortend;
}
- bcount_t old_count = 0, new_count = 0;
+ bcount_t old_count = 0;
+ bcount_t new_count = 0;
// Insert the lines in the sorted order below the last one.
linenr_T lnum = eap->line2;
@@ -1305,7 +1315,7 @@ void do_shell(char *cmd, int flags)
// This ui_cursor_goto is required for when the '\n' resulted in a "delete line
// 1" command to the terminal.
ui_cursor_goto(msg_row, msg_col);
- (void)call_shell(cmd, (ShellOpts)flags, NULL);
+ call_shell(cmd, (ShellOpts)flags, NULL);
if (msg_silent == 0) {
msg_didout = true;
}
@@ -1462,7 +1472,7 @@ void append_redir(char *const buf, const size_t buflen, const char *const opt,
}
}
-void print_line_no_prefix(linenr_T lnum, int use_number, int list)
+void print_line_no_prefix(linenr_T lnum, int use_number, bool list)
{
char numbuf[30];
@@ -1475,9 +1485,9 @@ void print_line_no_prefix(linenr_T lnum, int use_number, int list)
}
/// Print a text line. Also in silent mode ("ex -s").
-void print_line(linenr_T lnum, int use_number, int list)
+void print_line(linenr_T lnum, int use_number, bool list)
{
- int save_silent = silent_mode;
+ bool save_silent = silent_mode;
// apply :filter /pat/
if (message_filtered(ml_get(lnum))) {
@@ -1486,7 +1496,7 @@ void print_line(linenr_T lnum, int use_number, int list)
msg_start();
silent_mode = false;
- info_message = true; // use os_msg(), not os_errmsg()
+ info_message = true; // use stdout, not stderr
print_line_no_prefix(lnum, use_number, list);
if (save_silent) {
msg_putchar('\n');
@@ -1566,7 +1576,7 @@ void ex_file(exarg_T *eap)
void ex_update(exarg_T *eap)
{
if (curbufIsChanged()) {
- (void)do_write(eap);
+ do_write(eap);
}
}
@@ -1582,7 +1592,7 @@ void ex_write(exarg_T *eap)
if (eap->usefilter) { // input lines to shell command
do_bang(1, eap, false, true, false);
} else {
- (void)do_write(eap);
+ do_write(eap);
}
}
@@ -1605,7 +1615,7 @@ static int check_writable(const char *fname)
/// @return FAIL for failure, OK otherwise.
int do_write(exarg_T *eap)
{
- int other;
+ bool other;
char *fname = NULL; // init to shut up gcc
int retval = FAIL;
char *free_fname = NULL;
@@ -1724,7 +1734,7 @@ int do_write(exarg_T *eap)
// If 'filetype' was empty try detecting it now.
if (*curbuf->b_p_ft == NUL) {
if (augroup_exists("filetypedetect")) {
- (void)do_doautocmd("filetypedetect BufRead", true, NULL);
+ do_doautocmd("filetypedetect BufRead", true, NULL);
}
do_modelines(0);
}
@@ -1774,7 +1784,7 @@ theend:
/// @param other writing under other name
///
/// @return OK if it's OK, FAIL if it is not.
-int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int other)
+int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, bool other)
{
// Write to another file or b_flags set or not writing the whole file:
// overwriting only allowed with '!'
@@ -1815,8 +1825,6 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
// For ":w! filename" check that no swap file exists for "filename".
if (other && !emsg_silent) {
char *dir;
- char *p;
- char *swapname;
// We only try the first entry in 'directory', without checking if
// it's writable. If the "." directory is not writable the write
@@ -1828,10 +1836,10 @@ int check_overwrite(exarg_T *eap, buf_T *buf, char *fname, char *ffname, int oth
STRCPY(dir, ".");
} else {
dir = xmalloc(MAXPATHL);
- p = p_dir;
+ char *p = p_dir;
copy_option_part(&p, dir, MAXPATHL, ",");
}
- swapname = makeswapname(fname, ffname, curbuf, dir);
+ char *swapname = makeswapname(fname, ffname, curbuf, dir);
xfree(dir);
if (os_path_exists(swapname)) {
if (p_confirm || (cmdmod.cmod_flags & CMOD_CONFIRM)) {
@@ -1998,11 +2006,11 @@ static int check_readonly(int *forceit, buf_T *buf)
/// GETFILE_NOT_WRITTEN for "not written" error,
/// GETFILE_SAME_FILE for success
/// GETFILE_OPEN_OTHER for successfully opening another file.
-int getfile(int fnum, char *ffname_arg, char *sfname_arg, int setpm, linenr_T lnum, int forceit)
+int getfile(int fnum, char *ffname_arg, char *sfname_arg, bool setpm, linenr_T lnum, bool forceit)
{
char *ffname = ffname_arg;
char *sfname = sfname_arg;
- int other;
+ bool other;
int retval;
char *free_me = NULL;
@@ -2179,7 +2187,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
| ((flags & ECMD_FORCEIT) ? CCGD_FORCEIT : 0)
| (eap == NULL ? 0 : CCGD_EXCMD))) {
if (fnum == 0 && other_file && ffname != NULL) {
- (void)setaltfname(ffname, sfname, newlnum < 0 ? 0 : newlnum);
+ setaltfname(ffname, sfname, newlnum < 0 ? 0 : newlnum);
}
goto theend;
}
@@ -2270,7 +2278,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// Existing memfile.
oldbuf = true;
set_bufref(&bufref, buf);
- (void)buf_check_timestamp(buf);
+ buf_check_timestamp(buf);
// Check if autocommands made buffer invalid or changed the current
// buffer.
if (!bufref_valid(&bufref) || curbuf != old_curbuf.br_buf) {
@@ -2295,10 +2303,19 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// If the current buffer was empty and has no file name, curbuf
// is returned by buflist_new(), nothing to do here.
if (buf != curbuf) {
+ // Should only be possible to get here if the cmdwin is closed, or
+ // if it's opening and its buffer hasn't been set yet (the new
+ // buffer is for it).
+ assert(cmdwin_buf == NULL);
+
const int save_cmdwin_type = cmdwin_type;
+ win_T *const save_cmdwin_win = cmdwin_win;
+ win_T *const save_cmdwin_old_curwin = cmdwin_old_curwin;
// BufLeave applies to the old buffer.
cmdwin_type = 0;
+ cmdwin_win = NULL;
+ cmdwin_old_curwin = NULL;
// Be careful: The autocommands may delete any buffer and change
// the current buffer.
@@ -2314,7 +2331,11 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
const bufref_T save_au_new_curbuf = au_new_curbuf;
set_bufref(&au_new_curbuf, buf);
apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, false, curbuf);
+
cmdwin_type = save_cmdwin_type;
+ cmdwin_win = save_cmdwin_win;
+ cmdwin_old_curwin = save_cmdwin_old_curwin;
+
if (!bufref_valid(&au_new_curbuf)) {
// New buffer has been deleted.
delbuf_msg(new_name); // Frees new_name.
@@ -2606,7 +2627,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
// If the window options were changed may need to set the spell language.
// Can only do this after the buffer has been properly setup.
if (did_get_winopts && curwin->w_p_spell && *curwin->w_s->b_p_spl != NUL) {
- (void)parse_spelllang(curwin);
+ parse_spelllang(curwin);
}
if (command == NULL) {
@@ -2669,7 +2690,7 @@ int do_ecmd(int fnum, char *ffname, char *sfname, exarg_T *eap, linenr_T newlnum
}
if (curbuf->b_kmap_state & KEYMAP_INIT) {
- (void)keymap_init();
+ keymap_init();
}
RedrawingDisabled--;
@@ -2722,7 +2743,7 @@ void ex_append(exarg_T *eap)
linenr_T lnum = eap->line2;
int indent = 0;
char *p;
- int empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
+ bool empty = (curbuf->b_ml.ml_flags & ML_EMPTY);
// the ! flag toggles autoindent
if (eap->forceit) {
@@ -2824,7 +2845,7 @@ void ex_append(exarg_T *eap)
if (empty) {
ml_delete(2, false);
- empty = 0;
+ empty = false;
}
}
State = MODE_NORMAL;
@@ -3144,7 +3165,7 @@ static char *sub_grow_buf(char **new_start, int *new_start_len, int needed_len)
// substitution into (and some extra space to avoid
// too many calls to xmalloc()/free()).
*new_start_len = needed_len + 50;
- *new_start = xmalloc((size_t)(*new_start_len));
+ *new_start = xcalloc(1, (size_t)(*new_start_len));
**new_start = NUL;
new_end = *new_start;
} else {
@@ -3154,8 +3175,11 @@ static char *sub_grow_buf(char **new_start, int *new_start_len, int needed_len)
size_t len = strlen(*new_start);
needed_len += (int)len;
if (needed_len > *new_start_len) {
+ size_t prev_new_start_len = (size_t)(*new_start_len);
*new_start_len = needed_len + 50;
+ size_t added_len = (size_t)(*new_start_len) - prev_new_start_len;
*new_start = xrealloc(*new_start, (size_t)(*new_start_len));
+ memset(*new_start + prev_new_start_len, 0, added_len);
}
new_end = *new_start + len;
}
@@ -3261,7 +3285,7 @@ static int check_regexp_delim(int c)
///
/// @param cmdpreview_ns The namespace to show 'inccommand' preview highlights.
/// If <= 0, preview shouldn't be shown.
-/// @return 0, 1 or 2. See show_cmdpreview() for more information on what the return value means.
+/// @return 0, 1 or 2. See cmdpreview_may_show() for more information on the meaning.
static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_ns,
const handle_T cmdpreview_bufnr)
{
@@ -3301,7 +3325,8 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
.do_number = false,
.do_ic = kSubHonorOptions
};
- char *pat = NULL, *sub = NULL; // init for GCC
+ char *pat = NULL;
+ char *sub = NULL; // init for GCC
int delimiter;
bool has_second_delim = false;
int sublen;
@@ -3499,7 +3524,8 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
colnr_T copycol;
colnr_T matchcol;
colnr_T prev_matchcol = MAXCOL;
- char *new_end, *new_start = NULL;
+ char *new_end;
+ char *new_start = NULL;
int new_start_len = 0;
char *p1;
bool did_sub = false;
@@ -3949,11 +3975,11 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
current_match.start.col = start_col;
textlock++;
- (void)vim_regsub_multi(&regmatch,
- sub_firstlnum - regmatch.startpos[0].lnum,
- sub, new_end, sublen,
- REGSUB_COPY | REGSUB_BACKSLASH
- | (magic_isset() ? REGSUB_MAGIC : 0));
+ vim_regsub_multi(&regmatch,
+ sub_firstlnum - regmatch.startpos[0].lnum,
+ sub, new_end, sublen,
+ REGSUB_COPY | REGSUB_BACKSLASH
+ | (magic_isset() ? REGSUB_MAGIC : 0));
textlock--;
sub_nsubs++;
did_sub = true;
@@ -3969,7 +3995,8 @@ static int do_sub(exarg_T *eap, const proftime_T timeout, const int cmdpreview_n
// TODO(bfredl): this has some robustness issues, look into later.
bcount_t replaced_bytes = 0;
- lpos_T start = regmatch.startpos[0], end = regmatch.endpos[0];
+ lpos_T start = regmatch.startpos[0];
+ lpos_T end = regmatch.endpos[0];
for (i = 0; i < nmatch - 1; i++) {
replaced_bytes += (bcount_t)strlen(ml_get((linenr_T)(lnum_start + i))) + 1;
}
@@ -4262,7 +4289,7 @@ skip:
// Show 'inccommand' preview if there are matched lines.
if (cmdpreview_ns > 0 && !aborting()) {
if (got_quit || profile_passed_limit(timeout)) { // Too slow, disable.
- set_string_option_direct("icm", -1, "", OPT_FREE, SID_NONE);
+ set_string_option_direct(kOptInccommand, "", 0, SID_NONE);
} else if (*p_icm != NUL && pat != NULL) {
if (pre_hl_id == 0) {
pre_hl_id = syn_check_group(S_LEN("Substitute"));
@@ -4541,8 +4568,8 @@ bool prepare_tagpreview(bool undo_sync)
curwin->w_p_wfh = true;
RESET_BINDING(curwin); // don't take over 'scrollbind' and 'cursorbind'
curwin->w_p_diff = false; // no 'diff'
- set_string_option_direct("fdc", -1, // no 'foldcolumn'
- "0", OPT_FREE, SID_NONE);
+
+ set_string_option_direct(kOptFoldcolumn, "0", 0, SID_NONE); // no 'foldcolumn'
return true;
}
@@ -4561,10 +4588,7 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i
buf_T *cmdpreview_buf = NULL;
// disable file info message
- set_string_option_direct("shm", -1, "F", OPT_FREE, SID_NONE);
-
- // Update the topline to ensure that main window is on the correct line
- update_topline(curwin);
+ set_string_option_direct(kOptShortmess, "F", 0, SID_NONE);
// Place cursor on nearest matching line, to undo do_sub() cursor placement.
for (size_t i = 0; i < lines.subresults.size; i++) {
@@ -4576,8 +4600,10 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i
} // Else: All matches are above, do_sub() already placed cursor.
}
+ // Update the topline to ensure that main window is on the correct line
+ update_topline(curwin);
+
// Width of the "| lnum|..." column which displays the line numbers.
- linenr_T highest_num_line = 0;
int col_width = 0;
// Use preview window only when inccommand=split and range is not just the current line
bool preview = (*p_icm == 's') && (eap->line1 != old_cusr.lnum || eap->line2 != old_cusr.lnum);
@@ -4587,8 +4613,11 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i
assert(cmdpreview_buf != NULL);
if (lines.subresults.size > 0) {
- highest_num_line = kv_last(lines.subresults).end.lnum;
- col_width = (int)log10(highest_num_line) + 1 + 3;
+ SubResult last_match = kv_last(lines.subresults);
+ // `last_match.end.lnum` may be 0 when using 'n' flag.
+ linenr_T highest_lnum = MAX(last_match.start.lnum, last_match.end.lnum);
+ assert(highest_lnum > 0);
+ col_width = (int)log10(highest_lnum) + 1 + 3;
}
}
@@ -4645,7 +4674,7 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i
snprintf(str, line_size, "|%*" PRIdLINENR "| %s", col_width - 3,
next_linenr, line);
if (linenr_preview == 0) {
- ml_replace_buf(cmdpreview_buf, 1, str, true);
+ ml_replace_buf(cmdpreview_buf, 1, str, true, false);
} else {
ml_append_buf(cmdpreview_buf, linenr_preview, str, (colnr_T)line_size, false);
}
@@ -4660,7 +4689,7 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i
xfree(str);
- set_string_option_direct("shm", -1, save_shm_p, OPT_FREE, SID_NONE);
+ set_string_option_direct(kOptShortmess, save_shm_p, 0, SID_NONE);
xfree(save_shm_p);
return preview ? 2 : 1;
@@ -4669,7 +4698,7 @@ static int show_sub(exarg_T *eap, pos_T old_cusr, PreviewLines *preview_lines, i
/// :substitute command.
void ex_substitute(exarg_T *eap)
{
- (void)do_sub(eap, profile_zero(), 0, 0);
+ do_sub(eap, profile_zero(), 0, 0);
}
/// :substitute command preview callback.
diff --git a/src/nvim/ex_cmds.h b/src/nvim/ex_cmds.h
index de13f03197..e0894cf7a8 100644
--- a/src/nvim/ex_cmds.h
+++ b/src/nvim/ex_cmds.h
@@ -1,34 +1,24 @@
#pragma once
-#include <stdbool.h>
+#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
-#include "nvim/eval/typval_defs.h"
-#include "nvim/ex_cmds_defs.h" // IWYU pragma: export
-#include "nvim/os/time.h"
-#include "nvim/pos_defs.h" // IWYU pragma: keep
+/// flags for do_ecmd()
+enum {
+ ECMD_HIDE = 0x01, ///< don't free the current buffer
+ ECMD_SET_HELP = 0x02, ///< set b_help flag of (new) buffer before opening file
+ ECMD_OLDBUF = 0x04, ///< use existing buffer if it exists
+ ECMD_FORCEIT = 0x08, ///< ! used in Ex command
+ ECMD_ADDBUF = 0x10, ///< don't edit, just add to buffer list
+ ECMD_ALTBUF = 0x20, ///< like ECMD_ADDBUF and set the alternate file
+ ECMD_NOWINENTER = 0x40, ///< do not trigger BufWinEnter
+};
-// flags for do_ecmd()
-#define ECMD_HIDE 0x01 // don't free the current buffer
-#define ECMD_SET_HELP 0x02 // set b_help flag of (new) buffer before
- // opening file
-#define ECMD_OLDBUF 0x04 // use existing buffer if it exists
-#define ECMD_FORCEIT 0x08 // ! used in Ex command
-#define ECMD_ADDBUF 0x10 // don't edit, just add to buffer list
-#define ECMD_ALTBUF 0x20 // like ECMD_ADDBUF and set the alternate file
-#define ECMD_NOWINENTER 0x40 // do not trigger BufWinEnter
-
-// for lnum argument in do_ecmd()
-#define ECMD_LASTL 0 // use last position in loaded file
-#define ECMD_LAST (-1) // use last position in all files
-#define ECMD_ONE 1 // use first line
-
-/// Previous :substitute replacement string definition
-typedef struct {
- char *sub; ///< Previous replacement string.
- Timestamp timestamp; ///< Time when it was last set.
- list_T *additional_elements; ///< Additional data left from ShaDa file.
-} SubReplacementString;
+/// for lnum argument in do_ecmd()
+enum {
+ ECMD_LASTL = 0, ///< use last position in loaded file
+ ECMD_LAST = -1, ///< use last position in all files
+ ECMD_ONE = 1, ///< use first line
+};
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_cmds.h.generated.h"
diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua
index 4859a70553..1318eda5eb 100644
--- a/src/nvim/ex_cmds.lua
+++ b/src/nvim/ex_cmds.lua
@@ -4,3358 +4,3358 @@ local module = {}
-- Description of the values below is contained in ex_cmds_defs.h file.
-- "EX_" prefix is omitted.
-local RANGE = 0x001
-local BANG = 0x002
-local EXTRA = 0x004
-local XFILE = 0x008
-local NOSPC = 0x010
-local DFLALL = 0x020
-local WHOLEFOLD = 0x040
-local NEEDARG = 0x080
-local TRLBAR = 0x100
-local REGSTR = 0x200
-local COUNT = 0x400
-local NOTRLCOM = 0x800
-local ZEROR = 0x1000
-local CTRLV = 0x2000
-local CMDARG = 0x4000
-local BUFNAME = 0x8000
-local BUFUNL = 0x10000
-local ARGOPT = 0x20000
-local SBOXOK = 0x40000
-local CMDWIN = 0x80000
-local MODIFY = 0x100000
-local FLAGS = 0x200000
-local LOCK_OK = 0x1000000
-local PREVIEW = 0x8000000
-local FILES = bit.bor(XFILE, EXTRA)
-local WORD1 = bit.bor(EXTRA, NOSPC)
-local FILE1 = bit.bor(FILES, NOSPC)
+local RANGE = 0x001
+local BANG = 0x002
+local EXTRA = 0x004
+local XFILE = 0x008
+local NOSPC = 0x010
+local DFLALL = 0x020
+local WHOLEFOLD = 0x040
+local NEEDARG = 0x080
+local TRLBAR = 0x100
+local REGSTR = 0x200
+local COUNT = 0x400
+local NOTRLCOM = 0x800
+local ZEROR = 0x1000
+local CTRLV = 0x2000
+local CMDARG = 0x4000
+local BUFNAME = 0x8000
+local BUFUNL = 0x10000
+local ARGOPT = 0x20000
+local SBOXOK = 0x40000
+local CMDWIN = 0x80000
+local MODIFY = 0x100000
+local FLAGS = 0x200000
+local LOCK_OK = 0x1000000
+local PREVIEW = 0x8000000
+local FILES = bit.bor(XFILE, EXTRA)
+local WORD1 = bit.bor(EXTRA, NOSPC)
+local FILE1 = bit.bor(FILES, NOSPC)
module.flags = {
RANGE = RANGE,
DFLALL = DFLALL,
- PREVIEW = PREVIEW
+ PREVIEW = PREVIEW,
}
-- The following table is described in ex_cmds_defs.h file.
module.cmds = {
{
- command='append',
- flags=bit.bor(BANG, RANGE, ZEROR, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_append',
+ command = 'append',
+ flags = bit.bor(BANG, RANGE, ZEROR, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_append',
},
{
- command='abbreviate',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abbreviate',
+ command = 'abbreviate',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abbreviate',
},
{
- command='abclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abclear',
+ command = 'abclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abclear',
},
{
- command='aboveleft',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'aboveleft',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='all',
- flags=bit.bor(BANG, RANGE, COUNT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_all',
+ command = 'all',
+ flags = bit.bor(BANG, RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_all',
},
{
- command='amenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'amenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='anoremenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'anoremenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='args',
- flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_args',
+ command = 'args',
+ flags = bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_args',
},
{
- command='argadd',
- flags=bit.bor(BANG, RANGE, ZEROR, FILES, TRLBAR),
- addr_type='ADDR_ARGUMENTS',
- func='ex_argadd',
+ command = 'argadd',
+ flags = bit.bor(BANG, RANGE, ZEROR, FILES, TRLBAR),
+ addr_type = 'ADDR_ARGUMENTS',
+ func = 'ex_argadd',
},
{
- command='argdelete',
- flags=bit.bor(BANG, RANGE, FILES, TRLBAR),
- addr_type='ADDR_ARGUMENTS',
- func='ex_argdelete',
+ command = 'argdelete',
+ flags = bit.bor(BANG, RANGE, FILES, TRLBAR),
+ addr_type = 'ADDR_ARGUMENTS',
+ func = 'ex_argdelete',
},
{
- command='argdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
- addr_type='ADDR_ARGUMENTS',
- func='ex_listdo',
+ command = 'argdo',
+ flags = bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type = 'ADDR_ARGUMENTS',
+ func = 'ex_listdo',
},
{
- command='argdedupe',
- flags=TRLBAR,
- addr_type='ADDR_NONE',
- func='ex_argdedupe',
+ command = 'argdedupe',
+ flags = TRLBAR,
+ addr_type = 'ADDR_NONE',
+ func = 'ex_argdedupe',
},
{
- command='argedit',
- flags=bit.bor(BANG, NEEDARG, RANGE, ZEROR, FILES, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_ARGUMENTS',
- func='ex_argedit',
+ command = 'argedit',
+ flags = bit.bor(BANG, NEEDARG, RANGE, ZEROR, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_ARGUMENTS',
+ func = 'ex_argedit',
},
{
- command='argglobal',
- flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_args',
+ command = 'argglobal',
+ flags = bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_args',
},
{
- command='arglocal',
- flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_args',
+ command = 'arglocal',
+ flags = bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_args',
},
{
- command='argument',
- flags=bit.bor(BANG, RANGE, COUNT, EXTRA, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_ARGUMENTS',
- func='ex_argument',
+ command = 'argument',
+ flags = bit.bor(BANG, RANGE, COUNT, EXTRA, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_ARGUMENTS',
+ func = 'ex_argument',
},
{
- command='ascii',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='do_ascii',
+ command = 'ascii',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'do_ascii',
},
{
- command='autocmd',
- flags=bit.bor(BANG, EXTRA, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_autocmd',
+ command = 'autocmd',
+ flags = bit.bor(BANG, EXTRA, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_autocmd',
},
{
- command='augroup',
- flags=bit.bor(BANG, WORD1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_autocmd',
+ command = 'augroup',
+ flags = bit.bor(BANG, WORD1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_autocmd',
},
{
- command='aunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_menu',
+ command = 'aunmenu',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_menu',
},
{
- command='buffer',
- flags=bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, CMDARG, TRLBAR),
- addr_type='ADDR_BUFFERS',
- func='ex_buffer',
+ command = 'buffer',
+ flags = bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, CMDARG, TRLBAR),
+ addr_type = 'ADDR_BUFFERS',
+ func = 'ex_buffer',
},
{
- command='bNext',
- flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_bprevious',
+ command = 'bNext',
+ flags = bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_bprevious',
},
{
- command='ball',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_buffer_all',
+ command = 'ball',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_buffer_all',
},
{
- command='badd',
- flags=bit.bor(NEEDARG, FILE1, CMDARG, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_edit',
+ command = 'badd',
+ flags = bit.bor(NEEDARG, FILE1, CMDARG, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_edit',
},
{
- command='balt',
- flags=bit.bor(NEEDARG, FILE1, CMDARG, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_edit',
+ command = 'balt',
+ flags = bit.bor(NEEDARG, FILE1, CMDARG, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_edit',
},
{
- command='bdelete',
- flags=bit.bor(BANG, RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
- addr_type='ADDR_BUFFERS',
- func='ex_bunload',
+ command = 'bdelete',
+ flags = bit.bor(BANG, RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
+ addr_type = 'ADDR_BUFFERS',
+ func = 'ex_bunload',
},
{
- command='belowright',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'belowright',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='bfirst',
- flags=bit.bor(BANG, RANGE, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_brewind',
+ command = 'bfirst',
+ flags = bit.bor(BANG, RANGE, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_brewind',
},
{
- command='blast',
- flags=bit.bor(BANG, RANGE, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_blast',
+ command = 'blast',
+ flags = bit.bor(BANG, RANGE, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_blast',
},
{
- command='bmodified',
- flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_bmodified',
+ command = 'bmodified',
+ flags = bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_bmodified',
},
{
- command='bnext',
- flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_bnext',
+ command = 'bnext',
+ flags = bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_bnext',
},
{
- command='botright',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'botright',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='bprevious',
- flags=bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_bprevious',
+ command = 'bprevious',
+ flags = bit.bor(BANG, RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_bprevious',
},
{
- command='brewind',
- flags=bit.bor(BANG, RANGE, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_brewind',
+ command = 'brewind',
+ flags = bit.bor(BANG, RANGE, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_brewind',
},
{
- command='break',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_break',
+ command = 'break',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_break',
},
{
- command='breakadd',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_breakadd',
+ command = 'breakadd',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_breakadd',
},
{
- command='breakdel',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_breakdel',
+ command = 'breakdel',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_breakdel',
},
{
- command='breaklist',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_breaklist',
+ command = 'breaklist',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_breaklist',
},
{
- command='browse',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'browse',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='buffers',
- flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='buflist_list',
+ command = 'buffers',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'buflist_list',
},
{
- command='bufdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
- addr_type='ADDR_BUFFERS',
- func='ex_listdo',
+ command = 'bufdo',
+ flags = bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type = 'ADDR_BUFFERS',
+ func = 'ex_listdo',
},
{
- command='bunload',
- flags=bit.bor(BANG, RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
- addr_type='ADDR_LOADED_BUFFERS',
- func='ex_bunload',
+ command = 'bunload',
+ flags = bit.bor(BANG, RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
+ addr_type = 'ADDR_LOADED_BUFFERS',
+ func = 'ex_bunload',
},
{
- command='bwipeout',
- flags=bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, TRLBAR),
- addr_type='ADDR_BUFFERS',
- func='ex_bunload',
+ command = 'bwipeout',
+ flags = bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, TRLBAR),
+ addr_type = 'ADDR_BUFFERS',
+ func = 'ex_bunload',
},
{
- command='change',
- flags=bit.bor(BANG, WHOLEFOLD, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_change',
+ command = 'change',
+ flags = bit.bor(BANG, WHOLEFOLD, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_change',
},
{
- command='cNext',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cnext',
+ command = 'cNext',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cnext',
},
{
- command='cNfile',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cnext',
+ command = 'cNfile',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cnext',
},
{
- command='cabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abbreviate',
+ command = 'cabbrev',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abbreviate',
},
{
- command='cabclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abclear',
+ command = 'cabclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abclear',
},
{
- command='cabove',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='ex_cbelow',
+ command = 'cabove',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cbelow',
},
{
- command='caddbuffer',
- flags=bit.bor(RANGE, WORD1, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_cbuffer',
+ command = 'caddbuffer',
+ flags = bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_cbuffer',
},
{
- command='caddexpr',
- flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_cexpr',
+ command = 'caddexpr',
+ flags = bit.bor(NEEDARG, WORD1, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cexpr',
},
{
- command='caddfile',
- flags=bit.bor(TRLBAR, FILE1),
- addr_type='ADDR_NONE',
- func='ex_cfile',
+ command = 'caddfile',
+ flags = bit.bor(TRLBAR, FILE1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cfile',
},
{
- command='cafter',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='ex_cbelow',
+ command = 'cafter',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cbelow',
},
{
- command='call',
- flags=bit.bor(RANGE, NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_call',
+ command = 'call',
+ flags = bit.bor(RANGE, NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_call',
},
{
- command='catch',
- flags=bit.bor(EXTRA, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_catch',
+ command = 'catch',
+ flags = bit.bor(EXTRA, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_catch',
},
{
- command='cbuffer',
- flags=bit.bor(BANG, RANGE, WORD1, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_cbuffer',
+ command = 'cbuffer',
+ flags = bit.bor(BANG, RANGE, WORD1, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_cbuffer',
},
{
- command='cbefore',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='ex_cbelow',
+ command = 'cbefore',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cbelow',
},
{
- command='cbelow',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='ex_cbelow',
+ command = 'cbelow',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cbelow',
},
{
- command='cbottom',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_cbottom',
+ command = 'cbottom',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cbottom',
},
{
- command='cc',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_QUICKFIX',
- func='ex_cc',
+ command = 'cc',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_QUICKFIX',
+ func = 'ex_cc',
},
{
- command='cclose',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_cclose',
+ command = 'cclose',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cclose',
},
{
- command='cd',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_cd',
+ command = 'cd',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cd',
},
{
- command='cdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
- addr_type='ADDR_QUICKFIX_VALID',
- func='ex_listdo',
+ command = 'cdo',
+ flags = bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type = 'ADDR_QUICKFIX_VALID',
+ func = 'ex_listdo',
},
{
- command='center',
- flags=bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_align',
+ command = 'center',
+ flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_align',
},
{
- command='cexpr',
- flags=bit.bor(NEEDARG, WORD1, NOTRLCOM, BANG),
- addr_type='ADDR_NONE',
- func='ex_cexpr',
+ command = 'cexpr',
+ flags = bit.bor(NEEDARG, WORD1, NOTRLCOM, BANG),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cexpr',
},
{
- command='cfile',
- flags=bit.bor(TRLBAR, FILE1, BANG),
- addr_type='ADDR_NONE',
- func='ex_cfile',
+ command = 'cfile',
+ flags = bit.bor(TRLBAR, FILE1, BANG),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cfile',
},
-- Even though 'cfdo' is alphabetically lower than 'cfile', it is after
-- 'cfile' in this cmd list to support the existing ":cf" abbreviation.
{
- command='cfdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
- addr_type='ADDR_QUICKFIX_VALID',
- func='ex_listdo',
+ command = 'cfdo',
+ flags = bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type = 'ADDR_QUICKFIX_VALID',
+ func = 'ex_listdo',
},
{
- command='cfirst',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cc',
+ command = 'cfirst',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cc',
},
{
- command='cgetfile',
- flags=bit.bor(TRLBAR, FILE1),
- addr_type='ADDR_NONE',
- func='ex_cfile',
+ command = 'cgetfile',
+ flags = bit.bor(TRLBAR, FILE1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cfile',
},
{
- command='cgetbuffer',
- flags=bit.bor(RANGE, WORD1, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_cbuffer',
+ command = 'cgetbuffer',
+ flags = bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_cbuffer',
},
{
- command='cgetexpr',
- flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_cexpr',
+ command = 'cgetexpr',
+ flags = bit.bor(NEEDARG, WORD1, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cexpr',
},
{
- command='chdir',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_cd',
+ command = 'chdir',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cd',
},
{
- command='changes',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_changes',
+ command = 'changes',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_changes',
},
{
- command='checkhealth',
- flags=bit.bor(EXTRA, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_checkhealth',
+ command = 'checkhealth',
+ flags = bit.bor(EXTRA, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_checkhealth',
},
{
- command='checkpath',
- flags=bit.bor(TRLBAR, BANG, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_checkpath',
+ command = 'checkpath',
+ flags = bit.bor(TRLBAR, BANG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_checkpath',
},
{
- command='checktime',
- flags=bit.bor(RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_checktime',
+ command = 'checktime',
+ flags = bit.bor(RANGE, BUFNAME, COUNT, EXTRA, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_checktime',
},
{
- command='chistory',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='qf_history',
+ command = 'chistory',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'qf_history',
},
{
- command='clist',
- flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='qf_list',
+ command = 'clist',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'qf_list',
},
{
- command='clast',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cc',
+ command = 'clast',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cc',
},
{
- command='close',
- flags=bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_WINDOWS',
- func='ex_close',
+ command = 'close',
+ flags = bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_WINDOWS',
+ func = 'ex_close',
},
{
- command='clearjumps',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_clearjumps',
+ command = 'clearjumps',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_clearjumps',
},
{
- command='cmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'cmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='cmapclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mapclear',
+ command = 'cmapclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mapclear',
},
{
- command='cmenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'cmenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='cnext',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cnext',
+ command = 'cnext',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cnext',
},
{
- command='cnewer',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='qf_age',
+ command = 'cnewer',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'qf_age',
},
{
- command='cnfile',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cnext',
+ command = 'cnfile',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cnext',
},
{
- command='cnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'cnoremap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='cnoreabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abbreviate',
+ command = 'cnoreabbrev',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abbreviate',
},
{
- command='cnoremenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'cnoremenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='copy',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_copymove',
+ command = 'copy',
+ flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_copymove',
},
{
- command='colder',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='qf_age',
+ command = 'colder',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'qf_age',
},
{
- command='colorscheme',
- flags=bit.bor(WORD1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_colorscheme',
+ command = 'colorscheme',
+ flags = bit.bor(WORD1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_colorscheme',
},
{
- command='command',
- flags=bit.bor(EXTRA, BANG, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_command',
+ command = 'command',
+ flags = bit.bor(EXTRA, BANG, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_command',
},
{
- command='comclear',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_comclear',
+ command = 'comclear',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_comclear',
},
{
- command='compiler',
- flags=bit.bor(BANG, TRLBAR, WORD1, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_compiler',
+ command = 'compiler',
+ flags = bit.bor(BANG, TRLBAR, WORD1, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_compiler',
},
{
- command='continue',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_continue',
+ command = 'continue',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_continue',
},
{
- command='confirm',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'confirm',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='const',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_let',
+ command = 'const',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_let',
},
{
- command='copen',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_copen',
+ command = 'copen',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_copen',
},
{
- command='cprevious',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cnext',
+ command = 'cprevious',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cnext',
},
{
- command='cpfile',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_OTHER',
- func='ex_cnext',
+ command = 'cpfile',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_cnext',
},
{
- command='cquit',
- flags=bit.bor(RANGE, COUNT, ZEROR, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cquit',
+ command = 'cquit',
+ flags = bit.bor(RANGE, COUNT, ZEROR, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cquit',
},
{
- command='crewind',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cc',
+ command = 'crewind',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cc',
},
{
- command='cunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_unmap',
+ command = 'cunmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_unmap',
},
{
- command='cunabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abbreviate',
+ command = 'cunabbrev',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abbreviate',
},
{
- command='cunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_menu',
+ command = 'cunmenu',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_menu',
},
{
- command='cwindow',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_cwindow',
+ command = 'cwindow',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_cwindow',
},
{
- command='delete',
- flags=bit.bor(RANGE, WHOLEFOLD, REGSTR, COUNT, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_operators',
+ command = 'delete',
+ flags = bit.bor(RANGE, WHOLEFOLD, REGSTR, COUNT, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_operators',
},
{
- command='delmarks',
- flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_delmarks',
+ command = 'delmarks',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_delmarks',
},
{
- command='debug',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_debug',
+ command = 'debug',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_debug',
},
{
- command='debuggreedy',
- flags=bit.bor(RANGE, ZEROR, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_debuggreedy',
+ command = 'debuggreedy',
+ flags = bit.bor(RANGE, ZEROR, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_debuggreedy',
},
{
- command='defer',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_call',
+ command = 'defer',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_call',
},
{
- command='delcommand',
- flags=bit.bor(BANG, NEEDARG, WORD1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_delcommand',
+ command = 'delcommand',
+ flags = bit.bor(BANG, NEEDARG, WORD1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_delcommand',
},
{
- command='delfunction',
- flags=bit.bor(BANG, NEEDARG, WORD1, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_delfunction',
+ command = 'delfunction',
+ flags = bit.bor(BANG, NEEDARG, WORD1, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_delfunction',
},
{
- command='display',
- flags=bit.bor(EXTRA, NOTRLCOM, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_display',
+ command = 'display',
+ flags = bit.bor(EXTRA, NOTRLCOM, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_display',
},
{
- command='diffupdate',
- flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_diffupdate',
+ command = 'diffupdate',
+ flags = bit.bor(BANG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_diffupdate',
},
{
- command='diffget',
- flags=bit.bor(RANGE, EXTRA, TRLBAR, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_diffgetput',
+ command = 'diffget',
+ flags = bit.bor(RANGE, EXTRA, TRLBAR, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_diffgetput',
},
{
- command='diffoff',
- flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_diffoff',
+ command = 'diffoff',
+ flags = bit.bor(BANG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_diffoff',
},
{
- command='diffpatch',
- flags=bit.bor(EXTRA, FILE1, TRLBAR, MODIFY),
- addr_type='ADDR_NONE',
- func='ex_diffpatch',
+ command = 'diffpatch',
+ flags = bit.bor(EXTRA, FILE1, TRLBAR, MODIFY),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_diffpatch',
},
{
- command='diffput',
- flags=bit.bor(RANGE, EXTRA, TRLBAR),
- addr_type='ADDR_LINES',
- func='ex_diffgetput',
+ command = 'diffput',
+ flags = bit.bor(RANGE, EXTRA, TRLBAR),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_diffgetput',
},
{
- command='diffsplit',
- flags=bit.bor(EXTRA, FILE1, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_diffsplit',
+ command = 'diffsplit',
+ flags = bit.bor(EXTRA, FILE1, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_diffsplit',
},
{
- command='diffthis',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_diffthis',
+ command = 'diffthis',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_diffthis',
},
{
- command='digraphs',
- flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_digraphs',
+ command = 'digraphs',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_digraphs',
},
{
- command='djump',
- flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
- addr_type='ADDR_LINES',
- func='ex_findpat',
+ command = 'djump',
+ flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_findpat',
},
{
- command='dlist',
- flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_findpat',
+ command = 'dlist',
+ flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_findpat',
},
{
- command='doautocmd',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_doautocmd',
+ command = 'doautocmd',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_doautocmd',
},
{
- command='doautoall',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_doautoall',
+ command = 'doautoall',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_doautoall',
},
{
- command='drop',
- flags=bit.bor(FILES, CMDARG, NEEDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_drop',
+ command = 'drop',
+ flags = bit.bor(FILES, CMDARG, NEEDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_drop',
},
{
- command='dsearch',
- flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_findpat',
+ command = 'dsearch',
+ flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_findpat',
},
{
- command='dsplit',
- flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
- addr_type='ADDR_LINES',
- func='ex_findpat',
+ command = 'dsplit',
+ flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_findpat',
},
{
- command='edit',
- flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_edit',
+ command = 'edit',
+ flags = bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_edit',
},
{
- command='earlier',
- flags=bit.bor(TRLBAR, EXTRA, NOSPC, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_later',
+ command = 'earlier',
+ flags = bit.bor(TRLBAR, EXTRA, NOSPC, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_later',
},
{
- command='echo',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_echo',
+ command = 'echo',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_echo',
},
{
- command='echoerr',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_execute',
+ command = 'echoerr',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_execute',
},
{
- command='echohl',
- flags=bit.bor(EXTRA, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_echohl',
+ command = 'echohl',
+ flags = bit.bor(EXTRA, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_echohl',
},
{
- command='echomsg',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_execute',
+ command = 'echomsg',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_execute',
},
{
- command='echon',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_echo',
+ command = 'echon',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_echo',
},
{
- command='else',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_else',
+ command = 'else',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_else',
},
{
- command='elseif',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_else',
+ command = 'elseif',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_else',
},
{
- command='emenu',
- flags=bit.bor(NEEDARG, EXTRA, TRLBAR, NOTRLCOM, RANGE, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_emenu',
+ command = 'emenu',
+ flags = bit.bor(NEEDARG, EXTRA, TRLBAR, NOTRLCOM, RANGE, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_emenu',
},
{
- command='endif',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_endif',
+ command = 'endif',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_endif',
},
{
- command='endfunction',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_endfunction',
+ command = 'endfunction',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_endfunction',
},
{
- command='endfor',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_endwhile',
+ command = 'endfor',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_endwhile',
},
{
- command='endtry',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_endtry',
+ command = 'endtry',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_endtry',
},
{
- command='endwhile',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_endwhile',
+ command = 'endwhile',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_endwhile',
},
{
- command='enew',
- flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_edit',
+ command = 'enew',
+ flags = bit.bor(BANG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_edit',
},
{
- command='eval',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_eval',
+ command = 'eval',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_eval',
},
{
- command='ex',
- flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_edit',
+ command = 'ex',
+ flags = bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_edit',
},
{
- command='execute',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_execute',
+ command = 'execute',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_execute',
},
{
- command='exit',
- flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_exit',
+ command = 'exit',
+ flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_exit',
},
{
- command='exusage',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_exusage',
+ command = 'exusage',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_exusage',
},
{
- command='file',
- flags=bit.bor(RANGE, ZEROR, BANG, FILE1, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_file',
+ command = 'file',
+ flags = bit.bor(RANGE, ZEROR, BANG, FILE1, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_file',
},
{
- command='files',
- flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='buflist_list',
+ command = 'files',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'buflist_list',
},
{
- command='filetype',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_filetype',
+ command = 'filetype',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_filetype',
},
{
- command='filter',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'filter',
+ flags = bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='find',
- flags=bit.bor(RANGE, BANG, FILE1, CMDARG, ARGOPT, TRLBAR, NEEDARG),
- addr_type='ADDR_OTHER',
- func='ex_find',
+ command = 'find',
+ flags = bit.bor(RANGE, BANG, FILE1, CMDARG, ARGOPT, TRLBAR, NEEDARG),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_find',
},
{
- command='finally',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_finally',
+ command = 'finally',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_finally',
},
{
- command='finish',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_finish',
+ command = 'finish',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_finish',
},
{
- command='first',
- flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_rewind',
+ command = 'first',
+ flags = bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_rewind',
},
{
- command='fold',
- flags=bit.bor(RANGE, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_fold',
+ command = 'fold',
+ flags = bit.bor(RANGE, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_fold',
},
{
- command='foldclose',
- flags=bit.bor(RANGE, BANG, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_foldopen',
+ command = 'foldclose',
+ flags = bit.bor(RANGE, BANG, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_foldopen',
},
{
- command='folddoopen',
- flags=bit.bor(RANGE, DFLALL, NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
- func='ex_folddo',
+ command = 'folddoopen',
+ flags = bit.bor(RANGE, DFLALL, NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_folddo',
},
{
- command='folddoclosed',
- flags=bit.bor(RANGE, DFLALL, NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_LINES',
- func='ex_folddo',
+ command = 'folddoclosed',
+ flags = bit.bor(RANGE, DFLALL, NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_folddo',
},
{
- command='foldopen',
- flags=bit.bor(RANGE, BANG, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_foldopen',
+ command = 'foldopen',
+ flags = bit.bor(RANGE, BANG, WHOLEFOLD, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_foldopen',
},
{
- command='for',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_while',
+ command = 'for',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_while',
},
{
- command='function',
- flags=bit.bor(EXTRA, BANG, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_function',
+ command = 'function',
+ flags = bit.bor(EXTRA, BANG, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_function',
},
{
- command='fclose',
- flags=bit.bor(BANG, RANGE),
- addr_type='ADDR_OTHER',
- func='ex_fclose',
+ command = 'fclose',
+ flags = bit.bor(BANG, RANGE),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_fclose',
},
{
- command='global',
- flags=bit.bor(RANGE, WHOLEFOLD, BANG, EXTRA, DFLALL, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_global',
+ command = 'global',
+ flags = bit.bor(RANGE, WHOLEFOLD, BANG, EXTRA, DFLALL, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_global',
},
{
- command='goto',
- flags=bit.bor(RANGE, COUNT, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_goto',
+ command = 'goto',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_goto',
},
{
- command='grep',
- flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_OTHER',
- func='ex_make',
+ command = 'grep',
+ flags = bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_make',
},
{
- command='grepadd',
- flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_OTHER',
- func='ex_make',
+ command = 'grepadd',
+ flags = bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_make',
},
{
- command='gui',
- flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_nogui',
+ command = 'gui',
+ flags = bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_nogui',
},
{
- command='gvim',
- flags=bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_nogui',
+ command = 'gvim',
+ flags = bit.bor(BANG, FILES, CMDARG, ARGOPT, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_nogui',
},
{
- command='help',
- flags=bit.bor(BANG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_help',
+ command = 'help',
+ flags = bit.bor(BANG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_help',
},
{
- command='helpclose',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_helpclose',
+ command = 'helpclose',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_helpclose',
},
{
- command='helpgrep',
- flags=bit.bor(EXTRA, NOTRLCOM, NEEDARG),
- addr_type='ADDR_NONE',
- func='ex_helpgrep',
+ command = 'helpgrep',
+ flags = bit.bor(EXTRA, NOTRLCOM, NEEDARG),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_helpgrep',
},
{
- command='helptags',
- flags=bit.bor(NEEDARG, FILES, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_helptags',
+ command = 'helptags',
+ flags = bit.bor(NEEDARG, FILES, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_helptags',
},
{
- command='highlight',
- flags=bit.bor(BANG, EXTRA, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_highlight',
+ command = 'highlight',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_highlight',
},
{
- command='hide',
- flags=bit.bor(BANG, RANGE, COUNT, EXTRA, TRLBAR),
- addr_type='ADDR_WINDOWS',
- func='ex_hide',
+ command = 'hide',
+ flags = bit.bor(BANG, RANGE, COUNT, EXTRA, TRLBAR),
+ addr_type = 'ADDR_WINDOWS',
+ func = 'ex_hide',
},
{
- command='history',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_history',
+ command = 'history',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_history',
},
{
- command='horizontal',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'horizontal',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='insert',
- flags=bit.bor(BANG, RANGE, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_append',
+ command = 'insert',
+ flags = bit.bor(BANG, RANGE, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_append',
},
{
- command='iabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abbreviate',
+ command = 'iabbrev',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abbreviate',
},
{
- command='iabclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abclear',
+ command = 'iabclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abclear',
},
{
- command='if',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_if',
+ command = 'if',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_if',
},
{
- command='ijump',
- flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
- addr_type='ADDR_LINES',
- func='ex_findpat',
+ command = 'ijump',
+ flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_findpat',
},
{
- command='ilist',
- flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_findpat',
+ command = 'ilist',
+ flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_findpat',
},
{
- command='imap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'imap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='imapclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mapclear',
+ command = 'imapclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mapclear',
},
{
- command='imenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'imenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='inoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'inoremap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='inoreabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abbreviate',
+ command = 'inoreabbrev',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abbreviate',
},
{
- command='inoremenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'inoremenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='intro',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_intro',
+ command = 'intro',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_intro',
},
{
- command='isearch',
- flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_findpat',
+ command = 'isearch',
+ flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_findpat',
},
{
- command='isplit',
- flags=bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
- addr_type='ADDR_LINES',
- func='ex_findpat',
+ command = 'isplit',
+ flags = bit.bor(BANG, RANGE, DFLALL, WHOLEFOLD, EXTRA),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_findpat',
},
{
- command='iunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_unmap',
+ command = 'iunmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_unmap',
},
{
- command='iunabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abbreviate',
+ command = 'iunabbrev',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abbreviate',
},
{
- command='iunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_menu',
+ command = 'iunmenu',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_menu',
},
{
- command='join',
- flags=bit.bor(BANG, RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_join',
+ command = 'join',
+ flags = bit.bor(BANG, RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_join',
},
{
- command='jumps',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_jumps',
+ command = 'jumps',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_jumps',
},
{
- command='k',
- flags=bit.bor(RANGE, WORD1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_mark',
+ command = 'k',
+ flags = bit.bor(RANGE, WORD1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_mark',
},
{
- command='keepmarks',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'keepmarks',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='keepjumps',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'keepjumps',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='keeppatterns',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'keeppatterns',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='keepalt',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'keepalt',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='list',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_print',
+ command = 'list',
+ flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_print',
},
{
- command='lNext',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cnext',
+ command = 'lNext',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cnext',
},
{
- command='lNfile',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cnext',
+ command = 'lNfile',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cnext',
},
{
- command='last',
- flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_last',
+ command = 'last',
+ flags = bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_last',
},
{
- command='labove',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='ex_cbelow',
+ command = 'labove',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cbelow',
},
{
- command='language',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_language',
+ command = 'language',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_language',
},
{
- command='laddexpr',
- flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_cexpr',
+ command = 'laddexpr',
+ flags = bit.bor(NEEDARG, WORD1, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cexpr',
},
{
- command='laddbuffer',
- flags=bit.bor(RANGE, WORD1, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_cbuffer',
+ command = 'laddbuffer',
+ flags = bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_cbuffer',
},
{
- command='laddfile',
- flags=bit.bor(TRLBAR, FILE1),
- addr_type='ADDR_NONE',
- func='ex_cfile',
+ command = 'laddfile',
+ flags = bit.bor(TRLBAR, FILE1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cfile',
},
{
- command='lafter',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='ex_cbelow',
+ command = 'lafter',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cbelow',
},
{
- command='later',
- flags=bit.bor(TRLBAR, EXTRA, NOSPC, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_later',
+ command = 'later',
+ flags = bit.bor(TRLBAR, EXTRA, NOSPC, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_later',
},
{
- command='lbuffer',
- flags=bit.bor(BANG, RANGE, WORD1, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_cbuffer',
+ command = 'lbuffer',
+ flags = bit.bor(BANG, RANGE, WORD1, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_cbuffer',
},
{
- command='lbefore',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='ex_cbelow',
+ command = 'lbefore',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cbelow',
},
{
- command='lbelow',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='ex_cbelow',
+ command = 'lbelow',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cbelow',
},
{
- command='lbottom',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_cbottom',
+ command = 'lbottom',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cbottom',
},
{
- command='lcd',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_cd',
+ command = 'lcd',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cd',
},
{
- command='lchdir',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_cd',
+ command = 'lchdir',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cd',
},
{
- command='lclose',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_cclose',
+ command = 'lclose',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_cclose',
},
{
- command='ldo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
- addr_type='ADDR_QUICKFIX_VALID',
- func='ex_listdo',
+ command = 'ldo',
+ flags = bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type = 'ADDR_QUICKFIX_VALID',
+ func = 'ex_listdo',
},
{
- command='left',
- flags=bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_align',
+ command = 'left',
+ flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_align',
},
{
- command='leftabove',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'leftabove',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='let',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_let',
+ command = 'let',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_let',
},
{
- command='lexpr',
- flags=bit.bor(NEEDARG, WORD1, NOTRLCOM, BANG),
- addr_type='ADDR_NONE',
- func='ex_cexpr',
+ command = 'lexpr',
+ flags = bit.bor(NEEDARG, WORD1, NOTRLCOM, BANG),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cexpr',
},
{
- command='lfile',
- flags=bit.bor(TRLBAR, FILE1, BANG),
- addr_type='ADDR_NONE',
- func='ex_cfile',
+ command = 'lfile',
+ flags = bit.bor(TRLBAR, FILE1, BANG),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cfile',
},
-- Even though 'lfdo' is alphabetically lower than 'lfile', it is after
-- 'lfile' in this cmd list to support the existing ":lf" abbreviation.
{
- command='lfdo',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
- addr_type='ADDR_QUICKFIX_VALID',
- func='ex_listdo',
+ command = 'lfdo',
+ flags = bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type = 'ADDR_QUICKFIX_VALID',
+ func = 'ex_listdo',
},
{
- command='lfirst',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cc',
+ command = 'lfirst',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cc',
},
{
- command='lgetfile',
- flags=bit.bor(TRLBAR, FILE1),
- addr_type='ADDR_NONE',
- func='ex_cfile',
+ command = 'lgetfile',
+ flags = bit.bor(TRLBAR, FILE1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cfile',
},
{
- command='lgetbuffer',
- flags=bit.bor(RANGE, WORD1, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_cbuffer',
+ command = 'lgetbuffer',
+ flags = bit.bor(RANGE, WORD1, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_cbuffer',
},
{
- command='lgetexpr',
- flags=bit.bor(NEEDARG, WORD1, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_cexpr',
+ command = 'lgetexpr',
+ flags = bit.bor(NEEDARG, WORD1, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cexpr',
},
{
- command='lgrep',
- flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_OTHER',
- func='ex_make',
+ command = 'lgrep',
+ flags = bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_make',
},
{
- command='lgrepadd',
- flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_OTHER',
- func='ex_make',
+ command = 'lgrepadd',
+ flags = bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_make',
},
{
- command='lhelpgrep',
- flags=bit.bor(EXTRA, NOTRLCOM, NEEDARG),
- addr_type='ADDR_NONE',
- func='ex_helpgrep',
+ command = 'lhelpgrep',
+ flags = bit.bor(EXTRA, NOTRLCOM, NEEDARG),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_helpgrep',
},
{
- command='lhistory',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='qf_history',
+ command = 'lhistory',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'qf_history',
},
{
- command='ll',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_QUICKFIX',
- func='ex_cc',
+ command = 'll',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_QUICKFIX',
+ func = 'ex_cc',
},
{
- command='llast',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cc',
+ command = 'llast',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cc',
},
{
- command='llist',
- flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='qf_list',
+ command = 'llist',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'qf_list',
},
{
- command='lmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'lmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='lmapclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mapclear',
+ command = 'lmapclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mapclear',
},
{
- command='lmake',
- flags=bit.bor(BANG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_NONE',
- func='ex_make',
+ command = 'lmake',
+ flags = bit.bor(BANG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_make',
},
{
- command='lnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'lnoremap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='lnext',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cnext',
+ command = 'lnext',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cnext',
},
{
- command='lnewer',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='qf_age',
+ command = 'lnewer',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'qf_age',
},
{
- command='lnfile',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cnext',
+ command = 'lnfile',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cnext',
},
{
- command='loadview',
- flags=bit.bor(FILE1, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_loadview',
+ command = 'loadview',
+ flags = bit.bor(FILE1, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_loadview',
},
{
- command='loadkeymap',
- flags=bit.bor(CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_loadkeymap',
+ command = 'loadkeymap',
+ flags = bit.bor(CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_loadkeymap',
},
{
- command='lockmarks',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'lockmarks',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='lockvar',
- flags=bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_lockvar',
+ command = 'lockvar',
+ flags = bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_lockvar',
},
{
- command='lolder',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_UNSIGNED',
- func='qf_age',
+ command = 'lolder',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'qf_age',
},
{
- command='lopen',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_copen',
+ command = 'lopen',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_copen',
},
{
- command='lprevious',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cnext',
+ command = 'lprevious',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cnext',
},
{
- command='lpfile',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_OTHER',
- func='ex_cnext',
+ command = 'lpfile',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_cnext',
},
{
- command='lrewind',
- flags=bit.bor(RANGE, COUNT, TRLBAR, BANG),
- addr_type='ADDR_UNSIGNED',
- func='ex_cc',
+ command = 'lrewind',
+ flags = bit.bor(RANGE, COUNT, TRLBAR, BANG),
+ addr_type = 'ADDR_UNSIGNED',
+ func = 'ex_cc',
},
{
- command='ltag',
- flags=bit.bor(TRLBAR, BANG, WORD1),
- addr_type='ADDR_NONE',
- func='ex_tag',
+ command = 'ltag',
+ flags = bit.bor(TRLBAR, BANG, WORD1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_tag',
},
{
- command='lunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_unmap',
+ command = 'lunmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_unmap',
},
{
- command='lua',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_lua',
+ command = 'lua',
+ flags = bit.bor(RANGE, EXTRA, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_lua',
},
{
- command='luado',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_luado',
+ command = 'luado',
+ flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_luado',
},
{
- command='luafile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_luafile',
+ command = 'luafile',
+ flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_luafile',
},
{
- command='lvimgrep',
- flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_vimgrep',
+ command = 'lvimgrep',
+ flags = bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_vimgrep',
},
{
- command='lvimgrepadd',
- flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_vimgrep',
+ command = 'lvimgrepadd',
+ flags = bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_vimgrep',
},
{
- command='lwindow',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_cwindow',
+ command = 'lwindow',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_cwindow',
},
{
- command='ls',
- flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='buflist_list',
+ command = 'ls',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'buflist_list',
},
{
- command='move',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_copymove',
+ command = 'move',
+ flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_copymove',
},
{
- command='mark',
- flags=bit.bor(RANGE, WORD1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_mark',
+ command = 'mark',
+ flags = bit.bor(RANGE, WORD1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_mark',
},
{
- command='make',
- flags=bit.bor(BANG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_NONE',
- func='ex_make',
+ command = 'make',
+ flags = bit.bor(BANG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_make',
},
{
- command='map',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'map',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='mapclear',
- flags=bit.bor(EXTRA, BANG, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mapclear',
+ command = 'mapclear',
+ flags = bit.bor(EXTRA, BANG, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mapclear',
},
{
- command='marks',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_marks',
+ command = 'marks',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_marks',
},
{
- command='match',
- flags=bit.bor(RANGE, EXTRA, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_match',
+ command = 'match',
+ flags = bit.bor(RANGE, EXTRA, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_match',
},
{
- command='menu',
- flags=bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'menu',
+ flags = bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='menutranslate',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_menutranslate',
+ command = 'menutranslate',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_menutranslate',
},
{
- command='messages',
- flags=bit.bor(EXTRA, TRLBAR, RANGE, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_messages',
+ command = 'messages',
+ flags = bit.bor(EXTRA, TRLBAR, RANGE, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_messages',
},
{
- command='mkexrc',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mkrc',
+ command = 'mkexrc',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mkrc',
},
{
- command='mksession',
- flags=bit.bor(BANG, FILE1, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_mkrc',
+ command = 'mksession',
+ flags = bit.bor(BANG, FILE1, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mkrc',
},
{
- command='mkspell',
- flags=bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
- addr_type='ADDR_NONE',
- func='ex_mkspell',
+ command = 'mkspell',
+ flags = bit.bor(BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mkspell',
},
{
- command='mkvimrc',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mkrc',
+ command = 'mkvimrc',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mkrc',
},
{
- command='mkview',
- flags=bit.bor(BANG, FILE1, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_mkrc',
+ command = 'mkview',
+ flags = bit.bor(BANG, FILE1, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mkrc',
},
{
- command='mode',
- flags=bit.bor(WORD1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mode',
+ command = 'mode',
+ flags = bit.bor(WORD1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mode',
},
{
- command='mzscheme',
- flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN, LOCK_OK, SBOXOK),
- addr_type='ADDR_LINES',
- func='ex_script_ni',
+ command = 'mzscheme',
+ flags = bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN, LOCK_OK, SBOXOK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_script_ni',
},
{
- command='mzfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_ni',
+ command = 'mzfile',
+ flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_ni',
},
{
- command='next',
- flags=bit.bor(RANGE, BANG, FILES, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_next',
+ command = 'next',
+ flags = bit.bor(RANGE, BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_next',
},
{
- command='new',
- flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_splitview',
+ command = 'new',
+ flags = bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_splitview',
},
{
- command='nmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'nmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='nmapclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mapclear',
+ command = 'nmapclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mapclear',
},
{
- command='nmenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'nmenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='nnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'nnoremap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='nnoremenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'nnoremenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='noremap',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'noremap',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='noautocmd',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'noautocmd',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='nohlsearch',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_nohlsearch',
+ command = 'nohlsearch',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_nohlsearch',
},
{
- command='noreabbrev',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abbreviate',
+ command = 'noreabbrev',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abbreviate',
},
{
- command='noremenu',
- flags=bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'noremenu',
+ flags = bit.bor(RANGE, ZEROR, BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='noswapfile',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'noswapfile',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='normal',
- flags=bit.bor(RANGE, BANG, EXTRA, NEEDARG, NOTRLCOM, CTRLV, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_normal',
+ command = 'normal',
+ flags = bit.bor(RANGE, BANG, EXTRA, NEEDARG, NOTRLCOM, CTRLV, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_normal',
},
{
- command='number',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_print',
+ command = 'number',
+ flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_print',
},
{
- command='nunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_unmap',
+ command = 'nunmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_unmap',
},
{
- command='nunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_menu',
+ command = 'nunmenu',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_menu',
},
{
- command='oldfiles',
- flags=bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_oldfiles',
+ command = 'oldfiles',
+ flags = bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_oldfiles',
},
{
- command='omap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'omap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='omapclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mapclear',
+ command = 'omapclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mapclear',
},
{
- command='omenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'omenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='only',
- flags=bit.bor(BANG, RANGE, COUNT, TRLBAR),
- addr_type='ADDR_WINDOWS',
- func='ex_only',
+ command = 'only',
+ flags = bit.bor(BANG, RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_WINDOWS',
+ func = 'ex_only',
},
{
- command='onoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'onoremap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='onoremenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'onoremenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='options',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_options',
+ command = 'options',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_options',
},
{
- command='ounmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_unmap',
+ command = 'ounmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_unmap',
},
{
- command='ounmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_menu',
+ command = 'ounmenu',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_menu',
},
{
- command='ownsyntax',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_ownsyntax',
+ command = 'ownsyntax',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_ownsyntax',
},
{
- command='print',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, SBOXOK),
- addr_type='ADDR_LINES',
- func='ex_print',
+ command = 'print',
+ flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, SBOXOK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_print',
},
{
- command='packadd',
- flags=bit.bor(BANG, FILE1, NEEDARG, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_packadd',
+ command = 'packadd',
+ flags = bit.bor(BANG, FILE1, NEEDARG, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_packadd',
},
{
- command='packloadall',
- flags=bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_packloadall',
+ command = 'packloadall',
+ flags = bit.bor(BANG, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_packloadall',
},
{
- command='pclose',
- flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_pclose',
+ command = 'pclose',
+ flags = bit.bor(BANG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_pclose',
},
{
- command='perl',
- flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_perl',
+ command = 'perl',
+ flags = bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_perl',
},
{
- command='perldo',
- flags=bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_perldo',
+ command = 'perldo',
+ flags = bit.bor(RANGE, EXTRA, DFLALL, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_perldo',
},
{
- command='perlfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_perlfile',
+ command = 'perlfile',
+ flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_perlfile',
},
{
- command='pedit',
- flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_pedit',
+ command = 'pedit',
+ flags = bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_pedit',
},
{
- command='pop',
- flags=bit.bor(RANGE, BANG, COUNT, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_tag',
+ command = 'pop',
+ flags = bit.bor(RANGE, BANG, COUNT, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_tag',
},
{
- command='popup',
- flags=bit.bor(NEEDARG, EXTRA, BANG, TRLBAR, NOTRLCOM, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_popup',
+ command = 'popup',
+ flags = bit.bor(NEEDARG, EXTRA, BANG, TRLBAR, NOTRLCOM, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_popup',
},
{
- command='ppop',
- flags=bit.bor(RANGE, BANG, COUNT, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_ptag',
+ command = 'ppop',
+ flags = bit.bor(RANGE, BANG, COUNT, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_ptag',
},
{
- command='preserve',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_preserve',
+ command = 'preserve',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_preserve',
},
{
- command='previous',
- flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_previous',
+ command = 'previous',
+ flags = bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_previous',
},
{
- command='profile',
- flags=bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_profile',
+ command = 'profile',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_profile',
},
{
- command='profdel',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_breakdel',
+ command = 'profdel',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_breakdel',
},
{
- command='psearch',
- flags=bit.bor(BANG, RANGE, WHOLEFOLD, DFLALL, EXTRA),
- addr_type='ADDR_LINES',
- func='ex_psearch',
+ command = 'psearch',
+ flags = bit.bor(BANG, RANGE, WHOLEFOLD, DFLALL, EXTRA),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_psearch',
},
{
- command='ptag',
- flags=bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_ptag',
+ command = 'ptag',
+ flags = bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_ptag',
},
{
- command='ptNext',
- flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_ptag',
+ command = 'ptNext',
+ flags = bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_ptag',
},
{
- command='ptfirst',
- flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_ptag',
+ command = 'ptfirst',
+ flags = bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_ptag',
},
{
- command='ptjump',
- flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_NONE',
- func='ex_ptag',
+ command = 'ptjump',
+ flags = bit.bor(BANG, TRLBAR, WORD1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_ptag',
},
{
- command='ptlast',
- flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_ptag',
+ command = 'ptlast',
+ flags = bit.bor(BANG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_ptag',
},
{
- command='ptnext',
- flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_ptag',
+ command = 'ptnext',
+ flags = bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_ptag',
},
{
- command='ptprevious',
- flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_ptag',
+ command = 'ptprevious',
+ flags = bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_ptag',
},
{
- command='ptrewind',
- flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_ptag',
+ command = 'ptrewind',
+ flags = bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_ptag',
},
{
- command='ptselect',
- flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_NONE',
- func='ex_ptag',
+ command = 'ptselect',
+ flags = bit.bor(BANG, TRLBAR, WORD1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_ptag',
},
{
- command='put',
- flags=bit.bor(RANGE, WHOLEFOLD, BANG, REGSTR, TRLBAR, ZEROR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_put',
+ command = 'put',
+ flags = bit.bor(RANGE, WHOLEFOLD, BANG, REGSTR, TRLBAR, ZEROR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_put',
},
{
- command='pwd',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_pwd',
+ command = 'pwd',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_pwd',
},
{
- command='python',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_python3',
+ command = 'python',
+ flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_python3',
},
{
- command='pydo',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_pydo3',
+ command = 'pydo',
+ flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_pydo3',
},
{
- command='pyfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_py3file',
+ command = 'pyfile',
+ flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_py3file',
},
{
- command='py3',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_python3',
+ command = 'py3',
+ flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_python3',
},
{
- command='py3do',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_pydo3',
+ command = 'py3do',
+ flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_pydo3',
},
{
- command='python3',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_python3',
+ command = 'python3',
+ flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_python3',
},
{
- command='py3file',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_py3file',
+ command = 'py3file',
+ flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_py3file',
},
{
- command='pyx',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_python3',
+ command = 'pyx',
+ flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_python3',
},
{
- command='pyxdo',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_pydo3',
+ command = 'pyxdo',
+ flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_pydo3',
},
{
- command='pythonx',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_python3',
+ command = 'pythonx',
+ flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_python3',
},
{
- command='pyxfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_py3file',
+ command = 'pyxfile',
+ flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_py3file',
},
{
- command='quit',
- flags=bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_WINDOWS',
- func='ex_quit',
+ command = 'quit',
+ flags = bit.bor(BANG, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_WINDOWS',
+ func = 'ex_quit',
},
{
- command='quitall',
- flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_quit_all',
+ command = 'quitall',
+ flags = bit.bor(BANG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_quit_all',
},
{
- command='qall',
- flags=bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_quit_all',
+ command = 'qall',
+ flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_quit_all',
},
{
- command='read',
- flags=bit.bor(BANG, RANGE, WHOLEFOLD, FILE1, ARGOPT, TRLBAR, ZEROR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_read',
+ command = 'read',
+ flags = bit.bor(BANG, RANGE, WHOLEFOLD, FILE1, ARGOPT, TRLBAR, ZEROR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_read',
},
{
- command='recover',
- flags=bit.bor(BANG, FILE1, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_recover',
+ command = 'recover',
+ flags = bit.bor(BANG, FILE1, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_recover',
},
{
- command='redo',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_redo',
+ command = 'redo',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_redo',
},
{
- command='redir',
- flags=bit.bor(BANG, FILES, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_redir',
+ command = 'redir',
+ flags = bit.bor(BANG, FILES, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_redir',
},
{
- command='redraw',
- flags=bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_redraw',
+ command = 'redraw',
+ flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_redraw',
},
{
- command='redrawstatus',
- flags=bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_redrawstatus',
+ command = 'redrawstatus',
+ flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_redrawstatus',
},
{
- command='redrawtabline',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_redrawtabline',
+ command = 'redrawtabline',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_redrawtabline',
},
{
- command='registers',
- flags=bit.bor(EXTRA, NOTRLCOM, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_display',
+ command = 'registers',
+ flags = bit.bor(EXTRA, NOTRLCOM, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_display',
},
{
- command='resize',
- flags=bit.bor(RANGE, TRLBAR, WORD1, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_resize',
+ command = 'resize',
+ flags = bit.bor(RANGE, TRLBAR, WORD1, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_resize',
},
{
- command='retab',
- flags=bit.bor(TRLBAR, RANGE, WHOLEFOLD, DFLALL, BANG, WORD1, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_retab',
+ command = 'retab',
+ flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, DFLALL, BANG, WORD1, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_retab',
},
{
- command='return',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_return',
+ command = 'return',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_return',
},
{
- command='rewind',
- flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_rewind',
+ command = 'rewind',
+ flags = bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_rewind',
},
{
- command='right',
- flags=bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_align',
+ command = 'right',
+ flags = bit.bor(TRLBAR, RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_align',
},
{
- command='rightbelow',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'rightbelow',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='rshada',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_shada',
+ command = 'rshada',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_shada',
},
{
- command='runtime',
- flags=bit.bor(BANG, NEEDARG, FILES, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_runtime',
+ command = 'runtime',
+ flags = bit.bor(BANG, NEEDARG, FILES, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_runtime',
},
{
- command='rundo',
- flags=bit.bor(NEEDARG, FILE1),
- addr_type='ADDR_NONE',
- func='ex_rundo',
+ command = 'rundo',
+ flags = bit.bor(NEEDARG, FILE1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_rundo',
},
{
- command='ruby',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_ruby',
+ command = 'ruby',
+ flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_ruby',
},
{
- command='rubydo',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_rubydo',
+ command = 'rubydo',
+ flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_rubydo',
},
{
- command='rubyfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_rubyfile',
+ command = 'rubyfile',
+ flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_rubyfile',
},
{
- command='rviminfo',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_shada',
+ command = 'rviminfo',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_shada',
},
{
- command='substitute',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, PREVIEW),
- addr_type='ADDR_LINES',
- func='ex_substitute',
- preview_func='ex_substitute_preview',
+ command = 'substitute',
+ flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, PREVIEW),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_substitute',
+ preview_func = 'ex_substitute_preview',
},
{
- command='sNext',
- flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_previous',
+ command = 'sNext',
+ flags = bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_previous',
},
{
- command='sargument',
- flags=bit.bor(BANG, RANGE, COUNT, EXTRA, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_ARGUMENTS',
- func='ex_argument',
+ command = 'sargument',
+ flags = bit.bor(BANG, RANGE, COUNT, EXTRA, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_ARGUMENTS',
+ func = 'ex_argument',
},
{
- command='sall',
- flags=bit.bor(BANG, RANGE, COUNT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_all',
+ command = 'sall',
+ flags = bit.bor(BANG, RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_all',
},
{
- command='sandbox',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'sandbox',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='saveas',
- flags=bit.bor(BANG, FILE1, ARGOPT, CMDWIN, LOCK_OK, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_write',
+ command = 'saveas',
+ flags = bit.bor(BANG, FILE1, ARGOPT, CMDWIN, LOCK_OK, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_write',
},
{
- command='sbuffer',
- flags=bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, CMDARG, TRLBAR),
- addr_type='ADDR_BUFFERS',
- func='ex_buffer',
+ command = 'sbuffer',
+ flags = bit.bor(BANG, RANGE, BUFNAME, BUFUNL, COUNT, EXTRA, CMDARG, TRLBAR),
+ addr_type = 'ADDR_BUFFERS',
+ func = 'ex_buffer',
},
{
- command='sbNext',
- flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_bprevious',
+ command = 'sbNext',
+ flags = bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_bprevious',
},
{
- command='sball',
- flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_buffer_all',
+ command = 'sball',
+ flags = bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_buffer_all',
},
{
- command='sbfirst',
- flags=bit.bor(CMDARG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_brewind',
+ command = 'sbfirst',
+ flags = bit.bor(CMDARG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_brewind',
},
{
- command='sblast',
- flags=bit.bor(CMDARG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_blast',
+ command = 'sblast',
+ flags = bit.bor(CMDARG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_blast',
},
{
- command='sbmodified',
- flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_bmodified',
+ command = 'sbmodified',
+ flags = bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_bmodified',
},
{
- command='sbnext',
- flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_bnext',
+ command = 'sbnext',
+ flags = bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_bnext',
},
{
- command='sbprevious',
- flags=bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_bprevious',
+ command = 'sbprevious',
+ flags = bit.bor(RANGE, COUNT, CMDARG, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_bprevious',
},
{
- command='sbrewind',
- flags=bit.bor(CMDARG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_brewind',
+ command = 'sbrewind',
+ flags = bit.bor(CMDARG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_brewind',
},
{
- command='scriptnames',
- flags=bit.bor(BANG, FILES, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_scriptnames',
+ command = 'scriptnames',
+ flags = bit.bor(BANG, FILES, RANGE, COUNT, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_scriptnames',
},
{
- command='scriptencoding',
- flags=bit.bor(WORD1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_scriptencoding',
+ command = 'scriptencoding',
+ flags = bit.bor(WORD1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_scriptencoding',
},
{
- command='set',
- flags=bit.bor(BANG, TRLBAR, EXTRA, CMDWIN, LOCK_OK, SBOXOK),
- addr_type='ADDR_NONE',
- func='ex_set',
+ command = 'set',
+ flags = bit.bor(BANG, TRLBAR, EXTRA, CMDWIN, LOCK_OK, SBOXOK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_set',
},
{
- command='setfiletype',
- flags=bit.bor(TRLBAR, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_setfiletype',
+ command = 'setfiletype',
+ flags = bit.bor(TRLBAR, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_setfiletype',
},
{
- command='setglobal',
- flags=bit.bor(BANG, TRLBAR, EXTRA, CMDWIN, LOCK_OK, SBOXOK),
- addr_type='ADDR_NONE',
- func='ex_set',
+ command = 'setglobal',
+ flags = bit.bor(BANG, TRLBAR, EXTRA, CMDWIN, LOCK_OK, SBOXOK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_set',
},
{
- command='setlocal',
- flags=bit.bor(BANG, TRLBAR, EXTRA, CMDWIN, LOCK_OK, SBOXOK),
- addr_type='ADDR_NONE',
- func='ex_set',
+ command = 'setlocal',
+ flags = bit.bor(BANG, TRLBAR, EXTRA, CMDWIN, LOCK_OK, SBOXOK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_set',
},
{
- command='sfind',
- flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR, NEEDARG),
- addr_type='ADDR_OTHER',
- func='ex_splitview',
+ command = 'sfind',
+ flags = bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR, NEEDARG),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_splitview',
},
{
- command='sfirst',
- flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_rewind',
+ command = 'sfirst',
+ flags = bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_rewind',
},
{
- command='simalt',
- flags=bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_ni',
+ command = 'simalt',
+ flags = bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_ni',
},
{
- command='sign',
- flags=bit.bor(NEEDARG, RANGE, EXTRA, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_sign',
+ command = 'sign',
+ flags = bit.bor(NEEDARG, RANGE, EXTRA, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_sign',
},
{
- command='silent',
- flags=bit.bor(NEEDARG, EXTRA, BANG, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'silent',
+ flags = bit.bor(NEEDARG, EXTRA, BANG, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='sleep',
- flags=bit.bor(BANG, RANGE, COUNT, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_sleep',
+ command = 'sleep',
+ flags = bit.bor(BANG, RANGE, COUNT, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_sleep',
},
{
- command='slast',
- flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_last',
+ command = 'slast',
+ flags = bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_last',
},
{
- command='smagic',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, PREVIEW),
- addr_type='ADDR_LINES',
- func='ex_submagic',
- preview_func='ex_submagic_preview',
+ command = 'smagic',
+ flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, PREVIEW),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_submagic',
+ preview_func = 'ex_submagic_preview',
},
{
- command='smap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'smap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='smapclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mapclear',
+ command = 'smapclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mapclear',
},
{
- command='smenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'smenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='snext',
- flags=bit.bor(RANGE, BANG, FILES, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_next',
+ command = 'snext',
+ flags = bit.bor(RANGE, BANG, FILES, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_next',
},
{
- command='snomagic',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, PREVIEW),
- addr_type='ADDR_LINES',
- func='ex_submagic',
- preview_func='ex_submagic_preview',
+ command = 'snomagic',
+ flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, PREVIEW),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_submagic',
+ preview_func = 'ex_submagic_preview',
},
{
- command='snoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'snoremap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='snoremenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'snoremenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='source',
- flags=bit.bor(RANGE, DFLALL, WHOLEFOLD, BANG, FILE1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_source',
+ command = 'source',
+ flags = bit.bor(RANGE, DFLALL, WHOLEFOLD, BANG, FILE1, TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_source',
},
{
- command='sort',
- flags=bit.bor(RANGE, DFLALL, WHOLEFOLD, BANG, EXTRA, NOTRLCOM, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_sort',
+ command = 'sort',
+ flags = bit.bor(RANGE, DFLALL, WHOLEFOLD, BANG, EXTRA, NOTRLCOM, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_sort',
},
{
- command='split',
- flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_splitview',
+ command = 'split',
+ flags = bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_splitview',
},
{
- command='spellgood',
- flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_spell',
+ command = 'spellgood',
+ flags = bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_spell',
},
{
- command='spelldump',
- flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_spelldump',
+ command = 'spelldump',
+ flags = bit.bor(BANG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_spelldump',
},
{
- command='spellinfo',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_spellinfo',
+ command = 'spellinfo',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_spellinfo',
},
{
- command='spellrepall',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_spellrepall',
+ command = 'spellrepall',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_spellrepall',
},
{
- command='spellrare',
- flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_spell',
+ command = 'spellrare',
+ flags = bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_spell',
},
{
- command='spellundo',
- flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_spell',
+ command = 'spellundo',
+ flags = bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_spell',
},
{
- command='spellwrong',
- flags=bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_spell',
+ command = 'spellwrong',
+ flags = bit.bor(BANG, RANGE, NEEDARG, EXTRA, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_spell',
},
{
- command='sprevious',
- flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_previous',
+ command = 'sprevious',
+ flags = bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_previous',
},
{
- command='srewind',
- flags=bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_rewind',
+ command = 'srewind',
+ flags = bit.bor(EXTRA, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_rewind',
},
{
- command='stop',
- flags=bit.bor(TRLBAR, BANG, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_stop',
+ command = 'stop',
+ flags = bit.bor(TRLBAR, BANG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_stop',
},
{
- command='stag',
- flags=bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_stag',
+ command = 'stag',
+ flags = bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_stag',
},
{
- command='startinsert',
- flags=bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_startinsert',
+ command = 'startinsert',
+ flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_startinsert',
},
{
- command='startgreplace',
- flags=bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_startinsert',
+ command = 'startgreplace',
+ flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_startinsert',
},
{
- command='startreplace',
- flags=bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_startinsert',
+ command = 'startreplace',
+ flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_startinsert',
},
{
- command='stopinsert',
- flags=bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_stopinsert',
+ command = 'stopinsert',
+ flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_stopinsert',
},
{
- command='stjump',
- flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_NONE',
- func='ex_stag',
+ command = 'stjump',
+ flags = bit.bor(BANG, TRLBAR, WORD1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_stag',
},
{
- command='stselect',
- flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_NONE',
- func='ex_stag',
+ command = 'stselect',
+ flags = bit.bor(BANG, TRLBAR, WORD1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_stag',
},
{
- command='sunhide',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_buffer_all',
+ command = 'sunhide',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_buffer_all',
},
{
- command='sunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_unmap',
+ command = 'sunmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_unmap',
},
{
- command='sunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_menu',
+ command = 'sunmenu',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_menu',
},
{
- command='suspend',
- flags=bit.bor(TRLBAR, BANG, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_stop',
+ command = 'suspend',
+ flags = bit.bor(TRLBAR, BANG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_stop',
},
{
- command='sview',
- flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_splitview',
+ command = 'sview',
+ flags = bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_splitview',
},
{
- command='swapname',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_swapname',
+ command = 'swapname',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_swapname',
},
{
- command='syntax',
- flags=bit.bor(EXTRA, NOTRLCOM, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_syntax',
+ command = 'syntax',
+ flags = bit.bor(EXTRA, NOTRLCOM, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_syntax',
},
{
- command='syntime',
- flags=bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_syntime',
+ command = 'syntime',
+ flags = bit.bor(NEEDARG, WORD1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_syntime',
},
{
- command='syncbind',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_syncbind',
+ command = 'syncbind',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_syncbind',
},
{
- command='t',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_copymove',
+ command = 't',
+ flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_copymove',
},
{
- command='tcd',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_cd',
+ command = 'tcd',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cd',
},
{
- command='tchdir',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_cd',
+ command = 'tchdir',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_cd',
},
{
- command='tNext',
- flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_tag',
+ command = 'tNext',
+ flags = bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_tag',
},
{
- command='tag',
- flags=bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_tag',
+ command = 'tag',
+ flags = bit.bor(RANGE, BANG, WORD1, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_tag',
},
{
- command='tags',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='do_tags',
+ command = 'tags',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'do_tags',
},
{
- command='tab',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'tab',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='tabclose',
- flags=bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_TABS',
- func='ex_tabclose',
+ command = 'tabclose',
+ flags = bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_TABS',
+ func = 'ex_tabclose',
},
{
- command='tabdo',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
- addr_type='ADDR_TABS',
- func='ex_listdo',
+ command = 'tabdo',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type = 'ADDR_TABS',
+ func = 'ex_listdo',
},
{
- command='tabedit',
- flags=bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_TABS',
- func='ex_splitview',
+ command = 'tabedit',
+ flags = bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_TABS',
+ func = 'ex_splitview',
},
{
- command='tabfind',
- flags=bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, NEEDARG, TRLBAR),
- addr_type='ADDR_TABS',
- func='ex_splitview',
+ command = 'tabfind',
+ flags = bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, NEEDARG, TRLBAR),
+ addr_type = 'ADDR_TABS',
+ func = 'ex_splitview',
},
{
- command='tabfirst',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_tabnext',
+ command = 'tabfirst',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_tabnext',
},
{
- command='tabmove',
- flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
- addr_type='ADDR_TABS',
- func='ex_tabmove',
+ command = 'tabmove',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
+ addr_type = 'ADDR_TABS',
+ func = 'ex_tabmove',
},
{
- command='tablast',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_tabnext',
+ command = 'tablast',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_tabnext',
},
{
- command='tabnext',
- flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
- addr_type='ADDR_TABS',
- func='ex_tabnext',
+ command = 'tabnext',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
+ addr_type = 'ADDR_TABS',
+ func = 'ex_tabnext',
},
{
- command='tabnew',
- flags=bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_TABS',
- func='ex_splitview',
+ command = 'tabnew',
+ flags = bit.bor(BANG, FILE1, RANGE, ZEROR, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_TABS',
+ func = 'ex_splitview',
},
{
- command='tabonly',
- flags=bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_TABS',
- func='ex_tabonly',
+ command = 'tabonly',
+ flags = bit.bor(BANG, RANGE, ZEROR, EXTRA, NOSPC, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_TABS',
+ func = 'ex_tabonly',
},
{
- command='tabprevious',
- flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
- addr_type='ADDR_TABS_RELATIVE',
- func='ex_tabnext',
+ command = 'tabprevious',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
+ addr_type = 'ADDR_TABS_RELATIVE',
+ func = 'ex_tabnext',
},
{
- command='tabNext',
- flags=bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
- addr_type='ADDR_TABS_RELATIVE',
- func='ex_tabnext',
+ command = 'tabNext',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, NOSPC, TRLBAR),
+ addr_type = 'ADDR_TABS_RELATIVE',
+ func = 'ex_tabnext',
},
{
- command='tabrewind',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_tabnext',
+ command = 'tabrewind',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_tabnext',
},
{
- command='tabs',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_tabs',
+ command = 'tabs',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_tabs',
},
{
- command='tcl',
- flags=bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_script_ni',
+ command = 'tcl',
+ flags = bit.bor(RANGE, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_script_ni',
},
{
- command='tcldo',
- flags=bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_ni',
+ command = 'tcldo',
+ flags = bit.bor(RANGE, DFLALL, EXTRA, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_ni',
},
{
- command='tclfile',
- flags=bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_ni',
+ command = 'tclfile',
+ flags = bit.bor(RANGE, FILE1, NEEDARG, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_ni',
},
{
- command='terminal',
- flags=bit.bor(BANG, FILES, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_terminal',
+ command = 'terminal',
+ flags = bit.bor(BANG, FILES, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_terminal',
},
{
- command='tfirst',
- flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_tag',
+ command = 'tfirst',
+ flags = bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_tag',
},
{
- command='throw',
- flags=bit.bor(EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_throw',
+ command = 'throw',
+ flags = bit.bor(EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_throw',
},
{
- command='tjump',
- flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_NONE',
- func='ex_tag',
+ command = 'tjump',
+ flags = bit.bor(BANG, TRLBAR, WORD1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_tag',
},
{
- command='tlast',
- flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_tag',
+ command = 'tlast',
+ flags = bit.bor(BANG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_tag',
},
{
- command='tlmenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'tlmenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='tlnoremenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'tlnoremenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='tlunmenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'tlunmenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='tmenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'tmenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='tmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'tmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='tmapclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mapclear',
+ command = 'tmapclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mapclear',
},
{
- command='tnext',
- flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_tag',
+ command = 'tnext',
+ flags = bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_tag',
},
{
- command='tnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'tnoremap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='topleft',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'topleft',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='tprevious',
- flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_tag',
+ command = 'tprevious',
+ flags = bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_tag',
},
{
- command='trewind',
- flags=bit.bor(RANGE, BANG, TRLBAR, ZEROR),
- addr_type='ADDR_OTHER',
- func='ex_tag',
+ command = 'trewind',
+ flags = bit.bor(RANGE, BANG, TRLBAR, ZEROR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_tag',
},
{
- command='trust',
- flags=bit.bor(EXTRA, FILE1, TRLBAR, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_trust',
+ command = 'trust',
+ flags = bit.bor(EXTRA, FILE1, TRLBAR, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_trust',
},
{
- command='try',
- flags=bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_try',
+ command = 'try',
+ flags = bit.bor(TRLBAR, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_try',
},
{
- command='tselect',
- flags=bit.bor(BANG, TRLBAR, WORD1),
- addr_type='ADDR_NONE',
- func='ex_tag',
+ command = 'tselect',
+ flags = bit.bor(BANG, TRLBAR, WORD1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_tag',
},
{
- command='tunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_menu',
+ command = 'tunmenu',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_menu',
},
{
- command='tunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_unmap',
+ command = 'tunmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_unmap',
},
{
- command='undo',
- flags=bit.bor(BANG, RANGE, COUNT, ZEROR, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_undo',
+ command = 'undo',
+ flags = bit.bor(BANG, RANGE, COUNT, ZEROR, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_undo',
},
{
- command='undojoin',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_undojoin',
+ command = 'undojoin',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_undojoin',
},
{
- command='undolist',
- flags=bit.bor(TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_undolist',
+ command = 'undolist',
+ flags = bit.bor(TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_undolist',
},
{
- command='unabbreviate',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_abbreviate',
+ command = 'unabbreviate',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_abbreviate',
},
{
- command='unhide',
- flags=bit.bor(RANGE, COUNT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_buffer_all',
+ command = 'unhide',
+ flags = bit.bor(RANGE, COUNT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_buffer_all',
},
{
- command='unlet',
- flags=bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_unlet',
+ command = 'unlet',
+ flags = bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_unlet',
},
{
- command='unlockvar',
- flags=bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_lockvar',
+ command = 'unlockvar',
+ flags = bit.bor(BANG, EXTRA, NEEDARG, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_lockvar',
},
{
- command='unmap',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_unmap',
+ command = 'unmap',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_unmap',
},
{
- command='unmenu',
- flags=bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_menu',
+ command = 'unmenu',
+ flags = bit.bor(BANG, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_menu',
},
{
- command='unsilent',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'unsilent',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='update',
- flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR),
- addr_type='ADDR_LINES',
- func='ex_update',
+ command = 'update',
+ flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_update',
},
{
- command='vglobal',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, DFLALL, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_global',
+ command = 'vglobal',
+ flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, DFLALL, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_global',
},
{
- command='version',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_version',
+ command = 'version',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_version',
},
{
- command='verbose',
- flags=bit.bor(NEEDARG, RANGE, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_wrongmodifier',
+ command = 'verbose',
+ flags = bit.bor(NEEDARG, RANGE, EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_wrongmodifier',
},
{
- command='vertical',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM),
- addr_type='ADDR_NONE',
- func='ex_wrongmodifier',
+ command = 'vertical',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wrongmodifier',
},
{
- command='visual',
- flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_edit',
+ command = 'visual',
+ flags = bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_edit',
},
{
- command='view',
- flags=bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_edit',
+ command = 'view',
+ flags = bit.bor(BANG, FILE1, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_edit',
},
{
- command='vimgrep',
- flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_vimgrep',
+ command = 'vimgrep',
+ flags = bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_vimgrep',
},
{
- command='vimgrepadd',
- flags=bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_vimgrep',
+ command = 'vimgrepadd',
+ flags = bit.bor(RANGE, BANG, NEEDARG, EXTRA, NOTRLCOM, TRLBAR, XFILE, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_vimgrep',
},
{
- command='viusage',
- flags=bit.bor(TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_viusage',
+ command = 'viusage',
+ flags = bit.bor(TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_viusage',
},
{
- command='vmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'vmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='vmapclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mapclear',
+ command = 'vmapclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mapclear',
},
{
- command='vmenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'vmenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='vnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'vnoremap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='vnew',
- flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_splitview',
+ command = 'vnew',
+ flags = bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_splitview',
},
{
- command='vnoremenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'vnoremenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='vsplit',
- flags=bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_splitview',
+ command = 'vsplit',
+ flags = bit.bor(BANG, FILE1, RANGE, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_splitview',
},
{
- command='vunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_unmap',
+ command = 'vunmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_unmap',
},
{
- command='vunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_menu',
+ command = 'vunmenu',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_menu',
},
{
- command='write',
- flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_write',
+ command = 'write',
+ flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_write',
},
{
- command='wNext',
- flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_wnext',
+ command = 'wNext',
+ flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_wnext',
},
{
- command='wall',
- flags=bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='do_wqall',
+ command = 'wall',
+ flags = bit.bor(BANG, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'do_wqall',
},
{
- command='while',
- flags=bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_while',
+ command = 'while',
+ flags = bit.bor(EXTRA, NOTRLCOM, SBOXOK, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_while',
},
{
- command='winsize',
- flags=bit.bor(EXTRA, NEEDARG, TRLBAR),
- addr_type='ADDR_NONE',
- func='ex_winsize',
+ command = 'winsize',
+ flags = bit.bor(EXTRA, NEEDARG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_winsize',
},
{
- command='wincmd',
- flags=bit.bor(NEEDARG, WORD1, RANGE, COUNT, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_wincmd',
+ command = 'wincmd',
+ flags = bit.bor(NEEDARG, WORD1, RANGE, COUNT, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_wincmd',
},
{
- command='windo',
- flags=bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
- addr_type='ADDR_WINDOWS',
- func='ex_listdo',
+ command = 'windo',
+ flags = bit.bor(NEEDARG, EXTRA, NOTRLCOM, RANGE, DFLALL),
+ addr_type = 'ADDR_WINDOWS',
+ func = 'ex_listdo',
},
{
- command='winpos',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_ni',
+ command = 'winpos',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_ni',
},
{
- command='wnext',
- flags=bit.bor(RANGE, BANG, FILE1, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_wnext',
+ command = 'wnext',
+ flags = bit.bor(RANGE, BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_wnext',
},
{
- command='wprevious',
- flags=bit.bor(RANGE, BANG, FILE1, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_wnext',
+ command = 'wprevious',
+ flags = bit.bor(RANGE, BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_wnext',
},
{
- command='wq',
- flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR),
- addr_type='ADDR_LINES',
- func='ex_exit',
+ command = 'wq',
+ flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_exit',
},
{
- command='wqall',
- flags=bit.bor(BANG, FILE1, ARGOPT, TRLBAR),
- addr_type='ADDR_NONE',
- func='do_wqall',
+ command = 'wqall',
+ flags = bit.bor(BANG, FILE1, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'do_wqall',
},
{
- command='wshada',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_shada',
+ command = 'wshada',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_shada',
},
{
- command='wundo',
- flags=bit.bor(BANG, NEEDARG, FILE1),
- addr_type='ADDR_NONE',
- func='ex_wundo',
+ command = 'wundo',
+ flags = bit.bor(BANG, NEEDARG, FILE1),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_wundo',
},
{
- command='wviminfo',
- flags=bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_shada',
+ command = 'wviminfo',
+ flags = bit.bor(BANG, FILE1, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_shada',
},
{
- command='xit',
- flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_exit',
+ command = 'xit',
+ flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILE1, ARGOPT, DFLALL, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_exit',
},
{
- command='xall',
- flags=bit.bor(BANG, TRLBAR),
- addr_type='ADDR_NONE',
- func='do_wqall',
+ command = 'xall',
+ flags = bit.bor(BANG, TRLBAR),
+ addr_type = 'ADDR_NONE',
+ func = 'do_wqall',
},
{
- command='xmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'xmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='xmapclear',
- flags=bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_mapclear',
+ command = 'xmapclear',
+ flags = bit.bor(EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_mapclear',
},
{
- command='xmenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'xmenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='xnoremap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_map',
+ command = 'xnoremap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_map',
},
{
- command='xnoremenu',
- flags=bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_OTHER',
- func='ex_menu',
+ command = 'xnoremenu',
+ flags = bit.bor(RANGE, ZEROR, EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_menu',
},
{
- command='xunmap',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_unmap',
+ command = 'xunmap',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_unmap',
},
{
- command='xunmenu',
- flags=bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
- addr_type='ADDR_NONE',
- func='ex_menu',
+ command = 'xunmenu',
+ flags = bit.bor(EXTRA, TRLBAR, NOTRLCOM, CTRLV, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_NONE',
+ func = 'ex_menu',
},
{
- command='yank',
- flags=bit.bor(RANGE, WHOLEFOLD, REGSTR, COUNT, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_operators',
+ command = 'yank',
+ flags = bit.bor(RANGE, WHOLEFOLD, REGSTR, COUNT, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_operators',
},
{
- command='z',
- flags=bit.bor(RANGE, WHOLEFOLD, BANG, EXTRA, FLAGS, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_z',
+ command = 'z',
+ flags = bit.bor(RANGE, WHOLEFOLD, BANG, EXTRA, FLAGS, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_z',
},
-- commands that don't start with a letter
{
- command='!',
- enum='CMD_bang',
- flags=bit.bor(RANGE, WHOLEFOLD, BANG, FILES, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_bang',
+ command = '!',
+ enum = 'CMD_bang',
+ flags = bit.bor(RANGE, WHOLEFOLD, BANG, FILES, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_bang',
},
{
- command='#',
- enum='CMD_pound',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_print',
+ command = '#',
+ enum = 'CMD_pound',
+ flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_print',
},
{
- command='&',
- enum='CMD_and',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_substitute',
+ command = '&',
+ enum = 'CMD_and',
+ flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_substitute',
},
{
- command='<',
- enum='CMD_lshift',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_operators',
+ command = '<',
+ enum = 'CMD_lshift',
+ flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_operators',
},
{
- command='=',
- enum='CMD_equal',
- flags=bit.bor(RANGE, EXTRA, DFLALL, ARGOPT, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_equal',
+ command = '=',
+ enum = 'CMD_equal',
+ flags = bit.bor(RANGE, EXTRA, DFLALL, ARGOPT, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_equal',
},
{
- command='>',
- enum='CMD_rshift',
- flags=bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_operators',
+ command = '>',
+ enum = 'CMD_rshift',
+ flags = bit.bor(RANGE, WHOLEFOLD, COUNT, FLAGS, TRLBAR, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_operators',
},
{
- command='@',
- enum='CMD_at',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
- addr_type='ADDR_LINES',
- func='ex_at',
+ command = '@',
+ enum = 'CMD_at',
+ flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, TRLBAR, CMDWIN, LOCK_OK),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_at',
},
{
- command='~',
- enum='CMD_tilde',
- flags=bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY),
- addr_type='ADDR_LINES',
- func='ex_substitute',
+ command = '~',
+ enum = 'CMD_tilde',
+ flags = bit.bor(RANGE, WHOLEFOLD, EXTRA, CMDWIN, LOCK_OK, MODIFY),
+ addr_type = 'ADDR_LINES',
+ func = 'ex_substitute',
},
-- commands that start with an uppercase letter
{
- command='Next',
- flags=bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
- addr_type='ADDR_OTHER',
- func='ex_previous',
+ command = 'Next',
+ flags = bit.bor(EXTRA, RANGE, COUNT, BANG, CMDARG, ARGOPT, TRLBAR),
+ addr_type = 'ADDR_OTHER',
+ func = 'ex_previous',
},
}
diff --git a/src/nvim/ex_cmds2.c b/src/nvim/ex_cmds2.c
index 1722b7902b..8016e37ca7 100644
--- a/src/nvim/ex_cmds2.c
+++ b/src/nvim/ex_cmds2.c
@@ -11,12 +11,15 @@
#include "nvim/arglist.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/bufwrite.h"
#include "nvim/change.h"
#include "nvim/channel.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/vars.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
@@ -24,9 +27,10 @@
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/macros_defs.h"
#include "nvim/mark.h"
#include "nvim/memory.h"
@@ -39,6 +43,7 @@
#include "nvim/pos_defs.h"
#include "nvim/quickfix.h"
#include "nvim/runtime.h"
+#include "nvim/types_defs.h"
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -99,7 +104,7 @@ void ex_perldo(exarg_T *eap)
/// Careful: autocommands may make "buf" invalid!
///
/// @return FAIL for failure, OK otherwise
-int autowrite(buf_T *buf, int forceit)
+int autowrite(buf_T *buf, bool forceit)
{
bufref_T bufref;
@@ -131,7 +136,7 @@ void autowrite_all(void)
if (bufIsChanged(buf) && !buf->b_p_ro && !bt_dontwrite(buf)) {
bufref_T bufref;
set_bufref(&bufref, buf);
- (void)buf_write_all(buf, false);
+ buf_write_all(buf, false);
// an autocommand may have deleted the buffer
if (!bufref_valid(&bufref)) {
buf = firstbuf;
@@ -144,7 +149,7 @@ void autowrite_all(void)
/// For flags use the CCGD_ values.
bool check_changed(buf_T *buf, int flags)
{
- int forceit = (flags & CCGD_FORCEIT);
+ bool forceit = (flags & CCGD_FORCEIT);
bufref_T bufref;
set_bufref(&bufref, buf);
@@ -210,7 +215,7 @@ void dialog_changed(buf_T *buf, bool checkall)
if (buf->b_fname != NULL
&& check_overwrite(&ea, buf, buf->b_fname, buf->b_ffname, false) == OK) {
// didn't hit Cancel
- (void)buf_write_all(buf, false);
+ buf_write_all(buf, false);
}
} else if (ret == VIM_NO) {
unchanged(buf, true, false);
@@ -226,7 +231,7 @@ void dialog_changed(buf_T *buf, bool checkall)
if (buf2->b_fname != NULL
&& check_overwrite(&ea, buf2, buf2->b_fname, buf2->b_ffname, false) == OK) {
// didn't hit Cancel
- (void)buf_write_all(buf2, false);
+ buf_write_all(buf2, false);
}
// an autocommand may have deleted the buffer
if (!bufref_valid(&bufref)) {
@@ -260,7 +265,7 @@ bool dialog_close_terminal(buf_T *buf)
/// @return true if the buffer "buf" can be abandoned, either by making it
/// hidden, autowriting it or unloading it.
-bool can_abandon(buf_T *buf, int forceit)
+bool can_abandon(buf_T *buf, bool forceit)
{
return buf_hide(buf)
|| !bufIsChanged(buf)
@@ -400,7 +405,7 @@ buf_found:
// Open the changed buffer in the current window.
if (buf != curbuf) {
- set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO);
+ set_curbuf(buf, unload ? DOBUF_UNLOAD : DOBUF_GOTO, true);
}
theend:
@@ -422,7 +427,7 @@ int check_fname(void)
/// Flush the contents of a buffer, unless it has no file name.
///
/// @return FAIL for failure, OK otherwise
-int buf_write_all(buf_T *buf, int forceit)
+int buf_write_all(buf_T *buf, bool forceit)
{
buf_T *old_curbuf = curbuf;
@@ -546,7 +551,7 @@ void ex_listdo(exarg_T *eap)
break;
}
assert(wp);
- execute = !wp->w_floating || wp->w_float_config.focusable;
+ execute = !wp->w_floating || wp->w_config.focusable;
if (execute) {
win_goto(wp);
if (curwin != wp) {
@@ -743,7 +748,7 @@ void ex_checktime(exarg_T *eap)
} else {
buf_T *buf = buflist_findnr((int)eap->line2);
if (buf != NULL) { // cannot happen?
- (void)buf_check_timestamp(buf);
+ buf_check_timestamp(buf);
}
}
no_check_timestamps = save_no_check_timestamps;
@@ -762,7 +767,7 @@ static void script_host_execute(char *name, exarg_T *eap)
tv_list_append_number(args, (int)eap->line1);
tv_list_append_number(args, (int)eap->line2);
- (void)eval_call_provider(name, "execute", args, true);
+ eval_call_provider(name, "execute", args, true);
}
}
@@ -778,7 +783,7 @@ static void script_host_execute_file(char *name, exarg_T *eap)
// current range
tv_list_append_number(args, (int)eap->line1);
tv_list_append_number(args, (int)eap->line2);
- (void)eval_call_provider(name, "execute_file", args, true);
+ eval_call_provider(name, "execute_file", args, true);
}
}
@@ -789,13 +794,12 @@ static void script_host_do_range(char *name, exarg_T *eap)
tv_list_append_number(args, (int)eap->line1);
tv_list_append_number(args, (int)eap->line2);
tv_list_append_string(args, eap->arg, -1);
- (void)eval_call_provider(name, "do_range", args, true);
+ eval_call_provider(name, "do_range", args, true);
}
}
/// ":drop"
-/// Opens the first argument in a window. When there are two or more arguments
-/// the argument list is redefined.
+/// Opens the first argument in a window, and the argument list is redefined.
void ex_drop(exarg_T *eap)
{
bool split = false;
@@ -820,6 +824,8 @@ void ex_drop(exarg_T *eap)
// edited in a window yet. It's like ":tab all" but without closing
// windows or tabs.
ex_all(eap);
+ cmdmod.cmod_tab = 0;
+ ex_rewind(eap);
return;
}
@@ -840,6 +846,7 @@ void ex_drop(exarg_T *eap)
buf_check_timestamp(curbuf);
curbuf->b_p_ar = save_ar;
}
+ ex_rewind(eap);
return;
}
}
diff --git a/src/nvim/ex_cmds2.h b/src/nvim/ex_cmds2.h
index 4f41f2cc41..a35a27758c 100644
--- a/src/nvim/ex_cmds2.h
+++ b/src/nvim/ex_cmds2.h
@@ -1,7 +1,7 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
/// flags for check_changed()
enum {
diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h
index 00363884ec..827680cbb5 100644
--- a/src/nvim/ex_cmds_defs.h
+++ b/src/nvim/ex_cmds_defs.h
@@ -5,8 +5,7 @@
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_eval_defs.h"
-#include "nvim/normal_defs.h"
-#include "nvim/pos_defs.h"
+#include "nvim/os/time_defs.h"
#include "nvim/regexp_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -127,7 +126,7 @@ struct aucmd_executable_t {
typedef char *(*LineGetter)(int, void *, int, bool);
/// Structure for command definition.
-typedef struct cmdname {
+typedef struct {
char *cmd_name; ///< Name of the command.
ex_func_T cmd_func; ///< Function with implementation of this command.
ex_preview_func_T cmd_preview_func; ///< Preview callback function of this command.
@@ -229,3 +228,10 @@ typedef struct {
bool bar;
} magic;
} CmdParseInfo;
+
+/// Previous :substitute replacement string definition
+typedef struct {
+ char *sub; ///< Previous replacement string.
+ Timestamp timestamp; ///< Time when it was last set.
+ list_T *additional_elements; ///< Additional data left from ShaDa file.
+} SubReplacementString;
diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c
index 0b466bbe4e..2913f6d4e9 100644
--- a/src/nvim/ex_docmd.c
+++ b/src/nvim/ex_docmd.c
@@ -9,12 +9,15 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include "auto/config.h"
+#include "nvim/api/private/defs.h"
+#include "nvim/api/private/helpers.h"
#include "nvim/arglist.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/change.h"
@@ -28,23 +31,27 @@
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
+#include "nvim/ex_eval_defs.h"
#include "nvim/ex_getln.h"
#include "nvim/file_search.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/input.h"
#include "nvim/keycodes.h"
@@ -52,20 +59,25 @@
#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"
+#include "nvim/normal_defs.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/fs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/shell.h"
#include "nvim/path.h"
#include "nvim/popupmenu.h"
@@ -73,16 +85,20 @@
#include "nvim/profile.h"
#include "nvim/quickfix.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/search.h"
#include "nvim/shada.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
+#include "nvim/undo_defs.h"
#include "nvim/usercmd.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -190,8 +206,8 @@ static void restore_dbg_stuff(struct dbg_stuff *dsp)
trylevel = dsp->trylevel;
force_abort = dsp->force_abort;
caught_stack = dsp->caught_stack;
- (void)v_exception(dsp->vv_exception);
- (void)v_throwpoint(dsp->vv_throwpoint);
+ v_exception(dsp->vv_exception);
+ v_throwpoint(dsp->vv_throwpoint);
did_emsg = dsp->did_emsg;
got_int = dsp->got_int;
did_throw = dsp->did_throw;
@@ -293,6 +309,33 @@ static void msg_verbose_cmd(linenr_T lnum, char *cmd)
no_wait_return--;
}
+static int cmdline_call_depth = 0; ///< recursiveness
+
+/// Start executing an Ex command line.
+///
+/// @return FAIL if too recursive, OK otherwise.
+static int do_cmdline_start(void)
+{
+ assert(cmdline_call_depth >= 0);
+ // It's possible to create an endless loop with ":execute", catch that
+ // here. The value of 200 allows nested function calls, ":source", etc.
+ // Allow 200 or 'maxfuncdepth', whatever is larger.
+ if (cmdline_call_depth >= 200 && cmdline_call_depth >= p_mfd) {
+ return FAIL;
+ }
+ cmdline_call_depth++;
+ start_batch_changes();
+ return OK;
+}
+
+/// End executing an Ex command line.
+static void do_cmdline_end(void)
+{
+ cmdline_call_depth--;
+ assert(cmdline_call_depth >= 0);
+ end_batch_changes();
+}
+
/// Execute a simple command line. Used for translated commands like "*".
int do_cmdline_cmd(const char *cmd)
{
@@ -343,7 +386,6 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
char *(*cmd_getline)(int, void *, int, bool);
void *cmd_cookie;
struct loop_cookie cmd_loop_cookie;
- static int call_depth = 0; // recursiveness
// For every pair of do_cmdline()/do_one_cmd() calls, use an extra memory
// location for storing error messages to be converted to an exception.
@@ -355,10 +397,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
msg_list = &private_msg_list;
private_msg_list = NULL;
- // It's possible to create an endless loop with ":execute", catch that
- // here. The value of 200 allows nested function calls, ":source", etc.
- // Allow 200 or 'maxfuncdepth', whatever is larger.
- if (call_depth >= 200 && call_depth >= p_mfd) {
+ if (do_cmdline_start() == FAIL) {
emsg(_(e_command_too_recursive));
// When converting to an exception, we do not include the command name
// since this is not an error of the specific command.
@@ -366,8 +405,6 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
msg_list = saved_msg_list;
return FAIL;
}
- call_depth++;
- start_batch_changes();
ga_init(&lines_ga, (int)sizeof(wcmd_T), 10);
@@ -710,7 +747,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
}
// Convert an interrupt to an exception if appropriate.
- (void)do_intthrow(&cstack);
+ do_intthrow(&cstack);
// Continue executing command lines when:
// - no CTRL-C typed, no aborting error, no exception thrown or try
@@ -868,8 +905,7 @@ int do_cmdline(char *cmdline, LineGetter fgetline, void *cookie, int flags)
did_endif = false; // in case do_cmdline used recursively
- call_depth--;
- end_batch_changes();
+ do_cmdline_end();
return retval;
}
@@ -1653,9 +1689,13 @@ static int execute_cmd0(int *retv, exarg_T *eap, const char **errormsg, bool pre
/// @param preview Execute command preview callback instead of actual command
int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
{
- const char *errormsg = NULL;
int retv = 0;
+ if (do_cmdline_start() == FAIL) {
+ emsg(_(e_command_too_recursive));
+ return retv;
+ }
+ const char *errormsg = NULL;
#undef ERROR
#define ERROR(msg) \
do { \
@@ -1703,8 +1743,8 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
&& eap->addr_type == ADDR_LINES) {
// Put the first line at the start of a closed fold, put the last line
// at the end of a closed fold.
- (void)hasFolding(eap->line1, &eap->line1, NULL);
- (void)hasFolding(eap->line2, NULL, &eap->line2);
+ hasFolding(eap->line1, &eap->line1, NULL);
+ hasFolding(eap->line2, NULL, &eap->line2);
}
// Use first argument as count when possible
@@ -1712,6 +1752,9 @@ int execute_cmd(exarg_T *eap, CmdParseInfo *cmdinfo, bool preview)
goto end;
}
+ cstack_T cstack = { .cs_idx = -1 };
+ eap->cstack = &cstack;
+
// Execute the command
execute_cmd0(&retv, eap, &errormsg, preview);
@@ -1719,9 +1762,12 @@ end:
if (errormsg != NULL && *errormsg != NUL) {
emsg(errormsg);
}
+
// Undo command modifiers
undo_cmdmod(&cmdmod);
cmdmod = save_cmdmod;
+
+ do_cmdline_end();
return retv;
#undef ERROR
}
@@ -1955,7 +2001,7 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
}
if (!ea.skip && got_int) {
ea.skip = true;
- (void)do_intthrow(cstack);
+ do_intthrow(cstack);
}
// 4. Parse a range specifier of the form: addr [,addr] [;addr] ..
@@ -2167,8 +2213,8 @@ static char *do_one_cmd(char **cmdlinep, int flags, cstack_T *cstack, LineGetter
&& ea.addr_type == ADDR_LINES) {
// Put the first line at the start of a closed fold, put the last line
// at the end of a closed fold.
- (void)hasFolding(ea.line1, &ea.line1, NULL);
- (void)hasFolding(ea.line2, NULL, &ea.line2);
+ hasFolding(ea.line1, &ea.line1, NULL);
+ hasFolding(ea.line2, NULL, &ea.line2);
}
// For the ":make" and ":grep" commands we insert the 'makeprg'/'grepprg'
@@ -2651,7 +2697,7 @@ static void apply_cmdmod(cmdmod_T *cmod)
// Set 'eventignore' to "all".
// First save the existing option value for restoring it later.
cmod->cmod_save_ei = xstrdup(p_ei);
- set_string_option_direct("ei", -1, "all", OPT_FREE, SID_NONE);
+ set_string_option_direct(kOptEventignore, "all", 0, SID_NONE);
}
}
@@ -2671,7 +2717,7 @@ void undo_cmdmod(cmdmod_T *cmod)
if (cmod->cmod_save_ei != NULL) {
// Restore 'eventignore' to the value before ":noautocmd".
- set_string_option_direct("ei", -1, cmod->cmod_save_ei, OPT_FREE, SID_NONE);
+ set_string_option_direct(kOptEventignore, cmod->cmod_save_ei, 0, SID_NONE);
free_string_option(cmod->cmod_save_ei);
cmod->cmod_save_ei = NULL;
}
@@ -3256,7 +3302,7 @@ static const char *addr_error(cmd_addr_T addr_type)
/// @param errormsg Error message, if any
///
/// @return MAXLNUM when no Ex address was found.
-static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int skip, bool silent,
+static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, bool skip, bool silent,
int to_other_file, int address_count, const char **errormsg)
FUNC_ATTR_NONNULL_ALL
{
@@ -3376,7 +3422,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
fmark_T *fm = mark_get(curbuf, curwin, NULL, flag, *cmd);
cmd++;
if (fm != NULL && fm->fnum != curbuf->handle) {
- (void)mark_move_to(fm, 0);
+ mark_move_to(fm, 0);
// Jumped to another file.
lnum = curwin->w_cursor.lnum;
} else {
@@ -3550,7 +3596,7 @@ static linenr_T get_address(exarg_T *eap, char **ptr, cmd_addr_T addr_type, int
// closed fold after the first address.
if (addr_type == ADDR_LINES && (i == '-' || i == '+')
&& address_count >= 2) {
- (void)hasFolding(lnum, NULL, &lnum);
+ hasFolding(lnum, NULL, &lnum);
}
if (i == '-') {
lnum -= n;
@@ -3777,12 +3823,12 @@ int expand_filename(exarg_T *eap, char **cmdlinep, const char **errormsgp)
// Decide to expand wildcards *before* replacing '%', '#', etc. If
// the file name contains a wildcard it should not cause expanding.
// (it will be expanded anyway if there is a wildcard before replacing).
- int has_wildcards = path_has_wildcard(p);
+ bool has_wildcards = path_has_wildcard(p);
while (*p != NUL) {
// Skip over `=expr`, wildcards in it are not expanded.
if (p[0] == '`' && p[1] == '=') {
p += 2;
- (void)skip_expr(&p, NULL);
+ skip_expr(&p, NULL);
if (*p == '`') {
p++;
}
@@ -3857,9 +3903,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, const char **errormsgp)
|| eap->cmdidx == CMD_bang
|| eap->cmdidx == CMD_terminal)
&& strpbrk(repl, "!") != NULL) {
- char *l;
-
- l = vim_strsave_escaped(repl, "!");
+ char *l = vim_strsave_escaped(repl, "!");
xfree(repl);
repl = l;
}
@@ -3887,7 +3931,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, const char **errormsgp)
p = NULL;
}
if (p != NULL) {
- (void)repl_cmdline(eap, eap->arg, strlen(eap->arg), p, cmdlinep);
+ repl_cmdline(eap, eap->arg, strlen(eap->arg), p, cmdlinep);
}
}
@@ -3915,7 +3959,7 @@ int expand_filename(exarg_T *eap, char **cmdlinep, const char **errormsgp)
if (p == NULL) {
return FAIL;
}
- (void)repl_cmdline(eap, eap->arg, strlen(eap->arg), p, cmdlinep);
+ repl_cmdline(eap, eap->arg, strlen(eap->arg), p, cmdlinep);
xfree(p);
}
}
@@ -4001,7 +4045,7 @@ void separate_nextcmd(exarg_T *eap)
} else if (p[0] == '`' && p[1] == '=' && (eap->argt & EX_XFILE)) {
// Skip over `=expr` when wildcards are expanded.
p += 2;
- (void)skip_expr(&p, NULL);
+ skip_expr(&p, NULL);
if (*p == NUL) { // stop at NUL after CTRL-V
break;
}
@@ -4060,7 +4104,7 @@ static char *getargcmd(char **argp)
/// Find end of "+command" argument. Skip over "\ " and "\\".
///
/// @param rembs true to halve the number of backslashes
-char *skip_cmd_arg(char *p, int rembs)
+char *skip_cmd_arg(char *p, bool rembs)
{
while (*p && !ascii_isspace(*p)) {
if (*p == '\\' && p[1] != NUL) {
@@ -4373,7 +4417,7 @@ static void ex_doautocmd(exarg_T *eap)
int call_do_modelines = check_nomodeline(&arg);
bool did_aucmd;
- (void)do_doautocmd(arg, false, &did_aucmd);
+ do_doautocmd(arg, false, &did_aucmd);
// Only when there is no <nomodeline>.
if (call_do_modelines && did_aucmd) {
do_modelines(0);
@@ -4505,7 +4549,7 @@ char *check_nextcmd(char *p)
/// @param message when false check only, no messages
///
/// @return FAIL and give error message if 'message' true, return OK otherwise
-static int check_more(int message, bool forceit)
+static int check_more(bool message, bool forceit)
{
int n = ARGCOUNT - curwin->w_arg_idx - 1;
@@ -5368,9 +5412,9 @@ void do_exedit(exarg_T *eap, win_T *old_curwin)
|| eap->cmdidx == CMD_vnew) && *eap->arg == NUL) {
// ":new" or ":tabnew" without argument: edit a new empty buffer
setpcmark();
- (void)do_ecmd(0, NULL, NULL, eap, ECMD_ONE,
- ECMD_HIDE + (eap->forceit ? ECMD_FORCEIT : 0),
- old_curwin == NULL ? curwin : NULL);
+ do_ecmd(0, NULL, NULL, eap, ECMD_ONE,
+ ECMD_HIDE + (eap->forceit ? ECMD_FORCEIT : 0),
+ old_curwin == NULL ? curwin : NULL);
} else if ((eap->cmdidx != CMD_split && eap->cmdidx != CMD_vsplit)
|| *eap->arg != NUL) {
// Can't edit another file when "textlock" or "curbuf->b_ro_locked" is set.
@@ -5552,7 +5596,7 @@ static void ex_read(exarg_T *eap)
eap->line2, 0, (linenr_T)MAXLNUM, eap, 0, false);
} else {
if (vim_strchr(p_cpo, CPO_ALTREAD) != NULL) {
- (void)setaltfname(eap->arg, eap->arg, 1);
+ setaltfname(eap->arg, eap->arg, 1);
}
i = readfile(eap->arg, NULL,
eap->line2, 0, (linenr_T)MAXLNUM, eap, 0, false);
@@ -5823,7 +5867,7 @@ void do_sleep(int64_t msec)
// If CTRL-C was typed to interrupt the sleep, drop the CTRL-C from the
// input buffer, otherwise a following call to input() fails.
if (got_int) {
- (void)vpeekc();
+ vpeekc();
}
}
@@ -5908,7 +5952,7 @@ static void ex_operators(exarg_T *eap)
case CMD_yank:
oa.op_type = OP_YANK;
- (void)op_yank(&oa, true);
+ op_yank(&oa, true);
break;
default: // CMD_rshift or CMD_lshift
@@ -6050,7 +6094,7 @@ static void ex_at(exarg_T *eap)
// Continue until the stuff buffer is empty and all added characters
// have been consumed.
while (!stuff_empty() || typebuf.tb_len > prev_len) {
- (void)do_cmdline(NULL, getexline, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
+ do_cmdline(NULL, getexline, NULL, DOCMD_NOWAIT|DOCMD_VERBOSE);
}
exec_from_reg = save_efr;
@@ -6210,7 +6254,7 @@ static void ex_redir(exarg_T *eap)
semsg(_(e_invarg2), eap->arg);
}
} else if (*arg == '=' && arg[1] == '>') {
- int append;
+ bool append;
// redirect to a variable
close_redir();
@@ -6224,7 +6268,7 @@ static void ex_redir(exarg_T *eap)
}
if (var_redir_start(skipwhite(arg), append) == OK) {
- redir_vname = 1;
+ redir_vname = true;
}
} else { // TODO(vim): redirect to a buffer
semsg(_(e_invarg2), eap->arg);
@@ -6330,7 +6374,7 @@ static void close_redir(void)
redir_reg = 0;
if (redir_vname) {
var_redir_stop();
- redir_vname = 0;
+ redir_vname = false;
}
}
@@ -7171,7 +7215,7 @@ static void ex_shada(exarg_T *eap)
p_shada = "'100";
}
if (eap->cmdidx == CMD_rviminfo || eap->cmdidx == CMD_rshada) {
- (void)shada_read_everything(eap->arg, eap->forceit, false);
+ shada_read_everything(eap->arg, eap->forceit, false);
} else {
shada_write_file(eap->arg, eap->forceit);
}
@@ -7242,7 +7286,7 @@ static void ex_filetype(exarg_T *eap)
}
}
if (*arg == 'd') {
- (void)do_doautocmd("filetypedetect BufRead", true, NULL);
+ do_doautocmd("filetypedetect BufRead", true, NULL);
do_modelines(0);
}
} else if (strcmp(arg, "off") == 0) {
@@ -7304,7 +7348,7 @@ static void ex_setfiletype(exarg_T *eap)
arg += 9;
}
- set_option_value_give_err("filetype", CSTR_AS_OPTVAL(arg), OPT_LOCAL);
+ set_option_value_give_err(kOptFiletype, CSTR_AS_OPTVAL(arg), OPT_LOCAL);
if (arg != eap->arg) {
did_filetype = false;
}
@@ -7383,6 +7427,44 @@ void set_pressedreturn(bool val)
ex_pressedreturn = val;
}
+/// ":checkhealth [plugins]"
+static void ex_checkhealth(exarg_T *eap)
+{
+ Error err = ERROR_INIT;
+ MAXSIZE_TEMP_ARRAY(args, 2);
+
+ char mods[1024];
+ size_t mods_len = 0;
+ mods[0] = NUL;
+
+ if (cmdmod.cmod_tab > 0 || cmdmod.cmod_split != 0) {
+ bool multi_mods = false;
+ mods_len = add_win_cmd_modifiers(mods, &cmdmod, &multi_mods);
+ assert(mods_len < sizeof(mods));
+ }
+ ADD_C(args, STRING_OBJ(((String){ .data = mods, .size = mods_len })));
+ ADD_C(args, CSTR_AS_OBJ(eap->arg));
+
+ NLUA_EXEC_STATIC("vim.health._check(...)", args, kRetNilBool, NULL, &err);
+ if (!ERROR_SET(&err)) {
+ return;
+ }
+
+ const char *vimruntime_env = os_getenv("VIMRUNTIME");
+ if (vimruntime_env == NULL) {
+ emsg(_("E5009: $VIMRUNTIME is empty or unset"));
+ } else {
+ bool rtp_ok = NULL != strstr(p_rtp, vimruntime_env);
+ if (rtp_ok) {
+ semsg(_("E5009: Invalid $VIMRUNTIME: %s"), vimruntime_env);
+ } else {
+ emsg(_("E5009: Invalid 'runtimepath'"));
+ }
+ }
+ semsg_multiline(err.msg);
+ api_clear_error(&err);
+}
+
static void ex_terminal(exarg_T *eap)
{
char ex_cmd[1024];
@@ -7390,10 +7472,8 @@ static void ex_terminal(exarg_T *eap)
if (cmdmod.cmod_tab > 0 || cmdmod.cmod_split != 0) {
bool multi_mods = false;
-
- // ex_cmd must be a null terminated string before passing to add_win_cmd_modifiers
- ex_cmd[0] = '\0';
-
+ // ex_cmd must be a null-terminated string before passing to add_win_cmd_modifiers
+ ex_cmd[0] = NUL;
len = add_win_cmd_modifiers(ex_cmd, &cmdmod, &multi_mods);
assert(len < sizeof(ex_cmd));
int result = snprintf(ex_cmd + len, sizeof(ex_cmd) - len, " new");
@@ -7424,7 +7504,9 @@ static void ex_terminal(exarg_T *eap)
char shell_argv[512] = { 0 };
while (*p != NULL) {
- snprintf(tempstring, sizeof(tempstring), ",\"%s\"", *p);
+ char *escaped = vim_strsave_escaped(*p, "\"\\");
+ snprintf(tempstring, sizeof(tempstring), ",\"%s\"", escaped);
+ xfree(escaped);
xstrlcat(shell_argv, tempstring, sizeof(shell_argv));
p++;
}
diff --git a/src/nvim/ex_docmd.h b/src/nvim/ex_docmd.h
index 698153e8df..ce23b9f464 100644
--- a/src/nvim/ex_docmd.h
+++ b/src/nvim/ex_docmd.h
@@ -6,8 +6,8 @@
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/getchar_defs.h"
-#include "nvim/globals.h"
#include "nvim/types_defs.h" // IWYU pragma: keep
+#include "nvim/vim_defs.h" // IWYU pragma: keep
/// flags for do_cmdline()
enum {
diff --git a/src/nvim/ex_eval.c b/src/nvim/ex_eval.c
index d2a1d53b78..472741d537 100644
--- a/src/nvim/ex_eval.c
+++ b/src/nvim/ex_eval.c
@@ -13,19 +13,22 @@
#include "nvim/debugger.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
+#include "nvim/eval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
#include "nvim/ex_eval_defs.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option_vars.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/strings.h"
#include "nvim/vim_defs.h"
@@ -93,7 +96,7 @@ static void discard_pending_return(typval_T *p)
// expression evaluation is done without producing any error messages, but all
// error messages on parsing errors during the expression evaluation are given
// (even if a try conditional is active).
-static int cause_abort = false;
+static bool cause_abort = false;
/// @return true when immediately aborting on error, or when an interrupt
/// occurred or an exception was thrown but not caught.
@@ -106,7 +109,7 @@ static int cause_abort = false;
/// That is, during cancellation of an expression evaluation after an aborting
/// function call or due to a parsing error, aborting() always returns the same
/// value. "got_int" is also set by calling interrupt().
-int aborting(void)
+bool aborting(void)
{
return (did_emsg && force_abort) || got_int || did_throw;
}
@@ -126,7 +129,7 @@ void update_force_abort(void)
/// abort the script processing. Can be used to suppress an autocommand after
/// execution of a failing subcommand as long as the error message has not been
/// displayed and actually caused the abortion.
-int should_abort(int retcode)
+bool should_abort(int retcode)
{
return (retcode == FAIL && trylevel != 0 && !emsg_silent) || aborting();
}
@@ -135,7 +138,7 @@ int should_abort(int retcode)
/// ended on an error. This means that parsing commands is continued in order
/// to find finally clauses to be executed, and that some errors in skipped
/// commands are still reported.
-int aborted_in_try(void)
+bool aborted_in_try(void)
FUNC_ATTR_PURE
{
// This function is only called after an error. In this case, "force_abort"
@@ -224,7 +227,7 @@ bool cause_errthrow(const char *mesg, bool multiline, bool severe, bool *ignore)
// catch clause; just finally clauses are executed before the script
// is terminated.
return false;
- } else // NOLINT(readability/braces)
+ } else
#endif
{
// Prepare the throw of an error exception, so that everything will
@@ -327,7 +330,7 @@ void do_errthrow(cstack_T *cstack, char *cmdname)
///
/// @return true if the current exception is discarded or,
/// false otherwise.
-int do_intthrow(cstack_T *cstack)
+bool do_intthrow(cstack_T *cstack)
{
// If no interrupt occurred or no try conditional is active and no exception
// is being thrown, do nothing (for compatibility of non-EH scripts).
@@ -370,7 +373,7 @@ int do_intthrow(cstack_T *cstack)
}
/// Get an exception message that is to be stored in current_exception->value.
-char *get_exception_string(void *value, except_type_T type, char *cmdname, int *should_free)
+char *get_exception_string(void *value, except_type_T type, char *cmdname, bool *should_free)
{
char *ret;
@@ -455,7 +458,7 @@ static int throw_exception(void *value, except_type_T type, char *cmdname)
excp->messages = (msglist_T *)value;
}
- int should_free;
+ bool should_free;
excp->value = get_exception_string(value, type, cmdname, &should_free);
if (excp->value == NULL && should_free) {
goto nomem;
@@ -842,10 +845,10 @@ void ex_if(exarg_T *eap)
cstack->cs_idx++;
cstack->cs_flags[cstack->cs_idx] = 0;
- int skip = CHECK_SKIP;
+ bool skip = CHECK_SKIP;
bool error;
- int result = eval_to_bool(eap->arg, &error, eap, skip);
+ bool result = eval_to_bool(eap->arg, &error, eap, skip);
if (!skip && !error) {
if (result) {
@@ -876,7 +879,7 @@ void ex_endif(exarg_T *eap)
// discarded by throwing the interrupt exception later on.
if (!(eap->cstack->cs_flags[eap->cstack->cs_idx] & CSF_TRUE)
&& dbg_check_skipped(eap)) {
- (void)do_intthrow(eap->cstack);
+ do_intthrow(eap->cstack);
}
eap->cstack->cs_idx--;
@@ -927,7 +930,7 @@ void ex_else(exarg_T *eap)
// for a parsing errors is discarded when throwing the interrupt exception
// later on.
if (!skip && dbg_check_skipped(eap) && got_int) {
- (void)do_intthrow(cstack);
+ do_intthrow(cstack);
skip = true;
}
@@ -972,7 +975,7 @@ void ex_while(exarg_T *eap)
if (cstack->cs_idx == CSTACK_LEN - 1) {
eap->errmsg = _("E585: :while/:for nesting too deep");
} else {
- int result;
+ bool result;
// The loop flag is set when we have jumped back from the matching
// ":endwhile" or ":endfor". When not set, need to initialise this
// cstack entry.
@@ -1133,7 +1136,7 @@ void ex_endwhile(exarg_T *eap)
}
}
// Cleanup and rewind all contained (and unclosed) conditionals.
- (void)cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, false);
+ cleanup_conditionals(cstack, CSF_WHILE | CSF_FOR, false);
rewind_conditionals(cstack, idx, CSF_TRY, &cstack->cs_trylevel);
} else if (cstack->cs_flags[cstack->cs_idx] & CSF_TRUE
&& !(cstack->cs_flags[cstack->cs_idx] & CSF_ACTIVE)
@@ -1146,7 +1149,7 @@ void ex_endwhile(exarg_T *eap)
// throw an interrupt exception if appropriate. Doing this here
// prevents that an exception for a parsing error is discarded when
// throwing the interrupt exception later on.
- (void)do_intthrow(cstack);
+ do_intthrow(cstack);
}
// Set loop flag, so do_cmdline() will jump back to the matching
@@ -1184,7 +1187,7 @@ void ex_throw(exarg_T *eap)
/// used for rethrowing an uncaught exception.
void do_throw(cstack_T *cstack)
{
- int inactivate_try = false;
+ bool inactivate_try = false;
// Cleanup and deactivate up to the next surrounding try conditional that
// is not in its finally clause. Normally, do not deactivate the try
@@ -1477,7 +1480,7 @@ void ex_finally(exarg_T *eap)
// occurred before the ":finally". That is, discard the
// original exception and replace it by an interrupt
// exception.
- (void)do_intthrow(cstack);
+ do_intthrow(cstack);
}
// If there is a preceding catch clause and it caught the exception,
@@ -1618,7 +1621,7 @@ void ex_endtry(exarg_T *eap)
// set "skip" and "rethrow".
if (got_int) {
skip = true;
- (void)do_intthrow(cstack);
+ do_intthrow(cstack);
// The do_intthrow() call may have reset did_throw or
// cstack->cs_pending[idx].
rethrow = false;
@@ -1650,7 +1653,7 @@ void ex_endtry(exarg_T *eap)
// was no finally clause, finish the exception now. This happens also
// after errors except when this ":endtry" is not within a ":try".
// Restore "emsg_silent" if it has been reset by this try conditional.
- (void)cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, true);
+ cleanup_conditionals(cstack, CSF_TRY | CSF_SILENT, true);
if (cstack->cs_idx >= 0 && (cstack->cs_flags[cstack->cs_idx] & CSF_TRY)) {
cstack->cs_idx--;
@@ -1862,7 +1865,7 @@ void leave_cleanup(cleanup_T *csp)
int cleanup_conditionals(cstack_T *cstack, int searched_cond, int inclusive)
{
int idx;
- int stop = false;
+ bool stop = false;
for (idx = cstack->cs_idx; idx >= 0; idx--) {
if (cstack->cs_flags[idx] & CSF_TRY) {
@@ -1999,7 +2002,7 @@ void ex_endfunction(exarg_T *eap)
}
/// @return true if the string "p" looks like a ":while" or ":for" command.
-int has_loop_cmd(char *p)
+bool has_loop_cmd(char *p)
{
// skip modifiers, white space and ':'
while (true) {
diff --git a/src/nvim/ex_eval.h b/src/nvim/ex_eval.h
index 0294acd109..d46d9c695a 100644
--- a/src/nvim/ex_eval.h
+++ b/src/nvim/ex_eval.h
@@ -1,7 +1,7 @@
#pragma once
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
-#include "nvim/ex_eval_defs.h" // IWYU pragma: export
+#include "nvim/ex_eval_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ex_eval.h.generated.h"
diff --git a/src/nvim/ex_eval_defs.h b/src/nvim/ex_eval_defs.h
index c7231bb315..3f5e510a20 100644
--- a/src/nvim/ex_eval_defs.h
+++ b/src/nvim/ex_eval_defs.h
@@ -13,9 +13,11 @@ struct eslist_elem {
eslist_T *next; ///< next element on the list
};
-/// For conditional commands a stack is kept of nested conditionals.
-/// When cs_idx < 0, there is no conditional command.
-enum { CSTACK_LEN = 50, };
+enum {
+ /// For conditional commands a stack is kept of nested conditionals.
+ /// When cs_idx < 0, there is no conditional command.
+ CSTACK_LEN = 50,
+};
typedef struct {
int cs_flags[CSTACK_LEN]; ///< CSF_ flags
diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c
index 64ef17b157..44a78711d2 100644
--- a/src/nvim/ex_getln.c
+++ b/src/nvim/ex_getln.c
@@ -17,9 +17,12 @@
#include "nvim/arabic.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
+#include "nvim/cmdexpand_defs.h"
#include "nvim/cmdhist.h"
#include "nvim/cursor.h"
#include "nvim/digraph.h"
@@ -34,21 +37,24 @@
#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
#include "nvim/extmark.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
#include "nvim/map_defs.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
@@ -65,16 +71,21 @@
#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/search.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/undo.h"
+#include "nvim/undo_defs.h"
#include "nvim/usercmd.h"
#include "nvim/vim_defs.h"
#include "nvim/viml/parser/expressions.h"
#include "nvim/viml/parser/parser.h"
+#include "nvim/viml/parser/parser_defs.h"
#include "nvim/window.h"
/// Last value of prompt_id, incremented when doing new prompt
@@ -104,13 +115,13 @@ typedef struct {
optmagic_T magic_overruled_save;
} incsearch_state_T;
-typedef struct command_line_state {
+typedef struct {
VimState state;
int firstc;
int count;
int indent;
int c;
- int gotesc; // true when <ESC> just typed
+ bool gotesc; // true when <ESC> just typed
int do_abbr; // when true check for abbr.
char *lookfor; // string to match
int hiscnt; // current history line in use
@@ -133,7 +144,7 @@ typedef struct command_line_state {
buf_T *b_im_ptr_buf; ///< buffer where b_im_ptr is valid
} CommandLineState;
-typedef struct cmdpreview_undo_info {
+typedef struct {
u_header_T *save_b_u_oldhead;
u_header_T *save_b_u_newhead;
u_header_T *save_b_u_curhead;
@@ -149,15 +160,17 @@ typedef struct cmdpreview_undo_info {
colnr_T save_b_u_line_colnr;
} CpUndoInfo;
-typedef struct cmdpreview_buf_info {
+typedef struct {
buf_T *buf;
OptInt save_b_p_ul;
int save_b_changed;
+ pos_T save_b_op_start;
+ pos_T save_b_op_end;
varnumber_T save_changedtick;
CpUndoInfo undo_info;
} CpBufInfo;
-typedef struct cmdpreview_win_info {
+typedef struct {
win_T *win;
pos_T save_w_cursor;
viewstate_T save_viewstate;
@@ -165,7 +178,7 @@ typedef struct cmdpreview_win_info {
int save_w_p_cuc;
} CpWinInfo;
-typedef struct cmdpreview_info {
+typedef struct {
kvec_t(CpWinInfo) win_info;
kvec_t(CpBufInfo) buf_info;
bool save_hls;
@@ -206,6 +219,9 @@ static int cedit_key = -1; ///< key value of 'cedit' option
static handle_T cmdpreview_bufnr = 0;
static int cmdpreview_ns = 0;
+static const char e_active_window_or_buffer_changed_or_deleted[]
+ = N_("E199: Active window or buffer changed or deleted");
+
static void save_viewstate(win_T *wp, viewstate_T *vs)
FUNC_ATTR_NONNULL_ALL
{
@@ -467,7 +483,7 @@ static void may_do_incsearch_highlighting(int firstc, int count, incsearch_state
// if interrupted while searching, behave like it failed
if (got_int) {
- (void)vpeekc(); // remove <C-C> from input stream
+ vpeekc(); // remove <C-C> from input stream
got_int = false; // don't abandon the command line
found = 0;
} else if (char_avail()) {
@@ -583,7 +599,8 @@ static int may_add_char_to_search(int firstc, int *c, incsearch_state_T *s)
return OK;
}
-static void finish_incsearch_highlighting(int gotesc, incsearch_state_T *s, bool call_update_screen)
+static void finish_incsearch_highlighting(bool gotesc, incsearch_state_T *s,
+ bool call_update_screen)
{
if (!s->did_incsearch) {
return;
@@ -839,7 +856,7 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear
// error printed below, to avoid redraw issues
tl_ret = try_leave(&tstate, &err);
if (tv_dict_get_number(dict, "abort") != 0) {
- s->gotesc = 1;
+ s->gotesc = true;
}
restore_v_event(dict, &save_v_event);
}
@@ -885,9 +902,7 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear
// not get printed in the middle of it.
msg_check();
if (p_ch == 0 && !ui_has(kUIMessages)) {
- if (must_redraw < UPD_VALID) {
- must_redraw = UPD_VALID;
- }
+ set_must_redraw(UPD_VALID);
}
msg_scroll = s->save_msg_scroll;
redir_off = false;
@@ -904,7 +919,7 @@ static uint8_t *command_line_enter(int firstc, int count, int indent, bool clear
need_wait_return = false;
}
- set_string_option_direct("icm", -1, s->save_p_icm, OPT_FREE, SID_NONE);
+ set_string_option_direct(kOptInccommand, s->save_p_icm, 0, SID_NONE);
State = s->save_State;
if (cmdpreview != save_cmdpreview) {
cmdpreview = save_cmdpreview; // restore preview state
@@ -1051,7 +1066,7 @@ static int command_line_wildchar_complete(CommandLineState *s)
&& !s->did_wild_list
&& ((wim_flags[s->wim_index] & WIM_LIST)
|| (p_wmnu && (wim_flags[s->wim_index] & WIM_FULL) != 0))) {
- (void)showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0));
+ showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0));
redrawcmd();
s->did_wild_list = true;
}
@@ -1077,9 +1092,9 @@ static int command_line_wildchar_complete(CommandLineState *s)
// if interrupted while completing, behave like it failed
if (got_int) {
- (void)vpeekc(); // remove <C-C> from input stream
+ vpeekc(); // remove <C-C> from input stream
got_int = false; // don't abandon the command line
- (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE);
+ ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE);
s->xpc.xp_context = EXPAND_NOTHING;
return CMDLINE_CHANGED;
}
@@ -1103,7 +1118,7 @@ static int command_line_wildchar_complete(CommandLineState *s)
p_wmnu = p_wmnu_save;
}
- (void)showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0));
+ showmatches(&s->xpc, p_wmnu && ((wim_flags[s->wim_index] & WIM_LIST) == 0));
redrawcmd();
s->did_wild_list = true;
@@ -1137,7 +1152,7 @@ static void command_line_end_wildmenu(CommandLineState *s)
cmdline_pum_remove();
}
if (s->xpc.xp_numfiles != -1) {
- (void)ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE);
+ ExpandOne(&s->xpc, NULL, NULL, 0, WILD_FREE);
}
s->did_wild_list = false;
if (!p_wmnu || (s->c != K_UP && s->c != K_DOWN)) {
@@ -1249,7 +1264,7 @@ static int command_line_execute(VimState *state, int key)
// Ctrl-E: cancel the cmdline popup menu and return the original text.
if (s->c == Ctrl_E || s->c == Ctrl_Y) {
wild_type = (s->c == Ctrl_E) ? WILD_CANCEL : WILD_APPLY;
- (void)nextwild(&s->xpc, wild_type, WILD_NO_BEEP, s->firstc != '@');
+ nextwild(&s->xpc, wild_type, WILD_NO_BEEP, s->firstc != '@');
}
}
@@ -1418,7 +1433,7 @@ static int may_do_command_line_next_incsearch(int firstc, int count, incsearch_s
if (lt(s->match_start, s->match_end)) {
// start searching at the end of the match
// not at the beginning of the next column
- (void)decl(&t);
+ decl(&t);
}
search_flags += SEARCH_COL;
} else {
@@ -1446,21 +1461,21 @@ static int may_do_command_line_next_incsearch(int firstc, int count, incsearch_s
// when nv_search finishes the cursor will be
// put back on the match
s->search_start = t;
- (void)decl(&s->search_start);
+ decl(&s->search_start);
} else if (next_match && firstc == '?') {
// move just after the current match, so that
// when nv_search finishes the cursor will be
// put back on the match
s->search_start = t;
- (void)incl(&s->search_start);
+ incl(&s->search_start);
}
if (lt(t, s->search_start) && next_match) {
// wrap around
s->search_start = t;
if (firstc == '?') {
- (void)incl(&s->search_start);
+ incl(&s->search_start);
} else {
- (void)decl(&s->search_start);
+ decl(&s->search_start);
}
}
@@ -1495,10 +1510,8 @@ static int command_line_erase_chars(CommandLineState *s)
if (s->c == K_DEL && ccline.cmdpos != ccline.cmdlen) {
ccline.cmdpos++;
}
-
if (s->c == K_DEL) {
- ccline.cmdpos += mb_off_next(ccline.cmdbuff,
- ccline.cmdbuff + ccline.cmdpos);
+ ccline.cmdpos += mb_off_next(ccline.cmdbuff, ccline.cmdbuff + ccline.cmdpos);
}
if (ccline.cmdpos > 0) {
@@ -2175,7 +2188,7 @@ static bool empty_pattern(char *p, int delim)
magic_T magic_val = MAGIC_ON;
if (n > 0) {
- (void)skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic_val);
+ skip_regexp_ex(p, delim, magic_isset(), NULL, NULL, &magic_val);
} else {
return true;
}
@@ -2263,6 +2276,7 @@ static buf_T *cmdpreview_open_buf(void)
///
/// @return Pointer to command preview window if succeeded, NULL if failed.
static win_T *cmdpreview_open_win(buf_T *cmdpreview_buf)
+ FUNC_ATTR_NONNULL_ALL
{
win_T *save_curwin = curwin;
@@ -2361,6 +2375,8 @@ static void cmdpreview_prepare(CpInfo *cpinfo)
cp_bufinfo.buf = buf;
cp_bufinfo.save_b_p_ul = buf->b_p_ul;
cp_bufinfo.save_b_changed = buf->b_changed;
+ cp_bufinfo.save_b_op_start = buf->b_op_start;
+ cp_bufinfo.save_b_op_end = buf->b_op_end;
cp_bufinfo.save_changedtick = buf_get_changedtick(buf);
cmdpreview_save_undo(&cp_bufinfo.undo_info, buf);
kv_push(cpinfo->buf_info, cp_bufinfo);
@@ -2439,6 +2455,9 @@ static void cmdpreview_restore_state(CpInfo *cpinfo)
u_blockfree(buf);
cmdpreview_restore_undo(&cp_bufinfo.undo_info, buf);
+ buf->b_op_start = cp_bufinfo.save_b_op_start;
+ buf->b_op_end = cp_bufinfo.save_b_op_end;
+
if (cp_bufinfo.save_changedtick != buf_get_changedtick(buf)) {
buf_set_changedtick(buf, cp_bufinfo.save_changedtick);
}
@@ -2529,10 +2548,10 @@ static bool cmdpreview_may_show(CommandLineState *s)
cmdpreview_prepare(&cpinfo);
// Open preview buffer if inccommand=split.
- if (!icm_split) {
- cmdpreview_bufnr = 0;
- } else if ((cmdpreview_buf = cmdpreview_open_buf()) == NULL) {
- abort();
+ if (icm_split && (cmdpreview_buf = cmdpreview_open_buf()) == NULL) {
+ // Failed to create preview buffer, so disable preview.
+ set_string_option_direct(kOptInccommand, "nosplit", 0, SID_NONE);
+ icm_split = false;
}
// Setup preview namespace if it's not already set.
if (!cmdpreview_ns) {
@@ -2627,6 +2646,7 @@ static int command_line_changed(CommandLineState *s)
if (s->firstc == ':'
&& current_sctx.sc_sid == 0 // only if interactive
&& *p_icm != NUL // 'inccommand' is set
+ && !exmode_active // not in ex mode
&& curbuf->b_p_ma // buffer is modifiable
&& cmdline_star == 0 // not typing a password
&& !vpeekc_any()
@@ -2932,7 +2952,7 @@ char *getexline(int c, void *cookie, int indent, bool do_concat)
{
// When executing a register, remove ':' that's in front of each line.
if (exec_from_reg && vpeekc() == ':') {
- (void)vgetc();
+ vgetc();
}
return getcmdline(c, 1, indent, do_concat);
@@ -3447,7 +3467,7 @@ void cmdline_ui_flush(void)
// Put a character on the command line. Shifts the following text to the
// right when "shift" is true. Used for CTRL-V, CTRL-K, etc.
// "c" must be printable (fit in one display cell)!
-void putcmdline(char c, int shift)
+void putcmdline(char c, bool shift)
{
if (cmd_silent) {
return;
@@ -3494,7 +3514,7 @@ void unputcmdline(void)
// part will be redrawn, otherwise it will not. If this function is called
// twice in a row, then 'redraw' should be false and redrawcmd() should be
// called afterwards.
-void put_on_cmdline(const char *str, int len, int redraw)
+void put_on_cmdline(const char *str, int len, bool redraw)
{
int i;
int m;
@@ -3704,7 +3724,7 @@ static bool cmdline_paste(int regname, bool literally, bool remcr)
// When "literally" is true, insert literally.
// When "literally" is false, insert as typed, but don't leave the command
// line.
-void cmdline_paste_str(const char *s, int literally)
+void cmdline_paste_str(const char *s, bool literally)
{
if (literally) {
put_on_cmdline(s, -1, true);
@@ -4200,7 +4220,7 @@ int get_cmdline_firstc(void)
int get_list_range(char **str, int *num1, int *num2)
{
int len;
- int first = false;
+ bool first = false;
varnumber_T num;
*str = skipwhite((*str));
@@ -4274,7 +4294,7 @@ static int open_cmdwin(void)
int save_restart_edit = restart_edit;
int save_State = State;
bool save_exmode = exmode_active;
- int save_cmdmsg_rl = cmdmsg_rl;
+ bool save_cmdmsg_rl = cmdmsg_rl;
// Can't do this when text or buffer is locked.
// Can't do this recursively. Can't do it when typing a password.
@@ -4302,25 +4322,52 @@ static int open_cmdwin(void)
ga_clear(&winsizes);
return K_IGNORE;
}
+ // win_split() autocommands may have messed with the old window or buffer.
+ // Treat it as abandoning this command-line.
+ if (!win_valid(old_curwin) || curwin == old_curwin || !bufref_valid(&old_curbuf)
+ || old_curwin->w_buffer != old_curbuf.br_buf) {
+ beep_flush();
+ ga_clear(&winsizes);
+ return Ctrl_C;
+ }
// Don't let quitting the More prompt make this fail.
got_int = false;
- // Set "cmdwin_type" before any autocommands may mess things up.
+ // Set "cmdwin_..." variables before any autocommands may mess things up.
cmdwin_type = get_cmdline_type();
cmdwin_level = ccline.level;
+ cmdwin_win = curwin;
cmdwin_old_curwin = old_curwin;
- // Create empty command-line buffer.
- if (buf_open_scratch(0, _("[Command Line]")) == FAIL) {
- // Some autocommand messed it up?
- win_close(curwin, true, false);
- ga_clear(&winsizes);
+ // Create empty command-line buffer. Be especially cautious of BufLeave
+ // autocommands from do_ecmd(), as cmdwin restrictions do not apply to them!
+ const int newbuf_status = buf_open_scratch(0, NULL);
+ const bool cmdwin_valid = win_valid(cmdwin_win);
+ if (newbuf_status == FAIL || !cmdwin_valid || curwin != cmdwin_win || !win_valid(old_curwin)
+ || !bufref_valid(&old_curbuf) || old_curwin->w_buffer != old_curbuf.br_buf) {
+ if (newbuf_status == OK) {
+ set_bufref(&bufref, curbuf);
+ }
+ if (cmdwin_valid && !last_window(cmdwin_win)) {
+ win_close(cmdwin_win, true, false);
+ }
+ // win_close() autocommands may have already deleted the buffer.
+ if (newbuf_status == OK && bufref_valid(&bufref) && bufref.br_buf != curbuf) {
+ close_buffer(NULL, bufref.br_buf, DOBUF_WIPE, false, false);
+ }
+
cmdwin_type = 0;
+ cmdwin_level = 0;
+ cmdwin_win = NULL;
cmdwin_old_curwin = NULL;
+ beep_flush();
+ ga_clear(&winsizes);
return Ctrl_C;
}
+ cmdwin_buf = curbuf;
+
// Command-line buffer has bufhidden=wipe, unlike a true "scratch" buffer.
- set_option_value_give_err("bh", STATIC_CSTR_AS_OPTVAL("wipe"), OPT_LOCAL);
+ set_option_value_give_err(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("wipe"), OPT_LOCAL);
curbuf->b_p_ma = true;
curwin->w_p_fen = false;
curwin->w_p_rl = cmdmsg_rl;
@@ -4338,7 +4385,7 @@ static int open_cmdwin(void)
add_map("<Tab>", "<C-X><C-V>", MODE_INSERT, true);
add_map("<Tab>", "a<C-X><C-V>", MODE_NORMAL, true);
}
- set_option_value_give_err("ft", STATIC_CSTR_AS_OPTVAL("vim"), OPT_LOCAL);
+ set_option_value_give_err(kOptFiletype, STATIC_CSTR_AS_OPTVAL("vim"), OPT_LOCAL);
}
curbuf->b_ro_locked--;
@@ -4413,15 +4460,18 @@ static int open_cmdwin(void)
cmdwin_type = 0;
cmdwin_level = 0;
+ cmdwin_buf = NULL;
+ cmdwin_win = NULL;
cmdwin_old_curwin = NULL;
exmode_active = save_exmode;
- // Safety check: The old window or buffer was deleted: It's a bug when
- // this happens!
- if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)) {
+ // Safety check: The old window or buffer was changed or deleted: It's a bug
+ // when this happens!
+ if (!win_valid(old_curwin) || !bufref_valid(&old_curbuf)
+ || old_curwin->w_buffer != old_curbuf.br_buf) {
cmdwin_result = Ctrl_C;
- emsg(_("E199: Active window or buffer deleted"));
+ emsg(_(e_active_window_or_buffer_changed_or_deleted));
} else {
win_T *wp;
// autocmds may abort script processing
diff --git a/src/nvim/ex_getln.h b/src/nvim/ex_getln.h
index 93bdd2299f..3e14ea12b8 100644
--- a/src/nvim/ex_getln.h
+++ b/src/nvim/ex_getln.h
@@ -1,76 +1,13 @@
#pragma once
-#include <stdbool.h>
+#include <stddef.h> // IWYU pragma: keep
-#include "klib/kvec.h"
-#include "nvim/cmdexpand_defs.h"
-#include "nvim/eval/typval_defs.h"
+#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
+#include "nvim/ex_getln_defs.h" // IWYU pragma: keep
#include "nvim/option_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
-/// Command-line colors: one chunk
-///
-/// Defines a region which has the same highlighting.
-typedef struct {
- int start; ///< Colored chunk start.
- int end; ///< Colored chunk end (exclusive, > start).
- int attr; ///< Highlight attr.
-} CmdlineColorChunk;
-
-/// Command-line colors
-///
-/// Holds data about all colors.
-typedef kvec_t(CmdlineColorChunk) CmdlineColors;
-
-/// Command-line coloring
-///
-/// Holds both what are the colors and what have been colored. Latter is used to
-/// suppress unnecessary calls to coloring callbacks.
-typedef struct {
- unsigned prompt_id; ///< ID of the prompt which was colored last.
- char *cmdbuff; ///< What exactly was colored last time or NULL.
- CmdlineColors colors; ///< Last colors.
-} ColoredCmdline;
-
-/// Keeps track how much state must be sent to external ui.
-typedef enum {
- kCmdRedrawNone,
- kCmdRedrawPos,
- kCmdRedrawAll,
-} CmdRedraw;
-
-/// Variables shared between getcmdline(), redrawcmdline() and others.
-/// These need to be saved when using CTRL-R |, that's why they are in a
-/// structure.
-typedef struct cmdline_info CmdlineInfo;
-struct cmdline_info {
- char *cmdbuff; ///< pointer to command line buffer
- int cmdbufflen; ///< length of cmdbuff
- int cmdlen; ///< number of chars in command line
- int cmdpos; ///< current cursor position
- int cmdspos; ///< cursor column on screen
- int cmdfirstc; ///< ':', '/', '?', '=', '>' or NUL
- int cmdindent; ///< number of spaces before cmdline
- char *cmdprompt; ///< message in front of cmdline
- int cmdattr; ///< attributes for prompt
- int overstrike; ///< Typing mode on the command line. Shared by
- ///< getcmdline() and put_on_cmdline().
- expand_T *xpc; ///< struct being used for expansion, xp_pattern
- ///< may point into cmdbuff
- int xp_context; ///< type of expansion
- char *xp_arg; ///< user-defined expansion arg
- int input_fn; ///< when true Invoked for input() function
- unsigned prompt_id; ///< Prompt number, used to disable coloring on errors.
- Callback highlight_callback; ///< Callback used for coloring user input.
- ColoredCmdline last_colors; ///< Last cmdline colors
- int level; ///< current cmdline level
- CmdlineInfo *prev_ccline; ///< pointer to saved cmdline state
- char special_char; ///< last putcmdline char (used for redraws)
- bool special_shift; ///< shift of last putcmdline char
- CmdRedraw redraw_state; ///< needed redraw for external cmdline
-};
-
/// flags used by vim_strsave_fnameescape()
enum {
VSE_NONE = 0,
diff --git a/src/nvim/ex_getln_defs.h b/src/nvim/ex_getln_defs.h
new file mode 100644
index 0000000000..daba6cabb8
--- /dev/null
+++ b/src/nvim/ex_getln_defs.h
@@ -0,0 +1,68 @@
+#pragma once
+
+#include <stdbool.h>
+
+#include "klib/kvec.h"
+#include "nvim/cmdexpand_defs.h"
+
+/// Command-line colors: one chunk
+///
+/// Defines a region which has the same highlighting.
+typedef struct {
+ int start; ///< Colored chunk start.
+ int end; ///< Colored chunk end (exclusive, > start).
+ int attr; ///< Highlight attr.
+} CmdlineColorChunk;
+
+/// Command-line colors
+///
+/// Holds data about all colors.
+typedef kvec_t(CmdlineColorChunk) CmdlineColors;
+
+/// Command-line coloring
+///
+/// Holds both what are the colors and what have been colored. Latter is used to
+/// suppress unnecessary calls to coloring callbacks.
+typedef struct {
+ unsigned prompt_id; ///< ID of the prompt which was colored last.
+ char *cmdbuff; ///< What exactly was colored last time or NULL.
+ CmdlineColors colors; ///< Last colors.
+} ColoredCmdline;
+
+/// Keeps track how much state must be sent to external ui.
+typedef enum {
+ kCmdRedrawNone,
+ kCmdRedrawPos,
+ kCmdRedrawAll,
+} CmdRedraw;
+
+/// Variables shared between getcmdline(), redrawcmdline() and others.
+/// These need to be saved when using CTRL-R |, that's why they are in a
+/// structure.
+typedef struct cmdline_info CmdlineInfo;
+struct cmdline_info {
+ char *cmdbuff; ///< pointer to command line buffer
+ int cmdbufflen; ///< length of cmdbuff
+ int cmdlen; ///< number of chars in command line
+ int cmdpos; ///< current cursor position
+ int cmdspos; ///< cursor column on screen
+ int cmdfirstc; ///< ':', '/', '?', '=', '>' or NUL
+ int cmdindent; ///< number of spaces before cmdline
+ char *cmdprompt; ///< message in front of cmdline
+ int cmdattr; ///< attributes for prompt
+ int overstrike; ///< Typing mode on the command line. Shared by
+ ///< getcmdline() and put_on_cmdline().
+ expand_T *xpc; ///< struct being used for expansion, xp_pattern
+ ///< may point into cmdbuff
+ int xp_context; ///< type of expansion
+ char *xp_arg; ///< user-defined expansion arg
+ int input_fn; ///< when true Invoked for input() function
+ unsigned prompt_id; ///< Prompt number, used to disable coloring on errors.
+ Callback highlight_callback; ///< Callback used for coloring user input.
+ ColoredCmdline last_colors; ///< Last cmdline colors
+ int level; ///< current cmdline level
+ CmdlineInfo *prev_ccline; ///< pointer to saved cmdline state
+ char special_char; ///< last putcmdline char (used for redraws)
+ bool special_shift; ///< shift of last putcmdline char
+ CmdRedraw redraw_state; ///< needed redraw for external cmdline
+};
diff --git a/src/nvim/ex_session.c b/src/nvim/ex_session.c
index 71c01922bc..fb37bc86f1 100644
--- a/src/nvim/ex_session.c
+++ b/src/nvim/ex_session.c
@@ -10,9 +10,13 @@
#include <string.h>
#include "nvim/arglist.h"
+#include "nvim/arglist_defs.h"
#include "nvim/ascii_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/eval.h"
+#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
@@ -20,21 +24,24 @@
#include "nvim/file_search.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
-#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/mapping.h"
+#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/runtime.h"
+#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -60,7 +67,7 @@ static int put_view_curpos(FILE *fd, const win_T *wp, char *spaces)
return r >= 0;
}
-static int ses_winsizes(FILE *fd, int restore_size, win_T *tab_firstwin)
+static int ses_winsizes(FILE *fd, bool restore_size, win_T *tab_firstwin)
{
if (restore_size && (ssop_flags & SSOP_WINSIZE)) {
int n = 0;
@@ -209,7 +216,7 @@ static int ses_do_win(win_T *wp)
/// @param flagp
///
/// @returns FAIL if writing fails.
-static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, int fullname, unsigned *flagp)
+static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, bool fullname, unsigned *flagp)
{
char *buf = NULL;
@@ -222,7 +229,7 @@ static int ses_arglist(FILE *fd, char *cmd, garray_T *gap, int fullname, unsigne
if (s != NULL) {
if (fullname) {
buf = xmalloc(MAXPATHL);
- (void)vim_FullName(s, buf, MAXPATHL, false);
+ vim_FullName(s, buf, MAXPATHL, false);
s = buf;
}
char *fname_esc = ses_escape_fname(s, flagp);
@@ -315,11 +322,11 @@ static int ses_put_fname(FILE *fd, char *name, unsigned *flagp)
static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int current_arg_idx)
{
int f;
- int did_next = false;
+ bool did_next = false;
// Always restore cursor position for ":mksession". For ":mkview" only
// when 'viewoptions' contains "cursor".
- int do_cursor = (flagp == &ssop_flags || *flagp & SSOP_CURSOR);
+ bool do_cursor = (flagp == &ssop_flags || *flagp & SSOP_CURSOR);
// Local argument list.
if (wp->w_alist == &global_alist) {
@@ -359,6 +366,7 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
if (put_line(fd, "enew | setl bt=help") == FAIL
|| fprintf(fd, "help %s", curtag) < 0 || put_eol(fd) == FAIL) {
+ xfree(fname_esc);
return FAIL;
}
} else if (wp->w_buffer->b_ffname != NULL
@@ -518,6 +526,50 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
return OK;
}
+static int store_session_globals(FILE *fd)
+{
+ TV_DICT_ITER(&globvardict, this_var, {
+ if ((this_var->di_tv.v_type == VAR_NUMBER
+ || this_var->di_tv.v_type == VAR_STRING)
+ && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) {
+ // Escape special characters with a backslash. Turn a LF and
+ // CR into \n and \r.
+ char *const p = vim_strsave_escaped(tv_get_string(&this_var->di_tv), "\\\"\n\r");
+ for (char *t = p; *t != NUL; t++) {
+ if (*t == '\n') {
+ *t = 'n';
+ } else if (*t == '\r') {
+ *t = 'r';
+ }
+ }
+ if ((fprintf(fd, "let %s = %c%s%c",
+ this_var->di_key,
+ ((this_var->di_tv.v_type == VAR_STRING) ? '"' : ' '),
+ p,
+ ((this_var->di_tv.v_type == VAR_STRING) ? '"' : ' ')) < 0)
+ || put_eol(fd) == FAIL) {
+ xfree(p);
+ return FAIL;
+ }
+ xfree(p);
+ } else if (this_var->di_tv.v_type == VAR_FLOAT
+ && var_flavour(this_var->di_key) == VAR_FLAVOUR_SESSION) {
+ float_T f = this_var->di_tv.vval.v_float;
+ int sign = ' ';
+
+ if (f < 0) {
+ f = -f;
+ sign = '-';
+ }
+ if ((fprintf(fd, "let %s = %c%f", this_var->di_key, sign, f) < 0)
+ || put_eol(fd) == FAIL) {
+ return FAIL;
+ }
+ }
+ });
+ return OK;
+}
+
/// Writes commands for restoring the current buffers, for :mksession.
///
/// Legacy 'sessionoptions'/'viewoptions' flags SSOP_UNIX, SSOP_SLASH are
@@ -529,8 +581,8 @@ static int put_view(FILE *fd, win_T *wp, int add_edit, unsigned *flagp, int curr
/// @return FAIL on error, OK otherwise.
static int makeopens(FILE *fd, char *dirnow)
{
- int only_save_windows = true;
- int restore_size = true;
+ bool only_save_windows = true;
+ bool restore_size = true;
win_T *edited_win = NULL;
win_T *tab_firstwin;
frame_T *tab_topframe;
@@ -628,7 +680,7 @@ static int makeopens(FILE *fd, char *dirnow)
}
}
- int restore_stal = false;
+ bool restore_stal = false;
// When there are two or more tabpages and 'showtabline' is 1 the tabline
// will be displayed when creating the next tab. That resizes the windows
// in the first tab, which may cause problems. Set 'showtabline' to 2
@@ -887,7 +939,7 @@ void ex_loadview(exarg_T *eap)
/// - SSOP_SLASH: filenames are written with "/" slash
void ex_mkrc(exarg_T *eap)
{
- int view_session = false; // :mkview, :mksession
+ bool view_session = false; // :mkview, :mksession
int using_vdir = false; // using 'viewdir'?
char *viewFile = NULL;
@@ -928,7 +980,7 @@ void ex_mkrc(exarg_T *eap)
FILE *fd = open_exfile(fname, eap->forceit, WRITEBIN);
if (fd != NULL) {
- int failed = false;
+ bool failed = false;
unsigned *flagp;
if (eap->cmdidx == CMD_mkview) {
flagp = &vop_flags;
@@ -938,7 +990,7 @@ void ex_mkrc(exarg_T *eap)
// Write the version command for :mkvimrc
if (eap->cmdidx == CMD_mkvimrc) {
- (void)put_line(fd, "version 6.0");
+ put_line(fd, "version 6.0");
}
if (eap->cmdidx == CMD_mksession) {
diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c
index d9c1993f32..c4a34f8019 100644
--- a/src/nvim/extmark.c
+++ b/src/nvim/extmark.c
@@ -32,14 +32,18 @@
#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
#include "nvim/decoration.h"
+#include "nvim/decoration_defs.h"
#include "nvim/extmark.h"
#include "nvim/extmark_defs.h"
#include "nvim/globals.h"
#include "nvim/map_defs.h"
#include "nvim/marktree.h"
#include "nvim/memline.h"
+#include "nvim/memory.h"
#include "nvim/pos_defs.h"
+#include "nvim/types_defs.h"
#include "nvim/undo.h"
+#include "nvim/undo_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "extmark.c.generated.h"
@@ -50,12 +54,12 @@
/// must not be used during iteration!
void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col, int end_row,
colnr_T end_col, DecorInline decor, uint16_t decor_flags, bool right_gravity,
- bool end_right_gravity, bool no_undo, bool invalidate, Error *err)
+ bool end_right_gravity, bool no_undo, bool invalidate, bool scoped, Error *err)
{
uint32_t *ns = map_put_ref(uint32_t, uint32_t)(buf->b_extmark_ns, ns_id, NULL, NULL);
uint32_t id = idp ? *idp : 0;
- uint16_t flags = mt_flags(right_gravity, no_undo, invalidate, decor.ext) | decor_flags;
+ uint16_t flags = mt_flags(right_gravity, no_undo, invalidate, decor.ext, scoped) | decor_flags;
if (id == 0) {
id = ++*ns;
} else {
@@ -66,19 +70,27 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
extmark_del_id(buf, ns_id, id);
} else {
assert(marktree_itr_valid(itr));
+ bool invalid = mt_invalid(old_mark);
if (old_mark.pos.row == row && old_mark.pos.col == col) {
- if (mt_decor_any(old_mark)) {
- buf_decor_remove(buf, row, row, mt_decor(old_mark), true);
- }
-
// not paired: we can revise in place
- mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_EXTERNAL_MASK;
- mt_itr_rawkey(itr).flags |= flags;
+ if (!invalid && mt_decor_any(old_mark)) {
+ // TODO(bfredl): conflict of concerns: buf_decor_remove() must process
+ // the buffer as if MT_FLAG_DECOR_SIGNTEXT is already removed, however
+ // marktree must precisely adjust the set of flags from the old set to the new
+ uint16_t save_flags = mt_itr_rawkey(itr).flags;
+ mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_DECOR_SIGNTEXT;
+ buf_decor_remove(buf, row, row, col, mt_decor(old_mark), true);
+ mt_itr_rawkey(itr).flags = save_flags;
+ }
+ marktree_revise_flags(buf->b_marktree, itr, flags);
mt_itr_rawkey(itr).decor_data = decor.data;
goto revised;
}
- buf_decor_remove(buf, old_mark.pos.row, old_mark.pos.row, mt_decor(old_mark), true);
marktree_del_itr(buf->b_marktree, itr, false);
+ if (!invalid) {
+ buf_decor_remove(buf, old_mark.pos.row, old_mark.pos.row, old_mark.pos.col,
+ mt_decor(old_mark), true);
+ }
}
} else {
*ns = MAX(*ns, id);
@@ -92,7 +104,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col
revised:
if (decor_flags || decor.ext) {
buf_put_decor(buf, decor, row, end_row > -1 ? end_row : row);
- decor_redraw(buf, row, end_row > -1 ? end_row : row, decor);
+ decor_redraw(buf, row, end_row > -1 ? end_row : row, col, decor);
}
if (idp) {
@@ -100,20 +112,39 @@ revised:
}
}
-static bool extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col)
+static void extmark_setraw(buf_T *buf, uint64_t mark, int row, colnr_T col, bool invalid)
{
MarkTreeIter itr[1] = { 0 };
MTKey key = marktree_lookup(buf->b_marktree, mark, itr);
- if (key.pos.row == -1) {
- return false;
+ if (key.pos.row < 0 || (key.pos.row == row && key.pos.col == col)) {
+ return;
+ }
+
+ // Only the position before undo needs to be redrawn here,
+ // as the position after undo should be marked as changed.
+ if (!invalid && mt_decor_any(key) && key.pos.row != row) {
+ decor_redraw(buf, key.pos.row, key.pos.row, key.pos.col, mt_decor(key));
}
- if (key.pos.row == row && key.pos.col == col) {
- return true;
+ int row1 = 0;
+ int row2 = 0;
+ if (invalid) {
+ mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_INVALID;
+ } else if (key.flags & MT_FLAG_DECOR_SIGNTEXT && buf->b_signcols.autom) {
+ MTPos end = marktree_get_altpos(buf->b_marktree, key, NULL);
+ row1 = MIN(end.row, MIN(key.pos.row, row));
+ row2 = MAX(end.row, MAX(key.pos.row, row));
+ buf_signcols_count_range(buf, row1, row2, 0, kTrue);
}
marktree_move(buf->b_marktree, itr, row, col);
- return true;
+
+ if (invalid) {
+ MTPos end = marktree_get_altpos(buf->b_marktree, key, NULL);
+ buf_put_decor(buf, mt_decor(key), row, end.row);
+ } else if (key.flags & MT_FLAG_DECOR_SIGNTEXT && buf->b_signcols.autom) {
+ buf_signcols_count_range(buf, row1, row2, 0, kNone);
+ }
}
/// Remove an extmark in "ns_id" by "id"
@@ -147,7 +178,11 @@ void extmark_del(buf_T *buf, MarkTreeIter *itr, MTKey key, bool restore)
}
if (mt_decor_any(key)) {
- buf_decor_remove(buf, key.pos.row, key2.pos.row, mt_decor(key), true);
+ if (mt_invalid(key)) {
+ decor_free(mt_decor(key));
+ } else {
+ buf_decor_remove(buf, key.pos.row, key2.pos.row, key.pos.col, mt_decor(key), true);
+ }
}
// TODO(bfredl): delete it from current undo header, opportunistically?
@@ -218,7 +253,7 @@ ExtmarkInfoArray extmark_get(buf_T *buf, uint32_t ns_id, int l_row, colnr_T l_co
} else {
// Find all the marks beginning with the start position
marktree_itr_get_ext(buf->b_marktree, MTPos(l_row, l_col),
- itr, reverse, false, NULL);
+ itr, reverse, false, NULL, NULL);
}
int order = reverse ? -1 : 1;
@@ -302,6 +337,9 @@ void extmark_free_all(buf_T *buf)
marktree_clear(buf->b_marktree);
+ buf->b_signcols.max = 0;
+ CLEAR_FIELD(buf->b_signcols.count);
+
map_destroy(uint32_t, buf->b_extmark_ns);
*buf->b_extmark_ns = (Map(uint32_t, uint32_t)) MAP_INIT;
}
@@ -311,9 +349,8 @@ void extmark_free_all(buf_T *buf)
/// copying is useful when we cannot simply reverse the operation. This will do
/// nothing on redo, enforces correct position when undo.
void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, colnr_T u_col,
- ExtmarkOp op)
+ extmark_undo_vec_t *uvp, bool only_copy, ExtmarkOp op)
{
- u_header_T *uhp = u_force_get_undo_header(buf);
MarkTreeIter itr[1] = { 0 };
ExtmarkUndoObject undo;
@@ -328,38 +365,37 @@ void extmark_splice_delete(buf_T *buf, int l_row, colnr_T l_col, int u_row, coln
bool invalidated = false;
// Invalidate/delete mark
- if (!mt_invalid(mark) && mt_invalidate(mark) && !mt_end(mark)) {
+ if (!only_copy && !mt_invalid(mark) && mt_invalidate(mark) && !mt_end(mark)) {
MTPos endpos = marktree_get_altpos(buf->b_marktree, mark, NULL);
- if (endpos.row < 0) {
- endpos = mark.pos;
- }
- if ((endpos.col <= u_col || (!u_col && endpos.row == mark.pos.row))
- && mark.pos.col >= l_col
- && mark.pos.row >= l_row && endpos.row <= u_row - (u_col ? 0 : 1)) {
+ // Invalidate unpaired marks in deleted lines and paired marks whose entire
+ // range has been deleted.
+ if ((!mt_paired(mark) && mark.pos.row < u_row)
+ || (mt_paired(mark)
+ && (endpos.col <= u_col || (!u_col && endpos.row == mark.pos.row))
+ && mark.pos.col >= l_col
+ && mark.pos.row >= l_row && endpos.row <= u_row - (u_col ? 0 : 1))) {
if (mt_no_undo(mark)) {
extmark_del(buf, itr, mark, true);
continue;
} else {
invalidated = true;
mt_itr_rawkey(itr).flags |= MT_FLAG_INVALID;
- buf_decor_remove(buf, mark.pos.row, endpos.row, mt_decor(mark), false);
+ buf_decor_remove(buf, mark.pos.row, endpos.row, mark.pos.col, mt_decor(mark), false);
}
}
}
// Push mark to undo header
- if (uhp && op == kExtmarkUndo && !mt_no_undo(mark)) {
- ExtmarkSavePos pos;
- pos.mark = mt_lookup_key(mark);
- pos.invalidated = invalidated;
- pos.old_row = mark.pos.row;
- pos.old_col = mark.pos.col;
- pos.row = -1;
- pos.col = -1;
-
+ if (only_copy || (uvp != NULL && op == kExtmarkUndo && !mt_no_undo(mark))) {
+ ExtmarkSavePos pos = {
+ .mark = mt_lookup_key(mark),
+ .invalidated = invalidated,
+ .old_row = mark.pos.row,
+ .old_col = mark.pos.col
+ };
undo.data.savepos = pos;
undo.type = kExtmarkSavePos;
- kv_push(uhp->uh_extmark, undo);
+ kv_push(*uvp, undo);
}
marktree_itr_next(buf->b_marktree, itr);
@@ -389,23 +425,10 @@ void extmark_apply_undo(ExtmarkUndoObject undo_info, bool undo)
// kExtmarkSavePos
} else if (undo_info.type == kExtmarkSavePos) {
ExtmarkSavePos pos = undo_info.data.savepos;
- if (undo) {
- if (pos.invalidated) {
- MarkTreeIter itr[1] = { 0 };
- MTKey mark = marktree_lookup(curbuf->b_marktree, pos.mark, itr);
- mt_itr_rawkey(itr).flags &= (uint16_t) ~MT_FLAG_INVALID;
- MTPos end = marktree_get_altpos(curbuf->b_marktree, mark, itr);
- buf_put_decor(curbuf, mt_decor(mark), mark.pos.row, end.row < 0 ? mark.pos.row : end.row);
- }
- if (pos.old_row >= 0) {
- extmark_setraw(curbuf, pos.mark, pos.old_row, pos.old_col);
- }
- // Redo
- } else {
- if (pos.row >= 0) {
- extmark_setraw(curbuf, pos.mark, pos.row, pos.col);
- }
+ if (undo && pos.old_row >= 0) {
+ extmark_setraw(curbuf, pos.mark, pos.old_row, pos.old_col, pos.invalidated);
}
+ // No Redo since kExtmarkSplice will move marks back
} else if (undo_info.type == kExtmarkMove) {
ExtmarkMove move = undo_info.data.move;
if (undo) {
@@ -432,8 +455,10 @@ void extmark_adjust(buf_T *buf, linenr_T line1, linenr_T line2, linenr_T amount,
return;
}
bcount_t start_byte = ml_find_line_or_offset(buf, line1, NULL, true);
- bcount_t old_byte = 0, new_byte = 0;
- int old_row, new_row;
+ bcount_t old_byte = 0;
+ bcount_t new_byte = 0;
+ int old_row;
+ int new_row;
if (amount == MAXLNUM) {
old_row = line2 - line1 + 1;
// TODO(bfredl): ej kasta?
@@ -511,27 +536,24 @@ void extmark_splice_impl(buf_T *buf, int start_row, colnr_T start_col, bcount_t
// merge!)
int end_row = start_row + old_row;
int end_col = (old_row ? 0 : start_col) + old_col;
- extmark_splice_delete(buf, start_row, start_col, end_row, end_col, undo);
+ u_header_T *uhp = u_force_get_undo_header(buf);
+ extmark_undo_vec_t *uvp = uhp ? &uhp->uh_extmark : NULL;
+ extmark_splice_delete(buf, start_row, start_col, end_row, end_col, uvp, false, undo);
}
- // Move the signcolumn sentinel line
- if (buf->b_signs_with_text && buf->b_signcols.sentinel) {
- linenr_T se_lnum = buf->b_signcols.sentinel;
- if (se_lnum >= start_row) {
- if (old_row != 0 && se_lnum > old_row + start_row) {
- buf->b_signcols.sentinel += new_row - old_row;
- } else if (new_row == 0) {
- buf->b_signcols.sentinel = 0;
- } else {
- buf->b_signcols.sentinel += new_row;
- }
- }
+ // Remove signs inside edited region from "b_signcols.count", add after splicing.
+ if (old_row > 0 || new_row > 0) {
+ buf_signcols_count_range(buf, start_row, start_row + old_row, 0, kTrue);
}
marktree_splice(buf->b_marktree, (int32_t)start_row, start_col,
old_row, old_col,
new_row, new_col);
+ if (old_row > 0 || new_row > 0) {
+ buf_signcols_count_range(buf, start_row, start_row + new_row, 0, kNone);
+ }
+
if (undo == kExtmarkUndo) {
u_header_T *uhp = u_force_get_undo_header(buf);
if (!uhp) {
@@ -610,10 +632,16 @@ void extmark_move_region(buf_T *buf, int start_row, colnr_T start_col, bcount_t
extent_row, extent_col, extent_byte,
0, 0, 0);
+ int row1 = MIN(start_row, new_row);
+ int row2 = MAX(start_row, new_row) + extent_row;
+ buf_signcols_count_range(buf, row1, row2, 0, kTrue);
+
marktree_move_region(buf->b_marktree, start_row, start_col,
extent_row, extent_col,
new_row, new_col);
+ buf_signcols_count_range(buf, row1, row2, 0, kNone);
+
buf_updates_send_splice(buf, new_row, new_col, new_byte,
0, 0, 0,
extent_row, extent_col, extent_byte);
diff --git a/src/nvim/extmark.h b/src/nvim/extmark.h
index 061cd0ed5f..b1ef5cf214 100644
--- a/src/nvim/extmark.h
+++ b/src/nvim/extmark.h
@@ -1,19 +1,16 @@
#pragma once
#include <stdbool.h>
-#include <stddef.h>
#include <stdint.h>
#include "klib/kvec.h"
-#include "nvim/buffer_defs.h"
-#include "nvim/decoration.h"
-#include "nvim/extmark_defs.h" // IWYU pragma: export
+#include "nvim/extmark_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
-#include "nvim/marktree.h"
+#include "nvim/marktree_defs.h"
#include "nvim/pos_defs.h"
-#include "nvim/types_defs.h"
+#include "nvim/types_defs.h" // IWYU pragma: keep
-EXTERN int extmark_splice_pending INIT( = 0);
+EXTERN int curbuf_splice_pending INIT( = 0);
typedef kvec_t(MTPair) ExtmarkInfoArray;
@@ -48,8 +45,6 @@ typedef struct {
uint64_t mark; // raw mark id of the marktree
int old_row;
colnr_T old_col;
- int row;
- colnr_T col;
bool invalidated;
} ExtmarkSavePos;
diff --git a/src/nvim/extmark_defs.h b/src/nvim/extmark_defs.h
index c5a8684545..71150cf07c 100644
--- a/src/nvim/extmark_defs.h
+++ b/src/nvim/extmark_defs.h
@@ -1,7 +1,6 @@
#pragma once
#include "klib/kvec.h"
-#include "nvim/types_defs.h"
// TODO(bfredl): good enough name for now.
typedef ptrdiff_t bcount_t;
diff --git a/src/nvim/file_search.c b/src/nvim/file_search.c
index 460cd48fc5..ed4848b402 100644
--- a/src/nvim/file_search.c
+++ b/src/nvim/file_search.c
@@ -51,10 +51,13 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/file_search.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
@@ -63,8 +66,10 @@
#include "nvim/option.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/strings.h"
#include "nvim/vim_defs.h"
@@ -156,7 +161,7 @@ typedef struct ff_visited_list_hdr {
// ffsc_stopdirs_v: array of stop directories for upward search
// ffsc_find_what: FINDFILE_BOTH, FINDFILE_DIR or FINDFILE_FILE
// ffsc_tagfile: searching for tags file, don't use 'suffixesadd'
-typedef struct ff_search_ctx_T {
+typedef struct {
ff_stack_T *ffsc_stack_ptr;
ff_visited_list_hdr_T *ffsc_visited_list;
ff_visited_list_hdr_T *ffsc_dir_visited_list;
@@ -237,7 +242,6 @@ static const char e_path_too_long_for_completion[]
void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, int free_visited,
int find_what, void *search_ctx_arg, int tagfile, char *rel_fname)
{
- char *wc_part;
ff_stack_T *sptr;
ff_search_ctx_T *search_ctx;
@@ -308,7 +312,7 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
goto error_return;
}
path += 2;
- } else // NOLINT(readability/braces)
+ } else
#endif
if (os_dirname(ff_expand_buffer, MAXPATHL) == FAIL) {
goto error_return;
@@ -372,7 +376,7 @@ void *vim_findfile_init(char *path, char *filename, char *stopdirs, int level, i
// split into:
// -fix path
// -wildcard_stuff (might be NULL)
- wc_part = vim_strchr(path, '*');
+ char *wc_part = vim_strchr(path, '*');
if (wc_part != NULL) {
int64_t llevel;
int len;
@@ -548,24 +552,22 @@ void vim_findfile_cleanup(void *ctx)
/// NULL if nothing found.
char *vim_findfile(void *search_ctx_arg)
{
- char *file_path;
char *rest_of_wildcards;
char *path_end = NULL;
ff_stack_T *stackp = NULL;
size_t len;
char *p;
char *suf;
- ff_search_ctx_T *search_ctx;
if (search_ctx_arg == NULL) {
return NULL;
}
- search_ctx = (ff_search_ctx_T *)search_ctx_arg;
+ ff_search_ctx_T *search_ctx = (ff_search_ctx_T *)search_ctx_arg;
// filepath is used as buffer for various actions and as the storage to
// return a found filename.
- file_path = xmalloc(MAXPATHL);
+ char *file_path = xmalloc(MAXPATHL);
// store the end of the start dir -- needed for upward search
if (search_ctx->ffsc_start_dir != NULL) {
@@ -882,7 +884,7 @@ char *vim_findfile(void *search_ctx_arg)
// is the last starting directory in the stop list?
if (ff_path_in_stoplist(search_ctx->ffsc_start_dir,
(int)(path_end - search_ctx->ffsc_start_dir),
- search_ctx->ffsc_stopdirs_v) == true) {
+ search_ctx->ffsc_stopdirs_v)) {
break;
}
@@ -928,13 +930,11 @@ fail:
/// Can handle it if the passed search_context is NULL;
void vim_findfile_free_visited(void *search_ctx_arg)
{
- ff_search_ctx_T *search_ctx;
-
if (search_ctx_arg == NULL) {
return;
}
- search_ctx = (ff_search_ctx_T *)search_ctx_arg;
+ ff_search_ctx_T *search_ctx = (ff_search_ctx_T *)search_ctx_arg;
vim_findfile_free_visited_list(&search_ctx->ffsc_visited_lists_list);
vim_findfile_free_visited_list(&search_ctx->ffsc_dir_visited_lists_list);
}
@@ -1156,9 +1156,7 @@ static void ff_push(ff_search_ctx_T *search_ctx, ff_stack_T *stack_ptr)
/// @return NULL if stack is empty.
static ff_stack_T *ff_pop(ff_search_ctx_T *search_ctx)
{
- ff_stack_T *sptr;
-
- sptr = search_ctx->ffsc_stack_ptr;
+ ff_stack_T *sptr = search_ctx->ffsc_stack_ptr;
if (search_ctx->ffsc_stack_ptr != NULL) {
search_ctx->ffsc_stack_ptr = search_ctx->ffsc_stack_ptr->ffs_prev;
}
@@ -1221,10 +1219,8 @@ static void ff_clear(ff_search_ctx_T *search_ctx)
/// check if the given path is in the stopdirs
///
/// @return true if yes else false
-static int ff_path_in_stoplist(char *path, int path_len, char **stopdirs_v)
+static bool ff_path_in_stoplist(char *path, int path_len, char **stopdirs_v)
{
- int i = 0;
-
// eat up trailing path separators, except the first
while (path_len > 1 && vim_ispathsep(path[path_len - 1])) {
path_len--;
@@ -1235,7 +1231,7 @@ static int ff_path_in_stoplist(char *path, int path_len, char **stopdirs_v)
return true;
}
- for (i = 0; stopdirs_v[i] != NULL; i++) {
+ for (int i = 0; stopdirs_v[i] != NULL; i++) {
if ((int)strlen(stopdirs_v[i]) > path_len) {
// match for parent directory. So '/home' also matches
// '/home/rks'. Check for PATHSEP in stopdirs_v[i], else
@@ -1338,11 +1334,9 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
{
ff_search_ctx_T **search_ctx = (ff_search_ctx_T **)search_ctx_arg;
static char *dir;
- static int did_findfile_init = false;
- char save_char;
+ static bool did_findfile_init = false;
char *file_name = NULL;
char *buf = NULL;
- int rel_to_curdir;
if (rel_fname != NULL && path_with_url(rel_fname)) {
// Do not attempt to search "relative" to a URL. #6009
@@ -1355,7 +1349,7 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
}
// copy file name into NameBuff, expanding environment variables
- save_char = ptr[len];
+ char save_char = ptr[len];
ptr[len] = NUL;
expand_env_esc(ptr, NameBuff, MAXPATHL, false, true, NULL);
ptr[len] = save_char;
@@ -1372,12 +1366,12 @@ char *find_file_in_path_option(char *ptr, size_t len, int options, int first, ch
}
}
- rel_to_curdir = ((*file_to_find)[0] == '.'
- && ((*file_to_find)[1] == NUL
- || vim_ispathsep((*file_to_find)[1])
- || ((*file_to_find)[1] == '.'
- && ((*file_to_find)[2] == NUL
- || vim_ispathsep((*file_to_find)[2])))));
+ bool rel_to_curdir = ((*file_to_find)[0] == '.'
+ && ((*file_to_find)[1] == NUL
+ || vim_ispathsep((*file_to_find)[1])
+ || ((*file_to_find)[1] == '.'
+ && ((*file_to_find)[2] == NUL
+ || vim_ispathsep((*file_to_find)[2])))));
if (vim_isAbsName(*file_to_find)
// "..", "../path", "." and "./path": don't use the path_option
|| rel_to_curdir
diff --git a/src/nvim/file_search.h b/src/nvim/file_search.h
index d4b5c5d352..2450472681 100644
--- a/src/nvim/file_search.h
+++ b/src/nvim/file_search.h
@@ -1,14 +1,16 @@
#pragma once
-#include <stdlib.h>
+#include <stddef.h> // IWYU pragma: keep
-#include "nvim/globals.h"
#include "nvim/types_defs.h" // IWYU pragma: keep
+#include "nvim/vim_defs.h" // IWYU pragma: keep
-// Flags for find_file_*() functions.
-#define FINDFILE_FILE 0 // only files
-#define FINDFILE_DIR 1 // only directories
-#define FINDFILE_BOTH 2 // files and directories
+/// Flags for find_file_*() functions.
+enum {
+ FINDFILE_FILE = 0, ///< only files
+ FINDFILE_DIR = 1, ///< only directories
+ FINDFILE_BOTH = 2, ///< files and directories
+};
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "file_search.h.generated.h"
diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c
index 0bb664bcf5..3b715e2c0b 100644
--- a/src/nvim/fileio.c
+++ b/src/nvim/fileio.c
@@ -18,6 +18,7 @@
#include "auto/config.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
@@ -31,23 +32,27 @@
#include "nvim/ex_eval.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/iconv_defs.h"
#include "nvim/log.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memfile.h"
+#include "nvim/memfile_defs.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/fs.h"
@@ -58,6 +63,7 @@
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/sha256.h"
#include "nvim/shada.h"
#include "nvim/state_defs.h"
@@ -65,6 +71,7 @@
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
+#include "nvim/undo_defs.h"
#include "nvim/vim_defs.h"
#ifdef BACKSLASH_IN_FILENAME
@@ -158,14 +165,12 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
{
int retval = FAIL; // jump to "theend" instead of returning
int fd = stdin_fd >= 0 ? stdin_fd : 0;
- int newfile = (flags & READ_NEW);
- int check_readonly;
- int filtering = (flags & READ_FILTER);
- int read_stdin = (flags & READ_STDIN);
- int read_buffer = (flags & READ_BUFFER);
- int read_fifo = (flags & READ_FIFO);
- int set_options = newfile || read_buffer
- || (eap != NULL && eap->read_edit);
+ bool newfile = (flags & READ_NEW);
+ bool filtering = (flags & READ_FILTER);
+ bool read_stdin = (flags & READ_STDIN);
+ bool read_buffer = (flags & READ_BUFFER);
+ bool read_fifo = (flags & READ_FIFO);
+ bool set_options = newfile || read_buffer || (eap != NULL && eap->read_edit);
linenr_T read_buf_lnum = 1; // next line to read from curbuf
colnr_T read_buf_col = 0; // next char to read from this line
char c;
@@ -181,7 +186,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
off_T filesize = 0;
bool skip_read = false;
context_sha256_T sha_ctx;
- int read_undo_file = false;
+ bool read_undo_file = false;
int split = 0; // number of split lines
linenr_T linecnt;
bool error = false; // errors encountered
@@ -200,7 +205,6 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
linenr_T read_no_eol_lnum = 0; // non-zero lnum when last line of
// last read was missing the eol
bool file_rewind = false;
- int can_retry;
linenr_T conv_error = 0; // line nr with conversion error
linenr_T illegal_byte = 0; // line nr with illegal byte
bool keep_dest_enc = false; // don't retry when char doesn't fit
@@ -388,7 +392,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
// Default is r/w, can be set to r/o below.
// Don't reset it when in readonly mode
// Only set/reset b_p_ro when BF_CHECK_RO is set.
- check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
+ bool check_readonly = (newfile && (curbuf->b_flags & BF_CHECK_RO));
if (check_readonly && !readonlymode) {
curbuf->b_p_ro = false;
}
@@ -559,7 +563,7 @@ int readfile(char *fname, char *sfname, linenr_T from, linenr_T lines_to_skip,
}
}
- (void)os_setperm(swap_fname, swap_mode);
+ os_setperm(swap_fname, swap_mode);
}
#endif
}
@@ -853,7 +857,7 @@ retry:
// Set "can_retry" when it's possible to rewind the file and try with
// another "fenc" value. It's false when no other "fenc" to try, reading
// stdin or fixed at a specific encoding.
- can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc && !read_fifo);
+ bool can_retry = (*fenc != NUL && !read_stdin && !keep_dest_enc && !read_fifo);
if (!skip_read) {
linerest = 0;
@@ -1151,7 +1155,6 @@ retry:
if (fio_flags != 0) {
unsigned u8c;
- char *dest;
char *tail = NULL;
// Convert Unicode or Latin1 to UTF-8.
@@ -1159,7 +1162,7 @@ retry:
// of bytes may increase.
// "dest" points to after where the UTF-8 bytes go, "p" points
// to after the next character to convert.
- dest = ptr + real_size;
+ char *dest = ptr + real_size;
if (fio_flags == FIO_LATIN1 || fio_flags == FIO_UTF8) {
p = (uint8_t *)ptr + size;
if (fio_flags == FIO_UTF8) {
@@ -1315,7 +1318,7 @@ retry:
assert(u8c <= INT_MAX);
// produce UTF-8
dest -= utf_char2len((int)u8c);
- (void)utf_char2bytes((int)u8c, dest);
+ utf_char2bytes((int)u8c, dest);
}
// move the linerest to before the converted characters
@@ -1532,8 +1535,7 @@ rewind_retry:
// Otherwise give an error message later.
if (try_unix
&& !read_stdin
- && (read_buffer
- || vim_lseek(fd, 0, SEEK_SET) == 0)) {
+ && (read_buffer || vim_lseek(fd, 0, SEEK_SET) == 0)) {
fileformat = EOL_UNIX;
if (set_options) {
set_fileformat(EOL_UNIX, OPT_LOCAL);
@@ -1618,7 +1620,7 @@ failed:
save_file_ff(curbuf);
// If editing a new file: set 'fenc' for the current buffer.
// Also for ":read ++edit file".
- set_string_option_direct("fenc", -1, fenc, OPT_FREE | OPT_LOCAL, 0);
+ set_string_option_direct(kOptFileencoding, fenc, OPT_LOCAL, 0);
}
if (fenc_alloced) {
xfree(fenc);
@@ -1630,7 +1632,7 @@ failed:
if (!read_buffer && !read_stdin) {
close(fd); // errors are ignored
} else {
- (void)os_set_cloexec(fd);
+ os_set_cloexec(fd);
}
xfree(buffer);
@@ -1938,7 +1940,7 @@ void prep_exarg(exarg_T *eap, const buf_T *buf)
}
/// Set default or forced 'fileformat' and 'binary'.
-void set_file_options(int set_options, exarg_T *eap)
+void set_file_options(bool set_options, exarg_T *eap)
{
// set default 'fileformat'
if (set_options) {
@@ -1966,7 +1968,7 @@ void set_forced_fenc(exarg_T *eap)
}
char *fenc = enc_canonize(eap->cmd + eap->force_enc);
- set_string_option_direct("fenc", -1, fenc, OPT_FREE|OPT_LOCAL, 0);
+ set_string_option_direct(kOptFileencoding, fenc, OPT_LOCAL, 0);
xfree(fenc);
}
@@ -2098,7 +2100,7 @@ int set_rw_fname(char *fname, char *sfname)
// Do filetype detection now if 'filetype' is empty.
if (*curbuf->b_p_ft == NUL) {
if (augroup_exists("filetypedetect")) {
- (void)do_doautocmd("filetypedetect BufRead", false, NULL);
+ do_doautocmd("filetypedetect BufRead", false, NULL);
}
do_modelines(0);
}
@@ -2199,7 +2201,7 @@ bool time_differs(const FileInfo *file_info, int64_t mtime, int64_t mtime_ns)
bool need_conversion(const char *fenc)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
- int same_encoding;
+ bool same_encoding;
int fenc_flags;
if (*fenc == NUL || strcmp(p_enc, fenc) == 0) {
@@ -2627,7 +2629,7 @@ static int rename_with_tmp(const char *const from, const char *const to)
STRCPY(tempname, from);
for (int n = 123; n < 99999; n++) {
char *tail = path_tail(tempname);
- snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - tempname - 1)), "%d", n);
+ snprintf(tail, (size_t)((MAXPATHL + 1) - (tail - tempname)), "%d", n);
if (!os_path_exists(tempname)) {
if (os_rename(from, tempname) == OK) {
@@ -2636,7 +2638,7 @@ static int rename_with_tmp(const char *const from, const char *const to)
}
// Strange, the second step failed. Try moving the
// file back and return failure.
- (void)os_rename(tempname, from);
+ os_rename(tempname, from);
return -1;
}
// If it fails for one temp name it will most likely fail
@@ -2755,7 +2757,7 @@ int vim_rename(const char *from, const char *to)
return 0;
}
-static int already_warned = false;
+static bool already_warned = false;
/// Check if any not hidden buffer has been changed.
/// Postpone the check if there are characters in the stuff buffer, a global
@@ -3047,7 +3049,7 @@ int buf_check_timestamp(buf_T *buf)
msg_puts_attr(mesg2, HL_ATTR(HLF_W) + MSG_HIST);
}
msg_clr_eos();
- (void)msg_end();
+ msg_end();
if (emsg_silent == 0 && !in_assert_fails) {
ui_flush();
// give the user some time to think about it
@@ -3078,7 +3080,7 @@ int buf_check_timestamp(buf_T *buf)
// Trigger FileChangedShell when the file was changed in any way.
if (bufref_valid(&bufref) && retval != 0) {
- (void)apply_autocmds(EVENT_FILECHANGEDSHELLPOST, buf->b_fname, buf->b_fname, false, buf);
+ apply_autocmds(EVENT_FILECHANGEDSHELLPOST, buf->b_fname, buf->b_fname, false, buf);
}
return retval;
}
@@ -3151,7 +3153,7 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
curbuf->b_flags |= BF_CHECK_RO; // check for RO again
keep_filetype = true; // don't detect 'filetype'
if (readfile(buf->b_ffname, buf->b_fname, 0, 0,
- (linenr_T)MAXLNUM, &ea, flags, false) != OK) {
+ (linenr_T)MAXLNUM, &ea, flags, shortmess(SHM_FILEINFO)) != OK) {
if (!aborting()) {
semsg(_("E321: Could not reload \"%s\""), buf->b_fname);
}
@@ -3163,14 +3165,13 @@ void buf_reload(buf_T *buf, int orig_mode, bool reload_options)
break;
}
}
- (void)move_lines(savebuf, buf);
+ move_lines(savebuf, buf);
}
} else if (buf == curbuf) { // "buf" still valid.
// Mark the buffer as unmodified and free undo info.
unchanged(buf, true, true);
if ((flags & READ_KEEP_UNDO) == 0) {
- u_blockfree(buf);
- u_clearall(buf);
+ u_clearallandblockfree(buf);
} else {
// Mark all undo states as changed.
u_unchanged(curbuf);
@@ -3278,7 +3279,7 @@ static void vim_mktempdir(void)
char user[40] = { 0 };
char appname[40] = { 0 };
- (void)os_get_username(user, sizeof(user));
+ os_get_username(user, sizeof(user));
// Usernames may contain slashes! #19240
memchrsub(user, '/', '_', sizeof(user));
memchrsub(user, '\\', '_', sizeof(user));
@@ -3304,7 +3305,7 @@ static void vim_mktempdir(void)
xstrlcat(tmp, appname, sizeof(tmp));
xstrlcat(tmp, ".", sizeof(tmp));
xstrlcat(tmp, user, sizeof(tmp));
- (void)os_mkdir(tmp, 0700); // Always create, to avoid a race.
+ os_mkdir(tmp, 0700); // Always create, to avoid a race.
bool owned = os_file_owned(tmp);
bool isdir = os_isdir(tmp);
#ifdef UNIX
@@ -3346,7 +3347,7 @@ static void vim_mktempdir(void)
// Couldn't set `vim_tempdir` to `path` so remove created directory.
os_rmdir(path);
}
- (void)umask(umask_save);
+ umask(umask_save);
}
/// Core part of "readdir()" function.
diff --git a/src/nvim/fileio.h b/src/nvim/fileio.h
index d1f6561507..26161c03ba 100644
--- a/src/nvim/fileio.h
+++ b/src/nvim/fileio.h
@@ -4,48 +4,54 @@
#include <stdio.h> // IWYU pragma: keep
#include <time.h> // IWYU pragma: keep
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/garray_defs.h" // IWYU pragma: keep
-#include "nvim/globals.h"
#include "nvim/os/fs_defs.h" // IWYU pragma: keep
-#include "nvim/pos_defs.h"
-
-// Values for readfile() flags
-#define READ_NEW 0x01 // read a file into a new buffer
-#define READ_FILTER 0x02 // read filter output
-#define READ_STDIN 0x04 // read from stdin
-#define READ_BUFFER 0x08 // read from curbuf (converting stdin)
-#define READ_DUMMY 0x10 // reading into a dummy buffer
-#define READ_KEEP_UNDO 0x20 // keep undo info
-#define READ_FIFO 0x40 // read from fifo or socket
-#define READ_NOWINENTER 0x80 // do not trigger BufWinEnter
-#define READ_NOFILE 0x100 // do not read a file, do trigger BufReadCmd
+#include "nvim/os/os_defs.h" // IWYU pragma: keep
+#include "nvim/pos_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
+
+/// Values for readfile() flags
+enum {
+ READ_NEW = 0x01, ///< read a file into a new buffer
+ READ_FILTER = 0x02, ///< read filter output
+ READ_STDIN = 0x04, ///< read from stdin
+ READ_BUFFER = 0x08, ///< read from curbuf (converting stdin)
+ READ_DUMMY = 0x10, ///< reading into a dummy buffer
+ READ_KEEP_UNDO = 0x20, ///< keep undo info
+ READ_FIFO = 0x40, ///< read from fifo or socket
+ READ_NOWINENTER = 0x80, ///< do not trigger BufWinEnter
+ READ_NOFILE = 0x100, ///< do not read a file, do trigger BufReadCmd
+};
typedef varnumber_T (*CheckItem)(void *expr, const char *name);
enum {
- FIO_LATIN1 = 0x01, // convert Latin1
- FIO_UTF8 = 0x02, // convert UTF-8
- FIO_UCS2 = 0x04, // convert UCS-2
- FIO_UCS4 = 0x08, // convert UCS-4
- FIO_UTF16 = 0x10, // convert UTF-16
- FIO_ENDIAN_L = 0x80, // little endian
- FIO_NOCONVERT = 0x2000, // skip encoding conversion
- FIO_UCSBOM = 0x4000, // check for BOM at start of file
- FIO_ALL = -1, // allow all formats
+ FIO_LATIN1 = 0x01, ///< convert Latin1
+ FIO_UTF8 = 0x02, ///< convert UTF-8
+ FIO_UCS2 = 0x04, ///< convert UCS-2
+ FIO_UCS4 = 0x08, ///< convert UCS-4
+ FIO_UTF16 = 0x10, ///< convert UTF-16
+ FIO_ENDIAN_L = 0x80, ///< little endian
+ FIO_NOCONVERT = 0x2000, ///< skip encoding conversion
+ FIO_UCSBOM = 0x4000, ///< check for BOM at start of file
+ FIO_ALL = -1, ///< allow all formats
};
-// When converting, a read() or write() may leave some bytes to be converted
-// for the next call. The value is guessed...
-#define CONV_RESTLEN 30
+enum {
+ /// When converting, a read() or write() may leave some bytes to be converted
+ /// for the next call. The value is guessed...
+ CONV_RESTLEN = 30,
+};
-#define WRITEBUFSIZE 8192 // size of normal write buffer
+enum { WRITEBUFSIZE = 8192, }; ///< size of normal write buffer
-// We have to guess how much a sequence of bytes may expand when converting
-// with iconv() to be able to allocate a buffer.
-#define ICONV_MULT 8
+enum {
+ /// We have to guess how much a sequence of bytes may expand when converting
+ /// with iconv() to be able to allocate a buffer.
+ ICONV_MULT = 8,
+};
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "fileio.h.generated.h"
diff --git a/src/nvim/fold.c b/src/nvim/fold.c
index c905b2d3ed..c571aaf0a4 100644
--- a/src/nvim/fold.c
+++ b/src/nvim/fold.c
@@ -26,20 +26,22 @@
#include "nvim/eval/typval.h"
#include "nvim/ex_session.h"
#include "nvim/extmark.h"
+#include "nvim/extmark_defs.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/garray_defs.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/indent.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/ops.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/os/input.h"
#include "nvim/plines.h"
@@ -320,42 +322,42 @@ foldinfo_T fold_info(win_T *win, linenr_T lnum)
// foldmethodIsManual() {{{2
/// @return true if 'foldmethod' is "manual"
-int foldmethodIsManual(win_T *wp)
+bool foldmethodIsManual(win_T *wp)
{
return wp->w_p_fdm[3] == 'u';
}
// foldmethodIsIndent() {{{2
/// @return true if 'foldmethod' is "indent"
-int foldmethodIsIndent(win_T *wp)
+bool foldmethodIsIndent(win_T *wp)
{
return wp->w_p_fdm[0] == 'i';
}
// foldmethodIsExpr() {{{2
/// @return true if 'foldmethod' is "expr"
-int foldmethodIsExpr(win_T *wp)
+bool foldmethodIsExpr(win_T *wp)
{
return wp->w_p_fdm[1] == 'x';
}
// foldmethodIsMarker() {{{2
/// @return true if 'foldmethod' is "marker"
-int foldmethodIsMarker(win_T *wp)
+bool foldmethodIsMarker(win_T *wp)
{
return wp->w_p_fdm[2] == 'r';
}
// foldmethodIsSyntax() {{{2
/// @return true if 'foldmethod' is "syntax"
-int foldmethodIsSyntax(win_T *wp)
+bool foldmethodIsSyntax(win_T *wp)
{
return wp->w_p_fdm[0] == 's';
}
// foldmethodIsDiff() {{{2
/// @return true if 'foldmethod' is "diff"
-int foldmethodIsDiff(win_T *wp)
+bool foldmethodIsDiff(win_T *wp)
{
return wp->w_p_fdm[0] == 'd';
}
@@ -372,7 +374,7 @@ void closeFold(pos_T pos, int count)
/// Close fold for current window at position `pos` recursively.
void closeFoldRecurse(pos_T pos)
{
- (void)setManualFold(pos, false, true, NULL);
+ setManualFold(pos, false, true, NULL);
}
// opFoldRange() {{{2
@@ -383,7 +385,7 @@ void closeFoldRecurse(pos_T pos)
/// @param opening true to open, false to close
/// @param recurse true to do it recursively
/// @param had_visual true when Visual selection used
-void opFoldRange(pos_T firstpos, pos_T lastpos, int opening, int recurse, int had_visual)
+void opFoldRange(pos_T firstpos, pos_T lastpos, int opening, int recurse, bool had_visual)
{
int done = DONE_NOTHING; // avoid error messages
linenr_T first = firstpos.lnum;
@@ -396,13 +398,13 @@ void opFoldRange(pos_T firstpos, pos_T lastpos, int opening, int recurse, int ha
// Opening one level only: next fold to open is after the one going to
// be opened.
if (opening && !recurse) {
- (void)hasFolding(lnum, NULL, &lnum_next);
+ hasFolding(lnum, NULL, &lnum_next);
}
- (void)setManualFold(temp, opening, recurse, &done);
+ setManualFold(temp, opening, recurse, &done);
// Closing one level only: next line to close a fold is after just
// closed fold.
if (!opening && !recurse) {
- (void)hasFolding(lnum, NULL, &lnum_next);
+ hasFolding(lnum, NULL, &lnum_next);
}
}
if (done == DONE_NOTHING) {
@@ -426,7 +428,7 @@ void openFold(pos_T pos, int count)
/// Open fold for current window at position `pos` recursively.
void openFoldRecurse(pos_T pos)
{
- (void)setManualFold(pos, true, true, NULL);
+ setManualFold(pos, true, true, NULL);
}
// foldOpenCursor() {{{2
@@ -437,7 +439,7 @@ void foldOpenCursor(void)
if (hasAnyFolding(curwin)) {
while (true) {
int done = DONE_NOTHING;
- (void)setManualFold(curwin->w_cursor, true, false, &done);
+ setManualFold(curwin->w_cursor, true, false, &done);
if (!(done & DONE_ACTION)) {
break;
}
@@ -537,8 +539,8 @@ int foldManualAllowed(bool create)
/// window.
void foldCreate(win_T *wp, pos_T start, pos_T end)
{
- int use_level = false;
- int closed = false;
+ bool use_level = false;
+ bool closed = false;
int level = 0;
pos_T start_rel = start;
pos_T end_rel = end;
@@ -794,7 +796,7 @@ void foldUpdate(win_T *wp, linenr_T top, linenr_T bot)
maybe_small_end = top;
}
fold_T *fp;
- (void)foldFind(&wp->w_folds, maybe_small_start, &fp);
+ foldFind(&wp->w_folds, maybe_small_start, &fp);
while (fp < (fold_T *)wp->w_folds.ga_data + wp->w_folds.ga_len
&& fp->fd_top <= maybe_small_end) {
fp->fd_small = kNone;
@@ -850,7 +852,6 @@ void foldUpdateAll(win_T *win)
int foldMoveTo(const bool updown, const int dir, const int count)
{
int retval = FAIL;
- linenr_T lnum;
fold_T *fp;
checkupdate(curwin);
@@ -909,7 +910,7 @@ int foldMoveTo(const bool updown, const int dir, const int count)
if (dir == FORWARD) {
// to start of next fold if there is one
if (fp + 1 - (fold_T *)gap->ga_data < gap->ga_len) {
- lnum = fp[1].fd_top + lnum_off;
+ linenr_T lnum = fp[1].fd_top + lnum_off;
if (lnum > curwin->w_cursor.lnum) {
lnum_found = lnum;
}
@@ -917,7 +918,7 @@ int foldMoveTo(const bool updown, const int dir, const int count)
} else {
// to end of previous fold if there is one
if (fp > (fold_T *)gap->ga_data) {
- lnum = fp[-1].fd_top + lnum_off + fp[-1].fd_len - 1;
+ linenr_T lnum = fp[-1].fd_top + lnum_off + fp[-1].fd_len - 1;
if (lnum < curwin->w_cursor.lnum) {
lnum_found = lnum;
}
@@ -927,12 +928,12 @@ int foldMoveTo(const bool updown, const int dir, const int count)
// Open fold found, set cursor to its start/end and then check
// nested folds.
if (dir == FORWARD) {
- lnum = fp->fd_top + lnum_off + fp->fd_len - 1;
+ linenr_T lnum = fp->fd_top + lnum_off + fp->fd_len - 1;
if (lnum > curwin->w_cursor.lnum) {
lnum_found = lnum;
}
} else {
- lnum = fp->fd_top + lnum_off;
+ linenr_T lnum = fp->fd_top + lnum_off;
if (lnum < curwin->w_cursor.lnum) {
lnum_found = lnum;
}
@@ -1000,7 +1001,6 @@ void foldAdjustVisual(void)
}
pos_T *start, *end;
- char *ptr;
if (ltoreq(VIsual, curwin->w_cursor)) {
start = &VIsual;
@@ -1017,7 +1017,7 @@ void foldAdjustVisual(void)
return;
}
- ptr = ml_get(end->lnum);
+ char *ptr = ml_get(end->lnum);
end->col = (colnr_T)strlen(ptr);
if (end->col > 0 && *p_sel == 'o') {
end->col--;
@@ -1030,7 +1030,7 @@ void foldAdjustVisual(void)
/// Move the cursor to the first line of a closed fold.
void foldAdjustCursor(void)
{
- (void)hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL);
+ hasFolding(curwin->w_cursor.lnum, &curwin->w_cursor.lnum, NULL);
}
// Internal functions for "fold_T" {{{1
@@ -1140,7 +1140,7 @@ static void setFoldRepeat(pos_T pos, int count, int do_open)
{
for (int n = 0; n < count; n++) {
int done = DONE_NOTHING;
- (void)setManualFold(pos, do_open, false, &done);
+ setManualFold(pos, do_open, false, &done);
if (!(done & DONE_ACTION)) {
// Only give an error message when no fold could be opened.
if (n == 0 && !(done & DONE_FOLD)) {
@@ -1157,7 +1157,7 @@ static void setFoldRepeat(pos_T pos, int count, int do_open)
///
/// @param opening true when opening, false when closing
/// @param recurse true when closing/opening recursive
-static linenr_T setManualFold(pos_T pos, int opening, int recurse, int *donep)
+static linenr_T setManualFold(pos_T pos, bool opening, bool recurse, int *donep)
{
if (foldmethodIsDiff(curwin) && curwin->w_p_scb) {
linenr_T dlnum;
@@ -1168,7 +1168,7 @@ static linenr_T setManualFold(pos_T pos, int opening, int recurse, int *donep)
if (wp != curwin && foldmethodIsDiff(wp) && wp->w_p_scb) {
dlnum = diff_lnum_win(curwin->w_cursor.lnum, wp);
if (dlnum != 0) {
- (void)setManualFoldWin(wp, dlnum, opening, recurse, NULL);
+ setManualFoldWin(wp, dlnum, opening, recurse, NULL);
}
}
}
@@ -1189,7 +1189,7 @@ static linenr_T setManualFold(pos_T pos, int opening, int recurse, int *donep)
///
/// @return the line number of the next line that could be closed.
/// It's only valid when "opening" is true!
-static linenr_T setManualFoldWin(win_T *wp, linenr_T lnum, int opening, int recurse, int *donep)
+static linenr_T setManualFoldWin(win_T *wp, linenr_T lnum, bool opening, bool recurse, int *donep)
{
fold_T *fp;
fold_T *fp2;
@@ -1390,7 +1390,7 @@ static void foldMarkAdjustRecurse(win_T *wp, garray_T *gap, linenr_T line1, line
// Find the fold containing or just below "line1".
fold_T *fp;
- (void)foldFind(gap, line1, &fp);
+ foldFind(gap, line1, &fp);
// Adjust all folds below "line1" that are affected.
for (int i = (int)(fp - (fold_T *)gap->ga_data); i < gap->ga_len; i++, fp++) {
@@ -1626,7 +1626,7 @@ static void foldAddMarker(buf_T *buf, pos_T pos, const char *marker, size_t mark
STRCPY(newline + line_len + (p - cms) + markerlen, p + 2);
added = markerlen + strlen(cms) - 2;
}
- ml_replace_buf(buf, lnum, newline, false);
+ ml_replace_buf(buf, lnum, newline, false, false);
if (added) {
extmark_splice_cols(buf, (int)lnum - 1, (int)line_len,
0, (int)added, kExtmarkUndo);
@@ -1637,7 +1637,7 @@ static void foldAddMarker(buf_T *buf, pos_T pos, const char *marker, size_t mark
/// Delete the markers for a fold, causing it to be deleted.
///
/// @param lnum_off offset for fp->fd_top
-static void deleteFoldMarkers(win_T *wp, fold_T *fp, int recursive, linenr_T lnum_off)
+static void deleteFoldMarkers(win_T *wp, fold_T *fp, bool recursive, linenr_T lnum_off)
{
if (recursive) {
for (int i = 0; i < fp->fd_nested.ga_len; i++) {
@@ -1690,7 +1690,7 @@ static void foldDelMarker(buf_T *buf, linenr_T lnum, char *marker, size_t marker
assert(p >= line);
memcpy(newline, line, (size_t)(p - line));
STRCPY(newline + (p - line), p + len);
- ml_replace_buf(buf, lnum, newline, false);
+ ml_replace_buf(buf, lnum, newline, false, false);
extmark_splice_cols(buf, (int)lnum - 1, (int)(p - line),
(int)len, 0, kExtmarkUndo);
}
@@ -2172,7 +2172,7 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
// startlnum, it must be deleted.
if (getlevel == foldlevelMarker && flp->start <= flp->lvl - level
&& flp->lvl > 0) {
- (void)foldFind(gap, startlnum - 1, &fp);
+ foldFind(gap, startlnum - 1, &fp);
if (fp != NULL
&& (fp >= ((fold_T *)gap->ga_data) + gap->ga_len
|| fp->fd_top >= startlnum)) {
@@ -2238,7 +2238,7 @@ static linenr_T foldUpdateIEMSRecurse(garray_T *const gap, const int level,
}
}
if (lvl < level + i) {
- (void)foldFind(&fp->fd_nested, flp->lnum - fp->fd_top, &fp2);
+ foldFind(&fp->fd_nested, flp->lnum - fp->fd_top, &fp2);
if (fp2 != NULL) {
bot = fp2->fd_top + fp2->fd_len - 1 + fp->fd_top;
}
@@ -2604,7 +2604,7 @@ static void foldSplit(buf_T *buf, garray_T *const gap, const int i, const linenr
// any between top and bot, they have been removed by the caller.
garray_T *const gap1 = &fp->fd_nested;
garray_T *const gap2 = &fp[1].fd_nested;
- (void)foldFind(gap1, bot + 1 - fp->fd_top, &fp2);
+ foldFind(gap1, bot + 1 - fp->fd_top, &fp2);
if (fp2 != NULL) {
const int len = (int)((fold_T *)gap1->ga_data + gap1->ga_len - fp2);
if (len > 0) {
@@ -2803,7 +2803,8 @@ void foldMoveRange(win_T *const wp, garray_T *gap, const linenr_T line1, const l
// Case 5 or 6: changes rely on whether there are folds between the end of
// this fold and "dest".
size_t move_start = FOLD_INDEX(fp, gap);
- size_t move_end = 0, dest_index = 0;
+ size_t move_end = 0;
+ size_t dest_index = 0;
for (; VALID_FOLD(fp, gap) && fp->fd_top <= dest; fp++) {
if (fp->fd_top <= line2) {
// 5, or 6
@@ -2982,7 +2983,9 @@ static void foldlevelExpr(fline_T *flp)
// "<1", "<2", .. : end a fold with a certain level
case '<':
- flp->lvl_next = n - 1;
+ // To prevent an unexpected start of a new fold, the next
+ // level must not exceed the level of the current fold.
+ flp->lvl_next = MIN(flp->lvl, n - 1);
flp->end = n;
break;
@@ -3234,7 +3237,7 @@ static int put_fold_open_close(FILE *fd, fold_T *fp, linenr_T off)
// }}}1
/// "foldclosed()" and "foldclosedend()" functions
-static void foldclosed_both(typval_T *argvars, typval_T *rettv, int end)
+static void foldclosed_both(typval_T *argvars, typval_T *rettv, bool end)
{
const linenr_T lnum = tv_get_lnum(argvars);
if (lnum >= 1 && lnum <= curbuf->b_ml.ml_line_count) {
diff --git a/src/nvim/fold.h b/src/nvim/fold.h
index 3a70c11792..f9044d247f 100644
--- a/src/nvim/fold.h
+++ b/src/nvim/fold.h
@@ -1,13 +1,14 @@
#pragma once
-#include <stdio.h>
+#include <stdio.h> // IWYU pragma: keep
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
-#include "nvim/fold_defs.h" // IWYU pragma: export
+#include "nvim/decoration_defs.h" // IWYU pragma: keep
+#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
+#include "nvim/fold_defs.h" // IWYU pragma: keep
#include "nvim/garray_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
-#include "nvim/pos_defs.h"
-#include "nvim/types_defs.h"
+#include "nvim/pos_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
EXTERN int disable_fold_update INIT( = 0);
diff --git a/src/nvim/fold_defs.h b/src/nvim/fold_defs.h
index 68ecd9cc7e..453819d6f1 100644
--- a/src/nvim/fold_defs.h
+++ b/src/nvim/fold_defs.h
@@ -4,7 +4,7 @@
/// Info used to pass info about a fold from the fold-detection code to the
/// code that displays the foldcolumn.
-typedef struct foldinfo {
+typedef struct {
linenr_T fi_lnum; ///< line number where fold starts
int fi_level; ///< level of the fold; when this is zero the
///< other fields are invalid
diff --git a/src/nvim/func_attr.h b/src/nvim/func_attr.h
index 15370dcb3e..43af880767 100644
--- a/src/nvim/func_attr.h
+++ b/src/nvim/func_attr.h
@@ -1,24 +1,16 @@
-// If DEFINE_FUNC_ATTRIBUTES macro is not defined then all function attributes
-// are defined as empty values.
-//
-// If DO_NOT_DEFINE_EMPTY_ATTRIBUTES then empty macros are not defined. Thus
-// undefined DEFINE_FUNC_ATTRIBUTES and defined DO_NOT_DEFINE_EMPTY_ATTRIBUTES
+// Undefined DEFINE_FUNC_ATTRIBUTES and undefined DEFINE_EMPTY_ATTRIBUTES
// leaves file with untouched FUNC_ATTR_* macros. This variant is used for
-// scripts/gendeclarations.lua.
+// scripts/gen_declarations.lua.
//
-// Empty macros are used for *.c files. (undefined DEFINE_FUNC_ATTRIBUTES and
-// undefined DO_NOT_DEFINE_EMPTY_ATTRIBUTES)
+// Empty macros are used for *.c files.
+// (undefined DEFINE_FUNC_ATTRIBUTES and defined DEFINE_EMPTY_ATTRIBUTES)
//
// Macros defined as __attribute__((*)) are used by generated header files.
-// (defined DEFINE_FUNC_ATTRIBUTES and undefined
-// DO_NOT_DEFINE_EMPTY_ATTRIBUTES)
-//
-// Defined DEFINE_FUNC_ATTRIBUTES and defined DO_NOT_DEFINE_EMPTY_ATTRIBUTES is
-// not used by anything.
+// (defined DEFINE_FUNC_ATTRIBUTES and undefined DEFINE_EMPTY_ATTRIBUTES)
// FUNC_ATTR_* macros should be in *.c files for declarations generator. If you
// define a function for which declaration is not generated by
-// gendeclarations.lua (e.g. template hash implementation) then you should use
+// gen_declarations.lua (e.g. template hash implementation) then you should use
// REAL_FATTR_* macros.
// gcc and clang expose their version as follows:
@@ -217,9 +209,11 @@
# endif
#endif
-#ifdef DEFINE_FUNC_ATTRIBUTES
+#if defined(DEFINE_FUNC_ATTRIBUTES) || defined(DEFINE_EMPTY_ATTRIBUTES)
/// Fast (non-deferred) API function.
# define FUNC_API_FAST
+/// Return value needs to be freed
+# define FUNC_API_RET_ALLOC
/// Internal C function not exposed in the RPC API.
# define FUNC_API_NOEXPORT
/// API function not exposed in Vimscript/eval.
@@ -234,6 +228,9 @@
# define FUNC_API_SINCE(X)
/// API function deprecated since the given API level.
# define FUNC_API_DEPRECATED_SINCE(X)
+#endif
+
+#if defined(DEFINE_FUNC_ATTRIBUTES)
# define FUNC_ATTR_MALLOC REAL_FATTR_MALLOC
# define FUNC_ATTR_ALLOC_SIZE(x) REAL_FATTR_ALLOC_SIZE(x)
# define FUNC_ATTR_ALLOC_SIZE_PROD(x, y) REAL_FATTR_ALLOC_SIZE_PROD(x, y)
@@ -250,7 +247,7 @@
# define FUNC_ATTR_NO_SANITIZE_UNDEFINED REAL_FATTR_NO_SANITIZE_UNDEFINED
# define FUNC_ATTR_NO_SANITIZE_ADDRESS REAL_FATTR_NO_SANITIZE_ADDRESS
# define FUNC_ATTR_PRINTF(x, y) REAL_FATTR_PRINTF(x, y)
-#elif !defined(DO_NOT_DEFINE_EMPTY_ATTRIBUTES)
+#elif defined(DEFINE_EMPTY_ATTRIBUTES)
# define FUNC_ATTR_MALLOC
# define FUNC_ATTR_ALLOC_SIZE(x)
# define FUNC_ATTR_ALLOC_SIZE_PROD(x, y)
diff --git a/src/nvim/garray.c b/src/nvim/garray.c
index 24b6fb0007..f87a196361 100644
--- a/src/nvim/garray.c
+++ b/src/nvim/garray.c
@@ -5,7 +5,6 @@
#include <stdint.h>
#include <string.h>
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/log.h"
#include "nvim/memory.h"
@@ -13,7 +12,7 @@
#include "nvim/strings.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "garray.c.generated.h" // IWYU pragma: export
+# include "garray.c.generated.h"
#endif
/// Clear an allocated growing array.
@@ -218,3 +217,12 @@ void ga_append(garray_T *gap, uint8_t c)
{
GA_APPEND(uint8_t, gap, c);
}
+
+void *ga_append_via_ptr(garray_T *gap, size_t item_size)
+{
+ if ((int)item_size != gap->ga_itemsize) {
+ WLOG("wrong item size (%zu), should be %d", item_size, gap->ga_itemsize);
+ }
+ ga_grow(gap, 1);
+ return ((char *)gap->ga_data) + (item_size * (size_t)gap->ga_len++);
+}
diff --git a/src/nvim/garray.h b/src/nvim/garray.h
index a96deda759..7a766f988a 100644
--- a/src/nvim/garray.h
+++ b/src/nvim/garray.h
@@ -3,10 +3,8 @@
#include <stdbool.h>
#include <stddef.h>
-#include "nvim/garray_defs.h" // IWYU pragma: export
-#include "nvim/log.h"
+#include "nvim/garray_defs.h" // IWYU pragma: keep
#include "nvim/memory.h"
-#include "nvim/types_defs.h"
#define GA_EMPTY(ga_ptr) ((ga_ptr)->ga_len <= 0)
@@ -24,15 +22,6 @@
# include "garray.h.generated.h"
#endif
-static inline void *ga_append_via_ptr(garray_T *gap, size_t item_size)
-{
- if ((int)item_size != gap->ga_itemsize) {
- WLOG("wrong item size (%zu), should be %d", item_size, gap->ga_itemsize);
- }
- ga_grow(gap, 1);
- return ((char *)gap->ga_data) + (item_size * (size_t)gap->ga_len++);
-}
-
/// Deep free a garray of specific type using a custom free function.
/// Items in the array as well as the array itself are freed.
///
diff --git a/src/nvim/garray_defs.h b/src/nvim/garray_defs.h
index 5f4032884e..4db9667a43 100644
--- a/src/nvim/garray_defs.h
+++ b/src/nvim/garray_defs.h
@@ -5,7 +5,7 @@
/// Structure used for growing arrays.
/// This is used to store information that only grows, is deleted all at
/// once, and needs to be accessed by index. See ga_clear() and ga_grow().
-typedef struct growarray {
+typedef struct {
int ga_len; // current number of items used
int ga_maxlen; // maximum number of items possible
int ga_itemsize; // sizeof(item)
diff --git a/src/nvim/generators/c_grammar.lua b/src/nvim/generators/c_grammar.lua
index f33da452ff..9ce9f3d7a6 100644
--- a/src/nvim/generators/c_grammar.lua
+++ b/src/nvim/generators/c_grammar.lua
@@ -6,61 +6,112 @@ local lpeg = vim.lpeg
local P, R, S = lpeg.P, lpeg.R, lpeg.S
local C, Ct, Cc, Cg = lpeg.C, lpeg.Ct, lpeg.Cc, lpeg.Cg
+--- @param pat vim.lpeg.Pattern
+local function rep(pat)
+ return pat ^ 0
+end
+
+--- @param pat vim.lpeg.Pattern
+local function rep1(pat)
+ return pat ^ 1
+end
+
+--- @param pat vim.lpeg.Pattern
+local function opt(pat)
+ return pat ^ -1
+end
+
local any = P(1) -- (consume one character)
local letter = R('az', 'AZ') + S('_$')
local num = R('09')
local alpha = letter + num
local nl = P('\r\n') + P('\n')
local not_nl = any - nl
-local ws = S(' \t') + nl
-local fill = ws ^ 0
-local c_comment = P('//') * (not_nl ^ 0)
-local c_preproc = P('#') * (not_nl ^ 0)
-local dllexport = P('DLLEXPORT') * (ws ^ 1)
-local typed_container =
- (P('ArrayOf(') + P('DictionaryOf(') + P('Dict(')) * ((any - P(')')) ^ 1) * P(')')
-local c_id = (
- typed_container +
- (letter * (alpha ^ 0))
+local space = S(' \t')
+local ws = space + nl
+local fill = rep(ws)
+local c_comment = P('//') * rep(not_nl)
+local cdoc_comment = P('///') * opt(Ct(Cg(rep(space) * rep(not_nl), 'comment')))
+local c_preproc = P('#') * rep(not_nl)
+local dllexport = P('DLLEXPORT') * rep1(ws)
+
+local typed_container = (
+ (P('ArrayOf(') + P('DictionaryOf(') + P('Dict('))
+ * rep1(any - P(')'))
+ * P(')')
)
+
+local c_id = (typed_container + (letter * rep(alpha)))
local c_void = P('void')
+
local c_param_type = (
- ((P('Error') * fill * P('*') * fill) * Cc('error')) +
- ((P('Arena') * fill * P('*') * fill) * Cc('arena')) +
- ((P('lua_State') * fill * P('*') * fill) * Cc('lstate')) +
- C((P('const ') ^ -1) * (c_id) * (ws ^ 1) * P('*')) +
- (C(c_id) * (ws ^ 1))
- )
+ ((P('Error') * fill * P('*') * fill) * Cc('error'))
+ + ((P('Arena') * fill * P('*') * fill) * Cc('arena'))
+ + ((P('lua_State') * fill * P('*') * fill) * Cc('lstate'))
+ + C(opt(P('const ')) * c_id * rep1(ws) * rep1(P('*')))
+ + (C(c_id) * rep1(ws))
+)
+
local c_type = (C(c_void) * (ws ^ 1)) + c_param_type
local c_param = Ct(c_param_type * C(c_id))
local c_param_list = c_param * (fill * (P(',') * fill * c_param) ^ 0)
local c_params = Ct(c_void + c_param_list)
+
+local impl_line = (any - P('}')) * opt(rep(not_nl)) * nl
+
+local ignore_line = rep1(not_nl) * nl
+
+local empty_line = Ct(Cc('empty') * nl * nl)
+
local c_proto = Ct(
- (dllexport ^ -1) *
- Cg(c_type, 'return_type') * Cg(c_id, 'name') *
- fill * P('(') * fill * Cg(c_params, 'parameters') * fill * P(')') *
- Cg(Cc(false), 'fast') *
- (fill * Cg((P('FUNC_API_SINCE(') * C(num ^ 1)) * P(')'), 'since') ^ -1) *
- (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(num ^ 1)) * P(')'),
- 'deprecated_since') ^ -1) *
- (fill * Cg((P('FUNC_API_FAST') * Cc(true)), 'fast') ^ -1) *
- (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1) *
- (fill * Cg((P('FUNC_API_REMOTE_ONLY') * Cc(true)), 'remote_only') ^ -1) *
- (fill * Cg((P('FUNC_API_LUA_ONLY') * Cc(true)), 'lua_only') ^ -1) *
- (fill * (Cg(P('FUNC_API_TEXTLOCK_ALLOW_CMDWIN') * Cc(true), 'textlock_allow_cmdwin') +
- Cg(P('FUNC_API_TEXTLOCK') * Cc(true), 'textlock')) ^ -1) *
- (fill * Cg((P('FUNC_API_REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1) *
- (fill * Cg((P('FUNC_API_COMPOSITOR_IMPL') * Cc(true)), 'compositor_impl') ^ -1) *
- (fill * Cg((P('FUNC_API_CLIENT_IMPL') * Cc(true)), 'client_impl') ^ -1) *
- (fill * Cg((P('FUNC_API_CLIENT_IGNORE') * Cc(true)), 'client_ignore') ^ -1) *
- fill * P(';')
- )
+ Cc('proto')
+ * opt(dllexport)
+ * opt(Cg(P('static') * fill * Cc(true), 'static'))
+ * Cg(c_type, 'return_type')
+ * Cg(c_id, 'name')
+ * fill
+ * (P('(') * fill * Cg(c_params, 'parameters') * fill * P(')'))
+ * Cg(Cc(false), 'fast')
+ * (fill * Cg((P('FUNC_API_SINCE(') * C(rep1(num))) * P(')'), 'since') ^ -1)
+ * (fill * Cg((P('FUNC_API_DEPRECATED_SINCE(') * C(rep1(num))) * P(')'), 'deprecated_since') ^ -1)
+ * (fill * Cg((P('FUNC_API_FAST') * Cc(true)), 'fast') ^ -1)
+ * (fill * Cg((P('FUNC_API_RET_ALLOC') * Cc(true)), 'ret_alloc') ^ -1)
+ * (fill * Cg((P('FUNC_API_NOEXPORT') * Cc(true)), 'noexport') ^ -1)
+ * (fill * Cg((P('FUNC_API_REMOTE_ONLY') * Cc(true)), 'remote_only') ^ -1)
+ * (fill * Cg((P('FUNC_API_LUA_ONLY') * Cc(true)), 'lua_only') ^ -1)
+ * (fill * (Cg(P('FUNC_API_TEXTLOCK_ALLOW_CMDWIN') * Cc(true), 'textlock_allow_cmdwin') + Cg(
+ P('FUNC_API_TEXTLOCK') * Cc(true),
+ 'textlock'
+ )) ^ -1)
+ * (fill * Cg((P('FUNC_API_REMOTE_IMPL') * Cc(true)), 'remote_impl') ^ -1)
+ * (fill * Cg((P('FUNC_API_COMPOSITOR_IMPL') * Cc(true)), 'compositor_impl') ^ -1)
+ * (fill * Cg((P('FUNC_API_CLIENT_IMPL') * Cc(true)), 'client_impl') ^ -1)
+ * (fill * Cg((P('FUNC_API_CLIENT_IGNORE') * Cc(true)), 'client_ignore') ^ -1)
+ * fill
+ * (P(';') + (P('{') * nl + (impl_line ^ 0) * P('}')))
+)
local c_field = Ct(Cg(c_id, 'type') * ws * Cg(c_id, 'name') * fill * P(';') * fill)
local c_keyset = Ct(
- P('typedef') * ws * P('struct') * fill * P('{') * fill *
- Cg(Ct(c_field ^ 1), 'fields') *
- P('}') * fill * P('Dict') * fill * P('(') * Cg(c_id, 'keyset_name') * fill * P(')') * P(';'))
+ P('typedef')
+ * ws
+ * P('struct')
+ * fill
+ * P('{')
+ * fill
+ * Cg(Ct(c_field ^ 1), 'fields')
+ * P('}')
+ * fill
+ * P('Dict')
+ * fill
+ * P('(')
+ * Cg(c_id, 'keyset_name')
+ * fill
+ * P(')')
+ * P(';')
+)
-local grammar = Ct((c_proto + c_comment + c_preproc + ws + c_keyset) ^ 1)
-return {grammar=grammar, typed_container=typed_container}
+local grammar = Ct(
+ rep1(empty_line + c_proto + cdoc_comment + c_comment + c_preproc + ws + c_keyset + ignore_line)
+)
+return { grammar = grammar, typed_container = typed_container }
diff --git a/src/nvim/generators/dump_bin_array.lua b/src/nvim/generators/dump_bin_array.lua
index bee5aba73f..c6cda25e73 100644
--- a/src/nvim/generators/dump_bin_array.lua
+++ b/src/nvim/generators/dump_bin_array.lua
@@ -1,10 +1,10 @@
local function dump_bin_array(output, name, data)
output:write([[
- static const uint8_t ]]..name..[[[] = {
+ static const uint8_t ]] .. name .. [[[] = {
]])
for i = 1, #data do
- output:write(string.byte(data, i)..', ')
+ output:write(string.byte(data, i) .. ', ')
if i % 10 == 0 then
output:write('\n ')
end
diff --git a/src/nvim/generators/gen_api_dispatch.lua b/src/nvim/generators/gen_api_dispatch.lua
index 9720cca477..04b4363e42 100644
--- a/src/nvim/generators/gen_api_dispatch.lua
+++ b/src/nvim/generators/gen_api_dispatch.lua
@@ -1,16 +1,19 @@
local mpack = vim.mpack
-local hashy = require'generators.hashy'
+local hashy = require 'generators.hashy'
-assert(#arg >= 5)
+local pre_args = 7
+assert(#arg >= pre_args)
-- output h file with generated dispatch functions (dispatch_wrappers.generated.h)
local dispatch_outputf = arg[1]
--- output h file with packed metadata (funcs_metadata.generated.h)
-local funcs_metadata_outputf = arg[2]
+-- output h file with packed metadata (api_metadata.generated.h)
+local api_metadata_outputf = arg[2]
-- output metadata mpack file, for use by other build scripts (api_metadata.mpack)
local mpack_outputf = arg[3]
local lua_c_bindings_outputf = arg[4] -- lua_api_c_bindings.generated.c
local keysets_outputf = arg[5] -- keysets_defs.generated.h
+local ui_metadata_inputf = arg[6] -- ui events metadata
+local git_version_inputf = arg[7] -- git version header
local functions = {}
@@ -23,16 +26,18 @@ local function_names = {}
local c_grammar = require('generators.c_grammar')
-local function startswith(String,Start)
- return string.sub(String,1,string.len(Start))==Start
-end
+local startswith = vim.startswith
local function add_function(fn)
- local public = startswith(fn.name, "nvim_") or fn.deprecated_since
+ local public = startswith(fn.name, 'nvim_') or fn.deprecated_since
if public and not fn.noexport then
functions[#functions + 1] = fn
function_names[fn.name] = true
- if #fn.parameters >= 2 and fn.parameters[2][1] == 'Array' and fn.parameters[2][2] == 'uidata' then
+ if
+ #fn.parameters >= 2
+ and fn.parameters[2][1] == 'Array'
+ and fn.parameters[2][2] == 'uidata'
+ then
-- function receives the "args" as a parameter
fn.receives_array_args = true
-- remove the args parameter
@@ -51,15 +56,14 @@ local function add_function(fn)
-- for specifying errors
fn.parameters[#fn.parameters] = nil
end
- if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'arena' then
- -- return value is allocated in an arena
- fn.arena_return = true
- fn.parameters[#fn.parameters] = nil
- end
if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'lstate' then
fn.has_lua_imp = true
fn.parameters[#fn.parameters] = nil
end
+ if #fn.parameters ~= 0 and fn.parameters[#fn.parameters][1] == 'arena' then
+ fn.receives_arena = true
+ fn.parameters[#fn.parameters] = nil
+ end
end
end
@@ -70,7 +74,7 @@ local function add_keyset(val)
local types = {}
local is_set_name = 'is_set__' .. val.keyset_name .. '_'
local has_optional = false
- for i,field in ipairs(val.fields) do
+ for i, field in ipairs(val.fields) do
if field.type ~= 'Object' then
types[field.name] = field.type
end
@@ -80,36 +84,46 @@ local function add_keyset(val)
if i > 1 then
error("'is_set__{type}_' must be first if present")
elseif field.name ~= is_set_name then
- error(val.keyset_name..": name of first key should be "..is_set_name)
+ error(val.keyset_name .. ': name of first key should be ' .. is_set_name)
elseif field.type ~= 'OptionalKeys' then
- error("'"..is_set_name.."' must have type 'OptionalKeys'")
+ error("'" .. is_set_name .. "' must have type 'OptionalKeys'")
end
has_optional = true
end
end
- table.insert(keysets, {name=val.keyset_name, keys=keys, types=types, has_optional=has_optional})
+ table.insert(keysets, {
+ name = val.keyset_name,
+ keys = keys,
+ types = types,
+ has_optional = has_optional,
+ })
end
+local ui_options_text = nil
+
-- read each input file, parse and append to the api metadata
-for i = 6, #arg do
+for i = pre_args + 1, #arg do
local full_path = arg[i]
local parts = {}
for part in string.gmatch(full_path, '[^/]+') do
parts[#parts + 1] = part
end
- headers[#headers + 1] = parts[#parts - 1]..'/'..parts[#parts]
+ headers[#headers + 1] = parts[#parts - 1] .. '/' .. parts[#parts]
- local input = io.open(full_path, 'rb')
+ local input = assert(io.open(full_path, 'rb'))
- local tmp = c_grammar.grammar:match(input:read('*all'))
+ local text = input:read('*all')
+ local tmp = c_grammar.grammar:match(text)
for j = 1, #tmp do
local val = tmp[j]
if val.keyset_name then
add_keyset(val)
- else
+ elseif val.name then
add_function(val)
end
end
+
+ ui_options_text = ui_options_text or string.match(text, 'ui_ext_names%[][^{]+{([^}]+)}')
input:close()
end
@@ -123,14 +137,14 @@ end
-- Export functions under older deprecated names.
-- These will be removed eventually.
-local deprecated_aliases = require("api.dispatch_deprecated")
-for _,f in ipairs(shallowcopy(functions)) do
+local deprecated_aliases = require('api.dispatch_deprecated')
+for _, f in ipairs(shallowcopy(functions)) do
local ismethod = false
- if startswith(f.name, "nvim_") then
- if startswith(f.name, "nvim__") or f.name == "nvim_error_event" then
+ if startswith(f.name, 'nvim_') then
+ if startswith(f.name, 'nvim__') or f.name == 'nvim_error_event' then
f.since = -1
elseif f.since == nil then
- print("Function "..f.name.." lacks since field.\n")
+ print('Function ' .. f.name .. ' lacks since field.\n')
os.exit(1)
end
f.since = tonumber(f.since)
@@ -138,16 +152,16 @@ for _,f in ipairs(shallowcopy(functions)) do
f.deprecated_since = tonumber(f.deprecated_since)
end
- if startswith(f.name, "nvim_buf_") then
+ if startswith(f.name, 'nvim_buf_') then
ismethod = true
- elseif startswith(f.name, "nvim_win_") then
+ elseif startswith(f.name, 'nvim_win_') then
ismethod = true
- elseif startswith(f.name, "nvim_tabpage_") then
+ elseif startswith(f.name, 'nvim_tabpage_') then
ismethod = true
end
f.remote = f.remote_only or not f.lua_only
f.lua = f.lua_only or not f.remote_only
- f.eval = (not f.lua_only) and (not f.remote_only)
+ f.eval = (not f.lua_only) and not f.remote_only
else
f.deprecated_since = tonumber(f.deprecated_since)
assert(f.deprecated_since == 1)
@@ -159,63 +173,127 @@ for _,f in ipairs(shallowcopy(functions)) do
if newname ~= nil then
if function_names[newname] then
-- duplicate
- print("Function "..f.name.." has deprecated alias\n"
- ..newname.." which has a separate implementation.\n"..
- "Please remove it from src/nvim/api/dispatch_deprecated.lua")
+ print(
+ 'Function '
+ .. f.name
+ .. ' has deprecated alias\n'
+ .. newname
+ .. ' which has a separate implementation.\n'
+ .. 'Please remove it from src/nvim/api/dispatch_deprecated.lua'
+ )
os.exit(1)
end
local newf = shallowcopy(f)
newf.name = newname
- if newname == "ui_try_resize" then
+ if newname == 'ui_try_resize' then
-- The return type was incorrectly set to Object in 0.1.5.
-- Keep it that way for clients that rely on this.
- newf.return_type = "Object"
+ newf.return_type = 'Object'
end
newf.impl_name = f.name
newf.lua = false
newf.eval = false
newf.since = 0
newf.deprecated_since = 1
- functions[#functions+1] = newf
+ functions[#functions + 1] = newf
end
end
-- don't expose internal attributes like "impl_name" in public metadata
-local exported_attributes = {'name', 'return_type', 'method',
- 'since', 'deprecated_since'}
+local exported_attributes = { 'name', 'return_type', 'method', 'since', 'deprecated_since' }
local exported_functions = {}
-for _,f in ipairs(functions) do
- if not (startswith(f.name, "nvim__") or f.name == "nvim_error_event" or f.name == "redraw") then
+for _, f in ipairs(functions) do
+ if not (startswith(f.name, 'nvim__') or f.name == 'nvim_error_event' or f.name == 'redraw') then
local f_exported = {}
- for _,attr in ipairs(exported_attributes) do
+ for _, attr in ipairs(exported_attributes) do
f_exported[attr] = f[attr]
end
f_exported.parameters = {}
- for i,param in ipairs(f.parameters) do
- if param[1] == "DictionaryOf(LuaRef)" then
- param = {"Dictionary", param[2]}
- elseif startswith(param[1], "Dict(") then
- param = {"Dictionary", param[2]}
+ for i, param in ipairs(f.parameters) do
+ if param[1] == 'DictionaryOf(LuaRef)' then
+ param = { 'Dictionary', param[2] }
+ elseif startswith(param[1], 'Dict(') then
+ param = { 'Dictionary', param[2] }
end
f_exported.parameters[i] = param
end
- exported_functions[#exported_functions+1] = f_exported
+ if startswith(f.return_type, 'Dict(') then
+ f_exported.return_type = 'Dictionary'
+ end
+ exported_functions[#exported_functions + 1] = f_exported
end
end
+local ui_options = { 'rgb' }
+for x in string.gmatch(ui_options_text, '"([a-z][a-z_]+)"') do
+ table.insert(ui_options, x)
+end
+
+local version = require 'nvim_version'
+local git_version = io.open(git_version_inputf):read '*a'
+local version_build = string.match(git_version, '#define NVIM_VERSION_BUILD "([^"]+)"') or vim.NIL
-- serialize the API metadata using msgpack and embed into the resulting
-- binary for easy querying by clients
-local funcs_metadata_output = io.open(funcs_metadata_outputf, 'wb')
-local packed = mpack.encode(exported_functions)
-local dump_bin_array = require("generators.dump_bin_array")
-dump_bin_array(funcs_metadata_output, 'funcs_metadata', packed)
-funcs_metadata_output:close()
+local api_metadata_output = assert(io.open(api_metadata_outputf, 'wb'))
+local pieces = {}
+
+-- Naively using mpack.encode({foo=x, bar=y}) will make the build
+-- "non-reproducible". Emit maps directly as FIXDICT(2) "foo" x "bar" y instead
+local function fixdict(num)
+ if num > 15 then
+ error 'implement more dict codes'
+ end
+ table.insert(pieces, string.char(128 + num))
+end
+local function put(item, item2)
+ table.insert(pieces, mpack.encode(item))
+ if item2 ~= nil then
+ table.insert(pieces, mpack.encode(item2))
+ end
+end
+
+fixdict(6)
+
+put('version')
+fixdict(1 + #version)
+for _, item in ipairs(version) do
+ -- NB: all items are mandatory. But any error will be less confusing
+ -- with placholder vim.NIL (than invalid mpack data)
+ put(item[1], item[2] or vim.NIL)
+end
+put('build', version_build)
+
+put('functions', exported_functions)
+put('ui_events')
+table.insert(pieces, io.open(ui_metadata_inputf, 'rb'):read('*all'))
+put('ui_options', ui_options)
+
+put('error_types')
+fixdict(2)
+put('Exception', { id = 0 })
+put('Validation', { id = 1 })
+
+put('types')
+local types =
+ { { 'Buffer', 'nvim_buf_' }, { 'Window', 'nvim_win_' }, { 'Tabpage', 'nvim_tabpage_' } }
+fixdict(#types)
+for i, item in ipairs(types) do
+ put(item[1])
+ fixdict(2)
+ put('id', i - 1)
+ put('prefix', item[2])
+end
+
+local packed = table.concat(pieces)
+local dump_bin_array = require('generators.dump_bin_array')
+dump_bin_array(api_metadata_output, 'packed_api_metadata', packed)
+api_metadata_output:close()
-- start building the dispatch wrapper output
-local output = io.open(dispatch_outputf, 'wb')
+local output = assert(io.open(dispatch_outputf, 'wb'))
-local keysets_defs = io.open(keysets_outputf, 'wb')
+local keysets_defs = assert(io.open(keysets_outputf, 'wb'))
-- ===========================================================================
-- NEW API FILES MUST GO HERE.
@@ -226,9 +304,9 @@ local keysets_defs = io.open(keysets_outputf, 'wb')
output:write([[
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
+#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/map_defs.h"
-#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/api/autocmd.h"
#include "nvim/api/buffer.h"
@@ -246,67 +324,84 @@ output:write([[
]])
-for _,k in ipairs(keysets) do
+keysets_defs:write('// IWYU pragma: private, include "nvim/api/private/dispatch.h"\n\n')
+
+for _, k in ipairs(keysets) do
local c_name = {}
- for i = 1,#k.keys do
+ for i = 1, #k.keys do
-- some keys, like "register" are c keywords and get
-- escaped with a trailing _ in the struct.
- if vim.endswith(k.keys[i], "_") then
+ if vim.endswith(k.keys[i], '_') then
local orig = k.keys[i]
- k.keys[i] = string.sub(k.keys[i],1, #(k.keys[i]) - 1)
+ k.keys[i] = string.sub(k.keys[i], 1, #k.keys[i] - 1)
c_name[k.keys[i]] = orig
k.types[k.keys[i]] = k.types[orig]
end
end
- local neworder, hashfun = hashy.hashy_hash(k.name, k.keys, function (idx)
- return k.name.."_table["..idx.."].str"
+ local neworder, hashfun = hashy.hashy_hash(k.name, k.keys, function(idx)
+ return k.name .. '_table[' .. idx .. '].str'
end)
- keysets_defs:write("extern KeySetLink "..k.name.."_table[];\n")
+ keysets_defs:write('extern KeySetLink ' .. k.name .. '_table[' .. (1 + #neworder) .. '];\n')
local function typename(type)
- if type ~= nil then
- return "kObjectType"..type
+ if type == 'HLGroupID' then
+ return 'kObjectTypeInteger'
+ elseif type ~= nil then
+ return 'kObjectType' .. type
else
- return "kObjectTypeNil"
+ return 'kObjectTypeNil'
end
end
- output:write("KeySetLink "..k.name.."_table[] = {\n")
+ output:write('KeySetLink ' .. k.name .. '_table[] = {\n')
for i, key in ipairs(neworder) do
local ind = -1
if k.has_optional then
ind = i
- keysets_defs:write("#define KEYSET_OPTIDX_"..k.name.."__"..key.." "..ind.."\n")
- end
- output:write(' {"'..key..'", offsetof(KeyDict_'..k.name..", "..(c_name[key] or key).."), "..typename(k.types[key])..", "..ind.."},\n")
+ keysets_defs:write('#define KEYSET_OPTIDX_' .. k.name .. '__' .. key .. ' ' .. ind .. '\n')
+ end
+ output:write(
+ ' {"'
+ .. key
+ .. '", offsetof(KeyDict_'
+ .. k.name
+ .. ', '
+ .. (c_name[key] or key)
+ .. '), '
+ .. typename(k.types[key])
+ .. ', '
+ .. ind
+ .. ', '
+ .. (k.types[key] == 'HLGroupID' and 'true' or 'false')
+ .. '},\n'
+ )
end
- output:write(' {NULL, 0, kObjectTypeNil, -1},\n')
- output:write("};\n\n")
+ output:write(' {NULL, 0, kObjectTypeNil, -1, false},\n')
+ output:write('};\n\n')
output:write(hashfun)
output:write([[
-KeySetLink *KeyDict_]]..k.name..[[_get_field(const char *str, size_t len)
+KeySetLink *KeyDict_]] .. k.name .. [[_get_field(const char *str, size_t len)
{
- int hash = ]]..k.name..[[_hash(str, len);
+ int hash = ]] .. k.name .. [[_hash(str, len);
if (hash == -1) {
return NULL;
}
- return &]]..k.name..[[_table[hash];
+ return &]] .. k.name .. [[_table[hash];
}
]])
- keysets_defs:write("#define api_free_keydict_"..k.name.."(x) api_free_keydict(x, "..k.name.."_table)\n")
end
local function real_type(type)
local rv = type
- local rmatch = string.match(type, "Dict%(([_%w]+)%)")
+ local rmatch = string.match(type, 'Dict%(([_%w]+)%)')
if rmatch then
- return "KeyDict_"..rmatch
+ return 'KeyDict_' .. rmatch
elseif c_grammar.typed_container:match(rv) then
if rv:match('Array') then
rv = 'Array'
@@ -333,24 +428,30 @@ for i = 1, #functions do
if fn.impl_name == nil and fn.remote then
local args = {}
- output:write('Object handle_'..fn.name..'(uint64_t channel_id, Array args, Arena* arena, Error *error)')
+ output:write(
+ 'Object handle_' .. fn.name .. '(uint64_t channel_id, Array args, Arena* arena, Error *error)'
+ )
output:write('\n{')
output:write('\n#ifdef NVIM_LOG_DEBUG')
- output:write('\n DLOG("RPC: ch %" PRIu64 ": invoke '..fn.name..'", channel_id);')
+ output:write('\n DLOG("RPC: ch %" PRIu64 ": invoke ' .. fn.name .. '", channel_id);')
output:write('\n#endif')
output:write('\n Object ret = NIL;')
-- Declare/initialize variables that will hold converted arguments
for j = 1, #fn.parameters do
local param = fn.parameters[j]
local rt = real_type(param[1])
- local converted = 'arg_'..j
- output:write('\n '..rt..' '..converted..';')
+ local converted = 'arg_' .. j
+ output:write('\n ' .. rt .. ' ' .. converted .. ';')
end
output:write('\n')
if not fn.receives_array_args then
- output:write('\n if (args.size != '..#fn.parameters..') {')
- output:write('\n api_set_error(error, kErrorTypeException, \
- "Wrong number of arguments: expecting '..#fn.parameters..' but got %zu", args.size);')
+ output:write('\n if (args.size != ' .. #fn.parameters .. ') {')
+ output:write(
+ '\n api_set_error(error, kErrorTypeException, \
+ "Wrong number of arguments: expecting '
+ .. #fn.parameters
+ .. ' but got %zu", args.size);'
+ )
output:write('\n goto cleanup;')
output:write('\n }\n')
end
@@ -359,55 +460,121 @@ for i = 1, #functions do
for j = 1, #fn.parameters do
local converted, param
param = fn.parameters[j]
- converted = 'arg_'..j
+ converted = 'arg_' .. j
local rt = real_type(param[1])
if rt == 'Object' then
- output:write('\n '..converted..' = args.items['..(j - 1)..'];\n')
+ output:write('\n ' .. converted .. ' = args.items[' .. (j - 1) .. '];\n')
elseif rt:match('^KeyDict_') then
converted = '&' .. converted
- output:write('\n if (args.items['..(j - 1)..'].type == kObjectTypeDictionary) {') --luacheck: ignore 631
- output:write('\n memset('..converted..', 0, sizeof(*'..converted..'));') -- TODO: neeeee
- output:write('\n if (!api_dict_to_keydict('..converted..', '..rt..'_get_field, args.items['..(j - 1)..'].data.dictionary, error)) {')
+ output:write('\n if (args.items[' .. (j - 1) .. '].type == kObjectTypeDictionary) {') --luacheck: ignore 631
+ output:write('\n memset(' .. converted .. ', 0, sizeof(*' .. converted .. '));') -- TODO: neeeee
+ output:write(
+ '\n if (!api_dict_to_keydict('
+ .. converted
+ .. ', '
+ .. rt
+ .. '_get_field, args.items['
+ .. (j - 1)
+ .. '].data.dictionary, error)) {'
+ )
output:write('\n goto cleanup;')
output:write('\n }')
- output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeArray && args.items['..(j - 1)..'].data.array.size == 0) {') --luacheck: ignore 631
- output:write('\n memset('..converted..', 0, sizeof(*'..converted..'));')
+ output:write(
+ '\n } else if (args.items['
+ .. (j - 1)
+ .. '].type == kObjectTypeArray && args.items['
+ .. (j - 1)
+ .. '].data.array.size == 0) {'
+ ) --luacheck: ignore 631
+ output:write('\n memset(' .. converted .. ', 0, sizeof(*' .. converted .. '));')
output:write('\n } else {')
- output:write('\n api_set_error(error, kErrorTypeException, \
- "Wrong type for argument '..j..' when calling '..fn.name..', expecting '..param[1]..'");')
+ output:write(
+ '\n api_set_error(error, kErrorTypeException, \
+ "Wrong type for argument '
+ .. j
+ .. ' when calling '
+ .. fn.name
+ .. ', expecting '
+ .. param[1]
+ .. '");'
+ )
output:write('\n goto cleanup;')
output:write('\n }\n')
else
if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') then
-- Buffer, Window, and Tabpage have a specific type, but are stored in integer
- output:write('\n if (args.items['..
- (j - 1)..'].type == kObjectType'..rt..' && args.items['..(j - 1)..'].data.integer >= 0) {')
- output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;')
+ output:write(
+ '\n if (args.items['
+ .. (j - 1)
+ .. '].type == kObjectType'
+ .. rt
+ .. ' && args.items['
+ .. (j - 1)
+ .. '].data.integer >= 0) {'
+ )
+ output:write(
+ '\n ' .. converted .. ' = (handle_T)args.items[' .. (j - 1) .. '].data.integer;'
+ )
else
- output:write('\n if (args.items['..(j - 1)..'].type == kObjectType'..rt..') {')
- output:write('\n '..converted..' = args.items['..(j - 1)..'].data.'..attr_name(rt)..';')
+ output:write('\n if (args.items[' .. (j - 1) .. '].type == kObjectType' .. rt .. ') {')
+ output:write(
+ '\n '
+ .. converted
+ .. ' = args.items['
+ .. (j - 1)
+ .. '].data.'
+ .. attr_name(rt)
+ .. ';'
+ )
end
- if rt:match('^Buffer$') or rt:match('^Window$') or rt:match('^Tabpage$') or rt:match('^Boolean$') then
+ if
+ rt:match('^Buffer$')
+ or rt:match('^Window$')
+ or rt:match('^Tabpage$')
+ or rt:match('^Boolean$')
+ then
-- accept nonnegative integers for Booleans, Buffers, Windows and Tabpages
- output:write('\n } else if (args.items['..
- (j - 1)..'].type == kObjectTypeInteger && args.items['..(j - 1)..'].data.integer >= 0) {')
- output:write('\n '..converted..' = (handle_T)args.items['..(j - 1)..'].data.integer;')
+ output:write(
+ '\n } else if (args.items['
+ .. (j - 1)
+ .. '].type == kObjectTypeInteger && args.items['
+ .. (j - 1)
+ .. '].data.integer >= 0) {'
+ )
+ output:write(
+ '\n ' .. converted .. ' = (handle_T)args.items[' .. (j - 1) .. '].data.integer;'
+ )
end
if rt:match('^Float$') then
-- accept integers for Floats
- output:write('\n } else if (args.items['..
- (j - 1)..'].type == kObjectTypeInteger) {')
- output:write('\n '..converted..' = (Float)args.items['..(j - 1)..'].data.integer;')
+ output:write('\n } else if (args.items[' .. (j - 1) .. '].type == kObjectTypeInteger) {')
+ output:write(
+ '\n ' .. converted .. ' = (Float)args.items[' .. (j - 1) .. '].data.integer;'
+ )
end
-- accept empty lua tables as empty dictionaries
if rt:match('^Dictionary') then
- output:write('\n } else if (args.items['..(j - 1)..'].type == kObjectTypeArray && args.items['..(j - 1)..'].data.array.size == 0) {') --luacheck: ignore 631
- output:write('\n '..converted..' = (Dictionary)ARRAY_DICT_INIT;')
+ output:write(
+ '\n } else if (args.items['
+ .. (j - 1)
+ .. '].type == kObjectTypeArray && args.items['
+ .. (j - 1)
+ .. '].data.array.size == 0) {'
+ ) --luacheck: ignore 631
+ output:write('\n ' .. converted .. ' = (Dictionary)ARRAY_DICT_INIT;')
end
output:write('\n } else {')
- output:write('\n api_set_error(error, kErrorTypeException, \
- "Wrong type for argument '..j..' when calling '..fn.name..', expecting '..param[1]..'");')
+ output:write(
+ '\n api_set_error(error, kErrorTypeException, \
+ "Wrong type for argument '
+ .. j
+ .. ' when calling '
+ .. fn.name
+ .. ', expecting '
+ .. param[1]
+ .. '");'
+ )
output:write('\n goto cleanup;')
output:write('\n }\n')
end
@@ -427,127 +594,127 @@ for i = 1, #functions do
end
-- function call
- local call_args = table.concat(args, ', ')
output:write('\n ')
if fn.return_type ~= 'void' then
-- has a return value, prefix the call with a declaration
- output:write(fn.return_type..' rv = ')
+ output:write(fn.return_type .. ' rv = ')
end
-- write the function name and the opening parenthesis
- output:write(fn.name..'(')
+ output:write(fn.name .. '(')
+ local call_args = {}
if fn.receives_channel_id then
- -- if the function receives the channel id, pass it as first argument
- if #args > 0 or fn.can_fail then
- output:write('channel_id, ')
- if fn.receives_array_args then
- -- if the function receives the array args, pass it the second argument
- output:write('args, ')
- end
- output:write(call_args)
- else
- output:write('channel_id')
- if fn.receives_array_args then
- output:write(', args')
- end
- end
- else
- if fn.receives_array_args then
- if #args > 0 or fn.call_fail then
- output:write('args, '..call_args)
- else
- output:write('args')
- end
- else
- output:write(call_args)
- end
+ table.insert(call_args, 'channel_id')
+ end
+
+ if fn.receives_array_args then
+ table.insert(call_args, 'args')
end
- if fn.arena_return then
- output:write(', arena')
+ for _, a in ipairs(args) do
+ table.insert(call_args, a)
+ end
+
+ if fn.receives_arena then
+ table.insert(call_args, 'arena')
end
if fn.has_lua_imp then
- if #args > 0 then
- output:write(', NULL')
- else
- output:write('NULL')
- end
+ table.insert(call_args, 'NULL')
+ end
+
+ if fn.can_fail then
+ table.insert(call_args, 'error')
end
+ output:write(table.concat(call_args, ', '))
+ output:write(');\n')
+
if fn.can_fail then
-- if the function can fail, also pass a pointer to the local error object
- if #args > 0 then
- output:write(', error);\n')
- else
- output:write('error);\n')
- end
-- and check for the error
output:write('\n if (ERROR_SET(error)) {')
output:write('\n goto cleanup;')
output:write('\n }\n')
- else
- output:write(');\n')
end
- if fn.return_type ~= 'void' then
- output:write('\n ret = '..string.upper(real_type(fn.return_type))..'_OBJ(rv);')
+ local ret_type = real_type(fn.return_type)
+ if string.match(ret_type, '^KeyDict_') then
+ local table = string.sub(ret_type, 9) .. '_table'
+ output:write(
+ '\n ret = DICTIONARY_OBJ(api_keydict_to_dict(&rv, '
+ .. table
+ .. ', ARRAY_SIZE('
+ .. table
+ .. '), arena));'
+ )
+ elseif ret_type ~= 'void' then
+ output:write('\n ret = ' .. string.upper(real_type(fn.return_type)) .. '_OBJ(rv);')
end
- output:write('\n\ncleanup:');
+ output:write('\n\ncleanup:')
- output:write('\n return ret;\n}\n\n');
+ output:write('\n return ret;\n}\n\n')
end
end
local remote_fns = {}
-for _,fn in ipairs(functions) do
+for _, fn in ipairs(functions) do
if fn.remote then
remote_fns[fn.name] = fn
end
end
-remote_fns.redraw = {impl_name="ui_client_redraw", fast=true}
+remote_fns.redraw = { impl_name = 'ui_client_redraw', fast = true }
local names = vim.tbl_keys(remote_fns)
table.sort(names)
-local hashorder, hashfun = hashy.hashy_hash("msgpack_rpc_get_handler_for", names, function (idx)
- return "method_handlers["..idx.."].name"
+local hashorder, hashfun = hashy.hashy_hash('msgpack_rpc_get_handler_for', names, function(idx)
+ return 'method_handlers[' .. idx .. '].name'
end)
-output:write("const MsgpackRpcRequestHandler method_handlers[] = {\n")
+output:write('const MsgpackRpcRequestHandler method_handlers[] = {\n')
for n, name in ipairs(hashorder) do
local fn = remote_fns[name]
- fn.handler_id = n-1
- output:write(' { .name = "'..name..'", .fn = handle_'.. (fn.impl_name or fn.name)..
- ', .fast = '..tostring(fn.fast)..', .arena_return = '..tostring(not not fn.arena_return)..'},\n')
+ fn.handler_id = n - 1
+ output:write(
+ ' { .name = "'
+ .. name
+ .. '", .fn = handle_'
+ .. (fn.impl_name or fn.name)
+ .. ', .fast = '
+ .. tostring(fn.fast)
+ .. ', .ret_alloc = '
+ .. tostring(not not fn.ret_alloc)
+ .. '},\n'
+ )
end
-output:write("};\n\n")
+output:write('};\n\n')
output:write(hashfun)
output:close()
functions.keysets = keysets
-local mpack_output = io.open(mpack_outputf, 'wb')
+local mpack_output = assert(io.open(mpack_outputf, 'wb'))
mpack_output:write(mpack.encode(functions))
mpack_output:close()
local function include_headers(output_handle, headers_to_include)
for i = 1, #headers_to_include do
if headers_to_include[i]:sub(-12) ~= '.generated.h' then
- output_handle:write('\n#include "nvim/'..headers_to_include[i]..'"')
+ output_handle:write('\n#include "nvim/' .. headers_to_include[i] .. '"')
end
end
end
-local function write_shifted_output(_, str)
+local function write_shifted_output(str, ...)
str = str:gsub('\n ', '\n')
str = str:gsub('^ ', '')
str = str:gsub(' +$', '')
- output:write(str)
+ output:write(string.format(str, ...))
end
-- start building lua output
-output = io.open(lua_c_bindings_outputf, 'wb')
+output = assert(io.open(lua_c_bindings_outputf, 'wb'))
output:write([[
#include <lua.h>
@@ -557,6 +724,7 @@ output:write([[
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/func_attr.h"
+#include "nvim/globals.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/dispatch.h"
@@ -572,42 +740,51 @@ local lua_c_functions = {}
local function process_function(fn)
local lua_c_function_name = ('nlua_api_%s'):format(fn.name)
- write_shifted_output(output, string.format([[
+ write_shifted_output(
+ [[
static int %s(lua_State *lstate)
{
Error err = ERROR_INIT;
+ Arena arena = ARENA_EMPTY;
char *err_param = 0;
if (lua_gettop(lstate) != %i) {
api_set_error(&err, kErrorTypeValidation, "Expected %i argument%s");
goto exit_0;
}
- ]], lua_c_function_name, #fn.parameters, #fn.parameters,
- (#fn.parameters == 1) and '' or 's'))
+ ]],
+ lua_c_function_name,
+ #fn.parameters,
+ #fn.parameters,
+ (#fn.parameters == 1) and '' or 's'
+ )
lua_c_functions[#lua_c_functions + 1] = {
- binding=lua_c_function_name,
- api=fn.name
+ binding = lua_c_function_name,
+ api = fn.name,
}
if not fn.fast then
- write_shifted_output(output, string.format([[
+ write_shifted_output(
+ [[
if (!nlua_is_deferred_safe()) {
return luaL_error(lstate, e_luv_api_disabled, "%s");
}
- ]], fn.name))
+ ]],
+ fn.name
+ )
end
if fn.textlock then
- write_shifted_output(output, [[
+ write_shifted_output([[
if (text_locked()) {
- api_set_error(&err, kErrorTypeException, "%s", get_text_locked_msg());
+ api_set_error(&err, kErrorTypeException, "%%s", get_text_locked_msg());
goto exit_0;
}
]])
elseif fn.textlock_allow_cmdwin then
- write_shifted_output(output, [[
+ write_shifted_output([[
if (textlock != 0 || expr_map_locked()) {
- api_set_error(&err, kErrorTypeException, "%s", e_textlock);
+ api_set_error(&err, kErrorTypeException, "%%s", e_textlock);
goto exit_0;
}
]])
@@ -615,48 +792,69 @@ local function process_function(fn)
local cparams = ''
local free_code = {}
- for j = #fn.parameters,1,-1 do
+ for j = #fn.parameters, 1, -1 do
local param = fn.parameters[j]
local cparam = string.format('arg%u', j)
local param_type = real_type(param[1])
- local lc_param_type = real_type(param[1]):lower()
- local extra = param_type == "Dictionary" and "false, " or ""
- if param[1] == "Object" or param[1] == "DictionaryOf(LuaRef)" then
- extra = "true, "
+ local extra = param_type == 'Dictionary' and 'false, ' or ''
+ local arg_free_code = ''
+ if param[1] == 'Object' then
+ extra = 'true, '
+ arg_free_code = 'api_luarefs_free_object(' .. cparam .. ');'
+ elseif param[1] == 'DictionaryOf(LuaRef)' then
+ extra = 'true, '
+ arg_free_code = 'api_luarefs_free_dict(' .. cparam .. ');'
+ elseif param[1] == 'LuaRef' then
+ arg_free_code = 'api_free_luaref(' .. cparam .. ');'
end
local errshift = 0
local seterr = ''
if string.match(param_type, '^KeyDict_') then
- write_shifted_output(output, string.format([[
- %s %s = { 0 }; nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &err);]], param_type, cparam, cparam, param_type))
- cparam = '&'..cparam
+ write_shifted_output(
+ [[
+ %s %s = KEYDICT_INIT;
+ nlua_pop_keydict(lstate, &%s, %s_get_field, &err_param, &arena, &err);
+ ]],
+ param_type,
+ cparam,
+ cparam,
+ param_type
+ )
+ cparam = '&' .. cparam
errshift = 1 -- free incomplete dict on error
+ arg_free_code = 'api_luarefs_free_keydict('
+ .. cparam
+ .. ', '
+ .. string.sub(param_type, 9)
+ .. '_table);'
else
- write_shifted_output(output, string.format([[
- const %s %s = nlua_pop_%s(lstate, %s&err);]], param[1], cparam, param_type, extra))
- seterr = [[
- err_param = "]]..param[2]..[[";]]
+ write_shifted_output(
+ [[
+ const %s %s = nlua_pop_%s(lstate, %s&arena, &err);]],
+ param[1],
+ cparam,
+ param_type,
+ extra
+ )
+ seterr = '\n err_param = "' .. param[2] .. '";'
end
- write_shifted_output(output, string.format([[
+ write_shifted_output([[
+
+ if (ERROR_SET(&err)) {]] .. seterr .. [[
- if (ERROR_SET(&err)) {]]..seterr..[[
goto exit_%u;
}
- ]], #fn.parameters - j + errshift))
- free_code[#free_code + 1] = ('api_free_%s(%s);'):format(
- lc_param_type, cparam)
+ ]], #fn.parameters - j + errshift)
+ free_code[#free_code + 1] = arg_free_code
cparams = cparam .. ', ' .. cparams
end
if fn.receives_channel_id then
cparams = 'LUA_INTERNAL_CALL, ' .. cparams
end
- if fn.arena_return then
+ if fn.receives_arena then
cparams = cparams .. '&arena, '
- write_shifted_output(output, [[
- Arena arena = ARENA_EMPTY;
- ]])
end
if fn.has_lua_imp then
@@ -673,28 +871,28 @@ local function process_function(fn)
local rev_i = #free_code - i + 1
local code = free_code[rev_i]
if i == 1 and not string.match(real_type(fn.parameters[1][1]), '^KeyDict_') then
- free_at_exit_code = free_at_exit_code .. ('\n %s'):format(code)
+ free_at_exit_code = free_at_exit_code .. ('\n %s'):format(code)
else
- free_at_exit_code = free_at_exit_code .. ('\n exit_%u:\n %s'):format(
- rev_i, code)
+ free_at_exit_code = free_at_exit_code .. ('\nexit_%u:\n %s'):format(rev_i, code)
end
end
local err_throw_code = [[
- exit_0:
- if (ERROR_SET(&err)) {
- luaL_where(lstate, 1);
- if (err_param) {
- lua_pushstring(lstate, "Invalid '");
- lua_pushstring(lstate, err_param);
- lua_pushstring(lstate, "': ");
- }
- lua_pushstring(lstate, err.msg);
- api_clear_error(&err);
- lua_concat(lstate, err_param ? 5 : 2);
- return lua_error(lstate);
+exit_0:
+ arena_mem_free(arena_finish(&arena));
+ if (ERROR_SET(&err)) {
+ luaL_where(lstate, 1);
+ if (err_param) {
+ lua_pushstring(lstate, "Invalid '");
+ lua_pushstring(lstate, err_param);
+ lua_pushstring(lstate, "': ");
}
- ]]
+ lua_pushstring(lstate, err.msg);
+ api_clear_error(&err);
+ lua_concat(lstate, err_param ? 5 : 2);
+ return lua_error(lstate);
+ }
+]]
local return_type
if fn.return_type ~= 'void' then
if fn.return_type:match('^ArrayOf') then
@@ -702,45 +900,68 @@ local function process_function(fn)
else
return_type = fn.return_type
end
- local free_retval
- if fn.arena_return then
- free_retval = "arena_mem_free(arena_finish(&arena));"
- else
- free_retval = "api_free_"..return_type:lower().."(ret);"
+ local free_retval = ''
+ if fn.ret_alloc then
+ free_retval = ' api_free_' .. return_type:lower() .. '(ret);'
end
- write_shifted_output(output, string.format([[
- const %s ret = %s(%s);
- ]], fn.return_type, fn.name, cparams))
+ write_shifted_output(' %s ret = %s(%s);\n', fn.return_type, fn.name, cparams)
+ local ret_type = real_type(fn.return_type)
+ local ret_mode = (ret_type == 'Object') and '&' or ''
if fn.has_lua_imp then
-- only push onto the Lua stack if we haven't already
- write_shifted_output(output, string.format([[
+ write_shifted_output(string.format(
+ [[
if (lua_gettop(lstate) == 0) {
- nlua_push_%s(lstate, ret, true);
+ nlua_push_%s(lstate, %sret, true);
}
- ]], return_type))
+ ]],
+ return_type,
+ ret_mode
+ ))
+ elseif string.match(ret_type, '^KeyDict_') then
+ write_shifted_output(
+ ' nlua_push_keydict(lstate, &ret, %s_table);\n',
+ string.sub(ret_type, 9)
+ )
else
local special = (fn.since ~= nil and fn.since < 11)
- write_shifted_output(output, string.format([[
- nlua_push_%s(lstate, ret, %s);
- ]], return_type, tostring(special)))
+ write_shifted_output(
+ ' nlua_push_%s(lstate, %sret, %s);\n',
+ return_type,
+ ret_mode,
+ tostring(special)
+ )
end
- write_shifted_output(output, string.format([[
+ -- NOTE: we currently assume err_throw needs nothing from arena
+ write_shifted_output(
+
+ [[
%s
%s
%s
return 1;
- ]], free_retval, free_at_exit_code, err_throw_code))
+ ]],
+ free_retval,
+ free_at_exit_code,
+ err_throw_code
+ )
else
- write_shifted_output(output, string.format([[
+ write_shifted_output(
+ [[
%s(%s);
%s
%s
return 0;
- ]], fn.name, cparams, free_at_exit_code, err_throw_code))
+ ]],
+ fn.name,
+ cparams,
+ free_at_exit_code,
+ err_throw_code
+ )
end
- write_shifted_output(output, [[
+ write_shifted_output([[
}
]])
end
@@ -751,18 +972,25 @@ for _, fn in ipairs(functions) do
end
end
-output:write(string.format([[
-void nlua_add_api_functions(lua_State *lstate); // silence -Wmissing-prototypes
+output:write(string.format(
+ [[
+void nlua_add_api_functions(lua_State *lstate)
+ REAL_FATTR_NONNULL_ALL;
void nlua_add_api_functions(lua_State *lstate)
- FUNC_ATTR_NONNULL_ALL
{
lua_createtable(lstate, 0, %u);
-]], #lua_c_functions))
+]],
+ #lua_c_functions
+))
for _, func in ipairs(lua_c_functions) do
- output:write(string.format([[
+ output:write(string.format(
+ [[
lua_pushcfunction(lstate, &%s);
- lua_setfield(lstate, -2, "%s");]], func.binding, func.api))
+ lua_setfield(lstate, -2, "%s");]],
+ func.binding,
+ func.api
+ ))
end
output:write([[
diff --git a/src/nvim/generators/gen_api_ui_events.lua b/src/nvim/generators/gen_api_ui_events.lua
index e2af5f8d44..0808f71daa 100644
--- a/src/nvim/generators/gen_api_ui_events.lua
+++ b/src/nvim/generators/gen_api_ui_events.lua
@@ -10,11 +10,11 @@ local client_output = io.open(arg[5], 'wb')
local c_grammar = require('generators.c_grammar')
local events = c_grammar.grammar:match(input:read('*all'))
-local hashy = require'generators.hashy'
+local hashy = require 'generators.hashy'
local function write_signature(output, ev, prefix, notype)
- output:write('('..prefix)
- if prefix == "" and #ev.parameters == 0 then
+ output:write('(' .. prefix)
+ if prefix == '' and #ev.parameters == 0 then
output:write('void')
end
for j = 1, #ev.parameters do
@@ -23,7 +23,7 @@ local function write_signature(output, ev, prefix, notype)
end
local param = ev.parameters[j]
if not notype then
- output:write(param[1]..' ')
+ output:write(param[1] .. ' ')
end
output:write(param[2])
end
@@ -35,26 +35,28 @@ local function write_arglist(output, ev)
local param = ev.parameters[j]
local kind = string.upper(param[1])
output:write(' ADD_C(args, ')
- output:write(kind..'_OBJ('..param[2]..')')
+ output:write(kind .. '_OBJ(' .. param[2] .. ')')
output:write(');\n')
end
end
local function call_ui_event_method(output, ev)
- output:write('void ui_client_event_'..ev.name..'(Array args)\n{\n')
+ output:write('void ui_client_event_' .. ev.name .. '(Array args)\n{\n')
local hlattrs_args_count = 0
if #ev.parameters > 0 then
- output:write(' if (args.size < '..(#ev.parameters))
+ output:write(' if (args.size < ' .. #ev.parameters)
for j = 1, #ev.parameters do
local kind = ev.parameters[j][1]
- if kind ~= "Object" then
- if kind == 'HlAttrs' then kind = 'Dictionary' end
- output:write('\n || args.items['..(j-1)..'].type != kObjectType'..kind..'')
+ if kind ~= 'Object' then
+ if kind == 'HlAttrs' then
+ kind = 'Dictionary'
+ end
+ output:write('\n || args.items[' .. (j - 1) .. '].type != kObjectType' .. kind .. '')
end
end
output:write(') {\n')
- output:write(' ELOG("Error handling ui event \''..ev.name..'\'");\n')
+ output:write(' ELOG("Error handling ui event \'' .. ev.name .. '\'");\n')
output:write(' return;\n')
output:write(' }\n')
end
@@ -62,106 +64,118 @@ local function call_ui_event_method(output, ev)
for j = 1, #ev.parameters do
local param = ev.parameters[j]
local kind = param[1]
- output:write(' '..kind..' arg_'..j..' = ')
+ output:write(' ' .. kind .. ' arg_' .. j .. ' = ')
if kind == 'HlAttrs' then
-- The first HlAttrs argument is rgb_attrs and second is cterm_attrs
- output:write('ui_client_dict2hlattrs(args.items['..(j-1)..'].data.dictionary, '..(hlattrs_args_count == 0 and 'true' or 'false')..');\n')
+ output:write(
+ 'ui_client_dict2hlattrs(args.items['
+ .. (j - 1)
+ .. '].data.dictionary, '
+ .. (hlattrs_args_count == 0 and 'true' or 'false')
+ .. ');\n'
+ )
hlattrs_args_count = hlattrs_args_count + 1
elseif kind == 'Object' then
- output:write('args.items['..(j-1)..'];\n')
+ output:write('args.items[' .. (j - 1) .. '];\n')
elseif kind == 'Window' then
- output:write('(Window)args.items['..(j-1)..'].data.integer;\n')
+ output:write('(Window)args.items[' .. (j - 1) .. '].data.integer;\n')
else
- output:write('args.items['..(j-1)..'].data.'..string.lower(kind)..';\n')
+ output:write('args.items[' .. (j - 1) .. '].data.' .. string.lower(kind) .. ';\n')
end
end
- output:write(' tui_'..ev.name..'(tui')
+ output:write(' tui_' .. ev.name .. '(tui')
for j = 1, #ev.parameters do
- output:write(', arg_'..j)
+ output:write(', arg_' .. j)
end
output:write(');\n')
output:write('}\n\n')
end
+events = vim.tbl_filter(function(ev)
+ return ev[1] ~= 'empty'
+end, events)
+
for i = 1, #events do
local ev = events[i]
assert(ev.return_type == 'void')
if ev.since == nil and not ev.noexport then
- print("Ui event "..ev.name.." lacks since field.\n")
+ print('Ui event ' .. ev.name .. ' lacks since field.\n')
os.exit(1)
end
ev.since = tonumber(ev.since)
if not ev.remote_only then
-
if not ev.remote_impl and not ev.noexport then
- remote_output:write('void remote_ui_'..ev.name)
- write_signature(remote_output, ev, 'UI *ui')
+ remote_output:write('void remote_ui_' .. ev.name)
+ write_signature(remote_output, ev, 'RemoteUI *ui')
remote_output:write('\n{\n')
- remote_output:write(' UIData *data = ui->data;\n')
- remote_output:write(' Array args = data->call_buf;\n')
+ remote_output:write(' Array args = ui->call_buf;\n')
write_arglist(remote_output, ev)
- remote_output:write(' push_call(ui, "'..ev.name..'", args);\n')
+ remote_output:write(' push_call(ui, "' .. ev.name .. '", args);\n')
remote_output:write('}\n\n')
end
end
if not (ev.remote_only and ev.remote_impl) then
- call_output:write('void ui_call_'..ev.name)
+ call_output:write('void ui_call_' .. ev.name)
write_signature(call_output, ev, '')
call_output:write('\n{\n')
if ev.remote_only then
call_output:write(' Array args = call_buf;\n')
write_arglist(call_output, ev)
- call_output:write(' ui_call_event("'..ev.name..'", args);\n')
+ call_output:write(' ui_call_event("' .. ev.name .. '", args);\n')
elseif ev.compositor_impl then
- call_output:write(' ui_comp_'..ev.name)
+ call_output:write(' ui_comp_' .. ev.name)
write_signature(call_output, ev, '', true)
- call_output:write(";\n")
+ call_output:write(';\n')
call_output:write(' UI_CALL')
- write_signature(call_output, ev, '!ui->composed, '..ev.name..', ui', true)
- call_output:write(";\n")
+ write_signature(call_output, ev, '!ui->composed, ' .. ev.name .. ', ui', true)
+ call_output:write(';\n')
else
call_output:write(' UI_CALL')
- write_signature(call_output, ev, 'true, '..ev.name..', ui', true)
- call_output:write(";\n")
+ write_signature(call_output, ev, 'true, ' .. ev.name .. ', ui', true)
+ call_output:write(';\n')
end
- call_output:write("}\n\n")
+ call_output:write('}\n\n')
end
if ev.compositor_impl then
- call_output:write('void ui_composed_call_'..ev.name)
+ call_output:write('void ui_composed_call_' .. ev.name)
write_signature(call_output, ev, '')
call_output:write('\n{\n')
call_output:write(' UI_CALL')
- write_signature(call_output, ev, 'ui->composed, '..ev.name..', ui', true)
- call_output:write(";\n")
- call_output:write("}\n\n")
+ write_signature(call_output, ev, 'ui->composed, ' .. ev.name .. ', ui', true)
+ call_output:write(';\n')
+ call_output:write('}\n\n')
end
- if (not ev.remote_only) and (not ev.noexport) and (not ev.client_impl) and (not ev.client_ignore) then
+ if (not ev.remote_only) and not ev.noexport and not ev.client_impl and not ev.client_ignore then
call_ui_event_method(client_output, ev)
end
end
local client_events = {}
-for _,ev in ipairs(events) do
- if (not ev.noexport) and ((not ev.remote_only) or ev.client_impl) and (not ev.client_ignore) then
+for _, ev in ipairs(events) do
+ if (not ev.noexport) and ((not ev.remote_only) or ev.client_impl) and not ev.client_ignore then
client_events[ev.name] = ev
end
end
-local hashorder, hashfun = hashy.hashy_hash("ui_client_handler", vim.tbl_keys(client_events), function (idx)
- return "event_handlers["..idx.."].name"
-end)
+local hashorder, hashfun = hashy.hashy_hash(
+ 'ui_client_handler',
+ vim.tbl_keys(client_events),
+ function(idx)
+ return 'event_handlers[' .. idx .. '].name'
+ end
+)
-client_output:write("static const UIClientHandler event_handlers[] = {\n")
+client_output:write('static const UIClientHandler event_handlers[] = {\n')
for _, name in ipairs(hashorder) do
- client_output:write(' { .name = "'..name..'", .fn = ui_client_event_'..name..'},\n')
+ client_output:write(' { .name = "' .. name .. '", .fn = ui_client_event_' .. name .. '},\n')
end
client_output:write('\n};\n\n')
@@ -172,25 +186,22 @@ remote_output:close()
client_output:close()
-- don't expose internal attributes like "impl_name" in public metadata
-local exported_attributes = {'name', 'parameters',
- 'since', 'deprecated_since'}
+local exported_attributes = { 'name', 'parameters', 'since', 'deprecated_since' }
local exported_events = {}
-for _,ev in ipairs(events) do
+for _, ev in ipairs(events) do
local ev_exported = {}
- for _,attr in ipairs(exported_attributes) do
+ for _, attr in ipairs(exported_attributes) do
ev_exported[attr] = ev[attr]
end
- for _,p in ipairs(ev_exported.parameters) do
+ for _, p in ipairs(ev_exported.parameters) do
if p[1] == 'HlAttrs' then
p[1] = 'Dictionary'
end
end
if not ev.noexport then
- exported_events[#exported_events+1] = ev_exported
+ exported_events[#exported_events + 1] = ev_exported
end
end
-local packed = mpack.encode(exported_events)
-local dump_bin_array = require("generators.dump_bin_array")
-dump_bin_array(metadata_output, 'ui_events_metadata', packed)
+metadata_output:write(mpack.encode(exported_events))
metadata_output:close()
diff --git a/src/nvim/generators/gen_char_blob.lua b/src/nvim/generators/gen_char_blob.lua
index 11f6cbcc13..c40e0d6e82 100644
--- a/src/nvim/generators/gen_char_blob.lua
+++ b/src/nvim/generators/gen_char_blob.lua
@@ -1,6 +1,6 @@
if arg[1] == '--help' then
print('Usage:')
- print(' '..arg[0]..' [-c] target source varname [source varname]...')
+ print(' ' .. arg[0] .. ' [-c] target source varname [source varname]...')
print('')
print('Generates C file with big uint8_t blob.')
print('Blob will be stored in a static const array named varname.')
@@ -12,7 +12,7 @@ end
local options = {}
while true do
- local opt = string.match(arg[1], "^-(%w)")
+ local opt = string.match(arg[1], '^-(%w)')
if not opt then
break
end
@@ -36,33 +36,33 @@ for argi = 2, #arg, 2 do
local source_file = arg[argi]
local modname = arg[argi + 1]
if modnames[modname] then
- error(string.format("modname %q is already specified for file %q", modname, modnames[modname]))
+ error(string.format('modname %q is already specified for file %q', modname, modnames[modname]))
end
modnames[modname] = source_file
- local varname = string.gsub(modname,'%.','_dot_').."_module"
+ local varname = string.gsub(modname, '%.', '_dot_') .. '_module'
target:write(('static const uint8_t %s[] = {\n'):format(varname))
local output
if options.c then
- local luac = os.getenv("LUAC_PRG")
- if luac and luac ~= "" then
- output = io.popen(luac:format(source_file), "r"):read("*a")
+ local luac = os.getenv('LUAC_PRG')
+ if luac and luac ~= '' then
+ output = io.popen(luac:format(source_file), 'r'):read('*a')
elseif warn_on_missing_compiler then
- print("LUAC_PRG is missing, embedding raw source")
+ print('LUAC_PRG is missing, embedding raw source')
warn_on_missing_compiler = false
end
end
if not output then
- local source = io.open(source_file, "r")
- or error(string.format("source_file %q doesn't exist", source_file))
- output = source:read("*a")
+ local source = io.open(source_file, 'r')
+ or error(string.format("source_file %q doesn't exist", source_file))
+ output = source:read('*a')
source:close()
end
local num_bytes = 0
- local MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line
+ local MAX_NUM_BYTES = 15 -- 78 / 5: maximum number of bytes on one line
target:write(' ')
local increase_num_bytes
@@ -81,8 +81,11 @@ for argi = 2, #arg, 2 do
end
target:write(' 0};\n')
- if modname ~= "_" then
- table.insert(index_items, ' { "'..modname..'", '..varname..', sizeof '..varname..' },\n\n')
+ if modname ~= '_' then
+ table.insert(
+ index_items,
+ ' { "' .. modname .. '", ' .. varname .. ', sizeof ' .. varname .. ' },\n\n'
+ )
end
end
diff --git a/src/nvim/generators/gen_declarations.lua b/src/nvim/generators/gen_declarations.lua
index f9e9c6b0a8..5d1e586fe6 100644
--- a/src/nvim/generators/gen_declarations.lua
+++ b/src/nvim/generators/gen_declarations.lua
@@ -5,9 +5,9 @@ local preproc_fname = arg[4]
local lpeg = vim.lpeg
-local fold = function (func, ...)
+local fold = function(func, ...)
local result = nil
- for _, v in ipairs({...}) do
+ for _, v in ipairs({ ... }) do
if result == nil then
result = v
else
@@ -17,144 +17,112 @@ local fold = function (func, ...)
return result
end
-local folder = function (func)
- return function (...)
+local folder = function(func)
+ return function(...)
return fold(func, ...)
end
end
local lit = lpeg.P
local set = function(...)
- return lpeg.S(fold(function (a, b) return a .. b end, ...))
+ return lpeg.S(fold(function(a, b)
+ return a .. b
+ end, ...))
end
local any_character = lpeg.P(1)
-local rng = function(s, e) return lpeg.R(s .. e) end
-local concat = folder(function (a, b) return a * b end)
-local branch = folder(function (a, b) return a + b end)
-local one_or_more = function(v) return v ^ 1 end
-local two_or_more = function(v) return v ^ 2 end
-local any_amount = function(v) return v ^ 0 end
-local one_or_no = function(v) return v ^ -1 end
+local rng = function(s, e)
+ return lpeg.R(s .. e)
+end
+local concat = folder(function(a, b)
+ return a * b
+end)
+local branch = folder(function(a, b)
+ return a + b
+end)
+local one_or_more = function(v)
+ return v ^ 1
+end
+local two_or_more = function(v)
+ return v ^ 2
+end
+local any_amount = function(v)
+ return v ^ 0
+end
+local one_or_no = function(v)
+ return v ^ -1
+end
local look_behind = lpeg.B
-local look_ahead = function(v) return #v end
-local neg_look_ahead = function(v) return -v end
-local neg_look_behind = function(v) return -look_behind(v) end
+local look_ahead = function(v)
+ return #v
+end
+local neg_look_ahead = function(v)
+ return -v
+end
+local neg_look_behind = function(v)
+ return -look_behind(v)
+end
-local w = branch(
- rng('a', 'z'),
- rng('A', 'Z'),
- lit('_')
-)
-local aw = branch(
- w,
- rng('0', '9')
-)
+local w = branch(rng('a', 'z'), rng('A', 'Z'), lit('_'))
+local aw = branch(w, rng('0', '9'))
local s = set(' ', '\n', '\t')
local raw_word = concat(w, any_amount(aw))
-local right_word = concat(
- raw_word,
- neg_look_ahead(aw)
-)
+local right_word = concat(raw_word, neg_look_ahead(aw))
local word = branch(
concat(
branch(lit('ArrayOf('), lit('DictionaryOf('), lit('Dict(')), -- typed container macro
one_or_more(any_character - lit(')')),
lit(')')
),
- concat(
- neg_look_behind(aw),
- right_word
- )
-)
-local inline_comment = concat(
- lit('/*'),
- any_amount(concat(
- neg_look_ahead(lit('*/')),
- any_character
- )),
- lit('*/')
+ concat(neg_look_behind(aw), right_word)
)
+local inline_comment =
+ concat(lit('/*'), any_amount(concat(neg_look_ahead(lit('*/')), any_character)), lit('*/'))
local spaces = any_amount(branch(
s,
-- Comments are really handled by preprocessor, so the following is not needed
inline_comment,
- concat(
- lit('//'),
- any_amount(concat(
- neg_look_ahead(lit('\n')),
- any_character
- )),
- lit('\n')
- ),
+ concat(lit('//'), any_amount(concat(neg_look_ahead(lit('\n')), any_character)), lit('\n')),
-- Linemarker inserted by preprocessor
- concat(
- lit('# '),
- any_amount(concat(
- neg_look_ahead(lit('\n')),
- any_character
- )),
- lit('\n')
- )
+ concat(lit('# '), any_amount(concat(neg_look_ahead(lit('\n')), any_character)), lit('\n'))
))
-local typ_part = concat(
- word,
- any_amount(concat(
- spaces,
- lit('*')
- )),
- spaces
-)
+local typ_part = concat(word, any_amount(concat(spaces, lit('*'))), spaces)
local typ_id = two_or_more(typ_part)
-local arg = typ_id -- argument name is swallowed by typ
+local arg = typ_id -- argument name is swallowed by typ
local pattern = concat(
any_amount(branch(set(' ', '\t'), inline_comment)),
- typ_id, -- return type with function name
+ typ_id, -- return type with function name
spaces,
lit('('),
spaces,
- one_or_no(branch( -- function arguments
+ one_or_no(branch( -- function arguments
concat(
- arg, -- first argument, does not require comma
- any_amount(concat( -- following arguments, start with a comma
+ arg, -- first argument, does not require comma
+ any_amount(concat( -- following arguments, start with a comma
spaces,
lit(','),
spaces,
arg,
- any_amount(concat(
- lit('['),
- spaces,
- any_amount(aw),
- spaces,
- lit(']')
- ))
+ any_amount(concat(lit('['), spaces, any_amount(aw), spaces, lit(']')))
)),
- one_or_no(concat(
- spaces,
- lit(','),
- spaces,
- lit('...')
- ))
+ one_or_no(concat(spaces, lit(','), spaces, lit('...')))
),
- lit('void') -- also accepts just void
+ lit('void') -- also accepts just void
)),
spaces,
lit(')'),
- any_amount(concat( -- optional attributes
+ any_amount(concat( -- optional attributes
spaces,
lit('FUNC_'),
any_amount(aw),
- one_or_no(concat( -- attribute argument
+ one_or_no(concat( -- attribute argument
spaces,
lit('('),
- any_amount(concat(
- neg_look_ahead(lit(')')),
- any_character
- )),
+ any_amount(concat(neg_look_ahead(lit(')')), any_character)),
lit(')')
))
)),
- look_ahead(concat( -- definition must be followed by "{"
+ look_ahead(concat( -- definition must be followed by "{"
spaces,
lit('{')
))
@@ -164,7 +132,7 @@ if fname == '--help' then
print([[
Usage:
- gendeclarations.lua definitions.c static.h non-static.h definitions.i
+ gen_declarations.lua definitions.c static.h non-static.h definitions.i
Generates declarations for a C file definitions.c, putting declarations for
static functions into static.h and declarations for non-static functions into
@@ -198,21 +166,13 @@ Additionally uses the following environment variables:
end
local preproc_f = io.open(preproc_fname)
-local text = preproc_f:read("*all")
+local text = preproc_f:read('*all')
preproc_f:close()
-
-local header = [[
+local non_static = [[
#define DEFINE_FUNC_ATTRIBUTES
#include "nvim/func_attr.h"
#undef DEFINE_FUNC_ATTRIBUTES
-]]
-
-local footer = [[
-#include "nvim/func_attr.h"
-]]
-
-local non_static = header .. [[
#ifndef DLLEXPORT
# ifdef MSWIN
# define DLLEXPORT __declspec(dllexport)
@@ -222,7 +182,20 @@ local non_static = header .. [[
#endif
]]
-local static = header
+local static = [[
+#define DEFINE_FUNC_ATTRIBUTES
+#include "nvim/func_attr.h"
+#undef DEFINE_FUNC_ATTRIBUTES
+]]
+
+local non_static_footer = [[
+#include "nvim/func_attr.h"
+]]
+
+local static_footer = [[
+#define DEFINE_EMPTY_ATTRIBUTES
+#include "nvim/func_attr.h" // IWYU pragma: export
+]]
if fname:find('.*/src/nvim/.*%.c$') then
-- Add an IWYU pragma comment if the corresponding .h file exists.
@@ -234,6 +207,22 @@ if fname:find('.*/src/nvim/.*%.c$') then
// IWYU pragma: private, include "%s"
]]):format(header_fname:gsub('.*/src/nvim/', 'nvim/')) .. non_static
end
+elseif non_static_fname:find('/include/api/private/dispatch_wrappers%.h%.generated%.h$') then
+ non_static = [[
+// IWYU pragma: private, include "nvim/api/private/dispatch.h"
+]] .. non_static
+elseif non_static_fname:find('/include/ui_events_call%.h%.generated%.h$') then
+ non_static = [[
+// IWYU pragma: private, include "nvim/ui.h"
+]] .. non_static
+elseif non_static_fname:find('/include/ui_events_client%.h%.generated%.h$') then
+ non_static = [[
+// IWYU pragma: private, include "nvim/ui_client.h"
+]] .. non_static
+elseif non_static_fname:find('/include/ui_events_remote%.h%.generated%.h$') then
+ non_static = [[
+// IWYU pragma: private, include "nvim/api/ui.h"
+]] .. non_static
end
local filepattern = '^#%a* (%d+) "([^"]-)/?([^"/]+)"'
@@ -283,8 +272,7 @@ while init ~= nil do
declaration = declaration .. ';'
if os.getenv('NVIM_GEN_DECLARATIONS_LINE_NUMBERS') == '1' then
- declaration = declaration .. (' // %s/%s:%u'):format(
- curdir, curfile, declline)
+ declaration = declaration .. (' // %s/%s:%u'):format(curdir, curfile, declline)
end
declaration = declaration .. '\n'
if declaration:sub(1, 6) == 'static' then
@@ -307,8 +295,8 @@ while init ~= nil do
end
end
-non_static = non_static .. footer
-static = static .. footer
+non_static = non_static .. non_static_footer
+static = static .. static_footer
local F
F = io.open(static_fname, 'w')
diff --git a/src/nvim/generators/gen_eval.lua b/src/nvim/generators/gen_eval.lua
index 7b272c337e..1ce7f1af9d 100644
--- a/src/nvim/generators/gen_eval.lua
+++ b/src/nvim/generators/gen_eval.lua
@@ -8,7 +8,7 @@ local funcsfname = autodir .. '/funcs.generated.h'
--Will generate funcs.generated.h with definition of functions static const array.
-local hashy = require'generators.hashy'
+local hashy = require 'generators.hashy'
local hashpipe = assert(io.open(funcsfname, 'wb'))
@@ -48,18 +48,18 @@ hashpipe:write([[
local funcs = require('eval').funcs
for _, func in pairs(funcs) do
if func.float_func then
- func.func = "float_op_wrapper"
- func.data = "{ .float_func = &"..func.float_func.." }"
+ func.func = 'float_op_wrapper'
+ func.data = '{ .float_func = &' .. func.float_func .. ' }'
end
end
-local metadata = mpack.decode(io.open(metadata_file, 'rb'):read("*all"))
-for _,fun in ipairs(metadata) do
+local metadata = mpack.decode(io.open(metadata_file, 'rb'):read('*all'))
+for _, fun in ipairs(metadata) do
if fun.eval then
funcs[fun.name] = {
- args=#fun.parameters,
- func='api_wrapper',
- data='{ .api_handler = &method_handlers['..fun.handler_id..'] }'
+ args = #fun.parameters,
+ func = 'api_wrapper',
+ data = '{ .api_handler = &method_handlers[' .. fun.handler_id .. '] }',
}
end
end
@@ -74,28 +74,37 @@ local funcsdata = assert(io.open(funcs_file, 'w'))
funcsdata:write(mpack.encode(func_names))
funcsdata:close()
-local neworder, hashfun = hashy.hashy_hash("find_internal_func", func_names, function (idx)
- return "functions["..idx.."].name"
+local neworder, hashfun = hashy.hashy_hash('find_internal_func', func_names, function(idx)
+ return 'functions[' .. idx .. '].name'
end)
-hashpipe:write("static const EvalFuncDef functions[] = {\n")
+hashpipe:write('static const EvalFuncDef functions[] = {\n')
for _, name in ipairs(neworder) do
local def = funcs[name]
local args = def.args or 0
if type(args) == 'number' then
- args = {args, args}
+ args = { args, args }
elseif #args == 1 then
args[2] = 'MAX_FUNC_ARGS'
end
- local base = def.base or "BASE_NONE"
+ local base = def.base or 'BASE_NONE'
local func = def.func or ('f_' .. name)
- local data = def.data or "{ .null = NULL }"
+ local data = def.data or '{ .null = NULL }'
local fast = def.fast and 'true' or 'false'
- hashpipe:write((' { "%s", %s, %s, %s, %s, &%s, %s },\n')
- :format(name, args[1], args[2], base, fast, func, data))
+ hashpipe:write(
+ (' { "%s", %s, %s, %s, %s, &%s, %s },\n'):format(
+ name,
+ args[1],
+ args[2],
+ base,
+ fast,
+ func,
+ data
+ )
+ )
end
hashpipe:write(' { NULL, 0, 0, BASE_NONE, false, NULL, { .null = NULL } },\n')
-hashpipe:write("};\n\n")
+hashpipe:write('};\n\n')
hashpipe:write(hashfun)
hashpipe:close()
diff --git a/src/nvim/generators/gen_events.lua b/src/nvim/generators/gen_events.lua
index 4763a2f463..ee48e918e8 100644
--- a/src/nvim/generators/gen_events.lua
+++ b/src/nvim/generators/gen_events.lua
@@ -22,7 +22,7 @@ static const struct event_name {
for i, event in ipairs(events) do
enum_tgt:write(('\n EVENT_%s = %u,'):format(event:upper(), i - 1))
names_tgt:write(('\n {%u, "%s", EVENT_%s},'):format(#event, event, event:upper()))
- if i == #events then -- Last item.
+ if i == #events then -- Last item.
enum_tgt:write(('\n NUM_EVENTS = %u,'):format(i))
end
end
@@ -41,15 +41,15 @@ names_tgt:write('\n};\n')
do
names_tgt:write('\nstatic AutoCmdVec autocmds[NUM_EVENTS] = {\n ')
local line_len = 1
- for _ = 1,((#events) - 1) do
- line_len = line_len + #(' KV_INITIAL_VALUE,')
+ for _ = 1, (#events - 1) do
+ line_len = line_len + #' KV_INITIAL_VALUE,'
if line_len > 80 then
names_tgt:write('\n ')
- line_len = 1 + #(' KV_INITIAL_VALUE,')
+ line_len = 1 + #' KV_INITIAL_VALUE,'
end
names_tgt:write(' KV_INITIAL_VALUE,')
end
- if line_len + #(' KV_INITIAL_VALUE') > 80 then
+ if line_len + #' KV_INITIAL_VALUE' > 80 then
names_tgt:write('\n KV_INITIAL_VALUE')
else
names_tgt:write(' KV_INITIAL_VALUE')
diff --git a/src/nvim/generators/gen_ex_cmds.lua b/src/nvim/generators/gen_ex_cmds.lua
index ae8c952648..e8d1aac182 100644
--- a/src/nvim/generators/gen_ex_cmds.lua
+++ b/src/nvim/generators/gen_ex_cmds.lua
@@ -21,24 +21,32 @@ local a_to_z = byte_z - byte_a + 1
-- Table giving the index of the first command in cmdnames[] to lookup
-- based on the first letter of a command.
-local cmdidxs1_out = string.format([[
+local cmdidxs1_out = string.format(
+ [[
static const uint16_t cmdidxs1[%u] = {
-]], a_to_z)
+]],
+ a_to_z
+)
-- Table giving the index of the first command in cmdnames[] to lookup
-- based on the first 2 letters of a command.
-- Values in cmdidxs2[c1][c2] are relative to cmdidxs1[c1] so that they
-- fit in a byte.
-local cmdidxs2_out = string.format([[
+local cmdidxs2_out = string.format(
+ [[
static const uint8_t cmdidxs2[%u][%u] = {
/* a b c d e f g h i j k l m n o p q r s t u v w x y z */
-]], a_to_z, a_to_z)
+]],
+ a_to_z,
+ a_to_z
+)
enumfile:write([[
// IWYU pragma: private, include "nvim/ex_cmds_defs.h"
typedef enum CMD_index {
]])
-defsfile:write(string.format([[
+defsfile:write(string.format(
+ [[
#include "nvim/arglist.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
@@ -79,23 +87,34 @@ defsfile:write(string.format([[
static const int command_count = %u;
static CommandDefinition cmdnames[%u] = {
-]], #defs, #defs))
+]],
+ #defs,
+ #defs
+))
local cmds, cmdidxs1, cmdidxs2 = {}, {}, {}
for _, cmd in ipairs(defs) do
if bit.band(cmd.flags, flags.RANGE) == flags.RANGE then
- assert(cmd.addr_type ~= 'ADDR_NONE',
- string.format('ex_cmds.lua:%s: Using RANGE with ADDR_NONE\n', cmd.command))
+ assert(
+ cmd.addr_type ~= 'ADDR_NONE',
+ string.format('ex_cmds.lua:%s: Using RANGE with ADDR_NONE\n', cmd.command)
+ )
else
- assert(cmd.addr_type == 'ADDR_NONE',
- string.format('ex_cmds.lua:%s: Missing ADDR_NONE\n', cmd.command))
+ assert(
+ cmd.addr_type == 'ADDR_NONE',
+ string.format('ex_cmds.lua:%s: Missing ADDR_NONE\n', cmd.command)
+ )
end
if bit.band(cmd.flags, flags.DFLALL) == flags.DFLALL then
- assert(cmd.addr_type ~= 'ADDR_OTHER' and cmd.addr_type ~= 'ADDR_NONE',
- string.format('ex_cmds.lua:%s: Missing misplaced DFLALL\n', cmd.command))
+ assert(
+ cmd.addr_type ~= 'ADDR_OTHER' and cmd.addr_type ~= 'ADDR_NONE',
+ string.format('ex_cmds.lua:%s: Missing misplaced DFLALL\n', cmd.command)
+ )
end
if bit.band(cmd.flags, flags.PREVIEW) == flags.PREVIEW then
- assert(cmd.preview_func ~= nil,
- string.format('ex_cmds.lua:%s: Missing preview_func\n', cmd.command))
+ assert(
+ cmd.preview_func ~= nil,
+ string.format('ex_cmds.lua:%s: Missing preview_func\n', cmd.command)
+ )
end
local enumname = cmd.enum or ('CMD_' .. cmd.command)
local byte_cmd = cmd.command:sub(1, 1):byte()
@@ -104,12 +123,13 @@ for _, cmd in ipairs(defs) do
end
local preview_func
if cmd.preview_func then
- preview_func = string.format("&%s", cmd.preview_func)
+ preview_func = string.format('&%s', cmd.preview_func)
else
- preview_func = "NULL"
+ preview_func = 'NULL'
end
enumfile:write(' ' .. enumname .. ',\n')
- defsfile:write(string.format([[
+ defsfile:write(string.format(
+ [[
[%s] = {
.cmd_name = "%s",
.cmd_func = (ex_func_T)&%s,
@@ -117,7 +137,14 @@ for _, cmd in ipairs(defs) do
.cmd_argt = %uL,
.cmd_addr_type = %s
},
-]], enumname, cmd.command, cmd.func, preview_func, cmd.flags, cmd.addr_type))
+]],
+ enumname,
+ cmd.command,
+ cmd.func,
+ preview_func,
+ cmd.flags,
+ cmd.addr_type
+ ))
end
for i = #cmds, 1, -1 do
local cmd = cmds[i]
@@ -141,10 +168,12 @@ for i = byte_a, byte_z do
cmdidxs2_out = cmdidxs2_out .. ' /* ' .. c1 .. ' */ {'
for j = byte_a, byte_z do
local c2 = string.char(j)
- cmdidxs2_out = cmdidxs2_out ..
- ((cmdidxs2[c1] and cmdidxs2[c1][c2])
- and string.format('%3d', cmdidxs2[c1][c2] - cmdidxs1[c1])
- or ' 0') .. ','
+ cmdidxs2_out = cmdidxs2_out
+ .. ((cmdidxs2[c1] and cmdidxs2[c1][c2]) and string.format(
+ '%3d',
+ cmdidxs2[c1][c2] - cmdidxs1[c1]
+ ) or ' 0')
+ .. ','
end
cmdidxs2_out = cmdidxs2_out .. ' },\n'
end
@@ -154,8 +183,12 @@ enumfile:write([[
CMD_USER_BUF = -2
} cmdidx_T;
]])
-defsfile:write(string.format([[
+defsfile:write(string.format(
+ [[
};
%s};
%s};
-]], cmdidxs1_out, cmdidxs2_out))
+]],
+ cmdidxs1_out,
+ cmdidxs2_out
+))
diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua
index 26ade2745d..749844e658 100644
--- a/src/nvim/generators/gen_options.lua
+++ b/src/nvim/generators/gen_options.lua
@@ -15,40 +15,43 @@ local options = require('options')
local cstr = options.cstr
-local type_flags={
- bool='P_BOOL',
- number='P_NUM',
- string='P_STRING',
+local redraw_flags = {
+ ui_option = 'P_UI_OPTION',
+ tabline = 'P_RTABL',
+ statuslines = 'P_RSTAT',
+ current_window = 'P_RWIN',
+ current_buffer = 'P_RBUF',
+ all_windows = 'P_RALL',
+ curswant = 'P_CURSWANT',
+ highlight_only = 'P_HLONLY',
}
-local redraw_flags={
- ui_option='P_UI_OPTION',
- tabline='P_RTABL',
- statuslines='P_RSTAT',
- current_window='P_RWIN',
- current_window_only='P_RWINONLY',
- current_buffer='P_RBUF',
- all_windows='P_RALL',
- curswant='P_CURSWANT',
+local list_flags = {
+ comma = 'P_COMMA',
+ onecomma = 'P_ONECOMMA',
+ commacolon = 'P_COMMA|P_COLON',
+ onecommacolon = 'P_ONECOMMA|P_COLON',
+ flags = 'P_FLAGLIST',
+ flagscomma = 'P_COMMA|P_FLAGLIST',
}
-local list_flags={
- comma='P_COMMA',
- onecomma='P_ONECOMMA',
- commacolon='P_COMMA|P_COLON',
- onecommacolon='P_ONECOMMA|P_COLON',
- flags='P_FLAGLIST',
- flagscomma='P_COMMA|P_FLAGLIST',
-}
+--- @param s string
+--- @return string
+local lowercase_to_titlecase = function(s)
+ return s:sub(1, 1):upper() .. s:sub(2)
+end
--- @param o vim.option_meta
--- @return string
local function get_flags(o)
- --- @type string[]
- local ret = {type_flags[o.type]}
+ --- @type string
+ local flags = '0'
+
+ --- @param f string
local add_flag = function(f)
- ret[1] = ret[1] .. '|' .. f
+ flags = flags .. '|' .. f
end
+
if o.list then
add_flag(list_flags[o.list])
end
@@ -64,19 +67,19 @@ local function get_flags(o)
end
end
for _, flag_desc in ipairs({
- {'alloced'},
- {'nodefault'},
- {'no_mkrc'},
- {'secure'},
- {'gettext'},
- {'noglob'},
- {'normal_fname_chars', 'P_NFNAME'},
- {'normal_dname_chars', 'P_NDNAME'},
- {'pri_mkrc'},
- {'deny_in_modelines', 'P_NO_ML'},
- {'deny_duplicates', 'P_NODUP'},
- {'modelineexpr', 'P_MLE'},
- {'func'}
+ { 'alloced' },
+ { 'nodefault' },
+ { 'no_mkrc' },
+ { 'secure' },
+ { 'gettext' },
+ { 'noglob' },
+ { 'normal_fname_chars', 'P_NFNAME' },
+ { 'normal_dname_chars', 'P_NDNAME' },
+ { 'pri_mkrc' },
+ { 'deny_in_modelines', 'P_NO_ML' },
+ { 'deny_duplicates', 'P_NODUP' },
+ { 'modelineexpr', 'P_MLE' },
+ { 'func' },
}) do
local key_name = flag_desc[1]
local def_name = flag_desc[2] or ('P_' .. key_name:upper())
@@ -84,7 +87,22 @@ local function get_flags(o)
add_flag(def_name)
end
end
- return ret[1]
+ return flags
+end
+
+--- @param o vim.option_meta
+--- @return string
+local function get_type_flags(o)
+ local opt_types = (type(o.type) == 'table') and o.type or { o.type }
+ local type_flags = '0'
+ assert(type(opt_types) == 'table')
+
+ for _, opt_type in ipairs(opt_types) do
+ assert(type(opt_type) == 'string')
+ type_flags = ('%s | (1 << kOptValType%s)'):format(type_flags, lowercase_to_titlecase(opt_type))
+ end
+
+ return type_flags
end
--- @param c string|string[]
@@ -107,23 +125,27 @@ local function get_cond(c, base_string)
return cond_string
end
-local value_dumpers = {
- ['function']=function(v) return v() end,
- string=cstr,
- boolean=function(v) return v and 'true' or 'false' end,
- number=function(v) return ('%iL'):format(v) end,
- ['nil']=function(_) return '0' end,
-}
-
-local get_value = function(v)
- return '(void *) ' .. value_dumpers[type(v)](v)
-end
-
-local get_defaults = function(d,n)
+local get_defaults = function(d, n)
if d == nil then
- error("option '"..n.."' should have a default value")
- end
- return get_value(d)
+ error("option '" .. n .. "' should have a default value")
+ end
+
+ local value_dumpers = {
+ ['function'] = function(v)
+ return v()
+ end,
+ string = function(v)
+ return '.string=' .. cstr(v)
+ end,
+ boolean = function(v)
+ return '.boolean=' .. (v and 'true' or 'false')
+ end,
+ number = function(v)
+ return ('.number=%iL'):format(v)
+ end,
+ }
+
+ return value_dumpers[type(d)](d)
end
--- @type {[1]:string,[2]:string}[]
@@ -138,12 +160,13 @@ local function dump_option(i, o)
w(' .shortname=' .. cstr(o.abbreviation))
end
w(' .flags=' .. get_flags(o))
+ w(' .type_flags=' .. get_type_flags(o))
if o.enable_if then
w(get_cond(o.enable_if))
end
if o.varname then
w(' .var=&' .. o.varname)
- -- Immutable options should directly point to the default value
+ -- Immutable options can directly point to the default value.
elseif o.immutable then
w((' .var=&options[%u].def_val'):format(i - 1))
elseif #o.scope == 1 and o.scope[1] == 'window' then
@@ -153,20 +176,21 @@ local function dump_option(i, o)
if #o.scope == 1 and o.scope[1] == 'global' then
w(' .indir=PV_NONE')
else
- assert (#o.scope == 1 or #o.scope == 2)
- assert (#o.scope == 1 or o.scope[1] == 'global')
+ assert(#o.scope == 1 or #o.scope == 2)
+ assert(#o.scope == 1 or o.scope[1] == 'global')
local min_scope = o.scope[#o.scope]
- local varname = o.pv_name or o.varname or (
- 'p_' .. (o.abbreviation or o.full_name))
+ local varname = o.pv_name or o.varname or ('p_' .. (o.abbreviation or o.full_name))
local pv_name = (
- 'OPT_' .. min_scope:sub(1, 3):upper() .. '(' .. (
- min_scope:sub(1, 1):upper() .. 'V_' .. varname:sub(3):upper()
- ) .. ')'
+ 'OPT_'
+ .. min_scope:sub(1, 3):upper()
+ .. '('
+ .. (min_scope:sub(1, 1):upper() .. 'V_' .. varname:sub(3):upper())
+ .. ')'
)
if #o.scope == 2 then
pv_name = 'OPT_BOTH(' .. pv_name .. ')'
end
- table.insert(defines, { 'PV_' .. varname:sub(3):upper() , pv_name})
+ table.insert(defines, { 'PV_' .. varname:sub(3):upper(), pv_name })
w(' .indir=' .. pv_name)
end
if o.cb then
@@ -185,11 +209,11 @@ local function dump_option(i, o)
if o.defaults.condition then
w(get_cond(o.defaults.condition))
end
- w(' .def_val=' .. get_defaults(o.defaults.if_true, o.full_name))
+ w(' .def_val' .. get_defaults(o.defaults.if_true, o.full_name))
if o.defaults.condition then
if o.defaults.if_false then
w('#else')
- w(' .def_val=' .. get_defaults(o.defaults.if_false, o.full_name))
+ w(' .def_val' .. get_defaults(o.defaults.if_false, o.full_name))
end
w('#endif')
end
@@ -213,11 +237,9 @@ static vimoption_T options[] = {]])
for i, o in ipairs(options.options) do
dump_option(i, o)
end
-w(' [' .. ('%u'):format(#options.options) .. ']={.fullname=NULL}')
w('};')
w('')
for _, v in ipairs(defines) do
w('#define ' .. v[1] .. ' ' .. v[2])
end
-opt_fd:close()
diff --git a/src/nvim/generators/gen_options_enum.lua b/src/nvim/generators/gen_options_enum.lua
new file mode 100644
index 0000000000..9a3953fcbc
--- /dev/null
+++ b/src/nvim/generators/gen_options_enum.lua
@@ -0,0 +1,129 @@
+-- Generates option index enum and map of option name to option index.
+-- Handles option full name, short name and aliases.
+-- Also generates BV_ and WV_ enum constants.
+
+local options_enum_file = arg[1]
+local options_map_file = arg[2]
+local options_enum_fd = assert(io.open(options_enum_file, 'w'))
+local options_map_fd = assert(io.open(options_map_file, 'w'))
+
+--- @param s string
+local function enum_w(s)
+ options_enum_fd:write(s .. '\n')
+end
+
+--- @param s string
+local function map_w(s)
+ options_map_fd:write(s .. '\n')
+end
+
+enum_w('// IWYU pragma: private, include "nvim/option_defs.h"')
+enum_w('')
+
+--- @param s string
+--- @return string
+local lowercase_to_titlecase = function(s)
+ return s:sub(1, 1):upper() .. s:sub(2)
+end
+
+--- @type vim.option_meta[]
+local options = require('options').options
+
+-- Generate BV_ enum constants.
+enum_w('/// "indir" values for buffer-local options.')
+enum_w('/// These need to be defined globally, so that the BV_COUNT can be used with')
+enum_w('/// b_p_script_stx[].')
+enum_w('enum {')
+
+local bv_val = 0
+
+for _, o in ipairs(options) do
+ assert(#o.scope == 1 or #o.scope == 2)
+ assert(#o.scope == 1 or o.scope[1] == 'global')
+ local min_scope = o.scope[#o.scope]
+ if min_scope == 'buffer' then
+ local varname = o.pv_name or o.varname or ('p_' .. (o.abbreviation or o.full_name))
+ local bv_name = 'BV_' .. varname:sub(3):upper()
+ enum_w((' %s = %u,'):format(bv_name, bv_val))
+ bv_val = bv_val + 1
+ end
+end
+
+enum_w((' BV_COUNT = %u, ///< must be the last one'):format(bv_val))
+enum_w('};')
+enum_w('')
+
+-- Generate WV_ enum constants.
+enum_w('/// "indir" values for window-local options.')
+enum_w('/// These need to be defined globally, so that the WV_COUNT can be used in the')
+enum_w('/// window structure.')
+enum_w('enum {')
+
+local wv_val = 0
+
+for _, o in ipairs(options) do
+ assert(#o.scope == 1 or #o.scope == 2)
+ assert(#o.scope == 1 or o.scope[1] == 'global')
+ local min_scope = o.scope[#o.scope]
+ if min_scope == 'window' then
+ local varname = o.pv_name or o.varname or ('p_' .. (o.abbreviation or o.full_name))
+ local wv_name = 'WV_' .. varname:sub(3):upper()
+ enum_w((' %s = %u,'):format(wv_name, wv_val))
+ wv_val = wv_val + 1
+ end
+end
+
+enum_w((' WV_COUNT = %u, ///< must be the last one'):format(wv_val))
+enum_w('};')
+enum_w('')
+
+--- @type { [string]: string }
+local option_index = {}
+
+-- Generate option index enum and populate the `option_index` dictionary.
+enum_w('typedef enum {')
+enum_w(' kOptInvalid = -1,')
+
+for i, o in ipairs(options) do
+ local enum_val_name = 'kOpt' .. lowercase_to_titlecase(o.full_name)
+ enum_w((' %s = %u,'):format(enum_val_name, i - 1))
+
+ option_index[o.full_name] = enum_val_name
+
+ if o.abbreviation then
+ option_index[o.abbreviation] = enum_val_name
+ end
+
+ if o.alias then
+ o.alias = type(o.alias) == 'string' and { o.alias } or o.alias
+
+ for _, v in ipairs(o.alias) do
+ option_index[v] = enum_val_name
+ end
+ end
+end
+
+enum_w(' // Option count, used when iterating through options')
+enum_w('#define kOptIndexCount ' .. tostring(#options))
+enum_w('} OptIndex;')
+enum_w('')
+
+options_enum_fd:close()
+
+--- Generate option index map.
+local hashy = require('generators.hashy')
+local neworder, hashfun = hashy.hashy_hash('find_option', vim.tbl_keys(option_index), function(idx)
+ return ('option_hash_elems[%s].name'):format(idx)
+end)
+
+map_w('static const struct { const char *name; OptIndex opt_idx; } option_hash_elems[] = {')
+
+for _, name in ipairs(neworder) do
+ assert(option_index[name] ~= nil)
+ map_w((' { .name = "%s", .opt_idx = %s },'):format(name, option_index[name]))
+end
+
+map_w('};\n')
+map_w('static ' .. hashfun)
+
+options_map_fd:close()
diff --git a/src/nvim/generators/gen_unicode_tables.lua b/src/nvim/generators/gen_unicode_tables.lua
index 9ad99c8029..6cedb5db50 100644
--- a/src/nvim/generators/gen_unicode_tables.lua
+++ b/src/nvim/generators/gen_unicode_tables.lua
@@ -60,12 +60,10 @@ local fp_lines_to_lists = function(fp, n, has_comments)
if not line then
break
end
- if (not has_comments
- or (line:sub(1, 1) ~= '#' and not line:match('^%s*$'))) then
+ if not has_comments or (line:sub(1, 1) ~= '#' and not line:match('^%s*$')) then
local l = split_on_semicolons(line)
if #l ~= n then
- io.stderr:write(('Found %s items in line %u, expected %u\n'):format(
- #l, i, n))
+ io.stderr:write(('Found %s items in line %u, expected %u\n'):format(#l, i, n))
io.stderr:write('Line: ' .. line .. '\n')
return nil
end
@@ -93,15 +91,13 @@ end
local make_range = function(start, end_, step, add)
if step and add then
- return (' {0x%x, 0x%x, %d, %d},\n'):format(
- start, end_, step == 0 and -1 or step, add)
+ return (' {0x%x, 0x%x, %d, %d},\n'):format(start, end_, step == 0 and -1 or step, add)
else
return (' {0x%04x, 0x%04x},\n'):format(start, end_)
end
end
-local build_convert_table = function(ut_fp, props, cond_func, nl_index,
- table_name)
+local build_convert_table = function(ut_fp, props, cond_func, nl_index, table_name)
ut_fp:write('static const convertStruct ' .. table_name .. '[] = {\n')
local start = -1
local end_ = -1
@@ -137,8 +133,7 @@ local build_case_table = function(ut_fp, dataprops, table_name, index)
local cond_func = function(p)
return p[index] ~= ''
end
- return build_convert_table(ut_fp, dataprops, cond_func, index,
- 'to' .. table_name)
+ return build_convert_table(ut_fp, dataprops, cond_func, index, 'to' .. table_name)
end
local build_fold_table = function(ut_fp, foldprops)
@@ -154,7 +149,7 @@ local build_combining_table = function(ut_fp, dataprops)
local end_ = -1
for _, p in ipairs(dataprops) do
-- The 'Mc' property was removed, it does take up space.
- if (({Mn=true, Me=true})[p[3]]) then
+ if ({ Mn = true, Me = true })[p[3]] then
local n = tonumber(p[1], 16)
if start >= 0 and end_ + 1 == n then
-- Continue with the same range.
@@ -175,8 +170,7 @@ local build_combining_table = function(ut_fp, dataprops)
ut_fp:write('};\n')
end
-local build_width_table = function(ut_fp, dataprops, widthprops, widths,
- table_name)
+local build_width_table = function(ut_fp, dataprops, widthprops, widths, table_name)
ut_fp:write('static const struct interval ' .. table_name .. '[] = {\n')
local start = -1
local end_ = -1
@@ -208,13 +202,13 @@ local build_width_table = function(ut_fp, dataprops, widthprops, widths,
-- Only use the char when it’s not a composing char.
-- But use all chars from a range.
local dp = dataprops[dataidx]
- if (n_last > n) or (not (({Mn=true, Mc=true, Me=true})[dp[3]])) then
+ if (n_last > n) or not ({ Mn = true, Mc = true, Me = true })[dp[3]] then
if start >= 0 and end_ + 1 == n then -- luacheck: ignore 542
-- Continue with the same range.
else
if start >= 0 then
ut_fp:write(make_range(start, end_))
- table.insert(ret, {start, end_})
+ table.insert(ret, { start, end_ })
end
start = n
end
@@ -224,7 +218,7 @@ local build_width_table = function(ut_fp, dataprops, widthprops, widths,
end
if start >= 0 then
ut_fp:write(make_range(start, end_))
- table.insert(ret, {start, end_})
+ table.insert(ret, { start, end_ })
end
ut_fp:write('};\n')
return ret
@@ -316,10 +310,9 @@ local eaw_fp = io.open(eastasianwidth_fname, 'r')
local widthprops = parse_width_props(eaw_fp)
eaw_fp:close()
-local doublewidth = build_width_table(ut_fp, dataprops, widthprops,
- {W=true, F=true}, 'doublewidth')
-local ambiwidth = build_width_table(ut_fp, dataprops, widthprops,
- {A=true}, 'ambiguous')
+local doublewidth =
+ build_width_table(ut_fp, dataprops, widthprops, { W = true, F = true }, 'doublewidth')
+local ambiwidth = build_width_table(ut_fp, dataprops, widthprops, { A = true }, 'ambiguous')
local emoji_fp = io.open(emoji_fname, 'r')
local emojiprops = parse_emoji_props(emoji_fp)
diff --git a/src/nvim/generators/gen_vimvim.lua b/src/nvim/generators/gen_vimvim.lua
index 29355d3cda..fcdc5bddc2 100644
--- a/src/nvim/generators/gen_vimvim.lua
+++ b/src/nvim/generators/gen_vimvim.lua
@@ -41,12 +41,14 @@ end
-- Exclude these from the vimCommand keyword list, they are handled specially
-- in syntax/vim.vim (vimAugroupKey, vimAutoCmd, vimGlobal, vimSubst). #9327
local function is_special_cased_cmd(cmd)
- return (cmd == 'augroup'
- or cmd == 'autocmd'
- or cmd == 'doautocmd'
- or cmd == 'doautoall'
- or cmd == 'global'
- or cmd == 'substitute')
+ return (
+ cmd == 'augroup'
+ or cmd == 'autocmd'
+ or cmd == 'doautocmd'
+ or cmd == 'doautoall'
+ or cmd == 'global'
+ or cmd == 'substitute'
+ )
end
local vimcmd_start = 'syn keyword vimCommand contained '
@@ -81,7 +83,7 @@ local vimopt_start = 'syn keyword vimOption contained '
w('\n\n' .. vimopt_start)
for _, opt_desc in ipairs(options.options) do
- if not opt_desc.varname or opt_desc.varname:sub(1, 7) ~= 'p_force' then
+ if not opt_desc.immutable then
if lld.line_length > 850 then
w('\n' .. vimopt_start)
end
@@ -89,7 +91,7 @@ for _, opt_desc in ipairs(options.options) do
if opt_desc.abbreviation then
w(' ' .. opt_desc.abbreviation)
end
- if opt_desc.type == 'bool' then
+ if opt_desc.type == 'boolean' then
w(' inv' .. opt_desc.full_name)
w(' no' .. opt_desc.full_name)
if opt_desc.abbreviation then
@@ -133,7 +135,7 @@ end
w('\n\nsyn case match')
local vimfun_start = 'syn keyword vimFuncName contained '
w('\n\n' .. vimfun_start)
-local funcs = mpack.decode(io.open(funcs_file, 'rb'):read("*all"))
+local funcs = mpack.decode(io.open(funcs_file, 'rb'):read('*all'))
for _, name in ipairs(funcs) do
if name then
if lld.line_length > 850 then
diff --git a/src/nvim/generators/hashy.lua b/src/nvim/generators/hashy.lua
index b10bafb9f9..711e695742 100644
--- a/src/nvim/generators/hashy.lua
+++ b/src/nvim/generators/hashy.lua
@@ -3,7 +3,6 @@
local M = {}
_G.d = M
-
local function setdefault(table, key)
local val = table[key]
if val == nil then
@@ -16,28 +15,30 @@ end
function M.build_pos_hash(strings)
local len_buckets = {}
local maxlen = 0
- for _,s in ipairs(strings) do
- table.insert(setdefault(len_buckets, #s),s)
- if #s > maxlen then maxlen = #s end
+ for _, s in ipairs(strings) do
+ table.insert(setdefault(len_buckets, #s), s)
+ if #s > maxlen then
+ maxlen = #s
+ end
end
local len_pos_buckets = {}
local worst_buck_size = 0
- for len = 1,maxlen do
+ for len = 1, maxlen do
local strs = len_buckets[len]
if strs then
-- the best position so far generates `best_bucket`
-- with `minsize` worst case collisions
- local bestpos, minsize, best_bucket = nil, #strs*2, nil
- for pos = 1,len do
+ local bestpos, minsize, best_bucket = nil, #strs * 2, nil
+ for pos = 1, len do
local try_bucket = {}
- for _,str in ipairs(strs) do
+ for _, str in ipairs(strs) do
local poschar = string.sub(str, pos, pos)
table.insert(setdefault(try_bucket, poschar), str)
end
local maxsize = 1
- for _,pos_strs in pairs(try_bucket) do
+ for _, pos_strs in pairs(try_bucket) do
maxsize = math.max(maxsize, #pos_strs)
end
if maxsize < minsize then
@@ -46,7 +47,7 @@ function M.build_pos_hash(strings)
best_bucket = try_bucket
end
end
- len_pos_buckets[len] = {bestpos, best_bucket}
+ len_pos_buckets[len] = { bestpos, best_bucket }
worst_buck_size = math.max(worst_buck_size, minsize)
end
end
@@ -55,73 +56,79 @@ end
function M.switcher(put, tab, maxlen, worst_buck_size)
local neworder = {}
- put " switch (len) {\n"
+ put ' switch (len) {\n'
local bucky = worst_buck_size > 1
- for len = 1,maxlen do
+ for len = 1, maxlen do
local vals = tab[len]
if vals then
- put(" case "..len..": ")
+ put(' case ' .. len .. ': ')
local pos, posbuck = unpack(vals)
local keys = vim.tbl_keys(posbuck)
if #keys > 1 then
table.sort(keys)
- put("switch (str["..(pos-1).."]) {\n")
- for _,c in ipairs(keys) do
+ put('switch (str[' .. (pos - 1) .. ']) {\n')
+ for _, c in ipairs(keys) do
local buck = posbuck[c]
local startidx = #neworder
vim.list_extend(neworder, buck)
local endidx = #neworder
- put(" case '"..c.."': ")
- put("low = "..startidx.."; ")
- if bucky then put("high = "..endidx.."; ") end
- put "break;\n"
+ put(" case '" .. c .. "': ")
+ put('low = ' .. startidx .. '; ')
+ if bucky then
+ put('high = ' .. endidx .. '; ')
+ end
+ put 'break;\n'
end
- put " default: break;\n"
- put " }\n "
+ put ' default: break;\n'
+ put ' }\n '
else
- local startidx = #neworder
- table.insert(neworder, posbuck[keys[1]][1])
- local endidx = #neworder
- put("low = "..startidx.."; ")
- if bucky then put("high = "..endidx.."; ") end
+ local startidx = #neworder
+ table.insert(neworder, posbuck[keys[1]][1])
+ local endidx = #neworder
+ put('low = ' .. startidx .. '; ')
+ if bucky then
+ put('high = ' .. endidx .. '; ')
+ end
end
- put "break;\n"
+ put 'break;\n'
end
end
- put " default: break;\n"
- put " }\n"
+ put ' default: break;\n'
+ put ' }\n'
return neworder
end
function M.hashy_hash(name, strings, access)
local stats = {}
- local put = function(str) table.insert(stats, str) end
+ local put = function(str)
+ table.insert(stats, str)
+ end
local len_pos_buckets, maxlen, worst_buck_size = M.build_pos_hash(strings)
- put("int "..name.."_hash(const char *str, size_t len)\n{\n")
+ put('int ' .. name .. '_hash(const char *str, size_t len)\n{\n')
if worst_buck_size > 1 then
- put(" int low = 0, high = 0;\n")
+ put(' int low = 0, high = 0;\n')
else
- put(" int low = -1;\n")
+ put(' int low = -1;\n')
end
local neworder = M.switcher(put, len_pos_buckets, maxlen, worst_buck_size)
if worst_buck_size > 1 then
- put ([[
+ put([[
for (int i = low; i < high; i++) {
- if (!memcmp(str, ]]..access("i")..[[, len)) {
+ if (!memcmp(str, ]] .. access('i') .. [[, len)) {
return i;
}
}
return -1;
]])
else
- put ([[
- if (low < 0 || memcmp(str, ]]..access("low")..[[, len)) {
+ put([[
+ if (low < 0 || memcmp(str, ]] .. access('low') .. [[, len)) {
return -1;
}
return low;
]])
end
- put "}\n\n"
+ put '}\n\n'
return neworder, table.concat(stats)
end
diff --git a/src/nvim/generators/nvim_version.lua.in b/src/nvim/generators/nvim_version.lua.in
new file mode 100644
index 0000000000..d0dbf77922
--- /dev/null
+++ b/src/nvim/generators/nvim_version.lua.in
@@ -0,0 +1,9 @@
+return {
+ {"major", ${NVIM_VERSION_MAJOR}},
+ {"minor", ${NVIM_VERSION_MINOR}},
+ {"patch", ${NVIM_VERSION_PATCH}},
+ {"prerelease", "$NVIM_VERSION_PRERELEASE" ~= ""},
+ {"api_level", ${NVIM_API_LEVEL}},
+ {"api_compatible", ${NVIM_API_LEVEL_COMPAT}},
+ {"api_prerelease", ${NVIM_API_PRERELEASE}},
+}
diff --git a/src/nvim/generators/preload.lua b/src/nvim/generators/preload.lua
index 4b7fde2c39..e14671074c 100644
--- a/src/nvim/generators/preload.lua
+++ b/src/nvim/generators/preload.lua
@@ -1,10 +1,13 @@
local srcdir = table.remove(arg, 1)
local nlualib = table.remove(arg, 1)
-package.path = srcdir .. '/src/nvim/?.lua;' ..srcdir .. '/runtime/lua/?.lua;' .. package.path
-_G.vim = require'vim.shared'
+local gendir = table.remove(arg, 1)
+package.path = srcdir .. '/src/nvim/?.lua;' .. srcdir .. '/runtime/lua/?.lua;' .. package.path
+package.path = gendir .. '/?.lua;' .. package.path
+_G.vim = require 'vim.shared'
_G.vim.inspect = require 'vim.inspect'
package.cpath = package.cpath .. ';' .. nlualib
require 'nlua0'
+vim.NIL = vim.mpack.NIL -- WOW BOB WOW
arg[0] = table.remove(arg, 1)
return loadfile(arg[0])()
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 73af78d3e2..64c9c5a8c3 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -22,37 +22,42 @@
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
+#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/input.h"
#include "nvim/insexpand.h"
#include "nvim/keycodes.h"
#include "nvim/lua/executor.h"
-#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/mapping.h"
+#include "nvim/mapping_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/normal.h"
+#include "nvim/normal_defs.h"
#include "nvim/ops.h"
#include "nvim/option_vars.h"
#include "nvim/os/fileio.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/plines.h"
#include "nvim/pos_defs.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
@@ -60,8 +65,9 @@
#include "nvim/vim_defs.h"
/// Index in scriptin
-static int curscript = 0;
-FileDescriptor *scriptin[NSCRIPT] = { NULL };
+static int curscript = -1;
+/// Streams to read script from
+static FileDescriptor scriptin[NSCRIPT] = { 0 };
// These buffers are used for storing:
// - stuffed characters: A command that is translated into another command.
@@ -92,7 +98,7 @@ static int typeahead_char = 0; ///< typeahead char that's not flushed
/// When block_redo is true the redo buffer will not be changed.
/// Used by edit() to repeat insertions.
-static int block_redo = false;
+static bool block_redo = false;
static int KeyNoremap = 0; ///< remapping flags
@@ -190,15 +196,12 @@ static char *get_buffcont(buffheader_T *buffer, int dozero)
/// K_SPECIAL in the returned string is escaped.
char *get_recorded(void)
{
- char *p;
- size_t len;
-
- p = get_buffcont(&recordbuff, true);
+ char *p = get_buffcont(&recordbuff, true);
free_buff(&recordbuff);
// Remove the characters that were added the last time, these must be the
// (possibly mapped) characters that stopped the recording.
- len = strlen(p);
+ size_t len = strlen(p);
if (len >= last_recorded_len) {
len -= last_recorded_len;
p[len] = NUL;
@@ -274,12 +277,10 @@ static void add_buff(buffheader_T *const buf, const char *const s, ptrdiff_t sle
/// Only works when it was just added.
static void delete_buff_tail(buffheader_T *buf, int slen)
{
- int len;
-
if (buf->bh_curr == NULL) {
return; // nothing to delete
}
- len = (int)strlen(buf->bh_curr->b_str);
+ int len = (int)strlen(buf->bh_curr->b_str);
if (len < slen) {
return;
}
@@ -333,18 +334,16 @@ static void add_char_buff(buffheader_T *buf, int c)
/// if that one is empty.
/// If advance == true go to the next char.
/// No translation is done K_SPECIAL is escaped.
-static int read_readbuffers(int advance)
+static int read_readbuffers(bool advance)
{
- int c;
-
- c = read_readbuf(&readbuf1, advance);
+ int c = read_readbuf(&readbuf1, advance);
if (c == NUL) {
c = read_readbuf(&readbuf2, advance);
}
return c;
}
-static int read_readbuf(buffheader_T *buf, int advance)
+static int read_readbuf(buffheader_T *buf, bool advance)
{
if (buf->bh_first.b_next == NULL) { // buffer is empty
return NUL;
@@ -376,16 +375,16 @@ static void start_stuff(void)
}
}
-/// Return true if the stuff buffer is empty.
-int stuff_empty(void)
+/// @return true if the stuff buffer is empty.
+bool stuff_empty(void)
FUNC_ATTR_PURE
{
return (readbuf1.bh_first.b_next == NULL && readbuf2.bh_first.b_next == NULL);
}
-/// Return true if readbuf1 is empty. There may still be redo characters in
-/// redbuf2.
-int readbuf1_empty(void)
+/// @return true if readbuf1 is empty. There may still be redo characters in
+/// redbuf2.
+bool readbuf1_empty(void)
FUNC_ATTR_PURE
{
return (readbuf1.bh_first.b_next == NULL);
@@ -1002,7 +1001,7 @@ int ins_char_typebuf(int c, int modifiers)
unsigned len = special_to_buf(c, modifiers, true, buf);
assert(len < sizeof(buf));
buf[len] = NUL;
- (void)ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent);
+ ins_typebuf(buf, KeyNoremap, 0, !KeyTyped, cmd_silent);
return (int)len;
}
@@ -1148,10 +1147,10 @@ static void gotchars(const uint8_t *chars, size_t len)
maptick++;
}
-/// Record a <Nop> key.
-void gotchars_nop(void)
+/// Record an <Ignore> key.
+void gotchars_ignore(void)
{
- uint8_t nop_buf[3] = { K_SPECIAL, KS_EXTRA, KE_NOP };
+ uint8_t nop_buf[3] = { K_SPECIAL, KS_EXTRA, KE_IGNORE };
gotchars(nop_buf, 3);
}
@@ -1178,7 +1177,7 @@ void ungetchars(int len)
void may_sync_undo(void)
{
if ((!(State & (MODE_INSERT | MODE_CMDLINE)) || arrow_used)
- && scriptin[curscript] == NULL) {
+ && curscript < 0) {
u_sync(false);
}
}
@@ -1218,8 +1217,9 @@ void free_typebuf(void)
/// restored when "file" has been read completely.
static typebuf_T saved_typebuf[NSCRIPT];
-void save_typebuf(void)
+static void save_typebuf(void)
{
+ assert(curscript >= 0);
init_typebuf();
saved_typebuf[curscript] = typebuf;
alloc_typebuf();
@@ -1294,18 +1294,13 @@ void openscript(char *name, bool directly)
return;
}
- if (scriptin[curscript] != NULL) { // already reading script
- curscript++;
- }
+ curscript++;
// use NameBuff for expanded name
expand_env(name, NameBuff, MAXPATHL);
- int error;
- if ((scriptin[curscript] = file_open_new(&error, NameBuff,
- kFileReadOnly, 0)) == NULL) {
+ int error = file_open(&scriptin[curscript], NameBuff, kFileReadOnly, 0);
+ if (error) {
semsg(_(e_notopen_2), name, os_strerror(error));
- if (curscript) {
- curscript--;
- }
+ curscript--;
return;
}
save_typebuf();
@@ -1316,7 +1311,6 @@ void openscript(char *name, bool directly)
// always, "make test" would fail.
if (directly) {
oparg_T oa;
- int oldcurscript;
int save_State = State;
int save_restart_edit = restart_edit;
int save_finish_op = finish_op;
@@ -1328,12 +1322,12 @@ void openscript(char *name, bool directly)
clear_oparg(&oa);
finish_op = false;
- oldcurscript = curscript;
+ int oldcurscript = curscript;
do {
update_topline_cursor(); // update cursor position and topline
normal_cmd(&oa, false); // execute one command
- (void)vpeekc(); // check for end of file
- } while (scriptin[oldcurscript] != NULL);
+ vpeekc(); // check for end of file
+ } while (curscript >= oldcurscript);
State = save_State;
msg_scroll = save_msg_scroll;
@@ -1345,31 +1339,53 @@ void openscript(char *name, bool directly)
/// Close the currently active input script.
static void closescript(void)
{
+ assert(curscript >= 0);
free_typebuf();
typebuf = saved_typebuf[curscript];
- file_free(scriptin[curscript], false);
- scriptin[curscript] = NULL;
- if (curscript > 0) {
- curscript--;
- }
+ file_close(&scriptin[curscript], false);
+ curscript--;
}
#if defined(EXITFREE)
void close_all_scripts(void)
{
- while (scriptin[0] != NULL) {
+ while (curscript >= 0) {
closescript();
}
}
#endif
+bool open_scriptin(char *scriptin_name)
+ FUNC_ATTR_NONNULL_ALL
+{
+ assert(curscript == -1);
+ curscript++;
+
+ int error;
+ if (strequal(scriptin_name, "-")) {
+ error = file_open_stdin(&scriptin[0]);
+ } else {
+ error = file_open(&scriptin[0], scriptin_name,
+ kFileReadOnly|kFileNonBlocking, 0);
+ }
+ if (error) {
+ fprintf(stderr, _("Cannot open for reading: \"%s\": %s\n"),
+ scriptin_name, os_strerror(error));
+ curscript--;
+ return false;
+ }
+ save_typebuf();
+
+ return true;
+}
+
/// Return true when reading keys from a script file.
int using_script(void)
FUNC_ATTR_PURE
{
- return scriptin[curscript] != NULL;
+ return curscript >= 0;
}
/// This function is called just before doing a blocking wait. Thus after
@@ -1452,8 +1468,6 @@ int vgetc(void)
mouse_row = old_mouse_row;
mouse_col = old_mouse_col;
} else {
- int c2;
- int n;
// number of characters recorded from the last vgetc() call
static size_t last_vgetc_recorded_len = 0;
@@ -1483,7 +1497,7 @@ int vgetc(void)
int save_allow_keys = allow_keys;
no_mapping++;
allow_keys = 0; // make sure BS is not found
- c2 = vgetorpeek(true); // no mapping for these chars
+ int c2 = vgetorpeek(true); // no mapping for these chars
c = vgetorpeek(true);
no_mapping--;
allow_keys = save_allow_keys;
@@ -1576,6 +1590,7 @@ int vgetc(void)
// For a multi-byte character get all the bytes and return the
// converted character.
// Note: This will loop until enough bytes are received!
+ int n;
if ((n = MB_BYTE2LEN_CHECK(c)) > 1) {
no_mapping++;
buf[0] = (uint8_t)c;
@@ -1584,8 +1599,8 @@ int vgetc(void)
if (buf[i] == K_SPECIAL) {
// Must be a K_SPECIAL - KS_SPECIAL - KE_FILLER sequence,
// which represents a K_SPECIAL (0x80).
- (void)vgetorpeek(true); // skip KS_SPECIAL
- (void)vgetorpeek(true); // skip KE_FILLER
+ vgetorpeek(true); // skip KS_SPECIAL
+ vgetorpeek(true); // skip KE_FILLER
}
}
no_mapping--;
@@ -1607,7 +1622,7 @@ int vgetc(void)
&& !is_mouse_key(c)) {
mod_mask = 0;
int len = ins_char_typebuf(c, 0);
- (void)ins_char_typebuf(ESC, 0);
+ ins_char_typebuf(ESC, 0);
ungetchars(len + 3); // K_SPECIAL KS_MODIFIER MOD_MASK_ALT takes 3 more bytes
continue;
}
@@ -1639,9 +1654,7 @@ int vgetc(void)
/// directly from the user (ignoring typeahead).
int safe_vgetc(void)
{
- int c;
-
- c = vgetc();
+ int c = vgetc();
if (c == NUL) {
c = get_keystroke(NULL);
}
@@ -1679,9 +1692,7 @@ int vpeekc(void)
/// buffer, it must be an ESC that is recognized as the start of a key code.
int vpeekc_any(void)
{
- int c;
-
- c = vpeekc();
+ int c = vpeekc();
if (c == NUL && typebuf.tb_len > 0) {
c = ESC;
}
@@ -1692,10 +1703,8 @@ int vpeekc_any(void)
/// @return true if a character is available, false otherwise.
bool char_avail(void)
{
- int retval;
-
no_mapping++;
- retval = vpeekc();
+ int retval = vpeekc();
no_mapping--;
return retval != NUL;
}
@@ -1721,7 +1730,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
if (!char_avail()) {
// Flush screen updates before blocking.
ui_flush();
- (void)os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
+ os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
if (!multiqueue_empty(main_loop.events)) {
state_handle_k_event();
continue;
@@ -1794,7 +1803,7 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
if (win == NULL) {
return;
}
- (void)mouse_comp_pos(win, &row, &col, &lnum);
+ mouse_comp_pos(win, &row, &col, &lnum);
for (wp = firstwin; wp != win; wp = wp->w_next) {
winnr++;
}
@@ -1950,7 +1959,6 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth)
mapblock_T *mp_match;
int mp_match_len = 0;
int max_mlen = 0;
- int tb_c1;
int keylen = *keylenp;
int local_State = get_real_state();
bool is_plug_map = false;
@@ -1974,7 +1982,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth)
// - waiting for "hit return to continue" and CR or SPACE typed
// - waiting for a char with --more--
// - in Ctrl-X mode, and we get a valid char for that mode
- tb_c1 = typebuf.tb_buf[typebuf.tb_off];
+ int tb_c1 = typebuf.tb_buf[typebuf.tb_off];
if (no_mapping == 0
&& (no_zero_mapping == 0 || tb_c1 != '0')
&& (typebuf.tb_maplen == 0 || is_plug_map
@@ -2190,7 +2198,7 @@ static int handle_mapping(int *keylenp, const bool *timedout, int *mapdepth)
// mode temporarily. Append K_SELECT to switch back to Select mode.
if (VIsual_active && VIsual_select && (mp->m_mode & MODE_VISUAL)) {
VIsual_select = false;
- (void)ins_typebuf(K_SELECT_STRING, REMAP_NONE, 0, true, false);
+ ins_typebuf(K_SELECT_STRING, REMAP_NONE, 0, true, false);
}
// Copy the values from *mp that are used, because evaluating the
@@ -2513,20 +2521,22 @@ static int vgetorpeek(bool advance)
// we are expecting to truncate the trailing
// white-space, so find the last non-white
// character -- webb
- if (did_ai
- && *skipwhite(get_cursor_line_ptr() + curwin->w_cursor.col) == NUL) {
+ if (did_ai && *skipwhite(get_cursor_line_ptr() + curwin->w_cursor.col) == NUL) {
curwin->w_wcol = 0;
ptr = get_cursor_line_ptr();
- chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum, 0, ptr, ptr);
- while (cts.cts_ptr < ptr + curwin->w_cursor.col) {
- if (!ascii_iswhite(*cts.cts_ptr)) {
- curwin->w_wcol = cts.cts_vcol;
+ char *endptr = ptr + curwin->w_cursor.col;
+
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, curwin, curwin->w_cursor.lnum, ptr);
+ StrCharInfo ci = utf_ptr2StrCharInfo(ptr);
+ int vcol = 0;
+ while (ci.ptr < endptr) {
+ if (!ascii_iswhite(ci.chr.value)) {
+ curwin->w_wcol = vcol;
}
- cts.cts_vcol += lbr_chartabsize(&cts);
- cts.cts_ptr += utfc_ptr2len(cts.cts_ptr);
+ vcol += win_charsize(cstype, vcol, ci.ptr, ci.chr.value, &csarg).width;
+ ci = utfc_next(ci);
}
- clear_chartabsize_arg(&cts);
curwin->w_wrow = curwin->w_cline_row
+ curwin->w_wcol / curwin->w_width_inner;
@@ -2654,7 +2664,7 @@ static int vgetorpeek(bool advance)
showcmd_idx = typebuf.tb_len - SHOWCMD_COLS;
}
while (showcmd_idx < typebuf.tb_len) {
- (void)add_to_showcmd(typebuf.tb_buf[typebuf.tb_off + showcmd_idx++]);
+ add_to_showcmd(typebuf.tb_buf[typebuf.tb_off + showcmd_idx++]);
}
curwin->w_wcol = old_wcol;
curwin->w_wrow = old_wrow;
@@ -2755,9 +2765,9 @@ static int vgetorpeek(bool advance)
}
if (timedout && c == ESC) {
- // When recording there will be no timeout. Add a <Nop> after the ESC
- // to avoid that it forms a key code with following characters.
- gotchars_nop();
+ // When recording there will be no timeout. Add an <Ignore> after the
+ // ESC to avoid that it forms a key code with following characters.
+ gotchars_ignore();
}
vgetc_busy--;
@@ -2810,10 +2820,10 @@ int inchar(uint8_t *buf, int maxlen, long wait_time)
// Get a character from a script file if there is one.
// If interrupted: Stop reading script files, close them all.
ptrdiff_t read_size = -1;
- while (scriptin[curscript] != NULL && read_size <= 0 && !ignore_script) {
+ while (curscript >= 0 && read_size <= 0 && !ignore_script) {
char script_char;
if (got_int
- || (read_size = file_read(scriptin[curscript], &script_char, 1)) != 1) {
+ || (read_size = file_read(&scriptin[curscript], &script_char, 1)) != 1) {
// Reached EOF or some error occurred.
// Careful: closescript() frees typebuf.tb_buf[] and buf[] may
// point inside typebuf.tb_buf[]. Don't use buf[] after this!
@@ -2920,7 +2930,6 @@ char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat)
{
garray_T line_ga;
int c1 = -1;
- int c2;
int cmod = 0;
bool aborted = false;
@@ -2947,7 +2956,7 @@ char *getcmdkeycmd(int promptc, void *cookie, int indent, bool do_concat)
// Get two extra bytes for special keys
if (c1 == K_SPECIAL) {
c1 = vgetorpeek(true);
- c2 = vgetorpeek(true);
+ int c2 = vgetorpeek(true);
if (c1 == KS_MODIFIER) {
cmod = c2;
continue;
@@ -3037,7 +3046,7 @@ bool map_execute_lua(bool may_repeat)
Error err = ERROR_INIT;
Array args = ARRAY_DICT_INIT;
- nlua_call_ref(ref, NULL, args, false, &err);
+ nlua_call_ref(ref, NULL, args, kRetNilBool, NULL, &err);
if (err.type != kErrorTypeNone) {
semsg_multiline("E5108: %s", err.msg);
api_clear_error(&err);
diff --git a/src/nvim/getchar.h b/src/nvim/getchar.h
index 177a021706..4e962c9b03 100644
--- a/src/nvim/getchar.h
+++ b/src/nvim/getchar.h
@@ -1,11 +1,11 @@
#pragma once
-#include <stdbool.h>
-#include <stdint.h>
+#include <stddef.h> // IWYU pragma: keep
+#include <stdint.h> // IWYU pragma: keep
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
-#include "nvim/getchar_defs.h" // IWYU pragma: export
-#include "nvim/os/fileio.h"
+#include "nvim/getchar_defs.h" // IWYU pragma: keep
+#include "nvim/os/fileio_defs.h"
#include "nvim/types_defs.h" // IWYU pragma: keep
/// Argument for flush_buffers().
@@ -15,11 +15,7 @@ typedef enum {
FLUSH_INPUT, ///< flush typebuf and inchar() input
} flush_buffers_T;
-/// Maximum number of streams to read script from
-enum { NSCRIPT = 15, };
-
-/// Streams to read script from
-extern FileDescriptor *scriptin[NSCRIPT];
+enum { NSCRIPT = 15, }; ///< Maximum number of streams to read script from
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "getchar.h.generated.h"
diff --git a/src/nvim/getchar_defs.h b/src/nvim/getchar_defs.h
index 5e6db7d9f3..abf812fad3 100644
--- a/src/nvim/getchar_defs.h
+++ b/src/nvim/getchar_defs.h
@@ -6,22 +6,19 @@
#include "nvim/api/private/defs.h"
-typedef struct buffblock buffblock_T;
-typedef struct buffheader buffheader_T;
-
/// structure used to store one block of the stuff/redo/recording buffers
-struct buffblock {
- buffblock_T *b_next; ///< pointer to next buffblock
+typedef struct buffblock {
+ struct buffblock *b_next; ///< pointer to next buffblock
char b_str[1]; ///< contents (actually longer)
-};
+} buffblock_T;
/// header used for the stuff buffer and the redo buffer
-struct buffheader {
+typedef struct {
buffblock_T bh_first; ///< first (dummy) block of list
buffblock_T *bh_curr; ///< buffblock for appending
size_t bh_index; ///< index for reading
size_t bh_space; ///< space in bh_curr for appending
-};
+} buffheader_T;
typedef struct {
buffheader_T sr_redobuff;
diff --git a/src/nvim/gettext.h b/src/nvim/gettext_defs.h
index 2c7b5626d2..2c7b5626d2 100644
--- a/src/nvim/gettext.h
+++ b/src/nvim/gettext_defs.h
diff --git a/src/nvim/globals.h b/src/nvim/globals.h
index 270ffe4fa0..22f7daa823 100644
--- a/src/nvim/globals.h
+++ b/src/nvim/globals.h
@@ -11,10 +11,9 @@
#include "nvim/getchar_defs.h"
#include "nvim/iconv_defs.h"
#include "nvim/macros_defs.h"
-#include "nvim/mbyte.h"
#include "nvim/menu_defs.h"
#include "nvim/os/os_defs.h"
-#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/state_defs.h"
#include "nvim/syntax_defs.h"
#include "nvim/types_defs.h"
@@ -103,34 +102,6 @@ EXTERN struct nvim_stats_s {
EXTERN int Rows INIT( = DFLT_ROWS); // nr of rows in the screen
EXTERN int Columns INIT( = DFLT_COLS); // nr of columns in the screen
-// We use 64-bit file functions here, if available. E.g. ftello() returns
-// off_t instead of long, which helps if long is 32 bit and off_t is 64 bit.
-// We assume that when fseeko() is available then ftello() is too.
-// Note that Windows has different function names.
-#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__)
-typedef __int64 off_T;
-# ifdef __MINGW32__
-# define vim_lseek lseek64
-# define vim_fseek fseeko64
-# define vim_ftell ftello64
-# else
-# define vim_lseek _lseeki64
-# define vim_fseek _fseeki64
-# define vim_ftell _ftelli64
-# endif
-#else
-typedef off_t off_T;
-# ifdef HAVE_FSEEKO
-# define vim_lseek lseek
-# define vim_ftell ftello
-# define vim_fseek fseeko
-# else
-# define vim_lseek lseek
-# define vim_ftell ftell
-# define vim_fseek(a, b, c) fseek(a, (long)b, c)
-# endif
-#endif
-
// When vgetc() is called, it sets mod_mask to the set of modifiers that are
// held down based on the MOD_MASK_* symbols that are read first.
EXTERN int mod_mask INIT( = 0); // current key modifiers
@@ -152,7 +123,7 @@ EXTERN bool redraw_cmdline INIT( = false); // cmdline must be redrawn
EXTERN bool redraw_mode INIT( = false); // mode must be redrawn
EXTERN bool clear_cmdline INIT( = false); // cmdline must be cleared
EXTERN bool mode_displayed INIT( = false); // mode is being displayed
-EXTERN int cmdline_star INIT( = false); // cmdline is encrypted
+EXTERN int cmdline_star INIT( = 0); // cmdline is encrypted
EXTERN bool redrawing_cmdline INIT( = false); // cmdline is being redrawn
EXTERN bool cmdline_was_last_drawn INIT( = false); // cmdline was last drawn
@@ -370,24 +341,7 @@ EXTERN bool did_check_timestamps INIT( = false); // did check timestamps
// recently
EXTERN int no_check_timestamps INIT( = 0); // Don't check timestamps
-EXTERN bool autocmd_busy INIT( = false); // Is apply_autocmds() busy?
-EXTERN int autocmd_no_enter INIT( = false); // *Enter autocmds disabled
-EXTERN int autocmd_no_leave INIT( = false); // *Leave autocmds disabled
EXTERN int modified_was_set; // did ":set modified"
-EXTERN bool did_filetype INIT( = false); // FileType event found
-// value for did_filetype when starting to execute autocommands
-EXTERN bool keep_filetype INIT( = false);
-
-// When deleting the current buffer, another one must be loaded.
-// If we know which one is preferred, au_new_curbuf is set to it.
-EXTERN bufref_T au_new_curbuf INIT( = { NULL, 0, 0 });
-
-// When deleting a buffer/window and autocmd_busy is true, do not free the
-// buffer/window. but link it in the list starting with
-// au_pending_free_buf/ap_pending_free_win, using b_next/w_next.
-// Free the buffer/window when autocmd_busy is being set to false.
-EXTERN buf_T *au_pending_free_buf INIT( = NULL);
-EXTERN win_T *au_pending_free_win INIT( = NULL);
// Mouse coordinates, set by handle_mouse_event()
EXTERN int mouse_grid;
@@ -412,7 +366,7 @@ EXTERN win_T *lastwin; // last window
EXTERN win_T *prevwin INIT( = NULL); // previous window
#define ONE_WINDOW (firstwin == lastwin)
#define FOR_ALL_FRAMES(frp, first_frame) \
- for ((frp) = first_frame; (frp) != NULL; (frp) = (frp)->fr_next) // NOLINT
+ for ((frp) = first_frame; (frp) != NULL; (frp) = (frp)->fr_next)
// When using this macro "break" only breaks out of the inner loop. Use "goto"
// to break out of the tabpage loop.
@@ -426,19 +380,6 @@ EXTERN win_T *prevwin INIT( = NULL); // previous window
EXTERN win_T *curwin; // currently active window
-typedef struct {
- win_T *auc_win; ///< Window used in aucmd_prepbuf(). When not NULL the
- ///< window has been allocated.
- bool auc_win_used; ///< This auc_win is being used.
-} aucmdwin_T;
-
-/// When executing autocommands for a buffer that is not in any window, a
-/// special window is created to handle the side effects. When autocommands
-/// nest we may need more than one.
-EXTERN kvec_t(aucmdwin_T) aucmd_win_vec INIT( = KV_INITIAL_VALUE);
-#define aucmd_win (aucmd_win_vec.items)
-#define AUCMD_WIN_COUNT ((int)aucmd_win_vec.size)
-
// The window layout is kept in a tree of frames. topframe points to the top
// of the tree.
EXTERN frame_T *topframe; // top of the window frame tree
@@ -467,7 +408,7 @@ EXTERN buf_T *curbuf INIT( = NULL); // currently active buffer
for (buf_T *buf = lastbuf; buf != NULL; buf = buf->b_prev)
#define FOR_ALL_BUF_WININFO(buf, wip) \
- for ((wip) = (buf)->b_wininfo; (wip) != NULL; (wip) = (wip)->wi_next) // NOLINT
+ for ((wip) = (buf)->b_wininfo; (wip) != NULL; (wip) = (wip)->wi_next)
// List of files being edited (global argument list). curwin->w_alist points
// to this when the window is using the global argument list.
@@ -649,9 +590,9 @@ EXTERN int reg_executing INIT( = 0); // register being executed or zero
EXTERN bool pending_end_reg_executing INIT( = false);
EXTERN int reg_recorded INIT( = 0); // last recorded register or zero
-EXTERN int no_mapping INIT( = false); // currently no mapping allowed
+EXTERN int no_mapping INIT( = 0); // currently no mapping allowed
EXTERN int no_zero_mapping INIT( = 0); // mapping zero not allowed
-EXTERN int allow_keys INIT( = false); // allow key codes when no_mapping is set
+EXTERN int allow_keys INIT( = 0); // allow key codes when no_mapping is set
EXTERN int no_u_sync INIT( = 0); // Don't call u_sync()
EXTERN int u_sync_once INIT( = 0); // Call u_sync() once when evaluating
// an expression.
@@ -659,10 +600,10 @@ EXTERN int u_sync_once INIT( = 0); // Call u_sync() once when evaluating
EXTERN bool force_restart_edit INIT( = false); // force restart_edit after
// ex_normal returns
EXTERN int restart_edit INIT( = 0); // call edit when next cmd finished
-EXTERN int arrow_used; // Normally false, set to true after
- // hitting cursor key in insert mode.
- // Used by vgetorpeek() to decide when
- // to call u_sync()
+EXTERN bool arrow_used; // Normally false, set to true after
+ // hitting cursor key in insert mode.
+ // Used by vgetorpeek() to decide when
+ // to call u_sync()
EXTERN bool ins_at_eol INIT( = false); // put cursor after eol when
// restarting edit after CTRL-O
@@ -717,9 +658,9 @@ EXTERN bool typebuf_was_empty INIT( = false);
EXTERN int ex_normal_busy INIT( = 0); // recursiveness of ex_normal()
EXTERN int expr_map_lock INIT( = 0); // running expr mapping, prevent use of ex_normal() and text changes
EXTERN bool ignore_script INIT( = false); // ignore script input
-EXTERN int stop_insert_mode; // for ":stopinsert"
-EXTERN bool KeyTyped; // true if user typed current char
-EXTERN int KeyStuffed; // true if current char from stuffbuf
+EXTERN bool stop_insert_mode; // for ":stopinsert"
+EXTERN bool KeyTyped; // true if user typed current char
+EXTERN int KeyStuffed; // true if current char from stuffbuf
EXTERN int maptick INIT( = 0); // tick for each non-mapped char
EXTERN int must_redraw INIT( = 0); // type of redraw necessary
@@ -730,7 +671,7 @@ EXTERN bool must_redraw_pum INIT( = false); // redraw pum. NB: must_redraw
EXTERN bool need_highlight_changed INIT( = true);
-EXTERN FILE *scriptout INIT( = NULL); ///< Stream to write script to.
+EXTERN FILE *scriptout INIT( = NULL); ///< Write input to this file ("nvim -w").
// Note that even when handling SIGINT, volatile is not necessary because the
// callback is not called directly from the signal handlers.
@@ -758,11 +699,6 @@ EXTERN char last_mode[MODE_MAX_LENGTH] INIT( = "n");
EXTERN char *last_cmdline INIT( = NULL); // last command line (for ":)
EXTERN char *repeat_cmdline INIT( = NULL); // command line for "."
EXTERN char *new_last_cmdline INIT( = NULL); // new value for last_cmdline
-EXTERN char *autocmd_fname INIT( = NULL); // fname for <afile> on cmdline
-EXTERN bool autocmd_fname_full INIT( = false); // autocmd_fname is full path
-EXTERN int autocmd_bufnr INIT( = 0); // fnum for <abuf> on cmdline
-EXTERN char *autocmd_match INIT( = NULL); // name for <amatch> on cmdline
-EXTERN bool did_cursorhold INIT( = false); // set when CursorHold t'gerd
EXTERN int postponed_split INIT( = 0); // for CTRL-W CTRL-] command
EXTERN int postponed_split_flags INIT( = 0); // args for win_split()
@@ -788,7 +724,7 @@ EXTERN char *empty_string_option INIT( = "");
EXTERN bool redir_off INIT( = false); // no redirection for a moment
EXTERN FILE *redir_fd INIT( = NULL); // message redirection file
EXTERN int redir_reg INIT( = 0); // message redirection register
-EXTERN int redir_vname INIT( = 0); // message redirection variable
+EXTERN bool redir_vname INIT( = false); // message redirection variable
EXTERN garray_T *capture_ga INIT( = NULL); // captured output for execute()
EXTERN uint8_t langmap_mapchar[256]; // mapping for language keys
@@ -816,6 +752,8 @@ EXTERN bool km_startsel INIT( = false);
EXTERN int cmdwin_type INIT( = 0); ///< type of cmdline window or 0
EXTERN int cmdwin_result INIT( = 0); ///< result of cmdline window or 0
EXTERN int cmdwin_level INIT( = 0); ///< cmdline recursion level
+EXTERN buf_T *cmdwin_buf INIT( = NULL); ///< buffer of cmdline window or NULL
+EXTERN win_T *cmdwin_win INIT( = NULL); ///< window of cmdline window or NULL
EXTERN win_T *cmdwin_old_curwin INIT( = NULL); ///< curwin before opening cmdline window or NULL
EXTERN char no_lines_msg[] INIT( = N_("--No lines in buffer--"));
@@ -868,7 +806,9 @@ EXTERN const char e_argreq[] INIT(= N_("E471: Argument required"));
EXTERN const char e_backslash[] INIT(= N_("E10: \\ should be followed by /, ? or &"));
EXTERN const char e_cmdwin[] INIT(= N_("E11: Invalid in command-line window; <CR> executes, CTRL-C quits"));
EXTERN const char e_curdir[] INIT(= N_("E12: Command not allowed in secure mode in current dir or tag search"));
+EXTERN const char e_invalid_buffer_name_str[] INIT(= N_("E158: Invalid buffer name: %s"));
EXTERN const char e_command_too_recursive[] INIT(= N_("E169: Command too recursive"));
+EXTERN const char e_buffer_is_not_loaded[] INIT(= N_("E681: Buffer is not loaded"));
EXTERN const char e_endif[] INIT(= N_("E171: Missing :endif"));
EXTERN const char e_endtry[] INIT(= N_("E600: Missing :endtry"));
EXTERN const char e_endwhile[] INIT(= N_("E170: Missing :endwhile"));
@@ -950,6 +890,7 @@ EXTERN const char e_invalblob[] INIT(= N_("E978: Invalid operation for Blob"));
EXTERN const char e_toomanyarg[] INIT(= N_("E118: Too many arguments for function: %s"));
EXTERN const char e_toofewarg[] INIT(= N_("E119: Not enough arguments for function: %s"));
EXTERN const char e_dictkey[] INIT(= N_("E716: Key not present in Dictionary: \"%s\""));
+EXTERN const char e_dictkey_len[] INIT(= N_("E716: Key not present in Dictionary: \"%.*s\""));
EXTERN const char e_listreq[] INIT(= N_("E714: List required"));
EXTERN const char e_listblobreq[] INIT(= N_("E897: List or Blob required"));
EXTERN const char e_listdictarg[] INIT(= N_("E712: Argument of %s must be a List or Dictionary"));
@@ -1037,7 +978,7 @@ EXTERN const char bot_top_msg[] INIT(= N_("search hit BOTTOM, continuing at TOP"
EXTERN const char line_msg[] INIT(= N_(" line "));
-EXTERN FILE *time_fd INIT(= NULL); // where to write startup timing
+EXTERN FILE *time_fd INIT(= NULL); // Where to write --startuptime report.
// Some compilers warn for not using a return value, but in some situations we
// can't do anything useful with the value. Assign to this variable to avoid
@@ -1051,39 +992,7 @@ EXTERN bool headless_mode INIT(= false);
// uncrustify:on
-/// Used to track the status of external functions.
-/// Currently only used for iconv().
-typedef enum {
- kUnknown,
- kWorking,
- kBroken,
-} WorkingStatus;
-
-/// The scope of a working-directory command like `:cd`.
-///
-/// Scopes are enumerated from lowest to highest. When adding a scope make sure
-/// to update all functions using scopes as well, such as the implementation of
-/// `getcwd()`. When using scopes as limits (e.g. in loops) don't use the scopes
-/// directly, use `MIN_CD_SCOPE` and `MAX_CD_SCOPE` instead.
-typedef enum {
- kCdScopeInvalid = -1,
- kCdScopeWindow, ///< Affects one window.
- kCdScopeTabpage, ///< Affects one tab page.
- kCdScopeGlobal, ///< Affects the entire Nvim instance.
-} CdScope;
-
-#define MIN_CD_SCOPE kCdScopeWindow
-#define MAX_CD_SCOPE kCdScopeGlobal
-
-/// What caused the current directory to change.
-typedef enum {
- kCdCauseOther = -1,
- kCdCauseManual, ///< Using `:cd`, `:tcd`, `:lcd` or `chdir()`.
- kCdCauseWindow, ///< Switching to another window.
- kCdCauseAuto, ///< On 'autochdir'.
-} CdCause;
-
-// Only filled for Win32.
+/// Only filled for Win32.
EXTERN char windowsVersion[20] INIT( = { 0 });
/// While executing a regexp and set to OPTION_MAGIC_ON or OPTION_MAGIC_OFF this
diff --git a/src/nvim/grid.c b/src/nvim/grid.c
index 2ef89b778e..e386853022 100644
--- a/src/nvim/grid.c
+++ b/src/nvim/grid.c
@@ -24,11 +24,14 @@
#include "nvim/highlight.h"
#include "nvim/log.h"
#include "nvim/map_defs.h"
+#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option_vars.h"
+#include "nvim/optionstr.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "grid.c.generated.h"
@@ -67,7 +70,7 @@ void grid_adjust(ScreenGrid **grid, int *row_off, int *col_off)
}
}
-schar_T schar_from_str(char *str)
+schar_T schar_from_str(const char *str)
{
if (str == NULL) {
return 0;
@@ -120,6 +123,13 @@ void schar_cache_clear(void)
{
decor_check_invalid_glyphs();
set_clear(glyph, &glyph_cache);
+
+ // for char options we have stored the original strings. Regenerate
+ // the parsed schar_T values with the new clean cache.
+ // This must not return an error as cell widths have not changed.
+ if (check_chars_options()) {
+ abort();
+ }
}
bool schar_high(schar_T sc)
@@ -137,15 +147,39 @@ bool schar_high(schar_T sc)
# define schar_idx(sc) (sc >> 8)
#endif
-void schar_get(char *buf_out, schar_T sc)
+/// sets final NUL
+size_t schar_get(char *buf_out, schar_T sc)
+{
+ size_t len = schar_get_adv(&buf_out, sc);
+ *buf_out = NUL;
+ return len;
+}
+
+/// advance buf_out. do NOT set final NUL
+size_t schar_get_adv(char **buf_out, schar_T sc)
+{
+ size_t len;
+ if (schar_high(sc)) {
+ uint32_t idx = schar_idx(sc);
+ assert(idx < glyph_cache.h.n_keys);
+ len = strlen(&glyph_cache.keys[idx]);
+ memcpy(*buf_out, &glyph_cache.keys[idx], len);
+ } else {
+ len = strnlen((char *)&sc, 4);
+ memcpy(*buf_out, (char *)&sc, len);
+ }
+ *buf_out += len;
+ return len;
+}
+
+size_t schar_len(schar_T sc)
{
if (schar_high(sc)) {
uint32_t idx = schar_idx(sc);
assert(idx < glyph_cache.h.n_keys);
- xstrlcpy(buf_out, &glyph_cache.keys[idx], 32);
+ return strlen(&glyph_cache.keys[idx]);
} else {
- memcpy(buf_out, (char *)&sc, 4);
- buf_out[4] = NUL;
+ return strnlen((char *)&sc, 4);
}
}
@@ -243,7 +277,7 @@ void line_do_arabic_shape(schar_T *buf, int cols)
// Too bigly, discard one code-point.
// This should be enough as c0 cannot grow more than from 2 to 4 bytes
// (base arabic to extended arabic)
- rest -= (size_t)utf_cp_head_off(scbuf + off, scbuf + off + rest - 1) + 1;
+ rest -= (size_t)utf_cp_bounds(scbuf + off, scbuf + off + rest - 1).begin_off + 1;
}
memcpy(scbuf_new + len, scbuf + off, rest);
buf[i] = schar_from_buf(scbuf_new, len + rest);
@@ -263,13 +297,13 @@ void grid_clear_line(ScreenGrid *grid, size_t off, int width, bool valid)
grid->chars[off + (size_t)col] = schar_from_ascii(' ');
}
int fill = valid ? 0 : -1;
- (void)memset(grid->attrs + off, fill, (size_t)width * sizeof(sattr_T));
- (void)memset(grid->vcols + off, -1, (size_t)width * sizeof(colnr_T));
+ memset(grid->attrs + off, fill, (size_t)width * sizeof(sattr_T));
+ memset(grid->vcols + off, -1, (size_t)width * sizeof(colnr_T));
}
void grid_invalidate(ScreenGrid *grid)
{
- (void)memset(grid->attrs, -1, sizeof(sattr_T) * (size_t)grid->rows * (size_t)grid->cols);
+ memset(grid->attrs, -1, sizeof(sattr_T) * (size_t)grid->rows * (size_t)grid->cols);
}
static bool grid_invalid_row(ScreenGrid *grid, int row)
@@ -302,6 +336,9 @@ static int grid_line_coloff = 0;
static int grid_line_maxcol = 0;
static int grid_line_first = INT_MAX;
static int grid_line_last = 0;
+static int grid_line_clear_to = 0;
+static int grid_line_clear_attr = 0;
+static bool grid_line_rl = false;
/// Start a group of grid_line_puts calls that builds a single grid line.
///
@@ -310,14 +347,18 @@ static int grid_line_last = 0;
void grid_line_start(ScreenGrid *grid, int row)
{
int col = 0;
+ grid_line_maxcol = grid->cols;
grid_adjust(&grid, &row, &col);
assert(grid_line_grid == NULL);
grid_line_row = row;
grid_line_grid = grid;
grid_line_coloff = col;
grid_line_first = (int)linebuf_size;
- grid_line_maxcol = grid->cols - grid_line_coloff;
+ grid_line_maxcol = MIN(grid_line_maxcol, grid->cols - grid_line_coloff);
grid_line_last = 0;
+ grid_line_clear_to = 0;
+ grid_line_clear_attr = 0;
+ grid_line_rl = false;
assert((size_t)grid_line_maxcol <= linebuf_size);
@@ -433,14 +474,13 @@ int grid_line_puts(int col, const char *text, int textlen, int attr)
return col - start_col;
}
-void grid_line_fill(int start_col, int end_col, int c, int attr)
+int grid_line_fill(int start_col, int end_col, schar_T sc, int attr)
{
end_col = MIN(end_col, grid_line_maxcol);
if (start_col >= end_col) {
- return;
+ return end_col;
}
- schar_T sc = schar_from_char(c);
for (int col = start_col; col < end_col; col++) {
linebuf_char[col] = sc;
linebuf_attr[col] = attr;
@@ -449,6 +489,17 @@ void grid_line_fill(int start_col, int end_col, int c, int attr)
grid_line_first = MIN(grid_line_first, start_col);
grid_line_last = MAX(grid_line_last, end_col);
+ return end_col;
+}
+
+void grid_line_clear_end(int start_col, int end_col, int attr)
+{
+ if (grid_line_first > start_col) {
+ grid_line_first = start_col;
+ grid_line_last = start_col;
+ }
+ grid_line_clear_to = end_col;
+ grid_line_clear_attr = attr;
}
/// move the cursor to a position in a currently rendered line.
@@ -459,13 +510,15 @@ void grid_line_cursor_goto(int col)
void grid_line_mirror(void)
{
- if (grid_line_first >= grid_line_last) {
+ grid_line_clear_to = MAX(grid_line_last, grid_line_clear_to);
+ if (grid_line_first >= grid_line_clear_to) {
return;
}
- linebuf_mirror(&grid_line_first, &grid_line_last, grid_line_maxcol);
+ linebuf_mirror(&grid_line_first, &grid_line_last, &grid_line_clear_to, grid_line_maxcol);
+ grid_line_rl = true;
}
-void linebuf_mirror(int *firstp, int *lastp, int maxcol)
+void linebuf_mirror(int *firstp, int *lastp, int *clearp, int maxcol)
{
int first = *firstp;
int last = *lastp;
@@ -498,8 +551,9 @@ void linebuf_mirror(int *firstp, int *lastp, int maxcol)
linebuf_vcol[mirror - col] = scratch_vcol[col];
}
- *lastp = maxcol - first;
- *firstp = maxcol - last;
+ *firstp = maxcol - *clearp;
+ *clearp = maxcol - first;
+ *lastp = maxcol - last;
}
/// End a group of grid_line_puts calls and send the screen buffer to the UI layer.
@@ -507,13 +561,14 @@ void grid_line_flush(void)
{
ScreenGrid *grid = grid_line_grid;
grid_line_grid = NULL;
- assert(grid_line_last <= grid_line_maxcol);
- if (grid_line_first >= grid_line_last) {
+ grid_line_clear_to = MAX(grid_line_last, grid_line_clear_to);
+ assert(grid_line_clear_to <= grid_line_maxcol);
+ if (grid_line_first >= grid_line_clear_to) {
return;
}
grid_put_linebuf(grid, grid_line_row, grid_line_coloff, grid_line_first, grid_line_last,
- grid_line_last, false, 0, false);
+ grid_line_clear_to, grid_line_rl, grid_line_clear_attr, false);
}
/// flush grid line but only if on a valid row
@@ -532,89 +587,17 @@ void grid_line_flush_if_valid_row(void)
grid_line_flush();
}
-/// Fill the grid from "start_row" to "end_row" (exclusive), from "start_col"
-/// to "end_col" (exclusive) with character "c1" in first column followed by
-/// "c2" in the other columns. Use attributes "attr".
-void grid_fill(ScreenGrid *grid, int start_row, int end_row, int start_col, int end_col, int c1,
- int c2, int attr)
+void grid_clear(ScreenGrid *grid, int start_row, int end_row, int start_col, int end_col, int attr)
{
- int row_off = 0, col_off = 0;
- grid_adjust(&grid, &row_off, &col_off);
- start_row += row_off;
- end_row += row_off;
- start_col += col_off;
- end_col += col_off;
-
- // safety check
- if (end_row > grid->rows) {
- end_row = grid->rows;
- }
- if (end_col > grid->cols) {
- end_col = grid->cols;
- }
-
- // nothing to do
- if (start_row >= end_row || start_col >= end_col) {
- return;
- }
-
for (int row = start_row; row < end_row; row++) {
- int dirty_first = INT_MAX;
- int dirty_last = 0;
- size_t lineoff = grid->line_offset[row];
-
- // When drawing over the right half of a double-wide char clear
- // out the left half. When drawing over the left half of a
- // double wide-char clear out the right half. Only needed in a
- // terminal.
- if (start_col > 0 && grid->chars[lineoff + (size_t)start_col] == NUL) {
- size_t off = lineoff + (size_t)start_col - 1;
- grid->chars[off] = schar_from_ascii(' ');
- grid->attrs[off] = attr;
- dirty_first = start_col - 1;
- }
- if (end_col < grid->cols && grid->chars[lineoff + (size_t)end_col] == NUL) {
- size_t off = lineoff + (size_t)end_col;
- grid->chars[off] = schar_from_ascii(' ');
- grid->attrs[off] = attr;
- dirty_last = end_col + 1;
- }
-
- int col = start_col;
- schar_T sc = schar_from_char(c1);
- for (col = start_col; col < end_col; col++) {
- size_t off = lineoff + (size_t)col;
- if (grid->chars[off] != sc || grid->attrs[off] != attr || rdb_flags & RDB_NODELTA) {
- grid->chars[off] = sc;
- grid->attrs[off] = attr;
- if (dirty_first == INT_MAX) {
- dirty_first = col;
- }
- dirty_last = col + 1;
- }
- grid->vcols[off] = -1;
- if (col == start_col) {
- sc = schar_from_char(c2);
- }
- }
- if (dirty_last > dirty_first) {
- if (grid->throttled) {
- // Note: assumes msg_grid is the only throttled grid
- assert(grid == &msg_grid);
- int dirty = 0;
- if (attr != HL_ATTR(HLF_MSG) || c2 != ' ') {
- dirty = dirty_last;
- } else if (c1 != ' ') {
- dirty = dirty_first + 1;
- }
- if (grid->dirty_col && dirty > grid->dirty_col[row]) {
- grid->dirty_col[row] = dirty;
- }
- } else {
- int last = c2 != ' ' ? dirty_last : dirty_first + (c1 != ' ');
- ui_line(grid, row, dirty_first, last, dirty_last, attr, false);
- }
+ grid_line_start(grid, row);
+ end_col = MIN(end_col, grid_line_maxcol);
+ if (grid_line_row >= grid_line_grid->rows || start_col >= end_col) {
+ grid_line_grid = NULL; // TODO(bfredl): make callers behave instead
+ return;
}
+ grid_line_clear_end(start_col, end_col, attr);
+ grid_line_flush();
}
}
@@ -650,8 +633,6 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
{
bool redraw_next; // redraw_this for next character
bool clear_next = false;
- int char_cells; // 1: normal char
- // 2: occupies two display cells
assert(0 <= row && row < grid->rows);
// TODO(bfredl): check all callsites and eliminate
// Check for illegal col, just in case
@@ -673,22 +654,16 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
// two-cell character in the same grid, truncate that into a '>'.
if (col > 0 && grid->chars[off_to + (size_t)col] == 0) {
linebuf_char[col - 1] = schar_from_ascii('>');
+ linebuf_attr[col - 1] = grid->attrs[off_to + (size_t)col - 1];
col--;
}
+ int clear_start = endcol;
if (rl) {
- // Clear rest first, because it's left of the text.
- if (clear_width > 0) {
- while (col <= endcol && grid->chars[off_to + (size_t)col] == schar_from_ascii(' ')
- && grid->attrs[off_to + (size_t)col] == bg_attr) {
- col++;
- }
- if (col <= endcol) {
- grid_fill(grid, row, row + 1, col + coloff, endcol + coloff + 1, ' ', ' ', bg_attr);
- }
- }
- col = endcol + 1;
+ clear_start = col;
+ col = endcol;
endcol = clear_width;
+ clear_width = col;
}
if (p_arshape && !p_tbidi && endcol > col) {
@@ -701,17 +676,19 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
}
}
- redraw_next = grid_char_needs_redraw(grid, col, (size_t)col + off_to, endcol - col);
+ redraw_next = grid_char_needs_redraw(grid, col, off_to + (size_t)col, endcol - col);
- int start_dirty = -1, end_dirty = 0;
+ int start_dirty = -1;
+ int end_dirty = 0;
while (col < endcol) {
- char_cells = 1;
+ int char_cells = 1; // 1: normal char
+ // 2: occupies two display cells
if (col + 1 < endcol && linebuf_char[col + 1] == 0) {
char_cells = 2;
}
bool redraw_this = redraw_next; // Does character need redraw?
- size_t off = (size_t)col + off_to;
+ size_t off = off_to + (size_t)col;
redraw_next = grid_char_needs_redraw(grid, col + char_cells,
off + (size_t)char_cells,
endcol - col - char_cells);
@@ -755,49 +732,59 @@ void grid_put_linebuf(ScreenGrid *grid, int row, int coloff, int col, int endcol
if (clear_next) {
// Clear the second half of a double-wide character of which the left
// half was overwritten with a single-wide character.
- grid->chars[(size_t)col + off_to] = schar_from_ascii(' ');
+ grid->chars[off_to + (size_t)col] = schar_from_ascii(' ');
end_dirty++;
}
- int clear_end = -1;
- if (clear_width > 0 && !rl) {
- // blank out the rest of the line
- // TODO(bfredl): we could cache winline widths
- while (col < clear_width) {
- size_t off = (size_t)col + off_to;
- if (grid->chars[off] != schar_from_ascii(' ')
- || grid->attrs[off] != bg_attr
- || rdb_flags & RDB_NODELTA) {
- grid->chars[off] = schar_from_ascii(' ');
- grid->attrs[off] = bg_attr;
- if (start_dirty == -1) {
- start_dirty = col;
- end_dirty = col;
- } else if (clear_end == -1) {
- end_dirty = endcol;
- }
- clear_end = col + 1;
+ // When clearing the left half of a double-wide char also clear the right half.
+ if (off_to + (size_t)clear_width < max_off_to
+ && grid->chars[off_to + (size_t)clear_width] == 0) {
+ clear_width++;
+ }
+
+ int clear_dirty_start = -1, clear_end = -1;
+ // blank out the rest of the line
+ // TODO(bfredl): we could cache winline widths
+ col = clear_start;
+ while (col < clear_width) {
+ size_t off = off_to + (size_t)col;
+ if (grid->chars[off] != schar_from_ascii(' ')
+ || grid->attrs[off] != bg_attr
+ || rdb_flags & RDB_NODELTA) {
+ grid->chars[off] = schar_from_ascii(' ');
+ grid->attrs[off] = bg_attr;
+ if (clear_dirty_start == -1) {
+ clear_dirty_start = col;
}
- grid->vcols[off] = MAXCOL;
- col++;
+ clear_end = col + 1;
}
+ grid->vcols[off] = MAXCOL;
+ col++;
}
- if (clear_end < end_dirty) {
+ if (rl && start_dirty != -1 && clear_dirty_start != -1) {
+ if (grid->throttled || clear_dirty_start >= start_dirty - 5) {
+ // cannot draw now or too small to be worth a separate "clear" event
+ start_dirty = clear_dirty_start;
+ } else {
+ ui_line(grid, row, invalid_row, coloff + clear_dirty_start, coloff + clear_dirty_start,
+ coloff + clear_end, bg_attr, wrap);
+ }
clear_end = end_dirty;
+ } else {
+ if (start_dirty == -1) { // clear only
+ start_dirty = clear_dirty_start;
+ end_dirty = clear_dirty_start;
+ } else if (clear_end < end_dirty) { // put only
+ clear_end = end_dirty;
+ } else {
+ end_dirty = endcol;
+ }
}
- if (start_dirty == -1) {
- start_dirty = end_dirty;
- }
+
if (clear_end > start_dirty) {
if (!grid->throttled) {
- int start_pos = coloff + start_dirty;
- // When drawing over the right half of a double-wide char clear out the
- // left half. Only needed in a terminal.
- if (invalid_row && start_pos == 0) {
- start_pos = -1;
- }
- ui_line(grid, row, start_pos, coloff + end_dirty, coloff + clear_end,
+ ui_line(grid, row, invalid_row, coloff + start_dirty, coloff + end_dirty, coloff + clear_end,
bg_attr, wrap);
} else if (grid->dirty_col) {
// TODO(bfredl): really get rid of the extra pseudo terminal in message.c
@@ -879,15 +866,20 @@ void grid_free(ScreenGrid *grid)
grid->line_offset = NULL;
}
+#ifdef EXITFREE
/// Doesn't allow reinit, so must only be called by free_all_mem!
void grid_free_all_mem(void)
{
grid_free(&default_grid);
+ grid_free(&msg_grid);
+ XFREE_CLEAR(msg_grid.dirty_col);
xfree(linebuf_char);
xfree(linebuf_attr);
xfree(linebuf_vcol);
xfree(linebuf_scratch);
+ set_destroy(glyph, &glyph_cache);
}
+#endif
/// (Re)allocates a window grid if size changed while in ext_multigrid mode.
/// Updates size, offsets and handle for the grid regardless.
@@ -913,14 +905,14 @@ void win_grid_alloc(win_T *wp)
wp->w_lines = xcalloc((size_t)rows + 1, sizeof(wline_T));
}
- int was_resized = false;
+ bool was_resized = false;
if (want_allocation && (!has_allocation
|| grid_allocated->rows != total_rows
|| grid_allocated->cols != total_cols)) {
grid_alloc(grid_allocated, total_rows, total_cols,
wp->w_grid_alloc.valid, false);
grid_allocated->valid = true;
- if (wp->w_floating && wp->w_float_config.border) {
+ if (wp->w_floating && wp->w_config.border) {
wp->w_redr_border = true;
}
was_resized = true;
@@ -1082,3 +1074,15 @@ win_T *get_win_by_grid_handle(handle_T handle)
}
return NULL;
}
+
+/// Put a unicode character in a screen cell.
+schar_T schar_from_char(int c)
+{
+ schar_T sc = 0;
+ if (c >= 0x200000) {
+ // TODO(bfredl): this must NEVER happen, even if the file contained overlong sequences
+ c = 0xFFFD;
+ }
+ utf_char2bytes(c, (char *)&sc);
+ return sc;
+}
diff --git a/src/nvim/grid.h b/src/nvim/grid.h
index 9d8e395dae..7506f0fc9d 100644
--- a/src/nvim/grid.h
+++ b/src/nvim/grid.h
@@ -2,13 +2,11 @@
#include <stdbool.h>
#include <stddef.h> // IWYU pragma: keep
-#include <string.h>
-#include "nvim/buffer_defs.h"
-#include "nvim/grid_defs.h" // IWYU pragma: export
+#include "nvim/grid_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
-#include "nvim/mbyte.h"
#include "nvim/pos_defs.h"
+#include "nvim/types_defs.h"
/// By default, all windows are drawn on a single rectangular grid, represented by
/// this ScreenGrid instance. In multigrid mode each window will have its own
@@ -42,18 +40,6 @@ EXTERN char *linebuf_scratch INIT( = NULL);
# define schar_from_ascii(x) ((schar_T)(x))
#endif
-/// Put a unicode character in a screen cell.
-static inline schar_T schar_from_char(int c)
-{
- schar_T sc = 0;
- if (c >= 0x200000) {
- // TODO(bfredl): this must NEVER happen, even if the file contained overlong sequences
- c = 0xFFFD;
- }
- utf_char2bytes(c, (char *)&sc);
- return sc;
-}
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "grid.h.generated.h"
#endif
diff --git a/src/nvim/hashtab.c b/src/nvim/hashtab.c
index 475666be5e..a8a998a361 100644
--- a/src/nvim/hashtab.c
+++ b/src/nvim/hashtab.c
@@ -24,8 +24,7 @@
#include <string.h>
#include "nvim/ascii_defs.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/hashtab.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -122,7 +121,7 @@ hashitem_T *hash_lookup(const hashtab_T *const ht, const char *const key, const
{
#ifdef HT_DEBUG
hash_count_lookup++;
-#endif // ifdef HT_DEBUG
+#endif
// Quickly handle the most common situations:
// - return if there is no item at all
@@ -155,7 +154,7 @@ hashitem_T *hash_lookup(const hashtab_T *const ht, const char *const key, const
#ifdef HT_DEBUG
// count a "miss" for hashtab lookup
hash_count_perturb++;
-#endif // ifdef HT_DEBUG
+#endif
idx = 5 * idx + perturb + 1;
hi = &ht->ht_array[idx & ht->ht_mask];
@@ -190,7 +189,7 @@ void hash_debug_results(void)
(int64_t)hash_count_perturb);
fprintf(stderr, "Percentage of perturb loops: %" PRId64 "%%\r\n",
(int64_t)(hash_count_perturb * 100 / hash_count_lookup));
-#endif // ifdef HT_DEBUG
+#endif
}
/// Add (empty) item for key `key` to hashtable `ht`.
@@ -288,7 +287,7 @@ static void hash_may_resize(hashtab_T *ht, size_t minitems)
if (ht->ht_filled >= ht->ht_mask + 1) {
emsg("hash_may_resize(): table completely filled");
}
-#endif // ifdef HT_DEBUG
+#endif
size_t minsize;
const size_t oldsize = ht->ht_mask + 1;
diff --git a/src/nvim/hashtab.h b/src/nvim/hashtab.h
index d14eb6944e..06c73ce6c0 100644
--- a/src/nvim/hashtab.h
+++ b/src/nvim/hashtab.h
@@ -2,7 +2,7 @@
#include <stddef.h>
-#include "nvim/hashtab_defs.h" // IWYU pragma: export
+#include "nvim/hashtab_defs.h" // IWYU pragma: keep
/// Magic number used for hashitem "hi_key" value indicating a deleted item
///
diff --git a/src/nvim/hashtab_defs.h b/src/nvim/hashtab_defs.h
index 089838fcae..b0c275fcf0 100644
--- a/src/nvim/hashtab_defs.h
+++ b/src/nvim/hashtab_defs.h
@@ -21,7 +21,7 @@ typedef size_t hash_T;
/// value, so that you can get a pointer to the value subtracting an offset from
/// the pointer to the key.
/// This reduces the size of this item by 1/3.
-typedef struct hashitem_S {
+typedef struct {
/// Cached hash number for hi_key.
hash_T hi_hash;
@@ -34,11 +34,13 @@ typedef struct hashitem_S {
char *hi_key;
} hashitem_T;
-/// Initial size for a hashtable.
-/// Our items are relatively small and growing is expensive, thus start with 16.
-/// Must be a power of 2.
-/// This allows for storing 10 items (2/3 of 16) before a resize is needed.
-enum { HT_INIT_SIZE = 16, };
+enum {
+ /// Initial size for a hashtable.
+ /// Our items are relatively small and growing is expensive, thus start with 16.
+ /// Must be a power of 2.
+ /// This allows for storing 10 items (2/3 of 16) before a resize is needed.
+ HT_INIT_SIZE = 16,
+};
/// An array-based hashtable.
///
@@ -46,7 +48,7 @@ enum { HT_INIT_SIZE = 16, };
/// Values are of any type.
///
/// The hashtable grows to accommodate more entries when needed.
-typedef struct hashtable_S {
+typedef struct {
hash_T ht_mask; ///< mask used for hash value
///< (nr of items in array is "ht_mask" + 1)
size_t ht_used; ///< number of items used
diff --git a/src/nvim/help.c b/src/nvim/help.c
index c23dc7fd9d..779772cedf 100644
--- a/src/nvim/help.c
+++ b/src/nvim/help.c
@@ -8,36 +8,40 @@
#include "nvim/ascii_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/change.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
+#include "nvim/cmdexpand_defs.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/extmark_defs.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/help.h"
#include "nvim/macros_defs.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/fs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/runtime.h"
#include "nvim/strings.h"
-#include "nvim/syntax.h"
#include "nvim/tag.h"
#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
@@ -173,9 +177,9 @@ void ex_help(exarg_T *eap)
// set b_p_ro flag).
// Set the alternate file to the previously edited file.
alt_fnum = curbuf->b_fnum;
- (void)do_ecmd(0, NULL, NULL, NULL, ECMD_LASTL,
- ECMD_HIDE + ECMD_SET_HELP,
- NULL); // buffer is still open, don't store info
+ do_ecmd(0, NULL, NULL, NULL, ECMD_LASTL,
+ ECMD_HIDE + ECMD_SET_HELP,
+ NULL); // buffer is still open, don't store info
if ((cmdmod.cmod_flags & CMOD_KEEPALT) == 0) {
curwin->w_alt_fnum = alt_fnum;
@@ -253,7 +257,7 @@ char *check_help_lang(char *arg)
/// @param wrong_case no matching case
///
/// @return a heuristic indicating how well the given string matches.
-int help_heuristic(char *matched_string, int offset, int wrong_case)
+int help_heuristic(char *matched_string, int offset, bool wrong_case)
FUNC_ATTR_PURE
{
int num_letters = 0;
@@ -609,7 +613,7 @@ void cleanup_help_tags(int num_file, char **file)
void prepare_help_buffer(void)
{
curbuf->b_help = true;
- set_string_option_direct("buftype", -1, "help", OPT_FREE|OPT_LOCAL, 0);
+ set_string_option_direct(kOptBuftype, "help", OPT_LOCAL, 0);
// Always set these options after jumping to a help tag, because the
// user may have an autocommand that gets in the way.
@@ -618,13 +622,13 @@ void prepare_help_buffer(void)
// Only set it when needed, buf_init_chartab() is some work.
char *p = "!-~,^*,^|,^\",192-255";
if (strcmp(curbuf->b_p_isk, p) != 0) {
- set_string_option_direct("isk", -1, p, OPT_FREE|OPT_LOCAL, 0);
+ set_string_option_direct(kOptIskeyword, p, OPT_LOCAL, 0);
check_buf_options(curbuf);
- (void)buf_init_chartab(curbuf, false);
+ buf_init_chartab(curbuf, false);
}
// Don't use the global foldmethod.
- set_string_option_direct("fdm", -1, "manual", OPT_FREE|OPT_LOCAL, 0);
+ set_string_option_direct(kOptFoldmethod, "manual", OPT_LOCAL, 0);
curbuf->b_p_ts = 8; // 'tabstop' is 8.
curwin->w_p_list = false; // No list mode.
@@ -643,46 +647,9 @@ void prepare_help_buffer(void)
set_buflisted(false);
}
-/// After reading a help file: May cleanup a help buffer when syntax
-/// highlighting is not used.
-void fix_help_buffer(void)
+/// After reading a help file: if help.txt, populate *local-additions*
+void get_local_additions(void)
{
- // Set filetype to "help".
- if (strcmp(curbuf->b_p_ft, "help") != 0) {
- curbuf->b_ro_locked++;
- set_option_value_give_err("ft", STATIC_CSTR_AS_OPTVAL("help"), OPT_LOCAL);
- curbuf->b_ro_locked--;
- }
-
- if (!syntax_present(curwin)) {
- bool in_example = false;
- for (linenr_T lnum = 1; lnum <= curbuf->b_ml.ml_line_count; lnum++) {
- char *line = ml_get_buf(curbuf, lnum);
- const size_t len = strlen(line);
- if (in_example && len > 0 && !ascii_iswhite(line[0])) {
- // End of example: non-white or '<' in first column.
- if (line[0] == '<') {
- // blank-out a '<' in the first column
- line = ml_get_buf_mut(curbuf, lnum);
- line[0] = ' ';
- }
- in_example = false;
- }
- if (!in_example && len > 0) {
- if (line[len - 1] == '>' && (len == 1 || line[len - 2] == ' ')) {
- // blank-out a '>' in the last column (start of example)
- line = ml_get_buf_mut(curbuf, lnum);
- line[len - 1] = ' ';
- in_example = true;
- } else if (line[len - 1] == '~') {
- // blank-out a '~' at the end of line (header marker)
- line = ml_get_buf_mut(curbuf, lnum);
- line[len - 1] = ' ';
- }
- }
- }
- }
-
// In the "help.txt" and "help.abx" file, add the locally added help
// files. This uses the very first line in the help file.
char *const fname = path_tail(curbuf->b_fname);
@@ -734,6 +701,9 @@ void fix_help_buffer(void)
const char *const f1 = fnames[i1];
const char *const t1 = path_tail(f1);
const char *const e1 = strrchr(t1, '.');
+ if (e1 == NULL) {
+ continue;
+ }
if (path_fnamecmp(e1, ".txt") != 0
&& path_fnamecmp(e1, fname + 4) != 0) {
// Not .txt and not .abx, remove it.
@@ -748,7 +718,7 @@ void fix_help_buffer(void)
}
const char *const t2 = path_tail(f2);
const char *const e2 = strrchr(t2, '.');
- if (e1 == NULL || e2 == NULL) {
+ if (e2 == NULL) {
continue;
}
if (e1 - f1 != e2 - f2
@@ -833,7 +803,7 @@ void fix_help_buffer(void)
linenr_T appended = lnum - lnum_start;
if (appended) {
mark_adjust(lnum_start + 1, (linenr_T)MAXLNUM, appended, 0, kExtmarkUndo);
- buf_redraw_changed_lines_later(curbuf, lnum_start + 1, lnum_start + 1, appended);
+ changed_lines_redraw_buf(curbuf, lnum_start + 1, lnum_start + 1, appended);
}
break;
}
diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c
index 141761c52e..8729c74ce8 100644
--- a/src/nvim/highlight.c
+++ b/src/nvim/highlight.c
@@ -11,9 +11,10 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
#include "nvim/api/ui.h"
+#include "nvim/decoration_defs.h"
#include "nvim/decoration_provider.h"
#include "nvim/drawscreen.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/highlight_defs.h"
@@ -22,6 +23,7 @@
#include "nvim/macros_defs.h"
#include "nvim/map_defs.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/popupmenu.h"
@@ -40,6 +42,7 @@ static Set(HlEntry) attr_entries = SET_INIT;
static Map(int, int) combine_attr_entries = MAP_INIT;
static Map(int, int) blend_attr_entries = MAP_INIT;
static Map(int, int) blendthrough_attr_entries = MAP_INIT;
+static Set(cstr_t) urls = SET_INIT;
#define attr_entry(i) attr_entries.keys[i]
@@ -113,26 +116,28 @@ retry: {}
// new attr id, send event to remote ui:s
int id = (int)k;
- Array inspect = hl_inspect(id);
+ Arena arena = ARENA_EMPTY;
+ Array inspect = hl_inspect(id, &arena);
// Note: internally we don't distinguish between cterm and rgb attributes,
// remote_ui_hl_attr_define will however.
ui_call_hl_attr_define(id, entry.attr, entry.attr, inspect);
- api_free_array(inspect);
+ arena_mem_free(arena_finish(&arena));
return id;
}
/// When a UI connects, we need to send it the table of highlights used so far.
-void ui_send_all_hls(UI *ui)
+void ui_send_all_hls(RemoteUI *ui)
{
for (size_t i = 1; i < set_size(&attr_entries); i++) {
- Array inspect = hl_inspect((int)i);
+ Arena arena = ARENA_EMPTY;
+ Array inspect = hl_inspect((int)i, &arena);
HlAttrs attr = attr_entry(i).attr;
remote_ui_hl_attr_define(ui, (Integer)i, attr, attr, inspect);
- api_free_array(inspect);
+ arena_mem_free(arena_finish(&arena));
}
for (size_t hlf = 0; hlf < HLF_COUNT; hlf++) {
- remote_ui_hl_group_set(ui, cstr_as_string((char *)hlf_names[hlf]),
+ remote_ui_hl_group_set(ui, cstr_as_string(hlf_names[hlf]),
highlight_attr[hlf]);
}
}
@@ -201,13 +206,13 @@ 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, CSTR_TO_OBJ(syn_id2name(hl_id)));
+ ADD_C(args, CSTR_AS_OBJ(syn_id2name(hl_id)));
ADD_C(args, BOOLEAN_OBJ(link));
// TODO(bfredl): preload the "global" attr dict?
Error err = ERROR_INIT;
recursive++;
- Object ret = nlua_call_ref(p->hl_def, "hl_def", args, true, &err);
+ Object ret = nlua_call_ref(p->hl_def, "hl_def", args, kRetObject, NULL, &err);
recursive--;
// TODO(bfredl): or "inherit", combine with global value?
@@ -216,7 +221,7 @@ int ns_get_hl(NS *ns_hl, int hl_id, bool link, bool nodefault)
HlAttrs attrs = HLATTRS_INIT;
if (ret.type == kObjectTypeDictionary) {
fallback = false;
- Dict(highlight) dict = { 0 };
+ Dict(highlight) dict = KEYDICT_INIT;
if (api_dict_to_keydict(&dict, KeyDict_highlight_get_field,
ret.data.dictionary, &err)) {
attrs = dict2hlattrs(&dict, true, &it.link_id, &err);
@@ -364,7 +369,7 @@ void update_window_hl(win_T *wp, bool invalid)
// wp->w_hl_attr_normal group. HL_ATTR(HLF_NFLOAT) is always named.
// determine window specific background set in 'winhighlight'
- bool float_win = wp->w_floating && !wp->w_float_config.external;
+ bool float_win = wp->w_floating && !wp->w_config.external;
if (float_win && hl_def[HLF_NFLOAT] != 0) {
wp->w_hl_attr_normal = hl_def[HLF_NFLOAT];
} else if (hl_def[HLF_COUNT] > 0) {
@@ -377,19 +382,19 @@ void update_window_hl(win_T *wp, bool invalid)
wp->w_hl_attr_normal = hl_apply_winblend(wp, wp->w_hl_attr_normal);
}
- wp->w_float_config.shadow = false;
- if (wp->w_floating && wp->w_float_config.border) {
+ wp->w_config.shadow = false;
+ if (wp->w_floating && wp->w_config.border) {
for (int i = 0; i < 8; i++) {
int attr = hl_def[HLF_BORDER];
- if (wp->w_float_config.border_hl_ids[i]) {
+ if (wp->w_config.border_hl_ids[i]) {
attr = hl_get_ui_attr(ns_id, HLF_BORDER,
- wp->w_float_config.border_hl_ids[i], false);
+ wp->w_config.border_hl_ids[i], false);
}
attr = hl_apply_winblend(wp, attr);
if (syn_attr2entry(attr).hl_blend > 0) {
- wp->w_float_config.shadow = true;
+ wp->w_config.shadow = true;
}
- wp->w_float_config.border_attr[i] = attr;
+ wp->w_config.border_attr[i] = attr;
}
}
@@ -473,6 +478,7 @@ int hl_get_underline(void)
.rgb_bg_color = -1,
.rgb_sp_color = -1,
.hl_blend = -1,
+ .url = -1,
},
.kind = kHlUI,
.id1 = 0,
@@ -480,6 +486,43 @@ int hl_get_underline(void)
});
}
+/// Augment an existing attribute with a URL.
+///
+/// @param attr Existing attribute to combine with
+/// @param url The URL to associate with the highlight attribute
+/// @return Combined attribute
+int hl_add_url(int attr, const char *url)
+{
+ HlAttrs attrs = HLATTRS_INIT;
+
+ MHPutStatus status;
+ uint32_t k = set_put_idx(cstr_t, &urls, url, &status);
+ if (status != kMHExisting) {
+ urls.keys[k] = xstrdup(url);
+ }
+
+ attrs.url = (int32_t)k;
+
+ int new = get_attr_entry((HlEntry){
+ .attr = attrs,
+ .kind = kHlUI,
+ .id1 = 0,
+ .id2 = 0,
+ });
+
+ return hl_combine_attr(attr, new);
+}
+
+/// Get a URL by its index.
+///
+/// @param index URL index
+/// @return URL
+const char *hl_get_url(uint32_t index)
+{
+ assert(urls.keys);
+ return urls.keys[index];
+}
+
/// Get attribute code for forwarded :terminal highlights.
int hl_get_term_attr(HlAttrs *aep)
{
@@ -490,12 +533,18 @@ int hl_get_term_attr(HlAttrs *aep)
/// Clear all highlight tables.
void clear_hl_tables(bool reinit)
{
+ const char *url = NULL;
+ set_foreach(&urls, url, {
+ xfree((void *)url);
+ });
+
if (reinit) {
set_clear(HlEntry, &attr_entries);
highlight_init();
map_clear(int, &combine_attr_entries);
map_clear(int, &blend_attr_entries);
map_clear(int, &blendthrough_attr_entries);
+ set_clear(cstr_t, &urls);
memset(highlight_attr_last, -1, sizeof(highlight_attr_last));
highlight_attr_set_all();
highlight_changed();
@@ -506,6 +555,7 @@ void clear_hl_tables(bool reinit)
map_destroy(int, &blend_attr_entries);
map_destroy(int, &blendthrough_attr_entries);
map_destroy(ColorKey, &ns_hls);
+ set_destroy(cstr_t, &urls);
}
}
@@ -597,6 +647,10 @@ int hl_combine_attr(int char_attr, int prim_attr)
new_en.hl_blend = prim_aep.hl_blend;
}
+ if ((new_en.url == -1) && (prim_aep.url >= 0)) {
+ new_en.url = prim_aep.url;
+ }
+
id = get_attr_entry((HlEntry){ .attr = new_en, .kind = kHlCombine,
.id1 = char_attr, .id2 = prim_attr });
if (id > 0) {
@@ -678,8 +732,8 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through)
}
cattrs.cterm_bg_color = fattrs.cterm_bg_color;
- cattrs.cterm_fg_color = cterm_blend(ratio, battrs.cterm_fg_color,
- fattrs.cterm_bg_color);
+ cattrs.cterm_fg_color = (int16_t)cterm_blend(ratio, battrs.cterm_fg_color,
+ fattrs.cterm_bg_color);
cattrs.rgb_ae_attr &= ~(HL_FG_INDEXED | HL_BG_INDEXED);
} else {
cattrs = fattrs;
@@ -713,7 +767,8 @@ int hl_blend_attrs(int back_attr, int front_attr, bool *through)
static int rgb_blend(int ratio, int rgb1, int rgb2)
{
- int a = ratio, b = 100 - ratio;
+ int a = ratio;
+ int b = 100 - ratio;
int r1 = (rgb1 & 0xFF0000) >> 16;
int g1 = (rgb1 & 0x00FF00) >> 8;
int b1 = (rgb1 & 0x0000FF) >> 0;
@@ -726,7 +781,7 @@ static int rgb_blend(int ratio, int rgb1, int rgb2)
return (mr << 16) + (mg << 8) + mb;
}
-static int cterm_blend(int ratio, int c1, int c2)
+static int cterm_blend(int ratio, int16_t c1, int16_t c2)
{
// 1. Convert cterm color numbers to RGB.
// 2. Blend the RGB colors.
@@ -940,7 +995,11 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
{
#define HAS_KEY_X(d, key) HAS_KEY(d, highlight, key)
HlAttrs hlattrs = HLATTRS_INIT;
- int32_t fg = -1, bg = -1, ctermfg = -1, ctermbg = -1, sp = -1;
+ int32_t fg = -1;
+ int32_t bg = -1;
+ int32_t ctermfg = -1;
+ int32_t ctermbg = -1;
+ int32_t sp = -1;
int blend = -1;
int16_t mask = 0;
int16_t cterm_mask = 0;
@@ -1027,7 +1086,7 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
// Handle cterm attrs
if (dict->cterm.type == kObjectTypeDictionary) {
- Dict(highlight_cterm) cterm[1] = { 0 };
+ Dict(highlight_cterm) cterm[1] = KEYDICT_INIT;
if (!api_dict_to_keydict(cterm, KeyDict_highlight_cterm_get_field,
dict->cterm.data.dictionary, err)) {
return hlattrs;
@@ -1078,12 +1137,12 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e
hlattrs.rgb_fg_color = fg;
hlattrs.rgb_sp_color = sp;
hlattrs.hl_blend = blend;
- hlattrs.cterm_bg_color = ctermbg == -1 ? 0 : ctermbg + 1;
- hlattrs.cterm_fg_color = ctermfg == -1 ? 0 : ctermfg + 1;
+ hlattrs.cterm_bg_color = ctermbg == -1 ? 0 : (int16_t)(ctermbg + 1);
+ hlattrs.cterm_fg_color = ctermfg == -1 ? 0 : (int16_t)(ctermfg + 1);
hlattrs.cterm_ae_attr = cterm_mask;
} else {
- hlattrs.cterm_bg_color = bg == -1 ? 0 : bg + 1;
- hlattrs.cterm_fg_color = fg == -1 ? 0 : fg + 1;
+ hlattrs.cterm_bg_color = bg == -1 ? 0 : (int16_t)(bg + 1);
+ hlattrs.cterm_fg_color = fg == -1 ? 0 : (int16_t)(fg + 1);
hlattrs.cterm_ae_attr = mask;
}
@@ -1119,17 +1178,30 @@ int object_to_color(Object val, char *key, bool rgb, Error *err)
}
}
-Array hl_inspect(int attr)
+Array hl_inspect(int attr, Arena *arena)
{
- // TODO(bfredl): use arena allocation
- Array ret = ARRAY_DICT_INIT;
- if (hlstate_active) {
- hl_inspect_impl(&ret, attr);
+ if (!hlstate_active) {
+ return (Array)ARRAY_DICT_INIT;
}
+ Array ret = arena_array(arena, hl_inspect_size(attr));
+ hl_inspect_impl(&ret, attr, arena);
return ret;
}
-static void hl_inspect_impl(Array *arr, int attr)
+static size_t hl_inspect_size(int attr)
+{
+ if (attr <= 0 || attr >= (int)set_size(&attr_entries)) {
+ return 0;
+ }
+
+ HlEntry e = attr_entry(attr);
+ if (e.kind == kHlCombine || e.kind == kHlBlend || e.kind == kHlBlendThrough) {
+ return hl_inspect_size(e.id1) + hl_inspect_size(e.id2);
+ }
+ return 1;
+}
+
+static void hl_inspect_impl(Array *arr, int attr, Arena *arena)
{
Dictionary item = ARRAY_DICT_INIT;
if (attr <= 0 || attr >= (int)set_size(&attr_entries)) {
@@ -1139,35 +1211,36 @@ static void hl_inspect_impl(Array *arr, int attr)
HlEntry e = attr_entry(attr);
switch (e.kind) {
case kHlSyntax:
- PUT(item, "kind", CSTR_TO_OBJ("syntax"));
- PUT(item, "hi_name",
- CSTR_TO_OBJ(syn_id2name(e.id1)));
+ item = arena_dict(arena, 3);
+ PUT_C(item, "kind", CSTR_AS_OBJ("syntax"));
+ PUT_C(item, "hi_name", CSTR_AS_OBJ(syn_id2name(e.id1)));
break;
case kHlUI:
- PUT(item, "kind", CSTR_TO_OBJ("ui"));
+ item = arena_dict(arena, 4);
+ PUT_C(item, "kind", CSTR_AS_OBJ("ui"));
const char *ui_name = (e.id1 == -1) ? "Normal" : hlf_names[e.id1];
- PUT(item, "ui_name", CSTR_TO_OBJ(ui_name));
- PUT(item, "hi_name",
- CSTR_TO_OBJ(syn_id2name(e.id2)));
+ PUT_C(item, "ui_name", CSTR_AS_OBJ(ui_name));
+ PUT_C(item, "hi_name", CSTR_AS_OBJ(syn_id2name(e.id2)));
break;
case kHlTerminal:
- PUT(item, "kind", CSTR_TO_OBJ("term"));
+ item = arena_dict(arena, 2);
+ PUT_C(item, "kind", CSTR_AS_OBJ("term"));
break;
case kHlCombine:
case kHlBlend:
case kHlBlendThrough:
// attribute combination is associative, so flatten to an array
- hl_inspect_impl(arr, e.id1);
- hl_inspect_impl(arr, e.id2);
+ hl_inspect_impl(arr, e.id1, arena);
+ hl_inspect_impl(arr, e.id2, arena);
return;
case kHlUnknown:
case kHlInvalid:
return;
}
- PUT(item, "id", INTEGER_OBJ(attr));
- ADD(*arr, DICTIONARY_OBJ(item));
+ PUT_C(item, "id", INTEGER_OBJ(attr));
+ ADD_C(*arr, DICTIONARY_OBJ(item));
}
diff --git a/src/nvim/highlight.h b/src/nvim/highlight.h
index e5d3f3d1ca..cb3a84bcaf 100644
--- a/src/nvim/highlight.h
+++ b/src/nvim/highlight.h
@@ -2,12 +2,103 @@
#include <stdbool.h>
-#include "nvim/api/keysets_defs.h"
+#include "nvim/api/keysets_defs.h" // IWYU pragma: keep
#include "nvim/api/private/defs.h" // IWYU pragma: keep
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
-#include "nvim/highlight_defs.h" // IWYU pragma: export
+#include "nvim/buffer_defs.h"
+#include "nvim/highlight_defs.h" // IWYU pragma: keep
+#include "nvim/macros_defs.h"
#include "nvim/option_vars.h"
-#include "nvim/ui.h"
+#include "nvim/types_defs.h"
+#include "nvim/ui_defs.h" // IWYU pragma: keep
+
+EXTERN const char *hlf_names[] INIT( = {
+ [HLF_8] = "SpecialKey",
+ [HLF_EOB] = "EndOfBuffer",
+ [HLF_TERM] = "TermCursor",
+ [HLF_TERMNC] = "TermCursorNC",
+ [HLF_AT] = "NonText",
+ [HLF_D] = "Directory",
+ [HLF_E] = "ErrorMsg",
+ [HLF_I] = "IncSearch",
+ [HLF_L] = "Search",
+ [HLF_LC] = "CurSearch",
+ [HLF_M] = "MoreMsg",
+ [HLF_CM] = "ModeMsg",
+ [HLF_N] = "LineNr",
+ [HLF_LNA] = "LineNrAbove",
+ [HLF_LNB] = "LineNrBelow",
+ [HLF_CLN] = "CursorLineNr",
+ [HLF_CLS] = "CursorLineSign",
+ [HLF_CLF] = "CursorLineFold",
+ [HLF_R] = "Question",
+ [HLF_S] = "StatusLine",
+ [HLF_SNC] = "StatusLineNC",
+ [HLF_C] = "WinSeparator",
+ [HLF_T] = "Title",
+ [HLF_V] = "Visual",
+ [HLF_VNC] = "VisualNC",
+ [HLF_VSP] = "VertSplit",
+ [HLF_W] = "WarningMsg",
+ [HLF_WM] = "WildMenu",
+ [HLF_FL] = "Folded",
+ [HLF_FC] = "FoldColumn",
+ [HLF_ADD] = "DiffAdd",
+ [HLF_CHD] = "DiffChange",
+ [HLF_DED] = "DiffDelete",
+ [HLF_TXD] = "DiffText",
+ [HLF_SC] = "SignColumn",
+ [HLF_CONCEAL] = "Conceal",
+ [HLF_SPB] = "SpellBad",
+ [HLF_SPC] = "SpellCap",
+ [HLF_SPR] = "SpellRare",
+ [HLF_SPL] = "SpellLocal",
+ [HLF_PNI] = "Pmenu",
+ [HLF_PSI] = "PmenuSel",
+ [HLF_PNK] = "PmenuKind",
+ [HLF_PSK] = "PmenuKindSel",
+ [HLF_PNX] = "PmenuExtra",
+ [HLF_PSX] = "PmenuExtraSel",
+ [HLF_PSB] = "PmenuSbar",
+ [HLF_PST] = "PmenuThumb",
+ [HLF_TP] = "TabLine",
+ [HLF_TPS] = "TabLineSel",
+ [HLF_TPF] = "TabLineFill",
+ [HLF_CUC] = "CursorColumn",
+ [HLF_CUL] = "CursorLine",
+ [HLF_MC] = "ColorColumn",
+ [HLF_QFL] = "QuickFixLine",
+ [HLF_0] = "Whitespace",
+ [HLF_INACTIVE] = "NormalNC",
+ [HLF_MSGSEP] = "MsgSeparator",
+ [HLF_NFLOAT] = "NormalFloat",
+ [HLF_MSG] = "MsgArea",
+ [HLF_BORDER] = "FloatBorder",
+ [HLF_WBR] = "WinBar",
+ [HLF_WBRNC] = "WinBarNC",
+ [HLF_CU] = "Cursor",
+ [HLF_BTITLE] = "FloatTitle",
+ [HLF_BFOOTER] = "FloatFooter",
+});
+
+EXTERN int highlight_attr[HLF_COUNT + 1]; // Highl. attr for each context.
+EXTERN int highlight_attr_last[HLF_COUNT]; // copy for detecting changed groups
+EXTERN int highlight_user[9]; // User[1-9] attributes
+EXTERN int highlight_stlnc[9]; // On top of user
+EXTERN int cterm_normal_fg_color INIT( = 0);
+EXTERN int cterm_normal_bg_color INIT( = 0);
+EXTERN RgbValue normal_fg INIT( = -1);
+EXTERN RgbValue normal_bg INIT( = -1);
+EXTERN RgbValue normal_sp INIT( = -1);
+
+EXTERN NS ns_hl_global INIT( = 0); // global highlight namespace
+EXTERN NS ns_hl_win INIT( = -1); // highlight namespace for the current window
+EXTERN NS ns_hl_fast INIT( = -1); // highlight namespace specified in a fast callback
+EXTERN NS ns_hl_active INIT( = 0); // currently active/cached namespace
+
+EXTERN int *hl_attr_active INIT( = highlight_attr);
+
+// Enums need a typecast to be used as array index.
+#define HL_ATTR(n) hl_attr_active[(int)(n)]
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "highlight.h.generated.h"
@@ -20,8 +111,6 @@ static inline int win_hl_attr(win_T *wp, int hlf)
return ((wp->w_ns_hl_attr && ns_hl_fast < 0) ? wp->w_ns_hl_attr : hl_attr_active)[hlf];
}
-#define HLATTRS_DICT_SIZE 16
-
#define HL_SET_DEFAULT_COLORS(rgb_fg, rgb_bg, rgb_sp) \
do { \
bool dark_ = (*p_bg == 'd'); \
@@ -29,6 +118,3 @@ static inline int win_hl_attr(win_T *wp, int hlf)
rgb_bg = rgb_bg != -1 ? rgb_bg : (dark_ ? 0x000000 : 0xFFFFFF); \
rgb_sp = rgb_sp != -1 ? rgb_sp : 0xFF0000; \
} while (0);
-
-// Enums need a typecast to be used as array index.
-#define HL_ATTR(n) hl_attr_active[(int)(n)]
diff --git a/src/nvim/highlight_defs.h b/src/nvim/highlight_defs.h
index 24070199ee..25ab9dc2d9 100644
--- a/src/nvim/highlight_defs.h
+++ b/src/nvim/highlight_defs.h
@@ -1,9 +1,9 @@
#pragma once
-#include <inttypes.h>
+#include <stdbool.h>
+#include <stdint.h>
-#include "nvim/macros_defs.h"
-#include "nvim/types_defs.h"
+#include "nvim/api/private/defs.h"
typedef int32_t RgbValue;
@@ -35,11 +35,12 @@ typedef enum {
/// Stores a complete highlighting entry, including colors and attributes
/// for both TUI and GUI.
-typedef struct attr_entry {
+typedef struct {
int16_t rgb_ae_attr, cterm_ae_attr; ///< HlAttrFlags
RgbValue rgb_fg_color, rgb_bg_color, rgb_sp_color;
- int cterm_fg_color, cterm_bg_color;
- int hl_blend;
+ int16_t cterm_fg_color, cterm_bg_color;
+ int32_t hl_blend;
+ int32_t url;
} HlAttrs;
#define HLATTRS_INIT (HlAttrs) { \
@@ -51,167 +52,82 @@ typedef struct attr_entry {
.cterm_fg_color = 0, \
.cterm_bg_color = 0, \
.hl_blend = -1, \
+ .url = -1, \
}
/// Values for index in highlight_attr[].
-/// When making changes, also update hlf_names below!
+/// When making changes, also update hlf_names in highlight.h!
typedef enum {
- HLF_8 = 0, // Meta & special keys listed with ":map", text that is
- // displayed different from what it is
- HLF_EOB, // after the last line in the buffer
- HLF_TERM, // terminal cursor focused
- HLF_TERMNC, // terminal cursor unfocused
- HLF_AT, // @ characters at end of screen, characters that don't really exist in the text
- HLF_D, // directories in CTRL-D listing
- HLF_E, // error messages
- HLF_I, // incremental search
- HLF_L, // last search string
- HLF_LC, // current search match
- HLF_M, // "--More--" message
- HLF_CM, // Mode (e.g., "-- INSERT --")
- HLF_N, // line number for ":number" and ":#" commands
- HLF_LNA, // LineNrAbove
- HLF_LNB, // LineNrBelow
- HLF_CLN, // current line number when 'cursorline' is set
- HLF_CLS, // current line sign column
- HLF_CLF, // current line fold
- HLF_R, // return to continue message and yes/no questions
- HLF_S, // status lines
- HLF_SNC, // status lines of not-current windows
- HLF_C, // window split separators
- HLF_VSP, // VertSplit
- HLF_T, // Titles for output from ":set all", ":autocmd" etc.
- HLF_V, // Visual mode
- HLF_VNC, // Visual mode, autoselecting and not clipboard owner
- HLF_W, // warning messages
- HLF_WM, // Wildmenu highlight
- HLF_FL, // Folded line
- HLF_FC, // Fold column
- HLF_ADD, // Added diff line
- HLF_CHD, // Changed diff line
- HLF_DED, // Deleted diff line
- HLF_TXD, // Text Changed in diff line
- HLF_SC, // Sign column
- HLF_CONCEAL, // Concealed text
- HLF_SPB, // SpellBad
- HLF_SPC, // SpellCap
- HLF_SPR, // SpellRare
- HLF_SPL, // SpellLocal
- HLF_PNI, // popup menu normal item
- HLF_PSI, // popup menu selected item
- HLF_PNK, // popup menu normal item "kind"
- HLF_PSK, // popup menu selected item "kind"
- HLF_PNX, // popup menu normal item "menu" (extra text)
- HLF_PSX, // popup menu selected item "menu" (extra text)
- HLF_PSB, // popup menu scrollbar
- HLF_PST, // popup menu scrollbar thumb
- HLF_TP, // tabpage line
- HLF_TPS, // tabpage line selected
- HLF_TPF, // tabpage line filler
- HLF_CUC, // 'cursorcolumn'
- HLF_CUL, // 'cursorline'
- HLF_MC, // 'colorcolumn'
- HLF_QFL, // selected quickfix line
- HLF_0, // Whitespace
- HLF_INACTIVE, // NormalNC: Normal text in non-current windows
- HLF_MSGSEP, // message separator line
- HLF_NFLOAT, // Floating window
- HLF_MSG, // Message area
- HLF_BORDER, // Floating window border
- HLF_WBR, // Window bars
- HLF_WBRNC, // Window bars of not-current windows
- HLF_CU, // Cursor
- HLF_BTITLE, // Float Border Title
- HLF_BFOOTER, // Float Border Footer
- HLF_COUNT, // MUST be the last one
+ HLF_8 = 0, ///< Meta & special keys listed with ":map", text that is
+ ///< displayed different from what it is
+ HLF_EOB, ///< after the last line in the buffer
+ HLF_TERM, ///< terminal cursor focused
+ HLF_TERMNC, ///< terminal cursor unfocused
+ HLF_AT, ///< @ characters at end of screen, characters that don't really exist in the text
+ HLF_D, ///< directories in CTRL-D listing
+ HLF_E, ///< error messages
+ HLF_I, ///< incremental search
+ HLF_L, ///< last search string
+ HLF_LC, ///< current search match
+ HLF_M, ///< "--More--" message
+ HLF_CM, ///< Mode (e.g., "-- INSERT --")
+ HLF_N, ///< line number for ":number" and ":#" commands
+ HLF_LNA, ///< LineNrAbove
+ HLF_LNB, ///< LineNrBelow
+ HLF_CLN, ///< current line number when 'cursorline' is set
+ HLF_CLS, ///< current line sign column
+ HLF_CLF, ///< current line fold
+ HLF_R, ///< return to continue message and yes/no questions
+ HLF_S, ///< status lines
+ HLF_SNC, ///< status lines of not-current windows
+ HLF_C, ///< window split separators
+ HLF_VSP, ///< VertSplit
+ HLF_T, ///< Titles for output from ":set all", ":autocmd" etc.
+ HLF_V, ///< Visual mode
+ HLF_VNC, ///< Visual mode, autoselecting and not clipboard owner
+ HLF_W, ///< warning messages
+ HLF_WM, ///< Wildmenu highlight
+ HLF_FL, ///< Folded line
+ HLF_FC, ///< Fold column
+ HLF_ADD, ///< Added diff line
+ HLF_CHD, ///< Changed diff line
+ HLF_DED, ///< Deleted diff line
+ HLF_TXD, ///< Text Changed in diff line
+ HLF_SC, ///< Sign column
+ HLF_CONCEAL, ///< Concealed text
+ HLF_SPB, ///< SpellBad
+ HLF_SPC, ///< SpellCap
+ HLF_SPR, ///< SpellRare
+ HLF_SPL, ///< SpellLocal
+ HLF_PNI, ///< popup menu normal item
+ HLF_PSI, ///< popup menu selected item
+ HLF_PNK, ///< popup menu normal item "kind"
+ HLF_PSK, ///< popup menu selected item "kind"
+ HLF_PNX, ///< popup menu normal item "menu" (extra text)
+ HLF_PSX, ///< popup menu selected item "menu" (extra text)
+ HLF_PSB, ///< popup menu scrollbar
+ HLF_PST, ///< popup menu scrollbar thumb
+ HLF_TP, ///< tabpage line
+ HLF_TPS, ///< tabpage line selected
+ HLF_TPF, ///< tabpage line filler
+ HLF_CUC, ///< 'cursorcolumn'
+ HLF_CUL, ///< 'cursorline'
+ HLF_MC, ///< 'colorcolumn'
+ HLF_QFL, ///< selected quickfix line
+ HLF_0, ///< Whitespace
+ HLF_INACTIVE, ///< NormalNC: Normal text in non-current windows
+ HLF_MSGSEP, ///< message separator line
+ HLF_NFLOAT, ///< Floating window
+ HLF_MSG, ///< Message area
+ HLF_BORDER, ///< Floating window border
+ HLF_WBR, ///< Window bars
+ HLF_WBRNC, ///< Window bars of not-current windows
+ HLF_CU, ///< Cursor
+ HLF_BTITLE, ///< Float Border Title
+ HLF_BFOOTER, ///< Float Border Footer
+ HLF_COUNT, ///< MUST be the last one
} hlf_T;
-EXTERN const char *hlf_names[] INIT( = {
- [HLF_8] = "SpecialKey",
- [HLF_EOB] = "EndOfBuffer",
- [HLF_TERM] = "TermCursor",
- [HLF_TERMNC] = "TermCursorNC",
- [HLF_AT] = "NonText",
- [HLF_D] = "Directory",
- [HLF_E] = "ErrorMsg",
- [HLF_I] = "IncSearch",
- [HLF_L] = "Search",
- [HLF_LC] = "CurSearch",
- [HLF_M] = "MoreMsg",
- [HLF_CM] = "ModeMsg",
- [HLF_N] = "LineNr",
- [HLF_LNA] = "LineNrAbove",
- [HLF_LNB] = "LineNrBelow",
- [HLF_CLN] = "CursorLineNr",
- [HLF_CLS] = "CursorLineSign",
- [HLF_CLF] = "CursorLineFold",
- [HLF_R] = "Question",
- [HLF_S] = "StatusLine",
- [HLF_SNC] = "StatusLineNC",
- [HLF_C] = "WinSeparator",
- [HLF_T] = "Title",
- [HLF_V] = "Visual",
- [HLF_VNC] = "VisualNC",
- [HLF_VSP] = "VertSplit",
- [HLF_W] = "WarningMsg",
- [HLF_WM] = "WildMenu",
- [HLF_FL] = "Folded",
- [HLF_FC] = "FoldColumn",
- [HLF_ADD] = "DiffAdd",
- [HLF_CHD] = "DiffChange",
- [HLF_DED] = "DiffDelete",
- [HLF_TXD] = "DiffText",
- [HLF_SC] = "SignColumn",
- [HLF_CONCEAL] = "Conceal",
- [HLF_SPB] = "SpellBad",
- [HLF_SPC] = "SpellCap",
- [HLF_SPR] = "SpellRare",
- [HLF_SPL] = "SpellLocal",
- [HLF_PNI] = "Pmenu",
- [HLF_PSI] = "PmenuSel",
- [HLF_PNK] = "PmenuKind",
- [HLF_PSK] = "PmenuKindSel",
- [HLF_PNX] = "PmenuExtra",
- [HLF_PSX] = "PmenuExtraSel",
- [HLF_PSB] = "PmenuSbar",
- [HLF_PST] = "PmenuThumb",
- [HLF_TP] = "TabLine",
- [HLF_TPS] = "TabLineSel",
- [HLF_TPF] = "TabLineFill",
- [HLF_CUC] = "CursorColumn",
- [HLF_CUL] = "CursorLine",
- [HLF_MC] = "ColorColumn",
- [HLF_QFL] = "QuickFixLine",
- [HLF_0] = "Whitespace",
- [HLF_INACTIVE] = "NormalNC",
- [HLF_MSGSEP] = "MsgSeparator",
- [HLF_NFLOAT] = "NormalFloat",
- [HLF_MSG] = "MsgArea",
- [HLF_BORDER] = "FloatBorder",
- [HLF_WBR] = "WinBar",
- [HLF_WBRNC] = "WinBarNC",
- [HLF_CU] = "Cursor",
- [HLF_BTITLE] = "FloatTitle",
- [HLF_BFOOTER] = "FloatFooter",
-});
-
-EXTERN int highlight_attr[HLF_COUNT + 1]; // Highl. attr for each context.
-EXTERN int highlight_attr_last[HLF_COUNT]; // copy for detecting changed groups
-EXTERN int highlight_user[9]; // User[1-9] attributes
-EXTERN int highlight_stlnc[9]; // On top of user
-EXTERN int cterm_normal_fg_color INIT( = 0);
-EXTERN int cterm_normal_bg_color INIT( = 0);
-EXTERN RgbValue normal_fg INIT( = -1);
-EXTERN RgbValue normal_bg INIT( = -1);
-EXTERN RgbValue normal_sp INIT( = -1);
-
-EXTERN NS ns_hl_global INIT( = 0); // global highlight namespace
-EXTERN NS ns_hl_win INIT( = -1); // highlight namespace for the current window
-EXTERN NS ns_hl_fast INIT( = -1); // highlight namespace specified in a fast callback
-EXTERN NS ns_hl_active INIT( = 0); // currently active/cached namespace
-
-EXTERN int *hl_attr_active INIT( = highlight_attr);
-
typedef enum {
kHlUnknown,
kHlUI,
@@ -246,3 +162,5 @@ typedef struct {
} ColorItem;
#define COLOR_ITEM_INITIALIZER { .attr_id = -1, .link_id = -1, .version = -1, \
.is_default = false, .link_global = false }
+
+enum { HLATTRS_DICT_SIZE = 16, };
diff --git a/src/nvim/highlight_group.c b/src/nvim/highlight_group.c
index 3f1758894e..75c23c5bc4 100644
--- a/src/nvim/highlight_group.c
+++ b/src/nvim/highlight_group.c
@@ -15,6 +15,8 @@
#include "nvim/api/private/validate.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand_defs.h"
#include "nvim/cursor_shape.h"
@@ -24,9 +26,9 @@
#include "nvim/eval/typval_defs.h"
#include "nvim/eval/vars.h"
#include "nvim/ex_docmd.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
@@ -34,14 +36,17 @@
#include "nvim/macros_defs.h"
#include "nvim/map_defs.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/os/time.h"
#include "nvim/runtime.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/vim_defs.h"
/// \addtogroup SG_SET
@@ -136,263 +141,337 @@ static const char e_missing_argument_str[]
// they still work when the runtime files can't be found.
static const char *highlight_init_both[] = {
- "Conceal ctermbg=DarkGrey ctermfg=LightGrey guibg=DarkGrey guifg=LightGrey",
- "Cursor guibg=fg guifg=bg",
- "lCursor guibg=fg guifg=bg",
- "DiffText cterm=bold ctermbg=Red gui=bold guibg=Red",
- "ErrorMsg ctermbg=DarkRed ctermfg=White guibg=Red guifg=White",
- "IncSearch cterm=reverse gui=reverse",
- "ModeMsg cterm=bold gui=bold",
- "NonText ctermfg=Blue gui=bold guifg=Blue",
- "Normal cterm=NONE gui=NONE",
- "PmenuSbar ctermbg=Grey guibg=Grey",
- "StatusLine cterm=reverse,bold gui=reverse,bold",
- "StatusLineNC cterm=reverse gui=reverse",
- "TabLineFill cterm=reverse gui=reverse",
- "TabLineSel cterm=bold gui=bold",
- "TermCursor cterm=reverse gui=reverse",
- "WinBar cterm=bold gui=bold",
- "WildMenu ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
- "default link VertSplit Normal",
- "default link WinSeparator VertSplit",
- "default link WinBarNC WinBar",
- "default link EndOfBuffer NonText",
- "default link LineNrAbove LineNr",
- "default link LineNrBelow LineNr",
- "default link QuickFixLine Search",
- "default link CursorLineSign SignColumn",
+ "Cursor guifg=bg guibg=fg",
+ "CursorLineNr gui=bold cterm=bold",
+ "RedrawDebugNormal gui=reverse cterm=reverse",
+ "TabLineSel gui=bold cterm=bold",
+ "TermCursor gui=reverse cterm=reverse",
+ "Underlined gui=underline cterm=underline",
+ "lCursor guifg=bg guibg=fg",
+
+ // UI
+ "default link CursorIM Cursor",
"default link CursorLineFold FoldColumn",
- "default link CurSearch Search",
- "default link PmenuKind Pmenu",
- "default link PmenuKindSel PmenuSel",
- "default link PmenuExtra Pmenu",
- "default link PmenuExtraSel PmenuSel",
- "default link Substitute Search",
- "default link Whitespace NonText",
- "default link MsgSeparator StatusLine",
- "default link NormalFloat Pmenu",
- "default link FloatBorder WinSeparator",
- "default link FloatTitle Title",
- "default link FloatFooter Title",
- "default FloatShadow blend=80 guibg=Black",
- "default FloatShadowThrough blend=100 guibg=Black",
- "RedrawDebugNormal cterm=reverse gui=reverse",
- "RedrawDebugClear ctermbg=Yellow guibg=Yellow",
- "RedrawDebugComposed ctermbg=Green guibg=Green",
- "RedrawDebugRecompose ctermbg=Red guibg=Red",
- "Error term=reverse cterm=NONE ctermfg=White ctermbg=Red gui=NONE guifg=White guibg=Red",
- "Todo term=standout cterm=NONE ctermfg=Black ctermbg=Yellow gui=NONE guifg=Blue guibg=Yellow",
- "default link String Constant",
- "default link Character Constant",
- "default link Number Constant",
- "default link Boolean Constant",
- "default link Float Number",
- "default link Function Identifier",
- "default link Conditional Statement",
- "default link Repeat Statement",
- "default link Label Statement",
- "default link Operator Statement",
- "default link Keyword Statement",
- "default link Exception Statement",
- "default link Include PreProc",
- "default link Define PreProc",
- "default link Macro PreProc",
- "default link PreCondit PreProc",
- "default link StorageClass Type",
- "default link Structure Type",
- "default link Typedef Type",
- "default link Tag Special",
- "default link SpecialChar Special",
- "default link Delimiter Special",
+ "default link CursorLineSign SignColumn",
+ "default link EndOfBuffer NonText",
+ "default link FloatBorder NormalFloat",
+ "default link FloatFooter FloatTitle",
+ "default link FloatTitle Title",
+ "default link FoldColumn SignColumn",
+ "default link IncSearch CurSearch",
+ "default link LineNrAbove LineNr",
+ "default link LineNrBelow LineNr",
+ "default link MsgSeparator StatusLine",
+ "default link MsgArea NONE",
+ "default link NormalNC NONE",
+ "default link PmenuExtra Pmenu",
+ "default link PmenuExtraSel PmenuSel",
+ "default link PmenuKind Pmenu",
+ "default link PmenuKindSel PmenuSel",
+ "default link PmenuSbar Pmenu",
+ "default link Substitute Search",
+ "default link TabLine StatusLineNC",
+ "default link TabLineFill TabLine",
+ "default link TermCursorNC NONE",
+ "default link VertSplit WinSeparator",
+ "default link VisualNOS Visual",
+ "default link Whitespace NonText",
+ "default link WildMenu PmenuSel",
+ "default link WinSeparator Normal",
+
+ // Syntax
+ "default link Character Constant",
+ "default link Number Constant",
+ "default link Boolean Constant",
+ "default link Float Number",
+ "default link Conditional Statement",
+ "default link Repeat Statement",
+ "default link Label Statement",
+ "default link Keyword Statement",
+ "default link Exception Statement",
+ "default link Include PreProc",
+ "default link Define PreProc",
+ "default link Macro PreProc",
+ "default link PreCondit PreProc",
+ "default link StorageClass Type",
+ "default link Structure Type",
+ "default link Typedef Type",
+ "default link Tag Special",
+ "default link SpecialChar Special",
"default link SpecialComment Special",
- "default link Debug Special",
- "default DiagnosticError ctermfg=1 guifg=Red",
- "default DiagnosticWarn ctermfg=3 guifg=Orange",
- "default DiagnosticInfo ctermfg=4 guifg=LightBlue",
- "default DiagnosticHint ctermfg=7 guifg=LightGrey",
- "default DiagnosticOk ctermfg=10 guifg=LightGreen",
- "default DiagnosticUnderlineError cterm=underline gui=underline guisp=Red",
- "default DiagnosticUnderlineWarn cterm=underline gui=underline guisp=Orange",
- "default DiagnosticUnderlineInfo cterm=underline gui=underline guisp=LightBlue",
- "default DiagnosticUnderlineHint cterm=underline gui=underline guisp=LightGrey",
- "default DiagnosticUnderlineOk cterm=underline gui=underline guisp=LightGreen",
- "default link DiagnosticVirtualTextError DiagnosticError",
- "default link DiagnosticVirtualTextWarn DiagnosticWarn",
- "default link DiagnosticVirtualTextInfo DiagnosticInfo",
- "default link DiagnosticVirtualTextHint DiagnosticHint",
- "default link DiagnosticVirtualTextOk DiagnosticOk",
- "default link DiagnosticFloatingError DiagnosticError",
- "default link DiagnosticFloatingWarn DiagnosticWarn",
- "default link DiagnosticFloatingInfo DiagnosticInfo",
- "default link DiagnosticFloatingHint DiagnosticHint",
- "default link DiagnosticFloatingOk DiagnosticOk",
- "default link DiagnosticSignError DiagnosticError",
- "default link DiagnosticSignWarn DiagnosticWarn",
- "default link DiagnosticSignInfo DiagnosticInfo",
- "default link DiagnosticSignHint DiagnosticHint",
- "default link DiagnosticSignOk DiagnosticOk",
- "default DiagnosticDeprecated cterm=strikethrough gui=strikethrough guisp=Red",
- "default link DiagnosticUnnecessary Comment",
- "default link LspInlayHint NonText",
+ "default link Debug Special",
+ "default link Ignore Normal",
+ "default link LspInlayHint NonText",
"default link SnippetTabstop Visual",
- // Text
- "default link @text.literal Comment",
- "default link @text.reference Identifier",
- "default link @text.title Title",
- "default link @text.uri Underlined",
- "default link @text.underline Underlined",
- "default link @text.todo Todo",
+ // Diagnostic
+ "default link DiagnosticFloatingError DiagnosticError",
+ "default link DiagnosticFloatingWarn DiagnosticWarn",
+ "default link DiagnosticFloatingInfo DiagnosticInfo",
+ "default link DiagnosticFloatingHint DiagnosticHint",
+ "default link DiagnosticFloatingOk DiagnosticOk",
+ "default link DiagnosticVirtualTextError DiagnosticError",
+ "default link DiagnosticVirtualTextWarn DiagnosticWarn",
+ "default link DiagnosticVirtualTextInfo DiagnosticInfo",
+ "default link DiagnosticVirtualTextHint DiagnosticHint",
+ "default link DiagnosticVirtualTextOk DiagnosticOk",
+ "default link DiagnosticSignError DiagnosticError",
+ "default link DiagnosticSignWarn DiagnosticWarn",
+ "default link DiagnosticSignInfo DiagnosticInfo",
+ "default link DiagnosticSignHint DiagnosticHint",
+ "default link DiagnosticSignOk DiagnosticOk",
+ "default link DiagnosticUnnecessary Comment",
+
+ // Treesitter standard groups
+ "default link @variable.builtin Special",
+
+ "default link @constant Constant",
+ "default link @constant.builtin Special",
- // Miscs
- "default link @comment Comment",
- "default link @punctuation Delimiter",
+ "default link @module Structure",
+ "default link @module.builtin Special",
+ "default link @label Label",
- // Constants
- "default link @constant Constant",
- "default link @constant.builtin Special",
- "default link @constant.macro Define",
- "default link @define Define",
- "default link @macro Macro",
- "default link @string String",
- "default link @string.escape SpecialChar",
- "default link @string.special SpecialChar",
- "default link @character Character",
+ "default link @string String",
+ "default link @string.regexp @string.special",
+ "default link @string.escape @string.special",
+ "default link @string.special SpecialChar",
+ "default link @string.special.url Underlined",
+
+ "default link @character Character",
"default link @character.special SpecialChar",
- "default link @number Number",
- "default link @boolean Boolean",
- "default link @float Float",
- // Functions
- "default link @function Function",
+ "default link @boolean Boolean",
+ "default link @number Number",
+ "default link @number.float Float",
+
+ "default link @type Type",
+ "default link @type.builtin Special",
+
+ "default link @attribute Macro",
+ "default link @property Identifier",
+
+ "default link @function Function",
"default link @function.builtin Special",
- "default link @function.macro Macro",
- "default link @parameter Identifier",
- "default link @method Function",
- "default link @field Identifier",
- "default link @property Identifier",
+
"default link @constructor Special",
+ "default link @operator Operator",
- // Keywords
- "default link @conditional Conditional",
- "default link @repeat Repeat",
- "default link @label Label",
- "default link @operator Operator",
"default link @keyword Keyword",
- "default link @exception Exception",
-
- "default link @variable Identifier",
- "default link @type Type",
- "default link @type.definition Typedef",
- "default link @storageclass StorageClass",
- "default link @namespace Identifier",
- "default link @include Include",
- "default link @preproc PreProc",
- "default link @debug Debug",
+
+ "default link @punctuation Delimiter", // fallback for subgroups; never used itself
+ "default link @punctuation.special Special",
+
+ "default link @comment Comment",
+
+ "default link @comment.error DiagnosticError",
+ "default link @comment.warning DiagnosticWarn",
+ "default link @comment.note DiagnosticInfo",
+ "default link @comment.todo Todo",
+
+ "@markup.strong gui=bold cterm=bold",
+ "@markup.italic gui=italic cterm=italic",
+ "@markup.strikethrough gui=strikethrough cterm=strikethrough",
+ "@markup.underline gui=underline cterm=underline",
+
+ "default link @markup Special", // fallback for subgroups; never used itself
+ "default link @markup.heading Title",
+ "default link @markup.link Underlined",
+
+ "default link @diff.plus Added",
+ "default link @diff.minus Removed",
+ "default link @diff.delta Changed",
+
"default link @tag Tag",
// LSP semantic tokens
- "default link @lsp.type.class Structure",
- "default link @lsp.type.comment Comment",
- "default link @lsp.type.decorator Function",
- "default link @lsp.type.enum Structure",
- "default link @lsp.type.enumMember Constant",
- "default link @lsp.type.function Function",
- "default link @lsp.type.interface Structure",
- "default link @lsp.type.macro Macro",
- "default link @lsp.type.method Function",
- "default link @lsp.type.namespace Structure",
- "default link @lsp.type.parameter Identifier",
- "default link @lsp.type.property Identifier",
- "default link @lsp.type.struct Structure",
- "default link @lsp.type.type Type",
- "default link @lsp.type.typeParameter TypeDef",
- "default link @lsp.type.variable Identifier",
+ "default link @lsp.type.class @type",
+ "default link @lsp.type.comment @comment",
+ "default link @lsp.type.decorator @attribute",
+ "default link @lsp.type.enum @type",
+ "default link @lsp.type.enumMember @constant",
+ "default link @lsp.type.function @function",
+ "default link @lsp.type.interface @type",
+ "default link @lsp.type.macro @constant.macro",
+ "default link @lsp.type.method @function.method",
+ "default link @lsp.type.namespace @module",
+ "default link @lsp.type.parameter @variable.parameter",
+ "default link @lsp.type.property @property",
+ "default link @lsp.type.struct @type",
+ "default link @lsp.type.type @type",
+ "default link @lsp.type.typeParameter @type.definition",
+ "default link @lsp.type.variable @variable",
NULL
};
// Default colors only used with a light background.
static const char *highlight_init_light[] = {
- "ColorColumn ctermbg=LightRed guibg=LightRed",
- "CursorColumn ctermbg=LightGrey guibg=Grey90",
- "CursorLine cterm=underline guibg=Grey90",
- "CursorLineNr cterm=underline ctermfg=Brown gui=bold guifg=Brown",
- "DiffAdd ctermbg=LightBlue guibg=LightBlue",
- "DiffChange ctermbg=LightMagenta guibg=LightMagenta",
- "DiffDelete ctermfg=Blue ctermbg=LightCyan gui=bold guifg=Blue guibg=LightCyan",
- "Directory ctermfg=DarkBlue guifg=Blue",
- "FoldColumn ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue",
- "Folded ctermbg=Grey ctermfg=DarkBlue guibg=LightGrey guifg=DarkBlue",
- "LineNr ctermfg=Brown guifg=Brown",
- "MatchParen ctermbg=Cyan guibg=Cyan",
- "MoreMsg ctermfg=DarkGreen gui=bold guifg=SeaGreen",
- "Pmenu ctermbg=LightMagenta ctermfg=Black guibg=LightMagenta",
- "PmenuSel ctermbg=LightGrey ctermfg=Black guibg=Grey",
- "PmenuThumb ctermbg=Black guibg=Black",
- "Question ctermfg=DarkGreen gui=bold guifg=SeaGreen",
- "Search ctermbg=Yellow ctermfg=NONE guibg=Yellow guifg=NONE",
- "SignColumn ctermbg=Grey ctermfg=DarkBlue guibg=Grey guifg=DarkBlue",
- "SpecialKey ctermfg=DarkBlue guifg=Blue",
- "SpellBad ctermbg=LightRed guisp=Red gui=undercurl",
- "SpellCap ctermbg=LightBlue guisp=Blue gui=undercurl",
- "SpellLocal ctermbg=Cyan guisp=DarkCyan gui=undercurl",
- "SpellRare ctermbg=LightMagenta guisp=Magenta gui=undercurl",
- "TabLine cterm=underline ctermfg=black ctermbg=LightGrey gui=underline guibg=LightGrey",
- "Title ctermfg=DarkMagenta gui=bold guifg=Magenta",
- "Visual guibg=LightGrey",
- "WarningMsg ctermfg=DarkRed guifg=Red",
- "Comment term=bold cterm=NONE ctermfg=DarkBlue ctermbg=NONE gui=NONE guifg=Blue guibg=NONE",
- "Constant term=underline cterm=NONE ctermfg=DarkRed ctermbg=NONE gui=NONE guifg=Magenta guibg=NONE",
- "Special term=bold cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=#6a5acd guibg=NONE",
- "Identifier term=underline cterm=NONE ctermfg=DarkCyan ctermbg=NONE gui=NONE guifg=DarkCyan guibg=NONE",
- "Statement term=bold cterm=NONE ctermfg=Brown ctermbg=NONE gui=bold guifg=Brown guibg=NONE",
- "PreProc term=underline cterm=NONE ctermfg=DarkMagenta ctermbg=NONE gui=NONE guifg=#6a0dad guibg=NONE",
- "Type term=underline cterm=NONE ctermfg=DarkGreen ctermbg=NONE gui=bold guifg=SeaGreen guibg=NONE",
- "Underlined term=underline cterm=underline ctermfg=DarkMagenta gui=underline guifg=SlateBlue",
- "Ignore term=NONE cterm=NONE ctermfg=white ctermbg=NONE gui=NONE guifg=bg guibg=NONE",
+ "Normal guifg=NvimDarkGrey2 guibg=NvimLightGrey2 ctermfg=NONE ctermbg=NONE",
+
+ // UI
+ "Added guifg=NvimDarkGreen ctermfg=2",
+ "Changed guifg=NvimDarkCyan ctermfg=6",
+ "ColorColumn guibg=NvimLightGrey4 cterm=reverse",
+ "Conceal guifg=NvimLightGrey4",
+ "CurSearch guifg=NvimLightGrey1 guibg=NvimDarkYellow ctermfg=15 ctermbg=3",
+ "CursorColumn guibg=NvimLightGrey3",
+ "CursorLine guibg=NvimLightGrey3",
+ "DiffAdd guifg=NvimDarkGrey1 guibg=NvimLightGreen ctermfg=15 ctermbg=2",
+ "DiffChange guifg=NvimDarkGrey1 guibg=NvimLightGrey4",
+ "DiffDelete guifg=NvimDarkRed gui=bold ctermfg=1 cterm=bold",
+ "DiffText guifg=NvimDarkGrey1 guibg=NvimLightCyan ctermfg=15 ctermbg=6",
+ "Directory guifg=NvimDarkCyan ctermfg=6",
+ "ErrorMsg guifg=NvimDarkRed ctermfg=1",
+ "FloatShadow guibg=NvimLightGrey4 ctermbg=0 blend=80",
+ "FloatShadowThrough guibg=NvimLightGrey4 ctermbg=0 blend=100",
+ "Folded guifg=NvimDarkGrey4 guibg=NvimLightGrey3",
+ "LineNr guifg=NvimLightGrey4",
+ "MatchParen guibg=NvimLightGrey4 gui=bold cterm=bold,underline",
+ "ModeMsg guifg=NvimDarkGreen ctermfg=2",
+ "MoreMsg guifg=NvimDarkCyan ctermfg=6",
+ "NonText guifg=NvimLightGrey4",
+ "NormalFloat guibg=NvimLightGrey1",
+ "Pmenu guibg=NvimLightGrey3 cterm=reverse",
+ "PmenuSel guifg=NvimLightGrey3 guibg=NvimDarkGrey2 cterm=reverse,underline blend=0",
+ "PmenuThumb guibg=NvimLightGrey4",
+ "Question guifg=NvimDarkCyan ctermfg=6",
+ "QuickFixLine guifg=NvimDarkCyan ctermfg=6",
+ "RedrawDebugClear guibg=NvimLightYellow ctermfg=15 ctermbg=3",
+ "RedrawDebugComposed guibg=NvimLightGreen ctermfg=15 ctermbg=2",
+ "RedrawDebugRecompose guibg=NvimLightRed ctermfg=15 ctermbg=1",
+ "Removed guifg=NvimDarkRed ctermfg=1",
+ "Search guifg=NvimDarkGrey1 guibg=NvimLightYellow ctermfg=15 ctermbg=3",
+ "SignColumn guifg=NvimLightGrey4",
+ "SpecialKey guifg=NvimLightGrey4",
+ "SpellBad guisp=NvimDarkRed gui=undercurl cterm=undercurl",
+ "SpellCap guisp=NvimDarkYellow gui=undercurl cterm=undercurl",
+ "SpellLocal guisp=NvimDarkGreen gui=undercurl cterm=undercurl",
+ "SpellRare guisp=NvimDarkCyan gui=undercurl cterm=undercurl",
+ "StatusLine guifg=NvimLightGrey3 guibg=NvimDarkGrey3 cterm=reverse",
+ "StatusLineNC guifg=NvimDarkGrey3 guibg=NvimLightGrey3 cterm=bold",
+ "Title guifg=NvimDarkGrey2 gui=bold cterm=bold",
+ "Visual guibg=NvimLightGrey4 ctermfg=15 ctermbg=0",
+ "WarningMsg guifg=NvimDarkYellow ctermfg=3",
+ "WinBar guifg=NvimDarkGrey4 guibg=NvimLightGrey1 gui=bold cterm=bold",
+ "WinBarNC guifg=NvimDarkGrey4 guibg=NvimLightGrey1 cterm=bold",
+
+ // Syntax
+ "Constant guifg=NvimDarkGrey2", // Use only `Normal` foreground to be usable on different background
+ "Operator guifg=NvimDarkGrey2",
+ "PreProc guifg=NvimDarkGrey2",
+ "Type guifg=NvimDarkGrey2",
+ "Delimiter guifg=NvimDarkGrey2",
+
+ "Comment guifg=NvimDarkGrey4",
+ "String guifg=NvimDarkGreen ctermfg=2",
+ "Identifier guifg=NvimDarkBlue ctermfg=4",
+ "Function guifg=NvimDarkCyan ctermfg=6",
+ "Statement guifg=NvimDarkGrey2 gui=bold cterm=bold",
+ "Special guifg=NvimDarkCyan ctermfg=6",
+ "Error guifg=NvimDarkGrey1 guibg=NvimLightRed ctermfg=15 ctermbg=1",
+ "Todo guifg=NvimDarkGrey2 gui=bold cterm=bold",
+
+ // Diagnostic
+ "DiagnosticError guifg=NvimDarkRed ctermfg=1",
+ "DiagnosticWarn guifg=NvimDarkYellow ctermfg=3",
+ "DiagnosticInfo guifg=NvimDarkCyan ctermfg=6",
+ "DiagnosticHint guifg=NvimDarkBlue ctermfg=4",
+ "DiagnosticOk guifg=NvimDarkGreen ctermfg=2",
+ "DiagnosticUnderlineError guisp=NvimDarkRed gui=underline cterm=underline",
+ "DiagnosticUnderlineWarn guisp=NvimDarkYellow gui=underline cterm=underline",
+ "DiagnosticUnderlineInfo guisp=NvimDarkCyan gui=underline cterm=underline",
+ "DiagnosticUnderlineHint guisp=NvimDarkBlue gui=underline cterm=underline",
+ "DiagnosticUnderlineOk guisp=NvimDarkGreen gui=underline cterm=underline",
+ "DiagnosticDeprecated guisp=NvimDarkRed gui=strikethrough cterm=strikethrough",
+
+ // Treesitter standard groups
+ "@variable guifg=NvimDarkGrey2",
NULL
};
// Default colors only used with a dark background.
static const char *highlight_init_dark[] = {
- "ColorColumn ctermbg=DarkRed guibg=DarkRed",
- "CursorColumn ctermbg=DarkGrey guibg=Grey40",
- "CursorLine cterm=underline guibg=Grey40",
- "CursorLineNr cterm=underline ctermfg=Yellow gui=bold guifg=Yellow",
- "DiffAdd ctermbg=DarkBlue guibg=DarkBlue",
- "DiffChange ctermbg=DarkMagenta guibg=DarkMagenta",
- "DiffDelete ctermfg=Blue ctermbg=DarkCyan gui=bold guifg=Blue guibg=DarkCyan",
- "Directory ctermfg=LightCyan guifg=Cyan",
- "FoldColumn ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan",
- "Folded ctermbg=DarkGrey ctermfg=Cyan guibg=DarkGrey guifg=Cyan",
- "LineNr ctermfg=Yellow guifg=Yellow",
- "MatchParen ctermbg=DarkCyan guibg=DarkCyan",
- "MoreMsg ctermfg=LightGreen gui=bold guifg=SeaGreen",
- "Pmenu ctermbg=Magenta ctermfg=Black guibg=Magenta",
- "PmenuSel ctermbg=Black ctermfg=DarkGrey guibg=DarkGrey",
- "PmenuThumb ctermbg=White guibg=White",
- "Question ctermfg=LightGreen gui=bold guifg=Green",
- "Search ctermbg=Yellow ctermfg=Black guibg=Yellow guifg=Black",
- "SignColumn ctermbg=DarkGrey ctermfg=Cyan guibg=Grey guifg=Cyan",
- "SpecialKey ctermfg=LightBlue guifg=Cyan",
- "SpellBad ctermbg=Red guisp=Red gui=undercurl",
- "SpellCap ctermbg=Blue guisp=Blue gui=undercurl",
- "SpellLocal ctermbg=Cyan guisp=Cyan gui=undercurl",
- "SpellRare ctermbg=Magenta guisp=Magenta gui=undercurl",
- "TabLine cterm=underline ctermfg=white ctermbg=DarkGrey gui=underline guibg=DarkGrey",
- "Title ctermfg=LightMagenta gui=bold guifg=Magenta",
- "Visual guibg=DarkGrey",
- "WarningMsg ctermfg=LightRed guifg=Red",
- "Comment term=bold cterm=NONE ctermfg=Cyan ctermbg=NONE gui=NONE guifg=#80a0ff guibg=NONE",
- "Constant term=underline cterm=NONE ctermfg=Magenta ctermbg=NONE gui=NONE guifg=#ffa0a0 guibg=NONE",
- "Special term=bold cterm=NONE ctermfg=LightRed ctermbg=NONE gui=NONE guifg=Orange guibg=NONE",
- "Identifier term=underline cterm=bold ctermfg=Cyan ctermbg=NONE gui=NONE guifg=#40ffff guibg=NONE",
- "Statement term=bold cterm=NONE ctermfg=Yellow ctermbg=NONE gui=bold guifg=#ffff60 guibg=NONE",
- "PreProc term=underline cterm=NONE ctermfg=LightBlue ctermbg=NONE gui=NONE guifg=#ff80ff guibg=NONE",
- "Type term=underline cterm=NONE ctermfg=LightGreen ctermbg=NONE gui=bold guifg=#60ff60 guibg=NONE",
- "Underlined term=underline cterm=underline ctermfg=LightBlue gui=underline guifg=#80a0ff",
- "Ignore term=NONE cterm=NONE ctermfg=black ctermbg=NONE gui=NONE guifg=bg guibg=NONE",
+ "Normal guifg=NvimLightGrey2 guibg=NvimDarkGrey2 ctermfg=NONE ctermbg=NONE",
+
+ // UI
+ "Added guifg=NvimLightGreen ctermfg=10",
+ "Changed guifg=NvimLightCyan ctermfg=14",
+ "ColorColumn guibg=NvimDarkGrey4 cterm=reverse",
+ "Conceal guifg=NvimDarkGrey4",
+ "CurSearch guifg=NvimDarkGrey1 guibg=NvimLightYellow ctermfg=0 ctermbg=11",
+ "CursorColumn guibg=NvimDarkGrey3",
+ "CursorLine guibg=NvimDarkGrey3",
+ "DiffAdd guifg=NvimLightGrey1 guibg=NvimDarkGreen ctermfg=0 ctermbg=10",
+ "DiffChange guifg=NvimLightGrey1 guibg=NvimDarkGrey4",
+ "DiffDelete guifg=NvimLightRed gui=bold ctermfg=9 cterm=bold",
+ "DiffText guifg=NvimLightGrey1 guibg=NvimDarkCyan ctermfg=0 ctermbg=14",
+ "Directory guifg=NvimLightCyan ctermfg=14",
+ "ErrorMsg guifg=NvimLightRed ctermfg=9",
+ "FloatShadow guibg=NvimDarkGrey4 ctermbg=0 blend=80",
+ "FloatShadowThrough guibg=NvimDarkGrey4 ctermbg=0 blend=100",
+ "Folded guifg=NvimLightGrey4 guibg=NvimDarkGrey3",
+ "LineNr guifg=NvimDarkGrey4",
+ "MatchParen guibg=NvimDarkGrey4 gui=bold cterm=bold,underline",
+ "ModeMsg guifg=NvimLightGreen ctermfg=10",
+ "MoreMsg guifg=NvimLightCyan ctermfg=14",
+ "NonText guifg=NvimDarkGrey4",
+ "NormalFloat guibg=NvimDarkGrey1",
+ "Pmenu guibg=NvimDarkGrey3 cterm=reverse",
+ "PmenuSel guifg=NvimDarkGrey3 guibg=NvimLightGrey2 cterm=reverse,underline blend=0",
+ "PmenuThumb guibg=NvimDarkGrey4",
+ "Question guifg=NvimLightCyan ctermfg=14",
+ "QuickFixLine guifg=NvimLightCyan ctermfg=14",
+ "RedrawDebugClear guibg=NvimDarkYellow ctermfg=0 ctermbg=11",
+ "RedrawDebugComposed guibg=NvimDarkGreen ctermfg=0 ctermbg=10",
+ "RedrawDebugRecompose guibg=NvimDarkRed ctermfg=0 ctermbg=9",
+ "Removed guifg=NvimLightRed ctermfg=9",
+ "Search guifg=NvimLightGrey1 guibg=NvimDarkYellow ctermfg=0 ctermbg=11",
+ "SignColumn guifg=NvimDarkGrey4",
+ "SpecialKey guifg=NvimDarkGrey4",
+ "SpellBad guisp=NvimLightRed gui=undercurl cterm=undercurl",
+ "SpellCap guisp=NvimLightYellow gui=undercurl cterm=undercurl",
+ "SpellLocal guisp=NvimLightGreen gui=undercurl cterm=undercurl",
+ "SpellRare guisp=NvimLightCyan gui=undercurl cterm=undercurl",
+ "StatusLine guifg=NvimDarkGrey3 guibg=NvimLightGrey3 cterm=reverse",
+ "StatusLineNC guifg=NvimLightGrey3 guibg=NvimDarkGrey3 cterm=bold",
+ "Title guifg=NvimLightGrey2 gui=bold cterm=bold",
+ "Visual guibg=NvimDarkGrey4 ctermfg=0 ctermbg=15",
+ "WarningMsg guifg=NvimLightYellow ctermfg=11",
+ "WinBar guifg=NvimLightGrey4 guibg=NvimDarkGrey1 gui=bold cterm=bold",
+ "WinBarNC guifg=NvimLightGrey4 guibg=NvimDarkGrey1 cterm=bold",
+
+ // Syntax
+ "Constant guifg=NvimLightGrey2", // Use only `Normal` foreground to be usable on different background
+ "Operator guifg=NvimLightGrey2",
+ "PreProc guifg=NvimLightGrey2",
+ "Type guifg=NvimLightGrey2",
+ "Delimiter guifg=NvimLightGrey2",
+
+ "Comment guifg=NvimLightGrey4",
+ "String guifg=NvimLightGreen ctermfg=10",
+ "Identifier guifg=NvimLightBlue ctermfg=12",
+ "Function guifg=NvimLightCyan ctermfg=14",
+ "Statement guifg=NvimLightGrey2 gui=bold cterm=bold",
+ "Special guifg=NvimLightCyan ctermfg=14",
+ "Error guifg=NvimLightGrey1 guibg=NvimDarkRed ctermfg=0 ctermbg=9",
+ "Todo guifg=NvimLightGrey2 gui=bold cterm=bold",
+
+ // Diagnostic
+ "DiagnosticError guifg=NvimLightRed ctermfg=9",
+ "DiagnosticWarn guifg=NvimLightYellow ctermfg=11",
+ "DiagnosticInfo guifg=NvimLightCyan ctermfg=14",
+ "DiagnosticHint guifg=NvimLightBlue ctermfg=12",
+ "DiagnosticOk guifg=NvimLightGreen ctermfg=10",
+ "DiagnosticUnderlineError guisp=NvimLightRed gui=underline cterm=underline",
+ "DiagnosticUnderlineWarn guisp=NvimLightYellow gui=underline cterm=underline",
+ "DiagnosticUnderlineInfo guisp=NvimLightCyan gui=underline cterm=underline",
+ "DiagnosticUnderlineHint guisp=NvimLightBlue gui=underline cterm=underline",
+ "DiagnosticUnderlineOk guisp=NvimLightGreen gui=underline cterm=underline",
+ "DiagnosticDeprecated guisp=NvimLightRed gui=strikethrough cterm=strikethrough",
+
+ // Treesitter standard groups
+ "@variable guifg=NvimLightGrey2",
NULL
};
@@ -626,7 +705,7 @@ void syn_init_cmdline_highlight(bool reset, bool init)
/// @param reset clear groups first
void init_highlight(bool both, bool reset)
{
- static int had_both = false;
+ static bool had_both = false;
// Try finding the color scheme file. Used when a color file was loaded
// and 'background' or 't_Co' is changed.
@@ -663,22 +742,6 @@ void init_highlight(bool both, bool reset)
do_highlight(pp[i], reset, true);
}
- // Reverse looks ugly, but grey may not work for 8 colors. Thus let it
- // depend on the number of colors available.
- // With 8 colors brown is equal to yellow, need to use black for Search fg
- // to avoid Statement highlighted text disappears.
- // Clear the attributes, needed when changing the t_Co value.
- if (t_colors > 8) {
- do_highlight((*p_bg == 'l'
- ? "Visual cterm=NONE ctermbg=LightGrey"
- : "Visual cterm=NONE ctermbg=DarkGrey"), false, true);
- } else {
- do_highlight("Visual cterm=reverse ctermbg=NONE", false, true);
- if (*p_bg == 'l') {
- do_highlight("Search ctermfg=black", false, true);
- }
- }
-
syn_init_cmdline_highlight(false, false);
}
@@ -950,16 +1013,12 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// Handle ":highlight link {from} {to}" command.
if (dolink) {
const char *from_start = linep;
- const char *from_end;
- const char *to_start;
- const char *to_end;
- int from_id;
int to_id;
HlGroup *hlgroup = NULL;
- from_end = skiptowhite(from_start);
- to_start = skipwhite(from_end);
- to_end = skiptowhite(to_start);
+ const char *from_end = skiptowhite(from_start);
+ const char *to_start = skipwhite(from_end);
+ const char *to_end = skiptowhite(to_start);
if (ends_excmd((uint8_t)(*from_start))
|| ends_excmd((uint8_t)(*to_start))) {
@@ -973,7 +1032,7 @@ void do_highlight(const char *line, const bool forceit, const bool init)
return;
}
- from_id = syn_check_group(from_start, (size_t)(from_end - from_start));
+ int from_id = syn_check_group(from_start, (size_t)(from_end - from_start));
if (strncmp(to_start, "NONE", 4) == 0) {
to_id = 0;
} else {
@@ -1280,9 +1339,10 @@ void do_highlight(const char *line, const bool forceit, const bool init)
// wrong.
if (dark != -1
&& dark != (*p_bg == 'd')
- && !option_was_set("bg")) {
- set_option_value_give_err("bg", CSTR_AS_OPTVAL(dark ? "dark" : "light"), 0);
- reset_option_was_set("bg");
+ && !option_was_set(kOptBackground)) {
+ set_option_value_give_err(kOptBackground,
+ CSTR_AS_OPTVAL(dark ? "dark" : "light"), 0);
+ reset_option_was_set(kOptBackground);
}
}
}
@@ -1528,7 +1588,7 @@ static void highlight_list_one(const int id)
sgp->sg_blend + 1, NULL, "blend");
if (sgp->sg_link && !got_int) {
- (void)syn_list_header(didh, 0, id, true);
+ syn_list_header(didh, 0, id, true);
didh = true;
msg_puts_attr("links to", HL_ATTR(HLF_D));
msg_putchar(' ');
@@ -1612,10 +1672,7 @@ Dictionary ns_get_hl_defs(NS ns_id, Dict(get_highlight) *opts, Arena *arena, Err
return rv;
cleanup:
- api_free_integer(id);
- api_free_boolean(link);
- Dictionary empty = ARRAY_DICT_INIT;
- return empty;
+ return (Dictionary)ARRAY_DICT_INIT;
}
/// Outputs a highlight when doing ":hi MyHighlight"
@@ -1658,7 +1715,7 @@ static bool highlight_list_arg(const int id, bool didh, const int type, int iarg
}
}
- (void)syn_list_header(didh, vim_strsize(ts) + (int)strlen(name) + 1, id, false);
+ syn_list_header(didh, vim_strsize(ts) + (int)strlen(name) + 1, id, false);
didh = true;
if (!got_int) {
if (*name != NUL) {
@@ -1842,8 +1899,8 @@ static void set_hl_attr(int idx)
HlGroup *sgp = hl_table + idx;
at_en.cterm_ae_attr = (int16_t)sgp->sg_cterm;
- at_en.cterm_fg_color = sgp->sg_cterm_fg;
- at_en.cterm_bg_color = sgp->sg_cterm_bg;
+ at_en.cterm_fg_color = (int16_t)sgp->sg_cterm_fg;
+ at_en.cterm_bg_color = (int16_t)sgp->sg_cterm_bg;
at_en.rgb_ae_attr = (int16_t)sgp->sg_gui;
// FIXME(tarruda): The "unset value" for rgb is -1, but since hlgroup is
// initialized with 0(by garray functions), check for sg_rgb_{f,b}g_name
@@ -2046,7 +2103,6 @@ int syn_get_final_id(int hl_id)
bool syn_ns_get_final_id(int *ns_id, int *hl_idp)
{
- int count;
int hl_id = *hl_idp;
bool used = false;
@@ -2057,7 +2113,7 @@ bool syn_ns_get_final_id(int *ns_id, int *hl_idp)
// Follow links until there is no more.
// Look out for loops! Break after 100 links.
- for (count = 100; --count >= 0;) {
+ for (int count = 100; --count >= 0;) {
HlGroup *sgp = &hl_table[hl_id - 1]; // index is ID minus one
// TODO(bfredl): when using "tmp" attribute (no link) the function might be
@@ -2182,7 +2238,7 @@ void highlight_changed(void)
HlAttrs attrs = syn_attr2entry(highlight_attr[hlf]);
msg_grid.blending = attrs.hl_blend > -1;
}
- ui_call_hl_group_set(cstr_as_string((char *)hlf_names[hlf]),
+ ui_call_hl_group_set(cstr_as_string(hlf_names[hlf]),
highlight_attr[hlf]);
highlight_attr_last[hlf] = highlight_attr[hlf];
}
@@ -2829,6 +2885,29 @@ color_name_table_T color_name_table[] = {
{ "NavajoWhite4", RGB_(0x8b, 0x79, 0x5e) },
{ "Navy", RGB_(0x00, 0x00, 0x80) },
{ "NavyBlue", RGB_(0x0, 0x0, 0x80) },
+ // Default Neovim palettes.
+ // Dark/light palette is used for background in dark/light color scheme and
+ // for foreground in light/dark color scheme.
+ { "NvimDarkBlue", RGB_(0x00, 0x4c, 0x73) },
+ { "NvimDarkCyan", RGB_(0x00, 0x73, 0x73) },
+ { "NvimDarkGreen", RGB_(0x00, 0x55, 0x23) },
+ { "NvimDarkGrey1", RGB_(0x07, 0x08, 0x0d) },
+ { "NvimDarkGrey2", RGB_(0x14, 0x16, 0x1b) },
+ { "NvimDarkGrey3", RGB_(0x2c, 0x2e, 0x33) },
+ { "NvimDarkGrey4", RGB_(0x4f, 0x52, 0x58) },
+ { "NvimDarkMagenta", RGB_(0x47, 0x00, 0x45) },
+ { "NvimDarkRed", RGB_(0x59, 0x00, 0x08) },
+ { "NvimDarkYellow", RGB_(0x6b, 0x53, 0x00) },
+ { "NvimLightBlue", RGB_(0xa6, 0xdb, 0xff) },
+ { "NvimLightCyan", RGB_(0x8c, 0xf8, 0xf7) },
+ { "NvimLightGreen", RGB_(0xb3, 0xf6, 0xc0) },
+ { "NvimLightGrey1", RGB_(0xee, 0xf1, 0xf8) },
+ { "NvimLightGrey2", RGB_(0xe0, 0xe2, 0xea) },
+ { "NvimLightGrey3", RGB_(0xc4, 0xc6, 0xcd) },
+ { "NvimLightGrey4", RGB_(0x9b, 0x9e, 0xa4) },
+ { "NvimLightMagenta", RGB_(0xff, 0xca, 0xff) },
+ { "NvimLightRed", RGB_(0xff, 0xc0, 0xb9) },
+ { "NvimLightYellow", RGB_(0xfc, 0xe0, 0x94) },
{ "OldLace", RGB_(0xfd, 0xf5, 0xe6) },
{ "Olive", RGB_(0x80, 0x80, 0x00) },
{ "OliveDrab", RGB_(0x6b, 0x8e, 0x23) },
diff --git a/src/nvim/highlight_group.h b/src/nvim/highlight_group.h
index ca7bd36271..47d58d20f2 100644
--- a/src/nvim/highlight_group.h
+++ b/src/nvim/highlight_group.h
@@ -1,19 +1,18 @@
#pragma once
-#include "nvim/api/keysets_defs.h"
+#include "nvim/api/keysets_defs.h" // IWYU pragma: keep
#include "nvim/api/private/defs.h" // IWYU pragma: keep
-#include "nvim/api/private/helpers.h"
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/highlight_defs.h"
#include "nvim/types_defs.h" // IWYU pragma: keep
-#define MAX_HL_ID 20000 // maximum value for a highlight ID.
+enum { MAX_HL_ID = 20000, }; ///< maximum value for a highlight ID.
typedef struct {
char *name;
RgbValue color;
} color_name_table_T;
-extern color_name_table_T color_name_table[];
+extern color_name_table_T color_name_table[700];
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "highlight_group.h.generated.h"
diff --git a/src/nvim/indent.c b/src/nvim/indent.c
index 348f3a6528..14247b6d86 100644
--- a/src/nvim/indent.c
+++ b/src/nvim/indent.c
@@ -7,6 +7,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/assert_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/change.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
@@ -17,24 +18,27 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/extmark.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/extmark_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
-#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/input.h"
#include "nvim/plines.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/search.h"
#include "nvim/state_defs.h"
#include "nvim/strings.h"
@@ -54,15 +58,13 @@
bool tabstop_set(char *var, colnr_T **array)
{
int valcount = 1;
- int t;
- char *cp;
if (var[0] == NUL || (var[0] == '0' && var[1] == NUL)) {
*array = NULL;
return true;
}
- for (cp = var; *cp != NUL; cp++) {
+ for (char *cp = var; *cp != NUL; cp++) {
if (cp == var || cp[-1] == ',') {
char *end;
@@ -90,8 +92,8 @@ bool tabstop_set(char *var, colnr_T **array)
*array = (colnr_T *)xmalloc((unsigned)(valcount + 1) * sizeof(int));
(*array)[0] = (colnr_T)valcount;
- t = 1;
- for (cp = var; *cp != NUL;) {
+ int t = 1;
+ for (char *cp = var; *cp != NUL;) {
int n = atoi(cp);
// Catch negative values, overflow and ridiculous big values.
@@ -116,6 +118,7 @@ bool tabstop_set(char *var, colnr_T **array)
/// If "vts" is set then the tab widths are taken from that array,
/// otherwise the value of ts is used.
int tabstop_padding(colnr_T col, OptInt ts_arg, const colnr_T *vts)
+ FUNC_ATTR_PURE
{
OptInt ts = ts_arg == 0 ? 8 : ts_arg;
colnr_T tabcol = 0;
@@ -172,14 +175,13 @@ int tabstop_at(colnr_T col, OptInt ts, const colnr_T *vts)
colnr_T tabstop_start(colnr_T col, int ts, colnr_T *vts)
{
colnr_T tabcol = 0;
- int t;
if (vts == NULL || vts[0] == 0) {
return ((col / ts) * ts);
}
const int tabcount = vts[0];
- for (t = 1; t <= tabcount; t++) {
+ for (int t = 1; t <= tabcount; t++) {
tabcol += vts[t];
if (tabcol > col) {
return (tabcol - vts[t]);
@@ -259,8 +261,6 @@ void tabstop_fromto(colnr_T start_col, colnr_T end_col, int ts_arg, const colnr_
/// See if two tabstop arrays contain the same values.
bool tabstop_eq(const colnr_T *ts1, const colnr_T *ts2)
{
- int t;
-
if ((ts1 == 0 && ts2) || (ts1 && ts2 == 0)) {
return false;
}
@@ -271,7 +271,7 @@ bool tabstop_eq(const colnr_T *ts1, const colnr_T *ts2)
return false;
}
- for (t = 1; t <= ts1[0]; t++) {
+ for (int t = 1; t <= ts1[0]; t++) {
if (ts1[t] != ts2[t]) {
return false;
}
@@ -283,15 +283,12 @@ bool tabstop_eq(const colnr_T *ts1, const colnr_T *ts2)
/// Copy a tabstop array, allocating space for the new array.
int *tabstop_copy(const int *oldts)
{
- int *newts;
- int t;
-
if (oldts == 0) {
return 0;
}
- newts = xmalloc((unsigned)(oldts[0] + 1) * sizeof(int));
- for (t = 0; t <= oldts[0]; t++) {
+ int *newts = xmalloc((unsigned)(oldts[0] + 1) * sizeof(int));
+ for (int t = 0; t <= oldts[0]; t++) {
newts[t] = oldts[t];
}
@@ -353,117 +350,127 @@ int get_sts_value(void)
return result;
}
-// Count the size (in window cells) of the indent in the current line.
+/// Count the size (in window cells) of the indent in the current line.
int get_indent(void)
{
- return get_indent_str_vtab(get_cursor_line_ptr(),
- curbuf->b_p_ts,
- curbuf->b_p_vts_array,
- false);
+ return indent_size_ts(get_cursor_line_ptr(), curbuf->b_p_ts, curbuf->b_p_vts_array);
}
-// Count the size (in window cells) of the indent in line "lnum".
+/// Count the size (in window cells) of the indent in line "lnum".
int get_indent_lnum(linenr_T lnum)
{
- return get_indent_str_vtab(ml_get(lnum),
- curbuf->b_p_ts,
- curbuf->b_p_vts_array,
- false);
+ return indent_size_ts(ml_get(lnum), curbuf->b_p_ts, curbuf->b_p_vts_array);
}
-// Count the size (in window cells) of the indent in line "lnum" of buffer
-// "buf".
+/// Count the size (in window cells) of the indent in line "lnum" of buffer "buf".
int get_indent_buf(buf_T *buf, linenr_T lnum)
{
- return get_indent_str_vtab(ml_get_buf(buf, lnum), buf->b_p_ts, buf->b_p_vts_array, false);
+ return indent_size_ts(ml_get_buf(buf, lnum), buf->b_p_ts, buf->b_p_vts_array);
}
-/// Count the size (in window cells) of the indent in line "ptr", with
-/// 'tabstop' at "ts".
-/// If @param list is true, count only screen size for tabs.
-int get_indent_str(const char *ptr, int ts, bool list)
- FUNC_ATTR_NONNULL_ALL
+/// Compute the size of the indent (in window cells) in line "ptr",
+/// without tabstops (count tab as ^I or <09>).
+int indent_size_no_ts(char const *ptr)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
{
- int count = 0;
-
- for (; *ptr; ptr++) {
- // Count a tab for what it is worth.
- if (*ptr == TAB) {
- if (!list || curwin->w_p_lcs_chars.tab1) {
- // count a tab for what it is worth
- count += ts - (count % ts);
- } else {
- // In list mode, when tab is not set, count screen char width
- // for Tab, displays: ^I
- count += ptr2cells(ptr);
- }
- } else if (*ptr == ' ') {
- // Count a space for one.
- count++;
+ int tab_size = byte2cells(TAB);
+
+ int vcol = 0;
+ while (true) {
+ char const c = *ptr++;
+ if (c == ' ') {
+ vcol++;
+ } else if (c == TAB) {
+ vcol += tab_size;
} else {
- break;
+ return vcol;
}
}
- return count;
}
-/// Count the size (in window cells) of the indent in line "ptr", using
-/// variable tabstops.
-/// if "list" is true, count only screen size for tabs.
-int get_indent_str_vtab(const char *ptr, OptInt ts, colnr_T *vts, bool list)
+/// Compute the size of the indent (in window cells) in line "ptr",
+/// using tabstops
+int indent_size_ts(char const *ptr, OptInt ts, colnr_T *vts)
+ FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_PURE
{
- int count = 0;
+ assert(char2cells(' ') == 1);
+
+ int vcol = 0;
+ int tabstop_width, next_tab_vcol;
+
+ if (vts == NULL || vts[0] < 1) { // tab has fixed width
+ // can ts be 0 ? This is from tabstop_padding().
+ tabstop_width = (int)(ts == 0 ? 8 : ts);
+ next_tab_vcol = tabstop_width;
+ } else { // tab has variable width
+ colnr_T *cur_tabstop = vts + 1;
+ colnr_T *const last_tabstop = vts + vts[0];
+
+ while (cur_tabstop != last_tabstop) {
+ int cur_vcol = vcol;
+ vcol += *cur_tabstop++;
+ assert(cur_vcol < vcol);
+
+ do {
+ char const c = *ptr++;
+ if (c == ' ') {
+ cur_vcol++;
+ } else if (c == TAB) {
+ break;
+ } else {
+ return cur_vcol;
+ }
+ } while (cur_vcol != vcol);
+ }
- for (; *ptr; ptr++) {
- if (*ptr == TAB) { // count a tab for what it is worth
- if (!list || curwin->w_p_lcs_chars.tab1) {
- count += tabstop_padding(count, ts, vts);
- } else {
- // In list mode, when tab is not set, count screen char width
- // for Tab, displays: ^I
- count += ptr2cells(ptr);
- }
- } else if (*ptr == ' ') {
- count++; // count a space for one
+ tabstop_width = *last_tabstop;
+ next_tab_vcol = vcol + tabstop_width;
+ }
+
+ assert(tabstop_width != 0);
+ while (true) {
+ char const c = *ptr++;
+ if (c == ' ') {
+ vcol++;
+ next_tab_vcol += (vcol == next_tab_vcol) ? tabstop_width : 0;
+ } else if (c == TAB) {
+ vcol = next_tab_vcol;
+ next_tab_vcol += tabstop_width;
} else {
- break;
+ return vcol;
}
}
- return count;
}
-// Set the indent of the current line.
-// Leaves the cursor on the first non-blank in the line.
-// Caller must take care of undo.
-// "flags":
-// SIN_CHANGED: call changed_bytes() if the line was changed.
-// SIN_INSERT: insert the indent in front of the line.
-// SIN_UNDO: save line for undo before changing it.
-// SIN_NOMARK: don't move extmarks (because just after ml_append or something)
-// @param size measured in spaces
-// Returns true if the line was changed.
-int set_indent(int size, int flags)
+/// Set the indent of the current line.
+/// Leaves the cursor on the first non-blank in the line.
+/// Caller must take care of undo.
+/// "flags":
+/// SIN_CHANGED: call changed_bytes() if the line was changed.
+/// SIN_INSERT: insert the indent in front of the line.
+/// SIN_UNDO: save line for undo before changing it.
+/// SIN_NOMARK: don't move extmarks (because just after ml_append or something)
+/// @param size measured in spaces
+///
+/// @return true if the line was changed.
+bool set_indent(int size, int flags)
{
- char *p;
char *newline;
char *oldline;
char *s;
- int todo;
- int ind_len; // Measured in characters.
- int line_len;
int doit = false;
int ind_done = 0; // Measured in spaces.
int tab_pad;
- int retval = false;
+ bool retval = false;
// Number of initial whitespace chars when 'et' and 'pi' are both set.
int orig_char_len = -1;
// First check if there is anything to do and compute the number of
// characters needed for the indent.
- todo = size;
- ind_len = 0;
- p = oldline = get_cursor_line_ptr();
+ int todo = size;
+ int ind_len = 0; // Measured in characters.
+ char *p = oldline = get_cursor_line_ptr();
// Calculate the buffer size for the new indent, and check to see if it
// isn't already set.
@@ -561,7 +568,7 @@ int set_indent(int size, int flags)
} else {
p = skipwhite(p);
}
- line_len = (int)strlen(p) + 1;
+ int line_len = (int)strlen(p) + 1;
// If 'preserveindent' and 'expandtab' are both set keep the original
// characters and allocate accordingly. We will fill the rest with spaces
@@ -799,49 +806,60 @@ int get_breakindent_win(win_T *wp, char *line)
{
static int prev_indent = 0; // cached indent value
static OptInt prev_ts = 0; // cached tabstop value
+ static colnr_T *prev_vts = NULL; // cached vartabs values
static int prev_fnum = 0; // cached buffer number
static char *prev_line = NULL; // cached copy of "line"
static varnumber_T prev_tick = 0; // changedtick of cached value
- static colnr_T *prev_vts = NULL; // cached vartabs values
- static int prev_list = 0; // cached list value
+ static int prev_list = 0; // cached list indent
static int prev_listopt = 0; // cached w_p_briopt_list value
+ static bool prev_no_ts = false; // cached no_ts value
+ static unsigned prev_dy_uhex = 0; // cached 'display' "uhex" value
static char *prev_flp = NULL; // cached formatlistpat value
int bri = 0;
// window width minus window margin space, i.e. what rests for text
- const int eff_wwidth = wp->w_width_inner -
- ((wp->w_p_nu || wp->w_p_rnu)
- && (vim_strchr(p_cpo, CPO_NUMCOL) == NULL) ? number_width(wp) + 1 : 0);
-
- // used cached indent, unless
- // - buffer changed
- // - 'tabstop' changed
- // - buffer was changed
- // - 'briopt_list changed' changed or
- // - 'formatlistpattern' changed
- // - line changed
- // - 'vartabs' changed
+ const int eff_wwidth = wp->w_width_inner - win_col_off(wp) + win_col_off2(wp);
+
+ // In list mode, if 'listchars' "tab" isn't set, a TAB is displayed as ^I.
+ const bool no_ts = wp->w_p_list && wp->w_p_lcs_chars.tab1 == NUL;
+
+ // Used cached indent, unless
+ // - buffer changed, or
+ // - 'tabstop' changed, or
+ // - 'vartabstop' changed, or
+ // - buffer was changed, or
+ // - 'breakindentopt' "list" changed, or
+ // - 'list' or 'listchars' "tab" changed, or
+ // - 'display' "uhex" flag changed, or
+ // - 'formatlistpat' changed, or
+ // - line changed.
if (prev_fnum != wp->w_buffer->b_fnum
|| prev_ts != wp->w_buffer->b_p_ts
+ || prev_vts != wp->w_buffer->b_p_vts_array
|| prev_tick != buf_get_changedtick(wp->w_buffer)
|| prev_listopt != wp->w_briopt_list
+ || prev_no_ts != no_ts
+ || prev_dy_uhex != (dy_flags & DY_UHEX)
|| prev_flp == NULL
|| strcmp(prev_flp, get_flp_value(wp->w_buffer)) != 0
- || prev_line == NULL || strcmp(prev_line, line) != 0
- || prev_vts != wp->w_buffer->b_p_vts_array) {
+ || prev_line == NULL || strcmp(prev_line, line) != 0) {
prev_fnum = wp->w_buffer->b_fnum;
xfree(prev_line);
prev_line = xstrdup(line);
prev_ts = wp->w_buffer->b_p_ts;
- prev_tick = buf_get_changedtick(wp->w_buffer);
prev_vts = wp->w_buffer->b_p_vts_array;
if (wp->w_briopt_vcol == 0) {
- prev_indent = get_indent_str_vtab(line,
- wp->w_buffer->b_p_ts,
- wp->w_buffer->b_p_vts_array,
- wp->w_p_list);
+ if (no_ts) {
+ prev_indent = indent_size_no_ts(line);
+ } else {
+ prev_indent = indent_size_ts(line, wp->w_buffer->b_p_ts,
+ wp->w_buffer->b_p_vts_array);
+ }
}
+ prev_tick = buf_get_changedtick(wp->w_buffer);
prev_listopt = wp->w_briopt_list;
prev_list = 0;
+ prev_no_ts = no_ts;
+ prev_dy_uhex = (dy_flags & DY_UHEX);
xfree(prev_flp);
prev_flp = xstrdup(get_flp_value(wp->w_buffer));
// add additional indent for numbered lists
@@ -900,7 +918,7 @@ int get_breakindent_win(win_T *wp, char *line)
// non-blank in the line.
// When extra == 1: Return true if the cursor is before the first non-blank in
// the line.
-int inindent(int extra)
+bool inindent(int extra)
{
char *ptr;
colnr_T col;
@@ -934,23 +952,18 @@ static void emsg_text_too_long(void)
/// ":retab".
void ex_retab(exarg_T *eap)
{
- linenr_T lnum;
bool got_tab = false;
int num_spaces = 0;
- int num_tabs;
- int len;
int start_col = 0; // For start of white-space string
int64_t start_vcol = 0; // For start of white-space string
- int old_len;
char *new_line = (char *)1; // init to non-NULL
colnr_T *new_vts_array = NULL;
char *new_ts_str; // string value of tab argument
- int save_list;
linenr_T first_line = 0; // first changed line
linenr_T last_line = 0; // last changed line
- save_list = curwin->w_p_list;
+ int save_list = curwin->w_p_list;
curwin->w_p_list = 0; // don't want list mode here
new_ts_str = eap->arg;
@@ -970,7 +983,7 @@ void ex_retab(exarg_T *eap)
} else {
new_ts_str = xmemdupz(new_ts_str, (size_t)(eap->arg - new_ts_str));
}
- for (lnum = eap->line1; !got_int && lnum <= eap->line2; lnum++) {
+ for (linenr_T lnum = eap->line1; !got_int && lnum <= eap->line2; lnum++) {
char *ptr = ml_get(lnum);
int col = 0;
int64_t vcol = 0;
@@ -992,8 +1005,8 @@ void ex_retab(exarg_T *eap)
// Retabulate this string of white-space
// len is virtual length of white string
- len = num_spaces = (int)(vcol - start_vcol);
- num_tabs = 0;
+ int len = num_spaces = (int)(vcol - start_vcol);
+ int num_tabs = 0;
if (!curbuf->b_p_et) {
int t, s;
@@ -1015,7 +1028,7 @@ void ex_retab(exarg_T *eap)
// len is actual number of white characters used
len = num_spaces + num_tabs;
- old_len = (int)strlen(ptr);
+ int old_len = (int)strlen(ptr);
const int new_len = old_len - col + start_col + len + 1;
if (new_len <= 0 || new_len >= MAXCOL) {
emsg_text_too_long();
@@ -1092,7 +1105,7 @@ void ex_retab(exarg_T *eap)
colnr_T *old_vts_ary = curbuf->b_p_vts_array;
if (tabstop_count(old_vts_ary) > 0 || tabstop_count(new_vts_array) > 1) {
- set_string_option_direct("vts", -1, new_ts_str, OPT_FREE | OPT_LOCAL, 0);
+ set_string_option_direct(kOptVartabstop, new_ts_str, OPT_LOCAL, 0);
curbuf->b_p_vts_array = new_vts_array;
xfree(old_vts_ary);
} else {
@@ -1111,19 +1124,14 @@ void ex_retab(exarg_T *eap)
/// Get indent level from 'indentexpr'.
int get_expr_indent(void)
{
- int indent = -1;
- pos_T save_pos;
- colnr_T save_curswant;
- int save_set_curswant;
- int save_State;
- int use_sandbox = was_set_insecurely(curwin, "indentexpr", OPT_LOCAL);
+ bool use_sandbox = was_set_insecurely(curwin, kOptIndentexpr, OPT_LOCAL);
const sctx_T save_sctx = current_sctx;
// Save and restore cursor position and curswant, in case it was changed
// * via :normal commands.
- save_pos = curwin->w_cursor;
- save_curswant = curwin->w_curswant;
- save_set_curswant = curwin->w_set_curswant;
+ pos_T save_pos = curwin->w_cursor;
+ colnr_T save_curswant = curwin->w_curswant;
+ bool save_set_curswant = curwin->w_set_curswant;
set_vim_var_nr(VV_LNUM, (varnumber_T)curwin->w_cursor.lnum);
if (use_sandbox) {
@@ -1135,7 +1143,7 @@ int get_expr_indent(void)
// Need to make a copy, the 'indentexpr' option could be changed while
// evaluating it.
char *inde_copy = xstrdup(curbuf->b_p_inde);
- indent = (int)eval_to_number(inde_copy);
+ int indent = (int)eval_to_number(inde_copy);
xfree(inde_copy);
if (use_sandbox) {
@@ -1147,7 +1155,7 @@ int get_expr_indent(void)
// Restore the cursor position so that 'indentexpr' doesn't need to.
// Pretend to be in Insert mode, allow cursor past end of line for "o"
// command.
- save_State = State;
+ int save_State = State;
State = MODE_INSERT;
curwin->w_cursor = save_pos;
curwin->w_curswant = save_curswant;
@@ -1188,10 +1196,6 @@ int get_lisp_indent(void)
pos_T *pos;
pos_T paren;
int amount;
- char *that;
-
- // Set vi_lisp to use the vi-compatible method.
- int vi_lisp = (vim_strchr(p_cpo, CPO_LISP) != NULL);
pos_T realpos = curwin->w_cursor;
curwin->w_cursor.col = 0;
@@ -1218,7 +1222,7 @@ int get_lisp_indent(void)
continue;
}
- for (that = get_cursor_line_ptr(); *that != NUL; that++) {
+ for (char *that = get_cursor_line_ptr(); *that != NUL; that++) {
if (*that == ';') {
while (*(that + 1) != NUL) {
that++;
@@ -1268,94 +1272,83 @@ int get_lisp_indent(void)
curwin->w_cursor.col = pos->col;
colnr_T col = pos->col;
- that = get_cursor_line_ptr();
+ char *line = get_cursor_line_ptr();
+
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, curwin, pos->lnum, line);
- if (vi_lisp && (get_indent() == 0)) {
- amount = 2;
+ StrCharInfo sci = utf_ptr2StrCharInfo(line);
+ amount = 0;
+ while (*sci.ptr != NUL && col > 0) {
+ amount += win_charsize(cstype, amount, sci.ptr, sci.chr.value, &csarg).width;
+ sci = utfc_next(sci);
+ col--;
+ }
+ char *that = sci.ptr;
+
+ // Some keywords require "body" indenting rules (the
+ // non-standard-lisp ones are Scheme special forms):
+ // (let ((a 1)) instead (let ((a 1))
+ // (...)) of (...))
+ if (((*that == '(') || (*that == '[')) && lisp_match(that + 1)) {
+ amount += 2;
} else {
- char *line = that;
- chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, pos->lnum, 0, line, line);
- while (*cts.cts_ptr != NUL && col > 0) {
- cts.cts_vcol += lbr_chartabsize_adv(&cts);
- col--;
+ if (*that != NUL) {
+ that++;
+ amount++;
+ }
+ colnr_T firsttry = amount;
+
+ while (ascii_iswhite(*that)) {
+ amount += win_charsize(cstype, amount, that, (uint8_t)(*that), &csarg).width;
+ that++;
}
- amount = cts.cts_vcol;
- that = cts.cts_ptr;
- clear_chartabsize_arg(&cts);
-
- // Some keywords require "body" indenting rules (the
- // non-standard-lisp ones are Scheme special forms):
- // (let ((a 1)) instead (let ((a 1))
- // (...)) of (...))
- if (!vi_lisp && ((*that == '(') || (*that == '['))
- && lisp_match(that + 1)) {
- amount += 2;
- } else {
- if (*that != NUL) {
- that++;
- amount++;
- }
- colnr_T firsttry = amount;
- init_chartabsize_arg(&cts, curwin, (colnr_T)(that - line),
- amount, line, that);
- while (ascii_iswhite(*cts.cts_ptr)) {
- cts.cts_vcol += lbr_chartabsize(&cts);
- cts.cts_ptr++;
+ if (*that && (*that != ';')) {
+ // Not a comment line.
+ // Test *that != '(' to accommodate first let/do
+ // argument if it is more than one line.
+ if ((*that != '(') && (*that != '[')) {
+ firsttry++;
}
- that = cts.cts_ptr;
- amount = cts.cts_vcol;
- clear_chartabsize_arg(&cts);
-
- if (*that && (*that != ';')) {
- // Not a comment line.
- // Test *that != '(' to accommodate first let/do
- // argument if it is more than one line.
- if (!vi_lisp && (*that != '(') && (*that != '[')) {
- firsttry++;
- }
- parencount = 0;
-
- init_chartabsize_arg(&cts, curwin,
- (colnr_T)(that - line), amount, line, that);
- if (vi_lisp || ((*that != '"') && (*that != '\'')
- && (*that != '#')
- && (((uint8_t)(*that) < '0') || ((uint8_t)(*that) > '9')))) {
- int quotecount = 0;
- while (*cts.cts_ptr
- && (!ascii_iswhite(*cts.cts_ptr) || quotecount || parencount)
- && (!((*cts.cts_ptr == '(' || *cts.cts_ptr == '[')
- && !quotecount && !parencount && vi_lisp))) {
- if (*cts.cts_ptr == '"') {
- quotecount = !quotecount;
- }
- if (((*cts.cts_ptr == '(') || (*cts.cts_ptr == '[')) && !quotecount) {
- parencount++;
- }
- if (((*cts.cts_ptr == ')') || (*cts.cts_ptr == ']')) && !quotecount) {
- parencount--;
- }
- if ((*cts.cts_ptr == '\\') && (*(cts.cts_ptr + 1) != NUL)) {
- cts.cts_vcol += lbr_chartabsize_adv(&cts);
- }
-
- cts.cts_vcol += lbr_chartabsize_adv(&cts);
+ parencount = 0;
+
+ CharInfo ci = utf_ptr2CharInfo(that);
+ if (((ci.value != '"') && (ci.value != '\'') && (ci.value != '#')
+ && ((ci.value < '0') || (ci.value > '9')))) {
+ int quotecount = 0;
+ while (*that && (!ascii_iswhite(ci.value) || quotecount || parencount)) {
+ if (ci.value == '"') {
+ quotecount = !quotecount;
+ }
+ if (((ci.value == '(') || (ci.value == '[')) && !quotecount) {
+ parencount++;
+ }
+ if (((ci.value == ')') || (ci.value == ']')) && !quotecount) {
+ parencount--;
+ }
+ if ((ci.value == '\\') && (*(that + 1) != NUL)) {
+ amount += win_charsize(cstype, amount, that, ci.value, &csarg).width;
+ StrCharInfo next_sci = utfc_next((StrCharInfo){ that, ci });
+ that = next_sci.ptr;
+ ci = next_sci.chr;
}
- }
- while (ascii_iswhite(*cts.cts_ptr)) {
- cts.cts_vcol += lbr_chartabsize(&cts);
- cts.cts_ptr++;
+ amount += win_charsize(cstype, amount, that, ci.value, &csarg).width;
+ StrCharInfo next_sci = utfc_next((StrCharInfo){ that, ci });
+ that = next_sci.ptr;
+ ci = next_sci.chr;
}
- that = cts.cts_ptr;
- amount = cts.cts_vcol;
- clear_chartabsize_arg(&cts);
+ }
- if (!*that || (*that == ';')) {
- amount = firsttry;
- }
+ while (ascii_iswhite(*that)) {
+ amount += win_charsize(cstype, amount, that, (uint8_t)(*that), &csarg).width;
+ that++;
+ }
+
+ if (!*that || (*that == ';')) {
+ amount = firsttry;
}
}
}
@@ -1374,7 +1367,7 @@ static int lisp_match(char *p)
char *word = *curbuf->b_p_lw != NUL ? curbuf->b_p_lw : p_lispwords;
while (*word != NUL) {
- (void)copy_option_part(&word, buf, sizeof(buf), ",");
+ copy_option_part(&word, buf, sizeof(buf), ",");
int len = (int)strlen(buf);
if ((strncmp(buf, p, (size_t)len) == 0) && ascii_iswhite_or_nul(p[len])) {
diff --git a/src/nvim/indent.h b/src/nvim/indent.h
index b64015958c..54d27e6243 100644
--- a/src/nvim/indent.h
+++ b/src/nvim/indent.h
@@ -1,6 +1,5 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c
index c140d468d8..a660c9dead 100644
--- a/src/nvim/indent_c.c
+++ b/src/nvim/indent_c.c
@@ -9,12 +9,11 @@
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/edit.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/macros_defs.h"
-#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/option.h"
@@ -24,6 +23,7 @@
#include "nvim/search.h"
#include "nvim/state_defs.h"
#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
// Find result cache for cpp_baseclass
@@ -3105,8 +3105,8 @@ int get_c_indent(void)
} else {
// Found first unterminated line on a row, may
// line up with this line, remember its indent
- // 100 + // NOLINT(whitespace/tab)
- // -> here; // NOLINT(whitespace/tab)
+ // 100 +
+ // -> here;
l = get_cursor_line_ptr();
amount = cur_amount;
@@ -3655,7 +3655,7 @@ static int find_match(int lookfor, linenr_T ourscope)
if (cin_iselse(look)) {
mightbeif = cin_skipcomment(look + 4);
if (!cin_isif(mightbeif)) {
- elselevel++; // NOLINT(readability/braces)
+ elselevel++;
}
continue;
}
@@ -3670,7 +3670,7 @@ static int find_match(int lookfor, linenr_T ourscope)
// If it's an "if" decrement elselevel
look = cin_skipcomment(get_cursor_line_ptr());
if (cin_isif(look)) {
- elselevel--; // NOLINT(readability/braces)
+ elselevel--;
// When looking for an "if" ignore "while"s that
// get in the way.
if (elselevel == 0 && lookfor == LOOKFOR_IF) {
diff --git a/src/nvim/indent_c.h b/src/nvim/indent_c.h
index 64ba67a42b..65a402f02c 100644
--- a/src/nvim/indent_c.h
+++ b/src/nvim/indent_c.h
@@ -1,7 +1,7 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "indent_c.h.generated.h"
diff --git a/src/nvim/input.c b/src/nvim/input.c
index fb25968071..7667c49452 100644
--- a/src/nvim/input.c
+++ b/src/nvim/input.c
@@ -7,11 +7,11 @@
#include <string.h>
#include "nvim/ascii_defs.h"
-#include "nvim/event/multiqueue.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/input.h"
#include "nvim/keycodes.h"
#include "nvim/mbyte.h"
@@ -35,7 +35,7 @@
/// @param[in] str Prompt: question to ask user. Is always followed by
/// " (y/n)?".
/// @param[in] direct Determines what function to use to get user input. If
-/// true then ui_inchar() will be used, otherwise vgetc().
+/// true then os_inchar() will be used, otherwise vgetc().
/// I.e. when direct is true then characters are obtained
/// directly from the user without buffers involved.
///
@@ -159,7 +159,7 @@ int get_keystroke(MultiQueue *events)
/// When "mouse_used" is not NULL allow using the mouse.
///
/// @param colon allow colon to abort
-int get_number(int colon, int *mouse_used)
+int get_number(int colon, bool *mouse_used)
{
int n = 0;
int typed = 0;
@@ -220,12 +220,8 @@ int get_number(int colon, int *mouse_used)
///
/// When "mouse_used" is not NULL allow using the mouse and in that case return
/// the line number.
-int prompt_for_number(int *mouse_used)
+int prompt_for_number(bool *mouse_used)
{
- int i;
- int save_cmdline_row;
- int save_State;
-
// When using ":silent" assume that <CR> was entered.
if (mouse_used != NULL) {
msg_puts(_("Type number and <Enter> or click with the mouse "
@@ -236,14 +232,14 @@ int prompt_for_number(int *mouse_used)
// Set the state such that text can be selected/copied/pasted and we still
// get mouse events.
- save_cmdline_row = cmdline_row;
+ int save_cmdline_row = cmdline_row;
cmdline_row = 0;
- save_State = State;
+ int save_State = State;
State = MODE_ASKMORE; // prevents a screen update when using a timer
// May show different mouse shape.
setmouse();
- i = get_number(true, mouse_used);
+ int i = get_number(true, mouse_used);
if (KeyTyped) {
// don't call wait_return() now
if (msg_row > 0) {
diff --git a/src/nvim/input.h b/src/nvim/input.h
index 3d948fa4ca..8741dafba4 100644
--- a/src/nvim/input.h
+++ b/src/nvim/input.h
@@ -1,6 +1,6 @@
#pragma once
-#include "nvim/event/multiqueue.h" // IWYU pragma: keep
+#include "nvim/event/defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "input.h.generated.h"
diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c
index 12543a2d42..41b964323e 100644
--- a/src/nvim/insexpand.c
+++ b/src/nvim/insexpand.c
@@ -9,34 +9,43 @@
#include <stdlib.h>
#include <string.h>
+#include "klib/kvec.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/change.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
+#include "nvim/cmdexpand_defs.h"
#include "nvim/cursor.h"
#include "nvim/drawscreen.h"
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
+#include "nvim/extmark.h"
+#include "nvim/extmark_defs.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/insexpand.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
-#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -51,9 +60,11 @@
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/search.h"
#include "nvim/spell.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
#include "nvim/textformat.h"
@@ -62,6 +73,7 @@
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
+#include "nvim/winfloat.h"
// Definitions used for CTRL-X submode.
// Note: If you change CTRL-X submode, you must also maintain ctrl_x_msgs[]
@@ -252,6 +264,8 @@ static colnr_T compl_col = 0; ///< column where the text starts
///< that is being completed
static char *compl_orig_text = NULL; ///< text as it was before
///< completion started
+/// Undo information to restore extmarks for original text.
+static extmark_undo_vec_t compl_orig_extmarks;
static int compl_cont_mode = 0;
static expand_T compl_xp;
@@ -593,7 +607,6 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
int min_len, char **tofree)
{
bool has_lower = false;
- bool was_letter = false;
// Allocate wide character array for the completion and fill it.
int *const wca = xmalloc((size_t)char_len * sizeof(*wca));
@@ -625,6 +638,7 @@ static char *ins_compl_infercase_gettext(const char *str, int char_len, int comp
// Rule 2: No lower case, 2nd consecutive letter converted to
// upper case.
if (!has_lower) {
+ bool was_letter = false;
const char *p = compl_orig_text;
for (int i = 0; i < min_len; i++) {
const int c = mb_ptr2char_adv(&p);
@@ -744,6 +758,16 @@ int ins_compl_add_infercase(char *str_arg, int len, bool icase, char *fname, Dir
return res;
}
+/// free cptext
+static inline void free_cptext(char *const *const cptext)
+{
+ if (cptext != NULL) {
+ for (size_t i = 0; i < CPT_COUNT; i++) {
+ xfree(cptext[i]);
+ }
+ }
+}
+
/// Add a match to the list of matches
///
/// @param[in] str text of the match to add
@@ -781,16 +805,10 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons
} else {
os_breakcheck();
}
-#define FREE_CPTEXT(cptext, cptext_allocated) \
- do { \
- if ((cptext) != NULL && (cptext_allocated)) { \
- for (size_t i = 0; i < CPT_COUNT; i++) { \
- xfree((cptext)[i]); \
- } \
- } \
- } while (0)
if (got_int) {
- FREE_CPTEXT(cptext, cptext_allocated);
+ if (cptext_allocated) {
+ free_cptext(cptext);
+ }
return FAIL;
}
if (len < 0) {
@@ -804,7 +822,9 @@ static int ins_compl_add(char *const str, int len, char *const fname, char *cons
if (!match_at_original_text(match)
&& strncmp(match->cp_str, str, (size_t)len) == 0
&& ((int)strlen(match->cp_str) <= len || match->cp_str[len] == NUL)) {
- FREE_CPTEXT(cptext, cptext_allocated);
+ if (cptext_allocated) {
+ free_cptext(cptext);
+ }
return NOTDONE;
}
match = match->cp_next;
@@ -909,13 +929,11 @@ static bool ins_compl_equal(compl_T *match, char *str, size_t len)
/// Reduce the longest common string for match "match".
static void ins_compl_longest_match(compl_T *match)
{
- int had_match;
-
if (compl_leader == NULL) {
// First match, use it as a whole.
compl_leader = xstrdup(match->cp_str);
- had_match = (curwin->w_cursor.col > compl_col);
+ bool had_match = (curwin->w_cursor.col > compl_col);
ins_compl_delete();
ins_bytes(compl_leader + get_compl_len());
ins_redraw(false);
@@ -949,7 +967,7 @@ static void ins_compl_longest_match(compl_T *match)
if (*p != NUL) {
// Leader was shortened, need to change the inserted text.
*p = NUL;
- had_match = (curwin->w_cursor.col > compl_col);
+ bool had_match = (curwin->w_cursor.col > compl_col);
ins_compl_delete();
ins_bytes(compl_leader + get_compl_len());
ins_redraw(false);
@@ -1261,6 +1279,9 @@ void ins_compl_show_pum(void)
}
if (compl_match_array == NULL) {
+ if (compl_started && has_event(EVENT_COMPLETECHANGED)) {
+ trigger_complete_changed_event(cur);
+ }
return;
}
@@ -1276,11 +1297,38 @@ void ins_compl_show_pum(void)
pum_display(compl_match_array, compl_match_arraysize, cur, array_changed, 0);
curwin->w_cursor.col = col;
+ // After adding leader, set the current match to shown match.
+ if (compl_started && compl_curr_match != compl_shown_match) {
+ compl_curr_match = compl_shown_match;
+ }
+
if (has_event(EVENT_COMPLETECHANGED)) {
trigger_complete_changed_event(cur);
}
}
+/// used for set or update info
+void compl_set_info(int pum_idx)
+{
+ compl_T *comp = compl_first_match;
+ char *pum_text = compl_match_array[pum_idx].pum_text;
+
+ while (comp != NULL) {
+ if (pum_text == comp->cp_str
+ || pum_text == comp->cp_text[CPT_ABBR]) {
+ comp->cp_text[CPT_INFO] = compl_match_array[pum_idx].pum_info;
+
+ // if comp is current match update completed_item value
+ if (comp == compl_curr_match) {
+ dict_T *dict = ins_compl_dict_alloc(compl_curr_match);
+ set_vim_var_dict(VV_COMPLETED_ITEM, dict);
+ }
+ break;
+ }
+ comp = comp->cp_next;
+ }
+}
+
#define DICT_FIRST (1) ///< use just first element in "dict"
#define DICT_EXACT (2) ///< "dict" is the exact name of a file
@@ -1289,7 +1337,7 @@ void ins_compl_show_pum(void)
///
/// @param flags DICT_FIRST and/or DICT_EXACT
/// @param thesaurus Thesaurus completion
-static void ins_compl_dictionaries(char *dict_start, char *pat, int flags, int thesaurus)
+static void ins_compl_dictionaries(char *dict_start, char *pat, int flags, bool thesaurus)
{
char *dict = dict_start;
char *ptr;
@@ -1432,8 +1480,8 @@ static int thesaurus_add_words_in_line(char *fname, char **buf_arg, int dir, con
/// Process "count" dictionary/thesaurus "files" and add the text matching
/// "regmatch".
-static void ins_compl_files(int count, char **files, int thesaurus, int flags, regmatch_T *regmatch,
- char *buf, Direction *dir)
+static void ins_compl_files(int count, char **files, bool thesaurus, int flags,
+ regmatch_T *regmatch, char *buf, Direction *dir)
FUNC_ATTR_NONNULL_ARG(2, 7)
{
for (int i = 0; i < count && !got_int && !compl_interrupted; i++) {
@@ -1442,7 +1490,7 @@ static void ins_compl_files(int count, char **files, int thesaurus, int flags, r
msg_hist_off = true; // reset in msg_trunc()
vim_snprintf(IObuff, IOSIZE,
_("Scanning dictionary: %s"), files[i]);
- (void)msg_trunc(IObuff, true, HL_ATTR(HLF_R));
+ msg_trunc(IObuff, true, HL_ATTR(HLF_R));
}
if (fp == NULL) {
@@ -1549,9 +1597,7 @@ static void ins_compl_free(void)
if (match->cp_flags & CP_FREE_FNAME) {
xfree(match->cp_fname);
}
- for (int i = 0; i < CPT_COUNT; i++) {
- xfree(match->cp_text[i]);
- }
+ free_cptext(match->cp_text);
tv_clear(&match->cp_user_data);
xfree(match);
} while (compl_curr_match != NULL && !is_first_match(compl_curr_match));
@@ -1569,6 +1615,7 @@ void ins_compl_clear(void)
XFREE_CLEAR(compl_pattern);
XFREE_CLEAR(compl_leader);
edit_submode_extra = NULL;
+ kv_destroy(compl_orig_extmarks);
XFREE_CLEAR(compl_orig_text);
compl_enter_selects = false;
// clear v:completed_item
@@ -2019,6 +2066,7 @@ static bool ins_compl_stop(const int c, const int prev_mode, bool retval)
ins_bytes_len(p + compl_len, (size_t)(len - compl_len));
}
}
+ restore_orig_extmarks();
retval = true;
}
@@ -2454,9 +2502,7 @@ static int ins_compl_add_tv(typval_T *const tv, const Direction dir, bool fast)
CLEAR_FIELD(cptext);
}
if (word == NULL || (!empty && *word == NUL)) {
- for (size_t i = 0; i < CPT_COUNT; i++) {
- xfree(cptext[i]);
- }
+ free_cptext(cptext);
tv_clear(&user_data);
return FAIL;
}
@@ -2505,6 +2551,22 @@ static void ins_compl_add_dict(dict_T *dict)
}
}
+/// Save extmarks in "compl_orig_text" so that they may be restored when the
+/// completion is cancelled, or the original text is completed.
+static void save_orig_extmarks(void)
+{
+ extmark_splice_delete(curbuf, curwin->w_cursor.lnum - 1, compl_col, curwin->w_cursor.lnum - 1,
+ compl_col + compl_length, &compl_orig_extmarks, true, kExtmarkUndo);
+}
+
+static void restore_orig_extmarks(void)
+{
+ for (long i = (int)kv_size(compl_orig_extmarks) - 1; i > -1; i--) {
+ ExtmarkUndoObject undo_info = kv_A(compl_orig_extmarks, i);
+ extmark_apply_undo(undo_info, true);
+ }
+}
+
/// Start completion for the complete() function.
///
/// @param startcol where the matched text starts (1 is first column).
@@ -2526,10 +2588,10 @@ static void set_completion(colnr_T startcol, list_T *list)
startcol = curwin->w_cursor.col;
}
compl_col = startcol;
- compl_length = (int)curwin->w_cursor.col - (int)startcol;
+ compl_length = curwin->w_cursor.col - startcol;
// compl_pattern doesn't need to be set
- compl_orig_text = xstrnsave(get_cursor_line_ptr() + compl_col,
- (size_t)compl_length);
+ compl_orig_text = xstrnsave(get_cursor_line_ptr() + compl_col, (size_t)compl_length);
+ save_orig_extmarks();
if (p_ic) {
flags |= CP_ICASE;
}
@@ -2706,9 +2768,11 @@ static int info_add_completion_info(list_T *li)
// Skip the element with the CP_ORIGINAL_TEXT flag at the beginning, in case of
// forward completion, or at the end, in case of backward completion.
- match = forward ? match->cp_next
- : (compl_no_select && match_at_original_text(match)
- ? match->cp_prev : match->cp_prev->cp_prev);
+ match = (forward || match->cp_prev == NULL
+ ? match->cp_next
+ : (compl_no_select && match_at_original_text(match)
+ ? match->cp_prev
+ : match->cp_prev->cp_prev));
while (match != NULL && !match_at_original_text(match)) {
dict_T *di = tv_dict_alloc();
@@ -2790,6 +2854,11 @@ static void get_complete_info(list_T *what_list, dict_T *retdict)
ret = tv_dict_add_nr(retdict, S_LEN("selected"),
(compl_curr_match != NULL)
? compl_curr_match->cp_number - 1 : -1);
+ win_T *wp = win_float_find_preview();
+ if (wp != NULL) {
+ tv_dict_add_nr(retdict, S_LEN("preview_winid"), wp->handle);
+ tv_dict_add_nr(retdict, S_LEN("preview_bufnr"), wp->w_buffer->handle);
+ }
}
(void)ret;
@@ -2903,7 +2972,7 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar
: st->ins_buf->b_sfname == NULL
? st->ins_buf->b_fname
: st->ins_buf->b_sfname);
- (void)msg_trunc(IObuff, true, HL_ATTR(HLF_R));
+ msg_trunc(IObuff, true, HL_ATTR(HLF_R));
}
} else if (*st->e_cpt == NUL) {
status = INS_COMPL_CPT_END;
@@ -2931,12 +3000,12 @@ static int process_next_cpt_value(ins_compl_next_state_T *st, int *compl_type_ar
if (!shortmess(SHM_COMPLETIONSCAN)) {
msg_hist_off = true; // reset in msg_trunc()
vim_snprintf(IObuff, IOSIZE, "%s", _("Scanning tags."));
- (void)msg_trunc(IObuff, true, HL_ATTR(HLF_R));
+ msg_trunc(IObuff, true, HL_ATTR(HLF_R));
}
}
// in any case e_cpt is advanced to the next entry
- (void)copy_option_part(&st->e_cpt, IObuff, IOSIZE, ",");
+ copy_option_part(&st->e_cpt, IObuff, IOSIZE, ",");
st->found_all = true;
if (compl_type == -1) {
@@ -3488,7 +3557,12 @@ void ins_compl_delete(void)
/// "in_compl_func" is true when called from complete_check().
void ins_compl_insert(bool in_compl_func)
{
- ins_bytes(compl_shown_match->cp_str + get_compl_len());
+ int compl_len = get_compl_len();
+ // Make sure we don't go over the end of the string, this can happen with
+ // illegal bytes.
+ if (compl_len < (int)strlen(compl_shown_match->cp_str)) {
+ ins_bytes(compl_shown_match->cp_str + compl_len);
+ }
compl_used_match = !match_at_original_text(compl_shown_match);
dict_T *dict = ins_compl_dict_alloc(compl_shown_match);
@@ -3689,12 +3763,16 @@ static int ins_compl_next(bool allow_get_expansion, int count, bool insert_match
if (compl_no_insert && !started) {
ins_bytes(compl_orig_text + get_compl_len());
compl_used_match = false;
+ restore_orig_extmarks();
} else if (insert_match) {
if (!compl_get_longest || compl_used_match) {
ins_compl_insert(in_compl_func);
} else {
ins_bytes(compl_leader + get_compl_len());
}
+ if (!strcmp(compl_curr_match->cp_str, compl_orig_text)) {
+ restore_orig_extmarks();
+ }
} else {
compl_used_match = false;
}
@@ -3759,8 +3837,8 @@ void ins_compl_check_keys(int frequency, bool in_compl_func)
if (vim_is_ctrl_x_key(c) && c != Ctrl_X && c != Ctrl_R) {
c = safe_vgetc(); // Eat the character
compl_shows_dir = ins_compl_key2dir(c);
- (void)ins_compl_next(false, ins_compl_key2count(c),
- c != K_UP && c != K_DOWN, in_compl_func);
+ ins_compl_next(false, ins_compl_key2count(c),
+ c != K_UP && c != K_DOWN, in_compl_func);
} else {
// Need to get the character to have KeyTyped set. We'll put it
// back with vungetc() below. But skip K_IGNORE.
@@ -3780,7 +3858,7 @@ void ins_compl_check_keys(int frequency, bool in_compl_func)
int todo = compl_pending > 0 ? compl_pending : -compl_pending;
compl_pending = 0;
- (void)ins_compl_next(false, todo, true, in_compl_func);
+ ins_compl_next(false, todo, true, in_compl_func);
}
}
@@ -3882,8 +3960,8 @@ static int get_normal_compl_info(char *line, int startcol, colnr_T curs_col)
prefix = "";
}
STRCPY(compl_pattern, prefix);
- (void)quote_meta(compl_pattern + strlen(prefix),
- line + compl_col, compl_length);
+ quote_meta(compl_pattern + strlen(prefix),
+ line + compl_col, compl_length);
} else if (--startcol < 0
|| !vim_iswordp(mb_prevptr(line, line + startcol + 1))) {
// Match any word of at least two chars
@@ -3910,12 +3988,12 @@ static int get_normal_compl_info(char *line, int startcol, colnr_T curs_col)
// xmalloc(7) is enough -- Acevedo
compl_pattern = xmalloc(7);
STRCPY(compl_pattern, "\\<");
- (void)quote_meta(compl_pattern + 2, line + compl_col, 1);
+ quote_meta(compl_pattern + 2, line + compl_col, 1);
STRCAT(compl_pattern, "\\k");
} else {
compl_pattern = xmalloc(quote_meta(NULL, line + compl_col, compl_length) + 2);
STRCPY(compl_pattern, "\\<");
- (void)quote_meta(compl_pattern + 2, line + compl_col, compl_length);
+ quote_meta(compl_pattern + 2, line + compl_col, compl_length);
}
}
@@ -4267,7 +4345,9 @@ static int ins_compl_start(void)
// Always add completion for the original text.
xfree(compl_orig_text);
+ kv_destroy(compl_orig_extmarks);
compl_orig_text = xstrnsave(line + compl_col, (size_t)compl_length);
+ save_orig_extmarks();
int flags = CP_ORIGINAL_TEXT;
if (p_ic) {
flags |= CP_ICASE;
@@ -4276,6 +4356,7 @@ static int ins_compl_start(void)
flags, false) != OK) {
XFREE_CLEAR(compl_pattern);
XFREE_CLEAR(compl_orig_text);
+ kv_destroy(compl_orig_extmarks);
return FAIL;
}
@@ -4391,7 +4472,7 @@ int ins_complete(int c, bool enable_pum)
// Eat the ESC that vgetc() returns after a CTRL-C to avoid leaving Insert
// mode.
if (got_int && !global_busy) {
- (void)vgetc();
+ vgetc();
got_int = false;
}
@@ -4508,6 +4589,7 @@ static unsigned quote_meta(char *dest, char *src, int len)
void free_insexpand_stuff(void)
{
XFREE_CLEAR(compl_orig_text);
+ kv_destroy(compl_orig_extmarks);
callback_free(&cfu_cb);
callback_free(&ofu_cb);
callback_free(&tsrfu_cb);
diff --git a/src/nvim/insexpand.h b/src/nvim/insexpand.h
index 121d5568ff..b880e64ea4 100644
--- a/src/nvim/insexpand.h
+++ b/src/nvim/insexpand.h
@@ -1,10 +1,9 @@
#pragma once
-#include "nvim/macros_defs.h"
#include "nvim/option_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
-#include "nvim/vim_defs.h"
+#include "nvim/vim_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "insexpand.h.generated.h"
diff --git a/src/nvim/keycodes.c b/src/nvim/keycodes.c
index 745500fe39..44ddfbba00 100644
--- a/src/nvim/keycodes.c
+++ b/src/nvim/keycodes.c
@@ -4,21 +4,22 @@
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include "nvim/ascii_defs.h"
#include "nvim/charset.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/eval/vars.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
+#include "nvim/option_vars.h"
#include "nvim/strings.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -399,7 +400,7 @@ int name_to_mod_mask(int c)
int simplify_key(const int key, int *modifiers)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- if (!(*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL | MOD_MASK_ALT))) {
+ if (!(*modifiers & (MOD_MASK_SHIFT | MOD_MASK_CTRL))) {
return key;
}
@@ -757,17 +758,20 @@ static int extract_modifiers(int key, int *modp, const bool simplify, bool *cons
{
int modifiers = *modp;
- // Command-key and ctrl are special
- if (!(modifiers & MOD_MASK_CMD) && !(modifiers & MOD_MASK_CTRL)) {
- if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key)) {
- key = TOUPPER_ASC(key);
+ if ((modifiers & MOD_MASK_SHIFT) && ASCII_ISALPHA(key)) {
+ key = TOUPPER_ASC(key);
+ // With <C-S-a> we keep the shift modifier.
+ // With <S-a>, <A-S-a> and <S-A> we don't keep the shift modifier.
+ if (!(modifiers & MOD_MASK_CTRL)) {
modifiers &= ~MOD_MASK_SHIFT;
}
}
+
// <C-H> and <C-h> mean the same thing, always use "H"
if ((modifiers & MOD_MASK_CTRL) && ASCII_ISALPHA(key)) {
key = TOUPPER_ASC(key);
}
+
if (simplify && (modifiers & MOD_MASK_CTRL)
&& ((key >= '?' && key <= '_') || ASCII_ISALPHA(key))) {
key = CTRL_CHR(key);
@@ -853,8 +857,8 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag)
/// K_SPECIAL by itself is replaced by K_SPECIAL KS_SPECIAL KE_FILLER.
///
/// When "flags" has REPTERM_FROM_PART, trailing <C-v> is included, otherwise it is removed (to make
-/// ":map xx ^V" map xx to nothing). When cpo_flags contains FLAG_CPO_BSLASH, a backslash can be
-/// used in place of <C-v>. All other <C-v> characters are removed.
+/// ":map xx ^V" map xx to nothing). When cpo_val contains CPO_BSLASH, a backslash can be used in
+/// place of <C-v>. All other <C-v> characters are removed.
///
/// @param[in] from What characters to replace.
/// @param[in] from_len Length of the "from" argument.
@@ -868,20 +872,19 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag)
/// REPTERM_NO_SPECIAL do not accept <key> notation
/// REPTERM_NO_SIMPLIFY do not simplify <C-H> into 0x08, etc.
/// @param[out] did_simplify set when some <C-H> code was simplified, unless it is NULL.
-/// @param[in] cpo_flags Relevant flags derived from p_cpo, see CPO_TO_CPO_FLAGS.
+/// @param[in] cpo_val The value of 'cpoptions' to use. Only CPO_BSLASH matters.
///
/// @return The same as what `*bufp` is set to.
char *replace_termcodes(const char *const from, const size_t from_len, char **const bufp,
const scid_T sid_arg, const int flags, bool *const did_simplify,
- const int cpo_flags)
- FUNC_ATTR_NONNULL_ARG(1, 3)
+ const char *const cpo_val)
+ FUNC_ATTR_NONNULL_ARG(1, 3, 7)
{
- char key;
size_t dlen = 0;
- const char *src;
const char *const end = from + from_len - 1;
- const bool do_backslash = !(cpo_flags & FLAG_CPO_BSLASH); // backslash is a special character
+ // backslash is a special character
+ const bool do_backslash = (vim_strchr(cpo_val, CPO_BSLASH) == NULL);
const bool do_special = !(flags & REPTERM_NO_SPECIAL);
bool allocated = (*bufp == NULL);
@@ -891,7 +894,7 @@ char *replace_termcodes(const char *const from, const size_t from_len, char **co
const size_t buf_len = allocated ? from_len * 6 + 1 : 128;
char *result = allocated ? xmalloc(buf_len) : *bufp; // buffer for resulting string
- src = from;
+ const char *src = from;
// Copy each byte from *from to result[dlen]
while (src <= end) {
@@ -966,7 +969,7 @@ char *replace_termcodes(const char *const from, const size_t from_len, char **co
// For "from" side the CTRL-V at the end is included, for the "to"
// part it is removed.
// If 'cpoptions' does not contain 'B', also accept a backslash.
- key = *src;
+ char key = *src;
if (key == Ctrl_V || (do_backslash && key == '\\')) {
src++; // skip CTRL-V or backslash
if (src > end) {
@@ -1059,7 +1062,8 @@ char *vim_strsave_escape_ks(char *p)
/// vim_strsave_escape_ks(). Works in-place.
void vim_unescape_ks(char *p)
{
- uint8_t *s = (uint8_t *)p, *d = (uint8_t *)p;
+ uint8_t *s = (uint8_t *)p;
+ uint8_t *d = (uint8_t *)p;
while (*s != NUL) {
if (s[0] == K_SPECIAL && s[1] == KS_SPECIAL && s[2] == KE_FILLER) {
diff --git a/src/nvim/keycodes.h b/src/nvim/keycodes.h
index db9ef38cc3..18af3f87d6 100644
--- a/src/nvim/keycodes.h
+++ b/src/nvim/keycodes.h
@@ -1,11 +1,7 @@
#pragma once
-#include <stddef.h>
-
#include "nvim/ascii_defs.h"
-#include "nvim/option_defs.h"
-#include "nvim/option_vars.h"
-#include "nvim/strings.h"
+#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
// Keycode definitions for special keys.
//
@@ -476,11 +472,6 @@ enum key_extra {
/// This is a total of 6 tokens, and is currently the longest one possible.
#define MAX_KEY_CODE_LEN 6
-#define FLAG_CPO_BSLASH 0x01
-#define CPO_TO_CPO_FLAGS ((vim_strchr((char *)p_cpo, CPO_BSLASH) == NULL) \
- ? 0 \
- : FLAG_CPO_BSLASH)
-
/// Flags for replace_termcodes()
enum {
REPTERM_FROM_PART = 1,
diff --git a/src/nvim/lib/queue.h b/src/nvim/lib/queue_defs.h
index 40769e44b5..1f113a057a 100644
--- a/src/nvim/lib/queue.h
+++ b/src/nvim/lib/queue_defs.h
@@ -23,9 +23,9 @@
#include "nvim/func_attr.h"
-typedef struct _queue {
- struct _queue *next;
- struct _queue *prev;
+typedef struct queue {
+ struct queue *next;
+ struct queue *prev;
} QUEUE;
// Public macros.
@@ -44,22 +44,29 @@ typedef struct _queue {
}
// ffi.cdef is unable to swallow `bool` in place of `int` here.
+static inline int QUEUE_EMPTY(const QUEUE *q)
+ REAL_FATTR_ALWAYS_INLINE REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
+
static inline int QUEUE_EMPTY(const QUEUE *const q)
- FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
return q == q->next;
}
#define QUEUE_HEAD(q) (q)->next
-static inline void QUEUE_INIT(QUEUE *const q) FUNC_ATTR_ALWAYS_INLINE
+static inline void QUEUE_INIT(QUEUE *q)
+ REAL_FATTR_ALWAYS_INLINE;
+
+static inline void QUEUE_INIT(QUEUE *const q)
{
q->next = q;
q->prev = q;
}
+static inline void QUEUE_ADD(QUEUE *h, QUEUE *n)
+ REAL_FATTR_ALWAYS_INLINE;
+
static inline void QUEUE_ADD(QUEUE *const h, QUEUE *const n)
- FUNC_ATTR_ALWAYS_INLINE
{
h->prev->next = n->next;
n->next->prev = h->prev;
@@ -67,8 +74,10 @@ static inline void QUEUE_ADD(QUEUE *const h, QUEUE *const n)
h->prev->next = h;
}
+static inline void QUEUE_INSERT_HEAD(QUEUE *h, QUEUE *q)
+ REAL_FATTR_ALWAYS_INLINE;
+
static inline void QUEUE_INSERT_HEAD(QUEUE *const h, QUEUE *const q)
- FUNC_ATTR_ALWAYS_INLINE
{
q->next = h->next;
q->prev = h;
@@ -76,8 +85,10 @@ static inline void QUEUE_INSERT_HEAD(QUEUE *const h, QUEUE *const q)
h->next = q;
}
+static inline void QUEUE_INSERT_TAIL(QUEUE *h, QUEUE *q)
+ REAL_FATTR_ALWAYS_INLINE;
+
static inline void QUEUE_INSERT_TAIL(QUEUE *const h, QUEUE *const q)
- FUNC_ATTR_ALWAYS_INLINE
{
q->next = h;
q->prev = h->prev;
@@ -85,7 +96,10 @@ static inline void QUEUE_INSERT_TAIL(QUEUE *const h, QUEUE *const q)
h->prev = q;
}
-static inline void QUEUE_REMOVE(QUEUE *const q) FUNC_ATTR_ALWAYS_INLINE
+static inline void QUEUE_REMOVE(QUEUE *q)
+ REAL_FATTR_ALWAYS_INLINE;
+
+static inline void QUEUE_REMOVE(QUEUE *const q)
{
q->prev->next = q->next;
q->next->prev = q->prev;
diff --git a/src/nvim/lib/ringbuf.h b/src/nvim/lib/ringbuf.h
deleted file mode 100644
index c8abccfeb4..0000000000
--- a/src/nvim/lib/ringbuf.h
+++ /dev/null
@@ -1,290 +0,0 @@
-/// Macros-based ring buffer implementation.
-///
-/// Supported functions:
-///
-/// - new: allocates new ring buffer.
-/// - dealloc: free ring buffer itself.
-/// - free: free ring buffer and all its elements.
-/// - push: adds element to the end of the buffer.
-/// - length: get buffer length.
-/// - size: size of the ring buffer.
-/// - idx: get element at given index.
-/// - idx_p: get pointer to the element at given index.
-/// - insert: insert element at given position.
-/// - remove: remove element from given position.
-
-#pragma once
-
-#include <assert.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-
-#include "nvim/func_attr.h"
-#include "nvim/memory.h"
-
-#define _RINGBUF_LENGTH(rb) \
- ((rb)->first == NULL ? 0 \
- : ((rb)->next == (rb)->first) ? (size_t)((rb)->buf_end - (rb)->buf) + 1 \
- : ((rb)->next > (rb)->first) ? (size_t)((rb)->next - (rb)->first) \
- : (size_t)((rb)->next - (rb)->buf + (rb)->buf_end - (rb)->first + 1))
-
-#define _RINGBUF_NEXT(rb, var) \
- ((var) == (rb)->buf_end ? (rb)->buf : (var) + 1)
-#define _RINGBUF_PREV(rb, var) \
- ((var) == (rb)->buf ? (rb)->buf_end : (var) - 1)
-
-/// Iterate over all ringbuf values
-///
-/// @param rb Ring buffer to iterate over.
-/// @param RBType Type of the ring buffer element.
-/// @param varname Variable name.
-#define RINGBUF_FORALL(rb, RBType, varname) \
- size_t varname##_length_fa_ = _RINGBUF_LENGTH(rb); \
- for (RBType *varname = ((rb)->first == NULL ? (rb)->next : (rb)->first); \
- varname##_length_fa_; \
- (varname = _RINGBUF_NEXT(rb, varname)), \
- varname##_length_fa_--)
-
-/// Iterate over all ringbuf values, from end to the beginning
-///
-/// Unlike previous RINGBUF_FORALL uses already defined variable, in place of
-/// defining variable in the cycle body.
-///
-/// @param rb Ring buffer to iterate over.
-/// @param RBType Type of the ring buffer element.
-/// @param varname Variable name.
-#define RINGBUF_ITER_BACK(rb, RBType, varname) \
- size_t varname##_length_ib_ = _RINGBUF_LENGTH(rb); \
- for (varname = ((rb)->next == (rb)->buf ? (rb)->buf_end : (rb)->next - 1); \
- varname##_length_ib_; \
- (varname = _RINGBUF_PREV(rb, varname)), \
- varname##_length_ib_--)
-
-/// Define a ring buffer structure
-///
-/// @param TypeName Ring buffer type name. Actual type name will be
-/// `{TypeName}RingBuffer`.
-/// @param RBType Type of the single ring buffer element.
-#define RINGBUF_TYPEDEF(TypeName, RBType) \
- typedef struct { \
- RBType *buf; \
- RBType *next; \
- RBType *first; \
- RBType *buf_end; \
- } TypeName##RingBuffer;
-
-/// Dummy item free macros, for use in RINGBUF_INIT
-///
-/// This macros actually does nothing.
-///
-/// @param[in] item Item to be freed.
-#define RINGBUF_DUMMY_FREE(item)
-
-/// Static ring buffer
-///
-/// @warning Ring buffers created with this macros must neither be freed nor
-/// deallocated.
-///
-/// @param scope Ring buffer scope.
-/// @param TypeName Ring buffer type name.
-/// @param RBType Type of the single ring buffer element.
-/// @param varname Variable name.
-/// @param rbsize Ring buffer size.
-#define RINGBUF_STATIC(scope, TypeName, RBType, varname, rbsize) \
- static RBType _##varname##_buf[rbsize]; \
- scope TypeName##RingBuffer varname = { \
- .buf = _##varname##_buf, \
- .next = _##varname##_buf, \
- .first = NULL, \
- .buf_end = _##varname##_buf + rbsize - 1, \
- };
-
-/// Initialize a new ring buffer
-///
-/// @param TypeName Ring buffer type name. Actual type name will be
-/// `{TypeName}RingBuffer`.
-/// @param funcprefix Prefix for all ring buffer functions. Function name will
-/// look like `{funcprefix}_rb_{function_name}`.
-/// @param RBType Type of the single ring buffer element.
-/// @param rbfree Function used to free ring buffer element. May be
-/// a macros like `#define RBFREE(item)` (to skip freeing).
-///
-/// Intended function signature: `void *rbfree(RBType *)`;
-#define RINGBUF_INIT(TypeName, funcprefix, RBType, rbfree) \
- static inline TypeName##RingBuffer funcprefix##_rb_new(const size_t size) \
- REAL_FATTR_WARN_UNUSED_RESULT; \
- static inline TypeName##RingBuffer funcprefix##_rb_new(const size_t size) \
- { \
- assert(size != 0); \
- RBType *buf = xmalloc(size * sizeof(RBType)); \
- return (TypeName##RingBuffer) { \
- .buf = buf, \
- .next = buf, \
- .first = NULL, \
- .buf_end = buf + size - 1, \
- }; \
- } \
- static inline void funcprefix##_rb_free(TypeName##RingBuffer *const rb) \
- REAL_FATTR_UNUSED; \
- static inline void funcprefix##_rb_free(TypeName##RingBuffer *const rb) \
- { \
- if (rb == NULL) { \
- return; \
- } \
- RINGBUF_FORALL(rb, RBType, rbitem) { \
- rbfree(rbitem); \
- } \
- XFREE_CLEAR(rb->buf); \
- } \
- static inline void funcprefix##_rb_dealloc(TypeName##RingBuffer *const rb) \
- REAL_FATTR_UNUSED; \
- static inline void funcprefix##_rb_dealloc(TypeName##RingBuffer *const rb) \
- { \
- XFREE_CLEAR(rb->buf); \
- } \
- static inline void funcprefix##_rb_push(TypeName##RingBuffer *const rb, \
- RBType item) \
- REAL_FATTR_NONNULL_ARG(1); \
- static inline void funcprefix##_rb_push(TypeName##RingBuffer *const rb, \
- RBType item) \
- { \
- if (rb->next == rb->first) { \
- rbfree(rb->first); \
- rb->first = _RINGBUF_NEXT(rb, rb->first); \
- } else if (rb->first == NULL) { \
- rb->first = rb->next; \
- } \
- *rb->next = item; \
- rb->next = _RINGBUF_NEXT(rb, rb->next); \
- } \
- static inline ptrdiff_t funcprefix##_rb_find_idx(const TypeName##RingBuffer *const rb, \
- const RBType *const item_p) \
- REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE REAL_FATTR_UNUSED; \
- static inline ptrdiff_t funcprefix##_rb_find_idx(const TypeName##RingBuffer *const rb, \
- const RBType *const item_p) \
- { \
- assert(rb->buf <= item_p); \
- assert(rb->buf_end >= item_p); \
- if (rb->first == NULL) { \
- return -1; \
- } else if (item_p >= rb->first) { \
- return item_p - rb->first; \
- } else { \
- return item_p - rb->buf + rb->buf_end - rb->first + 1; \
- } \
- } \
- static inline size_t funcprefix##_rb_size(const TypeName##RingBuffer *const rb) \
- REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE; \
- static inline size_t funcprefix##_rb_size(const TypeName##RingBuffer *const rb) \
- { \
- return (size_t)(rb->buf_end - rb->buf) + 1; \
- } \
- static inline size_t funcprefix##_rb_length(const TypeName##RingBuffer *const rb) \
- REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE; \
- static inline size_t funcprefix##_rb_length(const TypeName##RingBuffer *const rb) \
- { \
- return _RINGBUF_LENGTH(rb); \
- } \
- static inline RBType *funcprefix##_rb_idx_p(const TypeName##RingBuffer *const rb, \
- const size_t idx) \
- REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE; \
- static inline RBType *funcprefix##_rb_idx_p(const TypeName##RingBuffer *const rb, \
- const size_t idx) \
- { \
- assert(idx <= funcprefix##_rb_size(rb)); \
- assert(idx <= funcprefix##_rb_length(rb)); \
- if (rb->first + idx > rb->buf_end) { \
- return rb->buf + ((rb->first + idx) - (rb->buf_end + 1)); \
- } else { \
- return rb->first + idx; \
- } \
- } \
- static inline RBType funcprefix##_rb_idx(const TypeName##RingBuffer *const rb, \
- const size_t idx) \
- REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE REAL_FATTR_UNUSED; \
- static inline RBType funcprefix##_rb_idx(const TypeName##RingBuffer *const rb, \
- const size_t idx) \
- { \
- return *funcprefix##_rb_idx_p(rb, idx); \
- } \
- static inline void funcprefix##_rb_insert(TypeName##RingBuffer *const rb, \
- const size_t idx, \
- RBType item) \
- REAL_FATTR_NONNULL_ARG(1) REAL_FATTR_UNUSED; \
- static inline void funcprefix##_rb_insert(TypeName##RingBuffer *const rb, \
- const size_t idx, \
- RBType item) \
- { \
- assert(idx <= funcprefix##_rb_size(rb)); \
- assert(idx <= funcprefix##_rb_length(rb)); \
- const size_t length = funcprefix##_rb_length(rb); \
- if (idx == length) { \
- funcprefix##_rb_push(rb, item); \
- return; \
- } \
- RBType *const insertpos = funcprefix##_rb_idx_p(rb, idx); \
- if (insertpos == rb->next) { \
- funcprefix##_rb_push(rb, item); \
- return; \
- } \
- if (length == funcprefix##_rb_size(rb)) { \
- rbfree(rb->first); \
- } \
- if (insertpos < rb->next) { \
- memmove(insertpos + 1, insertpos, \
- (size_t)((uintptr_t)rb->next - (uintptr_t)insertpos)); \
- } else { \
- assert(insertpos > rb->first); \
- assert(rb->next <= rb->first); \
- memmove(rb->buf + 1, rb->buf, \
- (size_t)((uintptr_t)rb->next - (uintptr_t)rb->buf)); \
- *rb->buf = *rb->buf_end; \
- memmove(insertpos + 1, insertpos, \
- (size_t)((uintptr_t)(rb->buf_end + 1) - (uintptr_t)insertpos)); \
- } \
- *insertpos = item; \
- if (length == funcprefix##_rb_size(rb)) { \
- rb->first = _RINGBUF_NEXT(rb, rb->first); \
- } \
- rb->next = _RINGBUF_NEXT(rb, rb->next); \
- } \
- static inline void funcprefix##_rb_remove(TypeName##RingBuffer *const rb, \
- const size_t idx) \
- REAL_FATTR_NONNULL_ARG(1) REAL_FATTR_UNUSED; \
- static inline void funcprefix##_rb_remove(TypeName##RingBuffer *const rb, \
- const size_t idx) \
- { \
- assert(idx < funcprefix##_rb_size(rb)); \
- assert(idx < funcprefix##_rb_length(rb)); \
- RBType *const rmpos = funcprefix##_rb_idx_p(rb, idx); \
- rbfree(rmpos); \
- if (rmpos == rb->next - 1) { \
- rb->next--; \
- if (rb->first == rb->next) { \
- rb->first = NULL; \
- rb->next = rb->buf; \
- } \
- } else if (rmpos == rb->first) { \
- rb->first = _RINGBUF_NEXT(rb, rb->first); \
- if (rb->first == rb->next) { \
- rb->first = NULL; \
- rb->next = rb->buf; \
- } \
- } else if (rb->first < rb->next || rb->next == rb->buf) { \
- assert(rmpos > rb->first); \
- assert(rmpos <= _RINGBUF_PREV(rb, rb->next)); \
- memmove(rb->first + 1, rb->first, \
- (size_t)((uintptr_t)rmpos - (uintptr_t)rb->first)); \
- rb->first = _RINGBUF_NEXT(rb, rb->first); \
- } else if (rmpos < rb->next) { \
- memmove(rmpos, rmpos + 1, \
- (size_t)((uintptr_t)rb->next - (uintptr_t)rmpos)); \
- rb->next = _RINGBUF_PREV(rb, rb->next); \
- } else { \
- assert(rb->first < rb->buf_end); \
- memmove(rb->first + 1, rb->first, \
- (size_t)((uintptr_t)rmpos - (uintptr_t)rb->first)); \
- rb->first = _RINGBUF_NEXT(rb, rb->first); \
- } \
- }
diff --git a/src/nvim/log.c b/src/nvim/log.c
index aeee088cd3..fbb3e0385a 100644
--- a/src/nvim/log.c
+++ b/src/nvim/log.c
@@ -19,13 +19,13 @@
#include "auto/config.h"
#include "nvim/ascii_defs.h"
#include "nvim/eval.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/os/fs.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/stdpaths_defs.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
@@ -296,7 +296,7 @@ static bool v_do_log_to_file(FILE *log_file, int log_level, const char *context,
FUNC_ATTR_PRINTF(7, 0)
{
// Name of the Nvim instance that produced the log.
- static char name[16] = { 0 };
+ static char name[32] = { 0 };
static const char *log_levels[] = {
[LOGLVL_DBG] = "DBG",
diff --git a/src/nvim/log.h b/src/nvim/log.h
index cac074d146..1fb15e3503 100644
--- a/src/nvim/log.h
+++ b/src/nvim/log.h
@@ -9,13 +9,19 @@
// USDT probes. Example invocation:
// NVIM_PROBE(nvim_foo_bar, 1, string.data);
#if defined(HAVE_SYS_SDT_H)
-# include <sys/sdt.h> // NOLINT
+# include <sys/sdt.h> // IWYU pragma: keep
# define NVIM_PROBE(name, n, ...) STAP_PROBE##n(neovim, name, __VA_ARGS__)
#else
# define NVIM_PROBE(name, n, ...)
#endif
+// uncrustify:off
+#if NVIM_HAS_INCLUDE(<sanitizer/asan_interface.h>)
+# include <sanitizer/asan_interface.h> // IWYU pragma: keep
+#endif
+// uncrustify:on
+
#define LOGLVL_DBG 1
#define LOGLVL_INF 2
#define LOGLVL_WRN 3
@@ -45,10 +51,6 @@
# define LOG_CALLSTACK_TO_FILE(fp) log_callstack_to_file(fp, __func__, __LINE__)
#endif
-#if NVIM_HAS_INCLUDE("sanitizer/asan_interface.h")
-# include "sanitizer/asan_interface.h"
-#endif
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "log.h.generated.h"
#endif
diff --git a/src/nvim/lua/converter.c b/src/nvim/lua/converter.c
index 4598d48c4a..bba771f8a5 100644
--- a/src/nvim/lua/converter.c
+++ b/src/nvim/lua/converter.c
@@ -16,8 +16,8 @@
#include "nvim/eval/typval_defs.h"
#include "nvim/eval/typval_encode.h"
#include "nvim/eval/userfunc.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
+#include "nvim/highlight_group.h"
#include "nvim/lua/converter.h"
#include "nvim/lua/executor.h"
#include "nvim/macros_defs.h"
@@ -149,7 +149,7 @@ static LuaTableProps nlua_traverse_table(lua_State *const lstate)
}
} else {
if (tsize == 0
- || (tsize == ret.maxidx
+ || (tsize <= ret.maxidx
&& other_keys_num == 0
&& ret.string_keys_num == 0)) {
ret.type = kObjectTypeArray;
@@ -171,11 +171,12 @@ static LuaTableProps nlua_traverse_table(lua_State *const lstate)
/// Helper structure for nlua_pop_typval
typedef struct {
- typval_T *tv; ///< Location where conversion result is saved.
- bool container; ///< True if tv is a container.
- bool special; ///< If true then tv is a _VAL part of special dictionary
- ///< that represents mapping.
- int idx; ///< Container index (used to detect self-referencing structures).
+ typval_T *tv; ///< Location where conversion result is saved.
+ size_t list_len; ///< Maximum length when tv is a list.
+ bool container; ///< True if tv is a container.
+ bool special; ///< If true then tv is a _VAL part of special dictionary
+ ///< that represents mapping.
+ int idx; ///< Container index (used to detect self-referencing structures).
} TVPopStackItem;
/// Convert lua object to Vimscript typval_T
@@ -193,7 +194,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
const int initial_size = lua_gettop(lstate);
kvec_withinit_t(TVPopStackItem, 2) stack = KV_INITIAL_VALUE;
kvi_init(stack);
- kvi_push(stack, ((TVPopStackItem) { ret_tv, false, false, 0 }));
+ kvi_push(stack, ((TVPopStackItem){ .tv = ret_tv }));
while (ret && kv_size(stack)) {
if (!lua_checkstack(lstate, lua_gettop(lstate) + 3)) {
semsg(_("E1502: Lua failed to grow stack to %i"), lua_gettop(lstate) + 3);
@@ -232,19 +233,14 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
});
kvi_push(stack, cur);
tv_list_append_list(cur.tv->vval.v_list, kv_pair);
- cur = (TVPopStackItem) {
- .tv = TV_LIST_ITEM_TV(tv_list_last(kv_pair)),
- .container = false,
- .special = false,
- .idx = 0,
- };
+ cur = (TVPopStackItem){ .tv = TV_LIST_ITEM_TV(tv_list_last(kv_pair)) };
} else {
dictitem_T *const di = tv_dict_item_alloc_len(s, len);
if (tv_dict_add(cur.tv->vval.v_dict, di) == FAIL) {
abort();
}
kvi_push(stack, cur);
- cur = (TVPopStackItem) { &di->di_tv, false, false, 0 };
+ cur = (TVPopStackItem){ .tv = &di->di_tv };
}
} else {
lua_pop(lstate, 1);
@@ -252,23 +248,18 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
}
} else {
assert(cur.tv->v_type == VAR_LIST);
- lua_rawgeti(lstate, -1, tv_list_len(cur.tv->vval.v_list) + 1);
- if (lua_isnil(lstate, -1)) {
- lua_pop(lstate, 2);
+ if ((size_t)tv_list_len(cur.tv->vval.v_list) == cur.list_len) {
+ lua_pop(lstate, 1);
continue;
}
+ lua_rawgeti(lstate, -1, tv_list_len(cur.tv->vval.v_list) + 1);
// Not populated yet, need to create list item to push.
tv_list_append_owned_tv(cur.tv->vval.v_list, (typval_T) {
.v_type = VAR_UNKNOWN,
});
kvi_push(stack, cur);
// TODO(ZyX-I): Use indexes, here list item *will* be reallocated.
- cur = (TVPopStackItem) {
- .tv = TV_LIST_ITEM_TV(tv_list_last(cur.tv->vval.v_list)),
- .container = false,
- .special = false,
- .idx = 0,
- };
+ cur = (TVPopStackItem){ .tv = TV_LIST_ITEM_TV(tv_list_last(cur.tv->vval.v_list)) };
}
}
assert(!cur.container);
@@ -332,6 +323,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
cur.tv->vval.v_list = tv_list_alloc((ptrdiff_t)table_props.maxidx);
cur.tv->vval.v_list->lua_table_ref = table_ref;
tv_list_ref(cur.tv->vval.v_list);
+ cur.list_len = table_props.maxidx;
if (table_props.maxidx != 0) {
cur.container = true;
cur.idx = lua_gettop(lstate);
@@ -355,6 +347,7 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
cur.tv = &val_di->di_tv;
cur.tv->vval.v_list->lua_table_ref = table_ref;
assert(cur.tv->v_type == VAR_LIST);
+ cur.list_len = table_props.string_keys_num;
} else {
cur.tv->v_type = VAR_DICT;
cur.tv->vval.v_dict = tv_dict_alloc();
@@ -372,9 +365,8 @@ bool nlua_pop_typval(lua_State *lstate, typval_T *ret_tv)
cur.tv->vval.v_float = (float_T)table_props.val;
break;
case kObjectTypeNil:
- emsg(_("E5100: Cannot convert given lua table: table "
- "should either have a sequence of positive integer keys "
- "or contain only string keys"));
+ emsg(_("E5100: Cannot convert given lua table: table should "
+ "contain either only integer keys or only string keys"));
ret = false;
break;
default:
@@ -727,7 +719,7 @@ void nlua_push_Dictionary(lua_State *lstate, const Dictionary dict, bool special
}
for (size_t i = 0; i < dict.size; i++) {
nlua_push_String(lstate, dict.items[i].key, special);
- nlua_push_Object(lstate, dict.items[i].value, special);
+ nlua_push_Object(lstate, &dict.items[i].value, special);
lua_rawset(lstate, -3);
}
}
@@ -740,7 +732,7 @@ void nlua_push_Array(lua_State *lstate, const Array array, bool special)
{
lua_createtable(lstate, (int)array.size, 0);
for (size_t i = 0; i < array.size; i++) {
- nlua_push_Object(lstate, array.items[i], special);
+ nlua_push_Object(lstate, &array.items[i], special);
lua_rawseti(lstate, -2, (int)i + 1);
}
}
@@ -761,10 +753,10 @@ GENERATE_INDEX_FUNCTION(Tabpage)
/// Convert given Object to lua value
///
/// Leaves converted value on top of the stack.
-void nlua_push_Object(lua_State *lstate, const Object obj, bool special)
+void nlua_push_Object(lua_State *lstate, Object *obj, bool special)
FUNC_ATTR_NONNULL_ALL
{
- switch (obj.type) {
+ switch (obj->type) {
case kObjectTypeNil:
if (special) {
lua_pushnil(lstate);
@@ -773,12 +765,14 @@ void nlua_push_Object(lua_State *lstate, const Object obj, bool special)
}
break;
case kObjectTypeLuaRef: {
- nlua_pushref(lstate, obj.data.luaref);
+ nlua_pushref(lstate, obj->data.luaref);
+ api_free_luaref(obj->data.luaref);
+ obj->data.luaref = LUA_NOREF;
break;
}
#define ADD_TYPE(type, data_key) \
case kObjectType##type: { \
- nlua_push_##type(lstate, obj.data.data_key, special); \
+ nlua_push_##type(lstate, obj->data.data_key, special); \
break; \
}
ADD_TYPE(Boolean, boolean)
@@ -790,7 +784,7 @@ void nlua_push_Object(lua_State *lstate, const Object obj, bool special)
#undef ADD_TYPE
#define ADD_REMOTE_TYPE(type) \
case kObjectType##type: { \
- nlua_push_##type(lstate, (type)obj.data.integer, special); \
+ nlua_push_##type(lstate, (type)obj->data.integer, special); \
break; \
}
ADD_REMOTE_TYPE(Buffer)
@@ -803,8 +797,8 @@ void nlua_push_Object(lua_State *lstate, const Object obj, bool special)
/// Convert lua value to string
///
/// Always pops one value from the stack.
-String nlua_pop_String(lua_State *lstate, Error *err)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+String nlua_pop_String(lua_State *lstate, Arena *arena, Error *err)
+ FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT
{
if (lua_type(lstate, -1) != LUA_TSTRING) {
lua_pop(lstate, 1);
@@ -815,7 +809,10 @@ String nlua_pop_String(lua_State *lstate, Error *err)
ret.data = (char *)lua_tolstring(lstate, -1, &(ret.size));
assert(ret.data != NULL);
- ret.data = xmemdupz(ret.data, ret.size);
+ // TODO(bfredl): it would be "nice" to just use the memory of the lua string
+ // directly, although ensuring the lifetime of such strings is a bit tricky
+ // (an API call could invoke nested lua, which triggers GC, and kaboom?)
+ ret.data = arena_memdupz(arena, ret.data, ret.size);
lua_pop(lstate, 1);
return ret;
@@ -824,8 +821,8 @@ String nlua_pop_String(lua_State *lstate, Error *err)
/// Convert lua value to integer
///
/// Always pops one value from the stack.
-Integer nlua_pop_Integer(lua_State *lstate, Error *err)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+Integer nlua_pop_Integer(lua_State *lstate, Arena *arena, Error *err)
+ FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT
{
if (lua_type(lstate, -1) != LUA_TNUMBER) {
lua_pop(lstate, 1);
@@ -848,8 +845,8 @@ Integer nlua_pop_Integer(lua_State *lstate, Error *err)
/// thus `err` is never set as any lua value can be co-erced into a lua bool
///
/// Always pops one value from the stack.
-Boolean nlua_pop_Boolean(lua_State *lstate, Error *err)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+Boolean nlua_pop_Boolean(lua_State *lstate, Arena *arena, Error *err)
+ FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT
{
const Boolean ret = lua_toboolean(lstate, -1);
lua_pop(lstate, 1);
@@ -923,7 +920,7 @@ static inline LuaTableProps nlua_check_type(lua_State *const lstate, Error *cons
/// Convert lua table to float
///
/// Always pops one value from the stack.
-Float nlua_pop_Float(lua_State *lstate, Error *err)
+Float nlua_pop_Float(lua_State *lstate, Arena *arena, Error *err)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
if (lua_type(lstate, -1) == LUA_TNUMBER) {
@@ -947,29 +944,29 @@ Float nlua_pop_Float(lua_State *lstate, Error *err)
/// @param[in] table_props nlua_traverse_table() output.
/// @param[out] err Location where error will be saved.
static Array nlua_pop_Array_unchecked(lua_State *const lstate, const LuaTableProps table_props,
- Error *const err)
+ Arena *arena, Error *const err)
{
- Array ret = { .size = table_props.maxidx, .items = NULL };
+ Array ret = arena_array(arena, table_props.maxidx);
- if (ret.size == 0) {
+ if (table_props.maxidx == 0) {
lua_pop(lstate, 1);
return ret;
}
- ret.items = xcalloc(ret.size, sizeof(*ret.items));
- for (size_t i = 1; i <= ret.size; i++) {
+ for (size_t i = 1; i <= table_props.maxidx; i++) {
Object val;
lua_rawgeti(lstate, -1, (int)i);
- val = nlua_pop_Object(lstate, false, err);
+ val = nlua_pop_Object(lstate, false, arena, err);
if (ERROR_SET(err)) {
- ret.size = i - 1;
lua_pop(lstate, 1);
- api_free_array(ret);
+ if (!arena) {
+ api_free_array(ret);
+ }
return (Array) { .size = 0, .items = NULL };
}
- ret.items[i - 1] = val;
+ ADD_C(ret, val);
}
lua_pop(lstate, 1);
@@ -979,15 +976,14 @@ static Array nlua_pop_Array_unchecked(lua_State *const lstate, const LuaTablePro
/// Convert lua table to array
///
/// Always pops one value from the stack.
-Array nlua_pop_Array(lua_State *lstate, Error *err)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+Array nlua_pop_Array(lua_State *lstate, Arena *arena, Error *err)
+ FUNC_ATTR_NONNULL_ARG(1, 3) FUNC_ATTR_WARN_UNUSED_RESULT
{
- const LuaTableProps table_props = nlua_check_type(lstate, err,
- kObjectTypeArray);
+ const LuaTableProps table_props = nlua_check_type(lstate, err, kObjectTypeArray);
if (table_props.type != kObjectTypeArray) {
return (Array) { .size = 0, .items = NULL };
}
- return nlua_pop_Array_unchecked(lstate, table_props, err);
+ return nlua_pop_Array_unchecked(lstate, table_props, arena, err);
}
/// Convert lua table to dictionary
@@ -999,30 +995,30 @@ Array nlua_pop_Array(lua_State *lstate, Error *err)
/// @param[in] table_props nlua_traverse_table() output.
/// @param[out] err Location where error will be saved.
static Dictionary nlua_pop_Dictionary_unchecked(lua_State *lstate, const LuaTableProps table_props,
- bool ref, Error *err)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+ bool ref, Arena *arena, Error *err)
+ FUNC_ATTR_NONNULL_ARG(1, 5) FUNC_ATTR_WARN_UNUSED_RESULT
{
- Dictionary ret = { .size = table_props.string_keys_num, .items = NULL };
+ Dictionary ret = arena_dict(arena, table_props.string_keys_num);
- if (ret.size == 0) {
+ if (table_props.string_keys_num == 0) {
lua_pop(lstate, 1);
return ret;
}
- ret.items = xcalloc(ret.size, sizeof(*ret.items));
lua_pushnil(lstate);
- for (size_t i = 0; lua_next(lstate, -2) && i < ret.size;) {
+ for (size_t i = 0; lua_next(lstate, -2) && i < table_props.string_keys_num;) {
// stack: dict, key, value
if (lua_type(lstate, -2) == LUA_TSTRING) {
lua_pushvalue(lstate, -2);
// stack: dict, key, value, key
- ret.items[i].key = nlua_pop_String(lstate, err);
+ String key = nlua_pop_String(lstate, arena, err);
// stack: dict, key, value
if (!ERROR_SET(err)) {
- ret.items[i].value = nlua_pop_Object(lstate, ref, err);
+ Object value = nlua_pop_Object(lstate, ref, arena, err);
+ kv_push_c(ret, ((KeyValuePair) { .key = key, .value = value }));
// stack: dict, key
} else {
lua_pop(lstate, 1);
@@ -1030,8 +1026,9 @@ static Dictionary nlua_pop_Dictionary_unchecked(lua_State *lstate, const LuaTabl
}
if (ERROR_SET(err)) {
- ret.size = i;
- api_free_dictionary(ret);
+ if (!arena) {
+ api_free_dictionary(ret);
+ }
lua_pop(lstate, 2);
// stack:
return (Dictionary) { .size = 0, .items = NULL };
@@ -1050,8 +1047,8 @@ static Dictionary nlua_pop_Dictionary_unchecked(lua_State *lstate, const LuaTabl
/// Convert lua table to dictionary
///
/// Always pops one value from the stack.
-Dictionary nlua_pop_Dictionary(lua_State *lstate, bool ref, Error *err)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+Dictionary nlua_pop_Dictionary(lua_State *lstate, bool ref, Arena *arena, Error *err)
+ FUNC_ATTR_NONNULL_ARG(1, 4) FUNC_ATTR_WARN_UNUSED_RESULT
{
const LuaTableProps table_props = nlua_check_type(lstate, err,
kObjectTypeDictionary);
@@ -1060,7 +1057,7 @@ Dictionary nlua_pop_Dictionary(lua_State *lstate, bool ref, Error *err)
return (Dictionary) { .size = 0, .items = NULL };
}
- return nlua_pop_Dictionary_unchecked(lstate, table_props, ref, err);
+ return nlua_pop_Dictionary_unchecked(lstate, table_props, ref, arena, err);
}
/// Helper structure for nlua_pop_Object
@@ -1072,13 +1069,14 @@ typedef struct {
/// Convert lua table to object
///
/// Always pops one value from the stack.
-Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
+Object nlua_pop_Object(lua_State *const lstate, bool ref, Arena *arena, Error *const err)
+ FUNC_ATTR_NONNULL_ARG(1, 4) FUNC_ATTR_WARN_UNUSED_RESULT
{
Object ret = NIL;
const int initial_size = lua_gettop(lstate);
kvec_withinit_t(ObjPopStackItem, 2) stack = KV_INITIAL_VALUE;
kvi_init(stack);
- kvi_push(stack, ((ObjPopStackItem) { &ret, false }));
+ kvi_push(stack, ((ObjPopStackItem){ .obj = &ret }));
while (!ERROR_SET(err) && kv_size(stack)) {
ObjPopStackItem cur = kv_pop(stack);
if (cur.container) {
@@ -1088,8 +1086,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
}
if (cur.obj->type == kObjectTypeDictionary) {
// stack: …, dict, key
- if (cur.obj->data.dictionary.size
- == cur.obj->data.dictionary.capacity) {
+ if (cur.obj->data.dictionary.size == cur.obj->data.dictionary.capacity) {
lua_pop(lstate, 2);
continue;
}
@@ -1108,15 +1105,9 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
size_t len;
const char *s = lua_tolstring(lstate, -2, &len);
const size_t idx = cur.obj->data.dictionary.size++;
- cur.obj->data.dictionary.items[idx].key = (String) {
- .data = xmemdupz(s, len),
- .size = len,
- };
+ cur.obj->data.dictionary.items[idx].key = CBUF_TO_ARENA_STR(arena, s, len);
kvi_push(stack, cur);
- cur = (ObjPopStackItem) {
- .obj = &cur.obj->data.dictionary.items[idx].value,
- .container = false,
- };
+ cur = (ObjPopStackItem){ .obj = &cur.obj->data.dictionary.items[idx].value };
} else {
// stack: …, dict
lua_pop(lstate, 1);
@@ -1130,15 +1121,8 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
}
const size_t idx = cur.obj->data.array.size++;
lua_rawgeti(lstate, -1, (int)idx + 1);
- if (lua_isnil(lstate, -1)) {
- lua_pop(lstate, 2);
- continue;
- }
kvi_push(stack, cur);
- cur = (ObjPopStackItem) {
- .obj = &cur.obj->data.array.items[idx],
- .container = false,
- };
+ cur = (ObjPopStackItem){ .obj = &cur.obj->data.array.items[idx] };
}
}
assert(!cur.container);
@@ -1152,7 +1136,7 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
case LUA_TSTRING: {
size_t len;
const char *s = lua_tolstring(lstate, -1, &len);
- *cur.obj = STRING_OBJ(((String) { .data = xmemdupz(s, len), .size = len }));
+ *cur.obj = STRING_OBJ(CBUF_TO_ARENA_STR(arena, s, len));
break;
}
case LUA_TNUMBER: {
@@ -1170,23 +1154,17 @@ Object nlua_pop_Object(lua_State *const lstate, bool ref, Error *const err)
switch (table_props.type) {
case kObjectTypeArray:
- *cur.obj = ARRAY_OBJ(((Array) { .items = NULL, .size = 0, .capacity = 0 }));
+ *cur.obj = ARRAY_OBJ(((Array)ARRAY_DICT_INIT));
if (table_props.maxidx != 0) {
- cur.obj->data.array.items =
- xcalloc(table_props.maxidx,
- sizeof(cur.obj->data.array.items[0]));
- cur.obj->data.array.capacity = table_props.maxidx;
+ cur.obj->data.array = arena_array(arena, table_props.maxidx);
cur.container = true;
kvi_push(stack, cur);
}
break;
case kObjectTypeDictionary:
- *cur.obj = DICTIONARY_OBJ(((Dictionary) { .items = NULL, .size = 0, .capacity = 0 }));
+ *cur.obj = DICTIONARY_OBJ(((Dictionary)ARRAY_DICT_INIT));
if (table_props.string_keys_num != 0) {
- cur.obj->data.dictionary.items =
- xcalloc(table_props.string_keys_num,
- sizeof(cur.obj->data.dictionary.items[0]));
- cur.obj->data.dictionary.capacity = table_props.string_keys_num;
+ cur.obj->data.dictionary = arena_dict(arena, table_props.string_keys_num);
cur.container = true;
kvi_push(stack, cur);
lua_pushnil(lstate);
@@ -1238,7 +1216,9 @@ type_error:
}
kvi_destroy(stack);
if (ERROR_SET(err)) {
- api_free_object(ret);
+ if (!arena) {
+ api_free_object(ret);
+ }
ret = NIL;
lua_pop(lstate, lua_gettop(lstate) - initial_size + 1);
}
@@ -1246,20 +1226,20 @@ type_error:
return ret;
}
-LuaRef nlua_pop_LuaRef(lua_State *const lstate, Error *err)
+LuaRef nlua_pop_LuaRef(lua_State *const lstate, Arena *arena, Error *err)
{
LuaRef rv = nlua_ref_global(lstate, -1);
lua_pop(lstate, 1);
return rv;
}
-handle_T nlua_pop_handle(lua_State *lstate, Error *err)
+handle_T nlua_pop_handle(lua_State *lstate, Arena *arena, Error *err)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
handle_T ret;
if (lua_type(lstate, -1) != LUA_TNUMBER) {
api_set_error(err, kErrorTypeValidation, "Expected Lua number");
- ret = (handle_T) - 1;
+ ret = (handle_T)(-1);
} else {
ret = (handle_T)lua_tonumber(lstate, -1);
}
@@ -1315,7 +1295,8 @@ void nlua_init_types(lua_State *const lstate)
}
// lua specific variant of api_dict_to_keydict
-void nlua_pop_keydict(lua_State *L, void *retval, FieldHashfn hashy, char **err_opt, Error *err)
+void nlua_pop_keydict(lua_State *L, void *retval, FieldHashfn hashy, char **err_opt, Arena *arena,
+ Error *err)
{
if (!lua_istable(L, -1)) {
api_set_error(err, kErrorTypeValidation, "Expected Lua table");
@@ -1342,24 +1323,31 @@ void nlua_pop_keydict(lua_State *L, void *retval, FieldHashfn hashy, char **err_
char *mem = ((char *)retval + field->ptr_off);
if (field->type == kObjectTypeNil) {
- *(Object *)mem = nlua_pop_Object(L, true, err);
+ *(Object *)mem = nlua_pop_Object(L, true, arena, err);
} else if (field->type == kObjectTypeInteger) {
- *(Integer *)mem = nlua_pop_Integer(L, err);
+ if (field->is_hlgroup && lua_type(L, -1) == LUA_TSTRING) {
+ size_t name_len;
+ const char *name = lua_tolstring(L, -1, &name_len);
+ lua_pop(L, 1);
+ *(Integer *)mem = name_len > 0 ? syn_check_group(name, name_len) : 0;
+ } else {
+ *(Integer *)mem = nlua_pop_Integer(L, arena, err);
+ }
} else if (field->type == kObjectTypeBoolean) {
*(Boolean *)mem = nlua_pop_Boolean_strict(L, err);
} else if (field->type == kObjectTypeString) {
- *(String *)mem = nlua_pop_String(L, err);
+ *(String *)mem = nlua_pop_String(L, arena, err);
} else if (field->type == kObjectTypeFloat) {
- *(Float *)mem = nlua_pop_Float(L, err);
+ *(Float *)mem = nlua_pop_Float(L, arena, err);
} else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow
|| field->type == kObjectTypeTabpage) {
- *(handle_T *)mem = nlua_pop_handle(L, err);
+ *(handle_T *)mem = nlua_pop_handle(L, arena, err);
} else if (field->type == kObjectTypeArray) {
- *(Array *)mem = nlua_pop_Array(L, err);
+ *(Array *)mem = nlua_pop_Array(L, arena, err);
} else if (field->type == kObjectTypeDictionary) {
- *(Dictionary *)mem = nlua_pop_Dictionary(L, false, err);
+ *(Dictionary *)mem = nlua_pop_Dictionary(L, false, arena, err);
} else if (field->type == kObjectTypeLuaRef) {
- *(LuaRef *)mem = nlua_pop_LuaRef(L, err);
+ *(LuaRef *)mem = nlua_pop_LuaRef(L, arena, err);
} else {
abort();
}
@@ -1372,3 +1360,48 @@ void nlua_pop_keydict(lua_State *L, void *retval, FieldHashfn hashy, char **err_
lua_pop(L, 1);
// []
}
+
+void nlua_push_keydict(lua_State *L, void *value, KeySetLink *table)
+{
+ lua_createtable(L, 0, 0);
+ for (size_t i = 0; table[i].str; i++) {
+ KeySetLink *field = &table[i];
+ bool is_set = true;
+ if (field->opt_index >= 0) {
+ OptKeySet *ks = (OptKeySet *)value;
+ is_set = ks->is_set_ & (1ULL << field->opt_index);
+ }
+
+ if (!is_set) {
+ continue;
+ }
+
+ char *mem = ((char *)value + field->ptr_off);
+
+ lua_pushstring(L, field->str);
+ if (field->type == kObjectTypeNil) {
+ nlua_push_Object(L, (Object *)mem, false);
+ } else if (field->type == kObjectTypeInteger) {
+ lua_pushinteger(L, *(Integer *)mem);
+ } else if (field->type == kObjectTypeBuffer || field->type == kObjectTypeWindow
+ || field->type == kObjectTypeTabpage) {
+ lua_pushinteger(L, *(handle_T *)mem);
+ } else if (field->type == kObjectTypeFloat) {
+ lua_pushnumber(L, *(Float *)mem);
+ } else if (field->type == kObjectTypeBoolean) {
+ lua_pushboolean(L, *(Boolean *)mem);
+ } else if (field->type == kObjectTypeString) {
+ nlua_push_String(L, *(String *)mem, false);
+ } else if (field->type == kObjectTypeArray) {
+ nlua_push_Array(L, *(Array *)mem, false);
+ } else if (field->type == kObjectTypeDictionary) {
+ nlua_push_Dictionary(L, *(Dictionary *)mem, false);
+ } else if (field->type == kObjectTypeLuaRef) {
+ nlua_pushref(L, *(LuaRef *)mem);
+ } else {
+ abort();
+ }
+
+ lua_rawset(L, -3);
+ }
+}
diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c
index 06d16efb05..1a9bd026b5 100644
--- a/src/nvim/lua/executor.c
+++ b/src/nvim/lua/executor.c
@@ -15,7 +15,9 @@
#include "nvim/api/extmark.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/api/ui.h"
#include "nvim/ascii_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/change.h"
#include "nvim/cmdexpand_defs.h"
#include "nvim/cursor.h"
@@ -33,8 +35,9 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_getln.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/keycodes.h"
#include "nvim/lua/converter.h"
@@ -45,22 +48,30 @@
#include "nvim/main.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/option_vars.h"
#include "nvim/os/fileio.h"
+#include "nvim/os/fileio_defs.h"
#include "nvim/os/os.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/strings.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/undo.h"
#include "nvim/usercmd.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
+#ifndef MSWIN
+# include <pthread.h>
+#endif
+
static int in_fast_callback = 0;
static bool in_script = false;
@@ -115,7 +126,7 @@ lua_State *get_global_lstate(void)
/// Convert lua error into a Vim error message
///
/// @param lstate Lua interpreter state.
-/// @param[in] msg Message base, must contain one `%*s`.
+/// @param[in] msg Message base, must contain one `%.*s`.
void nlua_error(lua_State *const lstate, const char *const msg)
FUNC_ATTR_NONNULL_ALL
{
@@ -208,7 +219,7 @@ static int nlua_luv_cfpcall(lua_State *lstate, int nargs, int nresult, int flags
const char *error = lua_tostring(lstate, -1);
multiqueue_put(main_loop.events, nlua_luv_error_event,
- 2, xstrdup(error), (intptr_t)kCallback);
+ xstrdup(error), (void *)(intptr_t)kCallback);
lua_pop(lstate, 1); // error message
retval = -status;
} else { // LUA_OK
@@ -254,8 +265,7 @@ static int nlua_luv_thread_common_cfpcall(lua_State *lstate, int nargs, int nres
if (status == LUA_ERRMEM && !(flags & LUVF_CALLBACK_NOEXIT)) {
// Terminate this thread, as the main thread may be able to continue
// execution.
- os_errmsg(e_outofmem);
- os_errmsg("\n");
+ fprintf(stderr, "%s\n", e_outofmem);
lua_close(lstate);
#ifdef MSWIN
ExitThread(0);
@@ -266,11 +276,11 @@ static int nlua_luv_thread_common_cfpcall(lua_State *lstate, int nargs, int nres
const char *error = lua_tostring(lstate, -1);
loop_schedule_deferred(&main_loop,
- event_create(nlua_luv_error_event, 2,
+ event_create(nlua_luv_error_event,
xstrdup(error),
- is_callback
- ? (intptr_t)kThreadCallback
- : (intptr_t)kThread));
+ (void *)(intptr_t)(is_callback
+ ? kThreadCallback
+ : kThread)));
lua_pop(lstate, 1); // error message
retval = -status;
} else { // LUA_OK
@@ -302,7 +312,10 @@ static int nlua_thr_api_nvim__get_runtime(lua_State *lstate)
lua_pop(lstate, 1);
Error err = ERROR_INIT;
- const Array pat = nlua_pop_Array(lstate, &err);
+ // TODO(bfredl): we could use an arena here for both "pat" and "ret", but then
+ // we need a path to not use the freelist but a private block local to the thread.
+ // We do not want mutex contentionery for the main arena freelist.
+ const Array pat = nlua_pop_Array(lstate, NULL, &err);
if (ERROR_SET(&err)) {
luaL_where(lstate, 1);
lua_pushstring(lstate, err.msg);
@@ -379,8 +392,7 @@ static int nlua_schedule(lua_State *const lstate)
LuaRef cb = nlua_ref_global(lstate, 1);
- multiqueue_put(main_loop.events, nlua_schedule_event,
- 1, (void *)(ptrdiff_t)cb);
+ multiqueue_put(main_loop.events, nlua_schedule_event, (void *)(ptrdiff_t)cb);
return 0;
}
@@ -643,8 +655,7 @@ static bool nlua_init_packages(lua_State *lstate, bool is_standalone)
lua_getglobal(lstate, "require");
lua_pushstring(lstate, "vim._init_packages");
if (nlua_pcall(lstate, 1, 0)) {
- os_errmsg(lua_tostring(lstate, -1));
- os_errmsg("\n");
+ fprintf(stderr, "%s\n", lua_tostring(lstate, -1));
return false;
}
@@ -818,12 +829,12 @@ void nlua_init(char **argv, int argc, int lua_arg0)
lua_State *lstate = luaL_newstate();
if (lstate == NULL) {
- os_errmsg(_("E970: Failed to initialize lua interpreter\n"));
+ fprintf(stderr, _("E970: Failed to initialize lua interpreter\n"));
os_exit(1);
}
luaL_openlibs(lstate);
if (!nlua_state_init(lstate)) {
- os_errmsg(_("E970: Failed to initialize builtin lua modules\n"));
+ fprintf(stderr, _("E970: Failed to initialize builtin lua modules\n"));
#ifdef EXITFREE
nlua_common_free_all_mem(lstate);
#endif
@@ -1022,15 +1033,14 @@ static int nlua_print(lua_State *const lstate)
if (is_thread) {
loop_schedule_deferred(&main_loop,
- event_create(nlua_print_event, 2,
+ event_create(nlua_print_event,
msg_ga.ga_data,
- (intptr_t)msg_ga.ga_len));
+ (void *)(intptr_t)msg_ga.ga_len));
} else if (in_fast_callback) {
multiqueue_put(main_loop.events, nlua_print_event,
- 2, msg_ga.ga_data, (intptr_t)msg_ga.ga_len);
+ msg_ga.ga_data, (void *)(intptr_t)msg_ga.ga_len);
} else {
- nlua_print_event((void *[]){ msg_ga.ga_data,
- (void *)(intptr_t)msg_ga.ga_len });
+ nlua_print_event((void *[]){ msg_ga.ga_data, (void *)(intptr_t)msg_ga.ga_len });
}
return 0;
@@ -1236,13 +1246,13 @@ static int nlua_rpc(lua_State *lstate, bool request)
const char *name = luaL_checklstring(lstate, 2, &name_len);
int nargs = lua_gettop(lstate) - 2;
Error err = ERROR_INIT;
- Array args = ARRAY_DICT_INIT;
+ Arena arena = ARENA_EMPTY;
+ Array args = arena_array(&arena, (size_t)nargs);
for (int i = 0; i < nargs; i++) {
lua_pushvalue(lstate, i + 3);
- ADD(args, nlua_pop_Object(lstate, false, &err));
+ ADD(args, nlua_pop_Object(lstate, false, &arena, &err));
if (ERROR_SET(&err)) {
- api_free_array(args);
goto check_err;
}
}
@@ -1251,7 +1261,7 @@ static int nlua_rpc(lua_State *lstate, bool request)
ArenaMem res_mem = NULL;
Object result = rpc_send_call(chan_id, name, args, &res_mem, &err);
if (!ERROR_SET(&err)) {
- nlua_push_Object(lstate, result, false);
+ nlua_push_Object(lstate, &result, false);
arena_mem_free(res_mem);
}
} else {
@@ -1259,10 +1269,11 @@ static int nlua_rpc(lua_State *lstate, bool request)
api_set_error(&err, kErrorTypeValidation,
"Invalid channel: %" PRIu64, chan_id);
}
- api_free_array(args); // TODO(bfredl): no
}
check_err:
+ arena_mem_free(arena_finish(&arena));
+
if (ERROR_SET(&err)) {
lua_pushstring(lstate, err.msg);
api_clear_error(&err);
@@ -1535,10 +1546,12 @@ int typval_exec_lua_callable(LuaRef lua_cb, int argcount, typval_T *argvars, typ
///
/// @param[in] str String to execute.
/// @param[in] args array of ... args
+/// @param[in] mode Whether and how the the return value should be converted to Object
+/// @param[in] arena can be NULL, then nested allocations are used
/// @param[out] err Location where error will be saved.
///
/// @return Return value of the execution.
-Object nlua_exec(const String str, const Array args, Error *err)
+Object nlua_exec(const String str, const Array args, LuaRetMode mode, Arena *arena, Error *err)
{
lua_State *const lstate = global_lstate;
@@ -1551,7 +1564,7 @@ Object nlua_exec(const String str, const Array args, Error *err)
}
for (size_t i = 0; i < args.size; i++) {
- nlua_push_Object(lstate, args.items[i], false);
+ nlua_push_Object(lstate, &args.items[i], false);
}
if (nlua_pcall(lstate, (int)args.size, 1)) {
@@ -1562,7 +1575,7 @@ Object nlua_exec(const String str, const Array args, Error *err)
return NIL;
}
- return nlua_pop_Object(lstate, false, err);
+ return nlua_call_pop_retval(lstate, mode, arena, err);
}
bool nlua_ref_is_function(LuaRef ref)
@@ -1583,12 +1596,12 @@ bool nlua_ref_is_function(LuaRef ref)
/// @param ref the reference to call (not consumed)
/// @param name if non-NULL, sent to callback as first arg
/// if NULL, only args are used
-/// @param retval if true, convert return value to Object
-/// if false, only check if return value is truthy
+/// @param mode Whether and how the the return value should be converted to Object
+/// @param arena can be NULL, then nested allocations are used
/// @param err Error details, if any (if NULL, errors are echoed)
-/// @return Return value of function, if retval was set. Otherwise
-/// BOOLEAN_OBJ(true) or NIL.
-Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Error *err)
+/// @return Return value of function, as per mode
+Object nlua_call_ref(LuaRef ref, const char *name, Array args, LuaRetMode mode, Arena *arena,
+ Error *err)
{
lua_State *const lstate = global_lstate;
nlua_pushref(lstate, ref);
@@ -1598,7 +1611,7 @@ Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Erro
nargs++;
}
for (size_t i = 0; i < args.size; i++) {
- nlua_push_Object(lstate, args.items[i], false);
+ nlua_push_Object(lstate, &args.items[i], false);
}
if (nlua_pcall(lstate, nargs, 1)) {
@@ -1614,18 +1627,34 @@ Object nlua_call_ref(LuaRef ref, const char *name, Array args, bool retval, Erro
return NIL;
}
- if (retval) {
- Error dummy = ERROR_INIT;
- if (err == NULL) {
- err = &dummy;
- }
- return nlua_pop_Object(lstate, false, err);
- } else {
- bool value = lua_toboolean(lstate, -1);
+ return nlua_call_pop_retval(lstate, mode, arena, err);
+}
+
+static Object nlua_call_pop_retval(lua_State *lstate, LuaRetMode mode, Arena *arena, Error *err)
+{
+ if (lua_isnil(lstate, -1)) {
lua_pop(lstate, 1);
+ return NIL;
+ }
+ Error dummy = ERROR_INIT;
- return value ? BOOLEAN_OBJ(true) : NIL;
+ switch (mode) {
+ case kRetNilBool: {
+ bool bool_value = lua_toboolean(lstate, -1);
+ lua_pop(lstate, 1);
+
+ return BOOLEAN_OBJ(bool_value);
+ }
+ case kRetLuaref: {
+ LuaRef ref = nlua_ref_global(lstate, -1);
+ lua_pop(lstate, 1);
+
+ return LUAREF_OBJ(ref);
}
+ case kRetObject:
+ return nlua_pop_Object(lstate, false, arena, err ? err : &dummy);
+ }
+ UNREACHABLE;
}
/// check if the current execution context is safe for calling deferred API
@@ -1635,27 +1664,38 @@ bool nlua_is_deferred_safe(void)
return in_fast_callback == 0;
}
-/// Run lua string
+/// Executes Lua code.
///
-/// Used for :lua.
+/// Implements `:lua` and `:lua ={expr}`.
///
-/// @param eap Vimscript command being run.
+/// @param eap Vimscript `:lua {code}`, `:{range}lua`, or `:lua ={expr}` command.
void ex_lua(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
+ // ":{range}lua", only if no {code}
+ if (*eap->arg == NUL) {
+ if (eap->addr_count > 0) {
+ cmd_source_buffer(eap, true);
+ } else {
+ emsg(_(e_argreq));
+ }
+ return;
+ }
+
size_t len;
char *code = script_get(eap, &len);
if (eap->skip || code == NULL) {
xfree(code);
return;
}
- // When =expr is used transform it to vim.print(expr)
+
+ // ":lua {code}", ":={expr}" or ":lua ={expr}"
+ //
+ // When "=expr" is used transform it to "vim.print(expr)".
if (eap->cmdidx == CMD_equal || code[0] == '=') {
size_t off = (eap->cmdidx == CMD_equal) ? 0 : 1;
len += sizeof("vim.print()") - 1 - off;
- // code_buf needs to be 1 char larger then len for null byte in the end.
- // lua nlua_typval_exec doesn't expect null terminated string so len
- // needs to end before null byte.
+ // `nlua_typval_exec` doesn't expect NUL-terminated string so `len` must end before NUL byte.
char *code_buf = xmallocz(len);
vim_snprintf(code_buf, len + 1, "vim.print(%s)", code + off);
xfree(code);
@@ -1667,11 +1707,11 @@ void ex_lua(exarg_T *const eap)
xfree(code);
}
-/// Run lua string for each line in range
+/// Executes Lua code for-each line in a buffer range.
///
-/// Used for :luado.
+/// Implements `:luado`.
///
-/// @param eap Vimscript command being run.
+/// @param eap Vimscript `:luado {code}` command.
void ex_luado(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
@@ -1715,10 +1755,15 @@ void ex_luado(exarg_T *const eap)
nlua_error(lstate, _("E5110: Error executing lua: %.*s"));
return;
}
+
+ buf_T *const was_curbuf = curbuf;
+
for (linenr_T l = eap->line1; l <= eap->line2; l++) {
+ // Check the line number, the command may have deleted lines.
if (l > curbuf->b_ml.ml_line_count) {
break;
}
+
lua_pushvalue(lstate, -1);
const char *const old_line = ml_get_buf(curbuf, l);
// Get length of old_line here as calling Lua code may free it.
@@ -1729,6 +1774,13 @@ void ex_luado(exarg_T *const eap)
nlua_error(lstate, _("E5111: Error calling lua: %.*s"));
break;
}
+
+ // Catch the command switching to another buffer.
+ // Check the line number, the command may have deleted lines.
+ if (curbuf != was_curbuf || l > curbuf->b_ml.ml_line_count) {
+ break;
+ }
+
if (lua_isstring(lstate, -1)) {
size_t new_line_len;
const char *const new_line = lua_tolstring(lstate, -1, &new_line_len);
@@ -1743,16 +1795,17 @@ void ex_luado(exarg_T *const eap)
}
lua_pop(lstate, 1);
}
+
lua_pop(lstate, 1);
check_cursor();
redraw_curbuf_later(UPD_NOT_VALID);
}
-/// Run lua file
+/// Executes Lua code from a file location.
///
-/// Used for :luafile.
+/// Implements `:luafile`.
///
-/// @param eap Vimscript command being run.
+/// @param eap Vimscript `:luafile {file}` command.
void ex_luafile(exarg_T *const eap)
FUNC_ATTR_NONNULL_ALL
{
@@ -1776,7 +1829,11 @@ bool nlua_exec_file(const char *path)
lua_getglobal(lstate, "loadfile");
lua_pushstring(lstate, path);
} else {
- FileDescriptor *stdin_dup = file_open_stdin();
+ FileDescriptor stdin_dup;
+ int error = file_open_stdin(&stdin_dup);
+ if (error) {
+ return false;
+ }
StringBuilder sb = KV_INITIAL_VALUE;
kv_resize(sb, 64);
@@ -1785,7 +1842,7 @@ bool nlua_exec_file(const char *path)
if (got_int) { // User canceled.
return false;
}
- ptrdiff_t read_size = file_read(stdin_dup, IObuff, 64);
+ ptrdiff_t read_size = file_read(&stdin_dup, IObuff, 64);
if (read_size < 0) { // Error.
return false;
}
@@ -1797,7 +1854,7 @@ bool nlua_exec_file(const char *path)
}
}
kv_push(sb, NUL);
- file_free(stdin_dup, false);
+ file_close(&stdin_dup, false);
lua_getglobal(lstate, "loadstring");
lua_pushstring(lstate, sb.items);
@@ -1900,13 +1957,14 @@ int nlua_expand_pat(expand_T *xp, char *pat, int *num_results, char ***results)
*num_results = 0;
*results = NULL;
- int prefix_len = (int)nlua_pop_Integer(lstate, &err);
+ Arena arena = ARENA_EMPTY;
+ int prefix_len = (int)nlua_pop_Integer(lstate, &arena, &err);
if (ERROR_SET(&err)) {
ret = FAIL;
goto cleanup;
}
- Array completions = nlua_pop_Array(lstate, &err);
+ Array completions = nlua_pop_Array(lstate, &arena, &err);
if (ERROR_SET(&err)) {
ret = FAIL;
goto cleanup_array;
@@ -1930,7 +1988,7 @@ int nlua_expand_pat(expand_T *xp, char *pat, int *num_results, char ***results)
*num_results = result_array.ga_len;
cleanup_array:
- api_free_array(completions);
+ arena_mem_free(arena_finish(&arena));
cleanup:
@@ -2178,7 +2236,7 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview)
// every possible modifier (with room to spare). If the list of possible
// modifiers grows this may need to be updated.
char buf[200] = { 0 };
- (void)uc_mods(buf, &cmdmod, false);
+ uc_mods(buf, &cmdmod, false);
lua_pushstring(lstate, buf);
lua_setfield(lstate, -2, "mods");
@@ -2274,11 +2332,9 @@ int nlua_do_ucmd(ucmd_T *cmd, exarg_T *eap, bool preview)
/// String representation of a Lua function reference
///
/// @return Allocated string
-char *nlua_funcref_str(LuaRef ref)
+char *nlua_funcref_str(LuaRef ref, Arena *arena)
{
lua_State *const lstate = global_lstate;
- StringBuilder str = KV_INITIAL_VALUE;
- kv_resize(str, 16);
if (!lua_checkstack(lstate, 1)) {
goto plain;
@@ -2292,14 +2348,13 @@ char *nlua_funcref_str(LuaRef ref)
lua_Debug ar;
if (lua_getinfo(lstate, ">S", &ar) && *ar.source == '@' && ar.linedefined >= 0) {
char *src = home_replace_save(NULL, ar.source + 1);
- kv_printf(str, "<Lua %d: %s:%d>", ref, src, ar.linedefined);
+ String str = arena_printf(arena, "<Lua %d: %s:%d>", ref, src, ar.linedefined);
xfree(src);
- return str.items;
+ return str.data;
}
-plain:
- kv_printf(str, "<Lua %d>", ref);
- return str.items;
+plain: {}
+ return arena_printf(arena, "<Lua %d>", ref).data;
}
/// Execute the vim._defaults module to set up default mappings and autocommands
@@ -2311,7 +2366,23 @@ void nlua_init_defaults(void)
lua_getglobal(L, "require");
lua_pushstring(L, "vim._defaults");
if (nlua_pcall(L, 1, 0)) {
- os_errmsg(lua_tostring(L, -1));
- os_errmsg("\n");
+ fprintf(stderr, "%s\n", lua_tostring(L, -1));
}
}
+
+/// check lua function exist
+bool nlua_func_exists(const char *lua_funcname)
+{
+ MAXSIZE_TEMP_ARRAY(args, 1);
+ size_t length = strlen(lua_funcname) + 8;
+ char *str = xmalloc(length);
+ vim_snprintf(str, length, "return %s", lua_funcname);
+ ADD_C(args, CSTR_AS_OBJ(str));
+ Error err = ERROR_INIT;
+ Object result = NLUA_EXEC_STATIC("return type(loadstring(...)()) == 'function'", args,
+ kRetNilBool, NULL, &err);
+ xfree(str);
+
+ api_clear_error(&err);
+ return LUARET_TRUTHY(result);
+}
diff --git a/src/nvim/lua/executor.h b/src/nvim/lua/executor.h
index b38faddbb3..ebcd62122f 100644
--- a/src/nvim/lua/executor.h
+++ b/src/nvim/lua/executor.h
@@ -4,18 +4,13 @@
#include <lua.h>
#include <stdbool.h>
-#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/assert_defs.h"
-#include "nvim/cmdexpand_defs.h"
-#include "nvim/eval/typval_defs.h"
-#include "nvim/ex_cmds_defs.h"
+#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
+#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/func_attr.h"
-#include "nvim/lua/converter.h"
#include "nvim/macros_defs.h"
-#include "nvim/map_defs.h"
#include "nvim/types_defs.h"
-#include "nvim/usercmd.h"
+#include "nvim/usercmd.h" // IWYU pragma: keep
// Generated by msgpack-gen.lua
void nlua_add_api_functions(lua_State *lstate) REAL_FATTR_NONNULL_ALL;
@@ -29,7 +24,8 @@ typedef struct {
#endif
} nlua_ref_state_t;
-#define NLUA_EXEC_STATIC(cstr, arg, err) nlua_exec(STATIC_CSTR_AS_STRING(cstr), arg, err)
+#define NLUA_EXEC_STATIC(cstr, arg, mode, arena, err) \
+ nlua_exec(STATIC_CSTR_AS_STRING(cstr), arg, mode, arena, err)
#define NLUA_CLEAR_REF(x) \
do { \
@@ -40,6 +36,16 @@ typedef struct {
} \
} while (0)
+typedef enum {
+ kRetObject, ///< any object, but doesn't preserve nested luarefs
+ kRetNilBool, ///< NIL preserved as such, other values return their booleanness
+ ///< Should also be used when return value is ignored, as it is allocation-free
+ kRetLuaref, ///< return value becomes a single Luaref, regardless of type (except NIL)
+} LuaRetMode;
+
+/// To use with kRetNilBool for quick thuthyness check
+#define LUARET_TRUTHY(res) ((res).type == kObjectTypeBoolean && (res).data.boolean == true)
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "lua/executor.h.generated.h"
#endif
diff --git a/src/nvim/lua/secure.c b/src/nvim/lua/secure.c
index 65c13f8872..f62e0ace04 100644
--- a/src/nvim/lua/secure.c
+++ b/src/nvim/lua/secure.c
@@ -4,7 +4,7 @@
#include "nvim/charset.h"
#include "nvim/ex_cmds_defs.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/lua/executor.h"
#include "nvim/lua/secure.h"
diff --git a/src/nvim/lua/spell.c b/src/nvim/lua/spell.c
index c261c5105e..ba83239dc5 100644
--- a/src/nvim/lua/spell.c
+++ b/src/nvim/lua/spell.c
@@ -7,7 +7,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight_defs.h"
#include "nvim/lua/spell.h"
@@ -15,10 +15,11 @@
#include "nvim/spell.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "lua/spell.c.generated.h" // IWYU pragma: export
+# include "lua/spell.c.generated.h"
#endif
int nlua_spell_check(lua_State *lstate)
+ FUNC_ATTR_NONNULL_ALL
{
if (lua_gettop(lstate) < 1) {
return luaL_error(lstate, "Expected 1 argument");
@@ -99,6 +100,7 @@ static const luaL_Reg spell_functions[] = {
};
int luaopen_spell(lua_State *L)
+ FUNC_ATTR_NONNULL_ALL
{
lua_newtable(L);
luaL_register(L, NULL, spell_functions);
diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c
index 33770b2e62..8f58fd1a1a 100644
--- a/src/nvim/lua/stdlib.c
+++ b/src/nvim/lua/stdlib.c
@@ -6,7 +6,7 @@
#include <stddef.h>
#include <stdint.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#ifdef NVIM_VENDOR_BIT
# include "bit.h"
@@ -19,10 +19,10 @@
#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/vars.h"
#include "nvim/ex_eval.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/lua/base64.h"
#include "nvim/lua/converter.h"
@@ -31,10 +31,12 @@
#include "nvim/lua/xdiff.h"
#include "nvim/map_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
@@ -83,7 +85,8 @@ static int regex_match_line(lua_State *lstate)
handle_T bufnr = (handle_T)luaL_checkinteger(lstate, 2);
linenr_T rownr = (linenr_T)luaL_checkinteger(lstate, 3);
- int start = 0, end = -1;
+ int start = 0;
+ int end = -1;
if (narg >= 4) {
start = (int)luaL_checkinteger(lstate, 4);
}
@@ -178,7 +181,8 @@ int nlua_str_utfindex(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
}
}
- size_t codepoints = 0, codeunits = 0;
+ size_t codepoints = 0;
+ size_t codeunits = 0;
mb_utflen(s1, (size_t)idx, &codepoints, &codeunits);
lua_pushinteger(lstate, (lua_Integer)codepoints);
@@ -222,11 +226,12 @@ static int nlua_str_utf_start(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
size_t s1_len;
const char *s1 = luaL_checklstring(lstate, 1, &s1_len);
ptrdiff_t offset = luaL_checkinteger(lstate, 2);
- if (offset < 0 || offset > (intptr_t)s1_len) {
+ if (offset <= 0 || offset > (intptr_t)s1_len) {
return luaL_error(lstate, "index out of range");
}
- int head_offset = -utf_cp_head_off(s1, s1 + offset - 1);
- lua_pushinteger(lstate, head_offset);
+ size_t const off = (size_t)(offset - 1);
+ int head_off = -utf_cp_bounds_len(s1, s1 + off, (int)(s1_len - off)).begin_off;
+ lua_pushinteger(lstate, head_off);
return 1;
}
@@ -242,11 +247,12 @@ static int nlua_str_utf_end(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL
size_t s1_len;
const char *s1 = luaL_checklstring(lstate, 1, &s1_len);
ptrdiff_t offset = luaL_checkinteger(lstate, 2);
- if (offset < 0 || offset > (intptr_t)s1_len) {
+ if (offset <= 0 || offset > (intptr_t)s1_len) {
return luaL_error(lstate, "index out of range");
}
- int tail_offset = utf_cp_tail_off(s1, s1 + offset - 1);
- lua_pushinteger(lstate, tail_offset);
+ size_t const off = (size_t)(offset - 1);
+ int tail_off = utf_cp_bounds_len(s1, s1 + off, (int)(s1_len - off)).end_off - 1;
+ lua_pushinteger(lstate, tail_off);
return 1;
}
@@ -537,11 +543,14 @@ static int nlua_iconv(lua_State *lstate)
return 1;
}
-// Like 'zx' but don't call newFoldLevel()
+// Update foldlevels (e.g., by evaluating 'foldexpr') for all lines in the current window without
+// invoking other side effects. Unlike `zx`, it does not close manually opened folds and does not
+// open folds under the cursor.
static int nlua_foldupdate(lua_State *lstate)
{
curwin->w_foldinvalid = true; // recompute folds
- foldOpenCursor();
+ foldUpdate(curwin, 1, (linenr_T)MAXLNUM);
+ curwin->w_foldinvalid = false;
return 0;
}
diff --git a/src/nvim/lua/treesitter.c b/src/nvim/lua/treesitter.c
index 008b3f2e95..25a753b179 100644
--- a/src/nvim/lua/treesitter.c
+++ b/src/nvim/lua/treesitter.c
@@ -1,5 +1,5 @@
-// lua bindings for tree-sitter.
-// NB: this file mostly contains a generic lua interface for tree-sitter
+// lua bindings for treesitter.
+// NB: this file mostly contains a generic lua interface for treesitter
// trees and nodes, and could be broken out as a reusable lua package
#include <assert.h>
@@ -56,6 +56,7 @@ typedef struct {
# include "lua/treesitter.c.generated.h"
#endif
+// TSParser
static struct luaL_Reg parser_meta[] = {
{ "__gc", parser_gc },
{ "__tostring", parser_tostring },
@@ -70,6 +71,7 @@ static struct luaL_Reg parser_meta[] = {
{ NULL, NULL }
};
+// TSTree
static struct luaL_Reg tree_meta[] = {
{ "__gc", tree_gc },
{ "__tostring", tree_tostring },
@@ -80,6 +82,7 @@ static struct luaL_Reg tree_meta[] = {
{ NULL, NULL }
};
+// TSNode
static struct luaL_Reg node_meta[] = {
{ "__tostring", node_tostring },
{ "__eq", node_eq },
@@ -119,6 +122,7 @@ static struct luaL_Reg node_meta[] = {
{ NULL, NULL }
};
+// TSQuery
static struct luaL_Reg query_meta[] = {
{ "__gc", query_gc },
{ "__tostring", query_tostring },
@@ -1360,9 +1364,16 @@ static int node_equal(lua_State *L)
/// assumes the match table being on top of the stack
static void set_match(lua_State *L, TSQueryMatch *match, int nodeidx)
{
- for (int i = 0; i < match->capture_count; i++) {
- push_node(L, match->captures[i].node, nodeidx);
- lua_rawseti(L, -2, (int)match->captures[i].index + 1);
+ // [match]
+ for (size_t i = 0; i < match->capture_count; i++) {
+ lua_rawgeti(L, -1, (int)match->captures[i].index + 1); // [match, captures]
+ if (lua_isnil(L, -1)) { // [match, nil]
+ lua_pop(L, 1); // [match]
+ lua_createtable(L, 1, 0); // [match, captures]
+ }
+ push_node(L, match->captures[i].node, nodeidx); // [match, captures, node]
+ lua_rawseti(L, -2, (int)lua_objlen(L, -2) + 1); // [match, captures]
+ lua_rawseti(L, -2, (int)match->captures[i].index + 1); // [match]
}
}
@@ -1375,7 +1386,7 @@ static int query_next_match(lua_State *L)
TSQueryMatch match;
if (ts_query_cursor_next_match(cursor, &match)) {
lua_pushinteger(L, match.pattern_index + 1); // [index]
- lua_createtable(L, (int)ts_query_capture_count(query), 2); // [index, match]
+ lua_createtable(L, (int)ts_query_capture_count(query), 0); // [index, match]
set_match(L, &match, lua_upvalueindex(2));
return 2;
}
@@ -1417,7 +1428,8 @@ static int query_next_capture(lua_State *L)
if (n_pred > 0 && (ud->max_match_id < (int)match.id)) {
ud->max_match_id = (int)match.id;
- lua_pushvalue(L, lua_upvalueindex(4)); // [index, node, match]
+ // Create a new cleared match table
+ lua_createtable(L, (int)ts_query_capture_count(query), 2); // [index, node, match]
set_match(L, &match, lua_upvalueindex(2));
lua_pushinteger(L, match.pattern_index + 1);
lua_setfield(L, -2, "pattern");
@@ -1427,6 +1439,10 @@ static int query_next_capture(lua_State *L)
lua_pushboolean(L, false);
lua_setfield(L, -2, "active");
}
+
+ // Set current_match to the new match
+ lua_replace(L, lua_upvalueindex(4)); // [index, node]
+ lua_pushvalue(L, lua_upvalueindex(4)); // [index, node, match]
return 3;
}
return 2;
@@ -1449,10 +1465,7 @@ static int node_rawquery(lua_State *L)
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, UINT32_MAX);
-#endif
ts_query_cursor_set_match_limit(cursor, 256);
ts_query_cursor_exec(cursor, query, node);
@@ -1475,11 +1488,8 @@ static int node_rawquery(lua_State *L)
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.
@@ -1655,8 +1665,10 @@ static int query_inspect(lua_State *L)
return 0;
}
- uint32_t n_pat = ts_query_pattern_count(query);
+ // TSQueryInfo
lua_createtable(L, 0, 2); // [retval]
+
+ uint32_t n_pat = ts_query_pattern_count(query);
lua_createtable(L, (int)n_pat, 1); // [retval, patterns]
for (size_t i = 0; i < n_pat; i++) {
uint32_t len;
diff --git a/src/nvim/lua/xdiff.c b/src/nvim/lua/xdiff.c
index 16c3aa5e11..035c171a14 100644
--- a/src/nvim/lua/xdiff.c
+++ b/src/nvim/lua/xdiff.c
@@ -5,7 +5,9 @@
#include <string.h>
#include "luaconf.h"
+#include "nvim/api/keysets_defs.h"
#include "nvim/api/private/defs.h"
+#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
#include "nvim/linematch.h"
#include "nvim/lua/converter.h"
@@ -74,7 +76,8 @@ static void get_linematch_results(lua_State *lstate, mmfile_t *ma, mmfile_t *mb,
int *decisions = NULL;
size_t decisions_length = linematch_nbuffers(diff_begin, diff_length, 2, &decisions, iwhite);
- int lnuma = start_a, lnumb = start_b;
+ int lnuma = start_a;
+ int lnumb = start_b;
int hunkstarta = lnuma;
int hunkstartb = lnumb;
@@ -186,136 +189,84 @@ static mmfile_t get_string_arg(lua_State *lstate, int idx)
return mf;
}
-// Helper function for validating option types
-static bool check_xdiff_opt(ObjectType actType, ObjectType expType, const char *name, Error *err)
-{
- if (actType != expType) {
- const char *type_str =
- expType == kObjectTypeString
- ? "string" : (expType == kObjectTypeInteger
- ? "integer" : (expType == kObjectTypeBoolean
- ? "boolean" : (expType == kObjectTypeLuaRef
- ? "function" : "NA")));
-
- api_set_error(err, kErrorTypeValidation, "%s is not a %s", name,
- type_str);
- return true;
- }
-
- return false;
-}
-
static NluaXdiffMode process_xdl_diff_opts(lua_State *lstate, xdemitconf_t *cfg, xpparam_t *params,
int64_t *linematch, Error *err)
{
- const DictionaryOf(LuaRef) opts = nlua_pop_Dictionary(lstate, true, err);
+ Dict(xdl_diff) opts = KEYDICT_INIT;
+ char *err_param = NULL;
+ KeySetLink *KeyDict_xdl_diff_get_field(const char *str, size_t len);
+ nlua_pop_keydict(lstate, &opts, KeyDict_xdl_diff_get_field, &err_param, NULL, err);
NluaXdiffMode mode = kNluaXdiffModeUnified;
- bool had_on_hunk = false;
bool had_result_type_indices = false;
- for (size_t i = 0; i < opts.size; i++) {
- String k = opts.items[i].key;
- Object *v = &opts.items[i].value;
- if (strequal("on_hunk", k.data)) {
- if (check_xdiff_opt(v->type, kObjectTypeLuaRef, "on_hunk", err)) {
- goto exit_1;
- }
- had_on_hunk = true;
- nlua_pushref(lstate, v->data.luaref);
- } else if (strequal("result_type", k.data)) {
- if (check_xdiff_opt(v->type, kObjectTypeString, "result_type", err)) {
- goto exit_1;
- }
- if (strequal("unified", v->data.string.data)) {
- // the default
- } else if (strequal("indices", v->data.string.data)) {
- had_result_type_indices = true;
- } else {
- api_set_error(err, kErrorTypeValidation, "not a valid result_type");
- goto exit_1;
- }
- } else if (strequal("algorithm", k.data)) {
- if (check_xdiff_opt(v->type, kObjectTypeString, "algorithm", err)) {
- goto exit_1;
- }
- if (strequal("myers", v->data.string.data)) {
- // default
- } else if (strequal("minimal", v->data.string.data)) {
- params->flags |= XDF_NEED_MINIMAL;
- } else if (strequal("patience", v->data.string.data)) {
- params->flags |= XDF_PATIENCE_DIFF;
- } else if (strequal("histogram", v->data.string.data)) {
- params->flags |= XDF_HISTOGRAM_DIFF;
- } else {
- api_set_error(err, kErrorTypeValidation, "not a valid algorithm");
- goto exit_1;
- }
- } else if (strequal("ctxlen", k.data)) {
- if (check_xdiff_opt(v->type, kObjectTypeInteger, "ctxlen", err)) {
- goto exit_1;
- }
- cfg->ctxlen = (long)v->data.integer;
- } else if (strequal("interhunkctxlen", k.data)) {
- if (check_xdiff_opt(v->type, kObjectTypeInteger, "interhunkctxlen",
- err)) {
- goto exit_1;
- }
- cfg->interhunkctxlen = (long)v->data.integer;
- } else if (strequal("linematch", k.data)) {
- if (v->type == kObjectTypeBoolean) {
- *linematch = v->data.boolean ? INT64_MAX : 0;
- } else if (v->type == kObjectTypeInteger) {
- *linematch = v->data.integer;
- } else {
- api_set_error(err, kErrorTypeValidation, "linematch must be a boolean or integer");
- goto exit_1;
- }
+
+ if (HAS_KEY(&opts, xdl_diff, result_type)) {
+ if (strequal("unified", opts.result_type.data)) {
+ // the default
+ } else if (strequal("indices", opts.result_type.data)) {
+ had_result_type_indices = true;
} else {
- struct {
- const char *name;
- unsigned long value;
- } flags[] = {
- { "ignore_whitespace", XDF_IGNORE_WHITESPACE },
- { "ignore_whitespace_change", XDF_IGNORE_WHITESPACE_CHANGE },
- { "ignore_whitespace_change_at_eol", XDF_IGNORE_WHITESPACE_AT_EOL },
- { "ignore_cr_at_eol", XDF_IGNORE_CR_AT_EOL },
- { "ignore_blank_lines", XDF_IGNORE_BLANK_LINES },
- { "indent_heuristic", XDF_INDENT_HEURISTIC },
- { NULL, 0 },
- };
- bool key_used = false;
- for (size_t j = 0; flags[j].name; j++) {
- if (strequal(flags[j].name, k.data)) {
- if (check_xdiff_opt(v->type, kObjectTypeBoolean, flags[j].name,
- err)) {
- goto exit_1;
- }
- if (v->data.boolean) {
- params->flags |= flags[j].value;
- }
- key_used = true;
- break;
- }
- }
+ api_set_error(err, kErrorTypeValidation, "not a valid result_type");
+ goto exit_1;
+ }
+ }
- if (key_used) {
- continue;
- }
+ if (HAS_KEY(&opts, xdl_diff, algorithm)) {
+ if (strequal("myers", opts.algorithm.data)) {
+ // default
+ } else if (strequal("minimal", opts.algorithm.data)) {
+ params->flags |= XDF_NEED_MINIMAL;
+ } else if (strequal("patience", opts.algorithm.data)) {
+ params->flags |= XDF_PATIENCE_DIFF;
+ } else if (strequal("histogram", opts.algorithm.data)) {
+ params->flags |= XDF_HISTOGRAM_DIFF;
+ } else {
+ api_set_error(err, kErrorTypeValidation, "not a valid algorithm");
+ goto exit_1;
+ }
+ }
- api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
+ if (HAS_KEY(&opts, xdl_diff, ctxlen)) {
+ cfg->ctxlen = (long)opts.ctxlen;
+ }
+
+ if (HAS_KEY(&opts, xdl_diff, interhunkctxlen)) {
+ cfg->interhunkctxlen = (long)opts.interhunkctxlen;
+ }
+
+ if (HAS_KEY(&opts, xdl_diff, linematch)) {
+ if (opts.linematch.type == kObjectTypeBoolean) {
+ *linematch = opts.linematch.data.boolean ? INT64_MAX : 0;
+ } else if (opts.linematch.type == kObjectTypeInteger) {
+ *linematch = opts.linematch.data.integer;
+ } else {
+ api_set_error(err, kErrorTypeValidation, "linematch must be a boolean or integer");
goto exit_1;
}
}
- if (had_on_hunk) {
+ params->flags |= opts.ignore_whitespace ? XDF_IGNORE_WHITESPACE : 0;
+ params->flags |= opts.ignore_whitespace_change ? XDF_IGNORE_WHITESPACE_CHANGE : 0;
+ params->flags |= opts.ignore_whitespace_change_at_eol ? XDF_IGNORE_WHITESPACE_AT_EOL : 0;
+ params->flags |= opts.ignore_cr_at_eol ? XDF_IGNORE_CR_AT_EOL : 0;
+ params->flags |= opts.ignore_blank_lines ? XDF_IGNORE_BLANK_LINES : 0;
+ params->flags |= opts.indent_heuristic ? XDF_INDENT_HEURISTIC : 0;
+
+ if (HAS_KEY(&opts, xdl_diff, on_hunk)) {
mode = kNluaXdiffModeOnHunkCB;
+ nlua_pushref(lstate, opts.on_hunk);
+ if (lua_type(lstate, -1) != LUA_TFUNCTION) {
+ api_set_error(err, kErrorTypeValidation, "on_hunk is not a function");
+ }
} else if (had_result_type_indices) {
mode = kNluaXdiffModeLocations;
}
exit_1:
- api_free_dictionary(opts);
+ api_free_string(opts.result_type);
+ api_free_string(opts.algorithm);
+ api_free_luaref(opts.on_hunk);
return mode;
}
diff --git a/src/nvim/macros_defs.h b/src/nvim/macros_defs.h
index a7af2f91c3..67da29031c 100644
--- a/src/nvim/macros_defs.h
+++ b/src/nvim/macros_defs.h
@@ -29,9 +29,6 @@
/// @return `s, sizeof(s) - 1`
#define S_LEN(s) (s), (sizeof(s) - 1)
-/// LINEEMPTY() - return true if the line is empty
-#define LINEEMPTY(p) (*ml_get(p) == NUL)
-
// toupper() and tolower() that use the current locale.
// Careful: Only call TOUPPER_LOC() and TOLOWER_LOC() with a character in the
// range 0 - 255. toupper()/tolower() on some systems can't handle others.
@@ -54,48 +51,12 @@
// Returns empty string if it is NULL.
#define EMPTY_IF_NULL(x) ((x) ? (x) : "")
-/// Adjust chars in a language according to 'langmap' option.
-/// NOTE that there is no noticeable overhead if 'langmap' is not set.
-/// When set the overhead for characters < 256 is small.
-/// Don't apply 'langmap' if the character comes from the Stuff buffer or from a
-/// mapping and the langnoremap option was set.
-/// The do-while is just to ignore a ';' after the macro.
-#define LANGMAP_ADJUST(c, condition) \
- do { \
- if (*p_langmap \
- && (condition) \
- && (p_lrm || (vgetc_busy ? typebuf_maplen() == 0 : KeyTyped)) \
- && !KeyStuffed \
- && (c) >= 0) \
- { \
- if ((c) < 256) \
- c = langmap_mapchar[c]; \
- else \
- c = langmap_adjust_mb(c); \
- } \
- } while (0)
-
#define WRITEBIN "wb" // no CR-LF translation
#define READBIN "rb"
#define APPENDBIN "ab"
#define REPLACE_NORMAL(s) (((s)& REPLACE_FLAG) && !((s)& VREPLACE_FLAG))
-// MB_PTR_ADV(): advance a pointer to the next character, taking care of
-// multi-byte characters if needed. Skip over composing chars.
-#define MB_PTR_ADV(p) (p += utfc_ptr2len((char *)p))
-
-// Advance multi-byte pointer, do not skip over composing chars.
-#define MB_CPTR_ADV(p) (p += utf_ptr2len((char *)p))
-
-// MB_PTR_BACK(): backup a pointer to the previous character, taking care of
-// multi-byte characters if needed. Only use with "p" > "s" !
-#define MB_PTR_BACK(s, p) \
- (p -= utf_head_off((char *)(s), (char *)(p) - 1) + 1)
-
-// MB_CHAR2BYTES(): convert character to bytes and advance pointer to bytes
-#define MB_CHAR2BYTES(c, b) ((b) += utf_char2bytes((c), ((char *)b)))
-
#define RESET_BINDING(wp) \
do { \
(wp)->w_p_scb = false; \
@@ -150,10 +111,13 @@
#endif
#if defined(__clang__) || defined(__GNUC__)
+# define EXPECT(cond, value) __builtin_expect((cond), (value))
# define UNREACHABLE __builtin_unreachable()
-#elif defined(_MSVC_VER)
+#elif defined(_MSC_VER)
+# define EXPECT(cond, value) (cond)
# define UNREACHABLE __assume(false)
#else
+# define EXPECT(cond, value) (cond)
# define UNREACHABLE
#endif
diff --git a/src/nvim/main.c b/src/nvim/main.c
index 6585bd1df7..ea189aaa0c 100644
--- a/src/nvim/main.c
+++ b/src/nvim/main.c
@@ -25,15 +25,19 @@
#include "nvim/arglist.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/channel.h"
+#include "nvim/channel_defs.h"
#include "nvim/decoration.h"
#include "nvim/decoration_provider.h"
#include "nvim/diff.h"
+#include "nvim/drawline.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/userfunc.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
@@ -42,12 +46,12 @@
#include "nvim/ex_cmds.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
+#include "nvim/extmark.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/hashtab.h"
@@ -66,18 +70,20 @@
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/msgpack_rpc/channel.h"
-#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/msgpack_rpc/server.h"
#include "nvim/normal.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/fileio.h"
+#include "nvim/os/fileio_defs.h"
#include "nvim/os/fs.h"
#include "nvim/os/input.h"
#include "nvim/os/lang.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/signal.h"
#include "nvim/os/stdpaths_defs.h"
#include "nvim/path.h"
@@ -85,6 +91,7 @@
#include "nvim/profile.h"
#include "nvim/quickfix.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/shada.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
@@ -97,10 +104,16 @@
#include "nvim/version.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
+#include "nvim/winfloat.h"
+
#ifdef MSWIN
# include "nvim/os/os_win_console.h"
#endif
+#if defined(MSWIN) && !defined(MAKE_LIB)
+# include "nvim/mbyte.h"
+#endif
+
// values for "window_layout"
enum {
WIN_HOR = 1, // "-o" horizontally split windows
@@ -138,11 +151,9 @@ void event_init(void)
loop_init(&main_loop, NULL);
resize_events = multiqueue_new_child(main_loop.events);
- // early msgpack-rpc initialization
- msgpack_rpc_helpers_init();
input_init();
signal_init();
- // finish mspgack-rpc initialization
+ // mspgack-rpc initialization
channel_init();
terminal_init();
ui_init();
@@ -247,7 +258,7 @@ int main(int argc, char **argv)
argv0 = argv[0];
if (!appname_is_valid()) {
- os_errmsg("$NVIM_APPNAME must be a name or relative path.\n");
+ fprintf(stderr, "$NVIM_APPNAME must be a name or relative path.\n");
exit(1);
}
@@ -336,7 +347,7 @@ int main(int argc, char **argv)
ui_client_forward_stdin = !stdin_isatty;
uint64_t rv = ui_client_start_server(params.argc, params.argv);
if (!rv) {
- os_errmsg("Failed to start Nvim server!\n");
+ fprintf(stderr, "Failed to start Nvim server!\n");
os_exit(1);
}
ui_client_channel_id = rv;
@@ -352,7 +363,7 @@ int main(int argc, char **argv)
setbuf(stdout, NULL); // NOLINT(bugprone-unsafe-functions)
- full_screen = !silent_mode;
+ full_screen = !silent_mode || exmode_active;
// Set the default values for the options that use Rows and Columns.
win_init_size();
@@ -385,6 +396,7 @@ int main(int argc, char **argv)
}
if (ui_client_channel_id) {
+ time_finish();
ui_client_run(remote_ui); // NORETURN
}
assert(!ui_client_channel_id && !use_builtin_ui);
@@ -411,7 +423,19 @@ int main(int argc, char **argv)
params.edit_type = EDIT_STDIN;
}
- open_script_files(&params);
+ if (params.scriptin) {
+ if (!open_scriptin(params.scriptin)) {
+ os_exit(2);
+ }
+ }
+ if (params.scriptout) {
+ scriptout = os_fopen(params.scriptout, params.scriptout_append ? APPENDBIN : WRITEBIN);
+ if (scriptout == NULL) {
+ fprintf(stderr, _("Cannot open for script output: \""));
+ fprintf(stderr, "%s\"\n", params.scriptout);
+ os_exit(2);
+ }
+ }
nlua_init_defaults();
@@ -615,7 +639,7 @@ int main(int argc, char **argv)
// WORKAROUND(mhi): #3023
if (cb_flags & CB_UNNAMEDMASK) {
- (void)eval_has_provider("clipboard");
+ eval_has_provider("clipboard");
}
if (params.luaf != NULL) {
@@ -681,6 +705,9 @@ void getout(int exitval)
assert(!ui_client_channel_id);
exiting = true;
+ // make sure startuptimes have been flushed
+ time_finish();
+
// On error during Ex mode, exit with a non-zero code.
// POSIX requires this, although it's not 100% clear from the standard.
if (exmode_active) {
@@ -823,8 +850,7 @@ void preserve_exit(const char *errmsg)
ui_client_stop();
}
if (errmsg != NULL) {
- os_errmsg(errmsg);
- os_errmsg("\n");
+ fprintf(stderr, "%s\n", errmsg);
}
if (ui_client_channel_id) {
os_exit(1);
@@ -835,7 +861,7 @@ void preserve_exit(const char *errmsg)
FOR_ALL_BUFFERS(buf) {
if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) {
if (errmsg != NULL) {
- os_errmsg("Vim: preserving files...\r\n");
+ fprintf(stderr, "Vim: preserving files...\r\n");
}
ml_sync_all(false, false, true); // preserve all swap files
break;
@@ -845,7 +871,7 @@ void preserve_exit(const char *errmsg)
ml_close_all(false); // close all memfiles, without deleting
if (errmsg != NULL) {
- os_errmsg("Vim: Finished.\r\n");
+ fprintf(stderr, "Vim: Finished.\r\n");
}
getout(1);
@@ -910,14 +936,11 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr,
if (is_ui) {
if (!chan) {
- os_errmsg("Remote ui failed to start: ");
- os_errmsg(connect_error);
- os_errmsg("\n");
+ fprintf(stderr, "Remote ui failed to start: %s\n", connect_error);
os_exit(1);
} else if (strequal(server_addr, os_getenv("NVIM"))) {
- os_errmsg("Cannot attach UI of :terminal child to its parent. ");
- os_errmsg("(Unset $NVIM to skip this check)");
- os_errmsg("\n");
+ fprintf(stderr, "%s", "Cannot attach UI of :terminal child to its parent. ");
+ fprintf(stderr, "%s\n", "(Unset $NVIM to skip this check)");
os_exit(1);
}
@@ -926,30 +949,29 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr,
}
Array args = ARRAY_DICT_INIT;
+ kv_resize(args, (size_t)(argc - remote_args));
for (int t_argc = remote_args; t_argc < argc; t_argc++) {
- String arg_s = cstr_to_string(argv[t_argc]);
- ADD(args, STRING_OBJ(arg_s));
+ ADD_C(args, CSTR_AS_OBJ(argv[t_argc]));
}
Error err = ERROR_INIT;
- Array a = ARRAY_DICT_INIT;
- ADD(a, INTEGER_OBJ((int)chan));
- ADD(a, CSTR_TO_OBJ(server_addr));
- ADD(a, CSTR_TO_OBJ(connect_error));
- ADD(a, ARRAY_OBJ(args));
+ MAXSIZE_TEMP_ARRAY(a, 4);
+ ADD_C(a, INTEGER_OBJ((int)chan));
+ ADD_C(a, CSTR_AS_OBJ(server_addr));
+ ADD_C(a, CSTR_AS_OBJ(connect_error));
+ ADD_C(a, ARRAY_OBJ(args));
String s = STATIC_CSTR_AS_STRING("return vim._cs_remote(...)");
- Object o = nlua_exec(s, a, &err);
- api_free_array(a);
+ Object o = nlua_exec(s, a, kRetObject, NULL, &err);
+ kv_destroy(args);
if (ERROR_SET(&err)) {
- os_errmsg(err.msg);
- os_errmsg("\n");
+ fprintf(stderr, "%s\n", err.msg);
os_exit(2);
}
if (o.type == kObjectTypeDictionary) {
rvobj.data.dictionary = o.data.dictionary;
} else {
- os_errmsg("vim._cs_remote returned unexpected value\n");
+ fprintf(stderr, "vim._cs_remote returned unexpected value\n");
os_exit(2);
}
@@ -959,34 +981,33 @@ static void remote_request(mparm_T *params, int remote_args, char *server_addr,
for (size_t i = 0; i < rvobj.data.dictionary.size; i++) {
if (strequal(rvobj.data.dictionary.items[i].key.data, "errmsg")) {
if (rvobj.data.dictionary.items[i].value.type != kObjectTypeString) {
- os_errmsg("vim._cs_remote returned an unexpected type for 'errmsg'\n");
+ fprintf(stderr, "vim._cs_remote returned an unexpected type for 'errmsg'\n");
os_exit(2);
}
- os_errmsg(rvobj.data.dictionary.items[i].value.data.string.data);
- os_errmsg("\n");
+ fprintf(stderr, "%s\n", rvobj.data.dictionary.items[i].value.data.string.data);
os_exit(2);
} else if (strequal(rvobj.data.dictionary.items[i].key.data, "result")) {
if (rvobj.data.dictionary.items[i].value.type != kObjectTypeString) {
- os_errmsg("vim._cs_remote returned an unexpected type for 'result'\n");
+ fprintf(stderr, "vim._cs_remote returned an unexpected type for 'result'\n");
os_exit(2);
}
- os_msg(rvobj.data.dictionary.items[i].value.data.string.data);
+ printf("%s", rvobj.data.dictionary.items[i].value.data.string.data);
} else if (strequal(rvobj.data.dictionary.items[i].key.data, "tabbed")) {
if (rvobj.data.dictionary.items[i].value.type != kObjectTypeBoolean) {
- os_errmsg("vim._cs_remote returned an unexpected type for 'tabbed'\n");
+ fprintf(stderr, "vim._cs_remote returned an unexpected type for 'tabbed'\n");
os_exit(2);
}
tabbed = rvobj.data.dictionary.items[i].value.data.boolean ? kTrue : kFalse;
} else if (strequal(rvobj.data.dictionary.items[i].key.data, "should_exit")) {
if (rvobj.data.dictionary.items[i].value.type != kObjectTypeBoolean) {
- os_errmsg("vim._cs_remote returned an unexpected type for 'should_exit'\n");
+ fprintf(stderr, "vim._cs_remote returned an unexpected type for 'should_exit'\n");
os_exit(2);
}
should_exit = rvobj.data.dictionary.items[i].value.data.boolean ? kTrue : kFalse;
}
}
if (should_exit == kNone || tabbed == kNone) {
- os_errmsg("vim._cs_remote didn't return a value for should_exit or tabbed, bailing\n");
+ fprintf(stderr, "vim._cs_remote didn't return a value for should_exit or tabbed, bailing\n");
os_exit(2);
}
api_free_object(o);
@@ -1008,6 +1029,7 @@ static bool edit_stdin(mparm_T *parmp)
&& !(embedded_mode && stdin_fd <= 0)
&& (!exmode_active || parmp->input_istext)
&& !stdin_isatty
+ && parmp->edit_type <= EDIT_STDIN
&& parmp->scriptin == NULL; // `-s -` was not given.
return parmp->had_stdin_file || implicit;
}
@@ -1019,7 +1041,7 @@ static void command_line_scan(mparm_T *parmp)
char **argv = parmp->argv;
int argv_idx; // index in argv[n][]
bool had_minmin = false; // found "--" argument
- int want_argument; // option argument with argument
+ bool want_argument; // option argument with argument
int n;
argc--;
@@ -1078,20 +1100,16 @@ static void command_line_scan(mparm_T *parmp)
FileDescriptor fp;
const int fof_ret = file_open_fd(&fp, STDOUT_FILENO,
kFileWriteOnly);
- msgpack_packer *p = msgpack_packer_new(&fp, msgpack_file_write);
-
if (fof_ret != 0) {
semsg(_("E5421: Failed to open stdin: %s"), os_strerror(fof_ret));
}
- if (p == NULL) {
- emsg(_(e_outofmem));
+ String data = api_metadata_raw();
+ const ptrdiff_t written_bytes = file_write(&fp, data.data, data.size);
+ if (written_bytes < 0) {
+ msgpack_file_write_error((int)written_bytes);
}
- Object md = DICTIONARY_OBJ(api_metadata());
- msgpack_rpc_from_object(md, p);
-
- msgpack_packer_free(p);
const int ff_ret = file_flush(&fp);
if (ff_ret < 0) {
msgpack_file_write_error(ff_ret);
@@ -1122,7 +1140,7 @@ static void command_line_scan(mparm_T *parmp)
} else if (STRNICMP(argv[0] + argv_idx, "clean", 5) == 0) {
parmp->use_vimrc = "NONE";
parmp->clean = true;
- set_option_value_give_err("shadafile", STATIC_CSTR_AS_OPTVAL("NONE"), 0);
+ set_option_value_give_err(kOptShadafile, STATIC_CSTR_AS_OPTVAL("NONE"), 0);
} else if (STRNICMP(argv[0] + argv_idx, "luamod-dev", 9) == 0) {
nlua_disable_preload = true;
} else {
@@ -1136,7 +1154,7 @@ static void command_line_scan(mparm_T *parmp)
}
break;
case 'A': // "-A" start in Arabic mode.
- set_option_value_give_err("arabic", BOOLEAN_OPTVAL(true), 0);
+ set_option_value_give_err(kOptArabic, BOOLEAN_OPTVAL(true), 0);
break;
case 'b': // "-b" binary mode.
// Needs to be effective before expanding file names, because
@@ -1166,8 +1184,8 @@ static void command_line_scan(mparm_T *parmp)
usage();
os_exit(0);
case 'H': // "-H" start in Hebrew mode: rl + keymap=hebrew set.
- set_option_value_give_err("keymap", STATIC_CSTR_AS_OPTVAL("hebrew"), 0);
- set_option_value_give_err("rl", BOOLEAN_OPTVAL(true), 0);
+ set_option_value_give_err(kOptKeymap, STATIC_CSTR_AS_OPTVAL("hebrew"), 0);
+ set_option_value_give_err(kOptRightleft, BOOLEAN_OPTVAL(true), 0);
break;
case 'M': // "-M" no changes or writing of files
reset_modifiable();
@@ -1247,7 +1265,7 @@ static void command_line_scan(mparm_T *parmp)
// default is 10: a little bit verbose
p_verbose = get_number_arg(argv[0], &argv_idx, 10);
if (argv[0][argv_idx] != NUL) {
- set_option_value_give_err("verbosefile", CSTR_AS_OPTVAL(argv[0] + argv_idx), 0);
+ set_option_value_give_err(kOptVerbosefile, CSTR_AS_OPTVAL(argv[0] + argv_idx), 0);
argv_idx = (int)strlen(argv[0]);
}
break;
@@ -1255,7 +1273,7 @@ static void command_line_scan(mparm_T *parmp)
// "-w {scriptout}" write to script
if (ascii_isdigit((argv[0])[argv_idx])) {
n = get_number_arg(argv[0], &argv_idx, 10);
- set_option_value_give_err("window", NUMBER_OPTVAL((OptInt)n), 0);
+ set_option_value_give_err(kOptWindow, NUMBER_OPTVAL((OptInt)n), 0);
break;
}
want_argument = true;
@@ -1351,7 +1369,7 @@ static void command_line_scan(mparm_T *parmp)
break;
case 'i': // "-i {shada}" use for shada
- set_option_value_give_err("shadafile", CSTR_AS_OPTVAL(argv[0]), 0);
+ set_option_value_give_err(kOptShadafile, CSTR_AS_OPTVAL(argv[0]), 0);
break;
case 'l': // "-l" Lua script: args after "-l".
@@ -1361,7 +1379,7 @@ static void command_line_scan(mparm_T *parmp)
parmp->no_swap_file = true;
parmp->use_vimrc = parmp->use_vimrc ? parmp->use_vimrc : "NONE";
if (p_shadafile == NULL || *p_shadafile == NUL) {
- set_option_value_give_err("shadafile", STATIC_CSTR_AS_OPTVAL("NONE"), 0);
+ set_option_value_give_err(kOptShadafile, STATIC_CSTR_AS_OPTVAL("NONE"), 0);
}
parmp->luaf = argv[0];
argc--;
@@ -1377,7 +1395,7 @@ scripterror:
vim_snprintf(IObuff, IOSIZE,
_("Attempt to open script file again: \"%s %s\"\n"),
argv[-1], argv[0]);
- os_errmsg(IObuff);
+ fprintf(stderr, "%s", IObuff);
os_exit(2);
}
parmp->scriptin = argv[0];
@@ -1397,7 +1415,7 @@ scripterror:
if (ascii_isdigit(*(argv[0]))) {
argv_idx = 0;
n = get_number_arg(argv[0], &argv_idx, 10);
- set_option_value_give_err("window", NUMBER_OPTVAL((OptInt)n), 0);
+ set_option_value_give_err(kOptWindow, NUMBER_OPTVAL((OptInt)n), 0);
argv_idx = -1;
break;
}
@@ -1486,9 +1504,16 @@ static void init_params(mparm_T *paramp, int argc, char **argv)
/// Initialize global startuptime file if "--startuptime" passed as an argument.
static void init_startuptime(mparm_T *paramp)
{
+ bool is_embed = false;
+ for (int i = 1; i < paramp->argc - 1; i++) {
+ if (STRICMP(paramp->argv[i], "--embed") == 0) {
+ is_embed = true;
+ break;
+ }
+ }
for (int i = 1; i < paramp->argc - 1; i++) {
if (STRICMP(paramp->argv[i], "--startuptime") == 0) {
- time_fd = fopen(paramp->argv[i + 1], "a");
+ time_init(paramp->argv[i + 1], is_embed ? "Embedded" : "Primary/TUI");
time_start("--- NVIM STARTING ---");
break;
}
@@ -1548,7 +1573,7 @@ static void handle_quickfix(mparm_T *paramp)
{
if (paramp->edit_type == EDIT_QF) {
if (paramp->use_ef != NULL) {
- set_string_option_direct("ef", -1, paramp->use_ef, OPT_FREE, SID_CARG);
+ set_string_option_direct(kOptErrorfile, paramp->use_ef, 0, SID_CARG);
}
vim_snprintf(IObuff, IOSIZE, "cfile %s", p_ef);
if (qf_init(NULL, p_ef, p_efm, true, IObuff, p_menc) < 0) {
@@ -1587,7 +1612,7 @@ static void read_stdin(void)
bool save_msg_didany = msg_didany;
set_buflisted(true);
// Create memfile and read from stdin.
- (void)open_buffer(true, NULL, 0);
+ open_buffer(true, NULL, 0);
if (buf_is_empty(curbuf) && curbuf->b_next != NULL) {
// stdin was empty, go to buffer 2 (e.g. "echo file1 | xargs nvim"). #8561
do_cmdline_cmd("silent! bnext");
@@ -1600,38 +1625,6 @@ static void read_stdin(void)
check_swap_exists_action();
}
-static void open_script_files(mparm_T *parmp)
-{
- if (parmp->scriptin) {
- int error;
- if (strequal(parmp->scriptin, "-")) {
- FileDescriptor *stdin_dup = file_open_stdin();
- scriptin[0] = stdin_dup;
- } else {
- scriptin[0] = file_open_new(&error, parmp->scriptin,
- kFileReadOnly|kFileNonBlocking, 0);
- if (scriptin[0] == NULL) {
- vim_snprintf(IObuff, IOSIZE,
- _("Cannot open for reading: \"%s\": %s\n"),
- parmp->scriptin, os_strerror(error));
- os_errmsg(IObuff);
- os_exit(2);
- }
- }
- save_typebuf();
- }
-
- if (parmp->scriptout) {
- scriptout = os_fopen(parmp->scriptout, parmp->scriptout_append ? APPENDBIN : WRITEBIN);
- if (scriptout == NULL) {
- os_errmsg(_("Cannot open for script output: \""));
- os_errmsg(parmp->scriptout);
- os_errmsg("\"\n");
- os_exit(2);
- }
- }
-}
-
// Create the requested number of windows and edit buffers in them.
// Also does recovery if "recoverymode" set.
static void create_windows(mparm_T *parmp)
@@ -1679,7 +1672,7 @@ static void create_windows(mparm_T *parmp)
// Don't execute Win/Buf Enter/Leave autocommands here
autocmd_no_enter++;
autocmd_no_leave++;
- int dorewind = true;
+ bool dorewind = true;
while (done++ < 1000) {
if (dorewind) {
if (parmp->window_layout == WIN_TABS) {
@@ -1710,7 +1703,7 @@ static void create_windows(mparm_T *parmp)
set_buflisted(true);
// create memfile, read file
- (void)open_buffer(false, NULL, 0);
+ open_buffer(false, NULL, 0);
if (swap_exists_action == SEA_QUIT) {
if (got_int || only_one_window()) {
@@ -1732,7 +1725,7 @@ static void create_windows(mparm_T *parmp)
}
os_breakcheck();
if (got_int) {
- (void)vgetc(); // only break the file loading, not the rest
+ vgetc(); // only break the file loading, not the rest
break;
}
}
@@ -1793,7 +1786,7 @@ static void edit_buffers(mparm_T *parmp, char *cwd)
p_shm_save = xstrdup(p_shm);
snprintf(buf, sizeof(buf), "F%s", p_shm);
- set_option_value_give_err("shm", CSTR_AS_OPTVAL(buf), 0);
+ set_option_value_give_err(kOptShortmess, CSTR_AS_OPTVAL(buf), 0);
}
} else {
if (curwin->w_next == NULL) { // just checking
@@ -1811,9 +1804,9 @@ static void edit_buffers(mparm_T *parmp, char *cwd)
// Edit file from arg list, if there is one. When "Quit" selected
// at the ATTENTION prompt close the window.
swap_exists_did_quit = false;
- (void)do_ecmd(0, arg_idx < GARGCOUNT
- ? alist_name(&GARGLIST[arg_idx])
- : NULL, NULL, NULL, ECMD_LASTL, ECMD_HIDE, curwin);
+ do_ecmd(0, arg_idx < GARGCOUNT
+ ? alist_name(&GARGLIST[arg_idx])
+ : NULL, NULL, NULL, ECMD_LASTL, ECMD_HIDE, curwin);
if (swap_exists_did_quit) {
// abort or quit selected
if (got_int || only_one_window()) {
@@ -1832,13 +1825,13 @@ static void edit_buffers(mparm_T *parmp, char *cwd)
}
os_breakcheck();
if (got_int) {
- (void)vgetc(); // only break the file loading, not the rest
+ vgetc(); // only break the file loading, not the rest
break;
}
}
if (p_shm_save != NULL) {
- set_option_value_give_err("shm", CSTR_AS_OPTVAL(p_shm_save), 0);
+ set_option_value_give_err(kOptShortmess, CSTR_AS_OPTVAL(p_shm_save), 0);
xfree(p_shm_save);
}
@@ -1964,7 +1957,7 @@ static void do_system_initialization(void)
#ifdef SYS_VIMRC_FILE
// Get system wide defaults, if the file name is defined.
- (void)do_source(SYS_VIMRC_FILE, false, DOSO_NONE, NULL);
+ do_source(SYS_VIMRC_FILE, false, DOSO_NONE, NULL);
#endif
}
@@ -2066,7 +2059,7 @@ static void do_exrc_initialization(void)
str = nlua_read_secure(VIMRC_LUA_FILE);
if (str != NULL) {
Error err = ERROR_INIT;
- nlua_exec(cstr_as_string(str), (Array)ARRAY_DICT_INIT, &err);
+ nlua_exec(cstr_as_string(str), (Array)ARRAY_DICT_INIT, kRetNilBool, NULL, &err);
xfree(str);
if (ERROR_SET(&err)) {
semsg("Error detected while processing %s:", VIMRC_LUA_FILE);
@@ -2158,17 +2151,12 @@ static void print_mainerr(const char *errstr, const char *str)
signal_stop(); // kill us with CTRL-C here, if you like
- os_errmsg(prgname);
- os_errmsg(": ");
- os_errmsg(_(errstr));
+ fprintf(stderr, "%s: %s", prgname, _(errstr));
if (str != NULL) {
- os_errmsg(": \"");
- os_errmsg(str);
- os_errmsg("\"");
+ fprintf(stderr, ": \"%s\"", str);
}
- os_errmsg(_("\nMore info with \""));
- os_errmsg(prgname);
- os_errmsg(" -h\"\n");
+ fprintf(stderr, _("\nMore info with \""));
+ fprintf(stderr, "%s -h\"\n", prgname);
}
/// Prints version information for "nvim -v" or "nvim --version".
@@ -2176,7 +2164,7 @@ static void version(void)
{
// TODO(bfred): not like this?
nlua_init(NULL, 0, -1);
- info_message = true; // use os_msg(), not os_errmsg()
+ info_message = true; // use stdout, not stderr
list_version();
msg_putchar('\n');
msg_didout = false;
@@ -2187,38 +2175,38 @@ static void usage(void)
{
signal_stop(); // kill us with CTRL-C here, if you like
- os_msg(_("Usage:\n"));
- os_msg(_(" nvim [options] [file ...]\n"));
- os_msg(_("\nOptions:\n"));
- os_msg(_(" --cmd <cmd> Execute <cmd> before any config\n"));
- os_msg(_(" +<cmd>, -c <cmd> Execute <cmd> after config and first file\n"));
- os_msg(_(" -l <script> [args...] Execute Lua <script> (with optional args)\n"));
- os_msg(_(" -S <session> Source <session> after loading the first file\n"));
- os_msg(_(" -s <scriptin> Read Normal mode commands from <scriptin>\n"));
- os_msg(_(" -u <config> Use this config file\n"));
- os_msg("\n");
- os_msg(_(" -d Diff mode\n"));
- os_msg(_(" -es, -Es Silent (batch) mode\n"));
- os_msg(_(" -h, --help Print this help message\n"));
- os_msg(_(" -i <shada> Use this shada file\n"));
- os_msg(_(" -n No swap file, use memory only\n"));
- os_msg(_(" -o[N] Open N windows (default: one per file)\n"));
- os_msg(_(" -O[N] Open N vertical windows (default: one per file)\n"));
- os_msg(_(" -p[N] Open N tab pages (default: one per file)\n"));
- os_msg(_(" -R Read-only (view) mode\n"));
- os_msg(_(" -v, --version Print version information\n"));
- os_msg(_(" -V[N][file] Verbose [level][file]\n"));
- os_msg("\n");
- os_msg(_(" -- Only file names after this\n"));
- os_msg(_(" --api-info Write msgpack-encoded API metadata to stdout\n"));
- os_msg(_(" --clean \"Factory defaults\" (skip user config and plugins, shada)\n"));
- os_msg(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n"));
- os_msg(_(" --headless Don't start a user interface\n"));
- os_msg(_(" --listen <address> Serve RPC API from this address\n"));
- os_msg(_(" --remote[-subcommand] Execute commands remotely on a server\n"));
- os_msg(_(" --server <address> Specify RPC server to send commands to\n"));
- os_msg(_(" --startuptime <file> Write startup timing messages to <file>\n"));
- os_msg(_("\nSee \":help startup-options\" for all options.\n"));
+ printf(_("Usage:\n"));
+ printf(_(" nvim [options] [file ...]\n"));
+ printf(_("\nOptions:\n"));
+ printf(_(" --cmd <cmd> Execute <cmd> before any config\n"));
+ printf(_(" +<cmd>, -c <cmd> Execute <cmd> after config and first file\n"));
+ printf(_(" -l <script> [args...] Execute Lua <script> (with optional args)\n"));
+ printf(_(" -S <session> Source <session> after loading the first file\n"));
+ printf(_(" -s <scriptin> Read Normal mode commands from <scriptin>\n"));
+ printf(_(" -u <config> Use this config file\n"));
+ printf("\n");
+ printf(_(" -d Diff mode\n"));
+ printf(_(" -es, -Es Silent (batch) mode\n"));
+ printf(_(" -h, --help Print this help message\n"));
+ printf(_(" -i <shada> Use this shada file\n"));
+ printf(_(" -n No swap file, use memory only\n"));
+ printf(_(" -o[N] Open N windows (default: one per file)\n"));
+ printf(_(" -O[N] Open N vertical windows (default: one per file)\n"));
+ printf(_(" -p[N] Open N tab pages (default: one per file)\n"));
+ printf(_(" -R Read-only (view) mode\n"));
+ printf(_(" -v, --version Print version information\n"));
+ printf(_(" -V[N][file] Verbose [level][file]\n"));
+ printf("\n");
+ printf(_(" -- Only file names after this\n"));
+ printf(_(" --api-info Write msgpack-encoded API metadata to stdout\n"));
+ printf(_(" --clean \"Factory defaults\" (skip user config and plugins, shada)\n"));
+ printf(_(" --embed Use stdin/stdout as a msgpack-rpc channel\n"));
+ printf(_(" --headless Don't start a user interface\n"));
+ printf(_(" --listen <address> Serve RPC API from this address\n"));
+ printf(_(" --remote[-subcommand] Execute commands remotely on a server\n"));
+ printf(_(" --server <address> Specify RPC server to send commands to\n"));
+ printf(_(" --startuptime <file> Write startup timing messages to <file>\n"));
+ printf(_("\nSee \":help startup-options\" for all options.\n"));
}
// Check the result of the ATTENTION dialog:
diff --git a/src/nvim/main.h b/src/nvim/main.h
index 6aeb62712a..dedfadf270 100644
--- a/src/nvim/main.h
+++ b/src/nvim/main.h
@@ -3,6 +3,7 @@
#include <stdbool.h>
#include "nvim/event/loop.h"
+#include "nvim/types_defs.h"
// Maximum number of commands from + or -c arguments.
#define MAX_ARG_CMDS 10
diff --git a/src/nvim/map_defs.h b/src/nvim/map_defs.h
index 147c03327a..836b1447c2 100644
--- a/src/nvim/map_defs.h
+++ b/src/nvim/map_defs.h
@@ -33,7 +33,8 @@ static inline bool equal_String(String a, String b)
if (a.size != b.size) {
return false;
}
- return memcmp(a.data, b.data, a.size) == 0;
+
+ return (a.size == 0) || (memcmp(a.data, b.data, a.size) == 0);
}
#define Set(type) Set_##type
@@ -172,9 +173,14 @@ MAP_DECLS(ColorKey, ColorItem)
#define set_put_ref(T, set, key, key_alloc) set_put_##T(set, key, key_alloc)
#define set_put_idx(T, set, key, status) mh_put_##T(set, key, status)
#define set_del(T, set, key) set_del_##T(set, key)
-#define set_destroy(T, set) (xfree((set)->keys), xfree((set)->h.hash))
-#define set_clear(T, set) mh_clear(&(set)->h)
#define set_size(set) ((set)->h.size)
+#define set_clear(T, set) mh_clear(&(set)->h)
+#define set_destroy(T, set) \
+ do { \
+ xfree((set)->keys); \
+ xfree((set)->h.hash); \
+ *(set) = (Set(T)) SET_INIT; \
+ } while (0)
#define map_get(T, U) map_get_##T##U
#define map_has(T, map, key) set_has(T, &(map)->set, key)
@@ -182,9 +188,13 @@ MAP_DECLS(ColorKey, ColorItem)
#define map_ref(T, U) map_ref_##T##U
#define map_put_ref(T, U) map_put_ref_##T##U
#define map_del(T, U) map_del_##T##U
-#define map_destroy(T, map) (set_destroy(T, &(map)->set), xfree((map)->values))
-#define map_clear(T, map) set_clear(T, &(map)->set)
#define map_size(map) set_size(&(map)->set)
+#define map_clear(T, map) set_clear(T, &(map)->set)
+#define map_destroy(T, map) \
+ do { \
+ set_destroy(T, &(map)->set); \
+ XFREE_CLEAR((map)->values); \
+ } while (0)
#define pmap_get(T) map_get(T, ptr_t)
#define pmap_put(T) map_put(T, ptr_t)
diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c
index 17593a9121..43a4c10ea7 100644
--- a/src/nvim/mapping.c
+++ b/src/nvim/mapping.c
@@ -22,19 +22,24 @@
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
+#include "nvim/eval/userfunc.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_session.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/getchar_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/keycodes.h"
#include "nvim/lua/executor.h"
#include "nvim/macros_defs.h"
#include "nvim/mapping.h"
+#include "nvim/mapping_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option_defs.h"
@@ -48,6 +53,7 @@
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/vim_defs.h"
/// List used for abbreviations.
@@ -138,20 +144,6 @@ mapblock_T *get_buf_maphash_list(int state, int c)
return curbuf->b_maphash[MAP_HASH(state, c)];
}
-/// Retrieve the mapblock at the index either globally or for a certain buffer
-///
-/// @param index The index in the maphash[]
-/// @param buf The buffer to get the maphash from. NULL for global
-mapblock_T *get_maphash(int index, buf_T *buf)
- FUNC_ATTR_PURE
-{
- if (index >= MAX_MAPHASH) {
- return NULL;
- }
-
- return (buf == NULL) ? maphash[index] : buf->b_maphash[index];
-}
-
/// Delete one entry from the abbrlist or maphash[].
/// "mpp" is a pointer to the m_next field of the PREVIOUS entry!
static void mapblock_free(mapblock_T **mpp)
@@ -168,51 +160,47 @@ static void mapblock_free(mapblock_T **mpp)
xfree(mp);
}
-/// Return characters to represent the map mode in an allocated string
+/// put characters to represent the map mode in a string buffer
///
-/// @return [allocated] NUL-terminated string with characters.
-static char *map_mode_to_chars(int mode)
- FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_RET
+/// @param[out] buf must be at least 7 bytes (including NUL)
+void map_mode_to_chars(int mode, char *buf)
+ FUNC_ATTR_NONNULL_ALL
{
- garray_T mapmode;
-
- ga_init(&mapmode, 1, 7);
-
+ char *p = buf;
if ((mode & (MODE_INSERT | MODE_CMDLINE)) == (MODE_INSERT | MODE_CMDLINE)) {
- ga_append(&mapmode, '!'); // :map!
+ *p++ = '!'; // :map!
} else if (mode & MODE_INSERT) {
- ga_append(&mapmode, 'i'); // :imap
+ *p++ = 'i'; // :imap
} else if (mode & MODE_LANGMAP) {
- ga_append(&mapmode, 'l'); // :lmap
+ *p++ = 'l'; // :lmap
} else if (mode & MODE_CMDLINE) {
- ga_append(&mapmode, 'c'); // :cmap
+ *p++ = 'c'; // :cmap
} else if ((mode & (MODE_NORMAL | MODE_VISUAL | MODE_SELECT | MODE_OP_PENDING))
== (MODE_NORMAL | MODE_VISUAL | MODE_SELECT | MODE_OP_PENDING)) {
- ga_append(&mapmode, ' '); // :map
+ *p++ = ' '; // :map
} else {
if (mode & MODE_NORMAL) {
- ga_append(&mapmode, 'n'); // :nmap
+ *p++ = 'n'; // :nmap
}
if (mode & MODE_OP_PENDING) {
- ga_append(&mapmode, 'o'); // :omap
+ *p++ = 'o'; // :omap
}
if (mode & MODE_TERMINAL) {
- ga_append(&mapmode, 't'); // :tmap
+ *p++ = 't'; // :tmap
}
if ((mode & (MODE_VISUAL | MODE_SELECT)) == (MODE_VISUAL | MODE_SELECT)) {
- ga_append(&mapmode, 'v'); // :vmap
+ *p++ = 'v'; // :vmap
} else {
if (mode & MODE_VISUAL) {
- ga_append(&mapmode, 'x'); // :xmap
+ *p++ = 'x'; // :xmap
}
if (mode & MODE_SELECT) {
- ga_append(&mapmode, 's'); // :smap
+ *p++ = 's'; // :smap
}
}
}
- ga_append(&mapmode, NUL);
- return (char *)mapmode.ga_data;
+ *p = NUL;
}
/// @param local true for buffer-local map
@@ -231,10 +219,10 @@ static void showmap(mapblock_T *mp, bool local)
}
}
- char *const mapchars = map_mode_to_chars(mp->m_mode);
+ char mapchars[7];
+ map_mode_to_chars(mp->m_mode, mapchars);
msg_puts(mapchars);
size_t len = strlen(mapchars);
- xfree(mapchars);
while (++len <= 3) {
msg_putchar(' ');
@@ -264,7 +252,7 @@ static void showmap(mapblock_T *mp, bool local)
// Use false below if we only want things like <Up> to show up as such on
// the rhs, and not M-x etc, true gets both -- webb
if (mp->m_luaref != LUA_NOREF) {
- char *str = nlua_funcref_str(mp->m_luaref);
+ char *str = nlua_funcref_str(mp->m_luaref, NULL);
msg_puts_attr(str, HL_ATTR(HLF_8));
xfree(str);
} else if (mp->m_str[0] == NUL) {
@@ -304,11 +292,11 @@ static void showmap(mapblock_T *mp, bool local)
/// @param[in] orig_rhs Original mapping RHS, with characters to replace.
/// @param[in] rhs_lua Lua reference for Lua mappings.
/// @param[in] orig_rhs_len `strlen` of orig_rhs.
-/// @param[in] cpo_flags See param docs for @ref replace_termcodes.
+/// @param[in] cpo_val See param docs for @ref replace_termcodes.
/// @param[out] mapargs MapArguments struct holding the replaced strings.
static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs_len,
const char *const orig_rhs, const size_t orig_rhs_len,
- const LuaRef rhs_lua, const int cpo_flags,
+ const LuaRef rhs_lua, const char *const cpo_val,
MapArguments *const mapargs)
{
char lhs_buf[128];
@@ -320,12 +308,13 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs
// replace_termcodes() may move the result to allocated memory, which
// needs to be freed later (*lhs_buf and *rhs_buf).
// replace_termcodes() also removes CTRL-Vs and sometimes backslashes.
- // If something like <C-H> is simplified to 0x08 then mark it as simplified.
+ // If something like <C-H> is simplified to 0x08 then mark it as simplified
+ // and also add en entry with a modifier.
bool did_simplify = false;
const int flags = REPTERM_FROM_PART | REPTERM_DO_LT;
char *bufarg = lhs_buf;
char *replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, 0,
- flags, &did_simplify, cpo_flags);
+ flags, &did_simplify, cpo_val);
if (replaced == NULL) {
return false;
}
@@ -333,7 +322,7 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs
xstrlcpy(mapargs->lhs, replaced, sizeof(mapargs->lhs));
if (did_simplify) {
replaced = replace_termcodes(orig_lhs, orig_lhs_len, &bufarg, 0,
- flags | REPTERM_NO_SIMPLIFY, NULL, cpo_flags);
+ flags | REPTERM_NO_SIMPLIFY, NULL, cpo_val);
if (replaced == NULL) {
return false;
}
@@ -343,14 +332,14 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs
mapargs->alt_lhs_len = 0;
}
- set_maparg_rhs(orig_rhs, orig_rhs_len, rhs_lua, 0, cpo_flags, mapargs);
+ set_maparg_rhs(orig_rhs, orig_rhs_len, rhs_lua, 0, cpo_val, mapargs);
return true;
}
/// @see set_maparg_lhs_rhs
static void set_maparg_rhs(const char *const orig_rhs, const size_t orig_rhs_len,
- const LuaRef rhs_lua, const scid_T sid, const int cpo_flags,
+ const LuaRef rhs_lua, const scid_T sid, const char *const cpo_val,
MapArguments *const mapargs)
{
mapargs->rhs_lua = rhs_lua;
@@ -366,7 +355,7 @@ static void set_maparg_rhs(const char *const orig_rhs, const size_t orig_rhs_len
} else {
char *rhs_buf = NULL;
char *replaced = replace_termcodes(orig_rhs, orig_rhs_len, &rhs_buf, sid,
- REPTERM_DO_LT, NULL, cpo_flags);
+ REPTERM_DO_LT, NULL, cpo_val);
mapargs->rhs_len = strlen(replaced);
// NB: replace_termcodes may produce an empty string even if orig_rhs is non-empty
// (e.g. a single ^V, see :h map-empty-rhs)
@@ -493,7 +482,7 @@ static int str_to_mapargs(const char *strargs, bool is_unmap, MapArguments *mapa
size_t orig_rhs_len = strlen(rhs_start);
if (!set_maparg_lhs_rhs(lhs_to_replace, orig_lhs_len,
rhs_start, orig_rhs_len, LUA_NOREF,
- CPO_TO_CPO_FLAGS, mapargs)) {
+ p_cpo, mapargs)) {
return 1;
}
@@ -1104,7 +1093,7 @@ bool map_to_exists(const char *const str, const char *const modechars, const boo
char *buf = NULL;
const char *const rhs = replace_termcodes(str, strlen(str), &buf, 0,
- REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS);
+ REPTERM_DO_LT, NULL, p_cpo);
#define MAPMODE(mode, modechars, chr, modeflags) \
do { \
@@ -1122,7 +1111,7 @@ bool map_to_exists(const char *const str, const char *const modechars, const boo
MAPMODE(mode, modechars, 'c', MODE_CMDLINE);
#undef MAPMODE
- int retval = map_to_exists_mode(rhs, mode, abbr);
+ bool retval = map_to_exists_mode(rhs, mode, abbr);
xfree(buf);
return retval;
@@ -1138,7 +1127,7 @@ bool map_to_exists(const char *const str, const char *const modechars, const boo
/// @param[in] abbr true if checking abbreviations in place of mappings.
///
/// @return true if there is at least one mapping with given parameters.
-int map_to_exists_mode(const char *const rhs, const int mode, const bool abbr)
+bool map_to_exists_mode(const char *const rhs, const int mode, const bool abbr)
{
bool exp_buffer = false;
@@ -1190,16 +1179,16 @@ static bool expand_buffer = false;
/// wider than the original description. The caller has to free the string
/// afterwards.
///
-/// @param cpo_flags Value of various flags present in &cpo
+/// @param[in] cpo_val See param docs for @ref replace_termcodes.
///
/// @return NULL when there is a problem.
-static char *translate_mapping(char *str_in, int cpo_flags)
+static char *translate_mapping(const char *const str_in, const char *const cpo_val)
{
- uint8_t *str = (uint8_t *)str_in;
+ const uint8_t *str = (const uint8_t *)str_in;
garray_T ga;
ga_init(&ga, 1, 40);
- bool cpo_bslash = cpo_flags & FLAG_CPO_BSLASH;
+ const bool cpo_bslash = (vim_strchr(cpo_val, CPO_BSLASH) != NULL);
for (; *str; str++) {
int c = *str;
@@ -1378,7 +1367,7 @@ int ExpandMappings(char *pat, regmatch_T *regmatch, int *numMatches, char ***mat
continue;
}
- char *p = translate_mapping(mp->m_keys, CPO_TO_CPO_FLAGS);
+ char *p = translate_mapping(mp->m_keys, p_cpo);
if (p == NULL) {
continue;
}
@@ -1529,7 +1518,6 @@ bool check_abbr(int c, char *ptr, int col, int mincol)
: (mp = mp->m_next)) {
int qlen = mp->m_keylen;
char *q = mp->m_keys;
- int match;
if (strchr(mp->m_keys, K_SPECIAL) != NULL) {
// Might have K_SPECIAL escaped mp->m_keys.
@@ -1538,9 +1526,9 @@ bool check_abbr(int c, char *ptr, int col, int mincol)
qlen = (int)strlen(q);
}
// find entries with right mode and keys
- match = (mp->m_mode & State)
- && qlen == len
- && !strncmp(q, ptr, (size_t)len);
+ int match = (mp->m_mode & State)
+ && qlen == len
+ && !strncmp(q, ptr, (size_t)len);
if (q != mp->m_keys) {
xfree(q);
}
@@ -1588,7 +1576,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol)
}
tb[j] = NUL;
// insert the last typed char
- (void)ins_typebuf((char *)tb, 1, 0, true, mp->m_silent);
+ ins_typebuf((char *)tb, 1, 0, true, mp->m_silent);
}
// copy values here, calling eval_map_expr() may make "mp" invalid!
@@ -1604,7 +1592,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol)
}
if (s != NULL) {
// insert the to string
- (void)ins_typebuf(s, noremap, 0, true, silent);
+ ins_typebuf(s, noremap, 0, true, silent);
// no abbrev. for these chars
typebuf.tb_no_abbr_cnt += (int)strlen(s) + j + 1;
if (expr) {
@@ -1616,7 +1604,7 @@ bool check_abbr(int c, char *ptr, int col, int mincol)
tb[1] = NUL;
len = clen; // Delete characters instead of bytes
while (len-- > 0) { // delete the from string
- (void)ins_typebuf((char *)tb, 1, 0, true, silent);
+ ins_typebuf((char *)tb, 1, 0, true, silent);
}
return true;
}
@@ -1653,7 +1641,7 @@ char *eval_map_expr(mapblock_T *mp, int c)
if (mp->m_luaref != LUA_NOREF) {
Error err = ERROR_INIT;
Array args = ARRAY_DICT_INIT;
- Object ret = nlua_call_ref(mp->m_luaref, NULL, args, true, &err);
+ Object ret = nlua_call_ref(mp->m_luaref, NULL, args, kRetObject, NULL, &err);
if (ret.type == kObjectTypeString) {
p = string_to_cstr(ret.data.string);
}
@@ -1678,7 +1666,7 @@ char *eval_map_expr(mapblock_T *mp, int c)
char *res = NULL;
if (replace_keycodes) {
- replace_termcodes(p, strlen(p), &res, 0, REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS);
+ replace_termcodes(p, strlen(p), &res, 0, REPTERM_DO_LT, NULL, p_cpo);
} else {
// Escape K_SPECIAL in the result to be able to use the string as typeahead.
res = vim_strsave_escape_ks(p);
@@ -2078,12 +2066,14 @@ void f_hasmapto(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
///
/// @return A Dictionary.
static Dictionary mapblock_fill_dict(const mapblock_T *const mp, const char *lhsrawalt,
- const int buffer_value, const bool abbr, const bool compatible)
+ const int buffer_value, const bool abbr, const bool compatible,
+ Arena *arena)
FUNC_ATTR_NONNULL_ARG(1)
{
- Dictionary dict = ARRAY_DICT_INIT;
- char *const lhs = str2special_save(mp->m_keys, compatible, !compatible);
- char *const mapmode = map_mode_to_chars(mp->m_mode);
+ Dictionary dict = arena_dict(arena, 19);
+ char *const lhs = str2special_arena(mp->m_keys, compatible, !compatible, arena);
+ char *mapmode = arena_alloc(arena, 7, false);
+ map_mode_to_chars(mp->m_mode, mapmode);
int noremap_value;
if (compatible) {
@@ -2097,36 +2087,37 @@ static Dictionary mapblock_fill_dict(const mapblock_T *const mp, const char *lhs
}
if (mp->m_luaref != LUA_NOREF) {
- PUT(dict, "callback", LUAREF_OBJ(api_new_luaref(mp->m_luaref)));
+ PUT_C(dict, "callback", LUAREF_OBJ(api_new_luaref(mp->m_luaref)));
} else {
- PUT(dict, "rhs", STRING_OBJ(compatible
- ? cstr_to_string(mp->m_orig_str)
- : cstr_as_string(str2special_save(mp->m_str, false, true))));
+ String rhs = cstr_as_string(compatible
+ ? mp->m_orig_str
+ : str2special_arena(mp->m_str, false, true, arena));
+ PUT_C(dict, "rhs", STRING_OBJ(rhs));
}
if (mp->m_desc != NULL) {
- PUT(dict, "desc", CSTR_TO_OBJ(mp->m_desc));
+ PUT_C(dict, "desc", CSTR_AS_OBJ(mp->m_desc));
}
- PUT(dict, "lhs", CSTR_AS_OBJ(lhs));
- PUT(dict, "lhsraw", CSTR_TO_OBJ(mp->m_keys));
+ PUT_C(dict, "lhs", CSTR_AS_OBJ(lhs));
+ PUT_C(dict, "lhsraw", CSTR_AS_OBJ(mp->m_keys));
if (lhsrawalt != NULL) {
// Also add the value for the simplified entry.
- 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));
- PUT(dict, "expr", INTEGER_OBJ(mp->m_expr ? 1 : 0));
- PUT(dict, "silent", INTEGER_OBJ(mp->m_silent ? 1 : 0));
- PUT(dict, "sid", INTEGER_OBJ(mp->m_script_ctx.sc_sid));
- PUT(dict, "scriptversion", INTEGER_OBJ(1));
- PUT(dict, "lnum", INTEGER_OBJ(mp->m_script_ctx.sc_lnum));
- PUT(dict, "buffer", INTEGER_OBJ(buffer_value));
- PUT(dict, "nowait", INTEGER_OBJ(mp->m_nowait ? 1 : 0));
+ PUT_C(dict, "lhsrawalt", CSTR_AS_OBJ(lhsrawalt));
+ }
+ PUT_C(dict, "noremap", INTEGER_OBJ(noremap_value));
+ PUT_C(dict, "script", INTEGER_OBJ(mp->m_noremap == REMAP_SCRIPT ? 1 : 0));
+ PUT_C(dict, "expr", INTEGER_OBJ(mp->m_expr ? 1 : 0));
+ PUT_C(dict, "silent", INTEGER_OBJ(mp->m_silent ? 1 : 0));
+ PUT_C(dict, "sid", INTEGER_OBJ(mp->m_script_ctx.sc_sid));
+ PUT_C(dict, "scriptversion", INTEGER_OBJ(1));
+ PUT_C(dict, "lnum", INTEGER_OBJ(mp->m_script_ctx.sc_lnum));
+ PUT_C(dict, "buffer", INTEGER_OBJ(buffer_value));
+ PUT_C(dict, "nowait", INTEGER_OBJ(mp->m_nowait ? 1 : 0));
if (mp->m_replace_keycodes) {
- PUT(dict, "replace_keycodes", INTEGER_OBJ(1));
+ PUT_C(dict, "replace_keycodes", INTEGER_OBJ(1));
}
- PUT(dict, "mode", CSTR_AS_OBJ(mapmode));
- PUT(dict, "abbr", INTEGER_OBJ(abbr ? 1 : 0));
- PUT(dict, "mode_bits", INTEGER_OBJ(mp->m_mode));
+ PUT_C(dict, "mode", CSTR_AS_OBJ(mapmode));
+ PUT_C(dict, "abbr", INTEGER_OBJ(abbr ? 1 : 0));
+ PUT_C(dict, "mode_bits", INTEGER_OBJ(mp->m_mode));
return dict;
}
@@ -2169,7 +2160,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
const int mode = get_map_mode((char **)&which, 0);
char *keys_simplified = replace_termcodes(keys, strlen(keys), &keys_buf, 0,
- flags, &did_simplify, CPO_TO_CPO_FLAGS);
+ flags, &did_simplify, p_cpo);
mapblock_T *mp = NULL;
int buffer_local;
LuaRef rhs_lua;
@@ -2178,8 +2169,8 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
if (did_simplify) {
// When the lhs is being simplified the not-simplified keys are
// preferred for printing, like in do_map().
- (void)replace_termcodes(keys, strlen(keys), &alt_keys_buf, 0,
- flags | REPTERM_NO_SIMPLIFY, NULL, CPO_TO_CPO_FLAGS);
+ replace_termcodes(keys, strlen(keys), &alt_keys_buf, 0,
+ flags | REPTERM_NO_SIMPLIFY, NULL, p_cpo);
rhs = check_map(alt_keys_buf, mode, exact, false, abbr, &mp, &buffer_local, &rhs_lua);
}
@@ -2192,16 +2183,16 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)
rettv->vval.v_string = str2special_save(rhs, false, false);
}
} else if (rhs_lua != LUA_NOREF) {
- rettv->vval.v_string = nlua_funcref_str(mp->m_luaref);
+ rettv->vval.v_string = nlua_funcref_str(mp->m_luaref, NULL);
}
} else {
// Return a dictionary.
if (mp != NULL && (rhs != NULL || rhs_lua != LUA_NOREF)) {
- Dictionary dict = mapblock_fill_dict(mp,
- did_simplify ? keys_simplified : NULL,
- buffer_local, abbr, true);
- (void)object_to_vim(DICTIONARY_OBJ(dict), rettv, NULL);
- api_free_dictionary(dict);
+ Arena arena = ARENA_EMPTY;
+ Dictionary dict = mapblock_fill_dict(mp, did_simplify ? keys_simplified : NULL,
+ buffer_local, abbr, true, &arena);
+ object_to_vim_take_luaref(&DICTIONARY_OBJ(dict), rettv, true, NULL);
+ arena_mem_free(arena_finish(&arena));
} else {
// Return an empty dictionary.
tv_dict_alloc_ret(rettv);
@@ -2314,13 +2305,13 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
LuaRef rhs_lua = LUA_NOREF;
dictitem_T *callback_di = tv_dict_find(d, S_LEN("callback"));
if (callback_di != NULL) {
- Object callback_obj = vim_to_object(&callback_di->di_tv);
- if (callback_obj.type == kObjectTypeLuaRef && callback_obj.data.luaref != LUA_NOREF) {
- rhs_lua = callback_obj.data.luaref;
- orig_rhs = "";
- callback_obj.data.luaref = LUA_NOREF;
+ if (callback_di->di_tv.v_type == VAR_FUNC) {
+ ufunc_T *fp = find_func(callback_di->di_tv.vval.v_string);
+ if (fp != NULL && (fp->uf_flags & FC_LUAREF)) {
+ rhs_lua = api_new_luaref(fp->uf_luaref);
+ orig_rhs = "";
+ }
}
- api_free_object(callback_obj);
}
if (lhs == NULL || lhsraw == NULL || orig_rhs == NULL) {
emsg(_(e_entries_missing_in_mapset_dict_argument));
@@ -2344,14 +2335,14 @@ void f_mapset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
bool buffer = tv_dict_get_number(d, "buffer") != 0;
// mode from the dict is not used
- set_maparg_rhs(orig_rhs, strlen(orig_rhs), rhs_lua, sid, CPO_TO_CPO_FLAGS, &args);
+ set_maparg_rhs(orig_rhs, strlen(orig_rhs), rhs_lua, sid, p_cpo, &args);
mapblock_T **map_table = buffer ? curbuf->b_maphash : maphash;
mapblock_T **abbr_table = buffer ? &curbuf->b_first_abbr : &first_abbr;
// Delete any existing mapping for this lhs and mode.
MapArguments unmap_args = MAP_ARGUMENTS_INIT;
- set_maparg_lhs_rhs(lhs, strlen(lhs), "", 0, LUA_NOREF, 0, &unmap_args);
+ set_maparg_lhs_rhs(lhs, strlen(lhs), "", 0, LUA_NOREF, p_cpo, &unmap_args);
unmap_args.buffer = buffer;
buf_do_map(MAPTYPE_UNMAP, &unmap_args, mode, is_abbr, curbuf);
xfree(unmap_args.rhs);
@@ -2399,19 +2390,18 @@ void f_maplist(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
char *keys_buf = NULL;
bool did_simplify = false;
- char *lhs = str2special_save(mp->m_keys, true, false);
- (void)replace_termcodes(lhs, strlen(lhs), &keys_buf, 0, flags, &did_simplify,
- CPO_TO_CPO_FLAGS);
- xfree(lhs);
+ Arena arena = ARENA_EMPTY;
+ char *lhs = str2special_arena(mp->m_keys, true, false, &arena);
+ replace_termcodes(lhs, strlen(lhs), &keys_buf, 0, flags, &did_simplify,
+ p_cpo);
- Dictionary dict = mapblock_fill_dict(mp,
- did_simplify ? keys_buf : NULL,
- buffer_local, abbr, true);
+ Dictionary dict = mapblock_fill_dict(mp, did_simplify ? keys_buf : NULL,
+ buffer_local, abbr, true, &arena);
typval_T d = TV_INITIAL_VALUE;
- (void)object_to_vim(DICTIONARY_OBJ(dict), &d, NULL);
+ object_to_vim_take_luaref(&DICTIONARY_OBJ(dict), &d, true, NULL);
assert(d.v_type == VAR_DICT);
tv_list_append_dict(rettv->vval.v_list, d.vval.v_dict);
- api_free_dictionary(dict);
+ arena_mem_free(arena_finish(&arena));
xfree(keys_buf);
}
}
@@ -2441,7 +2431,7 @@ void f_mapcheck(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
void add_map(char *lhs, char *rhs, int mode, bool buffer)
{
MapArguments args = MAP_ARGUMENTS_INIT;
- set_maparg_lhs_rhs(lhs, strlen(lhs), rhs, strlen(rhs), LUA_NOREF, 0, &args);
+ set_maparg_lhs_rhs(lhs, strlen(lhs), rhs, strlen(rhs), LUA_NOREF, p_cpo, &args);
args.buffer = buffer;
buf_do_map(MAPTYPE_NOREMAP, &args, mode, false, curbuf);
@@ -2721,7 +2711,7 @@ void modify_keymap(uint64_t channel_id, Buffer buffer, bool is_unmap, String mod
if (!set_maparg_lhs_rhs(lhs.data, lhs.size,
rhs.data, rhs.size, lua_funcref,
- CPO_TO_CPO_FLAGS, &parsed_args)) {
+ p_cpo, &parsed_args)) {
api_set_error(err, kErrorTypeValidation, "LHS exceeds maximum map length: %s", lhs.data);
goto fail_and_free;
}
@@ -2813,20 +2803,28 @@ fail_and_free:
/// @param mode The abbreviation for the mode
/// @param buf The buffer to get the mapping array. NULL for global
/// @returns Array of maparg()-like dictionaries describing mappings
-ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf)
+ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, Arena *arena)
{
- Array mappings = ARRAY_DICT_INIT;
+ ArrayBuilder mappings = KV_INITIAL_VALUE;
+ kvi_init(mappings);
- // Convert the string mode to the integer mode
- // that is stored within each mapblock
- char *p = mode.data;
- int int_mode = get_map_mode(&p, 0);
+ char *p = mode.size > 0 ? mode.data : "m";
+ bool forceit = *p == '!';
+ // Convert the string mode to the integer mode stored within each mapblock.
+ int int_mode = get_map_mode(&p, forceit);
+ if (forceit) {
+ assert(p == mode.data);
+ p++;
+ }
+ bool is_abbrev = (int_mode & (MODE_INSERT | MODE_CMDLINE)) != 0 && *p == 'a';
// Determine the desired buffer value
int buffer_value = (buf == NULL) ? 0 : buf->handle;
- for (int i = 0; i < MAX_MAPHASH; i++) {
- for (const mapblock_T *current_maphash = get_maphash(i, buf);
+ for (int i = 0; i < (is_abbrev ? 1 : MAX_MAPHASH); i++) {
+ for (const mapblock_T *current_maphash = is_abbrev
+ ? (buf ? buf->b_first_abbr : first_abbr)
+ : (buf ? buf->b_maphash[i] : maphash[i]);
current_maphash;
current_maphash = current_maphash->m_next) {
if (current_maphash->m_simplified) {
@@ -2834,12 +2832,11 @@ ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf)
}
// Check for correct mode
if (int_mode & current_maphash->m_mode) {
- ADD(mappings,
- DICTIONARY_OBJ(mapblock_fill_dict(current_maphash, NULL,
- buffer_value, false, false)));
+ kvi_push(mappings, DICTIONARY_OBJ(mapblock_fill_dict(current_maphash, NULL, buffer_value,
+ is_abbrev, false, arena)));
}
}
}
- return mappings;
+ return arena_take_arraybuilder(arena, &mappings);
}
diff --git a/src/nvim/mapping.h b/src/nvim/mapping.h
index ffe7ab4290..b82117ea86 100644
--- a/src/nvim/mapping.h
+++ b/src/nvim/mapping.h
@@ -8,11 +8,15 @@
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
-#include "nvim/mapping_defs.h" // IWYU pragma: export
+#include "nvim/mapping_defs.h" // IWYU pragma: keep
#include "nvim/option_defs.h" // IWYU pragma: keep
#include "nvim/regexp_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "mapping.h.generated.h"
+#endif
+
/// Used for the first argument of do_map()
enum {
MAPTYPE_MAP = 0,
@@ -20,6 +24,23 @@ enum {
MAPTYPE_NOREMAP = 2,
};
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "mapping.h.generated.h"
-#endif
+/// Adjust chars in a language according to 'langmap' option.
+/// NOTE that there is no noticeable overhead if 'langmap' is not set.
+/// When set the overhead for characters < 256 is small.
+/// Don't apply 'langmap' if the character comes from the Stuff buffer or from a
+/// mapping and the langnoremap option was set.
+/// The do-while is just to ignore a ';' after the macro.
+#define LANGMAP_ADJUST(c, condition) \
+ do { \
+ if (*p_langmap \
+ && (condition) \
+ && (p_lrm || (vgetc_busy ? typebuf_maplen() == 0 : KeyTyped)) \
+ && !KeyStuffed \
+ && (c) >= 0) \
+ { \
+ if ((c) < 256) \
+ c = langmap_mapchar[c]; \
+ else \
+ c = langmap_adjust_mb(c); \
+ } \
+ } while (0)
diff --git a/src/nvim/mapping_defs.h b/src/nvim/mapping_defs.h
index 6691c5ac3b..05b8aef23a 100644
--- a/src/nvim/mapping_defs.h
+++ b/src/nvim/mapping_defs.h
@@ -3,10 +3,8 @@
#include <stdbool.h>
#include "nvim/eval/typval_defs.h"
-#include "nvim/types_defs.h"
-/// Maximum length of key sequence to be mapped.
-enum { MAXMAPLEN = 50, };
+enum { MAXMAPLEN = 50, }; ///< Maximum length of key sequence to be mapped.
/// Structure used for mappings and abbreviations.
typedef struct mapblock mapblock_T;
diff --git a/src/nvim/mark.c b/src/nvim/mark.c
index 5839cf7a2e..34e35a8277 100644
--- a/src/nvim/mark.c
+++ b/src/nvim/mark.c
@@ -2,6 +2,7 @@
#include <assert.h>
#include <limits.h>
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
@@ -14,28 +15,35 @@
#include "nvim/diff.h"
#include "nvim/edit.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/extmark.h"
#include "nvim/extmark_defs.h"
#include "nvim/fold.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
-#include "nvim/normal.h"
+#include "nvim/normal_defs.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
+#include "nvim/os/time.h"
+#include "nvim/os/time_defs.h"
#include "nvim/path.h"
+#include "nvim/pos_defs.h"
#include "nvim/quickfix.h"
#include "nvim/strings.h"
#include "nvim/textobject.h"
+#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
// This file contains routines to maintain and manipulate marks.
@@ -926,8 +934,8 @@ void ex_delmarks(exarg_T *eap)
// clear specified marks only
const Timestamp timestamp = os_time();
for (char *p = eap->arg; *p != NUL; p++) {
- int lower = ASCII_ISLOWER(*p);
- int digit = ascii_isdigit(*p);
+ bool lower = ASCII_ISLOWER(*p);
+ bool digit = ascii_isdigit(*p);
if (lower || digit || ASCII_ISUPPER(*p)) {
if (p[1] == '-') {
// clear range of marks
@@ -1288,12 +1296,12 @@ void mark_adjust_buf(buf_T *buf, linenr_T line1, linenr_T line2, linenr_T amount
if (posp->lnum == lnum && posp->col >= mincol) { \
posp->lnum += lnum_amount; \
assert(col_amount > INT_MIN && col_amount <= INT_MAX); \
- if (col_amount < 0 && posp->col <= (colnr_T) - col_amount) { \
+ if (col_amount < 0 && posp->col <= -col_amount) { \
posp->col = 0; \
} else if (posp->col < spaces_removed) { \
- posp->col = (int)col_amount + spaces_removed; \
+ posp->col = col_amount + spaces_removed; \
} else { \
- posp->col += (colnr_T)col_amount; \
+ posp->col += col_amount; \
} \
} \
}
diff --git a/src/nvim/mark.h b/src/nvim/mark.h
index 3237ae541e..c3661e2e22 100644
--- a/src/nvim/mark.h
+++ b/src/nvim/mark.h
@@ -1,20 +1,50 @@
#pragma once
-#include <stdbool.h>
-#include <stddef.h>
+#include <locale.h>
#include "nvim/ascii_defs.h"
-#include "nvim/buffer_defs.h"
-#include "nvim/ex_cmds_defs.h"
-#include "nvim/extmark_defs.h"
+#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
+#include "nvim/extmark_defs.h" // IWYU pragma: keep
#include "nvim/func_attr.h"
#include "nvim/macros_defs.h"
-#include "nvim/mark_defs.h" // IWYU pragma: export
-#include "nvim/memory.h"
+#include "nvim/mark_defs.h" // IWYU pragma: keep
#include "nvim/os/time.h"
-#include "nvim/pos_defs.h"
-/// Set fmark using given value
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "mark.h.generated.h"
+#endif
+
+static inline int mark_global_index(char name)
+ REAL_FATTR_CONST;
+/// Convert mark name to the offset
+static inline int mark_global_index(const char name)
+{
+ return (ASCII_ISUPPER(name)
+ ? (name - 'A')
+ : (ascii_isdigit(name)
+ ? (NMARKS + (name - '0'))
+ : -1));
+}
+
+static inline int mark_local_index(char name)
+ REAL_FATTR_CONST;
+/// Convert local mark name to the offset
+static inline int mark_local_index(const char name)
+{
+ return (ASCII_ISLOWER(name)
+ ? (name - 'a')
+ : (name == '"'
+ ? NMARKS
+ : (name == '^'
+ ? NMARKS + 1
+ : (name == '.'
+ ? NMARKS + 2
+ : -1))));
+}
+
+/// Global marks (marks with file number or name)
+EXTERN xfmark_T namedfm[NGLOBALMARKS] INIT( = { 0 });
+
#define SET_FMARK(fmarkp_, mark_, fnum_, view_) \
do { \
fmark_T *const fmarkp__ = fmarkp_; \
@@ -49,74 +79,3 @@
xfmarkp__->fname = fname_; \
SET_FMARK(&(xfmarkp__->fmark), mark_, fnum_, view_); \
} while (0)
-
-/// Convert mark name to the offset
-static inline int mark_global_index(const char name)
- FUNC_ATTR_CONST
-{
- return (ASCII_ISUPPER(name)
- ? (name - 'A')
- : (ascii_isdigit(name)
- ? (NMARKS + (name - '0'))
- : -1));
-}
-
-/// Convert local mark name to the offset
-static inline int mark_local_index(const char name)
- FUNC_ATTR_CONST
-{
- return (ASCII_ISLOWER(name)
- ? (name - 'a')
- : (name == '"'
- ? NMARKS
- : (name == '^'
- ? NMARKS + 1
- : (name == '.'
- ? NMARKS + 2
- : -1))));
-}
-
-static inline bool lt(pos_T a, pos_T b)
- REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE;
-static inline bool equalpos(pos_T a, pos_T b)
- REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE;
-static inline bool ltoreq(pos_T a, pos_T b)
- REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE;
-static inline void clearpos(pos_T *a)
- REAL_FATTR_ALWAYS_INLINE;
-
-/// Return true if position a is before (less than) position b.
-static inline bool lt(pos_T a, pos_T b)
-{
- if (a.lnum != b.lnum) {
- return a.lnum < b.lnum;
- } else if (a.col != b.col) {
- return a.col < b.col;
- } else {
- return a.coladd < b.coladd;
- }
-}
-
-/// Return true if position a and b are equal.
-static inline bool equalpos(pos_T a, pos_T b)
-{
- return (a.lnum == b.lnum) && (a.col == b.col) && (a.coladd == b.coladd);
-}
-
-/// Return true if position a is less than or equal to b.
-static inline bool ltoreq(pos_T a, pos_T b)
-{
- return lt(a, b) || equalpos(a, b);
-}
-
-/// Clear the pos_T structure pointed to by a.
-static inline void clearpos(pos_T *a)
-{
- a->lnum = 0;
- a->col = 0;
- a->coladd = 0;
-}
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "mark.h.generated.h"
-#endif
diff --git a/src/nvim/mark_defs.h b/src/nvim/mark_defs.h
index 67532d030f..98bdb6ee04 100644
--- a/src/nvim/mark_defs.h
+++ b/src/nvim/mark_defs.h
@@ -2,7 +2,6 @@
#include "nvim/eval/typval_defs.h"
#include "nvim/os/time_defs.h"
-#include "nvim/pos_defs.h"
// marks: positions in a file
// (a normal mark is a lnum/col pair, the same as a file position)
@@ -59,7 +58,7 @@ typedef enum {
#define TAGSTACKSIZE 20
/// Represents view in which the mark was created
-typedef struct fmarkv {
+typedef struct {
linenr_T topline_offset; ///< Amount of lines from the mark lnum to the top of the window.
///< Use MAXLNUM to indicate that the mark does not have a view.
} fmarkv_T;
@@ -67,7 +66,7 @@ typedef struct fmarkv {
#define INIT_FMARKV { MAXLNUM }
/// Structure defining single local mark
-typedef struct filemark {
+typedef struct {
pos_T mark; ///< Cursor position.
int fnum; ///< File number.
Timestamp timestamp; ///< Time when this mark was last set.
@@ -78,12 +77,50 @@ typedef struct filemark {
#define INIT_FMARK { { 0, 0, 0 }, 0, 0, INIT_FMARKV, NULL }
/// Structure defining extended mark (mark with file name attached)
-typedef struct xfilemark {
+typedef struct {
fmark_T fmark; ///< Actual mark.
char *fname; ///< File name, used when fnum == 0.
} xfmark_T;
#define INIT_XFMARK { INIT_FMARK, NULL }
-/// Global marks (marks with file number or name)
-EXTERN xfmark_T namedfm[NGLOBALMARKS] INIT( = { 0 });
+/// Set fmark using given value
+static inline bool lt(pos_T a, pos_T b)
+ REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE;
+/// Return true if position a is before (less than) position b.
+static inline bool lt(pos_T a, pos_T b)
+{
+ if (a.lnum != b.lnum) {
+ return a.lnum < b.lnum;
+ } else if (a.col != b.col) {
+ return a.col < b.col;
+ } else {
+ return a.coladd < b.coladd;
+ }
+}
+
+static inline bool equalpos(pos_T a, pos_T b)
+ REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE;
+/// Return true if position a and b are equal.
+static inline bool equalpos(pos_T a, pos_T b)
+{
+ return (a.lnum == b.lnum) && (a.col == b.col) && (a.coladd == b.coladd);
+}
+
+static inline bool ltoreq(pos_T a, pos_T b)
+ REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE;
+/// Return true if position a is less than or equal to b.
+static inline bool ltoreq(pos_T a, pos_T b)
+{
+ return lt(a, b) || equalpos(a, b);
+}
+
+static inline void clearpos(pos_T *a)
+ REAL_FATTR_ALWAYS_INLINE;
+/// Clear the pos_T structure pointed to by a.
+static inline void clearpos(pos_T *a)
+{
+ a->lnum = 0;
+ a->col = 0;
+ a->coladd = 0;
+}
diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c
index b555b3b4ae..0ebebf409e 100644
--- a/src/nvim/marktree.c
+++ b/src/nvim/marktree.c
@@ -47,21 +47,22 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include "klib/kvec.h"
-#include "nvim/garray.h"
+#include "nvim/macros_defs.h"
+#include "nvim/map_defs.h"
#include "nvim/marktree.h"
#include "nvim/memory.h"
#include "nvim/pos_defs.h"
// only for debug functions
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/garray.h"
#include "nvim/garray_defs.h"
-#include "nvim/macros_defs.h"
#define T MT_BRANCH_FACTOR
-#define ILEN (sizeof(MTNode) + (2 * T) * sizeof(void *))
+#define ILEN (sizeof(MTNode) + sizeof(struct mtnode_inner_s))
#define ID_INCR (((uint64_t)1) << 2)
@@ -146,7 +147,8 @@ static inline int marktree_getp_aux(const MTNode *x, MTKey k, bool *match)
bool dummy_match;
bool *m = match ? match : &dummy_match;
- int begin = 0, end = x->n;
+ int begin = 0;
+ int end = x->n;
if (x->n == 0) {
*m = false;
return -1;
@@ -179,6 +181,8 @@ static MTNode *id2node(MarkTree *b, uint64_t id)
return pmap_get(uint64_t)(b->id2node, id);
}
+#define ptr s->i_ptr
+#define meta s->i_meta
// put functions
// x must be an internal node, which is not full
@@ -224,15 +228,17 @@ static inline void split_node(MarkTree *b, MTNode *x, const int i, MTKey next)
}
if (y->level) {
memcpy(z->ptr, &y->ptr[T], sizeof(MTNode *) * T);
+ memcpy(z->meta, &y->meta[T], sizeof(z->meta[0]) * T);
for (int j = 0; j < T; j++) {
z->ptr[j]->parent = z;
z->ptr[j]->p_idx = (int16_t)j;
}
}
y->n = T - 1;
- memmove(&x->ptr[i + 2], &x->ptr[i + 1],
- sizeof(MTNode *) * (size_t)(x->n - i));
+ memmove(&x->ptr[i + 2], &x->ptr[i + 1], sizeof(MTNode *) * (size_t)(x->n - i));
+ memmove(&x->meta[i + 2], &x->meta[i + 1], sizeof(x->meta[0]) * (size_t)(x->n - i));
x->ptr[i + 1] = z;
+ meta_describe_node(x->meta[i + 1], z);
z->parent = x; // == y->parent
for (int j = i + 1; j < x->n + 2; j++) {
x->ptr[j]->p_idx = (int16_t)j;
@@ -244,6 +250,13 @@ static inline void split_node(MarkTree *b, MTNode *x, const int i, MTKey next)
refkey(b, x, i);
x->n++;
+ uint32_t meta_inc[4];
+ meta_describe_key(meta_inc, x->key[i]);
+ for (int m = 0; m < kMTMetaCount; m++) {
+ // y used contain all of z and x->key[i], discount those
+ x->meta[i][m] -= (x->meta[i + 1][m] + meta_inc[m]);
+ }
+
for (int j = 0; j < T - 1; j++) {
relative(x->key[i].pos, &z->key[j].pos);
}
@@ -260,7 +273,7 @@ static inline void split_node(MarkTree *b, MTNode *x, const int i, MTKey next)
}
// x must not be a full node (even if there might be internal space)
-static inline void marktree_putp_aux(MarkTree *b, MTNode *x, MTKey k)
+static inline void marktree_putp_aux(MarkTree *b, MTNode *x, MTKey k, uint32_t *meta_inc)
{
// TODO(bfredl): ugh, make sure this is the _last_ valid (pos, gravity) position,
// to minimize movement
@@ -283,7 +296,10 @@ static inline void marktree_putp_aux(MarkTree *b, MTNode *x, MTKey k)
if (i > 0) {
relative(x->key[i - 1].pos, &k.pos);
}
- marktree_putp_aux(b, x->ptr[i], k);
+ marktree_putp_aux(b, x->ptr[i], k, meta_inc);
+ for (int m = 0; m < kMTMetaCount; m++) {
+ x->meta[i][m] += meta_inc[m];
+ }
}
}
@@ -303,7 +319,8 @@ void marktree_put(MarkTree *b, MTKey key, int end_row, int end_col, bool end_rig
|(uint16_t)(end_right ? MT_FLAG_RIGHT_GRAVITY : 0));
end_key.pos = (MTPos){ end_row, end_col };
marktree_put_key(b, end_key);
- MarkTreeIter itr[1] = { 0 }, end_itr[1] = { 0 };
+ MarkTreeIter itr[1] = { 0 };
+ MarkTreeIter end_itr[1] = { 0 };
marktree_lookup(b, mt_lookup_key(key), itr);
marktree_lookup(b, mt_lookup_key(end_key), end_itr);
@@ -413,7 +430,7 @@ void marktree_intersect_pair(MarkTree *b, uint64_t id, MarkTreeIter *itr, MarkTr
}
}
}
- marktree_itr_next_skip(b, itr, skip, true, NULL);
+ marktree_itr_next_skip(b, itr, skip, true, NULL, NULL);
}
#undef iat
}
@@ -426,24 +443,75 @@ static MTNode *marktree_alloc_node(MarkTree *b, bool internal)
return x;
}
+// really meta_inc[kMTMetaCount]
+static void meta_describe_key_inc(uint32_t *meta_inc, MTKey *k)
+{
+ if (!mt_end(*k)) {
+ meta_inc[kMTMetaInline] += (k->flags & MT_FLAG_DECOR_VIRT_TEXT_INLINE) ? 1 : 0;
+ meta_inc[kMTMetaLines] += (k->flags & MT_FLAG_DECOR_VIRT_LINES) ? 1 : 0;
+ meta_inc[kMTMetaSignHL] += (k->flags & MT_FLAG_DECOR_SIGNHL) ? 1 : 0;
+ meta_inc[kMTMetaSignText] += (k->flags & MT_FLAG_DECOR_SIGNTEXT) ? 1 : 0;
+ }
+}
+
+static void meta_describe_key(uint32_t *meta_inc, MTKey k)
+{
+ memset(meta_inc, 0, kMTMetaCount * sizeof(*meta_inc));
+ meta_describe_key_inc(meta_inc, &k);
+}
+
+// if x is internal, asumes x->meta[..] of children are correct
+static void meta_describe_node(uint32_t *meta_node, MTNode *x)
+{
+ memset(meta_node, 0, kMTMetaCount * sizeof(meta_node[0]));
+ for (int i = 0; i < x->n; i++) {
+ meta_describe_key_inc(meta_node, &x->key[i]);
+ }
+ if (x->level) {
+ for (int i = 0; i < x->n + 1; i++) {
+ for (int m = 0; m < kMTMetaCount; m++) {
+ meta_node[m] += x->meta[i][m];
+ }
+ }
+ }
+}
+
+static bool meta_has(const uint32_t *meta_count, MetaFilter meta_filter)
+{
+ uint32_t count = 0;
+ for (int m = 0; m < kMTMetaCount; m++) {
+ count += meta_count[m] & meta_filter[m];
+ }
+ return count > 0;
+}
+
void marktree_put_key(MarkTree *b, MTKey k)
{
k.flags |= MT_FLAG_REAL; // let's be real.
if (!b->root) {
b->root = marktree_alloc_node(b, true);
}
- b->n_keys++;
MTNode *r = b->root;
if (r->n == 2 * T - 1) {
MTNode *s = marktree_alloc_node(b, true);
b->root = s; s->level = r->level + 1; s->n = 0;
s->ptr[0] = r;
+ for (int m = 0; m < kMTMetaCount; m++) {
+ s->meta[0][m] = b->meta_root[m];
+ }
r->parent = s;
r->p_idx = 0;
split_node(b, s, 0, k);
r = s;
}
- marktree_putp_aux(b, r, k);
+
+ uint32_t meta_inc[4];
+ meta_describe_key(meta_inc, k);
+ marktree_putp_aux(b, r, k, meta_inc);
+ for (int m = 0; m < 4; m++) {
+ b->meta_root[m] += meta_inc[m];
+ }
+ b->n_keys++;
}
/// INITIATING DELETION PROTOCOL:
@@ -495,6 +563,7 @@ uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
}
}
+ // 2.
if (itr->x->level) {
if (rev) {
abort();
@@ -509,6 +578,9 @@ uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
MTNode *x = itr->x;
assert(x->level == 0);
MTKey intkey = x->key[itr->i];
+
+ uint32_t meta_inc[4];
+ meta_describe_key(meta_inc, intkey);
if (x->n > itr->i + 1) {
memmove(&x->key[itr->i], &x->key[itr->i + 1],
sizeof(MTKey) * (size_t)(x->n - itr->i - 1));
@@ -554,11 +626,16 @@ uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
}
}
+ for (int m = 0; m < kMTMetaCount; m++) {
+ p->meta[lnode->p_idx][m] -= meta_inc[m];
+ }
+
lnode = p;
ilvl--;
} while (lnode != cur);
MTKey deleted = cur->key[curi];
+ meta_describe_key(meta_inc, deleted);
cur->key[curi] = intkey;
refkey(b, cur, curi);
// if `did_bubble` then we already added `start_id` to some parent
@@ -583,6 +660,20 @@ uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
itr->i--;
}
+ MTNode *lnode = cur;
+ while (lnode->parent) {
+ uint32_t *meta_p = lnode->parent->meta[lnode->p_idx];
+ for (int m = 0; m < kMTMetaCount; m++) {
+ meta_p[m] -= meta_inc[m];
+ }
+
+ lnode = lnode->parent;
+ }
+ for (int m = 0; m < kMTMetaCount; m++) {
+ assert(b->meta_root[m] >= meta_inc[m]);
+ b->meta_root[m] -= meta_inc[m];
+ }
+
// 5.
bool itr_dirty = false;
int rlvl = itr->lvl - 1;
@@ -643,6 +734,10 @@ uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
if (b->root->level) {
MTNode *oldroot = b->root;
b->root = b->root->ptr[0];
+ for (int m = 0; m < kMTMetaCount; m++) {
+ assert(b->meta_root[m] == oldroot->meta[0][m]);
+ }
+
b->root->parent = NULL;
marktree_free_node(b, oldroot);
} else {
@@ -679,13 +774,44 @@ uint64_t marktree_del_itr(MarkTree *b, MarkTreeIter *itr, bool rev)
return other;
}
+void marktree_revise_flags(MarkTree *b, MarkTreeIter *itr, uint16_t new_flags)
+{
+ uint32_t meta_old[4];
+ meta_describe_key(meta_old, rawkey(itr));
+ rawkey(itr).flags &= (uint16_t) ~MT_FLAG_EXTERNAL_MASK;
+ rawkey(itr).flags |= new_flags;
+
+ uint32_t meta_new[4];
+ meta_describe_key(meta_new, rawkey(itr));
+
+ if (!memcmp(meta_old, meta_new, sizeof(meta_old))) {
+ return;
+ }
+
+ MTNode *lnode = itr->x;
+ while (lnode->parent) {
+ uint32_t *meta_p = lnode->parent->meta[lnode->p_idx];
+ for (int m = 0; m < kMTMetaCount; m++) {
+ meta_p[m] += meta_new[m] - meta_old[m];
+ }
+
+ lnode = lnode->parent;
+ }
+
+ for (int m = 0; m < kMTMetaCount; m++) {
+ b->meta_root[m] += meta_new[m] - meta_old[m];
+ }
+}
+
/// similar to intersect_common but modify x and y in place to retain
/// only the items which are NOT in common
static void intersect_merge(Intersection *restrict m, Intersection *restrict x,
Intersection *restrict y)
{
- size_t xi = 0, yi = 0;
- size_t xn = 0, yn = 0;
+ size_t xi = 0;
+ size_t yi = 0;
+ size_t xn = 0;
+ size_t yn = 0;
while (xi < kv_size(*x) && yi < kv_size(*y)) {
if (kv_A(*x, xi) == kv_A(*y, yi)) {
// TODO(bfredl): kvi_pushp is actually quite complex, break out kvi_resize() to a function?
@@ -717,8 +843,10 @@ static void intersect_merge(Intersection *restrict m, Intersection *restrict x,
static void intersect_mov(Intersection *restrict x, Intersection *restrict y,
Intersection *restrict w, Intersection *restrict d)
{
- size_t wi = 0, yi = 0;
- size_t wn = 0, yn = 0;
+ size_t wi = 0;
+ size_t yi = 0;
+ size_t wn = 0;
+ size_t yn = 0;
size_t xi = 0;
while (wi < kv_size(*w) || xi < kv_size(*x)) {
if (wi < kv_size(*w) && (xi >= kv_size(*x) || kv_A(*x, xi) >= kv_A(*w, wi))) {
@@ -810,7 +938,8 @@ bool intersect_mov_test(const uint64_t *x, size_t nx, const uint64_t *y, size_t
/// intersection: i = x & y
static void intersect_common(Intersection *i, Intersection *x, Intersection *y)
{
- size_t xi = 0, yi = 0;
+ size_t xi = 0;
+ size_t yi = 0;
while (xi < kv_size(*x) && yi < kv_size(*y)) {
if (kv_A(*x, xi) == kv_A(*y, yi)) {
kvi_push(*i, kv_A(*x, xi));
@@ -827,7 +956,8 @@ static void intersect_common(Intersection *i, Intersection *x, Intersection *y)
// inplace union: x |= y
static void intersect_add(Intersection *x, Intersection *y)
{
- size_t xi = 0, yi = 0;
+ size_t xi = 0;
+ size_t yi = 0;
while (xi < kv_size(*x) && yi < kv_size(*y)) {
if (kv_A(*x, xi) == kv_A(*y, yi)) {
xi++;
@@ -854,7 +984,8 @@ static void intersect_add(Intersection *x, Intersection *y)
// inplace asymmetric difference: x &= ~y
static void intersect_sub(Intersection *restrict x, Intersection *restrict y)
{
- size_t xi = 0, yi = 0;
+ size_t xi = 0;
+ size_t yi = 0;
size_t xn = 0;
while (xi < kv_size(*x) && yi < kv_size(*y)) {
if (kv_A(*x, xi) == kv_A(*y, yi)) {
@@ -898,11 +1029,12 @@ static void bubble_up(MTNode *x)
static MTNode *merge_node(MarkTree *b, MTNode *p, int i)
{
- MTNode *x = p->ptr[i], *y = p->ptr[i + 1];
- Intersection m;
- kvi_init(m);
+ MTNode *x = p->ptr[i];
+ MTNode *y = p->ptr[i + 1];
+ Intersection mi;
+ kvi_init(mi);
- intersect_merge(&m, &x->intersect, &y->intersect);
+ intersect_merge(&mi, &x->intersect, &y->intersect);
x->key[x->n] = p->key[i];
refkey(b, x, x->n);
@@ -910,6 +1042,9 @@ static MTNode *merge_node(MarkTree *b, MTNode *p, int i)
relative(p->key[i - 1].pos, &x->key[x->n].pos);
}
+ uint32_t meta_inc[4];
+ meta_describe_key(meta_inc, x->key[x->n]);
+
memmove(&x->key[x->n + 1], y->key, (size_t)y->n * sizeof(MTKey));
for (int k = 0; k < y->n; k++) {
refkey(b, x, x->n + 1 + k);
@@ -919,6 +1054,7 @@ static MTNode *merge_node(MarkTree *b, MTNode *p, int i)
// bubble down: ranges that intersected old-x but not old-y or vice versa
// must be moved to their respective children
memmove(&x->ptr[x->n + 1], y->ptr, ((size_t)y->n + 1) * sizeof(MTNode *));
+ memmove(&x->meta[x->n + 1], y->meta, ((size_t)y->n + 1) * sizeof(y->meta[0]));
for (int k = 0; k < x->n + 1; k++) {
// TODO(bfredl): dedicated impl for "Z |= Y"
for (size_t idx = 0; idx < kv_size(x->intersect); idx++) {
@@ -937,9 +1073,14 @@ static MTNode *merge_node(MarkTree *b, MTNode *p, int i)
}
}
x->n += y->n + 1;
+ for (int m = 0; m < kMTMetaCount; m++) {
+ // x now contains everything of y plus old p->key[i]
+ p->meta[i][m] += (p->meta[i + 1][m] + meta_inc[m]);
+ }
+
memmove(&p->key[i], &p->key[i + 1], (size_t)(p->n - i - 1) * sizeof(MTKey));
- memmove(&p->ptr[i + 1], &p->ptr[i + 2],
- (size_t)(p->n - i - 1) * sizeof(MTKey *));
+ memmove(&p->ptr[i + 1], &p->ptr[i + 2], (size_t)(p->n - i - 1) * sizeof(MTKey *));
+ memmove(&p->meta[i + 1], &p->meta[i + 2], (size_t)(p->n - i - 1) * sizeof(p->meta[0]));
for (int j = i + 1; j < p->n; j++) { // note: one has been deleted
p->ptr[j]->p_idx = (int16_t)j;
}
@@ -950,7 +1091,7 @@ static MTNode *merge_node(MarkTree *b, MTNode *p, int i)
// move of a kvec_withinit_t, messy!
// TODO(bfredl): special case version of intersect_merge(x_out, x_in_m_out, y) to avoid this
- kvi_move(&x->intersect, &m);
+ kvi_move(&x->intersect, &mi);
return x;
}
@@ -975,20 +1116,39 @@ void kvi_move(Intersection *dest, Intersection *src)
// key inside x, if x is the first leaf)
static void pivot_right(MarkTree *b, MTPos p_pos, MTNode *p, const int i)
{
- MTNode *x = p->ptr[i], *y = p->ptr[i + 1];
+ MTNode *x = p->ptr[i];
+ MTNode *y = p->ptr[i + 1];
memmove(&y->key[1], y->key, (size_t)y->n * sizeof(MTKey));
if (y->level) {
memmove(&y->ptr[1], y->ptr, ((size_t)y->n + 1) * sizeof(MTNode *));
+ memmove(&y->meta[1], y->meta, ((size_t)y->n + 1) * sizeof(y->meta[0]));
for (int j = 1; j < y->n + 2; j++) {
y->ptr[j]->p_idx = (int16_t)j;
}
}
+
y->key[0] = p->key[i];
refkey(b, y, 0);
p->key[i] = x->key[x->n - 1];
refkey(b, p, i);
+
+ uint32_t meta_inc_y[4];
+ meta_describe_key(meta_inc_y, y->key[0]);
+ uint32_t meta_inc_x[4];
+ meta_describe_key(meta_inc_x, p->key[i]);
+
+ for (int m = 0; m < kMTMetaCount; m++) {
+ p->meta[i + 1][m] += meta_inc_y[m];
+ p->meta[i][m] -= meta_inc_x[m];
+ }
+
if (x->level) {
y->ptr[0] = x->ptr[x->n];
+ memcpy(y->meta[0], x->meta[x->n], sizeof(y->meta[0]));
+ for (int m = 0; m < kMTMetaCount; m++) {
+ p->meta[i + 1][m] += y->meta[0][m];
+ p->meta[i][m] -= y->meta[0][m];
+ }
y->ptr[0]->parent = y;
y->ptr[0]->p_idx = 0;
}
@@ -1040,7 +1200,8 @@ static void pivot_right(MarkTree *b, MTPos p_pos, MTNode *p, const int i)
static void pivot_left(MarkTree *b, MTPos p_pos, MTNode *p, int i)
{
- MTNode *x = p->ptr[i], *y = p->ptr[i + 1];
+ MTNode *x = p->ptr[i];
+ MTNode *y = p->ptr[i + 1];
// reverse from how we "always" do it. but pivot_left
// is just the inverse of pivot_right, so reverse it literally.
@@ -1056,14 +1217,30 @@ static void pivot_left(MarkTree *b, MTPos p_pos, MTNode *p, int i)
refkey(b, x, x->n);
p->key[i] = y->key[0];
refkey(b, p, i);
+
+ uint32_t meta_inc_x[4];
+ meta_describe_key(meta_inc_x, x->key[x->n]);
+ uint32_t meta_inc_y[4];
+ meta_describe_key(meta_inc_y, p->key[i]);
+ for (int m = 0; m < kMTMetaCount; m++) {
+ p->meta[i][m] += meta_inc_x[m];
+ p->meta[i + 1][m] -= meta_inc_y[m];
+ }
+
if (x->level) {
x->ptr[x->n + 1] = y->ptr[0];
+ memcpy(x->meta[x->n + 1], y->meta[0], sizeof(y->meta[0]));
+ for (int m = 0; m < kMTMetaCount; m++) {
+ p->meta[i + 1][m] -= y->meta[0][m];
+ p->meta[i][m] += y->meta[0][m];
+ }
x->ptr[x->n + 1]->parent = x;
x->ptr[x->n + 1]->p_idx = (int16_t)(x->n + 1);
}
memmove(y->key, &y->key[1], (size_t)(y->n - 1) * sizeof(MTKey));
if (y->level) {
memmove(y->ptr, &y->ptr[1], (size_t)y->n * sizeof(MTNode *));
+ memmove(y->meta, &y->meta[1], (size_t)y->n * sizeof(y->meta[0]));
for (int j = 0; j < y->n; j++) { // note: last item deleted
y->ptr[j]->p_idx = (int16_t)j;
}
@@ -1117,8 +1294,8 @@ void marktree_clear(MarkTree *b)
b->root = NULL;
}
map_destroy(uint64_t, b->id2node);
- *b->id2node = (PMap(uint64_t)) MAP_INIT;
b->n_keys = 0;
+ memset(b->meta_root, 0, kMTMetaCount * sizeof(b->meta_root[0]));
assert(b->n_nodes == 0);
}
@@ -1219,11 +1396,11 @@ void marktree_restore_pair(MarkTree *b, MTKey key)
bool marktree_itr_get(MarkTree *b, int32_t row, int col, MarkTreeIter *itr)
{
- return marktree_itr_get_ext(b, MTPos(row, col), itr, false, false, NULL);
+ return marktree_itr_get_ext(b, MTPos(row, col), itr, false, false, NULL, NULL);
}
bool marktree_itr_get_ext(MarkTree *b, MTPos p, MarkTreeIter *itr, bool last, bool gravity,
- MTPos *oldbase)
+ MTPos *oldbase, MetaFilter meta_filter)
{
if (b->n_keys == 0) {
itr->x = NULL;
@@ -1246,6 +1423,12 @@ bool marktree_itr_get_ext(MarkTree *b, MTPos p, MarkTreeIter *itr, bool last, bo
if (itr->x->level == 0) {
break;
}
+ if (meta_filter) {
+ if (!meta_has(itr->x->meta[itr->i], meta_filter)) {
+ // this takes us to the interal position after the first rejected node
+ break;
+ }
+ }
itr->s[itr->lvl].i = itr->i;
itr->s[itr->lvl].oldcol = itr->pos.col;
@@ -1264,7 +1447,8 @@ bool marktree_itr_get_ext(MarkTree *b, MTPos p, MarkTreeIter *itr, bool last, bo
if (last) {
return marktree_itr_prev(b, itr);
} else if (itr->i >= itr->x->n) {
- return marktree_itr_next(b, itr);
+ // no need for "meta_filter" here, this just goes up one step
+ return marktree_itr_next_skip(b, itr, true, false, NULL, NULL);
}
return true;
}
@@ -1321,16 +1505,21 @@ int marktree_itr_last(MarkTree *b, MarkTreeIter *itr)
bool marktree_itr_next(MarkTree *b, MarkTreeIter *itr)
{
- return marktree_itr_next_skip(b, itr, false, false, NULL);
+ return marktree_itr_next_skip(b, itr, false, false, NULL, NULL);
}
static bool marktree_itr_next_skip(MarkTree *b, MarkTreeIter *itr, bool skip, bool preload,
- MTPos oldbase[])
+ MTPos oldbase[], MetaFilter meta_filter)
{
if (!itr->x) {
return false;
}
itr->i++;
+ if (meta_filter && itr->x->level > 0) {
+ if (!meta_has(itr->x->meta[itr->i], meta_filter)) {
+ skip = true;
+ }
+ }
if (itr->x->level == 0 || skip) {
if (preload && itr->x->level == 0 && skip) {
// skip rest of this leaf node
@@ -1372,14 +1561,98 @@ static bool marktree_itr_next_skip(MarkTree *b, MarkTreeIter *itr, bool skip, bo
if (preload && itr->x->level) {
itr->i = -1;
break;
- } else {
- itr->i = 0;
+ }
+ itr->i = 0;
+ if (meta_filter && itr->x->level) {
+ if (!meta_has(itr->x->meta[0], meta_filter)) {
+ // itr->x has filtered keys but x->ptr[0] does not, don't enter the latter
+ break;
+ }
}
}
}
return true;
}
+bool marktree_itr_get_filter(MarkTree *b, int32_t row, int col, int stop_row, int stop_col,
+ MetaFilter meta_filter, MarkTreeIter *itr)
+{
+ if (!meta_has(b->meta_root, meta_filter)) {
+ return false;
+ }
+ if (!marktree_itr_get_ext(b, MTPos(row, col), itr, false, false, NULL, meta_filter)) {
+ return false;
+ }
+
+ return marktree_itr_check_filter(b, itr, stop_row, stop_col, meta_filter);
+}
+
+/// use after marktree_itr_get_overlap() to continue in a filtered fashion
+///
+/// not strictly needed but steps out to the right parent node where there
+/// might be "start" keys matching the filter ("end" keys are properly handled
+/// by marktree_itr_step_overlap() already)
+bool marktree_itr_step_out_filter(MarkTree *b, MarkTreeIter *itr, MetaFilter meta_filter)
+{
+ if (!meta_has(b->meta_root, meta_filter)) {
+ itr->x = NULL;
+ return false;
+ }
+
+ while (itr->x && itr->x->parent) {
+ if (meta_has(itr->x->parent->meta[itr->x->p_idx], meta_filter)) {
+ return true;
+ }
+
+ itr->i = itr->x->n;
+
+ // no filter needed, just reuse the code path for step to parent
+ marktree_itr_next_skip(b, itr, true, false, NULL, NULL);
+ }
+
+ return itr->x;
+}
+
+bool marktree_itr_next_filter(MarkTree *b, MarkTreeIter *itr, int stop_row, int stop_col,
+ MetaFilter meta_filter)
+{
+ if (!marktree_itr_next_skip(b, itr, false, false, NULL, meta_filter)) {
+ return false;
+ }
+
+ return marktree_itr_check_filter(b, itr, stop_row, stop_col, meta_filter);
+}
+
+const uint32_t meta_map[4] = { MT_FLAG_DECOR_VIRT_TEXT_INLINE, MT_FLAG_DECOR_VIRT_LINES,
+ MT_FLAG_DECOR_SIGNHL, MT_FLAG_DECOR_SIGNTEXT };
+static bool marktree_itr_check_filter(MarkTree *b, MarkTreeIter *itr, int stop_row, int stop_col,
+ MetaFilter meta_filter)
+{
+ MTPos stop_pos = MTPos(stop_row, stop_col);
+
+ uint32_t key_filter = 0;
+ for (int m = 0; m < kMTMetaCount; m++) {
+ key_filter |= meta_map[m]&meta_filter[m];
+ }
+
+ while (true) {
+ if (pos_leq(stop_pos, marktree_itr_pos(itr))) {
+ itr->x = NULL;
+ return false;
+ }
+
+ MTKey k = rawkey(itr);
+ if (!mt_end(k) && (k.flags & key_filter)) {
+ return true;
+ }
+
+ // this skips subtrees, but not keys, thus the outer loop
+ if (!marktree_itr_next_skip(b, itr, false, false, NULL, meta_filter)) {
+ return false;
+ }
+ }
+}
+
bool marktree_itr_prev(MarkTree *b, MarkTreeIter *itr)
{
if (!itr->x) {
@@ -1558,7 +1831,7 @@ bool marktree_itr_step_overlap(MarkTree *b, MarkTreeIter *itr, MTPair *pair)
}
unrelative(itr->pos, &k.pos);
MTKey start = marktree_lookup(b, id, NULL);
- if (pos_less(itr->intersect_pos, start.pos)) {
+ if (pos_leq(itr->intersect_pos, start.pos)) {
continue;
}
*pair = mtpair_from(start, k);
@@ -1590,6 +1863,33 @@ static void swap_keys(MarkTree *b, MarkTreeIter *itr1, MarkTreeIter *itr2, Damag
kvi_push(*damage, ((Damage){ mt_lookup_key(rawkey(itr2)), itr2->x, itr1->x,
itr2->i, itr1->i }));
}
+
+ uint32_t meta_inc_1[4];
+ meta_describe_key(meta_inc_1, rawkey(itr1));
+ uint32_t meta_inc_2[4];
+ meta_describe_key(meta_inc_2, rawkey(itr2));
+
+ if (memcmp(meta_inc_1, meta_inc_2, sizeof(meta_inc_1)) != 0) {
+ MTNode *x1 = itr1->x;
+ MTNode *x2 = itr2->x;
+ while (x1 != x2) {
+ if (x1->level <= x2->level) {
+ // as the root node uniquely has the highest level, x1 cannot be it
+ uint32_t *meta_node = x1->parent->meta[x1->p_idx];
+ for (int m = 0; m < kMTMetaCount; m++) {
+ meta_node[m] += meta_inc_2[m] - meta_inc_1[m];
+ }
+ x1 = x1->parent;
+ }
+ if (x2->level < x1->level) {
+ uint32_t *meta_node = x2->parent->meta[x2->p_idx];
+ for (int m = 0; m < kMTMetaCount; m++) {
+ meta_node[m] += meta_inc_1[m] - meta_inc_2[m];
+ }
+ x2 = x2->parent;
+ }
+ }
+ }
}
MTKey key1 = rawkey(itr1);
@@ -1604,7 +1904,8 @@ static void swap_keys(MarkTree *b, MarkTreeIter *itr1, MarkTreeIter *itr2, Damag
static int damage_cmp(const void *s1, const void *s2)
{
- Damage *d1 = (Damage *)s1, *d2 = (Damage *)s2;
+ Damage *d1 = (Damage *)s1;
+ Damage *d2 = (Damage *)s2;
assert(d1->id != d2->id);
return d1->id > d2->id ? 1 : -1;
}
@@ -1620,11 +1921,12 @@ bool marktree_splice(MarkTree *b, int32_t start_line, int start_col, int old_ext
bool same_line = old_extent.row == 0 && new_extent.row == 0;
unrelative(start, &old_extent);
unrelative(start, &new_extent);
- MarkTreeIter itr[1] = { 0 }, enditr[1] = { 0 };
+ MarkTreeIter itr[1] = { 0 };
+ MarkTreeIter enditr[1] = { 0 };
MTPos oldbase[MT_MAX_DEPTH] = { 0 };
- marktree_itr_get_ext(b, start, itr, false, true, oldbase);
+ marktree_itr_get_ext(b, start, itr, false, true, oldbase, NULL);
if (!itr->x) {
// den e FÄRDIG
return false;
@@ -1637,7 +1939,7 @@ bool marktree_splice(MarkTree *b, int32_t start_line, int start_col, int old_ext
if (!pos_leq(old_extent, ipos)
|| (old_extent.row == ipos.row && old_extent.col == ipos.col
&& !mt_right(rawkey(itr)))) {
- marktree_itr_get_ext(b, old_extent, enditr, true, true, NULL);
+ marktree_itr_get_ext(b, old_extent, enditr, true, true, NULL, NULL);
assert(enditr->x);
// "assert" (itr <= enditr)
} else {
@@ -1692,7 +1994,7 @@ continue_same_node:
oldbase[itr->lvl + 1] = rawkey(itr).pos;
unrelative(oldbase[itr->lvl], &oldbase[itr->lvl + 1]);
rawkey(itr).pos = loc_start;
- marktree_itr_next_skip(b, itr, false, false, oldbase);
+ marktree_itr_next_skip(b, itr, false, false, oldbase, NULL);
} else {
rawkey(itr).pos = loc_start;
if (itr->i < itr->x->n - 1) {
@@ -1725,7 +2027,7 @@ past_continue_same_node:
oldbase[itr->lvl + 1] = oldpos;
unrelative(oldbase[itr->lvl], &oldbase[itr->lvl + 1]);
- marktree_itr_next_skip(b, itr, false, false, oldbase);
+ marktree_itr_next_skip(b, itr, false, false, oldbase, NULL);
} else {
if (itr->i < itr->x->n - 1) {
itr->i++;
@@ -1760,7 +2062,7 @@ past_continue_same_node:
if (done) {
break;
}
- marktree_itr_next_skip(b, itr, true, false, NULL);
+ marktree_itr_next_skip(b, itr, true, false, NULL, NULL);
}
if (kv_size(damage)) {
@@ -1825,11 +2127,12 @@ past_continue_same_node:
void marktree_move_region(MarkTree *b, int start_row, colnr_T start_col, int extent_row,
colnr_T extent_col, int new_row, colnr_T new_col)
{
- MTPos start = { start_row, start_col }, size = { extent_row, extent_col };
+ MTPos start = { start_row, start_col };
+ MTPos size = { extent_row, extent_col };
MTPos end = size;
unrelative(start, &end);
MarkTreeIter itr[1] = { 0 };
- marktree_itr_get_ext(b, start, itr, false, true, NULL);
+ marktree_itr_get_ext(b, start, itr, false, true, NULL, NULL);
kvec_t(MTKey) saved = KV_INITIAL_VALUE;
while (itr->x) {
MTKey k = marktree_itr_current(itr);
@@ -1957,13 +2260,10 @@ MTPos marktree_get_altpos(MarkTree *b, MTKey mark, MarkTreeIter *itr)
return marktree_get_alt(b, mark, itr).pos;
}
+/// @return alt mark for a paired mark or mark itself for unpaired mark
MTKey marktree_get_alt(MarkTree *b, MTKey mark, MarkTreeIter *itr)
{
- MTKey end = MT_INVALID_KEY;
- if (mt_paired(mark)) {
- end = marktree_lookup_ns(b, mark.ns, mark.id, !mt_end(mark), itr);
- }
- return end;
+ return mt_paired(mark) ? marktree_lookup_ns(b, mark.ns, mark.id, !mt_end(mark), itr) : mark;
}
static void marktree_itr_fix_pos(MarkTree *b, MarkTreeIter *itr)
@@ -1984,9 +2284,12 @@ static void marktree_itr_fix_pos(MarkTree *b, MarkTreeIter *itr)
// for unit test
void marktree_put_test(MarkTree *b, uint32_t ns, uint32_t id, int row, int col, bool right_gravity,
- int end_row, int end_col, bool end_right)
+ int end_row, int end_col, bool end_right, bool meta_inline)
{
- uint16_t flags = mt_flags(right_gravity, false, false, false);
+ uint16_t flags = mt_flags(right_gravity, false, false, false, false);
+ // The specific choice is irrelevant here, we pick one counted decor
+ // type to test the counting and filtering logic.
+ flags |= meta_inline ? MT_FLAG_DECOR_VIRT_TEXT_INLINE : 0;
MTKey key = { { row, col }, ns, id, flags, { .hl = DECOR_HIGHLIGHT_INLINE_INIT } };
marktree_put(b, key, end_row, end_col, end_right);
}
@@ -2021,7 +2324,8 @@ void marktree_check(MarkTree *b)
MTPos dummy;
bool last_right = false;
- size_t nkeys = marktree_check_node(b, b->root, &dummy, &last_right);
+
+ size_t nkeys = marktree_check_node(b, b->root, &dummy, &last_right, b->meta_root);
assert(b->n_keys == nkeys);
assert(b->n_keys == map_size(b->id2node));
#else
@@ -2031,7 +2335,8 @@ void marktree_check(MarkTree *b)
}
#ifndef NDEBUG
-size_t marktree_check_node(MarkTree *b, MTNode *x, MTPos *last, bool *last_right)
+size_t marktree_check_node(MarkTree *b, MTNode *x, MTPos *last, bool *last_right,
+ const uint32_t *meta_node_ref)
{
assert(x->n <= 2 * T - 1);
// TODO(bfredl): too strict if checking "in repair" post-delete tree.
@@ -2040,7 +2345,7 @@ size_t marktree_check_node(MarkTree *b, MTNode *x, MTPos *last, bool *last_right
for (int i = 0; i < x->n; i++) {
if (x->level) {
- n_keys += marktree_check_node(b, x->ptr[i], last, last_right);
+ n_keys += marktree_check_node(b, x->ptr[i], last, last_right, x->meta[i]);
} else {
*last = (MTPos) { 0, 0 };
}
@@ -2057,7 +2362,7 @@ size_t marktree_check_node(MarkTree *b, MTNode *x, MTPos *last, bool *last_right
}
if (x->level) {
- n_keys += marktree_check_node(b, x->ptr[x->n], last, last_right);
+ n_keys += marktree_check_node(b, x->ptr[x->n], last, last_right, x->meta[x->n]);
unrelative(x->key[x->n - 1].pos, last);
for (int i = 0; i < x->n + 1; i++) {
@@ -2072,6 +2377,13 @@ size_t marktree_check_node(MarkTree *b, MTNode *x, MTPos *last, bool *last_right
} else if (x->n > 0) {
*last = x->key[x->n - 1].pos;
}
+
+ uint32_t meta_node[4];
+ meta_describe_node(meta_node, x);
+ for (int m = 0; m < kMTMetaCount; m++) {
+ assert(meta_node_ref[m] == meta_node[m]);
+ }
+
return n_keys;
}
@@ -2201,7 +2513,12 @@ String mt_inspect(MarkTree *b, bool keys, bool dot)
return ga_take_string(ga);
}
-void mt_inspect_node(MarkTree *b, garray_T *ga, bool keys, MTNode *n, MTPos off)
+static inline uint64_t mt_dbg_id(uint64_t id)
+{
+ return (id >> 1) & 0xffffffff;
+}
+
+static void mt_inspect_node(MarkTree *b, garray_T *ga, bool keys, MTNode *n, MTPos off)
{
static char buf[1024];
GA_PUT("[");
@@ -2241,7 +2558,7 @@ void mt_inspect_node(MarkTree *b, garray_T *ga, bool keys, MTNode *n, MTPos off)
ga_concat(ga, "]");
}
-void mt_inspect_dotfile_node(MarkTree *b, garray_T *ga, MTNode *n, MTPos off, char *parent)
+static void mt_inspect_dotfile_node(MarkTree *b, garray_T *ga, MTNode *n, MTPos off, char *parent)
{
static char buf[1024];
char namebuf[64];
diff --git a/src/nvim/marktree.h b/src/nvim/marktree.h
index c76359d3f9..8e5cf30ff3 100644
--- a/src/nvim/marktree.h
+++ b/src/nvim/marktree.h
@@ -1,69 +1,16 @@
#pragma once
#include <stdbool.h>
-#include <stddef.h>
+#include <stddef.h> // IWYU pragma: keep
#include <stdint.h>
-#include "klib/kvec.h"
+#include "nvim/buffer_defs.h"
#include "nvim/decoration_defs.h"
-#include "nvim/garray_defs.h" // IWYU pragma: keep
-#include "nvim/map_defs.h"
+#include "nvim/marktree_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
// only for debug functions:
#include "nvim/api/private/defs.h" // IWYU pragma: keep
-#define MT_MAX_DEPTH 20
-#define MT_BRANCH_FACTOR 10
-// note max branch is actually 2*MT_BRANCH_FACTOR
-// and strictly this is ceil(log2(2*MT_BRANCH_FACTOR + 1))
-// as we need a pseudo-index for "right before this node"
-#define MT_LOG2_BRANCH 5
-
-typedef struct {
- int32_t row;
- int32_t col;
-} MTPos;
-#define MTPos(r, c) ((MTPos){ .row = (r), .col = (c) })
-
-typedef struct mtnode_s MTNode;
-
-typedef struct {
- MTPos pos;
- int lvl;
- MTNode *x;
- int i;
- struct {
- int oldcol;
- int i;
- } s[MT_MAX_DEPTH];
-
- size_t intersect_idx;
- MTPos intersect_pos;
- MTPos intersect_pos_x;
-} MarkTreeIter;
-
-#define marktree_itr_valid(itr) ((itr)->x != NULL)
-// access raw key: flags in MT_FLAG_EXTERNAL_MASK and decor_data are safe to modify.
-#define mt_itr_rawkey(itr) ((itr)->x->key[(itr)->i])
-
-// Internal storage
-//
-// NB: actual marks have flags > 0, so we can use (row,col,0) pseudo-key for
-// "space before (row,col)"
-typedef struct {
- MTPos pos;
- uint32_t ns;
- uint32_t id;
- uint16_t flags;
- DecorInlineData decor_data; // "ext" tag in flags
-} MTKey;
-
-typedef struct {
- MTKey start;
- MTPos end_pos;
- bool end_right_gravity;
-} MTPair;
-
#define MT_INVALID_KEY (MTKey) { { -1, -1 }, 0, 0, 0, { .hl = DECOR_HIGHLIGHT_INLINE_INIT } }
#define MT_FLAG_REAL (((uint16_t)1) << 0)
@@ -88,6 +35,8 @@ typedef struct {
#define MT_FLAG_DECOR_VIRT_LINES (((uint16_t)1) << 11)
#define MT_FLAG_DECOR_VIRT_TEXT_INLINE (((uint16_t)1) << 12)
+#define MT_FLAG_SCOPED (((uint16_t)1) << 13)
+
// These _must_ be last to preserve ordering of marks
#define MT_FLAG_RIGHT_GRAVITY (((uint16_t)1) << 14)
#define MT_FLAG_LAST (((uint16_t)1) << 15)
@@ -97,7 +46,7 @@ typedef struct {
| MT_FLAG_DECOR_VIRT_TEXT_INLINE)
#define MT_FLAG_EXTERNAL_MASK (MT_FLAG_DECOR_MASK | MT_FLAG_NO_UNDO \
- | MT_FLAG_INVALIDATE | MT_FLAG_INVALID)
+ | MT_FLAG_INVALIDATE | MT_FLAG_INVALID | MT_FLAG_SCOPED)
// this is defined so that start and end of the same range have adjacent ids
#define MARKTREE_END_FLAG ((uint64_t)1)
@@ -161,12 +110,24 @@ static inline bool mt_decor_sign(MTKey key)
return key.flags & (MT_FLAG_DECOR_SIGNTEXT | MT_FLAG_DECOR_SIGNHL);
}
-static inline uint16_t mt_flags(bool right_gravity, bool no_undo, bool invalidate, bool decor_ext)
+static inline bool mt_scoped(MTKey key)
+{
+ return key.flags & MT_FLAG_SCOPED;
+}
+
+static inline bool mt_scoped_in_win(MTKey key, win_T *wp)
+{
+ return !mt_scoped(key) || set_has(uint32_t, &wp->w_ns_set, key.ns);
+}
+
+static inline uint16_t mt_flags(bool right_gravity, bool no_undo, bool invalidate, bool decor_ext,
+ bool scoped)
{
return (uint16_t)((right_gravity ? MT_FLAG_RIGHT_GRAVITY : 0)
| (no_undo ? MT_FLAG_NO_UNDO : 0)
| (invalidate ? MT_FLAG_INVALIDATE : 0)
- | (decor_ext ? MT_FLAG_DECOR_EXT : 0));
+ | (decor_ext ? MT_FLAG_DECOR_EXT : 0)
+ | (scoped ? MT_FLAG_SCOPED : 0));
}
static inline MTPair mtpair_from(MTKey start, MTKey end)
@@ -179,31 +140,11 @@ static inline DecorInline mt_decor(MTKey key)
return (DecorInline){ .ext = key.flags & MT_FLAG_DECOR_EXT, .data = key.decor_data };
}
-typedef kvec_withinit_t(uint64_t, 4) Intersection;
-
-struct mtnode_s {
- int32_t n;
- int16_t level;
- int16_t p_idx; // index in parent
- Intersection intersect;
- // TODO(bfredl): we could consider having a only-sometimes-valid
- // index into parent for faster "cached" lookup.
- MTNode *parent;
- MTKey key[2 * MT_BRANCH_FACTOR - 1];
- MTNode *ptr[];
-};
-
-static inline uint64_t mt_dbg_id(uint64_t id)
+static inline DecorVirtText *mt_decor_virt(MTKey mark)
{
- return (id>>1)&0xffffffff;
+ return (mark.flags & MT_FLAG_DECOR_EXT) ? mark.decor_data.ext.vt : NULL;
}
-typedef struct {
- MTNode *root;
- size_t n_keys, n_nodes;
- PMap(uint64_t) id2node[1];
-} MarkTree;
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "marktree.h.generated.h"
#endif
diff --git a/src/nvim/marktree_defs.h b/src/nvim/marktree_defs.h
new file mode 100644
index 0000000000..d43130db6f
--- /dev/null
+++ b/src/nvim/marktree_defs.h
@@ -0,0 +1,103 @@
+#pragma once
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "nvim/decoration_defs.h"
+#include "nvim/map_defs.h"
+
+enum {
+ MT_MAX_DEPTH = 20,
+ MT_BRANCH_FACTOR = 10,
+ // note max branch is actually 2*MT_BRANCH_FACTOR
+ // and strictly this is ceil(log2(2*MT_BRANCH_FACTOR + 1))
+ // as we need a pseudo-index for "right before this node"
+ MT_LOG2_BRANCH = 5,
+};
+
+typedef struct {
+ int32_t row;
+ int32_t col;
+} MTPos;
+#define MTPos(r, c) ((MTPos){ .row = (r), .col = (c) })
+
+// Currently there are four counts, which makes for a uint32_t[4] per node
+// which makes for nice autovectorization into a single XMM or NEON register
+typedef enum {
+ kMTMetaInline,
+ kMTMetaLines,
+ kMTMetaSignHL,
+ kMTMetaSignText,
+ kMTMetaCount, // sentinel, must be last
+} MetaIndex;
+
+#define kMTFilterSelect ((uint32_t)-1)
+
+// a filter should be set to kMTFilterSelect for the selected kinds, zero otherwise
+typedef const uint32_t *MetaFilter;
+
+typedef struct mtnode_s MTNode;
+
+typedef struct {
+ MTPos pos;
+ int lvl;
+ MTNode *x;
+ int i;
+ struct {
+ int oldcol;
+ int i;
+ } s[MT_MAX_DEPTH];
+
+ size_t intersect_idx;
+ MTPos intersect_pos;
+ MTPos intersect_pos_x;
+} MarkTreeIter;
+
+#define marktree_itr_valid(itr) ((itr)->x != NULL)
+// access raw key: flags in MT_FLAG_EXTERNAL_MASK and decor_data are safe to modify.
+#define mt_itr_rawkey(itr) ((itr)->x->key[(itr)->i])
+
+// Internal storage
+//
+// NB: actual marks have flags > 0, so we can use (row,col,0) pseudo-key for
+// "space before (row,col)"
+typedef struct {
+ MTPos pos;
+ uint32_t ns;
+ uint32_t id;
+ uint16_t flags;
+ DecorInlineData decor_data; // "ext" tag in flags
+} MTKey;
+
+typedef struct {
+ MTKey start;
+ MTPos end_pos;
+ bool end_right_gravity;
+} MTPair;
+
+typedef kvec_withinit_t(uint64_t, 4) Intersection;
+
+// part of mtnode_s which is only allocated for inner nodes:
+// pointer to children as well as their meta counts
+struct mtnode_inner_s {
+ MTNode *i_ptr[2 * MT_BRANCH_FACTOR];
+ uint32_t i_meta[2 * MT_BRANCH_FACTOR][kMTMetaCount];
+};
+
+struct mtnode_s {
+ int32_t n;
+ int16_t level;
+ int16_t p_idx; // index in parent
+ Intersection intersect;
+ MTNode *parent;
+ MTKey key[2 * MT_BRANCH_FACTOR - 1];
+ struct mtnode_inner_s s[];
+};
+
+typedef struct {
+ MTNode *root;
+ uint32_t meta_root[kMTMetaCount];
+ size_t n_keys, n_nodes;
+ PMap(uint64_t) id2node[1];
+} MarkTree;
diff --git a/src/nvim/match.c b/src/nvim/match.c
index 0a7c264d4f..c8837969b6 100644
--- a/src/nvim/match.c
+++ b/src/nvim/match.c
@@ -16,14 +16,15 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/macros_defs.h"
#include "nvim/match.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -451,10 +452,8 @@ static void next_search_hl(win_T *win, match_T *search_hl, match_T *shl, linenr_
} else if (vim_strchr(p_cpo, CPO_SEARCH) == NULL
|| (shl->rm.endpos[0].lnum == 0
&& shl->rm.endpos[0].col <= shl->rm.startpos[0].col)) {
- char *ml;
-
matchcol = shl->rm.startpos[0].col;
- ml = ml_get_buf(shl->buf, lnum) + matchcol;
+ char *ml = ml_get_buf(shl->buf, lnum) + matchcol;
if (*ml == NUL) {
matchcol++;
shl->lnum = 0;
@@ -669,7 +668,7 @@ bool prepare_search_hl_line(win_T *wp, linenr_T lnum, colnr_T mincol, char **lin
/// is endcol.
/// Return the updated search_attr.
int update_search_hl(win_T *wp, linenr_T lnum, colnr_T col, char **line, match_T *search_hl,
- int *has_match_conc, int *match_conc, int lcs_eol_one, bool *on_last_col,
+ int *has_match_conc, int *match_conc, bool lcs_eol_todo, bool *on_last_col,
bool *search_attr_from_match)
{
matchitem_T *cur = wp->w_match_head; // points to the match list
@@ -790,7 +789,7 @@ int update_search_hl(win_T *wp, linenr_T lnum, colnr_T col, char **line, match_T
}
}
// Only highlight one character after the last column.
- if (*(*line + col) == NUL && (wp->w_p_list && lcs_eol_one == -1)) {
+ if (*(*line + col) == NUL && (wp->w_p_list && !lcs_eol_todo)) {
search_attr = 0;
}
return search_attr;
diff --git a/src/nvim/math.c b/src/nvim/math.c
index 96ff1bef10..9a0825823c 100644
--- a/src/nvim/math.c
+++ b/src/nvim/math.c
@@ -7,10 +7,11 @@
#include "nvim/math.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "math.c.generated.h" // IWYU pragma: export
+# include "math.c.generated.h"
#endif
int xfpclassify(double d)
+ FUNC_ATTR_CONST
{
uint64_t m;
@@ -29,11 +30,39 @@ int xfpclassify(double d)
}
int xisinf(double d)
+ FUNC_ATTR_CONST
{
return FP_INFINITE == xfpclassify(d);
}
int xisnan(double d)
+ FUNC_ATTR_CONST
{
return FP_NAN == xfpclassify(d);
}
+
+/// Count trailing zeroes at the end of bit field.
+int xctz(uint64_t x)
+{
+ // If x == 0, that means all bits are zeroes.
+ if (x == 0) {
+ return 8 * sizeof(x);
+ }
+
+ // Use compiler builtin if possible.
+#if defined(__clang__) || (defined(__GNUC__) && (__GNUC__ >= 4))
+ return __builtin_ctzll(x);
+#else
+ int count = 0;
+ // Set x's trailing zeroes to ones and zero the rest.
+ x = (x ^ (x - 1)) >> 1;
+
+ // Increment count until there are just zero bits remaining.
+ while (x) {
+ count++;
+ x >>= 1;
+ }
+
+ return count;
+#endif
+}
diff --git a/src/nvim/math.h b/src/nvim/math.h
index c88ce1e03d..0321d0c9c6 100644
--- a/src/nvim/math.h
+++ b/src/nvim/math.h
@@ -1,5 +1,14 @@
#pragma once
+#include <stdbool.h>
+#include <stdint.h>
+
+/// Check if number is a power of two
+static inline bool is_power_of_two(uint64_t x)
+{
+ return x != 0 && ((x & (x - 1)) == 0);
+}
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "math.h.generated.h"
#endif
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c
index f2883cc5c7..c7a56209e4 100644
--- a/src/nvim/mbyte.c
+++ b/src/nvim/mbyte.c
@@ -32,7 +32,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include <wctype.h>
#include "auto/config.h"
@@ -46,9 +46,10 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/iconv_defs.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
@@ -444,24 +445,26 @@ int mb_get_class_tab(const char *p, const uint64_t *const chartab)
static bool intable(const struct interval *table, size_t n_items, int c)
FUNC_ATTR_PURE
{
+ assert(n_items > 0);
// first quick check for Latin1 etc. characters
if (c < table[0].first) {
return false;
}
+ assert(n_items <= SIZE_MAX / 2);
// binary search in table
- int bot = 0;
- int top = (int)(n_items - 1);
- while (top >= bot) {
- int mid = (bot + top) / 2;
+ size_t bot = 0;
+ size_t top = n_items;
+ do {
+ size_t mid = (bot + top) >> 1;
if (table[mid].last < c) {
bot = mid + 1;
} else if (table[mid].first > c) {
- top = mid - 1;
+ top = mid;
} else {
return true;
}
- }
+ } while (top > bot);
return false;
}
@@ -475,32 +478,28 @@ static bool intable(const struct interval *table, size_t n_items, int c)
/// gen_unicode_tables.lua, which must be manually invoked as needed.
int utf_char2cells(int c)
{
- // Use the value from setcellwidths() at 0x80 and higher, unless the
- // character is not printable.
- if (c >= 0x80 && vim_isprintc(c)) {
- int n = cw_value(c);
- if (n != 0) {
- return n;
- }
+ if (c < 0x80) {
+ return 1;
}
- if (c >= 0x100) {
- if (!utf_printable(c)) {
- return 6; // unprintable, displays <xxxx>
- }
- if (intable(doublewidth, ARRAY_SIZE(doublewidth), c)) {
- return 2;
- }
- if (p_emoji && intable(emoji_wide, ARRAY_SIZE(emoji_wide), c)) {
- return 2;
- }
- } else if (c >= 0x80 && !vim_isprintc(c)) {
- // Characters below 0x100 are influenced by 'isprint' option.
- return 4; // unprintable, displays <xx>
+ if (!vim_isprintc(c)) {
+ assert(c <= 0xFFFF);
+ // unprintable is displayed either as <xx> or <xxxx>
+ return c > 0xFF ? 6 : 4;
+ }
+
+ int n = cw_value(c);
+ if (n != 0) {
+ return n;
}
- if (c >= 0x80 && *p_ambw == 'd'
- && intable(ambiguous, ARRAY_SIZE(ambiguous), c)) {
+ if (intable(doublewidth, ARRAY_SIZE(doublewidth), c)) {
+ return 2;
+ }
+ if (p_emoji && intable(emoji_wide, ARRAY_SIZE(emoji_wide), c)) {
+ return 2;
+ }
+ if (*p_ambw == 'd' && intable(ambiguous, ARRAY_SIZE(ambiguous), c)) {
return 2;
}
@@ -527,6 +526,74 @@ int utf_ptr2cells(const char *p)
return 1;
}
+/// Convert a UTF-8 byte sequence to a character number.
+/// Doesn't handle ascii! only multibyte and illegal sequences.
+///
+/// @param[in] p String to convert.
+/// @param[in] len Length of the character in bytes, 0 or 1 if illegal.
+///
+/// @return Unicode codepoint. A negative value when the sequence is illegal.
+int32_t utf_ptr2CharInfo_impl(uint8_t const *p, uintptr_t const len)
+ FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+{
+// uint8_t is a reminder for clang to use smaller cmp
+#define CHECK \
+ do { \
+ if (EXPECT((uint8_t)(cur & 0xC0U) != 0x80U, false)) { \
+ return -1; \
+ } \
+ } while (0)
+
+ static uint32_t const corrections[] = {
+ (1U << 31), // invalid - set invalid bits (safe to add as first 2 bytes
+ (1U << 31), // won't affect highest bit in normal ret)
+ -(0x80U + (0xC0U << 6)), // multibyte - subtract added UTF8 bits (1..10xxx and 10xxx)
+ -(0x80U + (0x80U << 6) + (0xE0U << 12)),
+ -(0x80U + (0x80U << 6) + (0x80U << 12) + (0xF0U << 18)),
+ -(0x80U + (0x80U << 6) + (0x80U << 12) + (0x80U << 18) + (0xF8U << 24)),
+ -(0x80U + (0x80U << 6) + (0x80U << 12) + (0x80U << 18) + (0x80U << 24)), // + (0xFCU << 30)
+ };
+
+ // len is 0-6, but declared uintptr_t to avoid zeroing out upper bits
+ uint32_t const corr = corrections[len];
+ uint8_t cur;
+
+ // reading second byte unconditionally, safe for invalid
+ // as it cannot be the last byte, not safe for ascii
+ uint32_t code_point = ((uint32_t)p[0] << 6) + (cur = p[1]);
+ CHECK;
+ if ((uint32_t)len < 3) {
+ goto ret; // len == 0, 1, 2
+ }
+
+ code_point = (code_point << 6) + (cur = p[2]);
+ CHECK;
+ if ((uint32_t)len == 3) {
+ goto ret;
+ }
+
+ code_point = (code_point << 6) + (cur = p[3]);
+ CHECK;
+ if ((uint32_t)len == 4) {
+ goto ret;
+ }
+
+ code_point = (code_point << 6) + (cur = p[4]);
+ CHECK;
+ if ((uint32_t)len == 5) {
+ goto ret;
+ }
+
+ code_point = (code_point << 6) + (cur = p[5]);
+ CHECK;
+ // len == 6
+
+ret:
+ return (int32_t)(code_point + corr);
+
+#undef CHECK
+}
+
/// Like utf_ptr2cells(), but limit string length to "size".
/// For an empty string or truncated character returns 1.
int utf_ptr2cells_len(const char *p, int size)
@@ -596,45 +663,62 @@ size_t mb_string2cells_len(const char *str, size_t size)
///
/// @return Unicode codepoint or byte value.
int utf_ptr2char(const char *const p_in)
- FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
uint8_t *p = (uint8_t *)p_in;
- if (p[0] < 0x80) { // Be quick for ASCII.
- return p[0];
+
+ uint32_t const v0 = p[0];
+ if (EXPECT(v0 < 0x80U, true)) { // Be quick for ASCII.
+ return (int)v0;
}
- const uint8_t len = utf8len_tab_zero[p[0]];
- if (len > 1 && (p[1] & 0xc0) == 0x80) {
- if (len == 2) {
- return ((p[0] & 0x1f) << 6) + (p[1] & 0x3f);
- }
- if ((p[2] & 0xc0) == 0x80) {
- if (len == 3) {
- return (((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6)
- + (p[2] & 0x3f));
- }
- if ((p[3] & 0xc0) == 0x80) {
- if (len == 4) {
- return (((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12)
- + ((p[2] & 0x3f) << 6) + (p[3] & 0x3f));
- }
- if ((p[4] & 0xc0) == 0x80) {
- if (len == 5) {
- return (((p[0] & 0x03) << 24) + ((p[1] & 0x3f) << 18)
- + ((p[2] & 0x3f) << 12) + ((p[3] & 0x3f) << 6)
- + (p[4] & 0x3f));
- }
- if ((p[5] & 0xc0) == 0x80 && len == 6) {
- return (((p[0] & 0x01) << 30) + ((p[1] & 0x3f) << 24)
- + ((p[2] & 0x3f) << 18) + ((p[3] & 0x3f) << 12)
- + ((p[4] & 0x3f) << 6) + (p[5] & 0x3f));
- }
- }
- }
- }
+ const uint8_t len = utf8len_tab[v0];
+ if (EXPECT(len < 2, false)) {
+ return (int)v0;
}
- // Illegal value: just return the first byte.
- return p[0];
+
+#define CHECK(v) \
+ do { \
+ if (EXPECT((uint8_t)((v) & 0xC0U) != 0x80U, false)) { \
+ return (int)v0; \
+ } \
+ } while (0)
+#define LEN_RETURN(len_v, result) \
+ do { \
+ if (len == (len_v)) { \
+ return (int)(result); \
+ } \
+ } while (0)
+#define S(s) ((uint32_t)0x80U << (s))
+
+ uint32_t const v1 = p[1];
+ CHECK(v1);
+ LEN_RETURN(2, (v0 << 6) + v1 - ((0xC0U << 6) + S(0)));
+
+ uint32_t const v2 = p[2];
+ CHECK(v2);
+ LEN_RETURN(3, (v0 << 12) + (v1 << 6) + v2 - ((0xE0U << 12) + S(6) + S(0)));
+
+ uint32_t const v3 = p[3];
+ CHECK(v3);
+ LEN_RETURN(4, (v0 << 18) + (v1 << 12) + (v2 << 6) + v3
+ - ((0xF0U << 18) + S(12) + S(6) + S(0)));
+
+ uint32_t const v4 = p[4];
+ CHECK(v4);
+ LEN_RETURN(5, (v0 << 24) + (v1 << 18) + (v2 << 12) + (v3 << 6) + v4
+ - ((0xF8U << 24) + S(18) + S(12) + S(6) + S(0)));
+
+ uint32_t const v5 = p[5];
+ CHECK(v5);
+ // len == 6
+ return (int)((v0 << 30) + (v1 << 24) + (v2 << 18) + (v3 << 12) + (v4 << 6) + v5
+ // - (0xFCU << 30)
+ - (S(24) + S(18) + S(12) + S(6) + S(0)));
+
+#undef S
+#undef CHECK
+#undef LEN_RETURN
}
// Convert a UTF-8 byte sequence to a wide character.
@@ -721,6 +805,16 @@ bool utf_composinglike(const char *p1, const char *p2)
return arabic_combine(utf_ptr2char(p1), c2);
}
+/// Check if the next character is a composing character when it
+/// comes after the first. For Arabic sometimes "ab" is replaced with "c", which
+/// behaves like a composing character.
+/// returns false for negative values
+bool utf_char_composinglike(int32_t const first, int32_t const next)
+ FUNC_ATTR_PURE
+{
+ return utf_iscomposing(next) || arabic_combine(first, next);
+}
+
/// Get the screen char at the beginning of a string
///
/// Caller is expected to check for things like unprintable chars etc
@@ -987,17 +1081,61 @@ int utf_char2bytes(const int c, char *const buf)
}
}
-// Return true if "c" is a composing UTF-8 character. This means it will be
-// drawn on top of the preceding character.
-// Based on code from Markus Kuhn.
+/// Return true if "c" is a composing UTF-8 character.
+/// This means it will be drawn on top of the preceding character.
+/// Based on code from Markus Kuhn.
+/// Returns false for negative values.
bool utf_iscomposing(int c)
{
return intable(combining, ARRAY_SIZE(combining), c);
}
+#ifdef __SSE2__
+
+# include <emmintrin.h>
+
+// Return true for characters that can be displayed in a normal way.
+// Only for characters of 0x100 and above!
+bool utf_printable(int c)
+ FUNC_ATTR_CONST
+{
+ if (c < 0x180B || c > 0xFFFF) {
+ return c != 0x70F;
+ }
+
+# define L(v) ((int16_t)((v) - 1)) // lower bound (exclusive)
+# define H(v) ((int16_t)(v)) // upper bound (inclusive)
+
+ // Boundaries of unprintable characters.
+ // Some values are negative when converted to int16_t.
+ // Ranges must not wrap around when converted to int16_t.
+ __m128i const lo = _mm_setr_epi16(L(0x180b), L(0x200b), L(0x202a), L(0x2060),
+ L(0xd800), L(0xfeff), L(0xfff9), L(0xfffe));
+
+ __m128i const hi = _mm_setr_epi16(H(0x180e), H(0x200f), H(0x202e), H(0x206f),
+ H(0xdfff), H(0xfeff), H(0xfffb), H(0xffff));
+
+# undef L
+# undef H
+
+ __m128i value = _mm_set1_epi16((int16_t)c);
+
+ // Using _mm_cmplt_epi16() is less optimal, since it would require
+ // swapping operands (sse2 only has cmpgt instruction),
+ // and only the second operand can be a memory location.
+
+ // Character is printable when it is above/below both bounds of each range
+ // (corresponding bits in both masks are equal).
+ return _mm_movemask_epi8(_mm_cmpgt_epi16(value, lo))
+ == _mm_movemask_epi8(_mm_cmpgt_epi16(value, hi));
+}
+
+#else
+
// Return true for characters that can be displayed in a normal way.
// Only for characters of 0x100 and above!
bool utf_printable(int c)
+ FUNC_ATTR_PURE
{
// Sorted list of non-overlapping intervals.
// 0xd800-0xdfff is reserved for UTF-16, actually illegal.
@@ -1010,6 +1148,8 @@ bool utf_printable(int c)
return !intable(nonprint, ARRAY_SIZE(nonprint), c);
}
+#endif
+
// Get class of a Unicode character.
// 0: white space
// 1: punctuation
@@ -1183,6 +1323,9 @@ int utf_fold(int a)
// invalid values or can't handle latin1 when the locale is C.
// Speed is most important here.
+// Note: UnicodeData.txt does not define U+1E9E as being the corresponding upper
+// case letter for U+00DF (ß), however it is part of the toLower table
+
/// Return the upper-case equivalent of "a", which is a UCS-4 character. Use
/// simple case folding.
int mb_toupper(int a)
@@ -1422,7 +1565,8 @@ int utf16_to_utf8(const wchar_t *utf16, int utf16len, char **utf8)
void mb_utflen(const char *s, size_t len, size_t *codepoints, size_t *codeunits)
FUNC_ATTR_NONNULL_ALL
{
- size_t count = 0, extra = 0;
+ size_t count = 0;
+ size_t extra = 0;
size_t clen;
for (size_t i = 0; i < len; i += clen) {
clen = (size_t)utf_ptr2len_len(s + i, (int)(len - i));
@@ -1740,99 +1884,66 @@ void mb_copy_char(const char **const fp, char **const tp)
*fp += l;
}
-/// Return the offset from "p_in" to the first byte of a character. When "p_in" is
+/// Return the offset from "p" to the first byte of a character. When "p" is
/// at the start of a character 0 is returned, otherwise the offset to the next
/// character. Can start anywhere in a stream of bytes.
-int mb_off_next(const char *base, const char *p_in)
+int mb_off_next(const char *base, const char *p)
{
- const uint8_t *p = (uint8_t *)p_in;
- int i;
+ int head_off = utf_head_off(base, p);
- if (*p < 0x80) { // be quick for ASCII
+ if (head_off == 0) {
return 0;
}
- // Find the next character that isn't 10xx.xxxx
- for (i = 0; (p[i] & 0xc0) == 0x80; i++) {}
- if (i > 0) {
- int j;
- // Check for illegal sequence.
- for (j = 0; p - j > (uint8_t *)base; j++) {
- if ((p[-j] & 0xc0) != 0x80) {
- break;
- }
- }
- if (utf8len_tab[p[-j]] != i + j) {
- return 0;
- }
- }
- return i;
+ return utfc_ptr2len(p - head_off) - head_off;
}
-/// Return the offset from `p_in` to the last byte of the codepoint it points
-/// to. Can start anywhere in a stream of bytes.
+/// Returns the offset in bytes from "p_in" to the first and one-past-end bytes
+/// of the codepoint it points to.
+/// "p_in" can point anywhere in a stream of bytes.
+/// "p_len" limits number of bytes after "p_in".
/// Note: Counts individual codepoints of composed characters separately.
-int utf_cp_tail_off(const char *base, const char *p_in)
+CharBoundsOff utf_cp_bounds_len(char const *base, char const *p_in, int p_len)
+ FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
{
- const uint8_t *p = (uint8_t *)p_in;
- int i;
- int j;
-
- if (*p == NUL) {
- return 0;
+ assert(base <= p_in && p_len > 0);
+ uint8_t const *const b = (uint8_t *)base;
+ uint8_t const *const p = (uint8_t *)p_in;
+ if (*p < 0x80U) { // be quick for ASCII
+ return (CharBoundsOff){ 0, 1 };
}
- // Find the last character that is 10xx.xxxx
- for (i = 0; (p[i + 1] & 0xc0) == 0x80; i++) {}
-
- // Check for illegal sequence.
- for (j = 0; p_in - j > base; j++) {
- if ((p[-j] & 0xc0) != 0x80) {
- break;
+ int const max_first_off = -MIN((int)(p - b), MB_MAXCHAR - 1);
+ int first_off = 0;
+ for (; utf_is_trail_byte(p[first_off]); first_off--) {
+ if (first_off == max_first_off) { // failed to find first byte
+ return (CharBoundsOff){ 0, 1 };
}
}
- if (utf8len_tab[p[-j]] != i + j + 1) {
- return 0;
+ int const max_end_off = utf8len_tab[p[first_off]] + first_off;
+ if (max_end_off <= 0 || max_end_off > p_len) { // illegal or incomplete sequence
+ return (CharBoundsOff){ 0, 1 };
}
- return i;
-}
-/// Return the offset from "p" to the first byte of the codepoint it points
-/// to. Can start anywhere in a stream of bytes.
-/// Note: Unlike `utf_head_off`, this counts individual codepoints of composed characters
-/// separately.
-///
-/// @param[in] base Pointer to start of string
-/// @param[in] p Pointer to byte for which to return the offset to the previous codepoint
-//
-/// @return 0 if invalid sequence, else number of bytes to previous codepoint
-int utf_cp_head_off(const char *base, const char *p)
-{
- int i;
-
- if (*p == NUL) {
- return 0;
- }
-
- // Find the first character that is not 10xx.xxxx
- for (i = 0; p - i >= base; i++) {
- if (((uint8_t)p[-i] & 0xc0) != 0x80) {
- break;
+ for (int end_off = 1; end_off < max_end_off; end_off++) {
+ if (!utf_is_trail_byte(p[end_off])) { // not enough trail bytes
+ return (CharBoundsOff){ 0, 1 };
}
}
- // Find the last character that is 10xx.xxxx (condition terminates on NUL)
- int j = 1;
- while (((uint8_t)p[j] & 0xc0) == 0x80) {
- j++;
- }
+ return (CharBoundsOff){ .begin_off = (int8_t)-first_off, .end_off = (int8_t)max_end_off };
+}
- // Check for illegal sequence.
- if (utf8len_tab[(uint8_t)p[-i]] != j + i) {
- return 0;
- }
- return i;
+/// Returns the offset in bytes from "p_in" to the first and one-past-end bytes
+/// of the codepoint it points to.
+/// "p_in" can point anywhere in a stream of bytes.
+/// Stream must be NUL-terminated.
+/// Note: Counts individual codepoints of composed characters separately.
+CharBoundsOff utf_cp_bounds(char const *base, char const *p_in)
+ FUNC_ATTR_PURE FUNC_ATTR_NONNULL_ALL
+{
+ return utf_cp_bounds_len(base, p_in, INT_MAX);
}
// Find the next illegal byte sequence.
@@ -2250,7 +2361,7 @@ void *my_iconv_open(char *to, char *from)
// stops for no apparent reason after about 8160 characters.
char *p = tobuf;
size_t tolen = ICONV_TESTLEN;
- (void)iconv(fd, NULL, NULL, &p, &tolen);
+ iconv(fd, NULL, NULL, &p, &tolen);
if (p == NULL) {
iconv_working = kBroken;
iconv_close(fd);
@@ -2651,8 +2762,10 @@ static int tv_nr_compare(const void *a1, const void *a2)
{
const listitem_T *const li1 = tv_list_first(*(const list_T **)a1);
const listitem_T *const li2 = tv_list_first(*(const list_T **)a2);
+ const varnumber_T n1 = TV_LIST_ITEM_TV(li1)->vval.v_number;
+ const varnumber_T n2 = TV_LIST_ITEM_TV(li2)->vval.v_number;
- return (int)(TV_LIST_ITEM_TV(li1)->vval.v_number - TV_LIST_ITEM_TV(li2)->vval.v_number);
+ return n1 == n2 ? 0 : n1 > n2 ? 1 : -1;
}
/// "setcellwidths()" function
@@ -2802,3 +2915,14 @@ char *get_encoding_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
return (char *)enc_canon_table[idx].name;
}
+
+/// Compare strings
+///
+/// @param[in] ic True if case is to be ignored.
+///
+/// @return 0 if s1 == s2, <0 if s1 < s2, >0 if s1 > s2.
+int mb_strcmp_ic(bool ic, const char *s1, const char *s2)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return (ic ? mb_stricmp(s1, s2) : strcmp(s1, s2));
+}
diff --git a/src/nvim/mbyte.h b/src/nvim/mbyte.h
index 49c323282d..ddac040aae 100644
--- a/src/nvim/mbyte.h
+++ b/src/nvim/mbyte.h
@@ -2,15 +2,24 @@
#include <stdbool.h>
#include <stdint.h>
-#include <string.h>
+#include <sys/types.h> // IWYU pragma: keep
+#include <uv.h> // IWYU pragma: keep
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/func_attr.h"
-#include "nvim/mbyte_defs.h" // IWYU pragma: export
-#include "nvim/os/os_defs.h" // IWYU pragma: export
+#include "nvim/macros_defs.h"
+#include "nvim/mbyte_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "mbyte.h.generated.h"
+#endif
+
+enum {
+ kInvalidByteCells = 4,
+};
+
// Return byte length of character that starts with byte "b".
// Returns 1 for a single-byte character.
// MB_BYTE2LEN_CHECK() can be used to count a special key as one byte.
@@ -22,19 +31,100 @@ extern const uint8_t utf8len_tab_zero[256];
extern const uint8_t utf8len_tab[256];
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "mbyte.h.generated.h"
-#endif
+// Use our own character-case definitions, because the current locale may
+// differ from what the .spl file uses.
+// These must not be called with negative number!
+// Multi-byte implementation. For Unicode we can call utf_*(), but don't do
+// that for ASCII, because we don't want to use 'casemap' here. Otherwise use
+// the "w" library function for characters above 255.
+#define SPELL_TOFOLD(c) ((c) >= 128 ? utf_fold(c) : (int)spelltab.st_fold[c])
+
+#define SPELL_TOUPPER(c) ((c) >= 128 ? mb_toupper(c) : (int)spelltab.st_upper[c])
+
+#define SPELL_ISUPPER(c) ((c) >= 128 ? mb_isupper(c) : spelltab.st_isu[c])
+
+// MB_PTR_ADV(): advance a pointer to the next character, taking care of
+// multi-byte characters if needed. Skip over composing chars.
+#define MB_PTR_ADV(p) (p += utfc_ptr2len((char *)p))
-static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2)
- REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT;
+// MB_PTR_BACK(): backup a pointer to the previous character, taking care of
+// multi-byte characters if needed. Only use with "p" > "s" !
+#define MB_PTR_BACK(s, p) \
+ (p -= utf_head_off((char *)(s), (char *)(p) - 1) + 1)
-/// Compare strings
+/// Check whether a given UTF-8 byte is a trailing byte (10xx.xxxx).
+static inline bool utf_is_trail_byte(uint8_t byte)
+ REAL_FATTR_CONST REAL_FATTR_ALWAYS_INLINE;
+
+static inline bool utf_is_trail_byte(uint8_t const byte)
+{
+ // uint8_t is for clang to use smaller cmp
+ return (uint8_t)(byte & 0xC0U) == 0x80U;
+}
+
+static inline CharInfo utf_ptr2CharInfo(char const *p_in)
+ REAL_FATTR_NONNULL_ALL REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE;
+
+/// Convert a UTF-8 byte sequence to a Unicode code point.
+/// Handles ascii, multibyte sequiences and illegal sequences.
///
-/// @param[in] ic True if case is to be ignored.
+/// @param[in] p_in String to convert.
+///
+/// @return information abouth the character. When the sequence is illegal,
+/// "value" is negative, "len" is 1.
+static inline CharInfo utf_ptr2CharInfo(char const *const p_in)
+{
+ uint8_t const *const p = (uint8_t const *)p_in;
+ uint8_t const first = *p;
+ if (first < 0x80) {
+ return (CharInfo){ .value = first, .len = 1 };
+ } else {
+ int len = utf8len_tab[first];
+ int32_t const code_point = utf_ptr2CharInfo_impl(p, (uintptr_t)len);
+ if (code_point < 0) {
+ len = 1;
+ }
+ return (CharInfo){ .value = code_point, .len = len };
+ }
+}
+
+static inline StrCharInfo utfc_next(StrCharInfo cur)
+ REAL_FATTR_NONNULL_ALL REAL_FATTR_ALWAYS_INLINE REAL_FATTR_PURE;
+
+/// Return information about the next character.
+/// Composing and combining characters are considered a part of the current character.
///
-/// @return 0 if s1 == s2, <0 if s1 < s2, >0 if s1 > s2.
-static inline int mb_strcmp_ic(bool ic, const char *s1, const char *s2)
+/// @param[in] cur Information about the current character in the string.
+static inline StrCharInfo utfc_next(StrCharInfo cur)
+{
+ int32_t prev_code = cur.chr.value;
+ uint8_t *next = (uint8_t *)(cur.ptr + cur.chr.len);
+
+ while (true) {
+ if (EXPECT(*next < 0x80U, true)) {
+ return (StrCharInfo){
+ .ptr = (char *)next,
+ .chr = (CharInfo){ .value = *next, .len = 1 },
+ };
+ }
+ uint8_t const next_len = utf8len_tab[*next];
+ int32_t const next_code = utf_ptr2CharInfo_impl(next, (uintptr_t)next_len);
+ if (!utf_char_composinglike(prev_code, next_code)) {
+ return (StrCharInfo){
+ .ptr = (char *)next,
+ .chr = (CharInfo){ .value = next_code, .len = (next_code < 0 ? 1 : next_len) },
+ };
+ }
+
+ prev_code = next_code;
+ next += next_len;
+ }
+}
+
+static inline StrCharInfo utf_ptr2StrCharInfo(char *ptr)
+ REAL_FATTR_NONNULL_ALL REAL_FATTR_ALWAYS_INLINE REAL_FATTR_PURE;
+
+static inline StrCharInfo utf_ptr2StrCharInfo(char *ptr)
{
- return (ic ? mb_stricmp(s1, s2) : strcmp(s1, s2));
+ return (StrCharInfo){ .ptr = ptr, .chr = utf_ptr2CharInfo(ptr) };
}
diff --git a/src/nvim/mbyte_defs.h b/src/nvim/mbyte_defs.h
index 2904047223..8670a0595d 100644
--- a/src/nvim/mbyte_defs.h
+++ b/src/nvim/mbyte_defs.h
@@ -1,16 +1,18 @@
#pragma once
#include <stdbool.h>
+#include <stdint.h>
#include "nvim/iconv_defs.h"
-/// Maximum number of bytes in a multi-byte character. It can be one 32-bit
-/// character of up to 6 bytes, or one 16-bit character of up to three bytes
-/// plus six following composing characters of three bytes each.
-enum { MB_MAXBYTES = 21, };
-
-/// max length of an unicode char
-enum { MB_MAXCHAR = 6, };
+enum {
+ /// Maximum number of bytes in a multi-byte character. It can be one 32-bit
+ /// character of up to 6 bytes, or one 16-bit character of up to three bytes
+ /// plus six following composing characters of three bytes each.
+ MB_MAXBYTES = 21,
+ /// max length of an unicode char
+ MB_MAXCHAR = 6,
+};
/// properties used in enc_canon_table[] (first three mutually exclusive)
enum {
@@ -54,3 +56,18 @@ typedef struct {
bool vc_fail; ///< What to do with invalid characters: if true, fail,
///< otherwise use '?'.
} vimconv_T;
+
+typedef struct {
+ int32_t value; ///< Code point.
+ int len; ///< Length in bytes.
+} CharInfo;
+
+typedef struct {
+ char *ptr; ///< Pointer to the first byte of the character.
+ CharInfo chr; ///< Information about the character.
+} StrCharInfo;
+
+typedef struct {
+ int8_t begin_off; ///< Offset to the first byte of the codepoint.
+ int8_t end_off; ///< Offset to one past the end byte of the codepoint.
+} CharBoundsOff;
diff --git a/src/nvim/memfile.c b/src/nvim/memfile.c
index d989600d45..fb9f2eb8df 100644
--- a/src/nvim/memfile.c
+++ b/src/nvim/memfile.c
@@ -47,7 +47,7 @@
#include "nvim/assert_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/fileio.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/map_defs.h"
#include "nvim/memfile.h"
@@ -56,10 +56,12 @@
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
-#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
+#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
#define MEMFILE_PAGE_SIZE 4096 /// default page size
@@ -204,7 +206,7 @@ void mf_close_file(buf_T *buf, bool getlines)
if (getlines) {
// get all blocks in memory by accessing all lines (clumsy!)
for (linenr_T lnum = 1; lnum <= buf->b_ml.ml_line_count; lnum++) {
- (void)ml_get_buf(buf, lnum);
+ ml_get_buf(buf, lnum);
}
}
@@ -271,7 +273,7 @@ bhdr_T *mf_new(memfile_T *mfp, bool negative, unsigned page_count)
// Init the data to all zero, to avoid reading uninitialized data.
// This also avoids that the passwd file ends up in the swap file!
- (void)memset(hp->bh_data, 0, (size_t)mfp->mf_page_size * page_count);
+ memset(hp->bh_data, 0, (size_t)mfp->mf_page_size * page_count);
return hp;
}
@@ -390,7 +392,7 @@ int mf_sync(memfile_T *mfp, int flags)
// Then we only try to write blocks within the existing file. If that also
// fails then we give up.
int status = OK;
- bhdr_T *hp;
+ bhdr_T *hp = NULL;
// note, "last" block is typically earlier in the hash list
map_foreach_value(&mfp->mf_hash, hp, {
if (((flags & MFS_ALL) || hp->bh_bnum >= 0)
@@ -757,7 +759,7 @@ static bool mf_do_open(memfile_T *mfp, char *fname, int flags)
return false;
}
- (void)os_set_cloexec(mfp->mf_fd);
+ os_set_cloexec(mfp->mf_fd);
return true;
}
diff --git a/src/nvim/memfile.h b/src/nvim/memfile.h
index 687ac042a4..17913e5fb2 100644
--- a/src/nvim/memfile.h
+++ b/src/nvim/memfile.h
@@ -1,7 +1,7 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
-#include "nvim/memfile_defs.h" // IWYU pragma: export
+#include "nvim/memfile_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
/// flags for mf_sync()
enum {
diff --git a/src/nvim/memfile_defs.h b/src/nvim/memfile_defs.h
index db68ecf039..5caf13c9fb 100644
--- a/src/nvim/memfile_defs.h
+++ b/src/nvim/memfile_defs.h
@@ -5,8 +5,6 @@
#include <stdlib.h>
#include "nvim/map_defs.h"
-#include "nvim/pos_defs.h"
-#include "nvim/types_defs.h"
/// A block number.
///
@@ -26,7 +24,7 @@ typedef int64_t blocknr_T;
/// The free list is a single linked list, not sorted.
/// The blocks in the free list have no block of memory allocated and
/// the contents of the block in the file (if any) is irrelevant.
-typedef struct bhdr {
+typedef struct {
blocknr_T bh_bnum; ///< key used in hash table
void *bh_data; ///< pointer to memory (for used block)
@@ -44,7 +42,7 @@ typedef enum {
} mfdirty_T;
/// A memory file.
-typedef struct memfile {
+typedef struct {
char *mf_fname; ///< name of the file
char *mf_ffname; ///< idem, full path
int mf_fd; ///< file descriptor
diff --git a/src/nvim/memline.c b/src/nvim/memline.c
index 3c671121b7..6b2f26b2d8 100644
--- a/src/nvim/memline.c
+++ b/src/nvim/memline.c
@@ -39,7 +39,6 @@
#include <stddef.h>
#include <stdio.h>
#include <string.h>
-#include <sys/types.h>
#include <time.h>
#include <uv.h>
@@ -47,6 +46,7 @@
#include "klib/kvec.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/change.h"
@@ -56,11 +56,11 @@
#include "nvim/eval/typval.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/input.h"
#include "nvim/macros_defs.h"
#include "nvim/main.h"
@@ -68,16 +68,21 @@
#include "nvim/mark.h"
#include "nvim/mbyte.h"
#include "nvim/memfile.h"
+#include "nvim/memfile_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/process.h"
#include "nvim/os/time.h"
+#include "nvim/os/time_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/spell.h"
@@ -331,7 +336,7 @@ int ml_open(buf_T *buf)
b0p->b0_dirty = buf->b_changed ? B0_DIRTY : 0;
b0p->b0_flags = (char)(get_fileformat(buf) + 1);
set_b0_fname(b0p, buf);
- (void)os_get_username(b0p->b0_uname, B0_UNAME_SIZE);
+ os_get_username(b0p->b0_uname, B0_UNAME_SIZE);
b0p->b0_uname[B0_UNAME_SIZE - 1] = NUL;
os_get_hostname(b0p->b0_hname, B0_HNAME_SIZE);
b0p->b0_hname[B0_HNAME_SIZE - 1] = NUL;
@@ -345,7 +350,7 @@ int ml_open(buf_T *buf)
// is created.
mf_put(mfp, hp, true, false);
if (!buf->b_help && !buf->b_spell) {
- (void)mf_sync(mfp, 0);
+ mf_sync(mfp, 0);
}
// Fill in root pointer block and write page 1.
@@ -451,7 +456,7 @@ void ml_setname(buf_T *buf)
emsg(_("E301: Oops, lost the swap file!!!"));
return;
}
- (void)os_set_cloexec(mfp->mf_fd);
+ os_set_cloexec(mfp->mf_fd);
}
if (!success) {
emsg(_("E302: Could not rename swap file"));
@@ -486,7 +491,7 @@ void ml_open_file(buf_T *buf)
if (buf->b_spell) {
char *fname = vim_tempname();
if (fname != NULL) {
- (void)mf_open_file(mfp, fname); // consumes fname!
+ mf_open_file(mfp, fname); // consumes fname!
}
buf->b_may_swap = false;
return;
@@ -530,8 +535,8 @@ void ml_open_file(buf_T *buf)
if (*p_dir != NUL && mfp->mf_fname == NULL) {
need_wait_return = true; // call wait_return() later
no_wait_return++;
- (void)semsg(_("E303: Unable to open swap file for \"%s\", recovery impossible"),
- buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname);
+ semsg(_("E303: Unable to open swap file for \"%s\", recovery impossible"),
+ buf_spname(buf) != NULL ? buf_spname(buf) : buf->b_fname);
no_wait_return--;
}
@@ -795,7 +800,7 @@ void ml_recover(bool checkext)
i = 1;
} else { // several swapfiles found, choose
// list the names of the swapfiles
- (void)recover_names(fname, true, NULL, 0, NULL);
+ recover_names(fname, true, NULL, 0, NULL);
msg_putchar('\n');
msg_puts(_("Enter number of swap file to use (0 to quit): "));
i = get_number(false, NULL);
@@ -804,7 +809,7 @@ void ml_recover(bool checkext)
}
}
// get the swapfile name that will be used
- (void)recover_names(fname, false, NULL, i, &fname_used);
+ recover_names(fname, false, NULL, i, &fname_used);
}
if (fname_used == NULL) {
goto theend; // user chose invalid number.
@@ -975,7 +980,7 @@ void ml_recover(bool checkext)
set_fileformat(b0_ff - 1, OPT_LOCAL);
}
if (b0_fenc != NULL) {
- set_option_value_give_err("fenc", CSTR_AS_OPTVAL(b0_fenc), OPT_LOCAL);
+ set_option_value_give_err(kOptFileencoding, CSTR_AS_OPTVAL(b0_fenc), OPT_LOCAL);
xfree(b0_fenc);
}
unchanged(curbuf, true, true);
@@ -1292,7 +1297,7 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn
// Isolate a directory name from *dirp and put it in dir_name (we know
// it is large enough, so use 31000 for length).
// Advance dirp to next directory name.
- (void)copy_option_part(&dirp, dir_name, 31000, ",");
+ copy_option_part(&dirp, dir_name, 31000, ",");
if (dir_name[0] == '.' && dir_name[1] == NUL) { // check current dir
if (fname == NULL) {
@@ -1403,7 +1408,7 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn
msg_puts(". ");
msg_puts(path_tail(files[i]));
msg_putchar('\n');
- (void)swapfile_info(files[i]);
+ swapfile_info(files[i]);
}
} else {
msg_puts(_(" -- none --\n"));
@@ -1642,7 +1647,7 @@ static bool swapfile_unchanged(char *fname)
return ret;
}
-static int recov_file_names(char **names, char *path, int prepend_dot)
+static int recov_file_names(char **names, char *path, bool prepend_dot)
FUNC_ATTR_NONNULL_ALL
{
int num_names = 0;
@@ -1689,9 +1694,9 @@ void ml_sync_all(int check_file, int check_char, bool do_fsync)
if (buf->b_ml.ml_mfp == NULL || buf->b_ml.ml_mfp->mf_fname == NULL) {
continue; // no file
}
- ml_flush_line(buf); // flush buffered line
+ ml_flush_line(buf, false); // flush buffered line
// flush locked block
- (void)ml_find_line(buf, 0, ML_FLUSH);
+ ml_find_line(buf, 0, ML_FLUSH);
if (bufIsChanged(buf) && check_file && mf_need_trans(buf->b_ml.ml_mfp)
&& buf->b_ffname != NULL) {
// If the original file does not exist anymore or has been changed
@@ -1707,8 +1712,8 @@ void ml_sync_all(int check_file, int check_char, bool do_fsync)
}
}
if (buf->b_ml.ml_mfp->mf_dirty == MF_DIRTY_YES) {
- (void)mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0)
- | (do_fsync && bufIsChanged(buf) ? MFS_FLUSH : 0));
+ mf_sync(buf->b_ml.ml_mfp, (check_char ? MFS_STOP : 0)
+ | (do_fsync && bufIsChanged(buf) ? MFS_FLUSH : 0));
if (check_char && os_char_avail()) { // character available now
break;
}
@@ -1724,7 +1729,7 @@ void ml_sync_all(int check_file, int check_char, bool do_fsync)
/// changed or deleted.
///
/// @param message if true, the success of preserving is reported.
-void ml_preserve(buf_T *buf, int message, bool do_fsync)
+void ml_preserve(buf_T *buf, bool message, bool do_fsync)
{
memfile_T *mfp = buf->b_ml.ml_mfp;
int got_int_save = got_int;
@@ -1740,8 +1745,8 @@ void ml_preserve(buf_T *buf, int message, bool do_fsync)
// before.
got_int = false;
- ml_flush_line(buf); // flush buffered line
- (void)ml_find_line(buf, 0, ML_FLUSH); // flush locked block
+ ml_flush_line(buf, false); // flush buffered line
+ ml_find_line(buf, 0, ML_FLUSH); // flush locked block
int status = mf_sync(mfp, MFS_ALL | (do_fsync ? MFS_FLUSH : 0));
// stack is invalid after mf_sync(.., MFS_ALL)
@@ -1768,7 +1773,7 @@ void ml_preserve(buf_T *buf, int message, bool do_fsync)
CHECK(buf->b_ml.ml_locked_low != lnum, "low != lnum");
lnum = buf->b_ml.ml_locked_high + 1;
}
- (void)ml_find_line(buf, 0, ML_FLUSH); // flush locked block
+ ml_find_line(buf, 0, ML_FLUSH); // flush locked block
// sync the updated pointer blocks
if (mf_sync(mfp, MFS_ALL | (do_fsync ? MFS_FLUSH : 0)) == FAIL) {
status = FAIL;
@@ -1857,7 +1862,7 @@ static char *ml_get_buf_impl(buf_T *buf, linenr_T lnum, bool will_change)
siemsg(_(e_ml_get_invalid_lnum_nr), (int64_t)lnum);
recursive--;
}
- ml_flush_line(buf);
+ ml_flush_line(buf, false);
errorret:
STRCPY(questions, "???");
buf->b_ml.ml_line_lnum = lnum;
@@ -1876,7 +1881,7 @@ errorret:
// Don't use the last used line when 'swapfile' is reset, need to load all
// blocks.
if (buf->b_ml.ml_line_lnum != lnum) {
- ml_flush_line(buf);
+ ml_flush_line(buf, false);
// Find the data block containing the line.
// This also fills the stack with the blocks from the root to the data
@@ -1959,7 +1964,7 @@ int ml_append(linenr_T lnum, char *line, colnr_T len, bool newfile)
}
if (curbuf->b_ml.ml_line_lnum != 0) {
- ml_flush_line(curbuf);
+ ml_flush_line(curbuf, false);
}
return ml_append_int(curbuf, lnum, line, len, newfile, false);
}
@@ -1979,7 +1984,7 @@ int ml_append_buf(buf_T *buf, linenr_T lnum, char *line, colnr_T len, bool newfi
}
if (buf->b_ml.ml_line_lnum != 0) {
- ml_flush_line(buf);
+ ml_flush_line(buf, false);
}
return ml_append_int(buf, lnum, line, len, newfile, false);
}
@@ -1989,7 +1994,8 @@ int ml_append_buf(buf_T *buf, linenr_T lnum, char *line, colnr_T len, bool newfi
/// @param len length of line, including NUL, or 0
/// @param newfile flag, see above
/// @param mark mark the new line
-static int ml_append_int(buf_T *buf, linenr_T lnum, char *line, colnr_T len, bool newfile, int mark)
+static int ml_append_int(buf_T *buf, linenr_T lnum, char *line, colnr_T len, bool newfile,
+ bool mark)
{
// lnum out of range
if (lnum > buf->b_ml.ml_line_count || buf->b_ml.ml_mfp == NULL) {
@@ -2242,7 +2248,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char *line, colnr_T len, boo
// pointer blocks is done below
int lineadd = buf->b_ml.ml_locked_lineadd;
buf->b_ml.ml_locked_lineadd = 0;
- (void)ml_find_line(buf, 0, ML_FLUSH); // flush data block
+ ml_find_line(buf, 0, ML_FLUSH); // flush data block
// update pointer blocks for the new data block
for (stack_idx = buf->b_ml.ml_stack_top - 1; stack_idx >= 0; stack_idx--) {
@@ -2289,8 +2295,7 @@ static int ml_append_int(buf_T *buf, linenr_T lnum, char *line, colnr_T len, boo
// fix line count for rest of blocks in the stack
ml_lineadd(buf, lineadd);
// fix stack itself
- buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high +=
- lineadd;
+ buf->b_ml.ml_stack[buf->b_ml.ml_stack_top].ip_high += lineadd;
(buf->b_ml.ml_stack_top)++;
}
@@ -2418,7 +2423,7 @@ void ml_add_deleted_len_buf(buf_T *buf, char *ptr, ssize_t len)
int ml_replace(linenr_T lnum, char *line, bool copy)
{
- return ml_replace_buf(curbuf, lnum, line, copy);
+ return ml_replace_buf(curbuf, lnum, line, copy, false);
}
/// Replace line "lnum", with buffering, in current buffer.
@@ -2433,7 +2438,7 @@ int ml_replace(linenr_T lnum, char *line, bool copy)
/// changed_lines(), unless update_screen(UPD_NOT_VALID) is used.
///
/// @return FAIL for failure, OK otherwise
-int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy)
+int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy, bool noalloc)
{
if (line == NULL) { // just checking...
return FAIL;
@@ -2445,12 +2450,13 @@ int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy)
}
if (copy) {
+ assert(!noalloc);
line = xstrdup(line);
}
if (buf->b_ml.ml_line_lnum != lnum) {
// another line is buffered, flush it
- ml_flush_line(buf);
+ ml_flush_line(buf, false);
}
if (kv_size(buf->update_callbacks)) {
@@ -2464,6 +2470,13 @@ int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy)
buf->b_ml.ml_line_ptr = line;
buf->b_ml.ml_line_lnum = lnum;
buf->b_ml.ml_flags = (buf->b_ml.ml_flags | ML_LINE_DIRTY) & ~ML_EMPTY;
+ if (noalloc) {
+ // TODO(bfredl): this is a bit of a hack. but replacing lines in a loop is really common,
+ // and allocating a separate scratch buffer for each line which is immediately freed adds
+ // a lot of noise. A more general refactor could be to use a _fixed_ scratch buffer for
+ // all lines up to $REASONABLE_SIZE .
+ ml_flush_line(buf, true);
+ }
return OK;
}
@@ -2478,7 +2491,7 @@ int ml_replace_buf(buf_T *buf, linenr_T lnum, char *line, bool copy)
/// @return FAIL for failure, OK otherwise
int ml_delete(linenr_T lnum, bool message)
{
- ml_flush_line(curbuf);
+ ml_flush_line(curbuf, false);
return ml_delete_int(curbuf, lnum, message);
}
@@ -2491,7 +2504,7 @@ int ml_delete(linenr_T lnum, bool message)
/// @return FAIL for failure, OK otherwise
int ml_delete_buf(buf_T *buf, linenr_T lnum, bool message)
{
- ml_flush_line(buf);
+ ml_flush_line(buf, false);
return ml_delete_int(buf, lnum, message);
}
@@ -2511,7 +2524,7 @@ static int ml_delete_int(buf_T *buf, linenr_T lnum, bool message)
set_keep_msg(_(no_lines_msg), 0);
}
- int i = ml_replace_buf(buf, 1, "", true);
+ int i = ml_replace_buf(buf, 1, "", true, false);
buf->b_ml.ml_flags |= ML_EMPTY;
return i;
@@ -2719,7 +2732,7 @@ size_t ml_flush_deleted_bytes(buf_T *buf, size_t *codepoints, size_t *codeunits)
}
/// flush ml_line if necessary
-static void ml_flush_line(buf_T *buf)
+static void ml_flush_line(buf_T *buf, bool noalloc)
{
static bool entered = false;
@@ -2788,15 +2801,18 @@ static void ml_flush_line(buf_T *buf)
// that has only one line.
// Don't forget to copy the mark!
// How about handling errors???
- (void)ml_append_int(buf, lnum, new_line, new_len, false,
- (int)(dp->db_index[idx] & DB_MARKED));
- (void)ml_delete_int(buf, lnum, false);
+ ml_append_int(buf, lnum, new_line, new_len, false,
+ (int)(dp->db_index[idx] & DB_MARKED));
+ ml_delete_int(buf, lnum, false);
}
}
- xfree(new_line);
+ if (!noalloc) {
+ xfree(new_line);
+ }
entered = false;
} else if (buf->b_ml.ml_flags & ML_ALLOCATED) {
+ assert(!noalloc); // caller must set ML_LINE_DIRTY with noalloc, handled above
xfree(buf->b_ml.ml_line_ptr);
}
@@ -3208,7 +3224,7 @@ static void attention_message(buf_T *buf, char *fname)
assert(buf->b_fname != NULL);
no_wait_return++;
- (void)emsg(_("E325: ATTENTION"));
+ emsg(_("E325: ATTENTION"));
msg_puts(_("\nFound a swap file by the name \""));
msg_home_replace(fname);
msg_puts("\"\n");
@@ -3311,7 +3327,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
// First allocate some memory to put the directory name in.
const size_t dir_len = strlen(*dirp) + 1;
char *dir_name = xmalloc(dir_len);
- (void)copy_option_part(dirp, dir_name, dir_len, ",");
+ copy_option_part(dirp, dir_name, dir_len, ",");
// We try different swapfile names until we find one that does not exist yet.
char *fname = makeswapname(buf_fname, buf->b_ffname, buf, dir_name);
@@ -3348,7 +3364,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
if (!recoverymode && buf_fname != NULL && !buf->b_help && !(buf->b_flags & BF_DUMMY)) {
int fd;
ZeroBlock b0;
- int differ = false;
+ bool differ = false;
// Try to read block 0 from the swapfile to get the original file name (and inode number).
fd = os_open(fname, O_RDONLY, 0);
@@ -3387,7 +3403,7 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
// Show the ATTENTION message when:
// - there is an old swapfile for the current file
// - the buffer was not recovered
- if (differ == false && !(curbuf->b_flags & BF_RECOVERED)
+ if (!differ && !(curbuf->b_flags & BF_RECOVERED)
&& vim_strchr(p_shm, SHM_ATTENTION) == NULL) {
sea_choice_T choice = SEA_CHOICE_NONE;
@@ -3898,7 +3914,7 @@ int ml_find_line_or_offset(buf_T *buf, linenr_T lnum, int *offp, bool no_ff)
// was never cached to start with anyway).
bool can_cache = (lnum != 0 && !ffdos && buf->b_ml.ml_line_lnum == lnum);
if (lnum == 0 || buf->b_ml.ml_line_lnum < lnum || !no_ff) {
- ml_flush_line(curbuf);
+ ml_flush_line(curbuf, false);
} else if (can_cache && buf->b_ml.ml_line_offset > 0) {
return (int)buf->b_ml.ml_line_offset;
}
@@ -3908,7 +3924,7 @@ int ml_find_line_or_offset(buf_T *buf, linenr_T lnum, int *offp, bool no_ff)
|| lnum < 0) {
// memline is currently empty. Although if it is loaded,
// it behaves like there is one empty line.
- if (!ffdos && buf->b_ml.ml_mfp && (lnum == 1 || lnum == 2)) {
+ if (no_ff && buf->b_ml.ml_mfp && (lnum == 1 || lnum == 2)) {
return lnum - 1;
}
return -1;
@@ -4025,7 +4041,7 @@ void goto_byte(int cnt)
{
int boff = cnt;
- ml_flush_line(curbuf); // cached line may be dirty
+ ml_flush_line(curbuf, false); // cached line may be dirty
setpcmark();
if (boff) {
boff--;
diff --git a/src/nvim/memline.h b/src/nvim/memline.h
index e70a8e423e..23cbf75c19 100644
--- a/src/nvim/memline.h
+++ b/src/nvim/memline.h
@@ -1,10 +1,14 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
-#include "nvim/memline_defs.h" // IWYU pragma: export
+#include "nvim/ascii_defs.h"
+#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
+#include "nvim/memline_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "memline.h.generated.h"
#endif
+
+/// LINEEMPTY() - return true if the line is empty
+#define LINEEMPTY(p) (*ml_get(p) == NUL)
diff --git a/src/nvim/memline_defs.h b/src/nvim/memline_defs.h
index f95dc7a2e5..1a217c96d4 100644
--- a/src/nvim/memline_defs.h
+++ b/src/nvim/memline_defs.h
@@ -1,20 +1,21 @@
#pragma once
#include "nvim/memfile_defs.h"
+#include "nvim/pos_defs.h"
///
/// When searching for a specific line, we remember what blocks in the tree
/// are the branches leading to that block. This is stored in ml_stack. Each
/// entry is a pointer to info in a block (may be data block or pointer block)
///
-typedef struct info_pointer {
+typedef struct {
blocknr_T ip_bnum; // block number
linenr_T ip_low; // lowest lnum in this block
linenr_T ip_high; // highest lnum in this block
int ip_index; // index for block with current lnum
} infoptr_T; // block/index pair
-typedef struct ml_chunksize {
+typedef struct {
int mlcs_numlines;
int mlcs_totalsize;
} chunksize_T;
@@ -39,7 +40,7 @@ typedef struct ml_chunksize {
/// memory. With this structure it is roughly (N * 128) pointer
/// moves, where N is the height (typically 1-3).
///
-typedef struct memline {
+typedef struct {
linenr_T ml_line_count; // number of lines in the buffer
memfile_T *ml_mfp; // pointer to associated memfile
diff --git a/src/nvim/memory.c b/src/nvim/memory.c
index df6c81fe0d..37e53e4453 100644
--- a/src/nvim/memory.c
+++ b/src/nvim/memory.c
@@ -9,29 +9,38 @@
#include <time.h>
#include "nvim/api/extmark.h"
+#include "nvim/api/private/helpers.h"
+#include "nvim/api/ui.h"
#include "nvim/arglist.h"
#include "nvim/ascii_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
+#include "nvim/channel.h"
#include "nvim/context.h"
#include "nvim/decoration_provider.h"
#include "nvim/drawline.h"
#include "nvim/eval.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
#include "nvim/highlight_group.h"
#include "nvim/insexpand.h"
#include "nvim/lua/executor.h"
#include "nvim/main.h"
+#include "nvim/map_defs.h"
#include "nvim/mapping.h"
#include "nvim/memfile.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option_vars.h"
+#include "nvim/os/input.h"
#include "nvim/sign.h"
#include "nvim/state_defs.h"
+#include "nvim/statusline.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_client.h"
+#include "nvim/ui_compositor.h"
#include "nvim/usercmd.h"
#include "nvim/vim_defs.h"
@@ -279,7 +288,8 @@ void strchrsub(char *str, char c, char x)
void memchrsub(void *data, char c, char x, size_t len)
FUNC_ATTR_NONNULL_ALL
{
- char *p = data, *end = (char *)data + len;
+ char *p = data;
+ char *end = (char *)data + len;
while ((p = memchr(p, c, (size_t)(end - p)))) {
*p++ = x;
}
@@ -314,7 +324,8 @@ size_t memcnt(const void *data, char c, size_t len)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE
{
size_t cnt = 0;
- const char *ptr = data, *end = ptr + len;
+ const char *ptr = data;
+ const char *end = ptr + len;
while ((ptr = memchr(ptr, c, (size_t)(end - ptr))) != NULL) {
cnt++;
ptr++; // Skip the instance of c.
@@ -508,6 +519,13 @@ bool strequal(const char *a, const char *b)
return (a == NULL && b == NULL) || (a && b && strcmp(a, b) == 0);
}
+/// Returns true if first `n` characters of strings `a` and `b` are equal. Arguments may be NULL.
+bool strnequal(const char *a, const char *b, size_t n)
+ FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
+{
+ return (a == NULL && b == NULL) || (a && b && strncmp(a, b, n) == 0);
+}
+
// Avoid repeating the error message many times (they take 1 second each).
// Did_outofmem_msg is reset when a character is read.
void do_outofmem_msg(size_t size)
@@ -536,7 +554,6 @@ void time_to_bytes(time_t time_, uint8_t buf[8])
}
}
-#define ARENA_BLOCK_SIZE 4096
#define REUSE_MAX 4
static struct consumed_blk *arena_reuse_blk;
@@ -565,17 +582,26 @@ ArenaMem arena_finish(Arena *arena)
return res;
}
-void alloc_block(Arena *arena)
+/// allocate a block of ARENA_BLOCK_SIZE
+///
+/// free it with free_block
+void *alloc_block(void)
{
- struct consumed_blk *prev_blk = (struct consumed_blk *)arena->cur_blk;
if (arena_reuse_blk_count > 0) {
- arena->cur_blk = (char *)arena_reuse_blk;
+ void *retval = (char *)arena_reuse_blk;
arena_reuse_blk = arena_reuse_blk->prev;
arena_reuse_blk_count--;
+ return retval;
} else {
arena_alloc_count++;
- arena->cur_blk = xmalloc(ARENA_BLOCK_SIZE);
+ return xmalloc(ARENA_BLOCK_SIZE);
}
+}
+
+void arena_alloc_block(Arena *arena)
+{
+ struct consumed_blk *prev_blk = (struct consumed_blk *)arena->cur_blk;
+ arena->cur_blk = alloc_block();
arena->pos = 0;
arena->size = ARENA_BLOCK_SIZE;
struct consumed_blk *blk = arena_alloc(arena, sizeof(struct consumed_blk), true);
@@ -597,7 +623,7 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
return xmalloc(size);
}
if (!arena->cur_blk) {
- alloc_block(arena);
+ arena_alloc_block(arena);
}
size_t alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos;
if (alloc_pos + size > arena->size) {
@@ -619,7 +645,7 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
cur_blk->prev = fix_blk;
return alloc + aligned_hdr_size;
} else {
- alloc_block(arena); // resets arena->pos
+ arena_alloc_block(arena); // resets arena->pos
alloc_pos = align ? arena_align_offset(arena->pos) : arena->pos;
}
}
@@ -629,17 +655,27 @@ void *arena_alloc(Arena *arena, size_t size, bool align)
return mem;
}
+void free_block(void *block)
+{
+ if (arena_reuse_blk_count < REUSE_MAX) {
+ struct consumed_blk *reuse_blk = block;
+ reuse_blk->prev = arena_reuse_blk;
+ arena_reuse_blk = reuse_blk;
+ arena_reuse_blk_count++;
+ } else {
+ xfree(block);
+ }
+}
+
void arena_mem_free(ArenaMem mem)
{
struct consumed_blk *b = mem;
// peel of the first block, as it is guaranteed to be ARENA_BLOCK_SIZE,
// not a custom fix_blk
- if (arena_reuse_blk_count < REUSE_MAX && b != NULL) {
+ if (b != NULL) {
struct consumed_blk *reuse_blk = b;
b = b->prev;
- reuse_blk->prev = arena_reuse_blk;
- arena_reuse_blk = reuse_blk;
- arena_reuse_blk_count++;
+ free_block(reuse_blk);
}
while (b) {
@@ -649,14 +685,20 @@ void arena_mem_free(ArenaMem mem)
}
}
-char *arena_memdupz(Arena *arena, const char *buf, size_t size)
+char *arena_allocz(Arena *arena, size_t size)
{
char *mem = arena_alloc(arena, size + 1, false);
- memcpy(mem, buf, size);
mem[size] = NUL;
return mem;
}
+char *arena_memdupz(Arena *arena, const char *buf, size_t size)
+{
+ char *mem = arena_allocz(arena, size);
+ memcpy(mem, buf, size);
+ return mem;
+}
+
#if defined(EXITFREE)
# include "nvim/autocmd.h"
@@ -705,13 +747,6 @@ void free_all_mem(void)
do_cmdline_cmd("tabonly!");
}
- if (!ONE_WINDOW) {
- // to keep things simple, don't perform this
- // ritual inside a float
- curwin = firstwin;
- do_cmdline_cmd("only!");
- }
-
// Free all spell info.
spell_free_all();
@@ -739,6 +774,7 @@ void free_all_mem(void)
free_all_marks();
alist_clear(&global_alist);
free_homedir();
+ free_envmap();
free_users();
free_search_patterns();
free_old_sub();
@@ -773,6 +809,25 @@ void free_all_mem(void)
// Free all option values. Must come after closing windows.
free_all_options();
+ // Free all buffers. Reset 'autochdir' to avoid accessing things that
+ // were freed already.
+ // Must be after eval_clear to avoid it trying to access b:changedtick after
+ // freeing it.
+ p_acd = false;
+ for (buf = firstbuf; buf != NULL;) {
+ bufref_T bufref;
+ set_bufref(&bufref, buf);
+ nextbuf = buf->b_next;
+
+ // Since options (in addition to other stuff) have been freed above we need to ensure no
+ // callbacks are called, so free them before closing the buffer.
+ buf_free_callbacks(buf);
+
+ close_buffer(NULL, buf, DOBUF_WIPE, false, false);
+ // Didn't work, try next one.
+ buf = bufref_valid(&bufref) ? nextbuf : firstbuf;
+ }
+
// Clear registers.
clear_registers();
ResetRedobuff();
@@ -793,31 +848,19 @@ void free_all_mem(void)
}
}
+ channel_free_all_mem();
eval_clear();
api_extmark_free_all_mem();
ctx_free_all();
- // Free all buffers. Reset 'autochdir' to avoid accessing things that
- // were freed already.
- // Must be after eval_clear to avoid it trying to access b:changedtick after
- // freeing it.
- p_acd = false;
- for (buf = firstbuf; buf != NULL;) {
- bufref_T bufref;
- set_bufref(&bufref, buf);
- nextbuf = buf->b_next;
-
- // Since options (in addition to other stuff) have been freed above we need to ensure no
- // callbacks are called, so free them before closing the buffer.
- buf_free_callbacks(buf);
-
- close_buffer(NULL, buf, DOBUF_WIPE, false, false);
- // Didn't work, try next one.
- buf = bufref_valid(&bufref) ? nextbuf : firstbuf;
- }
+ map_destroy(int, &buffer_handles);
+ map_destroy(int, &window_handles);
+ map_destroy(int, &tabpage_handles);
// free screenlines (can't display anything now!)
grid_free_all_mem();
+ stl_clear_click_defs(tab_page_click_defs, tab_page_click_defs_size);
+ xfree(tab_page_click_defs);
clear_hl_tables(false);
@@ -825,8 +868,15 @@ void free_all_mem(void)
decor_free_all_mem();
drawline_free_all_mem();
+ input_free_all_mem();
+
+ if (ui_client_channel_id) {
+ ui_client_free_all_mem();
+ }
+ remote_ui_free_all_mem();
ui_free_all_mem();
+ ui_comp_free_all_mem();
nlua_free_all_mem();
rpc_free_all_mem();
diff --git a/src/nvim/memory.h b/src/nvim/memory.h
index ffdc4c7366..0788670142 100644
--- a/src/nvim/memory.h
+++ b/src/nvim/memory.h
@@ -6,7 +6,7 @@
#include "auto/config.h"
#include "nvim/macros_defs.h"
-#include "nvim/memory_defs.h" // IWYU pragma: export
+#include "nvim/memory_defs.h" // IWYU pragma: keep
/// `malloc()` function signature
typedef void *(*MemMalloc)(size_t);
@@ -45,6 +45,8 @@ EXTERN size_t arena_alloc_count INIT( = 0);
((v).capacity = (s), \
(v).items = (void *)arena_alloc(a, sizeof((v).items[0]) * (v).capacity, true))
+#define ARENA_BLOCK_SIZE 4096
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "memory.h.generated.h"
#endif
diff --git a/src/nvim/menu.c b/src/nvim/menu.c
index 3252a73970..4ca2a61ab1 100644
--- a/src/nvim/menu.c
+++ b/src/nvim/menu.c
@@ -8,22 +8,28 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand_defs.h"
#include "nvim/cursor.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/getchar_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memory.h"
#include "nvim/menu.h"
#include "nvim/menu_defs.h"
@@ -32,6 +38,7 @@
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
@@ -69,7 +76,7 @@ void ex_menu(exarg_T *eap)
char *map_to; // command mapped to the menu entry
int noremap;
bool silent = false;
- int unmenu;
+ bool unmenu;
char *map_buf;
char *p;
int i;
@@ -226,7 +233,7 @@ void ex_menu(exarg_T *eap)
} else {
map_buf = NULL;
map_to = replace_termcodes(map_to, strlen(map_to), &map_buf, 0,
- REPTERM_DO_LT, NULL, CPO_TO_CPO_FLAGS);
+ REPTERM_DO_LT, NULL, p_cpo);
}
menuarg.modes = modes;
menuarg.noremap[0] = noremap;
@@ -868,7 +875,7 @@ char *set_context_in_menu_cmd(expand_T *xp, const char *cmd, char *arg, bool for
char *after_dot;
char *p;
char *path_name = NULL;
- int unmenu;
+ bool unmenu;
vimmenu_T *menu;
xp->xp_context = EXPAND_UNSUCCESSFUL;
@@ -969,7 +976,7 @@ char *get_menu_name(expand_T *xp, int idx)
{
static vimmenu_T *menu = NULL;
char *str;
- static int should_advance = false;
+ static bool should_advance = false;
if (idx == 0) { // first call: start at first item
menu = expand_menu;
@@ -1132,7 +1139,7 @@ static bool menu_namecmp(const char *const name, const char *const mname)
/// to whether the command is a "nore" command.
/// @param[out] unmenu If not NULL, the flag it points to is set according
/// to whether the command is an "unmenu" command.
-int get_menu_cmd_modes(const char *cmd, bool forceit, int *noremap, int *unmenu)
+int get_menu_cmd_modes(const char *cmd, bool forceit, int *noremap, bool *unmenu)
{
int modes;
@@ -1335,9 +1342,9 @@ bool menu_is_toolbar(const char *const name)
return strncmp(name, "ToolBar", 7) == 0;
}
-/// Return true if the name is a menu separator identifier: Starts and ends
-/// with '-'
-int menu_is_separator(char *name)
+/// @return true if the name is a menu separator identifier: Starts and ends
+/// with '-'
+bool menu_is_separator(char *name)
{
return name[0] == '-' && name[strlen(name) - 1] == '-';
}
@@ -1345,7 +1352,7 @@ int menu_is_separator(char *name)
/// True if a popup menu or starts with \ref MNU_HIDDEN_CHAR
///
/// @return true if the menu is hidden
-static int menu_is_hidden(char *name)
+static bool menu_is_hidden(char *name)
{
return (name[0] == MNU_HIDDEN_CHAR)
|| (menu_is_popup(name) && name[5] != NUL);
diff --git a/src/nvim/menu.h b/src/nvim/menu.h
index 9644386003..08f5601ca3 100644
--- a/src/nvim/menu.h
+++ b/src/nvim/menu.h
@@ -2,7 +2,7 @@
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
-#include "nvim/menu_defs.h" // IWYU pragma: export
+#include "nvim/menu_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/message.c b/src/nvim/message.c
index 3268ff389a..175e3b5d03 100644
--- a/src/nvim/message.c
+++ b/src/nvim/message.c
@@ -8,8 +8,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
+#include "klib/kvec.h"
+#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
@@ -18,25 +20,28 @@
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_eval.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/indent.h"
#include "nvim/input.h"
#include "nvim/keycodes.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
@@ -50,11 +55,13 @@
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/ui_compositor.h"
+#include "nvim/ui_defs.h"
#include "nvim/vim_defs.h"
// To be able to scroll back at the "more" and "hit-enter" prompts we need to
@@ -87,7 +94,7 @@ MessageHistoryEntry *last_msg_hist = NULL;
static int msg_hist_len = 0;
static FILE *verbose_fd = NULL;
-static int verbose_did_open = false;
+static bool verbose_did_open = false;
bool keep_msg_more = false; // keep_msg was set by msgmore()
@@ -122,7 +129,7 @@ bool keep_msg_more = false; // keep_msg was set by msgmore()
// Set: When the ruler or typeahead display is overwritten,
// scrolling the screen for some message.
// keep_msg Message to be displayed after redrawing the screen, in
-// main_loop().
+// Normal mode main loop.
// This is an allocated string or NULL when not used.
// Extended msg state, currently used for external UIs with ext_messages
@@ -144,9 +151,8 @@ static int msg_grid_pos_at_flush = 0;
static void ui_ext_msg_set_pos(int row, bool scrolled)
{
- char buf[MB_MAXCHAR + 1];
- size_t size = (size_t)utf_char2bytes(curwin->w_p_fcs_chars.msgsep, buf);
- buf[size] = '\0';
+ char buf[MAX_SCHAR_SIZE];
+ size_t size = schar_get(buf, curwin->w_p_fcs_chars.msgsep);
ui_call_msg_set_pos(msg_grid.handle, row, scrolled,
(String){ .data = buf, .size = size });
}
@@ -204,8 +210,13 @@ void msg_grid_validate(void)
msg_grid_adj.target = &default_grid;
redraw_cmdline = true;
} else if (msg_grid.chars && !msg_scrolled && msg_grid_pos != max_rows) {
+ int diff = msg_grid_pos - max_rows;
msg_grid_set_pos(max_rows, false);
+ if (diff > 0) {
+ grid_clear(&msg_grid_adj, Rows - diff, Rows, 0, Columns, HL_ATTR(HLF_MSG));
+ }
}
+ msg_grid_adj.cols = Columns;
if (msg_grid.chars && !msg_scrolled && cmdline_row < msg_grid_pos) {
// TODO(bfredl): this should already be the case, but fails in some
@@ -226,10 +237,10 @@ int verb_msg(const char *s)
}
/// Displays the string 's' on the status line
-/// When terminal not initialized (yet) os_errmsg(..) is used.
+/// When terminal not initialized (yet) printf("%s", ..) is used.
///
/// @return true if wait_return() not called
-int msg(const char *s, const int attr)
+bool msg(const char *s, const int attr)
FUNC_ATTR_NONNULL_ARG(1)
{
return msg_attr_keep(s, attr, false, false);
@@ -290,7 +301,6 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
FUNC_ATTR_NONNULL_ALL
{
static int entered = 0;
- char *buf = NULL;
if (keep && multiline) {
// Not implemented. 'multiline' is only used by nvim-added messages,
@@ -329,7 +339,7 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
// Truncate the message if needed.
msg_start();
- buf = msg_strtrunc(s, false);
+ char *buf = msg_strtrunc(s, false);
if (buf != NULL) {
s = buf;
}
@@ -343,7 +353,7 @@ bool msg_attr_keep(const char *s, int attr, bool keep, bool multiline)
if (need_clear) {
msg_clr_eos();
}
- int retval = msg_end();
+ bool retval = msg_end();
if (keep && retval && vim_strsize(s) < (Rows - cmdline_row - 1) * Columns + sc_col) {
set_keep_msg(s, 0);
@@ -462,7 +472,7 @@ void trunc_string(const char *s, char *buf, int room_in, int buflen)
}
} else if (e + 3 < buflen) {
// set the middle and copy the last part
- memmove(buf + e, "...", (size_t)3);
+ memmove(buf + e, "...", 3);
len = (int)strlen(s + i) + 1;
if (len >= buflen - e - 3) {
len = buflen - e - 3 - 1;
@@ -749,7 +759,7 @@ bool emsg_multiline(const char *s, bool multiline)
/// emsg() - display an error message
///
/// Rings the bell, if appropriate, and calls message() to do the real work
-/// When terminal not initialized (yet) os_errmsg(..) is used.
+/// When terminal not initialized (yet) fprintf(stderr, "%s", ..) is used.
///
/// @return true if wait_return() not called
bool emsg(const char *s)
@@ -841,7 +851,7 @@ void siemsg(const char *s, ...)
va_list ap;
va_start(ap, s);
- (void)semsgv(s, ap);
+ semsgv(s, ap);
va_end(ap);
#ifdef ABORT_ON_INTERNAL_ERROR
msg_putchar('\n'); // avoid overwriting the error message
@@ -859,7 +869,7 @@ void internal_error(const char *where)
static void msg_semsg_event(void **argv)
{
char *s = argv[0];
- (void)emsg(s);
+ emsg(s);
xfree(s);
}
@@ -872,13 +882,13 @@ void msg_schedule_semsg(const char *const fmt, ...)
va_end(ap);
char *s = xstrdup(IObuff);
- loop_schedule_deferred(&main_loop, event_create(msg_semsg_event, 1, s));
+ loop_schedule_deferred(&main_loop, event_create(msg_semsg_event, s));
}
static void msg_semsg_multiline_event(void **argv)
{
char *s = argv[0];
- (void)emsg_multiline(s, true);
+ emsg_multiline(s, true);
xfree(s);
}
@@ -890,7 +900,7 @@ void msg_schedule_semsg_multiline(const char *const fmt, ...)
va_end(ap);
char *s = xstrdup(IObuff);
- loop_schedule_deferred(&main_loop, event_create(msg_semsg_multiline_event, 1, s));
+ loop_schedule_deferred(&main_loop, event_create(msg_semsg_multiline_event, s));
}
/// Like msg(), but truncate to a single line if p_shm contains 't', or when
@@ -906,7 +916,7 @@ char *msg_trunc(char *s, bool force, int attr)
char *ts = msg_may_trunc(force, s);
msg_hist_off = true;
- int n = msg(ts, attr);
+ bool n = msg(ts, attr);
msg_hist_off = false;
if (n) {
@@ -971,7 +981,7 @@ static void add_msg_hist_multiattr(const char *s, int len, int attr, bool multil
// Don't let the message history get too big
while (msg_hist_len > MAX_MSG_HIST_LEN) {
- (void)delete_first_msg();
+ delete_first_msg();
}
// allocate an entry and add the message at the end of the history
@@ -1036,7 +1046,7 @@ void ex_messages(exarg_T *eap)
int keep = eap->addr_count == 0 ? 0 : eap->line2;
while (msg_hist_len > keep) {
- (void)delete_first_msg();
+ delete_first_msg();
}
return;
}
@@ -1251,7 +1261,7 @@ void wait_return(int redraw)
// Avoid that the mouse-up event causes visual mode to start.
if (c == K_LEFTMOUSE || c == K_MIDDLEMOUSE || c == K_RIGHTMOUSE
|| c == K_X1MOUSE || c == K_X2MOUSE) {
- (void)jump_to_mouse(MOUSE_SETPOS, NULL, 0);
+ jump_to_mouse(MOUSE_SETPOS, NULL, 0);
} else if (vim_strchr("\r\n ", c) == NULL && c != Ctrl_C) {
// Put the character back in the typeahead buffer. Don't use the
// stuff buffer, because lmaps wouldn't work.
@@ -1703,6 +1713,39 @@ char *str2special_save(const char *const str, const bool replace_spaces, const b
return (char *)ga.ga_data;
}
+/// Convert string, replacing key codes with printables
+///
+/// Used for lhs or rhs of mappings.
+///
+/// @param[in] str String to convert.
+/// @param[in] replace_spaces Convert spaces into `<Space>`, normally used for
+/// lhs of mapping and keytrans(), but not rhs.
+/// @param[in] replace_lt Convert `<` into `<lt>`.
+///
+/// @return [allocated] Converted string.
+char *str2special_arena(const char *str, bool replace_spaces, bool replace_lt, Arena *arena)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_MALLOC
+ FUNC_ATTR_NONNULL_RET
+{
+ const char *p = str;
+ size_t len = 0;
+ while (*p) {
+ len += strlen(str2special(&p, replace_spaces, replace_lt));
+ }
+
+ char *buf = arena_alloc(arena, len + 1, false);
+ size_t pos = 0;
+ p = str;
+ while (*p) {
+ const char *s = str2special(&p, replace_spaces, replace_lt);
+ size_t s_len = strlen(s);
+ memcpy(buf + pos, s, s_len);
+ pos += s_len;
+ }
+ buf[pos] = NUL;
+ return buf;
+}
+
/// Convert character, replacing key with printable representation.
///
/// @param[in,out] sp String to convert. Is advanced to the next key code.
@@ -1798,14 +1841,14 @@ void str2specialbuf(const char *sp, char *buf, size_t len)
}
/// print line for :print or :list command
-void msg_prt_line(const char *s, int list)
+void msg_prt_line(const char *s, bool list)
{
- int c;
+ schar_T sc;
int col = 0;
int n_extra = 0;
- int c_extra = 0;
- int c_final = 0;
- const char *p_extra = NULL; // init to make SASC shut up
+ schar_T sc_extra = 0;
+ schar_T sc_final = 0;
+ const char *p_extra = NULL; // init to make SASC shut up. ASCII only!
int n;
int attr = 0;
const char *lead = NULL;
@@ -1847,13 +1890,13 @@ void msg_prt_line(const char *s, int list)
while (!got_int) {
if (n_extra > 0) {
n_extra--;
- if (n_extra == 0 && c_final) {
- c = c_final;
- } else if (c_extra) {
- c = c_extra;
+ if (n_extra == 0 && sc_final) {
+ sc = sc_final;
+ } else if (sc_extra) {
+ sc = sc_extra;
} else {
assert(p_extra != NULL);
- c = (unsigned char)(*p_extra++);
+ sc = schar_from_ascii((unsigned char)(*p_extra++));
}
} else if ((l = utfc_ptr2len(s)) > 1) {
col += utf_ptr2cells(s);
@@ -1861,10 +1904,8 @@ void msg_prt_line(const char *s, int list)
if (l >= MB_MAXBYTES) {
xstrlcpy(buf, "?", sizeof(buf));
} else if (curwin->w_p_lcs_chars.nbsp != NUL && list
- && (utf_ptr2char(s) == 160
- || utf_ptr2char(s) == 0x202f)) {
- int len = utf_char2bytes(curwin->w_p_lcs_chars.nbsp, buf);
- buf[len] = NUL;
+ && (utf_ptr2char(s) == 160 || utf_ptr2char(s) == 0x202f)) {
+ schar_get(buf, curwin->w_p_lcs_chars.nbsp);
} else {
memmove(buf, s, (size_t)l);
buf[l] = NUL;
@@ -1874,7 +1915,9 @@ void msg_prt_line(const char *s, int list)
continue;
} else {
attr = 0;
- c = (uint8_t)(*s++);
+ int c = (uint8_t)(*s++);
+ sc_extra = NUL;
+ sc_final = NUL;
if (list) {
in_multispace = c == ' ' && (*s == ' '
|| (col > 0 && s[-2] == ' '));
@@ -1884,74 +1927,72 @@ void msg_prt_line(const char *s, int list)
}
if (c == TAB && (!list || curwin->w_p_lcs_chars.tab1)) {
// tab amount depends on current column
- n_extra = tabstop_padding(col,
- curbuf->b_p_ts,
+ n_extra = tabstop_padding(col, curbuf->b_p_ts,
curbuf->b_p_vts_array) - 1;
if (!list) {
- c = ' ';
- c_extra = ' ';
- c_final = NUL;
+ sc = schar_from_ascii(' ');
+ sc_extra = schar_from_ascii(' ');
} else {
- c = (n_extra == 0 && curwin->w_p_lcs_chars.tab3)
- ? curwin->w_p_lcs_chars.tab3
- : curwin->w_p_lcs_chars.tab1;
- c_extra = curwin->w_p_lcs_chars.tab2;
- c_final = curwin->w_p_lcs_chars.tab3;
+ sc = (n_extra == 0 && curwin->w_p_lcs_chars.tab3)
+ ? curwin->w_p_lcs_chars.tab3
+ : curwin->w_p_lcs_chars.tab1;
+ sc_extra = curwin->w_p_lcs_chars.tab2;
+ sc_final = curwin->w_p_lcs_chars.tab3;
attr = HL_ATTR(HLF_0);
}
- } else if (c == 160 && list && curwin->w_p_lcs_chars.nbsp != NUL) {
- c = curwin->w_p_lcs_chars.nbsp;
- attr = HL_ATTR(HLF_0);
} else if (c == NUL && list && curwin->w_p_lcs_chars.eol != NUL) {
p_extra = "";
- c_extra = NUL;
- c_final = NUL;
n_extra = 1;
- c = curwin->w_p_lcs_chars.eol;
+ sc = curwin->w_p_lcs_chars.eol;
attr = HL_ATTR(HLF_AT);
s--;
} else if (c != NUL && (n = byte2cells(c)) > 1) {
n_extra = n - 1;
p_extra = transchar_byte_buf(NULL, c);
- c_extra = NUL;
- c_final = NUL;
- c = (unsigned char)(*p_extra++);
+ sc = schar_from_ascii(*p_extra++);
// Use special coloring to be able to distinguish <hex> from
// the same in plain text.
attr = HL_ATTR(HLF_0);
} else if (c == ' ') {
if (lead != NULL && s <= lead && in_multispace
&& curwin->w_p_lcs_chars.leadmultispace != NULL) {
- c = curwin->w_p_lcs_chars.leadmultispace[multispace_pos++];
+ sc = curwin->w_p_lcs_chars.leadmultispace[multispace_pos++];
if (curwin->w_p_lcs_chars.leadmultispace[multispace_pos] == NUL) {
multispace_pos = 0;
}
attr = HL_ATTR(HLF_0);
} else if (lead != NULL && s <= lead && curwin->w_p_lcs_chars.lead != NUL) {
- c = curwin->w_p_lcs_chars.lead;
+ sc = curwin->w_p_lcs_chars.lead;
attr = HL_ATTR(HLF_0);
} else if (trail != NULL && s > trail) {
- c = curwin->w_p_lcs_chars.trail;
+ sc = curwin->w_p_lcs_chars.trail;
attr = HL_ATTR(HLF_0);
} else if (in_multispace
&& curwin->w_p_lcs_chars.multispace != NULL) {
- c = curwin->w_p_lcs_chars.multispace[multispace_pos++];
+ sc = curwin->w_p_lcs_chars.multispace[multispace_pos++];
if (curwin->w_p_lcs_chars.multispace[multispace_pos] == NUL) {
multispace_pos = 0;
}
attr = HL_ATTR(HLF_0);
} else if (list && curwin->w_p_lcs_chars.space != NUL) {
- c = curwin->w_p_lcs_chars.space;
+ sc = curwin->w_p_lcs_chars.space;
attr = HL_ATTR(HLF_0);
+ } else {
+ sc = schar_from_ascii(' '); // SPACE!
}
+ } else {
+ sc = schar_from_ascii(c);
}
}
- if (c == NUL) {
+ if (sc == NUL) {
break;
}
- msg_putchar_attr(c, attr);
+ // TODO(bfredl): this is such baloney. need msg_put_schar
+ char buf[MAX_SCHAR_SIZE];
+ schar_get(buf, sc);
+ msg_puts_attr(buf, attr);
col++;
}
msg_clr_eos();
@@ -2310,7 +2351,7 @@ void msg_scroll_up(bool may_throttle, bool zerocmd)
msg_grid.dirty_col[msg_grid.rows - 1] = 0;
}
- grid_fill(&msg_grid_adj, Rows - 1, Rows, 0, Columns, ' ', ' ', HL_ATTR(HLF_MSG));
+ grid_clear(&msg_grid_adj, Rows - 1, Rows, 0, Columns, HL_ATTR(HLF_MSG));
}
/// Send throttled message output to UI clients
@@ -2354,7 +2395,7 @@ void msg_scroll_flush(void)
for (int i = MAX(Rows - MAX(delta, 1), 0); i < Rows; i++) {
int row = i - msg_grid_pos;
assert(row >= 0);
- ui_line(&msg_grid, row, 0, msg_grid.dirty_col[row], msg_grid.cols,
+ ui_line(&msg_grid, row, false, 0, msg_grid.dirty_col[row], msg_grid.cols,
HL_ATTR(HLF_MSG), false);
msg_grid.dirty_col[row] = 0;
}
@@ -2411,9 +2452,7 @@ static void inc_msg_scrolled(void)
xfree(tofree);
}
msg_scrolled++;
- if (must_redraw < UPD_VALID) {
- must_redraw = UPD_VALID;
- }
+ set_must_redraw(UPD_VALID);
}
static msgchunk_T *last_msgchunk = NULL; // last displayed text
@@ -2524,7 +2563,7 @@ void sb_text_end_cmdline(void)
/// Clear any text remembered for scrolling back.
/// When "all" is false keep the last line.
/// Called when redrawing the screen.
-void clear_sb_text(int all)
+void clear_sb_text(bool all)
{
msgchunk_T *mp;
msgchunk_T **lastp;
@@ -2548,11 +2587,9 @@ void clear_sb_text(int all)
/// "g<" command.
void show_sb_text(void)
{
- msgchunk_T *mp;
-
// Only show something if there is more than one line, otherwise it looks
// weird, typing a command without output results in one line.
- mp = msg_sb_start(last_msgchunk);
+ msgchunk_T *mp = msg_sb_start(last_msgchunk);
if (mp == NULL || mp->sb_prev == NULL) {
vim_beep(BO_MESS);
} else {
@@ -2638,9 +2675,9 @@ static void msg_puts_printf(const char *str, const ptrdiff_t maxlen)
memcpy(p, s, (size_t)len);
*(p + len) = '\0';
if (info_message) {
- os_msg(buf);
+ printf("%s", buf);
} else {
- os_errmsg(buf);
+ fprintf(stderr, "%s", buf);
}
}
@@ -2662,13 +2699,13 @@ static void msg_puts_printf(const char *str, const ptrdiff_t maxlen)
/// otherwise it's NUL.
///
/// @return true when jumping ahead to "confirm_msg_tail".
-static int do_more_prompt(int typed_char)
+static bool do_more_prompt(int typed_char)
{
static bool entered = false;
int used_typed_char = typed_char;
int oldState = State;
int c;
- int retval = false;
+ bool retval = false;
bool to_redraw = false;
msgchunk_T *mp_last = NULL;
msgchunk_T *mp;
@@ -2827,16 +2864,14 @@ static int do_more_prompt(int typed_char)
if (toscroll == -1 && !to_redraw) {
grid_ins_lines(&msg_grid_adj, 0, 1, Rows, 0, Columns);
- grid_fill(&msg_grid_adj, 0, 1, 0, Columns, ' ', ' ',
- HL_ATTR(HLF_MSG));
+ grid_clear(&msg_grid_adj, 0, 1, 0, Columns, HL_ATTR(HLF_MSG));
// display line at top
- (void)disp_sb_line(0, mp);
+ disp_sb_line(0, mp);
} else {
// redisplay all lines
// TODO(bfredl): this case is not optimized (though only concerns
- // event fragmentization, not unnecessary scroll events).
- grid_fill(&msg_grid_adj, 0, Rows, 0, Columns, ' ', ' ',
- HL_ATTR(HLF_MSG));
+ // event fragmentation, not unnecessary scroll events).
+ grid_clear(&msg_grid_adj, 0, Rows, 0, Columns, HL_ATTR(HLF_MSG));
for (int i = 0; mp != NULL && i < Rows - 1; i++) {
mp = disp_sb_line(i, mp);
msg_scrolled++;
@@ -2862,8 +2897,7 @@ static int do_more_prompt(int typed_char)
// scroll up, display line at bottom
msg_scroll_up(true, false);
inc_msg_scrolled();
- grid_fill(&msg_grid_adj, Rows - 2, Rows - 1, 0, Columns, ' ', ' ',
- HL_ATTR(HLF_MSG));
+ grid_clear(&msg_grid_adj, Rows - 2, Rows - 1, 0, Columns, HL_ATTR(HLF_MSG));
mp_last = disp_sb_line(Rows - 2, mp_last);
toscroll--;
}
@@ -2871,8 +2905,7 @@ static int do_more_prompt(int typed_char)
if (toscroll <= 0) {
// displayed the requested text, more prompt again
- grid_fill(&msg_grid_adj, Rows - 1, Rows, 0, Columns, ' ', ' ',
- HL_ATTR(HLF_MSG));
+ grid_clear(&msg_grid_adj, Rows - 1, Rows, 0, Columns, HL_ATTR(HLF_MSG));
msg_moremsg(false);
continue;
}
@@ -2885,8 +2918,7 @@ static int do_more_prompt(int typed_char)
}
// clear the --more-- message
- grid_fill(&msg_grid_adj, Rows - 1, Rows, 0, Columns, ' ', ' ',
- HL_ATTR(HLF_MSG));
+ grid_clear(&msg_grid_adj, Rows - 1, Rows, 0, Columns, HL_ATTR(HLF_MSG));
redraw_cmdline = true;
clear_cmdline = false;
mode_displayed = false;
@@ -2902,41 +2934,7 @@ static int do_more_prompt(int typed_char)
return retval;
}
-#if defined(MSWIN)
-/// Headless (no UI) error message handler.
-static void do_msg(const char *str, bool errmsg)
-{
- static bool did_err = false;
- assert(str != NULL);
- wchar_t *utf16str;
- int r = utf8_to_utf16(str, -1, &utf16str);
- if (r != 0 && !did_err) {
- did_err = true;
- fprintf(stderr, "utf8_to_utf16 failed: %d", r);
- ELOG("utf8_to_utf16 failed: %d", r);
- } else if (r == 0) {
- if (errmsg) {
- fwprintf(stderr, L"%ls", utf16str);
- } else {
- wprintf(L"%ls", utf16str);
- }
- xfree(utf16str);
- }
-}
-
-void os_errmsg(const char *str)
-{
- do_msg(str, true);
-}
-
-/// Headless (no UI) message handler.
-void os_msg(const char *str)
-{
- do_msg(str, false);
-}
-#endif // MSWIN
-
-void msg_moremsg(int full)
+void msg_moremsg(bool full)
{
int attr = hl_combine_attr(HL_ATTR(HLF_MSG), HL_ATTR(HLF_M));
grid_line_start(&msg_grid_adj, Rows - 1);
@@ -3004,10 +3002,8 @@ void msg_clr_eos_force(void)
}
}
- grid_fill(&msg_grid_adj, msg_row, msg_row + 1, msg_startcol, msg_endcol,
- ' ', ' ', HL_ATTR(HLF_MSG));
- grid_fill(&msg_grid_adj, msg_row + 1, Rows, 0, Columns,
- ' ', ' ', HL_ATTR(HLF_MSG));
+ grid_clear(&msg_grid_adj, msg_row, msg_row + 1, msg_startcol, msg_endcol, HL_ATTR(HLF_MSG));
+ grid_clear(&msg_grid_adj, msg_row + 1, Rows, 0, Columns, HL_ATTR(HLF_MSG));
redraw_cmdline = true; // overwritten the command line
if (msg_row < Rows - 1 || msg_col == 0) {
@@ -3028,7 +3024,7 @@ void msg_clr_cmdline(void)
/// call wait_return() if the message does not fit in the available space
///
/// @return true if wait_return() not called.
-int msg_end(void)
+bool msg_end(void)
{
// If the string is larger than the window,
// or the ruler option is set and we run into it,
@@ -3056,7 +3052,7 @@ void msg_ext_ui_flush(void)
msg_ext_emit_chunk();
if (msg_ext_chunks.size > 0) {
- ui_call_msg_show(cstr_as_string((char *)msg_ext_kind),
+ ui_call_msg_show(cstr_as_string(msg_ext_kind),
msg_ext_chunks, msg_ext_overwrite);
if (!msg_ext_overwrite) {
msg_ext_visible++;
@@ -3102,9 +3098,7 @@ void msg_ext_clear_later(void)
{
if (msg_ext_is_visible()) {
msg_ext_need_clear = true;
- if (must_redraw < UPD_VALID) {
- must_redraw = UPD_VALID;
- }
+ set_must_redraw(UPD_VALID);
}
}
@@ -3394,7 +3388,6 @@ int do_dialog(int type, const char *title, const char *message, const char *butt
const char *textfield, int ex_cmd)
{
int retval = 0;
- char *hotkeys;
int i;
if (silent_mode // No dialogs in silent mode ("ex -s")
@@ -3413,7 +3406,7 @@ int do_dialog(int type, const char *title, const char *message, const char *butt
// Since we wait for a keypress, don't make the
// user press RETURN as well afterwards.
no_wait_return++;
- hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
+ char *hotkeys = msg_show_console_dialog(message, buttons, dfltbutton);
while (true) {
// Get a typed character directly from the user.
diff --git a/src/nvim/message.h b/src/nvim/message.h
index adbb40277b..c11c33c039 100644
--- a/src/nvim/message.h
+++ b/src/nvim/message.h
@@ -3,13 +3,11 @@
#include <errno.h>
#include <stdbool.h>
#include <stddef.h> // IWYU pragma: keep
-#include <stdio.h>
-#include "klib/kvec.h"
-#include "nvim/api/private/defs.h"
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/grid_defs.h"
#include "nvim/macros_defs.h"
+#include "nvim/message_defs.h" // IWYU pragma: keep
/// Types of dialogs passed to do_dialog().
enum {
@@ -30,25 +28,7 @@ enum {
VIM_DISCARDALL = 6,
};
-/// special attribute addition: Put message in history
-enum { MSG_HIST = 0x1000, };
-
-typedef struct {
- String text;
- int attr;
-} HlMessageChunk;
-
-typedef kvec_t(HlMessageChunk) HlMessage;
-
-/// Message history for `:messages`
-typedef struct msg_hist {
- struct msg_hist *next; ///< Next message.
- char *msg; ///< Message text.
- const char *kind; ///< Message kind (for msg_ext)
- int attr; ///< Message highlighting.
- bool multiline; ///< Multiline message.
- HlMessage multiattr; ///< multiattr message.
-} MessageHistoryEntry;
+enum { MSG_HIST = 0x1000, }; ///< special attribute addition: Put message in history
/// First message
extern MessageHistoryEntry *first_msg_hist;
@@ -84,10 +64,3 @@ EXTERN int msg_listdo_overwrite INIT( = 0);
// Prefer using semsg(), because perror() may send the output to the wrong
// destination and mess up the screen.
#define PERROR(msg) (void)semsg("%s: %s", (msg), strerror(errno))
-
-#ifndef MSWIN
-/// Headless (no UI) error message handler.
-# define os_errmsg(str) fprintf(stderr, "%s", (str))
-/// Headless (no UI) message handler.
-# define os_msg(str) printf("%s", (str))
-#endif
diff --git a/src/nvim/message_defs.h b/src/nvim/message_defs.h
new file mode 100644
index 0000000000..e60e60b3be
--- /dev/null
+++ b/src/nvim/message_defs.h
@@ -0,0 +1,22 @@
+#pragma once
+
+#include <stdbool.h>
+
+#include "nvim/api/private/defs.h"
+
+typedef struct {
+ String text;
+ int attr;
+} HlMessageChunk;
+
+typedef kvec_t(HlMessageChunk) HlMessage;
+
+/// Message history for `:messages`
+typedef struct msg_hist {
+ struct msg_hist *next; ///< Next message.
+ char *msg; ///< Message text.
+ const char *kind; ///< Message kind (for msg_ext)
+ int attr; ///< Message highlighting.
+ bool multiline; ///< Multiline message.
+ HlMessage multiattr; ///< multiattr message.
+} MessageHistoryEntry;
diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c
index 8fe3864424..506a428243 100644
--- a/src/nvim/mouse.c
+++ b/src/nvim/mouse.c
@@ -15,14 +15,15 @@
#include "nvim/eval/typval.h"
#include "nvim/ex_docmd.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
-#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/menu.h"
@@ -38,7 +39,9 @@
#include "nvim/pos_defs.h"
#include "nvim/search.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/statusline.h"
+#include "nvim/statusline_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
@@ -133,6 +136,26 @@ static void move_tab_to_mouse(void)
tabpage_move(tabnr);
}
}
+/// Close the current or specified tab page.
+///
+/// @param c1 tabpage number, or 999 for the current tabpage
+static void mouse_tab_close(int c1)
+{
+ tabpage_T *tp;
+
+ if (c1 == 999) {
+ tp = curtab;
+ } else {
+ tp = find_tabpage(c1);
+ }
+ if (tp == curtab) {
+ if (first_tabpage->tp_next != NULL) {
+ tabpage_close(false);
+ }
+ } else if (tp != NULL) {
+ tabpage_close_other(tp, false);
+ }
+}
static bool got_click = false; // got a click some time back
@@ -189,7 +212,7 @@ static void call_click_def_func(StlClickDefinition *click_defs, int col, int whi
}
};
typval_T rettv;
- (void)call_vim_function(click_defs[col].func, ARRAY_SIZE(argv), argv, &rettv);
+ call_vim_function(click_defs[col].func, ARRAY_SIZE(argv), argv, &rettv);
tv_clear(&rettv);
// Make sure next click does not register as drag when callback absorbs the release event.
got_click = false;
@@ -231,7 +254,7 @@ static int get_fpos_of_mouse(pos_T *mpos)
return IN_STATUS_LINE;
}
- if (winrow == -1 && wp->w_winbar_height != 0) {
+ if (winrow < 0 && winrow + wp->w_winbar_height >= 0) {
return MOUSE_WINBAR;
}
@@ -484,43 +507,32 @@ bool do_mouse(oparg_T *oap, int c, int dir, int count, bool fixindent)
if (is_click && cmdwin_type == 0 && mouse_col < Columns) {
in_tab_line = true;
c1 = tab_page_click_defs[mouse_col].tabnr;
+
switch (tab_page_click_defs[mouse_col].type) {
case kStlClickDisabled:
break;
- case kStlClickTabClose: {
- tabpage_T *tp;
-
- // Close the current or specified tab page.
- if (c1 == 999) {
- tp = curtab;
- } else {
- tp = find_tabpage(c1);
- }
- if (tp == curtab) {
- if (first_tabpage->tp_next != NULL) {
- tabpage_close(false);
- }
- } else if (tp != NULL) {
- tabpage_close_other(tp, false);
- }
- break;
- }
case kStlClickTabSwitch:
- if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) {
- // double click opens new page
- end_visual_mode();
- tabpage_new();
- tabpage_move(c1 == 0 ? 9999 : c1 - 1);
- } else {
- // Go to specified tab page, or next one if not clicking
- // on a label.
- goto_tabpage(c1);
-
- // It's like clicking on the status line of a window.
- if (curwin != old_curwin) {
+ if (which_button != MOUSE_MIDDLE) {
+ if ((mod_mask & MOD_MASK_MULTI_CLICK) == MOD_MASK_2CLICK) {
+ // double click opens new page
end_visual_mode();
+ tabpage_new();
+ tabpage_move(c1 == 0 ? 9999 : c1 - 1);
+ } else {
+ // Go to specified tab page, or next one if not clicking
+ // on a label.
+ goto_tabpage(c1);
+
+ // It's like clicking on the status line of a window.
+ if (curwin != old_curwin) {
+ end_visual_mode();
+ }
}
+ break;
}
+ FALLTHROUGH;
+ case kStlClickTabClose:
+ mouse_tab_close(c1);
break;
case kStlClickFuncRun:
call_click_def_func(tab_page_click_defs, mouse_col, which_button);
@@ -1012,7 +1024,7 @@ void do_mousescroll(cmdarg_T *cap)
// Vertical scrolling
if ((State & MODE_NORMAL) && shift_or_ctrl) {
// whole page up or down
- (void)onepage(cap->arg ? FORWARD : BACKWARD, 1);
+ onepage(cap->arg ? FORWARD : BACKWARD, 1);
} else {
if (shift_or_ctrl) {
// whole page up or down
@@ -1032,7 +1044,7 @@ void do_mousescroll(cmdarg_T *cap)
if (leftcol < 0) {
leftcol = 0;
}
- (void)do_mousescroll_horiz(leftcol);
+ do_mousescroll_horiz(leftcol);
}
}
@@ -1251,7 +1263,7 @@ retnomove:
bool below_window = grid == DEFAULT_GRID_HANDLE && row + wp->w_winbar_height >= wp->w_height;
on_status_line = below_window && row + wp->w_winbar_height - wp->w_height + 1 == 1;
on_sep_line = grid == DEFAULT_GRID_HANDLE && col >= wp->w_width && col - wp->w_width + 1 == 1;
- on_winbar = row == -1 && wp->w_winbar_height != 0;
+ on_winbar = row < 0 && row + wp->w_winbar_height >= 0;
on_statuscol = !below_window && !on_status_line && !on_sep_line && !on_winbar
&& *wp->w_p_stc != NUL
&& (wp->w_p_rl
@@ -1323,18 +1335,18 @@ retnomove:
&& !sep_line_offset
&& (wp->w_p_rl
? col < wp->w_width_inner - fdc
- : col >= fdc + (cmdwin_type == 0 && wp == curwin ? 0 : 1))
+ : col >= fdc + (wp != cmdwin_win ? 0 : 1))
&& (flags & MOUSE_MAY_STOP_VIS)))) {
end_visual_mode();
redraw_curbuf_later(UPD_INVERTED); // delete the inversion
}
- if (cmdwin_type != 0 && wp != curwin) {
+ if (cmdwin_type != 0 && wp != cmdwin_win) {
// A click outside the command-line window: Use modeless
// selection if possible. Allow dragging the status lines.
sep_line_offset = 0;
row = 0;
col += wp->w_wincol;
- wp = curwin;
+ wp = cmdwin_win;
}
// Only change window focus when not clicking on or dragging the
// status line. Do change focus when releasing the mouse button
@@ -1418,7 +1430,7 @@ retnomove:
break;
}
first = false;
- (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+ hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)) {
curwin->w_topfill++;
} else {
@@ -1568,9 +1580,6 @@ void nv_mousescroll(cmdarg_T *cap)
// Call the common mouse scroll function shared with other modes.
do_mousescroll(cap);
- if (curwin != old_curwin && curwin->w_p_cul) {
- redraw_for_cursorline(curwin);
- }
curwin->w_redr_status = true;
curwin = old_curwin;
curbuf = curwin->w_buffer;
@@ -1579,7 +1588,7 @@ void nv_mousescroll(cmdarg_T *cap)
/// Mouse clicks and drags.
void nv_mouse(cmdarg_T *cap)
{
- (void)do_mouse(cap->oap, cap->cmdchar, BACKWARD, cap->count1, 0);
+ do_mouse(cap->oap, cap->cmdchar, BACKWARD, cap->count1, 0);
}
/// Compute the position in the buffer line from the posn on the screen in
@@ -1628,7 +1637,7 @@ bool mouse_comp_pos(win_T *win, int *rowp, int *colp, linenr_T *lnump)
break; // Position is in this buffer line.
}
- (void)hasFoldingWin(win, lnum, NULL, &lnum, true, NULL);
+ hasFoldingWin(win, lnum, NULL, &lnum, true, NULL);
if (lnum == win->w_buffer->b_ml.ml_line_count) {
retval = true;
@@ -1722,7 +1731,7 @@ static win_T *mouse_find_grid_win(int *gridp, int *rowp, int *colp)
} else if (*gridp > 1) {
win_T *wp = get_win_by_grid_handle(*gridp);
if (wp && wp->w_grid_alloc.chars
- && !(wp->w_floating && !wp->w_float_config.focusable)) {
+ && !(wp->w_floating && !wp->w_config.focusable)) {
*rowp = MIN(*rowp - wp->w_grid.row_offset, wp->w_grid.rows - 1);
*colp = MIN(*colp - wp->w_grid.col_offset, wp->w_grid.cols - 1);
return wp;
@@ -1753,22 +1762,23 @@ colnr_T vcol2col(win_T *wp, linenr_T lnum, colnr_T vcol, colnr_T *coladdp)
{
// try to advance to the specified column
char *line = ml_get_buf(wp->w_buffer, lnum);
- chartabsize_T cts;
- init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
- while (cts.cts_vcol < vcol && *cts.cts_ptr != NUL) {
- int size = win_lbr_chartabsize(&cts, NULL);
- if (cts.cts_vcol + size > vcol) {
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, wp, lnum, line);
+ StrCharInfo ci = utf_ptr2StrCharInfo(line);
+ int cur_vcol = 0;
+ while (cur_vcol < vcol && *ci.ptr != NUL) {
+ int next_vcol = cur_vcol + win_charsize(cstype, cur_vcol, ci.ptr, ci.chr.value, &csarg).width;
+ if (next_vcol > vcol) {
break;
}
- cts.cts_vcol += size;
- MB_PTR_ADV(cts.cts_ptr);
+ cur_vcol = next_vcol;
+ ci = utfc_next(ci);
}
- clear_chartabsize_arg(&cts);
if (coladdp != NULL) {
- *coladdp = vcol - cts.cts_vcol;
+ *coladdp = vcol - cur_vcol;
}
- return (colnr_T)(cts.cts_ptr - line);
+ return (colnr_T)(ci.ptr - line);
}
/// Set UI mouse depending on current mode and 'mouse'.
@@ -1850,13 +1860,13 @@ static void mouse_check_grid(colnr_T *vcolp, int *flagsp)
int click_col = mouse_col;
// XXX: this doesn't change click_grid if it is 1, even with multigrid
- win_T *wp = mouse_find_win(&click_grid, &click_row, &click_col);
- // Only use vcols[] after the window was redrawn. Mainly matters
- // for tests, a user would not click before redrawing.
- if (wp == NULL || wp->w_redr_type != 0) {
+ if (mouse_find_win(&click_grid, &click_row, &click_col) != curwin
+ // Only use vcols[] after the window was redrawn. Mainly matters
+ // for tests, a user would not click before redrawing.
+ || curwin->w_redr_type != 0) {
return;
}
- ScreenGrid *gp = &wp->w_grid;
+ ScreenGrid *gp = &curwin->w_grid;
int start_row = 0;
int start_col = 0;
grid_adjust(&gp, &start_row, &start_col);
@@ -1892,12 +1902,12 @@ static void mouse_check_grid(colnr_T *vcolp, int *flagsp)
if (eol_vcol < 0) {
// Empty line or whole line before w_leftcol,
// with columns before buffer text
- eol_vcol = wp->w_leftcol - 1;
+ eol_vcol = curwin->w_leftcol - 1;
}
*vcolp = eol_vcol + (int)(off - off_r);
} else {
// Empty line or whole line before w_leftcol
- *vcolp = click_col - start_col + wp->w_leftcol;
+ *vcolp = click_col - start_col + curwin->w_leftcol;
}
} else if (col_from_screen >= 0) {
// Use the virtual column from vcols[], it is accurate also after
@@ -1941,7 +1951,7 @@ void f_getmousepos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
winrow = row + 1 + wp->w_winrow_off; // Adjust by 1 for top border
wincol = col + 1 + wp->w_wincol_off; // Adjust by 1 for left border
if (row >= 0 && row < wp->w_height && col >= 0 && col < wp->w_width) {
- (void)mouse_comp_pos(wp, &row, &col, &lnum);
+ mouse_comp_pos(wp, &row, &col, &lnum);
col = vcol2col(wp, lnum, col, &coladd);
column = col + 1;
}
diff --git a/src/nvim/mouse.h b/src/nvim/mouse.h
index 928b3e360b..2dcb3469da 100644
--- a/src/nvim/mouse.h
+++ b/src/nvim/mouse.h
@@ -1,10 +1,9 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/normal_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
-#include "nvim/vim_defs.h"
+#include "nvim/vim_defs.h" // IWYU pragma: keep
/// jump_to_mouse() returns one of first five these values, possibly with
/// some of the other five added.
diff --git a/src/nvim/move.c b/src/nvim/move.c
index 9ed3978490..551aa1bd4d 100644
--- a/src/nvim/move.c
+++ b/src/nvim/move.c
@@ -15,6 +15,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/cursor.h"
#include "nvim/diff.h"
#include "nvim/drawscreen.h"
@@ -22,14 +23,14 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/window.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/macros_defs.h"
-#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/message.h"
@@ -41,7 +42,6 @@
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
#include "nvim/search.h"
-#include "nvim/sign_defs.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
@@ -135,29 +135,55 @@ static void comp_botline(win_T *wp)
win_check_anchored_floats(wp);
}
-/// Redraw when w_virtcol changes and 'cursorcolumn' is set or 'cursorlineopt'
-/// contains "screenline" or when the "CurSearch" highlight is in use.
-/// Also when concealing is on and 'concealcursor' is active.
+/// Redraw when w_cline_row changes and 'relativenumber' or 'cursorline' is set.
+/// Also when concealing is on and 'concealcursor' is not active.
+static void redraw_for_cursorline(win_T *wp)
+ FUNC_ATTR_NONNULL_ALL
+{
+ if ((wp->w_valid & VALID_CROW) == 0 && !pum_visible()
+ && (wp->w_p_rnu || win_cursorline_standout(wp))) {
+ // win_line() will redraw the number column and cursorline only.
+ redraw_later(wp, UPD_VALID);
+ }
+}
+
+/// Redraw when w_virtcol changes and
+/// - 'cursorcolumn' is set, or
+/// - 'cursorlineopt' contains "screenline", or
+/// - "CurSearch" highlight is in use, or
+/// - 'concealcursor' is active, or
+/// - Visual mode is active.
static void redraw_for_cursorcolumn(win_T *wp)
FUNC_ATTR_NONNULL_ALL
{
- if ((wp->w_valid & VALID_VIRTCOL) == 0 && !pum_visible()) {
- if (wp->w_p_cuc
- || (win_hl_attr(wp, HLF_LC) != win_hl_attr(wp, HLF_L) && using_hlsearch())) {
- // When 'cursorcolumn' is set or "CurSearch" is in use
- // need to redraw with UPD_SOME_VALID.
- redraw_later(wp, UPD_SOME_VALID);
- } else if (wp->w_p_cul && (wp->w_p_culopt_flags & CULOPT_SCRLINE)) {
- // When 'cursorlineopt' contains "screenline" need to redraw with UPD_VALID.
- redraw_later(wp, UPD_VALID);
- }
+ if (wp->w_valid & VALID_VIRTCOL) {
+ return;
}
+
// If the cursor moves horizontally when 'concealcursor' is active, then the
- // current line needs to be redrawn in order to calculate the correct
- // cursor position.
- if ((wp->w_valid & VALID_VIRTCOL) == 0 && wp->w_p_cole > 0 && conceal_cursor_line(wp)) {
+ // current line needs to be redrawn to calculate the correct cursor position.
+ if (wp->w_p_cole > 0 && conceal_cursor_line(wp)) {
redrawWinline(wp, wp->w_cursor.lnum);
}
+
+ if (pum_visible()) {
+ return;
+ }
+
+ if (wp->w_p_cuc
+ || (win_hl_attr(wp, HLF_LC) != win_hl_attr(wp, HLF_L) && using_hlsearch())) {
+ // When 'cursorcolumn' is set or "CurSearch" is in use
+ // need to redraw with UPD_SOME_VALID.
+ redraw_later(wp, UPD_SOME_VALID);
+ } else if (wp->w_p_cul && (wp->w_p_culopt_flags & CULOPT_SCRLINE)) {
+ // When 'cursorlineopt' contains "screenline" need to redraw with UPD_VALID.
+ redraw_later(wp, UPD_VALID);
+ }
+
+ // When current buffer's cursor moves in Visual mode, redraw it with UPD_INVERTED.
+ if (VIsual_active && wp->w_buffer == curbuf) {
+ redraw_curbuf_later(UPD_INVERTED);
+ }
}
/// Calculates how much the 'listchars' "precedes" or 'smoothscroll' "<<<"
@@ -201,14 +227,16 @@ static int skipcol_from_plines(win_T *wp, int plines_off)
/// Set wp->w_skipcol to zero and redraw later if needed.
static void reset_skipcol(win_T *wp)
{
- if (wp->w_skipcol != 0) {
- wp->w_skipcol = 0;
-
- // Should use the least expensive way that displays all that changed.
- // UPD_NOT_VALID is too expensive, UPD_REDRAW_TOP does not redraw
- // enough when the top line gets another screen line.
- redraw_later(wp, UPD_SOME_VALID);
+ if (wp->w_skipcol == 0) {
+ return;
}
+
+ wp->w_skipcol = 0;
+
+ // Should use the least expensive way that displays all that changed.
+ // UPD_NOT_VALID is too expensive, UPD_REDRAW_TOP does not redraw
+ // enough when the top line gets another screen line.
+ redraw_later(wp, UPD_SOME_VALID);
}
// Update curwin->w_topline to move the cursor onto the screen.
@@ -304,7 +332,7 @@ void update_topline(win_T *wp)
if (lnum >= wp->w_buffer->b_ml.ml_line_count || n >= halfheight) {
break;
}
- (void)hasFoldingWin(wp, lnum, NULL, &lnum, true, NULL);
+ hasFoldingWin(wp, lnum, NULL, &lnum, true, NULL);
}
} else {
n = wp->w_topline + *so_ptr - wp->w_cursor.lnum;
@@ -321,7 +349,7 @@ void update_topline(win_T *wp)
}
} else {
// Make sure topline is the first line of a fold.
- (void)hasFoldingWin(wp, wp->w_topline, &wp->w_topline, NULL, true, NULL);
+ hasFoldingWin(wp, wp->w_topline, &wp->w_topline, NULL, true, NULL);
check_botline = true;
}
}
@@ -349,7 +377,7 @@ void update_topline(win_T *wp)
int n = wp->w_empty_rows;
loff.lnum = wp->w_cursor.lnum;
// In a fold go to its last line.
- (void)hasFoldingWin(wp, loff.lnum, NULL, &loff.lnum, true, NULL);
+ hasFoldingWin(wp, loff.lnum, NULL, &loff.lnum, true, NULL);
loff.fill = 0;
n += wp->w_filler_rows;
loff.height = 0;
@@ -383,7 +411,7 @@ void update_topline(win_T *wp)
if (lnum <= 0 || line_count > wp->w_height_inner + 1) {
break;
}
- (void)hasFolding(lnum, &lnum, NULL);
+ hasFolding(lnum, &lnum, NULL);
}
} else {
line_count = wp->w_cursor.lnum - wp->w_botline + 1 + (int)(*so_ptr);
@@ -527,7 +555,7 @@ void set_topline(win_T *wp, linenr_T lnum)
linenr_T prev_topline = wp->w_topline;
// go to first of folded lines
- (void)hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL);
+ hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL);
// Approximate the value of w_botline
wp->w_botline += lnum - wp->w_topline;
wp->w_topline = lnum;
@@ -567,19 +595,6 @@ void changed_line_abv_curs_win(win_T *wp)
|VALID_CHEIGHT|VALID_TOPLINE);
}
-/// Display of line has changed for "buf", invalidate cursor position and
-/// w_botline.
-void changed_line_display_buf(buf_T *buf)
-{
- FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer == buf) {
- wp->w_valid &= ~(VALID_WROW|VALID_WCOL|VALID_VIRTCOL
- |VALID_CROW|VALID_CHEIGHT
- |VALID_TOPLINE|VALID_BOTLINE|VALID_BOTLINE_AP);
- }
- }
-}
-
// Make sure the value of curwin->w_botline is valid.
void validate_botline(win_T *wp)
{
@@ -760,8 +775,8 @@ int win_col_off(win_T *wp)
{
return ((wp->w_p_nu || wp->w_p_rnu || *wp->w_p_stc != NUL)
? (number_width(wp) + (*wp->w_p_stc == NUL)) : 0)
- + ((cmdwin_type == 0 || wp != curwin) ? 0 : 1)
- + win_fdccol_count(wp) + (win_signcol_count(wp) * SIGN_WIDTH);
+ + ((wp != cmdwin_win) ? 0 : 1)
+ + win_fdccol_count(wp) + (wp->w_scwidth * SIGN_WIDTH);
}
int curwin_col_off(void)
@@ -1038,7 +1053,9 @@ void curs_columns(win_T *wp, int may_scroll)
void textpos2screenpos(win_T *wp, pos_T *pos, int *rowp, int *scolp, int *ccolp, int *ecolp,
bool local)
{
- colnr_T scol = 0, ccol = 0, ecol = 0;
+ colnr_T scol = 0;
+ colnr_T ccol = 0;
+ colnr_T ecol = 0;
int row = 0;
colnr_T coloff = 0;
bool visible_row = false;
@@ -1126,8 +1143,13 @@ void f_screenpos(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
semsg(_(e_invalid_line_number_nr), pos.lnum);
return;
}
+ if (pos.col < 0) {
+ pos.col = 0;
+ }
int row = 0;
- int scol = 0, ccol = 0, ecol = 0;
+ int scol = 0;
+ int ccol = 0;
+ int ecol = 0;
textpos2screenpos(wp, &pos, &row, &scol, &ccol, &ecol, false);
tv_dict_add_nr(dict, S_LEN("row"), row);
@@ -1202,7 +1224,7 @@ bool scrolldown(linenr_T line_count, int byfold)
}
// Make sure w_topline is at the first of a sequence of folded lines.
- (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+ hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
validate_cursor(); // w_wrow needs to be valid
for (int todo = line_count; todo > 0; todo--) {
if (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline)
@@ -1327,11 +1349,11 @@ bool scrolldown(linenr_T line_count, int byfold)
///
/// @param line_count number of lines to scroll
/// @param byfold if true, count a closed fold as one line
-bool scrollup(linenr_T line_count, int byfold)
+bool scrollup(linenr_T line_count, bool byfold)
{
linenr_T topline = curwin->w_topline;
linenr_T botline = curwin->w_botline;
- int do_sms = curwin->w_p_wrap && curwin->w_p_sms;
+ bool do_sms = curwin->w_p_wrap && curwin->w_p_sms;
if (do_sms || (byfold && hasAnyFolding(curwin)) || win_may_fill(curwin)) {
int width1 = curwin->w_width_inner - curwin_col_off();
@@ -1354,7 +1376,7 @@ bool scrollup(linenr_T line_count, int byfold)
linenr_T lnum = curwin->w_topline;
if (byfold) {
// for a closed fold: go to the last line in the fold
- (void)hasFolding(lnum, NULL, &lnum);
+ hasFolding(lnum, NULL, &lnum);
}
if (lnum == curwin->w_topline && do_sms) {
// 'smoothscroll': increase "w_skipcol" until it goes over
@@ -1410,7 +1432,7 @@ bool scrollup(linenr_T line_count, int byfold)
if (hasAnyFolding(curwin)) {
// Make sure w_topline is at the first of a sequence of folded lines.
- (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+ hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
}
curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE);
@@ -1572,7 +1594,7 @@ static void max_topfill(void)
// cursor off the screen.
void scrolldown_clamp(void)
{
- int can_fill = (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline));
+ bool can_fill = (curwin->w_topfill < win_get_fill(curwin, curwin->w_topline));
if (curwin->w_topline <= 1
&& !can_fill) {
@@ -1604,7 +1626,7 @@ void scrolldown_clamp(void)
curwin->w_topline--;
curwin->w_topfill = 0;
}
- (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+ hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
curwin->w_botline--; // approximate w_botline
curwin->w_valid &= ~(VALID_WROW|VALID_CROW|VALID_BOTLINE);
}
@@ -1635,7 +1657,7 @@ void scrollup_clamp(void)
if (curwin->w_topfill > 0) {
curwin->w_topfill--;
} else {
- (void)hasFolding(curwin->w_topline, NULL, &curwin->w_topline);
+ hasFolding(curwin->w_topline, NULL, &curwin->w_topline);
curwin->w_topline++;
}
curwin->w_botline++; // approximate w_botline
@@ -1864,7 +1886,7 @@ void set_empty_rows(win_T *wp, int used)
/// When scrolling scroll at least "min_scroll" lines.
/// If "set_topbot" is true, set topline and botline first (for "zb").
/// This is messy stuff!!!
-void scroll_cursor_bot(int min_scroll, int set_topbot)
+void scroll_cursor_bot(int min_scroll, bool set_topbot)
{
lineoff_T loff;
linenr_T old_topline = curwin->w_topline;
@@ -1874,7 +1896,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;
+ bool do_sms = curwin->w_p_wrap && curwin->w_p_sms;
if (set_topbot) {
bool set_skipcol = false;
@@ -2093,7 +2115,7 @@ void scroll_cursor_halfway(bool atend, bool prefer_above)
linenr_T old_topline = curwin->w_topline;
lineoff_T loff = { .lnum = curwin->w_cursor.lnum };
lineoff_T boff = { .lnum = curwin->w_cursor.lnum };
- (void)hasFolding(loff.lnum, &loff.lnum, &boff.lnum);
+ hasFolding(loff.lnum, &loff.lnum, &boff.lnum);
int used = plines_win_nofill(curwin, loff.lnum, true);
loff.fill = 0;
boff.fill = 0;
@@ -2439,7 +2461,7 @@ int onepage(Direction dir, int count)
botline_forw(curwin, &loff);
botline_topline(&loff);
// We're at the wrong end of a fold now.
- (void)hasFoldingWin(curwin, loff.lnum, &loff.lnum, NULL, true, NULL);
+ hasFoldingWin(curwin, loff.lnum, &loff.lnum, NULL, true, NULL);
// Always scroll at least one line. Avoid getting stuck on
// very long lines.
@@ -2486,10 +2508,10 @@ int onepage(Direction dir, int count)
if (curwin->w_topline <= old_topline
&& old_topline < curbuf->b_ml.ml_line_count) {
curwin->w_topline = old_topline + 1;
- (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+ hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
}
} else if (curwin->w_botline > curbuf->b_ml.ml_line_count) {
- (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+ hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
}
}
@@ -2588,7 +2610,7 @@ void halfpage(bool flag, linenr_T Prenum)
if (n < 0 && scrolled > 0) {
break;
}
- (void)hasFolding(curwin->w_topline, NULL, &curwin->w_topline);
+ hasFolding(curwin->w_topline, NULL, &curwin->w_topline);
curwin->w_topline++;
curwin->w_topfill = win_get_fill(curwin, curwin->w_topline);
@@ -2612,7 +2634,7 @@ void halfpage(bool flag, linenr_T Prenum)
if (i > room) {
break;
}
- (void)hasFolding(curwin->w_botline, NULL, &curwin->w_botline);
+ hasFolding(curwin->w_botline, NULL, &curwin->w_botline);
curwin->w_botline++;
room -= i;
} while (curwin->w_botline <= curbuf->b_ml.ml_line_count);
@@ -2624,8 +2646,8 @@ void halfpage(bool flag, linenr_T Prenum)
if (hasAnyFolding(curwin)) {
while (--n >= 0
&& curwin->w_cursor.lnum < curbuf->b_ml.ml_line_count) {
- (void)hasFolding(curwin->w_cursor.lnum, NULL,
- &curwin->w_cursor.lnum);
+ hasFolding(curwin->w_cursor.lnum, NULL,
+ &curwin->w_cursor.lnum);
curwin->w_cursor.lnum++;
}
} else {
@@ -2647,7 +2669,7 @@ void halfpage(bool flag, linenr_T Prenum)
break;
}
curwin->w_topline--;
- (void)hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
+ hasFolding(curwin->w_topline, &curwin->w_topline, NULL);
curwin->w_topfill = 0;
}
curwin->w_valid &= ~(VALID_CROW|VALID_WROW|
@@ -2666,8 +2688,8 @@ void halfpage(bool flag, linenr_T Prenum)
} else if (hasAnyFolding(curwin)) {
while (--n >= 0 && curwin->w_cursor.lnum > 1) {
curwin->w_cursor.lnum--;
- (void)hasFolding(curwin->w_cursor.lnum,
- &curwin->w_cursor.lnum, NULL);
+ hasFolding(curwin->w_cursor.lnum,
+ &curwin->w_cursor.lnum, NULL);
}
} else {
curwin->w_cursor.lnum -= n;
@@ -2697,7 +2719,7 @@ void do_check_cursorbind(void)
colnr_T col = curwin->w_cursor.col;
colnr_T coladd = curwin->w_cursor.coladd;
colnr_T curswant = curwin->w_curswant;
- int set_curswant = curwin->w_set_curswant;
+ bool set_curswant = curwin->w_set_curswant;
win_T *old_curwin = curwin;
buf_T *old_curbuf = curbuf;
int old_VIsual_select = VIsual_select;
diff --git a/src/nvim/move.h b/src/nvim/move.h
index ab8fb2b386..afeaeba235 100644
--- a/src/nvim/move.h
+++ b/src/nvim/move.h
@@ -1,11 +1,8 @@
#pragma once
-#include <stdbool.h>
-
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
-#include "nvim/vim_defs.h"
+#include "nvim/vim_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "move.h.generated.h"
diff --git a/src/nvim/msgpack_rpc/channel.c b/src/nvim/msgpack_rpc/channel.c
index 0fb1ebf931..a8fde5a652 100644
--- a/src/nvim/msgpack_rpc/channel.c
+++ b/src/nvim/msgpack_rpc/channel.c
@@ -1,7 +1,6 @@
#include <assert.h>
#include <inttypes.h>
#include <msgpack/object.h>
-#include <msgpack/pack.h>
#include <msgpack/sbuffer.h>
#include <msgpack/unpack.h>
#include <stdbool.h>
@@ -14,13 +13,13 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/ui.h"
#include "nvim/channel.h"
+#include "nvim/channel_defs.h"
#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/event/process.h"
#include "nvim/event/rstream.h"
-#include "nvim/event/stream.h"
#include "nvim/event/wstream.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/main.h"
@@ -29,10 +28,11 @@
#include "nvim/message.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/msgpack_rpc/channel_defs.h"
-#include "nvim/msgpack_rpc/helpers.h"
+#include "nvim/msgpack_rpc/packer.h"
#include "nvim/msgpack_rpc/unpacker.h"
#include "nvim/os/input.h"
#include "nvim/rbuffer.h"
+#include "nvim/rbuffer_defs.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/ui_client.h"
@@ -43,73 +43,31 @@
# define NOT "[notify] "
# define ERR "[error] "
-// Cannot define array with negative offsets, so this one is needed to be added
-// to MSGPACK_UNPACK_\* values.
-# define MUR_OFF 2
+# define SEND "->"
+# define RECV "<-"
-static const char *const msgpack_error_messages[] = {
- [MSGPACK_UNPACK_EXTRA_BYTES + MUR_OFF] = "extra bytes found",
- [MSGPACK_UNPACK_CONTINUE + MUR_OFF] = "incomplete string",
- [MSGPACK_UNPACK_PARSE_ERROR + MUR_OFF] = "parse error",
- [MSGPACK_UNPACK_NOMEM_ERROR + MUR_OFF] = "not enough memory",
-};
-
-static void log_close(FILE *f)
+static void log_request(char *dir, uint64_t channel_id, uint32_t req_id, const char *name)
{
- fputc('\n', f);
- fflush(f);
- fclose(f);
- log_unlock();
+ DLOGN("RPC %s %" PRIu64 ": %s id=%u: %s\n", dir, channel_id, REQ, req_id, name);
}
-static void log_server_msg(uint64_t channel_id, msgpack_sbuffer *packed)
+static void log_response(char *dir, uint64_t channel_id, char *kind, uint32_t req_id)
{
- msgpack_unpacked unpacked;
- msgpack_unpacked_init(&unpacked);
- DLOGN("RPC ->ch %" PRIu64 ": ", channel_id);
- const msgpack_unpack_return result =
- msgpack_unpack_next(&unpacked, packed->data, packed->size, NULL);
- switch (result) {
- case MSGPACK_UNPACK_SUCCESS: {
- uint64_t type = unpacked.data.via.array.ptr[0].via.u64;
- log_lock();
- FILE *f = open_log_file();
- fprintf(f, type ? (type == 1 ? RES : NOT) : REQ);
- msgpack_object_print(f, unpacked.data);
- log_close(f);
- msgpack_unpacked_destroy(&unpacked);
- break;
- }
- case MSGPACK_UNPACK_EXTRA_BYTES:
- case MSGPACK_UNPACK_CONTINUE:
- case MSGPACK_UNPACK_PARSE_ERROR:
- case MSGPACK_UNPACK_NOMEM_ERROR: {
- log_lock();
- FILE *f = open_log_file();
- fprintf(f, ERR);
- fprintf(f, "%s", msgpack_error_messages[result + MUR_OFF]);
- log_close(f);
- break;
- }
- }
+ DLOGN("RPC %s %" PRIu64 ": %s id=%u\n", dir, channel_id, kind, req_id);
}
-static void log_client_msg(uint64_t channel_id, bool is_request, const char *name)
+static void log_notify(char *dir, uint64_t channel_id, const char *name)
{
- DLOGN("RPC <-ch %" PRIu64 ": ", channel_id);
- log_lock();
- FILE *f = open_log_file();
- fprintf(f, "%s: %s", is_request ? REQ : RES, name);
- log_close(f);
+ DLOGN("RPC %s %" PRIu64 ": %s %s\n", dir, channel_id, NOT, name);
}
#else
-# define log_client_msg(...)
-# define log_server_msg(...)
+# define log_request(...)
+# define log_response(...)
+# define log_notify(...)
#endif
static Set(cstr_t) event_strings = SET_INIT;
-static msgpack_sbuffer out_buffer;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "msgpack_rpc/channel.c.generated.h"
@@ -118,7 +76,6 @@ static msgpack_sbuffer out_buffer;
void rpc_init(void)
{
ch_before_blocking_events = multiqueue_new_child(main_loop.events);
- msgpack_sbuffer_init(&out_buffer);
}
void rpc_start(Channel *channel)
@@ -168,8 +125,9 @@ bool rpc_send_event(uint64_t id, const char *name, Array args)
return false;
}
+ log_notify(SEND, channel ? channel->id : 0, name);
if (channel) {
- send_event(channel, name, args);
+ serialize_request(&channel, 1, 0, name, args);
} else {
broadcast_event(name, args);
}
@@ -191,7 +149,6 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem
if (!(channel = find_rpc_channel(id))) {
api_set_error(err, kErrorTypeException, "Invalid channel: %" PRIu64, id);
- api_free_array(args);
return NIL;
}
@@ -199,8 +156,9 @@ Object rpc_send_call(uint64_t id, const char *method_name, Array args, ArenaMem
RpcState *rpc = &channel->rpc;
uint32_t request_id = rpc->next_request_id++;
// Send the msgpack-rpc request
- send_request(channel, request_id, method_name, args);
- api_free_array(args);
+ serialize_request(&channel, 1, request_id, method_name, args);
+
+ log_request(SEND, channel->id, request_id, method_name);
// Push the frame
ChannelCallFrame frame = { request_id, false, false, NIL, NULL };
@@ -303,8 +261,11 @@ static void receive_msgpack(Stream *stream, RBuffer *rbuf, size_t c, void *data,
p->read_ptr = rbuffer_read_ptr(rbuf, &size);
p->read_size = size;
parse_msgpack(channel);
- size_t consumed = size - p->read_size;
- rbuffer_consumed_compact(rbuf, consumed);
+
+ if (!unpacker_closed(p)) {
+ size_t consumed = size - p->read_size;
+ rbuffer_consumed_compact(rbuf, consumed);
+ }
end:
channel_decref(channel);
@@ -359,8 +320,13 @@ static void parse_msgpack(Channel *channel)
frame->result = p->result;
}
frame->result_mem = arena_finish(&p->arena);
+ log_response(RECV, channel->id, frame->errored ? ERR : RES, p->request_id);
} else {
- log_client_msg(channel->id, p->type == kMessageTypeRequest, p->handler.name);
+ if (p->type == kMessageTypeNotification) {
+ log_notify(RECV, channel->id, p->handler.name);
+ } else {
+ log_request(RECV, channel->id, p->request_id, p->handler.name);
+ }
Object res = p->result;
if (p->result.type != kObjectTypeArray) {
@@ -405,7 +371,7 @@ static void handle_request(Channel *channel, Unpacker *p, Array args)
if (is_get_mode && !input_blocking()) {
// Defer the event to a special queue used by os/input.c. #6247
- multiqueue_put(ch_before_blocking_events, request_event, 1, evdata);
+ multiqueue_put(ch_before_blocking_events, request_event, evdata);
} else {
// Invoke immediately.
request_event((void **)&evdata);
@@ -413,12 +379,11 @@ static void handle_request(Channel *channel, Unpacker *p, Array args)
} else {
bool is_resize = p->handler.fn == handle_nvim_ui_try_resize;
if (is_resize) {
- Event ev = event_create_oneshot(event_create(request_event, 1, evdata),
- 2);
+ Event ev = event_create_oneshot(event_create(request_event, evdata), 2);
multiqueue_put_event(channel->events, ev);
multiqueue_put_event(resize_events, ev);
} else {
- multiqueue_put(channel->events, request_event, 1, evdata);
+ multiqueue_put(channel->events, request_event, evdata);
DLOG("RPC: scheduled %.*s", (int)p->method_name_len, p->handler.name);
}
}
@@ -441,17 +406,9 @@ static void request_event(void **argv)
Object result = handler.fn(channel->id, e->args, &e->used_mem, &error);
if (e->type == kMessageTypeRequest || ERROR_SET(&error)) {
// Send the response.
- msgpack_packer response;
- msgpack_packer_init(&response, &out_buffer, msgpack_sbuffer_write);
- channel_write(channel, serialize_response(channel->id,
- e->handler,
- e->type,
- e->request_id,
- &error,
- result,
- &out_buffer));
- }
- if (!handler.arena_return) {
+ serialize_response(channel, e->handler, e->type, e->request_id, &error, &result);
+ }
+ if (handler.ret_alloc) {
api_free_object(result);
}
@@ -485,7 +442,7 @@ static bool channel_write(Channel *channel, WBuffer *buffer)
if (channel->streamtype == kChannelStreamInternal) {
channel_incref(channel);
- CREATE_EVENT(channel->events, internal_read_event, 2, channel, buffer);
+ CREATE_EVENT(channel->events, internal_read_event, channel, buffer);
success = true;
} else {
Stream *in = channel_instream(channel);
@@ -532,41 +489,14 @@ static void send_error(Channel *chan, MsgpackRpcRequestHandler handler, MessageT
{
Error e = ERROR_INIT;
api_set_error(&e, kErrorTypeException, "%s", err);
- channel_write(chan, serialize_response(chan->id,
- handler,
- type,
- id,
- &e,
- NIL,
- &out_buffer));
+ serialize_response(chan, handler, type, id, &e, &NIL);
api_clear_error(&e);
}
-static void send_request(Channel *channel, uint32_t id, const char *name, Array args)
-{
- const String method = cstr_as_string((char *)name);
- channel_write(channel, serialize_request(channel->id,
- id,
- method,
- args,
- &out_buffer,
- 1));
-}
-
-static void send_event(Channel *channel, const char *name, Array args)
-{
- const String method = cstr_as_string((char *)name);
- channel_write(channel, serialize_request(channel->id,
- 0,
- method,
- args,
- &out_buffer,
- 1));
-}
-
static void broadcast_event(const char *name, Array args)
{
- kvec_t(Channel *) subscribed = KV_INITIAL_VALUE;
+ kvec_withinit_t(Channel *, 4) subscribed = KV_INITIAL_VALUE;
+ kvi_init(subscribed);
Channel *channel;
map_foreach_value(&channels, channel, {
@@ -576,25 +506,11 @@ static void broadcast_event(const char *name, Array args)
}
});
- if (!kv_size(subscribed)) {
- goto end;
- }
-
- const String method = cstr_as_string((char *)name);
- WBuffer *buffer = serialize_request(0,
- 0,
- method,
- args,
- &out_buffer,
- kv_size(subscribed));
-
- for (size_t i = 0; i < kv_size(subscribed); i++) {
- Channel *c = kv_A(subscribed, i);
- channel_write(c, buffer);
+ if (kv_size(subscribed)) {
+ serialize_request(subscribed.items, kv_size(subscribed), 0, name, args);
}
-end:
- kv_destroy(subscribed);
+ kvi_destroy(subscribed);
}
static void unsubscribe(Channel *channel, char *event)
@@ -652,27 +568,28 @@ static void chan_close_with_error(Channel *channel, char *msg, int loglevel)
channel_close(channel->id, kChannelPartRpc, NULL);
}
-static WBuffer *serialize_request(uint64_t channel_id, uint32_t request_id, const String method,
- Array args, msgpack_sbuffer *sbuffer, size_t refcount)
+static void serialize_request(Channel **chans, size_t nchans, uint32_t request_id,
+ const char *method, Array args)
{
- msgpack_packer pac;
- msgpack_packer_init(&pac, sbuffer, msgpack_sbuffer_write);
- msgpack_rpc_serialize_request(request_id, method, args, &pac);
- log_server_msg(channel_id, sbuffer);
- WBuffer *rv = wstream_new_buffer(xmemdup(sbuffer->data, sbuffer->size),
- sbuffer->size,
- refcount,
- xfree);
- msgpack_sbuffer_clear(sbuffer);
- return rv;
+ PackerBuffer packer;
+ packer_buffer_init_channels(chans, nchans, &packer);
+
+ mpack_array(&packer.ptr, request_id ? 4 : 3);
+ mpack_w(&packer.ptr, request_id ? 0 : 2);
+
+ if (request_id) {
+ mpack_uint(&packer.ptr, request_id);
+ }
+
+ mpack_str(cstr_as_string(method), &packer);
+ mpack_object_array(args, &packer);
+
+ packer_buffer_finish_channels(&packer);
}
-static WBuffer *serialize_response(uint64_t channel_id, MsgpackRpcRequestHandler handler,
- MessageType type, uint32_t response_id, Error *err, Object arg,
- msgpack_sbuffer *sbuffer)
+void serialize_response(Channel *channel, MsgpackRpcRequestHandler handler, MessageType type,
+ uint32_t response_id, Error *err, Object *arg)
{
- msgpack_packer pac;
- msgpack_packer_init(&pac, sbuffer, msgpack_sbuffer_write);
if (ERROR_SET(err) && type == kMessageTypeNotification) {
if (handler.fn == handle_nvim_paste) {
// TODO(bfredl): this is pretty much ad-hoc. maybe TUI and UI:s should be
@@ -681,23 +598,68 @@ static WBuffer *serialize_response(uint64_t channel_id, MsgpackRpcRequestHandler
semsg("paste: %s", err->msg);
api_clear_error(err);
} else {
- Array args = ARRAY_DICT_INIT;
- ADD(args, INTEGER_OBJ(err->type));
- ADD(args, CSTR_TO_OBJ(err->msg));
- msgpack_rpc_serialize_request(0, cstr_as_string("nvim_error_event"),
- args, &pac);
- api_free_array(args);
+ MAXSIZE_TEMP_ARRAY(args, 2);
+ ADD_C(args, INTEGER_OBJ(err->type));
+ ADD_C(args, CSTR_AS_OBJ(err->msg));
+ serialize_request(&channel, 1, 0, "nvim_error_event", args);
}
+ return;
+ }
+
+ PackerBuffer packer;
+ packer_buffer_init_channels(&channel, 1, &packer);
+
+ mpack_array(&packer.ptr, 4);
+ mpack_w(&packer.ptr, 1);
+ mpack_uint(&packer.ptr, response_id);
+
+ if (ERROR_SET(err)) {
+ // error represented by a [type, message] array
+ mpack_array(&packer.ptr, 2);
+ mpack_integer(&packer.ptr, err->type);
+ mpack_str(cstr_as_string(err->msg), &packer);
+ // Nil result
+ mpack_nil(&packer.ptr);
} else {
- msgpack_rpc_serialize_response(response_id, err, arg, &pac);
+ // Nil error
+ mpack_nil(&packer.ptr);
+ // Return value
+ mpack_object(arg, &packer);
}
- log_server_msg(channel_id, sbuffer);
- WBuffer *rv = wstream_new_buffer(xmemdup(sbuffer->data, sbuffer->size),
- sbuffer->size,
- 1, // responses only go though 1 channel
- xfree);
- msgpack_sbuffer_clear(sbuffer);
- return rv;
+
+ packer_buffer_finish_channels(&packer);
+
+ log_response(SEND, channel->id, ERROR_SET(err) ? ERR : RES, response_id);
+}
+
+static void packer_buffer_init_channels(Channel **chans, size_t nchans, PackerBuffer *packer)
+{
+ packer->startptr = alloc_block();
+ packer->ptr = packer->startptr;
+ packer->endptr = packer->startptr + ARENA_BLOCK_SIZE;
+ packer->packer_flush = channel_flush_callback;
+ packer->anydata = chans;
+ packer->anylen = nchans;
+}
+
+static void packer_buffer_finish_channels(PackerBuffer *packer)
+{
+ size_t len = (size_t)(packer->ptr - packer->startptr);
+ if (len > 0) {
+ WBuffer *buf = wstream_new_buffer(packer->startptr, len, packer->anylen, free_block);
+ Channel **chans = packer->anydata;
+ for (size_t i = 0; i < packer->anylen; i++) {
+ channel_write(chans[i], buf);
+ }
+ } else {
+ free_block(packer->startptr);
+ }
+}
+
+static void channel_flush_callback(PackerBuffer *packer)
+{
+ packer_buffer_finish_channels(packer);
+ packer_buffer_init_channels(packer->anydata, packer->anylen, packer);
}
void rpc_set_client_info(uint64_t id, Dictionary info)
@@ -753,6 +715,7 @@ const char *get_client_info(Channel *chan, const char *key)
return NULL;
}
+#ifdef EXITFREE
void rpc_free_all_mem(void)
{
cstr_t key;
@@ -760,4 +723,7 @@ void rpc_free_all_mem(void)
xfree((void *)key);
});
set_destroy(cstr_t, &event_strings);
+
+ multiqueue_free(ch_before_blocking_events);
}
+#endif
diff --git a/src/nvim/msgpack_rpc/channel.h b/src/nvim/msgpack_rpc/channel.h
index 818bee8318..ff73a2fc53 100644
--- a/src/nvim/msgpack_rpc/channel.h
+++ b/src/nvim/msgpack_rpc/channel.h
@@ -3,14 +3,10 @@
#include <stdint.h> // IWYU pragma: keep
#include "nvim/api/private/defs.h" // IWYU pragma: keep
-#include "nvim/channel.h"
-#include "nvim/event/multiqueue.h"
-#include "nvim/event/process.h"
-#include "nvim/event/socket.h"
-#include "nvim/event/wstream.h"
+#include "nvim/event/defs.h"
#include "nvim/macros_defs.h"
#include "nvim/memory_defs.h" // IWYU pragma: keep
-#include "nvim/msgpack_rpc/channel_defs.h" // IWYU pragma: export
+#include "nvim/msgpack_rpc/channel_defs.h" // IWYU pragma: keep
#define METHOD_MAXLEN 512
diff --git a/src/nvim/msgpack_rpc/channel_defs.h b/src/nvim/msgpack_rpc/channel_defs.h
index 20b8a89afb..56dbb332e0 100644
--- a/src/nvim/msgpack_rpc/channel_defs.h
+++ b/src/nvim/msgpack_rpc/channel_defs.h
@@ -4,11 +4,7 @@
#include <stdbool.h>
#include <uv.h>
-#include "klib/kvec.h"
-#include "nvim/api/private/defs.h"
#include "nvim/api/private/dispatch.h"
-#include "nvim/event/process.h"
-#include "nvim/event/socket.h"
#include "nvim/map_defs.h"
typedef struct Channel Channel;
diff --git a/src/nvim/msgpack_rpc/helpers.c b/src/nvim/msgpack_rpc/helpers.c
deleted file mode 100644
index 1fdfc9e536..0000000000
--- a/src/nvim/msgpack_rpc/helpers.c
+++ /dev/null
@@ -1,547 +0,0 @@
-#include <msgpack/object.h>
-#include <msgpack/sbuffer.h>
-#include <msgpack/unpack.h>
-#include <msgpack/zone.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include "klib/kvec.h"
-#include "msgpack/pack.h"
-#include "nvim/api/private/helpers.h"
-#include "nvim/assert_defs.h"
-#include "nvim/func_attr.h"
-#include "nvim/memory.h"
-#include "nvim/msgpack_rpc/helpers.h"
-#include "nvim/types_defs.h"
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "msgpack_rpc/helpers.c.generated.h"
-#endif
-
-static msgpack_zone zone;
-static msgpack_sbuffer sbuffer;
-
-void msgpack_rpc_helpers_init(void)
-{
- msgpack_zone_init(&zone, 0xfff);
- msgpack_sbuffer_init(&sbuffer);
-}
-
-typedef struct {
- const msgpack_object *mobj;
- Object *aobj;
- bool container;
- size_t idx;
-} MPToAPIObjectStackItem;
-
-// uncrustify:off
-
-/// Convert type used by msgpack parser to Nvim API type.
-///
-/// @param[in] obj Msgpack value to convert.
-/// @param[out] arg Location where result of conversion will be saved.
-///
-/// @return true in case of success, false otherwise.
-bool msgpack_rpc_to_object(const msgpack_object *const obj, Object *const arg)
- FUNC_ATTR_NONNULL_ALL
-{
- bool ret = true;
- kvec_withinit_t(MPToAPIObjectStackItem, 2) stack = KV_INITIAL_VALUE;
- kvi_init(stack);
- kvi_push(stack, ((MPToAPIObjectStackItem) {
- .mobj = obj,
- .aobj = arg,
- .container = false,
- .idx = 0,
- }));
- while (ret && kv_size(stack)) {
- MPToAPIObjectStackItem cur = kv_last(stack);
- if (!cur.container) {
- *cur.aobj = NIL;
- }
- switch (cur.mobj->type) {
- case MSGPACK_OBJECT_NIL:
- break;
- case MSGPACK_OBJECT_BOOLEAN:
- *cur.aobj = BOOLEAN_OBJ(cur.mobj->via.boolean);
- break;
- case MSGPACK_OBJECT_NEGATIVE_INTEGER:
- STATIC_ASSERT(sizeof(Integer) == sizeof(cur.mobj->via.i64),
- "Msgpack integer size does not match API integer");
- *cur.aobj = INTEGER_OBJ(cur.mobj->via.i64);
- break;
- case MSGPACK_OBJECT_POSITIVE_INTEGER:
- STATIC_ASSERT(sizeof(Integer) == sizeof(cur.mobj->via.u64),
- "Msgpack integer size does not match API integer");
- if (cur.mobj->via.u64 > API_INTEGER_MAX) {
- ret = false;
- } else {
- *cur.aobj = INTEGER_OBJ((Integer)cur.mobj->via.u64);
- }
- break;
- case MSGPACK_OBJECT_FLOAT32:
- case MSGPACK_OBJECT_FLOAT64:
- {
- STATIC_ASSERT(sizeof(Float) == sizeof(cur.mobj->via.f64),
- "Msgpack floating-point size does not match API integer");
- *cur.aobj = FLOAT_OBJ(cur.mobj->via.f64);
- break;
- }
-#define STR_CASE(type, attr, obj, dest, conv) \
- case type: { \
- dest = conv(((String) { \
- .size = obj->via.attr.size, \
- .data = (obj->via.attr.ptr == NULL || obj->via.attr.size == 0 \
- ? xmemdupz("", 0) \
- : xmemdupz(obj->via.attr.ptr, obj->via.attr.size)), })); \
- break; \
- }
- STR_CASE(MSGPACK_OBJECT_STR, str, cur.mobj, *cur.aobj, STRING_OBJ)
- STR_CASE(MSGPACK_OBJECT_BIN, bin, cur.mobj, *cur.aobj, STRING_OBJ)
- case MSGPACK_OBJECT_ARRAY: {
- const size_t size = cur.mobj->via.array.size;
- if (cur.container) {
- if (cur.idx >= size) {
- (void)kv_pop(stack);
- } else {
- const size_t idx = cur.idx;
- cur.idx++;
- kv_last(stack) = cur;
- kvi_push(stack, ((MPToAPIObjectStackItem) {
- .mobj = &cur.mobj->via.array.ptr[idx],
- .aobj = &cur.aobj->data.array.items[idx],
- .container = false,
- }));
- }
- } else {
- *cur.aobj = ARRAY_OBJ(((Array) {
- .size = size,
- .capacity = size,
- .items = (size > 0
- ? xcalloc(size, sizeof(*cur.aobj->data.array.items))
- : NULL),
- }));
- cur.container = true;
- kv_last(stack) = cur;
- }
- break;
- }
- case MSGPACK_OBJECT_MAP: {
- const size_t size = cur.mobj->via.map.size;
- if (cur.container) {
- if (cur.idx >= size) {
- (void)kv_pop(stack);
- } else {
- const size_t idx = cur.idx;
- cur.idx++;
- kv_last(stack) = cur;
- const msgpack_object *const key = &cur.mobj->via.map.ptr[idx].key;
- switch (key->type) {
-#define ID(x) x
- STR_CASE(MSGPACK_OBJECT_STR, str, key,
- cur.aobj->data.dictionary.items[idx].key, ID)
- STR_CASE(MSGPACK_OBJECT_BIN, bin, key,
- cur.aobj->data.dictionary.items[idx].key, ID)
-#undef ID
- case MSGPACK_OBJECT_NIL:
- case MSGPACK_OBJECT_BOOLEAN:
- case MSGPACK_OBJECT_POSITIVE_INTEGER:
- case MSGPACK_OBJECT_NEGATIVE_INTEGER:
- case MSGPACK_OBJECT_FLOAT32:
- case MSGPACK_OBJECT_FLOAT64:
- case MSGPACK_OBJECT_EXT:
- case MSGPACK_OBJECT_MAP:
- case MSGPACK_OBJECT_ARRAY:
- ret = false;
- break;
- }
- if (ret) {
- kvi_push(stack, ((MPToAPIObjectStackItem) {
- .mobj = &cur.mobj->via.map.ptr[idx].val,
- .aobj = &cur.aobj->data.dictionary.items[idx].value,
- .container = false,
- }));
- }
- }
- } else {
- *cur.aobj = DICTIONARY_OBJ(((Dictionary) {
- .size = size,
- .capacity = size,
- .items = (size > 0
- ? xcalloc(size, sizeof(*cur.aobj->data.dictionary.items))
- : NULL),
- }));
- cur.container = true;
- kv_last(stack) = cur;
- }
- break;
- }
- case MSGPACK_OBJECT_EXT:
- if (0 <= cur.mobj->via.ext.type && cur.mobj->via.ext.type <= EXT_OBJECT_TYPE_MAX) {
- cur.aobj->type = (ObjectType)(cur.mobj->via.ext.type + EXT_OBJECT_TYPE_SHIFT);
- msgpack_object data;
- msgpack_unpack_return status = msgpack_unpack(cur.mobj->via.ext.ptr, cur.mobj->via.ext.size,
- NULL, &zone, &data);
-
- if (status != MSGPACK_UNPACK_SUCCESS || data.type != MSGPACK_OBJECT_POSITIVE_INTEGER) {
- ret = false;
- break;
- }
- cur.aobj->data.integer = (handle_T)data.via.i64;
- ret = true;
- }
- break;
-#undef STR_CASE
- }
- if (!cur.container) {
- (void)kv_pop(stack);
- }
- }
- kvi_destroy(stack);
- return ret;
-}
-
-static bool msgpack_rpc_to_string(const msgpack_object *const obj, String *const arg)
- FUNC_ATTR_NONNULL_ALL
-{
- if (obj->type == MSGPACK_OBJECT_BIN || obj->type == MSGPACK_OBJECT_STR) {
- arg->data = obj->via.bin.ptr != NULL
- ? xmemdupz(obj->via.bin.ptr, obj->via.bin.size)
- : NULL;
- arg->size = obj->via.bin.size;
- return true;
- }
- return false;
-}
-
-bool msgpack_rpc_to_array(const msgpack_object *const obj, Array *const arg)
- FUNC_ATTR_NONNULL_ALL
-{
- if (obj->type != MSGPACK_OBJECT_ARRAY) {
- return false;
- }
-
- arg->size = obj->via.array.size;
- arg->items = xcalloc(obj->via.array.size, sizeof(Object));
-
- for (uint32_t i = 0; i < obj->via.array.size; i++) {
- if (!msgpack_rpc_to_object(obj->via.array.ptr + i, &arg->items[i])) {
- return false;
- }
- }
-
- return true;
-}
-
-bool msgpack_rpc_to_dictionary(const msgpack_object *const obj, Dictionary *const arg)
- FUNC_ATTR_NONNULL_ALL
-{
- if (obj->type != MSGPACK_OBJECT_MAP) {
- return false;
- }
-
- arg->size = obj->via.array.size;
- arg->items = xcalloc(obj->via.map.size, sizeof(KeyValuePair));
-
- for (uint32_t i = 0; i < obj->via.map.size; i++) {
- if (!msgpack_rpc_to_string(&obj->via.map.ptr[i].key,
- &arg->items[i].key)) {
- return false;
- }
-
- if (!msgpack_rpc_to_object(&obj->via.map.ptr[i].val,
- &arg->items[i].value)) {
- return false;
- }
- }
-
- return true;
-}
-
-void msgpack_rpc_from_boolean(Boolean result, msgpack_packer *res)
- FUNC_ATTR_NONNULL_ARG(2)
-{
- if (result) {
- msgpack_pack_true(res);
- } else {
- msgpack_pack_false(res);
- }
-}
-
-void msgpack_rpc_from_integer(Integer result, msgpack_packer *res)
- FUNC_ATTR_NONNULL_ARG(2)
-{
- msgpack_pack_int64(res, result);
-}
-
-void msgpack_rpc_from_float(Float result, msgpack_packer *res)
- FUNC_ATTR_NONNULL_ARG(2)
-{
- msgpack_pack_double(res, result);
-}
-
-void msgpack_rpc_from_string(const String result, msgpack_packer *res)
- FUNC_ATTR_NONNULL_ARG(2)
-{
- msgpack_pack_str(res, result.size);
- if (result.size > 0) {
- msgpack_pack_str_body(res, result.data, result.size);
- }
-}
-
-static void msgpack_rpc_from_handle(ObjectType type, Integer o, msgpack_packer *res)
- FUNC_ATTR_NONNULL_ARG(3)
-{
- msgpack_packer pac;
- msgpack_packer_init(&pac, &sbuffer, msgpack_sbuffer_write);
- msgpack_pack_int64(&pac, (handle_T)o);
- msgpack_pack_ext(res, sbuffer.size, (int8_t)(type - EXT_OBJECT_TYPE_SHIFT));
- msgpack_pack_ext_body(res, sbuffer.data, sbuffer.size);
- msgpack_sbuffer_clear(&sbuffer);
-}
-
-typedef struct {
- const Object *aobj;
- bool container;
- size_t idx;
-} APIToMPObjectStackItem;
-
-/// Convert type used by Nvim API to msgpack type.
-///
-/// @param[in] result Object to convert.
-/// @param[out] res Structure that defines where conversion results are saved.
-///
-/// @return true in case of success, false otherwise.
-void msgpack_rpc_from_object(const Object result, msgpack_packer *const res)
- FUNC_ATTR_NONNULL_ARG(2)
-{
- kvec_withinit_t(APIToMPObjectStackItem, 2) stack = KV_INITIAL_VALUE;
- kvi_init(stack);
- kvi_push(stack, ((APIToMPObjectStackItem) { &result, false, 0 }));
- while (kv_size(stack)) {
- APIToMPObjectStackItem cur = kv_last(stack);
- STATIC_ASSERT(kObjectTypeWindow == kObjectTypeBuffer + 1
- && kObjectTypeTabpage == kObjectTypeWindow + 1,
- "Buffer, window and tabpage enum items are in order");
- switch (cur.aobj->type) {
- case kObjectTypeNil:
- case kObjectTypeLuaRef:
- // TODO(bfredl): could also be an error. Though kObjectTypeLuaRef
- // should only appear when the caller has opted in to handle references,
- // see nlua_pop_Object.
- msgpack_pack_nil(res);
- break;
- case kObjectTypeBoolean:
- msgpack_rpc_from_boolean(cur.aobj->data.boolean, res);
- break;
- case kObjectTypeInteger:
- msgpack_rpc_from_integer(cur.aobj->data.integer, res);
- break;
- case kObjectTypeFloat:
- msgpack_rpc_from_float(cur.aobj->data.floating, res);
- break;
- case kObjectTypeString:
- msgpack_rpc_from_string(cur.aobj->data.string, res);
- break;
- case kObjectTypeBuffer:
- case kObjectTypeWindow:
- case kObjectTypeTabpage:
- msgpack_rpc_from_handle(cur.aobj->type, cur.aobj->data.integer, res);
- break;
- case kObjectTypeArray: {
- const size_t size = cur.aobj->data.array.size;
- if (cur.container) {
- if (cur.idx >= size) {
- (void)kv_pop(stack);
- } else {
- const size_t idx = cur.idx;
- cur.idx++;
- kv_last(stack) = cur;
- kvi_push(stack, ((APIToMPObjectStackItem) {
- .aobj = &cur.aobj->data.array.items[idx],
- .container = false,
- }));
- }
- } else {
- msgpack_pack_array(res, size);
- cur.container = true;
- kv_last(stack) = cur;
- }
- break;
- }
- case kObjectTypeDictionary: {
- const size_t size = cur.aobj->data.dictionary.size;
- if (cur.container) {
- if (cur.idx >= size) {
- (void)kv_pop(stack);
- } else {
- const size_t idx = cur.idx;
- cur.idx++;
- kv_last(stack) = cur;
- msgpack_rpc_from_string(cur.aobj->data.dictionary.items[idx].key, res);
- kvi_push(stack, ((APIToMPObjectStackItem) {
- .aobj = &cur.aobj->data.dictionary.items[idx].value,
- .container = false,
- }));
- }
- } else {
- msgpack_pack_map(res, size);
- cur.container = true;
- kv_last(stack) = cur;
- }
- break;
- }
- }
- if (!cur.container) {
- (void)kv_pop(stack);
- }
- }
- kvi_destroy(stack);
-}
-
-// uncrustify:on
-
-void msgpack_rpc_from_array(Array result, msgpack_packer *res)
- FUNC_ATTR_NONNULL_ARG(2)
-{
- msgpack_pack_array(res, result.size);
-
- for (size_t i = 0; i < result.size; i++) {
- msgpack_rpc_from_object(result.items[i], res);
- }
-}
-
-void msgpack_rpc_from_dictionary(Dictionary result, msgpack_packer *res)
- FUNC_ATTR_NONNULL_ARG(2)
-{
- msgpack_pack_map(res, result.size);
-
- for (size_t i = 0; i < result.size; i++) {
- msgpack_rpc_from_string(result.items[i].key, res);
- msgpack_rpc_from_object(result.items[i].value, res);
- }
-}
-
-/// Serializes a msgpack-rpc request or notification(id == 0)
-void msgpack_rpc_serialize_request(uint32_t request_id, const String method, Array args,
- msgpack_packer *pac)
- FUNC_ATTR_NONNULL_ARG(4)
-{
- msgpack_pack_array(pac, request_id ? 4 : 3);
- msgpack_pack_int(pac, request_id ? 0 : 2);
-
- if (request_id) {
- msgpack_pack_uint32(pac, request_id);
- }
-
- msgpack_rpc_from_string(method, pac);
- msgpack_rpc_from_array(args, pac);
-}
-
-/// Serializes a msgpack-rpc response
-void msgpack_rpc_serialize_response(uint32_t response_id, Error *err, Object arg,
- msgpack_packer *pac)
- FUNC_ATTR_NONNULL_ARG(2, 4)
-{
- msgpack_pack_array(pac, 4);
- msgpack_pack_int(pac, 1);
- msgpack_pack_uint32(pac, response_id);
-
- if (ERROR_SET(err)) {
- // error represented by a [type, message] array
- msgpack_pack_array(pac, 2);
- msgpack_rpc_from_integer(err->type, pac);
- msgpack_rpc_from_string(cstr_as_string(err->msg), pac);
- // Nil result
- msgpack_pack_nil(pac);
- } else {
- // Nil error
- msgpack_pack_nil(pac);
- // Return value
- msgpack_rpc_from_object(arg, pac);
- }
-}
-
-static bool msgpack_rpc_is_notification(msgpack_object *req)
-{
- return req->via.array.ptr[0].via.u64 == 2;
-}
-
-msgpack_object *msgpack_rpc_method(msgpack_object *req)
-{
- msgpack_object *obj = req->via.array.ptr
- + (msgpack_rpc_is_notification(req) ? 1 : 2);
- return obj->type == MSGPACK_OBJECT_STR || obj->type == MSGPACK_OBJECT_BIN
- ? obj : NULL;
-}
-
-msgpack_object *msgpack_rpc_args(msgpack_object *req)
-{
- msgpack_object *obj = req->via.array.ptr
- + (msgpack_rpc_is_notification(req) ? 2 : 3);
- return obj->type == MSGPACK_OBJECT_ARRAY ? obj : NULL;
-}
-
-static msgpack_object *msgpack_rpc_msg_id(msgpack_object *req)
-{
- if (msgpack_rpc_is_notification(req)) {
- return NULL;
- }
- msgpack_object *obj = &req->via.array.ptr[1];
- return obj->type == MSGPACK_OBJECT_POSITIVE_INTEGER ? obj : NULL;
-}
-
-MessageType msgpack_rpc_validate(uint32_t *response_id, msgpack_object *req, Error *err)
-{
- *response_id = 0;
- // Validate the basic structure of the msgpack-rpc payload
- if (req->type != MSGPACK_OBJECT_ARRAY) {
- api_set_error(err, kErrorTypeValidation, "Message is not an array");
- return kMessageTypeUnknown;
- }
-
- if (req->via.array.size == 0) {
- api_set_error(err, kErrorTypeValidation, "Message is empty");
- return kMessageTypeUnknown;
- }
-
- if (req->via.array.ptr[0].type != MSGPACK_OBJECT_POSITIVE_INTEGER) {
- api_set_error(err, kErrorTypeValidation, "Message type must be an integer");
- return kMessageTypeUnknown;
- }
-
- MessageType type = (MessageType)req->via.array.ptr[0].via.u64;
- if (type != kMessageTypeRequest && type != kMessageTypeNotification) {
- api_set_error(err, kErrorTypeValidation, "Unknown message type");
- return kMessageTypeUnknown;
- }
-
- if ((type == kMessageTypeRequest && req->via.array.size != 4)
- || (type == kMessageTypeNotification && req->via.array.size != 3)) {
- api_set_error(err, kErrorTypeValidation,
- "Request array size must be 4 (request) or 3 (notification)");
- return type;
- }
-
- if (type == kMessageTypeRequest) {
- msgpack_object *id_obj = msgpack_rpc_msg_id(req);
- if (!id_obj) {
- api_set_error(err, kErrorTypeValidation, "ID must be a positive integer");
- return type;
- }
- *response_id = (uint32_t)id_obj->via.u64;
- }
-
- if (!msgpack_rpc_method(req)) {
- api_set_error(err, kErrorTypeValidation, "Method must be a string");
- return type;
- }
-
- if (!msgpack_rpc_args(req)) {
- api_set_error(err, kErrorTypeValidation, "Parameters must be an array");
- return type;
- }
-
- return type;
-}
diff --git a/src/nvim/msgpack_rpc/helpers.h b/src/nvim/msgpack_rpc/helpers.h
deleted file mode 100644
index dd2096f305..0000000000
--- a/src/nvim/msgpack_rpc/helpers.h
+++ /dev/null
@@ -1,20 +0,0 @@
-#pragma once
-
-#include <msgpack.h>
-#include <stdbool.h>
-#include <stdint.h>
-
-#include "nvim/api/private/defs.h"
-#include "nvim/event/wstream.h"
-
-/// Value by which objects represented as EXT type are shifted
-///
-/// Subtracted when packing, added when unpacking. Used to allow moving
-/// buffer/window/tabpage block inside ObjectType enum. This block yet cannot be
-/// split or reordered.
-#define EXT_OBJECT_TYPE_SHIFT kObjectTypeBuffer
-#define EXT_OBJECT_TYPE_MAX (kObjectTypeTabpage - EXT_OBJECT_TYPE_SHIFT)
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "msgpack_rpc/helpers.h.generated.h"
-#endif
diff --git a/src/nvim/msgpack_rpc/packer.c b/src/nvim/msgpack_rpc/packer.c
new file mode 100644
index 0000000000..cac68f76f0
--- /dev/null
+++ b/src/nvim/msgpack_rpc/packer.c
@@ -0,0 +1,235 @@
+#include <assert.h>
+
+#include "nvim/api/private/defs.h"
+#include "nvim/lua/executor.h"
+#include "nvim/msgpack_rpc/packer.h"
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "msgpack_rpc/packer.c.generated.h"
+#endif
+
+static void check_buffer(PackerBuffer *packer)
+{
+ ptrdiff_t remaining = packer->endptr - packer->ptr;
+ if (remaining < MPACK_ITEM_SIZE) {
+ packer->packer_flush(packer);
+ }
+}
+
+static void mpack_w8(char **b, const char *data)
+{
+#ifdef ORDER_BIG_ENDIAN
+ memcpy(*b, data, 8);
+ *b += 8;
+#else
+ for (int i = 7; i >= 0; i--) {
+ *(*b)++ = data[i];
+ }
+#endif
+}
+
+void mpack_integer(char **ptr, Integer i)
+{
+ if (i >= 0) {
+ if (i > 0xfffffff) {
+ mpack_w(ptr, 0xcf);
+ mpack_w8(ptr, (char *)&i);
+ } else {
+ mpack_uint(ptr, (uint32_t)i);
+ }
+ } else {
+ if (i < -0x80000000LL) {
+ mpack_w(ptr, 0xd3);
+ mpack_w8(ptr, (char *)&i);
+ } else if (i < -0x8000) {
+ mpack_w(ptr, 0xd2);
+ mpack_w4(ptr, (uint32_t)i);
+ } else if (i < -0x80) {
+ mpack_w(ptr, 0xd1);
+ mpack_w2(ptr, (uint32_t)i);
+ } else if (i < -0x20) {
+ mpack_w(ptr, 0xd0);
+ mpack_w(ptr, (char)i);
+ } else {
+ mpack_w(ptr, (char)i);
+ }
+ }
+}
+
+void mpack_float8(char **ptr, double i)
+{
+ mpack_w(ptr, 0xcb);
+ mpack_w8(ptr, (char *)&i);
+}
+
+void mpack_str(String str, PackerBuffer *packer)
+{
+ const size_t len = str.size;
+ if (len < 20) {
+ mpack_w(&packer->ptr, 0xa0 | len);
+ } else if (len < 0xff) {
+ mpack_w(&packer->ptr, 0xd9);
+ mpack_w(&packer->ptr, len);
+ } else if (len < 0xffff) {
+ mpack_w(&packer->ptr, 0xda);
+ mpack_w2(&packer->ptr, (uint32_t)len);
+ } else if (len < 0xffffffff) {
+ mpack_w(&packer->ptr, 0xdb);
+ mpack_w4(&packer->ptr, (uint32_t)len);
+ } else {
+ abort();
+ }
+
+ size_t pos = 0;
+ while (pos < len) {
+ ptrdiff_t remaining = packer->endptr - packer->ptr;
+ size_t to_copy = MIN(len - pos, (size_t)remaining);
+ memcpy(packer->ptr, str.data + pos, to_copy);
+ packer->ptr += to_copy;
+ pos += to_copy;
+
+ if (pos < len) {
+ packer->packer_flush(packer);
+ }
+ }
+}
+
+void mpack_handle(ObjectType type, handle_T handle, PackerBuffer *packer)
+{
+ char exttype = (char)(type - EXT_OBJECT_TYPE_SHIFT);
+ if (-0x1f <= handle && handle <= 0x7f) {
+ mpack_w(&packer->ptr, 0xd4);
+ mpack_w(&packer->ptr, exttype);
+ mpack_w(&packer->ptr, (char)handle);
+ } else {
+ // we want to encode some small negative sentinel like -1. This is handled above
+ assert(handle >= 0);
+ // FAIL: we cannot use fixext 4/8 due to a design error
+ // (in theory fixext 2 for handle<=0xff but we don't gain much from it)
+ char buf[MPACK_ITEM_SIZE];
+ char *pos = buf;
+ mpack_uint(&pos, (uint32_t)handle);
+ ptrdiff_t packsize = pos - buf;
+ mpack_w(&packer->ptr, 0xc7);
+ mpack_w(&packer->ptr, packsize);
+ mpack_w(&packer->ptr, exttype);
+ // check_buffer(packer);
+ memcpy(packer->ptr, buf, (size_t)packsize);
+ packer->ptr += packsize;
+ }
+}
+
+void mpack_object(Object *obj, PackerBuffer *packer)
+{
+ mpack_object_inner(obj, NULL, 0, packer);
+}
+
+void mpack_object_array(Array arr, PackerBuffer *packer)
+{
+ mpack_array(&packer->ptr, (uint32_t)arr.size);
+ if (arr.size > 0) {
+ Object container = ARRAY_OBJ(arr);
+ mpack_object_inner(&arr.items[0], arr.size > 1 ? &container : NULL, 1, packer);
+ }
+}
+
+typedef struct {
+ Object *container;
+ size_t idx;
+} ContainerStackItem;
+
+void mpack_object_inner(Object *current, Object *container, size_t container_idx,
+ PackerBuffer *packer)
+ FUNC_ATTR_NONNULL_ARG(1, 4)
+{
+ // The inner loop of this function packs "current" and then fetches the next
+ // value from "container". "stack" is only used for nested containers.
+ kvec_withinit_t(ContainerStackItem, 2) stack = KV_INITIAL_VALUE;
+ kvi_init(stack);
+
+ while (true) {
+ check_buffer(packer);
+ switch (current->type) {
+ case kObjectTypeLuaRef:
+ // TODO(bfredl): could also be an error. Though kObjectTypeLuaRef
+ // should only appear when the caller has opted in to handle references,
+ // see nlua_pop_Object.
+ api_free_luaref(current->data.luaref);
+ current->data.luaref = LUA_NOREF;
+ FALLTHROUGH;
+ case kObjectTypeNil:
+ mpack_nil(&packer->ptr);
+ break;
+ case kObjectTypeBoolean:
+ mpack_bool(&packer->ptr, current->data.boolean);
+ break;
+ case kObjectTypeInteger:
+ mpack_integer(&packer->ptr, current->data.integer);
+ break;
+ case kObjectTypeFloat:
+ mpack_float8(&packer->ptr, current->data.floating);
+ break;
+ case kObjectTypeString:
+ mpack_str(current->data.string, packer);
+ break;
+ case kObjectTypeBuffer:
+ case kObjectTypeWindow:
+ case kObjectTypeTabpage:
+ mpack_handle(current->type, (handle_T)current->data.integer, packer);
+ break;
+ case kObjectTypeDictionary:
+ case kObjectTypeArray: {}
+ size_t current_size;
+ if (current->type == kObjectTypeArray) {
+ current_size = current->data.array.size;
+ mpack_array(&packer->ptr, (uint32_t)current_size);
+ } else {
+ current_size = current->data.dictionary.size;
+ mpack_map(&packer->ptr, (uint32_t)current_size);
+ }
+ if (current_size > 0) {
+ if (current->type == kObjectTypeArray && current_size == 1) {
+ current = &current->data.array.items[0];
+ continue;
+ }
+ if (container) {
+ kvi_push(stack, ((ContainerStackItem) {
+ .container = container,
+ .idx = container_idx,
+ }));
+ }
+ container = current;
+ container_idx = 0;
+ }
+ break;
+ }
+
+ if (!container) {
+ if (kv_size(stack)) {
+ ContainerStackItem it = kv_pop(stack);
+ container = it.container;
+ container_idx = it.idx;
+ } else {
+ break;
+ }
+ }
+
+ if (container->type == kObjectTypeArray) {
+ Array arr = container->data.array;
+ current = &arr.items[container_idx++];
+ if (container_idx >= arr.size) {
+ container = NULL;
+ }
+ } else {
+ Dictionary dict = container->data.dictionary;
+ KeyValuePair *it = &dict.items[container_idx++];
+ check_buffer(packer);
+ mpack_str(it->key, packer);
+ current = &it->value;
+ if (container_idx >= dict.size) {
+ container = NULL;
+ }
+ }
+ }
+ kvi_destroy(stack);
+}
diff --git a/src/nvim/msgpack_rpc/packer.h b/src/nvim/msgpack_rpc/packer.h
new file mode 100644
index 0000000000..8117bd09bd
--- /dev/null
+++ b/src/nvim/msgpack_rpc/packer.h
@@ -0,0 +1,76 @@
+#pragma once
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <string.h>
+
+#include "nvim/api/private/defs.h"
+#include "nvim/msgpack_rpc/packer_defs.h"
+
+#define mpack_w(b, byte) *(*(b))++ = (char)(byte);
+static inline void mpack_w2(char **b, uint32_t v)
+{
+ *(*b)++ = (char)((v >> 8) & 0xff);
+ *(*b)++ = (char)(v & 0xff);
+}
+
+static inline void mpack_w4(char **b, uint32_t v)
+{
+ *(*b)++ = (char)((v >> 24) & 0xff);
+ *(*b)++ = (char)((v >> 16) & 0xff);
+ *(*b)++ = (char)((v >> 8) & 0xff);
+ *(*b)++ = (char)(v & 0xff);
+}
+
+static inline void mpack_uint(char **buf, uint32_t val)
+{
+ if (val > 0xffff) {
+ mpack_w(buf, 0xce);
+ mpack_w4(buf, val);
+ } else if (val > 0xff) {
+ mpack_w(buf, 0xcd);
+ mpack_w2(buf, val);
+ } else if (val > 0x7f) {
+ mpack_w(buf, 0xcc);
+ mpack_w(buf, val);
+ } else {
+ mpack_w(buf, val);
+ }
+}
+
+#define mpack_nil(buf) mpack_w(buf, 0xc0)
+static inline void mpack_bool(char **buf, bool val)
+{
+ mpack_w(buf, 0xc2 | (val ? 1 : 0));
+}
+
+static inline void mpack_array(char **buf, uint32_t len)
+{
+ if (len < 0x10) {
+ mpack_w(buf, 0x90 | len);
+ } else if (len < 0x10000) {
+ mpack_w(buf, 0xdc);
+ mpack_w2(buf, len);
+ } else {
+ mpack_w(buf, 0xdd);
+ mpack_w4(buf, len);
+ }
+}
+
+static inline void mpack_map(char **buf, uint32_t len)
+{
+ if (len < 0x10) {
+ mpack_w(buf, 0x80 | len);
+ } else if (len < 0x10000) {
+ mpack_w(buf, 0xde);
+ mpack_w2(buf, len);
+ } else {
+ mpack_w(buf, 0xdf);
+ mpack_w4(buf, len);
+ }
+}
+
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "msgpack_rpc/packer.h.generated.h"
+#endif
diff --git a/src/nvim/msgpack_rpc/packer_defs.h b/src/nvim/msgpack_rpc/packer_defs.h
new file mode 100644
index 0000000000..420f3dc424
--- /dev/null
+++ b/src/nvim/msgpack_rpc/packer_defs.h
@@ -0,0 +1,24 @@
+#pragma once
+
+#include <stddef.h>
+#include <stdint.h>
+
+// Max possible length: bytecode + 8 int/float bytes
+// Ext objects are maximum 8=3+5 (nested uint32 payload)
+#define MPACK_ITEM_SIZE 9
+
+typedef struct packer_buffer_t PackerBuffer;
+
+// Must ensure at least MPACK_ITEM_SIZE of space.
+typedef void (*PackerBufferFlush)(PackerBuffer *self);
+
+struct packer_buffer_t {
+ char *startptr;
+ char *ptr;
+ char *endptr;
+
+ // these are free to be used by packer_flush for any purpose, if want
+ void *anydata;
+ size_t anylen;
+ PackerBufferFlush packer_flush;
+};
diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c
index f3627eaa61..56b03d67d0 100644
--- a/src/nvim/msgpack_rpc/server.c
+++ b/src/nvim/msgpack_rpc/server.c
@@ -6,9 +6,10 @@
#include "nvim/channel.h"
#include "nvim/eval.h"
+#include "nvim/event/defs.h"
#include "nvim/event/socket.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/memory.h"
diff --git a/src/nvim/msgpack_rpc/unpacker.c b/src/nvim/msgpack_rpc/unpacker.c
index 38263381bf..dbb30b0c9a 100644
--- a/src/nvim/msgpack_rpc/unpacker.c
+++ b/src/nvim/msgpack_rpc/unpacker.c
@@ -10,7 +10,6 @@
#include "nvim/macros_defs.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/channel_defs.h"
-#include "nvim/msgpack_rpc/helpers.h"
#include "nvim/msgpack_rpc/unpacker.h"
#include "nvim/ui_client.h"
@@ -18,15 +17,18 @@
# include "msgpack_rpc/unpacker.c.generated.h"
#endif
-Object unpack(const char *data, size_t size, Error *err)
+Object unpack(const char *data, size_t size, Arena *arena, Error *err)
{
Unpacker unpacker;
mpack_parser_init(&unpacker.parser, 0);
unpacker.parser.data.p = &unpacker;
+ unpacker.arena = *arena;
int result = mpack_parse(&unpacker.parser, &data, &size,
api_parse_enter, api_parse_exit);
+ *arena = unpacker.arena;
+
if (result == MPACK_NOMEM) {
api_set_error(err, kErrorTypeException, "object was too deep to unpack");
} else if (result == MPACK_EOF) {
diff --git a/src/nvim/msgpack_rpc/unpacker.h b/src/nvim/msgpack_rpc/unpacker.h
index 53af29761e..022d778013 100644
--- a/src/nvim/msgpack_rpc/unpacker.h
+++ b/src/nvim/msgpack_rpc/unpacker.h
@@ -1,19 +1,17 @@
#pragma once
#include <inttypes.h>
-#include <stdbool.h>
#include <string.h>
#include "mpack/mpack_core.h"
#include "mpack/object.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/dispatch.h"
-#include "nvim/api/private/helpers.h"
#include "nvim/grid_defs.h"
#include "nvim/memory_defs.h"
-#include "nvim/msgpack_rpc/channel_defs.h"
+#include "nvim/msgpack_rpc/channel_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h"
-#include "nvim/ui_client.h"
+#include "nvim/ui_defs.h"
struct Unpacker {
mpack_parser_t parser;
diff --git a/src/nvim/normal.c b/src/nvim/normal.c
index 1f789dc153..8ff47097fa 100644
--- a/src/nvim/normal.c
+++ b/src/nvim/normal.c
@@ -17,6 +17,7 @@
#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/change.h"
@@ -34,19 +35,21 @@
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/help.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
#include "nvim/mapping.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
@@ -62,21 +65,25 @@
#include "nvim/quickfix.h"
#include "nvim/search.h"
#include "nvim/spell.h"
+#include "nvim/spell_defs.h"
#include "nvim/spellfile.h"
#include "nvim/spellsuggest.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
#include "nvim/tag.h"
#include "nvim/textformat.h"
#include "nvim/textobject.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
-typedef struct normal_state {
+typedef struct {
VimState state;
bool command_finished;
bool ctrl_w;
@@ -368,7 +375,7 @@ static int nv_compare(const void *s1, const void *s2)
if (c2 < 0) {
c2 = -c2;
}
- return c1 - c2;
+ return c1 == c2 ? 0 : c1 > c2 ? 1 : -1;
}
/// Initialize the nv_cmd_idx[] table.
@@ -703,7 +710,7 @@ static void normal_get_additional_char(NormalState *s)
int *cp;
bool repl = false; // get character for replace mode
bool lit = false; // get extra character literally
- int lang; // getting a text character
+ bool lang; // getting a text character
no_mapping++;
allow_keys++; // no mapping for nchar, but allow key codes
@@ -838,10 +845,10 @@ static void normal_get_additional_char(NormalState *s)
no_mapping++;
// Vim may be in a different mode when the user types the next key,
// but when replaying a recording the next key is already in the
- // typeahead buffer, so record a <Nop> before that to prevent the
- // vpeekc() above from applying wrong mappings when replaying.
+ // typeahead buffer, so record an <Ignore> before that to prevent
+ // the vpeekc() above from applying wrong mappings when replaying.
no_u_sync++;
- gotchars_nop();
+ gotchars_ignore();
no_u_sync--;
}
}
@@ -1028,7 +1035,7 @@ normal_end:
restart_VIsual_select = 0;
}
if (restart_edit != 0 && !VIsual_active && s->old_mapped_len == 0) {
- (void)edit(restart_edit, false, 1);
+ edit(restart_edit, false, 1);
}
}
@@ -1257,7 +1264,7 @@ static void normal_check_interrupt(NormalState *s)
} else if (!global_busy || !exmode_active) {
if (!quit_more) {
// flush all buffers
- (void)vgetc();
+ vgetc();
}
got_int = false;
}
@@ -1340,10 +1347,6 @@ static void normal_redraw(NormalState *s)
show_cursor_info_later(false);
- if (VIsual_active) {
- redraw_curbuf_later(UPD_INVERTED); // update inverted part
- }
-
if (must_redraw) {
update_screen();
} else {
@@ -1448,9 +1451,7 @@ static int normal_check(VimState *state)
// has been done, close any file for startup messages.
if (time_fd != NULL) {
TIME_MSG("first screen update");
- TIME_MSG("--- NVIM STARTED ---");
- fclose(time_fd);
- time_fd = NULL;
+ time_finish();
}
// After the first screen update may start triggering WinScrolled
// autocmd events. Store all the scroll positions and sizes now.
@@ -1848,7 +1849,7 @@ void clear_showcmd(void)
}
if (VIsual_active && !char_avail()) {
- int cursor_bot = lt(VIsual, curwin->w_cursor);
+ bool cursor_bot = lt(VIsual, curwin->w_cursor);
int lines;
colnr_T leftcol, rightcol;
linenr_T top, bot;
@@ -1862,8 +1863,8 @@ void clear_showcmd(void)
bot = VIsual.lnum;
}
// Include closed folds as a whole.
- (void)hasFolding(top, &top, NULL);
- (void)hasFolding(bot, NULL, &bot);
+ hasFolding(top, &top, NULL);
+ hasFolding(bot, NULL, &bot);
lines = bot - top + 1;
if (VIsual_mode == Ctrl_V) {
@@ -2186,7 +2187,7 @@ void check_scrollbind(linenr_T topline_diff, int leftcol_diff)
// do the horizontal scroll
if (want_hor) {
- (void)set_leftcol(tgt_leftcol);
+ set_leftcol(tgt_leftcol);
}
}
@@ -2257,7 +2258,7 @@ static void nv_page(cmdarg_T *cap)
goto_tabpage(cap->count0);
}
} else {
- (void)onepage(cap->arg, cap->count1);
+ onepage(cap->arg, cap->count1);
}
}
@@ -2607,7 +2608,7 @@ void nv_scroll_line(cmdarg_T *cap)
}
/// Scroll "count" lines up or down, and redraw.
-void scroll_redraw(int up, linenr_T count)
+void scroll_redraw(bool up, linenr_T count)
{
linenr_T prev_topline = curwin->w_topline;
int prev_skipcol = curwin->w_skipcol;
@@ -2678,7 +2679,7 @@ static bool nv_z_get_count(cmdarg_T *cap, int *nchar_arg)
LANGMAP_ADJUST(nchar, true);
no_mapping--;
allow_keys--;
- (void)add_to_showcmd(nchar);
+ add_to_showcmd(nchar);
if (nchar == K_DEL || nchar == K_KDEL) {
n /= 10;
@@ -2723,7 +2724,7 @@ static int nv_zg_zw(cmdarg_T *cap, int nchar)
LANGMAP_ADJUST(nchar, true);
no_mapping--;
allow_keys--;
- (void)add_to_showcmd(nchar);
+ add_to_showcmd(nchar);
if (vim_strchr("gGwW", nchar) == NULL) {
clearopbeep(cap->oap);
@@ -2873,8 +2874,8 @@ static void nv_zet(cmdarg_T *cap)
case 'h':
case K_LEFT:
if (!curwin->w_p_wrap) {
- (void)set_leftcol((colnr_T)cap->count1 > curwin->w_leftcol
- ? 0 : curwin->w_leftcol - (colnr_T)cap->count1);
+ set_leftcol((colnr_T)cap->count1 > curwin->w_leftcol
+ ? 0 : curwin->w_leftcol - (colnr_T)cap->count1);
}
break;
@@ -2887,7 +2888,7 @@ static void nv_zet(cmdarg_T *cap)
case 'l':
case K_RIGHT:
if (!curwin->w_p_wrap) {
- (void)set_leftcol(curwin->w_leftcol + (colnr_T)cap->count1);
+ set_leftcol(curwin->w_leftcol + (colnr_T)cap->count1);
}
break;
@@ -3289,8 +3290,8 @@ static void nv_ctrlo(cmdarg_T *cap)
static void nv_hat(cmdarg_T *cap)
{
if (!checkclearopq(cap->oap)) {
- (void)buflist_getfile(cap->count0, 0,
- GETF_SETMARK|GETF_ALT, false);
+ buflist_getfile(cap->count0, 0,
+ GETF_SETMARK|GETF_ALT, false);
}
}
@@ -3555,7 +3556,7 @@ static void nv_ident(cmdarg_T *cap)
init_history();
add_to_history(HIST_SEARCH, buf, true, NUL);
- (void)normal_search(cap, cmdchar == '*' ? '/' : '?', buf, 0, NULL);
+ normal_search(cap, cmdchar == '*' ? '/' : '?', buf, 0, NULL);
} else {
g_tag_at_cursor = true;
do_cmdline_cmd(buf);
@@ -3639,8 +3640,8 @@ static void nv_scroll(cmdarg_T *cap)
// Count a fold for one screen line.
for (n = cap->count1 - 1; n > 0
&& curwin->w_cursor.lnum > curwin->w_topline; n--) {
- (void)hasFolding(curwin->w_cursor.lnum,
- &curwin->w_cursor.lnum, NULL);
+ hasFolding(curwin->w_cursor.lnum,
+ &curwin->w_cursor.lnum, NULL);
if (curwin->w_cursor.lnum > curwin->w_topline) {
curwin->w_cursor.lnum--;
}
@@ -3681,7 +3682,7 @@ static void nv_scroll(cmdarg_T *cap)
// Count a fold for one screen line.
lnum = curwin->w_topline;
while (n-- > 0 && lnum < curwin->w_botline - 1) {
- (void)hasFolding(lnum, NULL, &lnum);
+ hasFolding(lnum, NULL, &lnum);
lnum++;
}
n = lnum - curwin->w_topline;
@@ -3901,7 +3902,7 @@ static void nv_gotofile(cmdarg_T *cap)
if (ptr != NULL) {
// do autowrite if necessary
if (curbufIsChanged() && curbuf->b_nwindows <= 1 && !buf_hide(curbuf)) {
- (void)autowrite(curbuf, false);
+ autowrite(curbuf, false);
}
setpcmark();
if (do_ecmd(0, ptr, NULL, NULL, ECMD_LAST,
@@ -3972,9 +3973,9 @@ static void nv_search(cmdarg_T *cap)
return;
}
- (void)normal_search(cap, cap->cmdchar, cap->searchbuf,
- (cap->arg || !equalpos(save_cursor, curwin->w_cursor))
- ? 0 : SEARCH_MARK, NULL);
+ normal_search(cap, cap->cmdchar, cap->searchbuf,
+ (cap->arg || !equalpos(save_cursor, curwin->w_cursor))
+ ? 0 : SEARCH_MARK, NULL);
}
/// Handle "N" and "n" commands.
@@ -3990,7 +3991,7 @@ static void nv_next(cmdarg_T *cap)
// an offset is given and the cursor is on the last char in the buffer:
// Repeat with count + 1.
cap->count1 += 1;
- (void)normal_search(cap, 0, NULL, SEARCH_MARK | cap->arg, NULL);
+ normal_search(cap, 0, NULL, SEARCH_MARK | cap->arg, NULL);
cap->count1 -= 1;
}
}
@@ -4124,7 +4125,7 @@ static void nv_bracket_block(cmdarg_T *cap, const pos_T *old_pos)
if (cap->nchar == 'm' || cap->nchar == 'M') {
int c;
// norm is true for "]M" and "[m"
- int norm = ((findc == '{') == (cap->nchar == 'm'));
+ bool norm = ((findc == '{') == (cap->nchar == 'm'));
n = cap->count1;
// found a match: we were inside a method
@@ -4290,9 +4291,9 @@ static void nv_brackets(cmdarg_T *cap)
} else if (cap->nchar >= K_RIGHTRELEASE && cap->nchar <= K_LEFTMOUSE) {
// [ or ] followed by a middle mouse click: put selected text with
// indent adjustment. Any other button just does as usual.
- (void)do_mouse(cap->oap, cap->nchar,
- (cap->cmdchar == ']') ? FORWARD : BACKWARD,
- cap->count1, PUT_FIXINDENT);
+ do_mouse(cap->oap, cap->nchar,
+ (cap->cmdchar == ']') ? FORWARD : BACKWARD,
+ cap->count1, PUT_FIXINDENT);
} else if (cap->nchar == 'z') {
// "[z" and "]z": move to start or end of open fold.
if (foldMoveTo(false, cap->cmdchar == ']' ? FORWARD : BACKWARD,
@@ -4557,7 +4558,7 @@ static void nv_replace(cmdarg_T *cap)
// Insert the newline with an insert command, takes care of
// autoindent. The insert command depends on being on the last
// character of a line or not.
- (void)del_chars(cap->count1, false); // delete the characters
+ del_chars(cap->count1, false); // delete the characters
stuffcharReadbuff('\r');
stuffcharReadbuff(ESC);
@@ -4722,7 +4723,7 @@ static void nv_vreplace(cmdarg_T *cap)
/// Swap case for "~" command, when it does not work like an operator.
static void n_swapchar(cmdarg_T *cap)
{
- int did_change = 0;
+ bool did_change = false;
if (checkclearopq(cap->oap)) {
return;
@@ -5122,6 +5123,7 @@ static void n_start_visual_mode(int c)
curwin->w_old_cursor_lnum = curwin->w_cursor.lnum;
curwin->w_old_visual_lnum = curwin->w_cursor.lnum;
}
+ redraw_curbuf_later(UPD_VALID);
}
/// CTRL-W: Window commands
@@ -5313,7 +5315,7 @@ static void nv_g_dollar_cmd(cmdarg_T *cap)
} else {
if (cap->count1 > 1) {
// if it fails, let the cursor still move to the last char
- (void)cursor_down(cap->count1 - 1, false);
+ cursor_down(cap->count1 - 1, false);
}
i = curwin->w_leftcol + curwin->w_width_inner - col_off - 1;
coladvance((colnr_T)i);
@@ -5627,7 +5629,7 @@ static void nv_g_cmd(cmdarg_T *cap)
case K_X2DRAG:
case K_X2RELEASE:
mod_mask = MOD_MASK_CTRL;
- (void)do_mouse(oap, cap->nchar, BACKWARD, cap->count1, 0);
+ do_mouse(oap, cap->nchar, BACKWARD, cap->count1, 0);
break;
case K_IGNORE:
@@ -5700,12 +5702,12 @@ static void n_opencmd(cmdarg_T *cap)
if (cap->cmdchar == 'O') {
// Open above the first line of a folded sequence of lines
- (void)hasFolding(curwin->w_cursor.lnum,
- &curwin->w_cursor.lnum, NULL);
+ hasFolding(curwin->w_cursor.lnum,
+ &curwin->w_cursor.lnum, NULL);
} else {
// Open below the last line of a folded sequence of lines
- (void)hasFolding(curwin->w_cursor.lnum,
- NULL, &curwin->w_cursor.lnum);
+ hasFolding(curwin->w_cursor.lnum,
+ NULL, &curwin->w_cursor.lnum);
}
// trigger TextChangedI for the 'o/O' command
curbuf->b_last_changedtick_i = buf_get_changedtick(curbuf);
@@ -6109,10 +6111,10 @@ static void nv_normal(cmdarg_T *cap)
/// Don't even beep if we are canceling a command.
static void nv_esc(cmdarg_T *cap)
{
- int no_reason = (cap->oap->op_type == OP_NOP
- && cap->opcount == 0
- && cap->count0 == 0
- && cap->oap->regname == 0);
+ bool no_reason = (cap->oap->op_type == OP_NOP
+ && cap->opcount == 0
+ && cap->count0 == 0
+ && cap->oap->regname == 0);
if (cap->arg) { // true for CTRL-C
if (restart_edit == 0 && cmdwin_type == 0 && !VIsual_active && no_reason) {
@@ -6444,6 +6446,7 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
bool was_visual = false;
int dir;
int flags = 0;
+ const int save_fen = curwin->w_p_fen;
if (cap->oap->op_type != OP_NOP) {
// "dp" is ":diffput"
@@ -6494,6 +6497,10 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
savereg = copy_register(regname);
}
+ // Temporarily disable folding, as deleting a fold marker may cause
+ // the cursor to be included in a fold.
+ curwin->w_p_fen = false;
+
// To place the cursor correctly after a blockwise put, and to leave the
// text in the correct position when putting over a selection with
// 'virtualedit' and past the end of the line, we use the 'c' operator in
@@ -6544,9 +6551,12 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
xfree(savereg);
}
- // What to reselect with "gv"? Selecting the just put text seems to
- // be the most useful, since the original text was removed.
if (was_visual) {
+ if (save_fen) {
+ curwin->w_p_fen = true;
+ }
+ // What to reselect with "gv"? Selecting the just put text seems to
+ // be the most useful, since the original text was removed.
curbuf->b_visual.vi_start = curbuf->b_op_start;
curbuf->b_visual.vi_end = curbuf->b_op_end;
// need to adjust cursor position
@@ -6619,6 +6629,6 @@ void normal_cmd(oparg_T *oap, bool toplevel)
s.toplevel = toplevel;
s.oa = *oap;
normal_prepare(&s);
- (void)normal_execute(&s.state, safe_vgetc());
+ normal_execute(&s.state, safe_vgetc());
*oap = s.oa;
}
diff --git a/src/nvim/normal.h b/src/nvim/normal.h
index dbe74712fc..57a3418d92 100644
--- a/src/nvim/normal.h
+++ b/src/nvim/normal.h
@@ -1,9 +1,11 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
+#include <stddef.h> // IWYU pragma: keep
+
#include "nvim/macros_defs.h"
-#include "nvim/normal_defs.h" // IWYU pragma: export
+#include "nvim/normal_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
/// Values for find_ident_under_cursor()
enum {
diff --git a/src/nvim/normal_defs.h b/src/nvim/normal_defs.h
index 060c1057f9..0309f6bc80 100644
--- a/src/nvim/normal_defs.h
+++ b/src/nvim/normal_defs.h
@@ -16,7 +16,7 @@ typedef enum {
} MotionType;
/// Arguments for operators.
-typedef struct oparg_S {
+typedef struct {
int op_type; ///< current pending operator type
int regname; ///< register to use for the operator
MotionType motion_type; ///< type of the current cursor motion
@@ -42,7 +42,7 @@ typedef struct oparg_S {
} oparg_T;
/// Arguments for Normal mode commands.
-typedef struct cmdarg_S {
+typedef struct {
oparg_T *oap; ///< Operator arguments
int prechar; ///< prefix character (optional, always 'g')
int cmdchar; ///< command character
@@ -70,6 +70,5 @@ enum {
REPLACE_NL_NCHAR = -2,
};
-/// columns needed by shown command
-enum { SHOWCMD_COLS = 10, };
+enum { SHOWCMD_COLS = 10, }; ///< columns needed by shown command
enum { SHOWCMD_BUFLEN = SHOWCMD_COLS + 1 + 30, };
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index 9d0b8e01cd..fccc663e1a 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -9,13 +9,16 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include "nvim/api/private/defs.h"
#include "nvim/ascii_defs.h"
#include "nvim/assert_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
+#include "nvim/buffer_updates.h"
#include "nvim/change.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
@@ -29,17 +32,23 @@
#include "nvim/extmark.h"
#include "nvim/fold.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/getchar_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
@@ -54,11 +63,13 @@
#include "nvim/plines.h"
#include "nvim/search.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/terminal.h"
#include "nvim/textformat.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -73,25 +84,6 @@ static bool clipboard_delay_update = false; // delay clipboard update
static bool clipboard_needs_update = false; // clipboard was updated
static bool clipboard_didwarn = false;
-// structure used by block_prep, op_delete and op_yank for blockwise operators
-// also op_change, op_shift, op_insert, op_replace - AKelly
-struct block_def {
- int startspaces; // 'extra' cols before first char
- int endspaces; // 'extra' cols after last char
- int textlen; // chars in block
- char *textstart; // pointer to 1st char (partially) in block
- colnr_T textcol; // index of chars (partially) in block
- colnr_T start_vcol; // start col of 1st char wholly inside block
- colnr_T end_vcol; // start col of 1st char wholly after block
- int is_short; // true if line is too short to fit in block
- int is_MAX; // true if curswant==MAXCOL when starting
- int is_oneChar; // true if block within one character
- int pre_whitesp; // screen cols of ws before block
- int pre_whitesp_c; // chars of ws before block
- colnr_T end_char_vcols; // number of vcols of post-block char
- colnr_T start_char_vcols; // number of vcols of pre-block char
-};
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ops.c.generated.h"
#endif
@@ -213,9 +205,8 @@ int get_extra_op_char(int optype)
}
/// handle a shift operation
-void op_shift(oparg_T *oap, int curs_top, int amount)
+void op_shift(oparg_T *oap, bool curs_top, int amount)
{
- int i;
int block_col = 0;
if (u_save((linenr_T)(oap->start.lnum - 1),
@@ -227,7 +218,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
block_col = curwin->w_cursor.col;
}
- for (i = oap->line_count - 1; i >= 0; i--) {
+ for (int i = oap->line_count - 1; i >= 0; i--) {
int first_char = (uint8_t)(*get_cursor_line_ptr());
if (first_char == NUL) { // empty line
curwin->w_cursor.col = 0;
@@ -288,7 +279,7 @@ void op_shift(oparg_T *oap, int curs_top, int amount)
/// leaves cursor on first blank in the line.
///
/// @param call_changed_bytes call changed_bytes()
-void shift_line(int left, int round, int amount, int call_changed_bytes)
+void shift_line(bool left, bool round, int amount, int call_changed_bytes)
{
const int sw_val = get_sw_value_indent(curbuf);
@@ -324,7 +315,7 @@ void shift_line(int left, int round, int amount, int call_changed_bytes)
if (State & VREPLACE_FLAG) {
change_indent(INDENT_SET, count, false, NUL, call_changed_bytes);
} else {
- (void)set_indent(count, call_changed_bytes ? SIN_CHANGED : 0);
+ set_indent(count, call_changed_bytes ? SIN_CHANGED : 0);
}
}
@@ -378,19 +369,21 @@ static void shift_block(oparg_T *oap, int amount)
}
// TODO(vim): is passing bd.textstart for start of the line OK?
- chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum,
- bd.start_vcol, bd.textstart, bd.textstart);
- while (ascii_iswhite(*cts.cts_ptr)) {
- incr = lbr_chartabsize_adv(&cts);
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, curwin, curwin->w_cursor.lnum, bd.textstart);
+ StrCharInfo ci = utf_ptr2StrCharInfo(bd.textstart);
+ int vcol = bd.start_vcol;
+ while (ascii_iswhite(ci.chr.value)) {
+ incr = win_charsize(cstype, vcol, ci.ptr, ci.chr.value, &csarg).width;
+ ci = utfc_next(ci);
total += incr;
- cts.cts_vcol += incr;
+ vcol += incr;
}
- bd.textstart = cts.cts_ptr;
- bd.start_vcol = cts.cts_vcol;
- clear_chartabsize_arg(&cts);
+ bd.textstart = ci.ptr;
+ bd.start_vcol = vcol;
- int tabs = 0, spaces = 0;
+ int tabs = 0;
+ int spaces = 0;
// OK, now total=all the VWS reqd, and textstart points at the 1st
// non-ws char in the block.
if (!curbuf->b_p_et) {
@@ -438,16 +431,13 @@ static void shift_block(oparg_T *oap, int amount)
// The character's column is in "bd.start_vcol".
colnr_T non_white_col = bd.start_vcol;
- chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum,
- non_white_col, bd.textstart, non_white);
- while (ascii_iswhite(*cts.cts_ptr)) {
- incr = lbr_chartabsize_adv(&cts);
- cts.cts_vcol += incr;
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, curwin, curwin->w_cursor.lnum, bd.textstart);
+ while (ascii_iswhite(*non_white)) {
+ incr = win_charsize(cstype, non_white_col, non_white, (uint8_t)(*non_white), &csarg).width;
+ non_white_col += incr;
+ non_white++;
}
- non_white_col = cts.cts_vcol;
- non_white = cts.cts_ptr;
- clear_chartabsize_arg(&cts);
const colnr_T block_space_width = non_white_col - oap->start_vcol;
// We will shift by "total" or "block_space_width", whichever is less.
@@ -468,19 +458,17 @@ static void shift_block(oparg_T *oap, int amount)
if (bd.startspaces) {
verbatim_copy_width -= bd.start_char_vcols;
}
- init_chartabsize_arg(&cts, curwin, 0, verbatim_copy_width,
- bd.textstart, verbatim_copy_end);
- while (cts.cts_vcol < destination_col) {
- incr = lbr_chartabsize(&cts);
- if (cts.cts_vcol + incr > destination_col) {
+ cstype = init_charsize_arg(&csarg, curwin, 0, bd.textstart);
+ StrCharInfo ci = utf_ptr2StrCharInfo(verbatim_copy_end);
+ while (verbatim_copy_width < destination_col) {
+ incr = win_charsize(cstype, verbatim_copy_width, ci.ptr, ci.chr.value, &csarg).width;
+ if (verbatim_copy_width + incr > destination_col) {
break;
}
- cts.cts_vcol += incr;
- MB_PTR_ADV(cts.cts_ptr);
+ verbatim_copy_width += incr;
+ ci = utfc_next(ci);
}
- verbatim_copy_width = cts.cts_vcol;
- verbatim_copy_end = cts.cts_ptr;
- clear_chartabsize_arg(&cts);
+ verbatim_copy_end = ci.ptr;
// If "destination_col" is different from the width of the initial
// part of the line that will be copied, it means we encountered a tab
@@ -520,7 +508,7 @@ static void shift_block(oparg_T *oap, int amount)
/// Insert string "s" (b_insert ? before : after) block :AKelly
/// Caller must prepare for undo.
-static void block_insert(oparg_T *oap, char *s, int b_insert, struct block_def *bdp)
+static void block_insert(oparg_T *oap, char *s, bool b_insert, struct block_def *bdp)
{
int ts_val;
int count = 0; // extra spaces to replace a cut TAB
@@ -815,9 +803,15 @@ yankreg_T *get_yank_register(int regname, int mode)
{
yankreg_T *reg;
- if (mode == YREG_PASTE && get_clipboard(regname, &reg, false)) {
+ if ((mode == YREG_PASTE || mode == YREG_PUT)
+ && get_clipboard(regname, &reg, false)) {
// reg is set to clipboard contents.
return reg;
+ } else if (mode == YREG_PUT && (regname == '*' || regname == '+')) {
+ // in case clipboard not available and we aren't actually pasting,
+ // return an empty register
+ static yankreg_T empty_reg = { .y_array = NULL };
+ return &empty_reg;
} else if (mode != YREG_YANK
&& (regname == 0 || regname == '"' || regname == '*' || regname == '+')
&& y_previous != NULL) {
@@ -909,14 +903,14 @@ int do_record(int c)
if (p != NULL) {
// Remove escaping for K_SPECIAL in multi-byte chars.
vim_unescape_ks(p);
- (void)tv_dict_add_str(dict, S_LEN("regcontents"), p);
+ tv_dict_add_str(dict, S_LEN("regcontents"), p);
}
// Name of requested register, or empty string for unnamed operation.
char buf[NUMBUFLEN + 2];
buf[0] = (char)regname;
buf[1] = NUL;
- (void)tv_dict_add_str(dict, S_LEN("regname"), buf);
+ tv_dict_add_str(dict, S_LEN("regname"), buf);
tv_dict_set_keys_readonly(dict);
// Get the recorded key hits. K_SPECIAL will be escaped, this
@@ -1159,6 +1153,7 @@ int do_execreg(int regname, int colon, int addcr, int silent)
}
}
reg_executing = regname == 0 ? '"' : regname; // disable the 'q' command
+ pending_end_reg_executing = false;
}
return retval;
}
@@ -1266,9 +1261,24 @@ int insert_reg(int regname, bool literally_arg)
} else {
for (size_t i = 0; i < reg->y_size; i++) {
if (regname == '-') {
+ Direction dir = BACKWARD;
+ if ((State & REPLACE_FLAG) != 0) {
+ pos_T curpos;
+ if (u_save_cursor() == FAIL) {
+ return FAIL;
+ }
+ del_chars(mb_charlen(reg->y_array[0]), true);
+ curpos = curwin->w_cursor;
+ if (oneright() == FAIL) {
+ // hit end of line, need to put forward (after the current position)
+ dir = FORWARD;
+ }
+ curwin->w_cursor = curpos;
+ }
+
AppendCharToRedobuff(Ctrl_R);
AppendCharToRedobuff(regname);
- do_put(regname, NULL, BACKWARD, 1, PUT_CURSEND);
+ do_put(regname, NULL, dir, 1, PUT_CURSEND);
} else {
stuffescaped(reg->y_array[i], literally);
}
@@ -1495,7 +1505,7 @@ int op_delete(oparg_T *oap)
// register. For the black hole register '_' don't yank anything.
if (oap->regname != '_') {
yankreg_T *reg = NULL;
- int did_yank = false;
+ bool did_yank = false;
if (oap->regname != 0) {
// check for read-only register
if (!valid_yank_reg(oap->regname, true)) {
@@ -1695,8 +1705,8 @@ int op_delete(oparg_T *oap)
}
}
- (void)del_bytes((colnr_T)n, !virtual_op,
- oap->op_type == OP_DELETE && !oap->is_VIsual);
+ del_bytes((colnr_T)n, !virtual_op,
+ oap->op_type == OP_DELETE && !oap->is_VIsual);
} else {
// delete characters between lines
pos_T curpos;
@@ -1722,10 +1732,10 @@ int op_delete(oparg_T *oap)
// delete from start of line until op_end
int n = (oap->end.col + 1 - !oap->inclusive);
curwin->w_cursor.col = 0;
- (void)del_bytes((colnr_T)n, !virtual_op,
- oap->op_type == OP_DELETE && !oap->is_VIsual);
+ del_bytes((colnr_T)n, !virtual_op,
+ oap->op_type == OP_DELETE && !oap->is_VIsual);
curwin->w_cursor = curpos; // restore curwin->w_cursor
- (void)do_join(2, false, false, false, false);
+ do_join(2, false, false, false, false);
curbuf_splice_pending--;
extmark_splice(curbuf, (int)startpos.lnum - 1, startpos.col,
(int)oap->line_count - 1, n, deleted_bytes,
@@ -1760,8 +1770,13 @@ static void mb_adjust_opend(oparg_T *oap)
return;
}
- char *p = ml_get(oap->end.lnum);
- oap->end.col += utf_cp_tail_off(p, p + oap->end.col);
+ const char *line = ml_get(oap->end.lnum);
+ const char *ptr = line + oap->end.col;
+ if (*ptr != NUL) {
+ ptr -= utf_head_off(line, ptr);
+ ptr += utfc_ptr2len(ptr) - 1;
+ oap->end.col = (colnr_T)(ptr - line);
+ }
}
/// Put character 'c' at position 'lp'
@@ -1793,7 +1808,7 @@ static int op_replace(oparg_T *oap, int c)
int n;
struct block_def bd;
char *after_p = NULL;
- int had_ctrl_v_cr = false;
+ bool had_ctrl_v_cr = false;
if ((curbuf->b_ml.ml_flags & ML_EMPTY) || oap->empty) {
return OK; // nothing to do
@@ -1815,11 +1830,6 @@ static int op_replace(oparg_T *oap, int c)
// block mode replace
if (oap->motion_type == kMTBlockWise) {
- int numc;
- int num_chars;
- char *newp;
- char *oldp;
- colnr_T oldlen;
bd.is_MAX = (curwin->w_curswant == MAXCOL);
for (; curwin->w_cursor.lnum <= oap->end.lnum; curwin->w_cursor.lnum++) {
curwin->w_cursor.col = 0; // make sure cursor position is valid
@@ -1850,7 +1860,7 @@ static int op_replace(oparg_T *oap, int c)
&& !bd.is_oneChar
&& bd.end_char_vcols > 0) ? bd.end_char_vcols - 1 : 0;
// Figure out how many characters to replace.
- numc = oap->end_vcol - oap->start_vcol + 1;
+ int numc = oap->end_vcol - oap->start_vcol + 1;
if (bd.is_short && (!virtual_op || bd.is_MAX)) {
numc -= (oap->end_vcol - bd.end_vcol) + 1;
}
@@ -1866,11 +1876,11 @@ static int op_replace(oparg_T *oap, int c)
}
// Compute bytes needed, move character count to num_chars.
- num_chars = numc;
+ int num_chars = numc;
numc *= utf_char2len(c);
- oldp = get_cursor_line_ptr();
- oldlen = (int)strlen(oldp);
+ char *oldp = get_cursor_line_ptr();
+ colnr_T oldlen = (int)strlen(oldp);
size_t newp_size = (size_t)bd.textcol + (size_t)bd.startspaces;
if (had_ctrl_v_cr || (c != '\r' && c != '\n')) {
@@ -1880,7 +1890,7 @@ static int op_replace(oparg_T *oap, int c)
- bd.textcol - bd.textlen);
}
}
- newp = xmallocz(newp_size);
+ char *newp = xmallocz(newp_size);
// copy up to deleted part
memmove(newp, oldp, (size_t)bd.textcol);
oldp += bd.textcol + bd.textlen;
@@ -1891,7 +1901,8 @@ static int op_replace(oparg_T *oap, int c)
size_t after_p_len = 0;
int col = oldlen - bd.textcol - bd.textlen + 1;
assert(col >= 0);
- int newrows = 0, newcols = 0;
+ int newrows = 0;
+ int newcols = 0;
if (had_ctrl_v_cr || (c != '\r' && c != '\n')) {
// strlen(newp) at this point
int newp_len = bd.textcol + bd.startspaces;
@@ -2030,7 +2041,7 @@ static int op_replace(oparg_T *oap, int c)
void op_tilde(oparg_T *oap)
{
struct block_def bd;
- int did_change = false;
+ bool did_change = false;
if (u_save((linenr_T)(oap->start.lnum - 1),
(linenr_T)(oap->end.lnum + 1)) == FAIL) {
@@ -2040,11 +2051,9 @@ void op_tilde(oparg_T *oap)
pos_T pos = oap->start;
if (oap->motion_type == kMTBlockWise) { // Visual block mode
for (; pos.lnum <= oap->end.lnum; pos.lnum++) {
- int one_change;
-
block_prep(oap, &bd, pos.lnum, false);
pos.col = bd.textcol;
- one_change = swapchars(oap->op_type, &pos, bd.textlen);
+ bool one_change = swapchars(oap->op_type, &pos, bd.textlen);
did_change |= one_change;
}
if (did_change) {
@@ -2142,16 +2151,16 @@ bool swapchar(int op_type, pos_T *pos)
return false;
}
- if (op_type == OP_UPPER && c == 0xdf) {
+ // ~ is OP_NOP, g~ is OP_TILDE, gU is OP_UPPER
+ if ((op_type == OP_UPPER || op_type == OP_NOP || op_type == OP_TILDE) && c == 0xdf) {
pos_T sp = curwin->w_cursor;
- // Special handling of German sharp s: change to "SS".
+ // Special handling for lowercase German sharp s (ß): convert to uppercase (ẞ).
curwin->w_cursor = *pos;
del_char(false);
- ins_char('S');
- ins_char('S');
+ ins_char(0x1E9E);
curwin->w_cursor = sp;
- inc(pos);
+ return true;
}
int nc = c;
@@ -2270,7 +2279,7 @@ void op_insert(oparg_T *oap, int count1)
pos_T t1 = oap->start;
const pos_T start_insert = curwin->w_cursor;
- (void)edit(NUL, false, (linenr_T)count1);
+ edit(NUL, false, (linenr_T)count1);
// When a tab was inserted, and the characters in front of the tab
// have been converted to a tab as well, the column of the cursor
@@ -2472,9 +2481,6 @@ int op_change(oparg_T *oap)
ins_len = (int)strlen(firstline) - pre_textlen;
if (ins_len > 0) {
- int offset;
- char *newp;
- char *oldp;
// Subsequent calls to ml_get() flush the firstline data - take a
// copy of the inserted text.
char *ins_text = xmalloc((size_t)ins_len + 1);
@@ -2489,16 +2495,16 @@ int op_change(oparg_T *oap)
// initial coladd offset as part of "startspaces"
if (bd.is_short) {
vpos.lnum = linenr;
- (void)getvpos(&vpos, oap->start_vcol);
+ getvpos(&vpos, oap->start_vcol);
} else {
vpos.coladd = 0;
}
- oldp = ml_get(linenr);
- newp = xmalloc(strlen(oldp) + (size_t)vpos.coladd
- + (size_t)ins_len + 1);
+ char *oldp = ml_get(linenr);
+ char *newp = xmalloc(strlen(oldp) + (size_t)vpos.coladd
+ + (size_t)ins_len + 1);
// copy up to block start
memmove(newp, oldp, (size_t)bd.textcol);
- offset = bd.textcol;
+ int offset = bd.textcol;
memset(newp + offset, ' ', (size_t)vpos.coladd);
offset += vpos.coladd;
memmove(newp + offset, ins_text, (size_t)ins_len);
@@ -2635,66 +2641,11 @@ static void op_yank_reg(oparg_T *oap, bool message, yankreg_T *reg, bool append)
reg->y_array[y_idx] = xstrdup(ml_get(lnum));
break;
- case kMTCharWise: {
- colnr_T startcol = 0, endcol = MAXCOL;
- int is_oneChar = false;
- colnr_T cs, ce;
- char *p = ml_get(lnum);
- bd.startspaces = 0;
- bd.endspaces = 0;
-
- if (lnum == oap->start.lnum) {
- startcol = oap->start.col;
- if (virtual_op) {
- getvcol(curwin, &oap->start, &cs, NULL, &ce);
- if (ce != cs && oap->start.coladd > 0) {
- // Part of a tab selected -- but don't double-count it.
- bd.startspaces = (ce - cs + 1) - oap->start.coladd;
- if (bd.startspaces < 0) {
- bd.startspaces = 0;
- }
- startcol++;
- }
- }
- }
-
- if (lnum == oap->end.lnum) {
- endcol = oap->end.col;
- if (virtual_op) {
- getvcol(curwin, &oap->end, &cs, NULL, &ce);
- if (p[endcol] == NUL || (cs + oap->end.coladd < ce
- // Don't add space for double-wide
- // char; endcol will be on last byte
- // of multi-byte char.
- && utf_head_off(p, p + endcol) == 0)) {
- if (oap->start.lnum == oap->end.lnum
- && oap->start.col == oap->end.col) {
- // Special case: inside a single char
- is_oneChar = true;
- bd.startspaces = oap->end.coladd
- - oap->start.coladd + oap->inclusive;
- endcol = startcol;
- } else {
- bd.endspaces = oap->end.coladd
- + oap->inclusive;
- endcol -= oap->inclusive;
- }
- }
- }
- }
- if (endcol == MAXCOL) {
- endcol = (colnr_T)strlen(p);
- }
- if (startcol > endcol
- || is_oneChar) {
- bd.textlen = 0;
- } else {
- bd.textlen = endcol - startcol + oap->inclusive;
- }
- bd.textstart = p + startcol;
+ case kMTCharWise:
+ charwise_block_prep(oap->start, oap->end, &bd, lnum, oap->inclusive);
yank_copy_line(reg, &bd, y_idx, false);
break;
- }
+
// NOTREACHED
case kMTUnknown:
abort();
@@ -2836,17 +2787,17 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
tv_list_append_string(list, reg->y_array[i], -1);
}
tv_list_set_lock(list, VAR_FIXED);
- (void)tv_dict_add_list(dict, S_LEN("regcontents"), list);
+ tv_dict_add_list(dict, S_LEN("regcontents"), list);
// Register type.
char buf[NUMBUFLEN + 2];
format_reg_type(reg->y_type, reg->y_width, buf, ARRAY_SIZE(buf));
- (void)tv_dict_add_str(dict, S_LEN("regtype"), buf);
+ tv_dict_add_str(dict, S_LEN("regtype"), buf);
// Name of requested register, or empty string for unnamed operation.
buf[0] = (char)oap->regname;
buf[1] = NUL;
- (void)tv_dict_add_str(dict, S_LEN("regname"), buf);
+ tv_dict_add_str(dict, S_LEN("regname"), buf);
// Motion type: inclusive or exclusive.
tv_dict_add_bool(dict, S_LEN("inclusive"),
@@ -2855,11 +2806,11 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
// Kind of operation: yank, delete, change).
buf[0] = (char)get_op_char(oap->op_type);
buf[1] = NUL;
- (void)tv_dict_add_str(dict, S_LEN("operator"), buf);
+ tv_dict_add_str(dict, S_LEN("operator"), buf);
// Selection type: visual or not.
- (void)tv_dict_add_bool(dict, S_LEN("visual"),
- oap->is_VIsual ? kBoolVarTrue : kBoolVarFalse);
+ tv_dict_add_bool(dict, S_LEN("visual"),
+ oap->is_VIsual ? kBoolVarTrue : kBoolVarFalse);
tv_dict_set_keys_readonly(dict);
textlock++;
@@ -2978,7 +2929,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
if (flags & PUT_LINE) {
stuffcharReadbuff(command_start_char);
for (; count > 0; count--) {
- (void)stuff_inserted(NUL, 1, count != 1);
+ stuff_inserted(NUL, 1, count != 1);
if (count != 1) {
// To avoid 'autoindent' affecting the text, use Ctrl_U to remove any
// whitespace. Can't just insert Ctrl_U into readbuf1, this would go
@@ -2990,7 +2941,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
}
}
} else {
- (void)stuff_inserted(command_start_char, count, false);
+ stuff_inserted(command_start_char, count, false);
}
// Putting the text is done later, so can't move the cursor to the next
@@ -3111,6 +3062,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
return;
}
+ colnr_T split_pos = 0;
if (y_type == kMTLineWise) {
if (flags & PUT_LINE_SPLIT) {
// "p" or "P" in Visual mode: split the lines to put the text in
@@ -3118,23 +3070,24 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
if (u_save_cursor() == FAIL) {
goto end;
}
- char *p = get_cursor_pos_ptr();
+ char *curline = get_cursor_line_ptr();
+ char *p = curline + curwin->w_cursor.col;
if (dir == FORWARD && *p != NUL) {
MB_PTR_ADV(p);
}
+ // we need this later for the correct extmark_splice() event
+ split_pos = (colnr_T)(p - curline);
+
char *ptr = xstrdup(p);
ml_append(curwin->w_cursor.lnum, ptr, 0, false);
xfree(ptr);
- char *oldp = get_cursor_line_ptr();
- p = oldp + curwin->w_cursor.col;
- if (dir == FORWARD && *p != NUL) {
- MB_PTR_ADV(p);
- }
- ptr = xmemdupz(oldp, (size_t)(p - oldp));
+ ptr = xmemdupz(get_cursor_line_ptr(), (size_t)split_pos);
ml_replace(curwin->w_cursor.lnum, ptr, false);
nr_lines++;
dir = FORWARD;
+
+ buf_updates_send_changes(curbuf, curwin->w_cursor.lnum, 1, 1);
}
if (flags & PUT_LINE_FORWARD) {
// Must be "p" for a Visual block, put lines below the block.
@@ -3168,9 +3121,9 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
// Correct line number for closed fold. Don't move the cursor yet,
// u_save() uses it.
if (dir == BACKWARD) {
- (void)hasFolding(lnum, &lnum, NULL);
+ hasFolding(lnum, &lnum, NULL);
} else {
- (void)hasFolding(lnum, NULL, &lnum);
+ hasFolding(lnum, NULL, &lnum);
}
if (dir == FORWARD) {
lnum++;
@@ -3275,19 +3228,19 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
}
// get the old line and advance to the position to insert at
char *oldp = get_cursor_line_ptr();
- size_t oldlen = strlen(oldp);
- chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, curwin->w_cursor.lnum, 0, oldp, oldp);
- while (cts.cts_vcol < col && *cts.cts_ptr != NUL) {
- // Count a tab for what it's worth (if list mode not on)
- incr = lbr_chartabsize_adv(&cts);
- cts.cts_vcol += incr;
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, curwin, curwin->w_cursor.lnum, oldp);
+ StrCharInfo ci = utf_ptr2StrCharInfo(oldp);
+ vcol = 0;
+ while (vcol < col && *ci.ptr != NUL) {
+ incr = win_charsize(cstype, vcol, ci.ptr, ci.chr.value, &csarg).width;
+ vcol += incr;
+ ci = utfc_next(ci);
}
- vcol = cts.cts_vcol;
- char *ptr = cts.cts_ptr;
+ size_t oldlen = (size_t)(ci.ptr - oldp) + strlen(ci.ptr);
+ char *ptr = ci.ptr;
bd.textcol = (colnr_T)(ptr - oldp);
- clear_chartabsize_arg(&cts);
shortline = (vcol < col) || (vcol == col && !*ptr);
@@ -3311,16 +3264,15 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
yanklen = (int)strlen(y_array[i]);
if ((flags & PUT_BLOCK_INNER) == 0) {
- // calculate number of spaces required to fill right side of
- // block
+ // calculate number of spaces required to fill right side of block
spaces = y_width + 1;
- init_chartabsize_arg(&cts, curwin, 0, 0, y_array[i], y_array[i]);
- for (int j = 0; j < yanklen; j++) {
- spaces -= lbr_chartabsize(&cts);
- cts.cts_ptr++;
- cts.cts_vcol = 0;
+
+ cstype = init_charsize_arg(&csarg, curwin, 0, y_array[i]);
+ ci = utf_ptr2StrCharInfo(y_array[i]);
+ while (*ci.ptr != NUL) {
+ spaces -= win_charsize(cstype, 0, ci.ptr, ci.chr.value, &csarg).width;
+ ci = utfc_next(ci);
}
- clear_chartabsize_arg(&cts);
if (spaces < 0) {
spaces = 0;
}
@@ -3394,13 +3346,11 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
}
curbuf->b_op_end.coladd = 0;
if (flags & PUT_CURSEND) {
- colnr_T len;
-
curwin->w_cursor = curbuf->b_op_end;
curwin->w_cursor.col++;
// in Insert mode we might be after the NUL, correct for that
- len = (colnr_T)strlen(get_cursor_line_ptr());
+ colnr_T len = (colnr_T)strlen(get_cursor_line_ptr());
if (curwin->w_cursor.col > len) {
curwin->w_cursor.col = len;
}
@@ -3583,7 +3533,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
} else if ((indent = get_indent() + indent_diff) < 0) {
indent = 0;
}
- (void)set_indent(indent, SIN_NOMARK);
+ set_indent(indent, SIN_NOMARK);
curwin->w_cursor = old_pos;
// remember how many chars were removed
if (cnt == count && i == y_size - 1) {
@@ -3595,7 +3545,7 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
bcount_t totsize = 0;
int lastsize = 0;
if (y_type == kMTCharWise
- || (y_type == kMTLineWise && flags & PUT_LINE_SPLIT)) {
+ || (y_type == kMTLineWise && (flags & PUT_LINE_SPLIT))) {
for (i = 0; i < y_size - 1; i++) {
totsize += (bcount_t)strlen(y_array[i]) + 1;
}
@@ -3606,9 +3556,9 @@ void do_put(int regname, yankreg_T *reg, int dir, int count, int flags)
extmark_splice(curbuf, (int)new_cursor.lnum - 1, col, 0, 0, 0,
(int)y_size - 1, lastsize, totsize,
kExtmarkUndo);
- } else if (y_type == kMTLineWise && flags & PUT_LINE_SPLIT) {
+ } else if (y_type == kMTLineWise && (flags & PUT_LINE_SPLIT)) {
// Account for last pasted NL + last NL
- extmark_splice(curbuf, (int)new_cursor.lnum - 1, col + 1, 0, 0, 0,
+ extmark_splice(curbuf, (int)new_cursor.lnum - 1, split_pos, 0, 0, 0,
(int)y_size + 1, 0, totsize + 2, kExtmarkUndo);
}
@@ -3750,7 +3700,7 @@ void adjust_cursor_eol(void)
}
/// @return true if lines starting with '#' should be left aligned.
-int preprocs_left(void)
+bool preprocs_left(void)
{
return ((curbuf->b_p_si && !curbuf->b_p_cin)
|| (curbuf->b_p_cin && in_cinkeys('#', ' ', true)
@@ -4010,7 +3960,7 @@ char *skip_comment(char *line, bool process, bool include_space, bool *is_commen
/// to set those marks.
///
/// @return FAIL for failure, OK otherwise
-int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions, bool setmark)
+int do_join(size_t count, bool insert_space, bool save_undo, bool use_formatoptions, bool setmark)
{
char *curr = NULL;
char *curr_start = NULL;
@@ -4021,8 +3971,7 @@ int do_join(size_t count, int insert_space, int save_undo, int use_formatoptions
int sumsize = 0; // size of the long new line
int ret = OK;
int *comments = NULL;
- int remove_comments = (use_formatoptions == true)
- && has_format_option(FO_REMOVE_COMS);
+ bool remove_comments = use_formatoptions && has_format_option(FO_REMOVE_COMS);
bool prev_was_comment = false;
assert(count >= 1);
@@ -4239,7 +4188,7 @@ static void restore_lbr(bool lbr_saved)
/// - textlen includes the first/last char to be wholly yanked
/// - start/endspaces is the number of columns of the first/last yanked char
/// that are to be yanked.
-static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool is_del)
+void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool is_del)
{
int incr = 0;
// Avoid a problem with unwanted linebreaks in block mode.
@@ -4260,25 +4209,25 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool
char *line = ml_get(lnum);
char *prev_pstart = line;
- chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, lnum, bdp->start_vcol, line, line);
- while (cts.cts_vcol < oap->start_vcol && *cts.cts_ptr != NUL) {
- // Count a tab for what it's worth (if list mode not on)
- incr = lbr_chartabsize(&cts);
- cts.cts_vcol += incr;
- if (ascii_iswhite(*cts.cts_ptr)) {
+ CharsizeArg csarg;
+ CSType cstype = init_charsize_arg(&csarg, curwin, lnum, line);
+ StrCharInfo ci = utf_ptr2StrCharInfo(line);
+ int vcol = bdp->start_vcol;
+ while (vcol < oap->start_vcol && *ci.ptr != NUL) {
+ incr = win_charsize(cstype, vcol, ci.ptr, ci.chr.value, &csarg).width;
+ vcol += incr;
+ if (ascii_iswhite(ci.chr.value)) {
bdp->pre_whitesp += incr;
bdp->pre_whitesp_c++;
} else {
bdp->pre_whitesp = 0;
bdp->pre_whitesp_c = 0;
}
- prev_pstart = cts.cts_ptr;
- MB_PTR_ADV(cts.cts_ptr);
+ prev_pstart = ci.ptr;
+ ci = utfc_next(ci);
}
- bdp->start_vcol = cts.cts_vcol;
- char *pstart = cts.cts_ptr;
- clear_chartabsize_arg(&cts);
+ bdp->start_vcol = vcol;
+ char *pstart = ci.ptr;
bdp->start_char_vcols = incr;
if (bdp->start_vcol < oap->start_vcol) { // line too short
@@ -4315,17 +4264,18 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool
}
}
} else {
- init_chartabsize_arg(&cts, curwin, lnum, bdp->end_vcol, line, pend);
+ cstype = init_charsize_arg(&csarg, curwin, lnum, line);
+ ci = utf_ptr2StrCharInfo(pend);
+ vcol = bdp->end_vcol;
char *prev_pend = pend;
- while (cts.cts_vcol <= oap->end_vcol && *cts.cts_ptr != NUL) {
- // Count a tab for what it's worth (if list mode not on)
- prev_pend = cts.cts_ptr;
- incr = lbr_chartabsize_adv(&cts);
- cts.cts_vcol += incr;
+ while (vcol <= oap->end_vcol && *ci.ptr != NUL) {
+ prev_pend = ci.ptr;
+ incr = win_charsize(cstype, vcol, ci.ptr, ci.chr.value, &csarg).width;
+ vcol += incr;
+ ci = utfc_next(ci);
}
- bdp->end_vcol = cts.cts_vcol;
- pend = cts.cts_ptr;
- clear_chartabsize_arg(&cts);
+ bdp->end_vcol = vcol;
+ pend = ci.ptr;
if (bdp->end_vcol <= oap->end_vcol
&& (!is_del
@@ -4361,6 +4311,65 @@ static void block_prep(oparg_T *oap, struct block_def *bdp, linenr_T lnum, bool
restore_lbr(lbr_saved);
}
+/// Get block text from "start" to "end"
+void charwise_block_prep(pos_T start, pos_T end, struct block_def *bdp, linenr_T lnum,
+ bool inclusive)
+{
+ colnr_T startcol = 0;
+ colnr_T endcol = MAXCOL;
+ bool is_oneChar = false;
+ colnr_T cs, ce;
+ char *p = ml_get(lnum);
+ bdp->startspaces = 0;
+ bdp->endspaces = 0;
+
+ if (lnum == start.lnum) {
+ startcol = start.col;
+ if (virtual_op) {
+ getvcol(curwin, &start, &cs, NULL, &ce);
+ if (ce != cs && start.coladd > 0) {
+ // Part of a tab selected -- but don't double-count it.
+ bdp->startspaces = (ce - cs + 1) - start.coladd;
+ if (bdp->startspaces < 0) {
+ bdp->startspaces = 0;
+ }
+ startcol++;
+ }
+ }
+ }
+
+ if (lnum == end.lnum) {
+ endcol = end.col;
+ if (virtual_op) {
+ getvcol(curwin, &end, &cs, NULL, &ce);
+ if (p[endcol] == NUL || (cs + end.coladd < ce
+ // Don't add space for double-wide
+ // char; endcol will be on last byte
+ // of multi-byte char.
+ && utf_head_off(p, p + endcol) == 0)) {
+ if (start.lnum == end.lnum && start.col == end.col) {
+ // Special case: inside a single char
+ is_oneChar = true;
+ bdp->startspaces = end.coladd - start.coladd + inclusive;
+ endcol = startcol;
+ } else {
+ bdp->endspaces = end.coladd + inclusive;
+ endcol -= inclusive;
+ }
+ }
+ }
+ }
+ if (endcol == MAXCOL) {
+ endcol = (colnr_T)strlen(p);
+ }
+ if (startcol > endcol || is_oneChar) {
+ bdp->textlen = 0;
+ } else {
+ bdp->textlen = endcol - startcol + inclusive;
+ }
+ bdp->textstart = p + startcol;
+}
+
/// Handle the add/subtract operator.
///
/// @param[in] oap Arguments of operator.
@@ -4428,7 +4437,7 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
length = oap->end.col - pos.col + 1;
}
}
- int one_change = do_addsub(oap->op_type, &pos, length, amount);
+ bool one_change = do_addsub(oap->op_type, &pos, length, amount);
if (one_change) {
// Remember the start position of the first change.
if (change_cnt == 0) {
@@ -4473,7 +4482,7 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
/// @param Prenum1 Amount of addition or subtraction.
///
/// @return true if some character was changed.
-int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
+bool do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
{
char *buf1 = NULL;
char buf2[NUMBUFLEN];
@@ -4629,7 +4638,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
curwin->w_cursor.col = col;
startpos = curwin->w_cursor;
did_change = true;
- (void)del_char(false);
+ del_char(false);
ins_char(firstdigit);
endpos = curwin->w_cursor;
curwin->w_cursor.col = col;
@@ -4684,13 +4693,13 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
if (!pre) {
if (subtract) {
if (n > oldn) {
- n = 1 + (n ^ (uvarnumber_T) - 1);
+ n = 1 + (n ^ (uvarnumber_T)(-1));
negative ^= true;
}
} else {
// add
if (n < oldn) {
- n = (n ^ (uvarnumber_T) - 1);
+ n = (n ^ (uvarnumber_T)(-1));
negative ^= true;
}
}
@@ -4737,7 +4746,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
}
}
// del_char() will mark line needing displaying
- (void)del_char(false);
+ del_char(false);
c = gchar_cursor();
}
@@ -4948,7 +4957,7 @@ void *get_reg_contents(int regname, int flags)
return get_reg_wrap_one_line(xstrdup(retval), flags);
}
- yankreg_T *reg = get_yank_register(regname, YREG_PASTE);
+ yankreg_T *reg = get_yank_register(regname, YREG_PUT);
if (reg->y_array == NULL) {
return NULL;
}
@@ -5278,16 +5287,16 @@ static varnumber_T line_count_info(char *line, varnumber_T *wc, varnumber_T *cc,
varnumber_T i;
varnumber_T words = 0;
varnumber_T chars = 0;
- int is_word = 0;
+ bool is_word = false;
for (i = 0; i < limit && line[i] != NUL;) {
if (is_word) {
if (ascii_isspace(line[i])) {
words++;
- is_word = 0;
+ is_word = false;
}
} else if (!ascii_isspace(line[i])) {
- is_word = 1;
+ is_word = true;
}
chars++;
i += utfc_ptr2len(line + i);
@@ -5575,7 +5584,7 @@ static void op_colon(oparg_T *oap)
// When using !! on a closed fold the range ".!" works best to operate
// on, it will be made the whole closed fold later.
linenr_T endOfStartFold = oap->start.lnum;
- (void)hasFolding(oap->start.lnum, NULL, &endOfStartFold);
+ hasFolding(oap->start.lnum, NULL, &endOfStartFold);
if (oap->end.lnum != oap->start.lnum && oap->end.lnum != endOfStartFold) {
// Make it a range with the end line.
stuffcharReadbuff(',');
@@ -5794,7 +5803,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
const bool redo_yank = vim_strchr(p_cpo, CPO_YANK) != NULL && !gui_yank;
// Avoid a problem with unwanted linebreaks in block mode
- (void)reset_lbr();
+ reset_lbr();
oap->is_VIsual = VIsual_active;
if (oap->motion_force == 'V') {
oap->motion_type = kMTLineWise;
@@ -6180,7 +6189,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
vim_beep(BO_OPER);
CancelRedo();
} else {
- (void)op_delete(oap);
+ op_delete(oap);
// save cursor line for undo if it wasn't saved yet
if (oap->motion_type == kMTLineWise
&& has_format_option(FO_AUTO)
@@ -6199,7 +6208,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
} else {
restore_lbr(lbr_saved);
oap->excl_tr_ws = cap->cmdchar == 'z';
- (void)op_yank(oap, !gui_yank);
+ op_yank(oap, !gui_yank);
}
check_cursor_col();
break;
@@ -6330,7 +6339,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
op_insert(oap, cap->count1);
// Reset linebreak, so that formatting works correctly.
- (void)reset_lbr();
+ reset_lbr();
// TODO(brammool): when inserting in several lines, should format all
// the lines.
@@ -6404,7 +6413,7 @@ void do_pending_operator(cmdarg_T *cap, int old_col, bool gui_yank)
if (!p_sol && oap->motion_type == kMTLineWise && !oap->end_adjusted
&& (oap->op_type == OP_LSHIFT || oap->op_type == OP_RSHIFT
|| oap->op_type == OP_DELETE)) {
- (void)reset_lbr();
+ reset_lbr();
coladvance(curwin->w_curswant = old_col);
}
} else {
@@ -6534,8 +6543,6 @@ bool prepare_yankreg_from_object(yankreg_T *reg, String regtype, size_t lines)
}
}
- reg->y_array = xcalloc(lines, sizeof(uint8_t *));
- reg->y_size = lines;
reg->additional_data = NULL;
reg->timestamp = 0;
return true;
@@ -6548,7 +6555,6 @@ void finish_yankreg_from_object(yankreg_T *reg, bool clipboard_adjust)
// but otherwise there is no line after the final newline
if (reg->y_type != kMTCharWise) {
if (reg->y_type == kMTUnknown || clipboard_adjust) {
- xfree(reg->y_array[reg->y_size - 1]);
reg->y_size--;
}
if (reg->y_type == kMTUnknown) {
@@ -6734,7 +6740,7 @@ static void set_clipboard(int name, yankreg_T *reg)
tv_list_append_string(args, &regtype, 1);
tv_list_append_string(args, ((char[]) { (char)name }), 1);
- (void)eval_call_provider("clipboard", "set", args, true);
+ eval_call_provider("clipboard", "set", args, true);
}
/// Avoid slow things (clipboard) during batch operations (while/for-loops).
diff --git a/src/nvim/ops.h b/src/nvim/ops.h
index 67a613cbca..1a708fab03 100644
--- a/src/nvim/ops.h
+++ b/src/nvim/ops.h
@@ -15,6 +15,25 @@
#include "nvim/pos_defs.h"
#include "nvim/types_defs.h"
+/// structure used by block_prep, op_delete and op_yank for blockwise operators
+/// also op_change, op_shift, op_insert, op_replace - AKelly
+struct block_def {
+ int startspaces; ///< 'extra' cols before first char
+ int endspaces; ///< 'extra' cols after last char
+ int textlen; ///< chars in block
+ char *textstart; ///< pointer to 1st char (partially) in block
+ colnr_T textcol; ///< index of chars (partially) in block
+ colnr_T start_vcol; ///< start col of 1st char wholly inside block
+ colnr_T end_vcol; ///< start col of 1st char wholly after block
+ int is_short; ///< true if line is too short to fit in block
+ int is_MAX; ///< true if curswant==MAXCOL when starting
+ int is_oneChar; ///< true if block within one character
+ int pre_whitesp; ///< screen cols of ws before block
+ int pre_whitesp_c; ///< chars of ws before block
+ colnr_T end_char_vcols; ///< number of vcols of post-block char
+ colnr_T start_char_vcols; ///< number of vcols of pre-block char
+};
+
typedef int (*Indenter)(void);
/// flags for do_put()
@@ -86,7 +105,7 @@ enum GRegFlags {
};
/// Definition of one register
-typedef struct yankreg {
+typedef struct {
char **y_array; ///< Pointer to an array of line pointers.
size_t y_size; ///< Number of lines in y_array.
MotionType y_type; ///< Register type
@@ -102,13 +121,15 @@ typedef enum {
YREG_PUT,
} yreg_mode_t;
+static inline int op_reg_index(int regname)
+ REAL_FATTR_CONST;
+
/// Convert register name into register index
///
/// @param[in] regname Register name.
///
/// @return Index in y_regs array or -1 if register name was not recognized.
static inline int op_reg_index(const int regname)
- FUNC_ATTR_CONST
{
if (ascii_isdigit(regname)) {
return regname - '0';
@@ -127,11 +148,13 @@ static inline int op_reg_index(const int regname)
}
}
+static inline bool is_literal_register(int regname)
+ REAL_FATTR_CONST;
+
/// @see get_yank_register
/// @return true when register should be inserted literally
/// (selection or clipboard)
static inline bool is_literal_register(const int regname)
- FUNC_ATTR_CONST
{
return regname == '*' || regname == '+';
}
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 96d6d8e01e..0ac65ed95d 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -1,8 +1,7 @@
// User-settable options. Checklist for adding a new option:
// - Put it in options.lua
-// - For a global option: Add a variable for it in option_defs.h.
+// - For a global option: Add a variable for it in option_vars.h.
// - For a buffer or window local option:
-// - Add a BV_XX or WV_XX entry to option_defs.h
// - Add a variable to the window or buffer struct in buffer_defs.h.
// - For a window option, add some code to copy_winopt().
// - For a window string option, add code to check_winopt()
@@ -12,7 +11,7 @@
// - For a buffer string option, add code to check_buf_options().
// - If it's a numeric option, add any necessary bounds checks to check_num_option_bounds().
// - If it's a list of flags, add some code in do_set(), search for WW_ALL.
-// - Add documentation! doc/options.txt, and any other related places.
+// - Add documentation! "desc" in options.lua, and any other related places.
// - Add an entry in runtime/optwin.vim.
#define IN_OPTION_C
@@ -31,29 +30,35 @@
#include "nvim/api/private/helpers.h"
#include "nvim/api/private/validate.h"
#include "nvim/ascii_defs.h"
+#include "nvim/assert_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/change.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
#include "nvim/cmdexpand_defs.h"
#include "nvim/cursor_shape.h"
+#include "nvim/decoration_defs.h"
#include "nvim/decoration_provider.h"
#include "nvim/diff.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/vars.h"
+#include "nvim/eval/window.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/ex_session.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
@@ -63,6 +68,7 @@
#include "nvim/lua/executor.h"
#include "nvim/macros_defs.h"
#include "nvim/mapping.h"
+#include "nvim/math.h"
#include "nvim/mbyte.h"
#include "nvim/memfile.h"
#include "nvim/memline.h"
@@ -79,13 +85,14 @@
#include "nvim/os/input.h"
#include "nvim/os/lang.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
#include "nvim/search.h"
-#include "nvim/sign_defs.h"
#include "nvim/spell.h"
#include "nvim/spellfile.h"
#include "nvim/spellsuggest.h"
@@ -95,7 +102,9 @@
#include "nvim/terminal.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/undo.h"
+#include "nvim/undo_defs.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -109,8 +118,6 @@ static const char e_not_allowed_in_modeline[]
= N_("E520: Not allowed in a modeline");
static const char e_not_allowed_in_modeline_when_modelineexpr_is_off[]
= N_("E992: Not allowed in a modeline when 'modelineexpr' is off");
-static const char e_key_code_not_set[]
- = N_("E846: Key code not set");
static const char e_number_required_after_equal[]
= N_("E521: Number required after =");
static const char e_preview_window_already_exists[]
@@ -146,30 +153,28 @@ typedef enum {
# include "option.c.generated.h"
#endif
-// options[] is initialized here.
-// The order of the options MUST be alphabetic for ":set all" and findoption().
-// All option names MUST start with a lowercase letter (for findoption()).
-// Exception: "t_" options are at the end.
+// options[] is initialized in options.generated.h.
// The options with a NULL variable are 'hidden': a set command for them is
// ignored and they are not printed.
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "options.generated.h"
+# include "options_map.generated.h"
#endif
-static char *(p_bin_dep_opts[]) = {
- "textwidth", "wrapmargin", "modeline", "expandtab", NULL
+static int p_bin_dep_opts[] = {
+ kOptTextwidth, kOptWrapmargin, kOptModeline, kOptExpandtab, kOptInvalid
};
-static char *(p_paste_dep_opts[]) = {
- "autoindent", "expandtab", "ruler", "showmatch", "smarttab",
- "softtabstop", "textwidth", "wrapmargin", "revins", "varsofttabstop", NULL
+
+static int p_paste_dep_opts[] = {
+ kOptAutoindent, kOptExpandtab, kOptRuler, kOptShowmatch, kOptSmarttab, kOptSofttabstop,
+ kOptTextwidth, kOptWrapmargin, kOptRevins, kOptVarsofttabstop, kOptInvalid
};
void set_init_tablocal(void)
{
// susy baka: cmdheight calls itself OPT_GLOBAL but is really tablocal!
- int ch_idx = findoption("cmdheight");
- p_ch = (OptInt)(intptr_t)options[ch_idx].def_val;
+ p_ch = options[kOptCmdheight].def_val.number;
}
/// Initialize the 'shell' option to a default value.
@@ -183,9 +188,9 @@ static void set_init_default_shell(void)
const size_t len = strlen(shell) + 3; // two quotes and a trailing NUL
char *const cmd = xmalloc(len);
snprintf(cmd, len, "\"%s\"", shell);
- set_string_default("sh", cmd, true);
+ set_string_default(kOptShell, cmd, true);
} else {
- set_string_default("sh", (char *)shell, false);
+ set_string_default(kOptShell, (char *)shell, false);
}
}
}
@@ -200,7 +205,7 @@ static void set_init_default_backupskip(void)
static char *(names[3]) = { "TMPDIR", "TEMP", "TMP" };
#endif
garray_T ga;
- int opt_idx = findoption("backupskip");
+ OptIndex opt_idx = kOptBackupskip;
ga_init(&ga, 1, 100);
for (size_t n = 0; n < ARRAY_SIZE(names); n++) {
@@ -214,7 +219,7 @@ static void set_init_default_backupskip(void)
p = "/tmp";
# endif
mustfree = false;
- } else // NOLINT(readability/braces)
+ } else
#endif
{
p = vim_getenv(names[n]);
@@ -244,7 +249,7 @@ static void set_init_default_backupskip(void)
}
}
if (ga.ga_data != NULL) {
- set_string_default("bsk", ga.ga_data, true);
+ set_string_default(kOptBackupskip, ga.ga_data, true);
}
}
@@ -270,13 +275,8 @@ static void set_init_default_cdpath(void)
}
}
buf[j] = NUL;
- int opt_idx = findoption("cdpath");
- if (opt_idx >= 0) {
- options[opt_idx].def_val = buf;
- options[opt_idx].flags |= P_DEF_ALLOCED;
- } else {
- xfree(buf); // cannot happen
- }
+ options[kOptCdpath].def_val.string = buf;
+ options[kOptCdpath].flags |= P_DEF_ALLOCED;
xfree(cdpath);
}
@@ -289,7 +289,7 @@ static void set_init_default_cdpath(void)
/// default.
static void set_init_expand_env(void)
{
- for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
vimoption_T *opt = &options[opt_idx];
if (opt->flags & P_NO_DEF_EXP) {
continue;
@@ -304,9 +304,9 @@ static void set_init_expand_env(void)
p = xstrdup(p);
*(char **)opt->var = p;
if (opt->flags & P_DEF_ALLOCED) {
- xfree(opt->def_val);
+ xfree(opt->def_val.string);
}
- opt->def_val = p;
+ opt->def_val.string = p;
opt->flags |= P_DEF_ALLOCED;
}
}
@@ -347,20 +347,20 @@ void set_init_1(bool clean_arg)
backupdir = xrealloc(backupdir, backupdir_len + 3);
memmove(backupdir + 2, backupdir, backupdir_len + 1);
memmove(backupdir, ".,", 2);
- set_string_default("backupdir", backupdir, true);
- set_string_default("viewdir", stdpaths_user_state_subpath("view", 2, true),
+ set_string_default(kOptBackupdir, backupdir, true);
+ set_string_default(kOptViewdir, stdpaths_user_state_subpath("view", 2, true),
true);
- set_string_default("directory", stdpaths_user_state_subpath("swap", 2, true),
+ set_string_default(kOptDirectory, stdpaths_user_state_subpath("swap", 2, true),
true);
- set_string_default("undodir", stdpaths_user_state_subpath("undo", 2, true),
+ set_string_default(kOptUndodir, stdpaths_user_state_subpath("undo", 2, true),
true);
// Set default for &runtimepath. All necessary expansions are performed in
// this function.
char *rtp = runtimepath_default(clean_arg);
if (rtp) {
- set_string_default("runtimepath", rtp, true);
+ set_string_default(kOptRuntimepath, rtp, true);
// Make a copy of 'rtp' for 'packpath'
- set_string_default("packpath", rtp, false);
+ set_string_default(kOptPackpath, rtp, false);
rtp = NULL; // ownership taken
}
@@ -375,9 +375,6 @@ void set_init_1(bool clean_arg)
check_win_options(curwin);
check_options();
- // Set all options to their default value
- set_options_default(OPT_FREE);
-
// set 'laststatus'
last_status(false);
@@ -399,7 +396,7 @@ void set_init_1(bool clean_arg)
// NOTE: mlterm's author is being asked to 'set' a variable
// instead of an environment variable due to inheritance.
if (os_env_exists("MLTERM")) {
- set_option_value_give_err("tbidi", BOOLEAN_OPTVAL(true), 0);
+ set_option_value_give_err(kOptTermbidi, BOOLEAN_OPTVAL(true), 0);
}
didset_options2();
@@ -420,33 +417,35 @@ void set_init_1(bool clean_arg)
/// Set an option to its default value.
/// This does not take care of side effects!
///
-/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL
-static void set_option_default(const int opt_idx, int opt_flags)
+/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL.
+///
+/// TODO(famiu): Refactor this when def_val uses OptVal.
+static void set_option_default(const OptIndex opt_idx, int opt_flags)
{
- int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
+ bool both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
// pointer to variable for current option
vimoption_T *opt = &options[opt_idx];
void *varp = get_varp_scope(opt, both ? OPT_LOCAL : opt_flags);
uint32_t flags = opt->flags;
if (varp != NULL) { // skip hidden option, nothing to do for it
- if (flags & P_STRING) {
- // Use set_string_option_direct() for local options to handle
- // freeing and allocating the value.
+ if (option_has_type(opt_idx, kOptValTypeString)) {
+ // Use set_string_option_direct() for local options to handle freeing and allocating the
+ // value.
if (opt->indir != PV_NONE) {
- set_string_option_direct(NULL, opt_idx, opt->def_val, opt_flags, 0);
+ set_string_option_direct(opt_idx, opt->def_val.string, opt_flags, 0);
} else {
- if ((opt_flags & OPT_FREE) && (flags & P_ALLOCED)) {
+ if (flags & P_ALLOCED) {
free_string_option(*(char **)(varp));
}
- *(char **)varp = opt->def_val;
+ *(char **)varp = opt->def_val.string;
opt->flags &= ~P_ALLOCED;
}
- } else if (flags & P_NUM) {
+ } else if (option_has_type(opt_idx, kOptValTypeNumber)) {
if (opt->indir == PV_SCROLL) {
win_comp_scroll(curwin);
} else {
- OptInt def_val = (OptInt)(intptr_t)opt->def_val;
+ OptInt def_val = opt->def_val.number;
if ((OptInt *)varp == &curwin->w_p_so
|| (OptInt *)varp == &curwin->w_p_siso) {
// 'scrolloff' and 'sidescrolloff' local values have a
@@ -460,8 +459,8 @@ static void set_option_default(const int opt_idx, int opt_flags)
*(OptInt *)get_varp_scope(opt, OPT_GLOBAL) = def_val;
}
}
- } else { // P_BOOL
- *(int *)varp = (int)(intptr_t)opt->def_val;
+ } else { // boolean
+ *(int *)varp = opt->def_val.boolean;
#ifdef UNIX
// 'modeline' defaults to off for root
if (opt->indir == PV_ML && getuid() == ROOT_UID) {
@@ -480,17 +479,17 @@ static void set_option_default(const int opt_idx, int opt_flags)
*flagsp = *flagsp & ~P_INSECURE;
}
- set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
+ set_option_sctx(opt_idx, opt_flags, current_sctx);
}
/// Set all options (except terminal options) to their default value.
///
-/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL
+/// @param opt_flags Option flags.
static void set_options_default(int opt_flags)
{
- for (int i = 0; options[i].fullname; i++) {
- if (!(options[i].flags & P_NODEFAULT)) {
- set_option_default(i, opt_flags);
+ for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ if (!(options[opt_idx].flags & P_NODEFAULT)) {
+ set_option_default(opt_idx, opt_flags);
}
}
@@ -505,22 +504,23 @@ static void set_options_default(int opt_flags)
/// Set the Vi-default value of a string option.
/// Used for 'sh', 'backupskip' and 'term'.
///
-/// @param name The name of the option
-/// @param val The value of the option
-/// @param allocated If true, do not copy default as it was already allocated.
-static void set_string_default(const char *name, char *val, bool allocated)
+/// @param opt_idx Option index in options[] table.
+/// @param val The value of the option.
+/// @param allocated If true, do not copy default as it was already allocated.
+static void set_string_default(OptIndex opt_idx, char *val, bool allocated)
FUNC_ATTR_NONNULL_ALL
{
- int opt_idx = findoption(name);
- if (opt_idx >= 0) {
- vimoption_T *opt = &options[opt_idx];
- if (opt->flags & P_DEF_ALLOCED) {
- xfree(opt->def_val);
- }
+ if (opt_idx == kOptInvalid) {
+ return;
+ }
- opt->def_val = allocated ? val : xstrdup(val);
- opt->flags |= P_DEF_ALLOCED;
+ vimoption_T *opt = &options[opt_idx];
+ if (opt->flags & P_DEF_ALLOCED) {
+ xfree(opt->def_val.string);
}
+
+ opt->def_val.string = allocated ? val : xstrdup(val);
+ opt->flags |= P_DEF_ALLOCED;
}
/// For an option value that contains comma separated items, find "newval" in
@@ -556,11 +556,10 @@ static char *find_dup_item(char *origval, const char *newval, uint32_t flags)
/// Set the Vi-default value of a number option.
/// Used for 'lines' and 'columns'.
-void set_number_default(char *name, OptInt val)
+void set_number_default(OptIndex opt_idx, OptInt val)
{
- int opt_idx = findoption(name);
- if (opt_idx >= 0) {
- options[opt_idx].def_val = (void *)(intptr_t)val;
+ if (opt_idx != kOptInvalid) {
+ options[opt_idx].def_val.number = val;
}
}
@@ -568,22 +567,25 @@ void set_number_default(char *name, OptInt val)
/// Free all options.
void free_all_options(void)
{
- for (int i = 0; options[i].fullname; i++) {
- if (options[i].indir == PV_NONE) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ if (options[opt_idx].indir == PV_NONE) {
// global option: free value and default value.
- if ((options[i].flags & P_ALLOCED) && options[i].var != NULL) {
- optval_free(optval_from_varp(i, options[i].var));
+ if ((options[opt_idx].flags & P_ALLOCED) && options[opt_idx].var != NULL) {
+ optval_free(optval_from_varp(opt_idx, options[opt_idx].var));
}
- if (options[i].flags & P_DEF_ALLOCED) {
- optval_free(optval_from_varp(i, &options[i].def_val));
+ if (options[opt_idx].flags & P_DEF_ALLOCED) {
+ optval_free(optval_from_varp(opt_idx, &options[opt_idx].def_val));
}
- } else if (options[i].var != VAR_WIN) {
+ } else if (options[opt_idx].var != VAR_WIN) {
// buffer-local option: free global value
- optval_free(optval_from_varp(i, options[i].var));
+ optval_free(optval_from_varp(opt_idx, options[opt_idx].var));
}
}
free_operatorfunc_option();
free_tagfunc_option();
+ XFREE_CLEAR(fenc_default);
+ XFREE_CLEAR(p_term);
+ XFREE_CLEAR(p_ttytype);
}
#endif
@@ -595,18 +597,17 @@ void set_init_2(bool headless)
// 'scroll' defaults to half the window height. The stored default is zero,
// which results in the actual value computed from the window height.
- int idx = findoption("scroll");
- if (idx >= 0 && !(options[idx].flags & P_WAS_SET)) {
- set_option_default(idx, OPT_LOCAL);
+ if (!(options[kOptScroll].flags & P_WAS_SET)) {
+ set_option_default(kOptScroll, OPT_LOCAL);
}
comp_col();
// 'window' is only for backwards compatibility with Vi.
// Default is Rows - 1.
- if (!option_was_set("window")) {
+ if (!option_was_set(kOptWindow)) {
p_window = Rows - 1;
}
- set_number_default("window", Rows - 1);
+ set_number_default(kOptWindow, Rows - 1);
}
/// Initialize the options, part three: After reading the .vimrc
@@ -617,14 +618,8 @@ void set_init_3(void)
// Set 'shellpipe' and 'shellredir', depending on the 'shell' option.
// This is done after other initializations, where 'shell' might have been
// set, but only if they have not been set before.
- int idx_srr = findoption("srr");
- int do_srr = (idx_srr < 0)
- ? false
- : !(options[idx_srr].flags & P_WAS_SET);
- int idx_sp = findoption("sp");
- int do_sp = (idx_sp < 0)
- ? false
- : !(options[idx_sp].flags & P_WAS_SET);
+ bool do_srr = !(options[kOptShellredir].flags & P_WAS_SET);
+ bool do_sp = !(options[kOptShellpipe].flags & P_WAS_SET);
size_t len = 0;
char *p = (char *)invocation_path_tail(p_sh, &len);
@@ -639,11 +634,11 @@ void set_init_3(void)
|| path_fnamecmp(p, "tcsh") == 0) {
if (do_sp) {
p_sp = "|& tee";
- options[idx_sp].def_val = p_sp;
+ options[kOptShellpipe].def_val.string = p_sp;
}
if (do_srr) {
p_srr = ">&";
- options[idx_srr].def_val = p_srr;
+ options[kOptShellredir].def_val.string = p_srr;
}
} else if (path_fnamecmp(p, "sh") == 0
|| path_fnamecmp(p, "ksh") == 0
@@ -658,18 +653,18 @@ void set_init_3(void)
// Always use POSIX shell style redirection if we reach this
if (do_sp) {
p_sp = "2>&1| tee";
- options[idx_sp].def_val = p_sp;
+ options[kOptShellpipe].def_val.string = p_sp;
}
if (do_srr) {
p_srr = ">%s 2>&1";
- options[idx_srr].def_val = p_srr;
+ options[kOptShellredir].def_val.string = p_srr;
}
}
xfree(p);
}
if (buf_is_empty(curbuf)) {
- int idx_ffs = findoption_len(S_LEN("ffs"));
+ int idx_ffs = find_option("ffs");
// Apply the first entry of 'fileformats' to the initial buffer.
if (idx_ffs >= 0 && (options[idx_ffs].flags & P_WAS_SET)) {
@@ -692,12 +687,11 @@ void set_helplang_default(const char *lang)
if (lang_len < 2) { // safety check
return;
}
- int idx = findoption("hlg");
- if (idx < 0 || (options[idx].flags & P_WAS_SET)) {
+ if (options[kOptHelplang].flags & P_WAS_SET) {
return;
}
- if (options[idx].flags & P_ALLOCED) {
+ if (options[kOptHelplang].flags & P_ALLOCED) {
free_string_option(p_hlg);
}
p_hlg = xmemdupz(lang, lang_len);
@@ -711,7 +705,7 @@ void set_helplang_default(const char *lang)
p_hlg[1] = 'n';
}
p_hlg[2] = NUL;
- options[idx].flags |= P_ALLOCED;
+ options[kOptHelplang].flags |= P_ALLOCED;
}
/// 'title' and 'icon' only default to true if they have not been set or reset
@@ -724,15 +718,13 @@ void set_title_defaults(void)
// If GUI is (going to be) used, we can always set the window title and
// icon name. Saves a bit of time, because the X11 display server does
// not need to be contacted.
- int idx1 = findoption("title");
- if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) {
- options[idx1].def_val = 0;
- p_title = 0;
+ if (!(options[kOptTitle].flags & P_WAS_SET)) {
+ options[kOptTitle].def_val.boolean = false;
+ p_title = false;
}
- idx1 = findoption("icon");
- if (idx1 >= 0 && !(options[idx1].flags & P_WAS_SET)) {
- options[idx1].def_val = 0;
- p_icon = 0;
+ if (!(options[kOptIcon].flags & P_WAS_SET)) {
+ options[kOptIcon].def_val.boolean = false;
+ p_icon = false;
}
}
@@ -748,13 +740,13 @@ void ex_set(exarg_T *eap)
if (eap->forceit) {
flags |= OPT_ONECOLUMN;
}
- (void)do_set(eap->arg, flags);
+ do_set(eap->arg, flags);
}
/// Get the default value for a string option.
-static char *stropt_get_default_val(int opt_idx, uint64_t flags)
+static char *stropt_get_default_val(OptIndex opt_idx, uint64_t flags)
{
- char *newval = options[opt_idx].def_val;
+ char *newval = options[opt_idx].def_val.string;
// expand environment variables and ~ since the default value was
// already expanded, only required when an environment variable was set
// later
@@ -773,8 +765,7 @@ static char *stropt_get_default_val(int opt_idx, uint64_t flags)
}
/// Copy the new string value into allocated memory for the option.
-/// Can't use set_string_option_direct(), because we need to remove the
-/// backslashes.
+/// Can't use set_string_option_direct(), because we need to remove the backslashes.
static char *stropt_copy_value(char *origval, char **argp, set_op_T op,
uint32_t flags FUNC_ATTR_UNUSED)
{
@@ -822,7 +813,7 @@ static char *stropt_copy_value(char *origval, char **argp, set_op_T op,
}
/// Expand environment variables and ~ in string option value 'newval'.
-static char *stropt_expand_envvar(int opt_idx, char *origval, char *newval, set_op_T op)
+static char *stropt_expand_envvar(OptIndex opt_idx, char *origval, char *newval, set_op_T op)
{
char *s = option_expand(opt_idx, newval);
if (s == NULL) {
@@ -922,8 +913,8 @@ static void stropt_remove_dupflags(char *newval, uint32_t flags)
/// set {opt}<
/// set {opt}={val}
/// set {opt}:{val}
-static char *stropt_get_newval(int nextchar, int opt_idx, char **argp, void *varp, char *origval,
- set_op_T *op_arg, uint32_t flags)
+static char *stropt_get_newval(int nextchar, OptIndex opt_idx, char **argp, void *varp,
+ char *origval, set_op_T *op_arg, uint32_t flags)
{
char *arg = *argp;
set_op_T op = *op_arg;
@@ -1024,81 +1015,23 @@ static set_prefix_T get_option_prefix(char **argp)
return PREFIX_NONE;
}
-/// @param[in] arg Pointer to start option name
-/// @param[out] opt_idxp Option index in options[] table.
-/// @param[out] keyp
-/// @param[out] len Length of option name
-/// @return FAIL if an error is detected, OK otherwise
-static int parse_option_name(char *arg, int *keyp, int *lenp, int *opt_idxp)
-{
- // find end of name
- int key = 0;
- int len;
- int opt_idx;
-
- if (*arg == '<') {
- opt_idx = -1;
- // look out for <t_>;>
- if (arg[1] == 't' && arg[2] == '_' && arg[3] && arg[4]) {
- len = 5;
- } else {
- len = 1;
- while (arg[len] != NUL && arg[len] != '>') {
- len++;
- }
- }
- if (arg[len] != '>') {
- return FAIL;
- }
- if (arg[1] == 't' && arg[2] == '_') { // could be term code
- opt_idx = findoption_len(arg + 1, (size_t)(len - 1));
- }
- len++;
- if (opt_idx == -1) {
- key = find_key_option(arg + 1, true);
- }
- } else {
- // The two characters after "t_" may not be alphanumeric.
- if (arg[0] == 't' && arg[1] == '_' && arg[2] && arg[3]) {
- len = 4;
- } else {
- len = 0;
- while (ASCII_ISALNUM(arg[len]) || arg[len] == '_') {
- len++;
- }
- }
- opt_idx = findoption_len(arg, (size_t)len);
- if (opt_idx == -1) {
- key = find_key_option(arg, false);
- }
- }
-
- *keyp = key;
- *lenp = len;
- *opt_idxp = opt_idx;
-
- return OK;
-}
-
-static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t flags,
+static int validate_opt_idx(win_T *win, OptIndex opt_idx, int opt_flags, uint32_t flags,
set_prefix_T prefix, const char **errmsg)
{
// Only bools can have a prefix of 'inv' or 'no'
- if (!(flags & P_BOOL) && prefix != PREFIX_NONE) {
+ if (!option_has_type(opt_idx, kOptValTypeBoolean) && prefix != PREFIX_NONE) {
*errmsg = e_invarg;
return FAIL;
}
// Skip all options that are not window-local (used when showing
// an already loaded buffer in a window).
- if ((opt_flags & OPT_WINONLY)
- && (opt_idx < 0 || options[opt_idx].var != VAR_WIN)) {
+ if ((opt_flags & OPT_WINONLY) && (opt_idx == kOptInvalid || options[opt_idx].var != VAR_WIN)) {
return FAIL;
}
// Skip all options that are window-local (used for :vimgrep).
- if ((opt_flags & OPT_NOWIN) && opt_idx >= 0
- && options[opt_idx].var == VAR_WIN) {
+ if ((opt_flags & OPT_NOWIN) && opt_idx != kOptInvalid && options[opt_idx].var == VAR_WIN) {
return FAIL;
}
@@ -1116,7 +1049,7 @@ static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t fla
// 'foldmethod' becomes "marker" instead of "diff" and that
// "wrap" gets set.
if (win->w_p_diff
- && opt_idx >= 0 // shut up coverity warning
+ && opt_idx != kOptInvalid // shut up coverity warning
&& (options[opt_idx].indir == PV_FDM
|| options[opt_idx].indir == PV_WRAP)) {
return FAIL;
@@ -1132,8 +1065,79 @@ static int validate_opt_idx(win_T *win, int opt_idx, int opt_flags, uint32_t fla
return OK;
}
+/// Skip over the name of a TTY option or keycode option.
+///
+/// @param[in] arg Start of TTY or keycode option name.
+///
+/// @return NULL when option isn't a TTY or keycode option. Otherwise pointer to the char after the
+/// option name.
+static const char *find_tty_option_end(const char *arg)
+{
+ if (strequal(arg, "term")) {
+ return arg + sizeof("term") - 1;
+ } else if (strequal(arg, "ttytype")) {
+ return arg + sizeof("ttytype") - 1;
+ }
+
+ const char *p = arg;
+ bool delimit = false; // whether to delimit <
+
+ if (arg[0] == '<') {
+ // look out for <t_>;>
+ delimit = true;
+ p++;
+ }
+ if (p[0] == 't' && p[1] == '_' && p[2] && p[3]) {
+ p += 4;
+ } else if (delimit) {
+ // Search for delimiting >.
+ while (*p != NUL && *p != '>') {
+ p++;
+ }
+ }
+ // Return NULL when delimiting > is not found.
+ if (delimit) {
+ if (*p != '>') {
+ return NULL;
+ }
+ p++;
+ }
+
+ return arg == p ? NULL : p;
+}
+
+/// Skip over the name of an option.
+///
+/// @param[in] arg Start of option name.
+/// @param[out] opt_idxp Set to option index in options[] table.
+///
+/// @return NULL when no option name found. Otherwise pointer to the char after the option name.
+const char *find_option_end(const char *arg, OptIndex *opt_idxp)
+{
+ const char *p;
+
+ // Handle TTY and keycode options separately.
+ if ((p = find_tty_option_end(arg)) != NULL) {
+ *opt_idxp = kOptInvalid;
+ return p;
+ } else {
+ p = arg;
+ }
+
+ if (!ASCII_ISALPHA(*p)) {
+ *opt_idxp = kOptInvalid;
+ return NULL;
+ }
+ while (ASCII_ISALPHA(*p)) {
+ p++;
+ }
+
+ *opt_idxp = find_option_len(arg, (size_t)(p - arg));
+ return p;
+}
+
/// Get new option value from argp. Allocated OptVal must be freed by caller.
-static OptVal get_option_newval(int opt_idx, int opt_flags, set_prefix_T prefix, char **argp,
+static OptVal get_option_newval(OptIndex opt_idx, int opt_flags, set_prefix_T prefix, char **argp,
int nextchar, set_op_T op, uint32_t flags, void *varp, char *errbuf,
const size_t errbuflen, const char **errmsg)
FUNC_ATTR_WARN_UNUSED_RESULT
@@ -1169,7 +1173,7 @@ static OptVal get_option_newval(int opt_idx, int opt_flags, set_prefix_T prefix,
break;
}
} else if (nextchar == '&') {
- newval_bool = TRISTATE_FROM_INT((int)(intptr_t)options[opt_idx].def_val);
+ newval_bool = TRISTATE_FROM_INT(options[opt_idx].def_val.boolean);
} else if (nextchar == '<') {
// For 'autoread', kNone means to use global value.
if ((int *)varp == &curbuf->b_p_ar && opt_flags == OPT_LOCAL) {
@@ -1203,7 +1207,7 @@ static OptVal get_option_newval(int opt_idx, int opt_flags, set_prefix_T prefix,
// other error
arg++;
if (nextchar == '&') {
- newval_num = (OptInt)(intptr_t)options[opt_idx].def_val;
+ newval_num = options[opt_idx].def_val.number;
} else if (nextchar == '<') {
if ((OptInt *)varp == &curbuf->b_p_ul && opt_flags == OPT_LOCAL) {
// for 'undolevels' NO_LOCAL_UNDOLEVEL means using the global newval_num
@@ -1271,61 +1275,56 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
char *arg = *argp;
// find end of name
- int key = 0;
- int len;
- int opt_idx;
- if (parse_option_name(arg, &key, &len, &opt_idx) == FAIL) {
- *errmsg = e_invarg;
+ OptIndex opt_idx;
+ const char *const option_end = find_option_end(arg, &opt_idx);
+
+ if (opt_idx != kOptInvalid) {
+ assert(option_end >= arg);
+ } else if (is_tty_option(arg)) { // Silently ignore TTY options.
+ return;
+ } else { // Invalid option name, skip.
+ *errmsg = e_unknown_option;
return;
}
- // remember character after option name
- int afterchar = (uint8_t)arg[len];
+ // Remember character after option name.
+ uint8_t afterchar = (uint8_t)(*option_end);
+ char *p = (char *)option_end;
- // skip white space, allow ":set ai ?"
- while (ascii_iswhite(arg[len])) {
- len++;
+ // Skip white space, allow ":set ai ?".
+ while (ascii_iswhite(*p)) {
+ p++;
}
- set_op_T op = get_op(arg + len);
+ set_op_T op = get_op(p);
if (op != OP_NONE) {
- len++;
- }
-
- uint8_t nextchar = (uint8_t)arg[len]; // next non-white char after option name
-
- if (opt_idx == -1 && key == 0) { // found a mismatch: skip
- *errmsg = e_unknown_option;
- return;
+ p++;
}
- uint32_t flags; // flags for current option
+ uint8_t nextchar = (uint8_t)(*p); // next non-white char after option name
+ uint32_t flags = 0; // flags for current option
void *varp = NULL; // pointer to variable for current option
- if (opt_idx >= 0) {
- if (options[opt_idx].var == NULL) { // hidden option: skip
- // Only give an error message when requesting the value of
- // a hidden option, ignore setting it.
- if (vim_strchr("=:!&<", nextchar) == NULL
- && (!(options[opt_idx].flags & P_BOOL)
- || nextchar == '?')) {
- *errmsg = e_unsupportedoption;
- }
- return;
+ if (options[opt_idx].var == NULL) { // hidden option: skip
+ // Only give an error message when requesting the value of
+ // a hidden option, ignore setting it.
+ if (vim_strchr("=:!&<", nextchar) == NULL
+ && (!option_has_type(opt_idx, kOptValTypeBoolean) || nextchar == '?')) {
+ *errmsg = e_unsupportedoption;
}
-
- flags = options[opt_idx].flags;
- varp = get_varp_scope(&(options[opt_idx]), opt_flags);
- } else {
- flags = P_STRING;
+ return;
}
+ flags = options[opt_idx].flags;
+ varp = get_varp_scope(&(options[opt_idx]), opt_flags);
+
if (validate_opt_idx(curwin, opt_idx, opt_flags, flags, prefix, errmsg) == FAIL) {
return;
}
if (vim_strchr("?=:!&<", nextchar) != NULL) {
- *argp += len;
+ *argp = p;
+
if (nextchar == '&' && (*argp)[1] == 'v' && (*argp)[2] == 'i') {
if ((*argp)[3] == 'm') { // "opt&vim": set to Vim default
*argp += 3;
@@ -1340,14 +1339,10 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
}
}
- //
- // allow '=' and ':' as MS-DOS command.com allows only one
- // '=' character per "set" command line. grrr. (jw)
- //
+ // Allow '=' and ':' as MS-DOS command.com allows only one '=' character per "set" command line.
if (nextchar == '?'
- || (prefix == PREFIX_NONE
- && vim_strchr("=:&<", nextchar) == NULL
- && !(flags & P_BOOL))) {
+ || (prefix == PREFIX_NONE && vim_strchr("=:&<", nextchar) == NULL
+ && !option_has_type(opt_idx, kOptValTypeBoolean))) {
// print value
if (*did_show) {
msg_putchar('\n'); // cursor below last one
@@ -1355,29 +1350,26 @@ static void do_one_set_option(int opt_flags, char **argp, bool *did_show, char *
gotocmdline(true); // cursor at status line
*did_show = true; // remember that we did a line
}
- if (opt_idx >= 0) {
- showoneopt(&options[opt_idx], opt_flags);
- if (p_verbose > 0) {
- // Mention where the option was last set.
- if (varp == options[opt_idx].var) {
- option_last_set_msg(options[opt_idx].last_set);
- } else if ((int)options[opt_idx].indir & PV_WIN) {
- option_last_set_msg(curwin->w_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
- } else if ((int)options[opt_idx].indir & PV_BUF) {
- option_last_set_msg(curbuf->b_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
- }
+ showoneopt(&options[opt_idx], opt_flags);
+
+ if (p_verbose > 0) {
+ // Mention where the option was last set.
+ if (varp == options[opt_idx].var) {
+ option_last_set_msg(options[opt_idx].last_set);
+ } else if ((int)options[opt_idx].indir & PV_WIN) {
+ option_last_set_msg(curwin->w_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
+ } else if ((int)options[opt_idx].indir & PV_BUF) {
+ option_last_set_msg(curbuf->b_p_script_ctx[(int)options[opt_idx].indir & PV_MASK]);
}
- } else {
- *errmsg = e_key_code_not_set;
- return;
}
+
if (nextchar != '?' && nextchar != NUL && !ascii_iswhite(afterchar)) {
*errmsg = e_trailing;
}
return;
}
- if (flags & P_BOOL) {
+ if (option_has_type(opt_idx, kOptValTypeBoolean)) {
if (vim_strchr("=:", nextchar) != NULL) {
*errmsg = e_invarg;
return;
@@ -1441,7 +1433,7 @@ int do_set(char *arg, int opt_flags)
if (*arg == '&') {
arg++;
// Only for :set command set global value of local options.
- set_options_default(OPT_FREE | opt_flags);
+ set_options_default(opt_flags);
didset_options();
didset_options2();
ui_refresh_options();
@@ -1453,7 +1445,7 @@ int do_set(char *arg, int opt_flags)
} else {
char *startarg = arg; // remember for error message
const char *errmsg = NULL;
- char errbuf[80];
+ char errbuf[ERR_BUFLEN];
do_one_set_option(opt_flags, &arg, &did_show, errbuf, sizeof(errbuf), &errmsg);
@@ -1497,21 +1489,45 @@ int do_set(char *arg, int opt_flags)
if (silent_mode && did_show) {
// After displaying option values in silent mode.
silent_mode = false;
- info_message = true; // use os_msg(), not os_errmsg()
+ info_message = true; // use stdout, not stderr
msg_putchar('\n');
silent_mode = true;
- info_message = false; // use os_msg(), not os_errmsg()
+ info_message = false; // use stdout, not stderr
}
return OK;
}
+// Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
+// When "has_lt" is true there is a '<' before "*arg_arg".
+// Returns 0 when the key is not recognized.
+static int find_key_len(const char *arg_arg, size_t len, bool has_lt)
+{
+ int key = 0;
+ const char *arg = arg_arg;
+
+ // Don't use get_special_key_code() for t_xx, we don't want it to call
+ // add_termcap_entry().
+ if (len >= 4 && arg[0] == 't' && arg[1] == '_') {
+ key = TERMCAP2KEY((uint8_t)arg[2], (uint8_t)arg[3]);
+ } else if (has_lt) {
+ arg--; // put arg at the '<'
+ int modifiers = 0;
+ key = find_special_key(&arg, len + 1, &modifiers, FSK_KEYCODE | FSK_KEEP_X_KEY | FSK_SIMPLIFY,
+ NULL);
+ if (modifiers) { // can't handle modifiers here
+ key = 0;
+ }
+ }
+ return key;
+}
+
/// Convert a key name or string into a key value.
/// Used for 'wildchar' and 'cedit' options.
int string_to_key(char *arg)
{
if (*arg == '<') {
- return find_key_option(arg + 1, true);
+ return find_key_len(arg + 1, strlen(arg), true);
}
if (*arg == '^') {
return CTRL_CHR((uint8_t)arg[1]);
@@ -1623,7 +1639,7 @@ char *find_shada_parameter(int type)
/// These string options cannot be indirect!
/// If "val" is NULL expand the current value of the option.
/// Return pointer to NameBuff, or NULL when not expanded.
-static char *option_expand(int opt_idx, char *val)
+static char *option_expand(OptIndex opt_idx, char *val)
{
// if option doesn't need expansion nothing to do
if (!(options[opt_idx].flags & P_EXPAND) || options[opt_idx].var == NULL) {
@@ -1660,18 +1676,18 @@ static char *option_expand(int opt_idx, char *val)
static void didset_options(void)
{
// initialize the table for 'iskeyword' et.al.
- (void)init_chartab();
+ init_chartab();
didset_string_options();
- (void)spell_check_msm();
- (void)spell_check_sps();
- (void)compile_cap_prog(curwin->w_s);
- (void)did_set_spell_option(true);
+ spell_check_msm();
+ spell_check_sps();
+ compile_cap_prog(curwin->w_s);
+ did_set_spell_option(true);
// set cedit_key
- (void)did_set_cedit(NULL);
+ did_set_cedit(NULL);
// initialize the table for 'breakat'.
- (void)did_set_breakat(NULL);
+ did_set_breakat(NULL);
didset_window_options(curwin, true);
}
@@ -1682,49 +1698,49 @@ static void didset_options2(void)
highlight_changed();
// Parse default for 'fillchars'.
- (void)set_fillchars_option(curwin, curwin->w_p_fcs, true);
+ set_chars_option(curwin, curwin->w_p_fcs, kFillchars, true, NULL, 0);
// Parse default for 'listchars'.
- (void)set_listchars_option(curwin, curwin->w_p_lcs, true);
+ set_chars_option(curwin, curwin->w_p_lcs, kListchars, true, NULL, 0);
// Parse default for 'wildmode'.
check_opt_wim();
xfree(curbuf->b_p_vsts_array);
- (void)tabstop_set(curbuf->b_p_vsts, &curbuf->b_p_vsts_array);
+ tabstop_set(curbuf->b_p_vsts, &curbuf->b_p_vsts_array);
xfree(curbuf->b_p_vts_array);
- (void)tabstop_set(curbuf->b_p_vts, &curbuf->b_p_vts_array);
+ tabstop_set(curbuf->b_p_vts, &curbuf->b_p_vts_array);
}
/// Check for string options that are NULL (normally only termcap options).
void check_options(void)
{
- for (int opt_idx = 0; options[opt_idx].fullname != NULL; opt_idx++) {
- if ((options[opt_idx].flags & P_STRING) && options[opt_idx].var != NULL) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ if ((option_has_type(opt_idx, kOptValTypeString)) && options[opt_idx].var != NULL) {
check_string_option((char **)get_varp(&(options[opt_idx])));
}
}
}
-/// Return true when option "opt" was set from a modeline or in secure mode.
-/// Return false when it wasn't.
-/// Return -1 for an unknown option.
-int was_set_insecurely(win_T *const wp, char *opt, int opt_flags)
+/// Check if option was set insecurely.
+///
+/// @param wp Window.
+/// @param opt_idx Option index in options[] table.
+/// @param opt_flags Option flags.
+///
+/// @return True if option was set from a modeline or in secure mode, false if it wasn't.
+int was_set_insecurely(win_T *const wp, OptIndex opt_idx, int opt_flags)
{
- int idx = findoption(opt);
+ assert(opt_idx != kOptInvalid);
- if (idx >= 0) {
- uint32_t *flagp = insecure_flag(wp, idx, opt_flags);
- return (*flagp & P_INSECURE) != 0;
- }
- internal_error("was_set_insecurely()");
- return -1;
+ uint32_t *flagp = insecure_flag(wp, opt_idx, opt_flags);
+ return (*flagp & P_INSECURE) != 0;
}
/// Get a pointer to the flags used for the P_INSECURE flag of option
/// "opt_idx". For some local options a local flags field is used.
/// NOTE: Caller must make sure that "wp" is set to the window from which
/// the option is used.
-uint32_t *insecure_flag(win_T *const wp, int opt_idx, int opt_flags)
+uint32_t *insecure_flag(win_T *const wp, OptIndex opt_idx, int opt_flags)
{
if (opt_flags & OPT_LOCAL) {
assert(wp != NULL);
@@ -1774,7 +1790,7 @@ bool valid_name(const char *val, const char *allowed)
void check_blending(win_T *wp)
{
wp->w_grid_alloc.blending =
- wp->w_p_winbl > 0 || (wp->w_floating && wp->w_float_config.shadow);
+ wp->w_p_winbl > 0 || (wp->w_floating && wp->w_config.shadow);
}
/// Handle setting `winhighlight' in window "wp"
@@ -1827,23 +1843,18 @@ bool parse_winhl_opt(win_T *wp)
return true;
}
-/// Get the script context of global option "name".
-sctx_T *get_option_sctx(const char *const name)
+/// Get the script context of global option at index opt_idx.
+sctx_T *get_option_sctx(OptIndex opt_idx)
{
- int idx = findoption(name);
-
- if (idx >= 0) {
- return &options[idx].last_set.script_ctx;
- }
- siemsg("no such option: %s", name);
- return NULL;
+ assert(opt_idx != kOptInvalid);
+ return &options[opt_idx].last_set.script_ctx;
}
/// Set the script_ctx for an option, taking care of setting the buffer- or
/// window-local value.
-void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx)
+void set_option_sctx(OptIndex opt_idx, int opt_flags, sctx_T script_ctx)
{
- int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
+ bool both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
int indir = (int)options[opt_idx].indir;
nlua_set_sctx(&script_ctx);
LastSet last_set = {
@@ -1875,7 +1886,7 @@ void set_option_sctx_idx(int opt_idx, int opt_flags, sctx_T script_ctx)
}
/// Apply the OptionSet autocommand.
-static void apply_optionset_autocmd(int opt_idx, int opt_flags, OptVal oldval, OptVal oldval_g,
+static void apply_optionset_autocmd(OptIndex opt_idx, int opt_flags, OptVal oldval, OptVal oldval_g,
OptVal oldval_l, OptVal newval, const char *errmsg)
{
// Don't do this while starting up, failure or recursively.
@@ -1884,10 +1895,10 @@ static void apply_optionset_autocmd(int opt_idx, int opt_flags, OptVal oldval, O
}
char buf_type[7];
- typval_T oldval_tv = optval_as_tv(oldval);
- typval_T oldval_g_tv = optval_as_tv(oldval_g);
- typval_T oldval_l_tv = optval_as_tv(oldval_l);
- typval_T newval_tv = optval_as_tv(newval);
+ typval_T oldval_tv = optval_as_tv(oldval, false);
+ typval_T oldval_g_tv = optval_as_tv(oldval_g, false);
+ typval_T oldval_l_tv = optval_as_tv(oldval_l, false);
+ typval_T newval_tv = optval_as_tv(newval, false);
vim_snprintf(buf_type, sizeof(buf_type), "%s", (opt_flags & OPT_LOCAL) ? "local" : "global");
set_vim_var_tv(VV_OPTION_NEW, &newval_tv);
@@ -1950,7 +1961,7 @@ static const char *did_set_arabic(optset_T *args)
p_deco = true;
// Force-set the necessary keymap for arabic.
- errmsg = set_option_value("keymap", STATIC_CSTR_AS_OPTVAL("arabic"), OPT_LOCAL);
+ errmsg = set_option_value(kOptKeymap, STATIC_CSTR_AS_OPTVAL("arabic"), OPT_LOCAL);
} else {
// 'arabic' is reset, handle various sub-settings.
if (!p_tbidi) {
@@ -1995,22 +2006,6 @@ static const char *did_set_binary(optset_T *args)
return NULL;
}
-/// Called when the 'breakat' option changes value.
-static const char *did_set_breakat(optset_T *args FUNC_ATTR_UNUSED)
-{
- for (int i = 0; i < 256; i++) {
- breakat_flags[i] = false;
- }
-
- if (p_breakat != NULL) {
- for (char *p = p_breakat; *p; p++) {
- breakat_flags[(uint8_t)(*p)] = true;
- }
- }
-
- return NULL;
-}
-
/// Process the updated 'buflisted' option value.
static const char *did_set_buflisted(optset_T *args)
{
@@ -2174,26 +2169,64 @@ static const char *did_set_laststatus(optset_T *args)
// Also clear the cmdline to remove the ruler if there is one
if (value == 3 && old_value != 3) {
frame_new_height(topframe, topframe->fr_height - STATUS_HEIGHT, false, false);
- (void)win_comp_pos();
+ win_comp_pos();
clear_cmdline = true;
}
// When switching from global statusline, increase height of topframe by STATUS_HEIGHT
// in order to to re-add the space that was previously taken by the global statusline
if (old_value == 3 && value != 3) {
frame_new_height(topframe, topframe->fr_height + STATUS_HEIGHT, false, false);
- (void)win_comp_pos();
+ win_comp_pos();
}
last_status(false); // (re)set last window status line.
return NULL;
}
+/// Process the updated 'lines' or 'columns' option value.
+static const char *did_set_lines_or_columns(optset_T *args)
+{
+ // If the screen (shell) height has been changed, assume it is the
+ // physical screenheight.
+ if (p_lines != Rows || p_columns != Columns) {
+ // Changing the screen size is not allowed while updating the screen.
+ if (updating_screen) {
+ OptVal oldval = (OptVal){ .type = kOptValTypeNumber, .data = args->os_oldval };
+ set_option_varp(args->os_idx, args->os_varp, oldval, false);
+ } else if (full_screen) {
+ screen_resize((int)p_columns, (int)p_lines);
+ } else {
+ // TODO(bfredl): is this branch ever needed?
+ // Postpone the resizing; check the size and cmdline position for
+ // messages.
+ Rows = (int)p_lines;
+ Columns = (int)p_columns;
+ check_screensize();
+ int new_row = (int)(Rows - MAX(p_ch, 1));
+ if (cmdline_row > new_row && Rows > p_ch) {
+ assert(p_ch >= 0 && new_row <= INT_MAX);
+ cmdline_row = new_row;
+ }
+ }
+ if (p_window >= Rows || !option_was_set(kOptWindow)) {
+ p_window = Rows - 1;
+ }
+ }
+
+ // Adjust 'scrolljump' if needed.
+ if (p_sj >= Rows && full_screen) {
+ p_sj = Rows / 2;
+ }
+
+ return NULL;
+}
+
/// Process the updated 'lisp' option value.
static const char *did_set_lisp(optset_T *args)
{
buf_T *buf = (buf_T *)args->os_buf;
// When 'lisp' option changes include/exclude '-' in keyword characters.
- (void)buf_init_chartab(buf, false); // ignore errors
+ buf_init_chartab(buf, false); // ignore errors
return NULL;
}
@@ -2334,7 +2367,7 @@ static const char *did_set_paste(optset_T *args FUNC_ATTR_UNUSED)
buf->b_p_vsts = buf->b_p_vsts_nopaste ? xstrdup(buf->b_p_vsts_nopaste) : empty_string_option;
xfree(buf->b_p_vsts_array);
if (buf->b_p_vsts && buf->b_p_vsts != empty_string_option) {
- (void)tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array);
+ tabstop_set(buf->b_p_vsts, &buf->b_p_vsts_array);
} else {
buf->b_p_vsts_array = NULL;
}
@@ -2391,7 +2424,6 @@ static const char *did_set_previewwindow(optset_T *args)
/// Process the new 'pumblend' option value.
static const char *did_set_pumblend(optset_T *args FUNC_ATTR_UNUSED)
{
- p_pb = MAX(MIN(p_pb, 100), 0);
hl_invalidate_blends();
pum_grid.blending = (p_pb > 0);
if (pum_drawn()) {
@@ -2762,231 +2794,224 @@ static void do_spelllang_source(win_T *win)
}
/// Check the bounds of numeric options.
-static const char *check_num_option_bounds(OptInt *pp, OptInt old_value, char *errbuf,
- size_t errbuflen, const char *errmsg)
+///
+/// @param opt_idx Index in options[] table. Must not be kOptInvalid.
+/// @param[in] varp Pointer to option variable.
+/// @param[in,out] newval Pointer to new option value. Will be set to bound checked value.
+/// @param[out] errbuf Buffer for error message. Cannot be NULL.
+/// @param errbuflen Length of error buffer.
+///
+/// @return Error message, if any.
+static const char *check_num_option_bounds(OptIndex opt_idx, void *varp, OptInt *newval,
+ char *errbuf, size_t errbuflen)
+ FUNC_ATTR_NONNULL_ARG(4)
{
- int old_Rows = Rows; // remember old Rows
- // Check the (new) bounds for Rows and Columns here.
- if (p_lines < min_rows() && full_screen) {
- if (errbuf != NULL) {
+ const char *errmsg = NULL;
+
+ switch (opt_idx) {
+ case kOptLines:
+ if (*newval < min_rows() && full_screen) {
vim_snprintf(errbuf, errbuflen, _("E593: Need at least %d lines"), min_rows());
errmsg = errbuf;
+ *newval = min_rows();
}
- p_lines = min_rows();
- }
- if (p_columns < MIN_COLUMNS && full_screen) {
- if (errbuf != NULL) {
+ // True max size is defined by check_screensize().
+ *newval = MIN(*newval, INT_MAX);
+ break;
+ case kOptColumns:
+ if (*newval < MIN_COLUMNS && full_screen) {
vim_snprintf(errbuf, errbuflen, _("E594: Need at least %d columns"), MIN_COLUMNS);
errmsg = errbuf;
+ *newval = MIN_COLUMNS;
}
- p_columns = MIN_COLUMNS;
- }
-
- // True max size is defined by check_screensize()
- p_lines = MIN(p_lines, INT_MAX);
- p_columns = MIN(p_columns, INT_MAX);
-
- // If the screen (shell) height has been changed, assume it is the
- // physical screenheight.
- if (p_lines != Rows || p_columns != Columns) {
- // Changing the screen size is not allowed while updating the screen.
- if (updating_screen) {
- *pp = old_value;
- } else if (full_screen) {
- screen_resize((int)p_columns, (int)p_lines);
- } else {
- // TODO(bfredl): is this branch ever needed?
- // Postpone the resizing; check the size and cmdline position for
- // messages.
- Rows = (int)p_lines;
- Columns = (int)p_columns;
- check_screensize();
- int new_row = (int)(Rows - MAX(p_ch, 1));
- if (cmdline_row > new_row && Rows > p_ch) {
- assert(p_ch >= 0 && new_row <= INT_MAX);
- cmdline_row = new_row;
- }
- }
- if (p_window >= Rows || !option_was_set("window")) {
- p_window = Rows - 1;
+ // True max size is defined by check_screensize().
+ *newval = MIN(*newval, INT_MAX);
+ break;
+ case kOptPumblend:
+ *newval = MAX(MIN(*newval, 100), 0);
+ break;
+ case kOptScrolljump:
+ if ((*newval < -100 || *newval >= Rows) && full_screen) {
+ errmsg = e_scroll;
+ *newval = 1;
}
- }
-
- if ((curwin->w_p_scr <= 0 || (curwin->w_p_scr > curwin->w_height && curwin->w_height > 0))
- && full_screen) {
- if (pp == &(curwin->w_p_scr)) {
- if (curwin->w_p_scr != 0) {
+ break;
+ case kOptScroll:
+ if (varp == &(curwin->w_p_scr)
+ && (*newval <= 0
+ || (*newval > curwin->w_height_inner && curwin->w_height_inner > 0))
+ && full_screen) {
+ if (*newval != 0) {
errmsg = e_scroll;
}
- win_comp_scroll(curwin);
- } else if (curwin->w_p_scr <= 0) {
- // If 'scroll' became invalid because of a side effect silently adjust it.
- curwin->w_p_scr = 1;
- } else { // curwin->w_p_scr > curwin->w_height
- curwin->w_p_scr = curwin->w_height;
- }
- }
- if ((p_sj < -100 || p_sj >= Rows) && full_screen) {
- if (Rows != old_Rows) { // Rows changed, just adjust p_sj
- p_sj = Rows / 2;
- } else {
- errmsg = e_scroll;
- p_sj = 1;
+ *newval = win_default_scroll(curwin);
}
+ break;
+ default:
+ break;
}
return errmsg;
}
-/// Options that need some validation.
-static const char *validate_num_option(const OptInt *pp, OptInt *valuep)
+/// Validate and bound check option value.
+///
+/// @param opt_idx Index in options[] table. Must not be kOptInvalid.
+/// @param[in] varp Pointer to option variable.
+/// @param[in,out] newval Pointer to new option value. Will be set to bound checked value.
+/// @param[out] errbuf Buffer for error message. Cannot be NULL.
+/// @param errbuflen Length of error buffer.
+///
+/// @return Error message, if any.
+static const char *validate_num_option(OptIndex opt_idx, void *varp, OptInt *newval, char *errbuf,
+ size_t errbuflen)
{
- OptInt value = *valuep;
+ OptInt value = *newval;
// Many number options assume their value is in the signed int range.
if (value < INT_MIN || value > INT_MAX) {
return e_invarg;
}
- if (pp == &p_wh) {
+ if (varp == &p_wh) {
if (value < 1) {
return e_positive;
} else if (p_wmh > value) {
return e_winheight;
}
- } else if (pp == &p_hh) {
+ } else if (varp == &p_hh) {
if (value < 0) {
return e_positive;
}
- } else if (pp == &p_wmh) {
+ } else if (varp == &p_wmh) {
if (value < 0) {
return e_positive;
} else if (value > p_wh) {
return e_winheight;
}
- } else if (pp == &p_wiw) {
+ } else if (varp == &p_wiw) {
if (value < 1) {
return e_positive;
} else if (p_wmw > value) {
return e_winwidth;
}
- } else if (pp == &p_wmw) {
+ } else if (varp == &p_wmw) {
if (value < 0) {
return e_positive;
} else if (value > p_wiw) {
return e_winwidth;
}
- } else if (pp == &p_mco) {
- *valuep = MAX_MCO;
- } else if (pp == &p_titlelen) {
+ } else if (varp == &p_mco) {
+ *newval = MAX_MCO;
+ } else if (varp == &p_titlelen) {
if (value < 0) {
return e_positive;
}
- } else if (pp == &p_uc) {
+ } else if (varp == &p_uc) {
if (value < 0) {
return e_positive;
}
- } else if (pp == &p_ch) {
+ } else if (varp == &p_ch) {
if (value < 0) {
return e_positive;
} else {
p_ch_was_zero = value == 0;
}
- } else if (pp == &p_tm) {
+ } else if (varp == &p_tm) {
if (value < 0) {
return e_positive;
}
- } else if (pp == &p_hi) {
+ } else if (varp == &p_hi) {
if (value < 0) {
return e_positive;
} else if (value > 10000) {
return e_invarg;
}
- } else if (pp == &p_pyx) {
+ } else if (varp == &p_pyx) {
if (value == 0) {
- *valuep = 3;
+ *newval = 3;
} else if (value != 3) {
return e_invarg;
}
- } else if (pp == &p_re) {
+ } else if (varp == &p_re) {
if (value < 0 || value > 2) {
return e_invarg;
}
- } else if (pp == &p_report) {
+ } else if (varp == &p_report) {
if (value < 0) {
return e_positive;
}
- } else if (pp == &p_so) {
+ } else if (varp == &p_so) {
if (value < 0 && full_screen) {
return e_positive;
}
- } else if (pp == &p_siso) {
+ } else if (varp == &p_siso) {
if (value < 0 && full_screen) {
return e_positive;
}
- } else if (pp == &p_cwh) {
+ } else if (varp == &p_cwh) {
if (value < 1) {
return e_positive;
}
- } else if (pp == &p_ut) {
+ } else if (varp == &p_ut) {
if (value < 0) {
return e_positive;
}
- } else if (pp == &p_ss) {
+ } else if (varp == &p_ss) {
if (value < 0) {
return e_positive;
}
- } else if (pp == &curwin->w_p_fdl || pp == &curwin->w_allbuf_opt.wo_fdl) {
+ } else if (varp == &curwin->w_p_fdl || varp == &curwin->w_allbuf_opt.wo_fdl) {
if (value < 0) {
return e_positive;
}
- } else if (pp == &curwin->w_p_cole || pp == &curwin->w_allbuf_opt.wo_cole) {
+ } else if (varp == &curwin->w_p_cole || varp == &curwin->w_allbuf_opt.wo_cole) {
if (value < 0) {
return e_positive;
} else if (value > 3) {
return e_invarg;
}
- } else if (pp == &curwin->w_p_nuw || pp == &curwin->w_allbuf_opt.wo_nuw) {
+ } else if (varp == &curwin->w_p_nuw || varp == &curwin->w_allbuf_opt.wo_nuw) {
if (value < 1) {
return e_positive;
} else if (value > MAX_NUMBERWIDTH) {
return e_invarg;
}
- } else if (pp == &curbuf->b_p_iminsert || pp == &p_iminsert) {
+ } else if (varp == &curbuf->b_p_iminsert || varp == &p_iminsert) {
if (value < 0 || value > B_IMODE_LAST) {
return e_invarg;
}
- } else if (pp == &curbuf->b_p_imsearch || pp == &p_imsearch) {
+ } else if (varp == &curbuf->b_p_imsearch || varp == &p_imsearch) {
if (value < -1 || value > B_IMODE_LAST) {
return e_invarg;
}
- } else if (pp == &curbuf->b_p_channel || pp == &p_channel) {
+ } else if (varp == &curbuf->b_p_channel || varp == &p_channel) {
return e_invarg;
- } else if (pp == &curbuf->b_p_scbk || pp == &p_scbk) {
+ } else if (varp == &curbuf->b_p_scbk || varp == &p_scbk) {
if (value < -1 || value > SB_MAX) {
return e_invarg;
}
- } else if (pp == &curbuf->b_p_sw || pp == &p_sw) {
+ } else if (varp == &curbuf->b_p_sw || varp == &p_sw) {
if (value < 0) {
return e_positive;
}
- } else if (pp == &curbuf->b_p_ts || pp == &p_ts) {
+ } else if (varp == &curbuf->b_p_ts || varp == &p_ts) {
if (value < 1) {
return e_positive;
} else if (value > TABSTOP_MAX) {
return e_invarg;
}
- } else if (pp == &curbuf->b_p_tw || pp == &p_tw) {
+ } else if (varp == &curbuf->b_p_tw || varp == &p_tw) {
if (value < 0) {
return e_positive;
}
- } else if (pp == &p_wd) {
+ } else if (varp == &p_wd) {
if (value < 0) {
return e_positive;
}
}
- return NULL;
+ return check_num_option_bounds(opt_idx, varp, newval, errbuf, errbuflen);
}
/// Called after an option changed: check if something needs to be redrawn.
@@ -3004,14 +3029,15 @@ void check_redraw_for(buf_T *buf, win_T *win, uint32_t flags)
}
if ((flags & P_RBUF) || (flags & P_RWIN) || all) {
- changed_window_setting_win(win);
+ if (flags & P_HLONLY) {
+ redraw_later(win, UPD_NOT_VALID);
+ } else {
+ changed_window_setting_win(win);
+ }
}
if (flags & P_RBUF) {
redraw_buf_later(buf, UPD_NOT_VALID);
}
- if (flags & P_RWINONLY) {
- redraw_later(win, UPD_NOT_VALID);
- }
if (all) {
redraw_all_later(UPD_NOT_VALID);
}
@@ -3022,126 +3048,40 @@ void check_redraw(uint32_t flags)
check_redraw_for(curbuf, curwin, flags);
}
-/// Find index for named option
-///
-/// @param[in] arg Option to find index for.
-/// @param[in] len Length of the option.
-///
-/// @return Index of the option or -1 if option was not found.
-int findoption_len(const char *const arg, const size_t len)
-{
- const char *s;
- static int quick_tab[27] = { 0, 0 }; // quick access table
-
- // For first call: Initialize the quick-access table.
- // It contains the index for the first option that starts with a certain
- // letter. There are 26 letters, plus the first "t_" option.
- if (quick_tab[1] == 0) {
- const char *p = options[0].fullname;
- for (uint16_t i = 1; (s = options[i].fullname) != NULL; i++) {
- if (s[0] != p[0]) {
- if (s[0] == 't' && s[1] == '_') {
- quick_tab[26] = i;
- } else {
- quick_tab[CHAR_ORD_LOW(s[0])] = i;
- }
- }
- p = s;
- }
- }
-
- // Check for name starting with an illegal character.
- if (len == 0 || arg[0] < 'a' || arg[0] > 'z') {
- return -1;
- }
-
- int opt_idx;
- const bool is_term_opt = (len > 2 && arg[0] == 't' && arg[1] == '_');
- if (is_term_opt) {
- opt_idx = quick_tab[26];
- } else {
- opt_idx = quick_tab[CHAR_ORD_LOW(arg[0])];
- }
- // Match full name
- for (; (s = options[opt_idx].fullname) != NULL; opt_idx++) {
- if (strncmp(arg, s, len) == 0 && s[len] == NUL) {
- break;
- }
- }
- if (s == NULL && !is_term_opt) {
- opt_idx = quick_tab[CHAR_ORD_LOW(arg[0])];
- // Match short name
- for (; options[opt_idx].fullname != NULL; opt_idx++) {
- s = options[opt_idx].shortname;
- if (s != NULL && strncmp(arg, s, len) == 0 && s[len] == NUL) {
- break;
- }
- s = NULL;
- }
- }
- if (s == NULL) {
- opt_idx = -1;
- } else {
- // Nvim: handle option aliases.
- if (strncmp(options[opt_idx].fullname, "viminfo", 7) == 0) {
- if (strlen(options[opt_idx].fullname) == 7) {
- return findoption_len("shada", 5);
- }
- assert(strcmp(options[opt_idx].fullname, "viminfofile") == 0);
- return findoption_len("shadafile", 9);
- }
- }
- return opt_idx;
-}
-
bool is_tty_option(const char *name)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
- return (name[0] == 't' && name[1] == '_')
- || strequal(name, "term")
- || strequal(name, "ttytype");
+ return find_tty_option_end(name) != NULL;
}
#define TCO_BUFFER_SIZE 8
-/// @param name TUI-related option
-/// @param[out,allocated] value option string value
-bool get_tty_option(const char *name, char **value)
-{
- if (strequal(name, "t_Co")) {
- if (value) {
- if (t_colors <= 1) {
- *value = xstrdup("");
- } else {
- *value = xmalloc(TCO_BUFFER_SIZE);
- snprintf(*value, TCO_BUFFER_SIZE, "%d", t_colors);
- }
- }
- return true;
- }
-
- if (strequal(name, "term")) {
- if (value) {
- *value = p_term ? xstrdup(p_term) : xstrdup("nvim");
- }
- return true;
- }
- if (strequal(name, "ttytype")) {
- if (value) {
- *value = p_ttytype ? xstrdup(p_ttytype) : xstrdup("nvim");
- }
- return true;
- }
+/// Get value of TTY option.
+///
+/// @param name Name of TTY option.
+///
+/// @return [allocated] TTY option value. Returns NIL_OPTVAL if option isn't a TTY option.
+OptVal get_tty_option(const char *name)
+{
+ char *value = NULL;
- if (is_tty_option(name)) {
- if (value) {
- // XXX: All other t_* options were removed in 3baba1e7.
- *value = xstrdup("");
+ if (strequal(name, "t_Co")) {
+ if (t_colors <= 1) {
+ value = xstrdup("");
+ } else {
+ value = xmalloc(TCO_BUFFER_SIZE);
+ snprintf(value, TCO_BUFFER_SIZE, "%d", t_colors);
}
- return true;
+ } else if (strequal(name, "term")) {
+ value = p_term ? xstrdup(p_term) : xstrdup("nvim");
+ } else if (strequal(name, "ttytype")) {
+ value = p_ttytype ? xstrdup(p_ttytype) : xstrdup("nvim");
+ } else if (is_tty_option(name)) {
+ // XXX: All other t_* options were removed in 3baba1e7.
+ value = xstrdup("");
}
- return false;
+ return value == NULL ? NIL_OPTVAL : CSTR_AS_OPTVAL(value);
}
bool set_tty_option(const char *name, char *value)
@@ -3165,15 +3105,28 @@ bool set_tty_option(const char *name, char *value)
return false;
}
-/// Find index for an option
+/// Find index for an option. Don't go beyond `len` length.
+///
+/// @param[in] name Option name.
+/// @param len Option name length.
+///
+/// @return Option index or kOptInvalid if option was not found.
+OptIndex find_option_len(const char *const name, size_t len)
+ FUNC_ATTR_NONNULL_ALL
+{
+ int index = find_option_hash(name, len);
+ return index >= 0 ? option_hash_elems[index].opt_idx : kOptInvalid;
+}
+
+/// Find index for an option.
///
-/// @param[in] arg Option name.
+/// @param[in] name Option name.
///
-/// @return Option index or -1 if option was not found.
-int findoption(const char *const arg)
+/// @return Option index or kOptInvalid if option was not found.
+OptIndex find_option(const char *const name)
FUNC_ATTR_NONNULL_ALL
{
- return findoption_len(arg, strlen(arg));
+ return find_option_len(name, strlen(name));
}
/// Free an allocated OptVal.
@@ -3223,27 +3176,7 @@ bool optval_equal(OptVal o1, OptVal o2)
return o1.data.number == o2.data.number;
case kOptValTypeString:
return o1.data.string.size == o2.data.string.size
- && strequal(o1.data.string.data, o2.data.string.data);
- }
- UNREACHABLE;
-}
-
-/// Match type of OptVal with the type of the target option. Returns true if the types match and
-/// false otherwise.
-static bool optval_match_type(OptVal o, int opt_idx)
-{
- assert(opt_idx >= 0);
- uint32_t flags = options[opt_idx].flags;
-
- switch (o.type) {
- case kOptValTypeNil:
- return false;
- case kOptValTypeBoolean:
- return flags & P_BOOL;
- case kOptValTypeNumber:
- return flags & P_NUM;
- case kOptValTypeString:
- return flags & P_STRING;
+ && strnequal(o1.data.string.data, o2.data.string.data, o1.data.string.size);
}
UNREACHABLE;
}
@@ -3252,7 +3185,9 @@ static bool optval_match_type(OptVal o, int opt_idx)
///
/// @param opt_idx Option index in options[] table.
/// @param[out] varp Pointer to option variable.
-OptVal optval_from_varp(int opt_idx, void *varp)
+///
+/// @return Option value stored in varp.
+OptVal optval_from_varp(OptIndex opt_idx, void *varp)
{
// Special case: 'modified' is b_changed, but we also want to consider it set when 'ff' or 'fenc'
// changed.
@@ -3260,19 +3195,17 @@ OptVal optval_from_varp(int opt_idx, void *varp)
return BOOLEAN_OPTVAL(curbufIsChanged());
}
- uint32_t flags = options[opt_idx].flags;
-
- OptValType type = kOptValTypeNil;
- if (flags & P_BOOL) {
- type = kOptValTypeBoolean;
- } else if (flags & P_NUM) {
- type = kOptValTypeNumber;
- } else if (flags & P_STRING) {
- type = kOptValTypeString;
- } else {
- abort();
+ if (option_is_multitype(opt_idx)) {
+ // Multitype options are stored as OptVal.
+ return varp == NULL ? NIL_OPTVAL : *(OptVal *)varp;
}
+ // If the option only supports a single type, it means that the index of the option's type flag
+ // corresponds to the value of the type enum. So get the index of the type flag using xctz() and
+ // use that as the option's type.
+ OptValType type = xctz(options[opt_idx].type_flags);
+ assert(type > kOptValTypeNil && type < kOptValTypeSize);
+
switch (type) {
case kOptValTypeNil:
return NIL_OPTVAL;
@@ -3286,16 +3219,16 @@ OptVal optval_from_varp(int opt_idx, void *varp)
UNREACHABLE;
}
-/// Set option var pointer value from Optval.
+/// Set option var pointer value from OptVal.
///
/// @param opt_idx Option index in options[] table.
/// @param[out] varp Pointer to option variable.
/// @param[in] value New option value.
/// @param free_oldval Free old value.
-static void set_option_varp(int opt_idx, void *varp, OptVal value, bool free_oldval)
+static void set_option_varp(OptIndex opt_idx, void *varp, OptVal value, bool free_oldval)
FUNC_ATTR_NONNULL_ARG(2)
{
- assert(optval_match_type(value, opt_idx));
+ assert(option_has_type(opt_idx, value.type));
if (free_oldval) {
optval_free(optval_from_varp(opt_idx, varp));
@@ -3303,7 +3236,7 @@ static void set_option_varp(int opt_idx, void *varp, OptVal value, bool free_old
switch (value.type) {
case kOptValTypeNil:
- return;
+ abort();
case kOptValTypeBoolean:
*(int *)varp = value.data.boolean;
return;
@@ -3388,13 +3321,13 @@ OptVal object_as_optval(Object o, bool *error)
/// @param[in] varp Pointer to option variable.
///
/// @return [allocated] Option value equal to the unset value for the option.
-static OptVal optval_unset_local(int opt_idx, void *varp)
+static OptVal optval_unset_local(OptIndex opt_idx, void *varp)
{
vimoption_T *opt = &options[opt_idx];
// For global-local options, use the unset value of the local value.
if (opt->indir & PV_BOTH) {
// String global-local options always use an empty string for the unset value.
- if (opt->flags & P_STRING) {
+ if (option_has_type(opt_idx, kOptValTypeString)) {
return STATIC_CSTR_TO_OPTVAL("");
}
@@ -3410,43 +3343,29 @@ static OptVal optval_unset_local(int opt_idx, void *varp)
}
}
// For options that aren't global-local, just set the local value to the global value.
- return get_option_value(opt->fullname, NULL, OPT_GLOBAL, NULL);
+ return get_option_value(opt_idx, OPT_GLOBAL);
}
/// Get an allocated string containing a list of valid types for an option.
/// For options with a singular type, it returns the name of the type. For options with multiple
/// possible types, it returns a slash separated list of types. For example, if an option can be a
/// number, boolean or string, the function returns "Number/Boolean/String"
-static char *option_get_valid_types(int opt_idx)
+static char *option_get_valid_types(OptIndex opt_idx)
{
- uint32_t flags = options[opt_idx].flags;
- uint32_t type_count = 0;
-
StringBuilder str = KV_INITIAL_VALUE;
kv_resize(str, 32);
-#define OPTION_ADD_TYPE(typename) \
- do { \
- if (type_count == 0) { \
- kv_concat(str, typename); \
- } else { \
- kv_printf(str, "/%s", typename); \
- } \
- type_count++; \
- } while (0);
-
- if (flags & P_NUM) {
- OPTION_ADD_TYPE("Number");
- }
- if (flags & P_BOOL) {
- OPTION_ADD_TYPE("Boolean");
- }
- if (flags & P_STRING) {
- OPTION_ADD_TYPE("String");
- }
+ // Iterate through every valid option value type and check if the option supports that type
+ for (OptValType type = 0; type < kOptValTypeSize; type++) {
+ if (option_has_type(opt_idx, type)) {
+ const char *typename = optval_type_get_name(type);
- if (type_count == 0) {
- abort();
+ if (str.size == 0) {
+ kv_concat(str, typename);
+ } else {
+ kv_printf(str, "/%s", typename);
+ }
+ }
}
// Ensure that the string is NUL-terminated.
@@ -3456,52 +3375,48 @@ static char *option_get_valid_types(int opt_idx)
#undef OPTION_ADD_TYPE
}
-/// Gets the value for an option.
+/// Check if option is hidden.
///
-/// @param[in] name Option name.
-/// @param[out] flagsp Set to the option flags (P_xxxx) (if not NULL).
-/// @param[in] scope Option scope (can be OPT_LOCAL, OPT_GLOBAL or a combination).
-/// @param[out] hidden Whether option is hidden.
+/// @param opt_idx Option index in options[] table.
///
-/// @return [allocated] Option value. Returns NIL_OPTVAL for invalid options.
-OptVal get_option_value(const char *name, uint32_t *flagsp, int scope, bool *hidden)
+/// @return True if option is hidden, false otherwise. Returns false if option name is invalid.
+bool is_option_hidden(OptIndex opt_idx)
{
- // Make sure that hidden and flagsp are never returned uninitialized
- if (hidden != NULL) {
- *hidden = false;
- }
- if (flagsp != NULL) {
- *flagsp = 0;
- }
+ return opt_idx == kOptInvalid ? false : get_varp(&options[opt_idx]) == NULL;
+}
- char *str;
- if (get_tty_option(name, &str)) {
- return CSTR_AS_OPTVAL(str);
- }
+/// Get option flags.
+///
+/// @param opt_idx Option index in options[] table.
+///
+/// @return Option flags. Returns 0 for invalid option name.
+uint32_t get_option_flags(OptIndex opt_idx)
+{
+ return opt_idx == kOptInvalid ? 0 : options[opt_idx].flags;
+}
- int opt_idx = findoption(name);
- if (opt_idx < 0) { // option not in the table
+/// Gets the value for an option.
+///
+/// @param opt_idx Option index in options[] table.
+/// @param[in] scope Option scope (can be OPT_LOCAL, OPT_GLOBAL or a combination).
+///
+/// @return [allocated] Option value. Returns NIL_OPTVAL for invalid option index.
+OptVal get_option_value(OptIndex opt_idx, int scope)
+{
+ if (opt_idx == kOptInvalid) { // option not in the options[] table.
return NIL_OPTVAL;
}
vimoption_T *opt = &options[opt_idx];
void *varp = get_varp_scope(opt, scope);
- if (hidden != NULL) {
- *hidden = varp == NULL;
- }
-
- if (flagsp != NULL) {
- // Return the P_xxxx option flags.
- *flagsp = opt->flags;
- }
-
return optval_copy(optval_from_varp(opt_idx, varp));
}
/// Return information for option at 'opt_idx'
-vimoption_T *get_option(int opt_idx)
+vimoption_T *get_option(OptIndex opt_idx)
{
+ assert(opt_idx != kOptInvalid);
return &options[opt_idx];
}
@@ -3527,7 +3442,7 @@ static bool is_option_local_value_unset(vimoption_T *opt, buf_T *buf, win_T *win
/// Handle side-effects of setting an option.
///
-/// @param opt_idx Index in options[] table. Must be >= 0.
+/// @param opt_idx Index in options[] table. Must not be kOptInvalid.
/// @param[in] varp Option variable pointer, cannot be NULL.
/// @param old_value Old option value.
/// @param new_value New option value.
@@ -3538,9 +3453,10 @@ static bool is_option_local_value_unset(vimoption_T *opt, buf_T *buf, win_T *win
/// @param errbuflen Length of error buffer.
///
/// @return NULL on success, an untranslated error message on error.
-static const char *did_set_option(int opt_idx, void *varp, OptVal old_value, OptVal new_value,
+static const char *did_set_option(OptIndex opt_idx, void *varp, OptVal old_value, OptVal new_value,
int opt_flags, bool *value_checked, bool value_replaced,
- char *errbuf, size_t errbuflen)
+ char *errbuf, // NOLINT(readability-non-const-parameter)
+ size_t errbuflen)
{
vimoption_T *opt = &options[opt_idx];
const char *errmsg = NULL;
@@ -3593,7 +3509,7 @@ static const char *did_set_option(int opt_idx, void *varp, OptVal old_value, Opt
set_option_varp(opt_idx, varp, old_value, true);
// When resetting some values, need to act on it.
if (restore_chartab) {
- (void)buf_init_chartab(curbuf, true);
+ buf_init_chartab(curbuf, true);
}
// Unset new_value as it is no longer valid.
@@ -3605,7 +3521,7 @@ static const char *did_set_option(int opt_idx, void *varp, OptVal old_value, Opt
new_value = optval_from_varp(opt_idx, varp);
// Remember where the option was set.
- set_option_sctx_idx(opt_idx, opt_flags, current_sctx);
+ set_option_sctx(opt_idx, opt_flags, current_sctx);
// Free options that are in allocated memory.
// Use "free_oldval", because recursiveness may change the flags (esp. init_highlight()).
if (free_oldval) {
@@ -3613,14 +3529,6 @@ static const char *did_set_option(int opt_idx, void *varp, OptVal old_value, Opt
}
opt->flags |= P_ALLOCED;
- // Check the bound for num options.
- if (new_value.type == kOptValTypeNumber) {
- errmsg = check_num_option_bounds((OptInt *)varp, old_value.data.number, errbuf, errbuflen,
- errmsg);
- // Re-assign new_value because the new value was modified by the bound check.
- new_value = optval_from_varp(opt_idx, varp);
- }
-
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0 && (opt->indir & PV_BOTH)) {
// Global option with local value set to use global value.
// Free the local value and clear it.
@@ -3647,7 +3555,7 @@ static const char *did_set_option(int opt_idx, void *varp, OptVal old_value, Opt
do_spelllang_source(curwin);
}
- // In case 'columns' or 'ls' changed.
+ // In case 'ruler' or 'showcmd' or 'columns' or 'ls' changed.
comp_col();
if (varp == &p_mouse) {
@@ -3661,7 +3569,8 @@ static const char *did_set_option(int opt_idx, void *varp, OptVal old_value, Opt
set_winbar(true);
}
- if (curwin->w_curswant != MAXCOL && (opt->flags & (P_CURSWANT | P_RALL)) != 0) {
+ if (curwin->w_curswant != MAXCOL
+ && (opt->flags & (P_CURSWANT | P_RALL)) != 0 && (opt->flags & P_HLONLY) == 0) {
curwin->w_set_curswant = true;
}
@@ -3685,7 +3594,7 @@ static const char *did_set_option(int opt_idx, void *varp, OptVal old_value, Opt
/// Set the value of an option using an OptVal.
///
-/// @param opt_idx Index in options[] table. Must be >= 0.
+/// @param opt_idx Index in options[] table. Must not be kOptInvalid.
/// @param[in] varp Option variable pointer, cannot be NULL.
/// @param value New option value. Might get freed.
/// @param opt_flags Option flags.
@@ -3694,23 +3603,16 @@ static const char *did_set_option(int opt_idx, void *varp, OptVal old_value, Opt
/// @param errbuflen Length of error buffer.
///
/// @return NULL on success, an untranslated error message on error.
-static const char *set_option(const int opt_idx, void *varp, OptVal value, int opt_flags,
+static const char *set_option(const OptIndex opt_idx, void *varp, OptVal value, int opt_flags,
const bool value_replaced, char *errbuf, size_t errbuflen)
{
- assert(opt_idx >= 0 && varp != NULL);
+ assert(opt_idx != kOptInvalid && varp != NULL);
const char *errmsg = NULL;
bool value_checked = false;
vimoption_T *opt = &options[opt_idx];
- static const char *optval_type_names[] = {
- [kOptValTypeNil] = "Nil",
- [kOptValTypeBoolean] = "Boolean",
- [kOptValTypeNumber] = "Number",
- [kOptValTypeString] = "String"
- };
-
if (value.type == kOptValTypeNil) {
// Don't try to unset local value if scope is global.
// TODO(famiu): Change this to forbid changing all non-local scopes when the API scope bug is
@@ -3721,11 +3623,11 @@ static const char *set_option(const int opt_idx, void *varp, OptVal value, int o
optval_free(value);
value = optval_unset_local(opt_idx, varp);
}
- } else if (!optval_match_type(value, opt_idx)) {
+ } else if (!option_has_type(opt_idx, value.type)) {
char *rep = optval_to_cstr(value);
char *valid_types = option_get_valid_types(opt_idx);
snprintf(errbuf, IOSIZE, _("Invalid value for option '%s': expected %s, got %s %s"),
- opt->fullname, valid_types, optval_type_names[value.type], rep);
+ opt->fullname, valid_types, optval_type_get_name(value.type), rep);
xfree(rep);
xfree(valid_types);
errmsg = errbuf;
@@ -3767,9 +3669,7 @@ static const char *set_option(const int opt_idx, void *varp, OptVal value, int o
OptVal used_old_value = oldval_is_global ? optval_from_varp(opt_idx, get_varp(opt)) : old_value;
if (value.type == kOptValTypeNumber) {
- errmsg = validate_num_option((OptInt *)varp, &value.data.number);
-
- // Don't change the value and return early if validation failed.
+ errmsg = validate_num_option(opt_idx, varp, &value.data.number, errbuf, errbuflen);
if (errmsg != NULL) {
goto err;
}
@@ -3825,29 +3725,20 @@ err:
return errmsg;
}
-/// Set the value of an option
+/// Set the value of an option.
///
-/// @param[in] name Option name.
+/// @param opt_idx Index in options[] table. Must not be kOptInvalid.
/// @param[in] value Option value. If NIL_OPTVAL, the option value is cleared.
/// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both).
///
/// @return NULL on success, an untranslated error message on error.
-const char *set_option_value(const char *const name, const OptVal value, int opt_flags)
- FUNC_ATTR_NONNULL_ARG(1)
+const char *set_option_value(const OptIndex opt_idx, const OptVal value, int opt_flags)
{
- static char errbuf[IOSIZE];
-
- if (is_tty_option(name)) {
- return NULL; // Fail silently; many old vimrcs set t_xx options.
- }
-
- int opt_idx = findoption(name);
- if (opt_idx < 0) {
- snprintf(errbuf, IOSIZE, _(e_unknown_option2), name);
- return errbuf;
- }
+ assert(opt_idx != kOptInvalid);
+ static char errbuf[IOSIZE];
uint32_t flags = options[opt_idx].flags;
+
// Disallow changing some options in the sandbox
if (sandbox > 0 && (flags & P_SECURE)) {
return _(e_sandbox);
@@ -3859,58 +3750,283 @@ const char *set_option_value(const char *const name, const OptVal value, int opt
return NULL;
}
- const char *errmsg = NULL;
+ return set_option(opt_idx, varp, optval_copy(value), opt_flags, true, errbuf, sizeof(errbuf));
+}
- errmsg = set_option(opt_idx, varp, optval_copy(value), opt_flags, true, errbuf, sizeof(errbuf));
+/// Set the value of an option. Supports TTY options, unlike set_option_value().
+///
+/// @param name Option name. Used for error messages and for setting TTY options.
+/// @param opt_idx Option indx in options[] table. If kOptInvalid, `name` is used to
+/// check if the option is a TTY option, and an error is shown if it's not.
+/// If the option is a TTY option, the function fails silently.
+/// @param value Option value. If NIL_OPTVAL, the option value is cleared.
+/// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both).
+///
+/// @return NULL on success, an untranslated error message on error.
+const char *set_option_value_handle_tty(const char *name, OptIndex opt_idx, const OptVal value,
+ int opt_flags)
+ FUNC_ATTR_NONNULL_ARG(1)
+{
+ static char errbuf[IOSIZE];
- return errmsg;
+ if (opt_idx == kOptInvalid) {
+ if (is_tty_option(name)) {
+ return NULL; // Fail silently; many old vimrcs set t_xx options.
+ }
+
+ snprintf(errbuf, sizeof(errbuf), _(e_unknown_option2), name);
+ return errbuf;
+ }
+
+ return set_option_value(opt_idx, value, opt_flags);
}
-/// Call set_option_value() and when an error is returned report it.
+/// Call set_option_value() and when an error is returned, report it.
///
-/// @param opt_flags OPT_LOCAL or 0 (both)
-void set_option_value_give_err(const char *name, OptVal value, int opt_flags)
+/// @param opt_idx Option index in options[] table.
+/// @param value Option value. If NIL_OPTVAL, the option value is cleared.
+/// @param opt_flags OPT_LOCAL or 0 (both)
+void set_option_value_give_err(const OptIndex opt_idx, OptVal value, int opt_flags)
{
- const char *errmsg = set_option_value(name, value, opt_flags);
+ const char *errmsg = set_option_value(opt_idx, value, opt_flags);
if (errmsg != NULL) {
emsg(_(errmsg));
}
}
-bool is_option_allocated(const char *name)
+/// Switch current context to get/set option value for window/buffer.
+///
+/// @param[out] ctx Current context. switchwin_T for window and aco_save_T for buffer.
+/// @param req_scope Requested option scope. See OptReqScope in option.h.
+/// @param[in] from Target buffer/window.
+/// @param[out] err Error message, if any.
+///
+/// @return true if context was switched, false otherwise.
+static bool switch_option_context(void *const ctx, OptReqScope req_scope, void *const from,
+ Error *err)
{
- int idx = findoption(name);
- return idx >= 0 && (options[idx].flags & P_ALLOCED);
+ switch (req_scope) {
+ case kOptReqWin: {
+ win_T *const win = (win_T *)from;
+ switchwin_T *const switchwin = (switchwin_T *)ctx;
+
+ if (win == curwin) {
+ return false;
+ }
+
+ if (switch_win_noblock(switchwin, win, win_find_tabpage(win), true)
+ == FAIL) {
+ restore_win_noblock(switchwin, true);
+
+ if (try_end(err)) {
+ return false;
+ }
+ api_set_error(err, kErrorTypeException, "Problem while switching windows");
+ return false;
+ }
+ return true;
+ }
+ case kOptReqBuf: {
+ buf_T *const buf = (buf_T *)from;
+ aco_save_T *const aco = (aco_save_T *)ctx;
+
+ if (buf == curbuf) {
+ return false;
+ }
+ aucmd_prepbuf(aco, buf);
+ return true;
+ }
+ case kOptReqGlobal:
+ return false;
+ }
+ UNREACHABLE;
}
-// Translate a string like "t_xx", "<t_xx>" or "<S-Tab>" to a key number.
-// When "has_lt" is true there is a '<' before "*arg_arg".
-// Returns 0 when the key is not recognized.
-int find_key_option_len(const char *arg_arg, size_t len, bool has_lt)
+/// Restore context after getting/setting option for window/buffer. See switch_option_context() for
+/// params.
+static void restore_option_context(void *const ctx, OptReqScope req_scope)
{
- int key = 0;
- const char *arg = arg_arg;
+ switch (req_scope) {
+ case kOptReqWin:
+ restore_win_noblock((switchwin_T *)ctx, true);
+ break;
+ case kOptReqBuf:
+ aucmd_restbuf((aco_save_T *)ctx);
+ break;
+ case kOptReqGlobal:
+ break;
+ }
+}
- // Don't use get_special_key_code() for t_xx, we don't want it to call
- // add_termcap_entry().
- if (len >= 4 && arg[0] == 't' && arg[1] == '_') {
- key = TERMCAP2KEY((uint8_t)arg[2], (uint8_t)arg[3]);
- } else if (has_lt) {
- arg--; // put arg at the '<'
- int modifiers = 0;
- key = find_special_key(&arg, len + 1, &modifiers,
- FSK_KEYCODE | FSK_KEEP_X_KEY | FSK_SIMPLIFY, NULL);
- if (modifiers) { // can't handle modifiers here
- key = 0;
- }
+/// Get attributes for an option.
+///
+/// @param opt_idx Option index in options[] table.
+///
+/// @return Option attributes.
+/// 0 for hidden or unknown option.
+/// See SOPT_* in option_defs.h for other flags.
+int get_option_attrs(OptIndex opt_idx)
+{
+ if (opt_idx == kOptInvalid) {
+ return 0;
}
- return key;
+
+ vimoption_T *opt = get_option(opt_idx);
+
+ // Hidden option
+ if (opt->var == NULL) {
+ return 0;
+ }
+
+ int attrs = 0;
+
+ if (opt->indir == PV_NONE || (opt->indir & PV_BOTH)) {
+ attrs |= SOPT_GLOBAL;
+ }
+ if (opt->indir & PV_WIN) {
+ attrs |= SOPT_WIN;
+ } else if (opt->indir & PV_BUF) {
+ attrs |= SOPT_BUF;
+ }
+
+ return attrs;
+}
+
+/// Check if option has a value in the requested scope.
+///
+/// @param opt_idx Option index in options[] table.
+/// @param req_scope Requested option scope. See OptReqScope in option.h.
+///
+/// @return true if option has a value in the requested scope, false otherwise.
+static bool option_has_scope(OptIndex opt_idx, OptReqScope req_scope)
+{
+ if (opt_idx == kOptInvalid) {
+ return false;
+ }
+
+ vimoption_T *opt = get_option(opt_idx);
+
+ // Hidden option.
+ if (opt->var == NULL) {
+ return false;
+ }
+ // TTY option.
+ if (is_tty_option(opt->fullname)) {
+ return req_scope == kOptReqGlobal;
+ }
+
+ switch (req_scope) {
+ case kOptReqGlobal:
+ return opt->var != VAR_WIN;
+ case kOptReqBuf:
+ return opt->indir & PV_BUF;
+ case kOptReqWin:
+ return opt->indir & PV_WIN;
+ }
+ UNREACHABLE;
+}
+
+/// Get the option value in the requested scope.
+///
+/// @param opt_idx Option index in options[] table.
+/// @param req_scope Requested option scope. See OptReqScope in option.h.
+/// @param[in] from Pointer to buffer or window for local option value.
+/// @param[out] err Error message, if any.
+///
+/// @return Option value in the requested scope. Returns a Nil option value if option is not found,
+/// hidden or if it isn't present in the requested scope. (i.e. has no global, window-local or
+/// buffer-local value depending on opt_scope).
+OptVal get_option_value_strict(OptIndex opt_idx, OptReqScope req_scope, void *from, Error *err)
+{
+ if (opt_idx == kOptInvalid || !option_has_scope(opt_idx, req_scope)) {
+ return NIL_OPTVAL;
+ }
+
+ vimoption_T *opt = get_option(opt_idx);
+ switchwin_T switchwin;
+ aco_save_T aco;
+ void *ctx = req_scope == kOptReqWin ? (void *)&switchwin
+ : (req_scope == kOptReqBuf ? (void *)&aco : NULL);
+ bool switched = switch_option_context(ctx, req_scope, from, err);
+ if (ERROR_SET(err)) {
+ return NIL_OPTVAL;
+ }
+
+ char *varp = get_varp_scope(opt, req_scope == kOptReqGlobal ? OPT_GLOBAL : OPT_LOCAL);
+ OptVal retv = optval_from_varp(opt_idx, varp);
+
+ if (switched) {
+ restore_option_context(ctx, req_scope);
+ }
+
+ return retv;
+}
+
+/// Get option value for buffer / window.
+///
+/// @param opt_idx Option index in options[] table.
+/// @param[out] flagsp Set to the option flags (P_xxxx) (if not NULL).
+/// @param[in] scope Option scope (can be OPT_LOCAL, OPT_GLOBAL or a combination).
+/// @param[out] hidden Whether option is hidden.
+/// @param req_scope Requested option scope. See OptReqScope in option.h.
+/// @param[in] from Target buffer/window.
+/// @param[out] err Error message, if any.
+///
+/// @return Option value. Must be freed by caller.
+OptVal get_option_value_for(OptIndex opt_idx, int scope, const OptReqScope req_scope,
+ void *const from, Error *err)
+{
+ switchwin_T switchwin;
+ aco_save_T aco;
+ void *ctx = req_scope == kOptReqWin ? (void *)&switchwin
+ : (req_scope == kOptReqBuf ? (void *)&aco : NULL);
+
+ bool switched = switch_option_context(ctx, req_scope, from, err);
+ if (ERROR_SET(err)) {
+ return NIL_OPTVAL;
+ }
+
+ OptVal retv = get_option_value(opt_idx, scope);
+
+ if (switched) {
+ restore_option_context(ctx, req_scope);
+ }
+
+ return retv;
}
-static int find_key_option(const char *arg, bool has_lt)
+/// Set option value for buffer / window.
+///
+/// @param name Option name.
+/// @param opt_idx Option index in options[] table.
+/// @param[in] value Option value.
+/// @param[in] opt_flags Flags: OPT_LOCAL, OPT_GLOBAL, or 0 (both).
+/// @param req_scope Requested option scope. See OptReqScope in option.h.
+/// @param[in] from Target buffer/window.
+/// @param[out] err Error message, if any.
+void set_option_value_for(const char *name, OptIndex opt_idx, OptVal value, const int opt_flags,
+ const OptReqScope req_scope, void *const from, Error *err)
+ FUNC_ATTR_NONNULL_ARG(1)
{
- return find_key_option_len(arg, strlen(arg), has_lt);
+ switchwin_T switchwin;
+ aco_save_T aco;
+ void *ctx = req_scope == kOptReqWin ? (void *)&switchwin
+ : (req_scope == kOptReqBuf ? (void *)&aco : NULL);
+
+ bool switched = switch_option_context(ctx, req_scope, from, err);
+ if (ERROR_SET(err)) {
+ return;
+ }
+
+ const char *const errmsg = set_option_value_handle_tty(name, opt_idx, value, opt_flags);
+ if (errmsg) {
+ api_set_error(err, kErrorTypeException, "%s", errmsg);
+ }
+
+ if (switched) {
+ restore_option_context(ctx, req_scope);
+ }
}
/// if 'all' == false: show changed options
@@ -3940,33 +4056,35 @@ static void showoptions(bool all, int opt_flags)
for (int run = 1; run <= 2 && !got_int; run++) {
// collect the items in items[]
int item_count = 0;
- for (vimoption_T *p = &options[0]; p->fullname != NULL; p++) {
+ vimoption_T *opt;
+ for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ opt = &options[opt_idx];
// apply :filter /pat/
- if (message_filtered(p->fullname)) {
+ if (message_filtered(opt->fullname)) {
continue;
}
void *varp = NULL;
if ((opt_flags & (OPT_LOCAL | OPT_GLOBAL)) != 0) {
- if (p->indir != PV_NONE) {
- varp = get_varp_scope(p, opt_flags);
+ if (opt->indir != PV_NONE) {
+ varp = get_varp_scope(opt, opt_flags);
}
} else {
- varp = get_varp(p);
+ varp = get_varp(opt);
}
- if (varp != NULL && (all || !optval_default(p, varp))) {
+ if (varp != NULL && (all || !optval_default(opt_idx, varp))) {
int len;
if (opt_flags & OPT_ONECOLUMN) {
len = Columns;
- } else if (p->flags & P_BOOL) {
+ } else if (option_has_type(opt_idx, kOptValTypeBoolean)) {
len = 1; // a toggle option fits always
} else {
- option_value2string(p, opt_flags);
- len = (int)strlen(p->fullname) + vim_strsize(NameBuff) + 1;
+ option_value2string(opt, opt_flags);
+ len = (int)strlen(opt->fullname) + vim_strsize(NameBuff) + 1;
}
if ((len <= INC - GAP && run == 1)
|| (len > INC - GAP && run == 2)) {
- items[item_count++] = p;
+ items[item_count++] = opt;
}
}
}
@@ -4005,40 +4123,31 @@ static void showoptions(bool all, int opt_flags)
}
/// Return true if option "p" has its default value.
-static int optval_default(vimoption_T *p, const void *varp)
+static int optval_default(OptIndex opt_idx, void *varp)
{
- if (varp == NULL) {
- return true; // hidden option is always at default
- }
- if (p->flags & P_NUM) {
- return *(OptInt *)varp == (OptInt)(intptr_t)p->def_val;
- }
- if (p->flags & P_BOOL) {
- return *(int *)varp == (int)(intptr_t)p->def_val;
+ vimoption_T *opt = &options[opt_idx];
+
+ // Hidden or immutable options always use their default value.
+ if (varp == NULL || opt->immutable) {
+ return true;
}
- // P_STRING
- return strcmp(*(char **)varp, p->def_val) == 0;
+
+ OptVal current_val = optval_from_varp(opt_idx, varp);
+ OptVal default_val = optval_from_varp(opt_idx, &opt->def_val);
+
+ return optval_equal(current_val, default_val);
}
/// Send update to UIs with values of UI relevant options
void ui_refresh_options(void)
{
- for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
uint32_t flags = options[opt_idx].flags;
if (!(flags & P_UI_OPTION)) {
continue;
}
String name = cstr_as_string(options[opt_idx].fullname);
- void *varp = options[opt_idx].var;
- Object value = OBJECT_INIT;
- if (flags & P_BOOL) {
- value = BOOLEAN_OBJ(*(int *)varp);
- } else if (flags & P_NUM) {
- value = INTEGER_OBJ(*(OptInt *)varp);
- } else if (flags & P_STRING) {
- // cstr_as_string handles NULL string
- value = CSTR_AS_OBJ(*(char **)varp);
- }
+ Object value = optval_as_object(optval_from_varp(opt_idx, options[opt_idx].var));
ui_call_option_set(name, value);
}
if (p_mouse != NULL) {
@@ -4050,29 +4159,30 @@ void ui_refresh_options(void)
/// must not be called with a hidden option!
///
/// @param opt_flags OPT_LOCAL or OPT_GLOBAL
-static void showoneopt(vimoption_T *p, int opt_flags)
+static void showoneopt(vimoption_T *opt, int opt_flags)
{
int save_silent = silent_mode;
silent_mode = false;
- info_message = true; // use os_msg(), not os_errmsg()
+ info_message = true; // use stdout, not stderr
- void *varp = get_varp_scope(p, opt_flags);
+ OptIndex opt_idx = get_opt_idx(opt);
+ void *varp = get_varp_scope(opt, opt_flags);
// for 'modified' we also need to check if 'ff' or 'fenc' changed.
- if ((p->flags & P_BOOL) && ((int *)varp == &curbuf->b_changed
- ? !curbufIsChanged() : !*(int *)varp)) {
+ if (option_has_type(opt_idx, kOptValTypeBoolean)
+ && ((int *)varp == &curbuf->b_changed ? !curbufIsChanged() : !*(int *)varp)) {
msg_puts("no");
- } else if ((p->flags & P_BOOL) && *(int *)varp < 0) {
+ } else if (option_has_type(opt_idx, kOptValTypeBoolean) && *(int *)varp < 0) {
msg_puts("--");
} else {
msg_puts(" ");
}
- msg_puts(p->fullname);
- if (!(p->flags & P_BOOL)) {
+ msg_puts(opt->fullname);
+ if (!(option_has_type(opt_idx, kOptValTypeBoolean))) {
msg_putchar('=');
// put value string in NameBuff
- option_value2string(p, opt_flags);
+ option_value2string(opt, opt_flags);
msg_outtrans(NameBuff, 0);
}
@@ -4110,39 +4220,42 @@ int makeset(FILE *fd, int opt_flags, int local_only)
// Do the loop over "options[]" twice: once for options with the
// P_PRI_MKRC flag and once without.
for (int pri = 1; pri >= 0; pri--) {
- for (vimoption_T *p = &options[0]; p->fullname; p++) {
- if (!(p->flags & P_NO_MKRC)
- && ((pri == 1) == ((p->flags & P_PRI_MKRC) != 0))) {
+ vimoption_T *opt;
+ for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ opt = &options[opt_idx];
+
+ if (!(opt->flags & P_NO_MKRC)
+ && ((pri == 1) == ((opt->flags & P_PRI_MKRC) != 0))) {
// skip global option when only doing locals
- if (p->indir == PV_NONE && !(opt_flags & OPT_GLOBAL)) {
+ if (opt->indir == PV_NONE && !(opt_flags & OPT_GLOBAL)) {
continue;
}
// Do not store options like 'bufhidden' and 'syntax' in a vimrc
// file, they are always buffer-specific.
- if ((opt_flags & OPT_GLOBAL) && (p->flags & P_NOGLOB)) {
+ if ((opt_flags & OPT_GLOBAL) && (opt->flags & P_NOGLOB)) {
continue;
}
- void *varp = get_varp_scope(p, opt_flags); // currently used value
+ void *varp = get_varp_scope(opt, opt_flags); // currently used value
// Hidden options are never written.
if (!varp) {
continue;
}
// Global values are only written when not at the default value.
- if ((opt_flags & OPT_GLOBAL) && optval_default(p, varp)) {
+ if ((opt_flags & OPT_GLOBAL) && optval_default(opt_idx, varp)) {
continue;
}
if ((opt_flags & OPT_SKIPRTP)
- && (p->var == &p_rtp || p->var == &p_pp)) {
+ && (opt->var == &p_rtp || opt->var == &p_pp)) {
continue;
}
int round = 2;
void *varp_local = NULL; // fresh value
- if (p->indir != PV_NONE) {
- if (p->var == VAR_WIN) {
+ if (opt->indir != PV_NONE) {
+ if (opt->var == VAR_WIN) {
// skip window-local option when only doing globals
if (!(opt_flags & OPT_LOCAL)) {
continue;
@@ -4150,8 +4263,8 @@ int makeset(FILE *fd, int opt_flags, int local_only)
// When fresh value of window-local option is not at the
// default, need to write it too.
if (!(opt_flags & OPT_GLOBAL) && !local_only) {
- void *varp_fresh = get_varp_scope(p, OPT_GLOBAL); // local value
- if (!optval_default(p, varp_fresh)) {
+ void *varp_fresh = get_varp_scope(opt, OPT_GLOBAL); // local value
+ if (!optval_default(opt_idx, varp_fresh)) {
round = 1;
varp_local = varp;
varp = varp_fresh;
@@ -4170,28 +4283,28 @@ int makeset(FILE *fd, int opt_flags, int local_only)
cmd = "setlocal";
}
- if (p->flags & P_BOOL) {
- if (put_setbool(fd, cmd, p->fullname, *(int *)varp) == FAIL) {
+ if (option_has_type(opt_idx, kOptValTypeBoolean)) {
+ if (put_setbool(fd, cmd, opt->fullname, *(int *)varp) == FAIL) {
return FAIL;
}
- } else if (p->flags & P_NUM) {
- if (put_setnum(fd, cmd, p->fullname, (OptInt *)varp) == FAIL) {
+ } else if (option_has_type(opt_idx, kOptValTypeNumber)) {
+ if (put_setnum(fd, cmd, opt->fullname, (OptInt *)varp) == FAIL) {
return FAIL;
}
- } else { // P_STRING
- int do_endif = false;
+ } else { // string
+ bool do_endif = false;
// Don't set 'syntax' and 'filetype' again if the value is
// already right, avoids reloading the syntax file.
- if (p->indir == PV_SYN || p->indir == PV_FT) {
- if (fprintf(fd, "if &%s != '%s'", p->fullname,
+ if (opt->indir == PV_SYN || opt->indir == PV_FT) {
+ if (fprintf(fd, "if &%s != '%s'", opt->fullname,
*(char **)(varp)) < 0
|| put_eol(fd) < 0) {
return FAIL;
}
do_endif = true;
}
- if (put_setstring(fd, cmd, p->fullname, (char **)varp, p->flags) == FAIL) {
+ if (put_setstring(fd, cmd, opt->fullname, (char **)varp, opt->flags) == FAIL) {
return FAIL;
}
if (do_endif) {
@@ -4260,7 +4373,7 @@ static int put_setstring(FILE *fd, char *cmd, char *name, char **valuep, uint64_
if (fprintf(fd, "%s %s+=", cmd, name) < 0) {
goto fail;
}
- (void)copy_option_part(&p, part, size, ",");
+ copy_option_part(&p, part, size, ",");
if (put_escstr(fd, part, 2) == FAIL || put_eol(fd) == FAIL) {
goto fail;
}
@@ -4402,7 +4515,7 @@ void *get_varp_scope(vimoption_T *p, int scope)
/// Get pointer to option variable at 'opt_idx', depending on local or global
/// scope.
-void *get_option_varp_scope_from(int opt_idx, int scope, buf_T *buf, win_T *win)
+void *get_option_varp_scope_from(OptIndex opt_idx, int scope, buf_T *buf, win_T *win)
{
return get_varp_scope_from(&(options[opt_idx]), scope, buf, win);
}
@@ -4696,6 +4809,13 @@ void *get_varp_from(vimoption_T *p, buf_T *buf, win_T *win)
return &(buf->b_p_wm);
}
+/// Get option index from option pointer
+static inline OptIndex get_opt_idx(vimoption_T *opt)
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
+{
+ return (OptIndex)(opt - options);
+}
+
/// Get pointer to option variable.
static inline void *get_varp(vimoption_T *p)
{
@@ -4859,8 +4979,8 @@ void didset_window_options(win_T *wp, bool valid_cursor)
check_colorcolumn(wp);
briopt_check(wp);
fill_culopt_flags(NULL, wp);
- set_fillchars_option(wp, wp->w_p_fcs, true);
- set_listchars_option(wp, wp->w_p_lcs, true);
+ set_chars_option(wp, wp->w_p_fcs, kFillchars, true, NULL, 0);
+ set_chars_option(wp, wp->w_p_lcs, kListchars, true, NULL, 0);
parse_winhl_opt(wp); // sets w_hl_needs_update also for w_p_winbl
check_blending(wp);
set_winbar_win(wp, false, valid_cursor);
@@ -4869,19 +4989,19 @@ void didset_window_options(win_T *wp, bool valid_cursor)
}
/// Index into the options table for a buffer-local option enum.
-static int buf_opt_idx[BV_COUNT];
+static OptIndex buf_opt_idx[BV_COUNT];
#define COPY_OPT_SCTX(buf, bv) buf->b_p_script_ctx[bv] = options[buf_opt_idx[bv]].last_set
/// Initialize buf_opt_idx[] if not done already.
static void init_buf_opt_idx(void)
{
- static int did_init_buf_opt_idx = false;
+ static bool did_init_buf_opt_idx = false;
if (did_init_buf_opt_idx) {
return;
}
did_init_buf_opt_idx = true;
- for (int i = 0; options[i].fullname != NULL; i++) {
+ for (OptIndex i = 0; i < kOptIndexCount; i++) {
if (options[i].indir & PV_BUF) {
buf_opt_idx[options[i].indir & PV_MASK] = i;
}
@@ -4897,9 +5017,9 @@ static void init_buf_opt_idx(void)
/// BCO_NOHELP Don't copy the values to a help buffer.
void buf_copy_options(buf_T *buf, int flags)
{
- int should_copy = true;
+ bool should_copy = true;
char *save_p_isk = NULL; // init for GCC
- int did_isk = false;
+ bool did_isk = false;
// Skip this when the option defaults have not been set yet. Happens when
// main() allocates the first buffer.
@@ -5017,7 +5137,7 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_vsts = xstrdup(p_vsts);
COPY_OPT_SCTX(buf, BV_VSTS);
if (p_vsts && p_vsts != empty_string_option) {
- (void)tabstop_set(p_vsts, &buf->b_p_vsts_array);
+ tabstop_set(p_vsts, &buf->b_p_vsts_array);
} else {
buf->b_p_vsts_array = NULL;
}
@@ -5066,7 +5186,7 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_s.b_syn_isk = empty_string_option;
buf->b_s.b_p_spc = xstrdup(p_spc);
COPY_OPT_SCTX(buf, BV_SPC);
- (void)compile_cap_prog(&buf->b_s);
+ compile_cap_prog(&buf->b_s);
buf->b_s.b_p_spf = xstrdup(p_spf);
COPY_OPT_SCTX(buf, BV_SPF);
buf->b_s.b_p_spl = xstrdup(p_spl);
@@ -5128,7 +5248,7 @@ void buf_copy_options(buf_T *buf, int flags)
if (dont_do_help) {
buf->b_p_isk = save_p_isk;
if (p_vts && p_vts != empty_string_option && !buf->b_p_vts_array) {
- (void)tabstop_set(p_vts, &buf->b_p_vts_array);
+ tabstop_set(p_vts, &buf->b_p_vts_array);
} else {
buf->b_p_vts_array = NULL;
}
@@ -5141,7 +5261,7 @@ void buf_copy_options(buf_T *buf, int flags)
buf->b_p_vts = xstrdup(p_vts);
COPY_OPT_SCTX(buf, BV_VTS);
if (p_vts && p_vts != empty_string_option && !buf->b_p_vts_array) {
- (void)tabstop_set(p_vts, &buf->b_p_vts_array);
+ tabstop_set(p_vts, &buf->b_p_vts_array);
} else {
buf->b_p_vts_array = NULL;
}
@@ -5163,21 +5283,16 @@ void buf_copy_options(buf_T *buf, int flags)
check_buf_options(buf); // make sure we don't have NULLs
if (did_isk) {
- (void)buf_init_chartab(buf, false);
+ buf_init_chartab(buf, false);
}
}
/// Reset the 'modifiable' option and its default value.
void reset_modifiable(void)
{
- int opt_idx;
-
curbuf->b_p_ma = false;
p_ma = false;
- opt_idx = findoption("ma");
- if (opt_idx >= 0) {
- options[opt_idx].def_val = false;
- }
+ options[kOptModifiable].def_val.boolean = false;
}
/// Set the global value for 'iminsert' to the local value.
@@ -5192,7 +5307,7 @@ void set_imsearch_global(buf_T *buf)
p_imsearch = buf->b_p_imsearch;
}
-static int expand_option_idx = -1;
+static OptIndex expand_option_idx = kOptInvalid;
static int expand_option_start_col = 0;
static char expand_option_name[5] = { 't', '_', NUL, NUL, NUL };
static int expand_option_flags = 0;
@@ -5242,8 +5357,8 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
char nextchar;
uint32_t flags = 0;
- int opt_idx = 0;
- int is_term_option = false;
+ OptIndex opt_idx = 0;
+ bool is_term_option = false;
if (*arg == '<') {
while (*p != '>') {
@@ -5282,13 +5397,13 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
return;
}
nextchar = *p;
- opt_idx = findoption_len(arg, (size_t)(p - arg));
- if (opt_idx == -1 || options[opt_idx].var == NULL) {
+ opt_idx = find_option_len(arg, (size_t)(p - arg));
+ if (opt_idx == kOptInvalid || options[opt_idx].var == NULL) {
xp->xp_context = EXPAND_NOTHING;
return;
}
flags = options[opt_idx].flags;
- if (flags & P_BOOL) {
+ if (option_has_type(opt_idx, kOptValTypeBoolean)) {
xp->xp_context = EXPAND_NOTHING;
return;
}
@@ -5316,7 +5431,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
// Below are for handling expanding a specific option's value after the '=' or ':'
if (is_term_option) {
- expand_option_idx = -1;
+ expand_option_idx = kOptInvalid;
} else {
expand_option_idx = opt_idx;
}
@@ -5334,14 +5449,17 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
xp->xp_context = EXPAND_FILETYPE;
return;
}
+ if (options[opt_idx].var == &p_keymap) {
+ xp->xp_context = EXPAND_KEYMAP;
+ return;
+ }
// Now pick. If the option has a custom expander, use that. Otherwise, just
// fill with the existing option value.
if (expand_option_subtract) {
xp->xp_context = EXPAND_SETTING_SUBTRACT;
return;
- } else if (expand_option_idx >= 0
- && options[expand_option_idx].opt_expand_cb != NULL) {
+ } else if (expand_option_idx != kOptInvalid && options[expand_option_idx].opt_expand_cb != NULL) {
xp->xp_context = EXPAND_STRING_SETTING;
} else if (*xp->xp_pattern == NUL) {
xp->xp_context = EXPAND_OLD_SETTING;
@@ -5350,7 +5468,7 @@ void set_context_in_set_cmd(expand_T *xp, char *arg, int opt_flags)
xp->xp_context = EXPAND_NOTHING;
}
- if (is_term_option || (flags & P_NUM)) {
+ if (is_term_option || option_has_type(opt_idx, kOptValTypeNumber)) {
return;
}
@@ -5502,13 +5620,13 @@ int ExpandSettings(expand_T *xp, regmatch_T *regmatch, char *fuzzystr, int *numM
}
}
char *str;
- for (size_t opt_idx = 0; (str = options[opt_idx].fullname) != NULL;
- opt_idx++) {
+ for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ str = options[opt_idx].fullname;
if (options[opt_idx].var == NULL) {
continue;
}
if (xp->xp_context == EXPAND_BOOL_SETTINGS
- && !(options[opt_idx].flags & P_BOOL)) {
+ && !(option_has_type(opt_idx, kOptValTypeBoolean))) {
continue;
}
@@ -5567,7 +5685,7 @@ static char *escape_option_str_cmdline(char *var)
// The reverse is found at stropt_copy_value().
for (var = buf; *var != NUL; MB_PTR_ADV(var)) {
if (var[0] == '\\' && var[1] == '\\'
- && expand_option_idx >= 0
+ && expand_option_idx != kOptInvalid
&& (options[expand_option_idx].flags & P_EXPAND)
&& vim_isfilec((uint8_t)var[2])
&& (var[2] != '\\' || (var == buf && var[4] != '\\'))) {
@@ -5586,12 +5704,12 @@ int ExpandOldSetting(int *numMatches, char ***matches)
*numMatches = 0;
*matches = xmalloc(sizeof(char *));
- // For a terminal key code expand_option_idx is < 0.
- if (expand_option_idx < 0) {
- expand_option_idx = findoption(expand_option_name);
+ // For a terminal key code expand_option_idx is kOptInvalid.
+ if (expand_option_idx == kOptInvalid) {
+ expand_option_idx = find_option(expand_option_name);
}
- if (expand_option_idx >= 0) {
+ if (expand_option_idx != kOptInvalid) {
// Put string of option value in NameBuff.
option_value2string(&options[expand_option_idx], expand_option_flags);
var = NameBuff;
@@ -5609,8 +5727,7 @@ int ExpandOldSetting(int *numMatches, char ***matches)
/// Expansion handler for :set=/:set+= when the option has a custom expansion handler.
int ExpandStringSetting(expand_T *xp, regmatch_T *regmatch, int *numMatches, char ***matches)
{
- if (expand_option_idx < 0
- || options[expand_option_idx].opt_expand_cb == NULL) {
+ if (expand_option_idx == kOptInvalid || options[expand_option_idx].opt_expand_cb == NULL) {
// Not supposed to reach this. This function is only for options with
// custom expansion callbacks.
return FAIL;
@@ -5642,7 +5759,7 @@ int ExpandStringSetting(expand_T *xp, regmatch_T *regmatch, int *numMatches, cha
/// Expansion handler for :set-=
int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, char ***matches)
{
- if (expand_option_idx < 0) {
+ if (expand_option_idx == kOptInvalid) {
// term option
return ExpandOldSetting(numMatches, matches);
}
@@ -5653,7 +5770,7 @@ int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, c
uint32_t option_flags = options[expand_option_idx].flags;
- if (option_flags & P_NUM) {
+ if (option_has_type(expand_option_idx, kOptValTypeNumber)) {
return ExpandOldSetting(numMatches, matches);
} else if (option_flags & P_COMMA) {
// Split the option by comma, then present each option to the user if
@@ -5748,11 +5865,13 @@ int ExpandSettingSubtract(expand_T *xp, regmatch_T *regmatch, int *numMatches, c
/// NameBuff[]. Must not be called with a hidden option!
///
/// @param opt_flags OPT_GLOBAL and/or OPT_LOCAL
-static void option_value2string(vimoption_T *opp, int scope)
+///
+/// TODO(famiu): Replace this with optval_to_cstr() if possible.
+static void option_value2string(vimoption_T *opt, int scope)
{
- void *varp = get_varp_scope(opp, scope);
+ void *varp = get_varp_scope(opt, scope);
- if (opp->flags & P_NUM) {
+ if (option_has_type(get_opt_idx(opt), kOptValTypeNumber)) {
OptInt wc = 0;
if (wc_use_keyname(varp, &wc)) {
@@ -5765,11 +5884,11 @@ static void option_value2string(vimoption_T *opp, int scope)
"%" PRId64,
(int64_t)(*(OptInt *)varp));
}
- } else { // P_STRING
+ } else { // string
varp = *(char **)(varp);
if (varp == NULL) { // Just in case.
NameBuff[0] = NUL;
- } else if (opp->flags & P_EXPAND) {
+ } else if (opt->flags & P_EXPAND) {
home_replace(NULL, varp, NameBuff, MAXPATHL, false);
} else {
xstrlcpy(NameBuff, varp, MAXPATHL);
@@ -5822,35 +5941,24 @@ void vimrc_found(char *fname, char *envname)
}
}
-/// Check whether global option has been set
+/// Check whether global option has been set.
///
/// @param[in] name Option name.
///
-/// @return True if it was set.
-bool option_was_set(const char *name)
+/// @return True if option was set.
+bool option_was_set(OptIndex opt_idx)
{
- int idx;
-
- idx = findoption(name);
- if (idx < 0) { // Unknown option.
- return false;
- } else if (options[idx].flags & P_WAS_SET) {
- return true;
- }
- return false;
+ assert(opt_idx != kOptInvalid);
+ return options[opt_idx].flags & P_WAS_SET;
}
/// Reset the flag indicating option "name" was set.
///
/// @param[in] name Option name.
-void reset_option_was_set(const char *name)
+void reset_option_was_set(OptIndex opt_idx)
{
- const int idx = findoption(name);
- if (idx < 0) {
- return;
- }
-
- options[idx].flags &= ~P_WAS_SET;
+ assert(opt_idx != kOptInvalid);
+ options[opt_idx].flags &= ~P_WAS_SET;
}
/// fill_culopt_flags() -- called when 'culopt' changes value
@@ -5949,17 +6057,14 @@ int option_set_callback_func(char *optval, Callback *optcb)
return OK;
}
-static void didset_options_sctx(int opt_flags, char **buf)
+static void didset_options_sctx(int opt_flags, int *buf)
{
for (int i = 0;; i++) {
- if (buf[i] == NULL) {
+ if (buf[i] == kOptInvalid) {
break;
}
- int idx = findoption(buf[i]);
- if (idx >= 0) {
- set_option_sctx_idx(idx, opt_flags, current_sctx);
- }
+ set_option_sctx(buf[i], opt_flags, current_sctx);
}
}
@@ -6099,7 +6204,7 @@ void set_fileformat(int eol_style, int opt_flags)
// p is NULL if "eol_style" is EOL_UNKNOWN.
if (p != NULL) {
- set_string_option_direct("ff", -1, p, OPT_FREE | opt_flags, 0);
+ set_string_option_direct(kOptFileformat, p, opt_flags, 0);
}
// This may cause the buffer to become (un)modified.
@@ -6170,43 +6275,22 @@ bool fish_like_shell(void)
return strstr(path_tail(p_sh), "fish") != NULL;
}
-/// Return the number of requested sign columns, based on current
-/// buffer signs and on user configuration.
-int win_signcol_count(win_T *wp)
-{
- if (wp->w_minscwidth <= SCL_NO) {
- return 0;
- }
-
- int needed_signcols = buf_signcols(wp->w_buffer, wp->w_maxscwidth);
- int ret = MAX(wp->w_minscwidth, MIN(wp->w_maxscwidth, needed_signcols));
- assert(ret <= SIGN_SHOW_MAX);
- return ret;
-}
-
/// Get window or buffer local options
dict_T *get_winbuf_options(const int bufopt)
FUNC_ATTR_WARN_UNUSED_RESULT
{
dict_T *const d = tv_dict_alloc();
- for (int opt_idx = 0; options[opt_idx].fullname; opt_idx++) {
- struct vimoption *opt = &options[opt_idx];
+ for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ vimoption_T *opt = &options[opt_idx];
if ((bufopt && (opt->indir & PV_BUF))
|| (!bufopt && (opt->indir & PV_WIN))) {
void *varp = get_varp(opt);
if (varp != NULL) {
- if (opt->flags & P_STRING) {
- tv_dict_add_str(d, opt->fullname, strlen(opt->fullname),
- *(const char **)varp);
- } else if (opt->flags & P_NUM) {
- tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname),
- *(OptInt *)varp);
- } else {
- tv_dict_add_nr(d, opt->fullname, strlen(opt->fullname), *(int *)varp);
- }
+ typval_T opt_tv = optval_as_tv(optval_from_varp(opt_idx, varp), true);
+ tv_dict_add_tv(d, opt->fullname, strlen(opt->fullname), &opt_tv);
}
}
}
@@ -6232,32 +6316,33 @@ int get_sidescrolloff_value(win_T *wp)
return (int)(wp->w_p_siso < 0 ? p_siso : wp->w_p_siso);
}
-Dictionary get_vimoption(String name, int scope, buf_T *buf, win_T *win, Error *err)
+Dictionary get_vimoption(String name, int scope, buf_T *buf, win_T *win, Arena *arena, Error *err)
{
- int opt_idx = findoption_len(name.data, name.size);
- VALIDATE_S(opt_idx >= 0, "option (not found)", name.data, {
+ OptIndex opt_idx = find_option_len(name.data, name.size);
+ VALIDATE_S(opt_idx != kOptInvalid, "option (not found)", name.data, {
return (Dictionary)ARRAY_DICT_INIT;
});
- return vimoption2dict(&options[opt_idx], scope, buf, win);
+ return vimoption2dict(&options[opt_idx], scope, buf, win, arena);
}
-Dictionary get_all_vimoptions(void)
+Dictionary get_all_vimoptions(Arena *arena)
{
- Dictionary retval = ARRAY_DICT_INIT;
- for (size_t i = 0; options[i].fullname != NULL; i++) {
- Dictionary opt_dict = vimoption2dict(&options[i], OPT_GLOBAL, curbuf, curwin);
- PUT(retval, options[i].fullname, DICTIONARY_OBJ(opt_dict));
+ Dictionary retval = arena_dict(arena, kOptIndexCount);
+ for (OptIndex opt_idx = 0; opt_idx < kOptIndexCount; opt_idx++) {
+ Dictionary opt_dict = vimoption2dict(&options[opt_idx], OPT_GLOBAL, curbuf, curwin, arena);
+ PUT_C(retval, options[opt_idx].fullname, DICTIONARY_OBJ(opt_dict));
}
return retval;
}
-static Dictionary vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, win_T *win)
+static Dictionary vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, win_T *win,
+ Arena *arena)
{
- Dictionary dict = ARRAY_DICT_INIT;
+ Dictionary dict = arena_dict(arena, 13);
- PUT(dict, "name", CSTR_TO_OBJ(opt->fullname));
- PUT(dict, "shortname", CSTR_TO_OBJ(opt->shortname));
+ PUT_C(dict, "name", CSTR_AS_OBJ(opt->fullname));
+ PUT_C(dict, "shortname", CSTR_AS_OBJ(opt->shortname));
const char *scope;
if (opt->indir & PV_BUF) {
@@ -6268,14 +6353,14 @@ static Dictionary vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, wi
scope = "global";
}
- PUT(dict, "scope", CSTR_TO_OBJ(scope));
+ PUT_C(dict, "scope", CSTR_AS_OBJ(scope));
// welcome to the jungle
- PUT(dict, "global_local", BOOLEAN_OBJ(opt->indir & PV_BOTH));
- PUT(dict, "commalist", BOOLEAN_OBJ(opt->flags & P_COMMA));
- PUT(dict, "flaglist", BOOLEAN_OBJ(opt->flags & P_FLAGLIST));
+ PUT_C(dict, "global_local", BOOLEAN_OBJ(opt->indir & PV_BOTH));
+ PUT_C(dict, "commalist", BOOLEAN_OBJ(opt->flags & P_COMMA));
+ PUT_C(dict, "flaglist", BOOLEAN_OBJ(opt->flags & P_FLAGLIST));
- PUT(dict, "was_set", BOOLEAN_OBJ(opt->flags & P_WAS_SET));
+ PUT_C(dict, "was_set", BOOLEAN_OBJ(opt->flags & P_WAS_SET));
LastSet last_set = { .channel_id = 0 };
if (req_scope == OPT_GLOBAL) {
@@ -6293,29 +6378,37 @@ static Dictionary vimoption2dict(vimoption_T *opt, int req_scope, buf_T *buf, wi
}
}
- PUT(dict, "last_set_sid", INTEGER_OBJ(last_set.script_ctx.sc_sid));
- PUT(dict, "last_set_linenr", INTEGER_OBJ(last_set.script_ctx.sc_lnum));
- PUT(dict, "last_set_chan", INTEGER_OBJ((int64_t)last_set.channel_id));
+ PUT_C(dict, "last_set_sid", INTEGER_OBJ(last_set.script_ctx.sc_sid));
+ PUT_C(dict, "last_set_linenr", INTEGER_OBJ(last_set.script_ctx.sc_lnum));
+ PUT_C(dict, "last_set_chan", INTEGER_OBJ((int64_t)last_set.channel_id));
- const char *type;
- Object def;
// TODO(bfredl): do you even nocp?
- char *def_val = opt->def_val;
- if (opt->flags & P_STRING) {
- type = "string";
- def = CSTR_TO_OBJ(def_val ? def_val : "");
- } else if (opt->flags & P_NUM) {
- type = "number";
- def = INTEGER_OBJ((Integer)(intptr_t)def_val);
- } else if (opt->flags & P_BOOL) {
- type = "boolean";
- def = BOOLEAN_OBJ((intptr_t)def_val);
- } else {
- type = ""; def = NIL;
- }
- PUT(dict, "type", CSTR_TO_OBJ(type));
- PUT(dict, "default", def);
- PUT(dict, "allows_duplicates", BOOLEAN_OBJ(!(opt->flags & P_NODUP)));
+ OptVal def = optval_from_varp(get_opt_idx(opt), &opt->def_val);
+
+ PUT_C(dict, "type", CSTR_AS_OBJ(optval_type_get_name(def.type)));
+ PUT_C(dict, "default", optval_as_object(def));
+ PUT_C(dict, "allows_duplicates", BOOLEAN_OBJ(!(opt->flags & P_NODUP)));
return dict;
}
+
+/// Check if option is multitype (supports multiple types).
+static bool option_is_multitype(OptIndex opt_idx)
+{
+ const OptTypeFlags type_flags = get_option(opt_idx)->type_flags;
+ assert(type_flags != 0);
+ return !is_power_of_two(type_flags);
+}
+
+/// Check if option supports a specific type.
+bool option_has_type(OptIndex opt_idx, OptValType type)
+{
+ // Ensure that type flags variable can hold all types.
+ STATIC_ASSERT(kOptValTypeSize <= sizeof(OptTypeFlags) * 8,
+ "Option type_flags cannot fit all option types");
+ // Ensure that the type is valid before accessing type_flags.
+ assert(type > kOptValTypeNil && type < kOptValTypeSize);
+ // Bitshift 1 by the value of type to get the type's corresponding flag, and check if it's set in
+ // the type_flags bit field.
+ return get_option(opt_idx)->type_flags & (1 << type);
+}
diff --git a/src/nvim/option.h b/src/nvim/option.h
index ebf8e0417d..7cf880b19b 100644
--- a/src/nvim/option.h
+++ b/src/nvim/option.h
@@ -1,5 +1,6 @@
#pragma once
+#include <stdbool.h>
#include <stdint.h>
#include <stdio.h> // IWYU pragma: keep
@@ -8,7 +9,8 @@
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
-#include "nvim/option_defs.h" // IWYU pragma: export
+#include "nvim/macros_defs.h"
+#include "nvim/option_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
/// The options that are local to a window or buffer have "indir" set to one of
@@ -37,18 +39,17 @@ typedef enum {
// buffers. Indicate this by setting "var" to VAR_WIN.
#define VAR_WIN ((char *)-1)
-typedef struct vimoption {
- char *fullname; ///< full option name
- char *shortname; ///< permissible abbreviation
- uint32_t flags; ///< see above
- void *var; ///< global option: pointer to variable;
- ///< window-local option: VAR_WIN;
- ///< buffer-local option: global value
- idopt_T indir; ///< global option: PV_NONE;
- ///< local option: indirect option index
- ///< callback function to invoke after an option is modified to validate and
- ///< apply the new value.
- bool immutable; ///< option value cannot be changed from the default value.
+typedef struct {
+ char *fullname; ///< full option name
+ char *shortname; ///< permissible abbreviation
+ uint32_t flags; ///< see above
+ OptTypeFlags type_flags; ///< option type flags, see OptValType
+ void *var; ///< global option: pointer to variable;
+ ///< window-local option: VAR_WIN;
+ ///< buffer-local option: global value
+ idopt_T indir; ///< global option: PV_NONE;
+ ///< local option: indirect option index
+ bool immutable; ///< option value cannot be changed from the default value.
/// callback function to invoke after an option is modified to validate and
/// apply the new value.
@@ -59,7 +60,12 @@ typedef struct vimoption {
opt_expand_cb_T opt_expand_cb;
// TODO(famiu): Use OptVal for def_val.
- void *def_val; ///< default values for variable (neovim!!)
+ union {
+ int boolean;
+ OptInt number;
+ char *string;
+ } def_val; ///< default value for variable
+
LastSet last_set; ///< script in which the option was last set
} vimoption_T;
@@ -75,28 +81,39 @@ enum {
/// When OPT_GLOBAL and OPT_LOCAL are both missing, set both local and global
/// values, get local value.
typedef enum {
- // TODO(famiu): See if `OPT_FREE` is really necessary and remove it if not.
- OPT_FREE = 0x01, ///< Free old value if it was allocated.
- OPT_GLOBAL = 0x02, ///< Use global value.
- OPT_LOCAL = 0x04, ///< Use local value.
- OPT_MODELINE = 0x08, ///< Option in modeline.
- OPT_WINONLY = 0x10, ///< Only set window-local options.
- OPT_NOWIN = 0x20, ///< Don’t set window-local options.
- OPT_ONECOLUMN = 0x40, ///< list options one per line
- OPT_NO_REDRAW = 0x80, ///< ignore redraw flags on option
- OPT_SKIPRTP = 0x100, ///< "skiprtp" in 'sessionoptions'
-} OptionFlags;
-
-/// Return value from get_option_value_strict
+ OPT_GLOBAL = 0x01, ///< Use global value.
+ OPT_LOCAL = 0x02, ///< Use local value.
+ OPT_MODELINE = 0x04, ///< Option in modeline.
+ OPT_WINONLY = 0x08, ///< Only set window-local options.
+ OPT_NOWIN = 0x10, ///< Don’t set window-local options.
+ OPT_ONECOLUMN = 0x20, ///< list options one per line
+ OPT_NO_REDRAW = 0x40, ///< ignore redraw flags on option
+ OPT_SKIPRTP = 0x80, ///< "skiprtp" in 'sessionoptions'
+} OptionSetFlags;
+
+/// Return value from get_option_attrs().
enum {
- SOPT_BOOL = 0x01, ///< Boolean option
- SOPT_NUM = 0x02, ///< Number option
- SOPT_STRING = 0x04, ///< String option
- SOPT_GLOBAL = 0x08, ///< Option has global value
- SOPT_WIN = 0x10, ///< Option has window-local value
- SOPT_BUF = 0x20, ///< Option has buffer-local value
+ SOPT_GLOBAL = 0x01, ///< Option has global value
+ SOPT_WIN = 0x02, ///< Option has window-local value
+ SOPT_BUF = 0x04, ///< Option has buffer-local value
};
+/// Get name of OptValType as a string.
+static inline const char *optval_type_get_name(const OptValType type)
+{
+ switch (type) {
+ case kOptValTypeNil:
+ return "nil";
+ case kOptValTypeBoolean:
+ return "boolean";
+ case kOptValTypeNumber:
+ return "number";
+ case kOptValTypeString:
+ return "string";
+ }
+ UNREACHABLE;
+}
+
// OptVal helper macros.
#define NIL_OPTVAL ((OptVal) { .type = kOptValTypeNil })
#define BOOLEAN_OPTVAL(b) ((OptVal) { .type = kOptValTypeBoolean, .data.boolean = b })
diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h
index b2e8081a08..ae9ccd371c 100644
--- a/src/nvim/option_defs.h
+++ b/src/nvim/option_defs.h
@@ -6,16 +6,26 @@
#include "nvim/api/private/defs.h"
#include "nvim/cmdexpand_defs.h"
#include "nvim/regexp_defs.h"
-#include "nvim/types_defs.h"
-/// Option value type
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "options_enum.generated.h"
+#endif
+
+/// Option value type.
+/// These types are also used as type flags by using the type value as an index for the type_flags
+/// bit field (@see option_has_type()).
typedef enum {
- kOptValTypeNil = 0,
+ kOptValTypeNil = -1, // Make sure Nil can't be bitshifted and used as an option type flag.
kOptValTypeBoolean,
kOptValTypeNumber,
kOptValTypeString,
} OptValType;
+/// Always update this whenever a new option type is added.
+#define kOptValTypeSize (kOptValTypeString + 1)
+
+typedef uint32_t OptTypeFlags;
+
typedef union {
// boolean options are actually tri-states because they have a third "None" value.
TriState boolean;
@@ -43,10 +53,11 @@ typedef struct {
/// Pointer to the option variable. The variable can be an OptInt (numeric
/// option), an int (boolean option) or a char pointer (string option).
void *os_varp;
- int os_idx;
+ OptIndex os_idx;
int os_flags;
/// Old value of the option.
+ /// TODO(famiu): Convert `os_oldval` and `os_newval` to `OptVal` to accommodate multitype options.
OptValData os_oldval;
/// New value of the option.
OptValData os_newval;
@@ -66,6 +77,7 @@ typedef struct {
/// is parameterized, then the "os_errbuf" buffer is used to store the error
/// message (when it is not NULL).
char *os_errbuf;
+ /// length of the error buffer
size_t os_errbuflen;
void *os_win;
diff --git a/src/nvim/option_vars.h b/src/nvim/option_vars.h
index b0e9ff9434..175f2af896 100644
--- a/src/nvim/option_vars.h
+++ b/src/nvim/option_vars.h
@@ -1,60 +1,56 @@
#pragma once
#include "nvim/macros_defs.h"
+#include "nvim/os/os_defs.h"
+#include "nvim/sign_defs.h"
#include "nvim/types_defs.h"
// option_vars.h: definition of global variables for settable options
// Option Flags
-#define P_BOOL 0x01U ///< the option is boolean
-#define P_NUM 0x02U ///< the option is numeric
-#define P_STRING 0x04U ///< the option is a string
-#define P_ALLOCED 0x08U ///< the string option is in allocated memory,
+#define P_ALLOCED 0x01U ///< the option is in allocated memory,
///< must use free_string_option() when
///< assigning new value. Not set if default is
///< the same.
-#define P_EXPAND 0x10U ///< environment expansion. NOTE: P_EXPAND can
+#define P_EXPAND 0x02U ///< environment expansion. NOTE: P_EXPAND can
///< never be used for local or hidden options
-#define P_NO_DEF_EXP 0x20U ///< do not expand default value
-#define P_NODEFAULT 0x40U ///< don't set to default value
-#define P_DEF_ALLOCED 0x80U ///< default value is in allocated memory, must
+#define P_NO_DEF_EXP 0x04U ///< do not expand default value
+#define P_NODEFAULT 0x08U ///< don't set to default value
+#define P_DEF_ALLOCED 0x10U ///< default value is in allocated memory, must
///< use free() when assigning new value
-#define P_WAS_SET 0x100U ///< option has been set/reset
-#define P_NO_MKRC 0x200U ///< don't include in :mkvimrc output
+#define P_WAS_SET 0x20U ///< option has been set/reset
+#define P_NO_MKRC 0x40U ///< don't include in :mkvimrc output
// when option changed, what to display:
-#define P_UI_OPTION 0x400U ///< send option to remote UI
-#define P_RTABL 0x800U ///< redraw tabline
-#define P_RSTAT 0x1000U ///< redraw status lines
-#define P_RWIN 0x2000U ///< redraw current window and recompute text
-#define P_RBUF 0x4000U ///< redraw current buffer and recompute text
-#define P_RALL 0x6000U ///< redraw all windows
-#define P_RCLR 0x7000U ///< clear and redraw all
-
-#define P_COMMA 0x8000U ///< comma separated list
-#define P_ONECOMMA 0x18000U ///< P_COMMA and cannot have two consecutive
+#define P_UI_OPTION 0x80U ///< send option to remote UI
+#define P_RTABL 0x100U ///< redraw tabline
+#define P_RSTAT 0x200U ///< redraw status lines
+#define P_RWIN 0x400U ///< redraw current window and recompute text
+#define P_RBUF 0x800U ///< redraw current buffer and recompute text
+#define P_RALL 0xC00U ///< redraw all windows and recompute text
+#define P_RCLR 0xE00U ///< clear and redraw all and recompute text
+
+#define P_COMMA 0x1000U ///< comma separated list
+#define P_ONECOMMA 0x3000U ///< P_COMMA and cannot have two consecutive
///< commas
-#define P_NODUP 0x20000U ///< don't allow duplicate strings
-#define P_FLAGLIST 0x40000U ///< list of single-char flags
-
-#define P_SECURE 0x80000U ///< cannot change in modeline or secure mode
-#define P_GETTEXT 0x100000U ///< expand default value with _()
-#define P_NOGLOB 0x200000U ///< do not use local value for global vimrc
-#define P_NFNAME 0x400000U ///< only normal file name chars allowed
-#define P_INSECURE 0x800000U ///< option was set from a modeline
-#define P_PRI_MKRC 0x1000000U ///< priority for :mkvimrc (setting option
+#define P_NODUP 0x4000U ///< don't allow duplicate strings
+#define P_FLAGLIST 0x8000U ///< list of single-char flags
+
+#define P_SECURE 0x10000U ///< cannot change in modeline or secure mode
+#define P_GETTEXT 0x20000U ///< expand default value with _()
+#define P_NOGLOB 0x40000U ///< do not use local value for global vimrc
+#define P_NFNAME 0x80000U ///< only normal file name chars allowed
+#define P_INSECURE 0x100000U ///< option was set from a modeline
+#define P_PRI_MKRC 0x200000U ///< priority for :mkvimrc (setting option
///< has side effects)
-#define P_NO_ML 0x2000000U ///< not allowed in modeline
-#define P_CURSWANT 0x4000000U ///< update curswant required; not needed
+#define P_NO_ML 0x400000U ///< not allowed in modeline
+#define P_CURSWANT 0x800000U ///< update curswant required; not needed
///< when there is a redraw flag
-#define P_NDNAME 0x8000000U ///< only normal dir name chars allowed
-#define P_RWINONLY 0x10000000U ///< only redraw current window
-#define P_MLE 0x20000000U ///< under control of 'modelineexpr'
-#define P_FUNC 0x40000000U ///< accept a function reference or a lambda
-#define P_COLON 0x80000000U ///< values use colons to create sublists
-// Warning: Currently we have used all 32 bits for option flags, and adding more
-// flags will overflow it. Adding another flag will need to change how
-// it's stored first.
+#define P_NDNAME 0x1000000U ///< only normal dir name chars allowed
+#define P_HLONLY 0x2000000U ///< option only changes highlight, not text
+#define P_MLE 0x4000000U ///< under control of 'modelineexpr'
+#define P_FUNC 0x8000000U ///< accept a function reference or a lambda
+#define P_COLON 0x10000000U ///< values use colons to create sublists
#define HIGHLIGHT_INIT \
"8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText,d:Directory,e:ErrorMsg," \
@@ -157,7 +153,6 @@
#define CPO_NUMCOL 'n' // 'number' column also used for text
#define CPO_LINEOFF 'o'
#define CPO_OVERNEW 'O' // silently overwrite new file
-#define CPO_LISP 'p' // 'lisp' indenting
#define CPO_FNAMEAPP 'P' // set file name for ":w >>file"
#define CPO_JOINCOL 'q' // with "3J" use column after first join
#define CPO_REDO 'r'
@@ -223,7 +218,7 @@ enum {
SHM_INTRO = 'I', ///< Intro messages.
SHM_COMPLETIONMENU = 'c', ///< Completion menu messages.
SHM_COMPLETIONSCAN = 'C', ///< Completion scanning messages.
- SHM_RECORDING = 'q', ///< Short recording message.
+ SHM_RECORDING = 'q', ///< No recording message.
SHM_FILEINFO = 'F', ///< No file info messages.
SHM_SEARCHCOUNT = 'S', ///< No search stats: '[1/10]'
};
@@ -785,162 +780,17 @@ EXTERN int p_wb; ///< 'writebackup'
EXTERN OptInt p_wd; ///< 'writedelay'
EXTERN int p_cdh; ///< 'cdhome'
-/// "indir" values for buffer-local options.
-/// These need to be defined globally, so that the BV_COUNT can be used with
-/// b_p_script_stx[].
-enum {
- BV_AI = 0,
- BV_AR,
- BV_BH,
- BV_BKC,
- BV_BT,
- BV_EFM,
- BV_GP,
- BV_MP,
- BV_BIN,
- BV_BL,
- BV_BOMB,
- BV_CHANNEL,
- BV_CI,
- BV_CIN,
- BV_CINK,
- BV_CINO,
- BV_CINW,
- BV_CINSD,
- BV_CM,
- BV_CMS,
- BV_COM,
- BV_CPT,
- BV_DICT,
- BV_TSR,
- BV_CSL,
- BV_CFU,
- BV_DEF,
- BV_INC,
- BV_EOF,
- BV_EOL,
- BV_FIXEOL,
- BV_EP,
- BV_ET,
- BV_FENC,
- BV_FP,
- BV_BEXPR,
- BV_FEX,
- BV_FF,
- BV_FLP,
- BV_FO,
- BV_FT,
- BV_IMI,
- BV_IMS,
- BV_INDE,
- BV_INDK,
- BV_INEX,
- BV_INF,
- BV_ISK,
- BV_KMAP,
- BV_KP,
- BV_LISP,
- BV_LOP,
- BV_LW,
- BV_MENC,
- BV_MA,
- BV_ML,
- BV_MOD,
- BV_MPS,
- BV_NF,
- BV_OFU,
- BV_PATH,
- BV_PI,
- BV_QE,
- BV_RO,
- BV_SCBK,
- BV_SI,
- BV_SMC,
- BV_SYN,
- BV_SPC,
- BV_SPF,
- BV_SPL,
- BV_SPO,
- BV_STS,
- BV_SUA,
- BV_SW,
- BV_SWF,
- BV_TFU,
- BV_TSRFU,
- BV_TAGS,
- BV_TC,
- BV_TS,
- BV_TW,
- BV_TX,
- BV_UDF,
- BV_UL,
- BV_WM,
- BV_VSTS,
- BV_VTS,
- BV_COUNT, // must be the last one
-};
-
-/// "indir" values for window-local options.
-/// These need to be defined globally, so that the WV_COUNT can be used in the
-/// window structure.
-enum {
- WV_LIST = 0,
- WV_ARAB,
- WV_COCU,
- WV_COLE,
- WV_CRBIND,
- WV_BRI,
- WV_BRIOPT,
- WV_DIFF,
- WV_FDC,
- WV_FEN,
- WV_FDI,
- WV_FDL,
- WV_FDM,
- WV_FML,
- WV_FDN,
- WV_FDE,
- WV_FDT,
- WV_FMR,
- WV_LBR,
- WV_NU,
- WV_RNU,
- WV_VE,
- WV_NUW,
- WV_PVW,
- WV_RL,
- WV_RLC,
- WV_SCBIND,
- WV_SCROLL,
- WV_SMS,
- WV_SISO,
- WV_SO,
- WV_SPELL,
- WV_CUC,
- WV_CUL,
- WV_CULOPT,
- WV_CC,
- WV_SBR,
- WV_STC,
- WV_STL,
- WV_WFH,
- WV_WFW,
- WV_WRAP,
- WV_SCL,
- WV_WINHL,
- WV_LCS,
- WV_FCS,
- WV_WINBL,
- WV_WBR,
- WV_COUNT, // must be the last one
-};
-
// Value for b_p_ul indicating the global value must be used.
#define NO_LOCAL_UNDOLEVEL (-123456)
+#define ERR_BUFLEN 80
+
#define SB_MAX 100000 // Maximum 'scrollback' value.
-#define MAX_NUMBERWIDTH 20 // used for 'numberwidth' and 'statuscolumn'
+#define MAX_NUMBERWIDTH 20 // used for 'numberwidth'
+
+// Maximum 'statuscolumn' width: number + sign + fold columns
+#define MAX_STCWIDTH MAX_NUMBERWIDTH + SIGN_SHOW_MAX * SIGN_WIDTH + 9
#define TABSTOP_MAX 9999
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index daaf73d241..72f9ff849d 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2,10 +2,11 @@
--- @field full_name string
--- @field desc? string
--- @field abbreviation? string
+--- @field alias? string|string[]
--- @field short_desc? string|fun(): string
--- @field varname? string
--- @field pv_name? string
---- @field type 'bool'|'number'|'string'
+--- @field type 'boolean'|'number'|'string'
--- @field immutable? boolean
--- @field list? 'comma'|'onecomma'|'commacolon'|'onecommacolon'|'flags'|'flagscomma'
--- @field scope vim.option_scope[]
@@ -44,10 +45,10 @@
--- |'statuslines'
--- |'tabline'
--- |'current_window'
---- |'current_window_only'
--- |'current_buffer'
--- |'all_windows'
--- |'curswant'
+--- |'highlight_only'
--- |'ui_option'
--- @param s string
@@ -60,7 +61,7 @@ end
--- @return fun(): string
local function macros(s)
return function()
- return s
+ return '.string=' .. s
end
end
@@ -68,7 +69,7 @@ end
--- @return fun(): string
local function imacros(s)
return function()
- return '(intptr_t)' .. s
+ return '.number=' .. s
end
end
@@ -84,6 +85,7 @@ end
return {
cstr = cstr,
--- @type vim.option_meta[]
+ --- The order of the options MUST be alphabetic for ":set all".
options = {
{
abbreviation = 'al',
@@ -94,56 +96,6 @@ return {
type = 'number',
},
{
- abbreviation = 'arab',
- cb = 'did_set_arabic',
- defaults = { if_true = false },
- desc = [=[
- This option can be set to start editing Arabic text.
- Setting this option will:
- - Set the 'rightleft' option, unless 'termbidi' is set.
- - Set the 'arabicshape' option, unless 'termbidi' is set.
- - Set the 'keymap' option to "arabic"; in Insert mode CTRL-^ toggles
- between typing English and Arabic key mapping.
- - Set the 'delcombine' option
-
- Resetting this option will:
- - Reset the 'rightleft' option.
- - Disable the use of 'keymap' (without changing its value).
- Note that 'arabicshape' and 'delcombine' are not reset (it is a global
- option).
- Also see |arabic.txt|.
- ]=],
- full_name = 'arabic',
- redraw = { 'curswant' },
- scope = { 'window' },
- short_desc = N_('Arabic as a default second language'),
- type = 'bool',
- },
- {
- abbreviation = 'arshape',
- defaults = { if_true = true },
- desc = [=[
- When on and 'termbidi' is off, the required visual character
- corrections that need to take place for displaying the Arabic language
- take effect. Shaping, in essence, gets enabled; the term is a broad
- one which encompasses:
- a) the changing/morphing of characters based on their location
- within a word (initial, medial, final and stand-alone).
- b) the enabling of the ability to compose characters
- c) the enabling of the required combining of some characters
- When disabled the display shows each character's true stand-alone
- form.
- Arabic is a complex language which requires other settings, for
- further details see |arabic.txt|.
- ]=],
- full_name = 'arabicshape',
- redraw = { 'all_windows', 'ui_option' },
- scope = { 'global' },
- short_desc = N_('do shaping for Arabic characters'),
- type = 'bool',
- varname = 'p_arshape',
- },
- {
abbreviation = 'ari',
defaults = { if_true = false },
desc = [=[
@@ -155,7 +107,7 @@ return {
full_name = 'allowrevins',
scope = { 'global' },
short_desc = N_('allow CTRL-_ in Insert and Command-line mode'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ari',
},
{
@@ -203,6 +155,56 @@ return {
varname = 'p_ambw',
},
{
+ abbreviation = 'arab',
+ cb = 'did_set_arabic',
+ defaults = { if_true = false },
+ desc = [=[
+ This option can be set to start editing Arabic text.
+ Setting this option will:
+ - Set the 'rightleft' option, unless 'termbidi' is set.
+ - Set the 'arabicshape' option, unless 'termbidi' is set.
+ - Set the 'keymap' option to "arabic"; in Insert mode CTRL-^ toggles
+ between typing English and Arabic key mapping.
+ - Set the 'delcombine' option
+
+ Resetting this option will:
+ - Reset the 'rightleft' option.
+ - Disable the use of 'keymap' (without changing its value).
+ Note that 'arabicshape' and 'delcombine' are not reset (it is a global
+ option).
+ Also see |arabic.txt|.
+ ]=],
+ full_name = 'arabic',
+ redraw = { 'curswant' },
+ scope = { 'window' },
+ short_desc = N_('Arabic as a default second language'),
+ type = 'boolean',
+ },
+ {
+ abbreviation = 'arshape',
+ defaults = { if_true = true },
+ desc = [=[
+ When on and 'termbidi' is off, the required visual character
+ corrections that need to take place for displaying the Arabic language
+ take effect. Shaping, in essence, gets enabled; the term is a broad
+ one which encompasses:
+ a) the changing/morphing of characters based on their location
+ within a word (initial, medial, final and stand-alone).
+ b) the enabling of the ability to compose characters
+ c) the enabling of the required combining of some characters
+ When disabled the display shows each character's true stand-alone
+ form.
+ Arabic is a complex language which requires other settings, for
+ further details see |arabic.txt|.
+ ]=],
+ full_name = 'arabicshape',
+ redraw = { 'all_windows', 'ui_option' },
+ scope = { 'global' },
+ short_desc = N_('do shaping for Arabic characters'),
+ type = 'boolean',
+ varname = 'p_arshape',
+ },
+ {
abbreviation = 'acd',
cb = 'did_set_autochdir',
defaults = { if_true = false },
@@ -217,7 +219,7 @@ return {
full_name = 'autochdir',
scope = { 'global' },
short_desc = N_('change directory to the file in the current window'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_acd',
},
{
@@ -239,7 +241,7 @@ return {
full_name = 'autoindent',
scope = { 'buffer' },
short_desc = N_('take indent for new line from previous line'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ai',
},
{
@@ -252,14 +254,14 @@ return {
from before it was deleted. When it appears again then it is read.
|timestamp|
If this option has a local value, use this command to switch back to
- using the global value: >
- :set autoread<
+ using the global value: >vim
+ set autoread<
<
]=],
full_name = 'autoread',
scope = { 'global', 'buffer' },
short_desc = N_('autom. read file when changed outside of Vim'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ar',
},
{
@@ -284,7 +286,7 @@ return {
full_name = 'autowrite',
scope = { 'global' },
short_desc = N_('automatically write file if changed'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_aw',
},
{
@@ -299,7 +301,7 @@ return {
full_name = 'autowriteall',
scope = { 'global' },
short_desc = N_("as 'autowrite', but works with more commands"),
- type = 'bool',
+ type = 'boolean',
varname = 'p_awa',
},
{
@@ -316,23 +318,19 @@ return {
See |:hi-normal| if you want to set the background color explicitly.
*g:colors_name*
When a color scheme is loaded (the "g:colors_name" variable is set)
- setting 'background' will cause the color scheme to be reloaded. If
+ changing 'background' will cause the color scheme to be reloaded. If
the color scheme adjusts to the value of 'background' this will work.
However, if the color scheme sets 'background' itself the effect may
be undone. First delete the "g:colors_name" variable when needed.
Normally this option would be set in the vimrc file. Possibly
- depending on the terminal name. Example: >
- :if $TERM ==# "xterm"
- : set background=dark
- :endif
- < When this option is set, the default settings for the highlight groups
+ depending on the terminal name. Example: >vim
+ if $TERM ==# "xterm"
+ set background=dark
+ endif
+ < When this option is changed, the default settings for the highlight groups
will change. To use other settings, place ":highlight" commands AFTER
the setting of the 'background' option.
- This option is also used in the "$VIMRUNTIME/syntax/syntax.vim" file
- to select the colors for syntax highlighting. After changing this
- option, you must load syntax.vim again to see the result. This can be
- done with ":syntax on".
]=],
expand_cb = 'expand_set_background',
full_name = 'background',
@@ -387,7 +385,7 @@ return {
full_name = 'backup',
scope = { 'global' },
short_desc = N_('keep backup file after overwriting a file'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_bk',
},
{
@@ -498,12 +496,12 @@ return {
use '//', instead of '\\'.
- Environment variables are expanded |:set_env|.
- Careful with '\' characters, type one before a space, type two to
- get one in the option (see |option-backslash|), for example: >
- :set bdir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
+ get one in the option (see |option-backslash|), for example: >vim
+ set bdir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
<
See also 'backup' and 'writebackup' options.
- If you want to hide your backup files on Unix, consider this value: >
- :set backupdir=./.backup,~/.backup,.,/tmp
+ If you want to hide your backup files on Unix, consider this value: >vim
+ set backupdir=./.backup,~/.backup,.,/tmp
< You must create a ".backup" directory in each directory and in your
home directory for this to work properly.
The use of |:set+=| and |:set-=| is preferred when adding or removing
@@ -535,8 +533,8 @@ return {
If you like to keep a lot of backups, you could use a BufWritePre
autocommand to change 'backupext' just before writing the file to
- include a timestamp. >
- :au BufWritePre * let &bex = '-' .. strftime("%Y%b%d%X") .. '~'
+ include a timestamp. >vim
+ au BufWritePre * let &bex = '-' .. strftime("%Y%b%d%X") .. '~'
< Use 'backupdir' to put the backup in a different directory.
]=],
full_name = 'backupext',
@@ -573,7 +571,7 @@ return {
Note that environment variables are not expanded. If you want to use
$HOME you must expand it explicitly, e.g.: >vim
- :let &backupskip = escape(expand('$HOME'), '\') .. '/tmp/*'
+ let &backupskip = escape(expand('$HOME'), '\') .. '/tmp/*'
< Note that the default also makes sure that "crontab -e" works (when a
backup would be made by renaming the original file crontab won't see
@@ -671,7 +669,7 @@ return {
redraw = { 'statuslines' },
scope = { 'buffer' },
short_desc = N_('read/write/edit file in binary mode'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_bin',
},
{
@@ -699,7 +697,7 @@ return {
redraw = { 'statuslines' },
scope = { 'buffer' },
short_desc = N_('a Byte Order Mark to the file'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_bomb',
},
{
@@ -733,7 +731,7 @@ return {
redraw = { 'current_window' },
scope = { 'window' },
short_desc = N_('wrapped line repeats indent'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'briopt',
@@ -848,7 +846,7 @@ return {
scope = { 'buffer' },
short_desc = N_('whether the buffer shows up in the buffer list'),
tags = { 'E85' },
- type = 'bool',
+ type = 'boolean',
varname = 'p_bl',
},
{
@@ -950,7 +948,7 @@ return {
scope = { 'global' },
secure = true,
short_desc = N_(':cd without argument goes to the home directory'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_cdh',
},
{
@@ -971,8 +969,8 @@ return {
in the current directory first.
If the default value taken from $CDPATH is not what you want, include
a modified version of the following command in your vimrc file to
- override it: >
- :let &cdpath = ',' .. substitute(substitute($CDPATH, '[, ]', '\\\0', 'g'), ':', ',', 'g')
+ override it: >vim
+ let &cdpath = ',' .. substitute(substitute($CDPATH, '[, ]', '\\\0', 'g'), ':', ',', 'g')
< This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
(parts of 'cdpath' can be passed to the shell to expand file names).
@@ -997,9 +995,9 @@ return {
The key used in Command-line Mode to open the command-line window.
Only non-printable keys are allowed.
The key can be specified as a single character, but it is difficult to
- type. The preferred way is to use the <> notation. Examples: >
- :exe "set cedit=\\<C-Y>"
- :exe "set cedit=\\<Esc>"
+ type. The preferred way is to use the <> notation. Examples: >vim
+ exe "set cedit=\\<C-Y>"
+ exe "set cedit=\\<Esc>"
< |Nvi| also has this option, but it only uses the first character.
See |cmdwin|.
]=],
@@ -1045,7 +1043,7 @@ return {
Conversion between "latin1", "unicode", "ucs-2", "ucs-4" and "utf-8"
is done internally by Vim, 'charconvert' is not used for this.
Also used for Unicode conversion.
- Example: >
+ Example: >vim
set charconvert=CharConvert()
fun CharConvert()
system("recode "
@@ -1088,7 +1086,7 @@ return {
full_name = 'cindent',
scope = { 'buffer' },
short_desc = N_('do C program indenting'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_cin',
},
{
@@ -1129,6 +1127,25 @@ return {
varname = 'p_cino',
},
{
+ abbreviation = 'cinsd',
+ alloced = true,
+ defaults = { if_true = 'public,protected,private' },
+ deny_duplicates = true,
+ desc = [=[
+ Keywords that are interpreted as a C++ scope declaration by |cino-g|.
+ Useful e.g. for working with the Qt framework that defines additional
+ scope declarations "signals", "public slots" and "private slots": >vim
+ set cinscopedecls+=signals,public\ slots,private\ slots
+ <
+ ]=],
+ full_name = 'cinscopedecls',
+ list = 'onecomma',
+ scope = { 'buffer' },
+ short_desc = N_("words that are recognized by 'cino-g'"),
+ type = 'string',
+ varname = 'p_cinsd',
+ },
+ {
abbreviation = 'cinw',
alloced = true,
defaults = { if_true = 'if,else,while,do,for,switch' },
@@ -1149,25 +1166,6 @@ return {
varname = 'p_cinw',
},
{
- abbreviation = 'cinsd',
- alloced = true,
- defaults = { if_true = 'public,protected,private' },
- deny_duplicates = true,
- desc = [=[
- Keywords that are interpreted as a C++ scope declaration by |cino-g|.
- Useful e.g. for working with the Qt framework that defines additional
- scope declarations "signals", "public slots" and "private slots": >
- set cinscopedecls+=signals,public\ slots,private\ slots
- <
- ]=],
- full_name = 'cinscopedecls',
- list = 'onecomma',
- scope = { 'buffer' },
- short_desc = N_("words that are recognized by 'cino-g'"),
- type = 'string',
- varname = 'p_cinsd',
- },
- {
abbreviation = 'cb',
cb = 'did_set_clipboard',
defaults = { if_true = '' },
@@ -1253,26 +1251,27 @@ return {
highlighted with ColorColumn |hl-ColorColumn|. Useful to align
text. Will make screen redrawing slower.
The screen column can be an absolute number, or a number preceded with
- '+' or '-', which is added to or subtracted from 'textwidth'. >
+ '+' or '-', which is added to or subtracted from 'textwidth'. >vim
- :set cc=+1 " highlight column after 'textwidth'
- :set cc=+1,+2,+3 " highlight three columns after 'textwidth'
- :hi ColorColumn ctermbg=lightgrey guibg=lightgrey
+ set cc=+1 " highlight column after 'textwidth'
+ set cc=+1,+2,+3 " highlight three columns after 'textwidth'
+ hi ColorColumn ctermbg=lightgrey guibg=lightgrey
<
When 'textwidth' is zero then the items with '-' and '+' are not used.
A maximum of 256 columns are highlighted.
]=],
full_name = 'colorcolumn',
list = 'onecomma',
- redraw = { 'current_window' },
+ redraw = { 'current_window', 'highlight_only' },
scope = { 'window' },
short_desc = N_('columns to highlight'),
type = 'string',
},
{
abbreviation = 'co',
+ cb = 'did_set_lines_or_columns',
defaults = {
- if_true = macros('DFLT_COLS'),
+ if_true = imacros('DFLT_COLS'),
doc = '80 or terminal width',
},
desc = [=[
@@ -1285,8 +1284,8 @@ return {
number of columns of the display, the display may be messed up. For
the GUI it is always possible and Vim limits the number of columns to
what fits on the screen. You can use this command to get the widest
- window possible: >
- :set columns=9999
+ window possible: >vim
+ set columns=9999
< Minimum value is 12, maximum value is 10000.
]=],
full_name = 'columns',
@@ -1341,7 +1340,7 @@ return {
full_name = 'compatible',
scope = { 'global' },
short_desc = N_('No description'),
- type = 'bool',
+ type = 'boolean',
immutable = true,
},
{
@@ -1363,8 +1362,8 @@ return {
k scan the files given with the 'dictionary' option
kspell use the currently active spell checking |spell|
k{dict} scan the file {dict}. Several "k" flags can be given,
- patterns are valid too. For example: >
- :set cpt=k/usr/dict/*,k~/spanish
+ patterns are valid too. For example: >vim
+ set cpt=k/usr/dict/*,k~/spanish
< s scan the files given with the 'thesaurus' option
s{tsr} scan the file {tsr}. Several "s" flags can be given, patterns
are valid too.
@@ -1394,65 +1393,6 @@ return {
varname = 'p_cpt',
},
{
- abbreviation = 'cocu',
- alloced = true,
- cb = 'did_set_concealcursor',
- defaults = { if_true = '' },
- desc = [=[
- Sets the modes in which text in the cursor line can also be concealed.
- When the current mode is listed then concealing happens just like in
- other lines.
- n Normal mode
- v Visual mode
- i Insert mode
- c Command line editing, for 'incsearch'
-
- 'v' applies to all lines in the Visual area, not only the cursor.
- A useful value is "nc". This is used in help files. So long as you
- are moving around text is concealed, but when starting to insert text
- or selecting a Visual area the concealed text is displayed, so that
- you can see what you are doing.
- Keep in mind that the cursor position is not always where it's
- displayed. E.g., when moving vertically it may change column.
- ]=],
- expand_cb = 'expand_set_concealcursor',
- full_name = 'concealcursor',
- list = 'flags',
- redraw = { 'current_window' },
- scope = { 'window' },
- short_desc = N_('whether concealable text is hidden in cursor line'),
- type = 'string',
- },
- {
- abbreviation = 'cole',
- defaults = { if_true = 0 },
- desc = [=[
- Determine how text with the "conceal" syntax attribute |:syn-conceal|
- is shown:
-
- Value Effect ~
- 0 Text is shown normally
- 1 Each block of concealed text is replaced with one
- character. If the syntax item does not have a custom
- replacement character defined (see |:syn-cchar|) the
- character defined in 'listchars' is used.
- It is highlighted with the "Conceal" highlight group.
- 2 Concealed text is completely hidden unless it has a
- custom replacement character defined (see
- |:syn-cchar|).
- 3 Concealed text is completely hidden.
-
- Note: in the cursor line concealed text is not hidden, so that you can
- edit and copy the text. This can be changed with the 'concealcursor'
- option.
- ]=],
- full_name = 'conceallevel',
- redraw = { 'current_window' },
- scope = { 'window' },
- short_desc = N_('whether concealable text is shown or hidden'),
- type = 'number',
- },
- {
abbreviation = 'cfu',
alloced = true,
cb = 'did_set_completefunc',
@@ -1502,13 +1442,17 @@ return {
completion in the preview window. Only works in
combination with "menu" or "menuone".
- noinsert Do not insert any text for a match until the user selects
+ noinsert Do not insert any text for a match until the user selects
a match from the menu. Only works in combination with
"menu" or "menuone". No effect if "longest" is present.
- noselect Do not select a match in the menu, force the user to
+ noselect Do not select a match in the menu, force the user to
select one from the menu. Only works in combination with
"menu" or "menuone".
+
+ popup Show extra information about the currently selected
+ completion in a popup window. Only works in combination
+ with "menu" or "menuone". Overrides "preview".
]=],
expand_cb = 'expand_set_completeopt',
full_name = 'completeopt',
@@ -1543,6 +1487,65 @@ return {
varname = 'p_csl',
},
{
+ abbreviation = 'cocu',
+ alloced = true,
+ cb = 'did_set_concealcursor',
+ defaults = { if_true = '' },
+ desc = [=[
+ Sets the modes in which text in the cursor line can also be concealed.
+ When the current mode is listed then concealing happens just like in
+ other lines.
+ n Normal mode
+ v Visual mode
+ i Insert mode
+ c Command line editing, for 'incsearch'
+
+ 'v' applies to all lines in the Visual area, not only the cursor.
+ A useful value is "nc". This is used in help files. So long as you
+ are moving around text is concealed, but when starting to insert text
+ or selecting a Visual area the concealed text is displayed, so that
+ you can see what you are doing.
+ Keep in mind that the cursor position is not always where it's
+ displayed. E.g., when moving vertically it may change column.
+ ]=],
+ expand_cb = 'expand_set_concealcursor',
+ full_name = 'concealcursor',
+ list = 'flags',
+ redraw = { 'current_window' },
+ scope = { 'window' },
+ short_desc = N_('whether concealable text is hidden in cursor line'),
+ type = 'string',
+ },
+ {
+ abbreviation = 'cole',
+ defaults = { if_true = 0 },
+ desc = [=[
+ Determine how text with the "conceal" syntax attribute |:syn-conceal|
+ is shown:
+
+ Value Effect ~
+ 0 Text is shown normally
+ 1 Each block of concealed text is replaced with one
+ character. If the syntax item does not have a custom
+ replacement character defined (see |:syn-cchar|) the
+ character defined in 'listchars' is used.
+ It is highlighted with the "Conceal" highlight group.
+ 2 Concealed text is completely hidden unless it has a
+ custom replacement character defined (see
+ |:syn-cchar|).
+ 3 Concealed text is completely hidden.
+
+ Note: in the cursor line concealed text is not hidden, so that you can
+ edit and copy the text. This can be changed with the 'concealcursor'
+ option.
+ ]=],
+ full_name = 'conceallevel',
+ redraw = { 'current_window' },
+ scope = { 'window' },
+ short_desc = N_('whether concealable text is shown or hidden'),
+ type = 'number',
+ },
+ {
abbreviation = 'cf',
defaults = { if_true = false },
desc = [=[
@@ -1558,7 +1561,7 @@ return {
full_name = 'confirm',
scope = { 'global' },
short_desc = N_('ask what to do about unsaved/read-only files'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_confirm',
},
{
@@ -1578,7 +1581,7 @@ return {
full_name = 'copyindent',
scope = { 'buffer' },
short_desc = N_("make 'autoindent' use existing indent structure"),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ci',
},
{
@@ -1706,9 +1709,6 @@ return {
when it didn't exist when editing it. This is a
protection against a file unexpectedly created by
someone else. Vi didn't complain about this.
- *cpo-p*
- p Vi compatible Lisp indenting. When not present, a
- slightly better algorithm is used.
*cpo-P*
P When included, a ":write" command that appends to a
file will set the file name for the current buffer, if
@@ -1843,7 +1843,7 @@ return {
pv_name = 'p_crbind',
scope = { 'window' },
short_desc = N_('move cursor in window as it moves in other windows'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'cuc',
@@ -1853,16 +1853,16 @@ return {
|hl-CursorColumn|. Useful to align text. Will make screen redrawing
slower.
If you only want the highlighting in the current window you can use
- these autocommands: >
+ these autocommands: >vim
au WinLeave * set nocursorline nocursorcolumn
au WinEnter * set cursorline cursorcolumn
<
]=],
full_name = 'cursorcolumn',
- redraw = { 'current_window_only' },
+ redraw = { 'current_window', 'highlight_only' },
scope = { 'window' },
short_desc = N_('highlight the screen column of the cursor'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'cul',
@@ -1874,10 +1874,10 @@ return {
easier to see the selected text.
]=],
full_name = 'cursorline',
- redraw = { 'current_window_only' },
+ redraw = { 'current_window', 'highlight_only' },
scope = { 'window' },
short_desc = N_('highlight the screen line of the cursor'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'culopt',
@@ -1902,7 +1902,7 @@ return {
expand_cb = 'expand_set_cursorlineopt',
full_name = 'cursorlineopt',
list = 'onecomma',
- redraw = { 'current_window_only' },
+ redraw = { 'current_window', 'highlight_only' },
scope = { 'window' },
short_desc = N_("settings for 'cursorline'"),
type = 'string',
@@ -1950,7 +1950,7 @@ return {
< If the function is defined with `func_name : function() {...`: >
^\s*\ze\i\+\s*[:]\s*(*function\s*(
< When using the ":set" command, you need to double the backslashes!
- To avoid that use `:let` with a single quote string: >
+ To avoid that use `:let` with a single quote string: >vim
let &l:define = '^\s*\ze\k\+\s*=\s*function('
<
]=],
@@ -1978,7 +1978,7 @@ return {
full_name = 'delcombine',
scope = { 'global' },
short_desc = N_('delete combining characters on their own'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_deco',
},
{
@@ -2030,7 +2030,7 @@ return {
redraw = { 'current_window' },
scope = { 'window' },
short_desc = N_('diff mode for the current window'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'dex',
@@ -2157,11 +2157,11 @@ return {
patience patience diff algorithm
histogram histogram diff algorithm
- Examples: >
- :set diffopt=internal,filler,context:4
- :set diffopt=
- :set diffopt=internal,filler,foldcolumn:3
- :set diffopt-=internal " do NOT use the internal diff parser
+ Examples: >vim
+ set diffopt=internal,filler,context:4
+ set diffopt=
+ set diffopt=internal,filler,foldcolumn:3
+ set diffopt-=internal " do NOT use the internal diff parser
<
]=],
expand_cb = 'expand_set_diffopt',
@@ -2183,7 +2183,7 @@ return {
full_name = 'digraph',
scope = { 'global' },
short_desc = N_('enable the entering of digraphs in Insert mode'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_dg',
},
{
@@ -2222,8 +2222,8 @@ return {
- A directory name may end in an ':' or '/'.
- Environment variables are expanded |:set_env|.
- Careful with '\' characters, type one before a space, type two to
- get one in the option (see |option-backslash|), for example: >
- :set dir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
+ get one in the option (see |option-backslash|), for example: >vim
+ set dir=c:\\tmp,\ dir\\,with\\,commas,\\\ dir\ with\ spaces
<
Editing the same file twice will result in a warning. Using "/tmp" on
is discouraged: if the system crashes you lose the swap file. And
@@ -2299,7 +2299,7 @@ return {
full_name = 'edcompatible',
scope = { 'global' },
short_desc = N_('No description'),
- type = 'bool',
+ type = 'boolean',
immutable = true,
},
{
@@ -2317,7 +2317,7 @@ return {
redraw = { 'all_windows', 'ui_option' },
scope = { 'global' },
short_desc = N_('No description'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_emoji',
},
{
@@ -2354,7 +2354,7 @@ return {
redraw = { 'statuslines' },
scope = { 'buffer' },
short_desc = N_('write CTRL-Z for last line in file'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_eof',
},
{
@@ -2380,7 +2380,7 @@ return {
redraw = { 'statuslines' },
scope = { 'buffer' },
short_desc = N_('write <EOL> for last line in file'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_eol',
},
{
@@ -2406,7 +2406,7 @@ return {
full_name = 'equalalways',
scope = { 'global' },
short_desc = N_('windows are automatically made the same size'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ea',
},
{
@@ -2442,7 +2442,7 @@ return {
full_name = 'errorbells',
scope = { 'global' },
short_desc = N_('ring the bell for error messages'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_eb',
},
{
@@ -2493,8 +2493,8 @@ return {
A list of autocommand event names, which are to be ignored.
When set to "all" or when "all" is one of the items, all autocommand
events are ignored, autocommands will not be executed.
- Otherwise this is a comma-separated list of event names. Example: >
- :set ei=WinEnter,WinLeave
+ Otherwise this is a comma-separated list of event names. Example: >vim
+ set ei=WinEnter,WinLeave
<
]=],
expand_cb = 'expand_set_eventignore',
@@ -2517,7 +2517,7 @@ return {
full_name = 'expandtab',
scope = { 'buffer' },
short_desc = N_('use spaces when <Tab> is inserted'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_et',
},
{
@@ -2539,7 +2539,7 @@ return {
scope = { 'global' },
secure = true,
short_desc = N_('read .nvimrc and .exrc in the current directory'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_exrc',
},
{
@@ -2614,7 +2614,7 @@ return {
will work and the first entry of 'fileencodings' will be used (except
"ucs-bom", which requires the BOM to be present). If you prefer
another encoding use an BufReadPost autocommand event to test if your
- preferred encoding is to be used. Example: >
+ preferred encoding is to be used. Example: >vim
au BufReadPost * if search('\S', 'w') == 0 |
\ set fenc=iso-2022-jp | endif
< This sets 'fileencoding' to "iso-2022-jp" if the file does not contain
@@ -2622,8 +2622,8 @@ return {
When the |++enc| argument is used then the value of 'fileencodings' is
not used.
Note that 'fileencodings' is not used for a new file, the global value
- of 'fileencoding' is used instead. You can set it with: >
- :setglobal fenc=iso-8859-2
+ of 'fileencoding' is used instead. You can set it with: >vim
+ setglobal fenc=iso-8859-2
< This means that a non-existing file may get a different encoding than
an empty file.
The special value "ucs-bom" can be used to check for a Unicode BOM
@@ -2769,7 +2769,7 @@ return {
full_name = 'fileignorecase',
scope = { 'global' },
short_desc = N_('ignore case when using file names'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_fic',
},
{
@@ -2787,11 +2787,11 @@ return {
this use the ":filetype on" command. |:filetype|
Setting this option to a different value is most useful in a modeline,
for a file for which the file type is not automatically recognized.
- Example, for in an IDL file: >
+ Example, for in an IDL file: >c
/* vim: set filetype=idl : */
< |FileType| |filetypes|
When a dot appears in the value then this separates two filetype
- names. Example: >
+ names. Example: >c
/* vim: set filetype=c.doxygen : */
< This will use the "c" filetype first, then the "doxygen" filetype.
This works both for filetype plugins and for syntax files. More than
@@ -2818,7 +2818,7 @@ return {
Characters to fill the statuslines, vertical separators and special
lines in the window.
It is a comma-separated list of items. Each item has a name, a colon
- and the value of that item:
+ and the value of that item: |E1511|
item default Used for ~
stl ' ' statusline of the current window
@@ -2851,12 +2851,12 @@ return {
"vert", "vertleft", "vertright", "verthoriz", "foldsep" and "fold"
default to single-byte alternatives.
- Example: >
- :set fillchars=stl:\ ,stlnc:\ ,vert:│,fold:·,diff:-
+ Example: >vim
+ set fillchars=stl:\ ,stlnc:\ ,vert:│,fold:·,diff:-
<
For the "stl", "stlnc", "foldopen", "foldclose" and "foldsep" items
single-byte and multibyte characters are supported. But double-width
- characters are not supported.
+ characters are not supported. |E1512|
The highlighting used for these items:
item highlight group ~
@@ -2901,7 +2901,7 @@ return {
redraw = { 'statuslines' },
scope = { 'buffer' },
short_desc = N_('make sure last line in file has <EOL>'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_fixeol',
},
{
@@ -2960,7 +2960,7 @@ return {
redraw = { 'current_window' },
scope = { 'window' },
short_desc = N_('set to display all folds open'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'fde',
@@ -3181,6 +3181,9 @@ return {
It is not allowed to change text or jump to another window while
evaluating 'foldtext' |textlock|.
+
+ When set to an empty string, foldtext is disabled, and the line
+ is displayed normally with highlighting and no line wrapping.
]=],
full_name = 'foldtext',
modelineexpr = true,
@@ -3206,8 +3209,8 @@ return {
automatic formatting. This can be empty. Don't insert
it yet!
- Example: >
- :set formatexpr=mylang#Format()
+ Example: >vim
+ set formatexpr=mylang#Format()
< This will invoke the mylang#Format() function in the
autoload/mylang.vim file in 'runtimepath'. |autoload|
@@ -3221,7 +3224,7 @@ return {
the internal format mechanism.
If the expression starts with s: or |<SID>|, then it is replaced with
- the script ID (|local-function|). Example: >
+ the script ID (|local-function|). Example: >vim
set formatexpr=s:MyFormatExpr()
set formatexpr=<SID>SomeFormatExpr()
< Otherwise, the expression is evaluated in the context of the script
@@ -3241,27 +3244,6 @@ return {
varname = 'p_fex',
},
{
- abbreviation = 'fo',
- alloced = true,
- cb = 'did_set_formatoptions',
- defaults = { if_true = macros('DFLT_FO_VIM') },
- desc = [=[
- This is a sequence of letters which describes how automatic
- formatting is to be done.
- See |fo-table| for possible values and |gq| for how to format text.
- Commas can be inserted for readability.
- To avoid problems with flags that are added in the future, use the
- "+=" and "-=" feature of ":set" |add-option-flags|.
- ]=],
- expand_cb = 'expand_set_formatoptions',
- full_name = 'formatoptions',
- list = 'flags',
- scope = { 'buffer' },
- short_desc = N_('how automatic formatting is to be done'),
- type = 'string',
- varname = 'p_fo',
- },
- {
abbreviation = 'flp',
alloced = true,
defaults = { if_true = '^\\s*\\d\\+[\\]:.)}\\t ]\\s*' },
@@ -3283,6 +3265,27 @@ return {
varname = 'p_flp',
},
{
+ abbreviation = 'fo',
+ alloced = true,
+ cb = 'did_set_formatoptions',
+ defaults = { if_true = macros('DFLT_FO_VIM') },
+ desc = [=[
+ This is a sequence of letters which describes how automatic
+ formatting is to be done.
+ See |fo-table| for possible values and |gq| for how to format text.
+ Commas can be inserted for readability.
+ To avoid problems with flags that are added in the future, use the
+ "+=" and "-=" feature of ":set" |add-option-flags|.
+ ]=],
+ expand_cb = 'expand_set_formatoptions',
+ full_name = 'formatoptions',
+ list = 'flags',
+ scope = { 'buffer' },
+ short_desc = N_('how automatic formatting is to be done'),
+ type = 'string',
+ varname = 'p_fo',
+ },
+ {
abbreviation = 'fp',
defaults = { if_true = '' },
desc = [=[
@@ -3329,7 +3332,7 @@ return {
scope = { 'global' },
secure = true,
short_desc = N_('whether to invoke fsync() after file write'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_fs',
},
{
@@ -3346,14 +3349,14 @@ return {
:s///g subst. one subst. all
:s///gg subst. all subst. one
- DEPRECATED: Setting this option may break plugins that are not aware
- of this option. Also, many users get confused that adding the /g flag
- has the opposite effect of that it normally does.
+ NOTE: Setting this option may break plugins that rely on the default
+ behavior of the 'g' flag. This will also make the 'g' flag have the
+ opposite effect of that documented in |:s_g|.
]=],
full_name = 'gdefault',
scope = { 'global' },
short_desc = N_('the ":substitute" flag \'g\' is default on'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_gd',
},
{
@@ -3388,8 +3391,8 @@ return {
will be included. Environment variables are expanded |:set_env|. See
|option-backslash| about including spaces and backslashes.
When your "grep" accepts the "-H" argument, use this to make ":grep"
- also work well with a single file: >
- :set grepprg=grep\ -nH
+ also work well with a single file: >vim
+ set grepprg=grep\ -nH
< Special value: When 'grepprg' is set to "internal" the |:grep| command
works like |:vimgrep|, |:lgrep| like |:lvimgrep|, |:grepadd| like
|:vimgrepadd| and |:lgrepadd| like |:lvimgrepadd|.
@@ -3415,11 +3418,11 @@ return {
Configures the cursor style for each mode. Works in the GUI and many
terminals. See |tui-cursor-shape|.
- To disable cursor-styling, reset the option: >
- :set guicursor=
+ To disable cursor-styling, reset the option: >vim
+ set guicursor=
- < To enable mode shapes, "Cursor" highlight, and blinking: >
- :set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50
+ < To enable mode shapes, "Cursor" highlight, and blinking: >vim
+ set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr:hor20,o:hor50
\,a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor
\,sm:block-blinkwait175-blinkoff150-blinkon175
@@ -3452,8 +3455,8 @@ return {
the cursor starts blinking, blinkon is the time that
the cursor is shown and blinkoff is the time that the
cursor is not shown. Times are in msec. When one of
- the numbers is zero, there is no blinking. E.g.: >
- :set guicursor=n:blinkon0
+ the numbers is zero, there is no blinking. E.g.: >vim
+ set guicursor=n:blinkon0
< - Default is "blinkon0" for each mode.
{group-name}
Highlight group that decides the color and font of the
@@ -3491,9 +3494,9 @@ return {
to do a common setting for all modes. For example, to switch off
blinking: "a:blinkon0"
- Examples of cursor highlighting: >
- :highlight Cursor gui=reverse guifg=NONE guibg=NONE
- :highlight Cursor gui=NONE guifg=bg guibg=fg
+ Examples of cursor highlighting: >vim
+ highlight Cursor gui=reverse guifg=NONE guibg=NONE
+ highlight Cursor gui=NONE guifg=bg guibg=fg
<
]=],
full_name = 'guicursor',
@@ -3517,8 +3520,8 @@ return {
Spaces after a comma are ignored. To include a comma in a font name
precede it with a backslash. Setting an option requires an extra
backslash before a space and a backslash. See also
- |option-backslash|. For example: >
- :set guifont=Screen15,\ 7x13,font\\,with\\,commas
+ |option-backslash|. For example: >vim
+ set guifont=Screen15,\ 7x13,font\\,with\\,commas
< will make Vim try to use the font "Screen15" first, and if it fails it
will try to use "7x13" and then "font,with,commas" instead.
@@ -3529,14 +3532,14 @@ return {
the case of X). The font names given should be "normal" fonts. Vim
will try to find the related bold and italic fonts.
- For Win32 and Mac OS: >
- :set guifont=*
+ For Win32 and Mac OS: >vim
+ set guifont=*
< will bring up a font requester, where you can pick the font you want.
The font name depends on the GUI used.
- For Mac OSX you can use something like this: >
- :set guifont=Monaco:h10
+ For Mac OSX you can use something like this: >vim
+ set guifont=Monaco:h10
< *E236*
Note that the fonts must be mono-spaced (all characters have the same
width).
@@ -3561,9 +3564,9 @@ return {
Use a ':' to separate the options.
- A '_' can be used in the place of a space, so you don't need to use
backslashes to escape the spaces.
- - Examples: >
- :set guifont=courier_new:h12:w5:b:cRUSSIAN
- :set guifont=Andale_Mono:h7.5:w4.5
+ - Examples: >vim
+ set guifont=courier_new:h12:w5:b:cRUSSIAN
+ set guifont=Andale_Mono:h7.5:w4.5
<
]=],
deny_duplicates = true,
@@ -3743,8 +3746,8 @@ return {
When non-empty describes the text to use in a tooltip for the GUI tab
pages line. When empty Vim will use a default tooltip.
This option is otherwise just like 'guitablabel' above.
- You can include a line break. Simplest method is to use |:let|: >
- :let &guitabtooltip = "line one\nline two"
+ You can include a line break. Simplest method is to use |:let|: >vim
+ let &guitabtooltip = "line one\nline two"
<
]=],
enable_if = false,
@@ -3812,8 +3815,8 @@ return {
be used as a last resort. You can add "en" to prefer English over
another language, but that will only find tags that exist in that
language and not in the English help.
- Example: >
- :set helplang=de,it
+ Example: >vim
+ set helplang=de,it
< This will first search German, then Italian and finally English help
files.
When using |CTRL-]| and ":help!" in a non-English help file Vim will
@@ -3849,7 +3852,7 @@ return {
full_name = 'hidden',
scope = { 'global' },
short_desc = N_("don't unload buffer when it is |abandon|ed"),
- type = 'bool',
+ type = 'boolean',
varname = 'p_hid',
},
{
@@ -3885,7 +3888,7 @@ return {
full_name = 'hkmap',
scope = { 'global' },
short_desc = N_('No description'),
- type = 'bool',
+ type = 'boolean',
immutable = true,
},
{
@@ -3894,7 +3897,7 @@ return {
full_name = 'hkmapp',
scope = { 'global' },
short_desc = N_('No description'),
- type = 'bool',
+ type = 'boolean',
immutable = true,
},
{
@@ -3923,10 +3926,10 @@ return {
with the 'h' flag in 'shada' |shada-h|.
]=],
full_name = 'hlsearch',
- redraw = { 'all_windows' },
+ redraw = { 'all_windows', 'highlight_only' },
scope = { 'global' },
short_desc = N_('highlight matches with last search pattern'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_hls',
},
{
@@ -3945,7 +3948,7 @@ return {
full_name = 'icon',
scope = { 'global' },
short_desc = N_('Vim set the text of the window icon'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_icon',
},
{
@@ -3981,7 +3984,7 @@ return {
full_name = 'ignorecase',
scope = { 'global' },
short_desc = N_('ignore case in search patterns'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ic',
},
{
@@ -3998,7 +4001,7 @@ return {
full_name = 'imcmdline',
scope = { 'global' },
short_desc = N_('use IM when starting to edit a command line'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'imd',
@@ -4016,12 +4019,12 @@ return {
full_name = 'imdisable',
scope = { 'global' },
short_desc = N_('do not use the IM in any mode'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'imi',
cb = 'did_set_iminsert',
- defaults = { if_true = macros('B_IMODE_NONE') },
+ defaults = { if_true = imacros('B_IMODE_NONE') },
desc = [=[
Specifies whether :lmap or an Input Method (IM) is to be used in
Insert mode. Valid values:
@@ -4029,8 +4032,8 @@ return {
1 :lmap is ON and IM is off
2 :lmap is off and IM is ON
To always reset the option to zero when leaving Insert mode with <Esc>
- this can be used: >
- :inoremap <ESC> <ESC>:set iminsert=0<CR>
+ this can be used: >vim
+ inoremap <ESC> <ESC>:set iminsert=0<CR>
< This makes :lmap and IM turn off automatically when leaving Insert
mode.
Note that this option changes when using CTRL-^ in Insert mode
@@ -4047,7 +4050,7 @@ return {
},
{
abbreviation = 'ims',
- defaults = { if_true = macros('B_IMODE_USE_INSERT') },
+ defaults = { if_true = imacros('B_IMODE_USE_INSERT') },
desc = [=[
Specifies whether :lmap or an Input Method (IM) is to be used when
entering a search pattern. Valid values:
@@ -4123,20 +4126,20 @@ return {
defaults = { if_true = '' },
desc = [=[
Expression to be used to transform the string found with the 'include'
- option to a file name. Mostly useful to change "." to "/" for Java: >
- :setlocal includeexpr=substitute(v:fname,'\\.','/','g')
+ option to a file name. Mostly useful to change "." to "/" for Java: >vim
+ setlocal includeexpr=substitute(v:fname,'\\.','/','g')
< The "v:fname" variable will be set to the file name that was detected.
Note the double backslash: the `:set` command first halves them, then
one remains in the value, where "\." matches a dot literally. For
- simple character replacements `tr()` avoids the need for escaping: >
- :setlocal includeexpr=tr(v:fname,'.','/')
+ simple character replacements `tr()` avoids the need for escaping: >vim
+ setlocal includeexpr=tr(v:fname,'.','/')
<
Also used for the |gf| command if an unmodified file name can't be
found. Allows doing "gf" on the name after an 'include' statement.
Also used for |<cfile>|.
If the expression starts with s: or |<SID>|, then it is replaced with
- the script ID (|local-function|). Example: >
+ the script ID (|local-function|). Example: >vim
setlocal includeexpr=s:MyIncludeExpr(v:fname)
setlocal includeexpr=<SID>SomeIncludeExpr(v:fname)
< Otherwise, the expression is evaluated in the context of the script
@@ -4178,7 +4181,7 @@ return {
typing a search command. See also: 'hlsearch'.
If you don't want to turn 'hlsearch' on, but want to highlight all
matches while searching, you can turn on and off 'hlsearch' with
- autocmd. Example: >
+ autocmd. Example: >vim
augroup vimrc-incsearch-highlight
autocmd!
autocmd CmdlineEnter /,\? :set hlsearch
@@ -4195,7 +4198,7 @@ return {
full_name = 'incsearch',
scope = { 'global' },
short_desc = N_('highlight match while typing search pattern'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_is',
},
{
@@ -4215,7 +4218,7 @@ return {
when the expression is evaluated (but it may be moved around).
If the expression starts with s: or |<SID>|, then it is replaced with
- the script ID (|local-function|). Example: >
+ the script ID (|local-function|). Example: >vim
set indentexpr=s:MyIndentExpr()
set indentexpr=<SID>SomeIndentExpr()
< Otherwise, the expression is evaluated in the context of the script
@@ -4229,8 +4232,8 @@ return {
The evaluation of the expression must not have side effects! It must
not change the text, jump to another window, etc. Afterwards the
cursor position is always restored, thus the cursor may be moved.
- Normally this option would be set to call a function: >
- :set indentexpr=GetMyIndent()
+ Normally this option would be set to call a function: >vim
+ set indentexpr=GetMyIndent()
< Error messages will be suppressed, unless the 'debug' option contains
"msg".
See |indent-expression|.
@@ -4283,7 +4286,7 @@ return {
full_name = 'infercase',
scope = { 'buffer' },
short_desc = N_('adjust case of match for keyword completion'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_inf',
},
{
@@ -4292,7 +4295,7 @@ return {
full_name = 'insertmode',
scope = { 'global' },
short_desc = N_('No description'),
- type = 'bool',
+ type = 'boolean',
immutable = true,
},
{
@@ -4469,7 +4472,7 @@ return {
full_name = 'joinspaces',
scope = { 'global' },
short_desc = N_('two spaces after a period with a join command'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_js',
},
{
@@ -4558,9 +4561,9 @@ return {
When "man" or "man -s" is used, Vim will automatically translate
a [count] for the "K" command to a section number.
See |option-backslash| about including spaces and backslashes.
- Example: >
- :set keywordprg=man\ -s
- :set keywordprg=:Man
+ Example: >vim
+ set keywordprg=man\ -s
+ set keywordprg=:Man
< This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
]=],
@@ -4591,10 +4594,10 @@ return {
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
- Example (for Greek, in UTF-8): *greek* >
- :set langmap=ΑA,Î’B,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ΜM,ÎN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,ΘU,ΩV,WW,ΧX,Î¥Y,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,Ï€p,qq,Ïr,σs,Ï„t,θu,ωv,Ï‚w,χx,Ï…y,ζz
- < Example (exchanges meaning of z and y for commands): >
- :set langmap=zy,yz,ZY,YZ
+ Example (for Greek, in UTF-8): *greek* >vim
+ set langmap=ΑA,Î’B,ΨC,ΔD,ΕE,ΦF,ΓG,ΗH,ΙI,ΞJ,ΚK,ΛL,ΜM,ÎN,ΟO,ΠP,QQ,ΡR,ΣS,ΤT,ΘU,ΩV,WW,ΧX,Î¥Y,ΖZ,αa,βb,ψc,δd,εe,φf,γg,ηh,ιi,ξj,κk,λl,μm,νn,οo,Ï€p,qq,Ïr,σs,Ï„t,θu,ωv,Ï‚w,χx,Ï…y,ζz
+ < Example (exchanges meaning of z and y for commands): >vim
+ set langmap=zy,yz,ZY,YZ
<
The 'langmap' option is a list of parts, separated with commas. Each
part can be in one of two forms:
@@ -4632,22 +4635,22 @@ return {
defaults = { if_true = '' },
desc = [=[
Language to use for menu translation. Tells which file is loaded
- from the "lang" directory in 'runtimepath': >
+ from the "lang" directory in 'runtimepath': >vim
"lang/menu_" .. &langmenu .. ".vim"
< (without the spaces). For example, to always use the Dutch menus, no
- matter what $LANG is set to: >
- :set langmenu=nl_NL.ISO_8859-1
+ matter what $LANG is set to: >vim
+ set langmenu=nl_NL.ISO_8859-1
< When 'langmenu' is empty, |v:lang| is used.
Only normal file name characters can be used, `/\*?[|<>` are illegal.
If your $LANG is set to a non-English language but you do want to use
- the English menus: >
- :set langmenu=none
+ the English menus: >vim
+ set langmenu=none
< This option must be set before loading menus, switching on filetype
detection or syntax highlighting. Once the menus are defined setting
- this option has no effect. But you could do this: >
- :source $VIMRUNTIME/delmenu.vim
- :set langmenu=de_DE.ISO_8859-1
- :source $VIMRUNTIME/menu.vim
+ this option has no effect. But you could do this: >vim
+ source $VIMRUNTIME/delmenu.vim
+ set langmenu=de_DE.ISO_8859-1
+ source $VIMRUNTIME/menu.vim
< Warning: This deletes all menus that you defined yourself!
]=],
full_name = 'langmenu',
@@ -4664,7 +4667,7 @@ return {
full_name = 'langnoremap',
scope = { 'global' },
short_desc = N_("do not apply 'langmap' to mapped characters"),
- type = 'bool',
+ type = 'boolean',
varname = 'p_lnr',
},
{
@@ -4679,7 +4682,7 @@ return {
full_name = 'langremap',
scope = { 'global' },
short_desc = N_('No description'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_lrm',
},
{
@@ -4718,7 +4721,7 @@ return {
full_name = 'lazyredraw',
scope = { 'global' },
short_desc = N_("don't redraw while executing macros"),
- type = 'bool',
+ type = 'boolean',
varname = 'p_lz',
},
{
@@ -4739,11 +4742,12 @@ return {
redraw = { 'current_window' },
scope = { 'window' },
short_desc = N_('wrap long lines at a blank'),
- type = 'bool',
+ type = 'boolean',
},
{
+ cb = 'did_set_lines_or_columns',
defaults = {
- if_true = macros('DFLT_ROWS'),
+ if_true = imacros('DFLT_ROWS'),
doc = '24 or terminal height',
},
desc = [=[
@@ -4754,8 +4758,8 @@ return {
option will cause the window size to be changed. When you only want
to use the size for the GUI, put the command in your |gvimrc| file.
Vim limits the number of lines to what fits on the screen. You can
- use this command to get the tallest window possible: >
- :set lines=999
+ use this command to get the tallest window possible: >vim
+ set lines=999
< Minimum value is 2, maximum value is 1000.
]=],
full_name = 'lines',
@@ -4802,7 +4806,7 @@ return {
full_name = 'lisp',
scope = { 'buffer' },
short_desc = N_('indenting for Lisp'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_lisp',
},
{
@@ -4857,8 +4861,8 @@ return {
The cursor is displayed at the start of the space a Tab character
occupies, not at the end as usual in Normal mode. To get this cursor
- position while displaying Tabs with spaces, use: >
- :set list lcs=tab:\ \
+ position while displaying Tabs with spaces, use: >vim
+ set list lcs=tab:\ \
<
Note that list mode will also affect formatting (set with 'textwidth'
or 'wrapmargin') when 'cpoptions' includes 'L'. See 'listchars' for
@@ -4868,7 +4872,7 @@ return {
redraw = { 'current_window' },
scope = { 'window' },
short_desc = N_('<Tab> and <EOL>'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'lcs',
@@ -4878,7 +4882,7 @@ return {
deny_duplicates = true,
desc = [=[
Strings to use in 'list' mode and for the |:list| command. It is a
- comma-separated list of string settings.
+ comma-separated list of string settings. *E1511*
*lcs-eol*
eol:c Character to show at the end of each line. When
@@ -4922,8 +4926,8 @@ return {
lead:c Character to show for leading spaces. When omitted,
leading spaces are blank. Overrides the "space" and
"multispace" settings for leading spaces. You can
- combine it with "tab:", for example: >
- :set listchars+=tab:>-,lead:.
+ combine it with "tab:", for example: >vim
+ set listchars+=tab:>-,lead:.
<
*lcs-leadmultispace*
leadmultispace:c...
@@ -4957,19 +4961,19 @@ return {
omitted.
The characters ':' and ',' should not be used. UTF-8 characters can
- be used. All characters must be single width.
+ be used. All characters must be single width. *E1512*
- Each character can be specified as hex: >
+ Each character can be specified as hex: >vim
set listchars=eol:\\x24
set listchars=eol:\\u21b5
set listchars=eol:\\U000021b5
< Note that a double backslash is used. The number of hex characters
must be exactly 2 for \\x, 4 for \\u and 8 for \\U.
- Examples: >
- :set lcs=tab:>-,trail:-
- :set lcs=tab:>-,eol:<,nbsp:%
- :set lcs=extends:>,precedes:<
+ Examples: >vim
+ set lcs=tab:>-,trail:-
+ set lcs=tab:>-,eol:<,nbsp:%
+ set lcs=extends:>,precedes:<
< |hl-NonText| highlighting will be used for "eol", "extends" and
"precedes". |hl-Whitespace| for "nbsp", "space", "tab", "multispace",
"lead" and "trail".
@@ -4996,7 +5000,7 @@ return {
full_name = 'loadplugins',
scope = { 'global' },
short_desc = N_('load plugin scripts when starting up'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_lpl',
},
{
@@ -5013,7 +5017,7 @@ return {
full_name = 'magic',
scope = { 'global' },
short_desc = N_('special characters in search patterns'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_magic',
},
{
@@ -5053,8 +5057,8 @@ return {
This would be mostly useful when you use MS-Windows. If iconv is
enabled, setting 'makeencoding' to "char" has the same effect as
- setting to the system locale encoding. Example: >
- :set makeencoding=char " system locale is used
+ setting to the system locale encoding. Example: >vim
+ set makeencoding=char " system locale is used
<
]=],
expand_cb = 'expand_set_encoding',
@@ -5076,11 +5080,11 @@ return {
about including spaces and backslashes.
Note that a '|' must be escaped twice: once for ":set" and once for
the interpretation of a command. When you use a filter called
- "myfilter" do it like this: >
- :set makeprg=gmake\ \\\|\ myfilter
+ "myfilter" do it like this: >vim
+ set makeprg=gmake\ \\\|\ myfilter
< The placeholder "$*" can be given (even multiple times) to specify
- where the arguments will be included, for example: >
- :set makeprg=latex\ \\\\nonstopmode\ \\\\input\\{$*}
+ where the arguments will be included, for example: >vim
+ set makeprg=latex\ \\\\nonstopmode\ \\\\input\\{$*}
< This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
]=],
@@ -5105,12 +5109,12 @@ return {
jump between two double quotes.
The characters must be separated by a colon.
The pairs must be separated by a comma. Example for including '<' and
- '>' (for HTML): >
- :set mps+=<:>
+ '>' (for HTML): >vim
+ set mps+=<:>
< A more exotic example, to jump between the '=' and ';' in an
- assignment, useful for languages like C and Java: >
- :au FileType c,cpp,java set mps+==:;
+ assignment, useful for languages like C and Java: >vim
+ au FileType c,cpp,java set mps+==:;
< For a more advanced way of using "%", see the matchit.vim plugin in
the $VIMRUNTIME/plugin directory. |add-local-help|
@@ -5156,6 +5160,7 @@ return {
Increasing this limit above 200 also changes the maximum for Ex
command recursion, see |E169|.
See also |:function|.
+ Also used for maximum depth of callback functions.
]=],
full_name = 'maxfuncdepth',
scope = { 'global' },
@@ -5250,8 +5255,8 @@ return {
The languages for which these numbers are important are Italian and
Hungarian. The default works for when you have about 512 Mbyte. If
- you have 1 Gbyte you could use: >
- :set mkspellmem=900000,3000,800
+ you have 1 Gbyte you could use: >vim
+ set mkspellmem=900000,3000,800
< If you have less than 512 Mbyte |:mkspell| may fail for some
languages, no matter what you set 'mkspellmem' to.
@@ -5280,7 +5285,7 @@ return {
full_name = 'modeline',
scope = { 'buffer' },
short_desc = N_('recognize modelines at start or end of file'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ml',
},
{
@@ -5297,7 +5302,7 @@ return {
scope = { 'global' },
secure = true,
short_desc = N_('allow some options to be set in modeline'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_mle',
},
{
@@ -5329,7 +5334,7 @@ return {
scope = { 'buffer' },
short_desc = N_('changes to the text are not possible'),
tags = { 'E21' },
- type = 'bool',
+ type = 'boolean',
varname = 'p_ma',
},
{
@@ -5364,7 +5369,7 @@ return {
redraw = { 'statuslines' },
scope = { 'buffer' },
short_desc = N_('buffer has been modified'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_mod',
},
{
@@ -5377,7 +5382,7 @@ return {
full_name = 'more',
scope = { 'global' },
short_desc = N_('listings when the whole screen is filled'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_more',
},
{
@@ -5385,8 +5390,8 @@ return {
defaults = { if_true = 'nvi' },
desc = [=[
Enables mouse support. For example, to enable the mouse in Normal mode
- and Visual mode: >
- :set mouse=nv
+ and Visual mode: >vim
+ set mouse=nv
<
To temporarily disable mouse support, hold the shift key while using
the mouse.
@@ -5443,7 +5448,7 @@ return {
redraw = { 'ui_option' },
scope = { 'global' },
short_desc = N_('keyboard focus follows the mouse'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_mousef',
},
{
@@ -5459,7 +5464,7 @@ return {
redraw = { 'ui_option' },
scope = { 'global' },
short_desc = N_('hide mouse pointer while typing'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_mh',
},
{
@@ -5496,19 +5501,19 @@ return {
Note that you can further refine the meaning of buttons with mappings.
See |mouse-overview|. But mappings are NOT used for modeless selection.
- Example: >
- :map <S-LeftMouse> <RightMouse>
- :map <S-LeftDrag> <RightDrag>
- :map <S-LeftRelease> <RightRelease>
- :map <2-S-LeftMouse> <2-RightMouse>
- :map <2-S-LeftDrag> <2-RightDrag>
- :map <2-S-LeftRelease> <2-RightRelease>
- :map <3-S-LeftMouse> <3-RightMouse>
- :map <3-S-LeftDrag> <3-RightDrag>
- :map <3-S-LeftRelease> <3-RightRelease>
- :map <4-S-LeftMouse> <4-RightMouse>
- :map <4-S-LeftDrag> <4-RightDrag>
- :map <4-S-LeftRelease> <4-RightRelease>
+ Example: >vim
+ map <S-LeftMouse> <RightMouse>
+ map <S-LeftDrag> <RightDrag>
+ map <S-LeftRelease> <RightRelease>
+ map <2-S-LeftMouse> <2-RightMouse>
+ map <2-S-LeftDrag> <2-RightDrag>
+ map <2-S-LeftRelease> <2-RightRelease>
+ map <3-S-LeftMouse> <3-RightMouse>
+ map <3-S-LeftDrag> <3-RightDrag>
+ map <3-S-LeftRelease> <3-RightRelease>
+ map <4-S-LeftMouse> <4-RightMouse>
+ map <4-S-LeftDrag> <4-RightDrag>
+ map <4-S-LeftRelease> <4-RightRelease>
<
Mouse commands requiring the CTRL modifier can be simulated by typing
the "g" key before using the mouse:
@@ -5536,7 +5541,7 @@ return {
redraw = { 'ui_option' },
scope = { 'global' },
short_desc = N_('deliver mouse move events to input queue'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_mousemev',
},
{
@@ -5556,8 +5561,8 @@ return {
for vertical scrolling). You can disable mouse scrolling by using
a count of 0.
- Example: >
- :set mousescroll=ver:5,hor:2
+ Example: >vim
+ set mousescroll=ver:5,hor:2
< Will make Nvim scroll 5 lines at a time when scrolling vertically, and
scroll 2 columns at a time when scrolling horizontally.
]=],
@@ -5633,8 +5638,8 @@ return {
Any modes not specified or shapes not available use the normal mouse
pointer.
- Example: >
- :set mouseshape=s:udsizing,m:no
+ Example: >vim
+ set mouseshape=s:udsizing,m:no
< will make the mouse turn to a sizing arrow over the status lines and
indicate no input when the hit-enter prompt is displayed (since
clicking the mouse has no effect in this state.)
@@ -5733,7 +5738,7 @@ return {
redraw = { 'current_window' },
scope = { 'window' },
short_desc = N_('print the line number in front of each line'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'nuw',
@@ -5797,7 +5802,7 @@ return {
full_name = 'opendevice',
scope = { 'global' },
short_desc = N_('allow reading/writing devices on MS-Windows'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'opfunc',
@@ -5864,7 +5869,7 @@ return {
pri_mkrc = true,
scope = { 'global' },
short_desc = N_('pasting text'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_paste',
},
{
@@ -5932,30 +5937,30 @@ return {
provided that the file being searched for has a relative path (not
starting with "/", "./" or "../"). The directories in the 'path'
option may be relative or absolute.
- - Use commas to separate directory names: >
- :set path=.,/usr/local/include,/usr/include
+ - Use commas to separate directory names: >vim
+ set path=.,/usr/local/include,/usr/include
< - Spaces can also be used to separate directory names. To have a
space in a directory name, precede it with an extra backslash, and
- escape the space: >
- :set path=.,/dir/with\\\ space
+ escape the space: >vim
+ set path=.,/dir/with\\\ space
< - To include a comma in a directory name precede it with an extra
- backslash: >
- :set path=.,/dir/with\\,comma
- < - To search relative to the directory of the current file, use: >
- :set path=.
+ backslash: >vim
+ set path=.,/dir/with\\,comma
+ < - To search relative to the directory of the current file, use: >vim
+ set path=.
< - To search in the current directory use an empty string between two
- commas: >
- :set path=,,
+ commas: >vim
+ set path=,,
< - A directory name may end in a ':' or '/'.
- Environment variables are expanded |:set_env|.
- When using |netrw.vim| URLs can be used. For example, adding
"https://www.vim.org" will make ":find index.html" work.
- Search upwards and downwards in a directory tree using "*", "**" and
";". See |file-searching| for info and syntax.
- - Careful with '\' characters, type two to get one in the option: >
- :set path=.,c:\\include
- < Or just use '/' instead: >
- :set path=.,c:/include
+ - Careful with '\' characters, type two to get one in the option: >vim
+ set path=.,c:\\include
+ < Or just use '/' instead: >vim
+ set path=.,c:/include
< Don't forget "." or files won't even be found in the same directory as
the file!
The maximum length is limited. How much depends on the system, mostly
@@ -5964,14 +5969,14 @@ return {
'path', see |:checkpath|.
The use of |:set+=| and |:set-=| is preferred when adding or removing
directories from the list. This avoids problems when a future version
- uses another default. To remove the current directory use: >
- :set path-=
- < To add the current directory use: >
- :set path+=
+ uses another default. To remove the current directory use: >vim
+ set path-=
+ < To add the current directory use: >vim
+ set path+=
< To use an environment variable, you probably need to replace the
separator. Here is an example to append $INCL, in which directory
- names are separated with a semi-colon: >
- :let &path = &path .. "," .. substitute($INCL, ';', ',', 'g')
+ names are separated with a semi-colon: >vim
+ let &path = &path .. "," .. substitute($INCL, ';', ',', 'g')
< Replace the ';' with a ':' or whatever separator is used. Note that
this doesn't work when $INCL contains a comma or white space.
]=],
@@ -6004,7 +6009,7 @@ return {
full_name = 'preserveindent',
scope = { 'buffer' },
short_desc = N_('preserve the indent structure when reindenting'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_pi',
},
{
@@ -6035,14 +6040,14 @@ return {
scope = { 'window' },
short_desc = N_('identifies the preview window'),
tags = { 'E590' },
- type = 'bool',
+ type = 'boolean',
},
{
defaults = { if_true = true },
full_name = 'prompt',
scope = { 'global' },
short_desc = N_('enable prompt in Ex mode'),
- type = 'bool',
+ type = 'boolean',
immutable = true,
},
{
@@ -6056,10 +6061,10 @@ return {
It is possible to override the level for individual highlights within
the popupmenu using |highlight-blend|. For instance, to enable
- transparency but force the current selected element to be fully opaque: >
+ transparency but force the current selected element to be fully opaque: >vim
- :set pumblend=15
- :hi PmenuSel blend=0
+ set pumblend=15
+ hi PmenuSel blend=0
<
UI-dependent. Works best with RGB colors. 'termguicolors'
]=],
@@ -6176,7 +6181,7 @@ return {
redraw = { 'statuslines' },
scope = { 'buffer' },
short_desc = N_('disallow writing the buffer'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ro',
},
{
@@ -6292,14 +6297,14 @@ return {
redraw = { 'current_window' },
scope = { 'window' },
short_desc = N_('show relative line number in front of each line'),
- type = 'bool',
+ type = 'boolean',
},
{
defaults = { if_true = true },
full_name = 'remap',
scope = { 'global' },
short_desc = N_('No description'),
- type = 'bool',
+ type = 'boolean',
immutable = true,
},
{
@@ -6328,7 +6333,7 @@ return {
full_name = 'revins',
scope = { 'global' },
short_desc = N_('inserting characters will work backwards'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ri',
},
{
@@ -6349,7 +6354,7 @@ return {
redraw = { 'current_window' },
scope = { 'window' },
short_desc = N_('window is right-to-left oriented'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'rlc',
@@ -6403,7 +6408,7 @@ return {
redraw = { 'statuslines' },
scope = { 'global' },
short_desc = N_('show cursor line and column in the status line'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ru',
},
{
@@ -6419,8 +6424,8 @@ return {
The default ruler width is 17 characters. To make the ruler 15
characters wide, put "%15(" at the start and "%)" at the end.
- Example: >
- :set rulerformat=%15(%c%V\ %p%%%)
+ Example: >vim
+ set rulerformat=%15(%c%V\ %p%%%)
<
]=],
full_name = 'rulerformat',
@@ -6513,8 +6518,8 @@ return {
runtime files. For speed, use as few items as possible and avoid
wildcards.
See |:runtime|.
- Example: >
- :set runtimepath=~/vimruntime,/mygroup/vim,$VIMRUNTIME
+ Example: >vim
+ set runtimepath=~/vimruntime,/mygroup/vim,$VIMRUNTIME
< This will use the directory "~/vimruntime" first (containing your
personal Nvim runtime files), then "/mygroup/vim", and finally
"$VIMRUNTIME" (the default runtime files).
@@ -6557,27 +6562,6 @@ return {
type = 'number',
},
{
- abbreviation = 'sms',
- cb = 'did_set_smoothscroll',
- defaults = { if_true = false },
- desc = [=[
- Scrolling works with screen lines. When 'wrap' is set and the first
- line in the window wraps part of it may not be visible, as if it is
- above the window. "<<<" is displayed at the start of the first line,
- highlighted with |hl-NonText|.
- You may also want to add "lastline" to the 'display' option to show as
- much of the last line as possible.
- NOTE: only partly implemented, currently works with CTRL-E, CTRL-Y
- and scrolling with the mouse.
- ]=],
- full_name = 'smoothscroll',
- pv_name = 'p_sms',
- redraw = { 'current_window' },
- scope = { 'window' },
- short_desc = N_("scroll by screen lines when 'wrap' is set"),
- type = 'bool',
- },
- {
abbreviation = 'scbk',
cb = 'did_set_scrollback',
defaults = {
@@ -6619,7 +6603,7 @@ return {
pv_name = 'p_scbind',
scope = { 'window' },
short_desc = N_('scroll in window as other windows scroll'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'sj',
@@ -6648,7 +6632,7 @@ return {
in the middle of the window (except at the start or end of the file or
when long lines wrap).
After using the local value, go back the global value with one of
- these two: >
+ these two: >vim
setlocal scrolloff<
setlocal scrolloff=-1
< For scrolling horizontally see 'sidescrolloff'.
@@ -6721,7 +6705,7 @@ return {
scope = { 'global' },
secure = true,
short_desc = N_('No description'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_secure',
},
{
@@ -6830,6 +6814,7 @@ return {
},
{
abbreviation = 'sd',
+ alias = { 'vi', 'viminfo' },
cb = 'did_set_shada',
defaults = {
if_true = "!,'100,<50,s10,h",
@@ -6927,8 +6912,8 @@ return {
2^8 < 10240 < 2^16) + 10240 bytes (requested maximum item
contents size) = 10253 bytes.
- Example: >
- :set shada='50,<1000,s100,:0,n~/nvim/shada
+ Example: >vim
+ set shada='50,<1000,s100,:0,n~/nvim/shada
<
'50 Marks will be remembered for the last 50 files you
edited.
@@ -6961,6 +6946,7 @@ return {
},
{
abbreviation = 'sdf',
+ alias = { 'vif', 'viminfofile' },
defaults = { if_true = '' },
deny_duplicates = true,
desc = [=[
@@ -6998,12 +6984,12 @@ return {
Environment variables are expanded |:set_env|.
If the name of the shell contains a space, you need to enclose it in
- quotes. Example with quotes: >
- :set shell=\"c:\program\ files\unix\sh.exe\"\ -f
+ quotes. Example with quotes: >vim
+ set shell=\"c:\program\ files\unix\sh.exe\"\ -f
< Note the backslash before each quote (to avoid starting a comment) and
each space (to avoid ending the option value), so better use |:let-&|
- like this: >
- :let &shell='"C:\Program Files\unix\sh.exe" -f'
+ like this: >vim
+ let &shell='"C:\Program Files\unix\sh.exe" -f'
< Also note that the "-f" is not inside the quotes, because it is not
part of the command name.
*shell-unquoting*
@@ -7026,7 +7012,7 @@ return {
Note that such processing is done after |:set| did its own round of
unescaping, so to keep yourself sane use |:let-&| like shown above.
*shell-powershell*
- To use PowerShell: >
+ To use PowerShell: >vim
let &shell = executable('pwsh') ? 'pwsh' : 'powershell'
let &shellcmdflag = '-NoLogo -ExecutionPolicy RemoteSigned -Command [Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new();$PSDefaultParameterValues[''Out-File:Encoding'']=''utf8'';Remove-Alias -Force -ErrorAction SilentlyContinue tee;'
let &shellredir = '2>&1 | %%{ "$_" } | Out-File %s; exit $LastExitCode'
@@ -7197,7 +7183,7 @@ return {
existing file names, thus this option needs to be set before opening
any file for best results. This might change in the future.
'shellslash' only works when a backslash can be used as a path
- separator. To test if this is so use: >
+ separator. To test if this is so use: >vim
if exists('+shellslash')
< Also see 'completeslash'.
]=],
@@ -7205,7 +7191,7 @@ return {
full_name = 'shellslash',
scope = { 'global' },
short_desc = N_('use forward slash for shell file names'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ssl',
},
{
@@ -7226,10 +7212,27 @@ return {
full_name = 'shelltemp',
scope = { 'global' },
short_desc = N_('whether to use a temp file for shell commands'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_stmp',
},
{
+ abbreviation = 'sxe',
+ defaults = { if_true = '' },
+ desc = [=[
+ When 'shellxquote' is set to "(" then the characters listed in this
+ option will be escaped with a '^' character. This makes it possible
+ to execute most external commands with cmd.exe.
+ This option cannot be set from a |modeline| or in the |sandbox|, for
+ security reasons.
+ ]=],
+ full_name = 'shellxescape',
+ scope = { 'global' },
+ secure = true,
+ short_desc = N_("characters to escape when 'shellxquote' is ("),
+ type = 'string',
+ varname = 'p_sxe',
+ },
+ {
abbreviation = 'sxq',
defaults = {
condition = 'MSWIN',
@@ -7256,23 +7259,6 @@ return {
varname = 'p_sxq',
},
{
- abbreviation = 'sxe',
- defaults = { if_true = '' },
- desc = [=[
- When 'shellxquote' is set to "(" then the characters listed in this
- option will be escaped with a '^' character. This makes it possible
- to execute most external commands with cmd.exe.
- This option cannot be set from a |modeline| or in the |sandbox|, for
- security reasons.
- ]=],
- full_name = 'shellxescape',
- scope = { 'global' },
- secure = true,
- short_desc = N_("characters to escape when 'shellxquote' is ("),
- type = 'string',
- varname = 'p_sxe',
- },
- {
abbreviation = 'sr',
defaults = { if_true = false },
desc = [=[
@@ -7283,7 +7269,7 @@ return {
full_name = 'shiftround',
scope = { 'global' },
short_desc = N_('round indent to multiple of shiftwidth'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_sr',
},
{
@@ -7343,9 +7329,10 @@ return {
match", "Pattern not found", "Back at original", etc.
C don't give messages while scanning for ins-completion *shm-C*
items, for instance "scanning tags"
- q use "recording" instead of "recording @a" *shm-q*
+ q do not show "recording @a" when recording a macro *shm-q*
F don't give the file info when editing a file, like *shm-F*
- `:silent` was used for the command
+ `:silent` was used for the command; note that this also
+ affects messages from 'autoread' reloading
S do not show search count message when searching, e.g. *shm-S*
"[1/5]"
@@ -7373,9 +7360,9 @@ return {
defaults = { if_true = '' },
desc = [=[
String to put at the start of lines that have been wrapped. Useful
- values are "> " or "+++ ": >
- :let &showbreak = "> "
- :let &showbreak = '+++ '
+ values are "> " or "+++ ": >vim
+ let &showbreak = "> "
+ let &showbreak = '+++ '
< Only printable single-cell characters are allowed, excluding <Tab> and
comma (in a future version the comma might be used to separate the
part that is shown at the end and at the start of a line).
@@ -7384,8 +7371,8 @@ return {
If you want the 'showbreak' to appear in between line numbers, add the
"n" flag to 'cpoptions'.
A window-local value overrules a global value. If the global value is
- set and you want no value in the current window use NONE: >
- :setlocal showbreak=NONE
+ set and you want no value in the current window use NONE: >vim
+ setlocal showbreak=NONE
<
]=],
full_name = 'showbreak',
@@ -7415,7 +7402,7 @@ return {
full_name = 'showcmd',
scope = { 'global' },
short_desc = N_('show (partial) command in status line'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_sc',
},
{
@@ -7458,7 +7445,7 @@ return {
full_name = 'showfulltag',
scope = { 'global' },
short_desc = N_('show full tag pattern when completing tag'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_sft',
},
{
@@ -7484,7 +7471,7 @@ return {
full_name = 'showmatch',
scope = { 'global' },
short_desc = N_('briefly jump to matching bracket if insert one'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_sm',
},
{
@@ -7498,7 +7485,7 @@ return {
full_name = 'showmode',
scope = { 'global' },
short_desc = N_('message on status line to show current mode'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_smd',
},
{
@@ -7551,16 +7538,16 @@ return {
horizontally centered in the window, as long as one does not come too
close to the beginning of the line.
After using the local value, go back the global value with one of
- these two: >
+ these two: >vim
setlocal sidescrolloff<
setlocal sidescrolloff=-1
<
Example: Try this together with 'sidescroll' and 'listchars' as
in the following example to never allow the cursor to move
- onto the "extends" character: >
+ onto the "extends" character: >vim
- :set nowrap sidescroll=1 listchars=extends:>,precedes:<
- :set sidescrolloff=1
+ set nowrap sidescroll=1 listchars=extends:>,precedes:<
+ set sidescrolloff=1
<
]=],
full_name = 'sidescrolloff',
@@ -7613,7 +7600,7 @@ return {
full_name = 'smartcase',
scope = { 'global' },
short_desc = N_('no ignore case when pattern has uppercase'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_scs',
},
{
@@ -7643,7 +7630,7 @@ return {
full_name = 'smartindent',
scope = { 'buffer' },
short_desc = N_('smart autoindenting for C programs'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_si',
},
{
@@ -7664,10 +7651,31 @@ return {
full_name = 'smarttab',
scope = { 'global' },
short_desc = N_("use 'shiftwidth' when inserting <Tab>"),
- type = 'bool',
+ type = 'boolean',
varname = 'p_sta',
},
{
+ abbreviation = 'sms',
+ cb = 'did_set_smoothscroll',
+ defaults = { if_true = false },
+ desc = [=[
+ Scrolling works with screen lines. When 'wrap' is set and the first
+ line in the window wraps part of it may not be visible, as if it is
+ above the window. "<<<" is displayed at the start of the first line,
+ highlighted with |hl-NonText|.
+ You may also want to add "lastline" to the 'display' option to show as
+ much of the last line as possible.
+ NOTE: only partly implemented, currently works with CTRL-E, CTRL-Y
+ and scrolling with the mouse.
+ ]=],
+ full_name = 'smoothscroll',
+ pv_name = 'p_sms',
+ redraw = { 'current_window' },
+ scope = { 'window' },
+ short_desc = N_("scroll by screen lines when 'wrap' is set"),
+ type = 'boolean',
+ },
+ {
abbreviation = 'sts',
defaults = { if_true = 0 },
desc = [=[
@@ -7701,10 +7709,10 @@ return {
The languages are specified with 'spelllang'.
]=],
full_name = 'spell',
- redraw = { 'current_window' },
+ redraw = { 'current_window', 'highlight_only' },
scope = { 'window' },
short_desc = N_('spell checking'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'spc',
@@ -7723,7 +7731,7 @@ return {
|set-spc-auto|.
]=],
full_name = 'spellcapcheck',
- redraw = { 'current_buffer' },
+ redraw = { 'current_buffer', 'highlight_only' },
scope = { 'buffer' },
short_desc = N_('pattern to locate end of a sentence'),
type = 'string',
@@ -7739,7 +7747,7 @@ return {
Name of the word list file where words are added for the |zg| and |zw|
commands. It must end in ".{encoding}.add". You need to include the
path, otherwise the file is placed in the current directory.
- The path may include characters from 'isfname', space, comma and '@'.
+ The path may include characters from 'isfname', ' ', ',', '@' and ':'.
*E765*
It may also be a comma-separated list of names. A count before the
|zg| and |zw| commands can be used to access each. This allows using
@@ -7775,7 +7783,7 @@ return {
deny_duplicates = true,
desc = [=[
A comma-separated list of word list names. When the 'spell' option is
- on spellchecking will be done for these languages. Example: >
+ on spellchecking will be done for these languages. Example: >vim
set spelllang=en_us,nl,medical
< This means US English, Dutch and medical words are recognized. Words
that are not recognized will be highlighted.
@@ -7814,13 +7822,38 @@ return {
expand = true,
full_name = 'spelllang',
list = 'onecomma',
- redraw = { 'current_buffer' },
+ redraw = { 'current_buffer', 'highlight_only' },
scope = { 'buffer' },
short_desc = N_('language(s) to do spell checking for'),
type = 'string',
varname = 'p_spl',
},
{
+ abbreviation = 'spo',
+ cb = 'did_set_spelloptions',
+ defaults = { if_true = '' },
+ deny_duplicates = true,
+ desc = [=[
+ A comma-separated list of options for spell checking:
+ camel When a word is CamelCased, assume "Cased" is a
+ separate word: every upper-case character in a word
+ that comes after a lower case character indicates the
+ start of a new word.
+ noplainbuffer Only spellcheck a buffer when 'syntax' is enabled,
+ or when extmarks are set within the buffer. Only
+ designated regions of the buffer are spellchecked in
+ this case.
+ ]=],
+ expand_cb = 'expand_set_spelloptions',
+ full_name = 'spelloptions',
+ list = 'onecomma',
+ redraw = { 'current_buffer', 'highlight_only' },
+ scope = { 'buffer' },
+ secure = true,
+ type = 'string',
+ varname = 'p_spo',
+ },
+ {
abbreviation = 'sps',
cb = 'did_set_spellsuggest',
defaults = { if_true = 'best' },
@@ -7884,8 +7917,8 @@ return {
'verbose' option to a non-zero value.
Only one of "best", "double" or "fast" may be used. The others may
- appear several times in any order. Example: >
- :set sps=file:~/.config/nvim/sugg,best,expr:MySuggest()
+ appear several times in any order. Example: >vim
+ set sps=file:~/.config/nvim/sugg,best,expr:MySuggest()
<
This option cannot be set from a |modeline| or in the |sandbox|, for
security reasons.
@@ -7901,31 +7934,6 @@ return {
varname = 'p_sps',
},
{
- abbreviation = 'spo',
- cb = 'did_set_spelloptions',
- defaults = { if_true = '' },
- deny_duplicates = true,
- desc = [=[
- A comma-separated list of options for spell checking:
- camel When a word is CamelCased, assume "Cased" is a
- separate word: every upper-case character in a word
- that comes after a lower case character indicates the
- start of a new word.
- noplainbuffer Only spellcheck a buffer when 'syntax' is enabled,
- or when extmarks are set within the buffer. Only
- designated regions of the buffer are spellchecked in
- this case.
- ]=],
- expand_cb = 'expand_set_spelloptions',
- full_name = 'spelloptions',
- list = 'onecomma',
- redraw = { 'current_buffer' },
- scope = { 'buffer' },
- secure = true,
- type = 'string',
- varname = 'p_spo',
- },
- {
abbreviation = 'sb',
defaults = { if_true = false },
desc = [=[
@@ -7935,7 +7943,7 @@ return {
full_name = 'splitbelow',
scope = { 'global' },
short_desc = N_('new window from split is below the current one'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_sb',
},
{
@@ -7973,7 +7981,7 @@ return {
full_name = 'splitright',
scope = { 'global' },
short_desc = N_('new window is put right of the current one'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_spr',
},
{
@@ -7994,7 +8002,7 @@ return {
full_name = 'startofline',
scope = { 'global' },
short_desc = N_('commands move cursor to first non-blank in line'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_sol',
vim = false,
},
@@ -8017,9 +8025,13 @@ return {
%s sign column for currently drawn line
%C fold column for currently drawn line
- NOTE: To draw the sign and fold columns, their items must be included in
- 'statuscolumn'. Even when they are not included, the status column width
- will adapt to the 'signcolumn' and 'foldcolumn' width.
+ The 'statuscolumn' width follows that of the default columns and
+ adapts to the |'numberwidth'|, |'signcolumn'| and |'foldcolumn'| option
+ values (regardless of whether the sign and fold items are present).
+ Additionally, the 'statuscolumn' grows with the size of the evaluated
+ format string, up to a point (following the maximum size of the default
+ fold, sign and number columns). Shrinking only happens when the number
+ of lines in a buffer changes, or the 'statuscolumn' option is set.
The |v:lnum| variable holds the line number to be drawn.
The |v:relnum| variable holds the relative line number to be drawn.
@@ -8027,6 +8039,9 @@ return {
when drawing the actual buffer line, and positive when
drawing the wrapped part of a buffer line.
+ When using |v:relnum|, keep in mind that cursor movement by itself will
+ not cause the 'statuscolumn' to update unless |'relativenumber'| is set.
+
NOTE: The %@ click execute function item is supported as well but the
specified function will be the same for each row in the same column.
It cannot be switched out through a dynamic 'statuscolumn' format, the
@@ -8034,21 +8049,21 @@ return {
Examples: >vim
" Relative number with bar separator and click handlers:
- :set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T
+ set statuscolumn=%@SignCb@%s%=%T%@NumCb@%r│%T
" Right aligned relative cursor line number:
- :let &stc='%=%{v:relnum?v:relnum:v:lnum} '
+ let &stc='%=%{v:relnum?v:relnum:v:lnum} '
" Line numbers in hexadecimal for non wrapped part of lines:
- :let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} '
+ let &stc='%=%{v:virtnum>0?"":printf("%x",v:lnum)} '
" Human readable line numbers with thousands separator:
- :let &stc='%{substitute(v:lnum,"\\d\\zs\\ze\\'
+ let &stc='%{substitute(v:lnum,"\\d\\zs\\ze\\'
. '%(\\d\\d\\d\\)\\+$",",","g")}'
" Both relative and absolute line numbers with different
" highlighting for odd and even relative numbers:
- :let &stc='%#NonText#%{&nu?v:lnum:""}' .
+ let &stc='%#NonText#%{&nu?v:lnum:""}' .
'%=%{&rnu&&(v:lnum%2)?"\ ".v:relnum:""}' .
'%#LineNr#%{&rnu&&!(v:lnum%2)?"\ ".v:relnum:""}'
@@ -8078,8 +8093,8 @@ return {
be given as "%%".
When the option starts with "%!" then it is used as an expression,
- evaluated and the result is used as the option value. Example: >
- :set statusline=%!MyStatusLine()
+ evaluated and the result is used as the option value. Example: >vim
+ set statusline=%!MyStatusLine()
< The *g:statusline_winid* variable will be set to the |window-ID| of the
window that the status line belongs to.
The result can contain %{} items that will be evaluated too.
@@ -8160,7 +8175,7 @@ return {
return value of expr contains "%" items they will get expanded.
The expression can contain the "}" character, the end of
expression is denoted by "%}".
- For example: >
+ For example: >vim
func! Stl_filename() abort
return "%t"
endfunc
@@ -8172,16 +8187,17 @@ return {
) - End of item group. No width fields allowed.
T N For 'tabline': start of tab page N label. Use %T or %X to end
the label. Clicking this label with left mouse button switches
- to the specified tab page.
+ to the specified tab page, while clicking it with middle mouse
+ button closes the specified tab page.
X N For 'tabline': start of close tab N label. Use %X or %T to end
the label, e.g.: %3Xclose%X. Use %999X for a "close current
- tab" label. Clicking this label with left mouse button closes
- specified tab page.
- @ N Start of execute function label. Use %X or %T to
- end the label, e.g.: %10@SwitchBuffer@foo.c%X. Clicking this
- label runs specified function: in the example when clicking once
- using left mouse button on "foo.c" "SwitchBuffer(10, 1, 'l',
- ' ')" expression will be run. Function receives the
+ tab" label. Clicking this label with left mouse button closes
+ the specified tab page.
+ @ N Start of execute function label. Use %X or %T to end the label,
+ e.g.: %10@SwitchBuffer@foo.c%X. Clicking this label runs the
+ specified function: in the example when clicking once using left
+ mouse button on "foo.c", a `SwitchBuffer(10, 1, 'l', ' ')`
+ expression will be run. The specified function receives the
following arguments in order:
1. minwid field value or zero if no N was specified
2. number of mouse clicks to detect multiple clicks
@@ -8227,8 +8243,8 @@ return {
When all items in a group becomes an empty string (i.e. flags that are
not set) and a minwid is not set for the group, the whole group will
become empty. This will make a group like the following disappear
- completely from the statusline when none of the flags are set. >
- :set statusline=...%(\ [%M%R%H]%)...
+ completely from the statusline when none of the flags are set. >vim
+ set statusline=...%(\ [%M%R%H]%)...
< Beware that an expression is evaluated each and every time the status
line is displayed.
*stl-%{* *g:actual_curbuf* *g:actual_curwin*
@@ -8259,23 +8275,23 @@ return {
edit your vimrc or whatever with "vim --clean" to get it right.
Examples:
- Emulate standard status line with 'ruler' set >
- :set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
- < Similar, but add ASCII value of char under the cursor (like "ga") >
- :set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P
- < Display byte count and byte value, modified flag in red. >
- :set statusline=%<%f%=\ [%1*%M%*%n%R%H]\ %-19(%3l,%02c%03V%)%O'%02b'
- :hi User1 term=inverse,bold cterm=inverse,bold ctermfg=red
- < Display a ,GZ flag if a compressed file is loaded >
- :set statusline=...%r%{VarExists('b:gzflag','\ [GZ]')}%h...
- < In the |:autocmd|'s: >
- :let b:gzflag = 1
- < And: >
- :unlet b:gzflag
- < And define this function: >
- :function VarExists(var, val)
- : if exists(a:var) | return a:val | else | return '' | endif
- :endfunction
+ Emulate standard status line with 'ruler' set >vim
+ set statusline=%<%f\ %h%m%r%=%-14.(%l,%c%V%)\ %P
+ < Similar, but add ASCII value of char under the cursor (like "ga") >vim
+ set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P
+ < Display byte count and byte value, modified flag in red. >vim
+ set statusline=%<%f%=\ [%1*%M%*%n%R%H]\ %-19(%3l,%02c%03V%)%O'%02b'
+ hi User1 term=inverse,bold cterm=inverse,bold ctermfg=red
+ < Display a ,GZ flag if a compressed file is loaded >vim
+ set statusline=...%r%{VarExists('b:gzflag','\ [GZ]')}%h...
+ < In the |:autocmd|'s: >vim
+ let b:gzflag = 1
+ < And: >vim
+ unlet b:gzflag
+ < And define this function: >vim
+ function VarExists(var, val)
+ if exists(a:var) | return a:val | else | return '' | endif
+ endfunction
<
]=],
full_name = 'statusline',
@@ -8317,8 +8333,8 @@ return {
deny_duplicates = true,
desc = [=[
Comma-separated list of suffixes, which are used when searching for a
- file for the "gf", "[I", etc. commands. Example: >
- :set suffixesadd=.java
+ file for the "gf", "[I", etc. commands. Example: >vim
+ set suffixesadd=.java
<
]=],
full_name = 'suffixesadd',
@@ -8356,7 +8372,7 @@ return {
redraw = { 'statuslines' },
scope = { 'buffer' },
short_desc = N_('whether to use a swapfile for a buffer'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_swf',
},
{
@@ -8428,19 +8444,19 @@ return {
Otherwise this option does not always reflect the current syntax (the
b:current_syntax variable does).
This option is most useful in a modeline, for a file which syntax is
- not automatically recognized. Example, in an IDL file: >
+ not automatically recognized. Example, in an IDL file: >c
/* vim: set syntax=idl : */
< When a dot appears in the value then this separates two filetype
- names. Example: >
+ names. Example: >c
/* vim: set syntax=c.doxygen : */
< This will use the "c" syntax first, then the "doxygen" syntax.
Note that the second one must be prepared to be loaded as an addition,
otherwise it will be skipped. More than one dot may appear.
- To switch off syntax highlighting for the current file, use: >
- :set syntax=OFF
+ To switch off syntax highlighting for the current file, use: >vim
+ set syntax=OFF
< To switch syntax highlighting on according to the current value of the
- 'filetype' option: >
- :set syntax=ON
+ 'filetype' option: >vim
+ set syntax=ON
< What actually happens when setting the 'syntax' option is that the
Syntax autocommand event is triggered with the value as argument.
This option is not copied to another buffer, independent of the 's' or
@@ -8456,28 +8472,6 @@ return {
varname = 'p_syn',
},
{
- abbreviation = 'tfu',
- cb = 'did_set_tagfunc',
- defaults = { if_true = '' },
- desc = [=[
- This option specifies a function to be used to perform tag searches.
- The function gets the tag pattern and should return a List of matching
- tags. See |tag-function| for an explanation of how to write the
- function and an example. The value can be the name of a function, a
- |lambda| or a |Funcref|. See |option-value-function| for more
- information.
- This option cannot be set from a |modeline| or in the |sandbox|, for
- security reasons.
- ]=],
- full_name = 'tagfunc',
- func = true,
- scope = { 'buffer' },
- secure = true,
- short_desc = N_('function used to perform tag searches'),
- type = 'string',
- varname = 'p_tfu',
- },
- {
abbreviation = 'tal',
cb = 'did_set_tabline',
defaults = { if_true = '' },
@@ -8632,7 +8626,7 @@ return {
full_name = 'tagbsearch',
scope = { 'global' },
short_desc = N_('use binary searching in tags files'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_tbs',
},
{
@@ -8656,6 +8650,28 @@ return {
varname = 'p_tc',
},
{
+ abbreviation = 'tfu',
+ cb = 'did_set_tagfunc',
+ defaults = { if_true = '' },
+ desc = [=[
+ This option specifies a function to be used to perform tag searches.
+ The function gets the tag pattern and should return a List of matching
+ tags. See |tag-function| for an explanation of how to write the
+ function and an example. The value can be the name of a function, a
+ |lambda| or a |Funcref|. See |option-value-function| for more
+ information.
+ This option cannot be set from a |modeline| or in the |sandbox|, for
+ security reasons.
+ ]=],
+ full_name = 'tagfunc',
+ func = true,
+ scope = { 'buffer' },
+ secure = true,
+ short_desc = N_('function used to perform tag searches'),
+ type = 'string',
+ varname = 'p_tfu',
+ },
+ {
abbreviation = 'tl',
defaults = { if_true = 0 },
desc = [=[
@@ -8677,7 +8693,7 @@ return {
full_name = 'tagrelative',
scope = { 'global' },
short_desc = N_('file names in tag file are relative'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_tr',
},
{
@@ -8727,7 +8743,7 @@ return {
full_name = 'tagstack',
scope = { 'global' },
short_desc = N_('push tags onto the tag stack'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_tgst',
},
{
@@ -8746,7 +8762,7 @@ return {
full_name = 'termbidi',
scope = { 'global' },
short_desc = N_('terminal takes care of bi-directionality'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_tbidi',
},
{
@@ -8764,12 +8780,16 @@ return {
Enables 24-bit RGB color in the |TUI|. Uses "gui" |:highlight|
attributes instead of "cterm" attributes. |guifg|
Requires an ISO-8613-3 compatible terminal.
+
+ Nvim will automatically attempt to determine if the host terminal
+ supports 24-bit color and will enable this option if it does
+ (unless explicitly disabled by the user).
]=],
full_name = 'termguicolors',
redraw = { 'ui_option' },
scope = { 'global' },
short_desc = N_('Terminal true color support'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_tgc',
},
{
@@ -8816,7 +8836,7 @@ return {
redraw = { 'ui_option' },
scope = { 'global' },
short_desc = N_('synchronize redraw output with the host terminal'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_termsync',
},
{
@@ -8824,7 +8844,7 @@ return {
full_name = 'terse',
scope = { 'global' },
short_desc = N_('No description'),
- type = 'bool',
+ type = 'boolean',
immutable = true,
},
{
@@ -8840,7 +8860,7 @@ return {
When 'formatexpr' is set it will be used to break the line.
]=],
full_name = 'textwidth',
- redraw = { 'current_buffer' },
+ redraw = { 'current_buffer', 'highlight_only' },
scope = { 'buffer' },
short_desc = N_('maximum width of text that is being inserted'),
type = 'number',
@@ -8906,7 +8926,7 @@ return {
full_name = 'tildeop',
scope = { 'global' },
short_desc = N_('tilde command "~" behaves like an operator'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_to',
},
{
@@ -8921,7 +8941,7 @@ return {
full_name = 'timeout',
scope = { 'global' },
short_desc = N_('time out on mappings and key codes'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_timeout',
},
{
@@ -8955,7 +8975,7 @@ return {
full_name = 'title',
scope = { 'global' },
short_desc = N_('Vim set the title of the window'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_title',
},
{
@@ -9005,13 +9025,13 @@ return {
expanded according to the rules used for 'statusline'.
This option cannot be set in a modeline when 'modelineexpr' is off.
- Example: >
- :auto BufEnter * let &titlestring = hostname() .. "/" .. expand("%:p")
- :set title titlestring=%<%F%=%l/%L-%P titlelen=70
+ Example: >vim
+ auto BufEnter * let &titlestring = hostname() .. "/" .. expand("%:p")
+ set title titlestring=%<%F%=%l/%L-%P titlelen=70
< The value of 'titlelen' is used to align items in the middle or right
of the available space.
- Some people prefer to have the file name first: >
- :set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:.:h\")})%)%(\ %a%)
+ Some people prefer to have the file name first: >vim
+ set titlestring=%t%(\ %M%)%(\ (%{expand(\"%:~:.:h\")})%)%(\ %a%)
< Note the use of "%{ }" and an expression to get the path of the file,
without the file name. The "%( %)" constructs are used to add a
separating space only when needed.
@@ -9044,7 +9064,7 @@ return {
redraw = { 'ui_option' },
scope = { 'global' },
short_desc = N_('out on mappings'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_ttimeout',
},
{
@@ -9069,7 +9089,7 @@ return {
no_mkrc = true,
scope = { 'global' },
short_desc = N_('No description'),
- type = 'bool',
+ type = 'boolean',
immutable = true,
},
{
@@ -9125,7 +9145,7 @@ return {
full_name = 'undofile',
scope = { 'buffer' },
short_desc = N_('save undo information in a file'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_udf',
},
{
@@ -9137,13 +9157,13 @@ return {
is kept in memory, higher numbers will cause more memory to be used.
Nevertheless, a single change can already use a large amount of memory.
Set to 0 for Vi compatibility: One level of undo and "u" undoes
- itself: >
+ itself: >vim
set ul=0
< But you can also get Vi compatibility by including the 'u' flag in
'cpoptions', and still be able to use CTRL-R to repeat undo.
Also see |undo-two-ways|.
Set to -1 for no undo at all. You might want to do this only for the
- current buffer: >
+ current buffer: >vim
setlocal ul=-1
< This helps when you run out of memory for a single change.
@@ -9229,8 +9249,8 @@ return {
For example, when editing assembly language files where statements
start in the 9th column and comments in the 41st, it may be useful
- to use the following: >
- :set varsofttabstop=8,32,8
+ to use the following: >vim
+ set varsofttabstop=8,32,8
< This will set soft tabstops with 8 and 8 + 32 spaces, and 8 more
for every column thereafter.
@@ -9251,8 +9271,8 @@ return {
desc = [=[
A list of the number of spaces that a <Tab> in the file counts for,
separated by commas. Each value corresponds to one tab, with the
- final value applying to all subsequent tabs. For example: >
- :set vartabstop=4,20,10,8
+ final value applying to all subsequent tabs. For example: >vim
+ set vartabstop=4,20,10,8
< This will make the first tab 4 spaces wide, the second 20 spaces,
the third 10 spaces, and all following tabs 8 spaces.
@@ -9273,15 +9293,15 @@ return {
desc = [=[
Sets the verbosity level. Also set by |-V| and |:verbose|.
- Tracing of options in Lua scripts is activated at level 1; Lua scripts
- are not traced with verbose=0, for performance.
+ Tracing of assignments to options, mappings, etc. in Lua scripts is
+ enabled at level 1; Lua scripts are not traced when 'verbose' is 0,
+ for performance.
If greater than or equal to a given level, Nvim produces the following
messages:
Level Messages ~
----------------------------------------------------------------------
- 1 Lua assignments to options, mappings, etc.
2 When a file is ":source"'ed, or |shada| file is read or written.
3 UI info, terminal capabilities.
4 Shell commands.
@@ -9371,22 +9391,6 @@ return {
varname = 'p_vop',
},
{
- abbreviation = 'vi',
- full_name = 'viminfo',
- nodefault = true,
- scope = { 'global' },
- short_desc = N_('Alias for shada'),
- type = 'string',
- },
- {
- abbreviation = 'vif',
- full_name = 'viminfofile',
- nodefault = true,
- scope = { 'global' },
- short_desc = N_('Alias for shadafile instead'),
- type = 'string',
- },
- {
abbreviation = 've',
cb = 'did_set_virtualedit',
defaults = { if_true = '' },
@@ -9437,7 +9441,7 @@ return {
full_name = 'visualbell',
scope = { 'global' },
short_desc = N_('use visual bell instead of beeping'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_vb',
},
{
@@ -9449,7 +9453,7 @@ return {
full_name = 'warn',
scope = { 'global' },
short_desc = N_('for shell command when buffer was changed'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_warn',
},
{
@@ -9470,8 +9474,8 @@ return {
~ "~" Normal
[ <Left> Insert and Replace
] <Right> Insert and Replace
- For example: >
- :set ww=<,>,[,]
+ For example: >vim
+ set ww=<,>,[,]
< allows wrap only when cursor keys are used.
When the movement keys are used in combination with a delete or change
operator, the <EOL> also counts for a character. This makes "3h"
@@ -9508,8 +9512,8 @@ return {
Some keys will not work, such as CTRL-C, <CR> and Enter.
<Esc> can be used, but hitting it twice in a row will still exit
command-line as a failsafe measure.
- Although 'wc' is a number option, you can set it to a special key: >
- :set wc=<Tab>
+ Although 'wc' is a number option, you can set it to a special key: >vim
+ set wc=<Tab>
<
]=],
full_name = 'wildchar',
@@ -9527,9 +9531,9 @@ return {
recognized when used inside a macro. You can find "spare" command-line
keys suitable for this option by looking at |ex-edit-index|. Normally
you'll never actually type 'wildcharm', just use it in mappings that
- automatically invoke completion mode, e.g.: >
- :set wcm=<C-Z>
- :cnoremap ss so $vim/sessions/*.vim<C-Z>
+ automatically invoke completion mode, e.g.: >vim
+ set wcm=<C-Z>
+ cnoremap ss so $vim/sessions/*.vim<C-Z>
< Then after typing :ss you can use CTRL-P & CTRL-N.
]=],
full_name = 'wildcharm',
@@ -9549,8 +9553,8 @@ return {
|globpath()| unless a flag is passed to disable this.
The pattern is used like with |:autocmd|, see |autocmd-pattern|.
Also see 'suffixes'.
- Example: >
- :set wildignore=*.o,*.obj
+ Example: >vim
+ set wildignore=*.o,*.obj
< The use of |:set+=| and |:set-=| is preferred when adding or removing
a pattern from the list. This avoids problems when a future version
uses another default.
@@ -9574,7 +9578,7 @@ return {
full_name = 'wildignorecase',
scope = { 'global' },
short_desc = N_('ignore case when completing file names'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_wic',
},
{
@@ -9613,16 +9617,16 @@ return {
completion.
If you want <Left> and <Right> to move the cursor instead of selecting
- a different match, use this: >
- :cnoremap <Left> <Space><BS><Left>
- :cnoremap <Right> <Space><BS><Right>
+ a different match, use this: >vim
+ cnoremap <Left> <Space><BS><Left>
+ cnoremap <Right> <Space><BS><Right>
<
|hl-WildMenu| highlights the current match.
]=],
full_name = 'wildmenu',
scope = { 'global' },
short_desc = N_('use menu for command line completion'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_wmnu',
},
{
@@ -9662,16 +9666,16 @@ return {
and sort buffers by time last used (other than the
current buffer).
- Examples: >
- :set wildmode=full
- < Complete first full match, next match, etc. (the default) >
- :set wildmode=longest,full
- < Complete longest common string, then each full match >
- :set wildmode=list:full
- < List all matches and complete each full match >
- :set wildmode=list,full
- < List all matches without completing, then each full match >
- :set wildmode=longest,list
+ Examples: >vim
+ set wildmode=full
+ < Complete first full match, next match, etc. (the default) >vim
+ set wildmode=longest,full
+ < Complete longest common string, then each full match >vim
+ set wildmode=list:full
+ < List all matches and complete each full match >vim
+ set wildmode=list,full
+ < List all matches without completing, then each full match >vim
+ set wildmode=longest,list
< Complete longest common string, then list alternatives.
More info here: |cmdline-completion|.
]=],
@@ -9783,45 +9787,12 @@ return {
UI-dependent. Works best with RGB colors. 'termguicolors'
]=],
full_name = 'winblend',
- redraw = { 'current_window' },
+ redraw = { 'current_window', 'highlight_only' },
scope = { 'window' },
short_desc = N_('Controls transparency level for floating windows'),
type = 'number',
},
{
- abbreviation = 'winhl',
- alloced = true,
- cb = 'did_set_winhighlight',
- defaults = { if_true = '' },
- deny_duplicates = true,
- desc = [=[
- Window-local highlights. Comma-delimited list of highlight
- |group-name| pairs "{hl-from}:{hl-to},..." where each {hl-from} is
- a |highlight-groups| item to be overridden by {hl-to} group in
- the window.
-
- Note: highlight namespaces take precedence over 'winhighlight'.
- See |nvim_win_set_hl_ns()| and |nvim_set_hl()|.
-
- Highlights of vertical separators are determined by the window to the
- left of the separator. The 'tabline' highlight of a tabpage is
- decided by the last-focused window of the tabpage. Highlights of
- the popupmenu are determined by the current window. Highlights in the
- message area cannot be overridden.
-
- Example: show a different color for non-current windows: >
- set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC
- <
- ]=],
- expand_cb = 'expand_set_winhighlight',
- full_name = 'winhighlight',
- list = 'onecommacolon',
- redraw = { 'current_window' },
- scope = { 'window' },
- short_desc = N_('Setup window-local highlights'),
- type = 'string',
- },
- {
abbreviation = 'wi',
cb = 'did_set_window',
defaults = {
@@ -9846,6 +9817,35 @@ return {
varname = 'p_window',
},
{
+ abbreviation = 'wfh',
+ defaults = { if_true = false },
+ desc = [=[
+ Keep the window height when windows are opened or closed and
+ 'equalalways' is set. Also for |CTRL-W_=|. Set by default for the
+ |preview-window| and |quickfix-window|.
+ The height may be changed anyway when running out of room.
+ ]=],
+ full_name = 'winfixheight',
+ redraw = { 'statuslines' },
+ scope = { 'window' },
+ short_desc = N_('keep window height when opening/closing windows'),
+ type = 'boolean',
+ },
+ {
+ abbreviation = 'wfw',
+ defaults = { if_true = false },
+ desc = [=[
+ Keep the window width when windows are opened or closed and
+ 'equalalways' is set. Also for |CTRL-W_=|.
+ The width may be changed anyway when running out of room.
+ ]=],
+ full_name = 'winfixwidth',
+ redraw = { 'statuslines' },
+ scope = { 'window' },
+ short_desc = N_('keep window width when opening/closing windows'),
+ type = 'boolean',
+ },
+ {
abbreviation = 'wh',
cb = 'did_set_winheight',
defaults = { if_true = 1 },
@@ -9859,7 +9859,7 @@ return {
Other windows will be only 'winminheight' high. This has the drawback
that ":all" will create only two windows. To avoid "vim -o 1 2 3 4"
to create only two windows, set the option after startup is done,
- using the |VimEnter| event: >
+ using the |VimEnter| event: >vim
au VimEnter * set winheight=999
< Minimum value is 1.
The height is not adjusted after one of the commands that change the
@@ -9875,33 +9875,37 @@ return {
varname = 'p_wh',
},
{
- abbreviation = 'wfh',
- defaults = { if_true = false },
- desc = [=[
- Keep the window height when windows are opened or closed and
- 'equalalways' is set. Also for |CTRL-W_=|. Set by default for the
- |preview-window| and |quickfix-window|.
- The height may be changed anyway when running out of room.
- ]=],
- full_name = 'winfixheight',
- redraw = { 'statuslines' },
- scope = { 'window' },
- short_desc = N_('keep window height when opening/closing windows'),
- type = 'bool',
- },
- {
- abbreviation = 'wfw',
- defaults = { if_true = false },
+ abbreviation = 'winhl',
+ alloced = true,
+ cb = 'did_set_winhighlight',
+ defaults = { if_true = '' },
+ deny_duplicates = true,
desc = [=[
- Keep the window width when windows are opened or closed and
- 'equalalways' is set. Also for |CTRL-W_=|.
- The width may be changed anyway when running out of room.
+ Window-local highlights. Comma-delimited list of highlight
+ |group-name| pairs "{hl-from}:{hl-to},..." where each {hl-from} is
+ a |highlight-groups| item to be overridden by {hl-to} group in
+ the window.
+
+ Note: highlight namespaces take precedence over 'winhighlight'.
+ See |nvim_win_set_hl_ns()| and |nvim_set_hl()|.
+
+ Highlights of vertical separators are determined by the window to the
+ left of the separator. The 'tabline' highlight of a tabpage is
+ decided by the last-focused window of the tabpage. Highlights of
+ the popupmenu are determined by the current window. Highlights in the
+ message area cannot be overridden.
+
+ Example: show a different color for non-current windows: >vim
+ set winhighlight=Normal:MyNormal,NormalNC:MyNormalNC
+ <
]=],
- full_name = 'winfixwidth',
- redraw = { 'statuslines' },
+ expand_cb = 'expand_set_winhighlight',
+ full_name = 'winhighlight',
+ list = 'onecommacolon',
+ redraw = { 'current_window', 'highlight_only' },
scope = { 'window' },
- short_desc = N_('keep window width when opening/closing windows'),
- type = 'bool',
+ short_desc = N_('Setup window-local highlights'),
+ type = 'string',
},
{
abbreviation = 'wmh',
@@ -9981,9 +9985,9 @@ return {
horizontally.
The line will be broken in the middle of a word if necessary. See
'linebreak' to get the break at a word boundary.
- To make scrolling horizontally a bit more useful, try this: >
- :set sidescroll=5
- :set listchars+=precedes:<,extends:>
+ To make scrolling horizontally a bit more useful, try this: >vim
+ set sidescroll=5
+ set listchars+=precedes:<,extends:>
< See 'sidescroll', 'listchars' and |wrap-off|.
This option can't be set from a |modeline| when the 'diff' option is
on.
@@ -9992,7 +9996,7 @@ return {
redraw = { 'current_window' },
scope = { 'window' },
short_desc = N_('lines wrap and continue on the next line'),
- type = 'bool',
+ type = 'boolean',
},
{
abbreviation = 'wm',
@@ -10023,7 +10027,7 @@ return {
scope = { 'global' },
short_desc = N_('searches wrap around the end of the file'),
tags = { 'E384', 'E385' },
- type = 'bool',
+ type = 'boolean',
varname = 'p_ws',
},
{
@@ -10038,7 +10042,7 @@ return {
full_name = 'write',
scope = { 'global' },
short_desc = N_('to a file is allowed'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_write',
},
{
@@ -10050,7 +10054,7 @@ return {
full_name = 'writeany',
scope = { 'global' },
short_desc = N_('write to file with no need for "!" override'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_wa',
},
{
@@ -10073,7 +10077,7 @@ return {
full_name = 'writebackup',
scope = { 'global' },
short_desc = N_('make a backup before overwriting a file'),
- type = 'bool',
+ type = 'boolean',
varname = 'p_wb',
},
{
diff --git a/src/nvim/optionstr.c b/src/nvim/optionstr.c
index 281ec86171..4be08b28f5 100644
--- a/src/nvim/optionstr.c
+++ b/src/nvim/optionstr.c
@@ -19,9 +19,9 @@
#include "nvim/eval/vars.h"
#include "nvim/ex_getln.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
+#include "nvim/grid.h"
#include "nvim/highlight_group.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
@@ -39,6 +39,7 @@
#include "nvim/os/os.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/spell.h"
#include "nvim/spellfile.h"
#include "nvim/spellsuggest.h"
@@ -61,6 +62,10 @@ static const char e_backupext_and_patchmode_are_equal[]
= N_("E589: 'backupext' and 'patchmode' are equal");
static const char e_showbreak_contains_unprintable_or_wide_character[]
= N_("E595: 'showbreak' contains unprintable or wide character");
+static const char e_wrong_number_of_characters_for_field_str[]
+ = N_("E1511: Wrong number of characters for field \"%s\"");
+static const char e_wrong_character_width_for_field_str[]
+ = N_("E1512: Wrong character width for field \"%s\"");
static char *(p_ambw_values[]) = { "single", "double", NULL };
static char *(p_bg_values[]) = { "light", "dark", NULL };
@@ -117,7 +122,7 @@ static char *(p_fdm_values[]) = { "manual", "expr", "marker", "indent",
"syntax", "diff", NULL };
static char *(p_fcl_values[]) = { "all", NULL };
static char *(p_cot_values[]) = { "menu", "menuone", "longest", "preview", "noinsert", "noselect",
- NULL };
+ "popup", NULL };
#ifdef BACKSLASH_IN_FILENAME
static char *(p_csl_values[]) = { "slash", "backslash", NULL };
#endif
@@ -149,21 +154,21 @@ static char SHM_ALL[] = { SHM_RO, SHM_MOD, SHM_LINES,
/// option values.
void didset_string_options(void)
{
- (void)opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, true);
- (void)opt_strings_flags(p_bkc, p_bkc_values, &bkc_flags, true);
- (void)opt_strings_flags(p_bo, p_bo_values, &bo_flags, true);
- (void)opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true);
- (void)opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true);
- (void)opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true);
- (void)opt_strings_flags(p_dy, p_dy_values, &dy_flags, true);
- (void)opt_strings_flags(p_jop, p_jop_values, &jop_flags, true);
- (void)opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true);
- (void)opt_strings_flags(p_tc, p_tc_values, &tc_flags, false);
- (void)opt_strings_flags(p_tpf, p_tpf_values, &tpf_flags, true);
- (void)opt_strings_flags(p_ve, p_ve_values, &ve_flags, true);
- (void)opt_strings_flags(p_swb, p_swb_values, &swb_flags, true);
- (void)opt_strings_flags(p_wop, p_wop_values, &wop_flags, true);
- (void)opt_strings_flags(p_cb, p_cb_values, &cb_flags, true);
+ opt_strings_flags(p_cmp, p_cmp_values, &cmp_flags, true);
+ opt_strings_flags(p_bkc, p_bkc_values, &bkc_flags, true);
+ opt_strings_flags(p_bo, p_bo_values, &bo_flags, true);
+ opt_strings_flags(p_ssop, p_ssop_values, &ssop_flags, true);
+ opt_strings_flags(p_vop, p_ssop_values, &vop_flags, true);
+ opt_strings_flags(p_fdo, p_fdo_values, &fdo_flags, true);
+ opt_strings_flags(p_dy, p_dy_values, &dy_flags, true);
+ opt_strings_flags(p_jop, p_jop_values, &jop_flags, true);
+ opt_strings_flags(p_rdb, p_rdb_values, &rdb_flags, true);
+ opt_strings_flags(p_tc, p_tc_values, &tc_flags, false);
+ opt_strings_flags(p_tpf, p_tpf_values, &tpf_flags, true);
+ opt_strings_flags(p_ve, p_ve_values, &ve_flags, true);
+ opt_strings_flags(p_swb, p_swb_values, &swb_flags, true);
+ opt_strings_flags(p_wop, p_wop_values, &wop_flags, true);
+ opt_strings_flags(p_cb, p_cb_values, &cb_flags, true);
}
char *illegal_char(char *errbuf, size_t errbuflen, int c)
@@ -284,30 +289,17 @@ static void set_string_option_global(vimoption_T *opt, char **varp)
/// Set a string option to a new value (without checking the effect).
/// The string is copied into allocated memory.
-/// if ("opt_idx" == -1) "name" is used, otherwise "opt_idx" is used.
+/// if ("opt_idx" == kOptInvalid) "name" is used, otherwise "opt_idx" is used.
/// When "set_sid" is zero set the scriptID to current_sctx.sc_sid. When
/// "set_sid" is SID_NONE don't set the scriptID. Otherwise set the scriptID to
/// "set_sid".
///
-/// @param opt_flags OPT_FREE, OPT_LOCAL and/or OPT_GLOBAL.
+/// @param opt_flags Option flags.
///
/// TODO(famiu): Remove this and its win/buf variants.
-void set_string_option_direct(const char *name, int opt_idx, const char *val, int opt_flags,
- int set_sid)
+void set_string_option_direct(OptIndex opt_idx, const char *val, int opt_flags, scid_T set_sid)
{
- int both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
- int idx = opt_idx;
-
- if (idx == -1) { // Use name.
- idx = findoption(name);
- if (idx < 0) { // Not found (should not happen).
- internal_error("set_string_option_direct()");
- siemsg(_("For option %s"), name);
- return;
- }
- }
-
- vimoption_T *opt = get_option(idx);
+ vimoption_T *opt = get_option(opt_idx);
if (opt->var == NULL) { // can't set hidden option
return;
@@ -315,53 +307,53 @@ void set_string_option_direct(const char *name, int opt_idx, const char *val, in
assert(opt->var != &p_shada);
+ bool both = (opt_flags & (OPT_LOCAL | OPT_GLOBAL)) == 0;
char *s = xstrdup(val);
- {
- char **varp = (char **)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags);
- if ((opt_flags & OPT_FREE) && (opt->flags & P_ALLOCED)) {
- free_string_option(*varp);
- }
- *varp = s;
+ char **varp = (char **)get_varp_scope(opt, both ? OPT_LOCAL : opt_flags);
- // For buffer/window local option may also set the global value.
- if (both) {
- set_string_option_global(opt, varp);
- }
+ if (opt->flags & P_ALLOCED) {
+ free_string_option(*varp);
+ }
+ *varp = s;
- opt->flags |= P_ALLOCED;
+ // For buffer/window local option may also set the global value.
+ if (both) {
+ set_string_option_global(opt, varp);
+ }
- // When setting both values of a global option with a local value,
- // make the local value empty, so that the global value is used.
- if ((opt->indir & PV_BOTH) && both) {
- free_string_option(*varp);
- *varp = empty_string_option;
- }
- if (set_sid != SID_NONE) {
- sctx_T script_ctx;
+ opt->flags |= P_ALLOCED;
- if (set_sid == 0) {
- script_ctx = current_sctx;
- } else {
- script_ctx.sc_sid = set_sid;
- script_ctx.sc_seq = 0;
- script_ctx.sc_lnum = 0;
- }
- set_option_sctx_idx(idx, opt_flags, script_ctx);
+ // When setting both values of a global option with a local value,
+ // make the local value empty, so that the global value is used.
+ if ((opt->indir & PV_BOTH) && both) {
+ free_string_option(*varp);
+ *varp = empty_string_option;
+ }
+ if (set_sid != SID_NONE) {
+ sctx_T script_ctx;
+
+ if (set_sid == 0) {
+ script_ctx = current_sctx;
+ } else {
+ script_ctx.sc_sid = set_sid;
+ script_ctx.sc_seq = 0;
+ script_ctx.sc_lnum = 0;
}
+ set_option_sctx(opt_idx, opt_flags, script_ctx);
}
}
/// Like set_string_option_direct(), but for a window-local option in "wp".
/// Blocks autocommands to avoid the old curwin becoming invalid.
-void set_string_option_direct_in_win(win_T *wp, const char *name, int opt_idx, const char *val,
- int opt_flags, int set_sid)
+void set_string_option_direct_in_win(win_T *wp, OptIndex opt_idx, const char *val, int opt_flags,
+ int set_sid)
{
win_T *save_curwin = curwin;
block_autocmds();
curwin = wp;
curbuf = curwin->w_buffer;
- set_string_option_direct(name, opt_idx, val, opt_flags, set_sid);
+ set_string_option_direct(opt_idx, val, opt_flags, set_sid);
curwin = save_curwin;
curbuf = curwin->w_buffer;
unblock_autocmds();
@@ -369,14 +361,14 @@ void set_string_option_direct_in_win(win_T *wp, const char *name, int opt_idx, c
/// Like set_string_option_direct(), but for a buffer-local option in "buf".
/// Blocks autocommands to avoid the old curwin becoming invalid.
-void set_string_option_direct_in_buf(buf_T *buf, const char *name, int opt_idx, const char *val,
- int opt_flags, int set_sid)
+void set_string_option_direct_in_buf(buf_T *buf, OptIndex opt_idx, const char *val, int opt_flags,
+ int set_sid)
{
buf_T *save_curbuf = curbuf;
block_autocmds();
curbuf = buf;
- set_string_option_direct(name, opt_idx, val, opt_flags, set_sid);
+ set_string_option_direct(opt_idx, val, opt_flags, set_sid);
curbuf = save_curbuf;
unblock_autocmds();
}
@@ -443,7 +435,7 @@ int check_signcolumn(win_T *wp)
const char *check_stl_option(char *s)
{
int groupdepth = 0;
- static char errbuf[80];
+ static char errbuf[ERR_BUFLEN];
while (*s) {
// Check for valid keys after % sequences
@@ -677,12 +669,17 @@ int expand_set_ambiwidth(optexpand_T *args, int *numMatches, char ***matches)
}
/// The 'background' option is changed.
-const char *did_set_background(optset_T *args FUNC_ATTR_UNUSED)
+const char *did_set_background(optset_T *args)
{
if (check_opt_strings(p_bg, p_bg_values, false) != OK) {
return e_invarg;
}
+ if (args->os_oldval.string.data[0] == *p_bg) {
+ // Value was not changed
+ return NULL;
+ }
+
int dark = (*p_bg == 'd');
init_highlight(false, false);
@@ -757,7 +754,7 @@ const char *did_set_backupcopy(optset_T *args)
+ ((*flags & BKC_YES) != 0)
+ ((*flags & BKC_NO) != 0) != 1) {
// Must have exactly one of "auto", "yes" and "no".
- (void)opt_strings_flags(oldval, p_bkc_values, flags, true);
+ opt_strings_flags(oldval, p_bkc_values, flags, true);
return e_invarg;
}
}
@@ -800,6 +797,22 @@ int expand_set_belloff(optexpand_T *args, int *numMatches, char ***matches)
matches);
}
+/// The 'breakat' option is changed.
+const char *did_set_breakat(optset_T *args FUNC_ATTR_UNUSED)
+{
+ for (int i = 0; i < 256; i++) {
+ breakat_flags[i] = false;
+ }
+
+ if (p_breakat != NULL) {
+ for (char *p = p_breakat; *p; p++) {
+ breakat_flags[(uint8_t)(*p)] = true;
+ }
+ }
+
+ return NULL;
+}
+
/// The 'breakindentopt' option is changed.
const char *did_set_breakindentopt(optset_T *args)
{
@@ -885,18 +898,17 @@ int expand_set_casemap(optexpand_T *args, int *numMatches, char ***matches)
}
/// The global 'listchars' or 'fillchars' option is changed.
-static const char *did_set_global_listfillchars(win_T *win, char *val, bool opt_lcs, int opt_flags)
+static const char *did_set_global_chars_option(win_T *win, char *val, CharsOption what,
+ int opt_flags, char *errbuf, size_t errbuflen)
{
const char *errmsg = NULL;
- char **local_ptr = opt_lcs ? &win->w_p_lcs : &win->w_p_fcs;
+ char **local_ptr = (what == kListchars) ? &win->w_p_lcs : &win->w_p_fcs;
// only apply the global value to "win" when it does not have a
// local value
- if (opt_lcs) {
- errmsg = set_listchars_option(win, val, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
- } else {
- errmsg = set_fillchars_option(win, val, **local_ptr == NUL || !(opt_flags & OPT_GLOBAL));
- }
+ errmsg = set_chars_option(win, val, what,
+ **local_ptr == NUL || !(opt_flags & OPT_GLOBAL),
+ errbuf, errbuflen);
if (errmsg != NULL) {
return errmsg;
}
@@ -912,14 +924,9 @@ static const char *did_set_global_listfillchars(win_T *win, char *val, bool opt_
// again, it was changed when setting the global value.
// If no error was returned above, we don't expect an error
// here, so ignore the return value.
- if (opt_lcs) {
- if (*wp->w_p_lcs == NUL) {
- (void)set_listchars_option(wp, wp->w_p_lcs, true);
- }
- } else {
- if (*wp->w_p_fcs == NUL) {
- (void)set_fillchars_option(wp, wp->w_p_fcs, true);
- }
+ char *opt = (what == kListchars) ? wp->w_p_lcs : wp->w_p_fcs;
+ if (*opt == NUL) {
+ set_chars_option(wp, opt, what, true, errbuf, errbuflen);
}
}
@@ -935,13 +942,18 @@ const char *did_set_chars_option(optset_T *args)
char **varp = (char **)args->os_varp;
const char *errmsg = NULL;
- if (varp == &p_lcs // global 'listchars'
- || varp == &p_fcs) { // global 'fillchars'
- errmsg = did_set_global_listfillchars(win, *varp, varp == &p_lcs, args->os_flags);
+ if (varp == &p_lcs) { // global 'listchars'
+ errmsg = did_set_global_chars_option(win, *varp, kListchars, args->os_flags,
+ args->os_errbuf, args->os_errbuflen);
+ } else if (varp == &p_fcs) { // global 'fillchars'
+ errmsg = did_set_global_chars_option(win, *varp, kFillchars, args->os_flags,
+ args->os_errbuf, args->os_errbuflen);
} else if (varp == &win->w_p_lcs) { // local 'listchars'
- errmsg = set_listchars_option(win, *varp, true);
+ errmsg = set_chars_option(win, *varp, kListchars, true,
+ args->os_errbuf, args->os_errbuflen);
} else if (varp == &win->w_p_fcs) { // local 'fillchars'
- errmsg = set_fillchars_option(win, *varp, true);
+ errmsg = set_chars_option(win, *varp, kFillchars, true,
+ args->os_errbuf, args->os_errbuflen);
}
return errmsg;
@@ -1229,7 +1241,7 @@ const char *did_set_display(optset_T *args FUNC_ATTR_UNUSED)
if (opt_strings_flags(p_dy, p_dy_values, &dy_flags, true) != OK) {
return e_invarg;
}
- (void)init_chartab();
+ init_chartab();
msg_grid_validate();
return NULL;
}
@@ -1434,7 +1446,7 @@ int expand_set_foldcolumn(optexpand_T *args, int *numMatches, char ***matches)
const char *did_set_foldexpr(optset_T *args)
{
win_T *win = (win_T *)args->os_win;
- (void)did_set_optexpr(args);
+ did_set_optexpr(args);
if (foldmethodIsExpr(win)) {
foldUpdateAll(win);
}
@@ -1529,7 +1541,15 @@ int expand_set_formatoptions(optexpand_T *args, int *numMatches, char ***matches
/// The 'guicursor' option is changed.
const char *did_set_guicursor(optset_T *args FUNC_ATTR_UNUSED)
{
- return parse_shape_opt(SHAPE_CURSOR);
+ const char *errmsg = parse_shape_opt(SHAPE_CURSOR);
+ if (errmsg != NULL) {
+ return errmsg;
+ }
+ if (VIsual_active) {
+ // In Visual mode cursor may be drawn differently.
+ redrawWinline(curwin, curwin->w_cursor.lnum);
+ }
+ return NULL;
}
/// The 'helpfile' option is changed.
@@ -1946,6 +1966,10 @@ const char *did_set_selection(optset_T *args FUNC_ATTR_UNUSED)
if (*p_sel == NUL || check_opt_strings(p_sel, p_sel_values, false) != OK) {
return e_invarg;
}
+ if (VIsual_active) {
+ // Visual selection may be drawn differently.
+ redraw_curbuf_later(UPD_INVERTED);
+ }
return NULL;
}
@@ -1982,7 +2006,7 @@ const char *did_set_sessionoptions(optset_T *args)
if ((ssop_flags & SSOP_CURDIR) && (ssop_flags & SSOP_SESDIR)) {
// Don't allow both "sesdir" and "curdir".
const char *oldval = args->os_oldval.string.data;
- (void)opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true);
+ opt_strings_flags(oldval, p_ssop_values, &ssop_flags, true);
return e_invarg;
}
return NULL;
@@ -2076,7 +2100,13 @@ const char *did_set_showbreak(optset_T *args)
/// The 'showcmdloc' option is changed.
const char *did_set_showcmdloc(optset_T *args FUNC_ATTR_UNUSED)
{
- return did_set_opt_strings(p_sloc, p_sloc_values, true);
+ const char *errmsg = did_set_opt_strings(p_sloc, p_sloc_values, false);
+
+ if (errmsg == NULL) {
+ comp_col();
+ }
+
+ return errmsg;
}
int expand_set_showcmdloc(optexpand_T *args, int *numMatches, char ***matches)
@@ -2096,6 +2126,8 @@ const char *did_set_signcolumn(optset_T *args)
if (check_signcolumn(win) != OK) {
return e_invarg;
}
+ int scwidth = win->w_minscwidth <= 0 ? 0 : MIN(win->w_maxscwidth, win->w_scwidth);
+ win->w_scwidth = MAX(win->w_minscwidth, scwidth);
// When changing the 'signcolumn' to or from 'number', recompute the
// width of the number column if 'number' or 'relativenumber' is set.
if ((*oldval == 'n' && *(oldval + 1) == 'u') || win->w_minscwidth == SCL_NUM) {
@@ -2610,7 +2642,7 @@ static const char e_conflicts_with_value_of_fillchars[]
/// Calls mb_cptr2char_adv(p) and returns the character.
/// If "p" starts with "\x", "\u" or "\U" the hex or unicode value is used.
/// Returns 0 for invalid hex or invalid UTF-8 byte.
-static int get_encoded_char_adv(const char **p)
+static schar_T get_encoded_char_adv(const char **p)
{
const char *s = *p;
@@ -2625,71 +2657,82 @@ static int get_encoded_char_adv(const char **p)
num = num * 256 + n;
}
*p += 2;
- return (int)num;
+ return (char2cells((int)num) > 1) ? 0 : schar_from_char((int)num);
}
- // TODO(bfredl): use schar_T representation and utfc_ptr2len
- int clen = utf_ptr2len(s);
- int c = mb_cptr2char_adv(p);
- if (clen == 1 && c > 127) { // Invalid UTF-8 byte
- return 0;
- }
- return c;
+ int clen = utfc_ptr2len(s);
+ int firstc;
+ schar_T c = utfc_ptr2schar(s, &firstc);
+ *p += clen;
+ // Invalid UTF-8 byte or doublewidth not allowed
+ return ((clen == 1 && firstc > 127) || char2cells(firstc) > 1) ? 0 : c;
}
struct chars_tab {
- int *cp; ///< char value
+ schar_T *cp; ///< char value
const char *name; ///< char id
- int def; ///< default value
- int fallback; ///< default value when "def" isn't single-width
+ const char *def; ///< default value
+ const char *fallback; ///< default value when "def" isn't single-width
};
static fcs_chars_T fcs_chars;
static const struct chars_tab fcs_tab[] = {
- { &fcs_chars.stl, "stl", ' ', NUL },
- { &fcs_chars.stlnc, "stlnc", ' ', NUL },
- { &fcs_chars.wbr, "wbr", ' ', NUL },
- { &fcs_chars.horiz, "horiz", 0x2500, '-' }, // ─
- { &fcs_chars.horizup, "horizup", 0x2534, '-' }, // â”´
- { &fcs_chars.horizdown, "horizdown", 0x252c, '-' }, // ┬
- { &fcs_chars.vert, "vert", 0x2502, '|' }, // │
- { &fcs_chars.vertleft, "vertleft", 0x2524, '|' }, // ┤
- { &fcs_chars.vertright, "vertright", 0x251c, '|' }, // ├
- { &fcs_chars.verthoriz, "verthoriz", 0x253c, '+' }, // ┼
- { &fcs_chars.fold, "fold", 0x00b7, '-' }, // ·
- { &fcs_chars.foldopen, "foldopen", '-', NUL },
- { &fcs_chars.foldclosed, "foldclose", '+', NUL },
- { &fcs_chars.foldsep, "foldsep", 0x2502, '|' }, // │
- { &fcs_chars.diff, "diff", '-', NUL },
- { &fcs_chars.msgsep, "msgsep", ' ', NUL },
- { &fcs_chars.eob, "eob", '~', NUL },
- { &fcs_chars.lastline, "lastline", '@', NUL },
+ { &fcs_chars.stl, "stl", " ", NULL },
+ { &fcs_chars.stlnc, "stlnc", " ", NULL },
+ { &fcs_chars.wbr, "wbr", " ", NULL },
+ { &fcs_chars.horiz, "horiz", "─", "-" },
+ { &fcs_chars.horizup, "horizup", "â”´", "-" },
+ { &fcs_chars.horizdown, "horizdown", "┬", "-" },
+ { &fcs_chars.vert, "vert", "│", "|" },
+ { &fcs_chars.vertleft, "vertleft", "┤", "|" },
+ { &fcs_chars.vertright, "vertright", "├", "|" },
+ { &fcs_chars.verthoriz, "verthoriz", "┼", "+" },
+ { &fcs_chars.fold, "fold", "·", "-" },
+ { &fcs_chars.foldopen, "foldopen", "-", NULL },
+ { &fcs_chars.foldclosed, "foldclose", "+", NULL },
+ { &fcs_chars.foldsep, "foldsep", "│", "|" },
+ { &fcs_chars.diff, "diff", "-", NULL },
+ { &fcs_chars.msgsep, "msgsep", " ", NULL },
+ { &fcs_chars.eob, "eob", "~", NULL },
+ { &fcs_chars.lastline, "lastline", "@", NULL },
};
static lcs_chars_T lcs_chars;
static const struct chars_tab lcs_tab[] = {
- { &lcs_chars.eol, "eol", NUL, NUL },
- { &lcs_chars.ext, "extends", NUL, NUL },
- { &lcs_chars.nbsp, "nbsp", NUL, NUL },
- { &lcs_chars.prec, "precedes", NUL, NUL },
- { &lcs_chars.space, "space", NUL, NUL },
- { &lcs_chars.tab2, "tab", NUL, NUL },
- { &lcs_chars.lead, "lead", NUL, NUL },
- { &lcs_chars.trail, "trail", NUL, NUL },
- { &lcs_chars.conceal, "conceal", NUL, NUL },
- { NULL, "multispace", NUL, NUL },
- { NULL, "leadmultispace", NUL, NUL },
+ { &lcs_chars.eol, "eol", NULL, NULL },
+ { &lcs_chars.ext, "extends", NULL, NULL },
+ { &lcs_chars.nbsp, "nbsp", NULL, NULL },
+ { &lcs_chars.prec, "precedes", NULL, NULL },
+ { &lcs_chars.space, "space", NULL, NULL },
+ { &lcs_chars.tab2, "tab", NULL, NULL },
+ { &lcs_chars.lead, "lead", NULL, NULL },
+ { &lcs_chars.trail, "trail", NULL, NULL },
+ { &lcs_chars.conceal, "conceal", NULL, NULL },
+ { NULL, "multispace", NULL, NULL },
+ { NULL, "leadmultispace", NULL, NULL },
};
+static char *field_value_err(char *errbuf, size_t errbuflen, const char *fmt, const char *field)
+{
+ if (errbuf == NULL) {
+ return "";
+ }
+ vim_snprintf(errbuf, errbuflen, _(fmt), field);
+ return errbuf;
+}
+
/// Handle setting 'listchars' or 'fillchars'.
/// Assume monocell characters
///
-/// @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.
+/// @param value points to either the global or the window-local value.
+/// @param what kListchars or kFillchars
+/// @param apply if false, do not store the flags, only check for errors.
+/// @param errbuf buffer for error message, can be NULL if it won't be used.
+/// @param errbuflen size of error buffer.
+///
/// @return error message, NULL if it's OK.
-static const char *set_chars_option(win_T *wp, const char *value, const bool is_listchars,
- const bool apply)
+const char *set_chars_option(win_T *wp, const char *value, CharsOption what, bool apply,
+ char *errbuf, size_t errbuflen)
{
const char *last_multispace = NULL; // Last occurrence of "multispace:"
const char *last_lmultispace = NULL; // Last occurrence of "leadmultispace:"
@@ -2698,7 +2741,7 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
const struct chars_tab *tab;
int entries;
- if (is_listchars) {
+ if (what == kListchars) {
tab = lcs_tab;
entries = ARRAY_SIZE(lcs_tab);
if (wp->w_p_lcs[0] == NUL) {
@@ -2720,23 +2763,24 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
if (tab[i].cp != NULL) {
// XXX: Characters taking 2 columns is forbidden (TUI limitation?).
// Set old defaults in this case.
- *(tab[i].cp) = char2cells(tab[i].def) == 1 ? tab[i].def : tab[i].fallback;
+ *(tab[i].cp) = schar_from_str((tab[i].def && ptr2cells(tab[i].def) == 1)
+ ? tab[i].def : tab[i].fallback);
}
}
- if (is_listchars) {
+ if (what == kListchars) {
lcs_chars.tab1 = NUL;
lcs_chars.tab3 = NUL;
if (multispace_len > 0) {
- lcs_chars.multispace = xmalloc(((size_t)multispace_len + 1) * sizeof(int));
+ lcs_chars.multispace = xmalloc(((size_t)multispace_len + 1) * sizeof(schar_T));
lcs_chars.multispace[multispace_len] = NUL;
} else {
lcs_chars.multispace = NULL;
}
if (lead_multispace_len > 0) {
- lcs_chars.leadmultispace = xmalloc(((size_t)lead_multispace_len + 1) * sizeof(int));
+ lcs_chars.leadmultispace = xmalloc(((size_t)lead_multispace_len + 1) * sizeof(schar_T));
lcs_chars.leadmultispace[lead_multispace_len] = NUL;
} else {
lcs_chars.leadmultispace = NULL;
@@ -2749,34 +2793,36 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
int i;
for (i = 0; i < entries; i++) {
const size_t len = strlen(tab[i].name);
- if (!(strncmp(p, tab[i].name, len) == 0
- && p[len] == ':'
- && p[len + 1] != NUL)) {
+ if (!(strncmp(p, tab[i].name, len) == 0 && p[len] == ':')) {
continue;
}
- if (is_listchars && strcmp(tab[i].name, "multispace") == 0) {
+ if (what == kListchars && strcmp(tab[i].name, "multispace") == 0) {
const char *s = p + len + 1;
if (round == 0) {
// Get length of lcs-multispace string in the first round
last_multispace = p;
multispace_len = 0;
while (*s != NUL && *s != ',') {
- int c1 = get_encoded_char_adv(&s);
- if (c1 == 0 || char2cells(c1) > 1) {
- return e_invarg;
+ schar_T c1 = get_encoded_char_adv(&s);
+ if (c1 == 0) {
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_character_width_for_field_str,
+ tab[i].name);
}
multispace_len++;
}
if (multispace_len == 0) {
// lcs-multispace cannot be an empty string
- return e_invarg;
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_number_of_characters_for_field_str,
+ tab[i].name);
}
p = s;
} else {
int multispace_pos = 0;
while (*s != NUL && *s != ',') {
- int c1 = get_encoded_char_adv(&s);
+ schar_T c1 = get_encoded_char_adv(&s);
if (p == last_multispace) {
lcs_chars.multispace[multispace_pos++] = c1;
}
@@ -2786,28 +2832,32 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
break;
}
- if (is_listchars && strcmp(tab[i].name, "leadmultispace") == 0) {
+ if (what == kListchars && strcmp(tab[i].name, "leadmultispace") == 0) {
const char *s = p + len + 1;
if (round == 0) {
// get length of lcs-leadmultispace string in first round
last_lmultispace = p;
lead_multispace_len = 0;
while (*s != NUL && *s != ',') {
- int c1 = get_encoded_char_adv(&s);
- if (c1 == 0 || char2cells(c1) > 1) {
- return e_invarg;
+ schar_T c1 = get_encoded_char_adv(&s);
+ if (c1 == 0) {
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_character_width_for_field_str,
+ tab[i].name);
}
lead_multispace_len++;
}
if (lead_multispace_len == 0) {
// lcs-leadmultispace cannot be an empty string
- return e_invarg;
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_number_of_characters_for_field_str,
+ tab[i].name);
}
p = s;
} else {
int multispace_pos = 0;
while (*s != NUL && *s != ',') {
- int c1 = get_encoded_char_adv(&s);
+ schar_T c1 = get_encoded_char_adv(&s);
if (p == last_lmultispace) {
lcs_chars.leadmultispace[multispace_pos++] = c1;
}
@@ -2818,23 +2868,37 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
}
const char *s = p + len + 1;
- int c1 = get_encoded_char_adv(&s);
- if (c1 == 0 || char2cells(c1) > 1) {
- return e_invarg;
+ if (*s == NUL) {
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_number_of_characters_for_field_str,
+ tab[i].name);
+ }
+ schar_T c1 = get_encoded_char_adv(&s);
+ if (c1 == 0) {
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_character_width_for_field_str,
+ tab[i].name);
}
- int c2 = 0, c3 = 0;
+ schar_T c2 = 0;
+ schar_T c3 = 0;
if (tab[i].cp == &lcs_chars.tab2) {
if (*s == NUL) {
- return e_invarg;
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_number_of_characters_for_field_str,
+ tab[i].name);
}
c2 = get_encoded_char_adv(&s);
- if (c2 == 0 || char2cells(c2) > 1) {
- return e_invarg;
+ if (c2 == 0) {
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_character_width_for_field_str,
+ tab[i].name);
}
if (!(*s == ',' || *s == NUL)) {
c3 = get_encoded_char_adv(&s);
- if (c3 == 0 || char2cells(c3) > 1) {
- return e_invarg;
+ if (c3 == 0) {
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_character_width_for_field_str,
+ tab[i].name);
}
}
}
@@ -2851,6 +2915,10 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
}
p = s;
break;
+ } else {
+ return field_value_err(errbuf, errbuflen,
+ e_wrong_number_of_characters_for_field_str,
+ tab[i].name);
}
}
@@ -2865,7 +2933,7 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
}
if (apply) {
- if (is_listchars) {
+ if (what == kListchars) {
xfree(wp->w_p_lcs_chars.multispace);
xfree(wp->w_p_lcs_chars.leadmultispace);
wp->w_p_lcs_chars = lcs_chars;
@@ -2877,18 +2945,6 @@ static const char *set_chars_option(win_T *wp, const char *value, const bool is_
return NULL; // no error
}
-/// Handle the new value of 'fillchars'.
-const char *set_fillchars_option(win_T *wp, char *val, bool apply)
-{
- return set_chars_option(wp, val, false, apply);
-}
-
-/// Handle the new value of 'listchars'.
-const char *set_listchars_option(win_T *wp, char *val, bool apply)
-{
- return set_chars_option(wp, val, true, apply);
-}
-
/// Function given to ExpandGeneric() to obtain possible arguments of the
/// 'fillchars' option.
char *get_fillchars_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
@@ -2917,17 +2973,17 @@ char *get_listchars_name(expand_T *xp FUNC_ATTR_UNUSED, int idx)
/// @return an untranslated error message if any of them is invalid, NULL otherwise.
const char *check_chars_options(void)
{
- if (set_listchars_option(curwin, p_lcs, false) != NULL) {
+ if (set_chars_option(curwin, p_lcs, kListchars, false, NULL, 0) != NULL) {
return e_conflicts_with_value_of_listchars;
}
- if (set_fillchars_option(curwin, p_fcs, false) != NULL) {
+ if (set_chars_option(curwin, p_fcs, kFillchars, false, NULL, 0) != NULL) {
return e_conflicts_with_value_of_fillchars;
}
FOR_ALL_TAB_WINDOWS(tp, wp) {
- if (set_listchars_option(wp, wp->w_p_lcs, true) != NULL) {
+ if (set_chars_option(wp, wp->w_p_lcs, kListchars, true, NULL, 0) != NULL) {
return e_conflicts_with_value_of_listchars;
}
- if (set_fillchars_option(wp, wp->w_p_fcs, true) != NULL) {
+ if (set_chars_option(wp, wp->w_p_fcs, kFillchars, true, NULL, 0) != NULL) {
return e_conflicts_with_value_of_fillchars;
}
}
diff --git a/src/nvim/optionstr.h b/src/nvim/optionstr.h
index b317e55b7e..7001f18098 100644
--- a/src/nvim/optionstr.h
+++ b/src/nvim/optionstr.h
@@ -2,9 +2,14 @@
#include <stdint.h> // IWYU pragma: keep
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/option_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
+
+typedef enum {
+ kFillchars,
+ kListchars,
+} CharsOption;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "optionstr.h.generated.h"
diff --git a/src/nvim/os/dl.c b/src/nvim/os/dl.c
index 1a8d847f79..c6982e4fa8 100644
--- a/src/nvim/os/dl.c
+++ b/src/nvim/os/dl.c
@@ -5,7 +5,7 @@
#include <stdint.h>
#include <uv.h>
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/os/dl.h"
diff --git a/src/nvim/os/env.c b/src/nvim/os/env.c
index 8620c79069..5b1cb01976 100644
--- a/src/nvim/os/env.c
+++ b/src/nvim/os/env.c
@@ -13,9 +13,9 @@
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
+#include "nvim/cmdexpand_defs.h"
#include "nvim/eval.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/macros_defs.h"
@@ -25,8 +25,10 @@
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/version.h"
#include "nvim/vim_defs.h"
@@ -46,6 +48,10 @@
# include <sys/utsname.h>
#endif
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "os/env.c.generated.h"
+#endif
+
// Because `uv_os_getenv` requires allocating, we must manage a map to maintain
// the behavior of `os_getenv`.
static PMap(cstr_t) envmap = MAP_INIT;
@@ -55,8 +61,7 @@ static PMap(cstr_t) envmap = MAP_INIT;
const char *os_getenv(const char *name)
FUNC_ATTR_NONNULL_ALL
{
- char *e;
- size_t size = 64;
+ char *e = NULL;
if (name[0] == '\0') {
return NULL;
}
@@ -72,23 +77,31 @@ const char *os_getenv(const char *name)
}
pmap_del2(&envmap, name);
}
- e = xmalloc(size);
- r = uv_os_getenv(name, e, &size);
+#define INIT_SIZE 64
+ size_t size = INIT_SIZE;
+ char buf[INIT_SIZE];
+ r = uv_os_getenv(name, buf, &size);
if (r == UV_ENOBUFS) {
- e = xrealloc(e, size);
+ e = xmalloc(size);
r = uv_os_getenv(name, e, &size);
- }
- if (r != 0 || size == 0 || e[0] == '\0') {
- xfree(e);
+ if (r != 0 || size == 0 || e[0] == '\0') {
+ XFREE_CLEAR(e);
+ goto end;
+ }
+ } else if (r != 0 || size == 0 || buf[0] == '\0') {
e = NULL;
goto end;
+ } else {
+ // NB: `size` param of uv_os_getenv() includes the NUL-terminator,
+ // except when it does not include the NUL-terminator.
+ e = xmemdupz(buf, size);
}
pmap_put(cstr_t)(&envmap, xstrdup(name), e);
end:
if (r != 0 && r != UV_ENOENT && r != UV_UNKNOWN) {
ELOG("uv_os_getenv(%s) failed: %d %s", name, r, uv_err_name(r));
}
- return (e == NULL || size == 0 || e[0] == '\0') ? NULL : e;
+ return e;
}
/// Returns true if environment variable `name` is defined (even if empty).
@@ -507,6 +520,17 @@ void free_homedir(void)
xfree(homedir);
}
+void free_envmap(void)
+{
+ cstr_t name;
+ ptr_t e;
+ map_foreach(&envmap, name, e, {
+ xfree((char *)name);
+ xfree(e);
+ });
+ map_destroy(cstr_t, &envmap);
+}
+
#endif
/// Call expand_env() and store the result in an allocated string.
@@ -562,6 +586,9 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
bool copy_char;
bool mustfree; // var was allocated, need to free it later
bool at_start = true; // at start of a name
+#if defined(BACKSLASH_IN_FILENAME)
+ char *const save_dst = dst;
+#endif
int prefix_len = (prefix == NULL) ? 0 : (int)strlen(prefix);
@@ -572,7 +599,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
if (src[0] == '`' && src[1] == '=') {
var = src;
src += 2;
- (void)skip_expr(&src, NULL);
+ skip_expr(&src, NULL);
if (*src == '`') {
src++;
}
@@ -604,7 +631,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
while (c-- > 0 && *tail != NUL && *tail != '}') {
*var++ = *tail++;
}
- } else // NOLINT
+ } else
#endif
{
while (c-- > 0 && *tail != NUL && vim_isIDc((uint8_t)(*tail))) {
@@ -702,7 +729,7 @@ void expand_env_esc(char *restrict srcp, char *restrict dst, int dstlen, bool es
// with it, skip a character
if (after_pathsep(dst, dst + c)
#if defined(BACKSLASH_IN_FILENAME)
- && dst[-1] != ':'
+ && (dst == save_dst || dst[-1] != ':')
#endif
&& vim_ispathsep(*tail)) {
tail++;
@@ -904,10 +931,7 @@ char *vim_getenv(const char *name)
// Don't do this when default_vimruntime_dir is non-empty.
char *vim_path = NULL;
if (vimruntime
-#ifdef HAVE_PATHDEF
- && *default_vimruntime_dir == NUL
-#endif
- ) {
+ && *default_vimruntime_dir == NUL) {
kos_env_path = os_getenv("VIM");
if (kos_env_path != NULL) {
vim_path = vim_version_dir(kos_env_path);
@@ -966,7 +990,6 @@ char *vim_getenv(const char *name)
assert(vim_path != exe_name);
}
-#ifdef HAVE_PATHDEF
// When there is a pathdef.c file we can use default_vim_dir and
// default_vimruntime_dir
if (vim_path == NULL) {
@@ -980,7 +1003,6 @@ char *vim_getenv(const char *name)
}
}
}
-#endif
// Set the environment variable, so that the new value can be found fast
// next time, and others can also use it (e.g. Perl).
@@ -1051,7 +1073,7 @@ size_t home_replace(const buf_T *const buf, const char *src, char *const dst, si
size_t usedlen = 0;
size_t flen = strlen(homedir_env_mod);
char *fbuf = NULL;
- (void)modify_fname(":p", false, &usedlen, &homedir_env_mod, &fbuf, &flen);
+ modify_fname(":p", false, &usedlen, &homedir_env_mod, &fbuf, &flen);
flen = strlen(homedir_env_mod);
assert(homedir_env_mod != homedir_env);
if (vim_ispathsep(homedir_env_mod[flen - 1])) {
diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c
index 79d6ac08e7..da6fb13768 100644
--- a/src/nvim/os/fileio.c
+++ b/src/nvim/os/fileio.c
@@ -12,7 +12,7 @@
#include <uv.h>
#include "auto/config.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/macros_defs.h"
@@ -22,12 +22,9 @@
#include "nvim/os/fs.h"
#include "nvim/os/os_defs.h"
#include "nvim/rbuffer.h"
+#include "nvim/rbuffer_defs.h"
#include "nvim/types_defs.h"
-#ifdef MSWIN
-# include "nvim/os/os_win_console.h"
-#endif
-
#ifdef HAVE_SYS_UIO_H
# include <sys/uio.h>
#endif
@@ -132,69 +129,15 @@ int file_open_fd(FileDescriptor *const ret_fp, const int fd, const int flags)
return 0;
}
-/// Like file_open(), but allocate and return ret_fp
-///
-/// @param[out] error Error code, or 0 on success. @see os_strerror()
-/// @param[in] fname File name to open.
-/// @param[in] flags Flags, @see FileOpenFlags.
-/// @param[in] mode Permissions for the newly created file (ignored if flags
-/// does not have kFileCreate\*).
-///
-/// @return [allocated] Opened file or NULL in case of error.
-FileDescriptor *file_open_new(int *const error, const char *const fname, const int flags,
- const int mode)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
-{
- FileDescriptor *const fp = xmalloc(sizeof(*fp));
- if ((*error = file_open(fp, fname, flags, mode)) != 0) {
- xfree(fp);
- return NULL;
- }
- return fp;
-}
-
-/// Like file_open_fd(), but allocate and return ret_fp
-///
-/// @param[out] error Error code, or 0 on success. @see os_strerror()
-/// @param[in] fd File descriptor to wrap.
-/// @param[in] flags Flags, @see FileOpenFlags.
-/// @param[in] mode Permissions for the newly created file (ignored if flags
-/// does not have FILE_CREATE\*).
-///
-/// @return [allocated] Opened file or NULL in case of error.
-FileDescriptor *file_open_fd_new(int *const error, const int fd, const int flags)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
-{
- FileDescriptor *const fp = xmalloc(sizeof(*fp));
- if ((*error = file_open_fd(fp, fd, flags)) != 0) {
- xfree(fp);
- return NULL;
- }
- return fp;
-}
-
/// Opens standard input as a FileDescriptor.
-FileDescriptor *file_open_stdin(void)
- FUNC_ATTR_MALLOC FUNC_ATTR_WARN_UNUSED_RESULT
+int file_open_stdin(FileDescriptor *fp)
+ FUNC_ATTR_WARN_UNUSED_RESULT
{
- int error;
- int stdin_dup_fd;
- if (stdin_fd > 0) {
- stdin_dup_fd = stdin_fd;
- } else {
- stdin_dup_fd = os_dup(STDIN_FILENO);
-#ifdef MSWIN
- // Replace the original stdin with the console input handle.
- os_replace_stdin_to_conin();
-#endif
- }
- FileDescriptor *const stdin_dup = file_open_fd_new(&error, stdin_dup_fd,
- kFileReadOnly|kFileNonBlocking);
- assert(stdin_dup != NULL);
+ int error = file_open_fd(fp, os_open_stdin_fd(), kFileReadOnly|kFileNonBlocking);
if (error != 0) {
ELOG("failed to open stdin: %s", os_strerror(error));
}
- return stdin_dup;
+ return error;
}
/// Close file and free its buffer
@@ -215,20 +158,6 @@ int file_close(FileDescriptor *const fp, const bool do_fsync)
return flush_error;
}
-/// Close and free file obtained using file_open_new()
-///
-/// @param[in,out] fp File to close.
-/// @param[in] do_fsync If true, use fsync() to write changes to disk.
-///
-/// @return 0 or error code.
-int file_free(FileDescriptor *const fp, const bool do_fsync)
- FUNC_ATTR_NONNULL_ALL
-{
- const int ret = file_close(fp, do_fsync);
- xfree(fp);
- return ret;
-}
-
/// Flush file modifications to disk
///
/// @param[in,out] fp File to work with.
@@ -437,24 +366,6 @@ ptrdiff_t file_skip(FileDescriptor *const fp, const size_t size)
return (ptrdiff_t)read_bytes;
}
-/// Msgpack callback for writing to a file
-///
-/// @param data File to write to.
-/// @param[in] buf Data to write.
-/// @param[in] len Length of the data to write.
-///
-/// @return 0 in case of success, -1 in case of error.
-int msgpack_file_write(void *data, const char *buf, size_t len)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
-{
- assert(len < PTRDIFF_MAX);
- const ptrdiff_t written_bytes = file_write((FileDescriptor *)data, buf, len);
- if (written_bytes < 0) {
- return msgpack_file_write_error((int)written_bytes);
- }
- return 0;
-}
-
/// Print error which occurs when failing to write msgpack data
///
/// @param[in] error Error code of the error to print.
diff --git a/src/nvim/os/fileio.h b/src/nvim/os/fileio.h
index 72e7984c8a..e8fd2209db 100644
--- a/src/nvim/os/fileio.h
+++ b/src/nvim/os/fileio.h
@@ -1,20 +1,8 @@
#pragma once
-#include <stdbool.h>
-#include <stddef.h>
+#include <stddef.h> // IWYU pragma: keep
-#include "nvim/func_attr.h"
-#include "nvim/rbuffer.h"
-
-/// Structure used to read from/write to file
-typedef struct {
- int fd; ///< File descriptor.
- int _error; ///< Error code for use with RBuffer callbacks or zero.
- RBuffer *rv; ///< Read or write buffer.
- bool wr; ///< True if file is in write mode.
- bool eof; ///< True if end of file was encountered.
- bool non_blocking; ///< True if EAGAIN should not restart syscalls.
-} FileDescriptor;
+#include "nvim/os/fileio_defs.h" // IWYU pragma: keep
/// file_open() flags
typedef enum {
@@ -37,33 +25,6 @@ typedef enum {
kFileMkDir = 256,
} FileOpenFlags;
-static inline bool file_eof(const FileDescriptor *fp)
- REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL;
-
-/// Check whether end of file was encountered
-///
-/// @param[in] fp File to check.
-///
-/// @return true if it was, false if it was not or read operation was never
-/// performed.
-static inline bool file_eof(const FileDescriptor *const fp)
-{
- return fp->eof && rbuffer_size(fp->rv) == 0;
-}
-
-static inline int file_fd(const FileDescriptor *fp)
- REAL_FATTR_PURE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL;
-
-/// Return the file descriptor associated with the FileDescriptor structure
-///
-/// @param[in] fp File to check.
-///
-/// @return File descriptor.
-static inline int file_fd(const FileDescriptor *const fp)
-{
- return fp->fd;
-}
-
enum {
/// Read or write buffer size
///
diff --git a/src/nvim/os/fileio_defs.h b/src/nvim/os/fileio_defs.h
new file mode 100644
index 0000000000..3dc8c7b22a
--- /dev/null
+++ b/src/nvim/os/fileio_defs.h
@@ -0,0 +1,43 @@
+#pragma once
+
+#include <stdbool.h>
+
+#include "nvim/func_attr.h"
+#include "nvim/rbuffer_defs.h"
+
+/// Structure used to read from/write to file
+typedef struct {
+ int fd; ///< File descriptor.
+ int _error; ///< Error code for use with RBuffer callbacks or zero.
+ RBuffer *rv; ///< Read or write buffer.
+ bool wr; ///< True if file is in write mode.
+ bool eof; ///< True if end of file was encountered.
+ bool non_blocking; ///< True if EAGAIN should not restart syscalls.
+} FileDescriptor;
+
+static inline bool file_eof(const FileDescriptor *fp)
+ REAL_FATTR_ALWAYS_INLINE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL;
+
+/// Check whether end of file was encountered
+///
+/// @param[in] fp File to check.
+///
+/// @return true if it was, false if it was not or read operation was never
+/// performed.
+static inline bool file_eof(const FileDescriptor *const fp)
+{
+ return fp->eof && rbuffer_size(fp->rv) == 0;
+}
+
+static inline int file_fd(const FileDescriptor *fp)
+ REAL_FATTR_ALWAYS_INLINE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL;
+
+/// Return the file descriptor associated with the FileDescriptor structure
+///
+/// @param[in] fp File to check.
+///
+/// @return File descriptor.
+static inline int file_fd(const FileDescriptor *const fp)
+{
+ return fp->fd;
+}
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 8f939c3b40..ade745df2c 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -17,8 +17,8 @@
#endif
#include "auto/config.h"
-#include "nvim/func_attr.h"
#include "nvim/os/fs.h"
+#include "nvim/os/os_defs.h"
#if defined(HAVE_ACL)
# ifdef HAVE_SYS_ACL_H
@@ -33,8 +33,9 @@
# include <sys/xattr.h>
#endif
+#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/macros_defs.h"
@@ -44,6 +45,7 @@
#include "nvim/os/os.h"
#include "nvim/path.h"
#include "nvim/types_defs.h"
+#include "nvim/ui.h"
#include "nvim/vim_defs.h"
#ifdef HAVE_SYS_UIO_H
@@ -53,6 +55,7 @@
#ifdef MSWIN
# include "nvim/mbyte.h"
# include "nvim/option.h"
+# include "nvim/os/os_win_console.h"
# include "nvim/strings.h"
#endif
@@ -90,7 +93,11 @@ int os_chdir(const char *path)
smsg(0, "chdir(%s)", path);
verbose_leave();
}
- return uv_chdir(path);
+ int err = uv_chdir(path);
+ if (err == 0) {
+ ui_call_chdir(cstr_as_string(path));
+ }
+ return err;
}
/// Get the name of current directory.
@@ -535,6 +542,22 @@ os_dup_dup:
return ret;
}
+/// Open the file descriptor for stdin.
+int os_open_stdin_fd(void)
+{
+ int stdin_dup_fd;
+ if (stdin_fd > 0) {
+ stdin_dup_fd = stdin_fd;
+ } else {
+ stdin_dup_fd = os_dup(STDIN_FILENO);
+#ifdef MSWIN
+ // Replace the original stdin with the console input handle.
+ os_replace_stdin_to_conin();
+#endif
+ }
+ return stdin_dup_fd;
+}
+
/// Read from a file
///
/// Handles EINTR and ENOMEM, but not other errors.
diff --git a/src/nvim/os/fs.h b/src/nvim/os/fs.h
index 56dd657f70..19cdb09c99 100644
--- a/src/nvim/os/fs.h
+++ b/src/nvim/os/fs.h
@@ -5,7 +5,7 @@
#include <stdio.h> // IWYU pragma: keep
#include <uv.h> // IWYU pragma: keep
-#include "nvim/os/fs_defs.h" // IWYU pragma: export
+#include "nvim/os/fs_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index f3bd1c7ed9..fab360c9af 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -8,13 +8,14 @@
#include "nvim/api/private/defs.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/rstream.h"
#include "nvim/event/stream.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/keycodes.h"
#include "nvim/log.h"
@@ -27,7 +28,9 @@
#include "nvim/os/time.h"
#include "nvim/profile.h"
#include "nvim/rbuffer.h"
+#include "nvim/rbuffer_defs.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#define READ_BUFFER_SIZE 0xfff
#define INPUT_BUFFER_SIZE (READ_BUFFER_SIZE * 4)
@@ -75,6 +78,13 @@ void input_stop(void)
stream_close(&read_stream, NULL, NULL);
}
+#ifdef EXITFREE
+void input_free_all_mem(void)
+{
+ rbuffer_free(input_buffer);
+}
+#endif
+
static void cursorhold_event(void **argv)
{
event_T event = State & MODE_INSERT ? EVENT_CURSORHOLDI : EVENT_CURSORHOLD;
@@ -85,11 +95,11 @@ static void cursorhold_event(void **argv)
static void create_cursorhold_event(bool events_enabled)
{
// If events are enabled and the queue has any items, this function should not
- // have been called(inbuf_poll would return kInputAvail)
+ // have been called (inbuf_poll would return kInputAvail).
// TODO(tarruda): Cursorhold should be implemented as a timer set during the
// `state_check` callback for the states where it can be triggered.
assert(!events_enabled || multiqueue_empty(main_loop.events));
- multiqueue_put(main_loop.events, cursorhold_event, 0);
+ multiqueue_put(main_loop.events, cursorhold_event, NULL);
}
static void restart_cursorhold_wait(int tb_change_cnt)
@@ -100,7 +110,7 @@ static void restart_cursorhold_wait(int tb_change_cnt)
/// Low level input function
///
-/// wait until either the input buffer is non-empty or, if `events` is not NULL
+/// Wait until either the input buffer is non-empty or, if `events` is not NULL
/// until `events` is non-empty.
int os_inchar(uint8_t *buf, int maxlen, int ms, int tb_change_cnt, MultiQueue *events)
{
@@ -304,7 +314,8 @@ static uint8_t check_multiclick(int code, int grid, int row, int col)
}
// For click events the number of clicks is updated.
- if (code == KE_LEFTMOUSE || code == KE_RIGHTMOUSE || code == KE_MIDDLEMOUSE) {
+ if (code == KE_LEFTMOUSE || code == KE_RIGHTMOUSE || code == KE_MIDDLEMOUSE
+ || code == KE_X1MOUSE || code == KE_X2MOUSE) {
uint64_t mouse_time = os_hrtime(); // time of current mouse click (ns)
// compute the time elapsed since the previous mouse click and
// convert p_mouse from ms to ns
@@ -408,7 +419,8 @@ static unsigned handle_mouse_event(const char **ptr, uint8_t *buf, unsigned bufs
size_t input_enqueue_mouse(int code, uint8_t modifier, int grid, int row, int col)
{
modifier |= check_multiclick(code, grid, row, col);
- uint8_t buf[7], *p = buf;
+ uint8_t buf[7];
+ uint8_t *p = buf;
if (modifier) {
p[0] = K_SPECIAL;
p[1] = KS_MODIFIER;
@@ -531,7 +543,7 @@ bool os_input_ready(MultiQueue *events)
{
return (typebuf_was_filled // API call filled typeahead
|| rbuffer_size(input_buffer) // Input buffer filled
- || pending_events(events)); // Events must be processed
+ || pending_events(events)); // Events must be processed
}
// Exit because of an input read error.
diff --git a/src/nvim/os/input.h b/src/nvim/os/input.h
index 4b104b0b50..abef46072b 100644
--- a/src/nvim/os/input.h
+++ b/src/nvim/os/input.h
@@ -4,7 +4,7 @@
#include <stdint.h> // IWYU pragma: keep
#include "nvim/api/private/defs.h" // IWYU pragma: keep
-#include "nvim/event/multiqueue.h"
+#include "nvim/event/defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
EXTERN bool used_stdin INIT( = false);
diff --git a/src/nvim/os/lang.c b/src/nvim/os/lang.c
index 17d179a56a..fb534ab2f4 100644
--- a/src/nvim/os/lang.c
+++ b/src/nvim/os/lang.c
@@ -19,7 +19,8 @@
#include "nvim/eval.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
+#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -79,17 +80,21 @@ static char *get_mess_env(void)
return get_locale_val(LC_MESSAGES);
#else
char *p = (char *)os_getenv("LC_ALL");
+ if (p != NULL) {
+ return p;
+ }
+
+ p = (char *)os_getenv("LC_MESSAGES");
+ if (p != NULL) {
+ return p;
+ }
+
+ p = (char *)os_getenv("LANG");
+ if (p != NULL && ascii_isdigit(*p)) {
+ p = NULL; // ignore something like "1043"
+ }
if (p == NULL) {
- p = (char *)os_getenv("LC_MESSAGES");
- if (p == NULL) {
- p = (char *)os_getenv("LANG");
- if (p != NULL && ascii_isdigit(*p)) {
- p = NULL; // ignore something like "1043"
- }
- if (p == NULL) {
- p = get_locale_val(LC_CTYPE);
- }
- }
+ p = get_locale_val(LC_CTYPE);
}
return p;
#endif
@@ -99,9 +104,7 @@ static char *get_mess_env(void)
/// Also do "v:lc_time"and "v:ctype".
void set_lang_var(void)
{
- const char *loc;
-
- loc = get_locale_val(LC_CTYPE);
+ const char *loc = get_locale_val(LC_CTYPE);
set_vim_var_string(VV_CTYPE, loc, -1);
loc = get_mess_env();
@@ -142,8 +145,6 @@ void init_locale(void)
void ex_language(exarg_T *eap)
{
char *loc;
- char *p;
- char *name;
int what = LC_ALL;
char *whatstr = "";
#ifdef LC_MESSAGES
@@ -152,12 +153,12 @@ void ex_language(exarg_T *eap)
# define VIM_LC_MESSAGES 6789
#endif
- name = eap->arg;
+ char *name = eap->arg;
// Check for "messages {name}", "ctype {name}" or "time {name}" argument.
// Allow abbreviation, but require at least 3 characters to avoid
// confusion with a two letter language name "me" or "ct".
- p = skiptowhite(eap->arg);
+ char *p = skiptowhite(eap->arg);
if ((*p == NUL || ascii_iswhite(*p)) && p - eap->arg >= 3) {
if (STRNICMP(eap->arg, "messages", p - eap->arg) == 0) {
what = VIM_LC_MESSAGES;
@@ -248,7 +249,6 @@ static bool did_init_locales = false;
static char **find_locales(void)
{
garray_T locales_ga;
- char *loc;
char *saveptr = NULL;
// Find all available locales by running command "locale -a". If this
@@ -261,7 +261,7 @@ static char **find_locales(void)
// Transform locale_a string where each locale is separated by "\n"
// into an array of locale strings.
- loc = os_strtok(locale_a, "\n", &saveptr);
+ char *loc = os_strtok(locale_a, "\n", &saveptr);
while (loc != NULL) {
loc = xstrdup(loc);
diff --git a/src/nvim/os/os.h b/src/nvim/os/os.h
index 302d84d066..1a942d062b 100644
--- a/src/nvim/os/os.h
+++ b/src/nvim/os/os.h
@@ -1,24 +1,18 @@
#pragma once
-#include <stddef.h> // IWYU pragma: keep
-#include <stdint.h> // IWYU pragma: keep
-#include <uv.h> // IWYU pragma: keep
+#include <stddef.h>
+#include <stdint.h>
+#include <uv.h>
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
-#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
-#include "nvim/garray_defs.h" // IWYU pragma: keep
-#include "nvim/os/os_defs.h" // IWYU pragma: export
-#include "nvim/os/stdpaths_defs.h" // IWYU pragma: keep
+#include "nvim/cmdexpand_defs.h"
+#include "nvim/garray_defs.h"
+#include "nvim/os/os_defs.h"
+#include "nvim/os/stdpaths_defs.h"
+#include "nvim/types_defs.h"
-#define HAVE_PATHDEF
-
-// Some file names are stored in pathdef.c, which is generated from the
-// Makefile to make their value depend on the Makefile.
-#ifdef HAVE_PATHDEF
extern char *default_vim_dir;
extern char *default_vimruntime_dir;
extern char *default_lib_dir;
-#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
// IWYU pragma: begin_exports
diff --git a/src/nvim/os/os_defs.h b/src/nvim/os/os_defs.h
index 12de55a227..db575e005a 100644
--- a/src/nvim/os/os_defs.h
+++ b/src/nvim/os/os_defs.h
@@ -113,3 +113,31 @@
&& (defined(S_ISCHR) || defined(S_IFCHR))
# define OPEN_CHR_FILES
#endif
+
+// We use 64-bit file functions here, if available. E.g. ftello() returns
+// off_t instead of long, which helps if long is 32 bit and off_t is 64 bit.
+// We assume that when fseeko() is available then ftello() is too.
+// Note that Windows has different function names.
+#if (defined(_MSC_VER) && (_MSC_VER >= 1300)) || defined(__MINGW32__)
+typedef __int64 off_T;
+# ifdef __MINGW32__
+# define vim_lseek lseek64
+# define vim_fseek fseeko64
+# define vim_ftell ftello64
+# else
+# define vim_lseek _lseeki64
+# define vim_fseek _fseeki64
+# define vim_ftell _ftelli64
+# endif
+#else
+typedef off_t off_T;
+# ifdef HAVE_FSEEKO
+# define vim_lseek lseek
+# define vim_ftell ftello
+# define vim_fseek fseeko
+# else
+# define vim_lseek lseek
+# define vim_ftell ftell
+# define vim_fseek(a, b, c) fseek(a, (long)b, c)
+# endif
+#endif
diff --git a/src/nvim/os/os_win_console.c b/src/nvim/os/os_win_console.c
index 816e81e997..953d291290 100644
--- a/src/nvim/os/os_win_console.c
+++ b/src/nvim/os/os_win_console.c
@@ -1,6 +1,7 @@
#include <string.h>
#include "nvim/globals.h"
+#include "nvim/memory.h"
#include "nvim/os/fs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
@@ -105,3 +106,40 @@ void os_title_reset(void)
{
SetConsoleTitle(origTitle);
}
+
+#if !defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
+# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
+#endif
+/// Guesses the terminal-type. Calls SetConsoleMode() and uv_set_vterm_state()
+/// if appropriate.
+///
+/// @param[in,out] term Name of the guessed terminal, statically-allocated
+/// @param out_fd stdout file descriptor
+void os_tty_guess_term(const char **term, int out_fd)
+{
+ bool conemu_ansi = strequal(os_getenv("ConEmuANSI"), "ON");
+ bool vtp = false;
+
+ HANDLE handle = (HANDLE)_get_osfhandle(out_fd);
+ DWORD dwMode;
+ if (handle != INVALID_HANDLE_VALUE && GetConsoleMode(handle, &dwMode)) {
+ dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
+ if (SetConsoleMode(handle, dwMode)) {
+ vtp = true;
+ }
+ }
+
+ if (*term == NULL) {
+ if (vtp) {
+ *term = "vtpcon";
+ } else if (conemu_ansi) {
+ *term = "conemu";
+ } else {
+ *term = "win32con";
+ }
+ }
+
+ if (conemu_ansi) {
+ uv_tty_set_vterm_state(UV_TTY_SUPPORTED);
+ }
+}
diff --git a/src/nvim/os/process.c b/src/nvim/os/process.c
index d9ec3a7a8a..e8d38d5b8a 100644
--- a/src/nvim/os/process.c
+++ b/src/nvim/os/process.c
@@ -44,7 +44,7 @@
#endif
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "os/process.c.generated.h" // IWYU pragma: export
+# include "os/process.c.generated.h"
#endif
#ifdef MSWIN
@@ -114,6 +114,7 @@ bool os_proc_tree_kill(int pid, int sig)
/// @param[out] proc_count Number of child processes.
/// @return 0 on success, 1 if process not found, 2 on other error.
int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
+ FUNC_ATTR_NONNULL_ALL
{
if (ppid < 0) {
return 2;
@@ -229,7 +230,7 @@ int os_proc_children(int ppid, int **proc_list, size_t *proc_count)
///
/// @param pid Process to inspect.
/// @return Map of process properties, empty on error.
-Dictionary os_proc_info(int pid)
+Dictionary os_proc_info(int pid, Arena *arena)
{
Dictionary pinfo = ARRAY_DICT_INIT;
PROCESSENTRY32 pe;
@@ -257,9 +258,10 @@ Dictionary os_proc_info(int pid)
CloseHandle(h);
if (pe.th32ProcessID == (DWORD)pid) {
- PUT(pinfo, "pid", INTEGER_OBJ(pid));
- PUT(pinfo, "ppid", INTEGER_OBJ((int)pe.th32ParentProcessID));
- PUT(pinfo, "name", CSTR_TO_OBJ(pe.szExeFile));
+ pinfo = arena_dict(arena, 3);
+ PUT_C(pinfo, "pid", INTEGER_OBJ(pid));
+ PUT_C(pinfo, "ppid", INTEGER_OBJ((int)pe.th32ParentProcessID));
+ PUT_C(pinfo, "name", CSTR_TO_ARENA_OBJ(arena, pe.szExeFile));
}
return pinfo;
diff --git a/src/nvim/os/pty_conpty_win.c b/src/nvim/os/pty_conpty_win.c
index 53169c0ef8..e7697880af 100644
--- a/src/nvim/os/pty_conpty_win.c
+++ b/src/nvim/os/pty_conpty_win.c
@@ -1,5 +1,6 @@
#include <uv.h>
+#include "nvim/log.h"
#include "nvim/os/os.h"
#include "nvim/os/pty_conpty_win.h"
#include "nvim/vim_defs.h"
diff --git a/src/nvim/os/pty_conpty_win.h b/src/nvim/os/pty_conpty_win.h
index aa04cd1e84..a0c6a06cda 100644
--- a/src/nvim/os/pty_conpty_win.h
+++ b/src/nvim/os/pty_conpty_win.h
@@ -7,7 +7,7 @@
# define HPCON VOID *
#endif
-extern HRESULT(WINAPI *pCreatePseudoConsole) // NOLINT(whitespace/parens)
+extern HRESULT(WINAPI *pCreatePseudoConsole)
(COORD, HANDLE, HANDLE, DWORD, HPCON *);
extern HRESULT(WINAPI *pResizePseudoConsole)(HPCON, COORD);
extern void(WINAPI *pClosePseudoConsole)(HPCON);
diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c
index f801646967..4d34e8fac4 100644
--- a/src/nvim/os/pty_process_unix.c
+++ b/src/nvim/os/pty_process_unix.c
@@ -32,15 +32,15 @@
#include "auto/config.h"
#include "klib/klist.h"
#include "nvim/eval/typval.h"
+#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/process.h"
-#include "nvim/event/stream.h"
-#include "nvim/func_attr.h"
#include "nvim/log.h"
#include "nvim/os/fs.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/pty_process.h"
#include "nvim/os/pty_process_unix.h"
+#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_process_unix.c.generated.h"
@@ -405,3 +405,13 @@ static void chld_handler(uv_signal_t *handle, int signum)
proc->internal_exit_cb(proc);
}
}
+
+PtyProcess pty_process_init(Loop *loop, void *data)
+{
+ PtyProcess rv;
+ rv.process = process_init(loop, kProcessTypePty, data);
+ rv.width = 80;
+ rv.height = 24;
+ rv.tty_fd = -1;
+ return rv;
+}
diff --git a/src/nvim/os/pty_process_unix.h b/src/nvim/os/pty_process_unix.h
index 92cc582832..1a77ae5fd5 100644
--- a/src/nvim/os/pty_process_unix.h
+++ b/src/nvim/os/pty_process_unix.h
@@ -4,26 +4,15 @@
#include <stdint.h>
#include <sys/ioctl.h>
-#include "nvim/event/loop.h"
-#include "nvim/event/process.h"
+#include "nvim/event/defs.h"
-typedef struct pty_process {
+typedef struct {
Process process;
uint16_t width, height;
struct winsize winsize;
int tty_fd;
} PtyProcess;
-static inline PtyProcess pty_process_init(Loop *loop, void *data)
-{
- PtyProcess rv;
- rv.process = process_init(loop, kProcessTypePty, data);
- rv.width = 80;
- rv.height = 24;
- rv.tty_fd = -1;
- return rv;
-}
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_process_unix.h.generated.h"
#endif
diff --git a/src/nvim/os/pty_process_win.c b/src/nvim/os/pty_process_win.c
index ca2dce36ea..12831ff05f 100644
--- a/src/nvim/os/pty_process_win.c
+++ b/src/nvim/os/pty_process_win.c
@@ -4,6 +4,8 @@
#include "nvim/ascii_defs.h"
#include "nvim/eval/typval.h"
+#include "nvim/event/loop.h"
+#include "nvim/log.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/os/os.h"
@@ -21,9 +23,19 @@ static void CALLBACK pty_process_finish1(void *context, BOOLEAN unused)
Process *proc = (Process *)ptyproc;
os_conpty_free(ptyproc->conpty);
- uv_timer_init(&proc->loop->uv, &ptyproc->wait_eof_timer);
- ptyproc->wait_eof_timer.data = (void *)ptyproc;
- uv_timer_start(&ptyproc->wait_eof_timer, wait_eof_timer_cb, 200, 200);
+ // NB: pty_process_finish1() is called on a separate thread,
+ // but the timer only works properly if it's started by the main thread.
+ loop_schedule_fast(proc->loop, event_create(start_wait_eof_timer, ptyproc));
+}
+
+static void start_wait_eof_timer(void **argv)
+ FUNC_ATTR_NONNULL_ALL
+{
+ PtyProcess *ptyproc = (PtyProcess *)argv[0];
+
+ if (ptyproc->finish_wait != NULL) {
+ uv_timer_start(&ptyproc->wait_eof_timer, wait_eof_timer_cb, 200, 200);
+ }
}
/// @returns zero on success, or negative error code.
@@ -104,6 +116,8 @@ int pty_process_spawn(PtyProcess *ptyproc)
}
proc->pid = (int)GetProcessId(process_handle);
+ uv_timer_init(&proc->loop->uv, &ptyproc->wait_eof_timer);
+ ptyproc->wait_eof_timer.data = (void *)ptyproc;
if (!RegisterWaitForSingleObject(&ptyproc->finish_wait,
process_handle,
pty_process_finish1,
@@ -163,6 +177,16 @@ void pty_process_close(PtyProcess *ptyproc)
pty_process_close_master(ptyproc);
+ if (ptyproc->finish_wait != NULL) {
+ UnregisterWaitEx(ptyproc->finish_wait, NULL);
+ ptyproc->finish_wait = NULL;
+ uv_close((uv_handle_t *)&ptyproc->wait_eof_timer, NULL);
+ }
+ if (ptyproc->process_handle != NULL) {
+ CloseHandle(ptyproc->process_handle);
+ ptyproc->process_handle = NULL;
+ }
+
if (proc->internal_close_cb) {
proc->internal_close_cb(proc);
}
@@ -191,6 +215,7 @@ static void wait_eof_timer_cb(uv_timer_t *wait_eof_timer)
PtyProcess *ptyproc = wait_eof_timer->data;
Process *proc = (Process *)ptyproc;
+ assert(ptyproc->finish_wait != NULL);
if (proc->out.closed || proc->out.did_eof || !uv_is_readable(proc->out.uvstream)) {
uv_timer_stop(&ptyproc->wait_eof_timer);
pty_process_finish2(ptyproc);
@@ -202,16 +227,10 @@ static void pty_process_finish2(PtyProcess *ptyproc)
{
Process *proc = (Process *)ptyproc;
- UnregisterWaitEx(ptyproc->finish_wait, NULL);
- uv_close((uv_handle_t *)&ptyproc->wait_eof_timer, NULL);
-
DWORD exit_code = 0;
GetExitCodeProcess(ptyproc->process_handle, &exit_code);
proc->status = proc->exit_signal ? 128 + proc->exit_signal : (int)exit_code;
- CloseHandle(ptyproc->process_handle);
- ptyproc->process_handle = NULL;
-
proc->internal_exit_cb(proc);
}
@@ -407,3 +426,15 @@ cleanup:
return rc;
}
+
+PtyProcess pty_process_init(Loop *loop, void *data)
+{
+ PtyProcess rv;
+ rv.process = process_init(loop, kProcessTypePty, data);
+ rv.width = 80;
+ rv.height = 24;
+ rv.conpty = NULL;
+ rv.finish_wait = NULL;
+ rv.process_handle = NULL;
+ return rv;
+}
diff --git a/src/nvim/os/pty_process_win.h b/src/nvim/os/pty_process_win.h
index 26cf387e54..3528f6bfe5 100644
--- a/src/nvim/os/pty_process_win.h
+++ b/src/nvim/os/pty_process_win.h
@@ -4,7 +4,7 @@
#include <uv.h>
#include "nvim/event/process.h"
-#include "nvim/lib/queue.h"
+#include "nvim/lib/queue_defs.h"
#include "nvim/os/pty_conpty_win.h"
typedef struct pty_process {
@@ -22,18 +22,6 @@ typedef struct arg_node {
QUEUE node; // QUEUE structure.
} ArgNode;
-static inline PtyProcess pty_process_init(Loop *loop, void *data)
-{
- PtyProcess rv;
- rv.process = process_init(loop, kProcessTypePty, data);
- rv.width = 80;
- rv.height = 24;
- rv.conpty = NULL;
- rv.finish_wait = NULL;
- rv.process_handle = NULL;
- return rv;
-}
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/pty_process_win.h.generated.h"
#endif
diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c
index 191be784e8..46ba13c4cd 100644
--- a/src/nvim/os/shell.c
+++ b/src/nvim/os/shell.c
@@ -8,9 +8,11 @@
#include "auto/config.h"
#include "klib/kvec.h"
#include "nvim/ascii_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/eval.h"
#include "nvim/eval/typval_defs.h"
+#include "nvim/event/defs.h"
#include "nvim/event/libuv_process.h"
#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
@@ -20,8 +22,7 @@
#include "nvim/event/wstream.h"
#include "nvim/ex_cmds.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/main.h"
@@ -31,6 +32,7 @@
#include "nvim/message.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/shell.h"
#include "nvim/os/signal.h"
#include "nvim/os/time.h"
@@ -38,6 +40,7 @@
#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/rbuffer.h"
+#include "nvim/rbuffer_defs.h"
#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
@@ -118,14 +121,10 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
int i;
size_t len;
char *p;
- bool dir;
char *extra_shell_arg = NULL;
ShellOpts shellopts = kShellOptExpand | kShellOptSilent;
int j;
char *tempname;
- char *command;
- FILE *fd;
- char *buffer;
#define STYLE_ECHO 0 // use "echo", the default
#define STYLE_GLOB 1 // use "glob", for csh
#define STYLE_VIMGLOB 2 // use "vimglob", for Posix sh
@@ -241,7 +240,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
len += sizeof("egin;" " end") - 1;
}
- command = xmalloc(len);
+ char *command = xmalloc(len);
// Build the shell command:
// - Set $nonomatch depending on EW_NOTFOUND (hopefully the shell
@@ -389,7 +388,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
}
// read the names from the file into memory
- fd = fopen(tempname, READBIN);
+ FILE *fd = fopen(tempname, READBIN);
if (fd == NULL) {
// Something went wrong, perhaps a file name with a special char.
if (!(flags & EW_SILENT)) {
@@ -416,7 +415,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
#endif
len = (size_t)templen;
fseek(fd, 0, SEEK_SET);
- buffer = xmalloc(len + 1);
+ char *buffer = xmalloc(len + 1);
// fread() doesn't terminate buffer with NUL;
// appropriate termination (not always NUL) is done below.
size_t readlen = fread(buffer, 1, len, fd);
@@ -537,7 +536,7 @@ int os_expand_wildcards(int num_pat, char **pat, int *num_file, char ***file, in
}
// check if this entry should be included
- dir = (os_isdir((*file)[i]));
+ bool dir = (os_isdir((*file)[i]));
if ((dir && !(flags & EW_DIR)) || (!dir && !(flags & EW_FILE))) {
continue;
}
@@ -670,7 +669,8 @@ char *shell_argv_to_str(char **const argv)
int os_call_shell(char *cmd, ShellOpts opts, char *extra_args)
{
DynamicBuffer input = DYNAMIC_BUFFER_INIT;
- char *output = NULL, **output_ptr = NULL;
+ char *output = NULL;
+ char **output_ptr = NULL;
int current_state = State;
bool forward_output = true;
@@ -702,7 +702,7 @@ int os_call_shell(char *cmd, ShellOpts opts, char *extra_args)
xfree(input.data);
if (output) {
- (void)write_output(output, nread, true);
+ write_output(output, nread, true);
xfree(output);
}
@@ -1122,7 +1122,8 @@ static void out_data_ring(char *output, size_t size)
static void out_data_append_to_screen(char *output, size_t *count, bool eof)
FUNC_ATTR_NONNULL_ALL
{
- char *p = output, *end = output + *count;
+ char *p = output;
+ char *end = output + *count;
while (p < end) {
if (*p == '\n' || *p == '\r' || *p == TAB || *p == BELL) {
msg_putchar_attr((uint8_t)(*p), 0);
@@ -1141,7 +1142,7 @@ static void out_data_append_to_screen(char *output, size_t *count, bool eof)
goto end;
}
- (void)msg_outtrans_len(p, i, 0);
+ msg_outtrans_len(p, i, 0);
p += i;
}
}
@@ -1235,7 +1236,8 @@ static size_t word_length(const char *str)
/// before we finish writing.
static void read_input(DynamicBuffer *buf)
{
- size_t written = 0, len = 0;
+ size_t written = 0;
+ size_t len = 0;
linenr_T lnum = curbuf->b_op_start.lnum;
char *lp = ml_get(lnum);
diff --git a/src/nvim/os/signal.c b/src/nvim/os/signal.c
index c920cb655e..ecedf144e5 100644
--- a/src/nvim/os/signal.c
+++ b/src/nvim/os/signal.c
@@ -7,9 +7,11 @@
#endif
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/eval.h"
+#include "nvim/event/defs.h"
#include "nvim/event/signal.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/main.h"
diff --git a/src/nvim/os/stdpaths.c b/src/nvim/os/stdpaths.c
index 7691aa5122..ede17bc7c8 100644
--- a/src/nvim/os/stdpaths.c
+++ b/src/nvim/os/stdpaths.c
@@ -4,13 +4,16 @@
#include "nvim/ascii_defs.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/memory.h"
#include "nvim/os/os.h"
#include "nvim/os/stdpaths_defs.h"
#include "nvim/path.h"
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "os/stdpaths.c.generated.h"
+#endif
+
/// Names of the environment variables, mapped to XDGVarType values
static const char *xdg_env_vars[] = {
[kXDGConfigHome] = "XDG_CONFIG_HOME",
diff --git a/src/nvim/os/time.c b/src/nvim/os/time.c
index 49b43af6c0..16118028b4 100644
--- a/src/nvim/os/time.c
+++ b/src/nvim/os/time.c
@@ -8,8 +8,8 @@
#include "auto/config.h"
#include "nvim/event/loop.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/event/multiqueue.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/log.h"
#include "nvim/main.h"
@@ -19,7 +19,7 @@
#include "nvim/os/time.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "os/time.c.generated.h" // IWYU pragma: export
+# include "os/time.c.generated.h"
#endif
/// Gets a high-resolution (nanosecond), monotonically-increasing time relative
diff --git a/src/nvim/os/time.h b/src/nvim/os/time.h
index 2748ba6953..b4d82d8002 100644
--- a/src/nvim/os/time.h
+++ b/src/nvim/os/time.h
@@ -3,7 +3,7 @@
#include <stddef.h> // IWYU pragma: keep
#include <time.h> // IWYU pragma: keep
-#include "nvim/os/time_defs.h" // IWYU pragma: export
+#include "nvim/os/time_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/time.h.generated.h"
diff --git a/src/nvim/os/tty.c b/src/nvim/os/tty.c
deleted file mode 100644
index e683b9383f..0000000000
--- a/src/nvim/os/tty.c
+++ /dev/null
@@ -1,49 +0,0 @@
-//
-// Terminal/console utils
-//
-
-#include "nvim/os/os.h" // IWYU pragma: keep (Windows)
-#include "nvim/os/tty.h"
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "os/tty.c.generated.h" // IWYU pragma: export
-#endif
-
-#ifdef MSWIN
-# if !defined(ENABLE_VIRTUAL_TERMINAL_PROCESSING)
-# define ENABLE_VIRTUAL_TERMINAL_PROCESSING 0x0004
-# endif
-/// Guesses the terminal-type. Calls SetConsoleMode() and uv_set_vterm_state()
-/// if appropriate.
-///
-/// @param[in,out] term Name of the guessed terminal, statically-allocated
-/// @param out_fd stdout file descriptor
-void os_tty_guess_term(const char **term, int out_fd)
-{
- bool conemu_ansi = strequal(os_getenv("ConEmuANSI"), "ON");
- bool vtp = false;
-
- HANDLE handle = (HANDLE)_get_osfhandle(out_fd);
- DWORD dwMode;
- if (handle != INVALID_HANDLE_VALUE && GetConsoleMode(handle, &dwMode)) {
- dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
- if (SetConsoleMode(handle, dwMode)) {
- vtp = true;
- }
- }
-
- if (*term == NULL) {
- if (vtp) {
- *term = "vtpcon";
- } else if (conemu_ansi) {
- *term = "conemu";
- } else {
- *term = "win32con";
- }
- }
-
- if (conemu_ansi) {
- uv_tty_set_vterm_state(UV_TTY_SUPPORTED);
- }
-}
-#endif
diff --git a/src/nvim/os/tty.h b/src/nvim/os/tty.h
deleted file mode 100644
index a24d875c05..0000000000
--- a/src/nvim/os/tty.h
+++ /dev/null
@@ -1,5 +0,0 @@
-#pragma once
-
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "os/tty.h.generated.h" // IWYU pragma: export
-#endif
diff --git a/src/nvim/os/users.c b/src/nvim/os/users.c
index ae0994a73f..8886d6068d 100644
--- a/src/nvim/os/users.c
+++ b/src/nvim/os/users.c
@@ -9,8 +9,10 @@
#include "nvim/ascii_defs.h"
#include "nvim/cmdexpand_defs.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/memory.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/vim_defs.h"
#ifdef HAVE_PWD_FUNCS
# include <pwd.h>
@@ -22,6 +24,10 @@
# include "nvim/message.h"
#endif
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "os/users.c.generated.h"
+#endif
+
// All user names (for ~user completion as done by shell).
static garray_T ga_users = GA_EMPTY_INIT_VALUE;
@@ -186,7 +192,7 @@ void free_users(void)
/// Done only once and then cached.
static void init_users(void)
{
- static int lazy_init_done = false;
+ static bool lazy_init_done = false;
if (lazy_init_done) {
return;
diff --git a/src/nvim/path.c b/src/nvim/path.c
index c7212c7ade..4de18c7530 100644
--- a/src/nvim/path.c
+++ b/src/nvim/path.c
@@ -8,6 +8,7 @@
#include "auto/config.h"
#include "nvim/ascii_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
#include "nvim/eval.h"
@@ -15,23 +16,25 @@
#include "nvim/ex_docmd.h"
#include "nvim/file_search.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/garray_defs.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/shell.h"
#include "nvim/path.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/strings.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -153,7 +156,7 @@ char *path_tail_with_sep(char *fname)
///
/// @return The position of the last path separator + 1.
const char *invocation_path_tail(const char *invocation, size_t *len)
- FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ARG(1)
+ FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ARG(1)
{
const char *tail = get_past_head(invocation);
const char *p = tail;
@@ -238,9 +241,9 @@ char *get_past_head(const char *path)
return (char *)retval;
}
-/// Return true if 'c' is a path separator.
+/// @return true if 'c' is a path separator.
/// Note that for MS-Windows this includes the colon.
-int vim_ispathsep(int c)
+bool vim_ispathsep(int c)
{
#ifdef UNIX
return c == '/'; // Unix has ':' inside file names
@@ -254,7 +257,7 @@ int vim_ispathsep(int c)
}
// Like vim_ispathsep(c), but exclude the colon for MS-Windows.
-int vim_ispathsep_nocolon(int c)
+bool vim_ispathsep_nocolon(int c)
{
return vim_ispathsep(c)
#ifdef BACKSLASH_IN_FILENAME
@@ -263,8 +266,8 @@ int vim_ispathsep_nocolon(int c)
;
}
-/// return true if 'c' is a path list separator.
-int vim_ispathlistsep(int c)
+/// @return true if 'c' is a path list separator.
+bool vim_ispathlistsep(int c)
{
#ifdef UNIX
return c == ':';
@@ -652,7 +655,7 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
&& (vim_strchr("*?[{~$", (uint8_t)(*path_end)) != NULL
|| (!p_fic && (flags & EW_ICASE) && mb_isalpha(utf_ptr2char(path_end))))
#endif
- ) { // NOLINT(whitespace/parens)
+ ) {
e = p;
}
len = (size_t)(utfc_ptr2len(path_end));
@@ -718,7 +721,7 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
&& *path_end == '/') {
STRCPY(s, path_end + 1);
stardepth++;
- (void)do_path_expand(gap, buf, (size_t)(s - buf), flags, true);
+ do_path_expand(gap, buf, (size_t)(s - buf), flags, true);
stardepth--;
}
*s = NUL;
@@ -747,7 +750,7 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
STRCPY(buf + len, "/**"); // NOLINT
STRCPY(buf + len + 3, path_end);
stardepth++;
- (void)do_path_expand(gap, buf, len + 1, flags, true);
+ do_path_expand(gap, buf, len + 1, flags, true);
stardepth--;
}
@@ -755,7 +758,7 @@ static size_t do_path_expand(garray_T *gap, const char *path, size_t wildoff, in
if (path_has_exp_wildcard(path_end)) { // handle more wildcards
// need to expand another component of the path
// remove backslashes for the remaining components only
- (void)do_path_expand(gap, buf, len + 1, flags, false);
+ do_path_expand(gap, buf, len + 1, flags, false);
} else {
FileInfo file_info;
@@ -908,7 +911,7 @@ static char *get_path_cutoff(char *fname, garray_T *gap)
#ifdef MSWIN
|| (vim_ispathsep(fname[j]) && vim_ispathsep(path_part[i][j]))
#endif
- ) // NOLINT(whitespace/parens)
+ )
&& fname[j] != NUL && path_part[i][j] != NUL) {
j++;
}
@@ -972,20 +975,17 @@ static void uniquefy_paths(garray_T *gap, char *pattern)
for (int i = 0; i < gap->ga_len && !got_int; i++) {
char *path = fnames[i];
- int is_in_curdir;
const char *dir_end = gettail_dir(path);
- char *pathsep_p;
- char *path_cutoff;
len = strlen(path);
- is_in_curdir = path_fnamencmp(curdir, path, (size_t)(dir_end - path)) == 0
- && curdir[dir_end - path] == NUL;
+ bool is_in_curdir = path_fnamencmp(curdir, path, (size_t)(dir_end - path)) == 0
+ && curdir[dir_end - path] == NUL;
if (is_in_curdir) {
in_curdir[i] = xstrdup(path);
}
// Shorten the filename while maintaining its uniqueness
- path_cutoff = get_path_cutoff(path, &path_ga);
+ char *path_cutoff = get_path_cutoff(path, &path_ga);
// Don't assume all files can be reached without path when search
// pattern starts with **/, so only remove path_cutoff
@@ -1000,7 +1000,7 @@ static void uniquefy_paths(garray_T *gap, char *pattern)
} else {
// Here all files can be reached without path, so get shortest
// unique path. We start at the end of the path. */
- pathsep_p = path + len - 1;
+ char *pathsep_p = path + len - 1;
while (find_previous_pathsep(path, &pathsep_p)) {
if (vim_regexec(&regmatch, pathsep_p + 1, 0)
&& is_unique(pathsep_p + 1, gap, i)
@@ -1355,7 +1355,7 @@ void FreeWild(int count, char **files)
}
/// @return true if we can expand this backtick thing here.
-static int vim_backtick(char *p)
+static bool vim_backtick(char *p)
{
return *p == '`' && *(p + 1) != NUL && *(p + strlen(p) - 1) == '`';
}
@@ -1668,7 +1668,7 @@ static char *eval_includeexpr(const char *const ptr, const size_t len)
current_sctx = curbuf->b_p_script_ctx[BV_INEX].script_ctx;
char *res = eval_to_string_safe(curbuf->b_p_inex,
- was_set_insecurely(curwin, "includeexpr", OPT_LOCAL));
+ was_set_insecurely(curwin, kOptIncludeexpr, OPT_LOCAL));
set_vim_var_string(VV_FNAME, NULL, 0);
current_sctx = save_sctx;
@@ -1969,7 +1969,7 @@ bool same_directory(char *f1, char *f2)
return false;
}
- (void)vim_FullName(f1, ffname, MAXPATHL, false);
+ vim_FullName(f1, ffname, MAXPATHL, false);
t1 = path_tail_with_sep(ffname);
t2 = path_tail_with_sep(f2);
return t1 - ffname == t2 - f2
@@ -2239,7 +2239,7 @@ int expand_wildcards(int num_pat, char **pat, int *num_files, char ***files, int
}
/// @return true if "fname" matches with an entry in 'suffixes'.
-int match_suffix(char *fname)
+bool match_suffix(char *fname)
{
#define MAXSUFLEN 30 // maximum length of a file suffix
char suf_buf[MAXSUFLEN];
@@ -2394,7 +2394,7 @@ static int path_to_absolute(const char *fname, char *buf, size_t len, int force)
/// Check if file `fname` is a full (absolute) path.
///
/// @return `true` if "fname" is absolute.
-int path_is_absolute(const char *fname)
+bool path_is_absolute(const char *fname)
{
#ifdef MSWIN
if (*fname == NUL) {
diff --git a/src/nvim/path.h b/src/nvim/path.h
index 89f939dd02..a8eb893bb3 100644
--- a/src/nvim/path.h
+++ b/src/nvim/path.h
@@ -2,32 +2,33 @@
#include <stddef.h> // IWYU pragma: keep
-#include "nvim/func_attr.h"
#include "nvim/garray_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
-// Flags for expand_wildcards()
-#define EW_DIR 0x01 // include directory names
-#define EW_FILE 0x02 // include file names
-#define EW_NOTFOUND 0x04 // include not found names
-#define EW_ADDSLASH 0x08 // append slash to directory name
-#define EW_KEEPALL 0x10 // keep all matches
-#define EW_SILENT 0x20 // don't print "1 returned" from shell
-#define EW_EXEC 0x40 // executable files
-#define EW_PATH 0x80 // search in 'path' too
-#define EW_ICASE 0x100 // ignore case
-#define EW_NOERROR 0x200 // no error for bad regexp
-#define EW_NOTWILD 0x400 // add match with literal name if exists
-#define EW_KEEPDOLLAR 0x800 // do not escape $, $var is expanded
+/// Flags for expand_wildcards()
+enum {
+ EW_DIR = 0x01, ///< include directory names
+ EW_FILE = 0x02, ///< include file names
+ EW_NOTFOUND = 0x04, ///< include not found names
+ EW_ADDSLASH = 0x08, ///< append slash to directory name
+ EW_KEEPALL = 0x10, ///< keep all matches
+ EW_SILENT = 0x20, ///< don't print "1 returned" from shell
+ EW_EXEC = 0x40, ///< executable files
+ EW_PATH = 0x80, ///< search in 'path' too
+ EW_ICASE = 0x100, ///< ignore case
+ EW_NOERROR = 0x200, ///< no error for bad regexp
+ EW_NOTWILD = 0x400, ///< add match with literal name if exists
+ EW_KEEPDOLLAR = 0x800, ///< do not escape $, $var is expanded
+ EW_ALLLINKS = 0x1000, ///< also links not pointing to existing file
+ EW_SHELLCMD = 0x2000, ///< called from expand_shellcmd(), don't check
+ ///< if executable is in $PATH
+ EW_DODOT = 0x4000, ///< also files starting with a dot
+ EW_EMPTYOK = 0x8000, ///< no matches is not an error
+ EW_NOTENV = 0x10000, ///< do not expand environment variables
+ EW_NOBREAK = 0x20000, ///< do not invoke breakcheck
+};
// Note: mostly EW_NOTFOUND and EW_SILENT are mutually exclusive: EW_NOTFOUND
// is used when executing commands and EW_SILENT for interactive expanding.
-#define EW_ALLLINKS 0x1000 // also links not pointing to existing file
-#define EW_SHELLCMD 0x2000 // called from expand_shellcmd(), don't check
- // if executable is in $PATH
-#define EW_DODOT 0x4000 // also files starting with a dot
-#define EW_EMPTYOK 0x8000 // no matches is not an error
-#define EW_NOTENV 0x10000 // do not expand environment variables
-#define EW_NOBREAK 0x20000 // do not invoke breakcheck
/// Return value for the comparison of two files. Also @see path_full_compare.
typedef enum file_comparison {
diff --git a/src/nvim/plines.c b/src/nvim/plines.c
index 6e9f92c193..eca07f0144 100644
--- a/src/nvim/plines.c
+++ b/src/nvim/plines.c
@@ -6,16 +6,20 @@
#include <string.h>
#include "nvim/ascii_defs.h"
+#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/decoration.h"
+#include "nvim/decoration_defs.h"
#include "nvim/diff.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/indent.h"
#include "nvim/macros_defs.h"
-#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
+#include "nvim/marktree.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/move.h"
#include "nvim/option.h"
@@ -23,6 +27,7 @@
#include "nvim/plines.h"
#include "nvim/pos_defs.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/types_defs.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -31,14 +36,14 @@
/// Functions calculating horizontal size of text, when displayed in a window.
-/// Return the number of characters 'c' will take on the screen, taking
-/// into account the size of a tab.
+/// Return the number of cells the first char in "p" will take on the screen,
+/// taking into account the size of a tab.
/// Also see getvcol()
///
/// @param p
/// @param col
///
-/// @return Number of characters.
+/// @return Number of cells.
int win_chartabsize(win_T *wp, char *p, colnr_T col)
{
buf_T *buf = wp->w_buffer;
@@ -48,48 +53,21 @@ int win_chartabsize(win_T *wp, char *p, colnr_T col)
return ptr2cells(p);
}
-/// Return the number of characters the string 's' will take on the screen,
-/// taking into account the size of a tab.
-///
-/// @param s
-///
-/// @return Number of characters the string will take on the screen.
-int linetabsize_str(char *s)
-{
- return linetabsize_col(0, s);
-}
-
-/// Like linetabsize_str(), but "s" starts at column "startcol".
+/// Like linetabsize_str(), but "s" starts at virtual column "startvcol".
///
/// @param startcol
/// @param s
///
-/// @return Number of characters the string will take on the screen.
-int linetabsize_col(int startcol, char *s)
+/// @return Number of cells the string will take on the screen.
+int linetabsize_col(int startvcol, char *s)
{
- chartabsize_T cts;
- init_chartabsize_arg(&cts, curwin, 0, startcol, s, s);
- while (*cts.cts_ptr != NUL) {
- cts.cts_vcol += lbr_chartabsize_adv(&cts);
+ CharsizeArg csarg;
+ CSType const cstype = init_charsize_arg(&csarg, curwin, 0, s);
+ if (cstype == kCharsizeFast) {
+ return linesize_fast(&csarg, startvcol, MAXCOL);
+ } else {
+ return linesize_regular(&csarg, startvcol, MAXCOL);
}
- clear_chartabsize_arg(&cts);
- return cts.cts_vcol;
-}
-
-/// Like linetabsize_str(), but for a given window instead of the current one.
-///
-/// @param wp
-/// @param line
-/// @param len
-///
-/// @return Number of characters the string will take on the screen.
-int 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);
- win_linetabsize_cts(&cts, len);
- clear_chartabsize_arg(&cts);
- return cts.cts_vcol;
}
/// Return the number of cells line "lnum" of window "wp" will take on the
@@ -99,144 +77,100 @@ int linetabsize(win_T *wp, linenr_T lnum)
return win_linetabsize(wp, lnum, ml_get_buf(wp->w_buffer, lnum), (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 inline virtual text after the end of the line
- if (len == MAXCOL && cts->cts_has_virt_text && *cts->cts_ptr == NUL) {
- (void)win_lbr_chartabsize(cts, NULL);
- cts->cts_vcol += cts->cts_cur_text_width_left + cts->cts_cur_text_width_right;
- }
-}
+static const uint32_t inline_filter[4] = {[kMTMetaInline] = kMTFilterSelect };
-/// Prepare the structure passed to chartabsize functions.
+/// Prepare the structure passed to charsize functions.
///
-/// "line" is the start of the line, "ptr" is the first relevant character.
+/// "line" is the start of the line.
/// 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)
+CSType init_charsize_arg(CharsizeArg *csarg, win_T *wp, linenr_T lnum, char *line)
{
- cts->cts_win = wp;
- cts->cts_vcol = col;
- cts->cts_line = line;
- cts->cts_ptr = ptr;
- cts->cts_max_head_vcol = 0;
- 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 && wp->w_buffer->b_virt_text_inline > 0) {
- marktree_itr_get(wp->w_buffer->b_marktree, cts->cts_row, 0, cts->cts_iter);
- MTKey mark = marktree_itr_current(cts->cts_iter);
- if (mark.pos.row == cts->cts_row) {
- cts->cts_has_virt_text = true;
+ csarg->win = wp;
+ csarg->line = line;
+ csarg->max_head_vcol = 0;
+ csarg->cur_text_width_left = 0;
+ csarg->cur_text_width_right = 0;
+ csarg->virt_row = -1;
+ csarg->indent_width = INT_MIN;
+ csarg->use_tabstop = !wp->w_p_list || wp->w_p_lcs_chars.tab1;
+
+ if (lnum > 0) {
+ if (marktree_itr_get_filter(wp->w_buffer->b_marktree, lnum - 1, 0, lnum, 0,
+ inline_filter, csarg->iter)) {
+ csarg->virt_row = lnum - 1;
}
}
-}
-
-/// Free any allocated item in "cts".
-void clear_chartabsize_arg(chartabsize_T *cts)
-{
-}
-/// like win_chartabsize(), but also check for line breaks on the screen
-///
-/// @param cts
-///
-/// @return The number of characters taken up on the screen.
-int lbr_chartabsize(chartabsize_T *cts)
-{
- if (!curwin->w_p_lbr && *get_showbreak_value(curwin) == NUL
- && !curwin->w_p_bri && !cts->cts_has_virt_text) {
- if (curwin->w_p_wrap) {
- return win_nolbr_chartabsize(cts, NULL);
- }
- return win_chartabsize(curwin, cts->cts_ptr, cts->cts_vcol);
+ if (csarg->virt_row >= 0
+ || (wp->w_p_wrap && (wp->w_p_lbr || wp->w_p_bri || *get_showbreak_value(wp) != NUL))) {
+ return kCharsizeRegular;
+ } else {
+ return kCharsizeFast;
}
- return win_lbr_chartabsize(cts, NULL);
}
-/// Call lbr_chartabsize() and advance the pointer.
-///
-/// @param cts
-///
-/// @return The number of characters take up on the screen.
-int lbr_chartabsize_adv(chartabsize_T *cts)
-{
- int retval = lbr_chartabsize(cts);
- MB_PTR_ADV(cts->cts_ptr);
- return retval;
-}
-
-/// Get the number of characters taken up on the screen indicated by "cts".
-/// "cts->cts_cur_text_width_left" and "cts->cts_cur_text_width_right" are set
+/// Get the number of cells taken up on the screen for the given arguments.
+/// "csarg->cur_text_width_left" and "csarg->cur_text_width_right" are set
/// to the extra size for inline virtual text.
-/// This function is used very often, keep it fast!!!!
///
-/// If "headp" not NULL, set "*headp" to the size of 'showbreak'/'breakindent'
-/// included in the return value.
-/// When "cts->cts_max_head_vcol" is positive, only count in "*headp" the size
-/// of 'showbreak'/'breakindent' before "cts->cts_max_head_vcol".
-/// When "cts->cts_max_head_vcol" is negative, only count in "*headp" the size
+/// When "csarg->max_head_vcol" is positive, only count in "head" the size
+/// of 'showbreak'/'breakindent' before "csarg->max_head_vcol".
+/// When "csarg->max_head_vcol" is negative, only count in "head" the size
/// of 'showbreak'/'breakindent' before where cursor should be placed.
-///
-/// Warning: "*headp" may not be set if it's 0, init to 0 before calling.
-int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
+CharSize charsize_regular(CharsizeArg *csarg, char *const cur, colnr_T const vcol,
+ int32_t const cur_char)
{
- win_T *wp = cts->cts_win;
- char *line = cts->cts_line; // start of the line
- char *s = cts->cts_ptr;
- colnr_T vcol = cts->cts_vcol;
- int mb_added = 0;
-
- cts->cts_cur_text_width_left = 0;
- cts->cts_cur_text_width_right = 0;
+ csarg->cur_text_width_left = 0;
+ csarg->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
- && !cts->cts_has_virt_text) {
- if (wp->w_p_wrap) {
- return win_nolbr_chartabsize(cts, headp);
- }
- return win_chartabsize(wp, s, vcol);
- }
+ win_T *wp = csarg->win;
+ buf_T *buf = wp->w_buffer;
+ char *line = csarg->line;
+ bool const use_tabstop = cur_char == TAB && csarg->use_tabstop;
+ int mb_added = 0;
bool has_lcs_eol = wp->w_p_list && wp->w_p_lcs_chars.eol != NUL;
// First get normal size, without 'linebreak' or inline virtual text
- int size = win_chartabsize(wp, s, vcol);
- if (*s == NUL && !has_lcs_eol) {
- size = 0; // NUL is not displayed
+ int size;
+ int is_doublewidth = false;
+ if (use_tabstop) {
+ size = tabstop_padding(vcol, buf->b_p_ts, buf->b_p_vts_array);
+ } else if (*cur == NUL) {
+ // 1 cell for EOL list char (if present), as opposed to the two cell ^@
+ // for a NUL character in the text.
+ size = has_lcs_eol ? 1 : 0;
+ } else if (cur_char < 0) {
+ size = kInvalidByteCells;
+ } else {
+ size = char2cells(cur_char);
+ is_doublewidth = size == 2 && cur_char > 0x80;
}
- bool is_doublewidth = size == 2 && MB_BYTE2LEN((uint8_t)(*s)) > 1;
- if (cts->cts_has_virt_text) {
+ if (csarg->virt_row >= 0) {
int tab_size = size;
- int col = (int)(s - line);
+ int col = (int)(cur - line);
while (true) {
- MTKey mark = marktree_itr_current(cts->cts_iter);
- if (mark.pos.row != cts->cts_row || mark.pos.col > col) {
+ MTKey mark = marktree_itr_current(csarg->iter);
+ if (mark.pos.row != csarg->virt_row || mark.pos.col > col) {
break;
} else if (mark.pos.col == col) {
- if (!mt_end(mark) && mark.flags & (MT_FLAG_DECOR_VIRT_TEXT_INLINE)) {
+ if (!mt_end(mark) && (mark.flags & MT_FLAG_DECOR_VIRT_TEXT_INLINE)
+ && mt_scoped_in_win(mark, wp)) {
DecorInline decor = mt_decor(mark);
DecorVirtText *vt = decor.ext ? decor.data.ext.vt : NULL;
while (vt) {
if (!(vt->flags & kVTIsLines) && vt->pos == kVPosInline) {
if (mt_right(mark)) {
- cts->cts_cur_text_width_right += vt->width;
+ csarg->cur_text_width_right += vt->width;
} else {
- cts->cts_cur_text_width_left += vt->width;
+ csarg->cur_text_width_left += vt->width;
}
size += vt->width;
- if (*s == TAB) {
+ if (use_tabstop) {
// tab size changes because of the inserted text
size -= tab_size;
- tab_size = win_chartabsize(wp, s, vcol + size);
+ tab_size = tabstop_padding(vcol + size, buf->b_p_ts, buf->b_p_vts_array);
size += tab_size;
}
}
@@ -244,7 +178,8 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
}
}
}
- marktree_itr_next(wp->w_buffer->b_marktree, cts->cts_iter);
+ marktree_itr_next_filter(wp->w_buffer->b_marktree, csarg->iter, csarg->virt_row + 1, 0,
+ inline_filter);
}
}
@@ -254,16 +189,17 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
mb_added = 1;
}
+ char *const sbr = get_showbreak_value(wp);
+
// May have to add something for 'breakindent' and/or 'showbreak'
// string at the start of a screen line.
int head = mb_added;
- char *const sbr = get_showbreak_value(wp);
// When "size" is 0, no new screen line is started.
if (size > 0 && wp->w_p_wrap && (*sbr != NUL || wp->w_p_bri)) {
int col_off_prev = win_col_off(wp);
int width2 = wp->w_width_inner - col_off_prev + win_col_off2(wp);
colnr_T wcol = vcol + col_off_prev;
- colnr_T max_head_vcol = cts->cts_max_head_vcol;
+ colnr_T max_head_vcol = csarg->max_head_vcol;
int added = 0;
// cells taken by 'showbreak'/'breakindent' before current char
@@ -274,11 +210,16 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
if (wcol >= width2 && width2 > 0) {
wcol %= width2;
}
- if (*sbr != NUL) {
- head_prev += vim_strsize(sbr);
- }
- if (wp->w_p_bri) {
- head_prev += get_breakindent_win(wp, line);
+ head_prev = csarg->indent_width;
+ if (head_prev == INT_MIN) {
+ head_prev = 0;
+ if (*sbr != NUL) {
+ head_prev += vim_strsize(sbr);
+ }
+ if (wp->w_p_bri) {
+ head_prev += get_breakindent_win(wp, line);
+ }
+ csarg->indent_width = head_prev;
}
if (wcol < head_prev) {
head_prev -= wcol;
@@ -295,12 +236,16 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
if (wcol + size > wp->w_width) {
// cells taken by 'showbreak'/'breakindent' halfway current char
- int head_mid = 0;
- if (*sbr != NUL) {
- head_mid += vim_strsize(sbr);
- }
- if (wp->w_p_bri) {
- head_mid += get_breakindent_win(wp, line);
+ int head_mid = csarg->indent_width;
+ if (head_mid == INT_MIN) {
+ head_mid = 0;
+ if (*sbr != NUL) {
+ head_mid += vim_strsize(sbr);
+ }
+ if (wp->w_p_bri) {
+ head_mid += get_breakindent_win(wp, line);
+ }
+ csarg->indent_width = head_mid;
}
if (head_mid > 0 && wcol + size > wp->w_width_inner) {
// Calculate effective window width.
@@ -320,7 +265,7 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
head += (max_head_vcol - (vcol + head_prev + prev_rem)
+ width2 - 1) / width2 * head_mid;
} else if (max_head_vcol < 0) {
- int off = virt_text_cursor_off(cts, *s == NUL);
+ int off = virt_text_cursor_off(csarg, *cur == NUL);
if (off >= prev_rem) {
if (size > off) {
head += (1 + (off - prev_rem) / width) * head_mid;
@@ -335,25 +280,20 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
size += added;
}
- if (headp != NULL) {
- *headp = head;
- }
-
- colnr_T vcol_start = 0; // start from where to consider linebreak
+ bool need_lbr = false;
// If 'linebreak' set check at a blank before a non-blank if the line
- // needs a break here
- if (wp->w_p_lbr && wp->w_p_wrap && wp->w_width_inner != 0) {
- char *t = cts->cts_line;
+ // needs a break here.
+ if (wp->w_p_lbr && wp->w_p_wrap && wp->w_width_inner != 0
+ && vim_isbreak((uint8_t)cur[0]) && !vim_isbreak((uint8_t)cur[1])) {
+ char *t = csarg->line;
while (vim_isbreak((uint8_t)t[0])) {
t++;
}
- vcol_start = (colnr_T)(t - cts->cts_line);
+ // 'linebreak' is only needed when not in leading whitespace.
+ need_lbr = cur >= t;
}
- if (wp->w_p_lbr && vcol_start <= vcol
- && vim_isbreak((uint8_t)s[0])
- && !vim_isbreak((uint8_t)s[1])
- && wp->w_p_wrap
- && wp->w_width_inner != 0) {
+ if (need_lbr) {
+ char *s = cur;
// Count all characters from first non-blank after a blank up to next
// non-blank after a blank.
int numberextra = win_col_off(wp);
@@ -385,39 +325,54 @@ int win_lbr_chartabsize(chartabsize_T *cts, int *headp)
}
}
- return size;
+ return (CharSize){ .width = size, .head = head };
}
-/// Like win_lbr_chartabsize(), except that we know 'linebreak' is off and
-/// 'wrap' is on. This means we need to check for a double-byte character that
-/// doesn't fit at the end of the screen line.
-///
-/// @param cts
-/// @param headp
+/// Like charsize_regular(), except it doesn't handle inline virtual text,
+/// 'linebreak', 'breakindent' or 'showbreak'.
+/// Handles normal characters, tabs and wrapping.
+/// This function is always inlined.
///
-/// @return The number of characters take up on the screen.
-static int win_nolbr_chartabsize(chartabsize_T *cts, int *headp)
+/// @see charsize_regular
+/// @see charsize_fast
+static inline CharSize charsize_fast_impl(win_T *const wp, bool use_tabstop, colnr_T const vcol,
+ int32_t const cur_char)
+ FUNC_ATTR_PURE FUNC_ATTR_ALWAYS_INLINE
{
- win_T *wp = cts->cts_win;
- char *s = cts->cts_ptr;
- colnr_T col = cts->cts_vcol;
-
- if ((*s == TAB) && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
- return tabstop_padding(col,
- wp->w_buffer->b_p_ts,
- wp->w_buffer->b_p_vts_array);
- }
- int n = ptr2cells(s);
-
- // Add one cell for a double-width character in the last column of the
- // window, displayed with a ">".
- if ((n == 2) && (MB_BYTE2LEN((uint8_t)(*s)) > 1) && in_win_border(wp, col)) {
- if (headp != NULL) {
- *headp = 1;
+ // A tab gets expanded, depending on the current column
+ if (cur_char == TAB && use_tabstop) {
+ return (CharSize){
+ .width = tabstop_padding(vcol, wp->w_buffer->b_p_ts,
+ wp->w_buffer->b_p_vts_array)
+ };
+ } else {
+ int width;
+ if (cur_char < 0) {
+ width = kInvalidByteCells;
+ } else {
+ width = char2cells(cur_char);
+ }
+
+ // If a double-width char doesn't fit at the end of a line, it wraps to the next line,
+ // and the last column displays a '>'.
+ if (width == 2 && cur_char >= 0x80 && wp->w_p_wrap && in_win_border(wp, vcol)) {
+ return (CharSize){ .width = 3, .head = 1 };
+ } else {
+ return (CharSize){ .width = width };
}
- return 3;
}
- return n;
+}
+
+/// Like charsize_regular(), except it doesn't handle inline virtual text,
+/// 'linebreak', 'breakindent' or 'showbreak'.
+/// Handles normal characters, tabs and wrapping.
+/// Can be used if CSType is kCharsizeFast.
+///
+/// @see charsize_regular
+CharSize charsize_fast(CharsizeArg *csarg, colnr_T const vcol, int32_t const cur_char)
+ FUNC_ATTR_PURE
+{
+ return charsize_fast_impl(csarg->win, csarg->use_tabstop, vcol, cur_char);
}
/// Check that virtual column "vcol" is in the rightmost column of window "wp".
@@ -448,19 +403,65 @@ static bool in_win_border(win_T *wp, colnr_T vcol)
return (vcol - width1) % width2 == width2 - 1;
}
+/// Calculate virtual column until the given "len".
+///
+/// @param arg Argument to charsize functions.
+/// @param vcol Starting virtual column.
+/// @param len First byte of the end character, or MAXCOL.
+///
+/// @return virtual column before the character at "len",
+/// or full size of the line if "len" is MAXCOL.
+int linesize_regular(CharsizeArg *const csarg, int vcol, colnr_T const len)
+{
+ char *const line = csarg->line;
+
+ StrCharInfo ci = utf_ptr2StrCharInfo(line);
+ while (ci.ptr - line < len && *ci.ptr != NUL) {
+ vcol += charsize_regular(csarg, ci.ptr, vcol, ci.chr.value).width;
+ ci = utfc_next(ci);
+ }
+
+ // Check for inline virtual text after the end of the line.
+ if (len == MAXCOL && csarg->virt_row >= 0) {
+ (void)charsize_regular(csarg, ci.ptr, vcol, ci.chr.value);
+ vcol += csarg->cur_text_width_left + csarg->cur_text_width_right;
+ }
+
+ return vcol;
+}
+
+/// Like linesize_regular(), but can be used when CStype is kCharsizeFast.
+///
+/// @see linesize_regular
+int linesize_fast(CharsizeArg const *const csarg, int vcol, colnr_T const len)
+{
+ win_T *const wp = csarg->win;
+ bool const use_tabstop = csarg->use_tabstop;
+
+ char *const line = csarg->line;
+
+ StrCharInfo ci = utf_ptr2StrCharInfo(line);
+ while (ci.ptr - line < len && *ci.ptr != NUL) {
+ vcol += charsize_fast_impl(wp, use_tabstop, vcol, ci.chr.value).width;
+ ci = utfc_next(ci);
+ }
+
+ return vcol;
+}
+
/// Get how many virtual columns inline virtual text should offset the cursor.
///
-/// @param cts should contain information stored by win_lbr_chartabsize()
+/// @param csarg should contain information stored by charsize_regular()
/// about widths of left and right gravity virtual text
/// @param on_NUL whether this is the end of the line
-static int virt_text_cursor_off(chartabsize_T *cts, bool on_NUL)
+static int virt_text_cursor_off(const CharsizeArg *csarg, bool on_NUL)
{
int off = 0;
if (!on_NUL || !(State & MODE_NORMAL)) {
- off += cts->cts_cur_text_width_left;
+ off += csarg->cur_text_width_left;
}
if (!on_NUL && (State & MODE_NORMAL)) {
- off += cts->cts_cur_text_width_right;
+ off += csarg->cur_text_width_right;
}
return off;
}
@@ -479,115 +480,53 @@ static int virt_text_cursor_off(chartabsize_T *cts, bool on_NUL)
/// @param end
void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *end)
{
- char *ptr; // points to current char
- char *posptr; // points to char at pos->col
- int incr;
- int head;
- colnr_T *vts = wp->w_buffer->b_p_vts_array;
- int ts = (int)wp->w_buffer->b_p_ts;
-
- colnr_T vcol = 0;
- char *line = ptr = ml_get_buf(wp->w_buffer, pos->lnum); // start of the line
+ char *const line = ml_get_buf(wp->w_buffer, pos->lnum); // start of the line
+ int const end_col = pos->col;
- if (pos->col == MAXCOL) {
- // continue until the NUL
- posptr = NULL;
- } else {
- // In a few cases the position can be beyond the end of the line.
- for (colnr_T i = 0; i < pos->col; i++) {
- if (ptr[i] == NUL) {
- pos->col = i;
- break;
- }
- }
- posptr = ptr + pos->col;
- posptr -= utf_head_off(line, posptr);
- }
-
- chartabsize_T cts;
+ CharsizeArg csarg;
bool on_NUL = false;
- init_chartabsize_arg(&cts, wp, pos->lnum, 0, line, line);
- cts.cts_max_head_vcol = -1;
-
- // This function is used very often, do some speed optimizations.
- // When 'list', 'linebreak', 'showbreak' and 'breakindent' are not set
- // and there are no virtual text use a simple loop.
- // Also use this when 'list' is set but tabs take their normal size.
- if ((!wp->w_p_list || (wp->w_p_lcs_chars.tab1 != NUL))
- && !wp->w_p_lbr
- && *get_showbreak_value(wp) == NUL
- && !wp->w_p_bri
- && !cts.cts_has_virt_text) {
- while (true) {
- head = 0;
- int c = (uint8_t)(*ptr);
+ CSType const cstype = init_charsize_arg(&csarg, wp, pos->lnum, line);
+ csarg.max_head_vcol = -1;
- // make sure we don't go past the end of the line
- if (c == NUL) {
- // NUL at end of line only takes one column
- incr = 1;
+ colnr_T vcol = 0;
+ CharSize char_size;
+ StrCharInfo ci = utf_ptr2StrCharInfo(line);
+ if (cstype == kCharsizeFast) {
+ bool const use_tabstop = csarg.use_tabstop;
+ while (true) {
+ if (*ci.ptr == NUL) {
+ // if cursor is at NUL, it is treated like 1 cell char
+ char_size = (CharSize){ .width = 1 };
break;
}
-
- // A tab gets expanded, depending on the current column
- if (c == TAB) {
- incr = tabstop_padding(vcol, ts, vts);
- } else {
- // For utf-8, if the byte is >= 0x80, need to look at
- // further bytes to find the cell width.
- if (c >= 0x80) {
- incr = utf_ptr2cells(ptr);
- } else {
- incr = byte2cells(c);
- }
-
- // If a double-cell char doesn't fit at the end of a line
- // it wraps to the next line, it's like this char is three
- // cells wide.
- if ((incr == 2)
- && wp->w_p_wrap
- && (MB_BYTE2LEN((uint8_t)(*ptr)) > 1)
- && in_win_border(wp, vcol)) {
- incr++;
- head = 1;
- }
- }
-
- if ((posptr != NULL) && (ptr >= posptr)) {
- // character at pos->col
+ char_size = charsize_fast_impl(wp, use_tabstop, vcol, ci.chr.value);
+ StrCharInfo const next = utfc_next(ci);
+ if (next.ptr - line > end_col) {
break;
}
-
- vcol += incr;
- MB_PTR_ADV(ptr);
+ ci = next;
+ vcol += char_size.width;
}
} else {
while (true) {
- // A tab gets expanded, depending on the current column
- // Other things also take up space.
- head = 0;
- incr = win_lbr_chartabsize(&cts, &head);
-
- // 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, unless there is virtual text
- incr = MAX(1, cts.cts_cur_text_width_left + cts.cts_cur_text_width_right);
+ char_size = charsize_regular(&csarg, ci.ptr, vcol, ci.chr.value);
+ if (*ci.ptr == NUL) {
+ // if cursor is at NUL, it is treated like 1 cell char unless there is virtual text
+ char_size.width = MAX(1, csarg.cur_text_width_left + csarg.cur_text_width_right);
on_NUL = true;
break;
}
-
- if ((posptr != NULL) && (cts.cts_ptr >= posptr)) {
- // character at pos->col
+ StrCharInfo const next = utfc_next(ci);
+ if (next.ptr - line > end_col) {
break;
}
-
- cts.cts_vcol += incr;
- MB_PTR_ADV(cts.cts_ptr);
+ ci = next;
+ vcol += char_size.width;
}
- vcol = cts.cts_vcol;
- ptr = cts.cts_ptr;
}
- clear_chartabsize_arg(&cts);
+
+ int head = char_size.head;
+ int incr = char_size.width;
if (start != NULL) {
*start = vcol + head;
@@ -598,7 +537,7 @@ void getvcol(win_T *wp, pos_T *pos, colnr_T *start, colnr_T *cursor, colnr_T *en
}
if (cursor != NULL) {
- if ((*ptr == TAB)
+ if (ci.chr.value == TAB
&& (State & MODE_NORMAL)
&& !wp->w_p_list
&& !virtual_active()
@@ -606,7 +545,7 @@ 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 {
- vcol += virt_text_cursor_off(&cts, on_NUL);
+ vcol += virt_text_cursor_off(&csarg, on_NUL);
// cursor at start
*cursor = vcol + head;
}
@@ -730,7 +669,8 @@ void getvcols(win_T *wp, pos_T *pos1, pos_T *pos2, colnr_T *left, colnr_T *right
/// Check if there may be filler lines anywhere in window "wp".
bool win_may_fill(win_T *wp)
{
- return (wp->w_p_diff && diffopt_filler()) || wp->w_buffer->b_virt_line_blocks;
+ return ((wp->w_p_diff && diffopt_filler())
+ || buf_meta_total(wp->w_buffer, kMTMetaLines));
}
/// Return the number of filler lines above "lnum".
@@ -795,14 +735,18 @@ int plines_win_nofill(win_T *wp, linenr_T lnum, bool limit_winheight)
int plines_win_nofold(win_T *wp, linenr_T lnum)
{
char *s = ml_get_buf(wp->w_buffer, lnum);
- chartabsize_T cts;
- init_chartabsize_arg(&cts, wp, lnum, 0, s, s);
- if (*s == NUL && !cts.cts_has_virt_text) {
+ CharsizeArg csarg;
+ CSType const cstype = init_charsize_arg(&csarg, wp, lnum, s);
+ if (*s == NUL && csarg.virt_row < 0) {
return 1; // be quick for an empty line
}
- win_linetabsize_cts(&cts, (colnr_T)MAXCOL);
- clear_chartabsize_arg(&cts);
- int64_t col = cts.cts_vcol;
+
+ int64_t col;
+ if (cstype == kCharsizeFast) {
+ col = linesize_fast(&csarg, 0, MAXCOL);
+ } else {
+ col = linesize_regular(&csarg, 0, MAXCOL);
+ }
// If list mode is on, then the '$' at the end of the line may take up one
// extra column.
@@ -841,26 +785,33 @@ int plines_win_col(win_T *wp, linenr_T lnum, long column)
char *line = ml_get_buf(wp->w_buffer, lnum);
- colnr_T col = 0;
- chartabsize_T cts;
+ CharsizeArg csarg;
+ CSType const cstype = init_charsize_arg(&csarg, wp, lnum, line);
- init_chartabsize_arg(&cts, wp, lnum, 0, line, line);
- while (*cts.cts_ptr != NUL && --column >= 0) {
- cts.cts_vcol += win_lbr_chartabsize(&cts, NULL);
- MB_PTR_ADV(cts.cts_ptr);
+ colnr_T vcol = 0;
+ StrCharInfo ci = utf_ptr2StrCharInfo(line);
+ if (cstype == kCharsizeFast) {
+ bool const use_tabstop = csarg.use_tabstop;
+ while (*ci.ptr != NUL && --column >= 0) {
+ vcol += charsize_fast_impl(wp, use_tabstop, vcol, ci.chr.value).width;
+ ci = utfc_next(ci);
+ }
+ } else {
+ while (*ci.ptr != NUL && --column >= 0) {
+ vcol += charsize_regular(&csarg, ci.ptr, vcol, ci.chr.value).width;
+ ci = utfc_next(ci);
+ }
}
- // If *cts.cts_ptr is a TAB, and the TAB is not displayed as ^I, and we're not
+ // If current char is a TAB, and the TAB is not displayed as ^I, and we're not
// in MODE_INSERT state, then col must be adjusted so that it represents the
// last screen position of the TAB. This only fixes an error when the TAB
// wraps from one screen line to the next (when 'columns' is not a multiple
// of 'ts') -- webb.
- col = cts.cts_vcol;
- if (*cts.cts_ptr == TAB && (State & MODE_NORMAL)
- && (!wp->w_p_list || wp->w_p_lcs_chars.tab1)) {
- col += win_lbr_chartabsize(&cts, NULL) - 1;
+ colnr_T col = vcol;
+ if (ci.chr.value == TAB && (State & MODE_NORMAL) && csarg.use_tabstop) {
+ col += win_charsize(cstype, col, ci.ptr, ci.chr.value, &csarg).width - 1;
}
- clear_chartabsize_arg(&cts);
// Add column offset for 'number', 'relativenumber', 'foldcolumn', etc.
int width = wp->w_width_inner - win_col_off(wp);
diff --git a/src/nvim/plines.h b/src/nvim/plines.h
index 6aede88c8b..658206e1be 100644
--- a/src/nvim/plines.h
+++ b/src/nvim/plines.h
@@ -3,26 +3,97 @@
#include <stdbool.h>
#include <stdint.h>
-#include "nvim/buffer_defs.h"
-#include "nvim/marktree.h"
-#include "nvim/pos_defs.h" // IWYU pragma: keep
+#include "nvim/func_attr.h"
+#include "nvim/marktree_defs.h"
+#include "nvim/pos_defs.h"
+#include "nvim/types_defs.h"
-/// Argument for lbr_chartabsize().
+typedef bool CSType;
+
+enum {
+ kCharsizeRegular,
+ kCharsizeFast,
+};
+
+/// Argument for char size functions.
typedef struct {
- win_T *cts_win;
- char *cts_line; ///< start of the line
- char *cts_ptr; ///< current position in line
- int cts_row;
+ win_T *win;
+ char *line; ///< Start of the line.
+
+ bool use_tabstop; ///< Use 'tabstop' instead of char2cells() for a TAB.
+ int indent_width; ///< Width of 'showbreak' and 'breakindent' on wrapped
+ ///< parts of lines, INT_MIN if not yet calculated.
- bool cts_has_virt_text; ///< true if if there is inline virtual 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 virt_row; ///< Row for virtual text, -1 if no virtual text.
+ int cur_text_width_left; ///< Width of virtual text left of cursor.
+ int cur_text_width_right; ///< Width of virtual text right of cursor.
- int cts_vcol; ///< virtual column at current position
- int cts_max_head_vcol; ///< see win_lbr_chartabsize()
-} chartabsize_T;
+ int max_head_vcol; ///< See charsize_regular().
+ MarkTreeIter iter[1];
+} CharsizeArg;
+
+typedef struct {
+ int width;
+ int head; ///< Size of 'breakindent' etc. before the character (included in width).
+} CharSize;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "plines.h.generated.h"
#endif
+
+static inline CharSize win_charsize(CSType cstype, int vcol, char *ptr, int32_t chr,
+ CharsizeArg *csarg)
+ REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE;
+
+/// Get the number of cells taken up on the screen by the given character at vcol.
+/// "csarg->cur_text_width_left" and "csarg->cur_text_width_right" are set
+/// to the extra size for inline virtual text.
+///
+/// When "csarg->max_head_vcol" is positive, only count in "head" the size
+/// of 'showbreak'/'breakindent' before "csarg->max_head_vcol".
+/// When "csarg->max_head_vcol" is negative, only count in "head" the size
+/// of 'showbreak'/'breakindent' before where cursor should be placed.
+static inline CharSize win_charsize(CSType cstype, int vcol, char *ptr, int32_t chr,
+ CharsizeArg *csarg)
+{
+ if (cstype == kCharsizeFast) {
+ return charsize_fast(csarg, vcol, chr);
+ } else {
+ return charsize_regular(csarg, ptr, vcol, chr);
+ }
+}
+
+static inline int linetabsize_str(char *s)
+ REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE;
+
+/// Return the number of cells the string "s" will take on the screen,
+/// taking into account the size of a tab.
+///
+/// @param s
+///
+/// @return Number of cells the string will take on the screen.
+static inline int linetabsize_str(char *s)
+{
+ return linetabsize_col(0, s);
+}
+
+static inline int win_linetabsize(win_T *wp, linenr_T lnum, char *line, colnr_T len)
+ REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_ALWAYS_INLINE;
+
+/// Like linetabsize_str(), but for a given window instead of the current one.
+///
+/// @param wp
+/// @param line
+/// @param len
+///
+/// @return Number of cells the string will take on the screen.
+static inline int win_linetabsize(win_T *wp, linenr_T lnum, char *line, colnr_T len)
+{
+ CharsizeArg csarg;
+ CSType const cstype = init_charsize_arg(&csarg, wp, lnum, line);
+ if (cstype == kCharsizeFast) {
+ return linesize_fast(&csarg, 0, len);
+ } else {
+ return linesize_regular(&csarg, 0, len);
+ }
+}
diff --git a/src/nvim/po/CMakeLists.txt b/src/nvim/po/CMakeLists.txt
index 68e572911c..6c2008926a 100644
--- a/src/nvim/po/CMakeLists.txt
+++ b/src/nvim/po/CMakeLists.txt
@@ -53,16 +53,16 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG)
list(SORT NVIM_RELATIVE_SOURCES)
add_custom_command(
OUTPUT ${NVIM_POT}
- COMMAND $<TARGET_FILE:nvim> -u NONE -i NONE -n --headless --cmd "set cpo+=+"
+ COMMAND $<TARGET_FILE:nvim_bin> -u NONE -i NONE -n --headless --cmd "set cpo+=+"
-S ${CMAKE_CURRENT_SOURCE_DIR}/tojavascript.vim ${NVIM_POT} ${PROJECT_SOURCE_DIR}/runtime/optwin.vim
COMMAND ${XGETTEXT_PRG} -o ${NVIM_POT} --default-domain=nvim
--add-comments --keyword=_ --keyword=N_ --keyword=NGETTEXT:1,2
-D ${CMAKE_CURRENT_SOURCE_DIR} -D ${CMAKE_CURRENT_BINARY_DIR}
${NVIM_RELATIVE_SOURCES} optwin.js
- COMMAND $<TARGET_FILE:nvim> -u NONE -i NONE -n --headless --cmd "set cpo+=+"
+ COMMAND $<TARGET_FILE:nvim_bin> -u NONE -i NONE -n --headless --cmd "set cpo+=+"
-S ${CMAKE_CURRENT_SOURCE_DIR}/fixfilenames.vim ${NVIM_POT} ../../../runtime/optwin.vim
VERBATIM
- DEPENDS ${NVIM_SOURCES} nvim nvim_runtime_deps)
+ DEPENDS ${NVIM_SOURCES} nvim_bin nvim_runtime_deps)
set(LANGUAGE_MO_FILES)
set(UPDATE_PO_TARGETS)
@@ -88,7 +88,7 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG)
set(poFile ${CMAKE_CURRENT_SOURCE_DIR}/${name}.po)
add_custom_target(check-po-${name}
- COMMAND $<TARGET_FILE:nvim> -u NONE -n -e
+ COMMAND $<TARGET_FILE:nvim_bin> -u NONE -n -e
-S ${CMAKE_CURRENT_SOURCE_DIR}/check.vim
-c "if error == 0 | q | endif" -c cq ${poFile} ||
${CMAKE_COMMAND} -E echo "${name}.po failed the check."
@@ -182,6 +182,7 @@ if(HAVE_WORKING_LIBINTL AND GETTEXT_FOUND AND XGETTEXT_PRG AND ICONV_PRG)
BuildMo(${LANGUAGE})
endforeach()
- add_custom_target(translations ALL DEPENDS ${LANGUAGE_MO_FILES})
+ add_custom_target(nvim_translations DEPENDS ${LANGUAGE_MO_FILES})
add_custom_target(update-po DEPENDS ${UPDATE_PO_TARGETS})
+ add_dependencies(nvim nvim_translations)
endif()
diff --git a/src/nvim/po/uk.po b/src/nvim/po/uk.po
index 83898cda12..abc77071c4 100644
--- a/src/nvim/po/uk.po
+++ b/src/nvim/po/uk.po
@@ -14,8 +14,8 @@ msgid ""
msgstr ""
"Project-Id-Version: Neovim Ukrainian\n"
"Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2023-08-26 20:36+0300\n"
-"PO-Revision-Date: 2023-08-26 21:00+0300\n"
+"POT-Creation-Date: 2023-12-31 12:04+0200\n"
+"PO-Revision-Date: 2023-12-31 12:35+0200\n"
"Last-Translator: Ðнатолій Сахнік <sakhnik@gmail.com>\n"
"Language-Team: Ukrainian\n"
"Language: uk\n"
@@ -1434,6 +1434,9 @@ msgstr " [Змінено]"
msgid "[Not edited]"
msgstr "[Ðе редаговано]"
+msgid "[New]"
+msgstr "[Ðовий]"
+
msgid "[Read errors]"
msgstr "[Помилки читаннÑ]"
@@ -1481,14 +1484,6 @@ msgstr " (%d з %d)"
msgid " ((%d) of %d)"
msgstr " ((%d) з %d)"
-#, c-format
-msgid " (file %d of %d)"
-msgstr " (файл %d з %d)"
-
-#, c-format
-msgid " (file (%d) of %d)"
-msgstr " (файл (%d) з %d)"
-
msgid "E382: Cannot write, 'buftype' option is set"
msgstr "E382: Ðе можу запиÑати, вказана Ð¾Ð¿Ñ†Ñ–Ñ 'buftype'"
@@ -1584,6 +1579,9 @@ msgstr "[конвертовано]"
msgid "[Device]"
msgstr "[ПриÑтрій]"
+msgid "[noeol]"
+msgstr "[noeol]"
+
msgid " [a]"
msgstr "[д]"
@@ -1636,9 +1634,6 @@ msgstr " тип файлу\n"
msgid "'history' option is zero"
msgstr "ÐžÐ¿Ñ†Ñ–Ñ 'history' порожнÑ"
-msgid "E474: Failed to convert list to msgpack string buffer"
-msgstr "E474: Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€Ð¸Ñ‚Ð¸ ÑпиÑок у текÑтовий буфер msgpack"
-
msgid "E548: Digit expected"
msgstr "E548: ОчікуєтьÑÑ Ñ†Ð¸Ñ„Ñ€Ð°"
@@ -2062,16 +2057,6 @@ msgstr ""
"\n"
"\tВоÑтаннє змінена у "
-msgid "E5009: $VIMRUNTIME is empty or unset"
-msgstr "E5009: $VIMRUNTIME Ð¿Ð¾Ñ€Ð¾Ð¶Ð½Ñ Ñ‡Ð¸ не вÑтановлена"
-
-#, c-format
-msgid "E5009: Invalid $VIMRUNTIME: %s"
-msgstr "E5009: Ðекоректна $VIMRUNTIME: %s"
-
-msgid "E5009: Invalid 'runtimepath'"
-msgstr "E5009: Ðекоректний 'runtimepath'"
-
msgid "E977: Can only compare Blob with Blob"
msgstr "E977: Blob можна порівнÑти тільки з Blob"
@@ -2366,10 +2351,6 @@ msgstr "E998: Ð¡ÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð¿Ð¾Ñ€Ð¾Ð¶Ð½ÑŒÐ¾Ð³Ð¾ %s без початко
msgid "E1132: Missing function argument"
msgstr "E1132: Бракує аргументу функції"
-#, c-format
-msgid "Error converting the call result: %s"
-msgstr "Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€Ð¸Ñ‚Ð¸ результат виклику: %s"
-
msgid "add() argument"
msgstr "аргумент add()"
@@ -2839,8 +2820,8 @@ msgid "E940: Cannot lock or unlock variable %s"
msgstr "E940: Ðеможливо заблокувати чи розблокувати змінну %s"
#, c-format
-msgid "E963: Setting %s to value with wrong type"
-msgstr "E963: Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð· неправильним типом у %s"
+msgid "E963: Setting v:%s to value with wrong type"
+msgstr "E963: Ð’ÑÑ‚Ð°Ð½Ð¾Ð²Ð»ÐµÐ½Ð½Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ v:%s з неправильним типом"
msgid "E991: Cannot use =<< here"
msgstr "E991: Тут не можна заÑтоÑувати =<<"
@@ -3249,6 +3230,16 @@ msgstr "E500: Результат — порожній Ñ€Ñдок"
msgid "Untitled"
msgstr "Ðеназваний"
+msgid "E5009: $VIMRUNTIME is empty or unset"
+msgstr "E5009: $VIMRUNTIME Ð¿Ð¾Ñ€Ð¾Ð¶Ð½Ñ Ñ‡Ð¸ не вÑтановлена"
+
+#, c-format
+msgid "E5009: Invalid $VIMRUNTIME: %s"
+msgstr "E5009: Ðекоректна $VIMRUNTIME: %s"
+
+msgid "E5009: Invalid 'runtimepath'"
+msgstr "E5009: Ðекоректний 'runtimepath'"
+
msgid "E583: Multiple :else"
msgstr "E583: Ðе одне :else"
@@ -3476,27 +3467,12 @@ msgstr "ÐšÐ¾Ð½Ð²ÐµÑ€Ñ‚Ð°Ñ†Ñ–Ñ Ð· 'charconvert' не вдалаÑÑ"
msgid "can't read output of 'charconvert'"
msgstr "не вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ вивід 'charconvert'"
-msgid "[New File]"
-msgstr "[Ðовий файл]"
-
-msgid "[New]"
-msgstr "[Ðовий]"
-
-msgid "[dos format]"
-msgstr "[формат dos]"
-
msgid "[dos]"
msgstr "[dos]"
-msgid "[mac format]"
-msgstr "[формат mac]"
-
msgid "[mac]"
msgstr "[mac]"
-msgid "[unix format]"
-msgstr "[формат unix]"
-
msgid "[unix]"
msgstr "[unix]"
@@ -3514,12 +3490,6 @@ msgstr[0] "%<PRId64> байт"
msgstr[1] "%<PRId64> байти"
msgstr[2] "%<PRId64> байтів"
-msgid "[Incomplete last line]"
-msgstr "[Ðеповний оÑтанній Ñ€Ñдок]"
-
-msgid "[noeol]"
-msgstr "[noeol]"
-
#, c-format
msgid "E208: Error writing to \"%s\""
msgstr "E208: Помилка запиÑу у «%s»"
@@ -3602,18 +3572,18 @@ msgid "E351: Cannot delete fold with current 'foldmethod'"
msgstr "E351: Ðе вдалоÑÑ Ð·Ð½Ð¸Ñ‰Ð¸Ñ‚Ð¸ згортку методом 'foldmethod'"
#, c-format
-msgid "+--%3ld line folded"
-msgid_plural "+--%3ld lines folded "
-msgstr[0] "+--%3ld Ñ€Ñдок згорнуто "
+msgid "+--%3d line folded"
+msgid_plural "+--%3d lines folded "
+msgstr[0] "+--%3ld Ñ€Ñдок згорнуто"
msgstr[1] "+--%3ld Ñ€Ñдки згорнуто "
msgstr[2] "+--%3ld Ñ€Ñдків згорнуто "
#, c-format
-msgid "+-%s%3ld line: "
-msgid_plural "+-%s%3ld lines: "
-msgstr[0] "+-%s%3ld Ñ€Ñдок: "
-msgstr[1] "+-%s%3ld Ñ€Ñдки: "
-msgstr[2] "+-%s%3ld Ñ€Ñдків: "
+msgid "+-%s%3d line: "
+msgid_plural "+-%s%3d lines: "
+msgstr[0] "+-%s%3-о Ñ€Ñдок: "
+msgstr[1] "+-%s%3-о Ñ€Ñдки: "
+msgstr[2] "+-%s%3-о Ñ€Ñдків: "
msgid "E223: Recursive mapping"
msgstr "E223: Заміна клавіш рекурÑивна"
@@ -3925,6 +3895,10 @@ msgstr "E119: Замало аргументів Ð´Ð»Ñ Ñ„ÑƒÐ½ÐºÑ†Ñ–Ñ— %s"
msgid "E716: Key not present in Dictionary: \"%s\""
msgstr "E716: Ðемає такого ключа у Ñловнику: «%s»"
+#, c-format
+msgid "E716: Key not present in Dictionary: \"%.*s\""
+msgstr "E716: Ðемає такого ключа у Ñловнику: «%.*s»"
+
msgid "E714: List required"
msgstr "E714: Потрібен List"
@@ -4112,6 +4086,10 @@ msgstr "E1278: Заблудла '}' без відповідної '{': %s"
msgid "E1279: Missing '}': %s"
msgstr "E1279: Пропущено '}': %s"
+#, c-format
+msgid "E1510: Value too large: %s"
+msgstr "E1510: Величина завелика: %s"
+
msgid "E5767: Cannot use :undo! to redo or move to a different undo branch"
msgstr ""
"E5767: Ðеможливо заÑтоÑувати :undo! щоб повторити або перейти до іншої гілки "
@@ -4345,11 +4323,11 @@ msgid "E1502: Lua failed to grow stack to %i"
msgstr "E1502: Lua не вдалоÑÑ Ð·Ð±Ñ–Ð»ÑŒÑˆÐ¸Ñ‚Ð¸ Ñтек до %i"
msgid ""
-"E5100: Cannot convert given lua table: table should either have a sequence "
-"of positive integer keys or contain only string keys"
+"E5100: Cannot convert given lua table: table should contain either only "
+"integer keys or only string keys"
msgstr ""
-"E5100: Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€Ð¸Ñ‚Ð¸ таблицю lua: Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Ð¿Ð¾Ð²Ð¸Ð½Ð½Ð° мати "
-"поÑлідовніÑть додатних чиÑел Ñк ключі або текÑтові ключі"
+"E5100: Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€Ð¸Ñ‚Ð¸ таблицю lua: Ñ‚Ð°Ð±Ð»Ð¸Ñ†Ñ Ð¿Ð¾Ð²Ð¸Ð½Ð½Ð° мати або тільки "
+"цілочиÑельні ключі або тільки текÑтові ключі"
msgid "E5101: Cannot convert given lua type"
msgstr "E5101: Ðе вдалоÑÑ Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€Ð¸Ñ‚Ð¸ тип lua"
@@ -4362,9 +4340,11 @@ msgstr "E5102: Lua не вдалоÑÑ Ð·Ð±Ñ–Ð»ÑŒÑˆÐ¸Ñ‚Ð¸ Ñтек до %i"
msgid "Error executing vim.schedule lua callback: %.*s"
msgstr "Помилка Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ Ð¾Ð±Ñ€Ð¾Ð±Ð½Ð¸ÐºÐ° lua vim.schedule: %.*s"
+#, c-format
msgid "E970: Failed to initialize lua interpreter\n"
msgstr "E970: Ðе вдалоÑÑ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ інтерпретатор lua\n"
+#, c-format
msgid "E970: Failed to initialize builtin lua modules\n"
msgstr "E970: Ðе вдалоÑÑ Ñ–Ð½Ñ–Ñ†Ñ–Ð°Ð»Ñ–Ð·ÑƒÐ²Ð°Ñ‚Ð¸ інтерпретатор lua\n"
@@ -4469,6 +4449,7 @@ msgstr "--embed конфліктує з -es/-Es/-l"
msgid "Cannot open for reading: \"%s\": %s\n"
msgstr "Ðе вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ: \"%s\": %s\n"
+#, c-format
msgid "Cannot open for script output: \""
msgstr "Ðе вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ Ñк вихідний файл: \""
@@ -4483,6 +4464,7 @@ msgstr "E5422: Суперечливі конфігурації: «%s» «%s»"
msgid "E282: Cannot read from \"%s\""
msgstr "E282: Ðе вдалоÑÑ Ð¿Ñ€Ð¾Ñ‡Ð¸Ñ‚Ð°Ñ‚Ð¸ з «%s»"
+#, c-format
msgid ""
"\n"
"More info with \""
@@ -4490,12 +4472,15 @@ msgstr ""
"\n"
"ДізнайтеÑÑ Ð±Ñ–Ð»ÑŒÑˆÐµ: \""
+#, c-format
msgid "Usage:\n"
msgstr "Вжиток:\n"
+#, c-format
msgid " nvim [options] [file ...]\n"
msgstr " nvim [опції] [файл ...]\n"
+#, c-format
msgid ""
"\n"
"Options:\n"
@@ -4503,75 +4488,95 @@ msgstr ""
"\n"
"Опції:\n"
+#, c-format
msgid " --cmd <cmd> Execute <cmd> before any config\n"
msgstr ""
" --cmd <команда> Виконати <команду> перед будь-Ñкою конфігурацією\n"
+#, c-format
msgid " +<cmd>, -c <cmd> Execute <cmd> after config and first file\n"
msgstr ""
" +<cmd>, -c <команда> Виконати <команду> піÑÐ»Ñ Ð·Ð°Ð²Ð°Ð½Ñ‚Ð°Ð¶ÐµÐ½Ð½Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ файлу\n"
+#, c-format
msgid " -l <script> [args...] Execute Lua <script> (with optional args)\n"
msgstr " -l <Ñкрипт> [args...] Виконати <Ñкрипт> Lua (з арг-тами, Ñкщо Ñ”)\n"
+#, c-format
msgid " -S <session> Source <session> after loading the first file\n"
msgstr ""
" -S <ÑеанÑ> Виконати <ÑеанÑ> піÑÐ»Ñ Ð¿ÐµÑ€ÑˆÐ¾Ð³Ð¾ завантаженого файлу\n"
+#, c-format
msgid " -s <scriptin> Read Normal mode commands from <scriptin>\n"
msgstr ""
" -s <Ñкрипт> Зчитати команди нормального режиму з файлу <Ñкрипт>\n"
+#, c-format
msgid " -u <config> Use this config file\n"
msgstr " -u <config> Вжити цей файл конфігурації\n"
+#, c-format
msgid " -d Diff mode\n"
msgstr " -d Режим порівнÑннÑ\n"
+#, c-format
msgid " -es, -Es Silent (batch) mode\n"
msgstr " -es, -Es Мовчазний (пакетний) режим\n"
+#, c-format
msgid " -h, --help Print this help message\n"
msgstr " -h, --help Ðадрукувати це повідомленнÑ\n"
+#, c-format
msgid " -i <shada> Use this shada file\n"
msgstr " -i <shada> Вжити цей файл shada\n"
+#, c-format
msgid " -n No swap file, use memory only\n"
msgstr ""
" -n Ðе викориÑтовувати файл обміну, тримати уÑе в "
"пам'Ñті\n"
+#, c-format
msgid " -o[N] Open N windows (default: one per file)\n"
msgstr " -o[N] Відкрити N вікон (Ñтандартно: одне на файл)\n"
+#, c-format
msgid ""
" -O[N] Open N vertical windows (default: one per file)\n"
msgstr ""
" -o[N] Відкрити N вертикальних вікон (Ñтандартно: одне на "
"файл)\n"
+#, c-format
msgid " -p[N] Open N tab pages (default: one per file)\n"
msgstr ""
" -p[N] Відкрити N вкладок (Ñтандартно: одна на файл)\n"
+#, c-format
msgid " -R Read-only (view) mode\n"
msgstr " -R Режим тільки Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ\n"
+#, c-format
msgid " -v, --version Print version information\n"
msgstr " -v, --version Ðадрукувати інформацію про верÑÑ–ÑŽ програми\n"
+#, c-format
msgid " -V[N][file] Verbose [level][file]\n"
msgstr " -V[N][файл] Більше повідомлень [рівень][файл]\n"
+#, c-format
msgid " -- Only file names after this\n"
msgstr " -- Лише назви файлів піÑÐ»Ñ Ñ†ÑŒÐ¾Ð³Ð¾\n"
+#, c-format
msgid " --api-info Write msgpack-encoded API metadata to stdout\n"
msgstr ""
" --api-info ЗапиÑати метадані API, Ñеріалізовані у msgpack, у "
"stdout\n"
+#, c-format
msgid ""
" --clean \"Factory defaults\" (skip user config and plugins, "
"shada)\n"
@@ -4579,25 +4584,32 @@ msgstr ""
" --clean «з нулÑ» (пропуÑтити конфігурацію кориÑтувача Ñ– "
"плагіни, shada)\n"
+#, c-format
msgid " --embed Use stdin/stdout as a msgpack-rpc channel\n"
msgstr ""
" --embed ВикориÑтати stdin/stdout, Ñк канал msgpack-rpc\n"
+#, c-format
msgid " --headless Don't start a user interface\n"
msgstr " --headless Ðе запуÑкати Ñ–Ð½Ñ‚ÐµÑ€Ñ„ÐµÐ¹Ñ ÐºÐ¾Ñ€Ð¸Ñтувача\n"
+#, c-format
msgid " --listen <address> Serve RPC API from this address\n"
msgstr " --listen <адреÑа> ОбÑлуговувати RPC API за цією адреÑою\n"
+#, c-format
msgid " --remote[-subcommand] Execute commands remotely on a server\n"
msgstr " --remote[-subcommand] Виконати команди на віддаленому Ñервері\n"
+#, c-format
msgid " --server <address> Specify RPC server to send commands to\n"
msgstr " --server <адреÑа> Задати Ñервер RPC, куди Ñлати команди\n"
+#, c-format
msgid " --startuptime <file> Write startup timing messages to <file>\n"
msgstr " --startuptime <файл> ЗапиÑати профіль запуÑку до <файлу>\n"
+#, c-format
msgid ""
"\n"
"See \":help startup-options\" for all options.\n"
@@ -4624,6 +4636,10 @@ msgstr "E227: Вже Ñ” заміна клавіш Ð´Ð»Ñ %s"
msgid "E460: Entries missing in mapset() dict argument"
msgstr "E460: Бракує запиÑів у Ñловниковому аргументі mapset()"
+#, c-format
+msgid "E1276: Illegal map mode string: '%s'"
+msgstr "E1276: Ðедозволений режим заміни клавіш: '%s'"
+
msgid "No abbreviation found"
msgstr "Ð¡ÐºÐ¾Ñ€Ð¾Ñ‡ÐµÐ½Ð½Ñ Ð½Ðµ знайдено"
@@ -5217,9 +5233,8 @@ msgstr "E337: Меню не знайдено — перевірте назви Ð
msgid "Error detected while processing %s:"
msgstr "ВиÑвлено помилку під Ñ‡Ð°Ñ Ð²Ð¸ÐºÐ¾Ð½Ð°Ð½Ð½Ñ %s:"
-#, c-format
-msgid "line %4ld:"
-msgstr "Ñ€Ñдок %4ld:"
+msgid "line %4"
+msgstr "Ñ€Ñдок %4"
#, c-format
msgid "E354: Invalid register name: '%s'"
@@ -5232,18 +5247,18 @@ msgid "Press ENTER or type command to continue"
msgstr "ÐатиÑніть ENTER або введіть команду Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ"
#, c-format
-msgid "%ld more line"
-msgid_plural "%ld more lines"
-msgstr[0] "ще %ld Ñ€Ñдок"
-msgstr[1] "ще %ld Ñ€Ñдки"
-msgstr[2] "ще %ld Ñ€Ñдків"
+msgid "%d more line"
+msgid_plural "%d more lines"
+msgstr[0] "ще %d Ñ€Ñдок"
+msgstr[1] "ще %d Ñ€Ñдки"
+msgstr[2] "ще %d Ñ€Ñдків"
#, c-format
-msgid "%ld line less"
-msgid_plural "%ld fewer lines"
-msgstr[0] "на %ld Ñ€Ñдок менше"
-msgstr[1] "на %ld Ñ€Ñдки менше"
-msgstr[2] "на %ld Ñ€Ñдків менше"
+msgid "%d line less"
+msgid_plural "%d fewer lines"
+msgstr[0] "на %d Ñ€Ñдок менше"
+msgstr[1] "на %d Ñ€Ñдки менше"
+msgstr[2] "на %d Ñ€Ñдків менше"
msgid " (Interrupted)"
msgstr " (Перервано)"
@@ -5447,9 +5462,6 @@ msgstr "E520: Ðе дозволено у modeline"
msgid "E992: Not allowed in a modeline when 'modelineexpr' is off"
msgstr "E992: Ðе дозволено у modeline, коли 'modelineexpr' вимкнено"
-msgid "E846: Key code not set"
-msgstr "E846: Код ключа не вÑтановлено"
-
msgid "E521: Number required after ="
msgstr "E521: ПіÑÐ»Ñ = потрібно вказати чиÑло"
@@ -5468,6 +5480,9 @@ msgstr "E593: Потрібно щонайменше %d Ñ€Ñдків"
msgid "E594: Need at least %d columns"
msgstr "E594: Потрібно щонайменше %d Ñтовпців"
+msgid "Cannot unset global option value"
+msgstr "Ðеможливо прибрати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð³Ð»Ð¾Ð±Ð°Ð»ÑŒÐ½Ð¾Ñ— опції"
+
#, c-format
msgid "Invalid value for option '%s': expected %s, got %s %s"
msgstr "Ðекоректне Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð¾Ð¿Ñ†Ñ–Ñ— '%s': очікуєтьÑÑ %s, отримано %s %s"
@@ -5511,20 +5526,10 @@ msgstr "E589: Опції 'backupext' і 'patchmode' однакові"
msgid "E595: 'showbreak' contains unprintable or wide character"
msgstr "E595: 'showbreak' міÑтить недруковні або розширені Ñимволи"
-msgid "E1336: Internal error: shortmess too long"
-msgstr "E1336: Ð’Ð½ÑƒÑ‚Ñ€Ñ–ÑˆÐ½Ñ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ°: занадто довгий shortmess"
-
#, c-format
msgid "E539: Illegal character <%s>"
msgstr "E539: Ðедозволений Ñимвол <%s>"
-#, c-format
-msgid "For option %s"
-msgstr "Ð”Ð»Ñ Ð¾Ð¿Ñ†Ñ–Ñ— %s"
-
-msgid "E5080: Digit expected"
-msgstr "E5080: ОчікуєтьÑÑ Ñ†Ð¸Ñ„Ñ€Ð°"
-
msgid "E524: Missing colon"
msgstr "E524: Бракує двокрапки"
@@ -5532,6 +5537,17 @@ msgid "E525: Zero length string"
msgstr "E525: РÑдок порожній"
#, c-format
+msgid "E537: 'commentstring' must be empty or contain %s"
+msgstr "E537: 'commentstring' має бути порожньою чи міÑтити %s"
+
+#, c-format
+msgid "E535: Illegal character after <%c>"
+msgstr "E535: Ðедозволений Ñимвол піÑÐ»Ñ <%c>"
+
+msgid "E5080: Digit expected"
+msgstr "E5080: ОчікуєтьÑÑ Ñ†Ð¸Ñ„Ñ€Ð°"
+
+#, c-format
msgid "E526: Missing number after <%s>"
msgstr "E526: ПіÑÐ»Ñ <%s> бракує чиÑла"
@@ -5541,14 +5557,6 @@ msgstr "E527: Бракує коми"
msgid "E528: Must specify a ' value"
msgstr "E528: Потрібно вказати Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ '"
-#, c-format
-msgid "E535: Illegal character after <%c>"
-msgstr "E535: Ðедозволений Ñимвол піÑÐ»Ñ <%c>"
-
-#, c-format
-msgid "E537: 'commentstring' must be empty or contain %s"
-msgstr "E537: 'commentstring' має бути порожньою чи міÑтити %s"
-
msgid "E834: Conflicts with value of 'listchars'"
msgstr "E834: Конфліктує із значеннÑм 'listchars'"
@@ -5563,6 +5571,19 @@ msgstr "dlerror = «%s»"
msgid "E5420: Failed to write to file: %s"
msgstr "E5420: Ðе вдалоÑÑ Ð·Ð°Ð¿Ð¸Ñати у файл: %s"
+msgid "E1506: Buffer too small to copy xattr value or key"
+msgstr "E1506: Буфер замалий Ð´Ð»Ñ ÐºÐ¾Ð¿Ñ–ÑŽÐ²Ð°Ð½Ð½Ñ Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ñ‡Ð¸ ключа xattr"
+
+msgid ""
+"E1508: Size of the extended attribute value is larger than the maximum size "
+"allowed"
+msgstr ""
+"E1508: Розмір величини розширеного атрибуту більший, ніж макÑимально "
+"дозволений розмір"
+
+msgid "E1509: Error occurred when reading or writing extended attribute"
+msgstr "E1509: СталаÑÑ Ð¿Ð¾Ð¼Ð¸Ð»ÐºÐ° при читанні чи запиÑÑ– розширеного атрибуту"
+
msgid "Vim: Error reading input, exiting...\n"
msgstr "Vim: Помилка Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ Ð²Ð²Ð¾Ð´Ñƒ, робота завершуєтьÑÑ...\n"
@@ -5764,6 +5785,110 @@ msgstr "E554: СинтакÑична помилка в %s{...}"
msgid "E888: (NFA regexp) cannot repeat %s"
msgstr "E888: (NFA regexp) неможливо повторити %s"
+msgid "E65: Illegal back reference"
+msgstr "E65: Ðекоректне зворотне поÑиланнÑ"
+
+#, c-format
+msgid "E64: %s%c follows nothing"
+msgstr "E64: %s%c має йти за чимоÑÑŒ"
+
+msgid "E68: Invalid character after \\z"
+msgstr "E68: Ðекоректний Ñимвол піÑÐ»Ñ \\z"
+
+#, c-format
+msgid "E678: Invalid character after %s%%[dxouU]"
+msgstr "E678: Ðекоректний Ñимвол піÑÐ»Ñ %s%%[dxouU]"
+
+#, c-format
+msgid "E71: Invalid character after %s%%"
+msgstr "E71: Ðекоректний Ñимвол піÑÐ»Ñ %s%%"
+
+#, c-format
+msgid "E60: Too many complex %s{...}s"
+msgstr "E60: Забагато Ñкладних %s{...}"
+
+#, c-format
+msgid "E61: Nested %s*"
+msgstr "E61: Вкладені %s*"
+
+#, c-format
+msgid "E62: Nested %s%c"
+msgstr "E62: Вкладені %s%c"
+
+msgid "E50: Too many \\z("
+msgstr "E50: Забагато \\z("
+
+#, c-format
+msgid "E51: Too many %s("
+msgstr "E51: Забагато %s("
+
+msgid "E52: Unmatched \\z("
+msgstr "E52: Ðемає пари \\z("
+
+msgid "E339: Pattern too long"
+msgstr "E339: Задовгий шаблон"
+
+#, c-format
+msgid "External submatches:\n"
+msgstr "Зовнішні збіги:\n"
+
+msgid "E865: (NFA) Regexp end encountered prematurely"
+msgstr "E865: (NFA) Обірваний регулÑрний вираз"
+
+#, c-format
+msgid "E866: (NFA regexp) Misplaced %c"
+msgstr "E866: (NFA regexp) Ðедоречний %c"
+
+#, c-format
+msgid "E877: (NFA regexp) Invalid character class: %<PRId64>"
+msgstr "E877: (NFA regexp) Ðекоректний ÐºÐ»Ð°Ñ Ñимволів: %<PRId64>"
+
+msgid "E951: \\% value too large"
+msgstr "E951: Величина \\% завелика"
+
+#, c-format
+msgid "E867: (NFA) Unknown operator '\\z%c'"
+msgstr "E867: (NFA) Ðевідомий оператор '\\z%c'"
+
+#, c-format
+msgid "E867: (NFA) Unknown operator '\\%%%c'"
+msgstr "E867: (NFA) Ðевідомий оператор '\\%%%c'"
+
+#, c-format
+msgid "E869: (NFA) Unknown operator '\\@%c'"
+msgstr "E869: (NFA) Ðевідомий оператор '\\@%c'"
+
+msgid "E870: (NFA regexp) Error reading repetition limits"
+msgstr "E870: (NFA regexp) Помилка меж повтореннÑ"
+
+msgid "E871: (NFA regexp) Can't have a multi follow a multi"
+msgstr "E871: (NFA regexp) Ðе можна мульти- за мульти-"
+
+msgid "E872: (NFA regexp) Too many '('"
+msgstr "E872: (NFA regexp) Забагато '('"
+
+msgid "E879: (NFA regexp) Too many \\z("
+msgstr "E879: (NFA regexp) Забагато \\z("
+
+msgid "E873: (NFA regexp) proper termination error"
+msgstr "E873: (NFA regexp) неправильне завершеннÑ"
+
+msgid "Could not open temporary log file for writing, displaying on stderr... "
+msgstr "Ðе вдалоÑÑ Ð²Ñ–Ð´ÐºÑ€Ð¸Ñ‚Ð¸ тимчаÑовий файл Ð´Ð»Ñ Ð·Ð°Ð¿Ð¸Ñу, показую в stderr…"
+
+msgid "E874: (NFA) Could not pop the stack!"
+msgstr "E874: (NFA) Ðе вдалоÑÑ Ð²Ð¸Ñ‚Ñгнути зі Ñтеку!"
+
+msgid ""
+"E875: (NFA regexp) (While converting from postfix to NFA),too many states "
+"left on stack"
+msgstr ""
+"E875: (NFA regexp) (При перетворенні з поÑÑ‚Ñ„Ñ–ÐºÑ Ñƒ NFA), забагато Ñтанів "
+"залишилоÑÑ Ñƒ Ñтеку"
+
+msgid "E876: (NFA regexp) Not enough space to store the whole NFA "
+msgstr "E876: (NFA regexp) ÐедоÑтатньо міÑÑ†Ñ Ð´Ð»Ñ Ð·Ð±ÐµÑ€ÐµÐ¶ÐµÐ½Ð½Ñ Ð²Ñього NFA "
+
msgid ""
"E864: \\%#= can only be followed by 0, 1, or 2. The automatic engine will be "
"used "
@@ -6117,9 +6242,6 @@ msgstr ""
"Помилка при читанні файлу ShaDa: ÑпиÑок буферів у позиції %<PRIu64> міÑтить "
"поле, Ñке не має назву файлу"
-msgid "[Deleted]"
-msgstr "[Знищено]"
-
msgid ""
"\n"
"--- Signs ---"
@@ -6132,15 +6254,15 @@ msgid "Signs for %s:"
msgstr "Позначки Ð´Ð»Ñ %s:"
#, c-format
-msgid " group=%s"
-msgstr " група=%s"
+msgid " name=%s"
+msgstr " назв=%s"
#, c-format
-msgid " line=%ld id=%d%s name=%s priority=%d"
-msgstr " Ñ€Ñдок=%ld id=%d%s назва=%s пріоритет=%d"
+msgid " group=%s"
+msgstr " група=%s"
-msgid "E612: Too many signs defined"
-msgstr "E612: Визначено забагато надпиÑів"
+msgid " line=%"
+msgstr " Ñ€Ñд.=%"
#, c-format
msgid "E239: Invalid sign text: %s"
@@ -6150,20 +6272,23 @@ msgstr "E239: Ðекоректний надпиÑ: %s"
msgid "E155: Unknown sign: %s"
msgstr "E155: Ðевідомий надпиÑ: %s"
+msgid " (not supported)"
+msgstr " (не підтримуєтьÑÑ)"
+
#, c-format
msgid "E885: Not possible to change sign %s"
msgstr "E885: Ðеможливо змінити знак %s"
-msgid "E159: Missing sign number"
-msgstr "E159: Пропущено номер надпиÑу"
-
#, c-format
-msgid "E157: Invalid sign ID: %<PRId64>"
-msgstr "E157: Ðеправильний ID надпиÑу: %<PRId64>"
+msgid "E157: Invalid sign ID: %<PRId32>"
+msgstr "E157: Ðеправильний ID надпиÑу: %<PRId32>"
msgid "E934: Cannot jump to a buffer that does not have a name"
msgstr "E934: Ðе можна перейти до буфера без назви"
+msgid "E159: Missing sign number"
+msgstr "E159: Пропущено номер надпиÑу"
+
#, c-format
msgid "E160: Unknown sign command: %s"
msgstr "E160: Ðевідома команда надпиÑу: %s"
@@ -6171,9 +6296,6 @@ msgstr "E160: Ðевідома команда надпиÑу: %s"
msgid "E156: Missing sign name"
msgstr "E156: Пропущено назву надпиÑу"
-msgid " (not supported)"
-msgstr " (не підтримуєтьÑÑ)"
-
msgid "E759: Format error in spell file"
msgstr "E759: Помилка формату у файлі орфографії"
@@ -6394,8 +6516,8 @@ msgid "E760: No word count in %s"
msgstr "E760: Ðемає кількоÑті Ñлів у %s"
#, c-format
-msgid "line %6d, word %6ld - %s"
-msgstr "Ñ€Ñдок %6d, Ñлово %6ld - %s"
+msgid "line %6d, word %6d - %s"
+msgstr "Ñ€Ñдок %6d, Ñлово %6d - %s"
#, c-format
msgid "Duplicate word in %s line %d: %s"
@@ -6417,45 +6539,37 @@ msgstr "Пропущено %d Ñлів(~) із не-ASCII Ñимволами у
msgid "Reading word file %s..."
msgstr "ЧитаєтьÑÑ Ñ„Ð°Ð¹Ð» Ñлів %s..."
-#, c-format
-msgid "Conversion failure for word in %s line %ld: %s"
-msgstr "Помилка Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñлова у %s у Ñ€Ñдку %ld: %s"
+msgid "Conversion failure for word in %s line %"
+msgstr "Помилка Ð¿ÐµÑ€ÐµÑ‚Ð²Ð¾Ñ€ÐµÐ½Ð½Ñ Ñлова у %s Ñ€Ñдок %"
-#, c-format
-msgid "Duplicate /encoding= line ignored in %s line %ld: %s"
-msgstr "ÐŸÐ¾Ð²Ñ‚Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ñдка /encoding= проігноровано у %s у Ñ€Ñдку %ld: %s"
+msgid "Duplicate /encoding= line ignored in %s line %"
+msgstr "ÐŸÐ¾Ð²Ñ‚Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ñдка /encoding= проігноровано у %s Ñ€Ñдок %"
-#, c-format
-msgid "/encoding= line after word ignored in %s line %ld: %s"
-msgstr "РÑдок /encoding= піÑÐ»Ñ Ñлова проігноровано у %s у Ñ€Ñдку %ld: %s"
+msgid "/encoding= line after word ignored in %s line %"
+msgstr "РÑдок /encoding= піÑÐ»Ñ Ñлова проігноровано у %s Ñ€Ñдок %"
-#, c-format
-msgid "Duplicate /regions= line ignored in %s line %ld: %s"
-msgstr "ÐŸÐ¾Ð²Ñ‚Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ñдка /regions= проігноровано у %s у Ñ€Ñдку %ld: %s"
+msgid "Duplicate /regions= line ignored in %s line %"
+msgstr "ÐŸÐ¾Ð²Ñ‚Ð¾Ñ€ÐµÐ½Ð½Ñ Ñ€Ñдка /regions= проігноровано у %s Ñ€Ñдок %"
-#, c-format
-msgid "Too many regions in %s line %ld: %s"
-msgstr "Забагато регіонів у %s у Ñ€Ñдку %ld: %s"
+msgid "Too many regions in %s line %"
+msgstr "Забагато регіонів у %s Ñ€Ñдок %"
-#, c-format
-msgid "/ line ignored in %s line %ld: %s"
-msgstr "РÑдок / проігноровано у %s у Ñ€Ñдку %ld: %s"
+msgid "/ line ignored in %s line %"
+msgstr "РÑдок / проігноровано у %s Ñ€Ñдок %"
-#, c-format
-msgid "Invalid region nr in %s line %ld: %s"
-msgstr "Ðекоректний номер регіону у %s у Ñ€Ñдку %ld: %s"
+msgid "Invalid region nr in %s line %"
+msgstr "Ðекоректний номер регіону у %s Ñ€Ñдок %"
-#, c-format
-msgid "Unrecognized flags in %s line %ld: %s"
-msgstr "Ðерозпізнані прапорці у %s у Ñ€Ñдку %ld: %s"
+msgid "Unrecognized flags in %s line %"
+msgstr "Ðерозпізнані прапорці у %s Ñ€Ñдок %"
#, c-format
msgid "Ignored %d words with non-ASCII characters"
msgstr "Проігноровано %d Ñлів із не-ASCII Ñимволами"
#, c-format
-msgid "Compressed %s of %ld nodes; %ld (%ld%%) remaining"
-msgstr "СтиÑнено %s з %ld вузлів; залишилоÑÑ %ld (%ld%%)"
+msgid "Compressed %s of %d nodes; %d (%ld%%) remaining"
+msgstr "СтиÑнено %s з %d вузлів; залишилоÑÑ %d (%ld%%)"
msgid "Reading back spell file..."
msgstr "ПеречитуєтьÑÑ Ñ„Ð°Ð¹Ð» орфографії..."
@@ -6540,32 +6654,32 @@ msgid "[Preview]"
msgstr "[ПереглÑд]"
#, c-format
-msgid "E1400: Cannot mix positional and non-positional arguments: %s"
-msgstr "E1400: Ðеможливо змішувати позиційні й непозиційні аргументи: %s"
+msgid "E1500: Cannot mix positional and non-positional arguments: %s"
+msgstr "E1500: Ðеможливо змішувати позиційні й непозиційні аргументи: %s"
#, c-format
-msgid "E1401: format argument %d unused in $-style format: %s"
-msgstr "E1401: аргумент %d формату не викориÑтано у $-форматуванні: %s"
+msgid "E1501: format argument %d unused in $-style format: %s"
+msgstr "E1501: аргумент %d формату не викориÑтано у $-форматуванні: %s"
#, c-format
msgid ""
-"E1402: Positional argument %d used as field width reused as different type: "
+"E1502: Positional argument %d used as field width reused as different type: "
"%s/%s"
msgstr ""
-"E1402: Позиційний аргумент %d, що задає ширину полÑ, вжито Ñк інший тип: %s/"
+"E1502: Позиційний аргумент %d, що задає ширину полÑ, вжито Ñк інший тип: %s/"
"%s"
#, c-format
-msgid "E1403: Positional argument %d out of bounds: %s"
-msgstr "E1403: Позиційний аргумент %d поза межами: %s"
+msgid "E1503: Positional argument %d out of bounds: %s"
+msgstr "E1503: Позиційний аргумент %d поза межами: %s"
#, c-format
-msgid "E1404: Positional argument %d type used inconsistently: %s/%s"
-msgstr "E1404: Тип позиційного аргументу %d вжито нерегулÑрно: %s/%s"
+msgid "E1504: Positional argument %d type used inconsistently: %s/%s"
+msgstr "E1504: Тип позиційного аргументу %d вжито нерегулÑрно: %s/%s"
#, c-format
-msgid "E1405: Invalid format specifier: %s"
-msgstr "E1405: Ðекоректний Ñпецифікатор формату: %s"
+msgid "E1505: Invalid format specifier: %s"
+msgstr "E1505: Ðекоректний Ñпецифікатор формату: %s"
msgid "unknown"
msgstr "невідомо"
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c
index f009722357..e34d6fd97f 100644
--- a/src/nvim/popupmenu.c
+++ b/src/nvim/popupmenu.c
@@ -8,35 +8,47 @@
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
+#include "nvim/api/vim.h"
#include "nvim/ascii_defs.h"
+#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/drawscreen.h"
#include "nvim/eval/typval.h"
#include "nvim/ex_cmds.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/insexpand.h"
#include "nvim/keycodes.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/menu.h"
#include "nvim/message.h"
#include "nvim/move.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
+#include "nvim/optionstr.h"
+#include "nvim/plines.h"
#include "nvim/popupmenu.h"
#include "nvim/pos_defs.h"
#include "nvim/state_defs.h"
#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/ui_compositor.h"
+#include "nvim/ui_defs.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
+#include "nvim/winfloat.h"
static pumitem_T *pum_array = NULL; // items of displayed pum
static int pum_size; // nr of items in "pum_array"
@@ -53,7 +65,8 @@ static bool pum_rl; // true when popupmenu is drawn 'rightleft'
static int pum_anchor_grid; // grid where position is defined
static int pum_row; // top row of pum
-static int pum_col; // left column of pum
+static int pum_col; // left column of pum, right column if 'rightleft'
+static int pum_left_col; // left column of pum, before padding or scrollbar
static bool pum_above; // pum is drawn above cursor line
static bool pum_is_visible = false;
@@ -73,21 +86,20 @@ static void pum_compute_size(void)
pum_kind_width = 0;
pum_extra_width = 0;
for (int i = 0; i < pum_size; i++) {
- int w;
if (pum_array[i].pum_text != NULL) {
- w = vim_strsize(pum_array[i].pum_text);
+ int w = vim_strsize(pum_array[i].pum_text);
if (pum_base_width < w) {
pum_base_width = w;
}
}
if (pum_array[i].pum_kind != NULL) {
- w = vim_strsize(pum_array[i].pum_kind) + 1;
+ int w = vim_strsize(pum_array[i].pum_kind) + 1;
if (pum_kind_width < w) {
pum_kind_width = w;
}
}
if (pum_array[i].pum_extra != NULL) {
- w = vim_strsize(pum_array[i].pum_extra) + 1;
+ int w = vim_strsize(pum_array[i].pum_extra) + 1;
if (pum_extra_width < w) {
pum_extra_width = w;
}
@@ -460,14 +472,14 @@ void pum_redraw(void)
grid_assign_handle(&pum_grid);
- bool moved = ui_comp_put_grid(&pum_grid, pum_row, pum_col - col_off,
+ pum_left_col = pum_col - col_off;
+ bool moved = ui_comp_put_grid(&pum_grid, pum_row, pum_left_col,
pum_height, grid_width, false, true);
bool invalid_grid = moved || pum_invalid;
pum_invalid = false;
must_redraw_pum = false;
- if (!pum_grid.chars
- || pum_grid.rows != pum_height || pum_grid.cols != grid_width) {
+ if (!pum_grid.chars || pum_grid.rows != pum_height || pum_grid.cols != grid_width) {
grid_alloc(&pum_grid, pum_height, grid_width, !invalid_grid, false);
ui_call_grid_resize(pum_grid.handle, pum_grid.cols, pum_grid.rows);
} else if (invalid_grid) {
@@ -476,9 +488,8 @@ void pum_redraw(void)
if (ui_has(kUIMultigrid)) {
const char *anchor = pum_above ? "SW" : "NW";
int row_off = pum_above ? -pum_height : 0;
- ui_call_win_float_pos(pum_grid.handle, -1, cstr_as_string((char *)anchor),
- pum_anchor_grid, pum_row - row_off, pum_col - col_off,
- false, pum_grid.zindex);
+ ui_call_win_float_pos(pum_grid.handle, -1, cstr_as_string(anchor), pum_anchor_grid,
+ pum_row - row_off, pum_left_col, false, pum_grid.zindex);
}
// Never display more than we have
@@ -625,19 +636,19 @@ void pum_redraw(void)
}
if (pum_rl) {
- grid_line_fill(col_off - pum_base_width - n + 1, grid_col + 1, ' ', attr);
+ grid_line_fill(col_off - pum_base_width - n + 1, grid_col + 1, schar_from_ascii(' '), attr);
grid_col = col_off - pum_base_width - n + 1;
} else {
- grid_line_fill(grid_col, col_off + pum_base_width + n, ' ', attr);
+ grid_line_fill(grid_col, col_off + pum_base_width + n, schar_from_ascii(' '), attr);
grid_col = col_off + pum_base_width + n;
}
totwidth = pum_base_width + n;
}
if (pum_rl) {
- grid_line_fill(col_off - pum_width + 1, grid_col + 1, ' ', attr);
+ grid_line_fill(col_off - pum_width + 1, grid_col + 1, schar_from_ascii(' '), attr);
} else {
- grid_line_fill(grid_col, col_off + pum_width, ' ', attr);
+ grid_line_fill(grid_col, col_off + pum_width, schar_from_ascii(' '), attr);
}
if (pum_scrollbar > 0) {
@@ -654,6 +665,142 @@ void pum_redraw(void)
}
}
+/// create a floating preview window for info
+/// @return NULL when no enough room to show
+static win_T *pum_create_float_preview(bool enter)
+{
+ WinConfig config = WIN_CONFIG_INIT;
+ config.relative = kFloatRelativeEditor;
+ // when pum_above is SW otherwise is NW
+ config.anchor = pum_above ? kFloatAnchorSouth : 0;
+ int col = pum_col + pum_width + pum_scrollbar + 1;
+ // TODO(glepnir): support config align border by using completepopup
+ // align menu
+ config.row = pum_row;
+ int right_extra = Columns - col;
+ if (right_extra > 0) {
+ config.width = right_extra;
+ config.col = col - 1;
+ } else if (pum_col - 2 > 0) {
+ config.width = pum_col - 2;
+ config.col = pum_col - config.width - 1;
+ } else {
+ return NULL;
+ }
+ config.height = pum_height;
+ config.style = kWinStyleMinimal;
+ config.hide = true;
+ Error err = ERROR_INIT;
+ win_T *wp = win_new_float(NULL, true, config, &err);
+ // TODO(glepnir): remove win_enter usage
+ if (enter) {
+ win_enter(wp, false);
+ }
+
+ // create a new buffer
+ Buffer b = nvim_create_buf(false, true, &err);
+ if (!b) {
+ win_free(wp, NULL);
+ return NULL;
+ }
+ buf_T *buf = find_buffer_by_handle(b, &err);
+ set_string_option_direct_in_buf(buf, kOptBufhidden, "wipe", OPT_LOCAL, 0);
+ wp->w_float_is_info = true;
+ wp->w_p_diff = false;
+ buf->b_p_bl = false;
+ win_set_buf(wp, buf, true, &err);
+ return wp;
+}
+
+/// set info text to preview buffer.
+static void pum_preview_set_text(buf_T *buf, char *info, linenr_T *lnum, int *max_width)
+{
+ for (char *p = info; *p != NUL;) {
+ int text_width = 0;
+ char *e = vim_strchr(p, '\n');
+ if (e == NULL) {
+ ml_append_buf(buf, (*lnum)++, p, 0, false);
+ text_width = (int)mb_string2cells(p);
+ if (text_width > *max_width) {
+ *max_width = text_width;
+ }
+ break;
+ }
+ *e = NUL;
+ ml_append_buf(buf, (*lnum)++, p, (int)(e - p + 1), false);
+ text_width = (int)mb_string2cells(p);
+ if (text_width > *max_width) {
+ *max_width = text_width;
+ }
+ *e = '\n';
+ p = e + 1;
+ }
+ // delete the empty last line
+ ml_delete_buf(buf, buf->b_ml.ml_line_count, false);
+}
+
+/// adjust floating preview window width and height
+static void pum_adjust_float_position(win_T *wp, int height, int width)
+{
+ // when floating window in right and right no enough room to show
+ // but left has enough room, adjust floating window to left.
+ if (wp->w_config.width < width && wp->w_config.col > pum_col) {
+ if ((pum_col - 2) > width) {
+ wp->w_config.width = width;
+ wp->w_config.col = pum_col - width - 1;
+ }
+ }
+ wp->w_config.width = MIN(wp->w_config.width, width);
+ wp->w_config.height = MIN(Rows, height);
+ wp->w_config.hide = false;
+ win_config_float(wp, wp->w_config);
+}
+
+/// used in nvim_complete_set
+win_T *pum_set_info(int pum_idx, char *info)
+{
+ if (!pum_is_visible || pum_idx < 0 || pum_idx > pum_size) {
+ return NULL;
+ }
+ pum_array[pum_idx].pum_info = xstrdup(info);
+ compl_set_info(pum_idx);
+ bool use_float = strstr(p_cot, "popup") != NULL ? true : false;
+ if (pum_idx != pum_selected || !use_float) {
+ return NULL;
+ }
+
+ block_autocmds();
+ RedrawingDisabled++;
+ no_u_sync++;
+ win_T *wp = win_float_find_preview();
+ if (wp == NULL) {
+ wp = pum_create_float_preview(false);
+ // no enough room to show
+ if (!wp) {
+ return NULL;
+ }
+ } else {
+ // clean exist buffer
+ while (!buf_is_empty(wp->w_buffer)) {
+ ml_delete_buf(wp->w_buffer, 1, false);
+ }
+ }
+ no_u_sync--;
+ RedrawingDisabled--;
+
+ linenr_T lnum = 0;
+ int max_info_width = 0;
+ pum_preview_set_text(wp->w_buffer, info, &lnum, &max_info_width);
+ redraw_later(wp, UPD_SOME_VALID);
+
+ if (wp->w_p_wrap) {
+ lnum += plines_win(wp, lnum, true);
+ }
+ pum_adjust_float_position(wp, lnum, max_info_width);
+ unblock_autocmds();
+ return wp;
+}
+
/// Set the index of the currently selected item. The menu will scroll when
/// necessary. When "n" is out of range don't scroll.
/// This may be repeated when the preview window is used:
@@ -668,8 +815,9 @@ void pum_redraw(void)
/// menu must be recomputed.
static bool pum_set_selected(int n, int repeat)
{
- int resized = false;
+ bool resized = false;
int context = pum_height / 2;
+ int prev_selected = pum_selected;
pum_selected = n;
@@ -718,6 +866,10 @@ static bool pum_set_selected(int n, int repeat)
pum_first = pum_selected + context - pum_height + 1;
}
}
+ // adjust for the number of lines displayed
+ if (pum_first > pum_size - pum_height) {
+ pum_first = pum_size - pum_height;
+ }
// Show extra info in the preview window if there is something and
// 'completeopt' contains "preview".
@@ -730,6 +882,11 @@ static bool pum_set_selected(int n, int repeat)
&& (vim_strchr(p_cot, 'p') != NULL)) {
win_T *curwin_save = curwin;
tabpage_T *curtab_save = curtab;
+ bool use_float = strstr(p_cot, "popup") != NULL ? true : false;
+
+ if (use_float) {
+ block_autocmds();
+ }
// Open a preview window. 3 lines by default. Prefer
// 'previewheight' if set and smaller.
@@ -742,12 +899,26 @@ static bool pum_set_selected(int n, int repeat)
// Prevent undo sync here, if an autocommand syncs undo weird
// things can happen to the undo tree.
no_u_sync++;
- resized = prepare_tagpreview(false);
+
+ if (!use_float) {
+ resized = prepare_tagpreview(false);
+ } else {
+ win_T *wp = win_float_find_preview();
+ if (wp) {
+ win_enter(wp, false);
+ } else {
+ wp = pum_create_float_preview(true);
+ if (wp) {
+ resized = true;
+ }
+ }
+ }
+
no_u_sync--;
RedrawingDisabled--;
g_do_tagpreview = 0;
- if (curwin->w_p_pvw) {
+ if (curwin->w_p_pvw || curwin->w_float_is_info) {
int res = OK;
if (!resized
&& (curbuf->b_nwindows == 1)
@@ -767,32 +938,21 @@ static bool pum_set_selected(int n, int repeat)
if (res == OK) {
// Edit a new, empty buffer. Set options for a "wipeout"
// buffer.
- set_option_value_give_err("swf", BOOLEAN_OPTVAL(false), OPT_LOCAL);
- set_option_value_give_err("bl", BOOLEAN_OPTVAL(false), OPT_LOCAL);
- set_option_value_give_err("bt", STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL);
- set_option_value_give_err("bh", STATIC_CSTR_AS_OPTVAL("wipe"), OPT_LOCAL);
- set_option_value_give_err("diff", BOOLEAN_OPTVAL(false), OPT_LOCAL);
+ set_option_value_give_err(kOptSwapfile, BOOLEAN_OPTVAL(false), OPT_LOCAL);
+ set_option_value_give_err(kOptBuflisted, BOOLEAN_OPTVAL(false), OPT_LOCAL);
+ set_option_value_give_err(kOptBuftype, STATIC_CSTR_AS_OPTVAL("nofile"), OPT_LOCAL);
+ set_option_value_give_err(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("wipe"), OPT_LOCAL);
+ set_option_value_give_err(kOptDiff, BOOLEAN_OPTVAL(false), OPT_LOCAL);
}
}
if (res == OK) {
linenr_T lnum = 0;
-
- for (char *p = pum_array[pum_selected].pum_info; *p != NUL;) {
- char *e = vim_strchr(p, '\n');
- if (e == NULL) {
- ml_append(lnum++, p, 0, false);
- break;
- }
- *e = NUL;
- ml_append(lnum++, p, (int)(e - p + 1), false);
- *e = '\n';
- p = e + 1;
- }
-
+ int max_info_width = 0;
+ pum_preview_set_text(curbuf, pum_array[pum_selected].pum_info, &lnum, &max_info_width);
// Increase the height of the preview window to show the
// text, but no more than 'previewheight' lines.
- if (repeat == 0) {
+ if (repeat == 0 && !use_float) {
if (lnum > p_pvh) {
lnum = (linenr_T)p_pvh;
}
@@ -805,9 +965,22 @@ static bool pum_set_selected(int n, int repeat)
curbuf->b_changed = false;
curbuf->b_p_ma = false;
+ if (pum_selected != prev_selected) {
+ curwin->w_topline = 1;
+ } else if (curwin->w_topline > curbuf->b_ml.ml_line_count) {
+ curwin->w_topline = curbuf->b_ml.ml_line_count;
+ }
curwin->w_cursor.lnum = 1;
curwin->w_cursor.col = 0;
+ if (use_float) {
+ if (curwin->w_p_wrap) {
+ lnum += plines_win(curwin, lnum, true);
+ }
+ // adjust floating window by actually height and max info text width
+ pum_adjust_float_position(curwin, lnum, max_info_width);
+ }
+
if ((curwin != curwin_save && win_valid(curwin_save))
|| (curtab != curtab_save && valid_tabpage(curtab_save))) {
if (curtab != curtab_save && valid_tabpage(curtab_save)) {
@@ -829,7 +1002,7 @@ static bool pum_set_selected(int n, int repeat)
// update the view on the buffer. Only go back to
// the window when needed, otherwise it will always be
// redrawn.
- if (resized) {
+ if (resized && win_valid(curwin_save)) {
no_u_sync++;
win_enter(curwin_save, true);
no_u_sync--;
@@ -858,6 +1031,10 @@ static bool pum_set_selected(int n, int repeat)
}
}
}
+
+ if (use_float) {
+ unblock_autocmds();
+ }
}
}
@@ -892,6 +1069,10 @@ void pum_check_clear(void)
}
pum_is_drawn = false;
pum_external = false;
+ win_T *wp = win_float_find_preview();
+ if (wp != NULL) {
+ win_close(wp, false, false);
+ }
}
}
@@ -964,13 +1145,13 @@ void pum_set_event_info(dict_T *dict)
r = (double)pum_row;
c = (double)pum_col;
}
- (void)tv_dict_add_float(dict, S_LEN("height"), h);
- (void)tv_dict_add_float(dict, S_LEN("width"), w);
- (void)tv_dict_add_float(dict, S_LEN("row"), r);
- (void)tv_dict_add_float(dict, S_LEN("col"), c);
- (void)tv_dict_add_nr(dict, S_LEN("size"), pum_size);
- (void)tv_dict_add_bool(dict, S_LEN("scrollbar"),
- pum_scrollbar ? kBoolVarTrue : kBoolVarFalse);
+ tv_dict_add_float(dict, S_LEN("height"), h);
+ tv_dict_add_float(dict, S_LEN("width"), w);
+ tv_dict_add_float(dict, S_LEN("row"), r);
+ tv_dict_add_float(dict, S_LEN("col"), c);
+ tv_dict_add_nr(dict, S_LEN("size"), pum_size);
+ tv_dict_add_bool(dict, S_LEN("scrollbar"),
+ pum_scrollbar ? kBoolVarTrue : kBoolVarFalse);
}
static void pum_position_at_mouse(int min_width)
@@ -986,7 +1167,14 @@ static void pum_position_at_mouse(int min_width)
max_col = MAX(Columns - wp->w_wincol, wp->w_grid.cols);
}
}
- pum_anchor_grid = mouse_grid;
+ if (pum_grid.handle != 0 && mouse_grid == pum_grid.handle) {
+ // Repositioning the menu by right-clicking on itself
+ mouse_grid = pum_anchor_grid;
+ mouse_row += pum_row;
+ mouse_col += pum_left_col;
+ } else {
+ pum_anchor_grid = mouse_grid;
+ }
if (max_row - mouse_row > pum_size) {
// Enough space below the mouse row.
pum_above = false;
diff --git a/src/nvim/popupmenu.h b/src/nvim/popupmenu.h
index 24a3f8713a..20a342b841 100644
--- a/src/nvim/popupmenu.h
+++ b/src/nvim/popupmenu.h
@@ -6,6 +6,7 @@
#include "nvim/grid_defs.h"
#include "nvim/macros_defs.h"
#include "nvim/menu_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
/// Used for popup menu items.
typedef struct {
diff --git a/src/nvim/pos_defs.h b/src/nvim/pos_defs.h
index 98a1762a5c..a9816c6a66 100644
--- a/src/nvim/pos_defs.h
+++ b/src/nvim/pos_defs.h
@@ -12,19 +12,15 @@ typedef int colnr_T;
/// Format used to print values which have colnr_T type
#define PRIdCOLNR "d"
-/// Maximal (invalid) line number
-enum { MAXLNUM = 0x7fffffff, };
+enum { MAXLNUM = 0x7fffffff, }; ///< Maximal (invalid) line number
-/// Maximal column number
-/// MAXCOL used to be INT_MAX, but with 64 bit ints that results in running
-/// out of memory when trying to allocate a very long line.
-enum { MAXCOL = 0x7fffffff, };
+// MAXCOL used to be INT_MAX, but with 64 bit ints that results in running
+// out of memory when trying to allocate a very long line.
+enum { MAXCOL = 0x7fffffff, }; ///< Maximal column number
-/// Minimum line number
-enum { MINLNUM = 1, };
+enum { MINLNUM = 1, }; ///< Minimum line number
-/// Minimum column number
-enum { MINCOL = 1, };
+enum { MINCOL = 1, }; ///< Minimum column number
/// position in file or buffer
typedef struct {
diff --git a/src/nvim/profile.c b/src/nvim/profile.c
index 53ff57dacb..b88b08d3f0 100644
--- a/src/nvim/profile.c
+++ b/src/nvim/profile.c
@@ -15,11 +15,11 @@
#include "nvim/eval/userfunc.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/keycodes.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -36,7 +36,7 @@
#endif
/// Struct used in sn_prl_ga for every line of a script.
-typedef struct sn_prl_S {
+typedef struct {
int snp_count; ///< nr of times line was executed
proftime_T sn_prl_total; ///< time spent in a line + children
proftime_T sn_prl_self; ///< time spent in a line itself
@@ -45,6 +45,7 @@ typedef struct sn_prl_S {
#define PRL_ITEM(si, idx) (((sn_prl_T *)(si)->sn_prl_ga.ga_data)[(idx)])
static proftime_T prof_wait_time;
+static char *startuptime_buf = NULL; // --startuptime buffer
/// Gets the current time.
///
@@ -255,7 +256,7 @@ void profile_reset(void)
size_t todo = functbl->ht_used;
hashitem_T *hi = functbl->ht_array;
- for (; todo > (size_t)0; hi++) {
+ for (; todo > 0; hi++) {
if (!HASHITEM_EMPTY(hi)) {
todo--;
ufunc_T *uf = HI2UF(hi);
@@ -798,7 +799,7 @@ void script_line_start(void)
if (si->sn_prof_on && SOURCING_LNUM >= 1) {
// Grow the array before starting the timer, so that the time spent
// here isn't counted.
- (void)ga_grow(&si->sn_prl_ga, SOURCING_LNUM - si->sn_prl_ga.ga_len);
+ ga_grow(&si->sn_prl_ga, SOURCING_LNUM - si->sn_prl_ga.ga_len);
si->sn_prl_idx = SOURCING_LNUM - 1;
while (si->sn_prl_ga.ga_len <= si->sn_prl_idx
&& si->sn_prl_ga.ga_len < si->sn_prl_ga.ga_maxlen) {
@@ -907,7 +908,7 @@ void time_start(const char *message)
// initialize the global variables
g_prev_time = g_start_time = profile_start();
- fprintf(time_fd, "\n\ntimes in msec\n");
+ fprintf(time_fd, "\ntimes in msec\n");
fprintf(time_fd, " clock self+sourced self: sourced script\n");
fprintf(time_fd, " clock elapsed: other lines\n\n");
@@ -944,3 +945,47 @@ void time_msg(const char *mesg, const proftime_T *start)
g_prev_time = now;
fprintf(time_fd, ": %s\n", mesg);
}
+
+/// Initializes the `time_fd` stream for the --startuptime report.
+///
+/// @param fname startuptime report file path
+/// @param process_name name of the current Nvim process to write in the report.
+void time_init(const char *fname, const char *process_name)
+{
+ const size_t bufsize = 8192; // Big enough for the entire --startuptime report.
+ time_fd = fopen(fname, "a");
+ if (time_fd == NULL) {
+ semsg(_(e_notopen), fname);
+ return;
+ }
+ startuptime_buf = xmalloc(sizeof(char) * (bufsize + 1));
+ // The startuptime file is (potentially) written by multiple Nvim processes concurrently. So each
+ // report is buffered, and flushed to disk (`time_finish`) once after startup. `_IOFBF` mode
+ // ensures the buffer is not auto-flushed ("controlled buffering").
+ int r = setvbuf(time_fd, startuptime_buf, _IOFBF, bufsize + 1);
+ if (r != 0) {
+ XFREE_CLEAR(startuptime_buf);
+ fclose(time_fd);
+ time_fd = NULL;
+ ELOG("time_init: setvbuf failed: %d %s", r, uv_err_name(r));
+ semsg("time_init: setvbuf failed: %d %s", r, uv_err_name(r));
+ return;
+ }
+ fprintf(time_fd, "--- Startup times for process: %s ---\n", process_name);
+}
+
+/// Flushes the startuptimes to disk for the current process
+void time_finish(void)
+{
+ if (time_fd == NULL) {
+ return;
+ }
+ assert(startuptime_buf != NULL);
+ TIME_MSG("--- NVIM STARTED ---\n");
+
+ // flush buffer to disk
+ fclose(time_fd);
+ time_fd = NULL;
+
+ XFREE_CLEAR(startuptime_buf);
+}
diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c
index 4e20eb8925..651ebc9f93 100644
--- a/src/nvim/quickfix.c
+++ b/src/nvim/quickfix.c
@@ -13,7 +13,9 @@
#include "nvim/arglist.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
#include "nvim/drawscreen.h"
@@ -26,20 +28,24 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
+#include "nvim/ex_eval_defs.h"
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/help.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/macros_defs.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
@@ -49,16 +55,20 @@
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/quickfix.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/search.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/undo.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -107,7 +117,7 @@ typedef enum {
/// Usually the list contains one or more entries. But an empty list can be
/// created using setqflist()/setloclist() with a title and/or user context
/// information and entries can be added later using setqflist()/setloclist().
-typedef struct qf_list_S {
+typedef struct {
unsigned qf_id; ///< Unique identifier for this list
qfltype_T qfl_type;
qfline_T *qf_start; ///< pointer to the first error
@@ -232,7 +242,7 @@ typedef struct {
} qffields_T;
/// :vimgrep command arguments
-typedef struct vgr_args_S {
+typedef struct {
int tomatch; ///< maximum number of matches to find
char *spat; ///< search pattern
int flags; ///< search modifier
@@ -272,7 +282,7 @@ enum { QF_WINHEIGHT = 10, }; ///< default height for quickfix window
// Macro to loop through all the items in a quickfix list
// Quickfix item index starts from 1, so i below starts at 1
#define FOR_ALL_QFL_ITEMS(qfl, qfp, i) \
- for ((i) = 1, (qfp) = (qfl)->qf_start; /* NOLINT(readability/braces) */ \
+ for ((i) = 1, (qfp) = (qfl)->qf_start; \
!got_int && (i) <= (qfl)->qf_count && (qfp) != NULL; \
(i)++, (qfp) = (qfp)->qf_next)
@@ -1056,7 +1066,9 @@ static int qf_setup_state(qfstate_T *pstate, char *restrict enc, const char *res
}
if (efile != NULL
- && (pstate->fd = os_fopen(efile, "r")) == NULL) {
+ && (pstate->fd = (strequal(efile, "-")
+ ? fdopen(os_open_stdin_fd(), "r")
+ : os_fopen(efile, "r"))) == NULL) {
semsg(_(e_openerrf), efile);
return FAIL;
}
@@ -1603,7 +1615,7 @@ static int qf_parse_get_fields(char *linebuf, size_t linelen, efm_T *fmt_ptr, qf
// Always ignore case when looking for a matching error.
regmatch.rm_ic = true;
regmatch.regprog = fmt_ptr->prog;
- int r = vim_regexec(&regmatch, linebuf, 0);
+ bool r = vim_regexec(&regmatch, linebuf, 0);
fmt_ptr->prog = regmatch.regprog;
int status = QF_FAIL;
if (r) {
@@ -1970,7 +1982,7 @@ static qf_info_T *ll_get_or_alloc_list(win_T *wp)
/// For a location list command, returns the stack for the current window. If
/// the location list is not found, then returns NULL and prints an error
/// message if 'print_emsg' is true.
-static qf_info_T *qf_cmd_get_stack(exarg_T *eap, int print_emsg)
+static qf_info_T *qf_cmd_get_stack(exarg_T *eap, bool print_emsg)
{
qf_info_T *qi = &ql_info;
@@ -2512,7 +2524,7 @@ static void win_set_loclist(win_T *wp, qf_info_T *qi)
/// Find a help window or open one. If 'newwin' is true, then open a new help
/// window.
-static int jump_to_help_window(qf_info_T *qi, bool newwin, int *opened_window)
+static int jump_to_help_window(qf_info_T *qi, bool newwin, bool *opened_window)
{
win_T *wp = NULL;
@@ -2715,7 +2727,7 @@ static void qf_goto_win_with_qfl_file(int qf_fnum)
// window, jump to it. Otherwise open a new window to display the file. If
// 'newwin' is true, then always open a new window. This is called from either
// a quickfix or a location list window.
-static int qf_jump_to_usable_window(int qf_fnum, bool newwin, int *opened_window)
+static int qf_jump_to_usable_window(int qf_fnum, bool newwin, bool *opened_window)
{
win_T *usable_wp = NULL;
bool usable_win = false;
@@ -2770,7 +2782,7 @@ static int qf_jump_to_usable_window(int qf_fnum, bool newwin, int *opened_window
/// QF_ABORT if the quickfix/location list was freed by an autocmd
/// when opening the buffer.
static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, int prev_winid,
- int *opened_window)
+ bool *opened_window)
{
qf_list_T *qfl = qf_get_curlist(qi);
int old_changetick = qfl->qf_changedtick;
@@ -2905,7 +2917,7 @@ static void qf_jump_print_msg(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, buf
/// FAIL if not able to jump/open a window.
/// NOTDONE if a file is not associated with the entry.
/// QF_ABORT if the quickfix/location list was modified by an autocmd.
-static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, int *opened_window)
+static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, bool *opened_window)
{
qf_list_T *qfl = qf_get_curlist(qi);
int old_changetick = qfl->qf_changedtick;
@@ -2964,7 +2976,7 @@ static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, int
/// QF_ABORT if the quickfix/location list is freed by an autocmd when opening
/// the file.
static int qf_jump_to_buffer(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, int forceit,
- int prev_winid, int *opened_window, int openfold, int print_message)
+ int prev_winid, bool *opened_window, int openfold, bool print_message)
{
// If there is a file name, read the wanted file if needed, and check
// autowrite etc.
@@ -3051,7 +3063,7 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo
int prev_winid = curwin->handle;
- int opened_window = false;
+ bool opened_window = false;
int retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window);
if (retval == FAIL) {
goto failed;
@@ -3646,12 +3658,12 @@ static int qf_goto_cwindow(const qf_info_T *qi, bool resize, int sz, bool vertsp
static void qf_set_cwindow_options(void)
{
// switch off 'swapfile'
- set_option_value_give_err("swf", BOOLEAN_OPTVAL(false), OPT_LOCAL);
- set_option_value_give_err("bt", STATIC_CSTR_AS_OPTVAL("quickfix"), OPT_LOCAL);
- set_option_value_give_err("bh", STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL);
+ set_option_value_give_err(kOptSwapfile, BOOLEAN_OPTVAL(false), OPT_LOCAL);
+ set_option_value_give_err(kOptBuftype, STATIC_CSTR_AS_OPTVAL("quickfix"), OPT_LOCAL);
+ set_option_value_give_err(kOptBufhidden, STATIC_CSTR_AS_OPTVAL("hide"), OPT_LOCAL);
RESET_BINDING(curwin);
curwin->w_p_diff = false;
- set_option_value_give_err("fdm", STATIC_CSTR_AS_OPTVAL("manual"), OPT_LOCAL);
+ set_option_value_give_err(kOptFoldmethod, STATIC_CSTR_AS_OPTVAL("manual"), OPT_LOCAL);
}
// Open a new quickfix or location list window, load the quickfix buffer and
@@ -3988,7 +4000,7 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last)
buf_inc_changedtick(buf);
if (old_last == NULL) {
- (void)qf_win_pos_update(qi, 0);
+ qf_win_pos_update(qi, 0);
// restore curwin/curbuf and a few other things
aucmd_restbuf(&aco);
@@ -4131,6 +4143,12 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q
}
// delete all existing lines
+ //
+ // Note: we cannot store undo information, because
+ // qf buffer is usually not allowed to be modified.
+ //
+ // So we need to clean up undo information
+ // otherwise autocommands may invalidate the undo stack
while ((curbuf->b_ml.ml_flags & ML_EMPTY) == 0) {
// If deletion fails, this loop may run forever, so
// signal error and return.
@@ -4139,6 +4157,9 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q
return;
}
}
+
+ // Remove all undo information
+ u_clearallandblockfree(curbuf);
}
// Check if there is anything to display
@@ -4199,7 +4220,7 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q
}
if (old_last == NULL) {
// Delete the empty line which is now at the end
- (void)ml_delete(lnum + 1, false);
+ ml_delete(lnum + 1, false);
}
qfga_clear();
@@ -4213,7 +4234,7 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q
// resembles reading a file into a buffer, it's more logical when using
// autocommands.
curbuf->b_ro_locked++;
- set_option_value_give_err("ft", STATIC_CSTR_AS_OPTVAL("qf"), OPT_LOCAL);
+ set_option_value_give_err(kOptFiletype, STATIC_CSTR_AS_OPTVAL("qf"), OPT_LOCAL);
curbuf->b_p_ma = false;
keep_filetype = true; // don't detect 'filetype'
@@ -4583,7 +4604,7 @@ int qf_get_cur_valid_idx(exarg_T *eap)
/// Used by :cdo, :ldo, :cfdo and :lfdo commands.
/// For :cdo and :ldo, returns the 'n'th valid error entry.
/// For :cfdo and :lfdo, returns the 'n'th valid file entry.
-static size_t qf_get_nth_valid_entry(qf_list_T *qfl, size_t n, int fdo)
+static size_t qf_get_nth_valid_entry(qf_list_T *qfl, size_t n, bool fdo)
FUNC_ATTR_NONNULL_ALL
{
// Check if the list has valid errors.
@@ -5091,7 +5112,7 @@ void ex_cfile(exarg_T *eap)
}
}
if (*eap->arg != NUL) {
- set_string_option_direct("ef", -1, eap->arg, OPT_FREE, 0);
+ set_string_option_direct(kOptErrorfile, eap->arg, 0, 0);
}
char *enc = (*curbuf->b_p_menc != NUL) ? curbuf->b_p_menc : p_menc;
@@ -5690,7 +5711,7 @@ static buf_T *load_dummy_buffer(char *fname, char *dirname_start, char *resultin
return NULL;
}
- int failed = true;
+ bool failed = true;
bufref_T newbufref;
set_bufref(&newbufref, newbuf);
@@ -5706,7 +5727,7 @@ static buf_T *load_dummy_buffer(char *fname, char *dirname_start, char *resultin
aucmd_prepbuf(&aco, newbuf);
// Need to set the filename for autocommands.
- (void)setfname(curbuf, fname, NULL, false);
+ setfname(curbuf, fname, NULL, false);
// Create swap file now to avoid the ATTENTION message.
check_need_swap(true);
@@ -5958,7 +5979,7 @@ static int qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict)
if (qf_init_ext(qi, 0, NULL, NULL, &di->di_tv, errorformat,
true, 0, 0, NULL, NULL) > 0) {
- (void)get_errorlist(qi, NULL, 0, 0, l);
+ get_errorlist(qi, NULL, 0, 0, l);
qf_free(&qi->qf_lists[0]);
}
xfree(qi);
@@ -6907,7 +6928,7 @@ static int cbuffer_process_args(exarg_T *eap, buf_T **bufp, linenr_T *line1, lin
}
if (buf->b_ml.ml_mfp == NULL) {
- emsg(_("E681: Buffer is not loaded"));
+ emsg(_(e_buffer_is_not_loaded));
return FAIL;
}
@@ -7221,7 +7242,7 @@ void ex_helpgrep(exarg_T *eap)
bool updated = false;
// Make 'cpoptions' empty, the 'l' flag should not be used here.
char *const save_cpo = p_cpo;
- const bool save_cpo_allocated = is_option_allocated("cpo");
+ const bool save_cpo_allocated = (get_option(kOptCpoptions)->flags & P_ALLOCED);
p_cpo = empty_string_option;
bool new_qi = false;
@@ -7259,7 +7280,7 @@ void ex_helpgrep(exarg_T *eap)
// Darn, some plugin changed the value. If it's still empty it was
// changed and restored, need to restore in the complicated way.
if (*p_cpo == NUL) {
- set_option_value_give_err("cpo", CSTR_AS_OPTVAL(save_cpo), 0);
+ set_option_value_give_err(kOptCpoptions, CSTR_AS_OPTVAL(save_cpo), 0);
}
if (save_cpo_allocated) {
free_string_option(save_cpo);
@@ -7319,12 +7340,12 @@ void free_quickfix(void)
}
#endif
-static void get_qf_loc_list(int is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv)
+static void get_qf_loc_list(bool is_qf, win_T *wp, typval_T *what_arg, typval_T *rettv)
{
if (what_arg->v_type == VAR_UNKNOWN) {
tv_list_alloc_ret(rettv, kListLenMayKnow);
if (is_qf || wp != NULL) {
- (void)get_errorlist(NULL, wp, -1, 0, rettv->vval.v_list);
+ get_errorlist(NULL, wp, -1, 0, rettv->vval.v_list);
}
} else {
tv_dict_alloc_ret(rettv);
diff --git a/src/nvim/quickfix.h b/src/nvim/quickfix.h
index 9c49564d57..941aa2f991 100644
--- a/src/nvim/quickfix.h
+++ b/src/nvim/quickfix.h
@@ -1,5 +1,6 @@
#pragma once
+#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/option_defs.h" // IWYU pragma: keep
diff --git a/src/nvim/rbuffer.c b/src/nvim/rbuffer.c
index f74f68adb6..ef286b3e22 100644
--- a/src/nvim/rbuffer.c
+++ b/src/nvim/rbuffer.c
@@ -3,13 +3,12 @@
#include <stddef.h>
#include <string.h>
-#include "nvim/func_attr.h"
#include "nvim/macros_defs.h"
#include "nvim/memory.h"
#include "nvim/rbuffer.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "rbuffer.c.generated.h" // IWYU pragma: export
+# include "rbuffer.c.generated.h"
#endif
/// Creates a new `RBuffer` instance.
@@ -30,27 +29,12 @@ RBuffer *rbuffer_new(size_t capacity)
return rv;
}
-void rbuffer_free(RBuffer *buf)
+void rbuffer_free(RBuffer *buf) FUNC_ATTR_NONNULL_ALL
{
xfree(buf->temp);
xfree(buf);
}
-size_t rbuffer_size(RBuffer *buf) FUNC_ATTR_NONNULL_ALL
-{
- return buf->size;
-}
-
-size_t rbuffer_capacity(RBuffer *buf) FUNC_ATTR_NONNULL_ALL
-{
- return (size_t)(buf->end_ptr - buf->start_ptr);
-}
-
-size_t rbuffer_space(RBuffer *buf) FUNC_ATTR_NONNULL_ALL
-{
- return rbuffer_capacity(buf) - buf->size;
-}
-
/// Return a pointer to a raw buffer containing the first empty slot available
/// for writing. The second argument is a pointer to the maximum number of
/// bytes that could be written.
@@ -214,7 +198,7 @@ size_t rbuffer_read(RBuffer *buf, char *dst, size_t dst_size)
}
char *rbuffer_get(RBuffer *buf, size_t index)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
+ FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET
{
assert(index < buf->size);
char *rptr = buf->read_ptr + index;
@@ -229,7 +213,7 @@ int rbuffer_cmp(RBuffer *buf, const char *str, size_t count)
{
assert(count <= buf->size);
size_t rcnt;
- (void)rbuffer_read_ptr(buf, &rcnt);
+ rbuffer_read_ptr(buf, &rcnt);
size_t n = MIN(count, rcnt);
int rv = memcmp(str, buf->read_ptr, n);
count -= n;
diff --git a/src/nvim/rbuffer.h b/src/nvim/rbuffer.h
index 55e9849d3d..942e1f2365 100644
--- a/src/nvim/rbuffer.h
+++ b/src/nvim/rbuffer.h
@@ -16,6 +16,8 @@
#include <stddef.h>
#include <stdint.h>
+#include "nvim/rbuffer_defs.h" // IWYU pragma: keep
+
// Macros that simplify working with the read/write pointers directly by hiding
// ring buffer wrap logic. Some examples:
//
@@ -36,50 +38,34 @@
// Note that the rbuffer_{produced,consumed} calls are necessary or these macros
// create infinite loops
#define RBUFFER_UNTIL_EMPTY(buf, rptr, rcnt) \
- for (size_t rcnt = 0, _r = 1; _r; _r = 0) /* NOLINT(readability/braces) */ \
- for (char *rptr = rbuffer_read_ptr(buf, &rcnt); /* NOLINT(readability/braces) */ \
+ for (size_t rcnt = 0, _r = 1; _r; _r = 0) \
+ for (char *rptr = rbuffer_read_ptr(buf, &rcnt); \
buf->size; \
rptr = rbuffer_read_ptr(buf, &rcnt))
#define RBUFFER_UNTIL_FULL(buf, wptr, wcnt) \
- for (size_t wcnt = 0, _r = 1; _r; _r = 0) /* NOLINT(readability/braces) */ \
- for (char *wptr = rbuffer_write_ptr(buf, &wcnt); /* NOLINT(readability/braces) */ \
+ for (size_t wcnt = 0, _r = 1; _r; _r = 0) \
+ for (char *wptr = rbuffer_write_ptr(buf, &wcnt); \
rbuffer_space(buf); \
wptr = rbuffer_write_ptr(buf, &wcnt))
// Iteration
#define RBUFFER_EACH(buf, c, i) \
- for (size_t i = 0; /* NOLINT(readability/braces) */ \
+ for (size_t i = 0; \
i < buf->size; \
i = buf->size) \
- for (char c = 0; /* NOLINT(readability/braces) */ \
+ for (char c = 0; \
i < buf->size ? ((int)(c = *rbuffer_get(buf, i))) || 1 : 0; \
i++)
#define RBUFFER_EACH_REVERSE(buf, c, i) \
- for (size_t i = buf->size; /* NOLINT(readability/braces) */ \
+ for (size_t i = buf->size; \
i != SIZE_MAX; \
i = SIZE_MAX) \
- for (char c = 0; /* NOLINT(readability/braces) */ \
+ for (char c = 0; \
i-- > 0 ? ((int)(c = *rbuffer_get(buf, i))) || 1 : 0; \
)
-typedef struct rbuffer RBuffer;
-/// Type of function invoked during certain events:
-/// - When the RBuffer switches to the full state
-/// - When the RBuffer switches to the non-full state
-typedef void (*rbuffer_callback)(RBuffer *buf, void *data);
-
-struct rbuffer {
- rbuffer_callback full_cb, nonfull_cb;
- void *data;
- size_t size;
- // helper memory used to by rbuffer_reset if required
- char *temp;
- char *end_ptr, *read_ptr, *write_ptr;
- char start_ptr[];
-};
-
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "rbuffer.h.generated.h"
#endif
diff --git a/src/nvim/rbuffer_defs.h b/src/nvim/rbuffer_defs.h
new file mode 100644
index 0000000000..51dc349846
--- /dev/null
+++ b/src/nvim/rbuffer_defs.h
@@ -0,0 +1,45 @@
+#pragma once
+
+#include <stddef.h>
+
+#include "nvim/func_attr.h"
+
+typedef struct rbuffer RBuffer;
+/// Type of function invoked during certain events:
+/// - When the RBuffer switches to the full state
+/// - When the RBuffer switches to the non-full state
+typedef void (*rbuffer_callback)(RBuffer *buf, void *data);
+
+struct rbuffer {
+ rbuffer_callback full_cb, nonfull_cb;
+ void *data;
+ size_t size;
+ // helper memory used to by rbuffer_reset if required
+ char *temp;
+ char *end_ptr, *read_ptr, *write_ptr;
+ char start_ptr[];
+};
+
+static inline size_t rbuffer_size(RBuffer *buf)
+ REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL;
+
+static inline size_t rbuffer_size(RBuffer *buf)
+{
+ return buf->size;
+}
+
+static inline size_t rbuffer_capacity(RBuffer *buf)
+ REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL;
+
+static inline size_t rbuffer_capacity(RBuffer *buf)
+{
+ return (size_t)(buf->end_ptr - buf->start_ptr);
+}
+
+static inline size_t rbuffer_space(RBuffer *buf)
+ REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL;
+
+static inline size_t rbuffer_space(RBuffer *buf)
+{
+ return rbuffer_capacity(buf) - buf->size;
+}
diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c
index 3536196a3b..86082adbb6 100644
--- a/src/nvim/regexp.c
+++ b/src/nvim/regexp.c
@@ -13,7 +13,7 @@
#include <stdbool.h>
#include <stddef.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
@@ -21,14 +21,16 @@
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/eval/userfunc.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -43,6 +45,106 @@
#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
+enum {
+ /// In the NFA engine: how many braces are allowed.
+ /// TODO(RE): Use dynamic memory allocation instead of static, like here
+ NFA_MAX_BRACES = 20,
+};
+
+enum {
+ /// In the NFA engine: how many states are allowed.
+ NFA_MAX_STATES = 100000,
+ NFA_TOO_EXPENSIVE = -1,
+};
+
+/// Which regexp engine to use? Needed for vim_regcomp().
+/// Must match with 'regexpengine'.
+enum {
+ AUTOMATIC_ENGINE = 0,
+ BACKTRACKING_ENGINE = 1,
+ NFA_ENGINE = 2,
+};
+
+/// Structure returned by vim_regcomp() to pass on to vim_regexec().
+/// This is the general structure. For the actual matcher, two specific
+/// structures are used. See code below.
+struct regprog {
+ regengine_T *engine;
+ unsigned regflags;
+ unsigned re_engine; ///< Automatic, backtracking or NFA engine.
+ unsigned re_flags; ///< Second argument for vim_regcomp().
+ bool re_in_use; ///< prog is being executed
+};
+
+/// Structure used by the back track matcher.
+/// These fields are only to be used in regexp.c!
+/// See regexp.c for an explanation.
+typedef struct {
+ // These four members implement regprog_T.
+ regengine_T *engine;
+ unsigned regflags;
+ unsigned re_engine;
+ unsigned re_flags;
+ bool re_in_use;
+
+ int regstart;
+ uint8_t reganch;
+ uint8_t *regmust;
+ int regmlen;
+ uint8_t reghasz;
+ uint8_t program[];
+} bt_regprog_T;
+
+/// Structure representing a NFA state.
+/// An NFA state may have no outgoing edge, when it is a NFA_MATCH state.
+typedef struct nfa_state nfa_state_T;
+struct nfa_state {
+ int c;
+ nfa_state_T *out;
+ nfa_state_T *out1;
+ int id;
+ int lastlist[2]; ///< 0: normal, 1: recursive
+ int val;
+};
+
+/// Structure used by the NFA matcher.
+typedef struct {
+ // These four members implement regprog_T.
+ regengine_T *engine;
+ unsigned regflags;
+ unsigned re_engine;
+ unsigned re_flags;
+ bool re_in_use;
+
+ nfa_state_T *start; ///< points into state[]
+
+ int reganch; ///< pattern starts with ^
+ int regstart; ///< char at start of pattern
+ uint8_t *match_text; ///< plain text to match with
+
+ int has_zend; ///< pattern contains \ze
+ int has_backref; ///< pattern contains \1 .. \9
+ int reghasz;
+ char *pattern;
+ int nsubexp; ///< number of ()
+ int nstate;
+ nfa_state_T state[];
+} nfa_regprog_T;
+
+struct regengine {
+ /// bt_regcomp or nfa_regcomp
+ regprog_T *(*regcomp)(uint8_t *, int);
+ /// bt_regfree or nfa_regfree
+ void (*regfree)(regprog_T *);
+ /// bt_regexec_nl or nfa_regexec_nl
+ int (*regexec_nl)(regmatch_T *, uint8_t *, colnr_T, bool);
+ /// bt_regexec_mult or nfa_regexec_mult
+ int (*regexec_multi)(regmmatch_T *, win_T *, buf_T *, linenr_T, colnr_T, proftime_T *, int *);
+#ifdef REGEXP_DEBUG
+ uint8_t *expr;
+#endif
+};
+
// Structure used to save the current input state, when it needs to be
// restored after trying a match. Used by reg_save() and reg_restore().
// Also stores the length of "backpos".
@@ -1263,6 +1365,10 @@ static bool reg_match_visual(void)
top = curbuf->b_visual.vi_end;
bot = curbuf->b_visual.vi_start;
}
+ // a substitute command may have removed some lines
+ if (bot.lnum > curbuf->b_ml.ml_line_count) {
+ bot.lnum = curbuf->b_ml.ml_line_count;
+ }
mode = curbuf->b_visual.vi_mode;
curswant = curbuf->b_visual.vi_curswant;
}
@@ -5363,9 +5469,9 @@ static bool reg_save_equal(const regsave_T *save)
// After a failed match restore the sub-expressions.
#define restore_se(savep, posp, pp) { \
- if (REG_MULTI) /* NOLINT(readability/braces) */ \
+ if (REG_MULTI) \
*(posp) = (savep)->se_u.pos; \
- else /* NOLINT */ \
+ else \
*(pp) = (savep)->se_u.ptr; }
// Tentatively set the sub-expression start to the current position (after
@@ -5866,8 +5972,8 @@ static bool regmatch(uint8_t *scan, const proftime_T *tm, int *timed_out)
#ifdef REGEXP_DEBUG
if (scan != NULL && regnarrate) {
- os_errmsg((char *)regprop(scan));
- os_errmsg("(\n");
+ fprintf(stderr, "%s", (char *)regprop(scan));
+ fprintf(stderr, "%s", "(\n");
}
#endif
@@ -5893,18 +5999,18 @@ static bool regmatch(uint8_t *scan, const proftime_T *tm, int *timed_out)
#ifdef REGEXP_DEBUG
if (regnarrate) {
- os_errmsg((char *)regprop(scan));
- os_errmsg("...\n");
+ fprintf(stderr, "%s", (char *)regprop(scan));
+ fprintf(stderr, "%s", "...\n");
if (re_extmatch_in != NULL) {
int i;
- os_errmsg(_("External submatches:\n"));
+ fprintf(stderr, _("External submatches:\n"));
for (i = 0; i < NSUBEXP; i++) {
- os_errmsg(" \"");
+ fprintf(stderr, "%s", " \"");
if (re_extmatch_in->matches[i] != NULL) {
- os_errmsg((char *)re_extmatch_in->matches[i]);
+ fprintf(stderr, "%s", (char *)re_extmatch_in->matches[i]);
}
- os_errmsg("\"\n");
+ fprintf(stderr, "%s", "\"\n");
}
}
}
@@ -6326,15 +6432,33 @@ static bool regmatch(uint8_t *scan, const proftime_T *tm, int *timed_out)
break;
case ANYOF:
- case ANYBUT:
+ case ANYBUT: {
+ uint8_t *q = OPERAND(scan);
+
if (c == NUL) {
status = RA_NOMATCH;
- } else if ((cstrchr((char *)OPERAND(scan), c) == NULL) == (op == ANYOF)) {
+ } else if ((cstrchr((char *)q, c) == NULL) == (op == ANYOF)) {
status = RA_NOMATCH;
- } else {
- ADVANCE_REGINPUT();
+ } else { // Check following combining characters
+ int len = utfc_ptr2len((char *)q) - utf_ptr2len((char *)q);
+
+ rex.input += utf_ptr2len((char *)rex.input);
+ q += utf_ptr2len((char *)q);
+
+ if (len == 0) {
+ break;
+ }
+
+ for (int i = 0; i < len; i++) {
+ if (q[i] != rex.input[i]) {
+ status = RA_NOMATCH;
+ break;
+ }
+ }
+ rex.input += len;
}
break;
+ }
case MULTIBYTECODE: {
int i, len;
@@ -6380,7 +6504,7 @@ static bool regmatch(uint8_t *scan, const proftime_T *tm, int *timed_out)
case RE_COMPOSING:
// Skip composing characters.
while (utf_iscomposing(utf_ptr2char((char *)rex.input))) {
- MB_CPTR_ADV(rex.input);
+ rex.input += utf_ptr2len((char *)rex.input);
}
break;
@@ -8688,9 +8812,9 @@ static void nfa_emit_equi_class(int c)
case 0x1eb2:
case 0x1eb4:
case 0x1eb6:
- EMIT2('A') EMIT2(A_grave) EMIT2(A_acute) // NOLINT(whitespace/cast)
- EMIT2(A_circumflex) EMIT2(A_virguilla) // NOLINT(whitespace/cast)
- EMIT2(A_diaeresis) EMIT2(A_ring) // NOLINT(whitespace/cast)
+ EMIT2('A') EMIT2(A_grave) EMIT2(A_acute)
+ EMIT2(A_circumflex) EMIT2(A_virguilla)
+ EMIT2(A_diaeresis) EMIT2(A_ring)
EMIT2(0x100) EMIT2(0x102) EMIT2(0x104)
EMIT2(0x1cd) EMIT2(0x1de) EMIT2(0x1e0)
EMIT2(0x1fa) EMIT2(0x200) EMIT2(0x202)
@@ -8769,8 +8893,8 @@ static void nfa_emit_equi_class(int c)
case 0x1ec2:
case 0x1ec4:
case 0x1ec6:
- EMIT2('E') EMIT2(E_grave) EMIT2(E_acute) // NOLINT(whitespace/cast)
- EMIT2(E_circumflex) EMIT2(E_diaeresis) // NOLINT(whitespace/cast)
+ EMIT2('E') EMIT2(E_grave) EMIT2(E_acute)
+ EMIT2(E_circumflex) EMIT2(E_diaeresis)
EMIT2(0x112) EMIT2(0x114) EMIT2(0x116)
EMIT2(0x118) EMIT2(0x11a) EMIT2(0x204)
EMIT2(0x206) EMIT2(0x228) EMIT2(0x246)
@@ -8838,8 +8962,8 @@ static void nfa_emit_equi_class(int c)
case 0x1e2e:
case 0x1ec8:
case 0x1eca:
- EMIT2('I') EMIT2(I_grave) EMIT2(I_acute) // NOLINT(whitespace/cast)
- EMIT2(I_circumflex) EMIT2(I_diaeresis) // NOLINT(whitespace/cast)
+ EMIT2('I') EMIT2(I_grave) EMIT2(I_acute)
+ EMIT2(I_circumflex) EMIT2(I_diaeresis)
EMIT2(0x128) EMIT2(0x12a) EMIT2(0x12c)
EMIT2(0x12e) EMIT2(0x130) EMIT2(0x197)
EMIT2(0x1cf) EMIT2(0x208) EMIT2(0x20a)
@@ -8948,9 +9072,9 @@ static void nfa_emit_equi_class(int c)
case 0x1ede:
case 0x1ee0:
case 0x1ee2:
- EMIT2('O') EMIT2(O_grave) EMIT2(O_acute) // NOLINT(whitespace/cast)
- EMIT2(O_circumflex) EMIT2(O_virguilla) // NOLINT(whitespace/cast)
- EMIT2(O_diaeresis) EMIT2(O_slash) // NOLINT(whitespace/cast)
+ EMIT2('O') EMIT2(O_grave) EMIT2(O_acute)
+ EMIT2(O_circumflex) EMIT2(O_virguilla)
+ EMIT2(O_diaeresis) EMIT2(O_slash)
EMIT2(0x14c) EMIT2(0x14e) EMIT2(0x150)
EMIT2(0x19f) EMIT2(0x1a0) EMIT2(0x1d1)
EMIT2(0x1ea) EMIT2(0x1ec) EMIT2(0x1fe)
@@ -9065,8 +9189,8 @@ static void nfa_emit_equi_class(int c)
case 0x1eec:
case 0x1eee:
case 0x1ef0:
- EMIT2('U') EMIT2(U_grave) EMIT2(U_acute) // NOLINT(whitespace/cast)
- EMIT2(U_diaeresis) EMIT2(U_circumflex) // NOLINT(whitespace/cast)
+ EMIT2('U') EMIT2(U_grave) EMIT2(U_acute)
+ EMIT2(U_diaeresis) EMIT2(U_circumflex)
EMIT2(0x168) EMIT2(0x16a)
EMIT2(0x16c) EMIT2(0x16e) EMIT2(0x170)
EMIT2(0x172) EMIT2(0x1af) EMIT2(0x1d3)
@@ -9169,9 +9293,9 @@ static void nfa_emit_equi_class(int c)
case 0x1eb5:
case 0x1eb7:
case 0x2c65:
- EMIT2('a') EMIT2(a_grave) EMIT2(a_acute) // NOLINT(whitespace/cast)
- EMIT2(a_circumflex) EMIT2(a_virguilla) // NOLINT(whitespace/cast)
- EMIT2(a_diaeresis) EMIT2(a_ring) // NOLINT(whitespace/cast)
+ EMIT2('a') EMIT2(a_grave) EMIT2(a_acute)
+ EMIT2(a_circumflex) EMIT2(a_virguilla)
+ EMIT2(a_diaeresis) EMIT2(a_ring)
EMIT2(0x101) EMIT2(0x103) EMIT2(0x105)
EMIT2(0x1ce) EMIT2(0x1df) EMIT2(0x1e1)
EMIT2(0x1fb) EMIT2(0x201) EMIT2(0x203)
@@ -9258,8 +9382,8 @@ static void nfa_emit_equi_class(int c)
case 0x1ec3:
case 0x1ec5:
case 0x1ec7:
- EMIT2('e') EMIT2(e_grave) EMIT2(e_acute) // NOLINT(whitespace/cast)
- EMIT2(e_circumflex) EMIT2(e_diaeresis) // NOLINT(whitespace/cast)
+ EMIT2('e') EMIT2(e_grave) EMIT2(e_acute)
+ EMIT2(e_circumflex) EMIT2(e_diaeresis)
EMIT2(0x113) EMIT2(0x115)
EMIT2(0x117) EMIT2(0x119) EMIT2(0x11b)
EMIT2(0x205) EMIT2(0x207) EMIT2(0x229)
@@ -9334,8 +9458,8 @@ static void nfa_emit_equi_class(int c)
case 0x1e2f:
case 0x1ec9:
case 0x1ecb:
- EMIT2('i') EMIT2(i_grave) EMIT2(i_acute) // NOLINT(whitespace/cast)
- EMIT2(i_circumflex) EMIT2(i_diaeresis) // NOLINT(whitespace/cast)
+ EMIT2('i') EMIT2(i_grave) EMIT2(i_acute)
+ EMIT2(i_circumflex) EMIT2(i_diaeresis)
EMIT2(0x129) EMIT2(0x12b) EMIT2(0x12d)
EMIT2(0x12f) EMIT2(0x1d0) EMIT2(0x209)
EMIT2(0x20b) EMIT2(0x268) EMIT2(0x1d96)
@@ -9451,9 +9575,9 @@ static void nfa_emit_equi_class(int c)
case 0x1edf:
case 0x1ee1:
case 0x1ee3:
- EMIT2('o') EMIT2(o_grave) EMIT2(o_acute) // NOLINT(whitespace/cast)
- EMIT2(o_circumflex) EMIT2(o_virguilla) // NOLINT(whitespace/cast)
- EMIT2(o_diaeresis) EMIT2(o_slash) // NOLINT(whitespace/cast)
+ EMIT2('o') EMIT2(o_grave) EMIT2(o_acute)
+ EMIT2(o_circumflex) EMIT2(o_virguilla)
+ EMIT2(o_diaeresis) EMIT2(o_slash)
EMIT2(0x14d) EMIT2(0x14f) EMIT2(0x151)
EMIT2(0x1a1) EMIT2(0x1d2) EMIT2(0x1eb)
EMIT2(0x1ed) EMIT2(0x1ff) EMIT2(0x20d)
@@ -9582,8 +9706,8 @@ static void nfa_emit_equi_class(int c)
case 0x1eed:
case 0x1eef:
case 0x1ef1:
- EMIT2('u') EMIT2(u_grave) EMIT2(u_acute) // NOLINT(whitespace/cast)
- EMIT2(u_circumflex) EMIT2(u_diaeresis) // NOLINT(whitespace/cast)
+ EMIT2('u') EMIT2(u_grave) EMIT2(u_acute)
+ EMIT2(u_circumflex) EMIT2(u_diaeresis)
EMIT2(0x169) EMIT2(0x16b)
EMIT2(0x16d) EMIT2(0x16f) EMIT2(0x171)
EMIT2(0x173) EMIT2(0x1d6) EMIT2(0x1d8)
@@ -9636,7 +9760,7 @@ static void nfa_emit_equi_class(int c)
case 0x1ef5:
case 0x1ef7:
case 0x1ef9:
- EMIT2('y') EMIT2(y_acute) EMIT2(y_diaeresis) // NOLINT(whitespace/cast)
+ EMIT2('y') EMIT2(y_acute) EMIT2(y_diaeresis)
EMIT2(0x177) EMIT2(0x1b4) EMIT2(0x233) EMIT2(0x24f)
EMIT2(0x1e8f) EMIT2(0x1e99) EMIT2(0x1ef3)
EMIT2(0x1ef5) EMIT2(0x1ef7) EMIT2(0x1ef9)
@@ -9841,7 +9965,7 @@ static int nfa_regatom(void)
emsg(_(e_nopresub));
return FAIL;
}
- for (lp = (uint8_t *)reg_prev_sub; *lp != NUL; MB_CPTR_ADV(lp)) {
+ for (lp = (uint8_t *)reg_prev_sub; *lp != NUL; lp += utf_ptr2len((char *)lp)) {
EMIT(utf_ptr2char((char *)lp));
if (lp != (uint8_t *)reg_prev_sub) {
EMIT(NFA_CONCAT);
@@ -10348,13 +10472,39 @@ collection:
} else {
if (got_coll_char == true && startc == 0) {
EMIT(0x0a);
+ EMIT(NFA_CONCAT);
} else {
EMIT(startc);
+ if (utf_ptr2len(regparse) == utfc_ptr2len(regparse)) {
+ EMIT(NFA_CONCAT);
+ }
}
- EMIT(NFA_CONCAT);
}
}
+ int plen;
+ if (utf_ptr2len(regparse) != (plen = utfc_ptr2len(regparse))) {
+ int i = utf_ptr2len(regparse);
+
+ c = utf_ptr2char(regparse + i);
+
+ // Add composing characters
+ while (true) {
+ if (c == 0) {
+ // \x00 is translated to \x0a, start at \x01.
+ EMIT(1);
+ } else {
+ EMIT(c);
+ }
+ EMIT(NFA_CONCAT);
+ if ((i += utf_char2len(c)) >= plen) {
+ break;
+ }
+ c = utf_ptr2char(regparse + i);
+ }
+ EMIT(NFA_COMPOSING);
+ EMIT(NFA_CONCAT);
+ }
MB_PTR_ADV(regparse);
} // while (p < endp)
@@ -14403,6 +14553,78 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *subm
state = t->state->out;
result_if_matched = (t->state->c == NFA_START_COLL);
while (true) {
+ if (state->c == NFA_COMPOSING) {
+ int mc = curc;
+ int len = 0;
+ nfa_state_T *end;
+ nfa_state_T *sta;
+ int cchars[MAX_MCO];
+ int ccount = 0;
+ int j;
+
+ sta = t->state->out->out;
+ if (utf_iscomposing(sta->c)) {
+ // Only match composing character(s), ignore base
+ // character. Used for ".{composing}" and "{composing}"
+ // (no preceding character).
+ len += utf_char2len(mc);
+ }
+ if (rex.reg_icombine && len == 0) {
+ // If \Z was present, then ignore composing characters.
+ // When ignoring the base character this always matches.
+ if (sta->c != curc) {
+ result = FAIL;
+ } else {
+ result = OK;
+ }
+ while (sta->c != NFA_END_COMPOSING) {
+ sta = sta->out;
+ }
+ }
+ // Check base character matches first, unless ignored.
+ else if (len > 0 || mc == sta->c) {
+ if (len == 0) {
+ len += utf_char2len(mc);
+ sta = sta->out;
+ }
+
+ // We don't care about the order of composing characters.
+ // Get them into cchars[] first.
+ while (len < clen) {
+ mc = utf_ptr2char((char *)rex.input + len);
+ cchars[ccount++] = mc;
+ len += utf_char2len(mc);
+ if (ccount == MAX_MCO) {
+ break;
+ }
+ }
+
+ // Check that each composing char in the pattern matches a
+ // composing char in the text. We do not check if all
+ // composing chars are matched.
+ result = OK;
+ while (sta->c != NFA_END_COMPOSING) {
+ for (j = 0; j < ccount; j++) {
+ if (cchars[j] == sta->c) {
+ break;
+ }
+ }
+ if (j == ccount) {
+ result = FAIL;
+ break;
+ }
+ sta = sta->out;
+ }
+ } else {
+ result = FAIL;
+ }
+
+ if (t->state->out->out1->c == NFA_END_COMPOSING) {
+ end = t->state->out->out1;
+ ADD_STATE_IF_MATCH(end);
+ }
+ break;
+ }
if (state->c == NFA_END_COLL) {
result = !result_if_matched;
break;
@@ -15545,6 +15767,9 @@ static regengine_T bt_regengine = {
bt_regfree,
bt_regexec_nl,
bt_regexec_multi,
+#ifdef REGEXP_DEBUG
+ "",
+#endif
};
static regengine_T nfa_regengine = {
@@ -15552,6 +15777,9 @@ static regengine_T nfa_regengine = {
nfa_regfree,
nfa_regexec_nl,
nfa_regexec_multi,
+#ifdef REGEXP_DEBUG
+ "",
+#endif
};
// Which regexp engine to use? Needed for vim_regcomp().
diff --git a/src/nvim/regexp.h b/src/nvim/regexp.h
index 447f4860a9..de4e5ded9c 100644
--- a/src/nvim/regexp.h
+++ b/src/nvim/regexp.h
@@ -1,8 +1,8 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
+#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
-#include "nvim/regexp_defs.h" // IWYU pragma: export
+#include "nvim/regexp_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
// Second argument for vim_regcomp().
diff --git a/src/nvim/regexp_defs.h b/src/nvim/regexp_defs.h
index 079f3b6929..b8e87d069d 100644
--- a/src/nvim/regexp_defs.h
+++ b/src/nvim/regexp_defs.h
@@ -15,51 +15,15 @@
#include "nvim/pos_defs.h"
#include "nvim/types_defs.h"
-/// Used for "magic_overruled".
-typedef enum {
- OPTION_MAGIC_NOT_SET, ///< p_magic not overruled
- OPTION_MAGIC_ON, ///< magic on inside regexp
- OPTION_MAGIC_OFF, ///< magic off inside regexp
-} optmagic_T;
-
-/// Magicness of a pattern, used by regexp code.
-/// The order and values matter:
-/// magic <= MAGIC_OFF includes MAGIC_NONE
-/// magic >= MAGIC_ON includes MAGIC_ALL
-typedef enum {
- MAGIC_NONE = 1, ///< "\V" very unmagic
- MAGIC_OFF = 2, ///< "\M" or 'magic' off
- MAGIC_ON = 3, ///< "\m" or 'magic'
- MAGIC_ALL = 4, ///< "\v" very magic
-} magic_T;
-
-/// The number of sub-matches is limited to 10.
-/// The first one (index 0) is the whole match, referenced with "\0".
-/// The second one (index 1) is the first sub-match, referenced with "\1".
-/// This goes up to the tenth (index 9), referenced with "\9".
-enum { NSUBEXP = 10, };
-
-/// In the NFA engine: how many braces are allowed.
-/// TODO(RE): Use dynamic memory allocation instead of static, like here
-enum { NFA_MAX_BRACES = 20, };
-
-/// In the NFA engine: how many states are allowed.
enum {
- NFA_MAX_STATES = 100000,
- NFA_TOO_EXPENSIVE = -1,
-};
-
-/// Which regexp engine to use? Needed for vim_regcomp().
-/// Must match with 'regexpengine'.
-enum {
- AUTOMATIC_ENGINE = 0,
- BACKTRACKING_ENGINE = 1,
- NFA_ENGINE = 2,
+ /// The number of sub-matches is limited to 10.
+ /// The first one (index 0) is the whole match, referenced with "\0".
+ /// The second one (index 1) is the first sub-match, referenced with "\1".
+ /// This goes up to the tenth (index 9), referenced with "\9".
+ NSUBEXP = 10,
};
typedef struct regengine regengine_T;
-typedef struct regprog regprog_T;
-typedef struct reg_extmatch reg_extmatch_T;
/// Structure to be used for multi-line matching.
/// Sub-match "no" starts in line "startpos[no].lnum" column "startpos[no].col"
@@ -77,73 +41,23 @@ typedef struct {
colnr_T rmm_maxcol; ///< when not zero: maximum column
} regmmatch_T;
-#include "nvim/buffer_defs.h"
-
-/// Structure returned by vim_regcomp() to pass on to vim_regexec().
-/// This is the general structure. For the actual matcher, two specific
-/// structures are used. See code below.
-struct regprog {
- regengine_T *engine;
- unsigned regflags;
- unsigned re_engine; ///< Automatic, backtracking or NFA engine.
- unsigned re_flags; ///< Second argument for vim_regcomp().
- bool re_in_use; ///< prog is being executed
-};
-
-/// Structure used by the back track matcher.
-/// These fields are only to be used in regexp.c!
-/// See regexp.c for an explanation.
-typedef struct {
- // These four members implement regprog_T.
- regengine_T *engine;
- unsigned regflags;
- unsigned re_engine;
- unsigned re_flags;
- bool re_in_use;
-
- int regstart;
- uint8_t reganch;
- uint8_t *regmust;
- int regmlen;
- uint8_t reghasz;
- uint8_t program[];
-} bt_regprog_T;
-
-/// Structure representing a NFA state.
-/// An NFA state may have no outgoing edge, when it is a NFA_MATCH state.
-typedef struct nfa_state nfa_state_T;
-struct nfa_state {
- int c;
- nfa_state_T *out;
- nfa_state_T *out1;
- int id;
- int lastlist[2]; ///< 0: normal, 1: recursive
- int val;
-};
-
-/// Structure used by the NFA matcher.
-typedef struct {
- // These four members implement regprog_T.
- regengine_T *engine;
- unsigned regflags;
- unsigned re_engine;
- unsigned re_flags;
- bool re_in_use;
-
- nfa_state_T *start; ///< points into state[]
-
- int reganch; ///< pattern starts with ^
- int regstart; ///< char at start of pattern
- uint8_t *match_text; ///< plain text to match with
+/// Used for "magic_overruled".
+typedef enum {
+ OPTION_MAGIC_NOT_SET, ///< p_magic not overruled
+ OPTION_MAGIC_ON, ///< magic on inside regexp
+ OPTION_MAGIC_OFF, ///< magic off inside regexp
+} optmagic_T;
- int has_zend; ///< pattern contains \ze
- int has_backref; ///< pattern contains \1 .. \9
- int reghasz;
- char *pattern;
- int nsubexp; ///< number of ()
- int nstate;
- nfa_state_T state[];
-} nfa_regprog_T;
+/// Magicness of a pattern, used by regexp code.
+/// The order and values matter:
+/// magic <= MAGIC_OFF includes MAGIC_NONE
+/// magic >= MAGIC_ON includes MAGIC_ALL
+typedef enum {
+ MAGIC_NONE = 1, ///< "\V" very unmagic
+ MAGIC_OFF = 2, ///< "\M" or 'magic' off
+ MAGIC_ON = 3, ///< "\m" or 'magic'
+ MAGIC_ALL = 4, ///< "\v" very magic
+} magic_T;
/// Structure to be used for single-line matching.
/// Sub-match "no" starts at "startp[no]" and ends just before "endp[no]".
@@ -160,22 +74,10 @@ typedef struct {
/// Structure used to store external references: "\z\(\)" to "\z\1".
/// Use a reference count to avoid the need to copy this around. When it goes
/// from 1 to zero the matches need to be freed.
-struct reg_extmatch {
+typedef struct {
int16_t refcnt;
uint8_t *matches[NSUBEXP];
-};
-
-struct regengine {
- /// bt_regcomp or nfa_regcomp
- regprog_T *(*regcomp)(uint8_t *, int);
- /// bt_regfree or nfa_regfree
- void (*regfree)(regprog_T *);
- /// bt_regexec_nl or nfa_regexec_nl
- int (*regexec_nl)(regmatch_T *, uint8_t *, colnr_T, bool);
- /// bt_regexec_mult or nfa_regexec_mult
- int (*regexec_multi)(regmmatch_T *, win_T *, buf_T *, linenr_T, colnr_T, proftime_T *, int *);
- // uint8_t *expr;
-};
+} reg_extmatch_T;
/// Flags used by vim_regsub() and vim_regsub_both()
enum {
diff --git a/src/nvim/runtime.c b/src/nvim/runtime.c
index 38d3942126..76188499e3 100644
--- a/src/nvim/runtime.c
+++ b/src/nvim/runtime.c
@@ -17,6 +17,8 @@
#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
#include "nvim/debugger.h"
@@ -26,16 +28,18 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
-#include "nvim/func_attr.h"
+#include "nvim/ex_eval_defs.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/lua/executor.h"
#include "nvim/macros_defs.h"
#include "nvim/map_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -45,11 +49,13 @@
#include "nvim/os/fs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/stdpaths_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
@@ -303,7 +309,7 @@ static bool source_callback_vim_lua(int num_fnames, char **fnames, bool all, voi
for (int i = 0; i < num_fnames; i++) {
if (path_with_extension(fnames[i], "vim")) {
- (void)do_source(fnames[i], false, DOSO_NONE, cookie);
+ do_source(fnames[i], false, DOSO_NONE, cookie);
did_one = true;
if (!all) {
return true;
@@ -313,7 +319,7 @@ static bool source_callback_vim_lua(int num_fnames, char **fnames, bool all, voi
for (int i = 0; i < num_fnames; i++) {
if (path_with_extension(fnames[i], "lua")) {
- (void)do_source(fnames[i], false, DOSO_NONE, cookie);
+ do_source(fnames[i], false, DOSO_NONE, cookie);
did_one = true;
if (!all) {
return true;
@@ -337,7 +343,7 @@ static bool source_callback(int num_fnames, char **fnames, bool all, void *cooki
for (int i = 0; i < num_fnames; i++) {
if (!path_with_extension(fnames[i], "vim")
&& !path_with_extension(fnames[i], "lua")) {
- (void)do_source(fnames[i], false, DOSO_NONE, cookie);
+ do_source(fnames[i], false, DOSO_NONE, cookie);
did_one = true;
if (!all) {
return true;
@@ -568,31 +574,31 @@ static int do_in_cached_path(char *name, int flags, DoInRuntimepathCB callback,
return did_one ? OK : FAIL;
}
-Array runtime_inspect(void)
+Array runtime_inspect(Arena *arena)
{
RuntimeSearchPath path = runtime_search_path;
- Array rv = ARRAY_DICT_INIT;
+ Array rv = arena_array(arena, kv_size(path));
for (size_t i = 0; i < kv_size(path); i++) {
SearchPathItem *item = &kv_A(path, i);
- Array entry = ARRAY_DICT_INIT;
- ADD(entry, CSTR_TO_OBJ(item->path));
- ADD(entry, BOOLEAN_OBJ(item->after));
+ Array entry = arena_array(arena, 3);
+ ADD_C(entry, CSTR_AS_OBJ(item->path));
+ ADD_C(entry, BOOLEAN_OBJ(item->after));
if (item->has_lua != kNone) {
- ADD(entry, BOOLEAN_OBJ(item->has_lua == kTrue));
+ ADD_C(entry, BOOLEAN_OBJ(item->has_lua == kTrue));
}
- ADD(rv, ARRAY_OBJ(entry));
+ ADD_C(rv, ARRAY_OBJ(entry));
}
return rv;
}
-ArrayOf(String) runtime_get_named(bool lua, Array pat, bool all)
+ArrayOf(String) runtime_get_named(bool lua, Array pat, bool all, Arena *arena)
{
int ref;
RuntimeSearchPath path = runtime_search_path_get_cached(&ref);
static char buf[MAXPATHL];
- ArrayOf(String) rv = runtime_get_named_common(lua, pat, all, path, buf, sizeof buf);
+ ArrayOf(String) rv = runtime_get_named_common(lua, pat, all, path, buf, sizeof buf, arena);
runtime_search_path_unref(path, &ref);
return rv;
@@ -604,15 +610,16 @@ ArrayOf(String) runtime_get_named_thread(bool lua, Array pat, bool all)
uv_mutex_lock(&runtime_search_path_mutex);
static char buf[MAXPATHL];
ArrayOf(String) rv = runtime_get_named_common(lua, pat, all, runtime_search_path_thread,
- buf, sizeof buf);
+ buf, sizeof buf, NULL);
uv_mutex_unlock(&runtime_search_path_mutex);
return rv;
}
static ArrayOf(String) runtime_get_named_common(bool lua, Array pat, bool all,
- RuntimeSearchPath path, char *buf, size_t buf_len)
+ RuntimeSearchPath path, char *buf, size_t buf_len,
+ Arena *arena)
{
- ArrayOf(String) rv = ARRAY_DICT_INIT;
+ ArrayOf(String) rv = arena_array(arena, kv_size(path) * pat.size);
for (size_t i = 0; i < kv_size(path); i++) {
SearchPathItem *item = &kv_A(path, i);
if (lua) {
@@ -632,7 +639,7 @@ static 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, CSTR_TO_OBJ(buf));
+ ADD_C(rv, CSTR_TO_ARENA_OBJ(arena, buf));
if (!all) {
goto done;
}
@@ -1062,7 +1069,7 @@ static int add_pack_dir_to_rtp(char *fname, bool is_pack)
xstrlcat(new_rtp, afterdir, new_rtp_capacity);
}
- set_option_value_give_err("rtp", CSTR_AS_OPTVAL(new_rtp), 0);
+ set_option_value_give_err(kOptRuntimepath, CSTR_AS_OPTVAL(new_rtp), 0);
xfree(new_rtp);
retval = OK;
@@ -1085,7 +1092,7 @@ static int load_pack_plugin(bool opt, char *fname)
size_t len = strlen(ffname) + sizeof(plugpat);
char *pat = xmallocz(len);
- vim_snprintf(pat, len, plugpat, ffname); // NOLINT
+ vim_snprintf(pat, len, plugpat, ffname);
gen_expand_wildcards_and_cb(1, &pat, EW_FILE, true, source_callback_vim_lua, NULL);
char *cmd = xstrdup("g:did_load_filetypes");
@@ -1773,7 +1780,7 @@ freeall:
static void cmd_source(char *fname, exarg_T *eap)
{
if (eap != NULL && *fname == NUL) {
- cmd_source_buffer(eap);
+ cmd_source_buffer(eap, false);
} else if (eap != NULL && eap->forceit) {
// ":source!": read Normal mode commands
// Need to execute the commands directly. This is required at least
@@ -1804,7 +1811,7 @@ void ex_options(exarg_T *eap)
bool multi_mods = 0;
buf[0] = NUL;
- (void)add_win_cmd_modifiers(buf, &cmdmod, &multi_mods);
+ add_win_cmd_modifiers(buf, &cmdmod, &multi_mods);
os_setenv("OPTWIN_CMD", buf, 1);
cmd_source(SYS_OPTWIN_FILE, NULL);
@@ -1845,7 +1852,7 @@ static FILE *fopen_noinh_readbin(char *filename)
return NULL;
}
- (void)os_set_cloexec(fd_tmp);
+ os_set_cloexec(fd_tmp);
return fdopen(fd_tmp, READBIN);
}
@@ -1983,7 +1990,7 @@ static int source_using_linegetter(void *cookie, LineGetter fgetline, const char
return retval;
}
-static void cmd_source_buffer(const exarg_T *const eap)
+void cmd_source_buffer(const exarg_T *const eap, bool ex_lua)
FUNC_ATTR_NONNULL_ALL
{
if (curbuf == NULL) {
@@ -2006,9 +2013,10 @@ static void cmd_source_buffer(const exarg_T *const eap)
.buf = ga.ga_data,
.offset = 0,
};
- if (strequal(curbuf->b_p_ft, "lua")
+ if (ex_lua || strequal(curbuf->b_p_ft, "lua")
|| (curbuf->b_fname && path_with_extension(curbuf->b_fname, "lua"))) {
- nlua_source_using_linegetter(get_str_line, (void *)&cookie, ":source (no file)");
+ char *name = ex_lua ? ":{range}lua" : ":source (no file)";
+ nlua_source_using_linegetter(get_str_line, (void *)&cookie, name);
} else {
source_using_linegetter((void *)&cookie, get_str_line, ":source (no file)");
}
@@ -2623,7 +2631,7 @@ static char *get_one_sourceline(struct source_cookie *sp)
int c;
char *buf;
#ifdef USE_CRNL
- int has_cr; // CR-LF found
+ bool has_cr; // CR-LF found
#endif
bool have_read = false;
@@ -2758,7 +2766,7 @@ void ex_finish(exarg_T *eap)
/// Mark a sourced file as finished. Possibly makes the ":finish" pending.
/// Also called for a pending finish at the ":endtry" or after returning from
/// an extra do_cmdline(). "reanimate" is used in the latter case.
-void do_finish(exarg_T *eap, int reanimate)
+void do_finish(exarg_T *eap, bool reanimate)
{
if (reanimate) {
((struct source_cookie *)getline_cookie(eap->getline,
diff --git a/src/nvim/runtime.h b/src/nvim/runtime.h
index 87e4436618..7312b62526 100644
--- a/src/nvim/runtime.h
+++ b/src/nvim/runtime.h
@@ -9,7 +9,7 @@
#include "nvim/garray_defs.h"
#include "nvim/option_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
-#include "nvim/runtime_defs.h" // IWYU pragma: export
+#include "nvim/runtime_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
/// Stack of execution contexts. Each entry is an estack_T.
diff --git a/src/nvim/runtime_defs.h b/src/nvim/runtime_defs.h
index 169cadfb94..7029e8be66 100644
--- a/src/nvim/runtime_defs.h
+++ b/src/nvim/runtime_defs.h
@@ -3,11 +3,6 @@
#include <stdbool.h>
#include "nvim/autocmd_defs.h"
-#include "nvim/eval/typval_defs.h"
-#include "nvim/ex_eval_defs.h"
-#include "nvim/garray_defs.h"
-#include "nvim/pos_defs.h"
-#include "nvim/types_defs.h"
typedef enum {
ETYPE_TOP, ///< toplevel
diff --git a/src/nvim/search.c b/src/nvim/search.c
index 642219c1e0..48e41c290d 100644
--- a/src/nvim/search.c
+++ b/src/nvim/search.c
@@ -10,6 +10,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/change.h"
@@ -20,20 +21,23 @@
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
#include "nvim/ex_cmds.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/indent_c.h"
#include "nvim/insexpand.h"
#include "nvim/macros_defs.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -54,6 +58,7 @@
#include "nvim/strings.h"
#include "nvim/tag.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -92,7 +97,7 @@ static const char e_search_hit_bottom_without_match_for_str[]
// one for other searches. last_idx points to the one that was used the last
// time.
-static struct spat spats[2] = {
+static SearchPattern spats[2] = {
// Last used search pattern
[0] = { NULL, true, false, 0, { '/', false, false, 0 }, NULL },
// Last used substitute pattern
@@ -103,12 +108,12 @@ static int last_idx = 0; // index in spats[] for RE_LAST
static uint8_t lastc[2] = { NUL, NUL }; // last character searched for
static Direction lastcdir = FORWARD; // last direction of character search
-static int last_t_cmd = true; // last search t_cmd
+static bool last_t_cmd = true; // last search t_cmd
static char lastc_bytes[MB_MAXBYTES + 1];
static int lastc_bytelen = 1; // >1 for multi-byte char
// copy of spats[], for keeping the search patterns while executing autocmds
-static struct spat saved_spats[2];
+static SearchPattern saved_spats[2];
static char *saved_mr_pattern = NULL;
static int saved_spats_last_idx = 0;
static bool saved_spats_no_hlsearch = false;
@@ -118,7 +123,7 @@ static char *mr_pattern = NULL;
// Type used by find_pattern_in_path() to remember which included files have
// been searched already.
-typedef struct SearchedFile {
+typedef struct {
FILE *fp; // File pointer
char *name; // Full name of file
linenr_T lnum; // Line we were up to in file
@@ -272,7 +277,7 @@ void restore_search_patterns(void)
set_no_hlsearch(saved_spats_no_hlsearch);
}
-static inline void free_spat(struct spat *const spat)
+static inline void free_spat(SearchPattern *const spat)
{
xfree(spat->pat);
tv_dict_unref(spat->additional_data);
@@ -293,7 +298,7 @@ void free_search_patterns(void)
// copy of spats[RE_SEARCH], for keeping the search patterns while incremental
// searching
-static struct spat saved_last_search_spat;
+static SearchPattern saved_last_search_spat;
static int did_save_last_search_spat = 0;
static int saved_last_idx = 0;
static bool saved_no_hlsearch = false;
@@ -390,7 +395,7 @@ bool pat_has_uppercase(char *pat)
magic_T magic_val = MAGIC_ON;
// get the magicness of the pattern
- (void)skip_regexp_ex(pat, NUL, magic_isset(), NULL, NULL, &magic_val);
+ skip_regexp_ex(pat, NUL, magic_isset(), NULL, NULL, &magic_val);
while (*p != NUL) {
const int l = utfc_ptr2len(p);
@@ -438,7 +443,7 @@ int last_csearch_forward(void)
int last_csearch_until(void)
{
- return last_t_cmd == true;
+ return last_t_cmd;
}
void set_last_csearch(int c, char *s, int len)
@@ -476,7 +481,7 @@ void reset_search_dir(void)
// Set the last search pattern. For ":let @/ =" and ShaDa file.
// Also set the saved search pattern, so that this works in an autocommand.
-void set_last_search_pat(const char *s, int idx, int magic, int setlast)
+void set_last_search_pat(const char *s, int idx, int magic, bool setlast)
{
free_spat(&spats[idx]);
// An empty string means that nothing should be matched.
@@ -523,7 +528,7 @@ void last_pat_prog(regmmatch_T *regmatch)
return;
}
emsg_off++; // So it doesn't beep if bad expr
- (void)search_regcomp("", NULL, 0, last_idx, SEARCH_KEEP, regmatch);
+ search_regcomp("", NULL, 0, last_idx, SEARCH_KEEP, regmatch);
emsg_off--;
}
@@ -1049,7 +1054,7 @@ int do_search(oparg_T *oap, int dirc, int search_delim, char *pat, int count, in
// Save the values for when (options & SEARCH_KEEP) is used.
// (there is no "if ()" around this because gcc wants them initialized)
- struct soffset old_off = spats[0].off;
+ SearchOffset old_off = spats[0].off;
pos = curwin->w_cursor; // start searching at the cursor position
@@ -1497,7 +1502,7 @@ int search_for_exact_line(buf_T *buf, pos_T *pos, Direction dir, char *pat)
/// position of the character, otherwise move to just before the char.
/// Do this "cap->count1" times.
/// Return FAIL or OK.
-int searchc(cmdarg_T *cap, int t_cmd)
+int searchc(cmdarg_T *cap, bool t_cmd)
FUNC_ATTR_NONNULL_ALL
{
int c = cap->nchar; // char to search for
@@ -2520,7 +2525,7 @@ int current_search(int count, bool forward)
/// else from position "cur".
/// "direction" is FORWARD or BACKWARD.
/// Returns true, false or -1 for failure.
-static int is_zero_width(char *pattern, int move, pos_T *cur, Direction direction)
+static int is_zero_width(char *pattern, bool move, pos_T *cur, Direction direction)
{
regmmatch_T regmatch;
int result = -1;
@@ -2576,8 +2581,8 @@ static int is_zero_width(char *pattern, int move, pos_T *cur, Direction directio
return result;
}
-/// return true if line 'lnum' is empty or has white chars only.
-int linewhite(linenr_T lnum)
+/// @return true if line 'lnum' is empty or has white chars only.
+bool linewhite(linenr_T lnum)
{
char *p = skipwhite(ml_get(lnum));
return *p == NUL;
@@ -3192,7 +3197,11 @@ static int fuzzy_match_item_compare(const void *const s1, const void *const s2)
const int idx1 = ((const fuzzyItem_T *)s1)->idx;
const int idx2 = ((const fuzzyItem_T *)s2)->idx;
- return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
+ if (v1 == v2) {
+ return idx1 == idx2 ? 0 : idx1 > idx2 ? 1 : -1;
+ } else {
+ return v1 > v2 ? -1 : 1;
+ }
}
/// Fuzzy search the string "str" in a list of "items" and return the matching
@@ -3431,7 +3440,11 @@ static int fuzzy_match_str_compare(const void *const s1, const void *const s2)
const int idx1 = ((fuzmatch_str_T *)s1)->idx;
const int idx2 = ((fuzmatch_str_T *)s2)->idx;
- return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
+ if (v1 == v2) {
+ return idx1 == idx2 ? 0 : idx1 > idx2 ? 1 : -1;
+ } else {
+ return v1 > v2 ? -1 : 1;
+ }
}
/// Sort fuzzy matches by score
@@ -3460,7 +3473,11 @@ static int fuzzy_match_func_compare(const void *const s1, const void *const s2)
if (*str1 == '<' && *str2 != '<') {
return 1;
}
- return v1 == v2 ? (idx1 - idx2) : v1 > v2 ? -1 : 1;
+ if (v1 == v2) {
+ return idx1 == idx2 ? 0 : idx1 > idx2 ? 1 : -1;
+ } else {
+ return v1 > v2 ? -1 : 1;
+ }
}
/// Sort fuzzy matches of function names by score.
@@ -3559,7 +3576,6 @@ void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool
char *curr_fname = curbuf->b_fname;
char *prev_fname = NULL;
int depth_displayed; // For type==CHECK_PATH
- int already_searched;
char *p;
bool define_matched;
regmatch_T regmatch;
@@ -3645,7 +3661,7 @@ void find_pattern_in_path(char *ptr, Direction dir, size_t len, bool whole, bool
FNAME_EXP|FNAME_INCL|FNAME_REL, 1, p_fname,
NULL);
}
- already_searched = false;
+ bool already_searched = false;
if (new_fname != NULL) {
// Check whether we have already searched in this file
for (i = 0;; i++) {
diff --git a/src/nvim/search.h b/src/nvim/search.h
index 48ca555e7f..09af34d87e 100644
--- a/src/nvim/search.h
+++ b/src/nvim/search.h
@@ -3,67 +3,78 @@
#include <stdbool.h>
#include <stdint.h>
-#include "nvim/buffer_defs.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/normal_defs.h" // IWYU pragma: keep
#include "nvim/os/time_defs.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h"
-#include "nvim/vim_defs.h"
+#include "nvim/vim_defs.h" // IWYU pragma: keep
-// Values for the find_pattern_in_path() function args 'type' and 'action':
-#define FIND_ANY 1
-#define FIND_DEFINE 2
-#define CHECK_PATH 3
+/// Values for the find_pattern_in_path() function args 'type' and 'action':
+enum {
+ FIND_ANY = 1,
+ FIND_DEFINE = 2,
+ CHECK_PATH = 3,
+};
-#define ACTION_SHOW 1
-#define ACTION_GOTO 2
-#define ACTION_SPLIT 3
-#define ACTION_SHOW_ALL 4
-#define ACTION_EXPAND 5
+enum {
+ ACTION_SHOW = 1,
+ ACTION_GOTO = 2,
+ ACTION_SPLIT = 3,
+ ACTION_SHOW_ALL = 4,
+ ACTION_EXPAND = 5,
+};
-// Values for 'options' argument in do_search() and searchit()
-#define SEARCH_REV 0x01 ///< go in reverse of previous dir.
-#define SEARCH_ECHO 0x02 ///< echo the search command and handle options
-#define SEARCH_MSG 0x0c ///< give messages (yes, it's not 0x04)
-#define SEARCH_NFMSG 0x08 ///< give all messages except not found
-#define SEARCH_OPT 0x10 ///< interpret optional flags
-#define SEARCH_HIS 0x20 ///< put search pattern in history
-#define SEARCH_END 0x40 ///< put cursor at end of match
-#define SEARCH_NOOF 0x80 ///< don't add offset to position
-#define SEARCH_START 0x100 ///< start search without col offset
-#define SEARCH_MARK 0x200 ///< set previous context mark
-#define SEARCH_KEEP 0x400 ///< keep previous search pattern
-#define SEARCH_PEEK 0x800 ///< peek for typed char, cancel search
-#define SEARCH_COL 0x1000 ///< start at specified column instead of zero
+/// Values for "options" argument in do_search() and searchit()
+enum {
+ SEARCH_REV = 0x01, ///< go in reverse of previous dir.
+ SEARCH_ECHO = 0x02, ///< echo the search command and handle options
+ SEARCH_MSG = 0x0c, ///< give messages (yes, it's not 0x04)
+ SEARCH_NFMSG = 0x08, ///< give all messages except not found
+ SEARCH_OPT = 0x10, ///< interpret optional flags
+ SEARCH_HIS = 0x20, ///< put search pattern in history
+ SEARCH_END = 0x40, ///< put cursor at end of match
+ SEARCH_NOOF = 0x80, ///< don't add offset to position
+ SEARCH_START = 0x100, ///< start search without col offset
+ SEARCH_MARK = 0x200, ///< set previous context mark
+ SEARCH_KEEP = 0x400, ///< keep previous search pattern
+ SEARCH_PEEK = 0x800, ///< peek for typed char, cancel search
+ SEARCH_COL = 0x1000, ///< start at specified column instead of zero
+};
-// Values for flags argument for findmatchlimit()
-#define FM_BACKWARD 0x01 // search backwards
-#define FM_FORWARD 0x02 // search forwards
-#define FM_BLOCKSTOP 0x04 // stop at start/end of block
-#define FM_SKIPCOMM 0x08 // skip comments
+/// Values for flags argument for findmatchlimit()
+enum {
+ FM_BACKWARD = 0x01, ///< search backwards
+ FM_FORWARD = 0x02, ///< search forwards
+ FM_BLOCKSTOP = 0x04, ///< stop at start/end of block
+ FM_SKIPCOMM = 0x08, ///< skip comments
+};
-// Values for sub_cmd and which_pat argument for search_regcomp()
-// Also used for which_pat argument for searchit()
-#define RE_SEARCH 0 // save/use pat in/from search_pattern
-#define RE_SUBST 1 // save/use pat in/from subst_pattern
-#define RE_BOTH 2 // save pat in both patterns
-#define RE_LAST 2 // use last used pattern if "pat" is NULL
+/// Values for sub_cmd and which_pat argument for search_regcomp()
+/// Also used for which_pat argument for searchit()
+enum {
+ RE_SEARCH = 0, ///< save/use pat in/from search_pattern
+ RE_SUBST = 1, ///< save/use pat in/from subst_pattern
+ RE_BOTH = 2, ///< save pat in both patterns
+ RE_LAST = 2, ///< use last used pattern if "pat" is NULL
+};
// Values for searchcount()
-#define SEARCH_STAT_DEF_TIMEOUT 40
-#define SEARCH_STAT_DEF_MAX_COUNT 99
-#define SEARCH_STAT_BUF_LEN 12
+enum { SEARCH_STAT_DEF_TIMEOUT = 40, };
+enum { SEARCH_STAT_DEF_MAX_COUNT = 99, };
+enum { SEARCH_STAT_BUF_LEN = 12, };
-/// Maximum number of characters that can be fuzzy matched
-#define MAX_FUZZY_MATCHES 256
+enum {
+ /// Maximum number of characters that can be fuzzy matched
+ MAX_FUZZY_MATCHES = 256,
+};
/// Structure containing offset definition for the last search pattern
///
/// @note Only offset for the last search pattern is used, not for the last
/// substitute pattern.
-typedef struct soffset {
+typedef struct {
char dir; ///< Search direction: forward ('/') or backward ('?')
bool line; ///< True if search has line offset.
bool end; ///< True if search sets cursor at the end.
@@ -71,7 +82,7 @@ typedef struct soffset {
} SearchOffset;
/// Structure containing last search pattern and its attributes.
-typedef struct spat {
+typedef struct {
char *pat; ///< The pattern (in allocated memory) or NULL.
bool magic; ///< Magicness of the pattern.
bool no_scs; ///< No smartcase for this pattern.
@@ -88,7 +99,7 @@ typedef struct {
int sa_wrapped; ///< search wrapped around
} searchit_arg_T;
-typedef struct searchstat {
+typedef struct {
int cur; // current position of found words
int cnt; // total count of found words
bool exact_match; // true if matched exactly on specified position
diff --git a/src/nvim/shada.c b/src/nvim/shada.c
index be898142f0..490ab2b050 100644
--- a/src/nvim/shada.c
+++ b/src/nvim/shada.c
@@ -17,40 +17,49 @@
#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/cmdhist.h"
#include "nvim/eval.h"
#include "nvim/eval/decode.h"
#include "nvim/eval/encode.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/macros_defs.h"
#include "nvim/map_defs.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
-#include "nvim/msgpack_rpc/helpers.h"
-#include "nvim/normal.h"
+#include "nvim/normal_defs.h"
#include "nvim/ops.h"
#include "nvim/option.h"
#include "nvim/option_vars.h"
#include "nvim/os/fileio.h"
+#include "nvim/os/fileio_defs.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/time.h"
+#include "nvim/os/time_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
#include "nvim/search.h"
#include "nvim/shada.h"
#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/version.h"
#include "nvim/vim_defs.h"
@@ -347,25 +356,25 @@ typedef struct {
PMap(cstr_t) file_marks; ///< All file marks.
} WriteMergerState;
-struct sd_read_def;
+typedef struct sd_read_def ShaDaReadDef;
/// Function used to close files defined by ShaDaReadDef
-typedef void (*ShaDaReadCloser)(struct sd_read_def *const sd_reader)
+typedef void (*ShaDaReadCloser)(ShaDaReadDef *const sd_reader)
REAL_FATTR_NONNULL_ALL;
/// Function used to read ShaDa files
-typedef ptrdiff_t (*ShaDaFileReader)(struct sd_read_def *const sd_reader,
+typedef ptrdiff_t (*ShaDaFileReader)(ShaDaReadDef *const sd_reader,
void *const dest,
const size_t size)
REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
/// Function used to skip in ShaDa files
-typedef int (*ShaDaFileSkipper)(struct sd_read_def *const sd_reader,
+typedef int (*ShaDaFileSkipper)(ShaDaReadDef *const sd_reader,
const size_t offset)
REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
/// Structure containing necessary pointers for reading ShaDa files
-typedef struct sd_read_def {
+struct sd_read_def {
ShaDaFileReader read; ///< Reader function.
ShaDaReadCloser close; ///< Close function.
ShaDaFileSkipper skip; ///< Function used to skip some bytes.
@@ -374,27 +383,7 @@ typedef struct sd_read_def {
const char *error; ///< Error message in case of error.
uintmax_t fpos; ///< Current position (amount of bytes read since
///< reader structure initialization). May overflow.
-} ShaDaReadDef;
-
-struct sd_write_def;
-
-/// Function used to close files defined by ShaDaWriteDef
-typedef void (*ShaDaWriteCloser)(struct sd_write_def *const sd_writer)
- REAL_FATTR_NONNULL_ALL;
-
-/// Function used to write ShaDa files
-typedef ptrdiff_t (*ShaDaFileWriter)(struct sd_write_def *const sd_writer,
- const void *const src,
- const size_t size)
- REAL_FATTR_NONNULL_ALL REAL_FATTR_WARN_UNUSED_RESULT;
-
-/// Structure containing necessary pointers for writing ShaDa files
-typedef struct sd_write_def {
- ShaDaFileWriter write; ///< Writer function.
- ShaDaWriteCloser close; ///< Close function.
- void *cookie; ///< Data describing object written to.
- const char *error; ///< Error message in case of error.
-} ShaDaWriteDef;
+};
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "shada.c.generated.h"
@@ -626,33 +615,12 @@ static int read_char(ShaDaReadDef *const sd_reader)
return (int)ret;
}
-/// Wrapper for writing to file descriptors
-///
-/// @return -1 or number of bytes written.
-static ptrdiff_t write_file(ShaDaWriteDef *const sd_writer, const void *const dest,
- const size_t size)
- FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
-{
- const ptrdiff_t ret = file_write(sd_writer->cookie, dest, size);
- if (ret < 0) {
- sd_writer->error = os_strerror((int)ret);
- return -1;
- }
- return ret;
-}
-
/// Wrapper for closing file descriptors opened for reading
static void close_sd_reader(ShaDaReadDef *const sd_reader)
FUNC_ATTR_NONNULL_ALL
{
close_file(sd_reader->cookie);
-}
-
-/// Wrapper for closing file descriptors opened for writing
-static void close_sd_writer(ShaDaWriteDef *const sd_writer)
- FUNC_ATTR_NONNULL_ALL
-{
- close_file(sd_writer->cookie);
+ xfree(sd_reader->cookie);
}
/// Wrapper for read that reads to IObuff and ignores bytes read
@@ -721,8 +689,6 @@ static ShaDaReadResult sd_reader_skip(ShaDaReadDef *const sd_reader, const size_
static int open_shada_file_for_reading(const char *const fname, ShaDaReadDef *sd_reader)
FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
{
- int error;
-
*sd_reader = (ShaDaReadDef) {
.read = &read_file,
.close = &close_sd_reader,
@@ -730,9 +696,11 @@ static int open_shada_file_for_reading(const char *const fname, ShaDaReadDef *sd
.error = NULL,
.eof = false,
.fpos = 0,
- .cookie = file_open_new(&error, fname, kFileReadOnly, 0),
+ .cookie = xmalloc(sizeof(FileDescriptor)),
};
- if (sd_reader->cookie == NULL) {
+ int error = file_open(sd_reader->cookie, fname, kFileReadOnly, 0);
+ if (error) {
+ XFREE_CLEAR(sd_reader->cookie);
return error;
}
@@ -742,25 +710,26 @@ static int open_shada_file_for_reading(const char *const fname, ShaDaReadDef *sd
}
/// Wrapper for closing file descriptors
-static void close_file(void *cookie)
+static void close_file(FileDescriptor *cookie)
{
- const int error = file_free(cookie, !!p_fs);
+ const int error = file_close(cookie, !!p_fs);
if (error != 0) {
semsg(_(SERR "System error while closing ShaDa file: %s"),
os_strerror(error));
}
}
-/// Msgpack callback for writing to ShaDaWriteDef*
+/// Msgpack callback for writing to FileDescriptor*
static int msgpack_sd_writer_write(void *data, const char *buf, size_t len)
{
- ShaDaWriteDef *const sd_writer = (ShaDaWriteDef *)data;
- ptrdiff_t written_bytes = sd_writer->write(sd_writer, buf, len);
- if (written_bytes == -1) {
+ FileDescriptor *const sd_writer = (FileDescriptor *)data;
+ const ptrdiff_t ret = file_write(sd_writer, buf, len);
+ if (ret < 0) {
semsg(_(SERR "System error while writing ShaDa file: %s"),
- sd_writer->error);
+ os_strerror((int)ret));
return -1;
}
+
return 0;
}
@@ -997,6 +966,48 @@ static inline void hms_dealloc(HistoryMergerState *const hms_p)
#define HMS_ITER(hms_p, cur_entry, code) \
HMLL_FORALL(&((hms_p)->hmll), cur_entry, code)
+/// Iterate over global variables
+///
+/// @warning No modifications to global variable dictionary must be performed
+/// while iteration is in progress.
+///
+/// @param[in] iter Iterator. Pass NULL to start iteration.
+/// @param[out] name Variable name.
+/// @param[out] rettv Variable value.
+///
+/// @return Pointer that needs to be passed to next `var_shada_iter` invocation
+/// or NULL to indicate that iteration is over.
+static const void *var_shada_iter(const void *const iter, const char **const name, typval_T *rettv,
+ var_flavour_T flavour)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ARG(2, 3)
+{
+ const hashitem_T *hi;
+ const hashitem_T *hifirst = globvarht.ht_array;
+ const size_t hinum = (size_t)globvarht.ht_mask + 1;
+ *name = NULL;
+ if (iter == NULL) {
+ hi = globvarht.ht_array;
+ while ((size_t)(hi - hifirst) < hinum
+ && (HASHITEM_EMPTY(hi)
+ || !(var_flavour(hi->hi_key) & flavour))) {
+ hi++;
+ }
+ if ((size_t)(hi - hifirst) == hinum) {
+ return NULL;
+ }
+ } else {
+ hi = (const hashitem_T *)iter;
+ }
+ *name = TV_DICT_HI2DI(hi)->di_key;
+ tv_copy(&TV_DICT_HI2DI(hi)->di_tv, rettv);
+ while ((size_t)(++hi - hifirst) < hinum) {
+ if (!HASHITEM_EMPTY(hi) && (var_flavour(hi->hi_key) & flavour)) {
+ return hi;
+ }
+ }
+ return NULL;
+}
+
/// Find buffer for given buffer name (cached)
///
/// @param[in,out] fname_bufs Cache containing fname to buffer mapping.
@@ -1118,7 +1129,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
}
HistoryMergerState hms[HIST_COUNT];
if (srni_flags & kSDReadHistory) {
- for (HistoryType i = 0; i < HIST_COUNT; i++) {
+ for (int i = 0; i < HIST_COUNT; i++) {
hms_init(&hms[i], (uint8_t)i, (size_t)p_hi, true, true);
}
}
@@ -1211,7 +1222,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags)
// string is close to useless: you can only use it with :& or :~ and
// that’s all because s//~ is not available until the first call to
// regtilde. Vim was not calling this for some reason.
- (void)regtilde(cur_entry.data.sub_string.sub, magic_isset(), false);
+ regtilde(cur_entry.data.sub_string.sub, magic_isset(), false);
// Do not free shada entry: its allocated memory was saved above.
break;
case kSDItemHistoryEntry:
@@ -1382,7 +1393,7 @@ shada_read_main_cycle_end:
// memory for the history string itself and separator character which
// may be assigned right away.
if (srni_flags & kSDReadHistory) {
- for (HistoryType i = 0; i < HIST_COUNT; i++) {
+ for (int i = 0; i < HIST_COUNT; i++) {
hms_insert_whole_neovim_history(&hms[i]);
clr_history(i);
int *new_hisidx;
@@ -1823,9 +1834,7 @@ static int compare_file_marks(const void *a, const void *b)
const FileMarks *const *const b_fms = b;
return ((*a_fms)->greatest_timestamp == (*b_fms)->greatest_timestamp
? 0
- : ((*a_fms)->greatest_timestamp > (*b_fms)->greatest_timestamp
- ? -1
- : 1));
+ : ((*a_fms)->greatest_timestamp > (*b_fms)->greatest_timestamp ? -1 : 1));
}
/// Parse msgpack object that has given length
@@ -2473,7 +2482,7 @@ static int hist_type2char(const int type)
/// @param[in] sd_reader Structure containing file reader definition. If it is
/// not NULL then contents of this file will be merged
/// with current Neovim runtime.
-static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef *const sd_reader)
+static ShaDaWriteResult shada_write(FileDescriptor *const sd_writer, ShaDaReadDef *const sd_reader)
FUNC_ATTR_NONNULL_ARG(1)
{
ShaDaWriteResult ret = kSDWriteSuccessful;
@@ -2500,7 +2509,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
bool dump_history = false;
// Initialize history merger
- for (HistoryType i = 0; i < HIST_COUNT; i++) {
+ for (int i = 0; i < HIST_COUNT; i++) {
int num_saved = get_shada_parameter(hist_type2char(i));
if (num_saved == -1) {
num_saved = (int)p_hi;
@@ -2605,7 +2614,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
case VAR_LIST: {
list_T *l = vartv.vval.v_list;
int copyID = get_copyID();
- if (!set_ref_in_list(l, copyID, NULL)
+ if (!set_ref_in_list_items(l, copyID, NULL)
&& copyID == l->lv_copyID) {
tv_clear(&vartv);
continue;
@@ -2894,7 +2903,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
#undef PACK_WMS_ARRAY
if (dump_history) {
- for (size_t i = 0; i < HIST_COUNT; i++) {
+ for (int i = 0; i < HIST_COUNT; i++) {
if (dump_one_history[i]) {
hms_insert_whole_neovim_history(&wms->hms[i]);
HMS_ITER(&wms->hms[i], cur_entry, {
@@ -2914,7 +2923,7 @@ static ShaDaWriteResult shada_write(ShaDaWriteDef *const sd_writer, ShaDaReadDef
}
shada_write_exit:
- for (size_t i = 0; i < HIST_COUNT; i++) {
+ for (int i = 0; i < HIST_COUNT; i++) {
if (dump_one_history[i]) {
hms_dealloc(&wms->hms[i]);
}
@@ -2947,12 +2956,9 @@ int shada_write_file(const char *const file, bool nomerge)
char *const fname = shada_filename(file);
char *tempname = NULL;
- ShaDaWriteDef sd_writer = {
- .write = &write_file,
- .close = &close_sd_writer,
- .error = NULL,
- };
+ FileDescriptor sd_writer;
ShaDaReadDef sd_reader = { .close = NULL };
+ bool did_open_writer = false;
if (!nomerge) {
int error;
@@ -2982,8 +2988,8 @@ int shada_write_file(const char *const file, bool nomerge)
// 3: If somebody happened to delete the file after it was opened for
// reading use u=rw permissions.
shada_write_file_open: {}
- sd_writer.cookie = file_open_new(&error, tempname, kFileCreateOnly|kFileNoSymlink, perm);
- if (sd_writer.cookie == NULL) {
+ error = file_open(&sd_writer, tempname, kFileCreateOnly|kFileNoSymlink, perm);
+ if (error) {
if (error == UV_EEXIST || error == UV_ELOOP) {
// File already exists, try another name
char *const wp = tempname + strlen(tempname) - 1;
@@ -3004,6 +3010,8 @@ shada_write_file_open: {}
semsg(_(SERR "System error while opening temporary ShaDa file %s "
"for writing: %s"), tempname, os_strerror(error));
}
+ } else {
+ did_open_writer = true;
}
}
if (nomerge) {
@@ -3026,16 +3034,16 @@ shada_write_file_nomerge: {}
}
*tail = tail_save;
}
- int error;
- sd_writer.cookie = file_open_new(&error, fname, kFileCreate|kFileTruncate,
- 0600);
- if (sd_writer.cookie == NULL) {
+ int error = file_open(&sd_writer, fname, kFileCreate|kFileTruncate, 0600);
+ if (error) {
semsg(_(SERR "System error while opening ShaDa file %s for writing: %s"),
fname, os_strerror(error));
+ } else {
+ did_open_writer = true;
}
}
- if (sd_writer.cookie == NULL) {
+ if (!did_open_writer) {
xfree(fname);
xfree(tempname);
if (sd_reader.cookie != NULL) {
@@ -3050,9 +3058,7 @@ shada_write_file_nomerge: {}
verbose_leave();
}
- const ShaDaWriteResult sw_ret = shada_write(&sd_writer, (nomerge
- ? NULL
- : &sd_reader));
+ const ShaDaWriteResult sw_ret = shada_write(&sd_writer, (nomerge ? NULL : &sd_reader));
assert(sw_ret != kSDWriteIgnError);
if (!nomerge) {
sd_reader.close(&sd_reader);
@@ -3082,7 +3088,7 @@ shada_write_file_nomerge: {}
|| old_info.stat.st_gid != getgid()) {
const uv_uid_t old_uid = (uv_uid_t)old_info.stat.st_uid;
const uv_gid_t old_gid = (uv_gid_t)old_info.stat.st_gid;
- const int fchown_ret = os_fchown(file_fd(sd_writer.cookie),
+ const int fchown_ret = os_fchown(file_fd(&sd_writer),
old_uid, old_gid);
if (fchown_ret != 0) {
semsg(_(RNERR "Failed setting uid and gid for file %s: %s"),
@@ -3115,7 +3121,7 @@ shada_write_file_did_not_remove:
}
xfree(tempname);
}
- sd_writer.close(&sd_writer);
+ close_file(&sd_writer);
xfree(fname);
return OK;
@@ -3358,7 +3364,7 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const
CLEAR_GA_AND_ERROR_OUT(ad_ga); \
}
#define CHECKED_KEY(un, entry_name, name, error_desc, tgt, condition, attr, proc) \
- else if (CHECK_KEY((un).data.via.map.ptr[i].key, name)) /* NOLINT(readability/braces) */ \
+ else if (CHECK_KEY((un).data.via.map.ptr[i].key, name)) \
{ \
CHECKED_ENTRY(condition, \
"has " name " key value " error_desc, \
@@ -3389,7 +3395,7 @@ static ShaDaReadResult msgpack_read_uint64(ShaDaReadDef *const sd_reader, const
#define INTEGER_KEY(un, entry_name, name, tgt) \
INT_KEY(un, entry_name, name, tgt, TOINT)
#define ADDITIONAL_KEY(un) \
- else { /* NOLINT(readability/braces) */ \
+ else { \
ga_grow(&ad_ga, 1); \
memcpy(((char *)ad_ga.ga_data) + ((size_t)ad_ga.ga_len \
* sizeof(*(un).data.via.map.ptr)), \
@@ -3579,10 +3585,9 @@ shada_read_next_item_start:
entry->data = sd_default_values[type_u64].data;
switch ((ShadaEntryType)type_u64) {
case kSDItemHeader:
- if (!msgpack_rpc_to_dictionary(&(unpacked.data), &(entry->data.header))) {
- semsg(_(READERR("header", "is not a dictionary")), initial_fpos);
- goto shada_read_next_item_error;
- }
+ // TODO(bfredl): header is written to file and provides useful debugging
+ // info. It is never read by nvim (earlier we parsed it back to a
+ // Dictionary, but that value was never used)
break;
case kSDItemSearchPattern: {
if (unpacked.data.type != MSGPACK_OBJECT_MAP) {
@@ -3983,7 +3988,7 @@ static bool shada_removable(const char *name)
char *new_name = home_replace_save(NULL, name);
for (char *p = p_shada; *p;) {
- (void)copy_option_part(&p, part, ARRAY_SIZE(part), ", ");
+ copy_option_part(&p, part, ARRAY_SIZE(part), ", ");
if (part[0] == 'r') {
home_replace(NULL, part + 1, NameBuff, MAXPATHL, true);
size_t n = strlen(NameBuff);
diff --git a/src/nvim/sign.c b/src/nvim/sign.c
index d05c708d2c..4e6672c5dd 100644
--- a/src/nvim/sign.c
+++ b/src/nvim/sign.c
@@ -18,22 +18,27 @@
#include "nvim/cmdexpand_defs.h"
#include "nvim/cursor.h"
#include "nvim/decoration.h"
+#include "nvim/decoration_defs.h"
#include "nvim/drawscreen.h"
#include "nvim/edit.h"
#include "nvim/eval/funcs.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/extmark.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
+#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/macros_defs.h"
#include "nvim/map_defs.h"
#include "nvim/marktree.h"
+#include "nvim/marktree_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -46,8 +51,12 @@
#include "nvim/vim_defs.h"
#include "nvim/window.h"
-static PMap(cstr_t) sign_map INIT( = MAP_INIT);
-static kvec_t(Integer) sign_ns INIT( = MAP_INIT);
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "sign.c.generated.h"
+#endif
+
+static PMap(cstr_t) sign_map = MAP_INIT;
+static kvec_t(Integer) sign_ns = KV_INITIAL_VALUE;
static char *cmds[] = {
"define",
@@ -75,7 +84,7 @@ static int64_t group_get_ns(const char *group)
return UINT32_MAX; // All namespaces
}
// Specific or non-existing namespace
- int ns = map_get(String, int)(&namespace_ids, cstr_as_string((char *)group));
+ int ns = map_get(String, int)(&namespace_ids, cstr_as_string(group));
return ns ? ns : -1;
}
@@ -103,7 +112,7 @@ static void buf_set_sign(buf_T *buf, uint32_t *id, char *group, int prio, linenr
DecorSignHighlight sign = DECOR_SIGN_HIGHLIGHT_INIT;
sign.flags |= kSHIsSign;
- sign.text.ptr = sp->sn_text ? xstrdup(sp->sn_text) : NULL;
+ memcpy(sign.text, sp->sn_text, SIGN_WIDTH * sizeof(schar_T));
sign.sign_name = xstrdup(sp->sn_name);
sign.hl_id = sp->sn_text_hl;
sign.line_hl_id = sp->sn_line_hl;
@@ -112,12 +121,12 @@ static void buf_set_sign(buf_T *buf, uint32_t *id, char *group, int prio, linenr
sign.priority = (DecorPriority)prio;
bool has_hl = (sp->sn_line_hl || sp->sn_num_hl || sp->sn_cul_hl);
- uint16_t decor_flags = (sp->sn_text ? MT_FLAG_DECOR_SIGNTEXT : 0)
+ uint16_t decor_flags = (sp->sn_text[0] ? MT_FLAG_DECOR_SIGNTEXT : 0)
| (has_hl ? MT_FLAG_DECOR_SIGNHL : 0);
DecorInline decor = { .ext = true, .data.ext = { .vt = NULL, .sh_idx = decor_put_sh(sign) } };
extmark_set(buf, ns, id, lnum - 1, 0, -1, -1, decor, decor_flags, true,
- false, true, true, NULL);
+ false, true, true, false, NULL);
}
/// For an existing, placed sign with "id", modify the sign, group or priority.
@@ -159,24 +168,22 @@ static int buf_findsign(buf_T *buf, int id, char *group)
}
/// qsort() function to sort signs by line number, priority, id and recency.
-int sign_cmp(const void *p1, const void *p2)
+static int sign_row_cmp(const void *p1, const void *p2)
{
const MTKey *s1 = (MTKey *)p1;
const MTKey *s2 = (MTKey *)p2;
- int n = s1->pos.row - s2->pos.row;
- if (n) {
- return n;
+ if (s1->pos.row != s2->pos.row) {
+ return s1->pos.row > s2->pos.row ? 1 : -1;
}
DecorSignHighlight *sh1 = decor_find_sign(mt_decor(*s1));
DecorSignHighlight *sh2 = decor_find_sign(mt_decor(*s2));
assert(sh1 && sh2);
+ SignItem si1 = { sh1, s1->id };
+ SignItem si2 = { sh2, s2->id };
- n = sh2->priority - sh1->priority;
-
- return n ? n : (n = (int)(s2->id - s1->id))
- ? n : (sh2->sign_add_id - sh1->sign_add_id);
+ return sign_item_cmp(&si1, &si2);
}
/// Delete the specified sign(s)
@@ -232,7 +239,7 @@ static int buf_delete_signs(buf_T *buf, char *group, int id, linenr_T atlnum)
// Sort to remove the highest priority sign at a specific line number.
if (kv_size(signs)) {
- qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_cmp);
+ qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_row_cmp);
extmark_del_id(buf, kv_A(signs, 0).ns, kv_A(signs, 0).id);
kv_destroy(signs);
} else if (atlnum > 0) {
@@ -241,13 +248,18 @@ static int buf_delete_signs(buf_T *buf, char *group, int id, linenr_T atlnum)
// When deleting the last sign need to redraw the windows to remove the
// sign column. Not when curwin is NULL (this means we're exiting).
- if (!buf->b_signs_with_text && curwin != NULL) {
+ if (!buf_meta_total(buf, kMTMetaSignText) && curwin != NULL) {
changed_line_abv_curs();
}
return OK;
}
+bool buf_has_signs(const buf_T *buf)
+{
+ return (buf_meta_total(buf, kMTMetaSignHL) + buf_meta_total(buf, kMTMetaSignText));
+}
+
/// List placed signs for "rbuf". If "rbuf" is NULL do it for all buffers.
static void sign_list_placed(buf_T *rbuf, char *group)
{
@@ -261,7 +273,7 @@ static void sign_list_placed(buf_T *rbuf, char *group)
msg_putchar('\n');
while (buf != NULL && !got_int) {
- if (buf->b_signs) {
+ if (buf_has_signs(buf)) {
vim_snprintf(lbuf, MSG_BUF_LEN, _("Signs for %s:"), buf->b_fname);
msg_puts_attr(lbuf, HL_ATTR(HLF_D));
msg_putchar('\n');
@@ -282,7 +294,7 @@ static void sign_list_placed(buf_T *rbuf, char *group)
}
if (kv_size(signs)) {
- qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_cmp);
+ qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_row_cmp);
for (size_t i = 0; i < kv_size(signs); i++) {
namebuf[0] = '\0';
@@ -332,9 +344,24 @@ static int sign_cmd_idx(char *begin_cmd, char *end_cmd)
return idx;
}
+/// buf must be SIGN_WIDTH * MAX_SCHAR_SIZE (no extra +1 needed)
+size_t describe_sign_text(char *buf, schar_T *sign_text)
+{
+ size_t p = 0;
+ for (int i = 0; i < SIGN_WIDTH; i++) {
+ schar_get(buf + p, sign_text[i]);
+ size_t len = strlen(buf + p);
+ if (len == 0) {
+ break;
+ }
+ p += len;
+ }
+ return p;
+}
+
/// Initialize the "text" for a new sign and store in "sign_text".
/// "sp" is NULL for signs added through nvim_buf_set_extmark().
-int init_sign_text(sign_T *sp, char **sign_text, char *text)
+int init_sign_text(sign_T *sp, schar_T *sign_text, char *text)
{
char *s;
char *endp = text + (int)strlen(text);
@@ -349,34 +376,29 @@ int init_sign_text(sign_T *sp, char **sign_text, char *text)
// Count cells and check for non-printable chars
int cells = 0;
for (s = text; s < endp; s += utfc_ptr2len(s)) {
- if (!vim_isprintc(utf_ptr2char(s))) {
+ int c;
+ sign_text[cells] = utfc_ptr2schar(s, &c);
+ if (!vim_isprintc(c)) {
break;
}
- cells += utf_ptr2cells(s);
+ int width = utf_char2cells(c);
+ if (width == 2) {
+ sign_text[cells + 1] = 0;
+ }
+ cells += width;
}
// Currently must be empty, one or two display cells
- if (s != endp || cells > 2) {
+ if (s != endp || cells > SIGN_WIDTH) {
if (sp != NULL) {
semsg(_("E239: Invalid sign text: %s"), text);
}
return FAIL;
}
- if (cells < 1) {
- if (sp != NULL) {
- sp->sn_text = NULL;
- }
- return OK;
- }
- if (sp != NULL) {
- xfree(sp->sn_text);
- }
- // Allocate one byte more if we need to pad up with a space.
- size_t len = (size_t)(endp - text + (cells == 1));
- *sign_text = xstrnsave(text, len);
-
- if (cells == 1) {
- STRCPY(*sign_text + len - 1, " ");
+ if (cells < 1) {
+ sign_text[0] = 0;
+ } else if (cells == 1) {
+ sign_text[1] = schar_from_ascii(' ');
}
return OK;
@@ -396,7 +418,7 @@ static int sign_define_by_name(char *name, char *icon, char *text, char *linehl,
} else {
// Signs may already exist, a redraw is needed in windows with a non-empty sign list.
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
- if (wp->w_buffer->b_signs) {
+ if (buf_has_signs(wp->w_buffer)) {
redraw_buf_later(wp->w_buffer, UPD_NOT_VALID);
}
}
@@ -410,7 +432,7 @@ static int sign_define_by_name(char *name, char *icon, char *text, char *linehl,
backslash_halve((*sp)->sn_icon);
}
- if (text != NULL && (init_sign_text(*sp, &(*sp)->sn_text, text) == FAIL)) {
+ if (text != NULL && (init_sign_text(*sp, (*sp)->sn_text, text) == FAIL)) {
return FAIL;
}
@@ -435,7 +457,6 @@ static int sign_undefine_by_name(const char *name)
}
xfree(sp->sn_name);
- xfree(sp->sn_text);
xfree(sp->sn_icon);
xfree(sp);
return OK;
@@ -450,9 +471,11 @@ static void sign_list_defined(sign_T *sp)
msg_outtrans(sp->sn_icon, 0);
msg_puts(_(" (not supported)"));
}
- if (sp->sn_text != NULL) {
+ if (sp->sn_text[0]) {
msg_puts(" text=");
- msg_outtrans(sp->sn_text, 0);
+ char buf[SIGN_WIDTH * MAX_SCHAR_SIZE];
+ describe_sign_text(buf, sp->sn_text);
+ msg_outtrans(buf, 0);
}
static char *arg[] = { " linehl=", " texthl=", " culhl=", " numhl=" };
int hl[] = { sp->sn_line_hl, sp->sn_text_hl, sp->sn_cul_hl, sp->sn_num_hl };
@@ -522,7 +545,7 @@ static int sign_place(uint32_t *id, char *group, char *name, buf_T *buf, linenr_
static int sign_unplace_inner(buf_T *buf, int id, char *group, linenr_T atlnum)
{
- if (!buf->b_signs) { // No signs in the buffer
+ if (!buf_has_signs(buf)) { // No signs in the buffer
return FAIL;
}
@@ -542,7 +565,7 @@ static int sign_unplace_inner(buf_T *buf, int id, char *group, linenr_T atlnum)
// When all the signs in a buffer are removed, force recomputing the
// number column width (if enabled) in all the windows displaying the
// buffer if 'signcolumn' is set to 'number' in that window.
- if (!buf->b_signs_with_text) {
+ if (!buf_meta_total(buf, kMTMetaSignText)) {
may_force_numberwidth_recompute(buf, true);
}
@@ -706,7 +729,7 @@ static void sign_jump_cmd(buf_T *buf, linenr_T lnum, const char *name, int id, c
return;
}
- (void)sign_jump(id, group, buf);
+ sign_jump(id, group, buf);
}
/// Parse the command line arguments for the ":sign place", ":sign unplace" and
@@ -718,7 +741,7 @@ static int parse_sign_cmd_args(int cmd, char *arg, char **name, int *id, char **
{
char *arg1 = arg;
char *filename = NULL;
- int lnum_arg = false;
+ bool lnum_arg = false;
// first arg could be placed sign id
if (ascii_isdigit(*arg)) {
@@ -787,7 +810,7 @@ static int parse_sign_cmd_args(int cmd, char *arg, char **name, int *id, char **
}
if (filename != NULL && *buf == NULL) {
- semsg(_("E158: Invalid buffer name: %s"), filename);
+ semsg(_(e_invalid_buffer_name_str), filename);
return FAIL;
}
@@ -879,8 +902,10 @@ static dict_T *sign_get_info_dict(sign_T *sp)
if (sp->sn_icon != NULL) {
tv_dict_add_str(d, S_LEN("icon"), sp->sn_icon);
}
- if (sp->sn_text != NULL) {
- tv_dict_add_str(d, S_LEN("text"), sp->sn_text);
+ if (sp->sn_text[0]) {
+ char buf[SIGN_WIDTH * MAX_SCHAR_SIZE];
+ describe_sign_text(buf, sp->sn_text);
+ tv_dict_add_str(d, S_LEN("text"), buf);
}
static char *arg[] = { "linehl", "texthl", "culhl", "numhl" };
int hl[] = { sp->sn_line_hl, sp->sn_text_hl, sp->sn_cul_hl, sp->sn_num_hl };
@@ -910,7 +935,7 @@ static dict_T *sign_get_placed_info_dict(MTKey mark)
/// Returns information about signs placed in a buffer as list of dicts.
list_T *get_buffer_signs(buf_T *buf)
- FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
+ FUNC_ATTR_NONNULL_RET FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
{
list_T *const l = tv_list_alloc(kListLenMayKnow);
MarkTreeIter itr[1];
@@ -940,7 +965,7 @@ static void sign_get_placed_in_buf(buf_T *buf, linenr_T lnum, int sign_id, const
tv_dict_add_list(d, S_LEN("signs"), l);
int64_t ns = group_get_ns(group);
- if (!buf->b_signs || ns < 0) {
+ if (!buf_has_signs(buf) || ns < 0) {
return;
}
@@ -967,7 +992,7 @@ static void sign_get_placed_in_buf(buf_T *buf, linenr_T lnum, int sign_id, const
}
if (kv_size(signs)) {
- qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_cmp);
+ qsort((void *)&kv_A(signs, 0), kv_size(signs), sizeof(MTKey), sign_row_cmp);
for (size_t i = 0; i < kv_size(signs); i++) {
tv_list_append_dict(l, sign_get_placed_info_dict(kv_A(signs, i)));
}
@@ -984,7 +1009,7 @@ static void sign_get_placed(buf_T *buf, linenr_T lnum, int id, const char *group
sign_get_placed_in_buf(buf, lnum, id, group, retlist);
} else {
FOR_ALL_BUFFERS(cbuf) {
- if (cbuf->b_signs) {
+ if (buf_has_signs(cbuf)) {
sign_get_placed_in_buf(cbuf, 0, id, group, retlist);
}
}
@@ -994,9 +1019,14 @@ static void sign_get_placed(buf_T *buf, linenr_T lnum, int id, const char *group
void free_signs(void)
{
cstr_t name;
+ kvec_t(cstr_t) names = KV_INITIAL_VALUE;
map_foreach_key(&sign_map, name, {
- sign_undefine_by_name(name);
+ kv_push(names, name);
});
+ for (size_t i = 0; i < kv_size(names); i++) {
+ sign_undefine_by_name(kv_A(names, i));
+ }
+ kv_destroy(names);
}
static enum {
diff --git a/src/nvim/sign.h b/src/nvim/sign.h
index 1c607bc7de..c6d9e1002c 100644
--- a/src/nvim/sign.h
+++ b/src/nvim/sign.h
@@ -1,9 +1,8 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
-#include "nvim/sign_defs.h" // IWYU pragma: export
+#include "nvim/sign_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/sign_defs.h b/src/nvim/sign_defs.h
index 79d21585fc..ad2a2b737d 100644
--- a/src/nvim/sign_defs.h
+++ b/src/nvim/sign_defs.h
@@ -1,22 +1,29 @@
#pragma once
+#include "nvim/decoration_defs.h"
+#include "nvim/types_defs.h"
+
/// Sign attributes. Used by the screen refresh routines.
typedef struct {
- char *text;
+ schar_T text[SIGN_WIDTH];
int hl_id;
} SignTextAttrs;
/// Struct to hold the sign properties.
-typedef struct sign {
+typedef struct {
char *sn_name; // name of sign
char *sn_icon; // name of pixmap
- char *sn_text; // text used instead of pixmap
+ schar_T sn_text[SIGN_WIDTH]; // text used instead of pixmap
int sn_line_hl; // highlight ID for line
int sn_text_hl; // highlight ID for text
int sn_cul_hl; // highlight ID for text on current line when 'cursorline' is set
int sn_num_hl; // highlight ID for line number
} sign_T;
-enum { SIGN_WIDTH = 2, }; ///< Number of display cells for a sign in the signcolumn
+typedef struct {
+ DecorSignHighlight *sh;
+ uint32_t id;
+} SignItem;
+
enum { SIGN_SHOW_MAX = 9, }; ///< Maximum number of signs shown on a single line
enum { SIGN_DEF_PRIO = 10, }; ///< Default sign highlight priority
diff --git a/src/nvim/spell.c b/src/nvim/spell.c
index 905f5c25b4..c2091c6bae 100644
--- a/src/nvim/spell.c
+++ b/src/nvim/spell.c
@@ -63,7 +63,9 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/change.h"
#include "nvim/charset.h"
#include "nvim/cursor.h"
@@ -73,27 +75,32 @@
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/highlight_defs.h"
#include "nvim/insexpand.h"
#include "nvim/log.h"
#include "nvim/macros_defs.h"
-#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
#include "nvim/os/input.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
#include "nvim/search.h"
#include "nvim/spell.h"
@@ -124,7 +131,7 @@ slang_T *first_lang = NULL;
char *int_wordlist = NULL;
// Structure to store info for word matching.
-typedef struct matchinf_S {
+typedef struct {
langp_T *mi_lp; // info for language and region
// pointers to original text to be checked
@@ -163,20 +170,20 @@ typedef struct matchinf_S {
} matchinf_T;
// Structure used for the cookie argument of do_in_runtimepath().
-typedef struct spelload_S {
+typedef struct {
char sl_lang[MAXWLEN + 1]; // language name
slang_T *sl_slang; // resulting slang_T struct
int sl_nobreak; // NOBREAK language found
} spelload_T;
#define SY_MAXLEN 30
-typedef struct syl_item_S {
+typedef struct {
char sy_chars[SY_MAXLEN]; // the sequence of chars
int sy_len;
} syl_item_T;
spelltab_T spelltab;
-int did_set_spelltab;
+bool did_set_spelltab;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "spell.c.generated.h"
@@ -297,8 +304,8 @@ size_t spell_check(win_T *wp, char *ptr, hlf_T *attrp, int *capcol, bool docount
MB_PTR_ADV(mi.mi_fend);
}
- (void)spell_casefold(wp, ptr, (int)(mi.mi_fend - ptr), mi.mi_fword,
- MAXWLEN + 1);
+ spell_casefold(wp, ptr, (int)(mi.mi_fend - ptr), mi.mi_fword,
+ MAXWLEN + 1);
mi.mi_fwordlen = (int)strlen(mi.mi_fword);
if (is_camel_case && mi.mi_fwordlen > 0) {
@@ -363,7 +370,7 @@ size_t spell_check(win_T *wp, char *ptr, hlf_T *attrp, int *capcol, bool docount
// Check for end of sentence.
regmatch.regprog = wp->w_s->b_cap_prog;
regmatch.rm_ic = false;
- int r = vim_regexec(&regmatch, ptr, 0);
+ bool r = vim_regexec(&regmatch, ptr, 0);
wp->w_s->b_cap_prog = regmatch.regprog;
if (r) {
*capcol = (int)(regmatch.endp[0] - ptr);
@@ -802,7 +809,7 @@ static void find_word(matchinf_T *mip, int mode)
if (slang->sl_compsylmax < MAXWLEN) {
// "fword" is only needed for checking syllables.
if (ptr == mip->mi_word) {
- (void)spell_casefold(mip->mi_win, ptr, wlen, fword, MAXWLEN);
+ spell_casefold(mip->mi_win, ptr, wlen, fword, MAXWLEN);
} else {
xstrlcpy(fword, ptr, (size_t)endlen[endidxcnt] + 1);
}
@@ -1212,9 +1219,9 @@ static int fold_more(matchinf_T *mip)
MB_PTR_ADV(mip->mi_fend);
}
- (void)spell_casefold(mip->mi_win, p, (int)(mip->mi_fend - p),
- mip->mi_fword + mip->mi_fwordlen,
- MAXWLEN - mip->mi_fwordlen);
+ spell_casefold(mip->mi_win, p, (int)(mip->mi_fend - p),
+ mip->mi_fword + mip->mi_fwordlen,
+ MAXWLEN - mip->mi_fwordlen);
int flen = (int)strlen(mip->mi_fword + mip->mi_fwordlen);
mip->mi_fwordlen += flen;
return flen;
@@ -1272,7 +1279,7 @@ static TriState decor_spell_nav_col(win_T *wp, linenr_T lnum, linenr_T *decor_ln
static inline bool can_syn_spell(win_T *wp, linenr_T lnum, int col)
{
bool can_spell;
- (void)syn_get_id(wp, lnum, col, false, &can_spell, false);
+ syn_get_id(wp, lnum, col, false, &can_spell, false);
return can_spell;
}
@@ -1293,7 +1300,7 @@ size_t spell_move_to(win_T *wp, int dir, bool allwords, bool curline, hlf_T *att
size_t found_len = 0;
hlf_T attr = HLF_COUNT;
size_t len;
- int has_syntax = syntax_present(wp);
+ bool has_syntax = syntax_present(wp);
colnr_T col;
char *buf = NULL;
size_t buflen = 0;
@@ -2029,7 +2036,7 @@ char *parse_spelllang(win_T *wp)
// If not found try loading the language now.
if (slang == NULL) {
if (filename) {
- (void)spell_load_file(lang, lang, NULL, false);
+ spell_load_file(lang, lang, NULL, false);
} else {
spell_load_lang(lang);
// SpellFileMissing autocommands may do anything, including
@@ -2374,7 +2381,7 @@ void spell_reload(void)
// window for this buffer in which 'spell' is set.
if (*wp->w_s->b_p_spl != NUL) {
if (wp->w_p_spell) {
- (void)parse_spelllang(wp);
+ parse_spelllang(wp);
break;
}
}
@@ -2834,7 +2841,7 @@ void spell_soundfold(slang_T *slang, char *inword, bool folded, char *res)
if (folded) {
word = inword;
} else {
- (void)spell_casefold(curwin, inword, (int)strlen(inword), fword, MAXWLEN);
+ spell_casefold(curwin, inword, (int)strlen(inword), fword, MAXWLEN);
word = fword;
}
@@ -3219,14 +3226,14 @@ void ex_spelldump(exarg_T *eap)
if (no_spell_checking(curwin)) {
return;
}
- OptVal spl = get_option_value("spl", NULL, OPT_LOCAL, NULL);
+ OptVal spl = get_option_value(kOptSpelllang, OPT_LOCAL);
// Create a new empty buffer in a new window.
do_cmdline_cmd("new");
// enable spelling locally in the new window
- set_option_value_give_err("spell", BOOLEAN_OPTVAL(true), OPT_LOCAL);
- set_option_value_give_err("spl", spl, OPT_LOCAL);
+ set_option_value_give_err(kOptSpell, BOOLEAN_OPTVAL(true), OPT_LOCAL);
+ set_option_value_give_err(kOptSpelllang, spl, OPT_LOCAL);
optval_free(spl);
if (!buf_is_empty(curbuf)) {
diff --git a/src/nvim/spell.h b/src/nvim/spell.h
index f3977fdaf2..adbdd3705e 100644
--- a/src/nvim/spell.h
+++ b/src/nvim/spell.h
@@ -3,9 +3,8 @@
#include <stdbool.h>
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
-#include "nvim/globals.h"
-#include "nvim/spell_defs.h" // IWYU pragma: export
-#include "nvim/vim_defs.h"
+#include "nvim/spell_defs.h" // IWYU pragma: keep
+#include "nvim/vim_defs.h" // IWYU pragma: keep
/// First language that is loaded, start of the linked list of loaded languages.
extern slang_T *first_lang;
@@ -14,7 +13,7 @@ extern slang_T *first_lang;
extern char *int_wordlist;
extern spelltab_T spelltab;
-extern int did_set_spelltab;
+extern bool did_set_spelltab;
extern char *e_format;
diff --git a/src/nvim/spell_defs.h b/src/nvim/spell_defs.h
index dfa399750f..005f3aa9e4 100644
--- a/src/nvim/spell_defs.h
+++ b/src/nvim/spell_defs.h
@@ -4,16 +4,14 @@
#include <stdint.h>
#include "nvim/buffer_defs.h"
-#include "nvim/garray_defs.h"
-#include "nvim/hashtab_defs.h"
-#include "nvim/regexp_defs.h"
-/// Assume max. word len is this many bytes.
-/// Some places assume a word length fits in a byte, thus it can't be above 255.
-enum { MAXWLEN = 254, };
+enum {
+ /// Assume max. word len is this many bytes.
+ /// Some places assume a word length fits in a byte, thus it can't be above 255.
+ MAXWLEN = 254,
+};
-/// Number of regions supported.
-enum { MAXREGIONS = 8, };
+enum { MAXREGIONS = 8, }; ///< Number of regions supported.
/// Type used for indexes in the word tree need to be at least 4 bytes. If int
/// is 8 bytes we could use something smaller, but what?
@@ -77,7 +75,7 @@ enum {
/// Info from "REP", "REPSAL" and "SAL" entries in ".aff" file used in si_rep,
/// si_repsal, sl_rep, and si_sal. Not for sl_sal!
/// One replacement: from "ft_from" to "ft_to".
-typedef struct fromto_S {
+typedef struct {
char *ft_from;
char *ft_to;
} fromto_T;
@@ -85,7 +83,7 @@ typedef struct fromto_S {
/// Info from "SAL" entries in ".aff" file used in sl_sal.
/// The info is split for quick processing by spell_soundfold().
/// Note that "sm_oneof" and "sm_rules" point into sm_lead.
-typedef struct salitem_S {
+typedef struct {
char *sm_lead; ///< leading letters
int sm_leadlen; ///< length of "sm_lead"
char *sm_oneof; ///< letters from () or NULL
@@ -191,7 +189,7 @@ struct slang_S {
};
/// Structure used in "b_langp", filled from 'spelllang'.
-typedef struct langp_S {
+typedef struct {
slang_T *lp_slang; ///< info for this language
slang_T *lp_sallang; ///< language used for sound folding or NULL
slang_T *lp_replang; ///< language used for REP items or NULL
@@ -215,18 +213,6 @@ typedef struct {
uint8_t st_upper[256]; ///< chars: upper case
} spelltab_T;
-// Use our own character-case definitions, because the current locale may
-// differ from what the .spl file uses.
-// These must not be called with negative number!
-// Multi-byte implementation. For Unicode we can call utf_*(), but don't do
-// that for ASCII, because we don't want to use 'casemap' here. Otherwise use
-// the "w" library function for characters above 255.
-#define SPELL_TOFOLD(c) ((c) >= 128 ? utf_fold(c) : (int)spelltab.st_fold[c])
-
-#define SPELL_TOUPPER(c) ((c) >= 128 ? mb_toupper(c) : (int)spelltab.st_upper[c])
-
-#define SPELL_ISUPPER(c) ((c) >= 128 ? mb_isupper(c) : spelltab.st_isu[c])
-
/// Values for "what" argument of spell_add_word()
typedef enum {
SPELL_ADD_GOOD = 0,
@@ -234,7 +220,7 @@ typedef enum {
SPELL_ADD_RARE = 2,
} SpellAddType;
-typedef struct wordcount_S {
+typedef struct {
uint16_t wc_count; ///< nr of times word was seen
char wc_word[]; ///< word
} wordcount_T;
diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c
index 2607fddc31..1c632d2700 100644
--- a/src/nvim/spellfile.c
+++ b/src/nvim/spellfile.c
@@ -237,34 +237,42 @@
#include "nvim/arglist.h"
#include "nvim/ascii_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/drawscreen.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/time.h"
+#include "nvim/os/time_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/regexp.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/spell.h"
#include "nvim/spell_defs.h"
#include "nvim/spellfile.h"
#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
@@ -334,7 +342,7 @@ static const char *msg_compressing = N_("Compressing word tree...");
#define MAXLINELEN 500 // Maximum length in bytes of a line in a .aff
// and .dic file.
// Main structure to store the contents of a ".aff" file.
-typedef struct afffile_S {
+typedef struct {
char *af_enc; // "SET", normalized, alloc'ed string or NULL
int af_flagtype; // AFT_CHAR, AFT_LONG, AFT_NUM or AFT_CAPLONG
unsigned af_rare; // RARE ID for rare word
@@ -376,7 +384,7 @@ struct affentry_S {
#define AH_KEY_LEN 17 // 2 x 8 bytes + NUL
// Affix header from ".aff" file. Used for af_pref and af_suff.
-typedef struct affheader_S {
+typedef struct {
char ah_key[AH_KEY_LEN]; // key for hashtab == name of affix
unsigned ah_flag; // affix name as number, uses "af_flagtype"
int ah_newID; // prefix ID after renumbering; 0 if not used
@@ -388,7 +396,7 @@ typedef struct affheader_S {
#define HI2AH(hi) ((affheader_T *)(hi)->hi_key)
// Flag used in compound items.
-typedef struct compitem_S {
+typedef struct {
char ci_key[AH_KEY_LEN]; // key for hashtab == name of compound
unsigned ci_flag; // affix name as number, uses "af_flagtype"
int ci_newID; // affix ID after renumbering.
@@ -449,7 +457,7 @@ struct wordnode_S {
#define HI2WN(hi) (wordnode_T *)((hi)->hi_key)
// Info used while reading the spell files.
-typedef struct spellinfo_S {
+typedef struct {
wordnode_T *si_foldroot; // tree with case-folded words
int si_foldwcount; // nr of words in si_foldroot
@@ -574,7 +582,7 @@ static inline int spell_check_magic_string(FILE *const fd)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_ALWAYS_INLINE
{
char buf[VIMSPELLMAGICL];
- SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd,; ); // NOLINT(whitespace/parens)
+ SPELL_READ_BYTES(buf, VIMSPELLMAGICL, fd,; );
if (memcmp(buf, VIMSPELLMAGIC, VIMSPELLMAGICL) != 0) {
return SP_FORMERROR;
}
@@ -1036,7 +1044,7 @@ static int read_region_section(FILE *fd, slang_T *lp, int len)
if (len > MAXREGIONS * 2) {
return SP_FORMERROR;
}
- SPELL_READ_NONNUL_BYTES(lp->sl_regions, (size_t)len, fd,; ); // NOLINT(whitespace/parens)
+ SPELL_READ_NONNUL_BYTES(lp->sl_regions, (size_t)len, fd,; );
lp->sl_regions[len] = NUL;
return 0;
}
@@ -1101,7 +1109,7 @@ static int read_prefcond_section(FILE *fd, slang_T *lp)
if (n > 0) {
char buf[MAXWLEN + 1];
buf[0] = '^'; // always match at one position only
- SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd,; ); // NOLINT(whitespace/parens)
+ SPELL_READ_NONNUL_BYTES(buf + 1, (size_t)n, fd,; );
buf[n + 1] = NUL;
lp->sl_prefprog[i] = vim_regcomp(buf, RE_MAGIC | RE_STRING);
}
@@ -1536,7 +1544,7 @@ static int set_sofo(slang_T *lp, const char *from, const char *to)
// sl_sal_first[] for this.
for (p = from, s = to; *p != NUL && *s != NUL;) {
const int c = mb_cptr2char_adv(&p);
- MB_CPTR_ADV(s);
+ s += utf_ptr2len(s);
if (c >= 256) {
lp->sl_sal_first[c & 0xff]++;
}
@@ -2015,16 +2023,16 @@ static afffile_T *spell_read_aff(spellinfo_T *spin, char *fname)
spell_message(spin, IObuff);
// Only do REP lines when not done in another .aff file already.
- int do_rep = GA_EMPTY(&spin->si_rep);
+ bool do_rep = GA_EMPTY(&spin->si_rep);
// Only do REPSAL lines when not done in another .aff file already.
- int do_repsal = GA_EMPTY(&spin->si_repsal);
+ bool do_repsal = GA_EMPTY(&spin->si_repsal);
// Only do SAL lines when not done in another .aff file already.
- int do_sal = GA_EMPTY(&spin->si_sal);
+ bool do_sal = GA_EMPTY(&spin->si_sal);
// Only do MAP lines when not done in another .aff file already.
- int do_mapline = GA_EMPTY(&spin->si_map);
+ bool do_mapline = GA_EMPTY(&spin->si_map);
// Allocate and init the afffile_T structure.
afffile_T *aff = getroom(spin, sizeof(*aff), true);
@@ -2967,9 +2975,9 @@ static void add_fromto(spellinfo_T *spin, garray_T *gap, char *from, char *to)
char word[MAXWLEN];
fromto_T *ftp = GA_APPEND_VIA_PTR(fromto_T, gap);
- (void)spell_casefold(curwin, from, (int)strlen(from), word, MAXWLEN);
+ spell_casefold(curwin, from, (int)strlen(from), word, MAXWLEN);
ftp->ft_from = getroom_save(spin, word);
- (void)spell_casefold(curwin, to, (int)strlen(to), word, MAXWLEN);
+ spell_casefold(curwin, to, (int)strlen(to), word, MAXWLEN);
ftp->ft_to = getroom_save(spin, word);
}
@@ -3614,11 +3622,9 @@ static int spell_read_wordfile(spellinfo_T *spin, char *fname)
smsg(0, _("/encoding= line after word ignored in %s line %" PRIdLINENR ": %s"),
fname, lnum, line - 1);
} else {
- char *enc;
-
// Setup for conversion to 'encoding'.
line += 9;
- enc = enc_canonize(line);
+ char *enc = enc_canonize(line);
if (!spin->si_ascii
&& convert_setup(&spin->si_conv, enc, p_enc) == FAIL) {
smsg(0, _("Conversion in %s not supported: from %s to %s"),
@@ -3820,7 +3826,7 @@ static int store_word(spellinfo_T *spin, char *word, int flags, int region, cons
return FAIL;
}
- (void)spell_casefold(curwin, word, len, foldword, MAXWLEN);
+ spell_casefold(curwin, word, len, foldword, MAXWLEN);
for (const char *p = pfxlist; res == OK; p++) {
if (!need_affix || (p != NULL && *p != NUL)) {
res = tree_add_word(spin, foldword, spin->si_foldroot, ct | flags,
@@ -3980,7 +3986,7 @@ static int tree_add_word(spellinfo_T *spin, const char *word, wordnode_T *root,
// (si_compress_cnt == 1) and the number of free nodes drops below the
// maximum word length.
#ifndef SPELL_COMPRESS_ALWAYS
- if (spin->si_compress_cnt == 1 // NOLINT(readability/braces)
+ if (spin->si_compress_cnt == 1
? spin->si_free_count < MAXWLEN
: spin->si_blocks_cnt >= compress_start)
#endif
@@ -4593,7 +4599,7 @@ static int write_vim_spell(spellinfo_T *spin, char *fname)
spin->si_memtot += (int)(nodecount + nodecount * sizeof(int));
// Write the nodes.
- (void)put_node(fd, tree, 0, regionmask, round == 3);
+ put_node(fd, tree, 0, regionmask, round == 3);
}
// Write another byte to check for errors (file system full).
@@ -5098,7 +5104,7 @@ static void sug_write(spellinfo_T *spin, char *fname)
spin->si_memtot += (int)(nodecount + nodecount * sizeof(int));
// Write the nodes.
- (void)put_node(fd, tree, 0, 0, false);
+ put_node(fd, tree, 0, 0, false);
// <SUGTABLE>: <sugwcount> <sugline> ...
linenr_T wcount = spin->si_spellbuf->b_ml.ml_line_count;
@@ -5601,7 +5607,7 @@ static void init_spellfile(void)
&& strstr(path_tail(fname), ".ascii.") != NULL)
? "ascii"
: spell_enc()));
- set_option_value_give_err("spellfile", CSTR_AS_OPTVAL(buf), OPT_LOCAL);
+ set_option_value_give_err(kOptSpellfile, CSTR_AS_OPTVAL(buf), OPT_LOCAL);
break;
}
aspath = false;
@@ -5638,7 +5644,7 @@ static void set_spell_charflags(const char *flags_in, int cnt, const char *fol)
}
}
- (void)set_spell_finish(&new_st);
+ set_spell_finish(&new_st);
}
static int set_spell_finish(spelltab_T *new_st)
diff --git a/src/nvim/spellsuggest.c b/src/nvim/spellsuggest.c
index d9dd28527e..5c0e295f88 100644
--- a/src/nvim/spellsuggest.c
+++ b/src/nvim/spellsuggest.c
@@ -16,18 +16,20 @@
#include "nvim/cursor.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/fileio.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/highlight_defs.h"
#include "nvim/input.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
#include "nvim/message.h"
@@ -36,14 +38,17 @@
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
#include "nvim/os/input.h"
+#include "nvim/os/os_defs.h"
#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/spell.h"
+#include "nvim/spell_defs.h"
#include "nvim/spellfile.h"
#include "nvim/spellsuggest.h"
#include "nvim/strings.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
@@ -63,7 +68,7 @@
#define WF_MIXCAP 0x20 // mix of upper and lower case: macaRONI
/// Information used when looking for suggestions.
-typedef struct suginfo_S {
+typedef struct {
garray_T su_ga; ///< suggestions, contains "suggest_T"
int su_maxcount; ///< max. number of suggestions displayed
int su_maxscore; ///< maximum score for adding to su_ga
@@ -186,7 +191,7 @@ typedef enum {
} state_T;
/// Struct to keep the state at each level in suggest_try_change().
-typedef struct trystate_S {
+typedef struct {
state_T ts_state; ///< state at this level, STATE_
int ts_score; ///< score
idx_T ts_arridx; ///< index in tree array, start of node
@@ -442,7 +447,7 @@ void spell_suggest(int count)
char wcopy[MAXWLEN + 2];
suginfo_T sug;
suggest_T *stp;
- int mouse_used;
+ bool mouse_used;
int limit;
int selected = count;
int badlen = 0;
@@ -730,8 +735,8 @@ static void spell_find_suggest(char *badptr, int badlen, suginfo_T *su, int maxc
su->su_badlen = MAXWLEN - 1; // just in case
}
xstrlcpy(su->su_badword, su->su_badptr, (size_t)su->su_badlen + 1);
- (void)spell_casefold(curwin, su->su_badptr, su->su_badlen, su->su_fbadword,
- MAXWLEN);
+ spell_casefold(curwin, su->su_badptr, su->su_badlen, su->su_fbadword,
+ MAXWLEN);
// TODO(vim): make this work if the case-folded text is longer than the
// original text. Currently an illegal byte causes wrong pointer
@@ -845,7 +850,7 @@ static void spell_suggest_expr(suginfo_T *su, char *expr)
// Remove bogus suggestions, sort and truncate at "maxcount".
check_suggestions(su, &su->su_ga);
- (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
+ cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
}
/// Find suggestions in file "fname". Used for "file:" in 'spellsuggest'.
@@ -892,7 +897,7 @@ static void spell_suggest_file(suginfo_T *su, char *fname)
// Remove bogus suggestions, sort and truncate at "maxcount".
check_suggestions(su, &su->su_ga);
- (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
+ cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
}
/// Find suggestions for the internal method indicated by "sps_flags".
@@ -956,7 +961,7 @@ static void spell_suggest_intern(suginfo_T *su, bool interactive)
// got_int when using a command, not for spellsuggest().
os_breakcheck();
if (interactive && got_int) {
- (void)vgetc();
+ vgetc();
got_int = false;
}
@@ -968,7 +973,7 @@ static void spell_suggest_intern(suginfo_T *su, bool interactive)
// Remove bogus suggestions, sort and truncate at "maxcount".
check_suggestions(su, &su->su_ga);
- (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
+ cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
}
}
@@ -1064,7 +1069,7 @@ static void suggest_try_change(suginfo_T *su)
STRCPY(fword, su->su_fbadword);
int n = (int)strlen(fword);
char *p = su->su_badptr + su->su_badlen;
- (void)spell_casefold(curwin, p, (int)strlen(p), fword + n, MAXWLEN - n);
+ spell_casefold(curwin, p, (int)strlen(p), fword + n, MAXWLEN - n);
// Make sure the resulting text is not longer than the original text.
n = (int)strlen(su->su_badptr);
@@ -1272,10 +1277,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
break;
}
- int fword_ends = (fword[sp->ts_fidx] == NUL
- || (soundfold
- ? ascii_iswhite(fword[sp->ts_fidx])
- : !spell_iswordp(fword + sp->ts_fidx, curwin)));
+ bool fword_ends = (fword[sp->ts_fidx] == NUL
+ || (soundfold
+ ? ascii_iswhite(fword[sp->ts_fidx])
+ : !spell_iswordp(fword + sp->ts_fidx, curwin)));
tword[sp->ts_twordlen] = NUL;
if (sp->ts_prefixdepth <= PFD_NOTSPECIAL
@@ -1942,6 +1947,12 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char *fword, bool soun
// - Skip the byte if it's equal to the byte in the word,
// accepting that byte is always better.
n += sp->ts_curi++;
+
+ // break out, if we would be accessing byts buffer out of bounds
+ if (byts == slang->sl_fbyts && n >= slang->sl_fbyts_len) {
+ got_int = true;
+ break;
+ }
c = byts[n];
if (soundfold && sp->ts_twordlen == 0 && c == '*') {
// Inserting a vowel at the start of a word counts less,
@@ -2532,8 +2543,8 @@ static void score_combine(suginfo_T *su)
}
if (slang == NULL) { // Using "double" without sound folding.
- (void)cleanup_suggestions(&su->su_ga, su->su_maxscore,
- su->su_maxcount);
+ cleanup_suggestions(&su->su_ga, su->su_maxscore,
+ su->su_maxcount);
return;
}
@@ -2552,9 +2563,9 @@ static void score_combine(suginfo_T *su)
// Remove bad suggestions, sort the suggestions and truncate at "maxcount"
// for both lists.
check_suggestions(su, &su->su_ga);
- (void)cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
+ cleanup_suggestions(&su->su_ga, su->su_maxscore, su->su_maxcount);
check_suggestions(su, &su->su_sga);
- (void)cleanup_suggestions(&su->su_sga, su->su_maxscore, su->su_maxcount);
+ cleanup_suggestions(&su->su_sga, su->su_maxscore, su->su_maxcount);
ga_init(&ga, (int)sizeof(suginfo_T), 1);
ga_grow(&ga, su->su_ga.ga_len + su->su_sga.ga_len);
@@ -2615,7 +2626,7 @@ static int stp_sal_score(suggest_T *stp, suginfo_T *su, slang_T *slang, char *ba
pbad = badsound;
} else {
// soundfold the bad word with more characters following
- (void)spell_casefold(curwin, su->su_badptr, stp->st_orglen, fword, MAXWLEN);
+ spell_casefold(curwin, su->su_badptr, stp->st_orglen, fword, MAXWLEN);
// When joining two words the sound often changes a lot. E.g., "t he"
// sounds like "t h" while "the" sounds like "@". Avoid that by
@@ -3142,7 +3153,7 @@ static void check_suggestions(suginfo_T *su, garray_T *gap)
int len = stp[i].st_wordlen;
xstrlcpy(longword + len, su->su_badptr + stp[i].st_orglen, MAXWLEN + 1 - (size_t)len);
hlf_T attr = HLF_COUNT;
- (void)spell_check(curwin, longword, &attr, NULL, false);
+ spell_check(curwin, longword, &attr, NULL, false);
if (attr != HLF_COUNT) {
// Remove this entry.
xfree(stp[i].st_word);
@@ -3210,10 +3221,10 @@ static int sug_compare(const void *s1, const void *s2)
{
suggest_T *p1 = (suggest_T *)s1;
suggest_T *p2 = (suggest_T *)s2;
- int n = p1->st_score - p2->st_score;
+ int n = p1->st_score == p2->st_score ? 0 : p1->st_score > p2->st_score ? 1 : -1;
if (n == 0) {
- n = p1->st_altscore - p2->st_altscore;
+ n = p1->st_altscore == p2->st_altscore ? 0 : p1->st_altscore > p2->st_altscore ? 1 : -1;
if (n == 0) {
n = STRICMP(p1->st_word, p2->st_word);
}
diff --git a/src/nvim/state.c b/src/nvim/state.c
index 900eac0826..0df060ecf4 100644
--- a/src/nvim/state.c
+++ b/src/nvim/state.c
@@ -3,10 +3,14 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/event/defs.h"
+#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/ex_getln.h"
#include "nvim/getchar.h"
@@ -26,10 +30,11 @@
#include "nvim/ui.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "state.c.generated.h" // IWYU pragma: export
+# include "state.c.generated.h"
#endif
void state_enter(VimState *s)
+ FUNC_ATTR_NONNULL_ALL
{
while (true) {
int check_result = s->check ? s->check(s) : 1;
@@ -72,9 +77,9 @@ getkey:
// Call `os_inchar` directly to block for events or user input without
// consuming anything from `input_buffer`(os/input.c) or calling the
// mapping engine.
- (void)os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
+ os_inchar(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
// If an event was put into the queue, we send K_EVENT directly.
- if (!multiqueue_empty(main_loop.events)) {
+ if (!input_available() && !multiqueue_empty(main_loop.events)) {
key = K_EVENT;
} else {
goto getkey;
@@ -168,6 +173,7 @@ int get_real_state(void)
/// The first character represents the major mode, the following ones the minor
/// ones.
void get_mode(char *buf)
+ FUNC_ATTR_NONNULL_ALL
{
int i = 0;
diff --git a/src/nvim/state.h b/src/nvim/state.h
index 8c5957bf9a..9002f018d2 100644
--- a/src/nvim/state.h
+++ b/src/nvim/state.h
@@ -1,6 +1,6 @@
#pragma once
-#include "nvim/state_defs.h" // IWYU pragma: export
+#include "nvim/state_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "state.h.generated.h"
diff --git a/src/nvim/statusline.c b/src/nvim/statusline.c
index 4dac1b1451..b403f840ca 100644
--- a/src/nvim/statusline.c
+++ b/src/nvim/statusline.c
@@ -18,29 +18,37 @@
#include "nvim/eval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/eval/vars.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
#include "nvim/normal.h"
#include "nvim/option.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/plines.h"
#include "nvim/pos_defs.h"
#include "nvim/sign.h"
+#include "nvim/sign_defs.h"
#include "nvim/state_defs.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/undo.h"
#include "nvim/window.h"
@@ -59,7 +67,6 @@ typedef enum {
/// If inversion is possible we use it. Else '=' characters are used.
void win_redr_status(win_T *wp)
{
- int fillchar;
int attr;
bool is_stl_global = global_stl_height() > 0;
static bool busy = false;
@@ -85,7 +92,7 @@ void win_redr_status(win_T *wp)
// redraw custom status line
redraw_custom_statusline(wp);
} else {
- fillchar = fillchar_status(&attr, wp);
+ schar_T fillchar = fillchar_status(&attr, wp);
const int stl_width = is_stl_global ? Columns : wp->w_width;
get_trans_bufname(wp->w_buffer);
@@ -144,14 +151,14 @@ void win_redr_status(win_T *wp)
}
grid_line_start(&default_grid, is_stl_global ? (Rows - (int)p_ch - 1) : W_ENDROW(wp));
- int col = is_stl_global ? 0 : wp->w_wincol;
+ const int off = is_stl_global ? 0 : wp->w_wincol;
- int width = grid_line_puts(col, p, -1, attr);
- grid_line_fill(width + col, this_ru_col + col, fillchar, attr);
+ int width = grid_line_puts(off, p, -1, attr);
+ grid_line_fill(off + width, off + this_ru_col, fillchar, attr);
if (get_keymap_str(wp, "<%s>", NameBuff, MAXPATHL)
- && this_ru_col - len > (int)(strlen(NameBuff) + 1)) {
- grid_line_puts((int)((size_t)this_ru_col - strlen(NameBuff) - 1), NameBuff, -1, attr);
+ && this_ru_col - len > (int)strlen(NameBuff) + 1) {
+ grid_line_puts(off + this_ru_col - (int)strlen(NameBuff) - 1, NameBuff, -1, attr);
}
win_redr_ruler(wp);
@@ -161,7 +168,7 @@ void win_redr_status(win_T *wp)
const int sc_width = MIN(10, this_ru_col - len - 2);
if (sc_width > 0) {
- grid_line_puts(wp->w_wincol + this_ru_col - sc_width - 1, showcmd_buf, sc_width, attr);
+ grid_line_puts(off + this_ru_col - sc_width - 1, showcmd_buf, sc_width, attr);
}
}
@@ -170,6 +177,7 @@ void win_redr_status(win_T *wp)
// May need to draw the character below the vertical separator.
if (wp->w_vsep_width != 0 && wp->w_status_height != 0 && redrawing()) {
+ schar_T fillchar;
if (stl_connected(wp)) {
fillchar = fillchar_status(&attr, wp);
} else {
@@ -177,7 +185,7 @@ void win_redr_status(win_T *wp)
fillchar = wp->w_p_fcs_chars.vert;
}
grid_line_start(&default_grid, W_ENDROW(wp));
- grid_line_put_schar(W_ENDCOL(wp), schar_from_char(fillchar), attr);
+ grid_line_put_schar(W_ENDCOL(wp), fillchar, attr);
grid_line_flush();
}
busy = false;
@@ -292,11 +300,11 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
int row;
int col = 0;
int maxwidth;
- int fillchar;
+ schar_T fillchar;
char buf[MAXPATHL];
char transbuf[MAXPATHL];
char *stl;
- char *opt_name;
+ OptIndex opt_idx = kOptInvalid;
int opt_scope = 0;
stl_hlrec_t *hltab;
StlClickRecord *tabtab;
@@ -317,12 +325,12 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
// Use 'tabline'. Always at the first line of the screen.
stl = p_tal;
row = 0;
- fillchar = ' ';
+ fillchar = schar_from_ascii(' ');
attr = HL_ATTR(HLF_TPF);
maxwidth = Columns;
- opt_name = "tabline";
+ opt_idx = kOptTabline;
} else if (draw_winbar) {
- opt_name = "winbar";
+ opt_idx = kOptWinbar;
stl = ((*wp->w_p_wbr != NUL) ? wp->w_p_wbr : p_wbr);
opt_scope = ((*wp->w_p_wbr != NUL) ? OPT_LOCAL : 0);
row = -1; // row zero is first row of text
@@ -351,7 +359,7 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
if (draw_ruler) {
stl = p_ruf;
- opt_name = "rulerformat";
+ opt_idx = kOptRulerformat;
// advance past any leading group spec - implicit in ru_col
if (*stl == '%') {
if (*++stl == '-') {
@@ -375,11 +383,11 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
grid = &msg_grid_adj;
row = Rows - 1;
maxwidth--; // writing in last column may cause scrolling
- fillchar = ' ';
+ fillchar = schar_from_ascii(' ');
attr = HL_ATTR(HLF_MSG);
}
} else {
- opt_name = "statusline";
+ opt_idx = kOptStatusline;
stl = ((*wp->w_p_stl != NUL) ? wp->w_p_stl : p_stl);
opt_scope = ((*wp->w_p_stl != NUL) ? OPT_LOCAL : 0);
}
@@ -402,8 +410,8 @@ static void win_redr_custom(win_T *wp, bool draw_winbar, bool draw_ruler)
// Make a copy, because the statusline may include a function call that
// might change the option value and free the memory.
stl = xstrdup(stl);
- build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_name, opt_scope,
- fillchar, maxwidth, &hltab, &tabtab, NULL);
+ build_stl_str_hl(ewp, buf, sizeof(buf), stl, opt_idx, opt_scope,
+ fillchar, maxwidth, &hltab, NULL, &tabtab, NULL);
xfree(stl);
ewp->w_p_crb = p_crb_save;
@@ -514,7 +522,7 @@ void win_redr_ruler(win_T *wp)
&& *ml_get_buf(wp->w_buffer, wp->w_cursor.lnum) == NUL;
int width;
- int fillchar;
+ schar_T fillchar;
int attr;
int off;
bool part_of_status = false;
@@ -530,7 +538,7 @@ void win_redr_ruler(win_T *wp)
width = Columns;
part_of_status = true;
} else {
- fillchar = ' ';
+ fillchar = schar_from_ascii(' ');
attr = HL_ATTR(HLF_MSG);
width = Columns;
off = 0;
@@ -578,7 +586,7 @@ void win_redr_ruler(win_T *wp)
if (this_ru_col + o < width) {
// Need at least 3 chars left for get_rel_pos() + NUL.
while (this_ru_col + o < width && RULER_BUF_LEN > i + 4) {
- i += utf_char2bytes(fillchar, buffer + i);
+ i += (int)schar_get(buffer + i, fillchar);
o++;
}
get_rel_pos(wp, buffer + i, RULER_BUF_LEN - i);
@@ -607,24 +615,21 @@ void win_redr_ruler(win_T *wp)
}
}
- int w = grid_line_puts(this_ru_col + off, buffer, -1, attr);
- grid_line_fill(this_ru_col + off + w, off + width, fillchar, attr);
+ int w = grid_line_puts(off + this_ru_col, buffer, -1, attr);
+ grid_line_fill(off + this_ru_col + w, off + width, fillchar, attr);
}
}
/// Get the character to use in a status line. Get its attributes in "*attr".
-int fillchar_status(int *attr, win_T *wp)
+schar_T fillchar_status(int *attr, win_T *wp)
{
- int fill;
- bool is_curwin = (wp == curwin);
- if (is_curwin) {
+ if (wp == curwin) {
*attr = win_hl_attr(wp, HLF_S);
- fill = wp->w_p_fcs_chars.stl;
+ return wp->w_p_fcs_chars.stl;
} else {
*attr = win_hl_attr(wp, HLF_SNC);
- fill = wp->w_p_fcs_chars.stlnc;
+ return wp->w_p_fcs_chars.stlnc;
}
- return fill;
}
/// Redraw the status line according to 'statusline' and take care of any
@@ -660,7 +665,7 @@ static void ui_ext_tabline_update(void)
win_T *cwp = (tp == curtab) ? curwin : tp->tp_curwin;
get_trans_bufname(cwp->w_buffer);
- PUT_C(tab_info, "name", STRING_OBJ(arena_string(&arena, cstr_as_string(NameBuff))));
+ PUT_C(tab_info, "name", CSTR_TO_ARENA_OBJ(&arena, NameBuff));
ADD_C(tabs, DICTIONARY_OBJ(tab_info));
}
@@ -681,7 +686,7 @@ static void ui_ext_tabline_update(void)
PUT_C(buffer_info, "buffer", BUFFER_OBJ(buf->handle));
get_trans_bufname(buf);
- PUT_C(buffer_info, "name", STRING_OBJ(arena_string(&arena, cstr_as_string(NameBuff))));
+ PUT_C(buffer_info, "name", CSTR_TO_ARENA_OBJ(&arena, NameBuff));
ADD_C(buffers, DICTIONARY_OBJ(buffer_info));
}
@@ -696,7 +701,7 @@ void draw_tabline(void)
win_T *wp;
int attr_nosel = HL_ATTR(HLF_TP);
int attr_fill = HL_ATTR(HLF_TPF);
- int use_sep_chars = (t_colors < 8);
+ bool use_sep_chars = (t_colors < 8);
if (default_grid.chars == NULL) {
return;
@@ -725,9 +730,6 @@ void draw_tabline(void)
int col = 0;
win_T *cwp;
int wincount;
- int c;
- int len;
- char *p;
grid_line_start(&default_grid, 0);
FOR_ALL_TABS(tp) {
tabcount++;
@@ -772,7 +774,7 @@ void draw_tabline(void)
grid_line_put_schar(col++, schar_from_ascii(' '), attr);
- int modified = false;
+ bool modified = false;
for (wincount = 0; wp != NULL; wp = wp->w_next, wincount++) {
if (bufIsChanged(wp->w_buffer)) {
@@ -783,7 +785,7 @@ void draw_tabline(void)
if (modified || wincount > 1) {
if (wincount > 1) {
vim_snprintf(NameBuff, MAXPATHL, "%d", wincount);
- len = (int)strlen(NameBuff);
+ int len = (int)strlen(NameBuff);
if (col + len >= Columns - 3) {
break;
}
@@ -802,8 +804,8 @@ void draw_tabline(void)
// Get buffer name in NameBuff[]
get_trans_bufname(cwp->w_buffer);
shorten_dir(NameBuff);
- len = vim_strsize(NameBuff);
- p = NameBuff;
+ int len = vim_strsize(NameBuff);
+ char *p = NameBuff;
while (len > room) {
len -= ptr2cells(p);
MB_PTR_ADV(p);
@@ -829,12 +831,8 @@ void draw_tabline(void)
}
}
- if (use_sep_chars) {
- c = '_';
- } else {
- c = ' ';
- }
- grid_line_fill(col, Columns, c, attr_fill);
+ char c = use_sep_chars ? '_' : ' ';
+ grid_line_fill(col, Columns, schar_from_ascii(c), attr_fill);
// Draw the 'showcmd' information if 'showcmdloc' == "tabline".
if (p_sc && *p_sloc == 't') {
@@ -868,7 +866,7 @@ void draw_tabline(void)
/// the v:lnum and v:relnum variables don't have to be updated.
///
/// @return The width of the built status column string for line "lnum"
-int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, statuscol_T *stcp)
+int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, char *buf, statuscol_T *stcp)
{
// Only update click definitions once per window per redraw.
// Don't update when current width is 0, since it will be redrawn again if not empty.
@@ -881,15 +879,15 @@ int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, statuscol_T *
StlClickRecord *clickrec;
char *stc = xstrdup(wp->w_p_stc);
- int width = build_stl_str_hl(wp, stcp->text, MAXPATHL, stc, "statuscolumn", OPT_LOCAL, ' ',
- stcp->width, &stcp->hlrec, fillclick ? &clickrec : NULL, stcp);
+ int width = build_stl_str_hl(wp, buf, MAXPATHL, stc, kOptStatuscolumn, OPT_LOCAL, 0,
+ stcp->width, &stcp->hlrec, NULL, fillclick ? &clickrec : NULL, stcp);
xfree(stc);
if (fillclick) {
stl_clear_click_defs(wp->w_statuscol_click_defs, wp->w_statuscol_click_defs_size);
- wp->w_statuscol_click_defs = stl_alloc_click_defs(wp->w_statuscol_click_defs, stcp->width,
+ wp->w_statuscol_click_defs = stl_alloc_click_defs(wp->w_statuscol_click_defs, width,
&wp->w_statuscol_click_defs_size);
- stl_fill_click_defs(wp->w_statuscol_click_defs, clickrec, stcp->text, stcp->width, false);
+ stl_fill_click_defs(wp->w_statuscol_click_defs, clickrec, buf, width, false);
}
return width;
@@ -913,8 +911,8 @@ int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, statuscol_T *
/// Note: This should not be NameBuff
/// @param outlen The length of the output buffer
/// @param fmt The statusline format string
-/// @param opt_name The option name corresponding to "fmt"
-/// @param opt_scope The scope corresponding to "opt_name"
+/// @param opt_idx Index of the option corresponding to "fmt"
+/// @param opt_scope The scope corresponding to "opt_idx"
/// @param fillchar Character to use when filling empty space in the statusline
/// @param maxwidth The maximum width to make the statusline
/// @param hltab HL attributes (can be NULL)
@@ -922,9 +920,9 @@ int build_statuscol_str(win_T *wp, linenr_T lnum, linenr_T relnum, statuscol_T *
/// @param stcp Status column attributes (can be NULL)
///
/// @return The final width of the statusline
-int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_name, int opt_scope,
- int fillchar, int maxwidth, stl_hlrec_t **hltab, StlClickRecord **tabtab,
- statuscol_T *stcp)
+int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex opt_idx,
+ int opt_scope, schar_T fillchar, int maxwidth, stl_hlrec_t **hltab,
+ size_t *hltab_len, StlClickRecord **tabtab, statuscol_T *stcp)
{
static size_t stl_items_len = 20; // Initial value, grows as needed.
static stl_item_t *stl_items = NULL;
@@ -937,14 +935,20 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
char buf_tmp[TMPLEN];
char win_tmp[TMPLEN];
char *usefmt = fmt;
- const int save_must_redraw = must_redraw;
- const int save_redr_type = curwin->w_redr_type;
+ const bool save_redraw_not_allowed = redraw_not_allowed;
const bool save_KeyTyped = KeyTyped;
// TODO(Bram): find out why using called_emsg_before makes tests fail, does it
// matter?
// const int called_emsg_before = called_emsg;
const int did_emsg_before = did_emsg;
+ // When inside update_screen() we do not want redrawing a statusline,
+ // ruler, title, etc. to trigger another redraw, it may cause an endless
+ // loop.
+ if (updating_screen) {
+ redraw_not_allowed = true;
+ }
+
if (stl_items == NULL) {
stl_items = xmalloc(sizeof(stl_item_t) * stl_items_len);
stl_groupitems = xmalloc(sizeof(int) * stl_items_len);
@@ -957,10 +961,10 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
stl_separator_locations = xmalloc(sizeof(int) * stl_items_len);
}
- // if "fmt" was set insecurely it needs to be evaluated in the sandbox
- // "opt_name" will be NULL when caller is nvim_eval_statusline()
- const int use_sandbox = opt_name ? was_set_insecurely(wp, opt_name, opt_scope)
- : false;
+ // If "fmt" was set insecurely it needs to be evaluated in the sandbox.
+ // "opt_idx" will be kOptInvalid when caller is nvim_eval_statusline().
+ const bool use_sandbox = (opt_idx != kOptInvalid) ? was_set_insecurely(wp, opt_idx, opt_scope)
+ : false;
// When the format starts with "%!" then evaluate it as an expression and
// use the result as the actual format string.
@@ -980,7 +984,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
}
if (fillchar == 0) {
- fillchar = ' ';
+ fillchar = schar_from_ascii(' ');
}
// The cursor in windows other than the current one isn't always
@@ -1178,7 +1182,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
out_p = out_p - n + 1;
// Fill up space left over by half a double-wide char.
while (++group_len < stl_items[stl_groupitems[groupdepth]].minwid) {
- MB_CHAR2BYTES(fillchar, out_p);
+ schar_get_adv(&out_p, fillchar);
}
// }
@@ -1201,13 +1205,13 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
if (min_group_width < 0) {
min_group_width = 0 - min_group_width;
while (group_len++ < min_group_width && out_p < out_end_p) {
- MB_CHAR2BYTES(fillchar, out_p);
+ schar_get_adv(&out_p, fillchar);
}
// If the group is right-aligned, shift everything to the right and
// prepend with filler characters.
} else {
// { Move the group to the right
- group_len = (min_group_width - group_len) * utf_char2len(fillchar);
+ group_len = (min_group_width - group_len) * (int)schar_len(fillchar);
memmove(t + group_len, t, (size_t)(out_p - t));
if (out_p + group_len >= (out_end_p + 1)) {
group_len = out_end_p - out_p;
@@ -1222,7 +1226,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// Prepend the fill characters
for (; group_len > 0; group_len--) {
- MB_CHAR2BYTES(fillchar, t);
+ schar_get_adv(&t, fillchar);
}
}
}
@@ -1400,7 +1404,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
case STL_VIM_EXPR: // '{'
{
char *block_start = fmt_p - 1;
- int reevaluate = (*fmt_p == '%');
+ bool reevaluate = (*fmt_p == '%');
itemisflag = true;
if (reevaluate) {
@@ -1545,7 +1549,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
break;
case STL_SHOWCMD:
- if (p_sc && (opt_name == NULL || strcmp(opt_name, p_sloc) == 0)) {
+ if (p_sc && (opt_idx == kOptInvalid || find_option(p_sloc) == opt_idx)) {
str = showcmd_buf;
}
break;
@@ -1632,29 +1636,41 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
break;
}
bool fold = opt == STL_FOLDCOL;
- int width = fold ? (compute_foldcolumn(wp, 0) > 0) : wp->w_scwidth;
+ int fdc = fold ? compute_foldcolumn(wp, 0) : 0;
+ int width = fold ? fdc > 0 : wp->w_scwidth;
- if (width == 0) {
+ if (width <= 0) {
break;
}
foldsignitem = curitem;
char *p = NULL;
if (fold) {
- size_t n = fill_foldcolumn(out_p, wp, stcp->foldinfo,
- (linenr_T)get_vim_var_nr(VV_LNUM), NULL);
+ schar_T fold_buf[10];
+ fill_foldcolumn(wp, stcp->foldinfo, (linenr_T)get_vim_var_nr(VV_LNUM),
+ 0, fdc, NULL, fold_buf);
stl_items[curitem].minwid = -((stcp->use_cul ? HLF_CLF : HLF_FC) + 1);
+ size_t buflen = 0;
+ // TODO(bfredl): this is very backwards. we must support schar_T
+ // being used directly in 'statuscolumn'
+ for (int i = 0; i < fdc; i++) {
+ buflen += schar_get(out_p + buflen, fold_buf[i]);
+ }
p = out_p;
- p[n] = NUL;
}
+ char buf[SIGN_WIDTH * MAX_SCHAR_SIZE];
size_t buflen = 0;
varnumber_T virtnum = get_vim_var_nr(VV_VIRTNUM);
for (int i = 0; i < width; i++) {
if (!fold) {
SignTextAttrs *sattr = virtnum ? NULL : &stcp->sattrs[i];
- p = sattr && sattr->text ? sattr->text : " ";
- stl_items[curitem].minwid = -(sattr && sattr->text
+ p = " ";
+ if (sattr && sattr->text[0]) {
+ describe_sign_text(buf, sattr->text);
+ p = buf;
+ }
+ stl_items[curitem].minwid = -(sattr && sattr->text[0]
? (stcp->sign_cul_id ? stcp->sign_cul_id : sattr->hl_id)
: (stcp->use_cul ? HLF_CLS : HLF_SC) + 1);
}
@@ -1803,7 +1819,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
if (l + 1 == minwid && fillchar == '-' && ascii_isdigit(*t)) {
*out_p++ = ' ';
} else {
- MB_CHAR2BYTES(fillchar, out_p);
+ schar_get_adv(&out_p, fillchar);
}
}
minwid = 0;
@@ -1826,7 +1842,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// digit follows.
if (fillable && *t == ' '
&& (!ascii_isdigit(*(t + 1)) || fillchar != '-')) {
- MB_CHAR2BYTES(fillchar, out_p);
+ schar_get_adv(&out_p, fillchar);
} else {
*out_p++ = *t;
}
@@ -1843,7 +1859,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// For left-aligned items, fill any remaining space with the fillchar
for (; l < minwid && out_p < out_end_p; l++) {
- MB_CHAR2BYTES(fillchar, out_p);
+ schar_get_adv(&out_p, fillchar);
}
// Otherwise if the item is a number, copy that to the output buffer.
@@ -1928,16 +1944,16 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
stl_items[curitem].type = Empty;
}
+ if (num >= 0 || (!itemisflag && str && *str)) {
+ prevchar_isflag = false; // Item not NULL, but not a flag
+ }
+
// Only free the string buffer if we allocated it.
// Note: This is not needed if `str` is pointing at `tmp`
if (opt == STL_VIM_EXPR) {
XFREE_CLEAR(str);
}
- if (num >= 0 || (!itemisflag && str && *str)) {
- prevchar_isflag = false; // Item not NULL, but not a flag
- }
-
// Item processed, move to the next
curitem++;
}
@@ -1954,11 +1970,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// What follows is post-processing to handle alignment and highlighting.
int width = vim_strsize(out);
- // Return truncated width for 'statuscolumn'
- if (stcp != NULL && width > stcp->width) {
- stcp->truncate = width - stcp->width;
- }
- if (maxwidth > 0 && width > maxwidth) {
+ if (maxwidth > 0 && width > maxwidth && (!stcp || width > MAX_STCWIDTH)) {
// Result is too long, must truncate somewhere.
int item_idx = 0;
char *trunc_p;
@@ -2064,8 +2076,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// Fill up for half a double-wide character.
while (++width < maxwidth) {
- MB_CHAR2BYTES(fillchar, trunc_p);
- *trunc_p = NUL;
+ schar_get_adv(&trunc_p, fillchar);
}
}
width = maxwidth;
@@ -2094,12 +2105,12 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
for (int l = 0; l < num_separators; l++) {
int dislocation = (l == (num_separators - 1)) ? final_spaces : standard_spaces;
- dislocation *= utf_char2len(fillchar);
+ dislocation *= (int)schar_len(fillchar);
char *start = stl_items[stl_separator_locations[l]].start;
char *seploc = start + dislocation;
STRMOVE(seploc, start);
for (char *s = start; s < seploc;) {
- MB_CHAR2BYTES(fillchar, s);
+ schar_get_adv(&s, fillchar);
}
for (int item_idx = stl_separator_locations[l] + 1;
@@ -2127,6 +2138,9 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
sp->start = NULL;
sp->userhl = 0;
}
+ if (hltab_len) {
+ *hltab_len = (size_t)itemcnt;
+ }
// Store the info about tab pages labels.
if (tabtab != NULL) {
@@ -2164,12 +2178,7 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
cur_tab_rec->def.func = NULL;
}
- // When inside update_screen we do not want redrawing a statusline, ruler,
- // title, etc. to trigger another redraw, it may cause an endless loop.
- if (updating_screen) {
- must_redraw = save_must_redraw;
- curwin->w_redr_type = save_redr_type;
- }
+ redraw_not_allowed = save_redraw_not_allowed;
// Check for an error. If there is one the display will be messed up and
// might loop redrawing. Avoid that by making the corresponding option
@@ -2177,8 +2186,8 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, char *opt_n
// TODO(Bram): find out why using called_emsg_before makes tests fail, does it
// matter?
// if (called_emsg > called_emsg_before)
- if (opt_name && did_emsg > did_emsg_before) {
- set_string_option_direct(opt_name, -1, "", OPT_FREE | opt_scope, SID_ERROR);
+ if (opt_idx != kOptInvalid && did_emsg > did_emsg_before) {
+ set_string_option_direct(opt_idx, "", opt_scope, SID_ERROR);
}
// A user function may reset KeyTyped, restore it.
diff --git a/src/nvim/statusline.h b/src/nvim/statusline.h
index eab7c1aa47..1a5f12dbf4 100644
--- a/src/nvim/statusline.h
+++ b/src/nvim/statusline.h
@@ -2,9 +2,10 @@
#include <stddef.h>
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
-#include "nvim/statusline_defs.h" // IWYU pragma: export
+#include "nvim/option_defs.h" // IWYU pragma: keep
+#include "nvim/statusline_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
/// Array defining what should be done when tabline is clicked
EXTERN StlClickDefinition *tab_page_click_defs INIT( = NULL);
diff --git a/src/nvim/statusline_defs.h b/src/nvim/statusline_defs.h
index c1a54f4f54..118f4a257b 100644
--- a/src/nvim/statusline_defs.h
+++ b/src/nvim/statusline_defs.h
@@ -1,11 +1,8 @@
#pragma once
#include <stdbool.h>
-#include <stddef.h>
#include "nvim/fold_defs.h"
-#include "nvim/macros_defs.h"
-#include "nvim/os/os_defs.h"
#include "nvim/sign_defs.h"
/// Status line click definition
@@ -57,21 +54,13 @@ struct stl_item {
};
/// Struct to hold info for 'statuscolumn'
-typedef struct statuscol statuscol_T;
-
-struct statuscol {
+typedef struct {
int width; ///< width of the status column
- int cur_attr; ///< current attributes in text
int num_attr; ///< default highlight attr
int sign_cul_id; ///< cursorline sign highlight id
- int truncate; ///< truncated width
bool draw; ///< whether to draw the statuscolumn
bool use_cul; ///< whether to use cursorline attrs
- char text[MAXPATHL]; ///< text in status column
- char *textp; ///< current position in text
- char *text_end; ///< end of text (the NUL byte)
stl_hlrec_t *hlrec; ///< highlight groups
- stl_hlrec_t *hlrecp; ///< current highlight group
foldinfo_T foldinfo; ///< fold information
SignTextAttrs *sattrs; ///< sign attributes
-};
+} statuscol_T;
diff --git a/src/nvim/strings.c b/src/nvim/strings.c
index a439d11818..01bd610292 100644
--- a/src/nvim/strings.c
+++ b/src/nvim/strings.c
@@ -17,11 +17,13 @@
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/macros_defs.h"
#include "nvim/math.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
@@ -30,6 +32,10 @@
#include "nvim/types_defs.h"
#include "nvim/vim_defs.h"
+#ifdef INCLUDE_GENERATED_DECLARATIONS
+# include "strings.c.generated.h"
+#endif
+
static const char e_cannot_mix_positional_and_non_positional_str[]
= N_("E1500: Cannot mix positional and non-positional arguments: %s");
static const char e_fmt_arg_nr_unused_str[]
@@ -179,21 +185,17 @@ char *vim_strnsave_unquoted(const char *const string, const size_t length)
char *vim_strsave_shellescape(const char *string, bool do_special, bool do_newline)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
- char *d;
- char *escaped_string;
size_t l;
- int csh_like;
- bool fish_like;
// Only csh and similar shells expand '!' within single quotes. For sh and
// the like we must not put a backslash before it, it will be taken
// literally. If do_special is set the '!' will be escaped twice.
// Csh also needs to have "\n" escaped twice when do_special is set.
- csh_like = csh_like_shell();
+ int csh_like = csh_like_shell();
// Fish shell uses '\' as an escape character within single quotes, so '\'
// itself must be escaped to get a literal '\'.
- fish_like = fish_like_shell();
+ bool fish_like = fish_like_shell();
// First count the number of extra bytes required.
size_t length = strlen(string) + 3; // two quotes and a trailing NUL
@@ -225,8 +227,8 @@ char *vim_strsave_shellescape(const char *string, bool do_special, bool do_newli
}
// Allocate memory for the result and fill it.
- escaped_string = xmalloc(length);
- d = escaped_string;
+ char *escaped_string = xmalloc(length);
+ char *d = escaped_string;
// add opening quote
#ifdef MSWIN
@@ -297,9 +299,7 @@ char *vim_strsave_shellescape(const char *string, bool do_special, bool do_newli
char *vim_strsave_up(const char *string)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
- char *p1;
-
- p1 = xstrdup(string);
+ char *p1 = xstrdup(string);
vim_strup(p1);
return p1;
}
@@ -335,36 +335,41 @@ void vim_strup(char *p)
char *strcase_save(const char *const orig, bool upper)
FUNC_ATTR_NONNULL_RET FUNC_ATTR_MALLOC FUNC_ATTR_NONNULL_ALL
{
- char *res = xstrdup(orig);
+ // Calculate the initial length and allocate memory for the result
+ size_t orig_len = strlen(orig);
+ // +1 for the null terminator
+ char *res = xmalloc(orig_len + 1);
+ // Index in the result string
+ size_t res_index = 0;
+ // Current position in the original string
+ const char *p = orig;
- char *p = res;
while (*p != NUL) {
- int c = utf_ptr2char(p);
- int l = utf_ptr2len(p);
- if (c == 0) {
- // overlong sequence, use only the first byte
- c = (uint8_t)(*p);
- l = 1;
- }
- int uc = upper ? mb_toupper(c) : mb_tolower(c);
-
- // Reallocate string when byte count changes. This is rare,
- // thus it's OK to do another malloc()/free().
- int newl = utf_char2len(uc);
- if (newl != l) {
- // TODO(philix): use xrealloc() in strcase_save()
- char *s = xmalloc(strlen(res) + (size_t)(1 + newl - l));
- memcpy(s, res, (size_t)(p - res));
- STRCPY(s + (p - res) + newl, p + l);
- p = s + (p - res);
- xfree(res);
- res = s;
- }
-
- utf_char2bytes(uc, p);
- p += newl;
- }
-
+ CharInfo char_info = utf_ptr2CharInfo(p);
+ int c = char_info.value < 0 ? (uint8_t)(*p) : char_info.value;
+ int newc = upper ? mb_toupper(c) : mb_tolower(c);
+ // Cast to size_t to avoid mixing types in arithmetic
+ size_t newl = (size_t)utf_char2len(newc);
+
+ // Check if there's enough space in the allocated memory
+ if (res_index + newl > orig_len) {
+ // Need more space: allocate extra space for the new character and the null terminator
+ size_t new_size = res_index + newl + 1;
+ res = xrealloc(res, new_size);
+ // Adjust the original length to the new size, minus the null terminator
+ orig_len = new_size - 1;
+ }
+
+ // Write the possibly new character into the result string
+ utf_char2bytes(newc, res + res_index);
+ // Move the index in the result string
+ res_index += newl;
+ // Move to the next character in the original string
+ p += char_info.len;
+ }
+
+ // Null-terminate the result string
+ res[res_index] = NUL;
return res;
}
@@ -372,9 +377,7 @@ char *strcase_save(const char *const orig, bool upper)
void del_trailing_spaces(char *ptr)
FUNC_ATTR_NONNULL_ALL
{
- char *q;
-
- q = ptr + strlen(ptr);
+ char *q = ptr + strlen(ptr);
while (--q > ptr && ascii_iswhite(q[0]) && q[-1] != '\\' && q[-1] != Ctrl_V) {
*q = NUL;
}
@@ -461,9 +464,6 @@ char *vim_strchr(const char *const string, const int c)
// Sort an array of strings.
-#ifdef INCLUDE_GENERATED_DECLARATIONS
-# include "strings.c.generated.h"
-#endif
static int sort_compare(const void *s1, const void *s2)
FUNC_ATTR_NONNULL_ALL
{
@@ -1357,9 +1357,13 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
assert(n <= SIZE_MAX - str_l);
str_l += n;
} else {
- size_t min_field_width = 0, precision = 0;
- int zero_padding = 0, precision_specified = 0, justify_left = 0;
- int alternate_form = 0, force_sign = 0;
+ size_t min_field_width = 0;
+ size_t precision = 0;
+ bool zero_padding = false;
+ bool precision_specified = false;
+ bool justify_left = false;
+ bool alternate_form = false;
+ bool force_sign = false;
// if both ' ' and '+' flags appear, ' ' flag should be ignored
int space_for_positive = 1;
@@ -1424,17 +1428,17 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
while (true) {
switch (*p) {
case '0':
- zero_padding = 1; p++; continue;
+ zero_padding = true; p++; continue;
case '-':
- justify_left = 1; p++; continue;
+ justify_left = true; p++; continue;
// if both '0' and '-' flags appear, '0' should be ignored
case '+':
- force_sign = 1; space_for_positive = 0; p++; continue;
+ force_sign = true; space_for_positive = 0; p++; continue;
case ' ':
- force_sign = 1; p++; continue;
+ force_sign = true; p++; continue;
// if both ' ' and '+' flags appear, ' ' should be ignored
case '#':
- alternate_form = 1; p++; continue;
+ alternate_form = true; p++; continue;
case '\'':
p++; continue;
default:
@@ -1469,7 +1473,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
min_field_width = (size_t)j;
} else {
min_field_width = (size_t)-j;
- justify_left = 1;
+ justify_left = true;
}
} else if (ascii_isdigit((int)(*p))) {
// size_t could be wider than unsigned int; make sure we treat
@@ -1485,7 +1489,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
// parse precision
if (*p == '.') {
p++;
- precision_specified = 1;
+ precision_specified = true;
if (ascii_isdigit((int)(*p))) {
// size_t could be wider than unsigned int; make sure we
@@ -1520,7 +1524,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
if (j >= 0) {
precision = (size_t)j;
} else {
- precision_specified = 0;
+ precision_specified = false;
precision = 0;
}
}
@@ -1775,7 +1779,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
// '0' flag should be ignored. This is so with Solaris 2.6, Digital
// UNIX 4.0, HPUX 10, Linux, FreeBSD, NetBSD; but not with Perl.
if (precision_specified) {
- zero_padding = 0;
+ zero_padding = false;
}
if (fmt_spec == 'd') {
@@ -1863,8 +1867,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
&& !(zero_padding_insertion_ind < str_arg_l
&& tmp[zero_padding_insertion_ind] == '0')) {
// assure leading zero for alternate-form octal numbers
- if (!precision_specified
- || precision < num_of_digits + 1) {
+ if (!precision_specified || precision < num_of_digits + 1) {
// precision is increased to force the first character to be
// zero, except if a zero value is formatted with an explicit
// precision of zero
@@ -1895,7 +1898,7 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
case 'G': {
// floating point
char format[40];
- int remove_trailing_zeroes = false;
+ bool remove_trailing_zeroes = false;
double f = (tvs
? tv_float(tvs, &arg_idx)
@@ -1921,12 +1924,12 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
force_sign, space_for_positive),
sizeof(tmp));
str_arg_l = strlen(tmp);
- zero_padding = 0;
+ zero_padding = false;
} else if (xisnan(f)) {
// Not a number: nan or NAN
memmove(tmp, ASCII_ISUPPER(fmt_spec) ? "NAN" : "nan", 4);
str_arg_l = 3;
- zero_padding = 0;
+ zero_padding = false;
} else {
// Regular float number
format[0] = '%';
@@ -2012,8 +2015,8 @@ int vim_vsnprintf_typval(char *str, size_t str_m, const char *fmt, va_list ap_st
default:
// unrecognized conversion specifier, keep format string as-is
- zero_padding = 0; // turn zero padding off for non-numeric conversion
- justify_left = 1;
+ zero_padding = false; // turn zero padding off for non-numeric conversion
+ justify_left = true;
min_field_width = 0; // reset flags
// discard the unrecognized conversion, just keep
@@ -2163,6 +2166,47 @@ int kv_do_printf(StringBuilder *str, const char *fmt, ...)
return printed;
}
+String arena_printf(Arena *arena, const char *fmt, ...)
+ FUNC_ATTR_PRINTF(2, 3)
+{
+ size_t remaining = 0;
+ char *buf = NULL;
+ if (arena) {
+ if (!arena->cur_blk) {
+ arena_alloc_block(arena);
+ }
+
+ // happy case, we can fit the printed string in the rest of the current
+ // block (one pass):
+ remaining = arena->size - arena->pos;
+ buf = arena->cur_blk + arena->pos;
+ }
+
+ va_list ap;
+ va_start(ap, fmt);
+ int printed = vsnprintf(buf, remaining, fmt, ap);
+ va_end(ap);
+
+ if (printed < 0) {
+ return (String)STRING_INIT;
+ }
+
+ // printed string didn't fit, allocate and try again
+ if ((size_t)printed >= remaining) {
+ buf = arena_alloc(arena, (size_t)printed + 1, false);
+ va_start(ap, fmt);
+ printed = vsnprintf(buf, (size_t)printed + 1, fmt, ap);
+ va_end(ap);
+ if (printed < 0) {
+ return (String)STRING_INIT;
+ }
+ } else {
+ arena->pos += (size_t)printed + 1;
+ }
+
+ return cbuf_as_string(buf, (size_t)printed);
+}
+
/// Reverse text into allocated memory.
///
/// @return the allocated string.
@@ -2224,7 +2268,7 @@ char *strrep(const char *src, const char *what, const char *rep)
}
/// Implementation of "byteidx()" and "byteidxcomp()" functions
-static void byteidx_common(typval_T *argvars, typval_T *rettv, int comp)
+static void byteidx_common(typval_T *argvars, typval_T *rettv, bool comp)
{
rettv->vval.v_number = -1;
diff --git a/src/nvim/strings.h b/src/nvim/strings.h
index d717362f87..903559b062 100644
--- a/src/nvim/strings.h
+++ b/src/nvim/strings.h
@@ -5,11 +5,16 @@
#include "auto/config.h"
#include "klib/kvec.h"
+#include "nvim/api/private/defs.h"
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/func_attr.h"
#include "nvim/os/os_defs.h"
#include "nvim/types_defs.h" // IWYU pragma: keep
+static inline char *strappend(char *dst, const char *src)
+ REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL
+ REAL_FATTR_NONNULL_RET REAL_FATTR_WARN_UNUSED_RESULT;
+
/// Append string to string and return pointer to the next byte
///
/// Unlike strcat, this one does *not* add NUL byte and returns pointer to the
@@ -20,8 +25,6 @@
///
/// @return pointer to the byte just past the appended byte.
static inline char *strappend(char *const dst, const char *const src)
- FUNC_ATTR_ALWAYS_INLINE FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
- FUNC_ATTR_NONNULL_RET
{
const size_t src_len = strlen(src);
return (char *)memmove(dst, src, src_len) + src_len;
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 11282ea170..ab8ab62b90 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -9,6 +9,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
@@ -20,12 +21,14 @@
#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/indent_c.h"
#include "nvim/macros_defs.h"
@@ -40,6 +43,7 @@
#include "nvim/pos_defs.h"
#include "nvim/profile.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
@@ -77,7 +81,7 @@ static const char e_trailing_char_after_rsb_str_str[]
// and for the actually highlighted text (_h_start and _h_end).
//
// Note that ordering of members is optimized to reduce padding.
-typedef struct syn_pattern {
+typedef struct {
char sp_type; // see SPTYPE_ defines below
bool sp_syncing; // this item used for syncing
int16_t sp_syn_match_id; // highlight group ID of pattern
@@ -97,7 +101,7 @@ typedef struct syn_pattern {
syn_time_T sp_time;
} synpat_T;
-typedef struct syn_cluster_S {
+typedef struct {
char *scl_name; // syntax cluster name
char *scl_name_u; // uppercase of scl_name
int16_t *scl_list; // IDs in this syntax cluster
@@ -106,7 +110,7 @@ typedef struct syn_cluster_S {
// For the current state we need to remember more than just the idx.
// When si_m_endpos.lnum is 0, the items other than si_idx are unknown.
// (The end positions have the column number of the next char)
-typedef struct state_item {
+typedef struct {
int si_idx; // index of syntax pattern or
// KEYWORD_IDX
int si_id; // highlight group ID for keywords
@@ -342,10 +346,10 @@ void syntax_start(win_T *wp, linenr_T lnum)
if (VALID_STATE(&current_state)
&& current_lnum < lnum
&& current_lnum < syn_buf->b_ml.ml_line_count) {
- (void)syn_finish_line(false);
+ syn_finish_line(false);
if (!current_state_stored) {
current_lnum++;
- (void)store_current_state();
+ store_current_state();
}
// If the current_lnum is now the same as "lnum", keep the current
@@ -403,7 +407,7 @@ void syntax_start(win_T *wp, linenr_T lnum)
}
while (current_lnum < lnum) {
syn_start_line();
- (void)syn_finish_line(false);
+ syn_finish_line(false);
current_lnum++;
// If we parsed at least "minlines" lines or started at a valid
@@ -492,23 +496,16 @@ static void clear_current_state(void)
// 3. Simply start on a given number of lines above "lnum".
static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
{
- buf_T *curbuf_save;
- win_T *curwin_save;
pos_T cursor_save;
- int idx;
linenr_T lnum;
- linenr_T end_lnum;
linenr_T break_lnum;
- bool had_sync_point;
stateitem_T *cur_si;
synpat_T *spp;
- char *line;
int found_flags = 0;
int found_match_idx = 0;
linenr_T found_current_lnum = 0;
int found_current_col = 0;
lpos_T found_m_endpos;
- colnr_T prev_current_col;
// Clear any current state that might be hanging around.
invalidate_current_state();
@@ -545,14 +542,14 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
if (syn_block->b_syn_sync_flags & SF_CCOMMENT) {
// Need to make syn_buf the current buffer for a moment, to be able to
// use find_start_comment().
- curwin_save = curwin;
+ win_T *curwin_save = curwin;
curwin = wp;
- curbuf_save = curbuf;
+ buf_T *curbuf_save = curbuf;
curbuf = syn_buf;
// Skip lines that end in a backslash.
for (; start_lnum > 1; start_lnum--) {
- line = ml_get(start_lnum - 1);
+ char *line = ml_get(start_lnum - 1);
if (*line == NUL || *(line + strlen(line) - 1) != '\\') {
break;
}
@@ -568,7 +565,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
// defines the comment.
// Restrict the search for the end of a comment to b_syn_sync_maxlines.
if (find_start_comment((int)syn_block->b_syn_sync_maxlines) != NULL) {
- for (idx = syn_block->b_syn_patterns.ga_len; --idx >= 0;) {
+ for (int idx = syn_block->b_syn_patterns.ga_len; --idx >= 0;) {
if (SYN_ITEMS(syn_block)[idx].sp_syn.id
== syn_block->b_syn_sync_id
&& SYN_ITEMS(syn_block)[idx].sp_type == SPTYPE_START) {
@@ -595,7 +592,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
found_m_endpos.lnum = 0;
found_m_endpos.col = 0;
- end_lnum = start_lnum;
+ linenr_T end_lnum = start_lnum;
lnum = start_lnum;
while (--lnum > break_lnum) {
// This can take a long time: break when CTRL-C pressed.
@@ -623,7 +620,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
for (current_lnum = lnum; current_lnum < end_lnum; current_lnum++) {
syn_start_line();
while (true) {
- had_sync_point = syn_finish_line(true);
+ bool had_sync_point = syn_finish_line(true);
// When a sync point has been found, remember where, and
// continue to look for another one, further on in the line.
if (had_sync_point && current_state.ga_len) {
@@ -662,7 +659,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
// syn_current_attr() will have skipped the check for
// an item that ends here, need to do that now. Be
// careful not to go past the NUL.
- prev_current_col = current_col;
+ colnr_T prev_current_col = current_col;
if (syn_getcurline()[current_col] != NUL) {
current_col++;
}
@@ -699,7 +696,7 @@ static void syn_sync(win_T *wp, linenr_T start_lnum, synstate_T *last_valid)
}
current_col = found_m_endpos.col;
current_lnum = found_m_endpos.lnum;
- (void)syn_finish_line(false);
+ syn_finish_line(false);
current_lnum++;
} else {
current_lnum = start_lnum;
@@ -1151,7 +1148,7 @@ static synstate_T *store_current_state(void)
// Add a new entry
// If no free items, cleanup the array first.
if (syn_block->b_sst_freecount == 0) {
- (void)syn_stack_cleanup();
+ syn_stack_cleanup();
// "sp" may have been moved to the freelist now
sp = syn_stack_find_entry(current_lnum);
}
@@ -1371,7 +1368,7 @@ bool syntax_check_changed(linenr_T lnum)
if (sp != NULL && sp->sst_lnum == lnum) {
// finish the previous line (needed when not all of the line was
// drawn)
- (void)syn_finish_line(false);
+ syn_finish_line(false);
// Compare the current state with the previously saved state of
// the line.
@@ -1381,7 +1378,7 @@ bool syntax_check_changed(linenr_T lnum)
// Store the current state in b_sst_array[] for later use.
current_lnum++;
- (void)store_current_state();
+ store_current_state();
}
}
@@ -1397,7 +1394,7 @@ bool syntax_check_changed(linenr_T lnum)
static bool syn_finish_line(const bool syncing)
{
while (!current_finished) {
- (void)syn_current_attr(syncing, false, NULL, false);
+ syn_current_attr(syncing, false, NULL, false);
// When syncing, and found some item, need to check the item.
if (syncing && current_state.ga_len) {
@@ -1520,7 +1517,7 @@ static int syn_current_attr(const bool syncing, const bool displaying, bool *con
// If we found a match after the last column, use it.
if (next_match_idx >= 0 && next_match_col >= (int)current_col
&& next_match_col != MAXCOL) {
- (void)push_next_match();
+ push_next_match();
}
current_finished = true;
@@ -2418,8 +2415,8 @@ static void find_endpos(int idx, lpos_T *startpos, lpos_T *m_endpos, lpos_T *hl_
regmatch.rmm_ic = spp->sp_ic;
regmatch.regprog = spp->sp_prog;
- int r = syn_regexec(&regmatch, startpos->lnum, lc_col,
- IF_SYN_TIME(&spp->sp_time));
+ bool r = syn_regexec(&regmatch, startpos->lnum, lc_col,
+ IF_SYN_TIME(&spp->sp_time));
spp->sp_prog = regmatch.regprog;
if (r) {
if (best_idx == -1 || regmatch.startpos[0].col
@@ -2665,7 +2662,7 @@ static char *syn_getcurline(void)
// Call vim_regexec() to find a match with "rmp" in "syn_buf".
// Returns true when there is a match.
-static int syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T *st)
+static bool syn_regexec(regmmatch_T *rmp, linenr_T lnum, colnr_T col, syn_time_T *st)
{
int timed_out = 0;
proftime_T pt;
@@ -3369,7 +3366,7 @@ static void syn_list_one(const int id, const bool syncing, const bool link_only)
continue;
}
- (void)syn_list_header(did_header, 0, id, true);
+ syn_list_header(did_header, 0, id, true);
did_header = true;
last_matchgroup = 0;
if (spp->sp_type == SPTYPE_MATCH) {
@@ -3422,7 +3419,7 @@ static void syn_list_one(const int id, const bool syncing, const bool link_only)
// list the link, if there is one
if (highlight_link_id(id - 1) && (did_header || link_only) && !got_int) {
- (void)syn_list_header(did_header, 0, id, true);
+ syn_list_header(did_header, 0, id, true);
msg_puts_attr("links to", attr);
msg_putchar(' ');
msg_outtrans(highlight_group_name(highlight_link_id(id - 1) - 1), 0);
@@ -3644,23 +3641,17 @@ static bool syn_list_keywords(const int id, const hashtab_T *const ht, bool did_
static void syn_clear_keyword(int id, hashtab_T *ht)
{
- hashitem_T *hi;
- keyentry_T *kp;
- keyentry_T *kp_prev;
- keyentry_T *kp_next;
- int todo;
-
hash_lock(ht);
- todo = (int)ht->ht_used;
- for (hi = ht->ht_array; todo > 0; hi++) {
+ int todo = (int)ht->ht_used;
+ for (hashitem_T *hi = ht->ht_array; todo > 0; hi++) {
if (HASHITEM_EMPTY(hi)) {
continue;
}
todo--;
- kp_prev = NULL;
- for (kp = HI2KE(hi); kp != NULL;) {
+ keyentry_T *kp_prev = NULL;
+ for (keyentry_T *kp = HI2KE(hi); kp != NULL;) {
if (kp->k_syn.id == id) {
- kp_next = kp->ke_next;
+ keyentry_T *kp_next = kp->ke_next;
if (kp_prev == NULL) {
if (kp_next == NULL) {
hash_remove(ht, hi);
@@ -3686,16 +3677,13 @@ static void syn_clear_keyword(int id, hashtab_T *ht)
// Clear a whole keyword table.
static void clear_keywtab(hashtab_T *ht)
{
- hashitem_T *hi;
- int todo;
- keyentry_T *kp;
keyentry_T *kp_next;
- todo = (int)ht->ht_used;
- for (hi = ht->ht_array; todo > 0; hi++) {
+ int todo = (int)ht->ht_used;
+ for (hashitem_T *hi = ht->ht_array; todo > 0; hi++) {
if (!HASHITEM_EMPTY(hi)) {
todo--;
- for (kp = HI2KE(hi); kp != NULL; kp = kp_next) {
+ for (keyentry_T *kp = HI2KE(hi); kp != NULL; kp = kp_next) {
kp_next = kp->ke_next;
xfree(kp->next_list);
xfree(kp->k_syn.cont_in_list);
@@ -3791,9 +3779,7 @@ static char *get_group_name(char *arg, char **name_end)
/// Return NULL for any error;
static char *get_syn_options(char *arg, syn_opt_arg_T *opt, int *conceal_char, int skip)
{
- int syn_id;
int len = 0;
- char *p;
int fidx;
static const struct flag {
char *name;
@@ -3837,7 +3823,7 @@ static char *get_syn_options(char *arg, syn_opt_arg_T *opt, int *conceal_char, i
}
for (fidx = ARRAY_SIZE(flagtab); --fidx >= 0;) {
- p = flagtab[fidx].name;
+ char *p = flagtab[fidx].name;
int i;
for (i = 0, len = 0; p[i] != NUL; i += 2, len++) {
if (arg[len] != p[i] && arg[len] != p[i + 1]) {
@@ -3906,7 +3892,7 @@ static char *get_syn_options(char *arg, syn_opt_arg_T *opt, int *conceal_char, i
if (strcmp(gname, "NONE") == 0) {
*opt->sync_idx = NONE_IDX;
} else {
- syn_id = syn_name2id(gname);
+ int syn_id = syn_name2id(gname);
int i;
for (i = curwin->w_s->b_syn_patterns.ga_len; --i >= 0;) {
if (SYN_ITEMS(curwin->w_s)[i].sp_syn.id == syn_id
@@ -3962,10 +3948,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
char *arg = eap->arg;
int sgl_id = 1;
char *group_name_end;
- char *rest;
const char *errormsg = NULL;
- int prev_toplvl_grp;
- int prev_syn_inc_tag;
bool source = false;
eap->nextcmd = find_nextcmd(arg);
@@ -3975,7 +3958,7 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
if (arg[0] == '@') {
arg++;
- rest = get_group_name(arg, &group_name_end);
+ char *rest = get_group_name(arg, &group_name_end);
if (rest == NULL) {
emsg(_("E397: Filename required"));
return;
@@ -4011,9 +3994,9 @@ static void syn_cmd_include(exarg_T *eap, int syncing)
emsg(_("E847: Too many syntax includes"));
return;
}
- prev_syn_inc_tag = current_syn_inc_tag;
+ int prev_syn_inc_tag = current_syn_inc_tag;
current_syn_inc_tag = ++running_syn_inc_tag;
- prev_toplvl_grp = curwin->w_s->b_syn_topgrp;
+ int prev_toplvl_grp = curwin->w_s->b_syn_topgrp;
curwin->w_s->b_syn_topgrp = sgl_id;
if (source
? do_source(eap->arg, false, DOSO_NONE, NULL) == FAIL
@@ -4030,15 +4013,11 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing)
char *arg = eap->arg;
char *group_name_end;
int syn_id;
- char *rest;
char *keyword_copy = NULL;
- char *p;
- char *kw;
syn_opt_arg_T syn_opt_arg;
- int cnt;
int conceal_char = NUL;
- rest = get_group_name(arg, &group_name_end);
+ char *rest = get_group_name(arg, &group_name_end);
if (rest != NULL) {
if (eap->skip) {
@@ -4061,8 +4040,8 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing)
// The options given apply to ALL keywords, so all options must be
// found before keywords can be created.
// 1: collect the options and copy the keywords to keyword_copy.
- cnt = 0;
- p = keyword_copy;
+ int cnt = 0;
+ char *p = keyword_copy;
for (; rest != NULL && !ends_excmd(*rest); rest = skipwhite(rest)) {
rest = get_syn_options(rest, &syn_opt_arg, &conceal_char, eap->skip);
if (rest == NULL || ends_excmd(*rest)) {
@@ -4084,7 +4063,7 @@ static void syn_cmd_keyword(exarg_T *eap, int syncing)
syn_incl_toplevel(syn_id, &syn_opt_arg.flags);
// 2: Add an entry for each keyword.
- for (kw = keyword_copy; --cnt >= 0; kw += strlen(kw) + 1) {
+ for (char *kw = keyword_copy; --cnt >= 0; kw += strlen(kw) + 1) {
for (p = vim_strchr(kw, '[');;) {
if (p != NULL) {
*p = NUL;
@@ -4235,7 +4214,6 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
char *rest; // next arg, NULL on error
char *key_end;
char *key = NULL;
- char *p;
int item;
#define ITEM_START 0
#define ITEM_SKIP 1
@@ -4318,7 +4296,7 @@ static void syn_cmd_region(exarg_T *eap, int syncing)
}
if (item == ITEM_MATCHGROUP) {
- p = skiptowhite(rest);
+ char *p = skiptowhite(rest);
if ((p - rest == 4 && strncmp(rest, "NONE", 4) == 0) || eap->skip) {
matchgroup_id = 0;
} else {
@@ -4645,7 +4623,6 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing)
{
char *arg = eap->arg;
char *group_name_end;
- char *rest;
bool got_clstr = false;
int opt_len;
int list_op;
@@ -4655,7 +4632,7 @@ static void syn_cmd_cluster(exarg_T *eap, int syncing)
return;
}
- rest = get_group_name(arg, &group_name_end);
+ char *rest = get_group_name(arg, &group_name_end);
if (rest != NULL) {
int scl_id = syn_check_cluster(arg, (int)(group_name_end - arg));
@@ -4722,7 +4699,6 @@ static void init_syn_patterns(void)
/// @return a pointer to the next argument, or NULL in case of an error.
static char *get_syn_pattern(char *arg, synpat_T *ci)
{
- int *p;
int idx;
// need at least three chars
@@ -4759,7 +4735,7 @@ static char *get_syn_pattern(char *arg, synpat_T *ci)
}
}
if (idx >= 0) {
- p = &(ci->sp_offsets[idx]);
+ int *p = &(ci->sp_offsets[idx]);
if (idx != SPO_LC_OFF) {
switch (end[3]) {
case 's':
@@ -4812,12 +4788,9 @@ static char *get_syn_pattern(char *arg, synpat_T *ci)
static void syn_cmd_sync(exarg_T *eap, int syncing)
{
char *arg_start = eap->arg;
- char *arg_end;
char *key = NULL;
- char *next_arg;
- int illegal = false;
- int finished = false;
- char *cpo_save;
+ bool illegal = false;
+ bool finished = false;
if (ends_excmd(*arg_start)) {
syn_cmd_list(eap, true);
@@ -4825,8 +4798,8 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
}
while (!ends_excmd(*arg_start)) {
- arg_end = skiptowhite(arg_start);
- next_arg = skipwhite(arg_end);
+ char *arg_end = skiptowhite(arg_start);
+ char *next_arg = skipwhite(arg_end);
xfree(key);
key = vim_strnsave_up(arg_start, (size_t)(arg_end - arg_start));
if (strcmp(key, "CCOMMENT") == 0) {
@@ -4896,7 +4869,7 @@ static void syn_cmd_sync(exarg_T *eap, int syncing)
curwin->w_s->b_syn_linecont_ic = curwin->w_s->b_syn_ic;
// Make 'cpoptions' empty, to avoid the 'l' flag
- cpo_save = p_cpo;
+ char *cpo_save = p_cpo;
p_cpo = empty_string_option;
curwin->w_s->b_syn_linecont_prog =
vim_regcomp(curwin->w_s->b_syn_linecont_pat, RE_MAGIC);
@@ -5128,10 +5101,8 @@ static int16_t *copy_id_list(const int16_t *const list)
static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, int contained)
{
int retval;
- int16_t *scl_list;
int16_t id = ssp->id;
static int depth = 0;
- int r;
// If ssp has a "containedin" list and "cur_si" is in it, return true.
if (cur_si != NULL && ssp->cont_in_list != NULL
@@ -5194,12 +5165,12 @@ static int in_id_list(stateitem_T *cur_si, int16_t *list, struct sp_syn *ssp, in
return retval;
}
if (item >= SYNID_CLUSTER) {
- scl_list = SYN_CLSTR(syn_block)[item - SYNID_CLUSTER].scl_list;
+ int16_t *scl_list = SYN_CLSTR(syn_block)[item - SYNID_CLUSTER].scl_list;
// restrict recursiveness to 30 to avoid an endless loop for a
// cluster that includes itself (indirectly)
if (scl_list != NULL && depth < 30) {
depth++;
- r = in_id_list(NULL, scl_list, ssp, contained);
+ int r = in_id_list(NULL, scl_list, ssp, contained);
depth--;
if (r) {
return retval;
@@ -5442,7 +5413,7 @@ int syn_get_id(win_T *wp, linenr_T lnum, colnr_T col, int trans, bool *spellp, i
next_match_idx = -1;
}
- (void)get_syntax_attr(col, spellp, keep_state);
+ get_syntax_attr(col, spellp, keep_state);
return trans ? current_trans_id : current_id;
}
@@ -5464,7 +5435,7 @@ int syn_get_concealed_id(win_T *wp, linenr_T lnum, colnr_T col)
{
int seqnr;
- (void)syn_get_id(wp, lnum, col, false, NULL, false);
+ syn_get_id(wp, lnum, col, false, NULL, false);
int syntax_flags = get_syntax_info(&seqnr);
if (syntax_flags & HL_CONCEAL) {
@@ -5524,7 +5495,7 @@ int syn_get_foldlevel(win_T *wp, linenr_T lnum)
int cur_level = level;
int low_level = cur_level;
while (!current_finished) {
- (void)syn_current_attr(false, false, NULL, false);
+ syn_current_attr(false, false, NULL, false);
cur_level = syn_cur_foldlevel();
if (cur_level < low_level) {
low_level = cur_level;
diff --git a/src/nvim/syntax.h b/src/nvim/syntax.h
index 4e9c7a27dc..69fc1a74b8 100644
--- a/src/nvim/syntax.h
+++ b/src/nvim/syntax.h
@@ -1,33 +1,32 @@
#pragma once
-#include <stdbool.h>
-
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
-#include "nvim/globals.h"
#include "nvim/macros_defs.h"
-#include "nvim/syntax_defs.h" // IWYU pragma: export
+#include "nvim/syntax_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
-#define HL_CONTAINED 0x01 // not used on toplevel
-#define HL_TRANSP 0x02 // has no highlighting
-#define HL_ONELINE 0x04 // match within one line only
-#define HL_HAS_EOL 0x08 // end pattern that matches with $
-#define HL_SYNC_HERE 0x10 // sync point after this item (syncing only)
-#define HL_SYNC_THERE 0x20 // sync point at current line (syncing only)
-#define HL_MATCH 0x40 // use match ID instead of item ID
-#define HL_SKIPNL 0x80 // nextgroup can skip newlines
-#define HL_SKIPWHITE 0x100 // nextgroup can skip white space
-#define HL_SKIPEMPTY 0x200 // nextgroup can skip empty lines
-#define HL_KEEPEND 0x400 // end match always kept
-#define HL_EXCLUDENL 0x800 // exclude NL from match
-#define HL_DISPLAY 0x1000 // only used for displaying, not syncing
-#define HL_FOLD 0x2000 // define fold
-#define HL_EXTEND 0x4000 // ignore a keepend
-#define HL_MATCHCONT 0x8000 // match continued from previous line
-#define HL_TRANS_CONT 0x10000 // transparent item without contains arg
-#define HL_CONCEAL 0x20000 // can be concealed
-#define HL_CONCEALENDS 0x40000 // can be concealed
+enum {
+ HL_CONTAINED = 0x01, ///< not used on toplevel
+ HL_TRANSP = 0x02, ///< has no highlighting
+ HL_ONELINE = 0x04, ///< match within one line only
+ HL_HAS_EOL = 0x08, ///< end pattern that matches with $
+ HL_SYNC_HERE = 0x10, ///< sync point after this item (syncing only)
+ HL_SYNC_THERE = 0x20, ///< sync point at current line (syncing only)
+ HL_MATCH = 0x40, ///< use match ID instead of item ID
+ HL_SKIPNL = 0x80, ///< nextgroup can skip newlines
+ HL_SKIPWHITE = 0x100, ///< nextgroup can skip white space
+ HL_SKIPEMPTY = 0x200, ///< nextgroup can skip empty lines
+ HL_KEEPEND = 0x400, ///< end match always kept
+ HL_EXCLUDENL = 0x800, ///< exclude NL from match
+ HL_DISPLAY = 0x1000, ///< only used for displaying, not syncing
+ HL_FOLD = 0x2000, ///< define fold
+ HL_EXTEND = 0x4000, ///< ignore a keepend
+ HL_MATCHCONT = 0x8000, ///< match continued from previous line
+ HL_TRANS_CONT = 0x10000, ///< transparent item without contains arg
+ HL_CONCEAL = 0x20000, ///< can be concealed
+ HL_CONCEALENDS = 0x40000, ///< can be concealed
+};
#define SYN_GROUP_STATIC(s) syn_check_group(S_LEN(s))
diff --git a/src/nvim/syntax_defs.h b/src/nvim/syntax_defs.h
index ae4997154e..94ca2c4cba 100644
--- a/src/nvim/syntax_defs.h
+++ b/src/nvim/syntax_defs.h
@@ -1,6 +1,6 @@
#pragma once
-#include "nvim/highlight_defs.h"
+#include "nvim/buffer_defs.h"
#define SST_MIN_ENTRIES 150 // minimal size for state stack array
#define SST_MAX_ENTRIES 1000 // maximal size for state stack array
@@ -8,11 +8,6 @@
#define SST_DIST 16 // normal distance between entries
#define SST_INVALID ((synstate_T *)-1) // invalid syn_state pointer
-typedef struct syn_state synstate_T;
-
-#include "nvim/buffer_defs.h"
-#include "nvim/regexp_defs.h"
-
// struct passed to in_id_list()
struct sp_syn {
int inc_tag; // ":syn include" unique tag
@@ -33,7 +28,7 @@ struct keyentry {
};
// Struct used to store one state of the state stack.
-typedef struct buf_state {
+typedef struct {
int bs_idx; // index of pattern
int bs_flags; // flags for pattern
int bs_seqnr; // stores si_seqnr
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index c6a1a13606..ab5bfc6773 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -10,9 +10,12 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/cmdexpand.h"
+#include "nvim/cmdexpand_defs.h"
#include "nvim/cursor.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
@@ -23,18 +26,22 @@
#include "nvim/file_search.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/help.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/input.h"
#include "nvim/insexpand.h"
#include "nvim/macros_defs.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
+#include "nvim/mbyte_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/move.h"
@@ -44,22 +51,25 @@
#include "nvim/optionstr.h"
#include "nvim/os/fs.h"
#include "nvim/os/input.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/time.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/quickfix.h"
#include "nvim/regexp.h"
+#include "nvim/regexp_defs.h"
#include "nvim/runtime.h"
#include "nvim/search.h"
#include "nvim/state_defs.h"
#include "nvim/strings.h"
#include "nvim/tag.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
// Structure to hold pointers to various items in a tag line.
-typedef struct tag_pointers {
+typedef struct {
// filled in by parse_tag_line():
char *tagname; // start of tag name (skip "file:")
char *tagname_end; // char after tag name
@@ -207,8 +217,8 @@ static char *tagmatchname = NULL; // name of last used tag
// normal tagstack.
static taggy_T ptag_entry = { NULL, INIT_FMARK, 0, 0, NULL };
-static int tfu_in_use = false; // disallow recursive call of tagfunc
-static Callback tfu_cb; // 'tagfunc' callback function
+static bool tfu_in_use = false; // disallow recursive call of tagfunc
+static Callback tfu_cb; // 'tagfunc' callback function
// Used instead of NUL to separate tag fields in the growarrays.
#define TAG_SEP 0x02
@@ -278,7 +288,7 @@ void set_buflocal_tfu_callback(buf_T *buf)
/// @param tag tag (pattern) to jump to
/// @param forceit :ta with !
/// @param verbose print "tag not found" message
-void do_tag(char *tag, int type, int count, int forceit, int verbose)
+void do_tag(char *tag, int type, int count, int forceit, bool verbose)
{
taggy_T *tagstack = curwin->w_tagstack;
int tagstackidx = curwin->w_tagstackidx;
@@ -287,17 +297,17 @@ void do_tag(char *tag, int type, int count, int forceit, int verbose)
int cur_fnum = curbuf->b_fnum;
int oldtagstackidx = tagstackidx;
int prevtagstackidx = tagstackidx;
- int new_tag = false;
- int no_regexp = false;
+ bool new_tag = false;
+ bool no_regexp = false;
int error_cur_match = 0;
- int save_pos = false;
+ bool save_pos = false;
fmark_T saved_fmark;
int new_num_matches;
char **new_matches;
- int use_tagstack;
- int skip_msg = false;
+ bool use_tagstack;
+ bool skip_msg = false;
char *buf_ffname = curbuf->b_ffname; // name for priority computation
- int use_tfu = 1;
+ bool use_tfu = true;
char *tofree = NULL;
// remember the matches for the last used tag
@@ -323,7 +333,7 @@ void do_tag(char *tag, int type, int count, int forceit, int verbose)
if (type == DT_HELP) {
type = DT_TAG;
no_regexp = true;
- use_tfu = 0;
+ use_tfu = false;
}
int prev_num_matches = num_matches;
@@ -378,7 +388,7 @@ void do_tag(char *tag, int type, int count, int forceit, int verbose)
for (int i = 1; i < tagstacklen; i++) {
tagstack[i - 1] = tagstack[i];
}
- tagstackidx--;
+ tagstack[--tagstackidx].user_data = NULL;
}
// put the tag name in the tag stack
@@ -545,7 +555,6 @@ void do_tag(char *tag, int type, int count, int forceit, int verbose)
// Repeat searching for tags, when a file has not been found.
while (true) {
- int other_name;
char *name;
// When desired match not found yet, try to find it (and others).
@@ -559,7 +568,7 @@ void do_tag(char *tag, int type, int count, int forceit, int verbose)
} else {
name = tag;
}
- other_name = (tagmatchname == NULL || strcmp(tagmatchname, name) != 0);
+ bool other_name = (tagmatchname == NULL || strcmp(tagmatchname, name) != 0);
if (new_tag
|| (cur_match >= num_matches && max_num_matches != MAXCOL)
|| other_name) {
@@ -716,7 +725,7 @@ void do_tag(char *tag, int type, int count, int forceit, int verbose)
smsg(0, _("File \"%s\" does not exist"), nofile_fname);
}
- int ic = (matches[cur_match][0] & MT_IC_OFF);
+ bool ic = (matches[cur_match][0] & MT_IC_OFF);
if (type != DT_TAG && type != DT_SELECT && type != DT_JUMP
&& (num_matches > 1 || ic)
&& !skip_msg) {
@@ -792,7 +801,7 @@ end_do_tag:
}
// List all the matching tags.
-static void print_tag_list(int new_tag, int use_tagstack, int num_matches, char **matches)
+static void print_tag_list(bool new_tag, bool use_tagstack, int num_matches, char **matches)
{
taggy_T *tagstack = curwin->w_tagstack;
int tagstackidx = curwin->w_tagstackidx;
@@ -1159,7 +1168,7 @@ static int tag_strnicmp(char *s1, char *s2, size_t len)
}
// Extract info from the tag search pattern "pats->pat".
-static void prepare_pats(pat_T *pats, int has_re)
+static void prepare_pats(pat_T *pats, bool has_re)
{
pats->head = pats->pat;
pats->headlen = pats->len;
@@ -1274,7 +1283,7 @@ static int find_tagfunc_tags(char *pat, garray_T *ga, int *match_count, int flag
char *res_fname;
char *res_cmd;
char *res_kind;
- int has_extra = 0;
+ bool has_extra = false;
int name_only = flags & TAG_NAMES;
if (TV_LIST_ITEM_TV(li)->v_type != VAR_DICT) {
@@ -1309,7 +1318,7 @@ static int find_tagfunc_tags(char *pat, garray_T *ga, int *match_count, int flag
res_cmd = tv->vval.v_string;
continue;
}
- has_extra = 1;
+ has_extra = true;
if (!strcmp(dict_key, "kind")) {
res_kind = tv->vval.v_string;
continue;
@@ -1529,7 +1538,7 @@ static int findtags_apply_tfu(findtags_state_T *st, char *pat, char *buf_ffname)
/// reached end of a emacs included tags file)
static tags_read_status_T findtags_get_next_line(findtags_state_T *st, tagsearch_info_T *sinfo_p)
{
- int eof;
+ bool eof;
// For binary search: compute the next offset to use.
if (st->state == TS_BINARY) {
@@ -1544,7 +1553,7 @@ static tags_read_status_T findtags_get_next_line(findtags_state_T *st, tagsearch
sinfo_p->curr_offset -= st->lbuf_size * 2;
if (sinfo_p->curr_offset < 0) {
sinfo_p->curr_offset = 0;
- (void)fseek(st->fp, 0, SEEK_SET);
+ fseek(st->fp, 0, SEEK_SET);
st->state = TS_STEP_FORWARD;
}
}
@@ -2303,7 +2312,7 @@ int find_tags(char *pat, int *num_matches, char ***matchesp, int flags, int minc
char *saved_pat = NULL; // copy of pat[]
int findall = (mincount == MAXCOL || mincount == TAG_MANY); // find all matching tags
- int has_re = (flags & TAG_REGEXP); // regexp used
+ bool has_re = (flags & TAG_REGEXP); // regexp used
int noic = (flags & TAG_NOIC);
int verbose = (flags & TAG_VERBOSE);
int save_p_ic = p_ic;
@@ -2563,7 +2572,7 @@ int get_tagfname(tagname_T *tnp, int first, char *buf)
// Copy next file name into buf.
buf[0] = NUL;
- (void)copy_option_part(&tnp->tn_np, buf, MAXPATHL - 1, " ,");
+ copy_option_part(&tnp->tn_np, buf, MAXPATHL - 1, " ,");
char *r_ptr = vim_findfile_stopdir(buf);
// move the filename one char forward and truncate the
@@ -2773,7 +2782,7 @@ static char *tag_full_fname(tagptrs_T *tagp)
/// @param keep_help keep help flag
///
/// @return OK for success, NOTAGFILE when file not found, FAIL otherwise.
-static int jumpto_tag(const char *lbuf_arg, int forceit, int keep_help)
+static int jumpto_tag(const char *lbuf_arg, int forceit, bool keep_help)
{
char *pbuf_end;
char *tofree_fname = NULL;
@@ -2946,11 +2955,10 @@ static int jumpto_tag(const char *lbuf_arg, int forceit, int keep_help)
// try again, ignore case now
p_ic = true;
- if (!do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, 1,
- search_options, NULL)) {
+ if (!do_search(NULL, pbuf[0], pbuf[0], pbuf + 1, 1, search_options, NULL)) {
// Failed to find pattern, take a guess: "^func ("
found = 2;
- (void)test_for_static(&tagp);
+ test_for_static(&tagp);
char cc = *tagp.tagname_end;
*tagp.tagname_end = NUL;
snprintf(pbuf, LSIZE, "^%s\\s\\*(", tagp.tagname);
@@ -3170,7 +3178,7 @@ static void tagstack_clear_entry(taggy_T *item)
}
/// @param tagnames expand tag names
-int expand_tags(int tagnames, char *pat, int *num_file, char ***file)
+int expand_tags(bool tagnames, char *pat, int *num_file, char ***file)
{
int extra_flag;
size_t name_buf_size = 100;
@@ -3202,10 +3210,8 @@ int expand_tags(int tagnames, char *pat, int *num_file, char ***file)
parse_match((*file)[i], &t_p);
len = (size_t)(t_p.tagname_end - t_p.tagname);
if (len > name_buf_size - 3) {
- char *buf;
-
name_buf_size = len + 3;
- buf = xrealloc(name_buf, name_buf_size);
+ char *buf = xrealloc(name_buf, name_buf_size);
name_buf = buf;
}
@@ -3316,12 +3322,11 @@ int get_tags(list_T *list, char *pat, char *buf_fname)
// skip "file:" (static tag)
p += 4;
} else if (!ascii_iswhite(*p)) {
- char *n;
int len;
// Add extra field as a dict entry. Fields are
// separated by Tabs.
- n = p;
+ char *n = p;
while (*p != NUL && *p >= ' ' && *p < 127 && *p != ':') {
p++;
}
diff --git a/src/nvim/tag.h b/src/nvim/tag.h
index 87e71c8bef..42196b44b7 100644
--- a/src/nvim/tag.h
+++ b/src/nvim/tag.h
@@ -1,9 +1,9 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/option_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
enum { LSIZE = 512, }; ///< max. size of a line in the tags file
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
index 1527738165..b5a3cffe2f 100644
--- a/src/nvim/terminal.c
+++ b/src/nvim/terminal.c
@@ -43,26 +43,31 @@
#include <vterm.h>
#include <vterm_keycodes.h>
-#include "nvim/api/private/defs.h"
+#include "klib/kvec.h"
#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/change.h"
#include "nvim/channel.h"
+#include "nvim/channel_defs.h"
#include "nvim/cursor.h"
#include "nvim/drawline.h"
#include "nvim/drawscreen.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
+#include "nvim/event/defs.h"
+#include "nvim/event/loop.h"
#include "nvim/event/multiqueue.h"
#include "nvim/event/time.h"
#include "nvim/ex_docmd.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
@@ -74,19 +79,23 @@
#include "nvim/mouse.h"
#include "nvim/move.h"
#include "nvim/msgpack_rpc/channel_defs.h"
-#include "nvim/normal.h"
+#include "nvim/normal_defs.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/optionstr.h"
#include "nvim/pos_defs.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
+#include "nvim/strings.h"
#include "nvim/terminal.h"
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/vim_defs.h"
+#include "nvim/window.h"
-typedef struct terminal_state {
+typedef struct {
VimState state;
Terminal *term;
int save_rd; // saved value of RedrawingDisabled
@@ -154,6 +163,9 @@ struct terminal {
bool color_set[16];
+ // When there is a pending TermRequest autocommand, block and store input.
+ StringBuilder *pending_send;
+
size_t refcount; // reference count
};
@@ -169,6 +181,82 @@ static VTermScreenCallbacks vterm_screen_callbacks = {
static Set(ptr_t) invalidated_terminals = SET_INIT;
+static void emit_termrequest(void **argv)
+{
+ Terminal *term = argv[0];
+ char *payload = argv[1];
+ size_t payload_length = (size_t)argv[2];
+ StringBuilder *pending_send = argv[3];
+
+ buf_T *buf = handle_get_buffer(term->buf_handle);
+ String termrequest = { .data = payload, .size = payload_length };
+ Object data = STRING_OBJ(termrequest);
+ set_vim_var_string(VV_TERMREQUEST, payload, (ptrdiff_t)payload_length);
+ apply_autocmds_group(EVENT_TERMREQUEST, NULL, NULL, false, AUGROUP_ALL, buf, NULL, &data);
+ xfree(payload);
+
+ StringBuilder *term_pending_send = term->pending_send;
+ term->pending_send = NULL;
+ if (kv_size(*pending_send)) {
+ terminal_send(term, pending_send->items, pending_send->size);
+ kv_destroy(*pending_send);
+ }
+ if (term_pending_send != pending_send) {
+ term->pending_send = term_pending_send;
+ }
+ xfree(pending_send);
+}
+
+static void schedule_termrequest(Terminal *term, char *payload, size_t payload_length)
+{
+ term->pending_send = xmalloc(sizeof(StringBuilder));
+ kv_init(*term->pending_send);
+ multiqueue_put(main_loop.events, emit_termrequest, term, payload, (void *)payload_length,
+ term->pending_send);
+}
+
+static int on_osc(int command, VTermStringFragment frag, void *user)
+{
+ if (frag.str == NULL) {
+ return 0;
+ }
+ if (!has_event(EVENT_TERMREQUEST)) {
+ return 1;
+ }
+
+ StringBuilder request = KV_INITIAL_VALUE;
+ kv_printf(request, "\x1b]%d;", command);
+ kv_concat_len(request, frag.str, frag.len);
+ schedule_termrequest(user, request.items, request.size);
+ return 1;
+}
+
+static int on_dcs(const char *command, size_t commandlen, VTermStringFragment frag, void *user)
+{
+ if (command == NULL || frag.str == NULL) {
+ return 0;
+ }
+ if (!has_event(EVENT_TERMREQUEST)) {
+ return 1;
+ }
+
+ StringBuilder request = KV_INITIAL_VALUE;
+ kv_printf(request, "\x1bP%*s", (int)commandlen, command);
+ kv_concat_len(request, frag.str, frag.len);
+ schedule_termrequest(user, request.items, request.size);
+ return 1;
+}
+
+static VTermStateFallbacks vterm_fallbacks = {
+ .control = NULL,
+ .csi = NULL,
+ .osc = on_osc,
+ .dcs = on_dcs,
+ .apc = NULL,
+ .pm = NULL,
+ .sos = NULL,
+};
+
void terminal_init(void)
{
time_watcher_init(&main_loop, &refresh_timer, NULL);
@@ -189,7 +277,7 @@ void terminal_teardown(void)
static void term_output_callback(const char *s, size_t len, void *user_data)
{
- terminal_send((Terminal *)user_data, (char *)s, len);
+ terminal_send((Terminal *)user_data, s, len);
}
// public API {{{
@@ -205,36 +293,37 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
FUNC_ATTR_NONNULL_ALL
{
// Create a new terminal instance and configure it
- Terminal *rv = *termpp = xcalloc(1, sizeof(Terminal));
- rv->opts = opts;
- rv->cursor.visible = true;
+ Terminal *term = *termpp = xcalloc(1, sizeof(Terminal));
+ term->opts = opts;
+ term->cursor.visible = true;
// Associate the terminal instance with the new buffer
- rv->buf_handle = buf->handle;
- buf->terminal = rv;
+ term->buf_handle = buf->handle;
+ buf->terminal = term;
// Create VTerm
- rv->vt = vterm_new(opts.height, opts.width);
- vterm_set_utf8(rv->vt, 1);
+ term->vt = vterm_new(opts.height, opts.width);
+ vterm_set_utf8(term->vt, 1);
// Setup state
- VTermState *state = vterm_obtain_state(rv->vt);
+ VTermState *state = vterm_obtain_state(term->vt);
// Set up screen
- rv->vts = vterm_obtain_screen(rv->vt);
- vterm_screen_enable_altscreen(rv->vts, true);
- vterm_screen_enable_reflow(rv->vts, true);
+ term->vts = vterm_obtain_screen(term->vt);
+ vterm_screen_enable_altscreen(term->vts, true);
+ vterm_screen_enable_reflow(term->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);
- vterm_screen_reset(rv->vts, 1);
- vterm_output_set_callback(rv->vt, term_output_callback, rv);
+ vterm_screen_set_callbacks(term->vts, &vterm_screen_callbacks, term);
+ vterm_screen_set_unrecognised_fallbacks(term->vts, &vterm_fallbacks, term);
+ vterm_screen_set_damage_merge(term->vts, VTERM_DAMAGE_SCROLL);
+ vterm_screen_reset(term->vts, 1);
+ vterm_output_set_callback(term->vt, term_output_callback, term);
// force a initial refresh of the screen to ensure the buffer will always
// have as many lines as screen rows when refresh_scrollback is called
- rv->invalid_start = 0;
- rv->invalid_end = opts.height;
+ term->invalid_start = 0;
+ term->invalid_end = opts.height;
aco_save_T aco;
aucmd_prepbuf(&aco, buf);
- refresh_screen(rv, buf);
- set_option_value("buftype", STATIC_CSTR_AS_OPTVAL("terminal"), OPT_LOCAL);
+ refresh_screen(term, buf);
+ set_option_value(kOptBuftype, STATIC_CSTR_AS_OPTVAL("terminal"), OPT_LOCAL);
// Default settings for terminal buffers
buf->b_p_ma = false; // 'nomodifiable'
@@ -242,8 +331,8 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
buf->b_p_scbk = // 'scrollback' (initialize local from global)
(p_scbk < 0) ? 10000 : MAX(1, p_scbk);
buf->b_p_tw = 0; // 'textwidth'
- set_option_value("wrap", BOOLEAN_OPTVAL(false), OPT_LOCAL);
- set_option_value("list", BOOLEAN_OPTVAL(false), OPT_LOCAL);
+ set_option_value(kOptWrap, BOOLEAN_OPTVAL(false), OPT_LOCAL);
+ set_option_value(kOptList, BOOLEAN_OPTVAL(false), OPT_LOCAL);
if (buf->b_ffname != NULL) {
buf_set_term_title(buf, buf->b_ffname, strlen(buf->b_ffname));
}
@@ -251,7 +340,7 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
// Reset cursor in current window.
curwin->w_cursor = (pos_T){ .lnum = 1, .col = 0, .coladd = 0 };
// Initialize to check if the scrollback buffer has been allocated in a TermOpen autocmd.
- rv->sb_buffer = NULL;
+ term->sb_buffer = NULL;
// Apply TermOpen autocmds _before_ configuring the scrollback buffer.
apply_autocmds(EVENT_TERMOPEN, NULL, NULL, false, buf);
@@ -261,14 +350,14 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
return; // Terminal has already been destroyed.
}
- if (rv->sb_buffer == NULL) {
+ if (term->sb_buffer == NULL) {
// Local 'scrollback' _after_ autocmds.
if (buf->b_p_scbk < 1) {
buf->b_p_scbk = SB_MAX;
}
// Configure the scrollback buffer.
- rv->sb_size = (size_t)buf->b_p_scbk;
- rv->sb_buffer = xmalloc(sizeof(ScrollbackLine *) * rv->sb_size);
+ term->sb_size = (size_t)buf->b_p_scbk;
+ term->sb_buffer = xmalloc(sizeof(ScrollbackLine *) * term->sb_size);
}
// Configure the color palette. Try to get the color from:
@@ -277,14 +366,12 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
// - g:terminal_color_{NUM}
// - the VTerm instance
for (int i = 0; i < 16; i++) {
- RgbValue color_val = -1;
char var[64];
snprintf(var, sizeof(var), "terminal_color_%d", i);
char *name = get_config_string(var);
if (name) {
int dummy;
- color_val = name_to_color(name, &dummy);
- xfree(name);
+ RgbValue color_val = name_to_color(name, &dummy);
if (color_val != -1) {
VTermColor color;
@@ -293,7 +380,7 @@ void terminal_open(Terminal **termpp, buf_T *buf, TerminalOptions opts)
(uint8_t)((color_val >> 8) & 0xFF),
(uint8_t)((color_val >> 0) & 0xFF));
vterm_state_set_palette_color(state, i, &color);
- rv->color_set[i] = true;
+ term->color_set[i] = true;
}
}
}
@@ -388,7 +475,8 @@ void terminal_check_size(Terminal *term)
int curwidth, curheight;
vterm_get_size(term->vt, &curheight, &curwidth);
- uint16_t width = 0, height = 0;
+ uint16_t width = 0;
+ uint16_t height = 0;
// Check if there is a window that displays the terminal and find the maximum width and height.
// Skip the autocommand window which isn't actually displayed.
@@ -556,6 +644,8 @@ static int terminal_check(VimState *state)
curbuf->b_locked--;
}
+ may_trigger_win_scrolled_resized();
+
if (need_maketitle) { // Update title in terminal-mode. #7248
maketitle();
}
@@ -681,11 +771,15 @@ void terminal_destroy(Terminal **termpp)
}
}
-void terminal_send(Terminal *term, char *data, size_t size)
+static void terminal_send(Terminal *term, const char *data, size_t size)
{
if (term->closed) {
return;
}
+ if (term->pending_send) {
+ kv_concat_len(*term->pending_send, data, size);
+ return;
+ }
term->opts.write_cb(data, size, term->opts.data);
}
@@ -763,7 +857,7 @@ void terminal_paste(int count, char **y_array, size_t y_size)
vterm_keyboard_end_paste(curbuf->terminal->vt);
}
-void terminal_send_key(Terminal *term, int c)
+static void terminal_send_key(Terminal *term, int c)
{
VTermModifier mod = VTERM_MOD_NONE;
@@ -781,13 +875,27 @@ void terminal_send_key(Terminal *term, int c)
}
}
-void terminal_receive(Terminal *term, char *data, size_t len)
+void terminal_receive(Terminal *term, const char *data, size_t len)
{
if (!data) {
return;
}
- vterm_input_write(term->vt, data, len);
+ if (term->opts.force_crlf) {
+ StringBuilder crlf_data = KV_INITIAL_VALUE;
+
+ for (size_t i = 0; i < len; i++) {
+ if (data[i] == '\n' && (i == 0 || (i > 0 && data[i - 1] != '\r'))) {
+ kv_push(crlf_data, '\r');
+ }
+ kv_push(crlf_data, data[i]);
+ }
+
+ vterm_input_write(term->vt, crlf_data.items, kv_size(crlf_data));
+ kv_destroy(crlf_data);
+ } else {
+ vterm_input_write(term->vt, data, len);
+ }
vterm_screen_flush_damage(term->vts);
}
@@ -840,8 +948,8 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *te
bool fg_indexed = VTERM_COLOR_IS_INDEXED(&cell.fg);
bool bg_indexed = VTERM_COLOR_IS_INDEXED(&cell.bg);
- int vt_fg_idx = ((!fg_default && fg_indexed) ? cell.fg.indexed.idx + 1 : 0);
- int vt_bg_idx = ((!bg_default && bg_indexed) ? cell.bg.indexed.idx + 1 : 0);
+ int16_t vt_fg_idx = ((!fg_default && fg_indexed) ? cell.fg.indexed.idx + 1 : 0);
+ int16_t vt_bg_idx = ((!bg_default && bg_indexed) ? cell.bg.indexed.idx + 1 : 0);
bool fg_set = vt_fg_idx && vt_fg_idx <= 16 && term->color_set[vt_fg_idx - 1];
bool bg_set = vt_bg_idx && vt_bg_idx <= 16 && term->color_set[vt_bg_idx - 1];
@@ -866,6 +974,7 @@ void terminal_get_line_attributes(Terminal *term, win_T *wp, int linenr, int *te
.rgb_bg_color = vt_bg,
.rgb_sp_color = -1,
.hl_blend = -1,
+ .url = -1,
});
}
@@ -926,6 +1035,7 @@ static void buf_set_term_title(buf_T *buf, const char *title, size_t len)
STRING_OBJ(((String){ .data = (char *)title, .size = len })),
false,
false,
+ NULL,
&err);
api_clear_error(&err);
status_redraw_buf(buf);
@@ -1414,15 +1524,19 @@ static void mouse_action(Terminal *term, int button, int row, int col, bool pres
// terminal should lose focus
static bool send_mouse_event(Terminal *term, int c)
{
- int row = mouse_row, col = mouse_col, grid = mouse_grid;
+ int row = mouse_row;
+ int col = mouse_col;
+ int grid = mouse_grid;
win_T *mouse_win = mouse_find_win(&grid, &row, &col);
if (mouse_win == NULL) {
goto end;
}
int offset;
- if (term->forward_mouse && mouse_win->w_buffer->terminal == term
- && col >= (offset = win_col_off(mouse_win))) {
+ if (term->forward_mouse && mouse_win->w_buffer->terminal == term && row >= 0
+ && (grid > 1 || row + mouse_win->w_winbar_height < mouse_win->w_height)
+ && col >= (offset = win_col_off(mouse_win))
+ && (grid > 1 || col < mouse_win->w_width)) {
// event in the terminal window and mouse events was enabled by the
// program. translate and forward the event
int button;
@@ -1802,10 +1916,10 @@ static char *get_config_string(char *key)
{
Error err = ERROR_INIT;
// Only called from terminal_open where curbuf->terminal is the context.
- Object obj = dict_get_value(curbuf->b_vars, cstr_as_string(key), &err);
+ Object obj = dict_get_value(curbuf->b_vars, cstr_as_string(key), NULL, &err);
api_clear_error(&err);
if (obj.type == kObjectTypeNil) {
- obj = dict_get_value(&globvardict, cstr_as_string(key), &err);
+ obj = dict_get_value(&globvardict, cstr_as_string(key), NULL, &err);
api_clear_error(&err);
}
if (obj.type == kObjectTypeString) {
diff --git a/src/nvim/terminal.h b/src/nvim/terminal.h
index 66cad7ee7a..317003c0d2 100644
--- a/src/nvim/terminal.h
+++ b/src/nvim/terminal.h
@@ -1,21 +1,23 @@
#pragma once
+#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
-typedef struct terminal Terminal;
-typedef void (*terminal_write_cb)(char *buffer, size_t size, void *data);
+#include "nvim/api/private/defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h" // IWYU pragma: keep
+
+typedef void (*terminal_write_cb)(const char *buffer, size_t size, void *data);
typedef void (*terminal_resize_cb)(uint16_t width, uint16_t height, void *data);
typedef void (*terminal_close_cb)(void *data);
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
-
typedef struct {
void *data; // PTY process channel
uint16_t width, height;
terminal_write_cb write_cb;
terminal_resize_cb resize_cb;
terminal_close_cb close_cb;
+ bool force_crlf;
} TerminalOptions;
#ifdef INCLUDE_GENERATED_DECLARATIONS
diff --git a/src/nvim/testing.c b/src/nvim/testing.c
index cada04d276..343568d71e 100644
--- a/src/nvim/testing.c
+++ b/src/nvim/testing.c
@@ -12,17 +12,19 @@
#include "nvim/eval/typval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_docmd.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/garray_defs.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/hashtab.h"
+#include "nvim/hashtab_defs.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/os/fs.h"
#include "nvim/runtime.h"
+#include "nvim/runtime_defs.h"
#include "nvim/strings.h"
#include "nvim/testing.h"
#include "nvim/types_defs.h"
diff --git a/src/nvim/textformat.c b/src/nvim/textformat.c
index b69d438a59..bfe3ed5972 100644
--- a/src/nvim/textformat.c
+++ b/src/nvim/textformat.c
@@ -14,12 +14,10 @@
#include "nvim/eval.h"
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
-#include "nvim/func_attr.h"
#include "nvim/getchar.h"
#include "nvim/globals.h"
#include "nvim/indent.h"
#include "nvim/indent_c.h"
-#include "nvim/macros_defs.h"
#include "nvim/mark.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
@@ -28,6 +26,7 @@
#include "nvim/move.h"
#include "nvim/ops.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/os/input.h"
#include "nvim/pos_defs.h"
@@ -79,10 +78,10 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on
bool first_line = true;
colnr_T leader_len;
bool no_leader = false;
- int do_comments = (flags & INSCHAR_DO_COM);
+ bool do_comments = (flags & INSCHAR_DO_COM);
int has_lbr = curwin->w_p_lbr;
- // make sure win_lbr_chartabsize() counts correctly
+ // make sure win_charsize() counts correctly
curwin->w_p_lbr = false;
// When 'ai' is off we don't want a space under the cursor to be
@@ -102,17 +101,19 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on
int wantcol; // column at textwidth border
int foundcol; // column for start of spaces
int end_foundcol = 0; // column for start of word
- colnr_T virtcol;
int orig_col = 0;
char *saved_text = NULL;
colnr_T col;
- colnr_T end_col;
bool did_do_comment = false;
- virtcol = get_nolist_virtcol()
- + char2cells(c != NUL ? c : gchar_cursor());
- if (virtcol <= (colnr_T)textwidth) {
- break;
+ // Cursor is currently at the end of line. No need to format
+ // if line length is less than textwidth (8 * textwidth for
+ // utf safety)
+ if (curwin->w_cursor.col < 8 * textwidth) {
+ colnr_T virtcol = get_nolist_virtcol() + char2cells(c != NUL ? c : gchar_cursor());
+ if (virtcol <= (colnr_T)textwidth) {
+ break;
+ }
}
if (no_leader) {
@@ -160,9 +161,16 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on
coladvance((colnr_T)textwidth);
wantcol = curwin->w_cursor.col;
- curwin->w_cursor.col = startcol;
+ // If startcol is large (a long line), formatting takes too much
+ // time. The algorithm is O(n^2), it walks from the end of the
+ // line to textwidth border every time for each line break.
+ //
+ // Ceil to 8 * textwidth to optimize.
+ curwin->w_cursor.col = startcol < 8 * textwidth ? startcol : 8 * textwidth;
+
foundcol = 0;
int skip_pos = 0;
+ bool first_pass = true;
// Find position to break at.
// Stop at first entered white when 'formatoptions' has 'v'
@@ -170,14 +178,15 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on
|| (flags & INSCHAR_FORMAT)
|| curwin->w_cursor.lnum != Insstart.lnum
|| curwin->w_cursor.col >= Insstart.col) {
- if (curwin->w_cursor.col == startcol && c != NUL) {
+ if (first_pass && c != NUL) {
cc = c;
+ first_pass = false;
} else {
cc = gchar_cursor();
}
if (WHITECHAR(cc)) {
// remember position of blank just before text
- end_col = curwin->w_cursor.col;
+ colnr_T end_col = curwin->w_cursor.col;
// find start of sequence of blanks
int wcc = 0; // counter for whitespace chars
@@ -421,7 +430,7 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on
ins_str(" ");
}
} else {
- (void)set_indent(second_indent, SIN_CHANGED);
+ set_indent(second_indent, SIN_CHANGED);
}
}
}
@@ -474,9 +483,7 @@ void internal_format(int textwidth, int second_indent, int flags, bool format_on
static int fmt_check_par(linenr_T lnum, int *leader_len, char **leader_flags, bool do_comments)
{
char *flags = NULL; // init for GCC
- char *ptr;
-
- ptr = ml_get(lnum);
+ char *ptr = ml_get(lnum);
if (do_comments) {
*leader_len = get_leader_len(ptr, leader_flags, false, true);
} else {
@@ -626,8 +633,6 @@ static bool paragraph_start(linenr_T lnum)
/// @param prev_line may start in previous line
void auto_format(bool trailblank, bool prev_line)
{
- char *linep;
-
if (!has_format_option(FO_AUTO)) {
return;
}
@@ -679,7 +684,7 @@ void auto_format(bool trailblank, bool prev_line)
// Do the formatting and restore the cursor position. "saved_cursor" will
// be adjusted for the text formatting.
saved_cursor = pos;
- format_lines((linenr_T) - 1, false);
+ format_lines(-1, false);
curwin->w_cursor = saved_cursor;
saved_cursor.lnum = 0;
@@ -696,7 +701,7 @@ void auto_format(bool trailblank, bool prev_line)
// need to add a space when 'w' is in 'formatoptions' to keep a paragraph
// formatted.
if (!wasatend && has_format_option(FO_WHITE_PAR)) {
- linep = get_cursor_line_ptr();
+ char *linep = get_cursor_line_ptr();
colnr_T len = (colnr_T)strlen(linep);
if (curwin->w_cursor.col == len) {
char *plinep = xstrnsave(linep, (size_t)len + 2);
@@ -758,11 +763,11 @@ int comp_textwidth(bool ff)
// The width is the window width minus 'wrapmargin' minus all the
// things that add to the margin.
textwidth = curwin->w_width_inner - (int)curbuf->b_p_wm;
- if (cmdwin_type != 0) {
+ if (curbuf == cmdwin_buf) {
textwidth -= 1;
}
textwidth -= win_fdccol_count(curwin);
- textwidth -= win_signcol_count(curwin);
+ textwidth -= curwin->w_scwidth;
if (curwin->w_p_nu || curwin->w_p_rnu) {
textwidth -= 8;
@@ -871,7 +876,7 @@ void op_formatexpr(oparg_T *oap)
/// @param c character to be inserted
int fex_format(linenr_T lnum, long count, int c)
{
- int use_sandbox = was_set_insecurely(curwin, "formatexpr", OPT_LOCAL);
+ bool use_sandbox = was_set_insecurely(curwin, kOptFormatexpr, OPT_LOCAL);
const sctx_T save_sctx = current_sctx;
// Set v:lnum to the first line number and v:count to the number of lines.
@@ -1054,7 +1059,7 @@ void format_lines(linenr_T line_count, bool avoid_fex)
indent = get_indent();
}
}
- (void)set_indent(indent, SIN_CHANGED);
+ set_indent(indent, SIN_CHANGED);
}
// put cursor on last non-space
@@ -1098,13 +1103,13 @@ void format_lines(linenr_T line_count, bool avoid_fex)
break;
}
if (next_leader_len > 0) {
- (void)del_bytes(next_leader_len, false, false);
+ del_bytes(next_leader_len, false, false);
mark_col_adjust(curwin->w_cursor.lnum, 0, 0, -next_leader_len, 0);
} else if (second_indent > 0) { // the "leader" for FO_Q_SECOND
int indent = (int)getwhitecols_curline();
if (indent > 0) {
- (void)del_bytes(indent, false, false);
+ del_bytes(indent, false, false);
mark_col_adjust(curwin->w_cursor.lnum, 0, 0, -indent, 0);
}
}
diff --git a/src/nvim/textobject.c b/src/nvim/textobject.c
index d4310d47a4..d9c2b3b111 100644
--- a/src/nvim/textobject.c
+++ b/src/nvim/textobject.c
@@ -6,16 +6,16 @@
#include <string.h>
#include "nvim/ascii_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/cursor.h"
#include "nvim/drawscreen.h"
#include "nvim/edit.h"
#include "nvim/eval/funcs.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/indent.h"
-#include "nvim/macros_defs.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
@@ -170,14 +170,13 @@ found:
/// @return true if the next paragraph or section was found.
bool findpar(bool *pincl, int dir, int count, int what, bool both)
{
- linenr_T curr;
bool first; // true on first line
linenr_T fold_first; // first line of a closed fold
linenr_T fold_last; // last line of a closed fold
bool fold_skipped; // true if a closed fold was skipped this
// iteration
- curr = curwin->w_cursor.lnum;
+ linenr_T curr = curwin->w_cursor.lnum;
while (count--) {
bool did_skip = false; // true after separating lines have been skipped
@@ -214,7 +213,7 @@ bool findpar(bool *pincl, int dir, int count, int what, bool both)
curr++;
}
curwin->w_cursor.lnum = curr;
- if (curr == curbuf->b_ml.ml_line_count && what != '}') {
+ if (curr == curbuf->b_ml.ml_line_count && what != '}' && dir == FORWARD) {
char *line = ml_get(curr);
// Put the cursor on the last character in the last line and make the
@@ -260,9 +259,7 @@ static bool inmacro(char *opt, const char *s)
/// If 'both' is true also stop at '}'
bool startPS(linenr_T lnum, int para, bool both)
{
- char *s;
-
- s = ml_get(lnum);
+ char *s = ml_get(lnum);
if ((uint8_t)(*s) == para || *s == '\f' || (both && *s == '}')) {
return true;
}
@@ -294,9 +291,7 @@ static bool cls_bigword; ///< true for "W", "B" or "E"
/// boundaries are of interest.
static int cls(void)
{
- int c;
-
- c = gchar_cursor();
+ int c = gchar_cursor();
if (c == ' ' || c == '\t' || c == NUL) {
return 0;
}
@@ -535,9 +530,7 @@ static bool skip_chars(int cclass, int dir)
/// Go back to the start of the word or the start of white space
static void back_in_line(void)
{
- int sclass; // starting class
-
- sclass = cls();
+ int sclass = cls(); // starting class
while (true) {
if (curwin->w_cursor.col == 0) { // stop at start of line
break;
@@ -587,7 +580,7 @@ int current_word(oparg_T *oap, int count, bool include, bool bigword)
{
pos_T start_pos;
bool inclusive = true;
- int include_white = false;
+ bool include_white = false;
cls_bigword = bigword;
clearpos(&start_pos);
@@ -724,15 +717,13 @@ int current_word(oparg_T *oap, int count, bool include, bool bigword)
/// When Visual active, extend it by one or more sentences.
int current_sent(oparg_T *oap, int count, bool include)
{
- pos_T start_pos;
- pos_T pos;
bool start_blank;
int c;
bool at_start_sent;
int ncount;
- start_pos = curwin->w_cursor;
- pos = start_pos;
+ pos_T start_pos = curwin->w_cursor;
+ pos_T pos = start_pos;
findsent(FORWARD, 1); // Find start of next sentence.
// When the Visual area is bigger than one character: Extend it.
@@ -965,6 +956,13 @@ int current_block(oparg_T *oap, int count, bool include, int what, int other)
}
}
+ // In Visual mode, when resulting area is empty
+ // i.e. there is no inner block to select, abort.
+ if (equalpos(start_pos, *end_pos) && VIsual_active) {
+ curwin->w_cursor = old_pos;
+ return FAIL;
+ }
+
// In Visual mode, when the resulting area is not bigger than what we
// started with, extend it to the next block, and then exclude again.
// Don't try to expand the area if the area is empty.
@@ -1080,7 +1078,7 @@ int current_tagblock(oparg_T *oap, int count_arg, bool include)
bool do_include = include;
bool save_p_ws = p_ws;
int retval = FAIL;
- int is_inclusive = true;
+ bool is_inclusive = true;
p_ws = false;
@@ -1315,7 +1313,7 @@ extend:
}
// First move back to the start_lnum of the paragraph or white lines
- int white_in_front = linewhite(start_lnum);
+ bool white_in_front = linewhite(start_lnum);
while (start_lnum > 1) {
if (white_in_front) { // stop at first white line
if (!linewhite(start_lnum - 1)) {
diff --git a/src/nvim/textobject.h b/src/nvim/textobject.h
index a540c7c98f..735a2fec3d 100644
--- a/src/nvim/textobject.h
+++ b/src/nvim/textobject.h
@@ -2,7 +2,7 @@
#include "nvim/normal_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
-#include "nvim/vim_defs.h"
+#include "nvim/vim_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "textobject.h.generated.h"
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index bdbb5e4872..214474ff51 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -6,14 +6,16 @@
#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
-#include "nvim/event/defs.h"
-#include "nvim/func_attr.h"
+#include "nvim/event/loop.h"
+#include "nvim/event/stream.h"
#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/map_defs.h"
#include "nvim/memory.h"
#include "nvim/option_vars.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
+#include "nvim/rbuffer.h"
#include "nvim/strings.h"
#include "nvim/tui/input.h"
#include "nvim/tui/input_defs.h"
@@ -28,6 +30,11 @@
#define READ_STREAM_SIZE 0xfff
#define KEY_BUFFER_SIZE 0xfff
+/// Size of libtermkey's internal input buffer. The buffer may grow larger than
+/// this when processing very long escape sequences, but will shrink back to
+/// this size afterward
+#define INPUT_BUFFER_SIZE 256
+
static const struct kitty_key_map_entry {
int key;
const char *name;
@@ -140,6 +147,7 @@ void tinput_init(TermInput *input, Loop *loop)
input->tk = termkey_new_abstract(term,
TERMKEY_FLAG_UTF8 | TERMKEY_FLAG_NOSTART);
+ termkey_set_buffer_size(input->tk, INPUT_BUFFER_SIZE);
termkey_hook_terminfo_getstr(input->tk, input->tk_ti_hook_fn, input);
termkey_start(input->tk);
@@ -148,17 +156,17 @@ void tinput_init(TermInput *input, Loop *loop)
// setup input handle
rstream_init_fd(loop, &input->read_stream, input->in_fd, READ_STREAM_SIZE);
- termkey_set_buffer_size(input->tk, rbuffer_capacity(input->read_stream.buffer));
// initialize a timer handle for handling ESC with libtermkey
- time_watcher_init(loop, &input->timer_handle, input);
+ uv_timer_init(&loop->uv, &input->timer_handle);
+ input->timer_handle.data = input;
}
void tinput_destroy(TermInput *input)
{
map_destroy(int, &kitty_key_map);
rbuffer_free(input->key_buffer);
- time_watcher_close(&input->timer_handle, NULL);
+ uv_close((uv_handle_t *)&input->timer_handle, NULL);
stream_close(&input->read_stream, NULL, NULL);
termkey_destroy(input->tk);
}
@@ -171,7 +179,7 @@ void tinput_start(TermInput *input)
void tinput_stop(TermInput *input)
{
rstream_stop(&input->read_stream);
- time_watcher_stop(&input->timer_handle);
+ uv_timer_stop(&input->timer_handle);
}
static void tinput_done_event(void **argv)
@@ -231,13 +239,13 @@ static size_t handle_termkey_modifiers(TermKeyKey *key, char *buf, size_t buflen
{
size_t len = 0;
if (key->modifiers & TERMKEY_KEYMOD_SHIFT) { // Shift
- len += (size_t)snprintf(buf + len, sizeof(buf) - len, "S-");
+ len += (size_t)snprintf(buf + len, buflen - len, "S-");
}
if (key->modifiers & TERMKEY_KEYMOD_ALT) { // Alt
- len += (size_t)snprintf(buf + len, sizeof(buf) - len, "A-");
+ len += (size_t)snprintf(buf + len, buflen - len, "A-");
}
if (key->modifiers & TERMKEY_KEYMOD_CTRL) { // Ctrl
- len += (size_t)snprintf(buf + len, sizeof(buf) - len, "C-");
+ len += (size_t)snprintf(buf + len, buflen - len, "C-");
}
assert(len < buflen);
return len;
@@ -364,15 +372,6 @@ static void forward_mouse_event(TermInput *input, TermKeyKey *key)
button = last_pressed_button;
}
- if (ev == TERMKEY_MOUSE_UNKNOWN && !(key->code.mouse[0] & 0x20)) {
- int code = key->code.mouse[0] & ~0x3c;
- // https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h3-Other-buttons
- if (code == 66 || code == 67) {
- ev = TERMKEY_MOUSE_PRESS;
- button = code + 4 - 64;
- }
- }
-
if ((button == 0 && ev != TERMKEY_MOUSE_RELEASE)
|| (ev != TERMKEY_MOUSE_PRESS && ev != TERMKEY_MOUSE_DRAG && ev != TERMKEY_MOUSE_RELEASE)) {
return;
@@ -461,17 +460,16 @@ static void tk_getkeys(TermInput *input, bool force)
if (input->ttimeout && input->ttimeoutlen >= 0) {
// Stop the current timer if already running
- time_watcher_stop(&input->timer_handle);
- time_watcher_start(&input->timer_handle, tinput_timer_cb,
- (uint64_t)input->ttimeoutlen, 0);
+ uv_timer_stop(&input->timer_handle);
+ uv_timer_start(&input->timer_handle, tinput_timer_cb, (uint64_t)input->ttimeoutlen, 0);
} else {
tk_getkeys(input, true);
}
}
-static void tinput_timer_cb(TimeWatcher *watcher, void *data)
+static void tinput_timer_cb(uv_timer_t *handle)
{
- TermInput *input = (TermInput *)data;
+ TermInput *input = handle->data;
// If the raw buffer is not empty, process the raw buffer first because it is
// processing an incomplete bracketed paster sequence.
if (rbuffer_size(input->read_stream.buffer)) {
@@ -484,8 +482,8 @@ static void tinput_timer_cb(TimeWatcher *watcher, void *data)
/// Handle focus events.
///
/// If the upcoming sequence of bytes in the input stream matches the termcode
-/// for "focus gained" or "focus lost", consume that sequence and schedule an
-/// event on the main loop.
+/// for "focus gained" or "focus lost", consume that sequence and send an event
+/// to Nvim server.
///
/// @param input the input stream
/// @return true iff handle_focus_event consumed some input
@@ -692,20 +690,44 @@ static void handle_raw_buffer(TermInput *input, bool force)
}
// Push through libtermkey (translates to "<keycode>" strings, etc.).
RBUFFER_UNTIL_EMPTY(input->read_stream.buffer, ptr, len) {
- size_t consumed = termkey_push_bytes(input->tk, ptr, MIN(count, len));
- // termkey_push_bytes can return (size_t)-1, so it is possible that
- // `consumed > rbuffer_size(input->read_stream.buffer)`, but since tk_getkeys is
- // called soon, it shouldn't happen.
+ const size_t size = MIN(count, len);
+ if (size > termkey_get_buffer_remaining(input->tk)) {
+ // We are processing a very long escape sequence. Increase termkey's
+ // internal buffer size. We don't handle out of memory situations so
+ // abort if it fails
+ const size_t delta = size - termkey_get_buffer_remaining(input->tk);
+ const size_t bufsize = termkey_get_buffer_size(input->tk);
+ if (!termkey_set_buffer_size(input->tk, MAX(bufsize + delta, bufsize * 2))) {
+ abort();
+ }
+ }
+
+ size_t consumed = termkey_push_bytes(input->tk, ptr, size);
+
+ // We resize termkey's buffer when it runs out of space, so this should
+ // never happen
assert(consumed <= rbuffer_size(input->read_stream.buffer));
rbuffer_consumed(input->read_stream.buffer, consumed);
- // Process the keys now: there is no guarantee `count` will
- // fit into libtermkey's input buffer.
+
+ // Process the input buffer now for any keys
tk_getkeys(input, false);
+
if (!(count -= consumed)) {
break;
}
}
} while (rbuffer_size(input->read_stream.buffer));
+
+ const size_t tk_size = termkey_get_buffer_size(input->tk);
+ const size_t tk_remaining = termkey_get_buffer_remaining(input->tk);
+ const size_t tk_count = tk_size - tk_remaining;
+ if (tk_count < INPUT_BUFFER_SIZE && tk_size > INPUT_BUFFER_SIZE) {
+ // If the termkey buffer was resized to handle a large input sequence then
+ // shrink it back down to its original size.
+ if (!termkey_set_buffer_size(input->tk, INPUT_BUFFER_SIZE)) {
+ abort();
+ }
+ }
}
static void tinput_read_cb(Stream *stream, RBuffer *buf, size_t count_, void *data, bool eof)
@@ -713,7 +735,7 @@ static void tinput_read_cb(Stream *stream, RBuffer *buf, size_t count_, void *da
TermInput *input = data;
if (eof) {
- loop_schedule_fast(&main_loop, event_create(tinput_done_event, 0));
+ loop_schedule_fast(&main_loop, event_create(tinput_done_event, NULL));
return;
}
@@ -728,8 +750,8 @@ static void tinput_read_cb(Stream *stream, RBuffer *buf, size_t count_, void *da
int64_t ms = input->ttimeout
? (input->ttimeoutlen >= 0 ? input->ttimeoutlen : 0) : 0;
// Stop the current timer if already running
- time_watcher_stop(&input->timer_handle);
- time_watcher_start(&input->timer_handle, tinput_timer_cb, (uint32_t)ms, 0);
+ uv_timer_stop(&input->timer_handle);
+ uv_timer_start(&input->timer_handle, tinput_timer_cb, (uint32_t)ms, 0);
return;
}
diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h
index 2743a5e286..bf6d0f2978 100644
--- a/src/nvim/tui/input.h
+++ b/src/nvim/tui/input.h
@@ -2,16 +2,14 @@
#include <stdbool.h>
#include <stdint.h>
-#include <termkey.h>
#include <uv.h>
-#include "nvim/event/loop.h"
-#include "nvim/event/stream.h"
-#include "nvim/event/time.h"
-#include "nvim/rbuffer.h"
-#include "nvim/tui/input_defs.h" // IWYU pragma: export
-#include "nvim/tui/tui.h"
+#include "nvim/event/defs.h"
+#include "nvim/rbuffer_defs.h"
+#include "nvim/tui/input_defs.h" // IWYU pragma: keep
+#include "nvim/tui/tui_defs.h"
#include "nvim/types_defs.h"
+#include "termkey/termkey.h"
typedef enum {
kKeyEncodingLegacy, ///< Legacy key encoding
@@ -33,7 +31,7 @@ typedef struct {
OptInt ttimeoutlen;
TermKey *tk;
TermKey_Terminfo_Getstr_Hook *tk_ti_hook_fn; ///< libtermkey terminfo hook
- TimeWatcher timer_handle;
+ uv_timer_t timer_handle;
Loop *loop;
Stream read_stream;
RBuffer *key_buffer;
diff --git a/src/nvim/tui/terminfo_defs.h b/src/nvim/tui/terminfo_defs.h
index e221e80d1e..74ba23e4d9 100644
--- a/src/nvim/tui/terminfo_defs.h
+++ b/src/nvim/tui/terminfo_defs.h
@@ -1,6 +1,6 @@
// uncrustify:off
-// Generated by scripts/update_terminfo.sh and ncurses 6.4.20221231
+// Generated by scripts/update_terminfo.sh and ncurses 6.4.20230520
#pragma once
@@ -158,6 +158,7 @@ static const int8_t ansi_terminfo[] = {
// key_a3=\EOy,
// key_b2=\E[G,
// key_backspace=^H,
+// key_beg=\EOE,
// key_btab=\E[Z,
// key_c1=\EOq,
// key_c3=\EOs,
@@ -279,7 +280,9 @@ static const int8_t ansi_terminfo[] = {
// set_a_background=\E[48;5;%p1%dm,
// set_a_foreground=\E[38;5;%p1%dm,
// set_attributes=\E[0%?%p1%p3%|%t;7%;%?%p2%t;4%;%?%p6%t;1%;m,
+// set_left_margin_parm@,
// set_lr_margin@,
+// set_right_margin_parm@,
// set_tab@,
// tab=^I,
// user6@,
@@ -287,7 +290,7 @@ static const int8_t ansi_terminfo[] = {
// user8@,
// user9@,
static const int8_t conemu_terminfo[] = {
- 30,2,61,0,38,0,15,0,-99,1,57,3,99,111,110,101,109,117,124,65,78,73,83,32,88,51,46,54,52,32,97,110,100,32,88,116,101,114,109,32,50,53,54,32,99,111,108,111,114,115,32,102,111,114,32,67,111,110,69,109,117,32,119,105,116,104,32,108,105,98,117,118,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,-2,-1,0,0,2,0,4,0,-2,-1,21,0,29,0,33,0,37,0,-1,-1,48,0,65,0,69,0,73,0,80,0,-1,-1,82,0,89,0,-1,-1,93,0,-2,-1,97,0,101,0,-1,-1,-1,-1,-2,-1,-2,-1,105,0,110,0,-1,-1,-2,-1,-2,-1,-2,-1,-1,-1,119,0,124,0,-127,0,-122,0,-2,-1,-113,0,-108,0,-1,-1,-2,-1,-99,0,-93,0,-2,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-87,0,-1,-1,-83,0,-1,-1,-1,-1,-1,-1,-81,0,-1,-1,-76,0,-1,-1,-1,-1,-1,-1,-1,-1,-72,0,-67,0,-61,0,-56,0,-51,0,-46,0,-41,0,-35,0,-29,0,-23,0,-17,0,-12,0,-1,-1,-7,0,-1,-1,-3,0,2,1,7,1,11,1,18,1,-1,-1,25,1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,29,1,-1,-1,32,1,41,1,50,1,59,1,68,1,77,1,86,1,95,1,104,1,113,1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,122,1,-2,-1,-2,-1,-1,-1,-1,-1,-114,1,-111,1,-100,1,-97,1,-95,1,-92,1,-2,-1,-1,-1,-49,1,-1,-1,-1,-1,-1,-1,-1,-1,-47,1,-43,1,-39,1,-35,1,-31,1,-1,-1,-1,-1,-2,-1,-1,-1,-27,1,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-23,1,-18,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-14,1,-1,-1,-1,-1,-7,1,-1,-1,-1,-1,-1,-1,-1,-1,0,2,7,2,14,2,-1,-1,-1,-1,21,2,-1,-1,28,2,-1,-1,-1,-1,-1,-1,35,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,42,2,48,2,54,2,60,2,66,2,72,2,78,2,84,2,90,2,96,2,102,2,108,2,114,2,120,2,126,2,-124,2,-118,2,-112,2,-106,2,-100,2,-94,2,-88,2,-82,2,-76,2,-70,2,-64,2,-58,2,-52,2,-46,2,-40,2,-33,2,-27,2,-21,2,-15,2,-9,2,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-3,2,2,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,9,3,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,18,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,23,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,29,3,43,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,27,91,66,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,91,48,109,0,27,91,63,49,48,52,57,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,76,0,8,0,27,91,51,126,0,27,91,66,0,27,91,91,65,0,27,91,50,49,126,0,27,91,91,66,0,27,91,91,67,0,27,91,91,68,0,27,91,91,69,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,68,0,27,91,54,126,0,27,91,53,126,0,27,91,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,91,65,0,27,69,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,54,37,116,59,49,37,59,109,0,9,0,27,79,119,0,27,79,121,0,27,91,71,0,27,79,113,0,27,79,115,0,27,91,90,0,27,91,52,126,0,27,79,77,0,27,91,51,59,50,126,0,27,91,52,59,50,126,0,27,91,49,59,50,126,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,50,51,36,0,27,91,50,52,36,0,27,91,49,49,94,0,27,91,49,50,94,0,27,91,49,51,94,0,27,91,49,52,94,0,27,91,49,53,94,0,27,91,49,55,94,0,27,91,49,56,94,0,27,91,49,57,94,0,27,91,50,48,94,0,27,91,50,49,94,0,27,91,50,51,94,0,27,91,50,52,94,0,27,91,50,53,94,0,27,91,50,54,94,0,27,91,50,56,94,0,27,91,50,57,94,0,27,91,51,49,94,0,27,91,49,59,54,83,0,27,91,51,50,94,0,27,91,51,51,94,0,27,91,51,52,94,0,27,91,50,51,64,0,27,91,50,52,64,0,27,91,49,75,0,27,91,63,54,57,108,0,27,91,51,57,59,52,57,109,0,27,91,51,109,0,27,91,50,51,109,0,27,91,51,56,59,53,59,37,112,49,37,100,109,0,27,91,52,56,59,53,59,37,112,49,37,100,109,0,0,2,0,0,0,74,0,92,0,-46,1,1,1,-2,-1,-2,-1,0,0,-2,-1,5,0,11,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,21,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,28,0,32,0,36,0,40,0,44,0,48,0,52,0,56,0,60,0,64,0,68,0,72,0,-2,-1,-2,-1,-2,-1,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,32,0,37,0,42,0,47,0,52,0,56,0,61,0,66,0,71,0,76,0,81,0,87,0,93,0,99,0,105,0,111,0,117,0,123,0,-127,0,-121,0,-115,0,-110,0,-105,0,-100,0,-95,0,-90,0,-84,0,-78,0,-72,0,-66,0,-60,0,-54,0,-48,0,-42,0,-36,0,-30,0,-24,0,-18,0,-12,0,-6,0,0,1,6,1,12,1,18,1,24,1,30,1,34,1,39,1,44,1,49,1,54,1,59,1,63,1,67,1,71,1,75,1,79,1,85,1,91,1,97,1,103,1,109,1,115,1,121,1,126,1,-125,1,27,91,51,74,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,91,49,59,50,65,0,27,79,120,0,27,79,116,0,27,79,118,0,27,79,114,0,27,79,69,0,27,79,107,0,27,79,108,0,27,79,111,0,27,79,110,0,27,79,106,0,27,79,109,0,27,79,112,0,65,88,0,88,84,0,67,114,0,67,115,0,69,51,0,77,115,0,83,101,0,83,115,0,88,77,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,107,97,50,0,107,98,49,0,107,98,51,0,107,99,50,0,107,112,53,0,107,112,65,68,68,0,107,112,67,77,65,0,107,112,68,73,86,0,107,112,68,79,84,0,107,112,77,85,76,0,107,112,83,85,66,0,107,112,90,82,79,0,114,109,120,120,0,115,109,120,120,0,120,109,0
+ 30,2,61,0,38,0,15,0,-99,1,61,3,99,111,110,101,109,117,124,65,78,73,83,32,88,51,46,54,52,32,97,110,100,32,88,116,101,114,109,32,50,53,54,32,99,111,108,111,114,115,32,102,111,114,32,67,111,110,69,109,117,32,119,105,116,104,32,108,105,98,117,118,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,-2,-1,0,0,2,0,4,0,-2,-1,21,0,29,0,33,0,37,0,-1,-1,48,0,65,0,69,0,73,0,80,0,-1,-1,82,0,89,0,-1,-1,93,0,-2,-1,97,0,101,0,-1,-1,-1,-1,-2,-1,-2,-1,105,0,110,0,-1,-1,-2,-1,-2,-1,-2,-1,-1,-1,119,0,124,0,-127,0,-122,0,-2,-1,-113,0,-108,0,-1,-1,-2,-1,-99,0,-93,0,-2,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-87,0,-1,-1,-83,0,-1,-1,-1,-1,-1,-1,-81,0,-1,-1,-76,0,-1,-1,-1,-1,-1,-1,-1,-1,-72,0,-67,0,-61,0,-56,0,-51,0,-46,0,-41,0,-35,0,-29,0,-23,0,-17,0,-12,0,-1,-1,-7,0,-1,-1,-3,0,2,1,7,1,11,1,18,1,-1,-1,25,1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,29,1,-1,-1,32,1,41,1,50,1,59,1,68,1,77,1,86,1,95,1,104,1,113,1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,122,1,-2,-1,-2,-1,-1,-1,-1,-1,-114,1,-111,1,-100,1,-97,1,-95,1,-92,1,-2,-1,-1,-1,-49,1,-1,-1,-1,-1,-1,-1,-1,-1,-47,1,-43,1,-39,1,-35,1,-31,1,-1,-1,-1,-1,-2,-1,-1,-1,-27,1,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-23,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-19,1,-14,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-10,1,-1,-1,-1,-1,-3,1,-1,-1,-1,-1,-1,-1,-1,-1,4,2,11,2,18,2,-1,-1,-1,-1,25,2,-1,-1,32,2,-1,-1,-1,-1,-1,-1,39,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,46,2,52,2,58,2,64,2,70,2,76,2,82,2,88,2,94,2,100,2,106,2,112,2,118,2,124,2,-126,2,-120,2,-114,2,-108,2,-102,2,-96,2,-90,2,-84,2,-78,2,-72,2,-66,2,-60,2,-54,2,-48,2,-42,2,-36,2,-29,2,-23,2,-17,2,-11,2,-5,2,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,1,3,6,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,13,3,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,22,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,27,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,33,3,47,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,27,91,66,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,91,48,109,0,27,91,63,49,48,52,57,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,76,0,8,0,27,91,51,126,0,27,91,66,0,27,91,91,65,0,27,91,50,49,126,0,27,91,91,66,0,27,91,91,67,0,27,91,91,68,0,27,91,91,69,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,68,0,27,91,54,126,0,27,91,53,126,0,27,91,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,91,65,0,27,69,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,54,37,116,59,49,37,59,109,0,9,0,27,79,119,0,27,79,121,0,27,91,71,0,27,79,113,0,27,79,115,0,27,91,90,0,27,79,69,0,27,91,52,126,0,27,79,77,0,27,91,51,59,50,126,0,27,91,52,59,50,126,0,27,91,49,59,50,126,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,50,51,36,0,27,91,50,52,36,0,27,91,49,49,94,0,27,91,49,50,94,0,27,91,49,51,94,0,27,91,49,52,94,0,27,91,49,53,94,0,27,91,49,55,94,0,27,91,49,56,94,0,27,91,49,57,94,0,27,91,50,48,94,0,27,91,50,49,94,0,27,91,50,51,94,0,27,91,50,52,94,0,27,91,50,53,94,0,27,91,50,54,94,0,27,91,50,56,94,0,27,91,50,57,94,0,27,91,51,49,94,0,27,91,49,59,54,83,0,27,91,51,50,94,0,27,91,51,51,94,0,27,91,51,52,94,0,27,91,50,51,64,0,27,91,50,52,64,0,27,91,49,75,0,27,91,63,54,57,108,0,27,91,51,57,59,52,57,109,0,27,91,51,109,0,27,91,50,51,109,0,27,91,51,56,59,53,59,37,112,49,37,100,109,0,27,91,52,56,59,53,59,37,112,49,37,100,109,0,0,3,0,0,0,86,0,117,0,121,2,1,1,1,0,0,0,9,0,-2,-1,-2,-1,18,0,-2,-1,23,0,30,0,37,0,42,0,48,0,-2,-1,58,0,64,0,73,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,82,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,89,0,93,0,97,0,101,0,105,0,109,0,113,0,117,0,121,0,125,0,-127,0,-123,0,-119,0,-115,0,-2,-1,-111,0,-2,-1,-2,-1,-86,0,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,30,0,33,0,36,0,39,0,42,0,45,0,48,0,51,0,54,0,59,0,64,0,69,0,74,0,79,0,83,0,88,0,93,0,98,0,103,0,108,0,114,0,120,0,126,0,-124,0,-118,0,-112,0,-106,0,-100,0,-94,0,-88,0,-83,0,-78,0,-73,0,-68,0,-63,0,-57,0,-51,0,-45,0,-39,0,-33,0,-27,0,-21,0,-15,0,-9,0,-3,0,3,1,9,1,15,1,21,1,27,1,33,1,39,1,45,1,51,1,57,1,61,1,66,1,71,1,76,1,81,1,86,1,90,1,94,1,98,1,102,1,106,1,112,1,118,1,124,1,-126,1,-120,1,-114,1,-108,1,-103,1,-97,1,-92,1,-89,1,-84,1,-81,1,27,91,63,50,48,48,52,108,0,27,91,63,50,48,48,52,104,0,27,91,51,74,0,27,91,50,48,49,126,0,27,91,50,48,48,126,0,27,91,62,99,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,91,62,48,113,0,27,91,63,49,48,48,52,108,0,27,91,63,49,48,48,52,104,0,27,91,49,59,50,65,0,27,79,120,0,27,79,116,0,27,79,118,0,27,79,114,0,27,79,69,0,27,79,107,0,27,79,108,0,27,79,111,0,27,79,110,0,27,79,106,0,27,79,109,0,27,79,112,0,27,91,73,0,27,91,79,0,27,92,91,52,49,59,91,49,45,54,93,91,48,45,57,93,91,48,45,57,93,59,48,99,0,27,80,62,92,124,88,84,101,114,109,92,40,91,49,45,57,93,91,48,45,57,93,43,92,41,27,92,92,0,65,88,0,88,70,0,88,84,0,66,68,0,66,69,0,67,114,0,67,115,0,69,51,0,77,115,0,80,69,0,80,83,0,82,86,0,83,101,0,83,115,0,88,77,0,88,82,0,102,100,0,102,101,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,107,97,50,0,107,98,49,0,107,98,51,0,107,99,50,0,107,112,53,0,107,112,65,68,68,0,107,112,67,77,65,0,107,112,68,73,86,0,107,112,68,79,84,0,107,112,77,85,76,0,107,112,83,85,66,0,107,112,90,82,79,0,107,120,73,78,0,107,120,79,85,84,0,114,109,120,120,0,114,118,0,115,109,120,120,0,120,109,0,120,114,0
};
// cygwin|ANSI emulation for Cygwin,
@@ -670,10 +673,10 @@ static const int8_t interix_8colour_terminfo[] = {
// user8=\E[?%[;0123456789]c,
// user9=\E[c,
static const int8_t iterm_256colour_terminfo[] = {
- 30,2,49,0,29,0,15,0,105,1,-29,3,105,84,101,114,109,50,46,97,112,112,124,105,116,101,114,109,50,124,116,101,114,109,105,110,97,108,32,101,109,117,108,97,116,111,114,32,102,111,114,32,77,97,99,32,79,83,32,88,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,1,0,0,1,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,50,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,25,0,30,0,37,0,41,0,45,0,-1,-1,56,0,73,0,75,0,79,0,86,0,-1,-1,88,0,95,0,-1,-1,99,0,-1,-1,103,0,107,0,111,0,-1,-1,117,0,119,0,124,0,-127,0,-1,-1,-109,0,-104,0,-1,-1,-1,-1,-99,0,-94,0,-89,0,-1,-1,-84,0,-82,0,-77,0,-1,-1,-59,0,-54,0,-48,0,-42,0,-1,-1,-24,0,-1,-1,-1,-1,-1,-1,-1,-1,-22,0,-18,0,-1,-1,-14,0,-1,-1,-1,-1,-1,-1,-12,0,-1,-1,-7,0,-1,-1,-1,-1,-1,-1,-1,-1,-3,0,1,1,7,1,11,1,15,1,19,1,25,1,31,1,37,1,43,1,49,1,-1,-1,-1,-1,53,1,-1,-1,57,1,62,1,67,1,71,1,78,1,-1,-1,85,1,89,1,97,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,105,1,-1,-1,108,1,117,1,126,1,-121,1,-112,1,-103,1,-94,1,-85,1,-76,1,-67,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-58,1,-1,-1,-1,-1,-32,1,-29,1,-18,1,-15,1,-13,1,-10,1,68,2,-1,-1,71,2,73,2,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-1,-1,78,2,-1,-1,-127,2,-1,-1,-1,-1,-123,2,-117,2,-1,-1,-1,-1,-111,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-104,2,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-100,2,-1,-1,-1,-1,-1,-1,-1,-1,-93,2,-1,-1,-86,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-79,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-72,2,-66,2,-60,2,-53,2,-46,2,-39,2,-32,2,-24,2,-16,2,-8,2,0,3,8,3,16,3,24,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,32,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,37,3,48,3,53,3,72,3,76,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,85,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,90,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,96,3,-1,-1,-1,-1,-1,-1,100,3,-93,3,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,93,50,59,7,0,14,0,27,91,53,109,0,27,91,49,109,0,27,91,63,49,48,52,57,104,27,91,50,50,59,48,59,48,116,0,27,91,50,109,0,27,91,52,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,15,0,27,91,109,15,0,27,91,63,49,48,52,57,108,27,91,50,51,59,48,59,48,116,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,50,48,48,47,62,27,91,63,53,108,0,7,0,27,91,64,0,27,91,76,0,127,0,27,91,51,126,0,27,79,66,0,27,79,80,0,27,91,50,49,126,0,27,79,81,0,27,79,82,0,27,79,83,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,79,72,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,27,69,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,27,91,33,112,27,91,63,51,59,52,108,27,91,52,108,27,62,27,91,63,49,48,48,48,108,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,54,37,116,59,49,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,37,63,37,112,53,37,116,59,50,37,59,109,37,63,37,112,57,37,116,14,37,101,15,37,59,0,27,72,0,9,0,27,93,50,59,0,96,96,97,97,102,102,103,103,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,91,90,0,27,91,63,55,104,0,27,91,63,55,108,0,27,40,66,27,41,48,0,27,79,70,0,27,91,49,59,50,70,0,27,91,49,59,50,72,0,27,91,49,59,50,68,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,49,59,50,80,0,27,91,49,59,50,81,0,27,91,49,59,50,82,0,27,91,49,59,50,83,0,27,91,49,53,59,50,126,0,27,91,49,55,59,50,126,0,27,91,49,56,59,50,126,0,27,91,49,57,59,50,126,0,27,91,50,48,59,50,126,0,27,91,50,49,59,50,126,0,27,91,50,51,59,50,126,0,27,91,50,52,59,50,126,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,37,91,59,48,49,50,51,52,53,54,55,56,57,93,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,91,51,109,0,27,91,50,51,109,0,27,91,77,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,0,0,0,0,0,33,0,66,0,-37,1,0,0,5,0,32,0,37,0,45,0,52,0,59,0,66,0,74,0,81,0,88,0,96,0,104,0,111,0,119,0,126,0,-123,0,-115,0,-107,0,-102,0,-94,0,-87,0,-80,0,-74,0,-68,0,-63,0,-55,0,-48,0,-41,0,-36,0,-28,0,-21,0,-14,0,0,0,3,0,6,0,11,0,16,0,21,0,26,0,32,0,38,0,44,0,50,0,56,0,62,0,68,0,74,0,80,0,86,0,92,0,98,0,104,0,110,0,116,0,122,0,-128,0,-122,0,-116,0,-110,0,-104,0,-98,0,-93,0,-88,0,-83,0,-78,0,27,93,50,59,0,27,91,63,49,48,48,48,37,63,37,112,49,37,123,49,125,37,61,37,116,104,37,101,108,37,59,0,27,27,91,66,0,27,91,49,59,49,48,66,0,27,91,49,59,53,66,0,27,91,49,59,54,66,0,27,91,49,59,57,70,0,27,91,49,59,49,48,70,0,27,91,49,59,53,70,0,27,91,49,59,54,70,0,27,91,49,59,49,51,70,0,27,91,49,59,49,52,70,0,27,91,49,59,57,72,0,27,91,49,59,49,48,72,0,27,91,49,59,53,72,0,27,91,49,59,54,72,0,27,91,49,59,49,51,72,0,27,91,49,59,49,52,72,0,27,27,91,68,0,27,91,49,59,49,48,68,0,27,91,49,59,53,68,0,27,91,49,59,54,68,0,27,27,91,54,126,0,27,27,91,53,126,0,27,27,91,67,0,27,91,49,59,49,48,67,0,27,91,49,59,53,67,0,27,91,49,59,54,67,0,27,27,91,65,0,27,91,49,59,49,48,65,0,27,91,49,59,53,65,0,27,91,49,59,54,65,0,27,91,77,37,63,37,112,52,37,116,37,112,51,37,101,37,123,51,125,37,59,37,39,32,39,37,43,37,99,37,112,50,37,39,33,39,37,43,37,99,37,112,49,37,39,33,39,37,43,37,99,0,84,83,0,88,77,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,69,78,68,56,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,72,79,77,56,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,78,88,84,51,0,107,80,82,86,51,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,120,109,0
+ 30,2,49,0,29,0,15,0,105,1,-29,3,105,84,101,114,109,50,46,97,112,112,124,105,116,101,114,109,50,124,116,101,114,109,105,110,97,108,32,101,109,117,108,97,116,111,114,32,102,111,114,32,77,97,99,32,79,83,32,88,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,1,0,0,1,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,50,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,25,0,30,0,37,0,41,0,45,0,-1,-1,56,0,73,0,75,0,79,0,86,0,-1,-1,88,0,95,0,-1,-1,99,0,-1,-1,103,0,107,0,111,0,-1,-1,117,0,119,0,124,0,-127,0,-1,-1,-109,0,-104,0,-1,-1,-1,-1,-99,0,-94,0,-89,0,-1,-1,-84,0,-82,0,-77,0,-1,-1,-59,0,-54,0,-48,0,-42,0,-1,-1,-24,0,-1,-1,-1,-1,-1,-1,-1,-1,-22,0,-18,0,-1,-1,-14,0,-1,-1,-1,-1,-1,-1,-12,0,-1,-1,-7,0,-1,-1,-1,-1,-1,-1,-1,-1,-3,0,1,1,7,1,11,1,15,1,19,1,25,1,31,1,37,1,43,1,49,1,-1,-1,-1,-1,53,1,-1,-1,57,1,62,1,67,1,71,1,78,1,-1,-1,85,1,89,1,97,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,105,1,-1,-1,108,1,117,1,126,1,-121,1,-112,1,-103,1,-94,1,-85,1,-76,1,-67,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-58,1,-1,-1,-1,-1,-32,1,-29,1,-18,1,-15,1,-13,1,-10,1,68,2,-1,-1,71,2,73,2,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-1,-1,-1,-1,78,2,-1,-1,-127,2,-1,-1,-1,-1,-123,2,-117,2,-1,-1,-1,-1,-111,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-104,2,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-100,2,-1,-1,-1,-1,-1,-1,-1,-1,-93,2,-1,-1,-86,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-79,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-72,2,-66,2,-60,2,-53,2,-46,2,-39,2,-32,2,-24,2,-16,2,-8,2,0,3,8,3,16,3,24,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,32,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,37,3,48,3,53,3,72,3,76,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,85,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,90,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,96,3,-1,-1,-1,-1,-1,-1,100,3,-93,3,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,93,50,59,7,0,14,0,27,91,53,109,0,27,91,49,109,0,27,91,63,49,48,52,57,104,27,91,50,50,59,48,59,48,116,0,27,91,50,109,0,27,91,52,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,15,0,27,91,109,15,0,27,91,63,49,48,52,57,108,27,91,50,51,59,48,59,48,116,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,50,48,48,47,62,27,91,63,53,108,0,7,0,27,91,64,0,27,91,76,0,127,0,27,91,51,126,0,27,79,66,0,27,79,80,0,27,91,50,49,126,0,27,79,81,0,27,79,82,0,27,79,83,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,79,72,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,27,69,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,27,91,33,112,27,91,63,51,59,52,108,27,91,52,108,27,62,27,91,63,49,48,48,48,108,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,54,37,116,59,49,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,37,63,37,112,53,37,116,59,50,37,59,109,37,63,37,112,57,37,116,14,37,101,15,37,59,0,27,72,0,9,0,27,93,50,59,0,96,96,97,97,102,102,103,103,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,91,90,0,27,91,63,55,104,0,27,91,63,55,108,0,27,40,66,27,41,48,0,27,79,70,0,27,91,49,59,50,70,0,27,91,49,59,50,72,0,27,91,49,59,50,68,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,49,59,50,80,0,27,91,49,59,50,81,0,27,91,49,59,50,82,0,27,91,49,59,50,83,0,27,91,49,53,59,50,126,0,27,91,49,55,59,50,126,0,27,91,49,56,59,50,126,0,27,91,49,57,59,50,126,0,27,91,50,48,59,50,126,0,27,91,50,49,59,50,126,0,27,91,50,51,59,50,126,0,27,91,50,52,59,50,126,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,37,91,59,48,49,50,51,52,53,54,55,56,57,93,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,91,51,109,0,27,91,50,51,109,0,27,91,77,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,0,0,0,0,0,37,0,74,0,7,2,0,0,9,0,18,0,25,0,32,0,37,0,64,0,69,0,77,0,84,0,91,0,98,0,106,0,113,0,120,0,-128,0,-120,0,-113,0,-105,0,-98,0,-91,0,-83,0,-75,0,-70,0,-62,0,-55,0,-48,0,-42,0,-36,0,-31,0,-23,0,-16,0,-9,0,-4,0,4,1,11,1,18,1,0,0,3,0,6,0,9,0,12,0,15,0,18,0,23,0,28,0,33,0,38,0,44,0,50,0,56,0,62,0,68,0,74,0,80,0,86,0,92,0,98,0,104,0,110,0,116,0,122,0,-128,0,-122,0,-116,0,-110,0,-104,0,-98,0,-92,0,-86,0,-81,0,-76,0,-71,0,-66,0,27,91,63,50,48,48,52,108,0,27,91,63,50,48,48,52,104,0,27,91,50,48,49,126,0,27,91,50,48,48,126,0,27,93,50,59,0,27,91,63,49,48,48,48,37,63,37,112,49,37,123,49,125,37,61,37,116,104,37,101,108,37,59,0,27,27,91,66,0,27,91,49,59,49,48,66,0,27,91,49,59,53,66,0,27,91,49,59,54,66,0,27,91,49,59,57,70,0,27,91,49,59,49,48,70,0,27,91,49,59,53,70,0,27,91,49,59,54,70,0,27,91,49,59,49,51,70,0,27,91,49,59,49,52,70,0,27,91,49,59,57,72,0,27,91,49,59,49,48,72,0,27,91,49,59,53,72,0,27,91,49,59,54,72,0,27,91,49,59,49,51,72,0,27,91,49,59,49,52,72,0,27,27,91,68,0,27,91,49,59,49,48,68,0,27,91,49,59,53,68,0,27,91,49,59,54,68,0,27,27,91,54,126,0,27,27,91,53,126,0,27,27,91,67,0,27,91,49,59,49,48,67,0,27,91,49,59,53,67,0,27,91,49,59,54,67,0,27,27,91,65,0,27,91,49,59,49,48,65,0,27,91,49,59,53,65,0,27,91,49,59,54,65,0,27,91,77,37,63,37,112,52,37,116,37,112,51,37,101,37,123,51,125,37,59,37,39,32,39,37,43,37,99,37,112,50,37,39,33,39,37,43,37,99,37,112,49,37,39,33,39,37,43,37,99,0,66,68,0,66,69,0,80,69,0,80,83,0,84,83,0,88,77,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,69,78,68,56,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,72,79,77,56,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,78,88,84,51,0,107,80,82,86,51,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,120,109,0
};
-// linux|linux console,
+// linux|Linux console,
// auto_right_margin,
// back_color_erase,
// can_change,
@@ -732,7 +735,7 @@ static const int8_t iterm_256colour_terminfo[] = {
// insert_line=\E[L,
// key_b2=\E[G,
// key_backspace=\177,
-// key_btab=\E[Z,
+// key_btab=\E^I,
// key_dc=\E[3~,
// key_down=\E[B,
// key_end=\E[4~,
@@ -792,7 +795,7 @@ static const int8_t iterm_256colour_terminfo[] = {
// user8=\E[?6c,
// user9=\E[c,
static const int8_t linux_16colour_terminfo[] = {
- 26,1,20,0,29,0,16,0,125,1,67,3,108,105,110,117,120,124,108,105,110,117,120,32,99,111,110,115,111,108,101,0,0,1,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,-1,-1,8,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,0,64,0,18,0,-1,-1,0,0,2,0,4,0,21,0,26,0,33,0,37,0,41,0,-1,-1,52,0,69,0,71,0,75,0,87,0,-1,-1,89,0,101,0,-1,-1,105,0,109,0,121,0,125,0,-1,-1,-1,-1,-127,0,-125,0,-120,0,-1,-1,-1,-1,-115,0,-110,0,-1,-1,-1,-1,-105,0,-100,0,-95,0,-90,0,-81,0,-79,0,-1,-1,-1,-1,-74,0,-69,0,-63,0,-57,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-39,0,-35,0,-1,-1,-31,0,-1,-1,-1,-1,-1,-1,-29,0,-1,-1,-24,0,-1,-1,-1,-1,-1,-1,-1,-1,-20,0,-15,0,-9,0,-4,0,1,1,6,1,11,1,17,1,23,1,29,1,35,1,40,1,-1,-1,45,1,-1,-1,49,1,54,1,59,1,-1,-1,-1,-1,-1,-1,63,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,67,1,-1,-1,70,1,79,1,88,1,97,1,-1,-1,106,1,115,1,124,1,-1,-1,-123,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-114,1,-1,-1,-1,-1,-1,-1,-108,1,-105,1,-94,1,-91,1,-89,1,-86,1,1,2,-1,-1,4,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,6,2,-1,-1,-1,-1,-1,-1,-1,-1,10,2,-1,-1,75,2,-1,-1,-1,-1,79,2,85,2,-1,-1,-1,-1,91,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,95,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,100,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,102,2,108,2,114,2,120,2,126,2,-124,2,-118,2,-112,2,-106,2,-100,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-94,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-89,2,-78,2,-73,2,-67,2,-63,2,-54,2,-50,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,31,3,-1,-1,-1,-1,-1,-1,35,3,45,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,55,3,61,3,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,27,91,63,49,99,0,8,0,27,91,63,50,53,104,27,91,63,48,99,0,27,91,67,0,27,91,65,0,27,91,63,50,53,104,27,91,63,56,99,0,27,91,80,0,27,91,77,0,14,0,27,91,53,109,0,27,91,49,109,0,27,91,50,109,0,27,91,52,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,15,0,27,91,109,15,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,50,48,48,47,62,27,91,63,53,108,0,27,91,64,0,27,91,76,0,127,0,27,91,51,126,0,27,91,66,0,27,91,91,65,0,27,91,50,49,126,0,27,91,91,66,0,27,91,91,67,0,27,91,91,68,0,27,91,91,69,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,68,0,27,91,54,126,0,27,91,53,126,0,27,91,67,0,27,91,65,0,13,10,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,65,0,27,99,27,93,82,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,59,49,48,37,63,37,112,49,37,116,59,55,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,51,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,37,63,37,112,53,37,116,59,50,37,59,37,63,37,112,54,37,116,59,49,37,59,109,37,63,37,112,57,37,116,14,37,101,15,37,59,0,27,72,0,9,0,27,91,71,0,43,43,44,44,45,45,46,46,48,48,96,96,97,97,102,102,103,103,104,104,105,105,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,91,90,0,27,91,63,55,104,0,27,91,63,55,108,0,27,41,48,0,27,91,52,126,0,26,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,54,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,93,82,0,27,93,80,37,112,49,37,120,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,48,50,120,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,48,50,120,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,48,50,120,0,27,91,77,0,27,91,51,37,112,49,37,100,109,0,27,91,52,37,112,49,37,100,109,0,27,91,49,49,109,0,27,91,49,48,109,0,0,1,0,1,0,1,0,4,0,14,0,1,0,1,0,0,0,0,0,3,0,6,0,27,91,51,74,0,65,88,0,85,56,0,69,51,0
+ 26,1,20,0,29,0,16,0,125,1,66,3,108,105,110,117,120,124,76,105,110,117,120,32,99,111,110,115,111,108,101,0,0,1,0,0,1,1,0,0,0,0,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,1,1,0,-1,-1,8,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,8,0,64,0,18,0,-1,-1,0,0,2,0,4,0,21,0,26,0,33,0,37,0,41,0,-1,-1,52,0,69,0,71,0,75,0,87,0,-1,-1,89,0,101,0,-1,-1,105,0,109,0,121,0,125,0,-1,-1,-1,-1,-127,0,-125,0,-120,0,-1,-1,-1,-1,-115,0,-110,0,-1,-1,-1,-1,-105,0,-100,0,-95,0,-90,0,-81,0,-79,0,-1,-1,-1,-1,-74,0,-69,0,-63,0,-57,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-39,0,-35,0,-1,-1,-31,0,-1,-1,-1,-1,-1,-1,-29,0,-1,-1,-24,0,-1,-1,-1,-1,-1,-1,-1,-1,-20,0,-15,0,-9,0,-4,0,1,1,6,1,11,1,17,1,23,1,29,1,35,1,40,1,-1,-1,45,1,-1,-1,49,1,54,1,59,1,-1,-1,-1,-1,-1,-1,63,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,67,1,-1,-1,70,1,79,1,88,1,97,1,-1,-1,106,1,115,1,124,1,-1,-1,-123,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-114,1,-1,-1,-1,-1,-1,-1,-108,1,-105,1,-94,1,-91,1,-89,1,-86,1,1,2,-1,-1,4,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,6,2,-1,-1,-1,-1,-1,-1,-1,-1,10,2,-1,-1,75,2,-1,-1,-1,-1,78,2,84,2,-1,-1,-1,-1,90,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,94,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,99,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,101,2,107,2,113,2,119,2,125,2,-125,2,-119,2,-113,2,-107,2,-101,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-95,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-90,2,-79,2,-74,2,-68,2,-64,2,-55,2,-51,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,30,3,-1,-1,-1,-1,-1,-1,34,3,44,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,54,3,60,3,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,27,91,63,49,99,0,8,0,27,91,63,50,53,104,27,91,63,48,99,0,27,91,67,0,27,91,65,0,27,91,63,50,53,104,27,91,63,56,99,0,27,91,80,0,27,91,77,0,14,0,27,91,53,109,0,27,91,49,109,0,27,91,50,109,0,27,91,52,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,15,0,27,91,109,15,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,50,48,48,47,62,27,91,63,53,108,0,27,91,64,0,27,91,76,0,127,0,27,91,51,126,0,27,91,66,0,27,91,91,65,0,27,91,50,49,126,0,27,91,91,66,0,27,91,91,67,0,27,91,91,68,0,27,91,91,69,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,68,0,27,91,54,126,0,27,91,53,126,0,27,91,67,0,27,91,65,0,13,10,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,65,0,27,99,27,93,82,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,59,49,48,37,63,37,112,49,37,116,59,55,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,51,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,37,63,37,112,53,37,116,59,50,37,59,37,63,37,112,54,37,116,59,49,37,59,109,37,63,37,112,57,37,116,14,37,101,15,37,59,0,27,72,0,9,0,27,91,71,0,43,43,44,44,45,45,46,46,48,48,96,96,97,97,102,102,103,103,104,104,105,105,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,9,0,27,91,63,55,104,0,27,91,63,55,108,0,27,41,48,0,27,91,52,126,0,26,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,54,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,93,82,0,27,93,80,37,112,49,37,120,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,48,50,120,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,48,50,120,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,48,50,120,0,27,91,77,0,27,91,51,37,112,49,37,100,109,0,27,91,52,37,112,49,37,100,109,0,27,91,49,49,109,0,27,91,49,48,109,0,1,0,1,0,2,0,6,0,24,0,1,0,1,0,0,0,5,0,0,0,3,0,6,0,9,0,27,91,51,74,0,27,91,90,0,65,88,0,85,56,0,69,51,0,107,99,98,116,50,0
};
// putty-256color|PuTTY 0.58 with xterm 256-colors,
@@ -836,7 +839,7 @@ static const int8_t linux_16colour_terminfo[] = {
// enter_am_mode=\E[?7h,
// enter_blink_mode=\E[5m,
// enter_bold_mode=\E[1m,
-// enter_ca_mode=\E[?47h,
+// enter_ca_mode=\E[?1049h,
// enter_insert_mode=\E[4h,
// enter_pc_charset_mode=\E[11m,
// enter_reverse_mode=\E[7m,
@@ -846,7 +849,7 @@ static const int8_t linux_16colour_terminfo[] = {
// exit_alt_charset_mode=^O,
// exit_am_mode=\E[?7l,
// exit_attribute_mode=\E[m^O,
-// exit_ca_mode=\E[2J\E[?47l,
+// exit_ca_mode=\E[?1049l,
// exit_insert_mode=\E[4l,
// exit_pc_charset_mode=\E[10m,
// exit_standout_mode=\E[27m,
@@ -933,7 +936,7 @@ static const int8_t linux_16colour_terminfo[] = {
// user8=\E[?6c,
// user9=\E[c,
static const int8_t putty_256colour_terminfo[] = {
- 30,2,48,0,29,0,16,0,125,1,-70,4,112,117,116,116,121,45,50,53,54,99,111,108,111,114,124,80,117,84,84,89,32,48,46,53,56,32,119,105,116,104,32,120,116,101,114,109,32,50,53,54,45,99,111,108,111,114,115,0,1,1,0,0,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,-1,-1,-1,-1,8,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,22,0,0,0,0,0,4,0,6,0,8,0,25,0,30,0,37,0,41,0,45,0,-1,-1,56,0,73,0,76,0,80,0,87,0,-1,-1,89,0,96,0,-1,-1,100,0,-1,-1,103,0,107,0,111,0,-1,-1,117,0,119,0,124,0,-127,0,-1,-1,-1,-1,-120,0,-1,-1,-1,-1,-115,0,-110,0,-105,0,-100,0,-91,0,-89,0,-84,0,-1,-1,-73,0,-68,0,-62,0,-56,0,-1,-1,-38,0,-1,-1,-36,0,-1,-1,-1,-1,-1,-1,-2,0,-1,-1,2,1,-1,-1,-1,-1,-1,-1,4,1,-1,-1,9,1,-1,-1,-1,-1,-1,-1,13,1,17,1,23,1,29,1,35,1,41,1,47,1,53,1,59,1,65,1,71,1,77,1,82,1,-1,-1,87,1,-1,-1,91,1,96,1,101,1,105,1,109,1,-1,-1,113,1,117,1,125,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-123,1,-1,-1,-120,1,-111,1,-102,1,-1,-1,-93,1,-84,1,-75,1,-66,1,-57,1,-48,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-39,1,-1,-1,-19,1,-1,-1,-1,-1,14,2,17,2,28,2,31,2,33,2,36,2,108,2,-1,-1,111,2,113,2,-1,-1,-1,-1,-1,-1,118,2,122,2,126,2,-126,2,-122,2,-1,-1,-1,-1,-118,2,-1,-1,-67,2,-1,-1,-1,-1,-63,2,-57,2,-1,-1,-1,-1,-51,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-44,2,-39,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-35,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-33,2,-27,2,-21,2,-15,2,-9,2,-3,2,3,3,9,3,15,3,21,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,27,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,32,3,43,3,48,3,54,3,58,3,67,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,71,3,-1,-1,-1,-1,-1,-1,75,3,-118,3,-1,-1,-1,-1,-1,-1,-54,3,-48,3,-42,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-36,3,-82,4,-76,4,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,27,68,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,77,0,27,91,80,0,27,91,77,0,27,93,48,59,7,0,14,0,27,91,53,109,0,27,91,49,109,0,27,91,63,52,55,104,0,27,91,52,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,15,0,27,91,109,15,0,27,91,50,74,27,91,63,52,55,108,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,49,48,48,47,62,27,91,63,53,108,0,7,0,27,55,27,91,114,27,91,109,27,91,63,55,104,27,91,63,49,59,52,59,54,108,27,91,52,108,27,56,27,62,27,93,82,0,27,91,76,0,127,0,27,91,51,126,0,27,79,66,0,27,79,121,0,27,91,49,49,126,0,27,91,50,49,126,0,27,91,49,50,126,0,27,91,49,51,126,0,27,91,49,52,126,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,66,0,27,91,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,13,10,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,60,27,91,34,112,27,91,53,48,59,54,34,112,27,99,27,91,63,51,108,27,93,82,27,91,63,49,48,48,48,108,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,49,37,112,54,37,124,37,116,59,49,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,109,37,63,37,112,57,37,116,14,37,101,15,37,59,0,27,72,0,9,0,27,93,48,59,0,27,79,113,0,27,79,115,0,27,79,114,0,27,79,112,0,27,79,110,0,96,96,97,97,102,102,103,103,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,91,90,0,27,91,63,55,104,0,27,91,63,55,108,0,27,40,66,27,41,48,0,27,91,52,126,0,27,79,77,0,26,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,54,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,93,82,0,27,91,60,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,49,48,109,0,27,91,49,49,109,0,27,91,49,50,109,0,37,63,37,112,49,37,123,56,125,37,61,37,116,27,37,37,71,-30,-105,-104,27,37,37,64,37,101,37,112,49,37,123,49,48,125,37,61,37,116,27,37,37,71,-30,-105,-103,27,37,37,64,37,101,37,112,49,37,123,49,50,125,37,61,37,116,27,37,37,71,-30,-103,-128,27,37,37,64,37,101,37,112,49,37,123,49,51,125,37,61,37,116,27,37,37,71,-30,-103,-86,27,37,37,64,37,101,37,112,49,37,123,49,52,125,37,61,37,116,27,37,37,71,-30,-103,-85,27,37,37,64,37,101,37,112,49,37,123,49,53,125,37,61,37,116,27,37,37,71,-30,-104,-68,27,37,37,64,37,101,37,112,49,37,123,50,55,125,37,61,37,116,27,37,37,71,-30,-122,-112,27,37,37,64,37,101,37,112,49,37,123,49,53,53,125,37,61,37,116,27,37,37,71,-32,-126,-94,27,37,37,64,37,101,37,112,49,37,99,37,59,0,27,91,49,49,109,0,27,91,49,48,109,0,1,0,1,0,20,0,42,0,-17,0,1,0,1,0,0,0,0,0,5,0,10,0,42,0,46,0,50,0,54,0,58,0,62,0,66,0,70,0,74,0,78,0,82,0,86,0,90,0,94,0,98,0,102,0,106,0,0,0,3,0,6,0,9,0,12,0,15,0,19,0,23,0,27,0,31,0,35,0,39,0,43,0,47,0,51,0,57,0,63,0,69,0,75,0,81,0,87,0,93,0,27,91,51,74,0,27,93,48,59,0,27,91,63,49,48,48,54,59,49,48,48,48,37,63,37,112,49,37,123,49,125,37,61,37,116,104,37,101,108,37,59,0,27,79,113,0,27,79,114,0,27,79,115,0,27,79,116,0,27,79,117,0,27,79,118,0,27,79,119,0,27,79,120,0,27,79,121,0,27,79,108,0,27,79,81,0,27,79,110,0,27,79,82,0,27,79,80,0,27,79,83,0,27,79,112,0,27,91,60,37,105,37,112,51,37,100,59,37,112,49,37,100,59,37,112,50,37,100,59,37,63,37,112,52,37,116,77,37,101,109,37,59,0,88,84,0,85,56,0,69,51,0,84,83,0,88,77,0,107,112,49,0,107,112,50,0,107,112,51,0,107,112,52,0,107,112,53,0,107,112,54,0,107,112,55,0,107,112,56,0,107,112,57,0,107,112,65,68,68,0,107,112,68,73,86,0,107,112,68,79,84,0,107,112,77,85,76,0,107,112,78,85,77,0,107,112,83,85,66,0,107,112,90,82,79,0,120,109,0
+ 30,2,48,0,29,0,16,0,125,1,-70,4,112,117,116,116,121,45,50,53,54,99,111,108,111,114,124,80,117,84,84,89,32,48,46,53,56,32,119,105,116,104,32,120,116,101,114,109,32,50,53,54,45,99,111,108,111,114,115,0,1,1,0,0,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,-1,-1,-1,-1,8,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,22,0,0,0,0,0,4,0,6,0,8,0,25,0,30,0,37,0,41,0,45,0,-1,-1,56,0,73,0,76,0,80,0,87,0,-1,-1,89,0,96,0,-1,-1,100,0,-1,-1,103,0,107,0,111,0,-1,-1,117,0,119,0,124,0,-127,0,-1,-1,-1,-1,-118,0,-1,-1,-1,-1,-113,0,-108,0,-103,0,-98,0,-89,0,-87,0,-82,0,-1,-1,-73,0,-68,0,-62,0,-56,0,-1,-1,-38,0,-1,-1,-36,0,-1,-1,-1,-1,-1,-1,-2,0,-1,-1,2,1,-1,-1,-1,-1,-1,-1,4,1,-1,-1,9,1,-1,-1,-1,-1,-1,-1,13,1,17,1,23,1,29,1,35,1,41,1,47,1,53,1,59,1,65,1,71,1,77,1,82,1,-1,-1,87,1,-1,-1,91,1,96,1,101,1,105,1,109,1,-1,-1,113,1,117,1,125,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-123,1,-1,-1,-120,1,-111,1,-102,1,-1,-1,-93,1,-84,1,-75,1,-66,1,-57,1,-48,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-39,1,-1,-1,-19,1,-1,-1,-1,-1,14,2,17,2,28,2,31,2,33,2,36,2,108,2,-1,-1,111,2,113,2,-1,-1,-1,-1,-1,-1,118,2,122,2,126,2,-126,2,-122,2,-1,-1,-1,-1,-118,2,-1,-1,-67,2,-1,-1,-1,-1,-63,2,-57,2,-1,-1,-1,-1,-51,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-44,2,-39,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-35,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-33,2,-27,2,-21,2,-15,2,-9,2,-3,2,3,3,9,3,15,3,21,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,27,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,32,3,43,3,48,3,54,3,58,3,67,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,71,3,-1,-1,-1,-1,-1,-1,75,3,-118,3,-1,-1,-1,-1,-1,-1,-54,3,-48,3,-42,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-36,3,-82,4,-76,4,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,27,68,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,77,0,27,91,80,0,27,91,77,0,27,93,48,59,7,0,14,0,27,91,53,109,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,52,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,15,0,27,91,109,15,0,27,91,63,49,48,52,57,108,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,49,48,48,47,62,27,91,63,53,108,0,7,0,27,55,27,91,114,27,91,109,27,91,63,55,104,27,91,63,49,59,52,59,54,108,27,91,52,108,27,56,27,62,27,93,82,0,27,91,76,0,127,0,27,91,51,126,0,27,79,66,0,27,79,121,0,27,91,49,49,126,0,27,91,50,49,126,0,27,91,49,50,126,0,27,91,49,51,126,0,27,91,49,52,126,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,66,0,27,91,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,13,10,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,60,27,91,34,112,27,91,53,48,59,54,34,112,27,99,27,91,63,51,108,27,93,82,27,91,63,49,48,48,48,108,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,49,37,112,54,37,124,37,116,59,49,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,109,37,63,37,112,57,37,116,14,37,101,15,37,59,0,27,72,0,9,0,27,93,48,59,0,27,79,113,0,27,79,115,0,27,79,114,0,27,79,112,0,27,79,110,0,96,96,97,97,102,102,103,103,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,91,90,0,27,91,63,55,104,0,27,91,63,55,108,0,27,40,66,27,41,48,0,27,91,52,126,0,27,79,77,0,26,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,54,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,93,82,0,27,91,60,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,49,48,109,0,27,91,49,49,109,0,27,91,49,50,109,0,37,63,37,112,49,37,123,56,125,37,61,37,116,27,37,37,71,-30,-105,-104,27,37,37,64,37,101,37,112,49,37,123,49,48,125,37,61,37,116,27,37,37,71,-30,-105,-103,27,37,37,64,37,101,37,112,49,37,123,49,50,125,37,61,37,116,27,37,37,71,-30,-103,-128,27,37,37,64,37,101,37,112,49,37,123,49,51,125,37,61,37,116,27,37,37,71,-30,-103,-86,27,37,37,64,37,101,37,112,49,37,123,49,52,125,37,61,37,116,27,37,37,71,-30,-103,-85,27,37,37,64,37,101,37,112,49,37,123,49,53,125,37,61,37,116,27,37,37,71,-30,-104,-68,27,37,37,64,37,101,37,112,49,37,123,50,55,125,37,61,37,116,27,37,37,71,-30,-122,-112,27,37,37,64,37,101,37,112,49,37,123,49,53,53,125,37,61,37,116,27,37,37,71,-32,-126,-94,27,37,37,64,37,101,37,112,49,37,99,37,59,0,27,91,49,49,109,0,27,91,49,48,109,0,1,0,1,0,30,0,62,0,86,1,1,0,1,0,0,0,0,0,9,0,18,0,23,0,30,0,37,0,42,0,74,0,78,0,82,0,86,0,90,0,94,0,98,0,102,0,106,0,110,0,114,0,118,0,122,0,126,0,-126,0,-122,0,-118,0,-114,0,-110,0,-106,0,-102,0,-96,0,-91,0,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,32,0,38,0,44,0,49,0,53,0,57,0,61,0,65,0,69,0,73,0,77,0,81,0,85,0,91,0,97,0,103,0,109,0,115,0,121,0,127,0,-124,0,-119,0,27,91,63,50,48,48,52,108,0,27,91,63,50,48,48,52,104,0,27,91,51,74,0,27,91,50,48,49,126,0,27,91,50,48,48,126,0,27,93,48,59,0,27,91,63,49,48,48,54,59,49,48,48,48,37,63,37,112,49,37,123,49,125,37,61,37,116,104,37,101,108,37,59,0,27,91,66,0,27,91,68,0,27,91,67,0,27,91,65,0,27,79,113,0,27,79,114,0,27,79,115,0,27,79,116,0,27,79,117,0,27,79,118,0,27,79,119,0,27,79,120,0,27,79,121,0,27,79,108,0,27,79,81,0,27,79,110,0,27,79,82,0,27,79,80,0,27,79,83,0,27,79,112,0,27,91,50,57,109,0,27,91,57,109,0,27,91,60,37,105,37,112,51,37,100,59,37,112,49,37,100,59,37,112,50,37,100,59,37,63,37,112,52,37,116,77,37,101,109,37,59,0,88,84,0,85,56,0,66,68,0,66,69,0,69,51,0,80,69,0,80,83,0,84,83,0,88,77,0,107,68,78,53,0,107,76,70,84,53,0,107,82,73,84,53,0,107,85,80,53,0,107,112,49,0,107,112,50,0,107,112,51,0,107,112,52,0,107,112,53,0,107,112,54,0,107,112,55,0,107,112,56,0,107,112,57,0,107,112,65,68,68,0,107,112,68,73,86,0,107,112,68,79,84,0,107,112,77,85,76,0,107,112,78,85,77,0,107,112,83,85,66,0,107,112,90,82,79,0,114,109,120,120,0,115,109,120,120,0,120,109,0
};
// rxvt-256color|rxvt 2.7.9 with xterm 256-colors,
@@ -1404,7 +1407,7 @@ static const int8_t screen_256colour_terminfo[] = {
// user8=\E[?1;2c,
// user9=\E[c,
static const int8_t st_256colour_terminfo[] = {
- 30,2,55,0,29,0,15,0,105,1,-28,5,115,116,45,50,53,54,99,111,108,111,114,124,115,116,116,101,114,109,45,50,53,54,99,111,108,111,114,124,115,105,109,112,108,101,116,101,114,109,32,119,105,116,104,32,50,53,54,32,99,111,108,111,114,115,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,1,1,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,25,0,30,0,38,0,42,0,46,0,-1,-1,57,0,74,0,76,0,80,0,87,0,-1,-1,89,0,96,0,-1,-1,100,0,-1,-1,104,0,108,0,112,0,-1,-1,118,0,122,0,127,0,-124,0,-1,-1,-115,0,-110,0,-105,0,-1,-1,-100,0,-95,0,-90,0,-85,0,-76,0,-72,0,-67,0,-1,-1,-58,0,-53,0,-47,0,-41,0,-1,-1,-23,0,-1,-1,-21,0,-1,-1,-1,-1,-1,-1,-6,0,-1,-1,-2,0,-1,-1,0,1,-1,-1,7,1,12,1,19,1,23,1,30,1,37,1,-1,-1,44,1,48,1,54,1,58,1,62,1,66,1,72,1,78,1,84,1,90,1,96,1,101,1,106,1,113,1,-1,-1,117,1,122,1,127,1,-125,1,-118,1,-1,-1,-111,1,-107,1,-99,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-91,1,-82,1,-73,1,-64,1,-55,1,-46,1,-37,1,-28,1,-19,1,-10,1,-1,-1,-1,-1,-1,-1,-1,1,3,2,8,2,-1,-1,13,2,16,2,-1,-1,-1,-1,31,2,34,2,45,2,48,2,50,2,53,2,-110,2,-1,-1,-107,2,-105,2,-1,-1,-1,-1,-1,-1,-100,2,-95,2,-90,2,-86,2,-81,2,-1,-1,-1,-1,-76,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-7,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,2,-1,-1,-1,-1,5,3,-1,-1,-1,-1,-1,-1,-1,-1,12,3,19,3,26,3,-1,-1,-1,-1,33,3,-1,-1,40,3,-1,-1,-1,-1,-1,-1,47,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,54,3,60,3,66,3,73,3,80,3,87,3,94,3,102,3,110,3,118,3,126,3,-122,3,-114,3,-106,3,-98,3,-91,3,-84,3,-77,3,-70,3,-62,3,-54,3,-46,3,-38,3,-30,3,-22,3,-14,3,-6,3,1,4,8,4,15,4,22,4,30,4,38,4,46,4,54,4,62,4,70,4,78,4,86,4,93,4,100,4,107,4,114,4,122,4,-126,4,-118,4,-110,4,-102,4,-94,4,-86,4,-78,4,-71,4,-64,4,-57,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-52,4,-41,4,-36,4,-28,4,-24,4,-15,4,-8,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,86,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,91,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,97,5,-1,-1,-1,-1,-1,-1,101,5,-92,5,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,93,48,59,7,0,27,40,48,0,27,91,53,109,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,50,109,0,27,91,52,104,0,27,91,56,109,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,40,66,0,27,91,48,109,0,27,91,63,49,48,52,57,108,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,49,48,48,47,62,27,91,63,53,108,0,7,0,27,91,52,108,27,62,27,91,63,49,48,51,52,108,0,27,91,76,0,127,0,27,91,51,59,53,126,0,27,91,51,126,0,27,91,51,59,50,126,0,27,79,66,0,27,91,50,59,50,126,0,27,91,49,59,50,70,0,27,91,49,59,53,70,0,27,79,80,0,27,91,50,49,126,0,27,79,81,0,27,79,82,0,27,79,83,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,50,59,53,126,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,27,91,105,0,27,91,52,105,0,27,91,53,105,0,27,99,0,27,91,52,108,27,62,27,91,63,49,48,51,52,108,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,37,63,37,112,57,37,116,27,40,48,37,101,27,40,66,37,59,27,91,48,37,63,37,112,54,37,116,59,49,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,37,63,37,112,53,37,116,59,50,37,59,37,63,37,112,55,37,116,59,56,37,59,109,0,27,72,0,9,0,27,93,48,59,0,27,91,49,126,0,27,91,53,126,0,27,79,117,0,27,91,52,126,0,27,91,54,126,0,43,67,44,68,45,65,46,66,48,69,96,96,97,97,102,102,103,103,104,70,105,71,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,41,48,0,27,91,52,126,0,27,91,51,59,50,126,0,27,91,49,59,50,70,0,27,91,49,59,50,72,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,49,59,50,80,0,27,91,49,59,50,81,0,27,91,49,59,50,82,0,27,91,49,59,50,83,0,27,91,49,53,59,50,126,0,27,91,49,55,59,50,126,0,27,91,49,56,59,50,126,0,27,91,49,57,59,50,126,0,27,91,50,48,59,50,126,0,27,91,50,49,59,50,126,0,27,91,50,51,59,50,126,0,27,91,50,52,59,50,126,0,27,91,49,59,53,80,0,27,91,49,59,53,81,0,27,91,49,59,53,82,0,27,91,49,59,53,83,0,27,91,49,53,59,53,126,0,27,91,49,55,59,53,126,0,27,91,49,56,59,53,126,0,27,91,49,57,59,53,126,0,27,91,50,48,59,53,126,0,27,91,50,49,59,53,126,0,27,91,50,51,59,53,126,0,27,91,50,52,59,53,126,0,27,91,49,59,54,80,0,27,91,49,59,54,81,0,27,91,49,59,54,82,0,27,91,49,59,54,83,0,27,91,49,53,59,54,126,0,27,91,49,55,59,54,126,0,27,91,49,56,59,54,126,0,27,91,49,57,59,54,126,0,27,91,50,48,59,54,126,0,27,91,50,49,59,54,126,0,27,91,50,51,59,54,126,0,27,91,50,52,59,54,126,0,27,91,49,59,51,80,0,27,91,49,59,51,81,0,27,91,49,59,51,82,0,27,91,49,59,51,83,0,27,91,49,53,59,51,126,0,27,91,49,55,59,51,126,0,27,91,49,56,59,51,126,0,27,91,49,57,59,51,126,0,27,91,50,48,59,51,126,0,27,91,50,49,59,51,126,0,27,91,50,51,59,51,126,0,27,91,50,52,59,51,126,0,27,91,49,59,52,80,0,27,91,49,59,52,81,0,27,91,49,59,52,82,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,49,59,50,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,93,49,48,52,7,0,27,93,52,59,37,112,49,37,100,59,114,103,98,58,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,27,92,0,27,91,51,109,0,27,91,50,51,109,0,27,91,77,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,1,0,0,0,18,0,37,0,-29,0,1,0,0,0,18,0,24,0,34,0,39,0,46,0,53,0,60,0,67,0,74,0,81,0,88,0,95,0,102,0,109,0,116,0,123,0,-127,0,0,0,3,0,6,0,9,0,12,0,15,0,20,0,25,0,31,0,37,0,43,0,49,0,55,0,61,0,67,0,73,0,78,0,83,0,88,0,27,93,53,50,59,37,112,49,37,115,59,37,112,50,37,115,7,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,93,48,59,0,27,91,49,59,51,66,0,27,91,49,59,53,66,0,27,91,49,59,51,68,0,27,91,49,59,53,68,0,27,91,54,59,51,126,0,27,91,54,59,53,126,0,27,91,53,59,51,126,0,27,91,53,59,53,126,0,27,91,49,59,51,67,0,27,91,49,59,53,67,0,27,91,49,59,51,65,0,27,91,49,59,53,65,0,27,91,50,57,109,0,27,91,57,109,0,88,84,0,77,115,0,83,101,0,83,115,0,84,83,0,107,68,78,51,0,107,68,78,53,0,107,76,70,84,51,0,107,76,70,84,53,0,107,78,88,84,51,0,107,78,88,84,53,0,107,80,82,86,51,0,107,80,82,86,53,0,107,82,73,84,51,0,107,82,73,84,53,0,107,85,80,51,0,107,85,80,53,0,114,109,120,120,0,115,109,120,120,0
+ 30,2,55,0,29,0,15,0,105,1,-28,5,115,116,45,50,53,54,99,111,108,111,114,124,115,116,116,101,114,109,45,50,53,54,99,111,108,111,114,124,115,105,109,112,108,101,116,101,114,109,32,119,105,116,104,32,50,53,54,32,99,111,108,111,114,115,0,0,1,0,0,1,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,1,1,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,25,0,30,0,38,0,42,0,46,0,-1,-1,57,0,74,0,76,0,80,0,87,0,-1,-1,89,0,96,0,-1,-1,100,0,-1,-1,104,0,108,0,112,0,-1,-1,118,0,122,0,127,0,-124,0,-1,-1,-115,0,-110,0,-105,0,-1,-1,-100,0,-95,0,-90,0,-85,0,-76,0,-72,0,-67,0,-1,-1,-58,0,-53,0,-47,0,-41,0,-1,-1,-23,0,-1,-1,-21,0,-1,-1,-1,-1,-1,-1,-6,0,-1,-1,-2,0,-1,-1,0,1,-1,-1,7,1,12,1,19,1,23,1,30,1,37,1,-1,-1,44,1,48,1,54,1,58,1,62,1,66,1,72,1,78,1,84,1,90,1,96,1,101,1,106,1,113,1,-1,-1,117,1,122,1,127,1,-125,1,-118,1,-1,-1,-111,1,-107,1,-99,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-91,1,-82,1,-73,1,-64,1,-55,1,-46,1,-37,1,-28,1,-19,1,-10,1,-1,-1,-1,-1,-1,-1,-1,1,3,2,8,2,-1,-1,13,2,16,2,-1,-1,-1,-1,31,2,34,2,45,2,48,2,50,2,53,2,-110,2,-1,-1,-107,2,-105,2,-1,-1,-1,-1,-1,-1,-100,2,-95,2,-90,2,-86,2,-81,2,-1,-1,-1,-1,-76,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-11,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-7,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,2,-1,-1,-1,-1,5,3,-1,-1,-1,-1,-1,-1,-1,-1,12,3,19,3,26,3,-1,-1,-1,-1,33,3,-1,-1,40,3,-1,-1,-1,-1,-1,-1,47,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,54,3,60,3,66,3,73,3,80,3,87,3,94,3,102,3,110,3,118,3,126,3,-122,3,-114,3,-106,3,-98,3,-91,3,-84,3,-77,3,-70,3,-62,3,-54,3,-46,3,-38,3,-30,3,-22,3,-14,3,-6,3,1,4,8,4,15,4,22,4,30,4,38,4,46,4,54,4,62,4,70,4,78,4,86,4,93,4,100,4,107,4,114,4,122,4,-126,4,-118,4,-110,4,-102,4,-94,4,-86,4,-78,4,-71,4,-64,4,-57,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-52,4,-41,4,-36,4,-28,4,-24,4,-15,4,-8,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,86,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,91,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,97,5,-1,-1,-1,-1,-1,-1,101,5,-92,5,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,93,48,59,7,0,27,40,48,0,27,91,53,109,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,50,109,0,27,91,52,104,0,27,91,56,109,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,40,66,0,27,91,48,109,0,27,91,63,49,48,52,57,108,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,49,48,48,47,62,27,91,63,53,108,0,7,0,27,91,52,108,27,62,27,91,63,49,48,51,52,108,0,27,91,76,0,127,0,27,91,51,59,53,126,0,27,91,51,126,0,27,91,51,59,50,126,0,27,79,66,0,27,91,50,59,50,126,0,27,91,49,59,50,70,0,27,91,49,59,53,70,0,27,79,80,0,27,91,50,49,126,0,27,79,81,0,27,79,82,0,27,79,83,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,50,59,53,126,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,27,91,105,0,27,91,52,105,0,27,91,53,105,0,27,99,0,27,91,52,108,27,62,27,91,63,49,48,51,52,108,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,37,63,37,112,57,37,116,27,40,48,37,101,27,40,66,37,59,27,91,48,37,63,37,112,54,37,116,59,49,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,37,63,37,112,53,37,116,59,50,37,59,37,63,37,112,55,37,116,59,56,37,59,109,0,27,72,0,9,0,27,93,48,59,0,27,91,49,126,0,27,91,53,126,0,27,79,117,0,27,91,52,126,0,27,91,54,126,0,43,67,44,68,45,65,46,66,48,69,96,96,97,97,102,102,103,103,104,70,105,71,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,41,48,0,27,91,52,126,0,27,91,51,59,50,126,0,27,91,49,59,50,70,0,27,91,49,59,50,72,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,49,59,50,80,0,27,91,49,59,50,81,0,27,91,49,59,50,82,0,27,91,49,59,50,83,0,27,91,49,53,59,50,126,0,27,91,49,55,59,50,126,0,27,91,49,56,59,50,126,0,27,91,49,57,59,50,126,0,27,91,50,48,59,50,126,0,27,91,50,49,59,50,126,0,27,91,50,51,59,50,126,0,27,91,50,52,59,50,126,0,27,91,49,59,53,80,0,27,91,49,59,53,81,0,27,91,49,59,53,82,0,27,91,49,59,53,83,0,27,91,49,53,59,53,126,0,27,91,49,55,59,53,126,0,27,91,49,56,59,53,126,0,27,91,49,57,59,53,126,0,27,91,50,48,59,53,126,0,27,91,50,49,59,53,126,0,27,91,50,51,59,53,126,0,27,91,50,52,59,53,126,0,27,91,49,59,54,80,0,27,91,49,59,54,81,0,27,91,49,59,54,82,0,27,91,49,59,54,83,0,27,91,49,53,59,54,126,0,27,91,49,55,59,54,126,0,27,91,49,56,59,54,126,0,27,91,49,57,59,54,126,0,27,91,50,48,59,54,126,0,27,91,50,49,59,54,126,0,27,91,50,51,59,54,126,0,27,91,50,52,59,54,126,0,27,91,49,59,51,80,0,27,91,49,59,51,81,0,27,91,49,59,51,82,0,27,91,49,59,51,83,0,27,91,49,53,59,51,126,0,27,91,49,55,59,51,126,0,27,91,49,56,59,51,126,0,27,91,49,57,59,51,126,0,27,91,50,48,59,51,126,0,27,91,50,49,59,51,126,0,27,91,50,51,59,51,126,0,27,91,50,52,59,51,126,0,27,91,49,59,52,80,0,27,91,49,59,52,81,0,27,91,49,59,52,82,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,49,59,50,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,93,49,48,52,7,0,27,93,52,59,37,112,49,37,100,59,114,103,98,58,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,27,92,0,27,91,51,109,0,27,91,50,51,109,0,27,91,77,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,1,0,0,0,22,0,45,0,15,1,1,0,0,0,9,0,18,0,36,0,43,0,50,0,56,0,66,0,71,0,78,0,85,0,92,0,99,0,106,0,113,0,120,0,127,0,-122,0,-115,0,-108,0,-101,0,-95,0,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,32,0,37,0,43,0,49,0,55,0,61,0,67,0,73,0,79,0,85,0,90,0,95,0,100,0,27,91,63,50,48,48,52,108,0,27,91,63,50,48,48,52,104,0,27,93,53,50,59,37,112,49,37,115,59,37,112,50,37,115,7,0,27,91,50,48,49,126,0,27,91,50,48,48,126,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,93,48,59,0,27,91,49,59,51,66,0,27,91,49,59,53,66,0,27,91,49,59,51,68,0,27,91,49,59,53,68,0,27,91,54,59,51,126,0,27,91,54,59,53,126,0,27,91,53,59,51,126,0,27,91,53,59,53,126,0,27,91,49,59,51,67,0,27,91,49,59,53,67,0,27,91,49,59,51,65,0,27,91,49,59,53,65,0,27,91,50,57,109,0,27,91,57,109,0,88,84,0,66,68,0,66,69,0,77,115,0,80,69,0,80,83,0,83,101,0,83,115,0,84,83,0,107,68,78,51,0,107,68,78,53,0,107,76,70,84,51,0,107,76,70,84,53,0,107,78,88,84,51,0,107,78,88,84,53,0,107,80,82,86,51,0,107,80,82,86,53,0,107,82,73,84,51,0,107,82,73,84,53,0,107,85,80,51,0,107,85,80,53,0,114,109,120,120,0,115,109,120,120,0
};
// tmux-256color|tmux with 256 colors,
@@ -1467,7 +1470,7 @@ static const int8_t st_256colour_terminfo[] = {
// from_status_line=^G,
// init_2string=\E)0,
// insert_line=\E[L,
-// key_backspace=\177,
+// key_backspace=^H,
// key_btab=\E[Z,
// key_dc=\E[3~,
// key_down=\EOB,
@@ -1565,6 +1568,7 @@ static const int8_t st_256colour_terminfo[] = {
// parm_insert_line=\E[%p1%dL,
// parm_left_cursor=\E[%p1%dD,
// parm_right_cursor=\E[%p1%dC,
+// parm_rindex=\E[%p1%dT,
// parm_up_cursor=\E[%p1%dA,
// reset_2string=\Ec\E[?1000l\E[?25h,
// restore_cursor=\E8,
@@ -1583,7 +1587,7 @@ static const int8_t st_256colour_terminfo[] = {
// user8=\E[?1;2c,
// user9=\E[c,
static const int8_t tmux_256colour_terminfo[] = {
- 30,2,35,0,43,0,15,0,105,1,13,5,116,109,117,120,45,50,53,54,99,111,108,111,114,124,116,109,117,120,32,119,105,116,104,32,50,53,54,32,99,111,108,111,114,115,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,25,0,30,0,37,0,41,0,45,0,-1,-1,56,0,73,0,75,0,79,0,86,0,-1,-1,88,0,100,0,-1,-1,104,0,107,0,113,0,117,0,121,0,-1,-1,127,0,-127,0,-122,0,-117,0,-1,-1,-108,0,-103,0,-98,0,-1,-1,-93,0,-88,0,-83,0,-1,-1,-78,0,-76,0,-71,0,-1,-1,-62,0,-57,0,-51,0,-45,0,-1,-1,-42,0,-1,-1,-40,0,-1,-1,-1,-1,-1,-1,-36,0,-1,-1,-32,0,-1,-1,-1,-1,-1,-1,-30,0,-1,-1,-25,0,-1,-1,-1,-1,-1,-1,-1,-1,-21,0,-17,0,-11,0,-7,0,-3,0,1,1,7,1,13,1,19,1,25,1,31,1,36,1,-1,-1,41,1,-1,-1,45,1,50,1,55,1,59,1,66,1,-1,-1,73,1,77,1,85,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,93,1,-1,-1,96,1,105,1,114,1,123,1,-124,1,-115,1,-106,1,-97,1,-1,-1,-88,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-79,1,-1,-1,-1,-1,-62,1,-59,1,-48,1,-45,1,-43,1,-40,1,49,2,-1,-1,52,2,54,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,59,2,-1,-1,124,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-128,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-121,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-116,2,-1,-1,-1,-1,-109,2,-1,-1,-1,-1,-1,-1,-1,-1,-102,2,-95,2,-88,2,-1,-1,-1,-1,-81,2,-1,-1,-74,2,-1,-1,-1,-1,-1,-1,-67,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-60,2,-54,2,-48,2,-41,2,-34,2,-27,2,-20,2,-12,2,-4,2,4,3,12,3,20,3,28,3,36,3,44,3,51,3,58,3,65,3,72,3,80,3,88,3,96,3,104,3,112,3,120,3,-128,3,-120,3,-113,3,-106,3,-99,3,-92,3,-84,3,-76,3,-68,3,-60,3,-52,3,-44,3,-36,3,-28,3,-21,3,-14,3,-7,3,0,4,8,4,16,4,24,4,32,4,40,4,48,4,56,4,64,4,71,4,78,4,85,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,90,4,101,4,106,4,114,4,118,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,127,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-124,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-118,4,-1,-1,-1,-1,-1,-1,-114,4,-51,4,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,51,52,104,27,91,63,50,53,104,0,27,91,67,0,27,77,0,27,91,51,52,108,0,27,91,80,0,27,91,77,0,27,93,48,59,7,0,14,0,27,91,53,109,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,50,109,0,27,91,52,104,0,27,91,56,109,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,15,0,27,91,109,15,0,27,91,63,49,48,52,57,108,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,103,0,7,0,27,41,48,0,27,91,76,0,127,0,27,91,51,126,0,27,79,66,0,27,79,80,0,27,91,50,49,126,0,27,79,81,0,27,79,82,0,27,79,83,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,27,69,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,65,0,27,99,27,91,63,49,48,48,48,108,27,91,63,50,53,104,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,54,37,116,59,49,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,37,63,37,112,53,37,116,59,50,37,59,37,63,37,112,55,37,116,59,56,37,59,109,37,63,37,112,57,37,116,14,37,101,15,37,59,0,27,72,0,9,0,27,93,48,59,0,43,43,44,44,45,45,46,46,48,48,96,96,97,97,102,102,103,103,104,104,105,105,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,91,90,0,27,40,66,27,41,48,0,27,91,52,126,0,27,91,51,59,50,126,0,27,91,49,59,50,70,0,27,91,49,59,50,72,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,49,59,50,80,0,27,91,49,59,50,81,0,27,91,49,59,50,82,0,27,91,49,59,50,83,0,27,91,49,53,59,50,126,0,27,91,49,55,59,50,126,0,27,91,49,56,59,50,126,0,27,91,49,57,59,50,126,0,27,91,50,48,59,50,126,0,27,91,50,49,59,50,126,0,27,91,50,51,59,50,126,0,27,91,50,52,59,50,126,0,27,91,49,59,53,80,0,27,91,49,59,53,81,0,27,91,49,59,53,82,0,27,91,49,59,53,83,0,27,91,49,53,59,53,126,0,27,91,49,55,59,53,126,0,27,91,49,56,59,53,126,0,27,91,49,57,59,53,126,0,27,91,50,48,59,53,126,0,27,91,50,49,59,53,126,0,27,91,50,51,59,53,126,0,27,91,50,52,59,53,126,0,27,91,49,59,54,80,0,27,91,49,59,54,81,0,27,91,49,59,54,82,0,27,91,49,59,54,83,0,27,91,49,53,59,54,126,0,27,91,49,55,59,54,126,0,27,91,49,56,59,54,126,0,27,91,49,57,59,54,126,0,27,91,50,48,59,54,126,0,27,91,50,49,59,54,126,0,27,91,50,51,59,54,126,0,27,91,50,52,59,54,126,0,27,91,49,59,51,80,0,27,91,49,59,51,81,0,27,91,49,59,51,82,0,27,91,49,59,51,83,0,27,91,49,53,59,51,126,0,27,91,49,55,59,51,126,0,27,91,49,56,59,51,126,0,27,91,49,57,59,51,126,0,27,91,50,48,59,51,126,0,27,91,50,49,59,51,126,0,27,91,50,51,59,51,126,0,27,91,50,52,59,51,126,0,27,91,49,59,52,80,0,27,91,49,59,52,81,0,27,91,49,59,52,82,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,49,59,50,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,91,51,109,0,27,91,50,51,109,0,27,91,77,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,0,2,0,1,0,64,0,-125,0,33,3,1,1,1,0,0,0,0,0,7,0,19,0,23,0,28,0,46,0,54,0,60,0,71,0,81,0,86,0,93,0,100,0,107,0,114,0,121,0,-128,0,-121,0,-114,0,-107,0,-100,0,-93,0,-86,0,-79,0,-72,0,-65,0,-58,0,-51,0,-44,0,-37,0,-30,0,-23,0,-16,0,-9,0,-2,0,5,1,12,1,19,1,26,1,33,1,40,1,47,1,54,1,61,1,68,1,75,1,82,1,89,1,96,1,103,1,110,1,117,1,124,1,-125,1,-118,1,-111,1,-104,1,-97,1,-90,1,-83,1,-76,1,-69,1,-62,1,-56,1,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,30,0,36,0,39,0,42,0,47,0,52,0,57,0,62,0,67,0,71,0,76,0,81,0,86,0,91,0,96,0,102,0,108,0,114,0,120,0,126,0,-124,0,-118,0,-112,0,-106,0,-100,0,-95,0,-90,0,-85,0,-80,0,-75,0,-69,0,-63,0,-57,0,-51,0,-45,0,-39,0,-33,0,-27,0,-21,0,-15,0,-9,0,-3,0,3,1,9,1,15,1,21,1,27,1,33,1,39,1,45,1,49,1,54,1,59,1,64,1,69,1,74,1,79,1,27,93,49,49,50,7,0,27,93,49,50,59,37,112,49,37,115,7,0,27,40,66,0,27,91,51,74,0,27,93,53,50,59,37,112,49,37,115,59,37,112,50,37,115,7,0,27,40,37,112,49,37,99,0,27,91,50,32,113,0,27,91,52,58,37,112,49,37,100,109,0,27,91,37,112,49,37,100,32,113,0,27,93,48,59,0,27,91,51,59,51,126,0,27,91,51,59,52,126,0,27,91,51,59,53,126,0,27,91,51,59,54,126,0,27,91,51,59,55,126,0,27,91,49,59,50,66,0,27,91,49,59,51,66,0,27,91,49,59,52,66,0,27,91,49,59,53,66,0,27,91,49,59,54,66,0,27,91,49,59,55,66,0,27,91,49,59,51,70,0,27,91,49,59,52,70,0,27,91,49,59,53,70,0,27,91,49,59,54,70,0,27,91,49,59,55,70,0,27,91,49,59,51,72,0,27,91,49,59,52,72,0,27,91,49,59,53,72,0,27,91,49,59,54,72,0,27,91,49,59,55,72,0,27,91,50,59,51,126,0,27,91,50,59,52,126,0,27,91,50,59,53,126,0,27,91,50,59,54,126,0,27,91,50,59,55,126,0,27,91,49,59,51,68,0,27,91,49,59,52,68,0,27,91,49,59,53,68,0,27,91,49,59,54,68,0,27,91,49,59,55,68,0,27,91,54,59,51,126,0,27,91,54,59,52,126,0,27,91,54,59,53,126,0,27,91,54,59,54,126,0,27,91,54,59,55,126,0,27,91,53,59,51,126,0,27,91,53,59,52,126,0,27,91,53,59,53,126,0,27,91,53,59,54,126,0,27,91,53,59,55,126,0,27,91,49,59,51,67,0,27,91,49,59,52,67,0,27,91,49,59,53,67,0,27,91,49,59,54,67,0,27,91,49,59,55,67,0,27,91,49,59,50,65,0,27,91,49,59,51,65,0,27,91,49,59,52,65,0,27,91,49,59,53,65,0,27,91,49,59,54,65,0,27,91,49,59,55,65,0,27,91,50,57,109,0,27,91,57,109,0,65,88,0,71,48,0,85,56,0,67,114,0,67,115,0,69,48,0,69,51,0,77,115,0,83,48,0,83,101,0,83,109,117,108,120,0,83,115,0,84,83,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,114,109,120,120,0,115,109,120,120,0
+ 30,2,35,0,43,0,15,0,105,1,22,5,116,109,117,120,45,50,53,54,99,111,108,111,114,124,116,109,117,120,32,119,105,116,104,32,50,53,54,32,99,111,108,111,114,115,0,0,1,0,0,1,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,1,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,25,0,30,0,37,0,41,0,45,0,-1,-1,56,0,73,0,75,0,79,0,86,0,-1,-1,88,0,100,0,-1,-1,104,0,107,0,113,0,117,0,121,0,-1,-1,127,0,-127,0,-122,0,-117,0,-1,-1,-108,0,-103,0,-98,0,-1,-1,-93,0,-88,0,-83,0,-1,-1,-78,0,-76,0,-71,0,-1,-1,-62,0,-57,0,-51,0,-45,0,-1,-1,-42,0,-1,-1,-40,0,-1,-1,-1,-1,-1,-1,-36,0,-1,-1,-32,0,-1,-1,-1,-1,-1,-1,-30,0,-1,-1,-25,0,-1,-1,-1,-1,-1,-1,-1,-1,-21,0,-17,0,-11,0,-7,0,-3,0,1,1,7,1,13,1,19,1,25,1,31,1,36,1,-1,-1,41,1,-1,-1,45,1,50,1,55,1,59,1,66,1,-1,-1,73,1,77,1,85,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,93,1,-1,-1,96,1,105,1,114,1,123,1,-124,1,-115,1,-106,1,-97,1,-88,1,-79,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-70,1,-1,-1,-1,-1,-53,1,-50,1,-39,1,-36,1,-34,1,-31,1,58,2,-1,-1,61,2,63,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,68,2,-1,-1,-123,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-119,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-112,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-107,2,-1,-1,-1,-1,-100,2,-1,-1,-1,-1,-1,-1,-1,-1,-93,2,-86,2,-79,2,-1,-1,-1,-1,-72,2,-1,-1,-65,2,-1,-1,-1,-1,-1,-1,-58,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-51,2,-45,2,-39,2,-32,2,-25,2,-18,2,-11,2,-3,2,5,3,13,3,21,3,29,3,37,3,45,3,53,3,60,3,67,3,74,3,81,3,89,3,97,3,105,3,113,3,121,3,-127,3,-119,3,-111,3,-104,3,-97,3,-90,3,-83,3,-75,3,-67,3,-59,3,-51,3,-43,3,-35,3,-27,3,-19,3,-12,3,-5,3,2,4,9,4,17,4,25,4,33,4,41,4,49,4,57,4,65,4,73,4,80,4,87,4,94,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,99,4,110,4,115,4,123,4,127,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-120,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-115,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-109,4,-1,-1,-1,-1,-1,-1,-105,4,-42,4,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,51,52,104,27,91,63,50,53,104,0,27,91,67,0,27,77,0,27,91,51,52,108,0,27,91,80,0,27,91,77,0,27,93,48,59,7,0,14,0,27,91,53,109,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,50,109,0,27,91,52,104,0,27,91,56,109,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,15,0,27,91,109,15,0,27,91,63,49,48,52,57,108,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,103,0,7,0,27,41,48,0,27,91,76,0,8,0,27,91,51,126,0,27,79,66,0,27,79,80,0,27,91,50,49,126,0,27,79,81,0,27,79,82,0,27,79,83,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,27,69,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,27,99,27,91,63,49,48,48,48,108,27,91,63,50,53,104,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,54,37,116,59,49,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,37,63,37,112,53,37,116,59,50,37,59,37,63,37,112,55,37,116,59,56,37,59,109,37,63,37,112,57,37,116,14,37,101,15,37,59,0,27,72,0,9,0,27,93,48,59,0,43,43,44,44,45,45,46,46,48,48,96,96,97,97,102,102,103,103,104,104,105,105,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,91,90,0,27,40,66,27,41,48,0,27,91,52,126,0,27,91,51,59,50,126,0,27,91,49,59,50,70,0,27,91,49,59,50,72,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,49,59,50,80,0,27,91,49,59,50,81,0,27,91,49,59,50,82,0,27,91,49,59,50,83,0,27,91,49,53,59,50,126,0,27,91,49,55,59,50,126,0,27,91,49,56,59,50,126,0,27,91,49,57,59,50,126,0,27,91,50,48,59,50,126,0,27,91,50,49,59,50,126,0,27,91,50,51,59,50,126,0,27,91,50,52,59,50,126,0,27,91,49,59,53,80,0,27,91,49,59,53,81,0,27,91,49,59,53,82,0,27,91,49,59,53,83,0,27,91,49,53,59,53,126,0,27,91,49,55,59,53,126,0,27,91,49,56,59,53,126,0,27,91,49,57,59,53,126,0,27,91,50,48,59,53,126,0,27,91,50,49,59,53,126,0,27,91,50,51,59,53,126,0,27,91,50,52,59,53,126,0,27,91,49,59,54,80,0,27,91,49,59,54,81,0,27,91,49,59,54,82,0,27,91,49,59,54,83,0,27,91,49,53,59,54,126,0,27,91,49,55,59,54,126,0,27,91,49,56,59,54,126,0,27,91,49,57,59,54,126,0,27,91,50,48,59,54,126,0,27,91,50,49,59,54,126,0,27,91,50,51,59,54,126,0,27,91,50,52,59,54,126,0,27,91,49,59,51,80,0,27,91,49,59,51,81,0,27,91,49,59,51,82,0,27,91,49,59,51,83,0,27,91,49,53,59,51,126,0,27,91,49,55,59,51,126,0,27,91,49,56,59,51,126,0,27,91,49,57,59,51,126,0,27,91,50,48,59,51,126,0,27,91,50,49,59,51,126,0,27,91,50,51,59,51,126,0,27,91,50,52,59,51,126,0,27,91,49,59,52,80,0,27,91,49,59,52,81,0,27,91,49,59,52,82,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,49,59,50,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,91,51,109,0,27,91,50,51,109,0,27,91,77,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,3,0,1,0,76,0,-100,0,-70,3,1,1,1,0,1,0,0,0,0,0,9,0,18,0,25,0,37,0,41,0,46,0,64,0,71,0,78,0,83,0,91,0,97,0,108,0,118,0,123,0,-127,0,-118,0,-109,0,-102,0,-95,0,-88,0,-81,0,-74,0,-67,0,-60,0,-53,0,-46,0,-39,0,-32,0,-25,0,-18,0,-11,0,-4,0,3,1,10,1,17,1,24,1,31,1,38,1,45,1,52,1,59,1,66,1,73,1,80,1,87,1,94,1,101,1,108,1,115,1,122,1,-127,1,-120,1,-113,1,-106,1,-99,1,-92,1,-85,1,-78,1,-71,1,-64,1,-57,1,-50,1,-43,1,-36,1,-29,1,-22,1,-15,1,-8,1,-1,1,3,2,7,2,13,2,38,2,43,2,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,30,0,33,0,36,0,39,0,42,0,45,0,48,0,54,0,57,0,60,0,63,0,66,0,69,0,74,0,79,0,84,0,89,0,94,0,98,0,103,0,108,0,113,0,118,0,123,0,-127,0,-121,0,-115,0,-109,0,-103,0,-97,0,-91,0,-85,0,-79,0,-73,0,-68,0,-63,0,-58,0,-53,0,-48,0,-42,0,-36,0,-30,0,-24,0,-18,0,-12,0,-6,0,0,1,6,1,12,1,18,1,24,1,30,1,36,1,42,1,48,1,54,1,60,1,66,1,72,1,76,1,81,1,86,1,91,1,96,1,101,1,106,1,112,1,117,1,120,1,125,1,27,91,63,50,48,48,52,108,0,27,91,63,50,48,48,52,104,0,27,93,49,49,50,7,0,27,93,49,50,59,37,112,49,37,115,7,0,27,40,66,0,27,91,51,74,0,27,93,53,50,59,37,112,49,37,115,59,37,112,50,37,115,7,0,27,91,50,48,49,126,0,27,91,50,48,48,126,0,27,91,62,99,0,27,40,37,112,49,37,99,0,27,91,50,32,113,0,27,91,52,58,37,112,49,37,100,109,0,27,91,37,112,49,37,100,32,113,0,27,93,48,59,0,27,91,62,48,113,0,27,91,63,49,48,48,52,108,0,27,91,63,49,48,48,52,104,0,27,91,51,59,51,126,0,27,91,51,59,52,126,0,27,91,51,59,53,126,0,27,91,51,59,54,126,0,27,91,51,59,55,126,0,27,91,49,59,50,66,0,27,91,49,59,51,66,0,27,91,49,59,52,66,0,27,91,49,59,53,66,0,27,91,49,59,54,66,0,27,91,49,59,55,66,0,27,91,49,59,51,70,0,27,91,49,59,52,70,0,27,91,49,59,53,70,0,27,91,49,59,54,70,0,27,91,49,59,55,70,0,27,91,49,59,51,72,0,27,91,49,59,52,72,0,27,91,49,59,53,72,0,27,91,49,59,54,72,0,27,91,49,59,55,72,0,27,91,50,59,51,126,0,27,91,50,59,52,126,0,27,91,50,59,53,126,0,27,91,50,59,54,126,0,27,91,50,59,55,126,0,27,91,49,59,51,68,0,27,91,49,59,52,68,0,27,91,49,59,53,68,0,27,91,49,59,54,68,0,27,91,49,59,55,68,0,27,91,54,59,51,126,0,27,91,54,59,52,126,0,27,91,54,59,53,126,0,27,91,54,59,54,126,0,27,91,54,59,55,126,0,27,91,53,59,51,126,0,27,91,53,59,52,126,0,27,91,53,59,53,126,0,27,91,53,59,54,126,0,27,91,53,59,55,126,0,27,91,49,59,51,67,0,27,91,49,59,52,67,0,27,91,49,59,53,67,0,27,91,49,59,54,67,0,27,91,49,59,55,67,0,27,91,49,59,50,65,0,27,91,49,59,51,65,0,27,91,49,59,52,65,0,27,91,49,59,53,65,0,27,91,49,59,54,65,0,27,91,49,59,55,65,0,27,91,73,0,27,91,79,0,27,91,50,57,109,0,27,92,91,91,48,45,57,93,43,59,91,48,45,57,93,43,59,91,48,45,57,93,43,99,0,27,91,57,109,0,27,80,62,92,124,91,32,45,126,93,43,27,92,92,0,65,88,0,71,48,0,88,70,0,85,56,0,66,68,0,66,69,0,67,114,0,67,115,0,69,48,0,69,51,0,77,115,0,80,69,0,80,83,0,82,86,0,83,48,0,83,101,0,83,109,117,108,120,0,83,115,0,84,83,0,88,82,0,102,100,0,102,101,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,107,120,73,78,0,107,120,79,85,84,0,114,109,120,120,0,114,118,0,115,109,120,120,0,120,114,0
};
// vte-256color|VTE with xterm 256-colors,
@@ -1620,11 +1624,12 @@ static const int8_t tmux_256colour_terminfo[] = {
// cursor_up=\E[A,
// delete_character=\E[P,
// delete_line=\E[M,
-// ena_acs=\E)0,
+// ena_acs=\E(B\E)0,
// enter_alt_charset_mode=^N,
// enter_am_mode=\E[?7h,
+// enter_blink_mode=\E[5m,
// enter_bold_mode=\E[1m,
-// enter_ca_mode=\E7\E[?47h,
+// enter_ca_mode=\E[?1049h\E[22;0;0t,
// enter_dim_mode=\E[2m,
// enter_insert_mode=\E[4h,
// enter_italics_mode=\E[3m,
@@ -1636,7 +1641,7 @@ static const int8_t tmux_256colour_terminfo[] = {
// exit_alt_charset_mode=^O,
// exit_am_mode=\E[?7l,
// exit_attribute_mode=\E[0m^O,
-// exit_ca_mode=\E[2J\E[?47l\E8,
+// exit_ca_mode=\E[?1049l\E[23;0;0t,
// exit_insert_mode=\E[4l,
// exit_italics_mode=\E[23m,
// exit_standout_mode=\E[27m,
@@ -1739,6 +1744,7 @@ static const int8_t tmux_256colour_terminfo[] = {
// keypad_xmit=\E[?1h\E=,
// memory_lock=\El,
// memory_unlock=\Em,
+// newline=\EE,
// orig_colors=\E]104^G,
// orig_pair=\E[39;49m,
// parm_dch=\E[%p1%dP,
@@ -1751,6 +1757,7 @@ static const int8_t tmux_256colour_terminfo[] = {
// parm_right_cursor=\E[%p1%dC,
// parm_rindex=\E[%p1%dT,
// parm_up_cursor=\E[%p1%dA,
+// repeat_char=%p1%c\E[%p2%{1}%-%db,
// reset_1string=\Ec,
// reset_2string=\E7\E[r\E8\E[m\E[?7h\E[\041p\E[?1;3;4;6l\E[4l\E>\E[?1000l\E[?25h,
// restore_cursor=\E8,
@@ -1760,7 +1767,7 @@ static const int8_t tmux_256colour_terminfo[] = {
// scroll_reverse=\EM,
// set_a_background=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
// set_a_foreground=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m,
-// set_attributes=\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p5%t;2%;%?%p7%t;8%;%?%p1%p3%|%t;7%;m%?%p9%t^N%e^O%;,
+// set_attributes=\E[0%?%p6%t;1%;%?%p2%t;4%;%?%p4%t;5%;%?%p5%t;2%;%?%p7%t;8%;%?%p1%p3%|%t;7%;m%?%p9%t^N%e^O%;,
// set_tab=\EH,
// tab=^I,
// user6=\E[%i%d;%dR,
@@ -1768,7 +1775,7 @@ static const int8_t tmux_256colour_terminfo[] = {
// user8=\E[?%[;0123456789]c,
// user9=\E[c,
static const int8_t vte_256colour_terminfo[] = {
- 30,2,39,0,38,0,15,0,-99,1,-49,5,118,116,101,45,50,53,54,99,111,108,111,114,124,86,84,69,32,119,105,116,104,32,120,116,101,114,109,32,50,53,54,45,99,111,108,111,114,115,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,25,0,30,0,38,0,42,0,46,0,-1,-1,57,0,74,0,76,0,80,0,87,0,-1,-1,89,0,96,0,-1,-1,100,0,-1,-1,104,0,108,0,-1,-1,-1,-1,112,0,-1,-1,114,0,119,0,-1,-1,-128,0,-123,0,-118,0,-1,-1,-113,0,-108,0,-103,0,-98,0,-89,0,-87,0,-81,0,-1,-1,-68,0,-63,0,-57,0,-51,0,-1,-1,-1,-1,-1,-1,-33,0,-1,-1,-1,-1,-1,-1,0,1,-1,-1,4,1,-1,-1,-1,-1,-1,-1,6,1,-1,-1,11,1,-1,-1,-1,-1,-1,-1,-1,-1,15,1,19,1,25,1,29,1,33,1,37,1,43,1,49,1,55,1,61,1,67,1,71,1,-1,-1,76,1,-1,-1,80,1,85,1,90,1,94,1,101,1,-1,-1,108,1,112,1,120,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-128,1,-119,1,-110,1,-101,1,-92,1,-83,1,-74,1,-65,1,-56,1,-47,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-38,1,-35,1,-1,-1,-1,-1,16,2,19,2,30,2,33,2,35,2,38,2,116,2,-1,-1,119,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,121,2,-1,-1,-1,-1,-1,-1,-1,-1,125,2,-1,-1,-78,2,-1,-1,-1,-1,-74,2,-68,2,-1,-1,-1,-1,-62,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-58,2,-54,2,-1,-1,-50,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-45,2,-1,-1,-38,2,-33,2,-1,-1,-1,-1,-1,-1,-1,-1,-26,2,-19,2,-12,2,-1,-1,-1,-1,-5,2,-1,-1,2,3,-1,-1,-1,-1,-1,-1,9,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,16,3,22,3,28,3,35,3,42,3,49,3,56,3,64,3,72,3,80,3,88,3,96,3,104,3,112,3,120,3,127,3,-122,3,-115,3,-108,3,-100,3,-92,3,-84,3,-76,3,-68,3,-60,3,-52,3,-44,3,-37,3,-30,3,-23,3,-16,3,-8,3,0,4,8,4,16,4,24,4,32,4,40,4,48,4,55,4,62,4,69,4,76,4,84,4,92,4,100,4,108,4,116,4,124,4,-124,4,-116,4,-109,4,-102,4,-95,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-90,4,-79,4,-74,4,-55,4,-51,4,-42,4,-35,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,59,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,64,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,70,5,-1,-1,-1,-1,-1,-1,74,5,-119,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-55,5,-52,5,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,14,0,27,91,49,109,0,27,55,27,91,63,52,55,104,0,27,91,50,109,0,27,91,52,104,0,27,91,56,109,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,15,0,27,91,48,109,15,0,27,91,50,74,27,91,63,52,55,108,27,56,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,49,48,48,47,62,27,91,63,53,108,0,27,91,109,27,91,63,55,104,27,91,52,108,27,62,27,55,27,91,114,27,91,63,49,59,51,59,52,59,54,108,27,56,0,27,91,76,0,127,0,27,91,51,126,0,27,79,66,0,27,79,80,0,27,91,50,49,126,0,27,79,81,0,27,79,82,0,27,79,83,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,79,72,0,27,91,50,126,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,27,99,0,27,55,27,91,114,27,56,27,91,109,27,91,63,55,104,27,91,33,112,27,91,63,49,59,51,59,52,59,54,108,27,91,52,108,27,62,27,91,63,49,48,48,48,108,27,91,63,50,53,104,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,54,37,116,59,49,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,53,37,116,59,50,37,59,37,63,37,112,55,37,116,59,56,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,109,37,63,37,112,57,37,116,14,37,101,15,37,59,0,27,72,0,9,0,27,91,69,0,96,96,97,97,102,102,103,103,105,105,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,91,90,0,27,91,63,55,104,0,27,91,63,55,108,0,27,41,48,0,27,79,70,0,27,79,77,0,27,91,49,126,0,27,91,51,59,50,126,0,27,91,52,126,0,27,91,49,59,50,70,0,27,91,49,59,50,72,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,49,59,50,80,0,27,91,49,59,50,81,0,27,91,49,59,50,82,0,27,91,49,59,50,83,0,27,91,49,53,59,50,126,0,27,91,49,55,59,50,126,0,27,91,49,56,59,50,126,0,27,91,49,57,59,50,126,0,27,91,50,48,59,50,126,0,27,91,50,49,59,50,126,0,27,91,50,51,59,50,126,0,27,91,50,52,59,50,126,0,27,91,49,59,53,80,0,27,91,49,59,53,81,0,27,91,49,59,53,82,0,27,91,49,59,53,83,0,27,91,49,53,59,53,126,0,27,91,49,55,59,53,126,0,27,91,49,56,59,53,126,0,27,91,49,57,59,53,126,0,27,91,50,48,59,53,126,0,27,91,50,49,59,53,126,0,27,91,50,51,59,53,126,0,27,91,50,52,59,53,126,0,27,91,49,59,54,80,0,27,91,49,59,54,81,0,27,91,49,59,54,82,0,27,91,49,59,54,83,0,27,91,49,53,59,54,126,0,27,91,49,55,59,54,126,0,27,91,49,56,59,54,126,0,27,91,49,57,59,54,126,0,27,91,50,48,59,54,126,0,27,91,50,49,59,54,126,0,27,91,50,51,59,54,126,0,27,91,50,52,59,54,126,0,27,91,49,59,51,80,0,27,91,49,59,51,81,0,27,91,49,59,51,82,0,27,91,49,59,51,83,0,27,91,49,53,59,51,126,0,27,91,49,55,59,51,126,0,27,91,49,56,59,51,126,0,27,91,49,57,59,51,126,0,27,91,50,48,59,51,126,0,27,91,50,49,59,51,126,0,27,91,50,51,59,51,126,0,27,91,50,52,59,51,126,0,27,91,49,59,52,80,0,27,91,49,59,52,81,0,27,91,49,59,52,82,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,37,91,59,48,49,50,51,52,53,54,55,56,57,93,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,93,49,48,52,7,0,27,93,52,59,37,112,49,37,100,59,114,103,98,58,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,27,92,0,27,91,51,109,0,27,91,50,51,109,0,27,91,60,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,27,108,0,27,109,0,0,1,0,0,0,59,0,119,0,22,3,1,0,0,0,6,0,12,0,23,0,55,0,62,0,69,0,76,0,83,0,90,0,97,0,104,0,111,0,118,0,125,0,-124,0,-117,0,-110,0,-103,0,-96,0,-89,0,-82,0,-75,0,-68,0,-61,0,-54,0,-47,0,-40,0,-33,0,-26,0,-19,0,-12,0,-5,0,2,1,9,1,16,1,23,1,30,1,37,1,44,1,51,1,58,1,65,1,72,1,79,1,86,1,93,1,100,1,107,1,114,1,121,1,-128,1,-121,1,-114,1,-107,1,-100,1,-93,1,-87,1,-82,1,0,0,3,0,8,0,13,0,19,0,22,0,27,0,32,0,37,0,42,0,47,0,51,0,56,0,61,0,66,0,71,0,76,0,82,0,88,0,94,0,100,0,106,0,112,0,118,0,124,0,-126,0,-120,0,-115,0,-110,0,-105,0,-100,0,-95,0,-89,0,-83,0,-77,0,-71,0,-65,0,-59,0,-53,0,-47,0,-41,0,-35,0,-29,0,-23,0,-17,0,-11,0,-5,0,1,1,7,1,13,1,19,1,25,1,29,1,34,1,39,1,44,1,49,1,54,1,59,1,64,1,27,91,53,53,109,0,27,91,53,51,109,0,27,91,52,58,37,112,49,37,100,109,0,27,91,63,49,48,48,54,59,49,48,48,48,37,63,37,112,49,37,123,49,125,37,61,37,116,104,37,101,108,37,59,0,27,91,51,59,51,126,0,27,91,51,59,52,126,0,27,91,51,59,53,126,0,27,91,51,59,54,126,0,27,91,51,59,55,126,0,27,91,49,59,50,66,0,27,91,49,59,51,66,0,27,91,49,59,52,66,0,27,91,49,59,53,66,0,27,91,49,59,54,66,0,27,91,49,59,55,66,0,27,91,49,59,51,70,0,27,91,49,59,52,70,0,27,91,49,59,53,70,0,27,91,49,59,54,70,0,27,91,49,59,55,70,0,27,91,49,59,51,72,0,27,91,49,59,52,72,0,27,91,49,59,53,72,0,27,91,49,59,54,72,0,27,91,49,59,55,72,0,27,91,50,59,51,126,0,27,91,50,59,52,126,0,27,91,50,59,53,126,0,27,91,50,59,54,126,0,27,91,50,59,55,126,0,27,91,49,59,51,68,0,27,91,49,59,52,68,0,27,91,49,59,53,68,0,27,91,49,59,54,68,0,27,91,49,59,55,68,0,27,91,54,59,51,126,0,27,91,54,59,52,126,0,27,91,54,59,53,126,0,27,91,54,59,54,126,0,27,91,54,59,55,126,0,27,91,53,59,51,126,0,27,91,53,59,52,126,0,27,91,53,59,53,126,0,27,91,53,59,54,126,0,27,91,53,59,55,126,0,27,91,49,59,51,67,0,27,91,49,59,52,67,0,27,91,49,59,53,67,0,27,91,49,59,54,67,0,27,91,49,59,55,67,0,27,91,49,59,50,65,0,27,91,49,59,51,65,0,27,91,49,59,52,65,0,27,91,49,59,53,65,0,27,91,49,59,54,65,0,27,91,49,59,55,65,0,27,91,50,57,109,0,27,91,57,109,0,27,91,60,37,105,37,112,51,37,100,59,37,112,49,37,100,59,37,112,50,37,100,59,37,63,37,112,52,37,116,77,37,101,109,37,59,0,88,84,0,82,109,111,108,0,83,109,111,108,0,83,109,117,108,120,0,88,77,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,114,109,120,120,0,115,109,120,120,0,120,109,0
+ 30,2,39,0,38,0,15,0,-99,1,7,6,118,116,101,45,50,53,54,99,111,108,111,114,124,86,84,69,32,119,105,116,104,32,120,116,101,114,109,32,50,53,54,45,99,111,108,111,114,115,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,25,0,30,0,38,0,42,0,46,0,-1,-1,57,0,74,0,76,0,80,0,87,0,-1,-1,89,0,96,0,-1,-1,100,0,-1,-1,104,0,108,0,-1,-1,-1,-1,112,0,114,0,119,0,124,0,-1,-1,-114,0,-109,0,-104,0,-1,-1,-99,0,-94,0,-89,0,-84,0,-75,0,-73,0,-67,0,-1,-1,-49,0,-44,0,-38,0,-32,0,-1,-1,-1,-1,-1,-1,-14,0,-1,-1,-1,-1,-1,-1,19,1,-1,-1,23,1,-1,-1,-1,-1,-1,-1,25,1,-1,-1,30,1,-1,-1,-1,-1,-1,-1,-1,-1,34,1,38,1,44,1,48,1,52,1,56,1,62,1,68,1,74,1,80,1,86,1,90,1,-1,-1,95,1,-1,-1,99,1,104,1,109,1,113,1,120,1,-1,-1,127,1,-125,1,-117,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-109,1,-1,-1,-106,1,-97,1,-88,1,-79,1,-70,1,-61,1,-52,1,-43,1,-34,1,-25,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-16,1,4,2,7,2,-1,-1,-1,-1,58,2,61,2,72,2,75,2,77,2,80,2,-87,2,-1,-1,-84,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-82,2,-1,-1,-1,-1,-1,-1,-1,-1,-78,2,-1,-1,-25,2,-1,-1,-1,-1,-21,2,-15,2,-1,-1,-1,-1,-9,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,2,2,3,-1,-1,6,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,11,3,-1,-1,18,3,23,3,-1,-1,-1,-1,-1,-1,-1,-1,30,3,37,3,44,3,-1,-1,-1,-1,51,3,-1,-1,58,3,-1,-1,-1,-1,-1,-1,65,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,72,3,78,3,84,3,91,3,98,3,105,3,112,3,120,3,-128,3,-120,3,-112,3,-104,3,-96,3,-88,3,-80,3,-73,3,-66,3,-59,3,-52,3,-44,3,-36,3,-28,3,-20,3,-12,3,-4,3,4,4,12,4,19,4,26,4,33,4,40,4,48,4,56,4,64,4,72,4,80,4,88,4,96,4,104,4,111,4,118,4,125,4,-124,4,-116,4,-108,4,-100,4,-92,4,-84,4,-76,4,-68,4,-60,4,-53,4,-46,4,-39,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-34,4,-23,4,-18,4,1,5,5,5,14,5,21,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,115,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,120,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,126,5,-1,-1,-1,-1,-1,-1,-126,5,-63,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1,6,4,6,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,14,0,27,91,53,109,0,27,91,49,109,0,27,91,63,49,48,52,57,104,27,91,50,50,59,48,59,48,116,0,27,91,50,109,0,27,91,52,104,0,27,91,56,109,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,15,0,27,91,48,109,15,0,27,91,63,49,48,52,57,108,27,91,50,51,59,48,59,48,116,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,49,48,48,47,62,27,91,63,53,108,0,27,91,109,27,91,63,55,104,27,91,52,108,27,62,27,55,27,91,114,27,91,63,49,59,51,59,52,59,54,108,27,56,0,27,91,76,0,127,0,27,91,51,126,0,27,79,66,0,27,79,80,0,27,91,50,49,126,0,27,79,81,0,27,79,82,0,27,79,83,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,79,72,0,27,91,50,126,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,27,69,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,99,0,27,55,27,91,114,27,56,27,91,109,27,91,63,55,104,27,91,33,112,27,91,63,49,59,51,59,52,59,54,108,27,91,52,108,27,62,27,91,63,49,48,48,48,108,27,91,63,50,53,104,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,54,37,116,59,49,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,52,37,116,59,53,37,59,37,63,37,112,53,37,116,59,50,37,59,37,63,37,112,55,37,116,59,56,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,109,37,63,37,112,57,37,116,14,37,101,15,37,59,0,27,72,0,9,0,27,91,69,0,96,96,97,97,102,102,103,103,105,105,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,91,90,0,27,91,63,55,104,0,27,91,63,55,108,0,27,40,66,27,41,48,0,27,79,70,0,27,79,77,0,27,91,49,126,0,27,91,51,59,50,126,0,27,91,52,126,0,27,91,49,59,50,70,0,27,91,49,59,50,72,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,49,59,50,80,0,27,91,49,59,50,81,0,27,91,49,59,50,82,0,27,91,49,59,50,83,0,27,91,49,53,59,50,126,0,27,91,49,55,59,50,126,0,27,91,49,56,59,50,126,0,27,91,49,57,59,50,126,0,27,91,50,48,59,50,126,0,27,91,50,49,59,50,126,0,27,91,50,51,59,50,126,0,27,91,50,52,59,50,126,0,27,91,49,59,53,80,0,27,91,49,59,53,81,0,27,91,49,59,53,82,0,27,91,49,59,53,83,0,27,91,49,53,59,53,126,0,27,91,49,55,59,53,126,0,27,91,49,56,59,53,126,0,27,91,49,57,59,53,126,0,27,91,50,48,59,53,126,0,27,91,50,49,59,53,126,0,27,91,50,51,59,53,126,0,27,91,50,52,59,53,126,0,27,91,49,59,54,80,0,27,91,49,59,54,81,0,27,91,49,59,54,82,0,27,91,49,59,54,83,0,27,91,49,53,59,54,126,0,27,91,49,55,59,54,126,0,27,91,49,56,59,54,126,0,27,91,49,57,59,54,126,0,27,91,50,48,59,54,126,0,27,91,50,49,59,54,126,0,27,91,50,51,59,54,126,0,27,91,50,52,59,54,126,0,27,91,49,59,51,80,0,27,91,49,59,51,81,0,27,91,49,59,51,82,0,27,91,49,59,51,83,0,27,91,49,53,59,51,126,0,27,91,49,55,59,51,126,0,27,91,49,56,59,51,126,0,27,91,49,57,59,51,126,0,27,91,50,48,59,51,126,0,27,91,50,49,59,51,126,0,27,91,50,51,59,51,126,0,27,91,50,52,59,51,126,0,27,91,49,59,52,80,0,27,91,49,59,52,81,0,27,91,49,59,52,82,0,27,91,49,75,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,37,91,59,48,49,50,51,52,53,54,55,56,57,93,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,93,49,48,52,7,0,27,93,52,59,37,112,49,37,100,59,114,103,98,58,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,27,92,0,27,91,51,109,0,27,91,50,51,109,0,27,91,60,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,27,108,0,27,109,0,0,2,0,0,0,69,0,-116,0,-52,3,1,1,0,0,9,0,18,0,25,0,37,0,55,0,62,0,69,0,75,0,81,0,87,0,98,0,108,0,-116,0,-109,0,-102,0,-95,0,-88,0,-81,0,-74,0,-67,0,-60,0,-53,0,-46,0,-39,0,-32,0,-25,0,-18,0,-11,0,-4,0,3,1,10,1,17,1,24,1,31,1,38,1,45,1,52,1,59,1,66,1,73,1,80,1,87,1,94,1,101,1,108,1,115,1,122,1,-127,1,-120,1,-113,1,-106,1,-99,1,-92,1,-85,1,-78,1,-71,1,-64,1,-57,1,-50,1,-43,1,-36,1,-29,1,-22,1,-15,1,-8,1,-2,1,59,2,64,2,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,32,0,35,0,40,0,46,0,49,0,52,0,57,0,62,0,67,0,72,0,77,0,81,0,86,0,91,0,96,0,101,0,106,0,112,0,118,0,124,0,-126,0,-120,0,-114,0,-108,0,-102,0,-96,0,-90,0,-85,0,-80,0,-75,0,-70,0,-65,0,-59,0,-53,0,-47,0,-41,0,-35,0,-29,0,-23,0,-17,0,-11,0,-5,0,1,1,7,1,13,1,19,1,25,1,31,1,37,1,43,1,49,1,55,1,59,1,64,1,69,1,74,1,79,1,84,1,89,1,95,1,100,1,27,91,63,50,48,48,52,108,0,27,91,63,50,48,48,52,104,0,27,93,49,49,50,7,0,27,93,49,50,59,37,112,49,37,115,7,0,27,93,53,50,59,37,112,49,37,115,59,37,112,50,37,115,7,0,27,91,50,48,49,126,0,27,91,50,48,48,126,0,27,91,53,53,109,0,27,91,49,32,113,0,27,91,53,51,109,0,27,91,52,58,37,112,49,37,100,109,0,27,91,37,112,49,37,100,32,113,0,27,91,63,49,48,48,54,59,49,48,48,48,37,63,37,112,49,37,123,49,125,37,61,37,116,104,37,101,108,37,59,0,27,91,51,59,51,126,0,27,91,51,59,52,126,0,27,91,51,59,53,126,0,27,91,51,59,54,126,0,27,91,51,59,55,126,0,27,91,49,59,50,66,0,27,91,49,59,51,66,0,27,91,49,59,52,66,0,27,91,49,59,53,66,0,27,91,49,59,54,66,0,27,91,49,59,55,66,0,27,91,49,59,51,70,0,27,91,49,59,52,70,0,27,91,49,59,53,70,0,27,91,49,59,54,70,0,27,91,49,59,55,70,0,27,91,49,59,51,72,0,27,91,49,59,52,72,0,27,91,49,59,53,72,0,27,91,49,59,54,72,0,27,91,49,59,55,72,0,27,91,50,59,51,126,0,27,91,50,59,52,126,0,27,91,50,59,53,126,0,27,91,50,59,54,126,0,27,91,50,59,55,126,0,27,91,49,59,51,68,0,27,91,49,59,52,68,0,27,91,49,59,53,68,0,27,91,49,59,54,68,0,27,91,49,59,55,68,0,27,91,54,59,51,126,0,27,91,54,59,52,126,0,27,91,54,59,53,126,0,27,91,54,59,54,126,0,27,91,54,59,55,126,0,27,91,53,59,51,126,0,27,91,53,59,52,126,0,27,91,53,59,53,126,0,27,91,53,59,54,126,0,27,91,53,59,55,126,0,27,91,49,59,51,67,0,27,91,49,59,52,67,0,27,91,49,59,53,67,0,27,91,49,59,54,67,0,27,91,49,59,55,67,0,27,91,49,59,50,65,0,27,91,49,59,51,65,0,27,91,49,59,52,65,0,27,91,49,59,53,65,0,27,91,49,59,54,65,0,27,91,49,59,55,65,0,27,91,50,57,109,0,27,91,53,56,58,50,58,58,37,112,49,37,123,54,53,53,51,54,125,37,47,37,100,58,37,112,49,37,123,50,53,54,125,37,47,37,123,50,53,53,125,37,38,37,100,58,37,112,49,37,123,50,53,53,125,37,38,37,100,109,0,27,91,57,109,0,27,91,60,37,105,37,112,51,37,100,59,37,112,49,37,100,59,37,112,50,37,100,59,37,63,37,112,52,37,116,77,37,101,109,37,59,0,65,88,0,88,84,0,66,68,0,66,69,0,67,114,0,67,115,0,77,115,0,80,69,0,80,83,0,82,109,111,108,0,83,101,0,83,109,111,108,0,83,109,117,108,120,0,83,115,0,88,77,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,114,109,120,120,0,115,101,116,97,108,0,115,109,120,120,0,120,109,0
};
// vtpcon|ANIS emulation for console virtual terminal sequence with libuv,
@@ -1776,6 +1783,7 @@ static const int8_t vte_256colour_terminfo[] = {
// back_color_erase,
// backspaces_with_bs,
// has_meta_key,
+// has_status_line,
// move_insert_mode,
// move_standout_mode,
// no_pad_char,
@@ -1807,6 +1815,7 @@ static const int8_t vte_256colour_terminfo[] = {
// cursor_visible@,
// delete_character=\E[P,
// delete_line=\E[M,
+// dis_status_line=\E]0;^G,
// enter_alt_charset_mode=\E(0,
// enter_am_mode@,
// enter_blink_mode@,
@@ -1829,6 +1838,7 @@ static const int8_t vte_256colour_terminfo[] = {
// exit_standout_mode=\E[27m,
// exit_underline_mode=\E[24m,
// flash_screen@,
+// from_status_line=^G,
// init_2string=\E[\041p\E[?3l,
// initialize_color=\E]4;%p1%d;rgb\072%p2%{255}%*%{1000}%/%2.2X/%p3%{255}%*%{1000}%/%2.2X/%p4%{255}%*%{1000}%/%2.2X\E,
// insert_line=\E[L,
@@ -1836,6 +1846,7 @@ static const int8_t vte_256colour_terminfo[] = {
// key_a3=\EOy,
// key_b2=\E[G,
// key_backspace=^H,
+// key_beg=\EOE,
// key_btab=\E[Z,
// key_c1=\EOq,
// key_c3=\EOs,
@@ -1957,15 +1968,18 @@ static const int8_t vte_256colour_terminfo[] = {
// set_a_background=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
// set_a_foreground=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m,
// set_attributes=\E[0%?%p1%p3%|%t;7%;%?%p2%t;4%;%?%p6%t;1%;m,
+// set_left_margin_parm@,
// set_lr_margin@,
+// set_right_margin_parm@,
// set_tab=\EH,
// tab=^I,
+// to_status_line=\E]0;,
// user6@,
// user7@,
// user8@,
// user9@,
static const int8_t vtpcon_terminfo[] = {
- 30,2,71,0,38,0,15,0,-99,1,47,4,118,116,112,99,111,110,124,65,78,73,83,32,101,109,117,108,97,116,105,111,110,32,102,111,114,32,99,111,110,115,111,108,101,32,118,105,114,116,117,97,108,32,116,101,114,109,105,110,97,108,32,115,101,113,117,101,110,99,101,32,119,105,116,104,32,108,105,98,117,118,0,0,1,0,0,0,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,-2,-1,25,0,33,0,37,0,41,0,-1,-1,52,0,69,0,73,0,77,0,84,0,-1,-1,86,0,99,0,-1,-1,103,0,-2,-1,107,0,111,0,-1,-1,-1,-1,115,0,-2,-1,119,0,124,0,-1,-1,-2,-1,-2,-1,-2,-1,-1,-1,-123,0,-118,0,-113,0,-108,0,-99,0,-95,0,-90,0,-1,-1,-2,-1,-81,0,-75,0,-2,-1,-1,-1,-1,-1,-1,-1,-69,0,-1,-1,-1,-1,-1,-1,-59,0,-1,-1,-55,0,-1,-1,-1,-1,-1,-1,-53,0,-1,-1,-48,0,-1,-1,-1,-1,-1,-1,-1,-1,-44,0,-39,0,-33,0,-28,0,-23,0,-18,0,-13,0,-7,0,-1,0,5,1,11,1,16,1,-1,-1,21,1,-1,-1,25,1,30,1,35,1,39,1,46,1,-1,-1,53,1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,57,1,-1,-1,60,1,69,1,78,1,87,1,96,1,105,1,114,1,123,1,-124,1,-115,1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-106,1,-2,-1,-2,-1,-1,-1,-1,-1,-86,1,-83,1,-72,1,-69,1,-67,1,-64,1,-21,1,-1,-1,-18,1,-1,-1,-1,-1,-1,-1,-1,-1,-16,1,-12,1,-8,1,-4,1,0,2,-1,-1,-1,-1,4,2,-1,-1,27,2,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,31,2,36,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,40,2,-1,-1,-1,-1,47,2,-1,-1,-1,-1,-1,-1,-1,-1,54,2,61,2,68,2,-1,-1,-1,-1,75,2,-1,-1,82,2,-1,-1,-1,-1,-1,-1,89,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,96,2,102,2,108,2,114,2,120,2,126,2,-124,2,-118,2,-112,2,-106,2,-100,2,-94,2,-88,2,-82,2,-76,2,-70,2,-64,2,-58,2,-52,2,-46,2,-40,2,-34,2,-28,2,-22,2,-16,2,-10,2,-4,2,2,3,8,3,14,3,21,3,27,3,33,3,39,3,45,3,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,51,3,56,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,63,3,-2,-1,72,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-91,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-86,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-80,3,-17,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,27,91,66,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,49,50,108,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,40,48,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,40,66,0,27,91,48,109,0,27,91,63,49,48,52,57,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,33,112,27,91,63,51,108,0,27,91,76,0,8,0,27,91,51,126,0,27,91,66,0,27,91,91,65,0,27,91,50,49,126,0,27,91,91,66,0,27,91,91,67,0,27,91,91,68,0,27,91,91,69,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,68,0,27,91,54,126,0,27,91,53,126,0,27,91,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,91,65,0,27,69,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,54,37,116,59,49,37,59,109,0,27,72,0,9,0,27,79,119,0,27,79,121,0,27,91,71,0,27,79,113,0,27,79,115,0,106,106,107,107,108,108,109,109,110,110,113,113,116,116,117,117,118,118,119,119,120,120,0,27,91,90,0,27,91,52,126,0,27,79,77,0,27,91,51,59,50,126,0,27,91,52,59,50,126,0,27,91,49,59,50,126,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,50,51,36,0,27,91,50,52,36,0,27,91,49,49,94,0,27,91,49,50,94,0,27,91,49,51,94,0,27,91,49,52,94,0,27,91,49,53,94,0,27,91,49,55,94,0,27,91,49,56,94,0,27,91,49,57,94,0,27,91,50,48,94,0,27,91,50,49,94,0,27,91,50,51,94,0,27,91,50,52,94,0,27,91,50,53,94,0,27,91,50,54,94,0,27,91,50,56,94,0,27,91,50,57,94,0,27,91,51,49,94,0,27,91,49,59,54,83,0,27,91,51,50,94,0,27,91,51,51,94,0,27,91,51,52,94,0,27,91,50,51,64,0,27,91,50,52,64,0,27,91,49,75,0,27,91,63,54,57,108,0,27,91,51,57,59,52,57,109,0,27,93,52,59,37,112,49,37,100,59,114,103,98,58,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,27,0,27,91,51,109,0,27,91,50,51,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,0,2,0,0,0,74,0,92,0,-46,1,1,1,-2,-1,-2,-1,0,0,-2,-1,5,0,11,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,21,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,28,0,32,0,36,0,40,0,44,0,48,0,52,0,56,0,60,0,64,0,68,0,72,0,-2,-1,-2,-1,-2,-1,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,32,0,37,0,42,0,47,0,52,0,56,0,61,0,66,0,71,0,76,0,81,0,87,0,93,0,99,0,105,0,111,0,117,0,123,0,-127,0,-121,0,-115,0,-110,0,-105,0,-100,0,-95,0,-90,0,-84,0,-78,0,-72,0,-66,0,-60,0,-54,0,-48,0,-42,0,-36,0,-30,0,-24,0,-18,0,-12,0,-6,0,0,1,6,1,12,1,18,1,24,1,30,1,34,1,39,1,44,1,49,1,54,1,59,1,63,1,67,1,71,1,75,1,79,1,85,1,91,1,97,1,103,1,109,1,115,1,121,1,126,1,-125,1,27,91,51,74,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,91,49,59,50,65,0,27,79,120,0,27,79,116,0,27,79,118,0,27,79,114,0,27,79,69,0,27,79,107,0,27,79,108,0,27,79,111,0,27,79,110,0,27,79,106,0,27,79,109,0,27,79,112,0,65,88,0,88,84,0,67,114,0,67,115,0,69,51,0,77,115,0,83,101,0,83,115,0,88,77,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,107,97,50,0,107,98,49,0,107,98,51,0,107,99,50,0,107,112,53,0,107,112,65,68,68,0,107,112,67,77,65,0,107,112,68,73,86,0,107,112,68,79,84,0,107,112,77,85,76,0,107,112,83,85,66,0,107,112,90,82,79,0,114,109,120,120,0,115,109,120,120,0,120,109,0
+ 30,2,71,0,38,0,15,0,-99,1,64,4,118,116,112,99,111,110,124,65,78,73,83,32,101,109,117,108,97,116,105,111,110,32,102,111,114,32,99,111,110,115,111,108,101,32,118,105,114,116,117,97,108,32,116,101,114,109,105,110,97,108,32,115,101,113,117,101,110,99,101,32,119,105,116,104,32,108,105,98,117,118,0,0,1,0,0,0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,-2,-1,25,0,33,0,37,0,41,0,-1,-1,52,0,69,0,73,0,77,0,84,0,-1,-1,86,0,99,0,-1,-1,103,0,-2,-1,107,0,111,0,115,0,-1,-1,121,0,-2,-1,125,0,-126,0,-1,-1,-2,-1,-2,-1,-2,-1,-1,-1,-117,0,-112,0,-107,0,-102,0,-93,0,-89,0,-84,0,-1,-1,-2,-1,-75,0,-69,0,-2,-1,-1,-1,-63,0,-1,-1,-61,0,-1,-1,-1,-1,-1,-1,-51,0,-1,-1,-47,0,-1,-1,-1,-1,-1,-1,-45,0,-1,-1,-40,0,-1,-1,-1,-1,-1,-1,-1,-1,-36,0,-31,0,-25,0,-20,0,-15,0,-10,0,-5,0,1,1,7,1,13,1,19,1,24,1,-1,-1,29,1,-1,-1,33,1,38,1,43,1,47,1,54,1,-1,-1,61,1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,65,1,-1,-1,68,1,77,1,86,1,95,1,104,1,113,1,122,1,-125,1,-116,1,-107,1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-98,1,-2,-1,-2,-1,-1,-1,-1,-1,-78,1,-75,1,-64,1,-61,1,-59,1,-56,1,-13,1,-1,-1,-10,1,-8,1,-1,-1,-1,-1,-1,-1,-3,1,1,2,5,2,9,2,13,2,-1,-1,-1,-1,17,2,-1,-1,40,2,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,44,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,48,2,53,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,57,2,-1,-1,-1,-1,64,2,-1,-1,-1,-1,-1,-1,-1,-1,71,2,78,2,85,2,-1,-1,-1,-1,92,2,-1,-1,99,2,-1,-1,-1,-1,-1,-1,106,2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,113,2,119,2,125,2,-125,2,-119,2,-113,2,-107,2,-101,2,-95,2,-89,2,-83,2,-77,2,-71,2,-65,2,-59,2,-53,2,-47,2,-41,2,-35,2,-29,2,-23,2,-17,2,-11,2,-5,2,1,3,7,3,13,3,19,3,25,3,31,3,38,3,44,3,50,3,56,3,62,3,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,68,3,73,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-2,-1,-2,-1,80,3,-2,-1,89,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-74,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-69,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-63,3,0,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-2,-1,-2,-1,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,27,91,66,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,49,50,108,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,80,0,27,91,77,0,27,93,48,59,7,0,27,40,48,0,27,91,49,109,0,27,91,63,49,48,52,57,104,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,40,66,0,27,91,48,109,0,27,91,63,49,48,52,57,108,0,27,91,50,55,109,0,27,91,50,52,109,0,7,0,27,91,33,112,27,91,63,51,108,0,27,91,76,0,8,0,27,91,51,126,0,27,91,66,0,27,91,91,65,0,27,91,50,49,126,0,27,91,91,66,0,27,91,91,67,0,27,91,91,68,0,27,91,91,69,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,91,49,126,0,27,91,50,126,0,27,91,68,0,27,91,54,126,0,27,91,53,126,0,27,91,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,91,65,0,27,69,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,27,91,48,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,54,37,116,59,49,37,59,109,0,27,72,0,9,0,27,93,48,59,0,27,79,119,0,27,79,121,0,27,91,71,0,27,79,113,0,27,79,115,0,106,106,107,107,108,108,109,109,110,110,113,113,116,116,117,117,118,118,119,119,120,120,0,27,91,90,0,27,79,69,0,27,91,52,126,0,27,79,77,0,27,91,51,59,50,126,0,27,91,52,59,50,126,0,27,91,49,59,50,126,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,50,53,126,0,27,91,50,54,126,0,27,91,50,56,126,0,27,91,50,57,126,0,27,91,51,49,126,0,27,91,51,50,126,0,27,91,51,51,126,0,27,91,51,52,126,0,27,91,50,51,36,0,27,91,50,52,36,0,27,91,49,49,94,0,27,91,49,50,94,0,27,91,49,51,94,0,27,91,49,52,94,0,27,91,49,53,94,0,27,91,49,55,94,0,27,91,49,56,94,0,27,91,49,57,94,0,27,91,50,48,94,0,27,91,50,49,94,0,27,91,50,51,94,0,27,91,50,52,94,0,27,91,50,53,94,0,27,91,50,54,94,0,27,91,50,56,94,0,27,91,50,57,94,0,27,91,51,49,94,0,27,91,49,59,54,83,0,27,91,51,50,94,0,27,91,51,51,94,0,27,91,51,52,94,0,27,91,50,51,64,0,27,91,50,52,64,0,27,91,49,75,0,27,91,63,54,57,108,0,27,91,51,57,59,52,57,109,0,27,93,52,59,37,112,49,37,100,59,114,103,98,58,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,27,0,27,91,51,109,0,27,91,50,51,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,3,0,0,0,87,0,119,0,-127,2,1,1,1,0,0,0,9,0,-2,-1,-2,-1,18,0,-2,-1,23,0,30,0,37,0,42,0,48,0,58,0,-2,-1,63,0,69,0,78,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,87,0,-2,-1,-2,-1,-2,-1,-2,-1,-2,-1,94,0,98,0,102,0,106,0,110,0,114,0,118,0,122,0,126,0,-126,0,-122,0,-118,0,-114,0,-110,0,-2,-1,-106,0,-2,-1,-2,-1,-81,0,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,30,0,33,0,36,0,39,0,42,0,45,0,48,0,51,0,54,0,57,0,62,0,67,0,72,0,77,0,82,0,86,0,91,0,96,0,101,0,106,0,111,0,117,0,123,0,-127,0,-121,0,-115,0,-109,0,-103,0,-97,0,-91,0,-85,0,-80,0,-75,0,-70,0,-65,0,-60,0,-54,0,-48,0,-42,0,-36,0,-30,0,-24,0,-18,0,-12,0,-6,0,0,1,6,1,12,1,18,1,24,1,30,1,36,1,42,1,48,1,54,1,60,1,64,1,69,1,74,1,79,1,84,1,89,1,93,1,97,1,101,1,105,1,109,1,115,1,121,1,127,1,-123,1,-117,1,-111,1,-105,1,-100,1,-94,1,-89,1,-86,1,-81,1,-78,1,27,91,63,50,48,48,52,108,0,27,91,63,50,48,48,52,104,0,27,91,51,74,0,27,91,50,48,49,126,0,27,91,50,48,48,126,0,27,91,62,99,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,93,48,59,0,27,91,62,48,113,0,27,91,63,49,48,48,52,108,0,27,91,63,49,48,48,52,104,0,27,91,49,59,50,65,0,27,79,120,0,27,79,116,0,27,79,118,0,27,79,114,0,27,79,69,0,27,79,107,0,27,79,108,0,27,79,111,0,27,79,110,0,27,79,106,0,27,79,109,0,27,79,112,0,27,91,73,0,27,91,79,0,27,92,91,52,49,59,91,49,45,54,93,91,48,45,57,93,91,48,45,57,93,59,48,99,0,27,80,62,92,124,88,84,101,114,109,92,40,91,49,45,57,93,91,48,45,57,93,43,92,41,27,92,92,0,65,88,0,88,70,0,88,84,0,66,68,0,66,69,0,67,114,0,67,115,0,69,51,0,77,115,0,80,69,0,80,83,0,82,86,0,83,101,0,83,115,0,84,83,0,88,77,0,88,82,0,102,100,0,102,101,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,107,97,50,0,107,98,49,0,107,98,51,0,107,99,50,0,107,112,53,0,107,112,65,68,68,0,107,112,67,77,65,0,107,112,68,73,86,0,107,112,68,79,84,0,107,112,77,85,76,0,107,112,83,85,66,0,107,112,90,82,79,0,107,120,73,78,0,107,120,79,85,84,0,114,109,120,120,0,114,118,0,115,109,120,120,0,120,109,0,120,114,0
};
// win32con|ANSI emulation for libuv on legacy console,
@@ -2172,6 +2186,7 @@ static const int8_t win32con_terminfo[] = {
// key_a3=\EOy,
// key_b2=\EOu,
// key_backspace=^H,
+// key_beg=\EOE,
// key_btab=\E[Z,
// key_c1=\EOq,
// key_c3=\EOs,
@@ -2293,7 +2308,9 @@ static const int8_t win32con_terminfo[] = {
// set_a_background=\E[%?%p1%{8}%<%t4%p1%d%e%p1%{16}%<%t10%p1%{8}%-%d%e48;5;%p1%d%;m,
// set_a_foreground=\E[%?%p1%{8}%<%t3%p1%d%e%p1%{16}%<%t9%p1%{8}%-%d%e38;5;%p1%d%;m,
// set_attributes=%?%p9%t\E(0%e\E(B%;\E[0%?%p6%t;1%;%?%p5%t;2%;%?%p2%t;4%;%?%p1%p3%|%t;7%;%?%p4%t;5%;%?%p7%t;8%;m,
+// set_left_margin_parm=\E[?69h\E[%i%p1%ds,
// set_lr_margin=\E[?69h\E[%i%p1%d;%p2%ds,
+// set_right_margin_parm=\E[?69h\E[%i;%p1%ds,
// set_tab=\EH,
// tab=^I,
// user6=\E[%i%d;%dR,
@@ -2301,5 +2318,5 @@ static const int8_t win32con_terminfo[] = {
// user8=\E[?%[;0123456789]c,
// user9=\E[c,
static const int8_t xterm_256colour_terminfo[] = {
- 30,2,37,0,38,0,15,0,-99,1,51,6,120,116,101,114,109,45,50,53,54,99,111,108,111,114,124,120,116,101,114,109,32,119,105,116,104,32,50,53,54,32,99,111,108,111,114,115,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,25,0,30,0,38,0,42,0,46,0,-1,-1,57,0,74,0,76,0,80,0,87,0,-1,-1,89,0,102,0,-1,-1,106,0,110,0,120,0,124,0,-1,-1,-1,-1,-128,0,-124,0,-119,0,-114,0,-1,-1,-96,0,-91,0,-86,0,-1,-1,-81,0,-76,0,-71,0,-66,0,-57,0,-53,0,-46,0,-1,-1,-28,0,-23,0,-17,0,-11,0,-1,-1,-1,-1,-1,-1,7,1,-1,-1,-1,-1,-1,-1,25,1,-1,-1,29,1,-1,-1,-1,-1,-1,-1,31,1,-1,-1,36,1,-1,-1,-1,-1,-1,-1,-1,-1,40,1,44,1,50,1,54,1,58,1,62,1,68,1,74,1,80,1,86,1,92,1,96,1,-1,-1,101,1,-1,-1,105,1,110,1,115,1,119,1,126,1,-1,-1,-123,1,-119,1,-111,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-103,1,-94,1,-85,1,-1,-1,-82,1,-73,1,-64,1,-55,1,-46,1,-37,1,-28,1,-19,1,-10,1,-1,1,-1,-1,-1,-1,-1,-1,8,2,12,2,17,2,22,2,42,2,51,2,-1,-1,-1,-1,69,2,72,2,83,2,86,2,88,2,91,2,-72,2,-1,-1,-69,2,-1,-1,-1,-1,-1,-1,-1,-1,-67,2,-63,2,-59,2,-55,2,-51,2,-1,-1,-1,-1,-47,2,-1,-1,6,3,-1,-1,-1,-1,10,3,16,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,22,3,26,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,30,3,-1,-1,-1,-1,37,3,-1,-1,-1,-1,-1,-1,-1,-1,44,3,51,3,58,3,-1,-1,-1,-1,65,3,-1,-1,72,3,-1,-1,-1,-1,-1,-1,79,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,86,3,92,3,98,3,105,3,112,3,119,3,126,3,-122,3,-114,3,-106,3,-98,3,-90,3,-82,3,-74,3,-66,3,-59,3,-52,3,-45,3,-38,3,-30,3,-22,3,-14,3,-6,3,2,4,10,4,18,4,26,4,33,4,40,4,47,4,54,4,62,4,70,4,78,4,86,4,94,4,102,4,110,4,118,4,125,4,-124,4,-117,4,-110,4,-102,4,-94,4,-86,4,-78,4,-70,4,-62,4,-54,4,-46,4,-39,4,-32,4,-25,4,-20,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-13,4,-2,4,3,5,22,5,26,5,35,5,42,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-120,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-115,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-109,5,-1,-1,-1,-1,-1,-1,-105,5,-42,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,22,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,45,6,48,6,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,49,50,108,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,63,49,50,59,50,53,104,0,27,91,80,0,27,91,77,0,27,40,48,0,27,91,53,109,0,27,91,49,109,0,27,91,63,49,48,52,57,104,27,91,50,50,59,48,59,48,116,0,27,91,50,109,0,27,91,52,104,0,27,91,56,109,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,40,66,0,27,40,66,27,91,109,0,27,91,63,49,48,52,57,108,27,91,50,51,59,48,59,48,116,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,49,48,48,47,62,27,91,63,53,108,0,27,91,33,112,27,91,63,51,59,52,108,27,91,52,108,27,62,0,27,91,76,0,8,0,27,91,51,126,0,27,79,66,0,27,79,80,0,27,91,50,49,126,0,27,79,81,0,27,79,82,0,27,79,83,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,79,72,0,27,91,50,126,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,27,91,63,49,48,51,52,108,0,27,91,63,49,48,51,52,104,0,27,69,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,27,91,105,0,27,91,52,105,0,27,91,53,105,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,99,27,93,49,48,52,7,0,27,91,33,112,27,91,63,51,59,52,108,27,91,52,108,27,62,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,37,63,37,112,57,37,116,27,40,48,37,101,27,40,66,37,59,27,91,48,37,63,37,112,54,37,116,59,49,37,59,37,63,37,112,53,37,116,59,50,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,37,63,37,112,55,37,116,59,56,37,59,109,0,27,72,0,9,0,27,79,119,0,27,79,121,0,27,79,117,0,27,79,113,0,27,79,115,0,96,96,97,97,102,102,103,103,105,105,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,91,90,0,27,91,63,55,104,0,27,91,63,55,108,0,27,79,70,0,27,79,77,0,27,91,51,59,50,126,0,27,91,49,59,50,70,0,27,91,49,59,50,72,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,49,59,50,80,0,27,91,49,59,50,81,0,27,91,49,59,50,82,0,27,91,49,59,50,83,0,27,91,49,53,59,50,126,0,27,91,49,55,59,50,126,0,27,91,49,56,59,50,126,0,27,91,49,57,59,50,126,0,27,91,50,48,59,50,126,0,27,91,50,49,59,50,126,0,27,91,50,51,59,50,126,0,27,91,50,52,59,50,126,0,27,91,49,59,53,80,0,27,91,49,59,53,81,0,27,91,49,59,53,82,0,27,91,49,59,53,83,0,27,91,49,53,59,53,126,0,27,91,49,55,59,53,126,0,27,91,49,56,59,53,126,0,27,91,49,57,59,53,126,0,27,91,50,48,59,53,126,0,27,91,50,49,59,53,126,0,27,91,50,51,59,53,126,0,27,91,50,52,59,53,126,0,27,91,49,59,54,80,0,27,91,49,59,54,81,0,27,91,49,59,54,82,0,27,91,49,59,54,83,0,27,91,49,53,59,54,126,0,27,91,49,55,59,54,126,0,27,91,49,56,59,54,126,0,27,91,49,57,59,54,126,0,27,91,50,48,59,54,126,0,27,91,50,49,59,54,126,0,27,91,50,51,59,54,126,0,27,91,50,52,59,54,126,0,27,91,49,59,51,80,0,27,91,49,59,51,81,0,27,91,49,59,51,82,0,27,91,49,59,51,83,0,27,91,49,53,59,51,126,0,27,91,49,55,59,51,126,0,27,91,49,56,59,51,126,0,27,91,49,57,59,51,126,0,27,91,50,48,59,51,126,0,27,91,50,49,59,51,126,0,27,91,50,51,59,51,126,0,27,91,50,52,59,51,126,0,27,91,49,59,52,80,0,27,91,49,59,52,81,0,27,91,49,59,52,82,0,27,91,49,75,0,27,91,63,54,57,108,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,37,91,59,48,49,50,51,52,53,54,55,56,57,93,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,93,49,48,52,7,0,27,93,52,59,37,112,49,37,100,59,114,103,98,58,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,27,92,0,27,91,51,109,0,27,91,50,51,109,0,27,91,60,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,63,54,57,104,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,115,0,27,108,0,27,109,0,0,2,0,0,0,74,0,-106,0,-84,3,1,1,0,0,7,0,19,0,24,0,42,0,48,0,58,0,90,0,97,0,104,0,111,0,118,0,125,0,-124,0,-117,0,-110,0,-103,0,-96,0,-89,0,-82,0,-75,0,-68,0,-61,0,-54,0,-47,0,-40,0,-33,0,-26,0,-19,0,-12,0,-5,0,2,1,9,1,16,1,23,1,30,1,37,1,44,1,51,1,58,1,65,1,72,1,79,1,86,1,93,1,100,1,107,1,114,1,121,1,-128,1,-121,1,-114,1,-107,1,-100,1,-93,1,-86,1,-79,1,-72,1,-65,1,-58,1,-54,1,-50,1,-46,1,-42,1,-38,1,-34,1,-30,1,-26,1,-22,1,-18,1,-14,1,-10,1,-4,1,1,2,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,32,0,37,0,42,0,47,0,52,0,56,0,61,0,66,0,71,0,76,0,81,0,87,0,93,0,99,0,105,0,111,0,117,0,123,0,-127,0,-121,0,-115,0,-110,0,-105,0,-100,0,-95,0,-90,0,-84,0,-78,0,-72,0,-66,0,-60,0,-54,0,-48,0,-42,0,-36,0,-30,0,-24,0,-18,0,-12,0,-6,0,0,1,6,1,12,1,18,1,24,1,30,1,34,1,39,1,44,1,49,1,54,1,59,1,63,1,67,1,71,1,75,1,79,1,85,1,91,1,97,1,103,1,109,1,115,1,121,1,126,1,-125,1,27,93,49,49,50,7,0,27,93,49,50,59,37,112,49,37,115,7,0,27,91,51,74,0,27,93,53,50,59,37,112,49,37,115,59,37,112,50,37,115,7,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,91,63,49,48,48,54,59,49,48,48,48,37,63,37,112,49,37,123,49,125,37,61,37,116,104,37,101,108,37,59,0,27,91,51,59,51,126,0,27,91,51,59,52,126,0,27,91,51,59,53,126,0,27,91,51,59,54,126,0,27,91,51,59,55,126,0,27,91,49,59,50,66,0,27,91,49,59,51,66,0,27,91,49,59,52,66,0,27,91,49,59,53,66,0,27,91,49,59,54,66,0,27,91,49,59,55,66,0,27,91,49,59,51,70,0,27,91,49,59,52,70,0,27,91,49,59,53,70,0,27,91,49,59,54,70,0,27,91,49,59,55,70,0,27,91,49,59,51,72,0,27,91,49,59,52,72,0,27,91,49,59,53,72,0,27,91,49,59,54,72,0,27,91,49,59,55,72,0,27,91,50,59,51,126,0,27,91,50,59,52,126,0,27,91,50,59,53,126,0,27,91,50,59,54,126,0,27,91,50,59,55,126,0,27,91,49,59,51,68,0,27,91,49,59,52,68,0,27,91,49,59,53,68,0,27,91,49,59,54,68,0,27,91,49,59,55,68,0,27,91,54,59,51,126,0,27,91,54,59,52,126,0,27,91,54,59,53,126,0,27,91,54,59,54,126,0,27,91,54,59,55,126,0,27,91,53,59,51,126,0,27,91,53,59,52,126,0,27,91,53,59,53,126,0,27,91,53,59,54,126,0,27,91,53,59,55,126,0,27,91,49,59,51,67,0,27,91,49,59,52,67,0,27,91,49,59,53,67,0,27,91,49,59,54,67,0,27,91,49,59,55,67,0,27,91,49,59,50,65,0,27,91,49,59,51,65,0,27,91,49,59,52,65,0,27,91,49,59,53,65,0,27,91,49,59,54,65,0,27,91,49,59,55,65,0,27,79,120,0,27,79,116,0,27,79,118,0,27,79,114,0,27,79,69,0,27,79,107,0,27,79,108,0,27,79,111,0,27,79,110,0,27,79,106,0,27,79,109,0,27,79,112,0,27,91,50,57,109,0,27,91,57,109,0,27,91,60,37,105,37,112,51,37,100,59,37,112,49,37,100,59,37,112,50,37,100,59,37,63,37,112,52,37,116,77,37,101,109,37,59,0,65,88,0,88,84,0,67,114,0,67,115,0,69,51,0,77,115,0,83,101,0,83,115,0,88,77,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,107,97,50,0,107,98,49,0,107,98,51,0,107,99,50,0,107,112,53,0,107,112,65,68,68,0,107,112,67,77,65,0,107,112,68,73,86,0,107,112,68,79,84,0,107,112,77,85,76,0,107,112,83,85,66,0,107,112,90,82,79,0,114,109,120,120,0,115,109,120,120,0,120,109,0
+ 30,2,37,0,38,0,15,0,-99,1,90,6,120,116,101,114,109,45,50,53,54,99,111,108,111,114,124,120,116,101,114,109,32,119,105,116,104,32,50,53,54,32,99,111,108,111,114,115,0,0,1,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,1,0,0,1,0,1,1,0,0,0,0,0,0,0,0,1,0,80,0,0,0,8,0,0,0,24,0,0,0,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,1,0,0,0,0,1,0,0,0,4,0,6,0,8,0,25,0,30,0,38,0,42,0,46,0,-1,-1,57,0,74,0,76,0,80,0,87,0,-1,-1,89,0,102,0,-1,-1,106,0,110,0,120,0,124,0,-1,-1,-1,-1,-128,0,-124,0,-119,0,-114,0,-1,-1,-96,0,-91,0,-86,0,-1,-1,-81,0,-76,0,-71,0,-66,0,-57,0,-53,0,-46,0,-1,-1,-28,0,-23,0,-17,0,-11,0,-1,-1,-1,-1,-1,-1,7,1,-1,-1,-1,-1,-1,-1,25,1,-1,-1,29,1,-1,-1,-1,-1,-1,-1,31,1,-1,-1,36,1,-1,-1,-1,-1,-1,-1,-1,-1,40,1,44,1,50,1,54,1,58,1,62,1,68,1,74,1,80,1,86,1,92,1,96,1,-1,-1,101,1,-1,-1,105,1,110,1,115,1,119,1,126,1,-1,-1,-123,1,-119,1,-111,1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-103,1,-94,1,-85,1,-1,-1,-82,1,-73,1,-64,1,-55,1,-46,1,-37,1,-28,1,-19,1,-10,1,-1,1,-1,-1,-1,-1,-1,-1,8,2,12,2,17,2,22,2,42,2,51,2,-1,-1,-1,-1,69,2,72,2,83,2,86,2,88,2,91,2,-72,2,-1,-1,-69,2,-1,-1,-1,-1,-1,-1,-1,-1,-67,2,-63,2,-59,2,-55,2,-51,2,-1,-1,-1,-1,-47,2,-1,-1,6,3,-1,-1,-1,-1,10,3,16,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,22,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,26,3,30,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,34,3,-1,-1,-1,-1,41,3,-1,-1,-1,-1,-1,-1,-1,-1,48,3,55,3,62,3,-1,-1,-1,-1,69,3,-1,-1,76,3,-1,-1,-1,-1,-1,-1,83,3,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,90,3,96,3,102,3,109,3,116,3,123,3,-126,3,-118,3,-110,3,-102,3,-94,3,-86,3,-78,3,-70,3,-62,3,-55,3,-48,3,-41,3,-34,3,-26,3,-18,3,-10,3,-2,3,6,4,14,4,22,4,30,4,37,4,44,4,51,4,58,4,66,4,74,4,82,4,90,4,98,4,106,4,114,4,122,4,-127,4,-120,4,-113,4,-106,4,-98,4,-90,4,-82,4,-74,4,-66,4,-58,4,-50,4,-42,4,-35,4,-28,4,-21,4,-16,4,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-9,4,2,5,7,5,26,5,30,5,39,5,46,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-116,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-111,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-105,5,-88,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-70,5,-1,-1,-1,-1,-1,-1,-66,5,-3,5,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,61,6,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,84,6,87,6,27,91,90,0,7,0,13,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,114,0,27,91,51,103,0,27,91,72,27,91,50,74,0,27,91,75,0,27,91,74,0,27,91,37,105,37,112,49,37,100,71,0,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,72,0,10,0,27,91,72,0,27,91,63,50,53,108,0,8,0,27,91,63,49,50,108,27,91,63,50,53,104,0,27,91,67,0,27,91,65,0,27,91,63,49,50,59,50,53,104,0,27,91,80,0,27,91,77,0,27,40,48,0,27,91,53,109,0,27,91,49,109,0,27,91,63,49,48,52,57,104,27,91,50,50,59,48,59,48,116,0,27,91,50,109,0,27,91,52,104,0,27,91,56,109,0,27,91,55,109,0,27,91,55,109,0,27,91,52,109,0,27,91,37,112,49,37,100,88,0,27,40,66,0,27,40,66,27,91,109,0,27,91,63,49,48,52,57,108,27,91,50,51,59,48,59,48,116,0,27,91,52,108,0,27,91,50,55,109,0,27,91,50,52,109,0,27,91,63,53,104,36,60,49,48,48,47,62,27,91,63,53,108,0,27,91,33,112,27,91,63,51,59,52,108,27,91,52,108,27,62,0,27,91,76,0,8,0,27,91,51,126,0,27,79,66,0,27,79,80,0,27,91,50,49,126,0,27,79,81,0,27,79,82,0,27,79,83,0,27,91,49,53,126,0,27,91,49,55,126,0,27,91,49,56,126,0,27,91,49,57,126,0,27,91,50,48,126,0,27,79,72,0,27,91,50,126,0,27,79,68,0,27,91,54,126,0,27,91,53,126,0,27,79,67,0,27,91,49,59,50,66,0,27,91,49,59,50,65,0,27,79,65,0,27,91,63,49,108,27,62,0,27,91,63,49,104,27,61,0,27,91,63,49,48,51,52,108,0,27,91,63,49,48,51,52,104,0,27,69,0,27,91,37,112,49,37,100,80,0,27,91,37,112,49,37,100,77,0,27,91,37,112,49,37,100,66,0,27,91,37,112,49,37,100,64,0,27,91,37,112,49,37,100,83,0,27,91,37,112,49,37,100,76,0,27,91,37,112,49,37,100,68,0,27,91,37,112,49,37,100,67,0,27,91,37,112,49,37,100,84,0,27,91,37,112,49,37,100,65,0,27,91,105,0,27,91,52,105,0,27,91,53,105,0,37,112,49,37,99,27,91,37,112,50,37,123,49,125,37,45,37,100,98,0,27,99,27,93,49,48,52,7,0,27,91,33,112,27,91,63,51,59,52,108,27,91,52,108,27,62,0,27,56,0,27,91,37,105,37,112,49,37,100,100,0,27,55,0,10,0,27,77,0,37,63,37,112,57,37,116,27,40,48,37,101,27,40,66,37,59,27,91,48,37,63,37,112,54,37,116,59,49,37,59,37,63,37,112,53,37,116,59,50,37,59,37,63,37,112,50,37,116,59,52,37,59,37,63,37,112,49,37,112,51,37,124,37,116,59,55,37,59,37,63,37,112,52,37,116,59,53,37,59,37,63,37,112,55,37,116,59,56,37,59,109,0,27,72,0,9,0,27,79,119,0,27,79,121,0,27,79,117,0,27,79,113,0,27,79,115,0,96,96,97,97,102,102,103,103,105,105,106,106,107,107,108,108,109,109,110,110,111,111,112,112,113,113,114,114,115,115,116,116,117,117,118,118,119,119,120,120,121,121,122,122,123,123,124,124,125,125,126,126,0,27,91,90,0,27,91,63,55,104,0,27,91,63,55,108,0,27,79,69,0,27,79,70,0,27,79,77,0,27,91,51,59,50,126,0,27,91,49,59,50,70,0,27,91,49,59,50,72,0,27,91,50,59,50,126,0,27,91,49,59,50,68,0,27,91,54,59,50,126,0,27,91,53,59,50,126,0,27,91,49,59,50,67,0,27,91,50,51,126,0,27,91,50,52,126,0,27,91,49,59,50,80,0,27,91,49,59,50,81,0,27,91,49,59,50,82,0,27,91,49,59,50,83,0,27,91,49,53,59,50,126,0,27,91,49,55,59,50,126,0,27,91,49,56,59,50,126,0,27,91,49,57,59,50,126,0,27,91,50,48,59,50,126,0,27,91,50,49,59,50,126,0,27,91,50,51,59,50,126,0,27,91,50,52,59,50,126,0,27,91,49,59,53,80,0,27,91,49,59,53,81,0,27,91,49,59,53,82,0,27,91,49,59,53,83,0,27,91,49,53,59,53,126,0,27,91,49,55,59,53,126,0,27,91,49,56,59,53,126,0,27,91,49,57,59,53,126,0,27,91,50,48,59,53,126,0,27,91,50,49,59,53,126,0,27,91,50,51,59,53,126,0,27,91,50,52,59,53,126,0,27,91,49,59,54,80,0,27,91,49,59,54,81,0,27,91,49,59,54,82,0,27,91,49,59,54,83,0,27,91,49,53,59,54,126,0,27,91,49,55,59,54,126,0,27,91,49,56,59,54,126,0,27,91,49,57,59,54,126,0,27,91,50,48,59,54,126,0,27,91,50,49,59,54,126,0,27,91,50,51,59,54,126,0,27,91,50,52,59,54,126,0,27,91,49,59,51,80,0,27,91,49,59,51,81,0,27,91,49,59,51,82,0,27,91,49,59,51,83,0,27,91,49,53,59,51,126,0,27,91,49,55,59,51,126,0,27,91,49,56,59,51,126,0,27,91,49,57,59,51,126,0,27,91,50,48,59,51,126,0,27,91,50,49,59,51,126,0,27,91,50,51,59,51,126,0,27,91,50,52,59,51,126,0,27,91,49,59,52,80,0,27,91,49,59,52,81,0,27,91,49,59,52,82,0,27,91,49,75,0,27,91,63,54,57,108,0,27,91,37,105,37,100,59,37,100,82,0,27,91,54,110,0,27,91,63,37,91,59,48,49,50,51,52,53,54,55,56,57,93,99,0,27,91,99,0,27,91,51,57,59,52,57,109,0,27,93,49,48,52,7,0,27,93,52,59,37,112,49,37,100,59,114,103,98,58,37,112,50,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,51,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,47,37,112,52,37,123,50,53,53,125,37,42,37,123,49,48,48,48,125,37,47,37,50,46,50,88,27,92,0,27,91,51,109,0,27,91,50,51,109,0,27,91,63,54,57,104,27,91,37,105,37,112,49,37,100,115,0,27,91,63,54,57,104,27,91,37,105,59,37,112,49,37,100,115,0,27,91,60,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,51,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,57,37,112,49,37,123,56,125,37,45,37,100,37,101,51,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,37,63,37,112,49,37,123,56,125,37,60,37,116,52,37,112,49,37,100,37,101,37,112,49,37,123,49,54,125,37,60,37,116,49,48,37,112,49,37,123,56,125,37,45,37,100,37,101,52,56,59,53,59,37,112,49,37,100,37,59,109,0,27,91,63,54,57,104,27,91,37,105,37,112,49,37,100,59,37,112,50,37,100,115,0,27,108,0,27,109,0,3,0,0,0,86,0,-81,0,83,4,1,1,1,0,0,0,9,0,18,0,25,0,37,0,42,0,60,0,67,0,74,0,79,0,85,0,95,0,127,0,-123,0,-114,0,-105,0,-98,0,-91,0,-84,0,-77,0,-70,0,-63,0,-56,0,-49,0,-42,0,-35,0,-28,0,-21,0,-14,0,-7,0,0,1,7,1,14,1,21,1,28,1,35,1,42,1,49,1,56,1,63,1,70,1,77,1,84,1,91,1,98,1,105,1,112,1,119,1,126,1,-123,1,-116,1,-109,1,-102,1,-95,1,-88,1,-81,1,-74,1,-67,1,-60,1,-53,1,-46,1,-39,1,-32,1,-25,1,-18,1,-11,1,-4,1,3,2,7,2,11,2,15,2,19,2,23,2,27,2,31,2,35,2,39,2,43,2,47,2,51,2,55,2,59,2,65,2,90,2,95,2,-124,2,0,0,3,0,6,0,9,0,12,0,15,0,18,0,21,0,24,0,27,0,30,0,33,0,36,0,39,0,42,0,45,0,48,0,51,0,54,0,59,0,64,0,69,0,74,0,79,0,83,0,88,0,93,0,98,0,103,0,108,0,114,0,120,0,126,0,-124,0,-118,0,-112,0,-106,0,-100,0,-94,0,-88,0,-83,0,-78,0,-73,0,-68,0,-63,0,-57,0,-51,0,-45,0,-39,0,-33,0,-27,0,-21,0,-15,0,-9,0,-3,0,3,1,9,1,15,1,21,1,27,1,33,1,39,1,45,1,51,1,57,1,61,1,66,1,71,1,76,1,81,1,86,1,90,1,94,1,98,1,102,1,106,1,112,1,118,1,124,1,-126,1,-120,1,-114,1,-108,1,-103,1,-97,1,-92,1,-89,1,-84,1,-81,1,27,91,63,50,48,48,52,108,0,27,91,63,50,48,48,52,104,0,27,93,49,49,50,7,0,27,93,49,50,59,37,112,49,37,115,7,0,27,91,51,74,0,27,93,53,50,59,37,112,49,37,115,59,37,112,50,37,115,7,0,27,91,50,48,49,126,0,27,91,50,48,48,126,0,27,91,62,99,0,27,91,50,32,113,0,27,91,37,112,49,37,100,32,113,0,27,91,63,49,48,48,54,59,49,48,48,48,37,63,37,112,49,37,123,49,125,37,61,37,116,104,37,101,108,37,59,0,27,91,62,48,113,0,27,91,63,49,48,48,52,108,0,27,91,63,49,48,48,52,104,0,27,91,51,59,51,126,0,27,91,51,59,52,126,0,27,91,51,59,53,126,0,27,91,51,59,54,126,0,27,91,51,59,55,126,0,27,91,49,59,50,66,0,27,91,49,59,51,66,0,27,91,49,59,52,66,0,27,91,49,59,53,66,0,27,91,49,59,54,66,0,27,91,49,59,55,66,0,27,91,49,59,51,70,0,27,91,49,59,52,70,0,27,91,49,59,53,70,0,27,91,49,59,54,70,0,27,91,49,59,55,70,0,27,91,49,59,51,72,0,27,91,49,59,52,72,0,27,91,49,59,53,72,0,27,91,49,59,54,72,0,27,91,49,59,55,72,0,27,91,50,59,51,126,0,27,91,50,59,52,126,0,27,91,50,59,53,126,0,27,91,50,59,54,126,0,27,91,50,59,55,126,0,27,91,49,59,51,68,0,27,91,49,59,52,68,0,27,91,49,59,53,68,0,27,91,49,59,54,68,0,27,91,49,59,55,68,0,27,91,54,59,51,126,0,27,91,54,59,52,126,0,27,91,54,59,53,126,0,27,91,54,59,54,126,0,27,91,54,59,55,126,0,27,91,53,59,51,126,0,27,91,53,59,52,126,0,27,91,53,59,53,126,0,27,91,53,59,54,126,0,27,91,53,59,55,126,0,27,91,49,59,51,67,0,27,91,49,59,52,67,0,27,91,49,59,53,67,0,27,91,49,59,54,67,0,27,91,49,59,55,67,0,27,91,49,59,50,65,0,27,91,49,59,51,65,0,27,91,49,59,52,65,0,27,91,49,59,53,65,0,27,91,49,59,54,65,0,27,91,49,59,55,65,0,27,79,120,0,27,79,116,0,27,79,118,0,27,79,114,0,27,79,69,0,27,79,107,0,27,79,108,0,27,79,111,0,27,79,110,0,27,79,106,0,27,79,109,0,27,79,112,0,27,91,73,0,27,91,79,0,27,91,50,57,109,0,27,92,91,52,49,59,91,49,45,54,93,91,48,45,57,93,91,48,45,57,93,59,48,99,0,27,91,57,109,0,27,91,60,37,105,37,112,51,37,100,59,37,112,49,37,100,59,37,112,50,37,100,59,37,63,37,112,52,37,116,77,37,101,109,37,59,0,27,80,62,92,124,88,84,101,114,109,92,40,91,49,45,57,93,91,48,45,57,93,43,92,41,27,92,92,0,65,88,0,88,70,0,88,84,0,66,68,0,66,69,0,67,114,0,67,115,0,69,51,0,77,115,0,80,69,0,80,83,0,82,86,0,83,101,0,83,115,0,88,77,0,88,82,0,102,100,0,102,101,0,107,68,67,51,0,107,68,67,52,0,107,68,67,53,0,107,68,67,54,0,107,68,67,55,0,107,68,78,0,107,68,78,51,0,107,68,78,52,0,107,68,78,53,0,107,68,78,54,0,107,68,78,55,0,107,69,78,68,51,0,107,69,78,68,52,0,107,69,78,68,53,0,107,69,78,68,54,0,107,69,78,68,55,0,107,72,79,77,51,0,107,72,79,77,52,0,107,72,79,77,53,0,107,72,79,77,54,0,107,72,79,77,55,0,107,73,67,51,0,107,73,67,52,0,107,73,67,53,0,107,73,67,54,0,107,73,67,55,0,107,76,70,84,51,0,107,76,70,84,52,0,107,76,70,84,53,0,107,76,70,84,54,0,107,76,70,84,55,0,107,78,88,84,51,0,107,78,88,84,52,0,107,78,88,84,53,0,107,78,88,84,54,0,107,78,88,84,55,0,107,80,82,86,51,0,107,80,82,86,52,0,107,80,82,86,53,0,107,80,82,86,54,0,107,80,82,86,55,0,107,82,73,84,51,0,107,82,73,84,52,0,107,82,73,84,53,0,107,82,73,84,54,0,107,82,73,84,55,0,107,85,80,0,107,85,80,51,0,107,85,80,52,0,107,85,80,53,0,107,85,80,54,0,107,85,80,55,0,107,97,50,0,107,98,49,0,107,98,51,0,107,99,50,0,107,112,53,0,107,112,65,68,68,0,107,112,67,77,65,0,107,112,68,73,86,0,107,112,68,79,84,0,107,112,77,85,76,0,107,112,83,85,66,0,107,112,90,82,79,0,107,120,73,78,0,107,120,79,85,84,0,114,109,120,120,0,114,118,0,115,109,120,120,0,120,109,0,120,114,0
};
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index 197bbcabb5..7fae34d33f 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -3,6 +3,7 @@
#include <assert.h>
#include <signal.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -15,37 +16,37 @@
#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/cursor_shape.h"
+#include "nvim/event/defs.h"
#include "nvim/event/loop.h"
#include "nvim/event/signal.h"
#include "nvim/event/stream.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/highlight_defs.h"
#include "nvim/log.h"
#include "nvim/macros_defs.h"
#include "nvim/main.h"
+#include "nvim/map_defs.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
#include "nvim/msgpack_rpc/channel.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
+#include "nvim/os/os_defs.h"
+#include "nvim/strings.h"
#include "nvim/tui/input.h"
#include "nvim/tui/terminfo.h"
#include "nvim/tui/tui.h"
#include "nvim/types_defs.h"
#include "nvim/ugrid.h"
-#include "nvim/ui.h"
#include "nvim/ui_client.h"
+#include "nvim/ui_defs.h"
#ifdef MSWIN
# include "nvim/os/os_win_console.h"
-# include "nvim/os/tty.h"
#endif
-// Space reserved in two output buffers to make the cursor normal or invisible
-// when flushing. No existing terminal will require 32 bytes to do that.
-#define CNORM_COMMAND_MAX_SIZE 32
#define OUTBUF_SIZE 0xffff
#define TOO_MANY_EVENTS 1000000
@@ -78,7 +79,7 @@ struct TUIData {
TermInput input;
uv_loop_t write_loop;
unibi_term *ut;
- char *term; // value of $TERM
+ char *term; ///< value of $TERM
union {
uv_tty_t tty;
uv_pipe_t pipe;
@@ -136,11 +137,14 @@ struct TUIData {
int sync;
} unibi_ext;
char *space_buf;
+ size_t space_buf_len;
bool stopped;
int seen_error_exit;
int width;
int height;
bool rgb;
+ int url; ///< Index of URL currently being printed, if any
+ StringBuilder urlbuf; ///< Re-usable buffer for writing OSC 8 control sequences
};
static int got_winch = 0;
@@ -149,7 +153,10 @@ static bool cursor_style_enabled = false;
# include "tui/tui.c.generated.h"
#endif
-void tui_start(TUIData **tui_p, int *width, int *height, char **term)
+static Set(cstr_t) urls = SET_INIT;
+
+void tui_start(TUIData **tui_p, int *width, int *height, char **term, bool *rgb)
+ FUNC_ATTR_NONNULL_ALL
{
TUIData *tui = xcalloc(1, sizeof(TUIData));
tui->is_starting = true;
@@ -157,7 +164,9 @@ void tui_start(TUIData **tui_p, int *width, int *height, char **term)
tui->stopped = false;
tui->seen_error_exit = 0;
tui->loop = &main_loop;
+ tui->url = -1;
kv_init(tui->invalid_regions);
+ kv_init(tui->urlbuf);
signal_watcher_init(tui->loop, &tui->winch_handle, tui);
// TODO(bfredl): zero hl is empty, send this explicitly?
@@ -170,14 +179,14 @@ void tui_start(TUIData **tui_p, int *width, int *height, char **term)
uv_timer_init(&tui->loop->uv, &tui->startup_delay_timer);
tui->startup_delay_timer.data = tui;
- uv_timer_start(&tui->startup_delay_timer, after_startup_cb,
- 100, 0);
+ uv_timer_start(&tui->startup_delay_timer, after_startup_cb, 100, 0);
*tui_p = tui;
loop_poll_events(&main_loop, 1);
*width = tui->width;
*height = tui->height;
*term = tui->term;
+ *rgb = tui->rgb;
}
void tui_set_key_encoding(TUIData *tui)
@@ -261,6 +270,10 @@ static void tui_query_kitty_keyboard(TUIData *tui)
out(tui, S_LEN("\x1b[?u\x1b[c"));
}
+/// Enable the alternate screen and emit other control sequences to start the TUI.
+///
+/// This is also called when the TUI is resumed after being suspended. We reinitialize all state
+/// from terminfo just in case the controlling terminal has changed (#27177).
static void terminfo_start(TUIData *tui)
{
tui->scroll_region_is_full_screen = true;
@@ -335,6 +348,9 @@ static void terminfo_start(TUIData *tui)
int konsolev = konsolev_env ? (int)strtol(konsolev_env, NULL, 10)
: (konsole ? 1 : 0);
+ // truecolor support must be checked before patching/augmenting terminfo
+ tui->rgb = term_has_truecolor(tui, colorterm);
+
patch_terminfo_bugs(tui, term, colorterm, vtev, konsolev, iterm_env, nsterm);
augment_terminfo(tui, term, vtev, konsolev, iterm_env, nsterm);
tui->can_change_scroll_region =
@@ -407,10 +423,11 @@ static void terminfo_start(TUIData *tui)
flush_buf(tui);
}
+/// Disable the alternate screen and prepare for the TUI to close.
static void terminfo_stop(TUIData *tui)
{
// Destroy output stuff
- tui_mode_change(tui, (String)STRING_INIT, SHAPE_IDX_N);
+ tui_mode_change(tui, NULL_STRING, SHAPE_IDX_N);
tui_mouse_off(tui);
unibi_out(tui, unibi_exit_attribute_mode);
// Reset cursor to normal before exiting alternate screen.
@@ -421,7 +438,7 @@ static void terminfo_stop(TUIData *tui)
tui_reset_key_encoding(tui);
// May restore old title before exiting alternate screen.
- tui_set_title(tui, (String)STRING_INIT);
+ tui_set_title(tui, NULL_STRING);
if (ui_client_exit_status == 0) {
ui_client_exit_status = tui->seen_error_exit;
}
@@ -478,7 +495,7 @@ static void tui_terminal_after_startup(TUIData *tui)
flush_buf(tui);
}
-/// stop the terminal but allow it to restart later (like after suspend)
+/// Stop the terminal but allow it to restart later (like after suspend)
static void tui_terminal_stop(TUIData *tui)
{
if (uv_is_closing((uv_handle_t *)&tui->output_handle)) {
@@ -520,7 +537,15 @@ void tui_free_all_mem(TUIData *tui)
{
ugrid_free(&tui->grid);
kv_destroy(tui->invalid_regions);
+
+ const char *url;
+ set_foreach(&urls, url, {
+ xfree((void *)url);
+ });
+ set_destroy(cstr_t, &urls);
+
kv_destroy(tui->attrs);
+ kv_destroy(tui->urlbuf);
xfree(tui->space_buf);
xfree(tui->term);
xfree(tui);
@@ -548,6 +573,10 @@ static bool attrs_differ(TUIData *tui, int id1, int id2, bool rgb)
HlAttrs a1 = kv_A(tui->attrs, (size_t)id1);
HlAttrs a2 = kv_A(tui->attrs, (size_t)id2);
+ if (a1.url != a2.url) {
+ return true;
+ }
+
if (rgb) {
return a1.rgb_fg_color != a2.rgb_fg_color
|| a1.rgb_bg_color != a2.rgb_bg_color
@@ -707,6 +736,19 @@ static void update_attrs(TUIData *tui, int attr_id)
}
}
+ if (tui->url != attrs.url) {
+ if (attrs.url >= 0) {
+ const char *url = urls.keys[attrs.url];
+ kv_size(tui->urlbuf) = 0;
+ kv_printf(tui->urlbuf, "\x1b]8;;%s\x1b\\", url);
+ out(tui, tui->urlbuf.items, kv_size(tui->urlbuf));
+ } else {
+ out(tui, S_LEN("\x1b]8;;\x1b\\"));
+ }
+
+ tui->url = attrs.url;
+ }
+
tui->default_attr = fg == -1 && bg == -1
&& !bold && !italic && !has_any_underline && !reverse && !standout
&& !strikethrough;
@@ -783,6 +825,13 @@ static void cursor_goto(TUIData *tui, int row, int col)
if (row == grid->row && col == grid->col) {
return;
}
+
+ // If an OSC 8 sequence is active terminate it before moving the cursor
+ if (tui->url >= 0) {
+ out(tui, S_LEN("\x1b]8;;\x1b\\"));
+ tui->url = -1;
+ }
+
if (0 == row && 0 == col) {
unibi_out(tui, unibi_cursor_home);
ugrid_goto(grid, row, col);
@@ -1007,10 +1056,7 @@ void tui_grid_resize(TUIData *tui, Integer g, Integer width, Integer height)
{
UGrid *grid = &tui->grid;
ugrid_resize(grid, (int)width, (int)height);
-
- xfree(tui->space_buf);
- tui->space_buf = xmalloc((size_t)width * sizeof(*tui->space_buf));
- memset(tui->space_buf, ' ', (size_t)width);
+ ensure_space_buf_size(tui, (size_t)width);
// resize might not always be followed by a clear before flush
// so clip the invalid region
@@ -1222,8 +1268,10 @@ void tui_grid_scroll(TUIData *tui, Integer g, Integer startrow, Integer endrow,
Integer endcol, Integer rows, Integer cols FUNC_ATTR_UNUSED)
{
UGrid *grid = &tui->grid;
- int top = (int)startrow, bot = (int)endrow - 1;
- int left = (int)startcol, right = (int)endcol - 1;
+ int top = (int)startrow;
+ int bot = (int)endrow - 1;
+ int left = (int)startcol;
+ int right = (int)endcol - 1;
bool fullwidth = left == 0 && right == tui->width - 1;
tui->scroll_region_is_full_screen = fullwidth
@@ -1277,11 +1325,32 @@ void tui_grid_scroll(TUIData *tui, Integer g, Integer startrow, Integer endrow,
}
}
+/// Add a URL to be used in an OSC 8 hyperlink.
+///
+/// @param tui TUIData
+/// @param url URL to add
+/// @return Index of new URL, or -1 if URL is invalid
+int32_t tui_add_url(TUIData *tui, const char *url)
+ FUNC_ATTR_NONNULL_ARG(1)
+{
+ if (url == NULL) {
+ return -1;
+ }
+
+ MHPutStatus status;
+ uint32_t k = set_put_idx(cstr_t, &urls, url, &status);
+ if (status != kMHExisting) {
+ urls.keys[k] = xstrdup(url);
+ }
+ return (int32_t)k;
+}
+
void tui_hl_attr_define(TUIData *tui, Integer id, HlAttrs attrs, HlAttrs cterm_attrs, Array info)
{
attrs.cterm_ae_attr = cterm_attrs.cterm_ae_attr;
attrs.cterm_fg_color = cterm_attrs.cterm_fg_color;
attrs.cterm_bg_color = cterm_attrs.cterm_bg_color;
+
kv_a(tui->attrs, (size_t)id) = attrs;
}
@@ -1298,49 +1367,19 @@ void tui_visual_bell(TUIData *tui)
void tui_default_colors_set(TUIData *tui, Integer rgb_fg, Integer rgb_bg, Integer rgb_sp,
Integer cterm_fg, Integer cterm_bg)
{
- tui->clear_attrs.rgb_fg_color = (int)rgb_fg;
- tui->clear_attrs.rgb_bg_color = (int)rgb_bg;
- tui->clear_attrs.rgb_sp_color = (int)rgb_sp;
- tui->clear_attrs.cterm_fg_color = (int)cterm_fg;
- tui->clear_attrs.cterm_bg_color = (int)cterm_bg;
+ tui->clear_attrs.rgb_fg_color = (RgbValue)rgb_fg;
+ tui->clear_attrs.rgb_bg_color = (RgbValue)rgb_bg;
+ tui->clear_attrs.rgb_sp_color = (RgbValue)rgb_sp;
+ tui->clear_attrs.cterm_fg_color = (int16_t)cterm_fg;
+ tui->clear_attrs.cterm_bg_color = (int16_t)cterm_bg;
tui->print_attr_id = -1;
invalidate(tui, 0, tui->grid.height, 0, tui->grid.width);
}
-/// Begin flushing the TUI. If 'termsync' is set and the terminal supports synchronized updates,
-/// begin a synchronized update. Otherwise, hide the cursor to avoid cursor jumping.
-static void tui_flush_start(TUIData *tui)
- FUNC_ATTR_NONNULL_ALL
-{
- if (tui->sync_output && tui->unibi_ext.sync != -1) {
- UNIBI_SET_NUM_VAR(tui->params[0], 1);
- unibi_out_ext(tui, tui->unibi_ext.sync);
- } else if (!tui->is_invisible) {
- unibi_out(tui, unibi_cursor_invisible);
- tui->is_invisible = true;
- }
-}
-
-/// Finish flushing the TUI. If 'termsync' is set and the terminal supports synchronized updates,
-/// end a synchronized update. Otherwise, make the cursor visible again.
-static void tui_flush_end(TUIData *tui)
- FUNC_ATTR_NONNULL_ALL
-{
- if (tui->sync_output && tui->unibi_ext.sync != -1) {
- UNIBI_SET_NUM_VAR(tui->params[0], 0);
- unibi_out_ext(tui, tui->unibi_ext.sync);
- }
- bool should_invisible = tui->busy || tui->want_invisible;
- if (tui->is_invisible && !should_invisible) {
- unibi_out(tui, unibi_cursor_normal);
- tui->is_invisible = false;
- } else if (!tui->is_invisible && should_invisible) {
- unibi_out(tui, unibi_cursor_invisible);
- tui->is_invisible = true;
- }
-}
-
+/// Flushes TUI grid state to a buffer (which is later flushed to the TTY by `flush_buf`).
+///
+/// @see flush_buf
void tui_flush(TUIData *tui)
{
UGrid *grid = &tui->grid;
@@ -1357,8 +1396,6 @@ void tui_flush(TUIData *tui)
tui_busy_stop(tui); // avoid hidden cursor
}
- tui_flush_start(tui);
-
while (kv_size(tui->invalid_regions)) {
Rect r = kv_pop(tui->invalid_regions);
assert(r.bot <= grid->height && r.right <= grid->width);
@@ -1386,8 +1423,6 @@ void tui_flush(TUIData *tui)
cursor_goto(tui, tui->row, tui->col);
- tui_flush_end(tui);
-
flush_buf(tui);
}
@@ -1399,28 +1434,28 @@ static void show_verbose_terminfo(TUIData *tui)
abort();
}
- Array chunks = ARRAY_DICT_INIT;
- Array title = ARRAY_DICT_INIT;
- 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;
+ MAXSIZE_TEMP_ARRAY(chunks, 3);
+ MAXSIZE_TEMP_ARRAY(title, 2);
+ ADD_C(title, CSTR_AS_OBJ("\n\n--- Terminal info --- {{{\n"));
+ ADD_C(title, CSTR_AS_OBJ("Title"));
+ ADD_C(chunks, ARRAY_OBJ(title));
+ MAXSIZE_TEMP_ARRAY(info, 2);
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, CSTR_TO_OBJ("}}}\n"));
- ADD(end_fold, CSTR_TO_OBJ("Title"));
- ADD(chunks, ARRAY_OBJ(end_fold));
-
- Array args = ARRAY_DICT_INIT;
- ADD(args, ARRAY_OBJ(chunks));
- ADD(args, BOOLEAN_OBJ(true)); // history
- Dictionary opts = ARRAY_DICT_INIT;
- PUT(opts, "verbose", BOOLEAN_OBJ(true));
- ADD(args, DICTIONARY_OBJ(opts));
+ ADD_C(info, STRING_OBJ(str));
+ ADD_C(chunks, ARRAY_OBJ(info));
+ MAXSIZE_TEMP_ARRAY(end_fold, 2);
+ ADD_C(end_fold, CSTR_AS_OBJ("}}}\n"));
+ ADD_C(end_fold, CSTR_AS_OBJ("Title"));
+ ADD_C(chunks, ARRAY_OBJ(end_fold));
+
+ MAXSIZE_TEMP_ARRAY(args, 3);
+ ADD_C(args, ARRAY_OBJ(chunks));
+ ADD_C(args, BOOLEAN_OBJ(true)); // history
+ MAXSIZE_TEMP_DICT(opts, 1);
+ PUT_C(opts, "verbose", BOOLEAN_OBJ(true));
+ ADD_C(args, DICTIONARY_OBJ(opts));
rpc_send_event(ui_client_channel_id, "nvim_echo", args);
- api_free_array(args);
+ xfree(str.data);
}
void tui_suspend(TUIData *tui)
@@ -1440,7 +1475,7 @@ void tui_suspend(TUIData *tui)
tui_mouse_on(tui);
}
stream_set_blocking(tui->input.in_fd, false); // libuv expects this
- ui_client_attach(tui->width, tui->height, tui->term);
+ ui_client_attach(tui->width, tui->height, tui->term, tui->rgb);
#endif
}
@@ -1530,6 +1565,14 @@ void tui_option_set(TUIData *tui, String name, Object value)
}
}
+void tui_chdir(TUIData *tui, String path)
+{
+ int err = uv_chdir(path.data);
+ if (err != 0) {
+ ELOG("Failed to chdir to %s: %s", path.data, strerror(err));
+ }
+}
+
void tui_raw_line(TUIData *tui, Integer g, Integer linerow, Integer startcol, Integer endcol,
Integer clearcol, Integer clearattr, LineFlags flags, const schar_T *chunk,
const sattr_T *attrs)
@@ -1597,11 +1640,21 @@ static void invalidate(TUIData *tui, int top, int bot, int left, int right)
}
}
+static void ensure_space_buf_size(TUIData *tui, size_t len)
+{
+ if (len > tui->space_buf_len) {
+ tui->space_buf = xrealloc(tui->space_buf, len * sizeof *tui->space_buf);
+ memset(tui->space_buf + tui->space_buf_len, ' ', len - tui->space_buf_len);
+ tui->space_buf_len = len;
+ }
+}
+
/// Tries to get the user's wanted dimensions (columns and rows) for the entire
/// application (i.e., the host terminal).
void tui_guess_size(TUIData *tui)
{
- int width = 0, height = 0;
+ int width = 0;
+ int height = 0;
// 1 - try from a system call(ioctl/TIOCGWINSZ on unix)
if (tui->out_isatty
@@ -1632,6 +1685,7 @@ void tui_guess_size(TUIData *tui)
tui->width = width;
tui->height = height;
+ ensure_space_buf_size(tui, (size_t)tui->width);
// Redraw on SIGWINCH event if size didn't change. #23411
ui_client_set_size(width, height);
@@ -1753,6 +1807,44 @@ static int unibi_find_ext_bool(unibi_term *ut, const char *name)
return -1;
}
+/// Determine if the terminal supports truecolor or not:
+///
+/// 1. If $COLORTERM is "24bit" or "truecolor", return true
+/// 2. Else, check terminfo for Tc, RGB, setrgbf, or setrgbb capabilities. If
+/// found, return true
+/// 3. Else, return false
+static bool term_has_truecolor(TUIData *tui, const char *colorterm)
+{
+ // Check $COLORTERM
+ if (strequal(colorterm, "truecolor") || strequal(colorterm, "24bit")) {
+ return true;
+ }
+
+ // Check for Tc and RGB
+ for (size_t i = 0; i < unibi_count_ext_bool(tui->ut); i++) {
+ const char *n = unibi_get_ext_bool_name(tui->ut, i);
+ if (n && (!strcmp(n, "Tc") || !strcmp(n, "RGB"))) {
+ return true;
+ }
+ }
+
+ // Check for setrgbf and setrgbb
+ bool setrgbf = false;
+ bool setrgbb = false;
+ for (size_t i = 0; i < unibi_count_ext_str(tui->ut) && (!setrgbf || !setrgbb); i++) {
+ const char *n = unibi_get_ext_str_name(tui->ut, i);
+ if (n) {
+ if (!setrgbf && !strcmp(n, "setrgbf")) {
+ setrgbf = true;
+ } else if (!setrgbb && !strcmp(n, "setrgbb")) {
+ setrgbb = true;
+ }
+ }
+ }
+
+ return setrgbf && setrgbb;
+}
+
/// Patches the terminfo records after loading from system or built-in db.
/// Several entries in terminfo are known to be deficient or outright wrong;
/// and several terminal emulators falsely announce incorrect terminal types.
@@ -2254,23 +2346,103 @@ static void augment_terminfo(TUIData *tui, const char *term, int vte_version, in
}
}
+static bool should_invisible(TUIData *tui)
+{
+ return tui->busy || tui->want_invisible;
+}
+
+/// Write the sequence to begin flushing output to `buf`.
+/// If 'termsync' is set and the terminal supports synchronized output, begin synchronized update.
+/// Otherwise, hide the cursor to avoid cursor jumping.
+///
+/// @param buf the buffer to write the sequence to
+/// @param len the length of `buf`
+static size_t flush_buf_start(TUIData *tui, char *buf, size_t len)
+ FUNC_ATTR_NONNULL_ALL
+{
+ unibi_var_t params[9]; // Don't use tui->params[] as they may already be in use.
+
+ const char *str = NULL;
+ if (tui->sync_output && tui->unibi_ext.sync != -1) {
+ UNIBI_SET_NUM_VAR(params[0], 1);
+ str = unibi_get_ext_str(tui->ut, (size_t)tui->unibi_ext.sync);
+ } else if (!tui->is_invisible) {
+ str = unibi_get_str(tui->ut, unibi_cursor_invisible);
+ tui->is_invisible = true;
+ }
+
+ if (str == NULL) {
+ return 0;
+ }
+
+ return unibi_run(str, params, buf, len);
+}
+
+/// Write the sequence to end flushing output to `buf`.
+/// If 'termsync' is set and the terminal supports synchronized output, end synchronized update.
+/// Otherwise, make the cursor visible again.
+///
+/// @param buf the buffer to write the sequence to
+/// @param len the length of `buf`
+static size_t flush_buf_end(TUIData *tui, char *buf, size_t len)
+ FUNC_ATTR_NONNULL_ALL
+{
+ unibi_var_t params[9]; // Don't use tui->params[] as they may already be in use.
+
+ size_t offset = 0;
+ if (tui->sync_output && tui->unibi_ext.sync != -1) {
+ UNIBI_SET_NUM_VAR(params[0], 0);
+ const char *str = unibi_get_ext_str(tui->ut, (size_t)tui->unibi_ext.sync);
+ offset = unibi_run(str, params, buf, len);
+ }
+
+ const char *str = NULL;
+ if (tui->is_invisible && !should_invisible(tui)) {
+ str = unibi_get_str(tui->ut, unibi_cursor_normal);
+ tui->is_invisible = false;
+ } else if (!tui->is_invisible && should_invisible(tui)) {
+ str = unibi_get_str(tui->ut, unibi_cursor_invisible);
+ tui->is_invisible = true;
+ }
+
+ if (str != NULL) {
+ assert(len >= offset);
+ offset += unibi_run(str, params, buf + offset, len - offset);
+ }
+
+ return offset;
+}
+
+/// Flushes the rendered buffer to the TTY.
+///
+/// @see tui_flush
static void flush_buf(TUIData *tui)
{
uv_write_t req;
- uv_buf_t buf;
+ uv_buf_t bufs[3];
+ char pre[32];
+ char post[32];
- if (tui->bufpos <= 0) {
+ if (tui->bufpos <= 0 && tui->is_invisible == should_invisible(tui)) {
return;
}
- buf.base = tui->buf;
- buf.len = UV_BUF_LEN(tui->bufpos);
+ bufs[0].base = pre;
+ bufs[0].len = UV_BUF_LEN(flush_buf_start(tui, pre, sizeof(pre)));
+
+ bufs[1].base = tui->buf;
+ bufs[1].len = UV_BUF_LEN(tui->bufpos);
+
+ bufs[2].base = post;
+ bufs[2].len = UV_BUF_LEN(flush_buf_end(tui, post, sizeof(post)));
if (tui->screenshot) {
- fwrite(buf.base, buf.len, 1, tui->screenshot);
+ for (size_t i = 0; i < ARRAY_SIZE(bufs); i++) {
+ fwrite(bufs[i].base, bufs[i].len, 1, tui->screenshot);
+ }
} else {
int ret
- = uv_write(&req, (uv_stream_t *)&tui->output_handle, &buf, 1, NULL);
+ = uv_write(&req, (uv_stream_t *)&tui->output_handle, bufs, ARRAY_SIZE(bufs), NULL);
if (ret) {
ELOG("uv_write failed: %s", uv_strerror(ret));
}
diff --git a/src/nvim/tui/tui.h b/src/nvim/tui/tui.h
index 8eb4ac9bd8..12e0491b4b 100644
--- a/src/nvim/tui/tui.h
+++ b/src/nvim/tui/tui.h
@@ -1,23 +1,8 @@
#pragma once
-#include "nvim/api/private/defs.h" // IWYU pragma: keep
#include "nvim/highlight_defs.h" // IWYU pragma: keep
-#include "nvim/types_defs.h" // IWYU pragma: keep
-#include "nvim/ui.h"
-
-typedef struct TUIData TUIData;
-
-typedef enum {
- kTermModeSynchronizedOutput = 2026,
-} TermMode;
-
-typedef enum {
- kTermModeNotRecognized = 0,
- kTermModeSet = 1,
- kTermModeReset = 2,
- kTermModePermanentlySet = 3,
- kTermModePermanentlyReset = 4,
-} TermModeState;
+#include "nvim/tui/tui_defs.h" // IWYU pragma: keep
+#include "nvim/ui_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "tui/tui.h.generated.h"
diff --git a/src/nvim/tui/tui_defs.h b/src/nvim/tui/tui_defs.h
new file mode 100644
index 0000000000..c5149d4829
--- /dev/null
+++ b/src/nvim/tui/tui_defs.h
@@ -0,0 +1,15 @@
+#pragma once
+
+typedef struct TUIData TUIData;
+
+typedef enum {
+ kTermModeSynchronizedOutput = 2026,
+} TermMode;
+
+typedef enum {
+ kTermModeNotRecognized = 0,
+ kTermModeSet = 1,
+ kTermModeReset = 2,
+ kTermModePermanentlySet = 3,
+ kTermModePermanentlyReset = 4,
+} TermModeState;
diff --git a/src/nvim/types_defs.h b/src/nvim/types_defs.h
index c06737abb5..934159b9d9 100644
--- a/src/nvim/types_defs.h
+++ b/src/nvim/types_defs.h
@@ -1,6 +1,5 @@
#pragma once
-#include <stdbool.h>
#include <stdint.h>
// dummy to pass an ACL to a function
@@ -48,3 +47,12 @@ typedef enum {
#define TRISTATE_FROM_INT(val) ((val) == 0 ? kFalse : ((val) >= 1 ? kTrue : kNone))
typedef int64_t OptInt;
+
+enum { SIGN_WIDTH = 2, }; ///< Number of display cells for a sign in the signcolumn
+
+typedef struct file_buffer buf_T;
+typedef struct loop Loop;
+typedef struct regprog regprog_T;
+typedef struct syn_state synstate_T;
+typedef struct terminal Terminal;
+typedef struct window_S win_T;
diff --git a/src/nvim/ugrid.h b/src/nvim/ugrid.h
index 54cd33e58f..8679769468 100644
--- a/src/nvim/ugrid.h
+++ b/src/nvim/ugrid.h
@@ -2,12 +2,12 @@
#include "nvim/types_defs.h"
-typedef struct ucell {
+typedef struct {
schar_T data;
sattr_T attr;
} UCell;
-typedef struct ugrid {
+typedef struct {
int row, col;
int width, height;
UCell **cells;
diff --git a/src/nvim/ui.c b/src/nvim/ui.c
index 36f34bc75a..bddcf98b53 100644
--- a/src/nvim/ui.c
+++ b/src/nvim/ui.c
@@ -1,10 +1,10 @@
#include <assert.h>
#include <limits.h>
#include <stdbool.h>
-#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+#include <uv.h>
#include "klib/kvec.h"
#include "nvim/api/private/helpers.h"
@@ -13,10 +13,12 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/cursor_shape.h"
#include "nvim/drawscreen.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/ex_getln.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
@@ -25,9 +27,12 @@
#include "nvim/lua/executor.h"
#include "nvim/map_defs.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
#include "nvim/option.h"
+#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
+#include "nvim/os/os_defs.h"
#include "nvim/os/time.h"
#include "nvim/state_defs.h"
#include "nvim/strings.h"
@@ -37,13 +42,18 @@
#include "nvim/window.h"
#include "nvim/winfloat.h"
+typedef struct {
+ LuaRef cb;
+ bool ext_widgets[kUIGlobalCount];
+} UIEventCallback;
+
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui.c.generated.h"
#endif
#define MAX_UI_COUNT 16
-static UI *uis[MAX_UI_COUNT];
+static RemoteUI *uis[MAX_UI_COUNT];
static bool ui_ext[kUIExtCount] = { 0 };
static size_t ui_count = 0;
static int ui_mode_idx = SHAPE_IDX_N;
@@ -59,6 +69,7 @@ bool ui_cb_ext[kUIExtCount]; ///< Internalized UI capabilities.
static bool has_mouse = false;
static int pending_has_mouse = -1;
+static bool pending_default_colors = false;
static Array call_buf = ARRAY_DICT_INIT;
@@ -97,7 +108,7 @@ static void ui_log(const char *funname)
do { \
bool any_call = false; \
for (size_t i = 0; i < ui_count; i++) { \
- UI *ui = uis[i]; \
+ RemoteUI *ui = uis[i]; \
if ((cond)) { \
remote_ui_##funname(__VA_ARGS__); \
any_call = true; \
@@ -130,6 +141,8 @@ void ui_free_all_mem(void)
free_ui_event_callback(event_cb);
})
map_destroy(uint32_t, &ui_event_cbs);
+
+ multiqueue_free(resize_events);
}
#endif
@@ -190,7 +203,8 @@ void ui_refresh(void)
return;
}
- int width = INT_MAX, height = INT_MAX;
+ int width = INT_MAX;
+ int height = INT_MAX;
bool ext_widgets[kUIExtCount];
for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
ext_widgets[i] = true;
@@ -198,7 +212,7 @@ void ui_refresh(void)
bool inclusive = ui_override();
for (size_t i = 0; i < ui_count; i++) {
- UI *ui = uis[i];
+ RemoteUI *ui = uis[i];
width = MIN(ui->width, width);
height = MIN(ui->height, height);
for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
@@ -215,7 +229,7 @@ void ui_refresh(void)
}
ui_ext[i] = ext_widgets[i];
if (i < kUIGlobalCount) {
- ui_call_option_set(cstr_as_string((char *)ui_ext_names[i]),
+ ui_call_option_set(cstr_as_string(ui_ext_names[i]),
BOOLEAN_OBJ(ext_widgets[i]));
}
}
@@ -228,7 +242,7 @@ void ui_refresh(void)
p_lz = save_p_lz;
if (ext_widgets[kUIMessages]) {
- set_option_value("cmdheight", NUMBER_OPTVAL(0), 0);
+ set_option_value(kOptCmdheight, NUMBER_OPTVAL(0), 0);
command_height();
}
ui_mode_info_set();
@@ -272,13 +286,26 @@ static void ui_refresh_event(void **argv)
void ui_schedule_refresh(void)
{
- multiqueue_put(resize_events, ui_refresh_event, 0);
+ multiqueue_put(resize_events, ui_refresh_event, NULL);
}
void ui_default_colors_set(void)
{
- ui_call_default_colors_set(normal_fg, normal_bg, normal_sp,
- cterm_normal_fg_color, cterm_normal_bg_color);
+ // Throttle setting of default colors at startup, so it only happens once
+ // if the user sets the colorscheme in startup.
+ pending_default_colors = true;
+ if (starting == 0) {
+ ui_may_set_default_colors();
+ }
+}
+
+static void ui_may_set_default_colors(void)
+{
+ if (pending_default_colors) {
+ pending_default_colors = false;
+ ui_call_default_colors_set(normal_fg, normal_bg, normal_sp,
+ cterm_normal_fg_color, cterm_normal_bg_color);
+ }
}
void ui_busy_start(void)
@@ -340,12 +367,11 @@ void vim_beep(unsigned val)
void do_autocmd_uienter_all(void)
{
for (size_t i = 0; i < ui_count; i++) {
- UIData *data = uis[i]->data;
- do_autocmd_uienter(data->channel_id, true);
+ do_autocmd_uienter(uis[i]->channel_id, true);
}
}
-void ui_attach_impl(UI *ui, uint64_t chanid)
+void ui_attach_impl(RemoteUI *ui, uint64_t chanid)
{
if (ui_count == MAX_UI_COUNT) {
abort();
@@ -359,6 +385,12 @@ void ui_attach_impl(UI *ui, uint64_t chanid)
ui_refresh_options();
resettitle();
+ char cwd[MAXPATHL];
+ size_t cwdlen = sizeof(cwd);
+ if (uv_cwd(cwd, &cwdlen) == 0) {
+ ui_call_chdir((String){ .data = cwd, .size = cwdlen });
+ }
+
for (UIExtension i = kUIGlobalCount; (int)i < kUIExtCount; i++) {
ui_set_ext_option(ui, i, ui->ui_ext[i]);
}
@@ -375,7 +407,7 @@ void ui_attach_impl(UI *ui, uint64_t chanid)
do_autocmd_uienter(chanid, true);
}
-void ui_detach_impl(UI *ui, uint64_t chanid)
+void ui_detach_impl(RemoteUI *ui, uint64_t chanid)
{
size_t shift_index = MAX_UI_COUNT;
@@ -411,31 +443,32 @@ void ui_detach_impl(UI *ui, uint64_t chanid)
do_autocmd_uienter(chanid, false);
}
-void ui_set_ext_option(UI *ui, UIExtension ext, bool active)
+void ui_set_ext_option(RemoteUI *ui, UIExtension ext, bool active)
{
if (ext < kUIGlobalCount) {
ui_refresh();
return;
}
if (ui_ext_names[ext][0] != '_' || active) {
- remote_ui_option_set(ui, cstr_as_string((char *)ui_ext_names[ext]),
- BOOLEAN_OBJ(active));
+ remote_ui_option_set(ui, cstr_as_string(ui_ext_names[ext]), BOOLEAN_OBJ(active));
}
if (ext == kUITermColors) {
ui_default_colors_set();
}
}
-void ui_line(ScreenGrid *grid, int row, int startcol, int endcol, int clearcol, int clearattr,
- bool wrap)
+void ui_line(ScreenGrid *grid, int row, bool invalid_row, int startcol, int endcol, int clearcol,
+ int clearattr, bool wrap)
{
assert(0 <= row && row < grid->rows);
LineFlags flags = wrap ? kLineFlagWrap : 0;
- if (startcol == -1) {
- startcol = 0;
+ if (startcol == 0 && invalid_row) {
flags |= kLineFlagInvalid;
}
+ // set default colors now so that that text won't have to be repainted later
+ ui_may_set_default_colors();
+
size_t off = grid->line_offset[row] + (size_t)startcol;
ui_call_raw_line(grid->handle, row, startcol, endcol, clearcol, clearattr,
@@ -611,34 +644,35 @@ bool ui_has(UIExtension ext)
return ui_ext[ext];
}
-Array ui_array(void)
+Array ui_array(Arena *arena)
{
- Array all_uis = ARRAY_DICT_INIT;
+ Array all_uis = arena_array(arena, ui_count);
for (size_t i = 0; i < ui_count; i++) {
- UI *ui = uis[i];
- Dictionary info = ARRAY_DICT_INIT;
- PUT(info, "width", INTEGER_OBJ(ui->width));
- PUT(info, "height", INTEGER_OBJ(ui->height));
- PUT(info, "rgb", BOOLEAN_OBJ(ui->rgb));
- PUT(info, "override", BOOLEAN_OBJ(ui->override));
+ RemoteUI *ui = uis[i];
+ Dictionary info = arena_dict(arena, 10 + kUIExtCount);
+ PUT_C(info, "width", INTEGER_OBJ(ui->width));
+ PUT_C(info, "height", INTEGER_OBJ(ui->height));
+ PUT_C(info, "rgb", BOOLEAN_OBJ(ui->rgb));
+ PUT_C(info, "override", BOOLEAN_OBJ(ui->override));
// TUI fields. (`stdin_fd` is intentionally omitted.)
- PUT(info, "term_name", CSTR_TO_OBJ(ui->term_name));
+ PUT_C(info, "term_name", CSTR_AS_OBJ(ui->term_name));
// term_background is deprecated. Populate with an empty string
- PUT(info, "term_background", CSTR_TO_OBJ(""));
+ PUT_C(info, "term_background", STATIC_CSTR_AS_OBJ(""));
- 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));
+ PUT_C(info, "term_colors", INTEGER_OBJ(ui->term_colors));
+ PUT_C(info, "stdin_tty", BOOLEAN_OBJ(ui->stdin_tty));
+ PUT_C(info, "stdout_tty", BOOLEAN_OBJ(ui->stdout_tty));
for (UIExtension j = 0; j < kUIExtCount; j++) {
if (ui_ext_names[j][0] != '_' || ui->ui_ext[j]) {
- PUT(info, ui_ext_names[j], BOOLEAN_OBJ(ui->ui_ext[j]));
+ PUT_C(info, (char *)ui_ext_names[j], BOOLEAN_OBJ(ui->ui_ext[j]));
}
}
- remote_ui_inspect(ui, &info);
- ADD(all_uis, DICTIONARY_OBJ(info));
+ PUT_C(info, "chan", INTEGER_OBJ((Integer)ui->channel_id));
+
+ ADD_C(all_uis, DICTIONARY_OBJ(info));
}
return all_uis;
}
@@ -657,9 +691,9 @@ void ui_grid_resize(handle_T grid_handle, int width, int height, Error *err)
if (wp->w_floating) {
if (width != wp->w_width || height != wp->w_height) {
- wp->w_float_config.width = width;
- wp->w_float_config.height = height;
- win_config_float(wp, wp->w_float_config);
+ wp->w_config.width = width;
+ wp->w_config.height = height;
+ win_config_float(wp, wp->w_config);
}
} else {
// non-positive indicates no request
@@ -675,8 +709,8 @@ void ui_call_event(char *name, Array args)
bool handled = false;
map_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) {
+ Object res = nlua_call_ref(event_cb->cb, name, args, kRetNilBool, NULL, &err);
+ if (LUARET_TRUTHY(res)) {
handled = true;
}
if (ERROR_SET(&err)) {
@@ -692,7 +726,7 @@ void ui_call_event(char *name, Array args)
ui_log(name);
}
-void ui_cb_update_ext(void)
+static void ui_cb_update_ext(void)
{
memset(ui_cb_ext, 0, ARRAY_SIZE(ui_cb_ext));
@@ -708,7 +742,7 @@ void ui_cb_update_ext(void)
}
}
-void free_ui_event_callback(UIEventCallback *event_cb)
+static void free_ui_event_callback(UIEventCallback *event_cb)
{
api_free_luaref(event_cb->cb);
xfree(event_cb);
diff --git a/src/nvim/ui.h b/src/nvim/ui.h
index 666a869c89..52b1334b15 100644
--- a/src/nvim/ui.h
+++ b/src/nvim/ui.h
@@ -1,128 +1,19 @@
#pragma once
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
+#include <stdint.h> // IWYU pragma: keep
-#include "nvim/api/private/defs.h"
-#include "nvim/event/multiqueue.h"
-#include "nvim/globals.h"
-#include "nvim/highlight_defs.h"
+#include "nvim/api/private/defs.h" // IWYU pragma: keep
+#include "nvim/event/defs.h"
+#include "nvim/grid_defs.h" // IWYU pragma: keep
+#include "nvim/highlight_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
-#include "nvim/memory.h"
-#include "nvim/types_defs.h"
-
-struct ui_t;
-
-typedef enum {
- kUICmdline = 0,
- kUIPopupmenu,
- kUITabline,
- kUIWildmenu,
- kUIMessages,
-#define kUIGlobalCount kUILinegrid
- kUILinegrid,
- kUIMultigrid,
- kUIHlState,
- kUITermColors,
- kUIFloatDebug,
- kUIExtCount,
-} UIExtension;
-
-EXTERN const char *ui_ext_names[] INIT( = {
- "ext_cmdline",
- "ext_popupmenu",
- "ext_tabline",
- "ext_wildmenu",
- "ext_messages",
- "ext_linegrid",
- "ext_multigrid",
- "ext_hlstate",
- "ext_termcolors",
- "_debug_float",
-});
-
-typedef struct ui_t UI;
-
-enum {
- kLineFlagWrap = 1,
- kLineFlagInvalid = 2,
-};
-
-typedef int LineFlags;
-
-typedef struct {
- uint64_t channel_id;
-
-#define UI_BUF_SIZE 4096 ///< total buffer size for pending msgpack data.
- /// guaranteed size available for each new event (so packing of simple events
- /// and the header of grid_line will never fail)
-#define EVENT_BUF_SIZE 256
- char buf[UI_BUF_SIZE]; ///< buffer of packed but not yet sent msgpack data
- char *buf_wptr; ///< write head of buffer
- const char *cur_event; ///< name of current event (might get multiple arglists)
- Array call_buf; ///< buffer for constructing a single arg list (max 16 elements!)
-
- // state for write_cb, while packing a single arglist to msgpack. This
- // might fail due to buffer overflow.
- size_t pack_totlen;
- bool buf_overflow;
- char *temp_buf;
-
- // We start packing the two outermost msgpack arrays before knowing the total
- // number of elements. Thus track the location where array size will need
- // to be written in the msgpack buffer, once the specific array is finished.
- char *nevents_pos;
- char *ncalls_pos;
- uint32_t nevents; ///< number of distinct events (top-level args to "redraw"
- uint32_t ncalls; ///< number of calls made to the current event (plus one for the name!)
- bool flushed_events; ///< events where sent to client without "flush" event
-
- size_t ncells_pending; ///< total number of cells since last buffer flush
-
- int hl_id; // Current highlight for legacy put event.
- Integer cursor_row, cursor_col; // Intended visible cursor position.
-
- // Position of legacy cursor, used both for drawing and visible user cursor.
- Integer client_row, client_col;
- bool wildmenu_active;
-} UIData;
-
-struct ui_t {
- bool rgb;
- bool override; ///< Force highest-requested UI capabilities.
- bool composed;
- bool ui_ext[kUIExtCount]; ///< Externalized UI capabilities.
- int width;
- int height;
- int pum_nlines; /// actual nr. lines shown in PUM
- bool pum_pos; /// UI reports back pum position?
- double pum_row;
- double pum_col;
- double pum_height;
- double pum_width;
-
- // TUI fields.
- char *term_name;
- char *term_background; ///< Deprecated. No longer needed since background color detection happens
- ///< in Lua. To be removed in a future release.
- int term_colors;
- bool stdin_tty;
- bool stdout_tty;
-
- // TODO(bfredl): integrate into struct!
- UIData data[1];
-};
-
-typedef struct ui_event_callback {
- LuaRef cb;
- bool ext_widgets[kUIGlobalCount];
-} UIEventCallback;
+#include "nvim/types_defs.h" // IWYU pragma: keep
+#include "nvim/ui_defs.h" // IWYU pragma: keep
// uncrustify:off
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui.h.generated.h"
-# include "ui_events_call.h.generated.h" // IWYU pragma: export
+# include "ui_events_call.h.generated.h"
#endif
// uncrustify:on
diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c
index 30f44d182d..4f36cae4b2 100644
--- a/src/nvim/ui_client.c
+++ b/src/nvim/ui_client.c
@@ -5,23 +5,29 @@
#include <stdlib.h>
#include "nvim/api/keysets_defs.h"
+#include "nvim/api/private/defs.h"
#include "nvim/api/private/dispatch.h"
#include "nvim/api/private/helpers.h"
#include "nvim/channel.h"
+#include "nvim/channel_defs.h"
#include "nvim/eval.h"
#include "nvim/eval/typval_defs.h"
-#include "nvim/event/loop.h"
-#include "nvim/func_attr.h"
+#include "nvim/event/multiqueue.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/log.h"
#include "nvim/main.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/msgpack_rpc/channel.h"
+#include "nvim/msgpack_rpc/channel_defs.h"
#include "nvim/os/os_defs.h"
#include "nvim/tui/tui.h"
+#include "nvim/tui/tui_defs.h"
#include "nvim/ui.h"
#include "nvim/ui_client.h"
+#include "nvim/ui_defs.h"
#ifdef MSWIN
# include "nvim/os/os_win_console.h"
@@ -56,6 +62,9 @@ uint64_t ui_client_start_server(int argc, char **argv)
CALLBACK_READER_INIT, on_err, CALLBACK_NONE,
false, true, true, false, kChannelStdinPipe,
NULL, 0, 0, NULL, &exit_status);
+ if (!channel) {
+ return 0;
+ }
// If stdin is not a pty, it is forwarded to the client.
// Replace stdin in the TUI process with the tty fd.
@@ -71,14 +80,14 @@ uint64_t ui_client_start_server(int argc, char **argv)
return channel->id;
}
-void ui_client_attach(int width, int height, char *term)
+void ui_client_attach(int width, int height, char *term, bool rgb)
{
MAXSIZE_TEMP_ARRAY(args, 3);
ADD_C(args, INTEGER_OBJ(width));
ADD_C(args, INTEGER_OBJ(height));
MAXSIZE_TEMP_DICT(opts, 9);
- PUT_C(opts, "rgb", BOOLEAN_OBJ(true));
+ PUT_C(opts, "rgb", BOOLEAN_OBJ(rgb));
PUT_C(opts, "ext_linegrid", BOOLEAN_OBJ(true));
PUT_C(opts, "ext_termcolors", BOOLEAN_OBJ(true));
if (term) {
@@ -112,9 +121,10 @@ void ui_client_run(bool remote_ui)
ui_client_is_remote = remote_ui;
int width, height;
char *term;
- tui_start(&tui, &width, &height, &term);
+ bool rgb;
+ tui_start(&tui, &width, &height, &term, &rgb);
- ui_client_attach(width, height, term);
+ ui_client_attach(width, height, term, rgb);
// os_exit() will be invoked when the client channel detaches
while (true) {
@@ -163,12 +173,19 @@ Object handle_ui_client_redraw(uint64_t channel_id, Array args, Arena *arena, Er
static HlAttrs ui_client_dict2hlattrs(Dictionary d, bool rgb)
{
Error err = ERROR_INIT;
- Dict(highlight) dict = { 0 };
+ Dict(highlight) dict = KEYDICT_INIT;
if (!api_dict_to_keydict(&dict, KeyDict_highlight_get_field, d, &err)) {
// TODO(bfredl): log "err"
return HLATTRS_INIT;
}
- return dict2hlattrs(&dict, rgb, NULL, &err);
+
+ HlAttrs attrs = dict2hlattrs(&dict, rgb, NULL, &err);
+
+ if (HAS_KEY(&dict, highlight, url)) {
+ attrs.url = tui_add_url(tui, dict.url.data);
+ }
+
+ return attrs;
}
void ui_client_event_grid_resize(Array args)
@@ -203,7 +220,9 @@ void ui_client_event_grid_line(Array args)
void ui_client_event_raw_line(GridLineEvent *g)
{
- int grid = g->args[0], row = g->args[1], startcol = g->args[2];
+ int grid = g->args[0];
+ int row = g->args[1];
+ int startcol = g->args[2];
Integer endcol = startcol + g->coloff;
Integer clearcol = endcol + g->clear_width;
LineFlags lineflags = g->wrap ? kLineFlagWrap : 0;
@@ -211,3 +230,12 @@ void ui_client_event_raw_line(GridLineEvent *g)
tui_raw_line(tui, grid, row, startcol, endcol, clearcol, g->cur_attr, lineflags,
(const schar_T *)grid_line_buf_char, grid_line_buf_attr);
}
+
+#ifdef EXITFREE
+void ui_client_free_all_mem(void)
+{
+ tui_free_all_mem(tui);
+ xfree(grid_line_buf_char);
+ xfree(grid_line_buf_attr);
+}
+#endif
diff --git a/src/nvim/ui_client.h b/src/nvim/ui_client.h
index 93170ed86d..d3be9882aa 100644
--- a/src/nvim/ui_client.h
+++ b/src/nvim/ui_client.h
@@ -4,15 +4,10 @@
#include <stddef.h>
#include <stdint.h>
-#include "nvim/api/private/defs.h"
#include "nvim/grid_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
#include "nvim/types_defs.h"
-
-typedef struct {
- const char *name;
- void (*fn)(Array args);
-} UIClientHandler;
+#include "nvim/ui_defs.h" // IWYU pragma: keep
// Temporary buffer for converting a single grid_line event
EXTERN size_t grid_line_buf_size INIT( = 0);
@@ -39,6 +34,6 @@ EXTERN bool ui_client_forward_stdin INIT( = false);
// uncrustify:off
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui_client.h.generated.h"
-# include "ui_events_client.h.generated.h" // IWYU pragma: export
+# include "ui_events_client.h.generated.h"
#endif
// uncrustify:on
diff --git a/src/nvim/ui_compositor.c b/src/nvim/ui_compositor.c
index b698e017dc..6e89894e0b 100644
--- a/src/nvim/ui_compositor.c
+++ b/src/nvim/ui_compositor.c
@@ -9,14 +9,16 @@
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
+#include <uv.h>
#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/ascii_defs.h"
+#include "nvim/buffer_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/highlight_group.h"
#include "nvim/log.h"
#include "nvim/macros_defs.h"
@@ -60,6 +62,15 @@ void ui_comp_init(void)
curgrid = &default_grid;
}
+#ifdef EXITFREE
+void ui_comp_free_all_mem(void)
+{
+ kv_destroy(layers);
+ xfree(linebuf);
+ xfree(attrbuf);
+}
+#endif
+
void ui_comp_syn_init(void)
{
dbghl_normal = syn_check_group(S_LEN("RedrawDebugNormal"));
@@ -68,13 +79,13 @@ void ui_comp_syn_init(void)
dbghl_recompose = syn_check_group(S_LEN("RedrawDebugRecompose"));
}
-void ui_comp_attach(UI *ui)
+void ui_comp_attach(RemoteUI *ui)
{
composed_uis++;
ui->composed = true;
}
-void ui_comp_detach(UI *ui)
+void ui_comp_detach(RemoteUI *ui)
{
composed_uis--;
if (composed_uis == 0) {
@@ -296,7 +307,8 @@ static void compose_line(Integer row, Integer startcol, Integer endcol, LineFlag
startcol = MAX(startcol, 0);
// in case we start on the right half of a double-width char, we need to
// check the left half. But skip it in output if it wasn't doublewidth.
- int skipstart = 0, skipend = 0;
+ int skipstart = 0;
+ int skipend = 0;
if (startcol > 0 && (flags & kLineFlagInvalid)) {
startcol--;
skipstart = 1;
diff --git a/src/nvim/ui_compositor.h b/src/nvim/ui_compositor.h
index f3f5981680..b0dd8e126b 100644
--- a/src/nvim/ui_compositor.h
+++ b/src/nvim/ui_compositor.h
@@ -1,10 +1,9 @@
#pragma once
#include "nvim/api/private/defs.h" // IWYU pragma: keep
-#include "nvim/event/defs.h"
#include "nvim/grid_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
-#include "nvim/ui.h"
+#include "nvim/ui_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "ui_compositor.h.generated.h"
diff --git a/src/nvim/ui_defs.h b/src/nvim/ui_defs.h
new file mode 100644
index 0000000000..4d73cc2321
--- /dev/null
+++ b/src/nvim/ui_defs.h
@@ -0,0 +1,90 @@
+#pragma once
+
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdint.h>
+
+#include "nvim/api/private/defs.h"
+#include "nvim/msgpack_rpc/packer_defs.h"
+
+/// Keep in sync with ui_ext_names[] in ui.h
+typedef enum {
+ kUICmdline = 0,
+ kUIPopupmenu,
+ kUITabline,
+ kUIWildmenu,
+ kUIMessages,
+#define kUIGlobalCount kUILinegrid
+ kUILinegrid,
+ kUIMultigrid,
+ kUIHlState,
+ kUITermColors,
+ kUIFloatDebug,
+ kUIExtCount,
+} UIExtension;
+
+enum {
+ kLineFlagWrap = 1,
+ kLineFlagInvalid = 2,
+};
+
+typedef int LineFlags;
+
+typedef struct {
+ bool rgb;
+ bool override; ///< Force highest-requested UI capabilities.
+ bool composed;
+ bool ui_ext[kUIExtCount]; ///< Externalized UI capabilities.
+ int width;
+ int height;
+ int pum_nlines; /// actual nr. lines shown in PUM
+ bool pum_pos; /// UI reports back pum position?
+ double pum_row;
+ double pum_col;
+ double pum_height;
+ double pum_width;
+
+ // TUI fields.
+ char *term_name;
+ char *term_background; ///< Deprecated. No longer needed since background color detection happens
+ ///< in Lua. To be removed in a future release.
+ int term_colors;
+ bool stdin_tty;
+ bool stdout_tty;
+
+ uint64_t channel_id;
+
+#define UI_BUF_SIZE ARENA_BLOCK_SIZE ///< total buffer size for pending msgpack data.
+ /// guaranteed size available for each new event (so packing of simple events
+ /// and the header of grid_line will never fail)
+#define EVENT_BUF_SIZE 256
+
+// Fields related to packing
+ PackerBuffer packer;
+
+ const char *cur_event; ///< name of current event (might get multiple arglists)
+ Array call_buf; ///< buffer for constructing a single arg list (max 16 elements!)
+
+ // We start packing the two outermost msgpack arrays before knowing the total
+ // number of elements. Thus track the location where array size will need
+ // to be written in the msgpack buffer, once the specific array is finished.
+ char *nevents_pos;
+ char *ncalls_pos;
+ uint32_t nevents; ///< number of distinct events (top-level args to "redraw"
+ uint32_t ncalls; ///< number of calls made to the current event (plus one for the name!)
+ bool flushed_events; ///< events where sent to client without "flush" event
+
+ size_t ncells_pending; ///< total number of cells since last buffer flush
+
+ int hl_id; // Current highlight for legacy put event.
+ Integer cursor_row, cursor_col; // Intended visible cursor position.
+
+ // Position of legacy cursor, used both for drawing and visible user cursor.
+ Integer client_row, client_col;
+ bool wildmenu_active;
+} RemoteUI;
+
+typedef struct {
+ const char *name;
+ void (*fn)(Array args);
+} UIClientHandler;
diff --git a/src/nvim/undo.c b/src/nvim/undo.c
index 93a973c33d..e9170ba858 100644
--- a/src/nvim/undo.c
+++ b/src/nvim/undo.c
@@ -77,7 +77,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
#include <time.h>
#include <uv.h>
@@ -86,9 +85,11 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/buffer_updates.h"
#include "nvim/change.h"
#include "nvim/cursor.h"
+#include "nvim/decoration.h"
#include "nvim/drawscreen.h"
#include "nvim/edit.h"
#include "nvim/eval/funcs.h"
@@ -97,25 +98,33 @@
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
#include "nvim/extmark.h"
+#include "nvim/extmark_defs.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
+#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/macros_defs.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
+#include "nvim/marktree_defs.h"
+#include "nvim/mbyte.h"
#include "nvim/memline.h"
+#include "nvim/memline_defs.h"
#include "nvim/memory.h"
#include "nvim/message.h"
#include "nvim/option.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
+#include "nvim/os/fs_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os_defs.h"
#include "nvim/os/time.h"
+#include "nvim/os/time_defs.h"
#include "nvim/path.h"
#include "nvim/pos_defs.h"
#include "nvim/sha256.h"
@@ -345,7 +354,7 @@ static inline void zero_fmark_additional_data(fmark_T *fmarks)
/// "reload" is true when saving for a buffer reload.
/// Careful: may trigger autocommands that reload the buffer.
/// Returns FAIL when lines could not be saved, OK otherwise.
-int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, int reload)
+int u_savecommon(buf_T *buf, linenr_T top, linenr_T bot, linenr_T newbot, bool reload)
{
if (!reload) {
// When making changes is not allowed return FAIL. It's a crude way
@@ -935,7 +944,7 @@ static u_header_T *unserialize_uhp(bufinfo_T *bi, const char *file_name)
default:
// Field not supported, skip it.
while (--len >= 0) {
- (void)undo_read_byte(bi);
+ undo_read_byte(bi);
}
}
}
@@ -964,12 +973,11 @@ static u_header_T *unserialize_uhp(bufinfo_T *bi, const char *file_name)
}
// Unserialize all extmark undo information
- ExtmarkUndoObject *extup;
kv_init(uhp->uh_extmark);
while ((c = undo_read_2c(bi)) == UF_ENTRY_MAGIC) {
bool error = false;
- extup = unserialize_extmark(bi, &error, file_name);
+ ExtmarkUndoObject *extup = unserialize_extmark(bi, &error, file_name);
if (error) {
kv_destroy(uhp->uh_extmark);
xfree(extup);
@@ -1257,7 +1265,7 @@ void u_write_undo(const char *const name, const bool forceit, buf_T *const buf,
semsg(_(e_not_open), file_name);
goto theend;
}
- (void)os_setperm(file_name, perm);
+ os_setperm(file_name, perm);
if (p_verbose > 0) {
verbose_enter();
smsg(0, _("Writing undo file: %s"), file_name);
@@ -1502,7 +1510,7 @@ void u_read_undo(char *name, const uint8_t *hash, const char *orig_name FUNC_ATT
default:
// field not supported, skip
while (--len >= 0) {
- (void)undo_read_byte(&bi);
+ undo_read_byte(&bi);
}
}
}
@@ -1554,7 +1562,9 @@ void u_read_undo(char *name, const uint8_t *hash, const char *orig_name FUNC_ATT
// We have put all of the headers into a table. Now we iterate through the
// table and swizzle each sequence number we have stored in uh_*_seq into
// a pointer corresponding to the header with that sequence number.
- int16_t old_idx = -1, new_idx = -1, cur_idx = -1;
+ int16_t old_idx = -1;
+ int16_t new_idx = -1;
+ int16_t cur_idx = -1;
for (int i = 0; i < num_head; i++) {
u_header_T *uhp = uhp_table[i];
if (uhp == NULL) {
@@ -2250,7 +2260,7 @@ target_zero:
///
/// @param undo If `true`, go up the tree. Down if `false`.
/// @param do_buf_event If `true`, send buffer updates.
-static void u_undoredo(int undo, bool do_buf_event)
+static void u_undoredo(bool undo, bool do_buf_event)
{
char **newarray = NULL;
linenr_T newlnum = MAXLNUM;
@@ -2416,17 +2426,14 @@ static void u_undoredo(int undo, bool do_buf_event)
}
// Adjust Extmarks
- ExtmarkUndoObject undo_info;
if (undo) {
for (int i = (int)kv_size(curhead->uh_extmark) - 1; i > -1; i--) {
- undo_info = kv_A(curhead->uh_extmark, i);
- extmark_apply_undo(undo_info, undo);
+ extmark_apply_undo(kv_A(curhead->uh_extmark, i), undo);
}
// redo
} else {
for (int i = 0; i < (int)kv_size(curhead->uh_extmark); i++) {
- undo_info = kv_A(curhead->uh_extmark, i);
- extmark_apply_undo(undo_info, undo);
+ extmark_apply_undo(kv_A(curhead->uh_extmark, i), undo);
}
}
if (curhead->uh_flags & UH_RELOAD) {
@@ -2434,7 +2441,7 @@ static void u_undoredo(int undo, bool do_buf_event)
// should have all info to send a buffer-reloaing on_lines/on_bytes event
buf_updates_unload(curbuf, true);
}
- // finish Adjusting extmarks
+ // Finish adjusting extmarks
curhead->uh_entry = newlist;
curhead->uh_flags = new_flags;
@@ -2981,6 +2988,28 @@ void u_clearall(buf_T *buf)
buf->b_u_line_lnum = 0;
}
+/// Free all allocated memory blocks for the buffer 'buf'.
+void u_blockfree(buf_T *buf)
+{
+ while (buf->b_u_oldhead != NULL) {
+#ifndef NDEBUG
+ u_header_T *previous_oldhead = buf->b_u_oldhead;
+#endif
+
+ u_freeheader(buf, buf->b_u_oldhead, NULL);
+ assert(buf->b_u_oldhead != previous_oldhead);
+ }
+ xfree(buf->b_u_line_ptr);
+}
+
+/// Free all allocated memory blocks for the buffer 'buf'.
+/// and invalidate the undo buffer
+void u_clearallandblockfree(buf_T *buf)
+{
+ u_blockfree(buf);
+ u_clearall(buf);
+}
+
/// Save the line "lnum" for the "U" command.
void u_saveline(buf_T *buf, linenr_T lnum)
{
@@ -3032,9 +3061,9 @@ void u_undoline(void)
char *oldp = u_save_line(curbuf->b_u_line_lnum);
ml_replace(curbuf->b_u_line_lnum, curbuf->b_u_line_ptr, true);
- changed_bytes(curbuf->b_u_line_lnum, 0);
extmark_splice_cols(curbuf, (int)curbuf->b_u_line_lnum - 1, 0, (colnr_T)strlen(oldp),
(colnr_T)strlen(curbuf->b_u_line_ptr), kExtmarkUndo);
+ changed_bytes(curbuf->b_u_line_lnum, 0);
xfree(curbuf->b_u_line_ptr);
curbuf->b_u_line_ptr = oldp;
@@ -3047,20 +3076,6 @@ void u_undoline(void)
check_cursor_col();
}
-/// Free all allocated memory blocks for the buffer 'buf'.
-void u_blockfree(buf_T *buf)
-{
- while (buf->b_u_oldhead != NULL) {
-#ifndef NDEBUG
- u_header_T *previous_oldhead = buf->b_u_oldhead;
-#endif
-
- u_freeheader(buf, buf->b_u_oldhead, NULL);
- assert(buf->b_u_oldhead != previous_oldhead);
- }
- xfree(buf->b_u_line_ptr);
-}
-
/// Allocate memory and copy curbuf line into it.
///
/// @param lnum the line to copy
diff --git a/src/nvim/undo.h b/src/nvim/undo.h
index f3a8a60d45..800a1bfae0 100644
--- a/src/nvim/undo.h
+++ b/src/nvim/undo.h
@@ -1,10 +1,10 @@
#pragma once
-#include "nvim/buffer_defs.h" // IWYU pragma: keep
+#include "nvim/eval/typval_defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/pos_defs.h" // IWYU pragma: keep
#include "nvim/types_defs.h" // IWYU pragma: keep
-#include "nvim/undo_defs.h" // IWYU pragma: export
+#include "nvim/undo_defs.h" // IWYU pragma: keep
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "undo.h.generated.h"
diff --git a/src/nvim/undo_defs.h b/src/nvim/undo_defs.h
index 0b78ea543f..39786fa928 100644
--- a/src/nvim/undo_defs.h
+++ b/src/nvim/undo_defs.h
@@ -4,10 +4,8 @@
#include "nvim/extmark_defs.h"
#include "nvim/mark_defs.h"
-#include "nvim/pos_defs.h"
-/// Size in bytes of the hash used in the undo file.
-enum { UNDO_HASH_SIZE = 32, };
+enum { UNDO_HASH_SIZE = 32, }; ///< Size in bytes of the hash used in the undo file.
typedef struct u_header u_header_T;
@@ -19,8 +17,6 @@ typedef struct {
colnr_T vi_curswant; ///< MAXCOL from w_curswant
} visualinfo_T;
-#include "nvim/buffer_defs.h"
-
typedef struct u_entry u_entry_T;
struct u_entry {
u_entry_T *ue_next; ///< pointer to next entry in list
diff --git a/src/nvim/usercmd.c b/src/nvim/usercmd.c
index 7c65af5138..8d41edec8a 100644
--- a/src/nvim/usercmd.c
+++ b/src/nvim/usercmd.c
@@ -8,7 +8,6 @@
#include <string.h>
#include "auto/config.h"
-#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
@@ -16,11 +15,11 @@
#include "nvim/cmdexpand_defs.h"
#include "nvim/eval.h"
#include "nvim/ex_docmd.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/keycodes.h"
#include "nvim/lua/executor.h"
#include "nvim/macros_defs.h"
@@ -77,6 +76,7 @@ static const char *command_complete[] = {
[EXPAND_HELP] = "help",
[EXPAND_HIGHLIGHT] = "highlight",
[EXPAND_HISTORY] = "history",
+ [EXPAND_KEYMAP] = "keymap",
#ifdef HAVE_WORKING_LIBINTL
[EXPAND_LOCALES] = "locale",
#endif
@@ -584,7 +584,7 @@ static void uc_list(char *name, size_t name_len)
msg_outtrans(IObuff, 0);
if (cmd->uc_luaref != LUA_NOREF) {
- char *fn = nlua_funcref_str(cmd->uc_luaref);
+ char *fn = nlua_funcref_str(cmd->uc_luaref, NULL);
msg_puts_attr(fn, HL_ATTR(HLF_8));
xfree(fn);
// put the description on a new line
@@ -874,7 +874,7 @@ int uc_add_command(char *name, size_t name_len, const char *rep, uint32_t argt,
char *rep_buf = NULL;
garray_T *gap;
- replace_termcodes(rep, strlen(rep), &rep_buf, 0, 0, NULL, CPO_TO_CPO_FLAGS);
+ replace_termcodes(rep, strlen(rep), &rep_buf, 0, 0, NULL, p_cpo);
if (rep_buf == NULL) {
// Can't replace termcodes - try using the string as is
rep_buf = xstrdup(rep);
@@ -1136,6 +1136,20 @@ bool uc_split_args_iter(const char *arg, size_t arglen, size_t *end, char *buf,
return true;
}
+size_t uc_nargs_upper_bound(const char *arg, size_t arglen)
+{
+ bool was_white = true; // space before first arg
+ size_t nargs = 0;
+ for (size_t i = 0; i < arglen; i++) {
+ bool is_white = ascii_iswhite(arg[i]);
+ if (was_white && !is_white) {
+ nargs++;
+ }
+ was_white = is_white;
+ }
+ return nargs;
+}
+
/// split and quote args for <f-args>
static char *uc_split_args(const char *arg, char **args, const size_t *arglens, size_t argc,
size_t *lenp)
@@ -1710,8 +1724,8 @@ int do_ucmd(exarg_T *eap, bool preview)
save_current_sctx = current_sctx;
current_sctx.sc_sid = cmd->uc_script_ctx.sc_sid;
}
- (void)do_cmdline(buf, eap->getline, eap->cookie,
- DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
+ do_cmdline(buf, eap->getline, eap->cookie,
+ DOCMD_VERBOSE|DOCMD_NOWAIT|DOCMD_KEYTYPED);
// Careful: Do not use "cmd" here, it may have become invalid if a user
// command was added.
@@ -1730,25 +1744,24 @@ int do_ucmd(exarg_T *eap, bool preview)
/// @param buf Buffer to inspect, or NULL to get global commands.
///
/// @return Map of maps describing commands
-Dictionary commands_array(buf_T *buf)
+Dictionary commands_array(buf_T *buf, Arena *arena)
{
- Dictionary rv = ARRAY_DICT_INIT;
- char str[20];
garray_T *gap = (buf == NULL) ? &ucmds : &buf->b_ucmds;
+ Dictionary rv = arena_dict(arena, (size_t)gap->ga_len);
for (int i = 0; i < gap->ga_len; i++) {
char arg[2] = { 0, 0 };
- Dictionary d = ARRAY_DICT_INIT;
+ Dictionary d = arena_dict(arena, 14);
ucmd_T *cmd = USER_CMD_GA(gap, i);
- 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)));
- PUT(d, "register", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_REGSTR)));
- PUT(d, "keepscript", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_KEEPSCRIPT)));
- PUT(d, "preview", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_PREVIEW)));
+ PUT_C(d, "name", CSTR_AS_OBJ(cmd->uc_name));
+ PUT_C(d, "definition", CSTR_AS_OBJ(cmd->uc_rep));
+ PUT_C(d, "script_id", INTEGER_OBJ(cmd->uc_script_ctx.sc_sid));
+ PUT_C(d, "bang", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_BANG)));
+ PUT_C(d, "bar", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_TRLBAR)));
+ PUT_C(d, "register", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_REGSTR)));
+ PUT_C(d, "keepscript", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_KEEPSCRIPT)));
+ PUT_C(d, "preview", BOOLEAN_OBJ(!!(cmd->uc_argt & EX_PREVIEW)));
switch (cmd->uc_argt & (EX_EXTRA | EX_NOSPC | EX_NEEDARG)) {
case 0:
@@ -1762,49 +1775,47 @@ Dictionary commands_array(buf_T *buf)
case (EX_EXTRA | EX_NOSPC | EX_NEEDARG):
arg[0] = '1'; break;
}
- PUT(d, "nargs", CSTR_TO_OBJ(arg));
+ PUT_C(d, "nargs", CSTR_TO_ARENA_OBJ(arena, arg));
char *cmd_compl = get_command_complete(cmd->uc_compl);
- PUT(d, "complete", (cmd_compl == NULL
- ? NIL : CSTR_TO_OBJ(cmd_compl)));
- PUT(d, "complete_arg", cmd->uc_compl_arg == NULL
- ? NIL : CSTR_TO_OBJ(cmd->uc_compl_arg));
+ PUT_C(d, "complete", (cmd_compl == NULL
+ ? NIL : CSTR_AS_OBJ(cmd_compl)));
+ PUT_C(d, "complete_arg", cmd->uc_compl_arg == NULL
+ ? NIL : CSTR_AS_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 = CSTR_TO_OBJ(str); // -count=N
+ obj = STRING_OBJ(arena_printf(arena, "%" PRId64, cmd->uc_def)); // -count=N
} else {
- obj = CSTR_TO_OBJ("0"); // -count
+ obj = CSTR_AS_OBJ("0"); // -count
}
}
- PUT(d, "count", obj);
+ PUT_C(d, "count", obj);
obj = NIL;
if (cmd->uc_argt & EX_RANGE) {
if (cmd->uc_argt & EX_DFLALL) {
- obj = CSTR_TO_OBJ("%"); // -range=%
+ obj = STATIC_CSTR_AS_OBJ("%"); // -range=%
} else if (cmd->uc_def >= 0) {
- snprintf(str, sizeof(str), "%" PRId64, cmd->uc_def);
- obj = CSTR_TO_OBJ(str); // -range=N
+ obj = STRING_OBJ(arena_printf(arena, "%" PRId64, cmd->uc_def)); // -range=N
} else {
- obj = CSTR_TO_OBJ("."); // -range
+ obj = STATIC_CSTR_AS_OBJ("."); // -range
}
}
- PUT(d, "range", obj);
+ PUT_C(d, "range", obj);
obj = NIL;
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 = CSTR_TO_OBJ(addr_type_complete[j].name);
+ obj = CSTR_AS_OBJ(addr_type_complete[j].name);
break;
}
}
- PUT(d, "addr", obj);
+ PUT_C(d, "addr", obj);
- PUT(rv, cmd->uc_name, DICTIONARY_OBJ(d));
+ PUT_C(rv, cmd->uc_name, DICTIONARY_OBJ(d));
}
return rv;
}
diff --git a/src/nvim/usercmd.h b/src/nvim/usercmd.h
index bcabf9460b..84a8f61719 100644
--- a/src/nvim/usercmd.h
+++ b/src/nvim/usercmd.h
@@ -3,13 +3,14 @@
#include <stddef.h> // IWYU pragma: keep
#include <stdint.h>
+#include "nvim/api/private/defs.h" // IWYU pragma: keep
#include "nvim/cmdexpand_defs.h" // IWYU pragma: keep
#include "nvim/eval/typval_defs.h"
#include "nvim/ex_cmds_defs.h"
#include "nvim/garray_defs.h"
-#include "nvim/types_defs.h" // IWYU pragma: keep
+#include "nvim/types_defs.h"
-typedef struct ucmd {
+typedef struct {
char *uc_name; ///< The command name
uint32_t uc_argt; ///< The argument type
char *uc_rep; ///< The command's replacement string
diff --git a/src/nvim/version.c b/src/nvim/version.c
index cb9088afae..038c9701bf 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -13,18 +13,18 @@
#include "auto/versiondef.h" // version info generated by the build system
#include "auto/versiondef_git.h"
-#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/ascii_defs.h"
#include "nvim/buffer.h"
+#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
#include "nvim/drawscreen.h"
#include "nvim/ex_cmds_defs.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
#include "nvim/highlight.h"
+#include "nvim/highlight_defs.h"
#include "nvim/lua/executor.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
@@ -512,7 +512,7 @@ static const int included_patches[] = {
1971,
1970,
// 1969,
- // 1968,
+ 1968,
1967,
1966,
1965,
@@ -897,7 +897,7 @@ static const int included_patches[] = {
// 1586,
1585,
// 1584,
- // 1583,
+ 1583,
1582,
1581,
// 1580,
@@ -2550,24 +2550,6 @@ bool has_vim_patch(int n)
return false;
}
-Dictionary version_dict(void)
-{
- Dictionary d = ARRAY_DICT_INIT;
- PUT(d, "major", INTEGER_OBJ(NVIM_VERSION_MAJOR));
- PUT(d, "minor", INTEGER_OBJ(NVIM_VERSION_MINOR));
- PUT(d, "patch", INTEGER_OBJ(NVIM_VERSION_PATCH));
-#ifndef NVIM_VERSION_BUILD
- PUT(d, "build", NIL);
-#else
- PUT(d, "build", CSTR_AS_OBJ(NVIM_VERSION_BUILD));
-#endif
- PUT(d, "prerelease", BOOLEAN_OBJ(NVIM_VERSION_PRERELEASE[0] != '\0'));
- PUT(d, "api_level", INTEGER_OBJ(NVIM_API_LEVEL));
- PUT(d, "api_compatible", INTEGER_OBJ(NVIM_API_LEVEL_COMPAT));
- PUT(d, "api_prerelease", BOOLEAN_OBJ(NVIM_API_PRERELEASE));
- return d;
-}
-
void ex_version(exarg_T *eap)
{
// Ignore a ":version 9.99" command.
@@ -2582,7 +2564,7 @@ void ex_version(exarg_T *eap)
/// When "wrap" is true wrap the string in [].
/// @param s
/// @param wrap
-static void version_msg_wrap(char *s, int wrap)
+static void version_msg_wrap(char *s, bool wrap)
{
int len = vim_strsize(s) + (wrap ? 2 : 0);
@@ -2649,7 +2631,7 @@ void list_in_columns(char **items, int size, int current)
for (int i = 0; !got_int && i < nrow * ncol; i++) {
int idx = (i / ncol) + (i % ncol) * nrow;
if (idx < item_count) {
- int last_col = (i + 1) % ncol == 0;
+ bool last_col = (i + 1) % ncol == 0;
if (idx == current) {
msg_putchar('[');
}
@@ -2681,9 +2663,9 @@ void list_in_columns(char **items, int size, int current)
void list_lua_version(void)
{
- char *code = "return ((jit and jit.version) and jit.version or _VERSION)";
Error err = ERROR_INIT;
- Object ret = nlua_exec(cstr_as_string(code), (Array)ARRAY_DICT_INIT, &err);
+ Object ret = NLUA_EXEC_STATIC("return ((jit and jit.version) and jit.version or _VERSION)",
+ (Array)ARRAY_DICT_INIT, kRetObject, NULL, &err);
assert(!ERROR_SET(&err));
assert(ret.type == kObjectTypeString);
msg(ret.data.string.data, 0);
@@ -2708,7 +2690,6 @@ void list_version(void)
version_msg("\"\n");
#endif
-#ifdef HAVE_PATHDEF
if (*default_vim_dir != NUL) {
version_msg(_(" fall-back for $VIM: \""));
version_msg(default_vim_dir);
@@ -2720,7 +2701,6 @@ void list_version(void)
version_msg(default_vimruntime_dir);
version_msg("\"\n");
}
-#endif
}
version_msg(p_verbose > 0
diff --git a/src/nvim/version.h b/src/nvim/version.h
index 94219aaddc..cc355f2df5 100644
--- a/src/nvim/version.h
+++ b/src/nvim/version.h
@@ -1,5 +1,6 @@
#pragma once
+#include "nvim/api/private/defs.h" // IWYU pragma: keep
#include "nvim/ex_cmds_defs.h" // IWYU pragma: keep
#include "nvim/macros_defs.h"
diff --git a/src/nvim/vim_defs.h b/src/nvim/vim_defs.h
index faf79b1c79..f6b348e009 100644
--- a/src/nvim/vim_defs.h
+++ b/src/nvim/vim_defs.h
@@ -6,20 +6,10 @@
#define SYS_OPTWIN_FILE "$VIMRUNTIME/optwin.vim"
#define RUNTIME_DIRNAME "runtime"
-#include "auto/config.h"
-
-// Check if configure correctly managed to find sizeof(int). If this failed,
-// it becomes zero. This is likely a problem of not being able to run the
-// test program. Other items from configure may also be wrong then!
-#if (SIZEOF_INT == 0)
-# error Configure did not run properly.
-#endif
-
-// bring lots of system header files
-#include "nvim/os/os_defs.h" // IWYU pragma: keep
-
-/// length of a buffer to store a number in ASCII (64 bits binary + NUL)
-enum { NUMBUFLEN = 65, };
+enum {
+ /// length of a buffer to store a number in ASCII (64 bits binary + NUL)
+ NUMBUFLEN = 65,
+};
#define MAX_TYPENR 65535
@@ -32,6 +22,38 @@ typedef enum {
BACKWARD_FILE = -3,
} Direction;
+/// Used to track the status of external functions.
+/// Currently only used for iconv().
+typedef enum {
+ kUnknown,
+ kWorking,
+ kBroken,
+} WorkingStatus;
+
+/// The scope of a working-directory command like `:cd`.
+///
+/// Scopes are enumerated from lowest to highest. When adding a scope make sure
+/// to update all functions using scopes as well, such as the implementation of
+/// `getcwd()`. When using scopes as limits (e.g. in loops) don't use the scopes
+/// directly, use `MIN_CD_SCOPE` and `MAX_CD_SCOPE` instead.
+typedef enum {
+ kCdScopeInvalid = -1,
+ kCdScopeWindow, ///< Affects one window.
+ kCdScopeTabpage, ///< Affects one tab page.
+ kCdScopeGlobal, ///< Affects the entire Nvim instance.
+} CdScope;
+
+#define MIN_CD_SCOPE kCdScopeWindow
+#define MAX_CD_SCOPE kCdScopeGlobal
+
+/// What caused the current directory to change.
+typedef enum {
+ kCdCauseOther = -1,
+ kCdCauseManual, ///< Using `:cd`, `:tcd`, `:lcd` or `chdir()`.
+ kCdCauseWindow, ///< Switching to another window.
+ kCdCauseAuto, ///< On 'autochdir'.
+} CdCause;
+
// return values for functions
#if !(defined(OK) && (OK == 1))
// OK already defined to 1 in MacOS X curses, skip this
diff --git a/src/nvim/viml/parser/expressions.c b/src/nvim/viml/parser/expressions.c
index 8b637fbb9b..3403fb7926 100644
--- a/src/nvim/viml/parser/expressions.c
+++ b/src/nvim/viml/parser/expressions.c
@@ -59,8 +59,7 @@
#include "nvim/assert_defs.h"
#include "nvim/charset.h"
#include "nvim/eval.h"
-#include "nvim/func_attr.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
#include "nvim/mbyte.h"
diff --git a/src/nvim/viml/parser/expressions.h b/src/nvim/viml/parser/expressions.h
index 94287ea4e1..ba54c4de07 100644
--- a/src/nvim/viml/parser/expressions.h
+++ b/src/nvim/viml/parser/expressions.h
@@ -6,9 +6,7 @@
#include "nvim/eval/typval_defs.h"
#include "nvim/types_defs.h"
-#include "nvim/viml/parser/parser.h"
-
-struct expr_ast_node;
+#include "nvim/viml/parser/parser_defs.h"
// Defines whether to ignore case:
// == kCCStrategyUseOption
diff --git a/src/nvim/viml/parser/parser.c b/src/nvim/viml/parser/parser.c
index b854aedca6..bdade3fae2 100644
--- a/src/nvim/viml/parser/parser.c
+++ b/src/nvim/viml/parser/parser.c
@@ -1,3 +1,6 @@
+#include "nvim/func_attr.h"
+#include "nvim/mbyte.h"
+#include "nvim/memory.h"
#include "nvim/viml/parser/parser.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -5,8 +8,68 @@
#endif
void parser_simple_get_line(void *cookie, ParserLine *ret_pline)
+ FUNC_ATTR_NONNULL_ALL
{
ParserLine **plines_p = (ParserLine **)cookie;
*ret_pline = **plines_p;
(*plines_p)++;
}
+
+/// Get currently parsed line, shifted to pstate->pos.col
+///
+/// @param pstate Parser state to operate on.
+///
+/// @return True if there is a line, false in case of EOF.
+bool viml_parser_get_remaining_line(ParserState *const pstate, ParserLine *const ret_pline)
+ FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL
+{
+ const size_t num_lines = kv_size(pstate->reader.lines);
+ if (pstate->pos.line == num_lines) {
+ viml_preader_get_line(&pstate->reader, ret_pline);
+ } else {
+ *ret_pline = kv_last(pstate->reader.lines);
+ }
+ assert(pstate->pos.line == kv_size(pstate->reader.lines) - 1);
+ if (ret_pline->data != NULL) {
+ ret_pline->data += pstate->pos.col;
+ ret_pline->size -= pstate->pos.col;
+ }
+ return ret_pline->data != NULL;
+}
+
+/// Get one line from ParserInputReader
+static void viml_preader_get_line(ParserInputReader *const preader, ParserLine *const ret_pline)
+ FUNC_ATTR_NONNULL_ALL
+{
+ ParserLine pline;
+ preader->get_line(preader->cookie, &pline);
+ if (preader->conv.vc_type != CONV_NONE && pline.size) {
+ ParserLine cpline = {
+ .allocated = true,
+ .size = pline.size,
+ };
+ cpline.data = string_convert(&preader->conv, (char *)pline.data, &cpline.size);
+ if (pline.allocated) {
+ xfree((void *)pline.data);
+ }
+ pline = cpline;
+ }
+ kvi_push(preader->lines, pline);
+ *ret_pline = pline;
+}
+
+/// Free all memory allocated by the parser on heap
+///
+/// @param pstate Parser state to free.
+void viml_parser_destroy(ParserState *const pstate)
+ FUNC_ATTR_NONNULL_ALL
+{
+ for (size_t i = 0; i < kv_size(pstate->reader.lines); i++) {
+ ParserLine pline = kv_A(pstate->reader.lines, i);
+ if (pline.allocated) {
+ xfree((void *)pline.data);
+ }
+ }
+ kvi_destroy(pstate->reader.lines);
+ kvi_destroy(pstate->stack);
+}
diff --git a/src/nvim/viml/parser/parser.h b/src/nvim/viml/parser/parser.h
index cd5a493643..31decdc798 100644
--- a/src/nvim/viml/parser/parser.h
+++ b/src/nvim/viml/parser/parser.h
@@ -6,80 +6,8 @@
#include "klib/kvec.h"
#include "nvim/func_attr.h"
-#include "nvim/mbyte.h"
#include "nvim/mbyte_defs.h"
-#include "nvim/memory.h"
-
-/// One parsed line
-typedef struct {
- const char *data; ///< Parsed line pointer
- size_t size; ///< Parsed line size
- bool allocated; ///< True if line may be freed.
-} ParserLine;
-
-/// Line getter type for parser
-///
-/// Line getter must return {NULL, 0} for EOF.
-typedef void (*ParserLineGetter)(void *cookie, ParserLine *ret_pline);
-
-/// Parser position in the input
-typedef struct {
- size_t line; ///< Line index in ParserInputReader.lines.
- size_t col; ///< Byte index in the line.
-} ParserPosition;
-
-/// Parser state item.
-typedef struct {
- enum {
- kPTopStateParsingCommand = 0,
- kPTopStateParsingExpression,
- } type;
- union {
- struct {
- enum {
- kExprUnknown = 0,
- } type;
- } expr;
- } data;
-} ParserStateItem;
-
-/// Structure defining input reader
-typedef struct {
- /// Function used to get next line.
- ParserLineGetter get_line;
- /// Data for get_line function.
- void *cookie;
- /// All lines obtained by get_line.
- kvec_withinit_t(ParserLine, 4) lines;
- /// Conversion, for :scriptencoding.
- vimconv_T conv;
-} ParserInputReader;
-
-/// Highlighted region definition
-///
-/// Note: one chunk may highlight only one line.
-typedef struct {
- ParserPosition start; ///< Start of the highlight: line and column.
- size_t end_col; ///< End column, points to the start of the next character.
- const char *group; ///< Highlight group.
-} ParserHighlightChunk;
-
-/// Highlighting defined by a parser
-typedef kvec_withinit_t(ParserHighlightChunk, 16) ParserHighlight;
-
-/// Structure defining parser state
-typedef struct {
- /// Line reader.
- ParserInputReader reader;
- /// Position up to which input was parsed.
- ParserPosition pos;
- /// Parser state stack.
- kvec_withinit_t(ParserStateItem, 16) stack;
- /// Highlighting support.
- ParserHighlight *colors;
- /// True if line continuation can be used.
- bool can_continuate;
-} ParserState;
+#include "nvim/viml/parser/parser_defs.h" // IWYU pragma: keep
static inline void viml_parser_init(ParserState *ret_pstate, ParserLineGetter get_line,
void *cookie, ParserHighlight *colors)
@@ -109,73 +37,6 @@ static inline void viml_parser_init(ParserState *const ret_pstate, const ParserL
kvi_init(ret_pstate->stack);
}
-static inline void viml_parser_destroy(ParserState *pstate)
- REAL_FATTR_NONNULL_ALL REAL_FATTR_ALWAYS_INLINE;
-
-/// Free all memory allocated by the parser on heap
-///
-/// @param pstate Parser state to free.
-static inline void viml_parser_destroy(ParserState *const pstate)
-{
- for (size_t i = 0; i < kv_size(pstate->reader.lines); i++) {
- ParserLine pline = kv_A(pstate->reader.lines, i);
- if (pline.allocated) {
- xfree((void *)pline.data);
- }
- }
- kvi_destroy(pstate->reader.lines);
- kvi_destroy(pstate->stack);
-}
-
-static inline void viml_preader_get_line(ParserInputReader *preader, ParserLine *ret_pline)
- REAL_FATTR_NONNULL_ALL;
-
-/// Get one line from ParserInputReader
-static inline void viml_preader_get_line(ParserInputReader *const preader,
- ParserLine *const ret_pline)
-{
- ParserLine pline;
- preader->get_line(preader->cookie, &pline);
- if (preader->conv.vc_type != CONV_NONE && pline.size) {
- ParserLine cpline = {
- .allocated = true,
- .size = pline.size,
- };
- cpline.data = string_convert(&preader->conv, (char *)pline.data, &cpline.size);
- if (pline.allocated) {
- xfree((void *)pline.data);
- }
- pline = cpline;
- }
- kvi_push(preader->lines, pline);
- *ret_pline = pline;
-}
-
-static inline bool viml_parser_get_remaining_line(ParserState *pstate, ParserLine *ret_pline)
- REAL_FATTR_ALWAYS_INLINE REAL_FATTR_WARN_UNUSED_RESULT REAL_FATTR_NONNULL_ALL;
-
-/// Get currently parsed line, shifted to pstate->pos.col
-///
-/// @param pstate Parser state to operate on.
-///
-/// @return True if there is a line, false in case of EOF.
-static inline bool viml_parser_get_remaining_line(ParserState *const pstate,
- ParserLine *const ret_pline)
-{
- const size_t num_lines = kv_size(pstate->reader.lines);
- if (pstate->pos.line == num_lines) {
- viml_preader_get_line(&pstate->reader, ret_pline);
- } else {
- *ret_pline = kv_last(pstate->reader.lines);
- }
- assert(pstate->pos.line == kv_size(pstate->reader.lines) - 1);
- if (ret_pline->data != NULL) {
- ret_pline->data += pstate->pos.col;
- ret_pline->size -= pstate->pos.col;
- }
- return ret_pline->data != NULL;
-}
-
static inline void viml_parser_advance(ParserState *pstate, size_t len)
REAL_FATTR_ALWAYS_INLINE REAL_FATTR_NONNULL_ALL;
diff --git a/src/nvim/viml/parser/parser_defs.h b/src/nvim/viml/parser/parser_defs.h
new file mode 100644
index 0000000000..59fab23054
--- /dev/null
+++ b/src/nvim/viml/parser/parser_defs.h
@@ -0,0 +1,79 @@
+#pragma once
+
+#include <assert.h>
+#include <stdbool.h>
+#include <stddef.h>
+
+#include "klib/kvec.h"
+#include "nvim/mbyte_defs.h"
+
+/// One parsed line
+typedef struct {
+ const char *data; ///< Parsed line pointer
+ size_t size; ///< Parsed line size
+ bool allocated; ///< True if line may be freed.
+} ParserLine;
+
+/// Line getter type for parser
+///
+/// Line getter must return {NULL, 0} for EOF.
+typedef void (*ParserLineGetter)(void *cookie, ParserLine *ret_pline);
+
+/// Parser position in the input
+typedef struct {
+ size_t line; ///< Line index in ParserInputReader.lines.
+ size_t col; ///< Byte index in the line.
+} ParserPosition;
+
+/// Parser state item.
+typedef struct {
+ enum {
+ kPTopStateParsingCommand = 0,
+ kPTopStateParsingExpression,
+ } type;
+ union {
+ struct {
+ enum {
+ kExprUnknown = 0,
+ } type;
+ } expr;
+ } data;
+} ParserStateItem;
+
+/// Structure defining input reader
+typedef struct {
+ /// Function used to get next line.
+ ParserLineGetter get_line;
+ /// Data for get_line function.
+ void *cookie;
+ /// All lines obtained by get_line.
+ kvec_withinit_t(ParserLine, 4) lines;
+ /// Conversion, for :scriptencoding.
+ vimconv_T conv;
+} ParserInputReader;
+
+/// Highlighted region definition
+///
+/// Note: one chunk may highlight only one line.
+typedef struct {
+ ParserPosition start; ///< Start of the highlight: line and column.
+ size_t end_col; ///< End column, points to the start of the next character.
+ const char *group; ///< Highlight group.
+} ParserHighlightChunk;
+
+/// Highlighting defined by a parser
+typedef kvec_withinit_t(ParserHighlightChunk, 16) ParserHighlight;
+
+/// Structure defining parser state
+typedef struct {
+ /// Line reader.
+ ParserInputReader reader;
+ /// Position up to which input was parsed.
+ ParserPosition pos;
+ /// Parser state stack.
+ kvec_withinit_t(ParserStateItem, 16) stack;
+ /// Highlighting support.
+ ParserHighlight *colors;
+ /// True if line continuation can be used.
+ bool can_continuate;
+} ParserState;
diff --git a/src/nvim/vvars.lua b/src/nvim/vvars.lua
new file mode 100644
index 0000000000..37cb70c725
--- /dev/null
+++ b/src/nvim/vvars.lua
@@ -0,0 +1,885 @@
+local M = {}
+
+M.vars = {
+ argv = {
+ type = 'string[]',
+ desc = [=[
+ The command line arguments Vim was invoked with. This is a
+ list of strings. The first item is the Vim command.
+ See |v:progpath| for the command with full path.
+ ]=],
+ },
+ char = {
+ desc = [=[
+ Argument for evaluating 'formatexpr' and used for the typed
+ character when using <expr> in an abbreviation |:map-<expr>|.
+ It is also used by the |InsertCharPre| and |InsertEnter| events.
+ ]=],
+ },
+ charconvert_from = {
+ type = 'string',
+ desc = [=[
+ The name of the character encoding of a file to be converted.
+ Only valid while evaluating the 'charconvert' option.
+ ]=],
+ },
+ charconvert_to = {
+ type = 'string',
+ desc = [=[
+ The name of the character encoding of a file after conversion.
+ Only valid while evaluating the 'charconvert' option.
+ ]=],
+ },
+ cmdarg = {
+ type = 'string',
+ desc = [=[
+ The extra arguments ("++p", "++enc=", "++ff=") given to a file
+ read/write command. This is set before an autocommand event
+ for a file read/write command is triggered. There is a
+ leading space to make it possible to append this variable
+ directly after the read/write command. Note: "+cmd" isn't
+ included here, because it will be executed anyway.
+ ]=],
+ },
+ collate = {
+ type = 'string',
+ desc = [=[
+ The current locale setting for collation order of the runtime
+ environment. This allows Vim scripts to be aware of the
+ current locale encoding. Technical: it's the value of
+ LC_COLLATE. When not using a locale the value is "C".
+ This variable can not be set directly, use the |:language|
+ command.
+ See |multi-lang|.
+ ]=],
+ },
+ cmdbang = {
+ type = 'integer',
+ desc = [=[
+ Set like v:cmdarg for a file read/write command. When a "!"
+ was used the value is 1, otherwise it is 0. Note that this
+ can only be used in autocommands. For user commands |<bang>|
+ can be used.
+ ]=],
+ },
+ completed_item = {
+ desc = [=[
+ Dictionary containing the most recent |complete-items| after
+ |CompleteDone|. Empty if the completion failed, or after
+ leaving and re-entering insert mode.
+ Note: Plugins can modify the value to emulate the builtin
+ |CompleteDone| event behavior.
+ ]=],
+ },
+ count = {
+ type = 'integer',
+ desc = [=[
+ The count given for the last Normal mode command. Can be used
+ to get the count before a mapping. Read-only. Example: >vim
+ :map _x :<C-U>echo "the count is " .. v:count<CR>
+ <
+ Note: The <C-U> is required to remove the line range that you
+ get when typing ':' after a count.
+ When there are two counts, as in "3d2w", they are multiplied,
+ just like what happens in the command, "d6w" for the example.
+ Also used for evaluating the 'formatexpr' option.
+ ]=],
+ },
+ count1 = {
+ type = 'integer',
+ desc = [=[
+ Just like "v:count", but defaults to one when no count is
+ used.
+ ]=],
+ },
+ ctype = {
+ desc = [=[
+ The current locale setting for characters of the runtime
+ environment. This allows Vim scripts to be aware of the
+ current locale encoding. Technical: it's the value of
+ LC_CTYPE. When not using a locale the value is "C".
+ This variable can not be set directly, use the |:language|
+ command.
+ See |multi-lang|.
+ ]=],
+ },
+ dying = {
+ type = 'integer',
+ desc = [=[
+ Normally zero. When a deadly signal is caught it's set to
+ one. When multiple signals are caught the number increases.
+ Can be used in an autocommand to check if Vim didn't
+ terminate normally.
+ Example: >vim
+ :au VimLeave * if v:dying | echo "\nAAAAaaaarrrggghhhh!!!\n" | endif
+ <
+ Note: if another deadly signal is caught when v:dying is one,
+ VimLeave autocommands will not be executed.
+ ]=],
+ },
+ exiting = {
+ desc = [=[
+ Exit code, or |v:null| before invoking the |VimLeavePre|
+ and |VimLeave| autocmds. See |:q|, |:x| and |:cquit|.
+ Example: >vim
+ :au VimLeave * echo "Exit value is " .. v:exiting
+ <
+ ]=],
+ },
+ echospace = {
+ type = 'integer',
+ desc = [=[
+ Number of screen cells that can be used for an `:echo` message
+ in the last screen line before causing the |hit-enter-prompt|.
+ Depends on 'showcmd', 'ruler' and 'columns'. You need to
+ check 'cmdheight' for whether there are full-width lines
+ available above the last line.
+ ]=],
+ },
+ errmsg = {
+ type = 'string',
+ desc = [=[
+ Last given error message.
+ Modifiable (can be set).
+ Example: >vim
+ let v:errmsg = ""
+ silent! next
+ if v:errmsg != ""
+ " ... handle error
+ <
+ ]=],
+ },
+ errors = {
+ type = 'string[]',
+ tags = { 'assert-return' },
+ desc = [=[
+ Errors found by assert functions, such as |assert_true()|.
+ This is a list of strings.
+ The assert functions append an item when an assert fails.
+ The return value indicates this: a one is returned if an item
+ was added to v:errors, otherwise zero is returned.
+ To remove old results make it empty: >vim
+ let v:errors = []
+ <
+ If v:errors is set to anything but a list it is made an empty
+ list by the assert function.
+ ]=],
+ },
+ event = {
+ desc = [=[
+ Dictionary of event data for the current |autocommand|. Valid
+ only during the event lifetime; storing or passing v:event is
+ invalid! Copy it instead: >vim
+ au TextYankPost * let g:foo = deepcopy(v:event)
+ <
+ Keys vary by event; see the documentation for the specific
+ event, e.g. |DirChanged| or |TextYankPost|.
+ KEY DESCRIPTION ~
+ abort Whether the event triggered during
+ an aborting condition (e.g. |c_Esc| or
+ |c_CTRL-C| for |CmdlineLeave|).
+ chan |channel-id|
+ cmdlevel Level of cmdline.
+ cmdtype Type of cmdline, |cmdline-char|.
+ cwd Current working directory.
+ inclusive Motion is |inclusive|, else exclusive.
+ scope Event-specific scope name.
+ operator Current |operator|. Also set for Ex
+ commands (unlike |v:operator|). For
+ example if |TextYankPost| is triggered
+ by the |:yank| Ex command then
+ `v:event.operator` is "y".
+ regcontents Text stored in the register as a
+ |readfile()|-style list of lines.
+ regname Requested register (e.g "x" for "xyy)
+ or the empty string for an unnamed
+ operation.
+ regtype Type of register as returned by
+ |getregtype()|.
+ visual Selection is visual (as opposed to,
+ e.g., via motion).
+ completed_item Current selected complete item on
+ |CompleteChanged|, Is `{}` when no complete
+ item selected.
+ height Height of popup menu on |CompleteChanged|
+ width Width of popup menu on |CompleteChanged|
+ row Row count of popup menu on |CompleteChanged|,
+ relative to screen.
+ col Col count of popup menu on |CompleteChanged|,
+ relative to screen.
+ size Total number of completion items on
+ |CompleteChanged|.
+ scrollbar Is |v:true| if popup menu have scrollbar, or
+ |v:false| if not.
+ changed_window Is |v:true| if the event fired while
+ changing window (or tab) on |DirChanged|.
+ status Job status or exit code, -1 means "unknown". |TermClose|
+ ]=],
+ },
+ exception = {
+ type = 'string',
+ desc = [=[
+ The value of the exception most recently caught and not
+ finished. See also |v:throwpoint| and |throw-variables|.
+ Example: >vim
+ try
+ throw "oops"
+ catch /.*/
+ echo "caught " .. v:exception
+ endtry
+ <
+ Output: "caught oops".
+ ]=],
+ },
+ ['false'] = {
+ type = 'boolean',
+ desc = [=[
+ Special value used to put "false" in JSON and msgpack. See
+ |json_encode()|. This value is converted to "v:false" when used
+ as a String (e.g. in |expr5| with string concatenation
+ operator) and to zero when used as a Number (e.g. in |expr5|
+ or |expr7| when used with numeric operators). Read-only.
+ ]=],
+ },
+ fcs_reason = {
+ type = 'string',
+ desc = [=[
+ The reason why the |FileChangedShell| event was triggered.
+ Can be used in an autocommand to decide what to do and/or what
+ to set v:fcs_choice to. Possible values:
+ deleted file no longer exists
+ conflict file contents, mode or timestamp was
+ changed and buffer is modified
+ changed file contents has changed
+ mode mode of file changed
+ time only file timestamp changed
+ ]=],
+ },
+ fcs_choice = {
+ type = 'string',
+ desc = [=[
+ What should happen after a |FileChangedShell| event was
+ triggered. Can be used in an autocommand to tell Vim what to
+ do with the affected buffer:
+ reload Reload the buffer (does not work if
+ the file was deleted).
+ edit Reload the buffer and detect the
+ values for options such as
+ 'fileformat', 'fileencoding', 'binary'
+ (does not work if the file was
+ deleted).
+ ask Ask the user what to do, as if there
+ was no autocommand. Except that when
+ only the timestamp changed nothing
+ will happen.
+ <empty> Nothing, the autocommand should do
+ everything that needs to be done.
+ The default is empty. If another (invalid) value is used then
+ Vim behaves like it is empty, there is no warning message.
+ ]=],
+ },
+ fname = {
+ type = 'string',
+ desc = [=[
+ When evaluating 'includeexpr': the file name that was
+ detected. Empty otherwise.
+ ]=],
+ },
+ fname_in = {
+ type = 'string',
+ desc = [=[
+ The name of the input file. Valid while evaluating:
+ option used for ~
+ 'charconvert' file to be converted
+ 'diffexpr' original file
+ 'patchexpr' original file
+ And set to the swap file name for |SwapExists|.
+ ]=],
+ },
+ fname_out = {
+ type = 'string',
+ desc = [=[
+ The name of the output file. Only valid while
+ evaluating:
+ option used for ~
+ 'charconvert' resulting converted file [1]
+ 'diffexpr' output of diff
+ 'patchexpr' resulting patched file
+ [1] When doing conversion for a write command (e.g., ":w
+ file") it will be equal to v:fname_in. When doing conversion
+ for a read command (e.g., ":e file") it will be a temporary
+ file and different from v:fname_in.
+ ]=],
+ },
+ fname_new = {
+ type = 'string',
+ desc = [=[
+ The name of the new version of the file. Only valid while
+ evaluating 'diffexpr'.
+ ]=],
+ },
+ fname_diff = {
+ type = 'string',
+ desc = [=[
+ The name of the diff (patch) file. Only valid while
+ evaluating 'patchexpr'.
+ ]=],
+ },
+ folddashes = {
+ type = 'string',
+ desc = [=[
+ Used for 'foldtext': dashes representing foldlevel of a closed
+ fold.
+ Read-only in the |sandbox|. |fold-foldtext|
+ ]=],
+ },
+ foldlevel = {
+ type = 'integer',
+ desc = [=[
+ Used for 'foldtext': foldlevel of closed fold.
+ Read-only in the |sandbox|. |fold-foldtext|
+ ]=],
+ },
+ foldend = {
+ type = 'integer',
+ desc = [=[
+ Used for 'foldtext': last line of closed fold.
+ Read-only in the |sandbox|. |fold-foldtext|
+ ]=],
+ },
+ foldstart = {
+ type = 'integer',
+ desc = [=[
+ Used for 'foldtext': first line of closed fold.
+ Read-only in the |sandbox|. |fold-foldtext|
+ ]=],
+ },
+ hlsearch = {
+ type = 'integer',
+ desc = [=[
+ Variable that indicates whether search highlighting is on.
+ Setting it makes sense only if 'hlsearch' is enabled. Setting
+ this variable to zero acts like the |:nohlsearch| command,
+ setting it to one acts like >vim
+ let &hlsearch = &hlsearch
+ <
+ Note that the value is restored when returning from a
+ function. |function-search-undo|.
+ ]=],
+ },
+ insertmode = {
+ type = 'string',
+ desc = [=[
+ Used for the |InsertEnter| and |InsertChange| autocommand
+ events. Values:
+ i Insert mode
+ r Replace mode
+ v Virtual Replace mode
+ ]=],
+ },
+ key = {
+ type = 'string',
+ desc = [=[
+ Key of the current item of a |Dictionary|. Only valid while
+ evaluating the expression used with |map()| and |filter()|.
+ Read-only.
+ ]=],
+ },
+ lang = {
+ type = 'string',
+ desc = [=[
+ The current locale setting for messages of the runtime
+ environment. This allows Vim scripts to be aware of the
+ current language. Technical: it's the value of LC_MESSAGES.
+ The value is system dependent.
+ This variable can not be set directly, use the |:language|
+ command.
+ It can be different from |v:ctype| when messages are desired
+ in a different language than what is used for character
+ encoding. See |multi-lang|.
+ ]=],
+ },
+ lc_time = {
+ type = 'string',
+ desc = [=[
+ The current locale setting for time messages of the runtime
+ environment. This allows Vim scripts to be aware of the
+ current language. Technical: it's the value of LC_TIME.
+ This variable can not be set directly, use the |:language|
+ command. See |multi-lang|.
+ ]=],
+ },
+ lnum = {
+ type = 'integer',
+ desc = [=[
+ Line number for the 'foldexpr' |fold-expr|, 'formatexpr',
+ 'indentexpr' and 'statuscolumn' expressions, tab page number
+ for 'guitablabel' and 'guitabtooltip'. Only valid while one of
+ these expressions is being evaluated. Read-only when in the
+ |sandbox|.
+ ]=],
+ },
+ lua = {
+ desc = [=[
+ Prefix for calling Lua functions from expressions.
+ See |v:lua-call| for more information.
+ ]=],
+ },
+ maxcol = {
+ type = 'integer',
+ desc = [=[
+ Maximum line length. Depending on where it is used it can be
+ screen columns, characters or bytes. The value currently is
+ 2147483647 on all systems.
+ ]=],
+ },
+ mouse_win = {
+ type = 'integer',
+ desc = [=[
+ Window number for a mouse click obtained with |getchar()|.
+ First window has number 1, like with |winnr()|. The value is
+ zero when there was no mouse button click.
+ ]=],
+ },
+ mouse_winid = {
+ type = 'integer',
+ desc = [=[
+ |window-ID| for a mouse click obtained with |getchar()|.
+ The value is zero when there was no mouse button click.
+ ]=],
+ },
+ mouse_lnum = {
+ type = 'integer',
+ desc = [=[
+ Line number for a mouse click obtained with |getchar()|.
+ This is the text line number, not the screen line number. The
+ value is zero when there was no mouse button click.
+ ]=],
+ },
+ mouse_col = {
+ type = 'integer',
+ desc = [=[
+ Column number for a mouse click obtained with |getchar()|.
+ This is the screen column number, like with |virtcol()|. The
+ value is zero when there was no mouse button click.
+ ]=],
+ },
+ msgpack_types = {
+ desc = [=[
+ Dictionary containing msgpack types used by |msgpackparse()|
+ and |msgpackdump()|. All types inside dictionary are fixed
+ (not editable) empty lists. To check whether some list is one
+ of msgpack types, use |is| operator.
+ ]=],
+ },
+ null = {
+ type = 'vim.NIL',
+ desc = [=[
+ Special value used to put "null" in JSON and NIL in msgpack.
+ See |json_encode()|. This value is converted to "v:null" when
+ used as a String (e.g. in |expr5| with string concatenation
+ operator) and to zero when used as a Number (e.g. in |expr5|
+ or |expr7| when used with numeric operators). Read-only.
+ In some places `v:null` can be used for a List, Dict, etc.
+ that is not set. That is slightly different than an empty
+ List, Dict, etc.
+ ]=],
+ },
+ numbermax = {
+ type = 'integer',
+ desc = 'Maximum value of a number.',
+ },
+ numbermin = {
+ type = 'integer',
+ desc = 'Minimum value of a number (negative).',
+ },
+ numbersize = {
+ type = 'integer',
+ desc = [=[
+ Number of bits in a Number. This is normally 64, but on some
+ systems it may be 32.
+ ]=],
+ },
+ oldfiles = {
+ type = 'string[]',
+ desc = [=[
+ List of file names that is loaded from the |shada| file on
+ startup. These are the files that Vim remembers marks for.
+ The length of the List is limited by the ' argument of the
+ 'shada' option (default is 100).
+ When the |shada| file is not used the List is empty.
+ Also see |:oldfiles| and |c_#<|.
+ The List can be modified, but this has no effect on what is
+ stored in the |shada| file later. If you use values other
+ than String this will cause trouble.
+ ]=],
+ },
+ option_new = {
+ desc = [=[
+ New value of the option. Valid while executing an |OptionSet|
+ autocommand.
+ ]=],
+ },
+ option_old = {
+ desc = [=[
+ Old value of the option. Valid while executing an |OptionSet|
+ autocommand. Depending on the command used for setting and the
+ kind of option this is either the local old value or the
+ global old value.
+ ]=],
+ },
+ option_oldlocal = {
+ desc = [=[
+ Old local value of the option. Valid while executing an
+ |OptionSet| autocommand.
+ ]=],
+ },
+ option_oldglobal = {
+ desc = [=[
+ Old global value of the option. Valid while executing an
+ |OptionSet| autocommand.
+ ]=],
+ },
+ option_type = {
+ type = 'string',
+ desc = [=[
+ Scope of the set command. Valid while executing an
+ |OptionSet| autocommand. Can be either "global" or "local"
+ ]=],
+ },
+ option_command = {
+ type = 'string',
+ desc = [=[
+ Command used to set the option. Valid while executing an
+ |OptionSet| autocommand.
+ value option was set via ~
+ "setlocal" |:setlocal| or `:let l:xxx`
+ "setglobal" |:setglobal| or `:let g:xxx`
+ "set" |:set| or |:let|
+ "modeline" |modeline|
+ ]=],
+ },
+ operator = {
+ type = 'string',
+ desc = [=[
+ The last operator given in Normal mode. This is a single
+ character except for commands starting with <g> or <z>,
+ in which case it is two characters. Best used alongside
+ |v:prevcount| and |v:register|. Useful if you want to cancel
+ Operator-pending mode and then use the operator, e.g.: >vim
+ :omap O <Esc>:call MyMotion(v:operator)<CR>
+ <
+ The value remains set until another operator is entered, thus
+ don't expect it to be empty.
+ v:operator is not set for |:delete|, |:yank| or other Ex
+ commands.
+ Read-only.
+ ]=],
+ },
+ prevcount = {
+ type = 'integer',
+ desc = [=[
+ The count given for the last but one Normal mode command.
+ This is the v:count value of the previous command. Useful if
+ you want to cancel Visual or Operator-pending mode and then
+ use the count, e.g.: >vim
+ :vmap % <Esc>:call MyFilter(v:prevcount)<CR>
+ <
+ Read-only.
+ ]=],
+ },
+ profiling = {
+ type = 'integer',
+ desc = [=[
+ Normally zero. Set to one after using ":profile start".
+ See |profiling|.
+ ]=],
+ },
+ progname = {
+ type = 'string',
+ desc = [=[
+ The name by which Nvim was invoked (with path removed).
+ Read-only.
+ ]=],
+ },
+ progpath = {
+ type = 'string',
+ desc = [=[
+ Absolute path to the current running Nvim.
+ Read-only.
+ ]=],
+ },
+ register = {
+ type = 'string',
+ desc = [=[
+ The name of the register in effect for the current normal mode
+ command (regardless of whether that command actually used a
+ register). Or for the currently executing normal mode mapping
+ (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 '+'.
+ Also see |getreg()| and |setreg()|
+ ]=],
+ },
+ relnum = {
+ type = 'integer',
+ desc = [=[
+ Relative line number for the 'statuscolumn' expression.
+ Read-only.
+ ]=],
+ },
+ scrollstart = {
+ desc = [=[
+ String describing the script or function that caused the
+ screen to scroll up. It's only set when it is empty, thus the
+ first reason is remembered. It is set to "Unknown" for a
+ typed command.
+ This can be used to find out why your script causes the
+ hit-enter prompt.
+ ]=],
+ },
+ servername = {
+ type = 'string',
+ desc = [=[
+ Primary listen-address of Nvim, the first item returned by
+ |serverlist()|. Usually this is the named pipe created by Nvim
+ at |startup| or given by |--listen| (or the deprecated
+ |$NVIM_LISTEN_ADDRESS| env var).
+
+ See also |serverstart()| |serverstop()|.
+ Read-only.
+
+ *$NVIM*
+ $NVIM is set by |terminal| and |jobstart()|, and is thus
+ a hint that the current environment is a subprocess of Nvim.
+ Example: >vim
+ if $NVIM
+ echo nvim_get_chan_info(v:parent)
+ endif
+ <
+
+ Note the contents of $NVIM may change in the future.
+ ]=],
+ },
+ searchforward = {
+ type = 'integer',
+ desc = [=[
+ Search direction: 1 after a forward search, 0 after a
+ backward search. It is reset to forward when directly setting
+ the last search pattern, see |quote/|.
+ Note that the value is restored when returning from a
+ function. |function-search-undo|.
+ Read-write.
+ ]=],
+ },
+ shell_error = {
+ type = 'integer',
+ desc = [=[
+ Result of the last shell command. When non-zero, the last
+ shell command had an error. When zero, there was no problem.
+ This only works when the shell returns the error code to Vim.
+ The value -1 is often used when the command could not be
+ executed. Read-only.
+ Example: >vim
+ !mv foo bar
+ if v:shell_error
+ echo 'could not rename "foo" to "bar"!'
+ endif
+ <
+ ]=],
+ },
+ statusmsg = {
+ type = 'string',
+ desc = [=[
+ Last given status message.
+ Modifiable (can be set).
+ ]=],
+ },
+ stderr = {
+ type = 'integer',
+ desc = [=[
+ |channel-id| corresponding to stderr. The value is always 2;
+ use this variable to make your code more descriptive.
+ Unlike stdin and stdout (see |stdioopen()|), stderr is always
+ open for writing. Example: >vim
+ :call chansend(v:stderr, "error: toaster empty\n")
+ <
+ ]=],
+ },
+ swapname = {
+ type = 'string',
+ desc = [=[
+ Name of the swapfile found.
+ Only valid during |SwapExists| event.
+ Read-only.
+ ]=],
+ },
+ swapchoice = {
+ type = 'string',
+ desc = [=[
+ |SwapExists| autocommands can set this to the selected choice
+ for handling an existing swapfile:
+ 'o' Open read-only
+ 'e' Edit anyway
+ 'r' Recover
+ 'd' Delete swapfile
+ 'q' Quit
+ 'a' Abort
+ The value should be a single-character string. An empty value
+ results in the user being asked, as would happen when there is
+ no SwapExists autocommand. The default is empty.
+ ]=],
+ },
+ swapcommand = {
+ type = 'string',
+ desc = [=[
+ Normal mode command to be executed after a file has been
+ opened. Can be used for a |SwapExists| autocommand to have
+ another Vim open the file and jump to the right place. For
+ example, when jumping to a tag the value is ":tag tagname\r".
+ For ":edit +cmd file" the value is ":cmd\r".
+ ]=],
+ },
+ t_blob = {
+ type = 'integer',
+ tags = { 'v:t_TYPE' },
+ desc = 'Value of |Blob| type. Read-only. See: |type()|',
+ },
+ t_bool = {
+ type = 'integer',
+ desc = 'Value of |Boolean| type. Read-only. See: |type()|',
+ },
+ t_dict = {
+ type = 'integer',
+ desc = 'Value of |Dictionary| type. Read-only. See: |type()|',
+ },
+ t_float = {
+ type = 'integer',
+ desc = 'Value of |Float| type. Read-only. See: |type()|',
+ },
+ t_func = {
+ type = 'integer',
+ desc = 'Value of |Funcref| type. Read-only. See: |type()|',
+ },
+ t_list = {
+ type = 'integer',
+ desc = 'Value of |List| type. Read-only. See: |type()|',
+ },
+ t_number = {
+ type = 'integer',
+ desc = 'Value of |Number| type. Read-only. See: |type()|',
+ },
+ t_string = {
+ type = 'integer',
+ desc = 'Value of |String| type. Read-only. See: |type()|',
+ },
+ termresponse = {
+ type = 'string',
+ desc = [=[
+ The value of the most recent OSC or DCS control sequence
+ received by Nvim from the terminal. This can be read in a
+ |TermResponse| event handler after querying the terminal using
+ another escape sequence.
+ ]=],
+ },
+ termrequest = {
+ type = 'string',
+ desc = [=[
+ The value of the most recent OSC or DCS control sequence
+ sent from a process running in the embedded |terminal|.
+ This can be read in a |TermRequest| event handler to respond
+ to queries from embedded applications.
+ ]=],
+ },
+ testing = {
+ desc = [=[
+ Must be set before using `test_garbagecollect_now()`.
+ ]=],
+ },
+ this_session = {
+ desc = [=[
+ Full filename of the last loaded or saved session file.
+ Empty when no session file has been saved. See |:mksession|.
+ Modifiable (can be set).
+ ]=],
+ },
+ throwpoint = {
+ desc = [=[
+ The point where the exception most recently caught and not
+ finished was thrown. Not set when commands are typed. See
+ also |v:exception| and |throw-variables|.
+ Example: >vim
+ try
+ throw "oops"
+ catch /.*/
+ echo "Exception from" v:throwpoint
+ endtry
+ <
+ Output: "Exception from test.vim, line 2"
+ ]=],
+ },
+ ['true'] = {
+ type = 'boolean',
+ desc = [=[
+ Special value used to put "true" in JSON and msgpack. See
+ |json_encode()|. This value is converted to "v:true" when used
+ as a String (e.g. in |expr5| with string concatenation
+ operator) and to one when used as a Number (e.g. in |expr5| or
+ |expr7| when used with numeric operators). Read-only.
+ ]=],
+ },
+ val = {
+ desc = [=[
+ Value of the current item of a |List| or |Dictionary|. Only
+ valid while evaluating the expression used with |map()| and
+ |filter()|. Read-only.
+ ]=],
+ },
+ version = {
+ type = 'integer',
+ desc = [=[
+ Vim version number: major version times 100 plus minor
+ version. Vim 5.0 is 500, Vim 5.1 is 501.
+ Read-only.
+ Use |has()| to check the Nvim (not Vim) version: >vim
+ :if has("nvim-0.2.1")
+ <
+ ]=],
+ },
+ virtnum = {
+ type = 'integer',
+ desc = [=[
+ Virtual line number for the 'statuscolumn' expression.
+ Negative when drawing the status column for virtual lines, zero
+ when drawing an actual buffer line, and positive when drawing
+ the wrapped part of a buffer line.
+ Read-only.
+ ]=],
+ },
+ vim_did_enter = {
+ type = 'integer',
+ desc = [=[
+ 0 during startup, 1 just before |VimEnter|.
+ Read-only.
+ ]=],
+ },
+ warningmsg = {
+ type = 'string',
+ desc = [=[
+ Last given warning message.
+ Modifiable (can be set).
+ ]=],
+ },
+ windowid = {
+ type = 'integer',
+ desc = [=[
+ Application-specific window "handle" which may be set by any
+ attached UI. Defaults to zero.
+ Note: For Nvim |windows| use |winnr()| or |win_getid()|, see
+ |window-ID|.
+ ]=],
+ },
+}
+
+return M
diff --git a/src/nvim/window.c b/src/nvim/window.c
index bcf245ef93..e2c4524eaa 100644
--- a/src/nvim/window.c
+++ b/src/nvim/window.c
@@ -13,6 +13,7 @@
#include "nvim/arglist.h"
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
+#include "nvim/autocmd_defs.h"
#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/charset.h"
@@ -23,29 +24,32 @@
#include "nvim/edit.h"
#include "nvim/eval.h"
#include "nvim/eval/typval.h"
+#include "nvim/eval/typval_defs.h"
#include "nvim/eval/vars.h"
#include "nvim/eval/window.h"
#include "nvim/ex_cmds.h"
#include "nvim/ex_cmds2.h"
+#include "nvim/ex_cmds_defs.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_eval.h"
#include "nvim/ex_getln.h"
#include "nvim/file_search.h"
#include "nvim/fileio.h"
#include "nvim/fold.h"
-#include "nvim/func_attr.h"
#include "nvim/garray.h"
#include "nvim/getchar.h"
-#include "nvim/gettext.h"
+#include "nvim/gettext_defs.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/hashtab.h"
#include "nvim/keycodes.h"
#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/map_defs.h"
-#include "nvim/mapping.h" // IWYU pragma: keep (langmap_adjust_mb)
+#include "nvim/mapping.h"
#include "nvim/mark.h"
+#include "nvim/mark_defs.h"
#include "nvim/match.h"
#include "nvim/mbyte.h"
#include "nvim/memory.h"
@@ -57,12 +61,14 @@
#include "nvim/option_defs.h"
#include "nvim/option_vars.h"
#include "nvim/os/fs.h"
+#include "nvim/os/os_defs.h"
#include "nvim/path.h"
#include "nvim/plines.h"
#include "nvim/pos_defs.h"
#include "nvim/quickfix.h"
#include "nvim/search.h"
#include "nvim/state.h"
+#include "nvim/state_defs.h"
#include "nvim/statusline.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
@@ -70,6 +76,7 @@
#include "nvim/types_defs.h"
#include "nvim/ui.h"
#include "nvim/ui_compositor.h"
+#include "nvim/ui_defs.h"
#include "nvim/undo.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
@@ -191,7 +198,7 @@ void do_window(int nchar, int Prenum, int xchar)
if (bt_quickfix(curbuf)) {
goto newwindow;
}
- (void)win_split(Prenum, 0);
+ win_split(Prenum, 0);
break;
// split current window in two parts, vertically
@@ -204,7 +211,7 @@ void do_window(int nchar, int Prenum, int xchar)
if (bt_quickfix(curbuf)) {
goto newwindow;
}
- (void)win_split(Prenum, WSP_VERT);
+ win_split(Prenum, WSP_VERT);
break;
// split current window and edit alternate file
@@ -223,8 +230,8 @@ void do_window(int nchar, int Prenum, int xchar)
}
if (!curbuf_locked() && win_split(0, 0) == OK) {
- (void)buflist_getfile(Prenum == 0 ? curwin->w_alt_fnum : Prenum,
- 0, GETF_ALT, false);
+ buflist_getfile(Prenum == 0 ? curwin->w_alt_fnum : Prenum,
+ 0, GETF_ALT, false);
}
break;
@@ -321,13 +328,13 @@ newwindow:
wp = lastwin; // wrap around
}
while (wp != NULL && wp->w_floating
- && !wp->w_float_config.focusable) {
+ && !wp->w_config.focusable) {
wp = wp->w_prev;
}
} else { // go to next window
wp = curwin->w_next;
while (wp != NULL && wp->w_floating
- && !wp->w_float_config.focusable) {
+ && !wp->w_config.focusable) {
wp = wp->w_next;
}
if (wp == NULL) {
@@ -611,7 +618,7 @@ wingotofile:
LANGMAP_ADJUST(xchar, true);
no_mapping--;
allow_keys--;
- (void)add_to_showcmd(xchar);
+ add_to_showcmd(xchar);
switch (xchar) {
case '}':
@@ -662,7 +669,7 @@ wingotofile:
beep_flush();
break;
}
- FloatConfig config = FLOAT_CONFIG_INIT;
+ WinConfig config = WIN_CONFIG_INIT;
config.width = curwin->w_width;
config.height = curwin->w_height;
config.external = true;
@@ -706,7 +713,7 @@ void win_set_buf(win_T *win, buf_T *buf, bool noautocmd, Error *err)
}
switchwin_T switchwin;
- if (switch_win_noblock(&switchwin, win, tab, false) == FAIL) {
+ if (switch_win_noblock(&switchwin, win, tab, true) == FAIL) {
api_set_error(err,
kErrorTypeException,
"Failed to switch to window %d",
@@ -726,7 +733,7 @@ void win_set_buf(win_T *win, buf_T *buf, bool noautocmd, Error *err)
// So do it now.
validate_cursor();
- restore_win_noblock(&switchwin, false);
+ restore_win_noblock(&switchwin, true);
if (noautocmd) {
unblock_autocmds();
}
@@ -756,10 +763,11 @@ void ui_ext_win_position(win_T *wp, bool validate)
return;
}
- FloatConfig c = wp->w_float_config;
+ WinConfig c = wp->w_config;
if (!c.external) {
ScreenGrid *grid = &default_grid;
- Float row = c.row, col = c.col;
+ Float row = c.row;
+ Float col = c.col;
if (c.relative == kFloatRelativeWindow) {
Error dummy = ERROR_INIT;
win_T *win = find_window_by_handle(c.window, &dummy);
@@ -771,7 +779,8 @@ void ui_ext_win_position(win_T *wp, bool validate)
ui_ext_win_position(win, validate);
}
grid = &win->w_grid;
- int row_off = 0, col_off = 0;
+ int row_off = 0;
+ int col_off = 0;
grid_adjust(&grid, &row_off, &col_off);
row += row_off;
col += col_off;
@@ -785,9 +794,9 @@ void ui_ext_win_position(win_T *wp, bool validate)
}
}
- wp->w_grid_alloc.zindex = wp->w_float_config.zindex;
+ wp->w_grid_alloc.zindex = wp->w_config.zindex;
if (ui_has(kUIMultigrid)) {
- String anchor = cstr_as_string((char *)float_anchor_str[c.anchor]);
+ String anchor = cstr_as_string(float_anchor_str[c.anchor]);
if (!c.hide) {
ui_call_win_float_pos(wp->w_grid_alloc.handle, wp->handle, anchor,
grid->handle, row, col, c.focusable,
@@ -808,9 +817,10 @@ void ui_ext_win_position(win_T *wp, bool validate)
int comp_row = (int)row - (south ? wp->w_height_outer : 0);
int comp_col = (int)col - (east ? wp->w_width_outer : 0);
+ int above_ch = wp->w_config.zindex < kZIndexMessages ? (int)p_ch : 0;
comp_row += grid->comp_row;
comp_col += grid->comp_col;
- comp_row = MAX(MIN(comp_row, Rows - wp->w_height_outer - (p_ch > 0 ? 1 : 0)), 0);
+ comp_row = MAX(MIN(comp_row, Rows - wp->w_height_outer - above_ch), 0);
if (!c.fixed || east) {
comp_col = MAX(MIN(comp_col, Columns - wp->w_width_outer), 0);
}
@@ -821,7 +831,7 @@ void ui_ext_win_position(win_T *wp, bool validate)
ui_comp_put_grid(&wp->w_grid_alloc, comp_row, comp_col,
wp->w_height_outer, wp->w_width_outer, valid, false);
ui_check_cursor_grid(wp->w_grid_alloc.handle);
- wp->w_grid_alloc.focusable = wp->w_float_config.focusable;
+ wp->w_grid_alloc.focusable = wp->w_config.focusable;
if (!valid) {
wp->w_grid_alloc.valid = false;
redraw_later(wp, UPD_NOT_VALID);
@@ -919,6 +929,7 @@ static int check_split_disallowed(void)
// WSP_TOP: open window at the top-left of the screen (help window).
// WSP_BOT: open window at the bottom-right of the screen (quickfix window).
// WSP_HELP: creating the help window, keep layout snapshot
+// WSP_NOENTER: do not enter the new window or trigger WinNew autocommands
//
// return FAIL for failure, OK otherwise
int win_split(int size, int flags)
@@ -947,20 +958,20 @@ int win_split(int size, int flags)
clear_snapshot(curtab, SNAP_HELP_IDX);
}
- return win_split_ins(size, flags, NULL, 0);
+ return win_split_ins(size, flags, NULL, 0) == NULL ? FAIL : OK;
}
/// When "new_wp" is NULL: split the current window in two.
/// When "new_wp" is not NULL: insert this window at the far
/// top/left/right/bottom.
-/// @return FAIL for failure, OK otherwise
-int win_split_ins(int size, int flags, win_T *new_wp, int dir)
+/// @return NULL for failure, or pointer to new window
+win_T *win_split_ins(int size, int flags, win_T *new_wp, int dir)
{
win_T *wp = new_wp;
// aucmd_win[] should always remain floating
if (new_wp != NULL && is_aucmd_win(new_wp)) {
- return FAIL;
+ return NULL;
}
win_T *oldwin;
@@ -976,22 +987,24 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
int need_status = 0;
int new_size = size;
bool new_in_layout = (new_wp == NULL || new_wp->w_floating);
+ bool vertical = flags & WSP_VERT;
+ bool toplevel = flags & (WSP_TOP | WSP_BOT);
// add a status line when p_ls == 1 and splitting the first window
if (one_nonfloat() && p_ls == 1 && oldwin->w_status_height == 0) {
if (oldwin->w_height <= p_wmh && new_in_layout) {
emsg(_(e_noroom));
- return FAIL;
+ return NULL;
}
need_status = STATUS_HEIGHT;
}
bool do_equal = false;
int oldwin_height = 0;
- const int layout = flags & WSP_VERT ? FR_ROW : FR_COL;
+ const int layout = vertical ? FR_ROW : FR_COL;
bool did_set_fraction = false;
- if (flags & WSP_VERT) {
+ if (vertical) {
// Check if we are able to split the current window and compute its
// width.
// Current window requires at least 1 space.
@@ -1002,7 +1015,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
int minwidth;
int available;
- if (flags & (WSP_BOT | WSP_TOP)) {
+ if (toplevel) {
minwidth = frame_minwidth(topframe, NOWIN);
available = topframe->fr_width;
needed += minwidth;
@@ -1030,7 +1043,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
if (available < needed && new_in_layout) {
emsg(_(e_noroom));
- return FAIL;
+ return NULL;
}
if (new_size == 0) {
new_size = oldwin->w_width / 2;
@@ -1083,7 +1096,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
int minheight;
int available;
- if (flags & (WSP_BOT | WSP_TOP)) {
+ if (toplevel) {
minheight = frame_minheight(topframe, NOWIN) + need_status;
available = topframe->fr_height;
needed += minheight;
@@ -1110,7 +1123,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
if (available < needed && new_in_layout) {
emsg(_(e_noroom));
- return FAIL;
+ return NULL;
}
oldwin_height = oldwin->w_height;
if (need_status) {
@@ -1173,7 +1186,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
&& ((flags & WSP_BOT)
|| (flags & WSP_BELOW)
|| (!(flags & WSP_ABOVE)
- && ((flags & WSP_VERT) ? p_spr : p_sb)))) {
+ && (vertical ? p_spr : p_sb)))) {
// new window below/right of current one
if (new_wp == NULL) {
wp = win_alloc(oldwin, false);
@@ -1190,7 +1203,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
if (new_wp == NULL) {
if (wp == NULL) {
- return FAIL;
+ return NULL;
}
new_frame(wp);
@@ -1201,17 +1214,17 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
new_frame(wp);
wp->w_floating = false;
// non-floating window doesn't store float config or have a border.
- wp->w_float_config = FLOAT_CONFIG_INIT;
+ wp->w_config = WIN_CONFIG_INIT;
CLEAR_FIELD(wp->w_border_adj);
}
- int before;
+ bool before;
frame_T *curfrp;
// Reorganise the tree of frames to insert the new window.
- if (flags & (WSP_TOP | WSP_BOT)) {
- if ((topframe->fr_layout == FR_COL && (flags & WSP_VERT) == 0)
- || (topframe->fr_layout == FR_ROW && (flags & WSP_VERT) != 0)) {
+ if (toplevel) {
+ if ((topframe->fr_layout == FR_COL && !vertical)
+ || (topframe->fr_layout == FR_ROW && vertical)) {
curfrp = topframe->fr_child;
if (flags & WSP_BOT) {
while (curfrp->fr_next != NULL) {
@@ -1228,7 +1241,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
before = false;
} else if (flags & WSP_ABOVE) {
before = true;
- } else if (flags & WSP_VERT) {
+ } else if (vertical) {
before = !p_spr;
} else {
before = !p_sb;
@@ -1276,14 +1289,14 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
wp->w_fraction = oldwin->w_fraction;
- if (flags & WSP_VERT) {
+ if (vertical) {
wp->w_p_scr = curwin->w_p_scr;
if (need_status) {
win_new_height(oldwin, oldwin->w_height - 1);
oldwin->w_status_height = need_status;
}
- if (flags & (WSP_TOP | WSP_BOT)) {
+ if (toplevel) {
// set height and row of new window to full height
wp->w_winrow = tabline_height();
win_new_height(wp, curfrp->fr_height - (p_ls == 1 || p_ls == 2));
@@ -1307,7 +1320,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
wp->w_vsep_width = oldwin->w_vsep_width;
oldwin->w_vsep_width = 1;
}
- if (flags & (WSP_TOP | WSP_BOT)) {
+ if (toplevel) {
if (flags & WSP_BOT) {
frame_add_vsep(curfrp);
}
@@ -1329,7 +1342,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
} else {
const bool is_stl_global = global_stl_height() > 0;
// width and column of new window is same as current window
- if (flags & (WSP_TOP | WSP_BOT)) {
+ if (toplevel) {
wp->w_wincol = 0;
win_new_width(wp, Columns);
wp->w_vsep_width = 0;
@@ -1350,7 +1363,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
wp->w_hsep_height = oldwin->w_hsep_height;
oldwin->w_hsep_height = is_stl_global ? 1 : 0;
}
- if (flags & (WSP_TOP | WSP_BOT)) {
+ if (toplevel) {
int new_fr_height = curfrp->fr_height - new_size;
if (is_stl_global) {
if (flags & WSP_BOT) {
@@ -1396,8 +1409,8 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
frame_fix_height(oldwin);
}
- if (flags & (WSP_TOP | WSP_BOT)) {
- (void)win_comp_pos();
+ if (toplevel) {
+ win_comp_pos();
}
// Both windows need redrawing. Update all status lines, in case they
@@ -1417,7 +1430,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
// equalize the window sizes.
if (do_equal || dir != 0) {
- win_equal(wp, true, (flags & WSP_VERT) ? (dir == 'v' ? 'b' : 'h') : (dir == 'h' ? 'b' : 'v'));
+ win_equal(wp, true, vertical ? (dir == 'v' ? 'b' : 'h') : (dir == 'h' ? 'b' : 'v'));
} else if (!is_aucmd_win(wp)) {
win_fix_scroll(false);
}
@@ -1438,10 +1451,12 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
}
}
- // make the new window the current window
- win_enter_ext(wp, WEE_TRIGGER_NEW_AUTOCMDS | WEE_TRIGGER_ENTER_AUTOCMDS
- | WEE_TRIGGER_LEAVE_AUTOCMDS);
- if (flags & WSP_VERT) {
+ if (!(flags & WSP_NOENTER)) {
+ // make the new window the current window
+ win_enter_ext(wp, WEE_TRIGGER_NEW_AUTOCMDS | WEE_TRIGGER_ENTER_AUTOCMDS
+ | WEE_TRIGGER_LEAVE_AUTOCMDS);
+ }
+ if (vertical) {
p_wiw = i;
} else {
p_wh = i;
@@ -1452,7 +1467,7 @@ int win_split_ins(int size, int flags, win_T *new_wp, int dir)
oldwin->w_pos_changed = true;
}
- return OK;
+ return wp;
}
// Initialize window "newp" from window "oldp".
@@ -1548,7 +1563,7 @@ bool win_valid(const win_T *win) FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
/// Check if "win" is a pointer to an existing window in tabpage "tp".
///
/// @param win window to check
-static bool tabpage_win_valid(const tabpage_T *tp, const win_T *win)
+bool tabpage_win_valid(const tabpage_T *tp, const win_T *win)
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{
if (win == NULL) {
@@ -1745,7 +1760,7 @@ static void win_exchange(int Prenum)
frame_fix_width(curwin);
frame_fix_width(wp);
- (void)win_comp_pos(); // recompute window positions
+ win_comp_pos(); // recompute window positions
if (wp->w_buffer != curbuf) {
reset_VIsual_and_resel();
@@ -1832,7 +1847,7 @@ static void win_rotate(bool upwards, int count)
frame_fix_width(wp2);
// recompute w_winrow and w_wincol for all windows
- (void)win_comp_pos();
+ win_comp_pos();
}
wp1->w_pos_changed = true;
@@ -1869,14 +1884,14 @@ static void win_totop(int size, int flags)
}
} else {
// Remove the window and frame from the tree of frames.
- (void)winframe_remove(curwin, &dir, NULL);
+ winframe_remove(curwin, &dir, NULL);
}
win_remove(curwin, NULL);
last_status(false); // may need to remove last status line
- (void)win_comp_pos(); // recompute window positions
+ win_comp_pos(); // recompute window positions
// Split a window on the desired side and put the window there.
- (void)win_split_ins(size, flags, curwin, dir);
+ win_split_ins(size, flags, curwin, dir);
if (!(flags & WSP_VERT)) {
win_setheight(height);
if (p_ea) {
@@ -1943,7 +1958,7 @@ void win_move_after(win_T *win1, win_T *win2)
win_append(win2, win1);
frame_append(win2->w_frame, win1->w_frame);
- (void)win_comp_pos(); // recompute w_winrow for all windows
+ win_comp_pos(); // recompute w_winrow for all windows
redraw_later(curwin, UPD_NOT_VALID);
}
win_enter(win1, false);
@@ -2022,7 +2037,7 @@ static void win_equal_rec(win_T *next_curwin, bool current, frame_T *topfr, int
int totwincount = 0;
int next_curwin_size = 0;
int room = 0;
- int has_next_curwin = 0;
+ bool has_next_curwin = false;
if (topfr->fr_layout == FR_LEAF) {
// Set the width/height of this frame.
@@ -2311,7 +2326,7 @@ void leaving_window(win_T *const win)
// When leaving the window (or closing the window) was done from a
// callback we need to break out of the Insert mode loop and restart Insert
// mode when entering the window again.
- if (State & MODE_INSERT) {
+ if ((State & MODE_INSERT) && !stop_insert_mode) {
stop_insert_mode = true;
if (win->w_buffer->b_prompt_insert == NUL) {
win->w_buffer->b_prompt_insert = 'A';
@@ -2476,7 +2491,7 @@ bool can_close_in_cmdwin(win_T *win, Error *err)
FUNC_ATTR_NONNULL_ALL
{
if (cmdwin_type != 0) {
- if (win == curwin) {
+ if (win == cmdwin_win) {
cmdwin_result = Ctrl_C;
return false;
} else if (win == cmdwin_old_curwin) {
@@ -2544,6 +2559,7 @@ static bool close_last_window_tabpage(win_T *win, bool free_buf, tabpage_T *prev
/// "abort_if_last" is passed to close_buffer(): abort closing if all other
/// windows are closed.
static void win_close_buffer(win_T *win, int action, bool abort_if_last)
+ FUNC_ATTR_NONNULL_ALL
{
// Free independent synblock before the buffer is freed.
if (win->w_buffer != NULL) {
@@ -2581,6 +2597,7 @@ static void win_close_buffer(win_T *win, int action, bool abort_if_last)
// Called by :quit, :close, :xit, :wq and findtag().
// Returns FAIL when the window was not closed.
int win_close(win_T *win, bool free_buf, bool force)
+ FUNC_ATTR_NONNULL_ALL
{
tabpage_T *prev_curtab = curtab;
frame_T *win_frame = win->w_floating ? NULL : win->w_frame->fr_parent;
@@ -2741,7 +2758,7 @@ int win_close(win_T *win, bool free_buf, bool force)
if (win->w_floating) {
ui_comp_remove_grid(&win->w_grid_alloc);
assert(first_tabpage != NULL); // suppress clang "Dereference of NULL pointer"
- if (win->w_float_config.external) {
+ if (win->w_config.external) {
for (tabpage_T *tp = first_tabpage; tp != NULL; tp = tp->tp_next) {
if (tp == curtab) {
continue;
@@ -2813,7 +2830,7 @@ int win_close(win_T *win, bool free_buf, bool force)
// only resize that frame. Otherwise resize all windows.
win_equal(curwin, curwin->w_frame->fr_parent == win_frame, dir);
} else {
- (void)win_comp_pos();
+ win_comp_pos();
win_fix_scroll(false);
}
}
@@ -2879,6 +2896,7 @@ static void do_autocmd_winclosed(win_T *win)
// Caller must check if buffer is hidden and whether the tabline needs to be
// updated.
void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
+ FUNC_ATTR_NONNULL_ALL
{
// Get here with win->w_buffer == NULL when win_close() detects the tab page
// changed.
@@ -2980,6 +2998,7 @@ void win_close_othertab(win_T *win, int free_buf, tabpage_T *tp)
///
/// @return a pointer to the window that got the freed up space.
static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp)
+ FUNC_ATTR_NONNULL_ARG(1)
{
win_T *wp;
tabpage_T *win_tp = tp == NULL ? curtab : tp;
@@ -2998,6 +3017,7 @@ static win_T *win_free_mem(win_T *win, int *dirp, tabpage_T *tp)
wp = firstwin;
}
} else {
+ assert(tp != curtab);
if (tabpage_win_valid(tp, tp->tp_prevwin) && tp->tp_prevwin != win) {
wp = tp->tp_prevwin;
} else {
@@ -3021,6 +3041,9 @@ void win_free_all(void)
{
// avoid an error for switching tabpage with the cmdline window open
cmdwin_type = 0;
+ cmdwin_buf = NULL;
+ cmdwin_win = NULL;
+ cmdwin_old_curwin = NULL;
while (first_tabpage->tp_next != NULL) {
tabpage_close(true);
@@ -3030,7 +3053,7 @@ void win_free_all(void)
win_T *wp = lastwin;
win_remove(lastwin, NULL);
int dummy;
- (void)win_free_mem(wp, &dummy, NULL);
+ win_free_mem(wp, &dummy, NULL);
for (int i = 0; i < AUCMD_WIN_COUNT; i++) {
if (aucmd_win[i].auc_win == wp) {
aucmd_win[i].auc_win = NULL;
@@ -3041,7 +3064,7 @@ void win_free_all(void)
for (int i = 0; i < AUCMD_WIN_COUNT; i++) {
if (aucmd_win[i].auc_win != NULL) {
int dummy;
- (void)win_free_mem(aucmd_win[i].auc_win, &dummy, NULL);
+ win_free_mem(aucmd_win[i].auc_win, &dummy, NULL);
aucmd_win[i].auc_win = NULL;
}
}
@@ -3050,7 +3073,7 @@ void win_free_all(void)
while (firstwin != NULL) {
int dummy;
- (void)win_free_mem(firstwin, &dummy, NULL);
+ win_free_mem(firstwin, &dummy, NULL);
}
// No window should be used after this. Set curwin to NULL to crash
@@ -3067,7 +3090,10 @@ void win_free_all(void)
///
/// @return a pointer to the window that got the freed up space.
win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp)
+ FUNC_ATTR_NONNULL_ARG(1, 2)
{
+ assert(tp == NULL || tp != curtab);
+
// If there is only one window there is nothing to remove.
if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) {
return NULL;
@@ -3214,7 +3240,10 @@ win_T *winframe_remove(win_T *win, int *dirp, tabpage_T *tp)
/// @return a pointer to the frame that will receive the empty screen space that
/// is left over after "win" is closed.
static frame_T *win_altframe(win_T *win, tabpage_T *tp)
+ FUNC_ATTR_NONNULL_ARG(1)
{
+ assert(tp == NULL || tp != curtab);
+
if (tp == NULL ? ONE_WINDOW : tp->tp_firstwin == tp->tp_lastwin) {
return alt_tabpage()->tp_curwin->w_frame;
}
@@ -3278,6 +3307,7 @@ static tabpage_T *alt_tabpage(void)
// Find the left-upper window in frame "frp".
win_T *frame2win(frame_T *frp)
+ FUNC_ATTR_NONNULL_ALL
{
while (frp->fr_win == NULL) {
frp = frp->fr_child;
@@ -3850,7 +3880,7 @@ void win_alloc_first(void)
void win_alloc_aucmd_win(int idx)
{
Error err = ERROR_INIT;
- FloatConfig fconfig = FLOAT_CONFIG_INIT;
+ WinConfig fconfig = WIN_CONFIG_INIT;
fconfig.width = Columns;
fconfig.height = 5;
fconfig.focusable = false;
@@ -4299,7 +4329,7 @@ static void tabpage_check_windows(tabpage_T *old_curtab)
for (win_T *wp = old_curtab->tp_firstwin; wp; wp = next_wp) {
next_wp = wp->w_next;
if (wp->w_floating) {
- if (wp->w_float_config.external) {
+ if (wp->w_config.external) {
win_remove(wp, old_curtab);
win_append(lastwin_nofloating(), wp);
} else {
@@ -4310,8 +4340,8 @@ static void tabpage_check_windows(tabpage_T *old_curtab)
}
for (win_T *wp = firstwin; wp; wp = wp->w_next) {
- if (wp->w_floating && !wp->w_float_config.external) {
- win_config_float(wp, wp->w_float_config);
+ if (wp->w_floating && !wp->w_config.external) {
+ win_config_float(wp, wp->w_config);
}
wp->w_pos_changed = true;
}
@@ -4427,6 +4457,10 @@ void tabpage_move(int nr)
return;
}
+ if (tabpage_move_disallowed) {
+ return;
+ }
+
int n = 1;
tabpage_T *tp;
@@ -4471,11 +4505,12 @@ void tabpage_move(int nr)
redraw_tabline = true;
}
-// Go to another window.
-// When jumping to another buffer, stop Visual mode. Do this before
-// changing windows so we can yank the selection into the '*' register.
-// When jumping to another window on the same buffer, adjust its cursor
-// position to keep the same Visual area.
+/// Go to another window.
+/// When jumping to another buffer, stop Visual mode. Do this before
+/// changing windows so we can yank the selection into the '*' register.
+/// (note: this may trigger ModeChanged autocommand!)
+/// When jumping to another window on the same buffer, adjust its cursor
+/// position to keep the same Visual area.
void win_goto(win_T *wp)
{
win_T *owp = curwin;
@@ -4486,11 +4521,17 @@ void win_goto(win_T *wp)
}
if (wp->w_buffer != curbuf) {
+ // careful: triggers ModeChanged autocommand
reset_VIsual_and_resel();
} else if (VIsual_active) {
wp->w_cursor = curwin->w_cursor;
}
+ // autocommand may have made wp invalid
+ if (!win_valid(wp)) {
+ return;
+ }
+
win_enter(wp, true);
// Conceal cursor line in previous window, unconceal in current window.
@@ -4726,10 +4767,14 @@ static void win_enter_ext(win_T *const wp, const int flags)
if (wp->w_buffer != curbuf) {
buf_copy_options(wp->w_buffer, BCO_ENTER | BCO_NOHELP);
}
+
if (!curwin_invalid) {
prevwin = curwin; // remember for CTRL-W p
curwin->w_redr_status = true;
+ } else if (wp == prevwin) {
+ prevwin = NULL; // don't want it to be the new curwin
}
+
curwin = wp;
curbuf = wp->w_buffer;
@@ -4902,12 +4947,12 @@ win_T *buf_jump_open_tab(buf_T *buf)
return NULL;
}
+static int last_win_id = LOWEST_WIN_ID - 1;
+
/// @param hidden allocate a window structure and link it in the window if
// false.
win_T *win_alloc(win_T *after, bool hidden)
{
- static int last_win_id = LOWEST_WIN_ID - 1;
-
// allocate window structure and linesizes arrays
win_T *new_wp = xcalloc(1, sizeof(win_T));
@@ -4939,12 +4984,15 @@ win_T *win_alloc(win_T *after, bool hidden)
new_wp->w_cursor.lnum = 1;
new_wp->w_scbind_pos = 1;
new_wp->w_floating = 0;
- new_wp->w_float_config = FLOAT_CONFIG_INIT;
+ new_wp->w_config = WIN_CONFIG_INIT;
new_wp->w_viewport_invalid = true;
new_wp->w_viewport_last_topline = 1;
new_wp->w_ns_hl = -1;
+ Set(uint32_t) ns_set = SET_INIT;
+ new_wp->w_ns_set = ns_set;
+
// use global option for global-local options
new_wp->w_allbuf_opt.wo_so = new_wp->w_p_so = -1;
new_wp->w_allbuf_opt.wo_siso = new_wp->w_p_siso = -1;
@@ -4972,7 +5020,7 @@ void free_wininfo(wininfo_T *wip, buf_T *bp)
/// Remove window 'wp' from the window list and free the structure.
///
/// @param tp tab page "win" is in, NULL for current
-static void win_free(win_T *wp, tabpage_T *tp)
+void win_free(win_T *wp, tabpage_T *tp)
{
pmap_del(int)(&window_handles, wp->handle, NULL);
clearFolding(wp);
@@ -4983,6 +5031,8 @@ static void win_free(win_T *wp, tabpage_T *tp)
// Don't execute autocommands while the window is halfway being deleted.
block_autocmds();
+ set_destroy(uint32_t, &wp->w_ns_set);
+
clear_winopt(&wp->w_onebuf_opt);
clear_winopt(&wp->w_allbuf_opt);
@@ -5053,8 +5103,8 @@ static void win_free(win_T *wp, tabpage_T *tp)
}
// free the border text
- clear_virttext(&wp->w_float_config.title_chunks);
- clear_virttext(&wp->w_float_config.footer_chunks);
+ clear_virttext(&wp->w_config.title_chunks);
+ clear_virttext(&wp->w_config.footer_chunks);
clear_matches(wp);
@@ -5115,7 +5165,10 @@ void win_append(win_T *after, win_T *wp)
///
/// @param tp tab page "win" is in, NULL for current
void win_remove(win_T *wp, tabpage_T *tp)
+ FUNC_ATTR_NONNULL_ARG(1)
{
+ assert(tp == NULL || tp != curtab);
+
if (wp->w_prev != NULL) {
wp->w_prev->w_next = wp->w_next;
} else if (tp == NULL) {
@@ -5177,7 +5230,7 @@ void win_new_screensize(void)
if (old_Rows != Rows) {
// If 'window' uses the whole screen, keep it using that.
// Don't change it when set with "-w size" on the command line.
- if (p_window == old_Rows - 1 || (old_Rows == 0 && !option_was_set("window"))) {
+ if (p_window == old_Rows - 1 || (old_Rows == 0 && !option_was_set(kOptWindow))) {
p_window = Rows - 1;
}
old_Rows = Rows;
@@ -5209,7 +5262,7 @@ void win_new_screen_rows(void)
frame_new_height(topframe, h, false, false);
}
- (void)win_comp_pos(); // recompute w_winrow and w_wincol
+ win_comp_pos(); // recompute w_winrow and w_wincol
win_reconfig_floats(); // The size of floats might change
compute_cmdrow();
curtab->tp_ch_used = p_ch;
@@ -5233,7 +5286,7 @@ void win_new_screen_cols(void)
frame_new_width(topframe, Columns, false, false);
}
- (void)win_comp_pos(); // recompute w_winrow and w_wincol
+ win_comp_pos(); // recompute w_winrow and w_wincol
win_reconfig_floats(); // The size of floats might change
}
@@ -5343,7 +5396,7 @@ static int check_window_scroll_resize(int *size_count, win_T **first_scroll_win,
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
// Skip floating windows that do not have a snapshot (usually because they are newly-created),
- // as unlike split windows, creating floating windows do not cause other windows to resize.
+ // as unlike split windows, creating floating windows doesn't cause other windows to resize.
if (wp->w_floating && wp->w_last_topline == 0) {
wp->w_last_topline = wp->w_topline;
wp->w_last_topfill = wp->w_topfill;
@@ -5452,12 +5505,13 @@ void may_trigger_win_scrolled_resized(void)
}
int size_count = 0;
- win_T *first_scroll_win = NULL, *first_size_win = NULL;
+ win_T *first_scroll_win = NULL;
+ win_T *first_size_win = NULL;
int cwsr = check_window_scroll_resize(&size_count,
&first_scroll_win, &first_size_win,
NULL, NULL);
- int trigger_resize = do_resize && size_count > 0;
- int trigger_scroll = do_scroll && cwsr != 0;
+ bool trigger_resize = do_resize && size_count > 0;
+ bool trigger_scroll = do_scroll && cwsr != 0;
if (!trigger_resize && !trigger_scroll) {
return; // no relevant changes
}
@@ -5467,7 +5521,7 @@ void may_trigger_win_scrolled_resized(void)
// Create the list for v:event.windows before making the snapshot.
// windows_list = tv_list_alloc_with_items(size_count);
windows_list = tv_list_alloc(size_count);
- (void)check_window_scroll_resize(NULL, NULL, NULL, windows_list, NULL);
+ check_window_scroll_resize(NULL, NULL, NULL, windows_list, NULL);
}
dict_T *scroll_dict = NULL;
@@ -5475,7 +5529,7 @@ void may_trigger_win_scrolled_resized(void)
// Create the dict with entries for v:event before making the snapshot.
scroll_dict = tv_dict_alloc();
scroll_dict->dv_refcount = 1;
- (void)check_window_scroll_resize(NULL, NULL, NULL, NULL, scroll_dict);
+ check_window_scroll_resize(NULL, NULL, NULL, NULL, scroll_dict);
}
// WinScrolled/WinResized are triggered only once, even when multiple
@@ -5559,7 +5613,7 @@ void win_size_restore(garray_T *gap)
}
}
// recompute the window positions
- (void)win_comp_pos();
+ win_comp_pos();
}
}
@@ -5574,7 +5628,7 @@ int win_comp_pos(void)
for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {
// float might be anchored to moved window
- if (wp->w_float_config.relative == kFloatRelativeWindow) {
+ if (wp->w_config.relative == kFloatRelativeWindow) {
wp->w_pos_changed = true;
}
}
@@ -5633,8 +5687,8 @@ void win_setheight_win(int height, win_T *win)
height = MAX(height, (int)(win == curwin ? MAX(p_wmh, 1) : p_wmh) + win->w_winbar_height);
if (win->w_floating) {
- win->w_float_config.height = height;
- win_config_float(win, win->w_float_config);
+ win->w_config.height = height;
+ win_config_float(win, win->w_config);
redraw_later(win, UPD_VALID);
} else {
frame_setheight(win->w_frame, height + win->w_hsep_height + win->w_status_height);
@@ -5645,7 +5699,7 @@ void win_setheight_win(int height, win_T *win)
// If there is extra space created between the last window and the command
// line, clear it.
if (full_screen && msg_scrolled == 0 && row < cmdline_row) {
- grid_fill(&default_grid, row, cmdline_row, 0, Columns, ' ', ' ', 0);
+ grid_clear(&default_grid, row, cmdline_row, 0, Columns, 0);
if (msg_grid.chars) {
clear_cmdline = true;
}
@@ -5845,14 +5899,14 @@ void win_setwidth_win(int width, win_T *wp)
width = 0;
}
if (wp->w_floating) {
- wp->w_float_config.width = width;
- win_config_float(wp, wp->w_float_config);
+ wp->w_config.width = width;
+ win_config_float(wp, wp->w_config);
redraw_later(wp, UPD_NOT_VALID);
} else {
frame_setwidth(wp->w_frame, width + wp->w_vsep_width);
// recompute the window positions
- (void)win_comp_pos();
+ win_comp_pos();
redraw_all_later(UPD_NOT_VALID);
}
}
@@ -6128,7 +6182,7 @@ void win_drag_status_line(win_T *dragwin, int offset)
}
}
int row = win_comp_pos();
- grid_fill(&default_grid, row, cmdline_row, 0, Columns, ' ', ' ', 0);
+ grid_clear(&default_grid, row, cmdline_row, 0, Columns, 0);
if (msg_grid.chars) {
clear_cmdline = true;
}
@@ -6237,7 +6291,7 @@ void win_drag_vsep_line(win_T *dragwin, int offset)
fr = fr->fr_next;
}
}
- (void)win_comp_pos();
+ win_comp_pos();
redraw_all_later(UPD_NOT_VALID);
}
@@ -6262,7 +6316,7 @@ void set_fraction(win_T *wp)
/// TODO(vim): Ensure this also works with wrapped lines.
/// Requires a not fully visible cursor line to be allowed at the bottom of
/// a window("zb"), probably only when 'smoothscroll' is also set.
-void win_fix_scroll(int resize)
+void win_fix_scroll(bool resize)
{
if (*p_spk == 'c') {
return; // 'splitkeep' is "cursor"
@@ -6433,7 +6487,7 @@ void scroll_to_fraction(win_T *wp, int prev_height)
}
} else if (sline > 0) {
while (sline > 0 && lnum > 1) {
- (void)hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL);
+ hasFoldingWin(wp, lnum, &lnum, NULL, true, NULL);
if (lnum == 1) {
// first line in buffer is folded
line_size = 1;
@@ -6453,7 +6507,7 @@ void scroll_to_fraction(win_T *wp, int prev_height)
if (sline < 0) {
// Line we want at top would go off top of screen. Use next
// line instead.
- (void)hasFoldingWin(wp, lnum, NULL, &lnum, true, NULL);
+ hasFoldingWin(wp, lnum, NULL, &lnum, true, NULL);
lnum++;
wp->w_wrow -= line_size + sline;
} else if (sline > 0) {
@@ -6548,14 +6602,16 @@ void win_new_width(win_T *wp, int width)
win_set_inner_size(wp, true);
}
+OptInt win_default_scroll(win_T *wp)
+{
+ return MAX(wp->w_height_inner / 2, 1);
+}
+
void win_comp_scroll(win_T *wp)
{
const OptInt old_w_p_scr = wp->w_p_scr;
+ wp->w_p_scr = win_default_scroll(wp);
- wp->w_p_scr = wp->w_height_inner / 2;
- if (wp->w_p_scr == 0) {
- wp->w_p_scr = 1;
- }
if (wp->w_p_scr != old_w_p_scr) {
// Used by "verbose set scroll".
wp->w_p_script_ctx[WV_SCROLL].script_ctx.sc_sid = SID_WINLAYOUT;
@@ -6617,11 +6673,11 @@ void command_height(void)
}
// Recompute window positions.
- (void)win_comp_pos();
+ win_comp_pos();
// clear the lines added to cmdline
if (full_screen) {
- grid_fill(&default_grid, cmdline_row, Rows, 0, Columns, ' ', ' ', 0);
+ grid_clear(&default_grid, cmdline_row, Rows, 0, Columns, 0);
}
msg_row = cmdline_row;
redraw_cmdline = true;
@@ -6637,7 +6693,7 @@ void command_height(void)
// Recompute window positions.
if (frp != lastwin->w_frame) {
- (void)win_comp_pos();
+ win_comp_pos();
}
}
@@ -6853,7 +6909,7 @@ static bool resize_frame_for_status(frame_T *fr)
} else if (fp != fr) {
frame_new_height(fp, fp->fr_height - 1, false, false);
frame_fix_height(wp);
- (void)win_comp_pos();
+ win_comp_pos();
} else {
win_new_height(wp, wp->w_height - 1);
}
@@ -6875,7 +6931,7 @@ static bool resize_frame_for_winbar(frame_T *fr)
frame_new_height(fp, fp->fr_height - 1, false, false);
win_new_height(wp, wp->w_height + 1);
frame_fix_height(wp);
- (void)win_comp_pos();
+ win_comp_pos();
return true;
}
@@ -7211,7 +7267,7 @@ void restore_snapshot(int idx, int close_curwin)
&& curtab->tp_snapshot[idx]->fr_height == topframe->fr_height
&& check_snapshot_rec(curtab->tp_snapshot[idx], topframe) == OK) {
win_T *wp = restore_snapshot_rec(curtab->tp_snapshot[idx], topframe);
- (void)win_comp_pos();
+ win_comp_pos();
if (wp != NULL && close_curwin) {
win_goto(wp);
}
@@ -7309,9 +7365,17 @@ static bool frame_check_width(const frame_T *topfrp, int width)
}
/// Simple int comparison function for use with qsort()
-static int int_cmp(const void *a, const void *b)
+static int int_cmp(const void *pa, const void *pb)
{
- return *(const int *)a - *(const int *)b;
+ const int a = *(const int *)pa;
+ const int b = *(const int *)pb;
+ if (a > b) {
+ return 1;
+ }
+ if (a < b) {
+ return -1;
+ }
+ return 0;
}
/// Handle setting 'colorcolumn' or 'textwidth' in window "wp".
@@ -7388,12 +7452,18 @@ skip:
return NULL; // no error
}
+int get_last_winid(void)
+{
+ return last_win_id;
+}
+
void win_get_tabwin(handle_T id, int *tabnr, int *winnr)
{
*tabnr = 0;
*winnr = 0;
- int tnum = 1, wnum = 1;
+ int tnum = 1;
+ int wnum = 1;
FOR_ALL_TABS(tp) {
FOR_ALL_WINDOWS_IN_TAB(wp, tp) {
if (wp->handle == id) {
diff --git a/src/nvim/window.h b/src/nvim/window.h
index 3650fef46e..d20b799e20 100644
--- a/src/nvim/window.h
+++ b/src/nvim/window.h
@@ -21,15 +21,16 @@ enum {
/// arguments for win_split()
enum {
- WSP_ROOM = 0x01, ///< require enough room
- WSP_VERT = 0x02, ///< split/equalize vertically
- WSP_HOR = 0x04, ///< equalize horizontally
- WSP_TOP = 0x08, ///< window at top-left of shell
- WSP_BOT = 0x10, ///< window at bottom-right of shell
- WSP_HELP = 0x20, ///< creating the help window
- WSP_BELOW = 0x40, ///< put new window below/right
- WSP_ABOVE = 0x80, ///< put new window above/left
- WSP_NEWLOC = 0x100, ///< don't copy location list
+ WSP_ROOM = 0x01, ///< require enough room
+ WSP_VERT = 0x02, ///< split/equalize vertically
+ WSP_HOR = 0x04, ///< equalize horizontally
+ WSP_TOP = 0x08, ///< window at top-left of shell
+ WSP_BOT = 0x10, ///< window at bottom-right of shell
+ WSP_HELP = 0x20, ///< creating the help window
+ WSP_BELOW = 0x40, ///< put new window below/right
+ WSP_ABOVE = 0x80, ///< put new window above/left
+ WSP_NEWLOC = 0x100, ///< don't copy location list
+ WSP_NOENTER = 0x200, ///< don't enter the new window
};
enum {
@@ -38,8 +39,12 @@ enum {
STATUS_HEIGHT = 1, ///< height of a status line under a window
};
-/// Lowest number used for window ID. Cannot have this many windows per tab.
-enum { LOWEST_WIN_ID = 1000, };
+enum {
+ /// Lowest number used for window ID. Cannot have this many windows per tab.
+ LOWEST_WIN_ID = 1000,
+};
+
+EXTERN int tabpage_move_disallowed INIT( = 0); ///< moving tabpages around disallowed
/// Set to true if 'cmdheight' was explicitly set to 0.
EXTERN bool p_ch_was_zero INIT( = false);
diff --git a/src/nvim/winfloat.c b/src/nvim/winfloat.c
index 44f0e2fc0b..8fe0315230 100644
--- a/src/nvim/winfloat.c
+++ b/src/nvim/winfloat.c
@@ -9,9 +9,9 @@
#include "nvim/ascii_defs.h"
#include "nvim/buffer_defs.h"
#include "nvim/drawscreen.h"
-#include "nvim/func_attr.h"
#include "nvim/globals.h"
#include "nvim/grid.h"
+#include "nvim/grid_defs.h"
#include "nvim/macros_defs.h"
#include "nvim/memory.h"
#include "nvim/mouse.h"
@@ -20,7 +20,9 @@
#include "nvim/optionstr.h"
#include "nvim/pos_defs.h"
#include "nvim/strings.h"
+#include "nvim/types_defs.h"
#include "nvim/ui.h"
+#include "nvim/ui_defs.h"
#include "nvim/vim_defs.h"
#include "nvim/window.h"
#include "nvim/winfloat.h"
@@ -36,7 +38,7 @@
/// @param last make the window the last one in the window list.
/// Only used when allocating the autocommand window.
/// @param config must already have been validated!
-win_T *win_new_float(win_T *wp, bool last, FloatConfig fconfig, Error *err)
+win_T *win_new_float(win_T *wp, bool last, WinConfig fconfig, Error *err)
{
if (wp == NULL) {
wp = win_alloc(last ? lastwin : lastwin_nofloating(), false);
@@ -57,7 +59,7 @@ win_T *win_new_float(win_T *wp, bool last, FloatConfig fconfig, Error *err)
int dir;
winframe_remove(wp, &dir, NULL);
XFREE_CLEAR(wp->w_frame);
- (void)win_comp_pos(); // recompute window positions
+ win_comp_pos(); // recompute window positions
win_remove(wp, NULL);
win_append(lastwin_nofloating(), wp);
}
@@ -136,7 +138,7 @@ int win_border_width(win_T *wp)
return wp->w_border_adj[1] + wp->w_border_adj[3];
}
-void win_config_float(win_T *wp, FloatConfig fconfig)
+void win_config_float(win_T *wp, WinConfig fconfig)
{
wp->w_width = MAX(fconfig.width, 1);
wp->w_height = MAX(fconfig.height, 1);
@@ -147,7 +149,9 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
fconfig.col += curwin->w_wcol;
fconfig.window = curwin->handle;
} else if (fconfig.relative == kFloatRelativeMouse) {
- int row = mouse_row, col = mouse_col, grid = mouse_grid;
+ int row = mouse_row;
+ int col = mouse_col;
+ int grid = mouse_grid;
win_T *mouse_win = mouse_find_win(&grid, &row, &col);
if (mouse_win != NULL) {
fconfig.relative = kFloatRelativeWindow;
@@ -157,17 +161,17 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
}
}
- bool change_external = fconfig.external != wp->w_float_config.external;
- bool change_border = (fconfig.border != wp->w_float_config.border
+ bool change_external = fconfig.external != wp->w_config.external;
+ bool change_border = (fconfig.border != wp->w_config.border
|| memcmp(fconfig.border_hl_ids,
- wp->w_float_config.border_hl_ids,
+ wp->w_config.border_hl_ids,
sizeof fconfig.border_hl_ids) != 0);
- wp->w_float_config = fconfig;
+ wp->w_config = fconfig;
- bool has_border = wp->w_floating && wp->w_float_config.border;
+ bool has_border = wp->w_floating && wp->w_config.border;
for (int i = 0; i < 4; i++) {
- int new_adj = has_border && wp->w_float_config.border_chars[2 * i + 1][0];
+ int new_adj = has_border && wp->w_config.border_chars[2 * i + 1][0];
if (new_adj != wp->w_border_adj[i]) {
change_border = true;
wp->w_border_adj[i] = new_adj;
@@ -180,7 +184,7 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
}
win_set_inner_size(wp, true);
- must_redraw = MAX(must_redraw, UPD_VALID);
+ set_must_redraw(UPD_VALID);
wp->w_pos_changed = true;
if (change_external || change_border) {
@@ -189,22 +193,23 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
}
// compute initial position
- if (wp->w_float_config.relative == kFloatRelativeWindow) {
- int row = (int)wp->w_float_config.row;
- int col = (int)wp->w_float_config.col;
+ if (wp->w_config.relative == kFloatRelativeWindow) {
+ int row = (int)wp->w_config.row;
+ int col = (int)wp->w_config.col;
Error dummy = ERROR_INIT;
- win_T *parent = find_window_by_handle(wp->w_float_config.window, &dummy);
+ win_T *parent = find_window_by_handle(wp->w_config.window, &dummy);
if (parent) {
row += parent->w_winrow;
col += parent->w_wincol;
ScreenGrid *grid = &parent->w_grid;
- int row_off = 0, col_off = 0;
+ int row_off = 0;
+ int col_off = 0;
grid_adjust(&grid, &row_off, &col_off);
row += row_off;
col += col_off;
- if (wp->w_float_config.bufpos.lnum >= 0) {
- pos_T pos = { wp->w_float_config.bufpos.lnum + 1,
- wp->w_float_config.bufpos.col, 0 };
+ if (wp->w_config.bufpos.lnum >= 0) {
+ pos_T pos = { wp->w_config.bufpos.lnum + 1,
+ wp->w_config.bufpos.col, 0 };
int trow, tcol, tcolc, tcole;
textpos2screenpos(parent, &pos, &trow, &tcol, &tcolc, &tcole, true);
row += trow - 1;
@@ -228,7 +233,9 @@ void win_config_float(win_T *wp, FloatConfig fconfig)
static int float_zindex_cmp(const void *a, const void *b)
{
- return (*(win_T **)b)->w_float_config.zindex - (*(win_T **)a)->w_float_config.zindex;
+ int za = (*(win_T **)a)->w_config.zindex;
+ int zb = (*(win_T **)b)->w_config.zindex;
+ return za == zb ? 0 : za < zb ? 1 : -1;
}
void win_float_remove(bool bang, int count)
@@ -237,7 +244,9 @@ void win_float_remove(bool bang, int count)
for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {
kv_push(float_win_arr, wp);
}
- qsort(float_win_arr.items, float_win_arr.size, sizeof(win_T *), float_zindex_cmp);
+ if (float_win_arr.size > 0) {
+ qsort(float_win_arr.items, float_win_arr.size, sizeof(win_T *), float_zindex_cmp);
+ }
for (size_t i = 0; i < float_win_arr.size; i++) {
if (win_close(float_win_arr.items[i], false, false) == FAIL) {
break;
@@ -256,8 +265,8 @@ void win_check_anchored_floats(win_T *win)
{
for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {
// float might be anchored to moved window
- if (wp->w_float_config.relative == kFloatRelativeWindow
- && wp->w_float_config.window == win->handle) {
+ if (wp->w_config.relative == kFloatRelativeWindow
+ && wp->w_config.window == win->handle) {
wp->w_pos_changed = true;
}
}
@@ -266,7 +275,7 @@ void win_check_anchored_floats(win_T *win)
void win_reconfig_floats(void)
{
for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {
- win_config_float(wp, wp->w_float_config);
+ win_config_float(wp, wp->w_config);
}
}
@@ -287,3 +296,13 @@ bool win_float_valid(const win_T *win)
}
return false;
}
+
+win_T *win_float_find_preview(void)
+{
+ for (win_T *wp = lastwin; wp && wp->w_floating; wp = wp->w_prev) {
+ if (wp->w_float_is_info) {
+ return wp;
+ }
+ }
+ return NULL;
+}
diff --git a/src/nvim/winfloat.h b/src/nvim/winfloat.h
index 876ea9ccea..6e30c8da69 100644
--- a/src/nvim/winfloat.h
+++ b/src/nvim/winfloat.h
@@ -2,6 +2,13 @@
#include "nvim/api/private/defs.h" // IWYU pragma: keep
#include "nvim/buffer_defs.h" // IWYU pragma: keep
+#include "nvim/macros_defs.h"
+
+/// NW -> 0
+/// NE -> kFloatAnchorEast
+/// SW -> kFloatAnchorSouth
+/// SE -> kFloatAnchorSouth | kFloatAnchorEast
+EXTERN const char *const float_anchor_str[] INIT( = { "NW", "NE", "SW", "SE" });
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "winfloat.h.generated.h"
diff --git a/src/termkey/driver-csi.c b/src/termkey/driver-csi.c
new file mode 100644
index 0000000000..4cd5bbafe4
--- /dev/null
+++ b/src/termkey/driver-csi.c
@@ -0,0 +1,772 @@
+#include "termkey.h"
+#include "termkey-internal.h"
+
+#include <stdio.h>
+#include <string.h>
+
+// There are 64 codes 0x40 - 0x7F
+static int keyinfo_initialised = 0;
+static struct keyinfo ss3s[64];
+static char ss3_kpalts[64];
+
+typedef struct {
+ TermKey *tk;
+ int saved_string_id;
+ char *saved_string;
+} TermKeyCsi;
+
+typedef TermKeyResult CsiHandler(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args);
+static CsiHandler *csi_handlers[64];
+
+/*
+ * Handler for CSI/SS3 cmd keys
+ */
+
+static struct keyinfo csi_ss3s[64];
+
+static TermKeyResult handle_csi_ss3_full(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args)
+{
+ if(args > 1 && arg[1] != -1)
+ key->modifiers = arg[1] - 1;
+ else
+ key->modifiers = 0;
+
+ key->type = csi_ss3s[cmd - 0x40].type;
+ key->code.sym = csi_ss3s[cmd - 0x40].sym;
+ key->modifiers &= ~(csi_ss3s[cmd - 0x40].modifier_mask);
+ key->modifiers |= csi_ss3s[cmd - 0x40].modifier_set;
+
+ if(key->code.sym == TERMKEY_SYM_UNKNOWN)
+ return TERMKEY_RES_NONE;
+
+ return TERMKEY_RES_KEY;
+}
+
+static void register_csi_ss3_full(TermKeyType type, TermKeySym sym, int modifier_set, int modifier_mask, unsigned char cmd)
+{
+ if(cmd < 0x40 || cmd >= 0x80) {
+ return;
+ }
+
+ csi_ss3s[cmd - 0x40].type = type;
+ csi_ss3s[cmd - 0x40].sym = sym;
+ csi_ss3s[cmd - 0x40].modifier_set = modifier_set;
+ csi_ss3s[cmd - 0x40].modifier_mask = modifier_mask;
+
+ csi_handlers[cmd - 0x40] = &handle_csi_ss3_full;
+}
+
+static void register_csi_ss3(TermKeyType type, TermKeySym sym, unsigned char cmd)
+{
+ register_csi_ss3_full(type, sym, 0, 0, cmd);
+}
+
+/*
+ * Handler for SS3 keys with kpad alternate representations
+ */
+
+static void register_ss3kpalt(TermKeyType type, TermKeySym sym, unsigned char cmd, char kpalt)
+{
+ if(cmd < 0x40 || cmd >= 0x80) {
+ return;
+ }
+
+ ss3s[cmd - 0x40].type = type;
+ ss3s[cmd - 0x40].sym = sym;
+ ss3s[cmd - 0x40].modifier_set = 0;
+ ss3s[cmd - 0x40].modifier_mask = 0;
+ ss3_kpalts[cmd - 0x40] = kpalt;
+}
+
+/*
+ * Handler for CSI number ~ function keys
+ */
+
+static struct keyinfo csifuncs[35]; /* This value must be increased if more CSI function keys are added */
+#define NCSIFUNCS (sizeof(csifuncs)/sizeof(csifuncs[0]))
+
+static TermKeyResult handle_csifunc(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args)
+{
+ if(args > 1 && arg[1] != -1)
+ key->modifiers = arg[1] - 1;
+ else
+ key->modifiers = 0;
+
+ key->type = TERMKEY_TYPE_KEYSYM;
+
+ if(arg[0] == 27) {
+ int mod = key->modifiers;
+ (*tk->method.emit_codepoint)(tk, arg[2], key);
+ key->modifiers |= mod;
+ }
+ else if(arg[0] >= 0 && arg[0] < NCSIFUNCS) {
+ key->type = csifuncs[arg[0]].type;
+ key->code.sym = csifuncs[arg[0]].sym;
+ key->modifiers &= ~(csifuncs[arg[0]].modifier_mask);
+ key->modifiers |= csifuncs[arg[0]].modifier_set;
+ }
+ else
+ key->code.sym = TERMKEY_SYM_UNKNOWN;
+
+ if(key->code.sym == TERMKEY_SYM_UNKNOWN) {
+#ifdef DEBUG
+ fprintf(stderr, "CSI: Unknown function key %ld\n", arg[0]);
+#endif
+ return TERMKEY_RES_NONE;
+ }
+
+ return TERMKEY_RES_KEY;
+}
+
+static void register_csifunc(TermKeyType type, TermKeySym sym, int number)
+{
+ if(number >= NCSIFUNCS) {
+ return;
+ }
+
+ csifuncs[number].type = type;
+ csifuncs[number].sym = sym;
+ csifuncs[number].modifier_set = 0;
+ csifuncs[number].modifier_mask = 0;
+
+ csi_handlers['~' - 0x40] = &handle_csifunc;
+}
+
+/*
+ * Handler for CSI u extended Unicode keys
+ */
+
+static TermKeyResult handle_csi_u(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args)
+{
+ switch(cmd) {
+ case 'u': {
+ if(args > 1 && arg[1] != -1)
+ key->modifiers = arg[1] - 1;
+ else
+ key->modifiers = 0;
+
+ int mod = key->modifiers;
+ key->type = TERMKEY_TYPE_KEYSYM;
+ (*tk->method.emit_codepoint)(tk, arg[0], key);
+ key->modifiers |= mod;
+
+ return TERMKEY_RES_KEY;
+ }
+ default:
+ return TERMKEY_RES_NONE;
+ }
+}
+
+/*
+ * Handler for CSI M / CSI m mouse events in SGR and rxvt encodings
+ * Note: This does not handle X10 encoding
+ */
+
+static TermKeyResult handle_csi_m(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args)
+{
+ int initial = cmd >> 8;
+ cmd &= 0xff;
+
+ switch(cmd) {
+ case 'M':
+ case 'm':
+ break;
+ default:
+ return TERMKEY_RES_NONE;
+ }
+
+ if(!initial && args >= 3) { // rxvt protocol
+ key->type = TERMKEY_TYPE_MOUSE;
+ key->code.mouse[0] = arg[0];
+
+ key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
+ key->code.mouse[0] &= ~0x1c;
+
+ termkey_key_set_linecol(key, arg[1], arg[2]);
+
+ return TERMKEY_RES_KEY;
+ }
+
+ if(initial == '<' && args >= 3) { // SGR protocol
+ key->type = TERMKEY_TYPE_MOUSE;
+ key->code.mouse[0] = arg[0];
+
+ key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
+ key->code.mouse[0] &= ~0x1c;
+
+ termkey_key_set_linecol(key, arg[1], arg[2]);
+
+ if(cmd == 'm') // release
+ key->code.mouse[3] |= 0x80;
+
+ return TERMKEY_RES_KEY;
+ }
+
+ return TERMKEY_RES_NONE;
+}
+
+TermKeyResult termkey_interpret_mouse(TermKey *tk, const TermKeyKey *key, TermKeyMouseEvent *event, int *button, int *line, int *col)
+{
+ if(key->type != TERMKEY_TYPE_MOUSE)
+ return TERMKEY_RES_NONE;
+
+ if(button)
+ *button = 0;
+
+ termkey_key_get_linecol(key, line, col);
+
+ if(!event)
+ return TERMKEY_RES_KEY;
+
+ int btn = 0;
+
+ int code = key->code.mouse[0];
+
+ int drag = code & 0x20;
+
+ code &= ~0x3c;
+
+ switch(code) {
+ case 0:
+ case 1:
+ case 2:
+ *event = drag ? TERMKEY_MOUSE_DRAG : TERMKEY_MOUSE_PRESS;
+ btn = code + 1;
+ break;
+
+ case 3:
+ *event = TERMKEY_MOUSE_RELEASE;
+ // no button hint
+ break;
+
+ case 64:
+ case 65:
+ case 66:
+ case 67:
+ *event = drag ? TERMKEY_MOUSE_DRAG : TERMKEY_MOUSE_PRESS;
+ btn = code + 4 - 64;
+ break;
+
+ default:
+ *event = TERMKEY_MOUSE_UNKNOWN;
+ }
+
+ if(button)
+ *button = btn;
+
+ if(key->code.mouse[3] & 0x80)
+ *event = TERMKEY_MOUSE_RELEASE;
+
+ return TERMKEY_RES_KEY;
+}
+
+/*
+ * Handler for CSI ? R position reports
+ * A plain CSI R with no arguments is probably actually <F3>
+ */
+
+static TermKeyResult handle_csi_R(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args)
+{
+ switch(cmd) {
+ case 'R'|'?'<<8:
+ if(args < 2)
+ return TERMKEY_RES_NONE;
+
+ key->type = TERMKEY_TYPE_POSITION;
+ termkey_key_set_linecol(key, arg[1], arg[0]);
+ return TERMKEY_RES_KEY;
+
+ default:
+ return handle_csi_ss3_full(tk, key, cmd, arg, args);
+ }
+}
+
+TermKeyResult termkey_interpret_position(TermKey *tk, const TermKeyKey *key, int *line, int *col)
+{
+ if(key->type != TERMKEY_TYPE_POSITION)
+ return TERMKEY_RES_NONE;
+
+ termkey_key_get_linecol(key, line, col);
+
+ return TERMKEY_RES_KEY;
+}
+
+/*
+ * Handler for CSI $y mode status reports
+ */
+
+static TermKeyResult handle_csi_y(TermKey *tk, TermKeyKey *key, int cmd, long *arg, int args)
+{
+ switch(cmd) {
+ case 'y'|'$'<<16:
+ case 'y'|'$'<<16 | '?'<<8:
+ if(args < 2)
+ return TERMKEY_RES_NONE;
+
+ key->type = TERMKEY_TYPE_MODEREPORT;
+ key->code.mouse[0] = (cmd >> 8);
+ key->code.mouse[1] = arg[0] >> 8;
+ key->code.mouse[2] = arg[0] & 0xff;
+ key->code.mouse[3] = arg[1];
+ return TERMKEY_RES_KEY;
+
+ default:
+ return TERMKEY_RES_NONE;
+ }
+}
+
+TermKeyResult termkey_interpret_modereport(TermKey *tk, const TermKeyKey *key, int *initial, int *mode, int *value)
+{
+ if(key->type != TERMKEY_TYPE_MODEREPORT)
+ return TERMKEY_RES_NONE;
+
+ if(initial)
+ *initial = key->code.mouse[0];
+
+ if(mode)
+ *mode = ((uint8_t)key->code.mouse[1] << 8) | (uint8_t)key->code.mouse[2];
+
+ if(value)
+ *value = key->code.mouse[3];
+
+ return TERMKEY_RES_KEY;
+}
+
+#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
+
+static TermKeyResult parse_csi(TermKey *tk, size_t introlen, size_t *csi_len, long args[], size_t *nargs, unsigned long *commandp)
+{
+ size_t csi_end = introlen;
+
+ while(csi_end < tk->buffcount) {
+ if(CHARAT(csi_end) >= 0x40 && CHARAT(csi_end) < 0x80)
+ break;
+ csi_end++;
+ }
+
+ if(csi_end >= tk->buffcount)
+ return TERMKEY_RES_AGAIN;
+
+ unsigned char cmd = CHARAT(csi_end);
+ *commandp = cmd;
+
+ char present = 0;
+ int argi = 0;
+
+ size_t p = introlen;
+
+ // See if there is an initial byte
+ if(CHARAT(p) >= '<' && CHARAT(p) <= '?') {
+ *commandp |= (CHARAT(p) << 8);
+ p++;
+ }
+
+ // Now attempt to parse out up number;number;... separated values
+ while(p < csi_end) {
+ unsigned char c = CHARAT(p);
+
+ if(c >= '0' && c <= '9') {
+ if(!present) {
+ args[argi] = c - '0';
+ present = 1;
+ }
+ else {
+ args[argi] = (args[argi] * 10) + c - '0';
+ }
+ }
+ else if(c == ';') {
+ if(!present)
+ args[argi] = -1;
+ present = 0;
+ argi++;
+
+ if(argi > 16)
+ break;
+ }
+ else if(c >= 0x20 && c <= 0x2f) {
+ *commandp |= c << 16;
+ break;
+ }
+
+ p++;
+ }
+
+ if(present)
+ argi++;
+
+ *nargs = argi;
+ *csi_len = csi_end + 1;
+
+ return TERMKEY_RES_KEY;
+}
+
+TermKeyResult termkey_interpret_csi(TermKey *tk, const TermKeyKey *key, long args[], size_t *nargs, unsigned long *cmd)
+{
+ size_t dummy;
+
+ if(tk->hightide == 0)
+ return TERMKEY_RES_NONE;
+ if(key->type != TERMKEY_TYPE_UNKNOWN_CSI)
+ return TERMKEY_RES_NONE;
+
+ return parse_csi(tk, 0, &dummy, args, nargs, cmd);
+}
+
+static int register_keys(void)
+{
+ int i;
+
+ for(i = 0; i < 64; i++) {
+ csi_ss3s[i].sym = TERMKEY_SYM_UNKNOWN;
+ ss3s[i].sym = TERMKEY_SYM_UNKNOWN;
+ ss3_kpalts[i] = 0;
+ }
+
+ for(i = 0; i < NCSIFUNCS; i++)
+ csifuncs[i].sym = TERMKEY_SYM_UNKNOWN;
+
+ register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 'A');
+ register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN, 'B');
+ register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT, 'C');
+ register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_LEFT, 'D');
+ register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 'E');
+ register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 'F');
+ register_csi_ss3(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 'H');
+ register_csi_ss3(TERMKEY_TYPE_FUNCTION, 1, 'P');
+ register_csi_ss3(TERMKEY_TYPE_FUNCTION, 2, 'Q');
+ register_csi_ss3(TERMKEY_TYPE_FUNCTION, 3, 'R');
+ register_csi_ss3(TERMKEY_TYPE_FUNCTION, 4, 'S');
+
+ register_csi_ss3_full(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_TAB, TERMKEY_KEYMOD_SHIFT, TERMKEY_KEYMOD_SHIFT, 'Z');
+
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPENTER, 'M', 0);
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPEQUALS, 'X', '=');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPMULT, 'j', '*');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPPLUS, 'k', '+');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPCOMMA, 'l', ',');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPMINUS, 'm', '-');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPPERIOD, 'n', '.');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KPDIV, 'o', '/');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP0, 'p', '0');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP1, 'q', '1');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP2, 'r', '2');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP3, 's', '3');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP4, 't', '4');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP5, 'u', '5');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP6, 'v', '6');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP7, 'w', '7');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP8, 'x', '8');
+ register_ss3kpalt(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_KP9, 'y', '9');
+
+ register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_FIND, 1);
+ register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_INSERT, 2);
+ register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DELETE, 3);
+ register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SELECT, 4);
+ register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 5);
+ register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 6);
+ register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 7);
+ register_csifunc(TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 8);
+
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 1, 11);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 2, 12);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 3, 13);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 4, 14);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 5, 15);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 6, 17);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 7, 18);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 8, 19);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 9, 20);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 10, 21);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 11, 23);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 12, 24);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 13, 25);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 14, 26);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 15, 28);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 16, 29);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 17, 31);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 18, 32);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 19, 33);
+ register_csifunc(TERMKEY_TYPE_FUNCTION, 20, 34);
+
+ csi_handlers['u' - 0x40] = &handle_csi_u;
+
+ csi_handlers['M' - 0x40] = &handle_csi_m;
+ csi_handlers['m' - 0x40] = &handle_csi_m;
+
+ csi_handlers['R' - 0x40] = &handle_csi_R;
+
+ csi_handlers['y' - 0x40] = &handle_csi_y;
+
+ keyinfo_initialised = 1;
+ return 1;
+}
+
+static void *new_driver(TermKey *tk, const char *term)
+{
+ if(!keyinfo_initialised)
+ if(!register_keys())
+ return NULL;
+
+ TermKeyCsi *csi = malloc(sizeof *csi);
+ if(!csi)
+ return NULL;
+
+ csi->tk = tk;
+ csi->saved_string_id = 0;
+ csi->saved_string = NULL;
+
+ return csi;
+}
+
+static void free_driver(void *info)
+{
+ TermKeyCsi *csi = info;
+
+ if(csi->saved_string)
+ free(csi->saved_string);
+
+ free(csi);
+}
+
+static TermKeyResult peekkey_csi(TermKey *tk, TermKeyCsi *csi, size_t introlen, TermKeyKey *key, int force, size_t *nbytep)
+{
+ size_t csi_len;
+ size_t args = 16;
+ long arg[16];
+ unsigned long cmd;
+
+ TermKeyResult ret = parse_csi(tk, introlen, &csi_len, arg, &args, &cmd);
+
+ if(ret == TERMKEY_RES_AGAIN) {
+ if(!force)
+ return TERMKEY_RES_AGAIN;
+
+ (*tk->method.emit_codepoint)(tk, '[', key);
+ key->modifiers |= TERMKEY_KEYMOD_ALT;
+ *nbytep = introlen;
+ return TERMKEY_RES_KEY;
+ }
+
+ if(cmd == 'M' && args < 3) { // Mouse in X10 encoding consumes the next 3 bytes also
+ tk->buffstart += csi_len;
+ tk->buffcount -= csi_len;
+
+ TermKeyResult mouse_result = (*tk->method.peekkey_mouse)(tk, key, nbytep);
+
+ tk->buffstart -= csi_len;
+ tk->buffcount += csi_len;
+
+ if(mouse_result == TERMKEY_RES_KEY)
+ *nbytep += csi_len;
+
+ return mouse_result;
+ }
+
+ TermKeyResult result = TERMKEY_RES_NONE;
+
+ // We know from the logic above that cmd must be >= 0x40 and < 0x80
+ if(csi_handlers[(cmd & 0xff) - 0x40])
+ result = (*csi_handlers[(cmd & 0xff) - 0x40])(tk, key, cmd, arg, args);
+
+ if(result == TERMKEY_RES_NONE) {
+#ifdef DEBUG
+ switch(args) {
+ case 0:
+ fprintf(stderr, "CSI: Unknown cmd=%c\n", (char)cmd);
+ break;
+ case 1:
+ fprintf(stderr, "CSI: Unknown arg1=%ld cmd=%c\n", arg[0], (char)cmd);
+ break;
+ case 2:
+ fprintf(stderr, "CSI: Unknown arg1=%ld arg2=%ld cmd=%c\n", arg[0], arg[1], (char)cmd);
+ break;
+ case 3:
+ fprintf(stderr, "CSI: Unknown arg1=%ld arg2=%ld arg3=%ld cmd=%c\n", arg[0], arg[1], arg[2], (char)cmd);
+ break;
+ default:
+ fprintf(stderr, "CSI: Unknown arg1=%ld arg2=%ld arg3=%ld ... args=%d cmd=%c\n", arg[0], arg[1], arg[2], args, (char)cmd);
+ break;
+ }
+#endif
+ key->type = TERMKEY_TYPE_UNKNOWN_CSI;
+ key->code.number = cmd;
+ key->modifiers = 0;
+
+ tk->hightide = csi_len - introlen;
+ *nbytep = introlen; // Do not yet eat the data bytes
+ return TERMKEY_RES_KEY;
+ }
+
+ *nbytep = csi_len;
+ return result;
+}
+
+static TermKeyResult peekkey_ss3(TermKey *tk, TermKeyCsi *csi, size_t introlen, TermKeyKey *key, int force, size_t *nbytep)
+{
+ if(tk->buffcount < introlen + 1) {
+ if(!force)
+ return TERMKEY_RES_AGAIN;
+
+ (*tk->method.emit_codepoint)(tk, 'O', key);
+ key->modifiers |= TERMKEY_KEYMOD_ALT;
+ *nbytep = tk->buffcount;
+ return TERMKEY_RES_KEY;
+ }
+
+ unsigned char cmd = CHARAT(introlen);
+
+ if(cmd < 0x40 || cmd >= 0x80)
+ return TERMKEY_RES_NONE;
+
+ key->type = csi_ss3s[cmd - 0x40].type;
+ key->code.sym = csi_ss3s[cmd - 0x40].sym;
+ key->modifiers = csi_ss3s[cmd - 0x40].modifier_set;
+
+ if(key->code.sym == TERMKEY_SYM_UNKNOWN) {
+ if(tk->flags & TERMKEY_FLAG_CONVERTKP && ss3_kpalts[cmd - 0x40]) {
+ key->type = TERMKEY_TYPE_UNICODE;
+ key->code.codepoint = ss3_kpalts[cmd - 0x40];
+ key->modifiers = 0;
+
+ key->utf8[0] = key->code.codepoint;
+ key->utf8[1] = 0;
+ }
+ else {
+ key->type = ss3s[cmd - 0x40].type;
+ key->code.sym = ss3s[cmd - 0x40].sym;
+ key->modifiers = ss3s[cmd - 0x40].modifier_set;
+ }
+ }
+
+ if(key->code.sym == TERMKEY_SYM_UNKNOWN) {
+#ifdef DEBUG
+ fprintf(stderr, "CSI: Unknown SS3 %c (0x%02x)\n", (char)cmd, cmd);
+#endif
+ return TERMKEY_RES_NONE;
+ }
+
+ *nbytep = introlen + 1;
+
+ return TERMKEY_RES_KEY;
+}
+
+static TermKeyResult peekkey_ctrlstring(TermKey *tk, TermKeyCsi *csi, size_t introlen, TermKeyKey *key, int force, size_t *nbytep)
+{
+ size_t str_end = introlen;
+
+ while(str_end < tk->buffcount) {
+ if(CHARAT(str_end) == 0x07) // BEL
+ break;
+ if(CHARAT(str_end) == 0x9c) // ST
+ break;
+ if(CHARAT(str_end) == 0x1b &&
+ (str_end + 1) < tk->buffcount &&
+ CHARAT(str_end+1) == 0x5c) // ESC-prefixed ST
+ break;
+
+ str_end++;
+ }
+
+ if(str_end >= tk->buffcount)
+ return TERMKEY_RES_AGAIN;
+
+#ifdef DEBUG
+ fprintf(stderr, "Found a control string: %*s",
+ str_end - introlen, tk->buffer + tk->buffstart + introlen);
+#endif
+
+ *nbytep = str_end + 1;
+ if(CHARAT(str_end) == 0x1b)
+ (*nbytep)++;
+
+ if(csi->saved_string)
+ free(csi->saved_string);
+
+ size_t len = str_end - introlen;
+
+ csi->saved_string_id++;
+ csi->saved_string = malloc(len + 1);
+
+ strncpy(csi->saved_string, (char *)tk->buffer + tk->buffstart + introlen, len);
+ csi->saved_string[len] = 0;
+
+ key->type = (CHARAT(introlen-1) & 0x1f) == 0x10 ?
+ TERMKEY_TYPE_DCS : TERMKEY_TYPE_OSC;
+ key->code.number = csi->saved_string_id;
+ key->modifiers = 0;
+
+ return TERMKEY_RES_KEY;
+}
+
+static TermKeyResult peekkey(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytep)
+{
+ if(tk->buffcount == 0)
+ return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE;
+
+ TermKeyCsi *csi = info;
+
+ switch(CHARAT(0)) {
+ case 0x1b:
+ if(tk->buffcount < 2)
+ return TERMKEY_RES_NONE;
+
+ switch(CHARAT(1)) {
+ case 0x4f: // ESC-prefixed SS3
+ return peekkey_ss3(tk, csi, 2, key, force, nbytep);
+
+ case 0x50: // ESC-prefixed DCS
+ case 0x5d: // ESC-prefixed OSC
+ return peekkey_ctrlstring(tk, csi, 2, key, force, nbytep);
+
+ case 0x5b: // ESC-prefixed CSI
+ return peekkey_csi(tk, csi, 2, key, force, nbytep);
+ }
+
+ return TERMKEY_RES_NONE;
+
+ case 0x8f: // SS3
+ return peekkey_ss3(tk, csi, 1, key, force, nbytep);
+
+ case 0x90: // DCS
+ case 0x9d: // OSC
+ return peekkey_ctrlstring(tk, csi, 1, key, force, nbytep);
+
+ case 0x9b: // CSI
+ return peekkey_csi(tk, csi, 1, key, force, nbytep);
+ }
+
+ return TERMKEY_RES_NONE;
+}
+
+struct TermKeyDriver termkey_driver_csi = {
+ .name = "CSI",
+
+ .new_driver = new_driver,
+ .free_driver = free_driver,
+
+ .peekkey = peekkey,
+};
+
+TermKeyResult termkey_interpret_string(TermKey *tk, const TermKeyKey *key, const char **strp)
+{
+ struct TermKeyDriverNode *p;
+ for(p = tk->drivers; p; p = p->next)
+ if(p->driver == &termkey_driver_csi)
+ break;
+
+ if(!p)
+ return TERMKEY_RES_NONE;
+
+ if(key->type != TERMKEY_TYPE_DCS &&
+ key->type != TERMKEY_TYPE_OSC)
+ return TERMKEY_RES_NONE;
+
+ TermKeyCsi *csi = p->info;
+
+ if(csi->saved_string_id != key->code.number)
+ return TERMKEY_RES_NONE;
+
+ *strp = csi->saved_string;
+
+ return TERMKEY_RES_KEY;
+}
diff --git a/src/termkey/driver-ti.c b/src/termkey/driver-ti.c
new file mode 100644
index 0000000000..1f8ee10808
--- /dev/null
+++ b/src/termkey/driver-ti.c
@@ -0,0 +1,654 @@
+// we want strdup()
+#define _XOPEN_SOURCE 600
+
+#include "termkey.h"
+#include "termkey-internal.h"
+
+#ifdef HAVE_UNIBILIUM
+# include <unibilium.h>
+#else
+# include <curses.h>
+# include <term.h>
+
+/* curses.h has just polluted our namespace. We want this back */
+# undef buttons
+#endif
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#ifndef _WIN32
+# include <unistd.h>
+#else
+# include <io.h>
+#endif
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#define streq(a,b) (!strcmp(a,b))
+
+#define MAX_FUNCNAME 9
+
+static struct {
+ const char *funcname;
+ TermKeyType type;
+ TermKeySym sym;
+ int mods;
+} funcs[] =
+{
+ /* THIS LIST MUST REMAIN SORTED! */
+ { "backspace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BACKSPACE, 0 },
+ { "begin", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 },
+ { "beg", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_BEGIN, 0 },
+ { "btab", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_TAB, TERMKEY_KEYMOD_SHIFT },
+ { "cancel", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CANCEL, 0 },
+ { "clear", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLEAR, 0 },
+ { "close", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_CLOSE, 0 },
+ { "command", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COMMAND, 0 },
+ { "copy", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_COPY, 0 },
+ { "dc", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DELETE, 0 },
+ { "down", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_DOWN, 0 },
+ { "end", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_END, 0 },
+ { "enter", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_ENTER, 0 },
+ { "exit", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_EXIT, 0 },
+ { "find", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_FIND, 0 },
+ { "help", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HELP, 0 },
+ { "home", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_HOME, 0 },
+ { "ic", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_INSERT, 0 },
+ { "left", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_LEFT, 0 },
+ { "mark", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MARK, 0 },
+ { "message", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MESSAGE, 0 },
+ { "move", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_MOVE, 0 },
+ { "next", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 }, // Not quite, but it's the best we can do
+ { "npage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEDOWN, 0 },
+ { "open", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPEN, 0 },
+ { "options", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_OPTIONS, 0 },
+ { "ppage", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 },
+ { "previous", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PAGEUP, 0 }, // Not quite, but it's the best we can do
+ { "print", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_PRINT, 0 },
+ { "redo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REDO, 0 },
+ { "reference", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFERENCE, 0 },
+ { "refresh", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REFRESH, 0 },
+ { "replace", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_REPLACE, 0 },
+ { "restart", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESTART, 0 },
+ { "resume", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RESUME, 0 },
+ { "right", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_RIGHT, 0 },
+ { "save", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SAVE, 0 },
+ { "select", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SELECT, 0 },
+ { "suspend", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_SUSPEND, 0 },
+ { "undo", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UNDO, 0 },
+ { "up", TERMKEY_TYPE_KEYSYM, TERMKEY_SYM_UP, 0 },
+ { NULL },
+};
+
+#ifdef HAVE_UNIBILIUM
+static enum unibi_string unibi_lookup_str(const char *name)
+{
+ for(enum unibi_string ret = unibi_string_begin_+1; ret < unibi_string_end_; ret++)
+ if(streq(unibi_name_str(ret), name))
+ return ret;
+
+ return -1;
+}
+
+static const char *unibi_get_str_by_name(const unibi_term *ut, const char *name)
+{
+ enum unibi_string idx = unibi_lookup_str(name);
+ if(idx == (enum unibi_string)-1)
+ return NULL;
+
+ return unibi_get_str(ut, idx);
+}
+#endif
+
+/* To be efficient at lookups, we store the byte sequence => keyinfo mapping
+ * in a trie. This avoids a slow linear search through a flat list of
+ * sequences. Because it is likely most nodes will be very sparse, we optimise
+ * vector to store an extent map after the database is loaded.
+ */
+
+typedef enum {
+ TYPE_KEY,
+ TYPE_ARR,
+} trie_nodetype;
+
+struct trie_node {
+ trie_nodetype type;
+};
+
+struct trie_node_key {
+ trie_nodetype type;
+ struct keyinfo key;
+};
+
+struct trie_node_arr {
+ trie_nodetype type;
+ unsigned char min, max; /* INCLUSIVE endpoints of the extent range */
+ struct trie_node *arr[]; /* dynamic size at allocation time */
+};
+
+typedef struct {
+ TermKey *tk;
+
+#ifdef HAVE_UNIBILIUM
+ unibi_term *unibi; /* only valid until first 'start' call */
+#else
+ char *term; /* only valid until first 'start' call */
+#endif
+
+ struct trie_node *root;
+
+ char *start_string;
+ char *stop_string;
+} TermKeyTI;
+
+static int insert_seq(TermKeyTI *ti, const char *seq, struct trie_node *node);
+
+static struct trie_node *new_node_key(TermKeyType type, TermKeySym sym, int modmask, int modset)
+{
+ struct trie_node_key *n = malloc(sizeof(*n));
+ if(!n)
+ return NULL;
+
+ n->type = TYPE_KEY;
+
+ n->key.type = type;
+ n->key.sym = sym;
+ n->key.modifier_mask = modmask;
+ n->key.modifier_set = modset;
+
+ return (struct trie_node*)n;
+}
+
+static struct trie_node *new_node_arr(unsigned char min, unsigned char max)
+{
+ struct trie_node_arr *n = malloc(sizeof(*n) + ((int)max-min+1) * sizeof(n->arr[0]));
+ if(!n)
+ return NULL;
+
+ n->type = TYPE_ARR;
+ n->min = min; n->max = max;
+
+ int i;
+ for(i = min; i <= max; i++)
+ n->arr[i-min] = NULL;
+
+ return (struct trie_node*)n;
+}
+
+static struct trie_node *lookup_next(struct trie_node *n, unsigned char b)
+{
+ switch(n->type) {
+ case TYPE_KEY:
+ fprintf(stderr, "ABORT: lookup_next within a TYPE_KEY node\n");
+ abort();
+ case TYPE_ARR:
+ {
+ struct trie_node_arr *nar = (struct trie_node_arr*)n;
+ if(b < nar->min || b > nar->max)
+ return NULL;
+ return nar->arr[b - nar->min];
+ }
+ }
+
+ return NULL; // Never reached but keeps compiler happy
+}
+
+static void free_trie(struct trie_node *n)
+{
+ switch(n->type) {
+ case TYPE_KEY:
+ break;
+ case TYPE_ARR:
+ {
+ struct trie_node_arr *nar = (struct trie_node_arr*)n;
+ int i;
+ for(i = nar->min; i <= nar->max; i++)
+ if(nar->arr[i - nar->min])
+ free_trie(nar->arr[i - nar->min]);
+ break;
+ }
+ }
+
+ free(n);
+}
+
+static struct trie_node *compress_trie(struct trie_node *n)
+{
+ if(!n)
+ return NULL;
+
+ switch(n->type) {
+ case TYPE_KEY:
+ return n;
+ case TYPE_ARR:
+ {
+ struct trie_node_arr *nar = (struct trie_node_arr*)n;
+ unsigned char min, max;
+ // Find the real bounds
+ for(min = 0; !nar->arr[min]; min++)
+ if(min == 255 && !nar->arr[min]) {
+ free(nar);
+ return new_node_arr(1, 0);
+ }
+
+ for(max = 0xff; !nar->arr[max]; max--)
+ ;
+
+ struct trie_node_arr *new = (struct trie_node_arr*)new_node_arr(min, max);
+ int i;
+ for(i = min; i <= max; i++)
+ new->arr[i - min] = compress_trie(nar->arr[i]);
+
+ free(nar);
+ return (struct trie_node*)new;
+ }
+ }
+
+ return n;
+}
+
+static bool try_load_terminfo_key(TermKeyTI *ti, const char *name, struct keyinfo *info)
+{
+ const char *value = NULL;
+
+#ifdef HAVE_UNIBILIUM
+ if(ti->unibi)
+ value = unibi_get_str_by_name(ti->unibi, name);
+#else
+ if(ti->term)
+ value = tigetstr(name);
+#endif
+
+ if(ti->tk->ti_getstr_hook)
+ value = (ti->tk->ti_getstr_hook)(name, value, ti->tk->ti_getstr_hook_data);
+
+ if(!value || value == (char*)-1 || !value[0])
+ return false;
+
+ struct trie_node *node = new_node_key(info->type, info->sym, info->modifier_mask, info->modifier_set);
+ insert_seq(ti, value, node);
+
+ return true;
+}
+
+static int load_terminfo(TermKeyTI *ti)
+{
+ int i;
+
+#ifdef HAVE_UNIBILIUM
+ unibi_term *unibi = ti->unibi;
+#else
+ {
+ int err;
+
+ /* Have to cast away the const. But it's OK - we know terminfo won't really
+ * modify term */
+ if(setupterm((char*)ti->term, 1, &err) != OK)
+ return 0;
+ }
+#endif
+
+ ti->root = new_node_arr(0, 0xff);
+ if(!ti->root)
+ return 0;
+
+ /* First the regular key strings
+ */
+ for(i = 0; funcs[i].funcname; i++) {
+ char name[MAX_FUNCNAME + 5 + 1];
+
+ sprintf(name, "key_%s", funcs[i].funcname);
+ if(!try_load_terminfo_key(ti, name, &(struct keyinfo){
+ .type = funcs[i].type,
+ .sym = funcs[i].sym,
+ .modifier_mask = funcs[i].mods,
+ .modifier_set = funcs[i].mods,
+ }))
+ continue;
+
+ /* Maybe it has a shifted version */
+ sprintf(name, "key_s%s", funcs[i].funcname);
+ try_load_terminfo_key(ti, name, &(struct keyinfo){
+ .type = funcs[i].type,
+ .sym = funcs[i].sym,
+ .modifier_mask = funcs[i].mods | TERMKEY_KEYMOD_SHIFT,
+ .modifier_set = funcs[i].mods | TERMKEY_KEYMOD_SHIFT,
+ });
+ }
+
+ /* Now the F<digit> keys
+ */
+ for(i = 1; i < 255; i++) {
+ char name[9];
+ sprintf(name, "key_f%d", i);
+ if(!try_load_terminfo_key(ti, name, &(struct keyinfo){
+ .type = TERMKEY_TYPE_FUNCTION,
+ .sym = i,
+ .modifier_mask = 0,
+ .modifier_set = 0,
+ }))
+ break;
+ }
+
+ /* Finally mouse mode */
+ {
+ const char *value = NULL;
+
+#ifdef HAVE_UNIBILIUM
+ if(ti->unibi)
+ value = unibi_get_str_by_name(ti->unibi, "key_mouse");
+#else
+ if(ti->term)
+ value = tigetstr("key_mouse");
+#endif
+
+ if(ti->tk->ti_getstr_hook)
+ value = (ti->tk->ti_getstr_hook)("key_mouse", value, ti->tk->ti_getstr_hook_data);
+
+ /* Some terminfos (e.g. xterm-1006) claim a different key_mouse that won't
+ * give X10 encoding. We'll only accept this if it's exactly "\e[M"
+ */
+ if(value && streq(value, "\x1b[M")) {
+ struct trie_node *node = new_node_key(TERMKEY_TYPE_MOUSE, 0, 0, 0);
+ insert_seq(ti, value, node);
+ }
+ }
+
+ /* Take copies of these terminfo strings, in case we build multiple termkey
+ * instances for multiple different termtypes, and it's different by the
+ * time we want to use it
+ */
+#ifdef HAVE_UNIBILIUM
+ const char *keypad_xmit = unibi ?
+ unibi_get_str(unibi, unibi_keypad_xmit) :
+ NULL;
+#endif
+
+ if(keypad_xmit)
+ ti->start_string = strdup(keypad_xmit);
+ else
+ ti->start_string = NULL;
+
+#ifdef HAVE_UNIBILIUM
+ const char *keypad_local = unibi ?
+ unibi_get_str(unibi, unibi_keypad_local) :
+ NULL;
+#endif
+
+ if(keypad_local)
+ ti->stop_string = strdup(keypad_local);
+ else
+ ti->stop_string = NULL;
+
+#ifdef HAVE_UNIBILIUM
+ if(unibi)
+ unibi_destroy(unibi);
+
+ ti->unibi = NULL;
+#else
+ if(ti->term)
+ free(ti->term);
+
+ ti->term = NULL;
+#endif
+
+ ti->root = compress_trie(ti->root);
+
+ return 1;
+}
+
+static void *new_driver(TermKey *tk, const char *term)
+{
+ TermKeyTI *ti = malloc(sizeof *ti);
+ if(!ti)
+ return NULL;
+
+ ti->tk = tk;
+ ti->root = NULL;
+ ti->start_string = NULL;
+ ti->stop_string = NULL;
+
+#ifdef HAVE_UNIBILIUM
+ ti->unibi = unibi_from_term(term);
+ int saved_errno = errno;
+ if(!ti->unibi && saved_errno != ENOENT) {
+ free(ti);
+ return NULL;
+ }
+ /* ti->unibi may be NULL if errno == ENOENT. That means the terminal wasn't
+ * known. Lets keep going because if we get getstr hook that might invent
+ * new strings for us
+ */
+#else
+ {
+ int err;
+
+ ti->term = NULL;
+
+ /* Have to cast away the const. But it's OK - we know terminfo won't really
+ * modify term */
+ if(setupterm((char*)term, 1, &err) == OK)
+ ti->term = strdup(term);
+ }
+#endif
+
+ return ti;
+}
+
+static int start_driver(TermKey *tk, void *info)
+{
+ TermKeyTI *ti = info;
+ struct stat statbuf;
+ char *start_string;
+ size_t len;
+
+ if(!ti->root)
+ load_terminfo(ti);
+
+ start_string = ti->start_string;
+
+ if(tk->fd == -1 || !start_string)
+ return 1;
+
+ /* The terminfo database will contain keys in application cursor key mode.
+ * We may need to enable that mode
+ */
+
+ /* There's no point trying to write() to a pipe */
+ if(fstat(tk->fd, &statbuf) == -1)
+ return 0;
+
+#ifndef _WIN32
+ if(S_ISFIFO(statbuf.st_mode))
+ return 1;
+#endif
+
+ // Can't call putp or tputs because they suck and don't give us fd control
+ len = strlen(start_string);
+ while(len) {
+ size_t written = write(tk->fd, start_string, len);
+ if(written == -1)
+ return 0;
+ start_string += written;
+ len -= written;
+ }
+ return 1;
+}
+
+static int stop_driver(TermKey *tk, void *info)
+{
+ TermKeyTI *ti = info;
+ struct stat statbuf;
+ char *stop_string = ti->stop_string;
+ size_t len;
+
+ if(tk->fd == -1 || !stop_string)
+ return 1;
+
+ /* There's no point trying to write() to a pipe */
+ if(fstat(tk->fd, &statbuf) == -1)
+ return 0;
+
+#ifndef _WIN32
+ if(S_ISFIFO(statbuf.st_mode))
+ return 1;
+#endif
+
+ /* The terminfo database will contain keys in application cursor key mode.
+ * We may need to enable that mode
+ */
+
+ // Can't call putp or tputs because they suck and don't give us fd control
+ len = strlen(stop_string);
+ while(len) {
+ size_t written = write(tk->fd, stop_string, len);
+ if(written == -1)
+ return 0;
+ stop_string += written;
+ len -= written;
+ }
+ return 1;
+}
+
+static void free_driver(void *info)
+{
+ TermKeyTI *ti = info;
+
+ free_trie(ti->root);
+
+ if(ti->start_string)
+ free(ti->start_string);
+
+ if(ti->stop_string)
+ free(ti->stop_string);
+
+#ifdef HAVE_UNIBILIUM
+ if(ti->unibi)
+ unibi_destroy(ti->unibi);
+#else
+ if(ti->term)
+ free(ti->term);
+#endif
+
+ free(ti);
+}
+
+#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
+
+static TermKeyResult peekkey(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytep)
+{
+ TermKeyTI *ti = info;
+
+ if(tk->buffcount == 0)
+ return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE;
+
+ struct trie_node *p = ti->root;
+
+ unsigned int pos = 0;
+ while(pos < tk->buffcount) {
+ p = lookup_next(p, CHARAT(pos));
+ if(!p)
+ break;
+
+ pos++;
+
+ if(p->type != TYPE_KEY)
+ continue;
+
+ struct trie_node_key *nk = (struct trie_node_key*)p;
+ if(nk->key.type == TERMKEY_TYPE_MOUSE) {
+ tk->buffstart += pos;
+ tk->buffcount -= pos;
+
+ TermKeyResult mouse_result = (*tk->method.peekkey_mouse)(tk, key, nbytep);
+
+ tk->buffstart -= pos;
+ tk->buffcount += pos;
+
+ if(mouse_result == TERMKEY_RES_KEY)
+ *nbytep += pos;
+
+ return mouse_result;
+ }
+
+ key->type = nk->key.type;
+ key->code.sym = nk->key.sym;
+ key->modifiers = nk->key.modifier_set;
+ *nbytep = pos;
+ return TERMKEY_RES_KEY;
+ }
+
+ // If p is not NULL then we hadn't walked off the end yet, so we have a
+ // partial match
+ if(p && !force)
+ return TERMKEY_RES_AGAIN;
+
+ return TERMKEY_RES_NONE;
+}
+
+static int insert_seq(TermKeyTI *ti, const char *seq, struct trie_node *node)
+{
+ int pos = 0;
+ struct trie_node *p = ti->root;
+
+ // Unsigned because we'll be using it as an array subscript
+ unsigned char b;
+
+ while((b = seq[pos])) {
+ struct trie_node *next = lookup_next(p, b);
+ if(!next)
+ break;
+ p = next;
+ pos++;
+ }
+
+ while((b = seq[pos])) {
+ struct trie_node *next;
+ if(seq[pos+1])
+ // Intermediate node
+ next = new_node_arr(0, 0xff);
+ else
+ // Final key node
+ next = node;
+
+ if(!next)
+ return 0;
+
+ switch(p->type) {
+ case TYPE_ARR:
+ {
+ struct trie_node_arr *nar = (struct trie_node_arr*)p;
+ if(b < nar->min || b > nar->max) {
+ fprintf(stderr, "ASSERT FAIL: Trie insert at 0x%02x is outside of extent bounds (0x%02x..0x%02x)\n",
+ b, nar->min, nar->max);
+ abort();
+ }
+ nar->arr[b - nar->min] = next;
+ p = next;
+ break;
+ }
+ case TYPE_KEY:
+ fprintf(stderr, "ASSERT FAIL: Tried to insert child node in TYPE_KEY\n");
+ abort();
+ }
+
+ pos++;
+ }
+
+ return 1;
+}
+
+struct TermKeyDriver termkey_driver_ti = {
+ .name = "terminfo",
+
+ .new_driver = new_driver,
+ .free_driver = free_driver,
+
+ .start_driver = start_driver,
+ .stop_driver = stop_driver,
+
+ .peekkey = peekkey,
+};
diff --git a/src/termkey/termkey-internal.h b/src/termkey/termkey-internal.h
new file mode 100644
index 0000000000..c300b02616
--- /dev/null
+++ b/src/termkey/termkey-internal.h
@@ -0,0 +1,112 @@
+#ifndef GUARD_TERMKEY_INTERNAL_H_
+#define GUARD_TERMKEY_INTERNAL_H_
+
+#define HAVE_TERMIOS
+
+#ifdef _WIN32
+# undef HAVE_TERMIOS
+#endif
+
+#include "termkey.h"
+
+#include <stdint.h>
+#ifdef HAVE_TERMIOS
+# include <termios.h>
+#endif
+
+#ifdef _MSC_VER
+#include <BaseTsd.h>
+typedef SSIZE_T ssize_t;
+#endif
+
+struct TermKeyDriver
+{
+ const char *name;
+ void *(*new_driver)(TermKey *tk, const char *term);
+ void (*free_driver)(void *info);
+ int (*start_driver)(TermKey *tk, void *info);
+ int (*stop_driver)(TermKey *tk, void *info);
+ TermKeyResult (*peekkey)(TermKey *tk, void *info, TermKeyKey *key, int force, size_t *nbytes);
+};
+
+struct keyinfo {
+ TermKeyType type;
+ TermKeySym sym;
+ int modifier_mask;
+ int modifier_set;
+};
+
+struct TermKeyDriverNode;
+struct TermKeyDriverNode {
+ struct TermKeyDriver *driver;
+ void *info;
+ struct TermKeyDriverNode *next;
+};
+
+struct TermKey {
+ int fd;
+ int flags;
+ int canonflags;
+ unsigned char *buffer;
+ size_t buffstart; // First offset in buffer
+ size_t buffcount; // NUMBER of entires valid in buffer
+ size_t buffsize; // Total malloc'ed size
+ size_t hightide; /* Position beyond buffstart at which peekkey() should next start
+ * normally 0, but see also termkey_interpret_csi */
+
+#ifdef HAVE_TERMIOS
+ struct termios restore_termios;
+ char restore_termios_valid;
+#endif
+
+ TermKey_Terminfo_Getstr_Hook *ti_getstr_hook;
+ void *ti_getstr_hook_data;
+
+ int waittime; // msec
+
+ char is_closed;
+ char is_started;
+
+ int nkeynames;
+ const char **keynames;
+
+ // There are 32 C0 codes
+ struct keyinfo c0[32];
+
+ struct TermKeyDriverNode *drivers;
+
+ // Now some "protected" methods for the driver to call but which we don't
+ // want exported as real symbols in the library
+ struct {
+ void (*emit_codepoint)(TermKey *tk, long codepoint, TermKeyKey *key);
+ TermKeyResult (*peekkey_simple)(TermKey *tk, TermKeyKey *key, int force, size_t *nbytes);
+ TermKeyResult (*peekkey_mouse)(TermKey *tk, TermKeyKey *key, size_t *nbytes);
+ } method;
+};
+
+static inline void termkey_key_get_linecol(const TermKeyKey *key, int *line, int *col)
+{
+ if(col)
+ *col = (unsigned char)key->code.mouse[1] | ((unsigned char)key->code.mouse[3] & 0x0f) << 8;
+
+ if(line)
+ *line = (unsigned char)key->code.mouse[2] | ((unsigned char)key->code.mouse[3] & 0x70) << 4;
+}
+
+static inline void termkey_key_set_linecol(TermKeyKey *key, int line, int col)
+{
+ if(line > 0xfff)
+ line = 0xfff;
+
+ if(col > 0x7ff)
+ col = 0x7ff;
+
+ key->code.mouse[1] = (line & 0x0ff);
+ key->code.mouse[2] = (col & 0x0ff);
+ key->code.mouse[3] = (line & 0xf00) >> 8 | (col & 0x300) >> 4;
+}
+
+extern struct TermKeyDriver termkey_driver_csi;
+extern struct TermKeyDriver termkey_driver_ti;
+
+#endif
diff --git a/src/termkey/termkey.c b/src/termkey/termkey.c
new file mode 100644
index 0000000000..832e5a9a9e
--- /dev/null
+++ b/src/termkey/termkey.c
@@ -0,0 +1,1606 @@
+#include "termkey.h"
+#include "termkey-internal.h"
+
+#include <ctype.h>
+#include <errno.h>
+#ifndef _WIN32
+# include <poll.h>
+# include <unistd.h>
+# include <strings.h>
+#else
+# include <io.h>
+#endif
+#include <string.h>
+
+#include <stdio.h>
+
+#ifdef _MSC_VER
+# define strcaseeq(a,b) (_stricmp(a,b) == 0)
+#else
+# define strcaseeq(a,b) (strcasecmp(a,b) == 0)
+#endif
+
+void termkey_check_version(int major, int minor)
+{
+ if(major != TERMKEY_VERSION_MAJOR) {
+ fprintf(stderr, "libtermkey major version mismatch; %d (wants) != %d (library)\n",
+ major, TERMKEY_VERSION_MAJOR);
+ exit(1);
+ }
+
+ if(minor > TERMKEY_VERSION_MINOR) {
+ fprintf(stderr, "libtermkey minor version mismatch; %d (wants) > %d (library)\n",
+ minor, TERMKEY_VERSION_MINOR);
+ exit(1);
+ }
+
+ // Happy
+}
+
+static struct TermKeyDriver *drivers[] = {
+ &termkey_driver_ti,
+ &termkey_driver_csi,
+ NULL,
+};
+
+// Forwards for the "protected" methods
+// static void eat_bytes(TermKey *tk, size_t count);
+static void emit_codepoint(TermKey *tk, long codepoint, TermKeyKey *key);
+static TermKeyResult peekkey_simple(TermKey *tk, TermKeyKey *key, int force, size_t *nbytes);
+static TermKeyResult peekkey_mouse(TermKey *tk, TermKeyKey *key, size_t *nbytes);
+
+static TermKeySym register_c0(TermKey *tk, TermKeySym sym, unsigned char ctrl, const char *name);
+static TermKeySym register_c0_full(TermKey *tk, TermKeySym sym, int modifier_set, int modifier_mask, unsigned char ctrl, const char *name);
+
+static struct {
+ TermKeySym sym;
+ const char *name;
+} keynames[] = {
+ { TERMKEY_SYM_NONE, "NONE" },
+ { TERMKEY_SYM_BACKSPACE, "Backspace" },
+ { TERMKEY_SYM_TAB, "Tab" },
+ { TERMKEY_SYM_ENTER, "Enter" },
+ { TERMKEY_SYM_ESCAPE, "Escape" },
+ { TERMKEY_SYM_SPACE, "Space" },
+ { TERMKEY_SYM_DEL, "DEL" },
+ { TERMKEY_SYM_UP, "Up" },
+ { TERMKEY_SYM_DOWN, "Down" },
+ { TERMKEY_SYM_LEFT, "Left" },
+ { TERMKEY_SYM_RIGHT, "Right" },
+ { TERMKEY_SYM_BEGIN, "Begin" },
+ { TERMKEY_SYM_FIND, "Find" },
+ { TERMKEY_SYM_INSERT, "Insert" },
+ { TERMKEY_SYM_DELETE, "Delete" },
+ { TERMKEY_SYM_SELECT, "Select" },
+ { TERMKEY_SYM_PAGEUP, "PageUp" },
+ { TERMKEY_SYM_PAGEDOWN, "PageDown" },
+ { TERMKEY_SYM_HOME, "Home" },
+ { TERMKEY_SYM_END, "End" },
+ { TERMKEY_SYM_CANCEL, "Cancel" },
+ { TERMKEY_SYM_CLEAR, "Clear" },
+ { TERMKEY_SYM_CLOSE, "Close" },
+ { TERMKEY_SYM_COMMAND, "Command" },
+ { TERMKEY_SYM_COPY, "Copy" },
+ { TERMKEY_SYM_EXIT, "Exit" },
+ { TERMKEY_SYM_HELP, "Help" },
+ { TERMKEY_SYM_MARK, "Mark" },
+ { TERMKEY_SYM_MESSAGE, "Message" },
+ { TERMKEY_SYM_MOVE, "Move" },
+ { TERMKEY_SYM_OPEN, "Open" },
+ { TERMKEY_SYM_OPTIONS, "Options" },
+ { TERMKEY_SYM_PRINT, "Print" },
+ { TERMKEY_SYM_REDO, "Redo" },
+ { TERMKEY_SYM_REFERENCE, "Reference" },
+ { TERMKEY_SYM_REFRESH, "Refresh" },
+ { TERMKEY_SYM_REPLACE, "Replace" },
+ { TERMKEY_SYM_RESTART, "Restart" },
+ { TERMKEY_SYM_RESUME, "Resume" },
+ { TERMKEY_SYM_SAVE, "Save" },
+ { TERMKEY_SYM_SUSPEND, "Suspend" },
+ { TERMKEY_SYM_UNDO, "Undo" },
+ { TERMKEY_SYM_KP0, "KP0" },
+ { TERMKEY_SYM_KP1, "KP1" },
+ { TERMKEY_SYM_KP2, "KP2" },
+ { TERMKEY_SYM_KP3, "KP3" },
+ { TERMKEY_SYM_KP4, "KP4" },
+ { TERMKEY_SYM_KP5, "KP5" },
+ { TERMKEY_SYM_KP6, "KP6" },
+ { TERMKEY_SYM_KP7, "KP7" },
+ { TERMKEY_SYM_KP8, "KP8" },
+ { TERMKEY_SYM_KP9, "KP9" },
+ { TERMKEY_SYM_KPENTER, "KPEnter" },
+ { TERMKEY_SYM_KPPLUS, "KPPlus" },
+ { TERMKEY_SYM_KPMINUS, "KPMinus" },
+ { TERMKEY_SYM_KPMULT, "KPMult" },
+ { TERMKEY_SYM_KPDIV, "KPDiv" },
+ { TERMKEY_SYM_KPCOMMA, "KPComma" },
+ { TERMKEY_SYM_KPPERIOD, "KPPeriod" },
+ { TERMKEY_SYM_KPEQUALS, "KPEquals" },
+ { 0, NULL },
+};
+
+// Mouse event names
+static const char *evnames[] = { "Unknown", "Press", "Drag", "Release" };
+
+#define CHARAT(i) (tk->buffer[tk->buffstart + (i)])
+
+#ifdef DEBUG
+/* Some internal debugging functions */
+
+static void print_buffer(TermKey *tk)
+{
+ int i;
+ for(i = 0; i < tk->buffcount && i < 20; i++)
+ fprintf(stderr, "%02x ", CHARAT(i));
+ if(tk->buffcount > 20)
+ fprintf(stderr, "...");
+}
+
+static void print_key(TermKey *tk, TermKeyKey *key)
+{
+ switch(key->type) {
+ case TERMKEY_TYPE_UNICODE:
+ fprintf(stderr, "Unicode codepoint=U+%04lx utf8='%s'", key->code.codepoint, key->utf8);
+ break;
+ case TERMKEY_TYPE_FUNCTION:
+ fprintf(stderr, "Function F%d", key->code.number);
+ break;
+ case TERMKEY_TYPE_KEYSYM:
+ fprintf(stderr, "Keysym sym=%d(%s)", key->code.sym, termkey_get_keyname(tk, key->code.sym));
+ break;
+ case TERMKEY_TYPE_MOUSE:
+ {
+ TermKeyMouseEvent ev;
+ int button, line, col;
+ termkey_interpret_mouse(tk, key, &ev, &button, &line, &col);
+ fprintf(stderr, "Mouse ev=%d button=%d pos=(%d,%d)\n", ev, button, line, col);
+ }
+ break;
+ case TERMKEY_TYPE_POSITION:
+ {
+ int line, col;
+ termkey_interpret_position(tk, key, &line, &col);
+ fprintf(stderr, "Position report pos=(%d,%d)\n", line, col);
+ }
+ break;
+ case TERMKEY_TYPE_MODEREPORT:
+ {
+ int initial, mode, value;
+ termkey_interpret_modereport(tk, key, &initial, &mode, &value);
+ fprintf(stderr, "Mode report mode=%s %d val=%d\n", initial == '?' ? "DEC" : "ANSI", mode, value);
+ }
+ break;
+ case TERMKEY_TYPE_DCS:
+ fprintf(stderr, "Device Control String");
+ break;
+ case TERMKEY_TYPE_OSC:
+ fprintf(stderr, "Operating System Control");
+ break;
+ case TERMKEY_TYPE_UNKNOWN_CSI:
+ fprintf(stderr, "unknown CSI\n");
+ break;
+ }
+
+ int m = key->modifiers;
+ fprintf(stderr, " mod=%s%s%s+%02x",
+ (m & TERMKEY_KEYMOD_CTRL ? "C" : ""),
+ (m & TERMKEY_KEYMOD_ALT ? "A" : ""),
+ (m & TERMKEY_KEYMOD_SHIFT ? "S" : ""),
+ m & ~(TERMKEY_KEYMOD_CTRL|TERMKEY_KEYMOD_ALT|TERMKEY_KEYMOD_SHIFT));
+}
+
+static const char *res2str(TermKeyResult res)
+{
+ static char errorbuffer[256];
+
+ switch(res) {
+ case TERMKEY_RES_KEY:
+ return "TERMKEY_RES_KEY";
+ case TERMKEY_RES_EOF:
+ return "TERMKEY_RES_EOF";
+ case TERMKEY_RES_AGAIN:
+ return "TERMKEY_RES_AGAIN";
+ case TERMKEY_RES_NONE:
+ return "TERMKEY_RES_NONE";
+ case TERMKEY_RES_ERROR:
+ snprintf(errorbuffer, sizeof errorbuffer, "TERMKEY_RES_ERROR(errno=%d)\n", errno);
+ return (const char*)errorbuffer;
+ }
+
+ return "unknown";
+}
+#endif
+
+/* Similar to snprintf(str, size, "%s", src) except it turns CamelCase into
+ * space separated values
+ */
+static int snprint_cameltospaces(char *str, size_t size, const char *src)
+{
+ int prev_lower = 0;
+ size_t l = 0;
+ while(*src && l < size - 1) {
+ if(isupper(*src) && prev_lower) {
+ if(str)
+ str[l++] = ' ';
+ if(l >= size - 1)
+ break;
+ }
+ prev_lower = islower(*src);
+ str[l++] = tolower(*src++);
+ }
+ str[l] = 0;
+ /* For consistency with snprintf, return the number of bytes that would have
+ * been written, excluding '\0' */
+ while(*src) {
+ if(isupper(*src) && prev_lower) {
+ l++;
+ }
+ prev_lower = islower(*src);
+ src++; l++;
+ }
+ return l;
+}
+
+/* Similar to strcmp(str, strcamel, n) except that:
+ * it compares CamelCase in strcamel with space separated values in str;
+ * it takes char**s and updates them
+ * n counts bytes of strcamel, not str
+ */
+static int strpncmp_camel(const char **strp, const char **strcamelp, size_t n)
+{
+ const char *str = *strp, *strcamel = *strcamelp;
+ int prev_lower = 0;
+
+ for( ; (*str || *strcamel) && n; n--) {
+ char b = tolower(*strcamel);
+ if(isupper(*strcamel) && prev_lower) {
+ if(*str != ' ')
+ break;
+ str++;
+ if(*str != b)
+ break;
+ }
+ else
+ if(*str != b)
+ break;
+
+ prev_lower = islower(*strcamel);
+
+ str++;
+ strcamel++;
+ }
+
+ *strp = str;
+ *strcamelp = strcamel;
+ return *str - *strcamel;
+}
+
+static TermKey *termkey_alloc(void)
+{
+ TermKey *tk = malloc(sizeof(TermKey));
+ if(!tk)
+ return NULL;
+
+ /* Default all the object fields but don't allocate anything */
+
+ tk->fd = -1;
+ tk->flags = 0;
+ tk->canonflags = 0;
+
+ tk->buffer = NULL;
+ tk->buffstart = 0;
+ tk->buffcount = 0;
+ tk->buffsize = 256; /* bytes */
+ tk->hightide = 0;
+
+#ifdef HAVE_TERMIOS
+ tk->restore_termios_valid = 0;
+#endif
+
+ tk->ti_getstr_hook = NULL;
+ tk->ti_getstr_hook_data = NULL;
+
+ tk->waittime = 50; /* msec */
+
+ tk->is_closed = 0;
+ tk->is_started = 0;
+
+ tk->nkeynames = 64;
+ tk->keynames = NULL;
+
+ for(int i = 0; i < 32; i++)
+ tk->c0[i].sym = TERMKEY_SYM_NONE;
+
+ tk->drivers = NULL;
+
+ tk->method.emit_codepoint = &emit_codepoint;
+ tk->method.peekkey_simple = &peekkey_simple;
+ tk->method.peekkey_mouse = &peekkey_mouse;
+
+ return tk;
+}
+
+static int termkey_init(TermKey *tk, const char *term)
+{
+ tk->buffer = malloc(tk->buffsize);
+ if(!tk->buffer)
+ return 0;
+
+ tk->keynames = malloc(sizeof(tk->keynames[0]) * tk->nkeynames);
+ if(!tk->keynames)
+ goto abort_free_buffer;
+
+ int i;
+ for(i = 0; i < tk->nkeynames; i++)
+ tk->keynames[i] = NULL;
+
+ for(i = 0; keynames[i].name; i++)
+ if(termkey_register_keyname(tk, keynames[i].sym, keynames[i].name) == -1)
+ goto abort_free_keynames;
+
+ register_c0(tk, TERMKEY_SYM_TAB, 0x09, NULL);
+ register_c0(tk, TERMKEY_SYM_ENTER, 0x0d, NULL);
+ register_c0(tk, TERMKEY_SYM_ESCAPE, 0x1b, NULL);
+
+ struct TermKeyDriverNode *tail = NULL;
+
+ for(i = 0; drivers[i]; i++) {
+ void *info = (*drivers[i]->new_driver)(tk, term);
+ if(!info)
+ continue;
+
+#ifdef DEBUG
+ fprintf(stderr, "Loading the %s driver...\n", drivers[i]->name);
+#endif
+
+ struct TermKeyDriverNode *thisdrv = malloc(sizeof(*thisdrv));
+ if(!thisdrv)
+ goto abort_free_drivers;
+
+ thisdrv->driver = drivers[i];
+ thisdrv->info = info;
+ thisdrv->next = NULL;
+
+ if(!tail)
+ tk->drivers = thisdrv;
+ else
+ tail->next = thisdrv;
+
+ tail = thisdrv;
+
+#ifdef DEBUG
+ fprintf(stderr, "Loaded %s driver\n", drivers[i]->name);
+#endif
+ }
+
+ if(!tk->drivers) {
+ errno = ENOENT;
+ goto abort_free_keynames;
+ }
+
+ return 1;
+
+abort_free_drivers:
+ for(struct TermKeyDriverNode *p = tk->drivers; p; ) {
+ (*p->driver->free_driver)(p->info);
+ struct TermKeyDriverNode *next = p->next;
+ free(p);
+ p = next;
+ }
+
+abort_free_keynames:
+ free(tk->keynames);
+
+abort_free_buffer:
+ free(tk->buffer);
+
+ return 0;
+}
+
+TermKey *termkey_new(int fd, int flags)
+{
+ TermKey *tk = termkey_alloc();
+ if(!tk)
+ return NULL;
+
+ tk->fd = fd;
+
+ if(!(flags & (TERMKEY_FLAG_RAW|TERMKEY_FLAG_UTF8))) {
+ char *e;
+
+ /* Most OSes will set .UTF-8. Some will set .utf8. Try to be fairly
+ * generous in parsing these
+ */
+ if(((e = getenv("LANG")) || (e = getenv("LC_MESSAGES")) || (e = getenv("LC_ALL"))) &&
+ (e = strchr(e, '.')) && e++ &&
+ (strcaseeq(e, "UTF-8") || strcaseeq(e, "UTF8")))
+ flags |= TERMKEY_FLAG_UTF8;
+ else
+ flags |= TERMKEY_FLAG_RAW;
+ }
+
+ termkey_set_flags(tk, flags);
+
+ const char *term = getenv("TERM");
+
+ if(!termkey_init(tk, term))
+ goto abort;
+
+ if(!(flags & TERMKEY_FLAG_NOSTART) && !termkey_start(tk))
+ goto abort;
+
+ return tk;
+
+abort:
+ free(tk);
+ return NULL;
+}
+
+TermKey *termkey_new_abstract(const char *term, int flags)
+{
+ TermKey *tk = termkey_alloc();
+ if(!tk)
+ return NULL;
+
+ tk->fd = -1;
+
+ termkey_set_flags(tk, flags);
+
+ if(!termkey_init(tk, term)) {
+ free(tk);
+ return NULL;
+ }
+
+ if(!(flags & TERMKEY_FLAG_NOSTART) && !termkey_start(tk))
+ goto abort;
+
+ return tk;
+
+abort:
+ free(tk);
+ return NULL;
+}
+
+void termkey_free(TermKey *tk)
+{
+ free(tk->buffer); tk->buffer = NULL;
+ free(tk->keynames); tk->keynames = NULL;
+
+ struct TermKeyDriverNode *p;
+ for(p = tk->drivers; p; ) {
+ (*p->driver->free_driver)(p->info);
+ struct TermKeyDriverNode *next = p->next;
+ free(p);
+ p = next;
+ }
+
+ free(tk);
+}
+
+void termkey_destroy(TermKey *tk)
+{
+ if(tk->is_started)
+ termkey_stop(tk);
+
+ termkey_free(tk);
+}
+
+void termkey_hook_terminfo_getstr(TermKey *tk, TermKey_Terminfo_Getstr_Hook *hookfn, void *data)
+{
+ tk->ti_getstr_hook = hookfn;
+ tk->ti_getstr_hook_data = data;
+}
+
+int termkey_start(TermKey *tk)
+{
+ if(tk->is_started)
+ return 1;
+
+#ifdef HAVE_TERMIOS
+ if(tk->fd != -1 && !(tk->flags & TERMKEY_FLAG_NOTERMIOS)) {
+ struct termios termios;
+ if(tcgetattr(tk->fd, &termios) == 0) {
+ tk->restore_termios = termios;
+ tk->restore_termios_valid = 1;
+
+ termios.c_iflag &= ~(IXON|INLCR|ICRNL);
+ termios.c_lflag &= ~(ICANON|ECHO
+#ifdef IEXTEN
+ | IEXTEN
+#endif
+ );
+ termios.c_cc[VMIN] = 1;
+ termios.c_cc[VTIME] = 0;
+
+ if(tk->flags & TERMKEY_FLAG_CTRLC)
+ /* want no signal keys at all, so just disable ISIG */
+ termios.c_lflag &= ~ISIG;
+ else {
+ /* Disable Ctrl-\==VQUIT and Ctrl-D==VSUSP but leave Ctrl-C as SIGINT */
+ termios.c_cc[VQUIT] = _POSIX_VDISABLE;
+ termios.c_cc[VSUSP] = _POSIX_VDISABLE;
+ /* Some OSes have Ctrl-Y==VDSUSP */
+#ifdef VDSUSP
+ termios.c_cc[VDSUSP] = _POSIX_VDISABLE;
+#endif
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "Setting termios(3) flags\n");
+#endif
+ tcsetattr(tk->fd, TCSANOW, &termios);
+ }
+ }
+#endif
+
+ struct TermKeyDriverNode *p;
+ for(p = tk->drivers; p; p = p->next)
+ if(p->driver->start_driver)
+ if(!(*p->driver->start_driver)(tk, p->info))
+ return 0;
+
+#ifdef DEBUG
+ fprintf(stderr, "Drivers started; termkey instance %p is ready\n", tk);
+#endif
+
+ tk->is_started = 1;
+ return 1;
+}
+
+int termkey_stop(TermKey *tk)
+{
+ if(!tk->is_started)
+ return 1;
+
+ struct TermKeyDriverNode *p;
+ for(p = tk->drivers; p; p = p->next)
+ if(p->driver->stop_driver)
+ (*p->driver->stop_driver)(tk, p->info);
+
+#ifdef HAVE_TERMIOS
+ if(tk->restore_termios_valid)
+ tcsetattr(tk->fd, TCSANOW, &tk->restore_termios);
+#endif
+
+ tk->is_started = 0;
+
+ return 1;
+}
+
+int termkey_is_started(TermKey *tk)
+{
+ return tk->is_started;
+}
+
+int termkey_get_fd(TermKey *tk)
+{
+ return tk->fd;
+}
+
+int termkey_get_flags(TermKey *tk)
+{
+ return tk->flags;
+}
+
+void termkey_set_flags(TermKey *tk, int newflags)
+{
+ tk->flags = newflags;
+
+ if(tk->flags & TERMKEY_FLAG_SPACESYMBOL)
+ tk->canonflags |= TERMKEY_CANON_SPACESYMBOL;
+ else
+ tk->canonflags &= ~TERMKEY_CANON_SPACESYMBOL;
+}
+
+void termkey_set_waittime(TermKey *tk, int msec)
+{
+ tk->waittime = msec;
+}
+
+int termkey_get_waittime(TermKey *tk)
+{
+ return tk->waittime;
+}
+
+int termkey_get_canonflags(TermKey *tk)
+{
+ return tk->canonflags;
+}
+
+void termkey_set_canonflags(TermKey *tk, int flags)
+{
+ tk->canonflags = flags;
+
+ if(tk->canonflags & TERMKEY_CANON_SPACESYMBOL)
+ tk->flags |= TERMKEY_FLAG_SPACESYMBOL;
+ else
+ tk->flags &= ~TERMKEY_FLAG_SPACESYMBOL;
+}
+
+size_t termkey_get_buffer_size(TermKey *tk)
+{
+ return tk->buffsize;
+}
+
+int termkey_set_buffer_size(TermKey *tk, size_t size)
+{
+ unsigned char *buffer = realloc(tk->buffer, size);
+ if(!buffer)
+ return 0;
+
+ tk->buffer = buffer;
+ tk->buffsize = size;
+
+ return 1;
+}
+
+size_t termkey_get_buffer_remaining(TermKey *tk)
+{
+ /* Return the total number of free bytes in the buffer, because that's what
+ * is available to the user. */
+ return tk->buffsize - tk->buffcount;
+}
+
+static void eat_bytes(TermKey *tk, size_t count)
+{
+ if(count >= tk->buffcount) {
+ tk->buffstart = 0;
+ tk->buffcount = 0;
+ return;
+ }
+
+ tk->buffstart += count;
+ tk->buffcount -= count;
+}
+
+static inline unsigned int utf8_seqlen(long codepoint)
+{
+ if(codepoint < 0x0000080) return 1;
+ if(codepoint < 0x0000800) return 2;
+ if(codepoint < 0x0010000) return 3;
+ if(codepoint < 0x0200000) return 4;
+ if(codepoint < 0x4000000) return 5;
+ return 6;
+}
+
+static void fill_utf8(TermKeyKey *key)
+{
+ long codepoint = key->code.codepoint;
+ int nbytes = utf8_seqlen(codepoint);
+
+ key->utf8[nbytes] = 0;
+
+ // This is easier done backwards
+ int b = nbytes;
+ while(b > 1) {
+ b--;
+ key->utf8[b] = 0x80 | (codepoint & 0x3f);
+ codepoint >>= 6;
+ }
+
+ switch(nbytes) {
+ case 1: key->utf8[0] = (codepoint & 0x7f); break;
+ case 2: key->utf8[0] = 0xc0 | (codepoint & 0x1f); break;
+ case 3: key->utf8[0] = 0xe0 | (codepoint & 0x0f); break;
+ case 4: key->utf8[0] = 0xf0 | (codepoint & 0x07); break;
+ case 5: key->utf8[0] = 0xf8 | (codepoint & 0x03); break;
+ case 6: key->utf8[0] = 0xfc | (codepoint & 0x01); break;
+ }
+}
+
+#define UTF8_INVALID 0xFFFD
+static TermKeyResult parse_utf8(const unsigned char *bytes, size_t len, long *cp, size_t *nbytep)
+{
+ unsigned int nbytes;
+
+ unsigned char b0 = bytes[0];
+
+ if(b0 < 0x80) {
+ // Single byte ASCII
+ *cp = b0;
+ *nbytep = 1;
+ return TERMKEY_RES_KEY;
+ }
+ else if(b0 < 0xc0) {
+ // Starts with a continuation byte - that's not right
+ *cp = UTF8_INVALID;
+ *nbytep = 1;
+ return TERMKEY_RES_KEY;
+ }
+ else if(b0 < 0xe0) {
+ nbytes = 2;
+ *cp = b0 & 0x1f;
+ }
+ else if(b0 < 0xf0) {
+ nbytes = 3;
+ *cp = b0 & 0x0f;
+ }
+ else if(b0 < 0xf8) {
+ nbytes = 4;
+ *cp = b0 & 0x07;
+ }
+ else if(b0 < 0xfc) {
+ nbytes = 5;
+ *cp = b0 & 0x03;
+ }
+ else if(b0 < 0xfe) {
+ nbytes = 6;
+ *cp = b0 & 0x01;
+ }
+ else {
+ *cp = UTF8_INVALID;
+ *nbytep = 1;
+ return TERMKEY_RES_KEY;
+ }
+
+ for(unsigned int b = 1; b < nbytes; b++) {
+ unsigned char cb;
+
+ if(b >= len)
+ return TERMKEY_RES_AGAIN;
+
+ cb = bytes[b];
+ if(cb < 0x80 || cb >= 0xc0) {
+ *cp = UTF8_INVALID;
+ *nbytep = b;
+ return TERMKEY_RES_KEY;
+ }
+
+ *cp <<= 6;
+ *cp |= cb & 0x3f;
+ }
+
+ // Check for overlong sequences
+ if(nbytes > utf8_seqlen(*cp))
+ *cp = UTF8_INVALID;
+
+ // Check for UTF-16 surrogates or invalid *cps
+ if((*cp >= 0xD800 && *cp <= 0xDFFF) ||
+ *cp == 0xFFFE ||
+ *cp == 0xFFFF)
+ *cp = UTF8_INVALID;
+
+ *nbytep = nbytes;
+ return TERMKEY_RES_KEY;
+}
+
+static void emit_codepoint(TermKey *tk, long codepoint, TermKeyKey *key)
+{
+ if(codepoint == 0) {
+ // ASCII NUL = Ctrl-Space
+ key->type = TERMKEY_TYPE_KEYSYM;
+ key->code.sym = TERMKEY_SYM_SPACE;
+ key->modifiers = TERMKEY_KEYMOD_CTRL;
+ }
+ else if(codepoint < 0x20) {
+ // C0 range
+ key->code.codepoint = 0;
+ key->modifiers = 0;
+
+ if(!(tk->flags & TERMKEY_FLAG_NOINTERPRET) && tk->c0[codepoint].sym != TERMKEY_SYM_UNKNOWN) {
+ key->code.sym = tk->c0[codepoint].sym;
+ key->modifiers |= tk->c0[codepoint].modifier_set;
+ }
+
+ if(!key->code.sym) {
+ key->type = TERMKEY_TYPE_UNICODE;
+ /* Generically modified Unicode ought not report the SHIFT state, or else
+ * we get into complications trying to report Shift-; vs : and so on...
+ * In order to be able to represent Ctrl-Shift-A as CTRL modified
+ * unicode A, we need to call Ctrl-A simply 'a', lowercase
+ */
+ if(codepoint+0x40 >= 'A' && codepoint+0x40 <= 'Z')
+ // it's a letter - use lowercase instead
+ key->code.codepoint = codepoint + 0x60;
+ else
+ key->code.codepoint = codepoint + 0x40;
+ key->modifiers = TERMKEY_KEYMOD_CTRL;
+ }
+ else {
+ key->type = TERMKEY_TYPE_KEYSYM;
+ }
+ }
+ else if(codepoint == 0x7f && !(tk->flags & TERMKEY_FLAG_NOINTERPRET)) {
+ // ASCII DEL
+ key->type = TERMKEY_TYPE_KEYSYM;
+ key->code.sym = TERMKEY_SYM_DEL;
+ key->modifiers = 0;
+ }
+ else if(codepoint >= 0x20 && codepoint < 0x80) {
+ // ASCII lowbyte range
+ key->type = TERMKEY_TYPE_UNICODE;
+ key->code.codepoint = codepoint;
+ key->modifiers = 0;
+ }
+ else if(codepoint >= 0x80 && codepoint < 0xa0) {
+ // UTF-8 never starts with a C1 byte. So we can be sure of these
+ key->type = TERMKEY_TYPE_UNICODE;
+ key->code.codepoint = codepoint - 0x40;
+ key->modifiers = TERMKEY_KEYMOD_CTRL|TERMKEY_KEYMOD_ALT;
+ }
+ else {
+ // UTF-8 codepoint
+ key->type = TERMKEY_TYPE_UNICODE;
+ key->code.codepoint = codepoint;
+ key->modifiers = 0;
+ }
+
+ termkey_canonicalise(tk, key);
+
+ if(key->type == TERMKEY_TYPE_UNICODE)
+ fill_utf8(key);
+}
+
+void termkey_canonicalise(TermKey *tk, TermKeyKey *key)
+{
+ int flags = tk->canonflags;
+
+ if(flags & TERMKEY_CANON_SPACESYMBOL) {
+ if(key->type == TERMKEY_TYPE_UNICODE && key->code.codepoint == 0x20) {
+ key->type = TERMKEY_TYPE_KEYSYM;
+ key->code.sym = TERMKEY_SYM_SPACE;
+ }
+ }
+ else {
+ if(key->type == TERMKEY_TYPE_KEYSYM && key->code.sym == TERMKEY_SYM_SPACE) {
+ key->type = TERMKEY_TYPE_UNICODE;
+ key->code.codepoint = 0x20;
+ fill_utf8(key);
+ }
+ }
+
+ if(flags & TERMKEY_CANON_DELBS) {
+ if(key->type == TERMKEY_TYPE_KEYSYM && key->code.sym == TERMKEY_SYM_DEL) {
+ key->code.sym = TERMKEY_SYM_BACKSPACE;
+ }
+ }
+}
+
+static TermKeyResult peekkey(TermKey *tk, TermKeyKey *key, int force, size_t *nbytep)
+{
+ int again = 0;
+
+ if(!tk->is_started) {
+ errno = EINVAL;
+ return TERMKEY_RES_ERROR;
+ }
+
+#ifdef DEBUG
+ fprintf(stderr, "getkey(force=%d): buffer ", force);
+ print_buffer(tk);
+ fprintf(stderr, "\n");
+#endif
+
+ if(tk->hightide) {
+ tk->buffstart += tk->hightide;
+ tk->buffcount -= tk->hightide;
+ tk->hightide = 0;
+ }
+
+ TermKeyResult ret;
+ struct TermKeyDriverNode *p;
+ for(p = tk->drivers; p; p = p->next) {
+ ret = (p->driver->peekkey)(tk, p->info, key, force, nbytep);
+
+#ifdef DEBUG
+ fprintf(stderr, "Driver %s yields %s\n", p->driver->name, res2str(ret));
+#endif
+
+ switch(ret) {
+ case TERMKEY_RES_KEY:
+#ifdef DEBUG
+ print_key(tk, key); fprintf(stderr, "\n");
+#endif
+ // Slide the data down to stop it running away
+ {
+ size_t halfsize = tk->buffsize / 2;
+
+ if(tk->buffstart > halfsize) {
+ memcpy(tk->buffer, tk->buffer + halfsize, halfsize);
+ tk->buffstart -= halfsize;
+ }
+ }
+
+ /* fallthrough */
+ case TERMKEY_RES_EOF:
+ case TERMKEY_RES_ERROR:
+ return ret;
+
+ case TERMKEY_RES_AGAIN:
+ if(!force)
+ again = 1;
+
+ /* fallthrough */
+ case TERMKEY_RES_NONE:
+ break;
+ }
+ }
+
+ if(again)
+ return TERMKEY_RES_AGAIN;
+
+ ret = peekkey_simple(tk, key, force, nbytep);
+
+#ifdef DEBUG
+ fprintf(stderr, "getkey_simple(force=%d) yields %s\n", force, res2str(ret));
+ if(ret == TERMKEY_RES_KEY) {
+ print_key(tk, key); fprintf(stderr, "\n");
+ }
+#endif
+
+ return ret;
+}
+
+static TermKeyResult peekkey_simple(TermKey *tk, TermKeyKey *key, int force, size_t *nbytep)
+{
+ if(tk->buffcount == 0)
+ return tk->is_closed ? TERMKEY_RES_EOF : TERMKEY_RES_NONE;
+
+ unsigned char b0 = CHARAT(0);
+
+ if(b0 == 0x1b) {
+ // Escape-prefixed value? Might therefore be Alt+key
+ if(tk->buffcount == 1) {
+ // This might be an <Esc> press, or it may want to be part of a longer
+ // sequence
+ if(!force)
+ return TERMKEY_RES_AGAIN;
+
+ (*tk->method.emit_codepoint)(tk, b0, key);
+ *nbytep = 1;
+ return TERMKEY_RES_KEY;
+ }
+
+ // Try another key there
+ tk->buffstart++;
+ tk->buffcount--;
+
+ // Run the full driver
+ TermKeyResult metakey_result = peekkey(tk, key, force, nbytep);
+
+ tk->buffstart--;
+ tk->buffcount++;
+
+ switch(metakey_result) {
+ case TERMKEY_RES_KEY:
+ key->modifiers |= TERMKEY_KEYMOD_ALT;
+ (*nbytep)++;
+ break;
+
+ case TERMKEY_RES_NONE:
+ case TERMKEY_RES_EOF:
+ case TERMKEY_RES_AGAIN:
+ case TERMKEY_RES_ERROR:
+ break;
+ }
+
+ return metakey_result;
+ }
+ else if(b0 < 0xa0) {
+ // Single byte C0, G0 or C1 - C1 is never UTF-8 initial byte
+ (*tk->method.emit_codepoint)(tk, b0, key);
+ *nbytep = 1;
+ return TERMKEY_RES_KEY;
+ }
+ else if(tk->flags & TERMKEY_FLAG_UTF8) {
+ // Some UTF-8
+ long codepoint;
+ TermKeyResult res = parse_utf8(tk->buffer + tk->buffstart, tk->buffcount, &codepoint, nbytep);
+
+ if(res == TERMKEY_RES_AGAIN && force) {
+ /* There weren't enough bytes for a complete UTF-8 sequence but caller
+ * demands an answer. About the best thing we can do here is eat as many
+ * bytes as we have, and emit a UTF8_INVALID. If the remaining bytes
+ * arrive later, they'll be invalid too.
+ */
+ codepoint = UTF8_INVALID;
+ *nbytep = tk->buffcount;
+ res = TERMKEY_RES_KEY;
+ }
+
+ key->type = TERMKEY_TYPE_UNICODE;
+ key->modifiers = 0;
+ (*tk->method.emit_codepoint)(tk, codepoint, key);
+ return res;
+ }
+ else {
+ // Non UTF-8 case - just report the raw byte
+ key->type = TERMKEY_TYPE_UNICODE;
+ key->code.codepoint = b0;
+ key->modifiers = 0;
+
+ key->utf8[0] = key->code.codepoint;
+ key->utf8[1] = 0;
+
+ *nbytep = 1;
+
+ return TERMKEY_RES_KEY;
+ }
+}
+
+static TermKeyResult peekkey_mouse(TermKey *tk, TermKeyKey *key, size_t *nbytep)
+{
+ if(tk->buffcount < 3)
+ return TERMKEY_RES_AGAIN;
+
+ key->type = TERMKEY_TYPE_MOUSE;
+ key->code.mouse[0] = CHARAT(0) - 0x20;
+ key->code.mouse[1] = CHARAT(1) - 0x20;
+ key->code.mouse[2] = CHARAT(2) - 0x20;
+ key->code.mouse[3] = 0;
+
+ key->modifiers = (key->code.mouse[0] & 0x1c) >> 2;
+ key->code.mouse[0] &= ~0x1c;
+
+ *nbytep = 3;
+ return TERMKEY_RES_KEY;
+}
+
+TermKeyResult termkey_getkey(TermKey *tk, TermKeyKey *key)
+{
+ size_t nbytes = 0;
+ TermKeyResult ret = peekkey(tk, key, 0, &nbytes);
+
+ if(ret == TERMKEY_RES_KEY)
+ eat_bytes(tk, nbytes);
+
+ if(ret == TERMKEY_RES_AGAIN)
+ /* Call peekkey() again in force mode to obtain whatever it can */
+ (void)peekkey(tk, key, 1, &nbytes);
+ /* Don't eat it yet though */
+
+ return ret;
+}
+
+TermKeyResult termkey_getkey_force(TermKey *tk, TermKeyKey *key)
+{
+ size_t nbytes = 0;
+ TermKeyResult ret = peekkey(tk, key, 1, &nbytes);
+
+ if(ret == TERMKEY_RES_KEY)
+ eat_bytes(tk, nbytes);
+
+ return ret;
+}
+
+#ifndef _WIN32
+TermKeyResult termkey_waitkey(TermKey *tk, TermKeyKey *key)
+{
+ if(tk->fd == -1) {
+ errno = EBADF;
+ return TERMKEY_RES_ERROR;
+ }
+
+ while(1) {
+ TermKeyResult ret = termkey_getkey(tk, key);
+
+ switch(ret) {
+ case TERMKEY_RES_KEY:
+ case TERMKEY_RES_EOF:
+ case TERMKEY_RES_ERROR:
+ return ret;
+
+ case TERMKEY_RES_NONE:
+ ret = termkey_advisereadable(tk);
+ if(ret == TERMKEY_RES_ERROR)
+ return ret;
+ break;
+
+ case TERMKEY_RES_AGAIN:
+ {
+ if(tk->is_closed)
+ // We're closed now. Never going to get more bytes so just go with
+ // what we have
+ return termkey_getkey_force(tk, key);
+
+ struct pollfd fd;
+
+retry:
+ fd.fd = tk->fd;
+ fd.events = POLLIN;
+
+ int pollret = poll(&fd, 1, tk->waittime);
+ if(pollret == -1) {
+ if(errno == EINTR && !(tk->flags & TERMKEY_FLAG_EINTR))
+ goto retry;
+
+ return TERMKEY_RES_ERROR;
+ }
+
+ if(fd.revents & (POLLIN|POLLHUP|POLLERR))
+ ret = termkey_advisereadable(tk);
+ else
+ ret = TERMKEY_RES_NONE;
+
+ if(ret == TERMKEY_RES_ERROR)
+ return ret;
+ if(ret == TERMKEY_RES_NONE)
+ return termkey_getkey_force(tk, key);
+ }
+ break;
+ }
+ }
+
+ /* UNREACHABLE */
+}
+#endif
+
+TermKeyResult termkey_advisereadable(TermKey *tk)
+{
+ ssize_t len;
+
+ if(tk->fd == -1) {
+ errno = EBADF;
+ return TERMKEY_RES_ERROR;
+ }
+
+ if(tk->buffstart) {
+ memmove(tk->buffer, tk->buffer + tk->buffstart, tk->buffcount);
+ tk->buffstart = 0;
+ }
+
+ /* Not expecting it ever to be greater but doesn't hurt to handle that */
+ if(tk->buffcount >= tk->buffsize) {
+ errno = ENOMEM;
+ return TERMKEY_RES_ERROR;
+ }
+
+retry:
+ len = read(tk->fd, tk->buffer + tk->buffcount, tk->buffsize - tk->buffcount);
+
+ if(len == -1) {
+ if(errno == EAGAIN)
+ return TERMKEY_RES_NONE;
+ else if(errno == EINTR && !(tk->flags & TERMKEY_FLAG_EINTR))
+ goto retry;
+ else
+ return TERMKEY_RES_ERROR;
+ }
+ else if(len < 1) {
+ tk->is_closed = 1;
+ return TERMKEY_RES_NONE;
+ }
+ else {
+ tk->buffcount += len;
+ return TERMKEY_RES_AGAIN;
+ }
+}
+
+size_t termkey_push_bytes(TermKey *tk, const char *bytes, size_t len)
+{
+ if(tk->buffstart) {
+ memmove(tk->buffer, tk->buffer + tk->buffstart, tk->buffcount);
+ tk->buffstart = 0;
+ }
+
+ /* Not expecting it ever to be greater but doesn't hurt to handle that */
+ if(tk->buffcount >= tk->buffsize) {
+ errno = ENOMEM;
+ return (size_t)-1;
+ }
+
+ if(len > tk->buffsize - tk->buffcount)
+ len = tk->buffsize - tk->buffcount;
+
+ // memcpy(), not strncpy() in case of null bytes in input
+ memcpy(tk->buffer + tk->buffcount, bytes, len);
+ tk->buffcount += len;
+
+ return len;
+}
+
+TermKeySym termkey_register_keyname(TermKey *tk, TermKeySym sym, const char *name)
+{
+ if(!sym)
+ sym = tk->nkeynames;
+
+ if(sym >= tk->nkeynames) {
+ const char **new_keynames = realloc(tk->keynames, sizeof(new_keynames[0]) * (sym + 1));
+ if(!new_keynames)
+ return -1;
+
+ tk->keynames = new_keynames;
+
+ // Fill in the hole
+ for(int i = tk->nkeynames; i < sym; i++)
+ tk->keynames[i] = NULL;
+
+ tk->nkeynames = sym + 1;
+ }
+
+ tk->keynames[sym] = name;
+
+ return sym;
+}
+
+const char *termkey_get_keyname(TermKey *tk, TermKeySym sym)
+{
+ if(sym == TERMKEY_SYM_UNKNOWN)
+ return "UNKNOWN";
+
+ if(sym < tk->nkeynames)
+ return tk->keynames[sym];
+
+ return "UNKNOWN";
+}
+
+static const char *termkey_lookup_keyname_format(TermKey *tk, const char *str, TermKeySym *sym, TermKeyFormat format)
+{
+ /* We store an array, so we can't do better than a linear search. Doesn't
+ * matter because user won't be calling this too often */
+
+ for(*sym = 0; *sym < tk->nkeynames; (*sym)++) {
+ const char *thiskey = tk->keynames[*sym];
+ if(!thiskey)
+ continue;
+ size_t len = strlen(thiskey);
+ if(format & TERMKEY_FORMAT_LOWERSPACE) {
+ const char *thisstr = str;
+ if(strpncmp_camel(&thisstr, &thiskey, len) == 0)
+ return thisstr;
+ }
+ else {
+ if(strncmp(str, thiskey, len) == 0)
+ return (char *)str + len;
+ }
+ }
+
+ return NULL;
+}
+
+const char *termkey_lookup_keyname(TermKey *tk, const char *str, TermKeySym *sym)
+{
+ return termkey_lookup_keyname_format(tk, str, sym, 0);
+}
+
+TermKeySym termkey_keyname2sym(TermKey *tk, const char *keyname)
+{
+ TermKeySym sym;
+ const char *endp = termkey_lookup_keyname(tk, keyname, &sym);
+ if(!endp || endp[0])
+ return TERMKEY_SYM_UNKNOWN;
+ return sym;
+}
+
+static TermKeySym register_c0(TermKey *tk, TermKeySym sym, unsigned char ctrl, const char *name)
+{
+ return register_c0_full(tk, sym, 0, 0, ctrl, name);
+}
+
+static TermKeySym register_c0_full(TermKey *tk, TermKeySym sym, int modifier_set, int modifier_mask, unsigned char ctrl, const char *name)
+{
+ if(ctrl >= 0x20) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if(name)
+ sym = termkey_register_keyname(tk, sym, name);
+
+ tk->c0[ctrl].sym = sym;
+ tk->c0[ctrl].modifier_set = modifier_set;
+ tk->c0[ctrl].modifier_mask = modifier_mask;
+
+ return sym;
+}
+
+/* Previous name for this function
+ * No longer declared in termkey.h but it remains in the compiled library for
+ * backward-compatibility reasons.
+ */
+size_t termkey_snprint_key(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format)
+{
+ return termkey_strfkey(tk, buffer, len, key, format);
+}
+
+static struct modnames {
+ const char *shift, *alt, *ctrl;
+}
+modnames[] = {
+ { "S", "A", "C" }, // 0
+ { "Shift", "Alt", "Ctrl" }, // LONGMOD
+ { "S", "M", "C" }, // ALTISMETA
+ { "Shift", "Meta", "Ctrl" }, // ALTISMETA+LONGMOD
+ { "s", "a", "c" }, // LOWERMOD
+ { "shift", "alt", "ctrl" }, // LOWERMOD+LONGMOD
+ { "s", "m", "c" }, // LOWERMOD+ALTISMETA
+ { "shift", "meta", "ctrl" }, // LOWERMOD+ALTISMETA+LONGMOD
+};
+
+size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format)
+{
+ size_t pos = 0;
+ size_t l = 0;
+
+ struct modnames *mods = &modnames[!!(format & TERMKEY_FORMAT_LONGMOD) +
+ !!(format & TERMKEY_FORMAT_ALTISMETA) * 2 +
+ !!(format & TERMKEY_FORMAT_LOWERMOD) * 4];
+
+ int wrapbracket = (format & TERMKEY_FORMAT_WRAPBRACKET) &&
+ (key->type != TERMKEY_TYPE_UNICODE || key->modifiers != 0);
+
+ char sep = (format & TERMKEY_FORMAT_SPACEMOD) ? ' ' : '-';
+
+ if(format & TERMKEY_FORMAT_CARETCTRL &&
+ key->type == TERMKEY_TYPE_UNICODE &&
+ key->modifiers == TERMKEY_KEYMOD_CTRL) {
+ long codepoint = key->code.codepoint;
+
+ // Handle some of the special cases first
+ if(codepoint >= 'a' && codepoint <= 'z') {
+ l = snprintf(buffer + pos, len - pos, wrapbracket ? "<^%c>" : "^%c", (char)codepoint - 0x20);
+ if(l <= 0) return pos;
+ pos += l;
+ return pos;
+ }
+ else if((codepoint >= '@' && codepoint < 'A') ||
+ (codepoint > 'Z' && codepoint <= '_')) {
+ l = snprintf(buffer + pos, len - pos, wrapbracket ? "<^%c>" : "^%c", (char)codepoint);
+ if(l <= 0) return pos;
+ pos += l;
+ return pos;
+ }
+ }
+
+ if(wrapbracket) {
+ l = snprintf(buffer + pos, len - pos, "<");
+ if(l <= 0) return pos;
+ pos += l;
+ }
+
+ if(key->modifiers & TERMKEY_KEYMOD_ALT) {
+ l = snprintf(buffer + pos, len - pos, "%s%c", mods->alt, sep);
+ if(l <= 0) return pos;
+ pos += l;
+ }
+
+ if(key->modifiers & TERMKEY_KEYMOD_CTRL) {
+ l = snprintf(buffer + pos, len - pos, "%s%c", mods->ctrl, sep);
+ if(l <= 0) return pos;
+ pos += l;
+ }
+
+ if(key->modifiers & TERMKEY_KEYMOD_SHIFT) {
+ l = snprintf(buffer + pos, len - pos, "%s%c", mods->shift, sep);
+ if(l <= 0) return pos;
+ pos += l;
+ }
+
+ switch(key->type) {
+ case TERMKEY_TYPE_UNICODE:
+ if(!key->utf8[0]) // In case of user-supplied key structures
+ fill_utf8(key);
+ l = snprintf(buffer + pos, len - pos, "%s", key->utf8);
+ break;
+ case TERMKEY_TYPE_KEYSYM:
+ {
+ const char *name = termkey_get_keyname(tk, key->code.sym);
+ if(format & TERMKEY_FORMAT_LOWERSPACE)
+ l = snprint_cameltospaces(buffer + pos, len - pos, name);
+ else
+ l = snprintf(buffer + pos, len - pos, "%s", name);
+ }
+ break;
+ case TERMKEY_TYPE_FUNCTION:
+ l = snprintf(buffer + pos, len - pos, "%c%d",
+ (format & TERMKEY_FORMAT_LOWERSPACE ? 'f' : 'F'), key->code.number);
+ break;
+ case TERMKEY_TYPE_MOUSE:
+ {
+ TermKeyMouseEvent ev;
+ int button;
+ int line, col;
+ termkey_interpret_mouse(tk, key, &ev, &button, &line, &col);
+
+ l = snprintf(buffer + pos, len - pos, "Mouse%s(%d)",
+ evnames[ev], button);
+
+ if(format & TERMKEY_FORMAT_MOUSE_POS) {
+ if(l <= 0) return pos;
+ pos += l;
+
+ l = snprintf(buffer + pos, len - pos, " @ (%u,%u)", col, line);
+ }
+ }
+ break;
+ case TERMKEY_TYPE_POSITION:
+ l = snprintf(buffer + pos, len - pos, "Position");
+ break;
+ case TERMKEY_TYPE_MODEREPORT:
+ {
+ int initial, mode, value;
+ termkey_interpret_modereport(tk, key, &initial, &mode, &value);
+ if(initial)
+ l = snprintf(buffer + pos, len - pos, "Mode(%c%d=%d)", initial, mode, value);
+ else
+ l = snprintf(buffer + pos, len - pos, "Mode(%d=%d)", mode, value);
+ }
+ case TERMKEY_TYPE_DCS:
+ l = snprintf(buffer + pos, len - pos, "DCS");
+ break;
+ case TERMKEY_TYPE_OSC:
+ l = snprintf(buffer + pos, len - pos, "OSC");
+ break;
+ case TERMKEY_TYPE_UNKNOWN_CSI:
+ l = snprintf(buffer + pos, len - pos, "CSI %c", key->code.number & 0xff);
+ break;
+ }
+
+ if(l <= 0) return pos;
+ pos += l;
+
+ if(wrapbracket) {
+ l = snprintf(buffer + pos, len - pos, ">");
+ if(l <= 0) return pos;
+ pos += l;
+ }
+
+ return pos;
+}
+
+const char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format)
+{
+ struct modnames *mods = &modnames[!!(format & TERMKEY_FORMAT_LONGMOD) +
+ !!(format & TERMKEY_FORMAT_ALTISMETA) * 2 +
+ !!(format & TERMKEY_FORMAT_LOWERMOD) * 4];
+
+ key->modifiers = 0;
+
+ if((format & TERMKEY_FORMAT_CARETCTRL) && str[0] == '^' && str[1]) {
+ str = termkey_strpkey(tk, str+1, key, format & ~TERMKEY_FORMAT_CARETCTRL);
+
+ if(!str ||
+ key->type != TERMKEY_TYPE_UNICODE ||
+ key->code.codepoint < '@' || key->code.codepoint > '_' ||
+ key->modifiers != 0)
+ return NULL;
+
+ if(key->code.codepoint >= 'A' && key->code.codepoint <= 'Z')
+ key->code.codepoint += 0x20;
+ key->modifiers = TERMKEY_KEYMOD_CTRL;
+ fill_utf8(key);
+ return (char *)str;
+ }
+
+ const char *sep_at;
+
+ while((sep_at = strchr(str, (format & TERMKEY_FORMAT_SPACEMOD) ? ' ' : '-'))) {
+ size_t n = sep_at - str;
+
+ if(n == strlen(mods->alt) && strncmp(mods->alt, str, n) == 0)
+ key->modifiers |= TERMKEY_KEYMOD_ALT;
+ else if(n == strlen(mods->ctrl) && strncmp(mods->ctrl, str, n) == 0)
+ key->modifiers |= TERMKEY_KEYMOD_CTRL;
+ else if(n == strlen(mods->shift) && strncmp(mods->shift, str, n) == 0)
+ key->modifiers |= TERMKEY_KEYMOD_SHIFT;
+
+ else
+ break;
+
+ str = sep_at + 1;
+ }
+
+ size_t nbytes;
+ ssize_t snbytes;
+ const char *endstr;
+ int button;
+ char event_name[32];
+
+ if((endstr = termkey_lookup_keyname_format(tk, str, &key->code.sym, format))) {
+ key->type = TERMKEY_TYPE_KEYSYM;
+ str = endstr;
+ }
+ else if(sscanf(str, "F%d%zn", &key->code.number, &snbytes) == 1) {
+ key->type = TERMKEY_TYPE_FUNCTION;
+ str += snbytes;
+ }
+ else if(sscanf(str, "Mouse%31[^(](%d)%zn", event_name, &button, &snbytes) == 2) {
+ str += snbytes;
+ key->type = TERMKEY_TYPE_MOUSE;
+
+ TermKeyMouseEvent ev = TERMKEY_MOUSE_UNKNOWN;
+ for(size_t i = 0; i < sizeof(evnames)/sizeof(evnames[0]); i++) {
+ if(strcmp(evnames[i], event_name) == 0) {
+ ev = TERMKEY_MOUSE_UNKNOWN + i;
+ break;
+ }
+ }
+
+ int code;
+ switch(ev) {
+ case TERMKEY_MOUSE_PRESS:
+ case TERMKEY_MOUSE_DRAG:
+ code = button - 1;
+ if(ev == TERMKEY_MOUSE_DRAG) {
+ code |= 0x20;
+ }
+ break;
+ case TERMKEY_MOUSE_RELEASE:
+ code = 3;
+ break;
+ default:
+ code = 128;
+ break;
+ }
+ key->code.mouse[0] = code;
+
+ unsigned int line = 0, col = 0;
+ if((format & TERMKEY_FORMAT_MOUSE_POS) && sscanf(str, " @ (%u,%u)%zn", &col, &line, &snbytes) == 2) {
+ str += snbytes;
+ }
+ termkey_key_set_linecol(key, col, line);
+ }
+ // Unicode must be last
+ else if(parse_utf8((unsigned const char *)str, strlen(str), &key->code.codepoint, &nbytes) == TERMKEY_RES_KEY) {
+ key->type = TERMKEY_TYPE_UNICODE;
+ fill_utf8(key);
+ str += nbytes;
+ }
+ else
+ return NULL;
+
+ termkey_canonicalise(tk, key);
+
+ return (char *)str;
+}
+
+int termkey_keycmp(TermKey *tk, const TermKeyKey *key1p, const TermKeyKey *key2p)
+{
+ /* Copy the key structs since we'll be modifying them */
+ TermKeyKey key1 = *key1p, key2 = *key2p;
+
+ termkey_canonicalise(tk, &key1);
+ termkey_canonicalise(tk, &key2);
+
+ if(key1.type != key2.type)
+ return key1.type - key2.type;
+
+ switch(key1.type) {
+ case TERMKEY_TYPE_UNICODE:
+ if(key1.code.codepoint != key2.code.codepoint)
+ return key1.code.codepoint - key2.code.codepoint;
+ break;
+ case TERMKEY_TYPE_KEYSYM:
+ if(key1.code.sym != key2.code.sym)
+ return key1.code.sym - key2.code.sym;
+ break;
+ case TERMKEY_TYPE_FUNCTION:
+ case TERMKEY_TYPE_UNKNOWN_CSI:
+ if(key1.code.number != key2.code.number)
+ return key1.code.number - key2.code.number;
+ break;
+ case TERMKEY_TYPE_MOUSE:
+ {
+ int cmp = strncmp(key1.code.mouse, key2.code.mouse, 4);
+ if(cmp != 0)
+ return cmp;
+ }
+ break;
+ case TERMKEY_TYPE_POSITION:
+ {
+ int line1, col1, line2, col2;
+ termkey_interpret_position(tk, &key1, &line1, &col1);
+ termkey_interpret_position(tk, &key2, &line2, &col2);
+ if(line1 != line2)
+ return line1 - line2;
+ return col1 - col2;
+ }
+ break;
+ case TERMKEY_TYPE_DCS:
+ case TERMKEY_TYPE_OSC:
+ return key1p - key2p;
+ case TERMKEY_TYPE_MODEREPORT:
+ {
+ int initial1, initial2, mode1, mode2, value1, value2;
+ termkey_interpret_modereport(tk, &key1, &initial1, &mode1, &value1);
+ termkey_interpret_modereport(tk, &key2, &initial2, &mode2, &value2);
+ if(initial1 != initial2)
+ return initial1 - initial2;
+ if(mode1 != mode2)
+ return mode1 - mode2;
+ return value1 - value2;
+ }
+ }
+
+ return key1.modifiers - key2.modifiers;
+}
diff --git a/src/termkey/termkey.h b/src/termkey/termkey.h
new file mode 100644
index 0000000000..8e10fcff0c
--- /dev/null
+++ b/src/termkey/termkey.h
@@ -0,0 +1,249 @@
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef GUARD_TERMKEY_H_
+#define GUARD_TERMKEY_H_
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#define TERMKEY_VERSION_MAJOR 0
+#define TERMKEY_VERSION_MINOR 22
+
+#define TERMKEY_CHECK_VERSION \
+ termkey_check_version(TERMKEY_VERSION_MAJOR, TERMKEY_VERSION_MINOR)
+
+typedef enum {
+ TERMKEY_SYM_UNKNOWN = -1,
+ TERMKEY_SYM_NONE = 0,
+
+ /* Special names in C0 */
+ TERMKEY_SYM_BACKSPACE,
+ TERMKEY_SYM_TAB,
+ TERMKEY_SYM_ENTER,
+ TERMKEY_SYM_ESCAPE,
+
+ /* Special names in G0 */
+ TERMKEY_SYM_SPACE,
+ TERMKEY_SYM_DEL,
+
+ /* Special keys */
+ TERMKEY_SYM_UP,
+ TERMKEY_SYM_DOWN,
+ TERMKEY_SYM_LEFT,
+ TERMKEY_SYM_RIGHT,
+ TERMKEY_SYM_BEGIN,
+ TERMKEY_SYM_FIND,
+ TERMKEY_SYM_INSERT,
+ TERMKEY_SYM_DELETE,
+ TERMKEY_SYM_SELECT,
+ TERMKEY_SYM_PAGEUP,
+ TERMKEY_SYM_PAGEDOWN,
+ TERMKEY_SYM_HOME,
+ TERMKEY_SYM_END,
+
+ /* Special keys from terminfo */
+ TERMKEY_SYM_CANCEL,
+ TERMKEY_SYM_CLEAR,
+ TERMKEY_SYM_CLOSE,
+ TERMKEY_SYM_COMMAND,
+ TERMKEY_SYM_COPY,
+ TERMKEY_SYM_EXIT,
+ TERMKEY_SYM_HELP,
+ TERMKEY_SYM_MARK,
+ TERMKEY_SYM_MESSAGE,
+ TERMKEY_SYM_MOVE,
+ TERMKEY_SYM_OPEN,
+ TERMKEY_SYM_OPTIONS,
+ TERMKEY_SYM_PRINT,
+ TERMKEY_SYM_REDO,
+ TERMKEY_SYM_REFERENCE,
+ TERMKEY_SYM_REFRESH,
+ TERMKEY_SYM_REPLACE,
+ TERMKEY_SYM_RESTART,
+ TERMKEY_SYM_RESUME,
+ TERMKEY_SYM_SAVE,
+ TERMKEY_SYM_SUSPEND,
+ TERMKEY_SYM_UNDO,
+
+ /* Numeric keypad special keys */
+ TERMKEY_SYM_KP0,
+ TERMKEY_SYM_KP1,
+ TERMKEY_SYM_KP2,
+ TERMKEY_SYM_KP3,
+ TERMKEY_SYM_KP4,
+ TERMKEY_SYM_KP5,
+ TERMKEY_SYM_KP6,
+ TERMKEY_SYM_KP7,
+ TERMKEY_SYM_KP8,
+ TERMKEY_SYM_KP9,
+ TERMKEY_SYM_KPENTER,
+ TERMKEY_SYM_KPPLUS,
+ TERMKEY_SYM_KPMINUS,
+ TERMKEY_SYM_KPMULT,
+ TERMKEY_SYM_KPDIV,
+ TERMKEY_SYM_KPCOMMA,
+ TERMKEY_SYM_KPPERIOD,
+ TERMKEY_SYM_KPEQUALS,
+
+ /* et cetera ad nauseum */
+ TERMKEY_N_SYMS
+} TermKeySym;
+
+typedef enum {
+ TERMKEY_TYPE_UNICODE,
+ TERMKEY_TYPE_FUNCTION,
+ TERMKEY_TYPE_KEYSYM,
+ TERMKEY_TYPE_MOUSE,
+ TERMKEY_TYPE_POSITION,
+ TERMKEY_TYPE_MODEREPORT,
+ TERMKEY_TYPE_DCS,
+ TERMKEY_TYPE_OSC,
+ /* add other recognised types here */
+
+ TERMKEY_TYPE_UNKNOWN_CSI = -1
+} TermKeyType;
+
+typedef enum {
+ TERMKEY_RES_NONE,
+ TERMKEY_RES_KEY,
+ TERMKEY_RES_EOF,
+ TERMKEY_RES_AGAIN,
+ TERMKEY_RES_ERROR
+} TermKeyResult;
+
+typedef enum {
+ TERMKEY_MOUSE_UNKNOWN,
+ TERMKEY_MOUSE_PRESS,
+ TERMKEY_MOUSE_DRAG,
+ TERMKEY_MOUSE_RELEASE
+} TermKeyMouseEvent;
+
+enum {
+ TERMKEY_KEYMOD_SHIFT = 1 << 0,
+ TERMKEY_KEYMOD_ALT = 1 << 1,
+ TERMKEY_KEYMOD_CTRL = 1 << 2
+};
+
+typedef struct {
+ TermKeyType type;
+ union {
+ long codepoint; /* TERMKEY_TYPE_UNICODE */
+ int number; /* TERMKEY_TYPE_FUNCTION */
+ TermKeySym sym; /* TERMKEY_TYPE_KEYSYM */
+ char mouse[4]; /* TERMKEY_TYPE_MOUSE */
+ /* opaque. see termkey_interpret_mouse */
+ } code;
+
+ int modifiers;
+
+ /* Any Unicode character can be UTF-8 encoded in no more than 6 bytes, plus
+ * terminating NUL */
+ char utf8[7];
+} TermKeyKey;
+
+typedef struct TermKey TermKey;
+
+enum {
+ TERMKEY_FLAG_NOINTERPRET = 1 << 0, /* Do not interpret C0//DEL codes if possible */
+ TERMKEY_FLAG_CONVERTKP = 1 << 1, /* Convert KP codes to regular keypresses */
+ TERMKEY_FLAG_RAW = 1 << 2, /* Input is raw bytes, not UTF-8 */
+ TERMKEY_FLAG_UTF8 = 1 << 3, /* Input is definitely UTF-8 */
+ TERMKEY_FLAG_NOTERMIOS = 1 << 4, /* Do not make initial termios calls on construction */
+ TERMKEY_FLAG_SPACESYMBOL = 1 << 5, /* Sets TERMKEY_CANON_SPACESYMBOL */
+ TERMKEY_FLAG_CTRLC = 1 << 6, /* Allow Ctrl-C to be read as normal, disabling SIGINT */
+ TERMKEY_FLAG_EINTR = 1 << 7, /* Return ERROR on signal (EINTR) rather than retry */
+ TERMKEY_FLAG_NOSTART = 1 << 8 /* Do not call termkey_start() in constructor */
+};
+
+enum {
+ TERMKEY_CANON_SPACESYMBOL = 1 << 0, /* Space is symbolic rather than Unicode */
+ TERMKEY_CANON_DELBS = 1 << 1 /* Del is converted to Backspace */
+};
+
+void termkey_check_version(int major, int minor);
+
+TermKey *termkey_new(int fd, int flags);
+TermKey *termkey_new_abstract(const char *term, int flags);
+void termkey_free(TermKey *tk);
+void termkey_destroy(TermKey *tk);
+
+/* Mostly-undocumented hooks for doing evil evil things */
+typedef const char *TermKey_Terminfo_Getstr_Hook(const char *name, const char *value, void *data);
+void termkey_hook_terminfo_getstr(TermKey *tk, TermKey_Terminfo_Getstr_Hook *hookfn, void *data);
+
+int termkey_start(TermKey *tk);
+int termkey_stop(TermKey *tk);
+int termkey_is_started(TermKey *tk);
+
+int termkey_get_fd(TermKey *tk);
+
+int termkey_get_flags(TermKey *tk);
+void termkey_set_flags(TermKey *tk, int newflags);
+
+int termkey_get_waittime(TermKey *tk);
+void termkey_set_waittime(TermKey *tk, int msec);
+
+int termkey_get_canonflags(TermKey *tk);
+void termkey_set_canonflags(TermKey *tk, int);
+
+size_t termkey_get_buffer_size(TermKey *tk);
+int termkey_set_buffer_size(TermKey *tk, size_t size);
+
+size_t termkey_get_buffer_remaining(TermKey *tk);
+
+void termkey_canonicalise(TermKey *tk, TermKeyKey *key);
+
+TermKeyResult termkey_getkey(TermKey *tk, TermKeyKey *key);
+TermKeyResult termkey_getkey_force(TermKey *tk, TermKeyKey *key);
+TermKeyResult termkey_waitkey(TermKey *tk, TermKeyKey *key);
+
+TermKeyResult termkey_advisereadable(TermKey *tk);
+
+size_t termkey_push_bytes(TermKey *tk, const char *bytes, size_t len);
+
+TermKeySym termkey_register_keyname(TermKey *tk, TermKeySym sym, const char *name);
+const char *termkey_get_keyname(TermKey *tk, TermKeySym sym);
+const char *termkey_lookup_keyname(TermKey *tk, const char *str, TermKeySym *sym);
+
+TermKeySym termkey_keyname2sym(TermKey *tk, const char *keyname);
+
+TermKeyResult termkey_interpret_mouse(TermKey *tk, const TermKeyKey *key, TermKeyMouseEvent *event, int *button, int *line, int *col);
+
+TermKeyResult termkey_interpret_position(TermKey *tk, const TermKeyKey *key, int *line, int *col);
+
+TermKeyResult termkey_interpret_modereport(TermKey *tk, const TermKeyKey *key, int *initial, int *mode, int *value);
+
+TermKeyResult termkey_interpret_csi(TermKey *tk, const TermKeyKey *key, long args[], size_t *nargs, unsigned long *cmd);
+
+TermKeyResult termkey_interpret_string(TermKey *tk, const TermKeyKey *key, const char **strp);
+
+typedef enum {
+ TERMKEY_FORMAT_LONGMOD = 1 << 0, /* Shift-... instead of S-... */
+ TERMKEY_FORMAT_CARETCTRL = 1 << 1, /* ^X instead of C-X */
+ TERMKEY_FORMAT_ALTISMETA = 1 << 2, /* Meta- or M- instead of Alt- or A- */
+ TERMKEY_FORMAT_WRAPBRACKET = 1 << 3, /* Wrap special keys in brackets like <Escape> */
+ TERMKEY_FORMAT_SPACEMOD = 1 << 4, /* M Foo instead of M-Foo */
+ TERMKEY_FORMAT_LOWERMOD = 1 << 5, /* meta or m instead of Meta or M */
+ TERMKEY_FORMAT_LOWERSPACE = 1 << 6, /* page down instead of PageDown */
+
+ TERMKEY_FORMAT_MOUSE_POS = 1 << 8 /* Include mouse position if relevant; @ col,line */
+} TermKeyFormat;
+
+/* Some useful combinations */
+
+#define TERMKEY_FORMAT_VIM (TermKeyFormat)(TERMKEY_FORMAT_ALTISMETA|TERMKEY_FORMAT_WRAPBRACKET)
+#define TERMKEY_FORMAT_URWID (TermKeyFormat)(TERMKEY_FORMAT_LONGMOD|TERMKEY_FORMAT_ALTISMETA| \
+ TERMKEY_FORMAT_LOWERMOD|TERMKEY_FORMAT_SPACEMOD|TERMKEY_FORMAT_LOWERSPACE)
+
+size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format);
+const char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format);
+
+int termkey_keycmp(TermKey *tk, const TermKeyKey *key1, const TermKeyKey *key2);
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/src/uncrustify.cfg b/src/uncrustify.cfg
index ffd4955829..aaac6e4426 100644
--- a/src/uncrustify.cfg
+++ b/src/uncrustify.cfg
@@ -3709,6 +3709,7 @@ set CLASS_COLON FUNC_API_FAST
set CLASS_COLON FUNC_API_LUA_ONLY
set CLASS_COLON FUNC_API_NOEXPORT
set CLASS_COLON FUNC_API_REMOTE_ONLY
+set CLASS_COLON FUNC_API_RET_ALLOC
set CLASS_COLON FUNC_API_SINCE
set CLASS_COLON FUNC_API_TEXTLOCK
set CLASS_COLON FUNC_API_TEXTLOCK_ALLOW_CMDWIN
diff --git a/src/unicode/CaseFolding.txt b/src/unicode/CaseFolding.txt
index 65aa0fcd6b..69c5c64b4c 100644
--- a/src/unicode/CaseFolding.txt
+++ b/src/unicode/CaseFolding.txt
@@ -1,6 +1,6 @@
-# CaseFolding-15.0.0.txt
-# Date: 2022-02-02, 23:35:35 GMT
-# © 2022 Unicode®, Inc.
+# CaseFolding-15.1.0.txt
+# Date: 2023-05-12, 21:53:10 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
@@ -929,6 +929,7 @@
1FCC; S; 1FC3; # GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
1FD2; F; 03B9 0308 0300; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND VARIA
1FD3; F; 03B9 0308 0301; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
+1FD3; S; 0390; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
1FD6; F; 03B9 0342; # GREEK SMALL LETTER IOTA WITH PERISPOMENI
1FD7; F; 03B9 0308 0342; # GREEK SMALL LETTER IOTA WITH DIALYTIKA AND PERISPOMENI
1FD8; C; 1FD0; # GREEK CAPITAL LETTER IOTA WITH VRACHY
@@ -937,6 +938,7 @@
1FDB; C; 1F77; # GREEK CAPITAL LETTER IOTA WITH OXIA
1FE2; F; 03C5 0308 0300; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND VARIA
1FE3; F; 03C5 0308 0301; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA
+1FE3; S; 03B0; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND OXIA
1FE4; F; 03C1 0313; # GREEK SMALL LETTER RHO WITH PSILI
1FE6; F; 03C5 0342; # GREEK SMALL LETTER UPSILON WITH PERISPOMENI
1FE7; F; 03C5 0308 0342; # GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND PERISPOMENI
@@ -1328,6 +1330,7 @@ FB02; F; 0066 006C; # LATIN SMALL LIGATURE FL
FB03; F; 0066 0066 0069; # LATIN SMALL LIGATURE FFI
FB04; F; 0066 0066 006C; # LATIN SMALL LIGATURE FFL
FB05; F; 0073 0074; # LATIN SMALL LIGATURE LONG S T
+FB05; S; FB06; # LATIN SMALL LIGATURE LONG S T
FB06; F; 0073 0074; # LATIN SMALL LIGATURE ST
FB13; F; 0574 0576; # ARMENIAN SMALL LIGATURE MEN NOW
FB14; F; 0574 0565; # ARMENIAN SMALL LIGATURE MEN ECH
diff --git a/src/unicode/EastAsianWidth.txt b/src/unicode/EastAsianWidth.txt
index 38b7076c02..02df4df475 100644
--- a/src/unicode/EastAsianWidth.txt
+++ b/src/unicode/EastAsianWidth.txt
@@ -1,11 +1,11 @@
-# EastAsianWidth-15.0.0.txt
-# Date: 2022-05-24, 17:40:20 GMT [KW, LI]
-# © 2022 Unicode®, Inc.
+# EastAsianWidth-15.1.0.txt
+# Date: 2023-07-28, 23:34:08 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Unicode Character Database
-# For documentation, see https://www.unicode.org/reports/tr44/
+# For documentation, see https://www.unicode.org/reports/tr44/
#
# East_Asian_Width Property
#
@@ -30,2590 +30,2592 @@
# Character ranges are specified as for other property files in the
# Unicode Character Database.
#
-# For legacy reasons, there are no spaces before or after the semicolon
-# which separates the two fields. The comments following the number sign
-# "#" list the General_Category property value or the L& alias of the
-# derived value LC, the Unicode character name or names, and, in lines
-# with ranges of code points, the code point count in square brackets.
+# The comments following the number sign "#" list the General_Category
+# property value or the L& alias of the derived value LC, the Unicode
+# character name or names, and, in lines with ranges of code points,
+# the code point count in square brackets.
#
# For more information, see UAX #11: East Asian Width,
# at https://www.unicode.org/reports/tr11/
#
# @missing: 0000..10FFFF; N
-0000..001F;N # Cc [32] <control-0000>..<control-001F>
-0020;Na # Zs SPACE
-0021..0023;Na # Po [3] EXCLAMATION MARK..NUMBER SIGN
-0024;Na # Sc DOLLAR SIGN
-0025..0027;Na # Po [3] PERCENT SIGN..APOSTROPHE
-0028;Na # Ps LEFT PARENTHESIS
-0029;Na # Pe RIGHT PARENTHESIS
-002A;Na # Po ASTERISK
-002B;Na # Sm PLUS SIGN
-002C;Na # Po COMMA
-002D;Na # Pd HYPHEN-MINUS
-002E..002F;Na # Po [2] FULL STOP..SOLIDUS
-0030..0039;Na # Nd [10] DIGIT ZERO..DIGIT NINE
-003A..003B;Na # Po [2] COLON..SEMICOLON
-003C..003E;Na # Sm [3] LESS-THAN SIGN..GREATER-THAN SIGN
-003F..0040;Na # Po [2] QUESTION MARK..COMMERCIAL AT
-0041..005A;Na # Lu [26] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z
-005B;Na # Ps LEFT SQUARE BRACKET
-005C;Na # Po REVERSE SOLIDUS
-005D;Na # Pe RIGHT SQUARE BRACKET
-005E;Na # Sk CIRCUMFLEX ACCENT
-005F;Na # Pc LOW LINE
-0060;Na # Sk GRAVE ACCENT
-0061..007A;Na # Ll [26] LATIN SMALL LETTER A..LATIN SMALL LETTER Z
-007B;Na # Ps LEFT CURLY BRACKET
-007C;Na # Sm VERTICAL LINE
-007D;Na # Pe RIGHT CURLY BRACKET
-007E;Na # Sm TILDE
-007F;N # Cc <control-007F>
-0080..009F;N # Cc [32] <control-0080>..<control-009F>
-00A0;N # Zs NO-BREAK SPACE
-00A1;A # Po INVERTED EXCLAMATION MARK
-00A2..00A3;Na # Sc [2] CENT SIGN..POUND SIGN
-00A4;A # Sc CURRENCY SIGN
-00A5;Na # Sc YEN SIGN
-00A6;Na # So BROKEN BAR
-00A7;A # Po SECTION SIGN
-00A8;A # Sk DIAERESIS
-00A9;N # So COPYRIGHT SIGN
-00AA;A # Lo FEMININE ORDINAL INDICATOR
-00AB;N # Pi LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
-00AC;Na # Sm NOT SIGN
-00AD;A # Cf SOFT HYPHEN
-00AE;A # So REGISTERED SIGN
-00AF;Na # Sk MACRON
-00B0;A # So DEGREE SIGN
-00B1;A # Sm PLUS-MINUS SIGN
-00B2..00B3;A # No [2] SUPERSCRIPT TWO..SUPERSCRIPT THREE
-00B4;A # Sk ACUTE ACCENT
-00B5;N # Ll MICRO SIGN
-00B6..00B7;A # Po [2] PILCROW SIGN..MIDDLE DOT
-00B8;A # Sk CEDILLA
-00B9;A # No SUPERSCRIPT ONE
-00BA;A # Lo MASCULINE ORDINAL INDICATOR
-00BB;N # Pf RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
-00BC..00BE;A # No [3] VULGAR FRACTION ONE QUARTER..VULGAR FRACTION THREE QUARTERS
-00BF;A # Po INVERTED QUESTION MARK
-00C0..00C5;N # Lu [6] LATIN CAPITAL LETTER A WITH GRAVE..LATIN CAPITAL LETTER A WITH RING ABOVE
-00C6;A # Lu LATIN CAPITAL LETTER AE
-00C7..00CF;N # Lu [9] LATIN CAPITAL LETTER C WITH CEDILLA..LATIN CAPITAL LETTER I WITH DIAERESIS
-00D0;A # Lu LATIN CAPITAL LETTER ETH
-00D1..00D6;N # Lu [6] LATIN CAPITAL LETTER N WITH TILDE..LATIN CAPITAL LETTER O WITH DIAERESIS
-00D7;A # Sm MULTIPLICATION SIGN
-00D8;A # Lu LATIN CAPITAL LETTER O WITH STROKE
-00D9..00DD;N # Lu [5] LATIN CAPITAL LETTER U WITH GRAVE..LATIN CAPITAL LETTER Y WITH ACUTE
-00DE..00E1;A # L& [4] LATIN CAPITAL LETTER THORN..LATIN SMALL LETTER A WITH ACUTE
-00E2..00E5;N # Ll [4] LATIN SMALL LETTER A WITH CIRCUMFLEX..LATIN SMALL LETTER A WITH RING ABOVE
-00E6;A # Ll LATIN SMALL LETTER AE
-00E7;N # Ll LATIN SMALL LETTER C WITH CEDILLA
-00E8..00EA;A # Ll [3] LATIN SMALL LETTER E WITH GRAVE..LATIN SMALL LETTER E WITH CIRCUMFLEX
-00EB;N # Ll LATIN SMALL LETTER E WITH DIAERESIS
-00EC..00ED;A # Ll [2] LATIN SMALL LETTER I WITH GRAVE..LATIN SMALL LETTER I WITH ACUTE
-00EE..00EF;N # Ll [2] LATIN SMALL LETTER I WITH CIRCUMFLEX..LATIN SMALL LETTER I WITH DIAERESIS
-00F0;A # Ll LATIN SMALL LETTER ETH
-00F1;N # Ll LATIN SMALL LETTER N WITH TILDE
-00F2..00F3;A # Ll [2] LATIN SMALL LETTER O WITH GRAVE..LATIN SMALL LETTER O WITH ACUTE
-00F4..00F6;N # Ll [3] LATIN SMALL LETTER O WITH CIRCUMFLEX..LATIN SMALL LETTER O WITH DIAERESIS
-00F7;A # Sm DIVISION SIGN
-00F8..00FA;A # Ll [3] LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER U WITH ACUTE
-00FB;N # Ll LATIN SMALL LETTER U WITH CIRCUMFLEX
-00FC;A # Ll LATIN SMALL LETTER U WITH DIAERESIS
-00FD;N # Ll LATIN SMALL LETTER Y WITH ACUTE
-00FE;A # Ll LATIN SMALL LETTER THORN
-00FF;N # Ll LATIN SMALL LETTER Y WITH DIAERESIS
-0100;N # Lu LATIN CAPITAL LETTER A WITH MACRON
-0101;A # Ll LATIN SMALL LETTER A WITH MACRON
-0102..0110;N # L& [15] LATIN CAPITAL LETTER A WITH BREVE..LATIN CAPITAL LETTER D WITH STROKE
-0111;A # Ll LATIN SMALL LETTER D WITH STROKE
-0112;N # Lu LATIN CAPITAL LETTER E WITH MACRON
-0113;A # Ll LATIN SMALL LETTER E WITH MACRON
-0114..011A;N # L& [7] LATIN CAPITAL LETTER E WITH BREVE..LATIN CAPITAL LETTER E WITH CARON
-011B;A # Ll LATIN SMALL LETTER E WITH CARON
-011C..0125;N # L& [10] LATIN CAPITAL LETTER G WITH CIRCUMFLEX..LATIN SMALL LETTER H WITH CIRCUMFLEX
-0126..0127;A # L& [2] LATIN CAPITAL LETTER H WITH STROKE..LATIN SMALL LETTER H WITH STROKE
-0128..012A;N # L& [3] LATIN CAPITAL LETTER I WITH TILDE..LATIN CAPITAL LETTER I WITH MACRON
-012B;A # Ll LATIN SMALL LETTER I WITH MACRON
-012C..0130;N # L& [5] LATIN CAPITAL LETTER I WITH BREVE..LATIN CAPITAL LETTER I WITH DOT ABOVE
-0131..0133;A # L& [3] LATIN SMALL LETTER DOTLESS I..LATIN SMALL LIGATURE IJ
-0134..0137;N # L& [4] LATIN CAPITAL LETTER J WITH CIRCUMFLEX..LATIN SMALL LETTER K WITH CEDILLA
-0138;A # Ll LATIN SMALL LETTER KRA
-0139..013E;N # L& [6] LATIN CAPITAL LETTER L WITH ACUTE..LATIN SMALL LETTER L WITH CARON
-013F..0142;A # L& [4] LATIN CAPITAL LETTER L WITH MIDDLE DOT..LATIN SMALL LETTER L WITH STROKE
-0143;N # Lu LATIN CAPITAL LETTER N WITH ACUTE
-0144;A # Ll LATIN SMALL LETTER N WITH ACUTE
-0145..0147;N # L& [3] LATIN CAPITAL LETTER N WITH CEDILLA..LATIN CAPITAL LETTER N WITH CARON
-0148..014B;A # L& [4] LATIN SMALL LETTER N WITH CARON..LATIN SMALL LETTER ENG
-014C;N # Lu LATIN CAPITAL LETTER O WITH MACRON
-014D;A # Ll LATIN SMALL LETTER O WITH MACRON
-014E..0151;N # L& [4] LATIN CAPITAL LETTER O WITH BREVE..LATIN SMALL LETTER O WITH DOUBLE ACUTE
-0152..0153;A # L& [2] LATIN CAPITAL LIGATURE OE..LATIN SMALL LIGATURE OE
-0154..0165;N # L& [18] LATIN CAPITAL LETTER R WITH ACUTE..LATIN SMALL LETTER T WITH CARON
-0166..0167;A # L& [2] LATIN CAPITAL LETTER T WITH STROKE..LATIN SMALL LETTER T WITH STROKE
-0168..016A;N # L& [3] LATIN CAPITAL LETTER U WITH TILDE..LATIN CAPITAL LETTER U WITH MACRON
-016B;A # Ll LATIN SMALL LETTER U WITH MACRON
-016C..017F;N # L& [20] LATIN CAPITAL LETTER U WITH BREVE..LATIN SMALL LETTER LONG S
-0180..01BA;N # L& [59] LATIN SMALL LETTER B WITH STROKE..LATIN SMALL LETTER EZH WITH TAIL
-01BB;N # Lo LATIN LETTER TWO WITH STROKE
-01BC..01BF;N # L& [4] LATIN CAPITAL LETTER TONE FIVE..LATIN LETTER WYNN
-01C0..01C3;N # Lo [4] LATIN LETTER DENTAL CLICK..LATIN LETTER RETROFLEX CLICK
-01C4..01CD;N # L& [10] LATIN CAPITAL LETTER DZ WITH CARON..LATIN CAPITAL LETTER A WITH CARON
-01CE;A # Ll LATIN SMALL LETTER A WITH CARON
-01CF;N # Lu LATIN CAPITAL LETTER I WITH CARON
-01D0;A # Ll LATIN SMALL LETTER I WITH CARON
-01D1;N # Lu LATIN CAPITAL LETTER O WITH CARON
-01D2;A # Ll LATIN SMALL LETTER O WITH CARON
-01D3;N # Lu LATIN CAPITAL LETTER U WITH CARON
-01D4;A # Ll LATIN SMALL LETTER U WITH CARON
-01D5;N # Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
-01D6;A # Ll LATIN SMALL LETTER U WITH DIAERESIS AND MACRON
-01D7;N # Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
-01D8;A # Ll LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE
-01D9;N # Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
-01DA;A # Ll LATIN SMALL LETTER U WITH DIAERESIS AND CARON
-01DB;N # Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
-01DC;A # Ll LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE
-01DD..024F;N # L& [115] LATIN SMALL LETTER TURNED E..LATIN SMALL LETTER Y WITH STROKE
-0250;N # Ll LATIN SMALL LETTER TURNED A
-0251;A # Ll LATIN SMALL LETTER ALPHA
-0252..0260;N # Ll [15] LATIN SMALL LETTER TURNED ALPHA..LATIN SMALL LETTER G WITH HOOK
-0261;A # Ll LATIN SMALL LETTER SCRIPT G
-0262..0293;N # Ll [50] LATIN LETTER SMALL CAPITAL G..LATIN SMALL LETTER EZH WITH CURL
-0294;N # Lo LATIN LETTER GLOTTAL STOP
-0295..02AF;N # Ll [27] LATIN LETTER PHARYNGEAL VOICED FRICATIVE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL
-02B0..02C1;N # Lm [18] MODIFIER LETTER SMALL H..MODIFIER LETTER REVERSED GLOTTAL STOP
-02C2..02C3;N # Sk [2] MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER RIGHT ARROWHEAD
-02C4;A # Sk MODIFIER LETTER UP ARROWHEAD
-02C5;N # Sk MODIFIER LETTER DOWN ARROWHEAD
-02C6;N # Lm MODIFIER LETTER CIRCUMFLEX ACCENT
-02C7;A # Lm CARON
-02C8;N # Lm MODIFIER LETTER VERTICAL LINE
-02C9..02CB;A # Lm [3] MODIFIER LETTER MACRON..MODIFIER LETTER GRAVE ACCENT
-02CC;N # Lm MODIFIER LETTER LOW VERTICAL LINE
-02CD;A # Lm MODIFIER LETTER LOW MACRON
-02CE..02CF;N # Lm [2] MODIFIER LETTER LOW GRAVE ACCENT..MODIFIER LETTER LOW ACUTE ACCENT
-02D0;A # Lm MODIFIER LETTER TRIANGULAR COLON
-02D1;N # Lm MODIFIER LETTER HALF TRIANGULAR COLON
-02D2..02D7;N # Sk [6] MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER MINUS SIGN
-02D8..02DB;A # Sk [4] BREVE..OGONEK
-02DC;N # Sk SMALL TILDE
-02DD;A # Sk DOUBLE ACUTE ACCENT
-02DE;N # Sk MODIFIER LETTER RHOTIC HOOK
-02DF;A # Sk MODIFIER LETTER CROSS ACCENT
-02E0..02E4;N # Lm [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP
-02E5..02EB;N # Sk [7] MODIFIER LETTER EXTRA-HIGH TONE BAR..MODIFIER LETTER YANG DEPARTING TONE MARK
-02EC;N # Lm MODIFIER LETTER VOICING
-02ED;N # Sk MODIFIER LETTER UNASPIRATED
-02EE;N # Lm MODIFIER LETTER DOUBLE APOSTROPHE
-02EF..02FF;N # Sk [17] MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW
-0300..036F;A # Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X
-0370..0373;N # L& [4] GREEK CAPITAL LETTER HETA..GREEK SMALL LETTER ARCHAIC SAMPI
-0374;N # Lm GREEK NUMERAL SIGN
-0375;N # Sk GREEK LOWER NUMERAL SIGN
-0376..0377;N # L& [2] GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA..GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
-037A;N # Lm GREEK YPOGEGRAMMENI
-037B..037D;N # Ll [3] GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL
-037E;N # Po GREEK QUESTION MARK
-037F;N # Lu GREEK CAPITAL LETTER YOT
-0384..0385;N # Sk [2] GREEK TONOS..GREEK DIALYTIKA TONOS
-0386;N # Lu GREEK CAPITAL LETTER ALPHA WITH TONOS
-0387;N # Po GREEK ANO TELEIA
-0388..038A;N # Lu [3] GREEK CAPITAL LETTER EPSILON WITH TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS
-038C;N # Lu GREEK CAPITAL LETTER OMICRON WITH TONOS
-038E..0390;N # L& [3] GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
-0391..03A1;A # Lu [17] GREEK CAPITAL LETTER ALPHA..GREEK CAPITAL LETTER RHO
-03A3..03A9;A # Lu [7] GREEK CAPITAL LETTER SIGMA..GREEK CAPITAL LETTER OMEGA
-03AA..03B0;N # L& [7] GREEK CAPITAL LETTER IOTA WITH DIALYTIKA..GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
-03B1..03C1;A # Ll [17] GREEK SMALL LETTER ALPHA..GREEK SMALL LETTER RHO
-03C2;N # Ll GREEK SMALL LETTER FINAL SIGMA
-03C3..03C9;A # Ll [7] GREEK SMALL LETTER SIGMA..GREEK SMALL LETTER OMEGA
-03CA..03F5;N # L& [44] GREEK SMALL LETTER IOTA WITH DIALYTIKA..GREEK LUNATE EPSILON SYMBOL
-03F6;N # Sm GREEK REVERSED LUNATE EPSILON SYMBOL
-03F7..03FF;N # L& [9] GREEK CAPITAL LETTER SHO..GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL
-0400;N # Lu CYRILLIC CAPITAL LETTER IE WITH GRAVE
-0401;A # Lu CYRILLIC CAPITAL LETTER IO
-0402..040F;N # Lu [14] CYRILLIC CAPITAL LETTER DJE..CYRILLIC CAPITAL LETTER DZHE
-0410..044F;A # L& [64] CYRILLIC CAPITAL LETTER A..CYRILLIC SMALL LETTER YA
-0450;N # Ll CYRILLIC SMALL LETTER IE WITH GRAVE
-0451;A # Ll CYRILLIC SMALL LETTER IO
-0452..0481;N # L& [48] CYRILLIC SMALL LETTER DJE..CYRILLIC SMALL LETTER KOPPA
-0482;N # So CYRILLIC THOUSANDS SIGN
-0483..0487;N # Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE
-0488..0489;N # Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN
-048A..04FF;N # L& [118] CYRILLIC CAPITAL LETTER SHORT I WITH TAIL..CYRILLIC SMALL LETTER HA WITH STROKE
-0500..052F;N # L& [48] CYRILLIC CAPITAL LETTER KOMI DE..CYRILLIC SMALL LETTER EL WITH DESCENDER
-0531..0556;N # Lu [38] ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH
-0559;N # Lm ARMENIAN MODIFIER LETTER LEFT HALF RING
-055A..055F;N # Po [6] ARMENIAN APOSTROPHE..ARMENIAN ABBREVIATION MARK
-0560..0588;N # Ll [41] ARMENIAN SMALL LETTER TURNED AYB..ARMENIAN SMALL LETTER YI WITH STROKE
-0589;N # Po ARMENIAN FULL STOP
-058A;N # Pd ARMENIAN HYPHEN
-058D..058E;N # So [2] RIGHT-FACING ARMENIAN ETERNITY SIGN..LEFT-FACING ARMENIAN ETERNITY SIGN
-058F;N # Sc ARMENIAN DRAM SIGN
-0591..05BD;N # Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG
-05BE;N # Pd HEBREW PUNCTUATION MAQAF
-05BF;N # Mn HEBREW POINT RAFE
-05C0;N # Po HEBREW PUNCTUATION PASEQ
-05C1..05C2;N # Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT
-05C3;N # Po HEBREW PUNCTUATION SOF PASUQ
-05C4..05C5;N # Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT
-05C6;N # Po HEBREW PUNCTUATION NUN HAFUKHA
-05C7;N # Mn HEBREW POINT QAMATS QATAN
-05D0..05EA;N # Lo [27] HEBREW LETTER ALEF..HEBREW LETTER TAV
-05EF..05F2;N # Lo [4] HEBREW YOD TRIANGLE..HEBREW LIGATURE YIDDISH DOUBLE YOD
-05F3..05F4;N # Po [2] HEBREW PUNCTUATION GERESH..HEBREW PUNCTUATION GERSHAYIM
-0600..0605;N # Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE
-0606..0608;N # Sm [3] ARABIC-INDIC CUBE ROOT..ARABIC RAY
-0609..060A;N # Po [2] ARABIC-INDIC PER MILLE SIGN..ARABIC-INDIC PER TEN THOUSAND SIGN
-060B;N # Sc AFGHANI SIGN
-060C..060D;N # Po [2] ARABIC COMMA..ARABIC DATE SEPARATOR
-060E..060F;N # So [2] ARABIC POETIC VERSE SIGN..ARABIC SIGN MISRA
-0610..061A;N # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA
-061B;N # Po ARABIC SEMICOLON
-061C;N # Cf ARABIC LETTER MARK
-061D..061F;N # Po [3] ARABIC END OF TEXT MARK..ARABIC QUESTION MARK
-0620..063F;N # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
-0640;N # Lm ARABIC TATWEEL
-0641..064A;N # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH
-064B..065F;N # Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW
-0660..0669;N # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
-066A..066D;N # Po [4] ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR
-066E..066F;N # Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF
-0670;N # Mn ARABIC LETTER SUPERSCRIPT ALEF
-0671..06D3;N # Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
-06D4;N # Po ARABIC FULL STOP
-06D5;N # Lo ARABIC LETTER AE
-06D6..06DC;N # Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN
-06DD;N # Cf ARABIC END OF AYAH
-06DE;N # So ARABIC START OF RUB EL HIZB
-06DF..06E4;N # Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA
-06E5..06E6;N # Lm [2] ARABIC SMALL WAW..ARABIC SMALL YEH
-06E7..06E8;N # Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON
-06E9;N # So ARABIC PLACE OF SAJDAH
-06EA..06ED;N # Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM
-06EE..06EF;N # Lo [2] ARABIC LETTER DAL WITH INVERTED V..ARABIC LETTER REH WITH INVERTED V
-06F0..06F9;N # Nd [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE
-06FA..06FC;N # Lo [3] ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER GHAIN WITH DOT BELOW
-06FD..06FE;N # So [2] ARABIC SIGN SINDHI AMPERSAND..ARABIC SIGN SINDHI POSTPOSITION MEN
-06FF;N # Lo ARABIC LETTER HEH WITH INVERTED V
-0700..070D;N # Po [14] SYRIAC END OF PARAGRAPH..SYRIAC HARKLEAN ASTERISCUS
-070F;N # Cf SYRIAC ABBREVIATION MARK
-0710;N # Lo SYRIAC LETTER ALAPH
-0711;N # Mn SYRIAC LETTER SUPERSCRIPT ALAPH
-0712..072F;N # Lo [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH
-0730..074A;N # Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH
-074D..074F;N # Lo [3] SYRIAC LETTER SOGDIAN ZHAIN..SYRIAC LETTER SOGDIAN FE
-0750..077F;N # Lo [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE
-0780..07A5;N # Lo [38] THAANA LETTER HAA..THAANA LETTER WAAVU
-07A6..07B0;N # Mn [11] THAANA ABAFILI..THAANA SUKUN
-07B1;N # Lo THAANA LETTER NAA
-07C0..07C9;N # Nd [10] NKO DIGIT ZERO..NKO DIGIT NINE
-07CA..07EA;N # Lo [33] NKO LETTER A..NKO LETTER JONA RA
-07EB..07F3;N # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
-07F4..07F5;N # Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE
-07F6;N # So NKO SYMBOL OO DENNEN
-07F7..07F9;N # Po [3] NKO SYMBOL GBAKURUNEN..NKO EXCLAMATION MARK
-07FA;N # Lm NKO LAJANYALAN
-07FD;N # Mn NKO DANTAYALAN
-07FE..07FF;N # Sc [2] NKO DOROME SIGN..NKO TAMAN SIGN
-0800..0815;N # Lo [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF
-0816..0819;N # Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH
-081A;N # Lm SAMARITAN MODIFIER LETTER EPENTHETIC YUT
-081B..0823;N # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A
-0824;N # Lm SAMARITAN MODIFIER LETTER SHORT A
-0825..0827;N # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U
-0828;N # Lm SAMARITAN MODIFIER LETTER I
-0829..082D;N # Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA
-0830..083E;N # Po [15] SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUNCTUATION ANNAAU
-0840..0858;N # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN
-0859..085B;N # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK
-085E;N # Po MANDAIC PUNCTUATION
-0860..086A;N # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA
-0870..0887;N # Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT
-0888;N # Sk ARABIC RAISED ROUND DOT
-0889..088E;N # Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL
-0890..0891;N # Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE
-0898..089F;N # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA
-08A0..08C8;N # Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF
-08C9;N # Lm ARABIC SMALL FARSI YEH
-08CA..08E1;N # Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA
-08E2;N # Cf ARABIC DISPUTED END OF AYAH
-08E3..08FF;N # Mn [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA
-0900..0902;N # Mn [3] DEVANAGARI SIGN INVERTED CANDRABINDU..DEVANAGARI SIGN ANUSVARA
-0903;N # Mc DEVANAGARI SIGN VISARGA
-0904..0939;N # Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA
-093A;N # Mn DEVANAGARI VOWEL SIGN OE
-093B;N # Mc DEVANAGARI VOWEL SIGN OOE
-093C;N # Mn DEVANAGARI SIGN NUKTA
-093D;N # Lo DEVANAGARI SIGN AVAGRAHA
-093E..0940;N # Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II
-0941..0948;N # Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI
-0949..094C;N # Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU
-094D;N # Mn DEVANAGARI SIGN VIRAMA
-094E..094F;N # Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW
-0950;N # Lo DEVANAGARI OM
-0951..0957;N # Mn [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE
-0958..0961;N # Lo [10] DEVANAGARI LETTER QA..DEVANAGARI LETTER VOCALIC LL
-0962..0963;N # Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL
-0964..0965;N # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA
-0966..096F;N # Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE
-0970;N # Po DEVANAGARI ABBREVIATION SIGN
-0971;N # Lm DEVANAGARI SIGN HIGH SPACING DOT
-0972..097F;N # Lo [14] DEVANAGARI LETTER CANDRA A..DEVANAGARI LETTER BBA
-0980;N # Lo BENGALI ANJI
-0981;N # Mn BENGALI SIGN CANDRABINDU
-0982..0983;N # Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA
-0985..098C;N # Lo [8] BENGALI LETTER A..BENGALI LETTER VOCALIC L
-098F..0990;N # Lo [2] BENGALI LETTER E..BENGALI LETTER AI
-0993..09A8;N # Lo [22] BENGALI LETTER O..BENGALI LETTER NA
-09AA..09B0;N # Lo [7] BENGALI LETTER PA..BENGALI LETTER RA
-09B2;N # Lo BENGALI LETTER LA
-09B6..09B9;N # Lo [4] BENGALI LETTER SHA..BENGALI LETTER HA
-09BC;N # Mn BENGALI SIGN NUKTA
-09BD;N # Lo BENGALI SIGN AVAGRAHA
-09BE..09C0;N # Mc [3] BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN II
-09C1..09C4;N # Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR
-09C7..09C8;N # Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI
-09CB..09CC;N # Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU
-09CD;N # Mn BENGALI SIGN VIRAMA
-09CE;N # Lo BENGALI LETTER KHANDA TA
-09D7;N # Mc BENGALI AU LENGTH MARK
-09DC..09DD;N # Lo [2] BENGALI LETTER RRA..BENGALI LETTER RHA
-09DF..09E1;N # Lo [3] BENGALI LETTER YYA..BENGALI LETTER VOCALIC LL
-09E2..09E3;N # Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL
-09E6..09EF;N # Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE
-09F0..09F1;N # Lo [2] BENGALI LETTER RA WITH MIDDLE DIAGONAL..BENGALI LETTER RA WITH LOWER DIAGONAL
-09F2..09F3;N # Sc [2] BENGALI RUPEE MARK..BENGALI RUPEE SIGN
-09F4..09F9;N # No [6] BENGALI CURRENCY NUMERATOR ONE..BENGALI CURRENCY DENOMINATOR SIXTEEN
-09FA;N # So BENGALI ISSHAR
-09FB;N # Sc BENGALI GANDA MARK
-09FC;N # Lo BENGALI LETTER VEDIC ANUSVARA
-09FD;N # Po BENGALI ABBREVIATION SIGN
-09FE;N # Mn BENGALI SANDHI MARK
-0A01..0A02;N # Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI
-0A03;N # Mc GURMUKHI SIGN VISARGA
-0A05..0A0A;N # Lo [6] GURMUKHI LETTER A..GURMUKHI LETTER UU
-0A0F..0A10;N # Lo [2] GURMUKHI LETTER EE..GURMUKHI LETTER AI
-0A13..0A28;N # Lo [22] GURMUKHI LETTER OO..GURMUKHI LETTER NA
-0A2A..0A30;N # Lo [7] GURMUKHI LETTER PA..GURMUKHI LETTER RA
-0A32..0A33;N # Lo [2] GURMUKHI LETTER LA..GURMUKHI LETTER LLA
-0A35..0A36;N # Lo [2] GURMUKHI LETTER VA..GURMUKHI LETTER SHA
-0A38..0A39;N # Lo [2] GURMUKHI LETTER SA..GURMUKHI LETTER HA
-0A3C;N # Mn GURMUKHI SIGN NUKTA
-0A3E..0A40;N # Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II
-0A41..0A42;N # Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU
-0A47..0A48;N # Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI
-0A4B..0A4D;N # Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA
-0A51;N # Mn GURMUKHI SIGN UDAAT
-0A59..0A5C;N # Lo [4] GURMUKHI LETTER KHHA..GURMUKHI LETTER RRA
-0A5E;N # Lo GURMUKHI LETTER FA
-0A66..0A6F;N # Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE
-0A70..0A71;N # Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK
-0A72..0A74;N # Lo [3] GURMUKHI IRI..GURMUKHI EK ONKAR
-0A75;N # Mn GURMUKHI SIGN YAKASH
-0A76;N # Po GURMUKHI ABBREVIATION SIGN
-0A81..0A82;N # Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA
-0A83;N # Mc GUJARATI SIGN VISARGA
-0A85..0A8D;N # Lo [9] GUJARATI LETTER A..GUJARATI VOWEL CANDRA E
-0A8F..0A91;N # Lo [3] GUJARATI LETTER E..GUJARATI VOWEL CANDRA O
-0A93..0AA8;N # Lo [22] GUJARATI LETTER O..GUJARATI LETTER NA
-0AAA..0AB0;N # Lo [7] GUJARATI LETTER PA..GUJARATI LETTER RA
-0AB2..0AB3;N # Lo [2] GUJARATI LETTER LA..GUJARATI LETTER LLA
-0AB5..0AB9;N # Lo [5] GUJARATI LETTER VA..GUJARATI LETTER HA
-0ABC;N # Mn GUJARATI SIGN NUKTA
-0ABD;N # Lo GUJARATI SIGN AVAGRAHA
-0ABE..0AC0;N # Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II
-0AC1..0AC5;N # Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E
-0AC7..0AC8;N # Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI
-0AC9;N # Mc GUJARATI VOWEL SIGN CANDRA O
-0ACB..0ACC;N # Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU
-0ACD;N # Mn GUJARATI SIGN VIRAMA
-0AD0;N # Lo GUJARATI OM
-0AE0..0AE1;N # Lo [2] GUJARATI LETTER VOCALIC RR..GUJARATI LETTER VOCALIC LL
-0AE2..0AE3;N # Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL
-0AE6..0AEF;N # Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
-0AF0;N # Po GUJARATI ABBREVIATION SIGN
-0AF1;N # Sc GUJARATI RUPEE SIGN
-0AF9;N # Lo GUJARATI LETTER ZHA
-0AFA..0AFF;N # Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE
-0B01;N # Mn ORIYA SIGN CANDRABINDU
-0B02..0B03;N # Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA
-0B05..0B0C;N # Lo [8] ORIYA LETTER A..ORIYA LETTER VOCALIC L
-0B0F..0B10;N # Lo [2] ORIYA LETTER E..ORIYA LETTER AI
-0B13..0B28;N # Lo [22] ORIYA LETTER O..ORIYA LETTER NA
-0B2A..0B30;N # Lo [7] ORIYA LETTER PA..ORIYA LETTER RA
-0B32..0B33;N # Lo [2] ORIYA LETTER LA..ORIYA LETTER LLA
-0B35..0B39;N # Lo [5] ORIYA LETTER VA..ORIYA LETTER HA
-0B3C;N # Mn ORIYA SIGN NUKTA
-0B3D;N # Lo ORIYA SIGN AVAGRAHA
-0B3E;N # Mc ORIYA VOWEL SIGN AA
-0B3F;N # Mn ORIYA VOWEL SIGN I
-0B40;N # Mc ORIYA VOWEL SIGN II
-0B41..0B44;N # Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR
-0B47..0B48;N # Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI
-0B4B..0B4C;N # Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU
-0B4D;N # Mn ORIYA SIGN VIRAMA
-0B55..0B56;N # Mn [2] ORIYA SIGN OVERLINE..ORIYA AI LENGTH MARK
-0B57;N # Mc ORIYA AU LENGTH MARK
-0B5C..0B5D;N # Lo [2] ORIYA LETTER RRA..ORIYA LETTER RHA
-0B5F..0B61;N # Lo [3] ORIYA LETTER YYA..ORIYA LETTER VOCALIC LL
-0B62..0B63;N # Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL
-0B66..0B6F;N # Nd [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE
-0B70;N # So ORIYA ISSHAR
-0B71;N # Lo ORIYA LETTER WA
-0B72..0B77;N # No [6] ORIYA FRACTION ONE QUARTER..ORIYA FRACTION THREE SIXTEENTHS
-0B82;N # Mn TAMIL SIGN ANUSVARA
-0B83;N # Lo TAMIL SIGN VISARGA
-0B85..0B8A;N # Lo [6] TAMIL LETTER A..TAMIL LETTER UU
-0B8E..0B90;N # Lo [3] TAMIL LETTER E..TAMIL LETTER AI
-0B92..0B95;N # Lo [4] TAMIL LETTER O..TAMIL LETTER KA
-0B99..0B9A;N # Lo [2] TAMIL LETTER NGA..TAMIL LETTER CA
-0B9C;N # Lo TAMIL LETTER JA
-0B9E..0B9F;N # Lo [2] TAMIL LETTER NYA..TAMIL LETTER TTA
-0BA3..0BA4;N # Lo [2] TAMIL LETTER NNA..TAMIL LETTER TA
-0BA8..0BAA;N # Lo [3] TAMIL LETTER NA..TAMIL LETTER PA
-0BAE..0BB9;N # Lo [12] TAMIL LETTER MA..TAMIL LETTER HA
-0BBE..0BBF;N # Mc [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN I
-0BC0;N # Mn TAMIL VOWEL SIGN II
-0BC1..0BC2;N # Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU
-0BC6..0BC8;N # Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI
-0BCA..0BCC;N # Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU
-0BCD;N # Mn TAMIL SIGN VIRAMA
-0BD0;N # Lo TAMIL OM
-0BD7;N # Mc TAMIL AU LENGTH MARK
-0BE6..0BEF;N # Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE
-0BF0..0BF2;N # No [3] TAMIL NUMBER TEN..TAMIL NUMBER ONE THOUSAND
-0BF3..0BF8;N # So [6] TAMIL DAY SIGN..TAMIL AS ABOVE SIGN
-0BF9;N # Sc TAMIL RUPEE SIGN
-0BFA;N # So TAMIL NUMBER SIGN
-0C00;N # Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE
-0C01..0C03;N # Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA
-0C04;N # Mn TELUGU SIGN COMBINING ANUSVARA ABOVE
-0C05..0C0C;N # Lo [8] TELUGU LETTER A..TELUGU LETTER VOCALIC L
-0C0E..0C10;N # Lo [3] TELUGU LETTER E..TELUGU LETTER AI
-0C12..0C28;N # Lo [23] TELUGU LETTER O..TELUGU LETTER NA
-0C2A..0C39;N # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA
-0C3C;N # Mn TELUGU SIGN NUKTA
-0C3D;N # Lo TELUGU SIGN AVAGRAHA
-0C3E..0C40;N # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II
-0C41..0C44;N # Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR
-0C46..0C48;N # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
-0C4A..0C4D;N # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
-0C55..0C56;N # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
-0C58..0C5A;N # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA
-0C5D;N # Lo TELUGU LETTER NAKAARA POLLU
-0C60..0C61;N # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL
-0C62..0C63;N # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL
-0C66..0C6F;N # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE
-0C77;N # Po TELUGU SIGN SIDDHAM
-0C78..0C7E;N # No [7] TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR
-0C7F;N # So TELUGU SIGN TUUMU
-0C80;N # Lo KANNADA SIGN SPACING CANDRABINDU
-0C81;N # Mn KANNADA SIGN CANDRABINDU
-0C82..0C83;N # Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA
-0C84;N # Po KANNADA SIGN SIDDHAM
-0C85..0C8C;N # Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L
-0C8E..0C90;N # Lo [3] KANNADA LETTER E..KANNADA LETTER AI
-0C92..0CA8;N # Lo [23] KANNADA LETTER O..KANNADA LETTER NA
-0CAA..0CB3;N # Lo [10] KANNADA LETTER PA..KANNADA LETTER LLA
-0CB5..0CB9;N # Lo [5] KANNADA LETTER VA..KANNADA LETTER HA
-0CBC;N # Mn KANNADA SIGN NUKTA
-0CBD;N # Lo KANNADA SIGN AVAGRAHA
-0CBE;N # Mc KANNADA VOWEL SIGN AA
-0CBF;N # Mn KANNADA VOWEL SIGN I
-0CC0..0CC4;N # Mc [5] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN VOCALIC RR
-0CC6;N # Mn KANNADA VOWEL SIGN E
-0CC7..0CC8;N # Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI
-0CCA..0CCB;N # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO
-0CCC..0CCD;N # Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA
-0CD5..0CD6;N # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK
-0CDD..0CDE;N # Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA
-0CE0..0CE1;N # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL
-0CE2..0CE3;N # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL
-0CE6..0CEF;N # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE
-0CF1..0CF2;N # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA
-0CF3;N # Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT
-0D00..0D01;N # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU
-0D02..0D03;N # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA
-0D04..0D0C;N # Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L
-0D0E..0D10;N # Lo [3] MALAYALAM LETTER E..MALAYALAM LETTER AI
-0D12..0D3A;N # Lo [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA
-0D3B..0D3C;N # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA
-0D3D;N # Lo MALAYALAM SIGN AVAGRAHA
-0D3E..0D40;N # Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II
-0D41..0D44;N # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR
-0D46..0D48;N # Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI
-0D4A..0D4C;N # Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU
-0D4D;N # Mn MALAYALAM SIGN VIRAMA
-0D4E;N # Lo MALAYALAM LETTER DOT REPH
-0D4F;N # So MALAYALAM SIGN PARA
-0D54..0D56;N # Lo [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL
-0D57;N # Mc MALAYALAM AU LENGTH MARK
-0D58..0D5E;N # No [7] MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH..MALAYALAM FRACTION ONE FIFTH
-0D5F..0D61;N # Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL
-0D62..0D63;N # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL
-0D66..0D6F;N # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
-0D70..0D78;N # No [9] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE SIXTEENTHS
-0D79;N # So MALAYALAM DATE MARK
-0D7A..0D7F;N # Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K
-0D81;N # Mn SINHALA SIGN CANDRABINDU
-0D82..0D83;N # Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA
-0D85..0D96;N # Lo [18] SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA
-0D9A..0DB1;N # Lo [24] SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA
-0DB3..0DBB;N # Lo [9] SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA
-0DBD;N # Lo SINHALA LETTER DANTAJA LAYANNA
-0DC0..0DC6;N # Lo [7] SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA
-0DCA;N # Mn SINHALA SIGN AL-LAKUNA
-0DCF..0DD1;N # Mc [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA
-0DD2..0DD4;N # Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA
-0DD6;N # Mn SINHALA VOWEL SIGN DIGA PAA-PILLA
-0DD8..0DDF;N # Mc [8] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA
-0DE6..0DEF;N # Nd [10] SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE
-0DF2..0DF3;N # Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA
-0DF4;N # Po SINHALA PUNCTUATION KUNDDALIYA
-0E01..0E30;N # Lo [48] THAI CHARACTER KO KAI..THAI CHARACTER SARA A
-0E31;N # Mn THAI CHARACTER MAI HAN-AKAT
-0E32..0E33;N # Lo [2] THAI CHARACTER SARA AA..THAI CHARACTER SARA AM
-0E34..0E3A;N # Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU
-0E3F;N # Sc THAI CURRENCY SYMBOL BAHT
-0E40..0E45;N # Lo [6] THAI CHARACTER SARA E..THAI CHARACTER LAKKHANGYAO
-0E46;N # Lm THAI CHARACTER MAIYAMOK
-0E47..0E4E;N # Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN
-0E4F;N # Po THAI CHARACTER FONGMAN
-0E50..0E59;N # Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE
-0E5A..0E5B;N # Po [2] THAI CHARACTER ANGKHANKHU..THAI CHARACTER KHOMUT
-0E81..0E82;N # Lo [2] LAO LETTER KO..LAO LETTER KHO SUNG
-0E84;N # Lo LAO LETTER KHO TAM
-0E86..0E8A;N # Lo [5] LAO LETTER PALI GHA..LAO LETTER SO TAM
-0E8C..0EA3;N # Lo [24] LAO LETTER PALI JHA..LAO LETTER LO LING
-0EA5;N # Lo LAO LETTER LO LOOT
-0EA7..0EB0;N # Lo [10] LAO LETTER WO..LAO VOWEL SIGN A
-0EB1;N # Mn LAO VOWEL SIGN MAI KAN
-0EB2..0EB3;N # Lo [2] LAO VOWEL SIGN AA..LAO VOWEL SIGN AM
-0EB4..0EBC;N # Mn [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO
-0EBD;N # Lo LAO SEMIVOWEL SIGN NYO
-0EC0..0EC4;N # Lo [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI
-0EC6;N # Lm LAO KO LA
-0EC8..0ECE;N # Mn [7] LAO TONE MAI EK..LAO YAMAKKAN
-0ED0..0ED9;N # Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE
-0EDC..0EDF;N # Lo [4] LAO HO NO..LAO LETTER KHMU NYO
-0F00;N # Lo TIBETAN SYLLABLE OM
-0F01..0F03;N # So [3] TIBETAN MARK GTER YIG MGO TRUNCATED A..TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA
-0F04..0F12;N # Po [15] TIBETAN MARK INITIAL YIG MGO MDUN MA..TIBETAN MARK RGYA GRAM SHAD
-0F13;N # So TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN
-0F14;N # Po TIBETAN MARK GTER TSHEG
-0F15..0F17;N # So [3] TIBETAN LOGOTYPE SIGN CHAD RTAGS..TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS
-0F18..0F19;N # Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS
-0F1A..0F1F;N # So [6] TIBETAN SIGN RDEL DKAR GCIG..TIBETAN SIGN RDEL DKAR RDEL NAG
-0F20..0F29;N # Nd [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE
-0F2A..0F33;N # No [10] TIBETAN DIGIT HALF ONE..TIBETAN DIGIT HALF ZERO
-0F34;N # So TIBETAN MARK BSDUS RTAGS
-0F35;N # Mn TIBETAN MARK NGAS BZUNG NYI ZLA
-0F36;N # So TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN
-0F37;N # Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS
-0F38;N # So TIBETAN MARK CHE MGO
-0F39;N # Mn TIBETAN MARK TSA -PHRU
-0F3A;N # Ps TIBETAN MARK GUG RTAGS GYON
-0F3B;N # Pe TIBETAN MARK GUG RTAGS GYAS
-0F3C;N # Ps TIBETAN MARK ANG KHANG GYON
-0F3D;N # Pe TIBETAN MARK ANG KHANG GYAS
-0F3E..0F3F;N # Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES
-0F40..0F47;N # Lo [8] TIBETAN LETTER KA..TIBETAN LETTER JA
-0F49..0F6C;N # Lo [36] TIBETAN LETTER NYA..TIBETAN LETTER RRA
-0F71..0F7E;N # Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO
-0F7F;N # Mc TIBETAN SIGN RNAM BCAD
-0F80..0F84;N # Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA
-0F85;N # Po TIBETAN MARK PALUTA
-0F86..0F87;N # Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS
-0F88..0F8C;N # Lo [5] TIBETAN SIGN LCE TSA CAN..TIBETAN SIGN INVERTED MCHU CAN
-0F8D..0F97;N # Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA
-0F99..0FBC;N # Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA
-0FBE..0FC5;N # So [8] TIBETAN KU RU KHA..TIBETAN SYMBOL RDO RJE
-0FC6;N # Mn TIBETAN SYMBOL PADMA GDAN
-0FC7..0FCC;N # So [6] TIBETAN SYMBOL RDO RJE RGYA GRAM..TIBETAN SYMBOL NOR BU BZHI -KHYIL
-0FCE..0FCF;N # So [2] TIBETAN SIGN RDEL NAG RDEL DKAR..TIBETAN SIGN RDEL NAG GSUM
-0FD0..0FD4;N # Po [5] TIBETAN MARK BSKA- SHOG GI MGO RGYAN..TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA
-0FD5..0FD8;N # So [4] RIGHT-FACING SVASTI SIGN..LEFT-FACING SVASTI SIGN WITH DOTS
-0FD9..0FDA;N # Po [2] TIBETAN MARK LEADING MCHAN RTAGS..TIBETAN MARK TRAILING MCHAN RTAGS
-1000..102A;N # Lo [43] MYANMAR LETTER KA..MYANMAR LETTER AU
-102B..102C;N # Mc [2] MYANMAR VOWEL SIGN TALL AA..MYANMAR VOWEL SIGN AA
-102D..1030;N # Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU
-1031;N # Mc MYANMAR VOWEL SIGN E
-1032..1037;N # Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW
-1038;N # Mc MYANMAR SIGN VISARGA
-1039..103A;N # Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT
-103B..103C;N # Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA
-103D..103E;N # Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA
-103F;N # Lo MYANMAR LETTER GREAT SA
-1040..1049;N # Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE
-104A..104F;N # Po [6] MYANMAR SIGN LITTLE SECTION..MYANMAR SYMBOL GENITIVE
-1050..1055;N # Lo [6] MYANMAR LETTER SHA..MYANMAR LETTER VOCALIC LL
-1056..1057;N # Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR
-1058..1059;N # Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL
-105A..105D;N # Lo [4] MYANMAR LETTER MON NGA..MYANMAR LETTER MON BBE
-105E..1060;N # Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA
-1061;N # Lo MYANMAR LETTER SGAW KAREN SHA
-1062..1064;N # Mc [3] MYANMAR VOWEL SIGN SGAW KAREN EU..MYANMAR TONE MARK SGAW KAREN KE PHO
-1065..1066;N # Lo [2] MYANMAR LETTER WESTERN PWO KAREN THA..MYANMAR LETTER WESTERN PWO KAREN PWA
-1067..106D;N # Mc [7] MYANMAR VOWEL SIGN WESTERN PWO KAREN EU..MYANMAR SIGN WESTERN PWO KAREN TONE-5
-106E..1070;N # Lo [3] MYANMAR LETTER EASTERN PWO KAREN NNA..MYANMAR LETTER EASTERN PWO KAREN GHWA
-1071..1074;N # Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE
-1075..1081;N # Lo [13] MYANMAR LETTER SHAN KA..MYANMAR LETTER SHAN HA
-1082;N # Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA
-1083..1084;N # Mc [2] MYANMAR VOWEL SIGN SHAN AA..MYANMAR VOWEL SIGN SHAN E
-1085..1086;N # Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y
-1087..108C;N # Mc [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3
-108D;N # Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE
-108E;N # Lo MYANMAR LETTER RUMAI PALAUNG FA
-108F;N # Mc MYANMAR SIGN RUMAI PALAUNG TONE-5
-1090..1099;N # Nd [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE
-109A..109C;N # Mc [3] MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON A
-109D;N # Mn MYANMAR VOWEL SIGN AITON AI
-109E..109F;N # So [2] MYANMAR SYMBOL SHAN ONE..MYANMAR SYMBOL SHAN EXCLAMATION
-10A0..10C5;N # Lu [38] GEORGIAN CAPITAL LETTER AN..GEORGIAN CAPITAL LETTER HOE
-10C7;N # Lu GEORGIAN CAPITAL LETTER YN
-10CD;N # Lu GEORGIAN CAPITAL LETTER AEN
-10D0..10FA;N # Ll [43] GEORGIAN LETTER AN..GEORGIAN LETTER AIN
-10FB;N # Po GEORGIAN PARAGRAPH SEPARATOR
-10FC;N # Lm MODIFIER LETTER GEORGIAN NAR
-10FD..10FF;N # Ll [3] GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN
-1100..115F;W # Lo [96] HANGUL CHOSEONG KIYEOK..HANGUL CHOSEONG FILLER
-1160..11FF;N # Lo [160] HANGUL JUNGSEONG FILLER..HANGUL JONGSEONG SSANGNIEUN
-1200..1248;N # Lo [73] ETHIOPIC SYLLABLE HA..ETHIOPIC SYLLABLE QWA
-124A..124D;N # Lo [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE
-1250..1256;N # Lo [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO
-1258;N # Lo ETHIOPIC SYLLABLE QHWA
-125A..125D;N # Lo [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE
-1260..1288;N # Lo [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA
-128A..128D;N # Lo [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE
-1290..12B0;N # Lo [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA
-12B2..12B5;N # Lo [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE
-12B8..12BE;N # Lo [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO
-12C0;N # Lo ETHIOPIC SYLLABLE KXWA
-12C2..12C5;N # Lo [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE
-12C8..12D6;N # Lo [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O
-12D8..1310;N # Lo [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA
-1312..1315;N # Lo [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE
-1318..135A;N # Lo [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA
-135D..135F;N # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK
-1360..1368;N # Po [9] ETHIOPIC SECTION MARK..ETHIOPIC PARAGRAPH SEPARATOR
-1369..137C;N # No [20] ETHIOPIC DIGIT ONE..ETHIOPIC NUMBER TEN THOUSAND
-1380..138F;N # Lo [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE
-1390..1399;N # So [10] ETHIOPIC TONAL MARK YIZET..ETHIOPIC TONAL MARK KURT
-13A0..13F5;N # Lu [86] CHEROKEE LETTER A..CHEROKEE LETTER MV
-13F8..13FD;N # Ll [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV
-1400;N # Pd CANADIAN SYLLABICS HYPHEN
-1401..166C;N # Lo [620] CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA
-166D;N # So CANADIAN SYLLABICS CHI SIGN
-166E;N # Po CANADIAN SYLLABICS FULL STOP
-166F..167F;N # Lo [17] CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W
-1680;N # Zs OGHAM SPACE MARK
-1681..169A;N # Lo [26] OGHAM LETTER BEITH..OGHAM LETTER PEITH
-169B;N # Ps OGHAM FEATHER MARK
-169C;N # Pe OGHAM REVERSED FEATHER MARK
-16A0..16EA;N # Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X
-16EB..16ED;N # Po [3] RUNIC SINGLE PUNCTUATION..RUNIC CROSS PUNCTUATION
-16EE..16F0;N # Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL
-16F1..16F8;N # Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC
-1700..1711;N # Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA
-1712..1714;N # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA
-1715;N # Mc TAGALOG SIGN PAMUDPOD
-171F;N # Lo TAGALOG LETTER ARCHAIC RA
-1720..1731;N # Lo [18] HANUNOO LETTER A..HANUNOO LETTER HA
-1732..1733;N # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U
-1734;N # Mc HANUNOO SIGN PAMUDPOD
-1735..1736;N # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION
-1740..1751;N # Lo [18] BUHID LETTER A..BUHID LETTER HA
-1752..1753;N # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U
-1760..176C;N # Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA
-176E..1770;N # Lo [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA
-1772..1773;N # Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U
-1780..17B3;N # Lo [52] KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU
-17B4..17B5;N # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
-17B6;N # Mc KHMER VOWEL SIGN AA
-17B7..17BD;N # Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA
-17BE..17C5;N # Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU
-17C6;N # Mn KHMER SIGN NIKAHIT
-17C7..17C8;N # Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU
-17C9..17D3;N # Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT
-17D4..17D6;N # Po [3] KHMER SIGN KHAN..KHMER SIGN CAMNUC PII KUUH
-17D7;N # Lm KHMER SIGN LEK TOO
-17D8..17DA;N # Po [3] KHMER SIGN BEYYAL..KHMER SIGN KOOMUUT
-17DB;N # Sc KHMER CURRENCY SYMBOL RIEL
-17DC;N # Lo KHMER SIGN AVAKRAHASANYA
-17DD;N # Mn KHMER SIGN ATTHACAN
-17E0..17E9;N # Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE
-17F0..17F9;N # No [10] KHMER SYMBOL LEK ATTAK SON..KHMER SYMBOL LEK ATTAK PRAM-BUON
-1800..1805;N # Po [6] MONGOLIAN BIRGA..MONGOLIAN FOUR DOTS
-1806;N # Pd MONGOLIAN TODO SOFT HYPHEN
-1807..180A;N # Po [4] MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER..MONGOLIAN NIRUGU
-180B..180D;N # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
-180E;N # Cf MONGOLIAN VOWEL SEPARATOR
-180F;N # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR
-1810..1819;N # Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE
-1820..1842;N # Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI
-1843;N # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN
-1844..1878;N # Lo [53] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER CHA WITH TWO DOTS
-1880..1884;N # Lo [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA
-1885..1886;N # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA
-1887..18A8;N # Lo [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA
-18A9;N # Mn MONGOLIAN LETTER ALI GALI DAGALGA
-18AA;N # Lo MONGOLIAN LETTER MANCHU ALI GALI LHA
-18B0..18F5;N # Lo [70] CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S
-1900..191E;N # Lo [31] LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER TRA
-1920..1922;N # Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U
-1923..1926;N # Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU
-1927..1928;N # Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O
-1929..192B;N # Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA
-1930..1931;N # Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA
-1932;N # Mn LIMBU SMALL LETTER ANUSVARA
-1933..1938;N # Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA
-1939..193B;N # Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I
-1940;N # So LIMBU SIGN LOO
-1944..1945;N # Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK
-1946..194F;N # Nd [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE
-1950..196D;N # Lo [30] TAI LE LETTER KA..TAI LE LETTER AI
-1970..1974;N # Lo [5] TAI LE LETTER TONE-2..TAI LE LETTER TONE-6
-1980..19AB;N # Lo [44] NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA
-19B0..19C9;N # Lo [26] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2
-19D0..19D9;N # Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE
-19DA;N # No NEW TAI LUE THAM DIGIT ONE
-19DE..19DF;N # So [2] NEW TAI LUE SIGN LAE..NEW TAI LUE SIGN LAEV
-19E0..19FF;N # So [32] KHMER SYMBOL PATHAMASAT..KHMER SYMBOL DAP-PRAM ROC
-1A00..1A16;N # Lo [23] BUGINESE LETTER KA..BUGINESE LETTER HA
-1A17..1A18;N # Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U
-1A19..1A1A;N # Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O
-1A1B;N # Mn BUGINESE VOWEL SIGN AE
-1A1E..1A1F;N # Po [2] BUGINESE PALLAWA..BUGINESE END OF SECTION
-1A20..1A54;N # Lo [53] TAI THAM LETTER HIGH KA..TAI THAM LETTER GREAT SA
-1A55;N # Mc TAI THAM CONSONANT SIGN MEDIAL RA
-1A56;N # Mn TAI THAM CONSONANT SIGN MEDIAL LA
-1A57;N # Mc TAI THAM CONSONANT SIGN LA TANG LAI
-1A58..1A5E;N # Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA
-1A60;N # Mn TAI THAM SIGN SAKOT
-1A61;N # Mc TAI THAM VOWEL SIGN A
-1A62;N # Mn TAI THAM VOWEL SIGN MAI SAT
-1A63..1A64;N # Mc [2] TAI THAM VOWEL SIGN AA..TAI THAM VOWEL SIGN TALL AA
-1A65..1A6C;N # Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW
-1A6D..1A72;N # Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI
-1A73..1A7C;N # Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN
-1A7F;N # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT
-1A80..1A89;N # Nd [10] TAI THAM HORA DIGIT ZERO..TAI THAM HORA DIGIT NINE
-1A90..1A99;N # Nd [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE
-1AA0..1AA6;N # Po [7] TAI THAM SIGN WIANG..TAI THAM SIGN REVERSED ROTATED RANA
-1AA7;N # Lm TAI THAM SIGN MAI YAMOK
-1AA8..1AAD;N # Po [6] TAI THAM SIGN KAAN..TAI THAM SIGN CAANG
-1AB0..1ABD;N # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
-1ABE;N # Me COMBINING PARENTHESES OVERLAY
-1ABF..1ACE;N # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T
-1B00..1B03;N # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG
-1B04;N # Mc BALINESE SIGN BISAH
-1B05..1B33;N # Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA
-1B34;N # Mn BALINESE SIGN REREKAN
-1B35;N # Mc BALINESE VOWEL SIGN TEDUNG
-1B36..1B3A;N # Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA
-1B3B;N # Mc BALINESE VOWEL SIGN RA REPA TEDUNG
-1B3C;N # Mn BALINESE VOWEL SIGN LA LENGA
-1B3D..1B41;N # Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG
-1B42;N # Mn BALINESE VOWEL SIGN PEPET
-1B43..1B44;N # Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG
-1B45..1B4C;N # Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA
-1B50..1B59;N # Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE
-1B5A..1B60;N # Po [7] BALINESE PANTI..BALINESE PAMENENG
-1B61..1B6A;N # So [10] BALINESE MUSICAL SYMBOL DONG..BALINESE MUSICAL SYMBOL DANG GEDE
-1B6B..1B73;N # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
-1B74..1B7C;N # So [9] BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG..BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING
-1B7D..1B7E;N # Po [2] BALINESE PANTI LANTANG..BALINESE PAMADA LANTANG
-1B80..1B81;N # Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR
-1B82;N # Mc SUNDANESE SIGN PANGWISAD
-1B83..1BA0;N # Lo [30] SUNDANESE LETTER A..SUNDANESE LETTER HA
-1BA1;N # Mc SUNDANESE CONSONANT SIGN PAMINGKAL
-1BA2..1BA5;N # Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU
-1BA6..1BA7;N # Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG
-1BA8..1BA9;N # Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG
-1BAA;N # Mc SUNDANESE SIGN PAMAAEH
-1BAB..1BAD;N # Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA
-1BAE..1BAF;N # Lo [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA
-1BB0..1BB9;N # Nd [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE
-1BBA..1BBF;N # Lo [6] SUNDANESE AVAGRAHA..SUNDANESE LETTER FINAL M
-1BC0..1BE5;N # Lo [38] BATAK LETTER A..BATAK LETTER U
-1BE6;N # Mn BATAK SIGN TOMPI
-1BE7;N # Mc BATAK VOWEL SIGN E
-1BE8..1BE9;N # Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE
-1BEA..1BEC;N # Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O
-1BED;N # Mn BATAK VOWEL SIGN KARO O
-1BEE;N # Mc BATAK VOWEL SIGN U
-1BEF..1BF1;N # Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H
-1BF2..1BF3;N # Mc [2] BATAK PANGOLAT..BATAK PANONGONAN
-1BFC..1BFF;N # Po [4] BATAK SYMBOL BINDU NA METEK..BATAK SYMBOL BINDU PANGOLAT
-1C00..1C23;N # Lo [36] LEPCHA LETTER KA..LEPCHA LETTER A
-1C24..1C2B;N # Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU
-1C2C..1C33;N # Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T
-1C34..1C35;N # Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG
-1C36..1C37;N # Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA
-1C3B..1C3F;N # Po [5] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK
-1C40..1C49;N # Nd [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE
-1C4D..1C4F;N # Lo [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA
-1C50..1C59;N # Nd [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE
-1C5A..1C77;N # Lo [30] OL CHIKI LETTER LA..OL CHIKI LETTER OH
-1C78..1C7D;N # Lm [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD
-1C7E..1C7F;N # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD
-1C80..1C88;N # Ll [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK
-1C90..1CBA;N # Lu [43] GEORGIAN MTAVRULI CAPITAL LETTER AN..GEORGIAN MTAVRULI CAPITAL LETTER AIN
-1CBD..1CBF;N # Lu [3] GEORGIAN MTAVRULI CAPITAL LETTER AEN..GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN
-1CC0..1CC7;N # Po [8] SUNDANESE PUNCTUATION BINDU SURYA..SUNDANESE PUNCTUATION BINDU BA SATANGA
-1CD0..1CD2;N # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
-1CD3;N # Po VEDIC SIGN NIHSHVASA
-1CD4..1CE0;N # Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA
-1CE1;N # Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA
-1CE2..1CE8;N # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL
-1CE9..1CEC;N # Lo [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA..VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL
-1CED;N # Mn VEDIC SIGN TIRYAK
-1CEE..1CF3;N # Lo [6] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ROTATED ARDHAVISARGA
-1CF4;N # Mn VEDIC TONE CANDRA ABOVE
-1CF5..1CF6;N # Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA
-1CF7;N # Mc VEDIC SIGN ATIKRAMA
-1CF8..1CF9;N # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
-1CFA;N # Lo VEDIC SIGN DOUBLE ANUSVARA ANTARGOMUKHA
-1D00..1D2B;N # Ll [44] LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL
-1D2C..1D6A;N # Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI
-1D6B..1D77;N # Ll [13] LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G
-1D78;N # Lm MODIFIER LETTER CYRILLIC EN
-1D79..1D7F;N # Ll [7] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER UPSILON WITH STROKE
-1D80..1D9A;N # Ll [27] LATIN SMALL LETTER B WITH PALATAL HOOK..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK
-1D9B..1DBF;N # Lm [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA
-1DC0..1DFF;N # Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
-1E00..1EFF;N # L& [256] LATIN CAPITAL LETTER A WITH RING BELOW..LATIN SMALL LETTER Y WITH LOOP
-1F00..1F15;N # L& [22] GREEK SMALL LETTER ALPHA WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA
-1F18..1F1D;N # Lu [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
-1F20..1F45;N # L& [38] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA
-1F48..1F4D;N # Lu [6] GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
-1F50..1F57;N # Ll [8] GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI
-1F59;N # Lu GREEK CAPITAL LETTER UPSILON WITH DASIA
-1F5B;N # Lu GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
-1F5D;N # Lu GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
-1F5F..1F7D;N # L& [31] GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI..GREEK SMALL LETTER OMEGA WITH OXIA
-1F80..1FB4;N # L& [53] GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
-1FB6..1FBC;N # L& [7] GREEK SMALL LETTER ALPHA WITH PERISPOMENI..GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
-1FBD;N # Sk GREEK KORONIS
-1FBE;N # Ll GREEK PROSGEGRAMMENI
-1FBF..1FC1;N # Sk [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI
-1FC2..1FC4;N # Ll [3] GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
-1FC6..1FCC;N # L& [7] GREEK SMALL LETTER ETA WITH PERISPOMENI..GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
-1FCD..1FCF;N # Sk [3] GREEK PSILI AND VARIA..GREEK PSILI AND PERISPOMENI
-1FD0..1FD3;N # Ll [4] GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
-1FD6..1FDB;N # L& [6] GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK CAPITAL LETTER IOTA WITH OXIA
-1FDD..1FDF;N # Sk [3] GREEK DASIA AND VARIA..GREEK DASIA AND PERISPOMENI
-1FE0..1FEC;N # L& [13] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA
-1FED..1FEF;N # Sk [3] GREEK DIALYTIKA AND VARIA..GREEK VARIA
-1FF2..1FF4;N # Ll [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
-1FF6..1FFC;N # L& [7] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
-1FFD..1FFE;N # Sk [2] GREEK OXIA..GREEK DASIA
-2000..200A;N # Zs [11] EN QUAD..HAIR SPACE
-200B..200F;N # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
-2010;A # Pd HYPHEN
-2011..2012;N # Pd [2] NON-BREAKING HYPHEN..FIGURE DASH
-2013..2015;A # Pd [3] EN DASH..HORIZONTAL BAR
-2016;A # Po DOUBLE VERTICAL LINE
-2017;N # Po DOUBLE LOW LINE
-2018;A # Pi LEFT SINGLE QUOTATION MARK
-2019;A # Pf RIGHT SINGLE QUOTATION MARK
-201A;N # Ps SINGLE LOW-9 QUOTATION MARK
-201B;N # Pi SINGLE HIGH-REVERSED-9 QUOTATION MARK
-201C;A # Pi LEFT DOUBLE QUOTATION MARK
-201D;A # Pf RIGHT DOUBLE QUOTATION MARK
-201E;N # Ps DOUBLE LOW-9 QUOTATION MARK
-201F;N # Pi DOUBLE HIGH-REVERSED-9 QUOTATION MARK
-2020..2022;A # Po [3] DAGGER..BULLET
-2023;N # Po TRIANGULAR BULLET
-2024..2027;A # Po [4] ONE DOT LEADER..HYPHENATION POINT
-2028;N # Zl LINE SEPARATOR
-2029;N # Zp PARAGRAPH SEPARATOR
-202A..202E;N # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
-202F;N # Zs NARROW NO-BREAK SPACE
-2030;A # Po PER MILLE SIGN
-2031;N # Po PER TEN THOUSAND SIGN
-2032..2033;A # Po [2] PRIME..DOUBLE PRIME
-2034;N # Po TRIPLE PRIME
-2035;A # Po REVERSED PRIME
-2036..2038;N # Po [3] REVERSED DOUBLE PRIME..CARET
-2039;N # Pi SINGLE LEFT-POINTING ANGLE QUOTATION MARK
-203A;N # Pf SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
-203B;A # Po REFERENCE MARK
-203C..203D;N # Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG
-203E;A # Po OVERLINE
-203F..2040;N # Pc [2] UNDERTIE..CHARACTER TIE
-2041..2043;N # Po [3] CARET INSERTION POINT..HYPHEN BULLET
-2044;N # Sm FRACTION SLASH
-2045;N # Ps LEFT SQUARE BRACKET WITH QUILL
-2046;N # Pe RIGHT SQUARE BRACKET WITH QUILL
-2047..2051;N # Po [11] DOUBLE QUESTION MARK..TWO ASTERISKS ALIGNED VERTICALLY
-2052;N # Sm COMMERCIAL MINUS SIGN
-2053;N # Po SWUNG DASH
-2054;N # Pc INVERTED UNDERTIE
-2055..205E;N # Po [10] FLOWER PUNCTUATION MARK..VERTICAL FOUR DOTS
-205F;N # Zs MEDIUM MATHEMATICAL SPACE
-2060..2064;N # Cf [5] WORD JOINER..INVISIBLE PLUS
-2066..206F;N # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
-2070;N # No SUPERSCRIPT ZERO
-2071;N # Lm SUPERSCRIPT LATIN SMALL LETTER I
-2074;A # No SUPERSCRIPT FOUR
-2075..2079;N # No [5] SUPERSCRIPT FIVE..SUPERSCRIPT NINE
-207A..207C;N # Sm [3] SUPERSCRIPT PLUS SIGN..SUPERSCRIPT EQUALS SIGN
-207D;N # Ps SUPERSCRIPT LEFT PARENTHESIS
-207E;N # Pe SUPERSCRIPT RIGHT PARENTHESIS
-207F;A # Lm SUPERSCRIPT LATIN SMALL LETTER N
-2080;N # No SUBSCRIPT ZERO
-2081..2084;A # No [4] SUBSCRIPT ONE..SUBSCRIPT FOUR
-2085..2089;N # No [5] SUBSCRIPT FIVE..SUBSCRIPT NINE
-208A..208C;N # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN
-208D;N # Ps SUBSCRIPT LEFT PARENTHESIS
-208E;N # Pe SUBSCRIPT RIGHT PARENTHESIS
-2090..209C;N # Lm [13] LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T
-20A0..20A8;N # Sc [9] EURO-CURRENCY SIGN..RUPEE SIGN
-20A9;H # Sc WON SIGN
-20AA..20AB;N # Sc [2] NEW SHEQEL SIGN..DONG SIGN
-20AC;A # Sc EURO SIGN
-20AD..20C0;N # Sc [20] KIP SIGN..SOM SIGN
-20D0..20DC;N # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE
-20DD..20E0;N # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH
-20E1;N # Mn COMBINING LEFT RIGHT ARROW ABOVE
-20E2..20E4;N # Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE
-20E5..20F0;N # Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE
-2100..2101;N # So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT
-2102;N # Lu DOUBLE-STRUCK CAPITAL C
-2103;A # So DEGREE CELSIUS
-2104;N # So CENTRE LINE SYMBOL
-2105;A # So CARE OF
-2106;N # So CADA UNA
-2107;N # Lu EULER CONSTANT
-2108;N # So SCRUPLE
-2109;A # So DEGREE FAHRENHEIT
-210A..2112;N # L& [9] SCRIPT SMALL G..SCRIPT CAPITAL L
-2113;A # Ll SCRIPT SMALL L
-2114;N # So L B BAR SYMBOL
-2115;N # Lu DOUBLE-STRUCK CAPITAL N
-2116;A # So NUMERO SIGN
-2117;N # So SOUND RECORDING COPYRIGHT
-2118;N # Sm SCRIPT CAPITAL P
-2119..211D;N # Lu [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-STRUCK CAPITAL R
-211E..2120;N # So [3] PRESCRIPTION TAKE..SERVICE MARK
-2121..2122;A # So [2] TELEPHONE SIGN..TRADE MARK SIGN
-2123;N # So VERSICLE
-2124;N # Lu DOUBLE-STRUCK CAPITAL Z
-2125;N # So OUNCE SIGN
-2126;A # Lu OHM SIGN
-2127;N # So INVERTED OHM SIGN
-2128;N # Lu BLACK-LETTER CAPITAL Z
-2129;N # So TURNED GREEK SMALL LETTER IOTA
-212A;N # Lu KELVIN SIGN
-212B;A # Lu ANGSTROM SIGN
-212C..212D;N # Lu [2] SCRIPT CAPITAL B..BLACK-LETTER CAPITAL C
-212E;N # So ESTIMATED SYMBOL
-212F..2134;N # L& [6] SCRIPT SMALL E..SCRIPT SMALL O
-2135..2138;N # Lo [4] ALEF SYMBOL..DALET SYMBOL
-2139;N # Ll INFORMATION SOURCE
-213A..213B;N # So [2] ROTATED CAPITAL Q..FACSIMILE SIGN
-213C..213F;N # L& [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STRUCK CAPITAL PI
-2140..2144;N # Sm [5] DOUBLE-STRUCK N-ARY SUMMATION..TURNED SANS-SERIF CAPITAL Y
-2145..2149;N # L& [5] DOUBLE-STRUCK ITALIC CAPITAL D..DOUBLE-STRUCK ITALIC SMALL J
-214A;N # So PROPERTY LINE
-214B;N # Sm TURNED AMPERSAND
-214C..214D;N # So [2] PER SIGN..AKTIESELSKAB
-214E;N # Ll TURNED SMALL F
-214F;N # So SYMBOL FOR SAMARITAN SOURCE
-2150..2152;N # No [3] VULGAR FRACTION ONE SEVENTH..VULGAR FRACTION ONE TENTH
-2153..2154;A # No [2] VULGAR FRACTION ONE THIRD..VULGAR FRACTION TWO THIRDS
-2155..215A;N # No [6] VULGAR FRACTION ONE FIFTH..VULGAR FRACTION FIVE SIXTHS
-215B..215E;A # No [4] VULGAR FRACTION ONE EIGHTH..VULGAR FRACTION SEVEN EIGHTHS
-215F;N # No FRACTION NUMERATOR ONE
-2160..216B;A # Nl [12] ROMAN NUMERAL ONE..ROMAN NUMERAL TWELVE
-216C..216F;N # Nl [4] ROMAN NUMERAL FIFTY..ROMAN NUMERAL ONE THOUSAND
-2170..2179;A # Nl [10] SMALL ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL TEN
-217A..2182;N # Nl [9] SMALL ROMAN NUMERAL ELEVEN..ROMAN NUMERAL TEN THOUSAND
-2183..2184;N # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C
-2185..2188;N # Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND
-2189;A # No VULGAR FRACTION ZERO THIRDS
-218A..218B;N # So [2] TURNED DIGIT TWO..TURNED DIGIT THREE
-2190..2194;A # Sm [5] LEFTWARDS ARROW..LEFT RIGHT ARROW
-2195..2199;A # So [5] UP DOWN ARROW..SOUTH WEST ARROW
-219A..219B;N # Sm [2] LEFTWARDS ARROW WITH STROKE..RIGHTWARDS ARROW WITH STROKE
-219C..219F;N # So [4] LEFTWARDS WAVE ARROW..UPWARDS TWO HEADED ARROW
-21A0;N # Sm RIGHTWARDS TWO HEADED ARROW
-21A1..21A2;N # So [2] DOWNWARDS TWO HEADED ARROW..LEFTWARDS ARROW WITH TAIL
-21A3;N # Sm RIGHTWARDS ARROW WITH TAIL
-21A4..21A5;N # So [2] LEFTWARDS ARROW FROM BAR..UPWARDS ARROW FROM BAR
-21A6;N # Sm RIGHTWARDS ARROW FROM BAR
-21A7..21AD;N # So [7] DOWNWARDS ARROW FROM BAR..LEFT RIGHT WAVE ARROW
-21AE;N # Sm LEFT RIGHT ARROW WITH STROKE
-21AF..21B7;N # So [9] DOWNWARDS ZIGZAG ARROW..CLOCKWISE TOP SEMICIRCLE ARROW
-21B8..21B9;A # So [2] NORTH WEST ARROW TO LONG BAR..LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR
-21BA..21CD;N # So [20] ANTICLOCKWISE OPEN CIRCLE ARROW..LEFTWARDS DOUBLE ARROW WITH STROKE
-21CE..21CF;N # Sm [2] LEFT RIGHT DOUBLE ARROW WITH STROKE..RIGHTWARDS DOUBLE ARROW WITH STROKE
-21D0..21D1;N # So [2] LEFTWARDS DOUBLE ARROW..UPWARDS DOUBLE ARROW
-21D2;A # Sm RIGHTWARDS DOUBLE ARROW
-21D3;N # So DOWNWARDS DOUBLE ARROW
-21D4;A # Sm LEFT RIGHT DOUBLE ARROW
-21D5..21E6;N # So [18] UP DOWN DOUBLE ARROW..LEFTWARDS WHITE ARROW
-21E7;A # So UPWARDS WHITE ARROW
-21E8..21F3;N # So [12] RIGHTWARDS WHITE ARROW..UP DOWN WHITE ARROW
-21F4..21FF;N # Sm [12] RIGHT ARROW WITH SMALL CIRCLE..LEFT RIGHT OPEN-HEADED ARROW
-2200;A # Sm FOR ALL
-2201;N # Sm COMPLEMENT
-2202..2203;A # Sm [2] PARTIAL DIFFERENTIAL..THERE EXISTS
-2204..2206;N # Sm [3] THERE DOES NOT EXIST..INCREMENT
-2207..2208;A # Sm [2] NABLA..ELEMENT OF
-2209..220A;N # Sm [2] NOT AN ELEMENT OF..SMALL ELEMENT OF
-220B;A # Sm CONTAINS AS MEMBER
-220C..220E;N # Sm [3] DOES NOT CONTAIN AS MEMBER..END OF PROOF
-220F;A # Sm N-ARY PRODUCT
-2210;N # Sm N-ARY COPRODUCT
-2211;A # Sm N-ARY SUMMATION
-2212..2214;N # Sm [3] MINUS SIGN..DOT PLUS
-2215;A # Sm DIVISION SLASH
-2216..2219;N # Sm [4] SET MINUS..BULLET OPERATOR
-221A;A # Sm SQUARE ROOT
-221B..221C;N # Sm [2] CUBE ROOT..FOURTH ROOT
-221D..2220;A # Sm [4] PROPORTIONAL TO..ANGLE
-2221..2222;N # Sm [2] MEASURED ANGLE..SPHERICAL ANGLE
-2223;A # Sm DIVIDES
-2224;N # Sm DOES NOT DIVIDE
-2225;A # Sm PARALLEL TO
-2226;N # Sm NOT PARALLEL TO
-2227..222C;A # Sm [6] LOGICAL AND..DOUBLE INTEGRAL
-222D;N # Sm TRIPLE INTEGRAL
-222E;A # Sm CONTOUR INTEGRAL
-222F..2233;N # Sm [5] SURFACE INTEGRAL..ANTICLOCKWISE CONTOUR INTEGRAL
-2234..2237;A # Sm [4] THEREFORE..PROPORTION
-2238..223B;N # Sm [4] DOT MINUS..HOMOTHETIC
-223C..223D;A # Sm [2] TILDE OPERATOR..REVERSED TILDE
-223E..2247;N # Sm [10] INVERTED LAZY S..NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
-2248;A # Sm ALMOST EQUAL TO
-2249..224B;N # Sm [3] NOT ALMOST EQUAL TO..TRIPLE TILDE
-224C;A # Sm ALL EQUAL TO
-224D..2251;N # Sm [5] EQUIVALENT TO..GEOMETRICALLY EQUAL TO
-2252;A # Sm APPROXIMATELY EQUAL TO OR THE IMAGE OF
-2253..225F;N # Sm [13] IMAGE OF OR APPROXIMATELY EQUAL TO..QUESTIONED EQUAL TO
-2260..2261;A # Sm [2] NOT EQUAL TO..IDENTICAL TO
-2262..2263;N # Sm [2] NOT IDENTICAL TO..STRICTLY EQUIVALENT TO
-2264..2267;A # Sm [4] LESS-THAN OR EQUAL TO..GREATER-THAN OVER EQUAL TO
-2268..2269;N # Sm [2] LESS-THAN BUT NOT EQUAL TO..GREATER-THAN BUT NOT EQUAL TO
-226A..226B;A # Sm [2] MUCH LESS-THAN..MUCH GREATER-THAN
-226C..226D;N # Sm [2] BETWEEN..NOT EQUIVALENT TO
-226E..226F;A # Sm [2] NOT LESS-THAN..NOT GREATER-THAN
-2270..2281;N # Sm [18] NEITHER LESS-THAN NOR EQUAL TO..DOES NOT SUCCEED
-2282..2283;A # Sm [2] SUBSET OF..SUPERSET OF
-2284..2285;N # Sm [2] NOT A SUBSET OF..NOT A SUPERSET OF
-2286..2287;A # Sm [2] SUBSET OF OR EQUAL TO..SUPERSET OF OR EQUAL TO
-2288..2294;N # Sm [13] NEITHER A SUBSET OF NOR EQUAL TO..SQUARE CUP
-2295;A # Sm CIRCLED PLUS
-2296..2298;N # Sm [3] CIRCLED MINUS..CIRCLED DIVISION SLASH
-2299;A # Sm CIRCLED DOT OPERATOR
-229A..22A4;N # Sm [11] CIRCLED RING OPERATOR..DOWN TACK
-22A5;A # Sm UP TACK
-22A6..22BE;N # Sm [25] ASSERTION..RIGHT ANGLE WITH ARC
-22BF;A # Sm RIGHT TRIANGLE
-22C0..22FF;N # Sm [64] N-ARY LOGICAL AND..Z NOTATION BAG MEMBERSHIP
-2300..2307;N # So [8] DIAMETER SIGN..WAVY LINE
-2308;N # Ps LEFT CEILING
-2309;N # Pe RIGHT CEILING
-230A;N # Ps LEFT FLOOR
-230B;N # Pe RIGHT FLOOR
-230C..2311;N # So [6] BOTTOM RIGHT CROP..SQUARE LOZENGE
-2312;A # So ARC
-2313..2319;N # So [7] SEGMENT..TURNED NOT SIGN
-231A..231B;W # So [2] WATCH..HOURGLASS
-231C..231F;N # So [4] TOP LEFT CORNER..BOTTOM RIGHT CORNER
-2320..2321;N # Sm [2] TOP HALF INTEGRAL..BOTTOM HALF INTEGRAL
-2322..2328;N # So [7] FROWN..KEYBOARD
-2329;W # Ps LEFT-POINTING ANGLE BRACKET
-232A;W # Pe RIGHT-POINTING ANGLE BRACKET
-232B..237B;N # So [81] ERASE TO THE LEFT..NOT CHECK MARK
-237C;N # Sm RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW
-237D..239A;N # So [30] SHOULDERED OPEN BOX..CLEAR SCREEN SYMBOL
-239B..23B3;N # Sm [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM
-23B4..23DB;N # So [40] TOP SQUARE BRACKET..FUSE
-23DC..23E1;N # Sm [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET
-23E2..23E8;N # So [7] WHITE TRAPEZIUM..DECIMAL EXPONENT SYMBOL
-23E9..23EC;W # So [4] BLACK RIGHT-POINTING DOUBLE TRIANGLE..BLACK DOWN-POINTING DOUBLE TRIANGLE
-23ED..23EF;N # So [3] BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR..BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
-23F0;W # So ALARM CLOCK
-23F1..23F2;N # So [2] STOPWATCH..TIMER CLOCK
-23F3;W # So HOURGLASS WITH FLOWING SAND
-23F4..23FF;N # So [12] BLACK MEDIUM LEFT-POINTING TRIANGLE..OBSERVER EYE SYMBOL
-2400..2426;N # So [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO
-2440..244A;N # So [11] OCR HOOK..OCR DOUBLE BACKSLASH
-2460..249B;A # No [60] CIRCLED DIGIT ONE..NUMBER TWENTY FULL STOP
-249C..24E9;A # So [78] PARENTHESIZED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z
-24EA;N # No CIRCLED DIGIT ZERO
-24EB..24FF;A # No [21] NEGATIVE CIRCLED NUMBER ELEVEN..NEGATIVE CIRCLED DIGIT ZERO
-2500..254B;A # So [76] BOX DRAWINGS LIGHT HORIZONTAL..BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL
-254C..254F;N # So [4] BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL..BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL
-2550..2573;A # So [36] BOX DRAWINGS DOUBLE HORIZONTAL..BOX DRAWINGS LIGHT DIAGONAL CROSS
-2574..257F;N # So [12] BOX DRAWINGS LIGHT LEFT..BOX DRAWINGS HEAVY UP AND LIGHT DOWN
-2580..258F;A # So [16] UPPER HALF BLOCK..LEFT ONE EIGHTH BLOCK
-2590..2591;N # So [2] RIGHT HALF BLOCK..LIGHT SHADE
-2592..2595;A # So [4] MEDIUM SHADE..RIGHT ONE EIGHTH BLOCK
-2596..259F;N # So [10] QUADRANT LOWER LEFT..QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
-25A0..25A1;A # So [2] BLACK SQUARE..WHITE SQUARE
-25A2;N # So WHITE SQUARE WITH ROUNDED CORNERS
-25A3..25A9;A # So [7] WHITE SQUARE CONTAINING BLACK SMALL SQUARE..SQUARE WITH DIAGONAL CROSSHATCH FILL
-25AA..25B1;N # So [8] BLACK SMALL SQUARE..WHITE PARALLELOGRAM
-25B2..25B3;A # So [2] BLACK UP-POINTING TRIANGLE..WHITE UP-POINTING TRIANGLE
-25B4..25B5;N # So [2] BLACK UP-POINTING SMALL TRIANGLE..WHITE UP-POINTING SMALL TRIANGLE
-25B6;A # So BLACK RIGHT-POINTING TRIANGLE
-25B7;A # Sm WHITE RIGHT-POINTING TRIANGLE
-25B8..25BB;N # So [4] BLACK RIGHT-POINTING SMALL TRIANGLE..WHITE RIGHT-POINTING POINTER
-25BC..25BD;A # So [2] BLACK DOWN-POINTING TRIANGLE..WHITE DOWN-POINTING TRIANGLE
-25BE..25BF;N # So [2] BLACK DOWN-POINTING SMALL TRIANGLE..WHITE DOWN-POINTING SMALL TRIANGLE
-25C0;A # So BLACK LEFT-POINTING TRIANGLE
-25C1;A # Sm WHITE LEFT-POINTING TRIANGLE
-25C2..25C5;N # So [4] BLACK LEFT-POINTING SMALL TRIANGLE..WHITE LEFT-POINTING POINTER
-25C6..25C8;A # So [3] BLACK DIAMOND..WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND
-25C9..25CA;N # So [2] FISHEYE..LOZENGE
-25CB;A # So WHITE CIRCLE
-25CC..25CD;N # So [2] DOTTED CIRCLE..CIRCLE WITH VERTICAL FILL
-25CE..25D1;A # So [4] BULLSEYE..CIRCLE WITH RIGHT HALF BLACK
-25D2..25E1;N # So [16] CIRCLE WITH LOWER HALF BLACK..LOWER HALF CIRCLE
-25E2..25E5;A # So [4] BLACK LOWER RIGHT TRIANGLE..BLACK UPPER RIGHT TRIANGLE
-25E6..25EE;N # So [9] WHITE BULLET..UP-POINTING TRIANGLE WITH RIGHT HALF BLACK
-25EF;A # So LARGE CIRCLE
-25F0..25F7;N # So [8] WHITE SQUARE WITH UPPER LEFT QUADRANT..WHITE CIRCLE WITH UPPER RIGHT QUADRANT
-25F8..25FC;N # Sm [5] UPPER LEFT TRIANGLE..BLACK MEDIUM SQUARE
-25FD..25FE;W # Sm [2] WHITE MEDIUM SMALL SQUARE..BLACK MEDIUM SMALL SQUARE
-25FF;N # Sm LOWER RIGHT TRIANGLE
-2600..2604;N # So [5] BLACK SUN WITH RAYS..COMET
-2605..2606;A # So [2] BLACK STAR..WHITE STAR
-2607..2608;N # So [2] LIGHTNING..THUNDERSTORM
-2609;A # So SUN
-260A..260D;N # So [4] ASCENDING NODE..OPPOSITION
-260E..260F;A # So [2] BLACK TELEPHONE..WHITE TELEPHONE
-2610..2613;N # So [4] BALLOT BOX..SALTIRE
-2614..2615;W # So [2] UMBRELLA WITH RAIN DROPS..HOT BEVERAGE
-2616..261B;N # So [6] WHITE SHOGI PIECE..BLACK RIGHT POINTING INDEX
-261C;A # So WHITE LEFT POINTING INDEX
-261D;N # So WHITE UP POINTING INDEX
-261E;A # So WHITE RIGHT POINTING INDEX
-261F..263F;N # So [33] WHITE DOWN POINTING INDEX..MERCURY
-2640;A # So FEMALE SIGN
-2641;N # So EARTH
-2642;A # So MALE SIGN
-2643..2647;N # So [5] JUPITER..PLUTO
-2648..2653;W # So [12] ARIES..PISCES
-2654..265F;N # So [12] WHITE CHESS KING..BLACK CHESS PAWN
-2660..2661;A # So [2] BLACK SPADE SUIT..WHITE HEART SUIT
-2662;N # So WHITE DIAMOND SUIT
-2663..2665;A # So [3] BLACK CLUB SUIT..BLACK HEART SUIT
-2666;N # So BLACK DIAMOND SUIT
-2667..266A;A # So [4] WHITE CLUB SUIT..EIGHTH NOTE
-266B;N # So BEAMED EIGHTH NOTES
-266C..266D;A # So [2] BEAMED SIXTEENTH NOTES..MUSIC FLAT SIGN
-266E;N # So MUSIC NATURAL SIGN
-266F;A # Sm MUSIC SHARP SIGN
-2670..267E;N # So [15] WEST SYRIAC CROSS..PERMANENT PAPER SIGN
-267F;W # So WHEELCHAIR SYMBOL
-2680..2692;N # So [19] DIE FACE-1..HAMMER AND PICK
-2693;W # So ANCHOR
-2694..269D;N # So [10] CROSSED SWORDS..OUTLINED WHITE STAR
-269E..269F;A # So [2] THREE LINES CONVERGING RIGHT..THREE LINES CONVERGING LEFT
-26A0;N # So WARNING SIGN
-26A1;W # So HIGH VOLTAGE SIGN
-26A2..26A9;N # So [8] DOUBLED FEMALE SIGN..HORIZONTAL MALE WITH STROKE SIGN
-26AA..26AB;W # So [2] MEDIUM WHITE CIRCLE..MEDIUM BLACK CIRCLE
-26AC..26BC;N # So [17] MEDIUM SMALL WHITE CIRCLE..SESQUIQUADRATE
-26BD..26BE;W # So [2] SOCCER BALL..BASEBALL
-26BF;A # So SQUARED KEY
-26C0..26C3;N # So [4] WHITE DRAUGHTS MAN..BLACK DRAUGHTS KING
-26C4..26C5;W # So [2] SNOWMAN WITHOUT SNOW..SUN BEHIND CLOUD
-26C6..26CD;A # So [8] RAIN..DISABLED CAR
-26CE;W # So OPHIUCHUS
-26CF..26D3;A # So [5] PICK..CHAINS
-26D4;W # So NO ENTRY
-26D5..26E1;A # So [13] ALTERNATE ONE-WAY LEFT WAY TRAFFIC..RESTRICTED LEFT ENTRY-2
-26E2;N # So ASTRONOMICAL SYMBOL FOR URANUS
-26E3;A # So HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE
-26E4..26E7;N # So [4] PENTAGRAM..INVERTED PENTAGRAM
-26E8..26E9;A # So [2] BLACK CROSS ON SHIELD..SHINTO SHRINE
-26EA;W # So CHURCH
-26EB..26F1;A # So [7] CASTLE..UMBRELLA ON GROUND
-26F2..26F3;W # So [2] FOUNTAIN..FLAG IN HOLE
-26F4;A # So FERRY
-26F5;W # So SAILBOAT
-26F6..26F9;A # So [4] SQUARE FOUR CORNERS..PERSON WITH BALL
-26FA;W # So TENT
-26FB..26FC;A # So [2] JAPANESE BANK SYMBOL..HEADSTONE GRAVEYARD SYMBOL
-26FD;W # So FUEL PUMP
-26FE..26FF;A # So [2] CUP ON BLACK SQUARE..WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE
-2700..2704;N # So [5] BLACK SAFETY SCISSORS..WHITE SCISSORS
-2705;W # So WHITE HEAVY CHECK MARK
-2706..2709;N # So [4] TELEPHONE LOCATION SIGN..ENVELOPE
-270A..270B;W # So [2] RAISED FIST..RAISED HAND
-270C..2727;N # So [28] VICTORY HAND..WHITE FOUR POINTED STAR
-2728;W # So SPARKLES
-2729..273C;N # So [20] STRESS OUTLINED WHITE STAR..OPEN CENTRE TEARDROP-SPOKED ASTERISK
-273D;A # So HEAVY TEARDROP-SPOKED ASTERISK
-273E..274B;N # So [14] SIX PETALLED BLACK AND WHITE FLORETTE..HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
-274C;W # So CROSS MARK
-274D;N # So SHADOWED WHITE CIRCLE
-274E;W # So NEGATIVE SQUARED CROSS MARK
-274F..2752;N # So [4] LOWER RIGHT DROP-SHADOWED WHITE SQUARE..UPPER RIGHT SHADOWED WHITE SQUARE
-2753..2755;W # So [3] BLACK QUESTION MARK ORNAMENT..WHITE EXCLAMATION MARK ORNAMENT
-2756;N # So BLACK DIAMOND MINUS WHITE X
-2757;W # So HEAVY EXCLAMATION MARK SYMBOL
-2758..2767;N # So [16] LIGHT VERTICAL BAR..ROTATED FLORAL HEART BULLET
-2768;N # Ps MEDIUM LEFT PARENTHESIS ORNAMENT
-2769;N # Pe MEDIUM RIGHT PARENTHESIS ORNAMENT
-276A;N # Ps MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT
-276B;N # Pe MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT
-276C;N # Ps MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT
-276D;N # Pe MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT
-276E;N # Ps HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT
-276F;N # Pe HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT
-2770;N # Ps HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT
-2771;N # Pe HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT
-2772;N # Ps LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT
-2773;N # Pe LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT
-2774;N # Ps MEDIUM LEFT CURLY BRACKET ORNAMENT
-2775;N # Pe MEDIUM RIGHT CURLY BRACKET ORNAMENT
-2776..277F;A # No [10] DINGBAT NEGATIVE CIRCLED DIGIT ONE..DINGBAT NEGATIVE CIRCLED NUMBER TEN
-2780..2793;N # No [20] DINGBAT CIRCLED SANS-SERIF DIGIT ONE..DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN
-2794;N # So HEAVY WIDE-HEADED RIGHTWARDS ARROW
-2795..2797;W # So [3] HEAVY PLUS SIGN..HEAVY DIVISION SIGN
-2798..27AF;N # So [24] HEAVY SOUTH EAST ARROW..NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
-27B0;W # So CURLY LOOP
-27B1..27BE;N # So [14] NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW..OPEN-OUTLINED RIGHTWARDS ARROW
-27BF;W # So DOUBLE CURLY LOOP
-27C0..27C4;N # Sm [5] THREE DIMENSIONAL ANGLE..OPEN SUPERSET
-27C5;N # Ps LEFT S-SHAPED BAG DELIMITER
-27C6;N # Pe RIGHT S-SHAPED BAG DELIMITER
-27C7..27E5;N # Sm [31] OR WITH DOT INSIDE..WHITE SQUARE WITH RIGHTWARDS TICK
-27E6;Na # Ps MATHEMATICAL LEFT WHITE SQUARE BRACKET
-27E7;Na # Pe MATHEMATICAL RIGHT WHITE SQUARE BRACKET
-27E8;Na # Ps MATHEMATICAL LEFT ANGLE BRACKET
-27E9;Na # Pe MATHEMATICAL RIGHT ANGLE BRACKET
-27EA;Na # Ps MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
-27EB;Na # Pe MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
-27EC;Na # Ps MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET
-27ED;Na # Pe MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET
-27EE;N # Ps MATHEMATICAL LEFT FLATTENED PARENTHESIS
-27EF;N # Pe MATHEMATICAL RIGHT FLATTENED PARENTHESIS
-27F0..27FF;N # Sm [16] UPWARDS QUADRUPLE ARROW..LONG RIGHTWARDS SQUIGGLE ARROW
-2800..28FF;N # So [256] BRAILLE PATTERN BLANK..BRAILLE PATTERN DOTS-12345678
-2900..297F;N # Sm [128] RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE..DOWN FISH TAIL
-2980..2982;N # Sm [3] TRIPLE VERTICAL BAR DELIMITER..Z NOTATION TYPE COLON
-2983;N # Ps LEFT WHITE CURLY BRACKET
-2984;N # Pe RIGHT WHITE CURLY BRACKET
-2985;Na # Ps LEFT WHITE PARENTHESIS
-2986;Na # Pe RIGHT WHITE PARENTHESIS
-2987;N # Ps Z NOTATION LEFT IMAGE BRACKET
-2988;N # Pe Z NOTATION RIGHT IMAGE BRACKET
-2989;N # Ps Z NOTATION LEFT BINDING BRACKET
-298A;N # Pe Z NOTATION RIGHT BINDING BRACKET
-298B;N # Ps LEFT SQUARE BRACKET WITH UNDERBAR
-298C;N # Pe RIGHT SQUARE BRACKET WITH UNDERBAR
-298D;N # Ps LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
-298E;N # Pe RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
-298F;N # Ps LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
-2990;N # Pe RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
-2991;N # Ps LEFT ANGLE BRACKET WITH DOT
-2992;N # Pe RIGHT ANGLE BRACKET WITH DOT
-2993;N # Ps LEFT ARC LESS-THAN BRACKET
-2994;N # Pe RIGHT ARC GREATER-THAN BRACKET
-2995;N # Ps DOUBLE LEFT ARC GREATER-THAN BRACKET
-2996;N # Pe DOUBLE RIGHT ARC LESS-THAN BRACKET
-2997;N # Ps LEFT BLACK TORTOISE SHELL BRACKET
-2998;N # Pe RIGHT BLACK TORTOISE SHELL BRACKET
-2999..29D7;N # Sm [63] DOTTED FENCE..BLACK HOURGLASS
-29D8;N # Ps LEFT WIGGLY FENCE
-29D9;N # Pe RIGHT WIGGLY FENCE
-29DA;N # Ps LEFT DOUBLE WIGGLY FENCE
-29DB;N # Pe RIGHT DOUBLE WIGGLY FENCE
-29DC..29FB;N # Sm [32] INCOMPLETE INFINITY..TRIPLE PLUS
-29FC;N # Ps LEFT-POINTING CURVED ANGLE BRACKET
-29FD;N # Pe RIGHT-POINTING CURVED ANGLE BRACKET
-29FE..29FF;N # Sm [2] TINY..MINY
-2A00..2AFF;N # Sm [256] N-ARY CIRCLED DOT OPERATOR..N-ARY WHITE VERTICAL BAR
-2B00..2B1A;N # So [27] NORTH EAST WHITE ARROW..DOTTED SQUARE
-2B1B..2B1C;W # So [2] BLACK LARGE SQUARE..WHITE LARGE SQUARE
-2B1D..2B2F;N # So [19] BLACK VERY SMALL SQUARE..WHITE VERTICAL ELLIPSE
-2B30..2B44;N # Sm [21] LEFT ARROW WITH SMALL CIRCLE..RIGHTWARDS ARROW THROUGH SUPERSET
-2B45..2B46;N # So [2] LEFTWARDS QUADRUPLE ARROW..RIGHTWARDS QUADRUPLE ARROW
-2B47..2B4C;N # Sm [6] REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW..RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR
-2B4D..2B4F;N # So [3] DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW..SHORT BACKSLANTED SOUTH ARROW
-2B50;W # So WHITE MEDIUM STAR
-2B51..2B54;N # So [4] BLACK SMALL STAR..WHITE RIGHT-POINTING PENTAGON
-2B55;W # So HEAVY LARGE CIRCLE
-2B56..2B59;A # So [4] HEAVY OVAL WITH OVAL INSIDE..HEAVY CIRCLED SALTIRE
-2B5A..2B73;N # So [26] SLANTED NORTH ARROW WITH HOOKED HEAD..DOWNWARDS TRIANGLE-HEADED ARROW TO BAR
-2B76..2B95;N # So [32] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW
-2B97..2BFF;N # So [105] SYMBOL FOR TYPE A ELECTRONICS..HELLSCHREIBER PAUSE SYMBOL
-2C00..2C5F;N # L& [96] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC SMALL LETTER CAUDATE CHRIVI
-2C60..2C7B;N # L& [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E
-2C7C..2C7D;N # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V
-2C7E..2C7F;N # Lu [2] LATIN CAPITAL LETTER S WITH SWASH TAIL..LATIN CAPITAL LETTER Z WITH SWASH TAIL
-2C80..2CE4;N # L& [101] COPTIC CAPITAL LETTER ALFA..COPTIC SYMBOL KAI
-2CE5..2CEA;N # So [6] COPTIC SYMBOL MI RO..COPTIC SYMBOL SHIMA SIMA
-2CEB..2CEE;N # L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA
-2CEF..2CF1;N # Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS
-2CF2..2CF3;N # L& [2] COPTIC CAPITAL LETTER BOHAIRIC KHEI..COPTIC SMALL LETTER BOHAIRIC KHEI
-2CF9..2CFC;N # Po [4] COPTIC OLD NUBIAN FULL STOP..COPTIC OLD NUBIAN VERSE DIVIDER
-2CFD;N # No COPTIC FRACTION ONE HALF
-2CFE..2CFF;N # Po [2] COPTIC FULL STOP..COPTIC MORPHOLOGICAL DIVIDER
-2D00..2D25;N # Ll [38] GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE
-2D27;N # Ll GEORGIAN SMALL LETTER YN
-2D2D;N # Ll GEORGIAN SMALL LETTER AEN
-2D30..2D67;N # Lo [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO
-2D6F;N # Lm TIFINAGH MODIFIER LETTER LABIALIZATION MARK
-2D70;N # Po TIFINAGH SEPARATOR MARK
-2D7F;N # Mn TIFINAGH CONSONANT JOINER
-2D80..2D96;N # Lo [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE
-2DA0..2DA6;N # Lo [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO
-2DA8..2DAE;N # Lo [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO
-2DB0..2DB6;N # Lo [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO
-2DB8..2DBE;N # Lo [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO
-2DC0..2DC6;N # Lo [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO
-2DC8..2DCE;N # Lo [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO
-2DD0..2DD6;N # Lo [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO
-2DD8..2DDE;N # Lo [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO
-2DE0..2DFF;N # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
-2E00..2E01;N # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER
-2E02;N # Pi LEFT SUBSTITUTION BRACKET
-2E03;N # Pf RIGHT SUBSTITUTION BRACKET
-2E04;N # Pi LEFT DOTTED SUBSTITUTION BRACKET
-2E05;N # Pf RIGHT DOTTED SUBSTITUTION BRACKET
-2E06..2E08;N # Po [3] RAISED INTERPOLATION MARKER..DOTTED TRANSPOSITION MARKER
-2E09;N # Pi LEFT TRANSPOSITION BRACKET
-2E0A;N # Pf RIGHT TRANSPOSITION BRACKET
-2E0B;N # Po RAISED SQUARE
-2E0C;N # Pi LEFT RAISED OMISSION BRACKET
-2E0D;N # Pf RIGHT RAISED OMISSION BRACKET
-2E0E..2E16;N # Po [9] EDITORIAL CORONIS..DOTTED RIGHT-POINTING ANGLE
-2E17;N # Pd DOUBLE OBLIQUE HYPHEN
-2E18..2E19;N # Po [2] INVERTED INTERROBANG..PALM BRANCH
-2E1A;N # Pd HYPHEN WITH DIAERESIS
-2E1B;N # Po TILDE WITH RING ABOVE
-2E1C;N # Pi LEFT LOW PARAPHRASE BRACKET
-2E1D;N # Pf RIGHT LOW PARAPHRASE BRACKET
-2E1E..2E1F;N # Po [2] TILDE WITH DOT ABOVE..TILDE WITH DOT BELOW
-2E20;N # Pi LEFT VERTICAL BAR WITH QUILL
-2E21;N # Pf RIGHT VERTICAL BAR WITH QUILL
-2E22;N # Ps TOP LEFT HALF BRACKET
-2E23;N # Pe TOP RIGHT HALF BRACKET
-2E24;N # Ps BOTTOM LEFT HALF BRACKET
-2E25;N # Pe BOTTOM RIGHT HALF BRACKET
-2E26;N # Ps LEFT SIDEWAYS U BRACKET
-2E27;N # Pe RIGHT SIDEWAYS U BRACKET
-2E28;N # Ps LEFT DOUBLE PARENTHESIS
-2E29;N # Pe RIGHT DOUBLE PARENTHESIS
-2E2A..2E2E;N # Po [5] TWO DOTS OVER ONE DOT PUNCTUATION..REVERSED QUESTION MARK
-2E2F;N # Lm VERTICAL TILDE
-2E30..2E39;N # Po [10] RING POINT..TOP HALF SECTION SIGN
-2E3A..2E3B;N # Pd [2] TWO-EM DASH..THREE-EM DASH
-2E3C..2E3F;N # Po [4] STENOGRAPHIC FULL STOP..CAPITULUM
-2E40;N # Pd DOUBLE HYPHEN
-2E41;N # Po REVERSED COMMA
-2E42;N # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK
-2E43..2E4F;N # Po [13] DASH WITH LEFT UPTURN..CORNISH VERSE DIVIDER
-2E50..2E51;N # So [2] CROSS PATTY WITH RIGHT CROSSBAR..CROSS PATTY WITH LEFT CROSSBAR
-2E52..2E54;N # Po [3] TIRONIAN SIGN CAPITAL ET..MEDIEVAL QUESTION MARK
-2E55;N # Ps LEFT SQUARE BRACKET WITH STROKE
-2E56;N # Pe RIGHT SQUARE BRACKET WITH STROKE
-2E57;N # Ps LEFT SQUARE BRACKET WITH DOUBLE STROKE
-2E58;N # Pe RIGHT SQUARE BRACKET WITH DOUBLE STROKE
-2E59;N # Ps TOP HALF LEFT PARENTHESIS
-2E5A;N # Pe TOP HALF RIGHT PARENTHESIS
-2E5B;N # Ps BOTTOM HALF LEFT PARENTHESIS
-2E5C;N # Pe BOTTOM HALF RIGHT PARENTHESIS
-2E5D;N # Pd OBLIQUE HYPHEN
-2E80..2E99;W # So [26] CJK RADICAL REPEAT..CJK RADICAL RAP
-2E9B..2EF3;W # So [89] CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE
-2F00..2FD5;W # So [214] KANGXI RADICAL ONE..KANGXI RADICAL FLUTE
-2FF0..2FFB;W # So [12] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID
-3000;F # Zs IDEOGRAPHIC SPACE
-3001..3003;W # Po [3] IDEOGRAPHIC COMMA..DITTO MARK
-3004;W # So JAPANESE INDUSTRIAL STANDARD SYMBOL
-3005;W # Lm IDEOGRAPHIC ITERATION MARK
-3006;W # Lo IDEOGRAPHIC CLOSING MARK
-3007;W # Nl IDEOGRAPHIC NUMBER ZERO
-3008;W # Ps LEFT ANGLE BRACKET
-3009;W # Pe RIGHT ANGLE BRACKET
-300A;W # Ps LEFT DOUBLE ANGLE BRACKET
-300B;W # Pe RIGHT DOUBLE ANGLE BRACKET
-300C;W # Ps LEFT CORNER BRACKET
-300D;W # Pe RIGHT CORNER BRACKET
-300E;W # Ps LEFT WHITE CORNER BRACKET
-300F;W # Pe RIGHT WHITE CORNER BRACKET
-3010;W # Ps LEFT BLACK LENTICULAR BRACKET
-3011;W # Pe RIGHT BLACK LENTICULAR BRACKET
-3012..3013;W # So [2] POSTAL MARK..GETA MARK
-3014;W # Ps LEFT TORTOISE SHELL BRACKET
-3015;W # Pe RIGHT TORTOISE SHELL BRACKET
-3016;W # Ps LEFT WHITE LENTICULAR BRACKET
-3017;W # Pe RIGHT WHITE LENTICULAR BRACKET
-3018;W # Ps LEFT WHITE TORTOISE SHELL BRACKET
-3019;W # Pe RIGHT WHITE TORTOISE SHELL BRACKET
-301A;W # Ps LEFT WHITE SQUARE BRACKET
-301B;W # Pe RIGHT WHITE SQUARE BRACKET
-301C;W # Pd WAVE DASH
-301D;W # Ps REVERSED DOUBLE PRIME QUOTATION MARK
-301E..301F;W # Pe [2] DOUBLE PRIME QUOTATION MARK..LOW DOUBLE PRIME QUOTATION MARK
-3020;W # So POSTAL MARK FACE
-3021..3029;W # Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE
-302A..302D;W # Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK
-302E..302F;W # Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK
-3030;W # Pd WAVY DASH
-3031..3035;W # Lm [5] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT MARK LOWER HALF
-3036..3037;W # So [2] CIRCLED POSTAL MARK..IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL
-3038..303A;W # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY
-303B;W # Lm VERTICAL IDEOGRAPHIC ITERATION MARK
-303C;W # Lo MASU MARK
-303D;W # Po PART ALTERNATION MARK
-303E;W # So IDEOGRAPHIC VARIATION INDICATOR
-303F;N # So IDEOGRAPHIC HALF FILL SPACE
-3041..3096;W # Lo [86] HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE
-3099..309A;W # Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
-309B..309C;W # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
-309D..309E;W # Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK
-309F;W # Lo HIRAGANA DIGRAPH YORI
-30A0;W # Pd KATAKANA-HIRAGANA DOUBLE HYPHEN
-30A1..30FA;W # Lo [90] KATAKANA LETTER SMALL A..KATAKANA LETTER VO
-30FB;W # Po KATAKANA MIDDLE DOT
-30FC..30FE;W # Lm [3] KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK
-30FF;W # Lo KATAKANA DIGRAPH KOTO
-3105..312F;W # Lo [43] BOPOMOFO LETTER B..BOPOMOFO LETTER NN
-3131..318E;W # Lo [94] HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE
-3190..3191;W # So [2] IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION REVERSE MARK
-3192..3195;W # No [4] IDEOGRAPHIC ANNOTATION ONE MARK..IDEOGRAPHIC ANNOTATION FOUR MARK
-3196..319F;W # So [10] IDEOGRAPHIC ANNOTATION TOP MARK..IDEOGRAPHIC ANNOTATION MAN MARK
-31A0..31BF;W # Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH
-31C0..31E3;W # So [36] CJK STROKE T..CJK STROKE Q
-31F0..31FF;W # Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO
-3200..321E;W # So [31] PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED KOREAN CHARACTER O HU
-3220..3229;W # No [10] PARENTHESIZED IDEOGRAPH ONE..PARENTHESIZED IDEOGRAPH TEN
-322A..3247;W # So [30] PARENTHESIZED IDEOGRAPH MOON..CIRCLED IDEOGRAPH KOTO
-3248..324F;A # No [8] CIRCLED NUMBER TEN ON BLACK SQUARE..CIRCLED NUMBER EIGHTY ON BLACK SQUARE
-3250;W # So PARTNERSHIP SIGN
-3251..325F;W # No [15] CIRCLED NUMBER TWENTY ONE..CIRCLED NUMBER THIRTY FIVE
-3260..327F;W # So [32] CIRCLED HANGUL KIYEOK..KOREAN STANDARD SYMBOL
-3280..3289;W # No [10] CIRCLED IDEOGRAPH ONE..CIRCLED IDEOGRAPH TEN
-328A..32B0;W # So [39] CIRCLED IDEOGRAPH MOON..CIRCLED IDEOGRAPH NIGHT
-32B1..32BF;W # No [15] CIRCLED NUMBER THIRTY SIX..CIRCLED NUMBER FIFTY
-32C0..32FF;W # So [64] IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY..SQUARE ERA NAME REIWA
-3300..33FF;W # So [256] SQUARE APAATO..SQUARE GAL
-3400..4DBF;W # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF
-4DC0..4DFF;N # So [64] HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM FOR BEFORE COMPLETION
-4E00..9FFF;W # Lo [20992] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFF
-A000..A014;W # Lo [21] YI SYLLABLE IT..YI SYLLABLE E
-A015;W # Lm YI SYLLABLE WU
-A016..A48C;W # Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR
-A490..A4C6;W # So [55] YI RADICAL QOT..YI RADICAL KE
-A4D0..A4F7;N # Lo [40] LISU LETTER BA..LISU LETTER OE
-A4F8..A4FD;N # Lm [6] LISU LETTER TONE MYA TI..LISU LETTER TONE MYA JEU
-A4FE..A4FF;N # Po [2] LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP
-A500..A60B;N # Lo [268] VAI SYLLABLE EE..VAI SYLLABLE NG
-A60C;N # Lm VAI SYLLABLE LENGTHENER
-A60D..A60F;N # Po [3] VAI COMMA..VAI QUESTION MARK
-A610..A61F;N # Lo [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL JONG
-A620..A629;N # Nd [10] VAI DIGIT ZERO..VAI DIGIT NINE
-A62A..A62B;N # Lo [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO
-A640..A66D;N # L& [46] CYRILLIC CAPITAL LETTER ZEMLYA..CYRILLIC SMALL LETTER DOUBLE MONOCULAR O
-A66E;N # Lo CYRILLIC LETTER MULTIOCULAR O
-A66F;N # Mn COMBINING CYRILLIC VZMET
-A670..A672;N # Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN
-A673;N # Po SLAVONIC ASTERISK
-A674..A67D;N # Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK
-A67E;N # Po CYRILLIC KAVYKA
-A67F;N # Lm CYRILLIC PAYEROK
-A680..A69B;N # L& [28] CYRILLIC CAPITAL LETTER DWE..CYRILLIC SMALL LETTER CROSSED O
-A69C..A69D;N # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN
-A69E..A69F;N # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E
-A6A0..A6E5;N # Lo [70] BAMUM LETTER A..BAMUM LETTER KI
-A6E6..A6EF;N # Nl [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM
-A6F0..A6F1;N # Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS
-A6F2..A6F7;N # Po [6] BAMUM NJAEMLI..BAMUM QUESTION MARK
-A700..A716;N # Sk [23] MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR
-A717..A71F;N # Lm [9] MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK
-A720..A721;N # Sk [2] MODIFIER LETTER STRESS AND HIGH TONE..MODIFIER LETTER STRESS AND LOW TONE
-A722..A76F;N # L& [78] LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF..LATIN SMALL LETTER CON
-A770;N # Lm MODIFIER LETTER US
-A771..A787;N # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T
-A788;N # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT
-A789..A78A;N # Sk [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN
-A78B..A78E;N # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT
-A78F;N # Lo LATIN LETTER SINOLOGICAL DOT
-A790..A7CA;N # L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY
-A7D0..A7D1;N # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G
-A7D3;N # Ll LATIN SMALL LETTER DOUBLE THORN
-A7D5..A7D9;N # L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S
-A7F2..A7F4;N # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q
-A7F5..A7F6;N # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H
-A7F7;N # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I
-A7F8..A7F9;N # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE
-A7FA;N # Ll LATIN LETTER SMALL CAPITAL TURNED M
-A7FB..A7FF;N # Lo [5] LATIN EPIGRAPHIC LETTER REVERSED F..LATIN EPIGRAPHIC LETTER ARCHAIC M
-A800..A801;N # Lo [2] SYLOTI NAGRI LETTER A..SYLOTI NAGRI LETTER I
-A802;N # Mn SYLOTI NAGRI SIGN DVISVARA
-A803..A805;N # Lo [3] SYLOTI NAGRI LETTER U..SYLOTI NAGRI LETTER O
-A806;N # Mn SYLOTI NAGRI SIGN HASANTA
-A807..A80A;N # Lo [4] SYLOTI NAGRI LETTER KO..SYLOTI NAGRI LETTER GHO
-A80B;N # Mn SYLOTI NAGRI SIGN ANUSVARA
-A80C..A822;N # Lo [23] SYLOTI NAGRI LETTER CO..SYLOTI NAGRI LETTER HO
-A823..A824;N # Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I
-A825..A826;N # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E
-A827;N # Mc SYLOTI NAGRI VOWEL SIGN OO
-A828..A82B;N # So [4] SYLOTI NAGRI POETRY MARK-1..SYLOTI NAGRI POETRY MARK-4
-A82C;N # Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA
-A830..A835;N # No [6] NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC FRACTION THREE SIXTEENTHS
-A836..A837;N # So [2] NORTH INDIC QUARTER MARK..NORTH INDIC PLACEHOLDER MARK
-A838;N # Sc NORTH INDIC RUPEE MARK
-A839;N # So NORTH INDIC QUANTITY MARK
-A840..A873;N # Lo [52] PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU
-A874..A877;N # Po [4] PHAGS-PA SINGLE HEAD MARK..PHAGS-PA MARK DOUBLE SHAD
-A880..A881;N # Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA
-A882..A8B3;N # Lo [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA
-A8B4..A8C3;N # Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU
-A8C4..A8C5;N # Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU
-A8CE..A8CF;N # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA
-A8D0..A8D9;N # Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE
-A8E0..A8F1;N # Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA
-A8F2..A8F7;N # Lo [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA
-A8F8..A8FA;N # Po [3] DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET
-A8FB;N # Lo DEVANAGARI HEADSTROKE
-A8FC;N # Po DEVANAGARI SIGN SIDDHAM
-A8FD..A8FE;N # Lo [2] DEVANAGARI JAIN OM..DEVANAGARI LETTER AY
-A8FF;N # Mn DEVANAGARI VOWEL SIGN AY
-A900..A909;N # Nd [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE
-A90A..A925;N # Lo [28] KAYAH LI LETTER KA..KAYAH LI LETTER OO
-A926..A92D;N # Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU
-A92E..A92F;N # Po [2] KAYAH LI SIGN CWI..KAYAH LI SIGN SHYA
-A930..A946;N # Lo [23] REJANG LETTER KA..REJANG LETTER A
-A947..A951;N # Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R
-A952..A953;N # Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA
-A95F;N # Po REJANG SECTION MARK
-A960..A97C;W # Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH
-A980..A982;N # Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR
-A983;N # Mc JAVANESE SIGN WIGNYAN
-A984..A9B2;N # Lo [47] JAVANESE LETTER A..JAVANESE LETTER HA
-A9B3;N # Mn JAVANESE SIGN CECAK TELU
-A9B4..A9B5;N # Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG
-A9B6..A9B9;N # Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT
-A9BA..A9BB;N # Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE
-A9BC..A9BD;N # Mn [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET
-A9BE..A9C0;N # Mc [3] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE PANGKON
-A9C1..A9CD;N # Po [13] JAVANESE LEFT RERENGGAN..JAVANESE TURNED PADA PISELEH
-A9CF;N # Lm JAVANESE PANGRANGKEP
-A9D0..A9D9;N # Nd [10] JAVANESE DIGIT ZERO..JAVANESE DIGIT NINE
-A9DE..A9DF;N # Po [2] JAVANESE PADA TIRTA TUMETES..JAVANESE PADA ISEN-ISEN
-A9E0..A9E4;N # Lo [5] MYANMAR LETTER SHAN GHA..MYANMAR LETTER SHAN BHA
-A9E5;N # Mn MYANMAR SIGN SHAN SAW
-A9E6;N # Lm MYANMAR MODIFIER LETTER SHAN REDUPLICATION
-A9E7..A9EF;N # Lo [9] MYANMAR LETTER TAI LAING NYA..MYANMAR LETTER TAI LAING NNA
-A9F0..A9F9;N # Nd [10] MYANMAR TAI LAING DIGIT ZERO..MYANMAR TAI LAING DIGIT NINE
-A9FA..A9FE;N # Lo [5] MYANMAR LETTER TAI LAING LLA..MYANMAR LETTER TAI LAING BHA
-AA00..AA28;N # Lo [41] CHAM LETTER A..CHAM LETTER HA
-AA29..AA2E;N # Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE
-AA2F..AA30;N # Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI
-AA31..AA32;N # Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE
-AA33..AA34;N # Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA
-AA35..AA36;N # Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA
-AA40..AA42;N # Lo [3] CHAM LETTER FINAL K..CHAM LETTER FINAL NG
-AA43;N # Mn CHAM CONSONANT SIGN FINAL NG
-AA44..AA4B;N # Lo [8] CHAM LETTER FINAL CH..CHAM LETTER FINAL SS
-AA4C;N # Mn CHAM CONSONANT SIGN FINAL M
-AA4D;N # Mc CHAM CONSONANT SIGN FINAL H
-AA50..AA59;N # Nd [10] CHAM DIGIT ZERO..CHAM DIGIT NINE
-AA5C..AA5F;N # Po [4] CHAM PUNCTUATION SPIRAL..CHAM PUNCTUATION TRIPLE DANDA
-AA60..AA6F;N # Lo [16] MYANMAR LETTER KHAMTI GA..MYANMAR LETTER KHAMTI FA
-AA70;N # Lm MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION
-AA71..AA76;N # Lo [6] MYANMAR LETTER KHAMTI XA..MYANMAR LOGOGRAM KHAMTI HM
-AA77..AA79;N # So [3] MYANMAR SYMBOL AITON EXCLAMATION..MYANMAR SYMBOL AITON TWO
-AA7A;N # Lo MYANMAR LETTER AITON RA
-AA7B;N # Mc MYANMAR SIGN PAO KAREN TONE
-AA7C;N # Mn MYANMAR SIGN TAI LAING TONE-2
-AA7D;N # Mc MYANMAR SIGN TAI LAING TONE-5
-AA7E..AA7F;N # Lo [2] MYANMAR LETTER SHWE PALAUNG CHA..MYANMAR LETTER SHWE PALAUNG SHA
-AA80..AAAF;N # Lo [48] TAI VIET LETTER LOW KO..TAI VIET LETTER HIGH O
-AAB0;N # Mn TAI VIET MAI KANG
-AAB1;N # Lo TAI VIET VOWEL AA
-AAB2..AAB4;N # Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U
-AAB5..AAB6;N # Lo [2] TAI VIET VOWEL E..TAI VIET VOWEL O
-AAB7..AAB8;N # Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA
-AAB9..AABD;N # Lo [5] TAI VIET VOWEL UEA..TAI VIET VOWEL AN
-AABE..AABF;N # Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK
-AAC0;N # Lo TAI VIET TONE MAI NUENG
-AAC1;N # Mn TAI VIET TONE MAI THO
-AAC2;N # Lo TAI VIET TONE MAI SONG
-AADB..AADC;N # Lo [2] TAI VIET SYMBOL KON..TAI VIET SYMBOL NUENG
-AADD;N # Lm TAI VIET SYMBOL SAM
-AADE..AADF;N # Po [2] TAI VIET SYMBOL HO HOI..TAI VIET SYMBOL KOI KOI
-AAE0..AAEA;N # Lo [11] MEETEI MAYEK LETTER E..MEETEI MAYEK LETTER SSA
-AAEB;N # Mc MEETEI MAYEK VOWEL SIGN II
-AAEC..AAED;N # Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI
-AAEE..AAEF;N # Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU
-AAF0..AAF1;N # Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM
-AAF2;N # Lo MEETEI MAYEK ANJI
-AAF3..AAF4;N # Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK
-AAF5;N # Mc MEETEI MAYEK VOWEL SIGN VISARGA
-AAF6;N # Mn MEETEI MAYEK VIRAMA
-AB01..AB06;N # Lo [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO
-AB09..AB0E;N # Lo [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO
-AB11..AB16;N # Lo [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO
-AB20..AB26;N # Lo [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO
-AB28..AB2E;N # Lo [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO
-AB30..AB5A;N # Ll [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG
-AB5B;N # Sk MODIFIER BREVE WITH INVERTED BREVE
-AB5C..AB5F;N # Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK
-AB60..AB68;N # Ll [9] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER TURNED R WITH MIDDLE TILDE
-AB69;N # Lm MODIFIER LETTER SMALL TURNED W
-AB6A..AB6B;N # Sk [2] MODIFIER LETTER LEFT TACK..MODIFIER LETTER RIGHT TACK
-AB70..ABBF;N # Ll [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA
-ABC0..ABE2;N # Lo [35] MEETEI MAYEK LETTER KOK..MEETEI MAYEK LETTER I LONSUM
-ABE3..ABE4;N # Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP
-ABE5;N # Mn MEETEI MAYEK VOWEL SIGN ANAP
-ABE6..ABE7;N # Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP
-ABE8;N # Mn MEETEI MAYEK VOWEL SIGN UNAP
-ABE9..ABEA;N # Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG
-ABEB;N # Po MEETEI MAYEK CHEIKHEI
-ABEC;N # Mc MEETEI MAYEK LUM IYEK
-ABED;N # Mn MEETEI MAYEK APUN IYEK
-ABF0..ABF9;N # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE
-AC00..D7A3;W # Lo [11172] HANGUL SYLLABLE GA..HANGUL SYLLABLE HIH
-D7B0..D7C6;N # Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E
-D7CB..D7FB;N # Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH
-D800..DB7F;N # Cs [896] <surrogate-D800>..<surrogate-DB7F>
-DB80..DBFF;N # Cs [128] <surrogate-DB80>..<surrogate-DBFF>
-DC00..DFFF;N # Cs [1024] <surrogate-DC00>..<surrogate-DFFF>
-E000..F8FF;A # Co [6400] <private-use-E000>..<private-use-F8FF>
-F900..FA6D;W # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D
-FA6E..FA6F;W # Cn [2] <reserved-FA6E>..<reserved-FA6F>
-FA70..FAD9;W # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
-FADA..FAFF;W # Cn [38] <reserved-FADA>..<reserved-FAFF>
-FB00..FB06;N # Ll [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST
-FB13..FB17;N # Ll [5] ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH
-FB1D;N # Lo HEBREW LETTER YOD WITH HIRIQ
-FB1E;N # Mn HEBREW POINT JUDEO-SPANISH VARIKA
-FB1F..FB28;N # Lo [10] HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER WIDE TAV
-FB29;N # Sm HEBREW LETTER ALTERNATIVE PLUS SIGN
-FB2A..FB36;N # Lo [13] HEBREW LETTER SHIN WITH SHIN DOT..HEBREW LETTER ZAYIN WITH DAGESH
-FB38..FB3C;N # Lo [5] HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH
-FB3E;N # Lo HEBREW LETTER MEM WITH DAGESH
-FB40..FB41;N # Lo [2] HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH
-FB43..FB44;N # Lo [2] HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH
-FB46..FB4F;N # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATURE ALEF LAMED
-FB50..FBB1;N # Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM
-FBB2..FBC2;N # Sk [17] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL WASLA ABOVE
-FBD3..FD3D;N # Lo [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM
-FD3E;N # Pe ORNATE LEFT PARENTHESIS
-FD3F;N # Ps ORNATE RIGHT PARENTHESIS
-FD40..FD4F;N # So [16] ARABIC LIGATURE RAHIMAHU ALLAAH..ARABIC LIGATURE RAHIMAHUM ALLAAH
-FD50..FD8F;N # Lo [64] ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM
-FD92..FDC7;N # Lo [54] ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM
-FDCF;N # So ARABIC LIGATURE SALAAMUHU ALAYNAA
-FDF0..FDFB;N # Lo [12] ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM..ARABIC LIGATURE JALLAJALALOUHOU
-FDFC;N # Sc RIAL SIGN
-FDFD..FDFF;N # So [3] ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM..ARABIC LIGATURE AZZA WA JALL
-FE00..FE0F;A # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
-FE10..FE16;W # Po [7] PRESENTATION FORM FOR VERTICAL COMMA..PRESENTATION FORM FOR VERTICAL QUESTION MARK
-FE17;W # Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET
-FE18;W # Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET
-FE19;W # Po PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS
-FE20..FE2F;N # Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
-FE30;W # Po PRESENTATION FORM FOR VERTICAL TWO DOT LEADER
-FE31..FE32;W # Pd [2] PRESENTATION FORM FOR VERTICAL EM DASH..PRESENTATION FORM FOR VERTICAL EN DASH
-FE33..FE34;W # Pc [2] PRESENTATION FORM FOR VERTICAL LOW LINE..PRESENTATION FORM FOR VERTICAL WAVY LOW LINE
-FE35;W # Ps PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS
-FE36;W # Pe PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS
-FE37;W # Ps PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET
-FE38;W # Pe PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET
-FE39;W # Ps PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET
-FE3A;W # Pe PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET
-FE3B;W # Ps PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET
-FE3C;W # Pe PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET
-FE3D;W # Ps PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET
-FE3E;W # Pe PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET
-FE3F;W # Ps PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET
-FE40;W # Pe PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET
-FE41;W # Ps PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET
-FE42;W # Pe PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET
-FE43;W # Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET
-FE44;W # Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET
-FE45..FE46;W # Po [2] SESAME DOT..WHITE SESAME DOT
-FE47;W # Ps PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET
-FE48;W # Pe PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET
-FE49..FE4C;W # Po [4] DASHED OVERLINE..DOUBLE WAVY OVERLINE
-FE4D..FE4F;W # Pc [3] DASHED LOW LINE..WAVY LOW LINE
-FE50..FE52;W # Po [3] SMALL COMMA..SMALL FULL STOP
-FE54..FE57;W # Po [4] SMALL SEMICOLON..SMALL EXCLAMATION MARK
-FE58;W # Pd SMALL EM DASH
-FE59;W # Ps SMALL LEFT PARENTHESIS
-FE5A;W # Pe SMALL RIGHT PARENTHESIS
-FE5B;W # Ps SMALL LEFT CURLY BRACKET
-FE5C;W # Pe SMALL RIGHT CURLY BRACKET
-FE5D;W # Ps SMALL LEFT TORTOISE SHELL BRACKET
-FE5E;W # Pe SMALL RIGHT TORTOISE SHELL BRACKET
-FE5F..FE61;W # Po [3] SMALL NUMBER SIGN..SMALL ASTERISK
-FE62;W # Sm SMALL PLUS SIGN
-FE63;W # Pd SMALL HYPHEN-MINUS
-FE64..FE66;W # Sm [3] SMALL LESS-THAN SIGN..SMALL EQUALS SIGN
-FE68;W # Po SMALL REVERSE SOLIDUS
-FE69;W # Sc SMALL DOLLAR SIGN
-FE6A..FE6B;W # Po [2] SMALL PERCENT SIGN..SMALL COMMERCIAL AT
-FE70..FE74;N # Lo [5] ARABIC FATHATAN ISOLATED FORM..ARABIC KASRATAN ISOLATED FORM
-FE76..FEFC;N # Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM
-FEFF;N # Cf ZERO WIDTH NO-BREAK SPACE
-FF01..FF03;F # Po [3] FULLWIDTH EXCLAMATION MARK..FULLWIDTH NUMBER SIGN
-FF04;F # Sc FULLWIDTH DOLLAR SIGN
-FF05..FF07;F # Po [3] FULLWIDTH PERCENT SIGN..FULLWIDTH APOSTROPHE
-FF08;F # Ps FULLWIDTH LEFT PARENTHESIS
-FF09;F # Pe FULLWIDTH RIGHT PARENTHESIS
-FF0A;F # Po FULLWIDTH ASTERISK
-FF0B;F # Sm FULLWIDTH PLUS SIGN
-FF0C;F # Po FULLWIDTH COMMA
-FF0D;F # Pd FULLWIDTH HYPHEN-MINUS
-FF0E..FF0F;F # Po [2] FULLWIDTH FULL STOP..FULLWIDTH SOLIDUS
-FF10..FF19;F # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE
-FF1A..FF1B;F # Po [2] FULLWIDTH COLON..FULLWIDTH SEMICOLON
-FF1C..FF1E;F # Sm [3] FULLWIDTH LESS-THAN SIGN..FULLWIDTH GREATER-THAN SIGN
-FF1F..FF20;F # Po [2] FULLWIDTH QUESTION MARK..FULLWIDTH COMMERCIAL AT
-FF21..FF3A;F # Lu [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z
-FF3B;F # Ps FULLWIDTH LEFT SQUARE BRACKET
-FF3C;F # Po FULLWIDTH REVERSE SOLIDUS
-FF3D;F # Pe FULLWIDTH RIGHT SQUARE BRACKET
-FF3E;F # Sk FULLWIDTH CIRCUMFLEX ACCENT
-FF3F;F # Pc FULLWIDTH LOW LINE
-FF40;F # Sk FULLWIDTH GRAVE ACCENT
-FF41..FF5A;F # Ll [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z
-FF5B;F # Ps FULLWIDTH LEFT CURLY BRACKET
-FF5C;F # Sm FULLWIDTH VERTICAL LINE
-FF5D;F # Pe FULLWIDTH RIGHT CURLY BRACKET
-FF5E;F # Sm FULLWIDTH TILDE
-FF5F;F # Ps FULLWIDTH LEFT WHITE PARENTHESIS
-FF60;F # Pe FULLWIDTH RIGHT WHITE PARENTHESIS
-FF61;H # Po HALFWIDTH IDEOGRAPHIC FULL STOP
-FF62;H # Ps HALFWIDTH LEFT CORNER BRACKET
-FF63;H # Pe HALFWIDTH RIGHT CORNER BRACKET
-FF64..FF65;H # Po [2] HALFWIDTH IDEOGRAPHIC COMMA..HALFWIDTH KATAKANA MIDDLE DOT
-FF66..FF6F;H # Lo [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU
-FF70;H # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
-FF71..FF9D;H # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N
-FF9E..FF9F;H # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
-FFA0..FFBE;H # Lo [31] HALFWIDTH HANGUL FILLER..HALFWIDTH HANGUL LETTER HIEUH
-FFC2..FFC7;H # Lo [6] HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E
-FFCA..FFCF;H # Lo [6] HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE
-FFD2..FFD7;H # Lo [6] HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU
-FFDA..FFDC;H # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I
-FFE0..FFE1;F # Sc [2] FULLWIDTH CENT SIGN..FULLWIDTH POUND SIGN
-FFE2;F # Sm FULLWIDTH NOT SIGN
-FFE3;F # Sk FULLWIDTH MACRON
-FFE4;F # So FULLWIDTH BROKEN BAR
-FFE5..FFE6;F # Sc [2] FULLWIDTH YEN SIGN..FULLWIDTH WON SIGN
-FFE8;H # So HALFWIDTH FORMS LIGHT VERTICAL
-FFE9..FFEC;H # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS ARROW
-FFED..FFEE;H # So [2] HALFWIDTH BLACK SQUARE..HALFWIDTH WHITE CIRCLE
-FFF9..FFFB;N # Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR
-FFFC;N # So OBJECT REPLACEMENT CHARACTER
-FFFD;A # So REPLACEMENT CHARACTER
-10000..1000B;N # Lo [12] LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE
-1000D..10026;N # Lo [26] LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO
-10028..1003A;N # Lo [19] LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO
-1003C..1003D;N # Lo [2] LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE
-1003F..1004D;N # Lo [15] LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO
-10050..1005D;N # Lo [14] LINEAR B SYMBOL B018..LINEAR B SYMBOL B089
-10080..100FA;N # Lo [123] LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305
-10100..10102;N # Po [3] AEGEAN WORD SEPARATOR LINE..AEGEAN CHECK MARK
-10107..10133;N # No [45] AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOUSAND
-10137..1013F;N # So [9] AEGEAN WEIGHT BASE UNIT..AEGEAN MEASURE THIRD SUBUNIT
-10140..10174;N # Nl [53] GREEK ACROPHONIC ATTIC ONE QUARTER..GREEK ACROPHONIC STRATIAN FIFTY MNAS
-10175..10178;N # No [4] GREEK ONE HALF SIGN..GREEK THREE QUARTERS SIGN
-10179..10189;N # So [17] GREEK YEAR SIGN..GREEK TRYBLION BASE SIGN
-1018A..1018B;N # No [2] GREEK ZERO SIGN..GREEK ONE QUARTER SIGN
-1018C..1018E;N # So [3] GREEK SINUSOID SIGN..NOMISMA SIGN
-10190..1019C;N # So [13] ROMAN SEXTANS SIGN..ASCIA SYMBOL
-101A0;N # So GREEK SYMBOL TAU RHO
-101D0..101FC;N # So [45] PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC SIGN WAVY BAND
-101FD;N # Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE
-10280..1029C;N # Lo [29] LYCIAN LETTER A..LYCIAN LETTER X
-102A0..102D0;N # Lo [49] CARIAN LETTER A..CARIAN LETTER UUU3
-102E0;N # Mn COPTIC EPACT THOUSANDS MARK
-102E1..102FB;N # No [27] COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED
-10300..1031F;N # Lo [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS
-10320..10323;N # No [4] OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY
-1032D..1032F;N # Lo [3] OLD ITALIC LETTER YE..OLD ITALIC LETTER SOUTHERN TSE
-10330..10340;N # Lo [17] GOTHIC LETTER AHSA..GOTHIC LETTER PAIRTHRA
-10341;N # Nl GOTHIC LETTER NINETY
-10342..10349;N # Lo [8] GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL
-1034A;N # Nl GOTHIC LETTER NINE HUNDRED
-10350..10375;N # Lo [38] OLD PERMIC LETTER AN..OLD PERMIC LETTER IA
-10376..1037A;N # Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII
-10380..1039D;N # Lo [30] UGARITIC LETTER ALPA..UGARITIC LETTER SSU
-1039F;N # Po UGARITIC WORD DIVIDER
-103A0..103C3;N # Lo [36] OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA
-103C8..103CF;N # Lo [8] OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH
-103D0;N # Po OLD PERSIAN WORD DIVIDER
-103D1..103D5;N # Nl [5] OLD PERSIAN NUMBER ONE..OLD PERSIAN NUMBER HUNDRED
-10400..1044F;N # L& [80] DESERET CAPITAL LETTER LONG I..DESERET SMALL LETTER EW
-10450..1047F;N # Lo [48] SHAVIAN LETTER PEEP..SHAVIAN LETTER YEW
-10480..1049D;N # Lo [30] OSMANYA LETTER ALEF..OSMANYA LETTER OO
-104A0..104A9;N # Nd [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE
-104B0..104D3;N # Lu [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA
-104D8..104FB;N # Ll [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA
-10500..10527;N # Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE
-10530..10563;N # Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW
-1056F;N # Po CAUCASIAN ALBANIAN CITATION MARK
-10570..1057A;N # Lu [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA
-1057C..1058A;N # Lu [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE
-1058C..10592;N # Lu [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE
-10594..10595;N # Lu [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE
-10597..105A1;N # Ll [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA
-105A3..105B1;N # Ll [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE
-105B3..105B9;N # Ll [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE
-105BB..105BC;N # Ll [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE
-10600..10736;N # Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664
-10740..10755;N # Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE
-10760..10767;N # Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807
-10780..10785;N # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK
-10787..107B0;N # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK
-107B2..107BA;N # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL
-10800..10805;N # Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA
-10808;N # Lo CYPRIOT SYLLABLE JO
-1080A..10835;N # Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO
-10837..10838;N # Lo [2] CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE
-1083C;N # Lo CYPRIOT SYLLABLE ZA
-1083F;N # Lo CYPRIOT SYLLABLE ZO
-10840..10855;N # Lo [22] IMPERIAL ARAMAIC LETTER ALEPH..IMPERIAL ARAMAIC LETTER TAW
-10857;N # Po IMPERIAL ARAMAIC SECTION SIGN
-10858..1085F;N # No [8] IMPERIAL ARAMAIC NUMBER ONE..IMPERIAL ARAMAIC NUMBER TEN THOUSAND
-10860..10876;N # Lo [23] PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW
-10877..10878;N # So [2] PALMYRENE LEFT-POINTING FLEURON..PALMYRENE RIGHT-POINTING FLEURON
-10879..1087F;N # No [7] PALMYRENE NUMBER ONE..PALMYRENE NUMBER TWENTY
-10880..1089E;N # Lo [31] NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW
-108A7..108AF;N # No [9] NABATAEAN NUMBER ONE..NABATAEAN NUMBER ONE HUNDRED
-108E0..108F2;N # Lo [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH
-108F4..108F5;N # Lo [2] HATRAN LETTER SHIN..HATRAN LETTER TAW
-108FB..108FF;N # No [5] HATRAN NUMBER ONE..HATRAN NUMBER ONE HUNDRED
-10900..10915;N # Lo [22] PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU
-10916..1091B;N # No [6] PHOENICIAN NUMBER ONE..PHOENICIAN NUMBER THREE
-1091F;N # Po PHOENICIAN WORD SEPARATOR
-10920..10939;N # Lo [26] LYDIAN LETTER A..LYDIAN LETTER C
-1093F;N # Po LYDIAN TRIANGULAR MARK
-10980..1099F;N # Lo [32] MEROITIC HIEROGLYPHIC LETTER A..MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2
-109A0..109B7;N # Lo [24] MEROITIC CURSIVE LETTER A..MEROITIC CURSIVE LETTER DA
-109BC..109BD;N # No [2] MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS..MEROITIC CURSIVE FRACTION ONE HALF
-109BE..109BF;N # Lo [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN
-109C0..109CF;N # No [16] MEROITIC CURSIVE NUMBER ONE..MEROITIC CURSIVE NUMBER SEVENTY
-109D2..109FF;N # No [46] MEROITIC CURSIVE NUMBER ONE HUNDRED..MEROITIC CURSIVE FRACTION TEN TWELFTHS
-10A00;N # Lo KHAROSHTHI LETTER A
-10A01..10A03;N # Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R
-10A05..10A06;N # Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O
-10A0C..10A0F;N # Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA
-10A10..10A13;N # Lo [4] KHAROSHTHI LETTER KA..KHAROSHTHI LETTER GHA
-10A15..10A17;N # Lo [3] KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA
-10A19..10A35;N # Lo [29] KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER VHA
-10A38..10A3A;N # Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW
-10A3F;N # Mn KHAROSHTHI VIRAMA
-10A40..10A48;N # No [9] KHAROSHTHI DIGIT ONE..KHAROSHTHI FRACTION ONE HALF
-10A50..10A58;N # Po [9] KHAROSHTHI PUNCTUATION DOT..KHAROSHTHI PUNCTUATION LINES
-10A60..10A7C;N # Lo [29] OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH
-10A7D..10A7E;N # No [2] OLD SOUTH ARABIAN NUMBER ONE..OLD SOUTH ARABIAN NUMBER FIFTY
-10A7F;N # Po OLD SOUTH ARABIAN NUMERIC INDICATOR
-10A80..10A9C;N # Lo [29] OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH
-10A9D..10A9F;N # No [3] OLD NORTH ARABIAN NUMBER ONE..OLD NORTH ARABIAN NUMBER TWENTY
-10AC0..10AC7;N # Lo [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW
-10AC8;N # So MANICHAEAN SIGN UD
-10AC9..10AE4;N # Lo [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW
-10AE5..10AE6;N # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW
-10AEB..10AEF;N # No [5] MANICHAEAN NUMBER ONE..MANICHAEAN NUMBER ONE HUNDRED
-10AF0..10AF6;N # Po [7] MANICHAEAN PUNCTUATION STAR..MANICHAEAN PUNCTUATION LINE FILLER
-10B00..10B35;N # Lo [54] AVESTAN LETTER A..AVESTAN LETTER HE
-10B39..10B3F;N # Po [7] AVESTAN ABBREVIATION MARK..LARGE ONE RING OVER TWO RINGS PUNCTUATION
-10B40..10B55;N # Lo [22] INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW
-10B58..10B5F;N # No [8] INSCRIPTIONAL PARTHIAN NUMBER ONE..INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND
-10B60..10B72;N # Lo [19] INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW
-10B78..10B7F;N # No [8] INSCRIPTIONAL PAHLAVI NUMBER ONE..INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND
-10B80..10B91;N # Lo [18] PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW
-10B99..10B9C;N # Po [4] PSALTER PAHLAVI SECTION MARK..PSALTER PAHLAVI FOUR DOTS WITH DOT
-10BA9..10BAF;N # No [7] PSALTER PAHLAVI NUMBER ONE..PSALTER PAHLAVI NUMBER ONE HUNDRED
-10C00..10C48;N # Lo [73] OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH
-10C80..10CB2;N # Lu [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US
-10CC0..10CF2;N # Ll [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US
-10CFA..10CFF;N # No [6] OLD HUNGARIAN NUMBER ONE..OLD HUNGARIAN NUMBER ONE THOUSAND
-10D00..10D23;N # Lo [36] HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA MARK NA KHONNA
-10D24..10D27;N # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
-10D30..10D39;N # Nd [10] HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE
-10E60..10E7E;N # No [31] RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS
-10E80..10EA9;N # Lo [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET
-10EAB..10EAC;N # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
-10EAD;N # Pd YEZIDI HYPHENATION MARK
-10EB0..10EB1;N # Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE
-10EFD..10EFF;N # Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA
-10F00..10F1C;N # Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL
-10F1D..10F26;N # No [10] OLD SOGDIAN NUMBER ONE..OLD SOGDIAN FRACTION ONE HALF
-10F27;N # Lo OLD SOGDIAN LIGATURE AYIN-DALETH
-10F30..10F45;N # Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN
-10F46..10F50;N # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
-10F51..10F54;N # No [4] SOGDIAN NUMBER ONE..SOGDIAN NUMBER ONE HUNDRED
-10F55..10F59;N # Po [5] SOGDIAN PUNCTUATION TWO VERTICAL BARS..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT
-10F70..10F81;N # Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH
-10F82..10F85;N # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW
-10F86..10F89;N # Po [4] OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS
-10FB0..10FC4;N # Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW
-10FC5..10FCB;N # No [7] CHORASMIAN NUMBER ONE..CHORASMIAN NUMBER ONE HUNDRED
-10FE0..10FF6;N # Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH
-11000;N # Mc BRAHMI SIGN CANDRABINDU
-11001;N # Mn BRAHMI SIGN ANUSVARA
-11002;N # Mc BRAHMI SIGN VISARGA
-11003..11037;N # Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA
-11038..11046;N # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA
-11047..1104D;N # Po [7] BRAHMI DANDA..BRAHMI PUNCTUATION LOTUS
-11052..11065;N # No [20] BRAHMI NUMBER ONE..BRAHMI NUMBER ONE THOUSAND
-11066..1106F;N # Nd [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE
-11070;N # Mn BRAHMI SIGN OLD TAMIL VIRAMA
-11071..11072;N # Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O
-11073..11074;N # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O
-11075;N # Lo BRAHMI LETTER OLD TAMIL LLA
-1107F;N # Mn BRAHMI NUMBER JOINER
-11080..11081;N # Mn [2] KAITHI SIGN CANDRABINDU..KAITHI SIGN ANUSVARA
-11082;N # Mc KAITHI SIGN VISARGA
-11083..110AF;N # Lo [45] KAITHI LETTER A..KAITHI LETTER HA
-110B0..110B2;N # Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II
-110B3..110B6;N # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI
-110B7..110B8;N # Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU
-110B9..110BA;N # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA
-110BB..110BC;N # Po [2] KAITHI ABBREVIATION SIGN..KAITHI ENUMERATION SIGN
-110BD;N # Cf KAITHI NUMBER SIGN
-110BE..110C1;N # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA
-110C2;N # Mn KAITHI VOWEL SIGN VOCALIC R
-110CD;N # Cf KAITHI NUMBER SIGN ABOVE
-110D0..110E8;N # Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE
-110F0..110F9;N # Nd [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE
-11100..11102;N # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA
-11103..11126;N # Lo [36] CHAKMA LETTER AA..CHAKMA LETTER HAA
-11127..1112B;N # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU
-1112C;N # Mc CHAKMA VOWEL SIGN E
-1112D..11134;N # Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA
-11136..1113F;N # Nd [10] CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE
-11140..11143;N # Po [4] CHAKMA SECTION MARK..CHAKMA QUESTION MARK
-11144;N # Lo CHAKMA LETTER LHAA
-11145..11146;N # Mc [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI
-11147;N # Lo CHAKMA LETTER VAA
-11150..11172;N # Lo [35] MAHAJANI LETTER A..MAHAJANI LETTER RRA
-11173;N # Mn MAHAJANI SIGN NUKTA
-11174..11175;N # Po [2] MAHAJANI ABBREVIATION SIGN..MAHAJANI SECTION MARK
-11176;N # Lo MAHAJANI LIGATURE SHRI
-11180..11181;N # Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA
-11182;N # Mc SHARADA SIGN VISARGA
-11183..111B2;N # Lo [48] SHARADA LETTER A..SHARADA LETTER HA
-111B3..111B5;N # Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II
-111B6..111BE;N # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O
-111BF..111C0;N # Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA
-111C1..111C4;N # Lo [4] SHARADA SIGN AVAGRAHA..SHARADA OM
-111C5..111C8;N # Po [4] SHARADA DANDA..SHARADA SEPARATOR
-111C9..111CC;N # Mn [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK
-111CD;N # Po SHARADA SUTRA MARK
-111CE;N # Mc SHARADA VOWEL SIGN PRISHTHAMATRA E
-111CF;N # Mn SHARADA SIGN INVERTED CANDRABINDU
-111D0..111D9;N # Nd [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE
-111DA;N # Lo SHARADA EKAM
-111DB;N # Po SHARADA SIGN SIDDHAM
-111DC;N # Lo SHARADA HEADSTROKE
-111DD..111DF;N # Po [3] SHARADA CONTINUATION SIGN..SHARADA SECTION MARK-2
-111E1..111F4;N # No [20] SINHALA ARCHAIC DIGIT ONE..SINHALA ARCHAIC NUMBER ONE THOUSAND
-11200..11211;N # Lo [18] KHOJKI LETTER A..KHOJKI LETTER JJA
-11213..1122B;N # Lo [25] KHOJKI LETTER NYA..KHOJKI LETTER LLA
-1122C..1122E;N # Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II
-1122F..11231;N # Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI
-11232..11233;N # Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU
-11234;N # Mn KHOJKI SIGN ANUSVARA
-11235;N # Mc KHOJKI SIGN VIRAMA
-11236..11237;N # Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA
-11238..1123D;N # Po [6] KHOJKI DANDA..KHOJKI ABBREVIATION SIGN
-1123E;N # Mn KHOJKI SIGN SUKUN
-1123F..11240;N # Lo [2] KHOJKI LETTER QA..KHOJKI LETTER SHORT I
-11241;N # Mn KHOJKI VOWEL SIGN VOCALIC R
-11280..11286;N # Lo [7] MULTANI LETTER A..MULTANI LETTER GA
-11288;N # Lo MULTANI LETTER GHA
-1128A..1128D;N # Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA
-1128F..1129D;N # Lo [15] MULTANI LETTER NYA..MULTANI LETTER BA
-1129F..112A8;N # Lo [10] MULTANI LETTER BHA..MULTANI LETTER RHA
-112A9;N # Po MULTANI SECTION MARK
-112B0..112DE;N # Lo [47] KHUDAWADI LETTER A..KHUDAWADI LETTER HA
-112DF;N # Mn KHUDAWADI SIGN ANUSVARA
-112E0..112E2;N # Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II
-112E3..112EA;N # Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA
-112F0..112F9;N # Nd [10] KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE
-11300..11301;N # Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU
-11302..11303;N # Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA
-11305..1130C;N # Lo [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L
-1130F..11310;N # Lo [2] GRANTHA LETTER EE..GRANTHA LETTER AI
-11313..11328;N # Lo [22] GRANTHA LETTER OO..GRANTHA LETTER NA
-1132A..11330;N # Lo [7] GRANTHA LETTER PA..GRANTHA LETTER RA
-11332..11333;N # Lo [2] GRANTHA LETTER LA..GRANTHA LETTER LLA
-11335..11339;N # Lo [5] GRANTHA LETTER VA..GRANTHA LETTER HA
-1133B..1133C;N # Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA
-1133D;N # Lo GRANTHA SIGN AVAGRAHA
-1133E..1133F;N # Mc [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I
-11340;N # Mn GRANTHA VOWEL SIGN II
-11341..11344;N # Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR
-11347..11348;N # Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI
-1134B..1134D;N # Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA
-11350;N # Lo GRANTHA OM
-11357;N # Mc GRANTHA AU LENGTH MARK
-1135D..11361;N # Lo [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL
-11362..11363;N # Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL
-11366..1136C;N # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX
-11370..11374;N # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA
-11400..11434;N # Lo [53] NEWA LETTER A..NEWA LETTER HA
-11435..11437;N # Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II
-11438..1143F;N # Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI
-11440..11441;N # Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU
-11442..11444;N # Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA
-11445;N # Mc NEWA SIGN VISARGA
-11446;N # Mn NEWA SIGN NUKTA
-11447..1144A;N # Lo [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI
-1144B..1144F;N # Po [5] NEWA DANDA..NEWA ABBREVIATION SIGN
-11450..11459;N # Nd [10] NEWA DIGIT ZERO..NEWA DIGIT NINE
-1145A..1145B;N # Po [2] NEWA DOUBLE COMMA..NEWA PLACEHOLDER MARK
-1145D;N # Po NEWA INSERTION SIGN
-1145E;N # Mn NEWA SANDHI MARK
-1145F..11461;N # Lo [3] NEWA LETTER VEDIC ANUSVARA..NEWA SIGN UPADHMANIYA
-11480..114AF;N # Lo [48] TIRHUTA ANJI..TIRHUTA LETTER HA
-114B0..114B2;N # Mc [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II
-114B3..114B8;N # Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL
-114B9;N # Mc TIRHUTA VOWEL SIGN E
-114BA;N # Mn TIRHUTA VOWEL SIGN SHORT E
-114BB..114BE;N # Mc [4] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN AU
-114BF..114C0;N # Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA
-114C1;N # Mc TIRHUTA SIGN VISARGA
-114C2..114C3;N # Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA
-114C4..114C5;N # Lo [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA GVANG
-114C6;N # Po TIRHUTA ABBREVIATION SIGN
-114C7;N # Lo TIRHUTA OM
-114D0..114D9;N # Nd [10] TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE
-11580..115AE;N # Lo [47] SIDDHAM LETTER A..SIDDHAM LETTER HA
-115AF..115B1;N # Mc [3] SIDDHAM VOWEL SIGN AA..SIDDHAM VOWEL SIGN II
-115B2..115B5;N # Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR
-115B8..115BB;N # Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU
-115BC..115BD;N # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA
-115BE;N # Mc SIDDHAM SIGN VISARGA
-115BF..115C0;N # Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA
-115C1..115D7;N # Po [23] SIDDHAM SIGN SIDDHAM..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
-115D8..115DB;N # Lo [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U
-115DC..115DD;N # Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU
-11600..1162F;N # Lo [48] MODI LETTER A..MODI LETTER LLA
-11630..11632;N # Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II
-11633..1163A;N # Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI
-1163B..1163C;N # Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU
-1163D;N # Mn MODI SIGN ANUSVARA
-1163E;N # Mc MODI SIGN VISARGA
-1163F..11640;N # Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA
-11641..11643;N # Po [3] MODI DANDA..MODI ABBREVIATION SIGN
-11644;N # Lo MODI SIGN HUVA
-11650..11659;N # Nd [10] MODI DIGIT ZERO..MODI DIGIT NINE
-11660..1166C;N # Po [13] MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT
-11680..116AA;N # Lo [43] TAKRI LETTER A..TAKRI LETTER RRA
-116AB;N # Mn TAKRI SIGN ANUSVARA
-116AC;N # Mc TAKRI SIGN VISARGA
-116AD;N # Mn TAKRI VOWEL SIGN AA
-116AE..116AF;N # Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II
-116B0..116B5;N # Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU
-116B6;N # Mc TAKRI SIGN VIRAMA
-116B7;N # Mn TAKRI SIGN NUKTA
-116B8;N # Lo TAKRI LETTER ARCHAIC KHA
-116B9;N # Po TAKRI ABBREVIATION SIGN
-116C0..116C9;N # Nd [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE
-11700..1171A;N # Lo [27] AHOM LETTER KA..AHOM LETTER ALTERNATE BA
-1171D..1171F;N # Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA
-11720..11721;N # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA
-11722..11725;N # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
-11726;N # Mc AHOM VOWEL SIGN E
-11727..1172B;N # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER
-11730..11739;N # Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE
-1173A..1173B;N # No [2] AHOM NUMBER TEN..AHOM NUMBER TWENTY
-1173C..1173E;N # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
-1173F;N # So AHOM SYMBOL VI
-11740..11746;N # Lo [7] AHOM LETTER CA..AHOM LETTER LLA
-11800..1182B;N # Lo [44] DOGRA LETTER A..DOGRA LETTER RRA
-1182C..1182E;N # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II
-1182F..11837;N # Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA
-11838;N # Mc DOGRA SIGN VISARGA
-11839..1183A;N # Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA
-1183B;N # Po DOGRA ABBREVIATION SIGN
-118A0..118DF;N # L& [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO
-118E0..118E9;N # Nd [10] WARANG CITI DIGIT ZERO..WARANG CITI DIGIT NINE
-118EA..118F2;N # No [9] WARANG CITI NUMBER TEN..WARANG CITI NUMBER NINETY
-118FF;N # Lo WARANG CITI OM
-11900..11906;N # Lo [7] DIVES AKURU LETTER A..DIVES AKURU LETTER E
-11909;N # Lo DIVES AKURU LETTER O
-1190C..11913;N # Lo [8] DIVES AKURU LETTER KA..DIVES AKURU LETTER JA
-11915..11916;N # Lo [2] DIVES AKURU LETTER NYA..DIVES AKURU LETTER TTA
-11918..1192F;N # Lo [24] DIVES AKURU LETTER DDA..DIVES AKURU LETTER ZA
-11930..11935;N # Mc [6] DIVES AKURU VOWEL SIGN AA..DIVES AKURU VOWEL SIGN E
-11937..11938;N # Mc [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O
-1193B..1193C;N # Mn [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU
-1193D;N # Mc DIVES AKURU SIGN HALANTA
-1193E;N # Mn DIVES AKURU VIRAMA
-1193F;N # Lo DIVES AKURU PREFIXED NASAL SIGN
-11940;N # Mc DIVES AKURU MEDIAL YA
-11941;N # Lo DIVES AKURU INITIAL RA
-11942;N # Mc DIVES AKURU MEDIAL RA
-11943;N # Mn DIVES AKURU SIGN NUKTA
-11944..11946;N # Po [3] DIVES AKURU DOUBLE DANDA..DIVES AKURU END OF TEXT MARK
-11950..11959;N # Nd [10] DIVES AKURU DIGIT ZERO..DIVES AKURU DIGIT NINE
-119A0..119A7;N # Lo [8] NANDINAGARI LETTER A..NANDINAGARI LETTER VOCALIC RR
-119AA..119D0;N # Lo [39] NANDINAGARI LETTER E..NANDINAGARI LETTER RRA
-119D1..119D3;N # Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II
-119D4..119D7;N # Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR
-119DA..119DB;N # Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI
-119DC..119DF;N # Mc [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA
-119E0;N # Mn NANDINAGARI SIGN VIRAMA
-119E1;N # Lo NANDINAGARI SIGN AVAGRAHA
-119E2;N # Po NANDINAGARI SIGN SIDDHAM
-119E3;N # Lo NANDINAGARI HEADSTROKE
-119E4;N # Mc NANDINAGARI VOWEL SIGN PRISHTHAMATRA E
-11A00;N # Lo ZANABAZAR SQUARE LETTER A
-11A01..11A0A;N # Mn [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK
-11A0B..11A32;N # Lo [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA
-11A33..11A38;N # Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA
-11A39;N # Mc ZANABAZAR SQUARE SIGN VISARGA
-11A3A;N # Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA
-11A3B..11A3E;N # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA
-11A3F..11A46;N # Po [8] ZANABAZAR SQUARE INITIAL HEAD MARK..ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK
-11A47;N # Mn ZANABAZAR SQUARE SUBJOINER
-11A50;N # Lo SOYOMBO LETTER A
-11A51..11A56;N # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE
-11A57..11A58;N # Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU
-11A59..11A5B;N # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK
-11A5C..11A89;N # Lo [46] SOYOMBO LETTER KA..SOYOMBO CLUSTER-INITIAL LETTER SA
-11A8A..11A96;N # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA
-11A97;N # Mc SOYOMBO SIGN VISARGA
-11A98..11A99;N # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER
-11A9A..11A9C;N # Po [3] SOYOMBO MARK TSHEG..SOYOMBO MARK DOUBLE SHAD
-11A9D;N # Lo SOYOMBO MARK PLUTA
-11A9E..11AA2;N # Po [5] SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO TERMINAL MARK-2
-11AB0..11ABF;N # Lo [16] CANADIAN SYLLABICS NATTILIK HI..CANADIAN SYLLABICS SPA
-11AC0..11AF8;N # Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL
-11B00..11B09;N # Po [10] DEVANAGARI HEAD MARK..DEVANAGARI SIGN MINDU
-11C00..11C08;N # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L
-11C0A..11C2E;N # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA
-11C2F;N # Mc BHAIKSUKI VOWEL SIGN AA
-11C30..11C36;N # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L
-11C38..11C3D;N # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA
-11C3E;N # Mc BHAIKSUKI SIGN VISARGA
-11C3F;N # Mn BHAIKSUKI SIGN VIRAMA
-11C40;N # Lo BHAIKSUKI SIGN AVAGRAHA
-11C41..11C45;N # Po [5] BHAIKSUKI DANDA..BHAIKSUKI GAP FILLER-2
-11C50..11C59;N # Nd [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE
-11C5A..11C6C;N # No [19] BHAIKSUKI NUMBER ONE..BHAIKSUKI HUNDREDS UNIT MARK
-11C70..11C71;N # Po [2] MARCHEN HEAD MARK..MARCHEN MARK SHAD
-11C72..11C8F;N # Lo [30] MARCHEN LETTER KA..MARCHEN LETTER A
-11C92..11CA7;N # Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA
-11CA9;N # Mc MARCHEN SUBJOINED LETTER YA
-11CAA..11CB0;N # Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA
-11CB1;N # Mc MARCHEN VOWEL SIGN I
-11CB2..11CB3;N # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E
-11CB4;N # Mc MARCHEN VOWEL SIGN O
-11CB5..11CB6;N # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU
-11D00..11D06;N # Lo [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E
-11D08..11D09;N # Lo [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O
-11D0B..11D30;N # Lo [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA
-11D31..11D36;N # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R
-11D3A;N # Mn MASARAM GONDI VOWEL SIGN E
-11D3C..11D3D;N # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O
-11D3F..11D45;N # Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA
-11D46;N # Lo MASARAM GONDI REPHA
-11D47;N # Mn MASARAM GONDI RA-KARA
-11D50..11D59;N # Nd [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE
-11D60..11D65;N # Lo [6] GUNJALA GONDI LETTER A..GUNJALA GONDI LETTER UU
-11D67..11D68;N # Lo [2] GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI
-11D6A..11D89;N # Lo [32] GUNJALA GONDI LETTER OO..GUNJALA GONDI LETTER SA
-11D8A..11D8E;N # Mc [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU
-11D90..11D91;N # Mn [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI
-11D93..11D94;N # Mc [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU
-11D95;N # Mn GUNJALA GONDI SIGN ANUSVARA
-11D96;N # Mc GUNJALA GONDI SIGN VISARGA
-11D97;N # Mn GUNJALA GONDI VIRAMA
-11D98;N # Lo GUNJALA GONDI OM
-11DA0..11DA9;N # Nd [10] GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE
-11EE0..11EF2;N # Lo [19] MAKASAR LETTER KA..MAKASAR ANGKA
-11EF3..11EF4;N # Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U
-11EF5..11EF6;N # Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O
-11EF7..11EF8;N # Po [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION
-11F00..11F01;N # Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA
-11F02;N # Lo KAWI SIGN REPHA
-11F03;N # Mc KAWI SIGN VISARGA
-11F04..11F10;N # Lo [13] KAWI LETTER A..KAWI LETTER O
-11F12..11F33;N # Lo [34] KAWI LETTER KA..KAWI LETTER JNYA
-11F34..11F35;N # Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA
-11F36..11F3A;N # Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R
-11F3E..11F3F;N # Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI
-11F40;N # Mn KAWI VOWEL SIGN EU
-11F41;N # Mc KAWI SIGN KILLER
-11F42;N # Mn KAWI CONJOINER
-11F43..11F4F;N # Po [13] KAWI DANDA..KAWI PUNCTUATION CLOSING SPIRAL
-11F50..11F59;N # Nd [10] KAWI DIGIT ZERO..KAWI DIGIT NINE
-11FB0;N # Lo LISU LETTER YHA
-11FC0..11FD4;N # No [21] TAMIL FRACTION ONE THREE-HUNDRED-AND-TWENTIETH..TAMIL FRACTION DOWNSCALING FACTOR KIIZH
-11FD5..11FDC;N # So [8] TAMIL SIGN NEL..TAMIL SIGN MUKKURUNI
-11FDD..11FE0;N # Sc [4] TAMIL SIGN KAACU..TAMIL SIGN VARAAKAN
-11FE1..11FF1;N # So [17] TAMIL SIGN PAARAM..TAMIL SIGN VAKAIYARAA
-11FFF;N # Po TAMIL PUNCTUATION END OF TEXT
-12000..12399;N # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U
-12400..1246E;N # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM
-12470..12474;N # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON
-12480..12543;N # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU
-12F90..12FF0;N # Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114
-12FF1..12FF2;N # Po [2] CYPRO-MINOAN SIGN CM301..CYPRO-MINOAN SIGN CM302
-13000..1342F;N # Lo [1072] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH V011D
-13430..1343F;N # Cf [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE
-13440;N # Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY
-13441..13446;N # Lo [6] EGYPTIAN HIEROGLYPH FULL BLANK..EGYPTIAN HIEROGLYPH WIDE LOST SIGN
-13447..13455;N # Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED
-14400..14646;N # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530
-16800..16A38;N # Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ
-16A40..16A5E;N # Lo [31] MRO LETTER TA..MRO LETTER TEK
-16A60..16A69;N # Nd [10] MRO DIGIT ZERO..MRO DIGIT NINE
-16A6E..16A6F;N # Po [2] MRO DANDA..MRO DOUBLE DANDA
-16A70..16ABE;N # Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA
-16AC0..16AC9;N # Nd [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE
-16AD0..16AED;N # Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I
-16AF0..16AF4;N # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
-16AF5;N # Po BASSA VAH FULL STOP
-16B00..16B2F;N # Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU
-16B30..16B36;N # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
-16B37..16B3B;N # Po [5] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS FEEM
-16B3C..16B3F;N # So [4] PAHAWH HMONG SIGN XYEEM NTXIV..PAHAWH HMONG SIGN XYEEM FAIB
-16B40..16B43;N # Lm [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM
-16B44;N # Po PAHAWH HMONG SIGN XAUS
-16B45;N # So PAHAWH HMONG SIGN CIM TSOV ROG
-16B50..16B59;N # Nd [10] PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE
-16B5B..16B61;N # No [7] PAHAWH HMONG NUMBER TENS..PAHAWH HMONG NUMBER TRILLIONS
-16B63..16B77;N # Lo [21] PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS
-16B7D..16B8F;N # Lo [19] PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ
-16E40..16E7F;N # L& [64] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN SMALL LETTER Y
-16E80..16E96;N # No [23] MEDEFAIDRIN DIGIT ZERO..MEDEFAIDRIN DIGIT THREE ALTERNATE FORM
-16E97..16E9A;N # Po [4] MEDEFAIDRIN COMMA..MEDEFAIDRIN EXCLAMATION OH
-16F00..16F4A;N # Lo [75] MIAO LETTER PA..MIAO LETTER RTE
-16F4F;N # Mn MIAO SIGN CONSONANT MODIFIER BAR
-16F50;N # Lo MIAO LETTER NASALIZATION
-16F51..16F87;N # Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
-16F8F..16F92;N # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
-16F93..16F9F;N # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8
-16FE0..16FE1;W # Lm [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK
-16FE2;W # Po OLD CHINESE HOOK MARK
-16FE3;W # Lm OLD CHINESE ITERATION MARK
-16FE4;W # Mn KHITAN SMALL SCRIPT FILLER
-16FF0..16FF1;W # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY
-17000..187F7;W # Lo [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7
-18800..18AFF;W # Lo [768] TANGUT COMPONENT-001..TANGUT COMPONENT-768
-18B00..18CD5;W # Lo [470] KHITAN SMALL SCRIPT CHARACTER-18B00..KHITAN SMALL SCRIPT CHARACTER-18CD5
-18D00..18D08;W # Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08
-1AFF0..1AFF3;W # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5
-1AFF5..1AFFB;W # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5
-1AFFD..1AFFE;W # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8
-1B000..1B0FF;W # Lo [256] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER RE-2
-1B100..1B122;W # Lo [35] HENTAIGANA LETTER RE-3..KATAKANA LETTER ARCHAIC WU
-1B132;W # Lo HIRAGANA LETTER SMALL KO
-1B150..1B152;W # Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO
-1B155;W # Lo KATAKANA LETTER SMALL KO
-1B164..1B167;W # Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N
-1B170..1B2FB;W # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB
-1BC00..1BC6A;N # Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M
-1BC70..1BC7C;N # Lo [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK
-1BC80..1BC88;N # Lo [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL
-1BC90..1BC99;N # Lo [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW
-1BC9C;N # So DUPLOYAN SIGN O WITH CROSS
-1BC9D..1BC9E;N # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
-1BC9F;N # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
-1BCA0..1BCA3;N # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
-1CF00..1CF2D;N # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT
-1CF30..1CF46;N # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG
-1CF50..1CFC3;N # So [116] ZNAMENNY NEUME KRYUK..ZNAMENNY NEUME PAUK
-1D000..1D0F5;N # So [246] BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MUSICAL SYMBOL GORGON NEO KATO
-1D100..1D126;N # So [39] MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBOL DRUM CLEF-2
-1D129..1D164;N # So [60] MUSICAL SYMBOL MULTIPLE MEASURE REST..MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE
-1D165..1D166;N # Mc [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM
-1D167..1D169;N # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3
-1D16A..1D16C;N # So [3] MUSICAL SYMBOL FINGERED TREMOLO-1..MUSICAL SYMBOL FINGERED TREMOLO-3
-1D16D..1D172;N # Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5
-1D173..1D17A;N # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
-1D17B..1D182;N # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE
-1D183..1D184;N # So [2] MUSICAL SYMBOL ARPEGGIATO UP..MUSICAL SYMBOL ARPEGGIATO DOWN
-1D185..1D18B;N # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE
-1D18C..1D1A9;N # So [30] MUSICAL SYMBOL RINFORZANDO..MUSICAL SYMBOL DEGREE SLASH
-1D1AA..1D1AD;N # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
-1D1AE..1D1EA;N # So [61] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL KORON
-1D200..1D241;N # So [66] GREEK VOCAL NOTATION SYMBOL-1..GREEK INSTRUMENTAL NOTATION SYMBOL-54
-1D242..1D244;N # Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME
-1D245;N # So GREEK MUSICAL LEIMMA
-1D2C0..1D2D3;N # No [20] KAKTOVIK NUMERAL ZERO..KAKTOVIK NUMERAL NINETEEN
-1D2E0..1D2F3;N # No [20] MAYAN NUMERAL ZERO..MAYAN NUMERAL NINETEEN
-1D300..1D356;N # So [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING
-1D360..1D378;N # No [25] COUNTING ROD UNIT DIGIT ONE..TALLY MARK FIVE
-1D400..1D454;N # L& [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G
-1D456..1D49C;N # L& [71] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A
-1D49E..1D49F;N # Lu [2] MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D
-1D4A2;N # Lu MATHEMATICAL SCRIPT CAPITAL G
-1D4A5..1D4A6;N # Lu [2] MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K
-1D4A9..1D4AC;N # Lu [4] MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q
-1D4AE..1D4B9;N # L& [12] MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D
-1D4BB;N # Ll MATHEMATICAL SCRIPT SMALL F
-1D4BD..1D4C3;N # Ll [7] MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N
-1D4C5..1D505;N # L& [65] MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B
-1D507..1D50A;N # Lu [4] MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G
-1D50D..1D514;N # Lu [8] MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q
-1D516..1D51C;N # Lu [7] MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y
-1D51E..1D539;N # L& [28] MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B
-1D53B..1D53E;N # Lu [4] MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G
-1D540..1D544;N # Lu [5] MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M
-1D546;N # Lu MATHEMATICAL DOUBLE-STRUCK CAPITAL O
-1D54A..1D550;N # Lu [7] MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y
-1D552..1D6A5;N # L& [340] MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J
-1D6A8..1D6C0;N # Lu [25] MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD CAPITAL OMEGA
-1D6C1;N # Sm MATHEMATICAL BOLD NABLA
-1D6C2..1D6DA;N # Ll [25] MATHEMATICAL BOLD SMALL ALPHA..MATHEMATICAL BOLD SMALL OMEGA
-1D6DB;N # Sm MATHEMATICAL BOLD PARTIAL DIFFERENTIAL
-1D6DC..1D6FA;N # L& [31] MATHEMATICAL BOLD EPSILON SYMBOL..MATHEMATICAL ITALIC CAPITAL OMEGA
-1D6FB;N # Sm MATHEMATICAL ITALIC NABLA
-1D6FC..1D714;N # Ll [25] MATHEMATICAL ITALIC SMALL ALPHA..MATHEMATICAL ITALIC SMALL OMEGA
-1D715;N # Sm MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL
-1D716..1D734;N # L& [31] MATHEMATICAL ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD ITALIC CAPITAL OMEGA
-1D735;N # Sm MATHEMATICAL BOLD ITALIC NABLA
-1D736..1D74E;N # Ll [25] MATHEMATICAL BOLD ITALIC SMALL ALPHA..MATHEMATICAL BOLD ITALIC SMALL OMEGA
-1D74F;N # Sm MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL
-1D750..1D76E;N # L& [31] MATHEMATICAL BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA
-1D76F;N # Sm MATHEMATICAL SANS-SERIF BOLD NABLA
-1D770..1D788;N # Ll [25] MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA
-1D789;N # Sm MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL
-1D78A..1D7A8;N # L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA
-1D7A9;N # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA
-1D7AA..1D7C2;N # Ll [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA
-1D7C3;N # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL
-1D7C4..1D7CB;N # L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA
-1D7CE..1D7FF;N # Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE
-1D800..1D9FF;N # So [512] SIGNWRITING HAND-FIST INDEX..SIGNWRITING HEAD
-1DA00..1DA36;N # Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN
-1DA37..1DA3A;N # So [4] SIGNWRITING AIR BLOW SMALL ROTATIONS..SIGNWRITING BREATH EXHALE
-1DA3B..1DA6C;N # Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT
-1DA6D..1DA74;N # So [8] SIGNWRITING SHOULDER HIP SPINE..SIGNWRITING TORSO-FLOORPLANE TWISTING
-1DA75;N # Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS
-1DA76..1DA83;N # So [14] SIGNWRITING LIMB COMBINATION..SIGNWRITING LOCATION DEPTH
-1DA84;N # Mn SIGNWRITING LOCATION HEAD NECK
-1DA85..1DA86;N # So [2] SIGNWRITING LOCATION TORSO..SIGNWRITING LOCATION LIMBS DIGITS
-1DA87..1DA8B;N # Po [5] SIGNWRITING COMMA..SIGNWRITING PARENTHESIS
-1DA9B..1DA9F;N # Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6
-1DAA1..1DAAF;N # Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16
-1DF00..1DF09;N # Ll [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK
-1DF0A;N # Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK
-1DF0B..1DF1E;N # Ll [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL
-1DF25..1DF2A;N # Ll [6] LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK
-1E000..1E006;N # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE
-1E008..1E018;N # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU
-1E01B..1E021;N # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI
-1E023..1E024;N # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS
-1E026..1E02A;N # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA
-1E030..1E06D;N # Lm [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE
-1E08F;N # Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
-1E100..1E12C;N # Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W
-1E130..1E136;N # Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D
-1E137..1E13D;N # Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER
-1E140..1E149;N # Nd [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE
-1E14E;N # Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ
-1E14F;N # So NYIAKENG PUACHUE HMONG CIRCLED CA
-1E290..1E2AD;N # Lo [30] TOTO LETTER PA..TOTO LETTER A
-1E2AE;N # Mn TOTO SIGN RISING TONE
-1E2C0..1E2EB;N # Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH
-1E2EC..1E2EF;N # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI
-1E2F0..1E2F9;N # Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE
-1E2FF;N # Sc WANCHO NGUN SIGN
-1E4D0..1E4EA;N # Lo [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL
-1E4EB;N # Lm NAG MUNDARI SIGN OJOD
-1E4EC..1E4EF;N # Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH
-1E4F0..1E4F9;N # Nd [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE
-1E7E0..1E7E6;N # Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO
-1E7E8..1E7EB;N # Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE
-1E7ED..1E7EE;N # Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE
-1E7F0..1E7FE;N # Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE
-1E800..1E8C4;N # Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON
-1E8C7..1E8CF;N # No [9] MENDE KIKAKUI DIGIT ONE..MENDE KIKAKUI DIGIT NINE
-1E8D0..1E8D6;N # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
-1E900..1E943;N # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA
-1E944..1E94A;N # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
-1E94B;N # Lm ADLAM NASALIZATION MARK
-1E950..1E959;N # Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE
-1E95E..1E95F;N # Po [2] ADLAM INITIAL EXCLAMATION MARK..ADLAM INITIAL QUESTION MARK
-1EC71..1ECAB;N # No [59] INDIC SIYAQ NUMBER ONE..INDIC SIYAQ NUMBER PREFIXED NINE
-1ECAC;N # So INDIC SIYAQ PLACEHOLDER
-1ECAD..1ECAF;N # No [3] INDIC SIYAQ FRACTION ONE QUARTER..INDIC SIYAQ FRACTION THREE QUARTERS
-1ECB0;N # Sc INDIC SIYAQ RUPEE MARK
-1ECB1..1ECB4;N # No [4] INDIC SIYAQ NUMBER ALTERNATE ONE..INDIC SIYAQ ALTERNATE LAKH MARK
-1ED01..1ED2D;N # No [45] OTTOMAN SIYAQ NUMBER ONE..OTTOMAN SIYAQ NUMBER NINETY THOUSAND
-1ED2E;N # So OTTOMAN SIYAQ MARRATAN
-1ED2F..1ED3D;N # No [15] OTTOMAN SIYAQ ALTERNATE NUMBER TWO..OTTOMAN SIYAQ FRACTION ONE SIXTH
-1EE00..1EE03;N # Lo [4] ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL
-1EE05..1EE1F;N # Lo [27] ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF
-1EE21..1EE22;N # Lo [2] ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM
-1EE24;N # Lo ARABIC MATHEMATICAL INITIAL HEH
-1EE27;N # Lo ARABIC MATHEMATICAL INITIAL HAH
-1EE29..1EE32;N # Lo [10] ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF
-1EE34..1EE37;N # Lo [4] ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH
-1EE39;N # Lo ARABIC MATHEMATICAL INITIAL DAD
-1EE3B;N # Lo ARABIC MATHEMATICAL INITIAL GHAIN
-1EE42;N # Lo ARABIC MATHEMATICAL TAILED JEEM
-1EE47;N # Lo ARABIC MATHEMATICAL TAILED HAH
-1EE49;N # Lo ARABIC MATHEMATICAL TAILED YEH
-1EE4B;N # Lo ARABIC MATHEMATICAL TAILED LAM
-1EE4D..1EE4F;N # Lo [3] ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN
-1EE51..1EE52;N # Lo [2] ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF
-1EE54;N # Lo ARABIC MATHEMATICAL TAILED SHEEN
-1EE57;N # Lo ARABIC MATHEMATICAL TAILED KHAH
-1EE59;N # Lo ARABIC MATHEMATICAL TAILED DAD
-1EE5B;N # Lo ARABIC MATHEMATICAL TAILED GHAIN
-1EE5D;N # Lo ARABIC MATHEMATICAL TAILED DOTLESS NOON
-1EE5F;N # Lo ARABIC MATHEMATICAL TAILED DOTLESS QAF
-1EE61..1EE62;N # Lo [2] ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM
-1EE64;N # Lo ARABIC MATHEMATICAL STRETCHED HEH
-1EE67..1EE6A;N # Lo [4] ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF
-1EE6C..1EE72;N # Lo [7] ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF
-1EE74..1EE77;N # Lo [4] ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH
-1EE79..1EE7C;N # Lo [4] ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH
-1EE7E;N # Lo ARABIC MATHEMATICAL STRETCHED DOTLESS FEH
-1EE80..1EE89;N # Lo [10] ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH
-1EE8B..1EE9B;N # Lo [17] ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN
-1EEA1..1EEA3;N # Lo [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL
-1EEA5..1EEA9;N # Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH
-1EEAB..1EEBB;N # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN
-1EEF0..1EEF1;N # Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL
-1F000..1F003;N # So [4] MAHJONG TILE EAST WIND..MAHJONG TILE NORTH WIND
-1F004;W # So MAHJONG TILE RED DRAGON
-1F005..1F02B;N # So [39] MAHJONG TILE GREEN DRAGON..MAHJONG TILE BACK
-1F030..1F093;N # So [100] DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06
-1F0A0..1F0AE;N # So [15] PLAYING CARD BACK..PLAYING CARD KING OF SPADES
-1F0B1..1F0BF;N # So [15] PLAYING CARD ACE OF HEARTS..PLAYING CARD RED JOKER
-1F0C1..1F0CE;N # So [14] PLAYING CARD ACE OF DIAMONDS..PLAYING CARD KING OF DIAMONDS
-1F0CF;W # So PLAYING CARD BLACK JOKER
-1F0D1..1F0F5;N # So [37] PLAYING CARD ACE OF CLUBS..PLAYING CARD TRUMP-21
-1F100..1F10A;A # No [11] DIGIT ZERO FULL STOP..DIGIT NINE COMMA
-1F10B..1F10C;N # No [2] DINGBAT CIRCLED SANS-SERIF DIGIT ZERO..DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO
-1F10D..1F10F;N # So [3] CIRCLED ZERO WITH SLASH..CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH
-1F110..1F12D;A # So [30] PARENTHESIZED LATIN CAPITAL LETTER A..CIRCLED CD
-1F12E..1F12F;N # So [2] CIRCLED WZ..COPYLEFT SYMBOL
-1F130..1F169;A # So [58] SQUARED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z
-1F16A..1F16F;N # So [6] RAISED MC SIGN..CIRCLED HUMAN FIGURE
-1F170..1F18D;A # So [30] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED SA
-1F18E;W # So NEGATIVE SQUARED AB
-1F18F..1F190;A # So [2] NEGATIVE SQUARED WC..SQUARE DJ
-1F191..1F19A;W # So [10] SQUARED CL..SQUARED VS
-1F19B..1F1AC;A # So [18] SQUARED THREE D..SQUARED VOD
-1F1AD;N # So MASK WORK SYMBOL
-1F1E6..1F1FF;N # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z
-1F200..1F202;W # So [3] SQUARE HIRAGANA HOKA..SQUARED KATAKANA SA
-1F210..1F23B;W # So [44] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-914D
-1F240..1F248;W # So [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
-1F250..1F251;W # So [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT
-1F260..1F265;W # So [6] ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI
-1F300..1F320;W # So [33] CYCLONE..SHOOTING STAR
-1F321..1F32C;N # So [12] THERMOMETER..WIND BLOWING FACE
-1F32D..1F335;W # So [9] HOT DOG..CACTUS
-1F336;N # So HOT PEPPER
-1F337..1F37C;W # So [70] TULIP..BABY BOTTLE
-1F37D;N # So FORK AND KNIFE WITH PLATE
-1F37E..1F393;W # So [22] BOTTLE WITH POPPING CORK..GRADUATION CAP
-1F394..1F39F;N # So [12] HEART WITH TIP ON THE LEFT..ADMISSION TICKETS
-1F3A0..1F3CA;W # So [43] CAROUSEL HORSE..SWIMMER
-1F3CB..1F3CE;N # So [4] WEIGHT LIFTER..RACING CAR
-1F3CF..1F3D3;W # So [5] CRICKET BAT AND BALL..TABLE TENNIS PADDLE AND BALL
-1F3D4..1F3DF;N # So [12] SNOW CAPPED MOUNTAIN..STADIUM
-1F3E0..1F3F0;W # So [17] HOUSE BUILDING..EUROPEAN CASTLE
-1F3F1..1F3F3;N # So [3] WHITE PENNANT..WAVING WHITE FLAG
-1F3F4;W # So WAVING BLACK FLAG
-1F3F5..1F3F7;N # So [3] ROSETTE..LABEL
-1F3F8..1F3FA;W # So [3] BADMINTON RACQUET AND SHUTTLECOCK..AMPHORA
-1F3FB..1F3FF;W # Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6
-1F400..1F43E;W # So [63] RAT..PAW PRINTS
-1F43F;N # So CHIPMUNK
-1F440;W # So EYES
-1F441;N # So EYE
-1F442..1F4FC;W # So [187] EAR..VIDEOCASSETTE
-1F4FD..1F4FE;N # So [2] FILM PROJECTOR..PORTABLE STEREO
-1F4FF..1F53D;W # So [63] PRAYER BEADS..DOWN-POINTING SMALL RED TRIANGLE
-1F53E..1F54A;N # So [13] LOWER RIGHT SHADOWED WHITE CIRCLE..DOVE OF PEACE
-1F54B..1F54E;W # So [4] KAABA..MENORAH WITH NINE BRANCHES
-1F54F;N # So BOWL OF HYGIEIA
-1F550..1F567;W # So [24] CLOCK FACE ONE OCLOCK..CLOCK FACE TWELVE-THIRTY
-1F568..1F579;N # So [18] RIGHT SPEAKER..JOYSTICK
-1F57A;W # So MAN DANCING
-1F57B..1F594;N # So [26] LEFT HAND TELEPHONE RECEIVER..REVERSED VICTORY HAND
-1F595..1F596;W # So [2] REVERSED HAND WITH MIDDLE FINGER EXTENDED..RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS
-1F597..1F5A3;N # So [13] WHITE DOWN POINTING LEFT HAND INDEX..BLACK DOWN POINTING BACKHAND INDEX
-1F5A4;W # So BLACK HEART
-1F5A5..1F5FA;N # So [86] DESKTOP COMPUTER..WORLD MAP
-1F5FB..1F5FF;W # So [5] MOUNT FUJI..MOYAI
-1F600..1F64F;W # So [80] GRINNING FACE..PERSON WITH FOLDED HANDS
-1F650..1F67F;N # So [48] NORTH WEST POINTING LEAF..REVERSE CHECKER BOARD
-1F680..1F6C5;W # So [70] ROCKET..LEFT LUGGAGE
-1F6C6..1F6CB;N # So [6] TRIANGLE WITH ROUNDED CORNERS..COUCH AND LAMP
-1F6CC;W # So SLEEPING ACCOMMODATION
-1F6CD..1F6CF;N # So [3] SHOPPING BAGS..BED
-1F6D0..1F6D2;W # So [3] PLACE OF WORSHIP..SHOPPING TROLLEY
-1F6D3..1F6D4;N # So [2] STUPA..PAGODA
-1F6D5..1F6D7;W # So [3] HINDU TEMPLE..ELEVATOR
-1F6DC..1F6DF;W # So [4] WIRELESS..RING BUOY
-1F6E0..1F6EA;N # So [11] HAMMER AND WRENCH..NORTHEAST-POINTING AIRPLANE
-1F6EB..1F6EC;W # So [2] AIRPLANE DEPARTURE..AIRPLANE ARRIVING
-1F6F0..1F6F3;N # So [4] SATELLITE..PASSENGER SHIP
-1F6F4..1F6FC;W # So [9] SCOOTER..ROLLER SKATE
-1F700..1F776;N # So [119] ALCHEMICAL SYMBOL FOR QUINTESSENCE..LUNAR ECLIPSE
-1F77B..1F77F;N # So [5] HAUMEA..ORCUS
-1F780..1F7D9;N # So [90] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..NINE POINTED WHITE STAR
-1F7E0..1F7EB;W # So [12] LARGE ORANGE CIRCLE..LARGE BROWN SQUARE
-1F7F0;W # So HEAVY EQUALS SIGN
-1F800..1F80B;N # So [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD
-1F810..1F847;N # So [56] LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD..DOWNWARDS HEAVY ARROW
-1F850..1F859;N # So [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW
-1F860..1F887;N # So [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW
-1F890..1F8AD;N # So [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS
-1F8B0..1F8B1;N # So [2] ARROW POINTING UPWARDS THEN NORTH WEST..ARROW POINTING RIGHTWARDS THEN CURVING SOUTH WEST
-1F900..1F90B;N # So [12] CIRCLED CROSS FORMEE WITH FOUR DOTS..DOWNWARD FACING NOTCHED HOOK WITH DOT
-1F90C..1F93A;W # So [47] PINCHED FINGERS..FENCER
-1F93B;N # So MODERN PENTATHLON
-1F93C..1F945;W # So [10] WRESTLERS..GOAL NET
-1F946;N # So RIFLE
-1F947..1F9FF;W # So [185] FIRST PLACE MEDAL..NAZAR AMULET
-1FA00..1FA53;N # So [84] NEUTRAL CHESS KING..BLACK CHESS KNIGHT-BISHOP
-1FA60..1FA6D;N # So [14] XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER
-1FA70..1FA7C;W # So [13] BALLET SHOES..CRUTCH
-1FA80..1FA88;W # So [9] YO-YO..FLUTE
-1FA90..1FABD;W # So [46] RINGED PLANET..WING
-1FABF..1FAC5;W # So [7] GOOSE..PERSON WITH CROWN
-1FACE..1FADB;W # So [14] MOOSE..PEA POD
-1FAE0..1FAE8;W # So [9] MELTING FACE..SHAKING FACE
-1FAF0..1FAF8;W # So [9] HAND WITH INDEX FINGER AND THUMB CROSSED..RIGHTWARDS PUSHING HAND
-1FB00..1FB92;N # So [147] BLOCK SEXTANT-1..UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK
-1FB94..1FBCA;N # So [55] LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK..WHITE UP-POINTING CHEVRON
-1FBF0..1FBF9;N # Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE
-20000..2A6DF;W # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF
-2A6E0..2A6FF;W # Cn [32] <reserved-2A6E0>..<reserved-2A6FF>
-2A700..2B739;W # Lo [4154] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B739
-2B73A..2B73F;W # Cn [6] <reserved-2B73A>..<reserved-2B73F>
-2B740..2B81D;W # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
-2B81E..2B81F;W # Cn [2] <reserved-2B81E>..<reserved-2B81F>
-2B820..2CEA1;W # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
-2CEA2..2CEAF;W # Cn [14] <reserved-2CEA2>..<reserved-2CEAF>
-2CEB0..2EBE0;W # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
-2EBE1..2F7FF;W # Cn [3103] <reserved-2EBE1>..<reserved-2F7FF>
-2F800..2FA1D;W # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
-2FA1E..2FA1F;W # Cn [2] <reserved-2FA1E>..<reserved-2FA1F>
-2FA20..2FFFD;W # Cn [1502] <reserved-2FA20>..<reserved-2FFFD>
-30000..3134A;W # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
-3134B..3134F;W # Cn [5] <reserved-3134B>..<reserved-3134F>
-31350..323AF;W # Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF
-323B0..3FFFD;W # Cn [56398] <reserved-323B0>..<reserved-3FFFD>
-E0001;N # Cf LANGUAGE TAG
-E0020..E007F;N # Cf [96] TAG SPACE..CANCEL TAG
-E0100..E01EF;A # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
-F0000..FFFFD;A # Co [65534] <private-use-F0000>..<private-use-FFFFD>
-100000..10FFFD;A # Co [65534] <private-use-100000>..<private-use-10FFFD>
+0000..001F ; N # Cc [32] <control-0000>..<control-001F>
+0020 ; Na # Zs SPACE
+0021..0023 ; Na # Po [3] EXCLAMATION MARK..NUMBER SIGN
+0024 ; Na # Sc DOLLAR SIGN
+0025..0027 ; Na # Po [3] PERCENT SIGN..APOSTROPHE
+0028 ; Na # Ps LEFT PARENTHESIS
+0029 ; Na # Pe RIGHT PARENTHESIS
+002A ; Na # Po ASTERISK
+002B ; Na # Sm PLUS SIGN
+002C ; Na # Po COMMA
+002D ; Na # Pd HYPHEN-MINUS
+002E..002F ; Na # Po [2] FULL STOP..SOLIDUS
+0030..0039 ; Na # Nd [10] DIGIT ZERO..DIGIT NINE
+003A..003B ; Na # Po [2] COLON..SEMICOLON
+003C..003E ; Na # Sm [3] LESS-THAN SIGN..GREATER-THAN SIGN
+003F..0040 ; Na # Po [2] QUESTION MARK..COMMERCIAL AT
+0041..005A ; Na # Lu [26] LATIN CAPITAL LETTER A..LATIN CAPITAL LETTER Z
+005B ; Na # Ps LEFT SQUARE BRACKET
+005C ; Na # Po REVERSE SOLIDUS
+005D ; Na # Pe RIGHT SQUARE BRACKET
+005E ; Na # Sk CIRCUMFLEX ACCENT
+005F ; Na # Pc LOW LINE
+0060 ; Na # Sk GRAVE ACCENT
+0061..007A ; Na # Ll [26] LATIN SMALL LETTER A..LATIN SMALL LETTER Z
+007B ; Na # Ps LEFT CURLY BRACKET
+007C ; Na # Sm VERTICAL LINE
+007D ; Na # Pe RIGHT CURLY BRACKET
+007E ; Na # Sm TILDE
+007F ; N # Cc <control-007F>
+0080..009F ; N # Cc [32] <control-0080>..<control-009F>
+00A0 ; N # Zs NO-BREAK SPACE
+00A1 ; A # Po INVERTED EXCLAMATION MARK
+00A2..00A3 ; Na # Sc [2] CENT SIGN..POUND SIGN
+00A4 ; A # Sc CURRENCY SIGN
+00A5 ; Na # Sc YEN SIGN
+00A6 ; Na # So BROKEN BAR
+00A7 ; A # Po SECTION SIGN
+00A8 ; A # Sk DIAERESIS
+00A9 ; N # So COPYRIGHT SIGN
+00AA ; A # Lo FEMININE ORDINAL INDICATOR
+00AB ; N # Pi LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
+00AC ; Na # Sm NOT SIGN
+00AD ; A # Cf SOFT HYPHEN
+00AE ; A # So REGISTERED SIGN
+00AF ; Na # Sk MACRON
+00B0 ; A # So DEGREE SIGN
+00B1 ; A # Sm PLUS-MINUS SIGN
+00B2..00B3 ; A # No [2] SUPERSCRIPT TWO..SUPERSCRIPT THREE
+00B4 ; A # Sk ACUTE ACCENT
+00B5 ; N # Ll MICRO SIGN
+00B6..00B7 ; A # Po [2] PILCROW SIGN..MIDDLE DOT
+00B8 ; A # Sk CEDILLA
+00B9 ; A # No SUPERSCRIPT ONE
+00BA ; A # Lo MASCULINE ORDINAL INDICATOR
+00BB ; N # Pf RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK
+00BC..00BE ; A # No [3] VULGAR FRACTION ONE QUARTER..VULGAR FRACTION THREE QUARTERS
+00BF ; A # Po INVERTED QUESTION MARK
+00C0..00C5 ; N # Lu [6] LATIN CAPITAL LETTER A WITH GRAVE..LATIN CAPITAL LETTER A WITH RING ABOVE
+00C6 ; A # Lu LATIN CAPITAL LETTER AE
+00C7..00CF ; N # Lu [9] LATIN CAPITAL LETTER C WITH CEDILLA..LATIN CAPITAL LETTER I WITH DIAERESIS
+00D0 ; A # Lu LATIN CAPITAL LETTER ETH
+00D1..00D6 ; N # Lu [6] LATIN CAPITAL LETTER N WITH TILDE..LATIN CAPITAL LETTER O WITH DIAERESIS
+00D7 ; A # Sm MULTIPLICATION SIGN
+00D8 ; A # Lu LATIN CAPITAL LETTER O WITH STROKE
+00D9..00DD ; N # Lu [5] LATIN CAPITAL LETTER U WITH GRAVE..LATIN CAPITAL LETTER Y WITH ACUTE
+00DE..00E1 ; A # L& [4] LATIN CAPITAL LETTER THORN..LATIN SMALL LETTER A WITH ACUTE
+00E2..00E5 ; N # Ll [4] LATIN SMALL LETTER A WITH CIRCUMFLEX..LATIN SMALL LETTER A WITH RING ABOVE
+00E6 ; A # Ll LATIN SMALL LETTER AE
+00E7 ; N # Ll LATIN SMALL LETTER C WITH CEDILLA
+00E8..00EA ; A # Ll [3] LATIN SMALL LETTER E WITH GRAVE..LATIN SMALL LETTER E WITH CIRCUMFLEX
+00EB ; N # Ll LATIN SMALL LETTER E WITH DIAERESIS
+00EC..00ED ; A # Ll [2] LATIN SMALL LETTER I WITH GRAVE..LATIN SMALL LETTER I WITH ACUTE
+00EE..00EF ; N # Ll [2] LATIN SMALL LETTER I WITH CIRCUMFLEX..LATIN SMALL LETTER I WITH DIAERESIS
+00F0 ; A # Ll LATIN SMALL LETTER ETH
+00F1 ; N # Ll LATIN SMALL LETTER N WITH TILDE
+00F2..00F3 ; A # Ll [2] LATIN SMALL LETTER O WITH GRAVE..LATIN SMALL LETTER O WITH ACUTE
+00F4..00F6 ; N # Ll [3] LATIN SMALL LETTER O WITH CIRCUMFLEX..LATIN SMALL LETTER O WITH DIAERESIS
+00F7 ; A # Sm DIVISION SIGN
+00F8..00FA ; A # Ll [3] LATIN SMALL LETTER O WITH STROKE..LATIN SMALL LETTER U WITH ACUTE
+00FB ; N # Ll LATIN SMALL LETTER U WITH CIRCUMFLEX
+00FC ; A # Ll LATIN SMALL LETTER U WITH DIAERESIS
+00FD ; N # Ll LATIN SMALL LETTER Y WITH ACUTE
+00FE ; A # Ll LATIN SMALL LETTER THORN
+00FF ; N # Ll LATIN SMALL LETTER Y WITH DIAERESIS
+0100 ; N # Lu LATIN CAPITAL LETTER A WITH MACRON
+0101 ; A # Ll LATIN SMALL LETTER A WITH MACRON
+0102..0110 ; N # L& [15] LATIN CAPITAL LETTER A WITH BREVE..LATIN CAPITAL LETTER D WITH STROKE
+0111 ; A # Ll LATIN SMALL LETTER D WITH STROKE
+0112 ; N # Lu LATIN CAPITAL LETTER E WITH MACRON
+0113 ; A # Ll LATIN SMALL LETTER E WITH MACRON
+0114..011A ; N # L& [7] LATIN CAPITAL LETTER E WITH BREVE..LATIN CAPITAL LETTER E WITH CARON
+011B ; A # Ll LATIN SMALL LETTER E WITH CARON
+011C..0125 ; N # L& [10] LATIN CAPITAL LETTER G WITH CIRCUMFLEX..LATIN SMALL LETTER H WITH CIRCUMFLEX
+0126..0127 ; A # L& [2] LATIN CAPITAL LETTER H WITH STROKE..LATIN SMALL LETTER H WITH STROKE
+0128..012A ; N # L& [3] LATIN CAPITAL LETTER I WITH TILDE..LATIN CAPITAL LETTER I WITH MACRON
+012B ; A # Ll LATIN SMALL LETTER I WITH MACRON
+012C..0130 ; N # L& [5] LATIN CAPITAL LETTER I WITH BREVE..LATIN CAPITAL LETTER I WITH DOT ABOVE
+0131..0133 ; A # L& [3] LATIN SMALL LETTER DOTLESS I..LATIN SMALL LIGATURE IJ
+0134..0137 ; N # L& [4] LATIN CAPITAL LETTER J WITH CIRCUMFLEX..LATIN SMALL LETTER K WITH CEDILLA
+0138 ; A # Ll LATIN SMALL LETTER KRA
+0139..013E ; N # L& [6] LATIN CAPITAL LETTER L WITH ACUTE..LATIN SMALL LETTER L WITH CARON
+013F..0142 ; A # L& [4] LATIN CAPITAL LETTER L WITH MIDDLE DOT..LATIN SMALL LETTER L WITH STROKE
+0143 ; N # Lu LATIN CAPITAL LETTER N WITH ACUTE
+0144 ; A # Ll LATIN SMALL LETTER N WITH ACUTE
+0145..0147 ; N # L& [3] LATIN CAPITAL LETTER N WITH CEDILLA..LATIN CAPITAL LETTER N WITH CARON
+0148..014B ; A # L& [4] LATIN SMALL LETTER N WITH CARON..LATIN SMALL LETTER ENG
+014C ; N # Lu LATIN CAPITAL LETTER O WITH MACRON
+014D ; A # Ll LATIN SMALL LETTER O WITH MACRON
+014E..0151 ; N # L& [4] LATIN CAPITAL LETTER O WITH BREVE..LATIN SMALL LETTER O WITH DOUBLE ACUTE
+0152..0153 ; A # L& [2] LATIN CAPITAL LIGATURE OE..LATIN SMALL LIGATURE OE
+0154..0165 ; N # L& [18] LATIN CAPITAL LETTER R WITH ACUTE..LATIN SMALL LETTER T WITH CARON
+0166..0167 ; A # L& [2] LATIN CAPITAL LETTER T WITH STROKE..LATIN SMALL LETTER T WITH STROKE
+0168..016A ; N # L& [3] LATIN CAPITAL LETTER U WITH TILDE..LATIN CAPITAL LETTER U WITH MACRON
+016B ; A # Ll LATIN SMALL LETTER U WITH MACRON
+016C..017F ; N # L& [20] LATIN CAPITAL LETTER U WITH BREVE..LATIN SMALL LETTER LONG S
+0180..01BA ; N # L& [59] LATIN SMALL LETTER B WITH STROKE..LATIN SMALL LETTER EZH WITH TAIL
+01BB ; N # Lo LATIN LETTER TWO WITH STROKE
+01BC..01BF ; N # L& [4] LATIN CAPITAL LETTER TONE FIVE..LATIN LETTER WYNN
+01C0..01C3 ; N # Lo [4] LATIN LETTER DENTAL CLICK..LATIN LETTER RETROFLEX CLICK
+01C4..01CD ; N # L& [10] LATIN CAPITAL LETTER DZ WITH CARON..LATIN CAPITAL LETTER A WITH CARON
+01CE ; A # Ll LATIN SMALL LETTER A WITH CARON
+01CF ; N # Lu LATIN CAPITAL LETTER I WITH CARON
+01D0 ; A # Ll LATIN SMALL LETTER I WITH CARON
+01D1 ; N # Lu LATIN CAPITAL LETTER O WITH CARON
+01D2 ; A # Ll LATIN SMALL LETTER O WITH CARON
+01D3 ; N # Lu LATIN CAPITAL LETTER U WITH CARON
+01D4 ; A # Ll LATIN SMALL LETTER U WITH CARON
+01D5 ; N # Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND MACRON
+01D6 ; A # Ll LATIN SMALL LETTER U WITH DIAERESIS AND MACRON
+01D7 ; N # Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND ACUTE
+01D8 ; A # Ll LATIN SMALL LETTER U WITH DIAERESIS AND ACUTE
+01D9 ; N # Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND CARON
+01DA ; A # Ll LATIN SMALL LETTER U WITH DIAERESIS AND CARON
+01DB ; N # Lu LATIN CAPITAL LETTER U WITH DIAERESIS AND GRAVE
+01DC ; A # Ll LATIN SMALL LETTER U WITH DIAERESIS AND GRAVE
+01DD..024F ; N # L& [115] LATIN SMALL LETTER TURNED E..LATIN SMALL LETTER Y WITH STROKE
+0250 ; N # Ll LATIN SMALL LETTER TURNED A
+0251 ; A # Ll LATIN SMALL LETTER ALPHA
+0252..0260 ; N # Ll [15] LATIN SMALL LETTER TURNED ALPHA..LATIN SMALL LETTER G WITH HOOK
+0261 ; A # Ll LATIN SMALL LETTER SCRIPT G
+0262..0293 ; N # Ll [50] LATIN LETTER SMALL CAPITAL G..LATIN SMALL LETTER EZH WITH CURL
+0294 ; N # Lo LATIN LETTER GLOTTAL STOP
+0295..02AF ; N # Ll [27] LATIN LETTER PHARYNGEAL VOICED FRICATIVE..LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL
+02B0..02C1 ; N # Lm [18] MODIFIER LETTER SMALL H..MODIFIER LETTER REVERSED GLOTTAL STOP
+02C2..02C3 ; N # Sk [2] MODIFIER LETTER LEFT ARROWHEAD..MODIFIER LETTER RIGHT ARROWHEAD
+02C4 ; A # Sk MODIFIER LETTER UP ARROWHEAD
+02C5 ; N # Sk MODIFIER LETTER DOWN ARROWHEAD
+02C6 ; N # Lm MODIFIER LETTER CIRCUMFLEX ACCENT
+02C7 ; A # Lm CARON
+02C8 ; N # Lm MODIFIER LETTER VERTICAL LINE
+02C9..02CB ; A # Lm [3] MODIFIER LETTER MACRON..MODIFIER LETTER GRAVE ACCENT
+02CC ; N # Lm MODIFIER LETTER LOW VERTICAL LINE
+02CD ; A # Lm MODIFIER LETTER LOW MACRON
+02CE..02CF ; N # Lm [2] MODIFIER LETTER LOW GRAVE ACCENT..MODIFIER LETTER LOW ACUTE ACCENT
+02D0 ; A # Lm MODIFIER LETTER TRIANGULAR COLON
+02D1 ; N # Lm MODIFIER LETTER HALF TRIANGULAR COLON
+02D2..02D7 ; N # Sk [6] MODIFIER LETTER CENTRED RIGHT HALF RING..MODIFIER LETTER MINUS SIGN
+02D8..02DB ; A # Sk [4] BREVE..OGONEK
+02DC ; N # Sk SMALL TILDE
+02DD ; A # Sk DOUBLE ACUTE ACCENT
+02DE ; N # Sk MODIFIER LETTER RHOTIC HOOK
+02DF ; A # Sk MODIFIER LETTER CROSS ACCENT
+02E0..02E4 ; N # Lm [5] MODIFIER LETTER SMALL GAMMA..MODIFIER LETTER SMALL REVERSED GLOTTAL STOP
+02E5..02EB ; N # Sk [7] MODIFIER LETTER EXTRA-HIGH TONE BAR..MODIFIER LETTER YANG DEPARTING TONE MARK
+02EC ; N # Lm MODIFIER LETTER VOICING
+02ED ; N # Sk MODIFIER LETTER UNASPIRATED
+02EE ; N # Lm MODIFIER LETTER DOUBLE APOSTROPHE
+02EF..02FF ; N # Sk [17] MODIFIER LETTER LOW DOWN ARROWHEAD..MODIFIER LETTER LOW LEFT ARROW
+0300..036F ; A # Mn [112] COMBINING GRAVE ACCENT..COMBINING LATIN SMALL LETTER X
+0370..0373 ; N # L& [4] GREEK CAPITAL LETTER HETA..GREEK SMALL LETTER ARCHAIC SAMPI
+0374 ; N # Lm GREEK NUMERAL SIGN
+0375 ; N # Sk GREEK LOWER NUMERAL SIGN
+0376..0377 ; N # L& [2] GREEK CAPITAL LETTER PAMPHYLIAN DIGAMMA..GREEK SMALL LETTER PAMPHYLIAN DIGAMMA
+037A ; N # Lm GREEK YPOGEGRAMMENI
+037B..037D ; N # Ll [3] GREEK SMALL REVERSED LUNATE SIGMA SYMBOL..GREEK SMALL REVERSED DOTTED LUNATE SIGMA SYMBOL
+037E ; N # Po GREEK QUESTION MARK
+037F ; N # Lu GREEK CAPITAL LETTER YOT
+0384..0385 ; N # Sk [2] GREEK TONOS..GREEK DIALYTIKA TONOS
+0386 ; N # Lu GREEK CAPITAL LETTER ALPHA WITH TONOS
+0387 ; N # Po GREEK ANO TELEIA
+0388..038A ; N # Lu [3] GREEK CAPITAL LETTER EPSILON WITH TONOS..GREEK CAPITAL LETTER IOTA WITH TONOS
+038C ; N # Lu GREEK CAPITAL LETTER OMICRON WITH TONOS
+038E..0390 ; N # L& [3] GREEK CAPITAL LETTER UPSILON WITH TONOS..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND TONOS
+0391..03A1 ; A # Lu [17] GREEK CAPITAL LETTER ALPHA..GREEK CAPITAL LETTER RHO
+03A3..03A9 ; A # Lu [7] GREEK CAPITAL LETTER SIGMA..GREEK CAPITAL LETTER OMEGA
+03AA..03B0 ; N # L& [7] GREEK CAPITAL LETTER IOTA WITH DIALYTIKA..GREEK SMALL LETTER UPSILON WITH DIALYTIKA AND TONOS
+03B1..03C1 ; A # Ll [17] GREEK SMALL LETTER ALPHA..GREEK SMALL LETTER RHO
+03C2 ; N # Ll GREEK SMALL LETTER FINAL SIGMA
+03C3..03C9 ; A # Ll [7] GREEK SMALL LETTER SIGMA..GREEK SMALL LETTER OMEGA
+03CA..03F5 ; N # L& [44] GREEK SMALL LETTER IOTA WITH DIALYTIKA..GREEK LUNATE EPSILON SYMBOL
+03F6 ; N # Sm GREEK REVERSED LUNATE EPSILON SYMBOL
+03F7..03FF ; N # L& [9] GREEK CAPITAL LETTER SHO..GREEK CAPITAL REVERSED DOTTED LUNATE SIGMA SYMBOL
+0400 ; N # Lu CYRILLIC CAPITAL LETTER IE WITH GRAVE
+0401 ; A # Lu CYRILLIC CAPITAL LETTER IO
+0402..040F ; N # Lu [14] CYRILLIC CAPITAL LETTER DJE..CYRILLIC CAPITAL LETTER DZHE
+0410..044F ; A # L& [64] CYRILLIC CAPITAL LETTER A..CYRILLIC SMALL LETTER YA
+0450 ; N # Ll CYRILLIC SMALL LETTER IE WITH GRAVE
+0451 ; A # Ll CYRILLIC SMALL LETTER IO
+0452..0481 ; N # L& [48] CYRILLIC SMALL LETTER DJE..CYRILLIC SMALL LETTER KOPPA
+0482 ; N # So CYRILLIC THOUSANDS SIGN
+0483..0487 ; N # Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE
+0488..0489 ; N # Me [2] COMBINING CYRILLIC HUNDRED THOUSANDS SIGN..COMBINING CYRILLIC MILLIONS SIGN
+048A..04FF ; N # L& [118] CYRILLIC CAPITAL LETTER SHORT I WITH TAIL..CYRILLIC SMALL LETTER HA WITH STROKE
+0500..052F ; N # L& [48] CYRILLIC CAPITAL LETTER KOMI DE..CYRILLIC SMALL LETTER EL WITH DESCENDER
+0531..0556 ; N # Lu [38] ARMENIAN CAPITAL LETTER AYB..ARMENIAN CAPITAL LETTER FEH
+0559 ; N # Lm ARMENIAN MODIFIER LETTER LEFT HALF RING
+055A..055F ; N # Po [6] ARMENIAN APOSTROPHE..ARMENIAN ABBREVIATION MARK
+0560..0588 ; N # Ll [41] ARMENIAN SMALL LETTER TURNED AYB..ARMENIAN SMALL LETTER YI WITH STROKE
+0589 ; N # Po ARMENIAN FULL STOP
+058A ; N # Pd ARMENIAN HYPHEN
+058D..058E ; N # So [2] RIGHT-FACING ARMENIAN ETERNITY SIGN..LEFT-FACING ARMENIAN ETERNITY SIGN
+058F ; N # Sc ARMENIAN DRAM SIGN
+0591..05BD ; N # Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG
+05BE ; N # Pd HEBREW PUNCTUATION MAQAF
+05BF ; N # Mn HEBREW POINT RAFE
+05C0 ; N # Po HEBREW PUNCTUATION PASEQ
+05C1..05C2 ; N # Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT
+05C3 ; N # Po HEBREW PUNCTUATION SOF PASUQ
+05C4..05C5 ; N # Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT
+05C6 ; N # Po HEBREW PUNCTUATION NUN HAFUKHA
+05C7 ; N # Mn HEBREW POINT QAMATS QATAN
+05D0..05EA ; N # Lo [27] HEBREW LETTER ALEF..HEBREW LETTER TAV
+05EF..05F2 ; N # Lo [4] HEBREW YOD TRIANGLE..HEBREW LIGATURE YIDDISH DOUBLE YOD
+05F3..05F4 ; N # Po [2] HEBREW PUNCTUATION GERESH..HEBREW PUNCTUATION GERSHAYIM
+0600..0605 ; N # Cf [6] ARABIC NUMBER SIGN..ARABIC NUMBER MARK ABOVE
+0606..0608 ; N # Sm [3] ARABIC-INDIC CUBE ROOT..ARABIC RAY
+0609..060A ; N # Po [2] ARABIC-INDIC PER MILLE SIGN..ARABIC-INDIC PER TEN THOUSAND SIGN
+060B ; N # Sc AFGHANI SIGN
+060C..060D ; N # Po [2] ARABIC COMMA..ARABIC DATE SEPARATOR
+060E..060F ; N # So [2] ARABIC POETIC VERSE SIGN..ARABIC SIGN MISRA
+0610..061A ; N # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA
+061B ; N # Po ARABIC SEMICOLON
+061C ; N # Cf ARABIC LETTER MARK
+061D..061F ; N # Po [3] ARABIC END OF TEXT MARK..ARABIC QUESTION MARK
+0620..063F ; N # Lo [32] ARABIC LETTER KASHMIRI YEH..ARABIC LETTER FARSI YEH WITH THREE DOTS ABOVE
+0640 ; N # Lm ARABIC TATWEEL
+0641..064A ; N # Lo [10] ARABIC LETTER FEH..ARABIC LETTER YEH
+064B..065F ; N # Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW
+0660..0669 ; N # Nd [10] ARABIC-INDIC DIGIT ZERO..ARABIC-INDIC DIGIT NINE
+066A..066D ; N # Po [4] ARABIC PERCENT SIGN..ARABIC FIVE POINTED STAR
+066E..066F ; N # Lo [2] ARABIC LETTER DOTLESS BEH..ARABIC LETTER DOTLESS QAF
+0670 ; N # Mn ARABIC LETTER SUPERSCRIPT ALEF
+0671..06D3 ; N # Lo [99] ARABIC LETTER ALEF WASLA..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE
+06D4 ; N # Po ARABIC FULL STOP
+06D5 ; N # Lo ARABIC LETTER AE
+06D6..06DC ; N # Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN
+06DD ; N # Cf ARABIC END OF AYAH
+06DE ; N # So ARABIC START OF RUB EL HIZB
+06DF..06E4 ; N # Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA
+06E5..06E6 ; N # Lm [2] ARABIC SMALL WAW..ARABIC SMALL YEH
+06E7..06E8 ; N # Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON
+06E9 ; N # So ARABIC PLACE OF SAJDAH
+06EA..06ED ; N # Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM
+06EE..06EF ; N # Lo [2] ARABIC LETTER DAL WITH INVERTED V..ARABIC LETTER REH WITH INVERTED V
+06F0..06F9 ; N # Nd [10] EXTENDED ARABIC-INDIC DIGIT ZERO..EXTENDED ARABIC-INDIC DIGIT NINE
+06FA..06FC ; N # Lo [3] ARABIC LETTER SHEEN WITH DOT BELOW..ARABIC LETTER GHAIN WITH DOT BELOW
+06FD..06FE ; N # So [2] ARABIC SIGN SINDHI AMPERSAND..ARABIC SIGN SINDHI POSTPOSITION MEN
+06FF ; N # Lo ARABIC LETTER HEH WITH INVERTED V
+0700..070D ; N # Po [14] SYRIAC END OF PARAGRAPH..SYRIAC HARKLEAN ASTERISCUS
+070F ; N # Cf SYRIAC ABBREVIATION MARK
+0710 ; N # Lo SYRIAC LETTER ALAPH
+0711 ; N # Mn SYRIAC LETTER SUPERSCRIPT ALAPH
+0712..072F ; N # Lo [30] SYRIAC LETTER BETH..SYRIAC LETTER PERSIAN DHALATH
+0730..074A ; N # Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH
+074D..074F ; N # Lo [3] SYRIAC LETTER SOGDIAN ZHAIN..SYRIAC LETTER SOGDIAN FE
+0750..077F ; N # Lo [48] ARABIC LETTER BEH WITH THREE DOTS HORIZONTALLY BELOW..ARABIC LETTER KAF WITH TWO DOTS ABOVE
+0780..07A5 ; N # Lo [38] THAANA LETTER HAA..THAANA LETTER WAAVU
+07A6..07B0 ; N # Mn [11] THAANA ABAFILI..THAANA SUKUN
+07B1 ; N # Lo THAANA LETTER NAA
+07C0..07C9 ; N # Nd [10] NKO DIGIT ZERO..NKO DIGIT NINE
+07CA..07EA ; N # Lo [33] NKO LETTER A..NKO LETTER JONA RA
+07EB..07F3 ; N # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
+07F4..07F5 ; N # Lm [2] NKO HIGH TONE APOSTROPHE..NKO LOW TONE APOSTROPHE
+07F6 ; N # So NKO SYMBOL OO DENNEN
+07F7..07F9 ; N # Po [3] NKO SYMBOL GBAKURUNEN..NKO EXCLAMATION MARK
+07FA ; N # Lm NKO LAJANYALAN
+07FD ; N # Mn NKO DANTAYALAN
+07FE..07FF ; N # Sc [2] NKO DOROME SIGN..NKO TAMAN SIGN
+0800..0815 ; N # Lo [22] SAMARITAN LETTER ALAF..SAMARITAN LETTER TAAF
+0816..0819 ; N # Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH
+081A ; N # Lm SAMARITAN MODIFIER LETTER EPENTHETIC YUT
+081B..0823 ; N # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A
+0824 ; N # Lm SAMARITAN MODIFIER LETTER SHORT A
+0825..0827 ; N # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U
+0828 ; N # Lm SAMARITAN MODIFIER LETTER I
+0829..082D ; N # Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA
+0830..083E ; N # Po [15] SAMARITAN PUNCTUATION NEQUDAA..SAMARITAN PUNCTUATION ANNAAU
+0840..0858 ; N # Lo [25] MANDAIC LETTER HALQA..MANDAIC LETTER AIN
+0859..085B ; N # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK
+085E ; N # Po MANDAIC PUNCTUATION
+0860..086A ; N # Lo [11] SYRIAC LETTER MALAYALAM NGA..SYRIAC LETTER MALAYALAM SSA
+0870..0887 ; N # Lo [24] ARABIC LETTER ALEF WITH ATTACHED FATHA..ARABIC BASELINE ROUND DOT
+0888 ; N # Sk ARABIC RAISED ROUND DOT
+0889..088E ; N # Lo [6] ARABIC LETTER NOON WITH INVERTED SMALL V..ARABIC VERTICAL TAIL
+0890..0891 ; N # Cf [2] ARABIC POUND MARK ABOVE..ARABIC PIASTRE MARK ABOVE
+0898..089F ; N # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA
+08A0..08C8 ; N # Lo [41] ARABIC LETTER BEH WITH SMALL V BELOW..ARABIC LETTER GRAF
+08C9 ; N # Lm ARABIC SMALL FARSI YEH
+08CA..08E1 ; N # Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA
+08E2 ; N # Cf ARABIC DISPUTED END OF AYAH
+08E3..08FF ; N # Mn [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA
+0900..0902 ; N # Mn [3] DEVANAGARI SIGN INVERTED CANDRABINDU..DEVANAGARI SIGN ANUSVARA
+0903 ; N # Mc DEVANAGARI SIGN VISARGA
+0904..0939 ; N # Lo [54] DEVANAGARI LETTER SHORT A..DEVANAGARI LETTER HA
+093A ; N # Mn DEVANAGARI VOWEL SIGN OE
+093B ; N # Mc DEVANAGARI VOWEL SIGN OOE
+093C ; N # Mn DEVANAGARI SIGN NUKTA
+093D ; N # Lo DEVANAGARI SIGN AVAGRAHA
+093E..0940 ; N # Mc [3] DEVANAGARI VOWEL SIGN AA..DEVANAGARI VOWEL SIGN II
+0941..0948 ; N # Mn [8] DEVANAGARI VOWEL SIGN U..DEVANAGARI VOWEL SIGN AI
+0949..094C ; N # Mc [4] DEVANAGARI VOWEL SIGN CANDRA O..DEVANAGARI VOWEL SIGN AU
+094D ; N # Mn DEVANAGARI SIGN VIRAMA
+094E..094F ; N # Mc [2] DEVANAGARI VOWEL SIGN PRISHTHAMATRA E..DEVANAGARI VOWEL SIGN AW
+0950 ; N # Lo DEVANAGARI OM
+0951..0957 ; N # Mn [7] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI VOWEL SIGN UUE
+0958..0961 ; N # Lo [10] DEVANAGARI LETTER QA..DEVANAGARI LETTER VOCALIC LL
+0962..0963 ; N # Mn [2] DEVANAGARI VOWEL SIGN VOCALIC L..DEVANAGARI VOWEL SIGN VOCALIC LL
+0964..0965 ; N # Po [2] DEVANAGARI DANDA..DEVANAGARI DOUBLE DANDA
+0966..096F ; N # Nd [10] DEVANAGARI DIGIT ZERO..DEVANAGARI DIGIT NINE
+0970 ; N # Po DEVANAGARI ABBREVIATION SIGN
+0971 ; N # Lm DEVANAGARI SIGN HIGH SPACING DOT
+0972..097F ; N # Lo [14] DEVANAGARI LETTER CANDRA A..DEVANAGARI LETTER BBA
+0980 ; N # Lo BENGALI ANJI
+0981 ; N # Mn BENGALI SIGN CANDRABINDU
+0982..0983 ; N # Mc [2] BENGALI SIGN ANUSVARA..BENGALI SIGN VISARGA
+0985..098C ; N # Lo [8] BENGALI LETTER A..BENGALI LETTER VOCALIC L
+098F..0990 ; N # Lo [2] BENGALI LETTER E..BENGALI LETTER AI
+0993..09A8 ; N # Lo [22] BENGALI LETTER O..BENGALI LETTER NA
+09AA..09B0 ; N # Lo [7] BENGALI LETTER PA..BENGALI LETTER RA
+09B2 ; N # Lo BENGALI LETTER LA
+09B6..09B9 ; N # Lo [4] BENGALI LETTER SHA..BENGALI LETTER HA
+09BC ; N # Mn BENGALI SIGN NUKTA
+09BD ; N # Lo BENGALI SIGN AVAGRAHA
+09BE..09C0 ; N # Mc [3] BENGALI VOWEL SIGN AA..BENGALI VOWEL SIGN II
+09C1..09C4 ; N # Mn [4] BENGALI VOWEL SIGN U..BENGALI VOWEL SIGN VOCALIC RR
+09C7..09C8 ; N # Mc [2] BENGALI VOWEL SIGN E..BENGALI VOWEL SIGN AI
+09CB..09CC ; N # Mc [2] BENGALI VOWEL SIGN O..BENGALI VOWEL SIGN AU
+09CD ; N # Mn BENGALI SIGN VIRAMA
+09CE ; N # Lo BENGALI LETTER KHANDA TA
+09D7 ; N # Mc BENGALI AU LENGTH MARK
+09DC..09DD ; N # Lo [2] BENGALI LETTER RRA..BENGALI LETTER RHA
+09DF..09E1 ; N # Lo [3] BENGALI LETTER YYA..BENGALI LETTER VOCALIC LL
+09E2..09E3 ; N # Mn [2] BENGALI VOWEL SIGN VOCALIC L..BENGALI VOWEL SIGN VOCALIC LL
+09E6..09EF ; N # Nd [10] BENGALI DIGIT ZERO..BENGALI DIGIT NINE
+09F0..09F1 ; N # Lo [2] BENGALI LETTER RA WITH MIDDLE DIAGONAL..BENGALI LETTER RA WITH LOWER DIAGONAL
+09F2..09F3 ; N # Sc [2] BENGALI RUPEE MARK..BENGALI RUPEE SIGN
+09F4..09F9 ; N # No [6] BENGALI CURRENCY NUMERATOR ONE..BENGALI CURRENCY DENOMINATOR SIXTEEN
+09FA ; N # So BENGALI ISSHAR
+09FB ; N # Sc BENGALI GANDA MARK
+09FC ; N # Lo BENGALI LETTER VEDIC ANUSVARA
+09FD ; N # Po BENGALI ABBREVIATION SIGN
+09FE ; N # Mn BENGALI SANDHI MARK
+0A01..0A02 ; N # Mn [2] GURMUKHI SIGN ADAK BINDI..GURMUKHI SIGN BINDI
+0A03 ; N # Mc GURMUKHI SIGN VISARGA
+0A05..0A0A ; N # Lo [6] GURMUKHI LETTER A..GURMUKHI LETTER UU
+0A0F..0A10 ; N # Lo [2] GURMUKHI LETTER EE..GURMUKHI LETTER AI
+0A13..0A28 ; N # Lo [22] GURMUKHI LETTER OO..GURMUKHI LETTER NA
+0A2A..0A30 ; N # Lo [7] GURMUKHI LETTER PA..GURMUKHI LETTER RA
+0A32..0A33 ; N # Lo [2] GURMUKHI LETTER LA..GURMUKHI LETTER LLA
+0A35..0A36 ; N # Lo [2] GURMUKHI LETTER VA..GURMUKHI LETTER SHA
+0A38..0A39 ; N # Lo [2] GURMUKHI LETTER SA..GURMUKHI LETTER HA
+0A3C ; N # Mn GURMUKHI SIGN NUKTA
+0A3E..0A40 ; N # Mc [3] GURMUKHI VOWEL SIGN AA..GURMUKHI VOWEL SIGN II
+0A41..0A42 ; N # Mn [2] GURMUKHI VOWEL SIGN U..GURMUKHI VOWEL SIGN UU
+0A47..0A48 ; N # Mn [2] GURMUKHI VOWEL SIGN EE..GURMUKHI VOWEL SIGN AI
+0A4B..0A4D ; N # Mn [3] GURMUKHI VOWEL SIGN OO..GURMUKHI SIGN VIRAMA
+0A51 ; N # Mn GURMUKHI SIGN UDAAT
+0A59..0A5C ; N # Lo [4] GURMUKHI LETTER KHHA..GURMUKHI LETTER RRA
+0A5E ; N # Lo GURMUKHI LETTER FA
+0A66..0A6F ; N # Nd [10] GURMUKHI DIGIT ZERO..GURMUKHI DIGIT NINE
+0A70..0A71 ; N # Mn [2] GURMUKHI TIPPI..GURMUKHI ADDAK
+0A72..0A74 ; N # Lo [3] GURMUKHI IRI..GURMUKHI EK ONKAR
+0A75 ; N # Mn GURMUKHI SIGN YAKASH
+0A76 ; N # Po GURMUKHI ABBREVIATION SIGN
+0A81..0A82 ; N # Mn [2] GUJARATI SIGN CANDRABINDU..GUJARATI SIGN ANUSVARA
+0A83 ; N # Mc GUJARATI SIGN VISARGA
+0A85..0A8D ; N # Lo [9] GUJARATI LETTER A..GUJARATI VOWEL CANDRA E
+0A8F..0A91 ; N # Lo [3] GUJARATI LETTER E..GUJARATI VOWEL CANDRA O
+0A93..0AA8 ; N # Lo [22] GUJARATI LETTER O..GUJARATI LETTER NA
+0AAA..0AB0 ; N # Lo [7] GUJARATI LETTER PA..GUJARATI LETTER RA
+0AB2..0AB3 ; N # Lo [2] GUJARATI LETTER LA..GUJARATI LETTER LLA
+0AB5..0AB9 ; N # Lo [5] GUJARATI LETTER VA..GUJARATI LETTER HA
+0ABC ; N # Mn GUJARATI SIGN NUKTA
+0ABD ; N # Lo GUJARATI SIGN AVAGRAHA
+0ABE..0AC0 ; N # Mc [3] GUJARATI VOWEL SIGN AA..GUJARATI VOWEL SIGN II
+0AC1..0AC5 ; N # Mn [5] GUJARATI VOWEL SIGN U..GUJARATI VOWEL SIGN CANDRA E
+0AC7..0AC8 ; N # Mn [2] GUJARATI VOWEL SIGN E..GUJARATI VOWEL SIGN AI
+0AC9 ; N # Mc GUJARATI VOWEL SIGN CANDRA O
+0ACB..0ACC ; N # Mc [2] GUJARATI VOWEL SIGN O..GUJARATI VOWEL SIGN AU
+0ACD ; N # Mn GUJARATI SIGN VIRAMA
+0AD0 ; N # Lo GUJARATI OM
+0AE0..0AE1 ; N # Lo [2] GUJARATI LETTER VOCALIC RR..GUJARATI LETTER VOCALIC LL
+0AE2..0AE3 ; N # Mn [2] GUJARATI VOWEL SIGN VOCALIC L..GUJARATI VOWEL SIGN VOCALIC LL
+0AE6..0AEF ; N # Nd [10] GUJARATI DIGIT ZERO..GUJARATI DIGIT NINE
+0AF0 ; N # Po GUJARATI ABBREVIATION SIGN
+0AF1 ; N # Sc GUJARATI RUPEE SIGN
+0AF9 ; N # Lo GUJARATI LETTER ZHA
+0AFA..0AFF ; N # Mn [6] GUJARATI SIGN SUKUN..GUJARATI SIGN TWO-CIRCLE NUKTA ABOVE
+0B01 ; N # Mn ORIYA SIGN CANDRABINDU
+0B02..0B03 ; N # Mc [2] ORIYA SIGN ANUSVARA..ORIYA SIGN VISARGA
+0B05..0B0C ; N # Lo [8] ORIYA LETTER A..ORIYA LETTER VOCALIC L
+0B0F..0B10 ; N # Lo [2] ORIYA LETTER E..ORIYA LETTER AI
+0B13..0B28 ; N # Lo [22] ORIYA LETTER O..ORIYA LETTER NA
+0B2A..0B30 ; N # Lo [7] ORIYA LETTER PA..ORIYA LETTER RA
+0B32..0B33 ; N # Lo [2] ORIYA LETTER LA..ORIYA LETTER LLA
+0B35..0B39 ; N # Lo [5] ORIYA LETTER VA..ORIYA LETTER HA
+0B3C ; N # Mn ORIYA SIGN NUKTA
+0B3D ; N # Lo ORIYA SIGN AVAGRAHA
+0B3E ; N # Mc ORIYA VOWEL SIGN AA
+0B3F ; N # Mn ORIYA VOWEL SIGN I
+0B40 ; N # Mc ORIYA VOWEL SIGN II
+0B41..0B44 ; N # Mn [4] ORIYA VOWEL SIGN U..ORIYA VOWEL SIGN VOCALIC RR
+0B47..0B48 ; N # Mc [2] ORIYA VOWEL SIGN E..ORIYA VOWEL SIGN AI
+0B4B..0B4C ; N # Mc [2] ORIYA VOWEL SIGN O..ORIYA VOWEL SIGN AU
+0B4D ; N # Mn ORIYA SIGN VIRAMA
+0B55..0B56 ; N # Mn [2] ORIYA SIGN OVERLINE..ORIYA AI LENGTH MARK
+0B57 ; N # Mc ORIYA AU LENGTH MARK
+0B5C..0B5D ; N # Lo [2] ORIYA LETTER RRA..ORIYA LETTER RHA
+0B5F..0B61 ; N # Lo [3] ORIYA LETTER YYA..ORIYA LETTER VOCALIC LL
+0B62..0B63 ; N # Mn [2] ORIYA VOWEL SIGN VOCALIC L..ORIYA VOWEL SIGN VOCALIC LL
+0B66..0B6F ; N # Nd [10] ORIYA DIGIT ZERO..ORIYA DIGIT NINE
+0B70 ; N # So ORIYA ISSHAR
+0B71 ; N # Lo ORIYA LETTER WA
+0B72..0B77 ; N # No [6] ORIYA FRACTION ONE QUARTER..ORIYA FRACTION THREE SIXTEENTHS
+0B82 ; N # Mn TAMIL SIGN ANUSVARA
+0B83 ; N # Lo TAMIL SIGN VISARGA
+0B85..0B8A ; N # Lo [6] TAMIL LETTER A..TAMIL LETTER UU
+0B8E..0B90 ; N # Lo [3] TAMIL LETTER E..TAMIL LETTER AI
+0B92..0B95 ; N # Lo [4] TAMIL LETTER O..TAMIL LETTER KA
+0B99..0B9A ; N # Lo [2] TAMIL LETTER NGA..TAMIL LETTER CA
+0B9C ; N # Lo TAMIL LETTER JA
+0B9E..0B9F ; N # Lo [2] TAMIL LETTER NYA..TAMIL LETTER TTA
+0BA3..0BA4 ; N # Lo [2] TAMIL LETTER NNA..TAMIL LETTER TA
+0BA8..0BAA ; N # Lo [3] TAMIL LETTER NA..TAMIL LETTER PA
+0BAE..0BB9 ; N # Lo [12] TAMIL LETTER MA..TAMIL LETTER HA
+0BBE..0BBF ; N # Mc [2] TAMIL VOWEL SIGN AA..TAMIL VOWEL SIGN I
+0BC0 ; N # Mn TAMIL VOWEL SIGN II
+0BC1..0BC2 ; N # Mc [2] TAMIL VOWEL SIGN U..TAMIL VOWEL SIGN UU
+0BC6..0BC8 ; N # Mc [3] TAMIL VOWEL SIGN E..TAMIL VOWEL SIGN AI
+0BCA..0BCC ; N # Mc [3] TAMIL VOWEL SIGN O..TAMIL VOWEL SIGN AU
+0BCD ; N # Mn TAMIL SIGN VIRAMA
+0BD0 ; N # Lo TAMIL OM
+0BD7 ; N # Mc TAMIL AU LENGTH MARK
+0BE6..0BEF ; N # Nd [10] TAMIL DIGIT ZERO..TAMIL DIGIT NINE
+0BF0..0BF2 ; N # No [3] TAMIL NUMBER TEN..TAMIL NUMBER ONE THOUSAND
+0BF3..0BF8 ; N # So [6] TAMIL DAY SIGN..TAMIL AS ABOVE SIGN
+0BF9 ; N # Sc TAMIL RUPEE SIGN
+0BFA ; N # So TAMIL NUMBER SIGN
+0C00 ; N # Mn TELUGU SIGN COMBINING CANDRABINDU ABOVE
+0C01..0C03 ; N # Mc [3] TELUGU SIGN CANDRABINDU..TELUGU SIGN VISARGA
+0C04 ; N # Mn TELUGU SIGN COMBINING ANUSVARA ABOVE
+0C05..0C0C ; N # Lo [8] TELUGU LETTER A..TELUGU LETTER VOCALIC L
+0C0E..0C10 ; N # Lo [3] TELUGU LETTER E..TELUGU LETTER AI
+0C12..0C28 ; N # Lo [23] TELUGU LETTER O..TELUGU LETTER NA
+0C2A..0C39 ; N # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA
+0C3C ; N # Mn TELUGU SIGN NUKTA
+0C3D ; N # Lo TELUGU SIGN AVAGRAHA
+0C3E..0C40 ; N # Mn [3] TELUGU VOWEL SIGN AA..TELUGU VOWEL SIGN II
+0C41..0C44 ; N # Mc [4] TELUGU VOWEL SIGN U..TELUGU VOWEL SIGN VOCALIC RR
+0C46..0C48 ; N # Mn [3] TELUGU VOWEL SIGN E..TELUGU VOWEL SIGN AI
+0C4A..0C4D ; N # Mn [4] TELUGU VOWEL SIGN O..TELUGU SIGN VIRAMA
+0C55..0C56 ; N # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
+0C58..0C5A ; N # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA
+0C5D ; N # Lo TELUGU LETTER NAKAARA POLLU
+0C60..0C61 ; N # Lo [2] TELUGU LETTER VOCALIC RR..TELUGU LETTER VOCALIC LL
+0C62..0C63 ; N # Mn [2] TELUGU VOWEL SIGN VOCALIC L..TELUGU VOWEL SIGN VOCALIC LL
+0C66..0C6F ; N # Nd [10] TELUGU DIGIT ZERO..TELUGU DIGIT NINE
+0C77 ; N # Po TELUGU SIGN SIDDHAM
+0C78..0C7E ; N # No [7] TELUGU FRACTION DIGIT ZERO FOR ODD POWERS OF FOUR..TELUGU FRACTION DIGIT THREE FOR EVEN POWERS OF FOUR
+0C7F ; N # So TELUGU SIGN TUUMU
+0C80 ; N # Lo KANNADA SIGN SPACING CANDRABINDU
+0C81 ; N # Mn KANNADA SIGN CANDRABINDU
+0C82..0C83 ; N # Mc [2] KANNADA SIGN ANUSVARA..KANNADA SIGN VISARGA
+0C84 ; N # Po KANNADA SIGN SIDDHAM
+0C85..0C8C ; N # Lo [8] KANNADA LETTER A..KANNADA LETTER VOCALIC L
+0C8E..0C90 ; N # Lo [3] KANNADA LETTER E..KANNADA LETTER AI
+0C92..0CA8 ; N # Lo [23] KANNADA LETTER O..KANNADA LETTER NA
+0CAA..0CB3 ; N # Lo [10] KANNADA LETTER PA..KANNADA LETTER LLA
+0CB5..0CB9 ; N # Lo [5] KANNADA LETTER VA..KANNADA LETTER HA
+0CBC ; N # Mn KANNADA SIGN NUKTA
+0CBD ; N # Lo KANNADA SIGN AVAGRAHA
+0CBE ; N # Mc KANNADA VOWEL SIGN AA
+0CBF ; N # Mn KANNADA VOWEL SIGN I
+0CC0..0CC4 ; N # Mc [5] KANNADA VOWEL SIGN II..KANNADA VOWEL SIGN VOCALIC RR
+0CC6 ; N # Mn KANNADA VOWEL SIGN E
+0CC7..0CC8 ; N # Mc [2] KANNADA VOWEL SIGN EE..KANNADA VOWEL SIGN AI
+0CCA..0CCB ; N # Mc [2] KANNADA VOWEL SIGN O..KANNADA VOWEL SIGN OO
+0CCC..0CCD ; N # Mn [2] KANNADA VOWEL SIGN AU..KANNADA SIGN VIRAMA
+0CD5..0CD6 ; N # Mc [2] KANNADA LENGTH MARK..KANNADA AI LENGTH MARK
+0CDD..0CDE ; N # Lo [2] KANNADA LETTER NAKAARA POLLU..KANNADA LETTER FA
+0CE0..0CE1 ; N # Lo [2] KANNADA LETTER VOCALIC RR..KANNADA LETTER VOCALIC LL
+0CE2..0CE3 ; N # Mn [2] KANNADA VOWEL SIGN VOCALIC L..KANNADA VOWEL SIGN VOCALIC LL
+0CE6..0CEF ; N # Nd [10] KANNADA DIGIT ZERO..KANNADA DIGIT NINE
+0CF1..0CF2 ; N # Lo [2] KANNADA SIGN JIHVAMULIYA..KANNADA SIGN UPADHMANIYA
+0CF3 ; N # Mc KANNADA SIGN COMBINING ANUSVARA ABOVE RIGHT
+0D00..0D01 ; N # Mn [2] MALAYALAM SIGN COMBINING ANUSVARA ABOVE..MALAYALAM SIGN CANDRABINDU
+0D02..0D03 ; N # Mc [2] MALAYALAM SIGN ANUSVARA..MALAYALAM SIGN VISARGA
+0D04..0D0C ; N # Lo [9] MALAYALAM LETTER VEDIC ANUSVARA..MALAYALAM LETTER VOCALIC L
+0D0E..0D10 ; N # Lo [3] MALAYALAM LETTER E..MALAYALAM LETTER AI
+0D12..0D3A ; N # Lo [41] MALAYALAM LETTER O..MALAYALAM LETTER TTTA
+0D3B..0D3C ; N # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA
+0D3D ; N # Lo MALAYALAM SIGN AVAGRAHA
+0D3E..0D40 ; N # Mc [3] MALAYALAM VOWEL SIGN AA..MALAYALAM VOWEL SIGN II
+0D41..0D44 ; N # Mn [4] MALAYALAM VOWEL SIGN U..MALAYALAM VOWEL SIGN VOCALIC RR
+0D46..0D48 ; N # Mc [3] MALAYALAM VOWEL SIGN E..MALAYALAM VOWEL SIGN AI
+0D4A..0D4C ; N # Mc [3] MALAYALAM VOWEL SIGN O..MALAYALAM VOWEL SIGN AU
+0D4D ; N # Mn MALAYALAM SIGN VIRAMA
+0D4E ; N # Lo MALAYALAM LETTER DOT REPH
+0D4F ; N # So MALAYALAM SIGN PARA
+0D54..0D56 ; N # Lo [3] MALAYALAM LETTER CHILLU M..MALAYALAM LETTER CHILLU LLL
+0D57 ; N # Mc MALAYALAM AU LENGTH MARK
+0D58..0D5E ; N # No [7] MALAYALAM FRACTION ONE ONE-HUNDRED-AND-SIXTIETH..MALAYALAM FRACTION ONE FIFTH
+0D5F..0D61 ; N # Lo [3] MALAYALAM LETTER ARCHAIC II..MALAYALAM LETTER VOCALIC LL
+0D62..0D63 ; N # Mn [2] MALAYALAM VOWEL SIGN VOCALIC L..MALAYALAM VOWEL SIGN VOCALIC LL
+0D66..0D6F ; N # Nd [10] MALAYALAM DIGIT ZERO..MALAYALAM DIGIT NINE
+0D70..0D78 ; N # No [9] MALAYALAM NUMBER TEN..MALAYALAM FRACTION THREE SIXTEENTHS
+0D79 ; N # So MALAYALAM DATE MARK
+0D7A..0D7F ; N # Lo [6] MALAYALAM LETTER CHILLU NN..MALAYALAM LETTER CHILLU K
+0D81 ; N # Mn SINHALA SIGN CANDRABINDU
+0D82..0D83 ; N # Mc [2] SINHALA SIGN ANUSVARAYA..SINHALA SIGN VISARGAYA
+0D85..0D96 ; N # Lo [18] SINHALA LETTER AYANNA..SINHALA LETTER AUYANNA
+0D9A..0DB1 ; N # Lo [24] SINHALA LETTER ALPAPRAANA KAYANNA..SINHALA LETTER DANTAJA NAYANNA
+0DB3..0DBB ; N # Lo [9] SINHALA LETTER SANYAKA DAYANNA..SINHALA LETTER RAYANNA
+0DBD ; N # Lo SINHALA LETTER DANTAJA LAYANNA
+0DC0..0DC6 ; N # Lo [7] SINHALA LETTER VAYANNA..SINHALA LETTER FAYANNA
+0DCA ; N # Mn SINHALA SIGN AL-LAKUNA
+0DCF..0DD1 ; N # Mc [3] SINHALA VOWEL SIGN AELA-PILLA..SINHALA VOWEL SIGN DIGA AEDA-PILLA
+0DD2..0DD4 ; N # Mn [3] SINHALA VOWEL SIGN KETTI IS-PILLA..SINHALA VOWEL SIGN KETTI PAA-PILLA
+0DD6 ; N # Mn SINHALA VOWEL SIGN DIGA PAA-PILLA
+0DD8..0DDF ; N # Mc [8] SINHALA VOWEL SIGN GAETTA-PILLA..SINHALA VOWEL SIGN GAYANUKITTA
+0DE6..0DEF ; N # Nd [10] SINHALA LITH DIGIT ZERO..SINHALA LITH DIGIT NINE
+0DF2..0DF3 ; N # Mc [2] SINHALA VOWEL SIGN DIGA GAETTA-PILLA..SINHALA VOWEL SIGN DIGA GAYANUKITTA
+0DF4 ; N # Po SINHALA PUNCTUATION KUNDDALIYA
+0E01..0E30 ; N # Lo [48] THAI CHARACTER KO KAI..THAI CHARACTER SARA A
+0E31 ; N # Mn THAI CHARACTER MAI HAN-AKAT
+0E32..0E33 ; N # Lo [2] THAI CHARACTER SARA AA..THAI CHARACTER SARA AM
+0E34..0E3A ; N # Mn [7] THAI CHARACTER SARA I..THAI CHARACTER PHINTHU
+0E3F ; N # Sc THAI CURRENCY SYMBOL BAHT
+0E40..0E45 ; N # Lo [6] THAI CHARACTER SARA E..THAI CHARACTER LAKKHANGYAO
+0E46 ; N # Lm THAI CHARACTER MAIYAMOK
+0E47..0E4E ; N # Mn [8] THAI CHARACTER MAITAIKHU..THAI CHARACTER YAMAKKAN
+0E4F ; N # Po THAI CHARACTER FONGMAN
+0E50..0E59 ; N # Nd [10] THAI DIGIT ZERO..THAI DIGIT NINE
+0E5A..0E5B ; N # Po [2] THAI CHARACTER ANGKHANKHU..THAI CHARACTER KHOMUT
+0E81..0E82 ; N # Lo [2] LAO LETTER KO..LAO LETTER KHO SUNG
+0E84 ; N # Lo LAO LETTER KHO TAM
+0E86..0E8A ; N # Lo [5] LAO LETTER PALI GHA..LAO LETTER SO TAM
+0E8C..0EA3 ; N # Lo [24] LAO LETTER PALI JHA..LAO LETTER LO LING
+0EA5 ; N # Lo LAO LETTER LO LOOT
+0EA7..0EB0 ; N # Lo [10] LAO LETTER WO..LAO VOWEL SIGN A
+0EB1 ; N # Mn LAO VOWEL SIGN MAI KAN
+0EB2..0EB3 ; N # Lo [2] LAO VOWEL SIGN AA..LAO VOWEL SIGN AM
+0EB4..0EBC ; N # Mn [9] LAO VOWEL SIGN I..LAO SEMIVOWEL SIGN LO
+0EBD ; N # Lo LAO SEMIVOWEL SIGN NYO
+0EC0..0EC4 ; N # Lo [5] LAO VOWEL SIGN E..LAO VOWEL SIGN AI
+0EC6 ; N # Lm LAO KO LA
+0EC8..0ECE ; N # Mn [7] LAO TONE MAI EK..LAO YAMAKKAN
+0ED0..0ED9 ; N # Nd [10] LAO DIGIT ZERO..LAO DIGIT NINE
+0EDC..0EDF ; N # Lo [4] LAO HO NO..LAO LETTER KHMU NYO
+0F00 ; N # Lo TIBETAN SYLLABLE OM
+0F01..0F03 ; N # So [3] TIBETAN MARK GTER YIG MGO TRUNCATED A..TIBETAN MARK GTER YIG MGO -UM GTER TSHEG MA
+0F04..0F12 ; N # Po [15] TIBETAN MARK INITIAL YIG MGO MDUN MA..TIBETAN MARK RGYA GRAM SHAD
+0F13 ; N # So TIBETAN MARK CARET -DZUD RTAGS ME LONG CAN
+0F14 ; N # Po TIBETAN MARK GTER TSHEG
+0F15..0F17 ; N # So [3] TIBETAN LOGOTYPE SIGN CHAD RTAGS..TIBETAN ASTROLOGICAL SIGN SGRA GCAN -CHAR RTAGS
+0F18..0F19 ; N # Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS
+0F1A..0F1F ; N # So [6] TIBETAN SIGN RDEL DKAR GCIG..TIBETAN SIGN RDEL DKAR RDEL NAG
+0F20..0F29 ; N # Nd [10] TIBETAN DIGIT ZERO..TIBETAN DIGIT NINE
+0F2A..0F33 ; N # No [10] TIBETAN DIGIT HALF ONE..TIBETAN DIGIT HALF ZERO
+0F34 ; N # So TIBETAN MARK BSDUS RTAGS
+0F35 ; N # Mn TIBETAN MARK NGAS BZUNG NYI ZLA
+0F36 ; N # So TIBETAN MARK CARET -DZUD RTAGS BZHI MIG CAN
+0F37 ; N # Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS
+0F38 ; N # So TIBETAN MARK CHE MGO
+0F39 ; N # Mn TIBETAN MARK TSA -PHRU
+0F3A ; N # Ps TIBETAN MARK GUG RTAGS GYON
+0F3B ; N # Pe TIBETAN MARK GUG RTAGS GYAS
+0F3C ; N # Ps TIBETAN MARK ANG KHANG GYON
+0F3D ; N # Pe TIBETAN MARK ANG KHANG GYAS
+0F3E..0F3F ; N # Mc [2] TIBETAN SIGN YAR TSHES..TIBETAN SIGN MAR TSHES
+0F40..0F47 ; N # Lo [8] TIBETAN LETTER KA..TIBETAN LETTER JA
+0F49..0F6C ; N # Lo [36] TIBETAN LETTER NYA..TIBETAN LETTER RRA
+0F71..0F7E ; N # Mn [14] TIBETAN VOWEL SIGN AA..TIBETAN SIGN RJES SU NGA RO
+0F7F ; N # Mc TIBETAN SIGN RNAM BCAD
+0F80..0F84 ; N # Mn [5] TIBETAN VOWEL SIGN REVERSED I..TIBETAN MARK HALANTA
+0F85 ; N # Po TIBETAN MARK PALUTA
+0F86..0F87 ; N # Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS
+0F88..0F8C ; N # Lo [5] TIBETAN SIGN LCE TSA CAN..TIBETAN SIGN INVERTED MCHU CAN
+0F8D..0F97 ; N # Mn [11] TIBETAN SUBJOINED SIGN LCE TSA CAN..TIBETAN SUBJOINED LETTER JA
+0F99..0FBC ; N # Mn [36] TIBETAN SUBJOINED LETTER NYA..TIBETAN SUBJOINED LETTER FIXED-FORM RA
+0FBE..0FC5 ; N # So [8] TIBETAN KU RU KHA..TIBETAN SYMBOL RDO RJE
+0FC6 ; N # Mn TIBETAN SYMBOL PADMA GDAN
+0FC7..0FCC ; N # So [6] TIBETAN SYMBOL RDO RJE RGYA GRAM..TIBETAN SYMBOL NOR BU BZHI -KHYIL
+0FCE..0FCF ; N # So [2] TIBETAN SIGN RDEL NAG RDEL DKAR..TIBETAN SIGN RDEL NAG GSUM
+0FD0..0FD4 ; N # Po [5] TIBETAN MARK BSKA- SHOG GI MGO RGYAN..TIBETAN MARK CLOSING BRDA RNYING YIG MGO SGAB MA
+0FD5..0FD8 ; N # So [4] RIGHT-FACING SVASTI SIGN..LEFT-FACING SVASTI SIGN WITH DOTS
+0FD9..0FDA ; N # Po [2] TIBETAN MARK LEADING MCHAN RTAGS..TIBETAN MARK TRAILING MCHAN RTAGS
+1000..102A ; N # Lo [43] MYANMAR LETTER KA..MYANMAR LETTER AU
+102B..102C ; N # Mc [2] MYANMAR VOWEL SIGN TALL AA..MYANMAR VOWEL SIGN AA
+102D..1030 ; N # Mn [4] MYANMAR VOWEL SIGN I..MYANMAR VOWEL SIGN UU
+1031 ; N # Mc MYANMAR VOWEL SIGN E
+1032..1037 ; N # Mn [6] MYANMAR VOWEL SIGN AI..MYANMAR SIGN DOT BELOW
+1038 ; N # Mc MYANMAR SIGN VISARGA
+1039..103A ; N # Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT
+103B..103C ; N # Mc [2] MYANMAR CONSONANT SIGN MEDIAL YA..MYANMAR CONSONANT SIGN MEDIAL RA
+103D..103E ; N # Mn [2] MYANMAR CONSONANT SIGN MEDIAL WA..MYANMAR CONSONANT SIGN MEDIAL HA
+103F ; N # Lo MYANMAR LETTER GREAT SA
+1040..1049 ; N # Nd [10] MYANMAR DIGIT ZERO..MYANMAR DIGIT NINE
+104A..104F ; N # Po [6] MYANMAR SIGN LITTLE SECTION..MYANMAR SYMBOL GENITIVE
+1050..1055 ; N # Lo [6] MYANMAR LETTER SHA..MYANMAR LETTER VOCALIC LL
+1056..1057 ; N # Mc [2] MYANMAR VOWEL SIGN VOCALIC R..MYANMAR VOWEL SIGN VOCALIC RR
+1058..1059 ; N # Mn [2] MYANMAR VOWEL SIGN VOCALIC L..MYANMAR VOWEL SIGN VOCALIC LL
+105A..105D ; N # Lo [4] MYANMAR LETTER MON NGA..MYANMAR LETTER MON BBE
+105E..1060 ; N # Mn [3] MYANMAR CONSONANT SIGN MON MEDIAL NA..MYANMAR CONSONANT SIGN MON MEDIAL LA
+1061 ; N # Lo MYANMAR LETTER SGAW KAREN SHA
+1062..1064 ; N # Mc [3] MYANMAR VOWEL SIGN SGAW KAREN EU..MYANMAR TONE MARK SGAW KAREN KE PHO
+1065..1066 ; N # Lo [2] MYANMAR LETTER WESTERN PWO KAREN THA..MYANMAR LETTER WESTERN PWO KAREN PWA
+1067..106D ; N # Mc [7] MYANMAR VOWEL SIGN WESTERN PWO KAREN EU..MYANMAR SIGN WESTERN PWO KAREN TONE-5
+106E..1070 ; N # Lo [3] MYANMAR LETTER EASTERN PWO KAREN NNA..MYANMAR LETTER EASTERN PWO KAREN GHWA
+1071..1074 ; N # Mn [4] MYANMAR VOWEL SIGN GEBA KAREN I..MYANMAR VOWEL SIGN KAYAH EE
+1075..1081 ; N # Lo [13] MYANMAR LETTER SHAN KA..MYANMAR LETTER SHAN HA
+1082 ; N # Mn MYANMAR CONSONANT SIGN SHAN MEDIAL WA
+1083..1084 ; N # Mc [2] MYANMAR VOWEL SIGN SHAN AA..MYANMAR VOWEL SIGN SHAN E
+1085..1086 ; N # Mn [2] MYANMAR VOWEL SIGN SHAN E ABOVE..MYANMAR VOWEL SIGN SHAN FINAL Y
+1087..108C ; N # Mc [6] MYANMAR SIGN SHAN TONE-2..MYANMAR SIGN SHAN COUNCIL TONE-3
+108D ; N # Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE
+108E ; N # Lo MYANMAR LETTER RUMAI PALAUNG FA
+108F ; N # Mc MYANMAR SIGN RUMAI PALAUNG TONE-5
+1090..1099 ; N # Nd [10] MYANMAR SHAN DIGIT ZERO..MYANMAR SHAN DIGIT NINE
+109A..109C ; N # Mc [3] MYANMAR SIGN KHAMTI TONE-1..MYANMAR VOWEL SIGN AITON A
+109D ; N # Mn MYANMAR VOWEL SIGN AITON AI
+109E..109F ; N # So [2] MYANMAR SYMBOL SHAN ONE..MYANMAR SYMBOL SHAN EXCLAMATION
+10A0..10C5 ; N # Lu [38] GEORGIAN CAPITAL LETTER AN..GEORGIAN CAPITAL LETTER HOE
+10C7 ; N # Lu GEORGIAN CAPITAL LETTER YN
+10CD ; N # Lu GEORGIAN CAPITAL LETTER AEN
+10D0..10FA ; N # Ll [43] GEORGIAN LETTER AN..GEORGIAN LETTER AIN
+10FB ; N # Po GEORGIAN PARAGRAPH SEPARATOR
+10FC ; N # Lm MODIFIER LETTER GEORGIAN NAR
+10FD..10FF ; N # Ll [3] GEORGIAN LETTER AEN..GEORGIAN LETTER LABIAL SIGN
+1100..115F ; W # Lo [96] HANGUL CHOSEONG KIYEOK..HANGUL CHOSEONG FILLER
+1160..11FF ; N # Lo [160] HANGUL JUNGSEONG FILLER..HANGUL JONGSEONG SSANGNIEUN
+1200..1248 ; N # Lo [73] ETHIOPIC SYLLABLE HA..ETHIOPIC SYLLABLE QWA
+124A..124D ; N # Lo [4] ETHIOPIC SYLLABLE QWI..ETHIOPIC SYLLABLE QWE
+1250..1256 ; N # Lo [7] ETHIOPIC SYLLABLE QHA..ETHIOPIC SYLLABLE QHO
+1258 ; N # Lo ETHIOPIC SYLLABLE QHWA
+125A..125D ; N # Lo [4] ETHIOPIC SYLLABLE QHWI..ETHIOPIC SYLLABLE QHWE
+1260..1288 ; N # Lo [41] ETHIOPIC SYLLABLE BA..ETHIOPIC SYLLABLE XWA
+128A..128D ; N # Lo [4] ETHIOPIC SYLLABLE XWI..ETHIOPIC SYLLABLE XWE
+1290..12B0 ; N # Lo [33] ETHIOPIC SYLLABLE NA..ETHIOPIC SYLLABLE KWA
+12B2..12B5 ; N # Lo [4] ETHIOPIC SYLLABLE KWI..ETHIOPIC SYLLABLE KWE
+12B8..12BE ; N # Lo [7] ETHIOPIC SYLLABLE KXA..ETHIOPIC SYLLABLE KXO
+12C0 ; N # Lo ETHIOPIC SYLLABLE KXWA
+12C2..12C5 ; N # Lo [4] ETHIOPIC SYLLABLE KXWI..ETHIOPIC SYLLABLE KXWE
+12C8..12D6 ; N # Lo [15] ETHIOPIC SYLLABLE WA..ETHIOPIC SYLLABLE PHARYNGEAL O
+12D8..1310 ; N # Lo [57] ETHIOPIC SYLLABLE ZA..ETHIOPIC SYLLABLE GWA
+1312..1315 ; N # Lo [4] ETHIOPIC SYLLABLE GWI..ETHIOPIC SYLLABLE GWE
+1318..135A ; N # Lo [67] ETHIOPIC SYLLABLE GGA..ETHIOPIC SYLLABLE FYA
+135D..135F ; N # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK
+1360..1368 ; N # Po [9] ETHIOPIC SECTION MARK..ETHIOPIC PARAGRAPH SEPARATOR
+1369..137C ; N # No [20] ETHIOPIC DIGIT ONE..ETHIOPIC NUMBER TEN THOUSAND
+1380..138F ; N # Lo [16] ETHIOPIC SYLLABLE SEBATBEIT MWA..ETHIOPIC SYLLABLE PWE
+1390..1399 ; N # So [10] ETHIOPIC TONAL MARK YIZET..ETHIOPIC TONAL MARK KURT
+13A0..13F5 ; N # Lu [86] CHEROKEE LETTER A..CHEROKEE LETTER MV
+13F8..13FD ; N # Ll [6] CHEROKEE SMALL LETTER YE..CHEROKEE SMALL LETTER MV
+1400 ; N # Pd CANADIAN SYLLABICS HYPHEN
+1401..166C ; N # Lo [620] CANADIAN SYLLABICS E..CANADIAN SYLLABICS CARRIER TTSA
+166D ; N # So CANADIAN SYLLABICS CHI SIGN
+166E ; N # Po CANADIAN SYLLABICS FULL STOP
+166F..167F ; N # Lo [17] CANADIAN SYLLABICS QAI..CANADIAN SYLLABICS BLACKFOOT W
+1680 ; N # Zs OGHAM SPACE MARK
+1681..169A ; N # Lo [26] OGHAM LETTER BEITH..OGHAM LETTER PEITH
+169B ; N # Ps OGHAM FEATHER MARK
+169C ; N # Pe OGHAM REVERSED FEATHER MARK
+16A0..16EA ; N # Lo [75] RUNIC LETTER FEHU FEOH FE F..RUNIC LETTER X
+16EB..16ED ; N # Po [3] RUNIC SINGLE PUNCTUATION..RUNIC CROSS PUNCTUATION
+16EE..16F0 ; N # Nl [3] RUNIC ARLAUG SYMBOL..RUNIC BELGTHOR SYMBOL
+16F1..16F8 ; N # Lo [8] RUNIC LETTER K..RUNIC LETTER FRANKS CASKET AESC
+1700..1711 ; N # Lo [18] TAGALOG LETTER A..TAGALOG LETTER HA
+1712..1714 ; N # Mn [3] TAGALOG VOWEL SIGN I..TAGALOG SIGN VIRAMA
+1715 ; N # Mc TAGALOG SIGN PAMUDPOD
+171F ; N # Lo TAGALOG LETTER ARCHAIC RA
+1720..1731 ; N # Lo [18] HANUNOO LETTER A..HANUNOO LETTER HA
+1732..1733 ; N # Mn [2] HANUNOO VOWEL SIGN I..HANUNOO VOWEL SIGN U
+1734 ; N # Mc HANUNOO SIGN PAMUDPOD
+1735..1736 ; N # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION
+1740..1751 ; N # Lo [18] BUHID LETTER A..BUHID LETTER HA
+1752..1753 ; N # Mn [2] BUHID VOWEL SIGN I..BUHID VOWEL SIGN U
+1760..176C ; N # Lo [13] TAGBANWA LETTER A..TAGBANWA LETTER YA
+176E..1770 ; N # Lo [3] TAGBANWA LETTER LA..TAGBANWA LETTER SA
+1772..1773 ; N # Mn [2] TAGBANWA VOWEL SIGN I..TAGBANWA VOWEL SIGN U
+1780..17B3 ; N # Lo [52] KHMER LETTER KA..KHMER INDEPENDENT VOWEL QAU
+17B4..17B5 ; N # Mn [2] KHMER VOWEL INHERENT AQ..KHMER VOWEL INHERENT AA
+17B6 ; N # Mc KHMER VOWEL SIGN AA
+17B7..17BD ; N # Mn [7] KHMER VOWEL SIGN I..KHMER VOWEL SIGN UA
+17BE..17C5 ; N # Mc [8] KHMER VOWEL SIGN OE..KHMER VOWEL SIGN AU
+17C6 ; N # Mn KHMER SIGN NIKAHIT
+17C7..17C8 ; N # Mc [2] KHMER SIGN REAHMUK..KHMER SIGN YUUKALEAPINTU
+17C9..17D3 ; N # Mn [11] KHMER SIGN MUUSIKATOAN..KHMER SIGN BATHAMASAT
+17D4..17D6 ; N # Po [3] KHMER SIGN KHAN..KHMER SIGN CAMNUC PII KUUH
+17D7 ; N # Lm KHMER SIGN LEK TOO
+17D8..17DA ; N # Po [3] KHMER SIGN BEYYAL..KHMER SIGN KOOMUUT
+17DB ; N # Sc KHMER CURRENCY SYMBOL RIEL
+17DC ; N # Lo KHMER SIGN AVAKRAHASANYA
+17DD ; N # Mn KHMER SIGN ATTHACAN
+17E0..17E9 ; N # Nd [10] KHMER DIGIT ZERO..KHMER DIGIT NINE
+17F0..17F9 ; N # No [10] KHMER SYMBOL LEK ATTAK SON..KHMER SYMBOL LEK ATTAK PRAM-BUON
+1800..1805 ; N # Po [6] MONGOLIAN BIRGA..MONGOLIAN FOUR DOTS
+1806 ; N # Pd MONGOLIAN TODO SOFT HYPHEN
+1807..180A ; N # Po [4] MONGOLIAN SIBE SYLLABLE BOUNDARY MARKER..MONGOLIAN NIRUGU
+180B..180D ; N # Mn [3] MONGOLIAN FREE VARIATION SELECTOR ONE..MONGOLIAN FREE VARIATION SELECTOR THREE
+180E ; N # Cf MONGOLIAN VOWEL SEPARATOR
+180F ; N # Mn MONGOLIAN FREE VARIATION SELECTOR FOUR
+1810..1819 ; N # Nd [10] MONGOLIAN DIGIT ZERO..MONGOLIAN DIGIT NINE
+1820..1842 ; N # Lo [35] MONGOLIAN LETTER A..MONGOLIAN LETTER CHI
+1843 ; N # Lm MONGOLIAN LETTER TODO LONG VOWEL SIGN
+1844..1878 ; N # Lo [53] MONGOLIAN LETTER TODO E..MONGOLIAN LETTER CHA WITH TWO DOTS
+1880..1884 ; N # Lo [5] MONGOLIAN LETTER ALI GALI ANUSVARA ONE..MONGOLIAN LETTER ALI GALI INVERTED UBADAMA
+1885..1886 ; N # Mn [2] MONGOLIAN LETTER ALI GALI BALUDA..MONGOLIAN LETTER ALI GALI THREE BALUDA
+1887..18A8 ; N # Lo [34] MONGOLIAN LETTER ALI GALI A..MONGOLIAN LETTER MANCHU ALI GALI BHA
+18A9 ; N # Mn MONGOLIAN LETTER ALI GALI DAGALGA
+18AA ; N # Lo MONGOLIAN LETTER MANCHU ALI GALI LHA
+18B0..18F5 ; N # Lo [70] CANADIAN SYLLABICS OY..CANADIAN SYLLABICS CARRIER DENTAL S
+1900..191E ; N # Lo [31] LIMBU VOWEL-CARRIER LETTER..LIMBU LETTER TRA
+1920..1922 ; N # Mn [3] LIMBU VOWEL SIGN A..LIMBU VOWEL SIGN U
+1923..1926 ; N # Mc [4] LIMBU VOWEL SIGN EE..LIMBU VOWEL SIGN AU
+1927..1928 ; N # Mn [2] LIMBU VOWEL SIGN E..LIMBU VOWEL SIGN O
+1929..192B ; N # Mc [3] LIMBU SUBJOINED LETTER YA..LIMBU SUBJOINED LETTER WA
+1930..1931 ; N # Mc [2] LIMBU SMALL LETTER KA..LIMBU SMALL LETTER NGA
+1932 ; N # Mn LIMBU SMALL LETTER ANUSVARA
+1933..1938 ; N # Mc [6] LIMBU SMALL LETTER TA..LIMBU SMALL LETTER LA
+1939..193B ; N # Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I
+1940 ; N # So LIMBU SIGN LOO
+1944..1945 ; N # Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK
+1946..194F ; N # Nd [10] LIMBU DIGIT ZERO..LIMBU DIGIT NINE
+1950..196D ; N # Lo [30] TAI LE LETTER KA..TAI LE LETTER AI
+1970..1974 ; N # Lo [5] TAI LE LETTER TONE-2..TAI LE LETTER TONE-6
+1980..19AB ; N # Lo [44] NEW TAI LUE LETTER HIGH QA..NEW TAI LUE LETTER LOW SUA
+19B0..19C9 ; N # Lo [26] NEW TAI LUE VOWEL SIGN VOWEL SHORTENER..NEW TAI LUE TONE MARK-2
+19D0..19D9 ; N # Nd [10] NEW TAI LUE DIGIT ZERO..NEW TAI LUE DIGIT NINE
+19DA ; N # No NEW TAI LUE THAM DIGIT ONE
+19DE..19DF ; N # So [2] NEW TAI LUE SIGN LAE..NEW TAI LUE SIGN LAEV
+19E0..19FF ; N # So [32] KHMER SYMBOL PATHAMASAT..KHMER SYMBOL DAP-PRAM ROC
+1A00..1A16 ; N # Lo [23] BUGINESE LETTER KA..BUGINESE LETTER HA
+1A17..1A18 ; N # Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U
+1A19..1A1A ; N # Mc [2] BUGINESE VOWEL SIGN E..BUGINESE VOWEL SIGN O
+1A1B ; N # Mn BUGINESE VOWEL SIGN AE
+1A1E..1A1F ; N # Po [2] BUGINESE PALLAWA..BUGINESE END OF SECTION
+1A20..1A54 ; N # Lo [53] TAI THAM LETTER HIGH KA..TAI THAM LETTER GREAT SA
+1A55 ; N # Mc TAI THAM CONSONANT SIGN MEDIAL RA
+1A56 ; N # Mn TAI THAM CONSONANT SIGN MEDIAL LA
+1A57 ; N # Mc TAI THAM CONSONANT SIGN LA TANG LAI
+1A58..1A5E ; N # Mn [7] TAI THAM SIGN MAI KANG LAI..TAI THAM CONSONANT SIGN SA
+1A60 ; N # Mn TAI THAM SIGN SAKOT
+1A61 ; N # Mc TAI THAM VOWEL SIGN A
+1A62 ; N # Mn TAI THAM VOWEL SIGN MAI SAT
+1A63..1A64 ; N # Mc [2] TAI THAM VOWEL SIGN AA..TAI THAM VOWEL SIGN TALL AA
+1A65..1A6C ; N # Mn [8] TAI THAM VOWEL SIGN I..TAI THAM VOWEL SIGN OA BELOW
+1A6D..1A72 ; N # Mc [6] TAI THAM VOWEL SIGN OY..TAI THAM VOWEL SIGN THAM AI
+1A73..1A7C ; N # Mn [10] TAI THAM VOWEL SIGN OA ABOVE..TAI THAM SIGN KHUEN-LUE KARAN
+1A7F ; N # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT
+1A80..1A89 ; N # Nd [10] TAI THAM HORA DIGIT ZERO..TAI THAM HORA DIGIT NINE
+1A90..1A99 ; N # Nd [10] TAI THAM THAM DIGIT ZERO..TAI THAM THAM DIGIT NINE
+1AA0..1AA6 ; N # Po [7] TAI THAM SIGN WIANG..TAI THAM SIGN REVERSED ROTATED RANA
+1AA7 ; N # Lm TAI THAM SIGN MAI YAMOK
+1AA8..1AAD ; N # Po [6] TAI THAM SIGN KAAN..TAI THAM SIGN CAANG
+1AB0..1ABD ; N # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
+1ABE ; N # Me COMBINING PARENTHESES OVERLAY
+1ABF..1ACE ; N # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T
+1B00..1B03 ; N # Mn [4] BALINESE SIGN ULU RICEM..BALINESE SIGN SURANG
+1B04 ; N # Mc BALINESE SIGN BISAH
+1B05..1B33 ; N # Lo [47] BALINESE LETTER AKARA..BALINESE LETTER HA
+1B34 ; N # Mn BALINESE SIGN REREKAN
+1B35 ; N # Mc BALINESE VOWEL SIGN TEDUNG
+1B36..1B3A ; N # Mn [5] BALINESE VOWEL SIGN ULU..BALINESE VOWEL SIGN RA REPA
+1B3B ; N # Mc BALINESE VOWEL SIGN RA REPA TEDUNG
+1B3C ; N # Mn BALINESE VOWEL SIGN LA LENGA
+1B3D..1B41 ; N # Mc [5] BALINESE VOWEL SIGN LA LENGA TEDUNG..BALINESE VOWEL SIGN TALING REPA TEDUNG
+1B42 ; N # Mn BALINESE VOWEL SIGN PEPET
+1B43..1B44 ; N # Mc [2] BALINESE VOWEL SIGN PEPET TEDUNG..BALINESE ADEG ADEG
+1B45..1B4C ; N # Lo [8] BALINESE LETTER KAF SASAK..BALINESE LETTER ARCHAIC JNYA
+1B50..1B59 ; N # Nd [10] BALINESE DIGIT ZERO..BALINESE DIGIT NINE
+1B5A..1B60 ; N # Po [7] BALINESE PANTI..BALINESE PAMENENG
+1B61..1B6A ; N # So [10] BALINESE MUSICAL SYMBOL DONG..BALINESE MUSICAL SYMBOL DANG GEDE
+1B6B..1B73 ; N # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
+1B74..1B7C ; N # So [9] BALINESE MUSICAL SYMBOL RIGHT-HAND OPEN DUG..BALINESE MUSICAL SYMBOL LEFT-HAND OPEN PING
+1B7D..1B7E ; N # Po [2] BALINESE PANTI LANTANG..BALINESE PAMADA LANTANG
+1B80..1B81 ; N # Mn [2] SUNDANESE SIGN PANYECEK..SUNDANESE SIGN PANGLAYAR
+1B82 ; N # Mc SUNDANESE SIGN PANGWISAD
+1B83..1BA0 ; N # Lo [30] SUNDANESE LETTER A..SUNDANESE LETTER HA
+1BA1 ; N # Mc SUNDANESE CONSONANT SIGN PAMINGKAL
+1BA2..1BA5 ; N # Mn [4] SUNDANESE CONSONANT SIGN PANYAKRA..SUNDANESE VOWEL SIGN PANYUKU
+1BA6..1BA7 ; N # Mc [2] SUNDANESE VOWEL SIGN PANAELAENG..SUNDANESE VOWEL SIGN PANOLONG
+1BA8..1BA9 ; N # Mn [2] SUNDANESE VOWEL SIGN PAMEPET..SUNDANESE VOWEL SIGN PANEULEUNG
+1BAA ; N # Mc SUNDANESE SIGN PAMAAEH
+1BAB..1BAD ; N # Mn [3] SUNDANESE SIGN VIRAMA..SUNDANESE CONSONANT SIGN PASANGAN WA
+1BAE..1BAF ; N # Lo [2] SUNDANESE LETTER KHA..SUNDANESE LETTER SYA
+1BB0..1BB9 ; N # Nd [10] SUNDANESE DIGIT ZERO..SUNDANESE DIGIT NINE
+1BBA..1BBF ; N # Lo [6] SUNDANESE AVAGRAHA..SUNDANESE LETTER FINAL M
+1BC0..1BE5 ; N # Lo [38] BATAK LETTER A..BATAK LETTER U
+1BE6 ; N # Mn BATAK SIGN TOMPI
+1BE7 ; N # Mc BATAK VOWEL SIGN E
+1BE8..1BE9 ; N # Mn [2] BATAK VOWEL SIGN PAKPAK E..BATAK VOWEL SIGN EE
+1BEA..1BEC ; N # Mc [3] BATAK VOWEL SIGN I..BATAK VOWEL SIGN O
+1BED ; N # Mn BATAK VOWEL SIGN KARO O
+1BEE ; N # Mc BATAK VOWEL SIGN U
+1BEF..1BF1 ; N # Mn [3] BATAK VOWEL SIGN U FOR SIMALUNGUN SA..BATAK CONSONANT SIGN H
+1BF2..1BF3 ; N # Mc [2] BATAK PANGOLAT..BATAK PANONGONAN
+1BFC..1BFF ; N # Po [4] BATAK SYMBOL BINDU NA METEK..BATAK SYMBOL BINDU PANGOLAT
+1C00..1C23 ; N # Lo [36] LEPCHA LETTER KA..LEPCHA LETTER A
+1C24..1C2B ; N # Mc [8] LEPCHA SUBJOINED LETTER YA..LEPCHA VOWEL SIGN UU
+1C2C..1C33 ; N # Mn [8] LEPCHA VOWEL SIGN E..LEPCHA CONSONANT SIGN T
+1C34..1C35 ; N # Mc [2] LEPCHA CONSONANT SIGN NYIN-DO..LEPCHA CONSONANT SIGN KANG
+1C36..1C37 ; N # Mn [2] LEPCHA SIGN RAN..LEPCHA SIGN NUKTA
+1C3B..1C3F ; N # Po [5] LEPCHA PUNCTUATION TA-ROL..LEPCHA PUNCTUATION TSHOOK
+1C40..1C49 ; N # Nd [10] LEPCHA DIGIT ZERO..LEPCHA DIGIT NINE
+1C4D..1C4F ; N # Lo [3] LEPCHA LETTER TTA..LEPCHA LETTER DDA
+1C50..1C59 ; N # Nd [10] OL CHIKI DIGIT ZERO..OL CHIKI DIGIT NINE
+1C5A..1C77 ; N # Lo [30] OL CHIKI LETTER LA..OL CHIKI LETTER OH
+1C78..1C7D ; N # Lm [6] OL CHIKI MU TTUDDAG..OL CHIKI AHAD
+1C7E..1C7F ; N # Po [2] OL CHIKI PUNCTUATION MUCAAD..OL CHIKI PUNCTUATION DOUBLE MUCAAD
+1C80..1C88 ; N # Ll [9] CYRILLIC SMALL LETTER ROUNDED VE..CYRILLIC SMALL LETTER UNBLENDED UK
+1C90..1CBA ; N # Lu [43] GEORGIAN MTAVRULI CAPITAL LETTER AN..GEORGIAN MTAVRULI CAPITAL LETTER AIN
+1CBD..1CBF ; N # Lu [3] GEORGIAN MTAVRULI CAPITAL LETTER AEN..GEORGIAN MTAVRULI CAPITAL LETTER LABIAL SIGN
+1CC0..1CC7 ; N # Po [8] SUNDANESE PUNCTUATION BINDU SURYA..SUNDANESE PUNCTUATION BINDU BA SATANGA
+1CD0..1CD2 ; N # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
+1CD3 ; N # Po VEDIC SIGN NIHSHVASA
+1CD4..1CE0 ; N # Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA
+1CE1 ; N # Mc VEDIC TONE ATHARVAVEDIC INDEPENDENT SVARITA
+1CE2..1CE8 ; N # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL
+1CE9..1CEC ; N # Lo [4] VEDIC SIGN ANUSVARA ANTARGOMUKHA..VEDIC SIGN ANUSVARA VAMAGOMUKHA WITH TAIL
+1CED ; N # Mn VEDIC SIGN TIRYAK
+1CEE..1CF3 ; N # Lo [6] VEDIC SIGN HEXIFORM LONG ANUSVARA..VEDIC SIGN ROTATED ARDHAVISARGA
+1CF4 ; N # Mn VEDIC TONE CANDRA ABOVE
+1CF5..1CF6 ; N # Lo [2] VEDIC SIGN JIHVAMULIYA..VEDIC SIGN UPADHMANIYA
+1CF7 ; N # Mc VEDIC SIGN ATIKRAMA
+1CF8..1CF9 ; N # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
+1CFA ; N # Lo VEDIC SIGN DOUBLE ANUSVARA ANTARGOMUKHA
+1D00..1D2B ; N # Ll [44] LATIN LETTER SMALL CAPITAL A..CYRILLIC LETTER SMALL CAPITAL EL
+1D2C..1D6A ; N # Lm [63] MODIFIER LETTER CAPITAL A..GREEK SUBSCRIPT SMALL LETTER CHI
+1D6B..1D77 ; N # Ll [13] LATIN SMALL LETTER UE..LATIN SMALL LETTER TURNED G
+1D78 ; N # Lm MODIFIER LETTER CYRILLIC EN
+1D79..1D7F ; N # Ll [7] LATIN SMALL LETTER INSULAR G..LATIN SMALL LETTER UPSILON WITH STROKE
+1D80..1D9A ; N # Ll [27] LATIN SMALL LETTER B WITH PALATAL HOOK..LATIN SMALL LETTER EZH WITH RETROFLEX HOOK
+1D9B..1DBF ; N # Lm [37] MODIFIER LETTER SMALL TURNED ALPHA..MODIFIER LETTER SMALL THETA
+1DC0..1DFF ; N # Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
+1E00..1EFF ; N # L& [256] LATIN CAPITAL LETTER A WITH RING BELOW..LATIN SMALL LETTER Y WITH LOOP
+1F00..1F15 ; N # L& [22] GREEK SMALL LETTER ALPHA WITH PSILI..GREEK SMALL LETTER EPSILON WITH DASIA AND OXIA
+1F18..1F1D ; N # Lu [6] GREEK CAPITAL LETTER EPSILON WITH PSILI..GREEK CAPITAL LETTER EPSILON WITH DASIA AND OXIA
+1F20..1F45 ; N # L& [38] GREEK SMALL LETTER ETA WITH PSILI..GREEK SMALL LETTER OMICRON WITH DASIA AND OXIA
+1F48..1F4D ; N # Lu [6] GREEK CAPITAL LETTER OMICRON WITH PSILI..GREEK CAPITAL LETTER OMICRON WITH DASIA AND OXIA
+1F50..1F57 ; N # Ll [8] GREEK SMALL LETTER UPSILON WITH PSILI..GREEK SMALL LETTER UPSILON WITH DASIA AND PERISPOMENI
+1F59 ; N # Lu GREEK CAPITAL LETTER UPSILON WITH DASIA
+1F5B ; N # Lu GREEK CAPITAL LETTER UPSILON WITH DASIA AND VARIA
+1F5D ; N # Lu GREEK CAPITAL LETTER UPSILON WITH DASIA AND OXIA
+1F5F..1F7D ; N # L& [31] GREEK CAPITAL LETTER UPSILON WITH DASIA AND PERISPOMENI..GREEK SMALL LETTER OMEGA WITH OXIA
+1F80..1FB4 ; N # L& [53] GREEK SMALL LETTER ALPHA WITH PSILI AND YPOGEGRAMMENI..GREEK SMALL LETTER ALPHA WITH OXIA AND YPOGEGRAMMENI
+1FB6..1FBC ; N # L& [7] GREEK SMALL LETTER ALPHA WITH PERISPOMENI..GREEK CAPITAL LETTER ALPHA WITH PROSGEGRAMMENI
+1FBD ; N # Sk GREEK KORONIS
+1FBE ; N # Ll GREEK PROSGEGRAMMENI
+1FBF..1FC1 ; N # Sk [3] GREEK PSILI..GREEK DIALYTIKA AND PERISPOMENI
+1FC2..1FC4 ; N # Ll [3] GREEK SMALL LETTER ETA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER ETA WITH OXIA AND YPOGEGRAMMENI
+1FC6..1FCC ; N # L& [7] GREEK SMALL LETTER ETA WITH PERISPOMENI..GREEK CAPITAL LETTER ETA WITH PROSGEGRAMMENI
+1FCD..1FCF ; N # Sk [3] GREEK PSILI AND VARIA..GREEK PSILI AND PERISPOMENI
+1FD0..1FD3 ; N # Ll [4] GREEK SMALL LETTER IOTA WITH VRACHY..GREEK SMALL LETTER IOTA WITH DIALYTIKA AND OXIA
+1FD6..1FDB ; N # L& [6] GREEK SMALL LETTER IOTA WITH PERISPOMENI..GREEK CAPITAL LETTER IOTA WITH OXIA
+1FDD..1FDF ; N # Sk [3] GREEK DASIA AND VARIA..GREEK DASIA AND PERISPOMENI
+1FE0..1FEC ; N # L& [13] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA
+1FED..1FEF ; N # Sk [3] GREEK DIALYTIKA AND VARIA..GREEK VARIA
+1FF2..1FF4 ; N # Ll [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
+1FF6..1FFC ; N # L& [7] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
+1FFD..1FFE ; N # Sk [2] GREEK OXIA..GREEK DASIA
+2000..200A ; N # Zs [11] EN QUAD..HAIR SPACE
+200B..200F ; N # Cf [5] ZERO WIDTH SPACE..RIGHT-TO-LEFT MARK
+2010 ; A # Pd HYPHEN
+2011..2012 ; N # Pd [2] NON-BREAKING HYPHEN..FIGURE DASH
+2013..2015 ; A # Pd [3] EN DASH..HORIZONTAL BAR
+2016 ; A # Po DOUBLE VERTICAL LINE
+2017 ; N # Po DOUBLE LOW LINE
+2018 ; A # Pi LEFT SINGLE QUOTATION MARK
+2019 ; A # Pf RIGHT SINGLE QUOTATION MARK
+201A ; N # Ps SINGLE LOW-9 QUOTATION MARK
+201B ; N # Pi SINGLE HIGH-REVERSED-9 QUOTATION MARK
+201C ; A # Pi LEFT DOUBLE QUOTATION MARK
+201D ; A # Pf RIGHT DOUBLE QUOTATION MARK
+201E ; N # Ps DOUBLE LOW-9 QUOTATION MARK
+201F ; N # Pi DOUBLE HIGH-REVERSED-9 QUOTATION MARK
+2020..2022 ; A # Po [3] DAGGER..BULLET
+2023 ; N # Po TRIANGULAR BULLET
+2024..2027 ; A # Po [4] ONE DOT LEADER..HYPHENATION POINT
+2028 ; N # Zl LINE SEPARATOR
+2029 ; N # Zp PARAGRAPH SEPARATOR
+202A..202E ; N # Cf [5] LEFT-TO-RIGHT EMBEDDING..RIGHT-TO-LEFT OVERRIDE
+202F ; N # Zs NARROW NO-BREAK SPACE
+2030 ; A # Po PER MILLE SIGN
+2031 ; N # Po PER TEN THOUSAND SIGN
+2032..2033 ; A # Po [2] PRIME..DOUBLE PRIME
+2034 ; N # Po TRIPLE PRIME
+2035 ; A # Po REVERSED PRIME
+2036..2038 ; N # Po [3] REVERSED DOUBLE PRIME..CARET
+2039 ; N # Pi SINGLE LEFT-POINTING ANGLE QUOTATION MARK
+203A ; N # Pf SINGLE RIGHT-POINTING ANGLE QUOTATION MARK
+203B ; A # Po REFERENCE MARK
+203C..203D ; N # Po [2] DOUBLE EXCLAMATION MARK..INTERROBANG
+203E ; A # Po OVERLINE
+203F..2040 ; N # Pc [2] UNDERTIE..CHARACTER TIE
+2041..2043 ; N # Po [3] CARET INSERTION POINT..HYPHEN BULLET
+2044 ; N # Sm FRACTION SLASH
+2045 ; N # Ps LEFT SQUARE BRACKET WITH QUILL
+2046 ; N # Pe RIGHT SQUARE BRACKET WITH QUILL
+2047..2051 ; N # Po [11] DOUBLE QUESTION MARK..TWO ASTERISKS ALIGNED VERTICALLY
+2052 ; N # Sm COMMERCIAL MINUS SIGN
+2053 ; N # Po SWUNG DASH
+2054 ; N # Pc INVERTED UNDERTIE
+2055..205E ; N # Po [10] FLOWER PUNCTUATION MARK..VERTICAL FOUR DOTS
+205F ; N # Zs MEDIUM MATHEMATICAL SPACE
+2060..2064 ; N # Cf [5] WORD JOINER..INVISIBLE PLUS
+2066..206F ; N # Cf [10] LEFT-TO-RIGHT ISOLATE..NOMINAL DIGIT SHAPES
+2070 ; N # No SUPERSCRIPT ZERO
+2071 ; N # Lm SUPERSCRIPT LATIN SMALL LETTER I
+2074 ; A # No SUPERSCRIPT FOUR
+2075..2079 ; N # No [5] SUPERSCRIPT FIVE..SUPERSCRIPT NINE
+207A..207C ; N # Sm [3] SUPERSCRIPT PLUS SIGN..SUPERSCRIPT EQUALS SIGN
+207D ; N # Ps SUPERSCRIPT LEFT PARENTHESIS
+207E ; N # Pe SUPERSCRIPT RIGHT PARENTHESIS
+207F ; A # Lm SUPERSCRIPT LATIN SMALL LETTER N
+2080 ; N # No SUBSCRIPT ZERO
+2081..2084 ; A # No [4] SUBSCRIPT ONE..SUBSCRIPT FOUR
+2085..2089 ; N # No [5] SUBSCRIPT FIVE..SUBSCRIPT NINE
+208A..208C ; N # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN
+208D ; N # Ps SUBSCRIPT LEFT PARENTHESIS
+208E ; N # Pe SUBSCRIPT RIGHT PARENTHESIS
+2090..209C ; N # Lm [13] LATIN SUBSCRIPT SMALL LETTER A..LATIN SUBSCRIPT SMALL LETTER T
+20A0..20A8 ; N # Sc [9] EURO-CURRENCY SIGN..RUPEE SIGN
+20A9 ; H # Sc WON SIGN
+20AA..20AB ; N # Sc [2] NEW SHEQEL SIGN..DONG SIGN
+20AC ; A # Sc EURO SIGN
+20AD..20C0 ; N # Sc [20] KIP SIGN..SOM SIGN
+20D0..20DC ; N # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE
+20DD..20E0 ; N # Me [4] COMBINING ENCLOSING CIRCLE..COMBINING ENCLOSING CIRCLE BACKSLASH
+20E1 ; N # Mn COMBINING LEFT RIGHT ARROW ABOVE
+20E2..20E4 ; N # Me [3] COMBINING ENCLOSING SCREEN..COMBINING ENCLOSING UPWARD POINTING TRIANGLE
+20E5..20F0 ; N # Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE
+2100..2101 ; N # So [2] ACCOUNT OF..ADDRESSED TO THE SUBJECT
+2102 ; N # Lu DOUBLE-STRUCK CAPITAL C
+2103 ; A # So DEGREE CELSIUS
+2104 ; N # So CENTRE LINE SYMBOL
+2105 ; A # So CARE OF
+2106 ; N # So CADA UNA
+2107 ; N # Lu EULER CONSTANT
+2108 ; N # So SCRUPLE
+2109 ; A # So DEGREE FAHRENHEIT
+210A..2112 ; N # L& [9] SCRIPT SMALL G..SCRIPT CAPITAL L
+2113 ; A # Ll SCRIPT SMALL L
+2114 ; N # So L B BAR SYMBOL
+2115 ; N # Lu DOUBLE-STRUCK CAPITAL N
+2116 ; A # So NUMERO SIGN
+2117 ; N # So SOUND RECORDING COPYRIGHT
+2118 ; N # Sm SCRIPT CAPITAL P
+2119..211D ; N # Lu [5] DOUBLE-STRUCK CAPITAL P..DOUBLE-STRUCK CAPITAL R
+211E..2120 ; N # So [3] PRESCRIPTION TAKE..SERVICE MARK
+2121..2122 ; A # So [2] TELEPHONE SIGN..TRADE MARK SIGN
+2123 ; N # So VERSICLE
+2124 ; N # Lu DOUBLE-STRUCK CAPITAL Z
+2125 ; N # So OUNCE SIGN
+2126 ; A # Lu OHM SIGN
+2127 ; N # So INVERTED OHM SIGN
+2128 ; N # Lu BLACK-LETTER CAPITAL Z
+2129 ; N # So TURNED GREEK SMALL LETTER IOTA
+212A ; N # Lu KELVIN SIGN
+212B ; A # Lu ANGSTROM SIGN
+212C..212D ; N # Lu [2] SCRIPT CAPITAL B..BLACK-LETTER CAPITAL C
+212E ; N # So ESTIMATED SYMBOL
+212F..2134 ; N # L& [6] SCRIPT SMALL E..SCRIPT SMALL O
+2135..2138 ; N # Lo [4] ALEF SYMBOL..DALET SYMBOL
+2139 ; N # Ll INFORMATION SOURCE
+213A..213B ; N # So [2] ROTATED CAPITAL Q..FACSIMILE SIGN
+213C..213F ; N # L& [4] DOUBLE-STRUCK SMALL PI..DOUBLE-STRUCK CAPITAL PI
+2140..2144 ; N # Sm [5] DOUBLE-STRUCK N-ARY SUMMATION..TURNED SANS-SERIF CAPITAL Y
+2145..2149 ; N # L& [5] DOUBLE-STRUCK ITALIC CAPITAL D..DOUBLE-STRUCK ITALIC SMALL J
+214A ; N # So PROPERTY LINE
+214B ; N # Sm TURNED AMPERSAND
+214C..214D ; N # So [2] PER SIGN..AKTIESELSKAB
+214E ; N # Ll TURNED SMALL F
+214F ; N # So SYMBOL FOR SAMARITAN SOURCE
+2150..2152 ; N # No [3] VULGAR FRACTION ONE SEVENTH..VULGAR FRACTION ONE TENTH
+2153..2154 ; A # No [2] VULGAR FRACTION ONE THIRD..VULGAR FRACTION TWO THIRDS
+2155..215A ; N # No [6] VULGAR FRACTION ONE FIFTH..VULGAR FRACTION FIVE SIXTHS
+215B..215E ; A # No [4] VULGAR FRACTION ONE EIGHTH..VULGAR FRACTION SEVEN EIGHTHS
+215F ; N # No FRACTION NUMERATOR ONE
+2160..216B ; A # Nl [12] ROMAN NUMERAL ONE..ROMAN NUMERAL TWELVE
+216C..216F ; N # Nl [4] ROMAN NUMERAL FIFTY..ROMAN NUMERAL ONE THOUSAND
+2170..2179 ; A # Nl [10] SMALL ROMAN NUMERAL ONE..SMALL ROMAN NUMERAL TEN
+217A..2182 ; N # Nl [9] SMALL ROMAN NUMERAL ELEVEN..ROMAN NUMERAL TEN THOUSAND
+2183..2184 ; N # L& [2] ROMAN NUMERAL REVERSED ONE HUNDRED..LATIN SMALL LETTER REVERSED C
+2185..2188 ; N # Nl [4] ROMAN NUMERAL SIX LATE FORM..ROMAN NUMERAL ONE HUNDRED THOUSAND
+2189 ; A # No VULGAR FRACTION ZERO THIRDS
+218A..218B ; N # So [2] TURNED DIGIT TWO..TURNED DIGIT THREE
+2190..2194 ; A # Sm [5] LEFTWARDS ARROW..LEFT RIGHT ARROW
+2195..2199 ; A # So [5] UP DOWN ARROW..SOUTH WEST ARROW
+219A..219B ; N # Sm [2] LEFTWARDS ARROW WITH STROKE..RIGHTWARDS ARROW WITH STROKE
+219C..219F ; N # So [4] LEFTWARDS WAVE ARROW..UPWARDS TWO HEADED ARROW
+21A0 ; N # Sm RIGHTWARDS TWO HEADED ARROW
+21A1..21A2 ; N # So [2] DOWNWARDS TWO HEADED ARROW..LEFTWARDS ARROW WITH TAIL
+21A3 ; N # Sm RIGHTWARDS ARROW WITH TAIL
+21A4..21A5 ; N # So [2] LEFTWARDS ARROW FROM BAR..UPWARDS ARROW FROM BAR
+21A6 ; N # Sm RIGHTWARDS ARROW FROM BAR
+21A7..21AD ; N # So [7] DOWNWARDS ARROW FROM BAR..LEFT RIGHT WAVE ARROW
+21AE ; N # Sm LEFT RIGHT ARROW WITH STROKE
+21AF..21B7 ; N # So [9] DOWNWARDS ZIGZAG ARROW..CLOCKWISE TOP SEMICIRCLE ARROW
+21B8..21B9 ; A # So [2] NORTH WEST ARROW TO LONG BAR..LEFTWARDS ARROW TO BAR OVER RIGHTWARDS ARROW TO BAR
+21BA..21CD ; N # So [20] ANTICLOCKWISE OPEN CIRCLE ARROW..LEFTWARDS DOUBLE ARROW WITH STROKE
+21CE..21CF ; N # Sm [2] LEFT RIGHT DOUBLE ARROW WITH STROKE..RIGHTWARDS DOUBLE ARROW WITH STROKE
+21D0..21D1 ; N # So [2] LEFTWARDS DOUBLE ARROW..UPWARDS DOUBLE ARROW
+21D2 ; A # Sm RIGHTWARDS DOUBLE ARROW
+21D3 ; N # So DOWNWARDS DOUBLE ARROW
+21D4 ; A # Sm LEFT RIGHT DOUBLE ARROW
+21D5..21E6 ; N # So [18] UP DOWN DOUBLE ARROW..LEFTWARDS WHITE ARROW
+21E7 ; A # So UPWARDS WHITE ARROW
+21E8..21F3 ; N # So [12] RIGHTWARDS WHITE ARROW..UP DOWN WHITE ARROW
+21F4..21FF ; N # Sm [12] RIGHT ARROW WITH SMALL CIRCLE..LEFT RIGHT OPEN-HEADED ARROW
+2200 ; A # Sm FOR ALL
+2201 ; N # Sm COMPLEMENT
+2202..2203 ; A # Sm [2] PARTIAL DIFFERENTIAL..THERE EXISTS
+2204..2206 ; N # Sm [3] THERE DOES NOT EXIST..INCREMENT
+2207..2208 ; A # Sm [2] NABLA..ELEMENT OF
+2209..220A ; N # Sm [2] NOT AN ELEMENT OF..SMALL ELEMENT OF
+220B ; A # Sm CONTAINS AS MEMBER
+220C..220E ; N # Sm [3] DOES NOT CONTAIN AS MEMBER..END OF PROOF
+220F ; A # Sm N-ARY PRODUCT
+2210 ; N # Sm N-ARY COPRODUCT
+2211 ; A # Sm N-ARY SUMMATION
+2212..2214 ; N # Sm [3] MINUS SIGN..DOT PLUS
+2215 ; A # Sm DIVISION SLASH
+2216..2219 ; N # Sm [4] SET MINUS..BULLET OPERATOR
+221A ; A # Sm SQUARE ROOT
+221B..221C ; N # Sm [2] CUBE ROOT..FOURTH ROOT
+221D..2220 ; A # Sm [4] PROPORTIONAL TO..ANGLE
+2221..2222 ; N # Sm [2] MEASURED ANGLE..SPHERICAL ANGLE
+2223 ; A # Sm DIVIDES
+2224 ; N # Sm DOES NOT DIVIDE
+2225 ; A # Sm PARALLEL TO
+2226 ; N # Sm NOT PARALLEL TO
+2227..222C ; A # Sm [6] LOGICAL AND..DOUBLE INTEGRAL
+222D ; N # Sm TRIPLE INTEGRAL
+222E ; A # Sm CONTOUR INTEGRAL
+222F..2233 ; N # Sm [5] SURFACE INTEGRAL..ANTICLOCKWISE CONTOUR INTEGRAL
+2234..2237 ; A # Sm [4] THEREFORE..PROPORTION
+2238..223B ; N # Sm [4] DOT MINUS..HOMOTHETIC
+223C..223D ; A # Sm [2] TILDE OPERATOR..REVERSED TILDE
+223E..2247 ; N # Sm [10] INVERTED LAZY S..NEITHER APPROXIMATELY NOR ACTUALLY EQUAL TO
+2248 ; A # Sm ALMOST EQUAL TO
+2249..224B ; N # Sm [3] NOT ALMOST EQUAL TO..TRIPLE TILDE
+224C ; A # Sm ALL EQUAL TO
+224D..2251 ; N # Sm [5] EQUIVALENT TO..GEOMETRICALLY EQUAL TO
+2252 ; A # Sm APPROXIMATELY EQUAL TO OR THE IMAGE OF
+2253..225F ; N # Sm [13] IMAGE OF OR APPROXIMATELY EQUAL TO..QUESTIONED EQUAL TO
+2260..2261 ; A # Sm [2] NOT EQUAL TO..IDENTICAL TO
+2262..2263 ; N # Sm [2] NOT IDENTICAL TO..STRICTLY EQUIVALENT TO
+2264..2267 ; A # Sm [4] LESS-THAN OR EQUAL TO..GREATER-THAN OVER EQUAL TO
+2268..2269 ; N # Sm [2] LESS-THAN BUT NOT EQUAL TO..GREATER-THAN BUT NOT EQUAL TO
+226A..226B ; A # Sm [2] MUCH LESS-THAN..MUCH GREATER-THAN
+226C..226D ; N # Sm [2] BETWEEN..NOT EQUIVALENT TO
+226E..226F ; A # Sm [2] NOT LESS-THAN..NOT GREATER-THAN
+2270..2281 ; N # Sm [18] NEITHER LESS-THAN NOR EQUAL TO..DOES NOT SUCCEED
+2282..2283 ; A # Sm [2] SUBSET OF..SUPERSET OF
+2284..2285 ; N # Sm [2] NOT A SUBSET OF..NOT A SUPERSET OF
+2286..2287 ; A # Sm [2] SUBSET OF OR EQUAL TO..SUPERSET OF OR EQUAL TO
+2288..2294 ; N # Sm [13] NEITHER A SUBSET OF NOR EQUAL TO..SQUARE CUP
+2295 ; A # Sm CIRCLED PLUS
+2296..2298 ; N # Sm [3] CIRCLED MINUS..CIRCLED DIVISION SLASH
+2299 ; A # Sm CIRCLED DOT OPERATOR
+229A..22A4 ; N # Sm [11] CIRCLED RING OPERATOR..DOWN TACK
+22A5 ; A # Sm UP TACK
+22A6..22BE ; N # Sm [25] ASSERTION..RIGHT ANGLE WITH ARC
+22BF ; A # Sm RIGHT TRIANGLE
+22C0..22FF ; N # Sm [64] N-ARY LOGICAL AND..Z NOTATION BAG MEMBERSHIP
+2300..2307 ; N # So [8] DIAMETER SIGN..WAVY LINE
+2308 ; N # Ps LEFT CEILING
+2309 ; N # Pe RIGHT CEILING
+230A ; N # Ps LEFT FLOOR
+230B ; N # Pe RIGHT FLOOR
+230C..2311 ; N # So [6] BOTTOM RIGHT CROP..SQUARE LOZENGE
+2312 ; A # So ARC
+2313..2319 ; N # So [7] SEGMENT..TURNED NOT SIGN
+231A..231B ; W # So [2] WATCH..HOURGLASS
+231C..231F ; N # So [4] TOP LEFT CORNER..BOTTOM RIGHT CORNER
+2320..2321 ; N # Sm [2] TOP HALF INTEGRAL..BOTTOM HALF INTEGRAL
+2322..2328 ; N # So [7] FROWN..KEYBOARD
+2329 ; W # Ps LEFT-POINTING ANGLE BRACKET
+232A ; W # Pe RIGHT-POINTING ANGLE BRACKET
+232B..237B ; N # So [81] ERASE TO THE LEFT..NOT CHECK MARK
+237C ; N # Sm RIGHT ANGLE WITH DOWNWARDS ZIGZAG ARROW
+237D..239A ; N # So [30] SHOULDERED OPEN BOX..CLEAR SCREEN SYMBOL
+239B..23B3 ; N # Sm [25] LEFT PARENTHESIS UPPER HOOK..SUMMATION BOTTOM
+23B4..23DB ; N # So [40] TOP SQUARE BRACKET..FUSE
+23DC..23E1 ; N # Sm [6] TOP PARENTHESIS..BOTTOM TORTOISE SHELL BRACKET
+23E2..23E8 ; N # So [7] WHITE TRAPEZIUM..DECIMAL EXPONENT SYMBOL
+23E9..23EC ; W # So [4] BLACK RIGHT-POINTING DOUBLE TRIANGLE..BLACK DOWN-POINTING DOUBLE TRIANGLE
+23ED..23EF ; N # So [3] BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR..BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR
+23F0 ; W # So ALARM CLOCK
+23F1..23F2 ; N # So [2] STOPWATCH..TIMER CLOCK
+23F3 ; W # So HOURGLASS WITH FLOWING SAND
+23F4..23FF ; N # So [12] BLACK MEDIUM LEFT-POINTING TRIANGLE..OBSERVER EYE SYMBOL
+2400..2426 ; N # So [39] SYMBOL FOR NULL..SYMBOL FOR SUBSTITUTE FORM TWO
+2440..244A ; N # So [11] OCR HOOK..OCR DOUBLE BACKSLASH
+2460..249B ; A # No [60] CIRCLED DIGIT ONE..NUMBER TWENTY FULL STOP
+249C..24E9 ; A # So [78] PARENTHESIZED LATIN SMALL LETTER A..CIRCLED LATIN SMALL LETTER Z
+24EA ; N # No CIRCLED DIGIT ZERO
+24EB..24FF ; A # No [21] NEGATIVE CIRCLED NUMBER ELEVEN..NEGATIVE CIRCLED DIGIT ZERO
+2500..254B ; A # So [76] BOX DRAWINGS LIGHT HORIZONTAL..BOX DRAWINGS HEAVY VERTICAL AND HORIZONTAL
+254C..254F ; N # So [4] BOX DRAWINGS LIGHT DOUBLE DASH HORIZONTAL..BOX DRAWINGS HEAVY DOUBLE DASH VERTICAL
+2550..2573 ; A # So [36] BOX DRAWINGS DOUBLE HORIZONTAL..BOX DRAWINGS LIGHT DIAGONAL CROSS
+2574..257F ; N # So [12] BOX DRAWINGS LIGHT LEFT..BOX DRAWINGS HEAVY UP AND LIGHT DOWN
+2580..258F ; A # So [16] UPPER HALF BLOCK..LEFT ONE EIGHTH BLOCK
+2590..2591 ; N # So [2] RIGHT HALF BLOCK..LIGHT SHADE
+2592..2595 ; A # So [4] MEDIUM SHADE..RIGHT ONE EIGHTH BLOCK
+2596..259F ; N # So [10] QUADRANT LOWER LEFT..QUADRANT UPPER RIGHT AND LOWER LEFT AND LOWER RIGHT
+25A0..25A1 ; A # So [2] BLACK SQUARE..WHITE SQUARE
+25A2 ; N # So WHITE SQUARE WITH ROUNDED CORNERS
+25A3..25A9 ; A # So [7] WHITE SQUARE CONTAINING BLACK SMALL SQUARE..SQUARE WITH DIAGONAL CROSSHATCH FILL
+25AA..25B1 ; N # So [8] BLACK SMALL SQUARE..WHITE PARALLELOGRAM
+25B2..25B3 ; A # So [2] BLACK UP-POINTING TRIANGLE..WHITE UP-POINTING TRIANGLE
+25B4..25B5 ; N # So [2] BLACK UP-POINTING SMALL TRIANGLE..WHITE UP-POINTING SMALL TRIANGLE
+25B6 ; A # So BLACK RIGHT-POINTING TRIANGLE
+25B7 ; A # Sm WHITE RIGHT-POINTING TRIANGLE
+25B8..25BB ; N # So [4] BLACK RIGHT-POINTING SMALL TRIANGLE..WHITE RIGHT-POINTING POINTER
+25BC..25BD ; A # So [2] BLACK DOWN-POINTING TRIANGLE..WHITE DOWN-POINTING TRIANGLE
+25BE..25BF ; N # So [2] BLACK DOWN-POINTING SMALL TRIANGLE..WHITE DOWN-POINTING SMALL TRIANGLE
+25C0 ; A # So BLACK LEFT-POINTING TRIANGLE
+25C1 ; A # Sm WHITE LEFT-POINTING TRIANGLE
+25C2..25C5 ; N # So [4] BLACK LEFT-POINTING SMALL TRIANGLE..WHITE LEFT-POINTING POINTER
+25C6..25C8 ; A # So [3] BLACK DIAMOND..WHITE DIAMOND CONTAINING BLACK SMALL DIAMOND
+25C9..25CA ; N # So [2] FISHEYE..LOZENGE
+25CB ; A # So WHITE CIRCLE
+25CC..25CD ; N # So [2] DOTTED CIRCLE..CIRCLE WITH VERTICAL FILL
+25CE..25D1 ; A # So [4] BULLSEYE..CIRCLE WITH RIGHT HALF BLACK
+25D2..25E1 ; N # So [16] CIRCLE WITH LOWER HALF BLACK..LOWER HALF CIRCLE
+25E2..25E5 ; A # So [4] BLACK LOWER RIGHT TRIANGLE..BLACK UPPER RIGHT TRIANGLE
+25E6..25EE ; N # So [9] WHITE BULLET..UP-POINTING TRIANGLE WITH RIGHT HALF BLACK
+25EF ; A # So LARGE CIRCLE
+25F0..25F7 ; N # So [8] WHITE SQUARE WITH UPPER LEFT QUADRANT..WHITE CIRCLE WITH UPPER RIGHT QUADRANT
+25F8..25FC ; N # Sm [5] UPPER LEFT TRIANGLE..BLACK MEDIUM SQUARE
+25FD..25FE ; W # Sm [2] WHITE MEDIUM SMALL SQUARE..BLACK MEDIUM SMALL SQUARE
+25FF ; N # Sm LOWER RIGHT TRIANGLE
+2600..2604 ; N # So [5] BLACK SUN WITH RAYS..COMET
+2605..2606 ; A # So [2] BLACK STAR..WHITE STAR
+2607..2608 ; N # So [2] LIGHTNING..THUNDERSTORM
+2609 ; A # So SUN
+260A..260D ; N # So [4] ASCENDING NODE..OPPOSITION
+260E..260F ; A # So [2] BLACK TELEPHONE..WHITE TELEPHONE
+2610..2613 ; N # So [4] BALLOT BOX..SALTIRE
+2614..2615 ; W # So [2] UMBRELLA WITH RAIN DROPS..HOT BEVERAGE
+2616..261B ; N # So [6] WHITE SHOGI PIECE..BLACK RIGHT POINTING INDEX
+261C ; A # So WHITE LEFT POINTING INDEX
+261D ; N # So WHITE UP POINTING INDEX
+261E ; A # So WHITE RIGHT POINTING INDEX
+261F..263F ; N # So [33] WHITE DOWN POINTING INDEX..MERCURY
+2640 ; A # So FEMALE SIGN
+2641 ; N # So EARTH
+2642 ; A # So MALE SIGN
+2643..2647 ; N # So [5] JUPITER..PLUTO
+2648..2653 ; W # So [12] ARIES..PISCES
+2654..265F ; N # So [12] WHITE CHESS KING..BLACK CHESS PAWN
+2660..2661 ; A # So [2] BLACK SPADE SUIT..WHITE HEART SUIT
+2662 ; N # So WHITE DIAMOND SUIT
+2663..2665 ; A # So [3] BLACK CLUB SUIT..BLACK HEART SUIT
+2666 ; N # So BLACK DIAMOND SUIT
+2667..266A ; A # So [4] WHITE CLUB SUIT..EIGHTH NOTE
+266B ; N # So BEAMED EIGHTH NOTES
+266C..266D ; A # So [2] BEAMED SIXTEENTH NOTES..MUSIC FLAT SIGN
+266E ; N # So MUSIC NATURAL SIGN
+266F ; A # Sm MUSIC SHARP SIGN
+2670..267E ; N # So [15] WEST SYRIAC CROSS..PERMANENT PAPER SIGN
+267F ; W # So WHEELCHAIR SYMBOL
+2680..2692 ; N # So [19] DIE FACE-1..HAMMER AND PICK
+2693 ; W # So ANCHOR
+2694..269D ; N # So [10] CROSSED SWORDS..OUTLINED WHITE STAR
+269E..269F ; A # So [2] THREE LINES CONVERGING RIGHT..THREE LINES CONVERGING LEFT
+26A0 ; N # So WARNING SIGN
+26A1 ; W # So HIGH VOLTAGE SIGN
+26A2..26A9 ; N # So [8] DOUBLED FEMALE SIGN..HORIZONTAL MALE WITH STROKE SIGN
+26AA..26AB ; W # So [2] MEDIUM WHITE CIRCLE..MEDIUM BLACK CIRCLE
+26AC..26BC ; N # So [17] MEDIUM SMALL WHITE CIRCLE..SESQUIQUADRATE
+26BD..26BE ; W # So [2] SOCCER BALL..BASEBALL
+26BF ; A # So SQUARED KEY
+26C0..26C3 ; N # So [4] WHITE DRAUGHTS MAN..BLACK DRAUGHTS KING
+26C4..26C5 ; W # So [2] SNOWMAN WITHOUT SNOW..SUN BEHIND CLOUD
+26C6..26CD ; A # So [8] RAIN..DISABLED CAR
+26CE ; W # So OPHIUCHUS
+26CF..26D3 ; A # So [5] PICK..CHAINS
+26D4 ; W # So NO ENTRY
+26D5..26E1 ; A # So [13] ALTERNATE ONE-WAY LEFT WAY TRAFFIC..RESTRICTED LEFT ENTRY-2
+26E2 ; N # So ASTRONOMICAL SYMBOL FOR URANUS
+26E3 ; A # So HEAVY CIRCLE WITH STROKE AND TWO DOTS ABOVE
+26E4..26E7 ; N # So [4] PENTAGRAM..INVERTED PENTAGRAM
+26E8..26E9 ; A # So [2] BLACK CROSS ON SHIELD..SHINTO SHRINE
+26EA ; W # So CHURCH
+26EB..26F1 ; A # So [7] CASTLE..UMBRELLA ON GROUND
+26F2..26F3 ; W # So [2] FOUNTAIN..FLAG IN HOLE
+26F4 ; A # So FERRY
+26F5 ; W # So SAILBOAT
+26F6..26F9 ; A # So [4] SQUARE FOUR CORNERS..PERSON WITH BALL
+26FA ; W # So TENT
+26FB..26FC ; A # So [2] JAPANESE BANK SYMBOL..HEADSTONE GRAVEYARD SYMBOL
+26FD ; W # So FUEL PUMP
+26FE..26FF ; A # So [2] CUP ON BLACK SQUARE..WHITE FLAG WITH HORIZONTAL MIDDLE BLACK STRIPE
+2700..2704 ; N # So [5] BLACK SAFETY SCISSORS..WHITE SCISSORS
+2705 ; W # So WHITE HEAVY CHECK MARK
+2706..2709 ; N # So [4] TELEPHONE LOCATION SIGN..ENVELOPE
+270A..270B ; W # So [2] RAISED FIST..RAISED HAND
+270C..2727 ; N # So [28] VICTORY HAND..WHITE FOUR POINTED STAR
+2728 ; W # So SPARKLES
+2729..273C ; N # So [20] STRESS OUTLINED WHITE STAR..OPEN CENTRE TEARDROP-SPOKED ASTERISK
+273D ; A # So HEAVY TEARDROP-SPOKED ASTERISK
+273E..274B ; N # So [14] SIX PETALLED BLACK AND WHITE FLORETTE..HEAVY EIGHT TEARDROP-SPOKED PROPELLER ASTERISK
+274C ; W # So CROSS MARK
+274D ; N # So SHADOWED WHITE CIRCLE
+274E ; W # So NEGATIVE SQUARED CROSS MARK
+274F..2752 ; N # So [4] LOWER RIGHT DROP-SHADOWED WHITE SQUARE..UPPER RIGHT SHADOWED WHITE SQUARE
+2753..2755 ; W # So [3] BLACK QUESTION MARK ORNAMENT..WHITE EXCLAMATION MARK ORNAMENT
+2756 ; N # So BLACK DIAMOND MINUS WHITE X
+2757 ; W # So HEAVY EXCLAMATION MARK SYMBOL
+2758..2767 ; N # So [16] LIGHT VERTICAL BAR..ROTATED FLORAL HEART BULLET
+2768 ; N # Ps MEDIUM LEFT PARENTHESIS ORNAMENT
+2769 ; N # Pe MEDIUM RIGHT PARENTHESIS ORNAMENT
+276A ; N # Ps MEDIUM FLATTENED LEFT PARENTHESIS ORNAMENT
+276B ; N # Pe MEDIUM FLATTENED RIGHT PARENTHESIS ORNAMENT
+276C ; N # Ps MEDIUM LEFT-POINTING ANGLE BRACKET ORNAMENT
+276D ; N # Pe MEDIUM RIGHT-POINTING ANGLE BRACKET ORNAMENT
+276E ; N # Ps HEAVY LEFT-POINTING ANGLE QUOTATION MARK ORNAMENT
+276F ; N # Pe HEAVY RIGHT-POINTING ANGLE QUOTATION MARK ORNAMENT
+2770 ; N # Ps HEAVY LEFT-POINTING ANGLE BRACKET ORNAMENT
+2771 ; N # Pe HEAVY RIGHT-POINTING ANGLE BRACKET ORNAMENT
+2772 ; N # Ps LIGHT LEFT TORTOISE SHELL BRACKET ORNAMENT
+2773 ; N # Pe LIGHT RIGHT TORTOISE SHELL BRACKET ORNAMENT
+2774 ; N # Ps MEDIUM LEFT CURLY BRACKET ORNAMENT
+2775 ; N # Pe MEDIUM RIGHT CURLY BRACKET ORNAMENT
+2776..277F ; A # No [10] DINGBAT NEGATIVE CIRCLED DIGIT ONE..DINGBAT NEGATIVE CIRCLED NUMBER TEN
+2780..2793 ; N # No [20] DINGBAT CIRCLED SANS-SERIF DIGIT ONE..DINGBAT NEGATIVE CIRCLED SANS-SERIF NUMBER TEN
+2794 ; N # So HEAVY WIDE-HEADED RIGHTWARDS ARROW
+2795..2797 ; W # So [3] HEAVY PLUS SIGN..HEAVY DIVISION SIGN
+2798..27AF ; N # So [24] HEAVY SOUTH EAST ARROW..NOTCHED LOWER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW
+27B0 ; W # So CURLY LOOP
+27B1..27BE ; N # So [14] NOTCHED UPPER RIGHT-SHADOWED WHITE RIGHTWARDS ARROW..OPEN-OUTLINED RIGHTWARDS ARROW
+27BF ; W # So DOUBLE CURLY LOOP
+27C0..27C4 ; N # Sm [5] THREE DIMENSIONAL ANGLE..OPEN SUPERSET
+27C5 ; N # Ps LEFT S-SHAPED BAG DELIMITER
+27C6 ; N # Pe RIGHT S-SHAPED BAG DELIMITER
+27C7..27E5 ; N # Sm [31] OR WITH DOT INSIDE..WHITE SQUARE WITH RIGHTWARDS TICK
+27E6 ; Na # Ps MATHEMATICAL LEFT WHITE SQUARE BRACKET
+27E7 ; Na # Pe MATHEMATICAL RIGHT WHITE SQUARE BRACKET
+27E8 ; Na # Ps MATHEMATICAL LEFT ANGLE BRACKET
+27E9 ; Na # Pe MATHEMATICAL RIGHT ANGLE BRACKET
+27EA ; Na # Ps MATHEMATICAL LEFT DOUBLE ANGLE BRACKET
+27EB ; Na # Pe MATHEMATICAL RIGHT DOUBLE ANGLE BRACKET
+27EC ; Na # Ps MATHEMATICAL LEFT WHITE TORTOISE SHELL BRACKET
+27ED ; Na # Pe MATHEMATICAL RIGHT WHITE TORTOISE SHELL BRACKET
+27EE ; N # Ps MATHEMATICAL LEFT FLATTENED PARENTHESIS
+27EF ; N # Pe MATHEMATICAL RIGHT FLATTENED PARENTHESIS
+27F0..27FF ; N # Sm [16] UPWARDS QUADRUPLE ARROW..LONG RIGHTWARDS SQUIGGLE ARROW
+2800..28FF ; N # So [256] BRAILLE PATTERN BLANK..BRAILLE PATTERN DOTS-12345678
+2900..297F ; N # Sm [128] RIGHTWARDS TWO-HEADED ARROW WITH VERTICAL STROKE..DOWN FISH TAIL
+2980..2982 ; N # Sm [3] TRIPLE VERTICAL BAR DELIMITER..Z NOTATION TYPE COLON
+2983 ; N # Ps LEFT WHITE CURLY BRACKET
+2984 ; N # Pe RIGHT WHITE CURLY BRACKET
+2985 ; Na # Ps LEFT WHITE PARENTHESIS
+2986 ; Na # Pe RIGHT WHITE PARENTHESIS
+2987 ; N # Ps Z NOTATION LEFT IMAGE BRACKET
+2988 ; N # Pe Z NOTATION RIGHT IMAGE BRACKET
+2989 ; N # Ps Z NOTATION LEFT BINDING BRACKET
+298A ; N # Pe Z NOTATION RIGHT BINDING BRACKET
+298B ; N # Ps LEFT SQUARE BRACKET WITH UNDERBAR
+298C ; N # Pe RIGHT SQUARE BRACKET WITH UNDERBAR
+298D ; N # Ps LEFT SQUARE BRACKET WITH TICK IN TOP CORNER
+298E ; N # Pe RIGHT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+298F ; N # Ps LEFT SQUARE BRACKET WITH TICK IN BOTTOM CORNER
+2990 ; N # Pe RIGHT SQUARE BRACKET WITH TICK IN TOP CORNER
+2991 ; N # Ps LEFT ANGLE BRACKET WITH DOT
+2992 ; N # Pe RIGHT ANGLE BRACKET WITH DOT
+2993 ; N # Ps LEFT ARC LESS-THAN BRACKET
+2994 ; N # Pe RIGHT ARC GREATER-THAN BRACKET
+2995 ; N # Ps DOUBLE LEFT ARC GREATER-THAN BRACKET
+2996 ; N # Pe DOUBLE RIGHT ARC LESS-THAN BRACKET
+2997 ; N # Ps LEFT BLACK TORTOISE SHELL BRACKET
+2998 ; N # Pe RIGHT BLACK TORTOISE SHELL BRACKET
+2999..29D7 ; N # Sm [63] DOTTED FENCE..BLACK HOURGLASS
+29D8 ; N # Ps LEFT WIGGLY FENCE
+29D9 ; N # Pe RIGHT WIGGLY FENCE
+29DA ; N # Ps LEFT DOUBLE WIGGLY FENCE
+29DB ; N # Pe RIGHT DOUBLE WIGGLY FENCE
+29DC..29FB ; N # Sm [32] INCOMPLETE INFINITY..TRIPLE PLUS
+29FC ; N # Ps LEFT-POINTING CURVED ANGLE BRACKET
+29FD ; N # Pe RIGHT-POINTING CURVED ANGLE BRACKET
+29FE..29FF ; N # Sm [2] TINY..MINY
+2A00..2AFF ; N # Sm [256] N-ARY CIRCLED DOT OPERATOR..N-ARY WHITE VERTICAL BAR
+2B00..2B1A ; N # So [27] NORTH EAST WHITE ARROW..DOTTED SQUARE
+2B1B..2B1C ; W # So [2] BLACK LARGE SQUARE..WHITE LARGE SQUARE
+2B1D..2B2F ; N # So [19] BLACK VERY SMALL SQUARE..WHITE VERTICAL ELLIPSE
+2B30..2B44 ; N # Sm [21] LEFT ARROW WITH SMALL CIRCLE..RIGHTWARDS ARROW THROUGH SUPERSET
+2B45..2B46 ; N # So [2] LEFTWARDS QUADRUPLE ARROW..RIGHTWARDS QUADRUPLE ARROW
+2B47..2B4C ; N # Sm [6] REVERSE TILDE OPERATOR ABOVE RIGHTWARDS ARROW..RIGHTWARDS ARROW ABOVE REVERSE TILDE OPERATOR
+2B4D..2B4F ; N # So [3] DOWNWARDS TRIANGLE-HEADED ZIGZAG ARROW..SHORT BACKSLANTED SOUTH ARROW
+2B50 ; W # So WHITE MEDIUM STAR
+2B51..2B54 ; N # So [4] BLACK SMALL STAR..WHITE RIGHT-POINTING PENTAGON
+2B55 ; W # So HEAVY LARGE CIRCLE
+2B56..2B59 ; A # So [4] HEAVY OVAL WITH OVAL INSIDE..HEAVY CIRCLED SALTIRE
+2B5A..2B73 ; N # So [26] SLANTED NORTH ARROW WITH HOOKED HEAD..DOWNWARDS TRIANGLE-HEADED ARROW TO BAR
+2B76..2B95 ; N # So [32] NORTH WEST TRIANGLE-HEADED ARROW TO BAR..RIGHTWARDS BLACK ARROW
+2B97..2BFF ; N # So [105] SYMBOL FOR TYPE A ELECTRONICS..HELLSCHREIBER PAUSE SYMBOL
+2C00..2C5F ; N # L& [96] GLAGOLITIC CAPITAL LETTER AZU..GLAGOLITIC SMALL LETTER CAUDATE CHRIVI
+2C60..2C7B ; N # L& [28] LATIN CAPITAL LETTER L WITH DOUBLE BAR..LATIN LETTER SMALL CAPITAL TURNED E
+2C7C..2C7D ; N # Lm [2] LATIN SUBSCRIPT SMALL LETTER J..MODIFIER LETTER CAPITAL V
+2C7E..2C7F ; N # Lu [2] LATIN CAPITAL LETTER S WITH SWASH TAIL..LATIN CAPITAL LETTER Z WITH SWASH TAIL
+2C80..2CE4 ; N # L& [101] COPTIC CAPITAL LETTER ALFA..COPTIC SYMBOL KAI
+2CE5..2CEA ; N # So [6] COPTIC SYMBOL MI RO..COPTIC SYMBOL SHIMA SIMA
+2CEB..2CEE ; N # L& [4] COPTIC CAPITAL LETTER CRYPTOGRAMMIC SHEI..COPTIC SMALL LETTER CRYPTOGRAMMIC GANGIA
+2CEF..2CF1 ; N # Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS
+2CF2..2CF3 ; N # L& [2] COPTIC CAPITAL LETTER BOHAIRIC KHEI..COPTIC SMALL LETTER BOHAIRIC KHEI
+2CF9..2CFC ; N # Po [4] COPTIC OLD NUBIAN FULL STOP..COPTIC OLD NUBIAN VERSE DIVIDER
+2CFD ; N # No COPTIC FRACTION ONE HALF
+2CFE..2CFF ; N # Po [2] COPTIC FULL STOP..COPTIC MORPHOLOGICAL DIVIDER
+2D00..2D25 ; N # Ll [38] GEORGIAN SMALL LETTER AN..GEORGIAN SMALL LETTER HOE
+2D27 ; N # Ll GEORGIAN SMALL LETTER YN
+2D2D ; N # Ll GEORGIAN SMALL LETTER AEN
+2D30..2D67 ; N # Lo [56] TIFINAGH LETTER YA..TIFINAGH LETTER YO
+2D6F ; N # Lm TIFINAGH MODIFIER LETTER LABIALIZATION MARK
+2D70 ; N # Po TIFINAGH SEPARATOR MARK
+2D7F ; N # Mn TIFINAGH CONSONANT JOINER
+2D80..2D96 ; N # Lo [23] ETHIOPIC SYLLABLE LOA..ETHIOPIC SYLLABLE GGWE
+2DA0..2DA6 ; N # Lo [7] ETHIOPIC SYLLABLE SSA..ETHIOPIC SYLLABLE SSO
+2DA8..2DAE ; N # Lo [7] ETHIOPIC SYLLABLE CCA..ETHIOPIC SYLLABLE CCO
+2DB0..2DB6 ; N # Lo [7] ETHIOPIC SYLLABLE ZZA..ETHIOPIC SYLLABLE ZZO
+2DB8..2DBE ; N # Lo [7] ETHIOPIC SYLLABLE CCHA..ETHIOPIC SYLLABLE CCHO
+2DC0..2DC6 ; N # Lo [7] ETHIOPIC SYLLABLE QYA..ETHIOPIC SYLLABLE QYO
+2DC8..2DCE ; N # Lo [7] ETHIOPIC SYLLABLE KYA..ETHIOPIC SYLLABLE KYO
+2DD0..2DD6 ; N # Lo [7] ETHIOPIC SYLLABLE XYA..ETHIOPIC SYLLABLE XYO
+2DD8..2DDE ; N # Lo [7] ETHIOPIC SYLLABLE GYA..ETHIOPIC SYLLABLE GYO
+2DE0..2DFF ; N # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
+2E00..2E01 ; N # Po [2] RIGHT ANGLE SUBSTITUTION MARKER..RIGHT ANGLE DOTTED SUBSTITUTION MARKER
+2E02 ; N # Pi LEFT SUBSTITUTION BRACKET
+2E03 ; N # Pf RIGHT SUBSTITUTION BRACKET
+2E04 ; N # Pi LEFT DOTTED SUBSTITUTION BRACKET
+2E05 ; N # Pf RIGHT DOTTED SUBSTITUTION BRACKET
+2E06..2E08 ; N # Po [3] RAISED INTERPOLATION MARKER..DOTTED TRANSPOSITION MARKER
+2E09 ; N # Pi LEFT TRANSPOSITION BRACKET
+2E0A ; N # Pf RIGHT TRANSPOSITION BRACKET
+2E0B ; N # Po RAISED SQUARE
+2E0C ; N # Pi LEFT RAISED OMISSION BRACKET
+2E0D ; N # Pf RIGHT RAISED OMISSION BRACKET
+2E0E..2E16 ; N # Po [9] EDITORIAL CORONIS..DOTTED RIGHT-POINTING ANGLE
+2E17 ; N # Pd DOUBLE OBLIQUE HYPHEN
+2E18..2E19 ; N # Po [2] INVERTED INTERROBANG..PALM BRANCH
+2E1A ; N # Pd HYPHEN WITH DIAERESIS
+2E1B ; N # Po TILDE WITH RING ABOVE
+2E1C ; N # Pi LEFT LOW PARAPHRASE BRACKET
+2E1D ; N # Pf RIGHT LOW PARAPHRASE BRACKET
+2E1E..2E1F ; N # Po [2] TILDE WITH DOT ABOVE..TILDE WITH DOT BELOW
+2E20 ; N # Pi LEFT VERTICAL BAR WITH QUILL
+2E21 ; N # Pf RIGHT VERTICAL BAR WITH QUILL
+2E22 ; N # Ps TOP LEFT HALF BRACKET
+2E23 ; N # Pe TOP RIGHT HALF BRACKET
+2E24 ; N # Ps BOTTOM LEFT HALF BRACKET
+2E25 ; N # Pe BOTTOM RIGHT HALF BRACKET
+2E26 ; N # Ps LEFT SIDEWAYS U BRACKET
+2E27 ; N # Pe RIGHT SIDEWAYS U BRACKET
+2E28 ; N # Ps LEFT DOUBLE PARENTHESIS
+2E29 ; N # Pe RIGHT DOUBLE PARENTHESIS
+2E2A..2E2E ; N # Po [5] TWO DOTS OVER ONE DOT PUNCTUATION..REVERSED QUESTION MARK
+2E2F ; N # Lm VERTICAL TILDE
+2E30..2E39 ; N # Po [10] RING POINT..TOP HALF SECTION SIGN
+2E3A..2E3B ; N # Pd [2] TWO-EM DASH..THREE-EM DASH
+2E3C..2E3F ; N # Po [4] STENOGRAPHIC FULL STOP..CAPITULUM
+2E40 ; N # Pd DOUBLE HYPHEN
+2E41 ; N # Po REVERSED COMMA
+2E42 ; N # Ps DOUBLE LOW-REVERSED-9 QUOTATION MARK
+2E43..2E4F ; N # Po [13] DASH WITH LEFT UPTURN..CORNISH VERSE DIVIDER
+2E50..2E51 ; N # So [2] CROSS PATTY WITH RIGHT CROSSBAR..CROSS PATTY WITH LEFT CROSSBAR
+2E52..2E54 ; N # Po [3] TIRONIAN SIGN CAPITAL ET..MEDIEVAL QUESTION MARK
+2E55 ; N # Ps LEFT SQUARE BRACKET WITH STROKE
+2E56 ; N # Pe RIGHT SQUARE BRACKET WITH STROKE
+2E57 ; N # Ps LEFT SQUARE BRACKET WITH DOUBLE STROKE
+2E58 ; N # Pe RIGHT SQUARE BRACKET WITH DOUBLE STROKE
+2E59 ; N # Ps TOP HALF LEFT PARENTHESIS
+2E5A ; N # Pe TOP HALF RIGHT PARENTHESIS
+2E5B ; N # Ps BOTTOM HALF LEFT PARENTHESIS
+2E5C ; N # Pe BOTTOM HALF RIGHT PARENTHESIS
+2E5D ; N # Pd OBLIQUE HYPHEN
+2E80..2E99 ; W # So [26] CJK RADICAL REPEAT..CJK RADICAL RAP
+2E9B..2EF3 ; W # So [89] CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE
+2F00..2FD5 ; W # So [214] KANGXI RADICAL ONE..KANGXI RADICAL FLUTE
+2FF0..2FFF ; W # So [16] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER ROTATION
+3000 ; F # Zs IDEOGRAPHIC SPACE
+3001..3003 ; W # Po [3] IDEOGRAPHIC COMMA..DITTO MARK
+3004 ; W # So JAPANESE INDUSTRIAL STANDARD SYMBOL
+3005 ; W # Lm IDEOGRAPHIC ITERATION MARK
+3006 ; W # Lo IDEOGRAPHIC CLOSING MARK
+3007 ; W # Nl IDEOGRAPHIC NUMBER ZERO
+3008 ; W # Ps LEFT ANGLE BRACKET
+3009 ; W # Pe RIGHT ANGLE BRACKET
+300A ; W # Ps LEFT DOUBLE ANGLE BRACKET
+300B ; W # Pe RIGHT DOUBLE ANGLE BRACKET
+300C ; W # Ps LEFT CORNER BRACKET
+300D ; W # Pe RIGHT CORNER BRACKET
+300E ; W # Ps LEFT WHITE CORNER BRACKET
+300F ; W # Pe RIGHT WHITE CORNER BRACKET
+3010 ; W # Ps LEFT BLACK LENTICULAR BRACKET
+3011 ; W # Pe RIGHT BLACK LENTICULAR BRACKET
+3012..3013 ; W # So [2] POSTAL MARK..GETA MARK
+3014 ; W # Ps LEFT TORTOISE SHELL BRACKET
+3015 ; W # Pe RIGHT TORTOISE SHELL BRACKET
+3016 ; W # Ps LEFT WHITE LENTICULAR BRACKET
+3017 ; W # Pe RIGHT WHITE LENTICULAR BRACKET
+3018 ; W # Ps LEFT WHITE TORTOISE SHELL BRACKET
+3019 ; W # Pe RIGHT WHITE TORTOISE SHELL BRACKET
+301A ; W # Ps LEFT WHITE SQUARE BRACKET
+301B ; W # Pe RIGHT WHITE SQUARE BRACKET
+301C ; W # Pd WAVE DASH
+301D ; W # Ps REVERSED DOUBLE PRIME QUOTATION MARK
+301E..301F ; W # Pe [2] DOUBLE PRIME QUOTATION MARK..LOW DOUBLE PRIME QUOTATION MARK
+3020 ; W # So POSTAL MARK FACE
+3021..3029 ; W # Nl [9] HANGZHOU NUMERAL ONE..HANGZHOU NUMERAL NINE
+302A..302D ; W # Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK
+302E..302F ; W # Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK
+3030 ; W # Pd WAVY DASH
+3031..3035 ; W # Lm [5] VERTICAL KANA REPEAT MARK..VERTICAL KANA REPEAT MARK LOWER HALF
+3036..3037 ; W # So [2] CIRCLED POSTAL MARK..IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL
+3038..303A ; W # Nl [3] HANGZHOU NUMERAL TEN..HANGZHOU NUMERAL THIRTY
+303B ; W # Lm VERTICAL IDEOGRAPHIC ITERATION MARK
+303C ; W # Lo MASU MARK
+303D ; W # Po PART ALTERNATION MARK
+303E ; W # So IDEOGRAPHIC VARIATION INDICATOR
+303F ; N # So IDEOGRAPHIC HALF FILL SPACE
+3041..3096 ; W # Lo [86] HIRAGANA LETTER SMALL A..HIRAGANA LETTER SMALL KE
+3099..309A ; W # Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+309B..309C ; W # Sk [2] KATAKANA-HIRAGANA VOICED SOUND MARK..KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
+309D..309E ; W # Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK
+309F ; W # Lo HIRAGANA DIGRAPH YORI
+30A0 ; W # Pd KATAKANA-HIRAGANA DOUBLE HYPHEN
+30A1..30FA ; W # Lo [90] KATAKANA LETTER SMALL A..KATAKANA LETTER VO
+30FB ; W # Po KATAKANA MIDDLE DOT
+30FC..30FE ; W # Lm [3] KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK
+30FF ; W # Lo KATAKANA DIGRAPH KOTO
+3105..312F ; W # Lo [43] BOPOMOFO LETTER B..BOPOMOFO LETTER NN
+3131..318E ; W # Lo [94] HANGUL LETTER KIYEOK..HANGUL LETTER ARAEAE
+3190..3191 ; W # So [2] IDEOGRAPHIC ANNOTATION LINKING MARK..IDEOGRAPHIC ANNOTATION REVERSE MARK
+3192..3195 ; W # No [4] IDEOGRAPHIC ANNOTATION ONE MARK..IDEOGRAPHIC ANNOTATION FOUR MARK
+3196..319F ; W # So [10] IDEOGRAPHIC ANNOTATION TOP MARK..IDEOGRAPHIC ANNOTATION MAN MARK
+31A0..31BF ; W # Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH
+31C0..31E3 ; W # So [36] CJK STROKE T..CJK STROKE Q
+31EF ; W # So IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION
+31F0..31FF ; W # Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO
+3200..321E ; W # So [31] PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED KOREAN CHARACTER O HU
+3220..3229 ; W # No [10] PARENTHESIZED IDEOGRAPH ONE..PARENTHESIZED IDEOGRAPH TEN
+322A..3247 ; W # So [30] PARENTHESIZED IDEOGRAPH MOON..CIRCLED IDEOGRAPH KOTO
+3248..324F ; A # No [8] CIRCLED NUMBER TEN ON BLACK SQUARE..CIRCLED NUMBER EIGHTY ON BLACK SQUARE
+3250 ; W # So PARTNERSHIP SIGN
+3251..325F ; W # No [15] CIRCLED NUMBER TWENTY ONE..CIRCLED NUMBER THIRTY FIVE
+3260..327F ; W # So [32] CIRCLED HANGUL KIYEOK..KOREAN STANDARD SYMBOL
+3280..3289 ; W # No [10] CIRCLED IDEOGRAPH ONE..CIRCLED IDEOGRAPH TEN
+328A..32B0 ; W # So [39] CIRCLED IDEOGRAPH MOON..CIRCLED IDEOGRAPH NIGHT
+32B1..32BF ; W # No [15] CIRCLED NUMBER THIRTY SIX..CIRCLED NUMBER FIFTY
+32C0..32FF ; W # So [64] IDEOGRAPHIC TELEGRAPH SYMBOL FOR JANUARY..SQUARE ERA NAME REIWA
+3300..33FF ; W # So [256] SQUARE APAATO..SQUARE GAL
+3400..4DBF ; W # Lo [6592] CJK UNIFIED IDEOGRAPH-3400..CJK UNIFIED IDEOGRAPH-4DBF
+4DC0..4DFF ; N # So [64] HEXAGRAM FOR THE CREATIVE HEAVEN..HEXAGRAM FOR BEFORE COMPLETION
+4E00..9FFF ; W # Lo [20992] CJK UNIFIED IDEOGRAPH-4E00..CJK UNIFIED IDEOGRAPH-9FFF
+A000..A014 ; W # Lo [21] YI SYLLABLE IT..YI SYLLABLE E
+A015 ; W # Lm YI SYLLABLE WU
+A016..A48C ; W # Lo [1143] YI SYLLABLE BIT..YI SYLLABLE YYR
+A490..A4C6 ; W # So [55] YI RADICAL QOT..YI RADICAL KE
+A4D0..A4F7 ; N # Lo [40] LISU LETTER BA..LISU LETTER OE
+A4F8..A4FD ; N # Lm [6] LISU LETTER TONE MYA TI..LISU LETTER TONE MYA JEU
+A4FE..A4FF ; N # Po [2] LISU PUNCTUATION COMMA..LISU PUNCTUATION FULL STOP
+A500..A60B ; N # Lo [268] VAI SYLLABLE EE..VAI SYLLABLE NG
+A60C ; N # Lm VAI SYLLABLE LENGTHENER
+A60D..A60F ; N # Po [3] VAI COMMA..VAI QUESTION MARK
+A610..A61F ; N # Lo [16] VAI SYLLABLE NDOLE FA..VAI SYMBOL JONG
+A620..A629 ; N # Nd [10] VAI DIGIT ZERO..VAI DIGIT NINE
+A62A..A62B ; N # Lo [2] VAI SYLLABLE NDOLE MA..VAI SYLLABLE NDOLE DO
+A640..A66D ; N # L& [46] CYRILLIC CAPITAL LETTER ZEMLYA..CYRILLIC SMALL LETTER DOUBLE MONOCULAR O
+A66E ; N # Lo CYRILLIC LETTER MULTIOCULAR O
+A66F ; N # Mn COMBINING CYRILLIC VZMET
+A670..A672 ; N # Me [3] COMBINING CYRILLIC TEN MILLIONS SIGN..COMBINING CYRILLIC THOUSAND MILLIONS SIGN
+A673 ; N # Po SLAVONIC ASTERISK
+A674..A67D ; N # Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK
+A67E ; N # Po CYRILLIC KAVYKA
+A67F ; N # Lm CYRILLIC PAYEROK
+A680..A69B ; N # L& [28] CYRILLIC CAPITAL LETTER DWE..CYRILLIC SMALL LETTER CROSSED O
+A69C..A69D ; N # Lm [2] MODIFIER LETTER CYRILLIC HARD SIGN..MODIFIER LETTER CYRILLIC SOFT SIGN
+A69E..A69F ; N # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E
+A6A0..A6E5 ; N # Lo [70] BAMUM LETTER A..BAMUM LETTER KI
+A6E6..A6EF ; N # Nl [10] BAMUM LETTER MO..BAMUM LETTER KOGHOM
+A6F0..A6F1 ; N # Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS
+A6F2..A6F7 ; N # Po [6] BAMUM NJAEMLI..BAMUM QUESTION MARK
+A700..A716 ; N # Sk [23] MODIFIER LETTER CHINESE TONE YIN PING..MODIFIER LETTER EXTRA-LOW LEFT-STEM TONE BAR
+A717..A71F ; N # Lm [9] MODIFIER LETTER DOT VERTICAL BAR..MODIFIER LETTER LOW INVERTED EXCLAMATION MARK
+A720..A721 ; N # Sk [2] MODIFIER LETTER STRESS AND HIGH TONE..MODIFIER LETTER STRESS AND LOW TONE
+A722..A76F ; N # L& [78] LATIN CAPITAL LETTER EGYPTOLOGICAL ALEF..LATIN SMALL LETTER CON
+A770 ; N # Lm MODIFIER LETTER US
+A771..A787 ; N # L& [23] LATIN SMALL LETTER DUM..LATIN SMALL LETTER INSULAR T
+A788 ; N # Lm MODIFIER LETTER LOW CIRCUMFLEX ACCENT
+A789..A78A ; N # Sk [2] MODIFIER LETTER COLON..MODIFIER LETTER SHORT EQUALS SIGN
+A78B..A78E ; N # L& [4] LATIN CAPITAL LETTER SALTILLO..LATIN SMALL LETTER L WITH RETROFLEX HOOK AND BELT
+A78F ; N # Lo LATIN LETTER SINOLOGICAL DOT
+A790..A7CA ; N # L& [59] LATIN CAPITAL LETTER N WITH DESCENDER..LATIN SMALL LETTER S WITH SHORT STROKE OVERLAY
+A7D0..A7D1 ; N # L& [2] LATIN CAPITAL LETTER CLOSED INSULAR G..LATIN SMALL LETTER CLOSED INSULAR G
+A7D3 ; N # Ll LATIN SMALL LETTER DOUBLE THORN
+A7D5..A7D9 ; N # L& [5] LATIN SMALL LETTER DOUBLE WYNN..LATIN SMALL LETTER SIGMOID S
+A7F2..A7F4 ; N # Lm [3] MODIFIER LETTER CAPITAL C..MODIFIER LETTER CAPITAL Q
+A7F5..A7F6 ; N # L& [2] LATIN CAPITAL LETTER REVERSED HALF H..LATIN SMALL LETTER REVERSED HALF H
+A7F7 ; N # Lo LATIN EPIGRAPHIC LETTER SIDEWAYS I
+A7F8..A7F9 ; N # Lm [2] MODIFIER LETTER CAPITAL H WITH STROKE..MODIFIER LETTER SMALL LIGATURE OE
+A7FA ; N # Ll LATIN LETTER SMALL CAPITAL TURNED M
+A7FB..A7FF ; N # Lo [5] LATIN EPIGRAPHIC LETTER REVERSED F..LATIN EPIGRAPHIC LETTER ARCHAIC M
+A800..A801 ; N # Lo [2] SYLOTI NAGRI LETTER A..SYLOTI NAGRI LETTER I
+A802 ; N # Mn SYLOTI NAGRI SIGN DVISVARA
+A803..A805 ; N # Lo [3] SYLOTI NAGRI LETTER U..SYLOTI NAGRI LETTER O
+A806 ; N # Mn SYLOTI NAGRI SIGN HASANTA
+A807..A80A ; N # Lo [4] SYLOTI NAGRI LETTER KO..SYLOTI NAGRI LETTER GHO
+A80B ; N # Mn SYLOTI NAGRI SIGN ANUSVARA
+A80C..A822 ; N # Lo [23] SYLOTI NAGRI LETTER CO..SYLOTI NAGRI LETTER HO
+A823..A824 ; N # Mc [2] SYLOTI NAGRI VOWEL SIGN A..SYLOTI NAGRI VOWEL SIGN I
+A825..A826 ; N # Mn [2] SYLOTI NAGRI VOWEL SIGN U..SYLOTI NAGRI VOWEL SIGN E
+A827 ; N # Mc SYLOTI NAGRI VOWEL SIGN OO
+A828..A82B ; N # So [4] SYLOTI NAGRI POETRY MARK-1..SYLOTI NAGRI POETRY MARK-4
+A82C ; N # Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA
+A830..A835 ; N # No [6] NORTH INDIC FRACTION ONE QUARTER..NORTH INDIC FRACTION THREE SIXTEENTHS
+A836..A837 ; N # So [2] NORTH INDIC QUARTER MARK..NORTH INDIC PLACEHOLDER MARK
+A838 ; N # Sc NORTH INDIC RUPEE MARK
+A839 ; N # So NORTH INDIC QUANTITY MARK
+A840..A873 ; N # Lo [52] PHAGS-PA LETTER KA..PHAGS-PA LETTER CANDRABINDU
+A874..A877 ; N # Po [4] PHAGS-PA SINGLE HEAD MARK..PHAGS-PA MARK DOUBLE SHAD
+A880..A881 ; N # Mc [2] SAURASHTRA SIGN ANUSVARA..SAURASHTRA SIGN VISARGA
+A882..A8B3 ; N # Lo [50] SAURASHTRA LETTER A..SAURASHTRA LETTER LLA
+A8B4..A8C3 ; N # Mc [16] SAURASHTRA CONSONANT SIGN HAARU..SAURASHTRA VOWEL SIGN AU
+A8C4..A8C5 ; N # Mn [2] SAURASHTRA SIGN VIRAMA..SAURASHTRA SIGN CANDRABINDU
+A8CE..A8CF ; N # Po [2] SAURASHTRA DANDA..SAURASHTRA DOUBLE DANDA
+A8D0..A8D9 ; N # Nd [10] SAURASHTRA DIGIT ZERO..SAURASHTRA DIGIT NINE
+A8E0..A8F1 ; N # Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA
+A8F2..A8F7 ; N # Lo [6] DEVANAGARI SIGN SPACING CANDRABINDU..DEVANAGARI SIGN CANDRABINDU AVAGRAHA
+A8F8..A8FA ; N # Po [3] DEVANAGARI SIGN PUSHPIKA..DEVANAGARI CARET
+A8FB ; N # Lo DEVANAGARI HEADSTROKE
+A8FC ; N # Po DEVANAGARI SIGN SIDDHAM
+A8FD..A8FE ; N # Lo [2] DEVANAGARI JAIN OM..DEVANAGARI LETTER AY
+A8FF ; N # Mn DEVANAGARI VOWEL SIGN AY
+A900..A909 ; N # Nd [10] KAYAH LI DIGIT ZERO..KAYAH LI DIGIT NINE
+A90A..A925 ; N # Lo [28] KAYAH LI LETTER KA..KAYAH LI LETTER OO
+A926..A92D ; N # Mn [8] KAYAH LI VOWEL UE..KAYAH LI TONE CALYA PLOPHU
+A92E..A92F ; N # Po [2] KAYAH LI SIGN CWI..KAYAH LI SIGN SHYA
+A930..A946 ; N # Lo [23] REJANG LETTER KA..REJANG LETTER A
+A947..A951 ; N # Mn [11] REJANG VOWEL SIGN I..REJANG CONSONANT SIGN R
+A952..A953 ; N # Mc [2] REJANG CONSONANT SIGN H..REJANG VIRAMA
+A95F ; N # Po REJANG SECTION MARK
+A960..A97C ; W # Lo [29] HANGUL CHOSEONG TIKEUT-MIEUM..HANGUL CHOSEONG SSANGYEORINHIEUH
+A980..A982 ; N # Mn [3] JAVANESE SIGN PANYANGGA..JAVANESE SIGN LAYAR
+A983 ; N # Mc JAVANESE SIGN WIGNYAN
+A984..A9B2 ; N # Lo [47] JAVANESE LETTER A..JAVANESE LETTER HA
+A9B3 ; N # Mn JAVANESE SIGN CECAK TELU
+A9B4..A9B5 ; N # Mc [2] JAVANESE VOWEL SIGN TARUNG..JAVANESE VOWEL SIGN TOLONG
+A9B6..A9B9 ; N # Mn [4] JAVANESE VOWEL SIGN WULU..JAVANESE VOWEL SIGN SUKU MENDUT
+A9BA..A9BB ; N # Mc [2] JAVANESE VOWEL SIGN TALING..JAVANESE VOWEL SIGN DIRGA MURE
+A9BC..A9BD ; N # Mn [2] JAVANESE VOWEL SIGN PEPET..JAVANESE CONSONANT SIGN KERET
+A9BE..A9C0 ; N # Mc [3] JAVANESE CONSONANT SIGN PENGKAL..JAVANESE PANGKON
+A9C1..A9CD ; N # Po [13] JAVANESE LEFT RERENGGAN..JAVANESE TURNED PADA PISELEH
+A9CF ; N # Lm JAVANESE PANGRANGKEP
+A9D0..A9D9 ; N # Nd [10] JAVANESE DIGIT ZERO..JAVANESE DIGIT NINE
+A9DE..A9DF ; N # Po [2] JAVANESE PADA TIRTA TUMETES..JAVANESE PADA ISEN-ISEN
+A9E0..A9E4 ; N # Lo [5] MYANMAR LETTER SHAN GHA..MYANMAR LETTER SHAN BHA
+A9E5 ; N # Mn MYANMAR SIGN SHAN SAW
+A9E6 ; N # Lm MYANMAR MODIFIER LETTER SHAN REDUPLICATION
+A9E7..A9EF ; N # Lo [9] MYANMAR LETTER TAI LAING NYA..MYANMAR LETTER TAI LAING NNA
+A9F0..A9F9 ; N # Nd [10] MYANMAR TAI LAING DIGIT ZERO..MYANMAR TAI LAING DIGIT NINE
+A9FA..A9FE ; N # Lo [5] MYANMAR LETTER TAI LAING LLA..MYANMAR LETTER TAI LAING BHA
+AA00..AA28 ; N # Lo [41] CHAM LETTER A..CHAM LETTER HA
+AA29..AA2E ; N # Mn [6] CHAM VOWEL SIGN AA..CHAM VOWEL SIGN OE
+AA2F..AA30 ; N # Mc [2] CHAM VOWEL SIGN O..CHAM VOWEL SIGN AI
+AA31..AA32 ; N # Mn [2] CHAM VOWEL SIGN AU..CHAM VOWEL SIGN UE
+AA33..AA34 ; N # Mc [2] CHAM CONSONANT SIGN YA..CHAM CONSONANT SIGN RA
+AA35..AA36 ; N # Mn [2] CHAM CONSONANT SIGN LA..CHAM CONSONANT SIGN WA
+AA40..AA42 ; N # Lo [3] CHAM LETTER FINAL K..CHAM LETTER FINAL NG
+AA43 ; N # Mn CHAM CONSONANT SIGN FINAL NG
+AA44..AA4B ; N # Lo [8] CHAM LETTER FINAL CH..CHAM LETTER FINAL SS
+AA4C ; N # Mn CHAM CONSONANT SIGN FINAL M
+AA4D ; N # Mc CHAM CONSONANT SIGN FINAL H
+AA50..AA59 ; N # Nd [10] CHAM DIGIT ZERO..CHAM DIGIT NINE
+AA5C..AA5F ; N # Po [4] CHAM PUNCTUATION SPIRAL..CHAM PUNCTUATION TRIPLE DANDA
+AA60..AA6F ; N # Lo [16] MYANMAR LETTER KHAMTI GA..MYANMAR LETTER KHAMTI FA
+AA70 ; N # Lm MYANMAR MODIFIER LETTER KHAMTI REDUPLICATION
+AA71..AA76 ; N # Lo [6] MYANMAR LETTER KHAMTI XA..MYANMAR LOGOGRAM KHAMTI HM
+AA77..AA79 ; N # So [3] MYANMAR SYMBOL AITON EXCLAMATION..MYANMAR SYMBOL AITON TWO
+AA7A ; N # Lo MYANMAR LETTER AITON RA
+AA7B ; N # Mc MYANMAR SIGN PAO KAREN TONE
+AA7C ; N # Mn MYANMAR SIGN TAI LAING TONE-2
+AA7D ; N # Mc MYANMAR SIGN TAI LAING TONE-5
+AA7E..AA7F ; N # Lo [2] MYANMAR LETTER SHWE PALAUNG CHA..MYANMAR LETTER SHWE PALAUNG SHA
+AA80..AAAF ; N # Lo [48] TAI VIET LETTER LOW KO..TAI VIET LETTER HIGH O
+AAB0 ; N # Mn TAI VIET MAI KANG
+AAB1 ; N # Lo TAI VIET VOWEL AA
+AAB2..AAB4 ; N # Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U
+AAB5..AAB6 ; N # Lo [2] TAI VIET VOWEL E..TAI VIET VOWEL O
+AAB7..AAB8 ; N # Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA
+AAB9..AABD ; N # Lo [5] TAI VIET VOWEL UEA..TAI VIET VOWEL AN
+AABE..AABF ; N # Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK
+AAC0 ; N # Lo TAI VIET TONE MAI NUENG
+AAC1 ; N # Mn TAI VIET TONE MAI THO
+AAC2 ; N # Lo TAI VIET TONE MAI SONG
+AADB..AADC ; N # Lo [2] TAI VIET SYMBOL KON..TAI VIET SYMBOL NUENG
+AADD ; N # Lm TAI VIET SYMBOL SAM
+AADE..AADF ; N # Po [2] TAI VIET SYMBOL HO HOI..TAI VIET SYMBOL KOI KOI
+AAE0..AAEA ; N # Lo [11] MEETEI MAYEK LETTER E..MEETEI MAYEK LETTER SSA
+AAEB ; N # Mc MEETEI MAYEK VOWEL SIGN II
+AAEC..AAED ; N # Mn [2] MEETEI MAYEK VOWEL SIGN UU..MEETEI MAYEK VOWEL SIGN AAI
+AAEE..AAEF ; N # Mc [2] MEETEI MAYEK VOWEL SIGN AU..MEETEI MAYEK VOWEL SIGN AAU
+AAF0..AAF1 ; N # Po [2] MEETEI MAYEK CHEIKHAN..MEETEI MAYEK AHANG KHUDAM
+AAF2 ; N # Lo MEETEI MAYEK ANJI
+AAF3..AAF4 ; N # Lm [2] MEETEI MAYEK SYLLABLE REPETITION MARK..MEETEI MAYEK WORD REPETITION MARK
+AAF5 ; N # Mc MEETEI MAYEK VOWEL SIGN VISARGA
+AAF6 ; N # Mn MEETEI MAYEK VIRAMA
+AB01..AB06 ; N # Lo [6] ETHIOPIC SYLLABLE TTHU..ETHIOPIC SYLLABLE TTHO
+AB09..AB0E ; N # Lo [6] ETHIOPIC SYLLABLE DDHU..ETHIOPIC SYLLABLE DDHO
+AB11..AB16 ; N # Lo [6] ETHIOPIC SYLLABLE DZU..ETHIOPIC SYLLABLE DZO
+AB20..AB26 ; N # Lo [7] ETHIOPIC SYLLABLE CCHHA..ETHIOPIC SYLLABLE CCHHO
+AB28..AB2E ; N # Lo [7] ETHIOPIC SYLLABLE BBA..ETHIOPIC SYLLABLE BBO
+AB30..AB5A ; N # Ll [43] LATIN SMALL LETTER BARRED ALPHA..LATIN SMALL LETTER Y WITH SHORT RIGHT LEG
+AB5B ; N # Sk MODIFIER BREVE WITH INVERTED BREVE
+AB5C..AB5F ; N # Lm [4] MODIFIER LETTER SMALL HENG..MODIFIER LETTER SMALL U WITH LEFT HOOK
+AB60..AB68 ; N # Ll [9] LATIN SMALL LETTER SAKHA YAT..LATIN SMALL LETTER TURNED R WITH MIDDLE TILDE
+AB69 ; N # Lm MODIFIER LETTER SMALL TURNED W
+AB6A..AB6B ; N # Sk [2] MODIFIER LETTER LEFT TACK..MODIFIER LETTER RIGHT TACK
+AB70..ABBF ; N # Ll [80] CHEROKEE SMALL LETTER A..CHEROKEE SMALL LETTER YA
+ABC0..ABE2 ; N # Lo [35] MEETEI MAYEK LETTER KOK..MEETEI MAYEK LETTER I LONSUM
+ABE3..ABE4 ; N # Mc [2] MEETEI MAYEK VOWEL SIGN ONAP..MEETEI MAYEK VOWEL SIGN INAP
+ABE5 ; N # Mn MEETEI MAYEK VOWEL SIGN ANAP
+ABE6..ABE7 ; N # Mc [2] MEETEI MAYEK VOWEL SIGN YENAP..MEETEI MAYEK VOWEL SIGN SOUNAP
+ABE8 ; N # Mn MEETEI MAYEK VOWEL SIGN UNAP
+ABE9..ABEA ; N # Mc [2] MEETEI MAYEK VOWEL SIGN CHEINAP..MEETEI MAYEK VOWEL SIGN NUNG
+ABEB ; N # Po MEETEI MAYEK CHEIKHEI
+ABEC ; N # Mc MEETEI MAYEK LUM IYEK
+ABED ; N # Mn MEETEI MAYEK APUN IYEK
+ABF0..ABF9 ; N # Nd [10] MEETEI MAYEK DIGIT ZERO..MEETEI MAYEK DIGIT NINE
+AC00..D7A3 ; W # Lo [11172] HANGUL SYLLABLE GA..HANGUL SYLLABLE HIH
+D7B0..D7C6 ; N # Lo [23] HANGUL JUNGSEONG O-YEO..HANGUL JUNGSEONG ARAEA-E
+D7CB..D7FB ; N # Lo [49] HANGUL JONGSEONG NIEUN-RIEUL..HANGUL JONGSEONG PHIEUPH-THIEUTH
+D800..DB7F ; N # Cs [896] <surrogate-D800>..<surrogate-DB7F>
+DB80..DBFF ; N # Cs [128] <surrogate-DB80>..<surrogate-DBFF>
+DC00..DFFF ; N # Cs [1024] <surrogate-DC00>..<surrogate-DFFF>
+E000..F8FF ; A # Co [6400] <private-use-E000>..<private-use-F8FF>
+F900..FA6D ; W # Lo [366] CJK COMPATIBILITY IDEOGRAPH-F900..CJK COMPATIBILITY IDEOGRAPH-FA6D
+FA6E..FA6F ; W # Cn [2] <reserved-FA6E>..<reserved-FA6F>
+FA70..FAD9 ; W # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COMPATIBILITY IDEOGRAPH-FAD9
+FADA..FAFF ; W # Cn [38] <reserved-FADA>..<reserved-FAFF>
+FB00..FB06 ; N # Ll [7] LATIN SMALL LIGATURE FF..LATIN SMALL LIGATURE ST
+FB13..FB17 ; N # Ll [5] ARMENIAN SMALL LIGATURE MEN NOW..ARMENIAN SMALL LIGATURE MEN XEH
+FB1D ; N # Lo HEBREW LETTER YOD WITH HIRIQ
+FB1E ; N # Mn HEBREW POINT JUDEO-SPANISH VARIKA
+FB1F..FB28 ; N # Lo [10] HEBREW LIGATURE YIDDISH YOD YOD PATAH..HEBREW LETTER WIDE TAV
+FB29 ; N # Sm HEBREW LETTER ALTERNATIVE PLUS SIGN
+FB2A..FB36 ; N # Lo [13] HEBREW LETTER SHIN WITH SHIN DOT..HEBREW LETTER ZAYIN WITH DAGESH
+FB38..FB3C ; N # Lo [5] HEBREW LETTER TET WITH DAGESH..HEBREW LETTER LAMED WITH DAGESH
+FB3E ; N # Lo HEBREW LETTER MEM WITH DAGESH
+FB40..FB41 ; N # Lo [2] HEBREW LETTER NUN WITH DAGESH..HEBREW LETTER SAMEKH WITH DAGESH
+FB43..FB44 ; N # Lo [2] HEBREW LETTER FINAL PE WITH DAGESH..HEBREW LETTER PE WITH DAGESH
+FB46..FB4F ; N # Lo [10] HEBREW LETTER TSADI WITH DAGESH..HEBREW LIGATURE ALEF LAMED
+FB50..FBB1 ; N # Lo [98] ARABIC LETTER ALEF WASLA ISOLATED FORM..ARABIC LETTER YEH BARREE WITH HAMZA ABOVE FINAL FORM
+FBB2..FBC2 ; N # Sk [17] ARABIC SYMBOL DOT ABOVE..ARABIC SYMBOL WASLA ABOVE
+FBD3..FD3D ; N # Lo [363] ARABIC LETTER NG ISOLATED FORM..ARABIC LIGATURE ALEF WITH FATHATAN ISOLATED FORM
+FD3E ; N # Pe ORNATE LEFT PARENTHESIS
+FD3F ; N # Ps ORNATE RIGHT PARENTHESIS
+FD40..FD4F ; N # So [16] ARABIC LIGATURE RAHIMAHU ALLAAH..ARABIC LIGATURE RAHIMAHUM ALLAAH
+FD50..FD8F ; N # Lo [64] ARABIC LIGATURE TEH WITH JEEM WITH MEEM INITIAL FORM..ARABIC LIGATURE MEEM WITH KHAH WITH MEEM INITIAL FORM
+FD92..FDC7 ; N # Lo [54] ARABIC LIGATURE MEEM WITH JEEM WITH KHAH INITIAL FORM..ARABIC LIGATURE NOON WITH JEEM WITH YEH FINAL FORM
+FDCF ; N # So ARABIC LIGATURE SALAAMUHU ALAYNAA
+FDF0..FDFB ; N # Lo [12] ARABIC LIGATURE SALLA USED AS KORANIC STOP SIGN ISOLATED FORM..ARABIC LIGATURE JALLAJALALOUHOU
+FDFC ; N # Sc RIAL SIGN
+FDFD..FDFF ; N # So [3] ARABIC LIGATURE BISMILLAH AR-RAHMAN AR-RAHEEM..ARABIC LIGATURE AZZA WA JALL
+FE00..FE0F ; A # Mn [16] VARIATION SELECTOR-1..VARIATION SELECTOR-16
+FE10..FE16 ; W # Po [7] PRESENTATION FORM FOR VERTICAL COMMA..PRESENTATION FORM FOR VERTICAL QUESTION MARK
+FE17 ; W # Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE LENTICULAR BRACKET
+FE18 ; W # Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE LENTICULAR BRAKCET
+FE19 ; W # Po PRESENTATION FORM FOR VERTICAL HORIZONTAL ELLIPSIS
+FE20..FE2F ; N # Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
+FE30 ; W # Po PRESENTATION FORM FOR VERTICAL TWO DOT LEADER
+FE31..FE32 ; W # Pd [2] PRESENTATION FORM FOR VERTICAL EM DASH..PRESENTATION FORM FOR VERTICAL EN DASH
+FE33..FE34 ; W # Pc [2] PRESENTATION FORM FOR VERTICAL LOW LINE..PRESENTATION FORM FOR VERTICAL WAVY LOW LINE
+FE35 ; W # Ps PRESENTATION FORM FOR VERTICAL LEFT PARENTHESIS
+FE36 ; W # Pe PRESENTATION FORM FOR VERTICAL RIGHT PARENTHESIS
+FE37 ; W # Ps PRESENTATION FORM FOR VERTICAL LEFT CURLY BRACKET
+FE38 ; W # Pe PRESENTATION FORM FOR VERTICAL RIGHT CURLY BRACKET
+FE39 ; W # Ps PRESENTATION FORM FOR VERTICAL LEFT TORTOISE SHELL BRACKET
+FE3A ; W # Pe PRESENTATION FORM FOR VERTICAL RIGHT TORTOISE SHELL BRACKET
+FE3B ; W # Ps PRESENTATION FORM FOR VERTICAL LEFT BLACK LENTICULAR BRACKET
+FE3C ; W # Pe PRESENTATION FORM FOR VERTICAL RIGHT BLACK LENTICULAR BRACKET
+FE3D ; W # Ps PRESENTATION FORM FOR VERTICAL LEFT DOUBLE ANGLE BRACKET
+FE3E ; W # Pe PRESENTATION FORM FOR VERTICAL RIGHT DOUBLE ANGLE BRACKET
+FE3F ; W # Ps PRESENTATION FORM FOR VERTICAL LEFT ANGLE BRACKET
+FE40 ; W # Pe PRESENTATION FORM FOR VERTICAL RIGHT ANGLE BRACKET
+FE41 ; W # Ps PRESENTATION FORM FOR VERTICAL LEFT CORNER BRACKET
+FE42 ; W # Pe PRESENTATION FORM FOR VERTICAL RIGHT CORNER BRACKET
+FE43 ; W # Ps PRESENTATION FORM FOR VERTICAL LEFT WHITE CORNER BRACKET
+FE44 ; W # Pe PRESENTATION FORM FOR VERTICAL RIGHT WHITE CORNER BRACKET
+FE45..FE46 ; W # Po [2] SESAME DOT..WHITE SESAME DOT
+FE47 ; W # Ps PRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET
+FE48 ; W # Pe PRESENTATION FORM FOR VERTICAL RIGHT SQUARE BRACKET
+FE49..FE4C ; W # Po [4] DASHED OVERLINE..DOUBLE WAVY OVERLINE
+FE4D..FE4F ; W # Pc [3] DASHED LOW LINE..WAVY LOW LINE
+FE50..FE52 ; W # Po [3] SMALL COMMA..SMALL FULL STOP
+FE54..FE57 ; W # Po [4] SMALL SEMICOLON..SMALL EXCLAMATION MARK
+FE58 ; W # Pd SMALL EM DASH
+FE59 ; W # Ps SMALL LEFT PARENTHESIS
+FE5A ; W # Pe SMALL RIGHT PARENTHESIS
+FE5B ; W # Ps SMALL LEFT CURLY BRACKET
+FE5C ; W # Pe SMALL RIGHT CURLY BRACKET
+FE5D ; W # Ps SMALL LEFT TORTOISE SHELL BRACKET
+FE5E ; W # Pe SMALL RIGHT TORTOISE SHELL BRACKET
+FE5F..FE61 ; W # Po [3] SMALL NUMBER SIGN..SMALL ASTERISK
+FE62 ; W # Sm SMALL PLUS SIGN
+FE63 ; W # Pd SMALL HYPHEN-MINUS
+FE64..FE66 ; W # Sm [3] SMALL LESS-THAN SIGN..SMALL EQUALS SIGN
+FE68 ; W # Po SMALL REVERSE SOLIDUS
+FE69 ; W # Sc SMALL DOLLAR SIGN
+FE6A..FE6B ; W # Po [2] SMALL PERCENT SIGN..SMALL COMMERCIAL AT
+FE70..FE74 ; N # Lo [5] ARABIC FATHATAN ISOLATED FORM..ARABIC KASRATAN ISOLATED FORM
+FE76..FEFC ; N # Lo [135] ARABIC FATHA ISOLATED FORM..ARABIC LIGATURE LAM WITH ALEF FINAL FORM
+FEFF ; N # Cf ZERO WIDTH NO-BREAK SPACE
+FF01..FF03 ; F # Po [3] FULLWIDTH EXCLAMATION MARK..FULLWIDTH NUMBER SIGN
+FF04 ; F # Sc FULLWIDTH DOLLAR SIGN
+FF05..FF07 ; F # Po [3] FULLWIDTH PERCENT SIGN..FULLWIDTH APOSTROPHE
+FF08 ; F # Ps FULLWIDTH LEFT PARENTHESIS
+FF09 ; F # Pe FULLWIDTH RIGHT PARENTHESIS
+FF0A ; F # Po FULLWIDTH ASTERISK
+FF0B ; F # Sm FULLWIDTH PLUS SIGN
+FF0C ; F # Po FULLWIDTH COMMA
+FF0D ; F # Pd FULLWIDTH HYPHEN-MINUS
+FF0E..FF0F ; F # Po [2] FULLWIDTH FULL STOP..FULLWIDTH SOLIDUS
+FF10..FF19 ; F # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NINE
+FF1A..FF1B ; F # Po [2] FULLWIDTH COLON..FULLWIDTH SEMICOLON
+FF1C..FF1E ; F # Sm [3] FULLWIDTH LESS-THAN SIGN..FULLWIDTH GREATER-THAN SIGN
+FF1F..FF20 ; F # Po [2] FULLWIDTH QUESTION MARK..FULLWIDTH COMMERCIAL AT
+FF21..FF3A ; F # Lu [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z
+FF3B ; F # Ps FULLWIDTH LEFT SQUARE BRACKET
+FF3C ; F # Po FULLWIDTH REVERSE SOLIDUS
+FF3D ; F # Pe FULLWIDTH RIGHT SQUARE BRACKET
+FF3E ; F # Sk FULLWIDTH CIRCUMFLEX ACCENT
+FF3F ; F # Pc FULLWIDTH LOW LINE
+FF40 ; F # Sk FULLWIDTH GRAVE ACCENT
+FF41..FF5A ; F # Ll [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z
+FF5B ; F # Ps FULLWIDTH LEFT CURLY BRACKET
+FF5C ; F # Sm FULLWIDTH VERTICAL LINE
+FF5D ; F # Pe FULLWIDTH RIGHT CURLY BRACKET
+FF5E ; F # Sm FULLWIDTH TILDE
+FF5F ; F # Ps FULLWIDTH LEFT WHITE PARENTHESIS
+FF60 ; F # Pe FULLWIDTH RIGHT WHITE PARENTHESIS
+FF61 ; H # Po HALFWIDTH IDEOGRAPHIC FULL STOP
+FF62 ; H # Ps HALFWIDTH LEFT CORNER BRACKET
+FF63 ; H # Pe HALFWIDTH RIGHT CORNER BRACKET
+FF64..FF65 ; H # Po [2] HALFWIDTH IDEOGRAPHIC COMMA..HALFWIDTH KATAKANA MIDDLE DOT
+FF66..FF6F ; H # Lo [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU
+FF70 ; H # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
+FF71..FF9D ; H # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N
+FF9E..FF9F ; H # Lm [2] HALFWIDTH KATAKANA VOICED SOUND MARK..HALFWIDTH KATAKANA SEMI-VOICED SOUND MARK
+FFA0..FFBE ; H # Lo [31] HALFWIDTH HANGUL FILLER..HALFWIDTH HANGUL LETTER HIEUH
+FFC2..FFC7 ; H # Lo [6] HALFWIDTH HANGUL LETTER A..HALFWIDTH HANGUL LETTER E
+FFCA..FFCF ; H # Lo [6] HALFWIDTH HANGUL LETTER YEO..HALFWIDTH HANGUL LETTER OE
+FFD2..FFD7 ; H # Lo [6] HALFWIDTH HANGUL LETTER YO..HALFWIDTH HANGUL LETTER YU
+FFDA..FFDC ; H # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL LETTER I
+FFE0..FFE1 ; F # Sc [2] FULLWIDTH CENT SIGN..FULLWIDTH POUND SIGN
+FFE2 ; F # Sm FULLWIDTH NOT SIGN
+FFE3 ; F # Sk FULLWIDTH MACRON
+FFE4 ; F # So FULLWIDTH BROKEN BAR
+FFE5..FFE6 ; F # Sc [2] FULLWIDTH YEN SIGN..FULLWIDTH WON SIGN
+FFE8 ; H # So HALFWIDTH FORMS LIGHT VERTICAL
+FFE9..FFEC ; H # Sm [4] HALFWIDTH LEFTWARDS ARROW..HALFWIDTH DOWNWARDS ARROW
+FFED..FFEE ; H # So [2] HALFWIDTH BLACK SQUARE..HALFWIDTH WHITE CIRCLE
+FFF9..FFFB ; N # Cf [3] INTERLINEAR ANNOTATION ANCHOR..INTERLINEAR ANNOTATION TERMINATOR
+FFFC ; N # So OBJECT REPLACEMENT CHARACTER
+FFFD ; A # So REPLACEMENT CHARACTER
+10000..1000B ; N # Lo [12] LINEAR B SYLLABLE B008 A..LINEAR B SYLLABLE B046 JE
+1000D..10026 ; N # Lo [26] LINEAR B SYLLABLE B036 JO..LINEAR B SYLLABLE B032 QO
+10028..1003A ; N # Lo [19] LINEAR B SYLLABLE B060 RA..LINEAR B SYLLABLE B042 WO
+1003C..1003D ; N # Lo [2] LINEAR B SYLLABLE B017 ZA..LINEAR B SYLLABLE B074 ZE
+1003F..1004D ; N # Lo [15] LINEAR B SYLLABLE B020 ZO..LINEAR B SYLLABLE B091 TWO
+10050..1005D ; N # Lo [14] LINEAR B SYMBOL B018..LINEAR B SYMBOL B089
+10080..100FA ; N # Lo [123] LINEAR B IDEOGRAM B100 MAN..LINEAR B IDEOGRAM VESSEL B305
+10100..10102 ; N # Po [3] AEGEAN WORD SEPARATOR LINE..AEGEAN CHECK MARK
+10107..10133 ; N # No [45] AEGEAN NUMBER ONE..AEGEAN NUMBER NINETY THOUSAND
+10137..1013F ; N # So [9] AEGEAN WEIGHT BASE UNIT..AEGEAN MEASURE THIRD SUBUNIT
+10140..10174 ; N # Nl [53] GREEK ACROPHONIC ATTIC ONE QUARTER..GREEK ACROPHONIC STRATIAN FIFTY MNAS
+10175..10178 ; N # No [4] GREEK ONE HALF SIGN..GREEK THREE QUARTERS SIGN
+10179..10189 ; N # So [17] GREEK YEAR SIGN..GREEK TRYBLION BASE SIGN
+1018A..1018B ; N # No [2] GREEK ZERO SIGN..GREEK ONE QUARTER SIGN
+1018C..1018E ; N # So [3] GREEK SINUSOID SIGN..NOMISMA SIGN
+10190..1019C ; N # So [13] ROMAN SEXTANS SIGN..ASCIA SYMBOL
+101A0 ; N # So GREEK SYMBOL TAU RHO
+101D0..101FC ; N # So [45] PHAISTOS DISC SIGN PEDESTRIAN..PHAISTOS DISC SIGN WAVY BAND
+101FD ; N # Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE
+10280..1029C ; N # Lo [29] LYCIAN LETTER A..LYCIAN LETTER X
+102A0..102D0 ; N # Lo [49] CARIAN LETTER A..CARIAN LETTER UUU3
+102E0 ; N # Mn COPTIC EPACT THOUSANDS MARK
+102E1..102FB ; N # No [27] COPTIC EPACT DIGIT ONE..COPTIC EPACT NUMBER NINE HUNDRED
+10300..1031F ; N # Lo [32] OLD ITALIC LETTER A..OLD ITALIC LETTER ESS
+10320..10323 ; N # No [4] OLD ITALIC NUMERAL ONE..OLD ITALIC NUMERAL FIFTY
+1032D..1032F ; N # Lo [3] OLD ITALIC LETTER YE..OLD ITALIC LETTER SOUTHERN TSE
+10330..10340 ; N # Lo [17] GOTHIC LETTER AHSA..GOTHIC LETTER PAIRTHRA
+10341 ; N # Nl GOTHIC LETTER NINETY
+10342..10349 ; N # Lo [8] GOTHIC LETTER RAIDA..GOTHIC LETTER OTHAL
+1034A ; N # Nl GOTHIC LETTER NINE HUNDRED
+10350..10375 ; N # Lo [38] OLD PERMIC LETTER AN..OLD PERMIC LETTER IA
+10376..1037A ; N # Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII
+10380..1039D ; N # Lo [30] UGARITIC LETTER ALPA..UGARITIC LETTER SSU
+1039F ; N # Po UGARITIC WORD DIVIDER
+103A0..103C3 ; N # Lo [36] OLD PERSIAN SIGN A..OLD PERSIAN SIGN HA
+103C8..103CF ; N # Lo [8] OLD PERSIAN SIGN AURAMAZDAA..OLD PERSIAN SIGN BUUMISH
+103D0 ; N # Po OLD PERSIAN WORD DIVIDER
+103D1..103D5 ; N # Nl [5] OLD PERSIAN NUMBER ONE..OLD PERSIAN NUMBER HUNDRED
+10400..1044F ; N # L& [80] DESERET CAPITAL LETTER LONG I..DESERET SMALL LETTER EW
+10450..1047F ; N # Lo [48] SHAVIAN LETTER PEEP..SHAVIAN LETTER YEW
+10480..1049D ; N # Lo [30] OSMANYA LETTER ALEF..OSMANYA LETTER OO
+104A0..104A9 ; N # Nd [10] OSMANYA DIGIT ZERO..OSMANYA DIGIT NINE
+104B0..104D3 ; N # Lu [36] OSAGE CAPITAL LETTER A..OSAGE CAPITAL LETTER ZHA
+104D8..104FB ; N # Ll [36] OSAGE SMALL LETTER A..OSAGE SMALL LETTER ZHA
+10500..10527 ; N # Lo [40] ELBASAN LETTER A..ELBASAN LETTER KHE
+10530..10563 ; N # Lo [52] CAUCASIAN ALBANIAN LETTER ALT..CAUCASIAN ALBANIAN LETTER KIW
+1056F ; N # Po CAUCASIAN ALBANIAN CITATION MARK
+10570..1057A ; N # Lu [11] VITHKUQI CAPITAL LETTER A..VITHKUQI CAPITAL LETTER GA
+1057C..1058A ; N # Lu [15] VITHKUQI CAPITAL LETTER HA..VITHKUQI CAPITAL LETTER RE
+1058C..10592 ; N # Lu [7] VITHKUQI CAPITAL LETTER SE..VITHKUQI CAPITAL LETTER XE
+10594..10595 ; N # Lu [2] VITHKUQI CAPITAL LETTER Y..VITHKUQI CAPITAL LETTER ZE
+10597..105A1 ; N # Ll [11] VITHKUQI SMALL LETTER A..VITHKUQI SMALL LETTER GA
+105A3..105B1 ; N # Ll [15] VITHKUQI SMALL LETTER HA..VITHKUQI SMALL LETTER RE
+105B3..105B9 ; N # Ll [7] VITHKUQI SMALL LETTER SE..VITHKUQI SMALL LETTER XE
+105BB..105BC ; N # Ll [2] VITHKUQI SMALL LETTER Y..VITHKUQI SMALL LETTER ZE
+10600..10736 ; N # Lo [311] LINEAR A SIGN AB001..LINEAR A SIGN A664
+10740..10755 ; N # Lo [22] LINEAR A SIGN A701 A..LINEAR A SIGN A732 JE
+10760..10767 ; N # Lo [8] LINEAR A SIGN A800..LINEAR A SIGN A807
+10780..10785 ; N # Lm [6] MODIFIER LETTER SMALL CAPITAL AA..MODIFIER LETTER SMALL B WITH HOOK
+10787..107B0 ; N # Lm [42] MODIFIER LETTER SMALL DZ DIGRAPH..MODIFIER LETTER SMALL V WITH RIGHT HOOK
+107B2..107BA ; N # Lm [9] MODIFIER LETTER SMALL CAPITAL Y..MODIFIER LETTER SMALL S WITH CURL
+10800..10805 ; N # Lo [6] CYPRIOT SYLLABLE A..CYPRIOT SYLLABLE JA
+10808 ; N # Lo CYPRIOT SYLLABLE JO
+1080A..10835 ; N # Lo [44] CYPRIOT SYLLABLE KA..CYPRIOT SYLLABLE WO
+10837..10838 ; N # Lo [2] CYPRIOT SYLLABLE XA..CYPRIOT SYLLABLE XE
+1083C ; N # Lo CYPRIOT SYLLABLE ZA
+1083F ; N # Lo CYPRIOT SYLLABLE ZO
+10840..10855 ; N # Lo [22] IMPERIAL ARAMAIC LETTER ALEPH..IMPERIAL ARAMAIC LETTER TAW
+10857 ; N # Po IMPERIAL ARAMAIC SECTION SIGN
+10858..1085F ; N # No [8] IMPERIAL ARAMAIC NUMBER ONE..IMPERIAL ARAMAIC NUMBER TEN THOUSAND
+10860..10876 ; N # Lo [23] PALMYRENE LETTER ALEPH..PALMYRENE LETTER TAW
+10877..10878 ; N # So [2] PALMYRENE LEFT-POINTING FLEURON..PALMYRENE RIGHT-POINTING FLEURON
+10879..1087F ; N # No [7] PALMYRENE NUMBER ONE..PALMYRENE NUMBER TWENTY
+10880..1089E ; N # Lo [31] NABATAEAN LETTER FINAL ALEPH..NABATAEAN LETTER TAW
+108A7..108AF ; N # No [9] NABATAEAN NUMBER ONE..NABATAEAN NUMBER ONE HUNDRED
+108E0..108F2 ; N # Lo [19] HATRAN LETTER ALEPH..HATRAN LETTER QOPH
+108F4..108F5 ; N # Lo [2] HATRAN LETTER SHIN..HATRAN LETTER TAW
+108FB..108FF ; N # No [5] HATRAN NUMBER ONE..HATRAN NUMBER ONE HUNDRED
+10900..10915 ; N # Lo [22] PHOENICIAN LETTER ALF..PHOENICIAN LETTER TAU
+10916..1091B ; N # No [6] PHOENICIAN NUMBER ONE..PHOENICIAN NUMBER THREE
+1091F ; N # Po PHOENICIAN WORD SEPARATOR
+10920..10939 ; N # Lo [26] LYDIAN LETTER A..LYDIAN LETTER C
+1093F ; N # Po LYDIAN TRIANGULAR MARK
+10980..1099F ; N # Lo [32] MEROITIC HIEROGLYPHIC LETTER A..MEROITIC HIEROGLYPHIC SYMBOL VIDJ-2
+109A0..109B7 ; N # Lo [24] MEROITIC CURSIVE LETTER A..MEROITIC CURSIVE LETTER DA
+109BC..109BD ; N # No [2] MEROITIC CURSIVE FRACTION ELEVEN TWELFTHS..MEROITIC CURSIVE FRACTION ONE HALF
+109BE..109BF ; N # Lo [2] MEROITIC CURSIVE LOGOGRAM RMT..MEROITIC CURSIVE LOGOGRAM IMN
+109C0..109CF ; N # No [16] MEROITIC CURSIVE NUMBER ONE..MEROITIC CURSIVE NUMBER SEVENTY
+109D2..109FF ; N # No [46] MEROITIC CURSIVE NUMBER ONE HUNDRED..MEROITIC CURSIVE FRACTION TEN TWELFTHS
+10A00 ; N # Lo KHAROSHTHI LETTER A
+10A01..10A03 ; N # Mn [3] KHAROSHTHI VOWEL SIGN I..KHAROSHTHI VOWEL SIGN VOCALIC R
+10A05..10A06 ; N # Mn [2] KHAROSHTHI VOWEL SIGN E..KHAROSHTHI VOWEL SIGN O
+10A0C..10A0F ; N # Mn [4] KHAROSHTHI VOWEL LENGTH MARK..KHAROSHTHI SIGN VISARGA
+10A10..10A13 ; N # Lo [4] KHAROSHTHI LETTER KA..KHAROSHTHI LETTER GHA
+10A15..10A17 ; N # Lo [3] KHAROSHTHI LETTER CA..KHAROSHTHI LETTER JA
+10A19..10A35 ; N # Lo [29] KHAROSHTHI LETTER NYA..KHAROSHTHI LETTER VHA
+10A38..10A3A ; N # Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW
+10A3F ; N # Mn KHAROSHTHI VIRAMA
+10A40..10A48 ; N # No [9] KHAROSHTHI DIGIT ONE..KHAROSHTHI FRACTION ONE HALF
+10A50..10A58 ; N # Po [9] KHAROSHTHI PUNCTUATION DOT..KHAROSHTHI PUNCTUATION LINES
+10A60..10A7C ; N # Lo [29] OLD SOUTH ARABIAN LETTER HE..OLD SOUTH ARABIAN LETTER THETH
+10A7D..10A7E ; N # No [2] OLD SOUTH ARABIAN NUMBER ONE..OLD SOUTH ARABIAN NUMBER FIFTY
+10A7F ; N # Po OLD SOUTH ARABIAN NUMERIC INDICATOR
+10A80..10A9C ; N # Lo [29] OLD NORTH ARABIAN LETTER HEH..OLD NORTH ARABIAN LETTER ZAH
+10A9D..10A9F ; N # No [3] OLD NORTH ARABIAN NUMBER ONE..OLD NORTH ARABIAN NUMBER TWENTY
+10AC0..10AC7 ; N # Lo [8] MANICHAEAN LETTER ALEPH..MANICHAEAN LETTER WAW
+10AC8 ; N # So MANICHAEAN SIGN UD
+10AC9..10AE4 ; N # Lo [28] MANICHAEAN LETTER ZAYIN..MANICHAEAN LETTER TAW
+10AE5..10AE6 ; N # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW
+10AEB..10AEF ; N # No [5] MANICHAEAN NUMBER ONE..MANICHAEAN NUMBER ONE HUNDRED
+10AF0..10AF6 ; N # Po [7] MANICHAEAN PUNCTUATION STAR..MANICHAEAN PUNCTUATION LINE FILLER
+10B00..10B35 ; N # Lo [54] AVESTAN LETTER A..AVESTAN LETTER HE
+10B39..10B3F ; N # Po [7] AVESTAN ABBREVIATION MARK..LARGE ONE RING OVER TWO RINGS PUNCTUATION
+10B40..10B55 ; N # Lo [22] INSCRIPTIONAL PARTHIAN LETTER ALEPH..INSCRIPTIONAL PARTHIAN LETTER TAW
+10B58..10B5F ; N # No [8] INSCRIPTIONAL PARTHIAN NUMBER ONE..INSCRIPTIONAL PARTHIAN NUMBER ONE THOUSAND
+10B60..10B72 ; N # Lo [19] INSCRIPTIONAL PAHLAVI LETTER ALEPH..INSCRIPTIONAL PAHLAVI LETTER TAW
+10B78..10B7F ; N # No [8] INSCRIPTIONAL PAHLAVI NUMBER ONE..INSCRIPTIONAL PAHLAVI NUMBER ONE THOUSAND
+10B80..10B91 ; N # Lo [18] PSALTER PAHLAVI LETTER ALEPH..PSALTER PAHLAVI LETTER TAW
+10B99..10B9C ; N # Po [4] PSALTER PAHLAVI SECTION MARK..PSALTER PAHLAVI FOUR DOTS WITH DOT
+10BA9..10BAF ; N # No [7] PSALTER PAHLAVI NUMBER ONE..PSALTER PAHLAVI NUMBER ONE HUNDRED
+10C00..10C48 ; N # Lo [73] OLD TURKIC LETTER ORKHON A..OLD TURKIC LETTER ORKHON BASH
+10C80..10CB2 ; N # Lu [51] OLD HUNGARIAN CAPITAL LETTER A..OLD HUNGARIAN CAPITAL LETTER US
+10CC0..10CF2 ; N # Ll [51] OLD HUNGARIAN SMALL LETTER A..OLD HUNGARIAN SMALL LETTER US
+10CFA..10CFF ; N # No [6] OLD HUNGARIAN NUMBER ONE..OLD HUNGARIAN NUMBER ONE THOUSAND
+10D00..10D23 ; N # Lo [36] HANIFI ROHINGYA LETTER A..HANIFI ROHINGYA MARK NA KHONNA
+10D24..10D27 ; N # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
+10D30..10D39 ; N # Nd [10] HANIFI ROHINGYA DIGIT ZERO..HANIFI ROHINGYA DIGIT NINE
+10E60..10E7E ; N # No [31] RUMI DIGIT ONE..RUMI FRACTION TWO THIRDS
+10E80..10EA9 ; N # Lo [42] YEZIDI LETTER ELIF..YEZIDI LETTER ET
+10EAB..10EAC ; N # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
+10EAD ; N # Pd YEZIDI HYPHENATION MARK
+10EB0..10EB1 ; N # Lo [2] YEZIDI LETTER LAM WITH DOT ABOVE..YEZIDI LETTER YOT WITH CIRCUMFLEX ABOVE
+10EFD..10EFF ; N # Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA
+10F00..10F1C ; N # Lo [29] OLD SOGDIAN LETTER ALEPH..OLD SOGDIAN LETTER FINAL TAW WITH VERTICAL TAIL
+10F1D..10F26 ; N # No [10] OLD SOGDIAN NUMBER ONE..OLD SOGDIAN FRACTION ONE HALF
+10F27 ; N # Lo OLD SOGDIAN LIGATURE AYIN-DALETH
+10F30..10F45 ; N # Lo [22] SOGDIAN LETTER ALEPH..SOGDIAN INDEPENDENT SHIN
+10F46..10F50 ; N # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
+10F51..10F54 ; N # No [4] SOGDIAN NUMBER ONE..SOGDIAN NUMBER ONE HUNDRED
+10F55..10F59 ; N # Po [5] SOGDIAN PUNCTUATION TWO VERTICAL BARS..SOGDIAN PUNCTUATION HALF CIRCLE WITH DOT
+10F70..10F81 ; N # Lo [18] OLD UYGHUR LETTER ALEPH..OLD UYGHUR LETTER LESH
+10F82..10F85 ; N # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW
+10F86..10F89 ; N # Po [4] OLD UYGHUR PUNCTUATION BAR..OLD UYGHUR PUNCTUATION FOUR DOTS
+10FB0..10FC4 ; N # Lo [21] CHORASMIAN LETTER ALEPH..CHORASMIAN LETTER TAW
+10FC5..10FCB ; N # No [7] CHORASMIAN NUMBER ONE..CHORASMIAN NUMBER ONE HUNDRED
+10FE0..10FF6 ; N # Lo [23] ELYMAIC LETTER ALEPH..ELYMAIC LIGATURE ZAYIN-YODH
+11000 ; N # Mc BRAHMI SIGN CANDRABINDU
+11001 ; N # Mn BRAHMI SIGN ANUSVARA
+11002 ; N # Mc BRAHMI SIGN VISARGA
+11003..11037 ; N # Lo [53] BRAHMI SIGN JIHVAMULIYA..BRAHMI LETTER OLD TAMIL NNNA
+11038..11046 ; N # Mn [15] BRAHMI VOWEL SIGN AA..BRAHMI VIRAMA
+11047..1104D ; N # Po [7] BRAHMI DANDA..BRAHMI PUNCTUATION LOTUS
+11052..11065 ; N # No [20] BRAHMI NUMBER ONE..BRAHMI NUMBER ONE THOUSAND
+11066..1106F ; N # Nd [10] BRAHMI DIGIT ZERO..BRAHMI DIGIT NINE
+11070 ; N # Mn BRAHMI SIGN OLD TAMIL VIRAMA
+11071..11072 ; N # Lo [2] BRAHMI LETTER OLD TAMIL SHORT E..BRAHMI LETTER OLD TAMIL SHORT O
+11073..11074 ; N # Mn [2] BRAHMI VOWEL SIGN OLD TAMIL SHORT E..BRAHMI VOWEL SIGN OLD TAMIL SHORT O
+11075 ; N # Lo BRAHMI LETTER OLD TAMIL LLA
+1107F ; N # Mn BRAHMI NUMBER JOINER
+11080..11081 ; N # Mn [2] KAITHI SIGN CANDRABINDU..KAITHI SIGN ANUSVARA
+11082 ; N # Mc KAITHI SIGN VISARGA
+11083..110AF ; N # Lo [45] KAITHI LETTER A..KAITHI LETTER HA
+110B0..110B2 ; N # Mc [3] KAITHI VOWEL SIGN AA..KAITHI VOWEL SIGN II
+110B3..110B6 ; N # Mn [4] KAITHI VOWEL SIGN U..KAITHI VOWEL SIGN AI
+110B7..110B8 ; N # Mc [2] KAITHI VOWEL SIGN O..KAITHI VOWEL SIGN AU
+110B9..110BA ; N # Mn [2] KAITHI SIGN VIRAMA..KAITHI SIGN NUKTA
+110BB..110BC ; N # Po [2] KAITHI ABBREVIATION SIGN..KAITHI ENUMERATION SIGN
+110BD ; N # Cf KAITHI NUMBER SIGN
+110BE..110C1 ; N # Po [4] KAITHI SECTION MARK..KAITHI DOUBLE DANDA
+110C2 ; N # Mn KAITHI VOWEL SIGN VOCALIC R
+110CD ; N # Cf KAITHI NUMBER SIGN ABOVE
+110D0..110E8 ; N # Lo [25] SORA SOMPENG LETTER SAH..SORA SOMPENG LETTER MAE
+110F0..110F9 ; N # Nd [10] SORA SOMPENG DIGIT ZERO..SORA SOMPENG DIGIT NINE
+11100..11102 ; N # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA
+11103..11126 ; N # Lo [36] CHAKMA LETTER AA..CHAKMA LETTER HAA
+11127..1112B ; N # Mn [5] CHAKMA VOWEL SIGN A..CHAKMA VOWEL SIGN UU
+1112C ; N # Mc CHAKMA VOWEL SIGN E
+1112D..11134 ; N # Mn [8] CHAKMA VOWEL SIGN AI..CHAKMA MAAYYAA
+11136..1113F ; N # Nd [10] CHAKMA DIGIT ZERO..CHAKMA DIGIT NINE
+11140..11143 ; N # Po [4] CHAKMA SECTION MARK..CHAKMA QUESTION MARK
+11144 ; N # Lo CHAKMA LETTER LHAA
+11145..11146 ; N # Mc [2] CHAKMA VOWEL SIGN AA..CHAKMA VOWEL SIGN EI
+11147 ; N # Lo CHAKMA LETTER VAA
+11150..11172 ; N # Lo [35] MAHAJANI LETTER A..MAHAJANI LETTER RRA
+11173 ; N # Mn MAHAJANI SIGN NUKTA
+11174..11175 ; N # Po [2] MAHAJANI ABBREVIATION SIGN..MAHAJANI SECTION MARK
+11176 ; N # Lo MAHAJANI LIGATURE SHRI
+11180..11181 ; N # Mn [2] SHARADA SIGN CANDRABINDU..SHARADA SIGN ANUSVARA
+11182 ; N # Mc SHARADA SIGN VISARGA
+11183..111B2 ; N # Lo [48] SHARADA LETTER A..SHARADA LETTER HA
+111B3..111B5 ; N # Mc [3] SHARADA VOWEL SIGN AA..SHARADA VOWEL SIGN II
+111B6..111BE ; N # Mn [9] SHARADA VOWEL SIGN U..SHARADA VOWEL SIGN O
+111BF..111C0 ; N # Mc [2] SHARADA VOWEL SIGN AU..SHARADA SIGN VIRAMA
+111C1..111C4 ; N # Lo [4] SHARADA SIGN AVAGRAHA..SHARADA OM
+111C5..111C8 ; N # Po [4] SHARADA DANDA..SHARADA SEPARATOR
+111C9..111CC ; N # Mn [4] SHARADA SANDHI MARK..SHARADA EXTRA SHORT VOWEL MARK
+111CD ; N # Po SHARADA SUTRA MARK
+111CE ; N # Mc SHARADA VOWEL SIGN PRISHTHAMATRA E
+111CF ; N # Mn SHARADA SIGN INVERTED CANDRABINDU
+111D0..111D9 ; N # Nd [10] SHARADA DIGIT ZERO..SHARADA DIGIT NINE
+111DA ; N # Lo SHARADA EKAM
+111DB ; N # Po SHARADA SIGN SIDDHAM
+111DC ; N # Lo SHARADA HEADSTROKE
+111DD..111DF ; N # Po [3] SHARADA CONTINUATION SIGN..SHARADA SECTION MARK-2
+111E1..111F4 ; N # No [20] SINHALA ARCHAIC DIGIT ONE..SINHALA ARCHAIC NUMBER ONE THOUSAND
+11200..11211 ; N # Lo [18] KHOJKI LETTER A..KHOJKI LETTER JJA
+11213..1122B ; N # Lo [25] KHOJKI LETTER NYA..KHOJKI LETTER LLA
+1122C..1122E ; N # Mc [3] KHOJKI VOWEL SIGN AA..KHOJKI VOWEL SIGN II
+1122F..11231 ; N # Mn [3] KHOJKI VOWEL SIGN U..KHOJKI VOWEL SIGN AI
+11232..11233 ; N # Mc [2] KHOJKI VOWEL SIGN O..KHOJKI VOWEL SIGN AU
+11234 ; N # Mn KHOJKI SIGN ANUSVARA
+11235 ; N # Mc KHOJKI SIGN VIRAMA
+11236..11237 ; N # Mn [2] KHOJKI SIGN NUKTA..KHOJKI SIGN SHADDA
+11238..1123D ; N # Po [6] KHOJKI DANDA..KHOJKI ABBREVIATION SIGN
+1123E ; N # Mn KHOJKI SIGN SUKUN
+1123F..11240 ; N # Lo [2] KHOJKI LETTER QA..KHOJKI LETTER SHORT I
+11241 ; N # Mn KHOJKI VOWEL SIGN VOCALIC R
+11280..11286 ; N # Lo [7] MULTANI LETTER A..MULTANI LETTER GA
+11288 ; N # Lo MULTANI LETTER GHA
+1128A..1128D ; N # Lo [4] MULTANI LETTER CA..MULTANI LETTER JJA
+1128F..1129D ; N # Lo [15] MULTANI LETTER NYA..MULTANI LETTER BA
+1129F..112A8 ; N # Lo [10] MULTANI LETTER BHA..MULTANI LETTER RHA
+112A9 ; N # Po MULTANI SECTION MARK
+112B0..112DE ; N # Lo [47] KHUDAWADI LETTER A..KHUDAWADI LETTER HA
+112DF ; N # Mn KHUDAWADI SIGN ANUSVARA
+112E0..112E2 ; N # Mc [3] KHUDAWADI VOWEL SIGN AA..KHUDAWADI VOWEL SIGN II
+112E3..112EA ; N # Mn [8] KHUDAWADI VOWEL SIGN U..KHUDAWADI SIGN VIRAMA
+112F0..112F9 ; N # Nd [10] KHUDAWADI DIGIT ZERO..KHUDAWADI DIGIT NINE
+11300..11301 ; N # Mn [2] GRANTHA SIGN COMBINING ANUSVARA ABOVE..GRANTHA SIGN CANDRABINDU
+11302..11303 ; N # Mc [2] GRANTHA SIGN ANUSVARA..GRANTHA SIGN VISARGA
+11305..1130C ; N # Lo [8] GRANTHA LETTER A..GRANTHA LETTER VOCALIC L
+1130F..11310 ; N # Lo [2] GRANTHA LETTER EE..GRANTHA LETTER AI
+11313..11328 ; N # Lo [22] GRANTHA LETTER OO..GRANTHA LETTER NA
+1132A..11330 ; N # Lo [7] GRANTHA LETTER PA..GRANTHA LETTER RA
+11332..11333 ; N # Lo [2] GRANTHA LETTER LA..GRANTHA LETTER LLA
+11335..11339 ; N # Lo [5] GRANTHA LETTER VA..GRANTHA LETTER HA
+1133B..1133C ; N # Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA
+1133D ; N # Lo GRANTHA SIGN AVAGRAHA
+1133E..1133F ; N # Mc [2] GRANTHA VOWEL SIGN AA..GRANTHA VOWEL SIGN I
+11340 ; N # Mn GRANTHA VOWEL SIGN II
+11341..11344 ; N # Mc [4] GRANTHA VOWEL SIGN U..GRANTHA VOWEL SIGN VOCALIC RR
+11347..11348 ; N # Mc [2] GRANTHA VOWEL SIGN EE..GRANTHA VOWEL SIGN AI
+1134B..1134D ; N # Mc [3] GRANTHA VOWEL SIGN OO..GRANTHA SIGN VIRAMA
+11350 ; N # Lo GRANTHA OM
+11357 ; N # Mc GRANTHA AU LENGTH MARK
+1135D..11361 ; N # Lo [5] GRANTHA SIGN PLUTA..GRANTHA LETTER VOCALIC LL
+11362..11363 ; N # Mc [2] GRANTHA VOWEL SIGN VOCALIC L..GRANTHA VOWEL SIGN VOCALIC LL
+11366..1136C ; N # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX
+11370..11374 ; N # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA
+11400..11434 ; N # Lo [53] NEWA LETTER A..NEWA LETTER HA
+11435..11437 ; N # Mc [3] NEWA VOWEL SIGN AA..NEWA VOWEL SIGN II
+11438..1143F ; N # Mn [8] NEWA VOWEL SIGN U..NEWA VOWEL SIGN AI
+11440..11441 ; N # Mc [2] NEWA VOWEL SIGN O..NEWA VOWEL SIGN AU
+11442..11444 ; N # Mn [3] NEWA SIGN VIRAMA..NEWA SIGN ANUSVARA
+11445 ; N # Mc NEWA SIGN VISARGA
+11446 ; N # Mn NEWA SIGN NUKTA
+11447..1144A ; N # Lo [4] NEWA SIGN AVAGRAHA..NEWA SIDDHI
+1144B..1144F ; N # Po [5] NEWA DANDA..NEWA ABBREVIATION SIGN
+11450..11459 ; N # Nd [10] NEWA DIGIT ZERO..NEWA DIGIT NINE
+1145A..1145B ; N # Po [2] NEWA DOUBLE COMMA..NEWA PLACEHOLDER MARK
+1145D ; N # Po NEWA INSERTION SIGN
+1145E ; N # Mn NEWA SANDHI MARK
+1145F..11461 ; N # Lo [3] NEWA LETTER VEDIC ANUSVARA..NEWA SIGN UPADHMANIYA
+11480..114AF ; N # Lo [48] TIRHUTA ANJI..TIRHUTA LETTER HA
+114B0..114B2 ; N # Mc [3] TIRHUTA VOWEL SIGN AA..TIRHUTA VOWEL SIGN II
+114B3..114B8 ; N # Mn [6] TIRHUTA VOWEL SIGN U..TIRHUTA VOWEL SIGN VOCALIC LL
+114B9 ; N # Mc TIRHUTA VOWEL SIGN E
+114BA ; N # Mn TIRHUTA VOWEL SIGN SHORT E
+114BB..114BE ; N # Mc [4] TIRHUTA VOWEL SIGN AI..TIRHUTA VOWEL SIGN AU
+114BF..114C0 ; N # Mn [2] TIRHUTA SIGN CANDRABINDU..TIRHUTA SIGN ANUSVARA
+114C1 ; N # Mc TIRHUTA SIGN VISARGA
+114C2..114C3 ; N # Mn [2] TIRHUTA SIGN VIRAMA..TIRHUTA SIGN NUKTA
+114C4..114C5 ; N # Lo [2] TIRHUTA SIGN AVAGRAHA..TIRHUTA GVANG
+114C6 ; N # Po TIRHUTA ABBREVIATION SIGN
+114C7 ; N # Lo TIRHUTA OM
+114D0..114D9 ; N # Nd [10] TIRHUTA DIGIT ZERO..TIRHUTA DIGIT NINE
+11580..115AE ; N # Lo [47] SIDDHAM LETTER A..SIDDHAM LETTER HA
+115AF..115B1 ; N # Mc [3] SIDDHAM VOWEL SIGN AA..SIDDHAM VOWEL SIGN II
+115B2..115B5 ; N # Mn [4] SIDDHAM VOWEL SIGN U..SIDDHAM VOWEL SIGN VOCALIC RR
+115B8..115BB ; N # Mc [4] SIDDHAM VOWEL SIGN E..SIDDHAM VOWEL SIGN AU
+115BC..115BD ; N # Mn [2] SIDDHAM SIGN CANDRABINDU..SIDDHAM SIGN ANUSVARA
+115BE ; N # Mc SIDDHAM SIGN VISARGA
+115BF..115C0 ; N # Mn [2] SIDDHAM SIGN VIRAMA..SIDDHAM SIGN NUKTA
+115C1..115D7 ; N # Po [23] SIDDHAM SIGN SIDDHAM..SIDDHAM SECTION MARK WITH CIRCLES AND FOUR ENCLOSURES
+115D8..115DB ; N # Lo [4] SIDDHAM LETTER THREE-CIRCLE ALTERNATE I..SIDDHAM LETTER ALTERNATE U
+115DC..115DD ; N # Mn [2] SIDDHAM VOWEL SIGN ALTERNATE U..SIDDHAM VOWEL SIGN ALTERNATE UU
+11600..1162F ; N # Lo [48] MODI LETTER A..MODI LETTER LLA
+11630..11632 ; N # Mc [3] MODI VOWEL SIGN AA..MODI VOWEL SIGN II
+11633..1163A ; N # Mn [8] MODI VOWEL SIGN U..MODI VOWEL SIGN AI
+1163B..1163C ; N # Mc [2] MODI VOWEL SIGN O..MODI VOWEL SIGN AU
+1163D ; N # Mn MODI SIGN ANUSVARA
+1163E ; N # Mc MODI SIGN VISARGA
+1163F..11640 ; N # Mn [2] MODI SIGN VIRAMA..MODI SIGN ARDHACANDRA
+11641..11643 ; N # Po [3] MODI DANDA..MODI ABBREVIATION SIGN
+11644 ; N # Lo MODI SIGN HUVA
+11650..11659 ; N # Nd [10] MODI DIGIT ZERO..MODI DIGIT NINE
+11660..1166C ; N # Po [13] MONGOLIAN BIRGA WITH ORNAMENT..MONGOLIAN TURNED SWIRL BIRGA WITH DOUBLE ORNAMENT
+11680..116AA ; N # Lo [43] TAKRI LETTER A..TAKRI LETTER RRA
+116AB ; N # Mn TAKRI SIGN ANUSVARA
+116AC ; N # Mc TAKRI SIGN VISARGA
+116AD ; N # Mn TAKRI VOWEL SIGN AA
+116AE..116AF ; N # Mc [2] TAKRI VOWEL SIGN I..TAKRI VOWEL SIGN II
+116B0..116B5 ; N # Mn [6] TAKRI VOWEL SIGN U..TAKRI VOWEL SIGN AU
+116B6 ; N # Mc TAKRI SIGN VIRAMA
+116B7 ; N # Mn TAKRI SIGN NUKTA
+116B8 ; N # Lo TAKRI LETTER ARCHAIC KHA
+116B9 ; N # Po TAKRI ABBREVIATION SIGN
+116C0..116C9 ; N # Nd [10] TAKRI DIGIT ZERO..TAKRI DIGIT NINE
+11700..1171A ; N # Lo [27] AHOM LETTER KA..AHOM LETTER ALTERNATE BA
+1171D..1171F ; N # Mn [3] AHOM CONSONANT SIGN MEDIAL LA..AHOM CONSONANT SIGN MEDIAL LIGATING RA
+11720..11721 ; N # Mc [2] AHOM VOWEL SIGN A..AHOM VOWEL SIGN AA
+11722..11725 ; N # Mn [4] AHOM VOWEL SIGN I..AHOM VOWEL SIGN UU
+11726 ; N # Mc AHOM VOWEL SIGN E
+11727..1172B ; N # Mn [5] AHOM VOWEL SIGN AW..AHOM SIGN KILLER
+11730..11739 ; N # Nd [10] AHOM DIGIT ZERO..AHOM DIGIT NINE
+1173A..1173B ; N # No [2] AHOM NUMBER TEN..AHOM NUMBER TWENTY
+1173C..1173E ; N # Po [3] AHOM SIGN SMALL SECTION..AHOM SIGN RULAI
+1173F ; N # So AHOM SYMBOL VI
+11740..11746 ; N # Lo [7] AHOM LETTER CA..AHOM LETTER LLA
+11800..1182B ; N # Lo [44] DOGRA LETTER A..DOGRA LETTER RRA
+1182C..1182E ; N # Mc [3] DOGRA VOWEL SIGN AA..DOGRA VOWEL SIGN II
+1182F..11837 ; N # Mn [9] DOGRA VOWEL SIGN U..DOGRA SIGN ANUSVARA
+11838 ; N # Mc DOGRA SIGN VISARGA
+11839..1183A ; N # Mn [2] DOGRA SIGN VIRAMA..DOGRA SIGN NUKTA
+1183B ; N # Po DOGRA ABBREVIATION SIGN
+118A0..118DF ; N # L& [64] WARANG CITI CAPITAL LETTER NGAA..WARANG CITI SMALL LETTER VIYO
+118E0..118E9 ; N # Nd [10] WARANG CITI DIGIT ZERO..WARANG CITI DIGIT NINE
+118EA..118F2 ; N # No [9] WARANG CITI NUMBER TEN..WARANG CITI NUMBER NINETY
+118FF ; N # Lo WARANG CITI OM
+11900..11906 ; N # Lo [7] DIVES AKURU LETTER A..DIVES AKURU LETTER E
+11909 ; N # Lo DIVES AKURU LETTER O
+1190C..11913 ; N # Lo [8] DIVES AKURU LETTER KA..DIVES AKURU LETTER JA
+11915..11916 ; N # Lo [2] DIVES AKURU LETTER NYA..DIVES AKURU LETTER TTA
+11918..1192F ; N # Lo [24] DIVES AKURU LETTER DDA..DIVES AKURU LETTER ZA
+11930..11935 ; N # Mc [6] DIVES AKURU VOWEL SIGN AA..DIVES AKURU VOWEL SIGN E
+11937..11938 ; N # Mc [2] DIVES AKURU VOWEL SIGN AI..DIVES AKURU VOWEL SIGN O
+1193B..1193C ; N # Mn [2] DIVES AKURU SIGN ANUSVARA..DIVES AKURU SIGN CANDRABINDU
+1193D ; N # Mc DIVES AKURU SIGN HALANTA
+1193E ; N # Mn DIVES AKURU VIRAMA
+1193F ; N # Lo DIVES AKURU PREFIXED NASAL SIGN
+11940 ; N # Mc DIVES AKURU MEDIAL YA
+11941 ; N # Lo DIVES AKURU INITIAL RA
+11942 ; N # Mc DIVES AKURU MEDIAL RA
+11943 ; N # Mn DIVES AKURU SIGN NUKTA
+11944..11946 ; N # Po [3] DIVES AKURU DOUBLE DANDA..DIVES AKURU END OF TEXT MARK
+11950..11959 ; N # Nd [10] DIVES AKURU DIGIT ZERO..DIVES AKURU DIGIT NINE
+119A0..119A7 ; N # Lo [8] NANDINAGARI LETTER A..NANDINAGARI LETTER VOCALIC RR
+119AA..119D0 ; N # Lo [39] NANDINAGARI LETTER E..NANDINAGARI LETTER RRA
+119D1..119D3 ; N # Mc [3] NANDINAGARI VOWEL SIGN AA..NANDINAGARI VOWEL SIGN II
+119D4..119D7 ; N # Mn [4] NANDINAGARI VOWEL SIGN U..NANDINAGARI VOWEL SIGN VOCALIC RR
+119DA..119DB ; N # Mn [2] NANDINAGARI VOWEL SIGN E..NANDINAGARI VOWEL SIGN AI
+119DC..119DF ; N # Mc [4] NANDINAGARI VOWEL SIGN O..NANDINAGARI SIGN VISARGA
+119E0 ; N # Mn NANDINAGARI SIGN VIRAMA
+119E1 ; N # Lo NANDINAGARI SIGN AVAGRAHA
+119E2 ; N # Po NANDINAGARI SIGN SIDDHAM
+119E3 ; N # Lo NANDINAGARI HEADSTROKE
+119E4 ; N # Mc NANDINAGARI VOWEL SIGN PRISHTHAMATRA E
+11A00 ; N # Lo ZANABAZAR SQUARE LETTER A
+11A01..11A0A ; N # Mn [10] ZANABAZAR SQUARE VOWEL SIGN I..ZANABAZAR SQUARE VOWEL LENGTH MARK
+11A0B..11A32 ; N # Lo [40] ZANABAZAR SQUARE LETTER KA..ZANABAZAR SQUARE LETTER KSSA
+11A33..11A38 ; N # Mn [6] ZANABAZAR SQUARE FINAL CONSONANT MARK..ZANABAZAR SQUARE SIGN ANUSVARA
+11A39 ; N # Mc ZANABAZAR SQUARE SIGN VISARGA
+11A3A ; N # Lo ZANABAZAR SQUARE CLUSTER-INITIAL LETTER RA
+11A3B..11A3E ; N # Mn [4] ZANABAZAR SQUARE CLUSTER-FINAL LETTER YA..ZANABAZAR SQUARE CLUSTER-FINAL LETTER VA
+11A3F..11A46 ; N # Po [8] ZANABAZAR SQUARE INITIAL HEAD MARK..ZANABAZAR SQUARE CLOSING DOUBLE-LINED HEAD MARK
+11A47 ; N # Mn ZANABAZAR SQUARE SUBJOINER
+11A50 ; N # Lo SOYOMBO LETTER A
+11A51..11A56 ; N # Mn [6] SOYOMBO VOWEL SIGN I..SOYOMBO VOWEL SIGN OE
+11A57..11A58 ; N # Mc [2] SOYOMBO VOWEL SIGN AI..SOYOMBO VOWEL SIGN AU
+11A59..11A5B ; N # Mn [3] SOYOMBO VOWEL SIGN VOCALIC R..SOYOMBO VOWEL LENGTH MARK
+11A5C..11A89 ; N # Lo [46] SOYOMBO LETTER KA..SOYOMBO CLUSTER-INITIAL LETTER SA
+11A8A..11A96 ; N # Mn [13] SOYOMBO FINAL CONSONANT SIGN G..SOYOMBO SIGN ANUSVARA
+11A97 ; N # Mc SOYOMBO SIGN VISARGA
+11A98..11A99 ; N # Mn [2] SOYOMBO GEMINATION MARK..SOYOMBO SUBJOINER
+11A9A..11A9C ; N # Po [3] SOYOMBO MARK TSHEG..SOYOMBO MARK DOUBLE SHAD
+11A9D ; N # Lo SOYOMBO MARK PLUTA
+11A9E..11AA2 ; N # Po [5] SOYOMBO HEAD MARK WITH MOON AND SUN AND TRIPLE FLAME..SOYOMBO TERMINAL MARK-2
+11AB0..11ABF ; N # Lo [16] CANADIAN SYLLABICS NATTILIK HI..CANADIAN SYLLABICS SPA
+11AC0..11AF8 ; N # Lo [57] PAU CIN HAU LETTER PA..PAU CIN HAU GLOTTAL STOP FINAL
+11B00..11B09 ; N # Po [10] DEVANAGARI HEAD MARK..DEVANAGARI SIGN MINDU
+11C00..11C08 ; N # Lo [9] BHAIKSUKI LETTER A..BHAIKSUKI LETTER VOCALIC L
+11C0A..11C2E ; N # Lo [37] BHAIKSUKI LETTER E..BHAIKSUKI LETTER HA
+11C2F ; N # Mc BHAIKSUKI VOWEL SIGN AA
+11C30..11C36 ; N # Mn [7] BHAIKSUKI VOWEL SIGN I..BHAIKSUKI VOWEL SIGN VOCALIC L
+11C38..11C3D ; N # Mn [6] BHAIKSUKI VOWEL SIGN E..BHAIKSUKI SIGN ANUSVARA
+11C3E ; N # Mc BHAIKSUKI SIGN VISARGA
+11C3F ; N # Mn BHAIKSUKI SIGN VIRAMA
+11C40 ; N # Lo BHAIKSUKI SIGN AVAGRAHA
+11C41..11C45 ; N # Po [5] BHAIKSUKI DANDA..BHAIKSUKI GAP FILLER-2
+11C50..11C59 ; N # Nd [10] BHAIKSUKI DIGIT ZERO..BHAIKSUKI DIGIT NINE
+11C5A..11C6C ; N # No [19] BHAIKSUKI NUMBER ONE..BHAIKSUKI HUNDREDS UNIT MARK
+11C70..11C71 ; N # Po [2] MARCHEN HEAD MARK..MARCHEN MARK SHAD
+11C72..11C8F ; N # Lo [30] MARCHEN LETTER KA..MARCHEN LETTER A
+11C92..11CA7 ; N # Mn [22] MARCHEN SUBJOINED LETTER KA..MARCHEN SUBJOINED LETTER ZA
+11CA9 ; N # Mc MARCHEN SUBJOINED LETTER YA
+11CAA..11CB0 ; N # Mn [7] MARCHEN SUBJOINED LETTER RA..MARCHEN VOWEL SIGN AA
+11CB1 ; N # Mc MARCHEN VOWEL SIGN I
+11CB2..11CB3 ; N # Mn [2] MARCHEN VOWEL SIGN U..MARCHEN VOWEL SIGN E
+11CB4 ; N # Mc MARCHEN VOWEL SIGN O
+11CB5..11CB6 ; N # Mn [2] MARCHEN SIGN ANUSVARA..MARCHEN SIGN CANDRABINDU
+11D00..11D06 ; N # Lo [7] MASARAM GONDI LETTER A..MASARAM GONDI LETTER E
+11D08..11D09 ; N # Lo [2] MASARAM GONDI LETTER AI..MASARAM GONDI LETTER O
+11D0B..11D30 ; N # Lo [38] MASARAM GONDI LETTER AU..MASARAM GONDI LETTER TRA
+11D31..11D36 ; N # Mn [6] MASARAM GONDI VOWEL SIGN AA..MASARAM GONDI VOWEL SIGN VOCALIC R
+11D3A ; N # Mn MASARAM GONDI VOWEL SIGN E
+11D3C..11D3D ; N # Mn [2] MASARAM GONDI VOWEL SIGN AI..MASARAM GONDI VOWEL SIGN O
+11D3F..11D45 ; N # Mn [7] MASARAM GONDI VOWEL SIGN AU..MASARAM GONDI VIRAMA
+11D46 ; N # Lo MASARAM GONDI REPHA
+11D47 ; N # Mn MASARAM GONDI RA-KARA
+11D50..11D59 ; N # Nd [10] MASARAM GONDI DIGIT ZERO..MASARAM GONDI DIGIT NINE
+11D60..11D65 ; N # Lo [6] GUNJALA GONDI LETTER A..GUNJALA GONDI LETTER UU
+11D67..11D68 ; N # Lo [2] GUNJALA GONDI LETTER EE..GUNJALA GONDI LETTER AI
+11D6A..11D89 ; N # Lo [32] GUNJALA GONDI LETTER OO..GUNJALA GONDI LETTER SA
+11D8A..11D8E ; N # Mc [5] GUNJALA GONDI VOWEL SIGN AA..GUNJALA GONDI VOWEL SIGN UU
+11D90..11D91 ; N # Mn [2] GUNJALA GONDI VOWEL SIGN EE..GUNJALA GONDI VOWEL SIGN AI
+11D93..11D94 ; N # Mc [2] GUNJALA GONDI VOWEL SIGN OO..GUNJALA GONDI VOWEL SIGN AU
+11D95 ; N # Mn GUNJALA GONDI SIGN ANUSVARA
+11D96 ; N # Mc GUNJALA GONDI SIGN VISARGA
+11D97 ; N # Mn GUNJALA GONDI VIRAMA
+11D98 ; N # Lo GUNJALA GONDI OM
+11DA0..11DA9 ; N # Nd [10] GUNJALA GONDI DIGIT ZERO..GUNJALA GONDI DIGIT NINE
+11EE0..11EF2 ; N # Lo [19] MAKASAR LETTER KA..MAKASAR ANGKA
+11EF3..11EF4 ; N # Mn [2] MAKASAR VOWEL SIGN I..MAKASAR VOWEL SIGN U
+11EF5..11EF6 ; N # Mc [2] MAKASAR VOWEL SIGN E..MAKASAR VOWEL SIGN O
+11EF7..11EF8 ; N # Po [2] MAKASAR PASSIMBANG..MAKASAR END OF SECTION
+11F00..11F01 ; N # Mn [2] KAWI SIGN CANDRABINDU..KAWI SIGN ANUSVARA
+11F02 ; N # Lo KAWI SIGN REPHA
+11F03 ; N # Mc KAWI SIGN VISARGA
+11F04..11F10 ; N # Lo [13] KAWI LETTER A..KAWI LETTER O
+11F12..11F33 ; N # Lo [34] KAWI LETTER KA..KAWI LETTER JNYA
+11F34..11F35 ; N # Mc [2] KAWI VOWEL SIGN AA..KAWI VOWEL SIGN ALTERNATE AA
+11F36..11F3A ; N # Mn [5] KAWI VOWEL SIGN I..KAWI VOWEL SIGN VOCALIC R
+11F3E..11F3F ; N # Mc [2] KAWI VOWEL SIGN E..KAWI VOWEL SIGN AI
+11F40 ; N # Mn KAWI VOWEL SIGN EU
+11F41 ; N # Mc KAWI SIGN KILLER
+11F42 ; N # Mn KAWI CONJOINER
+11F43..11F4F ; N # Po [13] KAWI DANDA..KAWI PUNCTUATION CLOSING SPIRAL
+11F50..11F59 ; N # Nd [10] KAWI DIGIT ZERO..KAWI DIGIT NINE
+11FB0 ; N # Lo LISU LETTER YHA
+11FC0..11FD4 ; N # No [21] TAMIL FRACTION ONE THREE-HUNDRED-AND-TWENTIETH..TAMIL FRACTION DOWNSCALING FACTOR KIIZH
+11FD5..11FDC ; N # So [8] TAMIL SIGN NEL..TAMIL SIGN MUKKURUNI
+11FDD..11FE0 ; N # Sc [4] TAMIL SIGN KAACU..TAMIL SIGN VARAAKAN
+11FE1..11FF1 ; N # So [17] TAMIL SIGN PAARAM..TAMIL SIGN VAKAIYARAA
+11FFF ; N # Po TAMIL PUNCTUATION END OF TEXT
+12000..12399 ; N # Lo [922] CUNEIFORM SIGN A..CUNEIFORM SIGN U U
+12400..1246E ; N # Nl [111] CUNEIFORM NUMERIC SIGN TWO ASH..CUNEIFORM NUMERIC SIGN NINE U VARIANT FORM
+12470..12474 ; N # Po [5] CUNEIFORM PUNCTUATION SIGN OLD ASSYRIAN WORD DIVIDER..CUNEIFORM PUNCTUATION SIGN DIAGONAL QUADCOLON
+12480..12543 ; N # Lo [196] CUNEIFORM SIGN AB TIMES NUN TENU..CUNEIFORM SIGN ZU5 TIMES THREE DISH TENU
+12F90..12FF0 ; N # Lo [97] CYPRO-MINOAN SIGN CM001..CYPRO-MINOAN SIGN CM114
+12FF1..12FF2 ; N # Po [2] CYPRO-MINOAN SIGN CM301..CYPRO-MINOAN SIGN CM302
+13000..1342F ; N # Lo [1072] EGYPTIAN HIEROGLYPH A001..EGYPTIAN HIEROGLYPH V011D
+13430..1343F ; N # Cf [16] EGYPTIAN HIEROGLYPH VERTICAL JOINER..EGYPTIAN HIEROGLYPH END WALLED ENCLOSURE
+13440 ; N # Mn EGYPTIAN HIEROGLYPH MIRROR HORIZONTALLY
+13441..13446 ; N # Lo [6] EGYPTIAN HIEROGLYPH FULL BLANK..EGYPTIAN HIEROGLYPH WIDE LOST SIGN
+13447..13455 ; N # Mn [15] EGYPTIAN HIEROGLYPH MODIFIER DAMAGED AT TOP START..EGYPTIAN HIEROGLYPH MODIFIER DAMAGED
+14400..14646 ; N # Lo [583] ANATOLIAN HIEROGLYPH A001..ANATOLIAN HIEROGLYPH A530
+16800..16A38 ; N # Lo [569] BAMUM LETTER PHASE-A NGKUE MFON..BAMUM LETTER PHASE-F VUEQ
+16A40..16A5E ; N # Lo [31] MRO LETTER TA..MRO LETTER TEK
+16A60..16A69 ; N # Nd [10] MRO DIGIT ZERO..MRO DIGIT NINE
+16A6E..16A6F ; N # Po [2] MRO DANDA..MRO DOUBLE DANDA
+16A70..16ABE ; N # Lo [79] TANGSA LETTER OZ..TANGSA LETTER ZA
+16AC0..16AC9 ; N # Nd [10] TANGSA DIGIT ZERO..TANGSA DIGIT NINE
+16AD0..16AED ; N # Lo [30] BASSA VAH LETTER ENNI..BASSA VAH LETTER I
+16AF0..16AF4 ; N # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
+16AF5 ; N # Po BASSA VAH FULL STOP
+16B00..16B2F ; N # Lo [48] PAHAWH HMONG VOWEL KEEB..PAHAWH HMONG CONSONANT CAU
+16B30..16B36 ; N # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
+16B37..16B3B ; N # Po [5] PAHAWH HMONG SIGN VOS THOM..PAHAWH HMONG SIGN VOS FEEM
+16B3C..16B3F ; N # So [4] PAHAWH HMONG SIGN XYEEM NTXIV..PAHAWH HMONG SIGN XYEEM FAIB
+16B40..16B43 ; N # Lm [4] PAHAWH HMONG SIGN VOS SEEV..PAHAWH HMONG SIGN IB YAM
+16B44 ; N # Po PAHAWH HMONG SIGN XAUS
+16B45 ; N # So PAHAWH HMONG SIGN CIM TSOV ROG
+16B50..16B59 ; N # Nd [10] PAHAWH HMONG DIGIT ZERO..PAHAWH HMONG DIGIT NINE
+16B5B..16B61 ; N # No [7] PAHAWH HMONG NUMBER TENS..PAHAWH HMONG NUMBER TRILLIONS
+16B63..16B77 ; N # Lo [21] PAHAWH HMONG SIGN VOS LUB..PAHAWH HMONG SIGN CIM NRES TOS
+16B7D..16B8F ; N # Lo [19] PAHAWH HMONG CLAN SIGN TSHEEJ..PAHAWH HMONG CLAN SIGN VWJ
+16E40..16E7F ; N # L& [64] MEDEFAIDRIN CAPITAL LETTER M..MEDEFAIDRIN SMALL LETTER Y
+16E80..16E96 ; N # No [23] MEDEFAIDRIN DIGIT ZERO..MEDEFAIDRIN DIGIT THREE ALTERNATE FORM
+16E97..16E9A ; N # Po [4] MEDEFAIDRIN COMMA..MEDEFAIDRIN EXCLAMATION OH
+16F00..16F4A ; N # Lo [75] MIAO LETTER PA..MIAO LETTER RTE
+16F4F ; N # Mn MIAO SIGN CONSONANT MODIFIER BAR
+16F50 ; N # Lo MIAO LETTER NASALIZATION
+16F51..16F87 ; N # Mc [55] MIAO SIGN ASPIRATION..MIAO VOWEL SIGN UI
+16F8F..16F92 ; N # Mn [4] MIAO TONE RIGHT..MIAO TONE BELOW
+16F93..16F9F ; N # Lm [13] MIAO LETTER TONE-2..MIAO LETTER REFORMED TONE-8
+16FE0..16FE1 ; W # Lm [2] TANGUT ITERATION MARK..NUSHU ITERATION MARK
+16FE2 ; W # Po OLD CHINESE HOOK MARK
+16FE3 ; W # Lm OLD CHINESE ITERATION MARK
+16FE4 ; W # Mn KHITAN SMALL SCRIPT FILLER
+16FF0..16FF1 ; W # Mc [2] VIETNAMESE ALTERNATE READING MARK CA..VIETNAMESE ALTERNATE READING MARK NHAY
+17000..187F7 ; W # Lo [6136] TANGUT IDEOGRAPH-17000..TANGUT IDEOGRAPH-187F7
+18800..18AFF ; W # Lo [768] TANGUT COMPONENT-001..TANGUT COMPONENT-768
+18B00..18CD5 ; W # Lo [470] KHITAN SMALL SCRIPT CHARACTER-18B00..KHITAN SMALL SCRIPT CHARACTER-18CD5
+18D00..18D08 ; W # Lo [9] TANGUT IDEOGRAPH-18D00..TANGUT IDEOGRAPH-18D08
+1AFF0..1AFF3 ; W # Lm [4] KATAKANA LETTER MINNAN TONE-2..KATAKANA LETTER MINNAN TONE-5
+1AFF5..1AFFB ; W # Lm [7] KATAKANA LETTER MINNAN TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-5
+1AFFD..1AFFE ; W # Lm [2] KATAKANA LETTER MINNAN NASALIZED TONE-7..KATAKANA LETTER MINNAN NASALIZED TONE-8
+1B000..1B0FF ; W # Lo [256] KATAKANA LETTER ARCHAIC E..HENTAIGANA LETTER RE-2
+1B100..1B122 ; W # Lo [35] HENTAIGANA LETTER RE-3..KATAKANA LETTER ARCHAIC WU
+1B132 ; W # Lo HIRAGANA LETTER SMALL KO
+1B150..1B152 ; W # Lo [3] HIRAGANA LETTER SMALL WI..HIRAGANA LETTER SMALL WO
+1B155 ; W # Lo KATAKANA LETTER SMALL KO
+1B164..1B167 ; W # Lo [4] KATAKANA LETTER SMALL WI..KATAKANA LETTER SMALL N
+1B170..1B2FB ; W # Lo [396] NUSHU CHARACTER-1B170..NUSHU CHARACTER-1B2FB
+1BC00..1BC6A ; N # Lo [107] DUPLOYAN LETTER H..DUPLOYAN LETTER VOCALIC M
+1BC70..1BC7C ; N # Lo [13] DUPLOYAN AFFIX LEFT HORIZONTAL SECANT..DUPLOYAN AFFIX ATTACHED TANGENT HOOK
+1BC80..1BC88 ; N # Lo [9] DUPLOYAN AFFIX HIGH ACUTE..DUPLOYAN AFFIX HIGH VERTICAL
+1BC90..1BC99 ; N # Lo [10] DUPLOYAN AFFIX LOW ACUTE..DUPLOYAN AFFIX LOW ARROW
+1BC9C ; N # So DUPLOYAN SIGN O WITH CROSS
+1BC9D..1BC9E ; N # Mn [2] DUPLOYAN THICK LETTER SELECTOR..DUPLOYAN DOUBLE MARK
+1BC9F ; N # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
+1BCA0..1BCA3 ; N # Cf [4] SHORTHAND FORMAT LETTER OVERLAP..SHORTHAND FORMAT UP STEP
+1CF00..1CF2D ; N # Mn [46] ZNAMENNY COMBINING MARK GORAZDO NIZKO S KRYZHEM ON LEFT..ZNAMENNY COMBINING MARK KRYZH ON LEFT
+1CF30..1CF46 ; N # Mn [23] ZNAMENNY COMBINING TONAL RANGE MARK MRACHNO..ZNAMENNY PRIZNAK MODIFIER ROG
+1CF50..1CFC3 ; N # So [116] ZNAMENNY NEUME KRYUK..ZNAMENNY NEUME PAUK
+1D000..1D0F5 ; N # So [246] BYZANTINE MUSICAL SYMBOL PSILI..BYZANTINE MUSICAL SYMBOL GORGON NEO KATO
+1D100..1D126 ; N # So [39] MUSICAL SYMBOL SINGLE BARLINE..MUSICAL SYMBOL DRUM CLEF-2
+1D129..1D164 ; N # So [60] MUSICAL SYMBOL MULTIPLE MEASURE REST..MUSICAL SYMBOL ONE HUNDRED TWENTY-EIGHTH NOTE
+1D165..1D166 ; N # Mc [2] MUSICAL SYMBOL COMBINING STEM..MUSICAL SYMBOL COMBINING SPRECHGESANG STEM
+1D167..1D169 ; N # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3
+1D16A..1D16C ; N # So [3] MUSICAL SYMBOL FINGERED TREMOLO-1..MUSICAL SYMBOL FINGERED TREMOLO-3
+1D16D..1D172 ; N # Mc [6] MUSICAL SYMBOL COMBINING AUGMENTATION DOT..MUSICAL SYMBOL COMBINING FLAG-5
+1D173..1D17A ; N # Cf [8] MUSICAL SYMBOL BEGIN BEAM..MUSICAL SYMBOL END PHRASE
+1D17B..1D182 ; N # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE
+1D183..1D184 ; N # So [2] MUSICAL SYMBOL ARPEGGIATO UP..MUSICAL SYMBOL ARPEGGIATO DOWN
+1D185..1D18B ; N # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE
+1D18C..1D1A9 ; N # So [30] MUSICAL SYMBOL RINFORZANDO..MUSICAL SYMBOL DEGREE SLASH
+1D1AA..1D1AD ; N # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
+1D1AE..1D1EA ; N # So [61] MUSICAL SYMBOL PEDAL MARK..MUSICAL SYMBOL KORON
+1D200..1D241 ; N # So [66] GREEK VOCAL NOTATION SYMBOL-1..GREEK INSTRUMENTAL NOTATION SYMBOL-54
+1D242..1D244 ; N # Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME
+1D245 ; N # So GREEK MUSICAL LEIMMA
+1D2C0..1D2D3 ; N # No [20] KAKTOVIK NUMERAL ZERO..KAKTOVIK NUMERAL NINETEEN
+1D2E0..1D2F3 ; N # No [20] MAYAN NUMERAL ZERO..MAYAN NUMERAL NINETEEN
+1D300..1D356 ; N # So [87] MONOGRAM FOR EARTH..TETRAGRAM FOR FOSTERING
+1D360..1D378 ; N # No [25] COUNTING ROD UNIT DIGIT ONE..TALLY MARK FIVE
+1D400..1D454 ; N # L& [85] MATHEMATICAL BOLD CAPITAL A..MATHEMATICAL ITALIC SMALL G
+1D456..1D49C ; N # L& [71] MATHEMATICAL ITALIC SMALL I..MATHEMATICAL SCRIPT CAPITAL A
+1D49E..1D49F ; N # Lu [2] MATHEMATICAL SCRIPT CAPITAL C..MATHEMATICAL SCRIPT CAPITAL D
+1D4A2 ; N # Lu MATHEMATICAL SCRIPT CAPITAL G
+1D4A5..1D4A6 ; N # Lu [2] MATHEMATICAL SCRIPT CAPITAL J..MATHEMATICAL SCRIPT CAPITAL K
+1D4A9..1D4AC ; N # Lu [4] MATHEMATICAL SCRIPT CAPITAL N..MATHEMATICAL SCRIPT CAPITAL Q
+1D4AE..1D4B9 ; N # L& [12] MATHEMATICAL SCRIPT CAPITAL S..MATHEMATICAL SCRIPT SMALL D
+1D4BB ; N # Ll MATHEMATICAL SCRIPT SMALL F
+1D4BD..1D4C3 ; N # Ll [7] MATHEMATICAL SCRIPT SMALL H..MATHEMATICAL SCRIPT SMALL N
+1D4C5..1D505 ; N # L& [65] MATHEMATICAL SCRIPT SMALL P..MATHEMATICAL FRAKTUR CAPITAL B
+1D507..1D50A ; N # Lu [4] MATHEMATICAL FRAKTUR CAPITAL D..MATHEMATICAL FRAKTUR CAPITAL G
+1D50D..1D514 ; N # Lu [8] MATHEMATICAL FRAKTUR CAPITAL J..MATHEMATICAL FRAKTUR CAPITAL Q
+1D516..1D51C ; N # Lu [7] MATHEMATICAL FRAKTUR CAPITAL S..MATHEMATICAL FRAKTUR CAPITAL Y
+1D51E..1D539 ; N # L& [28] MATHEMATICAL FRAKTUR SMALL A..MATHEMATICAL DOUBLE-STRUCK CAPITAL B
+1D53B..1D53E ; N # Lu [4] MATHEMATICAL DOUBLE-STRUCK CAPITAL D..MATHEMATICAL DOUBLE-STRUCK CAPITAL G
+1D540..1D544 ; N # Lu [5] MATHEMATICAL DOUBLE-STRUCK CAPITAL I..MATHEMATICAL DOUBLE-STRUCK CAPITAL M
+1D546 ; N # Lu MATHEMATICAL DOUBLE-STRUCK CAPITAL O
+1D54A..1D550 ; N # Lu [7] MATHEMATICAL DOUBLE-STRUCK CAPITAL S..MATHEMATICAL DOUBLE-STRUCK CAPITAL Y
+1D552..1D6A5 ; N # L& [340] MATHEMATICAL DOUBLE-STRUCK SMALL A..MATHEMATICAL ITALIC SMALL DOTLESS J
+1D6A8..1D6C0 ; N # Lu [25] MATHEMATICAL BOLD CAPITAL ALPHA..MATHEMATICAL BOLD CAPITAL OMEGA
+1D6C1 ; N # Sm MATHEMATICAL BOLD NABLA
+1D6C2..1D6DA ; N # Ll [25] MATHEMATICAL BOLD SMALL ALPHA..MATHEMATICAL BOLD SMALL OMEGA
+1D6DB ; N # Sm MATHEMATICAL BOLD PARTIAL DIFFERENTIAL
+1D6DC..1D6FA ; N # L& [31] MATHEMATICAL BOLD EPSILON SYMBOL..MATHEMATICAL ITALIC CAPITAL OMEGA
+1D6FB ; N # Sm MATHEMATICAL ITALIC NABLA
+1D6FC..1D714 ; N # Ll [25] MATHEMATICAL ITALIC SMALL ALPHA..MATHEMATICAL ITALIC SMALL OMEGA
+1D715 ; N # Sm MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL
+1D716..1D734 ; N # L& [31] MATHEMATICAL ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD ITALIC CAPITAL OMEGA
+1D735 ; N # Sm MATHEMATICAL BOLD ITALIC NABLA
+1D736..1D74E ; N # Ll [25] MATHEMATICAL BOLD ITALIC SMALL ALPHA..MATHEMATICAL BOLD ITALIC SMALL OMEGA
+1D74F ; N # Sm MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL
+1D750..1D76E ; N # L& [31] MATHEMATICAL BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD CAPITAL OMEGA
+1D76F ; N # Sm MATHEMATICAL SANS-SERIF BOLD NABLA
+1D770..1D788 ; N # Ll [25] MATHEMATICAL SANS-SERIF BOLD SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD SMALL OMEGA
+1D789 ; N # Sm MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL
+1D78A..1D7A8 ; N # L& [31] MATHEMATICAL SANS-SERIF BOLD EPSILON SYMBOL..MATHEMATICAL SANS-SERIF BOLD ITALIC CAPITAL OMEGA
+1D7A9 ; N # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA
+1D7AA..1D7C2 ; N # Ll [25] MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL ALPHA..MATHEMATICAL SANS-SERIF BOLD ITALIC SMALL OMEGA
+1D7C3 ; N # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL
+1D7C4..1D7CB ; N # L& [8] MATHEMATICAL SANS-SERIF BOLD ITALIC EPSILON SYMBOL..MATHEMATICAL BOLD SMALL DIGAMMA
+1D7CE..1D7FF ; N # Nd [50] MATHEMATICAL BOLD DIGIT ZERO..MATHEMATICAL MONOSPACE DIGIT NINE
+1D800..1D9FF ; N # So [512] SIGNWRITING HAND-FIST INDEX..SIGNWRITING HEAD
+1DA00..1DA36 ; N # Mn [55] SIGNWRITING HEAD RIM..SIGNWRITING AIR SUCKING IN
+1DA37..1DA3A ; N # So [4] SIGNWRITING AIR BLOW SMALL ROTATIONS..SIGNWRITING BREATH EXHALE
+1DA3B..1DA6C ; N # Mn [50] SIGNWRITING MOUTH CLOSED NEUTRAL..SIGNWRITING EXCITEMENT
+1DA6D..1DA74 ; N # So [8] SIGNWRITING SHOULDER HIP SPINE..SIGNWRITING TORSO-FLOORPLANE TWISTING
+1DA75 ; N # Mn SIGNWRITING UPPER BODY TILTING FROM HIP JOINTS
+1DA76..1DA83 ; N # So [14] SIGNWRITING LIMB COMBINATION..SIGNWRITING LOCATION DEPTH
+1DA84 ; N # Mn SIGNWRITING LOCATION HEAD NECK
+1DA85..1DA86 ; N # So [2] SIGNWRITING LOCATION TORSO..SIGNWRITING LOCATION LIMBS DIGITS
+1DA87..1DA8B ; N # Po [5] SIGNWRITING COMMA..SIGNWRITING PARENTHESIS
+1DA9B..1DA9F ; N # Mn [5] SIGNWRITING FILL MODIFIER-2..SIGNWRITING FILL MODIFIER-6
+1DAA1..1DAAF ; N # Mn [15] SIGNWRITING ROTATION MODIFIER-2..SIGNWRITING ROTATION MODIFIER-16
+1DF00..1DF09 ; N # Ll [10] LATIN SMALL LETTER FENG DIGRAPH WITH TRILL..LATIN SMALL LETTER T WITH HOOK AND RETROFLEX HOOK
+1DF0A ; N # Lo LATIN LETTER RETROFLEX CLICK WITH RETROFLEX HOOK
+1DF0B..1DF1E ; N # Ll [20] LATIN SMALL LETTER ESH WITH DOUBLE BAR..LATIN SMALL LETTER S WITH CURL
+1DF25..1DF2A ; N # Ll [6] LATIN SMALL LETTER D WITH MID-HEIGHT LEFT HOOK..LATIN SMALL LETTER T WITH MID-HEIGHT LEFT HOOK
+1E000..1E006 ; N # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE
+1E008..1E018 ; N # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU
+1E01B..1E021 ; N # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI
+1E023..1E024 ; N # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS
+1E026..1E02A ; N # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA
+1E030..1E06D ; N # Lm [62] MODIFIER LETTER CYRILLIC SMALL A..MODIFIER LETTER CYRILLIC SMALL STRAIGHT U WITH STROKE
+1E08F ; N # Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
+1E100..1E12C ; N # Lo [45] NYIAKENG PUACHUE HMONG LETTER MA..NYIAKENG PUACHUE HMONG LETTER W
+1E130..1E136 ; N # Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D
+1E137..1E13D ; N # Lm [7] NYIAKENG PUACHUE HMONG SIGN FOR PERSON..NYIAKENG PUACHUE HMONG SYLLABLE LENGTHENER
+1E140..1E149 ; N # Nd [10] NYIAKENG PUACHUE HMONG DIGIT ZERO..NYIAKENG PUACHUE HMONG DIGIT NINE
+1E14E ; N # Lo NYIAKENG PUACHUE HMONG LOGOGRAM NYAJ
+1E14F ; N # So NYIAKENG PUACHUE HMONG CIRCLED CA
+1E290..1E2AD ; N # Lo [30] TOTO LETTER PA..TOTO LETTER A
+1E2AE ; N # Mn TOTO SIGN RISING TONE
+1E2C0..1E2EB ; N # Lo [44] WANCHO LETTER AA..WANCHO LETTER YIH
+1E2EC..1E2EF ; N # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI
+1E2F0..1E2F9 ; N # Nd [10] WANCHO DIGIT ZERO..WANCHO DIGIT NINE
+1E2FF ; N # Sc WANCHO NGUN SIGN
+1E4D0..1E4EA ; N # Lo [27] NAG MUNDARI LETTER O..NAG MUNDARI LETTER ELL
+1E4EB ; N # Lm NAG MUNDARI SIGN OJOD
+1E4EC..1E4EF ; N # Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH
+1E4F0..1E4F9 ; N # Nd [10] NAG MUNDARI DIGIT ZERO..NAG MUNDARI DIGIT NINE
+1E7E0..1E7E6 ; N # Lo [7] ETHIOPIC SYLLABLE HHYA..ETHIOPIC SYLLABLE HHYO
+1E7E8..1E7EB ; N # Lo [4] ETHIOPIC SYLLABLE GURAGE HHWA..ETHIOPIC SYLLABLE HHWE
+1E7ED..1E7EE ; N # Lo [2] ETHIOPIC SYLLABLE GURAGE MWI..ETHIOPIC SYLLABLE GURAGE MWEE
+1E7F0..1E7FE ; N # Lo [15] ETHIOPIC SYLLABLE GURAGE QWI..ETHIOPIC SYLLABLE GURAGE PWEE
+1E800..1E8C4 ; N # Lo [197] MENDE KIKAKUI SYLLABLE M001 KI..MENDE KIKAKUI SYLLABLE M060 NYON
+1E8C7..1E8CF ; N # No [9] MENDE KIKAKUI DIGIT ONE..MENDE KIKAKUI DIGIT NINE
+1E8D0..1E8D6 ; N # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
+1E900..1E943 ; N # L& [68] ADLAM CAPITAL LETTER ALIF..ADLAM SMALL LETTER SHA
+1E944..1E94A ; N # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
+1E94B ; N # Lm ADLAM NASALIZATION MARK
+1E950..1E959 ; N # Nd [10] ADLAM DIGIT ZERO..ADLAM DIGIT NINE
+1E95E..1E95F ; N # Po [2] ADLAM INITIAL EXCLAMATION MARK..ADLAM INITIAL QUESTION MARK
+1EC71..1ECAB ; N # No [59] INDIC SIYAQ NUMBER ONE..INDIC SIYAQ NUMBER PREFIXED NINE
+1ECAC ; N # So INDIC SIYAQ PLACEHOLDER
+1ECAD..1ECAF ; N # No [3] INDIC SIYAQ FRACTION ONE QUARTER..INDIC SIYAQ FRACTION THREE QUARTERS
+1ECB0 ; N # Sc INDIC SIYAQ RUPEE MARK
+1ECB1..1ECB4 ; N # No [4] INDIC SIYAQ NUMBER ALTERNATE ONE..INDIC SIYAQ ALTERNATE LAKH MARK
+1ED01..1ED2D ; N # No [45] OTTOMAN SIYAQ NUMBER ONE..OTTOMAN SIYAQ NUMBER NINETY THOUSAND
+1ED2E ; N # So OTTOMAN SIYAQ MARRATAN
+1ED2F..1ED3D ; N # No [15] OTTOMAN SIYAQ ALTERNATE NUMBER TWO..OTTOMAN SIYAQ FRACTION ONE SIXTH
+1EE00..1EE03 ; N # Lo [4] ARABIC MATHEMATICAL ALEF..ARABIC MATHEMATICAL DAL
+1EE05..1EE1F ; N # Lo [27] ARABIC MATHEMATICAL WAW..ARABIC MATHEMATICAL DOTLESS QAF
+1EE21..1EE22 ; N # Lo [2] ARABIC MATHEMATICAL INITIAL BEH..ARABIC MATHEMATICAL INITIAL JEEM
+1EE24 ; N # Lo ARABIC MATHEMATICAL INITIAL HEH
+1EE27 ; N # Lo ARABIC MATHEMATICAL INITIAL HAH
+1EE29..1EE32 ; N # Lo [10] ARABIC MATHEMATICAL INITIAL YEH..ARABIC MATHEMATICAL INITIAL QAF
+1EE34..1EE37 ; N # Lo [4] ARABIC MATHEMATICAL INITIAL SHEEN..ARABIC MATHEMATICAL INITIAL KHAH
+1EE39 ; N # Lo ARABIC MATHEMATICAL INITIAL DAD
+1EE3B ; N # Lo ARABIC MATHEMATICAL INITIAL GHAIN
+1EE42 ; N # Lo ARABIC MATHEMATICAL TAILED JEEM
+1EE47 ; N # Lo ARABIC MATHEMATICAL TAILED HAH
+1EE49 ; N # Lo ARABIC MATHEMATICAL TAILED YEH
+1EE4B ; N # Lo ARABIC MATHEMATICAL TAILED LAM
+1EE4D..1EE4F ; N # Lo [3] ARABIC MATHEMATICAL TAILED NOON..ARABIC MATHEMATICAL TAILED AIN
+1EE51..1EE52 ; N # Lo [2] ARABIC MATHEMATICAL TAILED SAD..ARABIC MATHEMATICAL TAILED QAF
+1EE54 ; N # Lo ARABIC MATHEMATICAL TAILED SHEEN
+1EE57 ; N # Lo ARABIC MATHEMATICAL TAILED KHAH
+1EE59 ; N # Lo ARABIC MATHEMATICAL TAILED DAD
+1EE5B ; N # Lo ARABIC MATHEMATICAL TAILED GHAIN
+1EE5D ; N # Lo ARABIC MATHEMATICAL TAILED DOTLESS NOON
+1EE5F ; N # Lo ARABIC MATHEMATICAL TAILED DOTLESS QAF
+1EE61..1EE62 ; N # Lo [2] ARABIC MATHEMATICAL STRETCHED BEH..ARABIC MATHEMATICAL STRETCHED JEEM
+1EE64 ; N # Lo ARABIC MATHEMATICAL STRETCHED HEH
+1EE67..1EE6A ; N # Lo [4] ARABIC MATHEMATICAL STRETCHED HAH..ARABIC MATHEMATICAL STRETCHED KAF
+1EE6C..1EE72 ; N # Lo [7] ARABIC MATHEMATICAL STRETCHED MEEM..ARABIC MATHEMATICAL STRETCHED QAF
+1EE74..1EE77 ; N # Lo [4] ARABIC MATHEMATICAL STRETCHED SHEEN..ARABIC MATHEMATICAL STRETCHED KHAH
+1EE79..1EE7C ; N # Lo [4] ARABIC MATHEMATICAL STRETCHED DAD..ARABIC MATHEMATICAL STRETCHED DOTLESS BEH
+1EE7E ; N # Lo ARABIC MATHEMATICAL STRETCHED DOTLESS FEH
+1EE80..1EE89 ; N # Lo [10] ARABIC MATHEMATICAL LOOPED ALEF..ARABIC MATHEMATICAL LOOPED YEH
+1EE8B..1EE9B ; N # Lo [17] ARABIC MATHEMATICAL LOOPED LAM..ARABIC MATHEMATICAL LOOPED GHAIN
+1EEA1..1EEA3 ; N # Lo [3] ARABIC MATHEMATICAL DOUBLE-STRUCK BEH..ARABIC MATHEMATICAL DOUBLE-STRUCK DAL
+1EEA5..1EEA9 ; N # Lo [5] ARABIC MATHEMATICAL DOUBLE-STRUCK WAW..ARABIC MATHEMATICAL DOUBLE-STRUCK YEH
+1EEAB..1EEBB ; N # Lo [17] ARABIC MATHEMATICAL DOUBLE-STRUCK LAM..ARABIC MATHEMATICAL DOUBLE-STRUCK GHAIN
+1EEF0..1EEF1 ; N # Sm [2] ARABIC MATHEMATICAL OPERATOR MEEM WITH HAH WITH TATWEEL..ARABIC MATHEMATICAL OPERATOR HAH WITH DAL
+1F000..1F003 ; N # So [4] MAHJONG TILE EAST WIND..MAHJONG TILE NORTH WIND
+1F004 ; W # So MAHJONG TILE RED DRAGON
+1F005..1F02B ; N # So [39] MAHJONG TILE GREEN DRAGON..MAHJONG TILE BACK
+1F030..1F093 ; N # So [100] DOMINO TILE HORIZONTAL BACK..DOMINO TILE VERTICAL-06-06
+1F0A0..1F0AE ; N # So [15] PLAYING CARD BACK..PLAYING CARD KING OF SPADES
+1F0B1..1F0BF ; N # So [15] PLAYING CARD ACE OF HEARTS..PLAYING CARD RED JOKER
+1F0C1..1F0CE ; N # So [14] PLAYING CARD ACE OF DIAMONDS..PLAYING CARD KING OF DIAMONDS
+1F0CF ; W # So PLAYING CARD BLACK JOKER
+1F0D1..1F0F5 ; N # So [37] PLAYING CARD ACE OF CLUBS..PLAYING CARD TRUMP-21
+1F100..1F10A ; A # No [11] DIGIT ZERO FULL STOP..DIGIT NINE COMMA
+1F10B..1F10C ; N # No [2] DINGBAT CIRCLED SANS-SERIF DIGIT ZERO..DINGBAT NEGATIVE CIRCLED SANS-SERIF DIGIT ZERO
+1F10D..1F10F ; N # So [3] CIRCLED ZERO WITH SLASH..CIRCLED DOLLAR SIGN WITH OVERLAID BACKSLASH
+1F110..1F12D ; A # So [30] PARENTHESIZED LATIN CAPITAL LETTER A..CIRCLED CD
+1F12E..1F12F ; N # So [2] CIRCLED WZ..COPYLEFT SYMBOL
+1F130..1F169 ; A # So [58] SQUARED LATIN CAPITAL LETTER A..NEGATIVE CIRCLED LATIN CAPITAL LETTER Z
+1F16A..1F16F ; N # So [6] RAISED MC SIGN..CIRCLED HUMAN FIGURE
+1F170..1F18D ; A # So [30] NEGATIVE SQUARED LATIN CAPITAL LETTER A..NEGATIVE SQUARED SA
+1F18E ; W # So NEGATIVE SQUARED AB
+1F18F..1F190 ; A # So [2] NEGATIVE SQUARED WC..SQUARE DJ
+1F191..1F19A ; W # So [10] SQUARED CL..SQUARED VS
+1F19B..1F1AC ; A # So [18] SQUARED THREE D..SQUARED VOD
+1F1AD ; N # So MASK WORK SYMBOL
+1F1E6..1F1FF ; N # So [26] REGIONAL INDICATOR SYMBOL LETTER A..REGIONAL INDICATOR SYMBOL LETTER Z
+1F200..1F202 ; W # So [3] SQUARE HIRAGANA HOKA..SQUARED KATAKANA SA
+1F210..1F23B ; W # So [44] SQUARED CJK UNIFIED IDEOGRAPH-624B..SQUARED CJK UNIFIED IDEOGRAPH-914D
+1F240..1F248 ; W # So [9] TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-672C..TORTOISE SHELL BRACKETED CJK UNIFIED IDEOGRAPH-6557
+1F250..1F251 ; W # So [2] CIRCLED IDEOGRAPH ADVANTAGE..CIRCLED IDEOGRAPH ACCEPT
+1F260..1F265 ; W # So [6] ROUNDED SYMBOL FOR FU..ROUNDED SYMBOL FOR CAI
+1F300..1F320 ; W # So [33] CYCLONE..SHOOTING STAR
+1F321..1F32C ; N # So [12] THERMOMETER..WIND BLOWING FACE
+1F32D..1F335 ; W # So [9] HOT DOG..CACTUS
+1F336 ; N # So HOT PEPPER
+1F337..1F37C ; W # So [70] TULIP..BABY BOTTLE
+1F37D ; N # So FORK AND KNIFE WITH PLATE
+1F37E..1F393 ; W # So [22] BOTTLE WITH POPPING CORK..GRADUATION CAP
+1F394..1F39F ; N # So [12] HEART WITH TIP ON THE LEFT..ADMISSION TICKETS
+1F3A0..1F3CA ; W # So [43] CAROUSEL HORSE..SWIMMER
+1F3CB..1F3CE ; N # So [4] WEIGHT LIFTER..RACING CAR
+1F3CF..1F3D3 ; W # So [5] CRICKET BAT AND BALL..TABLE TENNIS PADDLE AND BALL
+1F3D4..1F3DF ; N # So [12] SNOW CAPPED MOUNTAIN..STADIUM
+1F3E0..1F3F0 ; W # So [17] HOUSE BUILDING..EUROPEAN CASTLE
+1F3F1..1F3F3 ; N # So [3] WHITE PENNANT..WAVING WHITE FLAG
+1F3F4 ; W # So WAVING BLACK FLAG
+1F3F5..1F3F7 ; N # So [3] ROSETTE..LABEL
+1F3F8..1F3FA ; W # So [3] BADMINTON RACQUET AND SHUTTLECOCK..AMPHORA
+1F3FB..1F3FF ; W # Sk [5] EMOJI MODIFIER FITZPATRICK TYPE-1-2..EMOJI MODIFIER FITZPATRICK TYPE-6
+1F400..1F43E ; W # So [63] RAT..PAW PRINTS
+1F43F ; N # So CHIPMUNK
+1F440 ; W # So EYES
+1F441 ; N # So EYE
+1F442..1F4FC ; W # So [187] EAR..VIDEOCASSETTE
+1F4FD..1F4FE ; N # So [2] FILM PROJECTOR..PORTABLE STEREO
+1F4FF..1F53D ; W # So [63] PRAYER BEADS..DOWN-POINTING SMALL RED TRIANGLE
+1F53E..1F54A ; N # So [13] LOWER RIGHT SHADOWED WHITE CIRCLE..DOVE OF PEACE
+1F54B..1F54E ; W # So [4] KAABA..MENORAH WITH NINE BRANCHES
+1F54F ; N # So BOWL OF HYGIEIA
+1F550..1F567 ; W # So [24] CLOCK FACE ONE OCLOCK..CLOCK FACE TWELVE-THIRTY
+1F568..1F579 ; N # So [18] RIGHT SPEAKER..JOYSTICK
+1F57A ; W # So MAN DANCING
+1F57B..1F594 ; N # So [26] LEFT HAND TELEPHONE RECEIVER..REVERSED VICTORY HAND
+1F595..1F596 ; W # So [2] REVERSED HAND WITH MIDDLE FINGER EXTENDED..RAISED HAND WITH PART BETWEEN MIDDLE AND RING FINGERS
+1F597..1F5A3 ; N # So [13] WHITE DOWN POINTING LEFT HAND INDEX..BLACK DOWN POINTING BACKHAND INDEX
+1F5A4 ; W # So BLACK HEART
+1F5A5..1F5FA ; N # So [86] DESKTOP COMPUTER..WORLD MAP
+1F5FB..1F5FF ; W # So [5] MOUNT FUJI..MOYAI
+1F600..1F64F ; W # So [80] GRINNING FACE..PERSON WITH FOLDED HANDS
+1F650..1F67F ; N # So [48] NORTH WEST POINTING LEAF..REVERSE CHECKER BOARD
+1F680..1F6C5 ; W # So [70] ROCKET..LEFT LUGGAGE
+1F6C6..1F6CB ; N # So [6] TRIANGLE WITH ROUNDED CORNERS..COUCH AND LAMP
+1F6CC ; W # So SLEEPING ACCOMMODATION
+1F6CD..1F6CF ; N # So [3] SHOPPING BAGS..BED
+1F6D0..1F6D2 ; W # So [3] PLACE OF WORSHIP..SHOPPING TROLLEY
+1F6D3..1F6D4 ; N # So [2] STUPA..PAGODA
+1F6D5..1F6D7 ; W # So [3] HINDU TEMPLE..ELEVATOR
+1F6DC..1F6DF ; W # So [4] WIRELESS..RING BUOY
+1F6E0..1F6EA ; N # So [11] HAMMER AND WRENCH..NORTHEAST-POINTING AIRPLANE
+1F6EB..1F6EC ; W # So [2] AIRPLANE DEPARTURE..AIRPLANE ARRIVING
+1F6F0..1F6F3 ; N # So [4] SATELLITE..PASSENGER SHIP
+1F6F4..1F6FC ; W # So [9] SCOOTER..ROLLER SKATE
+1F700..1F776 ; N # So [119] ALCHEMICAL SYMBOL FOR QUINTESSENCE..LUNAR ECLIPSE
+1F77B..1F77F ; N # So [5] HAUMEA..ORCUS
+1F780..1F7D9 ; N # So [90] BLACK LEFT-POINTING ISOSCELES RIGHT TRIANGLE..NINE POINTED WHITE STAR
+1F7E0..1F7EB ; W # So [12] LARGE ORANGE CIRCLE..LARGE BROWN SQUARE
+1F7F0 ; W # So HEAVY EQUALS SIGN
+1F800..1F80B ; N # So [12] LEFTWARDS ARROW WITH SMALL TRIANGLE ARROWHEAD..DOWNWARDS ARROW WITH LARGE TRIANGLE ARROWHEAD
+1F810..1F847 ; N # So [56] LEFTWARDS ARROW WITH SMALL EQUILATERAL ARROWHEAD..DOWNWARDS HEAVY ARROW
+1F850..1F859 ; N # So [10] LEFTWARDS SANS-SERIF ARROW..UP DOWN SANS-SERIF ARROW
+1F860..1F887 ; N # So [40] WIDE-HEADED LEFTWARDS LIGHT BARB ARROW..WIDE-HEADED SOUTH WEST VERY HEAVY BARB ARROW
+1F890..1F8AD ; N # So [30] LEFTWARDS TRIANGLE ARROWHEAD..WHITE ARROW SHAFT WIDTH TWO THIRDS
+1F8B0..1F8B1 ; N # So [2] ARROW POINTING UPWARDS THEN NORTH WEST..ARROW POINTING RIGHTWARDS THEN CURVING SOUTH WEST
+1F900..1F90B ; N # So [12] CIRCLED CROSS FORMEE WITH FOUR DOTS..DOWNWARD FACING NOTCHED HOOK WITH DOT
+1F90C..1F93A ; W # So [47] PINCHED FINGERS..FENCER
+1F93B ; N # So MODERN PENTATHLON
+1F93C..1F945 ; W # So [10] WRESTLERS..GOAL NET
+1F946 ; N # So RIFLE
+1F947..1F9FF ; W # So [185] FIRST PLACE MEDAL..NAZAR AMULET
+1FA00..1FA53 ; N # So [84] NEUTRAL CHESS KING..BLACK CHESS KNIGHT-BISHOP
+1FA60..1FA6D ; N # So [14] XIANGQI RED GENERAL..XIANGQI BLACK SOLDIER
+1FA70..1FA7C ; W # So [13] BALLET SHOES..CRUTCH
+1FA80..1FA88 ; W # So [9] YO-YO..FLUTE
+1FA90..1FABD ; W # So [46] RINGED PLANET..WING
+1FABF..1FAC5 ; W # So [7] GOOSE..PERSON WITH CROWN
+1FACE..1FADB ; W # So [14] MOOSE..PEA POD
+1FAE0..1FAE8 ; W # So [9] MELTING FACE..SHAKING FACE
+1FAF0..1FAF8 ; W # So [9] HAND WITH INDEX FINGER AND THUMB CROSSED..RIGHTWARDS PUSHING HAND
+1FB00..1FB92 ; N # So [147] BLOCK SEXTANT-1..UPPER HALF INVERSE MEDIUM SHADE AND LOWER HALF BLOCK
+1FB94..1FBCA ; N # So [55] LEFT HALF INVERSE MEDIUM SHADE AND RIGHT HALF BLOCK..WHITE UP-POINTING CHEVRON
+1FBF0..1FBF9 ; N # Nd [10] SEGMENTED DIGIT ZERO..SEGMENTED DIGIT NINE
+20000..2A6DF ; W # Lo [42720] CJK UNIFIED IDEOGRAPH-20000..CJK UNIFIED IDEOGRAPH-2A6DF
+2A6E0..2A6FF ; W # Cn [32] <reserved-2A6E0>..<reserved-2A6FF>
+2A700..2B739 ; W # Lo [4154] CJK UNIFIED IDEOGRAPH-2A700..CJK UNIFIED IDEOGRAPH-2B739
+2B73A..2B73F ; W # Cn [6] <reserved-2B73A>..<reserved-2B73F>
+2B740..2B81D ; W # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
+2B81E..2B81F ; W # Cn [2] <reserved-2B81E>..<reserved-2B81F>
+2B820..2CEA1 ; W # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
+2CEA2..2CEAF ; W # Cn [14] <reserved-2CEA2>..<reserved-2CEAF>
+2CEB0..2EBE0 ; W # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
+2EBE1..2EBEF ; W # Cn [15] <reserved-2EBE1>..<reserved-2EBEF>
+2EBF0..2EE5D ; W # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
+2EE5E..2F7FF ; W # Cn [2466] <reserved-2EE5E>..<reserved-2F7FF>
+2F800..2FA1D ; W # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
+2FA1E..2FA1F ; W # Cn [2] <reserved-2FA1E>..<reserved-2FA1F>
+2FA20..2FFFD ; W # Cn [1502] <reserved-2FA20>..<reserved-2FFFD>
+30000..3134A ; W # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
+3134B..3134F ; W # Cn [5] <reserved-3134B>..<reserved-3134F>
+31350..323AF ; W # Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF
+323B0..3FFFD ; W # Cn [56398] <reserved-323B0>..<reserved-3FFFD>
+E0001 ; N # Cf LANGUAGE TAG
+E0020..E007F ; N # Cf [96] TAG SPACE..CANCEL TAG
+E0100..E01EF ; A # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
+F0000..FFFFD ; A # Co [65534] <private-use-F0000>..<private-use-FFFFD>
+100000..10FFFD ; A # Co [65534] <private-use-100000>..<private-use-10FFFD>
# EOF
diff --git a/src/unicode/UnicodeData.txt b/src/unicode/UnicodeData.txt
index ea963a7162..bdcc41850d 100644
--- a/src/unicode/UnicodeData.txt
+++ b/src/unicode/UnicodeData.txt
@@ -11231,6 +11231,10 @@
2FF9;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT;So;0;ON;;;;;N;;;;;
2FFA;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT;So;0;ON;;;;;N;;;;;
2FFB;IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID;So;0;ON;;;;;N;;;;;
+2FFC;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM RIGHT;So;0;ON;;;;;N;;;;;
+2FFD;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER RIGHT;So;0;ON;;;;;N;;;;;
+2FFE;IDEOGRAPHIC DESCRIPTION CHARACTER HORIZONTAL REFLECTION;So;0;ON;;;;;N;;;;;
+2FFF;IDEOGRAPHIC DESCRIPTION CHARACTER ROTATION;So;0;ON;;;;;N;;;;;
3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
3001;IDEOGRAPHIC COMMA;Po;0;ON;;;;;N;;;;;
3002;IDEOGRAPHIC FULL STOP;Po;0;ON;;;;;N;IDEOGRAPHIC PERIOD;;;;
@@ -11705,6 +11709,7 @@
31E1;CJK STROKE HZZZG;So;0;ON;;;;;N;;;;;
31E2;CJK STROKE PG;So;0;ON;;;;;N;;;;;
31E3;CJK STROKE Q;So;0;ON;;;;;N;;;;;
+31EF;IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION;So;0;ON;;;;;N;;;;;
31F0;KATAKANA LETTER SMALL KU;Lo;0;L;;;;;N;;;;;
31F1;KATAKANA LETTER SMALL SI;Lo;0;L;;;;;N;;;;;
31F2;KATAKANA LETTER SMALL SU;Lo;0;L;;;;;N;;;;;
@@ -34035,6 +34040,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
2CEA1;<CJK Ideograph Extension E, Last>;Lo;0;L;;;;;N;;;;;
2CEB0;<CJK Ideograph Extension F, First>;Lo;0;L;;;;;N;;;;;
2EBE0;<CJK Ideograph Extension F, Last>;Lo;0;L;;;;;N;;;;;
+2EBF0;<CJK Ideograph Extension I, First>;Lo;0;L;;;;;N;;;;;
+2EE5D;<CJK Ideograph Extension I, Last>;Lo;0;L;;;;;N;;;;;
2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;;
2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;;
2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;;
diff --git a/src/unicode/emoji-data.txt b/src/unicode/emoji-data.txt
index 999a436779..0ba10e9ce4 100644
--- a/src/unicode/emoji-data.txt
+++ b/src/unicode/emoji-data.txt
@@ -1,11 +1,11 @@
# emoji-data.txt
-# Date: 2022-08-02, 00:26:10 GMT
-# © 2022 Unicode®, Inc.
+# Date: 2023-02-01, 02:22:54 GMT
+# © 2023 Unicode®, Inc.
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
# For terms of use, see https://www.unicode.org/terms_of_use.html
#
# Emoji Data for UTS #51
-# Used with Emoji Version 15.0 and subsequent minor revisions (if any)
+# Used with Emoji Version 15.1 and subsequent minor revisions (if any)
#
# For documentation and usage, see https://www.unicode.org/reports/tr51
#
diff --git a/test/.luarc.json b/test/.luarc.json
index 5d19a37266..1de363557d 100644
--- a/test/.luarc.json
+++ b/test/.luarc.json
@@ -12,7 +12,7 @@
"${3rd}/luassert/library",
"${3rd}/luv/library"
],
- "checkThirdParty": false
+ "checkThirdParty": "Disable"
},
"diagnostics": {
"groupFileStatus": {
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index e9be79edc0..3ae11bd1a7 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -1,33 +1,25 @@
add_subdirectory(functional/fixtures) # compile test programs
-get_directory_property(GENERATED_HELP_TAGS DIRECTORY ${PROJECT_SOURCE_DIR}/runtime DEFINITION GENERATED_HELP_TAGS)
-
-if(NOT BUSTED_OUTPUT_TYPE)
- set(BUSTED_OUTPUT_TYPE "nvim")
-endif()
get_target_property(TEST_INCLUDE_DIRS main_lib INTERFACE_INCLUDE_DIRECTORIES)
-set(UNITTEST_PREREQS nvim)
-set(FUNCTIONALTEST_PREREQS nvim printenv-test printargs-test shell-test pwsh-test streams-test tty-test ${GENERATED_HELP_TAGS})
-set(BENCHMARK_PREREQS nvim tty-test)
+set(TEST_OPTIONS
+ -D BUILD_DIR=${CMAKE_BINARY_DIR}
+ -D CIRRUS_CI=$ENV{CIRRUS_CI}
+ -D CI_BUILD=${CI_BUILD}
+ -D DEPS_INSTALL_DIR=${DEPS_INSTALL_DIR}
+ -D NVIM_PRG=$<TARGET_FILE:nvim_bin>
+ -D TEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}
+ -D WORKING_DIR=${PROJECT_SOURCE_DIR})
check_lua_module(${LUA_PRG} "ffi" LUA_HAS_FFI)
if(LUA_HAS_FFI)
add_custom_target(unittest
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 DEPS_INSTALL_DIR=${DEPS_INSTALL_DIR}
-D TEST_TYPE=unit
- -D CIRRUS_CI=$ENV{CIRRUS_CI}
- -D CI_BUILD=${CI_BUILD}
+ ${TEST_OPTIONS}
-P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
- DEPENDS ${UNITTEST_PREREQS}
USES_TERMINAL)
- add_dependencies(unittest lua-dev-deps)
+ add_dependencies(unittest lua-dev-deps nvim)
else()
message(WARNING "disabling unit tests: no Luajit FFI in ${LUA_PRG}")
endif()
@@ -38,33 +30,18 @@ configure_file(
add_custom_target(functionaltest
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 DEPS_INSTALL_DIR=${DEPS_INSTALL_DIR}
-D TEST_TYPE=functional
- -D CIRRUS_CI=$ENV{CIRRUS_CI}
- -D CI_BUILD=${CI_BUILD}
+ ${TEST_OPTIONS}
-P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
- DEPENDS ${FUNCTIONALTEST_PREREQS}
+ DEPENDS printenv-test printargs-test shell-test pwsh-test streams-test tty-test
USES_TERMINAL)
+add_dependencies(functionaltest lua-dev-deps nvim)
add_custom_target(benchmark
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 DEPS_INSTALL_DIR=${DEPS_INSTALL_DIR}
-D TEST_TYPE=benchmark
- -D CIRRUS_CI=$ENV{CIRRUS_CI}
- -D CI_BUILD=${CI_BUILD}
+ ${TEST_OPTIONS}
-P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
- DEPENDS ${BENCHMARK_PREREQS}
+ DEPENDS tty-test
USES_TERMINAL)
-
-add_dependencies(functionaltest lua-dev-deps)
-add_dependencies(benchmark lua-dev-deps)
+add_dependencies(benchmark lua-dev-deps nvim)
diff --git a/test/benchmark/autocmd_spec.lua b/test/benchmark/autocmd_spec.lua
index cd1af23640..b3421d86eb 100644
--- a/test/benchmark/autocmd_spec.lua
+++ b/test/benchmark/autocmd_spec.lua
@@ -27,7 +27,8 @@ describe('autocmd perf', function()
end)
it('nvim_create_autocmd, nvim_del_autocmd (same pattern)', function()
- exec_lua([[
+ exec_lua(
+ [[
local N = ...
local ids = {}
@@ -45,11 +46,14 @@ describe('autocmd perf', function()
vim.api.nvim_del_autocmd(ids[i])
end
stop('nvim_del_autocmd')
- ]], N)
+ ]],
+ N
+ )
end)
it('nvim_create_autocmd, nvim_del_autocmd (unique patterns)', function()
- exec_lua([[
+ exec_lua(
+ [[
local N = ...
local ids = {}
@@ -67,11 +71,14 @@ describe('autocmd perf', function()
vim.api.nvim_del_autocmd(ids[i])
end
stop('nvim_del_autocmd')
- ]], N)
+ ]],
+ N
+ )
end)
it('nvim_create_autocmd + nvim_del_autocmd', function()
- exec_lua([[
+ exec_lua(
+ [[
local N = ...
start()
@@ -83,11 +90,14 @@ describe('autocmd perf', function()
vim.api.nvim_del_autocmd(id)
end
stop('nvim_create_autocmd + nvim_del_autocmd')
- ]], N)
+ ]],
+ N
+ )
end)
it('nvim_exec_autocmds (same pattern)', function()
- exec_lua([[
+ exec_lua(
+ [[
local N = ...
for i = 1, N do
@@ -100,11 +110,14 @@ describe('autocmd perf', function()
start()
vim.api.nvim_exec_autocmds('User', { pattern = 'Benchmark', modeline = false })
stop('nvim_exec_autocmds')
- ]], N)
+ ]],
+ N
+ )
end)
it('nvim_del_augroup_by_id', function()
- exec_lua([[
+ exec_lua(
+ [[
local N = ...
local group = vim.api.nvim_create_augroup('Benchmark', {})
@@ -119,11 +132,14 @@ describe('autocmd perf', function()
start()
vim.api.nvim_del_augroup_by_id(group)
stop('nvim_del_augroup_by_id')
- ]], N)
+ ]],
+ N
+ )
end)
it('nvim_del_augroup_by_name', function()
- exec_lua([[
+ exec_lua(
+ [[
local N = ...
local group = vim.api.nvim_create_augroup('Benchmark', {})
@@ -138,11 +154,14 @@ describe('autocmd perf', function()
start()
vim.api.nvim_del_augroup_by_name('Benchmark')
stop('nvim_del_augroup_by_id')
- ]], N)
+ ]],
+ N
+ )
end)
it(':autocmd, :autocmd! (same pattern)', function()
- exec_lua([[
+ exec_lua(
+ [[
local N = ...
start()
@@ -154,11 +173,14 @@ describe('autocmd perf', function()
start()
vim.cmd('autocmd! User Benchmark')
stop(':autocmd!')
- ]], N)
+ ]],
+ N
+ )
end)
it(':autocmd, :autocmd! (unique patterns)', function()
- exec_lua([[
+ exec_lua(
+ [[
local N = ...
start()
@@ -170,6 +192,8 @@ describe('autocmd perf', function()
start()
vim.cmd('autocmd! User')
stop(':autocmd!')
- ]], N)
+ ]],
+ N
+ )
end)
end)
diff --git a/test/benchmark/bench_regexp_spec.lua b/test/benchmark/bench_regexp_spec.lua
index 6128549f0f..4a7c50557b 100644
--- a/test/benchmark/bench_regexp_spec.lua
+++ b/test/benchmark/bench_regexp_spec.lua
@@ -10,8 +10,7 @@ local result_file = 'benchmark.out'
local sample_file = 'test/old/testdir/samples/re.freeze.txt'
-- Vim script code that does both the work and the benchmarking of that work.
-local measure_cmd =
- [[call Measure(%d, ']] .. sample_file .. [[', '\s\+\%%#\@<!$', '+5')]]
+local measure_cmd = [[call Measure(%d, ']] .. sample_file .. [[', '\s\+\%%#\@<!$', '+5')]]
local measure_script = [[
func Measure(re, file, pattern, arg)
let sstart = reltime()
diff --git a/test/benchmark/deepcopy_spec.lua b/test/benchmark/deepcopy_spec.lua
new file mode 100644
index 0000000000..dc8655f19c
--- /dev/null
+++ b/test/benchmark/deepcopy_spec.lua
@@ -0,0 +1,58 @@
+local N = 20
+
+local function tcall(f, ...)
+ local ts = vim.uv.hrtime()
+ for _ = 1, N do
+ f(...)
+ end
+ return ((vim.uv.hrtime() - ts) / 1000000) / N
+end
+
+local function build_shared(n)
+ local t = {}
+ local a = {}
+ local b = {}
+ local c = {}
+ for _ = 1, n do
+ t[#t + 1] = {}
+ local tl = t[#t]
+ for _ = 1, n do
+ tl[#tl + 1] = a
+ tl[#tl + 1] = b
+ tl[#tl + 1] = c
+ end
+ end
+ return t
+end
+
+local function build_unique(n)
+ local t = {}
+ for _ = 1, n do
+ t[#t + 1] = {}
+ local tl = t[#t]
+ for _ = 1, n do
+ tl[#tl + 1] = {}
+ end
+ end
+ return t
+end
+
+describe('vim.deepcopy()', function()
+ local function run(name, n, noref)
+ it(string.format('%s entries=%d noref=%s', name, n, noref), function()
+ local t = name == 'shared' and build_shared(n) or build_unique(n)
+ local d = tcall(vim.deepcopy, t, noref)
+ print(string.format('%.2f ms', d))
+ end)
+ end
+
+ run('unique', 50, false)
+ run('unique', 50, true)
+ run('unique', 2000, false)
+ run('unique', 2000, true)
+
+ run('shared', 50, false)
+ run('shared', 50, true)
+ run('shared', 2000, false)
+ run('shared', 2000, true)
+end)
diff --git a/test/benchmark/screenpos_spec.lua b/test/benchmark/screenpos_spec.lua
new file mode 100644
index 0000000000..8a80712dfa
--- /dev/null
+++ b/test/benchmark/screenpos_spec.lua
@@ -0,0 +1,376 @@
+local helpers = require('test.functional.helpers')(after_each)
+local api = helpers.api
+local Screen = require('test.functional.ui.screen')
+
+local function rand_utf8(count, seed)
+ math.randomseed(seed)
+ local symbols = { 'i', 'À', 'â± ', 'ð€€' }
+ local s = ''
+ for _ = 1, count do
+ s = s .. symbols[math.random(1, #symbols)]
+ end
+ return s
+end
+
+local width, height = 100, 50
+
+local benchmark_chars = {
+ {
+ name = 'ascii',
+ line = function(count, _)
+ return ('i'):rep(count)
+ end,
+ },
+ {
+ name = '2 byte utf-8',
+ line = function(count, _)
+ return ('À'):rep(count)
+ end,
+ },
+ {
+ name = '3 byte utf-8',
+ line = function(count, _)
+ return ('â± '):rep(count)
+ end,
+ },
+ {
+ name = 'random 1-4 byte utf-8',
+ line = function(count, i)
+ return rand_utf8(count, 123456 + i)
+ end,
+ },
+}
+
+local benchmark_lines = {
+ {
+ name = 'long line',
+ lines = function(line)
+ return { line(width * height - 1, 1) }
+ end,
+ },
+ {
+ name = 'multiple lines',
+ lines = function(line)
+ local lines = {}
+ for i = 1, height - 1 do
+ table.insert(lines, line(width, i))
+ end
+ table.insert(lines, line(width - 1, height))
+ return lines
+ end,
+ },
+ {
+ name = 'multiple wrapped lines',
+ lines = function(line)
+ local lines = {}
+ local count = math.floor(height / 2)
+ for i = 1, count - 1 do
+ table.insert(lines, line(width * 2, i))
+ end
+ table.insert(lines, line(width * 2 - 1, count))
+ return lines
+ end,
+ },
+}
+
+local N = 10000
+
+local function benchmark(lines, expected_value)
+ local lnum = #lines
+
+ local results = helpers.exec_lua(
+ [==[
+ local N, lnum = ...
+
+ local values = {}
+ local stats = {} -- time in ns
+ for i = 1, N do
+ local tic = vim.uv.hrtime()
+ local result = vim.fn.screenpos(0, lnum, 999999)
+ local toc = vim.uv.hrtime()
+ table.insert(values, result)
+ table.insert(stats, toc - tic)
+ end
+
+ return { values, stats }
+ ]==],
+ N,
+ lnum
+ )
+
+ for _, value in ipairs(results[1]) do
+ helpers.eq(expected_value, value)
+ end
+ local stats = results[2]
+ table.sort(stats)
+
+ local us = 1 / 1000
+ print(
+ string.format(
+ 'min, 25%%, median, 75%%, max:\n\t%0.2fus,\t%0.2fus,\t%0.2fus,\t%0.2fus,\t%0.2fus',
+ stats[1] * us,
+ stats[1 + math.floor(#stats * 0.25)] * us,
+ stats[1 + math.floor(#stats * 0.5)] * us,
+ stats[1 + math.floor(#stats * 0.75)] * us,
+ stats[#stats] * us
+ )
+ )
+end
+
+local function benchmarks(benchmark_results)
+ describe('screenpos() perf', function()
+ before_each(helpers.clear)
+
+ -- no breakindent
+ for li, lines_type in ipairs(benchmark_lines) do
+ for ci, chars_type in ipairs(benchmark_chars) do
+ local name = 'for ' .. lines_type.name .. ', ' .. chars_type.name .. ', nobreakindent'
+
+ local lines = lines_type.lines(chars_type.line)
+ local result = benchmark_results[li][ci]
+
+ it(name, function()
+ local screen = Screen.new(width, height + 1)
+ screen:attach()
+ api.nvim_buf_set_lines(0, 0, 1, false, lines)
+ -- for smaller screen expect (last line always different, first line same as others)
+ helpers.feed('G$')
+ screen:expect(result.screen)
+ benchmark(lines, result.value)
+ end)
+ end
+ end
+
+ -- breakindent
+ for li, lines_type in ipairs(benchmark_lines) do
+ for ci, chars_type in ipairs(benchmark_chars) do
+ local name = 'for ' .. lines_type.name .. ', ' .. chars_type.name .. ', breakindent'
+
+ local lines = lines_type.lines(chars_type.line)
+ local result = benchmark_results[li][ci]
+
+ it(name, function()
+ local screen = Screen.new(width, height + 1)
+ screen:attach()
+ api.nvim_buf_set_lines(0, 0, 1, false, lines)
+ helpers.command('set breakindent')
+ -- for smaller screen expect (last line always different, first line same as others)
+ helpers.feed('G$')
+ screen:expect(result.screen)
+ benchmark(lines, result.value)
+ end)
+ end
+ end
+ end)
+end
+
+local ascii_results = {
+ screen = [=[
+ iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii|*49
+ iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii^i |
+ |
+ ]=],
+ value = { col = 100, curscol = 100, endcol = 100, row = 50 },
+}
+local two_byte_results = {
+ screen = [=[
+ ÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ|*49
+ ÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀÀ^À |
+ |
+ ]=],
+ value = { col = 100, curscol = 100, endcol = 100, row = 50 },
+}
+local three_byte_results = {
+ screen = [=[
+ â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± |*49
+ â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± â± ^â±  |
+ |
+ ]=],
+ value = { col = 100, curscol = 100, endcol = 100, row = 50 },
+}
+
+benchmarks({
+ {
+ ascii_results,
+ two_byte_results,
+ three_byte_results,
+ { -- random
+ screen = [=[
+ â± ð€€iið€€â± Ã€ð€€ið€€ð€€iÀÀÀiÀð€€â± ð€€â± iiâ± ð€€iiið€€Ã€â± Ã€â± â± Ã€iiÀⱠÀiâ± ið€€Ã€Ã€ð€€ð€€â± ð€€ð€€â± ð€€iÀⱠð€€ið€€Ã€Ã€â± iiÀð€€â± ð€€Ã€ð€€iið€€Ã€Ã€ð€€Ã€â± â± ð€€ð€€ð€€ð€€iið€€â± â± iâ± â± ð€€â± Ã€ð€€Ã€Ã€iiâ± |
+ ð€€ð€€Ã€â± Ã€ð€€ð€€iⱠÀð€€ð€€ið€€ð€€ð€€ð€€â± â± â± iiiiÀÀð€€â± Ã€â± Ã€ið€€ið€€â± â± Ã€iÀⱠið€€ð€€Ã€ð€€iÀð€€Ã€Ã€Ã€ð€€ð€€iÀⱠð€€ð€€â± ð€€ð€€Ã€iâ± iiⱠⱠÀÀÀÀið€€Ã€Ã€â± ð€€Ã€iiið€€iâ± â± â± ið€€â± Ã€ið€€iâ± ð€€â± iâ± |
+ ⱠⱠⱠÀið€€Ã€iⱠÀiâ± iâ± ð€€Ã€iiiÀiiÀÀⱠð€€Ã€ð€€Ã€â± Ã€Ã€Ã€â± ð€€iâ± â± ð€€iⱠÀð€€Ã€ð€€â± iÀÀÀÀiiÀiÀiÀⱠiÀið€€iÀÀⱠð€€ð€€â± Ã€ð€€iâ± ð€€ið€€ið€€Ã€â± ið€€iⱠÀÀiiâ± ð€€ð€€â± iÀiÀiiÀ|
+ iâ± ð€€iiⱠÀⱠð€€iÀÀÀⱠÀiÀð€€ð€€ð€€Ã€â± iâ± iÀiâ± iâ± ð€€ð€€â± â± ið€€â± â± ð€€ð€€â± ð€€Ã€iiⱠÀⱠⱠð€€iÀiÀÀð€€ð€€ð€€â± â± ð€€iiið€€Ã€ð€€â± ð€€iâ± iið€€ið€€ið€€Ã€iÀið€€â± ð€€ð€€ið€€iÀÀiâ± ð€€â± ð€€Ã€Ã€Ã€Ã€|
+ ð€€Ã€â± iÀⱠÀÀÀⱠð€€Ã€ð€€ð€€ð€€ið€€Ã€ið€€ð€€iâ± ð€€ð€€Ã€â± ð€€ð€€Ã€ð€€ð€€â± Ã€Ã€â± â± â± iⱠÀÀiið€€â± iið€€â± ið€€Ã€ið€€â± ð€€ð€€ð€€ð€€iÀð€€â± Ã€iÀð€€â± â± ið€€ið€€â± â± Ã€â± ð€€â± Ã€â± ð€€Ã€â± iiâ± ð€€ð€€â± ð€€â± ð€€ð€€Ã€ð€€ð€€Ã€i|
+ iÀÀiÀÀiⱠÀiiâ± iÀiiiÀⱠÀð€€Ã€ið€€iiÀÀÀiâ± â± iiâ± ð€€iÀð€€ð€€ð€€â± Ã€Ã€ð€€iiâ± ð€€â± ð€€â± Ã€â± ð€€Ã€ið€€ið€€Ã€iÀⱠⱠð€€Ã€â± iiⱠÀð€€ð€€â± iið€€ð€€ið€€ð€€Ã€Ã€iÀð€€ið€€ð€€ið€€Ã€iiiⱠÀÀÀ|
+ ÀÀⱠⱠÀⱠⱠÀiiiÀⱠÀⱠⱠið€€â± Ã€ð€€iⱠÀð€€â± Ã€iiÀÀÀÀⱠð€€ð€€Ã€ð€€iiÀð€€ð€€iâ± â± ð€€iiâ± â± ð€€Ã€Ã€Ã€ð€€â± ð€€Ã€ð€€Ã€â± ið€€â± Ã€â± Ã€â± â± iÀð€€iÀÀⱠð€€â± â± ð€€ð€€iâ± â± â± ð€€ð€€Ã€ð€€iÀÀið€€iâ± â± ð€€ð€€|
+ ÀÀiiⱠÀð€€Ã€ið€€iiÀð€€iÀⱠÀÀið€€ð€€â± â± ð€€iiâ± â± iÀð€€iⱠÀÀiâ± ð€€Ã€Ã€iiâ± â± iÀÀð€€Ã€ð€€iⱠÀÀⱠiâ± ð€€iâ± ð€€Ã€iiⱠÀÀⱠÀÀiÀð€€ð€€â± â± Ã€â± Ã€Ã€â± ð€€Ã€ð€€â± â± ið€€Ã€ð€€ð€€â± â± ð€€iâ± ið€€â± |
+ ÀÀⱠð€€ð€€Ã€â± â± â± Ã€â± iⱠⱠⱠÀiiiâ± iiiÀið€€ð€€iâ± â± iiÀiⱠⱠⱠÀÀiiið€€Ã€iⱠÀið€€ið€€ð€€Ã€iÀiÀÀiÀð€€iÀÀÀiÀⱠⱠÀiÀð€€Ã€ð€€iⱠÀⱠð€€iið€€ð€€iâ± iÀiâ± ð€€â± ð€€â± ð€€ð€€â± iÀⱠ|
+ ÀⱠiið€€ið€€iÀÀÀÀÀð€€Ã€iÀð€€ð€€Ã€â± iiiiiÀⱠð€€Ã€Ã€Ã€â± ið€€iâ± iâ± iÀⱠⱠð€€ð€€iið€€ð€€iÀÀÀⱠiiÀð€€iÀiÀð€€â± ð€€â± ð€€ið€€iÀⱠiÀð€€ið€€â± iⱠÀð€€iⱠÀⱠiâ± iÀÀÀÀð€€â± ð€€iⱠⱠÀ|
+ ð€€â± ð€€â± Ã€ð€€iâ± iÀið€€ið€€ð€€ð€€â± Ã€â± iÀⱠⱠð€€Ã€iÀiâ± ið€€Ã€â± ið€€ð€€Ã€Ã€ið€€Ã€ð€€Ã€iiâ± ð€€iⱠÀÀÀiiið€€â± iâ± ð€€ð€€ð€€â± â± iâ± ð€€ð€€iiâ± iiiiið€€ð€€ð€€ð€€ð€€Ã€Ã€Ã€Ã€ið€€ð€€â± â± ð€€iÀð€€Ã€iiÀii|
+ â± ð€€ð€€iâ± ið€€â± ð€€â± â± iÀÀⱠið€€Ã€iâ± â± â± ð€€Ã€â± iâ± â± iⱠⱠÀð€€â± iiiÀð€€ð€€ð€€Ã€Ã€iâ± ið€€â± Ã€ð€€Ã€â± Ã€ið€€â± iÀⱠiiⱠⱠÀⱠiÀÀⱠÀÀÀÀð€€iÀⱠⱠiâ± â± ð€€Ã€Ã€Ã€â± iÀÀiÀⱠð€€iÀⱠiiâ± ð€€|
+ iÀⱠið€€Ã€â± Ã€Ã€Ã€iÀÀⱠð€€Ã€ð€€ð€€ð€€â± iiiâ± iiâ± ð€€Ã€ð€€iiið€€Ã€ð€€â± â± ið€€iiⱠÀð€€ð€€ið€€â± Ã€ð€€ð€€ið€€Ã€iⱠÀÀiÀÀið€€ð€€â± ð€€Ã€ð€€ið€€iÀⱠⱠⱠð€€Ã€Ã€Ã€â± Ã€Ã€â± â± â± â± â± ið€€ð€€iiⱠÀið€€ð€€â± â± |
+ iiâ± â± â± ð€€Ã€â± ð€€Ã€iiið€€Ã€Ã€iið€€Ã€ð€€iiⱠÀⱠiiâ± ð€€â± ð€€Ã€â± ð€€iÀiâ± iiÀÀiÀÀiâ± iâ± â± iâ± ð€€â± ið€€ð€€Ã€Ã€Ã€Ã€iâ± iið€€â± Ã€ð€€â± ð€€ið€€â± iâ± â± ð€€ið€€â± iâ± â± ð€€Ã€iâ± ð€€iÀið€€ð€€Ã€Ã€ð€€ð€€i|
+ iÀÀið€€Ã€Ã€Ã€ð€€Ã€â± ð€€Ã€Ã€Ã€ð€€ð€€ð€€iiⱠÀÀⱠð€€â± Ã€ð€€iiiÀÀiiâ± ð€€ð€€â± iiâ± iÀiⱠⱠÀð€€â± iⱠÀð€€ið€€ð€€ð€€â± Ã€ð€€â± ð€€Ã€Ã€Ã€â± â± ð€€ð€€Ã€ð€€iiⱠⱠⱠⱠⱠÀð€€ð€€iâ± â± iiÀiⱠÀiÀⱠiÀð€€Ã€ð€€i|
+ ÀⱠⱠð€€Ã€â± ið€€ið€€â± Ã€Ã€Ã€iiiâ± ð€€â± Ã€â± Ã€Ã€â± ð€€Ã€Ã€iÀiÀÀⱠÀⱠiâ± iÀð€€iⱠÀð€€ð€€ð€€Ã€â± â± ð€€â± â± ð€€Ã€â± â± â± iið€€Ã€Ã€Ã€Ã€iÀið€€â± â± Ã€iâ± iⱠÀⱠð€€Ã€iâ± â± iÀⱠið€€ð€€ð€€Ã€Ã€iiÀÀð€€ð€€Ã€â± |
+ Àð€€Ã€Ã€Ã€Ã€ð€€Ã€Ã€ð€€ið€€â± Ã€â± iⱠÀÀð€€â± iÀÀiⱠÀⱠⱠÀð€€iÀð€€ið€€ð€€â± Ã€Ã€Ã€â± â± iÀiiiiâ± â± ið€€Ã€â± ið€€ið€€ið€€ð€€ð€€â± Ã€â± iiiÀið€€Ã€â± ið€€iiÀÀⱠÀÀⱠiiÀð€€Ã€ð€€Ã€Ã€ð€€â± Ã€â± Ã€ð€€iâ± |
+ â± ð€€Ã€iâ± ð€€iiÀð€€Ã€ð€€ð€€Ã€ð€€Ã€Ã€iiiiiiâ± â± iiÀið€€iÀð€€Ã€Ã€iâ± ð€€Ã€â± Ã€Ã€Ã€iÀⱠⱠð€€Ã€ð€€ð€€iÀð€€ð€€iið€€â± Ã€ð€€iið€€ð€€iⱠÀð€€Ã€Ã€Ã€iÀiið€€iâ± ð€€â± â± ð€€Ã€â± iiiâ± â± â± ið€€Ã€Ã€iÀð€€ð€€Ã€|
+ â± iÀð€€â± Ã€ð€€iÀⱠið€€Ã€iiiÀÀð€€Ã€â± ð€€â± â± â± Ã€â± ð€€â± Ã€iiÀið€€ið€€ð€€iⱠÀⱠiâ± iiÀÀð€€ð€€ð€€Ã€ið€€ð€€iiâ± iⱠÀⱠð€€iiⱠÀið€€â± â± â± ið€€Ã€Ã€iÀⱠð€€ð€€Ã€iⱠÀiiÀÀⱠð€€â± iiÀⱠⱠÀiÀ|
+ ið€€ð€€Ã€ið€€ð€€â± Ã€iÀÀⱠⱠið€€ð€€Ã€Ã€â± Ã€Ã€â± â± â± â± ð€€Ã€iâ± iiⱠⱠÀiiiⱠⱠÀð€€â± iið€€ið€€â± Ã€ð€€Ã€Ã€â± â± iÀiÀÀiⱠÀiiiiÀⱠiiÀⱠⱠⱠÀÀið€€Ã€ð€€â± â± ð€€â± ið€€â± â± ð€€ð€€ð€€iⱠÀÀⱠð€€â± â± |
+ iÀÀⱠⱠⱠiiÀiið€€ð€€â± Ã€iiið€€â± Ã€ð€€â± iiÀð€€iâ± ð€€Ã€â± ð€€â± ð€€ð€€â± ið€€Ã€iⱠÀⱠð€€Ã€Ã€ið€€â± iÀÀÀÀⱠÀⱠiâ± iâ± â± ð€€ð€€Ã€â± Ã€â± ð€€ð€€Ã€Ã€ð€€â± â± ð€€ð€€ið€€â± iið€€iiið€€â± ið€€â± ð€€â± ið€€ð€€Ã€â± i|
+ Àð€€ð€€Ã€â± Ã€iiiÀiiÀⱠið€€iiiâ± iiⱠÀÀð€€â± Ã€ð€€â± â± â± ð€€ið€€Ã€Ã€iâ± iiiâ± iiÀÀiâ± ð€€Ã€ð€€ið€€â± ð€€â± Ã€iâ± â± ð€€Ã€â± â± ð€€ð€€Ã€iⱠÀÀⱠiiâ± ið€€ið€€â± Ã€Ã€iâ± ð€€â± ð€€iâ± â± ð€€Ã€Ã€Ã€iÀÀii|
+ ⱠÀð€€ð€€â± iⱠÀð€€Ã€Ã€Ã€â± â± Ã€â± ð€€Ã€iâ± iið€€ð€€Ã€â± ð€€iÀÀiiÀiÀÀð€€iⱠÀiÀð€€ð€€Ã€ð€€â± ð€€ð€€iiâ± â± ð€€â± Ã€â± Ã€iÀiÀð€€iâ± â± iÀið€€â± ð€€iiiÀⱠð€€Ã€â± iÀiiiâ± iiÀⱠÀiâ± iÀÀiⱠÀi|
+ ð€€ð€€Ã€Ã€ið€€Ã€ð€€ð€€Ã€â± â± â± ð€€Ã€ð€€ð€€Ã€ð€€Ã€iâ± â± ð€€ð€€â± Ã€iâ± iⱠÀð€€Ã€iâ± iiiið€€iâ± iⱠÀð€€Ã€â± ð€€ð€€iÀⱠiÀið€€ð€€â± Ã€iâ± iÀⱠⱠð€€iâ± ð€€Ã€â± Ã€iið€€â± Ã€â± iið€€â± ð€€Ã€Ã€ið€€Ã€Ã€iÀiÀⱠð€€Ã€â± â± |
+ ð€€iiiið€€iⱠÀÀⱠiÀⱠð€€â± iÀiâ± ið€€iⱠⱠⱠÀⱠⱠÀⱠð€€iÀⱠⱠiið€€iiið€€Ã€ð€€â± â± â± Ã€iÀÀð€€iiiiâ± â± â± ið€€ð€€iiâ± ð€€â± iâ± ð€€ið€€ð€€Ã€Ã€â± â± ð€€iâ± iⱠÀÀÀⱠⱠÀð€€iÀⱠⱠⱠⱠÀð€€iÀ|
+ ÀÀÀð€€Ã€Ã€â± iⱠÀiiÀÀð€€â± ð€€Ã€iið€€â± â± ð€€iÀÀð€€ð€€â± ð€€iâ± ð€€iⱠÀⱠⱠð€€Ã€Ã€ð€€ð€€Ã€ð€€Ã€â± iⱠÀiÀð€€iÀið€€â± iâ± ð€€ið€€iiâ± â± iⱠÀÀð€€â± ð€€â± â± ð€€ð€€ð€€â± â± iâ± â± ð€€â± â± â± ð€€Ã€iâ± â± ið€€iÀÀÀ|
+ ÀÀⱠiiÀÀÀⱠÀð€€ð€€iÀÀÀiÀið€€iâ± iâ± ð€€iÀÀÀð€€ð€€ð€€iÀiÀÀiÀÀið€€ið€€ð€€â± Ã€ð€€iið€€ð€€â± ð€€Ã€ð€€iÀÀⱠð€€iÀÀÀⱠÀÀð€€ð€€iâ± ð€€â± iÀⱠið€€ð€€ð€€iâ± ð€€â± â± â± ið€€ð€€Ã€Ã€Ã€ð€€Ã€â± Ã€iii|
+ iiâ± ið€€Ã€Ã€iâ± ð€€ð€€â± â± Ã€ð€€ð€€iÀⱠiⱠÀⱠÀiÀiⱠÀð€€ð€€â± iÀⱠⱠⱠⱠð€€iiⱠÀÀð€€Ã€iÀð€€â± ð€€Ã€iâ± â± ð€€Ã€ð€€â± iiâ± iâ± ð€€iâ± ð€€Ã€Ã€ð€€Ã€Ã€iⱠÀið€€Ã€â± iið€€ð€€ð€€Ã€Ã€ð€€iâ± ð€€iⱠÀⱠⱠiiið€€|
+ iÀiⱠÀið€€Ã€ð€€ð€€iiÀð€€ð€€ð€€Ã€ið€€ð€€â± Ã€Ã€ð€€iið€€ð€€ið€€iið€€â± ð€€ð€€ð€€â± Ã€â± ð€€Ã€â± ð€€iÀÀÀⱠÀÀð€€ð€€iâ± â± iÀð€€Ã€â± ð€€iiÀÀiâ± â± â± â± ð€€â± ð€€â± ð€€Ã€ð€€iâ± â± iâ± ð€€iiiið€€â± ið€€Ã€iâ± ð€€Ã€Ã€ii|
+ ⱠÀiið€€Ã€â± â± ð€€ð€€ið€€iiâ± ð€€ið€€â± ð€€Ã€ð€€ð€€â± â± iiÀiiÀið€€iið€€ð€€iiiÀiiâ± iÀð€€ð€€Ã€Ã€Ã€ð€€Ã€â± ð€€Ã€ið€€Ã€ð€€Ã€iiÀÀð€€â± ð€€â± â± iiÀÀⱠð€€ð€€ið€€ð€€â± â± ð€€ð€€ð€€ð€€â± iâ± ð€€â± â± Ã€ð€€â± Ã€Ã€Ã€Ã€Ã€|
+ iâ± â± â± ð€€Ã€â± ð€€ð€€Ã€iÀð€€Ã€ð€€iiÀð€€ð€€iâ± iiⱠⱠÀiⱠÀⱠð€€â± Ã€Ã€ð€€iiÀð€€ð€€â± Ã€iÀð€€iâ± iⱠÀⱠiiiâ± iiâ± â± â± iiÀð€€iÀð€€iâ± â± ð€€â± ið€€â± â± Ã€iâ± ð€€ið€€ð€€ð€€iiâ± iÀð€€Ã€â± â± Ã€Ã€Ã€ð€€ið€€|
+ ÀÀÀiið€€â± iâ± â± iâ± ð€€â± iâ± ð€€Ã€Ã€ið€€ð€€Ã€Ã€â± â± iÀÀiÀⱠÀð€€â± Ã€â± ð€€ð€€ð€€iâ± iâ± iâ± ð€€Ã€ð€€ð€€Ã€â± ð€€ð€€iiÀⱠð€€ið€€ð€€ð€€iiⱠÀð€€ð€€Ã€iâ± ið€€â± iÀð€€iÀⱠÀiÀⱠⱠⱠð€€Ã€â± ð€€â± ð€€Ã€ð€€â± Ã€iii|
+ ð€€Ã€Ã€ð€€ð€€iâ± â± ð€€â± iâ± iið€€ð€€â± â± Ã€Ã€â± Ã€â± iÀⱠⱠð€€Ã€â± â± Ã€ð€€iið€€ð€€ð€€iið€€ð€€â± iið€€ð€€Ã€Ã€Ã€iⱠÀiiiiiâ± iÀⱠⱠÀð€€ð€€â± Ã€â± Ã€iiiâ± ð€€Ã€Ã€â± Ã€ið€€â± iÀiÀið€€Ã€â± iâ± iiâ± ð€€iÀÀÀ|
+ â± iiÀiið€€Ã€Ã€ið€€ð€€â± Ã€Ã€â± â± ð€€iið€€Ã€â± iⱠⱠÀð€€ð€€â± â± iâ± â± iið€€iÀiiiâ± ð€€iiⱠÀÀÀÀð€€â± Ã€ið€€iâ± ið€€iið€€â± ð€€â± Ã€iiið€€ð€€Ã€Ã€Ã€iiⱠÀð€€â± ð€€â± Ã€â± â± ð€€ð€€ð€€ð€€ð€€Ã€ð€€Ã€â± â± ið€€â± â± |
+ ÀⱠð€€iiⱠⱠⱠÀÀð€€iÀiÀð€€â± â± Ã€iÀⱠÀð€€Ã€Ã€Ã€iâ± ð€€ð€€â± Ã€ð€€Ã€â± Ã€Ã€ð€€ð€€ð€€ð€€ð€€Ã€Ã€ð€€ð€€iÀⱠⱠiâ± iÀiiiâ± iÀÀiⱠÀð€€ð€€Ã€ið€€iⱠÀð€€â± Ã€Ã€Ã€ð€€ð€€ð€€Ã€â± iiâ± ð€€Ã€â± Ã€Ã€ð€€iÀⱠÀⱠð€€Ã€ð€€|
+ ð€€â± ð€€â± â± â± â± â± â± â± iiâ± ð€€Ã€Ã€ð€€iÀⱠiⱠÀÀⱠÀð€€ið€€ð€€â± ð€€â± â± Ã€â± â± ð€€â± â± ð€€ð€€Ã€â± â± iÀÀÀÀÀiⱠÀð€€â± Ã€Ã€ð€€iÀið€€iâ± ð€€â± ð€€â± iið€€iâ± â± â± â± â± â± ið€€iÀÀð€€â± Ã€iÀⱠiÀð€€ð€€iið€€ð€€ð€€Ã€|
+ iâ± ið€€Ã€â± ið€€â± ð€€Ã€iiið€€â± iið€€â± iið€€ð€€â± ð€€â± Ã€Ã€iið€€â± â± ð€€ið€€ð€€â± iiⱠÀÀiⱠÀiⱠⱠÀⱠÀÀiÀið€€iâ± â± ð€€â± Ã€ð€€iⱠÀÀð€€ið€€ð€€Ã€iⱠⱠÀiÀiiiâ± â± â± ð€€Ã€ð€€Ã€Ã€iÀÀⱠÀⱠð€€Ã€â± |
+ ð€€ð€€â± ð€€â± Ã€Ã€ð€€iiÀið€€ð€€iiÀÀð€€ð€€ð€€iâ± ð€€Ã€ð€€iⱠⱠⱠÀⱠiÀÀiÀⱠiiiÀiÀÀⱠⱠⱠÀÀⱠⱠiÀiⱠⱠⱠⱠÀiÀⱠiÀð€€Ã€ð€€Ã€ð€€ð€€iiiâ± ð€€ð€€ð€€Ã€â± ð€€Ã€iÀÀiⱠÀÀⱠⱠÀⱠiiâ± ið€€ið€€|
+ iÀiiâ± iiiiⱠÀð€€Ã€Ã€Ã€iÀið€€iiiâ± ð€€ð€€â± Ã€iⱠÀⱠiⱠÀiⱠÀⱠiÀⱠÀⱠÀÀÀÀiÀⱠið€€â± iâ± ið€€â± ð€€Ã€ð€€ið€€ð€€â± iiÀⱠð€€â± Ã€â± â± â± iið€€ð€€iiiiiið€€Ã€ð€€iÀiiÀⱠÀⱠiâ± ið€€|
+ Àð€€ið€€â± Ã€iâ± ð€€â± Ã€â± ð€€ð€€â± â± iâ± iiiⱠÀⱠÀⱠⱠÀð€€ð€€â± ð€€ð€€ið€€â± Ã€ð€€iâ± â± iâ± iâ± ð€€â± iiið€€ð€€Ã€ð€€â± ð€€â± Ã€Ã€â± Ã€ð€€iÀⱠÀiⱠÀÀð€€â± iið€€â± iiiiⱠÀð€€Ã€ið€€ð€€â± iⱠÀÀð€€ð€€â± iⱠⱠÀÀ|
+ â± ð€€Ã€â± â± ð€€ð€€iâ± â± ð€€iÀÀiÀð€€â± Ã€ð€€ð€€ð€€ð€€iâ± ð€€Ã€ð€€â± â± ð€€â± ð€€ð€€iâ± iâ± â± ð€€â± â± Ã€Ã€â± â± Ã€Ã€â± ð€€ð€€â± Ã€Ã€iið€€ð€€ð€€Ã€Ã€â± ð€€ið€€â± ð€€iiiÀÀÀⱠiÀiÀð€€iið€€ð€€iâ± â± â± iið€€iiâ± â± ið€€Ã€Ã€ð€€i|
+ ð€€Ã€Ã€ð€€ð€€â± Ã€ð€€â± â± â± Ã€ð€€â± ð€€iið€€â± ð€€ð€€â± â± ð€€Ã€ð€€ð€€ð€€â± iâ± â± â± ð€€â± Ã€ið€€ð€€â± ð€€Ã€ið€€â± Ã€Ã€ið€€Ã€ð€€iâ± iâ± â± ð€€iiÀiⱠⱠÀð€€Ã€ð€€iiâ± â± â± â± ð€€Ã€Ã€â± â± â± iÀⱠð€€ið€€ið€€iiÀð€€ið€€â± iÀÀÀiÀ|
+ â± iið€€ið€€â± iÀiiÀÀÀð€€Ã€iið€€â± Ã€â± ið€€â± â± iâ± â± ið€€ið€€ð€€iâ± â± ð€€ð€€iâ± ð€€iâ± â± ð€€Ã€iiâ± iâ± iiið€€Ã€Ã€Ã€ið€€â± iÀⱠⱠⱠÀⱠⱠⱠⱠⱠⱠÀiiÀⱠið€€Ã€Ã€iÀⱠð€€Ã€iⱠⱠÀð€€ð€€iiÀð€€ð€€Ã€|
+ iâ± â± iâ± iiⱠÀÀⱠð€€iÀÀiÀð€€iiⱠÀð€€ið€€â± â± ð€€iâ± â± ð€€Ã€ð€€ð€€iiâ± â± â± ð€€â± iâ± ið€€iâ± ð€€â± â± Ã€iâ± ð€€ð€€â± ð€€â± ið€€iⱠⱠÀð€€Ã€ð€€Ã€â± â± ð€€Ã€â± â± ið€€â± ið€€iÀⱠÀð€€Ã€ð€€â± Ã€ð€€â± Ã€Ã€ið€€â± ð€€iiÀ|
+ â± â± â± ð€€â± iÀⱠⱠiiiiiiâ± ið€€ið€€â± Ã€ð€€ið€€ð€€â± â± Ã€â± ið€€Ã€Ã€Ã€Ã€â± ð€€â± â± ð€€ið€€iiÀð€€Ã€ið€€ð€€ið€€ið€€ð€€Ã€â± â± â± iið€€Ã€iiÀiâ± iâ± ð€€iiâ± â± â± â± ð€€ið€€iið€€iiÀÀð€€ð€€Ã€â± ð€€Ã€â± ð€€iÀð€€ð€€|
+ iⱠÀiâ± iið€€ð€€Ã€iâ± â± iiÀð€€Ã€Ã€ð€€ð€€â± Ã€â± ð€€iâ± iiâ± iiÀið€€â± â± â± iÀið€€ð€€Ã€â± Ã€Ã€â± ið€€iÀⱠÀⱠÀð€€ð€€Ã€ð€€ð€€Ã€ð€€â± iÀÀið€€iÀÀð€€Ã€â± â± â± ið€€iâ± â± ið€€iiⱠⱠⱠÀiÀð€€ð€€â± ð€€Ã€Ã€ð€€Ã€|
+ ÀiⱠÀÀⱠÀÀÀⱠⱠÀⱠiið€€ið€€ið€€iiâ± iÀiÀÀÀⱠⱠiâ± iiÀÀÀⱠÀⱠÀÀÀⱠiið€€â± ð€€â± ið€€Ã€â± â± iÀÀⱠið€€â± ð€€ð€€Ã€â± â± ð€€iâ± â± ð€€iÀiÀÀⱠÀÀð€€ið€€ð€€Ã€â± iÀⱠⱠð€€ð€€Ã€â± â± iⱠÀi|
+ ÀiⱠÀiiiÀⱠð€€ð€€iâ± ð€€ð€€iÀÀÀⱠÀⱠiÀiÀið€€â± ð€€Ã€ð€€iiâ± ð€€Ã€iÀⱠⱠð€€iiiâ± ð€€Ã€ið€€ð€€ð€€ð€€ð€€ð€€ð€€Ã€â± Ã€ð€€Ã€iÀð€€Ã€Ã€ð€€iâ± â± ð€€â± ð€€ið€€ð€€iiið€€ð€€ð€€ð€€â± â± ið€€iið€€ð€€â± â± â± ð€€Ã€iⱠÀⱠ|
+ Àð€€â± Ã€ð€€ð€€ð€€Ã€ð€€Ã€iÀⱠiiⱠⱠÀⱠⱠiⱠÀÀð€€ð€€ið€€ð€€ð€€â± iÀⱠÀÀð€€ð€€ð€€Ã€ð€€â± â± iÀiÀið€€â± iÀiiⱠÀð€€Ã€iiiâ± â± iâ± ð€€â± iÀð€€Ã€â± Ã€Ã€ið€€â± iâ± iiâ± iÀiiⱠÀⱠiiÀið€€â± ð€€ð€€iâ± i|
+ ÀÀð€€iÀÀÀð€€â± ð€€ð€€Ã€â± â± ð€€â± ð€€â± ð€€â± Ã€ð€€ið€€Ã€Ã€iÀÀð€€Ã€ð€€ð€€ð€€iÀiâ± iiÀⱠÀiâ± iið€€ð€€iÀiið€€â± ð€€â± Ã€â± iâ± iâ± ð€€Ã€â± Ã€ð€€ið€€iâ± â± ð€€â± â± â± Ã€Ã€Ã€iið€€â± ð€€ð€€ið€€ið€€ð€€iâ± ið€€Ã€ð€€ð€€^â±  |
+ |
+ ]=],
+ value = { col = 100, curscol = 100, endcol = 100, row = 50 },
+ },
+ },
+ {
+ ascii_results,
+ two_byte_results,
+ three_byte_results,
+ { -- random
+ screen = [=[
+ â± ð€€iið€€â± Ã€ð€€ið€€ð€€iÀÀÀiÀð€€â± ð€€â± iiâ± ð€€iiið€€Ã€â± Ã€â± â± Ã€iiÀⱠÀiâ± ið€€Ã€Ã€ð€€ð€€â± ð€€ð€€â± ð€€iÀⱠð€€ið€€Ã€Ã€â± iiÀð€€â± ð€€Ã€ð€€iið€€Ã€Ã€ð€€Ã€â± â± ð€€ð€€ð€€ð€€iið€€â± â± iâ± â± ð€€â± Ã€ð€€Ã€Ã€iiâ± |
+ iiâ± ð€€iÀÀiⱠⱠÀið€€â± â± Ã€ð€€ð€€Ã€iiiiÀiâ± ð€€iⱠÀiâ± iⱠⱠÀiÀð€€â± iiⱠⱠÀð€€Ã€iið€€â± Ã€â± iⱠÀⱠÀⱠiið€€Ã€ið€€â± â± ð€€Ã€Ã€Ã€ið€€Ã€Ã€Ã€ð€€iâ± ð€€iⱠÀð€€iâ± ið€€Ã€iÀð€€â± â± iÀð€€ð€€â± i|
+ iÀiiiⱠÀÀð€€â± â± â± ið€€Ã€ð€€ð€€iiiÀÀiiÀⱠÀð€€Ã€ð€€â± â± ð€€ð€€â± â± â± ið€€iiÀⱠð€€â± â± â± Ã€iâ± iâ± iÀÀÀið€€iâ± ð€€Ã€Ã€iâ± ð€€iÀÀið€€ið€€ð€€Ã€iÀⱠð€€ð€€iâ± ð€€Ã€Ã€iÀÀⱠð€€ð€€â± â± ð€€ð€€ð€€ð€€â± ð€€ð€€|
+ ÀⱠiâ± iÀð€€ið€€â± â± iⱠⱠÀð€€Ã€Ã€Ã€Ã€ð€€ð€€Ã€â± â± ð€€â± Ã€Ã€iâ± ð€€ið€€â± ð€€Ã€â± ið€€â± Ã€â± Ã€ð€€â± â± ð€€ið€€iⱠÀið€€ið€€ð€€Ã€ð€€iÀiâ± â± â± ð€€Ã€iÀⱠÀð€€Ã€Ã€Ã€ið€€ð€€ð€€â± Ã€ið€€ð€€Ã€ð€€Ã€ð€€ð€€iiâ± iÀið€€ið€€â± |
+ â± ð€€ið€€ð€€Ã€iÀⱠⱠⱠⱠⱠÀÀⱠⱠÀⱠð€€iið€€Ã€â± iâ± iiið€€ið€€ið€€ð€€ð€€Ã€ð€€iið€€iÀiiiÀÀⱠiiiâ± iiⱠÀð€€Ã€ð€€ð€€Ã€â± ð€€iÀÀiiÀiÀð€€iâ± ið€€ð€€Ã€ð€€Ã€iiâ± ð€€iÀð€€ð€€iⱠⱠÀÀⱠⱠiiÀ|
+ ð€€Ã€iⱠⱠÀð€€ð€€ð€€ið€€ið€€ið€€â± Ã€ð€€Ã€iiÀⱠð€€Ã€Ã€Ã€ið€€â± Ã€iÀⱠið€€â± Ã€iiÀÀÀiiiÀiâ± â± iÀð€€â± â± ð€€iÀⱠÀⱠⱠiÀÀⱠÀⱠÀÀiið€€â± ið€€iiÀÀÀiâ± ð€€ið€€ð€€ið€€iiÀð€€ð€€ð€€â± Ã€iâ± ð€€|
+ ið€€Ã€â± iâ± ið€€â± iâ± ð€€â± ið€€â± Ã€ð€€ð€€ð€€â± Ã€iiiiið€€â± ð€€iiiÀiiÀð€€ð€€ð€€Ã€ð€€ð€€â± ð€€â± Ã€ð€€â± â± â± iÀÀÀÀiið€€ið€€Ã€iiⱠÀiÀð€€iâ± â± iÀⱠiið€€ið€€â± ð€€ð€€iⱠⱠÀð€€â± iiiⱠⱠÀÀð€€iÀⱠ|
+ â± ð€€ð€€â± â± ð€€Ã€ð€€Ã€â± ð€€Ã€â± Ã€ð€€ð€€iⱠⱠÀÀiÀⱠð€€Ã€iÀⱠið€€â± Ã€ð€€ð€€ð€€ð€€â± ð€€iⱠÀð€€iÀð€€iÀð€€iÀÀⱠið€€iÀⱠið€€â± iiⱠÀð€€Ã€ð€€â± â± Ã€Ã€ið€€â± â± ð€€iiⱠÀiâ± ð€€ð€€ð€€ð€€â± â± â± Ã€â± iÀⱠiÀÀð€€Ã€|
+ ÀⱠÀÀð€€ið€€iⱠÀÀÀⱠð€€ð€€Ã€â± Ã€Ã€iiið€€ð€€iiÀiiⱠÀÀⱠiÀiÀÀð€€ið€€ið€€â± iâ± â± iⱠÀiiÀⱠð€€â± â± Ã€iÀⱠð€€ð€€iÀð€€â± ð€€iÀð€€â± Ã€Ã€â± Ã€Ã€Ã€ð€€ð€€ið€€ð€€Ã€ð€€ð€€iið€€Ã€ð€€ð€€â± Ã€ð€€â± â± â± ð€€ð€€|
+ ÀÀÀÀiâ± iâ± â± â± iâ± ð€€â± Ã€Ã€Ã€ð€€Ã€Ã€iⱠÀð€€Ã€iⱠÀⱠÀⱠⱠÀÀⱠiÀⱠⱠiiⱠÀð€€â± â± Ã€iâ± ð€€iÀⱠð€€â± ð€€â± ð€€iⱠÀⱠið€€ð€€â± ð€€iÀð€€Ã€â± ð€€Ã€Ã€â± ð€€â± ið€€iⱠÀð€€ð€€ð€€ð€€ið€€ið€€ð€€ð€€Ã€â± iÀÀð€€i|
+ ð€€ð€€iiÀð€€Ã€â± ð€€ð€€ð€€ð€€ð€€Ã€iiið€€ð€€ð€€â± ð€€ð€€ið€€Ã€Ã€ð€€iiÀiiiiÀð€€iâ± iâ± iÀⱠÀⱠÀiⱠⱠⱠⱠⱠⱠⱠⱠⱠÀiiâ± iÀⱠÀð€€iiⱠÀⱠiⱠⱠÀiâ± ð€€iâ± ð€€iiⱠÀð€€ð€€Ã€iið€€ið€€Ã€â± Ã€Ã€iÀÀ|
+ ð€€ð€€ð€€ið€€iÀð€€ð€€iÀð€€Ã€ið€€ð€€â± â± ð€€â± Ã€ið€€ð€€Ã€Ã€iiiâ± iâ± ð€€iⱠÀⱠÀð€€â± Ã€ð€€â± iiiiÀiⱠÀiiiⱠⱠÀð€€â± ð€€ð€€ð€€Ã€â± iÀⱠiiiiâ± iâ± ð€€â± ð€€Ã€â± Ã€iið€€ið€€â± ð€€Ã€ð€€iâ± â± ð€€iâ± iiiið€€|
+ iⱠÀÀⱠÀÀð€€ð€€ð€€iiiÀð€€Ã€ð€€iÀÀið€€Ã€ð€€Ã€â± Ã€iÀiið€€â± â± iið€€â± â± ð€€ð€€Ã€â± ð€€Ã€Ã€ð€€Ã€Ã€Ã€Ã€ið€€Ã€â± ð€€Ã€ð€€Ã€iiâ± ð€€Ã€Ã€â± iâ± ð€€â± ð€€Ã€Ã€ð€€â± â± ð€€â± â± Ã€ð€€â± â± â± ð€€iiÀⱠÀⱠiâ± ið€€iið€€Ã€i|
+ â± ð€€â± Ã€ð€€â± ið€€iÀð€€â± ð€€ð€€iÀiÀð€€iâ± ið€€â± Ã€iâ± â± iÀð€€iâ± iÀⱠið€€ð€€iâ± iâ± â± ð€€Ã€Ã€ið€€iÀⱠⱠð€€â± Ã€ð€€ð€€ð€€â± â± iÀÀiâ± â± â± ð€€ð€€â± â± â± â± Ã€iâ± ð€€Ã€ið€€iÀⱠiið€€Ã€â± iið€€â± ð€€Ã€â± Ã€ð€€â± i|
+ ð€€â± â± â± â± â± ð€€â± ð€€Ã€Ã€ð€€ð€€iÀÀⱠiÀiiⱠÀiâ± ð€€ð€€Ã€Ã€iÀⱠð€€Ã€Ã€â± ð€€Ã€ð€€Ã€ð€€iⱠⱠÀiⱠÀiiiⱠÀiÀÀÀð€€iⱠⱠⱠÀÀiâ± â± â± ð€€iið€€iið€€iâ± â± iið€€iⱠÀið€€ð€€ð€€iið€€Ã€â± â± iⱠÀð€€â± â± |
+ ð€€iâ± ð€€â± â± â± Ã€Ã€ð€€iiiÀÀⱠiið€€ið€€Ã€Ã€â± ð€€â± â± iâ± â± â± iâ± ð€€ið€€Ã€ð€€â± â± â± ið€€Ã€ið€€â± Ã€ð€€Ã€â± iiiiâ± iiâ± â± ið€€ð€€Ã€â± ð€€â± iÀÀð€€iiiⱠÀiâ± ið€€Ã€ð€€ð€€ið€€ð€€iiâ± ð€€Ã€ð€€iiⱠⱠÀð€€iâ± |
+ ⱠⱠÀÀⱠⱠð€€iÀⱠð€€iⱠⱠÀÀð€€Ã€iâ± ð€€iÀⱠⱠⱠð€€ð€€Ã€ð€€iið€€ð€€Ã€ð€€ð€€Ã€â± â± â± Ã€â± iiâ± ð€€ð€€iið€€â± â± Ã€â± iâ± ið€€â± â± ð€€ið€€ð€€ð€€ð€€â± ð€€iÀiâ± â± ð€€Ã€ð€€Ã€â± â± â± Ã€Ã€ð€€ð€€iÀⱠið€€ð€€Ã€iⱠⱠÀÀiÀÀ|
+ ð€€â± Ã€iÀð€€â± â± ð€€ið€€â± â± ð€€ð€€ð€€ð€€ð€€ð€€iⱠÀⱠⱠiiÀⱠð€€ð€€ið€€â± â± ð€€â± â± â± ð€€ð€€iÀiÀⱠð€€Ã€ð€€Ã€ð€€ð€€â± iiiâ± iiiâ± iâ± ð€€Ã€iiiâ± ð€€Ã€ð€€Ã€â± â± Ã€ð€€Ã€ð€€ð€€ð€€â± iâ± ið€€â± Ã€Ã€â± iiâ± â± â± â± ð€€Ã€â± ð€€ð€€|
+ â± ð€€iÀÀⱠð€€â± â± Ã€â± Ã€ð€€â± â± Ã€iiÀÀÀⱠð€€ið€€â± ð€€â± Ã€ð€€ð€€iâ± â± â± â± iiⱠⱠⱠÀiⱠÀiiⱠÀð€€â± ð€€â± ið€€ð€€â± Ã€ð€€Ã€â± â± ð€€Ã€â± Ã€â± ð€€â± ð€€iâ± ið€€Ã€â± â± iið€€Ã€â± Ã€ð€€â± ð€€Ã€ið€€Ã€ð€€Ã€Ã€â± iâ± â± iið€€|
+ ÀⱠⱠⱠÀⱠⱠiið€€Ã€ið€€â± ið€€ið€€ið€€â± ð€€Ã€Ã€Ã€iÀÀið€€Ã€Ã€Ã€ð€€ið€€iÀð€€ð€€â± iÀið€€ð€€ð€€â± Ã€iÀð€€ð€€iÀÀⱠⱠð€€â± â± â± â± Ã€Ã€Ã€Ã€iiÀð€€iiâ± â± â± ið€€â± Ã€ið€€Ã€â± â± Ã€ð€€â± iiâ± ð€€ð€€ið€€â± ið€€ð€€Ã€|
+ ÀⱠiiÀið€€â± Ã€Ã€iÀⱠið€€Ã€â± â± ð€€â± iÀiiâ± iiâ± â± ð€€iið€€ið€€ð€€ð€€ð€€ið€€â± â± Ã€â± Ã€Ã€iÀÀÀⱠÀⱠⱠÀÀⱠð€€Ã€Ã€ð€€Ã€Ã€â± Ã€ð€€ð€€Ã€iâ± ð€€â± â± ð€€iÀð€€â± ð€€iÀⱠⱠð€€iÀiiiið€€iið€€ð€€â± â± â± ð€€â± |
+ ð€€Ã€iÀⱠÀiiÀÀiiâ± â± â± ið€€Ã€Ã€iâ± ð€€iⱠⱠÀð€€ð€€ð€€Ã€â± â± Ã€ð€€â± Ã€Ã€â± ð€€Ã€Ã€ð€€ð€€â± ð€€Ã€Ã€ð€€Ã€â± ð€€â± Ã€iÀð€€iâ± ð€€â± â± ð€€ð€€Ã€ð€€iiið€€iiⱠÀⱠiⱠÀⱠð€€â± ð€€ið€€ð€€Ã€â± â± ið€€ð€€â± â± ð€€ð€€ð€€ð€€Ã€ð€€â± ð€€|
+ ð€€iiÀⱠiâ± iÀⱠð€€ið€€iiið€€â± ð€€ið€€iÀÀið€€â± iið€€Ã€iÀiiiÀⱠÀð€€Ã€Ã€â± ð€€â± ð€€iiÀið€€ið€€ð€€ið€€â± iiiÀⱠⱠⱠiiÀð€€Ã€ð€€ð€€iÀð€€iⱠÀⱠÀÀið€€â± iÀⱠÀð€€ð€€iÀÀð€€ið€€ð€€Ã€Ã€â± ð€€|
+ ÀiÀⱠⱠⱠⱠiið€€Ã€Ã€ð€€ð€€ð€€â± ið€€Ã€ð€€Ã€â± iiÀið€€â± iið€€iÀÀð€€â± iâ± ð€€â± iiiⱠÀÀiÀÀÀÀð€€â± â± iið€€Ã€ð€€Ã€iÀið€€Ã€Ã€ið€€iâ± iÀið€€Ã€iÀið€€Ã€iÀⱠð€€ið€€â± ið€€ð€€ð€€â± â± ð€€â± Ã€â± Ã€â± i|
+ ið€€â± iÀⱠⱠÀÀð€€ð€€iið€€Ã€Ã€ð€€iÀiÀⱠÀiiiið€€Ã€iÀⱠið€€ið€€ð€€ið€€ð€€iâ± ð€€iÀið€€Ã€Ã€Ã€Ã€iâ± iÀⱠÀÀⱠiiÀÀⱠⱠið€€iâ± iiâ± ið€€â± ð€€ð€€Ã€â± â± Ã€â± iⱠⱠÀð€€iiÀⱠⱠⱠð€€ð€€â± ið€€â± i|
+ iið€€iÀÀÀÀÀÀiÀð€€Ã€ð€€iiâ± iâ± â± ið€€Ã€ð€€Ã€â± Ã€ð€€â± â± ð€€ð€€ð€€iâ± â± iiⱠÀÀⱠÀiiⱠÀⱠⱠÀð€€ð€€â± ð€€Ã€Ã€Ã€Ã€â± ð€€ð€€ð€€â± â± Ã€â± ð€€Ã€iâ± iÀⱠiÀÀð€€iið€€iiiÀⱠÀⱠⱠð€€â± Ã€iÀÀð€€â± â± â± Ã€|
+ ð€€ð€€Ã€ð€€ð€€iÀⱠð€€â± iⱠÀÀð€€iÀÀð€€Ã€ð€€iÀÀⱠⱠÀiiið€€Ã€ð€€Ã€â± Ã€â± â± Ã€â± â± ið€€Ã€Ã€Ã€ið€€Ã€ð€€â± iÀið€€ið€€ið€€Ã€iÀÀiÀÀð€€ð€€Ã€ð€€â± Ã€ð€€â± Ã€â± ð€€â± iÀð€€ð€€Ã€iÀÀð€€ð€€ð€€Ã€ð€€â± ið€€ið€€ið€€Ã€i|
+ ð€€ð€€iâ± ð€€ið€€Ã€â± â± Ã€ð€€iÀð€€Ã€iâ± â± ið€€iiⱠÀð€€Ã€iiÀⱠð€€â± ð€€Ã€Ã€iÀiâ± ið€€Ã€ð€€ð€€iÀiÀiâ± ið€€â± â± â± ið€€Ã€ð€€Ã€â± â± ð€€â± ð€€Ã€Ã€â± iÀiÀð€€â± ð€€Ã€â± iⱠⱠÀÀÀið€€ið€€â± ið€€Ã€ð€€iið€€â± Ã€ð€€â± |
+ â± iâ± ð€€iÀⱠⱠð€€ið€€Ã€ð€€iÀÀð€€ð€€Ã€â± â± Ã€â± Ã€ð€€iiiÀð€€ið€€iÀð€€â± â± ð€€iÀⱠð€€â± Ã€ið€€iiiið€€iâ± â± ð€€Ã€iÀð€€Ã€iið€€â± ð€€ð€€â± iÀiið€€ð€€â± ð€€ð€€â± iâ± ð€€iâ± iâ± ið€€iiiâ± â± â± ið€€iiÀið€€â± |
+ ið€€ið€€Ã€Ã€Ã€ð€€Ã€iÀⱠiÀiiⱠÀÀÀiÀiiiið€€ið€€Ã€Ã€iiiⱠÀiÀⱠÀiâ± ð€€iiâ± iâ± â± iÀið€€â± â± ð€€Ã€â± iâ± ð€€â± Ã€iiⱠÀð€€Ã€â± â± ð€€â± iÀið€€Ã€ð€€ð€€iiÀð€€ð€€Ã€iâ± â± iâ± ð€€Ã€â± iÀÀⱠð€€i|
+ Àið€€ð€€ð€€iÀið€€Ã€ið€€Ã€ð€€â± â± ð€€â± Ã€iiÀⱠð€€ið€€ið€€ð€€â± iⱠÀð€€ð€€â± ð€€iÀð€€Ã€Ã€â± iâ± â± iÀð€€iÀð€€â± iÀÀÀÀⱠiiÀð€€ð€€Ã€â± â± iÀð€€iiÀð€€Ã€ð€€iÀiÀÀð€€iÀiÀÀiiÀð€€Ã€â± â± Ã€iiÀÀⱠ|
+ ð€€â± Ã€â± iⱠⱠÀð€€Ã€iiÀð€€iÀⱠⱠⱠⱠiÀÀið€€iÀið€€iiiâ± ð€€iâ± ð€€ð€€ð€€ð€€Ã€Ã€Ã€â± ið€€iâ± ið€€â± Ã€â± â± ð€€ð€€Ã€ð€€iiÀⱠð€€ð€€â± â± ð€€ð€€Ã€iⱠÀÀÀⱠð€€ð€€Ã€iâ± ð€€ð€€iÀÀiÀð€€â± Ã€ið€€ð€€â± â± â± â± ð€€â± i|
+ iÀið€€â± â± Ã€ð€€ð€€ið€€Ã€iið€€Ã€iÀÀiÀiÀÀð€€Ã€Ã€ð€€Ã€ð€€â± â± â± Ã€Ã€Ã€â± iið€€â± Ã€Ã€â± â± ið€€â± â± iâ± â± ð€€â± ð€€Ã€iÀiiiið€€Ã€iⱠÀiiiiâ± â± iiⱠÀÀÀⱠÀⱠð€€ð€€ð€€iiâ± â± ð€€â± Ã€â± ð€€iâ± â± ð€€ð€€â± |
+ Àð€€Ã€ð€€â± â± â± iÀð€€Ã€â± Ã€â± â± iiâ± iið€€â± Ã€Ã€Ã€ð€€iâ± iiiiiÀð€€Ã€Ã€iÀÀⱠð€€ð€€iiâ± ið€€ð€€Ã€ið€€â± Ã€Ã€iâ± â± â± â± ð€€iâ± iⱠⱠⱠⱠⱠÀÀⱠiiÀiâ± ð€€iÀiiâ± iiiið€€iið€€Ã€ð€€â± Ã€ð€€â± ð€€Ã€â± |
+ ÀⱠÀiiiiâ± iiâ± iÀið€€ð€€â± Ã€Ã€ð€€Ã€ið€€Ã€ið€€Ã€iⱠÀð€€â± â± â± â± ð€€â± iÀð€€iⱠⱠÀⱠið€€Ã€ið€€â± iiâ± ð€€â± iið€€Ã€Ã€Ã€â± ð€€Ã€Ã€Ã€â± Ã€iÀⱠiâ± iâ± ið€€ð€€Ã€ð€€ð€€ð€€Ã€â± iⱠⱠⱠⱠÀiiÀⱠð€€Ã€ð€€ð€€Ã€|
+ iÀð€€Ã€â± â± Ã€iÀið€€Ã€ið€€Ã€iⱠⱠÀð€€iⱠÀð€€ið€€Ã€iiÀÀÀⱠÀÀⱠð€€Ã€ð€€Ã€ð€€Ã€Ã€Ã€Ã€â± ið€€iⱠÀð€€ð€€Ã€â± iÀiâ± â± iÀð€€â± â± Ã€ð€€ð€€â± ð€€Ã€Ã€ð€€â± â± Ã€Ã€iÀið€€ð€€ð€€Ã€ð€€Ã€â± ð€€iâ± â± ð€€ð€€ð€€ið€€â± Ã€ð€€â± |
+ â± ið€€Ã€Ã€ð€€â± Ã€iÀið€€ið€€Ã€â± ð€€â± ð€€Ã€â± ð€€â± Ã€â± â± â± ð€€ð€€Ã€iiiiâ± â± ið€€â± Ã€â± Ã€ð€€â± ð€€ið€€Ã€ð€€ð€€ð€€â± ð€€Ã€iÀÀⱠⱠiiâ± iÀiⱠⱠÀiÀÀⱠⱠÀÀⱠÀð€€â± iâ± ð€€ð€€ið€€ið€€ð€€Ã€â± Ã€â± â± â± Ã€Ã€iiÀð€€|
+ â± â± â± iiÀⱠⱠiÀⱠð€€Ã€iⱠⱠÀⱠiÀⱠⱠÀÀið€€Ã€Ã€iÀð€€ð€€ið€€ið€€iiÀÀiâ± ð€€â± ð€€ð€€ð€€Ã€iiâ± ð€€Ã€ið€€iiiiÀiâ± â± iið€€â± ið€€iâ± â± ð€€Ã€Ã€â± ð€€iÀⱠⱠⱠiÀð€€ð€€iÀⱠiⱠÀð€€Ã€â± Ã€iâ± ð€€Ã€|
+ ð€€â± â± â± iâ± â± iiiið€€ð€€ið€€Ã€iiiið€€Ã€ð€€â± ið€€iâ± ð€€â± iÀiÀⱠið€€ð€€Ã€iÀiiÀÀÀð€€ð€€ið€€Ã€ð€€Ã€â± Ã€iiÀⱠð€€â± â± ð€€ð€€â± ð€€Ã€Ã€iÀð€€iâ± ð€€ð€€iÀÀⱠið€€iâ± iÀð€€â± â± ð€€Ã€Ã€â± iÀð€€Ã€â± â± Ã€â± |
+ â± iið€€ð€€â± Ã€iⱠⱠÀÀð€€Ã€Ã€Ã€Ã€Ã€Ã€Ã€â± iⱠⱠÀÀið€€Ã€iⱠÀð€€ð€€ið€€â± Ã€iið€€â± ð€€ð€€Ã€ð€€ð€€Ã€iÀð€€ið€€ð€€â± Ã€iÀÀⱠiiâ± â± iⱠÀiÀⱠÀið€€iÀð€€Ã€ð€€ð€€â± â± ið€€â± Ã€iÀÀÀⱠÀiÀÀⱠiâ± ð€€iÀ|
+ ð€€Ã€â± iÀⱠⱠⱠÀÀⱠÀⱠð€€iiiiÀiÀÀⱠð€€â± iiið€€ð€€iiâ± iÀð€€ð€€ið€€Ã€iiÀⱠð€€ð€€â± ð€€â± ð€€â± iið€€â± iⱠÀiⱠⱠÀÀÀⱠÀð€€â± ð€€ð€€ð€€Ã€ð€€â± ð€€â± ð€€â± Ã€ð€€â± â± iâ± ð€€ð€€Ã€iiiÀð€€Ã€iÀiⱠÀð€€Ã€|
+ ið€€â± iâ± ið€€iið€€ð€€iiiⱠⱠÀÀiiiið€€Ã€iⱠⱠÀið€€Ã€Ã€Ã€Ã€iÀiiâ± ð€€Ã€â± iâ± â± iÀⱠð€€Ã€â± â± ð€€Ã€Ã€Ã€ð€€â± Ã€ð€€Ã€ð€€iâ± ið€€iÀÀið€€iÀÀiâ± â± ð€€â± iÀÀiÀð€€iâ± ð€€â± Ã€â± Ã€iið€€ð€€â± â± ið€€|
+ iâ± ð€€Ã€ð€€ð€€Ã€ið€€Ã€â± ð€€â± ð€€ð€€â± Ã€ð€€â± â± â± iÀð€€Ã€iⱠⱠⱠÀⱠÀⱠiÀⱠið€€Ã€Ã€Ã€â± Ã€iÀⱠÀÀÀiiið€€ð€€Ã€iiⱠÀið€€iÀð€€Ã€ð€€Ã€iiÀÀÀiÀiÀÀið€€iiiiÀð€€Ã€â± â± iiâ± ið€€iiâ± ð€€Ã€ð€€ð€€|
+ ⱠⱠÀÀiâ± ð€€iâ± iÀÀⱠⱠið€€â± Ã€Ã€iâ± ð€€â± â± Ã€Ã€Ã€iið€€ð€€iiâ± ð€€iâ± ð€€iâ± â± ð€€Ã€ið€€iiÀÀⱠⱠð€€â± ð€€ð€€ð€€ið€€Ã€Ã€ið€€ð€€â± iÀið€€iÀiiⱠⱠÀⱠⱠiⱠÀiⱠⱠⱠÀÀÀð€€â± Ã€ð€€â± Ã€â± â± iÀÀⱠð€€|
+ Àiið€€ið€€iⱠÀÀⱠⱠÀiið€€â± â± iÀiÀiⱠÀiâ± ð€€â± ið€€ð€€ð€€Ã€ð€€ð€€ð€€ð€€ð€€iâ± ð€€â± â± ið€€ið€€iâ± ð€€â± â± Ã€â± ð€€iâ± â± â± iâ± â± ð€€â± â± â± â± ð€€â± Ã€Ã€â± â± â± â± Ã€ð€€â± Ã€â± Ã€iiÀiÀiÀⱠið€€ð€€ð€€ð€€Ã€ð€€ð€€ð€€Ã€|
+ â± iÀiâ± ið€€ð€€Ã€iâ± iⱠÀð€€iÀiið€€â± Ã€ð€€ð€€â± Ã€iÀÀð€€â± Ã€Ã€â± ð€€iÀiâ± ð€€ð€€â± ð€€â± â± â± Ã€ð€€iÀⱠiⱠÀÀð€€â± Ã€â± â± â± â± Ã€ð€€ð€€Ã€ð€€â± ð€€Ã€ð€€iâ± ið€€ið€€â± ið€€â± ð€€ð€€iiiâ± iâ± ð€€Ã€ð€€â± Ã€ð€€ð€€iÀÀi|
+ â± ið€€Ã€Ã€iÀið€€iⱠÀð€€ð€€â± iⱠÀⱠÀð€€iÀÀÀⱠð€€ð€€iÀÀiâ± ð€€iið€€ið€€ð€€iiiⱠⱠⱠÀÀiⱠÀð€€ið€€Ã€iⱠÀÀⱠⱠið€€â± Ã€ð€€Ã€ð€€iiâ± â± ð€€ð€€iÀⱠÀið€€Ã€ð€€ð€€iÀð€€iið€€ð€€Ã€ð€€iÀð€€ð€€iÀið€€|
+ iⱠÀiiiâ± ð€€â± iÀⱠⱠⱠⱠð€€Ã€ð€€â± â± ð€€â± â± ið€€ð€€ð€€â± Ã€Ã€ð€€ð€€â± ð€€iÀð€€â± iⱠÀð€€â± â± iÀið€€Ã€iÀⱠⱠÀð€€ð€€iiÀⱠð€€â± â± ið€€ð€€Ã€â± Ã€iâ± â± iÀÀð€€iÀÀÀð€€ð€€Ã€â± iið€€Ã€iiÀⱠÀⱠÀið€€ð€€iâ± |
+ iÀð€€â± Ã€ið€€iâ± â± iið€€â± Ã€ð€€Ã€ið€€ð€€iâ± ð€€iÀið€€Ã€ð€€iÀÀiÀð€€Ã€Ã€iiiÀⱠⱠið€€â± iiiâ± ið€€iÀÀð€€ð€€â± â± â± Ã€iiⱠÀⱠÀⱠiâ± ið€€â± Ã€Ã€ð€€â± ð€€ið€€â± Ã€Ã€ð€€iÀð€€â± ð€€iÀð€€â± ð€€â± Ã€â± Ã€Ã€ð€€|
+ ⱠÀð€€ð€€Ã€iÀiâ± iâ± â± ið€€ð€€ð€€Ã€â± â± ið€€Ã€ð€€ið€€ð€€ð€€ð€€iiÀÀÀÀð€€â± ð€€iið€€ið€€iÀið€€â± â± ð€€iÀð€€ð€€ð€€â± â± â± ð€€ð€€ð€€ð€€ið€€ð€€â± iâ± ð€€ið€€iâ± ið€€ið€€Ã€â± ð€€iâ± â± â± ð€€Ã€ð€€ð€€iiâ± ið€€Ã€Ã€Ã€iii^ð€€ |
+ |
+ ]=],
+ value = { col = 100, curscol = 100, endcol = 100, row = 50 },
+ },
+ },
+ {
+ ascii_results,
+ two_byte_results,
+ three_byte_results,
+ { -- random
+ screen = [=[
+ â± ð€€iið€€â± Ã€ð€€ið€€ð€€iÀÀÀiÀð€€â± ð€€â± iiâ± ð€€iiið€€Ã€â± Ã€â± â± Ã€iiÀⱠÀiâ± ið€€Ã€Ã€ð€€ð€€â± ð€€ð€€â± ð€€iÀⱠð€€ið€€Ã€Ã€â± iiÀð€€â± ð€€Ã€ð€€iið€€Ã€Ã€ð€€Ã€â± â± ð€€ð€€ð€€ð€€iið€€â± â± iâ± â± ð€€â± Ã€ð€€Ã€Ã€iiâ± |
+ ð€€ð€€Ã€â± Ã€ð€€ð€€iⱠÀð€€ð€€ið€€ð€€ð€€ð€€â± â± â± iiiiÀÀð€€â± Ã€â± Ã€ið€€ið€€â± â± Ã€iÀⱠið€€ð€€Ã€ð€€iÀð€€Ã€Ã€Ã€ð€€ð€€iÀⱠð€€ð€€â± ð€€ð€€Ã€iâ± iiⱠⱠÀÀÀÀið€€Ã€Ã€â± ð€€Ã€iiið€€iâ± â± â± ið€€â± Ã€ið€€iâ± ð€€â± iâ± |
+ iiâ± ð€€iÀÀiⱠⱠÀið€€â± â± Ã€ð€€ð€€Ã€iiiiÀiâ± ð€€iⱠÀiâ± iⱠⱠÀiÀð€€â± iiⱠⱠÀð€€Ã€iið€€â± Ã€â± iⱠÀⱠÀⱠiið€€Ã€ið€€â± â± ð€€Ã€Ã€Ã€ið€€Ã€Ã€Ã€ð€€iâ± ð€€iⱠÀð€€iâ± ið€€Ã€iÀð€€â± â± iÀð€€ð€€â± i|
+ Àð€€ð€€iÀiÀÀÀÀⱠⱠⱠð€€iÀÀiâ± ð€€Ã€ð€€â± Ã€iiâ± ð€€iiâ± â± ð€€iÀiⱠⱠÀⱠÀð€€Ã€ið€€iâ± ð€€ð€€iiⱠÀⱠiÀÀÀiÀiiÀð€€ið€€Ã€Ã€â± ð€€ð€€ð€€ið€€ð€€â± â± ið€€Ã€ð€€iâ± ið€€â± â± iiiÀⱠð€€â± Ã€iÀiâ± â± |
+ iÀiiiⱠÀÀð€€â± â± â± ið€€Ã€ð€€ð€€iiiÀÀiiÀⱠÀð€€Ã€ð€€â± â± ð€€ð€€â± â± â± ið€€iiÀⱠð€€â± â± â± Ã€iâ± iâ± iÀÀÀið€€iâ± ð€€Ã€Ã€iâ± ð€€iÀÀið€€ið€€ð€€Ã€iÀⱠð€€ð€€iâ± ð€€Ã€Ã€iÀÀⱠð€€ð€€â± â± ð€€ð€€ð€€ð€€â± ð€€ð€€|
+ ð€€Ã€Ã€â± Ã€ð€€Ã€Ã€iÀÀÀⱠiiâ± iiÀⱠÀiⱠÀiÀiâ± â± ð€€Ã€Ã€Ã€â± iiÀⱠð€€iÀið€€â± â± ð€€ð€€Ã€Ã€ð€€Ã€iÀÀⱠið€€iÀⱠð€€Ã€ð€€â± â± Ã€ð€€â± iiið€€â± iiâ± iÀⱠⱠiⱠÀⱠð€€â± Ã€Ã€â± ð€€Ã€ð€€Ã€iÀÀⱠⱠÀÀ|
+ ÀⱠiâ± iÀð€€ið€€â± â± iⱠⱠÀð€€Ã€Ã€Ã€Ã€ð€€ð€€Ã€â± â± ð€€â± Ã€Ã€iâ± ð€€ið€€â± ð€€Ã€â± ið€€â± Ã€â± Ã€ð€€â± â± ð€€ið€€iⱠÀið€€ið€€ð€€Ã€ð€€iÀiâ± â± â± ð€€Ã€iÀⱠÀð€€Ã€Ã€Ã€ið€€ð€€ð€€â± Ã€ið€€ð€€Ã€ð€€Ã€ð€€ð€€iiâ± iÀið€€ið€€â± |
+ ð€€ð€€ið€€Ã€â± â± ð€€ð€€ð€€iâ± â± ð€€Ã€ð€€Ã€â± iÀð€€ð€€â± Ã€ið€€ð€€iiiâ± ð€€ð€€iⱠÀÀð€€â± iiÀⱠⱠÀð€€ð€€â± Ã€â± â± Ã€iⱠⱠÀⱠÀⱠiâ± â± ð€€ð€€ð€€iâ± â± â± iâ± â± iið€€Ã€â± ið€€Ã€Ã€â± â± ið€€Ã€ð€€â± ð€€Ã€Ã€ð€€â± ð€€iâ± iiâ± â± |
+ â± ð€€ið€€ð€€Ã€iÀⱠⱠⱠⱠⱠÀÀⱠⱠÀⱠð€€iið€€Ã€â± iâ± iiið€€ið€€ið€€ð€€ð€€Ã€ð€€iið€€iÀiiiÀÀⱠiiiâ± iiⱠÀð€€Ã€ð€€ð€€Ã€â± ð€€iÀÀiiÀiÀð€€iâ± ið€€ð€€Ã€ð€€Ã€iiâ± ð€€iÀð€€ð€€iⱠⱠÀÀⱠⱠiiÀ|
+ ið€€ð€€ð€€Ã€Ã€ið€€â± â± â± â± â± Ã€iiÀð€€ð€€iið€€â± ð€€Ã€ið€€iâ± iÀÀⱠÀð€€Ã€â± iⱠÀið€€ð€€iiâ± ð€€ið€€â± Ã€iâ± iið€€ð€€Ã€ð€€ð€€â± â± Ã€â± iÀiⱠÀÀið€€ið€€â± Ã€iâ± â± â± ð€€ð€€Ã€iⱠⱠⱠÀÀið€€Ã€â± â± Ã€iâ± ð€€â± Ã€|
+ ð€€Ã€iⱠⱠÀð€€ð€€ð€€ið€€ið€€ið€€â± Ã€ð€€Ã€iiÀⱠð€€Ã€Ã€Ã€ið€€â± Ã€iÀⱠið€€â± Ã€iiÀÀÀiiiÀiâ± â± iÀð€€â± â± ð€€iÀⱠÀⱠⱠiÀÀⱠÀⱠÀÀiið€€â± ið€€iiÀÀÀiâ± ð€€ið€€ð€€ið€€iiÀð€€ð€€ð€€â± Ã€iâ± ð€€|
+ Àð€€â± â± â± â± ð€€Ã€iâ± â± iÀð€€ið€€Ã€â± Ã€â± iiÀiÀÀiâ± ð€€ð€€ð€€â± ð€€Ã€â± ið€€ð€€iâ± â± â± iiⱠÀið€€ð€€ð€€iⱠÀÀÀⱠið€€Ã€ð€€iiiⱠÀⱠiÀð€€iâ± ð€€iið€€ð€€ð€€Ã€â± â± Ã€Ã€â± â± â± â± iÀið€€Ã€iiið€€iið€€ð€€Ã€|
+ ið€€Ã€â± iâ± ið€€â± iâ± ð€€â± ið€€â± Ã€ð€€ð€€ð€€â± Ã€iiiiið€€â± ð€€iiiÀiiÀð€€ð€€ð€€Ã€ð€€ð€€â± ð€€â± Ã€ð€€â± â± â± iÀÀÀÀiið€€ið€€Ã€iiⱠÀiÀð€€iâ± â± iÀⱠiið€€ið€€â± ð€€ð€€iⱠⱠÀð€€â± iiiⱠⱠÀÀð€€iÀⱠ|
+ ð€€iiið€€Ã€â± iⱠÀð€€ð€€ið€€Ã€â± ð€€ð€€â± â± Ã€iâ± ð€€ð€€iâ± ð€€â± iiâ± iiⱠÀð€€ð€€â± iÀÀⱠÀiÀⱠð€€Ã€â± ð€€â± Ã€ið€€â± ið€€ð€€ð€€ð€€ð€€Ã€ð€€ð€€ð€€ið€€iÀð€€Ã€ð€€Ã€Ã€Ã€ð€€â± â± ð€€iiÀð€€Ã€Ã€Ã€â± Ã€ð€€â± Ã€â± Ã€iÀiiÀⱠ|
+ â± ð€€ð€€â± â± ð€€Ã€ð€€Ã€â± ð€€Ã€â± Ã€ð€€ð€€iⱠⱠÀÀiÀⱠð€€Ã€iÀⱠið€€â± Ã€ð€€ð€€ð€€ð€€â± ð€€iⱠÀð€€iÀð€€iÀð€€iÀÀⱠið€€iÀⱠið€€â± iiⱠÀð€€Ã€ð€€â± â± Ã€Ã€ið€€â± â± ð€€iiⱠÀiâ± ð€€ð€€ð€€ð€€â± â± â± Ã€â± iÀⱠiÀÀð€€Ã€|
+ ÀⱠð€€iiiÀÀð€€Ã€â± iâ± ð€€â± â± â± ð€€iÀð€€â± iâ± ð€€ið€€Ã€Ã€iâ± ð€€Ã€iiâ± â± iÀÀð€€Ã€iâ± iÀð€€ið€€Ã€iÀð€€Ã€â± iÀiâ± â± ið€€iⱠÀiÀÀⱠⱠiÀiⱠÀⱠið€€ð€€â± iÀⱠiið€€â± iiâ± ið€€â± ið€€Ã€iÀÀð€€|
+ ÀⱠÀÀð€€ið€€iⱠÀÀÀⱠð€€ð€€Ã€â± Ã€Ã€iiið€€ð€€iiÀiiⱠÀÀⱠiÀiÀÀð€€ið€€ið€€â± iâ± â± iⱠÀiiÀⱠð€€â± â± Ã€iÀⱠð€€ð€€iÀð€€â± ð€€iÀð€€â± Ã€Ã€â± Ã€Ã€Ã€ð€€ð€€ið€€ð€€Ã€ð€€ð€€iið€€Ã€ð€€ð€€â± Ã€ð€€â± â± â± ð€€ð€€|
+ â± ð€€ið€€ð€€ið€€ð€€â± ð€€iÀð€€Ã€iâ± iiÀÀiÀÀÀiÀiiâ± â± ð€€iâ± iÀið€€â± ð€€â± Ã€ð€€â± ð€€ð€€ð€€â± Ã€â± ð€€â± iiâ± iiiⱠÀÀiÀð€€Ã€Ã€ð€€Ã€â± Ã€ð€€iiÀÀiÀiÀÀÀⱠⱠÀÀiið€€â± Ã€Ã€iâ± iÀÀð€€iiiÀ|
+ ÀÀÀÀiâ± iâ± â± â± iâ± ð€€â± Ã€Ã€Ã€ð€€Ã€Ã€iⱠÀð€€Ã€iⱠÀⱠÀⱠⱠÀÀⱠiÀⱠⱠiiⱠÀð€€â± â± Ã€iâ± ð€€iÀⱠð€€â± ð€€â± ð€€iⱠÀⱠið€€ð€€â± ð€€iÀð€€Ã€â± ð€€Ã€Ã€â± ð€€â± ið€€iⱠÀð€€ð€€ð€€ð€€ið€€ið€€ð€€ð€€Ã€â± iÀÀð€€i|
+ ið€€iÀð€€ið€€iⱠⱠⱠÀÀiiiâ± ið€€iÀÀð€€iⱠÀÀð€€iið€€ið€€ð€€Ã€Ã€Ã€Ã€iÀiiÀiiiÀiÀið€€ð€€â± â± Ã€â± â± Ã€iÀÀⱠiâ± â± iÀⱠÀiâ± â± ð€€â± â± â± Ã€â± Ã€â± ð€€iiâ± â± â± ð€€iÀð€€iâ± ð€€iÀiÀiÀi|
+ ð€€ð€€iiÀð€€Ã€â± ð€€ð€€ð€€ð€€ð€€Ã€iiið€€ð€€ð€€â± ð€€ð€€ið€€Ã€Ã€ð€€iiÀiiiiÀð€€iâ± iâ± iÀⱠÀⱠÀiⱠⱠⱠⱠⱠⱠⱠⱠⱠÀiiâ± iÀⱠÀð€€iiⱠÀⱠiⱠⱠÀiâ± ð€€iâ± ð€€iiⱠÀð€€ð€€Ã€iið€€ið€€Ã€â± Ã€Ã€iÀÀ|
+ â± ð€€iÀiÀÀÀÀⱠið€€â± â± ið€€â± â± â± ð€€â± â± ð€€iÀÀÀiÀið€€Ã€ið€€ð€€ð€€â± Ã€iâ± iâ± ð€€ð€€Ã€iiið€€Ã€Ã€iⱠÀiâ± ð€€ð€€ið€€Ã€Ã€iiÀiâ± â± ið€€Ã€ð€€Ã€â± Ã€â± iiiiiið€€â± ð€€Ã€â± ð€€â± â± â± ð€€ð€€iâ± â± â± â± iÀ|
+ ð€€ð€€ð€€ið€€iÀð€€ð€€iÀð€€Ã€ið€€ð€€â± â± ð€€â± Ã€ið€€ð€€Ã€Ã€iiiâ± iâ± ð€€iⱠÀⱠÀð€€â± Ã€ð€€â± iiiiÀiⱠÀiiiⱠⱠÀð€€â± ð€€ð€€ð€€Ã€â± iÀⱠiiiiâ± iâ± ð€€â± ð€€Ã€â± Ã€iið€€ið€€â± ð€€Ã€ð€€iâ± â± ð€€iâ± iiiið€€|
+ ÀÀÀⱠⱠÀð€€Ã€ð€€Ã€ð€€iâ± ð€€ð€€ð€€Ã€ð€€â± â± ð€€Ã€iÀiÀið€€â± ð€€iiâ± iiÀⱠÀⱠð€€â± Ã€ið€€ð€€iÀiÀⱠið€€Ã€ð€€ð€€Ã€â± ð€€ð€€iⱠÀð€€â± ð€€Ã€iÀÀⱠÀiÀð€€â± â± â± iiÀið€€Ã€â± iÀÀÀiâ± â± iÀÀiÀⱠÀⱠÀ|
+ iⱠÀÀⱠÀÀð€€ð€€ð€€iiiÀð€€Ã€ð€€iÀÀið€€Ã€ð€€Ã€â± Ã€iÀiið€€â± â± iið€€â± â± ð€€ð€€Ã€â± ð€€Ã€Ã€ð€€Ã€Ã€Ã€Ã€ið€€Ã€â± ð€€Ã€ð€€Ã€iiâ± ð€€Ã€Ã€â± iâ± ð€€â± ð€€Ã€Ã€ð€€â± â± ð€€â± â± Ã€ð€€â± â± â± ð€€iiÀⱠÀⱠiâ± ið€€iið€€Ã€i|
+ ÀiÀⱠð€€Ã€ð€€ð€€iið€€ð€€â± â± iiiiâ± iÀiâ± iÀiÀð€€Ã€iⱠÀiiÀÀÀð€€ð€€â± ð€€â± â± ð€€iÀiâ± ð€€iið€€â± Ã€ð€€â± iⱠÀiiⱠÀⱠð€€Ã€ið€€Ã€iið€€iiÀiⱠÀiⱠⱠÀiÀð€€ið€€â± Ã€ð€€iÀÀⱠiið€€iÀð€€|
+ â± ð€€â± Ã€ð€€â± ið€€iÀð€€â± ð€€ð€€iÀiÀð€€iâ± ið€€â± Ã€iâ± â± iÀð€€iâ± iÀⱠið€€ð€€iâ± iâ± â± ð€€Ã€Ã€ið€€iÀⱠⱠð€€â± Ã€ð€€ð€€ð€€â± â± iÀÀiâ± â± â± ð€€ð€€â± â± â± â± Ã€iâ± ð€€Ã€ið€€iÀⱠiið€€Ã€â± iið€€â± ð€€Ã€â± Ã€ð€€â± i|
+ Àð€€iâ± â± iâ± ið€€iâ± iið€€â± ið€€iið€€iⱠÀð€€â± Ã€Ã€ið€€iÀð€€iÀð€€â± Ã€â± iⱠÀⱠið€€â± ð€€Ã€â± â± iâ± ð€€iâ± iÀð€€Ã€ð€€Ã€â± ið€€ð€€iÀið€€Ã€ð€€â± ð€€â± â± ið€€ð€€ð€€iⱠÀð€€Ã€â± Ã€ð€€ið€€ið€€iÀⱠÀÀÀð€€iâ± ð€€|
+ ð€€â± â± â± â± â± ð€€â± ð€€Ã€Ã€ð€€ð€€iÀÀⱠiÀiiⱠÀiâ± ð€€ð€€Ã€Ã€iÀⱠð€€Ã€Ã€â± ð€€Ã€ð€€Ã€ð€€iⱠⱠÀiⱠÀiiiⱠÀiÀÀÀð€€iⱠⱠⱠÀÀiâ± â± â± ð€€iið€€iið€€iâ± â± iið€€iⱠÀið€€ð€€ð€€iið€€Ã€â± â± iⱠÀð€€â± â± |
+ ð€€iiâ± ið€€Ã€â± ð€€Ã€iⱠÀÀiÀÀÀÀⱠð€€Ã€iiâ± ið€€iâ± ið€€Ã€â± Ã€ð€€ð€€ð€€iÀiÀð€€â± iÀð€€â± â± Ã€Ã€ið€€â± ð€€ið€€â± Ã€â± iâ± iâ± iiið€€Ã€â± â± ð€€ð€€Ã€â± ð€€ð€€iið€€Ã€iiÀÀⱠiÀð€€Ã€Ã€Ã€iÀⱠÀð€€Ã€ið€€â± |
+ ð€€iâ± ð€€â± â± â± Ã€Ã€ð€€iiiÀÀⱠiið€€ið€€Ã€Ã€â± ð€€â± â± iâ± â± â± iâ± ð€€ið€€Ã€ð€€â± â± â± ið€€Ã€ið€€â± Ã€ð€€Ã€â± iiiiâ± iiâ± â± ið€€ð€€Ã€â± ð€€â± iÀÀð€€iiiⱠÀiâ± ið€€Ã€ð€€ð€€ið€€ð€€iiâ± ð€€Ã€ð€€iiⱠⱠÀð€€iâ± |
+ ÀⱠð€€â± â± â± Ã€iið€€iiâ± â± ð€€iâ± ð€€iiâ± iið€€ð€€ð€€iiâ± iÀð€€â± â± Ã€Ã€Ã€iâ± â± ð€€Ã€ð€€â± â± â± ð€€Ã€iâ± ð€€Ã€iâ± ð€€ið€€Ã€Ã€ð€€â± ð€€â± ð€€iÀð€€iiiÀⱠiÀⱠiÀⱠⱠÀⱠiið€€â± â± â± Ã€iið€€ið€€iiâ± iÀð€€ð€€|
+ ⱠⱠÀÀⱠⱠð€€iÀⱠð€€iⱠⱠÀÀð€€Ã€iâ± ð€€iÀⱠⱠⱠð€€ð€€Ã€ð€€iið€€ð€€Ã€ð€€ð€€Ã€â± â± â± Ã€â± iiâ± ð€€ð€€iið€€â± â± Ã€â± iâ± ið€€â± â± ð€€ið€€ð€€ð€€ð€€â± ð€€iÀiâ± â± ð€€Ã€ð€€Ã€â± â± â± Ã€Ã€ð€€ð€€iÀⱠið€€ð€€Ã€iⱠⱠÀÀiÀÀ|
+ Àiâ± iið€€Ã€Ã€â± ið€€Ã€â± ið€€Ã€ð€€iið€€iâ± ið€€Ã€â± ð€€Ã€ð€€Ã€Ã€â± â± ð€€ið€€â± iiâ± ð€€Ã€Ã€ð€€Ã€ð€€ið€€ð€€ið€€â± ð€€â± ið€€ð€€ð€€ið€€Ã€ið€€ð€€Ã€â± â± ið€€Ã€iÀⱠÀiiiÀÀⱠⱠið€€Ã€iÀiⱠÀÀiÀð€€ð€€Ã€iiiiÀ|
+ ð€€â± Ã€iÀð€€â± â± ð€€ið€€â± â± ð€€ð€€ð€€ð€€ð€€ð€€iⱠÀⱠⱠiiÀⱠð€€ð€€ið€€â± â± ð€€â± â± â± ð€€ð€€iÀiÀⱠð€€Ã€ð€€Ã€ð€€ð€€â± iiiâ± iiiâ± iâ± ð€€Ã€iiiâ± ð€€Ã€ð€€Ã€â± â± Ã€ð€€Ã€ð€€ð€€ð€€â± iâ± ið€€â± Ã€Ã€â± iiâ± â± â± â± ð€€Ã€â± ð€€ð€€|
+ â± ð€€â± â± Ã€ð€€iâ± ð€€â± iiâ± ið€€Ã€â± â± ð€€iÀiÀÀiâ± ið€€iiÀð€€â± â± â± iÀⱠð€€â± â± â± Ã€ð€€â± iâ± ð€€ð€€Ã€â± Ã€Ã€ð€€Ã€â± â± iâ± ð€€ð€€iiÀÀð€€Ã€ð€€iâ± iÀð€€iÀð€€ð€€iiiiiið€€Ã€iâ± ð€€ð€€ið€€Ã€ið€€Ã€ð€€ð€€ið€€â± |
+ â± ð€€iÀÀⱠð€€â± â± Ã€â± Ã€ð€€â± â± Ã€iiÀÀÀⱠð€€ið€€â± ð€€â± Ã€ð€€ð€€iâ± â± â± â± iiⱠⱠⱠÀiⱠÀiiⱠÀð€€â± ð€€â± ið€€ð€€â± Ã€ð€€Ã€â± â± ð€€Ã€â± Ã€â± ð€€â± ð€€iâ± ið€€Ã€â± â± iið€€Ã€â± Ã€ð€€â± ð€€Ã€ið€€Ã€ð€€Ã€Ã€â± iâ± â± iið€€|
+ ⱠÀⱠⱠⱠiâ± ð€€â± ð€€â± ð€€â± iiⱠÀð€€Ã€iiÀið€€iÀÀiiiiÀⱠÀⱠÀⱠiiâ± ð€€ð€€â± Ã€Ã€ð€€ð€€Ã€ð€€Ã€â± â± ð€€ð€€iiið€€iiÀð€€â± iⱠⱠÀð€€Ã€Ã€iið€€â± Ã€â± ið€€ð€€â± ið€€Ã€â± â± ð€€Ã€Ã€Ã€ð€€iÀⱠⱠð€€Ã€Ã€ið€€i|
+ ÀⱠⱠⱠÀⱠⱠiið€€Ã€ið€€â± ið€€ið€€ið€€â± ð€€Ã€Ã€Ã€iÀÀið€€Ã€Ã€Ã€ð€€ið€€iÀð€€ð€€â± iÀið€€ð€€ð€€â± Ã€iÀð€€ð€€iÀÀⱠⱠð€€â± â± â± â± Ã€Ã€Ã€Ã€iiÀð€€iiâ± â± â± ið€€â± Ã€ið€€Ã€â± â± Ã€ð€€â± iiâ± ð€€ð€€ið€€â± ið€€ð€€Ã€|
+ ð€€Ã€ð€€â± ð€€ð€€iÀÀiâ± iiÀⱠÀiÀⱠÀⱠⱠð€€iⱠⱠÀiâ± â± â± â± ð€€iⱠÀÀⱠⱠiâ± ð€€Ã€iâ± â± ið€€ð€€â± iÀð€€Ã€iÀið€€ið€€â± ið€€â± Ã€iiÀⱠÀið€€Ã€ið€€Ã€Ã€Ã€ið€€ð€€Ã€â± ið€€â± iⱠÀiÀiâ± ð€€iið€€ð€€ð€€Ã€|
+ ÀⱠiiÀið€€â± Ã€Ã€iÀⱠið€€Ã€â± â± ð€€â± iÀiiâ± iiâ± â± ð€€iið€€ið€€ð€€ð€€ð€€ið€€â± â± Ã€â± Ã€Ã€iÀÀÀⱠÀⱠⱠÀÀⱠð€€Ã€Ã€ð€€Ã€Ã€â± Ã€ð€€ð€€Ã€iâ± ð€€â± â± ð€€iÀð€€â± ð€€iÀⱠⱠð€€iÀiiiið€€iið€€ð€€â± â± â± ð€€â± |
+ ⱠÀð€€â± â± Ã€Ã€iâ± â± ð€€iⱠⱠⱠÀⱠð€€â± â± ð€€iâ± ð€€ð€€ð€€ð€€â± iÀð€€â± â± Ã€ð€€â± ð€€Ã€Ã€iið€€â± ð€€Ã€Ã€ð€€Ã€Ã€â± ð€€â± Ã€iÀð€€ð€€Ã€ð€€Ã€ð€€ð€€iâ± ið€€Ã€â± â± â± â± ð€€â± â± Ã€Ã€ð€€ð€€ð€€Ã€Ã€iiⱠÀÀð€€â± â± â± iÀⱠÀⱠⱠiÀⱠð€€|
+ ð€€Ã€iÀⱠÀiiÀÀiiâ± â± â± ið€€Ã€Ã€iâ± ð€€iⱠⱠÀð€€ð€€ð€€Ã€â± â± Ã€ð€€â± Ã€Ã€â± ð€€Ã€Ã€ð€€ð€€â± ð€€Ã€Ã€ð€€Ã€â± ð€€â± Ã€iÀð€€iâ± ð€€â± â± ð€€ð€€Ã€ð€€iiið€€iiⱠÀⱠiⱠÀⱠð€€â± ð€€ið€€ð€€Ã€â± â± ið€€ð€€â± â± ð€€ð€€ð€€ð€€Ã€ð€€â± ð€€|
+ Àiiiiið€€iⱠÀÀÀiiâ± iiið€€ð€€Ã€iÀⱠÀÀiâ± â± ð€€iiÀÀⱠð€€â± iÀⱠð€€ð€€iið€€iⱠÀð€€iiâ± ð€€â± ð€€ð€€ið€€â± ð€€ið€€ð€€ð€€Ã€â± iâ± iâ± ið€€iiiÀiið€€ð€€Ã€iið€€Ã€ð€€â± ð€€ð€€â± ð€€ið€€â± Ã€â± iið€€â± |
+ ð€€iiÀⱠiâ± iÀⱠð€€ið€€iiið€€â± ð€€ið€€iÀÀið€€â± iið€€Ã€iÀiiiÀⱠÀð€€Ã€Ã€â± ð€€â± ð€€iiÀið€€ið€€ð€€ið€€â± iiiÀⱠⱠⱠiiÀð€€Ã€ð€€ð€€iÀð€€iⱠÀⱠÀÀið€€â± iÀⱠÀð€€ð€€iÀÀð€€ið€€ð€€Ã€Ã€â± ð€€|
+ ð€€iⱠⱠÀð€€Ã€â± Ã€ð€€iâ± ð€€Ã€iið€€ið€€ð€€Ã€Ã€ið€€ð€€ð€€iiⱠÀð€€iið€€â± ð€€ð€€iâ± ið€€iÀð€€Ã€ð€€â± â± ð€€Ã€ð€€ið€€ð€€iâ± iiÀÀⱠⱠⱠiÀÀiÀÀð€€ð€€ð€€Ã€ð€€ð€€ð€€â± Ã€â± ð€€iÀð€€ð€€â± ð€€â± â± iið€€ð€€Ã€Ã€â± Ã€ið€€ð€€i|
+ ÀiÀⱠⱠⱠⱠiið€€Ã€Ã€ð€€ð€€ð€€â± ið€€Ã€ð€€Ã€â± iiÀið€€â± iið€€iÀÀð€€â± iâ± ð€€â± iiiⱠÀÀiÀÀÀÀð€€â± â± iið€€Ã€ð€€Ã€iÀið€€Ã€Ã€ið€€iâ± iÀið€€Ã€iÀið€€Ã€iÀⱠð€€ið€€â± ið€€ð€€ð€€â± â± ð€€â± Ã€â± Ã€â± i|
+ Àð€€ð€€ið€€Ã€ið€€ð€€â± iⱠÀⱠiiâ± iⱠÀð€€ð€€Ã€iÀð€€ð€€Ã€Ã€â± â± â± ð€€â± iÀⱠⱠÀð€€â± ið€€ð€€Ã€iÀð€€Ã€ð€€iâ± ið€€ð€€Ã€Ã€ð€€iâ± iâ± â± ð€€Ã€Ã€ð€€ð€€Ã€iÀÀð€€Ã€Ã€ð€€ið€€Ã€Ã€ð€€ð€€Ã€Ã€â± iið€€â± ð€€â± ð€€iiÀÀÀið€€Ã€|
+ ið€€â± iÀⱠⱠÀÀð€€ð€€iið€€Ã€Ã€ð€€iÀiÀⱠÀiiiið€€Ã€iÀⱠið€€ið€€ð€€ið€€ð€€iâ± ð€€iÀið€€Ã€Ã€Ã€Ã€iâ± iÀⱠÀÀⱠiiÀÀⱠⱠið€€iâ± iiâ± ið€€â± ð€€ð€€Ã€â± â± Ã€â± iⱠⱠÀð€€iiÀⱠⱠⱠð€€ð€€â± ið€€â± i|
+ ⱠÀⱠð€€Ã€â± ð€€iⱠÀð€€â± iâ± iið€€Ã€â± Ã€Ã€ð€€ið€€â± ið€€â± iÀð€€â± Ã€Ã€Ã€iÀÀÀⱠð€€ð€€â± iiâ± ð€€Ã€â± iiÀiiâ± â± ið€€Ã€iiâ± ð€€iÀⱠÀið€€Ã€ð€€Ã€iÀÀÀið€€Ã€Ã€â± â± iÀiâ± ð€€iið€€â± Ã€iⱠÀⱠⱠi^i |
+ |
+ ]=],
+ value = { col = 100, curscol = 100, endcol = 100, row = 50 },
+ },
+ },
+})
diff --git a/test/benchmark/treesitter_spec.lua b/test/benchmark/treesitter_spec.lua
index 6d82f5de8d..7c9906a7b2 100644
--- a/test/benchmark/treesitter_spec.lua
+++ b/test/benchmark/treesitter_spec.lua
@@ -4,14 +4,13 @@ local clear = helpers.clear
local exec_lua = helpers.exec_lua
describe('treesitter perf', function()
-
setup(function()
clear()
end)
it('can handle large folds', function()
- helpers.command'edit ./src/nvim/eval.c'
- exec_lua[[
+ helpers.command 'edit ./src/nvim/eval.c'
+ exec_lua [[
local parser = vim.treesitter.get_parser(0, "c", {})
vim.treesitter.highlighter.new(parser)
@@ -47,7 +46,5 @@ describe('treesitter perf', function()
return vim.uv.hrtime() - start
]]
-
end)
-
end)
diff --git a/test/busted/outputHandlers/nvim.lua b/test/busted/outputHandlers/nvim.lua
index 4bfa21fe49..28855df261 100644
--- a/test/busted/outputHandlers/nvim.lua
+++ b/test/busted/outputHandlers/nvim.lua
@@ -1,12 +1,21 @@
local pretty = require 'pl.pretty'
local global_helpers = require('test.helpers')
-local colors = setmetatable({}, {__index = function() return function(s) return s == nil and '' or tostring(s) end end})
+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'
+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
@@ -18,49 +27,73 @@ return function(options)
local handler = require 'busted.outputHandlers.base'()
local c = {
- succ = function(s) return colors.bright(colors.green(s)) end,
- skip = function(s) return colors.bright(colors.yellow(s)) end,
- fail = function(s) return colors.bright(colors.magenta(s)) end,
- errr = function(s) return colors.bright(colors.red(s)) end,
+ succ = function(s)
+ return colors.bright(colors.green(s))
+ end,
+ skip = function(s)
+ return colors.bright(colors.yellow(s))
+ end,
+ fail = function(s)
+ return colors.bright(colors.magenta(s))
+ end,
+ errr = function(s)
+ return colors.bright(colors.red(s))
+ end,
test = tostring,
file = colors.cyan,
time = colors.dim,
note = colors.yellow,
- sect = function(s) return colors.green(colors.dim(s)) end,
+ sect = function(s)
+ return colors.green(colors.dim(s))
+ end,
nmbr = colors.bright,
}
local repeatSuiteString = '\nRepeating all tests (run %d of %d) . . .\n\n'
- local randomizeString = c.note('Note: Randomizing test order with a seed of %d.\n')
- local globalSetup = c.sect('--------') .. ' Global test environment setup.\n'
- local fileStartString = c.sect('--------') .. ' Running tests from ' .. c.file('%s') .. '\n'
- local runString = c.sect('RUN ') .. ' ' .. c.test('%s') .. ': '
- local successString = c.succ('OK') .. '\n'
- local skippedString = c.skip('SKIP') .. '\n'
- local failureString = c.fail('FAIL') .. '\n'
- local errorString = c.errr('ERR') .. '\n'
- local fileEndString = c.sect('--------') .. ' '.. c.nmbr('%d') .. ' %s from ' .. c.file('%s') .. ' ' .. c.time('(%.2f ms total)') .. '\n\n'
- local globalTeardown = c.sect('--------') .. ' Global test environment teardown.\n'
- local suiteEndString = c.sect('========') .. ' ' .. c.nmbr('%d') .. ' %s from ' .. c.nmbr('%d') .. ' test %s ran. ' .. c.time('(%.2f ms total)') .. '\n'
- local successStatus = c.succ('PASSED ') .. ' ' .. c.nmbr('%d') .. ' %s.\n'
- local timeString = c.time('%.2f ms')
+ local randomizeString = c.note('Note: Randomizing test order with a seed of %d.\n')
+ local globalSetup = c.sect('--------') .. ' Global test environment setup.\n'
+ local fileStartString = c.sect('--------') .. ' Running tests from ' .. c.file('%s') .. '\n'
+ local runString = c.sect('RUN ') .. ' ' .. c.test('%s') .. ': '
+ local successString = c.succ('OK') .. '\n'
+ local skippedString = c.skip('SKIP') .. '\n'
+ local failureString = c.fail('FAIL') .. '\n'
+ local errorString = c.errr('ERR') .. '\n'
+ local fileEndString = c.sect('--------')
+ .. ' '
+ .. c.nmbr('%d')
+ .. ' %s from '
+ .. c.file('%s')
+ .. ' '
+ .. c.time('(%.2f ms total)')
+ .. '\n\n'
+ local globalTeardown = c.sect('--------') .. ' Global test environment teardown.\n'
+ local suiteEndString = c.sect('========')
+ .. ' '
+ .. c.nmbr('%d')
+ .. ' %s from '
+ .. c.nmbr('%d')
+ .. ' test %s ran. '
+ .. c.time('(%.2f ms total)')
+ .. '\n'
+ local successStatus = c.succ('PASSED ') .. ' ' .. c.nmbr('%d') .. ' %s.\n'
+ local timeString = c.time('%.2f ms')
local summaryStrings = {
skipped = {
header = c.skip('SKIPPED ') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n',
- test = c.skip('SKIPPED ') .. ' %s\n',
+ test = c.skip('SKIPPED ') .. ' %s\n',
footer = ' ' .. c.nmbr('%d') .. ' SKIPPED %s\n',
},
failure = {
header = c.fail('FAILED ') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n',
- test = c.fail('FAILED ') .. ' %s\n',
+ test = c.fail('FAILED ') .. ' %s\n',
footer = ' ' .. c.nmbr('%d') .. ' FAILED %s\n',
},
error = {
header = c.errr('ERROR ') .. ' ' .. c.nmbr('%d') .. ' %s, listed below:\n',
- test = c.errr('ERROR ') .. ' %s\n',
+ test = c.errr('ERROR ') .. ' %s\n',
footer = ' ' .. c.nmbr('%d') .. ' %s\n',
},
}
@@ -107,8 +140,10 @@ return function(options)
local getFileLine = function(element)
local fileline = ''
if element.trace or element.trace.short_src then
- fileline = colors.cyan(element.trace.short_src) .. ' @ ' ..
- colors.cyan(element.trace.currentline) .. ': '
+ fileline = colors.cyan(element.trace.short_src)
+ .. ' @ '
+ .. colors.cyan(element.trace.currentline)
+ .. ': '
end
return fileline
end
@@ -219,7 +254,9 @@ return function(options)
local elapsedTime_ms = getElapsedTime(file)
local tests = (fileTestCount == 1 and 'test' or 'tests')
fileCount = fileCount + 1
- io.write(fileEndString:format(fileTestCount, tests, vim.fs.normalize(file.name), elapsedTime_ms))
+ io.write(
+ fileEndString:format(fileTestCount, tests, vim.fs.normalize(file.name), elapsedTime_ms)
+ )
io.flush()
return nil, true
end
@@ -256,7 +293,7 @@ return function(options)
errorCount = errorCount + 1
string = errorString .. failureDescription(handler.errors[#handler.errors])
else
- string = "unexpected test status! ("..status..")"
+ string = 'unexpected test status! (' .. status .. ')'
end
write_status(element, string)
diff --git a/test/client/msgpack_rpc_stream.lua b/test/client/msgpack_rpc_stream.lua
index 5711616b17..7131940a58 100644
--- a/test/client/msgpack_rpc_stream.lua
+++ b/test/client/msgpack_rpc_stream.lua
@@ -1,15 +1,4 @@
-local mpack = require('mpack')
-
--- temporary hack to be able to manipulate buffer/window/tabpage
-local Buffer = {}
-Buffer.__index = Buffer
-function Buffer.new(id) return setmetatable({id=id}, Buffer) end
-local Window = {}
-Window.__index = Window
-function Window.new(id) return setmetatable({id=id}, Window) end
-local Tabpage = {}
-Tabpage.__index = Tabpage
-function Tabpage.new(id) return setmetatable({id=id}, Tabpage) end
+local mpack = vim.mpack
local Response = {}
Response.__index = Response
@@ -17,7 +6,7 @@ Response.__index = Response
function Response.new(msgpack_rpc_stream, request_id)
return setmetatable({
_msgpack_rpc_stream = msgpack_rpc_stream,
- _request_id = request_id
+ _request_id = request_id,
}, Response)
end
@@ -33,27 +22,33 @@ function Response:send(value, is_error)
self._msgpack_rpc_stream._stream:write(data)
end
+--- @class test.MsgpackRpcStream
+--- @field private _stream test.Stream
+--- @field private __pack table
local MsgpackRpcStream = {}
MsgpackRpcStream.__index = MsgpackRpcStream
function MsgpackRpcStream.new(stream)
return setmetatable({
_stream = stream,
- _pack = mpack.Packer({
- ext = {
- [Buffer] = function(o) return 0, mpack.encode(o.id) end,
- [Window] = function(o) return 1, mpack.encode(o.id) end,
- [Tabpage] = function(o) return 2, mpack.encode(o.id) end
- }
- }),
+ _pack = mpack.Packer(),
_session = mpack.Session({
unpack = mpack.Unpacker({
ext = {
- [0] = function(_c, s) return Buffer.new(mpack.decode(s)) end,
- [1] = function(_c, s) return Window.new(mpack.decode(s)) end,
- [2] = function(_c, s) return Tabpage.new(mpack.decode(s)) end
- }
- })
+ -- Buffer
+ [0] = function(_c, s)
+ return mpack.decode(s)
+ end,
+ -- Window
+ [1] = function(_c, s)
+ return mpack.decode(s)
+ end,
+ -- Tabpage
+ [2] = function(_c, s)
+ return mpack.decode(s)
+ end,
+ },
+ }),
}),
}, MsgpackRpcStream)
end
@@ -67,7 +62,7 @@ function MsgpackRpcStream:write(method, args, response_cb)
data = self._session:notify()
end
- data = data .. self._pack(method) .. self._pack(args)
+ data = data .. self._pack(method) .. self._pack(args)
self._stream:write(data)
end
@@ -80,12 +75,10 @@ function MsgpackRpcStream:read_start(request_cb, notification_cb, eof_cb)
local pos = 1
local len = #data
while pos <= len do
- type, id_or_cb, method_or_error, args_or_result, pos =
- self._session:receive(data, pos)
+ type, id_or_cb, method_or_error, args_or_result, pos = self._session:receive(data, pos)
if type == 'request' or type == 'notification' then
if type == 'request' then
- request_cb(method_or_error, args_or_result, Response.new(self,
- id_or_cb))
+ request_cb(method_or_error, args_or_result, Response.new(self, id_or_cb))
else
notification_cb(method_or_error, args_or_result)
end
diff --git a/test/client/session.lua b/test/client/session.lua
index b1bf5ea75e..cf3d8c4f25 100644
--- a/test/client/session.lua
+++ b/test/client/session.lua
@@ -1,13 +1,19 @@
-local uv = require('luv')
+local uv = vim.uv
local MsgpackRpcStream = require('test.client.msgpack_rpc_stream')
+--- @class test.Session
+--- @field private _pending_messages string[]
+--- @field private _msgpack_rpc_stream test.MsgpackRpcStream
+--- @field private _prepare uv.uv_prepare_t
+--- @field private _timer uv.uv_timer_t
+--- @field private _is_running boolean
local Session = {}
Session.__index = Session
if package.loaded['jit'] then
-- luajit pcall is already coroutine safe
Session.safe_pcall = pcall
else
- Session.safe_pcall = require'coxpcall'.pcall
+ Session.safe_pcall = require 'coxpcall'.pcall
end
local function resume(co, ...)
@@ -25,8 +31,8 @@ local function resume(co, ...)
end
local function coroutine_exec(func, ...)
- local args = {...}
- local on_complete
+ local args = { ... }
+ local on_complete --- @type function?
if #args > 0 and type(args[#args]) == 'function' then
-- completion callback
@@ -50,18 +56,20 @@ function Session.new(stream)
_pending_messages = {},
_prepare = uv.new_prepare(),
_timer = uv.new_timer(),
- _is_running = false
+ _is_running = false,
}, Session)
end
+--- @param timeout integer?
+--- @return string?
function Session:next_message(timeout)
local function on_request(method, args, response)
- table.insert(self._pending_messages, {'request', method, args, response})
+ table.insert(self._pending_messages, { 'request', method, args, response })
uv.stop()
end
local function on_notification(method, args)
- table.insert(self._pending_messages, {'notification', method, args})
+ table.insert(self._pending_messages, { 'notification', method, args })
uv.stop()
end
@@ -83,11 +91,15 @@ function Session:next_message(timeout)
end
function Session:notify(method, ...)
- self._msgpack_rpc_stream:write(method, {...})
+ self._msgpack_rpc_stream:write(method, { ... })
end
+--- @param method string
+--- @param ... any
+--- @return boolean
+--- @return table
function Session:request(method, ...)
- local args = {...}
+ local args = { ... }
local err, result
if self._is_running then
err, result = self:_yielding_request(method, args)
@@ -141,8 +153,12 @@ function Session:stop()
end
function Session:close(signal)
- if not self._timer:is_closing() then self._timer:close() end
- if not self._prepare:is_closing() then self._prepare:close() end
+ if not self._timer:is_closing() then
+ self._timer:close()
+ end
+ if not self._prepare:is_closing() then
+ self._prepare:close()
+ end
self._msgpack_rpc_stream:close(signal)
self.closed = true
end
@@ -159,11 +175,11 @@ function Session:_blocking_request(method, args)
local err, result
local function on_request(method_, args_, response)
- table.insert(self._pending_messages, {'request', method_, args_, response})
+ table.insert(self._pending_messages, { 'request', method_, args_, response })
end
local function on_notification(method_, args_)
- table.insert(self._pending_messages, {'notification', method_, args_})
+ table.insert(self._pending_messages, { 'notification', method_, args_ })
end
self._msgpack_rpc_stream:write(method, args, function(e, r)
@@ -187,7 +203,7 @@ function Session:_run(request_cb, notification_cb, timeout)
end
self._msgpack_rpc_stream:read_start(request_cb, notification_cb, function()
uv.stop()
- self.eof_err = {1, "EOF was received from Nvim. Likely the Nvim process crashed."}
+ self.eof_err = { 1, 'EOF was received from Nvim. Likely the Nvim process crashed.' }
end)
uv.run()
self._prepare:stop()
diff --git a/test/client/uv_stream.lua b/test/client/uv_stream.lua
index cea77f0dbd..0540c44eb2 100644
--- a/test/client/uv_stream.lua
+++ b/test/client/uv_stream.lua
@@ -1,18 +1,28 @@
-local uv = require('luv')
+local uv = vim.uv
+--- @class test.Stream
+--- @field write fun(self, data: string|string[])
+--- @field read_start fun(self, cb: fun(chunk: string))
+--- @field read_stop fun(self)
+--- @field close fun(self, signal?: string)
+
+--- @class vim.StdioStream : test.Stream
+--- @field private _in uv.uv_pipe_t
+--- @field private _out uv.uv_pipe_t
local StdioStream = {}
StdioStream.__index = StdioStream
function StdioStream.open()
local self = setmetatable({
- _in = uv.new_pipe(false),
- _out = uv.new_pipe(false)
+ _in = assert(uv.new_pipe(false)),
+ _out = assert(uv.new_pipe(false)),
}, StdioStream)
self._in:open(0)
self._out:open(1)
return self
end
+--- @param data string|string[]
function StdioStream:write(data)
self._out:write(data)
end
@@ -35,34 +45,36 @@ function StdioStream:close()
self._out:close()
end
+--- @class test.SocketStream : test.Stream
+--- @field package _stream_error? string
+--- @field package _socket uv.uv_pipe_t
local SocketStream = {}
SocketStream.__index = SocketStream
function SocketStream.open(file)
- local socket = uv.new_pipe(false)
+ local socket = assert(uv.new_pipe(false))
local self = setmetatable({
_socket = socket,
- _stream_error = nil
+ _stream_error = nil,
}, SocketStream)
- uv.pipe_connect(socket, file, function (err)
+ uv.pipe_connect(socket, file, function(err)
self._stream_error = self._stream_error or err
end)
return self
end
function SocketStream.connect(host, port)
- local socket = uv.new_tcp()
+ local socket = assert(uv.new_tcp())
local self = setmetatable({
_socket = socket,
- _stream_error = nil
+ _stream_error = nil,
}, SocketStream)
- uv.tcp_connect(socket, host, port, function (err)
+ uv.tcp_connect(socket, host, port, function(err)
self._stream_error = self._stream_error or err
end)
return self
end
-
function SocketStream:write(data)
if self._stream_error then
error(self._stream_error)
@@ -97,23 +109,36 @@ function SocketStream:close()
uv.close(self._socket)
end
+--- @class test.ChildProcessStream : test.Stream
+--- @field private _proc uv.uv_process_t
+--- @field private _pid integer
+--- @field private _child_stdin uv.uv_pipe_t
+--- @field private _child_stdout uv.uv_pipe_t
+--- @field status integer
+--- @field signal integer
local ChildProcessStream = {}
ChildProcessStream.__index = ChildProcessStream
+--- @param argv string[]
+--- @param env string[]?
+--- @param io_extra uv.uv_pipe_t?
+--- @return test.ChildProcessStream
function ChildProcessStream.spawn(argv, env, io_extra)
local self = setmetatable({
- _child_stdin = uv.new_pipe(false);
- _child_stdout = uv.new_pipe(false);
- _exiting = false;
+ _child_stdin = uv.new_pipe(false),
+ _child_stdout = uv.new_pipe(false),
+ _exiting = false,
}, ChildProcessStream)
local prog = argv[1]
- local args = {}
+ local args = {} --- @type string[]
for i = 2, #argv do
args[#args + 1] = argv[i]
end
+ --- @diagnostic disable-next-line:missing-fields
self._proc, self._pid = uv.spawn(prog, {
- stdio = {self._child_stdin, self._child_stdout, 2, io_extra},
+ stdio = { self._child_stdin, self._child_stdout, 2, io_extra },
args = args,
+ --- @diagnostic disable-next-line:assign-type-mismatch
env = env,
}, function(status, signal)
self.status = status
@@ -154,7 +179,7 @@ function ChildProcessStream:close(signal)
self._child_stdin:close()
self._child_stdout:close()
if type(signal) == 'string' then
- self._proc:kill('sig'..signal)
+ self._proc:kill('sig' .. signal)
end
while self.status == nil do
uv.run 'once'
@@ -163,7 +188,7 @@ function ChildProcessStream:close(signal)
end
return {
- StdioStream = StdioStream;
- ChildProcessStream = ChildProcessStream;
- SocketStream = SocketStream;
+ StdioStream = StdioStream,
+ ChildProcessStream = ChildProcessStream,
+ SocketStream = SocketStream,
}
diff --git a/test/deprecated.lua b/test/deprecated.lua
deleted file mode 100644
index e30dfcf3ab..0000000000
--- a/test/deprecated.lua
+++ /dev/null
@@ -1,9 +0,0 @@
--- Island of Misfit Toys
-
-local M = {}
-
-function M.redir_exec()
- error('redir_exec is deprecated, use nvim_exec2() or pcall_err()')
-end
-
-return M
diff --git a/test/format_string.lua b/test/format_string.lua
new file mode 100644
index 0000000000..777fb652e8
--- /dev/null
+++ b/test/format_string.lua
@@ -0,0 +1,168 @@
+local luaassert = require('luassert')
+
+local M = {}
+
+local SUBTBL = {
+ '\\000',
+ '\\001',
+ '\\002',
+ '\\003',
+ '\\004',
+ '\\005',
+ '\\006',
+ '\\007',
+ '\\008',
+ '\\t',
+ '\\n',
+ '\\011',
+ '\\012',
+ '\\r',
+ '\\014',
+ '\\015',
+ '\\016',
+ '\\017',
+ '\\018',
+ '\\019',
+ '\\020',
+ '\\021',
+ '\\022',
+ '\\023',
+ '\\024',
+ '\\025',
+ '\\026',
+ '\\027',
+ '\\028',
+ '\\029',
+ '\\030',
+ '\\031',
+}
+
+--- @param v any
+--- @return string
+local function format_float(v)
+ -- On windows exponent appears to have three digits and not two
+ local ret = ('%.6e'):format(v)
+ local l, f, es, e = ret:match('^(%-?%d)%.(%d+)e([+%-])0*(%d%d+)$')
+ return l .. '.' .. f .. 'e' .. es .. e
+end
+
+-- Formats Lua value `v`.
+--
+-- TODO(justinmk): redundant with vim.inspect() ?
+--
+-- "Nice table formatting similar to screen:snapshot_util()".
+-- Commit: 520c0b91a528
+function M.format_luav(v, indent, opts)
+ opts = opts or {}
+ local linesep = '\n'
+ local next_indent_arg = nil
+ local indent_shift = opts.indent_shift or ' '
+ local next_indent
+ local nl = '\n'
+ if indent == nil then
+ indent = ''
+ linesep = ''
+ next_indent = ''
+ nl = ' '
+ else
+ next_indent_arg = indent .. indent_shift
+ next_indent = indent .. indent_shift
+ end
+ local ret = ''
+ if type(v) == 'string' then
+ if opts.literal_strings then
+ ret = v
+ else
+ local quote = opts.dquote_strings and '"' or "'"
+ ret = quote
+ .. tostring(v)
+ :gsub(opts.dquote_strings and '["\\]' or "['\\]", '\\%0')
+ :gsub('[%z\1-\31]', function(match)
+ return SUBTBL[match:byte() + 1]
+ end)
+ .. quote
+ end
+ elseif type(v) == 'table' then
+ if v == vim.NIL then
+ ret = 'REMOVE_THIS'
+ else
+ local processed_keys = {}
+ ret = '{' .. linesep
+ local non_empty = false
+ local format_luav = M.format_luav
+ for i, subv in ipairs(v) do
+ ret = ('%s%s%s,%s'):format(ret, next_indent, format_luav(subv, next_indent_arg, opts), nl)
+ processed_keys[i] = true
+ non_empty = true
+ end
+ for k, subv in pairs(v) do
+ if not processed_keys[k] then
+ if type(k) == 'string' and k:match('^[a-zA-Z_][a-zA-Z0-9_]*$') then
+ ret = ret .. next_indent .. k .. ' = '
+ else
+ ret = ('%s%s[%s] = '):format(ret, next_indent, format_luav(k, nil, opts))
+ end
+ ret = ret .. format_luav(subv, next_indent_arg, opts) .. ',' .. nl
+ non_empty = true
+ end
+ end
+ if nl == ' ' and non_empty then
+ ret = ret:sub(1, -3)
+ end
+ ret = ret .. indent .. '}'
+ end
+ elseif type(v) == 'number' then
+ if v % 1 == 0 then
+ ret = ('%d'):format(v)
+ else
+ ret = format_float(v)
+ end
+ elseif type(v) == 'nil' then
+ ret = 'nil'
+ elseif type(v) == 'boolean' then
+ ret = (v and 'true' or 'false')
+ else
+ print(type(v))
+ -- Not implemented yet
+ luaassert(false)
+ end
+ return ret
+end
+
+-- Like Python repr(), "{!r}".format(s)
+--
+-- Commit: 520c0b91a528
+function M.format_string(fmt, ...)
+ local i = 0
+ local args = { ... }
+ local function getarg()
+ i = i + 1
+ return args[i]
+ end
+ local ret = fmt:gsub('%%[0-9*]*%.?[0-9*]*[cdEefgGiouXxqsr%%]', function(match)
+ local subfmt = match:gsub('%*', function()
+ return tostring(getarg())
+ end)
+ local arg = nil
+ if subfmt:sub(-1) ~= '%' then
+ arg = getarg()
+ end
+ if subfmt:sub(-1) == 'r' or subfmt:sub(-1) == 'q' then
+ -- %r is like built-in %q, but it is supposed to single-quote strings and
+ -- not double-quote them, and also work not only for strings.
+ -- Builtin %q is replaced here as it gives invalid and inconsistent with
+ -- luajit results for e.g. "\e" on lua: luajit transforms that into `\27`,
+ -- lua leaves as-is.
+ arg = M.format_luav(arg, nil, { dquote_strings = (subfmt:sub(-1) == 'q') })
+ subfmt = subfmt:sub(1, -2) .. 's'
+ end
+ if subfmt == '%e' then
+ return format_float(arg)
+ else
+ return subfmt:format(arg)
+ end
+ end)
+ return ret
+end
+
+return M
diff --git a/test/functional/api/autocmd_spec.lua b/test/functional/api/autocmd_spec.lua
index fd46a1dcfa..e89abf6c64 100644
--- a/test/functional/api/autocmd_spec.lua
+++ b/test/functional/api/autocmd_spec.lua
@@ -6,7 +6,7 @@ local eq = helpers.eq
local neq = helpers.neq
local exec_lua = helpers.exec_lua
local matches = helpers.matches
-local meths = helpers.meths
+local api = helpers.api
local source = helpers.source
local pcall_err = helpers.pcall_err
@@ -15,43 +15,74 @@ before_each(clear)
describe('autocmd api', function()
describe('nvim_create_autocmd', function()
it('validation', function()
- eq("Cannot use both 'callback' and 'command'", pcall_err(meths.create_autocmd, 'BufReadPost', {
- pattern = '*.py,*.pyi',
- command = "echo 'Should Have Errored",
- callback = 'NotAllowed',
- }))
- eq("Cannot use both 'pattern' and 'buffer' for the same autocmd", pcall_err(meths.create_autocmd, 'FileType', {
- command = 'let g:called = g:called + 1',
- buffer = 0,
- pattern = '*.py',
- }))
- eq("Required: 'event'", pcall_err(meths.create_autocmd, {}, {
- command = 'ls',
- }))
- eq("Required: 'command' or 'callback'", pcall_err(meths.create_autocmd, 'FileType', {
- }))
- eq("Invalid 'desc': expected String, got Integer", pcall_err(meths.create_autocmd, 'FileType', {
- command = 'ls',
- desc = 42,
- }))
- eq("Invalid 'callback': expected Lua function or Vim function name, got Integer", pcall_err(meths.create_autocmd, 'FileType', {
- callback = 0,
- }))
- eq("Invalid 'event' item: expected String, got Array", pcall_err(meths.create_autocmd,
- {'FileType', {}}, {}))
- eq("Invalid 'group': 0", pcall_err(meths.create_autocmd, 'FileType', {
- group = 0,
- command = 'ls',
- }))
-
- eq("Invalid 'event': 'foo'", pcall_err(meths.create_autocmd, 'foo', { command = '' }))
- eq("Invalid 'event': 'VimEnter '", pcall_err(meths.create_autocmd, 'VimEnter ', { command = '' }))
- eq("Invalid 'event': 'VimEnter foo'", pcall_err(meths.create_autocmd, 'VimEnter foo', { command = '' }))
- eq("Invalid 'event': 'BufAdd,BufDelete'", pcall_err(meths.create_autocmd, 'BufAdd,BufDelete', { command = '' }))
+ eq(
+ "Cannot use both 'callback' and 'command'",
+ pcall_err(api.nvim_create_autocmd, 'BufReadPost', {
+ pattern = '*.py,*.pyi',
+ command = "echo 'Should Have Errored",
+ callback = 'NotAllowed',
+ })
+ )
+ eq(
+ "Cannot use both 'pattern' and 'buffer' for the same autocmd",
+ pcall_err(api.nvim_create_autocmd, 'FileType', {
+ command = 'let g:called = g:called + 1',
+ buffer = 0,
+ pattern = '*.py',
+ })
+ )
+ eq(
+ "Required: 'event'",
+ pcall_err(api.nvim_create_autocmd, {}, {
+ command = 'ls',
+ })
+ )
+ eq("Required: 'command' or 'callback'", pcall_err(api.nvim_create_autocmd, 'FileType', {}))
+ eq(
+ "Invalid 'desc': expected String, got Integer",
+ pcall_err(api.nvim_create_autocmd, 'FileType', {
+ command = 'ls',
+ desc = 42,
+ })
+ )
+ eq(
+ "Invalid 'callback': expected Lua function or Vim function name, got Integer",
+ pcall_err(api.nvim_create_autocmd, 'FileType', {
+ callback = 0,
+ })
+ )
+ eq(
+ "Invalid 'event' item: expected String, got Array",
+ pcall_err(api.nvim_create_autocmd, { 'FileType', {} }, {})
+ )
+ eq(
+ "Invalid 'group': 0",
+ pcall_err(api.nvim_create_autocmd, 'FileType', {
+ group = 0,
+ command = 'ls',
+ })
+ )
+
+ eq("Invalid 'event': 'foo'", pcall_err(api.nvim_create_autocmd, 'foo', { command = '' }))
+ eq(
+ "Invalid 'event': 'VimEnter '",
+ pcall_err(api.nvim_create_autocmd, 'VimEnter ', { command = '' })
+ )
+ eq(
+ "Invalid 'event': 'VimEnter foo'",
+ pcall_err(api.nvim_create_autocmd, 'VimEnter foo', { command = '' })
+ )
+ eq(
+ "Invalid 'event': 'BufAdd,BufDelete'",
+ pcall_err(api.nvim_create_autocmd, 'BufAdd,BufDelete', { command = '' })
+ )
end)
it('doesnt leak when you use ++once', function()
- eq(1, exec_lua([[
+ eq(
+ 1,
+ exec_lua(
+ [[
local count = 0
vim.api.nvim_create_autocmd("FileType", {
@@ -64,30 +95,33 @@ describe('autocmd api', function()
vim.cmd "set filetype=python"
return count
- ]], {}))
+ ]],
+ {}
+ )
+ )
end)
it('allows passing buffer by key', function()
- meths.set_var('called', 0)
+ api.nvim_set_var('called', 0)
- meths.create_autocmd("FileType", {
- command = "let g:called = g:called + 1",
+ api.nvim_create_autocmd('FileType', {
+ command = 'let g:called = g:called + 1',
buffer = 0,
})
- meths.command "set filetype=txt"
- eq(1, meths.get_var('called'))
+ command 'set filetype=txt'
+ eq(1, api.nvim_get_var('called'))
-- switch to a new buffer
- meths.command "new"
- meths.command "set filetype=python"
+ command 'new'
+ command 'set filetype=python'
- eq(1, meths.get_var('called'))
+ eq(1, api.nvim_get_var('called'))
end)
it('does not allow passing invalid buffers', function()
- local ok, msg = pcall(meths.create_autocmd, 'FileType', {
- command = "let g:called = g:called + 1",
+ local ok, msg = pcall(api.nvim_create_autocmd, 'FileType', {
+ command = 'let g:called = g:called + 1',
buffer = -1,
})
@@ -96,60 +130,66 @@ describe('autocmd api', function()
end)
it('errors on non-functions for cb', function()
- eq(false, pcall(exec_lua, [[
+ eq(
+ false,
+ pcall(
+ exec_lua,
+ [[
vim.api.nvim_create_autocmd("BufReadPost", {
pattern = "*.py,*.pyi",
callback = 5,
})
- ]]))
+ ]]
+ )
+ )
end)
it('allow passing pattern and <buffer> in same pattern', function()
- local ok = pcall(meths.create_autocmd, "BufReadPost", {
- pattern = "*.py,<buffer>",
- command = "echo 'Should Not Error'"
+ local ok = pcall(api.nvim_create_autocmd, 'BufReadPost', {
+ pattern = '*.py,<buffer>',
+ command = "echo 'Should Not Error'",
})
eq(true, ok)
end)
it('should handle multiple values as comma separated list', function()
- meths.create_autocmd("BufReadPost", {
- pattern = "*.py,*.pyi",
- command = "echo 'Should Not Have Errored'"
+ api.nvim_create_autocmd('BufReadPost', {
+ pattern = '*.py,*.pyi',
+ command = "echo 'Should Not Have Errored'",
})
-- We should have one autocmd for *.py and one for *.pyi
- eq(2, #meths.get_autocmds { event = "BufReadPost" })
+ eq(2, #api.nvim_get_autocmds { event = 'BufReadPost' })
end)
it('should handle multiple values as array', function()
- meths.create_autocmd("BufReadPost", {
- pattern = { "*.py", "*.pyi", },
- command = "echo 'Should Not Have Errored'"
+ api.nvim_create_autocmd('BufReadPost', {
+ pattern = { '*.py', '*.pyi' },
+ command = "echo 'Should Not Have Errored'",
})
-- We should have one autocmd for *.py and one for *.pyi
- eq(2, #meths.get_autocmds { event = "BufReadPost" })
+ eq(2, #api.nvim_get_autocmds { event = 'BufReadPost' })
end)
describe('desc', function()
it('can add description to one autocmd', function()
- local cmd = "echo 'Should Not Have Errored'"
- local desc = "Can show description"
- meths.create_autocmd("BufReadPost", {
- pattern = "*.py",
+ local cmd = "echo 'Should Not Have Errored'"
+ local desc = 'Can show description'
+ api.nvim_create_autocmd('BufReadPost', {
+ pattern = '*.py',
command = cmd,
desc = desc,
})
- eq(desc, meths.get_autocmds { event = "BufReadPost" }[1].desc)
- eq(cmd, meths.get_autocmds { event = "BufReadPost" }[1].command)
+ eq(desc, api.nvim_get_autocmds { event = 'BufReadPost' }[1].desc)
+ eq(cmd, api.nvim_get_autocmds { event = 'BufReadPost' }[1].command)
end)
it('can add description to one autocmd that uses a callback', function()
local desc = 'Can show description'
- meths.set_var('desc', desc)
+ api.nvim_set_var('desc', desc)
local result = exec_lua([[
local callback = function() print 'Should Not Have Errored' end
@@ -178,38 +218,38 @@ describe('autocmd api', function()
})
]])
- eq(nil, meths.get_autocmds({ event = 'BufReadPost' })[1].desc)
+ eq(nil, api.nvim_get_autocmds({ event = 'BufReadPost' })[1].desc)
end)
it('can add description to multiple autocmd', function()
- meths.create_autocmd("BufReadPost", {
- pattern = {"*.py", "*.pyi"},
+ api.nvim_create_autocmd('BufReadPost', {
+ pattern = { '*.py', '*.pyi' },
command = "echo 'Should Not Have Errored'",
- desc = "Can show description",
+ desc = 'Can show description',
})
- local aus = meths.get_autocmds { event = "BufReadPost" }
+ local aus = api.nvim_get_autocmds { event = 'BufReadPost' }
eq(2, #aus)
- eq("Can show description", aus[1].desc)
- eq("Can show description", aus[2].desc)
+ eq('Can show description', aus[1].desc)
+ eq('Can show description', aus[2].desc)
end)
end)
pending('script and verbose settings', function()
it('marks API client', function()
- meths.create_autocmd("BufReadPost", {
- pattern = "*.py",
+ api.nvim_create_autocmd('BufReadPost', {
+ pattern = '*.py',
command = "echo 'Should Not Have Errored'",
- desc = "Can show description",
+ desc = 'Can show description',
})
- local aus = meths.get_autocmds { event = "BufReadPost" }
+ local aus = api.nvim_get_autocmds { event = 'BufReadPost' }
eq(1, #aus, aus)
end)
end)
it('removes an autocommand if the callback returns true', function()
- meths.set_var("some_condition", false)
+ api.nvim_set_var('some_condition', false)
exec_lua [[
vim.api.nvim_create_autocmd("User", {
@@ -221,21 +261,21 @@ describe('autocmd api', function()
})
]]
- meths.exec_autocmds("User", {pattern = "Test"})
+ api.nvim_exec_autocmds('User', { pattern = 'Test' })
- local aus = meths.get_autocmds({ event = 'User', pattern = 'Test' })
+ local aus = api.nvim_get_autocmds({ event = 'User', pattern = 'Test' })
local first = aus[1]
eq(true, first.id > 0)
- meths.set_var("some_condition", true)
- meths.exec_autocmds("User", {pattern = "Test"})
- eq({}, meths.get_autocmds({event = "User", pattern = "Test"}))
+ api.nvim_set_var('some_condition', true)
+ api.nvim_exec_autocmds('User', { pattern = 'Test' })
+ eq({}, api.nvim_get_autocmds({ event = 'User', pattern = 'Test' }))
end)
it('receives an args table', function()
- local group_id = meths.create_augroup("TestGroup", {})
+ local group_id = api.nvim_create_augroup('TestGroup', {})
-- Having an existing autocmd calling expand("<afile>") shouldn't change args #18964
- meths.create_autocmd('User', {
+ api.nvim_create_autocmd('User', {
group = 'TestGroup',
pattern = 'Te*',
command = 'call expand("<afile>")',
@@ -251,15 +291,15 @@ describe('autocmd api', function()
})
]]
- meths.exec_autocmds("User", {pattern = "Test pattern"})
+ api.nvim_exec_autocmds('User', { pattern = 'Test pattern' })
eq({
id = autocmd_id,
group = group_id,
- event = "User",
- match = "Test pattern",
- file = "Test pattern",
+ event = 'User',
+ match = 'Test pattern',
+ file = 'Test pattern',
buf = 1,
- }, meths.get_var("autocmd_args"))
+ }, api.nvim_get_var('autocmd_args'))
-- Test without a group
autocmd_id = exec_lua [[
@@ -271,20 +311,23 @@ describe('autocmd api', function()
})
]]
- meths.exec_autocmds("User", {pattern = "some_pat"})
+ api.nvim_exec_autocmds('User', { pattern = 'some_pat' })
eq({
id = autocmd_id,
group = nil,
- event = "User",
- match = "some_pat",
- file = "some_pat",
+ event = 'User',
+ match = 'some_pat',
+ file = 'some_pat',
buf = 1,
- }, meths.get_var("autocmd_args"))
+ }, api.nvim_get_var('autocmd_args'))
end)
it('can receive arbitrary data', function()
local function test(data)
- eq(data, exec_lua([[
+ eq(
+ data,
+ exec_lua(
+ [[
local input = ...
local output
vim.api.nvim_create_autocmd("User", {
@@ -300,40 +343,64 @@ describe('autocmd api', function()
})
return output
- ]], data))
+ ]],
+ data
+ )
+ )
end
- test("Hello")
+ test('Hello')
test(42)
test(true)
- test({ "list" })
- test({ foo = "bar" })
+ test({ 'list' })
+ test({ foo = 'bar' })
end)
end)
describe('nvim_get_autocmds', function()
it('validation', function()
- eq("Invalid 'group': 9997999", pcall_err(meths.get_autocmds, {
- group = 9997999,
- }))
- eq("Invalid 'group': 'bogus'", pcall_err(meths.get_autocmds, {
- group = 'bogus',
- }))
- eq("Invalid 'group': 0", pcall_err(meths.get_autocmds, {
- group = 0,
- }))
- eq("Invalid 'group': expected String or Integer, got Array", pcall_err(meths.get_autocmds, {
- group = {},
- }))
- eq("Invalid 'buffer': expected Integer or Array, got Boolean", pcall_err(meths.get_autocmds, {
- buffer = true,
- }))
- eq("Invalid 'event': expected String or Array", pcall_err(meths.get_autocmds, {
- event = true,
- }))
- eq("Invalid 'pattern': expected String or Array, got Boolean", pcall_err(meths.get_autocmds, {
- pattern = true,
- }))
+ eq(
+ "Invalid 'group': 9997999",
+ pcall_err(api.nvim_get_autocmds, {
+ group = 9997999,
+ })
+ )
+ eq(
+ "Invalid 'group': 'bogus'",
+ pcall_err(api.nvim_get_autocmds, {
+ group = 'bogus',
+ })
+ )
+ eq(
+ "Invalid 'group': 0",
+ pcall_err(api.nvim_get_autocmds, {
+ group = 0,
+ })
+ )
+ eq(
+ "Invalid 'group': expected String or Integer, got Array",
+ pcall_err(api.nvim_get_autocmds, {
+ group = {},
+ })
+ )
+ eq(
+ "Invalid 'buffer': expected Integer or Array, got Boolean",
+ pcall_err(api.nvim_get_autocmds, {
+ buffer = true,
+ })
+ )
+ eq(
+ "Invalid 'event': expected String or Array",
+ pcall_err(api.nvim_get_autocmds, {
+ event = true,
+ })
+ )
+ eq(
+ "Invalid 'pattern': expected String or Array, got Boolean",
+ pcall_err(api.nvim_get_autocmds, {
+ pattern = true,
+ })
+ )
end)
describe('events', function()
@@ -341,7 +408,7 @@ describe('autocmd api', function()
command [[au! InsertEnter]]
command [[au InsertEnter * :echo "1"]]
- local aus = meths.get_autocmds { event = "InsertEnter" }
+ local aus = api.nvim_get_autocmds { event = 'InsertEnter' }
eq(1, #aus)
end)
@@ -350,7 +417,7 @@ describe('autocmd api', function()
command [[au InsertEnter * :echo "1"]]
command [[au InsertEnter * :echo "2"]]
- local aus = meths.get_autocmds { event = "InsertEnter" }
+ local aus = api.nvim_get_autocmds { event = 'InsertEnter' }
eq(2, #aus)
end)
@@ -359,8 +426,8 @@ describe('autocmd api', function()
command [[au InsertEnter * :echo "1"]]
command [[au InsertEnter * :echo "2"]]
- local string_aus = meths.get_autocmds { event = "InsertEnter" }
- local array_aus = meths.get_autocmds { event = { "InsertEnter" } }
+ local string_aus = api.nvim_get_autocmds { event = 'InsertEnter' }
+ local array_aus = api.nvim_get_autocmds { event = { 'InsertEnter' } }
eq(string_aus, array_aus)
end)
@@ -370,7 +437,7 @@ describe('autocmd api', function()
command [[au InsertEnter * :echo "1"]]
command [[au InsertEnter * :echo "2"]]
- local aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } }
+ local aus = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } }
eq(2, #aus)
end)
@@ -384,7 +451,7 @@ describe('autocmd api', function()
\ })
]]
- local aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } }
+ local aus = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } }
local first = aus[1]
eq(first.id, nil)
@@ -392,8 +459,8 @@ describe('autocmd api', function()
local second = aus[2]
neq(second.id, nil)
- meths.del_autocmd(second.id)
- local new_aus = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } }
+ api.nvim_del_autocmd(second.id)
+ local new_aus = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } }
eq(1, #new_aus)
eq(first, new_aus[1])
end)
@@ -402,8 +469,16 @@ describe('autocmd api', function()
command [[au! InsertEnter]]
command [[au InsertEnter * :echo "1"]]
- local aus = meths.get_autocmds { event = "InsertEnter" }
- eq({ { buflocal = false, command = ':echo "1"', event = "InsertEnter", once = false, pattern = "*" } }, aus)
+ local aus = api.nvim_get_autocmds { event = 'InsertEnter' }
+ eq({
+ {
+ buflocal = false,
+ command = ':echo "1"',
+ event = 'InsertEnter',
+ once = false,
+ pattern = '*',
+ },
+ }, aus)
end)
it('works with buffer numbers', function()
@@ -412,77 +487,96 @@ describe('autocmd api', function()
command [[au InsertEnter <buffer=1> :echo "1"]]
command [[au InsertEnter <buffer=2> :echo "2"]]
- local aus = meths.get_autocmds { event = "InsertEnter", buffer = 0 }
- eq({{
- buffer = 2,
- buflocal = true,
- command = ':echo "2"',
- event = 'InsertEnter',
- once = false,
- pattern = '<buffer=2>',
- }}, aus)
-
- aus = meths.get_autocmds { event = "InsertEnter", buffer = 1 }
- eq({{
- buffer = 1,
- buflocal = true,
- command = ':echo "1"',
- event = "InsertEnter",
- once = false,
- pattern = "<buffer=1>",
- }}, aus)
-
- aus = meths.get_autocmds { event = "InsertEnter", buffer = { 1, 2 } }
- eq({{
- buffer = 1,
- buflocal = true,
- command = ':echo "1"',
- event = "InsertEnter",
- once = false,
- pattern = "<buffer=1>",
- }, {
- buffer = 2,
- buflocal = true,
- command = ':echo "2"',
- event = "InsertEnter",
- once = false,
- pattern = "<buffer=2>",
- }}, aus)
-
- eq("Invalid 'buffer': expected Integer or Array, got String", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = "foo" }))
- eq("Invalid 'buffer': expected Integer, got String", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { "foo", 42 } }))
- eq("Invalid buffer id: 42", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = { 42 } }))
+ local aus = api.nvim_get_autocmds { event = 'InsertEnter', buffer = 0 }
+ eq({
+ {
+ buffer = 2,
+ buflocal = true,
+ command = ':echo "2"',
+ event = 'InsertEnter',
+ once = false,
+ pattern = '<buffer=2>',
+ },
+ }, aus)
+
+ aus = api.nvim_get_autocmds { event = 'InsertEnter', buffer = 1 }
+ eq({
+ {
+ buffer = 1,
+ buflocal = true,
+ command = ':echo "1"',
+ event = 'InsertEnter',
+ once = false,
+ pattern = '<buffer=1>',
+ },
+ }, aus)
+
+ aus = api.nvim_get_autocmds { event = 'InsertEnter', buffer = { 1, 2 } }
+ eq({
+ {
+ buffer = 1,
+ buflocal = true,
+ command = ':echo "1"',
+ event = 'InsertEnter',
+ once = false,
+ pattern = '<buffer=1>',
+ },
+ {
+ buffer = 2,
+ buflocal = true,
+ command = ':echo "2"',
+ event = 'InsertEnter',
+ once = false,
+ pattern = '<buffer=2>',
+ },
+ }, aus)
+
+ eq(
+ "Invalid 'buffer': expected Integer or Array, got String",
+ pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = 'foo' })
+ )
+ eq(
+ "Invalid 'buffer': expected Integer, got String",
+ pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = { 'foo', 42 } })
+ )
+ eq(
+ 'Invalid buffer id: 42',
+ pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = { 42 } })
+ )
local bufs = {}
for _ = 1, 257 do
- table.insert(bufs, meths.create_buf(true, false))
+ table.insert(bufs, api.nvim_create_buf(true, false))
end
- eq("Too many buffers (maximum of 256)", pcall_err(meths.get_autocmds, { event = "InsertEnter", buffer = bufs }))
+ eq(
+ 'Too many buffers (maximum of 256)',
+ pcall_err(api.nvim_get_autocmds, { event = 'InsertEnter', buffer = bufs })
+ )
end)
it('returns autocmds when group is specified by id', function()
- local auid = meths.create_augroup("nvim_test_augroup", { clear = true })
- meths.create_autocmd("FileType", { group = auid, command = 'echo "1"' })
- meths.create_autocmd("FileType", { group = auid, command = 'echo "2"' })
+ local auid = api.nvim_create_augroup('nvim_test_augroup', { clear = true })
+ api.nvim_create_autocmd('FileType', { group = auid, command = 'echo "1"' })
+ api.nvim_create_autocmd('FileType', { group = auid, command = 'echo "2"' })
- local aus = meths.get_autocmds { group = auid }
+ local aus = api.nvim_get_autocmds { group = auid }
eq(2, #aus)
- local aus2 = meths.get_autocmds { group = auid, event = "InsertEnter" }
+ local aus2 = api.nvim_get_autocmds { group = auid, event = 'InsertEnter' }
eq(0, #aus2)
end)
it('returns autocmds when group is specified by name', function()
- local auname = "nvim_test_augroup"
- meths.create_augroup(auname, { clear = true })
- meths.create_autocmd("FileType", { group = auname, command = 'echo "1"' })
- meths.create_autocmd("FileType", { group = auname, command = 'echo "2"' })
+ local auname = 'nvim_test_augroup'
+ api.nvim_create_augroup(auname, { clear = true })
+ api.nvim_create_autocmd('FileType', { group = auname, command = 'echo "1"' })
+ api.nvim_create_autocmd('FileType', { group = auname, command = 'echo "2"' })
- local aus = meths.get_autocmds { group = auname }
+ local aus = api.nvim_get_autocmds { group = auname }
eq(2, #aus)
- local aus2 = meths.get_autocmds { group = auname, event = "InsertEnter" }
+ local aus2 = api.nvim_get_autocmds { group = auname, event = 'InsertEnter' }
eq(0, #aus2)
end)
@@ -510,12 +604,12 @@ describe('autocmd api', function()
-- 1 for the first buffer
-- 2 for First.md
-- 3-7 for the 5 we make in the autocmd
- eq({1, 2, 3, 4, 5, 6, 7}, bufs)
+ eq({ 1, 2, 3, 4, 5, 6, 7 }, bufs)
end)
it('can retrieve a callback from an autocmd', function()
local content = 'I Am A Callback'
- meths.set_var('content', content)
+ api.nvim_set_var('content', content)
local result = exec_lua([[
local cb = function() return vim.g.content end
@@ -534,12 +628,14 @@ describe('autocmd api', function()
}
]])
- eq("function", result.cb.type)
+ eq('function', result.cb.type)
eq(true, result.cb.can_retrieve)
end)
- it('will return an empty string as the command for an autocmd that uses a callback', function()
- local result = exec_lua([[
+ it(
+ 'will return an empty string as the command for an autocmd that uses a callback',
+ function()
+ local result = exec_lua([[
local callback = function() print 'I Am A Callback' end
vim.api.nvim_create_autocmd("BufWritePost", {
pattern = "*.py",
@@ -553,8 +649,9 @@ describe('autocmd api', function()
}
]])
- eq({ command = "", cbtype = 'function' }, result)
- end)
+ eq({ command = '', cbtype = 'function' }, result)
+ end
+ )
end)
describe('groups', function()
@@ -574,7 +671,7 @@ describe('autocmd api', function()
end)
it('returns all groups if no group is specified', function()
- local aus = meths.get_autocmds { event = "InsertEnter" }
+ local aus = api.nvim_get_autocmds { event = 'InsertEnter' }
if #aus ~= 4 then
eq({}, aus)
end
@@ -583,33 +680,34 @@ describe('autocmd api', function()
end)
it('returns only the group specified', function()
- local aus = meths.get_autocmds {
- event = "InsertEnter",
- group = "GroupOne",
+ local aus = api.nvim_get_autocmds {
+ event = 'InsertEnter',
+ group = 'GroupOne',
}
eq(1, #aus)
eq([[:echo "GroupOne:1"]], aus[1].command)
- eq("GroupOne", aus[1].group_name)
+ eq('GroupOne', aus[1].group_name)
end)
it('returns only the group specified, multiple values', function()
- local aus = meths.get_autocmds {
- event = "InsertEnter",
- group = "GroupTwo",
+ local aus = api.nvim_get_autocmds {
+ event = 'InsertEnter',
+ group = 'GroupTwo',
}
eq(2, #aus)
eq([[:echo "GroupTwo:2"]], aus[1].command)
- eq("GroupTwo", aus[1].group_name)
+ eq('GroupTwo', aus[1].group_name)
eq([[:echo "GroupTwo:3"]], aus[2].command)
- eq("GroupTwo", aus[2].group_name)
+ eq('GroupTwo', aus[2].group_name)
end)
end)
describe('groups: 2', function()
it('raises error for undefined augroup name', function()
- local success, code = unpack(meths.exec_lua([[
+ local success, code = unpack(api.nvim_exec_lua(
+ [[
return {pcall(function()
vim.api.nvim_create_autocmd("FileType", {
pattern = "*",
@@ -617,14 +715,17 @@ describe('autocmd api', function()
command = "echo 'hello'",
})
end)}
- ]], {}))
+ ]],
+ {}
+ ))
eq(false, success)
matches("Invalid 'group': 'NotDefined'", code)
end)
it('raises error for undefined augroup id', function()
- local success, code = unpack(meths.exec_lua([[
+ local success, code = unpack(api.nvim_exec_lua(
+ [[
return {pcall(function()
-- Make sure the augroup is deleted
vim.api.nvim_del_augroup_by_id(1)
@@ -635,14 +736,17 @@ describe('autocmd api', function()
command = "echo 'hello'",
})
end)}
- ]], {}))
+ ]],
+ {}
+ ))
eq(false, success)
matches("Invalid 'group': 1", code)
end)
it('raises error for invalid group type', function()
- local success, code = unpack(meths.exec_lua([[
+ local success, code = unpack(api.nvim_exec_lua(
+ [[
return {pcall(function()
vim.api.nvim_create_autocmd("FileType", {
pattern = "*",
@@ -650,21 +754,26 @@ describe('autocmd api', function()
command = "echo 'hello'",
})
end)}
- ]], {}))
+ ]],
+ {}
+ ))
eq(false, success)
matches("Invalid 'group': expected String or Integer, got Boolean", code)
end)
it('raises error for invalid pattern array', function()
- local success, code = unpack(meths.exec_lua([[
+ local success, code = unpack(api.nvim_exec_lua(
+ [[
return {pcall(function()
vim.api.nvim_create_autocmd("FileType", {
pattern = {{}},
command = "echo 'hello'",
})
end)}
- ]], {}))
+ ]],
+ {}
+ ))
eq(false, success)
matches("Invalid 'pattern' item: expected String, got Array", code)
@@ -683,9 +792,9 @@ describe('autocmd api', function()
end)
it('returns for literal match', function()
- local aus = meths.get_autocmds {
- event = "InsertEnter",
- pattern = "*"
+ local aus = api.nvim_get_autocmds {
+ event = 'InsertEnter',
+ pattern = '*',
}
eq(1, #aus)
@@ -694,9 +803,9 @@ describe('autocmd api', function()
it('returns for multiple matches', function()
-- vim.api.nvim_get_autocmds
- local aus = meths.get_autocmds {
- event = "InsertEnter",
- pattern = { "*.one", "*.two" },
+ local aus = api.nvim_get_autocmds {
+ event = 'InsertEnter',
+ pattern = { '*.one', '*.two' },
}
eq(3, #aus)
@@ -706,19 +815,19 @@ describe('autocmd api', function()
end)
it('should work for buffer autocmds', function()
- local normalized_aus = meths.get_autocmds {
- event = "InsertEnter",
- pattern = "<buffer=1>",
+ local normalized_aus = api.nvim_get_autocmds {
+ event = 'InsertEnter',
+ pattern = '<buffer=1>',
}
- local raw_aus = meths.get_autocmds {
- event = "InsertEnter",
- pattern = "<buffer>",
+ local raw_aus = api.nvim_get_autocmds {
+ event = 'InsertEnter',
+ pattern = '<buffer>',
}
- local zero_aus = meths.get_autocmds {
- event = "InsertEnter",
- pattern = "<buffer=0>",
+ local zero_aus = api.nvim_get_autocmds {
+ event = 'InsertEnter',
+ pattern = '<buffer=0>',
}
eq(normalized_aus, raw_aus)
@@ -730,165 +839,186 @@ describe('autocmd api', function()
describe('nvim_exec_autocmds', function()
it('validation', function()
- eq("Invalid 'group': 9997999", pcall_err(meths.exec_autocmds, 'FileType', {
- group = 9997999,
- }))
- eq("Invalid 'group': 'bogus'", pcall_err(meths.exec_autocmds, 'FileType', {
- group = 'bogus',
- }))
- eq("Invalid 'group': expected String or Integer, got Array", pcall_err(meths.exec_autocmds, 'FileType', {
- group = {},
- }))
- eq("Invalid 'group': 0", pcall_err(meths.exec_autocmds, 'FileType', {
- group = 0,
- }))
- eq("Invalid 'buffer': expected Buffer, got Array", pcall_err(meths.exec_autocmds, 'FileType', {
- buffer = {},
- }))
- eq("Invalid 'event' item: expected String, got Array", pcall_err(meths.exec_autocmds,
- {'FileType', {}}, {}))
+ eq(
+ "Invalid 'group': 9997999",
+ pcall_err(api.nvim_exec_autocmds, 'FileType', {
+ group = 9997999,
+ })
+ )
+ eq(
+ "Invalid 'group': 'bogus'",
+ pcall_err(api.nvim_exec_autocmds, 'FileType', {
+ group = 'bogus',
+ })
+ )
+ eq(
+ "Invalid 'group': expected String or Integer, got Array",
+ pcall_err(api.nvim_exec_autocmds, 'FileType', {
+ group = {},
+ })
+ )
+ eq(
+ "Invalid 'group': 0",
+ pcall_err(api.nvim_exec_autocmds, 'FileType', {
+ group = 0,
+ })
+ )
+ eq(
+ "Invalid 'buffer': expected Buffer, got Array",
+ pcall_err(api.nvim_exec_autocmds, 'FileType', {
+ buffer = {},
+ })
+ )
+ eq(
+ "Invalid 'event' item: expected String, got Array",
+ pcall_err(api.nvim_exec_autocmds, { 'FileType', {} }, {})
+ )
end)
- it("can trigger builtin autocmds", function()
- meths.set_var("autocmd_executed", false)
+ it('can trigger builtin autocmds', function()
+ api.nvim_set_var('autocmd_executed', false)
- meths.create_autocmd("BufReadPost", {
- pattern = "*",
- command = "let g:autocmd_executed = v:true",
+ api.nvim_create_autocmd('BufReadPost', {
+ pattern = '*',
+ command = 'let g:autocmd_executed = v:true',
})
- eq(false, meths.get_var("autocmd_executed"))
- meths.exec_autocmds("BufReadPost", {})
- eq(true, meths.get_var("autocmd_executed"))
+ eq(false, api.nvim_get_var('autocmd_executed'))
+ api.nvim_exec_autocmds('BufReadPost', {})
+ eq(true, api.nvim_get_var('autocmd_executed'))
end)
- it("can trigger multiple patterns", function()
- meths.set_var("autocmd_executed", 0)
+ it('can trigger multiple patterns', function()
+ api.nvim_set_var('autocmd_executed', 0)
- meths.create_autocmd("BufReadPost", {
- pattern = "*",
- command = "let g:autocmd_executed += 1",
+ api.nvim_create_autocmd('BufReadPost', {
+ pattern = '*',
+ command = 'let g:autocmd_executed += 1',
})
- meths.exec_autocmds("BufReadPost", { pattern = { "*.lua", "*.vim" } })
- eq(2, meths.get_var("autocmd_executed"))
+ api.nvim_exec_autocmds('BufReadPost', { pattern = { '*.lua', '*.vim' } })
+ eq(2, api.nvim_get_var('autocmd_executed'))
- meths.create_autocmd("BufReadPre", {
- pattern = { "bar", "foo" },
- command = "let g:autocmd_executed += 10",
+ api.nvim_create_autocmd('BufReadPre', {
+ pattern = { 'bar', 'foo' },
+ command = 'let g:autocmd_executed += 10',
})
- meths.exec_autocmds("BufReadPre", { pattern = { "foo", "bar", "baz", "frederick" }})
- eq(22, meths.get_var("autocmd_executed"))
+ api.nvim_exec_autocmds('BufReadPre', { pattern = { 'foo', 'bar', 'baz', 'frederick' } })
+ eq(22, api.nvim_get_var('autocmd_executed'))
end)
- it("can pass the buffer", function()
- meths.set_var("buffer_executed", -1)
- eq(-1, meths.get_var("buffer_executed"))
+ it('can pass the buffer', function()
+ api.nvim_set_var('buffer_executed', -1)
+ eq(-1, api.nvim_get_var('buffer_executed'))
- meths.create_autocmd("BufLeave", {
- pattern = "*",
+ api.nvim_create_autocmd('BufLeave', {
+ pattern = '*',
command = 'let g:buffer_executed = +expand("<abuf>")',
})
-- Doesn't execute for other non-matching events
- meths.exec_autocmds("CursorHold", { buffer = 1 })
- eq(-1, meths.get_var("buffer_executed"))
+ api.nvim_exec_autocmds('CursorHold', { buffer = 1 })
+ eq(-1, api.nvim_get_var('buffer_executed'))
- meths.exec_autocmds("BufLeave", { buffer = 1 })
- eq(1, meths.get_var("buffer_executed"))
+ api.nvim_exec_autocmds('BufLeave', { buffer = 1 })
+ eq(1, api.nvim_get_var('buffer_executed'))
end)
- it("can pass the filename, pattern match", function()
- meths.set_var("filename_executed", 'none')
- eq('none', meths.get_var("filename_executed"))
+ it('can pass the filename, pattern match', function()
+ api.nvim_set_var('filename_executed', 'none')
+ eq('none', api.nvim_get_var('filename_executed'))
- meths.create_autocmd("BufEnter", {
- pattern = "*.py",
+ api.nvim_create_autocmd('BufEnter', {
+ pattern = '*.py',
command = 'let g:filename_executed = expand("<afile>")',
})
-- Doesn't execute for other non-matching events
- meths.exec_autocmds("CursorHold", { buffer = 1 })
- eq('none', meths.get_var("filename_executed"))
+ api.nvim_exec_autocmds('CursorHold', { buffer = 1 })
+ eq('none', api.nvim_get_var('filename_executed'))
- meths.command('edit __init__.py')
- eq('__init__.py', meths.get_var("filename_executed"))
+ command('edit __init__.py')
+ eq('__init__.py', api.nvim_get_var('filename_executed'))
end)
it('cannot pass buf and fname', function()
- local ok = pcall(meths.exec_autocmds, "BufReadPre", { pattern = "literally_cannot_error.rs", buffer = 1 })
+ local ok = pcall(
+ api.nvim_exec_autocmds,
+ 'BufReadPre',
+ { pattern = 'literally_cannot_error.rs', buffer = 1 }
+ )
eq(false, ok)
end)
- it("can pass the filename, exact match", function()
- meths.set_var("filename_executed", 'none')
- eq('none', meths.get_var("filename_executed"))
+ it('can pass the filename, exact match', function()
+ api.nvim_set_var('filename_executed', 'none')
+ eq('none', api.nvim_get_var('filename_executed'))
- meths.command('edit other_file.txt')
- meths.command('edit __init__.py')
- eq('none', meths.get_var("filename_executed"))
+ command('edit other_file.txt')
+ command('edit __init__.py')
+ eq('none', api.nvim_get_var('filename_executed'))
- meths.create_autocmd("CursorHoldI", {
- pattern = "__init__.py",
+ api.nvim_create_autocmd('CursorHoldI', {
+ pattern = '__init__.py',
command = 'let g:filename_executed = expand("<afile>")',
})
-- Doesn't execute for other non-matching events
- meths.exec_autocmds("CursorHoldI", { buffer = 1 })
- eq('none', meths.get_var("filename_executed"))
+ api.nvim_exec_autocmds('CursorHoldI', { buffer = 1 })
+ eq('none', api.nvim_get_var('filename_executed'))
- meths.exec_autocmds("CursorHoldI", { buffer = meths.get_current_buf() })
- eq('__init__.py', meths.get_var("filename_executed"))
+ api.nvim_exec_autocmds('CursorHoldI', { buffer = api.nvim_get_current_buf() })
+ eq('__init__.py', api.nvim_get_var('filename_executed'))
-- Reset filename
- meths.set_var("filename_executed", 'none')
+ api.nvim_set_var('filename_executed', 'none')
- meths.exec_autocmds("CursorHoldI", { pattern = '__init__.py' })
- eq('__init__.py', meths.get_var("filename_executed"))
+ api.nvim_exec_autocmds('CursorHoldI', { pattern = '__init__.py' })
+ eq('__init__.py', api.nvim_get_var('filename_executed'))
end)
- it("works with user autocmds", function()
- meths.set_var("matched", 'none')
+ it('works with user autocmds', function()
+ api.nvim_set_var('matched', 'none')
- meths.create_autocmd("User", {
- pattern = "TestCommand",
- command = 'let g:matched = "matched"'
+ api.nvim_create_autocmd('User', {
+ pattern = 'TestCommand',
+ command = 'let g:matched = "matched"',
})
- meths.exec_autocmds("User", { pattern = "OtherCommand" })
- eq('none', meths.get_var('matched'))
- meths.exec_autocmds("User", { pattern = "TestCommand" })
- eq('matched', meths.get_var('matched'))
+ api.nvim_exec_autocmds('User', { pattern = 'OtherCommand' })
+ eq('none', api.nvim_get_var('matched'))
+ api.nvim_exec_autocmds('User', { pattern = 'TestCommand' })
+ eq('matched', api.nvim_get_var('matched'))
end)
it('can pass group by id', function()
- meths.set_var("group_executed", false)
+ api.nvim_set_var('group_executed', false)
- local auid = meths.create_augroup("nvim_test_augroup", { clear = true })
- meths.create_autocmd("FileType", {
+ local auid = api.nvim_create_augroup('nvim_test_augroup', { clear = true })
+ api.nvim_create_autocmd('FileType', {
group = auid,
command = 'let g:group_executed = v:true',
})
- eq(false, meths.get_var("group_executed"))
- meths.exec_autocmds("FileType", { group = auid })
- eq(true, meths.get_var("group_executed"))
+ eq(false, api.nvim_get_var('group_executed'))
+ api.nvim_exec_autocmds('FileType', { group = auid })
+ eq(true, api.nvim_get_var('group_executed'))
end)
it('can pass group by name', function()
- meths.set_var("group_executed", false)
+ api.nvim_set_var('group_executed', false)
- local auname = "nvim_test_augroup"
- meths.create_augroup(auname, { clear = true })
- meths.create_autocmd("FileType", {
+ local auname = 'nvim_test_augroup'
+ api.nvim_create_augroup(auname, { clear = true })
+ api.nvim_create_autocmd('FileType', {
group = auname,
command = 'let g:group_executed = v:true',
})
- eq(false, meths.get_var("group_executed"))
- meths.exec_autocmds("FileType", { group = auname })
- eq(true, meths.get_var("group_executed"))
+ eq(false, api.nvim_get_var('group_executed'))
+ api.nvim_exec_autocmds('FileType', { group = auname })
+ eq(true, api.nvim_get_var('group_executed'))
end)
end)
@@ -896,39 +1026,39 @@ describe('autocmd api', function()
before_each(function()
clear()
- meths.set_var('executed', 0)
+ api.nvim_set_var('executed', 0)
end)
local make_counting_autocmd = function(opts)
opts = opts or {}
local resulting = {
- pattern = "*",
- command = "let g:executed = g:executed + 1",
+ pattern = '*',
+ command = 'let g:executed = g:executed + 1',
}
resulting.group = opts.group
resulting.once = opts.once
- meths.create_autocmd("FileType", resulting)
+ api.nvim_create_autocmd('FileType', resulting)
end
local set_ft = function(ft)
- ft = ft or "txt"
- source(string.format("set filetype=%s", ft))
+ ft = ft or 'txt'
+ source(string.format('set filetype=%s', ft))
end
local get_executed_count = function()
- return meths.get_var('executed')
+ return api.nvim_get_var('executed')
end
it('can be added in a group', function()
- local augroup = "TestGroup"
- meths.create_augroup(augroup, { clear = true })
+ local augroup = 'TestGroup'
+ api.nvim_create_augroup(augroup, { clear = true })
make_counting_autocmd { group = augroup }
- set_ft("txt")
- set_ft("python")
+ set_ft('txt')
+ set_ft('python')
eq(2, get_executed_count())
end)
@@ -943,7 +1073,7 @@ describe('autocmd api', function()
end)
it('handles ++once', function()
- make_counting_autocmd {once = true}
+ make_counting_autocmd { once = true }
set_ft('txt')
set_ft('help')
set_ft('txt')
@@ -953,9 +1083,9 @@ describe('autocmd api', function()
end)
it('errors on unexpected keys', function()
- local success, code = pcall(meths.create_autocmd, "FileType", {
- pattern = "*",
- not_a_valid_key = "NotDefined",
+ local success, code = pcall(api.nvim_create_autocmd, 'FileType', {
+ pattern = '*',
+ not_a_valid_key = 'NotDefined',
})
eq(false, success)
@@ -963,24 +1093,35 @@ describe('autocmd api', function()
end)
it('can execute simple callback', function()
- exec_lua([[
+ exec_lua(
+ [[
vim.g.executed = false
vim.api.nvim_create_autocmd("FileType", {
pattern = "*",
callback = function() vim.g.executed = true end,
})
- ]], {})
-
-
- eq(true, exec_lua([[
+ ]],
+ {}
+ )
+
+ eq(
+ true,
+ exec_lua(
+ [[
vim.cmd "set filetype=txt"
return vim.g.executed
- ]], {}))
+ ]],
+ {}
+ )
+ )
end)
it('calls multiple lua callbacks for the same autocmd execution', function()
- eq(4, exec_lua([[
+ eq(
+ 4,
+ exec_lua(
+ [[
local count = 0
local counter = function()
count = count + 1
@@ -1000,7 +1141,10 @@ describe('autocmd api', function()
vim.cmd "set filetype=txt"
return count
- ]], {}))
+ ]],
+ {}
+ )
+ )
end)
it('properly releases functions with ++once', function()
@@ -1030,108 +1174,112 @@ describe('autocmd api', function()
command [[set filetype=txt]]
eq(1, exec_lua([[return OnceCount]], {}))
- eq(0, exec_lua([[
+ eq(
+ 0,
+ exec_lua([[
local count = 0
for _ in pairs(WeakTable) do
count = count + 1
end
return count
- ]]), "Should have no keys remaining")
+ ]]),
+ 'Should have no keys remaining'
+ )
end)
it('groups can be cleared', function()
- local augroup = "TestGroup"
- meths.create_augroup(augroup, { clear = true })
- meths.create_autocmd("FileType", {
+ local augroup = 'TestGroup'
+ api.nvim_create_augroup(augroup, { clear = true })
+ api.nvim_create_autocmd('FileType', {
group = augroup,
- command = "let g:executed = g:executed + 1"
+ command = 'let g:executed = g:executed + 1',
})
- set_ft("txt")
- set_ft("txt")
- eq(2, get_executed_count(), "should only count twice")
+ set_ft('txt')
+ set_ft('txt')
+ eq(2, get_executed_count(), 'should only count twice')
- meths.create_augroup(augroup, { clear = true })
- eq({}, meths.get_autocmds { group = augroup })
+ api.nvim_create_augroup(augroup, { clear = true })
+ eq({}, api.nvim_get_autocmds { group = augroup })
- set_ft("txt")
- set_ft("txt")
- eq(2, get_executed_count(), "No additional counts")
+ set_ft('txt')
+ set_ft('txt')
+ eq(2, get_executed_count(), 'No additional counts')
end)
it('can delete non-existent groups with pcall', function()
- eq(false, exec_lua[[return pcall(vim.api.nvim_del_augroup_by_name, 'noexist')]])
- eq('Vim:E367: No such group: "noexist"', pcall_err(meths.del_augroup_by_name, 'noexist'))
+ eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_name, 'noexist')]])
+ eq('Vim:E367: No such group: "noexist"', pcall_err(api.nvim_del_augroup_by_name, 'noexist'))
- eq(false, exec_lua[[return pcall(vim.api.nvim_del_augroup_by_id, -12342)]])
- eq('Vim:E367: No such group: "--Deleted--"', pcall_err(meths.del_augroup_by_id, -12312))
+ eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_id, -12342)]])
+ eq('Vim:E367: No such group: "--Deleted--"', pcall_err(api.nvim_del_augroup_by_id, -12312))
- eq(false, exec_lua[[return pcall(vim.api.nvim_del_augroup_by_id, 0)]])
- eq('Vim:E367: No such group: "[NULL]"', pcall_err(meths.del_augroup_by_id, 0))
+ eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_id, 0)]])
+ eq('Vim:E367: No such group: "[NULL]"', pcall_err(api.nvim_del_augroup_by_id, 0))
- eq(false, exec_lua[[return pcall(vim.api.nvim_del_augroup_by_id, 12342)]])
- eq('Vim:E367: No such group: "[NULL]"', pcall_err(meths.del_augroup_by_id, 12312))
+ eq(false, exec_lua [[return pcall(vim.api.nvim_del_augroup_by_id, 12342)]])
+ eq('Vim:E367: No such group: "[NULL]"', pcall_err(api.nvim_del_augroup_by_id, 12312))
end)
it('groups work with once', function()
- local augroup = "TestGroup"
+ local augroup = 'TestGroup'
- meths.create_augroup(augroup, { clear = true })
+ api.nvim_create_augroup(augroup, { clear = true })
make_counting_autocmd { group = augroup, once = true }
- set_ft("txt")
- set_ft("python")
+ set_ft('txt')
+ set_ft('python')
eq(1, get_executed_count())
end)
it('autocmds can be registered multiple times.', function()
- local augroup = "TestGroup"
+ local augroup = 'TestGroup'
- meths.create_augroup(augroup, { clear = true })
+ api.nvim_create_augroup(augroup, { clear = true })
make_counting_autocmd { group = augroup, once = false }
make_counting_autocmd { group = augroup, once = false }
make_counting_autocmd { group = augroup, once = false }
- set_ft("txt")
- set_ft("python")
+ set_ft('txt')
+ set_ft('python')
eq(3 * 2, get_executed_count())
end)
it('can be deleted', function()
- local augroup = "WillBeDeleted"
+ local augroup = 'WillBeDeleted'
- meths.create_augroup(augroup, { clear = true })
- meths.create_autocmd({"FileType"}, {
- pattern = "*",
+ api.nvim_create_augroup(augroup, { clear = true })
+ api.nvim_create_autocmd({ 'FileType' }, {
+ pattern = '*',
command = "echo 'does not matter'",
})
-- Clears the augroup from before, which erases the autocmd
- meths.create_augroup(augroup, { clear = true })
+ api.nvim_create_augroup(augroup, { clear = true })
- local result = #meths.get_autocmds { group = augroup }
+ local result = #api.nvim_get_autocmds { group = augroup }
eq(0, result)
end)
it('can be used for buffer local autocmds', function()
- local augroup = "WillBeDeleted"
+ local augroup = 'WillBeDeleted'
- meths.set_var("value_set", false)
+ api.nvim_set_var('value_set', false)
- meths.create_augroup(augroup, { clear = true })
- meths.create_autocmd("FileType", {
- pattern = "<buffer>",
- command = "let g:value_set = v:true",
+ api.nvim_create_augroup(augroup, { clear = true })
+ api.nvim_create_autocmd('FileType', {
+ pattern = '<buffer>',
+ command = 'let g:value_set = v:true',
})
- command "new"
- command "set filetype=python"
+ command 'new'
+ command 'set filetype=python'
- eq(false, meths.get_var("value_set"))
+ eq(false, api.nvim_get_var('value_set'))
end)
it('can accept vimscript functions', function()
@@ -1154,118 +1302,124 @@ describe('autocmd api', function()
set filetype=txt
]]
- eq(2, meths.get_var("vimscript_executed"))
+ eq(2, api.nvim_get_var('vimscript_executed'))
end)
end)
describe('augroup!', function()
it('legacy: should clear and not return any autocmds for delete groups', function()
- command('augroup TEMP_A')
- command(' autocmd! BufReadPost *.py :echo "Hello"')
- command('augroup END')
+ command('augroup TEMP_A')
+ command(' autocmd! BufReadPost *.py :echo "Hello"')
+ command('augroup END')
- command('augroup! TEMP_A')
+ command('augroup! TEMP_A')
- eq(false, pcall(meths.get_autocmds, { group = 'TEMP_A' }))
+ eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_A' }))
- -- For some reason, augroup! doesn't clear the autocmds themselves, which is just wild
- -- but we managed to keep this behavior.
- eq(1, #meths.get_autocmds { event = 'BufReadPost' })
+ -- For some reason, augroup! doesn't clear the autocmds themselves, which is just wild
+ -- but we managed to keep this behavior.
+ eq(1, #api.nvim_get_autocmds { event = 'BufReadPost' })
end)
it('legacy: remove augroups that have no autocmds', function()
- command('augroup TEMP_AB')
- command('augroup END')
+ command('augroup TEMP_AB')
+ command('augroup END')
- command('augroup! TEMP_AB')
+ command('augroup! TEMP_AB')
- eq(false, pcall(meths.get_autocmds, { group = 'TEMP_AB' }))
- eq(0, #meths.get_autocmds { event = 'BufReadPost' })
+ eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_AB' }))
+ eq(0, #api.nvim_get_autocmds { event = 'BufReadPost' })
end)
it('legacy: multiple remove and add augroup', function()
- command('augroup TEMP_ABC')
- command(' au!')
- command(' autocmd BufReadPost *.py echo "Hello"')
- command('augroup END')
+ command('augroup TEMP_ABC')
+ command(' au!')
+ command(' autocmd BufReadPost *.py echo "Hello"')
+ command('augroup END')
- command('augroup! TEMP_ABC')
+ command('augroup! TEMP_ABC')
- -- Should still have one autocmd :'(
- local aus = meths.get_autocmds { event = 'BufReadPost' }
- eq(1, #aus, aus)
+ -- Should still have one autocmd :'(
+ local aus = api.nvim_get_autocmds { event = 'BufReadPost' }
+ eq(1, #aus, aus)
- command('augroup TEMP_ABC')
- command(' au!')
- command(' autocmd BufReadPost *.py echo "Hello"')
- command('augroup END')
+ command('augroup TEMP_ABC')
+ command(' au!')
+ command(' autocmd BufReadPost *.py echo "Hello"')
+ command('augroup END')
- -- Should now have two autocmds :'(
- aus = meths.get_autocmds { event = 'BufReadPost' }
- eq(2, #aus, aus)
+ -- Should now have two autocmds :'(
+ aus = api.nvim_get_autocmds { event = 'BufReadPost' }
+ eq(2, #aus, aus)
- command('augroup! TEMP_ABC')
+ command('augroup! TEMP_ABC')
- eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABC' }))
- eq(2, #meths.get_autocmds { event = 'BufReadPost' })
+ eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_ABC' }))
+ eq(2, #api.nvim_get_autocmds { event = 'BufReadPost' })
end)
it('api: should clear and not return any autocmds for delete groups by id', function()
- command('augroup TEMP_ABCD')
- command('autocmd! BufReadPost *.py :echo "Hello"')
- command('augroup END')
+ command('augroup TEMP_ABCD')
+ command('autocmd! BufReadPost *.py :echo "Hello"')
+ command('augroup END')
- local augroup_id = meths.create_augroup("TEMP_ABCD", { clear = false })
- meths.del_augroup_by_id(augroup_id)
+ local augroup_id = api.nvim_create_augroup('TEMP_ABCD', { clear = false })
+ api.nvim_del_augroup_by_id(augroup_id)
- -- For good reason, we kill all the autocmds from del_augroup,
- -- so now this works as expected
- eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABCD' }))
- eq(0, #meths.get_autocmds { event = 'BufReadPost' })
+ -- For good reason, we kill all the autocmds from del_augroup,
+ -- so now this works as expected
+ eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_ABCD' }))
+ eq(0, #api.nvim_get_autocmds { event = 'BufReadPost' })
end)
it('api: should clear and not return any autocmds for delete groups by name', function()
- command('augroup TEMP_ABCDE')
- command('autocmd! BufReadPost *.py :echo "Hello"')
- command('augroup END')
+ command('augroup TEMP_ABCDE')
+ command('autocmd! BufReadPost *.py :echo "Hello"')
+ command('augroup END')
- meths.del_augroup_by_name("TEMP_ABCDE")
+ api.nvim_del_augroup_by_name('TEMP_ABCDE')
- -- For good reason, we kill all the autocmds from del_augroup,
- -- so now this works as expected
- eq(false, pcall(meths.get_autocmds, { group = 'TEMP_ABCDE' }))
- eq(0, #meths.get_autocmds { event = 'BufReadPost' })
+ -- For good reason, we kill all the autocmds from del_augroup,
+ -- so now this works as expected
+ eq(false, pcall(api.nvim_get_autocmds, { group = 'TEMP_ABCDE' }))
+ eq(0, #api.nvim_get_autocmds { event = 'BufReadPost' })
end)
end)
describe('nvim_clear_autocmds', function()
it('validation', function()
- eq("Cannot use both 'pattern' and 'buffer'", pcall_err(meths.clear_autocmds, {
- pattern = '*',
- buffer = 42,
- }))
- eq("Invalid 'event' item: expected String, got Array", pcall_err(meths.clear_autocmds, {
- event = {'FileType', {}}
- }))
- eq("Invalid 'group': 0", pcall_err(meths.clear_autocmds, {group = 0}))
+ eq(
+ "Cannot use both 'pattern' and 'buffer'",
+ pcall_err(api.nvim_clear_autocmds, {
+ pattern = '*',
+ buffer = 42,
+ })
+ )
+ eq(
+ "Invalid 'event' item: expected String, got Array",
+ pcall_err(api.nvim_clear_autocmds, {
+ event = { 'FileType', {} },
+ })
+ )
+ eq("Invalid 'group': 0", pcall_err(api.nvim_clear_autocmds, { group = 0 }))
end)
it('should clear based on event + pattern', function()
command('autocmd InsertEnter *.py :echo "Python can be cool sometimes"')
command('autocmd InsertEnter *.txt :echo "Text Files Are Cool"')
- local search = { event = "InsertEnter", pattern = "*.txt" }
- local before_delete = meths.get_autocmds(search)
+ local search = { event = 'InsertEnter', pattern = '*.txt' }
+ local before_delete = api.nvim_get_autocmds(search)
eq(1, #before_delete)
- local before_delete_all = meths.get_autocmds { event = search.event }
+ local before_delete_all = api.nvim_get_autocmds { event = search.event }
eq(2, #before_delete_all)
- meths.clear_autocmds(search)
- local after_delete = meths.get_autocmds(search)
+ api.nvim_clear_autocmds(search)
+ local after_delete = api.nvim_get_autocmds(search)
eq(0, #after_delete)
- local after_delete_all = meths.get_autocmds { event = search.event }
+ local after_delete_all = api.nvim_get_autocmds { event = search.event }
eq(1, #after_delete_all)
end)
@@ -1273,12 +1427,12 @@ describe('autocmd api', function()
command('autocmd InsertEnter *.py :echo "Python can be cool sometimes"')
command('autocmd InsertEnter *.txt :echo "Text Files Are Cool"')
- local search = { event = "InsertEnter"}
- local before_delete = meths.get_autocmds(search)
+ local search = { event = 'InsertEnter' }
+ local before_delete = api.nvim_get_autocmds(search)
eq(2, #before_delete)
- meths.clear_autocmds(search)
- local after_delete = meths.get_autocmds(search)
+ api.nvim_clear_autocmds(search)
+ local after_delete = api.nvim_get_autocmds(search)
eq(0, #after_delete)
end)
@@ -1288,17 +1442,18 @@ describe('autocmd api', function()
command('autocmd InsertEnter *.TestPat2 :echo "Enter 2"')
command('autocmd InsertLeave *.TestPat2 :echo "Leave 2"')
- local search = { pattern = "*.TestPat1"}
- local before_delete = meths.get_autocmds(search)
+ local search = { pattern = '*.TestPat1' }
+ local before_delete = api.nvim_get_autocmds(search)
eq(2, #before_delete)
- local before_delete_events = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } }
+ local before_delete_events =
+ api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } }
eq(4, #before_delete_events)
- meths.clear_autocmds(search)
- local after_delete = meths.get_autocmds(search)
+ api.nvim_clear_autocmds(search)
+ local after_delete = api.nvim_get_autocmds(search)
eq(0, #after_delete)
- local after_delete_events = meths.get_autocmds { event = { "InsertEnter", "InsertLeave" } }
+ local after_delete_events = api.nvim_get_autocmds { event = { 'InsertEnter', 'InsertLeave' } }
eq(2, #after_delete_events)
end)
@@ -1307,14 +1462,14 @@ describe('autocmd api', function()
command('autocmd InsertEnter <buffer> :echo "Enter Buffer"')
command('autocmd InsertEnter *.TestPat1 :echo "Enter Pattern"')
- local search = { event = "InsertEnter" }
- local before_delete = meths.get_autocmds(search)
+ local search = { event = 'InsertEnter' }
+ local before_delete = api.nvim_get_autocmds(search)
eq(2, #before_delete)
- meths.clear_autocmds { buffer = 0 }
- local after_delete = meths.get_autocmds(search)
+ api.nvim_clear_autocmds { buffer = 0 }
+ local after_delete = api.nvim_get_autocmds(search)
eq(1, #after_delete)
- eq("*.TestPat1", after_delete[1].pattern)
+ eq('*.TestPat1', after_delete[1].pattern)
end)
it('should allow clearing by buffer and group', function()
@@ -1324,18 +1479,18 @@ describe('autocmd api', function()
command(' autocmd InsertEnter *.TestPat1 :echo "Enter Pattern"')
command('augroup END')
- local search = { event = "InsertEnter", group = "TestNvimClearAutocmds" }
- local before_delete = meths.get_autocmds(search)
+ local search = { event = 'InsertEnter', group = 'TestNvimClearAutocmds' }
+ local before_delete = api.nvim_get_autocmds(search)
eq(2, #before_delete)
-- Doesn't clear without passing group.
- meths.clear_autocmds { buffer = 0 }
- local without_group = meths.get_autocmds(search)
+ api.nvim_clear_autocmds { buffer = 0 }
+ local without_group = api.nvim_get_autocmds(search)
eq(2, #without_group)
-- Doesn't clear with passing group.
- meths.clear_autocmds { buffer = 0, group = search.group }
- local with_group = meths.get_autocmds(search)
+ api.nvim_clear_autocmds { buffer = 0, group = search.group }
+ local with_group = api.nvim_get_autocmds(search)
eq(1, #with_group)
end)
end)
diff --git a/test/functional/api/buffer_spec.lua b/test/functional/api/buffer_spec.lua
index 6ed9aa574a..78d220ff57 100644
--- a/test/functional/api/buffer_spec.lua
+++ b/test/functional/api/buffer_spec.lua
@@ -1,19 +1,18 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer
-local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq
-local curbufmeths, ok = helpers.curbufmeths, helpers.ok
+local clear = helpers.clear
+local eq = helpers.eq
+local ok = helpers.ok
local describe_lua_and_rpc = helpers.describe_lua_and_rpc(describe)
-local meths = helpers.meths
-local funcs = helpers.funcs
+local api = helpers.api
+local fn = helpers.fn
local request = helpers.request
local exc_exec = helpers.exc_exec
local exec_lua = helpers.exec_lua
local feed_command = helpers.feed_command
local insert = helpers.insert
-local NIL = helpers.NIL
+local NIL = vim.NIL
local command = helpers.command
-local bufmeths = helpers.bufmeths
local feed = helpers.feed
local pcall_err = helpers.pcall_err
local assert_alive = helpers.assert_alive
@@ -23,16 +22,15 @@ describe('api/buf', function()
-- access deprecated functions
local function curbuf_depr(method, ...)
- return request('buffer_'..method, 0, ...)
+ return request('buffer_' .. method, 0, ...)
end
-
describe('nvim_buf_set_lines, nvim_buf_line_count', function()
it('deprecated forms', function()
eq(1, curbuf_depr('line_count'))
- curbuf_depr('insert', -1, {'line'})
+ curbuf_depr('insert', -1, { 'line' })
eq(2, curbuf_depr('line_count'))
- curbuf_depr('insert', -1, {'line'})
+ curbuf_depr('insert', -1, { 'line' })
eq(3, curbuf_depr('line_count'))
curbuf_depr('del_line', -1)
eq(2, curbuf_depr('line_count'))
@@ -43,108 +41,114 @@ describe('api/buf', function()
end)
it("doesn't crash just after set undolevels=1 #24894", function()
- local buf = meths.create_buf(false, true)
- meths.buf_set_option(buf, 'undolevels', -1)
- meths.buf_set_lines(buf, 0, 1, false, { })
+ local buf = api.nvim_create_buf(false, true)
+ api.nvim_buf_set_option(buf, 'undolevels', -1)
+ api.nvim_buf_set_lines(buf, 0, 1, false, {})
assert_alive()
end)
it('cursor position is maintained after lines are inserted #9961', function()
-- replace the buffer contents with these three lines.
- request('nvim_buf_set_lines', 0, 0, -1, 1, {"line1", "line2", "line3", "line4"})
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'line1', 'line2', 'line3', 'line4' })
-- Set the current cursor to {3, 2}.
- curwin('set_cursor', {3, 2})
+ api.nvim_win_set_cursor(0, { 3, 2 })
-- add 2 lines and delete 1 line above the current cursor position.
- request('nvim_buf_set_lines', 0, 1, 2, 1, {"line5", "line6"})
+ api.nvim_buf_set_lines(0, 1, 2, true, { 'line5', 'line6' })
-- check the current set of lines in the buffer.
- eq({"line1", "line5", "line6", "line3", "line4"}, buffer('get_lines', 0, 0, -1, 1))
+ eq({ 'line1', 'line5', 'line6', 'line3', 'line4' }, api.nvim_buf_get_lines(0, 0, -1, true))
-- cursor should be moved below by 1 line.
- eq({4, 2}, curwin('get_cursor'))
+ eq({ 4, 2 }, api.nvim_win_get_cursor(0))
-- add a line after the current cursor position.
- request('nvim_buf_set_lines', 0, 5, 5, 1, {"line7"})
+ api.nvim_buf_set_lines(0, 5, 5, true, { 'line7' })
-- check the current set of lines in the buffer.
- eq({"line1", "line5", "line6", "line3", "line4", "line7"}, buffer('get_lines', 0, 0, -1, 1))
+ eq(
+ { 'line1', 'line5', 'line6', 'line3', 'line4', 'line7' },
+ api.nvim_buf_get_lines(0, 0, -1, true)
+ )
-- cursor position is unchanged.
- eq({4, 2}, curwin('get_cursor'))
+ eq({ 4, 2 }, api.nvim_win_get_cursor(0))
-- overwrite current cursor line.
- request('nvim_buf_set_lines', 0, 3, 5, 1, {"line8", "line9"})
+ api.nvim_buf_set_lines(0, 3, 5, true, { 'line8', 'line9' })
-- check the current set of lines in the buffer.
- eq({"line1", "line5", "line6", "line8", "line9", "line7"}, buffer('get_lines', 0, 0, -1, 1))
+ eq(
+ { 'line1', 'line5', 'line6', 'line8', 'line9', 'line7' },
+ api.nvim_buf_get_lines(0, 0, -1, true)
+ )
-- cursor position is unchanged.
- eq({4, 2}, curwin('get_cursor'))
+ eq({ 4, 2 }, api.nvim_win_get_cursor(0))
-- delete current cursor line.
- request('nvim_buf_set_lines', 0, 3, 5, 1, {})
+ api.nvim_buf_set_lines(0, 3, 5, true, {})
-- check the current set of lines in the buffer.
- eq({"line1", "line5", "line6", "line7"}, buffer('get_lines', 0, 0, -1, 1))
+ eq({ 'line1', 'line5', 'line6', 'line7' }, api.nvim_buf_get_lines(0, 0, -1, true))
-- cursor position is unchanged.
- eq({4, 2}, curwin('get_cursor'))
+ eq({ 4, 2 }, api.nvim_win_get_cursor(0))
end)
it('cursor position is maintained in non-current window', function()
- meths.buf_set_lines(0, 0, -1, 1, {"line1", "line2", "line3", "line4"})
- meths.win_set_cursor(0, {3, 2})
- local win = meths.get_current_win()
- local buf = meths.get_current_buf()
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'line1', 'line2', 'line3', 'line4' })
+ api.nvim_win_set_cursor(0, { 3, 2 })
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_get_current_buf()
command('new')
- meths.buf_set_lines(buf, 1, 2, 1, {"line5", "line6"})
- eq({"line1", "line5", "line6", "line3", "line4"}, meths.buf_get_lines(buf, 0, -1, true))
- eq({4, 2}, meths.win_get_cursor(win))
+ api.nvim_buf_set_lines(buf, 1, 2, true, { 'line5', 'line6' })
+ eq({ 'line1', 'line5', 'line6', 'line3', 'line4' }, api.nvim_buf_get_lines(buf, 0, -1, true))
+ eq({ 4, 2 }, api.nvim_win_get_cursor(win))
end)
it('cursor position is maintained in TWO non-current windows', function()
- meths.buf_set_lines(0, 0, -1, 1, {"line1", "line2", "line3", "line4"})
- meths.win_set_cursor(0, {3, 2})
- local win = meths.get_current_win()
- local buf = meths.get_current_buf()
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'line1', 'line2', 'line3', 'line4' })
+ api.nvim_win_set_cursor(0, { 3, 2 })
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_get_current_buf()
command('split')
- meths.win_set_cursor(0, {4, 2})
- local win2 = meths.get_current_win()
+ api.nvim_win_set_cursor(0, { 4, 2 })
+ local win2 = api.nvim_get_current_win()
-- set current window to third one with another buffer
- command("new")
+ command('new')
- meths.buf_set_lines(buf, 1, 2, 1, {"line5", "line6"})
- eq({"line1", "line5", "line6", "line3", "line4"}, meths.buf_get_lines(buf, 0, -1, true))
- eq({4, 2}, meths.win_get_cursor(win))
- eq({5, 2}, meths.win_get_cursor(win2))
+ api.nvim_buf_set_lines(buf, 1, 2, true, { 'line5', 'line6' })
+ eq({ 'line1', 'line5', 'line6', 'line3', 'line4' }, api.nvim_buf_get_lines(buf, 0, -1, true))
+ eq({ 4, 2 }, api.nvim_win_get_cursor(win))
+ eq({ 5, 2 }, api.nvim_win_get_cursor(win2))
end)
it('line_count has defined behaviour for unloaded buffers', function()
-- we'll need to know our bufnr for when it gets unloaded
- local bufnr = curbuf('get_number')
+ local bufnr = api.nvim_buf_get_number(0)
-- replace the buffer contents with these three lines
- request('nvim_buf_set_lines', bufnr, 0, -1, 1, {"line1", "line2", "line3", "line4"})
+ api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'line1', 'line2', 'line3', 'line4' })
-- check the line count is correct
- eq(4, request('nvim_buf_line_count', bufnr))
+ eq(4, api.nvim_buf_line_count(bufnr))
-- force unload the buffer (this will discard changes)
command('new')
- command('bunload! '..bufnr)
+ command('bunload! ' .. bufnr)
-- line count for an unloaded buffer should always be 0
- eq(0, request('nvim_buf_line_count', bufnr))
+ eq(0, api.nvim_buf_line_count(bufnr))
end)
it('get_lines has defined behaviour for unloaded buffers', function()
-- we'll need to know our bufnr for when it gets unloaded
- local bufnr = curbuf('get_number')
+ local bufnr = api.nvim_buf_get_number(0)
-- replace the buffer contents with these three lines
- buffer('set_lines', bufnr, 0, -1, 1, {"line1", "line2", "line3", "line4"})
+ api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'line1', 'line2', 'line3', 'line4' })
-- confirm that getting lines works
- eq({"line2", "line3"}, buffer('get_lines', bufnr, 1, 3, 1))
+ eq({ 'line2', 'line3' }, api.nvim_buf_get_lines(bufnr, 1, 3, true))
-- force unload the buffer (this will discard changes)
command('new')
- command('bunload! '..bufnr)
+ command('bunload! ' .. bufnr)
-- attempting to get lines now always gives empty list
- eq({}, buffer('get_lines', bufnr, 1, 3, 1))
+ eq({}, api.nvim_buf_get_lines(bufnr, 1, 3, true))
-- it's impossible to get out-of-bounds errors for an unloaded buffer
- eq({}, buffer('get_lines', bufnr, 8888, 9999, 1))
+ eq({}, api.nvim_buf_get_lines(bufnr, 8888, 9999, true))
end)
describe('handles topline', function()
@@ -152,28 +156,32 @@ describe('api/buf', function()
before_each(function()
screen = Screen.new(20, 12)
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Blue1};
- [2] = {reverse = true, bold = true};
- [3] = {reverse = true};
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { reverse = true, bold = true },
+ [3] = { reverse = true },
}
screen:attach()
- meths.buf_set_lines(0, 0, -1, 1, {"aaa", "bbb", "ccc", "ddd", "www", "xxx", "yyy", "zzz"})
- meths.set_option_value('modified', false, {})
+ api.nvim_buf_set_lines(
+ 0,
+ 0,
+ -1,
+ true,
+ { 'aaa', 'bbb', 'ccc', 'ddd', 'www', 'xxx', 'yyy', 'zzz' }
+ )
+ api.nvim_set_option_value('modified', false, {})
end)
it('of current window', function()
- local win = meths.get_current_win()
- local buf = meths.get_current_buf()
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_get_current_buf()
command('new | wincmd w')
- meths.win_set_cursor(win, {8,0})
+ api.nvim_win_set_cursor(win, { 8, 0 })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{3:[No Name] }|
www |
xxx |
@@ -181,15 +189,14 @@ describe('api/buf', function()
^zzz |
{2:[No Name] }|
|
- ]]}
+ ]],
+ }
- meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(buf, 0, 2, true, { 'aaabbb' })
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{3:[No Name] }|
www |
xxx |
@@ -197,16 +204,15 @@ describe('api/buf', function()
^zzz |
{2:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
-- replacing topline keeps it the topline
- meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(buf, 3, 4, true, { 'wwweeee' })
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{3:[No Name] }|
wwweeee |
xxx |
@@ -214,16 +220,15 @@ describe('api/buf', function()
^zzz |
{2:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
-- inserting just before topline does not scroll up if cursor would be moved
- meths.buf_set_lines(buf, 3, 3, true, {"mmm"})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(buf, 3, 3, true, { 'mmm' })
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{3:[No Name] }|
wwweeee |
xxx |
@@ -231,15 +236,15 @@ describe('api/buf', function()
^zzz |
{2:[No Name] [+] }|
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
- meths.win_set_cursor(0, {7, 0})
- screen:expect{grid=[[
+ api.nvim_win_set_cursor(0, { 7, 0 })
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{3:[No Name] }|
wwweeee |
xxx |
@@ -247,15 +252,14 @@ describe('api/buf', function()
zzz |
{2:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
- meths.buf_set_lines(buf, 4, 4, true, {"mmmeeeee"})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(buf, 4, 4, true, { 'mmmeeeee' })
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{3:[No Name] }|
mmmeeeee |
wwweeee |
@@ -263,22 +267,21 @@ describe('api/buf', function()
^yyy |
{2:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
end)
it('of non-current window', function()
- local win = meths.get_current_win()
- local buf = meths.get_current_buf()
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_get_current_buf()
command('new')
- meths.win_set_cursor(win, {8,0})
+ api.nvim_win_set_cursor(win, { 8, 0 })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{2:[No Name] }|
www |
xxx |
@@ -286,15 +289,14 @@ describe('api/buf', function()
zzz |
{3:[No Name] }|
|
- ]]}
+ ]],
+ }
- meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(buf, 0, 2, true, { 'aaabbb' })
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{2:[No Name] }|
www |
xxx |
@@ -302,16 +304,15 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
-- replacing topline keeps it the topline
- meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(buf, 3, 4, true, { 'wwweeee' })
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{2:[No Name] }|
wwweeee |
xxx |
@@ -319,16 +320,15 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
-- inserting just before topline scrolls up
- meths.buf_set_lines(buf, 3, 3, true, {"mmm"})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(buf, 3, 3, true, { 'mmm' })
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{2:[No Name] }|
mmm |
wwweeee |
@@ -336,18 +336,20 @@ describe('api/buf', function()
yyy |
{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
end)
it('of split windows with same buffer', function()
- local win = meths.get_current_win()
- local buf = meths.get_current_buf()
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_get_current_buf()
command('split')
- meths.win_set_cursor(win, {8,0})
- meths.win_set_cursor(0, {1,0})
+ api.nvim_win_set_cursor(win, { 8, 0 })
+ api.nvim_win_set_cursor(0, { 1, 0 })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^aaa |
bbb |
ccc |
@@ -360,10 +362,12 @@ describe('api/buf', function()
zzz |
{3:[No Name] }|
|
- ]]}
- meths.buf_set_lines(buf, 0, 2, true, {"aaabbb"})
+ ]],
+ }
+ api.nvim_buf_set_lines(buf, 0, 2, true, { 'aaabbb' })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^aaabbb |
ccc |
ddd |
@@ -376,11 +380,13 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
-- replacing topline keeps it the topline
- meths.buf_set_lines(buf, 3, 4, true, {"wwweeee"})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(buf, 3, 4, true, { 'wwweeee' })
+ screen:expect {
+ grid = [[
^aaabbb |
ccc |
ddd |
@@ -393,11 +399,13 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
-- inserting just before topline scrolls up
- meths.buf_set_lines(buf, 3, 3, true, {"mmm"})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(buf, 3, 3, true, { 'mmm' })
+ screen:expect {
+ grid = [[
^aaabbb |
ccc |
ddd |
@@ -410,20 +418,21 @@ describe('api/buf', function()
yyy |
{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
end)
end)
it('handles clearing out non-current buffer #24911', function()
- local buf = meths.get_current_buf()
- meths.buf_set_lines(buf, 0, -1, true, {"aaa", "bbb", "ccc"})
- command("new")
+ local buf = api.nvim_get_current_buf()
+ api.nvim_buf_set_lines(buf, 0, -1, true, { 'aaa', 'bbb', 'ccc' })
+ command('new')
- meths.buf_set_lines(0, 0, -1, true, {"xxx", "yyy", "zzz"})
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'xxx', 'yyy', 'zzz' })
- meths.buf_set_lines(buf, 0, -1, true, {})
- eq({"xxx", "yyy", "zzz"}, meths.buf_get_lines(0, 0, -1, true))
- eq({''}, meths.buf_get_lines(buf, 0, -1, true))
+ api.nvim_buf_set_lines(buf, 0, -1, true, {})
+ eq({ 'xxx', 'yyy', 'zzz' }, api.nvim_buf_get_lines(0, 0, -1, true))
+ eq({ '' }, api.nvim_buf_get_lines(buf, 0, -1, true))
end)
end)
@@ -461,8 +470,8 @@ describe('api/buf', function()
describe('deprecated: {get,set}_line_slice', function()
it('get_line_slice: out-of-bounds returns empty array', function()
- curbuf_depr('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'})
- eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity
+ curbuf_depr('set_line_slice', 0, 0, true, true, { 'a', 'b', 'c' })
+ eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity
eq({}, curbuf_depr('get_line_slice', 2, 3, false, true))
eq({}, curbuf_depr('get_line_slice', 3, 9, true, true))
@@ -472,62 +481,73 @@ describe('api/buf', function()
end)
it('set_line_slice: out-of-bounds extends past end', function()
- curbuf_depr('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'})
- eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity
+ curbuf_depr('set_line_slice', 0, 0, true, true, { 'a', 'b', 'c' })
+ eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, 2, true, true)) --sanity
- eq({'c'}, curbuf_depr('get_line_slice', -1, 4, true, true))
- eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, 5, true, true))
- curbuf_depr('set_line_slice', 4, 5, true, true, {'d'})
- eq({'a', 'b', 'c', 'd'}, curbuf_depr('get_line_slice', 0, 5, true, true))
- curbuf_depr('set_line_slice', -4, -5, true, true, {'e'})
- eq({'e', 'a', 'b', 'c', 'd'}, curbuf_depr('get_line_slice', 0, 5, true, true))
+ eq({ 'c' }, curbuf_depr('get_line_slice', -1, 4, true, true))
+ eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, 5, true, true))
+ curbuf_depr('set_line_slice', 4, 5, true, true, { 'd' })
+ eq({ 'a', 'b', 'c', 'd' }, curbuf_depr('get_line_slice', 0, 5, true, true))
+ curbuf_depr('set_line_slice', -4, -5, true, true, { 'e' })
+ eq({ 'e', 'a', 'b', 'c', 'd' }, curbuf_depr('get_line_slice', 0, 5, true, true))
end)
it('works', function()
- eq({''}, curbuf_depr('get_line_slice', 0, -1, true, true))
+ eq({ '' }, curbuf_depr('get_line_slice', 0, -1, true, true))
-- Replace buffer
- curbuf_depr('set_line_slice', 0, -1, true, true, {'a', 'b', 'c'})
- eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true))
- eq({'b', 'c'}, curbuf_depr('get_line_slice', 1, -1, true, true))
- eq({'b'}, curbuf_depr('get_line_slice', 1, 2, true, false))
+ curbuf_depr('set_line_slice', 0, -1, true, true, { 'a', 'b', 'c' })
+ eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true))
+ eq({ 'b', 'c' }, curbuf_depr('get_line_slice', 1, -1, true, true))
+ eq({ 'b' }, curbuf_depr('get_line_slice', 1, 2, true, false))
eq({}, curbuf_depr('get_line_slice', 1, 1, true, false))
- eq({'a', 'b'}, curbuf_depr('get_line_slice', 0, -1, true, false))
- eq({'b'}, curbuf_depr('get_line_slice', 1, -1, true, false))
- eq({'b', 'c'}, curbuf_depr('get_line_slice', -2, -1, true, true))
- curbuf_depr('set_line_slice', 1, 2, true, false, {'a', 'b', 'c'})
- eq({'a', 'a', 'b', 'c', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true))
- curbuf_depr('set_line_slice', -1, -1, true, true, {'a', 'b', 'c'})
- eq({'a', 'a', 'b', 'c', 'a', 'b', 'c'},
- curbuf_depr('get_line_slice', 0, -1, true, true))
+ eq({ 'a', 'b' }, curbuf_depr('get_line_slice', 0, -1, true, false))
+ eq({ 'b' }, curbuf_depr('get_line_slice', 1, -1, true, false))
+ eq({ 'b', 'c' }, curbuf_depr('get_line_slice', -2, -1, true, true))
+ curbuf_depr('set_line_slice', 1, 2, true, false, { 'a', 'b', 'c' })
+ eq({ 'a', 'a', 'b', 'c', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true))
+ curbuf_depr('set_line_slice', -1, -1, true, true, { 'a', 'b', 'c' })
+ eq({ 'a', 'a', 'b', 'c', 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true))
curbuf_depr('set_line_slice', 0, -3, true, false, {})
- eq({'a', 'b', 'c'}, curbuf_depr('get_line_slice', 0, -1, true, true))
+ eq({ 'a', 'b', 'c' }, curbuf_depr('get_line_slice', 0, -1, true, true))
curbuf_depr('set_line_slice', 0, -1, true, true, {})
- eq({''}, curbuf_depr('get_line_slice', 0, -1, true, true))
+ eq({ '' }, curbuf_depr('get_line_slice', 0, -1, true, true))
end)
end)
- describe_lua_and_rpc('nvim_buf_get_lines, nvim_buf_set_lines', function(api)
- local get_lines = api.curbufmeths.get_lines
- local set_lines = api.curbufmeths.set_lines
- local line_count = api.curbufmeths.line_count
+ describe_lua_and_rpc('nvim_buf_get_lines, nvim_buf_set_lines', function(lua_or_rpc)
+ local function get_lines(...)
+ return lua_or_rpc.nvim_buf_get_lines(0, ...)
+ end
+
+ local function set_lines(...)
+ return lua_or_rpc.nvim_buf_set_lines(0, ...)
+ end
+
+ local function line_count()
+ return lua_or_rpc.nvim_buf_line_count(0)
+ end
it('fails correctly when input is not valid', function()
- eq(1, api.curbufmeths.get_number())
- eq([['replacement string' item contains newlines]],
- pcall_err(bufmeths.set_lines, 1, 1, 2, false, {'b\na'}))
+ eq(1, lua_or_rpc.nvim_buf_get_number(0))
+ eq(
+ [['replacement string' item contains newlines]],
+ pcall_err(lua_or_rpc.nvim_buf_set_lines, 1, 1, 2, false, { 'b\na' })
+ )
end)
it("fails if 'nomodifiable'", function()
command('set nomodifiable')
- eq([[Buffer is not 'modifiable']],
- pcall_err(api.bufmeths.set_lines, 1, 1, 2, false, {'a','b'}))
+ eq(
+ [[Buffer is not 'modifiable']],
+ pcall_err(lua_or_rpc.nvim_buf_set_lines, 1, 1, 2, false, { 'a', 'b' })
+ )
end)
it('has correct line_count when inserting and deleting', function()
eq(1, line_count())
- set_lines(-1, -1, true, {'line'})
+ set_lines(-1, -1, true, { 'line' })
eq(2, line_count())
- set_lines(-1, -1, true, {'line'})
+ set_lines(-1, -1, true, { 'line' })
eq(3, line_count())
set_lines(-2, -1, true, {})
eq(2, line_count())
@@ -538,81 +558,80 @@ describe('api/buf', function()
end)
it('can get, set and delete a single line', function()
- eq({''}, get_lines(0, 1, true))
- set_lines(0, 1, true, {'line1'})
- eq({'line1'}, get_lines(0, 1, true))
- set_lines(0, 1, true, {'line2'})
- eq({'line2'}, get_lines(0, 1, true))
+ eq({ '' }, get_lines(0, 1, true))
+ set_lines(0, 1, true, { 'line1' })
+ eq({ 'line1' }, get_lines(0, 1, true))
+ set_lines(0, 1, true, { 'line2' })
+ eq({ 'line2' }, get_lines(0, 1, true))
set_lines(0, 1, true, {})
- eq({''}, get_lines(0, 1, true))
+ eq({ '' }, get_lines(0, 1, true))
end)
it('can get a single line with strict indexing', function()
- set_lines(0, 1, true, {'line1.a'})
+ set_lines(0, 1, true, { 'line1.a' })
eq(1, line_count()) -- sanity
eq('Index out of bounds', pcall_err(get_lines, 1, 2, true))
eq('Index out of bounds', pcall_err(get_lines, -3, -2, true))
end)
it('can get a single line with non-strict indexing', function()
- set_lines(0, 1, true, {'line1.a'})
+ set_lines(0, 1, true, { 'line1.a' })
eq(1, line_count()) -- sanity
eq({}, get_lines(1, 2, false))
eq({}, get_lines(-3, -2, false))
end)
it('can set and delete a single line with strict indexing', function()
- set_lines(0, 1, true, {'line1.a'})
- eq('Index out of bounds', pcall_err(set_lines, 1, 2, true, {'line1.b'}))
- eq('Index out of bounds', pcall_err(set_lines, -3, -2, true, {'line1.c'}))
- eq({'line1.a'}, get_lines(0, -1, true))
+ set_lines(0, 1, true, { 'line1.a' })
+ eq('Index out of bounds', pcall_err(set_lines, 1, 2, true, { 'line1.b' }))
+ eq('Index out of bounds', pcall_err(set_lines, -3, -2, true, { 'line1.c' }))
+ eq({ 'line1.a' }, get_lines(0, -1, true))
eq('Index out of bounds', pcall_err(set_lines, 1, 2, true, {}))
eq('Index out of bounds', pcall_err(set_lines, -3, -2, true, {}))
- eq({'line1.a'}, get_lines(0, -1, true))
+ eq({ 'line1.a' }, get_lines(0, -1, true))
end)
it('can set and delete a single line with non-strict indexing', function()
- set_lines(0, 1, true, {'line1.a'})
- set_lines(1, 2, false, {'line1.b'})
- set_lines(-4, -3, false, {'line1.c'})
- eq({'line1.c', 'line1.a', 'line1.b'}, get_lines(0, -1, true))
+ set_lines(0, 1, true, { 'line1.a' })
+ set_lines(1, 2, false, { 'line1.b' })
+ set_lines(-4, -3, false, { 'line1.c' })
+ eq({ 'line1.c', 'line1.a', 'line1.b' }, get_lines(0, -1, true))
set_lines(3, 4, false, {})
set_lines(-5, -4, false, {})
- eq({'line1.c', 'line1.a', 'line1.b'}, get_lines(0, -1, true))
+ eq({ 'line1.c', 'line1.a', 'line1.b' }, get_lines(0, -1, true))
end)
it('can handle NULs', function()
- set_lines(0, 1, true, {'ab\0cd'})
- eq({'ab\0cd'}, get_lines(0, -1, true))
+ set_lines(0, 1, true, { 'ab\0cd' })
+ eq({ 'ab\0cd' }, get_lines(0, -1, true))
end)
it('works with multiple lines', function()
- eq({''}, get_lines(0, -1, true))
+ eq({ '' }, get_lines(0, -1, true))
-- Replace buffer
- for _, mode in pairs({false, true}) do
- set_lines(0, -1, mode, {'a', 'b', 'c'})
- eq({'a', 'b', 'c'}, get_lines(0, -1, mode))
- eq({'b', 'c'}, get_lines(1, -1, mode))
- eq({'b'}, get_lines(1, 2, mode))
+ for _, mode in pairs({ false, true }) do
+ set_lines(0, -1, mode, { 'a', 'b', 'c' })
+ eq({ 'a', 'b', 'c' }, get_lines(0, -1, mode))
+ eq({ 'b', 'c' }, get_lines(1, -1, mode))
+ eq({ 'b' }, get_lines(1, 2, mode))
eq({}, get_lines(1, 1, mode))
- eq({'a', 'b'}, get_lines(0, -2, mode))
- eq({'b'}, get_lines(1, -2, mode))
- eq({'b', 'c'}, get_lines(-3, -1, mode))
- set_lines(1, 2, mode, {'a', 'b', 'c'})
- eq({'a', 'a', 'b', 'c', 'c'}, get_lines(0, -1, mode))
- set_lines(-2, -1, mode, {'a', 'b', 'c'})
- eq({'a', 'a', 'b', 'c', 'a', 'b', 'c'},
- get_lines(0, -1, mode))
+ eq({ 'a', 'b' }, get_lines(0, -2, mode))
+ eq({ 'b' }, get_lines(1, -2, mode))
+ eq({ 'b', 'c' }, get_lines(-3, -1, mode))
+ set_lines(1, 2, mode, { 'a', 'b', 'c' })
+ eq({ 'a', 'a', 'b', 'c', 'c' }, get_lines(0, -1, mode))
+ set_lines(-2, -1, mode, { 'a', 'b', 'c' })
+ eq({ 'a', 'a', 'b', 'c', 'a', 'b', 'c' }, get_lines(0, -1, mode))
set_lines(0, -4, mode, {})
- eq({'a', 'b', 'c'}, get_lines(0, -1, mode))
+ eq({ 'a', 'b', 'c' }, get_lines(0, -1, mode))
set_lines(0, -1, mode, {})
- eq({''}, get_lines(0, -1, mode))
+ eq({ '' }, get_lines(0, -1, mode))
end
end)
it('can get line ranges with non-strict indexing', function()
- set_lines(0, -1, true, {'a', 'b', 'c'})
- eq({'a', 'b', 'c'}, get_lines(0, -1, true)) --sanity
+ set_lines(0, -1, true, { 'a', 'b', 'c' })
+ eq({ 'a', 'b', 'c' }, get_lines(0, -1, true)) --sanity
eq({}, get_lines(3, 4, false))
eq({}, get_lines(3, 10, false))
@@ -622,8 +641,8 @@ describe('api/buf', function()
end)
it('can get line ranges with strict indexing', function()
- set_lines(0, -1, true, {'a', 'b', 'c'})
- eq({'a', 'b', 'c'}, get_lines(0, -1, true)) --sanity
+ set_lines(0, -1, true, { 'a', 'b', 'c' })
+ eq({ 'a', 'b', 'c' }, get_lines(0, -1, true)) --sanity
eq('Index out of bounds', pcall_err(get_lines, 3, 4, true))
eq('Index out of bounds', pcall_err(get_lines, 3, 10, true))
@@ -634,20 +653,20 @@ describe('api/buf', function()
end)
it('set_lines: out-of-bounds can extend past end', function()
- set_lines(0, -1, true, {'a', 'b', 'c'})
- eq({'a', 'b', 'c'}, get_lines(0, -1, true)) --sanity
+ set_lines(0, -1, true, { 'a', 'b', 'c' })
+ eq({ 'a', 'b', 'c' }, get_lines(0, -1, true)) --sanity
- eq({'c'}, get_lines(-2, 5, false))
- eq({'a', 'b', 'c'}, get_lines(0, 6, false))
- eq('Index out of bounds', pcall_err(set_lines, 4, 6, true, {'d'}))
- set_lines(4, 6, false, {'d'})
- eq({'a', 'b', 'c', 'd'}, get_lines(0, -1, true))
- eq('Index out of bounds', pcall_err(set_lines, -6, -6, true, {'e'}))
- set_lines(-6, -6, false, {'e'})
- eq({'e', 'a', 'b', 'c', 'd'}, get_lines(0, -1, true))
+ eq({ 'c' }, get_lines(-2, 5, false))
+ eq({ 'a', 'b', 'c' }, get_lines(0, 6, false))
+ eq('Index out of bounds', pcall_err(set_lines, 4, 6, true, { 'd' }))
+ set_lines(4, 6, false, { 'd' })
+ eq({ 'a', 'b', 'c', 'd' }, get_lines(0, -1, true))
+ eq('Index out of bounds', pcall_err(set_lines, -6, -6, true, { 'e' }))
+ set_lines(-6, -6, false, { 'e' })
+ eq({ 'e', 'a', 'b', 'c', 'd' }, get_lines(0, -1, true))
end)
- it("set_lines on alternate buffer does not access invalid line (E315)", function()
+ it('set_lines on alternate buffer does not access invalid line (E315)', function()
feed_command('set hidden')
insert('Initial file')
command('enew')
@@ -667,8 +686,8 @@ describe('api/buf', function()
it("set_lines of invisible buffer doesn't move cursor in current window", function()
local screen = Screen.new(20, 5)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {bold = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true },
})
screen:attach()
@@ -676,7 +695,7 @@ describe('api/buf', function()
Who would win?
A real window
with proper text]])
- local buf = api.meths.create_buf(false,true)
+ local buf = lua_or_rpc.nvim_create_buf(false, true)
screen:expect([[
Who would win? |
A real window |
@@ -685,7 +704,7 @@ describe('api/buf', function()
|
]])
- api.meths.buf_set_lines(buf, 0, -1, true, {'or some', 'scratchy text'})
+ lua_or_rpc.nvim_buf_set_lines(buf, 0, -1, true, { 'or some', 'scratchy text' })
feed('i') -- provoke redraw
screen:expect([[
Who would win? |
@@ -701,37 +720,42 @@ describe('api/buf', function()
visible buffer line 1
line 2
]])
- local hiddenbuf = api.meths.create_buf(false,true)
+ local hiddenbuf = lua_or_rpc.nvim_create_buf(false, true)
command('vsplit')
command('vsplit')
feed('<c-w>l<c-w>l<c-w>l')
- eq(3, funcs.winnr())
+ eq(3, fn.winnr())
feed('<c-w>h')
- eq(2, funcs.winnr())
- api.meths.buf_set_lines(hiddenbuf, 0, -1, true,
- {'hidden buffer line 1', 'line 2'})
+ eq(2, fn.winnr())
+ lua_or_rpc.nvim_buf_set_lines(hiddenbuf, 0, -1, true, { 'hidden buffer line 1', 'line 2' })
feed('<c-w>p')
- eq(3, funcs.winnr())
+ eq(3, fn.winnr())
end)
it('set_lines on unloaded buffer #8659 #22670', function()
- local bufnr = curbuf('get_number')
- meths.buf_set_lines(bufnr, 0, -1, false, {'a', 'b', 'c'})
- meths.buf_set_name(bufnr, 'set_lines')
+ local bufnr = api.nvim_get_current_buf()
+ lua_or_rpc.nvim_buf_set_lines(bufnr, 0, -1, false, { 'a', 'b', 'c' })
+ lua_or_rpc.nvim_buf_set_name(bufnr, 'set_lines')
finally(function()
os.remove('set_lines')
end)
command('write!')
command('new')
- command('bunload! '..bufnr)
- local new_bufnr = funcs.bufnr('set_lines', true)
- meths.buf_set_lines(new_bufnr, 0, -1, false, {})
- eq({''}, meths.buf_get_lines(new_bufnr, 0, -1, false))
+ command('bunload! ' .. bufnr)
+ local new_bufnr = fn.bufnr('set_lines', true)
+ lua_or_rpc.nvim_buf_set_lines(new_bufnr, 0, -1, false, {})
+ eq({ '' }, lua_or_rpc.nvim_buf_get_lines(new_bufnr, 0, -1, false))
end)
end)
describe('nvim_buf_set_text', function()
- local get_lines, set_text = curbufmeths.get_lines, curbufmeths.set_text
+ local function get_lines(...)
+ return api.nvim_buf_get_lines(0, ...)
+ end
+
+ local function set_text(...)
+ return api.nvim_buf_set_text(0, ...)
+ end
it('works', function()
insert([[
@@ -739,70 +763,69 @@ describe('api/buf', function()
text
]])
- eq({'hello foo!'}, get_lines(0, 1, true))
-
+ eq({ 'hello foo!' }, get_lines(0, 1, true))
-- can replace a single word
- set_text(0, 6, 0, 9, {'world'})
- eq({'hello world!', 'text'}, get_lines(0, 2, true))
+ set_text(0, 6, 0, 9, { 'world' })
+ eq({ 'hello world!', 'text' }, get_lines(0, 2, true))
-- can insert text
- set_text(0, 0, 0, 0, {'well '})
- eq({'well hello world!', 'text'}, get_lines(0, 2, true))
+ set_text(0, 0, 0, 0, { 'well ' })
+ eq({ 'well hello world!', 'text' }, get_lines(0, 2, true))
-- can delete text
- set_text(0, 0, 0, 5, {''})
- eq({'hello world!', 'text'}, get_lines(0, 2, true))
+ set_text(0, 0, 0, 5, { '' })
+ eq({ 'hello world!', 'text' }, get_lines(0, 2, true))
-- can replace with multiple lines
- set_text(0, 6, 0, 11, {'foo', 'wo', 'more'})
- eq({'hello foo', 'wo', 'more!', 'text'}, get_lines(0, 4, true))
+ set_text(0, 6, 0, 11, { 'foo', 'wo', 'more' })
+ eq({ 'hello foo', 'wo', 'more!', 'text' }, get_lines(0, 4, true))
-- will join multiple lines if needed
- set_text(0, 6, 3, 4, {'bar'})
- eq({'hello bar'}, get_lines(0, 1, true))
+ set_text(0, 6, 3, 4, { 'bar' })
+ eq({ 'hello bar' }, get_lines(0, 1, true))
-- can use negative line numbers
- set_text(-2, 0, -2, 5, {'goodbye'})
- eq({'goodbye bar', ''}, get_lines(0, -1, true))
+ set_text(-2, 0, -2, 5, { 'goodbye' })
+ eq({ 'goodbye bar', '' }, get_lines(0, -1, true))
- set_text(-1, 0, -1, 0, {'text'})
- eq({'goodbye bar', 'text'}, get_lines(0, 2, true))
+ set_text(-1, 0, -1, 0, { 'text' })
+ eq({ 'goodbye bar', 'text' }, get_lines(0, 2, true))
-- can append to a line
- set_text(1, 4, -1, 4, {' and', 'more'})
- eq({'goodbye bar', 'text and', 'more'}, get_lines(0, 3, true))
+ set_text(1, 4, -1, 4, { ' and', 'more' })
+ eq({ 'goodbye bar', 'text and', 'more' }, get_lines(0, 3, true))
-- can use negative column numbers
- set_text(0, -5, 0, -1, {'!'})
- eq({'goodbye!'}, get_lines(0, 1, true))
+ set_text(0, -5, 0, -1, { '!' })
+ eq({ 'goodbye!' }, get_lines(0, 1, true))
end)
it('works with undo', function()
- insert([[
+ insert([[
hello world!
foo bar
]])
- -- setting text
- set_text(0, 0, 0, 0, {'well '})
- feed('u')
- eq({'hello world!'}, get_lines(0, 1, true))
+ -- setting text
+ set_text(0, 0, 0, 0, { 'well ' })
+ feed('u')
+ eq({ 'hello world!' }, get_lines(0, 1, true))
- -- deleting text
- set_text(0, 0, 0, 6, {''})
- feed('u')
- eq({'hello world!'}, get_lines(0, 1, true))
+ -- deleting text
+ set_text(0, 0, 0, 6, { '' })
+ feed('u')
+ eq({ 'hello world!' }, get_lines(0, 1, true))
- -- inserting newlines
- set_text(0, 0, 0, 0, {'hello', 'mr '})
- feed('u')
- eq({'hello world!'}, get_lines(0, 1, true))
+ -- inserting newlines
+ set_text(0, 0, 0, 0, { 'hello', 'mr ' })
+ feed('u')
+ eq({ 'hello world!' }, get_lines(0, 1, true))
- -- deleting newlines
- set_text(0, 0, 1, 4, {'hello'})
- feed('u')
- eq({'hello world!'}, get_lines(0, 1, true))
+ -- deleting newlines
+ set_text(0, 0, 1, 4, { 'hello' })
+ feed('u')
+ eq({ 'hello world!' }, get_lines(0, 1, true))
end)
it('updates the cursor position', function()
@@ -811,12 +834,12 @@ describe('api/buf', function()
]])
-- position the cursor on `!`
- curwin('set_cursor', {1, 11})
+ api.nvim_win_set_cursor(0, { 1, 11 })
-- replace 'world' with 'foo'
- set_text(0, 6, 0, 11, {'foo'})
+ set_text(0, 6, 0, 11, { 'foo' })
eq('hello foo!', curbuf_depr('get_line', 0))
-- cursor should be moved left by two columns (replacement is shorter by 2 chars)
- eq({1, 9}, curwin('get_cursor'))
+ eq({ 1, 9 }, api.nvim_win_get_cursor(0))
end)
it('updates the cursor position in non-current window', function()
@@ -824,18 +847,18 @@ describe('api/buf', function()
hello world!]])
-- position the cursor on `!`
- meths.win_set_cursor(0, {1, 11})
+ api.nvim_win_set_cursor(0, { 1, 11 })
- local win = meths.get_current_win()
- local buf = meths.get_current_buf()
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_get_current_buf()
- command("new")
+ command('new')
-- replace 'world' with 'foo'
- meths.buf_set_text(buf, 0, 6, 0, 11, {'foo'})
- eq({'hello foo!'}, meths.buf_get_lines(buf, 0, -1, true))
+ api.nvim_buf_set_text(buf, 0, 6, 0, 11, { 'foo' })
+ eq({ 'hello foo!' }, api.nvim_buf_get_lines(buf, 0, -1, true))
-- cursor should be moved left by two columns (replacement is shorter by 2 chars)
- eq({1, 9}, meths.win_get_cursor(win))
+ eq({ 1, 9 }, api.nvim_win_get_cursor(win))
end)
it('updates the cursor position in TWO non-current windows', function()
@@ -843,24 +866,24 @@ describe('api/buf', function()
hello world!]])
-- position the cursor on `!`
- meths.win_set_cursor(0, {1, 11})
- local win = meths.get_current_win()
- local buf = meths.get_current_buf()
+ api.nvim_win_set_cursor(0, { 1, 11 })
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_get_current_buf()
- command("split")
- local win2 = meths.get_current_win()
+ command('split')
+ local win2 = api.nvim_get_current_win()
-- position the cursor on `w`
- meths.win_set_cursor(0, {1, 6})
+ api.nvim_win_set_cursor(0, { 1, 6 })
- command("new")
+ command('new')
-- replace 'hello' with 'foo'
- meths.buf_set_text(buf, 0, 0, 0, 5, {'foo'})
- eq({'foo world!'}, meths.buf_get_lines(buf, 0, -1, true))
+ api.nvim_buf_set_text(buf, 0, 0, 0, 5, { 'foo' })
+ eq({ 'foo world!' }, api.nvim_buf_get_lines(buf, 0, -1, true))
-- both cursors should be moved left by two columns (replacement is shorter by 2 chars)
- eq({1, 9}, meths.win_get_cursor(win))
- eq({1, 4}, meths.win_get_cursor(win2))
+ eq({ 1, 9 }, api.nvim_win_get_cursor(win))
+ eq({ 1, 4 }, api.nvim_win_get_cursor(win2))
end)
describe('when text is being added right at cursor position #22526', function()
@@ -869,12 +892,12 @@ describe('api/buf', function()
abcd]])
-- position the cursor on 'c'
- curwin('set_cursor', {1, 2})
+ api.nvim_win_set_cursor(0, { 1, 2 })
-- add 'xxx' before 'c'
- set_text(0, 2, 0, 2, {'xxx'})
- eq({'abxxxcd'}, get_lines(0, -1, true))
+ set_text(0, 2, 0, 2, { 'xxx' })
+ eq({ 'abxxxcd' }, get_lines(0, -1, true))
-- cursor should be on 'c'
- eq({1, 5}, curwin('get_cursor'))
+ eq({ 1, 5 }, api.nvim_win_get_cursor(0))
end)
it('updates the cursor position only in non-current window when in INSERT mode', function()
@@ -882,23 +905,23 @@ describe('api/buf', function()
abcd]])
-- position the cursor on 'c'
- curwin('set_cursor', {1, 2})
+ api.nvim_win_set_cursor(0, { 1, 2 })
-- open vertical split
feed('<c-w>v')
-- get into INSERT mode to treat cursor
-- as being after 'b', not on 'c'
feed('i')
-- add 'xxx' between 'b' and 'c'
- set_text(0, 2, 0, 2, {'xxx'})
- eq({'abxxxcd'}, get_lines(0, -1, true))
+ set_text(0, 2, 0, 2, { 'xxx' })
+ eq({ 'abxxxcd' }, get_lines(0, -1, true))
-- in the current window cursor should stay after 'b'
- eq({1, 2}, curwin('get_cursor'))
+ eq({ 1, 2 }, api.nvim_win_get_cursor(0))
-- quit INSERT mode
feed('<esc>')
-- close current window
feed('<c-w>c')
-- in another window cursor should be on 'c'
- eq({1, 5}, curwin('get_cursor'))
+ eq({ 1, 5 }, api.nvim_win_get_cursor(0))
end)
end)
@@ -908,20 +931,20 @@ describe('api/buf', function()
abcd]])
-- position the cursor on 'b'
- curwin('set_cursor', {1, 1})
+ api.nvim_win_set_cursor(0, { 1, 1 })
-- delete 'b'
set_text(0, 1, 0, 2, {})
- eq({'acd'}, get_lines(0, -1, true))
+ eq({ 'acd' }, get_lines(0, -1, true))
-- cursor is now on 'c'
- eq({1, 1}, curwin('get_cursor'))
+ eq({ 1, 1 }, api.nvim_win_get_cursor(0))
end)
- it('leaves cursor at the same position in INSERT mode in current and non-current window', function()
+ it('maintains INSERT-mode cursor position current/non-current window', function()
insert([[
abcd]])
-- position the cursor on 'b'
- curwin('set_cursor', {1, 1})
+ api.nvim_win_set_cursor(0, { 1, 1 })
-- open vertical split
feed('<c-w>v')
-- get into INSERT mode to treat cursor
@@ -929,27 +952,27 @@ describe('api/buf', function()
feed('i')
-- delete 'b'
set_text(0, 1, 0, 2, {})
- eq({'acd'}, get_lines(0, -1, true))
+ eq({ 'acd' }, get_lines(0, -1, true))
-- cursor in the current window should stay after 'a'
- eq({1, 1}, curwin('get_cursor'))
+ eq({ 1, 1 }, api.nvim_win_get_cursor(0))
-- quit INSERT mode
feed('<esc>')
-- close current window
feed('<c-w>c')
-- cursor in non-current window should stay on 'c'
- eq({1, 1}, curwin('get_cursor'))
+ eq({ 1, 1 }, api.nvim_win_get_cursor(0))
end)
end)
describe('when cursor is inside replaced row range', function()
- it('keeps cursor at the same position if cursor is at start_row, but before start_col', function()
+ it('maintains cursor position if at start_row, but before start_col', function()
insert([[
This should be first
then there is a line we do not want
and finally the last one]])
-- position the cursor on ' ' before 'first'
- curwin('set_cursor', {1, 14})
+ api.nvim_win_set_cursor(0, { 1, 14 })
set_text(0, 15, 2, 11, {
'the line we do not want',
@@ -961,17 +984,17 @@ describe('api/buf', function()
'but hopefully the last one',
}, get_lines(0, -1, true))
-- cursor should stay at the same position
- eq({1, 14}, curwin('get_cursor'))
+ eq({ 1, 14 }, api.nvim_win_get_cursor(0))
end)
- it('keeps cursor at the same position if cursor is at start_row and column is still valid', function()
+ it('maintains cursor position if at start_row and column is still valid', function()
insert([[
This should be first
then there is a line we do not want
and finally the last one]])
-- position the cursor on 'f' in 'first'
- curwin('set_cursor', {1, 15})
+ api.nvim_win_set_cursor(0, { 1, 15 })
set_text(0, 15, 2, 11, {
'the line we do not want',
@@ -983,7 +1006,7 @@ describe('api/buf', function()
'but hopefully the last one',
}, get_lines(0, -1, true))
-- cursor should stay at the same position
- eq({1, 15}, curwin('get_cursor'))
+ eq({ 1, 15 }, api.nvim_win_get_cursor(0))
end)
it('adjusts cursor column to keep it valid if start_row got smaller', function()
@@ -993,7 +1016,7 @@ describe('api/buf', function()
and finally the last one]])
-- position the cursor on 't' in 'first'
- curwin('set_cursor', {1, 19})
+ api.nvim_win_set_cursor(0, { 1, 19 })
local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 15, 2, 24, {'last'})
@@ -1002,19 +1025,19 @@ describe('api/buf', function()
eq({ 'This should be last' }, get_lines(0, -1, true))
-- cursor should end up on 't' in 'last'
- eq({1, 18}, curwin('get_cursor'))
+ eq({ 1, 18 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({1, 18}, cursor)
+ eq({ 1, 18 }, cursor)
end)
- it('adjusts cursor column to keep it valid if start_row got smaller in INSERT mode', function()
+ it('adjusts cursor column to keep it valid if start_row decreased in INSERT mode', function()
insert([[
This should be first
then there is a line we do not want
and finally the last one]])
-- position the cursor on 't' in 'first'
- curwin('set_cursor', {1, 19})
+ api.nvim_win_set_cursor(0, { 1, 19 })
-- enter INSERT mode to treat cursor as being after 't'
feed('a')
@@ -1025,19 +1048,19 @@ describe('api/buf', function()
eq({ 'This should be last' }, get_lines(0, -1, true))
-- cursor should end up after 't' in 'last'
- eq({1, 19}, curwin('get_cursor'))
+ eq({ 1, 19 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({1, 19}, cursor)
+ eq({ 1, 19 }, cursor)
end)
- it('adjusts cursor column to keep it valid in a row after start_row if it got smaller', function()
+ it('adjusts cursor to valid column in row after start_row if it got smaller', function()
insert([[
This should be first
then there is a line we do not want
and finally the last one]])
-- position the cursor on 'w' in 'want'
- curwin('set_cursor', {2, 31})
+ api.nvim_win_set_cursor(0, { 2, 31 })
local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, {
@@ -1054,23 +1077,25 @@ describe('api/buf', function()
'and then the last one',
}, get_lines(0, -1, true))
-- cursor column should end up at the end of a row
- eq({2, 5}, curwin('get_cursor'))
+ eq({ 2, 5 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({2, 5}, cursor)
+ eq({ 2, 5 }, cursor)
end)
- it('adjusts cursor column to keep it valid in a row after start_row if it got smaller in INSERT mode', function()
- insert([[
+ it(
+ 'adjusts cursor to valid column in row after start_row if it got smaller in INSERT mode',
+ function()
+ insert([[
This should be first
then there is a line we do not want
and finally the last one]])
- -- position the cursor on 'w' in 'want'
- curwin('set_cursor', {2, 31})
- -- enter INSERT mode
- feed('a')
+ -- position the cursor on 'w' in 'want'
+ api.nvim_win_set_cursor(0, { 2, 31 })
+ -- enter INSERT mode
+ feed('a')
- local cursor = exec_lua([[
+ local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, {
'1',
'then 2',
@@ -1079,16 +1104,17 @@ describe('api/buf', function()
return vim.api.nvim_win_get_cursor(0)
]])
- eq({
- 'This should be 1',
- 'then 2',
- 'and then the last one',
- }, get_lines(0, -1, true))
- -- cursor column should end up at the end of a row
- eq({2, 6}, curwin('get_cursor'))
- -- immediate call to nvim_win_get_cursor should have returned the same position
- eq({2, 6}, cursor)
- end)
+ eq({
+ 'This should be 1',
+ 'then 2',
+ 'and then the last one',
+ }, get_lines(0, -1, true))
+ -- cursor column should end up at the end of a row
+ eq({ 2, 6 }, api.nvim_win_get_cursor(0))
+ -- immediate call to nvim_win_get_cursor should have returned the same position
+ eq({ 2, 6 }, cursor)
+ end
+ )
it('adjusts cursor line and column to keep it inside replacement range', function()
insert([[
@@ -1097,7 +1123,7 @@ describe('api/buf', function()
and finally the last one]])
-- position the cursor on 'n' in 'finally'
- curwin('set_cursor', {3, 6})
+ api.nvim_win_set_cursor(0, { 3, 6 })
local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, {
@@ -1113,9 +1139,9 @@ describe('api/buf', function()
}, get_lines(0, -1, true))
-- cursor should end up on 'y' in 'hopefully'
-- to stay in the range, because it got smaller
- eq({2, 12}, curwin('get_cursor'))
+ eq({ 2, 12 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({2, 12}, cursor)
+ eq({ 2, 12 }, cursor)
end)
it('adjusts cursor line and column if replacement is empty', function()
@@ -1125,7 +1151,7 @@ describe('api/buf', function()
and finally the last one]])
-- position the cursor on 'r' in 'there'
- curwin('set_cursor', {2, 8})
+ api.nvim_win_set_cursor(0, { 2, 8 })
local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 15, 2, 12, {})
@@ -1134,9 +1160,9 @@ describe('api/buf', function()
eq({ 'This should be the last one' }, get_lines(0, -1, true))
-- cursor should end up on the next column after deleted range
- eq({1, 15}, curwin('get_cursor'))
+ eq({ 1, 15 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({1, 15}, cursor)
+ eq({ 1, 15 }, cursor)
end)
it('adjusts cursor line and column if replacement is empty and start_col == 0', function()
@@ -1146,7 +1172,7 @@ describe('api/buf', function()
and finally the last one]])
-- position the cursor on 'r' in 'there'
- curwin('set_cursor', {2, 8})
+ api.nvim_win_set_cursor(0, { 2, 8 })
local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 0, 2, 4, {})
@@ -1155,9 +1181,9 @@ describe('api/buf', function()
eq({ 'finally the last one' }, get_lines(0, -1, true))
-- cursor should end up in column 0
- eq({1, 0}, curwin('get_cursor'))
+ eq({ 1, 0 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({1, 0}, cursor)
+ eq({ 1, 0 }, cursor)
end)
it('adjusts cursor column if replacement ends at cursor row, after cursor column', function()
@@ -1167,7 +1193,7 @@ describe('api/buf', function()
and finally the last one]])
-- position the cursor on 'y' in 'finally'
- curwin('set_cursor', {3, 10})
+ api.nvim_win_set_cursor(0, { 3, 10 })
set_text(0, 15, 2, 11, { '1', 'this 2', 'and then' })
eq({
@@ -1176,29 +1202,32 @@ describe('api/buf', function()
'and then the last one',
}, get_lines(0, -1, true))
-- cursor should end up on 'n' in 'then'
- eq({3, 7}, curwin('get_cursor'))
+ eq({ 3, 7 }, api.nvim_win_get_cursor(0))
end)
- it('adjusts cursor column if replacement ends at cursor row, at cursor column in INSERT mode', function()
- insert([[
+ it(
+ 'adjusts cursor column if replacement ends at cursor row, at cursor column in INSERT mode',
+ function()
+ insert([[
This should be first
then there is a line we do not want
and finally the last one]])
- -- position the cursor on 'y' at 'finally'
- curwin('set_cursor', {3, 10})
- -- enter INSERT mode to treat cursor as being between 'l' and 'y'
- feed('i')
- set_text(0, 15, 2, 11, { '1', 'this 2', 'and then' })
+ -- position the cursor on 'y' at 'finally'
+ api.nvim_win_set_cursor(0, { 3, 10 })
+ -- enter INSERT mode to treat cursor as being between 'l' and 'y'
+ feed('i')
+ set_text(0, 15, 2, 11, { '1', 'this 2', 'and then' })
- eq({
- 'This should be 1',
- 'this 2',
- 'and then the last one',
- }, get_lines(0, -1, true))
- -- cursor should end up after 'n' in 'then'
- eq({3, 8}, curwin('get_cursor'))
- end)
+ eq({
+ 'This should be 1',
+ 'this 2',
+ 'and then the last one',
+ }, get_lines(0, -1, true))
+ -- cursor should end up after 'n' in 'then'
+ eq({ 3, 8 }, api.nvim_win_get_cursor(0))
+ end
+ )
it('adjusts cursor column if replacement is inside of a single line', function()
insert([[
@@ -1207,7 +1236,7 @@ describe('api/buf', function()
and finally the last one]])
-- position the cursor on 'y' in 'finally'
- curwin('set_cursor', {3, 10})
+ api.nvim_win_set_cursor(0, { 3, 10 })
set_text(2, 4, 2, 11, { 'then' })
eq({
@@ -1216,7 +1245,7 @@ describe('api/buf', function()
'and then the last one',
}, get_lines(0, -1, true))
-- cursor should end up on 'n' in 'then'
- eq({3, 7}, curwin('get_cursor'))
+ eq({ 3, 7 }, api.nvim_win_get_cursor(0))
end)
it('does not move cursor column after end of a line', function()
@@ -1225,7 +1254,7 @@ describe('api/buf', function()
!!!]])
-- position cursor on the last '1'
- curwin('set_cursor', {2, 2})
+ api.nvim_win_set_cursor(0, { 2, 2 })
local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 33, 1, 3, {})
@@ -1234,16 +1263,16 @@ describe('api/buf', function()
eq({ 'This should be the only line here' }, get_lines(0, -1, true))
-- cursor should end up on '!'
- eq({1, 32}, curwin('get_cursor'))
+ eq({ 1, 32 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({1, 32}, cursor)
+ eq({ 1, 32 }, cursor)
end)
it('does not move cursor column before start of a line', function()
insert('\n!!!')
-- position cursor on the last '1'
- curwin('set_cursor', {2, 2})
+ api.nvim_win_set_cursor(0, { 2, 2 })
local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 0, 1, 3, {})
@@ -1252,20 +1281,20 @@ describe('api/buf', function()
eq({ '' }, get_lines(0, -1, true))
-- cursor should end up on '!'
- eq({1, 0}, curwin('get_cursor'))
+ eq({ 1, 0 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({1, 0}, cursor)
+ eq({ 1, 0 }, cursor)
end)
describe('with virtualedit', function()
- it('adjusts cursor line and column to keep it inside replacement range if cursor is not after eol', function()
+ it('adjusts cursor line/col to keep inside replacement range if not after eol', function()
insert([[
This should be first
then there is a line we do not want
and finally the last one]])
-- position cursor on 't' in 'want'
- curwin('set_cursor', {2, 34})
+ api.nvim_win_set_cursor(0, { 2, 34 })
-- turn on virtualedit
command('set virtualedit=all')
@@ -1283,23 +1312,26 @@ describe('api/buf', function()
}, get_lines(0, -1, true))
-- cursor should end up on 'y' in 'hopefully'
-- to stay in the range
- eq({2, 12}, curwin('get_cursor'))
+ eq({ 2, 12 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({2, 12}, cursor)
+ eq({ 2, 12 }, cursor)
-- coladd should be 0
- eq(0, exec_lua([[
+ eq(
+ 0,
+ exec_lua([[
return vim.fn.winsaveview().coladd
- ]]))
+ ]])
+ )
end)
- it('does not change cursor screen column when cursor is after eol and row got shorter', function()
+ it('does not change cursor screen column when cursor >EOL and row got shorter', function()
insert([[
This should be first
then there is a line we do not want
and finally the last one]])
-- position cursor on 't' in 'want'
- curwin('set_cursor', {2, 34})
+ api.nvim_win_set_cursor(0, { 2, 34 })
-- turn on virtualedit
command('set virtualedit=all')
-- move cursor after eol
@@ -1320,31 +1352,36 @@ describe('api/buf', function()
'but hopefully the last one',
}, get_lines(0, -1, true))
-- cursor should end up at eol of a new row
- eq({2, 26}, curwin('get_cursor'))
+ eq({ 2, 26 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({2, 26}, cursor)
+ eq({ 2, 26 }, cursor)
-- coladd should be increased so that cursor stays in the same screen column
- eq(13, exec_lua([[
+ eq(
+ 13,
+ exec_lua([[
return vim.fn.winsaveview().coladd
- ]]))
+ ]])
+ )
end)
- it('does not change cursor screen column when cursor is after eol and row got longer', function()
- insert([[
+ it(
+ 'does not change cursor screen column when cursor is after eol and row got longer',
+ function()
+ insert([[
This should be first
then there is a line we do not want
and finally the last one]])
- -- position cursor on 't' in 'first'
- curwin('set_cursor', {1, 19})
- -- turn on virtualedit
- command('set virtualedit=all')
- -- move cursor after eol
- exec_lua([[
+ -- position cursor on 't' in 'first'
+ api.nvim_win_set_cursor(0, { 1, 19 })
+ -- turn on virtualedit
+ command('set virtualedit=all')
+ -- move cursor after eol
+ exec_lua([[
vim.fn.winrestview({ coladd = 21 })
]])
- local cursor = exec_lua([[
+ local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, {
'the line we do not want',
'but hopefully',
@@ -1352,36 +1389,42 @@ describe('api/buf', function()
return vim.api.nvim_win_get_cursor(0)
]])
- eq({
- 'This should be the line we do not want',
- 'but hopefully the last one',
- }, get_lines(0, -1, true))
- -- cursor should end up at eol of a new row
- eq({1, 38}, curwin('get_cursor'))
- -- immediate call to nvim_win_get_cursor should have returned the same position
- eq({1, 38}, cursor)
- -- coladd should be increased so that cursor stays in the same screen column
- eq(2, exec_lua([[
+ eq({
+ 'This should be the line we do not want',
+ 'but hopefully the last one',
+ }, get_lines(0, -1, true))
+ -- cursor should end up at eol of a new row
+ eq({ 1, 38 }, api.nvim_win_get_cursor(0))
+ -- immediate call to nvim_win_get_cursor should have returned the same position
+ eq({ 1, 38 }, cursor)
+ -- coladd should be increased so that cursor stays in the same screen column
+ eq(
+ 2,
+ exec_lua([[
return vim.fn.winsaveview().coladd
- ]]))
- end)
-
- it('does not change cursor screen column when cursor is after eol and row extended past cursor column', function()
- insert([[
+ ]])
+ )
+ end
+ )
+
+ it(
+ 'does not change cursor screen column when cursor is after eol and row extended past cursor column',
+ function()
+ insert([[
This should be first
then there is a line we do not want
and finally the last one]])
- -- position cursor on 't' in 'first'
- curwin('set_cursor', {1, 19})
- -- turn on virtualedit
- command('set virtualedit=all')
- -- move cursor after eol just a bit
- exec_lua([[
+ -- position cursor on 't' in 'first'
+ api.nvim_win_set_cursor(0, { 1, 19 })
+ -- turn on virtualedit
+ command('set virtualedit=all')
+ -- move cursor after eol just a bit
+ exec_lua([[
vim.fn.winrestview({ coladd = 3 })
]])
- local cursor = exec_lua([[
+ local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 15, 2, 11, {
'the line we do not want',
'but hopefully',
@@ -1389,37 +1432,43 @@ describe('api/buf', function()
return vim.api.nvim_win_get_cursor(0)
]])
- eq({
- 'This should be the line we do not want',
- 'but hopefully the last one',
- }, get_lines(0, -1, true))
- -- cursor should stay at the same screen column
- eq({1, 22}, curwin('get_cursor'))
- -- immediate call to nvim_win_get_cursor should have returned the same position
- eq({1, 22}, cursor)
- -- coladd should become 0
- eq(0, exec_lua([[
+ eq({
+ 'This should be the line we do not want',
+ 'but hopefully the last one',
+ }, get_lines(0, -1, true))
+ -- cursor should stay at the same screen column
+ eq({ 1, 22 }, api.nvim_win_get_cursor(0))
+ -- immediate call to nvim_win_get_cursor should have returned the same position
+ eq({ 1, 22 }, cursor)
+ -- coladd should become 0
+ eq(
+ 0,
+ exec_lua([[
return vim.fn.winsaveview().coladd
- ]]))
- end)
-
- it('does not change cursor screen column when cursor is after eol and row range decreased', function()
- insert([[
+ ]])
+ )
+ end
+ )
+
+ it(
+ 'does not change cursor screen column when cursor is after eol and row range decreased',
+ function()
+ insert([[
This should be first
then there is a line we do not want
and one more
and finally the last one]])
- -- position cursor on 'e' in 'more'
- curwin('set_cursor', {3, 11})
- -- turn on virtualedit
- command('set virtualedit=all')
- -- move cursor after eol
- exec_lua([[
+ -- position cursor on 'e' in 'more'
+ api.nvim_win_set_cursor(0, { 3, 11 })
+ -- turn on virtualedit
+ command('set virtualedit=all')
+ -- move cursor after eol
+ exec_lua([[
vim.fn.winrestview({ coladd = 28 })
]])
- local cursor = exec_lua([[
+ local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 15, 3, 11, {
'the line we do not want',
'but hopefully',
@@ -1427,19 +1476,23 @@ describe('api/buf', function()
return vim.api.nvim_win_get_cursor(0)
]])
- eq({
- 'This should be the line we do not want',
- 'but hopefully the last one',
- }, get_lines(0, -1, true))
- -- cursor should end up at eol of a new row
- eq({2, 26}, curwin('get_cursor'))
- -- immediate call to nvim_win_get_cursor should have returned the same position
- eq({2, 26}, cursor)
- -- coladd should be increased so that cursor stays in the same screen column
- eq(13, exec_lua([[
+ eq({
+ 'This should be the line we do not want',
+ 'but hopefully the last one',
+ }, get_lines(0, -1, true))
+ -- cursor should end up at eol of a new row
+ eq({ 2, 26 }, api.nvim_win_get_cursor(0))
+ -- immediate call to nvim_win_get_cursor should have returned the same position
+ eq({ 2, 26 }, cursor)
+ -- coladd should be increased so that cursor stays in the same screen column
+ eq(
+ 13,
+ exec_lua([[
return vim.fn.winsaveview().coladd
- ]]))
- end)
+ ]])
+ )
+ end
+ )
end)
end)
@@ -1451,80 +1504,86 @@ describe('api/buf', function()
line]])
-- position the cursor on 'i'
- curwin('set_cursor', {3, 2})
+ api.nvim_win_set_cursor(0, { 3, 2 })
set_text(1, 6, 2, 0, {})
- eq({'first line', 'second line'}, get_lines(0, -1, true))
+ eq({ 'first line', 'second line' }, get_lines(0, -1, true))
-- cursor should stay on 'i'
- eq({2, 8}, curwin('get_cursor'))
+ eq({ 2, 8 }, api.nvim_win_get_cursor(0))
-- add a newline back
- set_text(1, 6, 1, 6, {'', ''})
- eq({'first line', 'second', ' line'}, get_lines(0, -1, true))
+ set_text(1, 6, 1, 6, { '', '' })
+ eq({ 'first line', 'second', ' line' }, get_lines(0, -1, true))
-- cursor should return back to the original position
- eq({3, 2}, curwin('get_cursor'))
+ eq({ 3, 2 }, api.nvim_win_get_cursor(0))
end)
- it('adjusts cursor column if the range is not bound to either start or end of a line', function()
- insert([[
+ it(
+ 'adjusts cursor column if the range is not bound to either start or end of a line',
+ function()
+ insert([[
This should be first
then there is a line we do not want
and finally the last one]])
- -- position the cursor on 'h' in 'the'
- curwin('set_cursor', {3, 13})
- set_text(0, 14, 2, 11, {})
- eq({'This should be the last one'}, get_lines(0, -1, true))
- -- cursor should stay on 'h'
- eq({1, 16}, curwin('get_cursor'))
- -- add deleted lines back
- set_text(0, 14, 0, 14, {
- ' first',
- 'then there is a line we do not want',
- 'and finally',
- })
- eq({
- 'This should be first',
- 'then there is a line we do not want',
- 'and finally the last one',
- }, get_lines(0, -1, true))
- -- cursor should return back to the original position
- eq({3, 13}, curwin('get_cursor'))
- end)
-
- it('adjusts cursor column if replacing lines in range, not just deleting and adding', function()
- insert([[
+ -- position the cursor on 'h' in 'the'
+ api.nvim_win_set_cursor(0, { 3, 13 })
+ set_text(0, 14, 2, 11, {})
+ eq({ 'This should be the last one' }, get_lines(0, -1, true))
+ -- cursor should stay on 'h'
+ eq({ 1, 16 }, api.nvim_win_get_cursor(0))
+ -- add deleted lines back
+ set_text(0, 14, 0, 14, {
+ ' first',
+ 'then there is a line we do not want',
+ 'and finally',
+ })
+ eq({
+ 'This should be first',
+ 'then there is a line we do not want',
+ 'and finally the last one',
+ }, get_lines(0, -1, true))
+ -- cursor should return back to the original position
+ eq({ 3, 13 }, api.nvim_win_get_cursor(0))
+ end
+ )
+
+ it(
+ 'adjusts cursor column if replacing lines in range, not just deleting and adding',
+ function()
+ insert([[
This should be first
then there is a line we do not want
and finally the last one]])
- -- position the cursor on 's' in 'last'
- curwin('set_cursor', {3, 18})
- set_text(0, 15, 2, 11, {
- 'the line we do not want',
- 'but hopefully',
- })
+ -- position the cursor on 's' in 'last'
+ api.nvim_win_set_cursor(0, { 3, 18 })
+ set_text(0, 15, 2, 11, {
+ 'the line we do not want',
+ 'but hopefully',
+ })
- eq({
- 'This should be the line we do not want',
- 'but hopefully the last one',
- }, get_lines(0, -1, true))
- -- cursor should stay on 's'
- eq({2, 20}, curwin('get_cursor'))
+ eq({
+ 'This should be the line we do not want',
+ 'but hopefully the last one',
+ }, get_lines(0, -1, true))
+ -- cursor should stay on 's'
+ eq({ 2, 20 }, api.nvim_win_get_cursor(0))
- set_text(0, 15, 1, 13, {
- 'first',
- 'then there is a line we do not want',
- 'and finally',
- })
+ set_text(0, 15, 1, 13, {
+ 'first',
+ 'then there is a line we do not want',
+ 'and finally',
+ })
- eq({
- 'This should be first',
- 'then there is a line we do not want',
- 'and finally the last one',
- }, get_lines(0, -1, true))
- -- cursor should return back to the original position
- eq({3, 18}, curwin('get_cursor'))
- end)
+ eq({
+ 'This should be first',
+ 'then there is a line we do not want',
+ 'and finally the last one',
+ }, get_lines(0, -1, true))
+ -- cursor should return back to the original position
+ eq({ 3, 18 }, api.nvim_win_get_cursor(0))
+ end
+ )
it('does not move cursor column after end of a line', function()
insert([[
@@ -1532,7 +1591,7 @@ describe('api/buf', function()
]])
-- position cursor at the empty line
- curwin('set_cursor', {2, 0})
+ api.nvim_win_set_cursor(0, { 2, 0 })
local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 33, 1, 0, {'!'})
@@ -1541,9 +1600,9 @@ describe('api/buf', function()
eq({ 'This should be the only line here!' }, get_lines(0, -1, true))
-- cursor should end up on '!'
- eq({1, 33}, curwin('get_cursor'))
+ eq({ 1, 33 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({1, 33}, cursor)
+ eq({ 1, 33 }, cursor)
end)
it('does not move cursor column before start of a line', function()
@@ -1552,7 +1611,7 @@ describe('api/buf', function()
eq({ '', '' }, get_lines(0, -1, true))
-- position cursor on the last '1'
- curwin('set_cursor', {2, 2})
+ api.nvim_win_set_cursor(0, { 2, 2 })
local cursor = exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 0, 1, 0, {''})
@@ -1561,61 +1620,61 @@ describe('api/buf', function()
eq({ '' }, get_lines(0, -1, true))
-- cursor should end up on '!'
- eq({1, 0}, curwin('get_cursor'))
+ eq({ 1, 0 }, api.nvim_win_get_cursor(0))
-- immediate call to nvim_win_get_cursor should have returned the same position
- eq({1, 0}, cursor)
+ eq({ 1, 0 }, cursor)
end)
end)
it('can handle NULs', function()
- set_text(0, 0, 0, 0, {'ab\0cd'})
+ set_text(0, 0, 0, 0, { 'ab\0cd' })
eq('ab\0cd', curbuf_depr('get_line', 0))
end)
it('adjusts extmarks', function()
- local ns = request('nvim_create_namespace', "my-fancy-plugin")
+ local ns = api.nvim_create_namespace('my-fancy-plugin')
insert([[
foo bar
baz
]])
- local id1 = curbufmeths.set_extmark(ns, 0, 1, {})
- local id2 = curbufmeths.set_extmark(ns, 0, 7, {})
- local id3 = curbufmeths.set_extmark(ns, 1, 1, {})
- set_text(0, 4, 0, 7, {"q"})
+ local id1 = api.nvim_buf_set_extmark(0, ns, 0, 1, {})
+ local id2 = api.nvim_buf_set_extmark(0, ns, 0, 7, {})
+ local id3 = api.nvim_buf_set_extmark(0, ns, 1, 1, {})
+ set_text(0, 4, 0, 7, { 'q' })
- eq({'foo q', 'baz'}, get_lines(0, 2, true))
+ eq({ 'foo q', 'baz' }, get_lines(0, 2, true))
-- mark before replacement point is unaffected
- eq({0, 1}, curbufmeths.get_extmark_by_id(ns, id1, {}))
+ eq({ 0, 1 }, api.nvim_buf_get_extmark_by_id(0, ns, id1, {}))
-- mark gets shifted back because the replacement was shorter
- eq({0, 5}, curbufmeths.get_extmark_by_id(ns, id2, {}))
+ eq({ 0, 5 }, api.nvim_buf_get_extmark_by_id(0, ns, id2, {}))
-- mark on the next line is unaffected
- eq({1, 1}, curbufmeths.get_extmark_by_id(ns, id3, {}))
+ eq({ 1, 1 }, api.nvim_buf_get_extmark_by_id(0, ns, id3, {}))
-- replacing the text spanning two lines will adjust the mark on the next line
- set_text(0, 3, 1, 3, {"qux"})
- eq({'fooqux', ''}, get_lines(0, 2, true))
- eq({0, 6}, curbufmeths.get_extmark_by_id(ns, id3, {}))
+ set_text(0, 3, 1, 3, { 'qux' })
+ eq({ 'fooqux', '' }, get_lines(0, 2, true))
+ eq({ 0, 6 }, api.nvim_buf_get_extmark_by_id(0, ns, id3, {}))
-- but mark before replacement point is still unaffected
- eq({0, 1}, curbufmeths.get_extmark_by_id(ns, id1, {}))
+ eq({ 0, 1 }, api.nvim_buf_get_extmark_by_id(0, ns, id1, {}))
-- and the mark in the middle was shifted to the end of the insertion
- eq({0, 6}, curbufmeths.get_extmark_by_id(ns, id2, {}))
+ eq({ 0, 6 }, api.nvim_buf_get_extmark_by_id(0, ns, id2, {}))
-- marks should be put back into the same place after undoing
- set_text(0, 0, 0, 2, {''})
+ set_text(0, 0, 0, 2, { '' })
feed('u')
- eq({0, 1}, curbufmeths.get_extmark_by_id(ns, id1, {}))
- eq({0, 6}, curbufmeths.get_extmark_by_id(ns, id2, {}))
- eq({0, 6}, curbufmeths.get_extmark_by_id(ns, id3, {}))
+ eq({ 0, 1 }, api.nvim_buf_get_extmark_by_id(0, ns, id1, {}))
+ eq({ 0, 6 }, api.nvim_buf_get_extmark_by_id(0, ns, id2, {}))
+ eq({ 0, 6 }, api.nvim_buf_get_extmark_by_id(0, ns, id3, {}))
-- marks should be shifted over by the correct number of bytes for multibyte
-- chars
- set_text(0, 0, 0, 0, {'Ø'})
- eq({0, 3}, curbufmeths.get_extmark_by_id(ns, id1, {}))
- eq({0, 8}, curbufmeths.get_extmark_by_id(ns, id2, {}))
- eq({0, 8}, curbufmeths.get_extmark_by_id(ns, id3, {}))
+ set_text(0, 0, 0, 0, { 'Ø' })
+ eq({ 0, 3 }, api.nvim_buf_get_extmark_by_id(0, ns, id1, {}))
+ eq({ 0, 8 }, api.nvim_buf_get_extmark_by_id(0, ns, id2, {}))
+ eq({ 0, 8 }, api.nvim_buf_get_extmark_by_id(0, ns, id3, {}))
end)
- it("correctly marks changed region for redraw #13890", function()
+ it('correctly marks changed region for redraw #13890', function()
local screen = Screen.new(20, 5)
screen:attach()
@@ -1624,7 +1683,7 @@ describe('api/buf', function()
BBB
]])
- curbufmeths.set_text(0, 0, 1, 3, {'XXX', 'YYY'})
+ api.nvim_buf_set_text(0, 0, 0, 1, 3, { 'XXX', 'YYY' })
screen:expect([[
XXX |
@@ -1657,14 +1716,14 @@ describe('api/buf', function()
end)
it('no heap-use-after-free when called consecutively #19643', function()
- set_text(0, 0, 0, 0, {'one', '', '', 'two'})
- eq({'one', '', '', 'two'}, get_lines(0, 4, true))
- meths.win_set_cursor(0, {1, 0})
+ set_text(0, 0, 0, 0, { 'one', '', '', 'two' })
+ eq({ 'one', '', '', 'two' }, get_lines(0, 4, true))
+ api.nvim_win_set_cursor(0, { 1, 0 })
exec_lua([[
vim.api.nvim_buf_set_text(0, 0, 3, 1, 0, {''})
vim.api.nvim_buf_set_text(0, 0, 3, 1, 0, {''})
]])
- eq({'one', 'two'}, get_lines(0, 2, true))
+ eq({ 'one', 'two' }, get_lines(0, 2, true))
end)
describe('handles topline', function()
@@ -1672,28 +1731,32 @@ describe('api/buf', function()
before_each(function()
screen = Screen.new(20, 12)
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Blue1};
- [2] = {reverse = true, bold = true};
- [3] = {reverse = true};
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { reverse = true, bold = true },
+ [3] = { reverse = true },
}
screen:attach()
- meths.buf_set_lines(0, 0, -1, 1, {"aaa", "bbb", "ccc", "ddd", "www", "xxx", "yyy", "zzz"})
- meths.set_option_value('modified', false, {})
+ api.nvim_buf_set_lines(
+ 0,
+ 0,
+ -1,
+ true,
+ { 'aaa', 'bbb', 'ccc', 'ddd', 'www', 'xxx', 'yyy', 'zzz' }
+ )
+ api.nvim_set_option_value('modified', false, {})
end)
it('of current window', function()
- local win = meths.get_current_win()
- local buf = meths.get_current_buf()
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_get_current_buf()
command('new | wincmd w')
- meths.win_set_cursor(win, {8,0})
+ api.nvim_win_set_cursor(win, { 8, 0 })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{3:[No Name] }|
www |
xxx |
@@ -1701,15 +1764,14 @@ describe('api/buf', function()
^zzz |
{2:[No Name] }|
|
- ]]}
- meths.buf_set_text(buf, 0,3, 1,0, {"X"})
+ ]],
+ }
+ api.nvim_buf_set_text(buf, 0, 3, 1, 0, { 'X' })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{3:[No Name] }|
www |
xxx |
@@ -1717,22 +1779,21 @@ describe('api/buf', function()
^zzz |
{2:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
end)
it('of non-current window', function()
- local win = meths.get_current_win()
- local buf = meths.get_current_buf()
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_get_current_buf()
command('new')
- meths.win_set_cursor(win, {8,0})
+ api.nvim_win_set_cursor(win, { 8, 0 })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{2:[No Name] }|
www |
xxx |
@@ -1740,15 +1801,14 @@ describe('api/buf', function()
zzz |
{3:[No Name] }|
|
- ]]}
+ ]],
+ }
- meths.buf_set_text(buf, 0,3, 1,0, {"X"})
- screen:expect{grid=[[
+ api.nvim_buf_set_text(buf, 0, 3, 1, 0, { 'X' })
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{2:[No Name] }|
www |
xxx |
@@ -1756,18 +1816,20 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
end)
it('of split windows with same buffer', function()
- local win = meths.get_current_win()
- local buf = meths.get_current_buf()
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_get_current_buf()
command('split')
- meths.win_set_cursor(win, {8,0})
- meths.win_set_cursor(0, {1,1})
+ api.nvim_win_set_cursor(win, { 8, 0 })
+ api.nvim_win_set_cursor(0, { 1, 1 })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a^aa |
bbb |
ccc |
@@ -1780,10 +1842,12 @@ describe('api/buf', function()
zzz |
{3:[No Name] }|
|
- ]]}
- meths.buf_set_text(buf, 0,3, 1,0, {"X"})
+ ]],
+ }
+ api.nvim_buf_set_text(buf, 0, 3, 1, 0, { 'X' })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a^aaXbbb |
ccc |
ddd |
@@ -1796,13 +1860,14 @@ describe('api/buf', function()
zzz |
{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
end)
end)
end)
- describe_lua_and_rpc('nvim_buf_get_text', function(api)
- local get_text = api.curbufmeths.get_text
+ describe_lua_and_rpc('nvim_buf_get_text', function(lua_or_rpc)
+ local get_text = lua_or_rpc.nvim_buf_get_text
before_each(function()
insert([[
hello foo!
@@ -1811,119 +1876,118 @@ describe('api/buf', function()
end)
it('works', function()
- eq({'hello'}, get_text(0, 0, 0, 5, {}))
- eq({'hello foo!'}, get_text(0, 0, 0, 42, {}))
- eq({'foo!'}, get_text(0, 6, 0, 10, {}))
- eq({'foo!', 'tex'}, get_text(0, 6, 1, 3, {}))
- eq({'foo!', 'tex'}, get_text(-3, 6, -2, 3, {}))
- eq({''}, get_text(0, 18, 0, 20, {}))
- eq({'ext'}, get_text(-2, 1, -2, 4, {}))
- eq({'hello foo!', 'text', 'm'}, get_text(0, 0, 2, 1, {}))
+ eq({ 'hello' }, get_text(0, 0, 0, 0, 5, {}))
+ eq({ 'hello foo!' }, get_text(0, 0, 0, 0, 42, {}))
+ eq({ 'foo!' }, get_text(0, 0, 6, 0, 10, {}))
+ eq({ 'foo!', 'tex' }, get_text(0, 0, 6, 1, 3, {}))
+ eq({ 'foo!', 'tex' }, get_text(0, -3, 6, -2, 3, {}))
+ eq({ '' }, get_text(0, 0, 18, 0, 20, {}))
+ eq({ 'ext' }, get_text(0, -2, 1, -2, 4, {}))
+ eq({ 'hello foo!', 'text', 'm' }, get_text(0, 0, 0, 2, 1, {}))
end)
it('errors on out-of-range', function()
- eq('Index out of bounds', pcall_err(get_text, 2, 0, 4, 0, {}))
- eq('Index out of bounds', pcall_err(get_text, -4, 0, 0, 0, {}))
- eq('Index out of bounds', pcall_err(get_text, 0, 0, 3, 0, {}))
- eq('Index out of bounds', pcall_err(get_text, 0, 0, -4, 0, {}))
+ eq('Index out of bounds', pcall_err(get_text, 0, 2, 0, 4, 0, {}))
+ eq('Index out of bounds', pcall_err(get_text, 0, -4, 0, 0, 0, {}))
+ eq('Index out of bounds', pcall_err(get_text, 0, 0, 0, 3, 0, {}))
+ eq('Index out of bounds', pcall_err(get_text, 0, 0, 0, -4, 0, {}))
-- no ml_get errors should happen #19017
- eq('', meths.get_vvar('errmsg'))
+ eq('', api.nvim_get_vvar('errmsg'))
end)
it('errors when start is greater than end', function()
- eq("'start' is higher than 'end'", pcall_err(get_text, 1, 0, 0, 0, {}))
- eq('start_col must be less than end_col', pcall_err(get_text, 0, 1, 0, 0, {}))
+ eq("'start' is higher than 'end'", pcall_err(get_text, 0, 1, 0, 0, 0, {}))
+ eq('start_col must be less than end_col', pcall_err(get_text, 0, 0, 1, 0, 0, {}))
end)
end)
describe('nvim_buf_get_offset', function()
- local get_offset = curbufmeths.get_offset
+ local get_offset = api.nvim_buf_get_offset
it('works', function()
- curbufmeths.set_lines(0,-1,true,{'Some\r','exa\000mple', '', 'buf\rfer', 'text'})
- eq(5, curbufmeths.line_count())
- 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(29, get_offset(5))
- eq('Index out of bounds', pcall_err(get_offset, 6))
- eq('Index out of bounds', pcall_err(get_offset, -1))
-
- meths.set_option_value('eol', false, {})
- meths.set_option_value('fixeol', false, {})
- eq(28, get_offset(5))
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'Some\r', 'exa\000mple', '', 'buf\rfer', 'text' })
+ eq(5, api.nvim_buf_line_count(0))
+ eq(0, get_offset(0, 0))
+ eq(6, get_offset(0, 1))
+ eq(15, get_offset(0, 2))
+ eq(16, get_offset(0, 3))
+ eq(24, get_offset(0, 4))
+ eq(29, get_offset(0, 5))
+ eq('Index out of bounds', pcall_err(get_offset, 0, 6))
+ eq('Index out of bounds', pcall_err(get_offset, 0, -1))
+
+ api.nvim_set_option_value('eol', false, {})
+ api.nvim_set_option_value('fixeol', false, {})
+ eq(28, get_offset(0, 5))
-- fileformat is ignored
- 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))
- meths.set_option_value('eol', true, {})
- eq(29, get_offset(5))
-
- command("set hidden")
- command("enew")
- eq(6, bufmeths.get_offset(1,1))
- command("bunload! 1")
- eq(-1, bufmeths.get_offset(1,1))
- eq(-1, bufmeths.get_offset(1,0))
+ api.nvim_set_option_value('fileformat', 'dos', {})
+ eq(0, get_offset(0, 0))
+ eq(6, get_offset(0, 1))
+ eq(15, get_offset(0, 2))
+ eq(16, get_offset(0, 3))
+ eq(24, get_offset(0, 4))
+ eq(28, get_offset(0, 5))
+ api.nvim_set_option_value('eol', true, {})
+ eq(29, get_offset(0, 5))
+
+ command('set hidden')
+ command('enew')
+ eq(6, api.nvim_buf_get_offset(1, 1))
+ command('bunload! 1')
+ eq(-1, api.nvim_buf_get_offset(1, 1))
+ eq(-1, api.nvim_buf_get_offset(1, 0))
end)
it('works in empty buffer', function()
- eq(0, get_offset(0))
- eq(1, get_offset(1))
+ eq(0, get_offset(0, 0))
+ eq(1, get_offset(0, 1))
+ eq(-1, fn.line2byte('$'))
end)
it('works in buffer with one line inserted', function()
feed('itext')
- eq(0, get_offset(0))
- eq(5, get_offset(1))
+ eq(0, get_offset(0, 0))
+ eq(5, get_offset(0, 1))
end)
end)
describe('nvim_buf_get_var, nvim_buf_set_var, nvim_buf_del_var', function()
it('works', function()
- curbuf('set_var', 'lua', {1, 2, {['3'] = 1}})
- eq({1, 2, {['3'] = 1}}, curbuf('get_var', 'lua'))
- eq({1, 2, {['3'] = 1}}, nvim('eval', 'b:lua'))
- eq(1, funcs.exists('b:lua'))
- curbufmeths.del_var('lua')
- eq(0, funcs.exists('b:lua'))
- eq( 'Key not found: lua', pcall_err(curbufmeths.del_var, 'lua'))
- curbufmeths.set_var('lua', 1)
+ api.nvim_buf_set_var(0, 'lua', { 1, 2, { ['3'] = 1 } })
+ eq({ 1, 2, { ['3'] = 1 } }, api.nvim_buf_get_var(0, 'lua'))
+ eq({ 1, 2, { ['3'] = 1 } }, api.nvim_eval('b:lua'))
+ eq(1, fn.exists('b:lua'))
+ api.nvim_buf_del_var(0, 'lua')
+ eq(0, fn.exists('b:lua'))
+ eq('Key not found: lua', pcall_err(api.nvim_buf_del_var, 0, 'lua'))
+ api.nvim_buf_set_var(0, 'lua', 1)
command('lockvar b:lua')
- eq('Key is locked: lua', pcall_err(curbufmeths.del_var, 'lua'))
- eq('Key is locked: lua', pcall_err(curbufmeths.set_var, 'lua', 1))
- eq('Key is read-only: changedtick',
- pcall_err(curbufmeths.del_var, 'changedtick'))
- eq('Key is read-only: changedtick',
- pcall_err(curbufmeths.set_var, 'changedtick', 1))
+ eq('Key is locked: lua', pcall_err(api.nvim_buf_del_var, 0, 'lua'))
+ eq('Key is locked: lua', pcall_err(api.nvim_buf_set_var, 0, 'lua', 1))
+ eq('Key is read-only: changedtick', pcall_err(api.nvim_buf_del_var, 0, 'changedtick'))
+ eq('Key is read-only: changedtick', pcall_err(api.nvim_buf_set_var, 0, 'changedtick', 1))
end)
end)
describe('nvim_buf_get_changedtick', function()
it('works', function()
- eq(2, curbufmeths.get_changedtick())
- curbufmeths.set_lines(0, 1, false, {'abc\0', '\0def', 'ghi'})
- eq(3, curbufmeths.get_changedtick())
- eq(3, curbufmeths.get_var('changedtick'))
+ eq(2, api.nvim_buf_get_changedtick(0))
+ api.nvim_buf_set_lines(0, 0, 1, false, { 'abc\0', '\0def', 'ghi' })
+ eq(3, api.nvim_buf_get_changedtick(0))
+ eq(3, api.nvim_buf_get_var(0, 'changedtick'))
end)
it('buffer_set_var returns the old value', function()
- local val1 = {1, 2, {['3'] = 1}}
- local val2 = {4, 7}
+ local val1 = { 1, 2, { ['3'] = 1 } }
+ local val2 = { 4, 7 }
eq(NIL, request('buffer_set_var', 0, 'lua', val1))
eq(val1, request('buffer_set_var', 0, 'lua', val2))
end)
it('buffer_del_var returns the old value', function()
- local val1 = {1, 2, {['3'] = 1}}
- local val2 = {4, 7}
- eq(NIL, request('buffer_set_var', 0, 'lua', val1))
+ local val1 = { 1, 2, { ['3'] = 1 } }
+ local val2 = { 4, 7 }
+ eq(NIL, request('buffer_set_var', 0, 'lua', val1))
eq(val1, request('buffer_set_var', 0, 'lua', val2))
eq(val2, request('buffer_del_var', 0, 'lua'))
end)
@@ -1931,33 +1995,33 @@ describe('api/buf', function()
describe('nvim_get_option_value, nvim_set_option_value', function()
it('works', function()
- eq(8, nvim('get_option_value', 'shiftwidth', {}))
- nvim('set_option_value', 'shiftwidth', 4, {})
- eq(4, nvim('get_option_value', 'shiftwidth', {}))
+ eq(8, api.nvim_get_option_value('shiftwidth', {}))
+ api.nvim_set_option_value('shiftwidth', 4, {})
+ eq(4, api.nvim_get_option_value('shiftwidth', {}))
-- global-local option
- nvim('set_option_value', 'define', 'test', {buf = 0})
- eq('test', nvim('get_option_value', 'define', {buf = 0}))
+ api.nvim_set_option_value('define', 'test', { buf = 0 })
+ eq('test', api.nvim_get_option_value('define', { buf = 0 }))
-- Doesn't change the global value
- eq("", nvim('get_option_value', 'define', {scope='global'}))
+ eq('', api.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, nvim('get_option_value', 'undolevels', {buf=0}))
+ eq(-123456, api.nvim_get_option_value('undolevels', { buf = 0 }))
end)
end)
describe('nvim_buf_get_name, nvim_buf_set_name', function()
it('works', function()
- nvim('command', 'new')
- eq('', curbuf('get_name'))
- local new_name = nvim('eval', 'resolve(tempname())')
- curbuf('set_name', new_name)
- eq(new_name, curbuf('get_name'))
- nvim('command', 'w!')
- eq(1, funcs.filereadable(new_name))
+ command('new')
+ eq('', api.nvim_buf_get_name(0))
+ local new_name = api.nvim_eval('resolve(tempname())')
+ api.nvim_buf_set_name(0, new_name)
+ eq(new_name, api.nvim_buf_get_name(0))
+ command('w!')
+ eq(1, fn.filereadable(new_name))
os.remove(new_name)
end)
end)
@@ -1965,119 +2029,121 @@ describe('api/buf', function()
describe('nvim_buf_is_loaded', function()
it('works', function()
-- record our buffer number for when we unload it
- local bufnr = curbuf('get_number')
+ local bufnr = api.nvim_buf_get_number(0)
-- api should report that the buffer is loaded
- ok(buffer('is_loaded', bufnr))
+ ok(api.nvim_buf_is_loaded(bufnr))
-- hide the current buffer by switching to a new empty buffer
-- Careful! we need to modify the buffer first or vim will just reuse it
- buffer('set_lines', bufnr, 0, -1, 1, {'line1'})
+ api.nvim_buf_set_lines(bufnr, 0, -1, true, { 'line1' })
command('hide enew')
-- confirm the buffer is hidden, but still loaded
- local infolist = nvim('eval', 'getbufinfo('..bufnr..')')
+ local infolist = api.nvim_eval('getbufinfo(' .. bufnr .. ')')
eq(1, #infolist)
eq(1, infolist[1].hidden)
eq(1, infolist[1].loaded)
-- now force unload the buffer
- command('bunload! '..bufnr)
+ command('bunload! ' .. bufnr)
-- confirm the buffer is unloaded
- infolist = nvim('eval', 'getbufinfo('..bufnr..')')
+ infolist = api.nvim_eval('getbufinfo(' .. bufnr .. ')')
eq(0, infolist[1].loaded)
-- nvim_buf_is_loaded() should also report the buffer as unloaded
- eq(false, buffer('is_loaded', bufnr))
+ eq(false, api.nvim_buf_is_loaded(bufnr))
end)
end)
describe('nvim_buf_is_valid', function()
it('works', function()
- nvim('command', 'new')
- local b = nvim('get_current_buf')
- ok(buffer('is_valid', b))
- nvim('command', 'bw!')
- ok(not buffer('is_valid', b))
+ command('new')
+ local b = api.nvim_get_current_buf()
+ ok(api.nvim_buf_is_valid(b))
+ command('bw!')
+ ok(not api.nvim_buf_is_valid(b))
end)
end)
describe('nvim_buf_delete', function()
it('allows for just deleting', function()
- nvim('command', 'new')
- local b = nvim('get_current_buf')
- ok(buffer('is_valid', b))
- nvim('buf_delete', b, {})
- ok(not buffer('is_loaded', b))
- ok(not buffer('is_valid', b))
+ command('new')
+ local b = api.nvim_get_current_buf()
+ ok(api.nvim_buf_is_valid(b))
+ api.nvim_buf_delete(b, {})
+ ok(not api.nvim_buf_is_loaded(b))
+ ok(not api.nvim_buf_is_valid(b))
end)
it('allows for just unloading', function()
- nvim('command', 'new')
- local b = nvim('get_current_buf')
- ok(buffer('is_valid', b))
- nvim('buf_delete', b, { unload = true })
- ok(not buffer('is_loaded', b))
- ok(buffer('is_valid', b))
+ command('new')
+ local b = api.nvim_get_current_buf()
+ ok(api.nvim_buf_is_valid(b))
+ api.nvim_buf_delete(b, { unload = true })
+ ok(not api.nvim_buf_is_loaded(b))
+ ok(api.nvim_buf_is_valid(b))
end)
end)
describe('nvim_buf_get_mark', function()
it('works', function()
- curbuf('set_lines', -1, -1, true, {'a', 'bit of', 'text'})
- curwin('set_cursor', {3, 4})
- nvim('command', 'mark v')
- eq({3, 0}, curbuf('get_mark', 'v'))
+ api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' })
+ api.nvim_win_set_cursor(0, { 3, 4 })
+ command('mark v')
+ eq({ 3, 0 }, api.nvim_buf_get_mark(0, 'v'))
end)
end)
describe('nvim_buf_set_mark', function()
it('works with buffer local marks', function()
- curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
- eq(true, curbufmeths.set_mark('z', 1, 1, {}))
- eq({1, 1}, curbufmeths.get_mark('z'))
+ api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' })
+ eq(true, api.nvim_buf_set_mark(0, 'z', 1, 1, {}))
+ eq({ 1, 1 }, api.nvim_buf_get_mark(0, 'z'))
+ eq({ 0, 1, 2, 0 }, fn.getpos("'z"))
end)
it('works with file/uppercase marks', function()
- curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
- eq(true, curbufmeths.set_mark('Z', 3, 1, {}))
- eq({3, 1}, curbufmeths.get_mark('Z'))
+ api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' })
+ eq(true, api.nvim_buf_set_mark(0, 'Z', 3, 2, {}))
+ eq({ 3, 2 }, api.nvim_buf_get_mark(0, 'Z'))
+ eq({ api.nvim_get_current_buf(), 3, 3, 0 }, fn.getpos("'Z"))
end)
it('fails when invalid marks names are used', function()
- eq(false, pcall(curbufmeths.set_mark, '!', 1, 0, {}))
- eq(false, pcall(curbufmeths.set_mark, 'fail', 1, 0, {}))
+ eq(false, pcall(api.nvim_buf_set_mark, 0, '!', 1, 0, {}))
+ eq(false, pcall(api.nvim_buf_set_mark, 0, 'fail', 1, 0, {}))
end)
it('fails when invalid buffer number is used', function()
- eq(false, pcall(meths.buf_set_mark, 99, 'a', 1, 1, {}))
+ eq(false, pcall(api.nvim_buf_set_mark, 99, 'a', 1, 1, {}))
end)
end)
describe('nvim_buf_del_mark', function()
it('works with buffer local marks', function()
- curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
- curbufmeths.set_mark('z', 3, 1, {})
- eq(true, curbufmeths.del_mark('z'))
- eq({0, 0}, curbufmeths.get_mark('z'))
+ api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' })
+ api.nvim_buf_set_mark(0, 'z', 3, 1, {})
+ eq(true, api.nvim_buf_del_mark(0, 'z'))
+ eq({ 0, 0 }, api.nvim_buf_get_mark(0, 'z'))
end)
it('works with file/uppercase marks', function()
- curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
- curbufmeths.set_mark('Z', 3, 3, {})
- eq(true, curbufmeths.del_mark('Z'))
- eq({0, 0}, curbufmeths.get_mark('Z'))
+ api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' })
+ api.nvim_buf_set_mark(0, 'Z', 3, 3, {})
+ eq(true, api.nvim_buf_del_mark(0, 'Z'))
+ eq({ 0, 0 }, api.nvim_buf_get_mark(0, 'Z'))
end)
it('returns false in marks not set in this buffer', function()
- local abuf = meths.create_buf(false,true)
- bufmeths.set_lines(abuf, -1, -1, true, {'a', 'bit of', 'text'})
- bufmeths.set_mark(abuf, 'A', 2, 2, {})
- eq(false, curbufmeths.del_mark('A'))
- eq({2, 2}, bufmeths.get_mark(abuf, 'A'))
+ local abuf = api.nvim_create_buf(false, true)
+ api.nvim_buf_set_lines(abuf, -1, -1, true, { 'a', 'bit of', 'text' })
+ api.nvim_buf_set_mark(abuf, 'A', 2, 2, {})
+ eq(false, api.nvim_buf_del_mark(0, 'A'))
+ eq({ 2, 2 }, api.nvim_buf_get_mark(abuf, 'A'))
end)
it('returns false if mark was not deleted', function()
- curbufmeths.set_lines(-1, -1, true, {'a', 'bit of', 'text'})
- curbufmeths.set_mark('z', 3, 1, {})
- eq(true, curbufmeths.del_mark('z'))
- eq(false, curbufmeths.del_mark('z')) -- Mark was already deleted
+ api.nvim_buf_set_lines(0, -1, -1, true, { 'a', 'bit of', 'text' })
+ api.nvim_buf_set_mark(0, 'z', 3, 1, {})
+ eq(true, api.nvim_buf_del_mark(0, 'z'))
+ eq(false, api.nvim_buf_del_mark(0, 'z')) -- Mark was already deleted
end)
it('fails when invalid marks names are used', function()
- eq(false, pcall(curbufmeths.del_mark, '!'))
- eq(false, pcall(curbufmeths.del_mark, 'fail'))
+ eq(false, pcall(api.nvim_buf_del_mark, 0, '!'))
+ eq(false, pcall(api.nvim_buf_del_mark, 0, 'fail'))
end)
it('fails when invalid buffer number is used', function()
- eq(false, pcall(meths.buf_del_mark, 99, 'a'))
+ eq(false, pcall(api.nvim_buf_del_mark, 99, 'a'))
end)
end)
end)
diff --git a/test/functional/api/buffer_updates_spec.lua b/test/functional/api/buffer_updates_spec.lua
index 80e29c1ff2..262ca40e28 100644
--- a/test/functional/api/buffer_updates_spec.lua
+++ b/test/functional/api/buffer_updates_spec.lua
@@ -1,39 +1,43 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq, ok = helpers.eq, helpers.ok
-local buffer, command, eval, nvim, next_msg = helpers.buffer,
- helpers.command, helpers.eval, helpers.nvim, helpers.next_msg
+local fn = helpers.fn
+local api = helpers.api
+local command, eval, next_msg = helpers.command, helpers.eval, helpers.next_msg
local nvim_prog = helpers.nvim_prog
local pcall_err = helpers.pcall_err
-local sleep = helpers.sleep
+local sleep = vim.uv.sleep
local write_file = helpers.write_file
-local origlines = {"original line 1",
- "original line 2",
- "original line 3",
- "original line 4",
- "original line 5",
- "original line 6"}
+local origlines = {
+ 'original line 1',
+ 'original line 2',
+ 'original line 3',
+ 'original line 4',
+ 'original line 5',
+ 'original line 6',
+}
local function expectn(name, args)
-- expect the next message to be the specified notification event
- eq({'notification', name, args}, next_msg())
+ eq({ 'notification', name, args }, next_msg())
end
local function sendkeys(keys)
- nvim('input', keys)
+ api.nvim_input(keys)
-- give nvim some time to process msgpack requests before possibly sending
-- more key presses - otherwise they all pile up in the queue and get
-- processed at once
local ntime = os.clock() + 0.1
- repeat until os.clock() > ntime
+ repeat
+ until os.clock() > ntime
end
local function open(activate, lines)
local filename = helpers.tmpname()
- write_file(filename, table.concat(lines, "\n").."\n", true)
+ write_file(filename, table.concat(lines, '\n') .. '\n', true)
command('edit ' .. filename)
- local b = nvim('get_current_buf')
+ local b = api.nvim_get_current_buf()
-- what is the value of b:changedtick?
local tick = eval('b:changedtick')
@@ -41,8 +45,8 @@ local function open(activate, lines)
-- arrive as expected
if activate then
local firstline = 0
- ok(buffer('attach', b, true, {}))
- expectn('nvim_buf_lines_event', {b, tick, firstline, -1, lines, false})
+ ok(api.nvim_buf_attach(b, true, {}))
+ expectn('nvim_buf_lines_event', { b, tick, firstline, -1, lines, false })
end
return b, tick, filename
@@ -58,14 +62,14 @@ local function editoriginal(activate, lines)
end
local function reopen(buf, expectedlines)
- ok(buffer('detach', buf))
- expectn('nvim_buf_detach_event', {buf})
+ ok(api.nvim_buf_detach(buf))
+ expectn('nvim_buf_detach_event', { buf })
-- for some reason the :edit! increments tick by 2
command('edit!')
local tick = eval('b:changedtick')
- ok(buffer('attach', buf, true, {}))
+ ok(api.nvim_buf_attach(buf, true, {}))
local firstline = 0
- expectn('nvim_buf_lines_event', {buf, tick, firstline, -1, expectedlines, false})
+ expectn('nvim_buf_lines_event', { buf, tick, firstline, -1, expectedlines, false })
command('normal! gg')
return tick
end
@@ -80,18 +84,36 @@ local function reopenwithfolds(b)
-- add a fold
command('2,4fold')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 4, {'original line 2/*{{{*/',
- 'original line 3',
- 'original line 4/*}}}*/'}, false})
+ expectn('nvim_buf_lines_event', {
+ b,
+ tick,
+ 1,
+ 4,
+ {
+ 'original line 2/*{{{*/',
+ 'original line 3',
+ 'original line 4/*}}}*/',
+ },
+ false,
+ })
-- make a new fold that wraps lines 1-6
command('1,6fold')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 6, {'original line 1/*{{{*/',
- 'original line 2/*{{{*/',
- 'original line 3',
- 'original line 4/*}}}*/',
- 'original line 5',
- 'original line 6/*}}}*/'}, false})
+ expectn('nvim_buf_lines_event', {
+ b,
+ tick,
+ 0,
+ 6,
+ {
+ 'original line 1/*{{{*/',
+ 'original line 2/*{{{*/',
+ 'original line 3',
+ 'original line 4/*}}}*/',
+ 'original line 5',
+ 'original line 6/*}}}*/',
+ },
+ false,
+ })
return tick
end
@@ -104,97 +126,105 @@ describe('API: buffer events:', function()
-- add a new line at the start of the buffer
command('normal! GyyggP')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 0, {'original line 6'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 0, { 'original line 6' }, false })
-- add multiple lines at the start of the file
command('normal! GkkyGggP')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 0, {'original line 4',
- 'original line 5',
- 'original line 6'}, false})
+ expectn(
+ 'nvim_buf_lines_event',
+ { b, tick, 0, 0, { 'original line 4', 'original line 5', 'original line 6' }, false }
+ )
-- add one line to the middle of the file, several times
command('normal! ggYjjp')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 3, 3, {'original line 4'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 3, 3, { 'original line 4' }, false })
command('normal! p')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 4, 4, {'original line 4'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 4, 4, { 'original line 4' }, false })
command('normal! p')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 5, 5, {'original line 4'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 5, 5, { 'original line 4' }, false })
-- add multiple lines to the middle of the file
command('normal! gg4Yjjp')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 3, 3, {'original line 4',
- 'original line 5',
- 'original line 6',
- 'original line 4'}, false})
+ expectn('nvim_buf_lines_event', {
+ b,
+ tick,
+ 3,
+ 3,
+ {
+ 'original line 4',
+ 'original line 5',
+ 'original line 6',
+ 'original line 4',
+ },
+ false,
+ })
-- add one line to the end of the file
command('normal! ggYGp')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 17, 17, {'original line 4'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 17, 17, { 'original line 4' }, false })
-- add one line to the end of the file, several times
command('normal! ggYGppp')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 18, 18, {'original line 4'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 18, 18, { 'original line 4' }, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 19, 19, {'original line 4'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 19, 19, { 'original line 4' }, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 20, 20, {'original line 4'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 20, 20, { 'original line 4' }, false })
-- add several lines to the end of the file, several times
command('normal! gg4YGp')
command('normal! Gp')
command('normal! Gp')
- local firstfour = {'original line 4',
- 'original line 5',
- 'original line 6',
- 'original line 4'}
+ local firstfour = { 'original line 4', 'original line 5', 'original line 6', 'original line 4' }
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 21, 21, firstfour, false})
+ expectn('nvim_buf_lines_event', { b, tick, 21, 21, firstfour, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 25, 25, firstfour, false})
+ expectn('nvim_buf_lines_event', { b, tick, 25, 25, firstfour, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 29, 29, firstfour, false})
+ expectn('nvim_buf_lines_event', { b, tick, 29, 29, firstfour, false })
-- delete the current buffer to turn off buffer events
command('bdelete!')
- expectn('nvim_buf_detach_event', {b})
+ expectn('nvim_buf_detach_event', { b })
-- add a line at the start of an empty file
command('enew')
tick = eval('b:changedtick')
- local b2 = nvim('get_current_buf')
- ok(buffer('attach', b2, true, {}))
- expectn('nvim_buf_lines_event', {b2, tick, 0, -1, {""}, false})
+ local b2 = api.nvim_get_current_buf()
+ ok(api.nvim_buf_attach(b2, true, {}))
+ expectn('nvim_buf_lines_event', { b2, tick, 0, -1, { '' }, false })
eval('append(0, ["new line 1"])')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b2, tick, 0, 0, {'new line 1'}, false})
+ expectn('nvim_buf_lines_event', { b2, tick, 0, 0, { 'new line 1' }, false })
-- turn off buffer events manually
- buffer('detach', b2)
- expectn('nvim_buf_detach_event', {b2})
+ api.nvim_buf_detach(b2)
+ expectn('nvim_buf_detach_event', { b2 })
-- add multiple lines to a blank file
command('enew!')
- local b3 = nvim('get_current_buf')
- ok(buffer('attach', b3, true, {}))
+ local b3 = api.nvim_get_current_buf()
+ ok(api.nvim_buf_attach(b3, true, {}))
tick = eval('b:changedtick')
- expectn('nvim_buf_lines_event', {b3, tick, 0, -1, {""}, false})
+ expectn('nvim_buf_lines_event', { b3, tick, 0, -1, { '' }, false })
eval('append(0, ["new line 1", "new line 2", "new line 3"])')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b3, tick, 0, 0, {'new line 1',
- 'new line 2',
- 'new line 3'}, false})
+ expectn(
+ 'nvim_buf_lines_event',
+ { b3, tick, 0, 0, { 'new line 1', 'new line 2', 'new line 3' }, false }
+ )
-- use the API itself to add a line to the start of the buffer
- buffer('set_lines', b3, 0, 0, true, {'New First Line'})
+ api.nvim_buf_set_lines(b3, 0, 0, true, { 'New First Line' })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b3, tick, 0, 0, {"New First Line"}, false})
+ expectn('nvim_buf_lines_event', { b3, tick, 0, 0, { 'New First Line' }, false })
end)
it('when lines are removed', function()
@@ -203,37 +233,37 @@ describe('API: buffer events:', function()
-- remove one line from start of file
command('normal! dd')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, {}, false })
-- remove multiple lines from the start of the file
command('normal! 4dd')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 4, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 4, {}, false })
-- remove multiple lines from middle of file
tick = reopen(b, origlines)
command('normal! jj3dd')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 2, 5, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 2, 5, {}, false })
-- remove one line from the end of the file
tick = reopen(b, origlines)
command('normal! Gdd')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 5, 6, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 5, 6, {}, false })
-- remove multiple lines from the end of the file
tick = reopen(b, origlines)
command('normal! 4G3dd')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 3, 6, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 3, 6, {}, false })
-- pretend to remove heaps lines from the end of the file but really
-- just remove two
tick = reopen(b, origlines)
command('normal! Gk5dd')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 4, 6, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 4, 6, {}, false })
end)
it('when text is changed', function()
@@ -242,53 +272,56 @@ describe('API: buffer events:', function()
-- some normal text editing
command('normal! A555')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'original line 1555'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'original line 1555' }, false })
command('normal! jj8X')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 2, 3, {'origin3'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 2, 3, { 'origin3' }, false })
-- modify multiple lines at once using visual block mode
tick = reopen(b, origlines)
command('normal! jjw')
sendkeys('<C-v>jjllx')
tick = tick + 1
- expectn('nvim_buf_lines_event',
- {b, tick, 2, 5, {'original e 3', 'original e 4', 'original e 5'}, false})
+ expectn(
+ 'nvim_buf_lines_event',
+ { b, tick, 2, 5, { 'original e 3', 'original e 4', 'original e 5' }, false }
+ )
-- replace part of a line line using :s
tick = reopen(b, origlines)
command('3s/line 3/foo/')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 2, 3, {'original foo'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 2, 3, { 'original foo' }, false })
-- replace parts of several lines line using :s
tick = reopen(b, origlines)
command('%s/line [35]/foo/')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 2, 5, {'original foo',
- 'original line 4',
- 'original foo'}, false})
+ expectn(
+ 'nvim_buf_lines_event',
+ { b, tick, 2, 5, { 'original foo', 'original line 4', 'original foo' }, false }
+ )
-- type text into the first line of a blank file, one character at a time
command('bdelete!')
tick = 2
- expectn('nvim_buf_detach_event', {b})
- local bnew = nvim('get_current_buf')
- ok(buffer('attach', bnew, true, {}))
- expectn('nvim_buf_lines_event', {bnew, tick, 0, -1, {''}, false})
+ expectn('nvim_buf_detach_event', { b })
+ local bnew = api.nvim_get_current_buf()
+ ok(api.nvim_buf_attach(bnew, true, {}))
+ expectn('nvim_buf_lines_event', { bnew, tick, 0, -1, { '' }, false })
sendkeys('i')
sendkeys('h')
sendkeys('e')
sendkeys('l')
sendkeys('l')
sendkeys('o\nworld')
- expectn('nvim_buf_lines_event', {bnew, tick + 1, 0, 1, {'h'}, false})
- expectn('nvim_buf_lines_event', {bnew, tick + 2, 0, 1, {'he'}, false})
- expectn('nvim_buf_lines_event', {bnew, tick + 3, 0, 1, {'hel'}, false})
- expectn('nvim_buf_lines_event', {bnew, tick + 4, 0, 1, {'hell'}, false})
- expectn('nvim_buf_lines_event', {bnew, tick + 5, 0, 1, {'hello'}, false})
- expectn('nvim_buf_lines_event', {bnew, tick + 6, 0, 1, {'hello', ''}, false})
- expectn('nvim_buf_lines_event', {bnew, tick + 7, 1, 2, {'world'}, false})
+ expectn('nvim_buf_lines_event', { bnew, tick + 1, 0, 1, { 'h' }, false })
+ expectn('nvim_buf_lines_event', { bnew, tick + 2, 0, 1, { 'he' }, false })
+ expectn('nvim_buf_lines_event', { bnew, tick + 3, 0, 1, { 'hel' }, false })
+ expectn('nvim_buf_lines_event', { bnew, tick + 4, 0, 1, { 'hell' }, false })
+ expectn('nvim_buf_lines_event', { bnew, tick + 5, 0, 1, { 'hello' }, false })
+ expectn('nvim_buf_lines_event', { bnew, tick + 6, 0, 1, { 'hello', '' }, false })
+ expectn('nvim_buf_lines_event', { bnew, tick + 7, 1, 2, { 'world' }, false })
end)
it('when lines are replaced', function()
@@ -297,169 +330,179 @@ describe('API: buffer events:', function()
-- blast away parts of some lines with visual mode
command('normal! jjwvjjllx')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 2, 3, {'original '}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 2, 3, { 'original ' }, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 3, 4, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 3, 4, {}, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 3, 4, {'e 5'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 3, 4, { 'e 5' }, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 2, 3, {'original e 5'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 2, 3, { 'original e 5' }, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 3, 4, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 3, 4, {}, false })
-- blast away a few lines using :g
tick = reopen(b, origlines)
command('global/line [35]/delete')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 2, 3, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 2, 3, {}, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 3, 4, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 3, 4, {}, false })
+ end)
+
+ it('visual paste split empty line', function()
+ local b, tick = editoriginal(true, { 'abc', '{', 'def', '}' })
+ command('normal! ggyyjjvi{p')
+ expectn('nvim_buf_lines_event', { b, tick + 1, 2, 3, { '' }, false })
+ expectn('nvim_buf_lines_event', { b, tick + 2, 2, 3, { '}' }, false })
+ expectn('nvim_buf_lines_event', { b, tick + 3, 3, 4, {}, false })
+ expectn('nvim_buf_lines_event', { b, tick + 3, 2, 3, { '' }, false })
+ expectn('nvim_buf_lines_event', { b, tick + 4, 3, 3, { 'abc', '}' }, false })
end)
it('when lines are filtered', function()
-- Test filtering lines with !cat
- local b, tick = editoriginal(true, {"A", "C", "E", "B", "D", "F"})
+ local b, tick = editoriginal(true, { 'A', 'C', 'E', 'B', 'D', 'F' })
command('silent 2,5!cat')
-- the change comes through as two changes:
-- 1) addition of the new lines after the filtered lines
-- 2) removal of the original lines
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 5, 5, {"C", "E", "B", "D"}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 5, 5, { 'C', 'E', 'B', 'D' }, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 5, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 1, 5, {}, false })
end)
it('when you use "o"', function()
- local b, tick = editoriginal(true, {'AAA', 'BBB'})
+ local b, tick = editoriginal(true, { 'AAA', 'BBB' })
command('set noautoindent nosmartindent')
-- use 'o' to start a new line from a line with no indent
command('normal! o')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 1, {""}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 1, 1, { '' }, false })
-- undo the change, indent line 1 a bit, and try again
command('undo')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 2, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 1, 2, {}, false })
tick = tick + 1
- expectn('nvim_buf_changedtick_event', {b, tick})
+ expectn('nvim_buf_changedtick_event', { b, tick })
command('set autoindent')
command('normal! >>')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {"\tAAA"}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { '\tAAA' }, false })
command('normal! ommm')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 1, {"\t"}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 1, 1, { '\t' }, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 2, {"\tmmm"}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 1, 2, { '\tmmm' }, false })
-- undo the change, and try again with 'O'
command('undo')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 2, {'\t'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 1, 2, { '\t' }, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 2, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 1, 2, {}, false })
tick = tick + 1
- expectn('nvim_buf_changedtick_event', {b, tick})
+ expectn('nvim_buf_changedtick_event', { b, tick })
command('normal! ggOmmm')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 0, {"\t"}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 0, { '\t' }, false })
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {"\tmmm"}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { '\tmmm' }, false })
end)
it('deactivates if the buffer is changed externally', function()
-- Test changing file from outside vim and reloading using :edit
- local lines = {"Line 1", "Line 2"};
+ local lines = { 'Line 1', 'Line 2' }
local b, tick, filename = editoriginal(true, lines)
command('normal! x')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'ine 1'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'ine 1' }, false })
command('undo')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'Line 1'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'Line 1' }, false })
tick = tick + 1
- expectn('nvim_buf_changedtick_event', {b, tick})
+ expectn('nvim_buf_changedtick_event', { b, tick })
-- change the file directly
- write_file(filename, "another line\n", true, true)
+ write_file(filename, 'another line\n', true, true)
-- reopen the file and watch buffer events shut down
command('edit')
- expectn('nvim_buf_detach_event', {b})
+ expectn('nvim_buf_detach_event', { b })
end)
it('channel can watch many buffers at once', function()
-- edit 3 buffers, make sure they all have windows visible so that when we
-- move between buffers, none of them are unloaded
- local b1, tick1 = editoriginal(true, {'A1', 'A2'})
+ local b1, tick1 = editoriginal(true, { 'A1', 'A2' })
local b1nr = eval('bufnr("")')
command('split')
- local b2, tick2 = open(true, {'B1', 'B2'})
+ local b2, tick2 = open(true, { 'B1', 'B2' })
local b2nr = eval('bufnr("")')
command('split')
- local b3, tick3 = open(true, {'C1', 'C2'})
+ local b3, tick3 = open(true, { 'C1', 'C2' })
local b3nr = eval('bufnr("")')
-- make a new window for moving between buffers
command('split')
- command('b'..b1nr)
+ command('b' .. b1nr)
command('normal! x')
tick1 = tick1 + 1
- expectn('nvim_buf_lines_event', {b1, tick1, 0, 1, {'1'}, false})
+ expectn('nvim_buf_lines_event', { b1, tick1, 0, 1, { '1' }, false })
command('undo')
tick1 = tick1 + 1
- expectn('nvim_buf_lines_event', {b1, tick1, 0, 1, {'A1'}, false})
+ expectn('nvim_buf_lines_event', { b1, tick1, 0, 1, { 'A1' }, false })
tick1 = tick1 + 1
- expectn('nvim_buf_changedtick_event', {b1, tick1})
+ expectn('nvim_buf_changedtick_event', { b1, tick1 })
- command('b'..b2nr)
+ command('b' .. b2nr)
command('normal! x')
tick2 = tick2 + 1
- expectn('nvim_buf_lines_event', {b2, tick2, 0, 1, {'1'}, false})
+ expectn('nvim_buf_lines_event', { b2, tick2, 0, 1, { '1' }, false })
command('undo')
tick2 = tick2 + 1
- expectn('nvim_buf_lines_event', {b2, tick2, 0, 1, {'B1'}, false})
+ expectn('nvim_buf_lines_event', { b2, tick2, 0, 1, { 'B1' }, false })
tick2 = tick2 + 1
- expectn('nvim_buf_changedtick_event', {b2, tick2})
+ expectn('nvim_buf_changedtick_event', { b2, tick2 })
- command('b'..b3nr)
+ command('b' .. b3nr)
command('normal! x')
tick3 = tick3 + 1
- expectn('nvim_buf_lines_event', {b3, tick3, 0, 1, {'1'}, false})
+ expectn('nvim_buf_lines_event', { b3, tick3, 0, 1, { '1' }, false })
command('undo')
tick3 = tick3 + 1
- expectn('nvim_buf_lines_event', {b3, tick3, 0, 1, {'C1'}, false})
+ expectn('nvim_buf_lines_event', { b3, tick3, 0, 1, { 'C1' }, false })
tick3 = tick3 + 1
- expectn('nvim_buf_changedtick_event', {b3, tick3})
+ expectn('nvim_buf_changedtick_event', { b3, tick3 })
end)
it('does not get confused if enabled/disabled many times', function()
- local channel = nvim('get_api_info')[1]
+ local channel = api.nvim_get_chan_info(0).id
local b, tick = editoriginal(false)
-- Enable buffer events many times.
- ok(buffer('attach', b, true, {}))
- ok(buffer('attach', b, true, {}))
- ok(buffer('attach', b, true, {}))
- ok(buffer('attach', b, true, {}))
- ok(buffer('attach', b, true, {}))
- expectn('nvim_buf_lines_event', {b, tick, 0, -1, origlines, false})
- eval('rpcnotify('..channel..', "Hello There")')
+ ok(api.nvim_buf_attach(b, true, {}))
+ ok(api.nvim_buf_attach(b, true, {}))
+ ok(api.nvim_buf_attach(b, true, {}))
+ ok(api.nvim_buf_attach(b, true, {}))
+ ok(api.nvim_buf_attach(b, true, {}))
+ expectn('nvim_buf_lines_event', { b, tick, 0, -1, origlines, false })
+ eval('rpcnotify(' .. channel .. ', "Hello There")')
expectn('Hello There', {})
-- Disable buffer events many times.
- ok(buffer('detach', b))
- ok(buffer('detach', b))
- ok(buffer('detach', b))
- ok(buffer('detach', b))
- ok(buffer('detach', b))
- expectn('nvim_buf_detach_event', {b})
- eval('rpcnotify('..channel..', "Hello Again")')
+ ok(api.nvim_buf_detach(b))
+ ok(api.nvim_buf_detach(b))
+ ok(api.nvim_buf_detach(b))
+ ok(api.nvim_buf_detach(b))
+ ok(api.nvim_buf_detach(b))
+ expectn('nvim_buf_detach_event', { b })
+ eval('rpcnotify(' .. channel .. ', "Hello Again")')
expectn('Hello Again', {})
end)
@@ -469,7 +512,7 @@ describe('API: buffer events:', function()
-- create several new sessions, in addition to our main API
local sessions = {}
local pipe = helpers.new_pipename()
- eval("serverstart('"..pipe.."')")
+ eval("serverstart('" .. pipe .. "')")
sessions[1] = helpers.connect(pipe)
sessions[2] = helpers.connect(pipe)
sessions[3] = helpers.connect(pipe)
@@ -484,109 +527,105 @@ describe('API: buffer events:', function()
local function wantn(sessionid, name, args)
local session = sessions[sessionid]
- eq({'notification', name, args}, session:next_message(10000))
+ eq({ 'notification', name, args }, session:next_message(10000))
end
-- Edit a new file, but don't enable buffer events.
- local lines = {'AAA', 'BBB'}
+ local lines = { 'AAA', 'BBB' }
local b, tick = open(false, lines)
-- Enable buffer events for sessions 1, 2 and 3.
ok(request(1, 'nvim_buf_attach', b, true, {}))
ok(request(2, 'nvim_buf_attach', b, true, {}))
ok(request(3, 'nvim_buf_attach', b, true, {}))
- wantn(1, 'nvim_buf_lines_event', {b, tick, 0, -1, lines, false})
- wantn(2, 'nvim_buf_lines_event', {b, tick, 0, -1, lines, false})
- wantn(3, 'nvim_buf_lines_event', {b, tick, 0, -1, lines, false})
+ wantn(1, 'nvim_buf_lines_event', { b, tick, 0, -1, lines, false })
+ wantn(2, 'nvim_buf_lines_event', { b, tick, 0, -1, lines, false })
+ wantn(3, 'nvim_buf_lines_event', { b, tick, 0, -1, lines, false })
-- Change the buffer.
command('normal! x')
tick = tick + 1
- wantn(1, 'nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false})
- wantn(2, 'nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false})
- wantn(3, 'nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false})
+ wantn(1, 'nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false })
+ wantn(2, 'nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false })
+ wantn(3, 'nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false })
-- Stop watching on channel 1.
ok(request(1, 'nvim_buf_detach', b))
- wantn(1, 'nvim_buf_detach_event', {b})
+ wantn(1, 'nvim_buf_detach_event', { b })
-- Undo the change to buffer 1.
command('undo')
tick = tick + 1
- wantn(2, 'nvim_buf_lines_event', {b, tick, 0, 1, {'AAA'}, false})
- wantn(3, 'nvim_buf_lines_event', {b, tick, 0, 1, {'AAA'}, false})
+ wantn(2, 'nvim_buf_lines_event', { b, tick, 0, 1, { 'AAA' }, false })
+ wantn(3, 'nvim_buf_lines_event', { b, tick, 0, 1, { 'AAA' }, false })
tick = tick + 1
- wantn(2, 'nvim_buf_changedtick_event', {b, tick})
- wantn(3, 'nvim_buf_changedtick_event', {b, tick})
+ wantn(2, 'nvim_buf_changedtick_event', { b, tick })
+ wantn(3, 'nvim_buf_changedtick_event', { b, tick })
-- make sure there are no other pending nvim_buf_lines_event messages going to
-- channel 1
- local channel1 = request(1, 'nvim_get_api_info')[1]
- eval('rpcnotify('..channel1..', "Hello")')
+ local channel1 = request(1, 'nvim_get_chan_info', 0).id
+ eval('rpcnotify(' .. channel1 .. ', "Hello")')
wantn(1, 'Hello', {})
-- close the buffer and channels 2 and 3 should get a nvim_buf_detach_event
-- notification
command('edit')
- wantn(2, 'nvim_buf_detach_event', {b})
- wantn(3, 'nvim_buf_detach_event', {b})
+ wantn(2, 'nvim_buf_detach_event', { b })
+ wantn(3, 'nvim_buf_detach_event', { b })
-- make sure there are no other pending nvim_buf_lines_event messages going to
-- channel 1
- channel1 = request(1, 'nvim_get_api_info')[1]
- eval('rpcnotify('..channel1..', "Hello Again")')
+ channel1 = request(1, 'nvim_get_chan_info', 0).id
+ eval('rpcnotify(' .. channel1 .. ', "Hello Again")')
wantn(1, 'Hello Again', {})
end)
it('works with :diffput and :diffget', function()
- local b1, tick1 = editoriginal(true, {"AAA", "BBB"})
- local channel = nvim('get_api_info')[1]
+ local b1, tick1 = editoriginal(true, { 'AAA', 'BBB' })
+ local channel = api.nvim_get_chan_info(0).id
command('diffthis')
command('rightbelow vsplit')
- local b2, tick2 = open(true, {"BBB", "CCC"})
+ local b2, tick2 = open(true, { 'BBB', 'CCC' })
command('diffthis')
-- go back to first buffer, and push the 'AAA' line to the second buffer
command('1wincmd w')
command('normal! gg')
command('diffput')
tick2 = tick2 + 1
- expectn('nvim_buf_lines_event', {b2, tick2, 0, 0, {"AAA"}, false})
+ expectn('nvim_buf_lines_event', { b2, tick2, 0, 0, { 'AAA' }, false })
-- use :diffget to grab the other change from buffer 2
command('normal! G')
command('diffget')
tick1 = tick1 + 1
- expectn('nvim_buf_lines_event', {b1, tick1, 2, 2, {"CCC"}, false})
+ expectn('nvim_buf_lines_event', { b1, tick1, 2, 2, { 'CCC' }, false })
- eval('rpcnotify('..channel..', "Goodbye")')
+ eval('rpcnotify(' .. channel .. ', "Goodbye")')
expectn('Goodbye', {})
end)
it('works with :sort', function()
-- test for :sort
- local b, tick = editoriginal(true, {"B", "D", "C", "A", "E"})
+ local b, tick = editoriginal(true, { 'B', 'D', 'C', 'A', 'E' })
command('%sort')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 5, {"A", "B", "C", "D", "E"}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 5, { 'A', 'B', 'C', 'D', 'E' }, false })
end)
it('works with :left', function()
- local b, tick = editoriginal(true, {" A", " B", "B", "\tB", "\t\tC"})
+ local b, tick = editoriginal(true, { ' A', ' B', 'B', '\tB', '\t\tC' })
command('2,4left')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 4, {"B", "B", "B"}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 1, 4, { 'B', 'B', 'B' }, false })
end)
it('works with :right', function()
- local b, tick = editoriginal(true, {" A",
- "\t B",
- "\t \tBB",
- " \tB",
- "\t\tC"})
+ local b, tick = editoriginal(true, { ' A', '\t B', '\t \tBB', ' \tB', '\t\tC' })
command('set ts=2 et')
command('2,4retab')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 4, {" B", " BB", " B"}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 1, 4, { ' B', ' BB', ' B' }, false })
end)
it('works with :move', function()
@@ -594,19 +633,23 @@ describe('API: buffer events:', function()
-- move text down towards the end of the file
command('2,3move 4')
tick = tick + 2
- expectn('nvim_buf_lines_event', {b, tick, 4, 4, {"original line 2",
- "original line 3"}, false})
+ expectn(
+ 'nvim_buf_lines_event',
+ { b, tick, 4, 4, { 'original line 2', 'original line 3' }, false }
+ )
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 3, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 1, 3, {}, false })
-- move text up towards the start of the file
tick = reopen(b, origlines)
command('4,5move 2')
tick = tick + 2
- expectn('nvim_buf_lines_event', {b, tick, 2, 2, {"original line 4",
- "original line 5"}, false})
+ expectn(
+ 'nvim_buf_lines_event',
+ { b, tick, 2, 2, { 'original line 4', 'original line 5' }, false }
+ )
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 5, 7, {}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 5, 7, {}, false })
end)
it('when you manually add/remove folds', function()
@@ -616,13 +659,14 @@ describe('API: buffer events:', function()
-- delete the inner fold
command('normal! zR3Gzd')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 1, 4, {'original line 2',
- 'original line 3',
- 'original line 4'}, false})
+ expectn(
+ 'nvim_buf_lines_event',
+ { b, tick, 1, 4, { 'original line 2', 'original line 3', 'original line 4' }, false }
+ )
-- delete the outer fold
command('normal! zd')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 6, origlines, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 6, origlines, false })
-- discard changes and put the folds back
tick = reopenwithfolds(b)
@@ -630,7 +674,7 @@ describe('API: buffer events:', function()
-- remove both folds at once
command('normal! ggzczD')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 6, origlines, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 6, origlines, false })
-- discard changes and put the folds back
tick = reopenwithfolds(b)
@@ -638,101 +682,102 @@ describe('API: buffer events:', function()
-- now delete all folds at once
command('normal! zE')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 6, origlines, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 6, origlines, false })
-- create a fold from line 4 to the end of the file
command('normal! 4GA/*{{{*/')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 3, 4, {'original line 4/*{{{*/'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 3, 4, { 'original line 4/*{{{*/' }, false })
-- delete the fold which only has one marker
command('normal! Gzd')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 3, 6, {'original line 4',
- 'original line 5',
- 'original line 6'}, false})
+ expectn(
+ 'nvim_buf_lines_event',
+ { b, tick, 3, 6, { 'original line 4', 'original line 5', 'original line 6' }, false }
+ )
end)
it('detaches if the buffer is closed', function()
- local b, tick = editoriginal(true, {'AAA'})
- local channel = nvim('get_api_info')[1]
+ local b, tick = editoriginal(true, { 'AAA' })
+ local channel = api.nvim_get_chan_info(0).id
-- Test that buffer events are working.
command('normal! x')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false })
command('undo')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AAA'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AAA' }, false })
tick = tick + 1
- expectn('nvim_buf_changedtick_event', {b, tick})
+ expectn('nvim_buf_changedtick_event', { b, tick })
-- close our buffer and create a new one
command('bdelete')
command('enew')
- expectn('nvim_buf_detach_event', {b})
+ expectn('nvim_buf_detach_event', { b })
-- Reopen the original buffer, make sure there are no buffer events sent.
command('b1')
command('normal! x')
- eval('rpcnotify('..channel..', "Hello There")')
+ eval('rpcnotify(' .. channel .. ', "Hello There")')
expectn('Hello There', {})
end)
it(':edit! (reload) causes detach #9642', function()
- local b, tick = editoriginal(true, {'AAA', 'BBB'})
+ local b, tick = editoriginal(true, { 'AAA', 'BBB' })
command('set undoreload=1')
command('normal! x')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false })
command('edit!')
- expectn('nvim_buf_detach_event', {b})
+ expectn('nvim_buf_detach_event', { b })
end)
it(':enew! does not detach hidden buffer', function()
- local b, tick = editoriginal(true, {'AAA', 'BBB'})
- local channel = nvim('get_api_info')[1]
+ local b, tick = editoriginal(true, { 'AAA', 'BBB' })
+ local channel = api.nvim_get_chan_info(0).id
command('set undoreload=1 hidden')
command('normal! x')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false })
command('enew!')
- eval('rpcnotify('..channel..', "Hello There")')
+ eval('rpcnotify(' .. channel .. ', "Hello There")')
expectn('Hello There', {})
end)
it('stays attached if the buffer is hidden', function()
- local b, tick = editoriginal(true, {'AAA'})
- local channel = nvim('get_api_info')[1]
+ local b, tick = editoriginal(true, { 'AAA' })
+ local channel = api.nvim_get_chan_info(0).id
-- Test that buffer events are working.
command('normal! x')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false })
command('undo')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AAA'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AAA' }, false })
tick = tick + 1
- expectn('nvim_buf_changedtick_event', {b, tick})
+ expectn('nvim_buf_changedtick_event', { b, tick })
-- Close our buffer by creating a new one.
command('set hidden')
command('enew')
-- Assert that no nvim_buf_detach_event is sent.
- eval('rpcnotify('..channel..', "Hello There")')
+ eval('rpcnotify(' .. channel .. ', "Hello There")')
expectn('Hello There', {})
-- Reopen the original buffer, assert that buffer events are still active.
command('b1')
command('normal! x')
tick = tick + 1
- expectn('nvim_buf_lines_event', {b, tick, 0, 1, {'AA'}, false})
+ expectn('nvim_buf_lines_event', { b, tick, 0, 1, { 'AA' }, false })
end)
it('detaches if the buffer is unloaded/deleted/wiped', function()
@@ -740,29 +785,29 @@ describe('API: buffer events:', function()
clear()
-- need to make a new window with a buffer because :bunload doesn't let you
-- unload the last buffer
- for _, cmd in ipairs({'bunload', 'bdelete', 'bwipeout'}) do
+ for _, cmd in ipairs({ 'bunload', 'bdelete', 'bwipeout' }) do
command('new')
-- open a brand spanking new file
- local b = open(true, {'AAA'})
+ local b = open(true, { 'AAA' })
-- call :bunload or whatever the command is, and then check that we
-- receive a nvim_buf_detach_event
command(cmd)
- expectn('nvim_buf_detach_event', {b})
+ expectn('nvim_buf_detach_event', { b })
end
end)
it('does not send the buffer content if not requested', function()
clear()
local b, tick = editoriginal(false)
- ok(buffer('attach', b, false, {}))
- expectn('nvim_buf_changedtick_event', {b, tick})
+ ok(api.nvim_buf_attach(b, false, {}))
+ expectn('nvim_buf_changedtick_event', { b, tick })
end)
it('returns a proper error on nonempty options dict', function()
clear()
local b = editoriginal(false)
- eq("Invalid 'opts' key: 'builtin'", pcall_err(buffer, 'attach', b, false, {builtin="asfd"}))
+ eq("Invalid key: 'builtin'", pcall_err(api.nvim_buf_attach, b, false, { builtin = 'asfd' }))
end)
it('nvim_buf_attach returns response after delay #8634', function()
@@ -772,11 +817,13 @@ describe('API: buffer events:', function()
eq(true, helpers.request('nvim_buf_attach', 0, false, {}))
-- notification
eq({
- [1] = 'notification',
- [2] = 'nvim_buf_changedtick_event',
- [3] = {
- [1] = { id = 1 },
- [2] = 2 }, }, next_msg())
+ [1] = 'notification',
+ [2] = 'nvim_buf_changedtick_event',
+ [3] = {
+ [1] = 1,
+ [2] = 2,
+ },
+ }, next_msg())
end)
end)
@@ -786,7 +833,7 @@ describe('API: buffer events:', function()
end)
local function lines_subset(first, second)
- for i = 1,#first do
+ for i = 1, #first do
-- need to ignore trailing spaces
if first[i]:gsub(' +$', '') ~= second[i]:gsub(' +$', '') then
return false
@@ -802,7 +849,7 @@ describe('API: buffer events:', function()
local function assert_match_somewhere(expected_lines, buffer_lines)
local msg = next_msg()
- while(msg ~= nil) do
+ while msg ~= nil do
local event = msg[2]
if event == 'nvim_buf_lines_event' then
local args = msg[3]
@@ -813,7 +860,7 @@ describe('API: buffer events:', function()
-- with the test setup. Note updates are contiguous.
assert(#newlines <= 23)
- for i = 1,#newlines do
+ for i = 1, #newlines do
buffer_lines[starts + i] = newlines[i]
end
-- we don't compare the msg area of the embedded nvim, it's too flakey
@@ -832,36 +879,35 @@ describe('API: buffer events:', function()
it('when :terminal lines change', function()
local buffer_lines = {}
local expected_lines = {}
- command('terminal "'..nvim_prog..'" -u NONE -i NONE -n -c "set shortmess+=A"')
- local b = nvim('get_current_buf')
- ok(buffer('attach', b, true, {}))
+ fn.termopen({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '-n', '-c', 'set shortmess+=A' }, {
+ env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
+ })
- for _ = 1,22 do
- table.insert(expected_lines,'~')
+ local b = api.nvim_get_current_buf()
+ ok(api.nvim_buf_attach(b, true, {}))
+
+ for _ = 1, 22 do
+ table.insert(expected_lines, '~')
end
expected_lines[1] = ''
- expected_lines[22] = ('tmp_terminal_nvim'..(' '):rep(45)
- ..'0,0-1 All')
+ expected_lines[22] = ('tmp_terminal_nvim' .. (' '):rep(45) .. '0,0-1 All')
sendkeys('i:e tmp_terminal_nvim<Enter>')
assert_match_somewhere(expected_lines, buffer_lines)
expected_lines[1] = 'Blarg'
- expected_lines[22] = ('tmp_terminal_nvim [+]'..(' '):rep(41)
- ..'1,6 All')
+ expected_lines[22] = ('tmp_terminal_nvim [+]' .. (' '):rep(41) .. '1,6 All')
sendkeys('iBlarg')
assert_match_somewhere(expected_lines, buffer_lines)
- for i = 1,21 do
+ for i = 1, 21 do
expected_lines[i] = 'xyz'
end
- expected_lines[22] = ('tmp_terminal_nvim [+]'..(' '):rep(41)
- ..'31,4 Bot')
+ expected_lines[22] = ('tmp_terminal_nvim [+]' .. (' '):rep(41) .. '31,4 Bot')
local s = string.rep('\nxyz', 30)
sendkeys(s)
assert_match_somewhere(expected_lines, buffer_lines)
end)
-
end)
diff --git a/test/functional/api/command_spec.lua b/test/functional/api/command_spec.lua
index 1ddb289ded..f73b9c8b13 100644
--- a/test/functional/api/command_spec.lua
+++ b/test/functional/api/command_spec.lua
@@ -1,76 +1,177 @@
local helpers = require('test.functional.helpers')(after_each)
-local NIL = helpers.NIL
+local NIL = vim.NIL
local clear = helpers.clear
local command = helpers.command
-local curbufmeths = helpers.curbufmeths
local eq = helpers.eq
-local meths = helpers.meths
-local bufmeths = helpers.bufmeths
+local api = helpers.api
local matches = helpers.matches
local source = helpers.source
local pcall_err = helpers.pcall_err
local exec_lua = helpers.exec_lua
local assert_alive = helpers.assert_alive
local feed = helpers.feed
-local funcs = helpers.funcs
+local fn = helpers.fn
describe('nvim_get_commands', function()
- local cmd_dict = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='echo "Hello World"', name='Hello', nargs='1', preview=false, range=NIL, register=false, keepscript=false, script_id=0, }
- local cmd_dict2 = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='pwd', name='Pwd', nargs='?', preview=false, range=NIL, register=false, keepscript=false, script_id=0, }
+ local cmd_dict = {
+ addr = NIL,
+ bang = false,
+ bar = false,
+ complete = NIL,
+ complete_arg = NIL,
+ count = NIL,
+ definition = 'echo "Hello World"',
+ name = 'Hello',
+ nargs = '1',
+ preview = false,
+ range = NIL,
+ register = false,
+ keepscript = false,
+ script_id = 0,
+ }
+ local cmd_dict2 = {
+ addr = NIL,
+ bang = false,
+ bar = false,
+ complete = NIL,
+ complete_arg = NIL,
+ count = NIL,
+ definition = 'pwd',
+ name = 'Pwd',
+ nargs = '?',
+ preview = false,
+ range = NIL,
+ register = false,
+ keepscript = false,
+ script_id = 0,
+ }
before_each(clear)
it('gets empty list if no commands were defined', function()
- eq({}, meths.get_commands({builtin=false}))
+ eq({}, api.nvim_get_commands({ builtin = false }))
end)
it('validation', function()
- eq('builtin=true not implemented', pcall_err(meths.get_commands,
- {builtin=true}))
- eq("Invalid key: 'foo'", pcall_err(meths.get_commands,
- {foo='blah'}))
+ eq('builtin=true not implemented', pcall_err(api.nvim_get_commands, { builtin = true }))
+ eq("Invalid key: 'foo'", pcall_err(api.nvim_get_commands, { foo = 'blah' }))
end)
it('gets global user-defined commands', function()
-- Define a command.
command('command -nargs=1 Hello echo "Hello World"')
- eq({Hello=cmd_dict}, meths.get_commands({builtin=false}))
+ eq({ Hello = cmd_dict }, api.nvim_get_commands({ builtin = false }))
-- Define another command.
- command('command -nargs=? Pwd pwd');
- eq({Hello=cmd_dict, Pwd=cmd_dict2}, meths.get_commands({builtin=false}))
+ command('command -nargs=? Pwd pwd')
+ eq({ Hello = cmd_dict, Pwd = cmd_dict2 }, api.nvim_get_commands({ builtin = false }))
-- Delete a command.
command('delcommand Pwd')
- eq({Hello=cmd_dict}, meths.get_commands({builtin=false}))
+ eq({ Hello = cmd_dict }, api.nvim_get_commands({ builtin = false }))
end)
it('gets buffer-local user-defined commands', function()
-- Define a buffer-local command.
command('command -buffer -nargs=1 Hello echo "Hello World"')
- eq({Hello=cmd_dict}, curbufmeths.get_commands({builtin=false}))
+ eq({ Hello = cmd_dict }, api.nvim_buf_get_commands(0, { builtin = false }))
-- Define another buffer-local command.
command('command -buffer -nargs=? Pwd pwd')
- eq({Hello=cmd_dict, Pwd=cmd_dict2}, curbufmeths.get_commands({builtin=false}))
+ eq({ Hello = cmd_dict, Pwd = cmd_dict2 }, api.nvim_buf_get_commands(0, { builtin = false }))
-- Delete a command.
command('delcommand Pwd')
- eq({Hello=cmd_dict}, curbufmeths.get_commands({builtin=false}))
+ eq({ Hello = cmd_dict }, api.nvim_buf_get_commands(0, { builtin = false }))
-- {builtin=true} always returns empty for buffer-local case.
- eq({}, curbufmeths.get_commands({builtin=true}))
+ eq({}, api.nvim_buf_get_commands(0, { builtin = true }))
end)
it('gets various command attributes', function()
- local cmd0 = { addr='arguments', bang=false, bar=false, complete='dir', complete_arg=NIL, count='10', definition='pwd <args>', name='TestCmd', nargs='1', preview=false, range='10', register=false, keepscript=false, script_id=0, }
- local cmd1 = { addr=NIL, bang=false, bar=false, complete='custom', complete_arg='ListUsers', count=NIL, definition='!finger <args>', name='Finger', nargs='+', preview=false, range=NIL, register=false, keepscript=false, script_id=1, }
- local cmd2 = { addr=NIL, bang=true, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R2_foo(<q-args>)', name='Cmd2', nargs='*', preview=false, range=NIL, register=false, keepscript=false, script_id=2, }
- local cmd3 = { addr=NIL, bang=false, bar=true, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R3_ohyeah()', name='Cmd3', nargs='0', preview=false, range=NIL, register=false, keepscript=false, script_id=3, }
- local cmd4 = { addr=NIL, bang=false, bar=false, complete=NIL, complete_arg=NIL, count=NIL, definition='call \128\253R4_just_great()', name='Cmd4', nargs='0', preview=false, range=NIL, register=true, keepscript=false, script_id=4, }
+ local cmd0 = {
+ addr = 'arguments',
+ bang = false,
+ bar = false,
+ complete = 'dir',
+ complete_arg = NIL,
+ count = '10',
+ definition = 'pwd <args>',
+ name = 'TestCmd',
+ nargs = '1',
+ preview = false,
+ range = '10',
+ register = false,
+ keepscript = false,
+ script_id = 0,
+ }
+ local cmd1 = {
+ addr = NIL,
+ bang = false,
+ bar = false,
+ complete = 'custom',
+ complete_arg = 'ListUsers',
+ count = NIL,
+ definition = '!finger <args>',
+ name = 'Finger',
+ nargs = '+',
+ preview = false,
+ range = NIL,
+ register = false,
+ keepscript = false,
+ script_id = 1,
+ }
+ local cmd2 = {
+ addr = NIL,
+ bang = true,
+ bar = false,
+ complete = NIL,
+ complete_arg = NIL,
+ count = NIL,
+ definition = 'call \128\253R2_foo(<q-args>)',
+ name = 'Cmd2',
+ nargs = '*',
+ preview = false,
+ range = NIL,
+ register = false,
+ keepscript = false,
+ script_id = 2,
+ }
+ local cmd3 = {
+ addr = NIL,
+ bang = false,
+ bar = true,
+ complete = NIL,
+ complete_arg = NIL,
+ count = NIL,
+ definition = 'call \128\253R3_ohyeah()',
+ name = 'Cmd3',
+ nargs = '0',
+ preview = false,
+ range = NIL,
+ register = false,
+ keepscript = false,
+ script_id = 3,
+ }
+ local cmd4 = {
+ addr = NIL,
+ bang = false,
+ bar = false,
+ complete = NIL,
+ complete_arg = NIL,
+ count = NIL,
+ definition = 'call \128\253R4_just_great()',
+ name = 'Cmd4',
+ nargs = '0',
+ preview = false,
+ range = NIL,
+ register = true,
+ keepscript = false,
+ script_id = 4,
+ }
source([[
let s:foo = 1
command -complete=custom,ListUsers -nargs=+ Finger !finger <args>
]])
- eq({Finger=cmd1}, meths.get_commands({builtin=false}))
+ eq({ Finger = cmd1 }, api.nvim_get_commands({ builtin = false }))
command('command -nargs=1 -complete=dir -addr=arguments -count=10 TestCmd pwd <args>')
- eq({Finger=cmd1, TestCmd=cmd0}, meths.get_commands({builtin=false}))
+ eq({ Finger = cmd1, TestCmd = cmd0 }, api.nvim_get_commands({ builtin = false }))
source([[
function! s:foo() abort
@@ -88,7 +189,10 @@ describe('nvim_get_commands', function()
command -register Cmd4 call <SID>just_great()
]])
-- TODO(justinmk): Order is stable but undefined. Sort before return?
- eq({Cmd2=cmd2, Cmd3=cmd3, Cmd4=cmd4, Finger=cmd1, TestCmd=cmd0}, meths.get_commands({builtin=false}))
+ eq(
+ { Cmd2 = cmd2, Cmd3 = cmd3, Cmd4 = cmd4, Finger = cmd1, TestCmd = cmd0 },
+ api.nvim_get_commands({ builtin = false })
+ )
end)
end)
@@ -96,9 +200,9 @@ describe('nvim_create_user_command', function()
before_each(clear)
it('works with strings', function()
- meths.create_user_command('SomeCommand', 'let g:command_fired = <args>', {nargs = 1})
- meths.command('SomeCommand 42')
- eq(42, meths.eval('g:command_fired'))
+ api.nvim_create_user_command('SomeCommand', 'let g:command_fired = <args>', { nargs = 1 })
+ command('SomeCommand 42')
+ eq(42, api.nvim_eval('g:command_fired'))
end)
it('works with Lua functions', function()
@@ -113,227 +217,245 @@ describe('nvim_create_user_command', function()
})
]]
- eq({
- name = "CommandWithLuaCallback",
- args = [[this\ is a\ test]],
- fargs = {"this ", "is", "a test"},
- bang = false,
- line1 = 1,
- line2 = 1,
- mods = "",
- smods = {
- browse = false,
- confirm = false,
- emsg_silent = false,
- hide = false,
- horizontal = false,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = false,
- split = "",
- tab = -1,
- unsilent = false,
- verbose = -1,
- vertical = false,
+ eq(
+ {
+ name = 'CommandWithLuaCallback',
+ args = [[this\ is a\ test]],
+ fargs = { 'this ', 'is', 'a test' },
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = '',
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ horizontal = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = '',
+ tab = -1,
+ unsilent = false,
+ verbose = -1,
+ vertical = false,
+ },
+ range = 0,
+ count = 2,
+ reg = '',
},
- range = 0,
- count = 2,
- reg = "",
- }, exec_lua [=[
+ exec_lua [=[
vim.api.nvim_command([[CommandWithLuaCallback this\ is a\ test]])
return result
- ]=])
-
- eq({
- name = "CommandWithLuaCallback",
- args = [[this includes\ a backslash: \\]],
- fargs = {"this", "includes a", "backslash:", "\\"},
- bang = false,
- line1 = 1,
- line2 = 1,
- mods = "",
- smods = {
- browse = false,
- confirm = false,
- emsg_silent = false,
- hide = false,
- horizontal = false,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = false,
- split = "",
- tab = -1,
- unsilent = false,
- verbose = -1,
- vertical = false,
+ ]=]
+ )
+
+ eq(
+ {
+ name = 'CommandWithLuaCallback',
+ args = [[this includes\ a backslash: \\]],
+ fargs = { 'this', 'includes a', 'backslash:', '\\' },
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = '',
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ horizontal = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = '',
+ tab = -1,
+ unsilent = false,
+ verbose = -1,
+ vertical = false,
+ },
+ range = 0,
+ count = 2,
+ reg = '',
},
- range = 0,
- count = 2,
- reg = "",
- }, exec_lua [=[
+ exec_lua [=[
vim.api.nvim_command([[CommandWithLuaCallback this includes\ a backslash: \\]])
return result
- ]=])
-
- eq({
- name = "CommandWithLuaCallback",
- args = "a\\b",
- fargs = {"a\\b"},
- bang = false,
- line1 = 1,
- line2 = 1,
- mods = "",
- smods = {
- browse = false,
- confirm = false,
- emsg_silent = false,
- hide = false,
- horizontal = false,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = false,
- split = "",
- tab = -1,
- unsilent = false,
- verbose = -1,
- vertical = false,
+ ]=]
+ )
+
+ eq(
+ {
+ name = 'CommandWithLuaCallback',
+ args = 'a\\b',
+ fargs = { 'a\\b' },
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = '',
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ horizontal = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = '',
+ tab = -1,
+ unsilent = false,
+ verbose = -1,
+ vertical = false,
+ },
+ range = 0,
+ count = 2,
+ reg = '',
},
- range = 0,
- count = 2,
- reg = "",
- }, exec_lua [=[
+ exec_lua [=[
vim.api.nvim_command('CommandWithLuaCallback a\\b')
return result
- ]=])
-
- eq({
- name = "CommandWithLuaCallback",
- args = 'h\tey ',
- fargs = {[[h]], [[ey]]},
- bang = true,
- line1 = 10,
- line2 = 10,
- mods = "confirm unsilent botright horizontal",
- smods = {
- browse = false,
- confirm = true,
- emsg_silent = false,
- hide = false,
- horizontal = true,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = false,
- split = "botright",
- tab = -1,
- unsilent = true,
- verbose = -1,
- vertical = false,
+ ]=]
+ )
+
+ eq(
+ {
+ name = 'CommandWithLuaCallback',
+ args = 'h\tey ',
+ fargs = { [[h]], [[ey]] },
+ bang = true,
+ line1 = 10,
+ line2 = 10,
+ mods = 'confirm unsilent botright horizontal',
+ smods = {
+ browse = false,
+ confirm = true,
+ emsg_silent = false,
+ hide = false,
+ horizontal = true,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = 'botright',
+ tab = -1,
+ unsilent = true,
+ verbose = -1,
+ vertical = false,
+ },
+ range = 1,
+ count = 10,
+ reg = '',
},
- range = 1,
- count = 10,
- reg = "",
- }, exec_lua [=[
+ exec_lua [=[
vim.api.nvim_command('unsilent horizontal botright confirm 10CommandWithLuaCallback! h\tey ')
return result
- ]=])
-
- eq({
- name = "CommandWithLuaCallback",
- args = "h",
- fargs = {"h"},
- bang = false,
- line1 = 1,
- line2 = 42,
- mods = "",
- smods = {
- browse = false,
- confirm = false,
- emsg_silent = false,
- hide = false,
- horizontal = false,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = false,
- split = "",
- tab = -1,
- unsilent = false,
- verbose = -1,
- vertical = false,
+ ]=]
+ )
+
+ eq(
+ {
+ name = 'CommandWithLuaCallback',
+ args = 'h',
+ fargs = { 'h' },
+ bang = false,
+ line1 = 1,
+ line2 = 42,
+ mods = '',
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ horizontal = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = '',
+ tab = -1,
+ unsilent = false,
+ verbose = -1,
+ vertical = false,
+ },
+ range = 1,
+ count = 42,
+ reg = '',
},
- range = 1,
- count = 42,
- reg = "",
- }, exec_lua [[
+ exec_lua [[
vim.api.nvim_command('CommandWithLuaCallback 42 h')
return result
- ]])
-
- eq({
- name = "CommandWithLuaCallback",
- args = "",
- fargs = {}, -- fargs works without args
- bang = false,
- line1 = 1,
- line2 = 1,
- mods = "",
- smods = {
- browse = false,
- confirm = false,
- emsg_silent = false,
- hide = false,
- horizontal = false,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = false,
- split = "",
- tab = -1,
- unsilent = false,
- verbose = -1,
- vertical = false,
+ ]]
+ )
+
+ eq(
+ {
+ name = 'CommandWithLuaCallback',
+ args = '',
+ fargs = {}, -- fargs works without args
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = '',
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ horizontal = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = '',
+ tab = -1,
+ unsilent = false,
+ verbose = -1,
+ vertical = false,
+ },
+ range = 0,
+ count = 2,
+ reg = '',
},
- range = 0,
- count = 2,
- reg = "",
- }, exec_lua [[
+ exec_lua [[
vim.api.nvim_command('CommandWithLuaCallback')
return result
- ]])
+ ]]
+ )
-- f-args doesn't split when command nargs is 1 or "?"
exec_lua [[
@@ -347,80 +469,86 @@ describe('nvim_create_user_command', function()
})
]]
- eq({
- name = "CommandWithOneOrNoArg",
- args = "hello I'm one argument",
- fargs = {"hello I'm one argument"}, -- Doesn't split args
- bang = false,
- line1 = 1,
- line2 = 1,
- mods = "",
- smods = {
- browse = false,
- confirm = false,
- emsg_silent = false,
- hide = false,
- horizontal = false,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = false,
- split = "",
- tab = -1,
- unsilent = false,
- verbose = -1,
- vertical = false,
+ eq(
+ {
+ name = 'CommandWithOneOrNoArg',
+ args = "hello I'm one argument",
+ fargs = { "hello I'm one argument" }, -- Doesn't split args
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = '',
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ horizontal = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = '',
+ tab = -1,
+ unsilent = false,
+ verbose = -1,
+ vertical = false,
+ },
+ range = 0,
+ count = 2,
+ reg = '',
},
- range = 0,
- count = 2,
- reg = "",
- }, exec_lua [[
+ exec_lua [[
vim.api.nvim_command('CommandWithOneOrNoArg hello I\'m one argument')
return result
- ]])
+ ]]
+ )
-- f-args is an empty table if no args were passed
- eq({
- name = "CommandWithOneOrNoArg",
- args = "",
- fargs = {},
- bang = false,
- line1 = 1,
- line2 = 1,
- mods = "",
- smods = {
- browse = false,
- confirm = false,
- emsg_silent = false,
- hide = false,
- horizontal = false,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = false,
- split = "",
- tab = -1,
- unsilent = false,
- verbose = -1,
- vertical = false,
+ eq(
+ {
+ name = 'CommandWithOneOrNoArg',
+ args = '',
+ fargs = {},
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = '',
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ horizontal = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = '',
+ tab = -1,
+ unsilent = false,
+ verbose = -1,
+ vertical = false,
+ },
+ range = 0,
+ count = 2,
+ reg = '',
},
- range = 0,
- count = 2,
- reg = "",
- }, exec_lua [[
+ exec_lua [[
vim.api.nvim_command('CommandWithOneOrNoArg')
return result
- ]])
+ ]]
+ )
-- f-args is an empty table when the command nargs=0
exec_lua [[
@@ -434,88 +562,93 @@ describe('nvim_create_user_command', function()
register = true,
})
]]
- eq({
- name = "CommandWithNoArgs",
- args = "",
- fargs = {},
- bang = false,
- line1 = 1,
- line2 = 1,
- mods = "",
- smods = {
- browse = false,
- confirm = false,
- emsg_silent = false,
- hide = false,
- horizontal = false,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = false,
- split = "",
- tab = -1,
- unsilent = false,
- verbose = -1,
- vertical = false,
+ eq(
+ {
+ name = 'CommandWithNoArgs',
+ args = '',
+ fargs = {},
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = '',
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ horizontal = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = '',
+ tab = -1,
+ unsilent = false,
+ verbose = -1,
+ vertical = false,
+ },
+ range = 0,
+ count = 2,
+ reg = '',
},
- range = 0,
- count = 2,
- reg = "",
- }, exec_lua [[
+ exec_lua [[
vim.cmd('CommandWithNoArgs')
return result
- ]])
+ ]]
+ )
-- register can be specified
- eq({
- name = "CommandWithNoArgs",
- args = "",
- fargs = {},
- bang = false,
- line1 = 1,
- line2 = 1,
- mods = "",
- smods = {
- browse = false,
- confirm = false,
- emsg_silent = false,
- hide = false,
- horizontal = false,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = false,
- split = "",
- tab = -1,
- unsilent = false,
- verbose = -1,
- vertical = false,
+ eq(
+ {
+ name = 'CommandWithNoArgs',
+ args = '',
+ fargs = {},
+ bang = false,
+ line1 = 1,
+ line2 = 1,
+ mods = '',
+ smods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = false,
+ hide = false,
+ horizontal = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = '',
+ tab = -1,
+ unsilent = false,
+ verbose = -1,
+ vertical = false,
+ },
+ range = 0,
+ count = 2,
+ reg = '+',
},
- range = 0,
- count = 2,
- reg = "+",
- }, exec_lua [[
+ exec_lua [[
vim.cmd('CommandWithNoArgs +')
return result
- ]])
-
+ ]]
+ )
end)
it('can define buffer-local commands', function()
- local bufnr = meths.create_buf(false, false)
- bufmeths.create_user_command(bufnr, "Hello", "", {})
- matches("Not an editor command: Hello", pcall_err(meths.command, "Hello"))
- meths.set_current_buf(bufnr)
- meths.command("Hello")
+ local bufnr = api.nvim_create_buf(false, false)
+ api.nvim_buf_create_user_command(bufnr, 'Hello', '', {})
+ matches('Not an editor command: Hello', pcall_err(command, 'Hello'))
+ api.nvim_set_current_buf(bufnr)
+ command('Hello')
assert_alive()
end)
@@ -537,58 +670,88 @@ describe('nvim_create_user_command', function()
]]
feed(':Test a<Tab>')
- eq('Test aaa', funcs.getcmdline())
+ eq('Test aaa', fn.getcmdline())
feed('<C-U>Test b<Tab>')
- eq('Test bbb', funcs.getcmdline())
+ eq('Test bbb', fn.getcmdline())
end)
it('does not allow invalid command names', function()
- eq("Invalid command name (must start with uppercase): 'test'", pcall_err(exec_lua, [[
+ eq(
+ "Invalid command name (must start with uppercase): 'test'",
+ pcall_err(
+ exec_lua,
+ [[
vim.api.nvim_create_user_command('test', 'echo "hi"', {})
- ]]))
- eq("Invalid command name: 't@'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ eq(
+ "Invalid command name: 't@'",
+ pcall_err(
+ exec_lua,
+ [[
vim.api.nvim_create_user_command('t@', 'echo "hi"', {})
- ]]))
- eq("Invalid command name: 'T@st'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ eq(
+ "Invalid command name: 'T@st'",
+ pcall_err(
+ exec_lua,
+ [[
vim.api.nvim_create_user_command('T@st', 'echo "hi"', {})
- ]]))
- eq("Invalid command name: 'Test!'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ eq(
+ "Invalid command name: 'Test!'",
+ pcall_err(
+ exec_lua,
+ [[
vim.api.nvim_create_user_command('Test!', 'echo "hi"', {})
- ]]))
- eq("Invalid command name: '💩'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ eq(
+ "Invalid command name: '💩'",
+ pcall_err(
+ exec_lua,
+ [[
vim.api.nvim_create_user_command('💩', 'echo "hi"', {})
- ]]))
+ ]]
+ )
+ )
end)
it('smods can be used with nvim_cmd', function()
- exec_lua[[
+ exec_lua [[
vim.api.nvim_create_user_command('MyEcho', function(opts)
vim.api.nvim_cmd({ cmd = 'echo', args = { '&verbose' }, mods = opts.smods }, {})
end, {})
]]
- eq("3", meths.cmd({ cmd = 'MyEcho', mods = { verbose = 3 } }, { output = true }))
+ eq('3', api.nvim_cmd({ cmd = 'MyEcho', mods = { verbose = 3 } }, { output = true }))
- eq(1, #meths.list_tabpages())
- exec_lua[[
+ eq(1, #api.nvim_list_tabpages())
+ exec_lua [[
vim.api.nvim_create_user_command('MySplit', function(opts)
vim.api.nvim_cmd({ cmd = 'split', mods = opts.smods }, {})
end, {})
]]
- meths.cmd({ cmd = 'MySplit' }, {})
- eq(1, #meths.list_tabpages())
- eq(2, #meths.list_wins())
- meths.cmd({ cmd = 'MySplit', mods = { tab = 1 } }, {})
- eq(2, #meths.list_tabpages())
- eq(2, funcs.tabpagenr())
- meths.cmd({ cmd = 'MySplit', mods = { tab = 1 } }, {})
- eq(3, #meths.list_tabpages())
- eq(2, funcs.tabpagenr())
- meths.cmd({ cmd = 'MySplit', mods = { tab = 3 } }, {})
- eq(4, #meths.list_tabpages())
- eq(4, funcs.tabpagenr())
- meths.cmd({ cmd = 'MySplit', mods = { tab = 0 } }, {})
- eq(5, #meths.list_tabpages())
- eq(1, funcs.tabpagenr())
+ api.nvim_cmd({ cmd = 'MySplit' }, {})
+ eq(1, #api.nvim_list_tabpages())
+ eq(2, #api.nvim_list_wins())
+ api.nvim_cmd({ cmd = 'MySplit', mods = { tab = 1 } }, {})
+ eq(2, #api.nvim_list_tabpages())
+ eq(2, fn.tabpagenr())
+ api.nvim_cmd({ cmd = 'MySplit', mods = { tab = 1 } }, {})
+ eq(3, #api.nvim_list_tabpages())
+ eq(2, fn.tabpagenr())
+ api.nvim_cmd({ cmd = 'MySplit', mods = { tab = 3 } }, {})
+ eq(4, #api.nvim_list_tabpages())
+ eq(4, fn.tabpagenr())
+ api.nvim_cmd({ cmd = 'MySplit', mods = { tab = 0 } }, {})
+ eq(5, #api.nvim_list_tabpages())
+ eq(1, fn.tabpagenr())
end)
end)
@@ -596,16 +759,16 @@ describe('nvim_del_user_command', function()
before_each(clear)
it('can delete global commands', function()
- meths.create_user_command('Hello', 'echo "Hi"', {})
- meths.command('Hello')
- meths.del_user_command('Hello')
- matches("Not an editor command: Hello", pcall_err(meths.command, "Hello"))
+ api.nvim_create_user_command('Hello', 'echo "Hi"', {})
+ command('Hello')
+ api.nvim_del_user_command('Hello')
+ matches('Not an editor command: Hello', pcall_err(command, 'Hello'))
end)
it('can delete buffer-local commands', function()
- bufmeths.create_user_command(0, 'Hello', 'echo "Hi"', {})
- meths.command('Hello')
- bufmeths.del_user_command(0, 'Hello')
- matches("Not an editor command: Hello", pcall_err(meths.command, "Hello"))
+ api.nvim_buf_create_user_command(0, 'Hello', 'echo "Hi"', {})
+ command('Hello')
+ api.nvim_buf_del_user_command(0, 'Hello')
+ matches('Not an editor command: Hello', pcall_err(command, 'Hello'))
end)
end)
diff --git a/test/functional/api/extmark_spec.lua b/test/functional/api/extmark_spec.lua
index 44a151cf6a..2acfbfc949 100644
--- a/test/functional/api/extmark_spec.lua
+++ b/test/functional/api/extmark_spec.lua
@@ -4,15 +4,13 @@ local Screen = require('test.functional.ui.screen')
local request = helpers.request
local eq = helpers.eq
local ok = helpers.ok
-local curbufmeths = helpers.curbufmeths
-local bufmeths = helpers.bufmeths
local pcall_err = helpers.pcall_err
local insert = helpers.insert
local feed = helpers.feed
local clear = helpers.clear
local command = helpers.command
local exec = helpers.exec
-local meths = helpers.meths
+local api = helpers.api
local assert_alive = helpers.assert_alive
local function expect(contents)
@@ -26,32 +24,32 @@ local function set_extmark(ns_id, id, line, col, opts)
if id ~= nil and id ~= 0 then
opts.id = id
end
- return curbufmeths.set_extmark(ns_id, line, col, opts)
+ return api.nvim_buf_set_extmark(0, ns_id, line, col, opts)
end
local function get_extmarks(ns_id, start, end_, opts)
if opts == nil then
opts = {}
end
- return curbufmeths.get_extmarks(ns_id, start, end_, opts)
+ return api.nvim_buf_get_extmarks(0, ns_id, start, end_, opts)
end
local function get_extmark_by_id(ns_id, id, opts)
if opts == nil then
opts = {}
end
- return curbufmeths.get_extmark_by_id(ns_id, id, opts)
+ return api.nvim_buf_get_extmark_by_id(0, ns_id, id, opts)
end
local function check_undo_redo(ns, mark, sr, sc, er, ec) --s = start, e = end
local rv = get_extmark_by_id(ns, mark)
- eq({er, ec}, rv)
- feed("u")
+ eq({ er, ec }, rv)
+ feed('u')
rv = get_extmark_by_id(ns, mark)
- eq({sr, sc}, rv)
- feed("<c-r>")
+ eq({ sr, sc }, rv)
+ feed('<c-r>')
rv = get_extmark_by_id(ns, mark)
- eq({er, ec}, rv)
+ eq({ er, ec }, rv)
end
local function batch_set(ns_id, positions)
@@ -64,20 +62,20 @@ end
local function batch_check(ns_id, ids, positions)
local actual, expected = {}, {}
- for i,id in ipairs(ids) do
+ for i, id in ipairs(ids) do
expected[id] = positions[i]
end
for _, mark in pairs(get_extmarks(ns_id, 0, -1, {})) do
- actual[mark[1]] = {mark[2], mark[3]}
+ actual[mark[1]] = { mark[2], mark[3] }
end
eq(expected, actual)
end
local function batch_check_undo_redo(ns_id, ids, before, after)
batch_check(ns_id, ids, after)
- feed("u")
+ feed('u')
batch_check(ns_id, ids, before)
- feed("<c-r>")
+ feed('<c-r>')
batch_check(ns_id, ids, after)
end
@@ -88,49 +86,78 @@ describe('API/extmarks', function()
before_each(function()
-- Initialize some namespaces and insert 12345 into a buffer
- marks = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
- positions = {{0, 0,}, {0, 2}, {0, 3}}
+ marks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
+ positions = { { 0, 0 }, { 0, 2 }, { 0, 3 } }
- init_text = "12345"
+ init_text = '12345'
row = 0
col = 2
clear()
insert(init_text)
- ns = request('nvim_create_namespace', "my-fancy-plugin")
- ns2 = request('nvim_create_namespace', "my-fancy-plugin2")
+ ns = request('nvim_create_namespace', 'my-fancy-plugin')
+ ns2 = request('nvim_create_namespace', 'my-fancy-plugin2')
end)
it('validation', function()
- eq("Invalid 'end_col': expected Integer, got Array", pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = {}, end_row = 1 }))
- eq("Invalid 'end_row': expected Integer, got Array", pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = {} }))
- eq("Invalid 'virt_text_pos': expected String, got Integer", pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 0 }))
- eq("Invalid 'virt_text_pos': 'foo'", pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 'foo' }))
- eq("Invalid 'hl_mode': expected String, got Integer", pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 0 }))
+ eq(
+ "Invalid 'end_col': expected Integer, got Array",
+ pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = {}, end_row = 1 })
+ )
+ eq(
+ "Invalid 'end_row': expected Integer, got Array",
+ pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = {} })
+ )
+ eq(
+ "Invalid 'virt_text_pos': expected String, got Integer",
+ pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 0 })
+ )
+ eq(
+ "Invalid 'virt_text_pos': 'foo'",
+ pcall_err(set_extmark, ns, marks[2], 0, 0, { virt_text_pos = 'foo' })
+ )
+ eq(
+ "Invalid 'hl_mode': expected String, got Integer",
+ pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 0 })
+ )
eq("Invalid 'hl_mode': 'foo'", pcall_err(set_extmark, ns, marks[2], 0, 0, { hl_mode = 'foo' }))
- eq("Invalid 'id': expected Integer, got Array", pcall_err(set_extmark, ns, {}, 0, 0, { end_col = 1, end_row = 1 }))
- eq("Invalid mark position: expected 2 Integer items", pcall_err(get_extmarks, ns, {}, {-1, -1}))
- eq("Invalid mark position: expected mark id Integer or 2-item Array", pcall_err(get_extmarks, ns, true, {-1, -1}))
+ eq(
+ "Invalid 'id': expected Integer, got Array",
+ pcall_err(set_extmark, ns, {}, 0, 0, { end_col = 1, end_row = 1 })
+ )
+ eq(
+ 'Invalid mark position: expected 2 Integer items',
+ pcall_err(get_extmarks, ns, {}, { -1, -1 })
+ )
+ eq(
+ 'Invalid mark position: expected mark id Integer or 2-item Array',
+ pcall_err(get_extmarks, ns, true, { -1, -1 })
+ )
-- No memory leak with virt_text, virt_lines, sign_text
- eq("right_gravity is not a boolean", pcall_err(set_extmark, ns, marks[2], 0, 0, {
- virt_text = {{'foo', 'Normal'}},
- virt_lines = {{{'bar', 'Normal'}}},
- sign_text = 'a',
- right_gravity = 'baz',
- }))
+ eq(
+ 'right_gravity is not a boolean',
+ pcall_err(set_extmark, ns, marks[2], 0, 0, {
+ virt_text = { { 'foo', 'Normal' } },
+ virt_lines = { { { 'bar', 'Normal' } } },
+ sign_text = 'a',
+ right_gravity = 'baz',
+ })
+ )
end)
- it("can end extranges past final newline using end_col = 0", function()
+ it('can end extranges past final newline using end_col = 0', function()
set_extmark(ns, marks[1], 0, 0, {
end_col = 0,
- end_row = 1
+ end_row = 1,
})
- eq("Invalid 'end_col': out of range",
- pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 }))
+ eq(
+ "Invalid 'end_col': out of range",
+ pcall_err(set_extmark, ns, marks[2], 0, 0, { end_col = 1, end_row = 1 })
+ )
end)
- it("can end extranges past final newline when strict mode is false", function()
+ it('can end extranges past final newline when strict mode is false', function()
set_extmark(ns, marks[1], 0, 0, {
end_col = 1,
end_row = 1,
@@ -138,7 +165,7 @@ describe('API/extmarks', function()
})
end)
- it("can end extranges past final column when strict mode is false", function()
+ it('can end extranges past final column when strict mode is false', function()
set_extmark(ns, marks[1], 0, 0, {
end_col = 6,
end_row = 0,
@@ -150,7 +177,7 @@ describe('API/extmarks', function()
local rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2])
eq(marks[1], rv)
rv = get_extmark_by_id(ns, marks[1])
- eq({positions[1][1], positions[1][2]}, rv)
+ eq({ positions[1][1], positions[1][2] }, rv)
-- Test adding a second mark on same row works
rv = set_extmark(ns, marks[2], positions[2][1], positions[2][2])
eq(marks[2], rv)
@@ -159,21 +186,21 @@ describe('API/extmarks', function()
rv = set_extmark(ns, marks[1], positions[1][1], positions[1][2])
eq(marks[1], rv)
rv = get_extmark_by_id(ns, marks[2])
- eq({positions[2][1], positions[2][2]}, rv)
+ eq({ positions[2][1], positions[2][2] }, rv)
-- Test an update, (new pos)
row = positions[1][1]
col = positions[1][2] + 1
rv = set_extmark(ns, marks[1], row, col)
eq(marks[1], rv)
rv = get_extmark_by_id(ns, marks[1])
- eq({row, col}, rv)
+ eq({ row, col }, rv)
-- remove the test marks
- eq(true, curbufmeths.del_extmark(ns, marks[1]))
- eq(false, curbufmeths.del_extmark(ns, marks[1]))
- eq(true, curbufmeths.del_extmark(ns, marks[2]))
- eq(false, curbufmeths.del_extmark(ns, marks[3]))
- eq(false, curbufmeths.del_extmark(ns, 1000))
+ eq(true, api.nvim_buf_del_extmark(0, ns, marks[1]))
+ eq(false, api.nvim_buf_del_extmark(0, ns, marks[1]))
+ eq(true, api.nvim_buf_del_extmark(0, ns, marks[2]))
+ eq(false, api.nvim_buf_del_extmark(0, ns, marks[3]))
+ eq(false, api.nvim_buf_del_extmark(0, ns, 1000))
end)
it('can clear a specific namespace range', function()
@@ -181,15 +208,15 @@ describe('API/extmarks', function()
set_extmark(ns2, 1, 0, 1)
-- force a new undo buffer
feed('o<esc>')
- curbufmeths.clear_namespace(ns2, 0, -1)
- eq({{1, 0, 1}}, get_extmarks(ns, {0, 0}, {-1, -1}))
- eq({}, get_extmarks(ns2, {0, 0}, {-1, -1}))
+ api.nvim_buf_clear_namespace(0, ns2, 0, -1)
+ eq({ { 1, 0, 1 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
+ eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
feed('u')
- eq({{1, 0, 1}}, get_extmarks(ns, {0, 0}, {-1, -1}))
- eq({}, get_extmarks(ns2, {0, 0}, {-1, -1}))
+ eq({ { 1, 0, 1 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
+ eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
feed('<c-r>')
- eq({{1, 0, 1}}, get_extmarks(ns, {0, 0}, {-1, -1}))
- eq({}, get_extmarks(ns2, {0, 0}, {-1, -1}))
+ eq({ { 1, 0, 1 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
+ eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
end)
it('can clear a namespace range using 0,-1', function()
@@ -197,32 +224,32 @@ describe('API/extmarks', function()
set_extmark(ns2, 1, 0, 1)
-- force a new undo buffer
feed('o<esc>')
- curbufmeths.clear_namespace(-1, 0, -1)
- eq({}, get_extmarks(ns, {0, 0}, {-1, -1}))
- eq({}, get_extmarks(ns2, {0, 0}, {-1, -1}))
+ api.nvim_buf_clear_namespace(0, -1, 0, -1)
+ eq({}, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
+ eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
feed('u')
- eq({}, get_extmarks(ns, {0, 0}, {-1, -1}))
- eq({}, get_extmarks(ns2, {0, 0}, {-1, -1}))
+ eq({}, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
+ eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
feed('<c-r>')
- eq({}, get_extmarks(ns, {0, 0}, {-1, -1}))
- eq({}, get_extmarks(ns2, {0, 0}, {-1, -1}))
+ eq({}, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
+ eq({}, get_extmarks(ns2, { 0, 0 }, { -1, -1 }))
end)
it('can undo with extmarks (#25147)', function()
feed('itest<esc>')
set_extmark(ns, 1, 0, 0)
set_extmark(ns, 2, 1, 0)
- eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1}))
+ eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
feed('dd')
- eq({ { 1, 1, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1}))
- curbufmeths.clear_namespace(ns, 0, -1)
- eq({}, get_extmarks(ns, {0, 0}, {-1, -1}))
+ eq({ { 1, 1, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
+ eq({}, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
set_extmark(ns, 1, 0, 0, { right_gravity = false })
set_extmark(ns, 2, 1, 0, { right_gravity = false })
- eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1}))
+ eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
feed('u')
- eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, {0, 0}, {-1, -1}))
- curbufmeths.clear_namespace(ns, 0, -1)
+ eq({ { 1, 0, 0 }, { 2, 1, 0 } }, get_extmarks(ns, { 0, 0 }, { -1, -1 }))
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
end)
it('querying for information and ranges', function()
@@ -237,112 +264,114 @@ describe('API/extmarks', function()
end
-- {0, 0} and {-1, -1} work as extreme values
- eq({{1, 0, 0}}, get_extmarks(ns, {0, 0}, {0, 0}))
- eq({}, get_extmarks(ns, {-1, -1}, {-1, -1}))
- local rv = get_extmarks(ns, {0, 0}, {-1, -1})
+ eq({ { 1, 0, 0 } }, get_extmarks(ns, { 0, 0 }, { 0, 0 }))
+ eq({}, get_extmarks(ns, { -1, -1 }, { -1, -1 }))
+ local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
for i, m in ipairs(marks) do
if positions[i] ~= nil then
- eq({m, positions[i][1], positions[i][2]}, rv[i])
+ eq({ m, positions[i][1], positions[i][2] }, rv[i])
end
end
-- 0 and -1 works as short hand extreme values
- eq({{1, 0, 0}}, get_extmarks(ns, 0, 0))
+ eq({ { 1, 0, 0 } }, get_extmarks(ns, 0, 0))
eq({}, get_extmarks(ns, -1, -1))
rv = get_extmarks(ns, 0, -1)
for i, m in ipairs(marks) do
if positions[i] ~= nil then
- eq({m, positions[i][1], positions[i][2]}, rv[i])
+ eq({ m, positions[i][1], positions[i][2] }, rv[i])
end
end
-- next with mark id
- rv = get_extmarks(ns, marks[1], {-1, -1}, {limit=1})
- eq({{marks[1], positions[1][1], positions[1][2]}}, rv)
- rv = get_extmarks(ns, marks[2], {-1, -1}, {limit=1})
- eq({{marks[2], positions[2][1], positions[2][2]}}, rv)
+ rv = get_extmarks(ns, marks[1], { -1, -1 }, { limit = 1 })
+ eq({ { marks[1], positions[1][1], positions[1][2] } }, rv)
+ rv = get_extmarks(ns, marks[2], { -1, -1 }, { limit = 1 })
+ eq({ { marks[2], positions[2][1], positions[2][2] } }, rv)
-- next with positional when mark exists at position
- rv = get_extmarks(ns, positions[1], {-1, -1}, {limit=1})
- eq({{marks[1], positions[1][1], positions[1][2]}}, rv)
+ rv = get_extmarks(ns, positions[1], { -1, -1 }, { limit = 1 })
+ eq({ { marks[1], positions[1][1], positions[1][2] } }, rv)
-- next with positional index (no mark at position)
- rv = get_extmarks(ns, {positions[1][1], positions[1][2] +1}, {-1, -1}, {limit=1})
- eq({{marks[2], positions[2][1], positions[2][2]}}, rv)
+ rv = get_extmarks(ns, { positions[1][1], positions[1][2] + 1 }, { -1, -1 }, { limit = 1 })
+ eq({ { marks[2], positions[2][1], positions[2][2] } }, rv)
-- next with Extremity index
- rv = get_extmarks(ns, {0,0}, {-1, -1}, {limit=1})
- eq({{marks[1], positions[1][1], positions[1][2]}}, rv)
+ rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 1 })
+ eq({ { marks[1], positions[1][1], positions[1][2] } }, rv)
-- nextrange with mark id
rv = get_extmarks(ns, marks[1], marks[3])
- eq({marks[1], positions[1][1], positions[1][2]}, rv[1])
- eq({marks[2], positions[2][1], positions[2][2]}, rv[2])
+ eq({ marks[1], positions[1][1], positions[1][2] }, rv[1])
+ eq({ marks[2], positions[2][1], positions[2][2] }, rv[2])
-- nextrange with `limit`
- rv = get_extmarks(ns, marks[1], marks[3], {limit=2})
+ rv = get_extmarks(ns, marks[1], marks[3], { limit = 2 })
eq(2, #rv)
-- nextrange with positional when mark exists at position
rv = get_extmarks(ns, positions[1], positions[3])
- eq({marks[1], positions[1][1], positions[1][2]}, rv[1])
- eq({marks[2], positions[2][1], positions[2][2]}, rv[2])
+ eq({ marks[1], positions[1][1], positions[1][2] }, rv[1])
+ eq({ marks[2], positions[2][1], positions[2][2] }, rv[2])
rv = get_extmarks(ns, positions[2], positions[3])
eq(2, #rv)
-- nextrange with positional index (no mark at position)
- local lower = {positions[1][1], positions[2][2] -1}
- local upper = {positions[2][1], positions[3][2] - 1}
+ local lower = { positions[1][1], positions[2][2] - 1 }
+ local upper = { positions[2][1], positions[3][2] - 1 }
rv = get_extmarks(ns, lower, upper)
- eq({{marks[2], positions[2][1], positions[2][2]}}, rv)
- lower = {positions[3][1], positions[3][2] + 1}
- upper = {positions[3][1], positions[3][2] + 2}
+ eq({ { marks[2], positions[2][1], positions[2][2] } }, rv)
+ lower = { positions[3][1], positions[3][2] + 1 }
+ upper = { positions[3][1], positions[3][2] + 2 }
rv = get_extmarks(ns, lower, upper)
eq({}, rv)
-- nextrange with extremity index
- lower = {positions[2][1], positions[2][2]+1}
- upper = {-1, -1}
+ lower = { positions[2][1], positions[2][2] + 1 }
+ upper = { -1, -1 }
rv = get_extmarks(ns, lower, upper)
- eq({{marks[3], positions[3][1], positions[3][2]}}, rv)
+ eq({ { marks[3], positions[3][1], positions[3][2] } }, rv)
-- prev with mark id
- rv = get_extmarks(ns, marks[3], {0, 0}, {limit=1})
- eq({{marks[3], positions[3][1], positions[3][2]}}, rv)
- rv = get_extmarks(ns, marks[2], {0, 0}, {limit=1})
- eq({{marks[2], positions[2][1], positions[2][2]}}, rv)
+ rv = get_extmarks(ns, marks[3], { 0, 0 }, { limit = 1 })
+ eq({ { marks[3], positions[3][1], positions[3][2] } }, rv)
+ rv = get_extmarks(ns, marks[2], { 0, 0 }, { limit = 1 })
+ eq({ { marks[2], positions[2][1], positions[2][2] } }, rv)
-- prev with positional when mark exists at position
- rv = get_extmarks(ns, positions[3], {0, 0}, {limit=1})
- eq({{marks[3], positions[3][1], positions[3][2]}}, rv)
+ rv = get_extmarks(ns, positions[3], { 0, 0 }, { limit = 1 })
+ eq({ { marks[3], positions[3][1], positions[3][2] } }, rv)
-- prev with positional index (no mark at position)
- rv = get_extmarks(ns, {positions[1][1], positions[1][2] +1}, {0, 0}, {limit=1})
- eq({{marks[1], positions[1][1], positions[1][2]}}, rv)
+ rv = get_extmarks(ns, { positions[1][1], positions[1][2] + 1 }, { 0, 0 }, { limit = 1 })
+ eq({ { marks[1], positions[1][1], positions[1][2] } }, rv)
-- prev with Extremity index
- rv = get_extmarks(ns, {-1,-1}, {0,0}, {limit=1})
- eq({{marks[3], positions[3][1], positions[3][2]}}, rv)
+ rv = get_extmarks(ns, { -1, -1 }, { 0, 0 }, { limit = 1 })
+ eq({ { marks[3], positions[3][1], positions[3][2] } }, rv)
-- prevrange with mark id
rv = get_extmarks(ns, marks[3], marks[1])
- eq({marks[3], positions[3][1], positions[3][2]}, rv[1])
- eq({marks[2], positions[2][1], positions[2][2]}, rv[2])
- eq({marks[1], positions[1][1], positions[1][2]}, rv[3])
+ eq({ marks[3], positions[3][1], positions[3][2] }, rv[1])
+ eq({ marks[2], positions[2][1], positions[2][2] }, rv[2])
+ eq({ marks[1], positions[1][1], positions[1][2] }, rv[3])
-- prevrange with limit
- rv = get_extmarks(ns, marks[3], marks[1], {limit=2})
+ rv = get_extmarks(ns, marks[3], marks[1], { limit = 2 })
eq(2, #rv)
-- prevrange with positional when mark exists at position
rv = get_extmarks(ns, positions[3], positions[1])
- eq({{marks[3], positions[3][1], positions[3][2]},
- {marks[2], positions[2][1], positions[2][2]},
- {marks[1], positions[1][1], positions[1][2]}}, rv)
+ eq({
+ { marks[3], positions[3][1], positions[3][2] },
+ { marks[2], positions[2][1], positions[2][2] },
+ { marks[1], positions[1][1], positions[1][2] },
+ }, rv)
rv = get_extmarks(ns, positions[2], positions[1])
eq(2, #rv)
-- prevrange with positional index (no mark at position)
- lower = {positions[2][1], positions[2][2] + 1}
- upper = {positions[3][1], positions[3][2] + 1}
+ lower = { positions[2][1], positions[2][2] + 1 }
+ upper = { positions[3][1], positions[3][2] + 1 }
rv = get_extmarks(ns, upper, lower)
- eq({{marks[3], positions[3][1], positions[3][2]}}, rv)
- lower = {positions[3][1], positions[3][2] + 1}
- upper = {positions[3][1], positions[3][2] + 2}
+ eq({ { marks[3], positions[3][1], positions[3][2] } }, rv)
+ lower = { positions[3][1], positions[3][2] + 1 }
+ upper = { positions[3][1], positions[3][2] + 2 }
rv = get_extmarks(ns, upper, lower)
eq({}, rv)
-- prevrange with extremity index
- lower = {0,0}
- upper = {positions[2][1], positions[2][2] - 1}
+ lower = { 0, 0 }
+ upper = { positions[2][1], positions[2][2] - 1 }
rv = get_extmarks(ns, upper, lower)
- eq({{marks[1], positions[1][1], positions[1][2]}}, rv)
+ eq({ { marks[1], positions[1][1], positions[1][2] } }, rv)
end)
it('querying for information with limit', function()
@@ -354,34 +383,34 @@ describe('API/extmarks', function()
end
end
- local rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=1})
+ local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 1 })
eq(1, #rv)
- rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=2})
+ rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 2 })
eq(2, #rv)
- rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=3})
+ rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 3 })
eq(3, #rv)
-- now in reverse
- rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=1})
+ rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 1 })
eq(1, #rv)
- rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=2})
+ rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 2 })
eq(2, #rv)
- rv = get_extmarks(ns, {0, 0}, {-1, -1}, {limit=3})
+ rv = get_extmarks(ns, { 0, 0 }, { -1, -1 }, { limit = 3 })
eq(3, #rv)
end)
it('get_marks works when mark col > upper col', function()
feed('A<cr>12345<esc>')
feed('A<cr>12345<esc>')
- set_extmark(ns, 10, 0, 2) -- this shouldn't be found
- set_extmark(ns, 11, 2, 1) -- this shouldn't be found
+ set_extmark(ns, 10, 0, 2) -- this shouldn't be found
+ set_extmark(ns, 11, 2, 1) -- this shouldn't be found
set_extmark(ns, marks[1], 0, 4) -- check col > our upper bound
set_extmark(ns, marks[2], 1, 1) -- check col < lower bound
set_extmark(ns, marks[3], 2, 0) -- check is inclusive
- eq({{marks[1], 0, 4},
- {marks[2], 1, 1},
- {marks[3], 2, 0}},
- get_extmarks(ns, {0, 3}, {2, 0}))
+ eq(
+ { { marks[1], 0, 4 }, { marks[2], 1, 1 }, { marks[3], 2, 0 } },
+ get_extmarks(ns, { 0, 3 }, { 2, 0 })
+ )
end)
it('get_marks works in reverse when mark col < lower col', function()
@@ -392,28 +421,24 @@ describe('API/extmarks', function()
set_extmark(ns, marks[1], 2, 1) -- check col < our lower bound
set_extmark(ns, marks[2], 1, 4) -- check col > upper bound
set_extmark(ns, marks[3], 0, 2) -- check is inclusive
- local rv = get_extmarks(ns, {2, 3}, {0, 2})
- eq({{marks[1], 2, 1},
- {marks[2], 1, 4},
- {marks[3], 0, 2}},
- rv)
+ local rv = get_extmarks(ns, { 2, 3 }, { 0, 2 })
+ eq({ { marks[1], 2, 1 }, { marks[2], 1, 4 }, { marks[3], 0, 2 } }, rv)
end)
it('get_marks limit=0 returns nothing', function()
set_extmark(ns, marks[1], positions[1][1], positions[1][2])
- local rv = get_extmarks(ns, {-1, -1}, {-1, -1}, {limit=0})
+ local rv = get_extmarks(ns, { -1, -1 }, { -1, -1 }, { limit = 0 })
eq({}, rv)
end)
-
it('marks move with line insertations', function()
set_extmark(ns, marks[1], 0, 0)
- feed("yyP")
+ feed('yyP')
check_undo_redo(ns, marks[1], 0, 0, 1, 0)
end)
it('marks move with multiline insertations', function()
- feed("a<cr>22<cr>33<esc>")
+ feed('a<cr>22<cr>33<esc>')
set_extmark(ns, marks[1], 1, 1)
feed('ggVGyP')
check_undo_redo(ns, marks[1], 1, 1, 4, 1)
@@ -421,7 +446,7 @@ describe('API/extmarks', function()
it('marks move with line join', function()
-- do_join in ops.c
- feed("a<cr>222<esc>")
+ feed('a<cr>222<esc>')
set_extmark(ns, marks[1], 1, 0)
feed('ggJ')
check_undo_redo(ns, marks[1], 1, 0, 0, 6)
@@ -430,40 +455,33 @@ describe('API/extmarks', function()
it('join works when no marks are present', function()
screen = Screen.new(15, 10)
screen:attach()
- feed("a<cr>1<esc>")
+ feed('a<cr>1<esc>')
feed('kJ')
-- This shouldn't seg fault
screen:expect([[
12345^ 1 |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*8
|
]])
end)
it('marks move with multiline join', function()
-- do_join in ops.c
- feed("a<cr>222<cr>333<cr>444<esc>")
+ feed('a<cr>222<cr>333<cr>444<esc>')
set_extmark(ns, marks[1], 3, 0)
feed('2GVGJ')
check_undo_redo(ns, marks[1], 3, 0, 1, 8)
end)
it('marks move with line deletes', function()
- feed("a<cr>222<cr>333<cr>444<esc>")
+ feed('a<cr>222<cr>333<cr>444<esc>')
set_extmark(ns, marks[1], 2, 1)
feed('ggjdd')
check_undo_redo(ns, marks[1], 2, 1, 1, 1)
end)
it('marks move with multiline deletes', function()
- feed("a<cr>222<cr>333<cr>444<esc>")
+ feed('a<cr>222<cr>333<cr>444<esc>')
set_extmark(ns, marks[1], 3, 0)
feed('gg2dd')
check_undo_redo(ns, marks[1], 3, 0, 1, 0)
@@ -475,7 +493,7 @@ describe('API/extmarks', function()
it('marks move with open line', function()
-- open_line in change.c
-- testing marks below are also moved
- feed("yyP")
+ feed('yyP')
set_extmark(ns, marks[1], 0, 4)
set_extmark(ns, marks[2], 1, 4)
feed('1G<s-o><esc>')
@@ -495,18 +513,11 @@ describe('API/extmarks', function()
insert('abc')
screen:expect([[
ab^c12345 |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*8
|
]])
local rv = get_extmark_by_id(ns, marks[1])
- eq({0, 6}, rv)
+ eq({ 0, 6 }, rv)
check_undo_redo(ns, marks[1], 0, 3, 0, 6)
end)
@@ -515,12 +526,12 @@ describe('API/extmarks', function()
-- insertchar in edit.c (the ins_str branch)
set_extmark(ns, marks[1], 0, 2)
feed('03l')
- insert("X")
+ insert('X')
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
-- check multibyte chars
feed('03l<esc>')
- insert("~~")
+ insert('~~')
check_undo_redo(ns, marks[1], 0, 2, 0, 2)
end)
@@ -544,7 +555,7 @@ describe('API/extmarks', function()
it('marks move with line splits (using enter)', function()
-- open_line in change.c
-- testing marks below are also moved
- feed("yyP")
+ feed('yyP')
set_extmark(ns, marks[1], 0, 4)
set_extmark(ns, marks[2], 1, 4)
feed('1Gla<cr><esc>')
@@ -561,16 +572,16 @@ describe('API/extmarks', function()
it('yet again marks move with line splits', function()
-- the first test above wasn't catching all errors..
- feed("A67890<esc>")
+ feed('A67890<esc>')
set_extmark(ns, marks[1], 0, 4)
- feed("04li<cr><esc>")
+ feed('04li<cr><esc>')
check_undo_redo(ns, marks[1], 0, 4, 1, 0)
end)
it('and one last time line splits...', function()
set_extmark(ns, marks[1], 0, 1)
set_extmark(ns, marks[2], 0, 2)
- feed("02li<cr><esc>")
+ feed('02li<cr><esc>')
check_undo_redo(ns, marks[1], 0, 1, 0, 1)
check_undo_redo(ns, marks[2], 0, 2, 1, 0)
end)
@@ -578,7 +589,7 @@ describe('API/extmarks', function()
it('multiple marks move with mark splits', function()
set_extmark(ns, marks[1], 0, 1)
set_extmark(ns, marks[2], 0, 3)
- feed("0li<cr><esc>")
+ feed('0li<cr><esc>')
check_undo_redo(ns, marks[1], 0, 1, 1, 0)
check_undo_redo(ns, marks[2], 0, 3, 1, 2)
end)
@@ -670,11 +681,11 @@ describe('API/extmarks', function()
feed('0vx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 2)
- feed("u")
+ feed('u')
feed('0vlx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 1)
- feed("u")
+ feed('u')
feed('0v2lx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 0)
@@ -689,16 +700,16 @@ describe('API/extmarks', function()
feed('0x<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 2)
- feed("u")
+ feed('u')
feed('02x<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 1)
- feed("u")
+ feed('u')
feed('0v3lx<esc>')
check_undo_redo(ns, marks[1], 0, 3, 0, 0)
-- from the other side (nothing should happen)
- feed("u")
+ feed('u')
feed('$vx')
check_undo_redo(ns, marks[1], 0, 3, 0, 3)
end)
@@ -756,27 +767,44 @@ describe('API/extmarks', function()
it('delete', function()
local pos1 = {
- {2, 4}, {2, 12}, {2, 13}, {2, 14}, {2, 25},
- {4, 8}, {4, 10}, {4, 20},
- {5, 3}, {6, 10}
+ { 2, 4 },
+ { 2, 12 },
+ { 2, 13 },
+ { 2, 14 },
+ { 2, 25 },
+ { 4, 8 },
+ { 4, 10 },
+ { 4, 20 },
+ { 5, 3 },
+ { 6, 10 },
}
local ids = batch_set(ns, pos1)
batch_check(ns, ids, pos1)
feed('3Gfiv2+ftd')
batch_check_undo_redo(ns, ids, pos1, {
- {2, 4}, {2, 12}, {2, 13}, {2, 13}, {2, 13},
- {2, 13}, {2, 15}, {2, 25},
- {3, 3}, {4, 10}
+ { 2, 4 },
+ { 2, 12 },
+ { 2, 13 },
+ { 2, 13 },
+ { 2, 13 },
+ { 2, 13 },
+ { 2, 15 },
+ { 2, 25 },
+ { 3, 3 },
+ { 4, 10 },
})
end)
it('can get overlapping extmarks', function()
- set_extmark(ns, 1, 0, 0, {end_row = 5, end_col=0})
- set_extmark(ns, 2, 2, 5, {end_row = 2, end_col=30})
- set_extmark(ns, 3, 0, 5, {end_row = 2, end_col=10})
- set_extmark(ns, 4, 0, 0, {end_row = 1, end_col=0})
- eq({{ 2, 2, 5 }}, get_extmarks(ns, {2, 0}, {2, -1}, { overlap=false }))
- eq({{ 1, 0, 0 }, { 3, 0, 5}, {2, 2, 5}}, get_extmarks(ns, {2, 0}, {2, -1}, { overlap=true }))
+ set_extmark(ns, 1, 0, 0, { end_row = 5, end_col = 0 })
+ set_extmark(ns, 2, 2, 5, { end_row = 2, end_col = 30 })
+ set_extmark(ns, 3, 0, 5, { end_row = 2, end_col = 10 })
+ set_extmark(ns, 4, 0, 0, { end_row = 1, end_col = 0 })
+ eq({ { 2, 2, 5 } }, get_extmarks(ns, { 2, 0 }, { 2, -1 }, { overlap = false }))
+ eq(
+ { { 1, 0, 0 }, { 3, 0, 5 }, { 2, 2, 5 } },
+ get_extmarks(ns, { 2, 0 }, { 2, -1 }, { overlap = true })
+ )
end)
end)
@@ -876,33 +904,40 @@ describe('API/extmarks', function()
set_extmark(ns, marks[2], 0, -1)
set_extmark(ns, marks[3], 0, -1)
- feed("u")
- local rv = get_extmarks(ns, {0, 0}, {-1, -1})
+ feed('u')
+ local rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
eq(3, #rv)
- feed("<c-r>")
- rv = get_extmarks(ns, {0, 0}, {-1, -1})
+ feed('<c-r>')
+ rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
eq(3, #rv)
-- Test updates
feed('o<esc>')
set_extmark(ns, marks[1], positions[1][1], positions[1][2])
- rv = get_extmarks(ns, marks[1], marks[1], {limit=1})
+ rv = get_extmarks(ns, marks[1], marks[1], { limit = 1 })
eq(1, #rv)
- feed("u")
- feed("<c-r>")
+ feed('u')
+ feed('<c-r>')
-- old value is NOT kept in history
- check_undo_redo(ns, marks[1], positions[1][1], positions[1][2], positions[1][1], positions[1][2])
+ check_undo_redo(
+ ns,
+ marks[1],
+ positions[1][1],
+ positions[1][2],
+ positions[1][1],
+ positions[1][2]
+ )
-- Test unset
feed('o<esc>')
- curbufmeths.del_extmark(ns, marks[3])
- feed("u")
- rv = get_extmarks(ns, {0, 0}, {-1, -1})
+ api.nvim_buf_del_extmark(0, ns, marks[3])
+ feed('u')
+ rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
-- undo does NOT restore deleted marks
eq(2, #rv)
- feed("<c-r>")
- rv = get_extmarks(ns, {0, 0}, {-1, -1})
+ feed('<c-r>')
+ rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
eq(2, #rv)
end)
@@ -919,9 +954,9 @@ describe('API/extmarks', function()
eq(1, rv)
rv = set_extmark(ns2, marks[1], positions[1][1], positions[1][2])
eq(1, rv)
- rv = get_extmarks(ns, {0, 0}, {-1, -1})
+ rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
eq(1, #rv)
- rv = get_extmarks(ns2, {0, 0}, {-1, -1})
+ rv = get_extmarks(ns2, { 0, 0 }, { -1, -1 })
eq(1, #rv)
-- Set more marks for testing the ranges
@@ -931,14 +966,14 @@ describe('API/extmarks', function()
set_extmark(ns2, marks[3], positions[3][1], positions[3][2])
-- get_next (limit set)
- rv = get_extmarks(ns, {0, 0}, positions[2], {limit=1})
+ rv = get_extmarks(ns, { 0, 0 }, positions[2], { limit = 1 })
eq(1, #rv)
- rv = get_extmarks(ns2, {0, 0}, positions[2], {limit=1})
+ rv = get_extmarks(ns2, { 0, 0 }, positions[2], { limit = 1 })
eq(1, #rv)
-- get_prev (limit set)
- rv = get_extmarks(ns, positions[1], {0, 0}, {limit=1})
+ rv = get_extmarks(ns, positions[1], { 0, 0 }, { limit = 1 })
eq(1, #rv)
- rv = get_extmarks(ns2, positions[1], {0, 0}, {limit=1})
+ rv = get_extmarks(ns2, positions[1], { 0, 0 }, { limit = 1 })
eq(1, #rv)
-- get_next (no limit)
@@ -952,11 +987,11 @@ describe('API/extmarks', function()
rv = get_extmarks(ns2, positions[2], positions[1])
eq(2, #rv)
- curbufmeths.del_extmark(ns, marks[1])
- rv = get_extmarks(ns, {0, 0}, {-1, -1})
+ api.nvim_buf_del_extmark(0, ns, marks[1])
+ rv = get_extmarks(ns, { 0, 0 }, { -1, -1 })
eq(2, #rv)
- curbufmeths.del_extmark(ns2, marks[1])
- rv = get_extmarks(ns2, {0, 0}, {-1, -1})
+ api.nvim_buf_del_extmark(0, ns2, marks[1])
+ rv = get_extmarks(ns2, { 0, 0 }, { -1, -1 })
eq(2, #rv)
end)
@@ -980,16 +1015,16 @@ describe('API/extmarks', function()
feed(':set cindent<cr><esc>')
feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<cr><esc>')
- feed("0iint <esc>A {1M1<esc>b<esc>")
+ feed('0iint <esc>A {1M1<esc>b<esc>')
-- Set the mark on the M, should move..
set_extmark(ns, marks[1], 0, 12)
-- Set the mark before the cursor, should stay there
set_extmark(ns, marks[2], 0, 10)
- feed("i<cr><esc>")
+ feed('i<cr><esc>')
local rv = get_extmark_by_id(ns, marks[1])
- eq({1, 3}, rv)
+ eq({ 1, 3 }, rv)
rv = get_extmark_by_id(ns, marks[2])
- eq({0, 10}, rv)
+ eq({ 0, 10 }, rv)
check_undo_redo(ns, marks[1], 0, 12, 1, 3)
end)
@@ -998,39 +1033,39 @@ describe('API/extmarks', function()
feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<cr><esc>')
-- <c-f> will force an indent of 2
- feed("0iint <esc>A {<cr><esc>0i1M1<esc>")
+ feed('0iint <esc>A {<cr><esc>0i1M1<esc>')
set_extmark(ns, marks[1], 1, 1)
- feed("0i<c-f><esc>")
+ feed('0i<c-f><esc>')
local rv = get_extmark_by_id(ns, marks[1])
- eq({1, 3}, rv)
+ eq({ 1, 3 }, rv)
check_undo_redo(ns, marks[1], 1, 1, 1, 3)
-- now check when cursor at eol
- feed("uA<c-f><esc>")
+ feed('uA<c-f><esc>')
rv = get_extmark_by_id(ns, marks[1])
- eq({1, 3}, rv)
+ eq({ 1, 3 }, rv)
end)
it('removing auto indenting with <C-D> works', function()
feed(':set cindent<cr><esc>')
feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<cr><esc>')
- feed("0i<tab><esc>")
+ feed('0i<tab><esc>')
set_extmark(ns, marks[1], 0, 3)
- feed("bi<c-d><esc>")
+ feed('bi<c-d><esc>')
local rv = get_extmark_by_id(ns, marks[1])
- eq({0, 1}, rv)
+ eq({ 0, 1 }, rv)
check_undo_redo(ns, marks[1], 0, 3, 0, 1)
-- check when cursor at eol
- feed("uA<c-d><esc>")
+ feed('uA<c-d><esc>')
rv = get_extmark_by_id(ns, marks[1])
- eq({0, 1}, rv)
+ eq({ 0, 1 }, rv)
end)
it('indenting multiple lines with = works', function()
feed(':set cindent<cr><esc>')
feed(':set autoindent<cr><esc>')
feed(':set shiftwidth=2<cr><esc>')
- feed("0iint <esc>A {<cr><bs>1M1<cr><bs>2M2<esc>")
+ feed('0iint <esc>A {<cr><bs>1M1<cr><bs>2M2<esc>')
set_extmark(ns, marks[1], 1, 1)
set_extmark(ns, marks[2], 2, 1)
feed('=gg')
@@ -1152,7 +1187,7 @@ describe('API/extmarks', function()
check_undo_redo(ns, marks[5], 2, 0, 3, 0)
feed('u')
feed([[:1,2s:3:\rxx<cr>]])
- eq({1, 3}, get_extmark_by_id(ns, marks[3]))
+ eq({ 1, 3 }, get_extmark_by_id(ns, marks[3]))
end)
it('substitutes over multiple lines with replace in substitution', function()
@@ -1388,8 +1423,11 @@ describe('API/extmarks', function()
it('throws consistent error codes', function()
local ns_invalid = ns2 + 1
- eq("Invalid 'ns_id': 3", pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2]))
- eq("Invalid 'ns_id': 3", pcall_err(curbufmeths.del_extmark, ns_invalid, marks[1]))
+ eq(
+ "Invalid 'ns_id': 3",
+ pcall_err(set_extmark, ns_invalid, marks[1], positions[1][1], positions[1][2])
+ )
+ eq("Invalid 'ns_id': 3", pcall_err(api.nvim_buf_del_extmark, 0, ns_invalid, marks[1]))
eq("Invalid 'ns_id': 3", pcall_err(get_extmarks, ns_invalid, positions[1], positions[2]))
eq("Invalid 'ns_id': 3", pcall_err(get_extmark_by_id, ns_invalid, marks[1]))
end)
@@ -1397,11 +1435,11 @@ describe('API/extmarks', function()
it('when col = line-length, set the mark on eol', function()
set_extmark(ns, marks[1], 0, -1)
local rv = get_extmark_by_id(ns, marks[1])
- eq({0, init_text:len()}, rv)
+ eq({ 0, init_text:len() }, rv)
-- Test another
set_extmark(ns, marks[1], 0, -1)
rv = get_extmark_by_id(ns, marks[1])
- eq({0, init_text:len()}, rv)
+ eq({ 0, init_text:len() }, rv)
end)
it('when col = line-length, set the mark on eol', function()
@@ -1412,7 +1450,10 @@ describe('API/extmarks', function()
it('fails when line > line_count', function()
local invalid_col = init_text:len() + 1
local invalid_lnum = 3
- eq("Invalid 'line': out of range", pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col))
+ eq(
+ "Invalid 'line': out of range",
+ pcall_err(set_extmark, ns, marks[1], invalid_lnum, invalid_col)
+ )
eq({}, get_extmark_by_id(ns, marks[1]))
end)
@@ -1428,17 +1469,17 @@ describe('API/extmarks', function()
end)
it('in read-only buffer', function()
- command("view! runtime/doc/help.txt")
- eq(true, meths.get_option_value('ro', {}))
+ command('view! runtime/doc/help.txt')
+ eq(true, api.nvim_get_option_value('ro', {}))
local id = set_extmark(ns, 0, 0, 2)
- eq({{id, 0, 2}}, get_extmarks(ns,0, -1))
+ eq({ { id, 0, 2 } }, get_extmarks(ns, 0, -1))
end)
it('can set a mark to other buffer', function()
local buf = request('nvim_create_buf', 0, 1)
- request('nvim_buf_set_lines', buf, 0, -1, 1, {"", ""})
- local id = bufmeths.set_extmark(buf, ns, 1, 0, {})
- eq({{id, 1, 0}}, bufmeths.get_extmarks(buf, ns, 0, -1, {}))
+ request('nvim_buf_set_lines', buf, 0, -1, 1, { '', '' })
+ local id = api.nvim_buf_set_extmark(buf, ns, 1, 0, {})
+ eq({ { id, 1, 0 } }, api.nvim_buf_get_extmarks(buf, ns, 0, -1, {}))
end)
it('does not crash with append/delete/undo sequence', function()
@@ -1454,210 +1495,274 @@ describe('API/extmarks', function()
it('works with left and right gravity', function()
-- right gravity should move with inserted text, while
-- left gravity should stay in place.
- curbufmeths.set_extmark(ns, 0, 5, {right_gravity = false})
- curbufmeths.set_extmark(ns, 0, 5, {right_gravity = true})
+ api.nvim_buf_set_extmark(0, ns, 0, 5, { right_gravity = false })
+ api.nvim_buf_set_extmark(0, ns, 0, 5, { right_gravity = true })
feed([[Aasdfasdf]])
- eq({ {1, 0, 5}, {2, 0, 13} },
- curbufmeths.get_extmarks(ns, 0, -1, {}))
+ eq({ { 1, 0, 5 }, { 2, 0, 13 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {}))
-- but both move when text is inserted before
feed([[<esc>Iasdf<esc>]])
- -- eq({}, curbufmeths.get_lines(0, -1, true))
- eq({ {1, 0, 9}, {2, 0, 17} },
- curbufmeths.get_extmarks(ns, 0, -1, {}))
+ -- eq({}, api.nvim_buf_get_lines(0, 0, -1, true))
+ eq({ { 1, 0, 9 }, { 2, 0, 17 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {}))
-- clear text
- curbufmeths.set_text(0, 0, 0, 17, {})
+ api.nvim_buf_set_text(0, 0, 0, 0, 17, {})
-- handles set_text correctly as well
- eq({ {1, 0, 0}, {2, 0, 0} },
- meths.buf_get_extmarks(0, ns, 0, -1, {}))
- curbufmeths.set_text(0, 0, 0, 0, {'asdfasdf'})
- eq({ {1, 0, 0}, {2, 0, 8} },
- curbufmeths.get_extmarks(ns, 0, -1, {}))
+ eq({ { 1, 0, 0 }, { 2, 0, 0 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {}))
+ api.nvim_buf_set_text(0, 0, 0, 0, 0, { 'asdfasdf' })
+ eq({ { 1, 0, 0 }, { 2, 0, 8 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {}))
feed('u')
-- handles pasting
exec([[let @a='asdfasdf']])
feed([["ap]])
- eq({ {1, 0, 0}, {2, 0, 8} },
- meths.buf_get_extmarks(0, ns, 0, -1, {}))
+ eq({ { 1, 0, 0 }, { 2, 0, 8 } }, api.nvim_buf_get_extmarks(0, ns, 0, -1, {}))
end)
it('can accept "end_row" or "end_line" #16548', function()
set_extmark(ns, marks[1], 0, 0, {
end_col = 0,
- end_line = 1
+ end_line = 1,
})
- eq({ {1, 0, 0, {
- ns_id = 1,
- end_col = 0,
- end_row = 1,
- right_gravity = true,
- end_right_gravity = false,
- }} }, get_extmarks(ns, 0, -1, {details=true}))
+ eq({
+ {
+ 1,
+ 0,
+ 0,
+ {
+ ns_id = 1,
+ end_col = 0,
+ end_row = 1,
+ right_gravity = true,
+ end_right_gravity = false,
+ },
+ },
+ }, get_extmarks(ns, 0, -1, { details = true }))
end)
it('in prompt buffer', function()
feed('dd')
local id = set_extmark(ns, marks[1], 0, 0, {})
- meths.set_option_value('buftype', 'prompt', {})
+ api.nvim_set_option_value('buftype', 'prompt', {})
feed('i<esc>')
- eq({{id, 0, 2}}, get_extmarks(ns, 0, -1))
+ eq({ { id, 0, 2 } }, get_extmarks(ns, 0, -1))
end)
it('can get details', function()
set_extmark(ns, marks[1], 0, 0, {
- conceal = "c",
- cursorline_hl_group = "Statement",
+ conceal = 'c',
+ cursorline_hl_group = 'Statement',
end_col = 0,
end_right_gravity = true,
end_row = 1,
hl_eol = true,
- hl_group = "String",
- hl_mode = "blend",
- line_hl_group = "Statement",
- number_hl_group = "Statement",
+ hl_group = 'String',
+ hl_mode = 'blend',
+ line_hl_group = 'Statement',
+ number_hl_group = 'Statement',
priority = 0,
right_gravity = false,
- sign_hl_group = "Statement",
- sign_text = ">>",
+ sign_hl_group = 'Statement',
+ sign_text = '>>',
spell = true,
virt_lines = {
- { { "lines", "Macro" }, { "???" } },
- { { "stack", { "Type", "Search" } }, { "!!!" } },
+ { { 'lines', 'Macro' }, { '???' } },
+ { { 'stack', { 'Type', 'Search' } }, { '!!!' } },
},
virt_lines_above = true,
virt_lines_leftcol = true,
- virt_text = { { "text", "Macro" }, { "???" }, { "stack", { "Type", "Search" } } },
+ virt_text = { { 'text', 'Macro' }, { '???' }, { 'stack', { 'Type', 'Search' } } },
virt_text_hide = true,
- virt_text_pos = "right_align",
+ virt_text_pos = 'right_align',
})
set_extmark(ns, marks[2], 0, 0, {
priority = 0,
- virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } },
+ virt_text = { { '', 'Macro' }, { '', { 'Type', 'Search' } }, { '' } },
virt_text_win_col = 1,
})
- eq({0, 0, {
- conceal = "c",
- cursorline_hl_group = "Statement",
- end_col = 0,
- end_right_gravity = true,
- end_row = 1,
- hl_eol = true,
- hl_group = "String",
- hl_mode = "blend",
- line_hl_group = "Statement",
- ns_id = 1,
- number_hl_group = "Statement",
- priority = 0,
- right_gravity = false,
- sign_hl_group = "Statement",
- sign_text = ">>",
+ eq({
+ 0,
+ 0,
+ {
+ conceal = 'c',
+ cursorline_hl_group = 'Statement',
+ end_col = 0,
+ end_right_gravity = true,
+ end_row = 1,
+ hl_eol = true,
+ hl_group = 'String',
+ hl_mode = 'blend',
+ line_hl_group = 'Statement',
+ ns_id = 1,
+ number_hl_group = 'Statement',
+ priority = 0,
+ right_gravity = false,
+ sign_hl_group = 'Statement',
+ sign_text = '>>',
+ spell = true,
+ virt_lines = {
+ { { 'lines', 'Macro' }, { '???' } },
+ { { 'stack', { 'Type', 'Search' } }, { '!!!' } },
+ },
+ virt_lines_above = true,
+ virt_lines_leftcol = true,
+ virt_text = { { 'text', 'Macro' }, { '???' }, { 'stack', { 'Type', 'Search' } } },
+ virt_text_repeat_linebreak = false,
+ virt_text_hide = true,
+ virt_text_pos = 'right_align',
+ },
+ }, get_extmark_by_id(ns, marks[1], { details = true }))
+ eq({
+ 0,
+ 0,
+ {
+ ns_id = 1,
+ right_gravity = true,
+ priority = 0,
+ virt_text = { { '', 'Macro' }, { '', { 'Type', 'Search' } }, { '' } },
+ virt_text_repeat_linebreak = false,
+ virt_text_hide = false,
+ virt_text_pos = 'win_col',
+ virt_text_win_col = 1,
+ },
+ }, get_extmark_by_id(ns, marks[2], { details = true }))
+ set_extmark(ns, marks[3], 0, 0, { cursorline_hl_group = 'Statement' })
+ eq({
+ 0,
+ 0,
+ {
+ ns_id = 1,
+ cursorline_hl_group = 'Statement',
+ priority = 4096,
+ right_gravity = true,
+ },
+ }, get_extmark_by_id(ns, marks[3], { details = true }))
+ set_extmark(ns, marks[4], 0, 0, {
+ end_col = 1,
+ conceal = 'a',
spell = true,
- virt_lines = {
- { { "lines", "Macro" }, { "???" } },
- { { "stack", { "Type", "Search" } }, { "!!!" } },
+ })
+ eq({
+ 0,
+ 0,
+ {
+ conceal = 'a',
+ end_col = 1,
+ end_right_gravity = false,
+ end_row = 0,
+ ns_id = 1,
+ right_gravity = true,
+ spell = true,
},
- virt_lines_above = true,
- virt_lines_leftcol = true,
- virt_text = { { "text", "Macro" }, { "???" }, { "stack", { "Type", "Search" } } },
- virt_text_hide = true,
- virt_text_pos = "right_align",
- } }, get_extmark_by_id(ns, marks[1], { details = true }))
- eq({0, 0, {
- ns_id = 1,
- right_gravity = true,
- priority = 0,
- virt_text = { { "", "Macro" }, { "", { "Type", "Search" } }, { "" } },
- virt_text_hide = false,
- virt_text_pos = "win_col",
- virt_text_win_col = 1,
- } }, get_extmark_by_id(ns, marks[2], { details = true }))
- set_extmark(ns, marks[3], 0, 0, { cursorline_hl_group = "Statement" })
- eq({0, 0, {
- ns_id = 1,
- cursorline_hl_group = "Statement",
- priority = 4096,
- right_gravity = true,
- } }, get_extmark_by_id(ns, marks[3], { details = true }))
- curbufmeths.clear_namespace(ns, 0, -1)
+ }, get_extmark_by_id(ns, marks[4], { details = true }))
+ set_extmark(ns, marks[5], 0, 0, {
+ end_col = 1,
+ spell = false,
+ })
+ eq({
+ 0,
+ 0,
+ {
+ end_col = 1,
+ end_right_gravity = false,
+ end_row = 0,
+ ns_id = 1,
+ right_gravity = true,
+ spell = false,
+ },
+ }, get_extmark_by_id(ns, marks[5], { details = true }))
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
-- legacy sign mark includes sign name
command('sign define sign1 text=s1 texthl=Title linehl=LineNR numhl=Normal culhl=CursorLine')
command('sign place 1 name=sign1 line=1')
- eq({ {1, 0, 0, {
- cursorline_hl_group = 'CursorLine',
- invalidate = true,
- line_hl_group = 'LineNr',
- ns_id = 0,
- number_hl_group = 'Normal',
- priority = 10,
- right_gravity = true,
- sign_hl_group = 'Title',
- sign_name = 'sign1',
- sign_text = 's1',
- undo_restore = false
- } } }, get_extmarks(-1, 0, -1, { details = true }))
+ eq({
+ {
+ 1,
+ 0,
+ 0,
+ {
+ cursorline_hl_group = 'CursorLine',
+ invalidate = true,
+ line_hl_group = 'LineNr',
+ ns_id = 0,
+ number_hl_group = 'Normal',
+ priority = 10,
+ right_gravity = true,
+ sign_hl_group = 'Title',
+ sign_name = 'sign1',
+ sign_text = 's1',
+ undo_restore = false,
+ },
+ },
+ }, get_extmarks(-1, 0, -1, { details = true }))
end)
it('can get marks from anonymous namespaces', function()
- ns = request('nvim_create_namespace', "")
- ns2 = request('nvim_create_namespace', "")
+ ns = request('nvim_create_namespace', '')
+ ns2 = request('nvim_create_namespace', '')
set_extmark(ns, 1, 0, 0, {})
set_extmark(ns2, 2, 1, 0, {})
- eq({{ 1, 0, 0, { ns_id = ns, right_gravity = true }},
- { 2, 1, 0, { ns_id = ns2, right_gravity = true }}},
- get_extmarks(-1, 0, -1, { details = true }))
+ eq({
+ { 1, 0, 0, { ns_id = ns, right_gravity = true } },
+ { 2, 1, 0, { ns_id = ns2, right_gravity = true } },
+ }, get_extmarks(-1, 0, -1, { details = true }))
end)
it('can filter by extmark properties', function()
set_extmark(ns, 1, 0, 0, {})
set_extmark(ns, 2, 0, 0, { hl_group = 'Normal' })
set_extmark(ns, 3, 0, 0, { sign_text = '>>' })
- set_extmark(ns, 4, 0, 0, { virt_text = {{'text', 'Normal'}}})
- set_extmark(ns, 5, 0, 0, { virt_lines = {{{ 'line', 'Normal' }}}})
+ set_extmark(ns, 4, 0, 0, { virt_text = { { 'text', 'Normal' } } })
+ set_extmark(ns, 5, 0, 0, { virt_lines = { { { 'line', 'Normal' } } } })
eq(5, #get_extmarks(-1, 0, -1, {}))
- eq({{ 2, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'highlight' }))
- eq({{ 3, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'sign' }))
- eq({{ 4, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'virt_text' }))
- eq({{ 5, 0, 0 }}, get_extmarks(-1, 0, -1, { type = 'virt_lines' }))
+ eq({ { 2, 0, 0 } }, get_extmarks(-1, 0, -1, { type = 'highlight' }))
+ eq({ { 3, 0, 0 } }, get_extmarks(-1, 0, -1, { type = 'sign' }))
+ eq({ { 4, 0, 0 } }, get_extmarks(-1, 0, -1, { type = 'virt_text' }))
+ eq({ { 5, 0, 0 } }, get_extmarks(-1, 0, -1, { type = 'virt_lines' }))
end)
- it("invalidated marks are deleted", function()
+ it('invalidated marks are deleted', function()
screen = Screen.new(40, 6)
screen:attach()
feed('dd6iaaa bbb ccc<CR><ESC>gg')
- set_extmark(ns, 1, 0, 0, { invalidate = true, sign_text = 'S1' })
- set_extmark(ns, 2, 1, 0, { invalidate = true, sign_text = 'S2' })
+ api.nvim_set_option_value('signcolumn', 'auto:2', {})
+ set_extmark(ns, 1, 0, 0, { invalidate = true, sign_text = 'S1', end_row = 1 })
+ set_extmark(ns, 2, 1, 0, { invalidate = true, sign_text = 'S2', end_row = 2 })
-- mark with invalidate is removed
- command('d')
+ command('d2')
screen:expect([[
S2^aaa bbb ccc |
- aaa bbb ccc |
- aaa bbb ccc |
- aaa bbb ccc |
- aaa bbb ccc |
- |
+ aaa bbb ccc |*3
+ |*2
]])
-- mark is restored with undo_restore == true
command('silent undo')
screen:expect([[
- S1^aaa bbb ccc |
- S2aaa bbb ccc |
- aaa bbb ccc |
- aaa bbb ccc |
- aaa bbb ccc |
+ S1 ^aaa bbb ccc |
+ S1S2aaa bbb ccc |
+ S2 aaa bbb ccc |
+ aaa bbb ccc |*2
|
]])
+ -- decor is not removed twice
+ command('d3')
+ api.nvim_buf_del_extmark(0, ns, 1)
+ command('silent undo')
-- mark is deleted with undo_restore == false
set_extmark(ns, 1, 0, 0, { invalidate = true, undo_restore = false, sign_text = 'S1' })
set_extmark(ns, 2, 1, 0, { invalidate = true, undo_restore = false, sign_text = 'S2' })
command('1d 2')
eq(0, #get_extmarks(-1, 0, -1, {}))
-- mark is not removed when deleting bytes before the range
- set_extmark(ns, 3, 0, 4, { invalidate = true, undo_restore = false,
- hl_group = 'Error', end_col = 7 })
+ set_extmark(
+ ns,
+ 3,
+ 0,
+ 4,
+ { invalidate = true, undo_restore = false, hl_group = 'Error', end_col = 7 }
+ )
feed('dw')
eq(3, get_extmark_by_id(ns, 3, { details = true })[3].end_col)
-- mark is not removed when deleting bytes at the start of the range
@@ -1665,22 +1770,64 @@ describe('API/extmarks', function()
eq(2, get_extmark_by_id(ns, 3, { details = true })[3].end_col)
-- mark is not removed when deleting bytes from the end of the range
feed('lx')
- eq(1, get_extmark_by_id(ns, 3, { details = true})[3].end_col)
+ eq(1, get_extmark_by_id(ns, 3, { details = true })[3].end_col)
-- mark is not removed when deleting bytes beyond end of the range
feed('x')
- eq(1, get_extmark_by_id(ns, 3, { details = true})[3].end_col)
+ eq(1, get_extmark_by_id(ns, 3, { details = true })[3].end_col)
-- mark is removed when all bytes in the range are deleted
feed('hx')
eq({}, get_extmark_by_id(ns, 3, {}))
-- multiline mark is not removed when start of its range is deleted
- set_extmark(ns, 4, 1, 4, { undo_restore = false, invalidate = true,
- hl_group = 'Error', end_col = 7, end_row = 3 })
+ set_extmark(
+ ns,
+ 4,
+ 1,
+ 4,
+ { undo_restore = false, invalidate = true, hl_group = 'Error', end_col = 7, end_row = 3 }
+ )
feed('ddDdd')
- eq({0, 0}, get_extmark_by_id(ns, 4, {}))
+ eq({ 0, 0 }, get_extmark_by_id(ns, 4, {}))
-- multiline mark is removed when entirety of its range is deleted
feed('vj2ed')
eq({}, get_extmark_by_id(ns, 4, {}))
end)
+
+ it('can set a URL', function()
+ set_extmark(ns, 1, 0, 0, { url = 'https://example.com', end_col = 3 })
+ local extmarks = get_extmarks(ns, 0, -1, { details = true })
+ eq(1, #extmarks)
+ eq('https://example.com', extmarks[1][4].url)
+ end)
+
+ it('respects priority', function()
+ screen = Screen.new(15, 10)
+ screen:attach()
+
+ set_extmark(ns, marks[1], 0, 0, {
+ hl_group = 'Comment',
+ end_col = 2,
+ priority = 20,
+ })
+
+ -- Extmark defined after first extmark but has lower priority, first extmark "wins"
+ set_extmark(ns, marks[2], 0, 0, {
+ hl_group = 'String',
+ end_col = 2,
+ priority = 10,
+ })
+
+ screen:expect {
+ grid = [[
+ {1:12}34^5 |
+ {2:~ }|*8
+ |
+ ]],
+ attr_ids = {
+ [1] = { foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Blue1, bold = true },
+ },
+ }
+ end)
end)
describe('Extmarks buffer api with many marks', function()
@@ -1689,29 +1836,28 @@ describe('Extmarks buffer api with many marks', function()
local ns_marks = {}
before_each(function()
clear()
- ns1 = request('nvim_create_namespace', "ns1")
- ns2 = request('nvim_create_namespace', "ns2")
- ns_marks = {[ns1]={}, [ns2]={}}
+ ns1 = request('nvim_create_namespace', 'ns1')
+ ns2 = request('nvim_create_namespace', 'ns2')
+ ns_marks = { [ns1] = {}, [ns2] = {} }
local lines = {}
- for i = 1,30 do
- lines[#lines+1] = string.rep("x ",i)
+ for i = 1, 30 do
+ lines[#lines + 1] = string.rep('x ', i)
end
- curbufmeths.set_lines(0, -1, true, lines)
+ api.nvim_buf_set_lines(0, 0, -1, true, lines)
local ns = ns1
local q = 0
- for i = 0,29 do
- for j = 0,i do
- local id = set_extmark(ns,0, i,j)
+ for i = 0, 29 do
+ for j = 0, i do
+ local id = set_extmark(ns, 0, i, j)
eq(nil, ns_marks[ns][id])
ok(id > 0)
- ns_marks[ns][id] = {i,j}
- ns = ns1+ns2-ns
+ ns_marks[ns][id] = { i, j }
+ ns = ns1 + ns2 - ns
q = q + 1
end
end
eq(233, #ns_marks[ns1])
eq(232, #ns_marks[ns2])
-
end)
local function get_marks(ns)
@@ -1719,28 +1865,28 @@ describe('Extmarks buffer api with many marks', function()
local marks = {}
for _, mark in ipairs(mark_list) do
local id, row, col = unpack(mark)
- eq(nil, marks[id], "duplicate mark")
- marks[id] = {row,col}
+ eq(nil, marks[id], 'duplicate mark')
+ marks[id] = { row, col }
end
return marks
end
- it("can get marks", function()
+ it('can get marks', function()
eq(ns_marks[ns1], get_marks(ns1))
eq(ns_marks[ns2], get_marks(ns2))
end)
- it("can clear all marks in ns", function()
- curbufmeths.clear_namespace(ns1, 0, -1)
+ it('can clear all marks in ns', function()
+ api.nvim_buf_clear_namespace(0, ns1, 0, -1)
eq({}, get_marks(ns1))
eq(ns_marks[ns2], get_marks(ns2))
- curbufmeths.clear_namespace(ns2, 0, -1)
+ api.nvim_buf_clear_namespace(0, ns2, 0, -1)
eq({}, get_marks(ns1))
eq({}, get_marks(ns2))
end)
- it("can clear line range", function()
- curbufmeths.clear_namespace(ns1, 10, 20)
+ it('can clear line range', function()
+ api.nvim_buf_clear_namespace(0, ns1, 10, 20)
for id, mark in pairs(ns_marks[ns1]) do
if 10 <= mark[1] and mark[1] < 20 then
ns_marks[ns1][id] = nil
@@ -1750,12 +1896,12 @@ describe('Extmarks buffer api with many marks', function()
eq(ns_marks[ns2], get_marks(ns2))
end)
- it("can delete line", function()
+ it('can delete line', function()
feed('10Gdd')
for _, marks in pairs(ns_marks) do
for id, mark in pairs(marks) do
if mark[1] == 9 then
- marks[id] = {9,0}
+ marks[id] = { 9, 0 }
elseif mark[1] >= 10 then
mark[1] = mark[1] - 1
end
@@ -1765,12 +1911,12 @@ describe('Extmarks buffer api with many marks', function()
eq(ns_marks[ns2], get_marks(ns2))
end)
- it("can delete lines", function()
+ it('can delete lines', function()
feed('10G10dd')
for _, marks in pairs(ns_marks) do
for id, mark in pairs(marks) do
if 9 <= mark[1] and mark[1] < 19 then
- marks[id] = {9,0}
+ marks[id] = { 9, 0 }
elseif mark[1] >= 19 then
mark[1] = mark[1] - 10
end
@@ -1780,7 +1926,7 @@ describe('Extmarks buffer api with many marks', function()
eq(ns_marks[ns2], get_marks(ns2))
end)
- it("can wipe buffer", function()
+ it('can wipe buffer', function()
command('bwipe!')
eq({}, get_marks(ns1))
eq({}, get_marks(ns2))
@@ -1794,17 +1940,17 @@ describe('API/win_extmark', function()
before_each(function()
-- Initialize some namespaces and insert text into a buffer
- marks = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}
+ marks = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }
- line1 = "non ui-watched line"
- line2 = "ui-watched line"
+ line1 = 'non ui-watched line'
+ line2 = 'ui-watched line'
clear()
insert(line1)
- feed("o<esc>")
+ feed('o<esc>')
insert(line2)
- ns = request('nvim_create_namespace', "extmark-ui")
+ ns = request('nvim_create_namespace', 'extmark-ui')
end)
it('sends and only sends ui-watched marks to ui', function()
@@ -1824,8 +1970,8 @@ describe('API/win_extmark', function()
extmarks = {
[2] = {
-- positioned at the end of the 2nd line
- { {id = 1000}, 1, 1, 1, 16 },
- }
+ { 1000, ns, marks[1], 1, 16 },
+ },
},
})
end)
@@ -1833,35 +1979,45 @@ describe('API/win_extmark', function()
it('sends multiple ui-watched marks to ui', function()
screen = Screen.new(20, 4)
screen:attach()
+ feed('15A!<Esc>')
-- should send all of these
- set_extmark(ns, marks[1], 1, 0, { ui_watched = true, virt_text_pos = "overlay" })
- set_extmark(ns, marks[2], 1, 2, { ui_watched = true, virt_text_pos = "overlay" })
- set_extmark(ns, marks[3], 1, 4, { ui_watched = true, virt_text_pos = "overlay" })
- set_extmark(ns, marks[4], 1, 6, { ui_watched = true, virt_text_pos = "overlay" })
+ set_extmark(ns, marks[1], 1, 0, { ui_watched = true, virt_text_pos = 'overlay' })
+ set_extmark(ns, marks[2], 1, 2, { ui_watched = true, virt_text_pos = 'overlay' })
+ set_extmark(ns, marks[3], 1, 4, { ui_watched = true, virt_text_pos = 'overlay' })
+ set_extmark(ns, marks[4], 1, 6, { ui_watched = true, virt_text_pos = 'overlay' })
set_extmark(ns, marks[5], 1, 8, { ui_watched = true })
screen:expect({
grid = [[
non ui-watched line |
- ui-watched lin^e |
- ~ |
+ ui-watched line!!!!!|
+ !!!!!!!!!^! |
|
]],
extmarks = {
[2] = {
- -- earlier notifications
- { {id = 1000}, 1, 1, 1, 0 },
- { {id = 1000}, 1, 1, 1, 0 }, { {id = 1000}, 1, 2, 1, 2 },
- { {id = 1000}, 1, 1, 1, 0 }, { {id = 1000}, 1, 2, 1, 2 }, { {id = 1000}, 1, 3, 1, 4 },
- { {id = 1000}, 1, 1, 1, 0 }, { {id = 1000}, 1, 2, 1, 2 }, { {id = 1000}, 1, 3, 1, 4 }, { {id = 1000}, 1, 4, 1, 6 },
+ -- notification from 1st call
+ { 1000, ns, marks[1], 1, 0 },
+ -- notifications from 2nd call
+ { 1000, ns, marks[1], 1, 0 },
+ { 1000, ns, marks[2], 1, 2 },
+ -- notifications from 3rd call
+ { 1000, ns, marks[1], 1, 0 },
+ { 1000, ns, marks[2], 1, 2 },
+ { 1000, ns, marks[3], 1, 4 },
+ -- notifications from 4th call
+ { 1000, ns, marks[1], 1, 0 },
+ { 1000, ns, marks[2], 1, 2 },
+ { 1000, ns, marks[3], 1, 4 },
+ { 1000, ns, marks[4], 1, 6 },
-- final
-- overlay
- { {id = 1000}, 1, 1, 1, 0 },
- { {id = 1000}, 1, 2, 1, 2 },
- { {id = 1000}, 1, 3, 1, 4 },
- { {id = 1000}, 1, 4, 1, 6 },
+ { 1000, ns, marks[1], 1, 0 },
+ { 1000, ns, marks[2], 1, 2 },
+ { 1000, ns, marks[3], 1, 4 },
+ { 1000, ns, marks[4], 1, 6 },
-- eol
- { {id = 1000}, 1, 5, 1, 16 },
- }
+ { 1000, ns, marks[5], 2, 11 },
+ },
},
})
end)
@@ -1874,7 +2030,7 @@ describe('API/win_extmark', function()
-- should not send this
set_extmark(ns, marks[2], 0, 0, { ui_watched = false })
-- make some changes
- insert(" update")
+ insert(' update')
screen:expect({
grid = [[
non ui-watched line |
@@ -1885,13 +2041,13 @@ describe('API/win_extmark', function()
extmarks = {
[2] = {
-- positioned at the end of the 2nd line
- { {id = 1000}, 1, 1, 1, 16 },
+ { 1000, ns, marks[1], 1, 16 },
-- updated and wrapped to 3rd line
- { {id = 1000}, 1, 1, 2, 2 },
- }
- }
+ { 1000, ns, marks[1], 2, 2 },
+ },
+ },
})
- feed("<c-e>")
+ feed('<c-e>')
screen:expect({
grid = [[
ui-watched linupdat^e|
@@ -1902,18 +2058,18 @@ describe('API/win_extmark', function()
extmarks = {
[2] = {
-- positioned at the end of the 2nd line
- { {id = 1000}, 1, 1, 1, 16 },
+ { 1000, ns, marks[1], 1, 16 },
-- updated and wrapped to 3rd line
- { {id = 1000}, 1, 1, 2, 2 },
+ { 1000, ns, marks[1], 2, 2 },
-- scrolled up one line, should be handled by grid scroll
- }
- }
+ },
+ },
})
end)
it('sends ui-watched to splits', function()
screen = Screen.new(20, 8)
- screen:attach({ext_multigrid=true})
+ screen:attach({ ext_multigrid = true })
-- should send this
set_extmark(ns, marks[1], 1, 0, { ui_watched = true })
-- should not send this
@@ -1922,12 +2078,9 @@ describe('API/win_extmark', function()
screen:expect({
grid = [[
## grid 1
- [4:--------------------]|
- [4:--------------------]|
- [4:--------------------]|
+ [4:--------------------]|*3
[No Name] [+] |
- [2:--------------------]|
- [2:--------------------]|
+ [2:--------------------]|*2
[No Name] [+] |
[3:--------------------]|
## grid 2
@@ -1943,27 +2096,24 @@ describe('API/win_extmark', function()
extmarks = {
[2] = {
-- positioned at the end of the 2nd line
- { {id = 1000}, 1, 1, 1, 16 },
+ { 1000, ns, marks[1], 1, 16 },
-- updated after split
- { {id = 1000}, 1, 1, 1, 16 },
+ { 1000, ns, marks[1], 1, 16 },
},
[4] = {
-- only after split
- { {id = 1001}, 1, 1, 1, 16 },
- }
- }
+ { 1001, ns, marks[1], 1, 16 },
+ },
+ },
})
-- make some changes
- insert(" update")
+ insert(' update')
screen:expect({
grid = [[
## grid 1
- [4:--------------------]|
- [4:--------------------]|
- [4:--------------------]|
+ [4:--------------------]|*3
[No Name] [+] |
- [2:--------------------]|
- [2:--------------------]|
+ [2:--------------------]|*2
[No Name] [+] |
[3:--------------------]|
## grid 2
@@ -1979,16 +2129,16 @@ describe('API/win_extmark', function()
extmarks = {
[2] = {
-- positioned at the end of the 2nd line
- { {id = 1000}, 1, 1, 1, 16 },
+ { 1000, ns, marks[1], 1, 16 },
-- updated after split
- { {id = 1000}, 1, 1, 1, 16 },
+ { 1000, ns, marks[1], 1, 16 },
},
[4] = {
- { {id = 1001}, 1, 1, 1, 16 },
+ { 1001, ns, marks[1], 1, 16 },
-- updated
- { {id = 1001}, 1, 1, 2, 2 },
- }
- }
+ { 1001, ns, marks[1], 2, 2 },
+ },
+ },
})
end)
end)
diff --git a/test/functional/api/highlight_spec.lua b/test/functional/api/highlight_spec.lua
index 7d7d07e30e..1973d3e1c7 100644
--- a/test/functional/api/highlight_spec.lua
+++ b/test/functional/api/highlight_spec.lua
@@ -1,16 +1,16 @@
local helpers = require('test.functional.helpers')(after_each)
-local clear, nvim = helpers.clear, helpers.nvim
+local clear = helpers.clear
local Screen = require('test.functional.ui.screen')
local eq, eval = helpers.eq, helpers.eval
local command = helpers.command
local exec_capture = helpers.exec_capture
-local meths = helpers.meths
-local funcs = helpers.funcs
+local api = helpers.api
+local fn = helpers.fn
local pcall_err = helpers.pcall_err
local ok = helpers.ok
local assert_alive = helpers.assert_alive
-describe('API: highlight',function()
+describe('API: highlight', function()
clear()
Screen.new() -- initialize Screen.colors
@@ -45,127 +45,138 @@ describe('API: highlight',function()
before_each(function()
clear()
- command("hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold")
+ command(
+ 'hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold'
+ )
end)
- it("nvim_get_hl_by_id", function()
+ it('nvim_get_hl_by_id', function()
local hl_id = eval("hlID('NewHighlight')")
- eq(expected_cterm, nvim("get_hl_by_id", hl_id, false))
+ eq(expected_cterm, api.nvim_get_hl_by_id(hl_id, false))
hl_id = eval("hlID('NewHighlight')")
-- Test valid id.
- eq(expected_rgb, nvim("get_hl_by_id", hl_id, true))
+ eq(expected_rgb, api.nvim_get_hl_by_id(hl_id, true))
-- Test invalid id.
- eq('Invalid highlight id: 30000', pcall_err(meths.get_hl_by_id, 30000, false))
+ eq('Invalid highlight id: 30000', pcall_err(api.nvim_get_hl_by_id, 30000, false))
-- Test all highlight properties.
command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine')
- eq(expected_rgb2, nvim("get_hl_by_id", hl_id, true))
+ eq(expected_rgb2, api.nvim_get_hl_by_id(hl_id, true))
-- Test undercurl
command('hi NewHighlight gui=undercurl')
- eq(expected_undercurl, nvim("get_hl_by_id", hl_id, true))
+ eq(expected_undercurl, api.nvim_get_hl_by_id(hl_id, true))
-- Test nil argument.
- eq('Wrong type for argument 1 when calling nvim_get_hl_by_id, expecting Integer',
- pcall_err(meths.get_hl_by_id, { nil }, false))
+ eq(
+ 'Wrong type for argument 1 when calling nvim_get_hl_by_id, expecting Integer',
+ pcall_err(api.nvim_get_hl_by_id, { nil }, false)
+ )
-- Test 0 argument.
- eq('Invalid highlight id: 0', pcall_err(meths.get_hl_by_id, 0, false))
+ eq('Invalid highlight id: 0', pcall_err(api.nvim_get_hl_by_id, 0, false))
-- Test -1 argument.
- eq('Invalid highlight id: -1', pcall_err(meths.get_hl_by_id, -1, false))
+ eq('Invalid highlight id: -1', pcall_err(api.nvim_get_hl_by_id, -1, false))
-- Test highlight group without ctermbg value.
command('hi Normal ctermfg=red ctermbg=yellow')
command('hi NewConstant ctermfg=green guifg=white guibg=blue')
hl_id = eval("hlID('NewConstant')")
- eq({foreground = 10,}, meths.get_hl_by_id(hl_id, false))
+ eq({ foreground = 10 }, api.nvim_get_hl_by_id(hl_id, false))
-- Test highlight group without ctermfg value.
command('hi clear NewConstant')
command('hi NewConstant ctermbg=Magenta guifg=white guibg=blue')
- eq({background = 13,}, meths.get_hl_by_id(hl_id, false))
+ eq({ background = 13 }, api.nvim_get_hl_by_id(hl_id, false))
-- Test highlight group with ctermfg and ctermbg values.
command('hi clear NewConstant')
command('hi NewConstant ctermfg=green ctermbg=Magenta guifg=white guibg=blue')
- eq({foreground = 10, background = 13,}, meths.get_hl_by_id(hl_id, false))
+ eq({ foreground = 10, background = 13 }, api.nvim_get_hl_by_id(hl_id, false))
end)
- it("nvim_get_hl_by_name", function()
- local expected_normal = { background = Screen.colors.Yellow,
- foreground = Screen.colors.Red }
+ it('nvim_get_hl_by_name', function()
+ local expected_normal = { background = Screen.colors.Yellow, foreground = Screen.colors.Red }
-- Test `Normal` default values.
- eq({}, nvim("get_hl_by_name", 'Normal', true))
+ eq({}, api.nvim_get_hl_by_name('Normal', true))
- eq(expected_cterm, nvim("get_hl_by_name", 'NewHighlight', false))
- eq(expected_rgb, nvim("get_hl_by_name", 'NewHighlight', true))
+ eq(expected_cterm, api.nvim_get_hl_by_name('NewHighlight', false))
+ eq(expected_rgb, api.nvim_get_hl_by_name('NewHighlight', true))
-- Test `Normal` modified values.
command('hi Normal guifg=red guibg=yellow')
- eq(expected_normal, nvim("get_hl_by_name", 'Normal', true))
+ eq(expected_normal, api.nvim_get_hl_by_name('Normal', true))
-- Test invalid name.
- eq("Invalid highlight name: 'unknown_highlight'",
- pcall_err(meths.get_hl_by_name , 'unknown_highlight', false))
+ eq(
+ "Invalid highlight name: 'unknown_highlight'",
+ pcall_err(api.nvim_get_hl_by_name, 'unknown_highlight', false)
+ )
-- Test nil argument.
- eq('Wrong type for argument 1 when calling nvim_get_hl_by_name, expecting String',
- pcall_err(meths.get_hl_by_name , { nil }, false))
+ eq(
+ 'Wrong type for argument 1 when calling nvim_get_hl_by_name, expecting String',
+ pcall_err(api.nvim_get_hl_by_name, { nil }, false)
+ )
-- Test empty string argument.
- eq('Invalid highlight name',
- pcall_err(meths.get_hl_by_name , '', false))
+ eq('Invalid highlight name', pcall_err(api.nvim_get_hl_by_name, '', false))
-- Test "standout" attribute. #8054
- eq({ underline = true, },
- meths.get_hl_by_name('cursorline', 0));
+ eq({ underline = true }, api.nvim_get_hl_by_name('cursorline', 0))
command('hi CursorLine cterm=standout,underline term=standout,underline gui=standout,underline')
command('set cursorline')
- eq({ underline = true, standout = true, },
- meths.get_hl_by_name('cursorline', 0));
+ eq({ underline = true, standout = true }, api.nvim_get_hl_by_name('cursorline', 0))
-- Test cterm & Normal values. #18024 (tail) & #18980
-- Ensure Normal, and groups that match Normal return their fg & bg cterm values
- meths.set_hl(0, 'Normal', {ctermfg = 17, ctermbg = 213})
- meths.set_hl(0, 'NotNormal', {ctermfg = 17, ctermbg = 213, nocombine = true})
+ api.nvim_set_hl(0, 'Normal', { ctermfg = 17, ctermbg = 213 })
+ api.nvim_set_hl(0, 'NotNormal', { ctermfg = 17, ctermbg = 213, nocombine = true })
-- Note colors are "cterm" values, not rgb-as-ints
- eq({foreground = 17, background = 213}, nvim("get_hl_by_name", 'Normal', false))
- eq({foreground = 17, background = 213, nocombine = true}, nvim("get_hl_by_name", 'NotNormal', false))
+ eq({ foreground = 17, background = 213 }, api.nvim_get_hl_by_name('Normal', false))
+ eq(
+ { foreground = 17, background = 213, nocombine = true },
+ api.nvim_get_hl_by_name('NotNormal', false)
+ )
end)
it('nvim_get_hl_id_by_name', function()
-- precondition: use a hl group that does not yet exist
- eq("Invalid highlight name: 'Shrubbery'", pcall_err(meths.get_hl_by_name, "Shrubbery", true))
- eq(0, funcs.hlID("Shrubbery"))
+ eq("Invalid highlight name: 'Shrubbery'", pcall_err(api.nvim_get_hl_by_name, 'Shrubbery', true))
+ eq(0, fn.hlID('Shrubbery'))
- local hl_id = meths.get_hl_id_by_name("Shrubbery")
+ local hl_id = api.nvim_get_hl_id_by_name('Shrubbery')
ok(hl_id > 0)
- eq(hl_id, funcs.hlID("Shrubbery"))
+ eq(hl_id, fn.hlID('Shrubbery'))
command('hi Shrubbery guifg=#888888 guibg=#888888')
- eq({foreground=tonumber("0x888888"), background=tonumber("0x888888")},
- meths.get_hl_by_id(hl_id, true))
- eq({foreground=tonumber("0x888888"), background=tonumber("0x888888")},
- meths.get_hl_by_name("Shrubbery", true))
+ eq(
+ { foreground = tonumber('0x888888'), background = tonumber('0x888888') },
+ api.nvim_get_hl_by_id(hl_id, true)
+ )
+ eq(
+ { foreground = tonumber('0x888888'), background = tonumber('0x888888') },
+ api.nvim_get_hl_by_name('Shrubbery', true)
+ )
end)
it("nvim_buf_add_highlight to other buffer doesn't crash if undo is disabled #12873", function()
command('vsplit file')
- local err, _ = pcall(meths.set_option_value, 'undofile', false, { buf = 1 })
+ local err, _ = pcall(api.nvim_set_option_value, 'undofile', false, { buf = 1 })
eq(true, err)
- err, _ = pcall(meths.set_option_value, 'undolevels', -1, { buf = 1 })
+ err, _ = pcall(api.nvim_set_option_value, 'undolevels', -1, { buf = 1 })
eq(true, err)
- err, _ = pcall(meths.buf_add_highlight, 1, -1, 'Question', 0, 0, -1)
+ err, _ = pcall(api.nvim_buf_add_highlight, 1, -1, 'Question', 0, 0, -1)
eq(true, err)
assert_alive()
end)
end)
-describe("API: set highlight", function()
+describe('API: set highlight', function()
local highlight_color = {
fg = tonumber('0xff0000'),
bg = tonumber('0x0032aa'),
@@ -207,7 +218,7 @@ describe("API: set highlight", function()
strikethrough = true,
altfont = true,
nocombine = true,
- }
+ },
}
local highlight3_result_gui = {
background = highlight_color.bg,
@@ -230,57 +241,61 @@ describe("API: set highlight", function()
}
local function get_ns()
- local ns = meths.create_namespace('Test_set_hl')
- meths.set_hl_ns(ns)
+ local ns = api.nvim_create_namespace('Test_set_hl')
+ api.nvim_set_hl_ns(ns)
return ns
end
before_each(clear)
it('validation', function()
- eq("Invalid 'blend': out of range",
- pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='#FF00FF', blend=999}))
- eq("Invalid 'blend': expected Integer, got Array",
- pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='#FF00FF', blend={}}))
+ eq(
+ "Invalid 'blend': out of range",
+ pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { fg = '#FF00FF', blend = 999 })
+ )
+ eq(
+ "Invalid 'blend': expected Integer, got Array",
+ pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { fg = '#FF00FF', blend = {} })
+ )
end)
- it("can set gui highlight", function()
+ it('can set gui highlight', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', highlight1)
- eq(highlight1, meths.get_hl_by_name('Test_hl', true))
+ api.nvim_set_hl(ns, 'Test_hl', highlight1)
+ eq(highlight1, api.nvim_get_hl_by_name('Test_hl', true))
end)
- it("can set cterm highlight", function()
+ it('can set cterm highlight', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', highlight2_config)
- eq(highlight2_result, meths.get_hl_by_name('Test_hl', false))
+ api.nvim_set_hl(ns, 'Test_hl', highlight2_config)
+ eq(highlight2_result, api.nvim_get_hl_by_name('Test_hl', false))
end)
- it("can set empty cterm attr", function()
+ it('can set empty cterm attr', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', { cterm = {} })
- eq({}, meths.get_hl_by_name('Test_hl', false))
+ api.nvim_set_hl(ns, 'Test_hl', { cterm = {} })
+ eq({}, api.nvim_get_hl_by_name('Test_hl', false))
end)
- it("cterm attr defaults to gui attr", function()
+ it('cterm attr defaults to gui attr', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', highlight1)
+ api.nvim_set_hl(ns, 'Test_hl', highlight1)
eq({
bold = true,
italic = true,
- }, meths.get_hl_by_name('Test_hl', false))
+ }, api.nvim_get_hl_by_name('Test_hl', false))
end)
- it("can overwrite attr for cterm", function()
+ it('can overwrite attr for cterm', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', highlight3_config)
- eq(highlight3_result_gui, meths.get_hl_by_name('Test_hl', true))
- eq(highlight3_result_cterm, meths.get_hl_by_name('Test_hl', false))
+ api.nvim_set_hl(ns, 'Test_hl', highlight3_config)
+ eq(highlight3_result_gui, api.nvim_get_hl_by_name('Test_hl', true))
+ eq(highlight3_result_cterm, api.nvim_get_hl_by_name('Test_hl', false))
end)
- it("only allows one underline attribute #22371", function()
+ it('only allows one underline attribute #22371', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', {
+ api.nvim_set_hl(ns, 'Test_hl', {
underdouble = true,
underdotted = true,
cterm = {
@@ -288,84 +303,86 @@ describe("API: set highlight", function()
undercurl = true,
},
})
- eq({ undercurl = true }, meths.get_hl_by_name('Test_hl', false))
- eq({ underdotted = true }, meths.get_hl_by_name('Test_hl', true))
+ eq({ undercurl = true }, api.nvim_get_hl_by_name('Test_hl', false))
+ eq({ underdotted = true }, api.nvim_get_hl_by_name('Test_hl', true))
end)
- it("can set a highlight in the global namespace", function()
- meths.set_hl(0, 'Test_hl', highlight2_config)
- eq('Test_hl xxx cterm=underline,reverse ctermfg=8 ctermbg=15 gui=underline,reverse',
- exec_capture('highlight Test_hl'))
+ it('can set a highlight in the global namespace', function()
+ api.nvim_set_hl(0, 'Test_hl', highlight2_config)
+ eq(
+ 'Test_hl xxx cterm=underline,reverse ctermfg=8 ctermbg=15 gui=underline,reverse',
+ exec_capture('highlight Test_hl')
+ )
- meths.set_hl(0, 'Test_hl', { background = highlight_color.bg })
- eq('Test_hl xxx guibg=#0032aa',
- exec_capture('highlight Test_hl'))
+ api.nvim_set_hl(0, 'Test_hl', { background = highlight_color.bg })
+ eq('Test_hl xxx guibg=#0032aa', exec_capture('highlight Test_hl'))
- meths.set_hl(0, 'Test_hl2', highlight3_config)
- eq('Test_hl2 xxx cterm=italic,reverse,strikethrough,altfont,nocombine ctermfg=8 ctermbg=15 gui=bold,underdashed,italic,reverse,strikethrough,altfont guifg=#ff0000 guibg=#0032aa',
- exec_capture('highlight Test_hl2'))
+ api.nvim_set_hl(0, 'Test_hl2', highlight3_config)
+ eq(
+ 'Test_hl2 xxx cterm=italic,reverse,strikethrough,altfont,nocombine ctermfg=8 ctermbg=15 gui=bold,underdashed,italic,reverse,strikethrough,altfont guifg=#ff0000 guibg=#0032aa',
+ exec_capture('highlight Test_hl2')
+ )
-- Colors are stored with the name they are defined, but
-- with canonical casing
- meths.set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue'})
- eq('Test_hl3 xxx guifg=Blue guibg=Red',
- exec_capture('highlight Test_hl3'))
+ api.nvim_set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue' })
+ eq('Test_hl3 xxx guifg=Blue guibg=Red', exec_capture('highlight Test_hl3'))
end)
- it("can modify a highlight in the global namespace", function()
- meths.set_hl(0, 'Test_hl3', { bg = 'red', fg = 'blue'})
- eq('Test_hl3 xxx guifg=Blue guibg=Red',
- exec_capture('highlight Test_hl3'))
+ it('can modify a highlight in the global namespace', function()
+ api.nvim_set_hl(0, 'Test_hl3', { bg = 'red', fg = 'blue' })
+ eq('Test_hl3 xxx guifg=Blue guibg=Red', exec_capture('highlight Test_hl3'))
- meths.set_hl(0, 'Test_hl3', { bg = 'red' })
- eq('Test_hl3 xxx guibg=Red',
- exec_capture('highlight Test_hl3'))
+ api.nvim_set_hl(0, 'Test_hl3', { bg = 'red' })
+ eq('Test_hl3 xxx guibg=Red', exec_capture('highlight Test_hl3'))
- meths.set_hl(0, 'Test_hl3', { ctermbg = 9, ctermfg = 12})
- eq('Test_hl3 xxx ctermfg=12 ctermbg=9',
- exec_capture('highlight Test_hl3'))
+ api.nvim_set_hl(0, 'Test_hl3', { ctermbg = 9, ctermfg = 12 })
+ eq('Test_hl3 xxx ctermfg=12 ctermbg=9', exec_capture('highlight Test_hl3'))
- meths.set_hl(0, 'Test_hl3', { ctermbg = 'red' , ctermfg = 'blue'})
- eq('Test_hl3 xxx ctermfg=12 ctermbg=9',
- exec_capture('highlight Test_hl3'))
+ api.nvim_set_hl(0, 'Test_hl3', { ctermbg = 'red', ctermfg = 'blue' })
+ eq('Test_hl3 xxx ctermfg=12 ctermbg=9', exec_capture('highlight Test_hl3'))
- meths.set_hl(0, 'Test_hl3', { ctermbg = 9 })
- eq('Test_hl3 xxx ctermbg=9',
- exec_capture('highlight Test_hl3'))
+ api.nvim_set_hl(0, 'Test_hl3', { ctermbg = 9 })
+ eq('Test_hl3 xxx ctermbg=9', exec_capture('highlight Test_hl3'))
- eq("Invalid highlight color: 'redd'",
- pcall_err(meths.set_hl, 0, 'Test_hl3', {fg='redd'}))
+ eq(
+ "Invalid highlight color: 'redd'",
+ pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { fg = 'redd' })
+ )
- eq("Invalid highlight color: 'bleu'",
- pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='bleu'}))
+ eq(
+ "Invalid highlight color: 'bleu'",
+ pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { ctermfg = 'bleu' })
+ )
- meths.set_hl(0, 'Test_hl3', {fg='#FF00FF'})
- eq('Test_hl3 xxx guifg=#ff00ff',
- exec_capture('highlight Test_hl3'))
+ api.nvim_set_hl(0, 'Test_hl3', { fg = '#FF00FF' })
+ eq('Test_hl3 xxx guifg=#ff00ff', exec_capture('highlight Test_hl3'))
- eq("Invalid highlight color: '#FF00FF'",
- pcall_err(meths.set_hl, 0, 'Test_hl3', {ctermfg='#FF00FF'}))
+ eq(
+ "Invalid highlight color: '#FF00FF'",
+ pcall_err(api.nvim_set_hl, 0, 'Test_hl3', { ctermfg = '#FF00FF' })
+ )
- for _, fg_val in ipairs{ nil, 'NONE', 'nOnE', '', -1 } do
- meths.set_hl(0, 'Test_hl3', {fg = fg_val})
- eq('Test_hl3 xxx cleared',
- exec_capture('highlight Test_hl3'))
+ for _, fg_val in ipairs { nil, 'NONE', 'nOnE', '', -1 } do
+ api.nvim_set_hl(0, 'Test_hl3', { fg = fg_val })
+ eq('Test_hl3 xxx cleared', exec_capture('highlight Test_hl3'))
end
- meths.set_hl(0, 'Test_hl3', {fg='#FF00FF', blend=50})
- eq('Test_hl3 xxx guifg=#ff00ff blend=50',
- exec_capture('highlight Test_hl3'))
-
+ api.nvim_set_hl(0, 'Test_hl3', { fg = '#FF00FF', blend = 50 })
+ eq('Test_hl3 xxx guifg=#ff00ff blend=50', exec_capture('highlight Test_hl3'))
end)
it("correctly sets 'Normal' internal properties", function()
-- Normal has some special handling internally. #18024
- meths.set_hl(0, 'Normal', {fg='#000083', bg='#0000F3'})
- eq({foreground = 131, background = 243}, nvim("get_hl_by_name", 'Normal', true))
+ api.nvim_set_hl(0, 'Normal', { fg = '#000083', bg = '#0000F3' })
+ eq({ foreground = 131, background = 243 }, api.nvim_get_hl_by_name('Normal', true))
end)
it('does not segfault on invalid group name #20009', function()
- eq("Invalid highlight name: 'foo bar'", pcall_err(meths.set_hl, 0, 'foo bar', {bold = true}))
+ eq(
+ "Invalid highlight name: 'foo bar'",
+ pcall_err(api.nvim_set_hl, 0, 'foo bar', { bold = true })
+ )
assert_alive()
end)
end)
@@ -380,14 +397,16 @@ describe('API: get highlight', function()
local highlight1 = {
bg = highlight_color.bg,
fg = highlight_color.fg,
- bold = true, italic = true,
- cterm = {bold = true, italic = true},
+ bold = true,
+ italic = true,
+ cterm = { bold = true, italic = true },
}
local highlight2 = {
ctermbg = highlight_color.ctermbg,
ctermfg = highlight_color.ctermfg,
- underline = true, reverse = true,
- cterm = {underline = true, reverse = true},
+ underline = true,
+ reverse = true,
+ cterm = { underline = true, reverse = true },
}
local highlight3_config = {
bg = highlight_color.bg,
@@ -413,20 +432,31 @@ describe('API: get highlight', function()
fg = highlight_color.fg,
ctermbg = highlight_color.ctermbg,
ctermfg = highlight_color.ctermfg,
- bold = true, italic = true, reverse = true, underdashed = true, strikethrough = true, altfont = true,
- cterm = {italic = true, nocombine = true, reverse = true, strikethrough = true, altfont = true}
+ bold = true,
+ italic = true,
+ reverse = true,
+ underdashed = true,
+ strikethrough = true,
+ altfont = true,
+ cterm = {
+ italic = true,
+ nocombine = true,
+ reverse = true,
+ strikethrough = true,
+ altfont = true,
+ },
}
local function get_ns()
-- Test namespace filtering behavior
- local ns2 = meths.create_namespace('Another_namespace')
- meths.set_hl(ns2, 'Test_hl', { ctermfg = 23 })
- meths.set_hl(ns2, 'Test_another_hl', { link = 'Test_hl' })
- meths.set_hl(ns2, 'Test_hl_link', { link = 'Test_another_hl' })
- meths.set_hl(ns2, 'Test_another_hl_link', { link = 'Test_hl_link' })
+ local ns2 = api.nvim_create_namespace('Another_namespace')
+ api.nvim_set_hl(ns2, 'Test_hl', { ctermfg = 23 })
+ api.nvim_set_hl(ns2, 'Test_another_hl', { link = 'Test_hl' })
+ api.nvim_set_hl(ns2, 'Test_hl_link', { link = 'Test_another_hl' })
+ api.nvim_set_hl(ns2, 'Test_another_hl_link', { link = 'Test_hl_link' })
- local ns = meths.create_namespace('Test_set_hl')
- meths.set_hl_ns(ns)
+ local ns = api.nvim_create_namespace('Test_set_hl')
+ api.nvim_set_hl_ns(ns)
return ns
end
@@ -434,67 +464,69 @@ describe('API: get highlight', function()
before_each(clear)
it('validation', function()
- eq("Invalid 'name': expected String, got Integer",
- pcall_err(meths.get_hl, 0, { name = 177 }))
- eq('Highlight id out of bounds', pcall_err(meths.get_hl, 0, { name = 'Test set hl' }))
+ eq(
+ "Invalid 'name': expected String, got Integer",
+ pcall_err(api.nvim_get_hl, 0, { name = 177 })
+ )
+ eq('Highlight id out of bounds', pcall_err(api.nvim_get_hl, 0, { name = 'Test set hl' }))
end)
it('nvim_get_hl with create flag', function()
- eq({}, nvim("get_hl", 0, {name = 'Foo', create = false}))
- eq(0, funcs.hlexists('Foo'))
- meths.get_hl(0, {name = 'Bar', create = true})
- eq(1, funcs.hlexists('Bar'))
- meths.get_hl(0, {name = 'FooBar'})
- eq(1, funcs.hlexists('FooBar'))
+ eq({}, api.nvim_get_hl(0, { name = 'Foo', create = false }))
+ eq(0, fn.hlexists('Foo'))
+ api.nvim_get_hl(0, { name = 'Bar', create = true })
+ eq(1, fn.hlexists('Bar'))
+ api.nvim_get_hl(0, { name = 'FooBar' })
+ eq(1, fn.hlexists('FooBar'))
end)
it('can get all highlights in current namespace', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', { bg = '#B4BEFE' })
- meths.set_hl(ns, 'Test_hl_link', { link = 'Test_hl' })
+ api.nvim_set_hl(ns, 'Test_hl', { bg = '#B4BEFE' })
+ api.nvim_set_hl(ns, 'Test_hl_link', { link = 'Test_hl' })
eq({
Test_hl = {
- bg = 11845374
+ bg = 11845374,
},
Test_hl_link = {
- link = 'Test_hl'
- }
- }, meths.get_hl(ns, {}))
+ link = 'Test_hl',
+ },
+ }, api.nvim_get_hl(ns, {}))
end)
it('can get gui highlight', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', highlight1)
- eq(highlight1, meths.get_hl(ns, { name = 'Test_hl' }))
+ api.nvim_set_hl(ns, 'Test_hl', highlight1)
+ eq(highlight1, api.nvim_get_hl(ns, { name = 'Test_hl' }))
end)
it('can get cterm highlight', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', highlight2)
- eq(highlight2, meths.get_hl(ns, { name = 'Test_hl' }))
+ api.nvim_set_hl(ns, 'Test_hl', highlight2)
+ eq(highlight2, api.nvim_get_hl(ns, { name = 'Test_hl' }))
end)
it('can get empty cterm attr', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', { cterm = {} })
- eq({}, meths.get_hl(ns, { name = 'Test_hl' }))
+ api.nvim_set_hl(ns, 'Test_hl', { cterm = {} })
+ eq({}, api.nvim_get_hl(ns, { name = 'Test_hl' }))
end)
it('cterm attr defaults to gui attr', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', highlight1)
- eq(highlight1, meths.get_hl(ns, { name = 'Test_hl' }))
+ api.nvim_set_hl(ns, 'Test_hl', highlight1)
+ eq(highlight1, api.nvim_get_hl(ns, { name = 'Test_hl' }))
end)
it('can overwrite attr for cterm', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', highlight3_config)
- eq(highlight3_result, meths.get_hl(ns, { name = 'Test_hl' }))
+ api.nvim_set_hl(ns, 'Test_hl', highlight3_config)
+ eq(highlight3_result, api.nvim_get_hl(ns, { name = 'Test_hl' }))
end)
it('only allows one underline attribute #22371', function()
local ns = get_ns()
- meths.set_hl(ns, 'Test_hl', {
+ api.nvim_set_hl(ns, 'Test_hl', {
underdouble = true,
underdotted = true,
cterm = {
@@ -502,154 +534,178 @@ describe('API: get highlight', function()
undercurl = true,
},
})
- eq({ underdotted = true, cterm = { undercurl = true} },
- meths.get_hl(ns, { name = 'Test_hl' }))
+ eq(
+ { underdotted = true, cterm = { undercurl = true } },
+ api.nvim_get_hl(ns, { name = 'Test_hl' })
+ )
end)
it('can get a highlight in the global namespace', function()
- meths.set_hl(0, 'Test_hl', highlight2)
- eq(highlight2, meths.get_hl(0, { name = 'Test_hl' }))
+ api.nvim_set_hl(0, 'Test_hl', highlight2)
+ eq(highlight2, api.nvim_get_hl(0, { name = 'Test_hl' }))
- meths.set_hl(0, 'Test_hl', { background = highlight_color.bg })
+ api.nvim_set_hl(0, 'Test_hl', { background = highlight_color.bg })
eq({
bg = 12970,
- }, meths.get_hl(0, { name = 'Test_hl' }))
+ }, api.nvim_get_hl(0, { name = 'Test_hl' }))
- meths.set_hl(0, 'Test_hl2', highlight3_config)
- eq(highlight3_result, meths.get_hl(0, { name = 'Test_hl2' }))
+ api.nvim_set_hl(0, 'Test_hl2', highlight3_config)
+ eq(highlight3_result, api.nvim_get_hl(0, { name = 'Test_hl2' }))
-- Colors are stored with the name they are defined, but
-- with canonical casing
- meths.set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue' })
+ api.nvim_set_hl(0, 'Test_hl3', { bg = 'reD', fg = 'bLue' })
eq({
bg = 16711680,
fg = 255,
- }, meths.get_hl(0, { name = 'Test_hl3' }))
+ }, api.nvim_get_hl(0, { name = 'Test_hl3' }))
end)
it('nvim_get_hl by id', function()
- local hl_id = meths.get_hl_id_by_name('NewHighlight')
+ local hl_id = api.nvim_get_hl_id_by_name('NewHighlight')
command(
'hi NewHighlight cterm=underline ctermbg=green guifg=red guibg=yellow guisp=blue gui=bold'
)
- eq({ fg = 16711680, bg = 16776960, sp = 255, bold = true,
- ctermbg = 10, cterm = { underline = true },
- }, meths.get_hl(0, { id = hl_id }))
+ eq({
+ fg = 16711680,
+ bg = 16776960,
+ sp = 255,
+ bold = true,
+ ctermbg = 10,
+ cterm = { underline = true },
+ }, api.nvim_get_hl(0, { id = hl_id }))
-- Test 0 argument
- eq('Highlight id out of bounds', pcall_err(meths.get_hl, 0, { id = 0 }))
+ eq('Highlight id out of bounds', pcall_err(api.nvim_get_hl, 0, { id = 0 }))
eq(
"Invalid 'id': expected Integer, got String",
- pcall_err(meths.get_hl, 0, { id = 'Test_set_hl' })
+ pcall_err(api.nvim_get_hl, 0, { id = 'Test_set_hl' })
)
-- Test all highlight properties.
command('hi NewHighlight gui=underline,bold,italic,reverse,strikethrough,altfont,nocombine')
- eq({ fg = 16711680, bg = 16776960, sp = 255,
- altfont = true, bold = true, italic = true, nocombine = true, reverse = true, strikethrough = true, underline = true,
- ctermbg = 10, cterm = {underline = true},
- }, meths.get_hl(0, { id = hl_id }))
+ eq({
+ fg = 16711680,
+ bg = 16776960,
+ sp = 255,
+ altfont = true,
+ bold = true,
+ italic = true,
+ nocombine = true,
+ reverse = true,
+ strikethrough = true,
+ underline = true,
+ ctermbg = 10,
+ cterm = { underline = true },
+ }, api.nvim_get_hl(0, { id = hl_id }))
-- Test undercurl
command('hi NewHighlight gui=undercurl')
- eq({ fg = 16711680, bg = 16776960, sp = 255, undercurl = true,
- ctermbg = 10,
- cterm = {underline = true},
- }, meths.get_hl(0, { id = hl_id }))
+ eq({
+ fg = 16711680,
+ bg = 16776960,
+ sp = 255,
+ undercurl = true,
+ ctermbg = 10,
+ cterm = { underline = true },
+ }, api.nvim_get_hl(0, { id = hl_id }))
end)
it('can correctly detect links', function()
- command('hi String guifg=#a6e3a1')
+ command('hi String guifg=#a6e3a1 ctermfg=NONE')
command('hi link @string string')
command('hi link @string.cpp @string')
- eq({ fg = 10937249 }, meths.get_hl(0, { name = 'String' }))
- eq({ link = 'String' }, meths.get_hl(0, { name = '@string' }))
- eq({ fg = 10937249 }, meths.get_hl(0, { name = '@string.cpp', link = false }))
+ eq({ fg = 10937249 }, api.nvim_get_hl(0, { name = 'String' }))
+ eq({ link = 'String' }, api.nvim_get_hl(0, { name = '@string' }))
+ eq({ fg = 10937249 }, api.nvim_get_hl(0, { name = '@string.cpp', link = false }))
end)
it('can get all attributes for a linked group', function()
command('hi Bar guifg=red')
command('hi Foo guifg=#00ff00 gui=bold,underline')
command('hi! link Foo Bar')
- eq({ link = 'Bar', fg = tonumber('00ff00', 16), bold = true, underline = true }, meths.get_hl(0, { name = 'Foo', link = true }))
+ eq(
+ { link = 'Bar', fg = tonumber('00ff00', 16), bold = true, underline = true },
+ api.nvim_get_hl(0, { name = 'Foo', link = true })
+ )
end)
it('can set link as well as other attributes', function()
command('hi Bar guifg=red')
local hl = { link = 'Bar', fg = tonumber('00ff00', 16), bold = true, cterm = { bold = true } }
- meths.set_hl(0, 'Foo', hl)
- eq(hl, meths.get_hl(0, { name = 'Foo', link = true }))
+ api.nvim_set_hl(0, 'Foo', hl)
+ eq(hl, api.nvim_get_hl(0, { name = 'Foo', link = true }))
end)
it("doesn't contain unset groups", function()
- local id = meths.get_hl_id_by_name "@foobar.hubbabubba"
+ local id = api.nvim_get_hl_id_by_name '@foobar.hubbabubba'
ok(id > 0)
- local data = meths.get_hl(0, {})
- eq(nil, data["@foobar.hubbabubba"])
- eq(nil, data["@foobar"])
+ local data = api.nvim_get_hl(0, {})
+ eq(nil, data['@foobar.hubbabubba'])
+ eq(nil, data['@foobar'])
command 'hi @foobar.hubbabubba gui=bold'
- data = meths.get_hl(0, {})
- eq({bold = true}, data["@foobar.hubbabubba"])
- eq(nil, data["@foobar"])
+ data = api.nvim_get_hl(0, {})
+ eq({ bold = true }, data['@foobar.hubbabubba'])
+ eq(nil, data['@foobar'])
-- @foobar.hubbabubba was explicitly cleared and thus shows up
-- but @foobar was never touched, and thus doesn't
command 'hi clear @foobar.hubbabubba'
- data = meths.get_hl(0, {})
- eq({}, data["@foobar.hubbabubba"])
- eq(nil, data["@foobar"])
+ data = api.nvim_get_hl(0, {})
+ 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' }))
+ api.nvim_set_hl(0, 'Tried', { fg = '#00ff00', default = true })
+ eq({ fg = tonumber('00ff00', 16), default = true }, api.nvim_get_hl(0, { name = 'Tried' }))
end)
it('should not output empty gui and cterm #23474', function()
- meths.set_hl(0, 'Foo', {default = true})
- meths.set_hl(0, 'Bar', { default = true, fg = '#ffffff' })
- meths.set_hl(0, 'FooBar', { default = true, fg = '#ffffff', cterm = {bold = true} })
- meths.set_hl(0, 'FooBarA', { default = true, fg = '#ffffff', cterm = {bold = true,italic = true}})
-
- eq('Foo xxx cleared',
- exec_capture('highlight Foo'))
- eq({default = true}, meths.get_hl(0, {name = 'Foo'}))
- eq('Bar xxx guifg=#ffffff',
- exec_capture('highlight Bar'))
- eq('FooBar xxx cterm=bold guifg=#ffffff',
- exec_capture('highlight FooBar'))
- eq('FooBarA xxx cterm=bold,italic guifg=#ffffff',
- exec_capture('highlight FooBarA'))
+ api.nvim_set_hl(0, 'Foo', { default = true })
+ api.nvim_set_hl(0, 'Bar', { default = true, fg = '#ffffff' })
+ api.nvim_set_hl(0, 'FooBar', { default = true, fg = '#ffffff', cterm = { bold = true } })
+ api.nvim_set_hl(
+ 0,
+ 'FooBarA',
+ { default = true, fg = '#ffffff', cterm = { bold = true, italic = true } }
+ )
+
+ eq('Foo xxx cleared', exec_capture('highlight Foo'))
+ eq({ default = true }, api.nvim_get_hl(0, { name = 'Foo' }))
+ eq('Bar xxx guifg=#ffffff', exec_capture('highlight Bar'))
+ eq('FooBar xxx cterm=bold guifg=#ffffff', exec_capture('highlight FooBar'))
+ eq('FooBarA xxx cterm=bold,italic guifg=#ffffff', exec_capture('highlight FooBarA'))
end)
it('can override exist highlight group by force #20323', function()
local white = tonumber('ffffff', 16)
local green = tonumber('00ff00', 16)
- meths.set_hl(0, 'Foo', { fg=white })
- meths.set_hl(0, 'Foo', { fg=green, force = true })
- eq({ fg = green },meths.get_hl(0, {name = 'Foo'}))
- meths.set_hl(0, 'Bar', {link = 'Comment', default = true})
- meths.set_hl(0, 'Bar', {link = 'Foo',default = true, force = true})
- eq({link ='Foo', default = true}, meths.get_hl(0, {name = 'Bar'}))
+ api.nvim_set_hl(0, 'Foo', { fg = white })
+ api.nvim_set_hl(0, 'Foo', { fg = green, force = true })
+ eq({ fg = green }, api.nvim_get_hl(0, { name = 'Foo' }))
+ api.nvim_set_hl(0, 'Bar', { link = 'Comment', default = true })
+ api.nvim_set_hl(0, 'Bar', { link = 'Foo', default = true, force = true })
+ eq({ link = 'Foo', default = true }, api.nvim_get_hl(0, { name = 'Bar' }))
end)
end)
describe('API: set/get highlight namespace', function()
it('set/get highlight namespace', function()
- eq(0, meths.get_hl_ns({}))
- local ns = meths.create_namespace('')
- meths.set_hl_ns(ns)
- eq(ns, meths.get_hl_ns({}))
+ eq(0, api.nvim_get_hl_ns({}))
+ local ns = api.nvim_create_namespace('')
+ api.nvim_set_hl_ns(ns)
+ eq(ns, api.nvim_get_hl_ns({}))
end)
it('set/get window highlight namespace', function()
- eq(-1, meths.get_hl_ns({winid = 0}))
- local ns = meths.create_namespace('')
- meths.win_set_hl_ns(0, ns)
- eq(ns, meths.get_hl_ns({winid = 0}))
+ eq(-1, api.nvim_get_hl_ns({ winid = 0 }))
+ local ns = api.nvim_create_namespace('')
+ api.nvim_win_set_hl_ns(0, ns)
+ eq(ns, api.nvim_get_hl_ns({ winid = 0 }))
end)
end)
diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua
index 434f117956..0decd710e9 100644
--- a/test/functional/api/keymap_spec.lua
+++ b/test/functional/api/keymap_spec.lua
@@ -1,20 +1,18 @@
local helpers = require('test.functional.helpers')(after_each)
-local bufmeths = helpers.bufmeths
local clear = helpers.clear
local command = helpers.command
-local curbufmeths = helpers.curbufmeths
local eq, neq = helpers.eq, helpers.neq
local exec_lua = helpers.exec_lua
local exec = helpers.exec
local feed = helpers.feed
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local source = helpers.source
local pcall_err = helpers.pcall_err
local shallowcopy = helpers.shallowcopy
-local sleep = helpers.sleep
+local sleep = vim.uv.sleep
local sid_api_client = -9
local sid_lua = -8
@@ -39,25 +37,25 @@ describe('nvim_get_keymap', function()
-- Basic mapping and table to be used to describe results
local foo_bar_string = 'nnoremap foo bar'
local foo_bar_map_table = {
- lhs='foo',
- lhsraw='foo',
- script=0,
- silent=0,
- rhs='bar',
- expr=0,
- sid=0,
- scriptversion=1,
- buffer=0,
- nowait=0,
- mode='n',
- mode_bits=0x01,
- abbr=0,
- noremap=1,
- lnum=0,
+ lhs = 'foo',
+ lhsraw = 'foo',
+ script = 0,
+ silent = 0,
+ rhs = 'bar',
+ expr = 0,
+ sid = 0,
+ scriptversion = 1,
+ buffer = 0,
+ nowait = 0,
+ mode = 'n',
+ mode_bits = 0x01,
+ abbr = 0,
+ noremap = 1,
+ lnum = 0,
}
it('returns empty list when no map', function()
- eq({}, meths.get_keymap('n'))
+ eq({}, api.nvim_get_keymap('n'))
end)
it('returns list of all applicable mappings', function()
@@ -66,10 +64,8 @@ describe('nvim_get_keymap', function()
-- Should be the same as the dictionary we supplied earlier
-- and the dictionary you would get from maparg
-- since this is a global map, and not script local
- eq({foo_bar_map_table}, meths.get_keymap('n'))
- eq({funcs.maparg('foo', 'n', false, true)},
- meths.get_keymap('n')
- )
+ eq({ foo_bar_map_table }, api.nvim_get_keymap('n'))
+ eq({ fn.maparg('foo', 'n', false, true) }, api.nvim_get_keymap('n'))
-- Add another mapping
command('nnoremap foo_longer bar_longer')
@@ -78,15 +74,11 @@ describe('nvim_get_keymap', function()
foolong_bar_map_table['lhsraw'] = 'foo_longer'
foolong_bar_map_table['rhs'] = 'bar_longer'
- eq({foolong_bar_map_table, foo_bar_map_table},
- meths.get_keymap('n')
- )
+ eq({ foolong_bar_map_table, foo_bar_map_table }, api.nvim_get_keymap('n'))
-- Remove a mapping
command('unmap foo_longer')
- eq({foo_bar_map_table},
- meths.get_keymap('n')
- )
+ eq({ foo_bar_map_table }, api.nvim_get_keymap('n'))
end)
it('works for other modes', function()
@@ -100,7 +92,7 @@ describe('nvim_get_keymap', function()
insert_table['mode'] = 'i'
insert_table['mode_bits'] = 0x10
- eq({insert_table}, meths.get_keymap('i'))
+ eq({ insert_table }, api.nvim_get_keymap('i'))
end)
it('considers scope', function()
@@ -117,8 +109,8 @@ describe('nvim_get_keymap', function()
command('nnoremap <buffer> foo bar')
-- The buffer mapping should not show up
- eq({foolong_bar_map_table}, meths.get_keymap('n'))
- eq({buffer_table}, curbufmeths.get_keymap('n'))
+ eq({ foolong_bar_map_table }, api.nvim_get_keymap('n'))
+ eq({ buffer_table }, api.nvim_buf_get_keymap(0, 'n'))
end)
it('considers scope for overlapping maps', function()
@@ -129,12 +121,12 @@ describe('nvim_get_keymap', function()
command('nnoremap <buffer> foo bar')
- eq({foo_bar_map_table}, meths.get_keymap('n'))
- eq({buffer_table}, curbufmeths.get_keymap('n'))
+ eq({ foo_bar_map_table }, api.nvim_get_keymap('n'))
+ eq({ buffer_table }, api.nvim_buf_get_keymap(0, 'n'))
end)
it('can retrieve mapping for different buffers', function()
- local original_buffer = curbufmeths.get_number()
+ local original_buffer = api.nvim_buf_get_number(0)
-- Place something in each of the buffers to make sure they stick around
-- and set hidden so we can leave them
command('set hidden')
@@ -143,87 +135,124 @@ describe('nvim_get_keymap', function()
command('new')
command('normal! ihello 3')
- local final_buffer = curbufmeths.get_number()
+ local final_buffer = api.nvim_buf_get_number(0)
command('nnoremap <buffer> foo bar')
-- Final buffer will have buffer mappings
local buffer_table = shallowcopy(foo_bar_map_table)
buffer_table['buffer'] = final_buffer
- eq({buffer_table}, meths.buf_get_keymap(final_buffer, 'n'))
- eq({buffer_table}, meths.buf_get_keymap(0, 'n'))
+ eq({ buffer_table }, api.nvim_buf_get_keymap(final_buffer, 'n'))
+ eq({ buffer_table }, api.nvim_buf_get_keymap(0, 'n'))
command('buffer ' .. original_buffer)
- eq(original_buffer, curbufmeths.get_number())
+ eq(original_buffer, api.nvim_buf_get_number(0))
-- Original buffer won't have any mappings
- eq({}, meths.get_keymap('n'))
- eq({}, curbufmeths.get_keymap('n'))
- eq({buffer_table}, meths.buf_get_keymap(final_buffer, 'n'))
+ eq({}, api.nvim_get_keymap('n'))
+ eq({}, api.nvim_buf_get_keymap(0, 'n'))
+ eq({ buffer_table }, api.nvim_buf_get_keymap(final_buffer, 'n'))
end)
-- Test toggle switches for basic options
-- @param option The key represented in the `maparg()` result dict
- local function global_and_buffer_test(map,
- option,
- option_token,
- global_on_result,
- buffer_on_result,
- global_off_result,
- buffer_off_result,
- new_windows)
-
+ local function global_and_buffer_test(
+ map,
+ option,
+ option_token,
+ global_on_result,
+ buffer_on_result,
+ global_off_result,
+ buffer_off_result,
+ new_windows
+ )
local function make_new_windows(number_of_windows)
if new_windows == nil then
return nil
end
- for _=1,number_of_windows do
+ for _ = 1, number_of_windows do
command('new')
end
end
- local mode = string.sub(map, 1,1)
+ local mode = string.sub(map, 1, 1)
-- Don't run this for the <buffer> mapping, since it doesn't make sense
if option_token ~= '<buffer>' then
- it(string.format( 'returns %d for the key "%s" when %s is used globally with %s (%s)',
- global_on_result, option, option_token, map, mode), function()
- make_new_windows(new_windows)
- command(map .. ' ' .. option_token .. ' foo bar')
- local result = meths.get_keymap(mode)[1][option]
- eq(global_on_result, result)
- end)
+ it(
+ string.format(
+ 'returns %d for the key "%s" when %s is used globally with %s (%s)',
+ global_on_result,
+ option,
+ option_token,
+ map,
+ mode
+ ),
+ function()
+ make_new_windows(new_windows)
+ command(map .. ' ' .. option_token .. ' foo bar')
+ local result = api.nvim_get_keymap(mode)[1][option]
+ eq(global_on_result, result)
+ end
+ )
end
- it(string.format('returns %d for the key "%s" when %s is used for buffers with %s (%s)',
- buffer_on_result, option, option_token, map, mode), function()
- make_new_windows(new_windows)
- command(map .. ' <buffer> ' .. option_token .. ' foo bar')
- local result = curbufmeths.get_keymap(mode)[1][option]
- eq(buffer_on_result, result)
- end)
+ it(
+ string.format(
+ 'returns %d for the key "%s" when %s is used for buffers with %s (%s)',
+ buffer_on_result,
+ option,
+ option_token,
+ map,
+ mode
+ ),
+ function()
+ make_new_windows(new_windows)
+ command(map .. ' <buffer> ' .. option_token .. ' foo bar')
+ local result = api.nvim_buf_get_keymap(0, mode)[1][option]
+ eq(buffer_on_result, result)
+ end
+ )
-- Don't run these for the <buffer> mapping, since it doesn't make sense
if option_token ~= '<buffer>' then
- it(string.format('returns %d for the key "%s" when %s is not used globally with %s (%s)',
- global_off_result, option, option_token, map, mode), function()
- make_new_windows(new_windows)
- command(map .. ' baz bat')
- local result = meths.get_keymap(mode)[1][option]
- eq(global_off_result, result)
- end)
-
- it(string.format('returns %d for the key "%s" when %s is not used for buffers with %s (%s)',
- buffer_off_result, option, option_token, map, mode), function()
- make_new_windows(new_windows)
- command(map .. ' <buffer> foo bar')
+ it(
+ string.format(
+ 'returns %d for the key "%s" when %s is not used globally with %s (%s)',
+ global_off_result,
+ option,
+ option_token,
+ map,
+ mode
+ ),
+ function()
+ make_new_windows(new_windows)
+ command(map .. ' baz bat')
+ local result = api.nvim_get_keymap(mode)[1][option]
+ eq(global_off_result, result)
+ end
+ )
- local result = curbufmeths.get_keymap(mode)[1][option]
- eq(buffer_off_result, result)
- end)
+ it(
+ string.format(
+ 'returns %d for the key "%s" when %s is not used for buffers with %s (%s)',
+ buffer_off_result,
+ option,
+ option_token,
+ map,
+ mode
+ ),
+ function()
+ make_new_windows(new_windows)
+ command(map .. ' <buffer> foo bar')
+
+ local result = api.nvim_buf_get_keymap(0, mode)[1][option]
+ eq(buffer_off_result, result)
+ end
+ )
end
end
-- Standard modes and returns the same values in the dictionary as maparg()
- local mode_list = {'nnoremap', 'nmap', 'imap', 'inoremap', 'cnoremap'}
+ local mode_list = { 'nnoremap', 'nmap', 'imap', 'inoremap', 'cnoremap' }
for mode in pairs(mode_list) do
global_and_buffer_test(mode_list[mode], 'silent', '<silent>', 1, 1, 0, 0)
global_and_buffer_test(mode_list[mode], 'nowait', '<nowait>', 1, 1, 0, 0)
@@ -246,9 +275,9 @@ describe('nvim_get_keymap', function()
nnoremap fizz :call <SID>maparg_test_function()<CR>
]])
- local sid_result = meths.get_keymap('n')[1]['sid']
+ local sid_result = api.nvim_get_keymap('n')[1]['sid']
eq(1, sid_result)
- eq('testing', meths.call_function('<SNR>' .. sid_result .. '_maparg_test_function', {}))
+ eq('testing', api.nvim_call_function('<SNR>' .. sid_result .. '_maparg_test_function', {}))
end)
it('returns script numbers for buffer maps', function()
@@ -259,29 +288,29 @@ describe('nvim_get_keymap', function()
nnoremap <buffer> fizz :call <SID>maparg_test_function()<CR>
]])
- local sid_result = curbufmeths.get_keymap('n')[1]['sid']
+ local sid_result = api.nvim_buf_get_keymap(0, 'n')[1]['sid']
eq(1, sid_result)
- eq('testing', meths.call_function('<SNR>' .. sid_result .. '_maparg_test_function', {}))
+ eq('testing', api.nvim_call_function('<SNR>' .. sid_result .. '_maparg_test_function', {}))
end)
it('works with <F12> and others', function()
command('nnoremap <F12> :let g:maparg_test_var = 1<CR>')
- eq('<F12>', meths.get_keymap('n')[1]['lhs'])
- eq(':let g:maparg_test_var = 1<CR>', meths.get_keymap('n')[1]['rhs'])
+ eq('<F12>', api.nvim_get_keymap('n')[1]['lhs'])
+ eq(':let g:maparg_test_var = 1<CR>', api.nvim_get_keymap('n')[1]['rhs'])
end)
it('works correctly despite various &cpo settings', function()
local cpo_table = {
- script=0,
- silent=0,
- expr=0,
- sid=0,
- scriptversion=1,
- buffer=0,
- nowait=0,
- abbr=0,
- noremap=1,
- lnum=0,
+ script = 0,
+ silent = 0,
+ expr = 0,
+ sid = 0,
+ scriptversion = 1,
+ buffer = 0,
+ nowait = 0,
+ abbr = 0,
+ noremap = 1,
+ lnum = 0,
}
local function cpomap(lhs, rhs, mode)
local ret = shallowcopy(cpo_table)
@@ -310,7 +339,7 @@ describe('nvim_get_keymap', function()
-- wrapper around get_keymap() that drops "lhsraw" and "lhsrawalt" which are hard to check
local function get_keymap_noraw(...)
- local ret = meths.get_keymap(...)
+ local ret = api.nvim_get_keymap(...)
for _, item in ipairs(ret) do
item.lhsraw = nil
item.lhsrawalt = nil
@@ -323,103 +352,164 @@ describe('nvim_get_keymap', function()
'set cpo+=B',
}) do
command(cmd)
- eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'),
- cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n')},
- get_keymap_noraw('n'))
- eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'),
- cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x')},
- get_keymap_noraw('x'))
- eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'),
- cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's')},
- get_keymap_noraw('s'))
- eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'),
- cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 'o')},
- get_keymap_noraw('o'))
+ eq({
+ cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'),
+ cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n'),
+ }, get_keymap_noraw('n'))
+ eq({
+ cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'),
+ cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x'),
+ }, get_keymap_noraw('x'))
+ eq({
+ cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'),
+ cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's'),
+ }, get_keymap_noraw('s'))
+ eq({
+ cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'),
+ cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 'o'),
+ }, get_keymap_noraw('o'))
end
end)
it('always uses space for space and bar for bar', function()
local space_table = {
- lhs='| |',
- lhsraw='| |',
- rhs='| |',
- mode='n',
- mode_bits=0x01,
- abbr=0,
- script=0,
- silent=0,
- expr=0,
- sid=0,
- scriptversion=1,
- buffer=0,
- nowait=0,
- noremap=1,
- lnum=0,
+ lhs = '| |',
+ lhsraw = '| |',
+ rhs = '| |',
+ mode = 'n',
+ mode_bits = 0x01,
+ abbr = 0,
+ script = 0,
+ silent = 0,
+ expr = 0,
+ sid = 0,
+ scriptversion = 1,
+ buffer = 0,
+ nowait = 0,
+ noremap = 1,
+ lnum = 0,
}
command('nnoremap \\|<Char-0x20><Char-32><Space><Bar> \\|<Char-0x20><Char-32><Space> <Bar>')
- eq({space_table}, meths.get_keymap('n'))
+ eq({ space_table }, api.nvim_get_keymap('n'))
end)
it('can handle lua mappings', function()
- eq(0, exec_lua([[
+ eq(
+ 0,
+ exec_lua([[
GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]]))
+ ]])
+ )
feed('asdf\n')
eq(1, exec_lua([[return GlobalCount]]))
- eq(2, exec_lua([[
+ eq(
+ 2,
+ exec_lua([[
vim.api.nvim_get_keymap('n')[1].callback()
return GlobalCount
- ]]))
+ ]])
+ )
exec([[
call nvim_get_keymap('n')[0].callback()
]])
eq(3, exec_lua([[return GlobalCount]]))
- local mapargs = meths.get_keymap('n')
+ local mapargs = api.nvim_get_keymap('n')
mapargs[1].callback = nil
eq({
- lhs='asdf',
- lhsraw='asdf',
- script=0,
- silent=0,
- expr=0,
- sid=sid_lua,
- scriptversion=1,
- buffer=0,
- nowait=0,
- mode='n',
- mode_bits=0x01,
- abbr=0,
- noremap=0,
- lnum=0,
+ lhs = 'asdf',
+ lhsraw = 'asdf',
+ script = 0,
+ silent = 0,
+ expr = 0,
+ sid = sid_lua,
+ scriptversion = 1,
+ buffer = 0,
+ nowait = 0,
+ mode = 'n',
+ mode_bits = 0x01,
+ abbr = 0,
+ noremap = 0,
+ lnum = 0,
}, mapargs[1])
end)
it('can handle map descriptions', function()
- meths.set_keymap('n', 'lhs', 'rhs', {desc="map description"})
+ api.nvim_set_keymap('n', 'lhs', 'rhs', { desc = 'map description' })
eq({
- lhs='lhs',
- lhsraw='lhs',
- rhs='rhs',
- script=0,
- silent=0,
- expr=0,
- sid=sid_api_client,
- scriptversion=1,
- buffer=0,
- nowait=0,
- mode='n',
- mode_bits=0x01,
- abbr=0,
- noremap=0,
- lnum=0,
- desc='map description'
- }, meths.get_keymap('n')[1])
+ lhs = 'lhs',
+ lhsraw = 'lhs',
+ rhs = 'rhs',
+ script = 0,
+ silent = 0,
+ expr = 0,
+ sid = sid_api_client,
+ scriptversion = 1,
+ buffer = 0,
+ nowait = 0,
+ mode = 'n',
+ mode_bits = 0x01,
+ abbr = 0,
+ noremap = 0,
+ lnum = 0,
+ desc = 'map description',
+ }, api.nvim_get_keymap('n')[1])
+ end)
+
+ it('can get abbreviations', function()
+ command('inoreabbr foo bar')
+ command('cnoreabbr <buffer> foo baz')
+
+ local mapargs_i = {
+ abbr = 1,
+ buffer = 0,
+ expr = 0,
+ lhs = 'foo',
+ lhsraw = 'foo',
+ lnum = 0,
+ mode = 'i',
+ mode_bits = 0x10,
+ noremap = 1,
+ nowait = 0,
+ rhs = 'bar',
+ script = 0,
+ scriptversion = 1,
+ sid = 0,
+ silent = 0,
+ }
+ local mapargs_c = {
+ abbr = 1,
+ buffer = 1,
+ expr = 0,
+ lhs = 'foo',
+ lhsraw = 'foo',
+ lnum = 0,
+ mode = 'c',
+ mode_bits = 0x08,
+ noremap = 1,
+ nowait = 0,
+ rhs = 'baz',
+ script = 0,
+ scriptversion = 1,
+ sid = 0,
+ silent = 0,
+ }
+
+ local curbuf = api.nvim_get_current_buf()
+
+ eq({ mapargs_i }, api.nvim_get_keymap('ia'))
+ eq({}, api.nvim_buf_get_keymap(curbuf, 'ia'))
+
+ eq({}, api.nvim_get_keymap('ca'))
+ eq({ mapargs_c }, api.nvim_buf_get_keymap(curbuf, 'ca'))
+
+ eq({ mapargs_i }, api.nvim_get_keymap('!a'))
+ eq({ mapargs_c }, api.nvim_buf_get_keymap(curbuf, '!a'))
end)
end)
@@ -472,7 +562,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
-- Gets a maparg() dict from Nvim, if one exists.
local function get_mapargs(mode, lhs)
- local mapargs = funcs.maparg(lhs, normalize_mapmode(mode), mode:sub(-1) == 'a', true)
+ local mapargs = fn.maparg(lhs, normalize_mapmode(mode), mode:sub(-1) == 'a', true)
-- drop "lhsraw" and "lhsrawalt" which are hard to check
mapargs.lhsraw = nil
mapargs.lhsrawalt = nil
@@ -481,238 +571,239 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
it('error on empty LHS', function()
-- escape parentheses in lua string, else comparison fails erroneously
- eq('Invalid (empty) LHS', pcall_err(meths.set_keymap, '', '', 'rhs', {}))
- eq('Invalid (empty) LHS', pcall_err(meths.set_keymap, '', '', '', {}))
- eq('Invalid (empty) LHS', pcall_err(meths.del_keymap, '', ''))
+ eq('Invalid (empty) LHS', pcall_err(api.nvim_set_keymap, '', '', 'rhs', {}))
+ eq('Invalid (empty) LHS', pcall_err(api.nvim_set_keymap, '', '', '', {}))
+ eq('Invalid (empty) LHS', pcall_err(api.nvim_del_keymap, '', ''))
end)
it('error if LHS longer than MAXMAPLEN', function()
-- assume MAXMAPLEN of 50 chars, as declared in mapping_defs.h
local MAXMAPLEN = 50
local lhs = ''
- for i=1,MAXMAPLEN do
- lhs = lhs..(i % 10)
+ for i = 1, MAXMAPLEN do
+ lhs = lhs .. (i % 10)
end
-- exactly 50 chars should be fine
- meths.set_keymap('', lhs, 'rhs', {})
+ api.nvim_set_keymap('', lhs, 'rhs', {})
-- del_keymap should unmap successfully
- meths.del_keymap('', lhs)
+ api.nvim_del_keymap('', lhs)
eq({}, get_mapargs('', lhs))
-- 51 chars should produce an error
- lhs = lhs..'1'
- eq('LHS exceeds maximum map length: '..lhs,
- pcall_err(meths.set_keymap, '', lhs, 'rhs', {}))
- eq('LHS exceeds maximum map length: '..lhs,
- pcall_err(meths.del_keymap, '', lhs))
+ lhs = lhs .. '1'
+ eq(
+ 'LHS exceeds maximum map length: ' .. lhs,
+ pcall_err(api.nvim_set_keymap, '', lhs, 'rhs', {})
+ )
+ eq('LHS exceeds maximum map length: ' .. lhs, pcall_err(api.nvim_del_keymap, '', lhs))
end)
it('does not throw errors when rhs is longer than MAXMAPLEN', function()
local MAXMAPLEN = 50
local rhs = ''
- for i=1,MAXMAPLEN do
- rhs = rhs..(i % 10)
+ for i = 1, MAXMAPLEN do
+ rhs = rhs .. (i % 10)
end
- rhs = rhs..'1'
- meths.set_keymap('', 'lhs', rhs, {})
- eq(generate_mapargs('', 'lhs', rhs),
- get_mapargs('', 'lhs'))
+ rhs = rhs .. '1'
+ api.nvim_set_keymap('', 'lhs', rhs, {})
+ eq(generate_mapargs('', 'lhs', rhs), get_mapargs('', 'lhs'))
end)
it('error on invalid mode shortname', function()
- eq('Invalid mode shortname: " "', pcall_err(meths.set_keymap, ' ', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "m"', pcall_err(meths.set_keymap, 'm', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "?"', pcall_err(meths.set_keymap, '?', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "y"', pcall_err(meths.set_keymap, 'y', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "p"', pcall_err(meths.set_keymap, 'p', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "a"', pcall_err(meths.set_keymap, 'a', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "oa"', pcall_err(meths.set_keymap, 'oa', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "!o"', pcall_err(meths.set_keymap, '!o', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "!i"', pcall_err(meths.set_keymap, '!i', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "!!"', pcall_err(meths.set_keymap, '!!', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "map"', pcall_err(meths.set_keymap, 'map', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "vmap"', pcall_err(meths.set_keymap, 'vmap', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: "xnoremap"', pcall_err(meths.set_keymap, 'xnoremap', 'lhs', 'rhs', {}))
- eq('Invalid mode shortname: " "', pcall_err(meths.del_keymap, ' ', 'lhs'))
- eq('Invalid mode shortname: "m"', pcall_err(meths.del_keymap, 'm', 'lhs'))
- eq('Invalid mode shortname: "?"', pcall_err(meths.del_keymap, '?', 'lhs'))
- eq('Invalid mode shortname: "y"', pcall_err(meths.del_keymap, 'y', 'lhs'))
- eq('Invalid mode shortname: "p"', pcall_err(meths.del_keymap, 'p', 'lhs'))
- eq('Invalid mode shortname: "a"', pcall_err(meths.del_keymap, 'a', 'lhs'))
- eq('Invalid mode shortname: "oa"', pcall_err(meths.del_keymap, 'oa', 'lhs'))
- eq('Invalid mode shortname: "!o"', pcall_err(meths.del_keymap, '!o', 'lhs'))
- eq('Invalid mode shortname: "!i"', pcall_err(meths.del_keymap, '!i', 'lhs'))
- eq('Invalid mode shortname: "!!"', pcall_err(meths.del_keymap, '!!', 'lhs'))
- eq('Invalid mode shortname: "map"', pcall_err(meths.del_keymap, 'map', 'lhs'))
- eq('Invalid mode shortname: "vmap"', pcall_err(meths.del_keymap, 'vmap', 'lhs'))
- eq('Invalid mode shortname: "xnoremap"', pcall_err(meths.del_keymap, 'xnoremap', 'lhs'))
+ eq('Invalid mode shortname: " "', pcall_err(api.nvim_set_keymap, ' ', 'lhs', 'rhs', {}))
+ eq('Invalid mode shortname: "m"', pcall_err(api.nvim_set_keymap, 'm', 'lhs', 'rhs', {}))
+ eq('Invalid mode shortname: "?"', pcall_err(api.nvim_set_keymap, '?', 'lhs', 'rhs', {}))
+ eq('Invalid mode shortname: "y"', pcall_err(api.nvim_set_keymap, 'y', 'lhs', 'rhs', {}))
+ eq('Invalid mode shortname: "p"', pcall_err(api.nvim_set_keymap, 'p', 'lhs', 'rhs', {}))
+ eq('Invalid mode shortname: "a"', pcall_err(api.nvim_set_keymap, 'a', 'lhs', 'rhs', {}))
+ eq('Invalid mode shortname: "oa"', pcall_err(api.nvim_set_keymap, 'oa', 'lhs', 'rhs', {}))
+ eq('Invalid mode shortname: "!o"', pcall_err(api.nvim_set_keymap, '!o', 'lhs', 'rhs', {}))
+ eq('Invalid mode shortname: "!i"', pcall_err(api.nvim_set_keymap, '!i', 'lhs', 'rhs', {}))
+ eq('Invalid mode shortname: "!!"', pcall_err(api.nvim_set_keymap, '!!', 'lhs', 'rhs', {}))
+ eq('Invalid mode shortname: "map"', pcall_err(api.nvim_set_keymap, 'map', 'lhs', 'rhs', {}))
+ eq('Invalid mode shortname: "vmap"', pcall_err(api.nvim_set_keymap, 'vmap', 'lhs', 'rhs', {}))
+ eq(
+ 'Invalid mode shortname: "xnoremap"',
+ pcall_err(api.nvim_set_keymap, 'xnoremap', 'lhs', 'rhs', {})
+ )
+ eq('Invalid mode shortname: " "', pcall_err(api.nvim_del_keymap, ' ', 'lhs'))
+ eq('Invalid mode shortname: "m"', pcall_err(api.nvim_del_keymap, 'm', 'lhs'))
+ eq('Invalid mode shortname: "?"', pcall_err(api.nvim_del_keymap, '?', 'lhs'))
+ eq('Invalid mode shortname: "y"', pcall_err(api.nvim_del_keymap, 'y', 'lhs'))
+ eq('Invalid mode shortname: "p"', pcall_err(api.nvim_del_keymap, 'p', 'lhs'))
+ eq('Invalid mode shortname: "a"', pcall_err(api.nvim_del_keymap, 'a', 'lhs'))
+ eq('Invalid mode shortname: "oa"', pcall_err(api.nvim_del_keymap, 'oa', 'lhs'))
+ eq('Invalid mode shortname: "!o"', pcall_err(api.nvim_del_keymap, '!o', 'lhs'))
+ eq('Invalid mode shortname: "!i"', pcall_err(api.nvim_del_keymap, '!i', 'lhs'))
+ eq('Invalid mode shortname: "!!"', pcall_err(api.nvim_del_keymap, '!!', 'lhs'))
+ eq('Invalid mode shortname: "map"', pcall_err(api.nvim_del_keymap, 'map', 'lhs'))
+ eq('Invalid mode shortname: "vmap"', pcall_err(api.nvim_del_keymap, 'vmap', 'lhs'))
+ eq('Invalid mode shortname: "xnoremap"', pcall_err(api.nvim_del_keymap, 'xnoremap', 'lhs'))
end)
it('error on invalid optnames', function()
- eq("Invalid key: 'silentt'",
- pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {silentt = true}))
- eq("Invalid key: 'sidd'",
- pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {sidd = false}))
- eq("Invalid key: 'nowaiT'",
- pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {nowaiT = false}))
+ eq(
+ "Invalid key: 'silentt'",
+ pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', { silentt = true })
+ )
+ eq("Invalid key: 'sidd'", pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', { sidd = false }))
+ eq(
+ "Invalid key: 'nowaiT'",
+ pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', { nowaiT = false })
+ )
end)
it('error on <buffer> option key', function()
- eq("Invalid key: 'buffer'",
- pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {buffer = true}))
+ eq(
+ "Invalid key: 'buffer'",
+ pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', { buffer = true })
+ )
end)
it('error when "replace_keycodes" is used without "expr"', function()
- eq('"replace_keycodes" requires "expr"',
- pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', {replace_keycodes = true}))
+ eq(
+ '"replace_keycodes" requires "expr"',
+ pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', { replace_keycodes = true })
+ )
end)
- local optnames = {'nowait', 'silent', 'script', 'expr', 'unique'}
+ local optnames = { 'nowait', 'silent', 'script', 'expr', 'unique' }
for _, opt in ipairs(optnames) do
-- note: need '%' to escape hyphens, which have special meaning in lua
- it('throws an error when given non-boolean value for '..opt, function()
+ it('throws an error when given non-boolean value for ' .. opt, function()
local opts = {}
opts[opt] = 'fooo'
- eq(opt..' is not a boolean',
- pcall_err(meths.set_keymap, 'n', 'lhs', 'rhs', opts))
+ eq(opt .. ' is not a boolean', pcall_err(api.nvim_set_keymap, 'n', 'lhs', 'rhs', opts))
end)
end
-- Perform tests of basic functionality
it('sets ordinary mappings', function()
- meths.set_keymap('n', 'lhs', 'rhs', {})
+ api.nvim_set_keymap('n', 'lhs', 'rhs', {})
eq(generate_mapargs('n', 'lhs', 'rhs'), get_mapargs('n', 'lhs'))
- meths.set_keymap('v', 'lhs', 'rhs', {})
+ api.nvim_set_keymap('v', 'lhs', 'rhs', {})
eq(generate_mapargs('v', 'lhs', 'rhs'), get_mapargs('v', 'lhs'))
end)
it('does not throw when LHS or RHS have leading/trailing whitespace', function()
- meths.set_keymap('n', ' lhs', 'rhs', {})
- eq(generate_mapargs('n', '<Space><Space><Space>lhs', 'rhs'),
- get_mapargs('n', ' lhs'))
+ api.nvim_set_keymap('n', ' lhs', 'rhs', {})
+ eq(generate_mapargs('n', '<Space><Space><Space>lhs', 'rhs'), get_mapargs('n', ' lhs'))
- meths.set_keymap('n', 'lhs ', 'rhs', {})
- eq(generate_mapargs('n', 'lhs<Space><Space><Space><Space>', 'rhs'),
- get_mapargs('n', 'lhs '))
+ api.nvim_set_keymap('n', 'lhs ', 'rhs', {})
+ eq(generate_mapargs('n', 'lhs<Space><Space><Space><Space>', 'rhs'), get_mapargs('n', 'lhs '))
- meths.set_keymap('v', ' lhs ', '\trhs\t\f', {})
- eq(generate_mapargs('v', '<Space>lhs<Space><Space>', '\trhs\t\f'),
- get_mapargs('v', ' lhs '))
+ api.nvim_set_keymap('v', ' lhs ', '\trhs\t\f', {})
+ eq(generate_mapargs('v', '<Space>lhs<Space><Space>', '\trhs\t\f'), get_mapargs('v', ' lhs '))
end)
it('can set noremap mappings', function()
- meths.set_keymap('x', 'lhs', 'rhs', {noremap = true})
- eq(generate_mapargs('x', 'lhs', 'rhs', {noremap = true}),
- get_mapargs('x', 'lhs'))
+ api.nvim_set_keymap('x', 'lhs', 'rhs', { noremap = true })
+ eq(generate_mapargs('x', 'lhs', 'rhs', { noremap = true }), get_mapargs('x', 'lhs'))
- meths.set_keymap('t', 'lhs', 'rhs', {noremap = true})
- eq(generate_mapargs('t', 'lhs', 'rhs', {noremap = true}),
- get_mapargs('t', 'lhs'))
+ api.nvim_set_keymap('t', 'lhs', 'rhs', { noremap = true })
+ eq(generate_mapargs('t', 'lhs', 'rhs', { noremap = true }), get_mapargs('t', 'lhs'))
end)
it('can unmap mappings', function()
- meths.set_keymap('v', 'lhs', 'rhs', {})
- meths.del_keymap('v', 'lhs')
+ api.nvim_set_keymap('v', 'lhs', 'rhs', {})
+ api.nvim_del_keymap('v', 'lhs')
eq({}, get_mapargs('v', 'lhs'))
- meths.set_keymap('t', 'lhs', 'rhs', {noremap = true})
- meths.del_keymap('t', 'lhs')
+ api.nvim_set_keymap('t', 'lhs', 'rhs', { noremap = true })
+ api.nvim_del_keymap('t', 'lhs')
eq({}, get_mapargs('t', 'lhs'))
end)
-- Test some edge cases
it('"!" and empty string are synonyms for mapmode-nvo', function()
- local nvo_shortnames = {'', '!'}
+ local nvo_shortnames = { '', '!' }
for _, name in ipairs(nvo_shortnames) do
- meths.set_keymap(name, 'lhs', 'rhs', {})
- meths.del_keymap(name, 'lhs')
+ api.nvim_set_keymap(name, 'lhs', 'rhs', {})
+ api.nvim_del_keymap(name, 'lhs')
eq({}, get_mapargs(name, 'lhs'))
end
end)
- local special_chars = {'<C-U>', '<S-Left>', '<F12><F2><Tab>', '<Space><Tab>'}
+ local special_chars = { '<C-U>', '<S-Left>', '<F12><F2><Tab>', '<Space><Tab>' }
for _, lhs in ipairs(special_chars) do
for _, rhs in ipairs(special_chars) do
local mapmode = '!'
- it('can set mappings with special characters, lhs: '..lhs..', rhs: '..rhs,
- function()
- meths.set_keymap(mapmode, lhs, rhs, {})
+ it('can set mappings with special characters, lhs: ' .. lhs .. ', rhs: ' .. rhs, function()
+ api.nvim_set_keymap(mapmode, lhs, rhs, {})
eq(generate_mapargs(mapmode, lhs, rhs), get_mapargs(mapmode, lhs))
end)
end
end
it('can set mappings containing literal keycodes', function()
- meths.set_keymap('n', '\n\r\n', 'rhs', {})
+ api.nvim_set_keymap('n', '\n\r\n', 'rhs', {})
local expected = generate_mapargs('n', '<NL><CR><NL>', 'rhs')
eq(expected, get_mapargs('n', '<NL><CR><NL>'))
end)
it('can set mappings whose RHS is a <Nop>', function()
- meths.set_keymap('i', 'lhs', '<Nop>', {})
+ api.nvim_set_keymap('i', 'lhs', '<Nop>', {})
command('normal ilhs')
- eq({''}, curbufmeths.get_lines(0, -1, 0)) -- imap to <Nop> does nothing
- eq(generate_mapargs('i', 'lhs', '<Nop>', {}),
- get_mapargs('i', 'lhs'))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, 0)) -- imap to <Nop> does nothing
+ eq(generate_mapargs('i', 'lhs', '<Nop>', {}), get_mapargs('i', 'lhs'))
-- also test for case insensitivity
- meths.set_keymap('i', 'lhs', '<nOp>', {})
+ api.nvim_set_keymap('i', 'lhs', '<nOp>', {})
command('normal ilhs')
- eq({''}, curbufmeths.get_lines(0, -1, 0))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, 0))
-- note: RHS in returned mapargs() dict reflects the original RHS
-- provided by the user
- eq(generate_mapargs('i', 'lhs', '<nOp>', {}),
- get_mapargs('i', 'lhs'))
+ eq(generate_mapargs('i', 'lhs', '<nOp>', {}), get_mapargs('i', 'lhs'))
- meths.set_keymap('i', 'lhs', '<NOP>', {})
+ api.nvim_set_keymap('i', 'lhs', '<NOP>', {})
command('normal ilhs')
- eq({''}, curbufmeths.get_lines(0, -1, 0))
- eq(generate_mapargs('i', 'lhs', '<NOP>', {}),
- get_mapargs('i', 'lhs'))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, 0))
+ eq(generate_mapargs('i', 'lhs', '<NOP>', {}), get_mapargs('i', 'lhs'))
-- a single ^V in RHS is also <Nop> (see :h map-empty-rhs)
- meths.set_keymap('i', 'lhs', '\022', {})
+ api.nvim_set_keymap('i', 'lhs', '\022', {})
command('normal ilhs')
- eq({''}, curbufmeths.get_lines(0, -1, 0))
- eq(generate_mapargs('i', 'lhs', '\022', {}),
- get_mapargs('i', 'lhs'))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, 0))
+ eq(generate_mapargs('i', 'lhs', '\022', {}), get_mapargs('i', 'lhs'))
end)
it('treats an empty RHS in a mapping like a <Nop>', function()
- meths.set_keymap('i', 'lhs', '', {})
+ api.nvim_set_keymap('i', 'lhs', '', {})
command('normal ilhs')
- eq({''}, curbufmeths.get_lines(0, -1, 0))
- eq(generate_mapargs('i', 'lhs', '', {}),
- get_mapargs('i', 'lhs'))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, 0))
+ eq(generate_mapargs('i', 'lhs', '', {}), get_mapargs('i', 'lhs'))
end)
it('can set and unset <M-">', function()
-- Taken from the legacy test: test_mapping.vim. Exposes a bug in which
-- replace_termcodes changes the length of the mapping's LHS, but
-- do_map continues to use the *old* length of LHS.
- meths.set_keymap('i', '<M-">', 'foo', {})
- meths.del_keymap('i', '<M-">')
+ api.nvim_set_keymap('i', '<M-">', 'foo', {})
+ api.nvim_del_keymap('i', '<M-">')
eq({}, get_mapargs('i', '<M-">'))
end)
- it('interprets control sequences in expr-quotes correctly when called '
- ..'inside vim', function()
- command([[call nvim_set_keymap('i', "\<space>", "\<tab>", {})]])
- eq(generate_mapargs('i', '<Space>', '\t', {sid=0}),
- get_mapargs('i', '<Space>'))
- feed('i ')
- eq({'\t'}, curbufmeths.get_lines(0, -1, 0))
- end)
+ it(
+ 'interprets control sequences in expr-quotes correctly when called ' .. 'inside vim',
+ function()
+ command([[call nvim_set_keymap('i', "\<space>", "\<tab>", {})]])
+ eq(generate_mapargs('i', '<Space>', '\t', { sid = 0 }), get_mapargs('i', '<Space>'))
+ feed('i ')
+ eq({ '\t' }, api.nvim_buf_get_lines(0, 0, -1, 0))
+ end
+ )
it('throws appropriate error messages when setting <unique> maps', function()
- meths.set_keymap('l', 'lhs', 'rhs', {})
- eq('E227: mapping already exists for lhs',
- pcall_err(meths.set_keymap, 'l', 'lhs', 'rhs', {unique = true}))
+ api.nvim_set_keymap('l', 'lhs', 'rhs', {})
+ eq(
+ 'E227: mapping already exists for lhs',
+ pcall_err(api.nvim_set_keymap, 'l', 'lhs', 'rhs', { unique = true })
+ )
-- different mapmode, no error should be thrown
- meths.set_keymap('t', 'lhs', 'rhs', {unique = true})
+ api.nvim_set_keymap('t', 'lhs', 'rhs', { unique = true })
end)
it('can set <expr> mappings whose RHS change dynamically', function()
@@ -723,50 +814,50 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
return g:flip
endfunction
]])
- eq(1, meths.call_function('FlipFlop', {}))
- eq(0, meths.call_function('FlipFlop', {}))
- eq(1, meths.call_function('FlipFlop', {}))
- eq(0, meths.call_function('FlipFlop', {}))
+ eq(1, api.nvim_call_function('FlipFlop', {}))
+ eq(0, api.nvim_call_function('FlipFlop', {}))
+ eq(1, api.nvim_call_function('FlipFlop', {}))
+ eq(0, api.nvim_call_function('FlipFlop', {}))
- meths.set_keymap('i', 'lhs', 'FlipFlop()', {expr = true})
+ api.nvim_set_keymap('i', 'lhs', 'FlipFlop()', { expr = true })
command('normal ilhs')
- eq({'1'}, curbufmeths.get_lines(0, -1, 0))
+ eq({ '1' }, api.nvim_buf_get_lines(0, 0, -1, 0))
command('normal! ggVGd')
command('normal ilhs')
- eq({'0'}, curbufmeths.get_lines(0, -1, 0))
+ eq({ '0' }, api.nvim_buf_get_lines(0, 0, -1, 0))
end)
it('can set mappings that do trigger other mappings', function()
- meths.set_keymap('i', 'mhs', 'rhs', {})
- meths.set_keymap('i', 'lhs', 'mhs', {})
+ api.nvim_set_keymap('i', 'mhs', 'rhs', {})
+ api.nvim_set_keymap('i', 'lhs', 'mhs', {})
command('normal imhs')
- eq({'rhs'}, curbufmeths.get_lines(0, -1, 0))
+ eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, -1, 0))
command('normal! ggVGd')
command('normal ilhs')
- eq({'rhs'}, curbufmeths.get_lines(0, -1, 0))
+ eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, -1, 0))
end)
it("can set noremap mappings that don't trigger other mappings", function()
- meths.set_keymap('i', 'mhs', 'rhs', {})
- meths.set_keymap('i', 'lhs', 'mhs', {noremap = true})
+ api.nvim_set_keymap('i', 'mhs', 'rhs', {})
+ api.nvim_set_keymap('i', 'lhs', 'mhs', { noremap = true })
command('normal imhs')
- eq({'rhs'}, curbufmeths.get_lines(0, -1, 0))
+ eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, -1, 0))
command('normal! ggVGd')
- command('normal ilhs') -- shouldn't trigger mhs-to-rhs mapping
- eq({'mhs'}, curbufmeths.get_lines(0, -1, 0))
+ command('normal ilhs') -- shouldn't trigger mhs-to-rhs mapping
+ eq({ 'mhs' }, api.nvim_buf_get_lines(0, 0, -1, 0))
end)
- it("can set nowait mappings that fire without waiting", function()
- meths.set_keymap('i', '123456', 'longer', {})
- meths.set_keymap('i', '123', 'shorter', {nowait = true})
+ it('can set nowait mappings that fire without waiting', function()
+ api.nvim_set_keymap('i', '123456', 'longer', {})
+ api.nvim_set_keymap('i', '123', 'shorter', { nowait = true })
-- feed keys one at a time; if all keys arrive atomically, the longer
-- mapping will trigger
@@ -775,84 +866,99 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
feed(c)
sleep(5)
end
- eq({'shorter456'}, curbufmeths.get_lines(0, -1, 0))
+ eq({ 'shorter456' }, api.nvim_buf_get_lines(0, 0, -1, 0))
end)
-- Perform exhaustive tests of basic functionality
- local mapmodes = {'n', 'v', 'x', 's', 'o', '!', 'i', 'l', 'c', 't', '', 'ia', 'ca', '!a'}
+ local mapmodes = { 'n', 'v', 'x', 's', 'o', '!', 'i', 'l', 'c', 't', '', 'ia', 'ca', '!a' }
for _, mapmode in ipairs(mapmodes) do
- it('can set/unset normal mappings in mapmode '..mapmode, function()
- meths.set_keymap(mapmode, 'lhs', 'rhs', {})
- eq(generate_mapargs(mapmode, 'lhs', 'rhs'),
- get_mapargs(mapmode, 'lhs'))
+ it('can set/unset normal mappings in mapmode ' .. mapmode, function()
+ api.nvim_set_keymap(mapmode, 'lhs', 'rhs', {})
+ eq(generate_mapargs(mapmode, 'lhs', 'rhs'), get_mapargs(mapmode, 'lhs'))
-- some mapmodes (like 'o') will prevent other mapmodes (like '!') from
-- taking effect, so unmap after each mapping
- meths.del_keymap(mapmode, 'lhs')
+ api.nvim_del_keymap(mapmode, 'lhs')
eq({}, get_mapargs(mapmode, 'lhs'))
end)
end
for _, mapmode in ipairs(mapmodes) do
- it('can set/unset noremap mappings using mapmode '..mapmode, function()
- meths.set_keymap(mapmode, 'lhs', 'rhs', {noremap = true})
- eq(generate_mapargs(mapmode, 'lhs', 'rhs', {noremap = true}),
- get_mapargs(mapmode, 'lhs'))
+ it('can set/unset noremap mappings using mapmode ' .. mapmode, function()
+ api.nvim_set_keymap(mapmode, 'lhs', 'rhs', { noremap = true })
+ eq(generate_mapargs(mapmode, 'lhs', 'rhs', { noremap = true }), get_mapargs(mapmode, 'lhs'))
- meths.del_keymap(mapmode, 'lhs')
+ api.nvim_del_keymap(mapmode, 'lhs')
eq({}, get_mapargs(mapmode, 'lhs'))
end)
end
-- Test map-arguments, using optnames from above
-- remove some map arguments that are harder to test, or were already tested
- optnames = {'nowait', 'silent', 'expr', 'noremap'}
+ optnames = { 'nowait', 'silent', 'expr', 'noremap' }
for _, mapmode in ipairs(mapmodes) do
-- Test with single mappings
for _, maparg in ipairs(optnames) do
- it('can set/unset '..mapmode..'-mappings with maparg: '..maparg,
- function()
- meths.set_keymap(mapmode, 'lhs', 'rhs', {[maparg] = true})
- eq(generate_mapargs(mapmode, 'lhs', 'rhs', {[maparg] = true}),
- get_mapargs(mapmode, 'lhs'))
- meths.del_keymap(mapmode, 'lhs')
- eq({}, get_mapargs(mapmode, 'lhs'))
- end)
- it ('can set/unset '..mapmode..'-mode mappings with maparg '..
- maparg..', whose value is false', function()
- meths.set_keymap(mapmode, 'lhs', 'rhs', {[maparg] = false})
- eq(generate_mapargs(mapmode, 'lhs', 'rhs'),
- get_mapargs(mapmode, 'lhs'))
- meths.del_keymap(mapmode, 'lhs')
+ it('can set/unset ' .. mapmode .. '-mappings with maparg: ' .. maparg, function()
+ api.nvim_set_keymap(mapmode, 'lhs', 'rhs', { [maparg] = true })
+ eq(
+ generate_mapargs(mapmode, 'lhs', 'rhs', { [maparg] = true }),
+ get_mapargs(mapmode, 'lhs')
+ )
+ api.nvim_del_keymap(mapmode, 'lhs')
eq({}, get_mapargs(mapmode, 'lhs'))
end)
+ it(
+ 'can set/unset '
+ .. mapmode
+ .. '-mode mappings with maparg '
+ .. maparg
+ .. ', whose value is false',
+ function()
+ api.nvim_set_keymap(mapmode, 'lhs', 'rhs', { [maparg] = false })
+ eq(generate_mapargs(mapmode, 'lhs', 'rhs'), get_mapargs(mapmode, 'lhs'))
+ api.nvim_del_keymap(mapmode, 'lhs')
+ eq({}, get_mapargs(mapmode, 'lhs'))
+ end
+ )
end
-- Test with triplets of mappings, one of which is false
for i = 1, (#optnames - 2) do
local opt1, opt2, opt3 = optnames[i], optnames[i + 1], optnames[i + 2]
- it('can set/unset '..mapmode..'-mode mappings with mapargs '..
- opt1..', '..opt2..', '..opt3, function()
- local opts = {[opt1] = true, [opt2] = false, [opt3] = true}
- meths.set_keymap(mapmode, 'lhs', 'rhs', opts)
- eq(generate_mapargs(mapmode, 'lhs', 'rhs', opts),
- get_mapargs(mapmode, 'lhs'))
- meths.del_keymap(mapmode, 'lhs')
- eq({}, get_mapargs(mapmode, 'lhs'))
- end)
+ it(
+ 'can set/unset '
+ .. mapmode
+ .. '-mode mappings with mapargs '
+ .. opt1
+ .. ', '
+ .. opt2
+ .. ', '
+ .. opt3,
+ function()
+ local opts = { [opt1] = true, [opt2] = false, [opt3] = true }
+ api.nvim_set_keymap(mapmode, 'lhs', 'rhs', opts)
+ eq(generate_mapargs(mapmode, 'lhs', 'rhs', opts), get_mapargs(mapmode, 'lhs'))
+ api.nvim_del_keymap(mapmode, 'lhs')
+ eq({}, get_mapargs(mapmode, 'lhs'))
+ end
+ )
end
end
it('can make lua mappings', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]])
+ ]]
+ )
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
end)
it(':map command shows lua mapping correctly', function()
@@ -861,8 +967,8 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
]]
assert.truthy(
string.match(
- exec_lua[[return vim.api.nvim_exec2(':nmap asdf', { output = true }).output]],
- "^\nn asdf <Lua %d+>"
+ exec_lua [[return vim.api.nvim_exec2(':nmap asdf', { output = true }).output]],
+ '^\nn asdf <Lua %d+>'
)
)
end)
@@ -871,29 +977,34 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
exec_lua [[
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() print('jkl;') end })
]]
- assert.truthy(string.match(funcs.mapcheck('asdf', 'n'),
- "^<Lua %d+>"))
+ assert.truthy(string.match(fn.mapcheck('asdf', 'n'), '^<Lua %d+>'))
end)
it('maparg() returns lua mapping correctly', function()
- eq(0, exec_lua([[
+ eq(
+ 0,
+ exec_lua([[
GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]]))
+ ]])
+ )
- assert.truthy(string.match(funcs.maparg('asdf', 'n'), "^<Lua %d+>"))
+ assert.truthy(string.match(fn.maparg('asdf', 'n'), '^<Lua %d+>'))
- local mapargs = funcs.maparg('asdf', 'n', false, true)
+ local mapargs = fn.maparg('asdf', 'n', false, true)
mapargs.callback = nil
mapargs.lhsraw = nil
mapargs.lhsrawalt = nil
- eq(generate_mapargs('n', 'asdf', nil, {sid=sid_lua}), mapargs)
+ eq(generate_mapargs('n', 'asdf', nil, { sid = sid_lua }), mapargs)
- eq(1, exec_lua([[
+ eq(
+ 1,
+ exec_lua([[
vim.fn.maparg('asdf', 'n', false, true).callback()
return GlobalCount
- ]]))
+ ]])
+ )
exec([[
call maparg('asdf', 'n', v:false, v:true).callback()
@@ -908,7 +1019,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
feed('aa')
- eq({'Ï€<M-Ï€>foo<'}, meths.buf_get_lines(0, 0, -1, false))
+ eq({ 'Ï€<M-Ï€>foo<' }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
it('can make lua expr mappings without replacing keycodes', function()
@@ -918,7 +1029,7 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
feed('iaa<esc>')
- eq({'<space>'}, meths.buf_get_lines(0, 0, -1, false))
+ eq({ '<space>' }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
it('lua expr mapping returning nil is equivalent to returning an empty string', function()
@@ -928,41 +1039,50 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
feed('iaa<esc>')
- eq({''}, meths.buf_get_lines(0, 0, -1, false))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
it('does not reset pum in lua mapping', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
VisibleCount = 0
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]])
+ eq(2, exec_lua [[return VisibleCount]])
end)
it('redo of lua mappings in op-pending mode work', function()
- eq(0, exec_lua [[
+ 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]])
+ eq(1, exec_lua [[return OpCount]])
feed('.')
- eq(2, exec_lua[[return OpCount]])
+ eq(2, exec_lua [[return OpCount]])
end)
it('can overwrite lua mappings', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]])
+ ]]
+ )
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
exec_lua [[
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end })
@@ -970,19 +1090,22 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
feed('asdf\n')
- eq(0, exec_lua[[return GlobalCount]])
+ eq(0, exec_lua [[return GlobalCount]])
end)
it('can unmap lua mappings', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]])
+ ]]
+ )
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
exec_lua [[
vim.api.nvim_del_keymap('n', 'asdf' )
@@ -990,20 +1113,23 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
end)
it('no double-free when unmapping simplifiable lua mappings', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.api.nvim_set_keymap('n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]])
+ ]]
+ )
feed('<C-I>\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
exec_lua [[
vim.api.nvim_del_keymap('n', '<C-I>')
@@ -1011,15 +1137,14 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
feed('<C-I>\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
eq('\nNo mapping found', helpers.exec_capture('nmap <C-I>'))
end)
it('can set descriptions on mappings', function()
- meths.set_keymap('n', 'lhs', 'rhs', {desc="map description"})
- eq(generate_mapargs('n', 'lhs', 'rhs', {desc="map description"}), get_mapargs('n', 'lhs'))
- eq("\nn lhs rhs\n map description",
- helpers.exec_capture("nmap lhs"))
+ api.nvim_set_keymap('n', 'lhs', 'rhs', { desc = 'map description' })
+ eq(generate_mapargs('n', 'lhs', 'rhs', { desc = 'map description' }), get_mapargs('n', 'lhs'))
+ eq('\nn lhs rhs\n map description', helpers.exec_capture('nmap lhs'))
end)
it('can define !-mode abbreviations with lua callbacks', function()
@@ -1032,10 +1157,10 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
]]
feed 'iThe foo and the bar and the foo again<esc>'
- eq('The 1 and the bar and the 2 again', meths.get_current_line())
+ eq('The 1 and the bar and the 2 again', api.nvim_get_current_line())
feed ':let x = "The foo is the one"<cr>'
- eq('The 3 is the one', meths.eval'x')
+ eq('The 3 is the one', api.nvim_eval 'x')
end)
it('can define insert mode abbreviations with lua callbacks', function()
@@ -1048,10 +1173,10 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
]]
feed 'iThe foo and the bar and the foo again<esc>'
- eq('The 1 and the bar and the 2 again', meths.get_current_line())
+ eq('The 1 and the bar and the 2 again', api.nvim_get_current_line())
feed ':let x = "The foo is the one"<cr>'
- eq('The foo is the one', meths.eval'x')
+ eq('The foo is the one', api.nvim_eval 'x')
end)
it('can define cmdline mode abbreviations with lua callbacks', function()
@@ -1064,10 +1189,10 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
]]
feed 'iThe foo and the bar and the foo again<esc>'
- eq('The foo and the bar and the foo again', meths.get_current_line())
+ eq('The foo and the bar and the foo again', api.nvim_get_current_line())
feed ':let x = "The foo is the one"<cr>'
- eq('The 1 is the one', meths.eval'x')
+ eq('The 1 is the one', api.nvim_eval 'x')
end)
end)
@@ -1081,7 +1206,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
-- switch to the given buffer, abandoning any changes in the current buffer
local function switch_to_buf(bufnr)
- command(bufnr..'buffer!')
+ command(bufnr .. 'buffer!')
end
-- `set hidden`, then create two buffers and return their bufnr's
@@ -1090,10 +1215,10 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
local function make_two_buffers(start_from_first)
command('set hidden')
- local first_buf = meths.call_function('bufnr', {'%'})
+ local first_buf = api.nvim_call_function('bufnr', { '%' })
command('new')
- local second_buf = meths.call_function('bufnr', {'%'})
- neq(second_buf, first_buf) -- sanity check
+ local second_buf = api.nvim_call_function('bufnr', { '%' })
+ neq(second_buf, first_buf) -- sanity check
if start_from_first then
switch_to_buf(first_buf)
@@ -1103,80 +1228,84 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
end
it('rejects negative bufnr values', function()
- eq('Wrong type for argument 1 when calling nvim_buf_set_keymap, expecting Buffer',
- pcall_err(bufmeths.set_keymap, -1, '', 'lhs', 'rhs', {}))
+ eq(
+ 'Wrong type for argument 1 when calling nvim_buf_set_keymap, expecting Buffer',
+ pcall_err(api.nvim_buf_set_keymap, -1, '', 'lhs', 'rhs', {})
+ )
end)
it('can set mappings active in the current buffer but not others', function()
local first, second = make_two_buffers(true)
- bufmeths.set_keymap(0, '', 'lhs', 'irhs<Esc>', {})
+ api.nvim_buf_set_keymap(0, '', 'lhs', 'irhs<Esc>', {})
command('normal lhs')
- eq({'rhs'}, bufmeths.get_lines(0, 0, 1, 1))
+ eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, 1, 1))
-- mapping should have no effect in new buffer
switch_to_buf(second)
command('normal lhs')
- eq({''}, bufmeths.get_lines(0, 0, 1, 1))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, 1, 1))
-- mapping should remain active in old buffer
switch_to_buf(first)
command('normal ^lhs')
- eq({'rhsrhs'}, bufmeths.get_lines(0, 0, 1, 1))
+ eq({ 'rhsrhs' }, api.nvim_buf_get_lines(0, 0, 1, 1))
end)
it('can set local mappings in buffer other than current', function()
local first = make_two_buffers(false)
- bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {})
+ api.nvim_buf_set_keymap(first, '', 'lhs', 'irhs<Esc>', {})
-- shouldn't do anything
command('normal lhs')
- eq({''}, bufmeths.get_lines(0, 0, 1, 1))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, 1, 1))
-- should take effect
switch_to_buf(first)
command('normal lhs')
- eq({'rhs'}, bufmeths.get_lines(0, 0, 1, 1))
+ eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, 1, 1))
end)
it('can disable mappings made in another buffer, inside that buffer', function()
local first = make_two_buffers(false)
- bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {})
- bufmeths.del_keymap(first, '', 'lhs')
+ api.nvim_buf_set_keymap(first, '', 'lhs', 'irhs<Esc>', {})
+ api.nvim_buf_del_keymap(first, '', 'lhs')
switch_to_buf(first)
-- shouldn't do anything
command('normal lhs')
- eq({''}, bufmeths.get_lines(0, 0, 1, 1))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, 1, 1))
end)
it("can't disable mappings given wrong buffer handle", function()
local first, second = make_two_buffers(false)
- bufmeths.set_keymap(first, '', 'lhs', 'irhs<Esc>', {})
- eq('E31: No such mapping',
- pcall_err(bufmeths.del_keymap, second, '', 'lhs'))
+ api.nvim_buf_set_keymap(first, '', 'lhs', 'irhs<Esc>', {})
+ eq('E31: No such mapping', pcall_err(api.nvim_buf_del_keymap, second, '', 'lhs'))
-- should still work
switch_to_buf(first)
command('normal lhs')
- eq({'rhs'}, bufmeths.get_lines(0, 0, 1, 1))
+ eq({ 'rhs' }, api.nvim_buf_get_lines(0, 0, 1, 1))
end)
- it("does not crash when setting mapping in a non-existing buffer #13541", function()
- pcall_err(bufmeths.set_keymap, 100, '', 'lsh', 'irhs<Esc>', {})
+ it('does not crash when setting mapping in a non-existing buffer #13541', function()
+ pcall_err(api.nvim_buf_set_keymap, 100, '', 'lsh', 'irhs<Esc>', {})
helpers.assert_alive()
end)
it('can make lua mappings', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]])
+ ]]
+ )
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
end)
it('can make lua expr mappings replacing keycodes', function()
@@ -1186,7 +1315,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
feed('aa')
- eq({'Ï€<M-Ï€>foo<'}, meths.buf_get_lines(0, 0, -1, false))
+ eq({ 'Ï€<M-Ï€>foo<' }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
it('can make lua expr mappings without replacing keycodes', function()
@@ -1196,20 +1325,22 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
feed('iaa<esc>')
- eq({'<space>'}, meths.buf_get_lines(0, 0, -1, false))
+ eq({ '<space>' }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
-
it('can overwrite lua mappings', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]])
+ ]]
+ )
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
exec_lua [[
vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount - 1 end })
@@ -1217,19 +1348,22 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
feed('asdf\n')
- eq(0, exec_lua[[return GlobalCount]])
+ eq(0, exec_lua [[return GlobalCount]])
end)
it('can unmap lua mappings', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]])
+ ]]
+ )
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
exec_lua [[
vim.api.nvim_buf_del_keymap(0, 'n', 'asdf' )
@@ -1237,20 +1371,23 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
end)
it('no double-free when unmapping simplifiable lua mappings', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.api.nvim_buf_set_keymap(0, 'n', '<C-I>', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]])
+ ]]
+ )
feed('<C-I>\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
exec_lua [[
vim.api.nvim_buf_del_keymap(0, 'n', '<C-I>')
@@ -1258,7 +1395,7 @@ describe('nvim_buf_set_keymap, nvim_buf_del_keymap', function()
feed('<C-I>\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
eq('\nNo mapping found', helpers.exec_capture('nmap <C-I>'))
end)
end)
diff --git a/test/functional/api/menu_spec.lua b/test/functional/api/menu_spec.lua
index 34a92477f3..44b9039393 100644
--- a/test/functional/api/menu_spec.lua
+++ b/test/functional/api/menu_spec.lua
@@ -5,8 +5,7 @@ local clear = helpers.clear
local command = helpers.command
local feed = helpers.feed
-describe("update_menu notification", function()
-
+describe('update_menu notification', function()
local screen
before_each(function()
@@ -16,23 +15,26 @@ describe("update_menu notification", function()
end)
local function expect_sent(expected)
- screen:expect{condition=function()
- if screen.update_menu ~= expected then
- if expected then
- error('update_menu was expected but not sent')
- else
- error('update_menu was sent unexpectedly')
+ screen:expect {
+ condition = function()
+ if screen.update_menu ~= expected then
+ if expected then
+ error('update_menu was expected but not sent')
+ else
+ error('update_menu was sent unexpectedly')
+ end
end
- end
- end, unchanged=(not expected)}
+ end,
+ unchanged = not expected,
+ }
end
- it("should be sent when adding a menu", function()
+ it('should be sent when adding a menu', function()
command('menu Test.Test :')
expect_sent(true)
end)
- it("should be sent when deleting a menu", function()
+ it('should be sent when deleting a menu', function()
command('menu Test.Test :')
screen.update_menu = false
@@ -40,9 +42,8 @@ describe("update_menu notification", function()
expect_sent(true)
end)
- it("should not be sent unnecessarily", function()
+ it('should not be sent unnecessarily', function()
feed('i12345<ESC>:redraw<CR>')
expect_sent(false)
end)
-
end)
diff --git a/test/functional/api/proc_spec.lua b/test/functional/api/proc_spec.lua
index 20edea3feb..50c441792c 100644
--- a/test/functional/api/proc_spec.lua
+++ b/test/functional/api/proc_spec.lua
@@ -2,12 +2,12 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
-local funcs = helpers.funcs
+local fn = helpers.fn
local neq = helpers.neq
local nvim_argv = helpers.nvim_argv
local request = helpers.request
local retry = helpers.retry
-local NIL = helpers.NIL
+local NIL = vim.NIL
local is_os = helpers.is_os
describe('API', function()
@@ -15,44 +15,44 @@ describe('API', function()
describe('nvim_get_proc_children', function()
it('returns child process ids', function()
- local this_pid = funcs.getpid()
+ local this_pid = fn.getpid()
-- Might be non-zero already (left-over from some other test?),
-- but this is not what is tested here.
local initial_children = request('nvim_get_proc_children', this_pid)
- local job1 = funcs.jobstart(nvim_argv)
+ local job1 = fn.jobstart(nvim_argv)
retry(nil, nil, function()
eq(#initial_children + 1, #request('nvim_get_proc_children', this_pid))
end)
- local job2 = funcs.jobstart(nvim_argv)
+ local job2 = fn.jobstart(nvim_argv)
retry(nil, nil, function()
eq(#initial_children + 2, #request('nvim_get_proc_children', this_pid))
end)
- funcs.jobstop(job1)
+ fn.jobstop(job1)
retry(nil, nil, function()
eq(#initial_children + 1, #request('nvim_get_proc_children', this_pid))
end)
- funcs.jobstop(job2)
+ fn.jobstop(job2)
retry(nil, nil, function()
eq(#initial_children, #request('nvim_get_proc_children', this_pid))
end)
end)
it('validation', function()
- local status, rv = pcall(request, "nvim_get_proc_children", -1)
+ local status, rv = pcall(request, 'nvim_get_proc_children', -1)
eq(false, status)
- eq("Invalid 'pid': -1", string.match(rv, "Invalid.*"))
+ eq("Invalid 'pid': -1", string.match(rv, 'Invalid.*'))
- status, rv = pcall(request, "nvim_get_proc_children", 0)
+ status, rv = pcall(request, 'nvim_get_proc_children', 0)
eq(false, status)
- eq("Invalid 'pid': 0", string.match(rv, "Invalid.*"))
+ eq("Invalid 'pid': 0", string.match(rv, 'Invalid.*'))
-- Assume PID 99999 does not exist.
- status, rv = pcall(request, "nvim_get_proc_children", 99999)
+ status, rv = pcall(request, 'nvim_get_proc_children', 99999)
eq(true, status)
eq({}, rv)
end)
@@ -60,7 +60,7 @@ describe('API', function()
describe('nvim_get_proc', function()
it('returns process info', function()
- local pid = funcs.getpid()
+ local pid = fn.getpid()
local pinfo = request('nvim_get_proc', pid)
eq((is_os('win') and 'nvim.exe' or 'nvim'), pinfo.name)
eq(pid, pinfo.pid)
@@ -69,16 +69,16 @@ describe('API', function()
end)
it('validation', function()
- local status, rv = pcall(request, "nvim_get_proc", -1)
+ local status, rv = pcall(request, 'nvim_get_proc', -1)
eq(false, status)
- eq("Invalid 'pid': -1", string.match(rv, "Invalid.*"))
+ eq("Invalid 'pid': -1", string.match(rv, 'Invalid.*'))
- status, rv = pcall(request, "nvim_get_proc", 0)
+ status, rv = pcall(request, 'nvim_get_proc', 0)
eq(false, status)
- eq("Invalid 'pid': 0", string.match(rv, "Invalid.*"))
+ eq("Invalid 'pid': 0", string.match(rv, 'Invalid.*'))
-- Assume PID 99999 does not exist.
- status, rv = pcall(request, "nvim_get_proc", 99999)
+ status, rv = pcall(request, 'nvim_get_proc', 99999)
eq(true, status)
eq(NIL, rv)
end)
diff --git a/test/functional/api/rpc_fixture.lua b/test/functional/api/rpc_fixture.lua
index c860a6da59..050d439a1b 100644
--- a/test/functional/api/rpc_fixture.lua
+++ b/test/functional/api/rpc_fixture.lua
@@ -4,8 +4,8 @@
package.path = arg[1]
package.cpath = arg[2]
-local StdioStream = require'test.client.uv_stream'.StdioStream
-local Session = require'test.client.session'
+local StdioStream = require 'test.client.uv_stream'.StdioStream
+local Session = require 'test.client.session'
local stdio_stream = StdioStream.open()
local session = Session.new(stdio_stream)
@@ -15,8 +15,8 @@ local function on_request(method, args)
return 'ok'
elseif method == 'write_stderr' then
io.stderr:write(args[1])
- return "done!"
- elseif method == "exit" then
+ return 'done!'
+ elseif method == 'exit' then
session:stop()
return vim.NIL
end
@@ -24,7 +24,7 @@ end
local function on_notification(event, args)
if event == 'ping' and #args == 0 then
- session:notify("nvim_eval", "rpcnotify(g:channel, 'pong')")
+ session:notify('nvim_eval', "rpcnotify(g:channel, 'pong')")
end
end
diff --git a/test/functional/api/server_notifications_spec.lua b/test/functional/api/server_notifications_spec.lua
index bc43f6564d..d1608a951c 100644
--- a/test/functional/api/server_notifications_spec.lua
+++ b/test/functional/api/server_notifications_spec.lua
@@ -1,9 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local assert_log = helpers.assert_log
-local eq, clear, eval, command, nvim, next_msg =
- helpers.eq, helpers.clear, helpers.eval, helpers.command, helpers.nvim,
- helpers.next_msg
-local meths = helpers.meths
+local eq, clear, eval, command, next_msg =
+ helpers.eq, helpers.clear, helpers.eval, helpers.command, helpers.next_msg
+local api = helpers.api
local exec_lua = helpers.exec_lua
local retry = helpers.retry
local assert_alive = helpers.assert_alive
@@ -15,7 +14,7 @@ describe('notify', function()
before_each(function()
clear()
- channel = nvim('get_api_info')[1]
+ channel = api.nvim_get_chan_info(0).id
end)
after_each(function()
@@ -24,34 +23,34 @@ describe('notify', function()
describe('passing a valid channel id', function()
it('sends the notification/args to the corresponding channel', function()
- eval('rpcnotify('..channel..', "test-event", 1, 2, 3)')
- eq({'notification', 'test-event', {1, 2, 3}}, next_msg())
- command('au FileType lua call rpcnotify('..channel..', "lua!")')
+ eval('rpcnotify(' .. channel .. ', "test-event", 1, 2, 3)')
+ eq({ 'notification', 'test-event', { 1, 2, 3 } }, next_msg())
+ command('au FileType lua call rpcnotify(' .. channel .. ', "lua!")')
command('set filetype=lua')
- eq({'notification', 'lua!', {}}, next_msg())
+ eq({ 'notification', 'lua!', {} }, next_msg())
end)
end)
describe('passing 0 as the channel id', function()
it('sends the notification/args to all subscribed channels', function()
- nvim('subscribe', 'event2')
+ api.nvim_subscribe('event2')
eval('rpcnotify(0, "event1", 1, 2, 3)')
eval('rpcnotify(0, "event2", 4, 5, 6)')
eval('rpcnotify(0, "event2", 7, 8, 9)')
- eq({'notification', 'event2', {4, 5, 6}}, next_msg())
- eq({'notification', 'event2', {7, 8, 9}}, next_msg())
- nvim('unsubscribe', 'event2')
- nvim('subscribe', 'event1')
+ eq({ 'notification', 'event2', { 4, 5, 6 } }, next_msg())
+ eq({ 'notification', 'event2', { 7, 8, 9 } }, next_msg())
+ api.nvim_unsubscribe('event2')
+ api.nvim_subscribe('event1')
eval('rpcnotify(0, "event2", 10, 11, 12)')
eval('rpcnotify(0, "event1", 13, 14, 15)')
- eq({'notification', 'event1', {13, 14, 15}}, next_msg())
+ eq({ 'notification', 'event1', { 13, 14, 15 } }, next_msg())
end)
it('does not crash for deeply nested variable', function()
- meths.set_var('l', {})
+ api.nvim_set_var('l', {})
local nest_level = 1000
- meths.command(('call map(range(%u), "extend(g:, {\'l\': [g:l]})")'):format(nest_level - 1))
- eval('rpcnotify('..channel..', "event", g:l)')
+ command(('call map(range(%u), "extend(g:, {\'l\': [g:l]})")'):format(nest_level - 1))
+ eval('rpcnotify(' .. channel .. ', "event", g:l)')
local msg = next_msg()
eq('notification', msg[1])
eq('event', msg[2])
@@ -77,27 +76,37 @@ describe('notify', function()
end)
it('unsubscribe non-existing event #8745', function()
- clear{env={
- NVIM_LOG_FILE=testlog,
- }}
- nvim('subscribe', 'event1')
- nvim('unsubscribe', 'doesnotexist')
+ clear { env = {
+ NVIM_LOG_FILE = testlog,
+ } }
+ api.nvim_subscribe('event1')
+ api.nvim_unsubscribe('doesnotexist')
assert_log("tried to unsubscribe unknown event 'doesnotexist'", testlog, 10)
- nvim('unsubscribe', 'event1')
+ api.nvim_unsubscribe('event1')
assert_alive()
end)
it('cancels stale events on channel close', function()
local catchan = eval("jobstart(['cat'], {'rpc': v:true})")
local catpath = eval('exepath("cat")')
- eq({id=catchan, argv={catpath}, stream='job', mode='rpc', client = {}}, exec_lua ([[
+ eq(
+ { id = catchan, argv = { catpath }, stream = 'job', mode = 'rpc', client = {} },
+ exec_lua(
+ [[
vim.rpcnotify(..., "nvim_call_function", 'chanclose', {..., 'rpc'})
vim.rpcnotify(..., "nvim_subscribe", "daily_rant")
return vim.api.nvim_get_chan_info(...)
- ]], catchan))
+ ]],
+ catchan
+ )
+ )
assert_alive()
- eq({false, 'Invalid channel: '..catchan},
- exec_lua ([[ return {pcall(vim.rpcrequest, ..., 'nvim_eval', '1+1')}]], catchan))
- retry(nil, 3000, function() eq({}, meths.get_chan_info(catchan)) end) -- cat be dead :(
+ eq(
+ { false, 'Invalid channel: ' .. catchan },
+ exec_lua([[ return {pcall(vim.rpcrequest, ..., 'nvim_eval', '1+1')}]], catchan)
+ )
+ retry(nil, 3000, function()
+ eq({}, api.nvim_get_chan_info(catchan))
+ end) -- cat be dead :(
end)
end)
diff --git a/test/functional/api/server_requests_spec.lua b/test/functional/api/server_requests_spec.lua
index 1ad4ad3a02..298dbac217 100644
--- a/test/functional/api/server_requests_spec.lua
+++ b/test/functional/api/server_requests_spec.lua
@@ -2,12 +2,12 @@
-- `rpcrequest` calls we need the client event loop to be running.
local helpers = require('test.functional.helpers')(after_each)
-local clear, nvim, eval = helpers.clear, helpers.nvim, helpers.eval
+local clear, eval = helpers.clear, helpers.eval
local eq, neq, run, stop = helpers.eq, helpers.neq, helpers.run, helpers.stop
-local nvim_prog, command, funcs = helpers.nvim_prog, helpers.command, helpers.funcs
+local nvim_prog, command, fn = helpers.nvim_prog, helpers.command, helpers.fn
local source, next_msg = helpers.source, helpers.next_msg
local ok = helpers.ok
-local meths = helpers.meths
+local api = helpers.api
local spawn, merge_args = helpers.spawn, helpers.merge_args
local set_session = helpers.set_session
local pcall_err = helpers.pcall_err
@@ -18,18 +18,18 @@ describe('server -> client', function()
before_each(function()
clear()
- cid = nvim('get_api_info')[1]
+ cid = api.nvim_get_chan_info(0).id
end)
it('handles unexpected closed stream while preparing RPC response', function()
source([[
let g:_nvim_args = [v:progpath, '--embed', '--headless', '-n', '-u', 'NONE', '-i', 'NONE', ]
let ch1 = jobstart(g:_nvim_args, {'rpc': v:true})
- let child1_ch = rpcrequest(ch1, "nvim_get_api_info")[0]
+ let child1_ch = rpcrequest(ch1, "nvim_get_chan_info", 0).id
call rpcnotify(ch1, 'nvim_eval', 'rpcrequest('.child1_ch.', "nvim_get_api_info")')
let ch2 = jobstart(g:_nvim_args, {'rpc': v:true})
- let child2_ch = rpcrequest(ch2, "nvim_get_api_info")[0]
+ let child2_ch = rpcrequest(ch2, "nvim_get_chan_info", 0).id
call rpcnotify(ch2, 'nvim_eval', 'rpcrequest('.child2_ch.', "nvim_get_api_info")')
call jobstop(ch1)
@@ -40,14 +40,14 @@ describe('server -> client', function()
describe('simple call', function()
it('works', function()
local function on_setup()
- eq({4, 5, 6}, eval('rpcrequest('..cid..', "scall", 1, 2, 3)'))
+ eq({ 4, 5, 6 }, eval('rpcrequest(' .. cid .. ', "scall", 1, 2, 3)'))
stop()
end
local function on_request(method, args)
eq('scall', method)
- eq({1, 2, 3}, args)
- nvim('command', 'let g:result = [4, 5, 6]')
+ eq({ 1, 2, 3 }, args)
+ command('let g:result = [4, 5, 6]')
return eval('g:result')
end
run(on_request, nil, on_setup)
@@ -61,14 +61,14 @@ describe('server -> client', function()
-- elements following the empty string.
it('works', function()
local function on_setup()
- eq({1, 2, '', 3, 'asdf'}, eval('rpcrequest('..cid..', "nstring")'))
+ eq({ 1, 2, '', 3, 'asdf' }, eval('rpcrequest(' .. cid .. ', "nstring")'))
stop()
end
local function on_request()
-- No need to evaluate the args, we are only interested in
-- a response that contains an array with an empty string.
- return {1, 2, '', 3, 'asdf'}
+ return { 1, 2, '', 3, 'asdf' }
end
run(on_request, nil, on_setup)
end)
@@ -77,15 +77,15 @@ describe('server -> client', function()
describe('recursive call', function()
it('works', function()
local function on_setup()
- nvim('set_var', 'result1', 0)
- nvim('set_var', 'result2', 0)
- nvim('set_var', 'result3', 0)
- nvim('set_var', 'result4', 0)
- nvim('command', 'let g:result1 = rpcrequest('..cid..', "rcall", 2)')
- eq(4, nvim('get_var', 'result1'))
- eq(8, nvim('get_var', 'result2'))
- eq(16, nvim('get_var', 'result3'))
- eq(32, nvim('get_var', 'result4'))
+ api.nvim_set_var('result1', 0)
+ api.nvim_set_var('result2', 0)
+ api.nvim_set_var('result3', 0)
+ api.nvim_set_var('result4', 0)
+ command('let g:result1 = rpcrequest(' .. cid .. ', "rcall", 2)')
+ eq(4, api.nvim_get_var('result1'))
+ eq(8, api.nvim_get_var('result2'))
+ eq(16, api.nvim_get_var('result3'))
+ eq(32, api.nvim_get_var('result4'))
stop()
end
@@ -95,13 +95,13 @@ describe('server -> client', function()
if n <= 16 then
local cmd
if n == 4 then
- cmd = 'let g:result2 = rpcrequest('..cid..', "rcall", '..n..')'
+ cmd = 'let g:result2 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')'
elseif n == 8 then
- cmd = 'let g:result3 = rpcrequest('..cid..', "rcall", '..n..')'
+ cmd = 'let g:result3 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')'
elseif n == 16 then
- cmd = 'let g:result4 = rpcrequest('..cid..', "rcall", '..n..')'
+ cmd = 'let g:result4 = rpcrequest(' .. cid .. ', "rcall", ' .. n .. ')'
end
- nvim('command', cmd)
+ command(cmd)
end
return n
end
@@ -113,18 +113,18 @@ describe('server -> client', function()
it('does not delay notifications during pending request', function()
local received = false
local function on_setup()
- eq("retval", funcs.rpcrequest(cid, "doit"))
+ eq('retval', fn.rpcrequest(cid, 'doit'))
stop()
end
local function on_request(method)
- if method == "doit" then
- funcs.rpcnotify(cid, "headsup")
- eq(true,received)
- return "retval"
+ if method == 'doit' then
+ fn.rpcnotify(cid, 'headsup')
+ eq(true, received)
+ return 'retval'
end
end
local function on_notification(method)
- if method == "headsup" then
+ if method == 'headsup' then
received = true
end
end
@@ -148,28 +148,28 @@ describe('server -> client', function()
-- of nvim's request stack).
pending('will close connection if not properly synchronized', function()
local function on_setup()
- eq('notified!', eval('rpcrequest('..cid..', "notify")'))
+ eq('notified!', eval('rpcrequest(' .. cid .. ', "notify")'))
end
local function on_request(method)
- if method == "notify" then
- eq(1, eval('rpcnotify('..cid..', "notification")'))
+ if method == 'notify' then
+ eq(1, eval('rpcnotify(' .. cid .. ', "notification")'))
return 'notified!'
- elseif method == "nested" then
+ elseif method == 'nested' then
-- do some busywork, so the first request will return
-- before this one
for _ = 1, 5 do
assert_alive()
end
- eq(1, eval('rpcnotify('..cid..', "nested_done")'))
+ eq(1, eval('rpcnotify(' .. cid .. ', "nested_done")'))
return 'done!'
end
end
local function on_notification(method)
- if method == "notification" then
- eq('done!', eval('rpcrequest('..cid..', "nested")'))
- elseif method == "nested_done" then
+ if method == 'notification' then
+ eq('done!', eval('rpcrequest(' .. cid .. ', "nested")'))
+ elseif method == 'nested_done' then
ok(false, 'never sent', 'sent')
end
end
@@ -182,49 +182,57 @@ describe('server -> client', function()
describe('recursive (child) nvim client', function()
before_each(function()
- command("let vim = rpcstart('"..nvim_prog.."', ['-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--embed', '--headless'])")
+ command(
+ "let vim = rpcstart('"
+ .. nvim_prog
+ .. "', ['-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--embed', '--headless'])"
+ )
neq(0, eval('vim'))
end)
- after_each(function() command('call rpcstop(vim)') end)
+ after_each(function()
+ command('call rpcstop(vim)')
+ end)
it('can send/receive notifications and make requests', function()
- nvim('command', "call rpcnotify(vim, 'vim_set_current_line', 'SOME TEXT')")
+ command("call rpcnotify(vim, 'vim_set_current_line', 'SOME TEXT')")
-- Wait for the notification to complete.
- nvim('command', "call rpcrequest(vim, 'vim_eval', '0')")
+ command("call rpcrequest(vim, 'vim_eval', '0')")
eq('SOME TEXT', eval("rpcrequest(vim, 'vim_get_current_line')"))
end)
it('can communicate buffers, tabpages, and windows', function()
- eq({1}, eval("rpcrequest(vim, 'nvim_list_tabpages')"))
+ eq({ 1 }, eval("rpcrequest(vim, 'nvim_list_tabpages')"))
-- Window IDs start at 1000 (LOWEST_WIN_ID in window.h)
- eq({1000}, eval("rpcrequest(vim, 'nvim_list_wins')"))
+ eq({ 1000 }, eval("rpcrequest(vim, 'nvim_list_wins')"))
local buf = eval("rpcrequest(vim, 'nvim_list_bufs')")[1]
eq(1, buf)
- eval("rpcnotify(vim, 'buffer_set_line', "..buf..", 0, 'SOME TEXT')")
- nvim('command', "call rpcrequest(vim, 'vim_eval', '0')") -- wait
+ eval("rpcnotify(vim, 'buffer_set_line', " .. buf .. ", 0, 'SOME TEXT')")
+ command("call rpcrequest(vim, 'vim_eval', '0')") -- wait
- eq('SOME TEXT', eval("rpcrequest(vim, 'buffer_get_line', "..buf..", 0)"))
+ eq('SOME TEXT', eval("rpcrequest(vim, 'buffer_get_line', " .. buf .. ', 0)'))
-- Call get_lines(buf, range [0,0], strict_indexing)
- eq({'SOME TEXT'}, eval("rpcrequest(vim, 'buffer_get_lines', "..buf..", 0, 1, 1)"))
+ eq({ 'SOME TEXT' }, eval("rpcrequest(vim, 'buffer_get_lines', " .. buf .. ', 0, 1, 1)'))
end)
it('returns an error if the request failed', function()
- eq("Vim:Error invoking 'does-not-exist' on channel 3:\nInvalid method: does-not-exist",
- pcall_err(eval, "rpcrequest(vim, 'does-not-exist')"))
+ eq(
+ "Vim:Error invoking 'does-not-exist' on channel 3:\nInvalid method: does-not-exist",
+ pcall_err(eval, "rpcrequest(vim, 'does-not-exist')")
+ )
end)
end)
describe('jobstart()', function()
local jobid
before_each(function()
- local channel = nvim('get_api_info')[1]
- nvim('set_var', 'channel', channel)
+ local channel = api.nvim_get_chan_info(0).id
+ api.nvim_set_var('channel', channel)
source([[
function! s:OnEvent(id, data, event)
call rpcnotify(g:channel, a:event, 0, a:data)
@@ -236,64 +244,67 @@ describe('server -> client', function()
\ 'rpc': v:true
\ }
]])
- meths.set_var("args", {
- nvim_prog, '-ll',
+ api.nvim_set_var('args', {
+ nvim_prog,
+ '-ll',
'test/functional/api/rpc_fixture.lua',
package.path,
package.cpath,
})
- jobid = eval("jobstart(g:args, g:job_opts)")
+ jobid = eval('jobstart(g:args, g:job_opts)')
neq(0, jobid)
end)
after_each(function()
- pcall(funcs.jobstop, jobid)
+ pcall(fn.jobstop, jobid)
end)
- if helpers.skip(helpers.is_os('win')) then return end
+ if helpers.skip(helpers.is_os('win')) then
+ return
+ end
it('rpc and text stderr can be combined', function()
- local status, rv = pcall(funcs.rpcrequest, jobid, 'poll')
+ local status, rv = pcall(fn.rpcrequest, jobid, 'poll')
if not status then
error(string.format('missing nvim Lua module? (%s)', rv))
end
eq('ok', rv)
- funcs.rpcnotify(jobid, "ping")
- eq({'notification', 'pong', {}}, next_msg())
- eq("done!",funcs.rpcrequest(jobid, "write_stderr", "fluff\n"))
- eq({'notification', 'stderr', {0, {'fluff', ''}}}, next_msg())
- pcall(funcs.rpcrequest, jobid, "exit")
- eq({'notification', 'stderr', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 0}}, next_msg())
+ fn.rpcnotify(jobid, 'ping')
+ eq({ 'notification', 'pong', {} }, next_msg())
+ eq('done!', fn.rpcrequest(jobid, 'write_stderr', 'fluff\n'))
+ eq({ 'notification', 'stderr', { 0, { 'fluff', '' } } }, next_msg())
+ pcall(fn.rpcrequest, jobid, 'exit')
+ eq({ 'notification', 'stderr', { 0, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { 0, 0 } }, next_msg())
end)
end)
describe('connecting to another (peer) nvim', function()
- local nvim_argv = merge_args(helpers.nvim_argv, {'--headless'})
+ local nvim_argv = merge_args(helpers.nvim_argv, { '--headless' })
local function connect_test(server, mode, address)
- local serverpid = funcs.getpid()
+ local serverpid = fn.getpid()
local client = spawn(nvim_argv, false, nil, true)
set_session(client)
- local clientpid = funcs.getpid()
+ local clientpid = fn.getpid()
neq(serverpid, clientpid)
- local id = funcs.sockconnect(mode, address, {rpc=true})
+ local id = fn.sockconnect(mode, address, { rpc = true })
ok(id > 0)
- funcs.rpcrequest(id, 'nvim_set_current_line', 'hello')
- local client_id = funcs.rpcrequest(id, 'nvim_get_api_info')[1]
+ fn.rpcrequest(id, 'nvim_set_current_line', 'hello')
+ local client_id = fn.rpcrequest(id, 'nvim_get_chan_info', 0).id
set_session(server)
- eq(serverpid, funcs.getpid())
- eq('hello', meths.get_current_line())
+ eq(serverpid, fn.getpid())
+ eq('hello', api.nvim_get_current_line())
-- method calls work both ways
- funcs.rpcrequest(client_id, 'nvim_set_current_line', 'howdy!')
- eq(id, funcs.rpcrequest(client_id, 'nvim_get_api_info')[1])
+ fn.rpcrequest(client_id, 'nvim_set_current_line', 'howdy!')
+ eq(id, fn.rpcrequest(client_id, 'nvim_get_chan_info', 0).id)
set_session(client)
- eq(clientpid, funcs.getpid())
- eq('howdy!', meths.get_current_line())
+ eq(clientpid, fn.getpid())
+ eq('howdy!', api.nvim_get_current_line())
server:close()
client:close()
@@ -302,8 +313,8 @@ describe('server -> client', function()
it('via named pipe', function()
local server = spawn(nvim_argv)
set_session(server)
- local address = funcs.serverlist()[1]
- local first = string.sub(address,1,1)
+ local address = fn.serverlist()[1]
+ local first = string.sub(address, 1, 1)
ok(first == '/' or first == '\\')
connect_test(server, 'pipe', address)
end)
@@ -311,42 +322,42 @@ describe('server -> client', function()
it('via ipv4 address', function()
local server = spawn(nvim_argv)
set_session(server)
- local status, address = pcall(funcs.serverstart, "127.0.0.1:")
+ local status, address = pcall(fn.serverstart, '127.0.0.1:')
if not status then
pending('no ipv4 stack')
end
- eq('127.0.0.1:', string.sub(address,1,10))
+ eq('127.0.0.1:', string.sub(address, 1, 10))
connect_test(server, 'tcp', address)
end)
it('via ipv6 address', function()
local server = spawn(nvim_argv)
set_session(server)
- local status, address = pcall(funcs.serverstart, '::1:')
+ local status, address = pcall(fn.serverstart, '::1:')
if not status then
pending('no ipv6 stack')
end
- eq('::1:', string.sub(address,1,4))
+ eq('::1:', string.sub(address, 1, 4))
connect_test(server, 'tcp', address)
end)
it('via hostname', function()
local server = spawn(nvim_argv)
set_session(server)
- local address = funcs.serverstart("localhost:")
- eq('localhost:', string.sub(address,1,10))
+ local address = fn.serverstart('localhost:')
+ eq('localhost:', string.sub(address, 1, 10))
connect_test(server, 'tcp', address)
end)
it('does not crash on receiving UI events', function()
local server = spawn(nvim_argv)
set_session(server)
- local address = funcs.serverlist()[1]
+ local address = fn.serverlist()[1]
local client = spawn(nvim_argv, false, nil, true)
set_session(client)
- local id = funcs.sockconnect('pipe', address, {rpc=true})
- funcs.rpcrequest(id, 'nvim_ui_attach', 80, 24, {})
+ local id = fn.sockconnect('pipe', address, { rpc = true })
+ fn.rpcrequest(id, 'nvim_ui_attach', 80, 24, {})
assert_alive()
server:close()
@@ -356,18 +367,18 @@ describe('server -> client', function()
describe('connecting to its own pipe address', function()
it('does not deadlock', function()
- local address = funcs.serverlist()[1]
- local first = string.sub(address,1,1)
+ local address = fn.serverlist()[1]
+ local first = string.sub(address, 1, 1)
ok(first == '/' or first == '\\')
- local serverpid = funcs.getpid()
+ local serverpid = fn.getpid()
- local id = funcs.sockconnect('pipe', address, {rpc=true})
+ local id = fn.sockconnect('pipe', address, { rpc = true })
- funcs.rpcrequest(id, 'nvim_set_current_line', 'hello')
- eq('hello', meths.get_current_line())
- eq(serverpid, funcs.rpcrequest(id, "nvim_eval", "getpid()"))
+ fn.rpcrequest(id, 'nvim_set_current_line', 'hello')
+ eq('hello', api.nvim_get_current_line())
+ eq(serverpid, fn.rpcrequest(id, 'nvim_eval', 'getpid()'))
- eq(id, funcs.rpcrequest(id, 'nvim_get_api_info')[1])
+ eq(id, fn.rpcrequest(id, 'nvim_get_chan_info', 0).id)
end)
end)
end)
diff --git a/test/functional/api/tabpage_spec.lua b/test/functional/api/tabpage_spec.lua
index 20b3163d95..36955c4ace 100644
--- a/test/functional/api/tabpage_spec.lua
+++ b/test/functional/api/tabpage_spec.lua
@@ -1,11 +1,9 @@
local helpers = require('test.functional.helpers')(after_each)
-local clear, nvim, tabpage, curtab, eq, ok =
- helpers.clear, helpers.nvim, helpers.tabpage, helpers.curtab, helpers.eq,
- helpers.ok
-local curtabmeths = helpers.curtabmeths
-local funcs = helpers.funcs
+local clear, eq, ok = helpers.clear, helpers.eq, helpers.ok
+local api = helpers.api
+local fn = helpers.fn
local request = helpers.request
-local NIL = helpers.NIL
+local NIL = vim.NIL
local pcall_err = helpers.pcall_err
local command = helpers.command
@@ -14,48 +12,108 @@ describe('api/tabpage', function()
describe('list_wins and get_win', function()
it('works', function()
- nvim('command', 'tabnew')
- nvim('command', 'vsplit')
- local tab1, tab2 = unpack(nvim('list_tabpages'))
- local win1, win2, win3 = unpack(nvim('list_wins'))
- eq({win1}, tabpage('list_wins', tab1))
- eq({win2, win3}, tabpage('list_wins', tab2))
- eq(win2, tabpage('get_win', tab2))
- nvim('set_current_win', win3)
- eq(win3, tabpage('get_win', tab2))
+ command('tabnew')
+ command('vsplit')
+ local tab1, tab2 = unpack(api.nvim_list_tabpages())
+ local win1, win2, win3 = unpack(api.nvim_list_wins())
+ eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
+ eq(win1, api.nvim_tabpage_get_win(tab1))
+ eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
+ eq(win2, api.nvim_tabpage_get_win(tab2))
+ api.nvim_set_current_win(win3)
+ eq(win3, api.nvim_tabpage_get_win(tab2))
+ command('tabprev')
+ eq(win1, api.nvim_tabpage_get_win(tab1))
+ eq(win3, api.nvim_tabpage_get_win(tab2))
end)
it('validates args', function()
- eq('Invalid tabpage id: 23', pcall_err(tabpage, 'list_wins', 23))
+ eq('Invalid tabpage id: 23', pcall_err(api.nvim_tabpage_list_wins, 23))
+ end)
+ end)
+
+ describe('set_win', function()
+ it('works', function()
+ command('tabnew')
+ command('vsplit')
+ local tab1, tab2 = unpack(api.nvim_list_tabpages())
+ local win1, win2, win3 = unpack(api.nvim_list_wins())
+ eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
+ eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
+ eq(win2, api.nvim_tabpage_get_win(tab2))
+ api.nvim_tabpage_set_win(tab2, win3)
+ eq(win3, api.nvim_tabpage_get_win(tab2))
+ end)
+
+ it('works in non-current tabpages', function()
+ command('tabnew')
+ command('vsplit')
+ local tab1, tab2 = unpack(api.nvim_list_tabpages())
+ local win1, win2, win3 = unpack(api.nvim_list_wins())
+ eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
+ eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
+ eq(win2, api.nvim_tabpage_get_win(tab2))
+ eq(win2, api.nvim_get_current_win())
+
+ command('tabprev')
+
+ eq(tab1, api.nvim_get_current_tabpage())
+
+ eq(win2, api.nvim_tabpage_get_win(tab2))
+ api.nvim_tabpage_set_win(tab2, win3)
+ eq(win3, api.nvim_tabpage_get_win(tab2))
+
+ command('tabnext')
+ eq(win3, api.nvim_get_current_win())
+ end)
+
+ it('throws an error when the window does not belong to the tabpage', function()
+ command('tabnew')
+ command('vsplit')
+ local tab1, tab2 = unpack(api.nvim_list_tabpages())
+ local win1, win2, win3 = unpack(api.nvim_list_wins())
+ eq({ win1 }, api.nvim_tabpage_list_wins(tab1))
+ eq({ win2, win3 }, api.nvim_tabpage_list_wins(tab2))
+ eq(win2, api.nvim_get_current_win())
+
+ eq(
+ string.format('Window does not belong to tabpage %d', tab2),
+ pcall_err(api.nvim_tabpage_set_win, tab2, win1)
+ )
+
+ eq(
+ string.format('Window does not belong to tabpage %d', tab1),
+ pcall_err(api.nvim_tabpage_set_win, tab1, win3)
+ )
end)
end)
describe('{get,set,del}_var', function()
it('works', function()
- curtab('set_var', 'lua', {1, 2, {['3'] = 1}})
- eq({1, 2, {['3'] = 1}}, curtab('get_var', 'lua'))
- eq({1, 2, {['3'] = 1}}, nvim('eval', 't:lua'))
- eq(1, funcs.exists('t:lua'))
- curtabmeths.del_var('lua')
- eq(0, funcs.exists('t:lua'))
- eq('Key not found: lua', pcall_err(curtabmeths.del_var, 'lua'))
- curtabmeths.set_var('lua', 1)
+ api.nvim_tabpage_set_var(0, 'lua', { 1, 2, { ['3'] = 1 } })
+ eq({ 1, 2, { ['3'] = 1 } }, api.nvim_tabpage_get_var(0, 'lua'))
+ eq({ 1, 2, { ['3'] = 1 } }, api.nvim_eval('t:lua'))
+ eq(1, fn.exists('t:lua'))
+ api.nvim_tabpage_del_var(0, 'lua')
+ eq(0, fn.exists('t:lua'))
+ eq('Key not found: lua', pcall_err(api.nvim_tabpage_del_var, 0, 'lua'))
+ api.nvim_tabpage_set_var(0, 'lua', 1)
command('lockvar t:lua')
- eq('Key is locked: lua', pcall_err(curtabmeths.del_var, 'lua'))
- eq('Key is locked: lua', pcall_err(curtabmeths.set_var, 'lua', 1))
+ eq('Key is locked: lua', pcall_err(api.nvim_tabpage_del_var, 0, 'lua'))
+ eq('Key is locked: lua', pcall_err(api.nvim_tabpage_set_var, 0, 'lua', 1))
end)
it('tabpage_set_var returns the old value', function()
- local val1 = {1, 2, {['3'] = 1}}
- local val2 = {4, 7}
+ local val1 = { 1, 2, { ['3'] = 1 } }
+ local val2 = { 4, 7 }
eq(NIL, request('tabpage_set_var', 0, 'lua', val1))
eq(val1, request('tabpage_set_var', 0, 'lua', val2))
end)
it('tabpage_del_var returns the old value', function()
- local val1 = {1, 2, {['3'] = 1}}
- local val2 = {4, 7}
- eq(NIL, request('tabpage_set_var', 0, 'lua', val1))
+ local val1 = { 1, 2, { ['3'] = 1 } }
+ local val2 = { 4, 7 }
+ eq(NIL, request('tabpage_set_var', 0, 'lua', val1))
eq(val1, request('tabpage_set_var', 0, 'lua', val2))
eq(val2, request('tabpage_del_var', 0, 'lua'))
end)
@@ -63,28 +121,28 @@ describe('api/tabpage', function()
describe('get_number', function()
it('works', function()
- local tabs = nvim('list_tabpages')
- eq(1, tabpage('get_number', tabs[1]))
+ local tabs = api.nvim_list_tabpages()
+ eq(1, api.nvim_tabpage_get_number(tabs[1]))
- nvim('command', 'tabnew')
- local tab1, tab2 = unpack(nvim('list_tabpages'))
- eq(1, tabpage('get_number', tab1))
- eq(2, tabpage('get_number', tab2))
+ command('tabnew')
+ local tab1, tab2 = unpack(api.nvim_list_tabpages())
+ eq(1, api.nvim_tabpage_get_number(tab1))
+ eq(2, api.nvim_tabpage_get_number(tab2))
- nvim('command', '-tabmove')
- eq(2, tabpage('get_number', tab1))
- eq(1, tabpage('get_number', tab2))
+ command('-tabmove')
+ eq(2, api.nvim_tabpage_get_number(tab1))
+ eq(1, api.nvim_tabpage_get_number(tab2))
end)
end)
describe('is_valid', function()
it('works', function()
- nvim('command', 'tabnew')
- local tab = nvim('list_tabpages')[2]
- nvim('set_current_tabpage', tab)
- ok(tabpage('is_valid', tab))
- nvim('command', 'tabclose')
- ok(not tabpage('is_valid', tab))
+ command('tabnew')
+ local tab = api.nvim_list_tabpages()[2]
+ api.nvim_set_current_tabpage(tab)
+ ok(api.nvim_tabpage_is_valid(tab))
+ command('tabclose')
+ ok(not api.nvim_tabpage_is_valid(tab))
end)
end)
end)
diff --git a/test/functional/api/ui_spec.lua b/test/functional/api/ui_spec.lua
index 6efb6726fe..3e1f1ec965 100644
--- a/test/functional/api/ui_spec.lua
+++ b/test/functional/api/ui_spec.lua
@@ -6,7 +6,7 @@ local eq = helpers.eq
local eval = helpers.eval
local exec = helpers.exec
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
local request = helpers.request
local pcall_err = helpers.pcall_err
@@ -23,42 +23,56 @@ describe('nvim_ui_attach()', function()
end)
it('validation', function()
- eq('No such UI option: foo',
- pcall_err(meths.ui_attach, 80, 24, { foo={'foo'} }))
+ eq('No such UI option: foo', pcall_err(api.nvim_ui_attach, 80, 24, { foo = { 'foo' } }))
- eq("Invalid 'ext_linegrid': expected Boolean, got Array",
- pcall_err(meths.ui_attach, 80, 24, { ext_linegrid={} }))
- eq("Invalid 'override': expected Boolean, got Array",
- pcall_err(meths.ui_attach, 80, 24, { override={} }))
- eq("Invalid 'rgb': expected Boolean, got Array",
- pcall_err(meths.ui_attach, 80, 24, { rgb={} }))
- eq("Invalid 'term_name': expected String, got Boolean",
- pcall_err(meths.ui_attach, 80, 24, { term_name=true }))
- eq("Invalid 'term_colors': expected Integer, got Boolean",
- pcall_err(meths.ui_attach, 80, 24, { term_colors=true }))
- eq("Invalid 'stdin_fd': expected Integer, got String",
- pcall_err(meths.ui_attach, 80, 24, { stdin_fd='foo' }))
- eq("Invalid 'stdin_tty': expected Boolean, got String",
- pcall_err(meths.ui_attach, 80, 24, { stdin_tty='foo' }))
- eq("Invalid 'stdout_tty': expected Boolean, got String",
- pcall_err(meths.ui_attach, 80, 24, { stdout_tty='foo' }))
+ eq(
+ "Invalid 'ext_linegrid': expected Boolean, got Array",
+ pcall_err(api.nvim_ui_attach, 80, 24, { ext_linegrid = {} })
+ )
+ eq(
+ "Invalid 'override': expected Boolean, got Array",
+ pcall_err(api.nvim_ui_attach, 80, 24, { override = {} })
+ )
+ eq(
+ "Invalid 'rgb': expected Boolean, got Array",
+ pcall_err(api.nvim_ui_attach, 80, 24, { rgb = {} })
+ )
+ eq(
+ "Invalid 'term_name': expected String, got Boolean",
+ pcall_err(api.nvim_ui_attach, 80, 24, { term_name = true })
+ )
+ eq(
+ "Invalid 'term_colors': expected Integer, got Boolean",
+ pcall_err(api.nvim_ui_attach, 80, 24, { term_colors = true })
+ )
+ eq(
+ "Invalid 'stdin_fd': expected Integer, got String",
+ pcall_err(api.nvim_ui_attach, 80, 24, { stdin_fd = 'foo' })
+ )
+ eq(
+ "Invalid 'stdin_tty': expected Boolean, got String",
+ pcall_err(api.nvim_ui_attach, 80, 24, { stdin_tty = 'foo' })
+ )
+ eq(
+ "Invalid 'stdout_tty': expected Boolean, got String",
+ pcall_err(api.nvim_ui_attach, 80, 24, { stdout_tty = 'foo' })
+ )
- eq('UI not attached to channel: 1',
- pcall_err(request, 'nvim_ui_try_resize', 40, 10))
- eq('UI not attached to channel: 1',
- pcall_err(request, 'nvim_ui_set_option', 'rgb', true))
- eq('UI not attached to channel: 1',
- pcall_err(request, 'nvim_ui_detach'))
+ eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_try_resize', 40, 10))
+ eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_set_option', 'rgb', true))
+ eq('UI not attached to channel: 1', pcall_err(request, 'nvim_ui_detach'))
local screen = Screen.new()
- screen:attach({rgb=false})
- eq('UI already attached to channel: 1',
- pcall_err(request, 'nvim_ui_attach', 40, 10, { rgb=false }))
+ screen:attach({ rgb = false })
+ eq(
+ 'UI already attached to channel: 1',
+ pcall_err(request, 'nvim_ui_attach', 40, 10, { rgb = false })
+ )
end)
end)
it('autocmds UIEnter/UILeave', function()
- clear{args_rm={'--headless'}}
+ clear { args_rm = { '--headless' } }
exec([[
let g:evs = []
autocmd UIEnter * call add(g:evs, "UIEnter") | let g:uienter_ev = deepcopy(v:event)
@@ -67,9 +81,9 @@ it('autocmds UIEnter/UILeave', function()
]])
local screen = Screen.new()
screen:attach()
- eq({chan=1}, eval('g:uienter_ev'))
+ eq({ chan = 1 }, eval('g:uienter_ev'))
screen:detach()
- eq({chan=1}, eval('g:uileave_ev'))
+ eq({ chan = 1 }, eval('g:uileave_ev'))
eq({
'VimEnter',
'UIEnter',
@@ -89,29 +103,37 @@ it('autocmds VimSuspend/VimResume #22041', function()
eq(false, screen.suspended)
feed('<C-Z>')
- screen:expect(function() eq(true, screen.suspended) end)
+ screen:expect(function()
+ eq(true, screen.suspended)
+ end)
eq({ 's' }, eval('g:ev'))
screen.suspended = false
feed('<Ignore>')
eq({ 's', 'r' }, eval('g:ev'))
command('suspend')
- screen:expect(function() eq(true, screen.suspended) end)
+ screen:expect(function()
+ eq(true, screen.suspended)
+ end)
eq({ 's', 'r', 's' }, eval('g:ev'))
screen.suspended = false
- meths.input_mouse('move', '', '', 0, 0, 0)
+ api.nvim_input_mouse('move', '', '', 0, 0, 0)
eq({ 's', 'r', 's', 'r' }, eval('g:ev'))
feed('<C-Z><C-Z><C-Z>')
- screen:expect(function() eq(true, screen.suspended) end)
- meths.ui_set_focus(false)
+ screen:expect(function()
+ eq(true, screen.suspended)
+ end)
+ api.nvim_ui_set_focus(false)
eq({ 's', 'r', 's', 'r', 's' }, eval('g:ev'))
screen.suspended = false
- meths.ui_set_focus(true)
+ api.nvim_ui_set_focus(true)
eq({ 's', 'r', 's', 'r', 's', 'r' }, eval('g:ev'))
command('suspend | suspend | suspend')
- screen:expect(function() eq(true, screen.suspended) end)
+ screen:expect(function()
+ eq(true, screen.suspended)
+ end)
screen:detach()
eq({ 's', 'r', 's', 'r', 's', 'r', 's' }, eval('g:ev'))
screen.suspended = false
diff --git a/test/functional/api/version_spec.lua b/test/functional/api/version_spec.lua
index 6d466b0cc1..c304f1aa88 100644
--- a/test/functional/api/version_spec.lua
+++ b/test/functional/api/version_spec.lua
@@ -1,8 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
-local mpack = require('mpack')
-local clear, funcs, eq = helpers.clear, helpers.funcs, helpers.eq
-local call = helpers.call
-local meths = helpers.meths
+local clear, fn, eq = helpers.clear, helpers.fn, helpers.eq
+local api = helpers.api
local function read_mpack_file(fname)
local fd = io.open(fname, 'rb')
@@ -12,48 +10,47 @@ local function read_mpack_file(fname)
local data = fd:read('*a')
fd:close()
- local unpack = mpack.Unpacker()
+ local unpack = vim.mpack.Unpacker()
return unpack(data)
end
describe("api_info()['version']", function()
before_each(clear)
- it("returns API level", function()
- local version = call('api_info')['version']
+ it('returns API level', function()
+ local version = fn.api_info()['version']
local current = version['api_level']
- local compat = version['api_compatible']
- eq("number", type(current))
- eq("number", type(compat))
+ local compat = version['api_compatible']
+ eq('number', type(current))
+ eq('number', type(compat))
assert(current >= compat)
end)
- it("returns Nvim version", function()
- local version = call('api_info')['version']
- local major = version['major']
- local minor = version['minor']
- local patch = version['patch']
+ it('returns Nvim version', function()
+ local version = fn.api_info()['version']
+ local major = version['major']
+ local minor = version['minor']
+ local patch = version['patch']
local prerelease = version['prerelease']
- local build = version['build']
- eq("number", type(major))
- eq("number", type(minor))
- eq("number", type(patch))
- eq("boolean", type(prerelease))
- eq(1, funcs.has("nvim-"..major.."."..minor.."."..patch))
- eq(0, funcs.has("nvim-"..major.."."..minor.."."..(patch + 1)))
- eq(0, funcs.has("nvim-"..major.."."..(minor + 1).."."..patch))
- eq(0, funcs.has("nvim-"..(major + 1).."."..minor.."."..patch))
+ local build = version['build']
+ eq('number', type(major))
+ eq('number', type(minor))
+ eq('number', type(patch))
+ eq('boolean', type(prerelease))
+ eq(1, fn.has('nvim-' .. major .. '.' .. minor .. '.' .. patch))
+ eq(0, fn.has('nvim-' .. major .. '.' .. minor .. '.' .. (patch + 1)))
+ eq(0, fn.has('nvim-' .. major .. '.' .. (minor + 1) .. '.' .. patch))
+ eq(0, fn.has('nvim-' .. (major + 1) .. '.' .. minor .. '.' .. patch))
assert(build == nil or type(build) == 'string')
end)
end)
-
-describe("api metadata", function()
+describe('api metadata', function()
before_each(clear)
local function name_table(entries)
local by_name = {}
- for _,e in ipairs(entries) do
+ for _, e in ipairs(entries) do
by_name[e.name] = e
end
return by_name
@@ -63,10 +60,10 @@ describe("api metadata", function()
local function filter_function_metadata(f)
f.deprecated_since = nil
for idx, _ in ipairs(f.parameters) do
- f.parameters[idx][2] = '' -- Remove parameter name.
+ f.parameters[idx][2] = '' -- Remove parameter name.
end
- if string.sub(f.name, 1, 4) ~= "nvim" then
+ if string.sub(f.name, 1, 4) ~= 'nvim' then
f.method = nil
end
return f
@@ -76,7 +73,7 @@ describe("api metadata", function()
-- check types of existing params are the same
-- adding parameters is ok, but removing params is not (gives nil error)
eq(old_e.since, new_e.since, old_e.name)
- for i,p in ipairs(old_e.parameters) do
+ for i, p in ipairs(old_e.parameters) do
eq(new_e.parameters[i][1], p[1], old_e.name)
end
end
@@ -92,28 +89,30 @@ describe("api metadata", function()
end
end
- local api, compat, stable, api_level
+ local api_info, compat, stable, api_level
local old_api = {}
setup(function()
- clear() -- Ensure a session before requesting api_info.
- api = meths.get_api_info()[2]
- compat = api.version.api_compatible
- api_level = api.version.api_level
- if api.version.api_prerelease then
- stable = api_level-1
+ clear() -- Ensure a session before requesting api_info.
+ api_info = api.nvim_get_api_info()[2]
+ compat = api_info.version.api_compatible
+ api_level = api_info.version.api_level
+ if api_info.version.api_prerelease then
+ stable = api_level - 1
else
stable = api_level
end
for level = compat, stable do
- local path = ('test/functional/fixtures/api_level_'..
- tostring(level)..'.mpack')
+ local path = ('test/functional/fixtures/api_level_' .. tostring(level) .. '.mpack')
old_api[level] = read_mpack_file(path)
if old_api[level] == nil then
- local errstr = "missing metadata fixture for stable level "..level..". "
- if level == api_level and not api.version.api_prerelease then
- errstr = (errstr.."If NVIM_API_CURRENT was bumped, "..
- "don't forget to set NVIM_API_PRERELEASE to true.")
+ local errstr = 'missing metadata fixture for stable level ' .. level .. '. '
+ if level == api_level and not api_info.version.api_prerelease then
+ errstr = (
+ errstr
+ .. 'If NVIM_API_CURRENT was bumped, '
+ .. "don't forget to set NVIM_API_PRERELEASE to true."
+ )
end
error(errstr)
end
@@ -124,60 +123,76 @@ describe("api metadata", function()
end
end)
- it("functions are compatible with old metadata or have new level", function()
- local funcs_new = name_table(api.functions)
+ it('functions are compatible with old metadata or have new level', function()
+ local funcs_new = name_table(api_info.functions)
local funcs_compat = {}
for level = compat, stable do
- for _,f in ipairs(old_api[level].functions) do
+ for _, f in ipairs(old_api[level].functions) do
if funcs_new[f.name] == nil then
if f.since >= compat then
- error('function '..f.name..' was removed but exists in level '..
- f.since..' which nvim should be compatible with')
+ error(
+ 'function '
+ .. f.name
+ .. ' was removed but exists in level '
+ .. f.since
+ .. ' which nvim should be compatible with'
+ )
end
else
- eq(filter_function_metadata(f),
- filter_function_metadata(funcs_new[f.name]))
+ eq(filter_function_metadata(f), filter_function_metadata(funcs_new[f.name]))
end
end
funcs_compat[level] = name_table(old_api[level].functions)
end
- for _,f in ipairs(api.functions) do
+ for _, f in ipairs(api_info.functions) do
if f.since <= stable then
local f_old = funcs_compat[f.since][f.name]
if f_old == nil then
- if string.sub(f.name, 1, 4) == "nvim" then
- local errstr = ("function "..f.name.." has too low since value. "..
- "For new functions set it to "..(stable+1)..".")
- if not api.version.api_prerelease then
- errstr = (errstr.." Also bump NVIM_API_CURRENT and set "..
- "NVIM_API_PRERELEASE to true in CMakeLists.txt.")
+ if string.sub(f.name, 1, 4) == 'nvim' then
+ local errstr = (
+ 'function '
+ .. f.name
+ .. ' has too low since value. '
+ .. 'For new functions set it to '
+ .. (stable + 1)
+ .. '.'
+ )
+ if not api_info.version.api_prerelease then
+ errstr = (
+ errstr
+ .. ' Also bump NVIM_API_CURRENT and set '
+ .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.'
+ )
end
error(errstr)
else
- error("function name '"..f.name.."' doesn't begin with 'nvim_'")
+ error("function name '" .. f.name .. "' doesn't begin with 'nvim_'")
end
end
elseif f.since > api_level then
- if api.version.api_prerelease then
- error("New function "..f.name.." should use since value "..
- api_level)
+ if api_info.version.api_prerelease then
+ error('New function ' .. f.name .. ' should use since value ' .. api_level)
else
- error("function "..f.name.." has since value > api_level. "..
- "Bump NVIM_API_CURRENT and set "..
- "NVIM_API_PRERELEASE to true in CMakeLists.txt.")
+ error(
+ 'function '
+ .. f.name
+ .. ' has since value > api_level. '
+ .. 'Bump NVIM_API_CURRENT and set '
+ .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.'
+ )
end
end
end
end)
- it("UI events are compatible with old metadata or have new level", function()
- local ui_events_new = name_table(api.ui_events)
+ it('UI events are compatible with old metadata or have new level', function()
+ local ui_events_new = name_table(api_info.ui_events)
local ui_events_compat = {}
-- UI events were formalized in level 3
for level = 3, stable do
- for _,e in ipairs(old_api[level].ui_events) do
+ for _, e in ipairs(old_api[level].ui_events) do
local new_e = ui_events_new[e.name]
if new_e ~= nil then
check_ui_event_compatible(e, new_e)
@@ -186,41 +201,53 @@ describe("api metadata", function()
ui_events_compat[level] = name_table(old_api[level].ui_events)
end
- for _,e in ipairs(api.ui_events) do
+ for _, e in ipairs(api_info.ui_events) do
if e.since <= stable then
local e_old = ui_events_compat[e.since][e.name]
if e_old == nil then
- local errstr = ("UI event "..e.name.." has too low since value. "..
- "For new events set it to "..(stable+1)..".")
- if not api.version.api_prerelease then
- errstr = (errstr.." Also bump NVIM_API_CURRENT and set "..
- "NVIM_API_PRERELEASE to true in CMakeLists.txt.")
+ local errstr = (
+ 'UI event '
+ .. e.name
+ .. ' has too low since value. '
+ .. 'For new events set it to '
+ .. (stable + 1)
+ .. '.'
+ )
+ if not api_info.version.api_prerelease then
+ errstr = (
+ errstr
+ .. ' Also bump NVIM_API_CURRENT and set '
+ .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.'
+ )
end
error(errstr)
end
elseif e.since > api_level then
- if api.version.api_prerelease then
- error("New UI event "..e.name.." should use since value "..
- api_level)
+ if api_info.version.api_prerelease then
+ error('New UI event ' .. e.name .. ' should use since value ' .. api_level)
else
- error("UI event "..e.name.." has since value > api_level. "..
- "Bump NVIM_API_CURRENT and set "..
- "NVIM_API_PRERELEASE to true in CMakeLists.txt.")
+ error(
+ 'UI event '
+ .. e.name
+ .. ' has since value > api_level. '
+ .. 'Bump NVIM_API_CURRENT and set '
+ .. 'NVIM_API_PRERELEASE to true in CMakeLists.txt.'
+ )
end
end
end
end)
- it("ui_options are preserved from older levels", function()
+ it('ui_options are preserved from older levels', function()
local available_options = {}
- for _, option in ipairs(api.ui_options) do
+ for _, option in ipairs(api_info.ui_options) do
available_options[option] = true
end
-- UI options were versioned from level 4
for level = 4, stable do
for _, option in ipairs(old_api[level].ui_options) do
if not available_options[option] then
- error("UI option "..option.." from stable metadata is missing")
+ error('UI option ' .. option .. ' from stable metadata is missing')
end
end
end
diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua
index 8bbadda9b0..9a4a457637 100644
--- a/test/functional/api/vim_spec.lua
+++ b/test/functional/api/vim_spec.lua
@@ -1,22 +1,25 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local luv = require('luv')
+local uv = vim.uv
local fmt = string.format
+local dedent = helpers.dedent
local assert_alive = helpers.assert_alive
-local NIL = helpers.NIL
-local clear, nvim, eq, neq = helpers.clear, helpers.nvim, helpers.eq, helpers.neq
+local NIL = vim.NIL
+local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq
local command = helpers.command
+local command_output = helpers.api.nvim_command_output
local exec = helpers.exec
local exec_capture = helpers.exec_capture
local eval = helpers.eval
local expect = helpers.expect
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local matches = helpers.matches
-local pesc = helpers.pesc
+local pesc = vim.pesc
local mkdir_p = helpers.mkdir_p
local ok, nvim_async, feed = helpers.ok, helpers.nvim_async, helpers.feed
+local async_meths = helpers.async_meths
local is_os = helpers.is_os
local parse_context = helpers.parse_context
local request = helpers.request
@@ -31,203 +34,273 @@ local insert = helpers.insert
local skip = helpers.skip
local pcall_err = helpers.pcall_err
-local format_string = helpers.format_string
+local format_string = require('test.format_string').format_string
local intchar2lua = helpers.intchar2lua
local mergedicts_copy = helpers.mergedicts_copy
-local endswith = helpers.endswith
+local endswith = vim.endswith
describe('API', function()
before_each(clear)
it('validates requests', function()
-- RPC
- matches('Invalid method: bogus$',
- pcall_err(request, 'bogus'))
- matches('Invalid method: … 㮠り 。…$',
- pcall_err(request, '… 㮠り 。…'))
- matches('Invalid method: <empty>$',
- pcall_err(request, ''))
+ matches('Invalid method: bogus$', pcall_err(request, 'bogus'))
+ matches('Invalid method: … 㮠り 。…$', pcall_err(request, '… 㮠り 。…'))
+ matches('Invalid method: <empty>$', pcall_err(request, ''))
-- Non-RPC: rpcrequest(v:servername) uses internal channel.
- matches('Invalid method: … 㮠り 。…$',
- pcall_err(request, 'nvim_eval',
- [=[rpcrequest(sockconnect('pipe', v:servername, {'rpc':1}), '… 㮠り 。…')]=]))
- matches('Invalid method: bogus$',
- pcall_err(request, 'nvim_eval',
- [=[rpcrequest(sockconnect('pipe', v:servername, {'rpc':1}), 'bogus')]=]))
+ matches(
+ 'Invalid method: … 㮠り 。…$',
+ pcall_err(
+ request,
+ 'nvim_eval',
+ [=[rpcrequest(sockconnect('pipe', v:servername, {'rpc':1}), '… 㮠り 。…')]=]
+ )
+ )
+ matches(
+ 'Invalid method: bogus$',
+ pcall_err(
+ request,
+ 'nvim_eval',
+ [=[rpcrequest(sockconnect('pipe', v:servername, {'rpc':1}), 'bogus')]=]
+ )
+ )
-- XXX: This must be the last one, else next one will fail:
-- "Packer instance already working. Use another Packer ..."
- matches("can't serialize object of type .$",
- pcall_err(request, nil))
+ matches("can't serialize object of type .$", pcall_err(request, nil))
end)
it('handles errors in async requests', function()
- local error_types = meths.get_api_info()[2].error_types
+ local error_types = api.nvim_get_api_info()[2].error_types
nvim_async('bogus')
- eq({'notification', 'nvim_error_event',
- {error_types.Exception.id, 'Invalid method: nvim_bogus'}}, next_msg())
+ eq({
+ 'notification',
+ 'nvim_error_event',
+ { error_types.Exception.id, 'Invalid method: bogus' },
+ }, next_msg())
-- error didn't close channel.
assert_alive()
end)
it('failed async request emits nvim_error_event', function()
- local error_types = meths.get_api_info()[2].error_types
- nvim_async('command', 'bogus')
- eq({'notification', 'nvim_error_event',
- {error_types.Exception.id, 'Vim:E492: Not an editor command: bogus'}},
- next_msg())
+ local error_types = api.nvim_get_api_info()[2].error_types
+ async_meths.nvim_command('bogus')
+ eq({
+ 'notification',
+ 'nvim_error_event',
+ { error_types.Exception.id, 'Vim:E492: Not an editor command: bogus' },
+ }, next_msg())
-- error didn't close channel.
assert_alive()
end)
+ it('input is processed first when followed immediately by non-fast events', function()
+ api.nvim_set_current_line('ab')
+ async_meths.nvim_input('x')
+ async_meths.nvim_exec_lua('_G.res1 = vim.api.nvim_get_current_line()', {})
+ async_meths.nvim_exec_lua('_G.res2 = vim.api.nvim_get_current_line()', {})
+ eq({ 'b', 'b' }, exec_lua('return { _G.res1, _G.res2 }'))
+ end)
+
it('does not set CA_COMMAND_BUSY #7254', function()
- nvim('command', 'split')
- nvim('command', 'autocmd WinEnter * startinsert')
- nvim('command', 'wincmd w')
- eq({mode='i', blocking=false}, nvim("get_mode"))
+ command('split')
+ command('autocmd WinEnter * startinsert')
+ command('wincmd w')
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
end)
describe('nvim_exec2', function()
it('always returns table', function()
-- In built version this results into `vim.empty_dict()`
- eq({}, nvim('exec2', 'echo "Hello"', {}))
- eq({}, nvim('exec2', 'echo "Hello"', { output = false }))
- eq({ output = 'Hello' }, nvim('exec2', 'echo "Hello"', { output = true }))
+ eq({}, api.nvim_exec2('echo "Hello"', {}))
+ eq({}, api.nvim_exec2('echo "Hello"', { output = false }))
+ eq({ output = 'Hello' }, api.nvim_exec2('echo "Hello"', { output = true }))
end)
it('default options', function()
-- Should be equivalent to { output = false }
- nvim('exec2', "let x0 = 'a'", {})
- eq('a', nvim('get_var', 'x0'))
+ api.nvim_exec2("let x0 = 'a'", {})
+ eq('a', api.nvim_get_var('x0'))
end)
it('one-line input', function()
- nvim('exec2', "let x1 = 'a'", { output = false })
- eq('a', nvim('get_var', 'x1'))
+ api.nvim_exec2("let x1 = 'a'", { output = false })
+ eq('a', api.nvim_get_var('x1'))
end)
it(':verbose set {option}?', function()
- nvim('exec2', 'set nowrap', { output = false })
- eq({ output = 'nowrap\n\tLast set from anonymous :source' },
- nvim('exec2', 'verbose set wrap?', { output = true }))
+ api.nvim_exec2('set nowrap', { output = false })
+ eq(
+ { output = 'nowrap\n\tLast set from anonymous :source' },
+ api.nvim_exec2('verbose set wrap?', { output = true })
+ )
-- Using script var to force creation of a script item
- nvim('exec2', [[
+ api.nvim_exec2(
+ [[
let s:a = 1
set nowrap
- ]], { output = false })
- eq({ output = 'nowrap\n\tLast set from anonymous :source (script id 1)' },
- nvim('exec2', 'verbose set wrap?', { output = true }))
+ ]],
+ { output = false }
+ )
+ eq(
+ { output = 'nowrap\n\tLast set from anonymous :source (script id 1)' },
+ api.nvim_exec2('verbose set wrap?', { output = true })
+ )
end)
it('multiline input', function()
-- Heredoc + empty lines.
- nvim('exec2', "let x2 = 'a'\n", { output = false })
- eq('a', nvim('get_var', 'x2'))
- nvim('exec2','lua <<EOF\n\n\n\ny=3\n\n\nEOF', { output = false })
- eq(3, nvim('eval', "luaeval('y')"))
+ api.nvim_exec2("let x2 = 'a'\n", { output = false })
+ eq('a', api.nvim_get_var('x2'))
+ api.nvim_exec2('lua <<EOF\n\n\n\ny=3\n\n\nEOF', { output = false })
+ eq(3, api.nvim_eval("luaeval('y')"))
- eq({}, nvim('exec2', 'lua <<EOF\ny=3\nEOF', { output = false }))
- eq(3, nvim('eval', "luaeval('y')"))
+ eq({}, api.nvim_exec2('lua <<EOF\ny=3\nEOF', { output = false }))
+ eq(3, api.nvim_eval("luaeval('y')"))
-- Multiple statements
- nvim('exec2', 'let x1=1\nlet x2=2\nlet x3=3\n', { output = false })
- eq(1, nvim('eval', 'x1'))
- eq(2, nvim('eval', 'x2'))
- eq(3, nvim('eval', 'x3'))
+ api.nvim_exec2('let x1=1\nlet x2=2\nlet x3=3\n', { output = false })
+ eq(1, api.nvim_eval('x1'))
+ eq(2, api.nvim_eval('x2'))
+ eq(3, api.nvim_eval('x3'))
-- Functions
- nvim('exec2', 'function Foo()\ncall setline(1,["xxx"])\nendfunction', { output = false })
- eq('', nvim('get_current_line'))
- nvim('exec2', 'call Foo()', { output = false })
- eq('xxx', nvim('get_current_line'))
+ api.nvim_exec2('function Foo()\ncall setline(1,["xxx"])\nendfunction', { output = false })
+ eq('', api.nvim_get_current_line())
+ api.nvim_exec2('call Foo()', { output = false })
+ eq('xxx', api.nvim_get_current_line())
-- Autocmds
- nvim('exec2','autocmd BufAdd * :let x1 = "Hello"', { output = false })
- nvim('command', 'new foo')
+ api.nvim_exec2('autocmd BufAdd * :let x1 = "Hello"', { output = false })
+ command('new foo')
eq('Hello', request('nvim_eval', 'g:x1'))
-- Line continuations
- nvim('exec2', [[
+ api.nvim_exec2(
+ [[
let abc = #{
\ a: 1,
"\ b: 2,
\ c: 3
- \ }]], { output = false })
- eq({a = 1, c = 3}, request('nvim_eval', 'g:abc'))
+ \ }]],
+ { output = false }
+ )
+ eq({ a = 1, c = 3 }, request('nvim_eval', 'g:abc'))
-- try no spaces before continuations to catch off-by-one error
- nvim('exec2', 'let ab = #{\n\\a: 98,\n"\\ b: 2\n\\}', { output = false })
- eq({a = 98}, request('nvim_eval', 'g:ab'))
+ api.nvim_exec2('let ab = #{\n\\a: 98,\n"\\ b: 2\n\\}', { output = false })
+ eq({ a = 98 }, request('nvim_eval', 'g:ab'))
-- Script scope (s:)
- eq({ output = 'ahoy! script-scoped varrrrr' }, nvim('exec2', [[
+ eq(
+ { output = 'ahoy! script-scoped varrrrr' },
+ api.nvim_exec2(
+ [[
let s:pirate = 'script-scoped varrrrr'
function! s:avast_ye_hades(s) abort
return a:s .. ' ' .. s:pirate
endfunction
echo <sid>avast_ye_hades('ahoy!')
- ]], { output = true }))
-
- eq({ output = "{'output': 'ahoy! script-scoped varrrrr'}" }, nvim('exec2', [[
+ ]],
+ { output = true }
+ )
+ )
+
+ eq(
+ { output = "{'output': 'ahoy! script-scoped varrrrr'}" },
+ api.nvim_exec2(
+ [[
let s:pirate = 'script-scoped varrrrr'
function! Avast_ye_hades(s) abort
return a:s .. ' ' .. s:pirate
endfunction
echo nvim_exec2('echo Avast_ye_hades(''ahoy!'')', {'output': v:true})
- ]], { output = true }))
-
- matches('Vim%(echo%):E121: Undefined variable: s:pirate$',
- pcall_err(request, 'nvim_exec2', [[
+ ]],
+ { output = true }
+ )
+ )
+
+ matches(
+ 'Vim%(echo%):E121: Undefined variable: s:pirate$',
+ pcall_err(
+ request,
+ 'nvim_exec2',
+ [[
let s:pirate = 'script-scoped varrrrr'
call nvim_exec2('echo s:pirate', {'output': v:true})
- ]], { output = false }))
+ ]],
+ { output = false }
+ )
+ )
-- Script items are created only on script var access
- eq({ output = '1\n0' }, nvim('exec2', [[
+ eq(
+ { output = '1\n0' },
+ api.nvim_exec2(
+ [[
echo expand("<SID>")->empty()
let s:a = 123
echo expand("<SID>")->empty()
- ]], { output = true }))
-
- eq({ output = '1\n0' }, nvim('exec2', [[
+ ]],
+ { output = true }
+ )
+ )
+
+ eq(
+ { output = '1\n0' },
+ api.nvim_exec2(
+ [[
echo expand("<SID>")->empty()
function s:a() abort
endfunction
echo expand("<SID>")->empty()
- ]], { output = true }))
+ ]],
+ { output = true }
+ )
+ )
end)
it('non-ASCII input', function()
- nvim('exec2', [=[
+ api.nvim_exec2(
+ [=[
new
exe "normal! i ax \n Ax "
:%s/ax/--a1234--/g | :%s/Ax/--A1234--/g
- ]=], { output = false })
- nvim('command', '1')
- eq(' --a1234-- ', nvim('get_current_line'))
- nvim('command', '2')
- eq(' --A1234-- ', nvim('get_current_line'))
-
- nvim('exec2', [[
+ ]=],
+ { output = false }
+ )
+ command('1')
+ eq(' --a1234-- ', api.nvim_get_current_line())
+ command('2')
+ eq(' --A1234-- ', api.nvim_get_current_line())
+
+ api.nvim_exec2(
+ [[
new
call setline(1,['xxx'])
call feedkeys('r')
call feedkeys('ñ', 'xt')
- ]], { output = false })
- eq('ñxx', nvim('get_current_line'))
+ ]],
+ { output = false }
+ )
+ eq('ñxx', api.nvim_get_current_line())
end)
it('execution error', function()
- eq('nvim_exec2(): Vim:E492: Not an editor command: bogus_command',
- pcall_err(request, 'nvim_exec2', 'bogus_command', {}))
- eq('', nvim('eval', 'v:errmsg')) -- v:errmsg was not updated.
+ eq(
+ 'nvim_exec2(): Vim:E492: Not an editor command: bogus_command',
+ pcall_err(request, 'nvim_exec2', 'bogus_command', {})
+ )
+ eq('', api.nvim_eval('v:errmsg')) -- v:errmsg was not updated.
eq('', eval('v:exception'))
- eq('nvim_exec2(): Vim(buffer):E86: Buffer 23487 does not exist',
- pcall_err(request, 'nvim_exec2', 'buffer 23487', {}))
- eq('', eval('v:errmsg')) -- v:errmsg was not updated.
+ eq(
+ 'nvim_exec2(): Vim(buffer):E86: Buffer 23487 does not exist',
+ pcall_err(request, 'nvim_exec2', 'buffer 23487', {})
+ )
+ eq('', eval('v:errmsg')) -- v:errmsg was not updated.
eq('', eval('v:exception'))
end)
@@ -240,7 +313,7 @@ describe('API', function()
request('nvim_exec2', [[
let x2 = substitute('foo','o','X','g')
let x4 = 'should be overwritten'
- call nvim_exec2("source ]]..fname..[[\nlet x3 = substitute('foo','foo','set by recursive nvim_exec2','g')\nlet x5='overwritten'\nlet x4=x5\n", {'output': v:false})
+ call nvim_exec2("source ]] .. fname .. [[\nlet x3 = substitute('foo','foo','set by recursive nvim_exec2','g')\nlet x5='overwritten'\nlet x4=x5\n", {'output': v:false})
]], { output = false })
eq('set from :source file', request('nvim_get_var', 'x1'))
eq('fXX', request('nvim_get_var', 'x2'))
@@ -254,86 +327,108 @@ describe('API', function()
local fname = tmpname()
write_file(fname, 'echo "hello"\n')
local sourcing_fname = tmpname()
- write_file(sourcing_fname, 'call nvim_exec2("source '..fname..'", {"output": v:false})\n')
- meths.exec2('set verbose=2', { output = false })
- local traceback_output = 'line 0: sourcing "'..sourcing_fname..'"\n'..
- 'line 0: sourcing "'..fname..'"\n'..
- 'hello\n'..
- 'finished sourcing '..fname..'\n'..
- 'continuing in nvim_exec2() called at '..sourcing_fname..':1\n'..
- 'finished sourcing '..sourcing_fname..'\n'..
- 'continuing in nvim_exec2() called at nvim_exec2():0'
- eq({ output = traceback_output },
- meths.exec2('call nvim_exec2("source '..sourcing_fname..'", {"output": v:false})', { output = true }))
+ write_file(sourcing_fname, 'call nvim_exec2("source ' .. fname .. '", {"output": v:false})\n')
+ api.nvim_exec2('set verbose=2', { output = false })
+ local traceback_output = dedent([[
+ line 0: sourcing "%s"
+ line 0: sourcing "%s"
+ hello
+ finished sourcing %s
+ continuing in nvim_exec2() called at %s:1
+ finished sourcing %s
+ continuing in nvim_exec2() called at nvim_exec2():0]]):format(
+ sourcing_fname,
+ fname,
+ fname,
+ sourcing_fname,
+ sourcing_fname
+ )
+ eq(
+ { output = traceback_output },
+ api.nvim_exec2(
+ 'call nvim_exec2("source ' .. sourcing_fname .. '", {"output": v:false})',
+ { output = true }
+ )
+ )
os.remove(fname)
os.remove(sourcing_fname)
end)
it('returns output', function()
- eq({ output = 'this is spinal tap' },
- nvim('exec2', 'lua <<EOF\n\n\nprint("this is spinal tap")\n\n\nEOF', { output = true }))
- eq({ output = '' }, nvim('exec2', 'echo', { output = true }))
- eq({ output = 'foo 42' }, nvim('exec2', 'echo "foo" 42', { output = true }))
+ eq(
+ { output = 'this is spinal tap' },
+ api.nvim_exec2('lua <<EOF\n\n\nprint("this is spinal tap")\n\n\nEOF', { output = true })
+ )
+ eq({ output = '' }, api.nvim_exec2('echo', { output = true }))
+ eq({ output = 'foo 42' }, api.nvim_exec2('echo "foo" 42', { output = true }))
end)
it('displays messages when opts.output=false', function()
local screen = Screen.new(40, 8)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
})
- meths.exec2("echo 'hello'", { output = false })
- screen:expect{grid=[[
+ api.nvim_exec2("echo 'hello'", { output = false })
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
hello |
- ]]}
+ ]],
+ }
end)
- it('doesn\'t display messages when output=true', function()
+ it("doesn't display messages when output=true", function()
local screen = Screen.new(40, 6)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
})
- meths.exec2("echo 'hello'", { output = true })
- screen:expect{grid=[[
+ api.nvim_exec2("echo 'hello'", { output = true })
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
- ]]}
+ ]],
+ }
exec([[
func Print()
call nvim_exec2('echo "hello"', { 'output': v:true })
endfunc
]])
feed([[:echon 1 | call Print() | echon 5<CR>]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
15 |
- ]]}
+ ]],
+ }
+ end)
+
+ it('errors properly when command too recursive', function()
+ exec_lua([[
+ _G.success = false
+ vim.api.nvim_create_user_command('Test', function()
+ vim.api.nvim_exec2('Test', {})
+ _G.success = true
+ end, {})
+ ]])
+ pcall_err(command, 'Test')
+ assert_alive()
+ eq(false, exec_lua('return _G.success'))
end)
end)
describe('nvim_command', function()
it('works', function()
local fname = tmpname()
- nvim('command', 'new')
- nvim('command', 'edit '..fname)
- nvim('command', 'normal itesting\napi')
- nvim('command', 'w')
+ command('new')
+ command('edit ' .. fname)
+ command('normal itesting\napi')
+ command('w')
local f = assert(io.open(fname))
if is_os('win') then
eq('testing\r\napi\r\n', f:read('*a'))
@@ -345,158 +440,166 @@ describe('API', function()
end)
it('Vimscript validation error: fails with specific error', function()
- local status, rv = pcall(nvim, "command", "bogus_command")
- eq(false, status) -- nvim_command() failed.
- eq("E492:", string.match(rv, "E%d*:")) -- Vimscript error was returned.
- eq('', nvim('eval', 'v:errmsg')) -- v:errmsg was not updated.
+ local status, rv = pcall(command, 'bogus_command')
+ eq(false, status) -- nvim_command() failed.
+ eq('E492:', string.match(rv, 'E%d*:')) -- Vimscript error was returned.
+ eq('', api.nvim_eval('v:errmsg')) -- v:errmsg was not updated.
eq('', eval('v:exception'))
end)
it('Vimscript execution error: fails with specific error', function()
- local status, rv = pcall(nvim, "command", "buffer 23487")
- eq(false, status) -- nvim_command() failed.
- eq("E86: Buffer 23487 does not exist", string.match(rv, "E%d*:.*"))
- eq('', eval('v:errmsg')) -- v:errmsg was not updated.
+ local status, rv = pcall(command, 'buffer 23487')
+ eq(false, status) -- nvim_command() failed.
+ eq('E86: Buffer 23487 does not exist', string.match(rv, 'E%d*:.*'))
+ eq('', eval('v:errmsg')) -- v:errmsg was not updated.
eq('', eval('v:exception'))
end)
it('gives E493 instead of prompting on backwards range', function()
command('split')
- eq('Vim(windo):E493: Backwards range given: 2,1windo echo',
- pcall_err(command, '2,1windo echo'))
+ eq(
+ 'Vim(windo):E493: Backwards range given: 2,1windo echo',
+ pcall_err(command, '2,1windo echo')
+ )
end)
end)
describe('nvim_command_output', function()
it('does not induce hit-enter prompt', function()
- nvim("ui_attach", 80, 20, {})
+ api.nvim_ui_attach(80, 20, {})
-- Induce a hit-enter prompt use nvim_input (non-blocking).
- nvim('command', 'set cmdheight=1')
- nvim('input', [[:echo "hi\nhi2"<CR>]])
+ command('set cmdheight=1')
+ api.nvim_input([[:echo "hi\nhi2"<CR>]])
-- Verify hit-enter prompt.
- eq({mode='r', blocking=true}, nvim("get_mode"))
- nvim('input', [[<C-c>]])
+ eq({ mode = 'r', blocking = true }, api.nvim_get_mode())
+ api.nvim_input([[<C-c>]])
-- Verify NO hit-enter prompt.
- nvim('command_output', [[echo "hi\nhi2"]])
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ command_output([[echo "hi\nhi2"]])
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
it('captures command output', function()
- eq('this is\nspinal tap',
- nvim('command_output', [[echo "this is\nspinal tap"]]))
- eq('no line ending!',
- nvim('command_output', [[echon "no line ending!"]]))
+ eq('this is\nspinal tap', command_output([[echo "this is\nspinal tap"]]))
+ eq('no line ending!', command_output([[echon "no line ending!"]]))
end)
it('captures empty command output', function()
- eq('', nvim('command_output', 'echo'))
+ eq('', command_output('echo'))
end)
it('captures single-char command output', function()
- eq('x', nvim('command_output', 'echo "x"'))
+ eq('x', command_output('echo "x"'))
end)
it('captures multiple commands', function()
- eq('foo\n 1 %a "[No Name]" line 1',
- nvim('command_output', 'echo "foo" | ls'))
+ eq('foo\n 1 %a "[No Name]" line 1', command_output('echo "foo" | ls'))
end)
it('captures nested execute()', function()
- eq('\nnested1\nnested2\n 1 %a "[No Name]" line 1',
- nvim('command_output',
- [[echo execute('echo "nested1\nnested2"') | ls]]))
+ eq(
+ '\nnested1\nnested2\n 1 %a "[No Name]" line 1',
+ command_output([[echo execute('echo "nested1\nnested2"') | ls]])
+ )
end)
it('captures nested nvim_command_output()', function()
- eq('nested1\nnested2\n 1 %a "[No Name]" line 1',
- nvim('command_output',
- [[echo nvim_command_output('echo "nested1\nnested2"') | ls]]))
+ eq(
+ 'nested1\nnested2\n 1 %a "[No Name]" line 1',
+ command_output([[echo nvim_command_output('echo "nested1\nnested2"') | ls]])
+ )
end)
it('returns shell |:!| output', function()
local win_lf = is_os('win') and '\r' or ''
- eq(':!echo foo\r\n\nfoo'..win_lf..'\n', nvim('command_output', [[!echo foo]]))
+ eq(':!echo foo\r\n\nfoo' .. win_lf .. '\n', command_output([[!echo foo]]))
end)
it('Vimscript validation error: fails with specific error', function()
- local status, rv = pcall(nvim, "command_output", "bogus commannnd")
- eq(false, status) -- nvim_command_output() failed.
- eq("E492: Not an editor command: bogus commannnd",
- string.match(rv, "E%d*:.*"))
- eq('', eval('v:errmsg')) -- v:errmsg was not updated.
+ local status, rv = pcall(command_output, 'bogus commannnd')
+ eq(false, status) -- nvim_command_output() failed.
+ eq('E492: Not an editor command: bogus commannnd', string.match(rv, 'E%d*:.*'))
+ eq('', eval('v:errmsg')) -- v:errmsg was not updated.
-- Verify NO hit-enter prompt.
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
it('Vimscript execution error: fails with specific error', function()
- local status, rv = pcall(nvim, "command_output", "buffer 42")
- eq(false, status) -- nvim_command_output() failed.
- eq("E86: Buffer 42 does not exist", string.match(rv, "E%d*:.*"))
- eq('', eval('v:errmsg')) -- v:errmsg was not updated.
+ local status, rv = pcall(command_output, 'buffer 42')
+ eq(false, status) -- nvim_command_output() failed.
+ eq('E86: Buffer 42 does not exist', string.match(rv, 'E%d*:.*'))
+ eq('', eval('v:errmsg')) -- v:errmsg was not updated.
-- Verify NO hit-enter prompt.
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
it('does not cause heap buffer overflow with large output', function()
- eq(eval('string(range(1000000))'),
- nvim('command_output', 'echo range(1000000)'))
+ eq(eval('string(range(1000000))'), command_output('echo range(1000000)'))
end)
end)
describe('nvim_eval', function()
it('works', function()
- nvim('command', 'let g:v1 = "a"')
- nvim('command', 'let g:v2 = [1, 2, {"v3": 3}]')
- eq({v1 = 'a', v2 = { 1, 2, { v3 = 3 } } }, nvim('eval', 'g:'))
+ command('let g:v1 = "a"')
+ command('let g:v2 = [1, 2, {"v3": 3}]')
+ eq({ v1 = 'a', v2 = { 1, 2, { v3 = 3 } } }, api.nvim_eval('g:'))
end)
it('handles NULL-initialized strings correctly', function()
- eq(1, nvim('eval',"matcharg(1) == ['', '']"))
- eq({'', ''}, nvim('eval','matcharg(1)'))
+ eq(1, api.nvim_eval("matcharg(1) == ['', '']"))
+ eq({ '', '' }, api.nvim_eval('matcharg(1)'))
end)
it('works under deprecated name', function()
- eq(2, request("vim_eval", "1+1"))
+ eq(2, request('vim_eval', '1+1'))
end)
- it("Vimscript error: returns error details, does NOT update v:errmsg", function()
- eq('Vim:E121: Undefined variable: bogus',
- pcall_err(request, 'nvim_eval', 'bogus expression'))
- eq('', eval('v:errmsg')) -- v:errmsg was not updated.
+ it('Vimscript error: returns error details, does NOT update v:errmsg', function()
+ eq('Vim:E121: Undefined variable: bogus', pcall_err(request, 'nvim_eval', 'bogus expression'))
+ eq('', eval('v:errmsg')) -- v:errmsg was not updated.
end)
end)
describe('nvim_call_function', function()
it('works', function()
- nvim('call_function', 'setqflist', { { { filename = 'something', lnum = 17 } }, 'r' })
- eq(17, nvim('call_function', 'getqflist', {})[1].lnum)
- eq(17, nvim('call_function', 'eval', {17}))
- eq('foo', nvim('call_function', 'simplify', {'this/./is//redundant/../../../foo'}))
- end)
-
- it("Vimscript validation error: returns specific error, does NOT update v:errmsg", function()
- eq('Vim:E117: Unknown function: bogus function',
- pcall_err(request, 'nvim_call_function', 'bogus function', {'arg1'}))
- eq('Vim:E119: Not enough arguments for function: atan',
- pcall_err(request, 'nvim_call_function', 'atan', {}))
+ api.nvim_call_function('setqflist', { { { filename = 'something', lnum = 17 } }, 'r' })
+ eq(17, api.nvim_call_function('getqflist', {})[1].lnum)
+ eq(17, api.nvim_call_function('eval', { 17 }))
+ eq('foo', api.nvim_call_function('simplify', { 'this/./is//redundant/../../../foo' }))
+ end)
+
+ it('Vimscript validation error: returns specific error, does NOT update v:errmsg', function()
+ eq(
+ 'Vim:E117: Unknown function: bogus function',
+ pcall_err(request, 'nvim_call_function', 'bogus function', { 'arg1' })
+ )
+ eq(
+ 'Vim:E119: Not enough arguments for function: atan',
+ pcall_err(request, 'nvim_call_function', 'atan', {})
+ )
eq('', eval('v:exception'))
- eq('', eval('v:errmsg')) -- v:errmsg was not updated.
- end)
-
- it("Vimscript error: returns error details, does NOT update v:errmsg", function()
- eq('Vim:E808: Number or Float required',
- pcall_err(request, 'nvim_call_function', 'atan', {'foo'}))
- eq('Vim:Invalid channel stream "xxx"',
- pcall_err(request, 'nvim_call_function', 'chanclose', {999, 'xxx'}))
- eq('Vim:E900: Invalid channel id',
- pcall_err(request, 'nvim_call_function', 'chansend', {999, 'foo'}))
+ eq('', eval('v:errmsg')) -- v:errmsg was not updated.
+ end)
+
+ it('Vimscript error: returns error details, does NOT update v:errmsg', function()
+ eq(
+ 'Vim:E808: Number or Float required',
+ pcall_err(request, 'nvim_call_function', 'atan', { 'foo' })
+ )
+ eq(
+ 'Vim:Invalid channel stream "xxx"',
+ pcall_err(request, 'nvim_call_function', 'chanclose', { 999, 'xxx' })
+ )
+ eq(
+ 'Vim:E900: Invalid channel id',
+ pcall_err(request, 'nvim_call_function', 'chansend', { 999, 'foo' })
+ )
eq('', eval('v:exception'))
- eq('', eval('v:errmsg')) -- v:errmsg was not updated.
+ eq('', eval('v:errmsg')) -- v:errmsg was not updated.
end)
- it("Vimscript exception: returns exception details, does NOT update v:errmsg", function()
+ it('Vimscript exception: returns exception details, does NOT update v:errmsg', function()
source([[
function! Foo() abort
throw 'wtf'
@@ -504,10 +607,11 @@ describe('API', function()
]])
eq('function Foo, line 1: wtf', pcall_err(request, 'nvim_call_function', 'Foo', {}))
eq('', eval('v:exception'))
- eq('', eval('v:errmsg')) -- v:errmsg was not updated.
+ eq('', eval('v:errmsg')) -- v:errmsg was not updated.
end)
it('validation', function()
+ -- stylua: ignore
local too_many_args = { 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x', 'x' }
source([[
function! Foo(...) abort
@@ -515,8 +619,10 @@ describe('API', function()
endfunction
]])
-- E740
- eq('Function called with too many arguments',
- pcall_err(request, 'nvim_call_function', 'Foo', too_many_args))
+ eq(
+ 'Function called with too many arguments',
+ pcall_err(request, 'nvim_call_function', 'Foo', too_many_args)
+ )
end)
end)
@@ -535,40 +641,55 @@ describe('API', function()
]])
-- :help Dictionary-function
- eq('Hello, World!', nvim('call_dict_function', 'g:test_dict_fn', 'F', {'World'}))
+ eq('Hello, World!', api.nvim_call_dict_function('g:test_dict_fn', 'F', { 'World' }))
-- Funcref is sent as NIL over RPC.
- eq({ greeting = 'Hello', F = NIL }, nvim('get_var', 'test_dict_fn'))
+ eq({ greeting = 'Hello', F = NIL }, api.nvim_get_var('test_dict_fn'))
-- :help numbered-function
- eq('Hi, Moon ...', nvim('call_dict_function', 'g:test_dict_fn2', 'F2', {'Moon'}))
+ eq('Hi, Moon ...', api.nvim_call_dict_function('g:test_dict_fn2', 'F2', { 'Moon' }))
-- Funcref is sent as NIL over RPC.
- eq({ greeting = 'Hi', F2 = NIL }, nvim('get_var', 'test_dict_fn2'))
+ eq({ greeting = 'Hi', F2 = NIL }, api.nvim_get_var('test_dict_fn2'))
-- Function specified via RPC dict.
source('function! G() dict\n return "@".(self.result)."@"\nendfunction')
- eq('@it works@', nvim('call_dict_function', { result = 'it works', G = 'G'}, 'G', {}))
+ eq('@it works@', api.nvim_call_dict_function({ result = 'it works', G = 'G' }, 'G', {}))
end)
it('validation', function()
command('let g:d={"baz":"zub","meep":[]}')
- eq('Not found: bogus',
- pcall_err(request, 'nvim_call_dict_function', 'g:d', 'bogus', {1,2}))
- eq('Not a function: baz',
- pcall_err(request, 'nvim_call_dict_function', 'g:d', 'baz', {1,2}))
- eq('Not a function: meep',
- pcall_err(request, 'nvim_call_dict_function', 'g:d', 'meep', {1,2}))
- eq('Vim:E117: Unknown function: f',
- pcall_err(request, 'nvim_call_dict_function', { f = '' }, 'f', {1,2}))
- eq('Not a function: f',
- pcall_err(request, 'nvim_call_dict_function', "{ 'f': '' }", 'f', {1,2}))
- eq('dict argument type must be String or Dictionary',
- pcall_err(request, 'nvim_call_dict_function', 42, 'f', {1,2}))
- eq('Failed to evaluate dict expression',
- pcall_err(request, 'nvim_call_dict_function', 'foo', 'f', {1,2}))
- eq('dict not found',
- pcall_err(request, 'nvim_call_dict_function', '42', 'f', {1,2}))
- eq('Invalid (empty) function name',
- pcall_err(request, 'nvim_call_dict_function', "{ 'f': '' }", '', {1,2}))
+ eq(
+ 'Not found: bogus',
+ pcall_err(request, 'nvim_call_dict_function', 'g:d', 'bogus', { 1, 2 })
+ )
+ eq(
+ 'Not a function: baz',
+ pcall_err(request, 'nvim_call_dict_function', 'g:d', 'baz', { 1, 2 })
+ )
+ eq(
+ 'Not a function: meep',
+ pcall_err(request, 'nvim_call_dict_function', 'g:d', 'meep', { 1, 2 })
+ )
+ eq(
+ 'Vim:E117: Unknown function: f',
+ pcall_err(request, 'nvim_call_dict_function', { f = '' }, 'f', { 1, 2 })
+ )
+ eq(
+ 'Not a function: f',
+ pcall_err(request, 'nvim_call_dict_function', "{ 'f': '' }", 'f', { 1, 2 })
+ )
+ eq(
+ 'dict argument type must be String or Dictionary',
+ pcall_err(request, 'nvim_call_dict_function', 42, 'f', { 1, 2 })
+ )
+ eq(
+ 'Failed to evaluate dict expression',
+ pcall_err(request, 'nvim_call_dict_function', 'foo', 'f', { 1, 2 })
+ )
+ eq('dict not found', pcall_err(request, 'nvim_call_dict_function', '42', 'f', { 1, 2 }))
+ eq(
+ 'Invalid (empty) function name',
+ pcall_err(request, 'nvim_call_dict_function', "{ 'f': '' }", '', { 1, 2 })
+ )
end)
end)
@@ -576,85 +697,95 @@ describe('API', function()
local start_dir
before_each(function()
- funcs.mkdir("Xtestdir")
- start_dir = funcs.getcwd()
+ fn.mkdir('Xtestdir')
+ start_dir = fn.getcwd()
end)
after_each(function()
- helpers.rmdir("Xtestdir")
+ helpers.rmdir('Xtestdir')
end)
it('works', function()
- meths.set_current_dir("Xtestdir")
- eq(funcs.getcwd(), start_dir .. helpers.get_pathsep() .. "Xtestdir")
+ api.nvim_set_current_dir('Xtestdir')
+ eq(fn.getcwd(), start_dir .. helpers.get_pathsep() .. 'Xtestdir')
end)
it('sets previous directory', function()
- meths.set_current_dir("Xtestdir")
+ api.nvim_set_current_dir('Xtestdir')
command('cd -')
- eq(funcs.getcwd(), start_dir)
+ eq(fn.getcwd(), start_dir)
end)
end)
describe('nvim_exec_lua', function()
it('works', function()
- meths.exec_lua('vim.api.nvim_set_var("test", 3)', {})
- eq(3, meths.get_var('test'))
+ api.nvim_exec_lua('vim.api.nvim_set_var("test", 3)', {})
+ eq(3, api.nvim_get_var('test'))
- eq(17, meths.exec_lua('a, b = ...\nreturn a + b', {10,7}))
+ eq(17, api.nvim_exec_lua('a, b = ...\nreturn a + b', { 10, 7 }))
- eq(NIL, meths.exec_lua('function xx(a,b)\nreturn a..b\nend',{}))
- eq("xy", meths.exec_lua('return xx(...)', {'x','y'}))
+ eq(NIL, api.nvim_exec_lua('function xx(a,b)\nreturn a..b\nend', {}))
+ eq('xy', api.nvim_exec_lua('return xx(...)', { 'x', 'y' }))
-- Deprecated name: nvim_execute_lua.
- eq("xy", meths.execute_lua('return xx(...)', {'x','y'}))
+ eq('xy', api.nvim_execute_lua('return xx(...)', { 'x', 'y' }))
end)
it('reports errors', function()
- eq([[Error loading lua: [string "<nvim>"]:0: '=' expected near '+']],
- pcall_err(meths.exec_lua, 'a+*b', {}))
+ eq(
+ [[Error loading lua: [string "<nvim>"]:0: '=' expected near '+']],
+ pcall_err(api.nvim_exec_lua, 'a+*b', {})
+ )
- eq([[Error loading lua: [string "<nvim>"]:0: unexpected symbol near '1']],
- pcall_err(meths.exec_lua, '1+2', {}))
+ eq(
+ [[Error loading lua: [string "<nvim>"]:0: unexpected symbol near '1']],
+ pcall_err(api.nvim_exec_lua, '1+2', {})
+ )
- eq([[Error loading lua: [string "<nvim>"]:0: unexpected symbol]],
- pcall_err(meths.exec_lua, 'aa=bb\0', {}))
+ eq(
+ [[Error loading lua: [string "<nvim>"]:0: unexpected symbol]],
+ pcall_err(api.nvim_exec_lua, 'aa=bb\0', {})
+ )
- eq([[attempt to call global 'bork' (a nil value)]],
- pcall_err(meths.exec_lua, 'bork()', {}))
+ eq(
+ [[attempt to call global 'bork' (a nil value)]],
+ pcall_err(api.nvim_exec_lua, 'bork()', {})
+ )
- eq('did\nthe\nfail',
- pcall_err(meths.exec_lua, 'error("did\\nthe\\nfail")', {}))
+ eq('did\nthe\nfail', pcall_err(api.nvim_exec_lua, 'error("did\\nthe\\nfail")', {}))
end)
it('uses native float values', function()
- eq(2.5, meths.exec_lua("return select(1, ...)", {2.5}))
- eq("2.5", meths.exec_lua("return vim.inspect(...)", {2.5}))
+ eq(2.5, api.nvim_exec_lua('return select(1, ...)', { 2.5 }))
+ eq('2.5', api.nvim_exec_lua('return vim.inspect(...)', { 2.5 }))
-- "special" float values are still accepted as return values.
- eq(2.5, meths.exec_lua("return vim.api.nvim_eval('2.5')", {}))
- eq("{\n [false] = 2.5,\n [true] = 3\n}", meths.exec_lua("return vim.inspect(vim.api.nvim_eval('2.5'))", {}))
+ eq(2.5, api.nvim_exec_lua("return vim.api.nvim_eval('2.5')", {}))
+ eq(
+ '{\n [false] = 2.5,\n [true] = 3\n}',
+ api.nvim_exec_lua("return vim.inspect(vim.api.nvim_eval('2.5'))", {})
+ )
end)
end)
describe('nvim_notify', function()
it('can notify a info message', function()
- nvim("notify", "hello world", 2, {})
+ api.nvim_notify('hello world', 2, {})
end)
it('can be overridden', function()
- command("lua vim.notify = function(...) return 42 end")
- eq(42, meths.exec_lua("return vim.notify('Hello world')", {}))
- nvim("notify", "hello world", 4, {})
+ command('lua vim.notify = function(...) return 42 end')
+ eq(42, api.nvim_exec_lua("return vim.notify('Hello world')", {}))
+ api.nvim_notify('hello world', 4, {})
end)
end)
describe('nvim_input', function()
- it("Vimscript error: does NOT fail, updates v:errmsg", function()
- local status, _ = pcall(nvim, "input", ":call bogus_fn()<CR>")
- local v_errnum = string.match(nvim("eval", "v:errmsg"), "E%d*:")
- eq(true, status) -- nvim_input() did not fail.
- eq("E117:", v_errnum) -- v:errmsg was updated.
+ it('Vimscript error: does NOT fail, updates v:errmsg', function()
+ local status, _ = pcall(api.nvim_input, ':call bogus_fn()<CR>')
+ local v_errnum = string.match(api.nvim_eval('v:errmsg'), 'E%d*:')
+ eq(true, status) -- nvim_input() did not fail.
+ eq('E117:', v_errnum) -- v:errmsg was updated.
end)
it('does not crash even if trans_special result is largest #11788, #12287', function()
@@ -665,30 +796,28 @@ describe('API', function()
describe('nvim_paste', function()
it('validation', function()
- eq("Invalid 'phase': -2",
- pcall_err(request, 'nvim_paste', 'foo', true, -2))
- eq("Invalid 'phase': 4",
- pcall_err(request, 'nvim_paste', 'foo', true, 4))
+ eq("Invalid 'phase': -2", pcall_err(request, 'nvim_paste', 'foo', true, -2))
+ eq("Invalid 'phase': 4", pcall_err(request, 'nvim_paste', 'foo', true, 4))
end)
local function run_streamed_paste_tests()
it('stream: multiple chunks form one undo-block', function()
- nvim('paste', '1/chunk 1 (start)\n', true, 1)
- nvim('paste', '1/chunk 2 (end)\n', true, 3)
+ api.nvim_paste('1/chunk 1 (start)\n', true, 1)
+ api.nvim_paste('1/chunk 2 (end)\n', true, 3)
local expected1 = [[
1/chunk 1 (start)
1/chunk 2 (end)
]]
expect(expected1)
- nvim('paste', '2/chunk 1 (start)\n', true, 1)
- nvim('paste', '2/chunk 2\n', true, 2)
+ api.nvim_paste('2/chunk 1 (start)\n', true, 1)
+ api.nvim_paste('2/chunk 2\n', true, 2)
expect([[
1/chunk 1 (start)
1/chunk 2 (end)
2/chunk 1 (start)
2/chunk 2
]])
- nvim('paste', '2/chunk 3\n', true, 2)
- nvim('paste', '2/chunk 4 (end)\n', true, 3)
+ api.nvim_paste('2/chunk 3\n', true, 2)
+ api.nvim_paste('2/chunk 4 (end)\n', true, 3)
expect([[
1/chunk 1 (start)
1/chunk 2 (end)
@@ -697,17 +826,17 @@ describe('API', function()
2/chunk 3
2/chunk 4 (end)
]])
- feed('u') -- Undo.
+ feed('u') -- Undo.
expect(expected1)
end)
it('stream: Insert mode', function()
-- If nvim_paste() calls :undojoin without making any changes, this makes it an error.
feed('afoo<Esc>u')
feed('i')
- nvim('paste', 'aaaaaa', false, 1)
- nvim('paste', 'bbbbbb', false, 2)
- nvim('paste', 'cccccc', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa', false, 1)
+ api.nvim_paste('bbbbbb', false, 2)
+ api.nvim_paste('cccccc', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect('aaaaaabbbbbbccccccdddddd')
feed('<Esc>u')
expect('')
@@ -723,17 +852,17 @@ describe('API', function()
expect('')
end)
it('pasting one line', function()
- nvim('paste', 'aaaaaa', false, 1)
- nvim('paste', 'bbbbbb', false, 2)
- nvim('paste', 'cccccc', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa', false, 1)
+ api.nvim_paste('bbbbbb', false, 2)
+ api.nvim_paste('cccccc', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect('aaaaaabbbbbbccccccdddddd')
end)
it('pasting multiple lines', function()
- nvim('paste', 'aaaaaa\n', false, 1)
- nvim('paste', 'bbbbbb\n', false, 2)
- nvim('paste', 'cccccc\n', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa\n', false, 1)
+ api.nvim_paste('bbbbbb\n', false, 2)
+ api.nvim_paste('cccccc\n', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect([[
aaaaaa
bbbbbb
@@ -753,17 +882,17 @@ describe('API', function()
expect('||')
end)
it('pasting one line', function()
- nvim('paste', 'aaaaaa', false, 1)
- nvim('paste', 'bbbbbb', false, 2)
- nvim('paste', 'cccccc', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa', false, 1)
+ api.nvim_paste('bbbbbb', false, 2)
+ api.nvim_paste('cccccc', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect('|aaaaaabbbbbbccccccdddddd|')
end)
it('pasting multiple lines', function()
- nvim('paste', 'aaaaaa\n', false, 1)
- nvim('paste', 'bbbbbb\n', false, 2)
- nvim('paste', 'cccccc\n', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa\n', false, 1)
+ api.nvim_paste('bbbbbb\n', false, 2)
+ api.nvim_paste('cccccc\n', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect([[
|aaaaaa
bbbbbb
@@ -783,17 +912,17 @@ describe('API', function()
expect('||')
end)
it('pasting one line', function()
- nvim('paste', 'aaaaaa', false, 1)
- nvim('paste', 'bbbbbb', false, 2)
- nvim('paste', 'cccccc', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa', false, 1)
+ api.nvim_paste('bbbbbb', false, 2)
+ api.nvim_paste('cccccc', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect('||aaaaaabbbbbbccccccdddddd')
end)
it('pasting multiple lines', function()
- nvim('paste', 'aaaaaa\n', false, 1)
- nvim('paste', 'bbbbbb\n', false, 2)
- nvim('paste', 'cccccc\n', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa\n', false, 1)
+ api.nvim_paste('bbbbbb\n', false, 2)
+ api.nvim_paste('cccccc\n', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect([[
||aaaaaa
bbbbbb
@@ -817,24 +946,24 @@ describe('API', function()
xxx|]])
end)
it('with non-empty chunks', function()
- nvim('paste', 'aaaaaa', false, 1)
- nvim('paste', 'bbbbbb', false, 2)
- nvim('paste', 'cccccc', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa', false, 1)
+ api.nvim_paste('bbbbbb', false, 2)
+ api.nvim_paste('cccccc', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect('|aaaaaabbbbbbccccccdddddd|')
end)
it('with empty first chunk', function()
- nvim('paste', '', false, 1)
- nvim('paste', 'bbbbbb', false, 2)
- nvim('paste', 'cccccc', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('', false, 1)
+ api.nvim_paste('bbbbbb', false, 2)
+ api.nvim_paste('cccccc', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect('|bbbbbbccccccdddddd|')
end)
it('with all chunks empty', function()
- nvim('paste', '', false, 1)
- nvim('paste', '', false, 2)
- nvim('paste', '', false, 2)
- nvim('paste', '', false, 3)
+ api.nvim_paste('', false, 1)
+ api.nvim_paste('', false, 2)
+ api.nvim_paste('', false, 2)
+ api.nvim_paste('', false, 3)
expect('||')
end)
end)
@@ -852,17 +981,17 @@ describe('API', function()
xxx]])
end)
it('with non-empty chunks', function()
- nvim('paste', 'aaaaaa', false, 1)
- nvim('paste', 'bbbbbb', false, 2)
- nvim('paste', 'cccccc', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa', false, 1)
+ api.nvim_paste('bbbbbb', false, 2)
+ api.nvim_paste('cccccc', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect('||aaaaaabbbbbbccccccdddddd')
end)
it('with empty first chunk', function()
- nvim('paste', '', false, 1)
- nvim('paste', 'bbbbbb', false, 2)
- nvim('paste', 'cccccc', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('', false, 1)
+ api.nvim_paste('bbbbbb', false, 2)
+ api.nvim_paste('cccccc', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect('||bbbbbbccccccdddddd')
end)
end)
@@ -880,17 +1009,17 @@ describe('API', function()
xxx]])
end)
it('with non-empty chunks', function()
- nvim('paste', 'aaaaaa', false, 1)
- nvim('paste', 'bbbbbb', false, 2)
- nvim('paste', 'cccccc', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa', false, 1)
+ api.nvim_paste('bbbbbb', false, 2)
+ api.nvim_paste('cccccc', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect('||aaaaaabbbbbbccccccdddddd')
end)
it('with empty first chunk', function()
- nvim('paste', '', false, 1)
- nvim('paste', 'bbbbbb', false, 2)
- nvim('paste', 'cccccc', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('', false, 1)
+ api.nvim_paste('bbbbbb', false, 2)
+ api.nvim_paste('cccccc', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect('||bbbbbbccccccdddddd')
end)
end)
@@ -913,10 +1042,10 @@ describe('API', function()
feed('ggV')
end)
it('pasting text without final new line', function()
- nvim('paste', 'aaaaaa\n', false, 1)
- nvim('paste', 'bbbbbb\n', false, 2)
- nvim('paste', 'cccccc\n', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa\n', false, 1)
+ api.nvim_paste('bbbbbb\n', false, 2)
+ api.nvim_paste('cccccc\n', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect([[
aaaaaa
bbbbbb
@@ -925,10 +1054,10 @@ describe('API', function()
123456789]])
end)
it('pasting text with final new line', function()
- nvim('paste', 'aaaaaa\n', false, 1)
- nvim('paste', 'bbbbbb\n', false, 2)
- nvim('paste', 'cccccc\n', false, 2)
- nvim('paste', 'dddddd\n', false, 3)
+ api.nvim_paste('aaaaaa\n', false, 1)
+ api.nvim_paste('bbbbbb\n', false, 2)
+ api.nvim_paste('cccccc\n', false, 2)
+ api.nvim_paste('dddddd\n', false, 3)
expect([[
aaaaaa
bbbbbb
@@ -943,10 +1072,10 @@ describe('API', function()
feed('2ggV')
end)
it('pasting text without final new line', function()
- nvim('paste', 'aaaaaa\n', false, 1)
- nvim('paste', 'bbbbbb\n', false, 2)
- nvim('paste', 'cccccc\n', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa\n', false, 1)
+ api.nvim_paste('bbbbbb\n', false, 2)
+ api.nvim_paste('cccccc\n', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect([[
123456789
aaaaaa
@@ -955,10 +1084,10 @@ describe('API', function()
dddddd123456789]])
end)
it('pasting text with final new line', function()
- nvim('paste', 'aaaaaa\n', false, 1)
- nvim('paste', 'bbbbbb\n', false, 2)
- nvim('paste', 'cccccc\n', false, 2)
- nvim('paste', 'dddddd\n', false, 3)
+ api.nvim_paste('aaaaaa\n', false, 1)
+ api.nvim_paste('bbbbbb\n', false, 2)
+ api.nvim_paste('cccccc\n', false, 2)
+ api.nvim_paste('dddddd\n', false, 3)
expect([[
123456789
aaaaaa
@@ -973,10 +1102,10 @@ describe('API', function()
feed('3ggV')
end)
it('pasting text without final new line', function()
- nvim('paste', 'aaaaaa\n', false, 1)
- nvim('paste', 'bbbbbb\n', false, 2)
- nvim('paste', 'cccccc\n', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa\n', false, 1)
+ api.nvim_paste('bbbbbb\n', false, 2)
+ api.nvim_paste('cccccc\n', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect([[
123456789
987654321
@@ -986,10 +1115,10 @@ describe('API', function()
dddddd]])
end)
it('pasting text with final new line', function()
- nvim('paste', 'aaaaaa\n', false, 1)
- nvim('paste', 'bbbbbb\n', false, 2)
- nvim('paste', 'cccccc\n', false, 2)
- nvim('paste', 'dddddd\n', false, 3)
+ api.nvim_paste('aaaaaa\n', false, 1)
+ api.nvim_paste('bbbbbb\n', false, 2)
+ api.nvim_paste('cccccc\n', false, 2)
+ api.nvim_paste('dddddd\n', false, 3)
expect([[
123456789
987654321
@@ -1005,10 +1134,10 @@ describe('API', function()
feed('ggVG')
end)
it('pasting text without final new line', function()
- nvim('paste', 'aaaaaa\n', false, 1)
- nvim('paste', 'bbbbbb\n', false, 2)
- nvim('paste', 'cccccc\n', false, 2)
- nvim('paste', 'dddddd', false, 3)
+ api.nvim_paste('aaaaaa\n', false, 1)
+ api.nvim_paste('bbbbbb\n', false, 2)
+ api.nvim_paste('cccccc\n', false, 2)
+ api.nvim_paste('dddddd', false, 3)
expect([[
aaaaaa
bbbbbb
@@ -1016,10 +1145,10 @@ describe('API', function()
dddddd]])
end)
it('pasting text with final new line', function()
- nvim('paste', 'aaaaaa\n', false, 1)
- nvim('paste', 'bbbbbb\n', false, 2)
- nvim('paste', 'cccccc\n', false, 2)
- nvim('paste', 'dddddd\n', false, 3)
+ api.nvim_paste('aaaaaa\n', false, 1)
+ api.nvim_paste('bbbbbb\n', false, 2)
+ api.nvim_paste('cccccc\n', false, 2)
+ api.nvim_paste('dddddd\n', false, 3)
expect([[
aaaaaa
bbbbbb
@@ -1041,71 +1170,71 @@ describe('API', function()
end)
it('non-streaming', function()
-- With final "\n".
- nvim('paste', 'line 1\nline 2\nline 3\n', true, -1)
+ api.nvim_paste('line 1\nline 2\nline 3\n', true, -1)
expect([[
line 1
line 2
line 3
]])
- eq({0,4,1,0}, funcs.getpos('.')) -- Cursor follows the paste.
- eq(false, nvim('get_option_value', 'paste', {}))
+ eq({ 0, 4, 1, 0 }, fn.getpos('.')) -- Cursor follows the paste.
+ eq(false, api.nvim_get_option_value('paste', {}))
command('%delete _')
-- Without final "\n".
- nvim('paste', 'line 1\nline 2\nline 3', true, -1)
+ api.nvim_paste('line 1\nline 2\nline 3', true, -1)
expect([[
line 1
line 2
line 3]])
- eq({0,3,6,0}, funcs.getpos('.'))
+ eq({ 0, 3, 6, 0 }, fn.getpos('.'))
command('%delete _')
-- CRLF #10872
- nvim('paste', 'line 1\r\nline 2\r\nline 3\r\n', true, -1)
+ api.nvim_paste('line 1\r\nline 2\r\nline 3\r\n', true, -1)
expect([[
line 1
line 2
line 3
]])
- eq({0,4,1,0}, funcs.getpos('.'))
+ eq({ 0, 4, 1, 0 }, fn.getpos('.'))
command('%delete _')
-- CRLF without final "\n".
- nvim('paste', 'line 1\r\nline 2\r\nline 3\r', true, -1)
+ api.nvim_paste('line 1\r\nline 2\r\nline 3\r', true, -1)
expect([[
line 1
line 2
line 3
]])
- eq({0,4,1,0}, funcs.getpos('.'))
+ eq({ 0, 4, 1, 0 }, fn.getpos('.'))
command('%delete _')
-- CRLF without final "\r\n".
- nvim('paste', 'line 1\r\nline 2\r\nline 3', true, -1)
+ api.nvim_paste('line 1\r\nline 2\r\nline 3', true, -1)
expect([[
line 1
line 2
line 3]])
- eq({0,3,6,0}, funcs.getpos('.'))
+ eq({ 0, 3, 6, 0 }, fn.getpos('.'))
command('%delete _')
-- Various other junk.
- nvim('paste', 'line 1\r\n\r\rline 2\nline 3\rline 4\r', true, -1)
+ api.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_value', 'paste', {}))
+ eq({ 0, 7, 1, 0 }, fn.getpos('.'))
+ eq(false, api.nvim_get_option_value('paste', {}))
end)
it('Replace-mode', function()
-- Within single line
- nvim('put', {'aabbccdd', 'eeffgghh', 'iijjkkll'}, "c", true, false)
+ api.nvim_put({ 'aabbccdd', 'eeffgghh', 'iijjkkll' }, 'c', true, false)
command('normal l')
command('startreplace')
- nvim('paste', '123456', true, -1)
+ api.nvim_paste('123456', true, -1)
expect([[
a123456d
eeffgghh
iijjkkll]])
command('%delete _')
-- Across lines
- nvim('put', {'aabbccdd', 'eeffgghh', 'iijjkkll'}, "c", true, false)
+ api.nvim_put({ 'aabbccdd', 'eeffgghh', 'iijjkkll' }, 'c', true, false)
command('normal l')
command('startreplace')
- nvim('paste', '123\n456', true, -1)
+ api.nvim_paste('123\n456', true, -1)
expect([[
a123
456d
@@ -1114,34 +1243,33 @@ describe('API', function()
end)
it('when searching in Visual mode', function()
feed('v/')
- nvim('paste', 'aabbccdd', true, -1)
- eq('aabbccdd', funcs.getcmdline())
+ api.nvim_paste('aabbccdd', true, -1)
+ eq('aabbccdd', fn.getcmdline())
expect('')
end)
it('mappings are disabled in Cmdline mode', function()
command('cnoremap a b')
feed(':')
- nvim('paste', 'a', true, -1)
- eq('a', funcs.getcmdline())
+ api.nvim_paste('a', true, -1)
+ eq('a', fn.getcmdline())
end)
it('pasted text is saved in cmdline history when <CR> comes from mapping #20957', function()
command('cnoremap <CR> <CR>')
feed(':')
- nvim('paste', 'echo', true, -1)
- eq('', funcs.histget(':'))
+ api.nvim_paste('echo', true, -1)
+ eq('', fn.histget(':'))
feed('<CR>')
- eq('echo', funcs.histget(':'))
+ eq('echo', fn.histget(':'))
end)
it('pasting with empty last chunk in Cmdline mode', function()
local screen = Screen.new(20, 4)
screen:attach()
feed(':')
- nvim('paste', 'Foo', true, 1)
- nvim('paste', '', true, 3)
+ api.nvim_paste('Foo', true, 1)
+ api.nvim_paste('', true, 3)
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
:Foo^ |
]])
end)
@@ -1149,112 +1277,113 @@ describe('API', function()
local screen = Screen.new(20, 4)
screen:attach()
feed(':')
- nvim('paste', 'normal! \023\022\006\027', true, -1)
+ api.nvim_paste('normal! \023\022\006\027', true, -1)
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
:normal! ^W^V^F^[^ |
]])
end)
it('crlf=false does not break lines at CR, CRLF', function()
- nvim('paste', 'line 1\r\n\r\rline 2\nline 3\rline 4\r', false, -1)
+ api.nvim_paste('line 1\r\n\r\rline 2\nline 3\rline 4\r', false, -1)
expect('line 1\r\n\r\rline 2\nline 3\rline 4\r')
- eq({0,3,14,0}, funcs.getpos('.'))
+ eq({ 0, 3, 14, 0 }, fn.getpos('.'))
end)
it('vim.paste() failure', function()
- nvim('exec_lua', 'vim.paste = (function(lines, phase) error("fake fail") end)', {})
- eq('fake fail',
- pcall_err(request, 'nvim_paste', 'line 1\nline 2\nline 3', false, 1))
+ api.nvim_exec_lua('vim.paste = (function(lines, phase) error("fake fail") end)', {})
+ eq('fake fail', pcall_err(request, 'nvim_paste', 'line 1\nline 2\nline 3', false, 1))
end)
end)
describe('nvim_put', function()
it('validation', function()
- eq("Invalid 'line': expected String, got Integer",
- pcall_err(request, 'nvim_put', {42}, 'l', false, false))
- eq("Invalid 'type': 'x'",
- pcall_err(request, 'nvim_put', {'foo'}, 'x', false, false))
+ eq(
+ "Invalid 'line': expected String, got Integer",
+ pcall_err(request, 'nvim_put', { 42 }, 'l', false, false)
+ )
+ eq("Invalid 'type': 'x'", pcall_err(request, 'nvim_put', { 'foo' }, 'x', false, false))
end)
it("fails if 'nomodifiable'", function()
command('set nomodifiable')
- eq([[Vim:E21: Cannot make changes, 'modifiable' is off]],
- pcall_err(request, 'nvim_put', {'a','b'}, 'l', true, true))
+ eq(
+ [[Vim:E21: Cannot make changes, 'modifiable' is off]],
+ pcall_err(request, 'nvim_put', { 'a', 'b' }, 'l', true, true)
+ )
end)
it('inserts text', function()
-- linewise
- nvim('put', {'line 1','line 2','line 3'}, 'l', true, true)
+ api.nvim_put({ 'line 1', 'line 2', 'line 3' }, 'l', true, true)
expect([[
line 1
line 2
line 3]])
- eq({0,4,1,0}, funcs.getpos('.'))
+ eq({ 0, 4, 1, 0 }, fn.getpos('.'))
command('%delete _')
-- charwise
- nvim('put', {'line 1','line 2','line 3'}, 'c', true, false)
+ api.nvim_put({ 'line 1', 'line 2', 'line 3' }, 'c', true, false)
expect([[
line 1
line 2
line 3]])
- eq({0,1,1,0}, funcs.getpos('.')) -- follow=false
+ eq({ 0, 1, 1, 0 }, fn.getpos('.')) -- follow=false
-- blockwise
- nvim('put', {'AA','BB'}, 'b', true, true)
+ api.nvim_put({ 'AA', 'BB' }, 'b', true, true)
expect([[
lAAine 1
lBBine 2
line 3]])
- eq({0,2,4,0}, funcs.getpos('.'))
+ eq({ 0, 2, 4, 0 }, fn.getpos('.'))
command('%delete _')
-- Empty lines list.
- nvim('put', {}, 'c', true, true)
- eq({0,1,1,0}, funcs.getpos('.'))
+ api.nvim_put({}, 'c', true, true)
+ eq({ 0, 1, 1, 0 }, fn.getpos('.'))
expect([[]])
-- Single empty line.
- nvim('put', {''}, 'c', true, true)
- eq({0,1,1,0}, funcs.getpos('.'))
+ api.nvim_put({ '' }, 'c', true, true)
+ eq({ 0, 1, 1, 0 }, fn.getpos('.'))
expect([[
]])
- nvim('put', {'AB'}, 'c', true, true)
+ api.nvim_put({ 'AB' }, 'c', true, true)
-- after=false, follow=true
- nvim('put', {'line 1','line 2'}, 'c', false, true)
+ api.nvim_put({ 'line 1', 'line 2' }, 'c', false, true)
expect([[
Aline 1
line 2B]])
- eq({0,2,7,0}, funcs.getpos('.'))
+ eq({ 0, 2, 7, 0 }, fn.getpos('.'))
command('%delete _')
- nvim('put', {'AB'}, 'c', true, true)
+ api.nvim_put({ 'AB' }, 'c', true, true)
-- after=false, follow=false
- nvim('put', {'line 1','line 2'}, 'c', false, false)
+ api.nvim_put({ 'line 1', 'line 2' }, 'c', false, false)
expect([[
Aline 1
line 2B]])
- eq({0,1,2,0}, funcs.getpos('.'))
- eq('', nvim('eval', 'v:errmsg'))
+ eq({ 0, 1, 2, 0 }, fn.getpos('.'))
+ eq('', api.nvim_eval('v:errmsg'))
end)
it('detects charwise/linewise text (empty {type})', function()
-- linewise (final item is empty string)
- nvim('put', {'line 1','line 2','line 3',''}, '', true, true)
+ api.nvim_put({ 'line 1', 'line 2', 'line 3', '' }, '', true, true)
expect([[
line 1
line 2
line 3]])
- eq({0,4,1,0}, funcs.getpos('.'))
+ eq({ 0, 4, 1, 0 }, fn.getpos('.'))
command('%delete _')
-- charwise (final item is non-empty)
- nvim('put', {'line 1','line 2','line 3'}, '', true, true)
+ api.nvim_put({ 'line 1', 'line 2', 'line 3' }, '', true, true)
expect([[
line 1
line 2
line 3]])
- eq({0,3,6,0}, funcs.getpos('.'))
+ eq({ 0, 3, 6, 0 }, fn.getpos('.'))
end)
it('allows block width', function()
-- behave consistently with setreg(); support "\022{NUM}" return by getregtype()
- meths.put({'line 1','line 2','line 3'}, 'l', false, false)
+ api.nvim_put({ 'line 1', 'line 2', 'line 3' }, 'l', false, false)
expect([[
line 1
line 2
@@ -1262,67 +1391,69 @@ describe('API', function()
]])
-- larger width create spaces
- meths.put({'a', 'bc'}, 'b3', false, false)
+ api.nvim_put({ 'a', 'bc' }, 'b3', false, false)
expect([[
a line 1
bc line 2
line 3
]])
-- smaller width is ignored
- meths.put({'xxx', 'yyy'}, '\0221', false, true)
+ api.nvim_put({ 'xxx', 'yyy' }, '\0221', false, true)
expect([[
xxxa line 1
yyybc line 2
line 3
]])
- eq("Invalid 'type': 'bx'",
- pcall_err(meths.put, {'xxx', 'yyy'}, 'bx', false, true))
- eq("Invalid 'type': 'b3x'",
- pcall_err(meths.put, {'xxx', 'yyy'}, 'b3x', false, true))
+ eq("Invalid 'type': 'bx'", pcall_err(api.nvim_put, { 'xxx', 'yyy' }, 'bx', false, true))
+ eq("Invalid 'type': 'b3x'", pcall_err(api.nvim_put, { 'xxx', 'yyy' }, 'b3x', false, true))
end)
end)
describe('nvim_strwidth', function()
it('works', function()
- eq(3, nvim('strwidth', 'abc'))
+ eq(3, api.nvim_strwidth('abc'))
-- 6 + (neovim)
-- 19 * 2 (each japanese character occupies two cells)
- eq(44, nvim('strwidth', 'neovimã®ãƒ‡ã‚¶ã‚¤ãƒ³ã‹ãªã‚Šã¾ã¨ã‚‚ãªã®ã«ãªã£ã¦ã‚‹ã€‚'))
+ eq(44, api.nvim_strwidth('neovimã®ãƒ‡ã‚¶ã‚¤ãƒ³ã‹ãªã‚Šã¾ã¨ã‚‚ãªã®ã«ãªã£ã¦ã‚‹ã€‚'))
end)
it('cannot handle NULs', function()
- eq(0, nvim('strwidth', '\0abc'))
+ eq(0, api.nvim_strwidth('\0abc'))
end)
end)
describe('nvim_get_current_line, nvim_set_current_line', function()
it('works', function()
- eq('', nvim('get_current_line'))
- nvim('set_current_line', 'abc')
- eq('abc', nvim('get_current_line'))
+ eq('', api.nvim_get_current_line())
+ api.nvim_set_current_line('abc')
+ eq('abc', api.nvim_get_current_line())
end)
end)
describe('set/get/del variables', function()
it('validation', function()
- eq('Key not found: bogus', pcall_err(meths.get_var, 'bogus'))
- eq('Key not found: bogus', pcall_err(meths.del_var, 'bogus'))
+ eq('Key not found: bogus', pcall_err(api.nvim_get_var, 'bogus'))
+ eq('Key not found: bogus', pcall_err(api.nvim_del_var, 'bogus'))
end)
it('nvim_get_var, nvim_set_var, nvim_del_var', function()
- nvim('set_var', 'lua', {1, 2, {['3'] = 1}})
- eq({1, 2, {['3'] = 1}}, nvim('get_var', 'lua'))
- eq({1, 2, {['3'] = 1}}, nvim('eval', 'g:lua'))
- eq(1, funcs.exists('g:lua'))
- meths.del_var('lua')
- eq(0, funcs.exists('g:lua'))
- eq("Key not found: lua", pcall_err(meths.del_var, 'lua'))
- meths.set_var('lua', 1)
+ api.nvim_set_var('lua', { 1, 2, { ['3'] = 1 } })
+ eq({ 1, 2, { ['3'] = 1 } }, api.nvim_get_var('lua'))
+ eq({ 1, 2, { ['3'] = 1 } }, api.nvim_eval('g:lua'))
+ eq(1, fn.exists('g:lua'))
+ api.nvim_del_var('lua')
+ eq(0, fn.exists('g:lua'))
+ eq('Key not found: lua', pcall_err(api.nvim_del_var, 'lua'))
+ api.nvim_set_var('lua', 1)
+
+ -- Empty keys are allowed in Vim dicts (and msgpack).
+ api.nvim_set_var('dict_empty_key', { [''] = 'empty key' })
+ eq({ [''] = 'empty key' }, api.nvim_get_var('dict_empty_key'))
-- Set locked g: var.
command('lockvar lua')
- eq('Key is locked: lua', pcall_err(meths.del_var, 'lua'))
- eq('Key is locked: lua', pcall_err(meths.set_var, 'lua', 1))
+ eq('Key is locked: lua', pcall_err(api.nvim_del_var, 'lua'))
+ eq('Key is locked: lua', pcall_err(api.nvim_set_var, 'lua', 1))
exec([[
function Test()
@@ -1332,260 +1463,281 @@ describe('API', function()
let g:Unknown_func = function('Test')
let g:Unknown_script_func = function('s:Test')
]])
- eq(NIL, meths.get_var('Unknown_func'))
- eq(NIL, meths.get_var('Unknown_script_func'))
+ eq(NIL, api.nvim_get_var('Unknown_func'))
+ eq(NIL, api.nvim_get_var('Unknown_script_func'))
-- Check if autoload works properly
local pathsep = helpers.get_pathsep()
local xconfig = 'Xhome' .. pathsep .. 'Xconfig'
local xdata = 'Xhome' .. pathsep .. 'Xdata'
- local autoload_folder = table.concat({xconfig, 'nvim', 'autoload'}, pathsep)
- local autoload_file = table.concat({autoload_folder , 'testload.vim'}, pathsep)
+ local autoload_folder = table.concat({ xconfig, 'nvim', 'autoload' }, pathsep)
+ local autoload_file = table.concat({ autoload_folder, 'testload.vim' }, pathsep)
mkdir_p(autoload_folder)
- write_file(autoload_file , [[let testload#value = 2]])
+ write_file(autoload_file, [[let testload#value = 2]])
- clear{ args_rm={'-u'}, env={ XDG_CONFIG_HOME=xconfig, XDG_DATA_HOME=xdata } }
- eq(2, meths.get_var('testload#value'))
+ clear { args_rm = { '-u' }, env = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata } }
+ eq(2, api.nvim_get_var('testload#value'))
rmdir('Xhome')
end)
it('nvim_get_vvar, nvim_set_vvar', function()
eq('Key is read-only: count', pcall_err(request, 'nvim_set_vvar', 'count', 42))
eq('Dictionary is locked', pcall_err(request, 'nvim_set_vvar', 'nosuchvar', 42))
- meths.set_vvar('errmsg', 'set by API')
- eq('set by API', meths.get_vvar('errmsg'))
- meths.set_vvar('errmsg', 42)
+ api.nvim_set_vvar('errmsg', 'set by API')
+ eq('set by API', api.nvim_get_vvar('errmsg'))
+ api.nvim_set_vvar('errmsg', 42)
eq('42', eval('v:errmsg'))
- meths.set_vvar('oldfiles', { 'one', 'two' })
+ api.nvim_set_vvar('oldfiles', { 'one', 'two' })
eq({ 'one', 'two' }, eval('v:oldfiles'))
- meths.set_vvar('oldfiles', {})
+ api.nvim_set_vvar('oldfiles', {})
eq({}, eval('v:oldfiles'))
- eq('Setting v:oldfiles to value with wrong type', pcall_err(meths.set_vvar, 'oldfiles', 'a'))
+ eq(
+ 'Setting v:oldfiles to value with wrong type',
+ pcall_err(api.nvim_set_vvar, 'oldfiles', 'a')
+ )
eq({}, eval('v:oldfiles'))
feed('i foo foo foo<Esc>0/foo<CR>')
- eq({1, 1}, meths.win_get_cursor(0))
+ eq({ 1, 1 }, api.nvim_win_get_cursor(0))
eq(1, eval('v:searchforward'))
feed('n')
- eq({1, 5}, meths.win_get_cursor(0))
- meths.set_vvar('searchforward', 0)
+ eq({ 1, 5 }, api.nvim_win_get_cursor(0))
+ api.nvim_set_vvar('searchforward', 0)
eq(0, eval('v:searchforward'))
feed('n')
- eq({1, 1}, meths.win_get_cursor(0))
- meths.set_vvar('searchforward', 1)
+ eq({ 1, 1 }, api.nvim_win_get_cursor(0))
+ api.nvim_set_vvar('searchforward', 1)
eq(1, eval('v:searchforward'))
feed('n')
- eq({1, 5}, meths.win_get_cursor(0))
+ eq({ 1, 5 }, api.nvim_win_get_cursor(0))
local screen = Screen.new(60, 3)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {background = Screen.colors.Yellow},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { background = Screen.colors.Yellow },
})
screen:attach()
eq(1, eval('v:hlsearch'))
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:foo} {1:^foo} {1:foo} |
{0:~ }|
|
- ]]}
- meths.set_vvar('hlsearch', 0)
+ ]],
+ }
+ api.nvim_set_vvar('hlsearch', 0)
eq(0, eval('v:hlsearch'))
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
foo ^foo foo |
{0:~ }|
|
- ]]}
- meths.set_vvar('hlsearch', 1)
+ ]],
+ }
+ api.nvim_set_vvar('hlsearch', 1)
eq(1, eval('v:hlsearch'))
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:foo} {1:^foo} {1:foo} |
{0:~ }|
|
- ]]}
+ ]],
+ }
end)
it('vim_set_var returns the old value', function()
- local val1 = {1, 2, {['3'] = 1}}
- local val2 = {4, 7}
+ local val1 = { 1, 2, { ['3'] = 1 } }
+ local val2 = { 4, 7 }
eq(NIL, request('vim_set_var', 'lua', val1))
eq(val1, request('vim_set_var', 'lua', val2))
end)
it('vim_del_var returns the old value', function()
- local val1 = {1, 2, {['3'] = 1}}
- local val2 = {4, 7}
- eq(NIL, request('vim_set_var', 'lua', val1))
+ local val1 = { 1, 2, { ['3'] = 1 } }
+ local val2 = { 4, 7 }
+ eq(NIL, request('vim_set_var', 'lua', val1))
eq(val1, request('vim_set_var', 'lua', val2))
eq(val2, request('vim_del_var', 'lua'))
end)
it('truncates values with NULs in them', function()
- nvim('set_var', 'xxx', 'ab\0cd')
- eq('ab', nvim('get_var', 'xxx'))
+ api.nvim_set_var('xxx', 'ab\0cd')
+ eq('ab', api.nvim_get_var('xxx'))
end)
end)
describe('nvim_get_option_value, nvim_set_option_value', function()
it('works', function()
- ok(nvim('get_option_value', 'equalalways', {}))
- nvim('set_option_value', 'equalalways', false, {})
- ok(not nvim('get_option_value', 'equalalways', {}))
+ ok(api.nvim_get_option_value('equalalways', {}))
+ api.nvim_set_option_value('equalalways', false, {})
+ ok(not api.nvim_get_option_value('equalalways', {}))
end)
it('works to get global value of local options', function()
- eq(false, nvim('get_option_value', 'lisp', {}))
- eq(8, nvim('get_option_value', 'shiftwidth', {}))
+ eq(false, api.nvim_get_option_value('lisp', {}))
+ eq(8, api.nvim_get_option_value('shiftwidth', {}))
end)
it('works to set global value of local options', function()
- 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_value', 'shiftwidth', 20, {scope='global'})
- eq('20', nvim('command_output', 'setglobal shiftwidth?'):match('%d+'))
- eq('8', nvim('command_output', 'setlocal shiftwidth?'):match('%d+'))
+ api.nvim_set_option_value('lisp', true, { scope = 'global' })
+ eq(true, api.nvim_get_option_value('lisp', { scope = 'global' }))
+ eq(false, api.nvim_get_option_value('lisp', {}))
+ eq(nil, command_output('setglobal lisp?'):match('nolisp'))
+ eq('nolisp', command_output('setlocal lisp?'):match('nolisp'))
+ api.nvim_set_option_value('shiftwidth', 20, { scope = 'global' })
+ eq('20', command_output('setglobal shiftwidth?'):match('%d+'))
+ eq('8', command_output('setlocal shiftwidth?'):match('%d+'))
end)
it('updates where the option was last set from', function()
- nvim('set_option_value', 'equalalways', false, {})
- local status, rv = pcall(nvim, 'command_output',
- 'verbose set equalalways?')
+ api.nvim_set_option_value('equalalways', false, {})
+ local status, rv = pcall(command_output, 'verbose set equalalways?')
eq(true, status)
- ok(nil ~= string.find(rv, 'noequalalways\n'..
- '\tLast set from API client %(channel id %d+%)'))
+ ok(
+ nil ~= string.find(rv, 'noequalalways\n' .. '\tLast set from API client %(channel id %d+%)')
+ )
- nvim('exec_lua', 'vim.api.nvim_set_option_value("equalalways", true, {})', {})
- status, rv = pcall(nvim, 'command_output',
- 'verbose set equalalways?')
+ api.nvim_exec_lua('vim.api.nvim_set_option_value("equalalways", true, {})', {})
+ status, rv = pcall(command_output, 'verbose set equalalways?')
eq(true, status)
eq(' equalalways\n\tLast set from Lua', rv)
end)
it('updates whether the option has ever been set #25025', function()
- eq(false, nvim('get_option_info2', 'autochdir', {}).was_set)
- nvim('set_option_value', 'autochdir', true, {})
- eq(true, nvim('get_option_info2', 'autochdir', {}).was_set)
+ eq(false, api.nvim_get_option_info2('autochdir', {}).was_set)
+ api.nvim_set_option_value('autochdir', true, {})
+ eq(true, api.nvim_get_option_info2('autochdir', {}).was_set)
- eq(false, nvim('get_option_info2', 'cmdwinheight', {}).was_set)
- nvim('set_option_value', 'cmdwinheight', 10, {})
- eq(true, nvim('get_option_info2', 'cmdwinheight', {}).was_set)
+ eq(false, api.nvim_get_option_info2('cmdwinheight', {}).was_set)
+ api.nvim_set_option_value('cmdwinheight', 10, {})
+ eq(true, api.nvim_get_option_info2('cmdwinheight', {}).was_set)
- eq(false, nvim('get_option_info2', 'debug', {}).was_set)
- nvim('set_option_value', 'debug', 'beep', {})
- eq(true, nvim('get_option_info2', 'debug', {}).was_set)
+ eq(false, api.nvim_get_option_info2('debug', {}).was_set)
+ api.nvim_set_option_value('debug', 'beep', {})
+ eq(true, api.nvim_get_option_info2('debug', {}).was_set)
end)
it('validation', function()
- eq("Invalid 'scope': expected 'local' or 'global'",
- pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 'bogus'}))
- eq("Invalid 'scope': expected 'local' or 'global'",
- pcall_err(nvim, 'set_option_value', 'scrolloff', 1, {scope = 'bogus'}))
- eq("Invalid 'scope': expected String, got Integer",
- pcall_err(nvim, 'get_option_value', 'scrolloff', {scope = 42}))
- eq("Invalid 'value': expected valid option type, got Array",
- pcall_err(nvim, 'set_option_value', 'scrolloff', {}, {}))
- eq("Invalid value for option 'scrolloff': expected Number, got Boolean true",
- pcall_err(nvim, 'set_option_value', 'scrolloff', true, {}))
- eq("Invalid value for option 'scrolloff': expected Number, got String \"wrong\"",
- pcall_err(nvim, 'set_option_value', 'scrolloff', 'wrong', {}))
+ eq(
+ "Invalid 'scope': expected 'local' or 'global'",
+ pcall_err(api.nvim_get_option_value, 'scrolloff', { scope = 'bogus' })
+ )
+ eq(
+ "Invalid 'scope': expected 'local' or 'global'",
+ pcall_err(api.nvim_set_option_value, 'scrolloff', 1, { scope = 'bogus' })
+ )
+ eq(
+ "Invalid 'scope': expected String, got Integer",
+ pcall_err(api.nvim_get_option_value, 'scrolloff', { scope = 42 })
+ )
+ eq(
+ "Invalid 'value': expected valid option type, got Array",
+ pcall_err(api.nvim_set_option_value, 'scrolloff', {}, {})
+ )
+ eq(
+ "Invalid value for option 'scrolloff': expected number, got boolean true",
+ pcall_err(api.nvim_set_option_value, 'scrolloff', true, {})
+ )
+ eq(
+ 'Invalid value for option \'scrolloff\': expected number, got string "wrong"',
+ pcall_err(api.nvim_set_option_value, 'scrolloff', 'wrong', {})
+ )
end)
it('can get local values when global value is set', function()
- eq(0, nvim('get_option_value', 'scrolloff', {}))
- eq(-1, nvim('get_option_value', 'scrolloff', {scope = 'local'}))
+ eq(0, api.nvim_get_option_value('scrolloff', {}))
+ eq(-1, api.nvim_get_option_value('scrolloff', { scope = 'local' }))
end)
it('can set global and local values', function()
- nvim('set_option_value', 'makeprg', 'hello', {})
- eq('hello', nvim('get_option_value', 'makeprg', {}))
- eq('', nvim('get_option_value', 'makeprg', {scope = 'local'}))
- nvim('set_option_value', 'makeprg', 'world', {scope = 'local'})
- eq('world', nvim('get_option_value', 'makeprg', {scope = 'local'}))
- nvim('set_option_value', 'makeprg', 'goodbye', {scope = 'global'})
- eq('goodbye', nvim('get_option_value', 'makeprg', {scope = 'global'}))
- nvim('set_option_value', 'makeprg', 'hello', {})
- eq('hello', nvim('get_option_value', 'makeprg', {scope = 'global'}))
- eq('hello', nvim('get_option_value', 'makeprg', {}))
- eq('', nvim('get_option_value', 'makeprg', {scope = 'local'}))
+ api.nvim_set_option_value('makeprg', 'hello', {})
+ eq('hello', api.nvim_get_option_value('makeprg', {}))
+ eq('', api.nvim_get_option_value('makeprg', { scope = 'local' }))
+ api.nvim_set_option_value('makeprg', 'world', { scope = 'local' })
+ eq('world', api.nvim_get_option_value('makeprg', { scope = 'local' }))
+ api.nvim_set_option_value('makeprg', 'goodbye', { scope = 'global' })
+ eq('goodbye', api.nvim_get_option_value('makeprg', { scope = 'global' }))
+ api.nvim_set_option_value('makeprg', 'hello', {})
+ eq('hello', api.nvim_get_option_value('makeprg', { scope = 'global' }))
+ eq('hello', api.nvim_get_option_value('makeprg', {}))
+ eq('', api.nvim_get_option_value('makeprg', { scope = 'local' }))
end)
it('clears the local value of an option with nil', function()
-- Set global value
- nvim('set_option_value', 'shiftwidth', 42, {})
- eq(42, nvim('get_option_value', 'shiftwidth', {}))
+ api.nvim_set_option_value('shiftwidth', 42, {})
+ eq(42, api.nvim_get_option_value('shiftwidth', {}))
-- Set local value
- nvim('set_option_value', 'shiftwidth', 8, {scope = 'local'})
- eq(8, nvim('get_option_value', 'shiftwidth', {}))
- eq(8, nvim('get_option_value', 'shiftwidth', {scope = 'local'}))
- eq(42, nvim('get_option_value', 'shiftwidth', {scope = 'global'}))
+ api.nvim_set_option_value('shiftwidth', 8, { scope = 'local' })
+ eq(8, api.nvim_get_option_value('shiftwidth', {}))
+ eq(8, api.nvim_get_option_value('shiftwidth', { scope = 'local' }))
+ eq(42, api.nvim_get_option_value('shiftwidth', { scope = 'global' }))
-- Clear value without scope
- nvim('set_option_value', 'shiftwidth', NIL, {})
- eq(42, nvim('get_option_value', 'shiftwidth', {}))
- eq(42, nvim('get_option_value', 'shiftwidth', {scope = 'local'}))
+ api.nvim_set_option_value('shiftwidth', NIL, {})
+ eq(42, api.nvim_get_option_value('shiftwidth', {}))
+ eq(42, api.nvim_get_option_value('shiftwidth', { scope = 'local' }))
-- Clear value with explicit scope
- nvim('set_option_value', 'shiftwidth', 8, {scope = 'local'})
- nvim('set_option_value', 'shiftwidth', NIL, {scope = 'local'})
- eq(42, nvim('get_option_value', 'shiftwidth', {}))
- eq(42, nvim('get_option_value', 'shiftwidth', {scope = 'local'}))
+ api.nvim_set_option_value('shiftwidth', 8, { scope = 'local' })
+ api.nvim_set_option_value('shiftwidth', NIL, { scope = 'local' })
+ eq(42, api.nvim_get_option_value('shiftwidth', {}))
+ eq(42, api.nvim_get_option_value('shiftwidth', { scope = 'local' }))
-- Now try with options with a special "local is unset" value (e.g. 'undolevels')
- nvim('set_option_value', 'undolevels', 1000, {})
- nvim('set_option_value', 'undolevels', 1200, {scope = 'local'})
- eq(1200, nvim('get_option_value', 'undolevels', {scope = 'local'}))
- nvim('set_option_value', 'undolevels', NIL, {scope = 'local'})
- eq(-123456, nvim('get_option_value', 'undolevels', {scope = 'local'}))
- eq(1000, nvim('get_option_value', 'undolevels', {}))
+ api.nvim_set_option_value('undolevels', 1000, {})
+ api.nvim_set_option_value('undolevels', 1200, { scope = 'local' })
+ eq(1200, api.nvim_get_option_value('undolevels', { scope = 'local' }))
+ api.nvim_set_option_value('undolevels', NIL, { scope = 'local' })
+ eq(-123456, api.nvim_get_option_value('undolevels', { scope = 'local' }))
+ eq(1000, api.nvim_get_option_value('undolevels', {}))
- nvim('set_option_value', 'autoread', true, {})
- nvim('set_option_value', 'autoread', false, {scope = 'local'})
- eq(false, nvim('get_option_value', 'autoread', {scope = 'local'}))
- nvim('set_option_value', 'autoread', NIL, {scope = 'local'})
- eq(NIL, nvim('get_option_value', 'autoread', {scope = 'local'}))
- eq(true, nvim('get_option_value', 'autoread', {}))
+ api.nvim_set_option_value('autoread', true, {})
+ api.nvim_set_option_value('autoread', false, { scope = 'local' })
+ eq(false, api.nvim_get_option_value('autoread', { scope = 'local' }))
+ api.nvim_set_option_value('autoread', NIL, { scope = 'local' })
+ eq(NIL, api.nvim_get_option_value('autoread', { scope = 'local' }))
+ eq(true, api.nvim_get_option_value('autoread', {}))
end)
it('set window options', function()
- 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
- eq('4,3', nvim('get_option_value', 'colorcolumn', {scope = 'local'}))
+ api.nvim_set_option_value('colorcolumn', '4,3', {})
+ eq('4,3', api.nvim_get_option_value('colorcolumn', { scope = 'local' }))
+ command('set modified hidden')
+ command('enew') -- edit new buffer, window option is preserved
+ eq('4,3', api.nvim_get_option_value('colorcolumn', { scope = 'local' }))
end)
it('set local window options', function()
- 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")
- command("enew") -- edit new buffer, window option is reset
- eq('', nvim('get_option_value', 'colorcolumn', {win = 0, scope = 'local'}))
+ api.nvim_set_option_value('colorcolumn', '4,3', { win = 0, scope = 'local' })
+ eq('4,3', api.nvim_get_option_value('colorcolumn', { win = 0, scope = 'local' }))
+ command('set modified hidden')
+ command('enew') -- edit new buffer, window option is reset
+ eq('', api.nvim_get_option_value('colorcolumn', { win = 0, scope = 'local' }))
end)
it('get buffer or window-local options', function()
- nvim('command', 'new')
- local buf = nvim('get_current_buf').id
- nvim('set_option_value', 'tagfunc', 'foobar', {buf=buf})
- eq('foobar', nvim('get_option_value', 'tagfunc', {buf = buf}))
+ command('new')
+ local buf = api.nvim_get_current_buf()
+ api.nvim_set_option_value('tagfunc', 'foobar', { buf = buf })
+ eq('foobar', api.nvim_get_option_value('tagfunc', { buf = buf }))
- local win = nvim('get_current_win').id
- nvim('set_option_value', 'number', true, {win=win})
- eq(true, nvim('get_option_value', 'number', {win = win}))
+ local win = api.nvim_get_current_win()
+ api.nvim_set_option_value('number', true, { win = win })
+ eq(true, api.nvim_get_option_value('number', { win = win }))
end)
it('getting current buffer option does not adjust cursor #19381', function()
- nvim('command', 'new')
- local buf = nvim('get_current_buf').id
- local win = nvim('get_current_win').id
+ command('new')
+ local buf = api.nvim_get_current_buf()
+ print(vim.inspect(api.nvim_get_current_buf()))
+ local win = api.nvim_get_current_win()
insert('some text')
feed('0v$')
- eq({1, 9}, nvim('win_get_cursor', win))
- nvim('get_option_value', 'filetype', {buf = buf})
- eq({1, 9}, nvim('win_get_cursor', win))
+ eq({ 1, 9 }, api.nvim_win_get_cursor(win))
+ api.nvim_get_option_value('filetype', { buf = buf })
+ eq({ 1, 9 }, api.nvim_win_get_cursor(win))
end)
it('can get default option values for filetypes', function()
@@ -1593,158 +1745,160 @@ describe('API', function()
for ft, opts in pairs {
lua = { commentstring = '-- %s' },
vim = { commentstring = '"%s' },
- man = { tagfunc = 'v:lua.require\'man\'.goto_tag' },
- xml = { formatexpr = 'xmlformat#Format()' }
+ man = { tagfunc = "v:lua.require'man'.goto_tag" },
+ xml = { formatexpr = 'xmlformat#Format()' },
} do
for option, value in pairs(opts) do
- eq(value, nvim('get_option_value', option, { filetype = ft }))
+ eq(value, api.nvim_get_option_value(option, { filetype = ft }))
end
end
- command'au FileType lua setlocal commentstring=NEW\\ %s'
+ command 'au FileType lua setlocal commentstring=NEW\\ %s'
- eq('NEW %s', nvim('get_option_value', 'commentstring', { filetype = 'lua' }))
+ eq('NEW %s', api.nvim_get_option_value('commentstring', { filetype = 'lua' }))
end)
it('errors for bad FileType autocmds', function()
- command'au FileType lua setlocal commentstring=BAD'
- eq([[FileType Autocommands for "lua": Vim(setlocal):E537: 'commentstring' must be empty or contain %s: commentstring=BAD]],
- pcall_err(nvim, 'get_option_value', 'commentstring', { filetype = 'lua' }))
+ command 'au FileType lua setlocal commentstring=BAD'
+ eq(
+ [[FileType Autocommands for "lua": Vim(setlocal):E537: 'commentstring' must be empty or contain %s: commentstring=BAD]],
+ pcall_err(api.nvim_get_option_value, 'commentstring', { filetype = 'lua' })
+ )
end)
it("value of 'modified' is always false for scratch buffers", function()
- nvim('set_current_buf', nvim('create_buf', true, true))
+ api.nvim_set_current_buf(api.nvim_create_buf(true, true))
insert([[
foo
bar
baz
]])
- eq(false, nvim('get_option_value', 'modified', {}))
+ eq(false, api.nvim_get_option_value('modified', {}))
end)
end)
describe('nvim_{get,set}_current_buf, nvim_list_bufs', function()
it('works', function()
- eq(1, #nvim('list_bufs'))
- eq(nvim('list_bufs')[1], nvim('get_current_buf'))
- nvim('command', 'new')
- eq(2, #nvim('list_bufs'))
- eq(nvim('list_bufs')[2], nvim('get_current_buf'))
- nvim('set_current_buf', nvim('list_bufs')[1])
- eq(nvim('list_bufs')[1], nvim('get_current_buf'))
+ eq(1, #api.nvim_list_bufs())
+ eq(api.nvim_list_bufs()[1], api.nvim_get_current_buf())
+ command('new')
+ eq(2, #api.nvim_list_bufs())
+ eq(api.nvim_list_bufs()[2], api.nvim_get_current_buf())
+ api.nvim_set_current_buf(api.nvim_list_bufs()[1])
+ eq(api.nvim_list_bufs()[1], api.nvim_get_current_buf())
end)
end)
describe('nvim_{get,set}_current_win, nvim_list_wins', function()
it('works', function()
- eq(1, #nvim('list_wins'))
- eq(nvim('list_wins')[1], nvim('get_current_win'))
- nvim('command', 'vsplit')
- nvim('command', 'split')
- eq(3, #nvim('list_wins'))
- eq(nvim('list_wins')[1], nvim('get_current_win'))
- nvim('set_current_win', nvim('list_wins')[2])
- eq(nvim('list_wins')[2], nvim('get_current_win'))
+ eq(1, #api.nvim_list_wins())
+ eq(api.nvim_list_wins()[1], api.nvim_get_current_win())
+ command('vsplit')
+ command('split')
+ eq(3, #api.nvim_list_wins())
+ eq(api.nvim_list_wins()[1], api.nvim_get_current_win())
+ api.nvim_set_current_win(api.nvim_list_wins()[2])
+ eq(api.nvim_list_wins()[2], api.nvim_get_current_win())
end)
end)
describe('nvim_{get,set}_current_tabpage, nvim_list_tabpages', function()
it('works', function()
- eq(1, #nvim('list_tabpages'))
- eq(nvim('list_tabpages')[1], nvim('get_current_tabpage'))
- nvim('command', 'tabnew')
- eq(2, #nvim('list_tabpages'))
- eq(2, #nvim('list_wins'))
- eq(nvim('list_wins')[2], nvim('get_current_win'))
- eq(nvim('list_tabpages')[2], nvim('get_current_tabpage'))
- nvim('set_current_win', nvim('list_wins')[1])
+ eq(1, #api.nvim_list_tabpages())
+ eq(api.nvim_list_tabpages()[1], api.nvim_get_current_tabpage())
+ command('tabnew')
+ eq(2, #api.nvim_list_tabpages())
+ eq(2, #api.nvim_list_wins())
+ eq(api.nvim_list_wins()[2], api.nvim_get_current_win())
+ eq(api.nvim_list_tabpages()[2], api.nvim_get_current_tabpage())
+ api.nvim_set_current_win(api.nvim_list_wins()[1])
-- Switching window also switches tabpages if necessary
- eq(nvim('list_tabpages')[1], nvim('get_current_tabpage'))
- eq(nvim('list_wins')[1], nvim('get_current_win'))
- nvim('set_current_tabpage', nvim('list_tabpages')[2])
- eq(nvim('list_tabpages')[2], nvim('get_current_tabpage'))
- eq(nvim('list_wins')[2], nvim('get_current_win'))
+ eq(api.nvim_list_tabpages()[1], api.nvim_get_current_tabpage())
+ eq(api.nvim_list_wins()[1], api.nvim_get_current_win())
+ api.nvim_set_current_tabpage(api.nvim_list_tabpages()[2])
+ eq(api.nvim_list_tabpages()[2], api.nvim_get_current_tabpage())
+ eq(api.nvim_list_wins()[2], api.nvim_get_current_win())
end)
end)
describe('nvim_get_mode', function()
- it("during normal-mode `g` returns blocking=true", function()
- nvim("input", "o") -- add a line
- eq({mode='i', blocking=false}, nvim("get_mode"))
- nvim("input", [[<C-\><C-N>]])
- eq(2, nvim("eval", "line('.')"))
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ it('during normal-mode `g` returns blocking=true', function()
+ api.nvim_input('o') -- add a line
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
+ api.nvim_input([[<C-\><C-N>]])
+ eq(2, api.nvim_eval("line('.')"))
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
- nvim("input", "g")
- eq({mode='n', blocking=true}, nvim("get_mode"))
+ api.nvim_input('g')
+ eq({ mode = 'n', blocking = true }, api.nvim_get_mode())
- nvim("input", "k") -- complete the operator
- eq(1, nvim("eval", "line('.')")) -- verify the completed operator
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ api.nvim_input('k') -- complete the operator
+ eq(1, api.nvim_eval("line('.')")) -- verify the completed operator
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
- it("returns the correct result multiple consecutive times", function()
- for _ = 1,5 do
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ it('returns the correct result multiple consecutive times', function()
+ for _ = 1, 5 do
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end
- nvim("input", "g")
- for _ = 1,4 do
- eq({mode='n', blocking=true}, nvim("get_mode"))
+ api.nvim_input('g')
+ for _ = 1, 4 do
+ eq({ mode = 'n', blocking = true }, api.nvim_get_mode())
end
- nvim("input", "g")
- for _ = 1,7 do
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ api.nvim_input('g')
+ for _ = 1, 7 do
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end
end)
- it("during normal-mode CTRL-W, returns blocking=true", function()
- nvim("input", "<C-W>")
- eq({mode='n', blocking=true}, nvim("get_mode"))
+ it('during normal-mode CTRL-W, returns blocking=true', function()
+ api.nvim_input('<C-W>')
+ eq({ mode = 'n', blocking = true }, api.nvim_get_mode())
- nvim("input", "s") -- complete the operator
- eq(2, nvim("eval", "winnr('$')")) -- verify the completed operator
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ api.nvim_input('s') -- complete the operator
+ eq(2, api.nvim_eval("winnr('$')")) -- verify the completed operator
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
- it("during press-enter prompt without UI returns blocking=false", function()
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ it('during press-enter prompt without UI returns blocking=false', function()
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
command("echom 'msg1'")
command("echom 'msg2'")
command("echom 'msg3'")
command("echom 'msg4'")
command("echom 'msg5'")
- eq({mode='n', blocking=false}, nvim("get_mode"))
- nvim("input", ":messages<CR>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
+ api.nvim_input(':messages<CR>')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
- it("during press-enter prompt returns blocking=true", function()
- nvim("ui_attach", 80, 20, {})
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ it('during press-enter prompt returns blocking=true', function()
+ api.nvim_ui_attach(80, 20, {})
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
command("echom 'msg1'")
command("echom 'msg2'")
command("echom 'msg3'")
command("echom 'msg4'")
command("echom 'msg5'")
- eq({mode='n', blocking=false}, nvim("get_mode"))
- nvim("input", ":messages<CR>")
- eq({mode='r', blocking=true}, nvim("get_mode"))
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
+ api.nvim_input(':messages<CR>')
+ eq({ mode = 'r', blocking = true }, api.nvim_get_mode())
end)
- it("during getchar() returns blocking=false", function()
- nvim("input", ":let g:test_input = nr2char(getchar())<CR>")
+ it('during getchar() returns blocking=false', function()
+ api.nvim_input(':let g:test_input = nr2char(getchar())<CR>')
-- Events are enabled during getchar(), RPC calls are *not* blocked. #5384
- eq({mode='n', blocking=false}, nvim("get_mode"))
- eq(0, nvim("eval", "exists('g:test_input')"))
- nvim("input", "J")
- eq("J", nvim("eval", "g:test_input"))
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
+ eq(0, api.nvim_eval("exists('g:test_input')"))
+ api.nvim_input('J')
+ eq('J', api.nvim_eval('g:test_input'))
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
-- TODO: bug #6247#issuecomment-286403810
- it("batched with input", function()
- nvim("ui_attach", 80, 20, {})
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ it('batched with input', function()
+ api.nvim_ui_attach(80, 20, {})
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
command("echom 'msg1'")
command("echom 'msg2'")
command("echom 'msg3'")
@@ -1752,44 +1906,48 @@ describe('API', function()
command("echom 'msg5'")
local req = {
- {'nvim_get_mode', {}},
- {'nvim_input', {':messages<CR>'}},
- {'nvim_get_mode', {}},
- {'nvim_eval', {'1'}},
+ { 'nvim_get_mode', {} },
+ { 'nvim_input', { ':messages<CR>' } },
+ { 'nvim_get_mode', {} },
+ { 'nvim_eval', { '1' } },
}
- eq({ { {mode='n', blocking=false},
- 13,
- {mode='n', blocking=false}, -- TODO: should be blocked=true ?
- 1 },
- NIL}, meths.call_atomic(req))
- eq({mode='r', blocking=true}, nvim("get_mode"))
+ eq({
+ {
+ { mode = 'n', blocking = false },
+ 13,
+ { mode = 'n', blocking = false }, -- TODO: should be blocked=true ?
+ 1,
+ },
+ NIL,
+ }, api.nvim_call_atomic(req))
+ eq({ mode = 'r', blocking = true }, api.nvim_get_mode())
end)
- it("during insert-mode map-pending, returns blocking=true #6166", function()
- command("inoremap xx foo")
- nvim("input", "ix")
- eq({mode='i', blocking=true}, nvim("get_mode"))
+ it('during insert-mode map-pending, returns blocking=true #6166', function()
+ command('inoremap xx foo')
+ api.nvim_input('ix')
+ eq({ mode = 'i', blocking = true }, api.nvim_get_mode())
end)
- it("during normal-mode gU, returns blocking=false #6166", function()
- nvim("input", "gu")
- eq({mode='no', blocking=false}, nvim("get_mode"))
+ it('during normal-mode gU, returns blocking=false #6166', function()
+ api.nvim_input('gu')
+ eq({ mode = 'no', blocking = false }, api.nvim_get_mode())
end)
it("at '-- More --' prompt returns blocking=true #11899", function()
command('set more')
feed(':digraphs<cr>')
- eq({mode='rm', blocking=true}, nvim("get_mode"))
+ eq({ mode = 'rm', blocking = true }, api.nvim_get_mode())
end)
it('after <Nop> mapping returns blocking=false #17257', function()
command('nnoremap <F2> <Nop>')
feed('<F2>')
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
it('after empty string <expr> mapping returns blocking=false #17257', function()
command('nnoremap <expr> <F2> ""')
feed('<F2>')
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
end)
@@ -1798,16 +1956,16 @@ describe('API', function()
helpers.insert([[
FIRST LINE
SECOND LINE]])
- nvim('input', 'gg')
- nvim('input', 'gu')
+ api.nvim_input('gg')
+ api.nvim_input('gu')
-- Make any RPC request (can be non-async: op-pending does not block).
- nvim('get_current_buf')
+ api.nvim_get_current_buf()
-- Buffer should not change.
expect([[
FIRST LINE
SECOND LINE]])
-- Now send input to complete the operator.
- nvim('input', 'j')
+ api.nvim_input('j')
expect([[
first line
second line]])
@@ -1821,7 +1979,7 @@ describe('API', function()
feed('ia<cr>b<cr>c<cr><Esc>kkk')
feed('d')
-- Make any RPC request (can be non-async: op-pending does not block).
- nvim('get_current_buf')
+ api.nvim_get_current_buf()
screen:expect([[
^a$ |
b$ |
@@ -1835,12 +1993,12 @@ describe('API', function()
helpers.insert([[
FIRST LINE
SECOND LINE]])
- nvim('input', 'gg')
- nvim('input', 'd')
+ api.nvim_input('gg')
+ api.nvim_input('d')
-- Make any RPC request (must be async, because map-pending blocks).
- nvim('get_api_info')
+ api.nvim_get_api_info()
-- Send input to complete the mapping.
- nvim('input', 'd')
+ api.nvim_input('d')
expect([[
FIRST LINE
SECOND LINE]])
@@ -1853,11 +2011,11 @@ describe('API', function()
helpers.insert([[
FIRST LINE
SECOND LINE]])
- nvim('input', 'ix')
+ api.nvim_input('ix')
-- Make any RPC request (must be async, because map-pending blocks).
- nvim('get_api_info')
+ api.nvim_get_api_info()
-- Send input to complete the mapping.
- nvim('input', 'x')
+ api.nvim_input('x')
expect([[
FIRST LINE
SECOND LINfooE]])
@@ -1865,158 +2023,168 @@ describe('API', function()
it('does not interrupt Insert mode i_CTRL-O #10035', function()
feed('iHello World<c-o>')
- eq({mode='niI', blocking=false}, meths.get_mode()) -- fast event
- eq(2, eval('1+1')) -- causes K_EVENT key
- eq({mode='niI', blocking=false}, meths.get_mode()) -- still in ctrl-o mode
+ eq({ mode = 'niI', blocking = false }, api.nvim_get_mode()) -- fast event
+ eq(2, eval('1+1')) -- causes K_EVENT key
+ eq({ mode = 'niI', blocking = false }, api.nvim_get_mode()) -- still in ctrl-o mode
feed('dd')
- eq({mode='i', blocking=false}, meths.get_mode()) -- left ctrl-o mode
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode()) -- left ctrl-o mode
expect('') -- executed the command
end)
it('does not interrupt Select mode v_CTRL-O #15688', function()
feed('iHello World<esc>gh<c-o>')
- eq({mode='vs', blocking=false}, meths.get_mode()) -- fast event
- eq({mode='vs', blocking=false}, meths.get_mode()) -- again #15288
- eq(2, eval('1+1')) -- causes K_EVENT key
- eq({mode='vs', blocking=false}, meths.get_mode()) -- still in ctrl-o mode
+ eq({ mode = 'vs', blocking = false }, api.nvim_get_mode()) -- fast event
+ eq({ mode = 'vs', blocking = false }, api.nvim_get_mode()) -- again #15288
+ eq(2, eval('1+1')) -- causes K_EVENT key
+ eq({ mode = 'vs', blocking = false }, api.nvim_get_mode()) -- still in ctrl-o mode
feed('^')
- eq({mode='s', blocking=false}, meths.get_mode()) -- left ctrl-o mode
+ eq({ mode = 's', blocking = false }, api.nvim_get_mode()) -- left ctrl-o mode
feed('h')
- eq({mode='i', blocking=false}, meths.get_mode()) -- entered insert mode
- expect('h') -- selection is the whole line and is replaced
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode()) -- entered insert mode
+ expect('h') -- selection is the whole line and is replaced
end)
it('does not interrupt Insert mode i_0_CTRL-D #13997', function()
command('set timeoutlen=9999')
feed('i<Tab><Tab>a0')
- eq(2, eval('1+1')) -- causes K_EVENT key
+ eq(2, eval('1+1')) -- causes K_EVENT key
feed('<C-D>')
- expect('a') -- recognized i_0_CTRL-D
+ expect('a') -- recognized i_0_CTRL-D
end)
it("does not interrupt with 'digraph'", function()
command('set digraph')
feed('i,')
- eq(2, eval('1+1')) -- causes K_EVENT key
+ eq(2, eval('1+1')) -- causes K_EVENT key
feed('<BS>')
- eq(2, eval('1+1')) -- causes K_EVENT key
+ eq(2, eval('1+1')) -- causes K_EVENT key
feed('.')
- expect('…') -- digraph ",." worked
+ expect('…') -- digraph ",." worked
feed('<Esc>')
feed(':,')
- eq(2, eval('1+1')) -- causes K_EVENT key
+ eq(2, eval('1+1')) -- causes K_EVENT key
feed('<BS>')
- eq(2, eval('1+1')) -- causes K_EVENT key
+ eq(2, eval('1+1')) -- causes K_EVENT key
feed('.')
- eq('…', funcs.getcmdline()) -- digraph ",." worked
+ eq('…', fn.getcmdline()) -- digraph ",." worked
end)
end)
describe('nvim_get_context', function()
it('validation', function()
- eq("Invalid key: 'blah'",
- pcall_err(nvim, 'get_context', {blah={}}))
- eq("Invalid 'types': expected Array, got Integer",
- pcall_err(nvim, 'get_context', {types=42}))
- eq("Invalid 'type': 'zub'",
- pcall_err(nvim, 'get_context', {types={'jumps', 'zub', 'zam',}}))
+ eq("Invalid key: 'blah'", pcall_err(api.nvim_get_context, { blah = {} }))
+ eq(
+ "Invalid 'types': expected Array, got Integer",
+ pcall_err(api.nvim_get_context, { types = 42 })
+ )
+ eq(
+ "Invalid 'type': 'zub'",
+ pcall_err(api.nvim_get_context, { types = { 'jumps', 'zub', 'zam' } })
+ )
end)
it('returns map of current editor state', function()
- local opts = {types={'regs', 'jumps', 'bufs', 'gvars'}}
- eq({}, parse_context(nvim('get_context', {})))
+ local opts = { types = { 'regs', 'jumps', 'bufs', 'gvars' } }
+ eq({}, parse_context(api.nvim_get_context({})))
feed('i1<cr>2<cr>3<c-[>ddddddqahjklquuu')
feed('gg')
feed('G')
command('edit! BUF1')
command('edit BUF2')
- nvim('set_var', 'one', 1)
- nvim('set_var', 'Two', 2)
- nvim('set_var', 'THREE', 3)
+ api.nvim_set_var('one', 1)
+ api.nvim_set_var('Two', 2)
+ api.nvim_set_var('THREE', 3)
local expected_ctx = {
['regs'] = {
- {['rt'] = 1, ['rc'] = {'1'}, ['n'] = 49, ['ru'] = true},
- {['rt'] = 1, ['rc'] = {'2'}, ['n'] = 50},
- {['rt'] = 1, ['rc'] = {'3'}, ['n'] = 51},
- {['rc'] = {'hjkl'}, ['n'] = 97},
+ { ['rt'] = 1, ['rc'] = { '1' }, ['n'] = 49, ['ru'] = true },
+ { ['rt'] = 1, ['rc'] = { '2' }, ['n'] = 50 },
+ { ['rt'] = 1, ['rc'] = { '3' }, ['n'] = 51 },
+ { ['rc'] = { 'hjkl' }, ['n'] = 97 },
},
- ['jumps'] = eval(([[
+ ['jumps'] = eval((([[
filter(map(add(
getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }),
'filter(
{ "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
{ k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
- ]]):gsub('\n', '')),
+ ]]):gsub('\n', ''))),
['bufs'] = eval([[
filter(map(getbufinfo(), '{ "f": v:val.name }'), '!empty(v:val.f)')
]]),
- ['gvars'] = {{'one', 1}, {'Two', 2}, {'THREE', 3}},
+ ['gvars'] = { { 'one', 1 }, { 'Two', 2 }, { 'THREE', 3 } },
}
- eq(expected_ctx, parse_context(nvim('get_context', opts)))
- eq(expected_ctx, parse_context(nvim('get_context', {})))
- eq(expected_ctx, parse_context(nvim('get_context', {types={}})))
+ eq(expected_ctx, parse_context(api.nvim_get_context(opts)))
+ eq(expected_ctx, parse_context(api.nvim_get_context({})))
+ eq(expected_ctx, parse_context(api.nvim_get_context({ types = {} })))
end)
end)
describe('nvim_load_context', function()
it('sets current editor state to given context dictionary', function()
- local opts = {types={'regs', 'jumps', 'bufs', 'gvars'}}
- eq({}, parse_context(nvim('get_context', opts)))
+ local opts = { types = { 'regs', 'jumps', 'bufs', 'gvars' } }
+ eq({}, parse_context(api.nvim_get_context(opts)))
- nvim('set_var', 'one', 1)
- nvim('set_var', 'Two', 2)
- nvim('set_var', 'THREE', 3)
- local ctx = nvim('get_context', opts)
- nvim('set_var', 'one', 'a')
- nvim('set_var', 'Two', 'b')
- nvim('set_var', 'THREE', 'c')
- eq({'a', 'b' ,'c'}, eval('[g:one, g:Two, g:THREE]'))
- nvim('load_context', ctx)
- eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]'))
+ api.nvim_set_var('one', 1)
+ api.nvim_set_var('Two', 2)
+ api.nvim_set_var('THREE', 3)
+ local ctx = api.nvim_get_context(opts)
+ api.nvim_set_var('one', 'a')
+ api.nvim_set_var('Two', 'b')
+ api.nvim_set_var('THREE', 'c')
+ eq({ 'a', 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
+ api.nvim_load_context(ctx)
+ eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
end)
it('errors when context dictionary is invalid', function()
- eq('E474: Failed to convert list to msgpack string buffer',
- pcall_err(nvim, 'load_context', { regs = { {} }, jumps = { {} } }))
- eq("Empty dictionary keys aren't allowed",
- pcall_err(nvim, 'load_context', { regs = { { [''] = '' } } }))
+ eq(
+ 'E474: Failed to convert list to msgpack string buffer',
+ pcall_err(api.nvim_load_context, { regs = { {} }, jumps = { {} } })
+ )
+ eq(
+ 'E474: Failed to convert list to msgpack string buffer',
+ pcall_err(api.nvim_load_context, { regs = { { [''] = '' } } })
+ )
end)
end)
describe('nvim_replace_termcodes', function()
it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function()
- eq('\128\254X', helpers.nvim('replace_termcodes', '\128', true, true, true))
+ eq('\128\254X', helpers.api.nvim_replace_termcodes('\128', true, true, true))
end)
it('leaves non-K_SPECIAL string unchanged', function()
- eq('abc', helpers.nvim('replace_termcodes', 'abc', true, true, true))
+ eq('abc', helpers.api.nvim_replace_termcodes('abc', true, true, true))
end)
it('converts <expressions>', function()
- eq('\\', helpers.nvim('replace_termcodes', '<Leader>', true, true, true))
+ eq('\\', helpers.api.nvim_replace_termcodes('<Leader>', true, true, true))
end)
it('converts <LeftMouse> to K_SPECIAL KS_EXTRA KE_LEFTMOUSE', function()
-- K_SPECIAL KS_EXTRA KE_LEFTMOUSE
-- 0x80 0xfd 0x2c
-- 128 253 44
- eq('\128\253\44', helpers.nvim('replace_termcodes',
- '<LeftMouse>', true, true, true))
+ eq('\128\253\44', helpers.api.nvim_replace_termcodes('<LeftMouse>', true, true, true))
end)
it('converts keycodes', function()
- eq('\nx\27x\rx<x', helpers.nvim('replace_termcodes',
- '<NL>x<Esc>x<CR>x<lt>x', true, true, true))
+ eq(
+ '\nx\27x\rx<x',
+ helpers.api.nvim_replace_termcodes('<NL>x<Esc>x<CR>x<lt>x', true, true, true)
+ )
end)
it('does not convert keycodes if special=false', function()
- eq('<NL>x<Esc>x<CR>x<lt>x', helpers.nvim('replace_termcodes',
- '<NL>x<Esc>x<CR>x<lt>x', true, true, false))
+ eq(
+ '<NL>x<Esc>x<CR>x<lt>x',
+ helpers.api.nvim_replace_termcodes('<NL>x<Esc>x<CR>x<lt>x', true, true, false)
+ )
end)
it('does not crash when transforming an empty string', function()
@@ -2027,13 +2195,13 @@ describe('API', function()
-- then `return str` in vim_replace_termcodes body will make Neovim free
-- `str.data` twice: once when freeing arguments, then when freeing return
-- value.
- eq('', meths.replace_termcodes('', true, true, true))
+ eq('', api.nvim_replace_termcodes('', true, true, true))
end)
-- Not exactly the case, as nvim_replace_termcodes() escapes K_SPECIAL in Unicode
it('translates the result of keytrans() on string with 0x80 byte back', function()
local s = 'ff\128\253\097tt'
- eq(s, meths.replace_termcodes(funcs.keytrans(s), true, true, true))
+ eq(s, api.nvim_replace_termcodes(fn.keytrans(s), true, true, true))
end)
end)
@@ -2041,15 +2209,15 @@ describe('API', function()
it('K_SPECIAL escaping', function()
local function on_setup()
-- notice the special char(…) \xe2\80\xa6
- nvim('feedkeys', ':let x1="…"\n', '', true)
+ api.nvim_feedkeys(':let x1="…"\n', '', true)
-- Both nvim_replace_termcodes and nvim_feedkeys escape \x80
- local inp = helpers.nvim('replace_termcodes', ':let x2="…"<CR>', true, true, true)
- nvim('feedkeys', inp, '', true) -- escape_ks=true
+ local inp = helpers.api.nvim_replace_termcodes(':let x2="…"<CR>', true, true, true)
+ api.nvim_feedkeys(inp, '', true) -- escape_ks=true
-- nvim_feedkeys with K_SPECIAL escaping disabled
- inp = helpers.nvim('replace_termcodes', ':let x3="…"<CR>', true, true, true)
- nvim('feedkeys', inp, '', false) -- escape_ks=false
+ inp = helpers.api.nvim_replace_termcodes(':let x3="…"<CR>', true, true, true)
+ api.nvim_feedkeys(inp, '', false) -- escape_ks=false
helpers.stop()
end
@@ -2057,10 +2225,10 @@ describe('API', function()
-- spin the loop a bit
helpers.run(nil, nil, on_setup)
- eq('…', nvim('get_var', 'x1'))
+ eq('…', api.nvim_get_var('x1'))
-- Because of the double escaping this is neq
- neq('…', nvim('get_var', 'x2'))
- eq('…', nvim('get_var', 'x3'))
+ neq('…', api.nvim_get_var('x2'))
+ eq('…', api.nvim_get_var('x3'))
end)
end)
@@ -2071,10 +2239,10 @@ describe('API', function()
screen = Screen.new(40, 8)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {bold = true, foreground = Screen.colors.SeaGreen},
- [2] = {bold = true, reverse = true},
- [3] = {foreground = Screen.colors.Blue},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [2] = { bold = true, reverse = true },
+ [3] = { foreground = Screen.colors.Blue },
})
end)
@@ -2095,47 +2263,48 @@ describe('API', function()
silent! call nvim_out_write("\n")
redir END
]])
- eq('\naaa\n' .. ('a'):rep(5002) .. '\naaa', meths.get_var('out'))
+ eq('\naaa\n' .. ('a'):rep(5002) .. '\naaa', api.nvim_get_var('out'))
end)
it('blank line in message', function()
feed([[:call nvim_out_write("\na\n")<CR>]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2: }|
|
a |
{1:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed('<CR>')
feed([[:call nvim_out_write("b\n\nc\n")<CR>]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2: }|
b |
|
c |
{1:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
it('NUL bytes in message', function()
feed([[:lua vim.api.nvim_out_write('aaa\0bbb\0\0ccc\nddd\0\0\0eee\n')<CR>]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2: }|
aaa{3:^@}bbb{3:^@^@}ccc |
ddd{3:^@^@^@}eee |
{1:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
end)
@@ -2146,34 +2315,27 @@ describe('API', function()
screen = Screen.new(40, 8)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {foreground = Screen.colors.White, background = Screen.colors.Red},
- [2] = {bold = true, foreground = Screen.colors.SeaGreen},
- [3] = {bold = true, reverse = true},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { foreground = Screen.colors.White, background = Screen.colors.Red },
+ [2] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [3] = { bold = true, reverse = true },
})
end)
it('can show one line', function()
- nvim_async('err_write', 'has bork\n')
+ async_meths.nvim_err_write('has bork\n')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
{1:has bork} |
]])
end)
it('shows return prompt when more than &cmdheight lines', function()
- nvim_async('err_write', 'something happened\nvery bad\n')
+ async_meths.nvim_err_write('something happened\nvery bad\n')
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3: }|
{1:something happened} |
{1:very bad} |
@@ -2182,7 +2344,7 @@ describe('API', function()
end)
it('shows return prompt after all lines are shown', function()
- nvim_async('err_write', 'FAILURE\nERROR\nEXCEPTION\nTRACEBACK\n')
+ async_meths.nvim_err_write('FAILURE\nERROR\nEXCEPTION\nTRACEBACK\n')
screen:expect([[
|
{0:~ }|
@@ -2197,47 +2359,40 @@ describe('API', function()
it('handles multiple calls', function()
-- without linebreak text is joined to one line
- nvim_async('err_write', 'very ')
- nvim_async('err_write', 'fail\n')
+ async_meths.nvim_err_write('very ')
+ async_meths.nvim_err_write('fail\n')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
{1:very fail} |
]])
helpers.poke_eventloop()
-- shows up to &cmdheight lines
- nvim_async('err_write', 'more fail\ntoo fail\n')
+ async_meths.nvim_err_write('more fail\ntoo fail\n')
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3: }|
{1:more fail} |
{1:too fail} |
{2:Press ENTER or type command to continue}^ |
]])
- feed('<cr>') -- exit the press ENTER screen
+ feed('<cr>') -- exit the press ENTER screen
end)
it('NUL bytes in message', function()
- nvim_async('err_write', 'aaa\0bbb\0\0ccc\nddd\0\0\0eee\n')
- screen:expect{grid=[[
+ async_meths.nvim_err_write('aaa\0bbb\0\0ccc\nddd\0\0\0eee\n')
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3: }|
{1:aaa^@bbb^@^@ccc} |
{1:ddd^@^@^@eee} |
{2:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
end)
@@ -2248,15 +2403,15 @@ describe('API', function()
screen = Screen.new(40, 8)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {foreground = Screen.colors.White, background = Screen.colors.Red},
- [2] = {bold = true, foreground = Screen.colors.SeaGreen},
- [3] = {bold = true, reverse = true},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { foreground = Screen.colors.White, background = Screen.colors.Red },
+ [2] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [3] = { bold = true, reverse = true },
})
end)
it('shows only one return prompt after all lines are shown', function()
- nvim_async('err_writeln', 'FAILURE\nERROR\nEXCEPTION\nTRACEBACK')
+ async_meths.nvim_err_writeln('FAILURE\nERROR\nEXCEPTION\nTRACEBACK')
screen:expect([[
|
{0:~ }|
@@ -2270,12 +2425,7 @@ describe('API', function()
feed('<CR>')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
|
]])
end)
@@ -2299,116 +2449,126 @@ describe('API', function()
}
it('returns {} for invalid channel', function()
- eq({}, meths.get_chan_info(0))
- eq({}, meths.get_chan_info(-1))
+ eq({}, api.nvim_get_chan_info(-1))
-- more preallocated numbers might be added, try something high
- eq({}, meths.get_chan_info(10))
+ eq({}, api.nvim_get_chan_info(10))
end)
it('stream=stdio channel', function()
- eq({[1]=testinfo,[2]=stderr}, meths.list_chans())
- eq(testinfo, meths.get_chan_info(1))
- eq(stderr, meths.get_chan_info(2))
-
- meths.set_client_info("functionaltests",
- {major=0, minor=3, patch=17},
- 'ui',
- {do_stuff={n_args={2,3}}},
- {license= 'Apache2'})
+ eq({ [1] = testinfo, [2] = stderr }, api.nvim_list_chans())
+ -- 0 should return current channel
+ eq(testinfo, api.nvim_get_chan_info(0))
+ eq(testinfo, api.nvim_get_chan_info(1))
+ eq(stderr, api.nvim_get_chan_info(2))
+
+ api.nvim_set_client_info(
+ 'functionaltests',
+ { major = 0, minor = 3, patch = 17 },
+ 'ui',
+ { do_stuff = { n_args = { 2, 3 } } },
+ { license = 'Apache2' }
+ )
local info = {
stream = 'stdio',
id = 1,
mode = 'rpc',
client = {
- name='functionaltests',
- version={major=0, minor=3, patch=17},
- type='ui',
- methods={do_stuff={n_args={2,3}}},
- attributes={license='Apache2'},
+ name = 'functionaltests',
+ version = { major = 0, minor = 3, patch = 17 },
+ type = 'ui',
+ methods = { do_stuff = { n_args = { 2, 3 } } },
+ attributes = { license = 'Apache2' },
},
}
- eq({info=info}, meths.get_var("info_event"))
- eq({[1]=info, [2]=stderr}, meths.list_chans())
- eq(info, meths.get_chan_info(1))
+ eq({ info = info }, api.nvim_get_var('info_event'))
+ eq({ [1] = info, [2] = stderr }, api.nvim_list_chans())
+ eq(info, api.nvim_get_chan_info(1))
end)
it('stream=job channel', function()
eq(3, eval("jobstart(['cat'], {'rpc': v:true})"))
local catpath = eval('exepath("cat")')
local info = {
- stream='job',
- id=3,
- argv={ catpath },
- mode='rpc',
- client={},
+ stream = 'job',
+ id = 3,
+ argv = { catpath },
+ mode = 'rpc',
+ client = {},
}
- eq({info=info}, meths.get_var("opened_event"))
- eq({[1]=testinfo,[2]=stderr,[3]=info}, meths.list_chans())
- eq(info, meths.get_chan_info(3))
- eval('rpcrequest(3, "nvim_set_client_info", "amazing-cat", {}, "remote",'..
- '{"nvim_command":{"n_args":1}},'.. -- and so on
- '{"description":"The Amazing Cat"})')
+ eq({ info = info }, api.nvim_get_var('opened_event'))
+ eq({ [1] = testinfo, [2] = stderr, [3] = info }, api.nvim_list_chans())
+ eq(info, api.nvim_get_chan_info(3))
+ eval(
+ 'rpcrequest(3, "nvim_set_client_info", "amazing-cat", {}, "remote",'
+ .. '{"nvim_command":{"n_args":1}},' -- and so on
+ .. '{"description":"The Amazing Cat"})'
+ )
info = {
- stream='job',
- id=3,
- argv={ catpath },
- mode='rpc',
+ stream = 'job',
+ id = 3,
+ argv = { catpath },
+ mode = 'rpc',
client = {
- name='amazing-cat',
- version={major=0},
- type='remote',
- methods={nvim_command={n_args=1}},
- attributes={description="The Amazing Cat"},
+ name = 'amazing-cat',
+ version = { major = 0 },
+ type = 'remote',
+ methods = { nvim_command = { n_args = 1 } },
+ attributes = { description = 'The Amazing Cat' },
},
}
- eq({info=info}, meths.get_var("info_event"))
- eq({[1]=testinfo,[2]=stderr,[3]=info}, meths.list_chans())
+ eq({ info = info }, api.nvim_get_var('info_event'))
+ eq({ [1] = testinfo, [2] = stderr, [3] = info }, api.nvim_list_chans())
- eq("Vim:Error invoking 'nvim_set_current_buf' on channel 3 (amazing-cat):\nWrong type for argument 1 when calling nvim_set_current_buf, expecting Buffer",
- pcall_err(eval, 'rpcrequest(3, "nvim_set_current_buf", -1)'))
+ eq(
+ "Vim:Error invoking 'nvim_set_current_buf' on channel 3 (amazing-cat):\nWrong type for argument 1 when calling nvim_set_current_buf, expecting Buffer",
+ pcall_err(eval, 'rpcrequest(3, "nvim_set_current_buf", -1)')
+ )
+ eq(info, eval('rpcrequest(3, "nvim_get_chan_info", 0)'))
end)
it('stream=job :terminal channel', function()
command(':terminal')
- eq({id=1}, meths.get_current_buf())
- eq(3, meths.get_option_value('channel', {buf=1}))
+ eq(1, api.nvim_get_current_buf())
+ eq(3, api.nvim_get_option_value('channel', { buf = 1 }))
local info = {
- stream='job',
- id=3,
- argv={ eval('exepath(&shell)') },
- mode='terminal',
+ stream = 'job',
+ id = 3,
+ argv = { eval('exepath(&shell)') },
+ mode = 'terminal',
buffer = 1,
- pty='?',
+ pty = '?',
}
- local event = meths.get_var("opened_event")
+ local event = api.nvim_get_var('opened_event')
if not is_os('win') then
info.pty = event.info.pty
- neq(nil, string.match(info.pty, "^/dev/"))
+ neq(nil, string.match(info.pty, '^/dev/'))
end
- eq({info=info}, event)
- info.buffer = {id=1}
- eq({[1]=testinfo,[2]=stderr,[3]=info}, meths.list_chans())
- eq(info, meths.get_chan_info(3))
+ eq({ info = info }, event)
+ info.buffer = 1
+ eq({ [1] = testinfo, [2] = stderr, [3] = info }, api.nvim_list_chans())
+ eq(info, api.nvim_get_chan_info(3))
-- :terminal with args + running process.
- command(':exe "terminal" shellescape(v:progpath) "-u NONE -i NONE"')
- eq(-1, eval('jobwait([&channel], 0)[0]')) -- Running?
+ command('enew')
+ local progpath_esc = eval('shellescape(v:progpath)')
+ fn.termopen(('%s -u NONE -i NONE'):format(progpath_esc), {
+ env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
+ })
+ eq(-1, eval('jobwait([&channel], 0)[0]')) -- Running?
local expected2 = {
stream = 'job',
id = 4,
- argv = (
- is_os('win') and {
- eval('&shell'),
- '/s',
- '/c',
- fmt('"%s -u NONE -i NONE"', eval('shellescape(v:progpath)')),
- } or {
- eval('&shell'),
- eval('&shellcmdflag'),
- fmt('%s -u NONE -i NONE', eval('shellescape(v:progpath)')),
- }
- ),
+ argv = (is_os('win') and {
+ eval('&shell'),
+ '/s',
+ '/c',
+ fmt('"%s -u NONE -i NONE"', progpath_esc),
+ } or {
+ eval('&shell'),
+ eval('&shellcmdflag'),
+ fmt('%s -u NONE -i NONE', progpath_esc),
+ }),
mode = 'terminal',
buffer = 2,
pty = '?',
@@ -2419,163 +2579,172 @@ describe('API', function()
-- :terminal with args + stopped process.
eq(1, eval('jobstop(&channel)'))
- eval('jobwait([&channel], 1000)') -- Wait.
- expected2.pty = (is_os('win') and '?' or '') -- pty stream was closed.
+ eval('jobwait([&channel], 1000)') -- Wait.
+ expected2.pty = (is_os('win') and '?' or '') -- pty stream was closed.
eq(expected2, eval('nvim_get_chan_info(&channel)'))
end)
end)
describe('nvim_call_atomic', function()
it('works', function()
- meths.buf_set_lines(0, 0, -1, true, {'first'})
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'first' })
local req = {
- {'nvim_get_current_line', {}},
- {'nvim_set_current_line', {'second'}},
+ { 'nvim_get_current_line', {} },
+ { 'nvim_set_current_line', { 'second' } },
}
- eq({{'first', NIL}, NIL}, meths.call_atomic(req))
- eq({'second'}, meths.buf_get_lines(0, 0, -1, true))
+ eq({ { 'first', NIL }, NIL }, api.nvim_call_atomic(req))
+ eq({ 'second' }, api.nvim_buf_get_lines(0, 0, -1, true))
end)
it('allows multiple return values', function()
local req = {
- {'nvim_set_var', {'avar', true}},
- {'nvim_set_var', {'bvar', 'string'}},
- {'nvim_get_var', {'avar'}},
- {'nvim_get_var', {'bvar'}},
+ { 'nvim_set_var', { 'avar', true } },
+ { 'nvim_set_var', { 'bvar', 'string' } },
+ { 'nvim_get_var', { 'avar' } },
+ { 'nvim_get_var', { 'bvar' } },
}
- eq({{NIL, NIL, true, 'string'}, NIL}, meths.call_atomic(req))
+ eq({ { NIL, NIL, true, 'string' }, NIL }, api.nvim_call_atomic(req))
end)
it('is aborted by errors in call', function()
- local error_types = meths.get_api_info()[2].error_types
+ local error_types = api.nvim_get_api_info()[2].error_types
local req = {
- {'nvim_set_var', {'one', 1}},
- {'nvim_buf_set_lines', {}},
- {'nvim_set_var', {'two', 2}},
+ { 'nvim_set_var', { 'one', 1 } },
+ { 'nvim_buf_set_lines', {} },
+ { 'nvim_set_var', { 'two', 2 } },
}
- eq({{NIL}, {1, error_types.Exception.id,
- 'Wrong number of arguments: expecting 5 but got 0'}},
- meths.call_atomic(req))
- eq(1, meths.get_var('one'))
- eq(false, pcall(meths.get_var, 'two'))
+ eq({
+ { NIL },
+ {
+ 1,
+ error_types.Exception.id,
+ 'Wrong number of arguments: expecting 5 but got 0',
+ },
+ }, api.nvim_call_atomic(req))
+ eq(1, api.nvim_get_var('one'))
+ eq(false, pcall(api.nvim_get_var, 'two'))
-- still returns all previous successful calls
req = {
- {'nvim_set_var', {'avar', 5}},
- {'nvim_set_var', {'bvar', 'string'}},
- {'nvim_get_var', {'avar'}},
- {'nvim_buf_get_lines', {0, 10, 20, true}},
- {'nvim_get_var', {'bvar'}},
+ { 'nvim_set_var', { 'avar', 5 } },
+ { 'nvim_set_var', { 'bvar', 'string' } },
+ { 'nvim_get_var', { 'avar' } },
+ { 'nvim_buf_get_lines', { 0, 10, 20, true } },
+ { 'nvim_get_var', { 'bvar' } },
}
- eq({{NIL, NIL, 5}, {3, error_types.Validation.id, 'Index out of bounds'}},
- meths.call_atomic(req))
+ eq(
+ { { NIL, NIL, 5 }, { 3, error_types.Validation.id, 'Index out of bounds' } },
+ api.nvim_call_atomic(req)
+ )
req = {
- {'i_am_not_a_method', {'xx'}},
- {'nvim_set_var', {'avar', 10}},
+ { 'i_am_not_a_method', { 'xx' } },
+ { 'nvim_set_var', { 'avar', 10 } },
}
- eq({{}, {0, error_types.Exception.id, 'Invalid method: i_am_not_a_method'}},
- meths.call_atomic(req))
- eq(5, meths.get_var('avar'))
+ eq(
+ { {}, { 0, error_types.Exception.id, 'Invalid method: i_am_not_a_method' } },
+ api.nvim_call_atomic(req)
+ )
+ eq(5, api.nvim_get_var('avar'))
end)
it('validation', function()
local req = {
- {'nvim_set_var', {'avar', 1}},
- {'nvim_set_var'},
- {'nvim_set_var', {'avar', 2}},
+ { 'nvim_set_var', { 'avar', 1 } },
+ { 'nvim_set_var' },
+ { 'nvim_set_var', { 'avar', 2 } },
}
- eq("Invalid 'calls' item: expected 2-item Array",
- pcall_err(meths.call_atomic, req))
+ eq("Invalid 'calls' item: expected 2-item Array", pcall_err(api.nvim_call_atomic, req))
-- call before was done, but not after
- eq(1, meths.get_var('avar'))
+ eq(1, api.nvim_get_var('avar'))
req = {
{ 'nvim_set_var', { 'bvar', { 2, 3 } } },
12,
}
- eq("Invalid 'calls' item: expected Array, got Integer",
- pcall_err(meths.call_atomic, req))
- eq({2,3}, meths.get_var('bvar'))
+ eq("Invalid 'calls' item: expected Array, got Integer", pcall_err(api.nvim_call_atomic, req))
+ eq({ 2, 3 }, api.nvim_get_var('bvar'))
req = {
- {'nvim_set_current_line', 'little line'},
- {'nvim_set_var', {'avar', 3}},
+ { 'nvim_set_current_line', 'little line' },
+ { 'nvim_set_var', { 'avar', 3 } },
}
- eq("Invalid call args: expected Array, got String",
- pcall_err(meths.call_atomic, req))
+ eq('Invalid call args: expected Array, got String', pcall_err(api.nvim_call_atomic, req))
-- call before was done, but not after
- eq(1, meths.get_var('avar'))
- eq({''}, meths.buf_get_lines(0, 0, -1, true))
+ eq(1, api.nvim_get_var('avar'))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, true))
end)
end)
describe('nvim_list_runtime_paths', function()
setup(function()
local pathsep = helpers.get_pathsep()
- mkdir_p('Xtest'..pathsep..'a')
- mkdir_p('Xtest'..pathsep..'b')
+ mkdir_p('Xtest' .. pathsep .. 'a')
+ mkdir_p('Xtest' .. pathsep .. 'b')
end)
teardown(function()
rmdir 'Xtest'
end)
before_each(function()
- meths.set_current_dir 'Xtest'
+ api.nvim_set_current_dir 'Xtest'
end)
it('returns nothing with empty &runtimepath', function()
- meths.set_option_value('runtimepath', '', {})
- eq({}, meths.list_runtime_paths())
+ api.nvim_set_option_value('runtimepath', '', {})
+ eq({}, api.nvim_list_runtime_paths())
end)
it('returns single runtimepath', function()
- meths.set_option_value('runtimepath', 'a', {})
- eq({'a'}, meths.list_runtime_paths())
+ api.nvim_set_option_value('runtimepath', 'a', {})
+ eq({ 'a' }, api.nvim_list_runtime_paths())
end)
it('returns two runtimepaths', function()
- meths.set_option_value('runtimepath', 'a,b', {})
- eq({'a', 'b'}, meths.list_runtime_paths())
+ api.nvim_set_option_value('runtimepath', 'a,b', {})
+ eq({ 'a', 'b' }, api.nvim_list_runtime_paths())
end)
it('returns empty strings when appropriate', function()
- meths.set_option_value('runtimepath', 'a,,b', {})
- eq({'a', '', 'b'}, meths.list_runtime_paths())
- meths.set_option_value('runtimepath', ',a,b', {})
- eq({'', 'a', 'b'}, meths.list_runtime_paths())
+ api.nvim_set_option_value('runtimepath', 'a,,b', {})
+ eq({ 'a', '', 'b' }, api.nvim_list_runtime_paths())
+ api.nvim_set_option_value('runtimepath', ',a,b', {})
+ eq({ '', 'a', 'b' }, api.nvim_list_runtime_paths())
-- Trailing "," is ignored. Use ",," if you really really want CWD.
- meths.set_option_value('runtimepath', 'a,b,', {})
- eq({'a', 'b'}, meths.list_runtime_paths())
- meths.set_option_value('runtimepath', 'a,b,,', {})
- eq({'a', 'b', ''}, meths.list_runtime_paths())
+ api.nvim_set_option_value('runtimepath', 'a,b,', {})
+ eq({ 'a', 'b' }, api.nvim_list_runtime_paths())
+ api.nvim_set_option_value('runtimepath', 'a,b,,', {})
+ eq({ 'a', 'b', '' }, api.nvim_list_runtime_paths())
end)
it('truncates too long paths', function()
local long_path = ('/a'):rep(8192)
- meths.set_option_value('runtimepath', long_path, {})
- local paths_list = meths.list_runtime_paths()
+ api.nvim_set_option_value('runtimepath', long_path, {})
+ local paths_list = api.nvim_list_runtime_paths()
eq({}, paths_list)
end)
end)
it('can throw exceptions', function()
- local status, err = pcall(nvim, 'get_option_value', 'invalid-option', {})
+ local status, err = pcall(api.nvim_get_option_value, 'invalid-option', {})
eq(false, status)
ok(err:match("Unknown 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_value', very_long_name, {})
+ local very_long_name = 'A' .. ('x'):rep(10000) .. 'Z'
+ local status, err = pcall(api.nvim_get_option_value, very_long_name, {})
eq(false, status)
eq(very_long_name, err:match('Ax+Z?'))
end)
- it("does not leak memory on incorrect argument types", function()
- local status, err = pcall(nvim, 'set_current_dir',{'not', 'a', 'dir'})
+ it('does not leak memory on incorrect argument types', function()
+ local status, err = pcall(api.nvim_set_current_dir, { 'not', 'a', 'dir' })
eq(false, status)
- ok(err:match(': Wrong type for argument 1 when calling nvim_set_current_dir, expecting String') ~= nil)
+ ok(
+ err:match(': Wrong type for argument 1 when calling nvim_set_current_dir, expecting String')
+ ~= nil
+ )
end)
describe('nvim_parse_expression', function()
before_each(function()
- meths.set_option_value('isident', '', {})
+ api.nvim_set_option_value('isident', '', {})
end)
local function simplify_east_api_node(line, east_api_node)
@@ -2589,21 +2758,26 @@ describe('API', function()
end
local typ = east_api_node.type
if typ == 'Register' then
- typ = typ .. ('(name=%s)'):format(
- tostring(intchar2lua(east_api_node.name)))
+ typ = typ .. ('(name=%s)'):format(tostring(intchar2lua(east_api_node.name)))
east_api_node.name = nil
elseif typ == 'PlainIdentifier' then
- typ = typ .. ('(scope=%s,ident=%s)'):format(
- tostring(intchar2lua(east_api_node.scope)), east_api_node.ident)
+ typ = typ
+ .. ('(scope=%s,ident=%s)'):format(
+ tostring(intchar2lua(east_api_node.scope)),
+ east_api_node.ident
+ )
east_api_node.scope = nil
east_api_node.ident = nil
elseif typ == 'PlainKey' then
typ = typ .. ('(key=%s)'):format(east_api_node.ident)
east_api_node.ident = nil
elseif typ == 'Comparison' then
- typ = typ .. ('(type=%s,inv=%u,ccs=%s)'):format(
- east_api_node.cmp_type, east_api_node.invert and 1 or 0,
- east_api_node.ccs_strategy)
+ typ = typ
+ .. ('(type=%s,inv=%u,ccs=%s)'):format(
+ east_api_node.cmp_type,
+ east_api_node.invert and 1 or 0,
+ east_api_node.ccs_strategy
+ )
east_api_node.ccs_strategy = nil
east_api_node.cmp_type = nil
east_api_node.invert = nil
@@ -2620,7 +2794,8 @@ describe('API', function()
typ = ('%s(scope=%s,ident=%s)'):format(
typ,
tostring(intchar2lua(east_api_node.scope)),
- east_api_node.ident)
+ east_api_node.ident
+ )
east_api_node.ident = nil
east_api_node.scope = nil
elseif typ == 'Environment' then
@@ -2628,24 +2803,30 @@ describe('API', function()
east_api_node.ident = nil
elseif typ == 'Assignment' then
local aug = east_api_node.augmentation
- if aug == '' then aug = 'Plain' end
+ if aug == '' then
+ aug = 'Plain'
+ end
typ = ('%s(%s)'):format(typ, aug)
east_api_node.augmentation = nil
end
typ = ('%s:%u:%u:%s'):format(
- typ, east_api_node.start[1], east_api_node.start[2],
- line:sub(east_api_node.start[2] + 1,
- east_api_node.start[2] + 1 + east_api_node.len - 1))
+ typ,
+ east_api_node.start[1],
+ east_api_node.start[2],
+ line:sub(east_api_node.start[2] + 1, east_api_node.start[2] + 1 + east_api_node.len - 1)
+ )
assert(east_api_node.start[2] + east_api_node.len - 1 <= #line)
for k, _ in pairs(east_api_node.start) do
- assert(({true, true})[k])
+ assert(({ true, true })[k])
end
east_api_node.start = nil
east_api_node.type = nil
east_api_node.len = nil
local can_simplify = true
for _, _ in pairs(east_api_node) do
- if can_simplify then can_simplify = false end
+ if can_simplify then
+ can_simplify = false
+ end
end
if can_simplify then
return typ
@@ -2662,7 +2843,7 @@ describe('API', function()
east_api.err.message = nil
end
if east_api.ast then
- east_api.ast = {simplify_east_api_node(line, east_api.ast)}
+ east_api.ast = { simplify_east_api_node(line, east_api.ast) }
if #east_api.ast == 0 then
east_api.ast = nil
end
@@ -2674,26 +2855,21 @@ describe('API', function()
end
local function simplify_east_hl(line, east_hl)
for i, v in ipairs(east_hl) do
- east_hl[i] = ('%s:%u:%u:%s'):format(
- v[4],
- v[1],
- v[2],
- line:sub(v[2] + 1, v[3]))
+ east_hl[i] = ('%s:%u:%u:%s'):format(v[4], v[1], v[2], line:sub(v[2] + 1, v[3]))
end
return east_hl
end
local FLAGS_TO_STR = {
- [0] = "",
- [1] = "m",
- [2] = "E",
- [3] = "mE",
- [4] = "l",
- [5] = "lm",
- [6] = "lE",
- [7] = "lmE",
+ [0] = '',
+ [1] = 'm',
+ [2] = 'E',
+ [3] = 'mE',
+ [4] = 'l',
+ [5] = 'lm',
+ [6] = 'lE',
+ [7] = 'lmE',
}
- local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs,
- nz_flags_exps)
+ local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs, nz_flags_exps)
if type(str) ~= 'string' then
return
end
@@ -2701,7 +2877,7 @@ describe('API', function()
nz_flags_exps = nz_flags_exps or {}
for _, flags in ipairs(opts.flags) do
local err, msg = pcall(function()
- local east_api = meths.parse_expression(str, FLAGS_TO_STR[flags], true)
+ local east_api = api.nvim_parse_expression(str, FLAGS_TO_STR[flags], true)
local east_hl = east_api.highlight
east_api.highlight = nil
local ast = simplify_east_api(str, east_api)
@@ -2734,37 +2910,39 @@ describe('API', function()
end)
if not err then
if type(msg) == 'table' then
- local merr, new_msg = pcall(
- format_string, 'table error:\n%s\n\n(%r)', msg.message, msg)
+ local merr, new_msg = pcall(format_string, 'table error:\n%s\n\n(%r)', msg.message, msg)
if merr then
msg = new_msg
else
- msg = format_string('table error without .message:\n(%r)',
- msg)
+ msg = format_string('table error without .message:\n(%r)', msg)
end
elseif type(msg) ~= 'string' then
msg = format_string('non-string non-table error:\n%r', msg)
end
- error(format_string('Error while processing test (%r, %s):\n%s',
- str, FLAGS_TO_STR[flags], msg))
+ error(
+ format_string(
+ 'Error while processing test (%r, %s):\n%s',
+ str,
+ FLAGS_TO_STR[flags],
+ msg
+ )
+ )
end
end
end
local function hl(group, str, shift)
return function(next_col)
local col = next_col + (shift or 0)
- return (('%s:%u:%u:%s'):format(
- 'Nvim' .. group,
- 0,
- col,
- str)), (col + #str)
+ return (('%s:%u:%u:%s'):format('Nvim' .. group, 0, col, str)), (col + #str)
end
end
local function fmtn(typ, args, rest)
- if (typ == 'UnknownFigure'
- or typ == 'DictLiteral'
- or typ == 'CurlyBracesIdentifier'
- or typ == 'Lambda') then
+ if
+ typ == 'UnknownFigure'
+ or typ == 'DictLiteral'
+ or typ == 'CurlyBracesIdentifier'
+ or typ == 'Lambda'
+ then
return ('%s%s'):format(typ, rest)
elseif typ == 'DoubleQuotedString' or typ == 'SingleQuotedString' then
if args:sub(-4) == 'NULL' then
@@ -2773,18 +2951,17 @@ describe('API', function()
return ('%s(%s)%s'):format(typ, args, rest)
end
end
- require('test.unit.viml.expressions.parser_tests')(
- it, _check_parsing, hl, fmtn)
+ require('test.unit.viml.expressions.parser_tests')(it, _check_parsing, hl, fmtn)
end)
describe('nvim_list_uis', function()
it('returns empty if --headless', function()
-- Test runner defaults to --headless.
- eq({}, nvim("list_uis"))
+ eq({}, api.nvim_list_uis())
end)
it('returns attached UIs', function()
local screen = Screen.new(20, 4)
- screen:attach({override=true})
+ screen:attach({ override = true })
local expected = {
{
chan = 1,
@@ -2806,10 +2983,10 @@ describe('API', function()
term_colors = 0,
term_name = '',
width = 20,
- }
+ },
}
- eq(expected, nvim("list_uis"))
+ eq(expected, api.nvim_list_uis())
screen:detach()
screen = Screen.new(44, 99)
@@ -2818,96 +2995,102 @@ describe('API', function()
expected[1].override = false
expected[1].width = 44
expected[1].height = 99
- eq(expected, nvim("list_uis"))
+ eq(expected, api.nvim_list_uis())
end)
end)
describe('nvim_create_namespace', function()
it('works', function()
- eq({}, meths.get_namespaces())
- eq(1, meths.create_namespace("ns-1"))
- eq(2, meths.create_namespace("ns-2"))
- eq(1, meths.create_namespace("ns-1"))
- eq({["ns-1"]=1, ["ns-2"]=2}, meths.get_namespaces())
- eq(3, meths.create_namespace(""))
- eq(4, meths.create_namespace(""))
- eq({["ns-1"]=1, ["ns-2"]=2}, meths.get_namespaces())
+ eq({}, api.nvim_get_namespaces())
+ eq(1, api.nvim_create_namespace('ns-1'))
+ eq(2, api.nvim_create_namespace('ns-2'))
+ eq(1, api.nvim_create_namespace('ns-1'))
+ eq({ ['ns-1'] = 1, ['ns-2'] = 2 }, api.nvim_get_namespaces())
+ eq(3, api.nvim_create_namespace(''))
+ eq(4, api.nvim_create_namespace(''))
+ eq({ ['ns-1'] = 1, ['ns-2'] = 2 }, api.nvim_get_namespaces())
end)
end)
describe('nvim_create_buf', function()
it('works', function()
- eq({id=2}, meths.create_buf(true, false))
- eq({id=3}, meths.create_buf(false, false))
- eq(' 1 %a "[No Name]" line 1\n'..
- ' 2 h "[No Name]" line 0',
- meths.command_output("ls"))
+ eq(2, api.nvim_create_buf(true, false))
+ eq(3, api.nvim_create_buf(false, false))
+ eq(
+ ' 1 %a "[No Name]" line 1\n'
+ .. ' 2 h "[No Name]" line 0',
+ command_output('ls')
+ )
-- current buffer didn't change
- eq({id=1}, meths.get_current_buf())
+ eq(1, api.nvim_get_current_buf())
local screen = Screen.new(20, 4)
screen:attach()
- meths.buf_set_lines(2, 0, -1, true, {"some text"})
- meths.set_current_buf(2)
- screen:expect([[
+ api.nvim_buf_set_lines(2, 0, -1, true, { 'some text' })
+ api.nvim_set_current_buf(2)
+ screen:expect(
+ [[
^some text |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]], {
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- })
+ ]],
+ {
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ }
+ )
end)
it('can change buftype before visiting', function()
- meths.set_option_value("hidden", false, {})
- eq({id=2}, meths.create_buf(true, false))
- 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())
+ api.nvim_set_option_value('hidden', false, {})
+ eq(2, api.nvim_create_buf(true, false))
+ api.nvim_set_option_value('buftype', 'nofile', { buf = 2 })
+ api.nvim_buf_set_lines(2, 0, -1, true, { 'test text' })
+ command('split | buffer 2')
+ eq(2, api.nvim_get_current_buf())
-- if the buf_set_option("buftype") didn't work, this would error out.
- command("close")
- eq({id=1}, meths.get_current_buf())
+ command('close')
+ eq(1, api.nvim_get_current_buf())
end)
- it("does not trigger BufEnter, BufWinEnter", function()
- command("let g:fired = v:false")
- command("au BufEnter,BufWinEnter * let g:fired = v:true")
+ it('does not trigger BufEnter, BufWinEnter', function()
+ command('let g:fired = v:false')
+ command('au BufEnter,BufWinEnter * let g:fired = v:true')
- eq({id=2}, meths.create_buf(true, false))
- meths.buf_set_lines(2, 0, -1, true, {"test", "text"})
+ eq(2, api.nvim_create_buf(true, false))
+ api.nvim_buf_set_lines(2, 0, -1, true, { 'test', 'text' })
eq(false, eval('g:fired'))
end)
it('TextChanged and TextChangedI do not trigger without changes', function()
- local buf = meths.create_buf(true, false)
+ local buf = api.nvim_create_buf(true, false)
command([[let g:changed = '']])
- meths.create_autocmd({'TextChanged', 'TextChangedI'}, {
+ api.nvim_create_autocmd({ 'TextChanged', 'TextChangedI' }, {
buffer = buf,
command = 'let g:changed ..= mode()',
})
- meths.set_current_buf(buf)
+ api.nvim_set_current_buf(buf)
feed('i')
- eq('', meths.get_var('changed'))
+ eq('', api.nvim_get_var('changed'))
end)
it('scratch-buffer', function()
- eq({id=2}, meths.create_buf(false, true))
- eq({id=3}, meths.create_buf(true, true))
- eq({id=4}, meths.create_buf(true, true))
+ eq(2, api.nvim_create_buf(false, true))
+ eq(3, api.nvim_create_buf(true, true))
+ eq(4, api.nvim_create_buf(true, true))
local scratch_bufs = { 2, 3, 4 }
- eq(' 1 %a "[No Name]" line 1\n'..
- ' 3 h "[Scratch]" line 0\n'..
- ' 4 h "[Scratch]" line 0',
- exec_capture('ls'))
+ eq(
+ ' 1 %a "[No Name]" line 1\n'
+ .. ' 3 h "[Scratch]" line 0\n'
+ .. ' 4 h "[Scratch]" line 0',
+ exec_capture('ls')
+ )
-- current buffer didn't change
- eq({id=1}, meths.get_current_buf())
+ eq(1, api.nvim_get_current_buf())
local screen = Screen.new(20, 4)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
})
screen:attach()
@@ -2915,35 +3098,33 @@ describe('API', function()
-- Editing a scratch-buffer does NOT change its properties.
--
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.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}))
+ api.nvim_buf_set_lines(edited_buf, 0, -1, true, { 'some text' })
+ for _, b in ipairs(scratch_bufs) do
+ eq('nofile', api.nvim_get_option_value('buftype', { buf = b }))
+ eq('hide', api.nvim_get_option_value('bufhidden', { buf = b }))
+ eq(false, api.nvim_get_option_value('swapfile', { buf = b }))
+ eq(false, api.nvim_get_option_value('modeline', { buf = b }))
end
--
-- Visiting a scratch-buffer DOES NOT change its properties.
--
- meths.set_current_buf(edited_buf)
+ api.nvim_set_current_buf(edited_buf)
screen:expect([[
^some text |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
- 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}))
+ eq('nofile', api.nvim_get_option_value('buftype', { buf = edited_buf }))
+ eq('hide', api.nvim_get_option_value('bufhidden', { buf = edited_buf }))
+ eq(false, api.nvim_get_option_value('swapfile', { buf = edited_buf }))
+ eq(false, api.nvim_get_option_value('modeline', { buf = edited_buf }))
-- Scratch buffer can be wiped without error.
command('bwipe')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
end)
@@ -2959,117 +3140,121 @@ describe('API', function()
describe('nvim_get_runtime_file', function()
local p = helpers.alter_slashes
it('can find files', function()
- eq({}, meths.get_runtime_file("bork.borkbork", false))
- eq({}, meths.get_runtime_file("bork.borkbork", true))
- eq(1, #meths.get_runtime_file("autoload/msgpack.vim", false))
- eq(1, #meths.get_runtime_file("autoload/msgpack.vim", true))
- local val = meths.get_runtime_file("autoload/remote/*.vim", true)
+ eq({}, api.nvim_get_runtime_file('bork.borkbork', false))
+ eq({}, api.nvim_get_runtime_file('bork.borkbork', true))
+ eq(1, #api.nvim_get_runtime_file('autoload/msgpack.vim', false))
+ eq(1, #api.nvim_get_runtime_file('autoload/msgpack.vim', true))
+ local val = api.nvim_get_runtime_file('autoload/remote/*.vim', true)
eq(2, #val)
- if endswith(val[1], "define.vim") then
- ok(endswith(val[1], p"autoload/remote/define.vim"))
- ok(endswith(val[2], p"autoload/remote/host.vim"))
+ if endswith(val[1], 'define.vim') then
+ ok(endswith(val[1], p 'autoload/remote/define.vim'))
+ ok(endswith(val[2], p 'autoload/remote/host.vim'))
else
- ok(endswith(val[1], p"autoload/remote/host.vim"))
- ok(endswith(val[2], p"autoload/remote/define.vim"))
+ ok(endswith(val[1], p 'autoload/remote/host.vim'))
+ ok(endswith(val[2], p 'autoload/remote/define.vim'))
end
- val = meths.get_runtime_file("autoload/remote/*.vim", false)
+ val = api.nvim_get_runtime_file('autoload/remote/*.vim', false)
eq(1, #val)
- ok(endswith(val[1], p"autoload/remote/define.vim")
- or endswith(val[1], p"autoload/remote/host.vim"))
+ ok(
+ endswith(val[1], p 'autoload/remote/define.vim')
+ or endswith(val[1], p 'autoload/remote/host.vim')
+ )
- val = meths.get_runtime_file("lua", true)
+ val = api.nvim_get_runtime_file('lua', true)
eq(1, #val)
- ok(endswith(val[1], p"lua"))
+ ok(endswith(val[1], p 'lua'))
- val = meths.get_runtime_file("lua/vim", true)
+ val = api.nvim_get_runtime_file('lua/vim', true)
eq(1, #val)
- ok(endswith(val[1], p"lua/vim"))
+ ok(endswith(val[1], p 'lua/vim'))
end)
it('can find directories', function()
- local val = meths.get_runtime_file("lua/", true)
+ local val = api.nvim_get_runtime_file('lua/', true)
eq(1, #val)
- ok(endswith(val[1], p"lua/"))
+ ok(endswith(val[1], p 'lua/'))
- val = meths.get_runtime_file("lua/vim/", true)
+ val = api.nvim_get_runtime_file('lua/vim/', true)
eq(1, #val)
- ok(endswith(val[1], p"lua/vim/"))
+ ok(endswith(val[1], p 'lua/vim/'))
- eq({}, meths.get_runtime_file("foobarlang/", true))
+ eq({}, api.nvim_get_runtime_file('foobarlang/', true))
end)
it('can handle bad patterns', function()
skip(is_os('win'))
- eq("Vim:E220: Missing }.", pcall_err(meths.get_runtime_file, "{", false))
+ eq('Vim:E220: Missing }.', pcall_err(api.nvim_get_runtime_file, '{', false))
- eq('Vim(echo):E5555: API call: Vim:E220: Missing }.',
- exc_exec("echo nvim_get_runtime_file('{', v:false)"))
+ eq(
+ 'Vim(echo):E5555: API call: Vim:E220: Missing }.',
+ exc_exec("echo nvim_get_runtime_file('{', v:false)")
+ )
end)
end)
describe('nvim_get_all_options_info', function()
it('should have key value pairs of option names', function()
- local options_info = meths.get_all_options_info()
+ local options_info = api.nvim_get_all_options_info()
neq(nil, options_info.listchars)
neq(nil, options_info.tabstop)
- eq(meths.get_option_info'winhighlight', options_info.winhighlight)
+ eq(api.nvim_get_option_info 'winhighlight', options_info.winhighlight)
end)
it('should not crash when echoed', function()
- meths.exec2("echo nvim_get_all_options_info()", { output = true })
+ api.nvim_exec2('echo nvim_get_all_options_info()', { output = true })
end)
end)
describe('nvim_get_option_info', function()
it('should error for unknown options', function()
- eq("Invalid option (not found): 'bogus'", pcall_err(meths.get_option_info, 'bogus'))
+ eq("Invalid option (not found): 'bogus'", pcall_err(api.nvim_get_option_info, 'bogus'))
end)
it('should return the same options for short and long name', function()
- eq(meths.get_option_info'winhl', meths.get_option_info'winhighlight')
+ eq(api.nvim_get_option_info 'winhl', api.nvim_get_option_info 'winhighlight')
end)
it('should have information about window options', function()
eq({
allows_duplicates = false,
- commalist = true;
- default = "";
- flaglist = false;
- global_local = false;
- last_set_chan = 0;
- last_set_linenr = 0;
- last_set_sid = 0;
- name = "winhighlight";
- scope = "win";
- shortname = "winhl";
- type = "string";
- was_set = false;
- }, meths.get_option_info'winhl')
+ commalist = true,
+ default = '',
+ flaglist = false,
+ global_local = false,
+ last_set_chan = 0,
+ last_set_linenr = 0,
+ last_set_sid = 0,
+ name = 'winhighlight',
+ scope = 'win',
+ shortname = 'winhl',
+ type = 'string',
+ was_set = false,
+ }, api.nvim_get_option_info 'winhl')
end)
it('should have information about buffer options', function()
eq({
allows_duplicates = true,
commalist = false,
- default = "",
+ default = '',
flaglist = false,
global_local = false,
last_set_chan = 0,
last_set_linenr = 0,
last_set_sid = 0,
- name = "filetype",
- scope = "buf",
- shortname = "ft",
- type = "string",
- was_set = false
- }, meths.get_option_info'filetype')
+ name = 'filetype',
+ scope = 'buf',
+ shortname = 'ft',
+ type = 'string',
+ was_set = false,
+ }, api.nvim_get_option_info 'filetype')
end)
it('should have information about global options', function()
-- precondition: the option was changed from its default
-- in test setup.
- eq(false, meths.get_option_value('showcmd', {}))
+ eq(false, api.nvim_get_option_value('showcmd', {}))
eq({
allows_duplicates = true,
@@ -3080,14 +3265,14 @@ describe('API', function()
last_set_chan = 0,
last_set_linenr = 0,
last_set_sid = -2,
- name = "showcmd",
- scope = "global",
- shortname = "sc",
- type = "boolean",
- was_set = true
- }, meths.get_option_info'showcmd')
+ name = 'showcmd',
+ scope = 'global',
+ shortname = 'sc',
+ type = 'boolean',
+ was_set = true,
+ }, api.nvim_get_option_info 'showcmd')
- meths.set_option_value('showcmd', true, {})
+ api.nvim_set_option_value('showcmd', true, {})
eq({
allows_duplicates = true,
@@ -3098,12 +3283,12 @@ describe('API', function()
last_set_chan = 1,
last_set_linenr = 0,
last_set_sid = -9,
- name = "showcmd",
- scope = "global",
- shortname = "sc",
- type = "boolean",
- was_set = true
- }, meths.get_option_info'showcmd')
+ name = 'showcmd',
+ scope = 'global',
+ shortname = 'sc',
+ type = 'boolean',
+ was_set = true,
+ }, api.nvim_get_option_info 'showcmd')
end)
end)
@@ -3114,7 +3299,9 @@ describe('API', function()
before_each(function()
fname = tmpname()
- write_file(fname, [[
+ write_file(
+ fname,
+ [[
setglobal dictionary=mydict " 1, global-local (buffer)
setlocal formatprg=myprg " 2, global-local (buffer)
setglobal equalprg=prg1 " 3, global-local (buffer)
@@ -3124,21 +3311,22 @@ describe('API', function()
setglobal showbreak=aaa " 7, global-local (window)
setlocal showbreak=bbb " 8, global-local (window)
setglobal completeopt=menu " 9, global
- ]])
+ ]]
+ )
exec_lua 'vim.cmd.vsplit()'
- meths.create_buf(false, false)
+ api.nvim_create_buf(false, false)
- bufs = meths.list_bufs()
- wins = meths.list_wins()
+ bufs = api.nvim_list_bufs()
+ wins = api.nvim_list_wins()
- meths.win_set_buf(wins[1].id, bufs[1].id)
- meths.win_set_buf(wins[2].id, bufs[2].id)
+ api.nvim_win_set_buf(wins[1], bufs[1])
+ api.nvim_win_set_buf(wins[2], bufs[2])
- meths.set_current_win(wins[2].id)
- meths.exec('source ' .. fname, false)
+ api.nvim_set_current_win(wins[2])
+ api.nvim_exec('source ' .. fname, false)
- meths.set_current_win(wins[1].id)
+ api.nvim_set_current_win(wins[1])
end)
after_each(function()
@@ -3146,12 +3334,13 @@ describe('API', function()
end)
it('should return option information', function()
- eq(meths.get_option_info('dictionary'), meths.get_option_info2('dictionary', {})) -- buffer
- eq(meths.get_option_info('fillchars'), meths.get_option_info2('fillchars', {})) -- window
- eq(meths.get_option_info('completeopt'), meths.get_option_info2('completeopt', {})) -- global
+ eq(api.nvim_get_option_info('dictionary'), api.nvim_get_option_info2('dictionary', {})) -- buffer
+ eq(api.nvim_get_option_info('fillchars'), api.nvim_get_option_info2('fillchars', {})) -- window
+ eq(api.nvim_get_option_info('completeopt'), api.nvim_get_option_info2('completeopt', {})) -- global
end)
describe('last set', function()
+ -- stylua: ignore
local tests = {
{desc="(buf option, global requested, global set) points to global", linenr=1, sid=1, args={'dictionary', {scope='global'}}},
{desc="(buf option, global requested, local set) is not set", linenr=0, sid=0, args={'formatprg', {scope='global'}}},
@@ -3179,21 +3368,21 @@ describe('API', function()
for _, t in pairs(tests) do
it(t.desc, function()
-- Switch to the target buffer/window so that curbuf/curwin are used.
- meths.set_current_win(wins[2].id)
- local info = meths.get_option_info2(unpack(t.args))
+ api.nvim_set_current_win(wins[2])
+ local info = api.nvim_get_option_info2(unpack(t.args))
eq(t.linenr, info.last_set_linenr)
eq(t.sid, info.last_set_sid)
end)
end
it('is provided for cross-buffer requests', function()
- local info = meths.get_option_info2('formatprg', {buf=bufs[2].id})
+ local info = api.nvim_get_option_info2('formatprg', { buf = bufs[2] })
eq(2, info.last_set_linenr)
eq(1, info.last_set_sid)
end)
it('is provided for cross-window requests', function()
- local info = meths.get_option_info2('listchars', {win=wins[2].id})
+ local info = api.nvim_get_option_info2('listchars', { win = wins[2] })
eq(6, info.last_set_linenr)
eq(1, info.last_set_sid)
end)
@@ -3207,11 +3396,11 @@ describe('API', function()
screen = Screen.new(40, 8)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {bold = true, foreground = Screen.colors.SeaGreen},
- [2] = {bold = true, reverse = true},
- [3] = {foreground = Screen.colors.Brown, bold = true}, -- Statement
- [4] = {foreground = Screen.colors.SlateBlue}, -- Special
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [2] = { bold = true, reverse = true },
+ [3] = { foreground = Screen.colors.Brown, bold = true }, -- Statement
+ [4] = { foreground = Screen.colors.SlateBlue }, -- Special
})
command('highlight Statement gui=bold guifg=Brown')
command('highlight Special guifg=SlateBlue')
@@ -3219,60 +3408,57 @@ describe('API', function()
it('should clear cmdline message before echo', function()
feed(':call nvim_echo([["msg"]], v:false, {})<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
msg |
- ]]}
+ ]],
+ }
end)
it('can show highlighted line', function()
- nvim_async("echo", {{"msg_a"}, {"msg_b", "Statement"}, {"msg_c", "Special"}}, true, {})
- screen:expect{grid=[[
+ async_meths.nvim_echo(
+ { { 'msg_a' }, { 'msg_b', 'Statement' }, { 'msg_c', 'Special' } },
+ true,
+ {}
+ )
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
msg_a{3:msg_b}{4:msg_c} |
- ]]}
+ ]],
+ }
end)
it('can show highlighted multiline', function()
- nvim_async("echo", {{"msg_a\nmsg_a", "Statement"}, {"msg_b", "Special"}}, true, {})
- screen:expect{grid=[[
+ async_meths.nvim_echo({ { 'msg_a\nmsg_a', 'Statement' }, { 'msg_b', 'Special' } }, true, {})
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2: }|
{3:msg_a} |
{3:msg_a}{4:msg_b} |
{1:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
it('can save message history', function()
- nvim('command', 'set cmdheight=2') -- suppress Press ENTER
- nvim("echo", {{"msg\nmsg"}, {"msg"}}, true, {})
- eq("msg\nmsgmsg", exec_capture('messages'))
+ command('set cmdheight=2') -- suppress Press ENTER
+ api.nvim_echo({ { 'msg\nmsg' }, { 'msg' } }, true, {})
+ eq('msg\nmsgmsg', exec_capture('messages'))
end)
it('can disable saving message history', function()
- nvim('command', 'set cmdheight=2') -- suppress Press ENTER
- nvim_async("echo", {{"msg\nmsg"}, {"msg"}}, false, {})
- eq("", exec_capture('messages'))
+ command('set cmdheight=2') -- suppress Press ENTER
+ async_meths.nvim_echo({ { 'msg\nmsg' }, { 'msg' } }, false, {})
+ eq('', exec_capture('messages'))
end)
end)
-
describe('nvim_open_term', function()
local screen
@@ -3280,24 +3466,37 @@ describe('API', function()
screen = Screen.new(100, 35)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {background = Screen.colors.Plum1};
- [2] = {background = tonumber('0xffff40'), bg_indexed = true};
- [3] = {background = Screen.colors.Plum1, fg_indexed = true, foreground = tonumber('0x00e000')};
- [4] = {bold = true, reverse = true, background = Screen.colors.Plum1};
- [5] = {foreground = Screen.colors.Blue, background = Screen.colors.LightMagenta, bold = true};
- [6] = {bold = true};
- [7] = {reverse = true, background = Screen.colors.LightMagenta};
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { background = Screen.colors.Plum1 },
+ [2] = { background = tonumber('0xffff40'), bg_indexed = true },
+ [3] = {
+ background = Screen.colors.Plum1,
+ fg_indexed = true,
+ foreground = tonumber('0x00e000'),
+ },
+ [4] = { bold = true, reverse = true, background = Screen.colors.Plum1 },
+ [5] = {
+ foreground = Screen.colors.Blue,
+ background = Screen.colors.LightMagenta,
+ bold = true,
+ },
+ [6] = { bold = true },
+ [7] = { reverse = true, background = Screen.colors.LightMagenta },
})
end)
it('can batch process sequences', function()
- local b = meths.create_buf(true,true)
- meths.open_win(b, false, {width=79, height=31, row=1, col=1, relative='editor'})
- local t = meths.open_term(b, {})
-
- meths.chan_send(t, io.open("test/functional/fixtures/smile2.cat", "r"):read("*a"))
- screen:expect{grid=[[
+ local b = api.nvim_create_buf(true, true)
+ api.nvim_open_win(
+ b,
+ false,
+ { width = 79, height = 31, row = 1, col = 1, relative = 'editor' }
+ )
+ local t = api.nvim_open_term(b, {})
+
+ api.nvim_chan_send(t, io.open('test/functional/fixtures/smile2.cat', 'r'):read('*a'))
+ screen:expect {
+ grid = [[
^ |
{0:~}{1::smile }{0: }|
{0:~}{1: }{2:oooo$$$$$$$$$$$$oooo}{1: }{0: }|
@@ -3330,15 +3529,17 @@ describe('API', function()
{0:~}{3:Press ENTER or type command to continue}{1: }{0: }|
{0:~}{4:term://~/config2/docs/pres//32693:vim --clean +smile 29,39 All}{0: }|
{0:~}{1::call nvim__screenshot("smile2.cat") }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]]}
+ ]],
+ }
end)
it('can handle input', function()
screen:try_resize(50, 10)
- eq({3, 2}, exec_lua [[
+ eq(
+ { 3, 2 },
+ exec_lua [[
buf = vim.api.nvim_create_buf(1,1)
stream = ''
@@ -3354,251 +3555,297 @@ describe('API', function()
term = vim.api.nvim_open_term(buf, {on_input=input})
vim.api.nvim_open_win(buf, true, {width=40, height=5, row=1, col=1, relative='editor'})
return {term, buf}
- ]])
+ ]]
+ )
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{0:~}{1:^ }{0: }|
- {0:~}{1: }{0: }|
- {0:~}{1: }{0: }|
- {0:~}{1: }{0: }|
- {0:~}{1: }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~}{1: }{0: }|*4
+ {0:~ }|*3
|
- ]]}
+ ]],
+ }
feed 'iba<c-x>bla'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{0:~}{7: }{1: }{0: }|
- {0:~}{1: }{0: }|
- {0:~}{1: }{0: }|
- {0:~}{1: }{0: }|
- {0:~}{1: }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~}{1: }{0: }|*4
+ {0:~ }|*3
{6:-- TERMINAL --} |
- ]]}
+ ]],
+ }
eq('ba\024bla', exec_lua [[ return stream ]])
- eq({3,2}, exec_lua [[ return vals ]])
+ eq({ 3, 2 }, exec_lua [[ return vals ]])
exec_lua [[ do_the_echo = true ]]
feed 'herrejösses!'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{0:~}{1:herrejösses!}{7: }{1: }{0: }|
- {0:~}{1: }{0: }|
- {0:~}{1: }{0: }|
- {0:~}{1: }{0: }|
- {0:~}{1: }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~}{1: }{0: }|*4
+ {0:~ }|*3
{6:-- TERMINAL --} |
- ]]}
+ ]],
+ }
eq('ba\024blaherrejösses!', exec_lua [[ return stream ]])
end)
end)
describe('nvim_del_mark', function()
it('works', function()
- local buf = meths.create_buf(false,true)
- meths.buf_set_lines(buf, -1, -1, true, {'a', 'bit of', 'text'})
- eq(true, meths.buf_set_mark(buf, 'F', 2, 2, {}))
- eq(true, meths.del_mark('F'))
- eq({0, 0}, meths.buf_get_mark(buf, 'F'))
+ local buf = api.nvim_create_buf(false, true)
+ api.nvim_buf_set_lines(buf, -1, -1, true, { 'a', 'bit of', 'text' })
+ eq(true, api.nvim_buf_set_mark(buf, 'F', 2, 2, {}))
+ eq(true, api.nvim_del_mark('F'))
+ eq({ 0, 0 }, api.nvim_buf_get_mark(buf, 'F'))
end)
it('validation', function()
- eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(meths.del_mark, 'f'))
- eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(meths.del_mark, '!'))
- eq("Invalid mark name (must be a single char): 'fail'", pcall_err(meths.del_mark, 'fail'))
+ eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(api.nvim_del_mark, 'f'))
+ eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(api.nvim_del_mark, '!'))
+ eq("Invalid mark name (must be a single char): 'fail'", pcall_err(api.nvim_del_mark, 'fail'))
end)
end)
describe('nvim_get_mark', function()
it('works', function()
- local buf = meths.create_buf(false,true)
- meths.buf_set_lines(buf, -1, -1, true, {'a', 'bit of', 'text'})
- meths.buf_set_mark(buf, 'F', 2, 2, {})
- meths.buf_set_name(buf, "mybuf")
- local mark = meths.get_mark('F', {})
+ local buf = api.nvim_create_buf(false, true)
+ api.nvim_buf_set_lines(buf, -1, -1, true, { 'a', 'bit of', 'text' })
+ api.nvim_buf_set_mark(buf, 'F', 2, 2, {})
+ api.nvim_buf_set_name(buf, 'mybuf')
+ local mark = api.nvim_get_mark('F', {})
-- Compare the path tail only
- assert(string.find(mark[4], "mybuf$"))
- eq({2, 2, buf.id, mark[4]}, mark)
+ assert(string.find(mark[4], 'mybuf$'))
+ eq({ 2, 2, buf, mark[4] }, mark)
end)
it('validation', function()
- eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(meths.get_mark, 'f', {}))
- eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(meths.get_mark, '!', {}))
- eq("Invalid mark name (must be a single char): 'fail'", pcall_err(meths.get_mark, 'fail', {}))
+ eq("Invalid mark name (must be file/uppercase): 'f'", pcall_err(api.nvim_get_mark, 'f', {}))
+ eq("Invalid mark name (must be file/uppercase): '!'", pcall_err(api.nvim_get_mark, '!', {}))
+ eq(
+ "Invalid mark name (must be a single char): 'fail'",
+ pcall_err(api.nvim_get_mark, 'fail', {})
+ )
end)
it('returns the expected when mark is not set', function()
- eq(true, meths.del_mark('A'))
- eq({0, 0, 0, ''}, meths.get_mark('A', {}))
+ eq(true, api.nvim_del_mark('A'))
+ eq({ 0, 0, 0, '' }, api.nvim_get_mark('A', {}))
end)
it('works with deleted buffers', function()
local fname = tmpname()
write_file(fname, 'a\nbit of\text')
- nvim("command", "edit " .. fname)
- local buf = meths.get_current_buf()
+ command('edit ' .. fname)
+ local buf = api.nvim_get_current_buf()
- meths.buf_set_mark(buf, 'F', 2, 2, {})
- nvim("command", "new") -- Create new buf to avoid :bd failing
- nvim("command", "bd! " .. buf.id)
+ api.nvim_buf_set_mark(buf, 'F', 2, 2, {})
+ command('new') -- Create new buf to avoid :bd failing
+ command('bd! ' .. buf)
os.remove(fname)
- local mark = meths.get_mark('F', {})
+ local mark = api.nvim_get_mark('F', {})
-- To avoid comparing relative vs absolute path
local mfname = mark[4]
local tail_patt = [[[\/][^\/]*$]]
-- tail of paths should be equals
eq(fname:match(tail_patt), mfname:match(tail_patt))
- eq({2, 2, buf.id, mark[4]}, mark)
+ eq({ 2, 2, buf, mark[4] }, mark)
end)
end)
+
describe('nvim_eval_statusline', function()
it('works', function()
eq({
- str = '%StatusLineStringWithHighlights',
- width = 31
- },
- meths.eval_statusline(
- '%%StatusLineString%#WarningMsg#WithHighlights',
- {}))
+ str = '%StatusLineStringWithHighlights',
+ width = 31,
+ }, api.nvim_eval_statusline('%%StatusLineString%#WarningMsg#WithHighlights', {}))
end)
- it('doesn\'t exceed maxwidth', function()
+
+ it("doesn't exceed maxwidth", function()
eq({
- str = 'Should be trun>',
- width = 15
- },
- meths.eval_statusline(
- 'Should be truncated%<',
- { maxwidth = 15 }))
- end)
- it('supports ASCII fillchar', function()
- eq({ str = 'a~~~b', width = 5 },
- meths.eval_statusline('a%=b', { fillchar = '~', maxwidth = 5 }))
- end)
- it('supports single-width multibyte fillchar', function()
- eq({ str = 'aâ”â”â”b', width = 5 },
- meths.eval_statusline('a%=b', { fillchar = 'â”', maxwidth = 5 }))
- end)
- it('treats double-width fillchar as single-width', function()
- eq({ str = 'a哦哦哦b', width = 5 },
- meths.eval_statusline('a%=b', { fillchar = '哦', maxwidth = 5 }))
- end)
- it('treats control character fillchar as single-width', function()
- eq({ str = 'a\031\031\031b', width = 5 },
- meths.eval_statusline('a%=b', { fillchar = '\031', maxwidth = 5 }))
- end)
+ str = 'Should be trun>',
+ width = 15,
+ }, api.nvim_eval_statusline('Should be truncated%<', { maxwidth = 15 }))
+ end)
+
+ it('has correct default fillchar', function()
+ local oldwin = api.nvim_get_current_win()
+ command('set fillchars=stl:#,stlnc:$,wbr:%')
+ command('new')
+ eq({ str = 'a###b', width = 5 }, api.nvim_eval_statusline('a%=b', { maxwidth = 5 }))
+ eq(
+ { str = 'a$$$b', width = 5 },
+ api.nvim_eval_statusline('a%=b', { winid = oldwin, maxwidth = 5 })
+ )
+ eq(
+ { str = 'a%%%b', width = 5 },
+ api.nvim_eval_statusline('a%=b', { use_winbar = true, maxwidth = 5 })
+ )
+ eq(
+ { str = 'a b', width = 5 },
+ api.nvim_eval_statusline('a%=b', { use_tabline = true, maxwidth = 5 })
+ )
+ eq(
+ { str = 'a b', width = 5 },
+ api.nvim_eval_statusline('a%=b', { use_statuscol_lnum = 1, maxwidth = 5 })
+ )
+ end)
+
+ for fc, desc in pairs({
+ ['~'] = 'supports ASCII fillchar',
+ ['â”'] = 'supports single-width multibyte fillchar',
+ ['c̳'] = 'supports single-width fillchar with composing',
+ ['哦'] = 'treats double-width fillchar as single-width',
+ ['\031'] = 'treats control character fillchar as single-width',
+ }) do
+ it(desc, function()
+ eq(
+ { str = 'a' .. fc:rep(3) .. 'b', width = 5 },
+ api.nvim_eval_statusline('a%=b', { fillchar = fc, maxwidth = 5 })
+ )
+ eq(
+ { str = 'a' .. fc:rep(3) .. 'b', width = 5 },
+ api.nvim_eval_statusline('a%=b', { fillchar = fc, use_winbar = true, maxwidth = 5 })
+ )
+ eq(
+ { str = 'a' .. fc:rep(3) .. 'b', width = 5 },
+ api.nvim_eval_statusline('a%=b', { fillchar = fc, use_tabline = true, maxwidth = 5 })
+ )
+ eq(
+ { str = 'a' .. fc:rep(3) .. 'b', width = 5 },
+ api.nvim_eval_statusline('a%=b', { fillchar = fc, use_statuscol_lnum = 1, maxwidth = 5 })
+ )
+ end)
+ end
+
it('rejects multiple-character fillchar', function()
- eq("Invalid 'fillchar': expected single character",
- pcall_err(meths.eval_statusline, '', { fillchar = 'aa' }))
+ eq(
+ "Invalid 'fillchar': expected single character",
+ pcall_err(api.nvim_eval_statusline, '', { fillchar = 'aa' })
+ )
end)
+
it('rejects empty string fillchar', function()
- eq("Invalid 'fillchar': expected single character",
- pcall_err(meths.eval_statusline, '', { fillchar = '' }))
+ eq(
+ "Invalid 'fillchar': expected single character",
+ pcall_err(api.nvim_eval_statusline, '', { fillchar = '' })
+ )
end)
+
it('rejects non-string fillchar', function()
- eq("Invalid 'fillchar': expected String, got Integer",
- pcall_err(meths.eval_statusline, '', { fillchar = 1 }))
+ eq(
+ "Invalid 'fillchar': expected String, got Integer",
+ pcall_err(api.nvim_eval_statusline, '', { fillchar = 1 })
+ )
end)
+
it('rejects invalid string', function()
- eq('E539: Illegal character <}>',
- pcall_err(meths.eval_statusline, '%{%}', {}))
+ eq('E539: Illegal character <}>', pcall_err(api.nvim_eval_statusline, '%{%}', {}))
end)
+
it('supports various items', function()
- eq({ str = '0', width = 1 },
- meths.eval_statusline('%l', { maxwidth = 5 }))
+ eq({ str = '0', width = 1 }, api.nvim_eval_statusline('%l', { maxwidth = 5 }))
command('set readonly')
- eq({ str = '[RO]', width = 4 },
- meths.eval_statusline('%r', { maxwidth = 5 }))
+ eq({ str = '[RO]', width = 4 }, api.nvim_eval_statusline('%r', { maxwidth = 5 }))
local screen = Screen.new(80, 24)
screen:attach()
command('set showcmd')
feed('1234')
- screen:expect({any = '1234'})
- eq({ str = '1234', width = 4 },
- meths.eval_statusline('%S', { maxwidth = 5 }))
+ screen:expect({ any = '1234' })
+ eq({ str = '1234', width = 4 }, api.nvim_eval_statusline('%S', { maxwidth = 5 }))
feed('56')
- screen:expect({any = '123456'})
- eq({ str = '<3456', width = 5 },
- meths.eval_statusline('%S', { maxwidth = 5 }))
+ screen:expect({ any = '123456' })
+ eq({ str = '<3456', width = 5 }, api.nvim_eval_statusline('%S', { maxwidth = 5 }))
end)
+
describe('highlight parsing', function()
it('works', function()
- eq({
- str = "TextWithWarningHighlightTextWithUserHighlight",
+ eq(
+ {
+ str = 'TextWithWarningHighlightTextWithUserHighlight',
width = 45,
highlights = {
{ start = 0, group = 'WarningMsg' },
- { start = 24, group = 'User1' }
+ { start = 24, group = 'User1' },
},
},
- meths.eval_statusline(
+ api.nvim_eval_statusline(
'%#WarningMsg#TextWithWarningHighlight%1*TextWithUserHighlight',
- { highlights = true }))
+ { highlights = true }
+ )
+ )
end)
+
it('works with no highlight', function()
eq({
- str = "TextWithNoHighlight",
- width = 19,
- highlights = {
- { start = 0, group = 'StatusLine' },
- },
+ str = 'TextWithNoHighlight',
+ width = 19,
+ highlights = {
+ { start = 0, group = 'StatusLine' },
},
- meths.eval_statusline(
- 'TextWithNoHighlight',
- { highlights = true }))
+ }, api.nvim_eval_statusline('TextWithNoHighlight', { highlights = true }))
end)
+
it('works with inactive statusline', function()
command('split')
-
- eq({
+ eq(
+ {
str = 'TextWithNoHighlightTextWithWarningHighlight',
width = 43,
highlights = {
{ start = 0, group = 'StatusLineNC' },
- { start = 19, group = 'WarningMsg' }
- }
+ { start = 19, group = 'WarningMsg' },
+ },
},
- meths.eval_statusline(
+ api.nvim_eval_statusline(
'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight',
- { winid = meths.list_wins()[2].id, highlights = true }))
+ { winid = api.nvim_list_wins()[2], highlights = true }
+ )
+ )
end)
+
it('works with tabline', function()
- eq({
+ eq(
+ {
str = 'TextWithNoHighlightTextWithWarningHighlight',
width = 43,
highlights = {
{ start = 0, group = 'TabLineFill' },
- { start = 19, group = 'WarningMsg' }
- }
+ { start = 19, group = 'WarningMsg' },
+ },
},
- meths.eval_statusline(
+ api.nvim_eval_statusline(
'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight',
- { use_tabline = true, highlights = true }))
+ { use_tabline = true, highlights = true }
+ )
+ )
end)
+
it('works with winbar', function()
- eq({
+ eq(
+ {
str = 'TextWithNoHighlightTextWithWarningHighlight',
width = 43,
highlights = {
{ start = 0, group = 'WinBar' },
- { start = 19, group = 'WarningMsg' }
- }
+ { start = 19, group = 'WarningMsg' },
+ },
},
- meths.eval_statusline(
+ api.nvim_eval_statusline(
'TextWithNoHighlight%#WarningMsg#TextWithWarningHighlight',
- { use_winbar = true, highlights = true }))
+ { use_winbar = true, highlights = true }
+ )
+ )
end)
+
it('works with statuscolumn', function()
exec([[
let &stc='%C%s%=%l '
- set cul nu nuw=3 scl=yes:2 fdc=2
+ " should not use "stl" from 'fillchars'
+ set cul nu nuw=3 scl=yes:2 fdc=2 fillchars=stl:#
call setline(1, repeat(['aaaaa'], 5))
let g:ns = nvim_create_namespace('')
call sign_define('a', {'text':'aa', 'texthl':'IncSearch', 'numhl':'Normal'})
@@ -3615,28 +3862,31 @@ describe('API', function()
{ group = 'Normal', start = 6 },
{ group = 'IncSearch', start = 6 },
{ group = 'ErrorMsg', start = 8 },
- { group = 'Normal', start = 10 }
- }
- }, meths.eval_statusline('%C%s%=%l ', { use_statuscol_lnum = 4, highlights = true }))
- eq({
- str = '3 ' ,
- width = 2,
- highlights = {
- { group = 'LineNr', start = 0 },
- { group = 'ErrorMsg', start = 1 }
- }
- }, meths.eval_statusline('%l%#ErrorMsg# ', { use_statuscol_lnum = 3, highlights = true }))
+ { group = 'Normal', start = 10 },
+ },
+ }, api.nvim_eval_statusline(
+ '%C%s%=%l ',
+ { use_statuscol_lnum = 4, highlights = true }
+ ))
+ eq(
+ {
+ str = '3 ',
+ width = 2,
+ highlights = {
+ { group = 'LineNr', start = 0 },
+ { group = 'ErrorMsg', start = 1 },
+ },
+ },
+ api.nvim_eval_statusline('%l%#ErrorMsg# ', { use_statuscol_lnum = 3, highlights = true })
+ )
end)
+
it('no memory leak with click functions', function()
- meths.eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {})
+ api.nvim_eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {})
eq({
- str = 'StatusLineStringWithClickFunc',
- width = 29
- },
- meths.eval_statusline(
- '%@ClickFunc@StatusLineStringWithClickFunc%T',
- {})
- )
+ str = 'StatusLineStringWithClickFunc',
+ width = 29,
+ }, api.nvim_eval_statusline('%@ClickFunc@StatusLineStringWithClickFunc%T', {}))
end)
end)
end)
@@ -3649,8 +3899,8 @@ describe('API', function()
bang = false,
addr = 'none',
magic = {
- file = false,
- bar = false
+ file = false,
+ bar = false,
},
nargs = '*',
nextcmd = '',
@@ -3659,8 +3909,8 @@ describe('API', function()
confirm = false,
emsg_silent = false,
filter = {
- pattern = "",
- force = false
+ pattern = '',
+ force = false,
},
hide = false,
horizontal = false,
@@ -3673,13 +3923,13 @@ describe('API', function()
noswapfile = false,
sandbox = false,
silent = false,
- split = "",
+ split = '',
tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
- }
- }, meths.parse_cmd('echo foo', {}))
+ },
+ }, api.nvim_parse_cmd('echo foo', {}))
end)
it('works with ranges', function()
eq({
@@ -3689,8 +3939,8 @@ describe('API', function()
range = { 4, 6 },
addr = 'line',
magic = {
- file = false,
- bar = false
+ file = false,
+ bar = false,
},
nargs = '*',
nextcmd = '',
@@ -3699,8 +3949,8 @@ describe('API', function()
confirm = false,
emsg_silent = false,
filter = {
- pattern = "",
- force = false
+ pattern = '',
+ force = false,
},
hide = false,
horizontal = false,
@@ -3713,13 +3963,13 @@ describe('API', function()
noswapfile = false,
sandbox = false,
silent = false,
- split = "",
+ split = '',
tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
- }
- }, meths.parse_cmd('4,6s/math.random/math.max/', {}))
+ },
+ }, api.nvim_parse_cmd('4,6s/math.random/math.max/', {}))
end)
it('works with count', function()
eq({
@@ -3730,8 +3980,8 @@ describe('API', function()
count = 1,
addr = 'buf',
magic = {
- file = false,
- bar = true
+ file = false,
+ bar = true,
},
nargs = '*',
nextcmd = '',
@@ -3740,8 +3990,8 @@ describe('API', function()
confirm = false,
emsg_silent = false,
filter = {
- pattern = "",
- force = false
+ pattern = '',
+ force = false,
},
hide = false,
horizontal = false,
@@ -3754,13 +4004,13 @@ describe('API', function()
noswapfile = false,
sandbox = false,
silent = false,
- split = "",
+ split = '',
tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
- }
- }, meths.parse_cmd('buffer 1', {}))
+ },
+ }, api.nvim_parse_cmd('buffer 1', {}))
end)
it('works with register', function()
eq({
@@ -3771,8 +4021,8 @@ describe('API', function()
reg = '+',
addr = 'line',
magic = {
- file = false,
- bar = true
+ file = false,
+ bar = true,
},
nargs = '0',
nextcmd = '',
@@ -3781,8 +4031,8 @@ describe('API', function()
confirm = false,
emsg_silent = false,
filter = {
- pattern = "",
- force = false
+ pattern = '',
+ force = false,
},
hide = false,
horizontal = false,
@@ -3795,13 +4045,13 @@ describe('API', function()
noswapfile = false,
sandbox = false,
silent = false,
- split = "",
+ split = '',
tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
- }
- }, meths.parse_cmd('put +', {}))
+ },
+ }, api.nvim_parse_cmd('put +', {}))
eq({
cmd = 'put',
args = {},
@@ -3810,8 +4060,8 @@ describe('API', function()
reg = '',
addr = 'line',
magic = {
- file = false,
- bar = true
+ file = false,
+ bar = true,
},
nargs = '0',
nextcmd = '',
@@ -3820,8 +4070,8 @@ describe('API', function()
confirm = false,
emsg_silent = false,
filter = {
- pattern = "",
- force = false
+ pattern = '',
+ force = false,
},
hide = false,
horizontal = false,
@@ -3834,13 +4084,13 @@ describe('API', function()
noswapfile = false,
sandbox = false,
silent = false,
- split = "",
+ split = '',
tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
- }
- }, meths.parse_cmd('put', {}))
+ },
+ }, api.nvim_parse_cmd('put', {}))
end)
it('works with range, count and register', function()
eq({
@@ -3852,8 +4102,8 @@ describe('API', function()
reg = '*',
addr = 'line',
magic = {
- file = false,
- bar = true
+ file = false,
+ bar = true,
},
nargs = '0',
nextcmd = '',
@@ -3862,8 +4112,8 @@ describe('API', function()
confirm = false,
emsg_silent = false,
filter = {
- pattern = "",
- force = false
+ pattern = '',
+ force = false,
},
hide = false,
horizontal = false,
@@ -3876,13 +4126,13 @@ describe('API', function()
noswapfile = false,
sandbox = false,
silent = false,
- split = "",
+ split = '',
tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
- }
- }, meths.parse_cmd('1,3delete * 5', {}))
+ },
+ }, api.nvim_parse_cmd('1,3delete * 5', {}))
end)
it('works with bang', function()
eq({
@@ -3892,8 +4142,8 @@ describe('API', function()
range = {},
addr = 'line',
magic = {
- file = true,
- bar = true
+ file = true,
+ bar = true,
},
nargs = '?',
nextcmd = '',
@@ -3902,8 +4152,8 @@ describe('API', function()
confirm = false,
emsg_silent = false,
filter = {
- pattern = "",
- force = false
+ pattern = '',
+ force = false,
},
hide = false,
horizontal = false,
@@ -3916,91 +4166,103 @@ describe('API', function()
noswapfile = false,
sandbox = false,
silent = false,
- split = "",
+ split = '',
tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
},
- }, meths.parse_cmd('w!', {}))
+ }, api.nvim_parse_cmd('w!', {}))
end)
it('works with modifiers', function()
- eq({
- cmd = 'split',
- args = { 'foo.txt' },
- bang = false,
- range = {},
- addr = '?',
- magic = {
+ eq(
+ {
+ cmd = 'split',
+ args = { 'foo.txt' },
+ bang = false,
+ range = {},
+ addr = '?',
+ magic = {
file = true,
- bar = true
- },
- nargs = '?',
- nextcmd = '',
- mods = {
- browse = false,
- confirm = false,
- emsg_silent = true,
- filter = {
- pattern = "foo",
- force = false
+ bar = true,
+ },
+ nargs = '?',
+ nextcmd = '',
+ mods = {
+ browse = false,
+ confirm = false,
+ emsg_silent = true,
+ filter = {
+ pattern = 'foo',
+ force = false,
+ },
+ hide = false,
+ horizontal = true,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = true,
+ split = 'topleft',
+ tab = 1,
+ unsilent = false,
+ verbose = 15,
+ vertical = false,
},
- hide = false,
- horizontal = true,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = true,
- split = "topleft",
- tab = 1,
- unsilent = false,
- verbose = 15,
- vertical = false,
},
- }, meths.parse_cmd('15verbose silent! horizontal topleft tab filter /foo/ split foo.txt', {}))
- eq({
- cmd = 'split',
- args = { 'foo.txt' },
- bang = false,
- range = {},
- addr = '?',
- magic = {
+ api.nvim_parse_cmd(
+ '15verbose silent! horizontal topleft tab filter /foo/ split foo.txt',
+ {}
+ )
+ )
+ eq(
+ {
+ cmd = 'split',
+ args = { 'foo.txt' },
+ bang = false,
+ range = {},
+ addr = '?',
+ magic = {
file = true,
- bar = true
- },
- nargs = '?',
- nextcmd = '',
- mods = {
- browse = false,
- confirm = true,
- emsg_silent = false,
- filter = {
- pattern = "foo",
- force = true
+ bar = true,
+ },
+ nargs = '?',
+ nextcmd = '',
+ mods = {
+ browse = false,
+ confirm = true,
+ emsg_silent = false,
+ filter = {
+ pattern = 'foo',
+ force = true,
+ },
+ hide = false,
+ horizontal = false,
+ keepalt = false,
+ keepjumps = false,
+ keepmarks = false,
+ keeppatterns = false,
+ lockmarks = false,
+ noautocmd = false,
+ noswapfile = false,
+ sandbox = false,
+ silent = false,
+ split = 'botright',
+ tab = 0,
+ unsilent = true,
+ verbose = 0,
+ vertical = false,
},
- hide = false,
- horizontal = false,
- keepalt = false,
- keepjumps = false,
- keepmarks = false,
- keeppatterns = false,
- lockmarks = false,
- noautocmd = false,
- noswapfile = false,
- sandbox = false,
- silent = false,
- split = "botright",
- tab = 0,
- unsilent = true,
- verbose = 0,
- vertical = false,
},
- }, meths.parse_cmd('0verbose unsilent botright 0tab confirm filter! /foo/ split foo.txt', {}))
+ api.nvim_parse_cmd(
+ '0verbose unsilent botright 0tab confirm filter! /foo/ split foo.txt',
+ {}
+ )
+ )
end)
it('works with user commands', function()
command('command -bang -nargs=+ -range -addr=lines MyCommand echo foo')
@@ -4011,8 +4273,8 @@ describe('API', function()
range = { 4, 6 },
addr = 'line',
magic = {
- file = false,
- bar = false
+ file = false,
+ bar = false,
},
nargs = '+',
nextcmd = '',
@@ -4021,8 +4283,8 @@ describe('API', function()
confirm = false,
emsg_silent = false,
filter = {
- pattern = "",
- force = false
+ pattern = '',
+ force = false,
},
hide = false,
horizontal = false,
@@ -4035,13 +4297,13 @@ describe('API', function()
noswapfile = false,
sandbox = false,
silent = false,
- split = "",
+ split = '',
tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
- }
- }, meths.parse_cmd('4,6MyCommand! test it', {}))
+ },
+ }, api.nvim_parse_cmd('4,6MyCommand! test it', {}))
end)
it('works for commands separated by bar', function()
eq({
@@ -4051,8 +4313,8 @@ describe('API', function()
range = {},
addr = 'arg',
magic = {
- file = true,
- bar = true
+ file = true,
+ bar = true,
},
nargs = '*',
nextcmd = 'argadd b.txt',
@@ -4061,8 +4323,8 @@ describe('API', function()
confirm = false,
emsg_silent = false,
filter = {
- pattern = "",
- force = false
+ pattern = '',
+ force = false,
},
hide = false,
horizontal = false,
@@ -4075,13 +4337,13 @@ describe('API', function()
noswapfile = false,
sandbox = false,
silent = false,
- split = "",
+ split = '',
tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
- }
- }, meths.parse_cmd('argadd a.txt | argadd b.txt', {}))
+ },
+ }, api.nvim_parse_cmd('argadd a.txt | argadd b.txt', {}))
end)
it('works for nargs=1', function()
command('command -nargs=1 MyCommand echo <q-args>')
@@ -4091,8 +4353,8 @@ describe('API', function()
bang = false,
addr = 'none',
magic = {
- file = false,
- bar = false
+ file = false,
+ bar = false,
},
nargs = '1',
nextcmd = '',
@@ -4101,8 +4363,8 @@ describe('API', function()
confirm = false,
emsg_silent = false,
filter = {
- pattern = "",
- force = false
+ pattern = '',
+ force = false,
},
hide = false,
horizontal = false,
@@ -4115,33 +4377,41 @@ describe('API', function()
noswapfile = false,
sandbox = false,
silent = false,
- split = "",
+ split = '',
tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
- }
- }, meths.parse_cmd('MyCommand test it', {}))
+ },
+ }, api.nvim_parse_cmd('MyCommand test it', {}))
end)
it('validates command', function()
- eq('Error while parsing command line', pcall_err(meths.parse_cmd, '', {}))
- eq('Error while parsing command line', pcall_err(meths.parse_cmd, '" foo', {}))
- eq('Error while parsing command line: E492: Not an editor command: Fubar',
- pcall_err(meths.parse_cmd, 'Fubar', {}))
+ eq('Error while parsing command line', pcall_err(api.nvim_parse_cmd, '', {}))
+ eq('Error while parsing command line', pcall_err(api.nvim_parse_cmd, '" foo', {}))
+ eq(
+ 'Error while parsing command line: E492: Not an editor command: Fubar',
+ pcall_err(api.nvim_parse_cmd, 'Fubar', {})
+ )
command('command! Fubar echo foo')
- eq('Error while parsing command line: E477: No ! allowed',
- pcall_err(meths.parse_cmd, 'Fubar!', {}))
- eq('Error while parsing command line: E481: No range allowed',
- pcall_err(meths.parse_cmd, '4,6Fubar', {}))
+ eq(
+ 'Error while parsing command line: E477: No ! allowed',
+ pcall_err(api.nvim_parse_cmd, 'Fubar!', {})
+ )
+ eq(
+ 'Error while parsing command line: E481: No range allowed',
+ pcall_err(api.nvim_parse_cmd, '4,6Fubar', {})
+ )
command('command! Foobar echo foo')
- eq('Error while parsing command line: E464: Ambiguous use of user-defined command',
- pcall_err(meths.parse_cmd, 'F', {}))
+ eq(
+ 'Error while parsing command line: E464: Ambiguous use of user-defined command',
+ pcall_err(api.nvim_parse_cmd, 'F', {})
+ )
end)
it('does not interfere with printing line in Ex mode #19400', function()
local screen = Screen.new(60, 7)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, reverse = true}, -- MsgSeparator
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, reverse = true }, -- MsgSeparator
})
screen:attach()
insert([[
@@ -4151,13 +4421,12 @@ describe('API', function()
screen:expect([[
foo |
bar |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1: }|
Entering Ex mode. Type "visual" to go to Normal mode. |
:1^ |
]])
- eq('Error while parsing command line', pcall_err(meths.parse_cmd, '', {}))
+ eq('Error while parsing command line', pcall_err(api.nvim_parse_cmd, '', {}))
feed('<CR>')
screen:expect([[
foo |
@@ -4170,16 +4439,16 @@ describe('API', function()
]])
end)
it('does not move cursor or change search history/pattern #19878 #19890', function()
- meths.buf_set_lines(0, 0, -1, true, {'foo', 'bar', 'foo', 'bar'})
- eq({1, 0}, meths.win_get_cursor(0))
- eq('', funcs.getreg('/'))
- eq('', funcs.histget('search'))
- feed(':') -- call the API in cmdline mode to test whether it changes search history
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'foo', 'bar', 'foo', 'bar' })
+ eq({ 1, 0 }, api.nvim_win_get_cursor(0))
+ eq('', fn.getreg('/'))
+ eq('', fn.histget('search'))
+ feed(':') -- call the API in cmdline mode to test whether it changes search history
eq({
cmd = 'normal',
- args = {'x'},
+ args = { 'x' },
bang = true,
- range = {3, 4},
+ range = { 3, 4 },
addr = 'line',
magic = {
file = false,
@@ -4192,7 +4461,7 @@ describe('API', function()
confirm = false,
emsg_silent = false,
filter = {
- pattern = "",
+ pattern = '',
force = false,
},
hide = false,
@@ -4206,101 +4475,134 @@ describe('API', function()
noswapfile = false,
sandbox = false,
silent = false,
- split = "",
+ split = '',
tab = -1,
unsilent = false,
verbose = -1,
vertical = false,
- }
- }, meths.parse_cmd('+2;/bar/normal! x', {}))
- eq({1, 0}, meths.win_get_cursor(0))
- eq('', funcs.getreg('/'))
- eq('', funcs.histget('search'))
+ },
+ }, api.nvim_parse_cmd('+2;/bar/normal! x', {}))
+ eq({ 1, 0 }, api.nvim_win_get_cursor(0))
+ eq('', fn.getreg('/'))
+ eq('', fn.histget('search'))
end)
it('result can be used directly by nvim_cmd #20051', function()
- eq("foo", meths.cmd(meths.parse_cmd('echo "foo"', {}), { output = true }))
- meths.cmd(meths.parse_cmd("set cursorline", {}), {})
- eq(true, meths.get_option_value("cursorline", {}))
+ eq('foo', api.nvim_cmd(api.nvim_parse_cmd('echo "foo"', {}), { output = true }))
+ api.nvim_cmd(api.nvim_parse_cmd('set cursorline', {}), {})
+ eq(true, api.nvim_get_option_value('cursorline', {}))
end)
it('no side-effects (error messages) in pcall() #20339', function()
- eq({ false, 'Error while parsing command line: E16: Invalid range' },
- exec_lua([=[return {pcall(vim.api.nvim_parse_cmd, "'<,'>n", {})}]=]))
+ eq(
+ { false, 'Error while parsing command line: E16: Invalid range' },
+ exec_lua([=[return {pcall(vim.api.nvim_parse_cmd, "'<,'>n", {})}]=])
+ )
eq('', eval('v:errmsg'))
end)
end)
describe('nvim_cmd', function()
- it('works', function ()
- meths.cmd({ cmd = "set", args = { "cursorline" } }, {})
- eq(true, meths.get_option_value("cursorline", {}))
+ it('works', function()
+ api.nvim_cmd({ cmd = 'set', args = { 'cursorline' } }, {})
+ eq(true, api.nvim_get_option_value('cursorline', {}))
end)
it('validation', function()
- eq("Invalid 'cmd': expected non-empty String",
- pcall_err(meths.cmd, { cmd = ""}, {}))
- eq("Invalid 'cmd': expected String, got Array",
- pcall_err(meths.cmd, { cmd = {}}, {}))
- eq("Invalid 'args': expected Array, got Boolean",
- pcall_err(meths.cmd, { cmd = "set", args = true }, {}))
- eq("Invalid command arg: expected non-whitespace",
- pcall_err(meths.cmd, { cmd = "set", args = {' '}, }, {}))
- eq("Invalid command arg: expected valid type, got Array",
- pcall_err(meths.cmd, { cmd = "set", args = {{}}, }, {}))
- eq("Wrong number of arguments",
- pcall_err(meths.cmd, { cmd = "aboveleft", args = {}, }, {}))
- eq("Command cannot accept bang: print",
- pcall_err(meths.cmd, { cmd = "print", args = {}, bang = true }, {}))
-
- eq("Command cannot accept range: set",
- pcall_err(meths.cmd, { cmd = "set", args = {}, range = {1} }, {}))
- eq("Invalid 'range': expected Array, got Boolean",
- pcall_err(meths.cmd, { cmd = "print", args = {}, range = true }, {}))
- eq("Invalid 'range': expected <=2 elements",
- pcall_err(meths.cmd, { cmd = "print", args = {}, range = {1,2,3,4} }, {}))
- eq("Invalid range element: expected non-negative Integer",
- pcall_err(meths.cmd, { cmd = "print", args = {}, range = {-1} }, {}))
-
- eq("Command cannot accept count: set",
- pcall_err(meths.cmd, { cmd = "set", args = {}, count = 1 }, {}))
- eq("Invalid 'count': expected Integer, got Boolean",
- pcall_err(meths.cmd, { cmd = "print", args = {}, count = true }, {}))
- eq("Invalid 'count': expected non-negative Integer",
- pcall_err(meths.cmd, { cmd = "print", args = {}, count = -1 }, {}))
-
- eq("Command cannot accept register: set",
- pcall_err(meths.cmd, { cmd = "set", args = {}, reg = 'x' }, {}))
- eq('Cannot use register "=',
- pcall_err(meths.cmd, { cmd = "put", args = {}, reg = '=' }, {}))
- eq("Invalid 'reg': expected single character, got xx",
- pcall_err(meths.cmd, { cmd = "put", args = {}, reg = 'xx' }, {}))
+ eq("Invalid 'cmd': expected non-empty String", pcall_err(api.nvim_cmd, { cmd = '' }, {}))
+ eq("Invalid 'cmd': expected String, got Array", pcall_err(api.nvim_cmd, { cmd = {} }, {}))
+ eq(
+ "Invalid 'args': expected Array, got Boolean",
+ pcall_err(api.nvim_cmd, { cmd = 'set', args = true }, {})
+ )
+ eq(
+ 'Invalid command arg: expected non-whitespace',
+ pcall_err(api.nvim_cmd, { cmd = 'set', args = { ' ' } }, {})
+ )
+ eq(
+ 'Invalid command arg: expected valid type, got Array',
+ pcall_err(api.nvim_cmd, { cmd = 'set', args = { {} } }, {})
+ )
+ eq('Wrong number of arguments', pcall_err(api.nvim_cmd, { cmd = 'aboveleft', args = {} }, {}))
+ eq(
+ 'Command cannot accept bang: print',
+ pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, bang = true }, {})
+ )
+
+ eq(
+ 'Command cannot accept range: set',
+ pcall_err(api.nvim_cmd, { cmd = 'set', args = {}, range = { 1 } }, {})
+ )
+ eq(
+ "Invalid 'range': expected Array, got Boolean",
+ pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, range = true }, {})
+ )
+ eq(
+ "Invalid 'range': expected <=2 elements",
+ pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, range = { 1, 2, 3, 4 } }, {})
+ )
+ eq(
+ 'Invalid range element: expected non-negative Integer',
+ pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, range = { -1 } }, {})
+ )
+
+ eq(
+ 'Command cannot accept count: set',
+ pcall_err(api.nvim_cmd, { cmd = 'set', args = {}, count = 1 }, {})
+ )
+ eq(
+ "Invalid 'count': expected Integer, got Boolean",
+ pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, count = true }, {})
+ )
+ eq(
+ "Invalid 'count': expected non-negative Integer",
+ pcall_err(api.nvim_cmd, { cmd = 'print', args = {}, count = -1 }, {})
+ )
+
+ eq(
+ 'Command cannot accept register: set',
+ pcall_err(api.nvim_cmd, { cmd = 'set', args = {}, reg = 'x' }, {})
+ )
+ eq(
+ 'Cannot use register "=',
+ pcall_err(api.nvim_cmd, { cmd = 'put', args = {}, reg = '=' }, {})
+ )
+ eq(
+ "Invalid 'reg': expected single character, got xx",
+ pcall_err(api.nvim_cmd, { cmd = 'put', args = {}, reg = 'xx' }, {})
+ )
-- #20681
- eq('Invalid command: "win_getid"', pcall_err(meths.cmd, { cmd = 'win_getid'}, {}))
- eq('Invalid command: "echo "hi""', pcall_err(meths.cmd, { cmd = 'echo "hi"'}, {}))
+ eq('Invalid command: "win_getid"', pcall_err(api.nvim_cmd, { cmd = 'win_getid' }, {}))
+ eq('Invalid command: "echo "hi""', pcall_err(api.nvim_cmd, { cmd = 'echo "hi"' }, {}))
eq('Invalid command: "win_getid"', pcall_err(exec_lua, [[return vim.cmd.win_getid{}]]))
-- Lua call allows empty {} for dict item.
eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, magic = {} }]]))
eq('', exec_lua([[return vim.cmd{ cmd = "set", args = {}, mods = {} }]]))
- eq('', meths.cmd({ cmd = "set", args = {}, magic = {} }, {}))
+ eq('', api.nvim_cmd({ cmd = 'set', args = {}, magic = {} }, {}))
-- Lua call does not allow non-empty list-like {} for dict item.
- eq("Invalid 'magic': Expected Dict-like Lua table",
- pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { 'a' } }]]))
- eq("Invalid key: 'bogus'",
- pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { bogus = true } }]]))
- eq("Invalid key: 'bogus'",
- pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, mods = { bogus = true } }]]))
+ eq(
+ "Invalid 'magic': Expected Dict-like Lua table",
+ pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { 'a' } }]])
+ )
+ eq(
+ "Invalid key: 'bogus'",
+ pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, magic = { bogus = true } }]])
+ )
+ eq(
+ "Invalid key: 'bogus'",
+ pcall_err(exec_lua, [[return vim.cmd{ cmd = "set", args = {}, mods = { bogus = true } }]])
+ )
end)
it('captures output', function()
- eq("foo", meths.cmd({ cmd = "echo", args = { '"foo"' } }, { output = true }))
+ eq('foo', api.nvim_cmd({ cmd = 'echo', args = { '"foo"' } }, { output = true }))
end)
it('sets correct script context', function()
- meths.cmd({ cmd = "set", args = { "cursorline" } }, {})
+ api.nvim_cmd({ cmd = 'set', args = { 'cursorline' } }, {})
local str = exec_capture([[verbose set cursorline?]])
- neq(nil, str:find("cursorline\n\tLast set from API client %(channel id %d+%)"))
+ neq(nil, str:find('cursorline\n\tLast set from API client %(channel id %d+%)'))
end)
it('works with range', function()
@@ -4313,7 +4615,7 @@ describe('API', function()
line5
line6
]]
- meths.cmd({ cmd = "del", range = {2, 4} }, {})
+ api.nvim_cmd({ cmd = 'del', range = { 2, 4 } }, {})
expect [[
line1
you didn't expect this
@@ -4321,6 +4623,7 @@ describe('API', function()
line6
]]
end)
+
it('works with count', function()
insert [[
line1
@@ -4331,13 +4634,14 @@ describe('API', function()
line5
line6
]]
- meths.cmd({ cmd = "del", range = { 2 }, count = 4 }, {})
+ api.nvim_cmd({ cmd = 'del', range = { 2 }, count = 4 }, {})
expect [[
line1
line5
line6
]]
end)
+
it('works with register', function()
insert [[
line1
@@ -4348,7 +4652,7 @@ describe('API', function()
line5
line6
]]
- meths.cmd({ cmd = "del", range = { 2, 4 }, reg = 'a' }, {})
+ api.nvim_cmd({ cmd = 'del', range = { 2, 4 }, reg = 'a' }, {})
command('1put a')
expect [[
line1
@@ -4360,192 +4664,293 @@ describe('API', function()
line6
]]
end)
- it('works with bang', function ()
- meths.create_user_command("Foo", 'echo "<bang>"', { bang = true })
- eq("!", meths.cmd({ cmd = "Foo", bang = true }, { output = true }))
- eq("", meths.cmd({ cmd = "Foo", bang = false }, { output = true }))
+
+ it('works with bang', function()
+ api.nvim_create_user_command('Foo', 'echo "<bang>"', { bang = true })
+ eq('!', api.nvim_cmd({ cmd = 'Foo', bang = true }, { output = true }))
+ eq('', api.nvim_cmd({ cmd = 'Foo', bang = false }, { output = true }))
end)
+
it('works with modifiers', function()
-- with silent = true output is still captured
- eq('1',
- meths.cmd({ cmd = 'echomsg', args = { '1' }, mods = { silent = true } },
- { output = true }))
+ eq(
+ '1',
+ api.nvim_cmd(
+ { cmd = 'echomsg', args = { '1' }, mods = { silent = true } },
+ { output = true }
+ )
+ )
-- but message isn't added to message history
- eq('', meths.cmd({ cmd = 'messages' }, { output = true }))
-
- meths.create_user_command("Foo", 'set verbose', {})
- eq(" verbose=1", meths.cmd({ cmd = "Foo", mods = { verbose = 1 } }, { output = true }))
-
- meths.create_user_command("Mods", "echo '<mods>'", {})
- eq('keepmarks keeppatterns silent 3verbose aboveleft horizontal',
- meths.cmd({ cmd = "Mods", mods = {
- horizontal = true,
- keepmarks = true,
- keeppatterns = true,
- silent = true,
- split = 'aboveleft',
- verbose = 3,
- } }, { output = true }))
- eq(0, meths.get_option_value("verbose", {}))
+ eq('', api.nvim_cmd({ cmd = 'messages' }, { output = true }))
+
+ api.nvim_create_user_command('Foo', 'set verbose', {})
+ eq(' verbose=1', api.nvim_cmd({ cmd = 'Foo', mods = { verbose = 1 } }, { output = true }))
+
+ api.nvim_create_user_command('Mods', "echo '<mods>'", {})
+ eq(
+ 'keepmarks keeppatterns silent 3verbose aboveleft horizontal',
+ api.nvim_cmd({
+ cmd = 'Mods',
+ mods = {
+ horizontal = true,
+ keepmarks = true,
+ keeppatterns = true,
+ silent = true,
+ split = 'aboveleft',
+ verbose = 3,
+ },
+ }, { output = true })
+ )
+ eq(0, api.nvim_get_option_value('verbose', {}))
command('edit foo.txt | edit bar.txt')
- eq(' 1 #h "foo.txt" line 1',
- meths.cmd({ cmd = "buffers", mods = { filter = { pattern = "foo", force = false } } },
- { output = true }))
- eq(' 2 %a "bar.txt" line 1',
- meths.cmd({ cmd = "buffers", mods = { filter = { pattern = "foo", force = true } } },
- { output = true }))
+ eq(
+ ' 1 #h "foo.txt" line 1',
+ api.nvim_cmd(
+ { cmd = 'buffers', mods = { filter = { pattern = 'foo', force = false } } },
+ { output = true }
+ )
+ )
+ eq(
+ ' 2 %a "bar.txt" line 1',
+ api.nvim_cmd(
+ { cmd = 'buffers', mods = { filter = { pattern = 'foo', force = true } } },
+ { output = true }
+ )
+ )
-- with emsg_silent = true error is suppressed
feed([[:lua vim.api.nvim_cmd({ cmd = 'call', mods = { emsg_silent = true } }, {})<CR>]])
- eq('', meths.cmd({ cmd = 'messages' }, { output = true }))
+ eq('', api.nvim_cmd({ cmd = 'messages' }, { output = true }))
-- error from the next command typed is not suppressed #21420
feed(':call<CR><CR>')
- eq('E471: Argument required', meths.cmd({ cmd = 'messages' }, { output = true }))
+ eq('E471: Argument required', api.nvim_cmd({ cmd = 'messages' }, { output = true }))
end)
+
it('works with magic.file', function()
exec_lua([[
vim.api.nvim_create_user_command("Foo", function(opts)
vim.api.nvim_echo({{ opts.fargs[1] }}, false, {})
end, { nargs = 1 })
]])
- eq(luv.cwd(),
- meths.cmd({ cmd = "Foo", args = { '%:p:h' }, magic = { file = true } },
- { output = true }))
+ eq(
+ uv.cwd(),
+ api.nvim_cmd(
+ { cmd = 'Foo', args = { '%:p:h' }, magic = { file = true } },
+ { output = true }
+ )
+ )
end)
+
it('splits arguments correctly', function()
exec([[
function! FooFunc(...)
echo a:000
endfunction
]])
- meths.create_user_command("Foo", "call FooFunc(<f-args>)", { nargs = '+' })
- eq([=[['a quick', 'brown fox', 'jumps over the', 'lazy dog']]=],
- meths.cmd({ cmd = "Foo", args = { "a quick", "brown fox", "jumps over the", "lazy dog"}},
- { output = true }))
- eq([=[['test \ \\ \"""\', 'more\ tests\" ']]=],
- meths.cmd({ cmd = "Foo", args = { [[test \ \\ \"""\]], [[more\ tests\" ]] } },
- { output = true }))
+ api.nvim_create_user_command('Foo', 'call FooFunc(<f-args>)', { nargs = '+' })
+ eq(
+ [=[['a quick', 'brown fox', 'jumps over the', 'lazy dog']]=],
+ api.nvim_cmd(
+ { cmd = 'Foo', args = { 'a quick', 'brown fox', 'jumps over the', 'lazy dog' } },
+ { output = true }
+ )
+ )
+ eq(
+ [=[['test \ \\ \"""\', 'more\ tests\" ']]=],
+ api.nvim_cmd(
+ { cmd = 'Foo', args = { [[test \ \\ \"""\]], [[more\ tests\" ]] } },
+ { output = true }
+ )
+ )
end)
+
it('splits arguments correctly for Lua callback', function()
- meths.exec_lua([[
+ api.nvim_exec_lua(
+ [[
local function FooFunc(opts)
vim.print(opts.fargs)
end
vim.api.nvim_create_user_command("Foo", FooFunc, { nargs = '+' })
- ]], {})
- eq([[{ "a quick", "brown fox", "jumps over the", "lazy dog" }]],
- meths.cmd({ cmd = "Foo", args = { "a quick", "brown fox", "jumps over the", "lazy dog"}},
- { output = true }))
- eq([[{ 'test \\ \\\\ \\"""\\', 'more\\ tests\\" ' }]],
- meths.cmd({ cmd = "Foo", args = { [[test \ \\ \"""\]], [[more\ tests\" ]] } },
- { output = true }))
+ ]],
+ {}
+ )
+ eq(
+ [[{ "a quick", "brown fox", "jumps over the", "lazy dog" }]],
+ api.nvim_cmd(
+ { cmd = 'Foo', args = { 'a quick', 'brown fox', 'jumps over the', 'lazy dog' } },
+ { output = true }
+ )
+ )
+ eq(
+ [[{ 'test \\ \\\\ \\"""\\', 'more\\ tests\\" ' }]],
+ api.nvim_cmd(
+ { cmd = 'Foo', args = { [[test \ \\ \"""\]], [[more\ tests\" ]] } },
+ { output = true }
+ )
+ )
end)
+
it('works with buffer names', function()
- command("edit foo.txt | edit bar.txt")
- meths.cmd({ cmd = "buffer", args = { "foo.txt" } }, {})
- eq("foo.txt", funcs.fnamemodify(meths.buf_get_name(0), ":t"))
- meths.cmd({ cmd = "buffer", args = { "bar.txt" } }, {})
- eq("bar.txt", funcs.fnamemodify(meths.buf_get_name(0), ":t"))
+ command('edit foo.txt | edit bar.txt')
+ api.nvim_cmd({ cmd = 'buffer', args = { 'foo.txt' } }, {})
+ eq('foo.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
+ api.nvim_cmd({ cmd = 'buffer', args = { 'bar.txt' } }, {})
+ eq('bar.txt', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
end)
+
it('triggers CmdUndefined event if command is not found', function()
- meths.exec_lua([[
+ api.nvim_exec_lua(
+ [[
vim.api.nvim_create_autocmd("CmdUndefined",
{ pattern = "Foo",
callback = function()
vim.api.nvim_create_user_command("Foo", "echo 'foo'", {})
end
})
- ]], {})
- eq("foo", meths.cmd({ cmd = "Foo" }, { output = true }))
+ ]],
+ {}
+ )
+ eq('foo', api.nvim_cmd({ cmd = 'Foo' }, { output = true }))
end)
+
it('errors if command is not implemented', function()
- eq("Command not implemented: winpos", pcall_err(meths.cmd, { cmd = "winpos" }, {}))
+ eq('Command not implemented: winpos', pcall_err(api.nvim_cmd, { cmd = 'winpos' }, {}))
end)
+
it('works with empty arguments list', function()
- meths.cmd({ cmd = "update" }, {})
- meths.cmd({ cmd = "buffer", count = 0 }, {})
+ api.nvim_cmd({ cmd = 'update' }, {})
+ api.nvim_cmd({ cmd = 'buffer', count = 0 }, {})
end)
- it('doesn\'t suppress errors when used in keymapping', function()
- meths.exec_lua([[
+
+ it("doesn't suppress errors when used in keymapping", function()
+ api.nvim_exec_lua(
+ [[
vim.keymap.set("n", "[l",
function() vim.api.nvim_cmd({ cmd = "echo", args = {"foo"} }, {}) end)
- ]], {})
- feed("[l")
- neq(nil, string.find(eval("v:errmsg"), "E5108:"))
+ ]],
+ {}
+ )
+ feed('[l')
+ neq(nil, string.find(eval('v:errmsg'), 'E5108:'))
end)
+
it('handles 0 range #19608', function()
- meths.buf_set_lines(0, 0, -1, false, { "aa" })
- meths.cmd({ cmd = 'delete', range = { 0 } }, {})
+ api.nvim_buf_set_lines(0, 0, -1, false, { 'aa' })
+ api.nvim_cmd({ cmd = 'delete', range = { 0 } }, {})
command('undo')
- eq({'aa'}, meths.buf_get_lines(0, 0, 1, false))
+ eq({ 'aa' }, api.nvim_buf_get_lines(0, 0, 1, false))
assert_alive()
end)
+
it('supports filename expansion', function()
- meths.cmd({ cmd = 'argadd', args = { '%:p:h:t', '%:p:h:t' } }, {})
- local arg = funcs.expand('%:p:h:t')
- eq({ arg, arg }, funcs.argv())
+ api.nvim_cmd({ cmd = 'argadd', args = { '%:p:h:t', '%:p:h:t' } }, {})
+ local arg = fn.expand('%:p:h:t')
+ eq({ arg, arg }, fn.argv())
end)
- it("'make' command works when argument count isn't 1 #19696", function()
+
+ it(":make command works when argument count isn't 1 #19696", function()
command('set makeprg=echo')
command('set shellquote=')
- matches('^:!echo ',
- meths.cmd({ cmd = 'make' }, { output = true }))
+ matches('^:!echo ', api.nvim_cmd({ cmd = 'make' }, { output = true }))
assert_alive()
- matches('^:!echo foo bar',
- meths.cmd({ cmd = 'make', args = { 'foo', 'bar' } }, { output = true }))
+ matches(
+ '^:!echo foo bar',
+ api.nvim_cmd({ cmd = 'make', args = { 'foo', 'bar' } }, { output = true })
+ )
assert_alive()
- local arg_pesc = pesc(funcs.expand('%:p:h:t'))
- matches(('^:!echo %s %s'):format(arg_pesc, arg_pesc),
- meths.cmd({ cmd = 'make', args = { '%:p:h:t', '%:p:h:t' } }, { output = true }))
+ local arg_pesc = pesc(fn.expand('%:p:h:t'))
+ matches(
+ ('^:!echo %s %s'):format(arg_pesc, arg_pesc),
+ api.nvim_cmd({ cmd = 'make', args = { '%:p:h:t', '%:p:h:t' } }, { output = true })
+ )
assert_alive()
end)
- it('doesn\'t display messages when output=true', function()
+
+ it("doesn't display messages when output=true", function()
local screen = Screen.new(40, 6)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
})
- meths.cmd({cmd = 'echo', args = {[['hello']]}}, {output = true})
- screen:expect{grid=[[
+ api.nvim_cmd({ cmd = 'echo', args = { [['hello']] } }, { output = true })
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
- ]]}
+ ]],
+ }
exec([[
func Print()
call nvim_cmd(#{cmd: 'echo', args: ['"hello"']}, #{output: v:true})
endfunc
]])
feed([[:echon 1 | call Print() | echon 5<CR>]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
15 |
- ]]}
+ ]],
+ }
end)
+
it('works with non-String args', function()
- eq('2', meths.cmd({cmd = 'echo', args = {2}}, {output = true}))
- eq('1', meths.cmd({cmd = 'echo', args = {true}}, {output = true}))
+ eq('2', api.nvim_cmd({ cmd = 'echo', args = { 2 } }, { output = true }))
+ eq('1', api.nvim_cmd({ cmd = 'echo', args = { true } }, { output = true }))
end)
+
describe('first argument as count', function()
it('works', function()
command('vsplit | enew')
- meths.cmd({cmd = 'bdelete', args = {meths.get_current_buf()}}, {})
- eq(1, meths.get_current_buf().id)
+ api.nvim_cmd({ cmd = 'bdelete', args = { api.nvim_get_current_buf() } }, {})
+ eq(1, api.nvim_get_current_buf())
end)
+
it('works with :sleep using milliseconds', function()
- local start = luv.now()
- meths.cmd({cmd = 'sleep', args = {'100m'}}, {})
- ok(luv.now() - start <= 300)
+ local start = uv.now()
+ api.nvim_cmd({ cmd = 'sleep', args = { '100m' } }, {})
+ ok(uv.now() - start <= 300)
end)
end)
+
+ it(':call with unknown function does not crash #26289', function()
+ eq(
+ 'Vim:E117: Unknown function: UnknownFunc',
+ pcall_err(api.nvim_cmd, { cmd = 'call', args = { 'UnknownFunc()' } }, {})
+ )
+ end)
+
+ it(':throw does not crash #24556', function()
+ eq('42', pcall_err(api.nvim_cmd, { cmd = 'throw', args = { '42' } }, {}))
+ end)
+
+ it('can use :return #24556', function()
+ exec([[
+ func Foo()
+ let g:pos = 'before'
+ call nvim_cmd({'cmd': 'return', 'args': ['[1, 2, 3]']}, {})
+ let g:pos = 'after'
+ endfunc
+ let g:result = Foo()
+ ]])
+ eq('before', api.nvim_get_var('pos'))
+ eq({ 1, 2, 3 }, api.nvim_get_var('result'))
+ end)
+
+ it('errors properly when command too recursive #27210', function()
+ exec_lua([[
+ _G.success = false
+ vim.api.nvim_create_user_command('Test', function()
+ vim.api.nvim_cmd({ cmd = 'Test' }, {})
+ _G.success = true
+ end, {})
+ ]])
+ pcall_err(command, 'Test')
+ assert_alive()
+ eq(false, exec_lua('return _G.success'))
+ end)
end)
end)
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index 6737c2d15b..097a546ef2 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -1,17 +1,24 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq,
- ok, feed, insert, eval, tabpage = helpers.clear, helpers.nvim, helpers.curbuf,
- helpers.curbuf_contents, helpers.window, helpers.curwin, helpers.eq,
- helpers.neq, helpers.ok, helpers.feed, helpers.insert, helpers.eval,
- helpers.tabpage
+local clear, curbuf, curbuf_contents, curwin, eq, neq, matches, ok, feed, insert, eval =
+ helpers.clear,
+ helpers.api.nvim_get_current_buf,
+ helpers.curbuf_contents,
+ helpers.api.nvim_get_current_win,
+ helpers.eq,
+ helpers.neq,
+ helpers.matches,
+ helpers.ok,
+ helpers.feed,
+ helpers.insert,
+ helpers.eval
local poke_eventloop = helpers.poke_eventloop
-local curwinmeths = helpers.curwinmeths
local exec = helpers.exec
-local funcs = helpers.funcs
+local exec_lua = helpers.exec_lua
+local fn = helpers.fn
local request = helpers.request
-local NIL = helpers.NIL
-local meths = helpers.meths
+local NIL = vim.NIL
+local api = helpers.api
local command = helpers.command
local pcall_err = helpers.pcall_err
local assert_alive = helpers.assert_alive
@@ -21,201 +28,229 @@ describe('API/win', function()
describe('get_buf', function()
it('works', function()
- eq(curbuf(), window('get_buf', nvim('list_wins')[1]))
- nvim('command', 'new')
- nvim('set_current_win', nvim('list_wins')[2])
- eq(curbuf(), window('get_buf', nvim('list_wins')[2]))
- neq(window('get_buf', nvim('list_wins')[1]),
- window('get_buf', nvim('list_wins')[2]))
+ eq(curbuf(), api.nvim_win_get_buf(api.nvim_list_wins()[1]))
+ command('new')
+ api.nvim_set_current_win(api.nvim_list_wins()[2])
+ eq(curbuf(), api.nvim_win_get_buf(api.nvim_list_wins()[2]))
+ neq(
+ api.nvim_win_get_buf(api.nvim_list_wins()[1]),
+ api.nvim_win_get_buf(api.nvim_list_wins()[2])
+ )
end)
end)
describe('set_buf', function()
it('works', function()
- nvim('command', 'new')
- local windows = nvim('list_wins')
- neq(window('get_buf', windows[2]), window('get_buf', windows[1]))
- window('set_buf', windows[2], window('get_buf', windows[1]))
- eq(window('get_buf', windows[2]), window('get_buf', windows[1]))
+ command('new')
+ local windows = api.nvim_list_wins()
+ neq(api.nvim_win_get_buf(windows[2]), api.nvim_win_get_buf(windows[1]))
+ api.nvim_win_set_buf(windows[2], api.nvim_win_get_buf(windows[1]))
+ eq(api.nvim_win_get_buf(windows[2]), api.nvim_win_get_buf(windows[1]))
end)
it('validates args', function()
- eq('Invalid buffer id: 23', pcall_err(window, 'set_buf', nvim('get_current_win'), 23))
- eq('Invalid window id: 23', pcall_err(window, 'set_buf', 23, nvim('get_current_buf')))
+ eq('Invalid buffer id: 23', pcall_err(api.nvim_win_set_buf, api.nvim_get_current_win(), 23))
+ eq('Invalid window id: 23', pcall_err(api.nvim_win_set_buf, 23, api.nvim_get_current_buf()))
end)
- it('disallowed in cmdwin if win={old_}curwin or buf=curbuf', function()
- local new_buf = meths.create_buf(true, true)
- local old_win = meths.get_current_win()
- local new_win = meths.open_win(new_buf, false, {
- relative='editor', row=10, col=10, width=50, height=10,
+ it('disallowed in cmdwin if win=cmdwin_{old_cur}win or buf=cmdwin_buf', function()
+ local new_buf = api.nvim_create_buf(true, true)
+ local old_win = api.nvim_get_current_win()
+ local new_win = api.nvim_open_win(new_buf, false, {
+ relative = 'editor',
+ row = 10,
+ col = 10,
+ width = 50,
+ height = 10,
})
feed('q:')
- eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
- pcall_err(meths.win_set_buf, 0, new_buf))
- eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
- pcall_err(meths.win_set_buf, old_win, new_buf))
- eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
- pcall_err(meths.win_set_buf, new_win, 0))
-
- local next_buf = meths.create_buf(true, true)
- meths.win_set_buf(new_win, next_buf)
- eq(next_buf, meths.win_get_buf(new_win))
+ eq(
+ 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
+ pcall_err(api.nvim_win_set_buf, 0, new_buf)
+ )
+ eq(
+ 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
+ pcall_err(api.nvim_win_set_buf, old_win, new_buf)
+ )
+ eq(
+ 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
+ pcall_err(api.nvim_win_set_buf, new_win, 0)
+ )
+ matches(
+ 'E11: Invalid in command%-line window; <CR> executes, CTRL%-C quits$',
+ pcall_err(
+ exec_lua,
+ [[
+ local cmdwin_buf = vim.api.nvim_get_current_buf()
+ local new_win, new_buf = ...
+ vim.api.nvim_buf_call(new_buf, function()
+ vim.api.nvim_win_set_buf(new_win, cmdwin_buf)
+ end)
+ ]],
+ new_win,
+ new_buf
+ )
+ )
+ matches(
+ 'E11: Invalid in command%-line window; <CR> executes, CTRL%-C quits$',
+ pcall_err(
+ exec_lua,
+ [[
+ local cmdwin_win = vim.api.nvim_get_current_win()
+ local new_win, new_buf = ...
+ vim.api.nvim_win_call(new_win, function()
+ vim.api.nvim_win_set_buf(cmdwin_win, new_buf)
+ end)
+ ]],
+ new_win,
+ new_buf
+ )
+ )
+
+ local next_buf = api.nvim_create_buf(true, true)
+ api.nvim_win_set_buf(new_win, next_buf)
+ eq(next_buf, api.nvim_win_get_buf(new_win))
end)
end)
describe('{get,set}_cursor', function()
it('works', function()
- eq({1, 0}, curwin('get_cursor'))
- nvim('command', 'normal ityping\027o some text')
+ eq({ 1, 0 }, api.nvim_win_get_cursor(0))
+ command('normal ityping\027o some text')
eq('typing\n some text', curbuf_contents())
- eq({2, 10}, curwin('get_cursor'))
- curwin('set_cursor', {2, 6})
- nvim('command', 'normal i dumb')
+ eq({ 2, 10 }, api.nvim_win_get_cursor(0))
+ api.nvim_win_set_cursor(0, { 2, 6 })
+ command('normal i dumb')
eq('typing\n some dumb text', curbuf_contents())
end)
it('does not leak memory when using invalid window ID with invalid pos', function()
- eq('Invalid window id: 1', pcall_err(meths.win_set_cursor, 1, {"b\na"}))
+ eq('Invalid window id: 1', pcall_err(api.nvim_win_set_cursor, 1, { 'b\na' }))
end)
it('updates the screen, and also when the window is unfocused', function()
local screen = Screen.new(30, 9)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue},
- [2] = {bold = true, reverse = true};
- [3] = {reverse = true};
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { bold = true, reverse = true },
+ [3] = { reverse = true },
})
screen:attach()
- insert("prologue")
+ insert('prologue')
feed('100o<esc>')
- insert("epilogue")
+ insert('epilogue')
local win = curwin()
feed('gg')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^prologue |
- |
- |
- |
- |
- |
- |
- |
- |
- ]]}
+ |*8
+ ]],
+ }
-- cursor position is at beginning
- eq({1, 0}, window('get_cursor', win))
+ eq({ 1, 0 }, api.nvim_win_get_cursor(win))
-- move cursor to end
- window('set_cursor', win, {101, 0})
- screen:expect{grid=[[
- |
- |
- |
- |
- |
- |
- |
+ api.nvim_win_set_cursor(win, { 101, 0 })
+ screen:expect {
+ grid = [[
+ |*7
^epilogue |
|
- ]]}
+ ]],
+ }
-- move cursor to the beginning again
- window('set_cursor', win, {1, 0})
- screen:expect{grid=[[
+ api.nvim_win_set_cursor(win, { 1, 0 })
+ screen:expect {
+ grid = [[
^prologue |
- |
- |
- |
- |
- |
- |
- |
- |
- ]]}
+ |*8
+ ]],
+ }
-- move focus to new window
- nvim('command',"new")
+ command('new')
neq(win, curwin())
-- sanity check, cursor position is kept
- eq({1, 0}, window('get_cursor', win))
- screen:expect{grid=[[
+ eq({ 1, 0 }, api.nvim_win_get_cursor(win))
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:[No Name] }|
prologue |
- |
- |
+ |*2
{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
-- move cursor to end
- window('set_cursor', win, {101, 0})
- screen:expect{grid=[[
+ api.nvim_win_set_cursor(win, { 101, 0 })
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:[No Name] }|
- |
- |
+ |*2
epilogue |
{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
-- move cursor to the beginning again
- window('set_cursor', win, {1, 0})
- screen:expect{grid=[[
+ api.nvim_win_set_cursor(win, { 1, 0 })
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:[No Name] }|
prologue |
- |
- |
+ |*2
{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
-- curwin didn't change back
neq(win, curwin())
end)
it('remembers what column it wants to be in', function()
- insert("first line")
+ insert('first line')
feed('o<esc>')
- insert("second line")
+ insert('second line')
feed('gg')
poke_eventloop() -- let nvim process the 'gg' command
-- cursor position is at beginning
local win = curwin()
- eq({1, 0}, window('get_cursor', win))
+ eq({ 1, 0 }, api.nvim_win_get_cursor(win))
-- move cursor to column 5
- window('set_cursor', win, {1, 5})
+ api.nvim_win_set_cursor(win, { 1, 5 })
-- move down a line
feed('j')
poke_eventloop() -- let nvim process the 'j' command
-- cursor is still in column 5
- eq({2, 5}, window('get_cursor', win))
+ eq({ 2, 5 }, api.nvim_win_get_cursor(win))
end)
it('updates cursorline and statusline ruler in non-current window', function()
local screen = Screen.new(60, 8)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {background = Screen.colors.Grey90}, -- CursorLine
- [3] = {bold = true, reverse = true}, -- StatusLine
- [4] = {reverse = true}, -- StatusLineNC
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { background = Screen.colors.Grey90 }, -- CursorLine
+ [3] = { bold = true, reverse = true }, -- StatusLine
+ [4] = { reverse = true }, -- StatusLineNC
})
screen:attach()
command('set ruler')
@@ -232,19 +267,17 @@ describe('API/win', function()
bbb │bbb |
ccc │ccc |
{2:dd^d }│{2:ddd }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*2
{3:[No Name] [+] 4,3 All }{4:[No Name] [+] 4,3 All}|
|
]])
- window('set_cursor', oldwin, {1, 0})
+ api.nvim_win_set_cursor(oldwin, { 1, 0 })
screen:expect([[
aaa │{2:aaa }|
bbb │bbb |
ccc │ccc |
{2:dd^d }│ddd |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*2
{3:[No Name] [+] 4,3 All }{4:[No Name] [+] 1,1 All}|
|
]])
@@ -253,10 +286,10 @@ describe('API/win', function()
it('updates cursorcolumn in non-current window', function()
local screen = Screen.new(60, 8)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {background = Screen.colors.Grey90}, -- CursorColumn
- [3] = {bold = true, reverse = true}, -- StatusLine
- [4] = {reverse = true}, -- StatusLineNC
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { background = Screen.colors.Grey90 }, -- CursorColumn
+ [3] = { bold = true, reverse = true }, -- StatusLine
+ [4] = { reverse = true }, -- StatusLineNC
})
screen:attach()
command('set cursorcolumn')
@@ -272,19 +305,17 @@ describe('API/win', function()
bb{2:b} │bb{2:b} |
cc{2:c} │cc{2:c} |
dd^d │ddd |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*2
{3:[No Name] [+] }{4:[No Name] [+] }|
|
]])
- window('set_cursor', oldwin, {2, 0})
+ api.nvim_win_set_cursor(oldwin, { 2, 0 })
screen:expect([[
aa{2:a} │{2:a}aa |
bb{2:b} │bbb |
cc{2:c} │{2:c}cc |
dd^d │{2:d}dd |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*2
{3:[No Name] [+] }{4:[No Name] [+] }|
|
]])
@@ -293,31 +324,35 @@ describe('API/win', function()
describe('{get,set}_height', function()
it('works', function()
- nvim('command', 'vsplit')
- eq(window('get_height', nvim('list_wins')[2]),
- window('get_height', nvim('list_wins')[1]))
- nvim('set_current_win', nvim('list_wins')[2])
- nvim('command', 'split')
- eq(window('get_height', nvim('list_wins')[2]),
- math.floor(window('get_height', nvim('list_wins')[1]) / 2))
- window('set_height', nvim('list_wins')[2], 2)
- eq(2, window('get_height', nvim('list_wins')[2]))
+ command('vsplit')
+ eq(
+ api.nvim_win_get_height(api.nvim_list_wins()[2]),
+ api.nvim_win_get_height(api.nvim_list_wins()[1])
+ )
+ api.nvim_set_current_win(api.nvim_list_wins()[2])
+ command('split')
+ eq(
+ api.nvim_win_get_height(api.nvim_list_wins()[2]),
+ math.floor(api.nvim_win_get_height(api.nvim_list_wins()[1]) / 2)
+ )
+ api.nvim_win_set_height(api.nvim_list_wins()[2], 2)
+ eq(2, api.nvim_win_get_height(api.nvim_list_wins()[2]))
end)
it('correctly handles height=1', function()
- nvim('command', 'split')
- nvim('set_current_win', nvim('list_wins')[1])
- window('set_height', nvim('list_wins')[2], 1)
- eq(1, window('get_height', nvim('list_wins')[2]))
+ command('split')
+ api.nvim_set_current_win(api.nvim_list_wins()[1])
+ api.nvim_win_set_height(api.nvim_list_wins()[2], 1)
+ eq(1, api.nvim_win_get_height(api.nvim_list_wins()[2]))
end)
it('correctly handles height=1 with a winbar', function()
- nvim('command', 'set winbar=foobar')
- nvim('command', 'set winminheight=0')
- nvim('command', 'split')
- nvim('set_current_win', nvim('list_wins')[1])
- window('set_height', nvim('list_wins')[2], 1)
- eq(1, window('get_height', nvim('list_wins')[2]))
+ command('set winbar=foobar')
+ command('set winminheight=0')
+ command('split')
+ api.nvim_set_current_win(api.nvim_list_wins()[1])
+ api.nvim_win_set_height(api.nvim_list_wins()[2], 1)
+ eq(1, api.nvim_win_get_height(api.nvim_list_wins()[2]))
end)
it('do not cause ml_get errors with foldmethod=expr #19989', function()
@@ -333,21 +368,25 @@ describe('API/win', function()
call nvim_win_set_height(w, 5)
]])
feed('l')
- eq('', meths.get_vvar('errmsg'))
+ eq('', api.nvim_get_vvar('errmsg'))
end)
end)
describe('{get,set}_width', function()
it('works', function()
- nvim('command', 'split')
- eq(window('get_width', nvim('list_wins')[2]),
- window('get_width', nvim('list_wins')[1]))
- nvim('set_current_win', nvim('list_wins')[2])
- nvim('command', 'vsplit')
- eq(window('get_width', nvim('list_wins')[2]),
- math.floor(window('get_width', nvim('list_wins')[1]) / 2))
- window('set_width', nvim('list_wins')[2], 2)
- eq(2, window('get_width', nvim('list_wins')[2]))
+ command('split')
+ eq(
+ api.nvim_win_get_width(api.nvim_list_wins()[2]),
+ api.nvim_win_get_width(api.nvim_list_wins()[1])
+ )
+ api.nvim_set_current_win(api.nvim_list_wins()[2])
+ command('vsplit')
+ eq(
+ api.nvim_win_get_width(api.nvim_list_wins()[2]),
+ math.floor(api.nvim_win_get_width(api.nvim_list_wins()[1]) / 2)
+ )
+ api.nvim_win_set_width(api.nvim_list_wins()[2], 2)
+ eq(2, api.nvim_win_get_width(api.nvim_list_wins()[2]))
end)
it('do not cause ml_get errors with foldmethod=expr #19989', function()
@@ -363,36 +402,36 @@ describe('API/win', function()
call nvim_win_set_width(w, 5)
]])
feed('l')
- eq('', meths.get_vvar('errmsg'))
+ eq('', api.nvim_get_vvar('errmsg'))
end)
end)
describe('{get,set,del}_var', function()
it('works', function()
- curwin('set_var', 'lua', {1, 2, {['3'] = 1}})
- eq({1, 2, {['3'] = 1}}, curwin('get_var', 'lua'))
- eq({1, 2, {['3'] = 1}}, nvim('eval', 'w:lua'))
- eq(1, funcs.exists('w:lua'))
- curwinmeths.del_var('lua')
- eq(0, funcs.exists('w:lua'))
- eq('Key not found: lua', pcall_err(curwinmeths.del_var, 'lua'))
- curwinmeths.set_var('lua', 1)
+ api.nvim_win_set_var(0, 'lua', { 1, 2, { ['3'] = 1 } })
+ eq({ 1, 2, { ['3'] = 1 } }, api.nvim_win_get_var(0, 'lua'))
+ eq({ 1, 2, { ['3'] = 1 } }, api.nvim_eval('w:lua'))
+ eq(1, fn.exists('w:lua'))
+ api.nvim_win_del_var(0, 'lua')
+ eq(0, fn.exists('w:lua'))
+ eq('Key not found: lua', pcall_err(api.nvim_win_del_var, 0, 'lua'))
+ api.nvim_win_set_var(0, 'lua', 1)
command('lockvar w:lua')
- eq('Key is locked: lua', pcall_err(curwinmeths.del_var, 'lua'))
- eq('Key is locked: lua', pcall_err(curwinmeths.set_var, 'lua', 1))
+ eq('Key is locked: lua', pcall_err(api.nvim_win_del_var, 0, 'lua'))
+ eq('Key is locked: lua', pcall_err(api.nvim_win_set_var, 0, 'lua', 1))
end)
it('window_set_var returns the old value', function()
- local val1 = {1, 2, {['3'] = 1}}
- local val2 = {4, 7}
+ local val1 = { 1, 2, { ['3'] = 1 } }
+ local val2 = { 4, 7 }
eq(NIL, request('window_set_var', 0, 'lua', val1))
eq(val1, request('window_set_var', 0, 'lua', val2))
end)
it('window_del_var returns the old value', function()
- local val1 = {1, 2, {['3'] = 1}}
- local val2 = {4, 7}
- eq(NIL, request('window_set_var', 0, 'lua', val1))
+ local val1 = { 1, 2, { ['3'] = 1 } }
+ local val2 = { 4, 7 }
+ eq(NIL, request('window_set_var', 0, 'lua', val1))
eq(val1, request('window_set_var', 0, 'lua', val2))
eq(val2, request('window_del_var', 0, 'lua'))
end)
@@ -400,53 +439,51 @@ describe('API/win', function()
describe('nvim_get_option_value, nvim_set_option_value', function()
it('works', function()
- 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', nvim('get_option_value', 'colorcolumn', {}))
+ api.nvim_set_option_value('colorcolumn', '4,3', {})
+ eq('4,3', api.nvim_get_option_value('colorcolumn', {}))
+ command('set modified hidden')
+ command('enew') -- edit new buffer, window option is preserved
+ eq('4,3', api.nvim_get_option_value('colorcolumn', {}))
-- global-local option
- 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
+ api.nvim_set_option_value('statusline', 'window-status', { win = 0 })
+ eq('window-status', api.nvim_get_option_value('statusline', { win = 0 }))
+ eq('', api.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('', nvim('get_option_value', 'statusline', {win = 0}))
+ eq('', api.nvim_get_option_value('statusline', { win = 0 }))
eq('', eval('&l:statusline'))
end)
it('after switching windows #15390', function()
- nvim('command', 'tabnew')
- local tab1 = unpack(nvim('list_tabpages'))
- local win1 = unpack(tabpage('list_wins', tab1))
- nvim('set_option_value', 'statusline', 'window-status', {win=win1.id})
- nvim('command', 'split')
- nvim('command', 'wincmd J')
- nvim('command', 'wincmd j')
- eq('window-status', nvim('get_option_value', 'statusline', {win = win1.id}))
+ command('tabnew')
+ local tab1 = unpack(api.nvim_list_tabpages())
+ local win1 = unpack(api.nvim_tabpage_list_wins(tab1))
+ api.nvim_set_option_value('statusline', 'window-status', { win = win1 })
+ command('split')
+ command('wincmd J')
+ command('wincmd j')
+ eq('window-status', api.nvim_get_option_value('statusline', { win = win1 }))
assert_alive()
end)
it('returns values for unset local options', function()
- eq(-1, nvim('get_option_value', 'scrolloff', {win=0, scope='local'}))
+ eq(-1, api.nvim_get_option_value('scrolloff', { win = 0, scope = 'local' }))
end)
end)
describe('get_position', function()
it('works', function()
- local height = window('get_height', nvim('list_wins')[1])
- local width = window('get_width', nvim('list_wins')[1])
- nvim('command', 'split')
- nvim('command', 'vsplit')
- eq({0, 0}, window('get_position', nvim('list_wins')[1]))
+ local height = api.nvim_win_get_height(api.nvim_list_wins()[1])
+ local width = api.nvim_win_get_width(api.nvim_list_wins()[1])
+ command('split')
+ command('vsplit')
+ eq({ 0, 0 }, api.nvim_win_get_position(api.nvim_list_wins()[1]))
local vsplit_pos = math.floor(width / 2)
local split_pos = math.floor(height / 2)
- local win2row, win2col =
- unpack(window('get_position', nvim('list_wins')[2]))
- local win3row, win3col =
- unpack(window('get_position', nvim('list_wins')[3]))
+ local win2row, win2col = unpack(api.nvim_win_get_position(api.nvim_list_wins()[2]))
+ local win3row, win3col = unpack(api.nvim_win_get_position(api.nvim_list_wins()[3]))
eq(0, win2row)
eq(0, win3col)
ok(vsplit_pos - 1 <= win2col and win2col <= vsplit_pos + 1)
@@ -456,239 +493,362 @@ describe('API/win', function()
describe('get_position', function()
it('works', function()
- nvim('command', 'tabnew')
- nvim('command', 'vsplit')
- eq(window('get_tabpage',
- nvim('list_wins')[1]), nvim('list_tabpages')[1])
- eq(window('get_tabpage',
- nvim('list_wins')[2]), nvim('list_tabpages')[2])
- eq(window('get_tabpage',
- nvim('list_wins')[3]), nvim('list_tabpages')[2])
+ command('tabnew')
+ command('vsplit')
+ eq(api.nvim_win_get_tabpage(api.nvim_list_wins()[1]), api.nvim_list_tabpages()[1])
+ eq(api.nvim_win_get_tabpage(api.nvim_list_wins()[2]), api.nvim_list_tabpages()[2])
+ eq(api.nvim_win_get_tabpage(api.nvim_list_wins()[3]), api.nvim_list_tabpages()[2])
end)
end)
describe('get_number', function()
it('works', function()
- local wins = nvim('list_wins')
- eq(1, window('get_number', wins[1]))
+ local wins = api.nvim_list_wins()
+ eq(1, api.nvim_win_get_number(wins[1]))
- nvim('command', 'split')
- local win1, win2 = unpack(nvim('list_wins'))
- eq(1, window('get_number', win1))
- eq(2, window('get_number', win2))
+ command('split')
+ local win1, win2 = unpack(api.nvim_list_wins())
+ eq(1, api.nvim_win_get_number(win1))
+ eq(2, api.nvim_win_get_number(win2))
- nvim('command', 'wincmd J')
- eq(2, window('get_number', win1))
- eq(1, window('get_number', win2))
+ command('wincmd J')
+ eq(2, api.nvim_win_get_number(win1))
+ eq(1, api.nvim_win_get_number(win2))
- nvim('command', 'tabnew')
- local win3 = nvim('list_wins')[3]
+ command('tabnew')
+ local win3 = api.nvim_list_wins()[3]
-- First tab page
- eq(2, window('get_number', win1))
- eq(1, window('get_number', win2))
+ eq(2, api.nvim_win_get_number(win1))
+ eq(1, api.nvim_win_get_number(win2))
-- Second tab page
- eq(1, window('get_number', win3))
+ eq(1, api.nvim_win_get_number(win3))
end)
end)
describe('is_valid', function()
it('works', function()
- nvim('command', 'split')
- local win = nvim('list_wins')[2]
- nvim('set_current_win', win)
- ok(window('is_valid', win))
- nvim('command', 'close')
- ok(not window('is_valid', win))
+ command('split')
+ local win = api.nvim_list_wins()[2]
+ api.nvim_set_current_win(win)
+ ok(api.nvim_win_is_valid(win))
+ command('close')
+ ok(not api.nvim_win_is_valid(win))
end)
end)
describe('close', function()
it('can close current window', function()
- local oldwin = meths.get_current_win()
+ local oldwin = api.nvim_get_current_win()
command('split')
- local newwin = meths.get_current_win()
- meths.win_close(newwin,false)
- eq({oldwin}, meths.list_wins())
+ local newwin = api.nvim_get_current_win()
+ api.nvim_win_close(newwin, false)
+ eq({ oldwin }, api.nvim_list_wins())
end)
it('can close noncurrent window', function()
- local oldwin = meths.get_current_win()
+ local oldwin = api.nvim_get_current_win()
command('split')
- local newwin = meths.get_current_win()
- meths.win_close(oldwin,false)
- eq({newwin}, meths.list_wins())
+ local newwin = api.nvim_get_current_win()
+ api.nvim_win_close(oldwin, false)
+ eq({ newwin }, api.nvim_list_wins())
end)
it("handles changed buffer when 'hidden' is unset", function()
command('set nohidden')
- local oldwin = meths.get_current_win()
+ local oldwin = api.nvim_get_current_win()
insert('text')
command('new')
- local newwin = meths.get_current_win()
- eq("Vim:E37: No write since last change (add ! to override)",
- pcall_err(meths.win_close, oldwin,false))
- eq({newwin,oldwin}, meths.list_wins())
+ local newwin = api.nvim_get_current_win()
+ eq(
+ 'Vim:E37: No write since last change (add ! to override)',
+ pcall_err(api.nvim_win_close, oldwin, false)
+ )
+ eq({ newwin, oldwin }, api.nvim_list_wins())
end)
it('handles changed buffer with force', function()
- local oldwin = meths.get_current_win()
+ local oldwin = api.nvim_get_current_win()
insert('text')
command('new')
- local newwin = meths.get_current_win()
- meths.win_close(oldwin,true)
- eq({newwin}, meths.list_wins())
+ local newwin = api.nvim_get_current_win()
+ api.nvim_win_close(oldwin, true)
+ eq({ newwin }, api.nvim_list_wins())
end)
it('in cmdline-window #9767', function()
command('split')
- eq(2, #meths.list_wins())
- local oldwin = meths.get_current_win()
- local otherwin = meths.open_win(0, false, {
- relative='editor', row=10, col=10, width=10, height=10,
+ eq(2, #api.nvim_list_wins())
+ local oldbuf = api.nvim_get_current_buf()
+ local oldwin = api.nvim_get_current_win()
+ local otherwin = api.nvim_open_win(0, false, {
+ relative = 'editor',
+ row = 10,
+ col = 10,
+ width = 10,
+ height = 10,
})
-- Open cmdline-window.
feed('q:')
- eq(4, #meths.list_wins())
- eq(':', funcs.getcmdwintype())
+ eq(4, #api.nvim_list_wins())
+ eq(':', fn.getcmdwintype())
-- Not allowed to close previous window from cmdline-window.
- eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
- pcall_err(meths.win_close, oldwin, true))
+ eq(
+ 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
+ pcall_err(api.nvim_win_close, oldwin, true)
+ )
-- Closing other windows is fine.
- meths.win_close(otherwin, true)
- eq(false, meths.win_is_valid(otherwin))
+ api.nvim_win_close(otherwin, true)
+ eq(false, api.nvim_win_is_valid(otherwin))
-- Close cmdline-window.
- meths.win_close(0, true)
- eq(2, #meths.list_wins())
- eq('', funcs.getcmdwintype())
+ api.nvim_win_close(0, true)
+ eq(2, #api.nvim_list_wins())
+ eq('', fn.getcmdwintype())
+
+ -- Closing curwin in context of a different window shouldn't close cmdwin.
+ otherwin = api.nvim_open_win(0, false, {
+ relative = 'editor',
+ row = 10,
+ col = 10,
+ width = 10,
+ height = 10,
+ })
+ feed('q:')
+ exec_lua(
+ [[
+ vim.api.nvim_win_call(..., function()
+ vim.api.nvim_win_close(0, true)
+ end)
+ ]],
+ otherwin
+ )
+ eq(false, api.nvim_win_is_valid(otherwin))
+ eq(':', fn.getcmdwintype())
+ -- Closing cmdwin in context of a non-previous window is still OK.
+ otherwin = api.nvim_open_win(oldbuf, false, {
+ relative = 'editor',
+ row = 10,
+ col = 10,
+ width = 10,
+ height = 10,
+ })
+ exec_lua(
+ [[
+ local otherwin, cmdwin = ...
+ vim.api.nvim_win_call(otherwin, function()
+ vim.api.nvim_win_close(cmdwin, true)
+ end)
+ ]],
+ otherwin,
+ api.nvim_get_current_win()
+ )
+ eq('', fn.getcmdwintype())
+ eq(true, api.nvim_win_is_valid(otherwin))
end)
it('closing current (float) window of another tabpage #15313', function()
command('tabedit')
command('botright split')
- local prevwin = curwin().id
+ local prevwin = curwin()
eq(2, eval('tabpagenr()'))
- local win = meths.open_win(0, true, {
- relative='editor', row=10, col=10, width=50, height=10
+ local win = api.nvim_open_win(0, true, {
+ relative = 'editor',
+ row = 10,
+ col = 10,
+ width = 50,
+ height = 10,
})
local tab = eval('tabpagenr()')
command('tabprevious')
eq(1, eval('tabpagenr()'))
- meths.win_close(win, false)
+ api.nvim_win_close(win, false)
- eq(prevwin, meths.tabpage_get_win(tab).id)
+ eq(prevwin, api.nvim_tabpage_get_win(tab))
assert_alive()
end)
end)
describe('hide', function()
it('can hide current window', function()
- local oldwin = meths.get_current_win()
+ local oldwin = api.nvim_get_current_win()
command('split')
- local newwin = meths.get_current_win()
- meths.win_hide(newwin)
- eq({oldwin}, meths.list_wins())
+ local newwin = api.nvim_get_current_win()
+ api.nvim_win_hide(newwin)
+ eq({ oldwin }, api.nvim_list_wins())
end)
it('can hide noncurrent window', function()
- local oldwin = meths.get_current_win()
+ local oldwin = api.nvim_get_current_win()
command('split')
- local newwin = meths.get_current_win()
- meths.win_hide(oldwin)
- eq({newwin}, meths.list_wins())
+ local newwin = api.nvim_get_current_win()
+ api.nvim_win_hide(oldwin)
+ eq({ newwin }, api.nvim_list_wins())
end)
it('does not close the buffer', function()
- local oldwin = meths.get_current_win()
- local oldbuf = meths.get_current_buf()
- local buf = meths.create_buf(true, false)
- local newwin = meths.open_win(buf, true, {
- relative='win', row=3, col=3, width=12, height=3
+ local oldwin = api.nvim_get_current_win()
+ local oldbuf = api.nvim_get_current_buf()
+ local buf = api.nvim_create_buf(true, false)
+ local newwin = api.nvim_open_win(buf, true, {
+ relative = 'win',
+ row = 3,
+ col = 3,
+ width = 12,
+ height = 3,
})
- meths.win_hide(newwin)
- eq({oldwin}, meths.list_wins())
- eq({oldbuf, buf}, meths.list_bufs())
+ api.nvim_win_hide(newwin)
+ eq({ oldwin }, api.nvim_list_wins())
+ eq({ oldbuf, buf }, api.nvim_list_bufs())
end)
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).id
- local newwin = meths.open_win(buf, true, {
- relative='win', row=3, col=3, width=12, height=3
+ local oldwin = api.nvim_get_current_win()
+ local oldbuf = api.nvim_get_current_buf()
+ local buf = api.nvim_create_buf(true, false)
+ local newwin = api.nvim_open_win(buf, true, {
+ relative = 'win',
+ row = 3,
+ col = 3,
+ width = 12,
+ height = 3,
})
- meths.set_option_value('bufhidden', 'wipe', {buf=buf})
- meths.win_hide(newwin)
- eq({oldwin}, meths.list_wins())
- eq({oldbuf}, meths.list_bufs())
+ api.nvim_set_option_value('bufhidden', 'wipe', { buf = buf })
+ api.nvim_win_hide(newwin)
+ eq({ oldwin }, api.nvim_list_wins())
+ eq({ oldbuf }, api.nvim_list_bufs())
end)
it('in the cmdwin', function()
feed('q:')
-- Can close the cmdwin.
- meths.win_hide(0)
- eq('', funcs.getcmdwintype())
-
- local old_win = meths.get_current_win()
- local other_win = meths.open_win(0, false, {
- relative='win', row=3, col=3, width=12, height=3
+ api.nvim_win_hide(0)
+ eq('', fn.getcmdwintype())
+
+ local old_buf = api.nvim_get_current_buf()
+ local old_win = api.nvim_get_current_win()
+ local other_win = api.nvim_open_win(0, false, {
+ relative = 'win',
+ row = 3,
+ col = 3,
+ width = 12,
+ height = 3,
})
feed('q:')
-- Cannot close the previous window.
- eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
- pcall_err(meths.win_hide, old_win))
+ eq(
+ 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
+ pcall_err(api.nvim_win_hide, old_win)
+ )
-- Can close other windows.
- meths.win_hide(other_win)
- eq(false, meths.win_is_valid(other_win))
+ api.nvim_win_hide(other_win)
+ eq(false, api.nvim_win_is_valid(other_win))
+
+ -- Closing curwin in context of a different window shouldn't close cmdwin.
+ other_win = api.nvim_open_win(old_buf, false, {
+ relative = 'editor',
+ row = 10,
+ col = 10,
+ width = 10,
+ height = 10,
+ })
+ exec_lua(
+ [[
+ vim.api.nvim_win_call(..., function()
+ vim.api.nvim_win_hide(0)
+ end)
+ ]],
+ other_win
+ )
+ eq(false, api.nvim_win_is_valid(other_win))
+ eq(':', fn.getcmdwintype())
+ -- Closing cmdwin in context of a non-previous window is still OK.
+ other_win = api.nvim_open_win(old_buf, false, {
+ relative = 'editor',
+ row = 10,
+ col = 10,
+ width = 10,
+ height = 10,
+ })
+ exec_lua(
+ [[
+ local otherwin, cmdwin = ...
+ vim.api.nvim_win_call(otherwin, function()
+ vim.api.nvim_win_hide(cmdwin)
+ end)
+ ]],
+ other_win,
+ api.nvim_get_current_win()
+ )
+ eq('', fn.getcmdwintype())
+ eq(true, api.nvim_win_is_valid(other_win))
end)
end)
describe('text_height', function()
it('validation', function()
- local X = meths.get_vvar('maxcol')
+ local X = api.nvim_get_vvar('maxcol')
insert([[
aaa
bbb
ccc
ddd
eee]])
- eq("Invalid window id: 23",
- pcall_err(meths.win_text_height, 23, {}))
- eq("Line index out of bounds",
- pcall_err(curwinmeths.text_height, { start_row = 5 }))
- eq("Line index out of bounds",
- pcall_err(curwinmeths.text_height, { start_row = -6 }))
- eq("Line index out of bounds",
- pcall_err(curwinmeths.text_height, { end_row = 5 }))
- eq("Line index out of bounds",
- pcall_err(curwinmeths.text_height, { end_row = -6 }))
- eq("'start_row' is higher than 'end_row'",
- pcall_err(curwinmeths.text_height, { start_row = 3, end_row = 1 }))
- eq("'start_vcol' specified without 'start_row'",
- pcall_err(curwinmeths.text_height, { end_row = 2, start_vcol = 0 }))
- eq("'end_vcol' specified without 'end_row'",
- pcall_err(curwinmeths.text_height, { start_row = 2, end_vcol = 0 }))
- eq("Invalid 'start_vcol': out of range",
- pcall_err(curwinmeths.text_height, { start_row = 2, start_vcol = -1 }))
- eq("Invalid 'start_vcol': out of range",
- pcall_err(curwinmeths.text_height, { start_row = 2, start_vcol = X + 1 }))
- eq("Invalid 'end_vcol': out of range",
- pcall_err(curwinmeths.text_height, { end_row = 2, end_vcol = -1 }))
- eq("Invalid 'end_vcol': out of range",
- pcall_err(curwinmeths.text_height, { end_row = 2, end_vcol = X + 1 }))
- eq("'start_vcol' is higher than 'end_vcol'",
- pcall_err(curwinmeths.text_height, { start_row = 2, end_row = 2, start_vcol = 10, end_vcol = 5 }))
+ eq('Invalid window id: 23', pcall_err(api.nvim_win_text_height, 23, {}))
+ eq('Line index out of bounds', pcall_err(api.nvim_win_text_height, 0, { start_row = 5 }))
+ eq('Line index out of bounds', pcall_err(api.nvim_win_text_height, 0, { start_row = -6 }))
+ eq('Line index out of bounds', pcall_err(api.nvim_win_text_height, 0, { end_row = 5 }))
+ eq('Line index out of bounds', pcall_err(api.nvim_win_text_height, 0, { end_row = -6 }))
+ eq(
+ "'start_row' is higher than 'end_row'",
+ pcall_err(api.nvim_win_text_height, 0, { start_row = 3, end_row = 1 })
+ )
+ eq(
+ "'start_vcol' specified without 'start_row'",
+ pcall_err(api.nvim_win_text_height, 0, { end_row = 2, start_vcol = 0 })
+ )
+ eq(
+ "'end_vcol' specified without 'end_row'",
+ pcall_err(api.nvim_win_text_height, 0, { start_row = 2, end_vcol = 0 })
+ )
+ eq(
+ "Invalid 'start_vcol': out of range",
+ pcall_err(api.nvim_win_text_height, 0, { start_row = 2, start_vcol = -1 })
+ )
+ eq(
+ "Invalid 'start_vcol': out of range",
+ pcall_err(api.nvim_win_text_height, 0, { start_row = 2, start_vcol = X + 1 })
+ )
+ eq(
+ "Invalid 'end_vcol': out of range",
+ pcall_err(api.nvim_win_text_height, 0, { end_row = 2, end_vcol = -1 })
+ )
+ eq(
+ "Invalid 'end_vcol': out of range",
+ pcall_err(api.nvim_win_text_height, 0, { end_row = 2, end_vcol = X + 1 })
+ )
+ eq(
+ "'start_vcol' is higher than 'end_vcol'",
+ pcall_err(
+ api.nvim_win_text_height,
+ 0,
+ { start_row = 2, end_row = 2, start_vcol = 10, end_vcol = 5 }
+ )
+ )
end)
it('with two diff windows', function()
- local X = meths.get_vvar('maxcol')
+ local X = api.nvim_get_vvar('maxcol')
local screen = Screen.new(45, 22)
screen:set_default_attr_ids({
- [0] = {foreground = Screen.colors.Blue1, bold = true};
- [1] = {foreground = Screen.colors.Blue4, background = Screen.colors.Grey};
- [2] = {foreground = Screen.colors.Brown};
- [3] = {foreground = Screen.colors.Blue1, background = Screen.colors.LightCyan1, bold = true};
- [4] = {background = Screen.colors.LightBlue};
- [5] = {foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey};
- [6] = {background = Screen.colors.Plum1};
- [7] = {background = Screen.colors.Red, bold = true};
- [8] = {reverse = true};
- [9] = {bold = true, reverse = true};
+ [0] = { foreground = Screen.colors.Blue1, bold = true },
+ [1] = { foreground = Screen.colors.Blue4, background = Screen.colors.Grey },
+ [2] = { foreground = Screen.colors.Brown },
+ [3] = {
+ foreground = Screen.colors.Blue1,
+ background = Screen.colors.LightCyan1,
+ bold = true,
+ },
+ [4] = { background = Screen.colors.LightBlue },
+ [5] = { foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey },
+ [6] = { background = Screen.colors.Plum1 },
+ [7] = { background = Screen.colors.Red, bold = true },
+ [8] = { reverse = true },
+ [9] = { bold = true, reverse = true },
})
screen:attach()
exec([[
@@ -700,7 +860,8 @@ describe('API/win', function()
windo diffthis
]])
feed('24gg')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }{2: }{3:----------------}│{1: }{2: 1 }{4:00000001! }|
{1: }{2: }{3:----------------}│{1: }{2: 2 }{4:00000002!! }|
{1: }{2: 1 }00000003!!! │{1: }{2: 3 }00000003!!! |
@@ -723,68 +884,117 @@ describe('API/win', function()
{1: }{2: 41 }{4:00000050!!!!!!!!}│{1: }{2: }{3:----------------}|
{8:[No Name] [+] }{9:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
screen:try_resize(45, 3)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }{2: 19 }00000028!!!!!!!!│{1: }{2: 24 }^00000028!!!!!!!!|
{8:[No Name] [+] }{9:[No Name] [+] }|
|
- ]]}
- eq({ all = 20, fill = 5 }, meths.win_text_height(1000, {}))
- eq({ all = 20, fill = 5 }, meths.win_text_height(1001, {}))
- eq({ all = 20, fill = 5 }, meths.win_text_height(1000, { start_row = 0 }))
- eq({ all = 20, fill = 5 }, meths.win_text_height(1001, { start_row = 0 }))
- eq({ all = 15, fill = 0 }, meths.win_text_height(1000, { end_row = -1 }))
- eq({ all = 15, fill = 0 }, meths.win_text_height(1000, { end_row = 40 }))
- eq({ all = 20, fill = 5 }, meths.win_text_height(1001, { end_row = -1 }))
- eq({ all = 20, fill = 5 }, meths.win_text_height(1001, { end_row = 40 }))
- eq({ all = 10, fill = 5 }, meths.win_text_height(1000, { start_row = 23 }))
- eq({ all = 13, fill = 3 }, meths.win_text_height(1001, { start_row = 18 }))
- eq({ all = 11, fill = 0 }, meths.win_text_height(1000, { end_row = 23 }))
- eq({ all = 11, fill = 5 }, meths.win_text_height(1001, { end_row = 18 }))
- eq({ all = 11, fill = 0 }, meths.win_text_height(1000, { start_row = 3, end_row = 39 }))
- eq({ all = 11, fill = 3 }, meths.win_text_height(1001, { start_row = 1, end_row = 34 }))
- eq({ all = 9, fill = 0 }, meths.win_text_height(1000, { start_row = 4, end_row = 38 }))
- eq({ all = 9, fill = 3 }, meths.win_text_height(1001, { start_row = 2, end_row = 33 }))
- eq({ all = 9, fill = 0 }, meths.win_text_height(1000, { start_row = 5, end_row = 37 }))
- eq({ all = 9, fill = 3 }, meths.win_text_height(1001, { start_row = 3, end_row = 32 }))
- eq({ all = 9, fill = 0 }, meths.win_text_height(1000, { start_row = 17, end_row = 25 }))
- eq({ all = 9, fill = 3 }, meths.win_text_height(1001, { start_row = 15, end_row = 20 }))
- eq({ all = 7, fill = 0 }, meths.win_text_height(1000, { start_row = 18, end_row = 24 }))
- eq({ all = 7, fill = 3 }, meths.win_text_height(1001, { start_row = 16, end_row = 19 }))
- eq({ all = 6, fill = 5 }, meths.win_text_height(1000, { start_row = -1 }))
- eq({ all = 5, fill = 5 }, meths.win_text_height(1000, { start_row = -1, start_vcol = X }))
- eq({ all = 0, fill = 0 }, meths.win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1 }))
- eq({ all = 0, fill = 0 }, meths.win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1, end_vcol = X }))
- eq({ all = 1, fill = 0 }, meths.win_text_height(1000, { start_row = -1, start_vcol = 0, end_row = -1, end_vcol = X }))
- eq({ all = 3, fill = 2 }, meths.win_text_height(1001, { end_row = 0 }))
- eq({ all = 2, fill = 2 }, meths.win_text_height(1001, { end_row = 0, end_vcol = 0 }))
- eq({ all = 2, fill = 2 }, meths.win_text_height(1001, { start_row = 0, end_row = 0, end_vcol = 0 }))
- eq({ all = 0, fill = 0 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = 0 }))
- eq({ all = 1, fill = 0 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = X }))
- eq({ all = 11, fill = 5 }, meths.win_text_height(1001, { end_row = 18 }))
- eq({ all = 9, fill = 3 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18 }))
- eq({ all = 10, fill = 5 }, meths.win_text_height(1001, { end_row = 18, end_vcol = 0 }))
- eq({ all = 8, fill = 3 }, meths.win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18, end_vcol = 0 }))
+ ]],
+ }
+ eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1000, {}))
+ eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1001, {}))
+ eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1000, { start_row = 0 }))
+ eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1001, { start_row = 0 }))
+ eq({ all = 15, fill = 0 }, api.nvim_win_text_height(1000, { end_row = -1 }))
+ eq({ all = 15, fill = 0 }, api.nvim_win_text_height(1000, { end_row = 40 }))
+ eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1001, { end_row = -1 }))
+ eq({ all = 20, fill = 5 }, api.nvim_win_text_height(1001, { end_row = 40 }))
+ eq({ all = 10, fill = 5 }, api.nvim_win_text_height(1000, { start_row = 23 }))
+ eq({ all = 13, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 18 }))
+ eq({ all = 11, fill = 0 }, api.nvim_win_text_height(1000, { end_row = 23 }))
+ eq({ all = 11, fill = 5 }, api.nvim_win_text_height(1001, { end_row = 18 }))
+ eq({ all = 11, fill = 0 }, api.nvim_win_text_height(1000, { start_row = 3, end_row = 39 }))
+ eq({ all = 11, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 1, end_row = 34 }))
+ eq({ all = 9, fill = 0 }, api.nvim_win_text_height(1000, { start_row = 4, end_row = 38 }))
+ eq({ all = 9, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 2, end_row = 33 }))
+ eq({ all = 9, fill = 0 }, api.nvim_win_text_height(1000, { start_row = 5, end_row = 37 }))
+ eq({ all = 9, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 3, end_row = 32 }))
+ eq({ all = 9, fill = 0 }, api.nvim_win_text_height(1000, { start_row = 17, end_row = 25 }))
+ eq({ all = 9, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 15, end_row = 20 }))
+ eq({ all = 7, fill = 0 }, api.nvim_win_text_height(1000, { start_row = 18, end_row = 24 }))
+ eq({ all = 7, fill = 3 }, api.nvim_win_text_height(1001, { start_row = 16, end_row = 19 }))
+ eq({ all = 6, fill = 5 }, api.nvim_win_text_height(1000, { start_row = -1 }))
+ eq({ all = 5, fill = 5 }, api.nvim_win_text_height(1000, { start_row = -1, start_vcol = X }))
+ eq(
+ { all = 0, fill = 0 },
+ api.nvim_win_text_height(1000, { start_row = -1, start_vcol = X, end_row = -1 })
+ )
+ eq(
+ { all = 0, fill = 0 },
+ api.nvim_win_text_height(
+ 1000,
+ { start_row = -1, start_vcol = X, end_row = -1, end_vcol = X }
+ )
+ )
+ eq(
+ { all = 1, fill = 0 },
+ api.nvim_win_text_height(
+ 1000,
+ { start_row = -1, start_vcol = 0, end_row = -1, end_vcol = X }
+ )
+ )
+ eq({ all = 3, fill = 2 }, api.nvim_win_text_height(1001, { end_row = 0 }))
+ eq({ all = 2, fill = 2 }, api.nvim_win_text_height(1001, { end_row = 0, end_vcol = 0 }))
+ eq(
+ { all = 2, fill = 2 },
+ api.nvim_win_text_height(1001, { start_row = 0, end_row = 0, end_vcol = 0 })
+ )
+ eq(
+ { all = 0, fill = 0 },
+ api.nvim_win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = 0 })
+ )
+ eq(
+ { all = 1, fill = 0 },
+ api.nvim_win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 0, end_vcol = X })
+ )
+ eq({ all = 11, fill = 5 }, api.nvim_win_text_height(1001, { end_row = 18 }))
+ eq(
+ { all = 9, fill = 3 },
+ api.nvim_win_text_height(1001, { start_row = 0, start_vcol = 0, end_row = 18 })
+ )
+ eq({ all = 10, fill = 5 }, api.nvim_win_text_height(1001, { end_row = 18, end_vcol = 0 }))
+ eq(
+ { all = 8, fill = 3 },
+ api.nvim_win_text_height(
+ 1001,
+ { start_row = 0, start_vcol = 0, end_row = 18, end_vcol = 0 }
+ )
+ )
end)
it('with wrapped lines', function()
- local X = meths.get_vvar('maxcol')
+ local X = api.nvim_get_vvar('maxcol')
local screen = Screen.new(45, 22)
screen:set_default_attr_ids({
- [0] = {foreground = Screen.colors.Blue1, bold = true};
- [1] = {foreground = Screen.colors.Brown};
- [2] = {background = Screen.colors.Yellow};
+ [0] = { foreground = Screen.colors.Blue1, bold = true },
+ [1] = { foreground = Screen.colors.Brown },
+ [2] = { background = Screen.colors.Yellow },
})
screen:attach()
exec([[
set number cpoptions+=n
call setline(1, repeat([repeat('foobar-', 36)], 3))
]])
- local ns = meths.create_namespace('')
- meths.buf_set_extmark(0, ns, 1, 100, { virt_text = {{('?'):rep(15), 'Search'}}, virt_text_pos = 'inline' })
- meths.buf_set_extmark(0, ns, 2, 200, { virt_text = {{('!'):rep(75), 'Search'}}, virt_text_pos = 'inline' })
- screen:expect{grid=[[
+ local ns = api.nvim_create_namespace('')
+ api.nvim_buf_set_extmark(
+ 0,
+ ns,
+ 1,
+ 100,
+ { virt_text = { { ('?'):rep(15), 'Search' } }, virt_text_pos = 'inline' }
+ )
+ api.nvim_buf_set_extmark(
+ 0,
+ ns,
+ 2,
+ 200,
+ { virt_text = { { ('!'):rep(75), 'Search' } }, virt_text_pos = 'inline' }
+ )
+ screen:expect {
+ grid = [[
{1: 1 }^foobar-foobar-foobar-foobar-foobar-foobar|
-foobar-foobar-foobar-foobar-foobar-foobar-fo|
obar-foobar-foobar-foobar-foobar-foobar-fooba|
@@ -807,133 +1017,897 @@ describe('API/win', function()
{2:!!!!!!!!!}ar-foobar-foobar-foobar-foobar-fooba|
r-foobar-foobar- |
|
- ]]}
+ ]],
+ }
screen:try_resize(45, 2)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: 1 }^foobar-foobar-foobar-foobar-foobar-foobar|
|
- ]]}
- eq({ all = 21, fill = 0 }, meths.win_text_height(0, {}))
- eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 0, end_row = 0 }))
- eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, end_row = 1 }))
- eq({ all = 8, fill = 0 }, meths.win_text_height(0, { start_row = 2, end_row = 2 }))
- eq({ all = 0, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 0 }))
- eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 41 }))
- eq({ all = 2, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 42 }))
- eq({ all = 2, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 86 }))
- eq({ all = 3, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 87 }))
- eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 266 }))
- eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 267 }))
- eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 311 }))
- eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 312 }))
- eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = X }))
- eq({ all = 7, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 40, end_row = 1, end_vcol = X }))
- eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 41, end_row = 1, end_vcol = X }))
- eq({ all = 6, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 85, end_row = 1, end_vcol = X }))
- eq({ all = 5, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = X }))
- eq({ all = 2, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 265, end_row = 1, end_vcol = X }))
- eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 266, end_row = 1, end_vcol = X }))
- eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 310, end_row = 1, end_vcol = X }))
- eq({ all = 0, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 311, end_row = 1, end_vcol = X }))
- eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = 131 }))
- eq({ all = 1, fill = 0 }, meths.win_text_height(0, { start_row = 1, start_vcol = 221, end_row = 1, end_vcol = 266 }))
- eq({ all = 18, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 131 }))
- eq({ all = 19, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 130 }))
- eq({ all = 20, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 311 }))
- eq({ all = 21, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 312 }))
- eq({ all = 17, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 131, end_row = 2, end_vcol = 311 }))
- eq({ all = 19, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 130, end_row = 2, end_vcol = 312 }))
- eq({ all = 16, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 221 }))
- eq({ all = 17, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 220 }))
- eq({ all = 14, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 41 }))
- eq({ all = 15, fill = 0 }, meths.win_text_height(0, { end_row = 2, end_vcol = 42 }))
- eq({ all = 9, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 221, end_row = 2, end_vcol = 41 }))
- eq({ all = 11, fill = 0 }, meths.win_text_height(0, { start_row = 0, start_vcol = 220, end_row = 2, end_vcol = 42 }))
+ ]],
+ }
+ eq({ all = 21, fill = 0 }, api.nvim_win_text_height(0, {}))
+ eq({ all = 6, fill = 0 }, api.nvim_win_text_height(0, { start_row = 0, end_row = 0 }))
+ eq({ all = 7, fill = 0 }, api.nvim_win_text_height(0, { start_row = 1, end_row = 1 }))
+ eq({ all = 8, fill = 0 }, api.nvim_win_text_height(0, { start_row = 2, end_row = 2 }))
+ eq(
+ { all = 0, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 0 })
+ )
+ eq(
+ { all = 1, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 41 })
+ )
+ eq(
+ { all = 2, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 42 })
+ )
+ eq(
+ { all = 2, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 86 })
+ )
+ eq(
+ { all = 3, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 87 })
+ )
+ eq(
+ { all = 6, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 266 })
+ )
+ eq(
+ { all = 7, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 267 })
+ )
+ eq(
+ { all = 7, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 311 })
+ )
+ eq(
+ { all = 7, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = 312 })
+ )
+ eq(
+ { all = 7, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 0, end_row = 1, end_vcol = X })
+ )
+ eq(
+ { all = 7, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 40, end_row = 1, end_vcol = X })
+ )
+ eq(
+ { all = 6, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 41, end_row = 1, end_vcol = X })
+ )
+ eq(
+ { all = 6, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 85, end_row = 1, end_vcol = X })
+ )
+ eq(
+ { all = 5, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = X })
+ )
+ eq(
+ { all = 2, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 265, end_row = 1, end_vcol = X })
+ )
+ eq(
+ { all = 1, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 266, end_row = 1, end_vcol = X })
+ )
+ eq(
+ { all = 1, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 310, end_row = 1, end_vcol = X })
+ )
+ eq(
+ { all = 0, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 311, end_row = 1, end_vcol = X })
+ )
+ eq(
+ { all = 1, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 1, start_vcol = 86, end_row = 1, end_vcol = 131 })
+ )
+ eq(
+ { all = 1, fill = 0 },
+ api.nvim_win_text_height(
+ 0,
+ { start_row = 1, start_vcol = 221, end_row = 1, end_vcol = 266 }
+ )
+ )
+ eq({ all = 18, fill = 0 }, api.nvim_win_text_height(0, { start_row = 0, start_vcol = 131 }))
+ eq({ all = 19, fill = 0 }, api.nvim_win_text_height(0, { start_row = 0, start_vcol = 130 }))
+ eq({ all = 20, fill = 0 }, api.nvim_win_text_height(0, { end_row = 2, end_vcol = 311 }))
+ eq({ all = 21, fill = 0 }, api.nvim_win_text_height(0, { end_row = 2, end_vcol = 312 }))
+ eq(
+ { all = 17, fill = 0 },
+ api.nvim_win_text_height(
+ 0,
+ { start_row = 0, start_vcol = 131, end_row = 2, end_vcol = 311 }
+ )
+ )
+ eq(
+ { all = 19, fill = 0 },
+ api.nvim_win_text_height(
+ 0,
+ { start_row = 0, start_vcol = 130, end_row = 2, end_vcol = 312 }
+ )
+ )
+ eq({ all = 16, fill = 0 }, api.nvim_win_text_height(0, { start_row = 0, start_vcol = 221 }))
+ eq({ all = 17, fill = 0 }, api.nvim_win_text_height(0, { start_row = 0, start_vcol = 220 }))
+ eq({ all = 14, fill = 0 }, api.nvim_win_text_height(0, { end_row = 2, end_vcol = 41 }))
+ eq({ all = 15, fill = 0 }, api.nvim_win_text_height(0, { end_row = 2, end_vcol = 42 }))
+ eq(
+ { all = 9, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 0, start_vcol = 221, end_row = 2, end_vcol = 41 })
+ )
+ eq(
+ { all = 11, fill = 0 },
+ api.nvim_win_text_height(0, { start_row = 0, start_vcol = 220, end_row = 2, end_vcol = 42 })
+ )
end)
end)
describe('open_win', function()
it('noautocmd option works', function()
command('autocmd BufEnter,BufLeave,BufWinEnter * let g:fired = 1')
- meths.open_win(meths.create_buf(true, true), true, {
- relative='win', row=3, col=3, width=12, height=3, noautocmd=true
+ api.nvim_open_win(api.nvim_create_buf(true, true), true, {
+ relative = 'win',
+ row = 3,
+ col = 3,
+ width = 12,
+ height = 3,
+ noautocmd = true,
})
- eq(0, funcs.exists('g:fired'))
- meths.open_win(meths.create_buf(true, true), true, {
- relative='win', row=3, col=3, width=12, height=3
+ eq(0, fn.exists('g:fired'))
+ api.nvim_open_win(api.nvim_create_buf(true, true), true, {
+ relative = 'win',
+ row = 3,
+ col = 3,
+ width = 12,
+ height = 3,
})
- eq(1, funcs.exists('g:fired'))
+ eq(1, fn.exists('g:fired'))
end)
- it('disallowed in cmdwin if enter=true or buf=curbuf', function()
- local new_buf = meths.create_buf(true, true)
+ it('disallowed in cmdwin if enter=true or buf=cmdwin_buf', function()
+ local new_buf = api.nvim_create_buf(true, true)
feed('q:')
- eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
- pcall_err(meths.open_win, new_buf, true, {
- relative='editor', row=5, col=5, width=5, height=5,
- }))
- eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
- pcall_err(meths.open_win, 0, false, {
- relative='editor', row=5, col=5, width=5, height=5,
- }))
-
- eq(new_buf, meths.win_get_buf(meths.open_win(new_buf, false, {
- relative='editor', row=5, col=5, width=5, height=5,
- })))
+ eq(
+ 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
+ pcall_err(api.nvim_open_win, new_buf, true, {
+ relative = 'editor',
+ row = 5,
+ col = 5,
+ width = 5,
+ height = 5,
+ })
+ )
+ eq(
+ 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
+ pcall_err(api.nvim_open_win, 0, false, {
+ relative = 'editor',
+ row = 5,
+ col = 5,
+ width = 5,
+ height = 5,
+ })
+ )
+ matches(
+ 'E11: Invalid in command%-line window; <CR> executes, CTRL%-C quits$',
+ pcall_err(
+ exec_lua,
+ [[
+ local cmdwin_buf = vim.api.nvim_get_current_buf()
+ vim.api.nvim_buf_call(vim.api.nvim_create_buf(false, true), function()
+ vim.api.nvim_open_win(cmdwin_buf, false, {
+ relative='editor', row=5, col=5, width=5, height=5,
+ })
+ end)
+ ]]
+ )
+ )
+
+ eq(
+ new_buf,
+ api.nvim_win_get_buf(api.nvim_open_win(new_buf, false, {
+ relative = 'editor',
+ row = 5,
+ col = 5,
+ width = 5,
+ height = 5,
+ }))
+ )
end)
it('aborts if buffer is invalid', function()
- local wins_before = meths.list_wins()
- eq('Invalid buffer id: 1337', pcall_err(meths.open_win, 1337, false, {
- relative='editor', row=5, col=5, width=5, height=5,
- }))
- eq(wins_before, meths.list_wins())
+ local wins_before = api.nvim_list_wins()
+ eq(
+ 'Invalid buffer id: 1337',
+ pcall_err(api.nvim_open_win, 1337, false, {
+ relative = 'editor',
+ row = 5,
+ col = 5,
+ width = 5,
+ height = 5,
+ })
+ )
+ eq(wins_before, api.nvim_list_wins())
+ end)
+
+ it('creates a split window', function()
+ local win = api.nvim_open_win(0, true, {
+ vertical = false,
+ })
+ eq('', api.nvim_win_get_config(win).relative)
+ end)
+
+ it('creates split windows in the correct direction', function()
+ local initial_win = api.nvim_get_current_win()
+ local win = api.nvim_open_win(0, true, {
+ vertical = true,
+ })
+ eq('', api.nvim_win_get_config(win).relative)
+
+ local layout = fn.winlayout()
+
+ eq({
+ 'row',
+ {
+ { 'leaf', win },
+ { 'leaf', initial_win },
+ },
+ }, layout)
+ end)
+
+ it("respects the 'split' option", function()
+ local initial_win = api.nvim_get_current_win()
+ local win = api.nvim_open_win(0, true, {
+ split = 'below',
+ })
+ eq('', api.nvim_win_get_config(win).relative)
+
+ local layout = fn.winlayout()
+
+ eq({
+ 'col',
+ {
+ { 'leaf', initial_win },
+ { 'leaf', win },
+ },
+ }, layout)
+ end)
+
+ it(
+ "doesn't change tp_curwin when splitting window in non-current tab with enter=false",
+ function()
+ local tab1 = api.nvim_get_current_tabpage()
+ local tab1_win = api.nvim_get_current_win()
+
+ helpers.command('tabnew')
+ local tab2 = api.nvim_get_current_tabpage()
+ local tab2_win = api.nvim_get_current_win()
+
+ eq({ tab1_win, tab2_win }, api.nvim_list_wins())
+ eq({ tab1, tab2 }, api.nvim_list_tabpages())
+
+ api.nvim_set_current_tabpage(tab1)
+ eq(tab1_win, api.nvim_get_current_win())
+
+ local tab2_prevwin = fn.tabpagewinnr(tab2, '#')
+
+ -- split in tab2 whine in tab2, with enter = false
+ local tab2_win2 = api.nvim_open_win(api.nvim_create_buf(false, true), false, {
+ win = tab2_win,
+ split = 'right',
+ })
+ eq(tab1_win, api.nvim_get_current_win()) -- we should still be in the first tp
+ eq(tab1_win, api.nvim_tabpage_get_win(tab1))
+
+ eq(tab2_win, api.nvim_tabpage_get_win(tab2)) -- tab2's tp_curwin should not have changed
+ eq(tab2_prevwin, fn.tabpagewinnr(tab2, '#')) -- tab2's tp_prevwin should not have changed
+ eq({ tab1_win, tab2_win, tab2_win2 }, api.nvim_list_wins())
+ eq({ tab2_win, tab2_win2 }, api.nvim_tabpage_list_wins(tab2))
+ end
+ )
+
+ it('creates splits in the correct location', function()
+ local first_win = api.nvim_get_current_win()
+ -- specifying window 0 should create a split next to the current window
+ local win = api.nvim_open_win(0, true, {
+ vertical = false,
+ })
+ local layout = fn.winlayout()
+ eq({
+ 'col',
+ {
+ { 'leaf', win },
+ { 'leaf', first_win },
+ },
+ }, layout)
+ -- not specifying a window should create a top-level split
+ local win2 = api.nvim_open_win(0, true, {
+ split = 'left',
+ win = -1,
+ })
+ layout = fn.winlayout()
+ eq({
+ 'row',
+ {
+ { 'leaf', win2 },
+ {
+ 'col',
+ {
+ { 'leaf', win },
+ { 'leaf', first_win },
+ },
+ },
+ },
+ }, layout)
+
+ -- specifying a window should create a split next to that window
+ local win3 = api.nvim_open_win(0, true, {
+ win = win,
+ vertical = false,
+ })
+ layout = fn.winlayout()
+ eq({
+ 'row',
+ {
+ { 'leaf', win2 },
+ {
+ 'col',
+ {
+ { 'leaf', win3 },
+ { 'leaf', win },
+ { 'leaf', first_win },
+ },
+ },
+ },
+ }, layout)
+ end)
+ end)
+
+ describe('set_config', function()
+ it('moves a split into a float', function()
+ local win = api.nvim_open_win(0, true, {
+ vertical = false,
+ })
+ eq('', api.nvim_win_get_config(win).relative)
+ api.nvim_win_set_config(win, {
+ relative = 'editor',
+ row = 5,
+ col = 5,
+ width = 5,
+ height = 5,
+ })
+ eq('editor', api.nvim_win_get_config(win).relative)
+ end)
+
+ it('throws error when attempting to move the last window', function()
+ local err = pcall_err(api.nvim_win_set_config, 0, {
+ vertical = false,
+ })
+ eq('Cannot move last window', err)
+ end)
+
+ it('passing retval of get_config results in no-op', function()
+ -- simple split layout
+ local win = api.nvim_open_win(0, true, {
+ split = 'left',
+ })
+ local layout = fn.winlayout()
+ local config = api.nvim_win_get_config(win)
+ api.nvim_win_set_config(win, config)
+ eq(layout, fn.winlayout())
+
+ -- nested split layout
+ local win2 = api.nvim_open_win(0, true, {
+ vertical = true,
+ })
+ local win3 = api.nvim_open_win(0, true, {
+ win = win2,
+ vertical = false,
+ })
+ layout = fn.winlayout()
+ config = api.nvim_win_get_config(win2)
+ api.nvim_win_set_config(win2, config)
+ eq(layout, fn.winlayout())
+
+ config = api.nvim_win_get_config(win3)
+ api.nvim_win_set_config(win3, config)
+ eq(layout, fn.winlayout())
+ end)
+
+ it('moves a float into a split', function()
+ local layout = fn.winlayout()
+ eq('leaf', layout[1])
+ local win = api.nvim_open_win(0, true, {
+ relative = 'editor',
+ row = 5,
+ col = 5,
+ width = 5,
+ height = 5,
+ })
+ api.nvim_win_set_config(win, {
+ split = 'below',
+ win = -1,
+ })
+ eq('', api.nvim_win_get_config(win).relative)
+ layout = fn.winlayout()
+ eq('col', layout[1])
+ eq(2, #layout[2])
+ eq(win, layout[2][2][2])
+ end)
+
+ it('respects the "split" option', function()
+ local layout = fn.winlayout()
+ eq('leaf', layout[1])
+ local first_win = layout[2]
+ local win = api.nvim_open_win(0, true, {
+ relative = 'editor',
+ row = 5,
+ col = 5,
+ width = 5,
+ height = 5,
+ })
+ api.nvim_win_set_config(win, {
+ split = 'right',
+ win = first_win,
+ })
+ layout = fn.winlayout()
+ eq('row', layout[1])
+ eq(2, #layout[2])
+ eq(win, layout[2][2][2])
+ local config = api.nvim_win_get_config(win)
+ eq('', config.relative)
+ eq('right', config.split)
+ api.nvim_win_set_config(win, {
+ split = 'below',
+ win = first_win,
+ })
+ layout = fn.winlayout()
+ eq('col', layout[1])
+ eq(2, #layout[2])
+ eq(win, layout[2][2][2])
+ config = api.nvim_win_get_config(win)
+ eq('', config.relative)
+ eq('below', config.split)
+ end)
+
+ it('creates top-level splits', function()
+ local win = api.nvim_open_win(0, true, {
+ vertical = false,
+ })
+ local win2 = api.nvim_open_win(0, true, {
+ vertical = true,
+ win = -1,
+ })
+ local layout = fn.winlayout()
+ eq('row', layout[1])
+ eq(2, #layout[2])
+ eq(win2, layout[2][1][2])
+ api.nvim_win_set_config(win, {
+ split = 'below',
+ win = -1,
+ })
+ layout = fn.winlayout()
+ eq('col', layout[1])
+ eq(2, #layout[2])
+ eq('row', layout[2][1][1])
+ eq(win, layout[2][2][2])
+ end)
+
+ it('moves splits to other tabpages', function()
+ local curtab = api.nvim_get_current_tabpage()
+ local win = api.nvim_open_win(0, false, { split = 'left' })
+ command('tabnew')
+ local tabnr = api.nvim_get_current_tabpage()
+ command('tabprev') -- return to the initial tab
+
+ api.nvim_win_set_config(win, {
+ split = 'right',
+ win = api.nvim_tabpage_get_win(tabnr),
+ })
+
+ eq(tabnr, api.nvim_win_get_tabpage(win))
+ -- we are changing the config, the current tabpage should not change
+ eq(curtab, api.nvim_get_current_tabpage())
+
+ command('tabnext') -- switch to the new tabpage so we can get the layout
+ local layout = fn.winlayout()
+
+ eq({
+ 'row',
+ {
+ { 'leaf', api.nvim_tabpage_get_win(tabnr) },
+ { 'leaf', win },
+ },
+ }, layout)
+ end)
+
+ it('correctly moves curwin when moving curwin to a different tabpage', function()
+ local curtab = api.nvim_get_current_tabpage()
+ command('tabnew')
+ local tab2 = api.nvim_get_current_tabpage()
+ local tab2_win = api.nvim_get_current_win()
+
+ command('tabprev') -- return to the initial tab
+
+ local neighbor = api.nvim_get_current_win()
+
+ -- create and enter a new split
+ local win = api.nvim_open_win(0, true, {
+ vertical = false,
+ })
+
+ eq(curtab, api.nvim_win_get_tabpage(win))
+
+ eq({ win, neighbor }, api.nvim_tabpage_list_wins(curtab))
+
+ -- move the current win to a different tabpage
+ api.nvim_win_set_config(win, {
+ split = 'right',
+ win = api.nvim_tabpage_get_win(tab2),
+ })
+
+ eq(curtab, api.nvim_get_current_tabpage())
+
+ -- win should have moved to tab2
+ eq(tab2, api.nvim_win_get_tabpage(win))
+ -- tp_curwin of tab2 should not have changed
+ eq(tab2_win, api.nvim_tabpage_get_win(tab2))
+ -- win lists should be correct
+ eq({ tab2_win, win }, api.nvim_tabpage_list_wins(tab2))
+ eq({ neighbor }, api.nvim_tabpage_list_wins(curtab))
+
+ -- current win should have moved to neighboring win
+ eq(neighbor, api.nvim_tabpage_get_win(curtab))
+ end)
+
+ it('splits windows in non-current tabpage', function()
+ local curtab = api.nvim_get_current_tabpage()
+ command('tabnew')
+ local tabnr = api.nvim_get_current_tabpage()
+ command('tabprev') -- return to the initial tab
+
+ local win = api.nvim_open_win(0, false, {
+ vertical = false,
+ win = api.nvim_tabpage_get_win(tabnr),
+ })
+
+ eq(tabnr, api.nvim_win_get_tabpage(win))
+ -- since enter = false, the current tabpage should not change
+ eq(curtab, api.nvim_get_current_tabpage())
+ end)
+
+ it('moves the current split window', function()
+ local initial_win = api.nvim_get_current_win()
+ local win = api.nvim_open_win(0, true, {
+ vertical = true,
+ })
+ local win2 = api.nvim_open_win(0, true, {
+ vertical = true,
+ })
+ api.nvim_set_current_win(win)
+ eq({
+ 'row',
+ {
+ { 'leaf', win2 },
+ { 'leaf', win },
+ { 'leaf', initial_win },
+ },
+ }, fn.winlayout())
+
+ api.nvim_win_set_config(0, {
+ vertical = false,
+ win = 0,
+ })
+ eq(win, api.nvim_get_current_win())
+ eq({
+ 'col',
+ {
+ { 'leaf', win },
+ {
+ 'row',
+ {
+ { 'leaf', win2 },
+ { 'leaf', initial_win },
+ },
+ },
+ },
+ }, fn.winlayout())
+
+ api.nvim_set_current_win(win2)
+ local win3 = api.nvim_open_win(0, true, {
+ vertical = true,
+ })
+ eq(win3, api.nvim_get_current_win())
+
+ eq({
+ 'col',
+ {
+ { 'leaf', win },
+ {
+ 'row',
+ {
+ { 'leaf', win3 },
+ { 'leaf', win2 },
+ { 'leaf', initial_win },
+ },
+ },
+ },
+ }, fn.winlayout())
+
+ api.nvim_win_set_config(0, {
+ vertical = false,
+ win = 0,
+ })
+
+ eq(win3, api.nvim_get_current_win())
+ eq({
+ 'col',
+ {
+ { 'leaf', win },
+ {
+ 'row',
+ {
+ {
+ 'col',
+ {
+ { 'leaf', win3 },
+ { 'leaf', win2 },
+ },
+ },
+ { 'leaf', initial_win },
+ },
+ },
+ },
+ }, fn.winlayout())
end)
end)
describe('get_config', function()
it('includes border', function()
local b = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h' }
- local win = meths.open_win(0, true, {
- relative='win', row=3, col=3, width=12, height=3,
+ local win = api.nvim_open_win(0, true, {
+ relative = 'win',
+ row = 3,
+ col = 3,
+ width = 12,
+ height = 3,
border = b,
})
- local cfg = meths.win_get_config(win)
+ local cfg = api.nvim_win_get_config(win)
eq(b, cfg.border)
end)
it('includes border with highlight group', function()
local b = {
- {'a', 'Normal'},
- {'b', 'Special'},
- {'c', 'String'},
- {'d', 'Comment'},
- {'e', 'Visual'},
- {'f', 'Error'},
- {'g', 'Constant'},
- {'h', 'PreProc'},
+ { 'a', 'Normal' },
+ { 'b', 'Special' },
+ { 'c', 'String' },
+ { 'd', 'Comment' },
+ { 'e', 'Visual' },
+ { 'f', 'Error' },
+ { 'g', 'Constant' },
+ { 'h', 'PreProc' },
}
- local win = meths.open_win(0, true, {
- relative='win', row=3, col=3, width=12, height=3,
+ local win = api.nvim_open_win(0, true, {
+ relative = 'win',
+ row = 3,
+ col = 3,
+ width = 12,
+ height = 3,
border = b,
})
- local cfg = meths.win_get_config(win)
+ local cfg = api.nvim_win_get_config(win)
eq(b, cfg.border)
end)
it('includes title and footer', function()
- local title = { {'A', {'StatusLine', 'TabLine'}}, {'B'}, {'C', 'WinBar'} }
- local footer = { {'A', 'WinBar'}, {'B'}, {'C', {'StatusLine', 'TabLine'}} }
- local win = meths.open_win(0, true, {
- relative='win', row=3, col=3, width=12, height=3,
- border = 'single', title = title, footer = footer,
+ local title = { { 'A', { 'StatusLine', 'TabLine' } }, { 'B' }, { 'C', 'WinBar' } }
+ local footer = { { 'A', 'WinBar' }, { 'B' }, { 'C', { 'StatusLine', 'TabLine' } } }
+ local win = api.nvim_open_win(0, true, {
+ relative = 'win',
+ row = 3,
+ col = 3,
+ width = 12,
+ height = 3,
+ border = 'single',
+ title = title,
+ footer = footer,
})
- local cfg = meths.win_get_config(win)
+ local cfg = api.nvim_win_get_config(win)
eq(title, cfg.title)
eq(footer, cfg.footer)
end)
+
+ it('includes split for normal windows', function()
+ local win = api.nvim_open_win(0, true, {
+ vertical = true,
+ win = -1,
+ })
+ eq('left', api.nvim_win_get_config(win).split)
+ api.nvim_win_set_config(win, {
+ vertical = false,
+ win = -1,
+ })
+ eq('above', api.nvim_win_get_config(win).split)
+ api.nvim_win_set_config(win, {
+ split = 'below',
+ win = -1,
+ })
+ eq('below', api.nvim_win_get_config(win).split)
+ end)
+
+ it('includes split when splitting with ex commands', function()
+ local win = api.nvim_get_current_win()
+ eq('left', api.nvim_win_get_config(win).split)
+
+ command('vsplit')
+ local win2 = api.nvim_get_current_win()
+
+ -- initial window now be marked as right split
+ -- since it was split with a vertical split
+ -- and 'splitright' is false by default
+ eq('right', api.nvim_win_get_config(win).split)
+ eq('left', api.nvim_win_get_config(win2).split)
+
+ api.nvim_set_option_value('splitbelow', true, {
+ scope = 'global',
+ })
+ api.nvim_win_close(win, true)
+ command('split')
+ local win3 = api.nvim_get_current_win()
+ eq('below', api.nvim_win_get_config(win3).split)
+ end)
+
+ it("includes the correct 'split' option in complex layouts", function()
+ local initial_win = api.nvim_get_current_win()
+ local win = api.nvim_open_win(0, false, {
+ split = 'right',
+ win = -1,
+ })
+
+ local win2 = api.nvim_open_win(0, false, {
+ split = 'below',
+ win = win,
+ })
+
+ api.nvim_win_set_config(win2, {
+ width = 50,
+ })
+
+ api.nvim_win_set_config(win, {
+ split = 'left',
+ win = -1,
+ })
+
+ local win3 = api.nvim_open_win(0, false, {
+ split = 'above',
+ win = -1,
+ })
+ local float = api.nvim_open_win(0, false, {
+ relative = 'editor',
+ width = 40,
+ height = 20,
+ col = 20,
+ row = 10,
+ })
+ api.nvim_win_set_config(float, {
+ split = 'right',
+ win = -1,
+ })
+
+ local layout = fn.winlayout()
+
+ eq({
+ 'row',
+ {
+ {
+ 'col',
+ {
+ { 'leaf', win3 },
+ {
+ 'row',
+ {
+ { 'leaf', win },
+ { 'leaf', initial_win },
+ { 'leaf', win2 },
+ },
+ },
+ },
+ },
+ {
+ 'leaf',
+ float,
+ },
+ },
+ }, layout)
+
+ eq('above', api.nvim_win_get_config(win3).split)
+ eq('left', api.nvim_win_get_config(win).split)
+ eq('left', api.nvim_win_get_config(initial_win).split)
+ eq('right', api.nvim_win_get_config(win2).split)
+ eq('right', api.nvim_win_get_config(float).split)
+ end)
+ end)
+
+ describe('set_config', function()
+ it('no crash with invalid title', function()
+ local win = api.nvim_open_win(0, true, {
+ width = 10,
+ height = 10,
+ relative = 'editor',
+ row = 10,
+ col = 10,
+ title = { { 'test' } },
+ border = 'single',
+ })
+ eq(
+ 'title/footer cannot be an empty array',
+ pcall_err(api.nvim_win_set_config, win, { title = {} })
+ )
+ command('redraw!')
+ assert_alive()
+ end)
+
+ it('no crash with invalid footer', function()
+ local win = api.nvim_open_win(0, true, {
+ width = 10,
+ height = 10,
+ relative = 'editor',
+ row = 10,
+ col = 10,
+ footer = { { 'test' } },
+ border = 'single',
+ })
+ eq(
+ 'title/footer cannot be an empty array',
+ pcall_err(api.nvim_win_set_config, win, { footer = {} })
+ )
+ command('redraw!')
+ assert_alive()
+ end)
+ end)
+
+ describe('set_config', function()
+ it('no crash with invalid title', function()
+ local win = api.nvim_open_win(0, true, {
+ width = 10,
+ height = 10,
+ relative = 'editor',
+ row = 10,
+ col = 10,
+ title = { { 'test' } },
+ border = 'single',
+ })
+ eq(
+ 'title/footer cannot be an empty array',
+ pcall_err(api.nvim_win_set_config, win, { title = {} })
+ )
+ command('redraw!')
+ assert_alive()
+ end)
+
+ it('no crash with invalid footer', function()
+ local win = api.nvim_open_win(0, true, {
+ width = 10,
+ height = 10,
+ relative = 'editor',
+ row = 10,
+ col = 10,
+ footer = { { 'test' } },
+ border = 'single',
+ })
+ eq(
+ 'title/footer cannot be an empty array',
+ pcall_err(api.nvim_win_set_config, win, { footer = {} })
+ )
+ command('redraw!')
+ assert_alive()
+ end)
end)
end)
diff --git a/test/functional/autocmd/autocmd_oldtest_spec.lua b/test/functional/autocmd/autocmd_oldtest_spec.lua
index dfd746a06e..0243674f2d 100644
--- a/test/functional/autocmd/autocmd_oldtest_spec.lua
+++ b/test/functional/autocmd/autocmd_oldtest_spec.lua
@@ -3,8 +3,8 @@ local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local eq = helpers.eq
-local meths = helpers.meths
-local funcs = helpers.funcs
+local api = helpers.api
+local fn = helpers.fn
local exec = helpers.exec
local feed = helpers.feed
@@ -12,7 +12,7 @@ describe('oldtests', function()
before_each(clear)
local exec_lines = function(str)
- return funcs.split(funcs.execute(str), "\n")
+ return fn.split(fn.execute(str), '\n')
end
local add_an_autocmd = function()
@@ -23,7 +23,7 @@ describe('oldtests', function()
]]
eq(3, #exec_lines('au vimBarTest'))
- eq(1, #meths.get_autocmds({ group = 'vimBarTest' }))
+ eq(1, #api.nvim_get_autocmds({ group = 'vimBarTest' }))
end
it('should recognize a bar before the {event}', function()
@@ -31,14 +31,13 @@ describe('oldtests', function()
add_an_autocmd()
exec [[ augroup vimBarTest | au! | augroup END ]]
eq(1, #exec_lines('au vimBarTest'))
- eq({}, meths.get_autocmds({ group = 'vimBarTest' }))
+ eq({}, api.nvim_get_autocmds({ group = 'vimBarTest' }))
-- Sad spacing
add_an_autocmd()
exec [[ augroup vimBarTest| au!| augroup END ]]
eq(1, #exec_lines('au vimBarTest'))
-
-- test that a bar is recognized after the {event}
add_an_autocmd()
exec [[ augroup vimBarTest| au!BufReadCmd| augroup END ]]
@@ -50,8 +49,8 @@ describe('oldtests', function()
end)
it('should fire on unload buf', function()
- funcs.writefile({'Test file Xxx1'}, 'Xxx1')
- funcs.writefile({'Test file Xxx2'}, 'Xxx2')
+ fn.writefile({ 'Test file Xxx1' }, 'Xxx1')
+ fn.writefile({ 'Test file Xxx2' }, 'Xxx2')
local fname = 'Xtest_functional_autocmd_unload'
local content = [[
@@ -72,16 +71,16 @@ describe('oldtests', function()
q
]]
- funcs.writefile(funcs.split(content, "\n"), fname)
+ fn.writefile(fn.split(content, '\n'), fname)
- funcs.delete('Xout')
- funcs.system(string.format('%s -u NORC -i NONE -N -S %s', meths.get_vvar('progpath'), fname))
- eq(1, funcs.filereadable('Xout'))
+ fn.delete('Xout')
+ fn.system(string.format('%s --clean -N -S %s', api.nvim_get_vvar('progpath'), fname))
+ eq(1, fn.filereadable('Xout'))
- funcs.delete('Xxx1')
- funcs.delete('Xxx2')
- funcs.delete(fname)
- funcs.delete('Xout')
+ fn.delete('Xxx1')
+ fn.delete('Xxx2')
+ fn.delete(fname)
+ fn.delete('Xout')
end)
-- oldtest: Test_delete_ml_get_errors()
@@ -89,7 +88,7 @@ describe('oldtests', function()
local screen = Screen.new(75, 10)
screen:attach()
screen:set_default_attr_ids({
- [1] = {background = Screen.colors.Cyan};
+ [1] = { background = Screen.colors.Cyan },
})
exec([[
set noshowcmd noruler scrolloff=0
@@ -97,7 +96,8 @@ describe('oldtests', function()
edit test/old/testdir/samples/box.txt
]])
feed('249GV<C-End>d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
const auto themeEmoji = _forPeer->themeEmoji(); |
if (themeEmoji.isEmpty()) { |
return nonCustom; |
@@ -108,9 +108,11 @@ describe('oldtests', function()
return nonCustom; |
{1:^}} |
353 fewer lines |
- ]]}
+ ]],
+ }
feed('<PageUp>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
auto BackgroundBox::Inner::resolveResetCustomPaper() const |
-> std::optional<Data::WallPaper> { |
@@ -121,6 +123,7 @@ describe('oldtests', function()
const auto themeEmoji = _forPeer->themeEmoji(); |
^if (themeEmoji.isEmpty()) { |
353 fewer lines |
- ]]}
+ ]],
+ }
end)
end)
diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua
index 63a487c8bc..5fffb70095 100644
--- a/test/functional/autocmd/autocmd_spec.lua
+++ b/test/functional/autocmd/autocmd_spec.lua
@@ -10,14 +10,13 @@ local eval = helpers.eval
local feed = helpers.feed
local clear = helpers.clear
local matches = helpers.matches
-local meths = helpers.meths
+local api = helpers.api
local pcall_err = helpers.pcall_err
-local funcs = helpers.funcs
+local fn = helpers.fn
local expect = helpers.expect
local command = helpers.command
local exc_exec = helpers.exc_exec
local exec_lua = helpers.exec_lua
-local curbufmeths = helpers.curbufmeths
local retry = helpers.retry
local source = helpers.source
@@ -26,23 +25,23 @@ describe('autocmd', function()
it(':tabnew, :split, :close events order, <afile>', function()
local expected = {
- {'WinLeave', ''},
- {'TabLeave', ''},
- {'WinEnter', ''},
- {'TabNew', 'testfile1'}, -- :tabnew
- {'TabEnter', ''},
- {'BufLeave', ''},
- {'BufEnter', 'testfile1'}, -- :split
- {'WinLeave', 'testfile1'},
- {'WinEnter', 'testfile1'},
- {'WinLeave', 'testfile1'},
- {'WinClosed', '1002'}, -- :close, WinClosed <afile> = window-id
- {'WinEnter', 'testfile1'},
- {'WinLeave', 'testfile1'}, -- :bdelete
- {'WinEnter', 'testfile1'},
- {'BufLeave', 'testfile1'},
- {'BufEnter', 'testfile2'},
- {'WinClosed', '1000'},
+ { 'WinLeave', '' },
+ { 'TabLeave', '' },
+ { 'WinEnter', '' },
+ { 'TabNew', 'testfile1' }, -- :tabnew
+ { 'TabEnter', '' },
+ { 'BufLeave', '' },
+ { 'BufEnter', 'testfile1' }, -- :split
+ { 'WinLeave', 'testfile1' },
+ { 'WinEnter', 'testfile1' },
+ { 'WinLeave', 'testfile1' },
+ { 'WinClosed', '1002' }, -- :close, WinClosed <afile> = window-id
+ { 'WinEnter', 'testfile1' },
+ { 'WinLeave', 'testfile1' }, -- :bdelete
+ { 'WinEnter', 'testfile1' },
+ { 'BufLeave', 'testfile1' },
+ { 'BufEnter', 'testfile2' },
+ { 'WinClosed', '1000' },
}
command('let g:evs = []')
command('autocmd BufEnter * :call add(g:evs, ["BufEnter", expand("<afile>")])')
@@ -63,10 +62,10 @@ describe('autocmd', function()
it('first edit causes BufUnload on NoName', function()
local expected = {
- {'BufUnload', ''},
- {'BufDelete', ''},
- {'BufWipeout', ''},
- {'BufEnter', 'testfile1'},
+ { 'BufUnload', '' },
+ { 'BufDelete', '' },
+ { 'BufWipeout', '' },
+ { 'BufEnter', 'testfile1' },
}
command('let g:evs = []')
command('autocmd BufEnter * :call add(g:evs, ["BufEnter", expand("<afile>")])')
@@ -106,20 +105,23 @@ describe('autocmd', function()
local buf1 = eval("bufnr('%')")
command('new')
local buf2 = eval("bufnr('%')")
- command('autocmd WinClosed <buffer> :call add(g:evs, ["WinClosed", expand("<abuf>")])'
- -- Attempt recursion.
- ..' | bdelete '..buf2)
+ command(
+ 'autocmd WinClosed <buffer> :call add(g:evs, ["WinClosed", expand("<abuf>")])'
+ -- Attempt recursion.
+ .. ' | bdelete '
+ .. buf2
+ )
command('tabedit testfile2')
command('tabedit testfile3')
- command('bdelete '..buf2)
+ command('bdelete ' .. buf2)
-- Non-recursive: only triggered once.
eq({
- {'WinClosed', '2'},
+ { 'WinClosed', '2' },
}, eval('g:evs'))
- command('bdelete '..buf1)
+ command('bdelete ' .. buf1)
eq({
- {'WinClosed', '2'},
- {'WinClosed', '1'},
+ { 'WinClosed', '2' },
+ { 'WinClosed', '1' },
}, eval('g:evs'))
end)
@@ -130,7 +132,7 @@ describe('autocmd', function()
command('new')
command('close')
eq({
- {'WinClosed', '1001'},
+ { 'WinClosed', '1001' },
}, eval('g:evs'))
end)
@@ -139,16 +141,15 @@ describe('autocmd', function()
end)
describe('BufLeave autocommand', function()
- it('can wipe out the buffer created by :edit which triggered autocmd',
- function()
- meths.set_option_value('hidden', true, {})
- curbufmeths.set_lines(0, 1, false, {
+ it('can wipe out the buffer created by :edit which triggered autocmd', function()
+ api.nvim_set_option_value('hidden', true, {})
+ api.nvim_buf_set_lines(0, 0, 1, false, {
'start of test file xx',
- 'end of test file xx'})
+ 'end of test file xx',
+ })
command('autocmd BufLeave * bwipeout yy')
- eq('Vim(edit):E143: Autocommands unexpectedly deleted new buffer yy',
- exc_exec('edit yy'))
+ eq('Vim(edit):E143: Autocommands unexpectedly deleted new buffer yy', exc_exec('edit yy'))
expect([[
start of test file xx
@@ -156,7 +157,7 @@ describe('autocmd', function()
end)
end)
- it('++once', function() -- :help autocmd-once
+ it('++once', function() -- :help autocmd-once
--
-- ":autocmd ... ++once" executes its handler once, then removes the handler.
--
@@ -177,7 +178,8 @@ describe('autocmd', function()
command('autocmd TabNew * ++once :call add(g:foo, "Once2")')
command('autocmd TabNew * :call add(g:foo, "Many2")')
command('autocmd TabNew * ++once :call add(g:foo, "Once3")')
- eq(dedent([[
+ eq(
+ dedent([[
--- Autocommands ---
TabNew
@@ -186,18 +188,21 @@ describe('autocmd', function()
:call add(g:foo, "Once2")
:call add(g:foo, "Many2")
:call add(g:foo, "Once3")]]),
- funcs.execute('autocmd Tabnew'))
+ fn.execute('autocmd Tabnew')
+ )
command('tabnew')
command('tabnew')
command('tabnew')
eq(expected, eval('g:foo'))
- eq(dedent([[
+ eq(
+ dedent([[
--- Autocommands ---
TabNew
* :call add(g:foo, "Many1")
:call add(g:foo, "Many2")]]),
- funcs.execute('autocmd Tabnew'))
+ fn.execute('autocmd Tabnew')
+ )
--
-- ":autocmd ... ++once" handlers can be deleted.
@@ -218,7 +223,9 @@ describe('autocmd', function()
}
command('let g:foo = []')
command('autocmd OptionSet binary ++nested ++once :call add(g:foo, "OptionSet-Once")')
- command('autocmd CursorMoved <buffer> ++once ++nested setlocal binary|:call add(g:foo, "CursorMoved-Once")')
+ command(
+ 'autocmd CursorMoved <buffer> ++once ++nested setlocal binary|:call add(g:foo, "CursorMoved-Once")'
+ )
command("put ='foo bar baz'")
feed('0llhlh')
eq(expected, eval('g:foo'))
@@ -231,15 +238,17 @@ describe('autocmd', function()
'Once2',
}
command('let g:foo = []')
- command('autocmd! TabNew') -- Clear all TabNew handlers.
+ command('autocmd! TabNew') -- Clear all TabNew handlers.
command('autocmd TabNew * ++once :call add(g:foo, "Once1")')
command('autocmd TabNew * ++once :call add(g:foo, "Once2")')
command('tabnew')
eq(expected, eval('g:foo'))
- eq(dedent([[
+ eq(
+ dedent([[
--- Autocommands ---]]),
- funcs.execute('autocmd Tabnew'))
+ fn.execute('autocmd Tabnew')
+ )
end)
it('internal `aucmd_win` window', function()
@@ -250,9 +259,13 @@ describe('autocmd', function()
local screen = Screen.new(50, 10)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {background = Screen.colors.LightMagenta},
- [3] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue1},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { background = Screen.colors.LightMagenta },
+ [3] = {
+ background = Screen.colors.LightMagenta,
+ bold = true,
+ foreground = Screen.colors.Blue1,
+ },
})
source([[
@@ -272,96 +285,67 @@ describe('autocmd', function()
]])
screen:expect([[
^bb |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
|
]])
- feed(":enew | doautoall User<cr>")
+ feed(':enew | doautoall User<cr>')
screen:expect([[
{2:bb }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {3:~ }|*4
+ {1:~ }|*4
^:enew | doautoall User |
]])
feed('<cr>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
13 |
]])
eq(7, eval('g:test'))
-- API calls are blocked when aucmd_win is not in scope
- eq('Vim(call):E5555: API call: Invalid window id: 1001',
- pcall_err(command, "call nvim_set_current_win(g:winid)"))
+ eq(
+ 'Vim(call):E5555: API call: Invalid window id: 1001',
+ pcall_err(command, 'call nvim_set_current_win(g:winid)')
+ )
-- second time aucmd_win is needed, a different code path is invoked
-- to reuse the same window, so check again
- command("let g:test = v:null")
- command("let g:had_value = v:null")
- feed(":doautoall User<cr>")
+ command('let g:test = v:null')
+ command('let g:had_value = v:null')
+ feed(':doautoall User<cr>')
screen:expect([[
{2:bb }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {3:~ }|*4
+ {1:~ }|*4
^:doautoall User |
]])
feed('<cr>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
13 |
]])
-- win vars in aucmd_win should have been reset
eq(0, eval('g:had_value'))
eq(7, eval('g:test'))
- eq('Vim(call):E5555: API call: Invalid window id: 1001',
- pcall_err(command, "call nvim_set_current_win(g:winid)"))
+ eq(
+ 'Vim(call):E5555: API call: Invalid window id: 1001',
+ pcall_err(command, 'call nvim_set_current_win(g:winid)')
+ )
end)
- it("`aucmd_win` cannot be changed into a normal window #13699", function()
+ it('`aucmd_win` cannot be changed into a normal window #13699', function()
local screen = Screen.new(50, 10)
screen:attach()
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {reverse = true},
- [3] = {bold = true, reverse = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { reverse = true },
+ [3] = { bold = true, reverse = true },
}
-- Create specific layout and ensure it's left unchanged.
@@ -373,11 +357,7 @@ describe('autocmd', function()
]]
screen:expect [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{3:[No Name] }|
|
{2:[No Name] }|
@@ -408,13 +388,16 @@ describe('autocmd', function()
-- After all of our messing around, aucmd_win should still be floating.
-- Use :only to ensure _G.buf is hidden again (so the aucmd_win is used).
- eq("editor", exec_lua [[
+ eq(
+ 'editor',
+ exec_lua [[
vim.cmd "only"
vim.api.nvim_buf_call(_G.buf, function()
_G.config = vim.api.nvim_win_get_config(0)
end)
return _G.config.relative
- ]])
+ ]]
+ )
end)
describe('closing last non-floating window in tab from `aucmd_win`', function()
@@ -425,14 +408,22 @@ describe('autocmd', function()
end)
it('gives E814 when there are no other floating windows', function()
- eq('BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
- pcall_err(command, 'doautoall BufAdd'))
+ eq(
+ 'BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
+ pcall_err(command, 'doautoall BufAdd')
+ )
end)
it('gives E814 when there are other floating windows', function()
- meths.open_win(0, true, {width = 10, height = 10, relative = 'editor', row = 10, col = 10})
- eq('BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
- pcall_err(command, 'doautoall BufAdd'))
+ api.nvim_open_win(
+ 0,
+ true,
+ { width = 10, height = 10, relative = 'editor', row = 10, col = 10 }
+ )
+ eq(
+ 'BufAdd Autocommands for "Xa.txt": Vim(close):E814: Cannot close window, only autocmd window would remain',
+ pcall_err(command, 'doautoall BufAdd')
+ )
end)
end)
@@ -441,84 +432,116 @@ describe('autocmd', function()
vim.cmd('tabnew')
_G.buf = vim.api.nvim_create_buf(true, true)
]])
- matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[
+ matches(
+ 'Vim:E813: Cannot close autocmd window$',
+ pcall_err(
+ exec_lua,
+ [[
vim.api.nvim_buf_call(_G.buf, function()
local win = vim.api.nvim_get_current_win()
vim.api.nvim_win_close(win, true)
end)
- ]]))
- matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ 'Vim:E813: Cannot close autocmd window$',
+ pcall_err(
+ exec_lua,
+ [[
vim.api.nvim_buf_call(_G.buf, function()
local win = vim.api.nvim_get_current_win()
vim.cmd('tabnext')
vim.api.nvim_win_close(win, true)
end)
- ]]))
- matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ 'Vim:E813: Cannot close autocmd window$',
+ pcall_err(
+ exec_lua,
+ [[
vim.api.nvim_buf_call(_G.buf, function()
local win = vim.api.nvim_get_current_win()
vim.api.nvim_win_hide(win)
end)
- ]]))
- matches('Vim:E813: Cannot close autocmd window$', pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ 'Vim:E813: Cannot close autocmd window$',
+ pcall_err(
+ exec_lua,
+ [[
vim.api.nvim_buf_call(_G.buf, function()
local win = vim.api.nvim_get_current_win()
vim.cmd('tabnext')
vim.api.nvim_win_hide(win)
end)
- ]]))
+ ]]
+ )
+ )
end)
it(':doautocmd does not warn "No matching autocommands" #10689', function()
local screen = Screen.new(32, 3)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
})
feed(':doautocmd User Foo<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
{1:~ }|
:doautocmd User Foo |
- ]]}
+ ]],
+ }
feed(':autocmd! SessionLoadPost<cr>')
feed(':doautocmd SessionLoadPost<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
{1:~ }|
:doautocmd SessionLoadPost |
- ]]}
+ ]],
+ }
end)
describe('v:event is readonly #18063', function()
it('during ChanOpen event', function()
command('autocmd ChanOpen * let v:event.info.id = 0')
- funcs.jobstart({'cat'})
+ fn.jobstart({ 'cat' })
retry(nil, nil, function()
- eq('E46: Cannot change read-only variable "v:event.info"', meths.get_vvar('errmsg'))
+ eq('E46: Cannot change read-only variable "v:event.info"', api.nvim_get_vvar('errmsg'))
end)
end)
it('during ChanOpen event', function()
command('autocmd ChanInfo * let v:event.info.id = 0')
- meths.set_client_info('foo', {}, 'remote', {}, {})
+ api.nvim_set_client_info('foo', {}, 'remote', {}, {})
retry(nil, nil, function()
- eq('E46: Cannot change read-only variable "v:event.info"', meths.get_vvar('errmsg'))
+ eq('E46: Cannot change read-only variable "v:event.info"', api.nvim_get_vvar('errmsg'))
end)
end)
it('during RecordingLeave event', function()
command([[autocmd RecordingLeave * let v:event.regname = '']])
- eq('RecordingLeave Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.regname"',
- pcall_err(command, 'normal! qqq'))
+ eq(
+ 'RecordingLeave Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.regname"',
+ pcall_err(command, 'normal! qqq')
+ )
end)
it('during TermClose event', function()
command('autocmd TermClose * let v:event.status = 0')
command('terminal')
- eq('TermClose Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.status"',
- pcall_err(command, 'bdelete!'))
+ eq(
+ 'TermClose Autocommands for "*": Vim(let):E46: Cannot change read-only variable "v:event.status"',
+ pcall_err(command, 'bdelete!')
+ )
end)
end)
@@ -554,7 +577,7 @@ describe('autocmd', function()
call assert_fails('au WinNew * ++once ++once echo bad', 'E983:')
]]
- meths.set_var('did_split', 0)
+ api.nvim_set_var('did_split', 0)
source [[
augroup Testing
@@ -566,11 +589,11 @@ describe('autocmd', function()
split
]]
- eq(2, meths.get_var('did_split'))
- eq(1, funcs.exists('#WinNew'))
+ eq(2, api.nvim_get_var('did_split'))
+ eq(1, fn.exists('#WinNew'))
-- Now with once
- meths.set_var('did_split', 0)
+ api.nvim_set_var('did_split', 0)
source [[
augroup Testing
@@ -582,13 +605,16 @@ describe('autocmd', function()
split
]]
- eq(1, meths.get_var('did_split'))
- eq(0, funcs.exists('#WinNew'))
+ eq(1, api.nvim_get_var('did_split'))
+ eq(0, fn.exists('#WinNew'))
-- call assert_fails('au WinNew * ++once ++once echo bad', 'E983:')
- local ok, msg = pcall(source, [[
+ local ok, msg = pcall(
+ source,
+ [[
au WinNew * ++once ++once echo bad
- ]])
+ ]]
+ )
eq(false, ok)
eq(true, not not string.find(msg, 'E983:'))
@@ -596,7 +622,7 @@ describe('autocmd', function()
it('should have autocmds in filetypedetect group', function()
source [[filetype on]]
- neq({}, meths.get_autocmds { group = "filetypedetect" })
+ neq({}, api.nvim_get_autocmds { group = 'filetypedetect' })
end)
it('should allow comma-separated patterns', function()
@@ -608,7 +634,7 @@ describe('autocmd', function()
augroup END
]]
- eq(4, #meths.get_autocmds { event = "BufReadCmd", group = "TestingPatterns" })
+ eq(4, #api.nvim_get_autocmds { event = 'BufReadCmd', group = 'TestingPatterns' })
end)
end)
@@ -627,7 +653,7 @@ describe('autocmd', function()
})
vim.cmd "tabnew"
]]
- eq(1, eval('g:count')) -- Added autocommands should not be executed
+ eq(1, eval('g:count')) -- Added autocommands should not be executed
end)
it('no crash when clearing a group inside a callback #23355', function()
diff --git a/test/functional/autocmd/bufenter_spec.lua b/test/functional/autocmd/bufenter_spec.lua
index 47f4adb0d6..af0dd887fa 100644
--- a/test/functional/autocmd/bufenter_spec.lua
+++ b/test/functional/autocmd/bufenter_spec.lua
@@ -12,9 +12,9 @@ describe('autocmd BufEnter', function()
it("triggered by nvim_command('edit <dir>')", function()
command("autocmd BufEnter * if isdirectory(expand('<afile>')) | let g:dir_bufenter = 1 | endif")
- request("nvim_command", "split .")
- eq(1, eval("exists('g:dir_bufenter')")) -- Did BufEnter for the directory.
- eq(2, eval("bufnr('%')")) -- Switched to the dir buffer.
+ request('nvim_command', 'split .')
+ eq(1, eval("exists('g:dir_bufenter')")) -- Did BufEnter for the directory.
+ eq(2, eval("bufnr('%')")) -- Switched to the dir buffer.
end)
it('triggered by "try|:split <dir>|endtry" in a function', function()
@@ -27,21 +27,20 @@ describe('autocmd BufEnter', function()
endtry
endfunction
]])
- command("call Test()")
- eq(1, eval("exists('g:dir_bufenter')")) -- Did BufEnter for the directory.
- eq(2, eval("bufnr('%')")) -- Switched to the dir buffer.
+ command('call Test()')
+ eq(1, eval("exists('g:dir_bufenter')")) -- Did BufEnter for the directory.
+ eq(2, eval("bufnr('%')")) -- Switched to the dir buffer.
end)
it('triggered by ":split normal|:help|:bw"', function()
helpers.add_builddir_to_rtp()
- command("split normal")
- command("wincmd j")
- command("help")
- command("wincmd L")
- command("autocmd BufEnter normal let g:bufentered = 1")
- command("bw")
+ command('split normal')
+ command('wincmd j')
+ command('help')
+ command('wincmd L')
+ command('autocmd BufEnter normal let g:bufentered = 1')
+ command('bw')
eq(1, eval('bufnr("%")')) -- The cursor is back to the bottom window
eq(0, eval("exists('g:bufentered')")) -- The autocmd hasn't been triggered
end)
-
end)
diff --git a/test/functional/autocmd/bufmodifiedset_spec.lua b/test/functional/autocmd/bufmodifiedset_spec.lua
index c566361e37..27fe9fcc94 100644
--- a/test/functional/autocmd/bufmodifiedset_spec.lua
+++ b/test/functional/autocmd/bufmodifiedset_spec.lua
@@ -14,9 +14,9 @@ describe('BufModified', function()
let g:modified = 0
autocmd BufModifiedSet * let g:modified += 1
]])
- request("nvim_command", [[normal! aa\<Esc>]])
+ request('nvim_command', [[normal! aa\<Esc>]])
eq(1, eval('g:modified'))
- request("nvim_command", [[normal! u]])
+ request('nvim_command', [[normal! u]])
eq(2, eval('g:modified'))
end)
end)
diff --git a/test/functional/autocmd/cmdline_spec.lua b/test/functional/autocmd/cmdline_spec.lua
index 82fb9b9444..7428456656 100644
--- a/test/functional/autocmd/cmdline_spec.lua
+++ b/test/functional/autocmd/cmdline_spec.lua
@@ -8,14 +8,14 @@ local expect = helpers.expect
local eval = helpers.eval
local next_msg = helpers.next_msg
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
describe('cmdline autocommands', function()
local channel
before_each(function()
clear()
- channel = meths.get_api_info()[1]
- meths.set_var("channel",channel)
+ channel = api.nvim_get_chan_info(0).id
+ api.nvim_set_var('channel', channel)
command("autocmd CmdlineEnter * call rpcnotify(g:channel, 'CmdlineEnter', v:event)")
command("autocmd CmdlineLeave * call rpcnotify(g:channel, 'CmdlineLeave', v:event)")
command("autocmd CmdWinEnter * call rpcnotify(g:channel, 'CmdWinEnter', v:event)")
@@ -24,23 +24,27 @@ describe('cmdline autocommands', function()
it('works', function()
feed(':')
- eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg())
+ eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
feed('redraw<cr>')
- eq({'notification', 'CmdlineLeave',
- {{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } },
+ next_msg()
+ )
feed(':')
- eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg())
+ eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
-- note: feed('bork<c-c>') might not consume 'bork'
-- due to out-of-band interrupt handling
feed('bork<esc>')
- eq({'notification', 'CmdlineLeave',
- {{cmdtype=':', cmdlevel=1, abort=true}}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = true } } },
+ next_msg()
+ )
end)
it('can abort cmdline', function()
- command("autocmd CmdlineLeave * let v:event.abort= len(getcmdline())>15")
+ command('autocmd CmdlineLeave * let v:event.abort= len(getcmdline())>15')
feed(":put! ='ok'<cr>")
expect([[
ok
@@ -57,10 +61,10 @@ describe('cmdline autocommands', function()
local screen = Screen.new(72, 8)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [4] = {bold = true, reverse = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [4] = { bold = true, reverse = true },
})
command("autocmd CmdlineEnter * echoerr 'FAIL'")
command("autocmd CmdlineLeave * echoerr 'very error'")
@@ -68,9 +72,7 @@ describe('cmdline autocommands', function()
feed(':')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{4: }|
: |
{2:CmdlineEnter Autocommands for "*": Vim(echoerr):FAIL} |
@@ -94,18 +96,14 @@ describe('cmdline autocommands', function()
screen:expect([[
|
^lorem ipsum |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
command("autocmd CmdlineChanged * echoerr 'change erreor'")
-- history recall still works
- feed(":<c-p>")
+ feed(':<c-p>')
screen:expect([[
|
lorem ipsum |
@@ -117,7 +115,7 @@ describe('cmdline autocommands', function()
:put ='lorem ipsum'^ |
]])
- feed("<left>")
+ feed('<left>')
screen:expect([[
|
lorem ipsum |
@@ -130,7 +128,7 @@ describe('cmdline autocommands', function()
]])
-- edit still works
- feed(".")
+ feed('.')
screen:expect([[
{4: }|
: |
@@ -160,72 +158,104 @@ describe('cmdline autocommands', function()
|
lorem ipsum |
^lorem ipsum. |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
end)
it('works with nested cmdline', function()
feed(':')
- eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg())
+ eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
feed('<c-r>=')
- eq({'notification', 'CmdlineEnter', {{cmdtype='=', cmdlevel=2}}}, next_msg())
+ eq({ 'notification', 'CmdlineEnter', { { cmdtype = '=', cmdlevel = 2 } } }, next_msg())
feed('<c-f>')
- eq({'notification', 'CmdWinEnter', {{}}}, next_msg())
+ eq({ 'notification', 'CmdWinEnter', { {} } }, next_msg())
feed(':')
- eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=3}}}, next_msg())
+ eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 3 } } }, next_msg())
feed('<c-c>')
- eq({'notification', 'CmdlineLeave', {{cmdtype=':', cmdlevel=3, abort=true}}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 3, abort = true } } },
+ next_msg()
+ )
feed('<c-c>')
- eq({'notification', 'CmdWinLeave', {{}}}, next_msg())
+ eq({ 'notification', 'CmdWinLeave', { {} } }, next_msg())
feed('1+2<cr>')
- eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineLeave', { { cmdtype = '=', cmdlevel = 2, abort = false } } },
+ next_msg()
+ )
end)
it('no crash with recursive use of v:event #19484', function()
command('autocmd CmdlineEnter * normal :')
feed(':')
- eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg())
+ eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
feed('<CR>')
- eq({'notification', 'CmdlineLeave', {{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } },
+ next_msg()
+ )
end)
- it('supports CmdlineChanged' ,function()
- command("autocmd CmdlineChanged * call rpcnotify(g:channel, 'CmdlineChanged', v:event, getcmdline())")
+ it('supports CmdlineChanged', function()
+ command(
+ "autocmd CmdlineChanged * call rpcnotify(g:channel, 'CmdlineChanged', v:event, getcmdline())"
+ )
feed(':')
- eq({'notification', 'CmdlineEnter', {{cmdtype=':', cmdlevel=1}}}, next_msg())
+ eq({ 'notification', 'CmdlineEnter', { { cmdtype = ':', cmdlevel = 1 } } }, next_msg())
feed('l')
- eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "l"}}, next_msg())
+ eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'l' } }, next_msg())
feed('e')
- eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "le"}}, next_msg())
+ eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'le' } }, next_msg())
feed('t')
- eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let"}}, next_msg())
+ eq({ 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let' } }, next_msg())
feed('<space>')
- eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let "}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let ' } },
+ next_msg()
+ )
feed('x')
- eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x"}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x' } },
+ next_msg()
+ )
feed('<space>')
- eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x "}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x ' } },
+ next_msg()
+ )
feed('=')
- eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x ="}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x =' } },
+ next_msg()
+ )
feed('<space>')
- eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = "}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x = ' } },
+ next_msg()
+ )
feed('<c-r>=')
- eq({'notification', 'CmdlineEnter', {{cmdtype='=', cmdlevel=2}}}, next_msg())
+ eq({ 'notification', 'CmdlineEnter', { { cmdtype = '=', cmdlevel = 2 } } }, next_msg())
feed('1')
- eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1"}}, next_msg())
+ eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1' } }, next_msg())
feed('+')
- eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+"}}, next_msg())
+ eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1+' } }, next_msg())
feed('1')
- eq({'notification', 'CmdlineChanged', {{cmdtype='=', cmdlevel=2}, "1+1"}}, next_msg())
+ eq({ 'notification', 'CmdlineChanged', { { cmdtype = '=', cmdlevel = 2 }, '1+1' } }, next_msg())
feed('<cr>')
- eq({'notification', 'CmdlineLeave', {{cmdtype='=', cmdlevel=2, abort=false}}}, next_msg())
- eq({'notification', 'CmdlineChanged', {{cmdtype=':', cmdlevel=1}, "let x = 2"}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineLeave', { { cmdtype = '=', cmdlevel = 2, abort = false } } },
+ next_msg()
+ )
+ eq(
+ { 'notification', 'CmdlineChanged', { { cmdtype = ':', cmdlevel = 1 }, 'let x = 2' } },
+ next_msg()
+ )
feed('<cr>')
- eq({'notification', 'CmdlineLeave', {{cmdtype=':', cmdlevel=1, abort=false}}}, next_msg())
+ eq(
+ { 'notification', 'CmdlineLeave', { { cmdtype = ':', cmdlevel = 1, abort = false } } },
+ next_msg()
+ )
eq(2, eval('x'))
end)
end)
diff --git a/test/functional/autocmd/cursorhold_spec.lua b/test/functional/autocmd/cursorhold_spec.lua
index e6bcb19682..fc2b65f53a 100644
--- a/test/functional/autocmd/cursorhold_spec.lua
+++ b/test/functional/autocmd/cursorhold_spec.lua
@@ -5,8 +5,8 @@ local eq = helpers.eq
local feed = helpers.feed
local retry = helpers.retry
local exec = helpers.source
-local sleep = helpers.sleep
-local meths = helpers.meths
+local sleep = vim.uv.sleep
+local api = helpers.api
before_each(clear)
@@ -26,39 +26,47 @@ 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_value('updatetime', ut, {})
- feed('0') -- reset did_cursorhold
- meths.set_var('cursorhold', 0)
+ api.nvim_set_option_value('updatetime', ut, {})
+ feed('0') -- reset did_cursorhold
+ api.nvim_set_var('cursorhold', 0)
sleep(ut / 4)
fn()
- eq(0, meths.get_var('cursorhold'))
+ eq(0, api.nvim_get_var('cursorhold'))
sleep(ut / 2)
fn()
- eq(0, meths.get_var('cursorhold'))
+ eq(0, api.nvim_get_var('cursorhold'))
sleep(ut / 2)
- eq(early, meths.get_var('cursorhold'))
+ eq(early, api.nvim_get_var('cursorhold'))
sleep(ut / 4 * 3)
- eq(1, meths.get_var('cursorhold'))
+ eq(1, api.nvim_get_var('cursorhold'))
end)
end
- local ignore_key = meths.replace_termcodes('<Ignore>', true, true, true)
+ local ignore_key = api.nvim_replace_termcodes('<Ignore>', true, true, true)
test_cursorhold(function() end, 1)
- test_cursorhold(function() feed('') end, 1)
- test_cursorhold(function() meths.feedkeys('', 'n', true) end, 1)
- test_cursorhold(function() feed('<Ignore>') end, 0)
- test_cursorhold(function() meths.feedkeys(ignore_key, 'n', true) end, 0)
+ test_cursorhold(function()
+ feed('')
+ end, 1)
+ test_cursorhold(function()
+ api.nvim_feedkeys('', 'n', true)
+ end, 1)
+ test_cursorhold(function()
+ feed('<Ignore>')
+ end, 0)
+ test_cursorhold(function()
+ api.nvim_feedkeys(ignore_key, 'n', true)
+ end, 0)
end)
it("reducing 'updatetime' while waiting for CursorHold #20241", function()
- meths.set_option_value('updatetime', 10000, {})
- feed('0') -- reset did_cursorhold
- meths.set_var('cursorhold', 0)
+ api.nvim_set_option_value('updatetime', 10000, {})
+ feed('0') -- reset did_cursorhold
+ api.nvim_set_var('cursorhold', 0)
sleep(50)
- eq(0, meths.get_var('cursorhold'))
- meths.set_option_value('updatetime', 20, {})
+ eq(0, api.nvim_get_var('cursorhold'))
+ api.nvim_set_option_value('updatetime', 20, {})
sleep(10)
- eq(1, meths.get_var('cursorhold'))
+ eq(1, api.nvim_get_var('cursorhold'))
end)
end)
@@ -77,7 +85,7 @@ describe('CursorHoldI', function()
feed('ifoo')
retry(5, nil, function()
sleep(1)
- eq(1, meths.get_var('cursorhold'))
+ eq(1, api.nvim_get_var('cursorhold'))
end)
end)
end)
diff --git a/test/functional/autocmd/cursormoved_spec.lua b/test/functional/autocmd/cursormoved_spec.lua
index 854e14b088..302afe87b8 100644
--- a/test/functional/autocmd/cursormoved_spec.lua
+++ b/test/functional/autocmd/cursormoved_spec.lua
@@ -3,7 +3,7 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
local eval = helpers.eval
-local meths = helpers.meths
+local api = helpers.api
local source = helpers.source
local command = helpers.command
@@ -19,9 +19,9 @@ describe('CursorMoved', function()
]])
eq({}, eval('g:log'))
command('new')
- eq({'BufEnter2', 'CursorMoved2'}, eval('g:log'))
+ eq({ 'BufEnter2', 'CursorMoved2' }, eval('g:log'))
command('wincmd w')
- eq({'BufEnter2', 'CursorMoved2', 'BufEnter1', 'CursorMoved1'}, eval('g:log'))
+ eq({ 'BufEnter2', 'CursorMoved2', 'BufEnter1', 'CursorMoved1' }, eval('g:log'))
end)
it('is not triggered by temporarily switching window', function()
@@ -41,13 +41,13 @@ describe('CursorMoved', function()
vsplit foo
autocmd CursorMoved * let g:cursormoved += 1
]])
- meths.buf_set_lines(eval('g:buf'), 0, -1, true, {'aaa'})
+ api.nvim_buf_set_lines(eval('g:buf'), 0, -1, true, { 'aaa' })
eq(0, eval('g:cursormoved'))
- eq({'aaa'}, meths.buf_get_lines(eval('g:buf'), 0, -1, true))
+ eq({ 'aaa' }, api.nvim_buf_get_lines(eval('g:buf'), 0, -1, true))
eq(0, eval('g:cursormoved'))
end)
- it("is not triggered by cursor movement prior to first CursorMoved instantiation", function()
+ it('is not triggered by cursor movement prior to first CursorMoved instantiation', function()
source([[
let g:cursormoved = 0
autocmd! CursorMoved
diff --git a/test/functional/autocmd/dirchanged_spec.lua b/test/functional/autocmd/dirchanged_spec.lua
index 20aa07d058..7ad529891f 100644
--- a/test/functional/autocmd/dirchanged_spec.lua
+++ b/test/functional/autocmd/dirchanged_spec.lua
@@ -1,4 +1,3 @@
-local luv = require('luv')
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
@@ -9,7 +8,7 @@ local request = helpers.request
local is_os = helpers.is_os
describe('autocmd DirChanged and DirChangedPre', function()
- local curdir = string.gsub(luv.cwd(), '\\', '/')
+ local curdir = vim.uv.cwd():gsub('\\', '/')
local dirs = {
curdir .. '/Xtest-functional-autocmd-dirchanged.dir1',
curdir .. '/Xtest-functional-autocmd-dirchanged.dir2',
@@ -21,41 +20,55 @@ describe('autocmd DirChanged and DirChangedPre', function()
curdir .. '\\XTEST-FUNCTIONAL-AUTOCMD-DIRCHANGED.DIR3',
}
- setup(function() for _, dir in pairs(dirs) do helpers.mkdir(dir) end end)
- teardown(function() for _, dir in pairs(dirs) do helpers.rmdir(dir) end end)
+ setup(function()
+ for _, dir in pairs(dirs) do
+ helpers.mkdir(dir)
+ end
+ end)
+ teardown(function()
+ for _, dir in pairs(dirs) do
+ helpers.rmdir(dir)
+ end
+ end)
before_each(function()
clear()
- command('autocmd DirChangedPre * let [g:evpre, g:amatchpre, g:cdprecount] '
- ..'= [copy(v:event), expand("<amatch>"), 1 + get(g:, "cdprecount", 0)]')
- command('autocmd DirChanged * let [g:getcwd, g:ev, g:amatch, g:cdcount] '
- ..'= [getcwd(), copy(v:event), expand("<amatch>"), 1 + get(g:, "cdcount", 0)]')
+ command(
+ 'autocmd DirChangedPre * let [g:evpre, g:amatchpre, g:cdprecount] '
+ .. '= [copy(v:event), expand("<amatch>"), 1 + get(g:, "cdprecount", 0)]'
+ )
+ command(
+ 'autocmd DirChanged * let [g:getcwd, g:ev, g:amatch, g:cdcount] '
+ .. '= [getcwd(), copy(v:event), expand("<amatch>"), 1 + get(g:, "cdcount", 0)]'
+ )
-- Normalize path separators.
- command([[autocmd DirChangedPre * let g:evpre['directory'] = substitute(g:evpre['directory'], '\\', '/', 'g')]])
+ command(
+ [[autocmd DirChangedPre * let g:evpre['directory'] = substitute(g:evpre['directory'], '\\', '/', 'g')]]
+ )
command([[autocmd DirChanged * let g:ev['cwd'] = substitute(g:ev['cwd'], '\\', '/', 'g')]])
command([[autocmd DirChanged * let g:getcwd = substitute(g:getcwd, '\\', '/', 'g')]])
end)
it('set v:event and <amatch>', function()
- command('lcd '..dirs[1])
- eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
- eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ command('lcd ' .. dirs[1])
+ eq({ directory = dirs[1], scope = 'window', changed_window = false }, eval('g:evpre'))
+ eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev'))
eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
- command('tcd '..dirs[2])
- eq({directory=dirs[2], scope='tabpage', changed_window=false}, eval('g:evpre'))
- eq({cwd=dirs[2], scope='tabpage', changed_window=false}, eval('g:ev'))
+ command('tcd ' .. dirs[2])
+ eq({ directory = dirs[2], scope = 'tabpage', changed_window = false }, eval('g:evpre'))
+ eq({ cwd = dirs[2], scope = 'tabpage', changed_window = false }, eval('g:ev'))
eq('tabpage', eval('g:amatchpre'))
eq('tabpage', eval('g:amatch'))
eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
- command('cd '..dirs[3])
- eq({directory=dirs[3], scope='global', changed_window=false}, eval('g:evpre'))
- eq({cwd=dirs[3], scope='global', changed_window=false}, eval('g:ev'))
+ command('cd ' .. dirs[3])
+ eq({ directory = dirs[3], scope = 'global', changed_window = false }, eval('g:evpre'))
+ eq({ cwd = dirs[3], scope = 'global', changed_window = false }, eval('g:ev'))
eq('global', eval('g:amatchpre'))
eq('global', eval('g:amatch'))
eq(3, eval('g:cdprecount'))
@@ -63,22 +76,22 @@ describe('autocmd DirChanged and DirChangedPre', function()
end)
it('DirChanged set getcwd() during event #6260', function()
- command('lcd '..dirs[1])
+ command('lcd ' .. dirs[1])
eq(dirs[1], eval('g:getcwd'))
- command('tcd '..dirs[2])
+ command('tcd ' .. dirs[2])
eq(dirs[2], eval('g:getcwd'))
- command('cd '..dirs[3])
+ command('cd ' .. dirs[3])
eq(dirs[3], eval('g:getcwd'))
end)
it('disallow recursion', function()
command('set shellslash')
-- Set up a _nested_ handler.
- command('autocmd DirChanged * nested lcd '..dirs[3])
- command('lcd '..dirs[1])
- eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ command('autocmd DirChanged * nested lcd ' .. dirs[3])
+ command('lcd ' .. dirs[1])
+ eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev'))
eq(1, eval('g:cdcount'))
-- autocmd changed to dirs[3], but did NOT trigger another DirChanged.
eq(dirs[3], eval('getcwd()'))
@@ -89,27 +102,36 @@ describe('autocmd DirChanged and DirChangedPre', function()
command('let g:cdcount = 0')
local status1, err1 = pcall(function()
- command('lcd '..dirs[1]..'/doesnotexist')
+ command('lcd ' .. dirs[1] .. '/doesnotexist')
end)
- eq({directory=dirs[1]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre'))
+ eq(
+ { directory = dirs[1] .. '/doesnotexist', scope = 'window', changed_window = false },
+ eval('g:evpre')
+ )
eq({}, eval('g:ev'))
eq('window', eval('g:amatchpre'))
eq(1, eval('g:cdprecount'))
eq(0, eval('g:cdcount'))
local status2, err2 = pcall(function()
- command('lcd '..dirs[2]..'/doesnotexist')
+ command('lcd ' .. dirs[2] .. '/doesnotexist')
end)
- eq({directory=dirs[2]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre'))
+ eq(
+ { directory = dirs[2] .. '/doesnotexist', scope = 'window', changed_window = false },
+ eval('g:evpre')
+ )
eq({}, eval('g:ev'))
eq('window', eval('g:amatchpre'))
eq(2, eval('g:cdprecount'))
eq(0, eval('g:cdcount'))
local status3, err3 = pcall(function()
- command('lcd '..dirs[3]..'/doesnotexist')
+ command('lcd ' .. dirs[3] .. '/doesnotexist')
end)
- eq({directory=dirs[3]..'/doesnotexist', scope='window', changed_window=false}, eval('g:evpre'))
+ eq(
+ { directory = dirs[3] .. '/doesnotexist', scope = 'window', changed_window = false },
+ eval('g:evpre')
+ )
eq({}, eval('g:ev'))
eq('window', eval('g:amatchpre'))
eq(3, eval('g:cdprecount'))
@@ -119,93 +141,93 @@ describe('autocmd DirChanged and DirChangedPre', function()
eq(false, status2)
eq(false, status3)
- eq('E344:', string.match(err1, "E%d*:"))
- eq('E344:', string.match(err2, "E%d*:"))
- eq('E344:', string.match(err3, "E%d*:"))
+ eq('E344:', string.match(err1, 'E%d*:'))
+ eq('E344:', string.match(err2, 'E%d*:'))
+ eq('E344:', string.match(err3, 'E%d*:'))
end)
it("are triggered by 'autochdir'", function()
command('set autochdir')
- command('split '..dirs[1]..'/foo')
- eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
- eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ command('split ' .. dirs[1] .. '/foo')
+ eq({ directory = dirs[1], scope = 'window', changed_window = false }, eval('g:evpre'))
+ eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev'))
eq('auto', eval('g:amatchpre'))
eq('auto', eval('g:amatch'))
eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
- command('split '..dirs[2]..'/bar')
- eq({directory=dirs[2], scope='window', changed_window=false}, eval('g:evpre'))
- eq({cwd=dirs[2], scope='window', changed_window=false}, eval('g:ev'))
+ command('split ' .. dirs[2] .. '/bar')
+ eq({ directory = dirs[2], scope = 'window', changed_window = false }, eval('g:evpre'))
+ eq({ cwd = dirs[2], scope = 'window', changed_window = false }, eval('g:ev'))
eq('auto', eval('g:amatch'))
eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
end)
it('do not trigger if directory has not changed', function()
- command('lcd '..dirs[1])
- eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
- eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ command('lcd ' .. dirs[1])
+ eq({ directory = dirs[1], scope = 'window', changed_window = false }, eval('g:evpre'))
+ eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev'))
eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
command('let g:evpre = {}')
command('let g:ev = {}')
- command('lcd '..dirs[1])
+ command('lcd ' .. dirs[1])
eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
if is_os('win') then
- command('lcd '..win_dirs[1])
+ command('lcd ' .. win_dirs[1])
eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
end
- command('tcd '..dirs[2])
- eq({directory=dirs[2], scope='tabpage', changed_window=false}, eval('g:evpre'))
- eq({cwd=dirs[2], scope='tabpage', changed_window=false}, eval('g:ev'))
+ command('tcd ' .. dirs[2])
+ eq({ directory = dirs[2], scope = 'tabpage', changed_window = false }, eval('g:evpre'))
+ eq({ cwd = dirs[2], scope = 'tabpage', changed_window = false }, eval('g:ev'))
eq('tabpage', eval('g:amatchpre'))
eq('tabpage', eval('g:amatch'))
eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
command('let g:evpre = {}')
command('let g:ev = {}')
- command('tcd '..dirs[2])
+ command('tcd ' .. dirs[2])
eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
if is_os('win') then
- command('tcd '..win_dirs[2])
+ command('tcd ' .. win_dirs[2])
eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
end
- command('cd '..dirs[3])
- eq({directory=dirs[3], scope='global', changed_window=false}, eval('g:evpre'))
- eq({cwd=dirs[3], scope='global', changed_window=false}, eval('g:ev'))
+ command('cd ' .. dirs[3])
+ eq({ directory = dirs[3], scope = 'global', changed_window = false }, eval('g:evpre'))
+ eq({ cwd = dirs[3], scope = 'global', changed_window = false }, eval('g:ev'))
eq('global', eval('g:amatch'))
eq(3, eval('g:cdprecount'))
eq(3, eval('g:cdcount'))
command('let g:evpre = {}')
command('let g:ev = {}')
- command('cd '..dirs[3])
+ command('cd ' .. dirs[3])
eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
eq(3, eval('g:cdprecount'))
eq(3, eval('g:cdcount'))
if is_os('win') then
- command('cd '..win_dirs[3])
+ command('cd ' .. win_dirs[3])
eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
eq(3, eval('g:cdprecount'))
@@ -214,23 +236,23 @@ describe('autocmd DirChanged and DirChangedPre', function()
command('set autochdir')
- command('split '..dirs[1]..'/foo')
- eq({directory=dirs[1], scope='window', changed_window=false}, eval('g:evpre'))
- eq({cwd=dirs[1], scope='window', changed_window=false}, eval('g:ev'))
+ command('split ' .. dirs[1] .. '/foo')
+ eq({ directory = dirs[1], scope = 'window', changed_window = false }, eval('g:evpre'))
+ eq({ cwd = dirs[1], scope = 'window', changed_window = false }, eval('g:ev'))
eq('auto', eval('g:amatchpre'))
eq('auto', eval('g:amatch'))
eq(4, eval('g:cdprecount'))
eq(4, eval('g:cdcount'))
command('let g:evpre = {}')
command('let g:ev = {}')
- command('split '..dirs[1]..'/bar')
+ command('split ' .. dirs[1] .. '/bar')
eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
eq(4, eval('g:cdprecount'))
eq(4, eval('g:cdcount'))
if is_os('win') then
- command('split '..win_dirs[1]..'/baz')
+ command('split ' .. win_dirs[1] .. '/baz')
eq({}, eval('g:evpre'))
eq({}, eval('g:ev'))
eq(4, eval('g:cdprecount'))
@@ -238,93 +260,93 @@ describe('autocmd DirChanged and DirChangedPre', function()
end
end)
- it("are triggered by switching to win/tab with different CWD #6054", function()
- command('lcd '..dirs[3]) -- window 3
- command('split '..dirs[2]..'/foo') -- window 2
- command('lcd '..dirs[2])
- command('split '..dirs[1]..'/bar') -- window 1
- command('lcd '..dirs[1])
+ it('are triggered by switching to win/tab with different CWD #6054', function()
+ command('lcd ' .. dirs[3]) -- window 3
+ command('split ' .. dirs[2] .. '/foo') -- window 2
+ command('lcd ' .. dirs[2])
+ command('split ' .. dirs[1] .. '/bar') -- window 1
+ command('lcd ' .. dirs[1])
- command('2wincmd w') -- window 2
- eq({directory=dirs[2], scope='window', changed_window=true}, eval('g:evpre'))
- eq({cwd=dirs[2], scope='window', changed_window=true}, eval('g:ev'))
+ command('2wincmd w') -- window 2
+ eq({ directory = dirs[2], scope = 'window', changed_window = true }, eval('g:evpre'))
+ eq({ cwd = dirs[2], scope = 'window', changed_window = true }, eval('g:ev'))
eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
eq(4, eval('g:cdprecount'))
eq(4, eval('g:cdcount'))
- command('tabnew') -- tab 2 (tab-local CWD)
- eq(4, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(4, eval('g:cdcount')) -- same CWD, no DirChanged event
- command('tcd '..dirs[3])
- command('tabnext') -- tab 1 (no tab-local CWD)
- eq({directory=dirs[2], scope='window', changed_window=true}, eval('g:evpre'))
- eq({cwd=dirs[2], scope='window', changed_window=true}, eval('g:ev'))
+ command('tabnew') -- tab 2 (tab-local CWD)
+ eq(4, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(4, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tcd ' .. dirs[3])
+ command('tabnext') -- tab 1 (no tab-local CWD)
+ eq({ directory = dirs[2], scope = 'window', changed_window = true }, eval('g:evpre'))
+ eq({ cwd = dirs[2], scope = 'window', changed_window = true }, eval('g:ev'))
eq('window', eval('g:amatchpre'))
eq('window', eval('g:amatch'))
- command('tabnext') -- tab 2
- eq({directory=dirs[3], scope='tabpage', changed_window=true}, eval('g:evpre'))
- eq({cwd=dirs[3], scope='tabpage', changed_window=true}, eval('g:ev'))
+ command('tabnext') -- tab 2
+ eq({ directory = dirs[3], scope = 'tabpage', changed_window = true }, eval('g:evpre'))
+ eq({ cwd = dirs[3], scope = 'tabpage', changed_window = true }, eval('g:ev'))
eq('tabpage', eval('g:amatchpre'))
eq('tabpage', eval('g:amatch'))
eq(7, eval('g:cdprecount'))
eq(7, eval('g:cdcount'))
- command('tabnext') -- tab 1
- command('3wincmd w') -- window 3
+ command('tabnext') -- tab 1
+ command('3wincmd w') -- window 3
eq(9, eval('g:cdprecount'))
eq(9, eval('g:cdcount'))
- command('tabnext') -- tab 2 (has the *same* CWD)
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabnext') -- tab 2 (has the *same* CWD)
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
if is_os('win') then
- command('tabnew') -- tab 3
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
- command('tcd '..win_dirs[3])
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
- command('tabnext') -- tab 1
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
- command('tabprevious') -- tab 3
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
- command('tabprevious') -- tab 2
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
- command('tabprevious') -- tab 1
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
- command('lcd '..win_dirs[3]) -- window 3
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
- command('tabnext') -- tab 2
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
- command('tabnext') -- tab 3
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
- command('tabnext') -- tab 1
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
- command('tabprevious') -- tab 3
- eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
- eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabnew') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tcd ' .. win_dirs[3])
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabnext') -- tab 1
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabprevious') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabprevious') -- tab 2
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabprevious') -- tab 1
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('lcd ' .. win_dirs[3]) -- window 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabnext') -- tab 2
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabnext') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabnext') -- tab 1
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
+ command('tabprevious') -- tab 3
+ eq(9, eval('g:cdprecount')) -- same CWD, no DirChangedPre event
+ eq(9, eval('g:cdcount')) -- same CWD, no DirChanged event
end
end)
it('are triggered by nvim_set_current_dir()', function()
request('nvim_set_current_dir', dirs[1])
- eq({directory=dirs[1], scope='global', changed_window=false}, eval('g:evpre'))
- eq({cwd=dirs[1], scope='global', changed_window=false}, eval('g:ev'))
+ eq({ directory = dirs[1], scope = 'global', changed_window = false }, eval('g:evpre'))
+ eq({ cwd = dirs[1], scope = 'global', changed_window = false }, eval('g:ev'))
eq(1, eval('g:cdprecount'))
eq(1, eval('g:cdcount'))
request('nvim_set_current_dir', dirs[2])
- eq({directory=dirs[2], scope='global', changed_window=false}, eval('g:evpre'))
- eq({cwd=dirs[2], scope='global', changed_window=false}, eval('g:ev'))
+ eq({ directory = dirs[2], scope = 'global', changed_window = false }, eval('g:evpre'))
+ eq({ cwd = dirs[2], scope = 'global', changed_window = false }, eval('g:ev'))
eq(2, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
@@ -333,7 +355,7 @@ describe('autocmd DirChanged and DirChangedPre', function()
end)
eq(false, status)
eq('Failed to change directory', string.match(err, ': (.*)'))
- eq({directory='/doesnotexist', scope='global', changed_window=false}, eval('g:evpre'))
+ eq({ directory = '/doesnotexist', scope = 'global', changed_window = false }, eval('g:evpre'))
eq(3, eval('g:cdprecount'))
eq(2, eval('g:cdcount'))
end)
@@ -343,7 +365,7 @@ describe('autocmd DirChanged and DirChangedPre', function()
command('let g:triggered = 0')
command('autocmd DirChangedPre <buffer> let g:triggeredpre = 1')
command('autocmd DirChanged <buffer> let g:triggered = 1')
- command('cd '..dirs[1])
+ command('cd ' .. dirs[1])
eq(1, eval('g:triggeredpre'))
eq(1, eval('g:triggered'))
end)
diff --git a/test/functional/autocmd/filetype_spec.lua b/test/functional/autocmd/filetype_spec.lua
index a571f6ee3b..648f830f27 100644
--- a/test/functional/autocmd/filetype_spec.lua
+++ b/test/functional/autocmd/filetype_spec.lua
@@ -5,13 +5,13 @@ local clear = helpers.clear
local command = helpers.command
describe('autocmd FileType', function()
- before_each(clear)
+ before_each(clear)
- it("is triggered by :help only once", function()
- helpers.add_builddir_to_rtp()
- command("let g:foo = 0")
- command("autocmd FileType help let g:foo = g:foo + 1")
- command("help help")
- assert.same(1, eval('g:foo'))
- end)
+ it('is triggered by :help only once', function()
+ helpers.add_builddir_to_rtp()
+ command('let g:foo = 0')
+ command('autocmd FileType help let g:foo = g:foo + 1')
+ command('help help')
+ assert.same(1, eval('g:foo'))
+ end)
end)
diff --git a/test/functional/autocmd/focus_spec.lua b/test/functional/autocmd/focus_spec.lua
index 33e4d88c7b..4f4a036ba8 100644
--- a/test/functional/autocmd/focus_spec.lua
+++ b/test/functional/autocmd/focus_spec.lua
@@ -1,12 +1,12 @@
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
-local luv = require('luv')
local clear = helpers.clear
-local nvim_prog = helpers.nvim_prog
local feed_command = helpers.feed_command
local feed_data = thelpers.feed_data
-if helpers.skip(helpers.is_os('win')) then return end
+if helpers.skip(helpers.is_os('win')) then
+ return
+end
describe('autoread TUI FocusGained/FocusLost', function()
local f1 = 'xtest-foo'
@@ -14,8 +14,16 @@ describe('autoread TUI FocusGained/FocusLost', function()
before_each(function()
clear()
- screen = thelpers.screen_setup(0, '["'..nvim_prog
- ..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile noshowcmd noruler"]')
+ screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ 'set noswapfile noshowcmd noruler notermguicolors',
+ })
end)
teardown(function()
@@ -33,51 +41,54 @@ describe('autoread TUI FocusGained/FocusLost', function()
helpers.write_file(path, '')
local atime = os.time() - 10
- luv.fs_utime(path, atime, atime)
+ vim.uv.fs_utime(path, atime, atime)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
|
{3:-- TERMINAL --} |
- ]]}
- feed_command('edit '..path)
- screen:expect{grid=[[
+ ]],
+ }
+ feed_command('edit ' .. path)
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:xtest-foo }|
:edit xtest-foo |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
feed_data('\027[O')
feed_data('\027[O')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:xtest-foo }|
:edit xtest-foo |
{3:-- TERMINAL --} |
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
helpers.write_file(path, expected_addition)
feed_data('\027[I')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:l}ine 1 |
line 2 |
line 3 |
line 4 |
{5:xtest-foo }|
- "xtest-foo" 4L, 28B |
+ :edit xtest-foo |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
end)
end)
diff --git a/test/functional/autocmd/modechanged_spec.lua b/test/functional/autocmd/modechanged_spec.lua
index 69a722a0e9..8ad914a597 100644
--- a/test/functional/autocmd/modechanged_spec.lua
+++ b/test/functional/autocmd/modechanged_spec.lua
@@ -17,15 +17,15 @@ describe('ModeChanged', function()
feed('i')
eq({
old_mode = 'nt',
- new_mode = 't'
+ new_mode = 't',
}, eval('g:event'))
feed('<c-\\><c-n>')
eq({
old_mode = 't',
- new_mode = 'nt'
+ new_mode = 'nt',
}, eval('g:event'))
eq(3, eval('g:count'))
- command("bd!")
+ command('bd!')
-- v:event is cleared after the autocommand is done
eq({}, eval('v:event'))
diff --git a/test/functional/autocmd/safestate_spec.lua b/test/functional/autocmd/safestate_spec.lua
index 73693749e4..b5b7ab2f95 100644
--- a/test/functional/autocmd/safestate_spec.lua
+++ b/test/functional/autocmd/safestate_spec.lua
@@ -3,7 +3,7 @@ local clear = helpers.clear
local eq = helpers.eq
local exec = helpers.exec
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
before_each(clear)
@@ -18,40 +18,40 @@ describe('SafeState autocommand', function()
it('with pending operator', function()
feed('d')
create_autocmd()
- eq(0, meths.get_var('safe'))
+ eq(0, api.nvim_get_var('safe'))
feed('d')
- eq(1, meths.get_var('safe'))
+ eq(1, api.nvim_get_var('safe'))
end)
it('with specified register', function()
feed('"r')
create_autocmd()
- eq(0, meths.get_var('safe'))
+ eq(0, api.nvim_get_var('safe'))
feed('x')
- eq(1, meths.get_var('safe'))
+ eq(1, api.nvim_get_var('safe'))
end)
it('with i_CTRL-O', function()
feed('i<C-O>')
create_autocmd()
- eq(0, meths.get_var('safe'))
+ eq(0, api.nvim_get_var('safe'))
feed('x')
- eq(1, meths.get_var('safe'))
+ eq(1, api.nvim_get_var('safe'))
end)
it('with Insert mode completion', function()
feed('i<C-X><C-V>')
create_autocmd()
- eq(0, meths.get_var('safe'))
+ eq(0, api.nvim_get_var('safe'))
feed('<C-X><C-Z>')
- eq(1, meths.get_var('safe'))
+ eq(1, api.nvim_get_var('safe'))
end)
it('with Cmdline completion', function()
feed(':<Tab>')
create_autocmd()
- eq(0, meths.get_var('safe'))
+ eq(0, api.nvim_get_var('safe'))
feed('<C-E>')
- eq(1, meths.get_var('safe'))
+ eq(1, api.nvim_get_var('safe'))
end)
end)
diff --git a/test/functional/autocmd/searchwrapped_spec.lua b/test/functional/autocmd/searchwrapped_spec.lua
index 46c2c99b3d..0705b2d5de 100644
--- a/test/functional/autocmd/searchwrapped_spec.lua
+++ b/test/functional/autocmd/searchwrapped_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local command = helpers.command
-local curbufmeths = helpers.curbufmeths
+local api = helpers.api
local eq = helpers.eq
local eval = helpers.eval
local feed = helpers.feed
@@ -13,9 +13,10 @@ describe('autocmd SearchWrapped', function()
command('set ignorecase')
command('let g:test = 0')
command('autocmd! SearchWrapped * let g:test += 1')
- curbufmeths.set_lines(0, 1, false, {
+ api.nvim_buf_set_lines(0, 0, 1, false, {
'The quick brown fox',
- 'jumps over the lazy dog'})
+ 'jumps over the lazy dog',
+ })
end)
it('gets triggered when search wraps the end', function()
diff --git a/test/functional/autocmd/show_spec.lua b/test/functional/autocmd/show_spec.lua
index 9e0a5b819a..1a9dc8a337 100644
--- a/test/functional/autocmd/show_spec.lua
+++ b/test/functional/autocmd/show_spec.lua
@@ -5,29 +5,30 @@ local clear = helpers.clear
local command = helpers.command
local dedent = helpers.dedent
local eq = helpers.eq
-local funcs = helpers.funcs
+local fn = helpers.fn
local eval = helpers.eval
local exec = helpers.exec
local feed = helpers.feed
-describe(":autocmd", function()
+describe(':autocmd', function()
before_each(function()
- clear({'-u', 'NONE'})
+ clear({ '-u', 'NONE' })
end)
- it("should not segfault when you just do autocmd", function()
- command ":autocmd"
+ it('should not segfault when you just do autocmd', function()
+ command ':autocmd'
end)
- it("should filter based on ++once", function()
- command "autocmd! BufEnter"
+ it('should filter based on ++once', function()
+ command 'autocmd! BufEnter'
command "autocmd BufEnter * :echo 'Hello'"
command [[augroup TestingOne]]
command [[ autocmd BufEnter * :echo "Line 1"]]
command [[ autocmd BufEnter * :echo "Line 2"]]
command [[augroup END]]
- eq(dedent([[
+ eq(
+ dedent([[
--- Autocommands ---
BufEnter
@@ -35,15 +36,16 @@ describe(":autocmd", function()
TestingOne BufEnter
* :echo "Line 1"
:echo "Line 2"]]),
- funcs.execute('autocmd BufEnter'))
+ fn.execute('autocmd BufEnter')
+ )
end)
it('should not show group information if interrupted', function()
local screen = Screen.new(50, 6)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1}, -- NonText
- [2] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
- [3] = {bold = true, foreground = Screen.colors.Magenta}, -- Title
+ [1] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText
+ [2] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
+ [3] = { bold = true, foreground = Screen.colors.Magenta }, -- Title
})
screen:attach()
exec([[
@@ -79,10 +81,7 @@ describe(":autocmd", function()
feed('q')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
end)
@@ -112,7 +111,8 @@ describe(":autocmd", function()
autocmd User foo call Func()
doautocmd User foo
]])
- eq(dedent([[
+ eq(
+ dedent([[
--- Autocommands ---
test_1 BufEnter
@@ -122,7 +122,9 @@ describe(":autocmd", function()
test_3 BufEnter
D echo 'D'
E echo 'E'
- F echo 'F']]), eval('g:output'))
+ F echo 'F']]),
+ eval('g:output')
+ )
end)
it('can filter by pattern #17973', function()
@@ -148,7 +150,8 @@ describe(":autocmd", function()
autocmd User B echo "B3"
augroup END
]])
- eq(dedent([[
+ eq(
+ dedent([[
--- Autocommands ---
test_1 User
@@ -156,8 +159,11 @@ describe(":autocmd", function()
test_2 User
A echo "A2"
test_3 User
- A echo "A3"]]), funcs.execute('autocmd User A'))
- eq(dedent([[
+ A echo "A3"]]),
+ fn.execute('autocmd User A')
+ )
+ eq(
+ dedent([[
--- Autocommands ---
test_1 BufEnter
@@ -171,14 +177,19 @@ describe(":autocmd", function()
test_2 User
B echo "B2"
test_3 User
- B echo "B3"]]), funcs.execute('autocmd * B'))
- eq(dedent([[
+ B echo "B3"]]),
+ fn.execute('autocmd * B')
+ )
+ eq(
+ dedent([[
--- Autocommands ---
test_3 BufEnter
B echo "B3"
test_3 User
- B echo "B3"]]), funcs.execute('autocmd test_3 * B'))
+ B echo "B3"]]),
+ fn.execute('autocmd test_3 * B')
+ )
end)
it('should skip consecutive patterns', function()
@@ -203,7 +214,8 @@ describe(":autocmd", function()
let g:output = execute('autocmd BufEnter')
]])
- eq(dedent([[
+ eq(
+ dedent([[
--- Autocommands ---
test_1 BufEnter
@@ -219,6 +231,8 @@ describe(":autocmd", function()
echo 'C'
D echo 'D'
echo 'E'
- echo 'F']]), eval('g:output'))
+ echo 'F']]),
+ eval('g:output')
+ )
end)
end)
diff --git a/test/functional/autocmd/signal_spec.lua b/test/functional/autocmd/signal_spec.lua
index 738064090a..c7087254e7 100644
--- a/test/functional/autocmd/signal_spec.lua
+++ b/test/functional/autocmd/signal_spec.lua
@@ -3,15 +3,17 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
-local funcs = helpers.funcs
+local fn = helpers.fn
local next_msg = helpers.next_msg
local is_os = helpers.is_os
local skip = helpers.skip
-if skip(is_os('win'), 'Only applies to POSIX systems') then return end
+if skip(is_os('win'), 'Only applies to POSIX systems') then
+ return
+end
local function posix_kill(signame, pid)
- os.execute('kill -s '..signame..' -- '..pid..' >/dev/null')
+ os.execute('kill -s ' .. signame .. ' -- ' .. pid .. ' >/dev/null')
end
describe('autocmd Signal', function()
@@ -19,25 +21,25 @@ describe('autocmd Signal', function()
it('matches *', function()
command('autocmd Signal * call rpcnotify(1, "foo")')
- posix_kill('USR1', funcs.getpid())
- eq({'notification', 'foo', {}}, next_msg())
+ posix_kill('USR1', fn.getpid())
+ eq({ 'notification', 'foo', {} }, next_msg())
end)
it('matches SIGUSR1', function()
command('autocmd Signal SIGUSR1 call rpcnotify(1, "foo")')
- posix_kill('USR1', funcs.getpid())
- eq({'notification', 'foo', {}}, next_msg())
+ posix_kill('USR1', fn.getpid())
+ eq({ 'notification', 'foo', {} }, next_msg())
end)
it('matches SIGWINCH', function()
command('autocmd Signal SIGWINCH call rpcnotify(1, "foo")')
- posix_kill('WINCH', funcs.getpid())
- eq({'notification', 'foo', {}}, next_msg())
+ posix_kill('WINCH', fn.getpid())
+ eq({ 'notification', 'foo', {} }, next_msg())
end)
it('does not match unknown patterns', function()
command('autocmd Signal SIGUSR2 call rpcnotify(1, "foo")')
- posix_kill('USR1', funcs.getpid())
+ posix_kill('USR1', fn.getpid())
eq(nil, next_msg(500))
end)
end)
diff --git a/test/functional/autocmd/tabclose_spec.lua b/test/functional/autocmd/tabclose_spec.lua
index 92d860c628..d0b2ac6a8d 100644
--- a/test/functional/autocmd/tabclose_spec.lua
+++ b/test/functional/autocmd/tabclose_spec.lua
@@ -1,5 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
-local clear, nvim, eq = helpers.clear, helpers.nvim, helpers.eq
+local clear, eq = helpers.clear, helpers.eq
+local api = helpers.api
+local command = helpers.command
describe('TabClosed', function()
before_each(clear)
@@ -7,62 +9,71 @@ describe('TabClosed', function()
describe('au TabClosed', function()
describe('with * as <afile>', function()
it('matches when closing any tab', function()
- nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()')
+ command(
+ 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()'
+ )
repeat
- nvim('command', 'tabnew')
- until nvim('eval', 'tabpagenr()') == 6 -- current tab is now 6
- eq("tabclosed:6:6:5", nvim('exec', 'tabclose', true)) -- close last 6, current tab is now 5
- eq("tabclosed:5:5:4", nvim('exec', 'close', true)) -- close last window on tab, closes tab
- eq("tabclosed:2:2:3", nvim('exec', '2tabclose', true)) -- close tab 2, current tab is now 3
- eq("tabclosed:1:1:2\ntabclosed:1:1:1", nvim('exec', 'tabonly', true)) -- close tabs 1 and 2
+ command('tabnew')
+ until api.nvim_eval('tabpagenr()') == 6 -- current tab is now 6
+ eq('tabclosed:6:6:5', api.nvim_exec('tabclose', true)) -- close last 6, current tab is now 5
+ eq('tabclosed:5:5:4', api.nvim_exec('close', true)) -- close last window on tab, closes tab
+ eq('tabclosed:2:2:3', api.nvim_exec('2tabclose', true)) -- close tab 2, current tab is now 3
+ eq('tabclosed:1:1:2\ntabclosed:1:1:1', api.nvim_exec('tabonly', true)) -- close tabs 1 and 2
end)
it('is triggered when closing a window via bdelete from another tab', function()
- nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()')
- nvim('command', '1tabedit Xtestfile')
- nvim('command', '1tabedit Xtestfile')
- nvim('command', 'normal! 1gt')
- eq({1, 3}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
- eq("tabclosed:2:2:1\ntabclosed:2:2:1", nvim('exec', 'bdelete Xtestfile', true))
- eq({1, 1}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
+ command(
+ 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()'
+ )
+ command('1tabedit Xtestfile')
+ command('1tabedit Xtestfile')
+ command('normal! 1gt')
+ eq({ 1, 3 }, api.nvim_eval('[tabpagenr(), tabpagenr("$")]'))
+ eq('tabclosed:2:2:1\ntabclosed:2:2:1', api.nvim_exec('bdelete Xtestfile', true))
+ eq({ 1, 1 }, api.nvim_eval('[tabpagenr(), tabpagenr("$")]'))
end)
it('is triggered when closing a window via bdelete from current tab', function()
- nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()')
- nvim('command', 'file Xtestfile1')
- nvim('command', '1tabedit Xtestfile2')
- nvim('command', '1tabedit Xtestfile2')
+ command(
+ 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()'
+ )
+ command('file Xtestfile1')
+ command('1tabedit Xtestfile2')
+ command('1tabedit Xtestfile2')
-- Only one tab is closed, and the alternate file is used for the other.
- eq({2, 3}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
- eq("tabclosed:2:2:2", nvim('exec', 'bdelete Xtestfile2', true))
- eq('Xtestfile1', nvim('eval', 'bufname("")'))
+ eq({ 2, 3 }, api.nvim_eval('[tabpagenr(), tabpagenr("$")]'))
+ eq('tabclosed:2:2:2', api.nvim_exec('bdelete Xtestfile2', true))
+ eq('Xtestfile1', api.nvim_eval('bufname("")'))
end)
end)
describe('with NR as <afile>', function()
it('matches when closing a tab whose index is NR', function()
- nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()')
- nvim('command', 'au! TabClosed 2 echom "tabclosed:match"')
+ command(
+ 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()'
+ )
+ command('au! TabClosed 2 echom "tabclosed:match"')
repeat
- nvim('command', 'tabnew')
- until nvim('eval', 'tabpagenr()') == 7 -- current tab is now 7
+ command('tabnew')
+ until api.nvim_eval('tabpagenr()') == 7 -- current tab is now 7
-- sanity check, we shouldn't match on tabs with numbers other than 2
- eq("tabclosed:7:7:6", nvim('exec', 'tabclose', true))
+ eq('tabclosed:7:7:6', api.nvim_exec('tabclose', true))
-- close tab page 2, current tab is now 5
- eq("tabclosed:2:2:5\ntabclosed:match", nvim('exec', '2tabclose', true))
+ eq('tabclosed:2:2:5\ntabclosed:match', api.nvim_exec('2tabclose', true))
end)
end)
describe('with close', function()
it('is triggered', function()
- nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()')
- nvim('command', 'tabedit Xtestfile')
- eq({2, 2}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
- eq("tabclosed:2:2:1", nvim('exec', 'close', true))
- eq({1, 1}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
+ command(
+ 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()'
+ )
+ command('tabedit Xtestfile')
+ eq({ 2, 2 }, api.nvim_eval('[tabpagenr(), tabpagenr("$")]'))
+ eq('tabclosed:2:2:1', api.nvim_exec('close', true))
+ eq({ 1, 1 }, api.nvim_eval('[tabpagenr(), tabpagenr("$")]'))
end)
end)
end)
end)
-
diff --git a/test/functional/autocmd/tabnewentered_spec.lua b/test/functional/autocmd/tabnewentered_spec.lua
index 6e167dd55c..b888845e3b 100644
--- a/test/functional/autocmd/tabnewentered_spec.lua
+++ b/test/functional/autocmd/tabnewentered_spec.lua
@@ -6,7 +6,7 @@ local dedent = helpers.dedent
local eval = helpers.eval
local eq = helpers.eq
local feed = helpers.feed
-local nvim = helpers.nvim
+local api = helpers.api
local exec_capture = helpers.exec_capture
describe('TabNewEntered', function()
@@ -14,33 +14,33 @@ describe('TabNewEntered', function()
describe('with * as <afile>', function()
it('matches when entering any new tab', function()
clear()
- nvim('command', 'au! TabNewEntered * echom "tabnewentered:".tabpagenr().":".bufnr("")')
- eq("tabnewentered:2:2", nvim('exec', 'tabnew', true))
- eq("tabnewentered:3:3", nvim('exec', 'tabnew test.x2', true))
- end)
+ command('au! TabNewEntered * echom "tabnewentered:".tabpagenr().":".bufnr("")')
+ eq('tabnewentered:2:2', api.nvim_exec('tabnew', true))
+ eq('tabnewentered:3:3', api.nvim_exec('tabnew test.x2', true))
+ end)
end)
describe('with FILE as <afile>', function()
it('matches when opening a new tab for FILE', function()
clear()
- nvim('command', 'au! TabNewEntered Xtest-tabnewentered echom "tabnewentered:match"')
- eq('tabnewentered:match', nvim('exec', 'tabnew Xtest-tabnewentered', true))
- end)
+ command('au! TabNewEntered Xtest-tabnewentered echom "tabnewentered:match"')
+ eq('tabnewentered:match', api.nvim_exec('tabnew Xtest-tabnewentered', true))
+ end)
end)
describe('with CTRL-W T', function()
it('works when opening a new tab with CTRL-W T', function()
clear()
- nvim('command', 'au! TabNewEntered * echom "entered"')
- nvim('command', 'tabnew test.x2')
- nvim('command', 'split')
- eq('entered', nvim('exec', 'execute "normal \\<C-W>T"', true))
+ command('au! TabNewEntered * echom "entered"')
+ command('tabnew test.x2')
+ command('split')
+ eq('entered', api.nvim_exec('execute "normal \\<C-W>T"', true))
end)
end)
describe('with tab split #4334', function()
it('works when create a tab by using tab split command', function()
clear()
- nvim('command', 'au! TabNewEntered * let b:entered = "entered"')
- nvim('command', 'tab split')
- eq('entered', nvim('exec', 'echo b:entered', true))
+ command('au! TabNewEntered * let b:entered = "entered"')
+ command('tab split')
+ eq('entered', api.nvim_exec('echo b:entered', true))
end)
end)
end)
@@ -49,22 +49,22 @@ end)
describe('TabEnter', function()
before_each(clear)
it('has correct previous tab when entering any new tab', function()
- command('augroup TEMP')
- nvim('command', 'au! TabEnter * echom "tabenter:".tabpagenr().":".tabpagenr(\'#\')')
- command('augroup END')
- eq("tabenter:2:1", nvim('exec', 'tabnew', true))
- eq("tabenter:3:2", nvim('exec', 'tabnew test.x2', true))
- command('augroup! TEMP')
+ command('augroup TEMP')
+ command('au! TabEnter * echom "tabenter:".tabpagenr().":".tabpagenr(\'#\')')
+ command('augroup END')
+ eq('tabenter:2:1', api.nvim_exec('tabnew', true))
+ eq('tabenter:3:2', api.nvim_exec('tabnew test.x2', true))
+ command('augroup! TEMP')
end)
it('has correct previous tab when entering any preexisting tab', function()
- command('tabnew')
- command('tabnew')
- command('augroup TEMP')
- nvim('command', 'au! TabEnter * echom "tabenter:".tabpagenr().":".tabpagenr(\'#\')')
- command('augroup END')
- eq("tabenter:1:3", nvim('exec', 'tabnext', true))
- eq("tabenter:2:1", nvim('exec', 'tabnext', true))
- command('augroup! TEMP')
+ command('tabnew')
+ command('tabnew')
+ command('augroup TEMP')
+ command('au! TabEnter * echom "tabenter:".tabpagenr().":".tabpagenr(\'#\')')
+ command('augroup END')
+ eq('tabenter:1:3', api.nvim_exec('tabnext', true))
+ eq('tabenter:2:1', api.nvim_exec('tabnext', true))
+ command('augroup! TEMP')
end)
end)
@@ -72,18 +72,19 @@ describe('tabpage/previous', function()
before_each(clear)
local function switches_to_previous_after_new_tab_creation_at_end(characters)
return function()
- -- Add three tabs for a total of four
- command('tabnew')
- command('tabnew')
- command('tabnew')
+ -- Add three tabs for a total of four
+ command('tabnew')
+ command('tabnew')
+ command('tabnew')
- -- The previous tab is now the third.
- eq(3, eval('tabpagenr(\'#\')'))
+ -- The previous tab is now the third.
+ eq(3, eval("tabpagenr('#')"))
- -- Switch to the previous (third) tab
- feed(characters)
+ -- Switch to the previous (third) tab
+ feed(characters)
- eq(dedent([=[
+ eq(
+ dedent([=[
Tab page 1
[No Name]
@@ -93,18 +94,29 @@ describe('tabpage/previous', function()
> [No Name]
Tab page 4
# [No Name]]=]),
- exec_capture('tabs')
- )
+ exec_capture('tabs')
+ )
- -- The previous tab is now the fourth.
- eq(4, eval('tabpagenr(\'#\')'))
+ -- The previous tab is now the fourth.
+ eq(4, eval("tabpagenr('#')"))
end
end
- it('switches to previous via g<Tab> after new tab creation at end',
- switches_to_previous_after_new_tab_creation_at_end('g<Tab>'))
- it('switches to previous via <C-W>g<Tab>. after new tab creation at end', switches_to_previous_after_new_tab_creation_at_end('<C-W>g<Tab>'))
- it('switches to previous via <C-Tab>. after new tab creation at end', switches_to_previous_after_new_tab_creation_at_end('<C-Tab>'))
- it('switches to previous via :tabn #<CR>. after new tab creation at end', switches_to_previous_after_new_tab_creation_at_end(':tabn #<CR>'))
+ it(
+ 'switches to previous via g<Tab> after new tab creation at end',
+ switches_to_previous_after_new_tab_creation_at_end('g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-W>g<Tab>. after new tab creation at end',
+ switches_to_previous_after_new_tab_creation_at_end('<C-W>g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-Tab>. after new tab creation at end',
+ switches_to_previous_after_new_tab_creation_at_end('<C-Tab>')
+ )
+ it(
+ 'switches to previous via :tabn #<CR>. after new tab creation at end',
+ switches_to_previous_after_new_tab_creation_at_end(':tabn #<CR>')
+ )
local function switches_to_previous_after_new_tab_creation_in_middle(characters)
return function()
@@ -118,11 +130,12 @@ describe('tabpage/previous', function()
command('tabnew')
-- The previous tab is now the second.
- eq(2, eval('tabpagenr(\'#\')'))
+ eq(2, eval("tabpagenr('#')"))
-- Switch to the previous (second) tab
feed(characters)
- eq(dedent([=[
+ eq(
+ dedent([=[
Tab page 1
[No Name]
@@ -134,21 +147,29 @@ describe('tabpage/previous', function()
[No Name]
Tab page 5
[No Name]]=]),
- exec_capture('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the third.
- eq(3, eval('tabpagenr(\'#\')'))
+ eq(3, eval("tabpagenr('#')"))
end
end
- it('switches to previous via g<Tab> after new tab creation in middle',
- switches_to_previous_after_new_tab_creation_in_middle('g<Tab>'))
- it('switches to previous via <C-W>g<Tab> after new tab creation in middle',
- switches_to_previous_after_new_tab_creation_in_middle('<C-W>g<Tab>'))
- it('switches to previous via <C-Tab> after new tab creation in middle',
- switches_to_previous_after_new_tab_creation_in_middle('<C-Tab>'))
- it('switches to previous via :tabn #<CR> after new tab creation in middle',
- switches_to_previous_after_new_tab_creation_in_middle(':tabn #<CR>'))
+ it(
+ 'switches to previous via g<Tab> after new tab creation in middle',
+ switches_to_previous_after_new_tab_creation_in_middle('g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-W>g<Tab> after new tab creation in middle',
+ switches_to_previous_after_new_tab_creation_in_middle('<C-W>g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-Tab> after new tab creation in middle',
+ switches_to_previous_after_new_tab_creation_in_middle('<C-Tab>')
+ )
+ it(
+ 'switches to previous via :tabn #<CR> after new tab creation in middle',
+ switches_to_previous_after_new_tab_creation_in_middle(':tabn #<CR>')
+ )
local function switches_to_previous_after_switching_to_next_tab(characters)
return function()
@@ -160,12 +181,13 @@ describe('tabpage/previous', function()
command('tabnext')
-- The previous tab is now the fourth.
- eq(4, eval('tabpagenr(\'#\')'))
+ eq(4, eval("tabpagenr('#')"))
-- Switch to the previous (fourth) tab
feed(characters)
- eq(dedent([=[
+ eq(
+ dedent([=[
Tab page 1
# [No Name]
@@ -175,21 +197,29 @@ describe('tabpage/previous', function()
[No Name]
Tab page 4
> [No Name]]=]),
- exec_capture('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the first.
- eq(1, eval('tabpagenr(\'#\')'))
+ eq(1, eval("tabpagenr('#')"))
end
end
- it('switches to previous via g<Tab> after switching to next tab',
- switches_to_previous_after_switching_to_next_tab('g<Tab>'))
- it('switches to previous via <C-W>g<Tab> after switching to next tab',
- switches_to_previous_after_switching_to_next_tab('<C-W>g<Tab>'))
- it('switches to previous via <C-Tab> after switching to next tab',
- switches_to_previous_after_switching_to_next_tab('<C-Tab>'))
- it('switches to previous via :tabn #<CR> after switching to next tab',
- switches_to_previous_after_switching_to_next_tab(':tabn #<CR>'))
+ it(
+ 'switches to previous via g<Tab> after switching to next tab',
+ switches_to_previous_after_switching_to_next_tab('g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-W>g<Tab> after switching to next tab',
+ switches_to_previous_after_switching_to_next_tab('<C-W>g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-Tab> after switching to next tab',
+ switches_to_previous_after_switching_to_next_tab('<C-Tab>')
+ )
+ it(
+ 'switches to previous via :tabn #<CR> after switching to next tab',
+ switches_to_previous_after_switching_to_next_tab(':tabn #<CR>')
+ )
local function switches_to_previous_after_switching_to_last_tab(characters)
return function()
@@ -203,12 +233,13 @@ describe('tabpage/previous', function()
command('tablast')
-- The previous tab is now the second.
- eq(1, eval('tabpagenr(\'#\')'))
+ eq(1, eval("tabpagenr('#')"))
-- Switch to the previous (second) tab
feed(characters)
- eq(dedent([=[
+ eq(
+ dedent([=[
Tab page 1
> [No Name]
@@ -218,21 +249,29 @@ describe('tabpage/previous', function()
[No Name]
Tab page 4
# [No Name]]=]),
- exec_capture('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the fourth.
- eq(4, eval('tabpagenr(\'#\')'))
+ eq(4, eval("tabpagenr('#')"))
end
end
- it('switches to previous after switching to last tab',
- switches_to_previous_after_switching_to_last_tab('g<Tab>'))
- it('switches to previous after switching to last tab',
- switches_to_previous_after_switching_to_last_tab('<C-W>g<Tab>'))
- it('switches to previous after switching to last tab',
- switches_to_previous_after_switching_to_last_tab('<C-Tab>'))
- it('switches to previous after switching to last tab',
- switches_to_previous_after_switching_to_last_tab(':tabn #<CR>'))
+ it(
+ 'switches to previous after switching to last tab',
+ switches_to_previous_after_switching_to_last_tab('g<Tab>')
+ )
+ it(
+ 'switches to previous after switching to last tab',
+ switches_to_previous_after_switching_to_last_tab('<C-W>g<Tab>')
+ )
+ it(
+ 'switches to previous after switching to last tab',
+ switches_to_previous_after_switching_to_last_tab('<C-Tab>')
+ )
+ it(
+ 'switches to previous after switching to last tab',
+ switches_to_previous_after_switching_to_last_tab(':tabn #<CR>')
+ )
local function switches_to_previous_after_switching_to_previous_tab(characters)
return function()
@@ -244,12 +283,13 @@ describe('tabpage/previous', function()
command('tabprevious')
-- The previous tab is now the fourth.
- eq(4, eval('tabpagenr(\'#\')'))
+ eq(4, eval("tabpagenr('#')"))
-- Switch to the previous (fourth) tab
feed(characters)
- eq(dedent([=[
+ eq(
+ dedent([=[
Tab page 1
[No Name]
@@ -259,21 +299,29 @@ describe('tabpage/previous', function()
# [No Name]
Tab page 4
> [No Name]]=]),
- exec_capture('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the third.
- eq(3, eval('tabpagenr(\'#\')'))
+ eq(3, eval("tabpagenr('#')"))
end
end
- it('switches to previous via g<Tab> after switching to previous tab',
- switches_to_previous_after_switching_to_previous_tab('g<Tab>'))
- it('switches to previous via <C-W>g<Tab> after switching to previous tab',
- switches_to_previous_after_switching_to_previous_tab('<C-W>g<Tab>'))
- it('switches to previous via <C-Tab> after switching to previous tab',
- switches_to_previous_after_switching_to_previous_tab('<C-Tab>'))
- it('switches to previous via :tabn #<CR> after switching to previous tab',
- switches_to_previous_after_switching_to_previous_tab(':tabn #<CR>'))
+ it(
+ 'switches to previous via g<Tab> after switching to previous tab',
+ switches_to_previous_after_switching_to_previous_tab('g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-W>g<Tab> after switching to previous tab',
+ switches_to_previous_after_switching_to_previous_tab('<C-W>g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-Tab> after switching to previous tab',
+ switches_to_previous_after_switching_to_previous_tab('<C-Tab>')
+ )
+ it(
+ 'switches to previous via :tabn #<CR> after switching to previous tab',
+ switches_to_previous_after_switching_to_previous_tab(':tabn #<CR>')
+ )
local function switches_to_previous_after_switching_to_first_tab(characters)
return function()
@@ -287,12 +335,13 @@ describe('tabpage/previous', function()
command('tabfirst')
-- The previous tab is now the third.
- eq(3, eval('tabpagenr(\'#\')'))
+ eq(3, eval("tabpagenr('#')"))
-- Switch to the previous (third) tab
feed(characters)
- eq(dedent([=[
+ eq(
+ dedent([=[
Tab page 1
# [No Name]
@@ -302,21 +351,29 @@ describe('tabpage/previous', function()
> [No Name]
Tab page 4
[No Name]]=]),
- exec_capture('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the first.
- eq(1, eval('tabpagenr(\'#\')'))
+ eq(1, eval("tabpagenr('#')"))
end
end
- it('switches to previous via g<Tab> after switching to first tab',
- switches_to_previous_after_switching_to_first_tab('g<Tab>'))
- it('switches to previous via <C-W>g<Tab> after switching to first tab',
- switches_to_previous_after_switching_to_first_tab('<C-W>g<Tab>'))
- it('switches to previous via <C-Tab> after switching to first tab',
- switches_to_previous_after_switching_to_first_tab('<C-Tab>'))
- it('switches to previous via :tabn #<CR> after switching to first tab',
- switches_to_previous_after_switching_to_first_tab(':tabn #<CR>'))
+ it(
+ 'switches to previous via g<Tab> after switching to first tab',
+ switches_to_previous_after_switching_to_first_tab('g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-W>g<Tab> after switching to first tab',
+ switches_to_previous_after_switching_to_first_tab('<C-W>g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-Tab> after switching to first tab',
+ switches_to_previous_after_switching_to_first_tab('<C-Tab>')
+ )
+ it(
+ 'switches to previous via :tabn #<CR> after switching to first tab',
+ switches_to_previous_after_switching_to_first_tab(':tabn #<CR>')
+ )
local function switches_to_previous_after_numbered_tab_switch(characters)
return function()
@@ -328,12 +385,13 @@ describe('tabpage/previous', function()
command('tabnext 2')
-- The previous tab is now the fourth.
- eq(4, eval('tabpagenr(\'#\')'))
+ eq(4, eval("tabpagenr('#')"))
-- Switch to the previous (fourth) tab
feed(characters)
- eq(dedent([=[
+ eq(
+ dedent([=[
Tab page 1
[No Name]
@@ -343,21 +401,29 @@ describe('tabpage/previous', function()
[No Name]
Tab page 4
> [No Name]]=]),
- exec_capture('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the second.
- eq(2, eval('tabpagenr(\'#\')'))
+ eq(2, eval("tabpagenr('#')"))
end
end
- it('switches to previous via g<Tab> after numbered tab switch',
- switches_to_previous_after_numbered_tab_switch('g<Tab>'))
- it('switches to previous via <C-W>g<Tab> after numbered tab switch',
- switches_to_previous_after_numbered_tab_switch('<C-W>g<Tab>'))
- it('switches to previous via <C-Tab> after numbered tab switch',
- switches_to_previous_after_numbered_tab_switch('<C-Tab>'))
- it('switches to previous via :tabn #<CR> after numbered tab switch',
- switches_to_previous_after_numbered_tab_switch(':tabn #<CR>'))
+ it(
+ 'switches to previous via g<Tab> after numbered tab switch',
+ switches_to_previous_after_numbered_tab_switch('g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-W>g<Tab> after numbered tab switch',
+ switches_to_previous_after_numbered_tab_switch('<C-W>g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-Tab> after numbered tab switch',
+ switches_to_previous_after_numbered_tab_switch('<C-Tab>')
+ )
+ it(
+ 'switches to previous via :tabn #<CR> after numbered tab switch',
+ switches_to_previous_after_numbered_tab_switch(':tabn #<CR>')
+ )
local function switches_to_previous_after_switching_to_previous(characters1, characters2)
return function()
@@ -371,12 +437,13 @@ describe('tabpage/previous', function()
feed(characters1)
-- The previous tab is now the second.
- eq(2, eval('tabpagenr(\'#\')'))
+ eq(2, eval("tabpagenr('#')"))
-- Switch to the previous (second) tab
feed(characters2)
- eq(dedent([=[
+ eq(
+ dedent([=[
Tab page 1
[No Name]
@@ -386,45 +453,77 @@ describe('tabpage/previous', function()
[No Name]
Tab page 4
# [No Name]]=]),
- exec_capture('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the fourth.
- eq(4, eval('tabpagenr(\'#\')'))
+ eq(4, eval("tabpagenr('#')"))
end
end
- it('switches to previous via g<Tab> after switching to previous via g<Tab>',
- switches_to_previous_after_switching_to_previous('g<Tab>', 'g<Tab>'))
- it('switches to previous via <C-W>g<Tab> after switching to previous via g<Tab>',
- switches_to_previous_after_switching_to_previous('g<Tab>', '<C-W>g<Tab>'))
- it('switches to previous via <C-Tab> after switching to previous via g<Tab>',
- switches_to_previous_after_switching_to_previous('g<Tab>', '<C-Tab>'))
- it('switches to previous via :tabn #<CR> after switching to previous via g<Tab>',
- switches_to_previous_after_switching_to_previous('g<Tab>', ':tabn #<CR>'))
- it('switches to previous via g<Tab> after switching to previous via <C-W>g<Tab>',
- switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', 'g<Tab>'))
- it('switches to previous via <C-W>g<Tab> after switching to previous via <C-W>g<Tab>',
- switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-W>g<Tab>'))
- it('switches to previous via <C-Tab> after switching to previous via <C-W>g<Tab>',
- switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-Tab>'))
- it('switches to previous via :tabn #<CR> after switching to previous via <C-W>g<Tab>',
- switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', ':tabn #<CR>'))
- it('switches to previous via g<Tab> after switching to previous via <C-Tab>',
- switches_to_previous_after_switching_to_previous('<C-Tab>', 'g<Tab>'))
- it('switches to previous via <C-W>g<Tab> after switching to previous via <C-Tab>',
- switches_to_previous_after_switching_to_previous('<C-Tab>', '<C-W>g<Tab>'))
- it('switches to previous via <C-Tab> after switching to previous via <C-Tab>',
- switches_to_previous_after_switching_to_previous('<C-Tab>', '<C-Tab>'))
- it('switches to previous via :tabn #<CR> after switching to previous via <C-Tab>',
- switches_to_previous_after_switching_to_previous('<C-Tab>', ':tabn #<CR>'))
- it('switches to previous via g<Tab> after switching to previous via :tabn #<CR>',
- switches_to_previous_after_switching_to_previous(':tabn #<CR>', 'g<Tab>'))
- it('switches to previous via <C-W>g<Tab> after switching to previous via :tabn #<CR>',
- switches_to_previous_after_switching_to_previous(':tabn #<CR>', '<C-W>g<Tab>'))
- it('switches to previous via <C-Tab> after switching to previous via <C-Tab>',
- switches_to_previous_after_switching_to_previous(':tabn #<CR>', '<C-Tab>'))
- it('switches to previous via :tabn #<CR> after switching to previous via :tabn #<CR>',
- switches_to_previous_after_switching_to_previous(':tabn #<CR>', ':tabn #<CR>'))
+ it(
+ 'switches to previous via g<Tab> after switching to previous via g<Tab>',
+ switches_to_previous_after_switching_to_previous('g<Tab>', 'g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-W>g<Tab> after switching to previous via g<Tab>',
+ switches_to_previous_after_switching_to_previous('g<Tab>', '<C-W>g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-Tab> after switching to previous via g<Tab>',
+ switches_to_previous_after_switching_to_previous('g<Tab>', '<C-Tab>')
+ )
+ it(
+ 'switches to previous via :tabn #<CR> after switching to previous via g<Tab>',
+ switches_to_previous_after_switching_to_previous('g<Tab>', ':tabn #<CR>')
+ )
+ it(
+ 'switches to previous via g<Tab> after switching to previous via <C-W>g<Tab>',
+ switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', 'g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-W>g<Tab> after switching to previous via <C-W>g<Tab>',
+ switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-W>g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-Tab> after switching to previous via <C-W>g<Tab>',
+ switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-Tab>')
+ )
+ it(
+ 'switches to previous via :tabn #<CR> after switching to previous via <C-W>g<Tab>',
+ switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', ':tabn #<CR>')
+ )
+ it(
+ 'switches to previous via g<Tab> after switching to previous via <C-Tab>',
+ switches_to_previous_after_switching_to_previous('<C-Tab>', 'g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-W>g<Tab> after switching to previous via <C-Tab>',
+ switches_to_previous_after_switching_to_previous('<C-Tab>', '<C-W>g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-Tab> after switching to previous via <C-Tab>',
+ switches_to_previous_after_switching_to_previous('<C-Tab>', '<C-Tab>')
+ )
+ it(
+ 'switches to previous via :tabn #<CR> after switching to previous via <C-Tab>',
+ switches_to_previous_after_switching_to_previous('<C-Tab>', ':tabn #<CR>')
+ )
+ it(
+ 'switches to previous via g<Tab> after switching to previous via :tabn #<CR>',
+ switches_to_previous_after_switching_to_previous(':tabn #<CR>', 'g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-W>g<Tab> after switching to previous via :tabn #<CR>',
+ switches_to_previous_after_switching_to_previous(':tabn #<CR>', '<C-W>g<Tab>')
+ )
+ it(
+ 'switches to previous via <C-Tab> after switching to previous via <C-Tab>',
+ switches_to_previous_after_switching_to_previous(':tabn #<CR>', '<C-Tab>')
+ )
+ it(
+ 'switches to previous via :tabn #<CR> after switching to previous via :tabn #<CR>',
+ switches_to_previous_after_switching_to_previous(':tabn #<CR>', ':tabn #<CR>')
+ )
local function does_not_switch_to_previous_after_closing_current_tab(characters)
return function()
@@ -436,13 +535,14 @@ describe('tabpage/previous', function()
command('wincmd c')
-- The previous tab is now the "zeroth" -- there isn't one.
- eq(0, eval('tabpagenr(\'#\')'))
+ eq(0, eval("tabpagenr('#')"))
-- At this point, switching to the "previous" (i.e. fourth) tab would mean
-- switching to either a dangling or a null pointer.
feed(characters)
- eq(dedent([=[
+ eq(
+ dedent([=[
Tab page 1
[No Name]
@@ -450,21 +550,29 @@ describe('tabpage/previous', function()
[No Name]
Tab page 3
> [No Name]]=]),
- exec_capture('tabs')
+ exec_capture('tabs')
)
-- The previous tab is now the "zero".
- eq(0, eval('tabpagenr(\'#\')'))
+ eq(0, eval("tabpagenr('#')"))
end
end
- it('does not switch to previous via g<Tab> after closing current tab',
- does_not_switch_to_previous_after_closing_current_tab('g<Tab>'))
- it('does not switch to previous via <C-W>g<Tab> after closing current tab',
- does_not_switch_to_previous_after_closing_current_tab('<C-W>g<Tab>'))
- it('does not switch to previous via <C-Tab> after closing current tab',
- does_not_switch_to_previous_after_closing_current_tab('<C-Tab>'))
- it('does not switch to previous via :tabn #<CR> after closing current tab',
- does_not_switch_to_previous_after_closing_current_tab(':tabn #<CR>'))
+ it(
+ 'does not switch to previous via g<Tab> after closing current tab',
+ does_not_switch_to_previous_after_closing_current_tab('g<Tab>')
+ )
+ it(
+ 'does not switch to previous via <C-W>g<Tab> after closing current tab',
+ does_not_switch_to_previous_after_closing_current_tab('<C-W>g<Tab>')
+ )
+ it(
+ 'does not switch to previous via <C-Tab> after closing current tab',
+ does_not_switch_to_previous_after_closing_current_tab('<C-Tab>')
+ )
+ it(
+ 'does not switch to previous via :tabn #<CR> after closing current tab',
+ does_not_switch_to_previous_after_closing_current_tab(':tabn #<CR>')
+ )
local function does_not_switch_to_previous_after_entering_operator_pending(characters)
return function()
@@ -474,7 +582,7 @@ describe('tabpage/previous', function()
command('tabnew')
-- The previous tab is now the third.
- eq(3, eval('tabpagenr(\'#\')'))
+ eq(3, eval("tabpagenr('#')"))
-- Enter operator pending mode.
feed('d')
@@ -491,11 +599,13 @@ describe('tabpage/previous', function()
eq(4, eval('tabpagenr()'))
-- The previous tab is still the third.
- eq(3, eval('tabpagenr(\'#\')'))
+ eq(3, eval("tabpagenr('#')"))
end
end
- it('does not switch to previous via g<Tab> after entering operator pending',
- does_not_switch_to_previous_after_entering_operator_pending('g<Tab>'))
+ it(
+ 'does not switch to previous via g<Tab> after entering operator pending',
+ does_not_switch_to_previous_after_entering_operator_pending('g<Tab>')
+ )
-- NOTE: When in operator pending mode, attempting to switch to previous has
-- the following effect:
-- - Ctrl-W exits operator pending mode
@@ -506,8 +616,10 @@ describe('tabpage/previous', function()
-- be the same as the normal mode command to switch to the previous tab.
-- it('does not switch to previous via <C-W>g<Tab> after entering operator pending',
-- does_not_switch_to_previous_after_entering_operator_pending('<C-W>g<Tab>'))
- it('does not switch to previous via <C-Tab> after entering operator pending',
- does_not_switch_to_previous_after_entering_operator_pending('<C-Tab>'))
+ it(
+ 'does not switch to previous via <C-Tab> after entering operator pending',
+ does_not_switch_to_previous_after_entering_operator_pending('<C-Tab>')
+ )
-- NOTE: When in operator pending mode, pressing : leaves operator pending
-- mode and enters command mode, so :tabn #<CR> does in fact switch
-- tabs.
@@ -522,7 +634,7 @@ describe('tabpage/previous', function()
command('tabnew')
-- The previous tab is now the third.
- eq(3, eval('tabpagenr(\'#\')'))
+ eq(3, eval("tabpagenr('#')"))
-- Edit : command line in command-line window
feed('q:')
@@ -540,31 +652,34 @@ describe('tabpage/previous', function()
eq(4, eval('tabpagenr()'))
-- The previous tab is still the third.
- eq(3, eval('tabpagenr(\'#\')'))
+ eq(3, eval("tabpagenr('#')"))
end
end
- it('cmdline-win prevents tab switch via g<Tab>',
- cmdline_win_prevents_tab_switch('g<Tab>', 0))
- it('cmdline-win prevents tab switch via <C-W>g<Tab>',
- cmdline_win_prevents_tab_switch('<C-W>g<Tab>', 1))
- it('cmdline-win prevents tab switch via <C-Tab>',
- cmdline_win_prevents_tab_switch('<C-Tab>', 0))
- it('cmdline-win prevents tab switch via :tabn #<CR>',
- cmdline_win_prevents_tab_switch(':tabn #<CR>', 0))
+ it('cmdline-win prevents tab switch via g<Tab>', cmdline_win_prevents_tab_switch('g<Tab>', 0))
+ it(
+ 'cmdline-win prevents tab switch via <C-W>g<Tab>',
+ cmdline_win_prevents_tab_switch('<C-W>g<Tab>', 1)
+ )
+ it('cmdline-win prevents tab switch via <C-Tab>', cmdline_win_prevents_tab_switch('<C-Tab>', 0))
+ it(
+ 'cmdline-win prevents tab switch via :tabn #<CR>',
+ cmdline_win_prevents_tab_switch(':tabn #<CR>', 0)
+ )
it(':tabs indicates correct prevtab curwin', function()
- -- Add three tabs for a total of four
- command('tabnew')
- command('tabnew')
- command('split')
- command('vsplit')
- feed('<C-w>p')
- command('tabnew')
+ -- Add three tabs for a total of four
+ command('tabnew')
+ command('tabnew')
+ command('split')
+ command('vsplit')
+ feed('<C-w>p')
+ command('tabnew')
- -- The previous tab is now the three.
- eq(3, eval('tabpagenr(\'#\')'))
+ -- The previous tab is now the three.
+ eq(3, eval("tabpagenr('#')"))
- eq(dedent([=[
+ eq(
+ dedent([=[
Tab page 1
[No Name]
@@ -576,7 +691,7 @@ describe('tabpage/previous', function()
[No Name]
Tab page 4
> [No Name]]=]),
- exec_capture('tabs')
- )
+ exec_capture('tabs')
+ )
end)
end)
diff --git a/test/functional/autocmd/termxx_spec.lua b/test/functional/autocmd/termxx_spec.lua
index 332a936e3f..982edfa06a 100644
--- a/test/functional/autocmd/termxx_spec.lua
+++ b/test/functional/autocmd/termxx_spec.lua
@@ -1,15 +1,13 @@
-local luv = require('luv')
+local uv = vim.uv
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
-local clear, command, nvim, testprg =
- helpers.clear, helpers.command, helpers.nvim, helpers.testprg
-local eval, eq, neq, retry =
- helpers.eval, helpers.eq, helpers.neq, helpers.retry
+local clear, command, testprg = helpers.clear, helpers.command, helpers.testprg
+local eval, eq, neq, retry = helpers.eval, helpers.eq, helpers.neq, helpers.retry
local matches = helpers.matches
local ok = helpers.ok
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
local pcall_err = helpers.pcall_err
local assert_alive = helpers.assert_alive
local skip = helpers.skip
@@ -18,17 +16,19 @@ local is_os = helpers.is_os
describe('autocmd TermClose', function()
before_each(function()
clear()
- nvim('set_option_value', 'shell', testprg('shell-test'), {})
+ api.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_value', 'shell', string.format('"%s" INTERACT', testprg('shell-test')), {})
+ api.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://',
- pcall_err(command, 'bdelete!'))
+ matches(
+ '^TermClose Autocommands for "%*": Vim%(bdelete%):E937: Attempt to delete a buffer that is in use: term://',
+ pcall_err(command, 'bdelete!')
+ )
assert_alive()
end
@@ -46,58 +46,76 @@ describe('autocmd TermClose', function()
command('autocmd TermClose * let g:test_termclose = 23')
command('terminal')
-- shell-test exits immediately.
- retry(nil, nil, function() neq(-1, eval('jobwait([&channel], 0)[0]')) end)
- retry(nil, nil, function() eq(23, eval('g:test_termclose')) end)
+ retry(nil, nil, function()
+ neq(-1, eval('jobwait([&channel], 0)[0]'))
+ end)
+ retry(nil, nil, function()
+ eq(23, eval('g:test_termclose'))
+ end)
end)
it('triggers when long-running terminal job gets stopped', function()
skip(is_os('win'))
- nvim('set_option_value', 'shell', is_os('win') and 'cmd.exe' or 'sh', {})
+ api.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)')
- retry(nil, nil, function() eq(23, eval('g:test_termclose')) end)
+ retry(nil, nil, function()
+ eq(23, eval('g:test_termclose'))
+ end)
end)
it('kills job trapping SIGTERM', function()
skip(is_os('win'))
- 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')}}) ]])
- retry(nil, nil, function() eq(1, eval('get(g:, "test_job_started", 0)')) end)
-
- luv.update_time()
- local start = luv.now()
+ api.nvim_set_option_value('shell', 'sh', {})
+ api.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')}}) ]]
+ )
+ retry(nil, nil, function()
+ eq(1, eval('get(g:, "test_job_started", 0)'))
+ end)
+
+ uv.update_time()
+ local start = uv.now()
command('call jobstop(g:test_job)')
- retry(nil, nil, function() eq(1, eval('get(g:, "test_job_exited", 0)')) end)
- luv.update_time()
- local duration = luv.now() - start
+ retry(nil, nil, function()
+ eq(1, eval('get(g:, "test_job_exited", 0)'))
+ end)
+ uv.update_time()
+ local duration = uv.now() - start
-- Nvim begins SIGTERM after KILL_TIMEOUT_MS.
ok(duration >= 2000)
- ok(duration <= 4000) -- Epsilon for slow CI
+ ok(duration <= 4000) -- Epsilon for slow CI
end)
it('kills PTY job trapping SIGHUP and SIGTERM', function()
skip(is_os('win'))
- 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')}, ]]
- .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]])
- retry(nil, nil, function() eq(1, eval('get(g:, "test_job_started", 0)')) end)
-
- luv.update_time()
- local start = luv.now()
+ api.nvim_set_option_value('shell', 'sh', {})
+ api.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')}, ]]
+ .. [[ 'on_exit': {-> execute('let g:test_job_exited = 1')}}) ]]
+ )
+ retry(nil, nil, function()
+ eq(1, eval('get(g:, "test_job_started", 0)'))
+ end)
+
+ uv.update_time()
+ local start = uv.now()
command('call jobstop(g:test_job)')
- retry(nil, nil, function() eq(1, eval('get(g:, "test_job_exited", 0)')) end)
- luv.update_time()
- local duration = luv.now() - start
+ retry(nil, nil, function()
+ eq(1, eval('get(g:, "test_job_exited", 0)'))
+ end)
+ uv.update_time()
+ local duration = uv.now() - start
-- Nvim begins SIGKILL after (2 * KILL_TIMEOUT_MS).
ok(duration >= 4000)
- ok(duration <= 7000) -- Epsilon for slow CI
+ ok(duration <= 7000) -- Epsilon for slow CI
end)
it('reports the correct <abuf>', function()
@@ -109,13 +127,19 @@ describe('autocmd TermClose', function()
eq(2, eval('bufnr("%")'))
command('terminal ls')
- retry(nil, nil, function() eq(3, eval('bufnr("%")')) end)
+ retry(nil, nil, function()
+ eq(3, eval('bufnr("%")'))
+ end)
command('buffer 1')
- retry(nil, nil, function() eq(1, eval('bufnr("%")')) end)
+ retry(nil, nil, function()
+ eq(1, eval('bufnr("%")'))
+ end)
command('3bdelete!')
- retry(nil, nil, function() eq('3', eval('g:abuf')) end)
+ retry(nil, nil, function()
+ eq('3', eval('g:abuf'))
+ end)
feed('<c-c>:qa!<cr>')
end)
@@ -124,10 +148,14 @@ describe('autocmd TermClose', function()
command('autocmd TermClose * let g:status = v:event.status')
command('terminal 0')
- retry(nil, nil, function() eq(0, eval('g:status')) end)
+ retry(nil, nil, function()
+ eq(0, eval('g:status'))
+ end)
command('terminal 42')
- retry(nil, nil, function() eq(42, eval('g:status')) end)
+ retry(nil, nil, function()
+ eq(42, eval('g:status'))
+ end)
end)
end)
@@ -141,27 +169,30 @@ it('autocmd TermEnter, TermLeave', function()
command('terminal')
feed('i')
- eq({ {'TermOpen', 'n'}, {'TermEnter', 't'}, }, eval('g:evs'))
+ eq({ { 'TermOpen', 'n' }, { 'TermEnter', 't' } }, eval('g:evs'))
feed([[<C-\><C-n>]])
feed('A')
- eq({ {'TermOpen', 'n'}, {'TermEnter', 't'}, {'TermLeave', 'n'}, {'TermEnter', 't'}, }, eval('g:evs'))
+ eq(
+ { { 'TermOpen', 'n' }, { 'TermEnter', 't' }, { 'TermLeave', 'n' }, { 'TermEnter', 't' } },
+ eval('g:evs')
+ )
-- TermLeave is also triggered by :quit.
command('split foo')
- feed('<Ignore>') -- Add input to separate two RPC requests
+ feed('<Ignore>') -- Add input to separate two RPC requests
command('wincmd w')
feed('i')
command('q!')
- feed('<Ignore>') -- Add input to separate two RPC requests
+ feed('<Ignore>') -- Add input to separate two RPC requests
eq({
- {'TermOpen', 'n'},
- {'TermEnter', 't'},
- {'TermLeave', 'n'},
- {'TermEnter', 't'},
- {'TermLeave', 'n'},
- {'TermEnter', 't'},
- {'TermClose', 't'},
- {'TermLeave', 'n'},
+ { 'TermOpen', 'n' },
+ { 'TermEnter', 't' },
+ { 'TermLeave', 'n' },
+ { 'TermEnter', 't' },
+ { 'TermLeave', 'n' },
+ { 'TermEnter', 't' },
+ { 'TermClose', 't' },
+ { 'TermLeave', 'n' },
}, eval('g:evs'))
end)
@@ -172,13 +203,18 @@ describe('autocmd TextChangedT', function()
it('works', function()
command('autocmd TextChangedT * ++once let g:called = 1')
thelpers.feed_data('a')
- retry(nil, nil, function() eq(1, meths.get_var('called')) end)
+ retry(nil, nil, function()
+ eq(1, api.nvim_get_var('called'))
+ end)
end)
it('cannot delete terminal buffer', function()
command([[autocmd TextChangedT * call nvim_input('<CR>') | bwipe!]])
thelpers.feed_data('a')
- screen:expect({any = 'E937: '})
- matches('^E937: Attempt to delete a buffer that is in use: term://', meths.get_vvar('errmsg'))
+ screen:expect({ any = 'E937: ' })
+ matches(
+ '^E937: Attempt to delete a buffer that is in use: term://',
+ api.nvim_get_vvar('errmsg')
+ )
end)
end)
diff --git a/test/functional/autocmd/textchanged_spec.lua b/test/functional/autocmd/textchanged_spec.lua
index b621eb36bf..d501560dc1 100644
--- a/test/functional/autocmd/textchanged_spec.lua
+++ b/test/functional/autocmd/textchanged_spec.lua
@@ -88,7 +88,7 @@ it('TextChangedI and TextChangedP autocommands', function()
eq('IIPPPP', eval('g:autocmd'))
feed('<esc>')
- eq({'foo', 'bar', 'foobar', 'foo'}, eval('getline(1, "$")'))
+ eq({ 'foo', 'bar', 'foobar', 'foo' }, eval('getline(1, "$")'))
end)
-- oldtest: Test_TextChangedI_with_setline()
@@ -172,11 +172,22 @@ it('TextChangedI and TextChanged', function()
eq('', eval('g:autocmd_n'))
end
- validate_mixed_textchangedi({'o', '<esc>'})
- validate_mixed_textchangedi({'O', '<esc>'})
- validate_mixed_textchangedi({'ciw', '<esc>'})
- validate_mixed_textchangedi({'cc', '<esc>'})
- validate_mixed_textchangedi({'C', '<esc>'})
- validate_mixed_textchangedi({'s', '<esc>'})
- validate_mixed_textchangedi({'S', '<esc>'})
+ validate_mixed_textchangedi({ 'o', '<esc>' })
+ validate_mixed_textchangedi({ 'O', '<esc>' })
+ validate_mixed_textchangedi({ 'ciw', '<esc>' })
+ validate_mixed_textchangedi({ 'cc', '<esc>' })
+ validate_mixed_textchangedi({ 'C', '<esc>' })
+ validate_mixed_textchangedi({ 's', '<esc>' })
+ validate_mixed_textchangedi({ 'S', '<esc>' })
+end)
+
+-- oldtest: Test_TextChanged_with_norm()
+it('TextChanged is triggered after :norm that enters Insert mode', function()
+ exec([[
+ let g:a = 0
+ au TextChanged * let g:a += 1
+ ]])
+ eq(0, eval('g:a'))
+ feed(':norm! ia<CR>')
+ eq(1, eval('g:a'))
end)
diff --git a/test/functional/autocmd/textyankpost_spec.lua b/test/functional/autocmd/textyankpost_spec.lua
index 1640916ad8..29cd62f586 100644
--- a/test/functional/autocmd/textyankpost_spec.lua
+++ b/test/functional/autocmd/textyankpost_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, eval, eq = helpers.clear, helpers.eval, helpers.eq
local feed, command, expect = helpers.feed, helpers.command, helpers.expect
-local curbufmeths, funcs, neq = helpers.curbufmeths, helpers.funcs, helpers.neq
+local api, fn, neq = helpers.api, helpers.fn, helpers.neq
describe('TextYankPost', function()
before_each(function()
@@ -14,7 +14,7 @@ describe('TextYankPost', function()
command('autocmd TextYankPost * let g:event = copy(v:event)')
command('autocmd TextYankPost * let g:count += 1')
- curbufmeths.set_lines(0, -1, true, {
+ api.nvim_buf_set_lines(0, 0, -1, true, {
'foo\0bar',
'baz text',
})
@@ -28,7 +28,7 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' },
regname = '',
regtype = 'V',
- visual = false
+ visual = false,
}, eval('g:event'))
eq(1, eval('g:count'))
@@ -42,7 +42,7 @@ describe('TextYankPost', function()
regcontents = { 'baz ' },
regname = '',
regtype = 'v',
- visual = false
+ visual = false,
}, eval('g:event'))
eq(2, eval('g:count'))
@@ -52,8 +52,8 @@ describe('TextYankPost', function()
operator = 'y',
regcontents = { 'foo', 'baz' },
regname = '',
- regtype = "\0223", -- ^V + block width
- visual = true
+ regtype = '\0223', -- ^V + block width
+ visual = true,
}, eval('g:event'))
eq(3, eval('g:count'))
end)
@@ -66,25 +66,25 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' },
regname = '',
regtype = 'V',
- visual = false
+ visual = false,
}, eval('g:event'))
command('set debug=msg')
-- the regcontents should not be changed without copy.
- local status, err = pcall(command,'call extend(g:event.regcontents, ["more text"])')
- eq(status,false)
+ local status, err = pcall(command, 'call extend(g:event.regcontents, ["more text"])')
+ eq(status, false)
neq(nil, string.find(err, ':E742:'))
-- can't mutate keys inside the autocommand
command('autocmd! TextYankPost * let v:event.regcontents = 0')
- status, err = pcall(command,'normal yy')
- eq(status,false)
+ status, err = pcall(command, 'normal yy')
+ eq(status, false)
neq(nil, string.find(err, ':E46:'))
-- can't add keys inside the autocommand
command('autocmd! TextYankPost * let v:event.mykey = 0')
- status, err = pcall(command,'normal yy')
- eq(status,false)
+ status, err = pcall(command, 'normal yy')
+ eq(status, false)
neq(nil, string.find(err, ':E742:'))
end)
@@ -97,10 +97,10 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' },
regname = '',
regtype = 'V',
- visual = false
+ visual = false,
}, eval('g:event'))
eq(1, eval('g:count'))
- eq({ 'foo\nbar' }, funcs.getreg('+',1,1))
+ eq({ 'foo\nbar' }, fn.getreg('+', 1, 1))
end)
it('is executed after delete and change', function()
@@ -111,7 +111,7 @@ describe('TextYankPost', function()
regcontents = { 'foo' },
regname = '',
regtype = 'v',
- visual = false
+ visual = false,
}, eval('g:event'))
eq(1, eval('g:count'))
@@ -122,7 +122,7 @@ describe('TextYankPost', function()
regcontents = { '\nbar' },
regname = '',
regtype = 'V',
- visual = false
+ visual = false,
}, eval('g:event'))
eq(2, eval('g:count'))
@@ -133,7 +133,7 @@ describe('TextYankPost', function()
regcontents = { 'baz' },
regname = '',
regtype = 'v',
- visual = false
+ visual = false,
}, eval('g:event'))
eq(3, eval('g:count'))
end)
@@ -162,7 +162,7 @@ describe('TextYankPost', function()
regcontents = { 'bar' },
regname = 'b',
regtype = 'v',
- visual = false
+ visual = false,
}, eval('g:event'))
feed('"*yy')
@@ -172,10 +172,10 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' },
regname = '*',
regtype = 'V',
- visual = false
+ visual = false,
}, eval('g:event'))
- command("set clipboard=unnamed")
+ command('set clipboard=unnamed')
-- regname still shows the name the user requested
feed('yy')
@@ -185,7 +185,7 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' },
regname = '',
regtype = 'V',
- visual = false
+ visual = false,
}, eval('g:event'))
feed('"*yy')
@@ -195,7 +195,7 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' },
regname = '*',
regtype = 'V',
- visual = false
+ visual = false,
}, eval('g:event'))
end)
@@ -207,7 +207,7 @@ describe('TextYankPost', function()
regcontents = { 'foo\nbar' },
regname = '+',
regtype = 'V',
- visual = false
+ visual = false,
}, eval('g:event'))
eq(1, eval('g:count'))
@@ -218,7 +218,7 @@ describe('TextYankPost', function()
regcontents = { 'baz text' },
regname = '',
regtype = 'V',
- visual = false
+ visual = false,
}, eval('g:event'))
eq(2, eval('g:count'))
@@ -229,7 +229,7 @@ describe('TextYankPost', function()
regcontents = { 'baz ' },
regname = '',
regtype = 'v',
- visual = false
+ visual = false,
}, eval('g:event'))
eq(3, eval('g:count'))
@@ -240,7 +240,7 @@ describe('TextYankPost', function()
regcontents = { 'baz text' },
regname = '',
regtype = 'V',
- visual = false
+ visual = false,
}, eval('g:event'))
eq(4, eval('g:count'))
end)
diff --git a/test/functional/autocmd/win_scrolled_resized_spec.lua b/test/functional/autocmd/win_scrolled_resized_spec.lua
index e6fdd9560d..d40dc37103 100644
--- a/test/functional/autocmd/win_scrolled_resized_spec.lua
+++ b/test/functional/autocmd/win_scrolled_resized_spec.lua
@@ -7,7 +7,7 @@ local eval = helpers.eval
local exec = helpers.exec
local command = helpers.command
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
local assert_alive = helpers.assert_alive
before_each(clear)
@@ -32,12 +32,29 @@ describe('WinResized', function()
-- increase window height, two windows will be reported
feed('<C-W>+')
eq(1, eval('g:resized'))
- eq({windows = {1002, 1001}}, eval('g:v_event'))
+ eq({ windows = { 1002, 1001 } }, eval('g:v_event'))
-- increase window width, three windows will be reported
feed('<C-W>>')
eq(2, eval('g:resized'))
- eq({windows = {1002, 1001, 1000}}, eval('g:v_event'))
+ eq({ windows = { 1002, 1001, 1000 } }, eval('g:v_event'))
+ end)
+
+ it('is triggered in terminal mode #21197 #27207', function()
+ exec([[
+ autocmd TermOpen * startinsert
+ let g:resized = 0
+ autocmd WinResized * let g:resized += 1
+ ]])
+ eq(0, eval('g:resized'))
+
+ command('vsplit term://')
+ eq({ mode = 't', blocking = false }, api.nvim_get_mode())
+ eq(1, eval('g:resized'))
+
+ command('split')
+ eq({ mode = 't', blocking = false }, api.nvim_get_mode())
+ eq(2, eval('g:resized'))
end)
end)
@@ -45,7 +62,7 @@ describe('WinScrolled', function()
local win_id
before_each(function()
- win_id = meths.get_current_win().id
+ win_id = api.nvim_get_current_win()
command(string.format('autocmd WinScrolled %d let g:matched = v:true', win_id))
exec([[
let g:scrolled = 0
@@ -63,104 +80,104 @@ describe('WinScrolled', function()
end)
it('is triggered by scrolling vertically', function()
- local lines = {'123', '123'}
- meths.buf_set_lines(0, 0, -1, true, lines)
+ local lines = { '123', '123' }
+ api.nvim_buf_set_lines(0, 0, -1, true, lines)
eq(0, eval('g:scrolled'))
feed('<C-E>')
eq(1, eval('g:scrolled'))
eq({
- all = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
feed('<C-Y>')
eq(2, eval('g:scrolled'))
eq({
- all = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 0, topline = -1, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 0, topline = -1, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
end)
it('is triggered by scrolling horizontally', function()
command('set nowrap')
- local width = meths.win_get_width(0)
+ local width = api.nvim_win_get_width(0)
local line = '123' .. ('*'):rep(width * 2)
- local lines = {line, line}
- meths.buf_set_lines(0, 0, -1, true, lines)
+ local lines = { line, line }
+ api.nvim_buf_set_lines(0, 0, -1, true, lines)
eq(0, eval('g:scrolled'))
feed('zl')
eq(1, eval('g:scrolled'))
eq({
- all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
feed('zh')
eq(2, eval('g:scrolled'))
eq({
- all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
end)
it('is triggered by horizontal scrolling from cursor move', function()
command('set nowrap')
- local lines = {'', '', 'Foo'}
- meths.buf_set_lines(0, 0, -1, true, lines)
- meths.win_set_cursor(0, {3, 0})
+ local lines = { '', '', 'Foo' }
+ api.nvim_buf_set_lines(0, 0, -1, true, lines)
+ api.nvim_win_set_cursor(0, { 3, 0 })
eq(0, eval('g:scrolled'))
feed('zl')
eq(1, eval('g:scrolled'))
eq({
- all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
feed('zl')
eq(2, eval('g:scrolled'))
eq({
- all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
feed('h')
eq(3, eval('g:scrolled'))
eq({
- all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
feed('zh')
eq(4, eval('g:scrolled'))
eq({
- all = {leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = -1, topline = 0, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
end)
-- oldtest: Test_WinScrolled_long_wrapped()
it('is triggered by scrolling on a long wrapped line #19968', function()
- local height = meths.win_get_height(0)
- local width = meths.win_get_width(0)
- meths.buf_set_lines(0, 0, -1, true, {('foo'):rep(height * width)})
- meths.win_set_cursor(0, {1, height * width - 1})
+ local height = api.nvim_win_get_height(0)
+ local width = api.nvim_win_get_width(0)
+ api.nvim_buf_set_lines(0, 0, -1, true, { ('foo'):rep(height * width) })
+ api.nvim_win_set_cursor(0, { 1, height * width - 1 })
eq(0, eval('g:scrolled'))
feed('gj')
eq(1, eval('g:scrolled'))
eq({
- all = {leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width},
- ['1000'] = {leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width},
+ all = { leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width },
+ ['1000'] = { leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width },
}, eval('g:v_event'))
feed('0')
eq(2, eval('g:scrolled'))
eq({
- all = {leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width},
- ['1000'] = {leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = -width},
+ all = { leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = width },
+ ['1000'] = { leftcol = 0, topline = 0, topfill = 0, width = 0, height = 0, skipcol = -width },
}, eval('g:v_event'))
feed('$')
@@ -168,12 +185,12 @@ describe('WinScrolled', function()
end)
it('is triggered when the window scrolls in Insert mode', function()
- local height = meths.win_get_height(0)
+ local height = api.nvim_win_get_height(0)
local lines = {}
for i = 1, height * 2 do
lines[i] = tostring(i)
end
- meths.buf_set_lines(0, 0, -1, true, lines)
+ api.nvim_buf_set_lines(0, 0, -1, true, lines)
feed('M')
eq(0, eval('g:scrolled'))
@@ -181,15 +198,15 @@ describe('WinScrolled', function()
feed('i<C-X><C-E><Esc>')
eq(1, eval('g:scrolled'))
eq({
- all = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
feed('i<C-X><C-Y><Esc>')
eq(2, eval('g:scrolled'))
eq({
- all = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 0, topline = -1, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 0, topline = -1, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
feed('L')
@@ -198,8 +215,8 @@ describe('WinScrolled', function()
feed('A<CR><Esc>')
eq(3, eval('g:scrolled'))
eq({
- all = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
end)
end)
@@ -220,12 +237,12 @@ describe('WinScrolled', function()
eq(0, eval('g:scrolled'))
-- With the upper split focused, send a scroll-down event to the unfocused one.
- meths.input_mouse('wheel', 'down', '', 0, 6, 0)
+ api.nvim_input_mouse('wheel', 'down', '', 0, 6, 0)
eq(1, eval('g:scrolled'))
-- Again, but this time while we're in insert mode.
feed('i')
- meths.input_mouse('wheel', 'down', '', 0, 6, 0)
+ api.nvim_input_mouse('wheel', 'down', '', 0, 6, 0)
feed('<Esc>')
eq(2, eval('g:scrolled'))
end)
@@ -257,30 +274,30 @@ describe('WinScrolled', function()
feed('<C-E>')
eq({
- all = {leftcol = 0, topline = 1, topfill = 1, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1001'] = {leftcol = 0, topline = 0, topfill = -1, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 0, topline = 1, topfill = 1, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1001'] = { leftcol = 0, topline = 0, topfill = -1, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
feed('2<C-E>')
eq({
- all = {leftcol = 0, topline = 2, topfill = 2, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 0, topline = 2, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1001'] = {leftcol = 0, topline = 0, topfill = -2, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 0, topline = 2, topfill = 2, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 0, topline = 2, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1001'] = { leftcol = 0, topline = 0, topfill = -2, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
feed('<C-E>')
eq({
- all = {leftcol = 0, topline = 2, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1001'] = {leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 0, topline = 2, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1001'] = { leftcol = 0, topline = 1, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
feed('2<C-Y>')
eq({
- all = {leftcol = 0, topline = 3, topfill = 1, width = 0, height = 0, skipcol = 0},
- ['1000'] = {leftcol = 0, topline = -2, topfill = 0, width = 0, height = 0, skipcol = 0},
- ['1001'] = {leftcol = 0, topline = -1, topfill = 1, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 0, topline = 3, topfill = 1, width = 0, height = 0, skipcol = 0 },
+ ['1000'] = { leftcol = 0, topline = -2, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ ['1001'] = { leftcol = 0, topline = -1, topfill = 1, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
end)
@@ -296,35 +313,41 @@ describe('WinScrolled', function()
]])
eq(0, eval('g:scrolled'))
- local buf = meths.create_buf(true, true)
- meths.buf_set_lines(buf, 0, -1, false, {'@', 'b', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n'})
- local win = meths.open_win(buf, false, {
+ local buf = api.nvim_create_buf(true, true)
+ api.nvim_buf_set_lines(
+ buf,
+ 0,
+ -1,
+ false,
+ { '@', 'b', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n' }
+ )
+ local win = api.nvim_open_win(buf, false, {
height = 5,
width = 10,
col = 0,
row = 1,
relative = 'editor',
- style = 'minimal'
+ style = 'minimal',
})
screen:expect({ any = '@' })
- local winid_str = tostring(win.id)
+ local winid_str = tostring(win)
-- WinScrolled should not be triggered when creating a new floating window
eq(0, eval('g:scrolled'))
- meths.input_mouse('wheel', 'down', '', 0, 3, 3)
+ api.nvim_input_mouse('wheel', 'down', '', 0, 3, 3)
eq(1, eval('g:scrolled'))
eq(winid_str, eval('g:amatch'))
eq({
- all = {leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0},
- [winid_str] = {leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ [winid_str] = { leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
- meths.input_mouse('wheel', 'up', '', 0, 3, 3)
+ api.nvim_input_mouse('wheel', 'up', '', 0, 3, 3)
eq(2, eval('g:scrolled'))
- eq(tostring(win.id), eval('g:amatch'))
+ eq(tostring(win), eval('g:amatch'))
eq({
- all = {leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0},
- [winid_str] = {leftcol = 0, topline = -3, topfill = 0, width = 0, height = 0, skipcol = 0},
+ all = { leftcol = 0, topline = 3, topfill = 0, width = 0, height = 0, skipcol = 0 },
+ [winid_str] = { leftcol = 0, topline = -3, topfill = 0, width = 0, height = 0, skipcol = 0 },
}, eval('g:v_event'))
end)
end)
diff --git a/test/functional/core/channels_spec.lua b/test/functional/core/channels_spec.lua
index 5771ddcb94..56a2f5a571 100644
--- a/test/functional/core/channels_spec.lua
+++ b/test/functional/core/channels_spec.lua
@@ -1,10 +1,10 @@
local helpers = require('test.functional.helpers')(after_each)
-local clear, eq, eval, next_msg, ok, source = helpers.clear, helpers.eq,
- helpers.eval, helpers.next_msg, helpers.ok, helpers.source
-local command, funcs, meths = helpers.command, helpers.funcs, helpers.meths
-local sleep = helpers.sleep
+local clear, eq, eval, next_msg, ok, source =
+ helpers.clear, helpers.eq, helpers.eval, helpers.next_msg, helpers.ok, helpers.source
+local command, fn, api = helpers.command, helpers.fn, helpers.api
+local sleep = vim.uv.sleep
local spawn, nvim_argv = helpers.spawn, helpers.nvim_argv
-local set_session = helpers.set_session
+local get_session, set_session = helpers.get_session, helpers.set_session
local nvim_prog = helpers.nvim_prog
local is_os = helpers.is_os
local retry = helpers.retry
@@ -33,31 +33,67 @@ describe('channels', function()
pending('can connect to socket', function()
local server = spawn(nvim_argv, nil, nil, true)
set_session(server)
- local address = funcs.serverlist()[1]
+ local address = fn.serverlist()[1]
local client = spawn(nvim_argv, nil, nil, true)
set_session(client)
source(init)
- meths.set_var('address', address)
+ api.nvim_set_var('address', address)
command("let g:id = sockconnect('pipe', address, {'on_data':'OnEvent'})")
- local id = eval("g:id")
+ local id = eval('g:id')
ok(id > 0)
command("call chansend(g:id, msgpackdump([[2,'nvim_set_var',['code',23]]]))")
set_session(server)
retry(nil, 1000, function()
- eq(23, meths.get_var('code'))
+ eq(23, api.nvim_get_var('code'))
end)
set_session(client)
command("call chansend(g:id, msgpackdump([[0,0,'nvim_eval',['2+3']]]))")
-
- local res = eval("msgpackdump([[1,0,v:null,5]])")
- eq({"\148\001\n\192\005"}, res)
- eq({'notification', 'data', {id, res}}, next_msg())
+ local res = eval('msgpackdump([[1,0,v:null,5]])')
+ eq({ '\148\001\n\192\005' }, res)
+ eq({ 'notification', 'data', { id, res } }, next_msg())
command("call chansend(g:id, msgpackdump([[2,'nvim_command',['quit']]]))")
- eq({'notification', 'data', {id, {''}}}, next_msg())
+ eq({ 'notification', 'data', { id, { '' } } }, next_msg())
+ end)
+
+ it('dont crash due to garbage in rpc #23781', function()
+ local client = get_session()
+ local server = spawn(nvim_argv, nil, nil, true)
+ set_session(server)
+ local address = fn.serverlist()[1]
+ set_session(client)
+
+ api.nvim_set_var('address', address)
+ command("let g:id = sockconnect('pipe', address, {'on_data':'OnEvent'})")
+ local id = eval('g:id')
+ ok(id > 0)
+
+ command("call chansend(g:id, 'F')")
+ eq({ 'notification', 'data', { id, { '' } } }, next_msg())
+ set_session(server)
+ assert_alive()
+
+ set_session(client)
+ command('call chanclose(g:id)')
+ command("let g:id = sockconnect('pipe', address, {'on_data':'OnEvent'})")
+ id = eval('g:id')
+ ok(id > 0)
+
+ command("call chansend(g:id, msgpackdump([[2, 'redraw', 'F']], 'B')[:-4])")
+ set_session(server)
+ assert_alive()
+ set_session(client)
+ command("call chansend(g:id, 'F')")
+ eq({ 'notification', 'data', { id, { '' } } }, next_msg())
+
+ set_session(server)
+ assert_alive()
+ set_session(client)
+ command('call chanclose(g:id)')
+ server:close()
end)
it('can use stdio channel', function()
@@ -68,8 +104,10 @@ describe('channels', function()
\ 'on_exit': function('OnEvent'),
\ }
]])
- meths.set_var("nvim_prog", nvim_prog)
- meths.set_var("code", [[
+ api.nvim_set_var('nvim_prog', nvim_prog)
+ api.nvim_set_var(
+ 'code',
+ [[
function! OnEvent(id, data, event) dict
let text = string([a:id, a:data, a:event])
call chansend(g:x, text)
@@ -81,25 +119,31 @@ describe('channels', function()
endfunction
let g:x = stdioopen({'on_stdin':'OnEvent'})
call chansend(x, "hello")
- ]])
- command("let g:id = jobstart([ g:nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--headless', '--cmd', g:code], g:job_opts)")
- local id = eval("g:id")
+ ]]
+ )
+ command(
+ "let g:id = jobstart([ g:nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--headless', '--cmd', g:code], g:job_opts)"
+ )
+ local id = eval('g:id')
ok(id > 0)
- eq({ "notification", "stdout", {id, { "hello" } } }, next_msg())
+ eq({ 'notification', 'stdout', { id, { 'hello' } } }, next_msg())
command("call chansend(id, 'howdy')")
- eq({"notification", "stdout", {id, {"[1, ['howdy'], 'stdin']"}}}, next_msg())
+ eq({ 'notification', 'stdout', { id, { "[1, ['howdy'], 'stdin']" } } }, next_msg())
- command("call chansend(id, 0z686f6c61)")
- eq({"notification", "stdout", {id, {"[1, ['hola'], 'stdin']"}}}, next_msg())
+ command('call chansend(id, 0z686f6c61)')
+ eq({ 'notification', 'stdout', { id, { "[1, ['hola'], 'stdin']" } } }, next_msg())
command("call chanclose(id, 'stdin')")
- expect_twostreams({{"notification", "stdout", {id, {"[1, [''], 'stdin']"}}},
- {'notification', 'stdout', {id, {''}}}},
- {{"notification", "stderr", {id, {"*dies*"}}},
- {'notification', 'stderr', {id, {''}}}})
- eq({"notification", "exit", {3,0}}, next_msg())
+ expect_twostreams({
+ { 'notification', 'stdout', { id, { "[1, [''], 'stdin']" } } },
+ { 'notification', 'stdout', { id, { '' } } },
+ }, {
+ { 'notification', 'stderr', { id, { '*dies*' } } },
+ { 'notification', 'stderr', { id, { '' } } },
+ })
+ eq({ 'notification', 'exit', { 3, 0 } }, next_msg())
end)
it('can use stdio channel and on_print callback', function()
@@ -110,8 +154,10 @@ describe('channels', function()
\ 'on_exit': function('OnEvent'),
\ }
]])
- meths.set_var("nvim_prog", nvim_prog)
- meths.set_var("code", [[
+ api.nvim_set_var('nvim_prog', nvim_prog)
+ api.nvim_set_var(
+ 'code',
+ [[
function! OnStdin(id, data, event) dict
echo string([a:id, a:data, a:event])
if a:data == ['']
@@ -123,24 +169,27 @@ describe('channels', function()
endfunction
let g:x = stdioopen({'on_stdin': funcref('OnStdin'), 'on_print':'OnPrint'})
call chansend(x, "hello")
- ]])
- command("let g:id = jobstart([ g:nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--headless', '--cmd', g:code], g:job_opts)")
- local id = eval("g:id")
+ ]]
+ )
+ command(
+ "let g:id = jobstart([ g:nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--headless', '--cmd', g:code], g:job_opts)"
+ )
+ local id = eval('g:id')
ok(id > 0)
- eq({ "notification", "stdout", {id, { "hello" } } }, next_msg())
+ eq({ 'notification', 'stdout', { id, { 'hello' } } }, next_msg())
command("call chansend(id, 'howdy')")
- eq({"notification", "stdout", {id, {"OnPrint:[1, ['howdy'], 'stdin']"}}}, next_msg())
+ eq({ 'notification', 'stdout', { id, { "OnPrint:[1, ['howdy'], 'stdin']" } } }, next_msg())
end)
local function expect_twoline(id, stream, line1, line2, nobr)
local msg = next_msg()
- local joined = nobr and {line1..line2} or {line1, line2}
- if not pcall(eq, {"notification", stream, {id, joined}}, msg) then
- local sep = (not nobr) and "" or nil
- eq({"notification", stream, {id, {line1, sep}}}, msg)
- eq({"notification", stream, {id, {line2}}}, next_msg())
+ local joined = nobr and { line1 .. line2 } or { line1, line2 }
+ if not pcall(eq, { 'notification', stream, { id, joined } }, msg) then
+ local sep = (not nobr) and '' or nil
+ eq({ 'notification', stream, { id, { line1, sep } } }, msg)
+ eq({ 'notification', stream, { id, { line2 } } }, next_msg())
end
end
@@ -153,50 +202,52 @@ describe('channels', function()
\ 'pty': v:true,
\ }
]])
- meths.set_var("nvim_prog", nvim_prog)
- meths.set_var("code", [[
+ api.nvim_set_var('nvim_prog', nvim_prog)
+ api.nvim_set_var(
+ 'code',
+ [[
function! OnEvent(id, data, event) dict
let text = string([a:id, a:data, a:event])
call chansend(g:x, text)
endfunction
let g:x = stdioopen({'on_stdin':'OnEvent'})
- ]])
- command("let g:id = jobstart([ g:nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--headless', '--cmd', g:code], g:job_opts)")
- local id = eval("g:id")
+ ]]
+ )
+ command(
+ "let g:id = jobstart([ g:nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--headless', '--cmd', g:code], g:job_opts)"
+ )
+ local id = eval('g:id')
ok(id > 0)
command("call chansend(id, 'TEXT\n')")
- expect_twoline(id, "stdout", "TEXT\r", "[1, ['TEXT', ''], 'stdin']")
+ expect_twoline(id, 'stdout', 'TEXT\r', "[1, ['TEXT', ''], 'stdin']")
- command("call chansend(id, 0z426c6f6273210a)")
- expect_twoline(id, "stdout", "Blobs!\r", "[1, ['Blobs!', ''], 'stdin']")
+ command('call chansend(id, 0z426c6f6273210a)')
+ expect_twoline(id, 'stdout', 'Blobs!\r', "[1, ['Blobs!', ''], 'stdin']")
command("call chansend(id, 'neovan')")
- eq({"notification", "stdout", {id, {"neovan"}}}, next_msg())
+ eq({ 'notification', 'stdout', { id, { 'neovan' } } }, next_msg())
command("call chansend(id, '\127\127im\n')")
- expect_twoline(id, "stdout", "\b \b\b \bim\r", "[1, ['neovim', ''], 'stdin']")
+ expect_twoline(id, 'stdout', '\b \b\b \bim\r', "[1, ['neovim', ''], 'stdin']")
command("call chansend(id, 'incomplet\004')")
local bsdlike = is_os('bsd') or is_os('mac')
- local extra = bsdlike and "^D\008\008" or ""
- expect_twoline(id, "stdout",
- "incomplet"..extra, "[1, ['incomplet'], 'stdin']", true)
-
+ local extra = bsdlike and '^D\008\008' or ''
+ expect_twoline(id, 'stdout', 'incomplet' .. extra, "[1, ['incomplet'], 'stdin']", true)
command("call chansend(id, '\004')")
if bsdlike then
- expect_twoline(id, "stdout", extra, "[1, [''], 'stdin']", true)
+ expect_twoline(id, 'stdout', extra, "[1, [''], 'stdin']", true)
else
- eq({"notification", "stdout", {id, {"[1, [''], 'stdin']"}}}, next_msg())
+ eq({ 'notification', 'stdout', { id, { "[1, [''], 'stdin']" } } }, next_msg())
end
-- channel is still open
command("call chansend(id, 'hi again!\n')")
- eq({"notification", "stdout", {id, {"hi again!\r", ""}}}, next_msg())
+ eq({ 'notification', 'stdout', { id, { 'hi again!\r', '' } } }, next_msg())
end)
-
it('stdio channel can use rpc and stderr simultaneously', function()
skip(is_os('win'))
source([[
@@ -206,31 +257,37 @@ describe('channels', function()
\ 'rpc': v:true,
\ }
]])
- meths.set_var("nvim_prog", nvim_prog)
- meths.set_var("code", [[
+ api.nvim_set_var('nvim_prog', nvim_prog)
+ api.nvim_set_var(
+ 'code',
+ [[
let id = stdioopen({'rpc':v:true})
call rpcnotify(id,"nvim_call_function", "rpcnotify", [1, "message", "hi there!", id])
call chansend(v:stderr, "trouble!")
- ]])
- command("let id = jobstart([ g:nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--headless', '--cmd', g:code], g:job_opts)")
- eq({"notification", "message", {"hi there!", 1}}, next_msg())
- eq({"notification", "stderr", {3, {"trouble!"}}}, next_msg())
+ ]]
+ )
+ command(
+ "let id = jobstart([ g:nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', 'set noswapfile', '--headless', '--cmd', g:code], g:job_opts)"
+ )
+ eq({ 'notification', 'message', { 'hi there!', 1 } }, next_msg())
+ eq({ 'notification', 'stderr', { 3, { 'trouble!' } } }, next_msg())
eq(30, eval("rpcrequest(id, 'nvim_eval', '[chansend(v:stderr, \"math??\"), 5*6][1]')"))
- eq({"notification", "stderr", {3, {"math??"}}}, next_msg())
+ eq({ 'notification', 'stderr', { 3, { 'math??' } } }, next_msg())
- local _, err = pcall(command,"call rpcrequest(id, 'nvim_command', 'call chanclose(v:stderr, \"stdin\")')")
- ok(string.find(err,"E906: invalid stream for channel") ~= nil)
+ local _, err =
+ pcall(command, "call rpcrequest(id, 'nvim_command', 'call chanclose(v:stderr, \"stdin\")')")
+ ok(string.find(err, 'E906: invalid stream for channel') ~= nil)
eq(1, eval("rpcrequest(id, 'nvim_eval', 'chanclose(v:stderr, \"stderr\")')"))
- eq({"notification", "stderr", {3, {""}}}, next_msg())
+ eq({ 'notification', 'stderr', { 3, { '' } } }, next_msg())
command("call rpcnotify(id, 'nvim_command', 'quit')")
- eq({"notification", "exit", {3, 0}}, next_msg())
+ eq({ 'notification', 'exit', { 3, 0 } }, next_msg())
end)
it('can use buffered output mode', function()
- skip(funcs.executable('grep') == 0, 'missing "grep" command')
+ skip(fn.executable('grep') == 0, 'missing "grep" command')
source([[
let g:job_opts = {
\ 'on_stdout': function('OnEvent'),
@@ -239,31 +296,33 @@ describe('channels', function()
\ }
]])
command("let id = jobstart(['grep', '^[0-9]'], g:job_opts)")
- local id = eval("g:id")
+ local id = eval('g:id')
command([[call chansend(id, "stuff\n10 PRINT \"NVIM\"\nxx")]])
sleep(10)
command([[call chansend(id, "xx\n20 GOTO 10\nzz\n")]])
command("call chanclose(id, 'stdin')")
- eq({"notification", "stdout", {id, {'10 PRINT "NVIM"',
- '20 GOTO 10', ''}}}, next_msg())
- eq({"notification", "exit", {id, 0}}, next_msg())
+ eq({
+ 'notification',
+ 'stdout',
+ { id, { '10 PRINT "NVIM"', '20 GOTO 10', '' } },
+ }, next_msg())
+ eq({ 'notification', 'exit', { id, 0 } }, next_msg())
command("let id = jobstart(['grep', '^[0-9]'], g:job_opts)")
- id = eval("g:id")
+ id = eval('g:id')
command([[call chansend(id, "is no number\nnot at all")]])
command("call chanclose(id, 'stdin')")
-- works correctly with no output
- eq({"notification", "stdout", {id, {''}}}, next_msg())
- eq({"notification", "exit", {id, 1}}, next_msg())
-
+ eq({ 'notification', 'stdout', { id, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { id, 1 } }, next_msg())
end)
it('can use buffered output mode with no stream callback', function()
- skip(funcs.executable('grep') == 0, 'missing "grep" command')
+ skip(fn.executable('grep') == 0, 'missing "grep" command')
source([[
function! OnEvent(id, data, event) dict
call rpcnotify(1, a:event, a:id, a:data, self.stdout)
@@ -274,31 +333,40 @@ describe('channels', function()
\ }
]])
command("let id = jobstart(['grep', '^[0-9]'], g:job_opts)")
- local id = eval("g:id")
+ local id = eval('g:id')
command([[call chansend(id, "stuff\n10 PRINT \"NVIM\"\nxx")]])
sleep(10)
command([[call chansend(id, "xx\n20 GOTO 10\nzz\n")]])
command("call chanclose(id, 'stdin')")
- eq({"notification", "exit", {id, 0, {'10 PRINT "NVIM"',
- '20 GOTO 10', ''}}}, next_msg())
+ eq({
+ 'notification',
+ 'exit',
+ { id, 0, { '10 PRINT "NVIM"', '20 GOTO 10', '' } },
+ }, next_msg())
-- if dict is reused the new value is not stored,
-- but nvim also does not crash
command("let id = jobstart(['cat'], g:job_opts)")
- id = eval("g:id")
+ id = eval('g:id')
command([[call chansend(id, "cat text\n")]])
sleep(10)
command("call chanclose(id, 'stdin')")
-- old value was not overwritten
- eq({"notification", "exit", {id, 0, {'10 PRINT "NVIM"',
- '20 GOTO 10', ''}}}, next_msg())
+ eq({
+ 'notification',
+ 'exit',
+ { id, 0, { '10 PRINT "NVIM"', '20 GOTO 10', '' } },
+ }, next_msg())
-- and an error was thrown.
- eq("E5210: dict key 'stdout' already set for buffered stream in channel "..id, eval('v:errmsg'))
+ eq(
+ "E5210: dict key 'stdout' already set for buffered stream in channel " .. id,
+ eval('v:errmsg')
+ )
-- reset dictionary
source([[
@@ -308,13 +376,13 @@ describe('channels', function()
\ }
]])
command("let id = jobstart(['grep', '^[0-9]'], g:job_opts)")
- id = eval("g:id")
+ id = eval('g:id')
command([[call chansend(id, "is no number\nnot at all")]])
command("call chanclose(id, 'stdin')")
-- works correctly with no output
- eq({"notification", "exit", {id, 1, {''}}}, next_msg())
+ eq({ 'notification', 'exit', { id, 1, { '' } } }, next_msg())
end)
end)
@@ -325,8 +393,10 @@ describe('loopback', function()
end)
it('does not crash when sending raw data', function()
- eq("Vim(call):Can't send raw data to rpc channel",
- pcall_err(command, "call chansend(chan, 'test')"))
+ eq(
+ "Vim(call):Can't send raw data to rpc channel",
+ pcall_err(command, "call chansend(chan, 'test')")
+ )
assert_alive()
end)
diff --git a/test/functional/core/exit_spec.lua b/test/functional/core/exit_spec.lua
index d474b77806..d9e3cc3f31 100644
--- a/test/functional/core/exit_spec.lua
+++ b/test/functional/core/exit_spec.lua
@@ -7,7 +7,7 @@ local feed = helpers.feed
local eval = helpers.eval
local eq = helpers.eq
local run = helpers.run
-local funcs = helpers.funcs
+local fn = helpers.fn
local nvim_prog = helpers.nvim_prog
local pcall_err = helpers.pcall_err
local exec_capture = helpers.exec_capture
@@ -18,7 +18,7 @@ describe('v:exiting', function()
before_each(function()
helpers.clear()
- cid = helpers.nvim('get_api_info')[1]
+ cid = helpers.api.nvim_get_chan_info(0).id
end)
it('defaults to v:null', function()
@@ -27,8 +27,8 @@ describe('v:exiting', function()
local function test_exiting(setup_fn)
local function on_setup()
- command('autocmd VimLeavePre * call rpcrequest('..cid..', "exit", "VimLeavePre")')
- command('autocmd VimLeave * call rpcrequest('..cid..', "exit", "VimLeave")')
+ command('autocmd VimLeavePre * call rpcrequest(' .. cid .. ', "exit", "VimLeavePre")')
+ command('autocmd VimLeave * call rpcrequest(' .. cid .. ', "exit", "VimLeave")')
setup_fn()
end
local requests_args = {}
@@ -39,7 +39,7 @@ describe('v:exiting', function()
return ''
end
run(on_request, nil, on_setup)
- eq({{'VimLeavePre'}, {'VimLeave'}}, requests_args)
+ eq({ { 'VimLeavePre' }, { 'VimLeave' } }, requests_args)
end
it('is 0 on normal exit', function()
@@ -59,11 +59,16 @@ end)
describe(':cquit', function()
local function test_cq(cmdline, exit_code, redir_msg)
if redir_msg then
- eq(redir_msg, pcall_err(function() return exec_capture(cmdline) end))
+ eq(
+ redir_msg,
+ pcall_err(function()
+ return exec_capture(cmdline)
+ end)
+ )
poke_eventloop()
assert_alive()
else
- funcs.system({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless', '--cmd', cmdline})
+ fn.system({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless', '--cmd', cmdline })
eq(exit_code, eval('v:shell_error'))
end
end
diff --git a/test/functional/core/fileio_spec.lua b/test/functional/core/fileio_spec.lua
index 65f947132e..928cab525c 100644
--- a/test/functional/core/fileio_spec.lua
+++ b/test/functional/core/fileio_spec.lua
@@ -1,4 +1,4 @@
-local luv = require('luv')
+local uv = vim.uv
local helpers = require('test.functional.helpers')(after_each)
local assert_log = helpers.assert_log
@@ -9,18 +9,18 @@ local eq = helpers.eq
local neq = helpers.neq
local ok = helpers.ok
local feed = helpers.feed
-local funcs = helpers.funcs
+local fn = helpers.fn
local nvim_prog = helpers.nvim_prog
local request = helpers.request
local retry = helpers.retry
local rmdir = helpers.rmdir
local matches = helpers.matches
-local meths = helpers.meths
+local api = helpers.api
local mkdir = helpers.mkdir
-local sleep = helpers.sleep
+local sleep = vim.uv.sleep
local read_file = helpers.read_file
-local trim = helpers.trim
-local currentdir = helpers.funcs.getcwd
+local trim = vim.trim
+local currentdir = helpers.fn.getcwd
local assert_alive = helpers.assert_alive
local check_close = helpers.check_close
local expect_exit = helpers.expect_exit
@@ -30,10 +30,11 @@ local feed_command = helpers.feed_command
local skip = helpers.skip
local is_os = helpers.is_os
local is_ci = helpers.is_ci
+local spawn = helpers.spawn
+local set_session = helpers.set_session
describe('fileio', function()
- before_each(function()
- end)
+ before_each(function() end)
after_each(function()
check_close()
os.remove('Xtest_startup_shada')
@@ -49,54 +50,91 @@ describe('fileio', function()
rmdir('Xtest_backupdir with spaces')
end)
- it('fsync() codepaths #8304', function()
- clear({ args={ '-i', 'Xtest_startup_shada',
- '--cmd', 'set nofsync',
- '--cmd', 'set directory=Xtest_startup_swapdir' } })
+ local args = { nvim_prog, '--clean', '--cmd', 'set nofsync directory=Xtest_startup_swapdir' }
+ --- Starts a new nvim session and returns an attached screen.
+ local function startup(extra_args)
+ extra_args = extra_args or {}
+ local argv = vim.tbl_flatten({ args, '--embed', extra_args })
+ local screen_nvim = spawn(argv)
+ set_session(screen_nvim)
+ local screen = Screen.new(70, 10)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = { foreground = Screen.colors.NvimDarkGrey4 },
+ [2] = { background = Screen.colors.NvimDarkGrey1, foreground = Screen.colors.NvimLightGrey3 },
+ [3] = { foreground = Screen.colors.NvimLightCyan },
+ })
+ return screen
+ end
+
+ it("fsync() with 'nofsync' #8304", function()
+ clear({ args = { '--cmd', 'set nofsync directory=Xtest_startup_swapdir' } })
-- These cases ALWAYS force fsync (regardless of 'fsync' option):
-- 1. Idle (CursorHold) with modified buffers (+ 'swapfile').
command('write Xtest_startup_file1')
- feed('ifoo<esc>h')
+ feed('Afoo<esc>h')
command('write')
- eq(0, request('nvim__stats').fsync) -- 'nofsync' is the default.
+ eq(0, request('nvim__stats').fsync)
command('set swapfile')
command('set updatetime=1')
- feed('izub<esc>h') -- File is 'modified'.
- sleep(3) -- Allow 'updatetime' to expire.
+ feed('Azub<esc>h') -- File is 'modified'.
+ sleep(3) -- Allow 'updatetime' to expire.
retry(3, nil, function()
eq(1, request('nvim__stats').fsync)
end)
- command('set updatetime=9999')
+ command('set updatetime=100000 updatecount=100000')
- -- 2. Exit caused by deadly signal (+ 'swapfile').
- local j = funcs.jobstart({ nvim_prog, '-u', 'NONE', '-i',
- 'Xtest_startup_shada', '--headless',
- '-c', 'set swapfile',
- '-c', 'write Xtest_startup_file2',
- '-c', 'put =localtime()', })
- sleep(10) -- Let Nvim start.
- funcs.jobstop(j) -- Send deadly signal.
-
- -- 3. SIGPWR signal.
- -- ??
-
- -- 4. Explicit :preserve command.
+ -- 2. Explicit :preserve command.
command('preserve')
- eq(2, request('nvim__stats').fsync)
+ -- TODO: should be exactly 2; where is the extra fsync() is coming from? #26404
+ ok(request('nvim__stats').fsync == 2 or request('nvim__stats').fsync == 3)
- -- 5. Enable 'fsync' option, write file.
+ -- 3. Enable 'fsync' option, write file.
command('set fsync')
- feed('ibaz<esc>h')
+ feed('Abaz<esc>h')
command('write')
- eq(4, request('nvim__stats').fsync)
+ -- TODO: should be exactly 4; where is the extra fsync() is coming from? #26404
+ ok(request('nvim__stats').fsync == 4 or request('nvim__stats').fsync == 5)
+ eq('foozubbaz', trim(read_file('Xtest_startup_file1')))
+
+ -- 4. Exit caused by deadly signal (+ 'swapfile').
+ local j = fn.jobstart(vim.tbl_flatten({ args, '--embed' }), { rpc = true })
+ fn.rpcrequest(
+ j,
+ 'nvim_exec2',
+ [[
+ set nofsync directory=Xtest_startup_swapdir
+ edit Xtest_startup_file2
+ write
+ put ='fsyncd text'
+ ]],
+ {}
+ )
+ eq('Xtest_startup_swapdir', fn.rpcrequest(j, 'nvim_eval', '&directory'))
+ fn.jobstop(j) -- Send deadly signal.
+
+ local screen = startup()
+ feed(':recover Xtest_startup_file2<cr>')
+ screen:expect({ any = [[Using swap file "Xtest_startup_swapdir[/\]Xtest_startup_file2%.swp"]] })
+ feed('<cr>')
+ screen:expect({ any = 'fsyncd text' })
+
+ -- 5. SIGPWR signal.
+ -- oldtest: Test_signal_PWR()
end)
it('backup #9709', function()
skip(is_ci('cirrus'))
- clear({ args={ '-i', 'Xtest_startup_shada',
- '--cmd', 'set directory=Xtest_startup_swapdir' } })
+ clear({
+ args = {
+ '-i',
+ 'Xtest_startup_shada',
+ '--cmd',
+ 'set directory=Xtest_startup_swapdir',
+ },
+ })
command('write Xtest_startup_file1')
feed('ifoo<esc>')
@@ -109,8 +147,8 @@ describe('fileio', function()
local foobar_contents = trim(read_file('Xtest_startup_file1'))
local bar_contents = trim(read_file('Xtest_startup_file1~'))
- eq('foobar', foobar_contents);
- eq('foo', bar_contents);
+ eq('foobar', foobar_contents)
+ eq('foo', bar_contents)
end)
it('backup with full path #11214', function()
@@ -126,13 +164,16 @@ describe('fileio', function()
command('write')
-- Backup filename = fullpath, separators replaced with "%".
- local backup_file_name = string.gsub(currentdir()..'/Xtest_startup_file1',
- is_os('win') and '[:/\\]' or '/', '%%') .. '~'
- local foo_contents = trim(read_file('Xtest_backupdir/'..backup_file_name))
+ local backup_file_name = string.gsub(
+ currentdir() .. '/Xtest_startup_file1',
+ is_os('win') and '[:/\\]' or '/',
+ '%%'
+ ) .. '~'
+ local foo_contents = trim(read_file('Xtest_backupdir/' .. backup_file_name))
local foobar_contents = trim(read_file('Xtest_startup_file1'))
- eq('foobar', foobar_contents);
- eq('foo', foo_contents);
+ eq('foobar', foobar_contents)
+ eq('foo', foo_contents)
end)
it('backup with full path with spaces', function()
@@ -148,13 +189,16 @@ describe('fileio', function()
command('write')
-- Backup filename = fullpath, separators replaced with "%".
- local backup_file_name = string.gsub(currentdir()..'/Xtest_startup_file1',
- is_os('win') and '[:/\\]' or '/', '%%') .. '~'
- local foo_contents = trim(read_file('Xtest_backupdir with spaces/'..backup_file_name))
+ local backup_file_name = string.gsub(
+ currentdir() .. '/Xtest_startup_file1',
+ is_os('win') and '[:/\\]' or '/',
+ '%%'
+ ) .. '~'
+ local foo_contents = trim(read_file('Xtest_backupdir with spaces/' .. backup_file_name))
local foobar_contents = trim(read_file('Xtest_startup_file1'))
- eq('foobar', foobar_contents);
- eq('foo', foo_contents);
+ eq('foobar', foobar_contents)
+ eq('foo', foo_contents)
end)
it('backup symlinked files #11349', function()
@@ -166,7 +210,7 @@ describe('fileio', function()
local backup_file_name = link_file_name .. '~'
write_file('Xtest_startup_file1', initial_content, false)
- luv.fs_symlink('Xtest_startup_file1', link_file_name)
+ uv.fs_symlink('Xtest_startup_file1', link_file_name)
command('set backup')
command('set backupcopy=yes')
command('edit ' .. link_file_name)
@@ -174,11 +218,10 @@ describe('fileio', function()
command('write')
local backup_raw = read_file(backup_file_name)
- neq(nil, backup_raw, "Expected backup file " .. backup_file_name .. "to exist but did not")
+ neq(nil, backup_raw, 'Expected backup file ' .. backup_file_name .. 'to exist but did not')
eq(initial_content, trim(backup_raw), 'Expected backup to contain original contents')
end)
-
it('backup symlinked files in first available backupdir #11349', function()
skip(is_ci('cirrus'))
clear()
@@ -190,7 +233,7 @@ describe('fileio', function()
local backup_file_name = backup_dir .. sep .. link_file_name .. '~'
write_file('Xtest_startup_file1', initial_content, false)
- luv.fs_symlink('Xtest_startup_file1', link_file_name)
+ uv.fs_symlink('Xtest_startup_file1', link_file_name)
mkdir(backup_dir)
command('set backup')
command('set backupcopy=yes')
@@ -200,7 +243,7 @@ describe('fileio', function()
command('write')
local backup_raw = read_file(backup_file_name)
- neq(nil, backup_raw, "Expected backup file " .. backup_file_name .. " to exist but did not")
+ neq(nil, backup_raw, 'Expected backup file ' .. backup_file_name .. ' to exist but did not')
eq(initial_content, trim(backup_raw), 'Expected backup to contain original contents')
end)
@@ -215,11 +258,11 @@ describe('fileio', function()
'',
}
local fname = 'Xtest_теÑÑ‚.md'
- funcs.writefile(text, fname, 's')
+ fn.writefile(text, fname, 's')
table.insert(text, '')
- eq(text, funcs.readfile(fname, 'b'))
+ eq(text, fn.readfile(fname, 'b'))
end)
- it('read invalid u8 over INT_MAX doesn\'t segfault', function()
+ it("read invalid u8 over INT_MAX doesn't segfault", function()
clear()
command('call writefile(0zFFFFFFFF, "Xtest-u8-int-max")')
-- This should not segfault
@@ -229,34 +272,32 @@ describe('fileio', function()
it(':w! does not show "file has been changed" warning', function()
clear()
- write_file("Xtest-overwrite-forced", 'foobar')
+ write_file('Xtest-overwrite-forced', 'foobar')
command('set nofixendofline')
- local screen = Screen.new(40,4)
+ local screen = Screen.new(40, 4)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4}
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
})
screen:attach()
- command("set shortmess-=F")
+ command('set shortmess-=F')
- command("e Xtest-overwrite-forced")
+ command('e Xtest-overwrite-forced')
screen:expect([[
^foobar |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
"Xtest-overwrite-forced" [noeol] 1L, 6B |
]])
-- Get current unix time.
- local cur_unix_time = os.time(os.date("!*t"))
+ local cur_unix_time = os.time(os.date('!*t'))
local future_time = cur_unix_time + 999999
-- Set the file's access/update time to be
-- greater than the time at which it was created.
- local uv = require("luv")
uv.fs_utime('Xtest-overwrite-forced', future_time, future_time)
-- use async feed_command because nvim basically hangs on the prompt
- feed_command("w")
+ feed_command('w')
screen:expect([[
{2:WARNING: The file has been changed since}|
{2: reading it!!!} |
@@ -264,20 +305,18 @@ describe('fileio', function()
^ |
]])
- feed("n")
- feed("<cr>")
+ feed('n')
+ feed('<cr>')
screen:expect([[
^foobar |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
-- Use a screen test because the warning does not set v:errmsg.
- command("w!")
+ command('w!')
screen:expect([[
^foobar |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
<erwrite-forced" [noeol] 1L, 6B written |
]])
end)
@@ -302,13 +341,13 @@ describe('tmpdir', function()
-- Tempfiles typically look like: "…/nvim.<user>/xxx/0".
-- - "…/nvim.<user>/xxx/" is the per-process tmpdir, not shared with other Nvims.
-- - "…/nvim.<user>/" is the tmpdir root, shared by all Nvims (normally).
- local tmproot = (funcs.tempname()):match(tmproot_pat)
+ local tmproot = (fn.tempname()):match(tmproot_pat)
ok(tmproot:len() > 4, 'tmproot like "nvim.foo"', tmproot)
return tmproot
end
it('failure modes', function()
- clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=os_tmpdir, } })
+ clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } })
assert_nolog('tempdir is not a directory', testlog)
assert_nolog('tempdir has invalid permissions', testlog)
@@ -319,9 +358,9 @@ describe('tmpdir', function()
-- "…/nvim.<user>/" is not a directory:
expect_exit(command, ':qall!')
rmdir(tmproot)
- write_file(tmproot, '') -- Not a directory, vim_mktempdir() should skip it.
- clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=os_tmpdir, } })
- matches(tmproot_pat, funcs.stdpath('run')) -- Tickle vim_mktempdir().
+ write_file(tmproot, '') -- Not a directory, vim_mktempdir() should skip it.
+ clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } })
+ matches(tmproot_pat, fn.stdpath('run')) -- Tickle vim_mktempdir().
-- Assert that broken tmpdir root was handled.
assert_log('tempdir root not a directory', testlog, 100)
@@ -330,9 +369,9 @@ describe('tmpdir', function()
os.remove(testlog)
os.remove(tmproot)
mkdir(tmproot)
- funcs.setfperm(tmproot, 'rwxr--r--') -- Invalid permissions, vim_mktempdir() should skip it.
- clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=os_tmpdir, } })
- matches(tmproot_pat, funcs.stdpath('run')) -- Tickle vim_mktempdir().
+ fn.setfperm(tmproot, 'rwxr--r--') -- Invalid permissions, vim_mktempdir() should skip it.
+ clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } })
+ matches(tmproot_pat, fn.stdpath('run')) -- Tickle vim_mktempdir().
-- Assert that broken tmpdir root was handled.
assert_log('tempdir root has invalid permissions', testlog, 100)
end)
@@ -340,53 +379,54 @@ describe('tmpdir', function()
it('too long', function()
local bigname = ('%s/%s'):format(os_tmpdir, ('x'):rep(666))
mkdir(bigname)
- clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=bigname, } })
- matches(tmproot_pat, funcs.stdpath('run')) -- Tickle vim_mktempdir().
- local len = (funcs.tempname()):len()
+ clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = bigname } })
+ matches(tmproot_pat, fn.stdpath('run')) -- Tickle vim_mktempdir().
+ local len = (fn.tempname()):len()
ok(len > 4 and len < 256, '4 < len < 256', tostring(len))
end)
it('disappeared #1432', function()
- clear({ env={ NVIM_LOG_FILE=testlog, TMPDIR=os_tmpdir, } })
+ clear({ env = { NVIM_LOG_FILE = testlog, TMPDIR = os_tmpdir } })
assert_nolog('tempdir disappeared', testlog)
local function rm_tmpdir()
- local tmpname1 = funcs.tempname()
- local tmpdir1 = funcs.fnamemodify(tmpname1, ':h')
- eq(funcs.stdpath('run'), tmpdir1)
+ local tmpname1 = fn.tempname()
+ local tmpdir1 = fn.fnamemodify(tmpname1, ':h')
+ eq(fn.stdpath('run'), tmpdir1)
rmdir(tmpdir1)
retry(nil, 1000, function()
- eq(0, funcs.isdirectory(tmpdir1))
+ eq(0, fn.isdirectory(tmpdir1))
end)
- local tmpname2 = funcs.tempname()
- local tmpdir2 = funcs.fnamemodify(tmpname2, ':h')
+ local tmpname2 = fn.tempname()
+ local tmpdir2 = fn.fnamemodify(tmpname2, ':h')
neq(tmpdir1, tmpdir2)
end
-- Your antivirus hates you...
rm_tmpdir()
assert_log('tempdir disappeared', testlog, 100)
- funcs.tempname()
- funcs.tempname()
- funcs.tempname()
- eq('', meths.get_vvar('errmsg'))
+ fn.tempname()
+ fn.tempname()
+ fn.tempname()
+ eq('', api.nvim_get_vvar('errmsg'))
rm_tmpdir()
- funcs.tempname()
- funcs.tempname()
- funcs.tempname()
- eq('E5431: tempdir disappeared (2 times)', meths.get_vvar('errmsg'))
+ fn.tempname()
+ fn.tempname()
+ fn.tempname()
+ eq('E5431: tempdir disappeared (2 times)', api.nvim_get_vvar('errmsg'))
rm_tmpdir()
- eq('E5431: tempdir disappeared (3 times)', meths.get_vvar('errmsg'))
+ eq('E5431: tempdir disappeared (3 times)', api.nvim_get_vvar('errmsg'))
end)
it('$NVIM_APPNAME relative path', function()
- clear({ env={
- NVIM_APPNAME='a/b',
- NVIM_LOG_FILE=testlog,
- TMPDIR=os_tmpdir,
- } })
- matches([=[.*[/\\]a%%b%.[^/\\]+]=], funcs.tempname())
+ clear({
+ env = {
+ NVIM_APPNAME = 'a/b',
+ NVIM_LOG_FILE = testlog,
+ TMPDIR = os_tmpdir,
+ },
+ })
+ matches([=[.*[/\\]a%%b%.[^/\\]+]=], fn.tempname())
end)
-
end)
diff --git a/test/functional/core/job_spec.lua b/test/functional/core/job_spec.lua
index 038368c387..13f5f9a5e1 100644
--- a/test/functional/core/job_spec.lua
+++ b/test/functional/core/job_spec.lua
@@ -1,17 +1,28 @@
local helpers = require('test.functional.helpers')(after_each)
-local clear, eq, eval, exc_exec, feed_command, feed, insert, neq, next_msg, nvim,
- testprg, ok, source, write_file, mkdir, rmdir = helpers.clear,
- helpers.eq, helpers.eval, helpers.exc_exec, helpers.feed_command, helpers.feed,
- helpers.insert, helpers.neq, helpers.next_msg, helpers.nvim,
- helpers.testprg, helpers.ok, helpers.source,
- helpers.write_file, helpers.mkdir, helpers.rmdir
+local thelpers = require('test.functional.terminal.helpers')
+
+local clear = helpers.clear
+local eq = helpers.eq
+local eval = helpers.eval
+local exc_exec = helpers.exc_exec
+local feed_command = helpers.feed_command
+local feed = helpers.feed
+local insert = helpers.insert
+local neq = helpers.neq
+local next_msg = helpers.next_msg
+local testprg = helpers.testprg
+local ok = helpers.ok
+local source = helpers.source
+local write_file = helpers.write_file
+local mkdir = helpers.mkdir
+local rmdir = helpers.rmdir
local assert_alive = helpers.assert_alive
local command = helpers.command
-local funcs = helpers.funcs
+local fn = helpers.fn
local os_kill = helpers.os_kill
local retry = helpers.retry
-local meths = helpers.meths
-local NIL = helpers.NIL
+local api = helpers.api
+local NIL = vim.NIL
local poke_eventloop = helpers.poke_eventloop
local get_pathsep = helpers.get_pathsep
local pathroot = helpers.pathroot
@@ -31,8 +42,8 @@ describe('jobs', function()
before_each(function()
clear()
- channel = nvim('get_api_info')[1]
- nvim('set_var', 'channel', channel)
+ channel = api.nvim_get_chan_info(0).id
+ api.nvim_set_var('channel', channel)
source([[
function! Normalize(data) abort
" Windows: remove ^M and term escape sequences
@@ -54,66 +65,60 @@ describe('jobs', function()
end)
it('must specify env option as a dict', function()
- command("let g:job_opts.env = v:true")
+ command('let g:job_opts.env = v:true')
local _, err = pcall(function()
if is_os('win') then
- nvim('command', "let j = jobstart('set', g:job_opts)")
+ command("let j = jobstart('set', g:job_opts)")
else
- nvim('command', "let j = jobstart('env', g:job_opts)")
+ command("let j = jobstart('env', g:job_opts)")
end
end)
- ok(string.find(err, "E475: Invalid argument: env") ~= nil)
+ ok(string.find(err, 'E475: Invalid argument: env') ~= nil)
end)
it('append environment #env', function()
- nvim('command', "let $VAR = 'abc'")
- nvim('command', "let $TOTO = 'goodbye world'")
- nvim('command', "let g:job_opts.env = {'TOTO': 'hello world'}")
+ command("let $VAR = 'abc'")
+ command("let $TOTO = 'goodbye world'")
+ command("let g:job_opts.env = {'TOTO': 'hello world'}")
if is_os('win') then
- nvim('command', [[call jobstart('echo %TOTO% %VAR%', g:job_opts)]])
+ command([[call jobstart('echo %TOTO% %VAR%', g:job_opts)]])
else
- nvim('command', [[call jobstart('echo $TOTO $VAR', g:job_opts)]])
+ command([[call jobstart('echo $TOTO $VAR', g:job_opts)]])
end
- expect_msg_seq(
- {
- {'notification', 'stdout', {0, {'hello world abc'}}},
- {'notification', 'stdout', {0, {'', ''}}},
- },
- {
- {'notification', 'stdout', {0, {'hello world abc', ''}}},
- {'notification', 'stdout', {0, {''}}}
- }
- )
+ expect_msg_seq({
+ { 'notification', 'stdout', { 0, { 'hello world abc' } } },
+ { 'notification', 'stdout', { 0, { '', '' } } },
+ }, {
+ { 'notification', 'stdout', { 0, { 'hello world abc', '' } } },
+ { 'notification', 'stdout', { 0, { '' } } },
+ })
end)
it('append environment with pty #env', function()
- nvim('command', "let $VAR = 'abc'")
- nvim('command', "let $TOTO = 'goodbye world'")
- nvim('command', "let g:job_opts.pty = v:true")
- nvim('command', "let g:job_opts.env = {'TOTO': 'hello world'}")
+ command("let $VAR = 'abc'")
+ command("let $TOTO = 'goodbye world'")
+ command('let g:job_opts.pty = v:true')
+ command("let g:job_opts.env = {'TOTO': 'hello world'}")
if is_os('win') then
- nvim('command', [[call jobstart('echo %TOTO% %VAR%', g:job_opts)]])
+ command([[call jobstart('echo %TOTO% %VAR%', g:job_opts)]])
else
- nvim('command', [[call jobstart('echo $TOTO $VAR', g:job_opts)]])
+ command([[call jobstart('echo $TOTO $VAR', g:job_opts)]])
end
- expect_msg_seq(
- {
- {'notification', 'stdout', {0, {'hello world abc'}}},
- {'notification', 'stdout', {0, {'', ''}}},
- },
- {
- {'notification', 'stdout', {0, {'hello world abc', ''}}},
- {'notification', 'stdout', {0, {''}}}
- }
- )
+ expect_msg_seq({
+ { 'notification', 'stdout', { 0, { 'hello world abc' } } },
+ { 'notification', 'stdout', { 0, { '', '' } } },
+ }, {
+ { 'notification', 'stdout', { 0, { 'hello world abc', '' } } },
+ { 'notification', 'stdout', { 0, { '' } } },
+ })
end)
it('replace environment #env', function()
- nvim('command', "let $VAR = 'abc'")
- nvim('command', "let $TOTO = 'goodbye world'")
- nvim('command', "let g:job_opts.env = {'TOTO': 'hello world'}")
- nvim('command', "let g:job_opts.clear_env = 1")
+ command("let $VAR = 'abc'")
+ command("let $TOTO = 'goodbye world'")
+ command("let g:job_opts.env = {'TOTO': 'hello world'}")
+ command('let g:job_opts.clear_env = 1')
-- libuv ensures that certain "required" environment variables are
-- preserved if the user doesn't provide them in a custom environment
@@ -123,39 +128,39 @@ describe('jobs', function()
-- Rather than expecting a completely empty environment, ensure that $VAR
-- is *not* in the environment but $TOTO is.
if is_os('win') then
- nvim('command', [[call jobstart('echo %TOTO% %VAR%', g:job_opts)]])
+ command([[call jobstart('echo %TOTO% %VAR%', g:job_opts)]])
expect_msg_seq({
- {'notification', 'stdout', {0, {'hello world %VAR%', ''}}}
+ { 'notification', 'stdout', { 0, { 'hello world %VAR%', '' } } },
})
else
- nvim('command', "set shell=/bin/sh")
- nvim('command', [[call jobstart('echo $TOTO $VAR', g:job_opts)]])
+ command('set shell=/bin/sh')
+ command([[call jobstart('echo $TOTO $VAR', g:job_opts)]])
expect_msg_seq({
- {'notification', 'stdout', {0, {'hello world', ''}}}
+ { 'notification', 'stdout', { 0, { 'hello world', '' } } },
})
end
end)
it('handles case-insensitively matching #env vars', function()
- nvim('command', "let $TOTO = 'abc'")
+ command("let $TOTO = 'abc'")
-- Since $Toto is being set in the job, it should take precedence over the
-- global $TOTO on Windows
- nvim('command', "let g:job_opts = {'env': {'Toto': 'def'}, 'stdout_buffered': v:true}")
+ command("let g:job_opts = {'env': {'Toto': 'def'}, 'stdout_buffered': v:true}")
if is_os('win') then
- nvim('command', [[let j = jobstart('set | find /I "toto="', g:job_opts)]])
+ command([[let j = jobstart('set | find /I "toto="', g:job_opts)]])
else
- nvim('command', [[let j = jobstart('env | grep -i toto=', g:job_opts)]])
+ command([[let j = jobstart('env | grep -i toto=', g:job_opts)]])
end
- nvim('command', "call jobwait([j])")
- nvim('command', "let g:output = Normalize(g:job_opts.stdout)")
+ command('call jobwait([j])')
+ command('let g:output = Normalize(g:job_opts.stdout)')
local actual = eval('g:output')
local expected
if is_os('win') then
-- Toto is normalized to TOTO so we can detect duplicates, and because
-- Windows doesn't care about case
- expected = {'TOTO=def', ''}
+ expected = { 'TOTO=def', '' }
else
- expected = {'TOTO=abc', 'Toto=def', ''}
+ expected = { 'TOTO=abc', 'Toto=def', '' }
end
table.sort(actual)
table.sort(expected)
@@ -163,49 +168,50 @@ describe('jobs', function()
end)
it('uses &shell and &shellcmdflag if passed a string', function()
- nvim('command', "let $VAR = 'abc'")
+ command("let $VAR = 'abc'")
if is_os('win') then
- nvim('command', "let j = jobstart('echo %VAR%', g:job_opts)")
+ command("let j = jobstart('echo %VAR%', g:job_opts)")
else
- nvim('command', "let j = jobstart('echo $VAR', g:job_opts)")
+ command("let j = jobstart('echo $VAR', g:job_opts)")
end
- eq({'notification', 'stdout', {0, {'abc', ''}}}, next_msg())
- eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 0}}, next_msg())
+ eq({ 'notification', 'stdout', { 0, { 'abc', '' } } }, next_msg())
+ eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { 0, 0 } }, next_msg())
end)
it('changes to given / directory', function()
- nvim('command', "let g:job_opts.cwd = '/'")
+ command("let g:job_opts.cwd = '/'")
if is_os('win') then
- nvim('command', "let j = jobstart('cd', g:job_opts)")
+ command("let j = jobstart('cd', g:job_opts)")
else
- nvim('command', "let j = jobstart('pwd', g:job_opts)")
+ command("let j = jobstart('pwd', g:job_opts)")
end
- eq({'notification', 'stdout',
- {0, {pathroot(), ''}}}, next_msg())
- eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 0}}, next_msg())
+ eq({ 'notification', 'stdout', { 0, { pathroot(), '' } } }, next_msg())
+ eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { 0, 0 } }, next_msg())
end)
it('changes to given `cwd` directory', function()
- local dir = eval("resolve(tempname())"):gsub("/", get_pathsep())
+ local dir = eval('resolve(tempname())'):gsub('/', get_pathsep())
mkdir(dir)
- nvim('command', "let g:job_opts.cwd = '" .. dir .. "'")
+ command("let g:job_opts.cwd = '" .. dir .. "'")
if is_os('win') then
- nvim('command', "let j = jobstart('cd', g:job_opts)")
+ command("let j = jobstart('cd', g:job_opts)")
else
- nvim('command', "let j = jobstart('pwd', g:job_opts)")
+ command("let j = jobstart('pwd', g:job_opts)")
end
expect_msg_seq(
- { {'notification', 'stdout', {0, {dir, ''} } },
- {'notification', 'stdout', {0, {''} } },
- {'notification', 'exit', {0, 0} }
+ {
+ { 'notification', 'stdout', { 0, { dir, '' } } },
+ { 'notification', 'stdout', { 0, { '' } } },
+ { 'notification', 'exit', { 0, 0 } },
},
-- Alternative sequence:
- { {'notification', 'stdout', {0, {dir} } },
- {'notification', 'stdout', {0, {'', ''} } },
- {'notification', 'stdout', {0, {''} } },
- {'notification', 'exit', {0, 0} }
+ {
+ { 'notification', 'stdout', { 0, { dir } } },
+ { 'notification', 'stdout', { 0, { '', '' } } },
+ { 'notification', 'stdout', { 0, { '' } } },
+ { 'notification', 'exit', { 0, 0 } },
}
)
rmdir(dir)
@@ -214,14 +220,14 @@ describe('jobs', function()
it('fails to change to invalid `cwd`', function()
local dir = eval('resolve(tempname())."-bogus"')
local _, err = pcall(function()
- nvim('command', "let g:job_opts.cwd = '" .. dir .. "'")
+ command("let g:job_opts.cwd = '" .. dir .. "'")
if is_os('win') then
- nvim('command', "let j = jobstart('cd', g:job_opts)")
+ command("let j = jobstart('cd', g:job_opts)")
else
- nvim('command', "let j = jobstart('pwd', g:job_opts)")
+ command("let j = jobstart('pwd', g:job_opts)")
end
end)
- ok(string.find(err, "E475: Invalid argument: expected valid directory$") ~= nil)
+ ok(string.find(err, 'E475: Invalid argument: expected valid directory$') ~= nil)
end)
it('error on non-executable `cwd`', function()
@@ -229,17 +235,19 @@ describe('jobs', function()
local dir = 'Xtest_not_executable_dir'
mkdir(dir)
- funcs.setfperm(dir, 'rw-------')
- matches('^Vim%(call%):E903: Process failed to start: permission denied: .*',
- pcall_err(nvim, 'command', "call jobstart(['pwd'], {'cwd': '"..dir.."'})"))
+ fn.setfperm(dir, 'rw-------')
+ matches(
+ '^Vim%(call%):E903: Process failed to start: permission denied: .*',
+ pcall_err(command, "call jobstart(['pwd'], {'cwd': '" .. dir .. "'})")
+ )
rmdir(dir)
end)
it('returns 0 when it fails to start', function()
- eq("", eval("v:errmsg"))
- feed_command("let g:test_jobid = jobstart([])")
- eq(0, eval("g:test_jobid"))
- eq("E474:", string.match(eval("v:errmsg"), "E%d*:"))
+ eq('', eval('v:errmsg'))
+ feed_command('let g:test_jobid = jobstart([])')
+ eq(0, eval('g:test_jobid'))
+ eq('E474:', string.match(eval('v:errmsg'), 'E%d*:'))
end)
it('returns -1 when target is not executable #5465', function()
@@ -248,124 +256,131 @@ describe('jobs', function()
end
local executable_jobid = new_job()
- local exe = is_os('win') and './test/functional/fixtures' or './test/functional/fixtures/non_executable.txt'
- eq("Vim:E475: Invalid value for argument cmd: '"..exe.."' is not executable",
- pcall_err(eval, "jobstart(['"..exe.."'])"))
- eq("", eval("v:errmsg"))
+ local exe = is_os('win') and './test/functional/fixtures'
+ or './test/functional/fixtures/non_executable.txt'
+ eq(
+ "Vim:E475: Invalid value for argument cmd: '" .. exe .. "' is not executable",
+ pcall_err(eval, "jobstart(['" .. exe .. "'])")
+ )
+ eq('', eval('v:errmsg'))
-- Non-executable job should not increment the job ids. #5465
eq(executable_jobid + 1, new_job())
end)
it('invokes callbacks when the job writes and exits', function()
- nvim('command', "let g:job_opts.on_stderr = function('OnEvent')")
- nvim('command', [[call jobstart(has('win32') ? 'echo:' : 'echo', g:job_opts)]])
- expect_twostreams({{'notification', 'stdout', {0, {'', ''}}},
- {'notification', 'stdout', {0, {''}}}},
- {{'notification', 'stderr', {0, {''}}}})
- eq({'notification', 'exit', {0, 0}}, next_msg())
+ command("let g:job_opts.on_stderr = function('OnEvent')")
+ command([[call jobstart(has('win32') ? 'echo:' : 'echo', g:job_opts)]])
+ expect_twostreams({
+ { 'notification', 'stdout', { 0, { '', '' } } },
+ { 'notification', 'stdout', { 0, { '' } } },
+ }, { { 'notification', 'stderr', { 0, { '' } } } })
+ eq({ 'notification', 'exit', { 0, 0 } }, next_msg())
end)
it('interactive commands', function()
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
neq(0, eval('j'))
- nvim('command', 'call jobsend(j, "abc\\n")')
- eq({'notification', 'stdout', {0, {'abc', ''}}}, next_msg())
- nvim('command', 'call jobsend(j, "123\\nxyz\\n")')
+ command('call jobsend(j, "abc\\n")')
+ eq({ 'notification', 'stdout', { 0, { 'abc', '' } } }, next_msg())
+ command('call jobsend(j, "123\\nxyz\\n")')
expect_msg_seq(
- { {'notification', 'stdout', {0, {'123', 'xyz', ''}}}
- },
+ { { 'notification', 'stdout', { 0, { '123', 'xyz', '' } } } },
-- Alternative sequence:
- { {'notification', 'stdout', {0, {'123', ''}}},
- {'notification', 'stdout', {0, {'xyz', ''}}}
+ {
+ { 'notification', 'stdout', { 0, { '123', '' } } },
+ { 'notification', 'stdout', { 0, { 'xyz', '' } } },
}
)
- nvim('command', 'call jobsend(j, [123, "xyz", ""])')
+ command('call jobsend(j, [123, "xyz", ""])')
expect_msg_seq(
- { {'notification', 'stdout', {0, {'123', 'xyz', ''}}}
- },
+ { { 'notification', 'stdout', { 0, { '123', 'xyz', '' } } } },
-- Alternative sequence:
- { {'notification', 'stdout', {0, {'123', ''}}},
- {'notification', 'stdout', {0, {'xyz', ''}}}
+ {
+ { 'notification', 'stdout', { 0, { '123', '' } } },
+ { 'notification', 'stdout', { 0, { 'xyz', '' } } },
}
)
- nvim('command', "call jobstop(j)")
- eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 143}}, next_msg())
+ command('call jobstop(j)')
+ eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { 0, 143 } }, next_msg())
end)
it('preserves NULs', function()
-- Make a file with NULs in it.
local filename = helpers.tmpname()
- write_file(filename, "abc\0def\n")
+ write_file(filename, 'abc\0def\n')
- nvim('command', "let j = jobstart(['cat', '"..filename.."'], g:job_opts)")
- eq({'notification', 'stdout', {0, {'abc\ndef', ''}}}, next_msg())
- eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 0}}, next_msg())
+ command("let j = jobstart(['cat', '" .. filename .. "'], g:job_opts)")
+ eq({ 'notification', 'stdout', { 0, { 'abc\ndef', '' } } }, next_msg())
+ eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { 0, 0 } }, next_msg())
os.remove(filename)
-- jobsend() preserves NULs.
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
- nvim('command', [[call jobsend(j, ["123\n456",""])]])
- eq({'notification', 'stdout', {0, {'123\n456', ''}}}, next_msg())
- nvim('command', "call jobstop(j)")
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
+ command([[call jobsend(j, ["123\n456",""])]])
+ eq({ 'notification', 'stdout', { 0, { '123\n456', '' } } }, next_msg())
+ command('call jobstop(j)')
end)
- it("emits partial lines (does NOT buffer data lacking newlines)", function()
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
- nvim('command', 'call jobsend(j, "abc\\nxyz")')
- eq({'notification', 'stdout', {0, {'abc', 'xyz'}}}, next_msg())
- nvim('command', "call jobstop(j)")
- eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 143}}, next_msg())
+ it('emits partial lines (does NOT buffer data lacking newlines)', function()
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
+ command('call jobsend(j, "abc\\nxyz")')
+ eq({ 'notification', 'stdout', { 0, { 'abc', 'xyz' } } }, next_msg())
+ command('call jobstop(j)')
+ eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { 0, 143 } }, next_msg())
end)
it('preserves newlines', function()
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
- nvim('command', 'call jobsend(j, "a\\n\\nc\\n\\n\\n\\nb\\n\\n")')
- eq({'notification', 'stdout',
- {0, {'a', '', 'c', '', '', '', 'b', '', ''}}}, next_msg())
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
+ command('call jobsend(j, "a\\n\\nc\\n\\n\\n\\nb\\n\\n")')
+ eq({ 'notification', 'stdout', { 0, { 'a', '', 'c', '', '', '', 'b', '', '' } } }, next_msg())
end)
it('preserves NULs', function()
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
- nvim('command', 'call jobsend(j, ["\n123\n", "abc\\nxyz\n", ""])')
- eq({'notification', 'stdout', {0, {'\n123\n', 'abc\nxyz\n', ''}}},
- next_msg())
- nvim('command', "call jobstop(j)")
- eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 143}}, next_msg())
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
+ command('call jobsend(j, ["\n123\n", "abc\\nxyz\n", ""])')
+ eq({ 'notification', 'stdout', { 0, { '\n123\n', 'abc\nxyz\n', '' } } }, next_msg())
+ command('call jobstop(j)')
+ eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { 0, 143 } }, next_msg())
end)
it('avoids sending final newline', function()
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
- nvim('command', 'call jobsend(j, ["some data", "without\nfinal nl"])')
- eq({'notification', 'stdout', {0, {'some data', 'without\nfinal nl'}}},
- next_msg())
- nvim('command', "call jobstop(j)")
- eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 143}}, next_msg())
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
+ command('call jobsend(j, ["some data", "without\nfinal nl"])')
+ eq({ 'notification', 'stdout', { 0, { 'some data', 'without\nfinal nl' } } }, next_msg())
+ command('call jobstop(j)')
+ eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { 0, 143 } }, next_msg())
end)
it('closes the job streams with jobclose', function()
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
- nvim('command', 'call jobclose(j, "stdin")')
- eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 0}}, next_msg())
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
+ command('call jobclose(j, "stdin")')
+ eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { 0, 0 } }, next_msg())
end)
- it("disallows jobsend on a job that closed stdin", function()
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
- nvim('command', 'call jobclose(j, "stdin")')
- eq(false, pcall(function()
- nvim('command', 'call jobsend(j, ["some data"])')
- end))
+ it('disallows jobsend on a job that closed stdin', function()
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
+ command('call jobclose(j, "stdin")')
+ eq(
+ false,
+ pcall(function()
+ command('call jobsend(j, ["some data"])')
+ end)
+ )
command("let g:job_opts.stdin = 'null'")
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
- eq(false, pcall(function()
- nvim('command', 'call jobsend(j, ["some data"])')
- end))
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
+ eq(
+ false,
+ pcall(function()
+ command('call jobsend(j, ["some data"])')
+ end)
+ )
end)
it('disallows jobsend on a non-existent job', function()
@@ -374,91 +389,99 @@ describe('jobs', function()
end)
it('jobstop twice on the stopped or exited job return 0', function()
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
neq(0, eval('j'))
- eq(1, eval("jobstop(j)"))
- eq(0, eval("jobstop(j)"))
+ eq(1, eval('jobstop(j)'))
+ eq(0, eval('jobstop(j)'))
end)
it('will not leak memory if we leave a job running', function()
- nvim('command', "call jobstart(['cat', '-'], g:job_opts)")
+ command("call jobstart(['cat', '-'], g:job_opts)")
end)
it('can get the pid value using getpid', function()
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
local pid = eval('jobpid(j)')
- neq(NIL, meths.get_proc(pid))
- nvim('command', 'call jobstop(j)')
- eq({'notification', 'stdout', {0, {''}}}, next_msg())
- eq({'notification', 'exit', {0, 143}}, next_msg())
- eq(NIL, meths.get_proc(pid))
+ neq(NIL, api.nvim_get_proc(pid))
+ command('call jobstop(j)')
+ eq({ 'notification', 'stdout', { 0, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { 0, 143 } }, next_msg())
+ eq(NIL, api.nvim_get_proc(pid))
end)
- it("disposed on Nvim exit", function()
+ it('disposed on Nvim exit', function()
-- use sleep, which doesn't die on stdin close
- nvim('command', "let g:j = jobstart(has('win32') ? ['ping', '-n', '1001', '127.0.0.1'] : ['sleep', '1000'], g:job_opts)")
+ command(
+ "let g:j = jobstart(has('win32') ? ['ping', '-n', '1001', '127.0.0.1'] : ['sleep', '1000'], g:job_opts)"
+ )
local pid = eval('jobpid(g:j)')
- neq(NIL, meths.get_proc(pid))
+ neq(NIL, api.nvim_get_proc(pid))
clear()
- eq(NIL, meths.get_proc(pid))
+ eq(NIL, api.nvim_get_proc(pid))
end)
it('can survive the exit of nvim with "detach"', function()
- nvim('command', 'let g:job_opts.detach = 1')
- nvim('command', "let g:j = jobstart(has('win32') ? ['ping', '-n', '1001', '127.0.0.1'] : ['sleep', '1000'], g:job_opts)")
+ command('let g:job_opts.detach = 1')
+ command(
+ "let g:j = jobstart(has('win32') ? ['ping', '-n', '1001', '127.0.0.1'] : ['sleep', '1000'], g:job_opts)"
+ )
local pid = eval('jobpid(g:j)')
- neq(NIL, meths.get_proc(pid))
+ neq(NIL, api.nvim_get_proc(pid))
clear()
- neq(NIL, meths.get_proc(pid))
+ neq(NIL, api.nvim_get_proc(pid))
-- clean up after ourselves
eq(0, os_kill(pid))
end)
it('can pass user data to the callback', function()
- nvim('command', 'let g:job_opts.user = {"n": 5, "s": "str", "l": [1]}')
- nvim('command', [[call jobstart('echo foo', g:job_opts)]])
- local data = {n = 5, s = 'str', l = {1}}
+ command('let g:job_opts.user = {"n": 5, "s": "str", "l": [1]}')
+ command([[call jobstart('echo foo', g:job_opts)]])
+ local data = { n = 5, s = 'str', l = { 1 } }
expect_msg_seq(
- { {'notification', 'stdout', {data, {'foo', ''}}},
- {'notification', 'stdout', {data, {''}}},
+ {
+ { 'notification', 'stdout', { data, { 'foo', '' } } },
+ { 'notification', 'stdout', { data, { '' } } },
},
-- Alternative sequence:
- { {'notification', 'stdout', {data, {'foo'}}},
- {'notification', 'stdout', {data, {'', ''}}},
- {'notification', 'stdout', {data, {''}}},
+ {
+ { 'notification', 'stdout', { data, { 'foo' } } },
+ { 'notification', 'stdout', { data, { '', '' } } },
+ { 'notification', 'stdout', { data, { '' } } },
}
)
- eq({'notification', 'exit', {data, 0}}, next_msg())
+ eq({ 'notification', 'exit', { data, 0 } }, next_msg())
end)
it('can omit data callbacks', function()
- nvim('command', 'unlet g:job_opts.on_stdout')
- nvim('command', 'let g:job_opts.user = 5')
- nvim('command', [[call jobstart('echo foo', g:job_opts)]])
- eq({'notification', 'exit', {5, 0}}, next_msg())
+ command('unlet g:job_opts.on_stdout')
+ command('let g:job_opts.user = 5')
+ command([[call jobstart('echo foo', g:job_opts)]])
+ eq({ 'notification', 'exit', { 5, 0 } }, next_msg())
end)
it('can omit exit callback', function()
- nvim('command', 'unlet g:job_opts.on_exit')
- nvim('command', 'let g:job_opts.user = 5')
- nvim('command', [[call jobstart('echo foo', g:job_opts)]])
+ command('unlet g:job_opts.on_exit')
+ command('let g:job_opts.user = 5')
+ command([[call jobstart('echo foo', g:job_opts)]])
expect_msg_seq(
- { {'notification', 'stdout', {5, {'foo', ''} } },
- {'notification', 'stdout', {5, {''} } },
+ {
+ { 'notification', 'stdout', { 5, { 'foo', '' } } },
+ { 'notification', 'stdout', { 5, { '' } } },
},
-- Alternative sequence:
- { {'notification', 'stdout', {5, {'foo'} } },
- {'notification', 'stdout', {5, {'', ''} } },
- {'notification', 'stdout', {5, {''} } },
+ {
+ { 'notification', 'stdout', { 5, { 'foo' } } },
+ { 'notification', 'stdout', { 5, { '', '' } } },
+ { 'notification', 'stdout', { 5, { '' } } },
}
)
end)
it('will pass return code with the exit event', function()
- nvim('command', 'let g:job_opts.user = 5')
- nvim('command', "call jobstart('exit 55', g:job_opts)")
- eq({'notification', 'stdout', {5, {''}}}, next_msg())
- eq({'notification', 'exit', {5, 55}}, next_msg())
+ command('let g:job_opts.user = 5')
+ command("call jobstart('exit 55', g:job_opts)")
+ eq({ 'notification', 'stdout', { 5, { '' } } }, next_msg())
+ eq({ 'notification', 'exit', { 5, 55 } }, next_msg())
end)
it('can receive dictionary functions', function()
@@ -469,14 +492,14 @@ describe('jobs', function()
endfunction
call jobstart('exit 45', g:dict)
]])
- eq({'notification', 'exit', {45, 10}}, next_msg())
+ eq({ 'notification', 'exit', { 45, 10 } }, next_msg())
end)
it('can redefine callbacks being used by a job', function()
local screen = Screen.new()
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold=true, foreground=Screen.colors.Blue},
+ [1] = { bold = true, foreground = Screen.colors.Blue },
})
source([[
function! g:JobHandler(job_id, data, event)
@@ -495,16 +518,16 @@ describe('jobs', function()
endfunction
]])
- eq("", eval("v:errmsg"))
+ eq('', eval('v:errmsg'))
end)
it('requires funcrefs for script-local (s:) functions', function()
local screen = Screen.new(60, 5)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4}
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
})
-- Pass job callback names _without_ `function(...)`.
@@ -519,7 +542,7 @@ describe('jobs', function()
\ })
]])
- screen:expect{any="{2:E120: Using <SID> not in a script context: s:OnEvent}"}
+ screen:expect { any = '{2:E120: Using <SID> not in a script context: s:OnEvent}' }
end)
it('does not repeat output with slow output handlers', function()
@@ -542,22 +565,22 @@ describe('jobs', function()
call jobwait([g:id])
]])
- local expected = {'1', '2', '3', '4', '5', ''}
+ local expected = { '1', '2', '3', '4', '5', '' }
local chunks = eval('d.data')
-- check nothing was received after exit, including EOF
eq(eval('g:exit_data'), chunks)
- local received = {''}
+ local received = { '' }
for i, chunk in ipairs(chunks) do
if i < #chunks then
-- if chunks got joined, a spurious [''] callback was not sent
- neq({''}, chunk)
+ neq({ '' }, chunk)
else
-- but EOF callback is still sent
- eq({''}, chunk)
+ eq({ '' }, chunk)
end
- received[#received] = received[#received]..chunk[1]
+ received[#received] = received[#received] .. chunk[1]
for j = 2, #chunk do
- received[#received+1] = chunk[j]
+ received[#received + 1] = chunk[j]
end
end
eq(expected, received)
@@ -585,22 +608,22 @@ describe('jobs', function()
call jobwait([g:id])
]])
- local expected = {'1', '2', '3', '4', '5', ''}
+ local expected = { '1', '2', '3', '4', '5', '' }
local chunks = eval('d.data')
-- check nothing was received after exit, including EOF
eq(eval('g:exit_data'), chunks)
- local received = {''}
+ local received = { '' }
for i, chunk in ipairs(chunks) do
if i < #chunks then
-- if chunks got joined, a spurious [''] callback was not sent
- neq({''}, chunk)
+ neq({ '' }, chunk)
else
-- but EOF callback is still sent
- eq({''}, chunk)
+ eq({ '' }, chunk)
end
- received[#received] = received[#received]..chunk[1]
+ received[#received] = received[#received] .. chunk[1]
for j = 2, #chunk do
- received[#received+1] = chunk[j]
+ received[#received + 1] = chunk[j]
end
end
eq(expected, received)
@@ -618,11 +641,11 @@ describe('jobs', function()
call jobstart('echo some text', g:job_opts)
]])
expect_msg_seq(
- { {'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}},
- },
+ { { 'notification', '1', { 'foo', 'bar', { 'some text', '' }, 'stdout' } } },
-- Alternative sequence:
- { {'notification', '1', {'foo', 'bar', {'some text'}, 'stdout'}},
- {'notification', '1', {'foo', 'bar', {'', ''}, 'stdout'}},
+ {
+ { 'notification', '1', { 'foo', 'bar', { 'some text' }, 'stdout' } },
+ { 'notification', '1', { 'foo', 'bar', { '', '' }, 'stdout' } },
}
)
end)
@@ -638,11 +661,11 @@ describe('jobs', function()
call jobstart('echo some text', g:job_opts)
]])
expect_msg_seq(
- { {'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}},
- },
+ { { 'notification', '1', { 'foo', 'bar', { 'some text', '' }, 'stdout' } } },
-- Alternative sequence:
- { {'notification', '1', {'foo', 'bar', {'some text'}, 'stdout'}},
- {'notification', '1', {'foo', 'bar', {'', ''}, 'stdout'}},
+ {
+ { 'notification', '1', { 'foo', 'bar', { 'some text' }, 'stdout' } },
+ { 'notification', '1', { 'foo', 'bar', { '', '' }, 'stdout' } },
}
)
end)
@@ -653,18 +676,19 @@ describe('jobs', function()
call jobstart('echo some text', g:job_opts)
]])
expect_msg_seq(
- { {'notification', '1', {'foo', 'bar', {'some text', ''}, 'stdout'}},
- },
+ { { 'notification', '1', { 'foo', 'bar', { 'some text', '' }, 'stdout' } } },
-- Alternative sequence:
- { {'notification', '1', {'foo', 'bar', {'some text'}, 'stdout'}},
- {'notification', '1', {'foo', 'bar', {'', ''}, 'stdout'}},
+ {
+ { 'notification', '1', { 'foo', 'bar', { 'some text' }, 'stdout' } },
+ { 'notification', '1', { 'foo', 'bar', { '', '' }, 'stdout' } },
}
)
end)
it('jobstart() environment: $NVIM, $NVIM_LISTEN_ADDRESS #11009', function()
local function get_env_in_child_job(envname, env)
- return exec_lua([[
+ return exec_lua(
+ [[
local envname, env = ...
local join = function(s) return vim.fn.join(s, '') end
local stdout = {}
@@ -676,12 +700,13 @@ describe('jobs', function()
on_stderr = function(chan, data, name) stderr = data end,
on_stdout = function(chan, data, name) stdout = data end,
}
- local j1 = vim.fn.jobstart({ vim.v.progpath, '-es', '-V1',( '+echo "%s="..getenv("%s")'):format(envname, envname), '+qa!' }, opt)
+ local j1 = vim.fn.jobstart({ vim.v.progpath, '-es', '-V1',('+echo "%s="..getenv("%s")'):format(envname, envname), '+qa!' }, opt)
vim.fn.jobwait({ j1 }, 10000)
return join({ join(stdout), join(stderr) })
]],
- envname,
- env)
+ envname,
+ env
+ )
end
local addr = eval('v:servername')
@@ -689,14 +714,18 @@ describe('jobs', function()
-- $NVIM is _not_ defined in the top-level Nvim process.
eq('', eval('$NVIM'))
-- jobstart() shares its v:servername with the child via $NVIM.
- eq('NVIM='..addr, get_env_in_child_job('NVIM'))
+ eq('NVIM=' .. addr, get_env_in_child_job('NVIM'))
-- $NVIM_LISTEN_ADDRESS is unset by server_init in the child.
eq('NVIM_LISTEN_ADDRESS=v:null', get_env_in_child_job('NVIM_LISTEN_ADDRESS'))
- eq('NVIM_LISTEN_ADDRESS=v:null', get_env_in_child_job('NVIM_LISTEN_ADDRESS',
- { NVIM_LISTEN_ADDRESS='Xtest_jobstart_env' }))
+ eq(
+ 'NVIM_LISTEN_ADDRESS=v:null',
+ get_env_in_child_job('NVIM_LISTEN_ADDRESS', { NVIM_LISTEN_ADDRESS = 'Xtest_jobstart_env' })
+ )
-- User can explicitly set $NVIM_LOG_FILE, $VIM, $VIMRUNTIME.
- eq('NVIM_LOG_FILE=Xtest_jobstart_env',
- get_env_in_child_job('NVIM_LOG_FILE', { NVIM_LOG_FILE='Xtest_jobstart_env' }))
+ eq(
+ 'NVIM_LOG_FILE=Xtest_jobstart_env',
+ get_env_in_child_job('NVIM_LOG_FILE', { NVIM_LOG_FILE = 'Xtest_jobstart_env' })
+ )
os.remove('Xtest_jobstart_env')
end)
@@ -721,7 +750,7 @@ describe('jobs', function()
\ jobstart('sleep 0.310; exit 7')
\ ]))
]])
- eq({'notification', 'wait', {{4, 5, 6, 7}}}, next_msg())
+ eq({ 'notification', 'wait', { { 4, 5, 6, 7 } } }, next_msg())
end)
it('will run callbacks while waiting', function()
@@ -751,8 +780,7 @@ describe('jobs', function()
\ ])
call rpcnotify(g:channel, 'wait', sort(g:jobs), sort(g:exits))
]])
- eq({'notification', 'wait',
- {{3,4,5,6}, {3,4,5,6}}}, next_msg())
+ eq({ 'notification', 'wait', { { 3, 4, 5, 6 }, { 3, 4, 5, 6 } } }, next_msg())
end)
it('will return status codes in the order of passed ids', function()
@@ -769,7 +797,7 @@ describe('jobs', function()
\ jobstart('sleep 0.010; exit 7')
\ ]))
]])
- eq({'notification', 'wait', {{4, 5, 6, 7}}}, next_msg())
+ eq({ 'notification', 'wait', { { 4, 5, 6, 7 } } }, next_msg())
end)
it('will return -3 for invalid job ids', function()
@@ -779,29 +807,33 @@ describe('jobs', function()
\ jobstart((has('win32') ? 'Start-Sleep -Milliseconds 100' : 'sleep 0.01').'; exit 5'),
\ ]))
]])
- eq({'notification', 'wait', {{-3, 5}}}, next_msg())
+ eq({ 'notification', 'wait', { { -3, 5 } } }, next_msg())
end)
it('will return -2 when interrupted without timeout', function()
- feed_command('call rpcnotify(g:channel, "ready") | '..
- 'call rpcnotify(g:channel, "wait", '..
- 'jobwait([jobstart("'..
- (is_os('win') and 'Start-Sleep 10' or 'sleep 10')..
- '; exit 55")]))')
- eq({'notification', 'ready', {}}, next_msg())
+ feed_command(
+ 'call rpcnotify(g:channel, "ready") | '
+ .. 'call rpcnotify(g:channel, "wait", '
+ .. 'jobwait([jobstart("'
+ .. (is_os('win') and 'Start-Sleep 10' or 'sleep 10')
+ .. '; exit 55")]))'
+ )
+ eq({ 'notification', 'ready', {} }, next_msg())
feed('<c-c>')
- eq({'notification', 'wait', {{-2}}}, next_msg())
+ eq({ 'notification', 'wait', { { -2 } } }, next_msg())
end)
it('will return -2 when interrupted with timeout', function()
- feed_command('call rpcnotify(g:channel, "ready") | '..
- 'call rpcnotify(g:channel, "wait", '..
- 'jobwait([jobstart("'..
- (is_os('win') and 'Start-Sleep 10' or 'sleep 10')..
- '; exit 55")], 10000))')
- eq({'notification', 'ready', {}}, next_msg())
+ feed_command(
+ 'call rpcnotify(g:channel, "ready") | '
+ .. 'call rpcnotify(g:channel, "wait", '
+ .. 'jobwait([jobstart("'
+ .. (is_os('win') and 'Start-Sleep 10' or 'sleep 10')
+ .. '; exit 55")], 10000))'
+ )
+ eq({ 'notification', 'ready', {} }, next_msg())
feed('<c-c>')
- eq({'notification', 'wait', {{-2}}}, next_msg())
+ eq({ 'notification', 'wait', { { -2 } } }, next_msg())
end)
it('can be called recursively', function()
@@ -844,11 +876,11 @@ describe('jobs', function()
local r
for i = 10, 1, -1 do
r = next_msg()
- eq('job '..i..' closed', r[3][1])
+ eq('job ' .. i .. ' closed', r[3][1])
r = next_msg()
- eq('job '..i..' exited', r[3][1])
+ eq('job ' .. i .. ' exited', r[3][1])
end
- eq(10, nvim('eval', 'g:counter'))
+ eq(10, api.nvim_eval('g:counter'))
end)
describe('with timeout argument', function()
@@ -858,7 +890,7 @@ describe('jobs', function()
\ jobstart((has('win32') ? 'Start-Sleep 10' : 'sleep 10').'; exit 5'),
\ ], 100))
]])
- eq({'notification', 'wait', {{-1}}}, next_msg())
+ eq({ 'notification', 'wait', { { -1 } } }, next_msg())
end)
it('can pass 0 to check if a job exists', function()
@@ -871,16 +903,16 @@ describe('jobs', function()
\ jobstart('sleep 0.3; exit 5'),
\ ], 0))
]])
- eq({'notification', 'wait', {{-1, -1}}}, next_msg())
+ eq({ 'notification', 'wait', { { -1, -1 } } }, next_msg())
end)
end)
it('hides cursor and flushes messages before blocking', function()
local screen = Screen.new(50, 6)
screen:set_default_attr_ids({
- [0] = {foreground = Screen.colors.Blue, bold = true}; -- NonText
- [1] = {bold = true, reverse = true}; -- MsgSeparator
- [2] = {bold = true, foreground = Screen.colors.SeaGreen}; -- MoreMsg
+ [0] = { foreground = Screen.colors.Blue, bold = true }, -- NonText
+ [1] = { bold = true, reverse = true }, -- MsgSeparator
+ [2] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
})
screen:attach()
command([[let g:id = jobstart([v:progpath, '--clean', '--headless'])]])
@@ -892,56 +924,66 @@ describe('jobs', function()
endfunc
]])
feed_command('call PrintAndWait()')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1: }|
aaa |
bbb |
- ]], timeout=100}
- screen:expect{grid=[[
+ ]],
+ timeout = 100,
+ }
+ screen:expect {
+ grid = [[
|
{1: }|
aaa |
bbb |
ccc |
{2:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed('<CR>')
- funcs.jobstop(meths.get_var('id'))
+ fn.jobstop(api.nvim_get_var('id'))
end)
end)
pending('exit event follows stdout, stderr', function()
- nvim('command', "let g:job_opts.on_stderr = function('OnEvent')")
- nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)")
- nvim('eval', 'jobsend(j, "abcdef")')
- nvim('eval', 'jobstop(j)')
+ command("let g:job_opts.on_stderr = function('OnEvent')")
+ command("let j = jobstart(['cat', '-'], g:job_opts)")
+ api.nvim_eval('jobsend(j, "abcdef")')
+ api.nvim_eval('jobstop(j)')
expect_msg_seq(
- { {'notification', 'stdout', {0, {'abcdef'}}},
- {'notification', 'stdout', {0, {''}}},
- {'notification', 'stderr', {0, {''}}},
+ {
+ { 'notification', 'stdout', { 0, { 'abcdef' } } },
+ { 'notification', 'stdout', { 0, { '' } } },
+ { 'notification', 'stderr', { 0, { '' } } },
},
-- Alternative sequence:
- { {'notification', 'stderr', {0, {''}}},
- {'notification', 'stdout', {0, {'abcdef'}}},
- {'notification', 'stdout', {0, {''}}},
+ {
+ { 'notification', 'stderr', { 0, { '' } } },
+ { 'notification', 'stdout', { 0, { 'abcdef' } } },
+ { 'notification', 'stdout', { 0, { '' } } },
},
-- Alternative sequence:
- { {'notification', 'stdout', {0, {'abcdef'}}},
- {'notification', 'stderr', {0, {''}}},
- {'notification', 'stdout', {0, {''}}},
+ {
+ { 'notification', 'stdout', { 0, { 'abcdef' } } },
+ { 'notification', 'stderr', { 0, { '' } } },
+ { 'notification', 'stdout', { 0, { '' } } },
}
)
- eq({'notification', 'exit', {0, 143}}, next_msg())
+ eq({ 'notification', 'exit', { 0, 143 } }, next_msg())
end)
it('cannot have both rpc and pty options', function()
- command("let g:job_opts.pty = v:true")
- command("let g:job_opts.rpc = v:true")
+ command('let g:job_opts.pty = v:true')
+ command('let g:job_opts.rpc = v:true')
local _, err = pcall(command, "let j = jobstart(['cat', '-'], g:job_opts)")
- ok(string.find(err, "E475: Invalid argument: job cannot have both 'pty' and 'rpc' options set") ~= nil)
+ ok(
+ string.find(err, "E475: Invalid argument: job cannot have both 'pty' and 'rpc' options set")
+ ~= nil
+ )
end)
it('does not crash when repeatedly failing to start shell', function()
@@ -954,7 +996,7 @@ describe('jobs', function()
]])
-- The crash only triggered if both jobs are cleaned up on the same event
-- loop tick. This is also prevented by try-block, so feed must be used.
- feed_command("call DoIt()")
+ feed_command('call DoIt()')
feed('<cr>') -- press RETURN
assert_alive()
end)
@@ -991,7 +1033,7 @@ describe('jobs', function()
\ 'substitute(v:val, "\r", "", "")'),
\ 'split(v:val, "\\s\\+")')
if len(proc) == 6
- let s:procs[proc[1]] ..']]'..[[= {'name': proc[0],
+ let s:procs[proc[1]] .. ']]' .. [[= {'name': proc[0],
\ 'Session Name': proc[2],
\ 'Session': proc[3]}
endif
@@ -1015,15 +1057,13 @@ describe('jobs', function()
endfunction
]])
end
- local sleep_cmd = (is_os('win')
- and 'ping -n 31 127.0.0.1'
- or 'sleep 30')
- local j = eval("jobstart('"..sleep_cmd..' | '..sleep_cmd..' | '..sleep_cmd.."')")
- local ppid = funcs.jobpid(j)
+ local sleep_cmd = (is_os('win') and 'ping -n 31 127.0.0.1' or 'sleep 30')
+ local j = eval("jobstart('" .. sleep_cmd .. ' | ' .. sleep_cmd .. ' | ' .. sleep_cmd .. "')")
+ local ppid = fn.jobpid(j)
local children
if is_os('win') then
local status, result = pcall(retry, nil, nil, function()
- children = meths.get_proc_children(ppid)
+ children = api.nvim_get_proc_children(ppid)
-- On Windows conhost.exe may exist, and
-- e.g. vctip.exe might appear. #10783
ok(#children >= 3 and #children <= 5)
@@ -1034,36 +1074,38 @@ describe('jobs', function()
error(result)
end
else
- retry(nil, nil, function()
- children = meths.get_proc_children(ppid)
+ retry(nil, nil, function()
+ children = api.nvim_get_proc_children(ppid)
eq(3, #children)
end)
end
-- Assert that nvim_get_proc() sees the children.
for _, child_pid in ipairs(children) do
- local info = meths.get_proc(child_pid)
+ local info = api.nvim_get_proc(child_pid)
-- eq((is_os('win') and 'nvim.exe' or 'nvim'), info.name)
eq(ppid, info.ppid)
end
-- Kill the root of the tree.
- eq(1, funcs.jobstop(j))
+ eq(1, fn.jobstop(j))
-- Assert that the children were killed.
retry(nil, nil, function()
for _, child_pid in ipairs(children) do
- eq(NIL, meths.get_proc(child_pid))
+ eq(NIL, api.nvim_get_proc(child_pid))
end
end)
end)
it('jobstop on same id before stopped', function()
- nvim('command', 'let j = jobstart(["cat", "-"], g:job_opts)')
+ command('let j = jobstart(["cat", "-"], g:job_opts)')
neq(0, eval('j'))
- eq({1, 0}, eval('[jobstop(j), jobstop(j)]'))
+ eq({ 1, 0 }, eval('[jobstop(j), jobstop(j)]'))
end)
describe('running tty-test program', function()
- if skip(is_os('win')) then return end
+ if skip(is_os('win')) then
+ return
+ end
local function next_chunk()
local rv
while true do
@@ -1084,7 +1126,7 @@ describe('jobs', function()
local j
local function send(str)
-- check no nvim_chan_free double free with pty job (#14198)
- meths.chan_send(j, str)
+ api.nvim_chan_send(j, str)
end
before_each(function()
@@ -1095,10 +1137,10 @@ describe('jobs', function()
endfunction
]])
insert(testprg('tty-test'))
- nvim('command', 'let g:job_opts.pty = 1')
- nvim('command', 'let exec = [expand("<cfile>:p")]')
- nvim('command', "let j = jobstart(exec, g:job_opts)")
- j = eval'j'
+ command('let g:job_opts.pty = 1')
+ command('let exec = [expand("<cfile>:p")]')
+ command('let j = jobstart(exec, g:job_opts)')
+ j = eval 'j'
eq('tty ready', next_chunk())
end)
@@ -1108,17 +1150,17 @@ describe('jobs', function()
end)
it('resizing window', function()
- nvim('command', 'call jobresize(j, 40, 10)')
+ command('call jobresize(j, 40, 10)')
eq('rows: 10, cols: 40', next_chunk())
- nvim('command', 'call jobresize(j, 10, 40)')
+ command('call jobresize(j, 10, 40)')
eq('rows: 40, cols: 10', next_chunk())
end)
it('jobclose() sends SIGHUP', function()
- nvim('command', 'call jobclose(j)')
+ command('call jobclose(j)')
local msg = next_msg()
- msg = (msg[2] == 'stdout') and next_msg() or msg -- Skip stdout, if any.
- eq({'notification', 'exit', {0, 42}}, msg)
+ msg = (msg[2] == 'stdout') and next_msg() or msg -- Skip stdout, if any.
+ eq({ 'notification', 'exit', { 0, 42 } }, msg)
end)
it('jobstart() does not keep ptmx file descriptor open', function()
@@ -1132,7 +1174,7 @@ describe('jobs', function()
-- Have to wait so that the SIGHUP can be processed by tty-test on time.
-- Can't wait for the next message in case this test fails, if it fails
-- there won't be any more messages, and the test would hang.
- helpers.sleep(100)
+ vim.uv.sleep(100)
local err = exc_exec('call jobpid(j)')
eq('Vim(call):E900: Invalid channel id', err)
@@ -1141,9 +1183,49 @@ describe('jobs', function()
command('call jobstop(' .. other_jobid .. ')')
end)
end)
+
+ it('does not close the same handle twice on exit #25086', function()
+ local filename = string.format('%s.lua', helpers.tmpname())
+ write_file(
+ filename,
+ [[
+ vim.api.nvim_create_autocmd('VimLeavePre', {
+ callback = function()
+ local id = vim.fn.jobstart('sleep 0')
+ vim.fn.jobwait({id})
+ end,
+ })
+ ]]
+ )
+
+ local screen = thelpers.setup_child_nvim({
+ '--cmd',
+ 'set notermguicolors',
+ '-i',
+ 'NONE',
+ '-u',
+ filename,
+ })
+ -- Wait for startup to complete, so that all terminal responses are received.
+ screen:expect([[
+ {1: } |
+ ~ |*3
+ {1:[No Name] 0,0-1 All}|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+
+ feed(':q<CR>')
+ screen:expect([[
+ |
+ [Process exited 0]{1: } |
+ |*4
+ {3:-- TERMINAL --} |
+ ]])
+ end)
end)
-describe("pty process teardown", function()
+describe('pty process teardown', function()
local screen
before_each(function()
clear()
@@ -1151,31 +1233,33 @@ describe("pty process teardown", function()
screen:attach()
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
|
]])
end)
- it("does not prevent/delay exit. #4798 #4900", function()
- skip(is_os('win'))
+ it('does not prevent/delay exit. #4798 #4900', function()
-- Use a nested nvim (in :term) to test without --headless.
- feed_command(":terminal '"..helpers.nvim_prog
- .."' -u NONE -i NONE --cmd '"..nvim_set.."' "
+ fn.termopen({
+ helpers.nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ nvim_set,
-- Use :term again in the _nested_ nvim to get a PTY process.
-- Use `sleep` to simulate a long-running child of the PTY.
- .."+terminal +'!(sleep 300 &)' +qa")
+ '+terminal',
+ '+!(sleep 300 &)',
+ '+qa',
+ }, { env = { VIMRUNTIME = os.getenv('VIMRUNTIME') } })
-- Exiting should terminate all descendants (PTY, its children, ...).
screen:expect([[
^ |
[Process exited 0] |
- |
- |
- |
- |
+ |*4
]])
end)
end)
diff --git a/test/functional/core/log_spec.lua b/test/functional/core/log_spec.lua
index f682df4155..1637e683c1 100644
--- a/test/functional/core/log_spec.lua
+++ b/test/functional/core/log_spec.lua
@@ -23,7 +23,7 @@ describe('log', function()
-- calls, that needs investigation.
clear()
eq(0, request('nvim__stats').log_skip)
- clear{env={CDPATH='~doesnotexist'}}
+ clear { env = { CDPATH = '~doesnotexist' } }
assert(request('nvim__stats').log_skip <= 13)
end)
@@ -32,14 +32,16 @@ describe('log', function()
-- ERR 2022-05-29T12:30:03.800 T2 log_init:110: test log message
-- ERR 2022-05-29T12:30:03.814 T2/child log_init:110: test log message
- clear({env={
- NVIM_LOG_FILE=testlog,
- -- TODO: remove this after nvim_log #7062 is merged.
- __NVIM_TEST_LOG='1'
- }})
+ clear({
+ env = {
+ NVIM_LOG_FILE = testlog,
+ -- TODO: remove this after nvim_log #7062 is merged.
+ __NVIM_TEST_LOG = '1',
+ },
+ })
local tid = _G._nvim_test_id
- assert_log(tid..'%.%d+%.%d +server_init:%d+: test log message', testlog, 100)
+ assert_log(tid .. '%.%d+%.%d +server_init:%d+: test log message', testlog, 100)
exec_lua([[
local j1 = vim.fn.jobstart({ vim.v.progpath, '-es', '-V1', '+foochild', '+qa!' }, vim.empty_dict())
diff --git a/test/functional/core/main_spec.lua b/test/functional/core/main_spec.lua
index 19c7a93730..9d8d64c82d 100644
--- a/test/functional/core/main_spec.lua
+++ b/test/functional/core/main_spec.lua
@@ -1,4 +1,4 @@
-local luv = require('luv')
+local uv = vim.uv
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
@@ -7,7 +7,7 @@ local matches = helpers.matches
local feed = helpers.feed
local eval = helpers.eval
local clear = helpers.clear
-local funcs = helpers.funcs
+local fn = helpers.fn
local nvim_prog_abs = helpers.nvim_prog_abs
local write_file = helpers.write_file
local is_os = helpers.is_os
@@ -32,28 +32,57 @@ describe('command-line option', function()
end)
it('treats - as stdin', function()
- eq(nil, luv.fs_stat(fname))
- funcs.system(
- {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless',
- '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix',
- '-s', '-', fname},
- {':call setline(1, "42")', ':wqall!', ''})
+ eq(nil, uv.fs_stat(fname))
+ fn.system({
+ nvim_prog_abs(),
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--headless',
+ '--cmd',
+ 'set noswapfile shortmess+=IFW fileformats=unix',
+ '-s',
+ '-',
+ fname,
+ }, { ':call setline(1, "42")', ':wqall!', '' })
eq(0, eval('v:shell_error'))
- local attrs = luv.fs_stat(fname)
- eq(#('42\n'), attrs.size)
+ local attrs = uv.fs_stat(fname)
+ eq(#'42\n', attrs.size)
end)
it('does not expand $VAR', function()
- eq(nil, luv.fs_stat(fname))
+ eq(nil, uv.fs_stat(fname))
eq(true, not not dollar_fname:find('%$%w+'))
write_file(dollar_fname, ':call setline(1, "100500")\n:wqall!\n')
- funcs.system(
- {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless',
- '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix',
- '-s', dollar_fname, fname})
+ fn.system({
+ nvim_prog_abs(),
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--headless',
+ '--cmd',
+ 'set noswapfile shortmess+=IFW fileformats=unix',
+ '-s',
+ dollar_fname,
+ fname,
+ })
+ eq(0, eval('v:shell_error'))
+ local attrs = uv.fs_stat(fname)
+ eq(#'100500\n', attrs.size)
+ end)
+
+ it('does not crash when run completion in ex mode', function()
+ fn.system({
+ nvim_prog_abs(),
+ '--clean',
+ '-e',
+ '-s',
+ '--cmd',
+ 'exe "norm! i\\<C-X>\\<C-V>"',
+ })
eq(0, eval('v:shell_error'))
- local attrs = luv.fs_stat(fname)
- eq(#('100500\n'), attrs.size)
end)
it('does not crash after reading from stdin in non-headless mode', function()
@@ -61,36 +90,38 @@ describe('command-line option', function()
local screen = Screen.new(40, 8)
screen:attach()
local args = {
- nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE',
- '--cmd', '"set noswapfile shortmess+=IFW fileformats=unix"',
- '-s', '-'
+ nvim_prog_abs(),
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ '"set noswapfile shortmess+=IFW fileformats=unix notermguicolors"',
+ '-s',
+ '-',
}
-- Need to explicitly pipe to stdin so that the embedded Nvim instance doesn't try to read
-- data from the terminal #18181
- funcs.termopen(string.format([[echo "" | %s]], table.concat(args, " ")))
- screen:expect([[
- ^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {2:[No Name] 0,0-1 All}|
- |
- |
- ]], {
- [1] = {foreground = tonumber('0x4040ff'), fg_indexed=true},
- [2] = {bold = true, reverse = true}
+ fn.termopen(string.format([[echo "" | %s]], table.concat(args, ' ')), {
+ env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
})
+ screen:expect(
+ [[
+ ^ |
+ ~ |*4
+ {1:[No Name] 0,0-1 All}|
+ |*2
+ ]],
+ {
+ [1] = { reverse = true },
+ }
+ )
feed('i:cq<CR>')
screen:expect([[
|
[Process exited 1] |
- |
- |
- |
- |
- |
+ |*5
-- TERMINAL -- |
]])
--[=[ Example of incorrect output:
@@ -101,20 +132,29 @@ describe('command-line option', function()
LENO' failed. |
|
[Process exited 6] |
- |
- |
+ |*2
]])
]=]
end)
it('errors out when trying to use nonexistent file with -s', function()
eq(
- 'Cannot open for reading: "'..nonexistent_fname..'": no such file or directory\n',
- funcs.system(
- {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless',
- '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix',
- '--cmd', 'language C',
- '-s', nonexistent_fname}))
+ 'Cannot open for reading: "' .. nonexistent_fname .. '": no such file or directory\n',
+ fn.system({
+ nvim_prog_abs(),
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--headless',
+ '--cmd',
+ 'set noswapfile shortmess+=IFW fileformats=unix',
+ '--cmd',
+ 'language C',
+ '-s',
+ nonexistent_fname,
+ })
+ )
eq(2, eval('v:shell_error'))
end)
@@ -122,21 +162,34 @@ describe('command-line option', function()
write_file(fname, ':call setline(1, "1")\n:wqall!\n')
write_file(dollar_fname, ':call setline(1, "2")\n:wqall!\n')
eq(
- 'Attempt to open script file again: "-s '..dollar_fname..'"\n',
- funcs.system(
- {nvim_prog_abs(), '-u', 'NONE', '-i', 'NONE', '--headless',
- '--cmd', 'set noswapfile shortmess+=IFW fileformats=unix',
- '--cmd', 'language C',
- '-s', fname, '-s', dollar_fname, fname_2}))
+ 'Attempt to open script file again: "-s ' .. dollar_fname .. '"\n',
+ fn.system({
+ nvim_prog_abs(),
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--headless',
+ '--cmd',
+ 'set noswapfile shortmess+=IFW fileformats=unix',
+ '--cmd',
+ 'language C',
+ '-s',
+ fname,
+ '-s',
+ dollar_fname,
+ fname_2,
+ })
+ )
eq(2, eval('v:shell_error'))
- eq(nil, luv.fs_stat(fname_2))
+ eq(nil, uv.fs_stat(fname_2))
end)
end)
it('nvim -v, :version', function()
- matches('Run ":verbose version"', funcs.execute(':version'))
- matches('Compilation: .*Run :checkhealth', funcs.execute(':verbose version'))
- matches('Run "nvim %-V1 %-v"', funcs.system({nvim_prog_abs(), '-v'}))
- matches('Compilation: .*Run :checkhealth', funcs.system({nvim_prog_abs(), '-V1', '-v'}))
+ matches('Run ":verbose version"', fn.execute(':version'))
+ matches('Compilation: .*Run :checkhealth', fn.execute(':verbose version'))
+ matches('Run "nvim %-V1 %-v"', fn.system({ nvim_prog_abs(), '-v' }))
+ matches('Compilation: .*Run :checkhealth', fn.system({ nvim_prog_abs(), '-V1', '-v' }))
end)
end)
diff --git a/test/functional/core/path_spec.lua b/test/functional/core/path_spec.lua
index 97c32f7de6..e98bfc0d45 100644
--- a/test/functional/core/path_spec.lua
+++ b/test/functional/core/path_spec.lua
@@ -4,7 +4,7 @@ local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
local feed = helpers.feed
-local funcs = helpers.funcs
+local fn = helpers.fn
local insert = helpers.insert
local is_os = helpers.is_os
local mkdir = helpers.mkdir
@@ -13,7 +13,7 @@ local write_file = helpers.write_file
local function join_path(...)
local pathsep = (is_os('win') and '\\' or '/')
- return table.concat({...}, pathsep)
+ return table.concat({ ... }, pathsep)
end
describe('path collapse', function()
@@ -23,40 +23,40 @@ describe('path collapse', function()
before_each(function()
targetdir = join_path('test', 'functional', 'fixtures')
clear()
- command('edit '..join_path(targetdir, 'tty-test.c'))
+ command('edit ' .. join_path(targetdir, 'tty-test.c'))
expected_path = eval('expand("%:p")')
end)
it('with /./ segment #7117', function()
- command('edit '..join_path(targetdir, '.', 'tty-test.c'))
+ command('edit ' .. join_path(targetdir, '.', 'tty-test.c'))
eq(expected_path, eval('expand("%:p")'))
end)
it('with ./ prefix #7117', function()
- command('edit '..join_path('.', targetdir, 'tty-test.c'))
+ command('edit ' .. join_path('.', targetdir, 'tty-test.c'))
eq(expected_path, eval('expand("%:p")'))
end)
it('with ./ prefix, after directory change #7117', function()
- command('edit '..join_path('.', targetdir, 'tty-test.c'))
+ command('edit ' .. join_path('.', targetdir, 'tty-test.c'))
command('cd test')
eq(expected_path, eval('expand("%:p")'))
end)
it('with /../ segment #7117', function()
- command('edit '..join_path(targetdir, '..', 'fixtures', 'tty-test.c'))
+ command('edit ' .. join_path(targetdir, '..', 'fixtures', 'tty-test.c'))
eq(expected_path, eval('expand("%:p")'))
end)
it('with ../ and different starting directory #7117', function()
command('cd test')
- command('edit '..join_path('..', targetdir, 'tty-test.c'))
+ command('edit ' .. join_path('..', targetdir, 'tty-test.c'))
eq(expected_path, eval('expand("%:p")'))
end)
it('with ./../ and different starting directory #7117', function()
command('cd test')
- command('edit '..join_path('.', '..', targetdir, 'tty-test.c'))
+ command('edit ' .. join_path('.', '..', targetdir, 'tty-test.c'))
eq(expected_path, eval('expand("%:p")'))
end)
end)
@@ -67,16 +67,16 @@ describe('expand wildcard', function()
it('with special characters #24421', function()
local folders = is_os('win') and {
'{folder}',
- 'folder$name'
+ 'folder$name',
} or {
'folder-name',
- 'folder#name'
+ 'folder#name',
}
for _, folder in ipairs(folders) do
mkdir(folder)
local file = join_path(folder, 'file.txt')
write_file(file, '')
- eq(file, eval('expand("'..folder..'/*")'))
+ eq(file, eval('expand("' .. folder .. '/*")'))
rmdir(folder)
end
end)
@@ -131,14 +131,30 @@ describe('file search', function()
test_cfile([[c:foo]], [[c]])
-- Examples from: https://learn.microsoft.com/en-us/dotnet/standard/io/file-path-formats#example-ways-to-refer-to-the-same-file
test_cfile([[c:\temp\test-file.txt]], [[c:]], [[c:\temp\test-file.txt]])
- test_cfile([[\\127.0.0.1\c$\temp\test-file.txt]], [[127.0.0.1]], [[\\127.0.0.1\c$\temp\test-file.txt]])
- test_cfile([[\\LOCALHOST\c$\temp\test-file.txt]], [[LOCALHOST]], [[\\LOCALHOST\c$\temp\test-file.txt]])
+ test_cfile(
+ [[\\127.0.0.1\c$\temp\test-file.txt]],
+ [[127.0.0.1]],
+ [[\\127.0.0.1\c$\temp\test-file.txt]]
+ )
+ test_cfile(
+ [[\\LOCALHOST\c$\temp\test-file.txt]],
+ [[LOCALHOST]],
+ [[\\LOCALHOST\c$\temp\test-file.txt]]
+ )
-- not supported yet
test_cfile([[\\.\c:\temp\test-file.txt]], [[.]], [[\\.\c]])
-- not supported yet
test_cfile([[\\?\c:\temp\test-file.txt]], [[c:]], [[\\]])
- test_cfile([[\\.\UNC\LOCALHOST\c$\temp\test-file.txt]], [[.]], [[\\.\UNC\LOCALHOST\c$\temp\test-file.txt]])
- test_cfile([[\\127.0.0.1\c$\temp\test-file.txt]], [[127.0.0.1]], [[\\127.0.0.1\c$\temp\test-file.txt]])
+ test_cfile(
+ [[\\.\UNC\LOCALHOST\c$\temp\test-file.txt]],
+ [[.]],
+ [[\\.\UNC\LOCALHOST\c$\temp\test-file.txt]]
+ )
+ test_cfile(
+ [[\\127.0.0.1\c$\temp\test-file.txt]],
+ [[127.0.0.1]],
+ [[\\127.0.0.1\c$\temp\test-file.txt]]
+ )
end)
---@param funcname 'finddir' | 'findfile'
@@ -151,7 +167,7 @@ describe('file search', function()
else
write_file(expected, '')
end
- eq(expected, funcs[funcname](item, d:gsub(' ', [[\ ]])))
+ eq(expected, fn[funcname](item, d:gsub(' ', [[\ ]])))
end
it('finddir()', function()
diff --git a/test/functional/core/remote_spec.lua b/test/functional/core/remote_spec.lua
index a0ec748446..caff06f6ab 100644
--- a/test/functional/core/remote_spec.lua
+++ b/test/functional/core/remote_spec.lua
@@ -6,7 +6,7 @@ local eq = helpers.eq
local exec_capture = helpers.exec_capture
local exec_lua = helpers.exec_lua
local expect = helpers.expect
-local funcs = helpers.funcs
+local fn = helpers.fn
local insert = helpers.insert
local nvim_prog = helpers.nvim_prog
local new_argv = helpers.new_argv
@@ -42,7 +42,7 @@ describe('Remote', function()
-- Run a `nvim --remote*` command and return { stdout, stderr } of the process
local function run_remote(...)
set_session(server)
- local addr = funcs.serverlist()[1]
+ local addr = fn.serverlist()[1]
-- Create an nvim instance just to run the remote-invoking nvim. We want
-- to wait for the remote instance to exit and calling jobwait blocks
@@ -51,7 +51,10 @@ describe('Remote', function()
local client_starter = spawn(new_argv(), false, nil, true)
set_session(client_starter)
-- Call jobstart() and jobwait() in the same RPC request to reduce flakiness.
- eq({ 0 }, exec_lua([[return vim.fn.jobwait({ vim.fn.jobstart({...}, {
+ eq(
+ { 0 },
+ exec_lua(
+ [[return vim.fn.jobwait({ vim.fn.jobstart({...}, {
stdout_buffered = true,
stderr_buffered = true,
on_stdout = function(_, data, _)
@@ -60,7 +63,15 @@ describe('Remote', function()
on_stderr = function(_, data, _)
_G.Remote_stderr = table.concat(data, '\n')
end,
- }) })]], nvim_prog, '--clean', '--headless', '--server', addr, ...))
+ }) })]],
+ nvim_prog,
+ '--clean',
+ '--headless',
+ '--server',
+ addr,
+ ...
+ )
+ )
local res = exec_lua([[return { _G.Remote_stdout, _G.Remote_stderr }]])
client_starter:close()
set_session(server)
@@ -70,20 +81,20 @@ describe('Remote', function()
it('edit a single file', function()
eq({ '', '' }, run_remote('--remote', fname))
expect(contents)
- eq(2, #funcs.getbufinfo())
+ eq(1, #fn.getbufinfo())
end)
it('tab edit a single file with a non-changed buffer', function()
eq({ '', '' }, run_remote('--remote-tab', fname))
expect(contents)
- eq(1, #funcs.gettabinfo())
+ eq(1, #fn.gettabinfo())
end)
it('tab edit a single file with a changed buffer', function()
insert('hello')
eq({ '', '' }, run_remote('--remote-tab', fname))
expect(contents)
- eq(2, #funcs.gettabinfo())
+ eq(2, #fn.gettabinfo())
end)
it('edit multiple files', function()
@@ -91,15 +102,15 @@ describe('Remote', function()
expect(contents)
command('next')
expect(other_contents)
- eq(3, #funcs.getbufinfo())
+ eq(2, #fn.getbufinfo())
end)
it('send keys', function()
- eq({ '', '' }, run_remote('--remote-send', ':edit '..fname..'<CR><C-W>v'))
+ eq({ '', '' }, run_remote('--remote-send', ':edit ' .. fname .. '<CR><C-W>v'))
expect(contents)
- eq(2, #funcs.getwininfo())
+ eq(2, #fn.getwininfo())
-- Only a single buffer as we're using edit and not drop like --remote does
- eq(1, #funcs.getbufinfo())
+ eq(1, #fn.getbufinfo())
end)
it('evaluate expressions', function()
@@ -116,7 +127,7 @@ describe('Remote', function()
it('creates server if not found', function()
clear('--remote', fname)
expect(contents)
- eq(1, #funcs.getbufinfo())
+ eq(1, #fn.getbufinfo())
-- Since we didn't pass silent, we should get a complaint
neq(nil, string.find(exec_capture('messages'), 'E247:'))
end)
@@ -124,8 +135,8 @@ describe('Remote', function()
it('creates server if not found with tabs', function()
clear('--remote-tab-silent', fname, other_fname)
expect(contents)
- eq(2, #funcs.gettabinfo())
- eq(2, #funcs.getbufinfo())
+ eq(2, #fn.gettabinfo())
+ eq(2, #fn.getbufinfo())
-- We passed silent, so no message should be issued about the server not being found
eq(nil, string.find(exec_capture('messages'), 'E247:'))
end)
diff --git a/test/functional/core/spellfile_spec.lua b/test/functional/core/spellfile_spec.lua
index e3a59085cf..57953b8f80 100644
--- a/test/functional/core/spellfile_spec.lua
+++ b/test/functional/core/spellfile_spec.lua
@@ -2,8 +2,9 @@ local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local clear = helpers.clear
-local meths = helpers.meths
+local api = helpers.api
local exc_exec = helpers.exc_exec
+local fn = helpers.fn
local rmdir = helpers.rmdir
local write_file = helpers.write_file
local mkdir = helpers.mkdir
@@ -24,7 +25,8 @@ describe('spellfile', function()
-- │ ┌ Spell file version (#VIMSPELLVERSION)
local spellheader = 'VIMspell\050'
it('errors out when prefcond section is truncated', function()
- meths.set_option_value('runtimepath', testdir, {})
+ api.nvim_set_option_value('runtimepath', testdir, {})
+ -- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_PREFCOND)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -34,12 +36,12 @@ describe('spellfile', function()
-- │ ┌ Condition length (1 byte)
-- │ │ ┌ Condition regex (missing!)
.. '\000\001\001')
- meths.set_option_value('spelllang', 'en', {})
- eq('Vim(set):E758: Truncated spell file',
- exc_exec('set spell'))
+ api.nvim_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_value('runtimepath', testdir, {})
+ api.nvim_set_option_value('runtimepath', testdir, {})
+ -- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_PREFCOND)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -54,12 +56,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_value('spelllang', 'en', {})
- eq('Vim(set):E759: Format error in spell file',
- exc_exec('set spell'))
+ api.nvim_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_value('runtimepath', testdir, {})
+ api.nvim_set_option_value('runtimepath', testdir, {})
+ -- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_REGION)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -71,12 +73,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_value('spelllang', 'en', {})
- eq('Vim(set):E759: Format error in spell file',
- exc_exec('set spell'))
+ api.nvim_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_value('runtimepath', testdir, {})
+ api.nvim_set_option_value('runtimepath', testdir, {})
+ -- stylua: ignore
write_file(testdir .. '/spell/en.ascii.spl',
-- ┌ Section identifier (#SN_SAL)
-- │ ┌ Section flags (#SNF_REQUIRED or zero)
@@ -95,16 +97,23 @@ 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_value('spelllang', 'en', {})
- eq('Vim(set):E759: Format error in spell file',
- exc_exec('set spell'))
+ api.nvim_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_value('runtimepath', testdir, {})
- write_file(testdir .. '/spell/en.ascii.spl',
- spellheader:sub(1, -3) .. '\000\000')
- meths.set_option_value('spelllang', 'en', {})
- eq('Vim(set):E757: This does not look like a spell file',
- exc_exec('set spell'))
+ api.nvim_set_option_value('runtimepath', testdir, {})
+ write_file(testdir .. '/spell/en.ascii.spl', spellheader:sub(1, -3) .. '\000\000')
+ api.nvim_set_option_value('spelllang', 'en', {})
+ eq('Vim(set):E757: This does not look like a spell file', exc_exec('set spell'))
+ end)
+
+ it('can be set to a relative path', function()
+ local fname = testdir .. '/spell/spell.add'
+ api.nvim_set_option_value('spellfile', fname, {})
+ end)
+
+ it('can be set to an absolute path', function()
+ local fname = fn.fnamemodify(testdir .. '/spell/spell.add', ':p')
+ api.nvim_set_option_value('spellfile', fname, {})
end)
end)
diff --git a/test/functional/core/startup_spec.lua b/test/functional/core/startup_spec.lua
index 94ec3d4907..cc58226f48 100644
--- a/test/functional/core/startup_spec.lua
+++ b/test/functional/core/startup_spec.lua
@@ -13,8 +13,8 @@ local exec = helpers.exec
local exec_capture = helpers.exec_capture
local exec_lua = helpers.exec_lua
local feed = helpers.feed
-local funcs = helpers.funcs
-local pesc = helpers.pesc
+local fn = helpers.fn
+local pesc = vim.pesc
local mkdir = helpers.mkdir
local mkdir_p = helpers.mkdir_p
local nvim_prog = helpers.nvim_prog
@@ -22,23 +22,37 @@ local nvim_set = helpers.nvim_set
local read_file = helpers.read_file
local retry = helpers.retry
local rmdir = helpers.rmdir
-local sleep = helpers.sleep
-local startswith = helpers.startswith
+local sleep = vim.uv.sleep
+local startswith = vim.startswith
local write_file = helpers.write_file
-local meths = helpers.meths
+local api = helpers.api
local alter_slashes = helpers.alter_slashes
local is_os = helpers.is_os
local dedent = helpers.dedent
-local tbl_map = helpers.tbl_map
-local tbl_filter = helpers.tbl_filter
-local endswith = helpers.endswith
+local tbl_map = vim.tbl_map
+local tbl_filter = vim.tbl_filter
+local endswith = vim.endswith
describe('startup', function()
it('--clean', function()
clear()
- ok(string.find(alter_slashes(meths.get_option_value('runtimepath', {})), funcs.stdpath('config'), 1, true) ~= nil)
+ ok(
+ string.find(
+ alter_slashes(api.nvim_get_option_value('runtimepath', {})),
+ fn.stdpath('config'),
+ 1,
+ true
+ ) ~= nil
+ )
clear('--clean')
- ok(string.find(alter_slashes(meths.get_option_value('runtimepath', {})), funcs.stdpath('config'), 1, true) == nil)
+ ok(
+ string.find(
+ alter_slashes(api.nvim_get_option_value('runtimepath', {})),
+ fn.stdpath('config'),
+ 1,
+ true
+ ) == nil
+ )
end)
it('prevents remote UI infinite loop', function()
@@ -46,11 +60,10 @@ describe('startup', function()
local screen
screen = Screen.new(84, 3)
screen:attach()
- funcs.termopen({ nvim_prog, '-u', 'NONE', '--server', eval('v:servername'), '--remote-ui' })
+ fn.termopen({ nvim_prog, '-u', 'NONE', '--server', eval('v:servername'), '--remote-ui' })
screen:expect([[
^Cannot attach UI of :terminal child to its parent. (Unset $NVIM to skip this check) |
- |
- |
+ |*2
]])
end)
@@ -59,7 +72,8 @@ describe('startup', function()
finally(function()
os.remove(testfile)
end)
- clear({ args = {'--startuptime', testfile}})
+ clear({ args = { '--startuptime', testfile } })
+ assert_log('Embedded', testfile, 100)
assert_log('sourcing', testfile, 100)
assert_log("require%('vim%._editor'%)", testfile, 100)
end)
@@ -69,8 +83,20 @@ describe('startup', function()
local screen
screen = Screen.new(60, 7)
screen:attach()
- command([[let g:id = termopen('"]]..nvim_prog..
- [[" -u NONE -i NONE --cmd "set noruler" -D')]])
+ local id = fn.termopen({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'set noruler',
+ '-D',
+ }, {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+ },
+ })
screen:expect([[
^ |
|
@@ -80,15 +106,12 @@ describe('startup', function()
> |
|
]])
- command([[call chansend(g:id, "cont\n")]])
+ fn.chansend(id, 'cont\n')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
[No Name] |
- |
- |
+ |*2
]])
end)
end)
@@ -102,13 +125,13 @@ describe('startup', function()
vim.list_extend(args, nvim_args or {})
vim.list_extend(args, { '-l', (script or 'test/functional/fixtures/startup.lua') })
vim.list_extend(args, lua_args or {})
- local out = funcs.system(args, input):gsub('\r\n', '\n')
+ local out = fn.system(args, input):gsub('\r\n', '\n')
return eq(dedent(expected), out)
end
it('failure modes', function()
-- nvim -l <empty>
- matches('nvim%.?e?x?e?: Argument missing after: "%-l"', funcs.system({ nvim_prog, '-l' }))
+ matches('nvim%.?e?x?e?: Argument missing after: "%-l"', fn.system({ nvim_prog, '-l' }))
eq(1, eval('v:shell_error'))
end)
@@ -122,39 +145,48 @@ describe('startup', function()
vim.uv.os_setenv('ASAN_OPTIONS', asan_options .. ':detect_leaks=0')
]]
-- nvim -l foo.lua -arg1 -- a b c
- assert_l_out([[
+ assert_l_out(
+ [[
bufs:
nvim args: 7
lua args: { "-arg1", "--exitcode", "73", "--arg2",
[0] = "test/functional/fixtures/startup.lua"
}]],
{},
- { '-arg1', "--exitcode", "73", '--arg2' }
+ { '-arg1', '--exitcode', '73', '--arg2' }
)
eq(73, eval('v:shell_error'))
end)
it('Lua-error sets Nvim exitcode', function()
eq(0, eval('v:shell_error'))
- matches('E5113: .* my pearls!!',
- funcs.system({ nvim_prog, '-l', 'test/functional/fixtures/startup-fail.lua' }))
+ matches(
+ 'E5113: .* my pearls!!',
+ fn.system({ nvim_prog, '-l', 'test/functional/fixtures/startup-fail.lua' })
+ )
eq(1, eval('v:shell_error'))
- matches('E5113: .* %[string "error%("whoa"%)"%]:1: whoa',
- funcs.system({ nvim_prog, '-l', '-' }, 'error("whoa")'))
+ matches(
+ 'E5113: .* %[string "error%("whoa"%)"%]:1: whoa',
+ fn.system({ nvim_prog, '-l', '-' }, 'error("whoa")')
+ )
eq(1, eval('v:shell_error'))
end)
it('executes stdin "-"', function()
- assert_l_out('arg0=- args=2 whoa\n',
+ assert_l_out(
+ 'arg0=- args=2 whoa\n',
nil,
{ 'arg1', 'arg 2' },
'-',
- "print(('arg0=%s args=%d %s'):format(_G.arg[0], #_G.arg, 'whoa'))")
- assert_l_out('biiig input: 1000042\n',
+ "print(('arg0=%s args=%d %s'):format(_G.arg[0], #_G.arg, 'whoa'))"
+ )
+ assert_l_out(
+ 'biiig input: 1000042\n',
nil,
nil,
'-',
- ('print("biiig input: "..("%s"):len())'):format(string.rep('x', (1000 * 1000) + 42)))
+ ('print("biiig input: "..("%s"):len())'):format(string.rep('x', (1000 * 1000) + 42))
+ )
eq(0, eval('v:shell_error'))
end)
@@ -169,7 +201,8 @@ describe('startup', function()
it('sets _G.arg', function()
-- nvim -l foo.lua
- assert_l_out([[
+ assert_l_out(
+ [[
bufs:
nvim args: 3
lua args: {
@@ -182,7 +215,8 @@ describe('startup', function()
eq(0, eval('v:shell_error'))
-- nvim -l foo.lua [args]
- assert_l_out([[
+ assert_l_out(
+ [[
bufs:
nvim args: 7
lua args: { "-arg1", "--arg2", "--", "arg3",
@@ -195,20 +229,22 @@ describe('startup', function()
eq(0, eval('v:shell_error'))
-- nvim file1 file2 -l foo.lua -arg1 -- file3 file4
- assert_l_out([[
+ assert_l_out(
+ [[
bufs: file1 file2
nvim args: 10
lua args: { "-arg1", "arg 2", "--", "file3", "file4",
[0] = "test/functional/fixtures/startup.lua"
}
]],
- { 'file1', 'file2', },
+ { 'file1', 'file2' },
{ '-arg1', 'arg 2', '--', 'file3', 'file4' }
)
eq(0, eval('v:shell_error'))
-- nvim -l foo.lua <vim args>
- assert_l_out([[
+ assert_l_out(
+ [[
bufs:
nvim args: 5
lua args: { "-c", "set wrap?",
@@ -239,30 +275,50 @@ describe('startup', function()
end)
it('disables swapfile/shada/config/plugins', function()
- assert_l_out('updatecount=0 shadafile=NONE loadplugins=false scripts=1\n',
+ assert_l_out(
+ 'updatecount=0 shadafile=NONE loadplugins=false scripts=1\n',
nil,
nil,
'-',
[[print(('updatecount=%d shadafile=%s loadplugins=%s scripts=%d'):format(
- vim.o.updatecount, vim.o.shadafile, tostring(vim.o.loadplugins), math.max(1, #vim.fn.getscriptinfo())))]])
+ vim.o.updatecount, vim.o.shadafile, tostring(vim.o.loadplugins), math.max(1, #vim.fn.getscriptinfo())))]]
+ )
end)
end)
it('--cmd/-c/+ do not truncate long Lua print() message with --headless', function()
- local out = funcs.system({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless',
- '--cmd', 'lua print(("A"):rep(1234))',
- '-c', 'lua print(("B"):rep(1234))',
- '+lua print(("C"):rep(1234))',
- '+q' })
+ local out = fn.system({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--headless',
+ '--cmd',
+ 'lua print(("A"):rep(1234))',
+ '-c',
+ 'lua print(("B"):rep(1234))',
+ '+lua print(("C"):rep(1234))',
+ '+q',
+ })
eq(('A'):rep(1234) .. '\r\n' .. ('B'):rep(1234) .. '\r\n' .. ('C'):rep(1234), out)
end)
it('pipe at both ends: has("ttyin")==0 has("ttyout")==0', function()
-- system() puts a pipe at both ends.
- local out = funcs.system({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless',
- '--cmd', nvim_set,
- '-c', [[echo has('ttyin') has('ttyout')]],
- '+q' })
+ local out = fn.system({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--headless',
+ '--cmd',
+ nvim_set,
+ '-c',
+ [[echo has('ttyin') has('ttyout')]],
+ '+q',
+ })
eq('0 0', out)
end)
@@ -285,10 +341,21 @@ describe('startup', function()
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
end
-- Running in :terminal
- command([[exe printf("terminal %s -u NONE -i NONE --cmd \"]]
- ..nvim_set..[[\"]]
- ..[[ -c \"echo has('ttyin') has('ttyout')\""]]
- ..[[, shellescape(v:progpath))]])
+ fn.termopen({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ nvim_set,
+ '-c',
+ 'echo has("ttyin") has("ttyout")',
+ }, {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+ },
+ })
screen:expect([[
^ |
~ |
@@ -306,15 +373,24 @@ describe('startup', function()
os.remove('Xtest_startup_ttyout')
end)
-- Running in :terminal
- command([[exe printf("terminal %s -u NONE -i NONE --cmd \"]]
- ..nvim_set..[[\"]]
- ..[[ -c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
- ..[[ -c q | cat -v"]] -- Output to a pipe.
- ..[[, shellescape(v:progpath))]])
+ fn.termopen(
+ (
+ [["%s" -u NONE -i NONE --cmd "%s"]]
+ .. [[ -c "call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')"]]
+ .. [[ -c q | cat -v]]
+ ):format(nvim_prog, nvim_set),
+ {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+ },
+ }
+ )
retry(nil, 3000, function()
sleep(1)
- eq('1\n0\n', -- stdin is a TTY, stdout is a pipe
- read_file('Xtest_startup_ttyout'))
+ eq(
+ '1\n0\n', -- stdin is a TTY, stdout is a pipe
+ read_file('Xtest_startup_ttyout')
+ )
end)
end)
@@ -327,16 +403,25 @@ describe('startup', function()
os.remove('Xtest_startup_ttyout')
end)
-- Running in :terminal
- command([[exe printf("terminal echo foo | ]] -- Input from a pipe.
- ..[[%s -u NONE -i NONE --cmd \"]]
- ..nvim_set..[[\"]]
- ..[[ -c \"call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')\"]]
- ..[[ -c q -- -"]]
- ..[[, shellescape(v:progpath))]])
+ fn.termopen(
+ (
+ [[echo foo | ]] -- Input from a pipe.
+ .. [["%s" -u NONE -i NONE --cmd "%s"]]
+ .. [[ -c "call writefile([has('ttyin'), has('ttyout')], 'Xtest_startup_ttyout')"]]
+ .. [[ -c q -- -]]
+ ):format(nvim_prog, nvim_set),
+ {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+ },
+ }
+ )
retry(nil, 3000, function()
sleep(1)
- eq('0\n1\n', -- stdin is a pipe, stdout is a TTY
- read_file('Xtest_startup_ttyout'))
+ eq(
+ '0\n1\n', -- stdin is a pipe, stdout is a TTY
+ read_file('Xtest_startup_ttyout')
+ )
end)
end)
@@ -347,11 +432,18 @@ describe('startup', function()
command([[set shellcmdflag=/s\ /c shellxquote=\"]])
end
-- Running in :terminal
- command([[exe printf("terminal echo foo | ]] -- Input from a pipe.
- ..[[%s -u NONE -i NONE --cmd \"]]
- ..nvim_set..[[\"]]
- ..[[ -c \"echo has('ttyin') has('ttyout')\""]]
- ..[[, shellescape(v:progpath))]])
+ fn.termopen(
+ (
+ [[echo foo | ]]
+ .. [["%s" -u NONE -i NONE --cmd "%s"]]
+ .. [[ -c "echo has('ttyin') has('ttyout')"]]
+ ):format(nvim_prog, nvim_set),
+ {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+ },
+ }
+ )
screen:expect([[
^foo |
~ |
@@ -361,28 +453,44 @@ describe('startup', function()
end)
it('input from pipe + file args #7679', function()
- eq('ohyeah\r\n0 0 bufs=3',
- funcs.system({nvim_prog, '-n', '-u', 'NONE', '-i', 'NONE', '--headless',
- '+.print',
- "+echo has('ttyin') has('ttyout') 'bufs='.bufnr('$')",
- '+qall!',
- '-',
- 'test/functional/fixtures/tty-test.c',
- 'test/functional/fixtures/shell-test.c',
- },
- { 'ohyeah', '' }))
+ eq(
+ 'ohyeah\r\n0 0 bufs=3',
+ fn.system({
+ nvim_prog,
+ '-n',
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--headless',
+ '+.print',
+ "+echo has('ttyin') has('ttyout') 'bufs='.bufnr('$')",
+ '+qall!',
+ '-',
+ 'test/functional/fixtures/tty-test.c',
+ 'test/functional/fixtures/shell-test.c',
+ }, { 'ohyeah', '' })
+ )
end)
it('if stdin is empty: selects buffer 2, deletes buffer 1 #8561', function()
- eq('\r\n 2 %a "file1" line 0\r\n 3 "file2" line 0',
- funcs.system({nvim_prog, '-n', '-u', 'NONE', '-i', 'NONE', '--headless',
- '+ls!',
- '+qall!',
- '-',
- 'file1',
- 'file2',
- },
- { '' }))
+ eq(
+ '\r\n 2 %a "file1" line 0\r\n 3 "file2" line 0',
+ fn.system({
+ nvim_prog,
+ '-n',
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--headless',
+ '+ls!',
+ '+qall!',
+ '-',
+ 'file1',
+ 'file2',
+ }, { '' })
+ )
end)
it('stdin with -es/-Es #7679', function()
@@ -392,48 +500,70 @@ describe('startup', function()
--
-- -Es: read stdin as text
--
- eq('partylikeits1999\n',
- funcs.system({nvim_prog, '-n', '-u', 'NONE', '-i', 'NONE', '-Es', '+.print', 'test/functional/fixtures/tty-test.c' },
- { 'partylikeits1999', '' }))
- eq(inputstr,
- funcs.system({nvim_prog, '-i', 'NONE', '-Es', '+%print', '-' },
- input))
+ eq(
+ 'partylikeits1999\n',
+ fn.system({
+ nvim_prog,
+ '-n',
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '-Es',
+ '+.print',
+ 'test/functional/fixtures/tty-test.c',
+ }, { 'partylikeits1999', '' })
+ )
+ eq(inputstr, fn.system({ nvim_prog, '-i', 'NONE', '-Es', '+%print', '-' }, input))
-- with `-u NORC`
- eq('thepartycontinues\n',
- funcs.system({nvim_prog, '-n', '-u', 'NORC', '-Es', '+.print' },
- { 'thepartycontinues', '' }))
+ eq(
+ 'thepartycontinues\n',
+ fn.system({ nvim_prog, '-n', '-u', 'NORC', '-Es', '+.print' }, { 'thepartycontinues', '' })
+ )
-- without `-u`
- eq('thepartycontinues\n',
- funcs.system({nvim_prog, '-n', '-Es', '+.print' },
- { 'thepartycontinues', '' }))
+ eq(
+ 'thepartycontinues\n',
+ fn.system({ nvim_prog, '-n', '-Es', '+.print' }, { 'thepartycontinues', '' })
+ )
--
-- -es: read stdin as ex-commands
--
- eq(' encoding=utf-8\n',
- funcs.system({nvim_prog, '-n', '-u', 'NONE', '-i', 'NONE', '-es', 'test/functional/fixtures/tty-test.c' },
- { 'set encoding', '' }))
- eq('line1\nline2\n',
- funcs.system({nvim_prog, '-i', 'NONE', '-es', '-' },
- input))
+ eq(
+ ' encoding=utf-8\n',
+ fn.system({
+ nvim_prog,
+ '-n',
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '-es',
+ 'test/functional/fixtures/tty-test.c',
+ }, { 'set encoding', '' })
+ )
+ eq('line1\nline2\n', fn.system({ nvim_prog, '-i', 'NONE', '-es', '-' }, input))
-- with `-u NORC`
- eq(' encoding=utf-8\n',
- funcs.system({nvim_prog, '-n', '-u', 'NORC', '-es' },
- { 'set encoding', '' }))
+ eq(
+ ' encoding=utf-8\n',
+ fn.system({ nvim_prog, '-n', '-u', 'NORC', '-es' }, { 'set encoding', '' })
+ )
-- without `-u`
- eq(' encoding=utf-8\n',
- funcs.system({nvim_prog, '-n', '-es' },
- { 'set encoding', '' }))
+ eq(' encoding=utf-8\n', fn.system({ nvim_prog, '-n', '-es' }, { 'set encoding', '' }))
end)
it('-es/-Es disables swapfile, user config #8540', function()
- for _,arg in ipairs({'-es', '-Es'}) do
- local out = funcs.system({nvim_prog, arg,
- '+set swapfile? updatecount? shadafile?',
- "+put =map(getscriptinfo(), {-> v:val.name})", '+%print'})
+ for _, arg in ipairs({ '-es', '-Es' }) do
+ local out = fn.system({
+ nvim_prog,
+ arg,
+ '+set swapfile? updatecount? shadafile?',
+ '+put =map(getscriptinfo(), {-> v:val.name})',
+ '+%print',
+ })
local line1 = string.match(out, '^.-\n')
-- updatecount=0 means swapfile was disabled.
- eq(" swapfile updatecount=0 shadafile=\n", line1)
+ eq(' swapfile updatecount=0 shadafile=\n', line1)
-- Standard plugins were loaded, but not user config.
ok(string.find(out, 'man.lua') ~= nil)
ok(string.find(out, 'init.vim') == nil)
@@ -441,20 +571,39 @@ describe('startup', function()
end)
it('fails on --embed with -es/-Es/-l', function()
- matches('nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
- funcs.system({nvim_prog, '--embed', '-es' }))
- matches('nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
- funcs.system({nvim_prog, '--embed', '-Es' }))
- matches('nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
- funcs.system({nvim_prog, '--embed', '-l', 'foo.lua' }))
+ matches(
+ 'nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
+ fn.system({ nvim_prog, '--embed', '-es' })
+ )
+ matches(
+ 'nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
+ fn.system({ nvim_prog, '--embed', '-Es' })
+ )
+ matches(
+ 'nvim[.exe]*: %-%-embed conflicts with %-es/%-Es/%-l',
+ fn.system({ nvim_prog, '--embed', '-l', 'foo.lua' })
+ )
end)
it('ENTER dismisses early message #7967', function()
local screen
screen = Screen.new(60, 6)
screen:attach()
- command([[let g:id = termopen('"]]..nvim_prog..
- [[" -u NONE -i NONE --cmd "set noruler" --cmd "let g:foo = g:bar"')]])
+ local id = fn.termopen({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'set noruler',
+ '--cmd',
+ 'let g:foo = g:bar',
+ }, {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+ },
+ })
screen:expect([[
^ |
|
@@ -463,14 +612,12 @@ describe('startup', function()
Press ENTER or type command to continue |
|
]])
- command([[call chansend(g:id, "\n")]])
+ fn.chansend(id, '\n')
screen:expect([[
^ |
- ~ |
- ~ |
+ ~ |*2
[No Name] |
- |
- |
+ |*2
]])
end)
@@ -505,19 +652,32 @@ describe('startup', function()
expected,
-- FIXME(codehex): We should really set a timeout for the system function.
-- If this test fails, there will be a waiting input state.
- funcs.system({nvim_prog, '-u', 'NONE', '-c',
+ fn.system({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-c',
'for i in range(1, 100) | echo i | endfor | quit',
- '--headless'
+ '--headless',
})
)
end)
- it("get command line arguments from v:argv", function()
- local out = funcs.system({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless',
- '--cmd', nvim_set,
- '-c', [[echo v:argv[-1:] len(v:argv) > 1]],
- '+q' })
- eq('[\'+q\'] 1', out)
+ it('get command line arguments from v:argv', function()
+ local out = fn.system({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--headless',
+ '--cmd',
+ nvim_set,
+ '-c',
+ [[echo v:argv[-1:] len(v:argv) > 1]],
+ '+q',
+ })
+ eq("['+q'] 1", out)
end)
end)
@@ -549,20 +709,20 @@ describe('startup', function()
clear('-e')
screen:attach()
-- Verify we set the proper mode both before and after :vi.
- feed("put =mode(1)<CR>vi<CR>:put =mode(1)<CR>")
+ feed('put =mode(1)<CR>vi<CR>:put =mode(1)<CR>')
screen:expect([[
cv |
^n |
:put =mode(1) |
]])
- eq('cv\n',
- funcs.system({nvim_prog, '-n', '-es' },
- { 'put =mode(1)', 'print', '' }))
+ eq('cv\n', fn.system({ nvim_prog, '-n', '-es' }, { 'put =mode(1)', 'print', '' }))
end)
it('-d does not diff non-arglist windows #13720 #21289', function()
- write_file('Xdiff.vim', [[
+ write_file(
+ 'Xdiff.vim',
+ [[
let bufnr = nvim_create_buf(0, 1)
let config = {
\ 'relative': 'editor',
@@ -572,78 +732,92 @@ describe('startup', function()
\ 'row': 3,
\ 'col': 3
\ }
- autocmd WinEnter * call nvim_open_win(bufnr, v:false, config)]])
+ autocmd WinEnter * call nvim_open_win(bufnr, v:false, config)]]
+ )
finally(function()
os.remove('Xdiff.vim')
end)
- clear{args={'-u', 'Xdiff.vim', '-d', 'Xdiff.vim', 'Xdiff.vim'}}
- eq(true, meths.get_option_value('diff', {win = funcs.win_getid(1)}))
- eq(true, meths.get_option_value('diff', {win = funcs.win_getid(2)}))
- local float_win = funcs.win_getid(3)
- eq('editor', meths.win_get_config(float_win).relative)
- eq(false, meths.get_option_value('diff', {win = float_win}))
+ clear { args = { '-u', 'Xdiff.vim', '-d', 'Xdiff.vim', 'Xdiff.vim' } }
+ eq(true, api.nvim_get_option_value('diff', { win = fn.win_getid(1) }))
+ eq(true, api.nvim_get_option_value('diff', { win = fn.win_getid(2) }))
+ local float_win = fn.win_getid(3)
+ eq('editor', api.nvim_win_get_config(float_win).relative)
+ eq(false, api.nvim_get_option_value('diff', { win = float_win }))
end)
it('does not crash if --embed is given twice', function()
- clear{args={'--embed'}}
+ clear { args = { '--embed' } }
assert_alive()
end)
it('does not crash when expanding cdpath during early_init', function()
- clear{env={CDPATH='~doesnotexist'}}
+ clear { env = { CDPATH = '~doesnotexist' } }
assert_alive()
eq(',~doesnotexist', eval('&cdpath'))
end)
it("sets 'shortmess' when loading other tabs", function()
- clear({args={'-p', 'a', 'b', 'c'}})
+ clear({ args = { '-p', 'a', 'b', 'c' } })
local screen = Screen.new(25, 4)
screen:attach()
- screen:expect({grid=[[
+ screen:expect({
+ grid = [[
{1: a }{2: b c }{3: }{2:X}|
^ |
{4:~ }|
|
]],
- attr_ids={
- [1] = {bold = true},
- [2] = {background = Screen.colors.LightGrey, underline = true},
- [3] = {reverse = true},
- [4] = {bold = true, foreground = Screen.colors.Blue1},
- }})
+ attr_ids = {
+ [1] = { bold = true },
+ [2] = { background = Screen.colors.LightGrey, underline = true },
+ [3] = { reverse = true },
+ [4] = { bold = true, foreground = Screen.colors.Blue1 },
+ },
+ })
end)
end)
describe('startup', function()
local function pack_clear(cmd)
-- add packages after config dir in rtp but before config/after
- clear{args={'--cmd', 'set packpath=test/functional/fixtures', '--cmd', 'let paths=split(&rtp, ",")', '--cmd', 'let &rtp = paths[0]..",test/functional/fixtures,test/functional/fixtures/middle,"..join(paths[1:],",")', '--cmd', cmd}, env={XDG_CONFIG_HOME='test/functional/fixtures/'},
- args_rm={'runtimepath'},
+ clear {
+ args = {
+ '--cmd',
+ 'set packpath=test/functional/fixtures',
+ '--cmd',
+ 'let paths=split(&rtp, ",")',
+ '--cmd',
+ 'let &rtp = paths[0]..",test/functional/fixtures,test/functional/fixtures/middle,"..join(paths[1:],",")',
+ '--cmd',
+ cmd,
+ },
+ env = { XDG_CONFIG_HOME = 'test/functional/fixtures/' },
+ args_rm = { 'runtimepath' },
}
end
- it("handles &packpath during startup", function()
+ it('handles &packpath during startup', function()
pack_clear [[
let g:x = bar#test()
let g:y = leftpad#pad("heyya")
]]
eq(-3, eval 'g:x')
- eq(" heyya", eval 'g:y')
+ eq(' heyya', eval 'g:y')
pack_clear [[ lua _G.y = require'bar'.doit() _G.z = require'leftpad''howdy' ]]
- eq({9003, '\thowdy'}, exec_lua [[ return { _G.y, _G.z } ]])
+ eq({ 9003, '\thowdy' }, exec_lua [[ return { _G.y, _G.z } ]])
end)
- it("handles require from &packpath in an async handler", function()
- -- NO! you cannot just speed things up by calling async functions during startup!
- -- It doesn't make anything actually faster! NOOOO!
+ it('handles require from &packpath in an async handler', function()
+ -- NO! you cannot just speed things up by calling async functions during startup!
+ -- It doesn't make anything actually faster! NOOOO!
pack_clear [[ lua require'async_leftpad'('brrrr', 'async_res') ]]
-- haha, async leftpad go brrrrr
eq('\tbrrrr', exec_lua [[ return _G.async_res ]])
end)
- it("handles :packadd during startup", function()
+ it('handles :packadd during startup', function()
-- control group: opt/bonus is not available by default
pack_clear [[
try
@@ -655,8 +829,10 @@ describe('startup', function()
eq('Vim(let):E117: Unknown function: bonus#secret', eval 'g:err')
pack_clear [[ lua _G.test = {pcall(function() require'bonus'.launch() end)} ]]
- eq({false, [[[string ":lua"]:1: module 'bonus' not found:]]},
- exec_lua [[ _G.test[2] = string.gsub(_G.test[2], '[\r\n].*', '') return _G.test ]])
+ eq(
+ { false, [[[string ":lua"]:1: module 'bonus' not found:]] },
+ exec_lua [[ _G.test[2] = string.gsub(_G.test[2], '[\r\n].*', '') return _G.test ]]
+ )
-- ok, time to launch the nukes:
pack_clear [[ packadd! bonus | let g:x = bonus#secret() ]]
@@ -666,46 +842,77 @@ describe('startup', function()
eq('CPE 1704 TKS', exec_lua [[ return _G.y ]])
end)
- it("handles the correct order with start packages and after/", function()
+ it('handles the correct order with start packages and after/', function()
pack_clear [[ lua _G.test_loadorder = {} vim.cmd "runtime! filen.lua" ]]
- eq({'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ eq(
+ { 'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after' },
+ exec_lua [[ return _G.test_loadorder ]]
+ )
end)
- it("handles the correct order with start packages and after/ after startup", function()
+ it('handles the correct order with start packages and after/ after startup', function()
pack_clear [[ lua _G.test_loadorder = {} ]]
command [[ runtime! filen.lua ]]
- eq({'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ eq(
+ { 'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after' },
+ exec_lua [[ return _G.test_loadorder ]]
+ )
end)
- it("handles the correct order with globpath(&rtp, ...)", function()
+ it('handles the correct order with globpath(&rtp, ...)', function()
pack_clear [[ set loadplugins | lua _G.test_loadorder = {} ]]
command [[
for x in globpath(&rtp, "filen.lua",1,1)
call v:lua.dofile(x)
endfor
]]
- eq({'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ eq(
+ { 'ordinary', 'FANCY', 'mittel', 'FANCY after', 'ordinary after' },
+ exec_lua [[ return _G.test_loadorder ]]
+ )
- 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)
+ local rtp = api.nvim_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)
- it("handles the correct order with opt packages and after/", function()
+ it('handles the correct order with opt packages and after/', function()
pack_clear [[ lua _G.test_loadorder = {} vim.cmd "packadd! superspecial\nruntime! filen.lua" ]]
- eq({'ordinary', 'SuperSpecial', 'FANCY', 'mittel', 'FANCY after', 'SuperSpecial after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ eq({
+ 'ordinary',
+ 'SuperSpecial',
+ 'FANCY',
+ 'mittel',
+ 'FANCY after',
+ 'SuperSpecial after',
+ 'ordinary after',
+ }, exec_lua [[ return _G.test_loadorder ]])
end)
- it("handles the correct order with opt packages and after/ after startup", function()
+ it('handles the correct order with opt packages and after/ after startup', function()
pack_clear [[ lua _G.test_loadorder = {} ]]
command [[
packadd! superspecial
runtime! filen.lua
]]
- eq({'ordinary', 'SuperSpecial', 'FANCY', 'mittel', 'FANCY after', 'SuperSpecial after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ eq({
+ 'ordinary',
+ 'SuperSpecial',
+ 'FANCY',
+ 'mittel',
+ 'FANCY after',
+ 'SuperSpecial after',
+ 'ordinary after',
+ }, exec_lua [[ return _G.test_loadorder ]])
end)
- it("handles the correct order with opt packages and globpath(&rtp, ...)", function()
+ it('handles the correct order with opt packages and globpath(&rtp, ...)', function()
pack_clear [[ set loadplugins | lua _G.test_loadorder = {} ]]
command [[
packadd! superspecial
@@ -713,18 +920,40 @@ describe('startup', function()
call v:lua.dofile(x)
endfor
]]
- eq({'ordinary', 'SuperSpecial', 'FANCY', 'mittel', 'SuperSpecial after', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ eq({
+ 'ordinary',
+ 'SuperSpecial',
+ 'FANCY',
+ 'mittel',
+ 'SuperSpecial after',
+ 'FANCY after',
+ 'ordinary after',
+ }, exec_lua [[ return _G.test_loadorder ]])
end)
- it("handles the correct order with a package that changes packpath", function()
+ it('handles the correct order with a package that changes packpath', function()
pack_clear [[ lua _G.test_loadorder = {} vim.cmd "packadd! funky\nruntime! filen.lua" ]]
- eq({'ordinary', 'funky!', 'FANCY', 'mittel', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
- eq({'ordinary', 'funky!', 'mittel', 'ordinary after'}, exec_lua [[ return _G.nested_order ]])
+ eq(
+ { 'ordinary', 'funky!', 'FANCY', 'mittel', 'FANCY after', 'ordinary after' },
+ exec_lua [[ return _G.test_loadorder ]]
+ )
+ eq({ 'ordinary', 'funky!', 'mittel', 'ordinary after' }, exec_lua [[ return _G.nested_order ]])
end)
- it("handles the correct order when prepending packpath", function()
- clear{args={'--cmd', 'set packpath^=test/functional/fixtures', '--cmd', [[ lua _G.test_loadorder = {} vim.cmd "runtime! filen.lua" ]]}, env={XDG_CONFIG_HOME='test/functional/fixtures/'}}
- eq({'ordinary', 'FANCY', 'FANCY after', 'ordinary after'}, exec_lua [[ return _G.test_loadorder ]])
+ it('handles the correct order when prepending packpath', function()
+ clear {
+ args = {
+ '--cmd',
+ 'set packpath^=test/functional/fixtures',
+ '--cmd',
+ [[ lua _G.test_loadorder = {} vim.cmd "runtime! filen.lua" ]],
+ },
+ env = { XDG_CONFIG_HOME = 'test/functional/fixtures/' },
+ }
+ eq(
+ { 'ordinary', 'FANCY', 'FANCY after', 'ordinary after' },
+ exec_lua [[ return _G.test_loadorder ]]
+ )
end)
it('window widths are correct when modelines set &columns with tabpages', function()
@@ -734,10 +963,10 @@ describe('startup', function()
os.remove('Xtab1.noft')
os.remove('Xtab2.noft')
end)
- clear({args = {'-p', 'Xtab1.noft', 'Xtab2.noft'}})
- eq(81, meths.win_get_width(0))
+ clear({ args = { '-p', 'Xtab1.noft', 'Xtab2.noft' } })
+ eq(81, api.nvim_win_get_width(0))
command('tabnext')
- eq(81, meths.win_get_width(0))
+ eq(81, api.nvim_win_get_width(0))
end)
end)
@@ -754,16 +983,22 @@ describe('sysinit', function()
mkdir(xdgdir)
mkdir(xdgdir .. pathsep .. 'nvim')
- write_file(table.concat({xdgdir, 'nvim', 'sysinit.vim'}, pathsep), [[
+ write_file(
+ table.concat({ xdgdir, 'nvim', 'sysinit.vim' }, pathsep),
+ [[
let g:loaded = get(g:, "loaded", 0) + 1
let g:xdg = 1
- ]])
+ ]]
+ )
mkdir(vimdir)
- write_file(table.concat({vimdir, 'sysinit.vim'}, pathsep), [[
+ write_file(
+ table.concat({ vimdir, 'sysinit.vim' }, pathsep),
+ [[
let g:loaded = get(g:, "loaded", 0) + 1
let g:vim = 1
- ]])
+ ]]
+ )
mkdir(xhome)
end)
@@ -774,23 +1009,27 @@ describe('sysinit', function()
end)
it('prefers XDG_CONFIG_DIRS over VIM', function()
- clear{args={'--cmd', 'set nomore undodir=. directory=. belloff='},
- args_rm={'-u', '--cmd'},
- env={ HOME=xhome,
- XDG_CONFIG_DIRS=xdgdir,
- VIM=vimdir }}
- eq('loaded 1 xdg 1 vim 0',
- eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))'))
+ clear {
+ args = { '--cmd', 'set nomore undodir=. directory=. belloff=' },
+ args_rm = { '-u', '--cmd' },
+ env = { HOME = xhome, XDG_CONFIG_DIRS = xdgdir, VIM = vimdir },
+ }
+ eq(
+ 'loaded 1 xdg 1 vim 0',
+ eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))')
+ )
end)
it('uses VIM if XDG_CONFIG_DIRS unset', function()
- clear{args={'--cmd', 'set nomore undodir=. directory=. belloff='},
- args_rm={'-u', '--cmd'},
- env={ HOME=xhome,
- XDG_CONFIG_DIRS='',
- VIM=vimdir }}
- eq('loaded 1 xdg 0 vim 1',
- eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))'))
+ clear {
+ args = { '--cmd', 'set nomore undodir=. directory=. belloff=' },
+ args_rm = { '-u', '--cmd' },
+ env = { HOME = xhome, XDG_CONFIG_DIRS = '', VIM = vimdir },
+ }
+ eq(
+ 'loaded 1 xdg 0 vim 1',
+ eval('printf("loaded %d xdg %d vim %d", g:loaded, get(g:, "xdg", 0), get(g:, "vim", 0))')
+ )
end)
end)
@@ -799,8 +1038,8 @@ describe('user config init', function()
local pathsep = helpers.get_pathsep()
local xconfig = xhome .. pathsep .. 'Xconfig'
local xdata = xhome .. pathsep .. 'Xdata'
- local init_lua_path = table.concat({xconfig, 'nvim', 'init.lua'}, pathsep)
- local xenv = { XDG_CONFIG_HOME=xconfig, XDG_DATA_HOME=xdata }
+ local init_lua_path = table.concat({ xconfig, 'nvim', 'init.lua' }, pathsep)
+ local xenv = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata }
before_each(function()
rmdir(xhome)
@@ -808,9 +1047,12 @@ describe('user config init', function()
mkdir_p(xconfig .. pathsep .. 'nvim')
mkdir_p(xdata)
- write_file(init_lua_path, [[
+ write_file(
+ init_lua_path,
+ [[
vim.g.lua_rc = 1
- ]])
+ ]]
+ )
end)
after_each(function()
@@ -818,36 +1060,51 @@ describe('user config init', function()
end)
it('loads init.lua from XDG config home by default', function()
- clear{ args_rm={'-u'}, env=xenv }
+ clear { args_rm = { '-u' }, env = xenv }
eq(1, eval('g:lua_rc'))
- eq(funcs.fnamemodify(init_lua_path, ':p'), eval('$MYVIMRC'))
+ eq(fn.fnamemodify(init_lua_path, ':p'), eval('$MYVIMRC'))
end)
describe('loads existing', function()
local exrc_path = '.exrc'
local xstate = 'Xstate'
- local xstateenv = { XDG_CONFIG_HOME=xconfig, XDG_DATA_HOME=xdata, XDG_STATE_HOME=xstate }
+ local xstateenv = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata, XDG_STATE_HOME = xstate }
local function setup_exrc_file(filename)
exrc_path = filename
- if string.find(exrc_path, "%.lua$") then
- write_file(exrc_path, string.format([[
+ if string.find(exrc_path, '%.lua$') then
+ write_file(
+ exrc_path,
+ string.format(
+ [[
vim.g.exrc_file = "%s"
- ]], exrc_path))
+ ]],
+ exrc_path
+ )
+ )
else
- write_file(exrc_path, string.format([[
+ write_file(
+ exrc_path,
+ string.format(
+ [[
let g:exrc_file = "%s"
- ]], exrc_path))
+ ]],
+ exrc_path
+ )
+ )
end
end
before_each(function()
- write_file(init_lua_path, [[
+ write_file(
+ init_lua_path,
+ [[
vim.o.exrc = true
vim.g.exrc_file = '---'
- ]])
+ ]]
+ )
mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
end)
@@ -860,39 +1117,41 @@ describe('user config init', function()
it(filename .. ' in cwd', function()
setup_exrc_file(filename)
- clear{ args_rm={'-u'}, env=xstateenv }
+ clear { args_rm = { '-u' }, env = xstateenv }
-- The 'exrc' file is not trusted, and the prompt is skipped because there is no UI.
eq('---', eval('g:exrc_file'))
local screen = Screen.new(50, 8)
screen:attach()
- funcs.termopen({nvim_prog})
+ fn.termopen({ nvim_prog }, {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+ },
+ })
screen:expect({ any = pesc('[i]gnore, (v)iew, (d)eny, (a)llow:') })
-- `i` to enter Terminal mode, `a` to allow
feed('ia')
screen:expect([[
|
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
[No Name] 0,0-1 All|
|
-- TERMINAL -- |
]])
feed(':echo g:exrc_file<CR>')
- screen:expect(string.format([[
+ screen:expect(string.format(
+ [[
|
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
[No Name] 0,0-1 All|
%s%s|
-- TERMINAL -- |
- ]], filename, string.rep(' ', 50 - #filename)))
+ ]],
+ filename,
+ string.rep(' ', 50 - #filename)
+ ))
- clear{ args_rm={'-u'}, env=xstateenv }
+ clear { args_rm = { '-u' }, env = xstateenv }
-- The 'exrc' file is now trusted.
eq(filename, eval('g:exrc_file'))
end)
@@ -900,15 +1159,18 @@ describe('user config init', function()
end)
describe('with explicitly provided config', function()
- local custom_lua_path = table.concat({xhome, 'custom.lua'}, pathsep)
+ local custom_lua_path = table.concat({ xhome, 'custom.lua' }, pathsep)
before_each(function()
- write_file(custom_lua_path, [[
+ write_file(
+ custom_lua_path,
+ [[
vim.g.custom_lua_rc = 1
- ]])
+ ]]
+ )
end)
it('loads custom lua config and does not set $MYVIMRC', function()
- clear{ args={'-u', custom_lua_path }, env=xenv }
+ clear { args = { '-u', custom_lua_path }, env = xenv }
eq(1, eval('g:custom_lua_rc'))
eq('', eval('$MYVIMRC'))
end)
@@ -916,14 +1178,17 @@ describe('user config init', function()
describe('VIMRC also exists', function()
before_each(function()
- write_file(table.concat({xconfig, 'nvim', 'init.vim'}, pathsep), [[
+ write_file(
+ table.concat({ xconfig, 'nvim', 'init.vim' }, pathsep),
+ [[
let g:vim_rc = 1
- ]])
+ ]]
+ )
end)
it('loads default lua config, but shows an error', function()
- clear{ args_rm={'-u'}, env=xenv }
- feed('<cr><c-c>') -- Dismiss "Conflicting config …" message.
+ clear { args_rm = { '-u' }, env = xenv }
+ feed('<cr><c-c>') -- Dismiss "Conflicting config …" message.
eq(1, eval('g:lua_rc'))
matches('^E5422: Conflicting configs', exec_capture('messages'))
end)
@@ -935,7 +1200,7 @@ describe('runtime:', function()
local pathsep = helpers.get_pathsep()
local xconfig = xhome .. pathsep .. 'Xconfig'
local xdata = xhome .. pathsep .. 'Xdata'
- local xenv = { XDG_CONFIG_HOME=xconfig, XDG_DATA_HOME=xdata }
+ local xenv = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata }
setup(function()
rmdir(xhome)
@@ -948,23 +1213,24 @@ describe('runtime:', function()
end)
it('loads plugin/*.lua from XDG config home', function()
- local plugin_folder_path = table.concat({xconfig, 'nvim', 'plugin'}, pathsep)
- local plugin_file_path = table.concat({plugin_folder_path, 'plugin.lua'}, pathsep)
+ local plugin_folder_path = table.concat({ xconfig, 'nvim', 'plugin' }, pathsep)
+ local plugin_file_path = table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep)
mkdir_p(plugin_folder_path)
finally(function()
rmdir(plugin_folder_path)
end)
write_file(plugin_file_path, [[ vim.g.lua_plugin = 1 ]])
- clear{ args_rm={'-u'}, env=xenv }
+ clear { args_rm = { '-u' }, env = xenv }
eq(1, eval('g:lua_plugin'))
end)
it('loads plugin/*.lua from start packages', function()
- local plugin_path = table.concat({xconfig, 'nvim', 'pack', 'category', 'start', 'test_plugin'}, pathsep)
- local plugin_folder_path = table.concat({plugin_path, 'plugin'}, pathsep)
- local plugin_file_path = table.concat({plugin_folder_path, 'plugin.lua'}, pathsep)
+ local plugin_path =
+ table.concat({ xconfig, 'nvim', 'pack', 'category', 'start', 'test_plugin' }, pathsep)
+ local plugin_folder_path = table.concat({ plugin_path, 'plugin' }, pathsep)
+ local plugin_file_path = table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep)
local profiler_file = 'test_startuptime.log'
mkdir_p(plugin_folder_path)
finally(function()
@@ -974,12 +1240,16 @@ describe('runtime:', function()
write_file(plugin_file_path, [[vim.g.lua_plugin = 2]])
- clear{ args_rm={'-u'}, args={'--startuptime', profiler_file}, env=xenv }
+ clear { args_rm = { '-u' }, args = { '--startuptime', profiler_file }, env = xenv }
eq(2, eval('g:lua_plugin'))
-- Check if plugin_file_path is listed in getscriptinfo()
- local scripts = tbl_map(function(s) return s.name end, funcs.getscriptinfo())
- ok(#tbl_filter(function(s) return endswith(s, plugin_file_path) end, scripts) > 0)
+ local scripts = tbl_map(function(s)
+ return s.name
+ end, fn.getscriptinfo())
+ ok(#tbl_filter(function(s)
+ return endswith(s, plugin_file_path)
+ end, scripts) > 0)
-- Check if plugin_file_path is listed in startup profile
local profile_reader = io.open(profiler_file, 'r')
@@ -989,12 +1259,13 @@ describe('runtime:', function()
end)
it('loads plugin/*.lua from site packages', function()
- local nvimdata = is_os('win') and "nvim-data" or "nvim"
- local plugin_path = table.concat({xdata, nvimdata, 'site', 'pack', 'xa', 'start', 'yb'}, pathsep)
- local plugin_folder_path = table.concat({plugin_path, 'plugin'}, pathsep)
- local plugin_after_path = table.concat({plugin_path, 'after', 'plugin'}, pathsep)
- local plugin_file_path = table.concat({plugin_folder_path, 'plugin.lua'}, pathsep)
- local plugin_after_file_path = table.concat({plugin_after_path, 'helloo.lua'}, pathsep)
+ local nvimdata = is_os('win') and 'nvim-data' or 'nvim'
+ local plugin_path =
+ table.concat({ xdata, nvimdata, 'site', 'pack', 'xa', 'start', 'yb' }, pathsep)
+ local plugin_folder_path = table.concat({ plugin_path, 'plugin' }, pathsep)
+ local plugin_after_path = table.concat({ plugin_path, 'after', 'plugin' }, pathsep)
+ local plugin_file_path = table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep)
+ local plugin_after_file_path = table.concat({ plugin_after_path, 'helloo.lua' }, pathsep)
mkdir_p(plugin_folder_path)
mkdir_p(plugin_after_path)
finally(function()
@@ -1004,49 +1275,64 @@ describe('runtime:', function()
write_file(plugin_file_path, [[table.insert(_G.lista, "unos")]])
write_file(plugin_after_file_path, [[table.insert(_G.lista, "dos")]])
- clear{ args_rm={'-u'}, args={'--cmd', 'lua _G.lista = {}'}, env=xenv }
+ clear { args_rm = { '-u' }, args = { '--cmd', 'lua _G.lista = {}' }, env = xenv }
- eq({'unos', 'dos'}, exec_lua "return _G.lista")
+ eq({ 'unos', 'dos' }, exec_lua 'return _G.lista')
end)
it('no crash setting &rtp in plugins with :packloadall called before #18315', function()
- local plugin_folder_path = table.concat({xconfig, 'nvim', 'plugin'}, pathsep)
+ local plugin_folder_path = table.concat({ xconfig, 'nvim', 'plugin' }, pathsep)
mkdir_p(plugin_folder_path)
finally(function()
rmdir(plugin_folder_path)
end)
- write_file(table.concat({plugin_folder_path, 'plugin.vim'}, pathsep), [[
+ write_file(
+ table.concat({ plugin_folder_path, 'plugin.vim' }, pathsep),
+ [[
let &runtimepath = &runtimepath
let g:vim_plugin = 1
- ]])
- write_file(table.concat({plugin_folder_path, 'plugin.lua'}, pathsep), [[
+ ]]
+ )
+ write_file(
+ table.concat({ plugin_folder_path, 'plugin.lua' }, pathsep),
+ [[
vim.o.runtimepath = vim.o.runtimepath
vim.g.lua_plugin = 1
- ]])
+ ]]
+ )
- clear{ args_rm={'-u'}, args = {'--cmd', 'packloadall'}, env=xenv }
+ clear { args_rm = { '-u' }, args = { '--cmd', 'packloadall' }, env = xenv }
eq(1, eval('g:vim_plugin'))
eq(1, eval('g:lua_plugin'))
end)
it("loads ftdetect/*.{vim,lua} respecting 'rtp' order", function()
- local ftdetect_folder = table.concat({xconfig, 'nvim', 'ftdetect'}, pathsep)
- local after_ftdetect_folder = table.concat({xconfig, 'nvim', 'after', 'ftdetect'}, pathsep)
+ local ftdetect_folder = table.concat({ xconfig, 'nvim', 'ftdetect' }, pathsep)
+ local after_ftdetect_folder = table.concat({ xconfig, 'nvim', 'after', 'ftdetect' }, pathsep)
mkdir_p(ftdetect_folder)
mkdir_p(after_ftdetect_folder)
finally(function()
rmdir(ftdetect_folder)
rmdir(after_ftdetect_folder)
end)
- -- A .lua file is loaded after a .vim file if they only differ in extension.
- -- All files in after/ftdetect/ are loaded after all files in ftdetect/.
- write_file(table.concat({ftdetect_folder, 'new-ft.vim'}, pathsep), [[let g:seq ..= 'A']])
- write_file(table.concat({ftdetect_folder, 'new-ft.lua'}, pathsep), [[vim.g.seq = vim.g.seq .. 'B']])
- write_file(table.concat({after_ftdetect_folder, 'new-ft.vim'}, pathsep), [[let g:seq ..= 'a']])
- write_file(table.concat({after_ftdetect_folder, 'new-ft.lua'}, pathsep), [[vim.g.seq = vim.g.seq .. 'b']])
- clear{ args_rm={'-u'}, args = {'--cmd', 'let g:seq = ""'}, env=xenv }
+ -- A .lua file is loaded after a .vim file if they only differ in extension.
+ -- All files in after/ftdetect/ are loaded after all files in ftdetect/.
+ write_file(table.concat({ ftdetect_folder, 'new-ft.vim' }, pathsep), [[let g:seq ..= 'A']])
+ write_file(
+ table.concat({ ftdetect_folder, 'new-ft.lua' }, pathsep),
+ [[vim.g.seq = vim.g.seq .. 'B']]
+ )
+ write_file(
+ table.concat({ after_ftdetect_folder, 'new-ft.vim' }, pathsep),
+ [[let g:seq ..= 'a']]
+ )
+ write_file(
+ table.concat({ after_ftdetect_folder, 'new-ft.lua' }, pathsep),
+ [[vim.g.seq = vim.g.seq .. 'b']]
+ )
+ clear { args_rm = { '-u' }, args = { '--cmd', 'let g:seq = ""' }, env = xenv }
eq('ABab', eval('g:seq'))
end)
end)
@@ -1054,15 +1340,18 @@ end)
describe('user session', function()
local xhome = 'Xhome'
local pathsep = helpers.get_pathsep()
- local session_file = table.concat({xhome, 'session.lua'}, pathsep)
+ local session_file = table.concat({ xhome, 'session.lua' }, pathsep)
before_each(function()
rmdir(xhome)
mkdir(xhome)
- write_file(session_file, [[
+ write_file(
+ session_file,
+ [[
vim.g.lua_session = 1
- ]])
+ ]]
+ )
end)
after_each(function()
@@ -1070,7 +1359,45 @@ describe('user session', function()
end)
it('loads session from the provided lua file', function()
- clear{ args={'-S', session_file }, env={ HOME=xhome }}
+ clear { args = { '-S', session_file }, env = { HOME = xhome } }
eq(1, eval('g:lua_session'))
end)
end)
+
+describe('inccommand on ex mode', function()
+ it('should not preview', function()
+ clear()
+ local screen
+ screen = Screen.new(60, 10)
+ screen:attach()
+ local id = fn.termopen({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '-c',
+ 'set termguicolors background=dark',
+ '-E',
+ 'test/README.md',
+ }, {
+ env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
+ })
+ fn.chansend(id, '%s/N')
+ screen:expect {
+ grid = [[
+ {1:^ }|
+ {1: }|*6
+ {1:Entering Ex mode. Type "visual" to go to Normal mode. }|
+ {1::%s/N }|
+ |
+ ]],
+ attr_ids = {
+ [1] = {
+ background = Screen.colors.NvimDarkGrey2,
+ foreground = Screen.colors.NvimLightGrey2,
+ },
+ },
+ }
+ end)
+end)
diff --git a/test/functional/editor/K_spec.lua b/test/functional/editor/K_spec.lua
index b964fb3467..1fbdd1c142 100644
--- a/test/functional/editor/K_spec.lua
+++ b/test/functional/editor/K_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
-local eq, clear, eval, feed, meths, retry =
- helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.meths, helpers.retry
+local eq, clear, eval, feed, api, retry =
+ helpers.eq, helpers.clear, helpers.eval, helpers.feed, helpers.api, helpers.retry
describe('K', function()
local test_file = 'K_spec_out'
@@ -30,13 +30,15 @@ describe('K', function()
set keywordprg=echo\ fnord>>]])
-- K on the text "K_spec_out" resolves to `!echo fnord >> K_spec_out`.
- feed('i'..test_file..'<ESC>K')
- retry(nil, nil, function() eq(1, eval('filereadable("'..test_file..'")')) end)
- eq({'fnord'}, eval("readfile('"..test_file.."')"))
+ feed('i' .. test_file .. '<ESC>K')
+ retry(nil, nil, function()
+ eq(1, eval('filereadable("' .. test_file .. '")'))
+ end)
+ eq({ 'fnord' }, eval("readfile('" .. test_file .. "')"))
-- Confirm that Neovim is still in terminal mode after K is pressed (#16692).
- helpers.sleep(500)
+ vim.uv.sleep(500)
eq('t', eval('mode()'))
- feed('<space>') -- Any key, not just <space>, can be used here to escape.
+ feed('<space>') -- Any key, not just <space>, can be used here to escape.
eq('n', eval('mode()'))
end)
@@ -48,7 +50,7 @@ describe('K', function()
-- Confirm that an arbitrary keypress doesn't escape (i.e., the process is
-- still running). If the process were no longer running, an arbitrary
-- keypress would escape.
- helpers.sleep(500)
+ vim.uv.sleep(500)
feed('<space>')
eq('t', eval('mode()'))
-- Confirm that <esc> kills the buffer for the running command.
@@ -59,10 +61,9 @@ describe('K', function()
end)
it('empty string falls back to :help #19298', function()
- meths.set_option_value('keywordprg', '', {})
- meths.buf_set_lines(0, 0, -1, true, {'doesnotexist'})
+ api.nvim_set_option_value('keywordprg', '', {})
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'doesnotexist' })
feed('K')
- eq('E149: Sorry, no help for doesnotexist', meths.get_vvar('errmsg'))
+ eq('E149: Sorry, no help for doesnotexist', api.nvim_get_vvar('errmsg'))
end)
-
end)
diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua
index cbaf401f06..33d0d47499 100644
--- a/test/functional/editor/completion_spec.lua
+++ b/test/functional/editor/completion_spec.lua
@@ -4,10 +4,9 @@ local assert_alive = helpers.assert_alive
local clear, feed = helpers.clear, helpers.feed
local eval, eq, neq = helpers.eval, helpers.eq, helpers.neq
local feed_command, source, expect = helpers.feed_command, helpers.source, helpers.expect
-local funcs = helpers.funcs
-local curbufmeths = helpers.curbufmeths
+local fn = helpers.fn
local command = helpers.command
-local meths = helpers.meths
+local api = helpers.api
local poke_eventloop = helpers.poke_eventloop
describe('completion', function()
@@ -18,17 +17,17 @@ describe('completion', function()
screen = Screen.new(60, 8)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {background = Screen.colors.LightMagenta},
- [2] = {background = Screen.colors.Grey},
- [3] = {bold = true},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen},
- [5] = {foreground = Screen.colors.Red},
- [6] = {background = Screen.colors.Black},
- [7] = {foreground = Screen.colors.White, background = Screen.colors.Red},
- [8] = {reverse = true},
- [9] = {bold = true, reverse = true},
- [10] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { background = Screen.colors.LightMagenta },
+ [2] = { background = Screen.colors.Grey },
+ [3] = { bold = true },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [5] = { foreground = Screen.colors.Red },
+ [6] = { background = Screen.colors.Black },
+ [7] = { foreground = Screen.colors.White, background = Screen.colors.Red },
+ [8] = { reverse = true },
+ [9] = { bold = true, reverse = true },
+ [10] = { foreground = Screen.colors.Grey0, background = Screen.colors.Yellow },
})
end)
@@ -41,22 +40,14 @@ describe('completion', function()
screen:expect([[
foo |
foo^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- Keyword Local completion (^N^P) The only match} |
]])
feed('<C-e>')
screen:expect([[
foo |
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- INSERT --} |
]])
feed('<ESC>')
@@ -65,9 +56,10 @@ describe('completion', function()
it('returns expected dict in normal completion', function()
feed('ifoo<ESC>o<C-x><C-n>')
eq('foo', eval('getline(2)'))
- eq({word = 'foo', abbr = '', menu = '',
- info = '', kind = '', user_data = ''},
- eval('v:completed_item'))
+ eq(
+ { word = 'foo', abbr = '', menu = '', info = '', kind = '', user_data = '' },
+ eval('v:completed_item')
+ )
end)
it('is readonly', function()
screen:try_resize(80, 8)
@@ -112,15 +104,17 @@ describe('completion', function()
foo^ |
{2:bar foobaz baz }{0: }|
{1:abbr kind menu }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:-- Omni completion (^O^N^P) }{4:match 1 of 2} |
]])
- eq({word = 'foo', abbr = 'bar', menu = 'baz',
- info = 'foobar', kind = 'foobaz', user_data = ''},
- eval('v:completed_item'))
+ eq({
+ word = 'foo',
+ abbr = 'bar',
+ menu = 'baz',
+ info = 'foobar',
+ kind = 'foobaz',
+ user_data = '',
+ }, eval('v:completed_item'))
end)
end)
@@ -140,11 +134,7 @@ describe('completion', function()
screen:expect([[
foo |
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- INSERT --} |
]])
feed('<C-x>')
@@ -152,11 +142,7 @@ describe('completion', function()
screen:expect([[
foo |
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)} |
]])
feed('<C-n>')
@@ -164,10 +150,7 @@ describe('completion', function()
foo |
foo^ |
{2:foo }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:-- Keyword Local completion (^N^P) The only match} |
]])
feed('bar<ESC>')
@@ -178,9 +161,7 @@ describe('completion', function()
foobar |
foo^ |
{2:foo }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:-- INSERT --} |
]])
eq('foo', eval('getline(3)'))
@@ -192,34 +173,24 @@ describe('completion', function()
foo |
^ |
{2:foo }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:-- Keyword Local completion (^N^P) The only match} |
]])
feed('<C-y>')
screen:expect([[
foo |
foo^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- INSERT --} |
]])
feed('<ESC>')
eq('foo', eval('getline(2)'))
feed('o<C-r>=TestComplete()<CR>')
screen:expect([[
- foo |
- foo |
+ foo |*2
^ |
{2:foo }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:-- INSERT --} |
]])
feed('<C-y><ESC>')
@@ -232,21 +203,14 @@ describe('completion', function()
foo |
^ |
{1:foo }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:-- Keyword Local completion (^N^P) }{5:Back at original} |
]])
feed('b')
screen:expect([[
foo |
b^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- Keyword Local completion (^N^P) }{5:Back at original} |
]])
feed('ar<ESC>')
@@ -257,9 +221,7 @@ describe('completion', function()
bar |
^ |
{1:foo }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:-- INSERT --} |
]])
feed('bar<ESC>')
@@ -272,21 +234,14 @@ describe('completion', function()
foo |
^ |
{1:foo }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:-- Keyword Local completion (^N^P) }{5:Back at original} |
]])
feed('<ESC>')
screen:expect([[
foo |
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
eq('', eval('getline(2)'))
@@ -296,9 +251,7 @@ describe('completion', function()
|
^ |
{1:foo }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:-- INSERT --} |
]])
feed('<ESC>')
@@ -306,10 +259,7 @@ describe('completion', function()
foo |
|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
eq('', eval('getline(3)'))
@@ -341,8 +291,8 @@ describe('completion', function()
end)
local tests = {
- ['<up>, <down>, <cr>'] = {'<down><cr>', '<up><cr>'},
- ['<c-n>, <c-p>, <c-y>'] = {'<c-n><c-y>', '<c-p><c-y>'},
+ ['<up>, <down>, <cr>'] = { '<down><cr>', '<up><cr>' },
+ ['<c-n>, <c-p>, <c-y>'] = { '<c-n><c-y>', '<c-p><c-y>' },
}
for name, seq in pairs(tests) do
@@ -358,13 +308,13 @@ describe('completion', function()
feed('A<right><esc>A<right><esc>')
local expected = {
- {'foo', 'bar', 'foo'},
- {'foo', 'bar', 'ccc'},
- {'foo', 'bar'},
- {'foo', 'bbb'},
- {'foo'},
- {'aaa'},
- {''},
+ { 'foo', 'bar', 'foo' },
+ { 'foo', 'bar', 'ccc' },
+ { 'foo', 'bar' },
+ { 'foo', 'bbb' },
+ { 'foo' },
+ { 'aaa' },
+ { '' },
}
for i = 1, #expected do
@@ -384,7 +334,7 @@ describe('completion', function()
end
end)
- describe("refresh:always", function()
+ describe('refresh:always', function()
before_each(function()
source([[
function! TestCompletion(findstart, base) abort
@@ -409,9 +359,9 @@ describe('completion', function()
set completeopt=menuone,noselect
set completefunc=TestCompletion
]])
- end )
+ end)
- it('completes on each input char', function ()
+ it('completes on each input char', function()
feed('i<C-x><C-u>')
screen:expect([[
^ |
@@ -438,48 +388,32 @@ describe('completion', function()
screen:expect([[
ug^ |
{1:August }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- User defined completion (^U^N^P) }{5:Back at original} |
]])
feed('<Down>')
screen:expect([[
ug^ |
{2:August }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- User defined completion (^U^N^P) The only match} |
]])
feed('<C-y>')
screen:expect([[
August^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
{3:-- INSERT --} |
]])
expect('August')
end)
- it("repeats correctly after backspace #2674", function ()
+ it('repeats correctly after backspace #2674', function()
feed('o<C-x><C-u>Ja')
screen:expect([[
|
Ja^ |
{1:January }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:-- User defined completion (^U^N^P) }{5:Back at original} |
]])
feed('<BS>')
@@ -489,8 +423,7 @@ describe('completion', function()
{1:January }{0: }|
{1:June }{0: }|
{1:July }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- User defined completion (^U^N^P) }{5:Back at original} |
]])
feed('<C-n>')
@@ -500,8 +433,7 @@ describe('completion', function()
{2:January }{0: }|
{1:June }{0: }|
{1:July }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- User defined completion (^U^N^P) }{4:match 1 of 3} |
]])
feed('<C-n>')
@@ -511,19 +443,14 @@ describe('completion', function()
{1:January }{0: }|
{2:June }{0: }|
{1:July }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- User defined completion (^U^N^P) }{4:match 2 of 3} |
]])
feed('<Esc>')
screen:expect([[
|
Jun^e |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
feed('.')
@@ -531,10 +458,7 @@ describe('completion', function()
|
June |
Jun^e |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
expect([[
@@ -552,10 +476,10 @@ describe('completion', function()
return ''
endfunction
]])
- feed_command("set completeopt=menuone,noselect")
+ feed_command('set completeopt=menuone,noselect')
end)
- it("works", function()
+ it('works', function()
feed('i<C-r>=TestComplete()<CR>')
screen:expect([[
^ |
@@ -705,18 +629,13 @@ describe('completion', function()
feed('<cr>')
screen:expect([[
96^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
{3:-- INSERT --} |
]])
end)
end)
- it("does not indent until an item is selected #8345", function ()
+ it('does not indent until an item is selected #8345', function()
-- Indents on "ind", unindents on "unind".
source([[
function! TestIndent()
@@ -735,129 +654,106 @@ describe('completion', function()
]])
-- Give some words to complete.
- feed("iinc uninc indent unindent<CR>")
+ feed('iinc uninc indent unindent<CR>')
-- Does not indent when "ind" is typed.
- feed("in<C-X><C-N>")
+ feed('in<C-X><C-N>')
-- Completion list is generated incorrectly if we send everything at once
-- via nvim_input(). So poke_eventloop() before sending <BS>. #8480
poke_eventloop()
- feed("<BS>d")
+ feed('<BS>d')
screen:expect([[
inc uninc indent unindent |
ind^ |
{2:indent }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} |
]])
-- Indents when the item is selected
- feed("<C-Y>")
+ feed('<C-Y>')
screen:expect([[
inc uninc indent unindent |
indent^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- INSERT --} |
]])
-- Indents when completion is exited using ESC.
- feed("<CR>in<C-N><BS>d<Esc>")
+ feed('<CR>in<C-N><BS>d<Esc>')
screen:expect([[
inc uninc indent unindent |
indent |
in^d |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
-- Works for unindenting too.
- feed("ounin<C-X><C-N>")
- helpers.poke_eventloop()
- feed("<BS>d")
+ feed('ounin<C-X><C-N>')
+ poke_eventloop()
+ feed('<BS>d')
screen:expect([[
inc uninc indent unindent |
indent |
ind |
unind^ |
{0:~ }{2: unindent }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} |
]])
-- Works when going back and forth.
- feed("<BS>c")
+ feed('<BS>c')
screen:expect([[
inc uninc indent unindent |
indent |
ind |
uninc^ |
{0:~ }{2: uninc }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} |
]])
- feed("<BS>d")
+ feed('<BS>d')
screen:expect([[
inc uninc indent unindent |
indent |
ind |
unind^ |
{0:~ }{2: unindent }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- Keyword Local completion (^N^P) }{4:match 1 of 2} |
]])
- feed("<C-N><C-N><C-Y><Esc>")
+ feed('<C-N><C-N><C-Y><Esc>')
screen:expect([[
inc uninc indent unindent |
indent |
ind |
uninden^t |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
end)
- it('disables folding during completion', function ()
- feed_command("set foldmethod=indent")
+ it('disables folding during completion', function()
+ feed_command('set foldmethod=indent')
feed('i<Tab>foo<CR><Tab>bar<Esc>gg')
screen:expect([[
^foo |
bar |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
feed('A<C-x><C-l>')
screen:expect([[
foo^ |
bar |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- Whole line completion (^L^N^P) }{7:Pattern not found} |
]])
eq(-1, eval('foldclosed(1)'))
end)
- it('popupmenu is not interrupted by events', function ()
- feed_command("set complete=.")
+ it('popupmenu is not interrupted by events', function()
+ feed_command('set complete=.')
feed('ifoobar fooegg<cr>f<c-p>')
screen:expect([[
@@ -865,24 +761,23 @@ describe('completion', function()
fooegg^ |
{1:foobar }{0: }|
{2:fooegg }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:-- Keyword completion (^N^P) }{4:match 1 of 2} |
]])
assert_alive()
-- popupmenu still visible
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
foobar fooegg |
fooegg^ |
{1:foobar }{0: }|
{2:fooegg }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:-- Keyword completion (^N^P) }{4:match 1 of 2} |
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
feed('<c-p>')
-- Didn't restart completion: old matches still used
@@ -891,9 +786,7 @@ describe('completion', function()
foobar^ |
{2:foobar }{0: }|
{1:fooegg }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:-- Keyword completion (^N^P) }{4:match 2 of 2} |
]])
end)
@@ -902,68 +795,62 @@ describe('completion', function()
it('expands when there is only one match', function()
feed(':lua CURRENT_TESTING_VAR = 1<CR>')
feed(':lua CURRENT_TESTING_<TAB>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
:lua CURRENT_TESTING_VAR^ |
- ]]}
+ ]],
+ }
end)
it('expands when there is only one match', function()
feed(':lua CURRENT_TESTING_FOO = 1<CR>')
feed(':lua CURRENT_TESTING_BAR = 1<CR>')
feed(':lua CURRENT_TESTING_<TAB>')
- screen:expect{ grid = [[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{10:CURRENT_TESTING_BAR}{9: CURRENT_TESTING_FOO }|
:lua CURRENT_TESTING_BAR^ |
- ]], unchanged = true }
+ ]],
+ unchanged = true,
+ }
end)
it('provides completion from `getcompletion()`', function()
- eq({'vim'}, funcs.getcompletion('vi', 'lua'))
- eq({'api'}, funcs.getcompletion('vim.ap', 'lua'))
- eq({'tbl_filter'}, funcs.getcompletion('vim.tbl_fil', 'lua'))
- eq({'vim'}, funcs.getcompletion('print(vi', 'lua'))
+ eq({ 'vim' }, fn.getcompletion('vi', 'lua'))
+ eq({ 'api' }, fn.getcompletion('vim.ap', 'lua'))
+ eq({ 'tbl_filter' }, fn.getcompletion('vim.tbl_fil', 'lua'))
+ eq({ 'vim' }, fn.getcompletion('print(vi', 'lua'))
-- fuzzy completion is not supported, so the result should be the same
command('set wildoptions+=fuzzy')
- eq({'vim'}, funcs.getcompletion('vi', 'lua'))
+ eq({ 'vim' }, fn.getcompletion('vi', 'lua'))
end)
end)
it('cmdline completion supports various string options', function()
- eq('auto', funcs.getcompletion('set foldcolumn=', 'cmdline')[2])
- eq({'nosplit', 'split'}, funcs.getcompletion('set inccommand=', 'cmdline'))
- eq({'ver:3,hor:6', 'hor:', 'ver:'}, funcs.getcompletion('set mousescroll=', 'cmdline'))
- eq('BS', funcs.getcompletion('set termpastefilter=', 'cmdline')[2])
- eq('SpecialKey', funcs.getcompletion('set winhighlight=', 'cmdline')[1])
- eq('SpecialKey', funcs.getcompletion('set winhighlight=NonText:', 'cmdline')[1])
+ eq('auto', fn.getcompletion('set foldcolumn=', 'cmdline')[2])
+ eq({ 'nosplit', 'split' }, fn.getcompletion('set inccommand=', 'cmdline'))
+ eq({ 'ver:3,hor:6', 'hor:', 'ver:' }, fn.getcompletion('set mousescroll=', 'cmdline'))
+ eq('BS', fn.getcompletion('set termpastefilter=', 'cmdline')[2])
+ eq('SpecialKey', fn.getcompletion('set winhighlight=', 'cmdline')[1])
+ eq('SpecialKey', fn.getcompletion('set winhighlight=NonText:', 'cmdline')[1])
end)
describe('from the commandline window', function()
- it('is cleared after CTRL-C', function ()
+ it('is cleared after CTRL-C', function()
feed('q:')
feed('ifoo faa fee f')
screen:expect([[
|
{8:[No Name] }|
{0::}foo faa fee f^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{9:[Command Line] }|
{3:-- INSERT --} |
- ]] )
+ ]])
feed('<c-x><c-n>')
screen:expect([[
|
@@ -980,9 +867,7 @@ describe('completion', function()
|
{8:[No Name] }|
{0::}foo faa fee foo |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{9:[Command Line] }|
:foo faa fee foo^ |
]])
@@ -997,17 +882,19 @@ describe('completion', function()
return ''
endfunction
]])
- meths.set_option_value('completeopt', 'menuone,noselect', {})
- meths.set_var('_complist', {{
- word=0,
- abbr=1,
- menu=2,
- kind=3,
- info=4,
- icase=5,
- dup=6,
- empty=7,
- }})
+ api.nvim_set_option_value('completeopt', 'menuone,noselect', {})
+ api.nvim_set_var('_complist', {
+ {
+ word = 0,
+ abbr = 1,
+ menu = 2,
+ kind = 3,
+ info = 4,
+ icase = 5,
+ dup = 6,
+ empty = 7,
+ },
+ })
end)
it('shows correct variant as word', function()
@@ -1015,11 +902,7 @@ describe('completion', function()
screen:expect([[
^ |
{1:1 3 2 }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- INSERT --} |
]])
end)
@@ -1027,22 +910,24 @@ describe('completion', function()
it("'ignorecase' 'infercase' CTRL-X CTRL-N #6451", function()
feed_command('set ignorecase infercase')
- feed_command('edit BACKERS.md')
+ feed_command('edit runtime/doc/backers.txt')
feed('oX<C-X><C-N>')
- screen:expect([[
- # Bountysource Backers |
+ screen:expect {
+ grid = [[
+ *backers.txt* Nvim |
Xnull^ |
{2:Xnull }{6: } |
- {1:Xoxomoon }{6: }ryone who backed our [Bountysource fundraise|
- {1:Xu }{6: }ountysource.com/teams/neovim/fundraiser)! |
+ {1:Xoxomoon }{6: } |
+ {1:Xu }{6: } NVIM REFERENCE MANUAL |
{1:Xpayn }{2: } |
- {1:Xinity }{2: }d URL in BACKERS.md. |
+ {1:Xinity }{2: } |
{3:-- Keyword Local completion (^N^P) }{4:match 1 of 7} |
- ]])
+ ]],
+ }
end)
it('CompleteChanged autocommand', function()
- curbufmeths.set_lines(0, 1, false, { 'foo', 'bar', 'foobar', ''})
+ api.nvim_buf_set_lines(0, 0, 1, false, { 'foo', 'bar', 'foobar', '' })
source([[
set complete=. completeopt=noinsert,noselect,menuone
function! OnPumChange()
@@ -1057,43 +942,45 @@ describe('completion', function()
-- v:event.size should be set with ext_popupmenu #20646
screen:set_option('ext_popupmenu', true)
feed('Sf<C-N>')
- screen:expect({grid = [[
+ screen:expect({
+ grid = [[
foo |
bar |
foobar |
f^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:-- Keyword completion (^N^P) }{5:Back at original} |
- ]], popupmenu = {
- anchor = { 1, 3, 0 },
- items = { { "foo", "", "", "" }, { "foobar", "", "", "" } },
- pos = -1
- }})
- eq({completed_item = {}, width = 0,
- height = 2, size = 2,
- col = 0, row = 4, scrollbar = false},
- eval('g:event'))
+ ]],
+ popupmenu = {
+ anchor = { 1, 3, 0 },
+ items = { { 'foo', '', '', '' }, { 'foobar', '', '', '' } },
+ pos = -1,
+ },
+ })
+ eq(
+ { completed_item = {}, width = 0, height = 2, size = 2, col = 0, row = 4, scrollbar = false },
+ eval('g:event')
+ )
feed('oob')
- screen:expect({grid = [[
+ screen:expect({
+ grid = [[
foo |
bar |
foobar |
foob^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:-- Keyword completion (^N^P) }{5:Back at original} |
- ]], popupmenu = {
- anchor = { 1, 3, 0 },
- items = { { "foobar", "", "", "" } },
- pos = -1
- }})
- eq({completed_item = {}, width = 0,
- height = 1, size = 1,
- col = 0, row = 4, scrollbar = false},
- eval('g:event'))
+ ]],
+ popupmenu = {
+ anchor = { 1, 3, 0 },
+ items = { { 'foobar', '', '', '' } },
+ pos = -1,
+ },
+ })
+ eq(
+ { completed_item = {}, width = 0, height = 1, size = 1, col = 0, row = 4, scrollbar = false },
+ eval('g:event')
+ )
feed('<Esc>')
screen:set_option('ext_popupmenu', false)
@@ -1108,10 +995,10 @@ describe('completion', function()
{0:~ }|
{3:-- Keyword completion (^N^P) }{5:Back at original} |
]])
- eq({completed_item = {}, width = 15,
- height = 2, size = 2,
- col = 0, row = 4, scrollbar = false},
- eval('g:event'))
+ eq(
+ { completed_item = {}, width = 15, height = 2, size = 2, col = 0, row = 4, scrollbar = false },
+ eval('g:event')
+ )
feed('<C-N>')
screen:expect([[
foo |
@@ -1164,7 +1051,7 @@ describe('completion', function()
end)
it('is stopped by :stopinsert from timer #12976', function()
- screen:try_resize(32,14)
+ screen:try_resize(32, 14)
command([[call setline(1, ['hello', 'hullo', 'heeee', ''])]])
feed('Gah<c-x><c-n>')
screen:expect([[
@@ -1175,36 +1062,40 @@ describe('completion', function()
{2:hello }{0: }|
{1:hullo }{0: }|
{1:heeee }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
{3:-- }{4:match 1 of 3} |
]])
command([[call timer_start(100, { -> execute('stopinsert') })]])
- helpers.sleep(200)
- feed('k') -- cursor should move up in Normal mode
+ vim.uv.sleep(200)
+ feed('k') -- cursor should move up in Normal mode
screen:expect([[
hello |
hullo |
heee^e |
hello |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
end)
- it('does not crash if text is changed by first call to complete function #17489', function()
+ -- oldtest: Test_complete_changed_complete_info()
+ it('no crash calling complete_info() in CompleteChanged', function()
+ source([[
+ set completeopt=menuone
+ autocmd CompleteChanged * call complete_info(['items'])
+ call feedkeys("iii\<cr>\<c-p>")
+ ]])
+ screen:expect([[
+ ii |
+ ii^ |
+ {2:ii }{0: }|
+ {0:~ }|*4
+ {3:-- Keyword completion (^N^P) The only match} |
+ ]])
+ assert_alive()
+ end)
+
+ it('no crash if text changed by first call to complete function #17489', function()
source([[
func Complete(findstart, base) abort
if a:findstart
@@ -1223,7 +1114,7 @@ describe('completion', function()
assert_alive()
end)
- it('does not crash when using i_CTRL-X_CTRL-V to complete non-existent colorscheme', function()
+ it('no crash using i_CTRL-X_CTRL-V to complete non-existent colorscheme', function()
feed('icolorscheme NOSUCHCOLORSCHEME<C-X><C-V>')
expect('colorscheme NOSUCHCOLORSCHEME')
assert_alive()
@@ -1233,28 +1124,70 @@ describe('completion', function()
screen:try_resize(20, 9)
command('set complete+=f | edit foo | edit bar |edit foa |edit .hidden')
feed('i<C-n>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
foo^ |
{2:foo }{0: }|
{1:bar }{0: }|
{1:foa }{0: }|
{1:.hidden }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:-- }{4:match 1 of 4} |
- ]]}
+ ]],
+ }
feed('<Esc>ccf<C-n>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
foo^ |
{2:foo }{0: }|
{1:foa }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- }{4:match 1 of 2} |
- ]]}
+ ]],
+ }
+ end)
+
+ it('restores extmarks if original text is restored #23653', function()
+ screen:try_resize(screen._width, 4)
+ command([[
+ call setline(1, ['aaaa'])
+ let ns_id = nvim_create_namespace('extmark')
+ let mark_id = nvim_buf_set_extmark(0, ns_id, 0, 0, { 'end_col':2, 'hl_group':'Error'})
+ let mark = nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })
+ inoremap <C-x> <C-r>=Complete()<CR>
+ function Complete() abort
+ call complete(1, [{ 'word': 'aaaaa' }])
+ return ''
+ endfunction
+ ]])
+ feed('A<C-X><C-E><Esc>')
+ eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })"))
+ feed('A<C-N>')
+ eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })"))
+ feed('<Esc>0Yppia<Esc>ggI<C-N>')
+ screen:expect([[
+ aaaa{7:^aa}aa |
+ {2:aaaa } |
+ {1:aaaaa } |
+ {3:-- Keyword completion (^N^P) }{4:match 1 of 2} |
+ ]])
+ feed('<C-N><C-N><Esc>')
+ eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })"))
+ feed('A<C-N>')
+ eq(eval('mark'), eval("nvim_buf_get_extmark_by_id(0, ns_id, mark_id, { 'details':1 })"))
+ feed('<C-N>')
+ screen:expect([[
+ aaaaa^ |
+ {1:aaaa } |
+ {2:aaaaa } |
+ {3:-- Keyword completion (^N^P) }{4:match 2 of 2} |
+ ]])
+ feed('<C-E>')
+ screen:expect([[
+ {7:aa}aa^ |
+ aaaa |
+ aaaaa |
+ {3:-- INSERT --} |
+ ]])
end)
end)
diff --git a/test/functional/editor/ctrl_c_spec.lua b/test/functional/editor/ctrl_c_spec.lua
index 4548e1aa34..e6a6ea808a 100644
--- a/test/functional/editor/ctrl_c_spec.lua
+++ b/test/functional/editor/ctrl_c_spec.lua
@@ -3,9 +3,9 @@ local Screen = require('test.functional.ui.screen')
local clear, feed, source = helpers.clear, helpers.feed, helpers.source
local command = helpers.command
local poke_eventloop = helpers.poke_eventloop
-local sleep = helpers.sleep
+local sleep = vim.uv.sleep
-describe("CTRL-C (mapped)", function()
+describe('CTRL-C (mapped)', function()
local screen
before_each(function()
@@ -14,7 +14,7 @@ describe("CTRL-C (mapped)", function()
screen:attach()
end)
- it("interrupts :global", function()
+ it('interrupts :global', function()
-- Crashes luajit.
if helpers.skip_fragile(pending) then
return
@@ -25,7 +25,7 @@ describe("CTRL-C (mapped)", function()
nnoremap <C-C> <NOP>
]])
- command("silent edit! test/functional/fixtures/bigfile.txt")
+ command('silent edit! test/functional/fixtures/bigfile.txt')
screen:expect([[
^0000;<control>;Cc;0;BN;;;;;N;NULL;;;; |
@@ -37,19 +37,21 @@ describe("CTRL-C (mapped)", function()
]])
local function test_ctrl_c(ms)
- feed(":global/^/p<CR>")
+ feed(':global/^/p<CR>')
screen:sleep(ms)
- feed("<C-C>")
- screen:expect{any="Interrupt"}
+ feed('<C-C>')
+ screen:expect { any = 'Interrupt' }
end
-- The test is time-sensitive. Try different sleep values.
- local ms_values = {100, 1000, 10000}
+ local ms_values = { 100, 1000, 10000 }
for i, ms in ipairs(ms_values) do
if i < #ms_values then
local status, _ = pcall(test_ctrl_c, ms)
- if status then break end
- else -- Call the last attempt directly.
+ if status then
+ break
+ end
+ else -- Call the last attempt directly.
test_ctrl_c(ms)
end
end
@@ -58,16 +60,13 @@ describe("CTRL-C (mapped)", function()
it('interrupts :sleep', function()
command('nnoremap <C-C> <Nop>')
feed(':sleep 100<CR>')
- poke_eventloop() -- wait for :sleep to start
+ poke_eventloop() -- wait for :sleep to start
feed('foo<C-C>')
- poke_eventloop() -- wait for input buffer to be flushed
+ poke_eventloop() -- wait for input buffer to be flushed
feed('i')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
-- INSERT -- |
]])
end)
@@ -76,16 +75,13 @@ describe("CTRL-C (mapped)", function()
command('nnoremap <C-C> <Nop>')
command('nmap <F2> <Ignore><F2>')
feed('<F2>')
- sleep(10) -- wait for the key to enter typeahead
+ sleep(10) -- wait for the key to enter typeahead
feed('foo<C-C>')
- poke_eventloop() -- wait for input buffer to be flushed
+ poke_eventloop() -- wait for input buffer to be flushed
feed('i')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
-- INSERT -- |
]])
end)
diff --git a/test/functional/editor/fold_spec.lua b/test/functional/editor/fold_spec.lua
index 424ce839a2..7950f6aea4 100644
--- a/test/functional/editor/fold_spec.lua
+++ b/test/functional/editor/fold_spec.lua
@@ -2,19 +2,24 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local insert = helpers.insert
+local exec = helpers.exec
local feed = helpers.feed
local expect = helpers.expect
local command = helpers.command
-local funcs = helpers.funcs
+local fn = helpers.fn
local eq = helpers.eq
local neq = helpers.neq
-describe('Folds', function()
+describe('Folding', function()
local tempfname = 'Xtest-fold.txt'
setup(clear)
- before_each(function() command('bwipe! | new') end)
- after_each(function() os.remove(tempfname) end)
+ before_each(function()
+ command('bwipe! | new')
+ end)
+ after_each(function()
+ os.remove(tempfname)
+ end)
it('manual folding adjusts with filter', function()
insert([[
@@ -71,8 +76,8 @@ describe('Folds', function()
local function get_folds()
local rettab = {}
- for i = 1, funcs.line('$') do
- table.insert(rettab, funcs.foldlevel(i))
+ for i = 1, fn.line('$') do
+ table.insert(rettab, fn.foldlevel(i))
end
return rettab
end
@@ -94,7 +99,8 @@ describe('Folds', function()
end
it('neither closes nor corrupts folds', function()
- test_move_indent([[
+ test_move_indent(
+ [[
a
a
a
@@ -112,7 +118,9 @@ a
a
a
a
- a]], '7,12m0')
+ a]],
+ '7,12m0'
+ )
expect([[
a
a
@@ -133,25 +141,26 @@ a
a
a]])
-- lines are not closed, folds are correct
- for i = 1,funcs.line('$') do
- eq(-1, funcs.foldclosed(i))
+ for i = 1, fn.line('$') do
+ eq(-1, fn.foldclosed(i))
if i == 1 or i == 7 or i == 13 then
- eq(0, funcs.foldlevel(i))
+ eq(0, fn.foldlevel(i))
elseif i == 4 then
- eq(2, funcs.foldlevel(i))
+ eq(2, fn.foldlevel(i))
else
- eq(1, funcs.foldlevel(i))
+ eq(1, fn.foldlevel(i))
end
end
-- folds are not corrupted
feed('zM')
- eq(6, funcs.foldclosedend(2))
- eq(12, funcs.foldclosedend(8))
- eq(18, funcs.foldclosedend(14))
+ eq(6, fn.foldclosedend(2))
+ eq(12, fn.foldclosedend(8))
+ eq(18, fn.foldclosedend(14))
end)
it("doesn't split a fold when the move is within it", function()
- test_move_indent([[
+ test_move_indent(
+ [[
a
a
a
@@ -161,24 +170,30 @@ a
a
a
a
-a]], '5m6')
- eq({0, 1, 1, 2, 2, 2, 2, 1, 1, 0}, get_folds())
+a]],
+ '5m6'
+ )
+ eq({ 0, 1, 1, 2, 2, 2, 2, 1, 1, 0 }, get_folds())
end)
it('truncates folds that end in the moved range', function()
- test_move_indent([[
+ test_move_indent(
+ [[
a
a
a
a
a
a
-a]], '4,5m6')
- eq({0, 1, 2, 0, 0, 0, 0}, get_folds())
+a]],
+ '4,5m6'
+ )
+ eq({ 0, 1, 2, 0, 0, 0, 0 }, get_folds())
end)
it('moves folds that start between moved range and destination', function()
- test_move_indent([[
+ test_move_indent(
+ [[
a
a
a
@@ -191,12 +206,15 @@ a
a
a
a
- a]], '3,4m$')
- eq({0, 1, 1, 0, 0, 1, 2, 1, 0, 0, 1, 0, 0}, get_folds())
+ a]],
+ '3,4m$'
+ )
+ eq({ 0, 1, 1, 0, 0, 1, 2, 1, 0, 0, 1, 0, 0 }, get_folds())
end)
it('does not affect folds outside changed lines', function()
- test_move_indent([[
+ test_move_indent(
+ [[
a
a
a
@@ -205,12 +223,15 @@ a
a
a
a
- a]], '4m5')
- eq({1, 1, 1, 0, 0, 0, 1, 1, 1}, get_folds())
+ a]],
+ '4m5'
+ )
+ eq({ 1, 1, 1, 0, 0, 0, 1, 1, 1 }, get_folds())
end)
it('moves and truncates folds that start in moved range', function()
- test_move_indent([[
+ test_move_indent(
+ [[
a
a
a
@@ -220,34 +241,43 @@ a
a
a
a
-a]], '1,3m7')
- eq({0, 0, 0, 0, 0, 1, 2, 0, 0, 0}, get_folds())
+a]],
+ '1,3m7'
+ )
+ eq({ 0, 0, 0, 0, 0, 1, 2, 0, 0, 0 }, get_folds())
end)
it('breaks a fold when moving text into it', function()
- test_move_indent([[
+ test_move_indent(
+ [[
a
a
a
a
a
a
-a]], '$m4')
- eq({0, 1, 2, 2, 0, 0, 0}, get_folds())
+a]],
+ '$m4'
+ )
+ eq({ 0, 1, 2, 2, 0, 0, 0 }, get_folds())
end)
it('adjusts correctly when moving a range backwards', function()
- test_move_indent([[
+ test_move_indent(
+ [[
a
a
a
a
-a]], '2,3m0')
- eq({1, 2, 0, 0, 0}, get_folds())
+a]],
+ '2,3m0'
+ )
+ eq({ 1, 2, 0, 0, 0 }, get_folds())
end)
it('handles shifting all remaining folds', function()
- test_move_indent([[
+ test_move_indent(
+ [[
a
a
a
@@ -262,18 +292,23 @@ a]], '2,3m0')
a
a
a
-a]], '13m7')
- eq({1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0}, get_folds())
+a]],
+ '13m7'
+ )
+ eq({ 1, 2, 2, 2, 1, 2, 2, 1, 1, 1, 2, 2, 2, 1, 0 }, get_folds())
end)
end)
it('updates correctly on :read', function()
-- luacheck: ignore 621
- helpers.write_file(tempfname, [[
+ helpers.write_file(
+ tempfname,
+ [[
a
- a]])
+ a]]
+ )
insert([[
a
a
@@ -295,14 +330,14 @@ a]], '13m7')
a
a
]])
- for i = 1,2 do
- eq(1, funcs.foldlevel(i))
+ for i = 1, 2 do
+ eq(1, fn.foldlevel(i))
end
- for i = 3,5 do
- eq(0, funcs.foldlevel(i))
+ for i = 3, 5 do
+ eq(0, fn.foldlevel(i))
end
- for i = 6,8 do
- eq(1, funcs.foldlevel(i))
+ for i = 6, 8 do
+ eq(1, fn.foldlevel(i))
end
end)
@@ -320,7 +355,7 @@ a]], '13m7')
]])
command('setlocal foldmethod=indent')
command('3,5d')
- eq(5, funcs.foldclosedend(1))
+ eq(5, fn.foldclosedend(1))
end)
it("doesn't combine folds that have a specified end", function()
@@ -337,7 +372,7 @@ a]], '13m7')
command('setlocal foldmethod=marker')
command('3,5d')
command('%foldclose')
- eq(2, funcs.foldclosedend(1))
+ eq(2, fn.foldclosedend(1))
end)
it('splits folds according to >N and <N with foldexpr', function()
@@ -356,7 +391,9 @@ a]], '13m7')
return 0
endfunction
]])
- helpers.write_file(tempfname, [[
+ helpers.write_file(
+ tempfname,
+ [[
b
b
a
@@ -364,7 +401,8 @@ a]], '13m7')
d
a
a
- c]])
+ c]]
+ )
insert([[
a
a
@@ -378,20 +416,56 @@ a]], '13m7')
command('foldopen')
command('read ' .. tempfname)
command('%foldclose')
- eq(2, funcs.foldclosedend(1))
- eq(0, funcs.foldlevel(3))
- eq(0, funcs.foldlevel(4))
- eq(6, funcs.foldclosedend(5))
- eq(10, funcs.foldclosedend(7))
- eq(14, funcs.foldclosedend(11))
+ eq(2, fn.foldclosedend(1))
+ eq(0, fn.foldlevel(3))
+ eq(0, fn.foldlevel(4))
+ eq(6, fn.foldclosedend(5))
+ eq(10, fn.foldclosedend(7))
+ eq(14, fn.foldclosedend(11))
+ end)
+
+ it('fdm=expr works correctly with :move #18668', function()
+ exec([[
+ set foldmethod=expr foldexpr=indent(v:lnum)
+ let content = ['', '', 'Line1', ' Line2', ' Line3',
+ \ 'Line4', ' Line5', ' Line6',
+ \ 'Line7', ' Line8', ' Line9']
+ call append(0, content)
+ normal! zM
+ call cursor(4, 1)
+ move 2
+ move 1
+ ]])
+ expect([[
+
+ Line2
+ Line3
+
+ Line1
+ Line4
+ Line5
+ Line6
+ Line7
+ Line8
+ Line9
+ ]])
+ eq(0, fn.foldlevel(1))
+ eq(3, fn.foldclosedend(2))
+ eq(0, fn.foldlevel(4))
+ eq(0, fn.foldlevel(5))
+ eq(0, fn.foldlevel(6))
+ eq(8, fn.foldclosedend(7))
+ eq(0, fn.foldlevel(9))
+ eq(11, fn.foldclosedend(10))
+ eq(0, fn.foldlevel(12))
end)
it('no folds remain if :delete makes buffer empty #19671', function()
command('setlocal foldmethod=manual')
- funcs.setline(1, {'foo', 'bar', 'baz'})
+ fn.setline(1, { 'foo', 'bar', 'baz' })
command('2,3fold')
command('%delete')
- eq(0, funcs.foldlevel(1))
+ eq(0, fn.foldlevel(1))
end)
it('multibyte fold markers work #20438', function()
@@ -405,21 +479,21 @@ a]], '13m7')
bbbbb/*«*/
bbbbb
bbbbb/*»*/]])
- eq(1, funcs.foldlevel(1))
+ eq(1, fn.foldlevel(1))
end)
- it('updates correctly with indent method and visual blockwise insertion #22898', function()
+ it('fdm=indent updates correctly with visual blockwise insertion #22898', function()
insert([[
a
b
]])
command('setlocal foldmethod=indent shiftwidth=2')
feed('gg0<C-v>jI <Esc>') -- indent both lines using visual blockwise mode
- eq(1, funcs.foldlevel(1))
- eq(1, funcs.foldlevel(2))
+ eq(1, fn.foldlevel(1))
+ eq(1, fn.foldlevel(2))
end)
- it("doesn't open folds with indent method when inserting lower foldlevel line", function()
+ it("fdm=indent doesn't open folds when inserting lower foldlevel line", function()
insert([[
insert an unindented line under this line
keep the lines under this line folded
@@ -427,22 +501,22 @@ a]], '13m7')
keep this line folded 2
]])
command('set foldmethod=indent shiftwidth=2 noautoindent')
- eq(1, funcs.foldlevel(1))
- eq(1, funcs.foldlevel(2))
- eq(2, funcs.foldlevel(3))
- eq(2, funcs.foldlevel(4))
+ eq(1, fn.foldlevel(1))
+ eq(1, fn.foldlevel(2))
+ eq(2, fn.foldlevel(3))
+ eq(2, fn.foldlevel(4))
feed('zo') -- open the outer fold
- neq(-1, funcs.foldclosed(3)) -- make sure the inner fold is not open
+ neq(-1, fn.foldclosed(3)) -- make sure the inner fold is not open
feed('gg0oa<Esc>') -- insert unindented line
- eq(1, funcs.foldlevel(1)) --| insert an unindented line under this line
- eq(0, funcs.foldlevel(2)) --|a
- eq(1, funcs.foldlevel(3)) --| keep the lines under this line folded
- eq(2, funcs.foldlevel(4)) --| keep this line folded 1
- eq(2, funcs.foldlevel(5)) --| keep this line folded 2
+ eq(1, fn.foldlevel(1)) --| insert an unindented line under this line
+ eq(0, fn.foldlevel(2)) --|a
+ eq(1, fn.foldlevel(3)) --| keep the lines under this line folded
+ eq(2, fn.foldlevel(4)) --| keep this line folded 1
+ eq(2, fn.foldlevel(5)) --| keep this line folded 2
- neq(-1, funcs.foldclosed(4)) -- make sure the inner fold is still not open
+ neq(-1, fn.foldclosed(4)) -- make sure the inner fold is still not open
end)
end)
diff --git a/test/functional/editor/jump_spec.lua b/test/functional/editor/jump_spec.lua
index dc056cb252..fe03d82164 100644
--- a/test/functional/editor/jump_spec.lua
+++ b/test/functional/editor/jump_spec.lua
@@ -3,16 +3,17 @@ local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local command = helpers.command
+local dedent = helpers.dedent
local eq = helpers.eq
-local funcs = helpers.funcs
+local fn = helpers.fn
local feed = helpers.feed
local exec_capture = helpers.exec_capture
local write_file = helpers.write_file
-local curbufmeths = helpers.curbufmeths
+local api = helpers.api
describe('jumplist', function()
local fname1 = 'Xtest-functional-normal-jump'
- local fname2 = fname1..'2'
+ local fname2 = fname1 .. '2'
before_each(clear)
after_each(function()
os.remove(fname1)
@@ -20,33 +21,33 @@ describe('jumplist', function()
end)
it('does not add a new entry on startup', function()
- eq('\n jump line col file/text\n>', funcs.execute('jumps'))
+ eq('\n jump line col file/text\n>', fn.execute('jumps'))
end)
it('does not require two <C-O> strokes to jump back', function()
write_file(fname1, 'first file contents')
write_file(fname2, 'second file contents')
- command('args '..fname1..' '..fname2)
- local buf1 = funcs.bufnr(fname1)
- local buf2 = funcs.bufnr(fname2)
+ command('args ' .. fname1 .. ' ' .. fname2)
+ local buf1 = fn.bufnr(fname1)
+ local buf2 = fn.bufnr(fname2)
command('next')
feed('<C-O>')
- eq(buf1, funcs.bufnr('%'))
+ eq(buf1, fn.bufnr('%'))
command('first')
command('snext')
feed('<C-O>')
- eq(buf1, funcs.bufnr('%'))
+ eq(buf1, fn.bufnr('%'))
feed('<C-I>')
- eq(buf2, funcs.bufnr('%'))
+ eq(buf2, fn.bufnr('%'))
feed('<C-O>')
- eq(buf1, funcs.bufnr('%'))
+ eq(buf1, fn.bufnr('%'))
- command('drop '..fname2)
+ command('drop ' .. fname2)
feed('<C-O>')
- eq(buf1, funcs.bufnr('%'))
+ eq(buf1, fn.bufnr('%'))
end)
it('<C-O> scrolls cursor halfway when switching buffer #25763', function()
@@ -56,11 +57,12 @@ describe('jumplist', function()
local screen = Screen.new(5, 25)
screen:attach()
command('set number')
- command('edit '..fname1)
+ command('edit ' .. fname1)
feed('35gg')
- command('edit '..fname2)
+ command('edit ' .. fname2)
feed('<C-O>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: 24 }foobar |
{1: 25 }foobar |
{1: 26 }foobar |
@@ -86,9 +88,11 @@ describe('jumplist', function()
{1: 46 }foobar |
{1: 47 }foobar |
|
- ]], attr_ids={
- [1] = {foreground = Screen.colors.Brown};
- }}
+ ]],
+ attr_ids = {
+ [1] = { foreground = Screen.colors.Brown },
+ },
+ }
end)
end)
@@ -98,9 +102,8 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
feed(':clearjumps<cr>')
-- Add lines so that we have locations to jump to.
- for i = 1,101,1
- do
- feed('iLine ' .. i .. '<cr><esc>')
+ for i = 1, 101, 1 do
+ feed('iLine ' .. i .. '<cr><esc>')
end
-- Jump around to add some locations to the jump list.
@@ -115,82 +118,215 @@ describe("jumpoptions=stack behaves like 'tagstack'", function()
end)
after_each(function()
- feed('set jumpoptions=')
+ feed('set jumpoptions=')
end)
it('discards the tail when navigating from the middle', function()
feed('<C-O>')
feed('<C-O>')
- eq( ''
- .. ' jump line col file/text\n'
- .. ' 4 102 0 \n'
- .. ' 3 1 0 Line 1\n'
- .. ' 2 10 0 Line 10\n'
- .. ' 1 20 0 Line 20\n'
- .. '> 0 30 0 Line 30\n'
- .. ' 1 40 0 Line 40\n'
- .. ' 2 50 0 Line 50',
- exec_capture('jumps'))
+ eq(
+ ''
+ .. ' jump line col file/text\n'
+ .. ' 4 102 0 \n'
+ .. ' 3 1 0 Line 1\n'
+ .. ' 2 10 0 Line 10\n'
+ .. ' 1 20 0 Line 20\n'
+ .. '> 0 30 0 Line 30\n'
+ .. ' 1 40 0 Line 40\n'
+ .. ' 2 50 0 Line 50',
+ exec_capture('jumps')
+ )
feed('90gg')
- eq( ''
- .. ' jump line col file/text\n'
- .. ' 5 102 0 \n'
- .. ' 4 1 0 Line 1\n'
- .. ' 3 10 0 Line 10\n'
- .. ' 2 20 0 Line 20\n'
- .. ' 1 30 0 Line 30\n'
- .. '>',
- exec_capture('jumps'))
+ eq(
+ ''
+ .. ' jump line col file/text\n'
+ .. ' 5 102 0 \n'
+ .. ' 4 1 0 Line 1\n'
+ .. ' 3 10 0 Line 10\n'
+ .. ' 2 20 0 Line 20\n'
+ .. ' 1 30 0 Line 30\n'
+ .. '>',
+ exec_capture('jumps')
+ )
end)
it('does not add the same location twice adjacently', function()
feed('60gg')
feed('60gg')
- eq( ''
- .. ' jump line col file/text\n'
- .. ' 7 102 0 \n'
- .. ' 6 1 0 Line 1\n'
- .. ' 5 10 0 Line 10\n'
- .. ' 4 20 0 Line 20\n'
- .. ' 3 30 0 Line 30\n'
- .. ' 2 40 0 Line 40\n'
- .. ' 1 50 0 Line 50\n'
- .. '>',
- exec_capture('jumps'))
+ eq(
+ ''
+ .. ' jump line col file/text\n'
+ .. ' 7 102 0 \n'
+ .. ' 6 1 0 Line 1\n'
+ .. ' 5 10 0 Line 10\n'
+ .. ' 4 20 0 Line 20\n'
+ .. ' 3 30 0 Line 30\n'
+ .. ' 2 40 0 Line 40\n'
+ .. ' 1 50 0 Line 50\n'
+ .. '>',
+ exec_capture('jumps')
+ )
end)
it('does add the same location twice nonadjacently', function()
feed('10gg')
feed('20gg')
- eq( ''
- .. ' jump line col file/text\n'
- .. ' 8 102 0 \n'
- .. ' 7 1 0 Line 1\n'
- .. ' 6 10 0 Line 10\n'
- .. ' 5 20 0 Line 20\n'
- .. ' 4 30 0 Line 30\n'
- .. ' 3 40 0 Line 40\n'
- .. ' 2 50 0 Line 50\n'
- .. ' 1 10 0 Line 10\n'
- .. '>',
- exec_capture('jumps'))
+ eq(
+ ''
+ .. ' jump line col file/text\n'
+ .. ' 8 102 0 \n'
+ .. ' 7 1 0 Line 1\n'
+ .. ' 6 10 0 Line 10\n'
+ .. ' 5 20 0 Line 20\n'
+ .. ' 4 30 0 Line 30\n'
+ .. ' 3 40 0 Line 40\n'
+ .. ' 2 50 0 Line 50\n'
+ .. ' 1 10 0 Line 10\n'
+ .. '>',
+ exec_capture('jumps')
+ )
end)
end)
-describe("jumpoptions=view", function()
+describe('buffer deletion', function()
+ local base_file = 'Xtest-functional-buffer-deletion'
+ local file1 = base_file .. '1'
+ local file2 = base_file .. '2'
+ local file3 = base_file .. '3'
+ local base_content = 'text'
+ local content1 = base_content .. '1'
+ local content2 = base_content .. '2'
+ local content3 = base_content .. '3'
+
+ local function format_jumplist(input)
+ return dedent(input)
+ :gsub('%{file1%}', file1)
+ :gsub('%{file2%}', file2)
+ :gsub('%{file3%}', file3)
+ :gsub('%{content1%}', content1)
+ :gsub('%{content2%}', content2)
+ :gsub('%{content3%}', content3)
+ end
+
+ before_each(function()
+ clear()
+ command('clearjumps')
+
+ write_file(file1, content1, false, false)
+ write_file(file2, content2, false, false)
+ write_file(file3, content3, false, false)
+
+ command('edit ' .. file1)
+ command('edit ' .. file2)
+ command('edit ' .. file3)
+ end)
+
+ it('deletes jump list entries when the current buffer is deleted', function()
+ command('edit ' .. file1)
+
+ eq(
+ format_jumplist([[
+ jump line col file/text
+ 3 1 0 {content1}
+ 2 1 0 {file2}
+ 1 1 0 {file3}
+ >]]),
+ exec_capture('jumps')
+ )
+
+ command('bwipeout')
+
+ eq(
+ format_jumplist([[
+ jump line col file/text
+ 1 1 0 {file2}
+ > 0 1 0 {content3}]]),
+ exec_capture('jumps')
+ )
+ end)
+
+ it('deletes jump list entries when another buffer is deleted', function()
+ eq(
+ format_jumplist([[
+ jump line col file/text
+ 2 1 0 {file1}
+ 1 1 0 {file2}
+ >]]),
+ exec_capture('jumps')
+ )
+
+ command('bwipeout ' .. file2)
+
+ eq(
+ format_jumplist([[
+ jump line col file/text
+ 1 1 0 {file1}
+ >]]),
+ exec_capture('jumps')
+ )
+ end)
+
+ it('sets the correct jump index when the current buffer is deleted', function()
+ feed('<C-O>')
+
+ eq(
+ format_jumplist([[
+ jump line col file/text
+ 1 1 0 {file1}
+ > 0 1 0 {content2}
+ 1 1 0 {file3}]]),
+ exec_capture('jumps')
+ )
+
+ command('bw')
+
+ eq(
+ format_jumplist([[
+ jump line col file/text
+ 1 1 0 {file1}
+ > 0 1 0 {content3}]]),
+ exec_capture('jumps')
+ )
+ end)
+
+ it('sets the correct jump index when the another buffer is deleted', function()
+ feed('<C-O>')
+
+ eq(
+ format_jumplist([[
+ jump line col file/text
+ 1 1 0 {file1}
+ > 0 1 0 {content2}
+ 1 1 0 {file3}]]),
+ exec_capture('jumps')
+ )
+
+ command('bwipeout ' .. file1)
+
+ eq(
+ format_jumplist([[
+ jump line col file/text
+ > 0 1 0 {content2}
+ 1 1 0 {file3}]]),
+ exec_capture('jumps')
+ )
+ end)
+end)
+
+describe('jumpoptions=view', function()
local file1 = 'Xtestfile-functional-editor-jumps'
local file2 = 'Xtestfile-functional-editor-jumps-2'
local function content()
local c = {}
- for i=1,30 do
- c[i] = i .. " line"
+ for i = 1, 30 do
+ c[i] = i .. ' line'
end
- return table.concat(c, "\n")
+ return table.concat(c, '\n')
end
before_each(function()
clear()
@@ -206,9 +342,9 @@ describe("jumpoptions=view", function()
it('restores the view', function()
local screen = Screen.new(5, 8)
screen:attach()
- command("edit " .. file1)
- feed("12Gztj")
- feed("gg<C-o>")
+ command('edit ' .. file1)
+ feed('12Gztj')
+ feed('gg<C-o>')
screen:expect([[
12 line |
^13 line |
@@ -224,10 +360,10 @@ describe("jumpoptions=view", function()
it('restores the view across files', function()
local screen = Screen.new(5, 5)
screen:attach()
- command("args " .. file1 .. " " .. file2)
- feed("12Gzt")
- command("next")
- feed("G")
+ command('args ' .. file1 .. ' ' .. file2)
+ feed('12Gzt')
+ command('next')
+ feed('G')
screen:expect([[
27 line |
28 line |
@@ -235,7 +371,7 @@ describe("jumpoptions=view", function()
^30 line |
|
]])
- feed("<C-o><C-o>")
+ feed('<C-o><C-o>')
screen:expect([[
^12 line |
13 line |
@@ -248,10 +384,10 @@ describe("jumpoptions=view", function()
it('restores the view across files with <C-^>', function()
local screen = Screen.new(5, 5)
screen:attach()
- command("args " .. file1 .. " " .. file2)
- feed("12Gzt")
- command("next")
- feed("G")
+ command('args ' .. file1 .. ' ' .. file2)
+ feed('12Gzt')
+ command('next')
+ feed('G')
screen:expect([[
27 line |
28 line |
@@ -259,7 +395,7 @@ describe("jumpoptions=view", function()
^30 line |
|
]])
- feed("<C-^>")
+ feed('<C-^>')
screen:expect([[
^12 line |
13 line |
@@ -269,19 +405,19 @@ describe("jumpoptions=view", function()
]])
end)
- it('falls back to standard behavior when view can\'t be recovered', function()
+ it("falls back to standard behavior when view can't be recovered", function()
local screen = Screen.new(5, 8)
screen:attach()
- command("edit " .. file1)
- feed("7GzbG")
- curbufmeths.set_lines(0, 2, true, {})
+ command('edit ' .. file1)
+ feed('7GzbG')
+ api.nvim_buf_set_lines(0, 0, 2, true, {})
-- Move to line 7, and set it as the last line visible on the view with zb, meaning to recover
-- the view it needs to put the cursor 7 lines from the top line. Then go to the end of the
-- file, delete 2 lines before line 7, meaning the jump/mark is moved 2 lines up to line 5.
-- Therefore when trying to jump back to it it's not possible to set a 7 line offset from the
-- mark position to the top line, since there's only 5 lines from the mark position to line 0.
-- Therefore falls back to standard behavior which is centering the view/line.
- feed("<C-o>")
+ feed('<C-o>')
screen:expect([[
4 line |
5 line |
diff --git a/test/functional/editor/lang_spec.lua b/test/functional/editor/lang_spec.lua
index 24d1262f5f..ee7cfac057 100644
--- a/test/functional/editor/lang_spec.lua
+++ b/test/functional/editor/lang_spec.lua
@@ -9,11 +9,11 @@ describe('gu and gU', function()
it('works in any locale with default casemap', function()
eq('internal,keepascii', eval('&casemap'))
- insert("iI")
- feed("VgU")
- expect("II")
- feed("Vgu")
- expect("ii")
+ insert('iI')
+ feed('VgU')
+ expect('II')
+ feed('Vgu')
+ expect('ii')
end)
describe('works in Turkish locale', function()
@@ -21,7 +21,7 @@ describe('gu and gU', function()
local err = exc_exec('lang ctype tr_TR.UTF-8')
if err ~= 0 then
- pending("Locale tr_TR.UTF-8 not supported", function() end)
+ pending('Locale tr_TR.UTF-8 not supported', function() end)
return
end
@@ -32,29 +32,29 @@ describe('gu and gU', function()
it('with default casemap', function()
eq('internal,keepascii', eval('&casemap'))
-- expect ASCII behavior
- insert("iI")
- feed("VgU")
- expect("II")
- feed("Vgu")
- expect("ii")
+ insert('iI')
+ feed('VgU')
+ expect('II')
+ feed('Vgu')
+ expect('ii')
end)
it('with casemap=""', function()
command('set casemap=')
-- expect either Turkish locale behavior or ASCII behavior
local iupper = eval("toupper('i')")
- if iupper == "İ" then
- insert("iI")
- feed("VgU")
- expect("İI")
- feed("Vgu")
- expect("iı")
- elseif iupper == "I" then
- insert("iI")
- feed("VgU")
- expect("II")
- feed("Vgu")
- expect("ii")
+ if iupper == 'İ' then
+ insert('iI')
+ feed('VgU')
+ expect('İI')
+ feed('Vgu')
+ expect('iı')
+ elseif iupper == 'I' then
+ insert('iI')
+ feed('VgU')
+ expect('II')
+ feed('Vgu')
+ expect('ii')
else
error("expected toupper('i') to be either 'I' or 'İ'")
end
diff --git a/test/functional/editor/langmap_spec.lua b/test/functional/editor/langmap_spec.lua
index b1070ecddc..b2a4b21a89 100644
--- a/test/functional/editor/langmap_spec.lua
+++ b/test/functional/editor/langmap_spec.lua
@@ -4,7 +4,7 @@ local eq, neq, call = helpers.eq, helpers.neq, helpers.call
local eval, feed, clear = helpers.eval, helpers.feed, helpers.clear
local command, insert, expect = helpers.command, helpers.insert, helpers.expect
local feed_command = helpers.feed_command
-local curwin = helpers.curwin
+local curwin = helpers.api.nvim_get_current_win
describe("'langmap'", function()
before_each(function()
@@ -14,13 +14,13 @@ describe("'langmap'", function()
feed('gg0')
end)
- it("converts keys in normal mode", function()
+ it('converts keys in normal mode', function()
feed('ix')
expect('iii ww')
feed('whello<esc>')
expect('iii helloww')
end)
- it("gives characters that are mapped by :nmap.", function()
+ it('gives characters that are mapped by :nmap.', function()
command('map i 0x')
feed('w')
expect('ii www')
@@ -32,20 +32,18 @@ describe("'langmap'", function()
it("'langnoremap' is by default ON", function()
eq(1, eval('&langnoremap'))
end)
- it("Results of maps are not converted when 'langnoremap' ON.",
- function()
+ it("Results of maps are not converted when 'langnoremap' ON.", function()
command('nmap x i')
feed('xdl<esc>')
expect('dliii www')
end)
- it("applies when deciding whether to map recursively", function()
+ it('applies when deciding whether to map recursively', function()
command('nmap l i')
command('nmap w j')
feed('ll')
expect('liii www')
end)
- it("does not stop applying 'langmap' on first character of a mapping",
- function()
+ it("does not stop applying 'langmap' on first character of a mapping", function()
command('1t1')
command('1t1')
command('goto 1')
@@ -56,8 +54,7 @@ describe("'langmap'", function()
iii www
ihelloii www]])
end)
- it("Results of maps are converted when 'langnoremap' OFF.",
- function()
+ it("Results of maps are converted when 'langnoremap' OFF.", function()
command('set nolangnoremap')
command('nmap x i')
feed('xdl<esc>')
@@ -65,8 +62,7 @@ describe("'langmap'", function()
end)
end)
-- e.g. CTRL-W_j , mj , 'j and "jp
- it('conversions are applied to keys in middle of command',
- function()
+ it('conversions are applied to keys in middle of command', function()
-- Works in middle of window command
feed('<C-w>s')
local origwin = curwin()
@@ -74,12 +70,12 @@ describe("'langmap'", function()
neq(origwin, curwin())
-- Works when setting a mark
feed('yy3p3gg0mwgg0mi')
- eq({0, 3, 1, 0}, call('getpos', "'i"))
- eq({0, 1, 1, 0}, call('getpos', "'w"))
+ eq({ 0, 3, 1, 0 }, call('getpos', "'i"))
+ eq({ 0, 1, 1, 0 }, call('getpos', "'w"))
feed('3dd')
-- Works when moving to a mark
feed("'i")
- eq({0, 1, 1, 0}, call('getpos', '.'))
+ eq({ 0, 1, 1, 0 }, call('getpos', '.'))
-- Works when selecting a register
feed('qillqqwhhq')
eq('hh', eval('@i'))
@@ -193,8 +189,7 @@ describe("'langmap'", function()
eq(1, eval('gotten_one'))
end)
end)
- it('conversions are not applied during setreg()',
- function()
+ it('conversions are not applied during setreg()', function()
call('setreg', 'i', 'ww')
eq('ww', eval('@i'))
end)
@@ -214,12 +209,18 @@ describe("'langmap'", function()
end)
local function testrecording(command_string, expect_string, setup_function, expect_macro)
- if setup_function then setup_function() end
+ if setup_function then
+ setup_function()
+ end
feed('qa' .. command_string .. 'q')
expect(expect_string)
- eq(expect_macro or helpers.funcs.nvim_replace_termcodes(command_string, true, true, true),
- eval('@a'))
- if setup_function then setup_function() end
+ eq(
+ expect_macro or helpers.fn.nvim_replace_termcodes(command_string, true, true, true),
+ eval('@a')
+ )
+ if setup_function then
+ setup_function()
+ end
-- n.b. may need nvim_replace_termcodes() here.
feed('@a')
expect(expect_string)
@@ -276,5 +277,4 @@ describe("'langmap'", function()
testrecording('<C-w>', 'whello', local_setup, eval([["\<*C-w>"]]))
testrecording('<C-i>', 'ihello', local_setup, eval([["\<*C-i>"]]))
end)
-
end)
diff --git a/test/functional/editor/macro_spec.lua b/test/functional/editor/macro_spec.lua
index 53be7dcc62..c97befdf07 100644
--- a/test/functional/editor/macro_spec.lua
+++ b/test/functional/editor/macro_spec.lua
@@ -6,14 +6,14 @@ local feed = helpers.feed
local clear = helpers.clear
local expect = helpers.expect
local command = helpers.command
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local insert = helpers.insert
-local curbufmeths = helpers.curbufmeths
-
-before_each(clear)
describe('macros', function()
+ before_each(function()
+ clear({ args_rm = { '--cmd' } })
+ end)
it('can be recorded and replayed', function()
feed('qiahello<esc>q')
expect('hello')
@@ -40,31 +40,100 @@ hello]]
feed [[gg]]
feed [[qqAFOO<esc>q]]
- eq({'helloFOO', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false))
+ eq({ 'helloFOO', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ feed [[Q]]
+ eq({ 'helloFOOFOO', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ feed [[G3Q]]
+ eq({ 'helloFOOFOO', 'hello', 'helloFOOFOOFOO' }, api.nvim_buf_get_lines(0, 0, -1, false))
- feed[[Q]]
- eq({'helloFOOFOO', 'hello', 'hello'}, curbufmeths.get_lines(0, -1, false))
+ feed [[ggV3jQ]]
+ eq(
+ { 'helloFOOFOOFOO', 'helloFOO', 'helloFOOFOOFOOFOO' },
+ api.nvim_buf_get_lines(0, 0, -1, false)
+ )
+ end)
- feed[[G3Q]]
- eq({'helloFOOFOO', 'hello', 'helloFOOFOOFOO'}, curbufmeths.get_lines(0, -1, false))
+ it('can be replayed with @', function()
+ insert [[hello
+hello
+hello]]
+ feed [[gg]]
+
+ feed [[qqAFOO<esc>q]]
+ eq({ 'helloFOO', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ feed [[Q]]
+ eq({ 'helloFOOFOO', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ feed [[G3@@]]
+ eq({ 'helloFOOFOO', 'hello', 'helloFOOFOOFOO' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ feed [[ggV2j@@]]
+ eq(
+ { 'helloFOOFOOFOO', 'helloFOO', 'helloFOOFOOFOOFOO' },
+ api.nvim_buf_get_lines(0, 0, -1, false)
+ )
+ end)
+
+ it('can be replayed with @q and @w', function()
+ insert [[hello
+hello
+hello]]
+ feed [[gg]]
+
+ feed [[qqAFOO<esc>qu]]
+ eq({ 'hello', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ feed [[qwA123<esc>qu]]
+ eq({ 'hello', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ feed [[V3j@q]]
+ eq({ 'helloFOO', 'helloFOO', 'helloFOO' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ feed [[gg]]
+ feed [[Vj@w]]
+ eq({ 'helloFOO123', 'helloFOO123', 'helloFOO' }, api.nvim_buf_get_lines(0, 0, -1, false))
+ end)
+
+ it('can be replayed with @q and @w visual-block', function()
+ insert [[hello
+hello
+hello]]
+ feed [[gg]]
+
+ feed [[qqAFOO<esc>qu]]
+ eq({ 'hello', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ feed [[qwA123<esc>qu]]
+ eq({ 'hello', 'hello', 'hello' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ feed [[<C-v>3j@q]]
+ eq({ 'helloFOO', 'helloFOO', 'helloFOO' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ feed [[gg]]
+ feed [[<C-v>j@w]]
+ eq({ 'helloFOO123', 'helloFOO123', 'helloFOO' }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
end)
describe('immediately after a macro has finished executing,', function()
before_each(function()
+ clear()
command([[let @a = 'gg0']])
end)
describe('reg_executing() from RPC returns an empty string', function()
it('if the macro does not end with a <Nop> mapping', function()
feed('@a')
- eq('', funcs.reg_executing())
+ eq('', fn.reg_executing())
end)
it('if the macro ends with a <Nop> mapping', function()
command('nnoremap 0 <Nop>')
feed('@a')
- eq('', funcs.reg_executing())
+ eq('', fn.reg_executing())
end)
end)
@@ -74,16 +143,16 @@ describe('immediately after a macro has finished executing,', function()
end)
it('if the macro does not end with a <Nop> mapping', function()
- feed('@asq') -- "q" from "s" mapping should start recording a macro instead of being no-op
- eq({mode = 'n', blocking = false}, meths.get_mode())
+ feed('@asq') -- "q" from "s" mapping should start recording a macro instead of being no-op
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
expect('')
eq('', eval('@a'))
end)
it('if the macro ends with a <Nop> mapping', function()
command('nnoremap 0 <Nop>')
- feed('@asq') -- "q" from "s" mapping should start recording a macro instead of being no-op
- eq({mode = 'n', blocking = false}, meths.get_mode())
+ feed('@asq') -- "q" from "s" mapping should start recording a macro instead of being no-op
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
expect('')
eq('', eval('@a'))
end)
@@ -91,6 +160,7 @@ describe('immediately after a macro has finished executing,', function()
end)
describe('reg_recorded()', function()
+ before_each(clear)
it('returns the correct value', function()
feed [[qqyyq]]
eq('q', eval('reg_recorded()'))
diff --git a/test/functional/editor/mark_spec.lua b/test/functional/editor/mark_spec.lua
index e669d7f2bb..6b20a736c0 100644
--- a/test/functional/editor/mark_spec.lua
+++ b/test/functional/editor/mark_spec.lua
@@ -1,15 +1,16 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local meths = helpers.meths
-local curbufmeths = helpers.curbufmeths
+local api = helpers.api
local clear = helpers.clear
local command = helpers.command
-local funcs = helpers.funcs
+local fn = helpers.fn
local eq = helpers.eq
local feed = helpers.feed
local write_file = helpers.write_file
local pcall_err = helpers.pcall_err
-local cursor = function() return helpers.meths.win_get_cursor(0) end
+local cursor = function()
+ return helpers.api.nvim_win_get_cursor(0)
+end
describe('named marks', function()
local file1 = 'Xtestfile-functional-editor-marks'
@@ -24,153 +25,153 @@ describe('named marks', function()
os.remove(file2)
end)
- it("can be set", function()
- command("edit " .. file1)
- command("mark a")
- eq({1, 0}, curbufmeths.get_mark("a"))
- feed("jmb")
- eq({2, 0}, curbufmeths.get_mark("b"))
- feed("jmB")
- eq({3, 0}, curbufmeths.get_mark("B"))
- command("4kc")
- eq({4, 0}, curbufmeths.get_mark("c"))
+ it('can be set', function()
+ command('edit ' .. file1)
+ command('mark a')
+ eq({ 1, 0 }, api.nvim_buf_get_mark(0, 'a'))
+ feed('jmb')
+ eq({ 2, 0 }, api.nvim_buf_get_mark(0, 'b'))
+ feed('jmB')
+ eq({ 3, 0 }, api.nvim_buf_get_mark(0, 'B'))
+ command('4kc')
+ eq({ 4, 0 }, api.nvim_buf_get_mark(0, 'c'))
end)
- it("errors when set out of range with :mark", function()
- command("edit " .. file1)
- local err = pcall_err(helpers.exec_capture, "1000mark x")
- eq("nvim_exec2(): Vim(mark):E16: Invalid range: 1000mark x", err)
+ it('errors when set out of range with :mark', function()
+ command('edit ' .. file1)
+ local err = pcall_err(helpers.exec_capture, '1000mark x')
+ eq('nvim_exec2(): Vim(mark):E16: Invalid range: 1000mark x', err)
end)
- it("errors when set out of range with :k", function()
- command("edit " .. file1)
- local err = pcall_err(helpers.exec_capture, "1000kx")
- eq("nvim_exec2(): Vim(k):E16: Invalid range: 1000kx", err)
+ it('errors when set out of range with :k', function()
+ command('edit ' .. file1)
+ local err = pcall_err(helpers.exec_capture, '1000kx')
+ eq('nvim_exec2(): Vim(k):E16: Invalid range: 1000kx', err)
end)
- it("errors on unknown mark name with :mark", function()
- command("edit " .. file1)
- local err = pcall_err(helpers.exec_capture, "mark #")
- eq("nvim_exec2(): Vim(mark):E191: Argument must be a letter or forward/backward quote", err)
+ it('errors on unknown mark name with :mark', function()
+ command('edit ' .. file1)
+ local err = pcall_err(helpers.exec_capture, 'mark #')
+ eq('nvim_exec2(): Vim(mark):E191: Argument must be a letter or forward/backward quote', err)
end)
it("errors on unknown mark name with '", function()
- command("edit " .. file1)
+ command('edit ' .. file1)
local err = pcall_err(helpers.exec_capture, "normal! '#")
- eq("nvim_exec2(): Vim(normal):E78: Unknown mark", err)
+ eq('nvim_exec2(): Vim(normal):E78: Unknown mark', err)
end)
- it("errors on unknown mark name with `", function()
- command("edit " .. file1)
- local err = pcall_err(helpers.exec_capture, "normal! `#")
- eq("nvim_exec2(): Vim(normal):E78: Unknown mark", err)
+ it('errors on unknown mark name with `', function()
+ command('edit ' .. file1)
+ local err = pcall_err(helpers.exec_capture, 'normal! `#')
+ eq('nvim_exec2(): Vim(normal):E78: Unknown mark', err)
end)
it("errors when moving to a mark that is not set with '", function()
- command("edit " .. file1)
+ command('edit ' .. file1)
local err = pcall_err(helpers.exec_capture, "normal! 'z")
- eq("nvim_exec2(): Vim(normal):E20: Mark not set", err)
+ eq('nvim_exec2(): Vim(normal):E20: Mark not set', err)
err = pcall_err(helpers.exec_capture, "normal! '.")
- eq("nvim_exec2(): Vim(normal):E20: Mark not set", err)
+ eq('nvim_exec2(): Vim(normal):E20: Mark not set', err)
end)
- it("errors when moving to a mark that is not set with `", function()
- command("edit " .. file1)
- local err = pcall_err(helpers.exec_capture, "normal! `z")
- eq("nvim_exec2(): Vim(normal):E20: Mark not set", err)
- err = pcall_err(helpers.exec_capture, "normal! `>")
- eq("nvim_exec2(): Vim(normal):E20: Mark not set", err)
+ it('errors when moving to a mark that is not set with `', function()
+ command('edit ' .. file1)
+ local err = pcall_err(helpers.exec_capture, 'normal! `z')
+ eq('nvim_exec2(): Vim(normal):E20: Mark not set', err)
+ err = pcall_err(helpers.exec_capture, 'normal! `>')
+ eq('nvim_exec2(): Vim(normal):E20: Mark not set', err)
end)
it("errors when moving to a global mark that is not set with '", function()
- command("edit " .. file1)
+ command('edit ' .. file1)
local err = pcall_err(helpers.exec_capture, "normal! 'Z")
- eq("nvim_exec2(): Vim(normal):E20: Mark not set", err)
+ eq('nvim_exec2(): Vim(normal):E20: Mark not set', err)
end)
- it("errors when moving to a global mark that is not set with `", function()
- command("edit " .. file1)
- local err = pcall_err(helpers.exec_capture, "normal! `Z")
- eq("nvim_exec2(): Vim(normal):E20: Mark not set", err)
+ it('errors when moving to a global mark that is not set with `', function()
+ command('edit ' .. file1)
+ local err = pcall_err(helpers.exec_capture, 'normal! `Z')
+ eq('nvim_exec2(): Vim(normal):E20: Mark not set', err)
end)
it("can move to them using '", function()
- command("args " .. file1 .. " " .. file2)
- feed("j")
- feed("ma")
+ command('args ' .. file1 .. ' ' .. file2)
+ feed('j')
+ feed('ma')
feed("G'a")
- eq({2, 0}, cursor())
- feed("mA")
- command("next")
+ eq({ 2, 0 }, cursor())
+ feed('mA')
+ command('next')
feed("'A")
- eq(1, meths.get_current_buf().id)
- eq({2, 0}, cursor())
+ eq(1, api.nvim_get_current_buf())
+ eq({ 2, 0 }, cursor())
end)
- it("can move to them using `", function()
- command("args " .. file1 .. " " .. file2)
- feed("jll")
- feed("ma")
- feed("G`a")
- eq({2, 2}, cursor())
- feed("mA")
- command("next")
- feed("`A")
- eq(1, meths.get_current_buf().id)
- eq({2, 2}, cursor())
+ it('can move to them using `', function()
+ command('args ' .. file1 .. ' ' .. file2)
+ feed('jll')
+ feed('ma')
+ feed('G`a')
+ eq({ 2, 2 }, cursor())
+ feed('mA')
+ command('next')
+ feed('`A')
+ eq(1, api.nvim_get_current_buf())
+ eq({ 2, 2 }, cursor())
end)
it("can move to them using g'", function()
- command("args " .. file1 .. " " .. file2)
- feed("jll")
- feed("ma")
+ command('args ' .. file1 .. ' ' .. file2)
+ feed('jll')
+ feed('ma')
feed("Gg'a")
- eq({2, 0}, cursor())
- feed("mA")
- command("next")
+ eq({ 2, 0 }, cursor())
+ feed('mA')
+ command('next')
feed("g'A")
- eq(1, meths.get_current_buf().id)
- eq({2, 0}, cursor())
+ eq(1, api.nvim_get_current_buf())
+ eq({ 2, 0 }, cursor())
end)
- it("can move to them using g`", function()
- command("args " .. file1 .. " " .. file2)
- feed("jll")
- feed("ma")
- feed("Gg`a")
- eq({2, 2}, cursor())
- feed("mA")
- command("next")
- feed("g`A")
- eq(1, meths.get_current_buf().id)
- eq({2, 2}, cursor())
+ it('can move to them using g`', function()
+ command('args ' .. file1 .. ' ' .. file2)
+ feed('jll')
+ feed('ma')
+ feed('Gg`a')
+ eq({ 2, 2 }, cursor())
+ feed('mA')
+ command('next')
+ feed('g`A')
+ eq(1, api.nvim_get_current_buf())
+ eq({ 2, 2 }, cursor())
end)
it("can move to them using :'", function()
- command("args " .. file1 .. " " .. file2)
- feed("j")
- feed("ma")
- feed("G")
+ command('args ' .. file1 .. ' ' .. file2)
+ feed('j')
+ feed('ma')
+ feed('G')
command("'a")
- eq({2, 0}, cursor())
- feed("mA")
- command("next")
+ eq({ 2, 0 }, cursor())
+ feed('mA')
+ command('next')
command("'A")
- eq(1, meths.get_current_buf().id)
- eq({2, 0}, cursor())
+ eq(1, api.nvim_get_current_buf())
+ eq({ 2, 0 }, cursor())
end)
it("errors when it can't find the buffer", function()
- command("args " .. file1 .. " " .. file2)
- feed("mA")
- command("next")
- command("bw! " .. file1 )
+ command('args ' .. file1 .. ' ' .. file2)
+ feed('mA')
+ command('next')
+ command('bw! ' .. file1)
local err = pcall_err(helpers.exec_capture, "normal! 'A")
- eq("nvim_exec2(): Vim(normal):E92: Buffer 1 not found", err)
+ eq('nvim_exec2(): Vim(normal):E92: Buffer 1 not found', err)
os.remove(file1)
end)
- it("errors when using a mark in another buffer in command range", function()
+ it('errors when using a mark in another buffer in command range', function()
feed('ifoo<Esc>mA')
command('enew')
feed('ibar<Esc>')
@@ -178,147 +179,147 @@ describe('named marks', function()
end)
it("leave a context mark when moving with '", function()
- command("edit " .. file1)
- feed("llmamA")
- feed("10j0") -- first col, last line
+ command('edit ' .. file1)
+ feed('llmamA')
+ feed('10j0') -- first col, last line
local pos = cursor()
feed("'a")
- feed("<C-o>")
+ feed('<C-o>')
eq(pos, cursor())
feed("'A")
- feed("<C-o>")
+ feed('<C-o>')
eq(pos, cursor())
end)
- it("leave a context mark when moving with `", function()
- command("edit " .. file1)
- feed("llmamA")
- feed("10j0") -- first col, last line
+ it('leave a context mark when moving with `', function()
+ command('edit ' .. file1)
+ feed('llmamA')
+ feed('10j0') -- first col, last line
local pos = cursor()
- feed("`a")
- feed("<C-o>")
+ feed('`a')
+ feed('<C-o>')
eq(pos, cursor())
- feed("`A")
- feed("<C-o>")
+ feed('`A')
+ feed('<C-o>')
eq(pos, cursor())
end)
it("leave a context mark when the mark changes buffer with g'", function()
- command("args " .. file1 .. " " .. file2)
+ command('args ' .. file1 .. ' ' .. file2)
local pos
- feed("GmA")
- command("next")
+ feed('GmA')
+ command('next')
pos = cursor()
- command("clearjumps")
- feed("g'A") -- since the mark is in another buffer, it leaves a context mark
- feed("<C-o>")
+ command('clearjumps')
+ feed("g'A") -- since the mark is in another buffer, it leaves a context mark
+ feed('<C-o>')
eq(pos, cursor())
end)
- it("leave a context mark when the mark changes buffer with g`", function()
- command("args " .. file1 .. " " .. file2)
+ it('leave a context mark when the mark changes buffer with g`', function()
+ command('args ' .. file1 .. ' ' .. file2)
local pos
- feed("GmA")
- command("next")
+ feed('GmA')
+ command('next')
pos = cursor()
- command("clearjumps")
- feed("g`A") -- since the mark is in another buffer, it leaves a context mark
- feed("<C-o>")
+ command('clearjumps')
+ feed('g`A') -- since the mark is in another buffer, it leaves a context mark
+ feed('<C-o>')
eq(pos, cursor())
end)
it("do not leave a context mark when moving with g'", function()
- command("edit " .. file1)
+ command('edit ' .. file1)
local pos
- feed("ma")
+ feed('ma')
pos = cursor() -- Mark pos
- feed("10j0") -- first col, last line
+ feed('10j0') -- first col, last line
feed("g'a")
- feed("<C-o>") -- should do nothing
+ feed('<C-o>') -- should do nothing
eq(pos, cursor())
- feed("mA")
+ feed('mA')
pos = cursor() -- Mark pos
- feed("10j0") -- first col, last line
+ feed('10j0') -- first col, last line
feed("g'a")
- feed("<C-o>") -- should do nothing
+ feed('<C-o>') -- should do nothing
eq(pos, cursor())
end)
- it("do not leave a context mark when moving with g`", function()
- command("edit " .. file1)
+ it('do not leave a context mark when moving with g`', function()
+ command('edit ' .. file1)
local pos
- feed("ma")
+ feed('ma')
pos = cursor() -- Mark pos
- feed("10j0") -- first col, last line
- feed("g`a")
- feed("<C-o>") -- should do nothing
+ feed('10j0') -- first col, last line
+ feed('g`a')
+ feed('<C-o>') -- should do nothing
eq(pos, cursor())
- feed("mA")
+ feed('mA')
pos = cursor() -- Mark pos
- feed("10j0") -- first col, last line
+ feed('10j0') -- first col, last line
feed("g'a")
- feed("<C-o>") -- should do nothing
+ feed('<C-o>') -- should do nothing
eq(pos, cursor())
end)
- it("open folds when moving to them", function()
- command("edit " .. file1)
- feed("jzfG") -- Fold from the second line to the end
- command("3mark a")
- feed("G") -- On top of the fold
- assert(funcs.foldclosed('.') ~= -1) -- folded
+ it('open folds when moving to them', function()
+ command('edit ' .. file1)
+ feed('jzfG') -- Fold from the second line to the end
+ command('3mark a')
+ feed('G') -- On top of the fold
+ assert(fn.foldclosed('.') ~= -1) -- folded
feed("'a")
- eq(-1, funcs.foldclosed('.'))
+ eq(-1, fn.foldclosed('.'))
- feed("zc")
- assert(funcs.foldclosed('.') ~= -1) -- folded
+ feed('zc')
+ assert(fn.foldclosed('.') ~= -1) -- folded
-- TODO: remove this workaround after fixing #15873
- feed("k`a")
- eq(-1, funcs.foldclosed('.'))
+ feed('k`a')
+ eq(-1, fn.foldclosed('.'))
- feed("zc")
- assert(funcs.foldclosed('.') ~= -1) -- folded
+ feed('zc')
+ assert(fn.foldclosed('.') ~= -1) -- folded
feed("kg'a")
- eq(-1, funcs.foldclosed('.'))
+ eq(-1, fn.foldclosed('.'))
- feed("zc")
- assert(funcs.foldclosed('.') ~= -1) -- folded
- feed("kg`a")
- eq(-1, funcs.foldclosed('.'))
+ feed('zc')
+ assert(fn.foldclosed('.') ~= -1) -- folded
+ feed('kg`a')
+ eq(-1, fn.foldclosed('.'))
end)
it("do not open folds when moving to them doesn't move the cursor", function()
- command("edit " .. file1)
- feed("jzfG") -- Fold from the second line to the end
- assert(funcs.foldclosed('.') == 2) -- folded
- feed("ma")
+ command('edit ' .. file1)
+ feed('jzfG') -- Fold from the second line to the end
+ assert(fn.foldclosed('.') == 2) -- folded
+ feed('ma')
feed("'a")
- feed("`a")
+ feed('`a')
feed("g'a")
- feed("g`a")
+ feed('g`a')
-- should still be folded
- eq(2, funcs.foldclosed('.'))
+ eq(2, fn.foldclosed('.'))
end)
it("getting '{ '} '( ') does not move cursor", function()
- meths.buf_set_lines(0, 0, 0, true, {'aaaaa', 'bbbbb', 'ccccc', 'ddddd', 'eeeee'})
- meths.win_set_cursor(0, {2, 0})
- funcs.getpos("'{")
- eq({2, 0}, meths.win_get_cursor(0))
- funcs.getpos("'}")
- eq({2, 0}, meths.win_get_cursor(0))
- funcs.getpos("'(")
- eq({2, 0}, meths.win_get_cursor(0))
- funcs.getpos("')")
- eq({2, 0}, meths.win_get_cursor(0))
+ api.nvim_buf_set_lines(0, 0, 0, true, { 'aaaaa', 'bbbbb', 'ccccc', 'ddddd', 'eeeee' })
+ api.nvim_win_set_cursor(0, { 2, 0 })
+ fn.getpos("'{")
+ eq({ 2, 0 }, api.nvim_win_get_cursor(0))
+ fn.getpos("'}")
+ eq({ 2, 0 }, api.nvim_win_get_cursor(0))
+ fn.getpos("'(")
+ eq({ 2, 0 }, api.nvim_win_get_cursor(0))
+ fn.getpos("')")
+ eq({ 2, 0 }, api.nvim_win_get_cursor(0))
end)
it('in command range does not move cursor #19248', function()
- meths.create_user_command('Test', ':', {range = true})
- meths.buf_set_lines(0, 0, 0, true, {'aaaaa', 'bbbbb', 'ccccc', 'ddddd', 'eeeee'})
- meths.win_set_cursor(0, {2, 0})
+ api.nvim_create_user_command('Test', ':', { range = true })
+ api.nvim_buf_set_lines(0, 0, 0, true, { 'aaaaa', 'bbbbb', 'ccccc', 'ddddd', 'eeeee' })
+ api.nvim_win_set_cursor(0, { 2, 0 })
command([['{,'}Test]])
- eq({2, 0}, meths.win_get_cursor(0))
+ eq({ 2, 0 }, api.nvim_win_get_cursor(0))
end)
end)
@@ -327,16 +328,16 @@ describe('named marks view', function()
local file2 = 'Xtestfile-functional-editor-marks-2'
local function content()
local c = {}
- for i=1,30 do
- c[i] = i .. " line"
+ for i = 1, 30 do
+ c[i] = i .. ' line'
end
- return table.concat(c, "\n")
+ return table.concat(c, '\n')
end
before_each(function()
clear()
write_file(file1, content(), false, false)
write_file(file2, content(), false, false)
- command("set jumpoptions+=view")
+ command('set jumpoptions+=view')
end)
after_each(function()
os.remove(file1)
@@ -344,12 +345,12 @@ describe('named marks view', function()
end)
it('is restored in normal mode but not op-pending mode', function()
- local screen = Screen.new(5, 8)
- screen:attach()
- command("edit " .. file1)
- feed("<C-e>jWma")
- feed("G'a")
- local expected = [[
+ local screen = Screen.new(5, 8)
+ screen:attach()
+ command('edit ' .. file1)
+ feed('<C-e>jWma')
+ feed("G'a")
+ local expected = [[
2 line |
^3 line |
4 line |
@@ -359,9 +360,9 @@ describe('named marks view', function()
8 line |
|
]]
- screen:expect({grid=expected})
- feed("G`a")
- screen:expect([[
+ screen:expect({ grid = expected })
+ feed('G`a')
+ screen:expect([[
2 line |
3 ^line |
4 line |
@@ -371,9 +372,9 @@ describe('named marks view', function()
8 line |
|
]])
- -- not in op-pending mode #20886
- feed("ggj=`a")
- screen:expect([[
+ -- not in op-pending mode #20886
+ feed('ggj=`a')
+ screen:expect([[
1 line |
^2 line |
3 line |
@@ -388,8 +389,8 @@ describe('named marks view', function()
it('is restored across files', function()
local screen = Screen.new(5, 5)
screen:attach()
- command("args " .. file1 .. " " .. file2)
- feed("<C-e>mA")
+ command('args ' .. file1 .. ' ' .. file2)
+ feed('<C-e>mA')
local mark_view = [[
^2 line |
3 line |
@@ -398,7 +399,7 @@ describe('named marks view', function()
|
]]
screen:expect(mark_view)
- command("next")
+ command('next')
screen:expect([[
^1 line |
2 line |
@@ -410,18 +411,16 @@ describe('named marks view', function()
screen:expect(mark_view)
end)
- it('fallback to standard behavior when view can\'t be recovered', function()
- local screen = Screen.new(10, 10)
- screen:attach()
- command("edit " .. file1)
- feed("7GzbmaG") -- Seven lines from the top
- command("new") -- Screen size for window is now half the height can't be restored
- feed("<C-w>p'a")
- screen:expect([[
+ it("fallback to standard behavior when view can't be recovered", function()
+ local screen = Screen.new(10, 10)
+ screen:attach()
+ command('edit ' .. file1)
+ feed('7GzbmaG') -- Seven lines from the top
+ command('new') -- Screen size for window is now half the height can't be restored
+ feed("<C-w>p'a")
+ screen:expect([[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
[No Name] |
6 line |
^7 line |
@@ -454,10 +453,7 @@ describe('named marks view', function()
command('bwipe!')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
|
]])
command('rshada!')
diff --git a/test/functional/editor/meta_key_spec.lua b/test/functional/editor/meta_key_spec.lua
index 825b20138a..b57f5c3c35 100644
--- a/test/functional/editor/meta_key_spec.lua
+++ b/test/functional/editor/meta_key_spec.lua
@@ -4,7 +4,7 @@ local command = helpers.command
local exec_lua = helpers.exec_lua
local eval = helpers.eval
local expect = helpers.expect
-local funcs = helpers.funcs
+local fn = helpers.fn
local eq = helpers.eq
describe('meta-keys #8226 #13042', function()
@@ -66,11 +66,11 @@ describe('meta-keys #8226 #13042', function()
command('inoremap <A-j> alt-j')
feed('i<M-l> xxx <A-j><M-h>a<A-h>')
expect('meta-l xxx alt-j')
- eq({ 0, 1, 14, 0, }, funcs.getpos('.'))
+ eq({ 0, 1, 14, 0 }, fn.getpos('.'))
-- Unmapped ALT-chord behaves as ESC+c.
command('iunmap <M-l>')
feed('0i<M-l>')
- eq({ 0, 1, 2, 0, }, funcs.getpos('.'))
+ eq({ 0, 1, 2, 0 }, fn.getpos('.'))
-- Unmapped ALT-chord has same `undo` characteristics as ESC+<key>
command('0,$d')
feed('ahello<M-.>')
@@ -101,7 +101,7 @@ describe('meta-keys #8226 #13042', function()
eq(meta_l_seq .. 'yyy' .. meta_l_seq .. 'alt-j', exec_lua([[return _G.input_data]]))
eq('t', eval('mode(1)'))
feed('<Esc>j')
- eq({ 0, 2, 1, 0, }, funcs.getpos('.'))
+ eq({ 0, 2, 1, 0 }, fn.getpos('.'))
eq('nt', eval('mode(1)'))
end)
diff --git a/test/functional/editor/mode_cmdline_spec.lua b/test/functional/editor/mode_cmdline_spec.lua
index d34b5a1a28..06efe53718 100644
--- a/test/functional/editor/mode_cmdline_spec.lua
+++ b/test/functional/editor/mode_cmdline_spec.lua
@@ -2,11 +2,11 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, insert, funcs, eq, feed =
- helpers.clear, helpers.insert, helpers.funcs, helpers.eq, helpers.feed
+local clear, insert, fn, eq, feed =
+ helpers.clear, helpers.insert, helpers.fn, helpers.eq, helpers.feed
local eval = helpers.eval
local command = helpers.command
-local meths = helpers.meths
+local api = helpers.api
describe('cmdline', function()
before_each(clear)
@@ -20,22 +20,22 @@ describe('cmdline', function()
-- Yank 2 lines linewise, then paste to cmdline.
feed([[<C-\><C-N>gg0yj:<C-R>0]])
-- <CR> inserted between lines, NOT after the final line.
- eq('line1abc\rline2somemoretext', funcs.getcmdline())
+ eq('line1abc\rline2somemoretext', fn.getcmdline())
-- Yank 2 lines charwise, then paste to cmdline.
feed([[<C-\><C-N>gg05lyvj:<C-R>0]])
-- <CR> inserted between lines, NOT after the final line.
- eq('abc\rline2', funcs.getcmdline())
+ eq('abc\rline2', fn.getcmdline())
-- Yank 1 line linewise, then paste to cmdline.
feed([[<C-\><C-N>ggyy:<C-R>0]])
-- No <CR> inserted.
- eq('line1abc', funcs.getcmdline())
+ eq('line1abc', fn.getcmdline())
end)
it('pasting special register inserts <CR>, <NL>', function()
feed([[:<C-R>="foo\nbar\rbaz"<CR>]])
- eq('foo\nbar\rbaz', funcs.getcmdline())
+ eq('foo\nbar\rbaz', fn.getcmdline())
end)
end)
@@ -48,55 +48,59 @@ describe('cmdline', function()
it('redraws statusline when toggling overstrike', function()
local screen = Screen.new(60, 4)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {reverse = true, bold = true}, -- StatusLine
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { reverse = true, bold = true }, -- StatusLine
})
screen:attach()
command('set laststatus=2 statusline=%!mode(1)')
feed(':')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{0:~ }|
{1:c }|
:^ |
- ]]}
+ ]],
+ }
feed('<Insert>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{0:~ }|
{1:cr }|
:^ |
- ]]}
+ ]],
+ }
end)
describe('history', function()
it('correctly clears start of the history', function()
-- Regression test: check absence of the memory leak when clearing start of
- -- the history using ex_getln.c/clr_history().
- eq(1, funcs.histadd(':', 'foo'))
- eq(1, funcs.histdel(':'))
- eq('', funcs.histget(':', -1))
+ -- the history using cmdhist.c/clr_history().
+ eq(1, fn.histadd(':', 'foo'))
+ eq(1, fn.histdel(':'))
+ eq('', fn.histget(':', -1))
end)
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_value('history', 1, {})
- eq(1, funcs.histadd(':', 'foo'))
- eq(1, funcs.histdel(':'))
- eq('', funcs.histget(':', -1))
+ -- the history using cmdhist.c/clr_history().
+ api.nvim_set_option_value('history', 1, {})
+ eq(1, fn.histadd(':', 'foo'))
+ eq(1, fn.histdel(':'))
+ eq('', fn.histget(':', -1))
end)
it('correctly removes item from history', function()
- -- Regression test: check that ex_getln.c/del_history_idx() correctly clears
+ -- Regression test: check that cmdhist.c/del_history_idx() correctly clears
-- history index after removing history entry. If it does not then deleting
-- history will result in a double free.
- eq(1, funcs.histadd(':', 'foo'))
- eq(1, funcs.histadd(':', 'bar'))
- eq(1, funcs.histadd(':', 'baz'))
- eq(1, funcs.histdel(':', -2))
- eq(1, funcs.histdel(':'))
- eq('', funcs.histget(':', -1))
+ eq(1, fn.histadd(':', 'foo'))
+ eq(1, fn.histadd(':', 'bar'))
+ eq(1, fn.histadd(':', 'baz'))
+ eq(1, fn.histdel(':', -2))
+ eq(1, fn.histdel(':'))
+ eq('', fn.histget(':', -1))
end)
end)
end)
diff --git a/test/functional/editor/mode_insert_spec.lua b/test/functional/editor/mode_insert_spec.lua
index 37651164f5..e96813b6f7 100644
--- a/test/functional/editor/mode_insert_spec.lua
+++ b/test/functional/editor/mode_insert_spec.lua
@@ -53,31 +53,25 @@ describe('insert-mode', function()
it('double quote is removed after hit-enter prompt #22609', function()
local screen = Screen.new(60, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {foreground = Screen.colors.Blue}, -- SpecialKey
- [2] = {foreground = Screen.colors.SlateBlue},
- [3] = {bold = true}, -- ModeMsg
- [4] = {reverse = true, bold = true}, -- MsgSeparator
- [5] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- ErrorMsg
- [6] = {foreground = Screen.colors.SeaGreen, bold = true}, -- MoreMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { foreground = Screen.colors.Blue }, -- SpecialKey
+ [2] = { foreground = Screen.colors.SlateBlue },
+ [3] = { bold = true }, -- ModeMsg
+ [4] = { reverse = true, bold = true }, -- MsgSeparator
+ [5] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg
+ [6] = { foreground = Screen.colors.SeaGreen, bold = true }, -- MoreMsg
})
screen:attach()
feed('i<C-R>')
screen:expect([[
{1:^"} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:-- INSERT --} |
]])
feed('={}')
screen:expect([[
{1:"} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
={2:{}}^ |
]])
feed('<CR>')
@@ -92,10 +86,7 @@ describe('insert-mode', function()
feed('<CR>')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:-- INSERT --} |
]])
end)
@@ -196,10 +187,10 @@ describe('insert-mode', function()
it('multi-char mapping updates screen properly #25626', function()
local screen = Screen.new(60, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}; -- NonText
- [1] = {bold = true, reverse = true}; -- StatusLine
- [2] = {reverse = true}; -- StatusLineNC
- [3] = {bold = true}; -- ModeMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, reverse = true }, -- StatusLine
+ [2] = { reverse = true }, -- StatusLineNC
+ [3] = { bold = true }, -- ModeMsg
})
screen:attach()
command('vnew')
@@ -208,22 +199,26 @@ describe('insert-mode', function()
command('set timeoutlen=10000')
command('inoremap jk <Esc>')
feed('i<CR>βββ<Left><Left>j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
foo │ |
foo │β^jβ |
foo │{0:~ }|
{0:~ }│{0:~ }|
{2:[No Name] [+] }{1:[No Name] [+] }|
{3:-- INSERT --} |
- ]]}
+ ]],
+ }
feed('k')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
foo │ |
foo │^βββ |
foo │{0:~ }|
{0:~ }│{0:~ }|
{2:[No Name] [+] }{1:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
end)
end)
diff --git a/test/functional/editor/mode_normal_spec.lua b/test/functional/editor/mode_normal_spec.lua
new file mode 100644
index 0000000000..89bab3f6c9
--- /dev/null
+++ b/test/functional/editor/mode_normal_spec.lua
@@ -0,0 +1,22 @@
+-- Normal mode tests.
+
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local feed = helpers.feed
+local fn = helpers.fn
+local command = helpers.command
+local eq = helpers.eq
+
+describe('Normal mode', function()
+ before_each(clear)
+
+ it('setting &winhighlight or &winblend does not change curswant #27470', function()
+ fn.setline(1, { 'long long lone line', 'short line' })
+ feed('ggfi')
+ local pos = fn.getcurpos()
+ feed('j')
+ command('setlocal winblend=10 winhighlight=Visual:Search')
+ feed('k')
+ eq(pos, fn.getcurpos())
+ end)
+end)
diff --git a/test/functional/editor/put_spec.lua b/test/functional/editor/put_spec.lua
index 47068470bb..414b289222 100644
--- a/test/functional/editor/put_spec.lua
+++ b/test/functional/editor/put_spec.lua
@@ -6,12 +6,12 @@ local insert = helpers.insert
local feed = helpers.feed
local expect = helpers.expect
local eq = helpers.eq
-local map = helpers.tbl_map
-local filter = helpers.tbl_filter
+local map = vim.tbl_map
+local filter = vim.tbl_filter
local feed_command = helpers.feed_command
local command = helpers.command
local curbuf_contents = helpers.curbuf_contents
-local funcs = helpers.funcs
+local fn = helpers.fn
local dedent = helpers.dedent
local function reset()
@@ -21,9 +21,9 @@ local function reset()
Line of words 2]])
command('goto 1')
feed('itest_string.<esc>u')
- funcs.setreg('a', 'test_stringa', 'V')
- funcs.setreg('b', 'test_stringb\ntest_stringb\ntest_stringb', 'b')
- funcs.setreg('"', 'test_string"', 'v')
+ fn.setreg('a', 'test_stringa', 'V')
+ fn.setreg('b', 'test_stringb\ntest_stringb\ntest_stringb', 'b')
+ fn.setreg('"', 'test_string"', 'v')
end
-- We check the last inserted register ". in each of these tests because it is
@@ -35,12 +35,12 @@ describe('put command', function()
before_each(reset)
local function visual_marks_zero()
- for _,v in pairs(funcs.getpos("'<")) do
+ for _, v in pairs(fn.getpos("'<")) do
if v ~= 0 then
return false
end
end
- for _,v in pairs(funcs.getpos("'>")) do
+ for _, v in pairs(fn.getpos("'>")) do
if v ~= 0 then
return false
end
@@ -51,10 +51,12 @@ describe('put command', function()
-- {{{ Where test definitions are run
local function run_test_variations(test_variations, extra_setup)
reset()
- if extra_setup then extra_setup() end
+ if extra_setup then
+ extra_setup()
+ end
local init_contents = curbuf_contents()
- local init_cursorpos = funcs.getcurpos()
- local assert_no_change = function (exception_table, after_undo)
+ local init_cursorpos = fn.getcurpos()
+ local assert_no_change = function(exception_table, after_undo)
expect(init_contents)
-- When putting the ". register forwards, undo doesn't move
-- the cursor back to where it was before.
@@ -63,14 +65,16 @@ describe('put command', function()
-- one place to the right (unless we were at the end of the
-- line when we pasted).
if not (exception_table.undo_position and after_undo) then
- eq(init_cursorpos, funcs.getcurpos())
+ eq(init_cursorpos, fn.getcurpos())
end
end
for _, test in pairs(test_variations) do
it(test.description, function()
- if extra_setup then extra_setup() end
- local orig_dotstr = funcs.getreg('.')
+ if extra_setup then
+ extra_setup()
+ end
+ local orig_dotstr = fn.getreg('.')
helpers.ok(visual_marks_zero())
-- Make sure every test starts from the same conditions
assert_no_change(test.exception_table, false)
@@ -85,7 +89,7 @@ describe('put command', function()
-- If we paste the ". register with a count we can't avoid
-- changing this register, hence avoid this check.
if not test.exception_table.dot_reg_changed then
- eq(orig_dotstr, funcs.getreg('.'))
+ eq(orig_dotstr, fn.getreg('.'))
end
-- Doing something, undoing it, and then redoing it should
@@ -101,7 +105,7 @@ describe('put command', function()
end
if test.exception_table.undo_position then
- funcs.setpos('.', init_cursorpos)
+ fn.setpos('.', init_cursorpos)
end
if was_cli then
feed('@:')
@@ -115,8 +119,13 @@ describe('put command', function()
end -- run_test_variations()
-- }}}
- local function create_test_defs(test_defs, command_base, command_creator, -- {{{
- expect_base, expect_creator)
+ local function create_test_defs(
+ test_defs,
+ command_base,
+ command_creator, -- {{{
+ expect_base,
+ expect_creator
+ )
local rettab = {}
local exceptions
for _, v in pairs(test_defs) do
@@ -125,8 +134,7 @@ describe('put command', function()
else
exceptions = {}
end
- table.insert(rettab,
- {
+ table.insert(rettab, {
test_action = command_creator(command_base, v[1]),
test_assertions = expect_creator(expect_base, v[2]),
description = v[3],
@@ -143,10 +151,10 @@ describe('put command', function()
-- it was in.
-- This returns the cursor position that would leave the 'x' in that
-- place if we feed 'ix<esc>' and the string existed before it.
- for linenum, line in pairs(funcs.split(expect_string, '\n', 1)) do
+ for linenum, line in pairs(fn.split(expect_string, '\n', 1)) do
local column = line:find('x')
if column then
- return {linenum, column}, expect_string:gsub('x', '')
+ return { linenum, column }, expect_string:gsub('x', '')
end
end
end -- find_cursor_position() }}}
@@ -176,17 +184,17 @@ describe('put command', function()
return function(exception_table, after_redo)
expect(expect_string)
- -- Have to use getcurpos() instead of curwinmeths.get_cursor() in
+ -- Have to use getcurpos() instead of api.nvim_win_get_cursor(0) in
-- order to account for virtualedit.
-- We always want the curswant element in getcurpos(), which is
-- sometimes different to the column element in
- -- curwinmeths.get_cursor().
+ -- api.nvim_win_get_cursor(0).
-- NOTE: The ".gp command leaves the cursor after the pasted text
-- when running, but does not when the command is redone with the
-- '.' command.
if not (exception_table.redo_position and after_redo) then
- local actual_position = funcs.getcurpos()
- eq(cursor_position, {actual_position[2], actual_position[5]})
+ local actual_position = fn.getcurpos()
+ eq(cursor_position, { actual_position[2], actual_position[5] })
end
end
end -- expect_creator() }}}
@@ -195,13 +203,13 @@ describe('put command', function()
local function copy_def(def)
local rettab = { '', {}, '', nil }
rettab[1] = def[1]
- for k,v in pairs(def[2]) do
+ for k, v in pairs(def[2]) do
rettab[2][k] = v
end
rettab[3] = def[3]
if def[4] then
rettab[4] = {}
- for k,v in pairs(def[4]) do
+ for k, v in pairs(def[4]) do
rettab[4][k] = v
end
end
@@ -211,52 +219,52 @@ describe('put command', function()
local normal_command_defs = {
{
'p',
- {cursor_after = false, put_backwards = false, dot_register = false},
+ { cursor_after = false, put_backwards = false, dot_register = false },
'pastes after cursor with p',
},
{
'gp',
- {cursor_after = true, put_backwards = false, dot_register = false},
+ { cursor_after = true, put_backwards = false, dot_register = false },
'leaves cursor after text with gp',
},
{
'".p',
- {cursor_after = false, put_backwards = false, dot_register = true},
+ { cursor_after = false, put_backwards = false, dot_register = true },
'works with the ". register',
},
{
'".gp',
- {cursor_after = true, put_backwards = false, dot_register = true},
+ { cursor_after = true, put_backwards = false, dot_register = true },
'gp works with the ". register',
- {redo_position = true},
+ { redo_position = true },
},
{
'P',
- {cursor_after = false, put_backwards = true, dot_register = false},
+ { cursor_after = false, put_backwards = true, dot_register = false },
'pastes before cursor with P',
},
{
'gP',
- {cursor_after = true, put_backwards = true, dot_register = false},
+ { cursor_after = true, put_backwards = true, dot_register = false },
'gP pastes before cursor and leaves cursor after text',
},
{
'".P',
- {cursor_after = false, put_backwards = true, dot_register = true},
+ { cursor_after = false, put_backwards = true, dot_register = true },
'P works with ". register',
},
{
'".gP',
- {cursor_after = true, put_backwards = true, dot_register = true},
+ { cursor_after = true, put_backwards = true, dot_register = true },
'gP works with ". register',
- {redo_position = true},
+ { redo_position = true },
},
}
-- Add a definition applying a count for each definition above.
-- Could do this for each transformation (p -> P, p -> gp etc), but I think
-- it's neater this way (balance between being explicit and too verbose).
- for i = 1,#normal_command_defs do
+ for i = 1, #normal_command_defs do
local cur = normal_command_defs[i]
-- Make modified copy of current definition that includes a count.
@@ -279,35 +287,36 @@ describe('put command', function()
local ex_command_defs = {
{
'put',
- {put_backwards = false, dot_register = false},
+ { put_backwards = false, dot_register = false },
'pastes linewise forwards with :put',
},
{
'put!',
- {put_backwards = true, dot_register = false},
+ { put_backwards = true, dot_register = false },
'pastes linewise backwards with :put!',
},
{
'put .',
- {put_backwards = false, dot_register = true},
+ { put_backwards = false, dot_register = true },
'pastes linewise with the dot register',
},
{
'put! .',
- {put_backwards = true, dot_register = true},
+ { put_backwards = true, dot_register = true },
'pastes linewise backwards with the dot register',
},
}
local function non_dotdefs(def_table)
- return filter(function(d) return not d[2].dot_register end, def_table)
+ return filter(function(d)
+ return not d[2].dot_register
+ end, def_table)
end
-- }}}
-- Conversion functions {{{
- local function convert_charwise(expect_base, conversion_table,
- virtualedit_end, visual_put)
+ local function convert_charwise(expect_base, conversion_table, virtualedit_end, visual_put)
expect_base = dedent(expect_base)
-- There is no difference between 'P' and 'p' when VIsual_active
if not visual_put then
@@ -324,7 +333,7 @@ describe('put command', function()
end
if conversion_table.count > 1 then
local rep_string = 'test_string"'
- local extra_puts = rep_string:rep(conversion_table.count - 1)
+ local extra_puts = rep_string:rep(conversion_table.count - 1)
expect_base = expect_base:gsub('test_stringx"', extra_puts .. 'test_stringx"')
end
if conversion_table.cursor_after then
@@ -340,7 +349,7 @@ describe('put command', function()
local prev_line
local rettab = {}
local string_found = false
- for _, line in pairs(funcs.split(string, '\n', 1)) do
+ for _, line in pairs(fn.split(string, '\n', 1)) do
if line:find('test_string') then
string_found = true
table.insert(rettab, line)
@@ -395,7 +404,7 @@ describe('put command', function()
indent = ''
end
local rep_string = indent .. p_str .. '\n'
- local extra_puts = rep_string:rep(conversion_table.count - 1)
+ local extra_puts = rep_string:rep(conversion_table.count - 1)
local orig_string, new_string
if conversion_table.cursor_after then
orig_string = indent .. p_str .. '\nx'
@@ -420,8 +429,13 @@ describe('put command', function()
return orig_line:sub(1, prev_end - 1) .. 'x' .. orig_line:sub(prev_end)
end
- local function convert_blockwise(expect_base, conversion_table, visual,
- use_b, trailing_whitespace)
+ local function convert_blockwise(
+ expect_base,
+ conversion_table,
+ visual,
+ use_b,
+ trailing_whitespace
+ )
expect_base = dedent(expect_base)
local p_str = 'test_string"'
if use_b then
@@ -452,11 +466,9 @@ describe('put command', function()
if conversion_table.count and conversion_table.count > 1 then
local p_pattern = p_str:gsub('%.', '%%.')
- expect_base = expect_base:gsub(p_pattern,
- p_str:rep(conversion_table.count))
- expect_base = expect_base:gsub('test_stringx([b".])',
- p_str:rep(conversion_table.count - 1)
- .. '%0')
+ expect_base = expect_base:gsub(p_pattern, p_str:rep(conversion_table.count))
+ expect_base =
+ expect_base:gsub('test_stringx([b".])', p_str:rep(conversion_table.count - 1) .. '%0')
end
if conversion_table.cursor_after then
@@ -464,7 +476,7 @@ describe('put command', function()
local prev_line
local rettab = {}
local prev_in_block = false
- for _, line in pairs(funcs.split(expect_base, '\n', 1)) do
+ for _, line in pairs(fn.split(expect_base, '\n', 1)) do
if line:find('test_string') then
if prev_line then
prev_line = prev_line:gsub('x', '')
@@ -496,8 +508,13 @@ describe('put command', function()
-- }}}
-- Convenience functions {{{
- local function run_normal_mode_tests(test_string, base_map, extra_setup,
- virtualedit_end, selection_string)
+ local function run_normal_mode_tests(
+ test_string,
+ base_map,
+ extra_setup,
+ virtualedit_end,
+ selection_string
+ )
local function convert_closure(e, c)
return convert_charwise(e, c, virtualedit_end, selection_string)
end
@@ -507,10 +524,10 @@ describe('put command', function()
test_expect(exception_table, after_redo)
if selection_string then
if not conversion_table.put_backwards then
- eq(selection_string, funcs.getreg('"'))
+ eq(selection_string, fn.getreg('"'))
end
else
- eq('test_string"', funcs.getreg('"'))
+ eq('test_string"', fn.getreg('"'))
end
end
end
@@ -532,8 +549,12 @@ describe('put command', function()
local function run_linewise_tests(expect_base, base_command, extra_setup)
local linewise_test_defs = create_test_defs(
- ex_command_defs, base_command,
- create_put_action, expect_base, convert_linewiseer)
+ ex_command_defs,
+ base_command,
+ create_put_action,
+ expect_base,
+ convert_linewiseer
+ )
run_test_variations(linewise_test_defs, extra_setup)
end -- run_linewise_tests()
-- }}}
@@ -545,7 +566,8 @@ describe('put command', function()
Line of words 2]]
run_normal_mode_tests(expect_string, 'p')
- run_linewise_tests([[
+ run_linewise_tests(
+ [[
Line of words 1
xtest_string"
Line of words 2]],
@@ -585,11 +607,12 @@ describe('put command', function()
run_test_variations(
create_test_defs(
linewise_put_defs,
- 'put a', create_put_action,
- base_expect_string, convert_linewiseer
+ 'put a',
+ create_put_action,
+ base_expect_string,
+ convert_linewiseer
)
)
-
end)
describe('blockwise register', function()
@@ -600,18 +623,13 @@ describe('put command', function()
test_stringb]]
local function expect_block_creator(expect_base, conversion_table)
- return expect_creator(function(e,c) return convert_blockwise(e,c,nil,true) end,
- expect_base, conversion_table)
+ return expect_creator(function(e, c)
+ return convert_blockwise(e, c, nil, true)
+ end, expect_base, conversion_table)
end
run_test_variations(
- create_test_defs(
- blockwise_put_defs,
- '"bp',
- create_p_action,
- test_base,
- expect_block_creator
- )
+ create_test_defs(blockwise_put_defs, '"bp', create_p_action, test_base, expect_block_creator)
)
end)
@@ -632,17 +650,17 @@ describe('put command', function()
describe('linewise paste with autoindent', function()
-- luacheck: ignore
- run_linewise_tests([[
+ run_linewise_tests(
+ [[
Line of words 1
Line of words 2
xtest_string"]],
- 'put'
- ,
+ 'put',
function()
- funcs.setline('$', ' Line of words 2')
+ fn.setline('$', ' Line of words 2')
-- Set curswant to '8' to be at the end of the tab character
-- This is where the cursor is put back after the 'u' command.
- funcs.setpos('.', {0, 2, 1, 0, 8})
+ fn.setpos('.', { 0, 2, 1, 0, 8 })
command('set autoindent')
end
)
@@ -653,9 +671,9 @@ describe('put command', function()
Line of words 1
test_stringx" Line of words 2]]
run_normal_mode_tests(test_string, 'p', function()
- funcs.setline('$', ' Line of words 2')
+ fn.setline('$', ' Line of words 2')
command('setlocal virtualedit=all')
- funcs.setpos('.', {0, 2, 1, 2, 3})
+ fn.setpos('.', { 0, 2, 1, 2, 3 })
end)
end)
@@ -665,9 +683,9 @@ describe('put command', function()
Line of words 1 test_stringx"
Line of words 2]]
run_normal_mode_tests(test_string, 'p', function()
- funcs.setline('$', ' Line of words 2')
+ fn.setline('$', ' Line of words 2')
command('setlocal virtualedit=all')
- funcs.setpos('.', {0, 1, 16, 1, 17})
+ fn.setpos('.', { 0, 1, 16, 1, 17 })
end, true)
end)
@@ -679,12 +697,10 @@ describe('put command', function()
run_normal_mode_tests(test_string, 'v2ep', nil, nil, 'Line of')
end)
describe('over trailing newline', function()
- local test_string = 'Line of test_stringx"Line of words 2'
+ local test_string = 'Line of test_stringx"Line of words 2'
run_normal_mode_tests(test_string, 'v$p', function()
- funcs.setpos('.', {0, 1, 9, 0, 9})
- end,
- nil,
- 'words 1\n')
+ fn.setpos('.', { 0, 1, 9, 0, 9 })
+ end, nil, 'words 1\n')
end)
describe('linewise mode', function()
local test_string = [[
@@ -693,8 +709,7 @@ describe('put command', function()
local function expect_vis_linewise(expect_base, conversion_table)
return expect_creator(function(e, c)
return convert_linewise(e, c, nil, nil)
- end,
- expect_base, conversion_table)
+ end, expect_base, conversion_table)
end
run_test_variations(
create_test_defs(
@@ -704,19 +719,20 @@ describe('put command', function()
test_string,
expect_vis_linewise
),
- function() funcs.setpos('.', {0, 1, 1, 0, 1}) end
+ function()
+ fn.setpos('.', { 0, 1, 1, 0, 1 })
+ end
)
describe('with whitespace at bol', function()
local function expect_vis_lineindented(expect_base, conversion_table)
local test_expect = expect_creator(function(e, c)
- return convert_linewise(e, c, nil, nil, ' ')
- end,
- expect_base, conversion_table)
+ return convert_linewise(e, c, nil, nil, ' ')
+ end, expect_base, conversion_table)
return function(exception_table, after_redo)
test_expect(exception_table, after_redo)
if not conversion_table.put_backwards then
- eq('Line of words 1\n', funcs.getreg('"'))
+ eq('Line of words 1\n', fn.getreg('"'))
end
end
end
@@ -733,11 +749,10 @@ describe('put command', function()
),
function()
feed('i test_string.<esc>u')
- funcs.setreg('"', ' test_string"', 'v')
+ fn.setreg('"', ' test_string"', 'v')
end
)
end)
-
end)
describe('blockwise visual mode', function()
@@ -747,39 +762,37 @@ describe('put command', function()
local function expect_block_creator(expect_base, conversion_table)
local test_expect = expect_creator(function(e, c)
- return convert_blockwise(e, c, true)
- end, expect_base, conversion_table)
- return function(e,c)
- test_expect(e,c)
+ return convert_blockwise(e, c, true)
+ end, expect_base, conversion_table)
+ return function(e, c)
+ test_expect(e, c)
if not conversion_table.put_backwards then
- eq('Lin\nLin', funcs.getreg('"'))
+ eq('Lin\nLin', fn.getreg('"'))
end
end
end
local select_down_test_defs = create_test_defs(
- normal_command_defs,
- '<C-v>jllp',
- create_p_action,
- test_base,
- expect_block_creator
+ normal_command_defs,
+ '<C-v>jllp',
+ create_p_action,
+ test_base,
+ expect_block_creator
)
run_test_variations(select_down_test_defs)
-
-- Undo and redo of a visual block put leave the cursor in the top
-- left of the visual block area no matter where the cursor was
-- when it started.
local undo_redo_no = map(function(table)
- local rettab = copy_def(table)
- if not rettab[4] then
- rettab[4] = {}
- end
- rettab[4].undo_position = true
- rettab[4].redo_position = true
- return rettab
- end,
- normal_command_defs)
+ local rettab = copy_def(table)
+ if not rettab[4] then
+ rettab[4] = {}
+ end
+ rettab[4].undo_position = true
+ rettab[4].redo_position = true
+ return rettab
+ end, normal_command_defs)
-- Selection direction doesn't matter
run_test_variations(
@@ -790,7 +803,9 @@ describe('put command', function()
test_base,
expect_block_creator
),
- function() funcs.setpos('.', {0, 2, 1, 0, 1}) end
+ function()
+ fn.setpos('.', { 0, 2, 1, 0, 1 })
+ end
)
describe('blockwise cursor after undo', function()
@@ -800,62 +815,45 @@ describe('put command', function()
-- the same pattern as everything else.
-- Here we fix this by directly checking the undo/redo position
-- in the test_assertions of our test definitions.
- local function assertion_creator(_,_)
- return function(_,_)
+ local function assertion_creator(_, _)
+ return function(_, _)
feed('u')
-- Have to use feed('u') here to set curswant, because
-- ex_undo() doesn't do that.
- eq({0, 1, 1, 0, 1}, funcs.getcurpos())
+ eq({ 0, 1, 1, 0, 1 }, fn.getcurpos())
feed('<C-r>')
- eq({0, 1, 1, 0, 1}, funcs.getcurpos())
+ eq({ 0, 1, 1, 0, 1 }, fn.getcurpos())
end
end
run_test_variations(
- create_test_defs(
- undo_redo_no,
- '<C-v>kllp',
- create_p_action,
- test_base,
- assertion_creator
- ),
- function() funcs.setpos('.', {0, 2, 1, 0, 1}) end
+ create_test_defs(undo_redo_no, '<C-v>kllp', create_p_action, test_base, assertion_creator),
+ function()
+ fn.setpos('.', { 0, 2, 1, 0, 1 })
+ end
)
end)
end)
-
describe("with 'virtualedit'", function()
describe('splitting a tab character', function()
local base_expect_string = [[
Line of words 1
test_stringx" Line of words 2]]
- run_normal_mode_tests(
- base_expect_string,
- 'vp',
- function()
- funcs.setline('$', ' Line of words 2')
- command('setlocal virtualedit=all')
- funcs.setpos('.', {0, 2, 1, 2, 3})
- end,
- nil,
- ' '
- )
+ run_normal_mode_tests(base_expect_string, 'vp', function()
+ fn.setline('$', ' Line of words 2')
+ command('setlocal virtualedit=all')
+ fn.setpos('.', { 0, 2, 1, 2, 3 })
+ end, nil, ' ')
end)
describe('after end of line', function()
local base_expect_string = [[
Line of words 1 test_stringx"
Line of words 2]]
- run_normal_mode_tests(
- base_expect_string,
- 'vp',
- function()
- command('setlocal virtualedit=all')
- funcs.setpos('.', {0, 1, 16, 2, 18})
- end,
- true,
- ' '
- )
+ run_normal_mode_tests(base_expect_string, 'vp', function()
+ command('setlocal virtualedit=all')
+ fn.setpos('.', { 0, 1, 16, 2, 18 })
+ end, true, ' ')
end)
end)
end)
@@ -873,9 +871,12 @@ describe('put command', function()
Line of words 1
Line of words 2]])
feed('u1go<C-v>j".p')
- eq([[
+ eq(
+ [[
ine of words 1
- ine of words 2]], curbuf_contents())
+ ine of words 2]],
+ curbuf_contents()
+ )
end)
local screen
@@ -891,33 +892,42 @@ describe('put command', function()
end
helpers.ok(not screen.bell and not screen.visualbell)
actions()
- screen:expect{condition=function()
- if should_ring then
- if not screen.bell and not screen.visualbell then
- error('Bell was not rung after action')
- end
- else
- if screen.bell or screen.visualbell then
- error('Bell was rung after action')
+ screen:expect {
+ condition = function()
+ if should_ring then
+ if not screen.bell and not screen.visualbell then
+ error('Bell was not rung after action')
+ end
+ else
+ if screen.bell or screen.visualbell then
+ error('Bell was rung after action')
+ end
end
- end
- end, unchanged=(not should_ring)}
+ end,
+ unchanged = not should_ring,
+ }
screen.bell = false
screen.visualbell = false
end
it('should not ring the bell with gp at end of line', function()
- bell_test(function() feed('$".gp') end)
+ bell_test(function()
+ feed('$".gp')
+ end)
-- Even if the last character is a multibyte character.
reset()
- funcs.setline(1, 'helloม')
- bell_test(function() feed('$".gp') end)
+ fn.setline(1, 'helloม')
+ bell_test(function()
+ feed('$".gp')
+ end)
end)
it('should not ring the bell with gp and end of file', function()
- funcs.setpos('.', {0, 2, 1, 0})
- bell_test(function() feed('$vl".gp') end)
+ fn.setpos('.', { 0, 2, 1, 0 })
+ bell_test(function()
+ feed('$vl".gp')
+ end)
end)
it('should ring the bell when deleting if not appropriate', function()
@@ -926,13 +936,15 @@ describe('put command', function()
expect([[
ine of words 1
Line of words 2]])
- bell_test(function() feed('".P') end, true)
+ bell_test(function()
+ feed('".P')
+ end, true)
end)
it('should restore cursor position after undo of ".p', function()
- local origpos = funcs.getcurpos()
+ local origpos = fn.getcurpos()
feed('".pu')
- eq(origpos, funcs.getcurpos())
+ eq(origpos, fn.getcurpos())
end)
it("should be unaffected by 'autoindent' with V\".2p", function()
@@ -946,4 +958,3 @@ describe('put command', function()
end)
end)
end)
-
diff --git a/test/functional/editor/search_spec.lua b/test/functional/editor/search_spec.lua
index d5df131725..46a3e298b7 100644
--- a/test/functional/editor/search_spec.lua
+++ b/test/functional/editor/search_spec.lua
@@ -8,10 +8,7 @@ describe('search (/)', function()
before_each(clear)
it('fails with huge column (%c) value #9930', function()
- eq([[Vim:E951: \% value too large]],
- pcall_err(command, "/\\v%18446744071562067968c"))
- eq([[Vim:E951: \% value too large]],
- pcall_err(command, "/\\v%2147483648c"))
+ eq([[Vim:E951: \% value too large]], pcall_err(command, '/\\v%18446744071562067968c'))
+ eq([[Vim:E951: \% value too large]], pcall_err(command, '/\\v%2147483648c'))
end)
end)
-
diff --git a/test/functional/editor/tabpage_spec.lua b/test/functional/editor/tabpage_spec.lua
index a7f629a76b..0cbc2dbf3d 100644
--- a/test/functional/editor/tabpage_spec.lua
+++ b/test/functional/editor/tabpage_spec.lua
@@ -8,9 +8,9 @@ local neq = helpers.neq
local feed = helpers.feed
local eval = helpers.eval
local exec = helpers.exec
-local funcs = helpers.funcs
-local meths = helpers.meths
-local curwin = helpers.curwin
+local fn = helpers.fn
+local api = helpers.api
+local curwin = helpers.api.nvim_get_current_win
local assert_alive = helpers.assert_alive
describe('tabpage', function()
@@ -58,7 +58,9 @@ describe('tabpage', function()
end)
it('no segfault with strange WinClosed autocommand #20290', function()
- pcall(exec, [[
+ pcall(
+ exec,
+ [[
set nohidden
edit Xa
split Xb
@@ -66,45 +68,46 @@ describe('tabpage', function()
new
autocmd WinClosed * tabprev | bwipe!
close
- ]])
+ ]]
+ )
assert_alive()
end)
it('nvim_win_close and nvim_win_hide update tabline #20285', function()
- eq(1, #meths.list_tabpages())
- eq({1, 1}, funcs.win_screenpos(0))
- local win1 = curwin().id
+ eq(1, #api.nvim_list_tabpages())
+ eq({ 1, 1 }, fn.win_screenpos(0))
+ local win1 = curwin()
command('tabnew')
- eq(2, #meths.list_tabpages())
- eq({2, 1}, funcs.win_screenpos(0))
- local win2 = curwin().id
+ eq(2, #api.nvim_list_tabpages())
+ eq({ 2, 1 }, fn.win_screenpos(0))
+ local win2 = curwin()
- meths.win_close(win1, true)
- eq(win2, curwin().id)
- eq(1, #meths.list_tabpages())
- eq({1, 1}, funcs.win_screenpos(0))
+ api.nvim_win_close(win1, true)
+ eq(win2, curwin())
+ eq(1, #api.nvim_list_tabpages())
+ eq({ 1, 1 }, fn.win_screenpos(0))
command('tabnew')
- eq(2, #meths.list_tabpages())
- eq({2, 1}, funcs.win_screenpos(0))
- local win3 = curwin().id
-
- meths.win_hide(win2)
- eq(win3, curwin().id)
- eq(1, #meths.list_tabpages())
- eq({1, 1}, funcs.win_screenpos(0))
+ eq(2, #api.nvim_list_tabpages())
+ eq({ 2, 1 }, fn.win_screenpos(0))
+ local win3 = curwin()
+
+ api.nvim_win_hide(win2)
+ eq(win3, curwin())
+ eq(1, #api.nvim_list_tabpages())
+ eq({ 1, 1 }, fn.win_screenpos(0))
end)
it('switching tabpage after setting laststatus=3 #19591', function()
local screen = Screen.new(40, 8)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {bold = true, reverse = true}, -- StatusLine
- [2] = {reverse = true}, -- TabLineFill
- [3] = {bold = true}, -- TabLineSel
- [4] = {background = Screen.colors.LightGrey, underline = true}, -- TabLine
- [5] = {bold = true, foreground = Screen.colors.Magenta},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { bold = true, reverse = true }, -- StatusLine
+ [2] = { reverse = true }, -- TabLineFill
+ [3] = { bold = true }, -- TabLineSel
+ [4] = { background = Screen.colors.LightGrey, underline = true }, -- TabLine
+ [5] = { bold = true, foreground = Screen.colors.Magenta },
})
screen:attach()
@@ -116,10 +119,7 @@ describe('tabpage', function()
screen:expect([[
{4: [No Name] }{3: [No Name] }{2: }{4:X}|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{1:[No Name] }|
"[No Name]" --No lines in buffer-- |
]])
@@ -127,26 +127,23 @@ describe('tabpage', function()
screen:expect([[
{4: [No Name] }{3: }{5:2}{3: [No Name] }{2: }{4:X}|
^ │ |
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
+ {0:~ }│{0:~ }|*4
{1:[No Name] }|
"[No Name]" --No lines in buffer-- |
]])
end)
- it(":tabmove handles modifiers and addr", function()
+ it(':tabmove handles modifiers and addr', function()
command('tabnew | tabnew | tabnew')
- eq(4, funcs.nvim_tabpage_get_number(0))
+ eq(4, fn.nvim_tabpage_get_number(0))
command(' silent :keepalt :: ::: silent! - tabmove')
- eq(3, funcs.nvim_tabpage_get_number(0))
+ eq(3, fn.nvim_tabpage_get_number(0))
command(' silent :keepalt :: ::: silent! -2 tabmove')
- eq(1, funcs.nvim_tabpage_get_number(0))
+ eq(1, fn.nvim_tabpage_get_number(0))
end)
it(':tabs does not overflow IObuff with long path with comma #20850', function()
- meths.buf_set_name(0, ('x'):rep(1024) .. ',' .. ('x'):rep(1024))
+ api.nvim_buf_set_name(0, ('x'):rep(1024) .. ',' .. ('x'):rep(1024))
command('tabs')
assert_alive()
end)
diff --git a/test/functional/editor/undo_spec.lua b/test/functional/editor/undo_spec.lua
index d66ab352ef..c101bf02a0 100644
--- a/test/functional/editor/undo_spec.lua
+++ b/test/functional/editor/undo_spec.lua
@@ -8,12 +8,12 @@ local eq = helpers.eq
local feed = helpers.feed
local feed_command = helpers.feed_command
local insert = helpers.insert
-local funcs = helpers.funcs
+local fn = helpers.fn
local exec = helpers.exec
local exec_lua = helpers.exec_lua
local function lastmessage()
- local messages = funcs.split(funcs.execute('messages'), '\n')
+ local messages = fn.split(fn.execute('messages'), '\n')
return messages[#messages]
end
@@ -21,15 +21,23 @@ describe('u CTRL-R g- g+', function()
before_each(clear)
local function create_history(num_steps)
- if num_steps == 0 then return end
+ if num_steps == 0 then
+ return
+ end
insert('1')
- if num_steps == 1 then return end
+ if num_steps == 1 then
+ return
+ end
feed('o2<esc>')
feed('o3<esc>')
feed('u')
- if num_steps == 2 then return end
+ if num_steps == 2 then
+ return
+ end
feed('o4<esc>')
- if num_steps == 3 then return end
+ if num_steps == 3 then
+ return
+ end
feed('u')
end
@@ -57,13 +65,23 @@ describe('u CTRL-R g- g+', function()
undo_and_redo(2, 'g-', 'g+', '1')
end)
it('undoes properly around a branch point', function()
- undo_and_redo(3, 'u', '<C-r>', [[
+ undo_and_redo(
+ 3,
+ 'u',
+ '<C-r>',
+ [[
1
- 2]])
- undo_and_redo(3, 'g-', 'g+', [[
+ 2]]
+ )
+ undo_and_redo(
+ 3,
+ 'g-',
+ 'g+',
+ [[
1
2
- 3]])
+ 3]]
+ )
end)
it('can find the previous sequence after undoing to a branch', function()
undo_and_redo(4, 'u', '<C-r>', '1')
diff --git a/test/functional/ex_cmds/append_spec.lua b/test/functional/ex_cmds/append_spec.lua
index 4134eed87e..5eb8d49c74 100644
--- a/test/functional/ex_cmds/append_spec.lua
+++ b/test/functional/ex_cmds/append_spec.lua
@@ -5,21 +5,20 @@ local dedent = helpers.dedent
local exec = helpers.exec
local feed = helpers.feed
local clear = helpers.clear
-local funcs = helpers.funcs
+local fn = helpers.fn
local command = helpers.command
-local curbufmeths = helpers.curbufmeths
-local meths = helpers.meths
+local api = helpers.api
local Screen = require('test.functional.ui.screen')
local cmdtest = function(cmd, prep, ret1)
describe(':' .. cmd, function()
before_each(function()
clear()
- curbufmeths.set_lines(0, 1, true, { 'foo', 'bar', 'baz' })
+ api.nvim_buf_set_lines(0, 0, 1, true, { 'foo', 'bar', 'baz' })
end)
local buffer_contents = function()
- return curbufmeths.get_lines(0, -1, false)
+ return api.nvim_buf_get_lines(0, 0, -1, false)
end
it(cmd .. 's' .. prep .. ' the current line by default', function()
@@ -29,8 +28,7 @@ local cmdtest = function(cmd, prep, ret1)
-- Used to crash because this invokes history processing which uses
-- hist_char2type which after fdb68e35e4c729c7ed097d8ade1da29e5b3f4b31
-- crashed.
- it(cmd .. 's' .. prep .. ' the current line by default when feeding',
- function()
+ it(cmd .. 's' .. prep .. ' the current line by default when feeding', function()
feed(':' .. cmd .. '\nabc\ndef\n.\n')
eq(ret1, buffer_contents())
end)
@@ -40,15 +38,15 @@ local cmdtest = function(cmd, prep, ret1)
feed(':' .. hisline .. '<CR>')
feed(':' .. cmd .. '<CR>abc<CR>def<C-f>')
eq({ 'def' }, buffer_contents())
- eq(hisline, funcs.histget(':', -2))
- eq(cmd, funcs.histget(':'))
+ eq(hisline, fn.histget(':', -2))
+ eq(cmd, fn.histget(':'))
-- Test that command-line window was launched
- eq('nofile', meths.get_option_value('buftype', {}))
- eq('n', funcs.mode(1))
+ eq('nofile', api.nvim_get_option_value('buftype', {}))
+ eq('n', fn.mode(1))
feed('<CR>')
- eq('c', funcs.mode(1))
+ eq('c', fn.mode(1))
feed('.<CR>')
- eq('n', funcs.mode(1))
+ eq('n', fn.mode(1))
eq(ret1, buffer_contents())
end)
end)
@@ -63,8 +61,8 @@ describe('the first line is redrawn correctly after inserting text in an empty b
clear()
screen = Screen.new(20, 8)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue},
- [2] = {bold = true, reverse = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { bold = true, reverse = true },
})
screen:attach()
end)
@@ -78,11 +76,7 @@ describe('the first line is redrawn correctly after inserting text in an empty b
screen:expect([[
aaaaa |
^bbbbb |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
end)
@@ -96,11 +90,7 @@ describe('the first line is redrawn correctly after inserting text in an empty b
screen:expect([[
aaaaa |
^bbbbb |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
end)
diff --git a/test/functional/ex_cmds/arg_spec.lua b/test/functional/ex_cmds/arg_spec.lua
index 4dea50b53e..810b001ec0 100644
--- a/test/functional/ex_cmds/arg_spec.lua
+++ b/test/functional/ex_cmds/arg_spec.lua
@@ -1,30 +1,30 @@
-local helpers = require("test.functional.helpers")(after_each)
-local eq, command, funcs = helpers.eq, helpers.command, helpers.funcs
+local helpers = require('test.functional.helpers')(after_each)
+local eq, command, fn = helpers.eq, helpers.command, helpers.fn
local ok = helpers.ok
local clear = helpers.clear
-describe(":argument", function()
+describe(':argument', function()
before_each(function()
clear()
end)
- it("does not restart :terminal buffer", function()
- command("terminal")
- helpers.feed([[<C-\><C-N>]])
- command("argadd")
- helpers.feed([[<C-\><C-N>]])
- local bufname_before = funcs.bufname("%")
- local bufnr_before = funcs.bufnr("%")
- helpers.ok(nil ~= string.find(bufname_before, "^term://")) -- sanity
+ it('does not restart :terminal buffer', function()
+ command('terminal')
+ helpers.feed([[<C-\><C-N>]])
+ command('argadd')
+ helpers.feed([[<C-\><C-N>]])
+ local bufname_before = fn.bufname('%')
+ local bufnr_before = fn.bufnr('%')
+ helpers.ok(nil ~= string.find(bufname_before, '^term://')) -- sanity
- command("argument 1")
- helpers.feed([[<C-\><C-N>]])
+ command('argument 1')
+ helpers.feed([[<C-\><C-N>]])
- local bufname_after = funcs.bufname("%")
- local bufnr_after = funcs.bufnr("%")
- eq("["..bufname_before.."]", helpers.eval('trim(execute("args"))'))
- ok(funcs.line('$') > 1)
- eq(bufname_before, bufname_after)
- eq(bufnr_before, bufnr_after)
+ local bufname_after = fn.bufname('%')
+ local bufnr_after = fn.bufnr('%')
+ eq('[' .. bufname_before .. ']', helpers.eval('trim(execute("args"))'))
+ ok(fn.line('$') > 1)
+ eq(bufname_before, bufname_after)
+ eq(bufnr_before, bufnr_after)
end)
end)
diff --git a/test/functional/ex_cmds/cd_spec.lua b/test/functional/ex_cmds/cd_spec.lua
index b6a3713158..1815c672dc 100644
--- a/test/functional/ex_cmds/cd_spec.lua
+++ b/test/functional/ex_cmds/cd_spec.lua
@@ -1,6 +1,5 @@
-- Specs for :cd, :tcd, :lcd and getcwd()
-local luv = require('luv')
local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
@@ -21,18 +20,30 @@ local directories = {
}
-- Shorthand writing to get the current working directory
-local cwd = function(...) return call('getcwd', ...) end -- effective working dir
-local wcwd = function() return cwd(0) end -- window dir
-local tcwd = function() return cwd(-1, 0) end -- tab dir
+local cwd = function(...)
+ return call('getcwd', ...)
+end -- effective working dir
+local wcwd = function()
+ return cwd(0)
+end -- window dir
+local tcwd = function()
+ return cwd(-1, 0)
+end -- tab dir
-- Same, except these tell us if there is a working directory at all
-local lwd = function(...) return call('haslocaldir', ...) end -- effective working dir
-local wlwd = function() return lwd(0) end -- window dir
-local tlwd = function() return lwd(-1, 0) end -- tab dir
+local lwd = function(...)
+ return call('haslocaldir', ...)
+end -- effective working dir
+local wlwd = function()
+ return lwd(0)
+end -- window dir
+local tlwd = function()
+ return lwd(-1, 0)
+end -- tab dir
--local glwd = function() return eval('haslocaldir(-1, -1)') end -- global dir
-- Test both the `cd` and `chdir` variants
-for _, cmd in ipairs {'cd', 'chdir'} do
+for _, cmd in ipairs { 'cd', 'chdir' } do
describe(':' .. cmd, function()
before_each(function()
clear()
@@ -44,7 +55,7 @@ for _, cmd in ipairs {'cd', 'chdir'} do
after_each(function()
for _, d in pairs(directories) do
- luv.fs_rmdir(d)
+ vim.uv.fs_rmdir(d)
end
end)
@@ -168,23 +179,23 @@ for _, cmd in ipairs {'cd', 'chdir'} do
-- Create a new tab first and verify that is has the same working dir
command('tabnew')
eq(globalDir, cwd())
- eq(globalDir, tcwd()) -- has no tab-local directory
+ eq(globalDir, tcwd()) -- has no tab-local directory
eq(0, tlwd())
- eq(globalDir, wcwd()) -- has no window-local directory
+ eq(globalDir, wcwd()) -- has no window-local directory
eq(0, wlwd())
-- Change tab-local working directory and verify it is different
command('silent t' .. cmd .. ' ' .. directories.tab)
eq(globalDir .. pathsep .. directories.tab, cwd())
- eq(cwd(), tcwd()) -- working directory matches tab directory
+ eq(cwd(), tcwd()) -- working directory matches tab directory
eq(1, tlwd())
- eq(cwd(), wcwd()) -- still no window-directory
+ eq(cwd(), wcwd()) -- still no window-directory
eq(0, wlwd())
-- Create a new window in this tab to test `:lcd`
command('new')
- eq(1, tlwd()) -- Still tab-local working directory
- eq(0, wlwd()) -- Still no window-local working directory
+ eq(1, tlwd()) -- Still tab-local working directory
+ eq(0, wlwd()) -- Still no window-local working directory
eq(globalDir .. pathsep .. directories.tab, cwd())
command('silent l' .. cmd .. ' ../' .. directories.window)
eq(globalDir .. pathsep .. directories.window, cwd())
@@ -193,13 +204,13 @@ for _, cmd in ipairs {'cd', 'chdir'} do
-- Verify the first window still has the tab local directory
command('wincmd w')
- eq(globalDir .. pathsep .. directories.tab, cwd())
+ eq(globalDir .. pathsep .. directories.tab, cwd())
eq(globalDir .. pathsep .. directories.tab, tcwd())
- eq(0, wlwd()) -- No window-local directory
+ eq(0, wlwd()) -- No window-local directory
-- Change back to initial tab and verify working directory has stayed
command('tabnext')
- eq(globalDir, cwd() )
+ eq(globalDir, cwd())
eq(0, tlwd())
eq(0, wlwd())
@@ -207,31 +218,31 @@ for _, cmd in ipairs {'cd', 'chdir'} do
command('silent ' .. cmd .. ' ' .. directories.global)
eq(globalDir .. pathsep .. directories.global, cwd())
command('tabnext')
- eq(globalDir .. pathsep .. directories.tab, cwd())
+ eq(globalDir .. pathsep .. directories.tab, cwd())
eq(globalDir .. pathsep .. directories.tab, tcwd())
- eq(0, wlwd()) -- Still no window-local directory in this window
+ eq(0, wlwd()) -- Still no window-local directory in this window
-- Unless the global change happened in a tab with local directory
command('silent ' .. cmd .. ' ..')
- eq(globalDir, cwd() )
- eq(0 , tlwd())
- eq(0 , wlwd())
+ eq(globalDir, cwd())
+ eq(0, tlwd())
+ eq(0, wlwd())
-- Which also affects the first tab
command('tabnext')
eq(globalDir, cwd())
-- But not in a window with its own local directory
command('tabnext | wincmd w')
- eq(globalDir .. pathsep .. directories.window, cwd() )
- eq(0 , tlwd())
+ eq(globalDir .. pathsep .. directories.window, cwd())
+ eq(0, tlwd())
eq(globalDir .. pathsep .. directories.window, wcwd())
end)
end)
end
-- Test legal parameters for 'getcwd' and 'haslocaldir'
-for _, cmd in ipairs {'getcwd', 'haslocaldir'} do
- describe(cmd..'()', function()
+for _, cmd in ipairs { 'getcwd', 'haslocaldir' } do
+ describe(cmd .. '()', function()
before_each(function()
clear()
end)
@@ -271,7 +282,7 @@ for _, cmd in ipairs {'getcwd', 'haslocaldir'} do
end)
end
-describe("getcwd()", function ()
+describe('getcwd()', function()
before_each(function()
clear()
mkdir(directories.global)
@@ -281,11 +292,11 @@ describe("getcwd()", function ()
helpers.rmdir(directories.global)
end)
- it("returns empty string if working directory does not exist", function()
+ it('returns empty string if working directory does not exist', function()
skip(is_os('win'))
- command("cd "..directories.global)
- command("call delete('../"..directories.global.."', 'd')")
- eq("", helpers.eval("getcwd()"))
+ command('cd ' .. directories.global)
+ command("call delete('../" .. directories.global .. "', 'd')")
+ eq('', helpers.eval('getcwd()'))
end)
it("works with 'autochdir' after local directory was set (#9892)", function()
diff --git a/test/functional/ex_cmds/cmd_map_spec.lua b/test/functional/ex_cmds/cmd_map_spec.lua
index 2a2628350d..cb7d7340e2 100644
--- a/test/functional/ex_cmds/cmd_map_spec.lua
+++ b/test/functional/ex_cmds/cmd_map_spec.lua
@@ -4,7 +4,7 @@ local feed = helpers.feed
local eq = helpers.eq
local expect = helpers.expect
local eval = helpers.eval
-local funcs = helpers.funcs
+local fn = helpers.fn
local insert = helpers.insert
local write_file = helpers.write_file
local exc_exec = helpers.exc_exec
@@ -16,24 +16,24 @@ describe('mappings with <Cmd>', function()
local tmpfile = 'X_ex_cmds_cmd_map'
local function cmdmap(lhs, rhs)
- command('noremap '..lhs..' <Cmd>'..rhs..'<cr>')
- command('noremap! '..lhs..' <Cmd>'..rhs..'<cr>')
+ command('noremap ' .. lhs .. ' <Cmd>' .. rhs .. '<cr>')
+ command('noremap! ' .. lhs .. ' <Cmd>' .. rhs .. '<cr>')
end
before_each(function()
clear()
screen = Screen.new(65, 8)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [4] = {bold = true},
- [5] = {background = Screen.colors.LightGrey},
- [6] = {foreground = Screen.colors.Blue1},
- [7] = {bold = true, reverse = true},
- [8] = {background = Screen.colors.WebGray},
- [9] = {background = Screen.colors.LightMagenta},
- [10] = {foreground = Screen.colors.Red},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [4] = { bold = true },
+ [5] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey },
+ [6] = { foreground = Screen.colors.Blue1 },
+ [7] = { bold = true, reverse = true },
+ [8] = { background = Screen.colors.WebGray },
+ [9] = { background = Screen.colors.LightMagenta },
+ [10] = { foreground = Screen.colors.Red },
})
screen:attach()
@@ -57,7 +57,7 @@ describe('mappings with <Cmd>', function()
feed('gg')
cmdmap('<F8>', 'startinsert')
cmdmap('<F9>', 'stopinsert')
- command("abbr foo <Cmd>let g:y = 17<cr>bar")
+ command('abbr foo <Cmd>let g:y = 17<cr>bar')
end)
after_each(function()
@@ -69,11 +69,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
^some short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{6:<F3>} {6:*} {6:<Cmd>}let m = mode(1){6:<CR>} |
]])
end)
@@ -85,11 +81,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
^some short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:E1136: <Cmd> mapping must end with <CR> before second <Cmd>} |
]])
@@ -98,11 +90,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
^some short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:E1255: <Cmd> mapping must end with <CR>} |
]])
eq(0, eval('x'))
@@ -114,11 +102,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
some short lines |
^of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
@@ -127,11 +111,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
some short lines |
of ^test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
end)
@@ -141,7 +121,7 @@ describe('mappings with <Cmd>', function()
feed('<F3>')
eq('foo…bar', eval('g:str'))
local str = eval([["foo\<D-…>bar"]])
- command([[noremap <F3> <Cmd>let g:str = ']]..str..[['<CR>]])
+ command([[noremap <F3> <Cmd>let g:str = ']] .. str .. [['<CR>]])
feed('<F3>')
eq(str, eval('g:str'))
command([[noremap <F3> <Cmd>let g:str = 'foo<D-…>bar'<CR>]])
@@ -180,7 +160,7 @@ describe('mappings with <Cmd>', function()
eq('n', eval('mode(1)'))
-- operator-pending mode
- feed("d<F3>")
+ feed('d<F3>')
eq('no', eval('m'))
-- did leave operator-pending mode
eq('n', eval('mode(1)'))
@@ -191,21 +171,21 @@ describe('mappings with <Cmd>', function()
eq('i', eval('mode(1)'))
-- replace mode
- feed("<Ins><F3>")
+ feed('<Ins><F3>')
eq('R', eval('m'))
eq('R', eval('mode(1)'))
feed('<esc>')
eq('n', eval('mode(1)'))
-- virtual replace mode
- feed("gR<F3>")
+ feed('gR<F3>')
eq('Rv', eval('m'))
eq('Rv', eval('mode(1)'))
feed('<esc>')
eq('n', eval('mode(1)'))
-- langmap works, but is not distinguished in mode(1)
- feed(":set iminsert=1<cr>i<F3>")
+ feed(':set iminsert=1<cr>i<F3>')
eq('i', eval('m'))
eq('i', eval('mode(1)'))
feed('<esc>')
@@ -232,26 +212,22 @@ describe('mappings with <Cmd>', function()
-- check v:count and v:register works
feed('<F2>')
- eq({'n', 0, '"'}, eval('s'))
+ eq({ 'n', 0, '"' }, eval('s'))
feed('7<F2>')
- eq({'n', 7, '"'}, eval('s'))
+ eq({ 'n', 7, '"' }, eval('s'))
feed('"e<F2>')
- eq({'n', 0, 'e'}, eval('s'))
+ eq({ 'n', 0, 'e' }, eval('s'))
feed('5"k<F2>')
- eq({'n', 5, 'k'}, eval('s'))
+ eq({ 'n', 5, 'k' }, eval('s'))
feed('"+2<F2>')
- eq({'n', 2, '+'}, eval('s'))
+ eq({ 'n', 2, '+' }, eval('s'))
-- text object enters visual mode
feed('<F7>')
screen:expect([[
so{5:me short lines} |
{5:of }^test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- VISUAL --} |
]])
feed('<esc>')
@@ -269,15 +245,11 @@ describe('mappings with <Cmd>', function()
screen:expect([[
some short lines |
of alpha^test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- INSERT --} |
]])
-- feedkeys were not executed immediately
- eq({'n', 'of test text'}, eval('[m,a]'))
+ eq({ 'n', 'of test text' }, eval('[m,a]'))
eq('i', eval('mode(1)'))
feed('<esc>')
@@ -285,15 +257,11 @@ describe('mappings with <Cmd>', function()
screen:expect([[
some short lines |
of alphabet^atest text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
-- feedkeys(..., 'x') was executed immediately, but insert mode gets aborted
- eq({'n', 'of alphabetatest text'}, eval('[m,b]'))
+ eq({ 'n', 'of alphabetatest text' }, eval('[m,b]'))
eq('n', eval('mode(1)'))
end)
@@ -302,45 +270,39 @@ describe('mappings with <Cmd>', function()
command('noremap ,f <Cmd>nosuchcommand<cr>')
command('noremap ,e <Cmd>throw "very error"\\| call append(1, "yy")<cr>')
command('noremap ,m <Cmd>echoerr "The message."\\| call append(1, "zz")<cr>')
- command('noremap ,w <Cmd>for i in range(5)\\|if i==1\\|echoerr "Err"\\|endif\\|call append(1, i)\\|endfor<cr>')
+ command(
+ 'noremap ,w <Cmd>for i in range(5)\\|if i==1\\|echoerr "Err"\\|endif\\|call append(1, i)\\|endfor<cr>'
+ )
- feed(":normal ,x<cr>")
+ feed(':normal ,x<cr>')
screen:expect([[
^some short lines |
aa |
xx |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
:normal ,x |
]])
- eq('Vim:E492: Not an editor command: nosuchcommand', exc_exec("normal ,f"))
- eq('very error', exc_exec("normal ,e"))
- eq('Vim(echoerr):The message.', exc_exec("normal ,m"))
+ eq('Vim:E492: Not an editor command: nosuchcommand', exc_exec('normal ,f'))
+ eq('very error', exc_exec('normal ,e'))
+ eq('Vim(echoerr):The message.', exc_exec('normal ,m'))
feed('w')
screen:expect([[
some ^short lines |
aa |
xx |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
:normal ,x |
]])
command(':%d')
- eq('Vim(echoerr):Err', exc_exec("normal ,w"))
+ eq('Vim(echoerr):Err', exc_exec('normal ,w'))
screen:expect([[
^ |
0 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
--No lines in buffer-- |
]])
@@ -364,27 +326,22 @@ describe('mappings with <Cmd>', function()
screen:expect([[
{5:some short }^lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- VISUAL --} |
]])
- eq('v', funcs.mode(1))
+ eq('v', fn.mode(1))
-- can invoke operator, ending visual mode
feed('<F5>')
- eq('n', funcs.mode(1))
- eq({'some short l'}, funcs.getreg('a',1,1))
+ eq('n', fn.mode(1))
+ eq({ 'some short l' }, fn.getreg('a', 1, 1))
-- error doesn't interrupt visual mode
feed('ggvw<F6>')
screen:expect([[
{5:some }short lines |
of test text |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{7: }|
{2:Error detected while processing :} |
{2:E605: Exception not caught: very error} |
@@ -396,37 +353,25 @@ describe('mappings with <Cmd>', function()
screen:expect([[
{5:some }^short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- VISUAL --} |
]])
- eq('v', funcs.mode(1))
+ eq('v', fn.mode(1))
feed('<F7>')
screen:expect([[
so{5:me short lines} |
{5:of }^test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- VISUAL --} |
]])
- eq('v', funcs.mode(1))
+ eq('v', fn.mode(1))
-- startinsert gives "-- (insert) VISUAL --" mode
feed('<F8>')
screen:expect([[
so{5:me short lines} |
{5:of }^test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- (insert) VISUAL --} |
]])
eq('v', eval('mode(1)'))
@@ -442,32 +387,27 @@ describe('mappings with <Cmd>', function()
screen:expect([[
{5:some short }^lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- SELECT --} |
]])
- eq('s', funcs.mode(1))
+ eq('s', fn.mode(1))
-- visual mapping in select mode restart select mode after operator
feed('<F5>')
- eq('s', funcs.mode(1))
- eq({'some short l'}, funcs.getreg('a',1,1))
+ eq('s', fn.mode(1))
+ eq({ 'some short l' }, fn.getreg('a', 1, 1))
-- select mode mapping works, and does not restart select mode
feed('<F2>')
- eq('n', funcs.mode(1))
- eq({'some short l'}, funcs.getreg('b',1,1))
+ eq('n', fn.mode(1))
+ eq({ 'some short l' }, fn.getreg('b', 1, 1))
-- error doesn't interrupt temporary visual mode
feed('<esc>ggvw<c-g><F6>')
screen:expect([[
{5:some }short lines |
of test text |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{7: }|
{2:Error detected while processing :} |
{2:E605: Exception not caught: very error} |
@@ -479,23 +419,18 @@ describe('mappings with <Cmd>', function()
screen:expect([[
{5:some }^short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- VISUAL --} |
]])
-- quirk: restoration of select mode is not performed
- eq('v', funcs.mode(1))
+ eq('v', fn.mode(1))
-- error doesn't interrupt select mode
feed('<esc>ggvw<c-g><F1>')
screen:expect([[
{5:some }short lines |
of test text |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{7: }|
{2:Error detected while processing :} |
{2:E605: Exception not caught: very error} |
@@ -507,39 +442,27 @@ describe('mappings with <Cmd>', function()
screen:expect([[
{5:some }^short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- SELECT --} |
]])
-- quirk: restoration of select mode is not performed
- eq('s', funcs.mode(1))
+ eq('s', fn.mode(1))
feed('<F7>')
screen:expect([[
so{5:me short lines} |
{5:of }^test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- SELECT --} |
]])
- eq('s', funcs.mode(1))
+ eq('s', fn.mode(1))
-- startinsert gives "-- SELECT (insert) --" mode
feed('<F8>')
screen:expect([[
so{5:me short lines} |
{5:of }^test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- (insert) SELECT --} |
]])
eq('s', eval('mode(1)'))
@@ -547,17 +470,16 @@ describe('mappings with <Cmd>', function()
eq('i', eval('mode(1)'))
end)
-
it('works in operator-pending mode', function()
feed('d<F4>')
expect([[
lines
of test text]])
- eq({'some short '}, funcs.getreg('"',1,1))
+ eq({ 'some short ' }, fn.getreg('"', 1, 1))
feed('.')
expect([[
test text]])
- eq({'lines', 'of '}, funcs.getreg('"',1,1))
+ eq({ 'lines', 'of ' }, fn.getreg('"', 1, 1))
feed('uu')
expect([[
some short lines
@@ -568,8 +490,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
some short lines |
of test text |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{7: }|
{2:Error detected while processing :} |
{2:E605: Exception not caught: very error} |
@@ -584,7 +505,7 @@ describe('mappings with <Cmd>', function()
feed('"bd<F7>')
expect([[
soest text]])
- eq(funcs.getreg('b',1,1), {'me short lines', 'of t'})
+ eq(fn.getreg('b', 1, 1), { 'me short lines', 'of t' })
-- startinsert aborts operator
feed('d<F8>')
@@ -594,17 +515,12 @@ describe('mappings with <Cmd>', function()
end)
it('works in insert mode', function()
-
-- works the same as <c-o>w<c-o>w
feed('iindeed <F4>little ')
screen:expect([[
indeed some short little ^lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- INSERT --} |
]])
@@ -612,26 +528,20 @@ describe('mappings with <Cmd>', function()
screen:expect([[
indeed some short little lines |
of test text |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{7: }|
{2:Error detected while processing :} |
{2:E605: Exception not caught: very error} |
{3:Press ENTER or type command to continue}^ |
]])
-
feed('<cr>')
eq('E605: Exception not caught: very error', eval('v:errmsg'))
-- still in insert
screen:expect([[
indeed some short little ^lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- INSERT --} |
]])
eq('i', eval('mode(1)'))
@@ -643,11 +553,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
in{5:deed some short little lines} |
{5:of stuff }^test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- INSERT VISUAL --} |
]])
expect([[
@@ -655,17 +561,13 @@ describe('mappings with <Cmd>', function()
of stuff test text]])
feed('<F5>')
- eq(funcs.getreg('a',1,1), {'deed some short little lines', 'of stuff t'})
+ eq(fn.getreg('a', 1, 1), { 'deed some short little lines', 'of stuff t' })
-- still in insert
screen:expect([[
in^deed some short little lines |
of stuff test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- INSERT --} |
]])
eq('i', eval('mode(1)'))
@@ -675,11 +577,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
in bar ^deed some short little lines |
of stuff test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- INSERT --} |
]])
eq(17, eval('g:y'))
@@ -700,9 +598,7 @@ describe('mappings with <Cmd>', function()
some^ |
{8:some } |
{9:short }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{4:-- Keyword Local completion (^N^P) }{3:match 1 of 2} |
]])
@@ -717,9 +613,7 @@ describe('mappings with <Cmd>', function()
some^ |
{9:some } |
{9:short }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{4:-- Keyword Local completion (^N^P) }{10:Back at original} |
]])
end)
@@ -734,11 +628,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
^some short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:E492: Not an editor command: text} |
]])
@@ -773,11 +663,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
^some short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
eq('n', eval('mode(1)'))
@@ -786,11 +672,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
some short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:let g:x = 3^ |
]])
feed('+2<cr>')
@@ -798,11 +680,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
some short ^lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:let g:x = 3+2 |
]])
eq(5, eval('g:x'))
@@ -811,11 +689,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
some short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:let g:y = 7^ |
]])
eq('c', eval('mode(1)'))
@@ -824,16 +698,11 @@ describe('mappings with <Cmd>', function()
screen:expect([[
some short ^lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:-- INSERT --} |
]])
eq('i', eval('mode(1)'))
eq(9, eval('g:y'))
-
end)
it("doesn't crash when invoking cmdline mode recursively #8859", function()
@@ -842,11 +711,7 @@ describe('mappings with <Cmd>', function()
screen:expect([[
some short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:bar^ |
]])
@@ -854,27 +719,25 @@ describe('mappings with <Cmd>', function()
screen:expect([[
some short lines |
of test text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:barx^ |
]])
end)
- it("works with <SID> mappings", function()
+ it('works with <SID> mappings', function()
command('new!')
- write_file(tmpfile, [[
+ write_file(
+ tmpfile,
+ [[
map <f2> <Cmd>call <SID>do_it()<Cr>
function! s:do_it()
let g:x = 10
endfunction
- ]])
- command('source '..tmpfile)
+ ]]
+ )
+ command('source ' .. tmpfile)
feed('<f2>')
eq('', eval('v:errmsg'))
eq(10, eval('g:x'))
end)
end)
-
diff --git a/test/functional/ex_cmds/debug_spec.lua b/test/functional/ex_cmds/debug_spec.lua
index a4d381d3f1..85327c87e6 100644
--- a/test/functional/ex_cmds/debug_spec.lua
+++ b/test/functional/ex_cmds/debug_spec.lua
@@ -9,10 +9,10 @@ describe(':debug', function()
clear()
screen = Screen.new(30, 14)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {bold = true, reverse = true},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, reverse = true },
+ [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
})
screen:attach()
end)
@@ -20,14 +20,7 @@ describe(':debug', function()
feed(':echoerr bork<cr>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
{2: }|
{3:E121: Undefined variable: bork}|
|
@@ -38,11 +31,7 @@ describe(':debug', function()
feed(':debug echo "aa"| echo "bb"<cr>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2: }|
{3:E121: Undefined variable: bork}|
|
@@ -56,8 +45,7 @@ describe(':debug', function()
feed('step<cr>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2: }|
{3:E121: Undefined variable: bork}|
|
@@ -92,18 +80,7 @@ describe(':debug', function()
feed('<cr>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*12
|
]])
end)
diff --git a/test/functional/ex_cmds/dict_notifications_spec.lua b/test/functional/ex_cmds/dict_notifications_spec.lua
index 6a0b40bd88..fc7714d16b 100644
--- a/test/functional/ex_cmds/dict_notifications_spec.lua
+++ b/test/functional/ex_cmds/dict_notifications_spec.lua
@@ -1,6 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local assert_alive = helpers.assert_alive
-local clear, nvim, source = helpers.clear, helpers.nvim, helpers.source
+local clear, source = helpers.clear, helpers.source
+local api = helpers.api
local insert = helpers.insert
local eq, next_msg = helpers.eq, helpers.next_msg
local exc_exec = helpers.exc_exec
@@ -8,14 +9,13 @@ local exec_lua = helpers.exec_lua
local command = helpers.command
local eval = helpers.eval
-
describe('Vimscript dictionary notifications', function()
local channel
before_each(function()
clear()
- channel = nvim('get_api_info')[1]
- nvim('set_var', 'channel', channel)
+ channel = api.nvim_get_chan_info(0).id
+ api.nvim_set_var('channel', channel)
end)
-- the same set of tests are applied to top-level dictionaries(g:, b:, w: and
@@ -29,9 +29,9 @@ describe('Vimscript dictionary notifications', function()
key = 'watched'
end
if opval == '' then
- command(('unlet %s[\'%s\']'):format(dict_expr, key))
+ command(("unlet %s['%s']"):format(dict_expr, key))
else
- command(('let %s[\'%s\'] %s'):format(dict_expr, key, opval))
+ command(("let %s['%s'] %s"):format(dict_expr, key, opval))
end
end
@@ -40,9 +40,9 @@ describe('Vimscript dictionary notifications', function()
key = 'watched'
end
if opval == '' then
- exec_lua(('vim.api.nvim_del_var(\'%s\')'):format(key))
+ exec_lua(("vim.api.nvim_del_var('%s')"):format(key))
else
- exec_lua(('vim.api.nvim_set_var(\'%s\', %s)'):format(key, opval))
+ exec_lua(("vim.api.nvim_set_var('%s', %s)"):format(key, opval))
end
end
@@ -60,15 +60,15 @@ describe('Vimscript dictionary notifications', function()
local function verify_echo()
-- helper to verify that no notifications are sent after certain change
-- to a dict
- nvim('command', "call rpcnotify(g:channel, 'echo')")
- eq({'notification', 'echo', {}}, next_msg())
+ command("call rpcnotify(g:channel, 'echo')")
+ eq({ 'notification', 'echo', {} }, next_msg())
end
local function verify_value(vals, key)
if not key then
key = 'watched'
end
- eq({'notification', 'values', {key, vals}}, next_msg())
+ eq({ 'notification', 'values', { key, vals } }, next_msg())
end
describe(dict_expr .. ' watcher', function()
@@ -81,20 +81,20 @@ describe('Vimscript dictionary notifications', function()
before_each(function()
source([[
function! g:Changed(dict, key, value)
- if a:dict isnot ]]..dict_expr..[[ |
+ if a:dict isnot ]] .. dict_expr .. [[ |
throw 'invalid dict'
endif
call rpcnotify(g:channel, 'values', a:key, a:value)
endfunction
- call dictwatcheradd(]]..dict_expr..[[, "watched", "g:Changed")
- call dictwatcheradd(]]..dict_expr..[[, "watched2", "g:Changed")
+ call dictwatcheradd(]] .. dict_expr .. [[, "watched", "g:Changed")
+ call dictwatcheradd(]] .. dict_expr .. [[, "watched2", "g:Changed")
]])
end)
after_each(function()
source([[
- call dictwatcherdel(]]..dict_expr..[[, "watched", "g:Changed")
- call dictwatcherdel(]]..dict_expr..[[, "watched2", "g:Changed")
+ call dictwatcherdel(]] .. dict_expr .. [[, "watched", "g:Changed")
+ call dictwatcherdel(]] .. dict_expr .. [[, "watched2", "g:Changed")
]])
update('= "test"')
update('= "test2"', 'watched2')
@@ -134,99 +134,99 @@ describe('Vimscript dictionary notifications', function()
it('is triggered by remove()', function()
update('= "test"')
- verify_value({new = 'test'})
- nvim('command', 'call remove('..dict_expr..', "watched")')
- verify_value({old = 'test'})
+ verify_value({ new = 'test' })
+ command('call remove(' .. dict_expr .. ', "watched")')
+ verify_value({ old = 'test' })
end)
if is_g then
it('is triggered by remove() when updated with nvim_*_var', function()
update_with_api('"test"')
- verify_value({new = 'test'})
- nvim('command', 'call remove('..dict_expr..', "watched")')
- verify_value({old = 'test'})
+ verify_value({ new = 'test' })
+ command('call remove(' .. dict_expr .. ', "watched")')
+ verify_value({ old = 'test' })
end)
it('is triggered by remove() when updated with vim.g', function()
update_with_vim_g('= "test"')
- verify_value({new = 'test'})
- nvim('command', 'call remove('..dict_expr..', "watched")')
- verify_value({old = 'test'})
+ verify_value({ new = 'test' })
+ command('call remove(' .. dict_expr .. ', "watched")')
+ verify_value({ old = 'test' })
end)
end
it('is triggered by extend()', function()
update('= "xtend"')
- verify_value({new = 'xtend'})
- nvim('command', [[
- call extend(]]..dict_expr..[[, {'watched': 'xtend2', 'watched2': 5, 'watched3': 'a'})
+ verify_value({ new = 'xtend' })
+ command([[
+ call extend(]] .. dict_expr .. [[, {'watched': 'xtend2', 'watched2': 5, 'watched3': 'a'})
]])
- verify_value({old = 'xtend', new = 'xtend2'})
- verify_value({new = 5}, 'watched2')
+ verify_value({ old = 'xtend', new = 'xtend2' })
+ verify_value({ new = 5 }, 'watched2')
update('')
- verify_value({old = 'xtend2'})
+ verify_value({ old = 'xtend2' })
update('', 'watched2')
- verify_value({old = 5}, 'watched2')
+ verify_value({ old = 5 }, 'watched2')
update('', 'watched3')
verify_echo()
end)
it('is triggered with key patterns', function()
source([[
- call dictwatcheradd(]]..dict_expr..[[, "wat*", "g:Changed")
+ call dictwatcheradd(]] .. dict_expr .. [[, "wat*", "g:Changed")
]])
update('= 1')
- verify_value({new = 1})
- verify_value({new = 1})
+ verify_value({ new = 1 })
+ verify_value({ new = 1 })
update('= 3', 'watched2')
- verify_value({new = 3}, 'watched2')
- verify_value({new = 3}, 'watched2')
+ verify_value({ new = 3 }, 'watched2')
+ verify_value({ new = 3 }, 'watched2')
verify_echo()
source([[
- call dictwatcherdel(]]..dict_expr..[[, "wat*", "g:Changed")
+ call dictwatcherdel(]] .. dict_expr .. [[, "wat*", "g:Changed")
]])
-- watch every key pattern
source([[
- call dictwatcheradd(]]..dict_expr..[[, "*", "g:Changed")
+ call dictwatcheradd(]] .. dict_expr .. [[, "*", "g:Changed")
]])
update('= 3', 'another_key')
update('= 4', 'another_key')
update('', 'another_key')
update('= 2')
- verify_value({new = 3}, 'another_key')
- verify_value({old = 3, new = 4}, 'another_key')
- verify_value({old = 4}, 'another_key')
- verify_value({old = 1, new = 2})
- verify_value({old = 1, new = 2})
+ verify_value({ new = 3 }, 'another_key')
+ verify_value({ old = 3, new = 4 }, 'another_key')
+ verify_value({ old = 4 }, 'another_key')
+ verify_value({ old = 1, new = 2 })
+ verify_value({ old = 1, new = 2 })
verify_echo()
source([[
- call dictwatcherdel(]]..dict_expr..[[, "*", "g:Changed")
+ call dictwatcherdel(]] .. dict_expr .. [[, "*", "g:Changed")
]])
end)
it('is triggered for empty keys', function()
command([[
- call dictwatcheradd(]]..dict_expr..[[, "", "g:Changed")
+ call dictwatcheradd(]] .. dict_expr .. [[, "", "g:Changed")
]])
update('= 1', '')
- verify_value({new = 1}, '')
+ verify_value({ new = 1 }, '')
update('= 2', '')
- verify_value({old = 1, new = 2}, '')
+ verify_value({ old = 1, new = 2 }, '')
command([[
- call dictwatcherdel(]]..dict_expr..[[, "", "g:Changed")
+ call dictwatcherdel(]] .. dict_expr .. [[, "", "g:Changed")
]])
end)
it('is triggered for empty keys when using catch-all *', function()
command([[
- call dictwatcheradd(]]..dict_expr..[[, "*", "g:Changed")
+ call dictwatcheradd(]] .. dict_expr .. [[, "*", "g:Changed")
]])
update('= 1', '')
- verify_value({new = 1}, '')
+ verify_value({ new = 1 }, '')
update('= 2', '')
- verify_value({old = 1, new = 2}, '')
+ verify_value({ old = 1, new = 2 }, '')
command([[
- call dictwatcherdel(]]..dict_expr..[[, "*", "g:Changed")
+ call dictwatcherdel(]] .. dict_expr .. [[, "*", "g:Changed")
]])
end)
@@ -244,31 +244,31 @@ describe('Vimscript dictionary notifications', function()
end
test_updates({
- {'= 3', {new = 3}},
- {'= 6', {old = 3, new = 6}},
- {'+= 3', {old = 6, new = 9}},
- {'', {old = 9}}
+ { '= 3', { new = 3 } },
+ { '= 6', { old = 3, new = 6 } },
+ { '+= 3', { old = 6, new = 9 } },
+ { '', { old = 9 } },
})
test_updates({
- {'= "str"', {new = 'str'}},
- {'= "str2"', {old = 'str', new = 'str2'}},
- {'.= "2str"', {old = 'str2', new = 'str22str'}},
- {'', {old = 'str22str'}}
+ { '= "str"', { new = 'str' } },
+ { '= "str2"', { old = 'str', new = 'str2' } },
+ { '.= "2str"', { old = 'str2', new = 'str22str' } },
+ { '', { old = 'str22str' } },
})
test_updates({
- {'= [1, 2]', {new = {1, 2}}},
- {'= [1, 2, 3]', {old = {1, 2}, new = {1, 2, 3}}},
+ { '= [1, 2]', { new = { 1, 2 } } },
+ { '= [1, 2, 3]', { old = { 1, 2 }, new = { 1, 2, 3 } } },
-- the += will update the list in place, so old and new are the same
- {'+= [4, 5]', {old = {1, 2, 3, 4, 5}, new = {1, 2, 3, 4, 5}}},
- {'', {old = {1, 2, 3, 4 ,5}}}
+ { '+= [4, 5]', { old = { 1, 2, 3, 4, 5 }, new = { 1, 2, 3, 4, 5 } } },
+ { '', { old = { 1, 2, 3, 4, 5 } } },
})
test_updates({
- {'= {"k": "v"}', {new = {k = 'v'}}},
- {'= {"k1": 2}', {old = {k = 'v'}, new = {k1 = 2}}},
- {'', {old = {k1 = 2}}},
+ { '= {"k": "v"}', { new = { k = 'v' } } },
+ { '= {"k1": 2}', { old = { k = 'v' }, new = { k1 = 2 } } },
+ { '', { old = { k1 = 2 } } },
})
end)
end
@@ -294,18 +294,18 @@ describe('Vimscript dictionary notifications', function()
end)
it('invokes all callbacks when the key is changed', function()
- nvim('command', 'let g:key = "value"')
- eq({'notification', '1', {'key', {new = 'value'}}}, next_msg())
- eq({'notification', '2', {'key', {new = 'value'}}}, next_msg())
+ command('let g:key = "value"')
+ eq({ 'notification', '1', { 'key', { new = 'value' } } }, next_msg())
+ eq({ 'notification', '2', { 'key', { new = 'value' } } }, next_msg())
end)
it('only removes watchers that fully match dict, key and callback', function()
- nvim('command', 'let g:key = "value"')
- eq({'notification', '1', {'key', {new = 'value'}}}, next_msg())
- eq({'notification', '2', {'key', {new = 'value'}}}, next_msg())
- nvim('command', 'call dictwatcherdel(g:, "key", "g:Watcher1")')
- nvim('command', 'let g:key = "v2"')
- eq({'notification', '2', {'key', {old = 'value', new = 'v2'}}}, next_msg())
+ command('let g:key = "value"')
+ eq({ 'notification', '1', { 'key', { new = 'value' } } }, next_msg())
+ eq({ 'notification', '2', { 'key', { new = 'value' } } }, next_msg())
+ command('call dictwatcherdel(g:, "key", "g:Watcher1")')
+ command('let g:key = "v2"')
+ eq({ 'notification', '2', { 'key', { old = 'value', new = 'v2' } } }, next_msg())
end)
end)
@@ -315,8 +315,10 @@ describe('Vimscript dictionary notifications', function()
call rpcnotify(g:channel, '1', a:key, a:value)
endfunction
]])
- eq('Vim(call):E46: Cannot change read-only variable "dictwatcheradd() argument"',
- exc_exec('call dictwatcheradd(v:_null_dict, "x", "g:Watcher1")'))
+ eq(
+ 'Vim(call):E46: Cannot change read-only variable "dictwatcheradd() argument"',
+ exc_exec('call dictwatcheradd(v:_null_dict, "x", "g:Watcher1")')
+ )
end)
describe('errors', function()
@@ -333,13 +335,17 @@ describe('Vimscript dictionary notifications', function()
-- WARNING: This suite depends on the above tests
it('fails to remove if no watcher with matching callback is found', function()
- eq("Vim(call):Couldn't find a watcher matching key and callback",
- exc_exec('call dictwatcherdel(g:, "key", "g:Watcher1")'))
+ eq(
+ "Vim(call):Couldn't find a watcher matching key and callback",
+ exc_exec('call dictwatcherdel(g:, "key", "g:Watcher1")')
+ )
end)
it('fails to remove if no watcher with matching key is found', function()
- eq("Vim(call):Couldn't find a watcher matching key and callback",
- exc_exec('call dictwatcherdel(g:, "invalid_key", "g:Watcher2")'))
+ eq(
+ "Vim(call):Couldn't find a watcher matching key and callback",
+ exc_exec('call dictwatcherdel(g:, "invalid_key", "g:Watcher2")')
+ )
end)
it("does not fail to add/remove if the callback doesn't exist", function()
@@ -348,8 +354,10 @@ describe('Vimscript dictionary notifications', function()
end)
it('fails to remove watcher from v:_null_dict', function()
- eq("Vim(call):Couldn't find a watcher matching key and callback",
- exc_exec('call dictwatcherdel(v:_null_dict, "x", "g:Watcher2")'))
+ eq(
+ "Vim(call):Couldn't find a watcher matching key and callback",
+ exc_exec('call dictwatcherdel(v:_null_dict, "x", "g:Watcher2")')
+ )
end)
--[[
@@ -373,7 +381,7 @@ describe('Vimscript dictionary notifications', function()
]])
command('call g:ReplaceWatcher2()')
command('let g:key = "value"')
- eq({'notification', '2b', {'key', {old = 'v2', new = 'value'}}}, next_msg())
+ eq({ 'notification', '2b', { 'key', { old = 'v2', new = 'value' } } }, next_msg())
end)
it('does not crash when freeing a watched dictionary', function()
@@ -400,7 +408,7 @@ describe('Vimscript dictionary notifications', function()
call dictwatcheradd(d, 'foo', {dict, key, value -> rpcnotify(g:channel, '2', key, value)})
let d.foo = 'bar'
]])
- eq({'notification', '2', {'foo', {old = 'baz', new = 'bar'}}}, next_msg())
+ eq({ 'notification', '2', { 'foo', { old = 'baz', new = 'bar' } } }, next_msg())
end)
end)
@@ -412,12 +420,11 @@ describe('Vimscript dictionary notifications', function()
call dictwatcheradd(b:, 'changedtick', 'OnTickChanged')
]])
- insert('t');
- eq({'notification', 'SendChangeTick', {'changedtick', {old = 2, new = 3}}},
- next_msg())
+ insert('t')
+ eq({ 'notification', 'SendChangeTick', { 'changedtick', { old = 2, new = 3 } } }, next_msg())
command([[call dictwatcherdel(b:, 'changedtick', 'OnTickChanged')]])
- insert('t');
+ insert('t')
assert_alive()
end)
@@ -479,7 +486,7 @@ describe('Vimscript dictionary notifications', function()
let g:d.foo = 23
]])
eq(23, eval('g:d.foo'))
- eq({"W1"}, eval('g:calls'))
+ eq({ 'W1' }, eval('g:calls'))
end)
it('calls watcher deleted in callback', function()
@@ -507,7 +514,6 @@ describe('Vimscript dictionary notifications', function()
let g:d.foo = 123
]])
eq(123, eval('g:d.foo'))
- eq({"W1", "W2", "W2", "W1"}, eval('g:calls'))
+ eq({ 'W1', 'W2', 'W2', 'W1' }, eval('g:calls'))
end)
-
end)
diff --git a/test/functional/ex_cmds/digraphs_spec.lua b/test/functional/ex_cmds/digraphs_spec.lua
index 5de2adc191..24b6f7c53b 100644
--- a/test/functional/ex_cmds/digraphs_spec.lua
+++ b/test/functional/ex_cmds/digraphs_spec.lua
@@ -10,13 +10,13 @@ describe(':digraphs', function()
clear()
screen = Screen.new(65, 8)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [4] = {bold = true},
- [5] = {background = Screen.colors.LightGrey},
- [6] = {foreground = Screen.colors.Blue1},
- [7] = {bold = true, reverse = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [4] = { bold = true },
+ [5] = { background = Screen.colors.LightGrey },
+ [6] = { foreground = Screen.colors.Blue1 },
+ [7] = { bold = true, reverse = true },
})
screen:attach()
end)
diff --git a/test/functional/ex_cmds/drop_spec.lua b/test/functional/ex_cmds/drop_spec.lua
index 2537ab9cdc..cbda5aac98 100644
--- a/test/functional/ex_cmds/drop_spec.lua
+++ b/test/functional/ex_cmds/drop_spec.lua
@@ -3,7 +3,7 @@ local command = helpers.command
local Screen = require('test.functional.ui.screen')
local clear, feed, feed_command = helpers.clear, helpers.feed, helpers.feed_command
-describe(":drop", function()
+describe(':drop', function()
local screen
before_each(function()
@@ -11,68 +11,52 @@ describe(":drop", function()
screen = Screen.new(35, 10)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {bold = true, reverse = true},
- [2] = {reverse = true},
- [3] = {bold = true},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { bold = true, reverse = true },
+ [2] = { reverse = true },
+ [3] = { bold = true },
})
- command("set laststatus=2 shortmess-=F")
+ command('set laststatus=2 shortmess-=F')
end)
- it("works like :e when called with only one window open", function()
- feed_command("drop tmp1.vim")
+ it('works like :e when called with only one window open', function()
+ feed_command('drop tmp1.vim')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
{1:tmp1.vim }|
"tmp1.vim" [New] |
]])
end)
- it("switches to an open window showing the buffer", function()
- feed_command("edit tmp1")
- feed_command("vsplit")
- feed_command("edit tmp2")
- feed_command("drop tmp1")
+ it('switches to an open window showing the buffer', function()
+ feed_command('edit tmp1')
+ feed_command('vsplit')
+ feed_command('edit tmp2')
+ feed_command('drop tmp1')
screen:expect([[
│^ |
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
+ {0:~ }│{0:~ }|*7
{2:tmp2 }{1:tmp1 }|
- :drop tmp1 |
+ "tmp1" [New] |
]])
end)
it("splits off a new window when a buffer can't be abandoned", function()
- command("set nohidden")
- feed_command("edit tmp1")
- feed_command("vsplit")
- feed_command("edit tmp2")
- feed("iABC<esc>")
- feed_command("drop tmp3")
+ command('set nohidden')
+ feed_command('edit tmp1')
+ feed_command('vsplit')
+ feed_command('edit tmp2')
+ feed('iABC<esc>')
+ feed_command('drop tmp3')
screen:expect([[
^ │ |
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
+ {0:~ }│{0:~ }|*3
{1:tmp3 }│{0:~ }|
ABC │{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
+ {0:~ }│{0:~ }|*2
{2:tmp2 [+] tmp1 }|
"tmp3" [New] |
]])
end)
-
end)
diff --git a/test/functional/ex_cmds/echo_spec.lua b/test/functional/ex_cmds/echo_spec.lua
index a6be04138b..e9176a6204 100644
--- a/test/functional/ex_cmds/echo_spec.lua
+++ b/test/functional/ex_cmds/echo_spec.lua
@@ -1,11 +1,11 @@
local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
-local NIL = helpers.NIL
+local NIL = vim.NIL
local eval = helpers.eval
local clear = helpers.clear
-local meths = helpers.meths
-local funcs = helpers.funcs
+local api = helpers.api
+local fn = helpers.fn
local source = helpers.source
local dedent = helpers.dedent
local command = helpers.command
@@ -14,15 +14,15 @@ local exec_capture = helpers.exec_capture
local matches = helpers.matches
describe(':echo :echon :echomsg :echoerr', function()
- local fn_tbl = {'String', 'StringN', 'StringMsg', 'StringErr'}
+ local fn_tbl = { 'String', 'StringN', 'StringMsg', 'StringErr' }
local function assert_same_echo_dump(expected, input, use_eval)
- for _,v in pairs(fn_tbl) do
- eq(expected, use_eval and eval(v..'('..input..')') or funcs[v](input))
+ for _, v in pairs(fn_tbl) do
+ eq(expected, use_eval and eval(v .. '(' .. input .. ')') or fn[v](input))
end
end
local function assert_matches_echo_dump(expected, input, use_eval)
- for _,v in pairs(fn_tbl) do
- matches(expected, use_eval and eval(v..'('..input..')') or funcs[v](input))
+ for _, v in pairs(fn_tbl) do
+ matches(expected, use_eval and eval(v .. '(' .. input .. ')') or fn[v](input))
end
end
@@ -68,31 +68,29 @@ describe(':echo :echon :echomsg :echoerr', function()
eq('v:true', eval('String(v:true)'))
eq('v:false', eval('String(v:false)'))
eq('v:null', eval('String(v:null)'))
- eq('v:true', funcs.String(true))
- eq('v:false', funcs.String(false))
- eq('v:null', funcs.String(NIL))
+ eq('v:true', fn.String(true))
+ eq('v:false', fn.String(false))
+ eq('v:null', fn.String(NIL))
eq('v:true', eval('StringMsg(v:true)'))
eq('v:false', eval('StringMsg(v:false)'))
eq('v:null', eval('StringMsg(v:null)'))
- eq('v:true', funcs.StringMsg(true))
- eq('v:false', funcs.StringMsg(false))
- eq('v:null', funcs.StringMsg(NIL))
+ eq('v:true', fn.StringMsg(true))
+ eq('v:false', fn.StringMsg(false))
+ eq('v:null', fn.StringMsg(NIL))
eq('v:true', eval('StringErr(v:true)'))
eq('v:false', eval('StringErr(v:false)'))
eq('v:null', eval('StringErr(v:null)'))
- eq('v:true', funcs.StringErr(true))
- eq('v:false', funcs.StringErr(false))
- eq('v:null', funcs.StringErr(NIL))
+ eq('v:true', fn.StringErr(true))
+ eq('v:false', fn.StringErr(false))
+ eq('v:null', fn.StringErr(NIL))
end)
- it('dumps values with at most six digits after the decimal point',
- function()
+ it('dumps values with at most six digits after the decimal point', function()
assert_same_echo_dump('1.234568e-20', 1.23456789123456789123456789e-020)
assert_same_echo_dump('1.234568', 1.23456789123456789123456789)
end)
- it('dumps values with at most seven digits before the decimal point',
- function()
+ it('dumps values with at most seven digits before the decimal point', function()
assert_same_echo_dump('1234567.891235', 1234567.89123456789123456789)
assert_same_echo_dump('1.234568e7', 12345678.9123456789123456789)
end)
@@ -115,8 +113,8 @@ describe(':echo :echon :echomsg :echoerr', function()
end)
it('dumps large values', function()
- assert_same_echo_dump('2147483647', 2^31-1)
- assert_same_echo_dump('-2147483648', -2^31)
+ assert_same_echo_dump('2147483647', 2 ^ 31 - 1)
+ assert_same_echo_dump('-2147483648', -2 ^ 31)
end)
end)
@@ -198,75 +196,95 @@ describe(':echo :echon :echomsg :echoerr', function()
let TestDictRef = function('TestDict', d)
let d.tdr = TestDictRef
]])
- eq(dedent([[
+ eq(
+ dedent([[
function('TestDict', {'tdr': function('TestDict', {...@1})})]]),
- exec_capture('echo String(d.tdr)'))
+ exec_capture('echo String(d.tdr)')
+ )
end)
it('dumps automatically created partials', function()
assert_same_echo_dump(
"function('<SNR>1_Test2', {'f': function('<SNR>1_Test2')})",
'{"f": Test2_f}.f',
- true)
+ true
+ )
assert_same_echo_dump(
"function('<SNR>1_Test2', [1], {'f': function('<SNR>1_Test2', [1])})",
'{"f": function(Test2_f, [1])}.f',
- true)
+ true
+ )
end)
it('dumps manually created partials', function()
- assert_same_echo_dump("function('Test3', [1, 2], {})",
- "function('Test3', [1, 2], {})", true)
- assert_same_echo_dump("function('Test3', [1, 2])",
- "function('Test3', [1, 2])", true)
- assert_same_echo_dump("function('Test3', {})",
- "function('Test3', {})", true)
+ assert_same_echo_dump("function('Test3', [1, 2], {})", "function('Test3', [1, 2], {})", true)
+ assert_same_echo_dump("function('Test3', [1, 2])", "function('Test3', [1, 2])", true)
+ assert_same_echo_dump("function('Test3', {})", "function('Test3', {})", true)
end)
- it('does not crash or halt when dumping partials with reference cycles in self',
- function()
- meths.set_var('d', {v=true})
- eq(dedent([[
- {'p': function('<SNR>1_Test2', {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]]),
- exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))'))
+ it('does not crash or halt when dumping partials with reference cycles in self', function()
+ api.nvim_set_var('d', { v = true })
+ eq(
+ dedent(
+ [[
+ {'p': function('<SNR>1_Test2', {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]]
+ ),
+ exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))')
+ )
end)
- it('does not show errors when dumping partials referencing the same dictionary',
- function()
+ it('does not show errors when dumping partials referencing the same dictionary', function()
command('let d = {}')
-- Regression for “eval/typval_encode: Dump empty dictionary before
-- checking for refcycleâ€, results in error.
- eq('[function(\'tr\', {}), function(\'tr\', {})]', eval('String([function("tr", d), function("tr", d)])'))
+ eq(
+ "[function('tr', {}), function('tr', {})]",
+ eval('String([function("tr", d), function("tr", d)])')
+ )
-- Regression for “eval: Work with reference cycles in partials (self)
-- properlyâ€, results in crash.
eval('extend(d, {"a": 1})')
- eq('[function(\'tr\', {\'a\': 1}), function(\'tr\', {\'a\': 1})]', eval('String([function("tr", d), function("tr", d)])'))
+ eq(
+ "[function('tr', {'a': 1}), function('tr', {'a': 1})]",
+ eval('String([function("tr", d), function("tr", d)])')
+ )
end)
- it('does not crash or halt when dumping partials with reference cycles in arguments',
- function()
- meths.set_var('l', {})
+ it('does not crash or halt when dumping partials with reference cycles in arguments', function()
+ api.nvim_set_var('l', {})
eval('add(l, l)')
-- Regression: the below line used to crash (add returns original list and
-- there was error in dumping partials). Tested explicitly in
-- test/unit/api/private_helpers_spec.lua.
eval('add(l, function("Test1", l))')
- eq(dedent([=[
- function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])])]=]),
- exec_capture('echo String(function("Test1", l))'))
- end)
-
- it('does not crash or halt when dumping partials with reference cycles in self and arguments',
- function()
- meths.set_var('d', {v=true})
- meths.set_var('l', {})
- eval('add(l, l)')
- eval('add(l, function("Test1", l))')
- eval('add(l, function("Test1", d))')
- eq(dedent([=[
- {'p': function('<SNR>1_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]=]),
- exec_capture('echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))'))
- end)
+ eq(
+ dedent(
+ [=[
+ function('Test1', [[[...@2], function('Test1', [[...@2]])], function('Test1', [[[...@4], function('Test1', [[...@4]])]])])]=]
+ ),
+ exec_capture('echo String(function("Test1", l))')
+ )
+ end)
+
+ it(
+ 'does not crash or halt when dumping partials with reference cycles in self and arguments',
+ function()
+ api.nvim_set_var('d', { v = true })
+ api.nvim_set_var('l', {})
+ eval('add(l, l)')
+ eval('add(l, function("Test1", l))')
+ eval('add(l, function("Test1", d))')
+ eq(
+ dedent(
+ [=[
+ {'p': function('<SNR>1_Test2', [[[...@3], function('Test1', [[...@3]]), function('Test1', {...@0})], function('Test1', [[[...@5], function('Test1', [[...@5]]), function('Test1', {...@0})]]), function('Test1', {...@0})], {...@0}), 'f': function('<SNR>1_Test2'), 'v': v:true}]=]
+ ),
+ exec_capture(
+ 'echo String(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))'
+ )
+ )
+ end
+ )
end)
describe('used to represent lists', function()
@@ -275,25 +293,25 @@ describe(':echo :echon :echomsg :echoerr', function()
end)
it('dumps non-empty list', function()
- assert_same_echo_dump('[1, 2]', {1,2})
+ assert_same_echo_dump('[1, 2]', { 1, 2 })
end)
it('dumps nested lists', function()
- assert_same_echo_dump('[[[[[]]]]]', {{{{{}}}}})
+ assert_same_echo_dump('[[[[[]]]]]', { { { { {} } } } })
end)
it('dumps nested non-empty lists', function()
- assert_same_echo_dump('[1, [[3, [[5], 4]], 2]]', {1, {{3, {{5}, 4}}, 2}})
+ assert_same_echo_dump('[1, [[3, [[5], 4]], 2]]', { 1, { { 3, { { 5 }, 4 } }, 2 } })
end)
it('does not error when dumping recursive lists', function()
- meths.set_var('l', {})
+ api.nvim_set_var('l', {})
eval('add(l, l)')
eq(0, exc_exec('echo String(l)'))
end)
it('dumps recursive lists without error', function()
- meths.set_var('l', {})
+ api.nvim_set_var('l', {})
eval('add(l, l)')
eq('[[...@0]]', exec_capture('echo String(l)'))
eq('[[[...@1]]]', exec_capture('echo String([l])'))
@@ -308,27 +326,25 @@ describe(':echo :echon :echomsg :echoerr', function()
it('dumps list with two same empty dictionaries, also in partials', function()
command('let d = {}')
assert_same_echo_dump('[{}, {}]', '[d, d]', true)
- eq('[function(\'tr\', {}), {}]', eval('String([function("tr", d), d])'))
- eq('[{}, function(\'tr\', {})]', eval('String([d, function("tr", d)])'))
+ eq("[function('tr', {}), {}]", eval('String([function("tr", d), d])'))
+ eq("[{}, function('tr', {})]", eval('String([d, function("tr", d)])'))
end)
it('dumps non-empty dictionary', function()
- assert_same_echo_dump("{'t''est': 1}", {["t'est"]=1})
+ assert_same_echo_dump("{'t''est': 1}", { ["t'est"] = 1 })
end)
it('does not error when dumping recursive dictionaries', function()
- meths.set_var('d', {d=1})
+ api.nvim_set_var('d', { d = 1 })
eval('extend(d, {"d": d})')
eq(0, exc_exec('echo String(d)'))
end)
it('dumps recursive dictionaries without the error', function()
- meths.set_var('d', {d=1})
+ api.nvim_set_var('d', { d = 1 })
eval('extend(d, {"d": d})')
- eq('{\'d\': {...@0}}',
- exec_capture('echo String(d)'))
- eq('{\'out\': {\'d\': {...@1}}}',
- exec_capture('echo String({"out": d})'))
+ eq("{'d': {...@0}}", exec_capture('echo String(d)'))
+ eq("{'out': {'d': {...@1}}}", exec_capture('echo String({"out": d})'))
end)
end)
@@ -342,43 +358,43 @@ describe(':echo :echon :echomsg :echoerr', function()
it('displays hex as hex', function()
-- Regression: due to missing (uint8_t) cast \x80 was represented as
-- ~@<80>.
- eq('<80>', funcs.String(chr(0x80)))
- eq('<81>', funcs.String(chr(0x81)))
- eq('<8e>', funcs.String(chr(0x8e)))
- eq('<c2>', funcs.String(('«'):sub(1, 1)))
- eq('«', funcs.String(('«'):sub(1, 2)))
-
- eq('<80>', funcs.StringMsg(chr(0x80)))
- eq('<81>', funcs.StringMsg(chr(0x81)))
- eq('<8e>', funcs.StringMsg(chr(0x8e)))
- eq('<c2>', funcs.StringMsg(('«'):sub(1, 1)))
- eq('«', funcs.StringMsg(('«'):sub(1, 2)))
+ eq('<80>', fn.String(chr(0x80)))
+ eq('<81>', fn.String(chr(0x81)))
+ eq('<8e>', fn.String(chr(0x8e)))
+ eq('<c2>', fn.String(('«'):sub(1, 1)))
+ eq('«', fn.String(('«'):sub(1, 2)))
+
+ eq('<80>', fn.StringMsg(chr(0x80)))
+ eq('<81>', fn.StringMsg(chr(0x81)))
+ eq('<8e>', fn.StringMsg(chr(0x8e)))
+ eq('<c2>', fn.StringMsg(('«'):sub(1, 1)))
+ eq('«', fn.StringMsg(('«'):sub(1, 2)))
end)
it('displays ASCII control characters using ^X notation', function()
- eq('^C', funcs.String(ctrl('c')))
- eq('^A', funcs.String(ctrl('a')))
- eq('^F', funcs.String(ctrl('f')))
- eq('^C', funcs.StringMsg(ctrl('c')))
- eq('^A', funcs.StringMsg(ctrl('a')))
- eq('^F', funcs.StringMsg(ctrl('f')))
+ eq('^C', fn.String(ctrl('c')))
+ eq('^A', fn.String(ctrl('a')))
+ eq('^F', fn.String(ctrl('f')))
+ eq('^C', fn.StringMsg(ctrl('c')))
+ eq('^A', fn.StringMsg(ctrl('a')))
+ eq('^F', fn.StringMsg(ctrl('f')))
end)
it('prints CR, NL and tab as-is', function()
- eq('\n', funcs.String('\n'))
- eq('\r', funcs.String('\r'))
- eq('\t', funcs.String('\t'))
+ eq('\n', fn.String('\n'))
+ eq('\r', fn.String('\r'))
+ eq('\t', fn.String('\t'))
end)
it('prints non-printable UTF-8 in <> notation', function()
-- SINGLE SHIFT TWO, unicode control
- eq('<8e>', funcs.String(funcs.nr2char(0x8E)))
- eq('<8e>', funcs.StringMsg(funcs.nr2char(0x8E)))
+ eq('<8e>', fn.String(fn.nr2char(0x8E)))
+ eq('<8e>', fn.StringMsg(fn.nr2char(0x8E)))
-- Surrogate pair: U+1F0A0 PLAYING CARD BACK is represented in UTF-16 as
-- 0xD83C 0xDCA0. This is not valid in UTF-8.
- eq('<d83c>', funcs.String(funcs.nr2char(0xD83C)))
- eq('<dca0>', funcs.String(funcs.nr2char(0xDCA0)))
- eq('<d83c><dca0>', funcs.String(funcs.nr2char(0xD83C) .. funcs.nr2char(0xDCA0)))
- eq('<d83c>', funcs.StringMsg(funcs.nr2char(0xD83C)))
- eq('<dca0>', funcs.StringMsg(funcs.nr2char(0xDCA0)))
- eq('<d83c><dca0>', funcs.StringMsg(funcs.nr2char(0xD83C) .. funcs.nr2char(0xDCA0)))
+ eq('<d83c>', fn.String(fn.nr2char(0xD83C)))
+ eq('<dca0>', fn.String(fn.nr2char(0xDCA0)))
+ eq('<d83c><dca0>', fn.String(fn.nr2char(0xD83C) .. fn.nr2char(0xDCA0)))
+ eq('<d83c>', fn.StringMsg(fn.nr2char(0xD83C)))
+ eq('<dca0>', fn.StringMsg(fn.nr2char(0xDCA0)))
+ eq('<d83c><dca0>', fn.StringMsg(fn.nr2char(0xD83C) .. fn.nr2char(0xDCA0)))
end)
end)
end)
diff --git a/test/functional/ex_cmds/edit_spec.lua b/test/functional/ex_cmds/edit_spec.lua
index 6ed500a293..b927fa418a 100644
--- a/test/functional/ex_cmds/edit_spec.lua
+++ b/test/functional/ex_cmds/edit_spec.lua
@@ -1,27 +1,27 @@
-local helpers = require("test.functional.helpers")(after_each)
-local eq, command, funcs = helpers.eq, helpers.command, helpers.funcs
+local helpers = require('test.functional.helpers')(after_each)
+local eq, command, fn = helpers.eq, helpers.command, helpers.fn
local ok = helpers.ok
local clear = helpers.clear
local feed = helpers.feed
-describe(":edit", function()
+describe(':edit', function()
before_each(function()
clear()
end)
- it("without arguments does not restart :terminal buffer", function()
- command("terminal")
- feed([[<C-\><C-N>]])
- local bufname_before = funcs.bufname("%")
- local bufnr_before = funcs.bufnr("%")
- helpers.ok(nil ~= string.find(bufname_before, "^term://")) -- sanity
+ it('without arguments does not restart :terminal buffer', function()
+ command('terminal')
+ feed([[<C-\><C-N>]])
+ local bufname_before = fn.bufname('%')
+ local bufnr_before = fn.bufnr('%')
+ helpers.ok(nil ~= string.find(bufname_before, '^term://')) -- sanity
- command("edit")
+ command('edit')
- local bufname_after = funcs.bufname("%")
- local bufnr_after = funcs.bufnr("%")
- ok(funcs.line('$') > 1)
- eq(bufname_before, bufname_after)
- eq(bufnr_before, bufnr_after)
+ local bufname_after = fn.bufname('%')
+ local bufnr_after = fn.bufnr('%')
+ ok(fn.line('$') > 1)
+ eq(bufname_before, bufname_after)
+ eq(bufnr_before, bufnr_after)
end)
end)
diff --git a/test/functional/ex_cmds/encoding_spec.lua b/test/functional/ex_cmds/encoding_spec.lua
index 7f2bd78a47..8953fb8eaf 100644
--- a/test/functional/ex_cmds/encoding_spec.lua
+++ b/test/functional/ex_cmds/encoding_spec.lua
@@ -3,7 +3,6 @@ local clear, feed_command, feed = helpers.clear, helpers.feed_command, helpers.f
local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval
describe('&encoding', function()
-
before_each(function()
clear()
-- sanity check: tests should run with encoding=utf-8
@@ -32,9 +31,9 @@ describe('&encoding', function()
it('can be set to utf-8 without error', function()
feed_command('set encoding=utf-8')
- eq("", eval('v:errmsg'))
+ eq('', eval('v:errmsg'))
clear('--cmd', 'set enc=utf-8')
- eq("", eval('v:errmsg'))
+ eq('', eval('v:errmsg'))
end)
end)
diff --git a/test/functional/ex_cmds/excmd_spec.lua b/test/functional/ex_cmds/excmd_spec.lua
index a92329ede5..d16a52ee62 100644
--- a/test/functional/ex_cmds/excmd_spec.lua
+++ b/test/functional/ex_cmds/excmd_spec.lua
@@ -1,8 +1,8 @@
-local helpers = require("test.functional.helpers")(after_each)
+local helpers = require('test.functional.helpers')(after_each)
local command = helpers.command
local eq = helpers.eq
local clear = helpers.clear
-local funcs = helpers.funcs
+local fn = helpers.fn
local pcall_err = helpers.pcall_err
local assert_alive = helpers.assert_alive
@@ -20,15 +20,25 @@ describe('Ex cmds', function()
command(':later 9999999999999999999999999999999999999999')
command(':echo expand("#<9999999999999999999999999999999999999999")')
command(':lockvar 9999999999999999999999999999999999999999')
- command(':winsize 9999999999999999999999999999999999999999 9999999999999999999999999999999999999999')
- check_excmd_err(':tabnext 9999999999999999999999999999999999999999',
- 'Vim(tabnext):E475: Invalid argument: 9999999999999999999999999999999999999999')
- check_excmd_err(':N 9999999999999999999999999999999999999999',
- 'Vim(Next):E939: Positive count required')
- check_excmd_err(':bdelete 9999999999999999999999999999999999999999',
- 'Vim(bdelete):E939: Positive count required')
- eq('Vim(menu):E329: No menu "9999999999999999999999999999999999999999"',
- pcall_err(command, ':menu 9999999999999999999999999999999999999999'))
+ command(
+ ':winsize 9999999999999999999999999999999999999999 9999999999999999999999999999999999999999'
+ )
+ check_excmd_err(
+ ':tabnext 9999999999999999999999999999999999999999',
+ 'Vim(tabnext):E475: Invalid argument: 9999999999999999999999999999999999999999'
+ )
+ check_excmd_err(
+ ':N 9999999999999999999999999999999999999999',
+ 'Vim(Next):E939: Positive count required'
+ )
+ check_excmd_err(
+ ':bdelete 9999999999999999999999999999999999999999',
+ 'Vim(bdelete):E939: Positive count required'
+ )
+ eq(
+ 'Vim(menu):E329: No menu "9999999999999999999999999999999999999999"',
+ pcall_err(command, ':menu 9999999999999999999999999999999999999999')
+ )
assert_alive()
end)
@@ -39,15 +49,15 @@ describe('Ex cmds', function()
it(':def is an unknown command #23149', function()
eq('Vim:E492: Not an editor command: def', pcall_err(command, 'def'))
- eq(1, funcs.exists(':d'))
- eq('delete', funcs.fullcommand('d'))
- eq(1, funcs.exists(':de'))
- eq('delete', funcs.fullcommand('de'))
- eq(0, funcs.exists(':def'))
- eq('', funcs.fullcommand('def'))
- eq(1, funcs.exists(':defe'))
- eq('defer', funcs.fullcommand('defe'))
- eq(2, funcs.exists(':defer'))
- eq('defer', funcs.fullcommand('defer'))
+ eq(1, fn.exists(':d'))
+ eq('delete', fn.fullcommand('d'))
+ eq(1, fn.exists(':de'))
+ eq('delete', fn.fullcommand('de'))
+ eq(0, fn.exists(':def'))
+ eq('', fn.fullcommand('def'))
+ eq(1, fn.exists(':defe'))
+ eq('defer', fn.fullcommand('defe'))
+ eq(2, fn.exists(':defer'))
+ eq('defer', fn.fullcommand('defer'))
end)
end)
diff --git a/test/functional/ex_cmds/file_spec.lua b/test/functional/ex_cmds/file_spec.lua
index 131661828e..a48c408600 100644
--- a/test/functional/ex_cmds/file_spec.lua
+++ b/test/functional/ex_cmds/file_spec.lua
@@ -1,14 +1,13 @@
local helpers = require('test.functional.helpers')(after_each)
-local luv = require('luv')
local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
-local funcs = helpers.funcs
+local fn = helpers.fn
local rmdir = helpers.rmdir
local mkdir = helpers.mkdir
describe(':file', function()
- local swapdir = luv.cwd()..'/Xtest-file_spec'
+ local swapdir = vim.uv.cwd() .. '/Xtest-file_spec'
before_each(function()
clear()
rmdir(swapdir)
@@ -19,18 +18,17 @@ describe(':file', function()
rmdir(swapdir)
end)
- it("rename does not lose swapfile #6487", function()
+ it('rename does not lose swapfile #6487', function()
local testfile = 'test-file_spec'
- local testfile_renamed = testfile..'-renamed'
+ local testfile_renamed = testfile .. '-renamed'
-- Note: `set swapfile` *must* go after `set directory`: otherwise it may
-- attempt to create a swapfile in different directory.
- command('set directory^='..swapdir..'//')
+ command('set directory^=' .. swapdir .. '//')
command('set swapfile fileformat=unix undolevels=-1')
- command('edit! '..testfile)
+ command('edit! ' .. testfile)
-- Before #6487 this gave "E301: Oops, lost the swap file !!!" on Windows.
- command('file '..testfile_renamed)
- eq(testfile_renamed..'.swp',
- string.match(funcs.execute('swapname'), '[^%%]+$'))
+ command('file ' .. testfile_renamed)
+ eq(testfile_renamed .. '.swp', string.match(fn.execute('swapname'), '[^%%]+$'))
end)
end)
diff --git a/test/functional/ex_cmds/grep_spec.lua b/test/functional/ex_cmds/grep_spec.lua
index 43ef1bd424..bf81ba2137 100644
--- a/test/functional/ex_cmds/grep_spec.lua
+++ b/test/functional/ex_cmds/grep_spec.lua
@@ -15,7 +15,7 @@ describe(':grep', function()
-- Change to test directory so that the test does not run too long.
feed_command('cd test')
feed_command('grep a **/*')
- feed('<cr>') -- Press ENTER
- ok(eval('len(getqflist())') > 9000) -- IT'S OVER 9000!!1
+ feed('<cr>') -- Press ENTER
+ ok(eval('len(getqflist())') > 9000) -- IT'S OVER 9000!!1
end)
end)
diff --git a/test/functional/ex_cmds/help_spec.lua b/test/functional/ex_cmds/help_spec.lua
index aca0cbbaa6..cee33de1a6 100644
--- a/test/functional/ex_cmds/help_spec.lua
+++ b/test/functional/ex_cmds/help_spec.lua
@@ -3,8 +3,8 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local mkdir = helpers.mkdir
local rmdir = helpers.rmdir
local write_file = helpers.write_file
@@ -15,19 +15,19 @@ describe(':help', function()
it('window closed makes cursor return to a valid win/buf #9773', function()
helpers.add_builddir_to_rtp()
command('help help')
- eq(1001, funcs.win_getid())
+ eq(1001, fn.win_getid())
command('quit')
- eq(1000, funcs.win_getid())
+ eq(1000, fn.win_getid())
command('autocmd WinNew * wincmd p')
command('help help')
-- Window 1002 is opened, but the autocmd switches back to 1000 and
-- creates the help buffer there instead.
- eq(1000, funcs.win_getid())
+ eq(1000, fn.win_getid())
command('quit')
-- Before #9773, Nvim would crash on quitting the help window.
- eq(1002, funcs.win_getid())
+ eq(1002, fn.win_getid())
end)
it('multibyte help tags work #23975', function()
@@ -40,6 +40,6 @@ describe(':help', function()
command('helptags Xhelptags/doc')
command('set rtp+=Xhelptags')
command('help …')
- eq('*…*', meths.get_current_line())
+ eq('*…*', api.nvim_get_current_line())
end)
end)
diff --git a/test/functional/ex_cmds/highlight_spec.lua b/test/functional/ex_cmds/highlight_spec.lua
index 958dd99226..897a2997bc 100644
--- a/test/functional/ex_cmds/highlight_spec.lua
+++ b/test/functional/ex_cmds/highlight_spec.lua
@@ -1,11 +1,11 @@
local Screen = require('test.functional.ui.screen')
-local helpers = require("test.functional.helpers")(after_each)
+local helpers = require('test.functional.helpers')(after_each)
local eq, command = helpers.eq, helpers.command
local clear = helpers.clear
local eval, exc_exec = helpers.eval, helpers.exc_exec
local exec = helpers.exec
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
describe(':highlight', function()
local screen
@@ -17,15 +17,18 @@ describe(':highlight', function()
end)
it('invalid color name', function()
- eq('Vim(highlight):E421: Color name or number not recognized: ctermfg=#181818',
- exc_exec("highlight normal ctermfg=#181818"))
- eq('Vim(highlight):E421: Color name or number not recognized: ctermbg=#181818',
- exc_exec("highlight normal ctermbg=#181818"))
+ eq(
+ 'Vim(highlight):E421: Color name or number not recognized: ctermfg=#181818',
+ exc_exec('highlight normal ctermfg=#181818')
+ )
+ eq(
+ 'Vim(highlight):E421: Color name or number not recognized: ctermbg=#181818',
+ exc_exec('highlight normal ctermbg=#181818')
+ )
end)
it('invalid group name', function()
- eq('Vim(highlight):E411: Highlight group not found: foo',
- exc_exec("highlight foo"))
+ eq('Vim(highlight):E411: Highlight group not found: foo', exc_exec('highlight foo'))
end)
it('"Normal" foreground with red', function()
@@ -50,18 +53,18 @@ describe(':highlight', function()
end)
it('clear', function()
- meths.set_var('colors_name', 'foo')
- eq(1, funcs.exists('g:colors_name'))
+ api.nvim_set_var('colors_name', 'foo')
+ eq(1, fn.exists('g:colors_name'))
command('hi clear')
- eq(0, funcs.exists('g:colors_name'))
- meths.set_var('colors_name', 'foo')
- eq(1, funcs.exists('g:colors_name'))
+ eq(0, fn.exists('g:colors_name'))
+ api.nvim_set_var('colors_name', 'foo')
+ eq(1, fn.exists('g:colors_name'))
exec([[
func HiClear()
hi clear
endfunc
]])
- funcs.HiClear()
- eq(0, funcs.exists('g:colors_name'))
+ fn.HiClear()
+ eq(0, fn.exists('g:colors_name'))
end)
end)
diff --git a/test/functional/ex_cmds/ls_spec.lua b/test/functional/ex_cmds/ls_spec.lua
index d02af21731..5f59402d10 100644
--- a/test/functional/ex_cmds/ls_spec.lua
+++ b/test/functional/ex_cmds/ls_spec.lua
@@ -4,7 +4,7 @@ local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
local feed = helpers.feed
-local nvim = helpers.nvim
+local api = helpers.api
local testprg = helpers.testprg
local retry = helpers.retry
@@ -14,7 +14,7 @@ describe(':ls', function()
end)
it('R, F for :terminal buffers', function()
- nvim('set_option_value', 'shell', string.format('"%s" INTERACT', testprg('shell-test')), {})
+ api.nvim_set_option_value('shell', string.format('"%s" INTERACT', testprg('shell-test')), {})
command('edit foo')
command('set hidden')
@@ -44,6 +44,4 @@ describe(':ls', function()
eq('\n 3 %aF ', string.match(ls_output, '^\n *3 ... '))
end)
end)
-
end)
-
diff --git a/test/functional/ex_cmds/make_spec.lua b/test/functional/ex_cmds/make_spec.lua
index d82f59ddf9..dd47bdec58 100644
--- a/test/functional/ex_cmds/make_spec.lua
+++ b/test/functional/ex_cmds/make_spec.lua
@@ -3,40 +3,41 @@ local clear = helpers.clear
local eval = helpers.eval
local has_powershell = helpers.has_powershell
local matches = helpers.matches
-local nvim = helpers.nvim
+local api = helpers.api
local testprg = helpers.testprg
describe(':make', function()
clear()
- before_each(function ()
+ before_each(function()
clear()
end)
describe('with powershell', function()
if not has_powershell() then
- pending("not tested; powershell was not found", function() end)
+ pending('not tested; powershell was not found', function() end)
return
end
- before_each(function ()
+ before_each(function()
helpers.set_shell_powershell()
end)
- it('captures stderr & non zero exit code #14349', function ()
- nvim('set_option_value', 'makeprg', testprg('shell-test')..' foo', {})
+ it('captures stderr & non zero exit code #14349', function()
+ api.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)
+ 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_value', 'makeprg', testprg('shell-test'), {})
+ it('captures stderr & zero exit code #14349', function()
+ api.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)
matches('LastExitCode%s+ready [$]%s+[(]', out)
matches('\n.*%: ready [$]', out)
end)
-
end)
-
end)
diff --git a/test/functional/ex_cmds/map_spec.lua b/test/functional/ex_cmds/map_spec.lua
index a580e88b93..d3b027e6f4 100644
--- a/test/functional/ex_cmds/map_spec.lua
+++ b/test/functional/ex_cmds/map_spec.lua
@@ -1,11 +1,11 @@
-local helpers = require("test.functional.helpers")(after_each)
+local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local eq = helpers.eq
local exec = helpers.exec
local exec_capture = helpers.exec_capture
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
local clear = helpers.clear
local command = helpers.command
local expect = helpers.expect
@@ -16,13 +16,13 @@ describe(':*map', function()
before_each(clear)
it('are not affected by &isident', function()
- meths.set_var('counter', 0)
+ api.nvim_set_var('counter', 0)
command('nnoremap <C-x> :let counter+=1<CR>')
- meths.set_option_value('isident', ('%u'):format(('>'):byte()), {})
+ api.nvim_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>')
- eq(4, meths.get_var('counter'))
+ eq(4, api.nvim_get_var('counter'))
end)
it(':imap <M-">', function()
@@ -33,56 +33,60 @@ describe(':*map', function()
it('shows <Nop> as mapping rhs', function()
command('nmap asdf <Nop>')
- eq([[
+ eq(
+ [[
n asdf <Nop>]],
- exec_capture('nmap asdf'))
+ exec_capture('nmap asdf')
+ )
end)
it('mappings with description can be filtered', function()
- meths.set_keymap('n', 'asdf1', 'qwert', {desc='do the one thing'})
- meths.set_keymap('n', 'asdf2', 'qwert', {desc='doesnot really do anything'})
- meths.set_keymap('n', 'asdf3', 'qwert', {desc='do the other thing'})
- eq([[
+ api.nvim_set_keymap('n', 'asdf1', 'qwert', { desc = 'do the one thing' })
+ api.nvim_set_keymap('n', 'asdf2', 'qwert', { desc = 'doesnot really do anything' })
+ api.nvim_set_keymap('n', 'asdf3', 'qwert', { desc = 'do the other thing' })
+ eq(
+ [[
n asdf3 qwert
do the other thing
n asdf1 qwert
do the one thing]],
- exec_capture('filter the nmap'))
+ exec_capture('filter the nmap')
+ )
end)
it('<Plug> mappings ignore nore', function()
command('let x = 0')
- eq(0, meths.eval('x'))
+ eq(0, api.nvim_eval('x'))
command [[
nnoremap <Plug>(Increase_x) <cmd>let x+=1<cr>
nmap increase_x_remap <Plug>(Increase_x)
nnoremap increase_x_noremap <Plug>(Increase_x)
]]
feed('increase_x_remap')
- eq(1, meths.eval('x'))
+ eq(1, api.nvim_eval('x'))
feed('increase_x_noremap')
- eq(2, meths.eval('x'))
+ eq(2, api.nvim_eval('x'))
end)
it("Doesn't auto ignore nore for keys before or after <Plug> mapping", function()
command('let x = 0')
- eq(0, meths.eval('x'))
+ eq(0, api.nvim_eval('x'))
command [[
nnoremap x <nop>
nnoremap <Plug>(Increase_x) <cmd>let x+=1<cr>
nmap increase_x_remap x<Plug>(Increase_x)x
nnoremap increase_x_noremap x<Plug>(Increase_x)x
]]
- insert("Some text")
+ insert('Some text')
eq('Some text', eval("getline('.')"))
feed('increase_x_remap')
- eq(1, meths.eval('x'))
+ eq(1, api.nvim_eval('x'))
eq('Some text', eval("getline('.')"))
feed('increase_x_noremap')
- eq(2, meths.eval('x'))
+ eq(2, api.nvim_eval('x'))
eq('Some te', eval("getline('.')"))
end)
@@ -105,25 +109,19 @@ describe('Screen', function()
command('map <expr> x input("> ")')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
]])
feed('x')
screen:expect([[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
> ^ |
]])
feed('\n')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
> |
]])
end)
@@ -133,25 +131,19 @@ describe('Screen', function()
feed('i')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
-- INSERT -- |
]])
feed('x')
screen:expect([[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
> ^ |
]])
feed('\n')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
-- INSERT -- |
]])
end)
@@ -161,9 +153,7 @@ describe('Screen', function()
feed(':<F2>')
screen:expect([[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
:^ |
]])
end)
@@ -201,8 +191,7 @@ describe('Screen', function()
command('nmap <expr> <F2> execute("throw 42")')
feed('<F2>')
screen:expect([[
- |
- |
+ |*2
Error detected while processing : |
E605: Exception not caught: 42 |
Press ENTER or type command to continue^ |
@@ -210,9 +199,7 @@ describe('Screen', function()
feed('<CR>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
]])
end)
@@ -223,9 +210,7 @@ describe('Screen', function()
feed(':echo "foo')
screen:expect([[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
:echo "foo^ |
]])
feed('<F2>')
@@ -261,9 +246,7 @@ describe('Screen', function()
feed(': nmap a<CR>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
n a b |
]])
end)
diff --git a/test/functional/ex_cmds/menu_spec.lua b/test/functional/ex_cmds/menu_spec.lua
index b9ed32c328..bb6ef72787 100644
--- a/test/functional/ex_cmds/menu_spec.lua
+++ b/test/functional/ex_cmds/menu_spec.lua
@@ -1,12 +1,10 @@
local helpers = require('test.functional.helpers')(after_each)
-local clear, command, nvim = helpers.clear, helpers.command, helpers.nvim
+local clear, command = helpers.clear, helpers.command
local expect, feed = helpers.expect, helpers.feed
local eq, eval = helpers.eq, helpers.eval
-local funcs = helpers.funcs
-
+local fn = helpers.fn
describe(':emenu', function()
-
before_each(function()
clear()
command('nnoremenu Test.Test inormal<ESC>')
@@ -41,26 +39,25 @@ describe(':emenu', function()
end)
it('executes correct bindings in command mode', function()
- feed('ithis is a sentence<esc>^yiwo<esc>')
+ feed('ithis is a sentence<esc>^yiwo<esc>')
- -- Invoke "Edit.Paste" in normal-mode.
- nvim('command', 'emenu Edit.Paste')
+ -- Invoke "Edit.Paste" in normal-mode.
+ command('emenu Edit.Paste')
- -- Invoke "Edit.Paste" and "Test.Test" in command-mode.
- feed(':')
- nvim('command', 'emenu Edit.Paste')
- nvim('command', 'emenu Test.Test')
+ -- Invoke "Edit.Paste" and "Test.Test" in command-mode.
+ feed(':')
+ command('emenu Edit.Paste')
+ command('emenu Test.Test')
- expect([[
+ expect([[
this is a sentence
this]])
- -- Assert that Edit.Paste pasted @" into the commandline.
- eq('thiscmdmode', eval('getcmdline()'))
+ -- Assert that Edit.Paste pasted @" into the commandline.
+ eq('thiscmdmode', eval('getcmdline()'))
end)
end)
describe('menu_get', function()
-
before_each(function()
clear()
command([=[
@@ -83,12 +80,12 @@ describe('menu_get', function()
end)
it("path='', modes='a'", function()
- local m = funcs.menu_get("","a");
+ local m = fn.menu_get('', 'a')
-- HINT: To print the expected table and regenerate the tests:
-- print(require('vim.inspect')(m))
local expected = {
{
- shortcut = "T",
+ shortcut = 'T',
hidden = 0,
submenus = {
{
@@ -97,45 +94,45 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "insert",
- silent = 0
+ rhs = 'insert',
+ silent = 0,
},
s = {
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "x",
- silent = 0
+ rhs = 'x',
+ silent = 0,
},
n = {
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "inormal<Esc>",
- silent = 0
+ rhs = 'inormal<Esc>',
+ silent = 0,
},
v = {
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "x",
- silent = 0
+ rhs = 'x',
+ silent = 0,
},
c = {
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "cmdmode",
- silent = 0
- }
+ rhs = 'cmdmode',
+ silent = 0,
+ },
},
priority = 500,
- name = "Test",
- hidden = 0
+ name = 'Test',
+ hidden = 0,
},
{
priority = 500,
- name = "Nested",
+ name = 'Nested',
submenus = {
{
mappings = {
@@ -143,34 +140,34 @@ describe('menu_get', function()
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "level1",
- silent = 0
+ rhs = 'level1',
+ silent = 0,
},
v = {
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "level1",
- silent = 0
+ rhs = 'level1',
+ silent = 0,
},
s = {
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "level1",
- silent = 0
+ rhs = 'level1',
+ silent = 0,
},
n = {
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "level1",
- silent = 0
- }
+ rhs = 'level1',
+ silent = 0,
+ },
},
priority = 500,
- name = "test",
- hidden = 0
+ name = 'test',
+ hidden = 0,
},
{
mappings = {
@@ -178,67 +175,67 @@ describe('menu_get', function()
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "level2",
- silent = 0
+ rhs = 'level2',
+ silent = 0,
},
v = {
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "level2",
- silent = 0
+ rhs = 'level2',
+ silent = 0,
},
s = {
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "level2",
- silent = 0
+ rhs = 'level2',
+ silent = 0,
},
n = {
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "level2",
- silent = 0
- }
+ rhs = 'level2',
+ silent = 0,
+ },
},
priority = 500,
- name = "Nested2",
- hidden = 0
- }
+ name = 'Nested2',
+ hidden = 0,
+ },
},
- hidden = 0
- }
+ hidden = 0,
+ },
},
priority = 500,
- name = "Test"
+ name = 'Test',
},
{
priority = 500,
- name = "Export",
+ name = 'Export',
submenus = {
{
- tooltip = "This is the tooltip",
+ tooltip = 'This is the tooltip',
hidden = 0,
- name = "Script",
+ name = 'Script',
priority = 500,
mappings = {
n = {
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "p",
- silent = 0
- }
- }
- }
+ rhs = 'p',
+ silent = 0,
+ },
+ },
+ },
},
- hidden = 0
+ hidden = 0,
},
{
priority = 500,
- name = "Edit",
+ name = 'Edit',
submenus = {
{
mappings = {
@@ -246,27 +243,27 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "<C-R>\"",
- silent = 0
+ rhs = '<C-R>"',
+ silent = 0,
},
n = {
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "p",
- silent = 0
- }
+ rhs = 'p',
+ silent = 0,
+ },
},
priority = 500,
- name = "Paste",
- hidden = 0
- }
+ name = 'Paste',
+ hidden = 0,
+ },
},
- hidden = 0
+ hidden = 0,
},
{
priority = 500,
- name = "]Export",
+ name = ']Export',
submenus = {
{
mappings = {
@@ -274,72 +271,76 @@ describe('menu_get', function()
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "thisoneshouldbehidden",
- silent = 0
+ rhs = 'thisoneshouldbehidden',
+ silent = 0,
},
v = {
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "thisoneshouldbehidden",
- silent = 0
+ rhs = 'thisoneshouldbehidden',
+ silent = 0,
},
s = {
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "thisoneshouldbehidden",
- silent = 0
+ rhs = 'thisoneshouldbehidden',
+ silent = 0,
},
n = {
sid = 0,
noremap = 0,
enabled = 1,
- rhs = "thisoneshouldbehidden",
- silent = 0
- }
+ rhs = 'thisoneshouldbehidden',
+ silent = 0,
+ },
},
priority = 500,
- name = "hidden",
- hidden = 0
- }
+ name = 'hidden',
+ hidden = 0,
+ },
},
- hidden = 1
- }
+ hidden = 1,
+ },
}
eq(expected, m)
end)
it('matching path, all modes', function()
- local m = funcs.menu_get("Export", "a")
- local expected = { {
- hidden = 0,
- name = "Export",
- priority = 500,
- submenus = { {
- tooltip = "This is the tooltip",
+ local m = fn.menu_get('Export', 'a')
+ local expected = {
+ {
hidden = 0,
- name = "Script",
+ name = 'Export',
priority = 500,
- mappings = {
- n = {
- sid = 1,
- noremap = 1,
- enabled = 1,
- rhs = "p",
- silent = 0
- }
- }
- } }
- } }
+ submenus = {
+ {
+ tooltip = 'This is the tooltip',
+ hidden = 0,
+ name = 'Script',
+ priority = 500,
+ mappings = {
+ n = {
+ sid = 1,
+ noremap = 1,
+ enabled = 1,
+ rhs = 'p',
+ silent = 0,
+ },
+ },
+ },
+ },
+ },
+ }
eq(expected, m)
end)
it('no path, matching modes', function()
- local m = funcs.menu_get("","i")
+ local m = fn.menu_get('', 'i')
local expected = {
{
- shortcut = "T",
+ shortcut = 'T',
hidden = 0,
submenus = {
{
@@ -348,27 +349,27 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "insert",
- silent = 0
- }
+ rhs = 'insert',
+ silent = 0,
+ },
},
priority = 500,
- name = "Test",
- hidden = 0
+ name = 'Test',
+ hidden = 0,
},
},
priority = 500,
- name = "Test"
- }
+ name = 'Test',
+ },
}
eq(expected, m)
end)
it('matching path and modes', function()
- local m = funcs.menu_get("Test","i")
+ local m = fn.menu_get('Test', 'i')
local expected = {
{
- shortcut = "T",
+ shortcut = 'T',
submenus = {
{
mappings = {
@@ -376,26 +377,25 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "insert",
- silent = 0
+ rhs = 'insert',
+ silent = 0,
},
},
priority = 500,
- name = "Test",
- hidden = 0
+ name = 'Test',
+ hidden = 0,
},
},
priority = 500,
- name = "Test",
- hidden = 0
- }
+ name = 'Test',
+ hidden = 0,
+ },
}
eq(expected, m)
end)
end)
describe('menu_get', function()
-
before_each(function()
clear()
command('aunmenu *')
@@ -412,10 +412,10 @@ describe('menu_get', function()
command('nnoremenu &Test.Test8 <NoP>')
command('nnoremenu &Test.Test9 ""')
- local m = funcs.menu_get("");
+ local m = fn.menu_get('')
local expected = {
{
- shortcut = "T",
+ shortcut = 'T',
hidden = 0,
submenus = {
{
@@ -425,12 +425,12 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "inormal<Esc>",
- silent = 0
- }
+ rhs = 'inormal<Esc>',
+ silent = 0,
+ },
},
- name = "Test",
- hidden = 0
+ name = 'Test',
+ hidden = 0,
},
{
priority = 500,
@@ -439,12 +439,12 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "<Tab><Esc>",
- silent = 0
- }
+ rhs = '<Tab><Esc>',
+ silent = 0,
+ },
},
- name = "Test2",
- hidden = 0
+ name = 'Test2',
+ hidden = 0,
},
{
priority = 500,
@@ -453,19 +453,19 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "yA<C-R>0<Tab>xyz<Esc>",
- silent = 0
+ rhs = 'yA<C-R>0<Tab>xyz<Esc>',
+ silent = 0,
},
v = {
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "yA<C-R>0<Tab>xyz<Esc>",
- silent = 0
- }
+ rhs = 'yA<C-R>0<Tab>xyz<Esc>',
+ silent = 0,
+ },
},
- name = "Test3",
- hidden = 0
+ name = 'Test3',
+ hidden = 0,
},
{
priority = 500,
@@ -474,12 +474,12 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "<C-R>*",
- silent = 0
- }
+ rhs = '<C-R>*',
+ silent = 0,
+ },
},
- name = "Test4",
- hidden = 0
+ name = 'Test4',
+ hidden = 0,
},
{
priority = 500,
@@ -488,12 +488,12 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "<C-R>+",
- silent = 0
- }
+ rhs = '<C-R>+',
+ silent = 0,
+ },
},
- name = "Test5",
- hidden = 0
+ name = 'Test5',
+ hidden = 0,
},
{
priority = 500,
@@ -502,12 +502,12 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "",
- silent = 0
- }
+ rhs = '',
+ silent = 0,
+ },
},
- name = "Test6",
- hidden = 0
+ name = 'Test6',
+ hidden = 0,
},
{
priority = 500,
@@ -516,12 +516,12 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "",
- silent = 0
- }
+ rhs = '',
+ silent = 0,
+ },
},
- name = "Test7",
- hidden = 0
+ name = 'Test7',
+ hidden = 0,
},
{
priority = 500,
@@ -530,12 +530,12 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "",
- silent = 0
- }
+ rhs = '',
+ silent = 0,
+ },
},
- name = "Test8",
- hidden = 0
+ name = 'Test8',
+ hidden = 0,
},
{
priority = 500,
@@ -544,17 +544,17 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "\"\"",
- silent = 0
- }
+ rhs = '""',
+ silent = 0,
+ },
},
- name = "Test9",
- hidden = 0
- }
+ name = 'Test9',
+ hidden = 0,
+ },
},
priority = 500,
- name = "Test"
- }
+ name = 'Test',
+ },
}
eq(m, expected)
@@ -565,12 +565,12 @@ describe('menu_get', function()
command('nnoremenu &Test\\ 1.Test\\ 2 Wargl')
command('nnoremenu &Test4.Test<Tab>3 i space<Esc>')
- local m = funcs.menu_get("");
+ local m = fn.menu_get('')
local expected = {
{
- shortcut = "T",
+ shortcut = 'T',
hidden = 0,
- actext = "Y",
+ actext = 'Y',
submenus = {
{
mappings = {
@@ -578,21 +578,21 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "inormal<Alt-j>",
- silent = 0
- }
+ rhs = 'inormal<Alt-j>',
+ silent = 0,
+ },
},
hidden = 0,
- actext = "X x",
+ actext = 'X x',
priority = 500,
- name = "Test"
- }
+ name = 'Test',
+ },
},
priority = 500,
- name = "Test"
+ name = 'Test',
},
{
- shortcut = "T",
+ shortcut = 'T',
hidden = 0,
submenus = {
{
@@ -602,19 +602,19 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "Wargl",
- silent = 0
- }
+ rhs = 'Wargl',
+ silent = 0,
+ },
},
- name = "Test 2",
- hidden = 0
- }
+ name = 'Test 2',
+ hidden = 0,
+ },
},
priority = 500,
- name = "Test 1"
+ name = 'Test 1',
},
{
- shortcut = "T",
+ shortcut = 'T',
hidden = 0,
submenus = {
{
@@ -623,19 +623,19 @@ describe('menu_get', function()
sid = 1,
noremap = 1,
enabled = 1,
- rhs = "i space<Esc>",
- silent = 0
- }
+ rhs = 'i space<Esc>',
+ silent = 0,
+ },
},
hidden = 0,
- actext = "3",
+ actext = '3',
priority = 500,
- name = "Test"
- }
+ name = 'Test',
+ },
},
priority = 500,
- name = "Test4"
- }
+ name = 'Test4',
+ },
}
eq(m, expected)
diff --git a/test/functional/ex_cmds/mksession_spec.lua b/test/functional/ex_cmds/mksession_spec.lua
index 7522d4a99c..6f2e0be3d5 100644
--- a/test/functional/ex_cmds/mksession_spec.lua
+++ b/test/functional/ex_cmds/mksession_spec.lua
@@ -6,20 +6,18 @@ local command = helpers.command
local get_pathsep = helpers.get_pathsep
local eq = helpers.eq
local neq = helpers.neq
-local funcs = helpers.funcs
+local fn = helpers.fn
local matches = helpers.matches
-local pesc = helpers.pesc
+local pesc = vim.pesc
local rmdir = helpers.rmdir
-local sleep = helpers.sleep
-local meths = helpers.meths
+local sleep = vim.uv.sleep
+local api = helpers.api
local skip = helpers.skip
local is_os = helpers.is_os
local mkdir = helpers.mkdir
local file_prefix = 'Xtest-functional-ex_cmds-mksession_spec'
-if helpers.skip(helpers.is_os('win')) then return end
-
describe(':mksession', function()
local session_file = file_prefix .. '.vim'
local tab_dir = file_prefix .. '.d'
@@ -52,8 +50,8 @@ describe(':mksession', function()
-- Restore session.
command('source ' .. session_file)
- eq(funcs.winbufnr(1), funcs.winbufnr(2))
- neq(funcs.winbufnr(1), funcs.winbufnr(3))
+ eq(fn.winbufnr(1), fn.winbufnr(2))
+ neq(fn.winbufnr(1), fn.winbufnr(3))
end)
-- common testing procedure for testing "sessionoptions-=terminal"
@@ -68,64 +66,61 @@ describe(':mksession', function()
-- Restore session.
command('source ' .. session_file)
- eq(expected_buf_count, #meths.list_bufs())
+ eq(expected_buf_count, #api.nvim_list_bufs())
end
- it(
- 'do not restore :terminal if not set in sessionoptions, terminal in current window #13078',
- function()
- local tmpfile_base = file_prefix .. '-tmpfile'
- command('edit ' .. tmpfile_base)
- command('terminal')
+ it('do not restore :terminal if not set in sessionoptions, terminal in curwin #13078', function()
+ local tmpfile_base = file_prefix .. '-tmpfile'
+ command('edit ' .. tmpfile_base)
+ command('terminal')
- local buf_count = #meths.list_bufs()
- eq(2, buf_count)
+ local buf_count = #api.nvim_list_bufs()
+ eq(2, buf_count)
- eq('terminal', meths.get_option_value('buftype', {}))
+ eq('terminal', api.nvim_get_option_value('buftype', {}))
- test_terminal_session_disabled(2)
+ test_terminal_session_disabled(2)
- -- no terminal should be set. As a side effect we end up with a blank buffer
- eq('', meths.get_option_value('buftype', { buf = meths.list_bufs()[1] }))
- eq('', meths.get_option_value('buftype', { buf = meths.list_bufs()[2] }))
- end
- )
+ -- no terminal should be set. As a side effect we end up with a blank buffer
+ eq('', api.nvim_get_option_value('buftype', { buf = api.nvim_list_bufs()[1] }))
+ eq('', api.nvim_get_option_value('buftype', { buf = api.nvim_list_bufs()[2] }))
+ end)
it('do not restore :terminal if not set in sessionoptions, terminal hidden #13078', function()
command('terminal')
- local terminal_bufnr = meths.get_current_buf()
+ local terminal_bufnr = api.nvim_get_current_buf()
local tmpfile_base = file_prefix .. '-tmpfile'
-- make terminal hidden by opening a new file
command('edit ' .. tmpfile_base .. '1')
- local buf_count = #meths.list_bufs()
+ local buf_count = #api.nvim_list_bufs()
eq(2, buf_count)
- eq(1, funcs.getbufinfo(terminal_bufnr)[1].hidden)
+ eq(1, fn.getbufinfo(terminal_bufnr)[1].hidden)
test_terminal_session_disabled(1)
-- no terminal should exist here
- neq('', meths.buf_get_name(meths.list_bufs()[1]))
+ neq('', api.nvim_buf_get_name(api.nvim_list_bufs()[1]))
end)
it('do not restore :terminal if not set in sessionoptions, only buffer #13078', function()
command('terminal')
- eq('terminal', meths.get_option_value('buftype', {}))
+ eq('terminal', api.nvim_get_option_value('buftype', {}))
- local buf_count = #meths.list_bufs()
+ local buf_count = #api.nvim_list_bufs()
eq(1, buf_count)
test_terminal_session_disabled(1)
-- no terminal should be set
- eq('', meths.get_option_value('buftype', {}))
+ eq('', api.nvim_get_option_value('buftype', {}))
end)
it('restores tab-local working directories', function()
local tmpfile_base = file_prefix .. '-tmpfile'
- local cwd_dir = funcs.getcwd()
+ local cwd_dir = fn.getcwd()
-- :mksession does not save empty tabs, so create some buffers.
command('edit ' .. tmpfile_base .. '1')
@@ -141,15 +136,15 @@ describe(':mksession', function()
command('source ' .. session_file)
-- First tab should have the original working directory.
command('tabnext 1')
- eq(cwd_dir, funcs.getcwd())
+ eq(cwd_dir, fn.getcwd())
-- Second tab should have the tab-local working directory.
command('tabnext 2')
- eq(cwd_dir .. get_pathsep() .. tab_dir, funcs.getcwd())
+ eq(cwd_dir .. get_pathsep() .. tab_dir, fn.getcwd())
end)
it('restores buffers with tab-local CWD', function()
local tmpfile_base = file_prefix .. '-tmpfile'
- local cwd_dir = funcs.getcwd()
+ local cwd_dir = fn.getcwd()
local session_path = cwd_dir .. get_pathsep() .. session_file
command('edit ' .. tmpfile_base .. '1')
@@ -165,13 +160,15 @@ describe(':mksession', function()
-- Use :silent to avoid press-enter prompt due to long path
command('silent source ' .. session_path)
command('tabnext 1')
- eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '1', funcs.expand('%:p'))
+ eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '1', fn.expand('%:p'))
command('tabnext 2')
- eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '2', funcs.expand('%:p'))
+ eq(cwd_dir .. get_pathsep() .. tmpfile_base .. '2', fn.expand('%:p'))
end)
it('restores CWD for :terminal buffers #11288', function()
- local cwd_dir = funcs.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '')
+ skip(is_os('win'), 'causes rmdir() to fail')
+
+ local cwd_dir = fn.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '')
cwd_dir = cwd_dir:gsub([[\]], '/') -- :mksession always uses unix slashes.
local session_path = cwd_dir .. '/' .. session_file
@@ -189,7 +186,7 @@ describe(':mksession', function()
command('silent source ' .. session_path)
local expected_cwd = cwd_dir .. '/' .. tab_dir
- matches('^term://' .. pesc(expected_cwd) .. '//%d+:', funcs.expand('%'))
+ matches('^term://' .. pesc(expected_cwd) .. '//%d+:', fn.expand('%'))
command('%bwipeout!')
if is_os('win') then
sleep(100) -- Make sure all child processes have exited.
@@ -200,7 +197,7 @@ describe(':mksession', function()
skip(is_os('win'), 'N/A for Windows')
local screen
- local cwd_dir = funcs.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '')
+ local cwd_dir = fn.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '')
local session_path = cwd_dir .. '/' .. session_file
screen = Screen.new(50, 6)
@@ -209,9 +206,7 @@ describe(':mksession', function()
^/ |
|
[Process exited 0] |
- |
- |
- |
+ |*3
]]
command('cd /')
@@ -238,7 +233,7 @@ describe(':mksession', function()
local tmpfile = file_prefix .. '-tmpfile-float'
command('edit ' .. tmpfile)
- local buf = meths.create_buf(false, true)
+ local buf = api.nvim_create_buf(false, true)
local config = {
relative = 'editor',
focusable = false,
@@ -248,8 +243,8 @@ describe(':mksession', function()
col = 1,
style = 'minimal',
}
- meths.open_win(buf, false, config)
- local cmdheight = meths.get_option_value('cmdheight', {})
+ api.nvim_open_win(buf, false, config)
+ local cmdheight = api.nvim_get_option_value('cmdheight', {})
command('mksession ' .. session_file)
-- Create a new test instance of Nvim.
@@ -257,12 +252,12 @@ describe(':mksession', function()
command('source ' .. session_file)
- eq(tmpfile, funcs.expand('%'))
+ eq(tmpfile, fn.expand('%'))
-- Check that there is only a single window, which indicates the floating
-- window was not restored.
- eq(1, funcs.winnr('$'))
+ eq(1, fn.winnr('$'))
-- The command-line height should remain the same as it was.
- eq(cmdheight, meths.get_option_value('cmdheight', {}))
+ eq(cmdheight, api.nvim_get_option_value('cmdheight', {}))
os.remove(tmpfile)
end)
diff --git a/test/functional/ex_cmds/mkview_spec.lua b/test/functional/ex_cmds/mkview_spec.lua
index f71b826210..de0a4fe0ea 100644
--- a/test/functional/ex_cmds/mkview_spec.lua
+++ b/test/functional/ex_cmds/mkview_spec.lua
@@ -4,7 +4,7 @@ local clear = helpers.clear
local command = helpers.command
local get_pathsep = helpers.get_pathsep
local eq = helpers.eq
-local funcs = helpers.funcs
+local fn = helpers.fn
local rmdir = helpers.rmdir
local mkdir = helpers.mkdir
@@ -28,9 +28,8 @@ describe(':mkview', function()
end)
it('viewoption curdir restores local current directory', function()
- local cwd_dir = funcs.getcwd()
- local set_view_dir_command = 'set viewdir=' .. cwd_dir ..
- get_pathsep() .. view_dir
+ local cwd_dir = fn.getcwd()
+ local set_view_dir_command = 'set viewdir=' .. cwd_dir .. get_pathsep() .. view_dir
-- By default the local current directory should save
command(set_view_dir_command)
@@ -56,12 +55,11 @@ describe(':mkview', function()
command('edit ' .. tmp_file_base .. '2')
command('loadview')
-- The view's current directory should not have changed
- eq(cwd_dir, funcs.getcwd())
+ eq(cwd_dir, fn.getcwd())
-- Load the view with a saved local current directory
command('edit ' .. tmp_file_base .. '1')
command('loadview')
-- The view's local directory should have been saved
- eq(cwd_dir .. get_pathsep() .. local_dir, funcs.getcwd())
+ eq(cwd_dir .. get_pathsep() .. local_dir, fn.getcwd())
end)
-
end)
diff --git a/test/functional/ex_cmds/normal_spec.lua b/test/functional/ex_cmds/normal_spec.lua
index 009f1d6516..723bfefcf4 100644
--- a/test/functional/ex_cmds/normal_spec.lua
+++ b/test/functional/ex_cmds/normal_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local command = helpers.command
-local funcs = helpers.funcs
+local fn = helpers.fn
local feed = helpers.feed
local expect = helpers.expect
local eq = helpers.eq
@@ -29,10 +29,10 @@ describe(':normal!', function()
it('can stop Visual mode without closing cmdwin vim-patch:9.0.0234', function()
feed('q:')
feed('v')
- eq('v', funcs.mode(1))
- eq(':', funcs.getcmdwintype())
+ eq('v', fn.mode(1))
+ eq(':', fn.getcmdwintype())
command('normal! \027')
- eq('n', funcs.mode(1))
- eq(':', funcs.getcmdwintype())
+ eq('n', fn.mode(1))
+ eq(':', fn.getcmdwintype())
end)
end)
diff --git a/test/functional/ex_cmds/oldfiles_spec.lua b/test/functional/ex_cmds/oldfiles_spec.lua
index 19611429e0..8d1469f343 100644
--- a/test/functional/ex_cmds/oldfiles_spec.lua
+++ b/test/functional/ex_cmds/oldfiles_spec.lua
@@ -4,7 +4,7 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local command = helpers.command
local expect_exit = helpers.expect_exit
-local buf, eq, feed_command = helpers.curbufmeths, helpers.eq, helpers.feed_command
+local api, eq, feed_command = helpers.api, helpers.eq, helpers.feed_command
local feed, poke_eventloop = helpers.feed, helpers.poke_eventloop
local ok = helpers.ok
local eval = helpers.eval
@@ -12,9 +12,15 @@ local eval = helpers.eval
local shada_file = 'Xtest.shada'
local function _clear()
- clear{args={'-i', shada_file, -- Need shada for these tests.
- '--cmd', 'set noswapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler'},
- args_rm={'-i', '--cmd'}}
+ clear {
+ args = {
+ '-i',
+ shada_file, -- Need shada for these tests.
+ '--cmd',
+ 'set noswapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler',
+ },
+ args_rm = { '-i', '--cmd' },
+ }
end
describe(':oldfiles', function()
@@ -36,12 +42,12 @@ describe(':oldfiles', function()
feed_command('edit testfile2')
feed_command('wshada')
feed_command('rshada!')
- local oldfiles = helpers.meths.get_vvar('oldfiles')
+ local oldfiles = api.nvim_get_vvar('oldfiles')
feed_command('oldfiles')
screen:expect([[
|
- 1: ]].. add_padding(oldfiles[1]) ..[[ |
- 2: ]].. add_padding(oldfiles[2]) ..[[ |
+ 1: ]] .. add_padding(oldfiles[1]) .. [[ |
+ 2: ]] .. add_padding(oldfiles[2]) .. [[ |
|
Press ENTER or type command to continue^ |
]])
@@ -50,16 +56,16 @@ describe(':oldfiles', function()
it('can be filtered with :filter', function()
feed_command('edit file_one.txt')
- local file1 = buf.get_name()
+ local file1 = api.nvim_buf_get_name(0)
feed_command('edit file_two.txt')
- local file2 = buf.get_name()
+ local file2 = api.nvim_buf_get_name(0)
feed_command('edit another.txt')
- local another = buf.get_name()
+ local another = api.nvim_buf_get_name(0)
feed_command('wshada')
feed_command('rshada!')
local function get_oldfiles(cmd)
- local t = eval([[split(execute(']]..cmd..[['), "\n")]])
+ local t = eval([[split(execute(']] .. cmd .. [['), "\n")]])
for i, _ in ipairs(t) do
t[i] = t[i]:gsub('^%d+:%s+', '')
end
@@ -68,16 +74,16 @@ describe(':oldfiles', function()
end
local oldfiles = get_oldfiles('oldfiles')
- eq({another, file1, file2}, oldfiles)
+ eq({ another, file1, file2 }, oldfiles)
oldfiles = get_oldfiles('filter file_ oldfiles')
- eq({file1, file2}, oldfiles)
+ eq({ file1, file2 }, oldfiles)
oldfiles = get_oldfiles('filter /another/ oldfiles')
- eq({another}, oldfiles)
+ eq({ another }, oldfiles)
oldfiles = get_oldfiles('filter! file_ oldfiles')
- eq({another}, oldfiles)
+ eq({ another }, oldfiles)
end)
end)
@@ -89,9 +95,9 @@ describe(':browse oldfiles', function()
before_each(function()
_clear()
feed_command('edit testfile1')
- filename = buf.get_name()
+ filename = api.nvim_buf_get_name(0)
feed_command('edit testfile2')
- filename2 = buf.get_name()
+ filename2 = api.nvim_buf_get_name(0)
feed_command('wshada')
poke_eventloop()
_clear()
@@ -102,7 +108,7 @@ describe(':browse oldfiles', function()
-- Ensure v:oldfiles isn't busted. Since things happen so fast,
-- the ordering of v:oldfiles is unstable (it uses qsort() under-the-hood).
-- Let's verify the contents and the length of v:oldfiles before moving on.
- oldfiles = helpers.meths.get_vvar('oldfiles')
+ oldfiles = helpers.api.nvim_get_vvar('oldfiles')
eq(2, #oldfiles)
ok(filename == oldfiles[1] or filename == oldfiles[2])
ok(filename2 == oldfiles[1] or filename2 == oldfiles[2])
@@ -117,16 +123,16 @@ describe(':browse oldfiles', function()
it('provides a prompt and edits the chosen file', function()
feed('2<cr>')
- eq(oldfiles[2], buf.get_name())
+ eq(oldfiles[2], api.nvim_buf_get_name(0))
end)
it('provides a prompt and does nothing on <cr>', function()
feed('<cr>')
- eq('', buf.get_name())
+ eq('', api.nvim_buf_get_name(0))
end)
it('provides a prompt and does nothing if choice is out-of-bounds', function()
feed('3<cr>')
- eq('', buf.get_name())
+ eq('', api.nvim_buf_get_name(0))
end)
end)
diff --git a/test/functional/ex_cmds/print_commands_spec.lua b/test/functional/ex_cmds/print_commands_spec.lua
index 98c0f74635..ba5ec7d2d1 100644
--- a/test/functional/ex_cmds/print_commands_spec.lua
+++ b/test/functional/ex_cmds/print_commands_spec.lua
@@ -1,12 +1,11 @@
local helpers = require('test.functional.helpers')(after_each)
-local clear, eq, command, funcs =
- helpers.clear, helpers.eq, helpers.command, helpers.funcs
+local clear, eq, command, fn = helpers.clear, helpers.eq, helpers.command, helpers.fn
describe(':z^', function()
before_each(clear)
it('correctly sets the cursor after :z^', function()
command('z^')
- eq(1, funcs.line('.'))
+ eq(1, fn.line('.'))
end)
end)
diff --git a/test/functional/ex_cmds/profile_spec.lua b/test/functional/ex_cmds/profile_spec.lua
index 249373a9c4..f85dcc60ff 100644
--- a/test/functional/ex_cmds/profile_spec.lua
+++ b/test/functional/ex_cmds/profile_spec.lua
@@ -1,27 +1,27 @@
require('os')
-local luv = require('luv')
+local uv = vim.uv
-local helpers = require('test.functional.helpers')(after_each)
-local eval = helpers.eval
-local command = helpers.command
-local eq, neq = helpers.eq, helpers.neq
+local helpers = require('test.functional.helpers')(after_each)
+local eval = helpers.eval
+local command = helpers.command
+local eq, neq = helpers.eq, helpers.neq
local tempfile = helpers.tmpname()
-local source = helpers.source
-local matches = helpers.matches
+local source = helpers.source
+local matches = helpers.matches
local read_file = helpers.read_file
-- tmpname() also creates the file on POSIX systems. Remove it again.
-- We just need the name, ignoring any race conditions.
-if luv.fs_stat(tempfile).uid then
+if uv.fs_stat(tempfile).uid then
os.remove(tempfile)
end
local function assert_file_exists(filepath)
- neq(nil, luv.fs_stat(filepath).uid)
+ neq(nil, uv.fs_stat(filepath).uid)
end
local function assert_file_exists_not(filepath)
- eq(nil, luv.fs_stat(filepath))
+ eq(nil, uv.fs_stat(filepath))
end
describe(':profile', function()
@@ -29,7 +29,7 @@ describe(':profile', function()
after_each(function()
helpers.expect_exit(command, 'qall!')
- if luv.fs_stat(tempfile).uid ~= nil then
+ if uv.fs_stat(tempfile).uid ~= nil then
os.remove(tempfile)
end
end)
diff --git a/test/functional/ex_cmds/quickfix_commands_spec.lua b/test/functional/ex_cmds/quickfix_commands_spec.lua
index 4d9d8eeb90..5af0198ffe 100644
--- a/test/functional/ex_cmds/quickfix_commands_spec.lua
+++ b/test/functional/ex_cmds/quickfix_commands_spec.lua
@@ -4,31 +4,35 @@ local Screen = require('test.functional.ui.screen')
local feed = helpers.feed
local eq = helpers.eq
local clear = helpers.clear
-local funcs = helpers.funcs
+local fn = helpers.fn
local command = helpers.command
local exc_exec = helpers.exc_exec
local write_file = helpers.write_file
-local curbufmeths = helpers.curbufmeths
+local api = helpers.api
local source = helpers.source
local file_base = 'Xtest-functional-ex_cmds-quickfix_commands'
before_each(clear)
-for _, c in ipairs({'l', 'c'}) do
+for _, c in ipairs({ 'l', 'c' }) do
local file = ('%s.%s'):format(file_base, c)
local filecmd = c .. 'file'
local getfcmd = c .. 'getfile'
local addfcmd = c .. 'addfile'
- local getlist = (c == 'c') and funcs.getqflist or (
- function() return funcs.getloclist(0) end)
+ local getlist = (c == 'c') and fn.getqflist or function()
+ return fn.getloclist(0)
+ end
describe((':%s*file commands'):format(c), function()
before_each(function()
- write_file(file, ([[
+ write_file(
+ file,
+ ([[
%s-1.res:700:10:Line 700
%s-2.res:800:15:Line 800
- ]]):format(file, file))
+ ]]):format(file, file)
+ )
end)
after_each(function()
os.remove(file)
@@ -39,49 +43,114 @@ for _, c in ipairs({'l', 'c'}) do
-- Second line of each entry (i.e. `nr=-1, …`) was obtained from actual
-- results. First line (i.e. `{lnum=…`) was obtained from legacy test.
local list = {
- {lnum=700, end_lnum=0, col=10, end_col=0, text='Line 700', module='',
- nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''},
- {lnum=800, end_lnum=0, col=15, end_col=0, text='Line 800', module='',
- nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''},
+ {
+ lnum = 700,
+ end_lnum = 0,
+ col = 10,
+ end_col = 0,
+ text = 'Line 700',
+ module = '',
+ nr = -1,
+ bufnr = 2,
+ valid = 1,
+ pattern = '',
+ vcol = 0,
+ ['type'] = '',
+ },
+ {
+ lnum = 800,
+ end_lnum = 0,
+ col = 15,
+ end_col = 0,
+ text = 'Line 800',
+ module = '',
+ nr = -1,
+ bufnr = 3,
+ valid = 1,
+ pattern = '',
+ vcol = 0,
+ ['type'] = '',
+ },
}
eq(list, getlist())
- eq(('%s-1.res'):format(file), funcs.bufname(list[1].bufnr))
- eq(('%s-2.res'):format(file), funcs.bufname(list[2].bufnr))
+ eq(('%s-1.res'):format(file), fn.bufname(list[1].bufnr))
+ eq(('%s-2.res'):format(file), fn.bufname(list[2].bufnr))
-- Run cfile/lfile from a modified buffer
command('set nohidden')
command('enew!')
- curbufmeths.set_lines(1, 1, true, {'Quickfix'})
- eq(('Vim(%s):E37: No write since last change (add ! to override)'):format(
- filecmd),
- exc_exec(('%s %s'):format(filecmd, file)))
+ api.nvim_buf_set_lines(0, 1, 1, true, { 'Quickfix' })
+ eq(
+ ('Vim(%s):E37: No write since last change (add ! to override)'):format(filecmd),
+ exc_exec(('%s %s'):format(filecmd, file))
+ )
- write_file(file, ([[
+ write_file(
+ file,
+ ([[
%s-3.res:900:30:Line 900
- ]]):format(file))
+ ]]):format(file)
+ )
command(('%s %s'):format(addfcmd, file))
list[#list + 1] = {
- lnum=900, end_lnum=0, col=30, end_col=0, text='Line 900', module='',
- nr=-1, bufnr=5, valid=1, pattern='', vcol=0, ['type']='',
+ lnum = 900,
+ end_lnum = 0,
+ col = 30,
+ end_col = 0,
+ text = 'Line 900',
+ module = '',
+ nr = -1,
+ bufnr = 5,
+ valid = 1,
+ pattern = '',
+ vcol = 0,
+ ['type'] = '',
}
eq(list, getlist())
- eq(('%s-3.res'):format(file), funcs.bufname(list[3].bufnr))
+ eq(('%s-3.res'):format(file), fn.bufname(list[3].bufnr))
- write_file(file, ([[
+ write_file(
+ file,
+ ([[
%s-1.res:222:77:Line 222
%s-2.res:333:88:Line 333
- ]]):format(file, file))
+ ]]):format(file, file)
+ )
command('enew!')
command(('%s %s'):format(getfcmd, file))
list = {
- {lnum=222, end_lnum=0, col=77, end_col=0, text='Line 222', module='',
- nr=-1, bufnr=2, valid=1, pattern='', vcol=0, ['type']=''},
- {lnum=333, end_lnum=0, col=88, end_col=0, text='Line 333', module='',
- nr=-1, bufnr=3, valid=1, pattern='', vcol=0, ['type']=''},
+ {
+ lnum = 222,
+ end_lnum = 0,
+ col = 77,
+ end_col = 0,
+ text = 'Line 222',
+ module = '',
+ nr = -1,
+ bufnr = 2,
+ valid = 1,
+ pattern = '',
+ vcol = 0,
+ ['type'] = '',
+ },
+ {
+ lnum = 333,
+ end_lnum = 0,
+ col = 88,
+ end_col = 0,
+ text = 'Line 333',
+ module = '',
+ nr = -1,
+ bufnr = 3,
+ valid = 1,
+ pattern = '',
+ vcol = 0,
+ ['type'] = '',
+ },
}
eq(list, getlist())
- eq(('%s-1.res'):format(file), funcs.bufname(list[1].bufnr))
- eq(('%s-2.res'):format(file), funcs.bufname(list[2].bufnr))
+ eq(('%s-1.res'):format(file), fn.bufname(list[1].bufnr))
+ eq(('%s-2.res'):format(file), fn.bufname(list[2].bufnr))
end)
end)
end
@@ -109,7 +178,7 @@ describe('quickfix', function()
call append(0, ['New line 1', 'New line 2', 'New line 3'])
silent ll
]])
- eq({0, 6, 1, 0, 1}, funcs.getcurpos())
+ eq({ 0, 6, 1, 0, 1 }, fn.getcurpos())
end)
it('BufAdd does not cause E16 when reusing quickfix buffer #18135', function()
@@ -127,20 +196,20 @@ describe('quickfix', function()
end)
it(':vimgrep can specify Unicode pattern without delimiters', function()
- eq('Vim(vimgrep):E480: No match: →', exc_exec('vimgrep → test/functional/fixtures/tty-test.c'))
+ eq(
+ 'Vim(vimgrep):E480: No match: →',
+ exc_exec('vimgrep → test/functional/fixtures/tty-test.c')
+ )
local screen = Screen.new(40, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {reverse = true}, -- IncSearch
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { reverse = true }, -- IncSearch
})
screen:attach()
feed('i→<Esc>:vimgrep →')
screen:expect([[
{1:→} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
:vimgrep →^ |
]])
end)
diff --git a/test/functional/ex_cmds/quit_spec.lua b/test/functional/ex_cmds/quit_spec.lua
index 3680801dae..5a1759dab3 100644
--- a/test/functional/ex_cmds/quit_spec.lua
+++ b/test/functional/ex_cmds/quit_spec.lua
@@ -11,4 +11,3 @@ describe(':qa', function()
-- errors
end)
end)
-
diff --git a/test/functional/ex_cmds/script_spec.lua b/test/functional/ex_cmds/script_spec.lua
index 62249caa5e..4c963c5da7 100644
--- a/test/functional/ex_cmds/script_spec.lua
+++ b/test/functional/ex_cmds/script_spec.lua
@@ -5,7 +5,7 @@ local neq = helpers.neq
local command = helpers.command
local exec_capture = helpers.exec_capture
local write_file = helpers.write_file
-local meths = helpers.meths
+local api = helpers.api
local clear = helpers.clear
local dedent = helpers.dedent
local exc_exec = helpers.exc_exec
@@ -17,7 +17,7 @@ before_each(clear)
local function source(code)
write_file(tmpfile, code)
- command('source '..tmpfile)
+ command('source ' .. tmpfile)
end
describe('script_get-based command', function()
@@ -30,29 +30,48 @@ describe('script_get-based command', function()
local function test_garbage_exec(cmd, check_neq)
describe(cmd, function()
it('works correctly when skipping oneline variant', function()
- eq(true, pcall(source, (dedent([[
+ eq(
+ true,
+ pcall(
+ source,
+ (dedent([[
if 0
%s %s
endif
- ]])):format(cmd, garbage)))
+ ]])):format(cmd, garbage)
+ )
+ )
eq('', exec_capture('messages'))
if check_neq then
- neq(0, exc_exec(dedent([[
+ neq(
+ 0,
+ exc_exec(dedent([[
%s %s
- ]])):format(cmd, garbage))
+ ]])):format(cmd, garbage)
+ )
end
end)
it('works correctly when skipping HEREdoc variant', function()
- eq(true, pcall(source, (dedent([[
+ eq(
+ true,
+ pcall(
+ source,
+ (dedent([[
if 0
%s << EOF
%s
EOF
endif
- ]])):format(cmd, garbage)))
+ ]])):format(cmd, garbage)
+ )
+ )
eq('', exec_capture('messages'))
if check_neq then
- eq(true, pcall(source, (dedent([[
+ eq(
+ true,
+ pcall(
+ source,
+ (dedent([[
let g:exc = 0
try
%s << EOF
@@ -61,8 +80,10 @@ describe('script_get-based command', function()
catch
let g:exc = v:exception
endtry
- ]])):format(cmd, garbage)))
- neq(0, meths.get_var('exc'))
+ ]])):format(cmd, garbage)
+ )
+ )
+ neq(0, api.nvim_get_var('exc'))
end
end)
end)
@@ -75,7 +96,7 @@ describe('script_get-based command', function()
-- Provider-based scripts
test_garbage_exec('ruby', not missing_provider('ruby'))
- test_garbage_exec('python3', not missing_provider('python3'))
+ test_garbage_exec('python3', not missing_provider('python'))
-- Missing scripts
test_garbage_exec('python', false)
diff --git a/test/functional/ex_cmds/sign_spec.lua b/test/functional/ex_cmds/sign_spec.lua
index f280a45174..06de7f23a9 100644
--- a/test/functional/ex_cmds/sign_spec.lua
+++ b/test/functional/ex_cmds/sign_spec.lua
@@ -1,5 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
-local clear, nvim, eq, assert_alive = helpers.clear, helpers.nvim, helpers.eq, helpers.assert_alive
+local clear, eq, assert_alive = helpers.clear, helpers.eq, helpers.assert_alive
+local command = helpers.command
+local api = helpers.api
describe('sign', function()
before_each(clear)
@@ -7,24 +9,24 @@ describe('sign', function()
describe('without specifying buffer', function()
it('deletes the sign from all buffers', function()
-- place a sign with id 34 to first buffer
- nvim('command', 'sign define Foo text=+ texthl=Delimiter linehl=Comment numhl=Number')
- local buf1 = nvim('eval', 'bufnr("%")')
- nvim('command', 'sign place 34 line=3 name=Foo buffer='..buf1)
+ command('sign define Foo text=+ texthl=Delimiter linehl=Comment numhl=Number')
+ local buf1 = api.nvim_eval('bufnr("%")')
+ command('sign place 34 line=3 name=Foo buffer=' .. buf1)
-- create a second buffer and place the sign on it as well
- nvim('command', 'new')
- local buf2 = nvim('eval', 'bufnr("%")')
- nvim('command', 'sign place 34 line=3 name=Foo buffer='..buf2)
+ command('new')
+ local buf2 = api.nvim_eval('bufnr("%")')
+ command('sign place 34 line=3 name=Foo buffer=' .. buf2)
-- now unplace without specifying a buffer
- nvim('command', 'sign unplace 34')
- eq("--- Signs ---\n", nvim('exec', 'sign place buffer='..buf1, true))
- eq("--- Signs ---\n", nvim('exec', 'sign place buffer='..buf2, true))
+ command('sign unplace 34')
+ eq('--- Signs ---\n', api.nvim_exec('sign place buffer=' .. buf1, true))
+ eq('--- Signs ---\n', api.nvim_exec('sign place buffer=' .. buf2, true))
end)
end)
end)
describe('define {id}', function()
- it ('does not leak memory when specifying multiple times the same argument', function()
- nvim('command', 'sign define Foo culhl=Normal culhl=Normal')
+ it('does not leak memory when specifying multiple times the same argument', function()
+ command('sign define Foo culhl=Normal culhl=Normal')
assert_alive()
end)
end)
diff --git a/test/functional/ex_cmds/source_spec.lua b/test/functional/ex_cmds/source_spec.lua
index 24987354a4..5ce0e395bd 100644
--- a/test/functional/ex_cmds/source_spec.lua
+++ b/test/functional/ex_cmds/source_spec.lua
@@ -3,7 +3,7 @@ local command = helpers.command
local insert = helpers.insert
local eq = helpers.eq
local clear = helpers.clear
-local meths = helpers.meths
+local api = helpers.api
local feed = helpers.feed
local feed_command = helpers.feed_command
local write_file = helpers.write_file
@@ -49,37 +49,43 @@ describe(':source', function()
pending("'shellslash' only works on Windows")
return
end
- meths.set_option_value('shellslash', false, {})
+ api.nvim_set_option_value('shellslash', false, {})
mkdir('Xshellslash')
- write_file([[Xshellslash/Xstack.vim]], [[
+ write_file(
+ [[Xshellslash/Xstack.vim]],
+ [[
let g:stack1 = expand('<stack>')
set shellslash
let g:stack2 = expand('<stack>')
set noshellslash
let g:stack3 = expand('<stack>')
- ]])
+ ]]
+ )
for _ = 1, 2 do
command([[source Xshellslash/Xstack.vim]])
- matches([[Xshellslash\Xstack%.vim]], meths.get_var('stack1'))
- matches([[Xshellslash/Xstack%.vim]], meths.get_var('stack2'))
- matches([[Xshellslash\Xstack%.vim]], meths.get_var('stack3'))
+ matches([[Xshellslash\Xstack%.vim]], api.nvim_get_var('stack1'))
+ matches([[Xshellslash/Xstack%.vim]], api.nvim_get_var('stack2'))
+ matches([[Xshellslash\Xstack%.vim]], api.nvim_get_var('stack3'))
end
- write_file([[Xshellslash/Xstack.lua]], [[
+ write_file(
+ [[Xshellslash/Xstack.lua]],
+ [[
vim.g.stack1 = vim.fn.expand('<stack>')
vim.o.shellslash = true
vim.g.stack2 = vim.fn.expand('<stack>')
vim.o.shellslash = false
vim.g.stack3 = vim.fn.expand('<stack>')
- ]])
+ ]]
+ )
for _ = 1, 2 do
command([[source Xshellslash/Xstack.lua]])
- matches([[Xshellslash\Xstack%.lua]], meths.get_var('stack1'))
- matches([[Xshellslash/Xstack%.lua]], meths.get_var('stack2'))
- matches([[Xshellslash\Xstack%.lua]], meths.get_var('stack3'))
+ matches([[Xshellslash\Xstack%.lua]], api.nvim_get_var('stack1'))
+ matches([[Xshellslash/Xstack%.lua]], api.nvim_get_var('stack2'))
+ matches([[Xshellslash\Xstack%.lua]], api.nvim_get_var('stack3'))
end
rmdir('Xshellslash')
@@ -101,11 +107,11 @@ describe(':source', function()
eq("{'k': 'v'}", exec_capture('echo b'))
-- Script items are created only on script var access
- eq("1", exec_capture('echo c'))
- eq("0zBEEFCAFE", exec_capture('echo d'))
+ eq('1', exec_capture('echo c'))
+ eq('0zBEEFCAFE', exec_capture('echo d'))
exec('set cpoptions+=C')
- eq('Vim(let):E723: Missing end of Dictionary \'}\': ', exc_exec('source'))
+ eq("Vim(let):E723: Missing end of Dictionary '}': ", exc_exec('source'))
end)
it('selection in current buffer', function()
@@ -132,14 +138,14 @@ describe(':source', function()
feed_command(':source')
eq('4', exec_capture('echo a'))
eq("{'K': 'V'}", exec_capture('echo b'))
- eq("<SNR>1_C()", exec_capture('echo D()'))
+ eq('<SNR>1_C()', exec_capture('echo D()'))
-- Source last line only
feed_command(':$source')
eq('Vim(echo):E117: Unknown function: s:C', exc_exec('echo D()'))
exec('set cpoptions+=C')
- eq('Vim(let):E723: Missing end of Dictionary \'}\': ', exc_exec("'<,'>source"))
+ eq("Vim(let):E723: Missing end of Dictionary '}': ", exc_exec("'<,'>source"))
end)
it('does not break if current buffer is modified while sourced', function()
@@ -163,19 +169,22 @@ describe(':source', function()
it('can source lua files', function()
local test_file = 'test.lua'
- write_file(test_file, [[
+ write_file(
+ test_file,
+ [[
vim.g.sourced_lua = 1
vim.g.sfile_value = vim.fn.expand('<sfile>')
vim.g.stack_value = vim.fn.expand('<stack>')
vim.g.script_value = vim.fn.expand('<script>')
- ]])
+ ]]
+ )
command('set shellslash')
command('source ' .. test_file)
eq(1, eval('g:sourced_lua'))
- matches([[/test%.lua$]], meths.get_var('sfile_value'))
- matches([[/test%.lua$]], meths.get_var('stack_value'))
- matches([[/test%.lua$]], meths.get_var('script_value'))
+ matches([[/test%.lua$]], api.nvim_get_var('sfile_value'))
+ matches([[/test%.lua$]], api.nvim_get_var('stack_value'))
+ matches([[/test%.lua$]], api.nvim_get_var('script_value'))
os.remove(test_file)
end)
@@ -220,9 +229,9 @@ describe(':source', function()
eq(12, eval('g:c'))
eq(' \\ 1\n "\\ 2', exec_lua('return _G.a'))
- eq(':source (no file)', meths.get_var('sfile_value'))
- eq(':source (no file)', meths.get_var('stack_value'))
- eq(':source (no file)', meths.get_var('script_value'))
+ eq(':source (no file)', api.nvim_get_var('sfile_value'))
+ eq(':source (no file)', api.nvim_get_var('stack_value'))
+ eq(':source (no file)', api.nvim_get_var('script_value'))
end)
end
@@ -245,22 +254,22 @@ describe(':source', function()
local test_file = 'test.lua'
-- Does throw E484 for unreadable files
- local ok, result = pcall(exec_capture, ":source "..test_file ..'noexisting')
+ local ok, result = pcall(exec_capture, ':source ' .. test_file .. 'noexisting')
eq(false, ok)
- neq(nil, result:find("E484"))
+ neq(nil, result:find('E484'))
-- Doesn't throw for parsing error
- write_file (test_file, "vim.g.c = ")
- ok, result = pcall(exec_capture, ":source "..test_file)
+ write_file(test_file, 'vim.g.c = ')
+ ok, result = pcall(exec_capture, ':source ' .. test_file)
eq(false, ok)
- eq(nil, result:find("E484"))
+ eq(nil, result:find('E484'))
os.remove(test_file)
-- Doesn't throw for runtime error
- write_file (test_file, "error('Cause error anyway :D')")
- ok, result = pcall(exec_capture, ":source "..test_file)
+ write_file(test_file, "error('Cause error anyway :D')")
+ ok, result = pcall(exec_capture, ':source ' .. test_file)
eq(false, ok)
- eq(nil, result:find("E484"))
+ eq(nil, result:find('E484'))
os.remove(test_file)
end)
end)
diff --git a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
index 436873b464..a6fdb919c5 100644
--- a/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
+++ b/test/functional/ex_cmds/swapfile_preserve_recover_spec.lua
@@ -1,19 +1,18 @@
local Screen = require('test.functional.ui.screen')
local helpers = require('test.functional.helpers')(after_each)
-local luv = require('luv')
-local eq, eval, expect, exec =
- helpers.eq, helpers.eval, helpers.expect, helpers.exec
+local uv = vim.uv
+local eq, eval, expect, exec = helpers.eq, helpers.eval, helpers.expect, helpers.exec
local assert_alive = helpers.assert_alive
local clear = helpers.clear
local command = helpers.command
local feed = helpers.feed
-local funcs = helpers.funcs
+local fn = helpers.fn
local nvim_prog = helpers.nvim_prog
local ok = helpers.ok
local rmdir = helpers.rmdir
local new_argv = helpers.new_argv
local new_pipename = helpers.new_pipename
-local pesc = helpers.pesc
+local pesc = vim.pesc
local os_kill = helpers.os_kill
local set_session = helpers.set_session
local spawn = helpers.spawn
@@ -22,7 +21,7 @@ local expect_msg_seq = helpers.expect_msg_seq
local pcall_err = helpers.pcall_err
local mkdir = helpers.mkdir
local poke_eventloop = helpers.poke_eventloop
-local meths = helpers.meths
+local api = helpers.api
local retry = helpers.retry
local write_file = helpers.write_file
@@ -32,24 +31,24 @@ describe(':recover', function()
it('fails if given a non-existent swapfile', function()
local swapname = 'bogus_swapfile'
local swapname2 = 'bogus_swapfile.swp'
- eq('Vim(recover):E305: No swap file found for '..swapname,
- pcall_err(command, 'recover '..swapname)) -- Should not segfault. #2117
+ eq(
+ 'Vim(recover):E305: No swap file found for ' .. swapname,
+ pcall_err(command, 'recover ' .. swapname)
+ ) -- Should not segfault. #2117
-- Also check filename ending with ".swp". #9504
- eq('Vim(recover):E306: Cannot open '..swapname2,
- pcall_err(command, 'recover '..swapname2)) -- Should not segfault. #2117
+ eq('Vim(recover):E306: Cannot open ' .. swapname2, pcall_err(command, 'recover ' .. swapname2)) -- Should not segfault. #2117
assert_alive()
end)
-
end)
describe("preserve and (R)ecover with custom 'directory'", function()
- local swapdir = luv.cwd()..'/Xtest_recover_dir'
+ local swapdir = uv.cwd() .. '/Xtest_recover_dir'
local testfile = 'Xtest_recover_file1'
-- Put swapdir at the start of the 'directory' list. #1836
-- Note: `set swapfile` *must* go after `set directory`: otherwise it may
-- attempt to create a swapfile in different directory.
local init = [[
- set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[//
+ set directory^=]] .. swapdir:gsub([[\]], [[\\]]) .. [[//
set swapfile fileformat=unix undolevels=-1
]]
@@ -67,7 +66,7 @@ describe("preserve and (R)ecover with custom 'directory'", function()
local function setup_swapname()
exec(init)
- command('edit! '..testfile)
+ command('edit! ' .. testfile)
feed('isometext<esc>')
exec('redir => g:swapname | silent swapname | redir END')
return eval('g:swapname')
@@ -75,23 +74,23 @@ describe("preserve and (R)ecover with custom 'directory'", function()
local function test_recover(swappath1)
-- Start another Nvim instance.
- local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'}, true)
+ local nvim2 = spawn({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed' }, true)
set_session(nvim2)
exec(init)
-- Use the "SwapExists" event to choose the (R)ecover choice at the dialog.
command('autocmd SwapExists * let v:swapchoice = "r"')
- command('silent edit! '..testfile)
+ command('silent edit! ' .. testfile)
exec('redir => g:swapname | silent swapname | redir END')
local swappath2 = eval('g:swapname')
expect('sometext')
-- swapfile from session 1 should end in .swp
- eq(testfile..'.swp', string.match(swappath1, '[^%%]+$'))
+ eq(testfile .. '.swp', string.match(swappath1, '[^%%]+$'))
-- swapfile from session 2 should end in .swo
- eq(testfile..'.swo', string.match(swappath2, '[^%%]+$'))
+ eq(testfile .. '.swo', string.match(swappath2, '[^%%]+$'))
-- Verify that :swapname was not truncated (:help 'shortmess').
ok(nil == string.find(swappath1, '%.%.%.'))
ok(nil == string.find(swappath2, '%.%.%.'))
@@ -115,27 +114,28 @@ describe("preserve and (R)ecover with custom 'directory'", function()
local screen0 = Screen.new()
screen0:attach()
local child_server = new_pipename()
- funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--listen', child_server})
- screen0:expect({any = pesc('[No Name]')}) -- Wait for the child process to start.
+ fn.termopen({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--listen', child_server }, {
+ env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
+ })
+ screen0:expect({ any = pesc('[No Name]') }) -- Wait for the child process to start.
local child_session = helpers.connect(child_server)
set_session(child_session)
local swappath1 = setup_swapname()
set_session(nvim0)
- command('call chanclose(&channel)') -- Kill the child process.
- screen0:expect({any = pesc('[Process exited 1]')}) -- Wait for the child process to stop.
+ command('call chanclose(&channel)') -- Kill the child process.
+ screen0:expect({ any = pesc('[Process exited 1]') }) -- Wait for the child process to stop.
test_recover(swappath1)
end)
-
end)
describe('swapfile detection', function()
- local swapdir = luv.cwd()..'/Xtest_swapdialog_dir'
+ local swapdir = uv.cwd() .. '/Xtest_swapdialog_dir'
local nvim0
-- Put swapdir at the start of the 'directory' list. #1836
-- Note: `set swapfile` *must* go after `set directory`: otherwise it may
-- attempt to create a swapfile in different directory.
local init = [[
- set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[//
+ set directory^=]] .. swapdir:gsub([[\]], [[\\]]) .. [[//
set swapfile fileformat=unix nomodified undolevels=-1 nohidden
]]
before_each(function()
@@ -153,67 +153,88 @@ describe('swapfile detection', function()
it('always show swapfile dialog #8840 #9027', function()
local testfile = 'Xtest_swapdialog_file1'
- local expected_no_dialog = '^'..(' '):rep(256)..'|\n'
- for _=1,37 do
- expected_no_dialog = expected_no_dialog..'~'..(' '):rep(255)..'|\n'
+ local expected_no_dialog = '^' .. (' '):rep(256) .. '|\n'
+ for _ = 1, 37 do
+ expected_no_dialog = expected_no_dialog .. '~' .. (' '):rep(255) .. '|\n'
end
- expected_no_dialog = expected_no_dialog..testfile..(' '):rep(216)..'0,0-1 All|\n'
- expected_no_dialog = expected_no_dialog..(' '):rep(256)..'|\n'
+ expected_no_dialog = expected_no_dialog .. testfile .. (' '):rep(216) .. '0,0-1 All|\n'
+ expected_no_dialog = expected_no_dialog .. (' '):rep(256) .. '|\n'
exec(init)
- command('edit! '..testfile)
+ command('edit! ' .. testfile)
feed('isometext<esc>')
command('preserve')
-- Start another Nvim instance.
- local nvim2 = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed'}, true, nil, true)
+ local nvim2 = spawn({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed' }, true, nil, true)
set_session(nvim2)
local screen2 = Screen.new(256, 40)
screen2:attach()
exec(init)
- command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
-- With shortmess+=F
command('set shortmess+=F')
- feed(':edit '..testfile..'<CR>')
- screen2:expect{any=[[E325: ATTENTION.*]]..'\n'..[[Found a swap file by the name ".*]]
- ..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]}
- feed('e') -- Chose "Edit" at the swap dialog.
+ feed(':edit ' .. testfile .. '<CR>')
+ screen2:expect {
+ any = [[E325: ATTENTION.*]]
+ .. '\n'
+ .. [[Found a swap file by the name ".*]]
+ .. [[Xtest_swapdialog_dir[/\].*]]
+ .. testfile
+ .. [[%.swp"]],
+ }
+ feed('e') -- Chose "Edit" at the swap dialog.
screen2:expect(expected_no_dialog)
-- With :silent and shortmess+=F
feed(':silent edit %<CR>')
- screen2:expect{any=[[Found a swap file by the name ".*]]
- ..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]}
- feed('e') -- Chose "Edit" at the swap dialog.
+ screen2:expect {
+ any = [[Found a swap file by the name ".*]]
+ .. [[Xtest_swapdialog_dir[/\].*]]
+ .. testfile
+ .. [[%.swp"]],
+ }
+ feed('e') -- Chose "Edit" at the swap dialog.
screen2:expect(expected_no_dialog)
-- With :silent! and shortmess+=F
feed(':silent! edit %<CR>')
- screen2:expect{any=[[Found a swap file by the name ".*]]
- ..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]}
- feed('e') -- Chose "Edit" at the swap dialog.
+ screen2:expect {
+ any = [[Found a swap file by the name ".*]]
+ .. [[Xtest_swapdialog_dir[/\].*]]
+ .. testfile
+ .. [[%.swp"]],
+ }
+ feed('e') -- Chose "Edit" at the swap dialog.
screen2:expect(expected_no_dialog)
-- With API (via eval/Vimscript) call and shortmess+=F
feed(':call nvim_command("edit %")<CR>')
- screen2:expect{any=[[Found a swap file by the name ".*]]
- ..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]}
- feed('e') -- Chose "Edit" at the swap dialog.
+ screen2:expect {
+ any = [[Found a swap file by the name ".*]]
+ .. [[Xtest_swapdialog_dir[/\].*]]
+ .. testfile
+ .. [[%.swp"]],
+ }
+ feed('e') -- Chose "Edit" at the swap dialog.
feed('<c-c>')
screen2:expect(expected_no_dialog)
-- With API call and shortmess+=F
- async_meths.command('edit %')
- screen2:expect{any=[[Found a swap file by the name ".*]]
- ..[[Xtest_swapdialog_dir[/\].*]]..testfile..[[%.swp"]]}
- feed('e') -- Chose "Edit" at the swap dialog.
+ async_meths.nvim_command('edit %')
+ screen2:expect {
+ any = [[Found a swap file by the name ".*]]
+ .. [[Xtest_swapdialog_dir[/\].*]]
+ .. testfile
+ .. [[%.swp"]],
+ }
+ feed('e') -- Chose "Edit" at the swap dialog.
expect_msg_seq({
- ignore={'redraw'},
- seqs={
- { {'notification', 'nvim_error_event', {0, 'Vim(edit):E325: ATTENTION'}},
- }
- }
+ ignore = { 'redraw' },
+ seqs = {
+ { { 'notification', 'nvim_error_event', { 0, 'Vim(edit):E325: ATTENTION' } } },
+ },
})
feed('<cr>')
@@ -224,8 +245,8 @@ describe('swapfile detection', function()
exec(init)
command('edit Xfile1')
command("put ='some text...'")
- command('preserve') -- Make sure the swap file exists.
- local nvimpid = funcs.getpid()
+ command('preserve') -- Make sure the swap file exists.
+ local nvimpid = fn.getpid()
local nvim1 = spawn(new_argv(), true, nil, true)
set_session(nvim1)
@@ -242,44 +263,29 @@ describe('swapfile detection', function()
it('selecting "q" in the attention prompt', function()
exec(init)
command('edit Xfile1')
- command('preserve') -- Make sure the swap file exists.
+ command('preserve') -- Make sure the swap file exists.
local screen = Screen.new(75, 18)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
})
local nvim1 = spawn(new_argv(), true, nil, true)
set_session(nvim1)
screen:attach()
exec(init)
- command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
feed(':split Xfile1\n')
-- The default SwapExists handler does _not_ skip this prompt.
screen:expect({
- any = pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^')
+ any = pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'),
})
feed('q')
feed(':<CR>')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*16
: |
]])
nvim1:close()
@@ -288,35 +294,20 @@ describe('swapfile detection', function()
set_session(nvim2)
screen:attach()
exec(init)
- command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
command('set more')
command('au bufadd * let foo_w = wincol()')
feed(':e Xfile1<CR>')
- screen:expect({any = pesc('{1:-- More --}^')})
+ screen:expect({ any = pesc('{1:-- More --}^') })
feed('<Space>')
screen:expect({
- any = pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^')
+ any = pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'),
})
feed('q')
command([[echo 'hello']])
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*16
hello |
]])
nvim2:close()
@@ -327,15 +318,15 @@ describe('swapfile detection', function()
local function test_swapfile_after_reboot(swapexists, on_swapfile_running)
local screen = Screen.new(75, 30)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
- [2] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- ErrorMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
+ [2] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg
})
screen:attach()
exec(init)
if not swapexists then
- command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
+ command('autocmd! nvim_swapfile') -- Delete the default handler (which skips the dialog).
end
command('set nohidden')
@@ -361,7 +352,7 @@ describe('swapfile detection', function()
edit Xswaptest
call setline(1, ['a', 'b', 'c'])
]])
- local swname = funcs.CopySwapfile()
+ local swname = fn.CopySwapfile()
-- Forget we edited this file
exec([[
@@ -385,14 +376,16 @@ describe('swapfile detection', function()
]])
-- pretend that the swapfile was created before boot
- local atime = os.time() - luv.uptime() - 10
- luv.fs_utime(swname, atime, atime)
+ local atime = os.time() - uv.uptime() - 10
+ uv.fs_utime(swname, atime, atime)
feed(':edit Xswaptest<CR>')
- screen:expect({any = table.concat({
- pesc('{2:E325: ATTENTION}'),
- pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort: }^'),
- }, '.*')})
+ screen:expect({
+ any = table.concat({
+ pesc('{2:E325: ATTENTION}'),
+ pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort: }^'),
+ }, '.*'),
+ })
feed('e')
end
@@ -400,12 +393,14 @@ describe('swapfile detection', function()
-- oldtest: Test_nocatch_process_still_running()
it('swapfile created before boot vim-patch:8.2.2586', function()
test_swapfile_after_reboot(false, function(screen)
- screen:expect({any = table.concat({
- pesc('{2:E325: ATTENTION}'),
- 'file name: .*Xswaptest',
- 'process ID: %d* %(STILL RUNNING%)',
- pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'),
- }, '.*')})
+ screen:expect({
+ any = table.concat({
+ pesc('{2:E325: ATTENTION}'),
+ 'file name: .*Xswaptest',
+ 'process ID: %d* %(STILL RUNNING%)',
+ pesc('{1:[O]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: }^'),
+ }, '.*'),
+ })
end)
end)
@@ -414,34 +409,36 @@ describe('swapfile detection', function()
screen:expect({ any = 'W325: Ignoring swapfile from Nvim process' })
end)
end)
-
end)
describe('quitting swapfile dialog on startup stops TUI properly', function()
- local swapdir = luv.cwd()..'/Xtest_swapquit_dir'
+ local swapdir = uv.cwd() .. '/Xtest_swapquit_dir'
local testfile = 'Xtest_swapquit_file1'
local otherfile = 'Xtest_swapquit_file2'
-- Put swapdir at the start of the 'directory' list. #1836
-- Note: `set swapfile` *must* go after `set directory`: otherwise it may
-- attempt to create a swapfile in different directory.
- local init_dir = [[set directory^=]]..swapdir:gsub([[\]], [[\\]])..[[//]]
+ local init_dir = [[set directory^=]] .. swapdir:gsub([[\]], [[\\]]) .. [[//]]
local init_set = [[set swapfile fileformat=unix nomodified undolevels=-1 nohidden]]
before_each(function()
- clear({args = {'--cmd', init_dir, '--cmd', init_set}})
+ clear({ args = { '--cmd', init_dir, '--cmd', init_set } })
rmdir(swapdir)
mkdir(swapdir)
- write_file(testfile, [[
+ write_file(
+ testfile,
+ [[
first
second
third
- ]])
- command('edit! '..testfile)
+ ]]
+ )
+ command('edit! ' .. testfile)
feed('Gisometext<esc>')
poke_eventloop()
- clear() -- Leaves a swap file behind
- meths.ui_attach(80, 30, {})
+ clear() -- Leaves a swap file behind
+ api.nvim_ui_attach(80, 30, {})
end)
after_each(function()
rmdir(swapdir)
@@ -450,57 +447,100 @@ describe('quitting swapfile dialog on startup stops TUI properly', function()
end)
it('(Q)uit at first file argument', function()
- local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE',
- '--cmd', init_dir, '--cmd', init_set,
- testfile})
+ local chan = fn.termopen(
+ { nvim_prog, '-u', 'NONE', '-i', 'NONE', '--cmd', init_dir, '--cmd', init_set, testfile },
+ {
+ env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
+ }
+ )
retry(nil, nil, function()
- eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
- eval("getline('$')->trim(' ', 2)"))
+ eq(
+ '[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
+ eval("getline('$')->trim(' ', 2)")
+ )
end)
- meths.chan_send(chan, 'q')
+ api.nvim_chan_send(chan, 'q')
retry(nil, nil, function()
- eq({'', '[Process exited 1]', ''},
- eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})"))
+ eq(
+ { '', '[Process exited 1]', '' },
+ eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")
+ )
end)
end)
it('(A)bort at second file argument with -p', function()
- local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE',
- '--cmd', init_dir, '--cmd', init_set,
- '-p', otherfile, testfile})
+ local chan = fn.termopen({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ init_dir,
+ '--cmd',
+ init_set,
+ '-p',
+ otherfile,
+ testfile,
+ }, {
+ env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
+ })
retry(nil, nil, function()
- eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
- eval("getline('$')->trim(' ', 2)"))
+ eq(
+ '[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
+ eval("getline('$')->trim(' ', 2)")
+ )
end)
- meths.chan_send(chan, 'a')
+ api.nvim_chan_send(chan, 'a')
retry(nil, nil, function()
- eq({'', '[Process exited 1]', ''},
- eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})"))
+ eq(
+ { '', '[Process exited 1]', '' },
+ eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")
+ )
end)
end)
it('(Q)uit at file opened by -t', function()
- write_file(otherfile, ([[
+ write_file(
+ otherfile,
+ ([[
!_TAG_FILE_ENCODING utf-8 //
first %s /^ \zsfirst$/
second %s /^ \zssecond$/
- third %s /^ \zsthird$/]]):format(testfile, testfile, testfile))
- local chan = funcs.termopen({nvim_prog, '-u', 'NONE', '-i', 'NONE',
- '--cmd', init_dir, '--cmd', init_set,
- '--cmd', 'set tags='..otherfile, '-tsecond'})
+ third %s /^ \zsthird$/]]):format(testfile, testfile, testfile)
+ )
+ local chan = fn.termopen({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ init_dir,
+ '--cmd',
+ init_set,
+ '--cmd',
+ 'set tags=' .. otherfile,
+ '-tsecond',
+ }, {
+ env = { VIMRUNTIME = os.getenv('VIMRUNTIME') },
+ })
retry(nil, nil, function()
- eq('[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
- eval("getline('$')->trim(' ', 2)"))
+ eq(
+ '[O]pen Read-Only, (E)dit anyway, (R)ecover, (D)elete it, (Q)uit, (A)bort:',
+ eval("getline('$')->trim(' ', 2)")
+ )
end)
- meths.chan_send(chan, 'q')
+ api.nvim_chan_send(chan, 'q')
retry(nil, nil, function()
- eq('Press ENTER or type command to continue',
- eval("getline('$')->trim(' ', 2)"))
+ eq('Press ENTER or type command to continue', eval("getline('$')->trim(' ', 2)"))
end)
- meths.chan_send(chan, '\r')
+ api.nvim_chan_send(chan, '\r')
retry(nil, nil, function()
- eq({'', '[Process exited 1]', ''},
- eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})"))
+ eq(
+ { '', '[Process exited 1]', '' },
+ eval("[1, 2, '$']->map({_, lnum -> getline(lnum)->trim(' ', 2)})")
+ )
end)
end)
end)
diff --git a/test/functional/ex_cmds/syntax_spec.lua b/test/functional/ex_cmds/syntax_spec.lua
index c9e96703de..ccdd604c55 100644
--- a/test/functional/ex_cmds/syntax_spec.lua
+++ b/test/functional/ex_cmds/syntax_spec.lua
@@ -8,10 +8,11 @@ describe(':syntax', function()
before_each(clear)
describe('keyword', function()
- it('does not crash when group name contains unprintable characters',
- function()
- eq('Vim(syntax):E669: Unprintable character in group name',
- exc_exec('syntax keyword \024 foo bar'))
+ it('does not crash when group name contains unprintable characters', function()
+ eq(
+ 'Vim(syntax):E669: Unprintable character in group name',
+ exc_exec('syntax keyword \024 foo bar')
+ )
end)
end)
end)
diff --git a/test/functional/ex_cmds/trust_spec.lua b/test/functional/ex_cmds/trust_spec.lua
index fe13bd7cd2..2997b504fa 100644
--- a/test/functional/ex_cmds/trust_spec.lua
+++ b/test/functional/ex_cmds/trust_spec.lua
@@ -7,7 +7,7 @@ local exec_capture = helpers.exec_capture
local matches = helpers.matches
local pathsep = helpers.get_pathsep()
local is_os = helpers.is_os
-local funcs = helpers.funcs
+local fn = helpers.fn
describe(':trust', function()
local xstate = 'Xstate'
@@ -22,7 +22,7 @@ describe(':trust', function()
before_each(function()
helpers.write_file('test_file', 'test')
- clear{env={XDG_STATE_HOME=xstate}}
+ clear { env = { XDG_STATE_HOME = xstate } }
end)
after_each(function()
@@ -30,50 +30,53 @@ describe(':trust', function()
end)
it('trust then deny then remove a file using current buffer', function()
- local cwd = funcs.getcwd()
- local hash = funcs.sha256(helpers.read_file('test_file'))
+ local cwd = fn.getcwd()
+ local hash = fn.sha256(helpers.read_file('test_file'))
command('edit test_file')
matches('^Allowed ".*test_file" in trust database%.$', exec_capture('trust'))
- local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, cwd .. pathsep .. 'test_file'), vim.trim(trust))
matches('^Denied ".*test_file" in trust database%.$', exec_capture('trust ++deny'))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust))
matches('^Removed ".*test_file" from trust database%.$', exec_capture('trust ++remove'))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format(''), vim.trim(trust))
end)
it('deny then trust then remove a file using current buffer', function()
- local cwd = funcs.getcwd()
- local hash = funcs.sha256(helpers.read_file('test_file'))
+ local cwd = fn.getcwd()
+ local hash = fn.sha256(helpers.read_file('test_file'))
command('edit test_file')
matches('^Denied ".*test_file" in trust database%.$', exec_capture('trust ++deny'))
- local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust))
matches('^Allowed ".*test_file" in trust database%.$', exec_capture('trust'))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, cwd .. pathsep .. 'test_file'), vim.trim(trust))
matches('^Removed ".*test_file" from trust database%.$', exec_capture('trust ++remove'))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format(''), vim.trim(trust))
end)
it('deny then remove a file using file path', function()
- local cwd = funcs.getcwd()
+ local cwd = fn.getcwd()
matches('^Denied ".*test_file" in trust database%.$', exec_capture('trust ++deny test_file'))
- local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', cwd .. pathsep .. 'test_file'), vim.trim(trust))
- matches('^Removed ".*test_file" from trust database%.$', exec_capture('trust ++remove test_file'))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ matches(
+ '^Removed ".*test_file" from trust database%.$',
+ exec_capture('trust ++remove test_file')
+ )
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format(''), vim.trim(trust))
end)
end)
diff --git a/test/functional/ex_cmds/verbose_spec.lua b/test/functional/ex_cmds/verbose_spec.lua
index 50077e9e0c..7ceb2460d3 100644
--- a/test/functional/ex_cmds/verbose_spec.lua
+++ b/test/functional/ex_cmds/verbose_spec.lua
@@ -5,19 +5,21 @@ local eq = helpers.eq
local exec = helpers.exec
local exec_capture = helpers.exec_capture
local write_file = helpers.write_file
-local call_viml_function = helpers.meths.call_function
+local call_viml_function = helpers.api.nvim_call_function
local function last_set_tests(cmd)
local script_location, script_file
-- All test cases below use the same nvim instance.
setup(function()
- clear{args={'-V1'}}
+ clear { args = { '-V1' } }
script_file = 'test_verbose.lua'
local current_dir = call_viml_function('getcwd', {})
- current_dir = call_viml_function('fnamemodify', {current_dir, ':~'})
- script_location = table.concat{current_dir, helpers.get_pathsep(), script_file}
+ current_dir = call_viml_function('fnamemodify', { current_dir, ':~' })
+ script_location = table.concat { current_dir, helpers.get_pathsep(), script_file }
- write_file(script_file, [[
+ write_file(
+ script_file,
+ [[
vim.api.nvim_set_option_value('hlsearch', false, {})
vim.bo.expandtab = true
vim.opt.number = true
@@ -45,7 +47,8 @@ function! s:return80()\
endfunction\
let &tw = s:return80()\
", true)
-]])
+]]
+ )
exec(cmd .. ' ' .. script_file)
end)
@@ -55,54 +58,84 @@ let &tw = s:return80()\
it('"Last set" for option set by Lua', function()
local result = exec_capture(':verbose set hlsearch?')
- eq(string.format([[
+ eq(
+ string.format(
+ [[
nohlsearch
Last set from %s line 1]],
- script_location), result)
+ script_location
+ ),
+ result
+ )
end)
it('"Last set" for option set by vim.o', function()
local result = exec_capture(':verbose set expandtab?')
- eq(string.format([[
+ eq(
+ string.format(
+ [[
expandtab
Last set from %s line 2]],
- script_location), result)
+ script_location
+ ),
+ result
+ )
end)
it('"Last set" for option set by vim.opt', function()
local result = exec_capture(':verbose set number?')
- eq(string.format([[
+ eq(
+ string.format(
+ [[
number
Last set from %s line 3]],
- script_location), result)
+ script_location
+ ),
+ result
+ )
end)
it('"Last set" for mapping set by Lua', function()
local result = exec_capture(':verbose map <leader>key1')
- eq(string.format([[
+ eq(
+ string.format(
+ [[
n \key1 * :echo "test"<CR>
Last set from %s line 4]],
- script_location), result)
+ script_location
+ ),
+ result
+ )
end)
it('"Last set" for mapping set by vim.keymap', function()
local result = exec_capture(':verbose map <leader>key2')
- eq(string.format([[
+ eq(
+ string.format(
+ [[
n \key2 * :echo "test"<CR>
Last set from %s line 5]],
- script_location), result)
+ script_location
+ ),
+ result
+ )
end)
it('"Last set" for autocmd by vim.api.nvim_exec', function()
local result = exec_capture(':verbose autocmd test_group Filetype c')
- eq(string.format([[
+ eq(
+ string.format(
+ [[
--- Autocommands ---
test_group FileType
c setl cindent
Last set from %s line 7]],
- script_location), result)
+ script_location
+ ),
+ result
+ )
end)
it('"Last set" for command defined by nvim_command', function()
@@ -110,38 +143,58 @@ test_group FileType
pending('nvim_command does not set the script context')
end
local result = exec_capture(':verbose command Bdelete')
- eq(string.format([[
+ eq(
+ string.format(
+ [[
Name Args Address Complete Definition
Bdelete 0 :bd
Last set from %s line 13]],
- script_location), result)
+ script_location
+ ),
+ result
+ )
end)
it('"Last set" for command defined by nvim_create_user_command', function()
local result = exec_capture(':verbose command TestCommand')
- eq(string.format([[
+ eq(
+ string.format(
+ [[
Name Args Address Complete Definition
TestCommand 0 :echo 'Hello'
Last set from %s line 14]],
- script_location), result)
+ script_location
+ ),
+ result
+ )
end)
it('"Last set" for function', function()
local result = exec_capture(':verbose function Close_Window')
- eq(string.format([[
+ eq(
+ string.format(
+ [[
function Close_Window() abort
Last set from %s line 16
1 wincmd -
endfunction]],
- script_location), result)
+ script_location
+ ),
+ result
+ )
end)
it('"Last set" works with anonymous sid', function()
local result = exec_capture(':verbose set tw?')
- eq(string.format([[
+ eq(
+ string.format(
+ [[
textwidth=80
Last set from %s line 22]],
- script_location), result)
+ script_location
+ ),
+ result
+ )
end)
end
@@ -159,10 +212,13 @@ describe('lua verbose:', function()
setup(function()
clear()
script_file = 'test_luafile.lua'
- write_file(script_file, [[
+ write_file(
+ script_file,
+ [[
vim.api.nvim_set_option_value('hlsearch', false, {})
- ]])
- exec(':source '..script_file)
+ ]]
+ )
+ exec(':source ' .. script_file)
end)
teardown(function()
@@ -171,9 +227,11 @@ describe('lua verbose:', function()
it('is disabled when verbose = 0', function()
local result = exec_capture(':verbose set hlsearch?')
- eq([[
+ eq(
+ [[
nohlsearch
- Last set from Lua]], result)
+ Last set from Lua]],
+ result
+ )
end)
end)
-
diff --git a/test/functional/ex_cmds/wincmd_spec.lua b/test/functional/ex_cmds/wincmd_spec.lua
index b1f174f445..98c6358f45 100644
--- a/test/functional/ex_cmds/wincmd_spec.lua
+++ b/test/functional/ex_cmds/wincmd_spec.lua
@@ -1,13 +1,13 @@
-local helpers = require("test.functional.helpers")(after_each)
+local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
-local funcs = helpers.funcs
+local fn = helpers.fn
local command = helpers.command
it(':wincmd accepts a count', function()
clear()
command('vsplit')
- eq(1, funcs.winnr())
+ eq(1, fn.winnr())
command('wincmd 2 w')
- eq(2, funcs.winnr())
+ eq(2, fn.winnr())
end)
diff --git a/test/functional/ex_cmds/write_spec.lua b/test/functional/ex_cmds/write_spec.lua
index 0b8ce93b09..f711731072 100644
--- a/test/functional/ex_cmds/write_spec.lua
+++ b/test/functional/ex_cmds/write_spec.lua
@@ -1,13 +1,11 @@
local helpers = require('test.functional.helpers')(after_each)
-local luv = require('luv')
local eq, eval, clear, write_file, source, insert =
- helpers.eq, helpers.eval, helpers.clear, helpers.write_file,
- helpers.source, helpers.insert
+ helpers.eq, helpers.eval, helpers.clear, helpers.write_file, helpers.source, helpers.insert
local pcall_err = helpers.pcall_err
local command = helpers.command
local feed_command = helpers.feed_command
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local skip = helpers.skip
local is_os = helpers.is_os
local is_ci = helpers.is_ci
@@ -40,9 +38,9 @@ describe(':write', function()
command('set backupcopy=auto')
write_file('test_bkc_file.txt', 'content0')
if is_os('win') then
- command("silent !mklink test_bkc_link.txt test_bkc_file.txt")
+ command('silent !mklink test_bkc_link.txt test_bkc_file.txt')
else
- command("silent !ln -s test_bkc_file.txt test_bkc_link.txt")
+ command('silent !ln -s test_bkc_file.txt test_bkc_link.txt')
end
if eval('v:shell_error') ~= 0 then
pending('Cannot create symlink')
@@ -61,9 +59,9 @@ describe(':write', function()
command('set backupcopy=no')
write_file('test_bkc_file.txt', 'content0')
if is_os('win') then
- command("silent !mklink test_bkc_link.txt test_bkc_file.txt")
+ command('silent !mklink test_bkc_link.txt test_bkc_file.txt')
else
- command("silent !ln -s test_bkc_file.txt test_bkc_link.txt")
+ command('silent !ln -s test_bkc_file.txt test_bkc_link.txt')
end
if eval('v:shell_error') ~= 0 then
pending('Cannot create symlink')
@@ -77,73 +75,80 @@ describe(':write', function()
eq(eval("['content1']"), eval("readfile('test_bkc_link.txt')"))
end)
- it("appends FIFO file", function()
+ it('appends FIFO file', function()
-- mkfifo creates read-only .lnk files on Windows
if is_os('win') or eval("executable('mkfifo')") == 0 then
pending('missing "mkfifo" command')
end
- local text = "some fifo text from write_spec"
- assert(os.execute("mkfifo test_fifo"))
+ local text = 'some fifo text from write_spec'
+ assert(os.execute('mkfifo test_fifo'))
insert(text)
-- Blocks until a consumer reads the FIFO.
- feed_command("write >> test_fifo")
+ feed_command('write >> test_fifo')
-- Read the FIFO, this will unblock the :write above.
- local fifo = assert(io.open("test_fifo"))
- eq(text.."\n", fifo:read("*all"))
+ local fifo = assert(io.open('test_fifo'))
+ eq(text .. '\n', fifo:read('*all'))
fifo:close()
end)
- it("++p creates missing parent directories", function()
+ it('++p creates missing parent directories', function()
eq(0, eval("filereadable('p_opt.txt')"))
- command("write ++p p_opt.txt")
+ command('write ++p p_opt.txt')
eq(1, eval("filereadable('p_opt.txt')"))
- os.remove("p_opt.txt")
+ os.remove('p_opt.txt')
eq(0, eval("filereadable('p_opt.txt')"))
- command("write ++p ./p_opt.txt")
+ command('write ++p ./p_opt.txt')
eq(1, eval("filereadable('p_opt.txt')"))
- os.remove("p_opt.txt")
+ os.remove('p_opt.txt')
eq(0, eval("filereadable('test/write/p_opt.txt')"))
- command("write ++p test/write/p_opt.txt")
+ command('write ++p test/write/p_opt.txt')
eq(1, eval("filereadable('test/write/p_opt.txt')"))
- eq(('Vim(write):E32: No file name'), pcall_err(command, 'write ++p test_write/'))
+ eq('Vim(write):E32: No file name', pcall_err(command, 'write ++p test_write/'))
if not is_os('win') then
- eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'),
- pcall_err(command, 'write ++p .'))
- eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'),
- pcall_err(command, 'write ++p ./'))
+ eq(
+ ('Vim(write):E17: "' .. fn.fnamemodify('.', ':p:h') .. '" is a directory'),
+ pcall_err(command, 'write ++p .')
+ )
+ eq(
+ ('Vim(write):E17: "' .. fn.fnamemodify('.', ':p:h') .. '" is a directory'),
+ pcall_err(command, 'write ++p ./')
+ )
end
end)
it('errors out correctly', function()
skip(is_ci('cirrus'))
command('let $HOME=""')
- eq(funcs.fnamemodify('.', ':p:h'), funcs.fnamemodify('.', ':p:h:~'))
+ eq(fn.fnamemodify('.', ':p:h'), fn.fnamemodify('.', ':p:h:~'))
-- Message from check_overwrite
if not is_os('win') then
- eq(('Vim(write):E17: "'..funcs.fnamemodify('.', ':p:h')..'" is a directory'),
- pcall_err(command, 'write .'))
+ eq(
+ ('Vim(write):E17: "' .. fn.fnamemodify('.', ':p:h') .. '" is a directory'),
+ pcall_err(command, 'write .')
+ )
end
- meths.set_option_value('writeany', true, {})
+ api.nvim_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_value('backupdir', '.', {})
- meths.set_option_value('backup', true, {})
+ eq('Vim(write):E502: "." is a directory', pcall_err(command, 'write .'))
+ fn.mkdir(fname_bak)
+ api.nvim_set_option_value('backupdir', '.', {})
+ api.nvim_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_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'))
+ fn.setline(1, 'TTY')
+ eq("Vim(write):E510: Can't make backup file (add ! to override)", pcall_err(command, 'write'))
+ api.nvim_set_option_value('backup', false, {})
+ fn.setfperm(fname, 'r--------')
+ eq(
+ 'Vim(write):E505: "Xtest-functional-ex_cmds-write" is read-only (add ! to override)',
+ pcall_err(command, 'write')
+ )
if is_os('win') then
eq(0, os.execute('del /q/f ' .. fname))
eq(0, os.execute('rd /q/s ' .. fname_bak))
@@ -153,8 +158,7 @@ describe(':write', function()
end
write_file(fname_bak, 'TTYX')
skip(is_os('win'), [[FIXME: exc_exec('write!') outputs 0 in Windows]])
- luv.fs_symlink(fname_bak .. ('/xxxxx'):rep(20), fname)
- eq('Vim(write):E166: Can\'t open linked file for writing',
- pcall_err(command, 'write!'))
+ vim.uv.fs_symlink(fname_bak .. ('/xxxxx'):rep(20), fname)
+ eq("Vim(write):E166: Can't open linked file for writing", pcall_err(command, 'write!'))
end)
end)
diff --git a/test/functional/ex_cmds/wundo_spec.lua b/test/functional/ex_cmds/wundo_spec.lua
index b6fcae0cf4..78081fa45f 100644
--- a/test/functional/ex_cmds/wundo_spec.lua
+++ b/test/functional/ex_cmds/wundo_spec.lua
@@ -2,9 +2,12 @@
local helpers = require('test.functional.helpers')(after_each)
local command, clear, eval, spawn, nvim_prog, set_session =
- helpers.command, helpers.clear, helpers.eval, helpers.spawn,
- helpers.nvim_prog, helpers.set_session
-
+ helpers.command,
+ helpers.clear,
+ helpers.eval,
+ helpers.spawn,
+ helpers.nvim_prog,
+ helpers.set_session
describe(':wundo', function()
before_each(clear)
@@ -21,10 +24,18 @@ end)
describe('u_* functions', function()
it('safely fail on new, non-empty buffer', function()
- local session = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed',
- '-c', 'set undodir=. undofile'})
+ local session = spawn({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--embed',
+ '-c',
+ 'set undodir=. undofile',
+ })
set_session(session)
- command('echo "True"') -- Should not error out due to crashed Neovim
+ command('echo "True"') -- Should not error out due to crashed Neovim
session:close()
end)
end)
diff --git a/test/functional/ex_cmds/wviminfo_spec.lua b/test/functional/ex_cmds/wviminfo_spec.lua
index 7525343891..23ae1440e6 100644
--- a/test/functional/ex_cmds/wviminfo_spec.lua
+++ b/test/functional/ex_cmds/wviminfo_spec.lua
@@ -1,8 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
-local luv = require('luv')
local clear = helpers.clear
-local command, eq, neq, write_file =
- helpers.command, helpers.eq, helpers.neq, helpers.write_file
+local command, eq, neq, write_file = helpers.command, helpers.eq, helpers.neq, helpers.write_file
local read_file = helpers.read_file
local is_os = helpers.is_os
@@ -10,21 +8,27 @@ describe(':wshada', function()
local shada_file = 'wshada_test'
before_each(function()
- clear{args={'-i', is_os('win') and 'nul' or '/dev/null',
- -- Need 'swapfile' for these tests.
- '--cmd', 'set swapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler'},
- args_rm={'-n', '-i', '--cmd'}}
+ clear {
+ args = {
+ '-i',
+ is_os('win') and 'nul' or '/dev/null',
+ -- Need 'swapfile' for these tests.
+ '--cmd',
+ 'set swapfile undodir=. directory=. viewdir=. backupdir=. belloff= noshowcmd noruler',
+ },
+ args_rm = { '-n', '-i', '--cmd' },
+ }
end)
- after_each(function ()
+ after_each(function()
os.remove(shada_file)
end)
it('creates a shada file', function()
-- file should _not_ exist
- eq(nil, luv.fs_stat(shada_file))
- command('wsh! '..shada_file)
+ eq(nil, vim.uv.fs_stat(shada_file))
+ command('wsh! ' .. shada_file)
-- file _should_ exist
- neq(nil, luv.fs_stat(shada_file))
+ neq(nil, vim.uv.fs_stat(shada_file))
end)
it('overwrites existing files', function()
@@ -35,16 +39,15 @@ describe(':wshada', function()
-- sanity check
eq(text, read_file(shada_file))
- neq(nil, luv.fs_stat(shada_file))
+ neq(nil, vim.uv.fs_stat(shada_file))
- command('wsh! '..shada_file)
+ command('wsh! ' .. shada_file)
-- File should have been overwritten with a shada file.
local fp = io.open(shada_file, 'r')
local char1 = fp:read(1)
fp:close()
-- ShaDa file starts with a “header†entry
- assert(char1:byte() == 0x01,
- shada_file..' should be a shada file')
+ assert(char1:byte() == 0x01, shada_file .. ' should be a shada file')
end)
end)
diff --git a/test/functional/example_spec.lua b/test/functional/example_spec.lua
index f07f88b2b6..5fc55f4aab 100644
--- a/test/functional/example_spec.lua
+++ b/test/functional/example_spec.lua
@@ -12,12 +12,12 @@ describe('example', function()
local screen
before_each(function()
clear()
- screen = Screen.new(20,5)
+ screen = Screen.new(20, 5)
screen:attach()
- screen:set_default_attr_ids( {
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {bold=true, foreground=Screen.colors.Brown}
- } )
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { bold = true, foreground = Screen.colors.Brown },
+ })
end)
it('screen test', function()
@@ -47,7 +47,7 @@ describe('example', function()
-- For this example, we enable `ext_tabline`:
screen:detach()
screen = Screen.new(25, 5)
- screen:attach({rgb=true, ext_tabline=true})
+ screen:attach({ rgb = true, ext_tabline = true })
-- From ":help ui" we find that `tabline_update` receives `curtab` and
-- `tabs` objects. So we declare the UI handler like this:
@@ -60,13 +60,14 @@ describe('example', function()
command('tabedit foo')
-- Use screen:expect{condition=…} to check the result.
- screen:expect{condition=function()
- eq({ id = 2 }, event_curtab)
- eq({
- {tab = { id = 1 }, name = '[No Name]'},
- {tab = { id = 2 }, name = 'foo'},
- },
- event_tabs)
- end}
+ screen:expect {
+ condition = function()
+ eq(2, event_curtab)
+ eq({
+ { tab = 1, name = '[No Name]' },
+ { tab = 2, name = 'foo' },
+ }, event_tabs)
+ end,
+ }
end)
end)
diff --git a/test/functional/fixtures/CMakeLists.txt b/test/functional/fixtures/CMakeLists.txt
index 6e64b1e4dc..150407fe46 100644
--- a/test/functional/fixtures/CMakeLists.txt
+++ b/test/functional/fixtures/CMakeLists.txt
@@ -5,7 +5,7 @@ endif()
if(WIN32)
target_compile_definitions(test_lib INTERFACE MSWIN)
endif()
-target_link_libraries(test_lib INTERFACE nvim)
+target_link_libraries(test_lib INTERFACE nvim_bin)
add_executable(tty-test EXCLUDE_FROM_ALL tty-test.c)
add_executable(shell-test EXCLUDE_FROM_ALL shell-test.c)
diff --git a/test/functional/fixtures/fake-lsp-server.lua b/test/functional/fixtures/fake-lsp-server.lua
index 0db9265a29..d9f44da0b4 100644
--- a/test/functional/fixtures/fake-lsp-server.lua
+++ b/test/functional/fixtures/fake-lsp-server.lua
@@ -1,19 +1,15 @@
local protocol = require 'vim.lsp.protocol'
-
-- Logs to $NVIM_LOG_FILE.
--
-- TODO(justinmk): remove after https://github.com/neovim/neovim/pull/7062
local function log(loglevel, area, msg)
- vim.fn.writefile(
- {string.format('%s %s: %s', loglevel, area, msg)},
- vim.env.NVIM_LOG_FILE,
- 'a')
+ vim.fn.writefile({ string.format('%s %s: %s', loglevel, area, msg) }, vim.env.NVIM_LOG_FILE, 'a')
end
local function message_parts(sep, ...)
local parts = {}
- for i = 1, select("#", ...) do
+ for i = 1, select('#', ...) do
local arg = select(i, ...)
if arg ~= nil then
table.insert(parts, arg)
@@ -26,26 +22,33 @@ end
local function assert_eq(a, b, ...)
if not vim.deep_equal(a, b) then
- error(message_parts(": ",
- ..., "assert_eq failed",
- string.format("left == %q, right == %q",
- table.concat(vim.split(vim.inspect(a), "\n"), ""),
- table.concat(vim.split(vim.inspect(b), "\n"), "")
+ error(
+ message_parts(
+ ': ',
+ ...,
+ 'assert_eq failed',
+ string.format(
+ 'left == %q, right == %q',
+ table.concat(vim.split(vim.inspect(a), '\n'), ''),
+ table.concat(vim.split(vim.inspect(b), '\n'), '')
+ )
)
- ))
+ )
end
end
local function format_message_with_content_length(encoded_message)
return table.concat {
- 'Content-Length: '; tostring(#encoded_message); '\r\n\r\n';
- encoded_message;
+ 'Content-Length: ',
+ tostring(#encoded_message),
+ '\r\n\r\n',
+ encoded_message,
}
end
local function read_message()
- local line = io.read("*l")
- local length = line:lower():match("content%-length:%s*(%d+)")
+ local line = io.read('*l')
+ local length = line:lower():match('content%-length:%s*(%d+)')
return vim.json.decode(io.read(2 + length):sub(2))
end
@@ -54,49 +57,51 @@ local function send(payload)
end
local function respond(id, err, result)
- assert(type(id) == 'number', "id must be a number")
- send { jsonrpc = "2.0"; id = id, error = err, result = result }
+ assert(type(id) == 'number', 'id must be a number')
+ send { jsonrpc = '2.0', id = id, error = err, result = result }
end
local function notify(method, params)
- assert(type(method) == 'string', "method must be a string")
+ assert(type(method) == 'string', 'method must be a string')
send { method = method, params = params or {} }
end
local function expect_notification(method, params, ...)
local message = read_message()
- assert_eq(method, message.method,
- ..., "expect_notification", "method")
+ assert_eq(method, message.method, ..., 'expect_notification', 'method')
if params then
- assert_eq(params, message.params,
- ..., "expect_notification", method, "params")
- assert_eq({jsonrpc = "2.0"; method=method, params=params}, message,
- ..., "expect_notification", "message")
+ assert_eq(params, message.params, ..., 'expect_notification', method, 'params')
+ assert_eq(
+ { jsonrpc = '2.0', method = method, params = params },
+ message,
+ ...,
+ 'expect_notification',
+ 'message'
+ )
end
end
local function expect_request(method, handler, ...)
local req = read_message()
- assert_eq(method, req.method,
- ..., "expect_request", "method")
+ assert_eq(method, req.method, ..., 'expect_request', 'method')
local err, result = handler(req.params)
respond(req.id, err, result)
end
-io.stderr:setvbuf("no")
+io.stderr:setvbuf('no')
local function skeleton(config)
local on_init = assert(config.on_init)
local body = assert(config.body)
- expect_request("initialize", function(params)
+ expect_request('initialize', function(params)
return nil, on_init(params)
end)
- expect_notification("initialized", {})
+ expect_notification('initialized', {})
body()
- expect_request("shutdown", function()
+ expect_request('shutdown', function()
return nil, {}
end)
- expect_notification("exit", nil)
+ expect_notification('exit', nil)
end
-- The actual tests.
@@ -108,13 +113,13 @@ function tests.basic_init()
on_init = function(_)
return {
capabilities = {
- textDocumentSync = protocol.TextDocumentSyncKind.None;
- }
+ textDocumentSync = protocol.TextDocumentSyncKind.None,
+ },
}
- end;
+ end,
body = function()
notify('test')
- end;
+ end,
}
end
@@ -135,89 +140,95 @@ function tests.check_workspace_configuration()
skeleton {
on_init = function(_params)
return { capabilities = {} }
- end;
+ end,
body = function()
notify('start')
- notify('workspace/configuration', { items = {
- { section = "testSetting1" };
- { section = "testSetting2" };
- { section = "test.Setting3" };
- { section = "test.Setting4" };
- } })
- expect_notification('workspace/configuration', { true; false; 'nested'; vim.NIL})
+ notify('workspace/configuration', {
+ items = {
+ { section = 'testSetting1' },
+ { section = 'testSetting2' },
+ { section = 'test.Setting3' },
+ { section = 'test.Setting4' },
+ },
+ })
+ expect_notification('workspace/configuration', { true, false, 'nested', vim.NIL })
notify('shutdown')
- end;
+ end,
}
end
function tests.prepare_rename_nil()
skeleton {
on_init = function()
- return { capabilities = {
- renameProvider = {
- prepareProvider = true
- }
- }
+ return {
+ capabilities = {
+ renameProvider = {
+ prepareProvider = true,
+ },
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_request('textDocument/prepareRename', function()
return nil, nil
end)
notify('shutdown')
- end;
+ end,
}
end
function tests.prepare_rename_placeholder()
skeleton {
on_init = function()
- return { capabilities = {
- renameProvider = {
- prepareProvider = true
- }
- }
+ return {
+ capabilities = {
+ renameProvider = {
+ prepareProvider = true,
+ },
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_request('textDocument/prepareRename', function()
- return nil, {placeholder = 'placeholder'}
+ return nil, { placeholder = 'placeholder' }
end)
expect_request('textDocument/rename', function(params)
assert_eq(params.newName, 'renameto')
return nil, nil
end)
notify('shutdown')
- end;
+ end,
}
end
function tests.prepare_rename_range()
skeleton {
on_init = function()
- return { capabilities = {
- renameProvider = {
- prepareProvider = true
- }
- }
+ return {
+ capabilities = {
+ renameProvider = {
+ prepareProvider = true,
+ },
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_request('textDocument/prepareRename', function()
- return nil, {
- start = { line = 1, character = 8 },
- ['end'] = { line = 1, character = 12 },
- }
+ return nil,
+ {
+ start = { line = 1, character = 8 },
+ ['end'] = { line = 1, character = 12 },
+ }
end)
expect_request('textDocument/rename', function(params)
assert_eq(params.newName, 'renameto')
return nil, nil
end)
notify('shutdown')
- end;
+ end,
}
end
@@ -227,18 +238,18 @@ function tests.prepare_rename_error()
return {
capabilities = {
renameProvider = {
- prepareProvider = true
+ prepareProvider = true,
},
- }
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_request('textDocument/prepareRename', function()
return {}, nil
end)
notify('shutdown')
- end;
+ end,
}
end
@@ -249,13 +260,12 @@ function tests.basic_check_capabilities()
assert_eq(params.capabilities, expected_capabilities)
return {
capabilities = {
- textDocumentSync = protocol.TextDocumentSyncKind.Full;
- codeLensProvider = false
- }
+ textDocumentSync = protocol.TextDocumentSyncKind.Full,
+ codeLensProvider = false,
+ },
}
- end;
- body = function()
- end;
+ end,
+ body = function() end,
}
end
@@ -265,18 +275,18 @@ function tests.text_document_save_did_open()
return {
capabilities = {
textDocumentSync = {
- save = true
- }
- }
+ save = true,
+ },
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_notification('textDocument/didClose')
expect_notification('textDocument/didOpen')
expect_notification('textDocument/didSave')
notify('shutdown')
- end;
+ end,
}
end
@@ -286,16 +296,16 @@ function tests.text_document_sync_save_bool()
return {
capabilities = {
textDocumentSync = {
- save = true
- }
- }
+ save = true,
+ },
+ },
}
- end;
+ end,
body = function()
notify('start')
- expect_notification('textDocument/didSave', {textDocument = { uri = "file://" }})
+ expect_notification('textDocument/didSave', { textDocument = { uri = 'file://' } })
notify('shutdown')
- end;
+ end,
}
end
@@ -306,22 +316,22 @@ function tests.text_document_sync_save_includeText()
capabilities = {
textDocumentSync = {
save = {
- includeText = true
- }
- }
- }
+ includeText = true,
+ },
+ },
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_notification('textDocument/didSave', {
textDocument = {
- uri = "file://"
+ uri = 'file://',
},
- text = "help me\n"
+ text = 'help me\n',
})
notify('shutdown')
- end;
+ end,
}
end
@@ -332,18 +342,17 @@ function tests.capabilities_for_client_supports_method()
assert_eq(params.capabilities, expected_capabilities)
return {
capabilities = {
- textDocumentSync = protocol.TextDocumentSyncKind.Full;
- completionProvider = true;
- hoverProvider = true;
- renameProvider = false;
- definitionProvider = false;
- referencesProvider = false;
- codeLensProvider = { resolveProvider = true; };
- }
+ textDocumentSync = protocol.TextDocumentSyncKind.Full,
+ completionProvider = true,
+ hoverProvider = true,
+ renameProvider = false,
+ definitionProvider = false,
+ referencesProvider = false,
+ codeLensProvider = { resolveProvider = true },
+ },
}
- end;
- body = function()
- end;
+ end,
+ body = function() end,
}
end
@@ -351,13 +360,13 @@ function tests.check_forward_request_cancelled()
skeleton {
on_init = function(_)
return { capabilities = {} }
- end;
+ end,
body = function()
- expect_request("error_code_test", function()
- return {code = -32800}, nil, {method = "error_code_test", client_id=1}
+ expect_request('error_code_test', function()
+ return { code = -32800 }, nil, { method = 'error_code_test', client_id = 1 }
end)
notify('finish')
- end;
+ end,
}
end
@@ -365,14 +374,14 @@ function tests.check_forward_content_modified()
skeleton {
on_init = function(_)
return { capabilities = {} }
- end;
+ end,
body = function()
- expect_request("error_code_test", function()
- return {code = -32801}, nil, {method = "error_code_test", client_id=1}
+ expect_request('error_code_test', function()
+ return { code = -32801 }, nil, { method = 'error_code_test', client_id = 1 }
end)
expect_notification('finish')
notify('finish')
- end;
+ end,
}
end
@@ -380,15 +389,15 @@ function tests.check_pending_request_tracked()
skeleton {
on_init = function(_)
return { capabilities = {} }
- end;
+ end,
body = function()
- local msg = read_message()
- assert_eq('slow_request', msg.method)
- expect_notification('release')
- respond(msg.id, nil, {})
- expect_notification('finish')
- notify('finish')
- end;
+ local msg = read_message()
+ assert_eq('slow_request', msg.method)
+ expect_notification('release')
+ respond(msg.id, nil, {})
+ expect_notification('finish')
+ notify('finish')
+ end,
}
end
@@ -396,15 +405,15 @@ function tests.check_cancel_request_tracked()
skeleton {
on_init = function(_)
return { capabilities = {} }
- end;
+ end,
body = function()
- local msg = read_message()
- assert_eq('slow_request', msg.method)
- expect_notification('$/cancelRequest', {id=msg.id})
- expect_notification('release')
- respond(msg.id, {code = -32800}, nil)
- notify('finish')
- end;
+ local msg = read_message()
+ assert_eq('slow_request', msg.method)
+ expect_notification('$/cancelRequest', { id = msg.id })
+ expect_notification('release')
+ respond(msg.id, { code = -32800 }, nil)
+ notify('finish')
+ end,
}
end
@@ -412,16 +421,16 @@ function tests.check_tracked_requests_cleared()
skeleton {
on_init = function(_)
return { capabilities = {} }
- end;
+ end,
body = function()
- local msg = read_message()
- assert_eq('slow_request', msg.method)
- expect_notification('$/cancelRequest', {id=msg.id})
- expect_notification('release')
- respond(msg.id, nil, {})
- expect_notification('finish')
- notify('finish')
- end;
+ local msg = read_message()
+ assert_eq('slow_request', msg.method)
+ expect_notification('$/cancelRequest', { id = msg.id })
+ expect_notification('release')
+ respond(msg.id, nil, {})
+ expect_notification('finish')
+ notify('finish')
+ end,
}
end
@@ -432,14 +441,14 @@ function tests.basic_finish()
assert_eq(params.capabilities, expected_capabilities)
return {
capabilities = {
- textDocumentSync = protocol.TextDocumentSyncKind.Full;
- }
+ textDocumentSync = protocol.TextDocumentSyncKind.Full,
+ },
}
- end;
+ end,
body = function()
- expect_notification("finish")
+ expect_notification('finish')
notify('finish')
- end;
+ end,
}
end
@@ -450,23 +459,23 @@ function tests.basic_check_buffer_open()
assert_eq(params.capabilities, expected_capabilities)
return {
capabilities = {
- textDocumentSync = protocol.TextDocumentSyncKind.Full;
- }
+ textDocumentSync = protocol.TextDocumentSyncKind.Full,
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_notification('textDocument/didOpen', {
textDocument = {
- languageId = "";
- text = table.concat({"testing"; "123"}, "\n") .. '\n';
- uri = "file://";
- version = 0;
- };
+ languageId = '',
+ text = table.concat({ 'testing', '123' }, '\n') .. '\n',
+ uri = 'file://',
+ version = 0,
+ },
})
- expect_notification("finish")
+ expect_notification('finish')
notify('finish')
- end;
+ end,
}
end
@@ -477,32 +486,32 @@ function tests.basic_check_buffer_open_and_change()
assert_eq(params.capabilities, expected_capabilities)
return {
capabilities = {
- textDocumentSync = protocol.TextDocumentSyncKind.Full;
- }
+ textDocumentSync = protocol.TextDocumentSyncKind.Full,
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_notification('textDocument/didOpen', {
textDocument = {
- languageId = "";
- text = table.concat({"testing"; "123"}, "\n") .. '\n';
- uri = "file://";
- version = 0;
- };
+ languageId = '',
+ text = table.concat({ 'testing', '123' }, '\n') .. '\n',
+ uri = 'file://',
+ version = 0,
+ },
})
expect_notification('textDocument/didChange', {
textDocument = {
- uri = "file://";
- version = 3;
- };
+ uri = 'file://',
+ version = 3,
+ },
contentChanges = {
- { text = table.concat({"testing"; "boop"}, "\n") .. '\n'; };
- }
+ { text = table.concat({ 'testing', 'boop' }, '\n') .. '\n' },
+ },
})
- expect_notification("finish")
+ expect_notification('finish')
notify('finish')
- end;
+ end,
}
end
@@ -513,32 +522,32 @@ function tests.basic_check_buffer_open_and_change_noeol()
assert_eq(params.capabilities, expected_capabilities)
return {
capabilities = {
- textDocumentSync = protocol.TextDocumentSyncKind.Full;
- }
+ textDocumentSync = protocol.TextDocumentSyncKind.Full,
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_notification('textDocument/didOpen', {
textDocument = {
- languageId = "";
- text = table.concat({"testing"; "123"}, "\n");
- uri = "file://";
- version = 0;
- };
+ languageId = '',
+ text = table.concat({ 'testing', '123' }, '\n'),
+ uri = 'file://',
+ version = 0,
+ },
})
expect_notification('textDocument/didChange', {
textDocument = {
- uri = "file://";
- version = 3;
- };
+ uri = 'file://',
+ version = 3,
+ },
contentChanges = {
- { text = table.concat({"testing"; "boop"}, "\n"); };
- }
+ { text = table.concat({ 'testing', 'boop' }, '\n') },
+ },
})
- expect_notification("finish")
+ expect_notification('finish')
notify('finish')
- end;
+ end,
}
end
function tests.basic_check_buffer_open_and_change_multi()
@@ -548,41 +557,41 @@ function tests.basic_check_buffer_open_and_change_multi()
assert_eq(params.capabilities, expected_capabilities)
return {
capabilities = {
- textDocumentSync = protocol.TextDocumentSyncKind.Full;
- }
+ textDocumentSync = protocol.TextDocumentSyncKind.Full,
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_notification('textDocument/didOpen', {
textDocument = {
- languageId = "";
- text = table.concat({"testing"; "123"}, "\n") .. '\n';
- uri = "file://";
- version = 0;
- };
+ languageId = '',
+ text = table.concat({ 'testing', '123' }, '\n') .. '\n',
+ uri = 'file://',
+ version = 0,
+ },
})
expect_notification('textDocument/didChange', {
textDocument = {
- uri = "file://";
- version = 3;
- };
+ uri = 'file://',
+ version = 3,
+ },
contentChanges = {
- { text = table.concat({"testing"; "321"}, "\n") .. '\n'; };
- }
+ { text = table.concat({ 'testing', '321' }, '\n') .. '\n' },
+ },
})
expect_notification('textDocument/didChange', {
textDocument = {
- uri = "file://";
- version = 4;
- };
+ uri = 'file://',
+ version = 4,
+ },
contentChanges = {
- { text = table.concat({"testing"; "boop"}, "\n") .. '\n'; };
- }
+ { text = table.concat({ 'testing', 'boop' }, '\n') .. '\n' },
+ },
})
- expect_notification("finish")
+ expect_notification('finish')
notify('finish')
- end;
+ end,
}
end
@@ -593,46 +602,46 @@ function tests.basic_check_buffer_open_and_change_multi_and_close()
assert_eq(params.capabilities, expected_capabilities)
return {
capabilities = {
- textDocumentSync = protocol.TextDocumentSyncKind.Full;
- }
+ textDocumentSync = protocol.TextDocumentSyncKind.Full,
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_notification('textDocument/didOpen', {
textDocument = {
- languageId = "";
- text = table.concat({"testing"; "123"}, "\n") .. '\n';
- uri = "file://";
- version = 0;
- };
+ languageId = '',
+ text = table.concat({ 'testing', '123' }, '\n') .. '\n',
+ uri = 'file://',
+ version = 0,
+ },
})
expect_notification('textDocument/didChange', {
textDocument = {
- uri = "file://";
- version = 3;
- };
+ uri = 'file://',
+ version = 3,
+ },
contentChanges = {
- { text = table.concat({"testing"; "321"}, "\n") .. '\n'; };
- }
+ { text = table.concat({ 'testing', '321' }, '\n') .. '\n' },
+ },
})
expect_notification('textDocument/didChange', {
textDocument = {
- uri = "file://";
- version = 4;
- };
+ uri = 'file://',
+ version = 4,
+ },
contentChanges = {
- { text = table.concat({"testing"; "boop"}, "\n") .. '\n'; };
- }
+ { text = table.concat({ 'testing', 'boop' }, '\n') .. '\n' },
+ },
})
expect_notification('textDocument/didClose', {
textDocument = {
- uri = "file://";
- };
+ uri = 'file://',
+ },
})
- expect_notification("finish")
+ expect_notification('finish')
notify('finish')
- end;
+ end,
}
end
@@ -650,40 +659,40 @@ function tests.basic_check_buffer_open_and_change_incremental()
willSaveWaitUntil = true,
save = {
includeText = true,
- }
- }
- }
+ },
+ },
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_notification('textDocument/didOpen', {
textDocument = {
- languageId = "";
- text = table.concat({"testing"; "123"}, "\n") .. '\n';
- uri = "file://";
- version = 0;
- };
+ languageId = '',
+ text = table.concat({ 'testing', '123' }, '\n') .. '\n',
+ uri = 'file://',
+ version = 0,
+ },
})
expect_notification('textDocument/didChange', {
textDocument = {
- uri = "file://";
- version = 3;
- };
+ uri = 'file://',
+ version = 3,
+ },
contentChanges = {
{
range = {
- start = { line = 1; character = 3; };
- ["end"] = { line = 1; character = 3; };
- };
- rangeLength = 0;
- text = "boop";
- };
- }
+ start = { line = 1, character = 3 },
+ ['end'] = { line = 1, character = 3 },
+ },
+ rangeLength = 0,
+ text = 'boop',
+ },
+ },
})
- expect_notification("finish")
+ expect_notification('finish')
notify('finish')
- end;
+ end,
}
end
@@ -694,89 +703,88 @@ function tests.basic_check_buffer_open_and_change_incremental_editing()
assert_eq(params.capabilities, expected_capabilities)
return {
capabilities = {
- textDocumentSync = protocol.TextDocumentSyncKind.Incremental;
- }
+ textDocumentSync = protocol.TextDocumentSyncKind.Incremental,
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_notification('textDocument/didOpen', {
textDocument = {
- languageId = "";
- text = table.concat({"testing"; "123"}, "\n");
- uri = "file://";
- version = 0;
- };
+ languageId = '',
+ text = table.concat({ 'testing', '123' }, '\n'),
+ uri = 'file://',
+ version = 0,
+ },
})
expect_notification('textDocument/didChange', {
textDocument = {
- uri = "file://";
- version = 3;
- };
+ uri = 'file://',
+ version = 3,
+ },
contentChanges = {
{
range = {
- start = { line = 0; character = 0; };
- ["end"] = { line = 1; character = 0; };
- };
- rangeLength = 4;
- text = "testing\n\n";
- };
- }
+ start = { line = 0, character = 0 },
+ ['end'] = { line = 1, character = 0 },
+ },
+ rangeLength = 4,
+ text = 'testing\n\n',
+ },
+ },
})
- expect_notification("finish")
+ expect_notification('finish')
notify('finish')
- end;
+ end,
}
end
function tests.invalid_header()
- io.stdout:write("Content-length: \r\n")
+ io.stdout:write('Content-length: \r\n')
end
function tests.decode_nil()
skeleton {
on_init = function(_)
return { capabilities = {} }
- end;
+ end,
body = function()
notify('start')
- notify("workspace/executeCommand", {
- arguments = { "EXTRACT_METHOD", {metadata = {field = vim.NIL}}, 3, 0, 6123, vim.NIL },
- command = "refactor.perform",
- title = "EXTRACT_METHOD"
+ notify('workspace/executeCommand', {
+ arguments = { 'EXTRACT_METHOD', { metadata = { field = vim.NIL } }, 3, 0, 6123, vim.NIL },
+ command = 'refactor.perform',
+ title = 'EXTRACT_METHOD',
})
notify('finish')
- end;
+ end,
}
end
-
function tests.code_action_with_resolve()
skeleton {
on_init = function()
return {
capabilities = {
codeActionProvider = {
- resolveProvider = true
- }
- }
+ resolveProvider = true,
+ },
+ },
}
- end;
+ end,
body = function()
notify('start')
local cmd = {
title = 'Command 1',
- command = 'dummy1'
+ command = 'dummy1',
}
expect_request('textDocument/codeAction', function()
- return nil, { cmd, }
+ return nil, { cmd }
end)
expect_request('codeAction/resolve', function()
return nil, cmd
end)
notify('shutdown')
- end;
+ end,
}
end
@@ -789,7 +797,7 @@ function tests.code_action_server_side_command()
resolveProvider = false,
},
executeCommandProvider = {
- commands = {"dummy1"}
+ commands = { 'dummy1' },
},
},
}
@@ -811,23 +819,22 @@ function tests.code_action_server_side_command()
})
end
-
function tests.code_action_filter()
skeleton {
on_init = function()
return {
capabilities = {
codeActionProvider = {
- resolveProvider = false
- }
- }
+ resolveProvider = false,
+ },
+ },
}
- end;
+ end,
body = function()
notify('start')
local action = {
title = 'Action 1',
- command = 'command'
+ command = 'command',
}
local preferred_action = {
title = 'Action 2',
@@ -845,13 +852,13 @@ function tests.code_action_filter()
command = 'type_annotate_foo_command',
}
expect_request('textDocument/codeAction', function()
- return nil, { action, preferred_action, type_annotate_action, type_annotate_foo_action, }
+ return nil, { action, preferred_action, type_annotate_action, type_annotate_foo_action }
end)
expect_request('textDocument/codeAction', function()
- return nil, { action, preferred_action, type_annotate_action, type_annotate_foo_action, }
+ return nil, { action, preferred_action, type_annotate_action, type_annotate_foo_action }
end)
notify('shutdown')
- end;
+ end,
}
end
@@ -859,13 +866,13 @@ function tests.clientside_commands()
skeleton {
on_init = function()
return {
- capabilities = {}
+ capabilities = {},
}
- end;
+ end,
body = function()
notify('start')
notify('shutdown')
- end;
+ end,
}
end
@@ -874,41 +881,41 @@ function tests.codelens_refresh_lock()
on_init = function()
return {
capabilities = {
- codeLensProvider = { resolveProvider = true; };
- }
+ codeLensProvider = { resolveProvider = true },
+ },
}
- end;
+ end,
body = function()
notify('start')
- expect_request("textDocument/codeLens", function ()
- return {code = -32002, message = "ServerNotInitialized"}, nil
+ expect_request('textDocument/codeLens', function()
+ return { code = -32002, message = 'ServerNotInitialized' }, nil
end)
- expect_request("textDocument/codeLens", function ()
+ expect_request('textDocument/codeLens', function()
local lenses = {
{
range = {
- start = { line = 0, character = 0, },
- ['end'] = { line = 0, character = 3 }
+ start = { line = 0, character = 0 },
+ ['end'] = { line = 0, character = 3 },
},
- command = { title = 'Lens1', command = 'Dummy' }
+ command = { title = 'Lens1', command = 'Dummy' },
},
}
return nil, lenses
end)
- expect_request("textDocument/codeLens", function ()
+ expect_request('textDocument/codeLens', function()
local lenses = {
{
range = {
- start = { line = 0, character = 0, },
- ['end'] = { line = 0, character = 3 }
+ start = { line = 0, character = 0 },
+ ['end'] = { line = 0, character = 3 },
},
- command = { title = 'Lens2', command = 'Dummy' }
+ command = { title = 'Lens2', command = 'Dummy' },
},
}
return nil, lenses
end)
notify('shutdown')
- end;
+ end,
}
end
@@ -918,16 +925,16 @@ function tests.basic_formatting()
return {
capabilities = {
documentFormattingProvider = true,
- }
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_request('textDocument/formatting', function()
return nil, {}
end)
notify('shutdown')
- end;
+ end,
}
end
@@ -940,12 +947,12 @@ function tests.set_defaults_all_capabilities()
completionProvider = true,
documentRangeFormattingProvider = true,
hoverProvider = true,
- }
+ },
}
- end;
+ end,
body = function()
notify('test')
- end;
+ end,
}
end
@@ -956,18 +963,18 @@ function tests.inlay_hint()
assert_eq(params.capabilities, expected_capabilities)
return {
capabilities = {
- inlayHintProvider = true;
- }
+ inlayHintProvider = true,
+ },
}
- end;
+ end,
body = function()
notify('start')
expect_request('textDocument/inlayHint', function()
return nil, {}
end)
- expect_notification("finish")
+ expect_notification('finish')
notify('finish')
- end;
+ end,
}
end
@@ -981,11 +988,11 @@ kill_timer:start(timeout or 1e3, 0, function()
kill_timer:stop()
kill_timer:close()
log('ERROR', 'LSP', 'TIMEOUT')
- io.stderr:write("TIMEOUT")
+ io.stderr:write('TIMEOUT')
os.exit(100)
end)
-local status, err = pcall(assert(tests[test_name], "Test not found"))
+local status, err = pcall(assert(tests[test_name], 'Test not found'))
kill_timer:stop()
kill_timer:close()
if not status then
diff --git a/test/functional/fixtures/middle/filen.lua b/test/functional/fixtures/middle/filen.lua
index fce50cc776..24ccb200de 100644
--- a/test/functional/fixtures/middle/filen.lua
+++ b/test/functional/fixtures/middle/filen.lua
@@ -1 +1 @@
-table.insert(_G.test_loadorder, "mittel")
+table.insert(_G.test_loadorder, 'mittel')
diff --git a/test/functional/fixtures/nvim/after/filen.lua b/test/functional/fixtures/nvim/after/filen.lua
index 0128a0a16a..13f0cfc6b9 100644
--- a/test/functional/fixtures/nvim/after/filen.lua
+++ b/test/functional/fixtures/nvim/after/filen.lua
@@ -1 +1 @@
-table.insert(_G.test_loadorder, "ordinary after")
+table.insert(_G.test_loadorder, 'ordinary after')
diff --git a/test/functional/fixtures/nvim/filen.lua b/test/functional/fixtures/nvim/filen.lua
index e2bd5e8f7f..914e551c96 100644
--- a/test/functional/fixtures/nvim/filen.lua
+++ b/test/functional/fixtures/nvim/filen.lua
@@ -1 +1 @@
-table.insert(_G.test_loadorder, "ordinary")
+table.insert(_G.test_loadorder, 'ordinary')
diff --git a/test/functional/fixtures/pack/foo/opt/bonus/lua/bonus.lua b/test/functional/fixtures/pack/foo/opt/bonus/lua/bonus.lua
index 52cb0bc118..2ceec737fd 100644
--- a/test/functional/fixtures/pack/foo/opt/bonus/lua/bonus.lua
+++ b/test/functional/fixtures/pack/foo/opt/bonus/lua/bonus.lua
@@ -1 +1,5 @@
-return {launch=function() return "CPE 1704 TKS" end}
+return {
+ launch = function()
+ return 'CPE 1704 TKS'
+ end,
+}
diff --git a/test/functional/fixtures/pack/foo/opt/funky/filen.lua b/test/functional/fixtures/pack/foo/opt/funky/filen.lua
index a33b83c2a7..de0a754f6c 100644
--- a/test/functional/fixtures/pack/foo/opt/funky/filen.lua
+++ b/test/functional/fixtures/pack/foo/opt/funky/filen.lua
@@ -1,10 +1,10 @@
-table.insert(_G.test_loadorder, "funky!")
+table.insert(_G.test_loadorder, 'funky!')
if not _G.nesty then
_G.nesty = true
local save_order = _G.test_loadorder
_G.test_loadorder = {}
- _G.vim.o.pp = "" -- funky!
+ _G.vim.o.pp = '' -- funky!
vim.cmd [[runtime! filen.lua ]]
_G.nested_order = _G.test_loadorder
_G.test_loadorder = save_order
diff --git a/test/functional/fixtures/pack/foo/opt/superspecial/after/filen.lua b/test/functional/fixtures/pack/foo/opt/superspecial/after/filen.lua
index 94bf6850b2..c906250fc9 100644
--- a/test/functional/fixtures/pack/foo/opt/superspecial/after/filen.lua
+++ b/test/functional/fixtures/pack/foo/opt/superspecial/after/filen.lua
@@ -1 +1 @@
-table.insert(_G.test_loadorder, "SuperSpecial after")
+table.insert(_G.test_loadorder, 'SuperSpecial after')
diff --git a/test/functional/fixtures/pack/foo/opt/superspecial/filen.lua b/test/functional/fixtures/pack/foo/opt/superspecial/filen.lua
index cbaab1a45a..0dcd7f90d5 100644
--- a/test/functional/fixtures/pack/foo/opt/superspecial/filen.lua
+++ b/test/functional/fixtures/pack/foo/opt/superspecial/filen.lua
@@ -1 +1 @@
-table.insert(_G.test_loadorder, "SuperSpecial")
+table.insert(_G.test_loadorder, 'SuperSpecial')
diff --git a/test/functional/fixtures/pack/foo/start/bar/lua/bar.lua b/test/functional/fixtures/pack/foo/start/bar/lua/bar.lua
index a7e9a61e35..1413376e02 100644
--- a/test/functional/fixtures/pack/foo/start/bar/lua/bar.lua
+++ b/test/functional/fixtures/pack/foo/start/bar/lua/bar.lua
@@ -1 +1,5 @@
-return {doit=function() return 9003 end}
+return {
+ doit = function()
+ return 9003
+ end,
+}
diff --git a/test/functional/fixtures/pack/foo/start/bar/lua/baz-quux.lua b/test/functional/fixtures/pack/foo/start/bar/lua/baz-quux.lua
index c1c33d787e..c4677adcaf 100644
--- a/test/functional/fixtures/pack/foo/start/bar/lua/baz-quux.lua
+++ b/test/functional/fixtures/pack/foo/start/bar/lua/baz-quux.lua
@@ -1 +1,5 @@
-return {doit=function() return 9004 end}
+return {
+ doit = function()
+ return 9004
+ end,
+}
diff --git a/test/functional/fixtures/pack/foo/start/fancyplugin/after/filen.lua b/test/functional/fixtures/pack/foo/start/fancyplugin/after/filen.lua
index 9beac762ee..bfd837d703 100644
--- a/test/functional/fixtures/pack/foo/start/fancyplugin/after/filen.lua
+++ b/test/functional/fixtures/pack/foo/start/fancyplugin/after/filen.lua
@@ -1 +1 @@
-table.insert(_G.test_loadorder, "FANCY after")
+table.insert(_G.test_loadorder, 'FANCY after')
diff --git a/test/functional/fixtures/pack/foo/start/fancyplugin/after/lua/fancy_y.lua b/test/functional/fixtures/pack/foo/start/fancyplugin/after/lua/fancy_y.lua
index 7daa7733a0..a11d74597c 100644
--- a/test/functional/fixtures/pack/foo/start/fancyplugin/after/lua/fancy_y.lua
+++ b/test/functional/fixtures/pack/foo/start/fancyplugin/after/lua/fancy_y.lua
@@ -1 +1 @@
-return "I am fancy_y.lua"
+return 'I am fancy_y.lua'
diff --git a/test/functional/fixtures/pack/foo/start/fancyplugin/after/lua/fancy_z.lua b/test/functional/fixtures/pack/foo/start/fancyplugin/after/lua/fancy_z.lua
index 6e81afdd70..f360731c79 100644
--- a/test/functional/fixtures/pack/foo/start/fancyplugin/after/lua/fancy_z.lua
+++ b/test/functional/fixtures/pack/foo/start/fancyplugin/after/lua/fancy_z.lua
@@ -1 +1 @@
-return "I am fancy_z.lua"
+return 'I am fancy_z.lua'
diff --git a/test/functional/fixtures/pack/foo/start/fancyplugin/filen.lua b/test/functional/fixtures/pack/foo/start/fancyplugin/filen.lua
index 34e4b9c95e..b354c5d8cd 100644
--- a/test/functional/fixtures/pack/foo/start/fancyplugin/filen.lua
+++ b/test/functional/fixtures/pack/foo/start/fancyplugin/filen.lua
@@ -1 +1 @@
-table.insert(_G.test_loadorder, "FANCY")
+table.insert(_G.test_loadorder, 'FANCY')
diff --git a/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_x.lua b/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_x.lua
index 1b897a96cc..d96270f01e 100644
--- a/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_x.lua
+++ b/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_x.lua
@@ -1 +1 @@
-return "I am fancy_x.lua"
+return 'I am fancy_x.lua'
diff --git a/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_x/init.lua b/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_x/init.lua
index 8c27a43cab..83874e194c 100644
--- a/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_x/init.lua
+++ b/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_x/init.lua
@@ -1 +1 @@
-return "I am init.lua of fancy_x!"
+return 'I am init.lua of fancy_x!'
diff --git a/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_y/init.lua b/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_y/init.lua
index b66cbee4f6..a2dd2a9df0 100644
--- a/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_y/init.lua
+++ b/test/functional/fixtures/pack/foo/start/fancyplugin/lua/fancy_y/init.lua
@@ -1,2 +1 @@
-
-return "I am init.lua of fancy_y!"
+return 'I am init.lua of fancy_y!'
diff --git a/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua b/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua
index ffbd8a4f83..ee116d761a 100644
--- a/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua
+++ b/test/functional/fixtures/start/nvim-leftpad/lua/async_leftpad.lua
@@ -1,5 +1,8 @@
-return function (val, res)
+return function(val, res)
local handle
- handle = vim.uv.new_async(function() _G[res] = require'leftpad'(val) handle:close() end)
+ handle = vim.uv.new_async(function()
+ _G[res] = require 'leftpad'(val)
+ handle:close()
+ end)
handle:send()
end
diff --git a/test/functional/fixtures/start/nvim-leftpad/lua/leftpad.lua b/test/functional/fixtures/start/nvim-leftpad/lua/leftpad.lua
index 866ed2fd30..5deb505624 100644
--- a/test/functional/fixtures/start/nvim-leftpad/lua/leftpad.lua
+++ b/test/functional/fixtures/start/nvim-leftpad/lua/leftpad.lua
@@ -1 +1,3 @@
-return function (str) return '\t' .. str end
+return function(str)
+ return '\t' .. str
+end
diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua
index dcaaa664b9..d1d26919a0 100644
--- a/test/functional/helpers.lua
+++ b/test/functional/helpers.lua
@@ -1,4 +1,4 @@
-local luv = require('luv')
+local uv = vim.uv
local global_helpers = require('test.helpers')
local Session = require('test.client.session')
@@ -10,65 +10,76 @@ local check_cores = global_helpers.check_cores
local check_logs = global_helpers.check_logs
local dedent = global_helpers.dedent
local eq = global_helpers.eq
-local filter = global_helpers.tbl_filter
local is_os = global_helpers.is_os
-local map = global_helpers.tbl_map
local ok = global_helpers.ok
-local sleep = global_helpers.sleep
-local tbl_contains = global_helpers.tbl_contains
+local sleep = uv.sleep
local fail = global_helpers.fail
local module = {}
-local start_dir = luv.cwd()
local runtime_set = 'set runtimepath^=./build/lib/nvim/'
-module.nvim_prog = (
- os.getenv('NVIM_PRG')
- or global_helpers.test_build_dir .. '/bin/nvim'
-)
+module.nvim_prog = (os.getenv('NVIM_PRG') or global_helpers.paths.test_build_dir .. '/bin/nvim')
-- Default settings for the test session.
module.nvim_set = (
- 'set shortmess+=IS background=light noswapfile noautoindent startofline'
- ..' laststatus=1 undodir=. directory=. viewdir=. backupdir=.'
- ..' belloff= wildoptions-=pum joinspaces noshowcmd noruler nomore redrawdebug=invalid')
+ 'set shortmess+=IS background=light termguicolors noswapfile noautoindent startofline'
+ .. ' laststatus=1 undodir=. directory=. viewdir=. backupdir=.'
+ .. ' belloff= wildoptions-=pum joinspaces noshowcmd noruler nomore redrawdebug=invalid'
+)
module.nvim_argv = {
- module.nvim_prog, '-u', 'NONE', '-i', 'NONE',
+ module.nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
-- XXX: find treesitter parsers.
- '--cmd', runtime_set,
- '--cmd', module.nvim_set,
- '--cmd', 'mapclear',
- '--cmd', 'mapclear!',
- '--embed'}
+ '--cmd',
+ runtime_set,
+ '--cmd',
+ module.nvim_set,
+ -- Remove default mappings.
+ '--cmd',
+ 'mapclear | mapclear!',
+ -- Make screentest work after changing to the new default color scheme
+ -- Source 'vim' color scheme without side effects
+ -- TODO: rewrite tests
+ '--cmd',
+ 'lua dofile("runtime/colors/vim.lua")',
+ '--cmd',
+ 'unlet g:colors_name',
+ '--embed',
+}
-- Directory containing nvim.
-module.nvim_dir = module.nvim_prog:gsub("[/\\][^/\\]+$", "")
+module.nvim_dir = module.nvim_prog:gsub('[/\\][^/\\]+$', '')
if module.nvim_dir == module.nvim_prog then
- module.nvim_dir = "."
+ module.nvim_dir = '.'
end
-local prepend_argv
+local prepend_argv --- @type string[]?
if os.getenv('VALGRIND') then
local log_file = os.getenv('VALGRIND_LOG') or 'valgrind-%p.log'
- prepend_argv = {'valgrind', '-q', '--tool=memcheck',
- '--leak-check=yes', '--track-origins=yes',
- '--show-possibly-lost=no',
- '--suppressions=src/.valgrind.supp',
- '--log-file='..log_file}
+ prepend_argv = {
+ 'valgrind',
+ '-q',
+ '--tool=memcheck',
+ '--leak-check=yes',
+ '--track-origins=yes',
+ '--show-possibly-lost=no',
+ '--suppressions=src/.valgrind.supp',
+ '--log-file=' .. log_file,
+ }
if os.getenv('GDB') then
table.insert(prepend_argv, '--vgdb=yes')
table.insert(prepend_argv, '--vgdb-error=0')
end
elseif os.getenv('GDB') then
- local gdbserver_port = '7777'
- if os.getenv('GDBSERVER_PORT') then
- gdbserver_port = os.getenv('GDBSERVER_PORT')
- end
- prepend_argv = {'gdbserver', 'localhost:'..gdbserver_port}
+ local gdbserver_port = os.getenv('GDBSERVER_PORT') or '7777'
+ prepend_argv = { 'gdbserver', 'localhost:' .. gdbserver_port }
end
if prepend_argv then
- local new_nvim_argv = {}
+ local new_nvim_argv = {} --- @type string[]
local len = #prepend_argv
for i = 1, len do
new_nvim_argv[i] = prepend_argv[i]
@@ -80,12 +91,15 @@ if prepend_argv then
module.prepend_argv = prepend_argv
end
-local session, loop_running, last_error, method_error
+local session --- @type test.Session?
+local loop_running --- @type boolean?
+local last_error --- @type string?
+local method_error --- @type string?
if not is_os('win') then
- local sigpipe_handler = luv.new_signal()
- luv.signal_start(sigpipe_handler, "sigpipe", function()
- print("warning: got SIGPIPE signal. Likely related to a crash in nvim")
+ local sigpipe_handler = assert(uv.new_signal())
+ uv.signal_start(sigpipe_handler, 'sigpipe', function()
+ print('warning: got SIGPIPE signal. Likely related to a crash in nvim')
end)
end
@@ -97,10 +111,15 @@ function module.set_session(s)
session = s
end
+--- @param method string
+--- @param ... any
+--- @return any
function module.request(method, ...)
+ assert(session)
local status, rv = session:request(method, ...)
if not status then
if loop_running then
+ --- @type string
last_error = rv[2]
session:stop()
else
@@ -110,12 +129,18 @@ function module.request(method, ...)
return rv
end
+--- @param method string
+--- @param ... any
+--- @return any
function module.request_lua(method, ...)
return module.exec_lua([[return vim.api[...](select(2, ...))]], method, ...)
end
+--- @param timeout? integer
+--- @return string?
function module.next_msg(timeout)
- return session:next_message(timeout and timeout or 10000)
+ assert(session)
+ return session:next_message(timeout or 10000)
end
function module.expect_twostreams(msgs1, msgs2)
@@ -149,15 +174,16 @@ function module.expect_msg_seq(...)
error('need at least 1 argument')
end
local arg1 = select(1, ...)
- if (arg1['seqs'] and select('#', ...) > 1) or type(arg1) ~= 'table' then
+ if (arg1['seqs'] and select('#', ...) > 1) or type(arg1) ~= 'table' then
error('invalid args')
end
local ignore = arg1['ignore'] and arg1['ignore'] or {}
- local seqs = arg1['seqs'] and arg1['seqs'] or {...}
+ --- @type string[]
+ local seqs = arg1['seqs'] and arg1['seqs'] or { ... }
if type(ignore) ~= 'table' then
error("'ignore' arg must be a list of strings")
end
- table.sort(seqs, function(a, b) -- Sort ascending, by (shallow) length.
+ table.sort(seqs, function(a, b) -- Sort ascending, by (shallow) length.
return #a < #b
end)
@@ -170,7 +196,7 @@ function module.expect_msg_seq(...)
end
return string.format('%s\n%s\n%s', err1, string.rep('=', 78), err2)
end
- local msg_timeout = module.load_adjust(10000) -- Big timeout for ASAN/valgrind.
+ local msg_timeout = module.load_adjust(10000) -- Big timeout for ASAN/valgrind.
for anum = 1, #seqs do
local expected_seq = seqs[anum]
-- Collect enough messages to compare the next expected sequence.
@@ -178,10 +204,18 @@ function module.expect_msg_seq(...)
local msg = module.next_msg(msg_timeout)
local msg_type = msg and msg[2] or nil
if msg == nil then
- error(cat_err(final_error,
- string.format('got %d messages (ignored %d), expected %d',
- #actual_seq, nr_ignored, #expected_seq)))
- elseif tbl_contains(ignore, msg_type) then
+ error(
+ cat_err(
+ final_error,
+ string.format(
+ 'got %d messages (ignored %d), expected %d',
+ #actual_seq,
+ nr_ignored,
+ #expected_seq
+ )
+ )
+ )
+ elseif vim.tbl_contains(ignore, msg_type) then
nr_ignored = nr_ignored + 1
else
table.insert(actual_seq, msg)
@@ -192,8 +226,9 @@ function module.expect_msg_seq(...)
return result
end
local message = result
- if type(result) == "table" then
+ if type(result) == 'table' then
-- 'eq' returns several things
+ --- @type string
message = result.message
end
final_error = cat_err(final_error, message)
@@ -202,7 +237,7 @@ function module.expect_msg_seq(...)
end
local function call_and_stop_on_error(lsession, ...)
- local status, result = Session.safe_pcall(...) -- luacheck: ignore
+ local status, result = Session.safe_pcall(...) -- luacheck: ignore
if not status then
lsession:stop()
last_error = result
@@ -215,8 +250,16 @@ function module.set_method_error(err)
method_error = err
end
+--- @param lsession test.Session
+--- @param request_cb function?
+--- @param notification_cb function?
+--- @param setup_cb function?
+--- @param timeout integer
+--- @return {[1]: integer, [2]: string}
function module.run_session(lsession, request_cb, notification_cb, setup_cb, timeout)
- local on_request, on_notification, on_setup
+ local on_request --- @type function?
+ local on_notification --- @type function?
+ local on_setup --- @type function?
if request_cb then
function on_request(method, args)
@@ -254,29 +297,24 @@ function module.run_session(lsession, request_cb, notification_cb, setup_cb, tim
end
function module.run(request_cb, notification_cb, setup_cb, timeout)
+ assert(session)
return module.run_session(session, request_cb, notification_cb, setup_cb, timeout)
end
function module.stop()
- session:stop()
+ assert(session):stop()
end
function module.nvim_prog_abs()
-- system(['build/bin/nvim']) does not work for whatever reason. It must
-- be executable searched in $PATH or something starting with / or ./.
if module.nvim_prog:match('[/\\]') then
- return module.request('nvim_call_function', 'fnamemodify', {module.nvim_prog, ':p'})
+ return module.request('nvim_call_function', 'fnamemodify', { module.nvim_prog, ':p' })
else
return module.nvim_prog
end
end
--- Executes an ex-command. Vimscript errors manifest as client (lua) errors, but
--- v:errmsg will not be updated.
-function module.command(cmd)
- module.request('nvim_command', cmd)
-end
-
-- Use for commands which expect nvim to quit.
-- The first argument can also be a timeout.
function module.expect_exit(fn_or_timeout, ...)
@@ -284,37 +322,33 @@ function module.expect_exit(fn_or_timeout, ...)
if type(fn_or_timeout) == 'function' then
eq(eof_err_msg, module.pcall_err(fn_or_timeout, ...))
else
- eq(eof_err_msg, module.pcall_err(function(timeout, fn, ...)
- fn(...)
- while session:next_message(timeout) do
- end
- if session.eof_err then
- error(session.eof_err[2])
- end
- end, fn_or_timeout, ...))
+ eq(
+ eof_err_msg,
+ module.pcall_err(function(timeout, fn, ...)
+ fn(...)
+ assert(session)
+ while session:next_message(timeout) do
+ end
+ if session.eof_err then
+ error(session.eof_err[2])
+ end
+ end, fn_or_timeout, ...)
+ )
end
end
--- Evaluates a Vimscript expression.
--- Fails on Vimscript error, but does not update v:errmsg.
-function module.eval(expr)
- return module.request('nvim_eval', expr)
-end
-
--- Executes a Vimscript function via RPC.
--- Fails on Vimscript error, but does not update v:errmsg.
-function module.call(name, ...)
- return module.request('nvim_call_function', name, {...})
-end
-
--- Executes a Vimscript function via Lua.
--- Fails on Vimscript error, but does not update v:errmsg.
+--- Executes a Vimscript function via Lua.
+--- Fails on Vimscript error, but does not update v:errmsg.
+--- @param name string
+--- @param ... any
+--- @return any
function module.call_lua(name, ...)
return module.exec_lua([[return vim.call(...)]], name, ...)
end
--- Sends user input to Nvim.
--- Does not fail on Vimscript error, but v:errmsg will be updated.
+--- Sends user input to Nvim.
+--- Does not fail on Vimscript error, but v:errmsg will be updated.
+--- @param input string
local function nvim_feed(input)
while #input > 0 do
local written = module.request('nvim_input', input)
@@ -326,22 +360,27 @@ local function nvim_feed(input)
end
end
+--- @param ... string
function module.feed(...)
- for _, v in ipairs({...}) do
+ for _, v in ipairs({ ... }) do
nvim_feed(dedent(v))
end
end
+--- @param ... string
function module.rawfeed(...)
- for _, v in ipairs({...}) do
+ for _, v in ipairs({ ... }) do
nvim_feed(dedent(v))
end
end
+---@param ... string[]?
+---@return string[]
function module.merge_args(...)
local i = 1
- local argv = {}
- for anum = 1,select('#', ...) do
+ local argv = {} --- @type string[]
+ for anum = 1, select('#', ...) do
+ --- @type string[]?
local args = select(anum, ...)
if args then
for _, arg in ipairs(args) do
@@ -353,41 +392,44 @@ function module.merge_args(...)
return argv
end
--- Removes Nvim startup args from `args` matching items in `args_rm`.
---
--- - Special case: "-u", "-i", "--cmd" are treated specially: their "values" are also removed.
--- - Special case: "runtimepath" will remove only { '--cmd', 'set runtimepath^=…', }
---
--- Example:
--- args={'--headless', '-u', 'NONE'}
--- args_rm={'--cmd', '-u'}
--- Result:
--- {'--headless'}
---
--- All matching cases are removed.
---
--- Example:
--- args={'--cmd', 'foo', '-N', '--cmd', 'bar'}
--- args_rm={'--cmd', '-u'}
--- Result:
--- {'-N'}
+--- Removes Nvim startup args from `args` matching items in `args_rm`.
+---
+--- - Special case: "-u", "-i", "--cmd" are treated specially: their "values" are also removed.
+--- - Special case: "runtimepath" will remove only { '--cmd', 'set runtimepath^=…', }
+---
+--- Example:
+--- args={'--headless', '-u', 'NONE'}
+--- args_rm={'--cmd', '-u'}
+--- Result:
+--- {'--headless'}
+---
+--- All matching cases are removed.
+---
+--- Example:
+--- args={'--cmd', 'foo', '-N', '--cmd', 'bar'}
+--- args_rm={'--cmd', '-u'}
+--- Result:
+--- {'-N'}
+--- @param args string[]
+--- @param args_rm string[]
+--- @return string[]
local function remove_args(args, args_rm)
- local new_args = {}
- local skip_following = {'-u', '-i', '-c', '--cmd', '-s', '--listen'}
+ local new_args = {} --- @type string[]
+ local skip_following = { '-u', '-i', '-c', '--cmd', '-s', '--listen' }
if not args_rm or #args_rm == 0 then
- return {unpack(args)}
+ return { unpack(args) }
end
for _, v in ipairs(args_rm) do
assert(type(v) == 'string')
end
local last = ''
for _, arg in ipairs(args) do
- if tbl_contains(skip_following, last) then
+ if vim.tbl_contains(skip_following, last) then
last = ''
- elseif tbl_contains(args_rm, arg) then
+ elseif vim.tbl_contains(args_rm, arg) then
last = arg
- elseif arg == runtime_set and tbl_contains(args_rm, 'runtimepath') then
- table.remove(new_args) -- Remove the preceding "--cmd".
+ elseif arg == runtime_set and vim.tbl_contains(args_rm, 'runtimepath') then
+ table.remove(new_args) -- Remove the preceding "--cmd".
last = ''
else
table.insert(new_args, arg)
@@ -400,40 +442,48 @@ function module.check_close()
if not session then
return
end
- local start_time = luv.now()
+ local start_time = uv.now()
session:close()
- luv.update_time() -- Update cached value of luv.now() (libuv: uv_now()).
- local end_time = luv.now()
+ uv.update_time() -- Update cached value of luv.now() (libuv: uv_now()).
+ local end_time = uv.now()
local delta = end_time - start_time
if delta > 500 then
- print("nvim took " .. delta .. " milliseconds to exit after last test\n"..
- "This indicates a likely problem with the test even if it passed!\n")
+ print(
+ 'nvim took '
+ .. delta
+ .. ' milliseconds to exit after last test\n'
+ .. 'This indicates a likely problem with the test even if it passed!\n'
+ )
io.stdout:flush()
end
session = nil
end
---- @param io_extra used for stdin_fd, see :help ui-option
+--- @param argv string[]
+--- @param merge boolean?
+--- @param env string[]?
+--- @param keep boolean
+--- @param io_extra uv.uv_pipe_t? used for stdin_fd, see :help ui-option
+--- @return test.Session
function module.spawn(argv, merge, env, keep, io_extra)
if not keep then
module.check_close()
end
- local child_stream = ChildProcessStream.spawn(
- merge and module.merge_args(prepend_argv, argv) or argv,
- env, io_extra)
+ local child_stream =
+ ChildProcessStream.spawn(merge and module.merge_args(prepend_argv, argv) or argv, env, io_extra)
return Session.new(child_stream)
end
-- Creates a new Session connected by domain socket (named pipe) or TCP.
function module.connect(file_or_address)
- local addr, port = string.match(file_or_address, "(.*):(%d+)")
- local stream = (addr and port) and SocketStream.connect(addr, port) or
- SocketStream.open(file_or_address)
+ local addr, port = string.match(file_or_address, '(.*):(%d+)')
+ local stream = (addr and port) and SocketStream.connect(addr, port)
+ or SocketStream.open(file_or_address)
return Session.new(stream)
end
--- Starts a new global Nvim session.
+-- Starts (and returns) a new global Nvim session.
--
-- Parameters are interpreted as startup args, OR a map with these keys:
-- args: List: Args appended to the default `nvim_argv` set.
@@ -447,36 +497,49 @@ end
-- clear{args={'-e'}, args_rm={'-i'}, env={TERM=term}}
function module.clear(...)
module.set_session(module.spawn_argv(false, ...))
+ return module.get_session()
end
--- same params as clear, but does returns the session instead
--- of replacing the default session
+--- same params as clear, but does returns the session instead
+--- of replacing the default session
+--- @return test.Session
function module.spawn_argv(keep, ...)
local argv, env, io_extra = module.new_argv(...)
return module.spawn(argv, nil, env, keep, io_extra)
end
--- Builds an argument list for use in clear().
---
----@see clear() for parameters.
+--- @class test.new_argv.Opts
+--- @field args? string[]
+--- @field args_rm? string[]
+--- @field env? table<string,string>
+--- @field io_extra? uv.uv_pipe_t
+
+--- Builds an argument list for use in clear().
+---
+--- @see clear() for parameters.
+--- @param ... string
+--- @return string[]
+--- @return string[]?
+--- @return uv.uv_pipe_t?
function module.new_argv(...)
- local args = {unpack(module.nvim_argv)}
+ local args = { unpack(module.nvim_argv) }
table.insert(args, '--headless')
if _G._nvim_test_id then
-- Set the server name to the test-id for logging. #8519
table.insert(args, '--listen')
table.insert(args, _G._nvim_test_id)
end
- local new_args
- local io_extra
- local env = nil
+ local new_args --- @type string[]
+ local io_extra --- @type uv.uv_pipe_t?
+ local env --- @type string[]?
+ --- @type test.new_argv.Opts|string
local opts = select(1, ...)
if type(opts) ~= 'table' then
- new_args = {...}
+ new_args = { ... }
else
args = remove_args(args, opts.args_rm)
if opts.env then
- local env_opt = {}
+ local env_opt = {} --- @type table<string,string>
for k, v in pairs(opts.env) do
assert(type(k) == 'string')
assert(type(v) == 'string')
@@ -515,19 +578,21 @@ function module.new_argv(...)
return args, env, io_extra
end
+--- @param ... string
function module.insert(...)
nvim_feed('i')
- for _, v in ipairs({...}) do
+ for _, v in ipairs({ ... }) do
local escaped = v:gsub('<', '<lt>')
module.rawfeed(escaped)
end
nvim_feed('<ESC>')
end
--- Executes an ex-command by user input. Because nvim_input() is used, Vimscript
--- errors will not manifest as client (lua) errors. Use command() for that.
+--- Executes an ex-command by user input. Because nvim_input() is used, Vimscript
+--- errors will not manifest as client (lua) errors. Use command() for that.
+--- @param ... string
function module.feed_command(...)
- for _, v in ipairs({...}) do
+ for _, v in ipairs({ ... }) do
if v:sub(1, 1) ~= '/' then
-- not a search command, prefix with colon
nvim_feed(':')
@@ -543,7 +608,7 @@ function module.source(code)
end
function module.has_powershell()
- return module.eval('executable("'..(is_os('win') and 'powershell' or 'pwsh')..'")') == 1
+ return module.eval('executable("' .. (is_os('win') and 'powershell' or 'pwsh') .. '")') == 1
end
--- Sets Nvim shell to powershell.
@@ -557,102 +622,68 @@ function module.set_shell_powershell(fake)
assert(found)
end
local shell = found and (is_os('win') and 'powershell' or 'pwsh') or module.testprg('pwsh-test')
- local cmd = 'Remove-Item -Force '..table.concat(is_os('win')
- and {'alias:cat', 'alias:echo', 'alias:sleep', 'alias:sort', 'alias:tee'}
- or {'alias:echo'}, ',')..';'
+ local cmd = 'Remove-Item -Force '
+ .. table.concat(
+ is_os('win') and { 'alias:cat', 'alias:echo', 'alias:sleep', 'alias:sort', 'alias:tee' }
+ or { 'alias:echo' },
+ ','
+ )
+ .. ';'
module.exec([[
- let &shell = ']]..shell..[['
+ let &shell = ']] .. shell .. [['
set shellquote= shellxquote=
let &shellcmdflag = '-NoLogo -NoProfile -ExecutionPolicy RemoteSigned -Command '
let &shellcmdflag .= '[Console]::InputEncoding=[Console]::OutputEncoding=[System.Text.UTF8Encoding]::new();'
let &shellcmdflag .= '$PSDefaultParameterValues[''Out-File:Encoding'']=''utf8'';'
- let &shellcmdflag .= ']]..cmd..[['
+ let &shellcmdflag .= ']] .. cmd .. [['
let &shellredir = '2>&1 | %%{ "$_" } | Out-File %s; exit $LastExitCode'
let &shellpipe = '2>&1 | %%{ "$_" } | tee %s; exit $LastExitCode'
]])
return found
end
+---@param func function
+---@return table<string,function>
function module.create_callindex(func)
- local table = {}
- setmetatable(table, {
+ return setmetatable({}, {
+ --- @param tbl table<any,function>
+ --- @param arg1 string
+ --- @return function
__index = function(tbl, arg1)
- local ret = function(...) return func(arg1, ...) end
+ local ret = function(...)
+ return func(arg1, ...)
+ end
tbl[arg1] = ret
return ret
end,
})
- return table
end
-local function ui(method, ...)
- return module.request('nvim_ui_'..method, ...)
+--- @param method string
+--- @param ... any
+function module.nvim_async(method, ...)
+ assert(session):notify(method, ...)
end
-function module.nvim_async(method, ...)
- session:notify('nvim_'..method, ...)
+--- Executes a Vimscript function via RPC.
+--- Fails on Vimscript error, but does not update v:errmsg.
+--- @param name string
+--- @param ... any
+--- @return any
+function module.call(name, ...)
+ return module.request('nvim_call_function', name, { ... })
end
module.async_meths = module.create_callindex(module.nvim_async)
-module.uimeths = module.create_callindex(ui)
-
-local function create_api(request, call)
- local m = {}
- function m.nvim(method, ...)
- return request('nvim_'..method, ...)
- end
-
- function m.buffer(method, ...)
- return request('nvim_buf_'..method, ...)
- end
-
- function m.window(method, ...)
- return request('nvim_win_'..method, ...)
- end
-
- function m.tabpage(method, ...)
- return request('nvim_tabpage_'..method, ...)
- end
-
- function m.curbuf(method, ...)
- if not method then
- return m.nvim('get_current_buf')
- end
- return m.buffer(method, 0, ...)
- end
-
- function m.curwin(method, ...)
- if not method then
- return m.nvim('get_current_win')
- end
- return m.window(method, 0, ...)
- end
-
- function m.curtab(method, ...)
- if not method then
- return m.nvim('get_current_tabpage')
- end
- return m.tabpage(method, 0, ...)
- end
-
- m.funcs = module.create_callindex(call)
- m.meths = module.create_callindex(m.nvim)
- m.bufmeths = module.create_callindex(m.buffer)
- m.winmeths = module.create_callindex(m.window)
- m.tabmeths = module.create_callindex(m.tabpage)
- m.curbufmeths = module.create_callindex(m.curbuf)
- m.curwinmeths = module.create_callindex(m.curwin)
- m.curtabmeths = module.create_callindex(m.curtab)
-
- return m
-end
module.rpc = {
- api = create_api(module.request, module.call),
+ fn = module.create_callindex(module.call),
+ api = module.create_callindex(module.request),
}
module.lua = {
- api = create_api(module.request_lua, module.call_lua),
+ fn = module.create_callindex(module.call_lua),
+ api = module.create_callindex(module.request_lua),
}
module.describe_lua_and_rpc = function(describe)
@@ -668,24 +699,37 @@ module.describe_lua_and_rpc = function(describe)
end
end
-for name, fn in pairs(module.rpc.api) do
- module[name] = fn
+--- add for typing. The for loop after will overwrite this
+module.api = vim.api
+module.fn = vim.fn
+
+for name, fns in pairs(module.rpc) do
+ --- @diagnostic disable-next-line:no-unknown
+ module[name] = fns
end
+-- Executes an ex-command. Vimscript errors manifest as client (lua) errors, but
+-- v:errmsg will not be updated.
+module.command = module.api.nvim_command
+
+-- Evaluates a Vimscript expression.
+-- Fails on Vimscript error, but does not update v:errmsg.
+module.eval = module.api.nvim_eval
+
function module.poke_eventloop()
-- Execute 'nvim_eval' (a deferred function) to
-- force at least one main_loop iteration
- session:request('nvim_eval', '1')
+ module.api.nvim_eval('1')
end
function module.buf_lines(bufnr)
- return module.exec_lua("return vim.api.nvim_buf_get_lines((...), 0, -1, false)", bufnr)
+ return module.exec_lua('return vim.api.nvim_buf_get_lines((...), 0, -1, false)', bufnr)
end
---@see buf_lines()
function module.curbuf_contents()
- module.poke_eventloop() -- Before inspecting the buffer, do whatever.
- return table.concat(module.curbuf('get_lines', 0, -1, true), '\n')
+ module.poke_eventloop() -- Before inspecting the buffer, do whatever.
+ return table.concat(module.api.nvim_buf_get_lines(0, 0, -1, true), '\n')
end
function module.expect(contents)
@@ -697,18 +741,21 @@ function module.expect_any(contents)
return ok(nil ~= string.find(module.curbuf_contents(), contents, 1, true))
end
+--- @param expected any[]
+--- @param received any[]
+--- @param kind string
+--- @return any
function module.expect_events(expected, received, kind)
- local inspect = require'vim.inspect'
if not pcall(eq, expected, received) then
- local msg = 'unexpected '..kind..' received.\n\n'
+ local msg = 'unexpected ' .. kind .. ' received.\n\n'
msg = msg .. 'received events:\n'
for _, e in ipairs(received) do
- msg = msg .. ' ' .. inspect(e) .. ';\n'
+ msg = msg .. ' ' .. vim.inspect(e) .. ';\n'
end
msg = msg .. '\nexpected events:\n'
for _, e in ipairs(expected) do
- msg = msg .. ' ' .. inspect(e) .. ';\n'
+ msg = msg .. ' ' .. vim.inspect(e) .. ';\n'
end
fail(msg)
end
@@ -723,18 +770,23 @@ end
-- Asserts that buffer is loaded and visible in the current tabpage.
function module.assert_visible(bufnr, visible)
assert(type(visible) == 'boolean')
- eq(visible, module.bufmeths.is_loaded(bufnr))
+ eq(visible, module.api.nvim_buf_is_loaded(bufnr))
if visible then
- assert(-1 ~= module.funcs.bufwinnr(bufnr),
- 'expected buffer to be visible in current tabpage: '..tostring(bufnr))
+ assert(
+ -1 ~= module.fn.bufwinnr(bufnr),
+ 'expected buffer to be visible in current tabpage: ' .. tostring(bufnr)
+ )
else
- assert(-1 == module.funcs.bufwinnr(bufnr),
- 'expected buffer NOT visible in current tabpage: '..tostring(bufnr))
+ assert(
+ -1 == module.fn.bufwinnr(bufnr),
+ 'expected buffer NOT visible in current tabpage: ' .. tostring(bufnr)
+ )
end
end
+--- @param path string
local function do_rmdir(path)
- local stat = luv.fs_stat(path)
+ local stat = uv.fs_stat(path)
if stat == nil then
return
end
@@ -743,44 +795,45 @@ local function do_rmdir(path)
end
for file in vim.fs.dir(path) do
if file ~= '.' and file ~= '..' then
- local abspath = path..'/'..file
+ local abspath = path .. '/' .. file
if global_helpers.isdir(abspath) then
- do_rmdir(abspath) -- recurse
+ do_rmdir(abspath) -- recurse
else
local ret, err = os.remove(abspath)
if not ret then
if not session then
- error('os.remove: '..err)
+ error('os.remove: ' .. err)
else
-- Try Nvim delete(): it handles `readonly` attribute on Windows,
-- and avoids Lua cross-version/platform incompatibilities.
if -1 == module.call('delete', abspath) then
- local hint = (is_os('win')
- and ' (hint: try :%bwipeout! before rmdir())' or '')
- error('delete() failed'..hint..': '..abspath)
+ local hint = (is_os('win') and ' (hint: try :%bwipeout! before rmdir())' or '')
+ error('delete() failed' .. hint .. ': ' .. abspath)
end
end
end
end
end
end
- local ret, err = luv.fs_rmdir(path)
+ local ret, err = uv.fs_rmdir(path)
if not ret then
- error('luv.fs_rmdir('..path..'): '..err)
+ error('luv.fs_rmdir(' .. path .. '): ' .. err)
end
end
+local start_dir = uv.cwd()
+
function module.rmdir(path)
local ret, _ = pcall(do_rmdir, path)
if not ret and is_os('win') then
-- Maybe "Permission denied"; try again after changing the nvim
-- process to the top-level directory.
- module.command([[exe 'cd '.fnameescape(']]..start_dir.."')")
+ module.command([[exe 'cd '.fnameescape(']] .. start_dir .. "')")
ret, _ = pcall(do_rmdir, path)
end
-- During teardown, the nvim process may not exit quickly enough, then rmdir()
-- will fail (on Windows).
- if not ret then -- Try again.
+ if not ret then -- Try again.
sleep(1000)
do_rmdir(path)
end
@@ -799,44 +852,49 @@ function module.exc_exec(cmd)
return ret
end
+--- @param cond boolean
+--- @param reason string
+--- @return boolean
function module.skip(cond, reason)
if cond then
+ --- @type fun(reason: string)
local pending = getfenv(2).pending
pending(reason or 'FIXME')
return true
- else
- return false
end
+ return false
end
-- Calls pending() and returns `true` if the system is too slow to
-- run fragile or expensive tests. Else returns `false`.
function module.skip_fragile(pending_fn, cond)
- if pending_fn == nil or type(pending_fn) ~= type(function()end) then
- error("invalid pending_fn")
+ if pending_fn == nil or type(pending_fn) ~= type(function() end) then
+ error('invalid pending_fn')
end
if cond then
- pending_fn("skipped (test is fragile on this system)", function() end)
+ pending_fn('skipped (test is fragile on this system)', function() end)
return true
- elseif os.getenv("TEST_SKIP_FRAGILE") then
- pending_fn("skipped (TEST_SKIP_FRAGILE)", function() end)
+ elseif os.getenv('TEST_SKIP_FRAGILE') then
+ pending_fn('skipped (TEST_SKIP_FRAGILE)', function() end)
return true
end
return false
end
function module.exec(code)
- module.meths.exec2(code, {})
+ module.api.nvim_exec2(code, {})
end
+--- @param code string
+--- @return string
function module.exec_capture(code)
- return module.meths.exec2(code, { output = true }).output
+ return module.api.nvim_exec2(code, { output = true }).output
end
--- @param code string
--- @return any
function module.exec_lua(code, ...)
- return module.meths.exec_lua(code, {...})
+ return module.api.nvim_exec_lua(code, { ... })
end
function module.get_pathsep()
@@ -845,8 +903,8 @@ end
--- Gets the filesystem root dir, namely "/" or "C:/".
function module.pathroot()
- local pathsep = package.config:sub(1,1)
- return is_os('win') and (module.nvim_dir:sub(1,2)..pathsep) or '/'
+ local pathsep = package.config:sub(1, 1)
+ return is_os('win') and (module.nvim_dir:sub(1, 2) .. pathsep) or '/'
end
--- Gets the full `…/build/bin/{name}` path of a test program produced by
@@ -868,26 +926,32 @@ end
function module.new_pipename()
-- HACK: Start a server temporarily, get the name, then stop it.
local pipename = module.eval('serverstart()')
- module.funcs.serverstop(pipename)
+ module.fn.serverstop(pipename)
-- Remove the pipe so that trying to connect to it without a server listening
-- will be an error instead of a hang.
os.remove(pipename)
return pipename
end
+--- @param provider string
+--- @return string|boolean?
function module.missing_provider(provider)
- if provider == 'ruby' or provider == 'node' or provider == 'perl' then
- local e = module.funcs['provider#'..provider..'#Detect']()[2]
+ if provider == 'ruby' or provider == 'perl' then
+ --- @type string?
+ local e = module.exec_lua("return {require('vim.provider." .. provider .. "').detect()}")[2]
return e ~= '' and e or false
- elseif provider == 'python' or provider == 'python3' then
- local py_major_version = (provider == 'python3' and 3 or 2)
- local e = module.funcs['provider#pythonx#Detect'](py_major_version)[2]
+ elseif provider == 'node' then
+ --- @type string?
+ local e = module.fn['provider#node#Detect']()[2]
return e ~= '' and e or false
- else
- assert(false, 'Unknown provider: '..provider)
+ elseif provider == 'python' then
+ return module.exec_lua([[return {require('vim.provider.python').detect_by_module('neovim')}]])[2]
end
+ assert(false, 'Unknown provider: ' .. provider)
end
+--- @param obj string|table
+--- @return any
function module.alter_slashes(obj)
if not is_os('win') then
return obj
@@ -896,14 +960,14 @@ function module.alter_slashes(obj)
local ret = obj:gsub('/', '\\')
return ret
elseif type(obj) == 'table' then
- local ret = {}
+ --- @cast obj table<any,any>
+ local ret = {} --- @type table<any,any>
for k, v in pairs(obj) do
ret[k] = module.alter_slashes(v)
end
return ret
- else
- assert(false, 'expected string or table of strings, got '..type(obj))
end
+ assert(false, 'expected string or table of strings, got ' .. type(obj))
end
local load_factor = 1
@@ -913,19 +977,26 @@ if global_helpers.is_ci() then
module.request('nvim_command', 'source test/old/testdir/load.vim')
load_factor = module.request('nvim_eval', 'g:test_load_factor')
end
+
+--- @param num number
+--- @return number
function module.load_adjust(num)
return math.ceil(num * load_factor)
end
+--- @param ctx table<string,any>
+--- @return table
function module.parse_context(ctx)
- local parsed = {}
- for _, item in ipairs({'regs', 'jumps', 'bufs', 'gvars'}) do
- parsed[item] = filter(function(v)
+ local parsed = {} --- @type table<string,any>
+ for _, item in ipairs({ 'regs', 'jumps', 'bufs', 'gvars' }) do
+ --- @param v any
+ parsed[item] = vim.tbl_filter(function(v)
return type(v) == 'table'
end, module.call('msgpackparse', ctx[item]))
end
parsed['bufs'] = parsed['bufs'][1]
- return map(function(v)
+ --- @param v any
+ return vim.tbl_map(function(v)
if #v == 0 then
return nil
end
@@ -935,25 +1006,30 @@ end
function module.add_builddir_to_rtp()
-- Add runtime from build dir for doc/tags (used with :help).
- module.command(string.format([[set rtp+=%s/runtime]], module.test_build_dir))
+ module.command(string.format([[set rtp+=%s/runtime]], module.paths.test_build_dir))
end
--- Kill process with given pid
+--- Kill (reap) a process by PID.
+--- @param pid string
+--- @return boolean?
function module.os_kill(pid)
- return os.execute((is_os('win')
- and 'taskkill /f /t /pid '..pid..' > nul'
- or 'kill -9 '..pid..' > /dev/null'))
+ return os.execute(
+ (
+ is_os('win') and 'taskkill /f /t /pid ' .. pid .. ' > nul'
+ or 'kill -9 ' .. pid .. ' > /dev/null'
+ )
+ )
end
--- Create folder with non existing parents
+--- Create folder with non existing parents
+--- @param path string
+--- @return boolean?
function module.mkdir_p(path)
- return os.execute((is_os('win')
- and 'mkdir '..path
- or 'mkdir -p '..path))
+ return os.execute((is_os('win') and 'mkdir ' .. path or 'mkdir -p ' .. path))
end
--- @class test.functional.helpers: test.helpers
-module = global_helpers.tbl_extend('error', module, global_helpers)
+module = vim.tbl_extend('error', module, global_helpers)
--- @return test.functional.helpers
return function(after_each)
@@ -964,7 +1040,7 @@ return function(after_each)
if session then
local msg = session:next_message(0)
if msg then
- if msg[1] == "notification" and msg[2] == "nvim_error_event" then
+ if msg[1] == 'notification' and msg[2] == 'nvim_error_event' then
error(msg[3][2])
end
end
diff --git a/test/functional/legacy/008_autocommands_spec.lua b/test/functional/legacy/008_autocommands_spec.lua
index 4088cd1644..16f0216bc0 100644
--- a/test/functional/legacy/008_autocommands_spec.lua
+++ b/test/functional/legacy/008_autocommands_spec.lua
@@ -3,7 +3,8 @@
local helpers = require('test.functional.helpers')(after_each)
local source = helpers.source
-local clear, command, expect, eq, eval = helpers.clear, helpers.command, helpers.expect, helpers.eq, helpers.eval
+local clear, command, expect, eq, eval =
+ helpers.clear, helpers.command, helpers.expect, helpers.eq, helpers.eval
local write_file, dedent = helpers.write_file, helpers.dedent
local read_file = helpers.read_file
local expect_exit = helpers.expect_exit
@@ -16,8 +17,8 @@ describe('autocommands that delete and unload buffers:', function()
end of Xxx]])
local text2 = text1:gsub('1', '2')
setup(function()
- write_file('Xxx1', text1..'\n')
- write_file('Xxx2', text2..'\n')
+ write_file('Xxx1', text1 .. '\n')
+ write_file('Xxx2', text2 .. '\n')
end)
teardown(function()
os.remove(test_file)
@@ -36,8 +37,7 @@ describe('autocommands that delete and unload buffers:', function()
-- The legacy test file did not check the error message.
command('let v:errmsg = "no error"')
command('silent! write')
- eq('E203: Autocommands deleted or unloaded buffer to be written',
- eval('v:errmsg'))
+ eq('E203: Autocommands deleted or unloaded buffer to be written', eval('v:errmsg'))
eq('Xxx2', eval('bufname("%")'))
expect(text2)
-- Start editing Xxx2.
@@ -46,8 +46,7 @@ describe('autocommands that delete and unload buffers:', function()
command('let v:errmsg = "no error"')
-- Write Xxx2, will delete the buffer and give an error msg.
command('silent! write')
- eq('E203: Autocommands deleted or unloaded buffer to be written',
- eval('v:errmsg'))
+ eq('E203: Autocommands deleted or unloaded buffer to be written', eval('v:errmsg'))
eq('Xxx1', eval('bufname("%")'))
expect(text1)
end)
@@ -63,7 +62,7 @@ describe('autocommands that delete and unload buffers:', function()
endwhile
endfunc
func WriteToOut()
- edit! ]]..test_file..[[
+ edit! ]] .. test_file .. [[
$put ='VimLeave done'
write
@@ -80,7 +79,6 @@ describe('autocommands that delete and unload buffers:', function()
command('silent! edit Makefile') -- an existing file
command('silent! split new2')
expect_exit(command, 'silent! quit')
- eq('VimLeave done',
- string.match(read_file(test_file), "^%s*(.-)%s*$"))
+ eq('VimLeave done', string.match(read_file(test_file), '^%s*(.-)%s*$'))
end)
end)
diff --git a/test/functional/legacy/011_autocommands_spec.lua b/test/functional/legacy/011_autocommands_spec.lua
index 5b6d030567..eba878b99a 100644
--- a/test/functional/legacy/011_autocommands_spec.lua
+++ b/test/functional/legacy/011_autocommands_spec.lua
@@ -12,11 +12,16 @@
-- Use a FileChangedShell autocommand to avoid a prompt for "Xtestfile.gz"
-- being modified outside of Vim (noticed on Solaris).
-local helpers= require('test.functional.helpers')(after_each)
-local luv = require('luv')
+local helpers = require('test.functional.helpers')(after_each)
local clear, feed_command, expect, eq, neq, dedent, write_file, feed =
- helpers.clear, helpers.feed_command, helpers.expect, helpers.eq, helpers.neq,
- helpers.dedent, helpers.write_file, helpers.feed
+ helpers.clear,
+ helpers.feed_command,
+ helpers.expect,
+ helpers.eq,
+ helpers.neq,
+ helpers.dedent,
+ helpers.write_file,
+ helpers.feed
local command = helpers.command
local read_file = helpers.read_file
local is_os = helpers.is_os
@@ -27,12 +32,12 @@ local function has_gzip()
end
local function prepare_gz_file(name, text)
- write_file(name, text..'\n')
+ write_file(name, text .. '\n')
-- Compress the file with gzip.
- command([[call system(['gzip', '--force', ']]..name..[['])]])
+ command([[call system(['gzip', '--force', ']] .. name .. [['])]])
-- This should create the .gz file and delete the original.
- neq(nil, luv.fs_stat(name..'.gz'))
- eq(nil, luv.fs_stat(name))
+ neq(nil, vim.uv.fs_stat(name .. '.gz'))
+ eq(nil, vim.uv.fs_stat(name))
end
describe('file reading, writing and bufnew and filter autocommands', function()
@@ -49,14 +54,17 @@ describe('file reading, writing and bufnew and filter autocommands', function()
line 10 Abcdefghijklmnopqrstuvwxyz
end of testfile]])
setup(function()
- write_file('Xtest.c', [[
+ write_file(
+ 'Xtest.c',
+ [[
/*
* Here is a new .c file
*/
- ]])
+ ]]
+ )
end)
- before_each(function ()
- clear({env={GZIP=nil}})
+ before_each(function()
+ clear({ env = { GZIP = nil } })
end)
teardown(function()
os.remove('Xtestfile.gz')
@@ -67,7 +75,6 @@ describe('file reading, writing and bufnew and filter autocommands', function()
if not has_gzip() then
pending('skipped (missing `gzip` utility)', function() end)
else
-
it('FileReadPost (using gzip)', function()
prepare_gz_file('Xtestfile', text1)
--execute('au FileChangedShell * echo "caught FileChangedShell"')
@@ -75,7 +82,7 @@ describe('file reading, writing and bufnew and filter autocommands', function()
feed_command("au FileReadPost *.gz '[,']!gzip -d")
-- Read and decompress the testfile.
feed_command('$r Xtestfile.gz')
- expect('\n'..text1)
+ expect('\n' .. text1)
end)
it('BufReadPre, BufReadPost (using gzip)', function()
@@ -100,7 +107,9 @@ describe('file reading, writing and bufnew and filter autocommands', function()
-- luacheck: ignore 611 (Line contains only whitespaces)
it('FileReadPre, FileReadPost', function()
prepare_gz_file('Xtestfile', text1)
- feed_command('au! FileReadPre *.gz exe "silent !gzip -d " . shellescape(expand("<afile>"))')
+ feed_command(
+ 'au! FileReadPre *.gz exe "silent !gzip -d " . shellescape(expand("<afile>"))'
+ )
feed_command('au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))')
feed_command("au! FileReadPost *.gz '[,']s/l/L/")
-- Read compressed file.
@@ -121,7 +130,6 @@ describe('file reading, writing and bufnew and filter autocommands', function()
Line 10 Abcdefghijklmnopqrstuvwxyz
end of testfiLe]])
end)
-
end
it('FileAppendPre, FileAppendPost', function()
@@ -169,9 +177,15 @@ describe('file reading, writing and bufnew and filter autocommands', function()
*/]]))
-- Need temp files here.
feed_command('set shelltemp')
- feed_command('au FilterReadPre *.out call rename(expand("<afile>"), expand("<afile>") . ".t")')
- feed_command('au FilterReadPre *.out exe "silent !sed s/e/E/ " . shellescape(expand("<afile>")) . ".t >" . shellescape(expand("<afile>"))')
- feed_command('au FilterReadPre *.out exe "silent !rm " . shellescape(expand("<afile>")) . ".t"')
+ feed_command(
+ 'au FilterReadPre *.out call rename(expand("<afile>"), expand("<afile>") . ".t")'
+ )
+ feed_command(
+ 'au FilterReadPre *.out exe "silent !sed s/e/E/ " . shellescape(expand("<afile>")) . ".t >" . shellescape(expand("<afile>"))'
+ )
+ feed_command(
+ 'au FilterReadPre *.out exe "silent !rm " . shellescape(expand("<afile>")) . ".t"'
+ )
feed_command("au FilterReadPost *.out '[,']s/x/X/g")
-- Edit the output file.
feed_command('e! test.out')
diff --git a/test/functional/legacy/012_directory_spec.lua b/test/functional/legacy/012_directory_spec.lua
index 25d0dcb81e..b428318e3f 100644
--- a/test/functional/legacy/012_directory_spec.lua
+++ b/test/functional/legacy/012_directory_spec.lua
@@ -4,13 +4,12 @@
-- - "dir", in directory relative to current dir
local helpers = require('test.functional.helpers')(after_each)
-local luv = require('luv')
local eq = helpers.eq
local neq = helpers.neq
local poke_eventloop = helpers.poke_eventloop
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local clear = helpers.clear
local insert = helpers.insert
local command = helpers.command
@@ -21,7 +20,7 @@ local mkdir = helpers.mkdir
local function ls_dir_sorted(dirname)
local files = {}
for f in vim.fs.dir(dirname) do
- if f ~= "." and f~= ".." then
+ if f ~= '.' and f ~= '..' then
table.insert(files, f)
end
end
@@ -57,36 +56,36 @@ describe("'directory' option", function()
line 3 Abcdefghij
end of testfile]])
- meths.set_option_value('swapfile', true, {})
- meths.set_option_value('swapfile', true, {})
- meths.set_option_value('directory', '.', {})
+ api.nvim_set_option_value('swapfile', true, {})
+ api.nvim_set_option_value('swapfile', true, {})
+ api.nvim_set_option_value('directory', '.', {})
-- sanity check: files should not exist yet.
- eq(nil, luv.fs_stat('.Xtest1.swp'))
+ eq(nil, vim.uv.fs_stat('.Xtest1.swp'))
command('edit! Xtest1')
poke_eventloop()
- eq('Xtest1', funcs.buffer_name('%'))
+ eq('Xtest1', fn.buffer_name('%'))
-- Verify that the swapfile exists. In the legacy test this was done by
-- reading the output from :!ls.
- neq(nil, luv.fs_stat('.Xtest1.swp'))
+ neq(nil, vim.uv.fs_stat('.Xtest1.swp'))
- meths.set_option_value('directory', './Xtest2,.', {})
+ api.nvim_set_option_value('directory', './Xtest2,.', {})
command('edit Xtest1')
poke_eventloop()
-- swapfile should no longer exist in CWD.
- eq(nil, luv.fs_stat('.Xtest1.swp'))
+ eq(nil, vim.uv.fs_stat('.Xtest1.swp'))
- eq({ "Xtest1.swp", "Xtest3" }, ls_dir_sorted("Xtest2"))
+ eq({ 'Xtest1.swp', 'Xtest3' }, ls_dir_sorted('Xtest2'))
- meths.set_option_value('directory', 'Xtest.je', {})
+ api.nvim_set_option_value('directory', 'Xtest.je', {})
command('bdelete')
command('edit Xtest2/Xtest3')
- eq(true, meths.get_option_value('swapfile', {}))
+ eq(true, api.nvim_get_option_value('swapfile', {}))
poke_eventloop()
- eq({ "Xtest3" }, ls_dir_sorted("Xtest2"))
- eq({ "Xtest3.swp" }, ls_dir_sorted("Xtest.je"))
+ eq({ 'Xtest3' }, ls_dir_sorted('Xtest2'))
+ eq({ 'Xtest3.swp' }, ls_dir_sorted('Xtest.je'))
end)
end)
diff --git a/test/functional/legacy/023_edit_arguments_spec.lua b/test/functional/legacy/023_edit_arguments_spec.lua
index f59d192c1e..64b2f6fa95 100644
--- a/test/functional/legacy/023_edit_arguments_spec.lua
+++ b/test/functional/legacy/023_edit_arguments_spec.lua
@@ -28,7 +28,7 @@ describe(':edit', function()
-- Open Xfile2 using '|' range
command('edit Xfile2|1')
- command("s/\\//SLASH/")
+ command('s/\\//SLASH/')
command('yank A')
command('w! Xfile2')
diff --git a/test/functional/legacy/025_jump_tag_hidden_spec.lua b/test/functional/legacy/025_jump_tag_hidden_spec.lua
index 15bd56a601..33bab05404 100644
--- a/test/functional/legacy/025_jump_tag_hidden_spec.lua
+++ b/test/functional/legacy/025_jump_tag_hidden_spec.lua
@@ -56,6 +56,6 @@ describe('jump to a tag with hidden set', function()
feed_command('$d')
-- Assert buffer contents.
- expect("#efine SECTION_OFF 3")
+ expect('#efine SECTION_OFF 3')
end)
end)
diff --git a/test/functional/legacy/029_join_spec.lua b/test/functional/legacy/029_join_spec.lua
index b28f276a7c..c808a21afc 100644
--- a/test/functional/legacy/029_join_spec.lua
+++ b/test/functional/legacy/029_join_spec.lua
@@ -313,7 +313,9 @@ describe('joining lines', function()
feed('j')
feed_command('.,+5join')
feed('j6J<cr>')
- feed('oSome code!<cr>// Make sure backspacing does not remove this comment leader.<esc>0i<bs><esc>')
+ feed(
+ 'oSome code!<cr>// Make sure backspacing does not remove this comment leader.<esc>0i<bs><esc>'
+ )
expect([[
{
diff --git a/test/functional/legacy/031_close_commands_spec.lua b/test/functional/legacy/031_close_commands_spec.lua
index d02b1a2049..173ebf1cf4 100644
--- a/test/functional/legacy/031_close_commands_spec.lua
+++ b/test/functional/legacy/031_close_commands_spec.lua
@@ -119,9 +119,12 @@ describe('Commands that close windows and/or buffers', function()
feed_command('q!')
feed('<CR>')
expect('testtext 1')
- expect_exit(source, [[
+ expect_exit(
+ source,
+ [[
q!
" Now nvim should have exited
- throw "Oh, Not finished yet."]])
+ throw "Oh, Not finished yet."]]
+ )
end)
end)
diff --git a/test/functional/legacy/034_user_function_spec.lua b/test/functional/legacy/034_user_function_spec.lua
index 0b7dfc4f0e..c30c7275f2 100644
--- a/test/functional/legacy/034_user_function_spec.lua
+++ b/test/functional/legacy/034_user_function_spec.lua
@@ -7,13 +7,15 @@ local helpers = require('test.functional.helpers')(after_each)
local feed, insert, source = helpers.feed, helpers.insert, helpers.source
local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers.expect
-describe('user functions, expr-mappings, overwrite protected builtin functions and regression on calling expressions', function()
- setup(clear)
+describe(
+ 'user functions, expr-mappings, overwrite protected builtin functions and regression on calling expressions',
+ function()
+ setup(clear)
- it('are working', function()
- insert('here')
+ it('are working', function()
+ insert('here')
- source([[
+ source([[
function Table(title, ...)
let ret = a:title
let idx = 1
@@ -59,35 +61,35 @@ describe('user functions, expr-mappings, overwrite protected builtin functions a
let retval = "nop"
/^here
]])
- feed('C<C-R>=Table("xxx", 4, "asdf")<cr>')
- -- Using a actual space will not work as feed() calls dedent on the input.
- feed('<space><C-R>=Compute(45, 0, "retval")<cr>')
- feed('<space><C-R>=retval<cr>')
- feed('<space><C-R>=Compute(45, 5, "retval")<cr>')
- feed('<space><C-R>=retval<cr>')
- feed('<space><C-R>=g:FuncRef(333)<cr>')
- feed('<cr>')
- feed('XX+-XX<cr>')
- feed('---*---<cr>')
- feed('(one<cr>')
- feed('(two<cr>')
- feed('[(one again<esc>')
- feed_command('call append(line("$"), max([1, 2, 3]))')
- feed_command('call extend(g:, {"max": function("min")})')
- feed_command('call append(line("$"), max([1, 2, 3]))')
- feed_command('try')
- -- Regression: the first line below used to throw "E110: Missing ')'"
- -- Second is here just to prove that this line is correct when not
- -- skipping rhs of &&.
- feed_command([[ $put =(0&&(function('tr'))(1, 2, 3))]])
- feed_command([[ $put =(1&&(function('tr'))(1, 2, 3))]])
- feed_command('catch')
- feed_command([[ $put ='!!! Unexpected exception:']])
- feed_command(' $put =v:exception')
- feed_command('endtry')
+ feed('C<C-R>=Table("xxx", 4, "asdf")<cr>')
+ -- Using a actual space will not work as feed() calls dedent on the input.
+ feed('<space><C-R>=Compute(45, 0, "retval")<cr>')
+ feed('<space><C-R>=retval<cr>')
+ feed('<space><C-R>=Compute(45, 5, "retval")<cr>')
+ feed('<space><C-R>=retval<cr>')
+ feed('<space><C-R>=g:FuncRef(333)<cr>')
+ feed('<cr>')
+ feed('XX+-XX<cr>')
+ feed('---*---<cr>')
+ feed('(one<cr>')
+ feed('(two<cr>')
+ feed('[(one again<esc>')
+ feed_command('call append(line("$"), max([1, 2, 3]))')
+ feed_command('call extend(g:, {"max": function("min")})')
+ feed_command('call append(line("$"), max([1, 2, 3]))')
+ feed_command('try')
+ -- Regression: the first line below used to throw "E110: Missing ')'"
+ -- Second is here just to prove that this line is correct when not
+ -- skipping rhs of &&.
+ feed_command([[ $put =(0&&(function('tr'))(1, 2, 3))]])
+ feed_command([[ $put =(1&&(function('tr'))(1, 2, 3))]])
+ feed_command('catch')
+ feed_command([[ $put ='!!! Unexpected exception:']])
+ feed_command(' $put =v:exception')
+ feed_command('endtry')
- -- Assert buffer contents.
- expect([[
+ -- Assert buffer contents.
+ expect([[
xxx4asdf fail nop ok 9 333
XX111-XX
---222---
@@ -98,5 +100,6 @@ describe('user functions, expr-mappings, overwrite protected builtin functions a
3
0
1]])
- end)
-end)
+ end)
+ end
+)
diff --git a/test/functional/legacy/036_regexp_character_classes_spec.lua b/test/functional/legacy/036_regexp_character_classes_spec.lua
index 6f66efcb67..ed35b2b245 100644
--- a/test/functional/legacy/036_regexp_character_classes_spec.lua
+++ b/test/functional/legacy/036_regexp_character_classes_spec.lua
@@ -5,16 +5,16 @@ local clear, command, expect = helpers.clear, helpers.command, helpers.expect
local source, write_file = helpers.source, helpers.write_file
local function sixlines(text)
- local result = ''
- for _ = 1, 6 do
- result = result .. text .. '\n'
- end
- return result
+ local result = ''
+ for _ = 1, 6 do
+ result = result .. text .. '\n'
+ end
+ return result
end
local function diff(text, nodedent)
local fname = helpers.tmpname()
- command('w! '..fname)
+ command('w! ' .. fname)
helpers.poke_eventloop()
local data = io.open(fname):read('*all')
if nodedent then
@@ -40,7 +40,16 @@ describe('character classes in regexp', function()
-- The original test32.in file was not in utf-8 encoding and did also
-- contain some control characters. We use lua escape sequences to write
-- them to the test file.
- local line = ctrl1..punct1..digits..punct2..upper..punct3..lower..punct4..ctrl2..iso_text
+ local line = ctrl1
+ .. punct1
+ .. digits
+ .. punct2
+ .. upper
+ .. punct3
+ .. lower
+ .. punct4
+ .. ctrl2
+ .. iso_text
write_file('test36.in', sixlines(line))
end)
before_each(function()
@@ -59,8 +68,9 @@ describe('character classes in regexp', function()
4 s/\%#=0[0-9]//g
5 s/\%#=1[0-9]//g
6 s/\%#=2[0-9]//g]])
- diff(sixlines(ctrl1..punct1..punct2..upper..punct3..lower..punct4..
- ctrl2..iso_text))
+ diff(
+ sixlines(ctrl1 .. punct1 .. punct2 .. upper .. punct3 .. lower .. punct4 .. ctrl2 .. iso_text)
+ )
end)
it('is working', function()
source([[
@@ -86,8 +96,11 @@ describe('character classes in regexp', function()
4 s/\%#=0[0-7]//g
5 s/\%#=1[0-7]//g
6 s/\%#=2[0-7]//g]])
- diff(sixlines(ctrl1..punct1..'89'..punct2..upper..punct3..lower..punct4..ctrl2..
- iso_text))
+ diff(
+ sixlines(
+ ctrl1 .. punct1 .. '89' .. punct2 .. upper .. punct3 .. lower .. punct4 .. ctrl2 .. iso_text
+ )
+ )
end)
it('is working', function()
source([[
@@ -113,7 +126,11 @@ describe('character classes in regexp', function()
4 s/\%#=0[0-9A-Fa-f]//g
5 s/\%#=1[0-9A-Fa-f]//g
6 s/\%#=2[0-9A-Fa-f]//g]])
- diff(sixlines(ctrl1..punct1..punct2..'GHIXYZ'..punct3..'ghiwxyz'..punct4..ctrl2..iso_text))
+ diff(
+ sixlines(
+ ctrl1 .. punct1 .. punct2 .. 'GHIXYZ' .. punct3 .. 'ghiwxyz' .. punct4 .. ctrl2 .. iso_text
+ )
+ )
end)
it('is working', function()
source([[
@@ -139,7 +156,7 @@ describe('character classes in regexp', function()
4 s/\%#=0[0-9A-Za-z_]//g
5 s/\%#=1[0-9A-Za-z_]//g
6 s/\%#=2[0-9A-Za-z_]//g]])
- diff(sixlines(ctrl1..punct1..punct2..'[\\]^`'..punct4..ctrl2..iso_text))
+ diff(sixlines(ctrl1 .. punct1 .. punct2 .. '[\\]^`' .. punct4 .. ctrl2 .. iso_text))
end)
it('is working', function()
source([[
@@ -165,8 +182,7 @@ describe('character classes in regexp', function()
4 s/\%#=0[A-Za-z_]//g
5 s/\%#=1[A-Za-z_]//g
6 s/\%#=2[A-Za-z_]//g]])
- diff(sixlines(ctrl1..punct1..digits..punct2..'[\\]^`'..punct4..ctrl2..
- iso_text))
+ diff(sixlines(ctrl1 .. punct1 .. digits .. punct2 .. '[\\]^`' .. punct4 .. ctrl2 .. iso_text))
end)
it('is working', function()
source([[
@@ -192,7 +208,7 @@ describe('character classes in regexp', function()
4 s/\%#=0[A-Za-z]//g
5 s/\%#=1[A-Za-z]//g
6 s/\%#=2[A-Za-z]//g]])
- diff(sixlines(ctrl1..punct1..digits..punct2..punct3..punct4..ctrl2..iso_text))
+ diff(sixlines(ctrl1 .. punct1 .. digits .. punct2 .. punct3 .. punct4 .. ctrl2 .. iso_text))
end)
it('is working', function()
source([[
@@ -218,8 +234,11 @@ describe('character classes in regexp', function()
4 s/\%#=0[a-z]//g
5 s/\%#=1[a-z]//g
6 s/\%#=2[a-z]//g]])
- diff(sixlines(ctrl1..punct1..digits..punct2..upper..punct3..punct4..
- ctrl2..iso_text))
+ diff(
+ sixlines(
+ ctrl1 .. punct1 .. digits .. punct2 .. upper .. punct3 .. punct4 .. ctrl2 .. iso_text
+ )
+ )
end)
it('is working', function()
source([[
@@ -245,8 +264,11 @@ describe('character classes in regexp', function()
4 s/\%#=0[A-Z]//g
5 s/\%#=1[A-Z]//g
6 s/\%#=2[A-Z]//g]])
- diff(sixlines(ctrl1..punct1..digits..punct2..punct3..lower..punct4..
- ctrl2..iso_text))
+ diff(
+ sixlines(
+ ctrl1 .. punct1 .. digits .. punct2 .. punct3 .. lower .. punct4 .. ctrl2 .. iso_text
+ )
+ )
end)
it('is working', function()
source([[
@@ -272,8 +294,19 @@ describe('character classes in regexp', function()
4 s/\%#=0\%4l^\t...//g
5 s/\%#=1\%5l^\t...//g
6 s/\%#=2\%6l^\t...//g]])
- diff(sixlines(string.sub(punct1, 1)..digits..punct2..upper..punct3..
- lower..punct4..ctrl2..iso_text))
+ diff(
+ sixlines(
+ string.sub(punct1, 1)
+ .. digits
+ .. punct2
+ .. upper
+ .. punct3
+ .. lower
+ .. punct4
+ .. ctrl2
+ .. iso_text
+ )
+ )
end)
it('does not convert character class ranges to an incorrect class', function()
source([[
@@ -284,7 +317,9 @@ describe('character classes in regexp', function()
5 s/\%#=1[^0-z]//g
6 s/\%#=2[^0-z]//g
]])
- diff(string.rep(ctrl1..punct1..punct4..ctrl2..iso_text..'\n', 3)
- ..string.rep(digits..punct2..upper..punct3..lower..'\n', 3))
+ diff(
+ string.rep(ctrl1 .. punct1 .. punct4 .. ctrl2 .. iso_text .. '\n', 3)
+ .. string.rep(digits .. punct2 .. upper .. punct3 .. lower .. '\n', 3)
+ )
end)
end)
diff --git a/test/functional/legacy/038_virtual_replace_spec.lua b/test/functional/legacy/038_virtual_replace_spec.lua
index 8dd7bdda6e..2f85e7d5a3 100644
--- a/test/functional/legacy/038_virtual_replace_spec.lua
+++ b/test/functional/legacy/038_virtual_replace_spec.lua
@@ -38,7 +38,9 @@ describe('Virtual replace mode', function()
feed('BCDEFGHIJ<cr>')
feed('<tab>KL<cr>')
feed('MNO<cr>')
- feed('PQR<C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><esc>:$<cr>')
+ feed(
+ 'PQR<C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><C-h><esc>:$<cr>'
+ )
feed('iab<tab>cdefghi<tab>jkl<esc>0gRAB......CDEFGHI.J<esc>o<esc>:<cr>')
feed('iabcdefghijklmnopqrst<esc>0gRAB<tab>IJKLMNO<tab>QR<esc>')
diff --git a/test/functional/legacy/039_visual_block_mode_commands_spec.lua b/test/functional/legacy/039_visual_block_mode_commands_spec.lua
index 135058c579..bc3fea765c 100644
--- a/test/functional/legacy/039_visual_block_mode_commands_spec.lua
+++ b/test/functional/legacy/039_visual_block_mode_commands_spec.lua
@@ -2,13 +2,12 @@
-- And test "U" in Visual mode, also on German sharp S.
local helpers = require('test.functional.helpers')(after_each)
-local nvim, eq = helpers.meths, helpers.eq
+local nvim, eq = helpers.api, helpers.eq
local insert, feed = helpers.insert, helpers.feed
local clear, expect = helpers.clear, helpers.expect
local feed_command = helpers.feed_command
describe('Visual block mode', function()
-
before_each(function()
clear()
@@ -135,7 +134,7 @@ describe('Visual block mode', function()
end)
it('should make a selected part uppercase', function()
- -- GUe must uppercase a whole word, also when ß changes to SS.
+ -- GUe must uppercase a whole word, also when ß changes to ẞ.
feed('Gothe youtußeuu end<ESC>Ypk0wgUe<CR>')
-- GUfx must uppercase until x, inclusive.
feed('O- youßtußexu -<ESC>0fogUfx<CR>')
@@ -151,13 +150,13 @@ describe('Visual block mode', function()
expect([[
- the YOUTUSSEUU end
- - yOUSSTUSSEXu -
- THE YOUTUSSEUU END
- 111THE YOUTUSSEUU END
+ the YOUTUẞEUU end
+ - yOUẞTUẞEXu -
+ THE YOUTUẞEUU END
+ 111THE YOUTUẞEUU END
BLAH DI
DOH DUT
- 222the yoUTUSSEUU END
+ 222the yoUTUẞEUU END
333THE YOUTUßeuu end]])
end)
@@ -205,14 +204,14 @@ describe('Visual block mode', function()
feed('G2l')
feed('2k<C-v>$gj<ESC>')
feed_command([[let cpos=getpos("'>")]])
- local cpos = nvim.get_var('cpos')
+ local cpos = nvim.nvim_get_var('cpos')
local expected = {
col = 4,
- off = 0
+ off = 0,
}
local actual = {
col = cpos[3],
- off = cpos[4]
+ off = cpos[4],
}
eq(expected, actual)
diff --git a/test/functional/legacy/055_list_and_dict_types_spec.lua b/test/functional/legacy/055_list_and_dict_types_spec.lua
index 75294b3786..e8ae60e350 100644
--- a/test/functional/legacy/055_list_and_dict_types_spec.lua
+++ b/test/functional/legacy/055_list_and_dict_types_spec.lua
@@ -547,7 +547,8 @@ describe('list and dictionary types', function()
$put =string(sort(copy(l), 1))
$put =string(sort(copy(l), 'i'))
$put =string(sort(copy(l)))]=])
- expect([=[
+ expect(
+ [=[
['-0', 'A11', 2, 'xaaa', 4, 'foo', 'foo6', 'foo', [0, 1, 2], 'x8', [0, 1, 2], 1.5]
[1.5, [0, 1, 2], 'x8', [0, 1, 2], 'foo', 'foo6', 'foo', 4, 'xaaa', 2, 2, 'A11', '-0']
@@ -559,7 +560,8 @@ describe('list and dictionary types', function()
[-1, 'one', 'two', 'three', 'four', 1.0e-15, 0.22, 7, 9, 12, 18, 22, 255]
['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}]
['bar', 'BAR', 'Bar', 'Foo', 'FOO', 'foo', 'FOOBAR', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}]
- ['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}]]=])
+ ['BAR', 'Bar', 'FOO', 'FOOBAR', 'Foo', 'bar', 'foo', -1, 0, 0, 0.22, 1.0e-15, 12, 18, 22, 255, 7, 9, [], {}]]=]
+ )
end)
it('splitting a string to a list', function()
diff --git a/test/functional/legacy/057_sort_spec.lua b/test/functional/legacy/057_sort_spec.lua
index 328d6f6fa0..9b4746591f 100644
--- a/test/functional/legacy/057_sort_spec.lua
+++ b/test/functional/legacy/057_sort_spec.lua
@@ -2,8 +2,8 @@
local helpers = require('test.functional.helpers')(after_each)
-local insert, command, clear, expect, eq, poke_eventloop = helpers.insert,
- helpers.command, helpers.clear, helpers.expect, helpers.eq, helpers.poke_eventloop
+local insert, command, clear, expect, eq, poke_eventloop =
+ helpers.insert, helpers.command, helpers.clear, helpers.expect, helpers.eq, helpers.poke_eventloop
local exc_exec = helpers.exc_exec
describe(':sort', function()
diff --git a/test/functional/legacy/060_exists_and_has_functions_spec.lua b/test/functional/legacy/060_exists_and_has_functions_spec.lua
index 1794f23b3a..82fece3e84 100644
--- a/test/functional/legacy/060_exists_and_has_functions_spec.lua
+++ b/test/functional/legacy/060_exists_and_has_functions_spec.lua
@@ -9,7 +9,9 @@ describe('exists() and has() functions', function()
setup(function()
clear()
-- Create a temporary script needed for the test.
- write_file('test60.vim', [[
+ write_file(
+ 'test60.vim',
+ [[
" Vim script for exists() function test
" Script-local variables are checked here
@@ -107,7 +109,8 @@ describe('exists() and has() functions', function()
echo "FAILED"
endif
unlet str
- ]])
+ ]]
+ )
end)
teardown(function()
os.remove('test.out')
@@ -115,7 +118,6 @@ describe('exists() and has() functions', function()
end)
it('is working', function()
-
source([=[
" Add the special directory with test scripts to &rtp
set rtp+=test/functional/fixtures
@@ -850,6 +852,5 @@ describe('exists() and has() functions', function()
g:footest#x = 1
footest#F() 0
UndefFun() 0]])
-
end)
end)
diff --git a/test/functional/legacy/063_match_and_matchadd_spec.lua b/test/functional/legacy/063_match_and_matchadd_spec.lua
index 235a826640..0c2b59932b 100644
--- a/test/functional/legacy/063_match_and_matchadd_spec.lua
+++ b/test/functional/legacy/063_match_and_matchadd_spec.lua
@@ -13,35 +13,30 @@ describe('063: Test for ":match", "matchadd()" and related functions', function(
local screen = Screen.new(40, 5)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {background = Screen.colors.Red},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { background = Screen.colors.Red },
})
- command("highlight MyGroup1 term=bold ctermbg=red guibg=red")
- command("highlight MyGroup2 term=italic ctermbg=green guibg=green")
- command("highlight MyGroup3 term=underline ctermbg=blue guibg=blue")
+ command('highlight MyGroup1 term=bold ctermbg=red guibg=red')
+ command('highlight MyGroup2 term=italic ctermbg=green guibg=green')
+ command('highlight MyGroup3 term=underline ctermbg=blue guibg=blue')
-- Check that "matchaddpos()" positions matches correctly
insert('abcdefghijklmnopq')
command("call matchaddpos('MyGroup1', [[1, 5], [1, 8, 3]], 10, 3)")
screen:expect([[
abcd{1:e}fg{1:hij}klmnop^q |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
- command("call clearmatches()")
+ command('call clearmatches()')
command("call setline(1, 'abcdΣabcdef')")
command("call matchaddpos('MyGroup1', [[1, 4, 2], [1, 9, 2]])")
screen:expect([[
abc{1:dΣ}ab{1:cd}e^f |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
end)
end)
-
diff --git a/test/functional/legacy/069_multibyte_formatting_spec.lua b/test/functional/legacy/069_multibyte_formatting_spec.lua
index 9c248e3aa8..05e6aa1435 100644
--- a/test/functional/legacy/069_multibyte_formatting_spec.lua
+++ b/test/functional/legacy/069_multibyte_formatting_spec.lua
@@ -4,8 +4,13 @@
-- Also test byteidx() and byteidxcomp()
local helpers = require('test.functional.helpers')(after_each)
-local feed, insert, eq, eval, clear, feed_command, expect = helpers.feed,
- helpers.insert, helpers.eq, helpers.eval, helpers.clear, helpers.feed_command,
+local feed, insert, eq, eval, clear, feed_command, expect =
+ helpers.feed,
+ helpers.insert,
+ helpers.eq,
+ helpers.eval,
+ helpers.clear,
+ helpers.feed_command,
helpers.expect
describe('multibyte text', function()
diff --git a/test/functional/legacy/074_global_var_in_viminfo_spec.lua b/test/functional/legacy/074_global_var_in_viminfo_spec.lua
index 06d8b276d7..0a9ad330c2 100644
--- a/test/functional/legacy/074_global_var_in_viminfo_spec.lua
+++ b/test/functional/legacy/074_global_var_in_viminfo_spec.lua
@@ -1,10 +1,8 @@
-- Tests for storing global variables in the .shada file
local helpers = require('test.functional.helpers')(after_each)
-local luv = require('luv')
local clear, command, eq, neq, eval, poke_eventloop =
- helpers.clear, helpers.command, helpers.eq, helpers.neq, helpers.eval,
- helpers.poke_eventloop
+ helpers.clear, helpers.command, helpers.eq, helpers.neq, helpers.eval, helpers.poke_eventloop
describe('storing global variables in ShaDa files', function()
local tempname = 'Xtest-functional-legacy-074'
@@ -14,19 +12,115 @@ describe('storing global variables in ShaDa files', function()
end)
it('is working', function()
- clear{args_rm={'-i'}, args={'-i', 'Xviminfo'}}
+ clear { args_rm = { '-i' }, args = { '-i', 'Xviminfo' } }
- local test_dict = {foo = 1, bar = 0, longvarible = 1000}
- local test_list = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
- 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
- 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52,
- 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70,
- 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88,
- 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100}
+ local test_dict = { foo = 1, bar = 0, longvarible = 1000 }
+ local test_list = {
+ 1,
+ 2,
+ 3,
+ 4,
+ 5,
+ 6,
+ 7,
+ 8,
+ 9,
+ 10,
+ 11,
+ 12,
+ 13,
+ 14,
+ 15,
+ 16,
+ 17,
+ 18,
+ 19,
+ 20,
+ 21,
+ 22,
+ 23,
+ 24,
+ 25,
+ 26,
+ 27,
+ 28,
+ 29,
+ 30,
+ 31,
+ 32,
+ 33,
+ 34,
+ 35,
+ 36,
+ 37,
+ 38,
+ 39,
+ 40,
+ 41,
+ 42,
+ 43,
+ 44,
+ 45,
+ 46,
+ 47,
+ 48,
+ 49,
+ 50,
+ 51,
+ 52,
+ 53,
+ 54,
+ 55,
+ 56,
+ 57,
+ 58,
+ 59,
+ 60,
+ 61,
+ 62,
+ 63,
+ 64,
+ 65,
+ 66,
+ 67,
+ 68,
+ 69,
+ 70,
+ 71,
+ 72,
+ 73,
+ 74,
+ 75,
+ 76,
+ 77,
+ 78,
+ 79,
+ 80,
+ 81,
+ 82,
+ 83,
+ 84,
+ 85,
+ 86,
+ 87,
+ 88,
+ 89,
+ 90,
+ 91,
+ 92,
+ 93,
+ 94,
+ 95,
+ 96,
+ 97,
+ 98,
+ 99,
+ 100,
+ }
command('set visualbell')
command('set shada+=!')
- command('let MY_GLOBAL_DICT={\'foo\': 1, \'bar\': 0, \'longvarible\': 1000}')
+ command("let MY_GLOBAL_DICT={'foo': 1, 'bar': 0, 'longvarible': 1000}")
-- Store a really long list. Initially this was testing line wrapping in
-- viminfo, but shada files has no line wrapping, no matter how long the
-- list is.
@@ -39,7 +133,7 @@ describe('storing global variables in ShaDa files', function()
poke_eventloop()
-- Assert that the shada file exists.
- neq(nil, luv.fs_stat(tempname))
+ neq(nil, vim.uv.fs_stat(tempname))
command('unlet MY_GLOBAL_DICT')
command('unlet MY_GLOBAL_LIST')
-- Assert that the variables where deleted.
diff --git a/test/functional/legacy/078_swapfile_recover_spec.lua b/test/functional/legacy/078_swapfile_recover_spec.lua
index 45f0aed37a..dc5b1a8540 100644
--- a/test/functional/legacy/078_swapfile_recover_spec.lua
+++ b/test/functional/legacy/078_swapfile_recover_spec.lua
@@ -9,8 +9,8 @@ local clear, expect, source = helpers.clear, helpers.expect, helpers.source
describe('78', function()
setup(clear)
teardown(function()
- os.remove(".Xtest.swp")
- os.remove(".Xtest.swo")
+ os.remove('.Xtest.swp')
+ os.remove('.Xtest.swo')
end)
it('is working', function()
diff --git a/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua b/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua
index 54620c7104..5e9c131c64 100644
--- a/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua
+++ b/test/functional/legacy/083_tag_search_with_file_encoding_spec.lua
@@ -1,11 +1,11 @@
-- Tests for tag search with !_TAG_FILE_ENCODING.
local helpers = require('test.functional.helpers')(after_each)
-local insert, source, clear, expect, write_file = helpers.insert,
- helpers.source, helpers.clear, helpers.expect, helpers.write_file
+local insert, source, clear, expect, write_file =
+ helpers.insert, helpers.source, helpers.clear, helpers.expect, helpers.write_file
local function has_iconv()
- clear() -- ensures session
+ clear() -- ensures session
return 1 == helpers.eval('has("iconv")')
end
@@ -18,14 +18,17 @@ describe('tag search with !_TAG_FILE_ENCODING', function()
write_file('Xtags1.txt', 'text for tags1\nabcdefghijklmnopqrs\n')
write_file('Xtags2.txt', 'text for tags2\nABC\n')
write_file('Xtags3.txt', 'text for tags3\nABC\n')
- write_file('Xtags1', [[
+ write_file(
+ 'Xtags1',
+ [[
!_TAG_FILE_ENCODING utf-8 //
abcdefghijklmnopqrs Xtags1.txt /abcdefghijklmnopqrs
- ]])
- write_file('test83-tags2',
- '!_TAG_FILE_ENCODING cp932 //\n' ..
- '\130`\130a\130b Xtags2.txt /\130`\130a\130b\n'
- )
+ ]]
+ )
+ write_file(
+ 'test83-tags2',
+ '!_TAG_FILE_ENCODING cp932 //\n' .. '\130`\130a\130b Xtags2.txt /\130`\130a\130b\n'
+ )
-- The last file is very long but repetitive and can be generated on the
-- fly.
local text = helpers.dedent([[
@@ -51,7 +54,6 @@ describe('tag search with !_TAG_FILE_ENCODING', function()
pending('skipped (missing iconv)', function() end)
else
it('is working', function()
-
insert('Results of test83')
-- Case1:
diff --git a/test/functional/legacy/090_sha256_spec.lua b/test/functional/legacy/090_sha256_spec.lua
index e364af9400..701b777df1 100644
--- a/test/functional/legacy/090_sha256_spec.lua
+++ b/test/functional/legacy/090_sha256_spec.lua
@@ -8,7 +8,7 @@ describe('sha256()', function()
setup(clear)
it('is working', function()
- insert("start:")
+ insert('start:')
source([[
let testcase='test for empty string: '
diff --git a/test/functional/legacy/091_context_variables_spec.lua b/test/functional/legacy/091_context_variables_spec.lua
index c08a58e14b..3b9fdf740f 100644
--- a/test/functional/legacy/091_context_variables_spec.lua
+++ b/test/functional/legacy/091_context_variables_spec.lua
@@ -8,7 +8,7 @@ describe('context variables', function()
setup(clear)
it('is working', function()
- insert("start:")
+ insert('start:')
-- Test for getbufvar().
-- Use strings to test for memory leaks.
diff --git a/test/functional/legacy/096_location_list_spec.lua b/test/functional/legacy/096_location_list_spec.lua
index b21a2085f6..2817d5d240 100644
--- a/test/functional/legacy/096_location_list_spec.lua
+++ b/test/functional/legacy/096_location_list_spec.lua
@@ -45,20 +45,18 @@ describe('location list', function()
setl readonly
exe 'doautocmd BufRead ' . substitute(a:name, '\v^test://(.*)', '\1', '')
endfunction
- ]] ..
-
- -- Register the above buffer setup function to be executed before
- -- starting to edit a new "test protocol" buffer.
- [[
+ ]]
+ -- Register the above buffer setup function to be executed before
+ -- starting to edit a new "test protocol" buffer.
+ .. [[
augroup testgroup
au!
autocmd BufReadCmd test://* call ReadTestProtocol(expand("<amatch>"))
augroup END
- ]] ..
-
- -- Populate the location list of the current window with some test
- -- protocol file locations such as "test://foo.txt".
- [[
+ ]]
+ -- Populate the location list of the current window with some test
+ -- protocol file locations such as "test://foo.txt".
+ .. [[
let words = [ "foo", "bar", "baz", "quux", "shmoo", "spam", "eggs" ]
let qflist = []
for word in words
@@ -68,11 +66,12 @@ describe('location list', function()
" valid.
call setloclist(0, qflist, ' ')
endfor
- ]])
+ ]]
+ )
-- Set up the result buffer.
command('enew')
- command('w! '..test_file)
+ command('w! ' .. test_file)
command('b 1')
-- Test A.
@@ -99,14 +98,16 @@ describe('location list', function()
command([[let locationListFileName = substitute(getline(line('.')), '\([^|]*\)|.*', '\1', '')]])
command('wincmd n')
command('wincmd K')
- command('b '..test_file)
+ command('b ' .. test_file)
-- Prepare test output and write it to the result buffer.
command([[let fileName = substitute(fileName, '\\', '/', 'g')]])
command([[let locationListFileName = substitute(locationListFileName, '\\', '/', 'g')]])
command([[call append(line('$'), "Test A:")]])
command([[call append(line('$'), " - file name displayed: " . fileName)]])
- command([[call append(line('$'), " - quickfix claims that the file name displayed is: " . locationListFileName)]])
+ command(
+ [[call append(line('$'), " - quickfix claims that the file name displayed is: " . locationListFileName)]]
+ )
command('w')
-- Clean slate for the next test.
@@ -132,7 +133,7 @@ describe('location list', function()
command('let numberOfWindowsOpen = winnr("$")')
command('wincmd n')
command('wincmd K')
- command('b '..test_file)
+ command('b ' .. test_file)
-- Prepare test output and write it to the result buffer.
command('call append(line("$"), "Test B:")')
@@ -170,12 +171,14 @@ describe('location list', function()
command('let bufferName = expand("%")')
command('wincmd n')
command('wincmd K')
- command('b '..test_file)
+ command('b ' .. test_file)
-- Prepare test output and write it to the result buffer.
command([[let bufferName = substitute(bufferName, '\\', '/', 'g')]])
command([[call append(line("$"), "Test C:")]])
- command([[call append(line('$'), " - 'buftype' of the location list window: " . locationListWindowBufType)]])
+ command(
+ [[call append(line('$'), " - 'buftype' of the location list window: " . locationListWindowBufType)]]
+ )
command([[call append(line('$'), " - buffer displayed in the 2nd window: " . bufferName)]])
command('w')
command('wincmd o')
diff --git a/test/functional/legacy/097_glob_path_spec.lua b/test/functional/legacy/097_glob_path_spec.lua
index a62dc4d4c8..b335b3bf41 100644
--- a/test/functional/legacy/097_glob_path_spec.lua
+++ b/test/functional/legacy/097_glob_path_spec.lua
@@ -11,13 +11,13 @@ describe('glob() and globpath()', function()
setup(function()
if helpers.is_os('win') then
- os.execute("md sautest\\autoload")
- os.execute(".>sautest\\autoload\\Test104.vim 2>nul")
- os.execute(".>sautest\\autoload\\footest.vim 2>nul")
+ os.execute('md sautest\\autoload')
+ os.execute('.>sautest\\autoload\\Test104.vim 2>nul')
+ os.execute('.>sautest\\autoload\\footest.vim 2>nul')
else
- os.execute("mkdir -p sautest/autoload")
- os.execute("touch sautest/autoload/Test104.vim")
- os.execute("touch sautest/autoload/footest.vim")
+ os.execute('mkdir -p sautest/autoload')
+ os.execute('touch sautest/autoload/Test104.vim')
+ os.execute('touch sautest/autoload/footest.vim')
end
end)
@@ -76,7 +76,7 @@ describe('glob() and globpath()', function()
os.execute('del /q/f Xxx{ Xxx$')
os.execute('rd /q /s sautest')
else
- os.execute("rm -rf sautest Xxx{ Xxx$")
+ os.execute('rm -rf sautest Xxx{ Xxx$')
end
end)
end)
diff --git a/test/functional/legacy/102_fnameescape_spec.lua b/test/functional/legacy/102_fnameescape_spec.lua
index c8ee423ff3..11bdbd7c9c 100644
--- a/test/functional/legacy/102_fnameescape_spec.lua
+++ b/test/functional/legacy/102_fnameescape_spec.lua
@@ -20,7 +20,7 @@ describe('fnameescape', function()
end)
teardown(function()
- os.remove("Xspa ce")
- os.remove("Xemark!")
+ os.remove('Xspa ce')
+ os.remove('Xemark!')
end)
end)
diff --git a/test/functional/legacy/106_errorformat_spec.lua b/test/functional/legacy/106_errorformat_spec.lua
index 3f017a704f..2a83d48c07 100644
--- a/test/functional/legacy/106_errorformat_spec.lua
+++ b/test/functional/legacy/106_errorformat_spec.lua
@@ -8,7 +8,7 @@ describe('errorformat', function()
setup(clear)
it('is working', function()
- command("set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#")
+ command('set efm=%EEEE%m,%WWWW%m,%+CCCC%.%#,%-GGGG%.%#')
command("cgetexpr ['WWWW', 'EEEE', 'CCCC']")
command("$put =strtrans(string(map(getqflist(), '[v:val.text, v:val.valid]')))")
command("cgetexpr ['WWWW', 'GGGG', 'EEEE', 'CCCC']")
diff --git a/test/functional/legacy/107_adjust_window_and_contents_spec.lua b/test/functional/legacy/107_adjust_window_and_contents_spec.lua
index 841eeef0af..5a8fdda32d 100644
--- a/test/functional/legacy/107_adjust_window_and_contents_spec.lua
+++ b/test/functional/legacy/107_adjust_window_and_contents_spec.lua
@@ -50,15 +50,7 @@ describe('107', function()
[1, '1 '] |
[50, '50 '] |
^[59, '59 '] |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*9
3 more lines |
]])
end)
diff --git a/test/functional/legacy/108_backtrace_debug_commands_spec.lua b/test/functional/legacy/108_backtrace_debug_commands_spec.lua
index 1c1a2095d5..ccdd0cd2be 100644
--- a/test/functional/legacy/108_backtrace_debug_commands_spec.lua
+++ b/test/functional/legacy/108_backtrace_debug_commands_spec.lua
@@ -9,7 +9,7 @@ describe('108', function()
before_each(clear)
it('is working', function()
- command("set shortmess-=F")
+ command('set shortmess-=F')
feed_command('lang mess C')
feed_command('function! Foo()')
feed_command(' let var1 = 1')
diff --git a/test/functional/legacy/arglist_spec.lua b/test/functional/legacy/arglist_spec.lua
index a15809907b..3e78d7ca5f 100644
--- a/test/functional/legacy/arglist_spec.lua
+++ b/test/functional/legacy/arglist_spec.lua
@@ -33,10 +33,7 @@ describe('argument list commands', function()
feed('N')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
|
]])
feed(':confirm quit\n')
diff --git a/test/functional/legacy/assert_spec.lua b/test/functional/legacy/assert_spec.lua
index d49d7d665a..04c90281a7 100644
--- a/test/functional/legacy/assert_spec.lua
+++ b/test/functional/legacy/assert_spec.lua
@@ -1,20 +1,19 @@
local helpers = require('test.functional.helpers')(after_each)
-local nvim, call = helpers.meths, helpers.call
+local nvim, call = helpers.api, helpers.call
local clear, eq = helpers.clear, helpers.eq
local source, command = helpers.source, helpers.command
local exc_exec = helpers.exc_exec
local eval = helpers.eval
local function expected_errors(errors)
- eq(errors, nvim.get_vvar('errors'))
+ eq(errors, nvim.nvim_get_vvar('errors'))
end
local function expected_empty()
- eq({}, nvim.get_vvar('errors'))
+ eq({}, nvim.nvim_get_vvar('errors'))
end
describe('assert function:', function()
-
before_each(function()
clear()
end)
@@ -39,24 +38,24 @@ describe('assert function:', function()
end)
it('should change v:errors when expected is not equal to actual', function()
- eq(1, call('assert_equal', 0, {0}))
- expected_errors({'Expected 0 but got [0]'})
+ eq(1, call('assert_equal', 0, { 0 }))
+ expected_errors({ 'Expected 0 but got [0]' })
end)
it('should change v:errors when expected is not equal to actual', function()
- eq(1, call('assert_equal', 0, "0"))
- expected_errors({"Expected 0 but got '0'"})
+ eq(1, call('assert_equal', 0, '0'))
+ expected_errors({ "Expected 0 but got '0'" })
end)
it('should change v:errors when expected is not equal to actual', function()
-- Lua does not tell integer from float.
command('call assert_equal(1, 1.0)')
- expected_errors({'Expected 1 but got 1.0'})
+ expected_errors({ 'Expected 1 but got 1.0' })
end)
it('should change v:errors when expected is not equal to actual', function()
call('assert_equal', 'true', 'false')
- expected_errors({"Expected 'true' but got 'false'"})
+ expected_errors({ "Expected 'true' but got 'false'" })
end)
it('should change v:errors when expected is not equal to actual', function()
@@ -69,8 +68,10 @@ describe('assert function:', function()
call assert_equal(s:w, '')
endfunction
]])
- eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
- exc_exec('call CheckAssert()'))
+ eq(
+ 'Vim(call):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('call CheckAssert()')
+ )
end)
end)
@@ -84,12 +85,12 @@ describe('assert function:', function()
it('should change v:errors when actual is not false', function()
eq(1, call('assert_false', 1))
- expected_errors({'Expected False but got 1'})
+ expected_errors({ 'Expected False but got 1' })
end)
it('should change v:errors when actual is not false', function()
call('assert_false', {})
- expected_errors({'Expected False but got []'})
+ expected_errors({ 'Expected False but got []' })
end)
end)
@@ -97,14 +98,14 @@ describe('assert function:', function()
describe('assert_true', function()
it('should not change v:errors when actual is true', function()
eq(0, call('assert_true', 1))
- eq(0, call('assert_true', -1)) -- In Vim script, non-zero Numbers are TRUE.
+ eq(0, call('assert_true', -1)) -- In Vim script, non-zero Numbers are TRUE.
eq(0, call('assert_true', true))
expected_empty()
end)
it('should change v:errors when actual is not true', function()
eq(1, call('assert_true', 1.5))
- expected_errors({'Expected True but got 1.5'})
+ expected_errors({ 'Expected True but got 1.5' })
end)
end)
@@ -145,7 +146,7 @@ describe('assert function:', function()
call assert_true('', 'file two')
]])
expected_errors({
- "nvim_exec2(): equal assertion failed: Expected 1 but got 100",
+ 'nvim_exec2(): equal assertion failed: Expected 1 but got 100',
"nvim_exec2(): true assertion failed: Expected False but got 'true'",
"nvim_exec2(): false assertion failed: Expected True but got 'false'",
"nvim_exec2(): file two: Expected True but got ''",
@@ -162,7 +163,7 @@ describe('assert function:', function()
it('should change v:errors when cmd succeeds', function()
eq(1, eval([[assert_fails('call empty("")', '')]]))
- expected_errors({'command did not fail: call empty("")'})
+ expected_errors({ 'command did not fail: call empty("")' })
end)
end)
end)
diff --git a/test/functional/legacy/autochdir_spec.lua b/test/functional/legacy/autochdir_spec.lua
index 5da54b4850..e5980f5942 100644
--- a/test/functional/legacy/autochdir_spec.lua
+++ b/test/functional/legacy/autochdir_spec.lua
@@ -1,11 +1,11 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, eq, matches = helpers.clear, helpers.eq, helpers.matches
-local eval, command, call, meths = helpers.eval, helpers.command, helpers.call, helpers.meths
+local eval, command, call, api = helpers.eval, helpers.command, helpers.call, helpers.api
local source, exec_capture = helpers.source, helpers.exec_capture
local mkdir = helpers.mkdir
local function expected_empty()
- eq({}, meths.get_vvar('errors'))
+ eq({}, api.nvim_get_vvar('errors'))
end
describe('autochdir behavior', function()
@@ -25,13 +25,13 @@ describe('autochdir behavior', function()
it('sets filename', function()
command('set acd')
command('new')
- command('w '..dir..'/Xtest')
+ command('w ' .. dir .. '/Xtest')
eq('Xtest', eval("expand('%')"))
eq(dir, eval([[substitute(getcwd(), '.*/\(\k*\)', '\1', '')]]))
end)
it(':file in win_execute() does not cause wrong directory', function()
- command('cd '..dir)
+ command('cd ' .. dir)
source([[
func Test_set_filename_other_window()
let cwd = getcwd()
@@ -64,53 +64,53 @@ describe('autochdir behavior', function()
it('win_execute() does not change directory', function()
local subdir = 'Xfile'
- command('cd '..dir)
+ command('cd ' .. dir)
command('set acd')
call('mkdir', subdir)
local winid = eval('win_getid()')
- command('new '..subdir..'/file')
- matches(dir..'/'..subdir..'$', eval('getcwd()'))
+ command('new ' .. subdir .. '/file')
+ matches(dir .. '/' .. subdir .. '$', eval('getcwd()'))
command('cd ..')
- matches(dir..'$', eval('getcwd()'))
+ matches(dir .. '$', eval('getcwd()'))
call('win_execute', winid, 'echo')
- matches(dir..'$', eval('getcwd()'))
+ matches(dir .. '$', eval('getcwd()'))
end)
it(':verbose pwd shows whether autochdir is used', function()
local subdir = 'Xautodir'
- command('cd '..dir)
+ command('cd ' .. dir)
local cwd = eval('getcwd()')
command('edit global.txt')
- matches('%[global%].*'..dir..'$', exec_capture('verbose pwd'))
+ matches('%[global%].*' .. dir .. '$', exec_capture('verbose pwd'))
call('mkdir', subdir)
- command('split '..subdir..'/local.txt')
- command('lcd '..subdir)
- matches('%[window%].*'..dir..'/'..subdir..'$', exec_capture('verbose pwd'))
+ command('split ' .. subdir .. '/local.txt')
+ command('lcd ' .. subdir)
+ matches('%[window%].*' .. dir .. '/' .. subdir .. '$', exec_capture('verbose pwd'))
command('set acd')
command('wincmd w')
- matches('%[autochdir%].*'..dir..'$', exec_capture('verbose pwd'))
- command('tcd '..cwd)
- matches('%[tabpage%].*'..dir..'$', exec_capture('verbose pwd'))
- command('cd '..cwd)
- matches('%[global%].*'..dir..'$', exec_capture('verbose pwd'))
- command('lcd '..cwd)
- matches('%[window%].*'..dir..'$', exec_capture('verbose pwd'))
+ matches('%[autochdir%].*' .. dir .. '$', exec_capture('verbose pwd'))
+ command('tcd ' .. cwd)
+ matches('%[tabpage%].*' .. dir .. '$', exec_capture('verbose pwd'))
+ command('cd ' .. cwd)
+ matches('%[global%].*' .. dir .. '$', exec_capture('verbose pwd'))
+ command('lcd ' .. cwd)
+ matches('%[window%].*' .. dir .. '$', exec_capture('verbose pwd'))
command('edit')
- matches('%[autochdir%].*'..dir..'$', exec_capture('verbose pwd'))
+ matches('%[autochdir%].*' .. dir .. '$', exec_capture('verbose pwd'))
command('enew')
command('wincmd w')
- matches('%[autochdir%].*'..dir..'/'..subdir..'$', exec_capture('verbose pwd'))
+ matches('%[autochdir%].*' .. dir .. '/' .. subdir .. '$', exec_capture('verbose pwd'))
command('wincmd w')
- matches('%[window%].*'..dir..'$', exec_capture('verbose pwd'))
+ matches('%[window%].*' .. dir .. '$', exec_capture('verbose pwd'))
command('wincmd w')
- matches('%[autochdir%].*'..dir..'/'..subdir..'$', exec_capture('verbose pwd'))
+ matches('%[autochdir%].*' .. dir .. '/' .. subdir .. '$', exec_capture('verbose pwd'))
command('set noacd')
- matches('%[autochdir%].*'..dir..'/'..subdir..'$', exec_capture('verbose pwd'))
+ matches('%[autochdir%].*' .. dir .. '/' .. subdir .. '$', exec_capture('verbose pwd'))
command('wincmd w')
- matches('%[window%].*'..dir..'$', exec_capture('verbose pwd'))
- command('cd '..cwd)
- matches('%[global%].*'..dir..'$', exec_capture('verbose pwd'))
+ matches('%[window%].*' .. dir .. '$', exec_capture('verbose pwd'))
+ command('cd ' .. cwd)
+ matches('%[global%].*' .. dir .. '$', exec_capture('verbose pwd'))
command('wincmd w')
- matches('%[window%].*'..dir..'/'..subdir..'$', exec_capture('verbose pwd'))
+ matches('%[window%].*' .. dir .. '/' .. subdir .. '$', exec_capture('verbose pwd'))
end)
end)
diff --git a/test/functional/legacy/autocmd_option_spec.lua b/test/functional/legacy/autocmd_option_spec.lua
index 6034d13e2a..9966df263b 100644
--- a/test/functional/legacy/autocmd_option_spec.lua
+++ b/test/functional/legacy/autocmd_option_spec.lua
@@ -1,8 +1,9 @@
local helpers = require('test.functional.helpers')(after_each)
-local nvim = helpers.meths
+local nvim = helpers.api
local clear, eq, neq, eval = helpers.clear, helpers.eq, helpers.neq, helpers.eval
-local curbuf, buf = helpers.curbuf, helpers.bufmeths
-local curwin = helpers.curwin
+local api = helpers.api
+local curbuf = helpers.api.nvim_get_current_buf
+local curwin = helpers.api.nvim_get_current_win
local exec_capture = helpers.exec_capture
local source, command = helpers.source, helpers.command
@@ -29,9 +30,7 @@ end
local function set_hook(pattern)
command(
- 'au OptionSet '
- .. pattern ..
- ' :call AutoCommand(expand("<amatch>"), bufnr("%"), winnr())'
+ 'au OptionSet ' .. pattern .. ' :call AutoCommand(expand("<amatch>"), bufnr("%"), winnr())'
)
end
@@ -40,26 +39,26 @@ local function init_var()
end
local function get_result()
- local ret = nvim.get_var('ret')
+ local ret = nvim.nvim_get_var('ret')
init_var()
return ret
end
local function expected_table(option, oldval, oldval_l, oldval_g, newval, scope, cmd, attr)
return {
- option = option,
- oldval = oldval,
+ option = option,
+ oldval = oldval,
oldval_l = oldval_l,
oldval_g = oldval_g,
- newval = newval,
- scope = scope,
- cmd = cmd,
- attr = attr,
+ newval = newval,
+ scope = scope,
+ cmd = cmd,
+ attr = attr,
}
end
local function expected_combination(...)
- local args = {...}
+ local args = { ... }
local ret = get_result()
if not (#args == #ret) then
@@ -119,7 +118,6 @@ end
describe('au OptionSet', function()
describe('with any option (*)', function()
-
before_each(function()
clear()
declare_hook_function()
@@ -129,44 +127,44 @@ describe('au OptionSet', function()
it('should be called in setting number option', function()
command('set nu')
- expected_combination({'number', false, false, false, true, 'global', 'set'})
+ expected_combination({ 'number', false, false, false, true, 'global', 'set' })
command('setlocal nonu')
- expected_combination({'number', true, true, '', false, 'local', 'setlocal'})
+ expected_combination({ 'number', true, true, '', false, 'local', 'setlocal' })
command('setglobal nonu')
- expected_combination({'number', true, '', true, false, 'global', 'setglobal'})
+ expected_combination({ 'number', true, '', true, false, 'global', 'setglobal' })
end)
- it('should be called in setting autoindent option',function()
+ it('should be called in setting autoindent option', function()
command('setlocal ai')
- expected_combination({'autoindent', false, false, '', true, 'local', 'setlocal'})
+ expected_combination({ 'autoindent', false, false, '', true, 'local', 'setlocal' })
command('setglobal ai')
- expected_combination({'autoindent', false, '', false, true, 'global', 'setglobal'})
+ expected_combination({ 'autoindent', false, '', false, true, 'global', 'setglobal' })
command('set noai')
- expected_combination({'autoindent', true, true, true, false, 'global', 'set'})
+ expected_combination({ 'autoindent', true, true, true, false, 'global', 'set' })
end)
- it('should be called in inverting global autoindent option',function()
+ it('should be called in inverting global autoindent option', function()
command('set ai!')
- expected_combination({'autoindent', false, false, false, true, 'global', 'set'})
+ expected_combination({ 'autoindent', false, false, false, true, 'global', 'set' })
end)
- it('should be called in being unset local autoindent option',function()
+ it('should be called in being unset local autoindent option', function()
command('setlocal ai')
- expected_combination({'autoindent', false, false, '', true, 'local', 'setlocal'})
+ expected_combination({ 'autoindent', false, false, '', true, 'local', 'setlocal' })
command('setlocal ai<')
- expected_combination({'autoindent', true, true, '', false, 'local', 'setlocal'})
+ expected_combination({ 'autoindent', true, true, '', false, 'local', 'setlocal' })
end)
- it('should be called in setting global list and number option at the same time',function()
+ it('should be called in setting global list and number option at the same time', function()
command('set list nu')
expected_combination(
- {'list', false, false, false, true, 'global', 'set'},
- {'number', false, false, false, true, 'global', 'set'}
+ { 'list', false, false, false, true, 'global', 'set' },
+ { 'number', false, false, false, true, 'global', 'set' }
)
end)
@@ -177,27 +175,27 @@ describe('au OptionSet', function()
it('should be called in setting local acd', function()
command('setlocal acd')
- expected_combination({'autochdir', false, false, '', true, 'local', 'setlocal'})
+ expected_combination({ 'autochdir', false, false, '', true, 'local', 'setlocal' })
end)
it('should be called in setting autoread', function()
command('set noar')
- expected_combination({'autoread', true, true, true, false, 'global', 'set'})
+ expected_combination({ 'autoread', true, true, true, false, 'global', 'set' })
command('setlocal ar')
- expected_combination({'autoread', false, false, '', true, 'local', 'setlocal'})
+ expected_combination({ 'autoread', false, false, '', true, 'local', 'setlocal' })
end)
it('should be called in inverting global autoread', function()
command('setglobal invar')
- expected_combination({'autoread', true, '', true, false, 'global', 'setglobal'})
+ expected_combination({ 'autoread', true, '', true, false, 'global', 'setglobal' })
end)
it('should be called in setting backspace option through :let', function()
local oldval = eval('&backspace')
command('let &bs=""')
- expected_combination({'backspace', oldval, oldval, oldval, '', 'global', 'set'})
+ expected_combination({ 'backspace', oldval, oldval, oldval, '', 'global', 'set' })
end)
describe('being set by setbufvar()', function()
@@ -208,15 +206,24 @@ describe('au OptionSet', function()
it('should trigger using correct option name', function()
command('call setbufvar(1, "&backup", 1)')
- expected_combination({'backup', false, false, '', true, 'local', 'setlocal'})
+ expected_combination({ 'backup', false, false, '', true, 'local', 'setlocal' })
end)
it('should trigger if the current buffer is different from the targeted buffer', function()
local new_buffer = make_buffer()
- local new_bufnr = buf.get_number(new_buffer)
+ local new_bufnr = api.nvim_buf_get_number(new_buffer)
command('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")')
- expected_combination({'buftype', '', '', '', 'nofile', 'local', 'setlocal', {bufnr = new_bufnr}})
+ expected_combination({
+ 'buftype',
+ '',
+ '',
+ '',
+ 'nofile',
+ 'local',
+ 'setlocal',
+ { bufnr = new_bufnr },
+ })
end)
end)
@@ -224,24 +231,30 @@ describe('au OptionSet', function()
local oldval = eval('&backupext')
command('set backupext=foo')
- expected_combination({'backupext', oldval, oldval, oldval, 'foo', 'global', 'set'})
+ expected_combination({ 'backupext', oldval, oldval, oldval, 'foo', 'global', 'set' })
command('set backupext&')
- expected_combination({'backupext', 'foo', 'foo', 'foo', oldval, 'global', 'set'})
+ expected_combination({ 'backupext', 'foo', 'foo', 'foo', oldval, 'global', 'set' })
command('setglobal backupext=bar')
- expected_combination({'backupext', oldval, '', oldval, 'bar', 'global', 'setglobal'})
+ expected_combination({ 'backupext', oldval, '', oldval, 'bar', 'global', 'setglobal' })
command('noa set backupext&')
-- As this is a global option this sets the global value even though :setlocal is used!
command('setlocal backupext=baz')
- expected_combination({'backupext', oldval, oldval, '', 'baz', 'local', 'setlocal'})
+ expected_combination({ 'backupext', oldval, oldval, '', 'baz', 'local', 'setlocal' })
command('noa setglobal backupext=ext_global')
command('noa setlocal backupext=ext_local') -- Sets the global(!) value
command('set backupext=foo')
expected_combination({
- 'backupext', 'ext_local', 'ext_local', 'ext_local', 'foo', 'global', 'set'
+ 'backupext',
+ 'ext_local',
+ 'ext_local',
+ 'ext_local',
+ 'foo',
+ 'global',
+ 'set',
})
end)
@@ -249,16 +262,16 @@ describe('au OptionSet', function()
local oldval = eval('&tags')
command('set tags=tagpath')
- expected_combination({'tags', oldval, oldval, oldval, 'tagpath', 'global', 'set'})
+ expected_combination({ 'tags', oldval, oldval, oldval, 'tagpath', 'global', 'set' })
command('set tags&')
- expected_combination({'tags', 'tagpath', 'tagpath', 'tagpath', oldval, 'global', 'set'})
+ expected_combination({ 'tags', 'tagpath', 'tagpath', 'tagpath', oldval, 'global', 'set' })
command('setglobal tags=tagpath1')
- expected_combination({'tags', oldval, '', oldval, 'tagpath1', 'global', 'setglobal'})
+ expected_combination({ 'tags', oldval, '', oldval, 'tagpath1', 'global', 'setglobal' })
command('setlocal tags=tagpath2')
- expected_combination({'tags', 'tagpath1', 'tagpath1', '', 'tagpath2', 'local', 'setlocal'})
+ expected_combination({ 'tags', 'tagpath1', 'tagpath1', '', 'tagpath2', 'local', 'setlocal' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
@@ -266,7 +279,13 @@ describe('au OptionSet', function()
command('noa setlocal tags=tag_local')
command('set tags=tagpath')
expected_combination({
- 'tags', 'tag_global', 'tag_local', 'tag_global', 'tagpath', 'global', 'set'
+ 'tags',
+ 'tag_global',
+ 'tag_local',
+ 'tag_global',
+ 'tagpath',
+ 'global',
+ 'set',
})
-- Note: v:option_old is the old global value for global-local options.
@@ -274,26 +293,48 @@ describe('au OptionSet', function()
command('noa set tags=tag_global')
command('noa setlocal tags=')
command('set tags=tagpath')
- expected_combination({'tags', 'tag_global', 'tag_global', 'tag_global', 'tagpath', 'global', 'set'})
+ expected_combination({
+ 'tags',
+ 'tag_global',
+ 'tag_global',
+ 'tag_global',
+ 'tagpath',
+ 'global',
+ 'set',
+ })
end)
it('with string local (to buffer) option', function()
local oldval = eval('&spelllang')
command('set spelllang=elvish,klingon')
- expected_combination({'spelllang', oldval, oldval, oldval, 'elvish,klingon', 'global', 'set'})
+ expected_combination({
+ 'spelllang',
+ oldval,
+ oldval,
+ oldval,
+ 'elvish,klingon',
+ 'global',
+ 'set',
+ })
command('set spelllang&')
expected_combination({
- 'spelllang', 'elvish,klingon', 'elvish,klingon', 'elvish,klingon', oldval, 'global', 'set'
+ 'spelllang',
+ 'elvish,klingon',
+ 'elvish,klingon',
+ 'elvish,klingon',
+ oldval,
+ 'global',
+ 'set',
})
command('setglobal spelllang=elvish')
- expected_combination({'spelllang', oldval, '', oldval, 'elvish', 'global', 'setglobal'})
+ expected_combination({ 'spelllang', oldval, '', oldval, 'elvish', 'global', 'setglobal' })
command('noa set spelllang&')
command('setlocal spelllang=klingon')
- expected_combination({'spelllang', oldval, oldval, '', 'klingon', 'local', 'setlocal'})
+ expected_combination({ 'spelllang', oldval, oldval, '', 'klingon', 'local', 'setlocal' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
@@ -301,7 +342,13 @@ describe('au OptionSet', function()
command('noa setlocal spelllang=spelllocal')
command('set spelllang=foo')
expected_combination({
- 'spelllang', 'spelllocal', 'spelllocal', 'spellglobal', 'foo', 'global', 'set'
+ 'spelllang',
+ 'spelllocal',
+ 'spelllocal',
+ 'spellglobal',
+ 'foo',
+ 'global',
+ 'set',
})
end)
@@ -309,259 +356,257 @@ describe('au OptionSet', function()
local oldval = eval('&statusline')
command('set statusline=foo')
- expected_combination({'statusline', oldval, oldval, '', 'foo', 'global', 'set'})
+ expected_combination({ 'statusline', oldval, oldval, '', 'foo', 'global', 'set' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
command('set statusline&')
- expected_combination({'statusline', 'foo', 'foo', 'foo', oldval, 'global', 'set'})
+ expected_combination({ 'statusline', 'foo', 'foo', 'foo', oldval, 'global', 'set' })
command('setglobal statusline=bar')
- expected_combination({'statusline', oldval, '', oldval, 'bar', 'global', 'setglobal'})
+ expected_combination({ 'statusline', oldval, '', oldval, 'bar', 'global', 'setglobal' })
command('noa set statusline&')
command('setlocal statusline=baz')
- expected_combination({'statusline', oldval, oldval, '', 'baz', 'local', 'setlocal'})
+ expected_combination({ 'statusline', oldval, oldval, '', 'baz', 'local', 'setlocal' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
command('noa setglobal statusline=bar')
command('noa setlocal statusline=baz')
command('set statusline=foo')
- expected_combination({'statusline', 'bar', 'baz', 'bar', 'foo', 'global', 'set'})
+ expected_combination({ 'statusline', 'bar', 'baz', 'bar', 'foo', 'global', 'set' })
end)
it('with string local (to window) option', function()
local oldval = eval('&foldignore')
command('set foldignore=fo')
- expected_combination({'foldignore', oldval, oldval, oldval, 'fo', 'global', 'set'})
+ expected_combination({ 'foldignore', oldval, oldval, oldval, 'fo', 'global', 'set' })
command('set foldignore&')
- expected_combination({'foldignore', 'fo', 'fo', 'fo', oldval, 'global', 'set'})
+ expected_combination({ 'foldignore', 'fo', 'fo', 'fo', oldval, 'global', 'set' })
command('setglobal foldignore=bar')
- expected_combination({'foldignore', oldval, '', oldval, 'bar', 'global', 'setglobal'})
+ expected_combination({ 'foldignore', oldval, '', oldval, 'bar', 'global', 'setglobal' })
command('noa set foldignore&')
command('setlocal foldignore=baz')
- expected_combination({'foldignore', oldval, oldval, '', 'baz', 'local', 'setlocal'})
+ expected_combination({ 'foldignore', oldval, oldval, '', 'baz', 'local', 'setlocal' })
command('noa setglobal foldignore=glob')
command('noa setlocal foldignore=loc')
command('set foldignore=fo')
- expected_combination({'foldignore', 'loc', 'loc', 'glob', 'fo', 'global', 'set'})
+ expected_combination({ 'foldignore', 'loc', 'loc', 'glob', 'fo', 'global', 'set' })
end)
it('with number global option', function()
command('noa setglobal cmdheight=8')
command('noa setlocal cmdheight=1') -- Sets the global(!) value
command('setglobal cmdheight=2')
- expected_combination({'cmdheight', 1, '', 1, 2, 'global', 'setglobal'})
+ expected_combination({ 'cmdheight', 1, '', 1, 2, 'global', 'setglobal' })
command('noa setglobal cmdheight=8')
command('noa setlocal cmdheight=1') -- Sets the global(!) value
command('setlocal cmdheight=2')
- expected_combination({'cmdheight', 1, 1, '', 2, 'local', 'setlocal'})
+ expected_combination({ 'cmdheight', 1, 1, '', 2, 'local', 'setlocal' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
command('noa setglobal cmdheight=8')
command('noa setlocal cmdheight=1') -- Sets the global(!) value
command('set cmdheight=2')
- expected_combination({'cmdheight', 1, 1, 1, 2, 'global', 'set'})
+ expected_combination({ 'cmdheight', 1, 1, 1, 2, 'global', 'set' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
command('noa set cmdheight=8')
command('set cmdheight=2')
- expected_combination({'cmdheight', 8, 8, 8, 2, 'global', 'set'})
+ expected_combination({ 'cmdheight', 8, 8, 8, 2, 'global', 'set' })
end)
it('with number global-local (to buffer) option', function()
command('noa setglobal undolevels=8')
command('noa setlocal undolevels=1')
command('setglobal undolevels=2')
- expected_combination({'undolevels', 8, '', 8, 2, 'global', 'setglobal'})
+ expected_combination({ 'undolevels', 8, '', 8, 2, 'global', 'setglobal' })
command('noa setglobal undolevels=8')
command('noa setlocal undolevels=1')
command('setlocal undolevels=2')
- expected_combination({'undolevels', 1, 1, '', 2, 'local', 'setlocal'})
+ expected_combination({ 'undolevels', 1, 1, '', 2, 'local', 'setlocal' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
command('noa setglobal undolevels=8')
command('noa setlocal undolevels=1')
command('set undolevels=2')
- expected_combination({'undolevels', 8, 1, 8, 2, 'global', 'set'})
+ expected_combination({ 'undolevels', 8, 1, 8, 2, 'global', 'set' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
command('noa set undolevels=8')
command('set undolevels=2')
- expected_combination({'undolevels', 8, 8, 8, 2, 'global', 'set'})
+ expected_combination({ 'undolevels', 8, 8, 8, 2, 'global', 'set' })
end)
it('with number local (to buffer) option', function()
command('noa setglobal wrapmargin=8')
command('noa setlocal wrapmargin=1')
command('setglobal wrapmargin=2')
- expected_combination({'wrapmargin', 8, '', 8, 2, 'global', 'setglobal'})
+ expected_combination({ 'wrapmargin', 8, '', 8, 2, 'global', 'setglobal' })
command('noa setglobal wrapmargin=8')
command('noa setlocal wrapmargin=1')
command('setlocal wrapmargin=2')
- expected_combination({'wrapmargin', 1, 1, '', 2, 'local', 'setlocal'})
+ expected_combination({ 'wrapmargin', 1, 1, '', 2, 'local', 'setlocal' })
command('noa setglobal wrapmargin=8')
command('noa setlocal wrapmargin=1')
command('set wrapmargin=2')
- expected_combination({'wrapmargin', 1, 1, 8, 2, 'global', 'set'})
+ expected_combination({ 'wrapmargin', 1, 1, 8, 2, 'global', 'set' })
command('noa set wrapmargin=8')
command('set wrapmargin=2')
- expected_combination({'wrapmargin', 8, 8, 8, 2, 'global', 'set'})
+ expected_combination({ 'wrapmargin', 8, 8, 8, 2, 'global', 'set' })
end)
it('with number global-local (to window) option', function()
command('noa setglobal scrolloff=8')
command('noa setlocal scrolloff=1')
command('setglobal scrolloff=2')
- expected_combination({'scrolloff', 8, '', 8, 2, 'global', 'setglobal'})
+ expected_combination({ 'scrolloff', 8, '', 8, 2, 'global', 'setglobal' })
command('noa setglobal scrolloff=8')
command('noa setlocal scrolloff=1')
command('setlocal scrolloff=2')
- expected_combination({'scrolloff', 1, 1, '', 2, 'local', 'setlocal'})
+ expected_combination({ 'scrolloff', 1, 1, '', 2, 'local', 'setlocal' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
command('noa setglobal scrolloff=8')
command('noa setlocal scrolloff=1')
command('set scrolloff=2')
- expected_combination({'scrolloff', 8, 1, 8, 2, 'global', 'set'})
+ expected_combination({ 'scrolloff', 8, 1, 8, 2, 'global', 'set' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
command('noa set scrolloff=8')
command('set scrolloff=2')
- expected_combination({'scrolloff', 8, 8, 8, 2, 'global', 'set'})
+ expected_combination({ 'scrolloff', 8, 8, 8, 2, 'global', 'set' })
end)
it('with number local (to window) option', function()
command('noa setglobal foldcolumn=8')
command('noa setlocal foldcolumn=1')
command('setglobal foldcolumn=2')
- expected_combination({'foldcolumn', '8', '', '8', '2', 'global', 'setglobal'})
+ expected_combination({ 'foldcolumn', '8', '', '8', '2', 'global', 'setglobal' })
command('noa setglobal foldcolumn=8')
command('noa setlocal foldcolumn=1')
command('setlocal foldcolumn=2')
- expected_combination({'foldcolumn', '1', '1', '', '2', 'local', 'setlocal'})
+ expected_combination({ 'foldcolumn', '1', '1', '', '2', 'local', 'setlocal' })
command('noa setglobal foldcolumn=8')
command('noa setlocal foldcolumn=1')
command('set foldcolumn=2')
- expected_combination({'foldcolumn', '1', '1', '8', '2', 'global', 'set'})
+ expected_combination({ 'foldcolumn', '1', '1', '8', '2', 'global', 'set' })
command('noa set foldcolumn=8')
command('set foldcolumn=2')
- expected_combination({'foldcolumn', '8', '8', '8', '2', 'global', 'set'})
+ expected_combination({ 'foldcolumn', '8', '8', '8', '2', 'global', 'set' })
end)
it('with boolean global option', function()
command('noa setglobal nowrapscan')
command('noa setlocal wrapscan') -- Sets the global(!) value
command('setglobal nowrapscan')
- expected_combination({'wrapscan', true, '', true, false, 'global', 'setglobal'})
+ expected_combination({ 'wrapscan', true, '', true, false, 'global', 'setglobal' })
command('noa setglobal nowrapscan')
command('noa setlocal wrapscan') -- Sets the global(!) value
command('setlocal nowrapscan')
- expected_combination({'wrapscan', true, true, '', false, 'local', 'setlocal'})
+ expected_combination({ 'wrapscan', true, true, '', false, 'local', 'setlocal' })
command('noa setglobal nowrapscan')
command('noa setlocal wrapscan') -- Sets the global(!) value
command('set nowrapscan')
- expected_combination({'wrapscan', true, true, true, false, 'global', 'set'})
+ expected_combination({ 'wrapscan', true, true, true, false, 'global', 'set' })
command('noa set nowrapscan')
command('set wrapscan')
- expected_combination({'wrapscan', false, false, false, true, 'global', 'set'})
+ expected_combination({ 'wrapscan', false, false, false, true, 'global', 'set' })
end)
it('with boolean global-local (to buffer) option', function()
command('noa setglobal noautoread')
command('noa setlocal autoread')
command('setglobal autoread')
- expected_combination({'autoread', false, '', false, true, 'global', 'setglobal'})
+ expected_combination({ 'autoread', false, '', false, true, 'global', 'setglobal' })
command('noa setglobal noautoread')
command('noa setlocal autoread')
command('setlocal noautoread')
- expected_combination({'autoread', true, true, '', false, 'local', 'setlocal'})
+ expected_combination({ 'autoread', true, true, '', false, 'local', 'setlocal' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
command('noa setglobal noautoread')
command('noa setlocal autoread')
command('set autoread')
- expected_combination({'autoread', false, true, false, true, 'global', 'set'})
+ expected_combination({ 'autoread', false, true, false, true, 'global', 'set' })
-- Note: v:option_old is the old global value for global-local options.
-- but the old local value for all other kinds of options.
command('noa set noautoread')
command('set autoread')
- expected_combination({'autoread', false, false, false, true, 'global', 'set'})
+ expected_combination({ 'autoread', false, false, false, true, 'global', 'set' })
end)
it('with boolean local (to buffer) option', function()
command('noa setglobal nocindent')
command('noa setlocal cindent')
command('setglobal cindent')
- expected_combination({'cindent', false, '', false, true, 'global', 'setglobal'})
+ expected_combination({ 'cindent', false, '', false, true, 'global', 'setglobal' })
command('noa setglobal nocindent')
command('noa setlocal cindent')
command('setlocal nocindent')
- expected_combination({'cindent', true, true, '', false, 'local', 'setlocal'})
+ expected_combination({ 'cindent', true, true, '', false, 'local', 'setlocal' })
command('noa setglobal nocindent')
command('noa setlocal cindent')
command('set cindent')
- expected_combination({'cindent', true, true, false, true, 'global', 'set'})
+ expected_combination({ 'cindent', true, true, false, true, 'global', 'set' })
command('noa set nocindent')
command('set cindent')
- expected_combination({'cindent', false, false, false, true, 'global', 'set'})
+ expected_combination({ 'cindent', false, false, false, true, 'global', 'set' })
end)
it('with boolean local (to window) option', function()
command('noa setglobal nocursorcolumn')
command('noa setlocal cursorcolumn')
command('setglobal cursorcolumn')
- expected_combination({'cursorcolumn', false, '', false, true, 'global', 'setglobal'})
+ expected_combination({ 'cursorcolumn', false, '', false, true, 'global', 'setglobal' })
command('noa setglobal nocursorcolumn')
command('noa setlocal cursorcolumn')
command('setlocal nocursorcolumn')
- expected_combination({'cursorcolumn', true, true, '', false, 'local', 'setlocal'})
+ expected_combination({ 'cursorcolumn', true, true, '', false, 'local', 'setlocal' })
command('noa setglobal nocursorcolumn')
command('noa setlocal cursorcolumn')
command('set cursorcolumn')
- expected_combination({'cursorcolumn', true, true, false, true, 'global', 'set'})
+ expected_combination({ 'cursorcolumn', true, true, false, true, 'global', 'set' })
command('noa set nocursorcolumn')
command('set cursorcolumn')
- expected_combination({'cursorcolumn', false, false, false, true, 'global', 'set'})
+ expected_combination({ 'cursorcolumn', false, false, false, true, 'global', 'set' })
end)
-
end)
describe('with specific option', function()
-
before_each(function()
clear()
declare_hook_function()
@@ -575,13 +620,13 @@ describe('au OptionSet', function()
expected_empty()
command('setlocal ro')
- expected_combination({'readonly', false, false, '', true, 'local', 'setlocal'})
+ expected_combination({ 'readonly', false, false, '', true, 'local', 'setlocal' })
command('setglobal ro')
- expected_combination({'readonly', false, '', false, true, 'global', 'setglobal'})
+ expected_combination({ 'readonly', false, '', false, true, 'global', 'setglobal' })
command('set noro')
- expected_combination({'readonly', true, true, true, false, 'global', 'set'})
+ expected_combination({ 'readonly', true, true, true, false, 'global', 'set' })
end)
describe('being set by setbufvar()', function()
@@ -596,18 +641,26 @@ describe('au OptionSet', function()
set_hook('backup')
command('call setbufvar(1, "&backup", 1)')
- expected_combination({'backup', false, false, '', true, 'local', 'setlocal'})
+ expected_combination({ 'backup', false, false, '', true, 'local', 'setlocal' })
end)
it('should trigger if the current buffer is different from the targeted buffer', function()
set_hook('buftype')
local new_buffer = make_buffer()
- local new_bufnr = buf.get_number(new_buffer)
+ local new_bufnr = api.nvim_buf_get_number(new_buffer)
command('call setbufvar(' .. new_bufnr .. ', "&buftype", "nofile")')
- expected_combination({ 'buftype', '', '', '', 'nofile', 'local', 'setlocal',
- { bufnr = new_bufnr } })
+ expected_combination({
+ 'buftype',
+ '',
+ '',
+ '',
+ 'nofile',
+ 'local',
+ 'setlocal',
+ { bufnr = new_bufnr },
+ })
end)
end)
@@ -623,43 +676,54 @@ describe('au OptionSet', function()
set_hook('backup')
command('call setwinvar(1, "&backup", 1)')
- expected_combination({'backup', false, false, '', true, 'local', 'setlocal'})
+ expected_combination({ 'backup', false, false, '', true, 'local', 'setlocal' })
end)
- it('should not trigger if the current window is different from the targeted window', function()
- set_hook('cursorcolumn')
+ it(
+ 'should not trigger if the current window is different from the targeted window',
+ function()
+ set_hook('cursorcolumn')
- local new_winnr = get_new_window_number()
+ local new_winnr = get_new_window_number()
- command('call setwinvar(' .. new_winnr .. ', "&cursorcolumn", 1)')
- -- expected_combination({'cursorcolumn', false, true, 'local', {winnr = new_winnr}})
- expected_empty()
- end)
+ command('call setwinvar(' .. new_winnr .. ', "&cursorcolumn", 1)')
+ -- expected_combination({'cursorcolumn', false, true, 'local', {winnr = new_winnr}})
+ expected_empty()
+ end
+ )
end)
describe('being set by neovim api', function()
it('should trigger if a boolean option be set globally', function()
set_hook('autochdir')
- nvim.set_option_value('autochdir', true, {scope='global'})
- eq(true, nvim.get_option_value('autochdir', {scope='global'}))
- expected_combination({'autochdir', false, '', false, true, 'global', 'setglobal'})
+ nvim.nvim_set_option_value('autochdir', true, { scope = 'global' })
+ eq(true, nvim.nvim_get_option_value('autochdir', { scope = 'global' }))
+ expected_combination({ 'autochdir', false, '', false, true, 'global', 'setglobal' })
end)
it('should trigger if a number option be set globally', function()
set_hook('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'})
+ nvim.nvim_set_option_value('cmdheight', 5, { scope = 'global' })
+ eq(5, nvim.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_value('ambiwidth', 'double', {scope='global'})
- eq('double', nvim.get_option_value('ambiwidth', {scope='global'}))
- expected_combination({'ambiwidth', 'single', '', 'single', 'double', 'global', 'setglobal'})
+ nvim.nvim_set_option_value('ambiwidth', 'double', { scope = 'global' })
+ eq('double', nvim.nvim_get_option_value('ambiwidth', { scope = 'global' }))
+ expected_combination({
+ 'ambiwidth',
+ 'single',
+ '',
+ 'single',
+ 'double',
+ 'global',
+ 'setglobal',
+ })
end)
end)
end)
diff --git a/test/functional/legacy/autocmd_spec.lua b/test/functional/legacy/autocmd_spec.lua
new file mode 100644
index 0000000000..97051f3d3f
--- /dev/null
+++ b/test/functional/legacy/autocmd_spec.lua
@@ -0,0 +1,40 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local write_file = helpers.write_file
+local command = helpers.command
+local feed = helpers.feed
+local api = helpers.api
+local eq = helpers.eq
+
+before_each(clear)
+
+-- oldtest: Test_autocmd_invalidates_undo_on_textchanged()
+it('no E440 in quickfix window when autocommand invalidates undo', function()
+ write_file(
+ 'XTest_autocmd_invalidates_undo_on_textchanged',
+ [[
+ set hidden
+ " create quickfix list (at least 2 lines to move line)
+ vimgrep /u/j %
+
+ " enter quickfix window
+ cwindow
+
+ " set modifiable
+ setlocal modifiable
+
+ " set autocmd to clear quickfix list
+
+ autocmd! TextChanged <buffer> call setqflist([])
+ " move line
+ move+1
+ ]]
+ )
+ finally(function()
+ os.remove('XTest_autocmd_invalidates_undo_on_textchanged')
+ end)
+ command('edit XTest_autocmd_invalidates_undo_on_textchanged')
+ command('so %')
+ feed('G')
+ eq('', api.nvim_get_vvar('errmsg'))
+end)
diff --git a/test/functional/legacy/breakindent_spec.lua b/test/functional/legacy/breakindent_spec.lua
index 3913ba935a..cf0065f394 100644
--- a/test/functional/legacy/breakindent_spec.lua
+++ b/test/functional/legacy/breakindent_spec.lua
@@ -12,9 +12,9 @@ describe('breakindent', function()
it('cursor shown at correct position with showbreak', function()
local screen = Screen.new(75, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue}, -- SignColumn
- [2] = {bold = true}, -- ModeMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue }, -- SignColumn
+ [2] = { bold = true }, -- ModeMsg
})
screen:attach()
exec([[
@@ -26,13 +26,12 @@ describe('breakindent', function()
eval repeat('x', &columns - leftcol - 1)->setline(1)
eval 'second line'->setline(2)
]])
+
feed('AX')
screen:expect([[
{1: }xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX|
{1: }^second line |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2:-- INSERT --} |
]])
-- No line wraps, so changing 'showbreak' should lead to the same screen.
@@ -43,22 +42,75 @@ describe('breakindent', function()
screen:expect_unchanged()
-- The first line now wraps because of "eol" in 'listchars'.
command('setlocal list')
- screen:expect{grid=[[
+ screen:expect([[
{1: }xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX|
{1: } {0:+^$} |
{1: }second line{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:-- INSERT --} |
- ]]}
+ ]])
command('setlocal nobreakindent')
- screen:expect{grid=[[
+ screen:expect([[
{1: }xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxX|
{1: }{0:+^$} |
{1: }second line{0:$} |
+ {0:~ }|*2
+ {2:-- INSERT --} |
+ ]])
+ end)
+
+ -- oldtest: Test_visual_starts_before_skipcol()
+ it('Visual selection that starts before skipcol shows correctly', function()
+ local screen = Screen.new(75, 6)
+ exec([[
+ 1new
+ setlocal breakindent
+ call setline(1, "\t" .. join(range(100)))
+ ]])
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual
+ [2] = { bold = true, reverse = true }, -- StatusLine
+ [3] = { reverse = true }, -- StatusLineNC
+ [4] = { bold = true }, -- ModeMsg
+ })
+ screen:attach()
+
+ feed('v$')
+ screen:expect([[
+ {0:<<<} {1: 93 94 95 96 97 98 99}^ |
+ {2:[No Name] [+] }|
+ |
{0:~ }|
+ {3:[No Name] }|
+ {4:-- VISUAL --} |
+ ]])
+ command('setlocal showbreak=+++')
+ screen:expect([[
+ {0:+++}{1: 90 91 92 93 94 95 96 97 98 99}^ |
+ {2:[No Name] [+] }|
+ |
{0:~ }|
- {2:-- INSERT --} |
- ]]}
+ {3:[No Name] }|
+ {4:-- VISUAL --} |
+ ]])
+ command('setlocal breakindentopt+=sbr')
+ screen:expect([[
+ {0:+++} {1: 93 94 95 96 97 98 99}^ |
+ {2:[No Name] [+] }|
+ |
+ {0:~ }|
+ {3:[No Name] }|
+ {4:-- VISUAL --} |
+ ]])
+ command('setlocal nobreakindent')
+ screen:expect([[
+ {0:+++}{1: 98 99}^ |
+ {2:[No Name] [+] }|
+ |
+ {0:~ }|
+ {3:[No Name] }|
+ {4:-- VISUAL --} |
+ ]])
end)
end)
diff --git a/test/functional/legacy/buffer_spec.lua b/test/functional/legacy/buffer_spec.lua
index 1e8909f0d0..b3964540f0 100644
--- a/test/functional/legacy/buffer_spec.lua
+++ b/test/functional/legacy/buffer_spec.lua
@@ -1,16 +1,16 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, source = helpers.clear, helpers.source
-local call, eq, meths = helpers.call, helpers.eq, helpers.meths
+local call, eq, api = helpers.call, helpers.eq, helpers.api
local function expected_empty()
- eq({}, meths.get_vvar('errors'))
+ eq({}, api.nvim_get_vvar('errors'))
end
describe('buffer', function()
before_each(function()
clear()
- meths.ui_attach(80, 24, {})
- meths.set_option_value('hidden', false, {})
+ api.nvim_ui_attach(80, 24, {})
+ api.nvim_set_option_value('hidden', false, {})
end)
it('deleting a modified buffer with :confirm', function()
diff --git a/test/functional/legacy/changelist_spec.lua b/test/functional/legacy/changelist_spec.lua
index 72c9872163..b673e74128 100644
--- a/test/functional/legacy/changelist_spec.lua
+++ b/test/functional/legacy/changelist_spec.lua
@@ -9,7 +9,7 @@ describe('changelist', function()
setup(clear)
it('is working', function()
- insert("1\n2")
+ insert('1\n2')
feed('Gkylp')
feed_command('set ul=100')
diff --git a/test/functional/legacy/close_count_spec.lua b/test/functional/legacy/close_count_spec.lua
index 60ae155fbf..930dae668a 100644
--- a/test/functional/legacy/close_count_spec.lua
+++ b/test/functional/legacy/close_count_spec.lua
@@ -19,20 +19,20 @@ describe('close_count', function()
command('close!')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({6, 5, 4, 2, 1}, eval('buffers'))
+ eq({ 6, 5, 4, 2, 1 }, eval('buffers'))
command('1close!')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({5, 4, 2, 1}, eval('buffers'))
+ eq({ 5, 4, 2, 1 }, eval('buffers'))
command('$close!')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({5, 4, 2}, eval('buffers'))
+ eq({ 5, 4, 2 }, eval('buffers'))
command('1wincmd w')
command('2close!')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({5, 2}, eval('buffers'))
+ eq({ 5, 2 }, eval('buffers'))
command('1wincmd w')
command('new')
command('new')
@@ -40,37 +40,37 @@ describe('close_count', function()
command('-1close!')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({7, 5, 2}, eval('buffers'))
+ eq({ 7, 5, 2 }, eval('buffers'))
command('2wincmd w')
command('+1close!')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({7, 5}, eval('buffers'))
+ eq({ 7, 5 }, eval('buffers'))
command('only!')
command('b1')
command('let tests = []')
command('for i in range(5)|new|endfor')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({13, 12, 11, 10, 9, 1}, eval('buffers'))
+ eq({ 13, 12, 11, 10, 9, 1 }, eval('buffers'))
command('4wincmd w')
command('.hide')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({13, 12, 11, 9, 1}, eval('buffers'))
+ eq({ 13, 12, 11, 9, 1 }, eval('buffers'))
command('1hide')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({12, 11, 9, 1}, eval('buffers'))
+ eq({ 12, 11, 9, 1 }, eval('buffers'))
command('$hide')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({12, 11, 9}, eval('buffers'))
+ eq({ 12, 11, 9 }, eval('buffers'))
command('1wincmd w')
command('2hide')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({12, 9}, eval('buffers'))
+ eq({ 12, 9 }, eval('buffers'))
command('1wincmd w')
command('new')
command('new')
@@ -78,12 +78,12 @@ describe('close_count', function()
command('-hide')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({15, 12, 9}, eval('buffers'))
+ eq({ 15, 12, 9 }, eval('buffers'))
command('2wincmd w')
command('+hide')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({15, 12}, eval('buffers'))
+ eq({ 15, 12 }, eval('buffers'))
command('only!')
command('b1')
command('let tests = []')
@@ -93,16 +93,16 @@ describe('close_count', function()
command('$ hide')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({20, 19, 18, 17, 16}, eval('buffers'))
+ eq({ 20, 19, 18, 17, 16 }, eval('buffers'))
command('$-1 close!')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({20, 19, 18, 16}, eval('buffers'))
+ eq({ 20, 19, 18, 16 }, eval('buffers'))
command('1wincmd w')
command('.+close!')
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({20, 18, 16}, eval('buffers'))
+ eq({ 20, 18, 16 }, eval('buffers'))
command('only!')
command('b1')
command('let tests = []')
@@ -113,22 +113,22 @@ describe('close_count', function()
poke_eventloop()
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({25, 24, 23, 21, 1}, eval('buffers'))
+ eq({ 25, 24, 23, 21, 1 }, eval('buffers'))
feed('1<C-W>c<cr>')
poke_eventloop()
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({24, 23, 21, 1}, eval('buffers'))
+ eq({ 24, 23, 21, 1 }, eval('buffers'))
feed('9<C-W>c<cr>')
poke_eventloop()
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({24, 23, 21}, eval('buffers'))
+ eq({ 24, 23, 21 }, eval('buffers'))
command('1wincmd w')
feed('2<C-W>c<cr>')
poke_eventloop()
command('let buffers = []')
command('windo call add(buffers, bufnr("%"))')
- eq({24, 21}, eval('buffers'))
+ eq({ 24, 21 }, eval('buffers'))
end)
end)
diff --git a/test/functional/legacy/cmdline_spec.lua b/test/functional/legacy/cmdline_spec.lua
index 3cbff2a01b..8c94451f9a 100644
--- a/test/functional/legacy/cmdline_spec.lua
+++ b/test/functional/legacy/cmdline_spec.lua
@@ -5,8 +5,8 @@ local command = helpers.command
local feed = helpers.feed
local feed_command = helpers.feed_command
local exec = helpers.exec
-local meths = helpers.meths
-local pesc = helpers.pesc
+local api = helpers.api
+local pesc = vim.pesc
describe('cmdline', function()
before_each(clear)
@@ -16,10 +16,10 @@ describe('cmdline', function()
local screen = Screen.new(30, 10)
screen:attach()
screen:set_default_attr_ids {
- [1] = {underline = true, background = Screen.colors.LightGrey};
- [2] = {bold = true};
- [3] = {reverse = true};
- [4] = {bold = true, foreground = Screen.colors.Blue1};
+ [1] = { underline = true, background = Screen.colors.LightGrey },
+ [2] = { bold = true },
+ [3] = { reverse = true },
+ [4] = { bold = true, foreground = Screen.colors.Blue1 },
}
feed_command([[call setline(1, range(30))]])
@@ -37,35 +37,28 @@ describe('cmdline', function()
]])
feed [[:tabnew<cr>]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: + [No Name] }{2: [No Name] }{3: }{1:X}|
^ |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*7
:tabnew |
- ]]}
+ ]],
+ }
feed [[<C-w>-<C-w>-]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: + [No Name] }{2: [No Name] }{3: }{1:X}|
^ |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- |
- |
- |
- ]]}
+ {4:~ }|*5
+ |*3
+ ]],
+ }
feed [[gt]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2: + [No Name] }{1: [No Name] }{3: }{1:X}|
^0 |
1 |
@@ -76,20 +69,15 @@ describe('cmdline', function()
6 |
7 |
|
- ]]}
+ ]],
+ }
feed [[gt]]
screen:expect([[
{1: + [No Name] }{2: [No Name] }{3: }{1:X}|
^ |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- |
- |
- |
+ {4:~ }|*5
+ |*3
]])
end)
@@ -105,8 +93,7 @@ describe('cmdline', function()
feed_command('DoSomething')
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
|
Executing: DoSomething |
Executing: echo 'hello' |set ts=4 |let v = '123' |echo v |
@@ -123,8 +110,8 @@ describe('cmdline', function()
it('tabline is redrawn on entering cmdline', function()
local screen = Screen.new(30, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {reverse = true}, -- TabLineFill
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { reverse = true }, -- TabLineFill
})
screen:attach()
exec([[
@@ -135,9 +122,7 @@ describe('cmdline', function()
screen:expect([[
{1:foo }|
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
:^ |
]])
end)
@@ -146,7 +131,7 @@ describe('cmdline', function()
it('cmdline cursor position is correct after :redraw with cmdheight=2', function()
local screen = Screen.new(30, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
})
screen:attach()
exec([[
@@ -156,9 +141,7 @@ describe('cmdline', function()
feed(':for i in range(3)<CR>')
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
:for i in range(3) |
: ^ |
]])
@@ -166,9 +149,7 @@ describe('cmdline', function()
-- Note: this may still be considered broken, ref #18140
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
: :let i =^ |
|
]])
@@ -177,8 +158,8 @@ describe('cmdline', function()
it("setting 'cmdheight' works after outputting two messages vim-patch:9.0.0665", function()
local screen = Screen.new(60, 8)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, reverse = true}, -- StatusLine
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, reverse = true }, -- StatusLine
})
screen:attach()
exec([[
@@ -194,22 +175,14 @@ describe('cmdline', function()
feed(':call EchoTwo()')
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{1:[No Name] }|
:call EchoTwo()^ |
]])
feed('<CR>')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{1:[No Name] }|
|
]])
@@ -219,22 +192,19 @@ describe('cmdline', function()
it("changing 'cmdheight' when there is a tabline", function()
local screen = Screen.new(60, 8)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, reverse = true}, -- StatusLine
- [2] = {bold = true}, -- TabLineSel
- [3] = {reverse = true}, -- TabLineFill
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, reverse = true }, -- StatusLine
+ [2] = { bold = true }, -- TabLineSel
+ [3] = { reverse = true }, -- TabLineFill
})
screen:attach()
- meths.set_option_value('laststatus', 2, {})
- meths.set_option_value('showtabline', 2, {})
- meths.set_option_value('cmdheight', 1, {})
+ api.nvim_set_option_value('laststatus', 2, {})
+ api.nvim_set_option_value('showtabline', 2, {})
+ api.nvim_set_option_value('cmdheight', 1, {})
screen:expect([[
{2: [No Name] }{3: }|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{1:[No Name] }|
|
]])
@@ -244,13 +214,13 @@ describe('cmdline', function()
it("ruler has correct position with 'rulerformat' set", function()
local screen = Screen.new(20, 3)
screen:set_default_attr_ids {
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
}
screen:attach()
- meths.set_option_value('ruler', true, {})
- meths.set_option_value('rulerformat', 'longish', {})
- meths.set_option_value('laststatus', 0, {})
- meths.set_option_value('winwidth', 1, {})
+ api.nvim_set_option_value('ruler', true, {})
+ api.nvim_set_option_value('rulerformat', 'longish', {})
+ api.nvim_set_option_value('laststatus', 0, {})
+ api.nvim_set_option_value('winwidth', 1, {})
feed [[<C-W>v<C-W>|<C-W>p]]
screen:expect [[
│^ |
@@ -267,72 +237,41 @@ describe('cmdwin', function()
it('still uses a new buffer when interrupting more prompt on open', function()
local screen = Screen.new(30, 16)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, reverse = true}, -- StatusLine
- [2] = {reverse = true}, -- StatusLineNC
- [3] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
- [4] = {bold = true}, -- ModeMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, reverse = true }, -- StatusLine
+ [2] = { reverse = true }, -- StatusLineNC
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
+ [4] = { bold = true }, -- ModeMsg
})
screen:attach()
command('set more')
command('autocmd WinNew * highlight')
feed('q:')
- screen:expect({any = pesc('{3:-- More --}^')})
+ screen:expect({ any = pesc('{3:-- More --}^') })
feed('q')
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{2:[No Name] }|
{0::}^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
{1:[Command Line] }|
|
]])
feed([[aecho 'done']])
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{2:[No Name] }|
{0::}echo 'done'^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
{1:[Command Line] }|
{4:-- INSERT --} |
]])
feed('<CR>')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*14
done |
]])
end)
diff --git a/test/functional/legacy/conceal_spec.lua b/test/functional/legacy/conceal_spec.lua
index 6aaa93f886..9a23d16c5b 100644
--- a/test/functional/legacy/conceal_spec.lua
+++ b/test/functional/legacy/conceal_spec.lua
@@ -6,7 +6,7 @@ local exec = helpers.exec
local feed = helpers.feed
local expect_pos = function(row, col)
- return helpers.eq({row, col}, helpers.eval('[screenrow(), screencol()]'))
+ return helpers.eq({ row, col }, helpers.eval('[screenrow(), screencol()]'))
end
describe('Conceal', function()
@@ -19,10 +19,10 @@ describe('Conceal', function()
it('works', function()
local screen = Screen.new(75, 12)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, reverse = true}, -- StatusLine
- [2] = {reverse = true}, -- StatusLineNC, IncSearch
- [3] = {bold = true}, -- ModeMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, reverse = true }, -- StatusLine
+ [2] = { reverse = true }, -- StatusLineNC, IncSearch
+ [3] = { bold = true }, -- ModeMsg
})
screen:attach()
exec([[
@@ -386,9 +386,9 @@ describe('Conceal', function()
it('CursorColumn and ColorColumn on wrapped line', function()
local screen = Screen.new(40, 10)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.Grey90}, -- CursorColumn
- [2] = {background = Screen.colors.LightRed}, -- ColorColumn
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.Grey90 }, -- CursorColumn
+ [2] = { background = Screen.colors.LightRed }, -- ColorColumn
})
screen:attach()
-- Check that cursorcolumn and colorcolumn don't get broken in presence of
@@ -416,10 +416,7 @@ describe('Conceal', function()
two two two two |hidden| ^here two two |
three three three three {1:t}hree |
{0: >>> }thre{2:e} three three three |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
/here |
]])
@@ -431,10 +428,7 @@ describe('Conceal', function()
two two two two |hidden| here two tw^o |
three three three three three |
{0: >>> }thre{2:e} three three three |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
/here |
]])
end)
@@ -443,8 +437,8 @@ describe('Conceal', function()
it('resize editor', function()
local screen = Screen.new(75, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {foreground = Screen.colors.Blue}, -- Comment
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { foreground = Screen.colors.Blue }, -- Comment
})
screen:attach()
exec([[
@@ -455,21 +449,14 @@ describe('Conceal', function()
]])
screen:expect([[
one two three four five, the ^backticks should be concealed |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
screen:try_resize(75, 7)
screen:expect([[
one two three four five, the ^backticks should be concealed |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end)
@@ -478,7 +465,7 @@ describe('Conceal', function()
it('with linebreak', function()
local screen = Screen.new(75, 8)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
})
screen:attach()
exec([[
@@ -501,8 +488,7 @@ describe('Conceal', function()
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
{0:+ }bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
{0:+ }cccccc |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
diff --git a/test/functional/legacy/cpoptions_spec.lua b/test/functional/legacy/cpoptions_spec.lua
index d2f382ec12..288146199a 100644
--- a/test/functional/legacy/cpoptions_spec.lua
+++ b/test/functional/legacy/cpoptions_spec.lua
@@ -15,19 +15,13 @@ describe('cpoptions', function()
feed('c2w')
screen:expect([[
^one tw$ three |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
-- INSERT -- |
]])
feed('vim<Esc>')
screen:expect([[
vi^m three |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
|
]])
end)
diff --git a/test/functional/legacy/crash_spec.lua b/test/functional/legacy/crash_spec.lua
index 5094f81847..094bea253e 100644
--- a/test/functional/legacy/crash_spec.lua
+++ b/test/functional/legacy/crash_spec.lua
@@ -6,7 +6,6 @@ local feed = helpers.feed
before_each(clear)
--- oldtest: Test_crash1()
it('no crash when ending Visual mode while editing buffer closes window', function()
command('new')
command('autocmd ModeChanged v:n ++once close')
@@ -14,3 +13,21 @@ it('no crash when ending Visual mode while editing buffer closes window', functi
command('enew')
assert_alive()
end)
+
+it('no crash when ending Visual mode close the window to switch to', function()
+ command('new')
+ command('autocmd ModeChanged v:n ++once only')
+ feed('v')
+ command('wincmd p')
+ assert_alive()
+end)
+
+it('no crash when truncating overlong message', function()
+ pcall(command, 'source test/old/testdir/crash/vim_msg_trunc_poc')
+ assert_alive()
+end)
+
+it('no crash with very long option error message', function()
+ pcall(command, 'source test/old/testdir/crash/poc_did_set_langmap')
+ assert_alive()
+end)
diff --git a/test/functional/legacy/debugger_spec.lua b/test/functional/legacy/debugger_spec.lua
index e6fb81719f..7ed5e84da6 100644
--- a/test/functional/legacy/debugger_spec.lua
+++ b/test/functional/legacy/debugger_spec.lua
@@ -13,8 +13,8 @@ describe('debugger', function()
before_each(function()
screen = Screen.new(999, 10)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue};
- [1] = {reverse = true, bold = true};
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { reverse = true, bold = true },
})
screen:attach()
end)
@@ -30,20 +30,16 @@ describe('debugger', function()
command(':let g:Xtest_var = 10')
command(':breakadd expr g:Xtest_var')
feed(':source %<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^let g:Xtest_var += 1{MATCH: *}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
+ {0:~{MATCH: *}}|*8
:source %{MATCH: *}|
- ]]}
+ ]],
+ }
feed(':source %<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
let g:Xtest_var += 1{MATCH: *}|
{0:~{MATCH: *}}|
{1:{MATCH: *}}|
@@ -54,22 +50,19 @@ describe('debugger', function()
{MATCH:.*}XdebugBreakExpr.vim{MATCH: *}|
line 1: let g:Xtest_var += 1{MATCH: *}|
>^{MATCH: *}|
- ]]}
+ ]],
+ }
feed('cont<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^let g:Xtest_var += 1{MATCH: *}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
- {0:~{MATCH: *}}|
+ {0:~{MATCH: *}}|*8
{MATCH: *}|
- ]]}
+ ]],
+ }
feed(':source %<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
let g:Xtest_var += 1{MATCH: *}|
{0:~{MATCH: *}}|
{1:{MATCH: *}}|
@@ -80,6 +73,7 @@ describe('debugger', function()
{MATCH:.*}XdebugBreakExpr.vim{MATCH: *}|
line 1: let g:Xtest_var += 1{MATCH: *}|
>^{MATCH: *}|
- ]]}
+ ]],
+ }
end)
end)
diff --git a/test/functional/legacy/delete_spec.lua b/test/functional/legacy/delete_spec.lua
index 1b9ec9af62..1227065af2 100644
--- a/test/functional/legacy/delete_spec.lua
+++ b/test/functional/legacy/delete_spec.lua
@@ -49,9 +49,9 @@ describe('Test for delete()', function()
it('symlink directory delete', function()
command("call mkdir('Xdir1')")
if helpers.is_os('win') then
- command("silent !mklink /j Xlink Xdir1")
+ command('silent !mklink /j Xlink Xdir1')
else
- command("silent !ln -s Xdir1 Xlink")
+ command('silent !ln -s Xdir1 Xlink')
end
eq(1, eval("isdirectory('Xdir1')"))
eq(1, eval("isdirectory('Xlink')"))
diff --git a/test/functional/legacy/digraph_spec.lua b/test/functional/legacy/digraph_spec.lua
index 7eeb83eb5f..015f144b74 100644
--- a/test/functional/legacy/digraph_spec.lua
+++ b/test/functional/legacy/digraph_spec.lua
@@ -10,36 +10,27 @@ describe('digraph', function()
it('characters displayed on the screen', function()
local screen = Screen.new(10, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {foreground = Screen.colors.Blue}, -- SpecialKey
- [2] = {bold = true}, -- ModeMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { foreground = Screen.colors.Blue }, -- SpecialKey
+ [2] = { bold = true }, -- ModeMsg
})
screen:attach()
feed('i<C-K>')
screen:expect([[
{1:^?} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:-- INSERT --}|
]])
feed('1')
screen:expect([[
{1:^1} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:-- INSERT --}|
]])
feed('2')
screen:expect([[
½^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:-- INSERT --}|
]])
end)
diff --git a/test/functional/legacy/display_spec.lua b/test/functional/legacy/display_spec.lua
index 9c6f521882..153fad2e22 100644
--- a/test/functional/legacy/display_spec.lua
+++ b/test/functional/legacy/display_spec.lua
@@ -14,7 +14,7 @@ describe('display', function()
local screen = Screen.new(20, 4)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true},
+ [1] = { bold = true },
})
command([[call setline(1, repeat('a', 21))]])
@@ -32,9 +32,9 @@ describe('display', function()
local screen = Screen.new(60, 8)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true}, -- ModeMsg
- [2] = {background = Screen.colors.LightGrey}, -- Visual
- [3] = {background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue}, -- SignColumn
+ [1] = { bold = true }, -- ModeMsg
+ [2] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual
+ [3] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue }, -- SignColumn
})
exec([[
@@ -48,12 +48,7 @@ describe('display', function()
feed('VG7kk')
screen:expect([[
{3: }^f{2:oo} |
- {3: }foo |
- {3: }foo |
- {3: }foo |
- {3: }foo |
- {3: }foo |
- {3: }foo |
+ {3: }foo |*6
{1:-- VISUAL LINE --} |
]])
end)
@@ -61,9 +56,9 @@ describe('display', function()
local function run_test_display_lastline(euro)
local screen = Screen.new(75, 10)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {bold = true, reverse = true}, -- StatusLine
- [3] = {reverse = true}, -- StatusLineNC
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { bold = true, reverse = true }, -- StatusLine
+ [3] = { reverse = true }, -- StatusLineNC
})
screen:attach()
exec([[
@@ -80,12 +75,9 @@ describe('display', function()
end
screen:expect((([[
^a│aaa |
- a│bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- a│bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ a│bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|*2
b│bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
- b│{1:~ }|
- b│{1:~ }|
- b│{1:~ }|
+ b│{1:~ }|*3
{1:@}│{1:~ }|
{2:< }{3:[No Name] [+] }|
|
@@ -97,12 +89,9 @@ describe('display', function()
command('100wincmd >')
screen:expect((([[
^aaa │a|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb│a|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb│a|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb│a|*2
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb │b|
- {1:~ }│b|
- {1:~ }│b|
- {1:~ }│b|
+ {1:~ }│b|*3
{1:~ }│{1:@}|
{2:[No Name] [+] }{3:<}|
|
@@ -119,8 +108,7 @@ describe('display', function()
{1:@@@ }|
{2:[No Name] [+] }|
aaa |
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|*2
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
{3:[No Name] [+] }|
|
@@ -133,9 +121,7 @@ describe('display', function()
a │bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
bb│bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
bb│bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
- bb│{1:~ }|
- bb│{1:~ }|
- bb│{1:~ }|
+ bb│{1:~ }|*3
{1:@@}│{1:~ }|
{2:< }{3:[No Name] [+] }|
|
@@ -164,17 +150,7 @@ describe('display', function()
feed('736|')
screen:expect([[
<<<aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|*11
^aaaaaaaaaaaaaaa |
|
]])
@@ -182,16 +158,7 @@ describe('display', function()
feed('D')
screen:expect([[
<<<aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|*10
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^a|
bbbbb bbbbb bbbbb bbbbb bbbbb bb@@@|
|
@@ -205,29 +172,14 @@ describe('display', function()
bbbbb ccccc ccccc ccccc ccccc cccc|
c ccccc ccccc ddddd ddddd ddddd ddd|
dd ddddd ddddd ddddd |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*8
|
]])
-- "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|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|*9
aa^a |
bbbbb bbbbb bbbbb bbbbb bbbbb bbbbb|
bbbbb ccccc ccccc ccccc ccccc cccc|
@@ -246,11 +198,7 @@ describe('display', function()
]])
screen:expect([[
<<<bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|*5
b^b |
|
]])
@@ -260,12 +208,7 @@ describe('display', function()
feed('$0')
screen:expect([[
<<<b^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|*6
|
]])
-- Going to the start of the line with "b" did not set w_skipcol correctly with 'smoothscroll'.
@@ -273,24 +216,14 @@ describe('display', function()
feed('$b')
screen:expect([[
2 b ^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|*6
|
]])
-- Same for "ge".
feed('$ge')
screen:expect([[
2 ^b bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|*6
|
]])
end)
diff --git a/test/functional/legacy/edit_spec.lua b/test/functional/legacy/edit_spec.lua
index 939999e21b..0762e5e671 100644
--- a/test/functional/legacy/edit_spec.lua
+++ b/test/functional/legacy/edit_spec.lua
@@ -4,7 +4,7 @@ local clear = helpers.clear
local command = helpers.command
local expect = helpers.expect
local feed = helpers.feed
-local sleep = helpers.sleep
+local sleep = vim.uv.sleep
before_each(clear)
@@ -31,27 +31,21 @@ describe('edit', function()
it('inserting a register using CTRL-R', function()
local screen = Screen.new(10, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {foreground = Screen.colors.Blue}, -- SpecialKey
- [2] = {bold = true}, -- ModeMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { foreground = Screen.colors.Blue }, -- SpecialKey
+ [2] = { bold = true }, -- ModeMsg
})
screen:attach()
feed('a<C-R>')
screen:expect([[
{1:^"} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:-- INSERT --}|
]])
feed('=')
screen:expect([[
{1:"} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
=^ |
]])
end)
@@ -60,32 +54,26 @@ describe('edit', function()
it('positioning cursor after CTRL-R expression failed', function()
local screen = Screen.new(60, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {foreground = Screen.colors.Blue}, -- SpecialKey
- [2] = {foreground = Screen.colors.SlateBlue},
- [3] = {bold = true}, -- ModeMsg
- [4] = {reverse = true, bold = true}, -- MsgSeparator
- [5] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- ErrorMsg
- [6] = {foreground = Screen.colors.SeaGreen, bold = true}, -- MoreMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { foreground = Screen.colors.Blue }, -- SpecialKey
+ [2] = { foreground = Screen.colors.SlateBlue },
+ [3] = { bold = true }, -- ModeMsg
+ [4] = { reverse = true, bold = true }, -- MsgSeparator
+ [5] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg
+ [6] = { foreground = Screen.colors.SeaGreen, bold = true }, -- MoreMsg
})
screen:attach()
feed('i<C-R>')
screen:expect([[
{1:^"} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:-- INSERT --} |
]])
feed('={}')
screen:expect([[
{1:"} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
={2:{}}^ |
]])
-- trying to insert a dictionary produces an error
@@ -102,20 +90,14 @@ describe('edit', function()
feed(':')
screen:expect([[
:^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:-- INSERT --} |
]])
-- ending Insert mode should put the cursor back on the ':'
feed('<Esc>')
screen:expect([[
^: |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end)
diff --git a/test/functional/legacy/erasebackword_spec.lua b/test/functional/legacy/erasebackword_spec.lua
index 8ca64df328..46057fe599 100644
--- a/test/functional/legacy/erasebackword_spec.lua
+++ b/test/functional/legacy/erasebackword_spec.lua
@@ -8,7 +8,6 @@ describe('CTRL-W in Insert mode', function()
-- luacheck: ignore 611 (Line contains only whitespaces)
it('works for multi-byte characters', function()
-
for i = 1, 6 do
feed('o wwwã“ã‚“ã«ã¡ã‚世界ワールドvim ' .. string.rep('<C-w>', i) .. '<esc>')
end
diff --git a/test/functional/legacy/eval_spec.lua b/test/functional/legacy/eval_spec.lua
index c531c59fd1..21d0ce118d 100644
--- a/test/functional/legacy/eval_spec.lua
+++ b/test/functional/legacy/eval_spec.lua
@@ -11,7 +11,9 @@ local dedent = helpers.dedent
describe('eval', function()
setup(function()
- write_file('test_eval_setup.vim', [[
+ write_file(
+ 'test_eval_setup.vim',
+ [[
set noswapfile
lang C
@@ -33,7 +35,8 @@ describe('eval', function()
execute "silent normal! Go==\n==\e\"".a:1."P"
endif
endfun
- ]])
+ ]]
+ )
end)
before_each(clear)
teardown(function()
@@ -53,8 +56,8 @@ describe('eval', function()
expect([[
": type v; value: abc (['abc']), expr: abc (['abc'])
- ": type V; value: abc]].."\000 (['abc']), expr: abc\000"..[[ (['abc'])
- ": type V; value: abc]].."\r\000 (['abc\r']), expr: abc\r\000 (['abc\r"..[['])
+ ": type V; value: abc]] .. "\000 (['abc']), expr: abc\000" .. [[ (['abc'])
+ ": type V; value: abc]] .. "\r\000 (['abc\r']), expr: abc\r\000 (['abc\r" .. [['])
=: type v; value: abc (['abc']), expr: "abc" (['"abc"'])]])
end)
@@ -97,29 +100,29 @@ describe('eval', function()
==
=abcB=
{{{2 setreg('c', 'abcC', 'l')
- c: type V; value: abcC]].."\000 (['abcC']), expr: abcC\000"..[[ (['abcC'])
+ c: type V; value: abcC]] .. "\000 (['abcC']), expr: abcC\000" .. [[ (['abcC'])
==
abcC
==
{{{2 setreg('d', 'abcD', 'V')
- d: type V; value: abcD]].."\000 (['abcD']), expr: abcD\000"..[[ (['abcD'])
+ d: type V; value: abcD]] .. "\000 (['abcD']), expr: abcD\000" .. [[ (['abcD'])
==
abcD
==
{{{2 setreg('e', 'abcE', 'b')
- e: type ]]..'\022'..[[4; value: abcE (['abcE']), expr: abcE (['abcE'])
+ e: type ]] .. '\022' .. [[4; value: abcE (['abcE']), expr: abcE (['abcE'])
==
=abcE=
- {{{2 setreg('f', 'abcF', ']]..'\022'..[[')
- f: type ]]..'\022'..[[4; value: abcF (['abcF']), expr: abcF (['abcF'])
+ {{{2 setreg('f', 'abcF', ']] .. '\022' .. [[')
+ f: type ]] .. '\022' .. [[4; value: abcF (['abcF']), expr: abcF (['abcF'])
==
=abcF=
{{{2 setreg('g', 'abcG', 'b10')
- g: type ]]..'\022'..[[10; value: abcG (['abcG']), expr: abcG (['abcG'])
+ g: type ]] .. '\022' .. [[10; value: abcG (['abcG']), expr: abcG (['abcG'])
==
=abcG =
- {{{2 setreg('h', 'abcH', ']]..'\022'..[[10')
- h: type ]]..'\022'..[[10; value: abcH (['abcH']), expr: abcH (['abcH'])
+ {{{2 setreg('h', 'abcH', ']] .. '\022' .. [[10')
+ h: type ]] .. '\022' .. [[10; value: abcH (['abcH']), expr: abcH (['abcH'])
==
=abcH =
{{{2 setreg('I', 'abcI')
@@ -132,12 +135,12 @@ describe('eval', function()
==
=abcAabcAc=
{{{2 setreg('A', 'abcAl', 'l')
- A: type V; value: abcAabcAcabcAl]].."\000 (['abcAabcAcabcAl']), expr: abcAabcAcabcAl\000"..[[ (['abcAabcAcabcAl'])
+ A: type V; value: abcAabcAcabcAl]] .. "\000 (['abcAabcAcabcAl']), expr: abcAabcAcabcAl\000" .. [[ (['abcAabcAcabcAl'])
==
abcAabcAcabcAl
==
{{{2 setreg('A', 'abcAc2', 'c')
- A: type v; value: abcAabcAcabcAl]].."\000abcAc2 (['abcAabcAcabcAl', 'abcAc2']), expr: abcAabcAcabcAl\000"..[[abcAc2 (['abcAabcAcabcAl', 'abcAc2'])
+ A: type v; value: abcAabcAcabcAl]] .. "\000abcAc2 (['abcAabcAcabcAl', 'abcAc2']), expr: abcAabcAcabcAl\000" .. [[abcAc2 (['abcAabcAcabcAl', 'abcAc2'])
==
=abcAabcAcabcAl
abcAc2=
@@ -146,50 +149,50 @@ describe('eval', function()
==
=abcBabcBc=
{{{2 setreg('b', 'abcBb', 'ba')
- b: type ]]..'\022'..[[5; value: abcBabcBcabcBb (['abcBabcBcabcBb']), expr: abcBabcBcabcBb (['abcBabcBcabcBb'])
+ b: type ]] .. '\022' .. [[5; value: abcBabcBcabcBb (['abcBabcBcabcBb']), expr: abcBabcBcabcBb (['abcBabcBcabcBb'])
==
=abcBabcBcabcBb=
{{{2 setreg('b', 'abcBc2', 'ca')
- b: type v; value: abcBabcBcabcBb]].."\000abcBc2 (['abcBabcBcabcBb', 'abcBc2']), expr: abcBabcBcabcBb\000"..[[abcBc2 (['abcBabcBcabcBb', 'abcBc2'])
+ b: type v; value: abcBabcBcabcBb]] .. "\000abcBc2 (['abcBabcBcabcBb', 'abcBc2']), expr: abcBabcBcabcBb\000" .. [[abcBc2 (['abcBabcBcabcBb', 'abcBc2'])
==
=abcBabcBcabcBb
abcBc2=
{{{2 setreg('b', 'abcBb2', 'b50a')
- b: type ]].."\02250; value: abcBabcBcabcBb\000abcBc2abcBb2 (['abcBabcBcabcBb', 'abcBc2abcBb2']), expr: abcBabcBcabcBb\000"..[[abcBc2abcBb2 (['abcBabcBcabcBb', 'abcBc2abcBb2'])
+ b: type ]] .. "\02250; value: abcBabcBcabcBb\000abcBc2abcBb2 (['abcBabcBcabcBb', 'abcBc2abcBb2']), expr: abcBabcBcabcBb\000" .. [[abcBc2abcBb2 (['abcBabcBcabcBb', 'abcBc2abcBb2'])
==
=abcBabcBcabcBb =
abcBc2abcBb2
{{{2 setreg('C', 'abcCl', 'l')
- C: type V; value: abcC]].."\000abcCl\000 (['abcC', 'abcCl']), expr: abcC\000abcCl\000"..[[ (['abcC', 'abcCl'])
+ C: type V; value: abcC]] .. "\000abcCl\000 (['abcC', 'abcCl']), expr: abcC\000abcCl\000" .. [[ (['abcC', 'abcCl'])
==
abcC
abcCl
==
{{{2 setreg('C', 'abcCc', 'c')
- C: type v; value: abcC]].."\000abcCl\000abcCc (['abcC', 'abcCl', 'abcCc']), expr: abcC\000abcCl\000"..[[abcCc (['abcC', 'abcCl', 'abcCc'])
+ C: type v; value: abcC]] .. "\000abcCl\000abcCc (['abcC', 'abcCl', 'abcCc']), expr: abcC\000abcCl\000" .. [[abcCc (['abcC', 'abcCl', 'abcCc'])
==
=abcC
abcCl
abcCc=
{{{2 setreg('D', 'abcDb', 'b')
- D: type ]].."\0225; value: abcD\000abcDb (['abcD', 'abcDb']), expr: abcD\000"..[[abcDb (['abcD', 'abcDb'])
+ D: type ]] .. "\0225; value: abcD\000abcDb (['abcD', 'abcDb']), expr: abcD\000" .. [[abcDb (['abcD', 'abcDb'])
==
=abcD =
abcDb
{{{2 setreg('E', 'abcEb', 'b')
- E: type ]].."\0225; value: abcE\000abcEb (['abcE', 'abcEb']), expr: abcE\000"..[[abcEb (['abcE', 'abcEb'])
+ E: type ]] .. "\0225; value: abcE\000abcEb (['abcE', 'abcEb']), expr: abcE\000" .. [[abcEb (['abcE', 'abcEb'])
==
=abcE =
abcEb
{{{2 setreg('E', 'abcEl', 'l')
- E: type V; value: abcE]].."\000abcEb\000abcEl\000 (['abcE', 'abcEb', 'abcEl']), expr: abcE\000abcEb\000abcEl\000"..[[ (['abcE', 'abcEb', 'abcEl'])
+ E: type V; value: abcE]] .. "\000abcEb\000abcEl\000 (['abcE', 'abcEb', 'abcEl']), expr: abcE\000abcEb\000abcEl\000" .. [[ (['abcE', 'abcEb', 'abcEl'])
==
abcE
abcEb
abcEl
==
{{{2 setreg('F', 'abcFc', 'c')
- F: type v; value: abcF]].."\000abcFc (['abcF', 'abcFc']), expr: abcF\000"..[[abcFc (['abcF', 'abcFc'])
+ F: type v; value: abcF]] .. "\000abcFc (['abcF', 'abcFc']), expr: abcF\000" .. [[abcFc (['abcF', 'abcFc'])
==
=abcF
abcFc=]])
@@ -219,36 +222,36 @@ describe('eval', function()
command([[call SetReg('F', "\n", 'b')]])
expect([[
- {{{2 setreg('A', ']]..'\000'..[[')
- A: type V; value: abcA2]].."\000 (['abcA2']), expr: abcA2\000"..[[ (['abcA2'])
+ {{{2 setreg('A', ']] .. '\000' .. [[')
+ A: type V; value: abcA2]] .. "\000 (['abcA2']), expr: abcA2\000" .. [[ (['abcA2'])
==
abcA2
==
- {{{2 setreg('B', ']]..'\000'..[[', 'c')
- B: type v; value: abcB2]].."\000 (['abcB2', '']), expr: abcB2\000"..[[ (['abcB2', ''])
+ {{{2 setreg('B', ']] .. '\000' .. [[', 'c')
+ B: type v; value: abcB2]] .. "\000 (['abcB2', '']), expr: abcB2\000" .. [[ (['abcB2', ''])
==
=abcB2
=
- {{{2 setreg('C', ']]..'\000'..[[')
- C: type V; value: abcC2]].."\000\000 (['abcC2', '']), expr: abcC2\000\000"..[[ (['abcC2', ''])
+ {{{2 setreg('C', ']] .. '\000' .. [[')
+ C: type V; value: abcC2]] .. "\000\000 (['abcC2', '']), expr: abcC2\000\000" .. [[ (['abcC2', ''])
==
abcC2
==
- {{{2 setreg('D', ']]..'\000'..[[', 'l')
- D: type V; value: abcD2]].."\000\000 (['abcD2', '']), expr: abcD2\000\000"..[[ (['abcD2', ''])
+ {{{2 setreg('D', ']] .. '\000' .. [[', 'l')
+ D: type V; value: abcD2]] .. "\000\000 (['abcD2', '']), expr: abcD2\000\000" .. [[ (['abcD2', ''])
==
abcD2
==
- {{{2 setreg('E', ']]..'\000'..[[')
- E: type V; value: abcE2]].."\000\000 (['abcE2', '']), expr: abcE2\000\000"..[[ (['abcE2', ''])
+ {{{2 setreg('E', ']] .. '\000' .. [[')
+ E: type V; value: abcE2]] .. "\000\000 (['abcE2', '']), expr: abcE2\000\000" .. [[ (['abcE2', ''])
==
abcE2
==
- {{{2 setreg('F', ']]..'\000'..[[', 'b')
- F: type ]].."\0220; value: abcF2\000 (['abcF2', '']), expr: abcF2\000"..[[ (['abcF2', ''])
+ {{{2 setreg('F', ']] .. '\000' .. [[', 'b')
+ F: type ]] .. "\0220; value: abcF2\000 (['abcF2', '']), expr: abcF2\000" .. [[ (['abcF2', ''])
==
=abcF2=
]])
@@ -282,21 +285,21 @@ describe('eval', function()
==
=abcA3=
{{{2 setreg('b', ['abcB3'], 'l')
- b: type V; value: abcB3]].."\000 (['abcB3']), expr: abcB3\000"..[[ (['abcB3'])
+ b: type V; value: abcB3]] .. "\000 (['abcB3']), expr: abcB3\000" .. [[ (['abcB3'])
==
abcB3
==
{{{2 setreg('c', ['abcC3'], 'b')
- c: type ]]..'\022'..[[5; value: abcC3 (['abcC3']), expr: abcC3 (['abcC3'])
+ c: type ]] .. '\022' .. [[5; value: abcC3 (['abcC3']), expr: abcC3 (['abcC3'])
==
=abcC3=
{{{2 setreg('d', ['abcD3'])
- d: type V; value: abcD3]].."\000 (['abcD3']), expr: abcD3\000"..[[ (['abcD3'])
+ d: type V; value: abcD3]] .. "\000 (['abcD3']), expr: abcD3\000" .. [[ (['abcD3'])
==
abcD3
==
{{{2 setreg('e', [1, 2, 'abc', 3])
- e: type V; value: 1]].."\0002\000abc\0003\000 (['1', '2', 'abc', '3']), expr: 1\0002\000abc\0003\000"..[[ (['1', '2', 'abc', '3'])
+ e: type V; value: 1]] .. "\0002\000abc\0003\000 (['1', '2', 'abc', '3']), expr: 1\0002\000abc\0003\000" .. [[ (['1', '2', 'abc', '3'])
==
1
2
@@ -304,7 +307,7 @@ describe('eval', function()
3
==
{{{2 setreg('f', [1, 2, 3])
- f: type V; value: 1]].."\0002\0003\000 (['1', '2', '3']), expr: 1\0002\0003\000"..[[ (['1', '2', '3'])
+ f: type V; value: 1]] .. "\0002\0003\000 (['1', '2', '3']), expr: 1\0002\0003\000" .. [[ (['1', '2', '3'])
==
1
2
@@ -312,49 +315,49 @@ describe('eval', function()
==
{{{1 Appending lists with setreg()
{{{2 setreg('A', ['abcA3c'], 'c')
- A: type v; value: abcA3]].."\000abcA3c (['abcA3', 'abcA3c']), expr: abcA3\000"..[[abcA3c (['abcA3', 'abcA3c'])
+ A: type v; value: abcA3]] .. "\000abcA3c (['abcA3', 'abcA3c']), expr: abcA3\000" .. [[abcA3c (['abcA3', 'abcA3c'])
==
=abcA3
abcA3c=
{{{2 setreg('b', ['abcB3l'], 'la')
- b: type V; value: abcB3]].."\000abcB3l\000 (['abcB3', 'abcB3l']), expr: abcB3\000abcB3l\000"..[[ (['abcB3', 'abcB3l'])
+ b: type V; value: abcB3]] .. "\000abcB3l\000 (['abcB3', 'abcB3l']), expr: abcB3\000abcB3l\000" .. [[ (['abcB3', 'abcB3l'])
==
abcB3
abcB3l
==
{{{2 setreg('C', ['abcC3b'], 'lb')
- C: type ]].."\0226; value: abcC3\000abcC3b (['abcC3', 'abcC3b']), expr: abcC3\000"..[[abcC3b (['abcC3', 'abcC3b'])
+ C: type ]] .. "\0226; value: abcC3\000abcC3b (['abcC3', 'abcC3b']), expr: abcC3\000" .. [[abcC3b (['abcC3', 'abcC3b'])
==
=abcC3 =
abcC3b
{{{2 setreg('D', ['abcD32'])
- D: type V; value: abcD3]].."\000abcD32\000 (['abcD3', 'abcD32']), expr: abcD3\000abcD32\000"..[[ (['abcD3', 'abcD32'])
+ D: type V; value: abcD3]] .. "\000abcD32\000 (['abcD3', 'abcD32']), expr: abcD3\000abcD32\000" .. [[ (['abcD3', 'abcD32'])
==
abcD3
abcD32
==
{{{2 setreg('A', ['abcA32'])
- A: type V; value: abcA3]].."\000abcA3c\000abcA32\000 (['abcA3', 'abcA3c', 'abcA32']), expr: abcA3\000abcA3c\000abcA32\000"..[[ (['abcA3', 'abcA3c', 'abcA32'])
+ A: type V; value: abcA3]] .. "\000abcA3c\000abcA32\000 (['abcA3', 'abcA3c', 'abcA32']), expr: abcA3\000abcA3c\000abcA32\000" .. [[ (['abcA3', 'abcA3c', 'abcA32'])
==
abcA3
abcA3c
abcA32
==
{{{2 setreg('B', ['abcB3c'], 'c')
- B: type v; value: abcB3]].."\000abcB3l\000abcB3c (['abcB3', 'abcB3l', 'abcB3c']), expr: abcB3\000abcB3l\000"..[[abcB3c (['abcB3', 'abcB3l', 'abcB3c'])
+ B: type v; value: abcB3]] .. "\000abcB3l\000abcB3c (['abcB3', 'abcB3l', 'abcB3c']), expr: abcB3\000abcB3l\000" .. [[abcB3c (['abcB3', 'abcB3l', 'abcB3c'])
==
=abcB3
abcB3l
abcB3c=
{{{2 setreg('C', ['abcC3l'], 'l')
- C: type V; value: abcC3]].."\000abcC3b\000abcC3l\000 (['abcC3', 'abcC3b', 'abcC3l']), expr: abcC3\000abcC3b\000abcC3l\000"..[[ (['abcC3', 'abcC3b', 'abcC3l'])
+ C: type V; value: abcC3]] .. "\000abcC3b\000abcC3l\000 (['abcC3', 'abcC3b', 'abcC3l']), expr: abcC3\000abcC3b\000abcC3l\000" .. [[ (['abcC3', 'abcC3b', 'abcC3l'])
==
abcC3
abcC3b
abcC3l
==
{{{2 setreg('D', ['abcD3b'], 'b')
- D: type ]].."\0226; value: abcD3\000abcD32\000abcD3b (['abcD3', 'abcD32', 'abcD3b']), expr: abcD3\000abcD32\000"..[[abcD3b (['abcD3', 'abcD32', 'abcD3b'])
+ D: type ]] .. "\0226; value: abcD3\000abcD32\000abcD3b (['abcD3', 'abcD32', 'abcD3b']), expr: abcD3\000abcD32\000" .. [[abcD3b (['abcD3', 'abcD32', 'abcD3b'])
==
=abcD3 =
abcD32
@@ -368,53 +371,57 @@ describe('eval', function()
command([[$put ='{{{1 Appending lists with NL with setreg()']])
command([=[call SetReg('A', ["\n", 'abcA3l2'], 'l')]=])
expect(
- '\n'..
- '{{{1 Appending lists with NL with setreg()\n'..
- "{{{2 setreg('A', ['\000', 'abcA3l2'], 'l')\n"..
- "A: type V; value: abcA3\000abcA3c\000abcA32\000\000\000abcA3l2\000 (['abcA3', 'abcA3c', 'abcA32', '\000', 'abcA3l2']), expr: abcA3\000abcA3c\000abcA32\000\000\000abcA3l2\000 (['abcA3', 'abcA3c', 'abcA32', '\000', 'abcA3l2'])\n"..
- '==\n'..
- 'abcA3\n'..
- 'abcA3c\n'..
- 'abcA32\n'..
- '\000\n'..
- 'abcA3l2\n'..
- '==')
+ '\n'
+ .. '{{{1 Appending lists with NL with setreg()\n'
+ .. "{{{2 setreg('A', ['\000', 'abcA3l2'], 'l')\n"
+ .. "A: type V; value: abcA3\000abcA3c\000abcA32\000\000\000abcA3l2\000 (['abcA3', 'abcA3c', 'abcA32', '\000', 'abcA3l2']), expr: abcA3\000abcA3c\000abcA32\000\000\000abcA3l2\000 (['abcA3', 'abcA3c', 'abcA32', '\000', 'abcA3l2'])\n"
+ .. '==\n'
+ .. 'abcA3\n'
+ .. 'abcA3c\n'
+ .. 'abcA32\n'
+ .. '\000\n'
+ .. 'abcA3l2\n'
+ .. '=='
+ )
command('%delete')
command([=[call SetReg('B', ["\n", 'abcB3c2'], 'c')]=])
expect(
- '\n'..
- "{{{2 setreg('B', ['\000', 'abcB3c2'], 'c')\n"..
- "B: type v; value: abcB3\000abcB3l\000abcB3c\000\000\000abcB3c2 (['abcB3', 'abcB3l', 'abcB3c', '\000', 'abcB3c2']), expr: abcB3\000abcB3l\000abcB3c\000\000\000abcB3c2 (['abcB3', 'abcB3l', 'abcB3c', '\000', 'abcB3c2'])\n"..
- '==\n'..
- '=abcB3\n'..
- 'abcB3l\n'..
- 'abcB3c\n'..
- '\000\n'..
- 'abcB3c2=')
+ '\n'
+ .. "{{{2 setreg('B', ['\000', 'abcB3c2'], 'c')\n"
+ .. "B: type v; value: abcB3\000abcB3l\000abcB3c\000\000\000abcB3c2 (['abcB3', 'abcB3l', 'abcB3c', '\000', 'abcB3c2']), expr: abcB3\000abcB3l\000abcB3c\000\000\000abcB3c2 (['abcB3', 'abcB3l', 'abcB3c', '\000', 'abcB3c2'])\n"
+ .. '==\n'
+ .. '=abcB3\n'
+ .. 'abcB3l\n'
+ .. 'abcB3c\n'
+ .. '\000\n'
+ .. 'abcB3c2='
+ )
command('%delete')
command([=[call SetReg('C', ["\n", 'abcC3b2'], 'b')]=])
expect(
- '\n'..
- "{{{2 setreg('C', ['\000', 'abcC3b2'], 'b')\n"..
- "C: type \0227; value: abcC3\000abcC3b\000abcC3l\000\000\000abcC3b2 (['abcC3', 'abcC3b', 'abcC3l', '\000', 'abcC3b2']), expr: abcC3\000abcC3b\000abcC3l\000\000\000abcC3b2 (['abcC3', 'abcC3b', 'abcC3l', '\000', 'abcC3b2'])\n"..
- '==\n'..
- '=abcC3 =\n'..
- ' abcC3b\n'..
- ' abcC3l\n'..
- ' \000\n'..
- ' abcC3b2')
+ '\n'
+ .. "{{{2 setreg('C', ['\000', 'abcC3b2'], 'b')\n"
+ .. "C: type \0227; value: abcC3\000abcC3b\000abcC3l\000\000\000abcC3b2 (['abcC3', 'abcC3b', 'abcC3l', '\000', 'abcC3b2']), expr: abcC3\000abcC3b\000abcC3l\000\000\000abcC3b2 (['abcC3', 'abcC3b', 'abcC3l', '\000', 'abcC3b2'])\n"
+ .. '==\n'
+ .. '=abcC3 =\n'
+ .. ' abcC3b\n'
+ .. ' abcC3l\n'
+ .. ' \000\n'
+ .. ' abcC3b2'
+ )
command('%delete')
command([=[call SetReg('D', ["\n", 'abcD3b50'],'b50')]=])
expect(
- '\n'..
- "{{{2 setreg('D', ['\000', 'abcD3b50'], 'b50')\n"..
- "D: type \02250; value: abcD3\000abcD32\000abcD3b\000\000\000abcD3b50 (['abcD3', 'abcD32', 'abcD3b', '\000', 'abcD3b50']), expr: abcD3\000abcD32\000abcD3b\000\000\000abcD3b50 (['abcD3', 'abcD32', 'abcD3b', '\000', 'abcD3b50'])\n"..
- '==\n'..
- '=abcD3 =\n'..
- ' abcD32\n'..
- ' abcD3b\n'..
- ' \000\n'..
- ' abcD3b50')
+ '\n'
+ .. "{{{2 setreg('D', ['\000', 'abcD3b50'], 'b50')\n"
+ .. "D: type \02250; value: abcD3\000abcD32\000abcD3b\000\000\000abcD3b50 (['abcD3', 'abcD32', 'abcD3b', '\000', 'abcD3b50']), expr: abcD3\000abcD32\000abcD3b\000\000\000abcD3b50 (['abcD3', 'abcD32', 'abcD3b', '\000', 'abcD3b50'])\n"
+ .. '==\n'
+ .. '=abcD3 =\n'
+ .. ' abcD32\n'
+ .. ' abcD3b\n'
+ .. ' \000\n'
+ .. ' abcD3b50'
+ )
end)
-- The tests for setting lists with NLs are split into separate it() blocks
@@ -422,77 +429,92 @@ describe('eval', function()
-- make trouble on a line on its own.
it('setting lists with NLs with setreg(), part 1', function()
command('so test_eval_setup.vim')
- command([=[call SetReg('a', ['abcA4-0', "\n", "abcA4-2\n", "\nabcA4-3", "abcA4-4\nabcA4-4-2"])]=])
+ command(
+ [=[call SetReg('a', ['abcA4-0', "\n", "abcA4-2\n", "\nabcA4-3", "abcA4-4\nabcA4-4-2"])]=]
+ )
expect(
- '\n'..
- "{{{2 setreg('a', ['abcA4-0', '\000', 'abcA4-2\000', '\000abcA4-3', 'abcA4-4\000abcA4-4-2'])\n"..
- "a: type V; value: abcA4-0\000\000\000abcA4-2\000\000\000abcA4-3\000abcA4-4\000abcA4-4-2\000 (['abcA4-0', '\000', 'abcA4-2\000', '\000abcA4-3', 'abcA4-4\000abcA4-4-2']), expr: abcA4-0\000\000\000abcA4-2\000\000\000abcA4-3\000abcA4-4\000abcA4-4-2\000 (['abcA4-0', '\000', 'abcA4-2\000', '\000abcA4-3', 'abcA4-4\000abcA4-4-2'])\n"..
- '==\n'..
- 'abcA4-0\n'..
- '\000\n'..
- 'abcA4-2\000\n'..
- '\000abcA4-3\n'..
- 'abcA4-4\000abcA4-4-2\n'..
- '==')
+ '\n'
+ .. "{{{2 setreg('a', ['abcA4-0', '\000', 'abcA4-2\000', '\000abcA4-3', 'abcA4-4\000abcA4-4-2'])\n"
+ .. "a: type V; value: abcA4-0\000\000\000abcA4-2\000\000\000abcA4-3\000abcA4-4\000abcA4-4-2\000 (['abcA4-0', '\000', 'abcA4-2\000', '\000abcA4-3', 'abcA4-4\000abcA4-4-2']), expr: abcA4-0\000\000\000abcA4-2\000\000\000abcA4-3\000abcA4-4\000abcA4-4-2\000 (['abcA4-0', '\000', 'abcA4-2\000', '\000abcA4-3', 'abcA4-4\000abcA4-4-2'])\n"
+ .. '==\n'
+ .. 'abcA4-0\n'
+ .. '\000\n'
+ .. 'abcA4-2\000\n'
+ .. '\000abcA4-3\n'
+ .. 'abcA4-4\000abcA4-4-2\n'
+ .. '=='
+ )
end)
it('setting lists with NLs with setreg(), part 2', function()
command('so test_eval_setup.vim')
- command([=[call SetReg('b', ['abcB4c-0', "\n", "abcB4c-2\n", "\nabcB4c-3", "abcB4c-4\nabcB4c-4-2"], 'c')]=])
+ command(
+ [=[call SetReg('b', ['abcB4c-0', "\n", "abcB4c-2\n", "\nabcB4c-3", "abcB4c-4\nabcB4c-4-2"], 'c')]=]
+ )
expect(
- '\n'..
- "{{{2 setreg('b', ['abcB4c-0', '\000', 'abcB4c-2\000', '\000abcB4c-3', 'abcB4c-4\000abcB4c-4-2'], 'c')\n"..
- "b: type v; value: abcB4c-0\000\000\000abcB4c-2\000\000\000abcB4c-3\000abcB4c-4\000abcB4c-4-2 (['abcB4c-0', '\000', 'abcB4c-2\000', '\000abcB4c-3', 'abcB4c-4\000abcB4c-4-2']), expr: abcB4c-0\000\000\000abcB4c-2\000\000\000abcB4c-3\000abcB4c-4\000abcB4c-4-2 (['abcB4c-0', '\000', 'abcB4c-2\000', '\000abcB4c-3', 'abcB4c-4\000abcB4c-4-2'])\n"..
- '==\n'..
- '=abcB4c-0\n'..
- '\000\n'..
- 'abcB4c-2\000\n'..
- '\000abcB4c-3\n'..
- 'abcB4c-4\000abcB4c-4-2=')
+ '\n'
+ .. "{{{2 setreg('b', ['abcB4c-0', '\000', 'abcB4c-2\000', '\000abcB4c-3', 'abcB4c-4\000abcB4c-4-2'], 'c')\n"
+ .. "b: type v; value: abcB4c-0\000\000\000abcB4c-2\000\000\000abcB4c-3\000abcB4c-4\000abcB4c-4-2 (['abcB4c-0', '\000', 'abcB4c-2\000', '\000abcB4c-3', 'abcB4c-4\000abcB4c-4-2']), expr: abcB4c-0\000\000\000abcB4c-2\000\000\000abcB4c-3\000abcB4c-4\000abcB4c-4-2 (['abcB4c-0', '\000', 'abcB4c-2\000', '\000abcB4c-3', 'abcB4c-4\000abcB4c-4-2'])\n"
+ .. '==\n'
+ .. '=abcB4c-0\n'
+ .. '\000\n'
+ .. 'abcB4c-2\000\n'
+ .. '\000abcB4c-3\n'
+ .. 'abcB4c-4\000abcB4c-4-2='
+ )
end)
it('setting lists with NLs with setreg(), part 3', function()
command('so test_eval_setup.vim')
- command([=[call SetReg('c', ['abcC4l-0', "\n", "abcC4l-2\n", "\nabcC4l-3", "abcC4l-4\nabcC4l-4-2"], 'l')]=])
+ command(
+ [=[call SetReg('c', ['abcC4l-0', "\n", "abcC4l-2\n", "\nabcC4l-3", "abcC4l-4\nabcC4l-4-2"], 'l')]=]
+ )
expect(
- '\n'..
- "{{{2 setreg('c', ['abcC4l-0', '\000', 'abcC4l-2\000', '\000abcC4l-3', 'abcC4l-4\000abcC4l-4-2'], 'l')\n"..
- "c: type V; value: abcC4l-0\000\000\000abcC4l-2\000\000\000abcC4l-3\000abcC4l-4\000abcC4l-4-2\000 (['abcC4l-0', '\000', 'abcC4l-2\000', '\000abcC4l-3', 'abcC4l-4\000abcC4l-4-2']), expr: abcC4l-0\000\000\000abcC4l-2\000\000\000abcC4l-3\000abcC4l-4\000abcC4l-4-2\000 (['abcC4l-0', '\000', 'abcC4l-2\000', '\000abcC4l-3', 'abcC4l-4\000abcC4l-4-2'])\n"..
- '==\n'..
- 'abcC4l-0\n'..
- '\000\n'..
- 'abcC4l-2\000\n'..
- '\000abcC4l-3\n'..
- 'abcC4l-4\000abcC4l-4-2\n'..
- '==')
+ '\n'
+ .. "{{{2 setreg('c', ['abcC4l-0', '\000', 'abcC4l-2\000', '\000abcC4l-3', 'abcC4l-4\000abcC4l-4-2'], 'l')\n"
+ .. "c: type V; value: abcC4l-0\000\000\000abcC4l-2\000\000\000abcC4l-3\000abcC4l-4\000abcC4l-4-2\000 (['abcC4l-0', '\000', 'abcC4l-2\000', '\000abcC4l-3', 'abcC4l-4\000abcC4l-4-2']), expr: abcC4l-0\000\000\000abcC4l-2\000\000\000abcC4l-3\000abcC4l-4\000abcC4l-4-2\000 (['abcC4l-0', '\000', 'abcC4l-2\000', '\000abcC4l-3', 'abcC4l-4\000abcC4l-4-2'])\n"
+ .. '==\n'
+ .. 'abcC4l-0\n'
+ .. '\000\n'
+ .. 'abcC4l-2\000\n'
+ .. '\000abcC4l-3\n'
+ .. 'abcC4l-4\000abcC4l-4-2\n'
+ .. '=='
+ )
end)
it('setting lists with NLs with setreg(), part 4', function()
command('so test_eval_setup.vim')
- command([=[call SetReg('d', ['abcD4b-0', "\n", "abcD4b-2\n", "\nabcD4b-3", "abcD4b-4\nabcD4b-4-2"], 'b')]=])
+ command(
+ [=[call SetReg('d', ['abcD4b-0', "\n", "abcD4b-2\n", "\nabcD4b-3", "abcD4b-4\nabcD4b-4-2"], 'b')]=]
+ )
expect(
- '\n'..
- "{{{2 setreg('d', ['abcD4b-0', '\000', 'abcD4b-2\000', '\000abcD4b-3', 'abcD4b-4\000abcD4b-4-2'], 'b')\n"..
- "d: type \02219; value: abcD4b-0\000\000\000abcD4b-2\000\000\000abcD4b-3\000abcD4b-4\000abcD4b-4-2 (['abcD4b-0', '\000', 'abcD4b-2\000', '\000abcD4b-3', 'abcD4b-4\000abcD4b-4-2']), expr: abcD4b-0\000\000\000abcD4b-2\000\000\000abcD4b-3\000abcD4b-4\000abcD4b-4-2 (['abcD4b-0', '\000', 'abcD4b-2\000', '\000abcD4b-3', 'abcD4b-4\000abcD4b-4-2'])\n"..
- '==\n'..
- '=abcD4b-0 =\n'..
- ' \000\n'..
- ' abcD4b-2\000\n'..
- ' \000abcD4b-3\n'..
- ' abcD4b-4\000abcD4b-4-2')
+ '\n'
+ .. "{{{2 setreg('d', ['abcD4b-0', '\000', 'abcD4b-2\000', '\000abcD4b-3', 'abcD4b-4\000abcD4b-4-2'], 'b')\n"
+ .. "d: type \02219; value: abcD4b-0\000\000\000abcD4b-2\000\000\000abcD4b-3\000abcD4b-4\000abcD4b-4-2 (['abcD4b-0', '\000', 'abcD4b-2\000', '\000abcD4b-3', 'abcD4b-4\000abcD4b-4-2']), expr: abcD4b-0\000\000\000abcD4b-2\000\000\000abcD4b-3\000abcD4b-4\000abcD4b-4-2 (['abcD4b-0', '\000', 'abcD4b-2\000', '\000abcD4b-3', 'abcD4b-4\000abcD4b-4-2'])\n"
+ .. '==\n'
+ .. '=abcD4b-0 =\n'
+ .. ' \000\n'
+ .. ' abcD4b-2\000\n'
+ .. ' \000abcD4b-3\n'
+ .. ' abcD4b-4\000abcD4b-4-2'
+ )
end)
it('setting lists with NLs with setreg(), part 5', function()
command('so test_eval_setup.vim')
- command([=[call SetReg('e', ['abcE4b10-0', "\n", "abcE4b10-2\n", "\nabcE4b10-3", "abcE4b10-4\nabcE4b10-4-2"], 'b10')]=])
+ command(
+ [=[call SetReg('e', ['abcE4b10-0', "\n", "abcE4b10-2\n", "\nabcE4b10-3", "abcE4b10-4\nabcE4b10-4-2"], 'b10')]=]
+ )
expect(
- '\n'..
- "{{{2 setreg('e', ['abcE4b10-0', '\000', 'abcE4b10-2\000', '\000abcE4b10-3', 'abcE4b10-4\000abcE4b10-4-2'], 'b10')\n"..
- "e: type \02210; value: abcE4b10-0\000\000\000abcE4b10-2\000\000\000abcE4b10-3\000abcE4b10-4\000abcE4b10-4-2 (['abcE4b10-0', '\000', 'abcE4b10-2\000', '\000abcE4b10-3', 'abcE4b10-4\000abcE4b10-4-2']), expr: abcE4b10-0\000\000\000abcE4b10-2\000\000\000abcE4b10-3\000abcE4b10-4\000abcE4b10-4-2 (['abcE4b10-0', '\000', 'abcE4b10-2\000', '\000abcE4b10-3', 'abcE4b10-4\000abcE4b10-4-2'])\n"..
- '==\n'..
- '=abcE4b10-0=\n'..
- ' \000\n'..
- ' abcE4b10-2\000\n'..
- ' \000abcE4b10-3\n'..
- ' abcE4b10-4\000abcE4b10-4-2')
+ '\n'
+ .. "{{{2 setreg('e', ['abcE4b10-0', '\000', 'abcE4b10-2\000', '\000abcE4b10-3', 'abcE4b10-4\000abcE4b10-4-2'], 'b10')\n"
+ .. "e: type \02210; value: abcE4b10-0\000\000\000abcE4b10-2\000\000\000abcE4b10-3\000abcE4b10-4\000abcE4b10-4-2 (['abcE4b10-0', '\000', 'abcE4b10-2\000', '\000abcE4b10-3', 'abcE4b10-4\000abcE4b10-4-2']), expr: abcE4b10-0\000\000\000abcE4b10-2\000\000\000abcE4b10-3\000abcE4b10-4\000abcE4b10-4-2 (['abcE4b10-0', '\000', 'abcE4b10-2\000', '\000abcE4b10-3', 'abcE4b10-4\000abcE4b10-4-2'])\n"
+ .. '==\n'
+ .. '=abcE4b10-0=\n'
+ .. ' \000\n'
+ .. ' abcE4b10-2\000\n'
+ .. ' \000abcE4b10-3\n'
+ .. ' abcE4b10-4\000abcE4b10-4-2'
+ )
end)
it('getreg("a",1,1) returns a valid list when "a is unset', function()
@@ -511,19 +533,19 @@ describe('eval', function()
eq({}, eval("getreg('0',1,1)"))
-- x is a mutable list
- command("let y = x")
- eq({}, eval("y"))
+ command('let y = x')
+ eq({}, eval('y'))
command("call add(x, 'item')")
- eq({'item'}, eval("y"))
+ eq({ 'item' }, eval('y'))
end)
it('sets the unnamed register when the "u" option is passed to setreg', function()
command("call setreg('a','a reg', 'cu')")
- eq("a reg", eval('@"'))
+ eq('a reg', eval('@"'))
command("call setreg('b','b reg', 'cu')")
- eq("b reg", eval('@"'))
+ eq('b reg', eval('@"'))
command("call setreg('c','c reg', 'c')")
- eq("b reg", eval('@"'))
+ eq('b reg', eval('@"'))
end)
it('search and expressions', function()
@@ -532,20 +554,36 @@ describe('eval', function()
command([=[call SetReg('/', ["abc/\n"])]=])
command([=[call SetReg('=', ['"abc/"'])]=])
command([=[call SetReg('=', ["\"abc/\n\""])]=])
- expect([[
+ expect(
+ [[
{{{2 setreg('/', ['abc/'])
/: type v; value: abc/ (['abc/']), expr: abc/ (['abc/'])
==
=abc/=
- {{{2 setreg('/', ['abc/]]..'\000'..[['])
- /: type v; value: abc/]].."\000 (['abc/\000']), expr: abc/\000 (['abc/\000"..[['])
- ==
- =abc/]]..'\000'..[[=
+ {{{2 setreg('/', ['abc/]]
+ .. '\000'
+ .. [['])
+ /: type v; value: abc/]]
+ .. "\000 (['abc/\000']), expr: abc/\000 (['abc/\000"
+ .. [['])
+ ==
+ =abc/]]
+ .. '\000'
+ .. [[=
{{{2 setreg('=', ['"abc/"'])
=: type v; value: abc/ (['abc/']), expr: "abc/" (['"abc/"'])
- {{{2 setreg('=', ['"abc/]]..'\000'..[["'])
- =: type v; value: abc/]].."\000 (['abc/\000"..[[']), expr: "abc/]]..'\000'..[[" (['"abc/]]..'\000'..[["'])]])
+ {{{2 setreg('=', ['"abc/]]
+ .. '\000'
+ .. [["'])
+ =: type v; value: abc/]]
+ .. "\000 (['abc/\000"
+ .. [[']), expr: "abc/]]
+ .. '\000'
+ .. [[" (['"abc/]]
+ .. '\000'
+ .. [["'])]]
+ )
end)
describe('system clipboard', function()
@@ -574,15 +612,25 @@ describe('eval', function()
command('AR *')
command('let &cb=_clipopt')
command("call call('setreg', _clipreg)")
- expect([[
+ expect(
+ [[
Some first line (this text was at the top of the old test_eval.in).
Note: system clipboard is saved, changed and restored.
clipboard contents
something else
- *: type V; value: clipboard contents]]..'\00'..[[ (['clipboard contents']), expr: clipboard contents]]..'\00'..[[ (['clipboard contents'])
- *: type V; value: something else]]..'\00'..[[ (['something else']), expr: something else]]..'\00'..[[ (['something else'])]])
+ *: type V; value: clipboard contents]]
+ .. '\00'
+ .. [[ (['clipboard contents']), expr: clipboard contents]]
+ .. '\00'
+ .. [[ (['clipboard contents'])
+ *: type V; value: something else]]
+ .. '\00'
+ .. [[ (['something else']), expr: something else]]
+ .. '\00'
+ .. [[ (['something else'])]]
+ )
end)
end)
@@ -625,24 +673,30 @@ describe('eval', function()
end)
it('function name not starting with a capital', function()
- eq('Vim(function):E128: Function name must start with a capital or "s:": g:test()\\nendfunction',
- exc_exec(dedent([[
+ eq(
+ 'Vim(function):E128: Function name must start with a capital or "s:": g:test()\\nendfunction',
+ exc_exec(dedent([[
function! g:test()
- endfunction]])))
+ endfunction]]))
+ )
end)
it('Function name followed by #', function()
- eq('Vim(function):E128: Function name must start with a capital or "s:": test2() "#\\nendfunction',
- exc_exec(dedent([[
+ eq(
+ 'Vim(function):E128: Function name must start with a capital or "s:": test2() "#\\nendfunction',
+ exc_exec(dedent([[
function! test2() "#
- endfunction]])))
+ endfunction]]))
+ )
end)
it('function name includes a colon', function()
- eq('Vim(function):E884: Function name cannot contain a colon: b:test()\\nendfunction',
- exc_exec(dedent([[
+ eq(
+ 'Vim(function):E884: Function name cannot contain a colon: b:test()\\nendfunction',
+ exc_exec(dedent([[
function! b:test()
- endfunction]])))
+ endfunction]]))
+ )
end)
it('function name starting with/without "g:", buffer-local funcref', function()
@@ -686,8 +740,10 @@ describe('eval', function()
end)
it("using $ instead of '$' must give an error", function()
- eq('Vim(call):E116: Invalid arguments for function append',
- exc_exec('call append($, "foobar")'))
+ eq(
+ 'Vim(call):E116: Invalid arguments for function append',
+ exc_exec('call append($, "foobar")')
+ )
end)
it('getcurpos/setpos', function()
diff --git a/test/functional/legacy/ex_mode_spec.lua b/test/functional/legacy/ex_mode_spec.lua
index f21c47e175..ae4c4309d1 100644
--- a/test/functional/legacy/ex_mode_spec.lua
+++ b/test/functional/legacy/ex_mode_spec.lua
@@ -5,7 +5,7 @@ local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
local poke_eventloop = helpers.poke_eventloop
before_each(clear)
@@ -14,9 +14,9 @@ describe('Ex mode', function()
it('supports command line editing', function()
local function test_ex_edit(expected, cmd)
feed('gQ' .. cmd .. '<C-b>"<CR>')
- local ret = eval('@:[1:]') -- Remove leading quote.
+ local ret = eval('@:[1:]') -- Remove leading quote.
feed('visual<CR>')
- eq(meths.replace_termcodes(expected, true, true, true), ret)
+ eq(api.nvim_replace_termcodes(expected, true, true, true), ret)
end
command('set sw=2')
test_ex_edit('bar', 'foo bar<C-u>bar')
@@ -46,9 +46,9 @@ describe('Ex mode', function()
command('set noincsearch nohlsearch inccommand=')
local screen = Screen.new(60, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, reverse = true}, -- MsgSeparator
- [1] = {foreground = Screen.colors.Brown}, -- LineNr
- [2] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [0] = { bold = true, reverse = true }, -- MsgSeparator
+ [1] = { foreground = Screen.colors.Brown }, -- LineNr
+ [2] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
})
screen:attach()
command([[call setline(1, ['foo foo', 'foo foo', 'foo foo'])]])
@@ -118,8 +118,7 @@ describe('Ex mode', function()
{1: 1 }foo bar |
{1: 2 }foo foo |
{1: 3 }^foo foo |
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
|
]])
end)
@@ -127,8 +126,8 @@ describe('Ex mode', function()
it('pressing Ctrl-C in :append inside a loop in Ex mode does not hang', function()
local screen = Screen.new(60, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, reverse = true}, -- MsgSeparator
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [0] = { bold = true, reverse = true }, -- MsgSeparator
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
})
screen:attach()
feed('gQ')
@@ -143,7 +142,7 @@ describe('Ex mode', function()
^ |
]])
feed('<C-C>')
- poke_eventloop() -- Wait for input to be flushed
+ poke_eventloop() -- Wait for input to be flushed
feed('foo<CR>')
screen:expect([[
Entering Ex mode. Type "visual" to go to Normal mode. |
@@ -166,10 +165,7 @@ describe('Ex mode', function()
feed('vi<CR>')
screen:expect([[
^foo |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
end)
diff --git a/test/functional/legacy/excmd_spec.lua b/test/functional/legacy/excmd_spec.lua
index eb480a6689..41f14c4645 100644
--- a/test/functional/legacy/excmd_spec.lua
+++ b/test/functional/legacy/excmd_spec.lua
@@ -6,8 +6,8 @@ local exec = helpers.exec
local exec_lua = helpers.exec_lua
local expect_exit = helpers.expect_exit
local feed = helpers.feed
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local read_file = helpers.read_file
local source = helpers.source
local eq = helpers.eq
@@ -23,7 +23,9 @@ end
describe('Ex command', function()
before_each(clear)
- after_each(function() eq({}, meths.get_vvar('errors')) end)
+ after_each(function()
+ eq({}, api.nvim_get_vvar('errors'))
+ end)
it('checks for address line overflow', function()
if sizeoflong() < 8 then
@@ -47,10 +49,10 @@ describe(':confirm command dialog', function()
clear()
screen = Screen.new(75, 20)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, reverse = true}, -- StatusLine, MsgSeparator
- [2] = {reverse = true}, -- StatusLineNC
- [3] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, reverse = true }, -- StatusLine, MsgSeparator
+ [2] = { reverse = true }, -- StatusLineNC
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
})
screen:attach()
end
@@ -74,21 +76,13 @@ describe(':confirm command dialog', function()
feed(':confirm qall\n')
screen:expect([[
bar2 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{2:Xbar [+] }|
foo2 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:Xfoo [+] }|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1: }|
:confirm qall |
{3:Save changes to "Xbar"?} |
@@ -112,21 +106,13 @@ describe(':confirm command dialog', function()
feed(':confirm qall\n')
screen:expect([[
bar3 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{2:Xbar [+] }|
foo3 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:Xfoo [+] }|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1: }|
:confirm qall |
{3:Save changes to "Xbar"?} |
@@ -150,21 +136,13 @@ describe(':confirm command dialog', function()
feed(':confirm qall\n')
screen:expect([[
bar4 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{2:Xbar [+] }|
foo4 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:Xfoo [+] }|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1: }|
:confirm qall |
{3:Save changes to "Xbar"?} |
@@ -173,17 +151,10 @@ describe(':confirm command dialog', function()
feed('N')
screen:expect([[
bar4 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{2:Xbar [+] }|
foo4 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:Xfoo [+] }|
|
{1: }|
@@ -215,9 +186,7 @@ describe(':confirm command dialog', function()
feed(':confirm close\n')
screen:expect([[
abc |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1:[No Name] [+] }|
|
{1: }|
@@ -228,22 +197,17 @@ describe(':confirm command dialog', function()
feed('C')
screen:expect([[
^abc |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1:[No Name] [+] }|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:[No Name] }|
|
]])
feed(':confirm close\n')
screen:expect([[
abc |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1:[No Name] [+] }|
|
{1: }|
@@ -254,14 +218,7 @@ describe(':confirm command dialog', function()
feed('N')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
|
]])
end)
@@ -280,9 +237,7 @@ describe(':confirm command dialog', function()
feed(':confirm q\n')
screen:expect([[
foo |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1: }|
:confirm q |
{3:Save changes to "Untitled"?} |
@@ -291,12 +246,7 @@ describe(':confirm command dialog', function()
feed('C')
screen:expect([[
^abc |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
|
]])
@@ -304,9 +254,7 @@ describe(':confirm command dialog', function()
feed(':confirm wq\n')
screen:expect([[
foo |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1: }|
"Xfoo" [noeol] 1L, 3B written |
{3:Save changes to "Untitled"?} |
@@ -315,12 +263,7 @@ describe(':confirm command dialog', function()
feed('C')
screen:expect([[
^abc |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
"Xfoo" [noeol] 1L, 3B written |
]])
@@ -343,8 +286,7 @@ describe(':confirm command dialog', function()
feed(':set ro | confirm w\n')
screen:expect([[
foobar |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1: }|
:set ro | confirm w |
{3:'readonly' option is set for "Xconfirm_write_ro".} |
@@ -354,11 +296,7 @@ describe(':confirm command dialog', function()
feed('N')
screen:expect([[
fooba^r |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
1,6 All |
]])
@@ -367,8 +305,7 @@ describe(':confirm command dialog', function()
feed(':confirm w\n')
screen:expect([[
foobar |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1: }|
:confirm w |
{3:'readonly' option is set for "Xconfirm_write_ro".} |
@@ -400,10 +337,10 @@ describe(':confirm command dialog', function()
]])
end
eq('foobar\n', read_file('Xconfirm_write_ro'))
- feed('<CR>') -- suppress hit-enter prompt
+ feed('<CR>') -- suppress hit-enter prompt
-- Try to write with read-only file permissions.
- funcs.setfperm('Xconfirm_write_ro', 'r--r--r--')
+ fn.setfperm('Xconfirm_write_ro', 'r--r--r--')
feed(':set noro | silent undo | confirm w\n')
screen:expect([[
foobar |
@@ -440,7 +377,7 @@ describe(':confirm command dialog', function()
]])
end
eq('foo\n', read_file('Xconfirm_write_ro'))
- feed('<CR>') -- suppress hit-enter prompt
+ feed('<CR>') -- suppress hit-enter prompt
os.remove('Xconfirm_write_ro')
end)
@@ -473,8 +410,7 @@ describe(':confirm command dialog', function()
b |
c |
d |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
1,1 All |
]])
diff --git a/test/functional/legacy/filechanged_spec.lua b/test/functional/legacy/filechanged_spec.lua
index c8e772f597..46ecfdcd63 100644
--- a/test/functional/legacy/filechanged_spec.lua
+++ b/test/functional/legacy/filechanged_spec.lua
@@ -1,19 +1,19 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, source = helpers.clear, helpers.source
-local call, eq, meths = helpers.call, helpers.eq, helpers.meths
+local call, eq, api = helpers.call, helpers.eq, helpers.api
local is_os = helpers.is_os
local skip = helpers.skip
local function expected_empty()
- eq({}, meths.get_vvar('errors'))
+ eq({}, api.nvim_get_vvar('errors'))
end
describe('file changed dialog', function()
before_each(function()
clear()
- meths.ui_attach(80, 24, {})
- meths.set_option_value('autoread', false, {})
- meths.set_option_value('fsync', true, {})
+ api.nvim_ui_attach(80, 24, {})
+ api.nvim_set_option_value('autoread', false, {})
+ api.nvim_set_option_value('fsync', true, {})
end)
it('works', function()
diff --git a/test/functional/legacy/fixeol_spec.lua b/test/functional/legacy/fixeol_spec.lua
index 3cc9d54e2b..01b87ac9a0 100644
--- a/test/functional/legacy/fixeol_spec.lua
+++ b/test/functional/legacy/fixeol_spec.lua
@@ -6,11 +6,11 @@ local clear, feed_command, expect = helpers.clear, helpers.feed_command, helpers
describe('fixeol', function()
local function rmtestfiles()
- os.remove("test.out")
- os.remove("XXEol")
- os.remove("XXNoEol")
- os.remove("XXTestEol")
- os.remove("XXTestNoEol")
+ os.remove('test.out')
+ os.remove('XXEol')
+ os.remove('XXNoEol')
+ os.remove('XXTestEol')
+ os.remove('XXTestNoEol')
end
setup(function()
clear()
diff --git a/test/functional/legacy/fnamemodify_spec.lua b/test/functional/legacy/fnamemodify_spec.lua
index 6262db3a2f..570b523d92 100644
--- a/test/functional/legacy/fnamemodify_spec.lua
+++ b/test/functional/legacy/fnamemodify_spec.lua
@@ -2,10 +2,10 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, source = helpers.clear, helpers.source
-local call, eq, nvim = helpers.call, helpers.eq, helpers.meths
+local call, eq, nvim = helpers.call, helpers.eq, helpers.api
local function expected_empty()
- eq({}, nvim.get_vvar('errors'))
+ eq({}, nvim.nvim_get_vvar('errors'))
end
describe('filename modifiers', function()
diff --git a/test/functional/legacy/fold_spec.lua b/test/functional/legacy/fold_spec.lua
index 83513a3f94..c39aae87d2 100644
--- a/test/functional/legacy/fold_spec.lua
+++ b/test/functional/legacy/fold_spec.lua
@@ -15,10 +15,10 @@ describe('folding', function()
screen = Screen.new(45, 8)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey}, -- Folded
- [3] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Grey}, -- FoldColumn
- [4] = {foreground = Screen.colors.Brown}, -- LineNr
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey }, -- Folded
+ [3] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Grey }, -- FoldColumn
+ [4] = { foreground = Screen.colors.Brown }, -- LineNr
})
screen:attach()
end)
@@ -50,7 +50,7 @@ describe('folding', function()
1 aa]])
end)
- it("foldmethod=marker", function()
+ it('foldmethod=marker', function()
screen:try_resize(20, 10)
insert([[
dd {{{
@@ -72,18 +72,15 @@ describe('folding', function()
dd {{{ |
ee {{{ }}} |
{{{ |
- ff }}} |
- ff }}} |
+ ff }}} |*2
^ |
line 2 foldlevel=2 |
- 1 |
- 1 |
+ 1 |*2
|
]])
-
end)
- it("foldmethod=indent", function()
+ it('foldmethod=indent', function()
screen:try_resize(20, 8)
feed_command('set fdm=indent sw=2')
insert([[
@@ -109,7 +106,7 @@ describe('folding', function()
]])
end)
- it("foldmethod=syntax", function()
+ it('foldmethod=syntax', function()
screen:try_resize(35, 15)
insert([[
1 aa
@@ -148,7 +145,7 @@ describe('folding', function()
a jj]])
end)
- it("foldmethod=expression", function()
+ it('foldmethod=expression', function()
insert([[
1 aa
2 bb
@@ -227,22 +224,14 @@ describe('folding', function()
screen:expect([[
{3:+ }{4: 0 }{2:^+-- 2 lines: ·························}|
{3:+ }{4: 1 }{2:+-- 2 lines: ·························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
- feed("j")
+ feed('j')
screen:expect([[
{3:+ }{4: 1 }{2:+-- 2 lines: ·························}|
{3:+ }{4: 0 }{2:^+-- 2 lines: ·························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
end)
@@ -259,10 +248,7 @@ describe('folding', function()
^one |
{2:+-- 2 lines: two····························}|
four |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
feed('2G')
@@ -271,9 +257,7 @@ describe('folding', function()
^two |
three |
four |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
feed('4G')
@@ -281,10 +265,7 @@ describe('folding', function()
one |
{2:+-- 2 lines: two····························}|
^four |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
feed('3G')
@@ -293,9 +274,7 @@ describe('folding', function()
two |
^three |
four |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
feed('1G')
@@ -303,10 +282,7 @@ describe('folding', function()
^one |
{2:+-- 2 lines: two····························}|
four |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
feed('2G')
@@ -315,9 +291,7 @@ describe('folding', function()
^two |
three |
four |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
feed('k')
@@ -325,10 +299,7 @@ describe('folding', function()
^one |
{2:+-- 2 lines: two····························}|
four |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
end)
diff --git a/test/functional/legacy/function_sort_spec.lua b/test/functional/legacy/function_sort_spec.lua
index 414953aacc..36128bb0a2 100644
--- a/test/functional/legacy/function_sort_spec.lua
+++ b/test/functional/legacy/function_sort_spec.lua
@@ -11,24 +11,24 @@ describe('sort', function()
before_each(clear)
it('numbers compared as strings', function()
- eq({1, 2, 3}, eval('sort([3, 2, 1])'))
- eq({13, 28, 3}, eval('sort([3, 28, 13])'))
+ eq({ 1, 2, 3 }, eval('sort([3, 2, 1])'))
+ eq({ 13, 28, 3 }, eval('sort([3, 28, 13])'))
end)
it('numbers compared as numeric', function()
- eq({1, 2, 3}, eval("sort([3, 2, 1], 'n')"))
- eq({3, 13, 28}, eval("sort([3, 28, 13], 'n')"))
+ eq({ 1, 2, 3 }, eval("sort([3, 2, 1], 'n')"))
+ eq({ 3, 13, 28 }, eval("sort([3, 28, 13], 'n')"))
-- Strings are not sorted.
- eq({'13', '28', '3'}, eval("sort(['13', '28', '3'], 'n')"))
+ eq({ '13', '28', '3' }, eval("sort(['13', '28', '3'], 'n')"))
end)
it('numbers compared as numbers', function()
- eq({3, 13, 28}, eval("sort([13, 28, 3], 'N')"))
- eq({'3', '13', '28'}, eval("sort(['13', '28', '3'], 'N')"))
+ eq({ 3, 13, 28 }, eval("sort([13, 28, 3], 'N')"))
+ eq({ '3', '13', '28' }, eval("sort(['13', '28', '3'], 'N')"))
end)
it('numbers compared as float', function()
- eq({0.28, 3, 13.5}, eval("sort([13.5, 0.28, 3], 'f')"))
+ eq({ 0.28, 3, 13.5 }, eval("sort([13.5, 0.28, 3], 'f')"))
end)
it('ability to call sort() from a compare function', function()
@@ -43,15 +43,15 @@ describe('sort', function()
endfunc
]])
- eq({1, 3, 5}, eval("sort([3, 1, 5], 'Compare1')"))
+ eq({ 1, 3, 5 }, eval("sort([3, 1, 5], 'Compare1')"))
end)
it('default sort', function()
-- docs say omitted, empty or zero argument sorts on string representation
- eq({'2', 'A', 'AA', 'a', 1, 3.3}, eval('sort([3.3, 1, "2", "A", "a", "AA"])'))
- eq({'2', 'A', 'AA', 'a', 1, 3.3}, eval([[sort([3.3, 1, "2", "A", "a", "AA"], '')]]))
- eq({'2', 'A', 'AA', 'a', 1, 3.3}, eval('sort([3.3, 1, "2", "A", "a", "AA"], 0)'))
- eq({'2', 'A', 'a', 'AA', 1, 3.3}, eval('sort([3.3, 1, "2", "A", "a", "AA"], 1)'))
+ eq({ '2', 'A', 'AA', 'a', 1, 3.3 }, eval('sort([3.3, 1, "2", "A", "a", "AA"])'))
+ eq({ '2', 'A', 'AA', 'a', 1, 3.3 }, eval([[sort([3.3, 1, "2", "A", "a", "AA"], '')]]))
+ eq({ '2', 'A', 'AA', 'a', 1, 3.3 }, eval('sort([3.3, 1, "2", "A", "a", "AA"], 0)'))
+ eq({ '2', 'A', 'a', 'AA', 1, 3.3 }, eval('sort([3.3, 1, "2", "A", "a", "AA"], 1)'))
neq(nil, exc_exec('call sort([3.3, 1, "2"], 3)'):find('E474:'))
end)
end)
diff --git a/test/functional/legacy/gf_spec.lua b/test/functional/legacy/gf_spec.lua
index 9f725446be..b51f671bee 100644
--- a/test/functional/legacy/gf_spec.lua
+++ b/test/functional/legacy/gf_spec.lua
@@ -10,7 +10,9 @@ describe('gf', function()
it('is not allowed when buffer is locked', function()
command('au OptionSet diff norm! gf')
command([[call setline(1, ['Xfile1', 'line2', 'line3', 'line4'])]])
- eq('OptionSet Autocommands for "diff": Vim(normal):E788: Not allowed to edit another buffer now',
- pcall_err(command, 'diffthis'))
+ eq(
+ 'OptionSet Autocommands for "diff": Vim(normal):E788: Not allowed to edit another buffer now',
+ pcall_err(command, 'diffthis')
+ )
end)
end)
diff --git a/test/functional/legacy/global_spec.lua b/test/functional/legacy/global_spec.lua
index ff02c41e6c..2c92b7814a 100644
--- a/test/functional/legacy/global_spec.lua
+++ b/test/functional/legacy/global_spec.lua
@@ -12,8 +12,8 @@ describe(':global', function()
it('can be interrupted using Ctrl-C in cmdline mode vim-patch:9.0.0082', function()
local screen = Screen.new(75, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, reverse = true}, -- MsgSeparator
- [1] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- ErrorMsg
+ [0] = { bold = true, reverse = true }, -- MsgSeparator
+ [1] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg
})
screen:attach()
@@ -24,20 +24,17 @@ describe(':global', function()
]])
feed(':g/foo/norm :<C-V>;<CR>')
- poke_eventloop() -- Wait for :sleep to start
+ poke_eventloop() -- Wait for :sleep to start
feed('<C-C>')
screen:expect([[
^foo |
- foo |
- foo |
- foo |
- foo |
+ foo |*4
{1:Interrupted} |
]])
-- Also test in Ex mode
feed('gQg/foo/norm :<C-V>;<CR>')
- poke_eventloop() -- Wait for :sleep to start
+ poke_eventloop() -- Wait for :sleep to start
feed('<C-C>')
screen:expect([[
{0: }|
diff --git a/test/functional/legacy/highlight_spec.lua b/test/functional/legacy/highlight_spec.lua
index 0a130f1607..3d06bf3978 100644
--- a/test/functional/legacy/highlight_spec.lua
+++ b/test/functional/legacy/highlight_spec.lua
@@ -39,7 +39,9 @@ describe(':highlight', function()
-- Test setting colors.
-- Test clearing one color and all doesn't generate error or warning
- feed_command('hi NewGroup cterm=italic ctermfg=DarkBlue ctermbg=Grey gui=NONE guifg=#00ff00 guibg=Cyan')
+ feed_command(
+ 'hi NewGroup cterm=italic ctermfg=DarkBlue ctermbg=Grey gui=NONE guifg=#00ff00 guibg=Cyan'
+ )
feed_command('hi Group2 cterm=NONE')
feed_command('hi Group3 cterm=bold')
feed_command('redir! @a')
@@ -54,8 +56,7 @@ describe(':highlight', function()
feed_command('hi clear')
feed_command('hi Group3')
feed('<cr>')
- eq('Vim(highlight):E475: Invalid argument: cterm=\'asdf',
- exc_exec([[hi Crash cterm='asdf]]))
+ eq("Vim(highlight):E475: Invalid argument: cterm='asdf", exc_exec([[hi Crash cterm='asdf]]))
feed_command('redir END')
-- Filter ctermfg and ctermbg, the numbers depend on the terminal
@@ -99,9 +100,9 @@ describe('Visual selection highlight', function()
it("when 'showbreak' is set", function()
local screen = Screen.new(60, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.LightGrey}, -- Visual
- [2] = {bold = true}, -- ModeMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual
+ [2] = { bold = true }, -- ModeMsg
})
screen:attach()
exec([[
@@ -112,10 +113,7 @@ describe('Visual selection highlight', function()
feed('v$')
screen:expect([[
{0:>}{1:n, no sea takimata sanctus est Lorem ipsum dolor sit amet.}^ |
- |
- |
- |
- |
+ |*4
{2:-- VISUAL --} |
]])
end)
diff --git a/test/functional/legacy/increment_spec.lua b/test/functional/legacy/increment_spec.lua
index d35f4bdae6..a81044114c 100644
--- a/test/functional/legacy/increment_spec.lua
+++ b/test/functional/legacy/increment_spec.lua
@@ -3,10 +3,9 @@
local helpers = require('test.functional.helpers')(after_each)
local source, command = helpers.source, helpers.command
local call, clear = helpers.call, helpers.clear
-local eq, nvim = helpers.eq, helpers.meths
+local eq, nvim = helpers.eq, helpers.api
describe('Ctrl-A/Ctrl-X on visual selections', function()
-
before_each(function()
clear()
source([=[
@@ -744,18 +743,18 @@ describe('Ctrl-A/Ctrl-X on visual selections', function()
it('works on Test ' .. id, function()
command('set nrformats&vi') -- &vi makes Vim compatible
call('Test_visual_increment_' .. id)
- eq({}, nvim.get_vvar('errors'))
+ eq({}, nvim.nvim_get_vvar('errors'))
end)
end
it('does not drop leading zeroes', function()
command('set nrformats&vi') -- &vi makes Vim compatible
call('Test_normal_increment_01')
- eq({}, nvim.get_vvar('errors'))
+ eq({}, nvim.nvim_get_vvar('errors'))
end)
it('maintains correct column after CTRL-A', function()
call('Test_normal_increment_02')
- eq({}, nvim.get_vvar('errors'))
+ eq({}, nvim.nvim_get_vvar('errors'))
end)
end)
diff --git a/test/functional/legacy/lispwords_spec.lua b/test/functional/legacy/lispwords_spec.lua
index 57d8d51377..efac8775d3 100644
--- a/test/functional/legacy/lispwords_spec.lua
+++ b/test/functional/legacy/lispwords_spec.lua
@@ -8,7 +8,7 @@ local source = helpers.source
describe('lispwords', function()
before_each(clear)
- it('should be set global-local',function()
+ it('should be set global-local', function()
source([[
setglobal lispwords=foo,bar,baz
setlocal lispwords-=foo
diff --git a/test/functional/legacy/listchars_spec.lua b/test/functional/legacy/listchars_spec.lua
index a9aa238d4e..746e0550a6 100644
--- a/test/functional/legacy/listchars_spec.lua
+++ b/test/functional/legacy/listchars_spec.lua
@@ -103,10 +103,10 @@ describe("'listchars'", function()
it('"exceeds" character does not appear in foldcolumn vim-patch:8.2.3121', function()
local screen = Screen.new(60, 10)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {bold = true, reverse = true}, -- StatusLine
- [3] = {reverse = true}, -- StatusLineNC
- [4] = {background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue}, -- FoldColumn, SignColumn
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { bold = true, reverse = true }, -- StatusLine
+ [3] = { reverse = true }, -- StatusLineNC
+ [4] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue }, -- FoldColumn, SignColumn
})
screen:attach()
exec([[
@@ -121,10 +121,7 @@ describe("'listchars'", function()
{4: } │{4: } │{4: } |
{4: }a │{4: }a │{4: }a |
{4: }aaaaaa │{4: }a{1:>}│{4: }aaaaaa |
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
+ {1:~ }│{1:~ }│{1:~ }|*4
{3:[No Name] [+] <[+] }{2:[No Name] [+] }|
|
]])
@@ -134,10 +131,7 @@ describe("'listchars'", function()
{4: } │{4: } │{4: } |
{4: }a │{4: }a│{4: }a |
{4: }aaaaaa │{4: }{1:>}│{4: }aaaaaa |
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
+ {1:~ }│{1:~ }│{1:~ }|*4
{3:[No Name] [+] <+] }{2:[No Name] [+] }|
|
]])
@@ -147,10 +141,7 @@ describe("'listchars'", function()
{4: } │{4: }│{4: } |
{4: }a │{4: }│{4: }a |
{4: }aaaaaa │{4: }│{4: }aaaaaa |
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
+ {1:~ }│{1:~ }│{1:~ }|*4
{3:[No Name] [+] <] }{2:[No Name] [+] }|
|
]])
@@ -160,10 +151,7 @@ describe("'listchars'", function()
{4: } │{4: }│{4: } |
{4: }a │{4: }│{4: }a |
{4: }aaaaaa │{4: }│{4: }aaaaaa |
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
+ {1:~ }│{1:~ }│{1:~ }|*4
{3:[No Name] [+] < }{2:[No Name] [+] }|
|
]])
@@ -173,10 +161,7 @@ describe("'listchars'", function()
{4: } │{4: }│{4: } |
{4: }a │{4: }│{4: }a |
{4: }aaaaaa │{4: }│{4: }aaaaaa |
- {1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~}│{1:~ }|
+ {1:~ }│{1:~}│{1:~ }|*4
{3:[No Name] [+] < }{2:[No Name] [+] }|
|
]])
@@ -187,10 +172,7 @@ describe("'listchars'", function()
{4: } │{4: } │{4: } |
{4: }a │{4: }a │{4: }a |
{4: }aaaaaa │{4: }aaaaaa │{4: }aaaaaa |
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
+ {1:~ }│{1:~ }│{1:~ }|*4
{3:[No Name] [+] }{2:[No Name] [+] }{3:[No Name] [+] }|
:set nowrap foldcolumn=4 |
]])
@@ -200,10 +182,7 @@ describe("'listchars'", function()
{4: } │{4: }│{4: } |
{4: }a │{4: }│{4: }a |
{4: }aaaaaa │{4: ^ }│{4: }aaaaaa |
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
- {1:~ }│{1:~ }│{1:~ }|
+ {1:~ }│{1:~ }│{1:~ }|*4
{3:[No Name] [+] }{2:<[+] }{3:[No Name] [+] }|
:set nowrap foldcolumn=4 |
]])
@@ -213,10 +192,7 @@ describe("'listchars'", function()
{4: } │{4: }│{4: } |
{4: }a │{4: }│{4: }a |
{4: }aaaaaa │{4:^ }│{4: }aaaaaa |
- {1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~}│{1:~ }|
+ {1:~ }│{1:~}│{1:~ }|*4
{3:[No Name] [+] }{2:< }{3:[No Name] [+] }|
:set nowrap foldcolumn=4 |
]])
diff --git a/test/functional/legacy/listlbr_spec.lua b/test/functional/legacy/listlbr_spec.lua
index d4f11a61c2..50628e5ef9 100644
--- a/test/functional/legacy/listlbr_spec.lua
+++ b/test/functional/legacy/listlbr_spec.lua
@@ -57,7 +57,9 @@ describe('listlbr', function()
feed_command('let line=ScreenChar(winwidth(0))')
feed_command('call DoRecordScreen()')
- feed_command('let g:test ="Test 4: set linebreak with tab and 1 line as long as screen: should break!"')
+ feed_command(
+ 'let g:test ="Test 4: set linebreak with tab and 1 line as long as screen: should break!"'
+ )
feed_command('set nolist linebreak ts=8')
feed_command([[let line="1\t".repeat('a', winwidth(0)-2)]])
feed_command('$put =line')
@@ -71,7 +73,9 @@ describe('listlbr', function()
feed_command('$')
feed_command('norm! zt')
- feed_command('let g:test ="Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated)"')
+ feed_command(
+ 'let g:test ="Test 5: set linebreak with conceal and set list and tab displayed by different char (line may not be truncated)"'
+ )
feed_command('set cpo&vim list linebreak conceallevel=2 concealcursor=nv listchars=tab:ab')
feed_command('syn match ConcealVar contained /_/ conceal')
feed_command('syn match All /.*/ contains=ConcealVar')
@@ -201,9 +205,9 @@ describe('listlbr', function()
it('cursor position is drawn correctly after operator', function()
local screen = Screen.new(60, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.LightGrey}, -- Visual
- [2] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- ErrorMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual
+ [2] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg
})
screen:attach()
@@ -217,18 +221,14 @@ describe('listlbr', function()
screen:expect([[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
bbbbbbbbbb {1:c}^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
2 |
]])
feed('zo')
screen:expect([[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
bbbbbbbbbb ^c |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2:E490: No fold found} |
]])
@@ -236,18 +236,14 @@ describe('listlbr', function()
screen:expect([[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
bbbbbbbbbb {1:c}^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2:E490: No fold found} 2 |
]])
feed('gq')
screen:expect([[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
bbbbbbbbbb ^c |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2:E490: No fold found} |
]])
@@ -255,18 +251,14 @@ describe('listlbr', function()
screen:expect([[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
bbbbbbbbbb {1:c}^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2:E490: No fold found} 1x2 |
]])
feed('I')
screen:expect([[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
bbbbbbbbbb ^c |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2:E490: No fold found} |
]])
@@ -274,18 +266,14 @@ describe('listlbr', function()
screen:expect([[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
bbbbbbbbbb {1:c}^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2:E490: No fold found} 2 |
]])
feed('s')
screen:expect([[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
bbbbbbbbbb ^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2:E490: No fold found} |
]])
end)
diff --git a/test/functional/legacy/listlbr_utf8_spec.lua b/test/functional/legacy/listlbr_utf8_spec.lua
index d7f4c71af2..8e5d9b88bc 100644
--- a/test/functional/legacy/listlbr_utf8_spec.lua
+++ b/test/functional/legacy/listlbr_utf8_spec.lua
@@ -1,12 +1,14 @@
-- Test for linebreak and list option in utf-8 mode
local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
local source = helpers.source
local feed = helpers.feed
+local exec = helpers.exec
local clear, expect = helpers.clear, helpers.expect
describe('linebreak', function()
- setup(clear)
+ before_each(clear)
-- luacheck: ignore 621 (Indentation)
-- luacheck: ignore 613 (Trailing whitespaces in a string)
@@ -208,4 +210,29 @@ describe('linebreak', function()
a b c¶
Screen attributes are the same!]])
end)
+
+ -- oldtest: Test_visual_ends_before_showbreak()
+ it("Visual area is correct when it ends before multibyte 'showbreak'", function()
+ local screen = Screen.new(60, 8)
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual
+ [2] = { bold = true }, -- ModeMsg
+ })
+ screen:attach()
+ exec([[
+ let &wrap = v:true
+ let &linebreak = v:true
+ let &showbreak = '↪ '
+ eval ['xxxxx ' .. 'y'->repeat(&columns - 6) .. ' zzzz']->setline(1)
+ normal! wvel
+ ]])
+ screen:expect([[
+ xxxxx |
+ {0:↪ }{1:yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy}^ {1: }|
+ {0:↪ }zzzz |
+ {0:~ }|*4
+ {2:-- VISUAL --} |
+ ]])
+ end)
end)
diff --git a/test/functional/legacy/mapping_spec.lua b/test/functional/legacy/mapping_spec.lua
index c1f23ab0a6..9eddec40f7 100644
--- a/test/functional/legacy/mapping_spec.lua
+++ b/test/functional/legacy/mapping_spec.lua
@@ -3,8 +3,8 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local expect, poke_eventloop = helpers.expect, helpers.poke_eventloop
-local command, eq, eval, meths = helpers.command, helpers.eq, helpers.eval, helpers.meths
-local sleep = helpers.sleep
+local command, eq, eval, api = helpers.command, helpers.eq, helpers.eval, helpers.api
+local sleep = vim.uv.sleep
describe('mapping', function()
before_each(clear)
@@ -110,7 +110,9 @@ describe('mapping', function()
command('imapclear')
command('set whichwrap=<,>,[,]')
feed('G3o<esc>2k')
- command([[:exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."]])
+ command(
+ [[:exe ":norm! iTest3: text with a (parenthesis here\<C-G>U\<Right>new line here\<esc>\<up>\<up>."]]
+ )
expect([[
@@ -132,9 +134,9 @@ describe('mapping', function()
command('nnoremap <LeftDrag> <LeftDrag><Cmd><CR>')
poke_eventloop()
- meths.input_mouse('left', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 0, 0, 1)
+ api.nvim_input_mouse('left', 'drag', '', 0, 0, 1)
poke_eventloop()
eq('s', eval('mode()'))
end)
@@ -145,9 +147,9 @@ describe('mapping', function()
command('inoremap <LeftDrag> <LeftDrag><Cmd>let g:dragged = 1<CR>')
feed('i')
poke_eventloop()
- meths.input_mouse('left', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 0, 0, 1)
+ api.nvim_input_mouse('left', 'drag', '', 0, 0, 1)
poke_eventloop()
eq(1, eval('g:dragged'))
eq('v', eval('mode()'))
@@ -156,9 +158,9 @@ describe('mapping', function()
command([[inoremap <LeftDrag> <LeftDrag><C-\><C-N>]])
feed('i')
poke_eventloop()
- meths.input_mouse('left', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 0, 0, 1)
+ api.nvim_input_mouse('left', 'drag', '', 0, 0, 1)
poke_eventloop()
eq('n', eval('mode()'))
end)
diff --git a/test/functional/legacy/match_spec.lua b/test/functional/legacy/match_spec.lua
index b6e45c396c..ab791f03e5 100644
--- a/test/functional/legacy/match_spec.lua
+++ b/test/functional/legacy/match_spec.lua
@@ -11,8 +11,8 @@ describe('matchaddpos()', function()
it('can add more than 8 match positions vim-patch:9.0.0620', function()
local screen = Screen.new(60, 14)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.Yellow}, -- Search
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.Yellow }, -- Search
})
screen:attach()
exec([[
@@ -43,8 +43,8 @@ describe('match highlighting', function()
it('does not continue in linebreak vim-patch:8.2.3698', function()
local screen = Screen.new(75, 10)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- ErrorMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg
})
screen:attach()
exec([=[
@@ -55,13 +55,7 @@ describe('match highlighting', function()
screen:expect([[
^xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx{1:]} |
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
|
]])
end)
@@ -69,9 +63,9 @@ describe('match highlighting', function()
it('is shown with incsearch vim-patch:8.2.3940', function()
local screen = Screen.new(75, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.Yellow}, -- Search
- [2] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- ErrorMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.Yellow }, -- Search
+ [2] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg
})
screen:attach()
exec([[
@@ -101,8 +95,8 @@ describe('match highlighting', function()
it('on a Tab vim-patch:8.2.4062', function()
local screen = Screen.new(75, 10)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- ErrorMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg
})
screen:attach()
exec([[
@@ -112,14 +106,7 @@ describe('match highlighting', function()
]])
screen:expect([[
{1: ^ }ix |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
|
]])
end)
diff --git a/test/functional/legacy/matchparen_spec.lua b/test/functional/legacy/matchparen_spec.lua
index 22d9247698..b03107deb0 100644
--- a/test/functional/legacy/matchparen_spec.lua
+++ b/test/functional/legacy/matchparen_spec.lua
@@ -13,8 +13,8 @@ describe('matchparen', function()
local screen = Screen.new(30, 7)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true},
- [2] = {background = Screen.colors.LightGrey},
+ [1] = { bold = true },
+ [2] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black },
})
exec([[
@@ -40,23 +40,19 @@ describe('matchparen', function()
it('matchparen highlight is cleared when switching buffer', function()
local screen = Screen.new(20, 5)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {background = Screen.colors.Cyan},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { background = Screen.colors.Cyan },
})
screen:attach()
local screen1 = [[
{1:^()} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]]
local screen2 = [[
^aa |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]]
@@ -86,11 +82,11 @@ describe('matchparen', function()
local screen = Screen.new(30, 9)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue};
- [1] = {background = Screen.colors.Plum1};
- [2] = {background = Screen.colors.Grey};
- [3] = {bold = true};
- [4] = {bold = true, foreground = Screen.colors.SeaGreen};
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { background = Screen.colors.Plum1 },
+ [2] = { background = Screen.colors.Grey },
+ [3] = { bold = true },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen },
})
exec([[
@@ -101,7 +97,8 @@ describe('matchparen', function()
]])
feed('i<C-X><C-N><C-N>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
aa |
aaa |
aaaa |
@@ -111,6 +108,7 @@ describe('matchparen', function()
{1: aaaa }{0: }|
{0:~ }|
{3:-- }{4:match 2 of 3} |
- ]]}
+ ]],
+ }
end)
end)
diff --git a/test/functional/legacy/memory_usage_spec.lua b/test/functional/legacy/memory_usage_spec.lua
index 5f722e5190..a05e9fdf57 100644
--- a/test/functional/legacy/memory_usage_spec.lua
+++ b/test/functional/legacy/memory_usage_spec.lua
@@ -19,7 +19,10 @@ if is_asan() then
return
elseif is_os('win') then
if is_ci('github') then
- pending('Windows runners in Github Actions do not have a stable environment to estimate memory usage', function() end)
+ pending(
+ 'Windows runners in Github Actions do not have a stable environment to estimate memory usage',
+ function() end
+ )
return
elseif eval("executable('wmic')") == 0 then
pending('missing "wmic" command', function() end)
@@ -34,9 +37,9 @@ local monitor_memory_usage = {
memory_usage = function(self)
local handle
if is_os('win') then
- handle = io.popen('wmic process where processid=' ..self.pid..' get WorkingSetSize')
+ handle = io.popen('wmic process where processid=' .. self.pid .. ' get WorkingSetSize')
else
- handle = io.popen('ps -o rss= -p '..self.pid)
+ handle = io.popen('ps -o rss= -p ' .. self.pid)
end
return tonumber(handle:read('*a'):match('%d+'))
end,
@@ -49,7 +52,7 @@ local monitor_memory_usage = {
table.insert(self.hist, val)
ok(#self.hist > 20)
local result = {}
- for key,value in ipairs(self.hist) do
+ for key, value in ipairs(self.hist) do
if value ~= self.hist[key + 1] then
table.insert(result, value)
end
@@ -60,7 +63,7 @@ local monitor_memory_usage = {
end)
end,
dump = function(self)
- return 'max: '..self.max ..', last: '..self.last
+ return 'max: ' .. self.max .. ', last: ' .. self.last
end,
monitor_memory_usage = function(self, pid)
local obj = {
@@ -72,12 +75,13 @@ local monitor_memory_usage = {
setmetatable(obj, { __index = self })
obj:op()
return obj
- end
+ end,
}
-setmetatable(monitor_memory_usage,
-{__call = function(self, pid)
- return monitor_memory_usage.monitor_memory_usage(self, pid)
-end})
+setmetatable(monitor_memory_usage, {
+ __call = function(self, pid)
+ return monitor_memory_usage.monitor_memory_usage(self, pid)
+ end,
+})
describe('memory usage', function()
local tmpfile = 'X_memory_usage'
@@ -101,46 +105,51 @@ describe('memory usage', function()
--[[
Case: if a local variable captures a:000, funccall object will be free
just after it finishes.
- ]]--
+ ]]
+ --
it('function capture vargs', function()
local pid = eval('getpid()')
local before = monitor_memory_usage(pid)
- write_file(tmpfile, [[
+ write_file(
+ tmpfile,
+ [[
func s:f(...)
let x = a:000
endfunc
for _ in range(10000)
call s:f(0)
endfor
- ]])
+ ]]
+ )
-- TODO: check_result fails if command() is used here. Why? #16064
- feed_command('source '..tmpfile)
+ feed_command('source ' .. tmpfile)
poke_eventloop()
local after = monitor_memory_usage(pid)
-- Estimate the limit of max usage as 2x initial usage.
-- The lower limit can fluctuate a bit, use 97%.
- check_result({before=before, after=after},
- pcall(ok, before.last * 97 / 100 < after.max))
- check_result({before=before, after=after},
- pcall(ok, before.last * 2 > after.max))
+ check_result({ before = before, after = after }, pcall(ok, before.last * 97 / 100 < after.max))
+ check_result({ before = before, after = after }, pcall(ok, before.last * 2 > after.max))
-- In this case, garbage collecting is not needed.
-- The value might fluctuate a bit, allow for 3% tolerance below and 5% above.
-- Based on various test runs.
local lower = after.last * 97 / 100
local upper = after.last * 105 / 100
- check_result({before=before, after=after}, pcall(ok, lower < after.max))
- check_result({before=before, after=after}, pcall(ok, after.max < upper))
+ check_result({ before = before, after = after }, pcall(ok, lower < after.max))
+ check_result({ before = before, after = after }, pcall(ok, after.max < upper))
end)
--[[
Case: if a local variable captures l: dict, funccall object will not be
free until garbage collector runs, but after that memory usage doesn't
increase so much even when rerun Xtest.vim since system memory caches.
- ]]--
+ ]]
+ --
it('function capture lvars', function()
local pid = eval('getpid()')
local before = monitor_memory_usage(pid)
- write_file(tmpfile, [[
+ write_file(
+ tmpfile,
+ [[
if !exists('s:defined_func')
func s:f()
let x = l:
@@ -150,13 +159,14 @@ describe('memory usage', function()
for _ in range(10000)
call s:f()
endfor
- ]])
- feed_command('source '..tmpfile)
+ ]]
+ )
+ feed_command('source ' .. tmpfile)
poke_eventloop()
local after = monitor_memory_usage(pid)
for _ = 1, 3 do
-- TODO: check_result fails if command() is used here. Why? #16064
- feed_command('source '..tmpfile)
+ feed_command('source ' .. tmpfile)
poke_eventloop()
end
local last = monitor_memory_usage(pid)
@@ -167,10 +177,8 @@ describe('memory usage', function()
local upper_multiplier = is_os('freebsd') and 19 or 12
local lower = before.last * 8 / 10
local upper = load_adjust((after.max + (after.last - before.last)) * upper_multiplier / 10)
- check_result({before=before, after=after, last=last},
- pcall(ok, lower < last.last))
- check_result({before=before, after=after, last=last},
- pcall(ok, last.last < upper))
+ check_result({ before = before, after = after, last = last }, pcall(ok, lower < last.last))
+ check_result({ before = before, after = after, last = last }, pcall(ok, last.last < upper))
end)
it('releases memory when closing windows when folds exist', function()
@@ -205,6 +213,6 @@ describe('memory usage', function()
-- but is small enough that if memory were not released (prior to PR #14884), the test
-- would fail.
local upper = before.last * 1.10
- check_result({before=before, after=after}, pcall(ok, after.last <= upper))
+ check_result({ before = before, after = after }, pcall(ok, after.last <= upper))
end)
end)
diff --git a/test/functional/legacy/messages_spec.lua b/test/functional/legacy/messages_spec.lua
index e0cc1dc79c..a87398b158 100644
--- a/test/functional/legacy/messages_spec.lua
+++ b/test/functional/legacy/messages_spec.lua
@@ -4,7 +4,7 @@ local clear = helpers.clear
local command = helpers.command
local exec = helpers.exec
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
local nvim_dir = helpers.nvim_dir
local assert_alive = helpers.assert_alive
@@ -17,10 +17,10 @@ describe('messages', function()
it('a warning causes scrolling if and only if it has a stacktrace', function()
screen = Screen.new(75, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
- [2] = {bold = true, reverse = true}, -- MsgSeparator
- [3] = {foreground = Screen.colors.Red}, -- WarningMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
+ [2] = { bold = true, reverse = true }, -- MsgSeparator
+ [3] = { foreground = Screen.colors.Red }, -- WarningMsg
})
screen:attach()
@@ -32,20 +32,17 @@ describe('messages', function()
command('enew')
command('set readonly')
feed('u')
- screen:expect({grid = [[
+ screen:expect({
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:W10: Warning: Changing a readonly file}^ |
- ]], timeout = 500})
+ ]],
+ timeout = 500,
+ })
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
Already at oldest change |
]])
end)
@@ -54,8 +51,8 @@ describe('messages', function()
it('clearing mode does not remove message', function()
screen = Screen.new(60, 10)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- ErrorMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg
})
screen:attach()
exec([[
@@ -74,12 +71,7 @@ describe('messages', function()
^one |
NoSuchFile |
three |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
from DebugSilent normal |
]])
@@ -89,12 +81,7 @@ describe('messages', function()
^one |
NoSuchFile |
three |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
from DebugSilent visual |
]])
@@ -105,11 +92,7 @@ describe('messages', function()
one |
NoSuchFil^e |
three |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
from DebugSilent visual |
{1:E447: Can't find file "NoSuchFile" in path} |
]])
@@ -124,8 +107,8 @@ describe('messages', function()
it('works', function()
screen = Screen.new(75, 6)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
- [2] = {foreground = Screen.colors.Brown}, -- LineNr
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
+ [2] = { foreground = Screen.colors.Brown }, -- LineNr
})
screen:attach()
@@ -421,15 +404,15 @@ describe('messages', function()
it('verbose message before echo command', function()
screen = Screen.new(60, 10)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
})
screen:attach()
- command('cd '..nvim_dir)
- meths.set_option_value('shell', './shell-test', {})
- meths.set_option_value('shellcmdflag', 'REP 20', {})
- meths.set_option_value('shellxquote', '', {}) -- win: avoid extra quotes
+ command('cd ' .. nvim_dir)
+ api.nvim_set_option_value('shell', './shell-test', {})
+ api.nvim_set_option_value('shellcmdflag', 'REP 20', {})
+ api.nvim_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>]])
@@ -475,18 +458,10 @@ describe('messages', function()
-- do the same with 'cmdheight' set to 2
feed('q')
command('set ch=2')
- command('mode') -- FIXME: bottom is invalid after scrolling
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
- |
+ {0:~ }|*7
+ |*2
]])
feed([[:4 verbose echo system('foo')<CR>]])
screen:expect([[
@@ -533,9 +508,9 @@ describe('messages', function()
it('with control characters can be quit vim-patch:8.2.1844', function()
screen = Screen.new(40, 10)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
- [2] = {foreground = Screen.colors.Blue}, -- SpecialKey
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
+ [2] = { foreground = Screen.colors.Blue }, -- SpecialKey
})
screen:attach()
@@ -555,14 +530,7 @@ describe('messages', function()
feed('q')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
|
]])
end)
@@ -572,9 +540,9 @@ describe('messages', function()
before_each(function()
screen = Screen.new(40, 6)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {bold = true}, -- ModeMsg
- [3] = {bold = true, reverse=true}, -- StatusLine
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { bold = true }, -- ModeMsg
+ [3] = { bold = true, reverse = true }, -- StatusLine
})
screen:attach()
end)
@@ -591,18 +559,14 @@ describe('messages', function()
feed('i')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{3: }|
{2:-- INSERT --} |
]])
feed('<C-C>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{3: }|
|
]])
@@ -617,18 +581,14 @@ describe('messages', function()
feed('i')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{3:[No Name] }|
{2:-- INSERT --} |
]])
feed('<Esc>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{3:[No Name] }|
|
]])
@@ -639,19 +599,13 @@ describe('messages', function()
feed('i<C-O>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{2:-- (insert) --} |
]])
feed('<C-C>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
end)
@@ -661,9 +615,9 @@ describe('messages', function()
it('y/n prompt works', function()
screen = Screen.new(75, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
- [2] = {bold = true, reverse = true}, -- MsgSeparator
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
+ [2] = { bold = true, reverse = true }, -- MsgSeparator
})
screen:attach()
command('set noincsearch nohlsearch inccommand=')
@@ -673,18 +627,14 @@ describe('messages', function()
screen:expect([[
1 |
2 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1:Backwards range given, OK to swap (y/n)?}^ |
]])
feed('n')
screen:expect([[
^1 |
2 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1:Backwards range given, OK to swap (y/n)?}n |
]])
@@ -692,18 +642,14 @@ describe('messages', function()
screen:expect([[
1 |
2 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1:Backwards range given, OK to swap (y/n)?}^ |
]])
feed('<Esc>')
screen:expect([[
^1 |
2 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1:Backwards range given, OK to swap (y/n)?}n |
]])
@@ -711,18 +657,14 @@ describe('messages', function()
screen:expect([[
1 |
2 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1:Backwards range given, OK to swap (y/n)?}^ |
]])
feed('y')
screen:expect([[
y1 |
^y2 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1:Backwards range given, OK to swap (y/n)?}y |
]])
end)
@@ -731,10 +673,10 @@ describe('messages', function()
it("fileinfo works when 'cmdheight' has just decreased", function()
screen = Screen.new(40, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}; -- NonText
- [1] = {bold = true}; -- TabLineSel
- [2] = {underline = true, background = Screen.colors.LightGrey}; -- TabLine
- [3] = {reverse = true}; -- TabLineFill
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true }, -- TabLineSel
+ [2] = { underline = true, background = Screen.colors.LightGrey }, -- TabLine
+ [3] = { reverse = true }, -- TabLineFill
})
screen:attach()
@@ -745,23 +687,18 @@ describe('messages', function()
tabnew
set cmdheight=2
]])
- command('mode') -- FIXME: bottom is invalid after scrolling
screen:expect([[
{2: [No Name] }{1: [No Name] }{3: }{2:X}|
^ |
- {0:~ }|
- {0:~ }|
- |
- |
+ {0:~ }|*2
+ |*2
]])
feed(':tabprev | edit Xfileinfo.txt<CR>')
screen:expect([[
{1: Xfileinfo.txt }{2: [No Name] }{3: }{2:X}|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
"Xfileinfo.txt" [New] |
]])
assert_alive()
@@ -771,7 +708,7 @@ describe('messages', function()
it('fileinfo does not overwrite echo message vim-patch:8.2.4156', function()
screen = Screen.new(40, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
})
screen:attach()
@@ -793,17 +730,9 @@ describe('messages', function()
feed('0$')
screen:expect([[
^hi |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
'b' written |
]])
os.remove('b.txt')
end)
-
- it('no crash when truncating overlong message', function()
- pcall(command, 'source test/old/testdir/crash/vim_msg_trunc_poc')
- assert_alive()
- end)
end)
diff --git a/test/functional/legacy/mksession_spec.lua b/test/functional/legacy/mksession_spec.lua
index bca9cd833c..689d918cd9 100644
--- a/test/functional/legacy/mksession_spec.lua
+++ b/test/functional/legacy/mksession_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local command = helpers.command
-local funcs = helpers.funcs
+local fn = helpers.fn
local eq = helpers.eq
describe('mksession', function()
@@ -18,7 +18,7 @@ describe('mksession', function()
command('mksession! Xtest_mks.out')
local found_rtp = 0
local found_pp = 0
- for _, line in pairs(funcs.readfile('Xtest_mks.out', 'b')) do
+ for _, line in pairs(fn.readfile('Xtest_mks.out', 'b')) do
if line:find('set runtimepath') then
found_rtp = found_rtp + 1
end
@@ -32,7 +32,7 @@ describe('mksession', function()
command('set sessionoptions+=skiprtp')
command('mksession! Xtest_mks.out')
local found_rtp_or_pp = 0
- for _, line in pairs(funcs.readfile('Xtest_mks.out', 'b')) do
+ for _, line in pairs(fn.readfile('Xtest_mks.out', 'b')) do
if line:find('set runtimepath') or line:find('set packpath') then
found_rtp_or_pp = found_rtp_or_pp + 1
end
diff --git a/test/functional/legacy/move_spec.lua b/test/functional/legacy/move_spec.lua
index 855996da8f..1500d48ad9 100644
--- a/test/functional/legacy/move_spec.lua
+++ b/test/functional/legacy/move_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local feed = helpers.feed
-local funcs = helpers.funcs
+local fn = helpers.fn
before_each(clear)
@@ -11,22 +11,18 @@ describe(':move', function()
it('redraws correctly when undone', function()
local screen = Screen.new(60, 10)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
})
screen:attach()
- funcs.setline(1, {'First', 'Second', 'Third', 'Fourth'})
+ fn.setline(1, { 'First', 'Second', 'Third', 'Fourth' })
feed('gg:move +1<CR>')
screen:expect([[
Second |
^First |
Third |
Fourth |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
:move +1 |
]])
@@ -38,11 +34,7 @@ describe(':move', function()
Second |
Third |
Fourth |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end)
diff --git a/test/functional/legacy/normal_spec.lua b/test/functional/legacy/normal_spec.lua
index ba875460f5..1dddeed033 100644
--- a/test/functional/legacy/normal_spec.lua
+++ b/test/functional/legacy/normal_spec.lua
@@ -7,35 +7,29 @@ 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([[
+ 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([[
+ screen:expect([[
{1: 2 }222222222222222222222222222222222222|
- {1: }222222222222222222222222222222222222|
- {1: }222222222222222222222222222222222222|
- {1: }222222222222222222222222222222222222|
- {1: }222222222222222222222222222222222222|
+ {1: }222222222222222222222222222222222222|*4
{1: }22222222222222222222 |
{1: 3 }333333333333333333333333333333333333|
- {1: }333333333333333333333333333333333333|
- {1: }333333333333333333333333333333333333|
- {1: }333333333333333333333333333333333333|
- {1: }333333333333333333333333333333333333|
+ {1: }333333333333333333333333333333333333|*4
{1: }33333333333333333333 |
{1: 4 }^444444444444444444444444444444444444|
- {1: }444444444444444444444444444444444444|
- {1: }444444444444444444444444444444444444|
- {1: }444444444444444444444444444444444444|
- {1: }444444444444444444444444444444444444|
+ {1: }444444444444444444444444444444444444|*4
{1: }44444444444444444444 |
|
]])
- end)
+ end
+ )
end)
diff --git a/test/functional/legacy/number_spec.lua b/test/functional/legacy/number_spec.lua
new file mode 100644
index 0000000000..c112532eed
--- /dev/null
+++ b/test/functional/legacy/number_spec.lua
@@ -0,0 +1,306 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear = helpers.clear
+local command = helpers.command
+local exec = helpers.exec
+local feed = helpers.feed
+
+describe("'number' and 'relativenumber'", function()
+ before_each(clear)
+
+ -- oldtest: Test_relativenumber_colors()
+ it('LineNr, LineNrAbove and LineNrBelow', function()
+ local screen = Screen.new(50, 10)
+ screen:set_default_attr_ids({
+ [1] = { foreground = Screen.colors.Red },
+ [2] = { foreground = Screen.colors.Blue },
+ [3] = { foreground = Screen.colors.Green },
+ })
+ screen:attach()
+ exec([[
+ call setline(1, range(200))
+ 111
+ set number relativenumber
+ hi LineNr guifg=red
+ ]])
+ screen:expect([[
+ {1: 4 }106 |
+ {1: 3 }107 |
+ {1: 2 }108 |
+ {1: 1 }109 |
+ {1:111 }^110 |
+ {1: 1 }111 |
+ {1: 2 }112 |
+ {1: 3 }113 |
+ {1: 4 }114 |
+ |
+ ]])
+ command('hi LineNrAbove guifg=blue')
+ screen:expect([[
+ {2: 4 }106 |
+ {2: 3 }107 |
+ {2: 2 }108 |
+ {2: 1 }109 |
+ {1:111 }^110 |
+ {1: 1 }111 |
+ {1: 2 }112 |
+ {1: 3 }113 |
+ {1: 4 }114 |
+ |
+ ]])
+ command('hi LineNrBelow guifg=green')
+ screen:expect([[
+ {2: 4 }106 |
+ {2: 3 }107 |
+ {2: 2 }108 |
+ {2: 1 }109 |
+ {1:111 }^110 |
+ {3: 1 }111 |
+ {3: 2 }112 |
+ {3: 3 }113 |
+ {3: 4 }114 |
+ |
+ ]])
+ command('hi clear LineNrAbove')
+ screen:expect([[
+ {1: 4 }106 |
+ {1: 3 }107 |
+ {1: 2 }108 |
+ {1: 1 }109 |
+ {1:111 }^110 |
+ {3: 1 }111 |
+ {3: 2 }112 |
+ {3: 3 }113 |
+ {3: 4 }114 |
+ |
+ ]])
+ end)
+
+ -- oldtest: Test_relativenumber_colors_wrapped()
+ it('LineNr, LineNrAbove and LineNrBelow with wrapped lines', function()
+ local screen = Screen.new(50, 20)
+ screen:set_default_attr_ids({
+ [1] = { background = Screen.colors.Red, foreground = Screen.colors.Black },
+ [2] = { background = Screen.colors.Blue, foreground = Screen.colors.Black },
+ [3] = { background = Screen.colors.Green, foreground = Screen.colors.Black },
+ [4] = { bold = true, foreground = Screen.colors.Blue },
+ })
+ screen:attach()
+ exec([[
+ set display=lastline scrolloff=0
+ call setline(1, range(200)->map('v:val->string()->repeat(40)'))
+ 111
+ set number relativenumber
+ hi LineNr guibg=red guifg=black
+ hi LineNrAbove guibg=blue guifg=black
+ hi LineNrBelow guibg=green guifg=black
+ ]])
+ screen:expect([[
+ {2: 2 }1081081081081081081081081081081081081081081081|
+ {2: }0810810810810810810810810810810810810810810810|
+ {2: }8108108108108108108108108108 |
+ {2: 1 }1091091091091091091091091091091091091091091091|
+ {2: }0910910910910910910910910910910910910910910910|
+ {2: }9109109109109109109109109109 |
+ {1:111 }^1101101101101101101101101101101101101101101101|
+ {1: }1011011011011011011011011011011011011011011011|
+ {1: }0110110110110110110110110110 |
+ {3: 1 }1111111111111111111111111111111111111111111111|
+ {3: }1111111111111111111111111111111111111111111111|
+ {3: }1111111111111111111111111111 |
+ {3: 2 }1121121121121121121121121121121121121121121121|
+ {3: }1211211211211211211211211211211211211211211211|
+ {3: }2112112112112112112112112112 |
+ {3: 3 }1131131131131131131131131131131131131131131131|
+ {3: }1311311311311311311311311311311311311311311311|
+ {3: }3113113113113113113113113113 |
+ {3: 4 }1141141141141141141141141141141141141141141{4:@@@}|
+ |
+ ]])
+ feed('k')
+ screen:expect([[
+ {2: 1 }1081081081081081081081081081081081081081081081|
+ {2: }0810810810810810810810810810810810810810810810|
+ {2: }8108108108108108108108108108 |
+ {1:110 }^1091091091091091091091091091091091091091091091|
+ {1: }0910910910910910910910910910910910910910910910|
+ {1: }9109109109109109109109109109 |
+ {3: 1 }1101101101101101101101101101101101101101101101|
+ {3: }1011011011011011011011011011011011011011011011|
+ {3: }0110110110110110110110110110 |
+ {3: 2 }1111111111111111111111111111111111111111111111|
+ {3: }1111111111111111111111111111111111111111111111|
+ {3: }1111111111111111111111111111 |
+ {3: 3 }1121121121121121121121121121121121121121121121|
+ {3: }1211211211211211211211211211211211211211211211|
+ {3: }2112112112112112112112112112 |
+ {3: 4 }1131131131131131131131131131131131131131131131|
+ {3: }1311311311311311311311311311311311311311311311|
+ {3: }3113113113113113113113113113 |
+ {3: 5 }1141141141141141141141141141141141141141141{4:@@@}|
+ |
+ ]])
+ feed('2j')
+ screen:expect([[
+ {2: 3 }1081081081081081081081081081081081081081081081|
+ {2: }0810810810810810810810810810810810810810810810|
+ {2: }8108108108108108108108108108 |
+ {2: 2 }1091091091091091091091091091091091091091091091|
+ {2: }0910910910910910910910910910910910910910910910|
+ {2: }9109109109109109109109109109 |
+ {2: 1 }1101101101101101101101101101101101101101101101|
+ {2: }1011011011011011011011011011011011011011011011|
+ {2: }0110110110110110110110110110 |
+ {1:112 }^1111111111111111111111111111111111111111111111|
+ {1: }1111111111111111111111111111111111111111111111|
+ {1: }1111111111111111111111111111 |
+ {3: 1 }1121121121121121121121121121121121121121121121|
+ {3: }1211211211211211211211211211211211211211211211|
+ {3: }2112112112112112112112112112 |
+ {3: 2 }1131131131131131131131131131131131131131131131|
+ {3: }1311311311311311311311311311311311311311311311|
+ {3: }3113113113113113113113113113 |
+ {3: 3 }1141141141141141141141141141141141141141141{4:@@@}|
+ |
+ ]])
+ feed('2j')
+ screen:expect([[
+ {2: 5 }1081081081081081081081081081081081081081081081|
+ {2: }0810810810810810810810810810810810810810810810|
+ {2: }8108108108108108108108108108 |
+ {2: 4 }1091091091091091091091091091091091091091091091|
+ {2: }0910910910910910910910910910910910910910910910|
+ {2: }9109109109109109109109109109 |
+ {2: 3 }1101101101101101101101101101101101101101101101|
+ {2: }1011011011011011011011011011011011011011011011|
+ {2: }0110110110110110110110110110 |
+ {2: 2 }1111111111111111111111111111111111111111111111|
+ {2: }1111111111111111111111111111111111111111111111|
+ {2: }1111111111111111111111111111 |
+ {2: 1 }1121121121121121121121121121121121121121121121|
+ {2: }1211211211211211211211211211211211211211211211|
+ {2: }2112112112112112112112112112 |
+ {1:114 }^1131131131131131131131131131131131131131131131|
+ {1: }1311311311311311311311311311311311311311311311|
+ {1: }3113113113113113113113113113 |
+ {3: 1 }1141141141141141141141141141141141141141141{4:@@@}|
+ |
+ ]])
+ feed('k')
+ screen:expect([[
+ {2: 4 }1081081081081081081081081081081081081081081081|
+ {2: }0810810810810810810810810810810810810810810810|
+ {2: }8108108108108108108108108108 |
+ {2: 3 }1091091091091091091091091091091091091091091091|
+ {2: }0910910910910910910910910910910910910910910910|
+ {2: }9109109109109109109109109109 |
+ {2: 2 }1101101101101101101101101101101101101101101101|
+ {2: }1011011011011011011011011011011011011011011011|
+ {2: }0110110110110110110110110110 |
+ {2: 1 }1111111111111111111111111111111111111111111111|
+ {2: }1111111111111111111111111111111111111111111111|
+ {2: }1111111111111111111111111111 |
+ {1:113 }^1121121121121121121121121121121121121121121121|
+ {1: }1211211211211211211211211211211211211211211211|
+ {1: }2112112112112112112112112112 |
+ {3: 1 }1131131131131131131131131131131131131131131131|
+ {3: }1311311311311311311311311311311311311311311311|
+ {3: }3113113113113113113113113113 |
+ {3: 2 }1141141141141141141141141141141141141141141{4:@@@}|
+ |
+ ]])
+ end)
+
+ -- oldtest: Test_relativenumber_callback()
+ it('relative line numbers are updated if cursor is moved from timer', function()
+ local screen = Screen.new(50, 8)
+ screen:set_default_attr_ids({
+ [1] = { foreground = Screen.colors.Brown }, -- LineNr
+ [2] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText
+ })
+ screen:attach()
+ exec([[
+ call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd'])
+ set relativenumber
+ call cursor(4, 1)
+
+ func Func(timer)
+ call cursor(1, 1)
+ endfunc
+
+ call timer_start(300, 'Func')
+ ]])
+ screen:expect({
+ grid = [[
+ {1: 3 }aaaaa |
+ {1: 2 }bbbbb |
+ {1: 1 }ccccc |
+ {1: 0 }^ddddd |
+ {2:~ }|*3
+ |
+ ]],
+ timeout = 100,
+ })
+ screen:expect({
+ grid = [[
+ {1: 0 }^aaaaa |
+ {1: 1 }bbbbb |
+ {1: 2 }ccccc |
+ {1: 3 }ddddd |
+ {2:~ }|*3
+ |
+ ]],
+ })
+ end)
+
+ -- oldtest: Test_number_insert_delete_lines()
+ it('line numbers are updated when deleting/inserting lines', function()
+ local screen = Screen.new(50, 8)
+ screen:set_default_attr_ids({
+ [1] = { foreground = Screen.colors.Brown }, -- LineNr
+ [2] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText
+ })
+ screen:attach()
+ exec([[
+ call setline(1, range(1, 7))
+ set number
+ call cursor(2, 1)
+ ]])
+ local snapshot1 = [[
+ {1: 1 }1 |
+ {1: 2 }^2 |
+ {1: 3 }3 |
+ {1: 4 }4 |
+ {1: 5 }5 |
+ {1: 6 }6 |
+ {1: 7 }7 |
+ |
+ ]]
+ screen:expect(snapshot1)
+ feed('dd')
+ screen:expect([[
+ {1: 1 }1 |
+ {1: 2 }^3 |
+ {1: 3 }4 |
+ {1: 4 }5 |
+ {1: 5 }6 |
+ {1: 6 }7 |
+ {2:~ }|
+ |
+ ]])
+ feed('P')
+ screen:expect(snapshot1)
+ feed('2dd')
+ screen:expect([[
+ {1: 1 }1 |
+ {1: 2 }^4 |
+ {1: 3 }5 |
+ {1: 4 }6 |
+ {1: 5 }7 |
+ {2:~ }|*2
+ |
+ ]])
+ feed('P')
+ screen:expect(snapshot1)
+ end)
+end)
diff --git a/test/functional/legacy/options_spec.lua b/test/functional/legacy/options_spec.lua
index ce46ea013d..2f20b6bd51 100644
--- a/test/functional/legacy/options_spec.lua
+++ b/test/functional/legacy/options_spec.lua
@@ -2,8 +2,8 @@
local helpers = require('test.functional.helpers')(after_each)
local command, clear = helpers.command, helpers.clear
local source, expect = helpers.source, helpers.expect
-local exc_exec = helpers.exc_exec;
-local matches = helpers.matches;
+local exc_exec = helpers.exc_exec
+local matches = helpers.matches
local Screen = require('test.functional.ui.screen')
describe('options', function()
@@ -66,17 +66,7 @@ describe('set', function()
command('verbose set scroll?')
screen:expect([[
|
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*11
|
scroll=7 |
Last set from changed window size |
diff --git a/test/functional/legacy/prompt_buffer_spec.lua b/test/functional/legacy/prompt_buffer_spec.lua
index 5c3f8a6f8c..e4810feedb 100644
--- a/test/functional/legacy/prompt_buffer_spec.lua
+++ b/test/functional/legacy/prompt_buffer_spec.lua
@@ -4,8 +4,9 @@ local feed = helpers.feed
local source = helpers.source
local clear = helpers.clear
local command = helpers.command
+local expect = helpers.expect
local poke_eventloop = helpers.poke_eventloop
-local meths = helpers.meths
+local api = helpers.api
local eq = helpers.eq
local neq = helpers.neq
@@ -57,14 +58,10 @@ describe('prompt buffer', function()
]])
screen:expect([[
cmd: ^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
[Prompt] [+] |
other buffer |
- ~ |
- ~ |
- ~ |
+ ~ |*3
-- INSERT -- |
]])
end
@@ -76,7 +73,7 @@ describe('prompt buffer', function()
-- oldtest: Test_prompt_basic()
it('works', function()
source_script()
- feed("hello\n")
+ feed('hello\n')
screen:expect([[
cmd: hello |
Command: "hello" |
@@ -84,22 +81,13 @@ describe('prompt buffer', function()
cmd: ^ |
[Prompt] |
other buffer |
- ~ |
- ~ |
- ~ |
+ ~ |*3
-- INSERT -- |
]])
- feed("exit\n")
+ feed('exit\n')
screen:expect([[
^other buffer |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*8
|
]])
end)
@@ -107,69 +95,46 @@ describe('prompt buffer', function()
-- oldtest: Test_prompt_editing()
it('editing', function()
source_script()
- feed("hello<BS><BS>")
+ feed('hello<BS><BS>')
screen:expect([[
cmd: hel^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
[Prompt] [+] |
other buffer |
- ~ |
- ~ |
- ~ |
+ ~ |*3
-- INSERT -- |
]])
- feed("<Left><Left><Left><BS>-")
+ feed('<Left><Left><Left><BS>-')
screen:expect([[
cmd: -^hel |
- ~ |
- ~ |
- ~ |
+ ~ |*3
[Prompt] [+] |
other buffer |
- ~ |
- ~ |
- ~ |
+ ~ |*3
-- INSERT -- |
]])
- feed("<C-O>lz")
+ feed('<C-O>lz')
screen:expect([[
cmd: -hz^el |
- ~ |
- ~ |
- ~ |
+ ~ |*3
[Prompt] [+] |
other buffer |
- ~ |
- ~ |
- ~ |
+ ~ |*3
-- INSERT -- |
]])
- feed("<End>x")
+ feed('<End>x')
screen:expect([[
cmd: -hzelx^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
[Prompt] [+] |
other buffer |
- ~ |
- ~ |
- ~ |
+ ~ |*3
-- INSERT -- |
]])
- feed("<C-U>exit\n")
+ feed('<C-U>exit\n')
screen:expect([[
^other buffer |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*8
|
]])
end)
@@ -177,43 +142,33 @@ describe('prompt buffer', function()
-- oldtest: Test_prompt_switch_windows()
it('switch windows', function()
source_script()
- feed("<C-O>:call SwitchWindows()<CR>")
- screen:expect{grid=[[
+ feed('<C-O>:call SwitchWindows()<CR>')
+ screen:expect {
+ grid = [[
cmd: |
- ~ |
- ~ |
- ~ |
+ ~ |*3
[Prompt] [+] |
^other buffer |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
- ]]}
- feed("<C-O>:call SwitchWindows()<CR>")
+ ]],
+ }
+ feed('<C-O>:call SwitchWindows()<CR>')
screen:expect([[
cmd: ^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
[Prompt] [+] |
other buffer |
- ~ |
- ~ |
- ~ |
+ ~ |*3
-- INSERT -- |
]])
- feed("<Esc>")
+ feed('<Esc>')
screen:expect([[
cmd:^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
[Prompt] [+] |
other buffer |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
]])
end)
@@ -226,12 +181,12 @@ describe('prompt buffer', function()
call timer_start(0, {-> nvim_buf_set_lines(s:buf, -1, -1, 0, ['walrus'])})
]]
poke_eventloop()
- eq({ mode = 'i', blocking = false }, meths.get_mode())
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
end)
-- oldtest: Test_prompt_appending_while_hidden()
it('accessing hidden prompt buffer does not start insert mode', function()
- local prev_win = meths.get_current_win()
+ local prev_win = api.nvim_get_current_win()
source([[
new prompt
set buftype=prompt
@@ -251,16 +206,48 @@ describe('prompt buffer', function()
endfunc
]])
feed('asomething<CR>')
- eq('something', meths.get_var('entered'))
- neq(prev_win, meths.get_current_win())
+ eq('something', api.nvim_get_var('entered'))
+ neq(prev_win, api.nvim_get_current_win())
feed('exit<CR>')
- eq(prev_win, meths.get_current_win())
- eq({ mode = 'n', blocking = false }, meths.get_mode())
+ eq(prev_win, api.nvim_get_current_win())
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
command('call DoAppend()')
- eq({ mode = 'n', blocking = false }, meths.get_mode())
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
feed('i')
- eq({ mode = 'i', blocking = false }, meths.get_mode())
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
command('call DoAppend()')
- eq({ mode = 'i', blocking = false }, meths.get_mode())
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
+ end)
+
+ -- oldtest: Test_prompt_leave_modify_hidden()
+ it('modifying hidden buffer does not prevent prompt buffer mode change', function()
+ source([[
+ file hidden
+ set bufhidden=hide
+ enew
+ new prompt
+ set buftype=prompt
+
+ inoremap <buffer> w <Cmd>wincmd w<CR>
+ inoremap <buffer> q <Cmd>bwipe!<CR>
+ autocmd BufLeave prompt call appendbufline('hidden', '$', 'Leave')
+ autocmd BufEnter prompt call appendbufline('hidden', '$', 'Enter')
+ autocmd BufWinLeave prompt call appendbufline('hidden', '$', 'Close')
+ ]])
+ feed('a')
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
+ feed('w')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
+ feed('<C-W>w')
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
+ feed('q')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
+ command('bwipe!')
+ expect([[
+
+ Leave
+ Enter
+ Leave
+ Close]])
end)
end)
diff --git a/test/functional/legacy/put_spec.lua b/test/functional/legacy/put_spec.lua
index 4a42a1c8a3..c78946d690 100644
--- a/test/functional/legacy/put_spec.lua
+++ b/test/functional/legacy/put_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local exec_lua = helpers.exec_lua
-local meths = helpers.meths
+local api = helpers.api
local source = helpers.source
local eq = helpers.eq
@@ -15,7 +15,9 @@ end
describe('put', function()
before_each(clear)
- after_each(function() eq({}, meths.get_vvar('errors')) end)
+ after_each(function()
+ eq({}, api.nvim_get_vvar('errors'))
+ end)
it('very large count 64-bit', function()
if sizeoflong() < 8 then
@@ -64,8 +66,7 @@ describe('put', function()
three more text │ three more text |
^four more text │ four more text |
│ |
- ~ │~ |
- ~ │~ |
+ ~ │~ |*2
[No Name] [+] [No Name] [+] |
|
]])
diff --git a/test/functional/legacy/scroll_opt_spec.lua b/test/functional/legacy/scroll_opt_spec.lua
index 8ac1141c2b..8d22c299d6 100644
--- a/test/functional/legacy/scroll_opt_spec.lua
+++ b/test/functional/legacy/scroll_opt_spec.lua
@@ -23,9 +23,9 @@ describe('smoothscroll', function()
set number
]])
feed('<C-Y>')
- screen:expect({any = " 1 ^one"})
+ screen:expect({ any = ' 1 ^one' })
feed('<C-E><C-E><C-E>')
- screen:expect({any = " 2 ^two"})
+ screen:expect({ any = ' 2 ^two' })
end)
-- oldtest: Test_smoothscroll_CtrlE_CtrlY()
@@ -36,17 +36,14 @@ describe('smoothscroll', function()
:5
]])
local s1 = [[
- word word word word word word word word |
- word word word word word word word word |
+ word word word word word word word word |*2
word word word word |
line three |
long word long word long word long word |
long word long word long word |
^line |
- line |
- line |
- ~ |
- ~ |
+ line |*2
+ ~ |*2
|
]]
local s2 = [[
@@ -56,11 +53,8 @@ describe('smoothscroll', function()
long word long word long word long word |
long word long word long word |
^line |
- line |
- line |
- ~ |
- ~ |
- ~ |
+ line |*2
+ ~ |*3
|
]]
local s3 = [[
@@ -69,26 +63,17 @@ describe('smoothscroll', function()
long word long word long word long word |
long word long word long word |
^line |
- line |
- line |
- ~ |
- ~ |
- ~ |
- ~ |
+ line |*2
+ ~ |*4
|
]]
local s4 = [[
line three |
long word long word long word long word |
long word long word long word |
- line |
- line |
+ line |*2
^line |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*5
|
]]
local s5 = [[
@@ -96,13 +81,9 @@ describe('smoothscroll', function()
line three |
long word long word long word long word |
long word long word long word |
- line |
- line |
+ line |*2
^line |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
|
]]
local s6 = [[
@@ -111,38 +92,30 @@ describe('smoothscroll', function()
line three |
long word long word long word long word |
long word long word long word |
- line |
- line |
+ line |*2
^line |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
]]
local s7 = [[
- word word word word word word word word |
- word word word word word word word word |
+ word word word word word word word word |*2
word word word word |
line three |
long word long word long word long word |
long word long word long word |
- line |
- line |
+ line |*2
^line |
- ~ |
- ~ |
+ ~ |*2
|
]]
local s8 = [[
line one |
- word word word word word word word word |
- word word word word word word word word |
+ word word word word word word word word |*2
word word word word |
line three |
long word long word long word long word |
long word long word long word |
- line |
- line |
+ line |*2
^line |
~ |
|
@@ -187,8 +160,7 @@ describe('smoothscroll', function()
ϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛϛ^ϛϛϛϛϛ|
ϛϛϛϛϛ |
222222222222222222222222222222222222 |
- ~ |
- ~ |
+ ~ |*2
|
]])
end)
@@ -217,9 +189,7 @@ describe('smoothscroll', function()
3 ^line |
4 line |
5 line |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
]])
feed('<C-E>')
@@ -231,10 +201,7 @@ describe('smoothscroll', function()
3 ^line |
4 line |
5 line |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
|
]])
feed('<C-E>')
@@ -245,11 +212,7 @@ describe('smoothscroll', function()
3 ^line |
4 line |
5 line |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*5
|
]])
exec('set cpo-=n')
@@ -261,10 +224,7 @@ describe('smoothscroll', function()
3 ^line |
4 line |
5 line |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
|
]])
feed('<C-Y>')
@@ -277,9 +237,7 @@ describe('smoothscroll', function()
3 ^line |
4 line |
5 line |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
]])
feed('<C-Y>')
@@ -293,8 +251,7 @@ describe('smoothscroll', function()
3 ^line |
4 line |
5 line |
- ~ |
- ~ |
+ ~ |*2
|
]])
exec('botright split')
@@ -351,18 +308,13 @@ describe('smoothscroll', function()
y long text very long text very long|
text very long text very long text |
1 three |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*6
--No lines in buffer-- |
]])
end)
-- oldtest: Test_smoothscroll_list()
- it("works with list mode", function()
+ it('works with list mode', function()
screen:try_resize(40, 8)
exec([[
set smoothscroll scrolloff=0
@@ -376,8 +328,7 @@ describe('smoothscroll', function()
very long text very long text very long |
text very long text- |
three |
- ~ |
- ~ |
+ ~ |*2
|
]])
exec('set listchars+=precedes:#')
@@ -387,14 +338,13 @@ describe('smoothscroll', function()
very long text very long text very long |
text very long text- |
three |
- ~ |
- ~ |
+ ~ |*2
|
]])
end)
-- oldtest: Test_smoothscroll_diff_mode()
- it("works with diff mode", function()
+ it('works with diff mode', function()
screen:try_resize(40, 8)
exec([[
let text = 'just some text here'
@@ -408,8 +358,7 @@ describe('smoothscroll', function()
]])
screen:expect([[
- ^just some text here |
- ~ |
- ~ |
+ ~ |*2
[No Name] [+] |
- just some text here |
~ |
@@ -476,7 +425,7 @@ describe('smoothscroll', function()
end)
-- oldtest: Test_smoothscroll_wrap_long_line()
- it("adjusts the cursor position in a long line", function()
+ it('adjusts the cursor position in a long line', function()
screen:try_resize(40, 6)
exec([[
call setline(1, ['one', 'two', 'Line' .. (' with lots of text'->repeat(30)) .. ' end', 'four'])
@@ -580,10 +529,7 @@ describe('smoothscroll', function()
feed('zt')
screen:expect([[
^four |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
|
]])
feed('zz')
@@ -591,8 +537,7 @@ describe('smoothscroll', function()
<<<of text with lots of text with lots o|
f text with lots of text end |
^four |
- ~ |
- ~ |
+ ~ |*2
|
]])
feed('zb')
@@ -608,7 +553,9 @@ describe('smoothscroll', function()
-- This time, use a shorter long line that is barely long enough to span more
-- 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'])")
+ 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()
@@ -630,7 +577,7 @@ describe('smoothscroll', function()
end)
-- oldtest: Test_smoothscroll_one_long_line()
- it("scrolls correctly when moving the cursor", function()
+ it('scrolls correctly when moving the cursor', function()
screen:try_resize(40, 6)
exec([[
call setline(1, 'with lots of text '->repeat(7))
@@ -650,8 +597,7 @@ describe('smoothscroll', function()
<<<ts of text with lots of text with lot|
^s of text with lots of text with lots of|
text |
- ~ |
- ~ |
+ ~ |*2
|
]])
feed('0')
@@ -659,7 +605,7 @@ describe('smoothscroll', function()
end)
-- oldtest: Test_smoothscroll_long_line_showbreak()
- it("cursor is not one screen line too far down", function()
+ it('cursor is not one screen line too far down', function()
screen:try_resize(40, 6)
-- a line that spans four screen lines
exec("call setline(1, 'with lots of text in one line '->repeat(6))")
@@ -696,28 +642,23 @@ describe('smoothscroll', function()
screen:expect([[
^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
å£å£å£å£å£å£å£å£å£å£ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
]])
feed('<C-E>')
screen:expect([[
<<< å£å£å£å£å£å£å£^å£ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
|
]])
end)
-- oldtest: Test_smoothscroll_zero_width()
- it("does not divide by zero with a narrow window", function()
+ it('does not divide by zero with a narrow window', function()
screen:try_resize(12, 2)
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.Brown},
- [2] = {foreground = Screen.colors.Blue1, bold = true},
+ [1] = { foreground = Screen.colors.Brown },
+ [2] = { foreground = Screen.colors.Blue1, bold = true },
})
exec([[
call setline(1, ['a'->repeat(100)])
@@ -739,7 +680,7 @@ describe('smoothscroll', function()
end)
-- oldtest: Test_smoothscroll_ins_lines()
- it("does not unnecessarily insert lines", function()
+ it('does not unnecessarily insert lines', function()
screen:try_resize(40, 6)
exec([=[
set wrap smoothscroll scrolloff=0 conceallevel=2 concealcursor=nc
@@ -763,7 +704,7 @@ describe('smoothscroll', function()
end)
-- oldtest: Test_smoothscroll_cursormoved_line()
- it("does not place the cursor in the command line", function()
+ it('does not place the cursor in the command line', function()
screen:try_resize(40, 6)
exec([=[
set smoothscroll
@@ -786,7 +727,7 @@ describe('smoothscroll', function()
end)
-- oldtest: Test_smoothscroll_eob()
- it("does not scroll halfway at end of buffer", function()
+ it('does not scroll halfway at end of buffer', function()
screen:try_resize(40, 10)
exec([[
set smoothscroll
@@ -795,14 +736,7 @@ describe('smoothscroll', function()
]])
-- does not scroll halfway when scrolling to end of buffer
screen:expect([[
- |
- |
- |
- |
- |
- |
- |
- |
+ |*8
^ |
|
]])
@@ -811,26 +745,20 @@ describe('smoothscroll', function()
-- cursor is not placed below window
screen:expect([[
<<<aaaaaaaaaaaaaaaaa |
- |
- |
- |
- |
- |
- |
- |
+ |*7
^ |
|
]])
end)
-- oldtest: Test_smoothscroll_incsearch()
- it("does not reset skipcol when doing incremental search on the same word", function()
+ 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},
+ [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
@@ -888,8 +816,8 @@ describe('smoothscroll', function()
it('scrolling multiple lines and stopping at non-zero skipcol', function()
screen:try_resize(40, 10)
screen:set_default_attr_ids({
- [0] = {foreground = Screen.colors.Blue, bold = true},
- [1] = {background = Screen.colors.Grey90},
+ [0] = { foreground = Screen.colors.Blue, bold = true },
+ [1] = { background = Screen.colors.Grey90 },
})
exec([[
setlocal cursorline scrolloff=0 smoothscroll
@@ -907,8 +835,7 @@ describe('smoothscroll', function()
aaaaaaaaaa |
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaa |
- |
- |
+ |*2
bbb |
|
]])
@@ -917,25 +844,19 @@ describe('smoothscroll', function()
{0:<<<}{1:aaaaaa^a }|
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaa |
- |
- |
+ |*2
bbb |
ccc |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('2<C-E>')
screen:expect([[
{0:<<<}{1:aaaaaa^a }|
- |
- |
+ |*2
bbb |
ccc |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end)
@@ -944,10 +865,10 @@ describe('smoothscroll', function()
it('does not divide by zero in zero-width window', function()
screen:try_resize(40, 19)
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.Brown}; -- LineNr
- [2] = {bold = true, foreground = Screen.colors.Blue}; -- NonText
- [3] = {bold = true, reverse = true}; -- StatusLine
- [4] = {reverse = true}; -- StatusLineNC
+ [1] = { foreground = Screen.colors.Brown }, -- LineNr
+ [2] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [3] = { bold = true, reverse = true }, -- StatusLine
+ [4] = { reverse = true }, -- StatusLineNC
})
exec([[
silent normal yy
@@ -962,21 +883,7 @@ describe('smoothscroll', function()
]])
screen:expect([[
{1: }│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
- {2:@}│ |
+ {2:@}│ |*15
{2:^@}│ |
{3:< }{4:[No Name] [+] }|
|
@@ -1001,8 +908,7 @@ describe('smoothscroll', function()
line3line3line3line3line3line3line3line3|
line3line3line3line3 |
line4 |
- ~ |
- ~ |
+ ~ |*2
[No Name] [+] |
|
]])
@@ -1023,7 +929,7 @@ describe('smoothscroll', function()
assert_alive()
end)
- it("works with virt_lines above and below", function()
+ it('works with virt_lines above and below', function()
screen:try_resize(55, 7)
exec([=[
call setline(1, ['Line' .. (' with some text'->repeat(7))]->repeat(3))
@@ -1096,6 +1002,22 @@ describe('smoothscroll', function()
]])
end)
+ it('works in Insert mode at bottom of window', function()
+ screen:try_resize(40, 9)
+ exec([[
+ call setline(1, repeat([repeat('A very long line ...', 10)], 5))
+ set wrap smoothscroll scrolloff=0
+ ]])
+ feed('Go123456789<CR>')
+ screen:expect([[
+ <<<ery long line ...A very long line ...|
+ A very long line ...A very long line ...|*5
+ 123456789 |
+ ^ |
+ -- INSERT -- |
+ ]])
+ end)
+
it('<<< marker shows with tabline, winbar and splits', function()
screen:try_resize(40, 12)
exec([[
@@ -1153,8 +1075,8 @@ describe('smoothscroll', function()
it('works with very long line', function()
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.Brown},
- [2] = {foreground = Screen.colors.Blue1, bold = true},
+ [1] = { foreground = Screen.colors.Brown },
+ [2] = { foreground = Screen.colors.Blue1, bold = true },
})
exec([[
edit test/functional/fixtures/bigfile_oneline.txt
diff --git a/test/functional/legacy/search_spec.lua b/test/functional/legacy/search_spec.lua
index 25620f5262..2fda341123 100644
--- a/test/functional/legacy/search_spec.lua
+++ b/test/functional/legacy/search_spec.lua
@@ -5,7 +5,7 @@ local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
local feed = helpers.feed
-local funcs = helpers.funcs
+local fn = helpers.fn
local poke_eventloop = helpers.poke_eventloop
local exec = helpers.exec
@@ -18,7 +18,7 @@ describe('search cmdline', function()
screen = Screen.new(20, 3)
screen:attach()
screen:set_default_attr_ids({
- inc = {reverse = true},
+ inc = { reverse = true },
err = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
more = { bold = true, foreground = Screen.colors.SeaGreen4 },
tilde = { bold = true, foreground = Screen.colors.Blue1 },
@@ -27,9 +27,17 @@ describe('search cmdline', function()
end)
local function tenlines()
- funcs.setline(1, {
- ' 1', ' 2 these', ' 3 the', ' 4 their', ' 5 there',
- ' 6 their', ' 7 the', ' 8 them', ' 9 these', ' 10 foobar'
+ fn.setline(1, {
+ ' 1',
+ ' 2 these',
+ ' 3 the',
+ ' 4 their',
+ ' 5 there',
+ ' 6 their',
+ ' 7 the',
+ ' 8 them',
+ ' 9 these',
+ ' 10 foobar',
})
command('1')
end
@@ -47,7 +55,7 @@ describe('search cmdline', function()
describe('can traverse matches', function()
before_each(tenlines)
local function forwarditer(wrapscan)
- command('set incsearch '..wrapscan)
+ command('set incsearch ' .. wrapscan)
feed('/the')
screen:expect([[
1 |
@@ -60,7 +68,7 @@ describe('search cmdline', function()
3 {inc:the} |
/the^ |
]])
- eq({0, 0, 0, 0}, funcs.getpos('"'))
+ eq({ 0, 0, 0, 0 }, fn.getpos('"'))
feed('<C-G>')
screen:expect([[
3 the |
@@ -106,20 +114,23 @@ describe('search cmdline', function()
/the^ |
]])
else
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
8 them |
9 {inc:the}se |
/the^ |
- ]], condition=function()
- eq(true, screen.bell)
- end}
+ ]],
+ condition = function()
+ eq(true, screen.bell)
+ end,
+ }
feed('<CR>')
- eq({0, 0, 0, 0}, funcs.getpos('"'))
+ eq({ 0, 0, 0, 0 }, fn.getpos('"'))
end
end
local function backiter(wrapscan)
- command('set incsearch '..wrapscan)
+ command('set incsearch ' .. wrapscan)
command('$')
feed('?the')
@@ -144,13 +155,16 @@ describe('search cmdline', function()
]])
else
feed('<C-G>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
9 {inc:the}se |
10 foobar |
?the^ |
- ]], condition=function()
- eq(true, screen.bell)
- end}
+ ]],
+ condition = function()
+ eq(true, screen.bell)
+ end,
+ }
feed('<CR>')
screen:expect([[
9 ^these |
@@ -193,13 +207,16 @@ describe('search cmdline', function()
?the^ |
]])
else
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
2 {inc:the}se |
3 the |
?the^ |
- ]], condition=function()
- eq(true, screen.bell)
- end}
+ ]],
+ condition = function()
+ eq(true, screen.bell)
+ end,
+ }
end
end
@@ -351,7 +368,7 @@ describe('search cmdline', function()
end)
it('can traverse matches in the same line with <C-G>/<C-T>', function()
- funcs.setline(1, { ' 1', ' 2 these', ' 3 the theother' })
+ fn.setline(1, { ' 1', ' 2 these', ' 3 the theother' })
command('1')
command('set incsearch')
@@ -439,9 +456,16 @@ describe('search cmdline', function()
10 ^foobar |
/fo |
]])
- eq({lnum = 10, leftcol = 0, col = 4, topfill = 0, topline = 6,
- coladd = 0, skipcol = 0, curswant = 4},
- funcs.winsaveview())
+ eq({
+ lnum = 10,
+ leftcol = 0,
+ col = 4,
+ topfill = 0,
+ topline = 6,
+ coladd = 0,
+ skipcol = 0,
+ curswant = 4,
+ }, fn.winsaveview())
end)
it('restores original view after failed search', function()
@@ -467,16 +491,23 @@ describe('search cmdline', function()
{more:Press ENTER or type command to continue}^ |
]])
feed('<CR>')
- eq({lnum = 1, leftcol = 0, col = 0, topfill = 0, topline = 1,
- coladd = 0, skipcol = 0, curswant = 0},
- funcs.winsaveview())
+ eq({
+ lnum = 1,
+ leftcol = 0,
+ col = 0,
+ topfill = 0,
+ topline = 1,
+ coladd = 0,
+ skipcol = 0,
+ curswant = 0,
+ }, fn.winsaveview())
end)
-- oldtest: Test_search_cmdline4().
it("CTRL-G with 'incsearch' and ? goes in the right direction", function()
screen:try_resize(40, 4)
command('enew!')
- funcs.setline(1, {' 1 the first', ' 2 the second', ' 3 the third'})
+ fn.setline(1, { ' 1 the first', ' 2 the second', ' 3 the third' })
command('set laststatus=0 shortmess+=s')
command('set incsearch')
command('$')
@@ -577,7 +608,7 @@ describe('search cmdline', function()
it('incsearch works with :sort', function()
screen:try_resize(20, 4)
command('set incsearch hlsearch scrolloff=0')
- funcs.setline(1, {'another one 2', 'that one 3', 'the one 1'})
+ fn.setline(1, { 'another one 2', 'that one 3', 'the one 1' })
feed(':sort ni u /on')
screen:expect([[
@@ -593,7 +624,7 @@ describe('search cmdline', function()
it('incsearch works with :vimgrep family', function()
screen:try_resize(30, 4)
command('set incsearch hlsearch scrolloff=0')
- funcs.setline(1, {'another one 2', 'that one 3', 'the one 1'})
+ fn.setline(1, { 'another one 2', 'that one 3', 'the one 1' })
feed(':vimgrep on')
screen:expect([[
@@ -688,27 +719,18 @@ describe('search cmdline', function()
local s = [[
{tilde:<<<} 18 19 20 21 22 2|
^3 24 |
- |
- |
- |
- |
+ |*4
]]
screen:expect(s)
feed('/xx')
screen:expect([[
- |
- |
- |
- |
+ |*4
{inc:xx}x |
/xx^ |
]])
feed('x')
screen:expect([[
- |
- |
- |
- |
+ |*4
{inc:xxx} |
/xxx^ |
]])
@@ -724,9 +746,9 @@ describe('Search highlight', function()
it('beyond line end vim-patch:8.2.2542', function()
local screen = Screen.new(50, 6)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {background = Screen.colors.Yellow}, -- Search
- [3] = {background = Screen.colors.Grey90}, -- CursorLine
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { background = Screen.colors.Yellow }, -- Search
+ [3] = { background = Screen.colors.Grey90 }, -- CursorLine
})
screen:attach()
exec([[
@@ -737,11 +759,9 @@ describe('Search highlight', function()
]])
feed([[/\_.*<CR>]])
screen:expect([[
- {2:xxx } |
- {2:xxx } |
+ {2:xxx } |*2
{2:^xxx }{3: }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
/\_.* |
]])
end)
@@ -750,11 +770,11 @@ describe('Search highlight', function()
it('is combined with Visual highlight vim-patch:8.2.2797', function()
local screen = Screen.new(40, 6)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {bold = true}, -- ModeMsg, Search
- [3] = {background = Screen.colors.LightGrey}, -- Visual
- [4] = {background = Screen.colors.Yellow, bold = true}, -- Search
- [5] = {background = Screen.colors.LightGrey, bold = true}, -- Visual + Search
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { bold = true }, -- ModeMsg, Search
+ [3] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual
+ [4] = { background = Screen.colors.Yellow, bold = true }, -- Search
+ [5] = { background = Screen.colors.LightGrey, bold = true, foreground = Screen.colors.Black },
})
screen:attach()
exec([[
@@ -769,8 +789,7 @@ describe('Search highlight', function()
xxx {4:y}{5:yy}{3: zzz} |
{3:xxx }{5:yyy}{3: zzz} |
{3:xxx }{5:y}{4:^yy} zzz |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:-- VISUAL --} |
]])
end)
diff --git a/test/functional/legacy/search_stat_spec.lua b/test/functional/legacy/search_stat_spec.lua
index bd5ab68e5c..378060d316 100644
--- a/test/functional/legacy/search_stat_spec.lua
+++ b/test/functional/legacy/search_stat_spec.lua
@@ -8,11 +8,11 @@ describe('search stat', function()
clear()
screen = Screen.new(30, 10)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {background = Screen.colors.Yellow}, -- Search
- [3] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey}, -- Folded
- [4] = {reverse = true}, -- IncSearch, TabLineFill
- [5] = {foreground = Screen.colors.Red}, -- WarningMsg
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { background = Screen.colors.Yellow }, -- Search
+ [3] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey }, -- Folded
+ [4] = { reverse = true }, -- IncSearch, TabLineFill
+ [5] = { foreground = Screen.colors.Red }, -- WarningMsg
})
screen:attach()
end)
@@ -35,8 +35,7 @@ describe('search stat', function()
{2:^find this} |
fooooobar |
foba |
- foobar |
- foobar |
+ foobar |*2
foo |
fooooobar |
foba |
@@ -49,8 +48,7 @@ describe('search stat', function()
{2:^find this} |
fooooobar |
foba |
- foobar |
- foobar |
+ foobar |*2
foo |
fooooobar |
foba |
@@ -73,11 +71,7 @@ describe('search stat', function()
{3:^+-- 2 lines: foo·············}|
endif |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
/foo [1/2] |
]])
-- Note: there is an intermediate state where the search stat disappears.
@@ -99,12 +93,7 @@ describe('search stat', function()
int cat; |
int {2:^dog}; |
cat = {2:dog}; |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
/dog [1/2] |
]])
feed('G0gD')
@@ -112,12 +101,7 @@ describe('search stat', function()
int {2:^cat}; |
int dog; |
{2:cat} = dog; |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end)
@@ -148,11 +132,7 @@ describe('search stat', function()
{2:abc}--c |
--------{4:abc} |
--{2:abc} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
/abc^ |
]])
@@ -162,11 +142,7 @@ describe('search stat', function()
{2:abc}--c |
--------{2:abc} |
--{4:abc} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
/abc^ |
]])
@@ -176,11 +152,7 @@ describe('search stat', function()
{4:abc}--c |
--------{2:abc} |
--{2:abc} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
/abc^ |
]])
end)
@@ -197,13 +169,7 @@ describe('search stat', function()
screen:expect([[
{2:^test} |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
/\<test\> [1/1] |
]])
@@ -211,13 +177,7 @@ describe('search stat', function()
screen:expect([[
{2:^test} |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
?\<test\> [1/1] |
]])
@@ -227,13 +187,7 @@ describe('search stat', function()
screen:expect([[
{2:^test} |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
{5:search hit TOP, continuing at BOTTOM} |
]])
end)
diff --git a/test/functional/legacy/source_spec.lua b/test/functional/legacy/source_spec.lua
index f31521607d..7a19541a77 100644
--- a/test/functional/legacy/source_spec.lua
+++ b/test/functional/legacy/source_spec.lua
@@ -9,22 +9,22 @@ before_each(clear)
describe(':source!', function()
-- oldtest: Test_nested_script()
it('gives E22 when scripts nested too deep', function()
- write_file('Xscript.vim', [[
+ write_file(
+ 'Xscript.vim',
+ [[
:source! Xscript.vim
- ]])
+ ]]
+ )
local screen = Screen.new(75, 6)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- ErrorMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg
})
screen:attach()
feed(':source! Xscript.vim\n')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{1:E22: Scripts nested too deep} |
]])
os.remove('Xscript.vim')
diff --git a/test/functional/legacy/statusline_spec.lua b/test/functional/legacy/statusline_spec.lua
index c5b17f8749..567e829879 100644
--- a/test/functional/legacy/statusline_spec.lua
+++ b/test/functional/legacy/statusline_spec.lua
@@ -16,9 +16,9 @@ describe('statusline', function()
it('is updated in cmdline mode when using window-local statusline vim-patch:8.2.2737', function()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {bold = true, reverse = true}, -- StatusLine
- [3] = {reverse = true}, -- StatusLineNC
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { bold = true, reverse = true }, -- StatusLine
+ [3] = { reverse = true }, -- StatusLineNC
})
exec([[
setlocal statusline=-%{mode()}-
@@ -48,9 +48,9 @@ describe('statusline', function()
it('truncated item does not cause off-by-one highlight vim-patch:8.2.4929', function()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {foreground = Screen.colors.Blue}, -- User1
- [3] = {background = Screen.colors.Red, foreground = Screen.colors.White}, -- User2
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { foreground = Screen.colors.Blue }, -- User1
+ [3] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- User2
})
exec([[
set laststatus=2
@@ -60,10 +60,7 @@ describe('statusline', function()
]])
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{3:<F}{2:GHI }|
|
]])
@@ -72,11 +69,11 @@ describe('statusline', function()
-- oldtest: Test_statusline_showcmd()
it('showcmdloc=statusline works', function()
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.LightGrey}, -- Visual
- [2] = {bold = true}, -- MoreMsg
- [3] = {bold = true, reverse = true}, -- StatusLine
- [5] = {background = Screen.colors.LightGrey, foreground = Screen.colors.DarkBlue}, -- Folded
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual
+ [2] = { bold = true }, -- MoreMsg
+ [3] = { bold = true, reverse = true }, -- StatusLine
+ [5] = { background = Screen.colors.LightGrey, foreground = Screen.colors.DarkBlue }, -- Folded
})
exec([[
func MyStatusLine()
@@ -97,9 +94,7 @@ describe('statusline', function()
screen:expect([[
{5:+-- 2 lines: a···································}|
^c |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:g }|
|
]])
@@ -110,8 +105,7 @@ describe('statusline', function()
^a |
b |
c |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3: }|
|
]])
@@ -121,8 +115,7 @@ describe('statusline', function()
{1:a} |
{1:b} |
{1:c}^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:3x2 }|
{2:-- VISUAL BLOCK --} |
]])
@@ -132,8 +125,7 @@ describe('statusline', function()
a |
b |
^c |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:1234 }|
|
]])
@@ -145,8 +137,7 @@ describe('statusline', function()
a |
b |
^c |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] [+] 1234 }|
: |
]])
diff --git a/test/functional/legacy/substitute_spec.lua b/test/functional/legacy/substitute_spec.lua
index f3ce343680..b462c10202 100644
--- a/test/functional/legacy/substitute_spec.lua
+++ b/test/functional/legacy/substitute_spec.lua
@@ -20,9 +20,14 @@ describe('substitute()', function()
local function test_1_and_2()
eq('AA', eval("substitute('A', 'A', '&&', '')"))
eq('&', eval([[substitute('B', 'B', '\&', '')]]))
- eq('C123456789987654321', eval([[substitute('C123456789', ]] ..
- [['C\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', ]] ..
- [['\0\9\8\7\6\5\4\3\2\1', '')]]))
+ eq(
+ 'C123456789987654321',
+ eval(
+ [[substitute('C123456789', ]]
+ .. [['C\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', ]]
+ .. [['\0\9\8\7\6\5\4\3\2\1', '')]]
+ )
+ )
eq('d', eval("substitute('D', 'D', 'd', '')"))
eq('~', eval("substitute('E', 'E', '~', '')"))
eq('~', eval([[substitute('F', 'F', '\~', '')]]))
@@ -61,10 +66,9 @@ describe('substitute()', function()
feed_command('set magic&')
eq('a\\a', eval([[substitute('aAa', 'A', '\="\\"', '')]]))
eq('b\\\\b', eval([[substitute('bBb', 'B', '\="\\\\"', '')]]))
- eq('c\rc', eval([[substitute('cCc', 'C', '\="]]..'\r'..[["', '')]]))
- eq('d\\\rd', eval([[substitute('dDd', 'D', '\="\\]]..'\r'..[["', '')]]))
- eq('e\\\\\re',
- eval([[substitute('eEe', 'E', '\="\\\\]]..'\r'..[["', '')]]))
+ eq('c\rc', eval([[substitute('cCc', 'C', '\="]] .. '\r' .. [["', '')]]))
+ eq('d\\\rd', eval([[substitute('dDd', 'D', '\="\\]] .. '\r' .. [["', '')]]))
+ eq('e\\\\\re', eval([[substitute('eEe', 'E', '\="\\\\]] .. '\r' .. [["', '')]]))
eq('f\\rf', eval([[substitute('fFf', 'F', '\="\\r"', '')]]))
eq('j\\nj', eval([[substitute('jJj', 'J', '\="\\n"', '')]]))
eq('k\rk', eval([[substitute('kKk', 'K', '\="\r"', '')]]))
@@ -73,39 +77,81 @@ describe('substitute()', function()
it('with submatch() (TEST_4)', function()
feed_command('set magic&')
- eq('a\\a', eval([[substitute('aAa', 'A', ]] ..
- [['\=substitute(submatch(0), ".", "\\", "")', '')]]))
- eq('b\\b', eval([[substitute('bBb', 'B', ]] ..
- [['\=substitute(submatch(0), ".", "\\\\", "")', '')]]))
- eq('c\rc', eval([[substitute('cCc', 'C', ]] ..
- [['\=substitute(submatch(0), ".", "]]..'\r'..[[", "")', '')]]))
- eq('d\rd', eval([[substitute('dDd', 'D', ]] ..
- [['\=substitute(submatch(0), ".", "\\]]..'\r'..[[", "")', '')]]))
- eq('e\\\re', eval([[substitute('eEe', 'E', ]] ..
- [['\=substitute(submatch(0), ".", "\\\\]]..'\r'..[[", "")', '')]]))
- eq('f\rf', eval([[substitute('fFf', 'F', ]] ..
- [['\=substitute(submatch(0), ".", "\\r", "")', '')]]))
- eq('j\nj', eval([[substitute('jJj', 'J', ]] ..
- [['\=substitute(submatch(0), ".", "\\n", "")', '')]]))
- eq('k\rk', eval([[substitute('kKk', 'K', ]] ..
- [['\=substitute(submatch(0), ".", "\r", "")', '')]]))
- eq('l\nl', eval([[substitute('lLl', 'L', ]] ..
- [['\=substitute(submatch(0), ".", "\n", "")', '')]]))
+ eq(
+ 'a\\a',
+ eval([[substitute('aAa', 'A', ]] .. [['\=substitute(submatch(0), ".", "\\", "")', '')]])
+ )
+ eq(
+ 'b\\b',
+ eval([[substitute('bBb', 'B', ]] .. [['\=substitute(submatch(0), ".", "\\\\", "")', '')]])
+ )
+ eq(
+ 'c\rc',
+ eval(
+ [[substitute('cCc', 'C', ]]
+ .. [['\=substitute(submatch(0), ".", "]]
+ .. '\r'
+ .. [[", "")', '')]]
+ )
+ )
+ eq(
+ 'd\rd',
+ eval(
+ [[substitute('dDd', 'D', ]]
+ .. [['\=substitute(submatch(0), ".", "\\]]
+ .. '\r'
+ .. [[", "")', '')]]
+ )
+ )
+ eq(
+ 'e\\\re',
+ eval(
+ [[substitute('eEe', 'E', ]]
+ .. [['\=substitute(submatch(0), ".", "\\\\]]
+ .. '\r'
+ .. [[", "")', '')]]
+ )
+ )
+ eq(
+ 'f\rf',
+ eval([[substitute('fFf', 'F', ]] .. [['\=substitute(submatch(0), ".", "\\r", "")', '')]])
+ )
+ eq(
+ 'j\nj',
+ eval([[substitute('jJj', 'J', ]] .. [['\=substitute(submatch(0), ".", "\\n", "")', '')]])
+ )
+ eq(
+ 'k\rk',
+ eval([[substitute('kKk', 'K', ]] .. [['\=substitute(submatch(0), ".", "\r", "")', '')]])
+ )
+ eq(
+ 'l\nl',
+ eval([[substitute('lLl', 'L', ]] .. [['\=substitute(submatch(0), ".", "\n", "")', '')]])
+ )
end)
it('with submatch() (TEST_5)', function()
feed_command('set magic&')
- eq('A123456789987654321', eval([[substitute('A123456789', ]] ..
- [['A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', ]] ..
- [['\=submatch(0) . submatch(9) . submatch(8) . submatch(7) . ]] ..
- [[submatch(6) . submatch(5) . submatch(4) . submatch(3) . ]] ..
- [[submatch(2) . submatch(1)', '')]]))
- eq("[['A123456789'], ['9'], ['8'], ['7'], ['6'], ['5'], ['4'], ['3'], " ..
- "['2'], ['1']]", eval([[substitute('A123456789', ]] ..
- [['A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', ]] ..
- [['\=string([submatch(0, 1), submatch(9, 1), submatch(8, 1), ]] ..
- [[submatch(7, 1), submatch(6, 1), submatch(5, 1), submatch(4, 1), ]] ..
- [[submatch(3, 1), submatch(2, 1), submatch(1, 1)])', '')]]))
+ eq(
+ 'A123456789987654321',
+ eval(
+ [[substitute('A123456789', ]]
+ .. [['A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', ]]
+ .. [['\=submatch(0) . submatch(9) . submatch(8) . submatch(7) . ]]
+ .. [[submatch(6) . submatch(5) . submatch(4) . submatch(3) . ]]
+ .. [[submatch(2) . submatch(1)', '')]]
+ )
+ )
+ eq(
+ "[['A123456789'], ['9'], ['8'], ['7'], ['6'], ['5'], ['4'], ['3'], " .. "['2'], ['1']]",
+ eval(
+ [[substitute('A123456789', ]]
+ .. [['A\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)', ]]
+ .. [['\=string([submatch(0, 1), submatch(9, 1), submatch(8, 1), ]]
+ .. [[submatch(7, 1), submatch(6, 1), submatch(5, 1), submatch(4, 1), ]]
+ .. [[submatch(3, 1), submatch(2, 1), submatch(1, 1)])', '')]]
+ )
+ )
end)
-- TEST_6 was about the 'cpoptions' flag / which was removed in pull request
@@ -115,8 +161,7 @@ describe('substitute()', function()
feed_command('set magic&')
eq('A\rA', eval("substitute('A\rA', 'A.', '\\=submatch(0)', '')"))
eq('B\nB', eval([[substitute("B\nB", 'B.', '\=submatch(0)', '')]]))
- eq("['B\n']B",
- eval([[substitute("B\nB", 'B.', '\=string(submatch(0, 1))', '')]]))
+ eq("['B\n']B", eval([[substitute("B\nB", 'B.', '\=string(submatch(0, 1))', '')]]))
eq('-abab', eval([[substitute('-bb', '\zeb', 'a', 'g')]]))
eq('c-cbcbc', eval([[substitute('-bb', '\ze', 'c', 'g')]]))
end)
@@ -145,9 +190,9 @@ describe(':substitute', function()
feed_command('set magic&')
feed_command([[1s/\(^\|,\)\ze\(,\|X\)/\1N/g]])
feed_command([[2s/\(^\|,\)\ze\(,\|Y\)/\1N/gc]])
- feed('a') -- For the dialog of the previous :s command.
+ feed('a') -- For the dialog of the previous :s command.
feed_command([[3s/\(^\|,\)\ze\(,\|Z\)/\1N/gc]])
- feed('yy') -- For the dialog of the previous :s command.
+ feed('yy') -- For the dialog of the previous :s command.
expect([[
N,,NX
N,,NY
@@ -158,16 +203,16 @@ describe(':substitute', function()
insert('xxx')
feed_command('set magic&')
feed_command('s/x/X/gc')
- feed('yyq') -- For the dialog of the previous :s command.
+ feed('yyq') -- For the dialog of the previous :s command.
expect('XXx')
end)
it('first char is highlighted with confirmation dialog and empty match', function()
local screen = Screen.new(60, 8)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {reverse = true}, -- IncSearch
- [2] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { reverse = true }, -- IncSearch
+ [2] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
})
screen:attach()
exec([[
@@ -179,10 +224,7 @@ describe(':substitute', function()
{1:o}ne |
two |
three |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:replace with (y/n/a/q/l/^E/^Y)?}^ |
]])
end)
diff --git a/test/functional/legacy/syn_attr_spec.lua b/test/functional/legacy/syn_attr_spec.lua
index e6573da5d3..ec47bdf9af 100644
--- a/test/functional/legacy/syn_attr_spec.lua
+++ b/test/functional/legacy/syn_attr_spec.lua
@@ -37,12 +37,12 @@ describe('synIDattr()', function()
end)
end
- for _, mode in ipairs({'cterm', 'gui'}) do
+ for _, mode in ipairs({ 'cterm', 'gui' }) do
describe(('"%s"'):format(mode), function()
for _, attr in ipairs(bool_attrs) do
none_test(attr, mode)
end
- for _, attr in ipairs({'inverse', 'bg', 'fg', 'sp'}) do
+ for _, attr in ipairs({ 'inverse', 'bg', 'fg', 'sp' }) do
none_test(attr, mode)
end
end)
diff --git a/test/functional/legacy/tabline_spec.lua b/test/functional/legacy/tabline_spec.lua
index 6b368d1857..683c7d9bd7 100644
--- a/test/functional/legacy/tabline_spec.lua
+++ b/test/functional/legacy/tabline_spec.lua
@@ -17,12 +17,12 @@ describe('tabline', function()
-- oldtest: Test_tabline_showcmd()
it('showcmdloc=tabline works', function()
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {background = Screen.colors.LightGrey}, -- Visual
- [2] = {bold = true}, -- MoreMsg, TabLineSel
- [3] = {reverse = true}, -- TabLineFill
- [4] = {background = Screen.colors.LightGrey, underline = true}, -- TabLine
- [5] = {background = Screen.colors.LightGrey, foreground = Screen.colors.DarkBlue}, -- Folded
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual
+ [2] = { bold = true }, -- MoreMsg, TabLineSel
+ [3] = { reverse = true }, -- TabLineFill
+ [4] = { background = Screen.colors.LightGrey, underline = true }, -- TabLine
+ [5] = { background = Screen.colors.LightGrey, foreground = Screen.colors.DarkBlue }, -- Folded
})
exec([[
func MyTabLine()
@@ -44,9 +44,7 @@ describe('tabline', function()
{3:g }|
{5:+-- 2 lines: a···································}|
^c |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
@@ -57,8 +55,7 @@ describe('tabline', function()
^a |
b |
c |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -68,8 +65,7 @@ describe('tabline', function()
{1:a} |
{1:b} |
{1:c}^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:-- VISUAL BLOCK --} |
]])
@@ -79,8 +75,7 @@ describe('tabline', function()
a |
b |
^c |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -92,8 +87,7 @@ describe('tabline', function()
a |
b |
^c |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
: |
]])
end)
diff --git a/test/functional/legacy/tagcase_spec.lua b/test/functional/legacy/tagcase_spec.lua
index 9ca0e0009f..f84fc673cf 100644
--- a/test/functional/legacy/tagcase_spec.lua
+++ b/test/functional/legacy/tagcase_spec.lua
@@ -10,10 +10,13 @@ local write_file = helpers.write_file
describe("'tagcase' option", function()
setup(function()
- write_file('Xtags', [[
+ write_file(
+ 'Xtags',
+ [[
Bar Xtext 3
Foo Xtext 2
- foo Xtext 4]])
+ foo Xtext 4]]
+ )
end)
before_each(function()
diff --git a/test/functional/legacy/undolevels_spec.lua b/test/functional/legacy/undolevels_spec.lua
index 1dfc4c17ba..e8badc6864 100644
--- a/test/functional/legacy/undolevels_spec.lua
+++ b/test/functional/legacy/undolevels_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local source, clear = helpers.source, helpers.clear
-local eq, nvim = helpers.eq, helpers.meths
+local eq, nvim = helpers.eq, helpers.api
describe('undolevel', function()
setup(clear)
@@ -57,6 +57,6 @@ describe('undolevel', function()
call Test_global_local_undolevels()
]])
- eq({}, nvim.get_vvar('errors'))
+ eq({}, nvim.nvim_get_vvar('errors'))
end)
end)
diff --git a/test/functional/legacy/vimscript_spec.lua b/test/functional/legacy/vimscript_spec.lua
index 16a1080396..8b0a920a3e 100644
--- a/test/functional/legacy/vimscript_spec.lua
+++ b/test/functional/legacy/vimscript_spec.lua
@@ -3,16 +3,16 @@ local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local exec = helpers.exec
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
before_each(clear)
describe('Vim script', function()
-- oldtest: Test_deep_nest()
- it('Error when if/for/while/try/function is nested too deep',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_value('laststatus', 2, {})
+ api.nvim_set_option_value('laststatus', 2, {})
exec([[
" Deep nesting of if ... endif
func Test1()
@@ -59,25 +59,25 @@ describe('Vim script', function()
let @a = ''
endfunc
]])
- screen:expect({any = '%[No Name%]'})
+ screen:expect({ any = '%[No Name%]' })
feed(':call Test1()<CR>')
- screen:expect({any = 'E579: '})
+ screen:expect({ any = 'E579: ' })
feed('<C-C>')
- screen:expect({any = '%[No Name%]'})
+ screen:expect({ any = '%[No Name%]' })
feed(':call Test2()<CR>')
- screen:expect({any = 'E585: '})
+ screen:expect({ any = 'E585: ' })
feed('<C-C>')
- screen:expect({any = '%[No Name%]'})
+ screen:expect({ any = '%[No Name%]' })
feed(':call Test3()<CR>')
- screen:expect({any = 'E585: '})
+ screen:expect({ any = 'E585: ' })
feed('<C-C>')
- screen:expect({any = '%[No Name%]'})
+ screen:expect({ any = '%[No Name%]' })
feed(':call Test4()<CR>')
- screen:expect({any = 'E601: '})
+ screen:expect({ any = 'E601: ' })
feed('<C-C>')
- screen:expect({any = '%[No Name%]'})
+ screen:expect({ any = '%[No Name%]' })
feed(':call Test5()<CR>')
- screen:expect({any = 'E1058: '})
+ screen:expect({ any = 'E1058: ' })
end)
-- oldtest: Test_typed_script_var()
@@ -85,6 +85,6 @@ describe('Vim script', function()
local screen = Screen.new(80, 24)
screen:attach()
feed(":echo get(s:, 'foo', 'x')\n")
- screen:expect({any = 'E116: '})
+ screen:expect({ any = 'E116: ' })
end)
end)
diff --git a/test/functional/legacy/visual_spec.lua b/test/functional/legacy/visual_spec.lua
index 629fab5eb5..151e5874e1 100644
--- a/test/functional/legacy/visual_spec.lua
+++ b/test/functional/legacy/visual_spec.lua
@@ -13,9 +13,9 @@ describe('Visual highlight', function()
before_each(function()
screen = Screen.new(50, 6)
screen:set_default_attr_ids({
- [0] = {foreground = Screen.colors.Blue, bold = true}, -- NonText
- [1] = {bold = true}, -- ModeMsg
- [2] = {background = Screen.colors.LightGrey}, -- Visual
+ [0] = { foreground = Screen.colors.Blue, bold = true }, -- NonText
+ [1] = { bold = true }, -- ModeMsg
+ [2] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black }, -- Visual
})
screen:attach()
end)
@@ -33,8 +33,7 @@ describe('Visual highlight', function()
{2:aaaaaa}^ |
{2:bbbb } |
{2:cc } |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1:-- VISUAL BLOCK --} |
]])
@@ -43,8 +42,7 @@ describe('Visual highlight', function()
{2:aaaaaa } |
{2:bbbb } |
{2:cc}^ {2: } |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1:-- VISUAL BLOCK --} |
]])
end)
@@ -60,9 +58,7 @@ describe('Visual highlight', function()
screen:expect([[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^a|
{0:+}{2:aaaa}aaaaaa |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1:-- VISUAL --} |
]])
end)
diff --git a/test/functional/legacy/window_cmd_spec.lua b/test/functional/legacy/window_cmd_spec.lua
index 979b46ae47..7fe4ec8eb6 100644
--- a/test/functional/legacy/window_cmd_spec.lua
+++ b/test/functional/legacy/window_cmd_spec.lua
@@ -11,7 +11,7 @@ it('scrolling with laststatus=0 and :botright split', function()
clear('--cmd', 'set ruler')
local screen = Screen.new(40, 10)
screen:set_default_attr_ids({
- [1] = {reverse = true}, -- StatusLineNC
+ [1] = { reverse = true }, -- StatusLineNC
})
screen:attach()
exec([[
@@ -296,10 +296,7 @@ describe('splitkeep', function()
a |
b |
c |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
[No Name] |
^a |
b |
@@ -328,8 +325,7 @@ describe('splitkeep', function()
<<<e line with lots of text in one line |
^with lots of text in one line with lots |
of text in one line |
- ~ |
- ~ |
+ ~ |*2
[No Name] [+] |
|
]])
diff --git a/test/functional/legacy/wordcount_spec.lua b/test/functional/legacy/wordcount_spec.lua
index 21f96628c0..82021dd98d 100644
--- a/test/functional/legacy/wordcount_spec.lua
+++ b/test/functional/legacy/wordcount_spec.lua
@@ -50,75 +50,83 @@ describe('wordcount', function()
]=])
-- Test 1: empty window
- eq(eval([=[
+ eq(
+ eval([=[
[[''], {'chars': 0, 'cursor_chars': 0, 'words': 0, 'cursor_words': 0, 'bytes': 0, 'cursor_bytes': 0}]
]=]),
- eval('DoRecordWin()')
- )
+ eval('DoRecordWin()')
+ )
-- Test 2: some words, cursor at start
command([[call PutInWindow('one two three')]])
- eq(eval([=[
+ eq(
+ eval([=[
[['', 'one two three'], {'chars': 15, 'cursor_chars': 1, 'words': 3, 'cursor_words': 0, 'bytes': 15, 'cursor_bytes': 1}]
]=]),
- eval('DoRecordWin([1, 1, 0])')
- )
+ eval('DoRecordWin([1, 1, 0])')
+ )
-- Test 3: some words, cursor at end
command([[call PutInWindow('one two three')]])
- eq(eval([=[
+ eq(
+ eval([=[
[['', 'one two three'], {'chars': 15, 'cursor_chars': 14, 'words': 3, 'cursor_words': 3, 'bytes': 15, 'cursor_bytes': 14}]
]=]),
- eval('DoRecordWin([2, 99, 0])')
- )
+ eval('DoRecordWin([2, 99, 0])')
+ )
-- Test 4: some words, cursor at end, ve=all
command('set ve=all')
command([[call PutInWindow('one two three')]])
- eq(eval([=[
+ eq(
+ eval([=[
[['', 'one two three'], {'chars': 15, 'cursor_chars': 15, 'words': 3, 'cursor_words': 3, 'bytes': 15, 'cursor_bytes': 15}]
]=]),
- eval('DoRecordWin([2,99,0])')
- )
+ eval('DoRecordWin([2,99,0])')
+ )
command('set ve=')
-- Test 5: several lines with words
command([=[call PutInWindow(['one two three', 'one two three', 'one two three'])]=])
- eq(eval([=[
+ eq(
+ eval([=[
[['', 'one two three', 'one two three', 'one two three'], {'chars': 43, 'cursor_chars': 42, 'words': 9, 'cursor_words': 9, 'bytes': 43, 'cursor_bytes': 42}]
]=]),
- eval('DoRecordWin([4,99,0])')
- )
+ eval('DoRecordWin([4,99,0])')
+ )
-- Test 6: one line with BOM set
command([[call PutInWindow('one two three')]])
command('wincmd k')
command('set bomb')
command('wincmd j')
- eq(eval([=[
+ eq(
+ eval([=[
[['', 'one two three'], {'chars': 15, 'cursor_chars': 14, 'words': 3, 'cursor_words': 3, 'bytes': 18, 'cursor_bytes': 14}]
]=]),
- eval('DoRecordWin([2,99,0])')
- )
+ eval('DoRecordWin([2,99,0])')
+ )
command('wincmd k')
command('set nobomb')
command('wincmd j')
-- Test 7: one line with multibyte words
command([=[call PutInWindow(['Äne M¤ne Müh'])]=])
- eq(eval([=[
+ eq(
+ eval([=[
[['', 'Äne M¤ne Müh'], {'chars': 14, 'cursor_chars': 13, 'words': 3, 'cursor_words': 3, 'bytes': 17, 'cursor_bytes': 16}]
]=]),
- eval('DoRecordWin([2,99,0])')
- )
+ eval('DoRecordWin([2,99,0])')
+ )
-- Test 8: several lines with multibyte words
command([=[call PutInWindow(['Äne M¤ne Müh', 'und raus bist dü!'])]=])
- eq(eval([=[
+ eq(
+ eval([=[
[['', 'Äne M¤ne Müh', 'und raus bist dü!'], {'chars': 32, 'cursor_chars': 31, 'words': 7, 'cursor_words': 7, 'bytes': 36, 'cursor_bytes': 35}]
]=]),
- eval('DoRecordWin([3,99,0])')
- )
+ eval('DoRecordWin([3,99,0])')
+ )
-- Test 9: visual mode, complete buffer
command([=[call PutInWindow(['Äne M¤ne Müh', 'und raus bist dü!'])]=])
@@ -131,11 +139,12 @@ describe('wordcount', function()
command('set stl= ls=1')
command('let log=DoRecordWin([3,99,0])')
command('let log[1]=g:visual_stat')
- eq(eval([=[
+ eq(
+ eval([=[
[['', 'Äne M¤ne Müh', 'und raus bist dü!'], {'chars': 32, 'words': 7, 'bytes': 36, 'visual_chars': 32, 'visual_words': 7, 'visual_bytes': 36}]
]=]),
- eval('log')
- )
+ eval('log')
+ )
-- Test 10: visual mode (empty)
command([=[call PutInWindow(['Äne M¤ne Müh', 'und raus bist dü!'])]=])
@@ -148,11 +157,12 @@ describe('wordcount', function()
command('set stl= ls=1')
command('let log=DoRecordWin([3,99,0])')
command('let log[1]=g:visual_stat')
- eq(eval([=[
+ eq(
+ eval([=[
[['', 'Äne M¤ne Müh', 'und raus bist dü!'], {'chars': 32, 'words': 7, 'bytes': 36, 'visual_chars': 1, 'visual_words': 0, 'visual_bytes': 1}]
]=]),
- eval('log')
- )
+ eval('log')
+ )
-- Test 11: visual mode, single line
command([=[call PutInWindow(['Äne M¤ne Müh', 'und raus bist dü!'])]=])
@@ -165,10 +175,11 @@ describe('wordcount', function()
command('set stl= ls=1')
command('let log=DoRecordWin([3,99,0])')
command('let log[1]=g:visual_stat')
- eq(eval([=[
+ eq(
+ eval([=[
[['', 'Äne M¤ne Müh', 'und raus bist dü!'], {'chars': 32, 'words': 7, 'bytes': 36, 'visual_chars': 13, 'visual_words': 3, 'visual_bytes': 16}]
]=]),
- eval('log')
- )
+ eval('log')
+ )
end)
end)
diff --git a/test/functional/lua/api_spec.lua b/test/functional/lua/api_spec.lua
index d808693a9e..acd56a0ddb 100644
--- a/test/functional/lua/api_spec.lua
+++ b/test/functional/lua/api_spec.lua
@@ -3,10 +3,10 @@ local helpers = require('test.functional.helpers')(after_each)
local exc_exec = helpers.exc_exec
local remove_trace = helpers.remove_trace
-local funcs = helpers.funcs
+local fn = helpers.fn
local clear = helpers.clear
local eval = helpers.eval
-local NIL = helpers.NIL
+local NIL = vim.NIL
local eq = helpers.eq
local exec_lua = helpers.exec_lua
local pcall_err = helpers.pcall_err
@@ -17,64 +17,77 @@ describe('luaeval(vim.api.…)', function()
describe('with channel_id and buffer handle', function()
describe('nvim_buf_get_lines', function()
it('works', function()
- funcs.setline(1, {"abc", "def", "a\nb", "ttt"})
- eq({'a\000b'},
- funcs.luaeval('vim.api.nvim_buf_get_lines(1, 2, 3, false)'))
+ fn.setline(1, { 'abc', 'def', 'a\nb', 'ttt' })
+ eq({ 'a\000b' }, fn.luaeval('vim.api.nvim_buf_get_lines(1, 2, 3, false)'))
end)
end)
describe('nvim_buf_set_lines', function()
it('works', function()
- funcs.setline(1, {"abc", "def", "a\nb", "ttt"})
- eq(NIL, funcs.luaeval('vim.api.nvim_buf_set_lines(1, 1, 2, false, {"b\\0a"})'))
- eq({'abc', 'b\000a', 'a\000b', 'ttt'},
- funcs.luaeval('vim.api.nvim_buf_get_lines(1, 0, 4, false)'))
+ fn.setline(1, { 'abc', 'def', 'a\nb', 'ttt' })
+ eq(NIL, fn.luaeval('vim.api.nvim_buf_set_lines(1, 1, 2, false, {"b\\0a"})'))
+ eq(
+ { 'abc', 'b\000a', 'a\000b', 'ttt' },
+ fn.luaeval('vim.api.nvim_buf_get_lines(1, 0, 4, false)')
+ )
end)
end)
end)
describe('with errors', function()
it('transforms API error from nvim_buf_set_lines into lua error', function()
- funcs.setline(1, {"abc", "def", "a\nb", "ttt"})
- eq({false, "'replacement string' item contains newlines"},
- funcs.luaeval('{pcall(vim.api.nvim_buf_set_lines, 1, 1, 2, false, {"b\\na"})}'))
+ fn.setline(1, { 'abc', 'def', 'a\nb', 'ttt' })
+ eq(
+ { false, "'replacement string' item contains newlines" },
+ fn.luaeval('{pcall(vim.api.nvim_buf_set_lines, 1, 1, 2, false, {"b\\na"})}')
+ )
end)
it('transforms API error from nvim_win_set_cursor into lua error', function()
- eq({false, 'Argument "pos" must be a [row, col] array'},
- funcs.luaeval('{pcall(vim.api.nvim_win_set_cursor, 0, {1, 2, 3})}'))
+ eq(
+ { false, 'Argument "pos" must be a [row, col] array' },
+ fn.luaeval('{pcall(vim.api.nvim_win_set_cursor, 0, {1, 2, 3})}')
+ )
-- Used to produce a memory leak due to a bug in nvim_win_set_cursor
- eq({false, 'Invalid window id: -1'},
- funcs.luaeval('{pcall(vim.api.nvim_win_set_cursor, -1, {1, 2, 3})}'))
+ eq(
+ { false, 'Invalid window id: -1' },
+ fn.luaeval('{pcall(vim.api.nvim_win_set_cursor, -1, {1, 2, 3})}')
+ )
end)
- it('transforms API error from nvim_win_set_cursor + same array as in first test into lua error',
- function()
- eq({false, 'Argument "pos" must be a [row, col] array'},
- funcs.luaeval('{pcall(vim.api.nvim_win_set_cursor, 0, {"b\\na"})}'))
- end)
+ it(
+ 'transforms API error from nvim_win_set_cursor + same array as in first test into lua error',
+ function()
+ eq(
+ { false, 'Argument "pos" must be a [row, col] array' },
+ fn.luaeval('{pcall(vim.api.nvim_win_set_cursor, 0, {"b\\na"})}')
+ )
+ end
+ )
end)
it('correctly evaluates API code which calls luaeval', function()
- local str = (([===[vim.api.nvim_eval([==[
+ local str = (
+ ([===[vim.api.nvim_eval([==[
luaeval('vim.api.nvim_eval([=[
luaeval("vim.api.nvim_eval([[
luaeval(1)
]])")
]=])')
- ]==])]===]):gsub('\n', ' '))
- eq(1, funcs.luaeval(str))
+ ]==])]===]):gsub('\n', ' ')
+ )
+ eq(1, fn.luaeval(str))
end)
it('correctly converts from API objects', function()
- eq(1, funcs.luaeval('vim.api.nvim_eval("1")'))
- eq('1', funcs.luaeval([[vim.api.nvim_eval('"1"')]]))
- eq('Blobby', funcs.luaeval('vim.api.nvim_eval("0z426c6f626279")'))
- eq({}, funcs.luaeval('vim.api.nvim_eval("[]")'))
- eq({}, funcs.luaeval('vim.api.nvim_eval("{}")'))
- eq(1, funcs.luaeval('vim.api.nvim_eval("1.0")'))
- eq('\000', funcs.luaeval('vim.api.nvim_eval("0z00")'))
- eq(true, funcs.luaeval('vim.api.nvim_eval("v:true")'))
- eq(false, funcs.luaeval('vim.api.nvim_eval("v:false")'))
- eq(NIL, funcs.luaeval('vim.api.nvim_eval("v:null")'))
+ eq(1, fn.luaeval('vim.api.nvim_eval("1")'))
+ eq('1', fn.luaeval([[vim.api.nvim_eval('"1"')]]))
+ eq('Blobby', fn.luaeval('vim.api.nvim_eval("0z426c6f626279")'))
+ eq({}, fn.luaeval('vim.api.nvim_eval("[]")'))
+ eq({}, fn.luaeval('vim.api.nvim_eval("{}")'))
+ eq(1, fn.luaeval('vim.api.nvim_eval("1.0")'))
+ eq('\000', fn.luaeval('vim.api.nvim_eval("0z00")'))
+ eq(true, fn.luaeval('vim.api.nvim_eval("v:true")'))
+ eq(false, fn.luaeval('vim.api.nvim_eval("v:false")'))
+ eq(NIL, fn.luaeval('vim.api.nvim_eval("v:null")'))
eq(0, eval([[type(luaeval('vim.api.nvim_eval("1")'))]]))
eq(1, eval([[type(luaeval('vim.api.nvim_eval("''1''")'))]]))
@@ -86,28 +99,32 @@ describe('luaeval(vim.api.…)', function()
eq(6, eval([[type(luaeval('vim.api.nvim_eval("v:false")'))]]))
eq(7, eval([[type(luaeval('vim.api.nvim_eval("v:null")'))]]))
- eq({foo=42}, funcs.luaeval([[vim.api.nvim_eval('{"foo": 42}')]]))
- eq({42}, funcs.luaeval([[vim.api.nvim_eval('[42]')]]))
+ eq({ foo = 42 }, fn.luaeval([[vim.api.nvim_eval('{"foo": 42}')]]))
+ eq({ 42 }, fn.luaeval([[vim.api.nvim_eval('[42]')]]))
- eq({foo={bar=42}, baz=50}, funcs.luaeval([[vim.api.nvim_eval('{"foo": {"bar": 42}, "baz": 50}')]]))
- eq({{42}, {}}, funcs.luaeval([=[vim.api.nvim_eval('[[42], []]')]=]))
+ eq(
+ { foo = { bar = 42 }, baz = 50 },
+ fn.luaeval([[vim.api.nvim_eval('{"foo": {"bar": 42}, "baz": 50}')]])
+ )
+ eq({ { 42 }, {} }, fn.luaeval([=[vim.api.nvim_eval('[[42], []]')]=]))
end)
it('correctly converts to API objects', function()
- eq(1, funcs.luaeval('vim.api.nvim__id(1)'))
- eq('1', funcs.luaeval('vim.api.nvim__id("1")'))
- eq({1}, funcs.luaeval('vim.api.nvim__id({1})'))
- eq({foo=1}, funcs.luaeval('vim.api.nvim__id({foo=1})'))
- eq(1.5, funcs.luaeval('vim.api.nvim__id(1.5)'))
- eq(true, funcs.luaeval('vim.api.nvim__id(true)'))
- eq(false, funcs.luaeval('vim.api.nvim__id(false)'))
- eq(NIL, funcs.luaeval('vim.api.nvim__id(nil)'))
+ eq(1, fn.luaeval('vim.api.nvim__id(1)'))
+ eq('1', fn.luaeval('vim.api.nvim__id("1")'))
+ eq({ 1 }, fn.luaeval('vim.api.nvim__id({1})'))
+ eq({ foo = 1 }, fn.luaeval('vim.api.nvim__id({foo=1})'))
+ eq(1.5, fn.luaeval('vim.api.nvim__id(1.5)'))
+ eq(true, fn.luaeval('vim.api.nvim__id(true)'))
+ eq(false, fn.luaeval('vim.api.nvim__id(false)'))
+ eq(NIL, fn.luaeval('vim.api.nvim__id(nil)'))
-- API strings from Blobs can work as NUL-terminated C strings
- eq('Vim(call):E5555: API call: Vim:E15: Invalid expression: ""',
- exc_exec('call nvim_eval(v:_null_blob)'))
- eq('Vim(call):E5555: API call: Vim:E15: Invalid expression: ""',
- exc_exec('call nvim_eval(0z)'))
+ eq(
+ 'Vim(call):E5555: API call: Vim:E15: Invalid expression: ""',
+ exc_exec('call nvim_eval(v:_null_blob)')
+ )
+ eq('Vim(call):E5555: API call: Vim:E15: Invalid expression: ""', exc_exec('call nvim_eval(0z)'))
eq(1, eval('nvim_eval(0z31)'))
eq(0, eval([[type(luaeval('vim.api.nvim__id(1)'))]]))
@@ -119,68 +136,152 @@ describe('luaeval(vim.api.…)', function()
eq(6, eval([[type(luaeval('vim.api.nvim__id(false)'))]]))
eq(7, eval([[type(luaeval('vim.api.nvim__id(nil)'))]]))
- eq({foo=1, bar={42, {{baz=true}, 5}}}, funcs.luaeval('vim.api.nvim__id({foo=1, bar={42, {{baz=true}, 5}}})'))
+ eq(
+ { foo = 1, bar = { 42, { { baz = true }, 5 } } },
+ fn.luaeval('vim.api.nvim__id({foo=1, bar={42, {{baz=true}, 5}}})')
+ )
- eq(true, funcs.luaeval('vim.api.nvim__id(vim.api.nvim__id)(true)'))
- eq(42, exec_lua [[
+ eq(true, fn.luaeval('vim.api.nvim__id(vim.api.nvim__id)(true)'))
+ eq(
+ 42,
+ exec_lua [[
local f = vim.api.nvim__id({42, vim.api.nvim__id})
return f[2](f[1])
- ]])
+ ]]
+ )
end)
it('correctly converts container objects with type_idx to API objects', function()
- eq(5, eval('type(luaeval("vim.api.nvim__id({[vim.type_idx]=vim.types.float, [vim.val_idx]=0})"))'))
+ eq(
+ 5,
+ eval('type(luaeval("vim.api.nvim__id({[vim.type_idx]=vim.types.float, [vim.val_idx]=0})"))')
+ )
eq(4, eval([[type(luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.dictionary})'))]]))
eq(3, eval([[type(luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array})'))]]))
- eq({}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array})'))
+ eq({}, fn.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array})'))
-- Presence of type_idx makes Vim ignore some keys
- eq({42}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'))
- eq({foo=2}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'))
- eq(10, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'))
- eq({}, funcs.luaeval('vim.api.nvim__id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})'))
+ eq(
+ { 42 },
+ fn.luaeval(
+ 'vim.api.nvim__id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'
+ )
+ )
+ eq(
+ { foo = 2 },
+ fn.luaeval(
+ 'vim.api.nvim__id({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'
+ )
+ )
+ eq(
+ 10,
+ fn.luaeval(
+ 'vim.api.nvim__id({[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'
+ )
+ )
+ eq(
+ {},
+ fn.luaeval(
+ 'vim.api.nvim__id({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})'
+ )
+ )
end)
it('correctly converts arrays with type_idx to API objects', function()
eq(3, eval([[type(luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array})'))]]))
- eq({}, funcs.luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array})'))
-
- eq({42}, funcs.luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'))
- eq({{foo=2}}, funcs.luaeval('vim.api.nvim__id_array({{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'))
- eq({10}, funcs.luaeval('vim.api.nvim__id_array({{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'))
- eq({}, funcs.luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})'))
-
- eq({}, funcs.luaeval('vim.api.nvim__id_array({})'))
+ eq({}, fn.luaeval('vim.api.nvim__id_array({[vim.type_idx]=vim.types.array})'))
+
+ eq(
+ { 42 },
+ fn.luaeval(
+ 'vim.api.nvim__id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'
+ )
+ )
+ eq(
+ { { foo = 2 } },
+ fn.luaeval(
+ 'vim.api.nvim__id_array({{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'
+ )
+ )
+ eq(
+ { 10 },
+ fn.luaeval(
+ 'vim.api.nvim__id_array({{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'
+ )
+ )
+ eq(
+ {},
+ fn.luaeval(
+ 'vim.api.nvim__id_array({[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2})'
+ )
+ )
+
+ eq({}, fn.luaeval('vim.api.nvim__id_array({})'))
eq(3, eval([[type(luaeval('vim.api.nvim__id_array({})'))]]))
end)
it('correctly converts dictionaries with type_idx to API objects', function()
- eq(4, eval([[type(luaeval('vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary})'))]]))
-
- eq({}, funcs.luaeval('vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary})'))
-
- eq({v={42}}, funcs.luaeval('vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'))
- eq({foo=2}, funcs.luaeval('vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'))
- eq({v=10}, funcs.luaeval('vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'))
- eq({v={}}, funcs.luaeval('vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2}})'))
+ eq(
+ 4,
+ eval([[type(luaeval('vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary})'))]])
+ )
+
+ eq({}, fn.luaeval('vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary})'))
+
+ eq(
+ { v = { 42 } },
+ fn.luaeval(
+ 'vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'
+ )
+ )
+ eq(
+ { foo = 2 },
+ fn.luaeval(
+ 'vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42})'
+ )
+ )
+ eq(
+ { v = 10 },
+ fn.luaeval(
+ 'vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}})'
+ )
+ )
+ eq(
+ { v = {} },
+ fn.luaeval(
+ 'vim.api.nvim__id_dictionary({v={[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2}})'
+ )
+ )
-- If API requests dictionary, then empty table will be the one. This is not
-- the case normally because empty table is an empty array.
- eq({}, funcs.luaeval('vim.api.nvim__id_dictionary({})'))
+ eq({}, fn.luaeval('vim.api.nvim__id_dictionary({})'))
eq(4, eval([[type(luaeval('vim.api.nvim__id_dictionary({})'))]]))
end)
it('converts booleans in positional args', function()
- eq({''}, exec_lua [[ return vim.api.nvim_buf_get_lines(0, 0, 10, false) ]])
- eq({''}, exec_lua [[ return vim.api.nvim_buf_get_lines(0, 0, 10, nil) ]])
- eq('Index out of bounds', pcall_err(exec_lua, [[ return vim.api.nvim_buf_get_lines(0, 0, 10, true) ]]))
- eq('Index out of bounds', pcall_err(exec_lua, [[ return vim.api.nvim_buf_get_lines(0, 0, 10, 1) ]]))
+ eq({ '' }, exec_lua [[ return vim.api.nvim_buf_get_lines(0, 0, 10, false) ]])
+ eq({ '' }, exec_lua [[ return vim.api.nvim_buf_get_lines(0, 0, 10, nil) ]])
+ eq(
+ 'Index out of bounds',
+ pcall_err(exec_lua, [[ return vim.api.nvim_buf_get_lines(0, 0, 10, true) ]])
+ )
+ eq(
+ 'Index out of bounds',
+ pcall_err(exec_lua, [[ return vim.api.nvim_buf_get_lines(0, 0, 10, 1) ]])
+ )
-- this follows lua conventions for bools (not api convention for Boolean)
- eq('Index out of bounds', pcall_err(exec_lua, [[ return vim.api.nvim_buf_get_lines(0, 0, 10, 0) ]]))
- eq('Index out of bounds', pcall_err(exec_lua, [[ return vim.api.nvim_buf_get_lines(0, 0, 10, {}) ]]))
+ eq(
+ 'Index out of bounds',
+ pcall_err(exec_lua, [[ return vim.api.nvim_buf_get_lines(0, 0, 10, 0) ]])
+ )
+ eq(
+ 'Index out of bounds',
+ pcall_err(exec_lua, [[ return vim.api.nvim_buf_get_lines(0, 0, 10, {}) ]])
+ )
end)
it('converts booleans in optional args', function()
@@ -190,50 +291,92 @@ describe('luaeval(vim.api.…)', function()
-- API conventions (not lua conventions): zero is falsy
eq({}, exec_lua [[ return vim.api.nvim_exec2("echo 'foobar'", {output=0}) ]])
- eq({output='foobar'}, exec_lua [[ return vim.api.nvim_exec2("echo 'foobar'", {output=true}) ]])
- eq({output='foobar'}, exec_lua [[ return vim.api.nvim_exec2("echo 'foobar'", {output=1}) ]])
- eq([[Invalid 'output': not a boolean]], pcall_err(exec_lua, [[ return vim.api.nvim_exec2("echo 'foobar'", {output={}}) ]]))
+ eq(
+ { output = 'foobar' },
+ exec_lua [[ return vim.api.nvim_exec2("echo 'foobar'", {output=true}) ]]
+ )
+ eq({ output = 'foobar' }, exec_lua [[ return vim.api.nvim_exec2("echo 'foobar'", {output=1}) ]])
+ eq(
+ [[Invalid 'output': not a boolean]],
+ pcall_err(exec_lua, [[ return vim.api.nvim_exec2("echo 'foobar'", {output={}}) ]])
+ )
end)
it('errors out correctly when working with API', function()
-- Conversion errors
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'obj': Cannot convert given Lua table]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim__id({1, foo=42})")]])))
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'obj': Cannot convert given Lua table]],
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id({1, foo=42})")]]))
+ )
-- Errors in number of arguments
- eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument',
- remove_trace(exc_exec([[call luaeval("vim.api.nvim__id()")]])))
- eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument',
- remove_trace(exc_exec([[call luaeval("vim.api.nvim__id(1, 2)")]])))
- eq('Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 2 arguments',
- remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2, 3)")]])))
+ eq(
+ 'Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument',
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id()")]]))
+ )
+ eq(
+ 'Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 1 argument',
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id(1, 2)")]]))
+ )
+ eq(
+ 'Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected 2 arguments',
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2, 3)")]]))
+ )
-- Error in argument types
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'name': Expected Lua string]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2)")]])))
-
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'start': Expected Lua number]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 'test', 1, false)")]])))
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'start': Number is not integral]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 1.5, 1, false)")]])))
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'window': Expected Lua number]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim_win_is_valid(nil)")]])))
-
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'flt': Expected Lua number]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_float('test')")]])))
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'flt': Expected Float-like Lua table]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_float({[vim.type_idx]=vim.types.dictionary})")]])))
-
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'arr': Expected Lua table]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_array(1)")]])))
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'arr': Expected Array-like Lua table]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_array({[vim.type_idx]=vim.types.dictionary})")]])))
-
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'dct': Expected Lua table]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_dictionary(1)")]])))
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'dct': Expected Dict-like Lua table]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.array})")]])))
-
- eq([[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected Lua table]],
- remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_keymap('', '', '', '')")]])))
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'name': Expected Lua string]],
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_var(1, 2)")]]))
+ )
+
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'start': Expected Lua number]],
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 'test', 1, false)")]]))
+ )
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'start': Number is not integral]],
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_buf_get_lines(0, 1.5, 1, false)")]]))
+ )
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'window': Expected Lua number]],
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_win_is_valid(nil)")]]))
+ )
+
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'flt': Expected Lua number]],
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_float('test')")]]))
+ )
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'flt': Expected Float-like Lua table]],
+ remove_trace(
+ exc_exec([[call luaeval("vim.api.nvim__id_float({[vim.type_idx]=vim.types.dictionary})")]])
+ )
+ )
+
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'arr': Expected Lua table]],
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_array(1)")]]))
+ )
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'arr': Expected Array-like Lua table]],
+ remove_trace(
+ exc_exec([[call luaeval("vim.api.nvim__id_array({[vim.type_idx]=vim.types.dictionary})")]])
+ )
+ )
+
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'dct': Expected Lua table]],
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim__id_dictionary(1)")]]))
+ )
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Invalid 'dct': Expected Dict-like Lua table]],
+ remove_trace(
+ exc_exec([[call luaeval("vim.api.nvim__id_dictionary({[vim.type_idx]=vim.types.array})")]])
+ )
+ )
+
+ eq(
+ [[Vim(call):E5108: Error executing lua [string "luaeval()"]:1: Expected Lua table]],
+ remove_trace(exc_exec([[call luaeval("vim.api.nvim_set_keymap('', '', '', '')")]]))
+ )
-- TODO: check for errors with Tabpage argument
-- TODO: check for errors with Window argument
@@ -241,8 +384,15 @@ describe('luaeval(vim.api.…)', function()
end)
it('accepts any value as API Boolean', function()
- eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", vim, false, nil)'))
- eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", 0, 1.5, "test")'))
- eq('', funcs.luaeval('vim.api.nvim_replace_termcodes("", true, {}, {[vim.type_idx]=vim.types.array})'))
+ eq('', fn.luaeval('vim.api.nvim_replace_termcodes("", vim, false, nil)'))
+ eq('', fn.luaeval('vim.api.nvim_replace_termcodes("", 0, 1.5, "test")'))
+ eq(
+ '',
+ fn.luaeval('vim.api.nvim_replace_termcodes("", true, {}, {[vim.type_idx]=vim.types.array})')
+ )
+ end)
+
+ it('serializes sparse arrays in Lua', function()
+ eq({ [1] = vim.NIL, [2] = 2 }, exec_lua [[ return { [2] = 2 } ]])
end)
end)
diff --git a/test/functional/lua/base64_spec.lua b/test/functional/lua/base64_spec.lua
index f0d112c23e..21fd536a98 100644
--- a/test/functional/lua/base64_spec.lua
+++ b/test/functional/lua/base64_spec.lua
@@ -49,12 +49,15 @@ describe('vim.base64', function()
end
-- Explicitly check encoded output
- eq('VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZwo=', encode('The quick brown fox jumps over the lazy dog\n'))
+ eq(
+ 'VGhlIHF1aWNrIGJyb3duIGZveCBqdW1wcyBvdmVyIHRoZSBsYXp5IGRvZwo=',
+ encode('The quick brown fox jumps over the lazy dog\n')
+ )
-- Test vectors from rfc4648
local rfc4648 = {
{ '', '' },
- { 'f', 'Zg==', },
+ { 'f', 'Zg==' },
{ 'fo', 'Zm8=' },
{ 'foo', 'Zm9v' },
{ 'foob', 'Zm9vYg==' },
diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua
index 51e4548edb..714e1b951f 100644
--- a/test/functional/lua/buffer_updates_spec.lua
+++ b/test/functional/lua/buffer_updates_spec.lua
@@ -1,10 +1,9 @@
-- Test suite for testing interactions with API bindings
local helpers = require('test.functional.helpers')(after_each)
-local luv = require('luv')
local command = helpers.command
-local meths = helpers.meths
-local funcs = helpers.funcs
+local api = helpers.api
+local fn = helpers.fn
local clear = helpers.clear
local eq = helpers.eq
local fail = helpers.fail
@@ -14,15 +13,17 @@ local expect_events = helpers.expect_events
local write_file = helpers.write_file
local dedent = helpers.dedent
-local origlines = {"original line 1",
- "original line 2",
- "original line 3",
- "original line 4",
- "original line 5",
- "original line 6",
- " indented line"}
-
-before_each(function ()
+local origlines = {
+ 'original line 1',
+ 'original line 2',
+ 'original line 3',
+ 'original line 4',
+ 'original line 5',
+ 'original line 6',
+ ' indented line',
+}
+
+before_each(function()
clear()
exec_lua [[
local evname = ...
@@ -53,15 +54,15 @@ end)
describe('lua buffer event callbacks: on_lines', function()
local function setup_eventcheck(verify, utf_sizes, lines)
local lastsize
- meths.buf_set_lines(0, 0, -1, true, lines)
+ api.nvim_buf_set_lines(0, 0, -1, true, lines)
if verify then
- lastsize = meths.buf_get_offset(0, meths.buf_line_count(0))
+ lastsize = api.nvim_buf_get_offset(0, api.nvim_buf_line_count(0))
end
- exec_lua("return test_register(...)", 0, "on_lines", "test1",false,utf_sizes)
- local verify_name = "test1"
+ exec_lua('return test_register(...)', 0, 'on_lines', 'test1', false, utf_sizes)
+ local verify_name = 'test1'
local function check_events(expected)
- local events = exec_lua("return get_events(...)" )
+ local events = exec_lua('return get_events(...)')
if utf_sizes then
-- this test case uses ASCII only, so sizes should be the same.
-- Unicode is tested below.
@@ -70,13 +71,14 @@ describe('lua buffer event callbacks: on_lines', function()
event[10] = event[10] or event[9]
end
end
- expect_events(expected, events, "line updates")
+ expect_events(expected, events, 'line updates')
if verify then
for _, event in ipairs(events) do
- if event[1] == verify_name and event[2] == "lines" then
+ if event[1] == verify_name and event[2] == 'lines' then
local startline, endline = event[5], event[7]
- local newrange = meths.buf_get_offset(0, endline) - meths.buf_get_offset(0, startline)
- local newsize = meths.buf_get_offset(0, meths.buf_line_count(0))
+ local newrange = api.nvim_buf_get_offset(0, endline)
+ - api.nvim_buf_get_offset(0, startline)
+ local newsize = api.nvim_buf_get_offset(0, api.nvim_buf_line_count(0))
local oldrange = newrange + lastsize - newsize
eq(oldrange, event[8])
lastsize = newsize
@@ -84,101 +86,102 @@ describe('lua buffer event callbacks: on_lines', function()
end
end
end
- return check_events, function(new) verify_name = new end
+ return check_events, function(new)
+ verify_name = new
+ end
end
-
-- verifying the sizes with nvim_buf_get_offset is nice (checks we cannot
-- assert the wrong thing), but masks errors with unflushed lines (as
-- nvim_buf_get_offset forces a flush of the memline). To be safe run the
-- test both ways.
- local function check(verify,utf_sizes)
+ local function check(verify, utf_sizes)
local check_events, verify_name = setup_eventcheck(verify, utf_sizes, origlines)
- local tick = meths.buf_get_changedtick(0)
+ local tick = api.nvim_buf_get_changedtick(0)
command('set autoindent')
command('normal! GyyggP')
tick = tick + 1
- check_events {{ "test1", "lines", 1, tick, 0, 0, 1, 0}}
+ check_events { { 'test1', 'lines', 1, tick, 0, 0, 1, 0 } }
- meths.buf_set_lines(0, 3, 5, true, {"changed line"})
+ api.nvim_buf_set_lines(0, 3, 5, true, { 'changed line' })
tick = tick + 1
- check_events {{ "test1", "lines", 1, tick, 3, 5, 4, 32 }}
+ check_events { { 'test1', 'lines', 1, tick, 3, 5, 4, 32 } }
- exec_lua("return test_register(...)", 0, "on_lines", "test2", true, utf_sizes)
+ exec_lua('return test_register(...)', 0, 'on_lines', 'test2', true, utf_sizes)
tick = tick + 1
command('undo')
-- plugins can opt in to receive changedtick events, or choose
-- to only receive actual changes.
check_events {
- { "test1", "lines", 1, tick, 3, 4, 5, 13 };
- { "test2", "lines", 1, tick, 3, 4, 5, 13 };
- { "test2", "changedtick", 1, tick+1 };
+ { 'test1', 'lines', 1, tick, 3, 4, 5, 13 },
+ { 'test2', 'lines', 1, tick, 3, 4, 5, 13 },
+ { 'test2', 'changedtick', 1, tick + 1 },
}
tick = tick + 1
tick = tick + 1
command('redo')
check_events {
- { "test1", "lines", 1, tick, 3, 5, 4, 32 };
- { "test2", "lines", 1, tick, 3, 5, 4, 32 };
- { "test2", "changedtick", 1, tick+1 };
+ { 'test1', 'lines', 1, tick, 3, 5, 4, 32 },
+ { 'test2', 'lines', 1, tick, 3, 5, 4, 32 },
+ { 'test2', 'changedtick', 1, tick + 1 },
}
tick = tick + 1
tick = tick + 1
command('undo!')
check_events {
- { "test1", "lines", 1, tick, 3, 4, 5, 13 };
- { "test2", "lines", 1, tick, 3, 4, 5, 13 };
- { "test2", "changedtick", 1, tick+1 };
+ { 'test1', 'lines', 1, tick, 3, 4, 5, 13 },
+ { 'test2', 'lines', 1, tick, 3, 4, 5, 13 },
+ { 'test2', 'changedtick', 1, tick + 1 },
}
tick = tick + 1
-- simulate next callback returning true
exec_lua("test_unreg = 'test1'")
- meths.buf_set_lines(0, 6, 7, true, {"x1","x2","x3"})
+ api.nvim_buf_set_lines(0, 6, 7, true, { 'x1', 'x2', 'x3' })
tick = tick + 1
-- plugins can opt in to receive changedtick events, or choose
-- to only receive actual changes.
check_events {
- { "test1", "lines", 1, tick, 6, 7, 9, 16 };
- { "test2", "lines", 1, tick, 6, 7, 9, 16 };
+ { 'test1', 'lines', 1, tick, 6, 7, 9, 16 },
+ { 'test2', 'lines', 1, tick, 6, 7, 9, 16 },
}
- verify_name "test2"
+ verify_name 'test2'
- meths.buf_set_lines(0, 1, 1, true, {"added"})
+ api.nvim_buf_set_lines(0, 1, 1, true, { 'added' })
tick = tick + 1
- check_events {{ "test2", "lines", 1, tick, 1, 1, 2, 0 }}
+ check_events { { 'test2', 'lines', 1, tick, 1, 1, 2, 0 } }
feed('wix')
tick = tick + 1
- check_events {{ "test2", "lines", 1, tick, 4, 5, 5, 16 }}
+ check_events { { 'test2', 'lines', 1, tick, 4, 5, 5, 16 } }
-- check hot path for multiple insert
feed('yz')
tick = tick + 1
- check_events {{ "test2", "lines", 1, tick, 4, 5, 5, 17 }}
+ check_events { { 'test2', 'lines', 1, tick, 4, 5, 5, 17 } }
feed('<bs>')
tick = tick + 1
- check_events {{ "test2", "lines", 1, tick, 4, 5, 5, 19 }}
+ check_events { { 'test2', 'lines', 1, tick, 4, 5, 5, 19 } }
feed('<esc>Go')
tick = tick + 1
- check_events {{ "test2", "lines", 1, tick, 11, 11, 12, 0 }}
+ check_events { { 'test2', 'lines', 1, tick, 11, 11, 12, 0 } }
feed('x')
tick = tick + 1
- check_events {{ "test2", "lines", 1, tick, 11, 12, 12, 5 }}
+ check_events { { 'test2', 'lines', 1, tick, 11, 12, 12, 5 } }
command('bwipe!')
- check_events {{ "test2", "detach", 1 }}
- end
+ check_events { { 'test2', 'detach', 1 } }
+ end
it('works', function()
check(false)
@@ -189,54 +192,56 @@ describe('lua buffer event callbacks: on_lines', function()
end)
it('works with utf_sizes and ASCII text', function()
- check(false,true)
+ check(false, true)
end)
local function check_unicode(verify)
- local unicode_text = {"ascii text",
- "latin text åäö",
- "BMP text ɧ αλφά",
- "BMP text 汉语 ↥↧",
- "SMP 🤦 🦄🦃",
- "combining aÌŠ بÙيَّة"}
+ local unicode_text = {
+ 'ascii text',
+ 'latin text åäö',
+ 'BMP text ɧ αλφά',
+ 'BMP text 汉语 ↥↧',
+ 'SMP 🤦 🦄🦃',
+ 'combining aÌŠ بÙيَّة',
+ }
local check_events, verify_name = setup_eventcheck(verify, true, unicode_text)
- local tick = meths.buf_get_changedtick(0)
+ local tick = api.nvim_buf_get_changedtick(0)
feed('ggdd')
tick = tick + 1
- check_events {{ "test1", "lines", 1, tick, 0, 1, 0, 11, 11, 11 }}
+ check_events { { 'test1', 'lines', 1, tick, 0, 1, 0, 11, 11, 11 } }
feed('A<bs>')
tick = tick + 1
- check_events {{ "test1", "lines", 1, tick, 0, 1, 1, 18, 15, 15 }}
+ check_events { { 'test1', 'lines', 1, tick, 0, 1, 1, 18, 15, 15 } }
feed('<esc>jylp')
tick = tick + 1
- check_events {{ "test1", "lines", 1, tick, 1, 2, 2, 21, 16, 16 }}
+ check_events { { 'test1', 'lines', 1, tick, 1, 2, 2, 21, 16, 16 } }
feed('+eea<cr>')
tick = tick + 1
- check_events {{ "test1", "lines", 1, tick, 2, 3, 4, 23, 15, 15 }}
+ check_events { { 'test1', 'lines', 1, tick, 2, 3, 4, 23, 15, 15 } }
feed('<esc>jdw')
tick = tick + 1
-- non-BMP chars count as 2 UTF-2 codeunits
- check_events {{ "test1", "lines", 1, tick, 4, 5, 5, 18, 9, 12 }}
+ check_events { { 'test1', 'lines', 1, tick, 4, 5, 5, 18, 9, 12 } }
feed('+rx')
tick = tick + 1
-- count the individual codepoints of a composed character.
- check_events {{ "test1", "lines", 1, tick, 5, 6, 6, 27, 20, 20 }}
+ check_events { { 'test1', 'lines', 1, tick, 5, 6, 6, 27, 20, 20 } }
feed('kJ')
tick = tick + 1
-- verification fails with multiple line updates, sorry about that
- verify_name ""
+ verify_name ''
-- NB: this is inefficient (but not really wrong).
check_events {
- { "test1", "lines", 1, tick, 4, 5, 5, 14, 5, 8 };
- { "test1", "lines", 1, tick+1, 5, 6, 5, 27, 20, 20 };
+ { 'test1', 'lines', 1, tick, 4, 5, 5, 14, 5, 8 },
+ { 'test1', 'lines', 1, tick + 1, 5, 6, 5, 27, 20, 20 },
}
end
@@ -248,9 +253,8 @@ describe('lua buffer event callbacks: on_lines', function()
check_unicode(true)
end)
-
it('has valid cursor position while shifting', function()
- meths.buf_set_lines(0, 0, -1, true, {'line1'})
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'line1' })
exec_lua([[
vim.api.nvim_buf_attach(0, false, {
on_lines = function()
@@ -259,15 +263,15 @@ describe('lua buffer event callbacks: on_lines', function()
})
]])
feed('>>')
- eq(1, meths.get_var('listener_cursor_line'))
+ eq(1, api.nvim_get_var('listener_cursor_line'))
end)
it('has valid cursor position while deleting lines', function()
- meths.buf_set_lines(0, 0, -1, true, { "line_1", "line_2", "line_3", "line_4"})
- meths.win_set_cursor(0, {2, 0})
- eq(2, meths.win_get_cursor(0)[1])
- meths.buf_set_lines(0, 0, -1, true, { "line_1", "line_2", "line_3"})
- eq(2, meths.win_get_cursor(0)[1])
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'line_1', 'line_2', 'line_3', 'line_4' })
+ api.nvim_win_set_cursor(0, { 2, 0 })
+ eq(2, api.nvim_win_get_cursor(0)[1])
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'line_1', 'line_2', 'line_3' })
+ eq(2, api.nvim_win_get_cursor(0)[1])
end)
it('does not SEGFAULT when accessing window buffer info in on_detach #14998', function()
@@ -286,16 +290,16 @@ describe('lua buffer event callbacks: on_lines', function()
]]
exec_lua(code)
- command("q!")
+ command('q!')
helpers.assert_alive()
exec_lua(code)
- command("bd!")
+ command('bd!')
helpers.assert_alive()
end)
it('#12718 lnume', function()
- meths.buf_set_lines(0, 0, -1, true, {'1', '2', '3'})
+ api.nvim_buf_set_lines(0, 0, -1, true, { '1', '2', '3' })
exec_lua([[
vim.api.nvim_buf_attach(0, false, {
on_lines = function(...)
@@ -308,28 +312,31 @@ describe('lua buffer event callbacks: on_lines', function()
feed('G0')
feed('p')
-- Is the last arg old_byte_size correct? Doesn't matter for this PR
- eq(meths.get_var('linesev'), { "lines", 1, 4, 2, 3, 5, 4 })
+ eq(api.nvim_get_var('linesev'), { 'lines', 1, 4, 2, 3, 5, 4 })
feed('2G0')
feed('p')
- eq(meths.get_var('linesev'), { "lines", 1, 5, 1, 4, 4, 8 })
+ eq(api.nvim_get_var('linesev'), { 'lines', 1, 5, 1, 4, 4, 8 })
feed('1G0')
feed('P')
- eq(meths.get_var('linesev'), { "lines", 1, 6, 0, 3, 3, 9 })
+ eq(api.nvim_get_var('linesev'), { 'lines', 1, 6, 0, 3, 3, 9 })
end)
- it('calling nvim_buf_call() from callback does not cause Normal mode CTRL-A to misbehave #16729', function()
- exec_lua([[
+ it(
+ 'calling nvim_buf_call() from callback does not cause Normal mode CTRL-A to misbehave #16729',
+ function()
+ exec_lua([[
vim.api.nvim_buf_attach(0, false, {
on_lines = function(...)
vim.api.nvim_buf_call(0, function() end)
end,
})
]])
- feed('itest123<Esc><C-A>')
- eq('test124', meths.get_current_line())
- end)
+ feed('itest123<Esc><C-A>')
+ eq('test124', api.nvim_get_current_line())
+ end
+ )
end)
describe('lua: nvim_buf_attach on_bytes', function()
@@ -339,24 +346,24 @@ describe('lua: nvim_buf_attach on_bytes', function()
-- test both ways.
local function setup_eventcheck(verify, start_txt)
if start_txt then
- meths.buf_set_lines(0, 0, -1, true, start_txt)
+ api.nvim_buf_set_lines(0, 0, -1, true, start_txt)
else
- start_txt = meths.buf_get_lines(0, 0, -1, true)
+ start_txt = api.nvim_buf_get_lines(0, 0, -1, true)
end
local shadowbytes = table.concat(start_txt, '\n') .. '\n'
-- TODO: while we are brewing the real strong coffee,
-- verify should check buf_get_offset after every check_events
if verify then
- local len = meths.buf_get_offset(0, meths.buf_line_count(0))
+ local len = api.nvim_buf_get_offset(0, api.nvim_buf_line_count(0))
eq(len == -1 and 1 or len, string.len(shadowbytes))
end
- exec_lua("return test_register(...)", 0, "on_bytes", "test1", false, false, true)
- meths.buf_get_changedtick(0)
+ exec_lua('return test_register(...)', 0, 'on_bytes', 'test1', false, false, true)
+ api.nvim_buf_get_changedtick(0)
- local verify_name = "test1"
+ local verify_name = 'test1'
local function check_events(expected)
- local events = exec_lua("return get_events(...)" )
- expect_events(expected, events, "byte updates")
+ local events = exec_lua('return get_events(...)')
+ expect_events(expected, events, 'byte updates')
if not verify then
return
@@ -364,12 +371,12 @@ describe('lua: nvim_buf_attach on_bytes', function()
for _, event in ipairs(events) do
for _, elem in ipairs(event) do
- if type(elem) == "number" and elem < 0 then
- fail(string.format("Received event has negative values"))
+ if type(elem) == 'number' and elem < 0 then
+ fail(string.format('Received event has negative values'))
end
end
- if event[1] == verify_name and event[2] == "bytes" then
+ if event[1] == verify_name and event[2] == 'bytes' then
local _, _, _, _, _, _, start_byte, _, _, old_byte, _, _, new_byte = unpack(event)
local before = string.sub(shadowbytes, 1, start_byte)
-- no text in the tests will contain 0xff bytes (invalid UTF-8)
@@ -377,15 +384,19 @@ describe('lua: nvim_buf_attach on_bytes', function()
local unknown = string.rep('\255', new_byte)
local after = string.sub(shadowbytes, start_byte + old_byte + 1)
shadowbytes = before .. unknown .. after
- elseif event[1] == verify_name and event[2] == "reload" then
- shadowbytes = table.concat(meths.buf_get_lines(0, 0, -1, true), '\n') .. '\n'
+ elseif event[1] == verify_name and event[2] == 'reload' then
+ shadowbytes = table.concat(api.nvim_buf_get_lines(0, 0, -1, true), '\n') .. '\n'
end
end
- local text = meths.buf_get_lines(0, 0, -1, true)
+ local text = api.nvim_buf_get_lines(0, 0, -1, true)
local bytes = table.concat(text, '\n') .. '\n'
- eq(string.len(bytes), string.len(shadowbytes), '\non_bytes: total bytecount of buffer is wrong')
+ eq(
+ string.len(bytes),
+ string.len(shadowbytes),
+ '\non_bytes: total bytecount of buffer is wrong'
+ )
for i = 1, string.len(shadowbytes) do
local shadowbyte = string.sub(shadowbytes, i, i)
if shadowbyte ~= '\255' then
@@ -400,89 +411,89 @@ describe('lua: nvim_buf_attach on_bytes', function()
-- Yes, we can do both
local function do_both(verify)
it('single and multiple join', function()
- local check_events = setup_eventcheck(verify, origlines)
- feed 'ggJ'
- check_events {
- {'test1', 'bytes', 1, 3, 0, 15, 15, 1, 0, 1, 0, 1, 1};
- }
+ local check_events = setup_eventcheck(verify, origlines)
+ feed 'ggJ'
+ check_events {
+ { 'test1', 'bytes', 1, 3, 0, 15, 15, 1, 0, 1, 0, 1, 1 },
+ }
- feed '3J'
- check_events {
- {'test1', 'bytes', 1, 5, 0, 31, 31, 1, 0, 1, 0, 1, 1};
- {'test1', 'bytes', 1, 5, 0, 47, 47, 1, 0, 1, 0, 1, 1};
- }
+ feed '3J'
+ check_events {
+ { 'test1', 'bytes', 1, 5, 0, 31, 31, 1, 0, 1, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 5, 0, 47, 47, 1, 0, 1, 0, 1, 1 },
+ }
end)
it('opening lines', function()
- local check_events = setup_eventcheck(verify, origlines)
- -- meths.set_option_value('autoindent', true, {})
- feed 'Go'
- check_events {
- { "test1", "bytes", 1, 4, 7, 0, 114, 0, 0, 0, 1, 0, 1 };
- }
- feed '<cr>'
- check_events {
- { "test1", "bytes", 1, 5, 7, 0, 114, 0, 0, 0, 1, 0, 1 };
- }
+ local check_events = setup_eventcheck(verify, origlines)
+ -- api.nvim_set_option_value('autoindent', true, {})
+ feed 'Go'
+ check_events {
+ { 'test1', 'bytes', 1, 3, 7, 0, 114, 0, 0, 0, 1, 0, 1 },
+ }
+ feed '<cr>'
+ check_events {
+ { 'test1', 'bytes', 1, 5, 7, 0, 114, 0, 0, 0, 1, 0, 1 },
+ }
end)
it('opening lines with autoindent', function()
- local check_events = setup_eventcheck(verify, origlines)
- meths.set_option_value('autoindent', true, {})
- feed 'Go'
- check_events {
- { "test1", "bytes", 1, 4, 7, 0, 114, 0, 0, 0, 1, 0, 5 };
- }
- feed '<cr>'
- check_events {
- { "test1", "bytes", 1, 4, 7, 0, 114, 0, 4, 4, 0, 0, 0 };
- { "test1", "bytes", 1, 5, 7, 0, 114, 0, 0, 0, 1, 4, 5 };
- }
+ local check_events = setup_eventcheck(verify, origlines)
+ api.nvim_set_option_value('autoindent', true, {})
+ feed 'Go'
+ check_events {
+ { 'test1', 'bytes', 1, 3, 7, 0, 114, 0, 0, 0, 1, 0, 5 },
+ }
+ feed '<cr>'
+ check_events {
+ { 'test1', 'bytes', 1, 4, 7, 0, 114, 0, 4, 4, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 5, 7, 0, 114, 0, 0, 0, 1, 4, 5 },
+ }
end)
it('setline(num, line)', function()
local check_events = setup_eventcheck(verify, origlines)
- funcs.setline(2, "babla")
+ fn.setline(2, 'babla')
check_events {
- { "test1", "bytes", 1, 3, 1, 0, 16, 0, 15, 15, 0, 5, 5 };
+ { 'test1', 'bytes', 1, 3, 1, 0, 16, 0, 15, 15, 0, 5, 5 },
}
- funcs.setline(2, {"foo", "bar"})
+ fn.setline(2, { 'foo', 'bar' })
check_events {
- { "test1", "bytes", 1, 4, 1, 0, 16, 0, 5, 5, 0, 3, 3 };
- { "test1", "bytes", 1, 5, 2, 0, 20, 0, 15, 15, 0, 3, 3 };
+ { 'test1', 'bytes', 1, 4, 1, 0, 16, 0, 5, 5, 0, 3, 3 },
+ { 'test1', 'bytes', 1, 5, 2, 0, 20, 0, 15, 15, 0, 3, 3 },
}
- local buf_len = meths.buf_line_count(0)
- funcs.setline(buf_len + 1, "baz")
+ local buf_len = api.nvim_buf_line_count(0)
+ fn.setline(buf_len + 1, 'baz')
check_events {
- { "test1", "bytes", 1, 6, 7, 0, 90, 0, 0, 0, 1, 0, 4 };
+ { 'test1', 'bytes', 1, 6, 7, 0, 90, 0, 0, 0, 1, 0, 4 },
}
end)
it('continuing comments with fo=or', function()
- local check_events = setup_eventcheck(verify, {'// Comment'})
- meths.set_option_value('formatoptions', 'ro', {})
- meths.set_option_value('filetype', 'c', {})
+ local check_events = setup_eventcheck(verify, { '// Comment' })
+ api.nvim_set_option_value('formatoptions', 'ro', {})
+ api.nvim_set_option_value('filetype', 'c', {})
feed 'A<CR>'
check_events {
- { "test1", "bytes", 1, 4, 0, 10, 10, 0, 0, 0, 1, 3, 4 };
+ { 'test1', 'bytes', 1, 4, 0, 10, 10, 0, 0, 0, 1, 3, 4 },
}
feed '<ESC>'
check_events {
- { "test1", "bytes", 1, 4, 1, 2, 13, 0, 1, 1, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 4, 1, 2, 13, 0, 1, 1, 0, 0, 0 },
}
feed 'ggo' -- goto first line to continue testing
check_events {
- { "test1", "bytes", 1, 6, 1, 0, 11, 0, 0, 0, 1, 0, 4 };
+ { 'test1', 'bytes', 1, 5, 1, 0, 11, 0, 0, 0, 1, 0, 4 },
}
feed '<CR>'
check_events {
- { "test1", "bytes", 1, 6, 1, 2, 13, 0, 1, 1, 0, 0, 0 };
- { "test1", "bytes", 1, 7, 1, 2, 13, 0, 0, 0, 1, 3, 4 };
+ { 'test1', 'bytes', 1, 6, 1, 2, 13, 0, 1, 1, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 7, 1, 2, 13, 0, 0, 0, 1, 3, 4 },
}
end)
@@ -491,757 +502,775 @@ describe('lua: nvim_buf_attach on_bytes', function()
feed 'ia'
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
}
end)
- it("deleting lines", function()
+ it('deleting lines', function()
local check_events = setup_eventcheck(verify, origlines)
- feed("dd")
+ feed('dd')
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 1, 0, 16, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 1, 0, 16, 0, 0, 0 },
}
- feed("d2j")
+ feed('d2j')
check_events {
- { "test1", "bytes", 1, 4, 0, 0, 0, 3, 0, 48, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 4, 0, 0, 0, 3, 0, 48, 0, 0, 0 },
}
- feed("ld<c-v>2j")
+ feed('ld<c-v>2j')
check_events {
- { "test1", "bytes", 1, 5, 0, 1, 1, 0, 1, 1, 0, 0, 0 };
- { "test1", "bytes", 1, 5, 1, 1, 16, 0, 1, 1, 0, 0, 0 };
- { "test1", "bytes", 1, 5, 2, 1, 31, 0, 1, 1, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 5, 0, 1, 1, 0, 1, 1, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 5, 1, 1, 16, 0, 1, 1, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 5, 2, 1, 31, 0, 1, 1, 0, 0, 0 },
}
- feed("vjwd")
+ feed('vjwd')
check_events {
- { "test1", "bytes", 1, 10, 0, 1, 1, 1, 9, 23, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 10, 0, 1, 1, 1, 9, 23, 0, 0, 0 },
}
end)
- it("changing lines", function()
+ it('changing lines', function()
local check_events = setup_eventcheck(verify, origlines)
- feed "cc"
+ feed 'cc'
check_events {
- { "test1", "bytes", 1, 4, 0, 0, 0, 0, 15, 15, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 4, 0, 0, 0, 0, 15, 15, 0, 0, 0 },
}
- feed "<ESC>"
+ feed '<ESC>'
check_events {}
- feed "c3j"
+ feed 'c3j'
check_events {
- { "test1", "bytes", 1, 4, 1, 0, 1, 3, 0, 48, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 4, 1, 0, 1, 3, 0, 48, 0, 0, 0 },
}
end)
- it("visual charwise paste", function()
- local check_events = setup_eventcheck(verify, {'1234567890'})
- funcs.setreg('a', '___')
+ it('visual charwise paste', function()
+ local check_events = setup_eventcheck(verify, { '1234567890' })
+ fn.setreg('a', '___')
feed '1G1|vll'
check_events {}
feed '"ap'
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 0, 3, 3, 0, 0, 0 };
- { "test1", "bytes", 1, 5, 0, 0, 0, 0, 0, 0, 0, 3, 3 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 3, 3, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 5, 0, 0, 0, 0, 0, 0, 0, 3, 3 },
}
end)
it('blockwise paste', function()
- local check_events = setup_eventcheck(verify, {'1', '2', '3'})
+ local check_events = setup_eventcheck(verify, { '1', '2', '3' })
feed('1G0')
feed('y<C-v>2j')
feed('G0')
feed('p')
check_events {
- { "test1", "bytes", 1, 3, 2, 1, 5, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 3, 3, 0, 7, 0, 0, 0, 0, 3, 3 };
- { "test1", "bytes", 1, 3, 4, 0, 10, 0, 0, 0, 0, 3, 3 };
+ { 'test1', 'bytes', 1, 3, 2, 1, 5, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 3, 3, 0, 7, 0, 0, 0, 0, 3, 3 },
+ { 'test1', 'bytes', 1, 3, 4, 0, 10, 0, 0, 0, 0, 3, 3 },
}
feed('2G0')
feed('p')
check_events {
- { "test1", "bytes", 1, 4, 1, 1, 3, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 4, 2, 1, 6, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 4, 3, 1, 10, 0, 0, 0, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 4, 1, 1, 3, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 4, 2, 1, 6, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 4, 3, 1, 10, 0, 0, 0, 0, 1, 1 },
}
feed('1G0')
feed('P')
check_events {
- { "test1", "bytes", 1, 5, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 5, 1, 0, 3, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 5, 2, 0, 7, 0, 0, 0, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 5, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 5, 1, 0, 3, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 5, 2, 0, 7, 0, 0, 0, 0, 1, 1 },
}
-
end)
- it("linewise paste", function()
+ it('linewise paste', function()
local check_events = setup_eventcheck(verify, origlines)
- feed'yyp'
+ feed 'yyp'
check_events {
- { "test1", "bytes", 1, 3, 1, 0, 16, 0, 0, 0, 1, 0, 16 };
+ { 'test1', 'bytes', 1, 3, 1, 0, 16, 0, 0, 0, 1, 0, 16 },
}
- feed'Gyyp'
+ feed 'Gyyp'
check_events {
- { "test1", "bytes", 1, 4, 8, 0, 130, 0, 0, 0, 1, 0, 18 };
+ { 'test1', 'bytes', 1, 4, 8, 0, 130, 0, 0, 0, 1, 0, 18 },
}
end)
it('inccomand=nosplit and substitute', function()
- local check_events = setup_eventcheck(verify,
- {"abcde", "12345"})
- meths.set_option_value('inccommand', 'nosplit', {})
+ local check_events = setup_eventcheck(verify, { 'abcde', '12345' })
+ api.nvim_set_option_value('inccommand', 'nosplit', {})
-- linewise substitute
feed(':%s/bcd/')
check_events {
- { "test1", "bytes", 1, 3, 0, 1, 1, 0, 3, 3, 0, 0, 0 };
- { "test1", "bytes", 1, 5, 0, 1, 1, 0, 0, 0, 0, 3, 3 };
+ { 'test1', 'bytes', 1, 3, 0, 1, 1, 0, 3, 3, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 5, 0, 1, 1, 0, 0, 0, 0, 3, 3 },
}
feed('a')
check_events {
- { "test1", "bytes", 1, 3, 0, 1, 1, 0, 3, 3, 0, 1, 1 };
- { "test1", "bytes", 1, 5, 0, 1, 1, 0, 1, 1, 0, 3, 3 };
+ { 'test1', 'bytes', 1, 3, 0, 1, 1, 0, 3, 3, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 5, 0, 1, 1, 0, 1, 1, 0, 3, 3 },
}
- feed("<esc>")
+ feed('<esc>')
-- splitting lines
feed([[:%s/abc/\r]])
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 0, 3, 3, 1, 0, 1 };
- { "test1", "bytes", 1, 6, 0, 0, 0, 1, 0, 1, 0, 3, 3 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 3, 3, 1, 0, 1 },
+ { 'test1', 'bytes', 1, 6, 0, 0, 0, 1, 0, 1, 0, 3, 3 },
}
- feed("<esc>")
+ feed('<esc>')
-- multi-line regex
feed([[:%s/de\n123/a]])
check_events {
- { "test1", "bytes", 1, 3, 0, 3, 3, 1, 3, 6, 0, 1, 1 };
- { "test1", "bytes", 1, 6, 0, 3, 3, 0, 1, 1, 1, 3, 6 };
+ { 'test1', 'bytes', 1, 3, 0, 3, 3, 1, 3, 6, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 6, 0, 3, 3, 0, 1, 1, 1, 3, 6 },
}
- feed("<esc>")
+ feed('<esc>')
-- replacing with unicode
- feed(":%s/b/→")
+ feed(':%s/b/→')
check_events {
- { "test1", "bytes", 1, 3, 0, 1, 1, 0, 1, 1, 0, 3, 3 };
- { "test1", "bytes", 1, 5, 0, 1, 1, 0, 3, 3, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 3, 0, 1, 1, 0, 1, 1, 0, 3, 3 },
+ { 'test1', 'bytes', 1, 5, 0, 1, 1, 0, 3, 3, 0, 1, 1 },
}
- feed("<esc>")
+ feed('<esc>')
-- replacing with expression register
feed([[:%s/b/\=5+5]])
check_events {
- { "test1", "bytes", 1, 3, 0, 1, 1, 0, 1, 1, 0, 2, 2 };
- { "test1", "bytes", 1, 5, 0, 1, 1, 0, 2, 2, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 3, 0, 1, 1, 0, 1, 1, 0, 2, 2 },
+ { 'test1', 'bytes', 1, 5, 0, 1, 1, 0, 2, 2, 0, 1, 1 },
}
- feed("<esc>")
+ feed('<esc>')
-- replacing with backslash
feed([[:%s/b/\\]])
check_events {
- { "test1", "bytes", 1, 3, 0, 1, 1, 0, 1, 1, 0, 1, 1 };
- { "test1", "bytes", 1, 5, 0, 1, 1, 0, 1, 1, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 3, 0, 1, 1, 0, 1, 1, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 5, 0, 1, 1, 0, 1, 1, 0, 1, 1 },
}
- feed("<esc>")
+ feed('<esc>')
-- replacing with backslash from expression register
feed([[:%s/b/\='\']])
check_events {
- { "test1", "bytes", 1, 3, 0, 1, 1, 0, 1, 1, 0, 1, 1 };
- { "test1", "bytes", 1, 5, 0, 1, 1, 0, 1, 1, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 3, 0, 1, 1, 0, 1, 1, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 5, 0, 1, 1, 0, 1, 1, 0, 1, 1 },
}
- feed("<esc>")
+ feed('<esc>')
-- replacing with backslash followed by another character
feed([[:%s/b/\\!]])
check_events {
- { "test1", "bytes", 1, 3, 0, 1, 1, 0, 1, 1, 0, 2, 2 };
- { "test1", "bytes", 1, 5, 0, 1, 1, 0, 2, 2, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 3, 0, 1, 1, 0, 1, 1, 0, 2, 2 },
+ { 'test1', 'bytes', 1, 5, 0, 1, 1, 0, 2, 2, 0, 1, 1 },
}
- feed("<esc>")
+ feed('<esc>')
-- replacing with backslash followed by another character from expression register
feed([[:%s/b/\='\!']])
check_events {
- { "test1", "bytes", 1, 3, 0, 1, 1, 0, 1, 1, 0, 2, 2 };
- { "test1", "bytes", 1, 5, 0, 1, 1, 0, 2, 2, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 3, 0, 1, 1, 0, 1, 1, 0, 2, 2 },
+ { 'test1', 'bytes', 1, 5, 0, 1, 1, 0, 2, 2, 0, 1, 1 },
}
end)
it('nvim_buf_set_text insert', function()
- local check_events = setup_eventcheck(verify, {"bastext"})
- meths.buf_set_text(0, 0, 3, 0, 3, {"fiol","kontra"})
+ local check_events = setup_eventcheck(verify, { 'bastext' })
+ api.nvim_buf_set_text(0, 0, 3, 0, 3, { 'fiol', 'kontra' })
check_events {
- { "test1", "bytes", 1, 3, 0, 3, 3, 0, 0, 0, 1, 6, 11 };
+ { 'test1', 'bytes', 1, 3, 0, 3, 3, 0, 0, 0, 1, 6, 11 },
}
- meths.buf_set_text(0, 1, 6, 1, 6, {"punkt","syntgitarr","övnings"})
+ api.nvim_buf_set_text(0, 1, 6, 1, 6, { 'punkt', 'syntgitarr', 'övnings' })
check_events {
- { "test1", "bytes", 1, 4, 1, 6, 14, 0, 0, 0, 2, 8, 25 };
+ { 'test1', 'bytes', 1, 4, 1, 6, 14, 0, 0, 0, 2, 8, 25 },
}
- eq({ "basfiol", "kontrapunkt", "syntgitarr", "övningstext" },
- meths.buf_get_lines(0, 0, -1, true))
+ eq(
+ { 'basfiol', 'kontrapunkt', 'syntgitarr', 'övningstext' },
+ api.nvim_buf_get_lines(0, 0, -1, true)
+ )
end)
it('nvim_buf_set_text replace', function()
local check_events = setup_eventcheck(verify, origlines)
- meths.buf_set_text(0, 2, 3, 2, 8, {"very text"})
+ api.nvim_buf_set_text(0, 2, 3, 2, 8, { 'very text' })
check_events {
- { "test1", "bytes", 1, 3, 2, 3, 35, 0, 5, 5, 0, 9, 9 };
+ { 'test1', 'bytes', 1, 3, 2, 3, 35, 0, 5, 5, 0, 9, 9 },
}
- meths.buf_set_text(0, 3, 5, 3, 7, {" splitty","line "})
+ api.nvim_buf_set_text(0, 3, 5, 3, 7, { ' splitty', 'line ' })
check_events {
- { "test1", "bytes", 1, 4, 3, 5, 57, 0, 2, 2, 1, 5, 14 };
+ { 'test1', 'bytes', 1, 4, 3, 5, 57, 0, 2, 2, 1, 5, 14 },
}
- meths.buf_set_text(0, 0, 8, 1, 2, {"JOINY"})
+ api.nvim_buf_set_text(0, 0, 8, 1, 2, { 'JOINY' })
check_events {
- { "test1", "bytes", 1, 5, 0, 8, 8, 1, 2, 10, 0, 5, 5 };
+ { 'test1', 'bytes', 1, 5, 0, 8, 8, 1, 2, 10, 0, 5, 5 },
}
- meths.buf_set_text(0, 4, 0, 6, 0, {"was 5,6",""})
+ api.nvim_buf_set_text(0, 4, 0, 6, 0, { 'was 5,6', '' })
check_events {
- { "test1", "bytes", 1, 6, 4, 0, 75, 2, 0, 32, 1, 0, 8 };
+ { 'test1', 'bytes', 1, 6, 4, 0, 75, 2, 0, 32, 1, 0, 8 },
}
- eq({ "originalJOINYiginal line 2", "orivery text line 3", "origi splitty",
- "line l line 4", "was 5,6", " indented line" },
- meths.buf_get_lines(0, 0, -1, true))
-
+ eq({
+ 'originalJOINYiginal line 2',
+ 'orivery text line 3',
+ 'origi splitty',
+ 'line l line 4',
+ 'was 5,6',
+ ' indented line',
+ }, api.nvim_buf_get_lines(0, 0, -1, true))
end)
it('nvim_buf_set_text delete', function()
local check_events = setup_eventcheck(verify, origlines)
-- really {""} but accepts {} as a shorthand
- meths.buf_set_text(0, 0, 0, 1, 0, {})
+ api.nvim_buf_set_text(0, 0, 0, 1, 0, {})
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 1, 0, 16, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 1, 0, 16, 0, 0, 0 },
}
-- TODO(bfredl): this works but is not as convenient as set_lines
- meths.buf_set_text(0, 4, 15, 5, 17, {""})
+ api.nvim_buf_set_text(0, 4, 15, 5, 17, { '' })
check_events {
- { "test1", "bytes", 1, 4, 4, 15, 79, 1, 17, 18, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 4, 4, 15, 79, 1, 17, 18, 0, 0, 0 },
}
- eq({ "original line 2", "original line 3", "original line 4",
- "original line 5", "original line 6" },
- meths.buf_get_lines(0, 0, -1, true))
+ eq({
+ 'original line 2',
+ 'original line 3',
+ 'original line 4',
+ 'original line 5',
+ 'original line 6',
+ }, api.nvim_buf_get_lines(0, 0, -1, true))
end)
it('checktime autoread', function()
- write_file("Xtest-reload", dedent [[
+ write_file(
+ 'Xtest-reload',
+ dedent [[
old line 1
- old line 2]])
+ old line 2]]
+ )
local atime = os.time() - 10
- luv.fs_utime("Xtest-reload", atime, atime)
- command "e Xtest-reload"
- command "set autoread"
+ vim.uv.fs_utime('Xtest-reload', atime, atime)
+ command 'e Xtest-reload'
+ command 'set autoread'
local check_events = setup_eventcheck(verify, nil)
- write_file("Xtest-reload", dedent [[
+ write_file(
+ 'Xtest-reload',
+ dedent [[
new line 1
new line 2
- new line 3]])
+ new line 3]]
+ )
- command "checktime"
+ command 'checktime'
check_events {
- { "test1", "reload", 1 };
+ { 'test1', 'reload', 1 },
}
feed 'ggJ'
check_events {
- { "test1", "bytes", 1, 5, 0, 10, 10, 1, 0, 1, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 5, 0, 10, 10, 1, 0, 1, 0, 1, 1 },
}
- eq({'new line 1 new line 2', 'new line 3'}, meths.buf_get_lines(0, 0, -1, true))
+ eq({ 'new line 1 new line 2', 'new line 3' }, api.nvim_buf_get_lines(0, 0, -1, true))
-- check we can undo and redo a reload event.
feed 'u'
check_events {
- { "test1", "bytes", 1, 8, 0, 10, 10, 0, 1, 1, 1, 0, 1 };
+ { 'test1', 'bytes', 1, 8, 0, 10, 10, 0, 1, 1, 1, 0, 1 },
}
feed 'u'
check_events {
- { "test1", "reload", 1 };
+ { 'test1', 'reload', 1 },
}
feed '<c-r>'
check_events {
- { "test1", "reload", 1 };
+ { 'test1', 'reload', 1 },
}
feed '<c-r>'
check_events {
- { "test1", "bytes", 1, 14, 0, 10, 10, 1, 0, 1, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 14, 0, 10, 10, 1, 0, 1, 0, 1, 1 },
}
end)
- it("tab with noexpandtab and softtabstop", function()
- command("set noet")
- command("set ts=4")
- command("set sw=2")
- command("set sts=4")
+ it('tab with noexpandtab and softtabstop', function()
+ command('set noet')
+ command('set ts=4')
+ command('set sw=2')
+ command('set sts=4')
- local check_events = setup_eventcheck(verify, {'asdfasdf'})
+ local check_events = setup_eventcheck(verify, { 'asdfasdf' })
- feed("gg0i<tab>")
+ feed('gg0i<tab>')
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
- { "test1", "bytes", 1, 4, 0, 1, 1, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 4, 0, 1, 1, 0, 0, 0, 0, 1, 1 },
}
- feed("<tab>")
+ feed('<tab>')
-- when spaces are merged into a tabstop
check_events {
- { "test1", "bytes", 1, 5, 0, 2, 2, 0, 0, 0, 0, 1, 1 },
- { "test1", "bytes", 1, 6, 0, 3, 3, 0, 0, 0, 0, 1, 1 },
- { "test1", "bytes", 1, 7, 0, 0, 0, 0, 4, 4, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 5, 0, 2, 2, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 6, 0, 3, 3, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 7, 0, 0, 0, 0, 4, 4, 0, 1, 1 },
}
-
- feed("<esc>u")
+ feed('<esc>u')
check_events {
- { "test1", "bytes", 1, 9, 0, 0, 0, 0, 1, 1, 0, 4, 4 },
- { "test1", "bytes", 1, 9, 0, 0, 0, 0, 4, 4, 0, 0, 0 }
+ { 'test1', 'bytes', 1, 9, 0, 0, 0, 0, 1, 1, 0, 4, 4 },
+ { 'test1', 'bytes', 1, 9, 0, 0, 0, 0, 4, 4, 0, 0, 0 },
}
-- in REPLACE mode
- feed("R<tab><tab>")
+ feed('R<tab><tab>')
check_events {
- { "test1", "bytes", 1, 10, 0, 0, 0, 0, 1, 1, 0, 1, 1 },
- { "test1", "bytes", 1, 11, 0, 1, 1, 0, 0, 0, 0, 1, 1 },
- { "test1", "bytes", 1, 12, 0, 2, 2, 0, 1, 1, 0, 1, 1 },
- { "test1", "bytes", 1, 13, 0, 3, 3, 0, 0, 0, 0, 1, 1 },
- { "test1", "bytes", 1, 14, 0, 0, 0, 0, 4, 4, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 10, 0, 0, 0, 0, 1, 1, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 11, 0, 1, 1, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 12, 0, 2, 2, 0, 1, 1, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 13, 0, 3, 3, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 14, 0, 0, 0, 0, 4, 4, 0, 1, 1 },
}
- feed("<esc>u")
+ feed('<esc>u')
check_events {
- { "test1", "bytes", 1, 16, 0, 0, 0, 0, 1, 1, 0, 4, 4 },
- { "test1", "bytes", 1, 16, 0, 2, 2, 0, 2, 2, 0, 1, 1 },
- { "test1", "bytes", 1, 16, 0, 0, 0, 0, 2, 2, 0, 1, 1 }
+ { 'test1', 'bytes', 1, 16, 0, 0, 0, 0, 1, 1, 0, 4, 4 },
+ { 'test1', 'bytes', 1, 16, 0, 2, 2, 0, 2, 2, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 16, 0, 0, 0, 0, 2, 2, 0, 1, 1 },
}
-- in VISUALREPLACE mode
- feed("gR<tab><tab>")
- check_events {
- { "test1", "bytes", 1, 17, 0, 0, 0, 0, 1, 1, 0, 1, 1 };
- { "test1", "bytes", 1, 18, 0, 1, 1, 0, 1, 1, 0, 1, 1 };
- { "test1", "bytes", 1, 19, 0, 2, 2, 0, 1, 1, 0, 1, 1 };
- { "test1", "bytes", 1, 20, 0, 3, 3, 0, 1, 1, 0, 1, 1 };
- { "test1", "bytes", 1, 21, 0, 3, 3, 0, 1, 1, 0, 0, 0 };
- { "test1", "bytes", 1, 22, 0, 3, 3, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 24, 0, 2, 2, 0, 1, 1, 0, 0, 0 };
- { "test1", "bytes", 1, 25, 0, 2, 2, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 27, 0, 1, 1, 0, 1, 1, 0, 0, 0 };
- { "test1", "bytes", 1, 28, 0, 1, 1, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 30, 0, 0, 0, 0, 1, 1, 0, 0, 0 };
- { "test1", "bytes", 1, 31, 0, 0, 0, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 33, 0, 0, 0, 0, 4, 4, 0, 1, 1 };
+ feed('gR<tab><tab>')
+ check_events {
+ { 'test1', 'bytes', 1, 17, 0, 0, 0, 0, 1, 1, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 18, 0, 1, 1, 0, 1, 1, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 19, 0, 2, 2, 0, 1, 1, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 20, 0, 3, 3, 0, 1, 1, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 21, 0, 3, 3, 0, 1, 1, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 22, 0, 3, 3, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 24, 0, 2, 2, 0, 1, 1, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 25, 0, 2, 2, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 27, 0, 1, 1, 0, 1, 1, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 28, 0, 1, 1, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 30, 0, 0, 0, 0, 1, 1, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 31, 0, 0, 0, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 33, 0, 0, 0, 0, 4, 4, 0, 1, 1 },
}
-- inserting tab after other tabs
- command("set sw=4")
- feed("<esc>0a<tab>")
+ command('set sw=4')
+ feed('<esc>0a<tab>')
check_events {
- { "test1", "bytes", 1, 34, 0, 1, 1, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 35, 0, 2, 2, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 36, 0, 3, 3, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 37, 0, 4, 4, 0, 0, 0, 0, 1, 1 };
- { "test1", "bytes", 1, 38, 0, 1, 1, 0, 4, 4, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 34, 0, 1, 1, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 35, 0, 2, 2, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 36, 0, 3, 3, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 37, 0, 4, 4, 0, 0, 0, 0, 1, 1 },
+ { 'test1', 'bytes', 1, 38, 0, 1, 1, 0, 4, 4, 0, 1, 1 },
}
end)
- it("retab", function()
- command("set noet")
- command("set ts=4")
+ it('retab', function()
+ command('set noet')
+ command('set ts=4')
- local check_events = setup_eventcheck(verify, {" asdf"})
- command("retab 8")
+ local check_events = setup_eventcheck(verify, { ' asdf' })
+ command('retab 8')
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 0, 7, 7, 0, 9, 9 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 7, 7, 0, 9, 9 },
}
end)
- it("sends events when undoing with undofile", function()
- write_file("Xtest-undofile", dedent([[
+ it('sends events when undoing with undofile', function()
+ write_file(
+ 'Xtest-undofile',
+ dedent([[
12345
hello world
- ]]))
+ ]])
+ )
- command("e! Xtest-undofile")
- command("set undodir=. | set undofile")
+ command('e! Xtest-undofile')
+ command('set undodir=. | set undofile')
- local ns = helpers.request('nvim_create_namespace', "ns1")
- meths.buf_set_extmark(0, ns, 0, 0, {})
+ local ns = helpers.request('nvim_create_namespace', 'ns1')
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {})
- eq({"12345", "hello world"}, meths.buf_get_lines(0, 0, -1, true))
+ eq({ '12345', 'hello world' }, api.nvim_buf_get_lines(0, 0, -1, true))
-- splice
- feed("gg0d2l")
+ feed('gg0d2l')
- eq({"345", "hello world"}, meths.buf_get_lines(0, 0, -1, true))
+ eq({ '345', 'hello world' }, api.nvim_buf_get_lines(0, 0, -1, true))
-- move
- command(".m+1")
+ command('.m+1')
- eq({"hello world", "345"}, meths.buf_get_lines(0, 0, -1, true))
+ eq({ 'hello world', '345' }, api.nvim_buf_get_lines(0, 0, -1, true))
-- reload undofile and undo changes
- command("w")
- command("set noundofile")
- command("bw!")
- command("e! Xtest-undofile")
+ command('w')
+ command('set noundofile')
+ command('bw!')
+ command('e! Xtest-undofile')
- command("set undofile")
+ command('set undofile')
local check_events = setup_eventcheck(verify, nil)
- feed("u")
- eq({"345", "hello world"}, meths.buf_get_lines(0, 0, -1, true))
+ feed('u')
+ eq({ '345', 'hello world' }, api.nvim_buf_get_lines(0, 0, -1, true))
check_events {
- { "test1", "bytes", 2, 6, 1, 0, 12, 1, 0, 4, 0, 0, 0 },
- { "test1", "bytes", 2, 6, 0, 0, 0, 0, 0, 0, 1, 0, 4 }
+ { 'test1', 'bytes', 2, 6, 1, 0, 12, 1, 0, 4, 0, 0, 0 },
+ { 'test1', 'bytes', 2, 6, 0, 0, 0, 0, 0, 0, 1, 0, 4 },
}
- feed("u")
- eq({"12345", "hello world"}, meths.buf_get_lines(0, 0, -1, true))
+ feed('u')
+ eq({ '12345', 'hello world' }, api.nvim_buf_get_lines(0, 0, -1, true))
check_events {
- { "test1", "bytes", 2, 8, 0, 0, 0, 0, 0, 0, 0, 2, 2 }
+ { 'test1', 'bytes', 2, 8, 0, 0, 0, 0, 0, 0, 0, 2, 2 },
}
- command("bw!")
+ command('bw!')
end)
- it("blockwise paste with uneven line lengths", function()
- local check_events = setup_eventcheck(verify, {'aaaa', 'aaa', 'aaa'})
+ it('blockwise paste with uneven line lengths', function()
+ local check_events = setup_eventcheck(verify, { 'aaaa', 'aaa', 'aaa' })
- -- eq({}, meths.buf_get_lines(0, 0, -1, true))
- feed("gg0<c-v>jj$d")
+ -- eq({}, api.nvim_buf_get_lines(0, 0, -1, true))
+ feed('gg0<c-v>jj$d')
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 0, 4, 4, 0, 0, 0 },
- { "test1", "bytes", 1, 3, 1, 0, 1, 0, 3, 3, 0, 0, 0 },
- { "test1", "bytes", 1, 3, 2, 0, 2, 0, 3, 3, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 4, 4, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 3, 1, 0, 1, 0, 3, 3, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 3, 2, 0, 2, 0, 3, 3, 0, 0, 0 },
}
- feed("p")
+ feed('p')
check_events {
- { "test1", "bytes", 1, 4, 0, 0, 0, 0, 0, 0, 0, 4, 4 },
- { "test1", "bytes", 1, 4, 1, 0, 5, 0, 0, 0, 0, 3, 3 },
- { "test1", "bytes", 1, 4, 2, 0, 9, 0, 0, 0, 0, 3, 3 },
+ { 'test1', 'bytes', 1, 4, 0, 0, 0, 0, 0, 0, 0, 4, 4 },
+ { 'test1', 'bytes', 1, 4, 1, 0, 5, 0, 0, 0, 0, 3, 3 },
+ { 'test1', 'bytes', 1, 4, 2, 0, 9, 0, 0, 0, 0, 3, 3 },
}
-
end)
- it(":luado", function()
- local check_events = setup_eventcheck(verify, {"abc", "12345"})
+ it(':luado', function()
+ local check_events = setup_eventcheck(verify, { 'abc', '12345' })
command(".luado return 'a'")
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 0, 3, 3, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 3, 3, 0, 1, 1 },
}
- command("luado return 10")
+ command('luado return 10')
check_events {
- { "test1", "bytes", 1, 4, 0, 0, 0, 0, 1, 1, 0, 2, 2 };
- { "test1", "bytes", 1, 5, 1, 0, 3, 0, 5, 5, 0, 2, 2 };
+ { 'test1', 'bytes', 1, 4, 0, 0, 0, 0, 1, 1, 0, 2, 2 },
+ { 'test1', 'bytes', 1, 5, 1, 0, 3, 0, 5, 5, 0, 2, 2 },
}
-
end)
- it("flushes deleted bytes on move", function()
- local check_events = setup_eventcheck(verify, {"AAA", "BBB", "CCC", "DDD"})
+ it('flushes deleted bytes on move', function()
+ local check_events = setup_eventcheck(verify, { 'AAA', 'BBB', 'CCC', 'DDD' })
- feed(":.move+1<cr>")
+ feed(':.move+1<cr>')
check_events {
- { "test1", "bytes", 1, 5, 0, 0, 0, 1, 0, 4, 0, 0, 0 };
- { "test1", "bytes", 1, 5, 1, 0, 4, 0, 0, 0, 1, 0, 4 };
+ { 'test1', 'bytes', 1, 5, 0, 0, 0, 1, 0, 4, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 5, 1, 0, 4, 0, 0, 0, 1, 0, 4 },
}
- feed("jd2j")
+ feed('jd2j')
check_events {
- { "test1", "bytes", 1, 6, 2, 0, 8, 2, 0, 8, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 6, 2, 0, 8, 2, 0, 8, 0, 0, 0 },
}
end)
- it("virtual edit", function ()
- local check_events = setup_eventcheck(verify, { "", " " })
+ it('virtual edit', function()
+ local check_events = setup_eventcheck(verify, { '', ' ' })
- meths.set_option_value('virtualedit', "all", {})
+ api.nvim_set_option_value('virtualedit', 'all', {})
feed [[<Right><Right>iab<ESC>]]
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 0, 0, 0, 0, 2, 2 };
- { "test1", "bytes", 1, 4, 0, 2, 2, 0, 0, 0, 0, 2, 2 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 0, 0, 0, 2, 2 },
+ { 'test1', 'bytes', 1, 4, 0, 2, 2, 0, 0, 0, 0, 2, 2 },
}
feed [[j<Right><Right>iab<ESC>]]
check_events {
- { "test1", "bytes", 1, 5, 1, 0, 5, 0, 1, 1, 0, 8, 8 };
- { "test1", "bytes", 1, 6, 1, 5, 10, 0, 0, 0, 0, 2, 2 };
+ { 'test1', 'bytes', 1, 5, 1, 0, 5, 0, 1, 1, 0, 8, 8 },
+ { 'test1', 'bytes', 1, 6, 1, 5, 10, 0, 0, 0, 0, 2, 2 },
}
end)
- it("block visual paste", function()
- local check_events = setup_eventcheck(verify, {"AAA",
- "BBB",
- "CCC",
- "DDD",
- "EEE",
- "FFF"})
- funcs.setreg("a", "___")
+ it('block visual paste', function()
+ local check_events = setup_eventcheck(verify, { 'AAA', 'BBB', 'CCC', 'DDD', 'EEE', 'FFF' })
+ fn.setreg('a', '___')
feed([[gg0l<c-v>3jl"ap]])
check_events {
- { "test1", "bytes", 1, 3, 0, 1, 1, 0, 2, 2, 0, 0, 0 };
- { "test1", "bytes", 1, 3, 1, 1, 3, 0, 2, 2, 0, 0, 0 };
- { "test1", "bytes", 1, 3, 2, 1, 5, 0, 2, 2, 0, 0, 0 };
- { "test1", "bytes", 1, 3, 3, 1, 7, 0, 2, 2, 0, 0, 0 };
- { "test1", "bytes", 1, 5, 0, 1, 1, 0, 0, 0, 0, 3, 3 };
- { "test1", "bytes", 1, 6, 1, 1, 6, 0, 0, 0, 0, 3, 3 };
- { "test1", "bytes", 1, 7, 2, 1, 11, 0, 0, 0, 0, 3, 3 };
- { "test1", "bytes", 1, 8, 3, 1, 16, 0, 0, 0, 0, 3, 3 };
+ { 'test1', 'bytes', 1, 3, 0, 1, 1, 0, 2, 2, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 3, 1, 1, 3, 0, 2, 2, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 3, 2, 1, 5, 0, 2, 2, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 3, 3, 1, 7, 0, 2, 2, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 5, 0, 1, 1, 0, 0, 0, 0, 3, 3 },
+ { 'test1', 'bytes', 1, 6, 1, 1, 6, 0, 0, 0, 0, 3, 3 },
+ { 'test1', 'bytes', 1, 7, 2, 1, 11, 0, 0, 0, 0, 3, 3 },
+ { 'test1', 'bytes', 1, 8, 3, 1, 16, 0, 0, 0, 0, 3, 3 },
}
end)
- it("visual paste", function()
- local check_events= setup_eventcheck(verify, { "aaa {", "b", "}" })
+ it('visual paste', function()
+ local check_events = setup_eventcheck(verify, { 'aaa {', 'b', '}' })
-- Setting up
- feed[[jdd]]
+ feed [[jdd]]
check_events {
- { "test1", "bytes", 1, 3, 1, 0, 6, 1, 0, 2, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 3, 1, 0, 6, 1, 0, 2, 0, 0, 0 },
}
-- Actually testing
- feed[[v%p]]
+ feed [[v%p]]
+ check_events {
+ { 'test1', 'bytes', 1, 8, 0, 4, 4, 1, 1, 3, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 8, 0, 4, 4, 0, 0, 0, 2, 0, 3 },
+ }
+ end)
+
+ it('visual paste 2: splitting an empty line', function()
+ local check_events = setup_eventcheck(verify, { 'abc', '{', 'def', '}' })
+ feed('ggyyjjvi{p')
check_events {
- { "test1", "bytes", 1, 8, 0, 4, 4, 1, 1, 3, 0, 0, 0 };
- { "test1", "bytes", 1, 8, 0, 4, 4, 0, 0, 0, 2, 0, 3 };
+ { 'test1', 'bytes', 1, 6, 2, 0, 6, 1, 0, 4, 0, 0, 0 },
+ { 'test1', 'bytes', 1, 6, 2, 0, 6, 0, 0, 0, 2, 0, 5 },
}
end)
- it("nvim_buf_set_lines", function()
- local check_events = setup_eventcheck(verify, {"AAA", "BBB"})
+ it('nvim_buf_set_lines', function()
+ local check_events = setup_eventcheck(verify, { 'AAA', 'BBB' })
-- delete
- meths.buf_set_lines(0, 0, 1, true, {})
+ api.nvim_buf_set_lines(0, 0, 1, true, {})
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 1, 0, 4, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 1, 0, 4, 0, 0, 0 },
}
-- add
- meths.buf_set_lines(0, 0, 0, true, {'asdf'})
+ api.nvim_buf_set_lines(0, 0, 0, true, { 'asdf' })
check_events {
- { "test1", "bytes", 1, 4, 0, 0, 0, 0, 0, 0, 1, 0, 5 };
+ { 'test1', 'bytes', 1, 4, 0, 0, 0, 0, 0, 0, 1, 0, 5 },
}
-- replace
- meths.buf_set_lines(0, 0, 1, true, {'asdf', 'fdsa'})
+ api.nvim_buf_set_lines(0, 0, 1, true, { 'asdf', 'fdsa' })
check_events {
- { "test1", "bytes", 1, 5, 0, 0, 0, 1, 0, 5, 2, 0, 10 };
+ { 'test1', 'bytes', 1, 5, 0, 0, 0, 1, 0, 5, 2, 0, 10 },
}
end)
- it("flushes delbytes on substitute", function()
- local check_events = setup_eventcheck(verify, {"AAA", "BBB", "CCC"})
+ it('flushes delbytes on substitute', function()
+ local check_events = setup_eventcheck(verify, { 'AAA', 'BBB', 'CCC' })
- feed("gg0")
- command("s/AAA/GGG/")
+ feed('gg0')
+ command('s/AAA/GGG/')
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 0, 3, 3, 0, 3, 3 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 3, 3, 0, 3, 3 },
}
-- check that byte updates for :delete (which uses curbuf->deleted_bytes2)
-- are correct
- command("delete")
+ command('delete')
check_events {
- { "test1", "bytes", 1, 4, 0, 0, 0, 1, 0, 4, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 4, 0, 0, 0, 1, 0, 4, 0, 0, 0 },
}
end)
- it("flushes delbytes on join", function()
- local check_events = setup_eventcheck(verify, {"AAA", "BBB", "CCC"})
+ it('flushes delbytes on join', function()
+ local check_events = setup_eventcheck(verify, { 'AAA', 'BBB', 'CCC' })
- feed("gg0J")
+ feed('gg0J')
check_events {
- { "test1", "bytes", 1, 3, 0, 3, 3, 1, 0, 1, 0, 1, 1 };
+ { 'test1', 'bytes', 1, 3, 0, 3, 3, 1, 0, 1, 0, 1, 1 },
}
- command("delete")
+ command('delete')
check_events {
- { "test1", "bytes", 1, 5, 0, 0, 0, 1, 0, 8, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 5, 0, 0, 0, 1, 0, 8, 0, 0, 0 },
}
end)
- it("sends updates on U", function()
- feed("ggiAAA<cr>BBB")
- feed("<esc>gg$a CCC")
+ it('sends updates on U', function()
+ feed('ggiAAA<cr>BBB')
+ feed('<esc>gg$a CCC')
local check_events = setup_eventcheck(verify, nil)
- feed("ggU")
+ feed('ggU')
check_events {
- { "test1", "bytes", 1, 6, 0, 7, 7, 0, 0, 0, 0, 3, 3 };
+ { 'test1', 'bytes', 1, 6, 0, 7, 7, 0, 0, 0, 0, 3, 3 },
}
end)
- it("delete in completely empty buffer", function()
+ it('delete in completely empty buffer', function()
local check_events = setup_eventcheck(verify, nil)
- command "delete"
- check_events { }
+ command 'delete'
+ check_events {}
end)
- it("delete the only line of a buffer", function()
- local check_events = setup_eventcheck(verify, {"AAA"})
+ it('delete the only line of a buffer', function()
+ local check_events = setup_eventcheck(verify, { 'AAA' })
- command "delete"
+ command 'delete'
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 1, 0, 4, 1, 0, 1 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 1, 0, 4, 1, 0, 1 },
}
end)
- it("delete the last line of a buffer with two lines", function()
- local check_events = setup_eventcheck(verify, {"AAA", "BBB"})
+ it('delete the last line of a buffer with two lines', function()
+ local check_events = setup_eventcheck(verify, { 'AAA', 'BBB' })
- command "2delete"
+ command '2delete'
check_events {
- { "test1", "bytes", 1, 3, 1, 0, 4, 1, 0, 4, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 3, 1, 0, 4, 1, 0, 4, 0, 0, 0 },
}
end)
- it(":sort lines", function()
- local check_events = setup_eventcheck(verify, {"CCC", "BBB", "AAA"})
+ it(':sort lines', function()
+ local check_events = setup_eventcheck(verify, { 'CCC', 'BBB', 'AAA' })
- command "%sort"
+ command '%sort'
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 3, 0, 12, 3, 0, 12 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 3, 0, 12, 3, 0, 12 },
}
end)
- it("handles already sorted lines", function()
- local check_events = setup_eventcheck(verify, {"AAA", "BBB", "CCC"})
+ it('handles already sorted lines', function()
+ local check_events = setup_eventcheck(verify, { 'AAA', 'BBB', 'CCC' })
- command "%sort"
- check_events { }
+ command '%sort'
+ check_events {}
end)
- it("works with accepting spell suggestions", function()
- local check_events = setup_eventcheck(verify, {"hallo world", "hallo world"})
+ it('works with accepting spell suggestions', function()
+ local check_events = setup_eventcheck(verify, { 'hallo world', 'hallo world' })
- feed("gg0z=4<cr><cr>") -- accepts 'Hello'
+ feed('gg0z=4<cr><cr>') -- accepts 'Hello'
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 0, 2, 2, 0, 2, 2 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 0, 2, 2, 0, 2, 2 },
}
- command("spellrepall") -- replaces whole words
+ command('spellrepall') -- replaces whole words
check_events {
- { "test1", "bytes", 1, 4, 1, 0, 12, 0, 5, 5, 0, 5, 5 };
+ { 'test1', 'bytes', 1, 4, 1, 0, 12, 0, 5, 5, 0, 5, 5 },
}
end)
it('works with :diffput and :diffget', function()
- local check_events = setup_eventcheck(verify, {"AAA"})
+ local check_events = setup_eventcheck(verify, { 'AAA' })
command('diffthis')
command('new')
command('diffthis')
- meths.buf_set_lines(0, 0, -1, true, {"AAA", "BBB"})
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'AAA', 'BBB' })
feed('G')
command('diffput')
check_events {
- { "test1", "bytes", 1, 3, 1, 0, 4, 0, 0, 0, 1, 0, 4 };
+ { 'test1', 'bytes', 1, 3, 1, 0, 4, 0, 0, 0, 1, 0, 4 },
}
- meths.buf_set_lines(0, 0, -1, true, {"AAA", "CCC"})
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'AAA', 'CCC' })
feed('<C-w>pG')
command('diffget')
check_events {
- { "test1", "bytes", 1, 4, 1, 0, 4, 1, 0, 4, 1, 0, 4 };
+ { 'test1', 'bytes', 1, 4, 1, 0, 4, 1, 0, 4, 1, 0, 4 },
}
end)
local function test_lockmarks(mode)
- local description = (mode ~= "") and mode or "(baseline)"
- it("test_lockmarks " .. description .. " %delete _", function()
- local check_events = setup_eventcheck(verify, {"AAA", "BBB", "CCC"})
+ local description = (mode ~= '') and mode or '(baseline)'
+ it('test_lockmarks ' .. description .. ' %delete _', function()
+ local check_events = setup_eventcheck(verify, { 'AAA', 'BBB', 'CCC' })
- command(mode .. " %delete _")
+ command(mode .. ' %delete _')
check_events {
- { "test1", "bytes", 1, 3, 0, 0, 0, 3, 0, 12, 1, 0, 1 };
+ { 'test1', 'bytes', 1, 3, 0, 0, 0, 3, 0, 12, 1, 0, 1 },
}
end)
- it("test_lockmarks " .. description .. " append()", function()
+ it('test_lockmarks ' .. description .. ' append()', function()
local check_events = setup_eventcheck(verify)
command(mode .. " call append(0, 'CCC')")
check_events {
- { "test1", "bytes", 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 4 };
+ { 'test1', 'bytes', 1, 2, 0, 0, 0, 0, 0, 0, 1, 0, 4 },
}
command(mode .. " call append(1, 'BBBB')")
check_events {
- { "test1", "bytes", 1, 3, 1, 0, 4, 0, 0, 0, 1, 0, 5 };
+ { 'test1', 'bytes', 1, 3, 1, 0, 4, 0, 0, 0, 1, 0, 5 },
}
command(mode .. " call append(2, '')")
check_events {
- { "test1", "bytes", 1, 4, 2, 0, 9, 0, 0, 0, 1, 0, 1 };
+ { 'test1', 'bytes', 1, 4, 2, 0, 9, 0, 0, 0, 1, 0, 1 },
}
- command(mode .. " $delete _")
+ command(mode .. ' $delete _')
check_events {
- { "test1", "bytes", 1, 5, 3, 0, 10, 1, 0, 1, 0, 0, 0 };
+ { 'test1', 'bytes', 1, 5, 3, 0, 10, 1, 0, 1, 0, 0, 0 },
}
- eq("CCC|BBBB|", table.concat(meths.buf_get_lines(0, 0, -1, true), "|"))
+ eq('CCC|BBBB|', table.concat(api.nvim_buf_get_lines(0, 0, -1, true), '|'))
end)
end
-- check that behavior is identical with and without "lockmarks"
- test_lockmarks ""
- test_lockmarks "lockmarks"
+ test_lockmarks ''
+ test_lockmarks 'lockmarks'
teardown(function()
- os.remove "Xtest-reload"
- os.remove "Xtest-undofile"
- os.remove ".Xtest-undofile.un~"
+ os.remove 'Xtest-reload'
+ os.remove 'Xtest-undofile'
+ os.remove '.Xtest-undofile.un~'
end)
end
@@ -1253,4 +1282,3 @@ describe('lua: nvim_buf_attach on_bytes', function()
do_both(false)
end)
end)
-
diff --git a/test/functional/lua/command_line_completion_spec.lua b/test/functional/lua/command_line_completion_spec.lua
index 177e077f4a..b88a38082f 100644
--- a/test/functional/lua/command_line_completion_spec.lua
+++ b/test/functional/lua/command_line_completion_spec.lua
@@ -5,34 +5,33 @@ local eq = helpers.eq
local exec_lua = helpers.exec_lua
local get_completions = function(input, env)
- return exec_lua("return {vim._expand_pat(...)}", input, env)
+ return exec_lua('return {vim._expand_pat(...)}', input, env)
end
local get_compl_parts = function(parts)
- return exec_lua("return {vim._expand_pat_get_parts(...)}", parts)
+ return exec_lua('return {vim._expand_pat_get_parts(...)}', parts)
end
before_each(clear)
describe('nlua_expand_pat', function()
it('should complete exact matches', function()
- eq({{'exact'}, 0}, get_completions('exact', { exact = true }))
+ eq({ { 'exact' }, 0 }, get_completions('exact', { exact = true }))
end)
it('should return empty table when nothing matches', function()
- eq({{}, 0}, get_completions('foo', { bar = true }))
+ eq({ {}, 0 }, get_completions('foo', { bar = true }))
end)
it('should return nice completions with function call prefix', function()
- eq({{'FOO'}, 6}, get_completions('print(F', { FOO = true, bawr = true }))
+ eq({ { 'FOO' }, 6 }, get_completions('print(F', { FOO = true, bawr = true }))
end)
it('should return keys for nested dictionaries', function()
eq(
- {{
+ { {
'nvim_buf_set_lines',
- }, 8
- },
+ }, 8 },
get_completions('vim.api.nvim_buf_', {
vim = {
api = {
@@ -40,34 +39,32 @@ describe('nlua_expand_pat', function()
nvim_win_doesnt_match = true,
},
other_key = true,
- }
+ },
})
)
end)
it('it should work with colons', function()
eq(
- {{
+ { {
'bawr',
'baz',
- }, 8
- },
+ }, 8 },
get_completions('MyClass:b', {
MyClass = {
baz = true,
bawr = true,
foo = false,
- }
+ },
})
)
end)
it('should return keys for string reffed dictionaries', function()
eq(
- {{
+ { {
'nvim_buf_set_lines',
- }, 11
- },
+ }, 11 },
get_completions('vim["api"].nvim_buf_', {
vim = {
api = {
@@ -75,17 +72,16 @@ describe('nlua_expand_pat', function()
nvim_win_doesnt_match = true,
},
other_key = true,
- }
+ },
})
)
end)
it('should return keys for string reffed dictionaries', function()
eq(
- {{
+ { {
'nvim_buf_set_lines',
- }, 21
- },
+ }, 21 },
get_completions('vim["nested"]["api"].nvim_buf_', {
vim = {
nested = {
@@ -95,80 +91,76 @@ describe('nlua_expand_pat', function()
},
},
other_key = true,
- }
+ },
})
)
end)
it('should work with lazy submodules of "vim" global', function()
- eq({{ 'inspect', 'inspect_pos' }, 4 },
- get_completions('vim.inspec'))
+ eq({ { 'inspect', 'inspect_pos' }, 4 }, get_completions('vim.inspec'))
- eq({{ 'treesitter' }, 4 },
- get_completions('vim.treesi'))
+ eq({ { 'treesitter' }, 4 }, get_completions('vim.treesi'))
- eq({{ 'set' }, 11 },
- get_completions('vim.keymap.se'))
+ eq({ { 'set' }, 11 }, get_completions('vim.keymap.se'))
end)
it('should be able to interpolate globals', function()
eq(
- {{
+ { {
'nvim_buf_set_lines',
- }, 12
- },
+ }, 12 },
get_completions('vim[MY_VAR].nvim_buf_', {
- MY_VAR = "api",
+ MY_VAR = 'api',
vim = {
api = {
nvim_buf_set_lines = true,
nvim_win_doesnt_match = true,
},
other_key = true,
- }
+ },
})
)
end)
it('should return everything if the input is of length 0', function()
- eq({{"other", "vim"}, 0}, get_completions('', { vim = true, other = true }))
+ eq({ { 'other', 'vim' }, 0 }, get_completions('', { vim = true, other = true }))
end)
describe('get_parts', function()
it('should return an empty list for no separators', function()
- eq({{}, 1}, get_compl_parts("vim"))
+ eq({ {}, 1 }, get_compl_parts('vim'))
end)
it('just the first item before a period', function()
- eq({{"vim"}, 5}, get_compl_parts("vim.ap"))
+ eq({ { 'vim' }, 5 }, get_compl_parts('vim.ap'))
end)
it('should return multiple parts just for period', function()
- eq({{"vim", "api"}, 9}, get_compl_parts("vim.api.nvim_buf"))
+ eq({ { 'vim', 'api' }, 9 }, get_compl_parts('vim.api.nvim_buf'))
end)
it('should be OK with colons', function()
- eq({{"vim", "api"}, 9}, get_compl_parts("vim:api.nvim_buf"))
+ eq({ { 'vim', 'api' }, 9 }, get_compl_parts('vim:api.nvim_buf'))
end)
it('should work for just one string ref', function()
- eq({{"vim", "api"}, 12}, get_compl_parts("vim['api'].nvim_buf"))
+ eq({ { 'vim', 'api' }, 12 }, get_compl_parts("vim['api'].nvim_buf"))
end)
it('should work for just one string ref, with double quote', function()
- eq({{"vim", "api"}, 12}, get_compl_parts('vim["api"].nvim_buf'))
+ eq({ { 'vim', 'api' }, 12 }, get_compl_parts('vim["api"].nvim_buf'))
end)
it('should allows back-to-back string ref', function()
- eq({{"vim", "nested", "api"}, 22}, get_compl_parts('vim["nested"]["api"].nvim_buf'))
+ eq({ { 'vim', 'nested', 'api' }, 22 }, get_compl_parts('vim["nested"]["api"].nvim_buf'))
end)
it('should allows back-to-back string ref with spaces before and after', function()
- eq({{"vim", "nested", "api"}, 25}, get_compl_parts('vim[ "nested" ]["api"].nvim_buf'))
+ eq({ { 'vim', 'nested', 'api' }, 25 }, get_compl_parts('vim[ "nested" ]["api"].nvim_buf'))
end)
it('should allow VAR style loolup', function()
- eq({{"vim", {"NESTED"}, "api"}, 20}, get_compl_parts('vim[NESTED]["api"].nvim_buf'))
+ eq({ { 'vim', { 'NESTED' }, 'api' }, 20 }, get_compl_parts('vim[NESTED]["api"].nvim_buf'))
end)
end)
end)
diff --git a/test/functional/lua/commands_spec.lua b/test/functional/lua/commands_spec.lua
index fca619348d..b8d0638ce5 100644
--- a/test/functional/lua/commands_spec.lua
+++ b/test/functional/lua/commands_spec.lua
@@ -3,106 +3,124 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local eq = helpers.eq
-local NIL = helpers.NIL
+local NIL = vim.NIL
local eval = helpers.eval
local feed = helpers.feed
local clear = helpers.clear
local matches = helpers.matches
-local meths = helpers.meths
+local api = helpers.api
local exec_lua = helpers.exec_lua
local exec_capture = helpers.exec_capture
-local funcs = helpers.funcs
+local fn = helpers.fn
local source = helpers.source
local dedent = helpers.dedent
local command = helpers.command
local exc_exec = helpers.exc_exec
local pcall_err = helpers.pcall_err
local write_file = helpers.write_file
-local curbufmeths = helpers.curbufmeths
local remove_trace = helpers.remove_trace
before_each(clear)
-describe(':lua command', function()
+describe(':lua', function()
it('works', function()
- eq('', exec_capture(
- 'lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"TEST"})'))
- eq({'', 'TEST'}, curbufmeths.get_lines(0, 100, false))
+ eq('', exec_capture('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"TEST"})'))
+ eq({ '', 'TEST' }, api.nvim_buf_get_lines(0, 0, 100, false))
source([[
lua << EOF
vim.api.nvim_buf_set_lines(1, 1, 2, false, {"TSET"})
EOF]])
- eq({'', 'TSET'}, curbufmeths.get_lines(0, 100, false))
+ eq({ '', 'TSET' }, api.nvim_buf_get_lines(0, 0, 100, false))
source([[
lua << EOF
vim.api.nvim_buf_set_lines(1, 1, 2, false, {"SETT"})]])
- eq({'', 'SETT'}, curbufmeths.get_lines(0, 100, false))
+ eq({ '', 'SETT' }, api.nvim_buf_get_lines(0, 0, 100, false))
source([[
lua << EOF
vim.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"})
vim.api.nvim_buf_set_lines(1, 2, 3, false, {"TTSE"})
vim.api.nvim_buf_set_lines(1, 3, 4, false, {"STTE"})
EOF]])
- eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false))
- matches('.*Vim%(lua%):E15: Invalid expression: .*', pcall_err(source, [[
+ eq({ '', 'ETTS', 'TTSE', 'STTE' }, api.nvim_buf_get_lines(0, 0, 100, false))
+ matches(
+ '.*Vim%(lua%):E15: Invalid expression: .*',
+ pcall_err(
+ source,
+ [[
lua << eval EOF
{}
EOF
- ]]))
+ ]]
+ )
+ )
end)
+
it('throws catchable errors', function()
- eq([[Vim(lua):E5107: Error loading lua [string ":lua"]:0: unexpected symbol near ')']],
- pcall_err(command, 'lua ()'))
- eq([[Vim(lua):E5108: Error executing lua [string ":lua"]:1: TEST]],
- remove_trace(exc_exec('lua error("TEST")')))
- eq([[Vim(lua):E5108: Error executing lua [string ":lua"]:1: Invalid buffer id: -10]],
- remove_trace(exc_exec('lua vim.api.nvim_buf_set_lines(-10, 1, 1, false, {"TEST"})')))
- eq({''}, curbufmeths.get_lines(0, 100, false))
+ eq('Vim(lua):E471: Argument required', pcall_err(command, 'lua'))
+ eq(
+ [[Vim(lua):E5107: Error loading lua [string ":lua"]:0: unexpected symbol near ')']],
+ pcall_err(command, 'lua ()')
+ )
+ eq(
+ [[Vim(lua):E5108: Error executing lua [string ":lua"]:1: TEST]],
+ remove_trace(exc_exec('lua error("TEST")'))
+ )
+ eq(
+ [[Vim(lua):E5108: Error executing lua [string ":lua"]:1: Invalid buffer id: -10]],
+ remove_trace(exc_exec('lua vim.api.nvim_buf_set_lines(-10, 1, 1, false, {"TEST"})'))
+ )
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, 100, false))
end)
+
it('works with NULL errors', function()
- eq([=[Vim(lua):E5108: Error executing lua [NULL]]=],
- exc_exec('lua error(nil)'))
+ eq([=[Vim(lua):E5108: Error executing lua [NULL]]=], exc_exec('lua error(nil)'))
end)
+
it('accepts embedded NLs without heredoc', function()
-- Such code is usually used for `:execute 'lua' {generated_string}`:
-- heredocs do not work in this case.
- meths.command([[
+ command([[
lua
vim.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"})
vim.api.nvim_buf_set_lines(1, 2, 3, false, {"TTSE"})
vim.api.nvim_buf_set_lines(1, 3, 4, false, {"STTE"})
]])
- eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false))
+ eq({ '', 'ETTS', 'TTSE', 'STTE' }, api.nvim_buf_get_lines(0, 0, 100, false))
end)
+
it('preserves global and not preserves local variables', function()
eq('', exec_capture('lua gvar = 42'))
eq('', exec_capture('lua local lvar = 100500'))
- eq(NIL, funcs.luaeval('lvar'))
- eq(42, funcs.luaeval('gvar'))
+ eq(NIL, fn.luaeval('lvar'))
+ eq(42, fn.luaeval('gvar'))
end)
+
it('works with long strings', function()
local s = ('x'):rep(100500)
- eq('Vim(lua):E5107: Error loading lua [string ":lua"]:0: unfinished string near \'<eof>\'',
- pcall_err(command, ('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s})'):format(s)))
- eq({''}, curbufmeths.get_lines(0, -1, false))
+ eq(
+ 'Vim(lua):E5107: Error loading lua [string ":lua"]:0: unfinished string near \'<eof>\'',
+ pcall_err(command, ('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s})'):format(s))
+ )
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, false))
eq('', exec_capture(('lua vim.api.nvim_buf_set_lines(1, 1, 2, false, {"%s"})'):format(s)))
- eq({'', s}, curbufmeths.get_lines(0, -1, false))
+ eq({ '', s }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
it('can show multiline error messages', function()
- local screen = Screen.new(40,10)
+ local screen = Screen.new(40, 10)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {bold = true, reverse = true},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, reverse = true },
+ [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
})
feed(':lua error("fail\\nmuch error\\nsuch details")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2: }|
{3:E5108: Error executing lua [string ":lua}|
{3:"]:1: fail} |
@@ -113,29 +131,30 @@ describe(':lua command', function()
{3: [string ":lua"]:1: in main chunk}|
|
{4:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
|
- ]]}
- eq('E5108: Error executing lua [string ":lua"]:1: fail\nmuch error\nsuch details', remove_trace(eval('v:errmsg')))
+ ]],
+ }
+ eq(
+ 'E5108: Error executing lua [string ":lua"]:1: fail\nmuch error\nsuch details',
+ remove_trace(eval('v:errmsg'))
+ )
- local status, err = pcall(command,'lua error("some error\\nin a\\nAPI command")')
- local expected = 'Vim(lua):E5108: Error executing lua [string ":lua"]:1: some error\nin a\nAPI command'
+ local status, err = pcall(command, 'lua error("some error\\nin a\\nAPI command")')
+ local expected =
+ 'Vim(lua):E5108: Error executing lua [string ":lua"]:1: some error\nin a\nAPI command'
eq(false, status)
eq(expected, string.sub(remove_trace(err), -string.len(expected)))
feed(':messages<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2: }|
{3:E5108: Error executing lua [string ":lua}|
{3:"]:1: fail} |
@@ -146,17 +165,18 @@ describe(':lua command', function()
{3: [string ":lua"]:1: in main chunk}|
|
{4:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
it('prints result of =expr', function()
- exec_lua("x = 5")
- eq("5", exec_capture(':lua =x'))
- eq("5", exec_capture('=x'))
+ exec_lua('x = 5')
+ eq('5', exec_capture(':lua =x'))
+ eq('5', exec_capture('=x'))
exec_lua("function x() return 'hello' end")
eq('hello', exec_capture(':lua = x()'))
- exec_lua("x = {a = 1, b = 2}")
- eq("{\n a = 1,\n b = 2\n}", exec_capture(':lua =x'))
+ exec_lua('x = {a = 1, b = 2}')
+ eq('{\n a = 1,\n b = 2\n}', exec_capture(':lua =x'))
exec_lua([[function x(success)
if success then
return true, "Return value"
@@ -164,69 +184,127 @@ describe(':lua command', function()
return false, nil, "Error message"
end
end]])
- eq(dedent[[
+ eq(
+ dedent [[
true
Return value]],
- exec_capture(':lua =x(true)'))
- eq(dedent[[
+ exec_capture(':lua =x(true)')
+ )
+ eq(
+ dedent [[
false
nil
Error message]],
- exec_capture('=x(false)'))
+ exec_capture('=x(false)')
+ )
+ end)
+
+ it('with range', function()
+ local screen = Screen.new(40, 10)
+ screen:attach()
+ api.nvim_buf_set_lines(0, 0, 0, 0, { 'nonsense', 'function x() print "hello" end', 'x()' })
+
+ -- ":{range}lua" fails on invalid Lua code.
+ eq(
+ [[:{range}lua: Vim(lua):E5107: Error loading lua [string ":{range}lua"]:0: '=' expected near '<eof>']],
+ pcall_err(command, '1lua')
+ )
+
+ -- ":{range}lua" executes valid Lua code.
+ feed(':2,3lua<CR>')
+ screen:expect {
+ grid = [[
+ nonsense |
+ function x() print "hello" end |
+ x() |
+ ^ |
+ {1:~ }|*5
+ hello |
+ ]],
+ attr_ids = {
+ [1] = { foreground = Screen.colors.Blue, bold = true },
+ },
+ }
+
+ -- ":{range}lua {code}" executes {code}, ignoring {range}
+ eq('', exec_capture('1lua gvar = 42'))
+ eq(42, fn.luaeval('gvar'))
end)
end)
describe(':luado command', function()
it('works', function()
- curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
+ api.nvim_buf_set_lines(0, 0, 1, false, { 'ABC', 'def', 'gHi' })
eq('', exec_capture('luado lines = (lines or {}) lines[#lines + 1] = {linenr, line}'))
- eq({'ABC', 'def', 'gHi'}, curbufmeths.get_lines(0, -1, false))
- eq({{1, 'ABC'}, {2, 'def'}, {3, 'gHi'}}, funcs.luaeval('lines'))
+ eq({ 'ABC', 'def', 'gHi' }, api.nvim_buf_get_lines(0, 0, -1, false))
+ eq({ { 1, 'ABC' }, { 2, 'def' }, { 3, 'gHi' } }, fn.luaeval('lines'))
-- Automatic transformation of numbers
eq('', exec_capture('luado return linenr'))
- eq({'1', '2', '3'}, curbufmeths.get_lines(0, -1, false))
+ eq({ '1', '2', '3' }, api.nvim_buf_get_lines(0, 0, -1, false))
eq('', exec_capture('luado return ("<%02x>"):format(line:byte())'))
- eq({'<31>', '<32>', '<33>'}, curbufmeths.get_lines(0, -1, false))
+ eq({ '<31>', '<32>', '<33>' }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
+
it('stops processing lines when suddenly out of lines', function()
- curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
+ api.nvim_buf_set_lines(0, 0, 1, false, { 'ABC', 'def', 'gHi' })
eq('', exec_capture('2,$luado runs = ((runs or 0) + 1) vim.api.nvim_command("%d")'))
- eq({''}, curbufmeths.get_lines(0, -1, false))
- eq(1, funcs.luaeval('runs'))
- end)
- it('works correctly when changing lines out of range', function()
- curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
- eq('Vim(luado):E322: Line number out of range: 1 past the end',
- pcall_err(command, '2,$luado vim.api.nvim_command("%d") return linenr'))
- eq({''}, curbufmeths.get_lines(0, -1, false))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, false))
+ eq(1, fn.luaeval('runs'))
+
+ api.nvim_buf_set_lines(0, 0, -1, false, { 'one', 'two', 'three' })
+ eq('', exec_capture('luado vim.api.nvim_command("%d")'))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ api.nvim_buf_set_lines(0, 0, -1, false, { 'one', 'two', 'three' })
+ eq('', exec_capture('luado vim.api.nvim_command("1,2d")'))
+ eq({ 'three' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ api.nvim_buf_set_lines(0, 0, -1, false, { 'one', 'two', 'three' })
+ eq('', exec_capture('luado vim.api.nvim_command("2,3d"); return "REPLACED"'))
+ eq({ 'REPLACED' }, api.nvim_buf_get_lines(0, 0, -1, false))
+
+ api.nvim_buf_set_lines(0, 0, -1, false, { 'one', 'two', 'three' })
+ eq('', exec_capture('2,3luado vim.api.nvim_command("1,2d"); return "REPLACED"'))
+ eq({ 'three' }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
+
it('fails on errors', function()
- eq([[Vim(luado):E5109: Error loading lua: [string ":luado"]:0: unexpected symbol near ')']],
- pcall_err(command, 'luado ()'))
- eq([[Vim(luado):E5111: Error calling lua: [string ":luado"]:0: attempt to perform arithmetic on global 'liness' (a nil value)]],
- pcall_err(command, 'luado return liness + 1'))
+ eq(
+ [[Vim(luado):E5109: Error loading lua: [string ":luado"]:0: unexpected symbol near ')']],
+ pcall_err(command, 'luado ()')
+ )
+ eq(
+ [[Vim(luado):E5111: Error calling lua: [string ":luado"]:0: attempt to perform arithmetic on global 'liness' (a nil value)]],
+ pcall_err(command, 'luado return liness + 1')
+ )
end)
+
it('works with NULL errors', function()
- eq([=[Vim(luado):E5111: Error calling lua: [NULL]]=],
- exc_exec('luado error(nil)'))
+ eq([=[Vim(luado):E5111: Error calling lua: [NULL]]=], exc_exec('luado error(nil)'))
end)
+
it('fails in sandbox when needed', function()
- curbufmeths.set_lines(0, 1, false, {"ABC", "def", "gHi"})
- eq('Vim(luado):E48: Not allowed in sandbox: sandbox luado runs = (runs or 0) + 1',
- pcall_err(command, 'sandbox luado runs = (runs or 0) + 1'))
- eq(NIL, funcs.luaeval('runs'))
+ api.nvim_buf_set_lines(0, 0, 1, false, { 'ABC', 'def', 'gHi' })
+ eq(
+ 'Vim(luado):E48: Not allowed in sandbox: sandbox luado runs = (runs or 0) + 1',
+ pcall_err(command, 'sandbox luado runs = (runs or 0) + 1')
+ )
+ eq(NIL, fn.luaeval('runs'))
end)
+
it('works with long strings', function()
local s = ('x'):rep(100500)
- eq('Vim(luado):E5109: Error loading lua: [string ":luado"]:0: unfinished string near \'<eof>\'',
- pcall_err(command, ('luado return "%s'):format(s)))
- eq({''}, curbufmeths.get_lines(0, -1, false))
+ eq(
+ 'Vim(luado):E5109: Error loading lua: [string ":luado"]:0: unfinished string near \'<eof>\'',
+ pcall_err(command, ('luado return "%s'):format(s))
+ )
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, false))
eq('', exec_capture(('luado return "%s"'):format(s)))
- eq({s}, curbufmeths.get_lines(0, -1, false))
+ eq({ s }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
end)
@@ -238,26 +316,40 @@ describe(':luafile', function()
end)
it('works', function()
- write_file(fname, [[
+ write_file(
+ fname,
+ [[
vim.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"})
vim.api.nvim_buf_set_lines(1, 2, 3, false, {"TTSE"})
vim.api.nvim_buf_set_lines(1, 3, 4, false, {"STTE"})
- ]])
+ ]]
+ )
eq('', exec_capture('luafile ' .. fname))
- eq({'', 'ETTS', 'TTSE', 'STTE'}, curbufmeths.get_lines(0, 100, false))
+ eq({ '', 'ETTS', 'TTSE', 'STTE' }, api.nvim_buf_get_lines(0, 0, 100, false))
end)
it('correctly errors out', function()
write_file(fname, '()')
- eq(("Vim(luafile):E5112: Error while creating lua chunk: %s:1: unexpected symbol near ')'"):format(fname),
- exc_exec('luafile ' .. fname))
+ eq(
+ ("Vim(luafile):E5112: Error while creating lua chunk: %s:1: unexpected symbol near ')'"):format(
+ fname
+ ),
+ exc_exec('luafile ' .. fname)
+ )
write_file(fname, 'vimm.api.nvim_buf_set_lines(1, 1, 2, false, {"ETTS"})')
- eq(("Vim(luafile):E5113: Error while calling lua chunk: %s:1: attempt to index global 'vimm' (a nil value)"):format(fname),
- remove_trace(exc_exec('luafile ' .. fname)))
+ eq(
+ ("Vim(luafile):E5113: Error while calling lua chunk: %s:1: attempt to index global 'vimm' (a nil value)"):format(
+ fname
+ ),
+ remove_trace(exc_exec('luafile ' .. fname))
+ )
end)
+
it('works with NULL errors', function()
write_file(fname, 'error(nil)')
- eq([=[Vim(luafile):E5113: Error while calling lua chunk: [NULL]]=],
- exc_exec('luafile ' .. fname))
+ eq(
+ [=[Vim(luafile):E5113: Error while calling lua chunk: [NULL]]=],
+ exc_exec('luafile ' .. fname)
+ )
end)
end)
diff --git a/test/functional/lua/diagnostic_spec.lua b/test/functional/lua/diagnostic_spec.lua
index f061fac50a..5802925339 100644
--- a/test/functional/lua/diagnostic_spec.lua
+++ b/test/functional/lua/diagnostic_spec.lua
@@ -1,12 +1,12 @@
local helpers = require('test.functional.helpers')(after_each)
-local NIL = helpers.NIL
+local NIL = vim.NIL
local command = helpers.command
local clear = helpers.clear
local exec_lua = helpers.exec_lua
local eq = helpers.eq
-local nvim = helpers.nvim
local matches = helpers.matches
+local api = helpers.api
local pcall_err = helpers.pcall_err
describe('vim.diagnostic', function()
@@ -128,12 +128,20 @@ describe('vim.diagnostic', function()
return vim.diagnostic.get()
]]
eq(3, #result)
- eq(2, exec_lua([[return #vim.tbl_filter(function(d) return d.bufnr == diagnostic_bufnr end, ...)]], result))
+ eq(
+ 2,
+ exec_lua(
+ [[return #vim.tbl_filter(function(d) return d.bufnr == diagnostic_bufnr end, ...)]],
+ result
+ )
+ )
eq('Diagnostic #1', result[1].message)
end)
it('removes diagnostics from the cache when a buffer is removed', function()
- eq(2, exec_lua [[
+ eq(
+ 2,
+ exec_lua [[
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
local other_bufnr = vim.fn.bufadd('test | test')
local lines = vim.api.nvim_buf_get_lines(diagnostic_bufnr, 0, -1, true)
@@ -151,16 +159,23 @@ describe('vim.diagnostic', function()
vim.opt_local.buflisted = true
vim.cmd('bwipeout!')
return #vim.diagnostic.get()
- ]])
- eq(2, exec_lua [[
+ ]]
+ )
+ eq(
+ 2,
+ exec_lua [[
vim.api.nvim_set_current_buf(diagnostic_bufnr)
vim.opt_local.buflisted = false
return #vim.diagnostic.get()
- ]])
- eq(0, exec_lua [[
+ ]]
+ )
+ eq(
+ 0,
+ exec_lua [[
vim.cmd('bwipeout!')
return #vim.diagnostic.get()
- ]])
+ ]]
+ )
end)
it('removes diagnostic from stale cache on reset', function()
@@ -194,37 +209,48 @@ describe('vim.diagnostic', function()
end)
it('resolves buffer number 0 to the current buffer', function()
- eq(2, exec_lua [[
+ eq(
+ 2,
+ exec_lua [[
vim.api.nvim_set_current_buf(diagnostic_bufnr)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 1, 1, 1, 1),
make_error('Diagnostic #2', 2, 1, 2, 1),
})
return #vim.diagnostic.get(0)
- ]])
+ ]]
+ )
end)
it('saves and count a single error', function()
- eq(1, exec_lua [[
+ eq(
+ 1,
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 1, 1, 1, 1),
})
return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)
- ]])
+ ]]
+ )
end)
it('saves and count multiple errors', function()
- eq(2, exec_lua [[
+ eq(
+ 2,
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 1, 1, 1, 1),
make_error('Diagnostic #2', 2, 1, 2, 1),
})
return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)
- ]])
+ ]]
+ )
end)
it('saves and count from multiple namespaces', function()
- eq({1, 1, 2}, exec_lua [[
+ eq(
+ { 1, 1, 2 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic From Server 1', 1, 1, 1, 1),
})
@@ -239,11 +265,14 @@ describe('vim.diagnostic', function()
-- All namespaces
count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR),
}
- ]])
+ ]]
+ )
end)
it('saves and count from multiple namespaces with respect to severity', function()
- eq({3, 0, 3}, exec_lua [[
+ eq(
+ { 3, 0, 3 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
make_error('Diagnostic From Server 1:2', 2, 2, 2, 2),
@@ -260,7 +289,8 @@ describe('vim.diagnostic', function()
-- All namespaces
count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR),
}
- ]])
+ ]]
+ )
end)
it('handles one namespace clearing highlights while the other still has highlights', function()
@@ -269,8 +299,10 @@ describe('vim.diagnostic', function()
-- 1 Warning (2) + 1 Warning (1)
-- 2 highlights and 2 underlines (since error)
-- 1 highlight + 1 underline
- local all_highlights = {1, 1, 2, 4, 2}
- eq(all_highlights, exec_lua [[
+ local all_highlights = { 1, 1, 2, 4, 2 }
+ eq(
+ all_highlights,
+ exec_lua [[
local ns_1_diags = {
make_error("Error 1", 1, 1, 1, 5),
make_warning("Warning on Server 1", 2, 1, 2, 3),
@@ -289,10 +321,13 @@ describe('vim.diagnostic', function()
count_extmarks(diagnostic_bufnr, diagnostic_ns),
count_extmarks(diagnostic_bufnr, other_ns),
}
- ]])
+ ]]
+ )
-- Clear diagnostics from namespace 1, and make sure we have the right amount of stuff for namespace 2
- eq({1, 1, 2, 0, 2}, exec_lua [[
+ eq(
+ { 1, 1, 2, 0, 2 },
+ exec_lua [[
vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
return {
count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
@@ -301,10 +336,13 @@ describe('vim.diagnostic', function()
count_extmarks(diagnostic_bufnr, diagnostic_ns),
count_extmarks(diagnostic_bufnr, other_ns),
}
- ]])
+ ]]
+ )
-- Show diagnostics from namespace 1 again
- eq(all_highlights, exec_lua([[
+ eq(
+ all_highlights,
+ exec_lua([[
vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
return {
count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
@@ -313,11 +351,14 @@ describe('vim.diagnostic', function()
count_extmarks(diagnostic_bufnr, diagnostic_ns),
count_extmarks(diagnostic_bufnr, other_ns),
}
- ]]))
+ ]])
+ )
end)
it('does not display diagnostics when disabled', function()
- eq({0, 2}, exec_lua [[
+ eq(
+ { 0, 2 },
+ exec_lua [[
local ns_1_diags = {
make_error("Error 1", 1, 1, 1, 5),
make_warning("Warning on Server 1", 2, 1, 2, 3),
@@ -335,9 +376,12 @@ describe('vim.diagnostic', function()
count_extmarks(diagnostic_bufnr, diagnostic_ns),
count_extmarks(diagnostic_bufnr, other_ns),
}
- ]])
+ ]]
+ )
- eq({4, 0}, exec_lua [[
+ eq(
+ { 4, 0 },
+ exec_lua [[
vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
vim.diagnostic.disable(diagnostic_bufnr, other_ns)
@@ -345,7 +389,8 @@ describe('vim.diagnostic', function()
count_extmarks(diagnostic_bufnr, diagnostic_ns),
count_extmarks(diagnostic_bufnr, other_ns),
}
- ]])
+ ]]
+ )
end)
describe('show() and hide()', function()
@@ -660,8 +705,10 @@ describe('vim.diagnostic', function()
-- 1 Warning (2) + 1 Warning (1)
-- 2 highlights and 2 underlines (since error)
-- 1 highlight + 1 underline
- local all_highlights = {1, 1, 2, 4, 2}
- eq(all_highlights, exec_lua [[
+ local all_highlights = { 1, 1, 2, 4, 2 }
+ eq(
+ all_highlights,
+ exec_lua [[
local ns_1_diags = {
make_error("Error 1", 1, 1, 1, 5),
make_warning("Warning on Server 1", 2, 1, 2, 3),
@@ -680,13 +727,16 @@ describe('vim.diagnostic', function()
count_extmarks(diagnostic_bufnr, diagnostic_ns),
count_extmarks(diagnostic_bufnr, other_ns),
}
- ]])
+ ]]
+ )
-- Reset diagnostics from namespace 1
exec_lua([[ vim.diagnostic.reset(diagnostic_ns) ]])
-- Make sure we have the right diagnostic count
- eq({0, 1, 1, 0, 2} , exec_lua [[
+ eq(
+ { 0, 1, 1, 0, 2 },
+ exec_lua [[
local diagnostic_count = {}
vim.wait(100, function () diagnostic_count = {
count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
@@ -696,13 +746,16 @@ describe('vim.diagnostic', function()
count_extmarks(diagnostic_bufnr, other_ns),
} end )
return diagnostic_count
- ]])
+ ]]
+ )
-- Reset diagnostics from namespace 2
exec_lua([[ vim.diagnostic.reset(other_ns) ]])
-- Make sure we have the right diagnostic count
- eq({0, 0, 0, 0, 0}, exec_lua [[
+ eq(
+ { 0, 0, 0, 0, 0 },
+ exec_lua [[
local diagnostic_count = {}
vim.wait(100, function () diagnostic_count = {
count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns),
@@ -712,8 +765,8 @@ describe('vim.diagnostic', function()
count_extmarks(diagnostic_bufnr, other_ns),
} end )
return diagnostic_count
- ]])
-
+ ]]
+ )
end)
it("doesn't error after bwipeout called on buffer", function()
@@ -728,17 +781,22 @@ describe('vim.diagnostic', function()
describe('get_next_pos()', function()
it('can find the next pos with only one namespace', function()
- eq({1, 1}, exec_lua [[
+ eq(
+ { 1, 1 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 1, 1, 1, 1),
})
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
return vim.diagnostic.get_next_pos()
- ]])
+ ]]
+ )
end)
it('can find next pos with two errors', function()
- eq({4, 4}, exec_lua [[
+ eq(
+ { 4, 4 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 1, 1, 1, 1),
make_error('Diagnostic #2', 4, 4, 4, 4),
@@ -746,44 +804,56 @@ describe('vim.diagnostic', function()
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.api.nvim_win_set_cursor(0, {3, 1})
return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
- ]])
+ ]]
+ )
end)
it('can cycle when position is past error', function()
- eq({1, 1}, exec_lua [[
+ eq(
+ { 1, 1 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 1, 1, 1, 1),
})
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.api.nvim_win_set_cursor(0, {3, 1})
return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
- ]])
+ ]]
+ )
end)
it('will not cycle when wrap is off', function()
- eq(false, exec_lua [[
+ eq(
+ false,
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 1, 1, 1, 1),
})
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.api.nvim_win_set_cursor(0, {3, 1})
return vim.diagnostic.get_next_pos { namespace = diagnostic_ns, wrap = false }
- ]])
+ ]]
+ )
end)
it('can cycle even from the last line', function()
- eq({4, 4}, exec_lua [[
+ eq(
+ { 4, 4 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #2', 4, 4, 4, 4),
})
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.api.nvim_win_set_cursor(0, {vim.api.nvim_buf_line_count(0), 1})
return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
- ]])
+ ]]
+ )
end)
it('works with diagnostics past the end of the line #16349', function()
- eq({4, 0}, exec_lua [[
+ eq(
+ { 4, 0 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 3, 9001, 3, 9001),
make_error('Diagnostic #2', 4, 0, 4, 0),
@@ -792,11 +862,14 @@ describe('vim.diagnostic', function()
vim.api.nvim_win_set_cursor(0, {1, 1})
vim.diagnostic.goto_next { float = false }
return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
- ]])
+ ]]
+ )
end)
it('works with diagnostics before the start of the line', function()
- eq({4, 0}, exec_lua [[
+ eq(
+ { 4, 0 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 3, 9001, 3, 9001),
make_error('Diagnostic #2', 4, -1, 4, -1),
@@ -805,24 +878,30 @@ describe('vim.diagnostic', function()
vim.api.nvim_win_set_cursor(0, {1, 1})
vim.diagnostic.goto_next { float = false }
return vim.diagnostic.get_next_pos { namespace = diagnostic_ns }
- ]])
-end)
+ ]]
+ )
+ end)
end)
describe('get_prev_pos()', function()
it('can find the prev pos with only one namespace', function()
- eq({1, 1}, exec_lua [[
+ eq(
+ { 1, 1 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 1, 1, 1, 1),
})
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.api.nvim_win_set_cursor(0, {3, 1})
return vim.diagnostic.get_prev_pos()
- ]])
+ ]]
+ )
end)
it('can find prev pos with two errors', function()
- eq({1, 1}, exec_lua [[
+ eq(
+ { 1, 1 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 1, 1, 1, 1),
make_error('Diagnostic #2', 4, 4, 4, 4),
@@ -830,29 +909,36 @@ end)
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.api.nvim_win_set_cursor(0, {3, 1})
return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
- ]])
+ ]]
+ )
end)
it('can cycle when position is past error', function()
- eq({4, 4}, exec_lua [[
+ eq(
+ { 4, 4 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #2', 4, 4, 4, 4),
})
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.api.nvim_win_set_cursor(0, {3, 1})
return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns }
- ]])
+ ]]
+ )
end)
it('respects wrap parameter', function()
- eq(false, exec_lua [[
+ eq(
+ false,
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #2', 4, 4, 4, 4),
})
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
vim.api.nvim_win_set_cursor(0, {3, 1})
return vim.diagnostic.get_prev_pos { namespace = diagnostic_ns, wrap = false}
- ]])
+ ]]
+ )
end)
end)
@@ -862,18 +948,23 @@ end)
end)
it('returns all diagnostics when no severity is supplied', function()
- eq(2, exec_lua [[
+ eq(
+ 2,
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error("Error 1", 1, 1, 1, 5),
make_warning("Warning on Server 1", 1, 1, 2, 3),
})
return #vim.diagnostic.get(diagnostic_bufnr)
- ]])
+ ]]
+ )
end)
it('returns only requested diagnostics when severity range is supplied', function()
- eq({2, 3, 2}, exec_lua [[
+ eq(
+ { 2, 3, 2 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error("Error 1", 1, 1, 1, 5),
make_warning("Warning on Server 1", 1, 1, 2, 3),
@@ -891,11 +982,14 @@ end)
}
}),
}
- ]])
+ ]]
+ )
end)
it('returns only requested diagnostics when severities are supplied', function()
- eq({1, 1, 2}, exec_lua [[
+ eq(
+ { 1, 1, 2 },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error("Error 1", 1, 1, 1, 5),
make_warning("Warning on Server 1", 1, 1, 2, 3),
@@ -913,11 +1007,14 @@ end)
}
}),
}
- ]])
+ ]]
+ )
end)
it('allows filtering by line', function()
- eq(1, exec_lua [[
+ eq(
+ 1,
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error("Error 1", 1, 1, 1, 5),
make_warning("Warning on Server 1", 1, 1, 2, 3),
@@ -926,13 +1023,132 @@ end)
})
return #vim.diagnostic.get(diagnostic_bufnr, {lnum = 2})
- ]])
+ ]]
+ )
+ end)
+ end)
+
+ describe('count', function()
+ it('returns actually present severity counts', function()
+ eq(
+ exec_lua [[return {
+ [vim.diagnostic.severity.ERROR] = 4,
+ [vim.diagnostic.severity.WARN] = 3,
+ [vim.diagnostic.severity.INFO] = 2,
+ [vim.diagnostic.severity.HINT] = 1,
+ }]],
+ exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Error 1", 1, 1, 1, 2),
+ make_error("Error 2", 1, 3, 1, 4),
+ make_error("Error 3", 1, 5, 1, 6),
+ make_error("Error 4", 1, 7, 1, 8),
+ make_warning("Warning 1", 2, 1, 2, 2),
+ make_warning("Warning 2", 2, 3, 2, 4),
+ make_warning("Warning 3", 2, 5, 2, 6),
+ make_info("Info 1", 3, 1, 3, 2),
+ make_info("Info 2", 3, 3, 3, 4),
+ make_hint("Hint 1", 4, 1, 4, 2),
+ })
+ return vim.diagnostic.count(diagnostic_bufnr)
+ ]]
+ )
+ eq(
+ exec_lua [[return {
+ [vim.diagnostic.severity.ERROR] = 2,
+ [vim.diagnostic.severity.INFO] = 1,
+ }]],
+ exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Error 1", 1, 1, 1, 2),
+ make_error("Error 2", 1, 3, 1, 4),
+ make_info("Info 1", 3, 1, 3, 2),
+ })
+ return vim.diagnostic.count(diagnostic_bufnr)
+ ]]
+ )
+ end)
+
+ it('returns only requested diagnostics count when severity range is supplied', function()
+ eq(
+ exec_lua [[return {
+ { [vim.diagnostic.severity.ERROR] = 1, [vim.diagnostic.severity.WARN] = 1 },
+ { [vim.diagnostic.severity.WARN] = 1, [vim.diagnostic.severity.INFO] = 1, [vim.diagnostic.severity.HINT] = 1 },
+ { [vim.diagnostic.severity.WARN] = 1, [vim.diagnostic.severity.INFO] = 1 },
+ }]],
+ exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 1, 1, 2, 3),
+ make_info("Ignored information", 1, 1, 2, 3),
+ make_hint("Here's a hint", 1, 1, 2, 3),
+ })
+
+ return {
+ vim.diagnostic.count(diagnostic_bufnr, { severity = {min=vim.diagnostic.severity.WARN} }),
+ vim.diagnostic.count(diagnostic_bufnr, { severity = {max=vim.diagnostic.severity.WARN} }),
+ vim.diagnostic.count(diagnostic_bufnr, {
+ severity = {
+ min=vim.diagnostic.severity.INFO,
+ max=vim.diagnostic.severity.WARN,
+ }
+ }),
+ }
+ ]]
+ )
+ end)
+
+ it('returns only requested diagnostics when severities are supplied', function()
+ eq(
+ exec_lua [[return {
+ { [vim.diagnostic.severity.WARN] = 1 },
+ { [vim.diagnostic.severity.ERROR] = 1 },
+ { [vim.diagnostic.severity.WARN] = 1, [vim.diagnostic.severity.INFO] = 1 },
+ }]],
+ exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 1, 1, 2, 3),
+ make_info("Ignored information", 1, 1, 2, 3),
+ make_hint("Here's a hint", 1, 1, 2, 3),
+ })
+
+ return {
+ vim.diagnostic.count(diagnostic_bufnr, { severity = {vim.diagnostic.severity.WARN} }),
+ vim.diagnostic.count(diagnostic_bufnr, { severity = {vim.diagnostic.severity.ERROR} }),
+ vim.diagnostic.count(diagnostic_bufnr, {
+ severity = {
+ vim.diagnostic.severity.INFO,
+ vim.diagnostic.severity.WARN,
+ }
+ }),
+ }
+ ]]
+ )
+ end)
+
+ it('allows filtering by line', function()
+ eq(
+ exec_lua [[return { [vim.diagnostic.severity.ERROR] = 1 }]],
+ exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
+ make_error("Error 1", 1, 1, 1, 5),
+ make_warning("Warning on Server 1", 1, 1, 2, 3),
+ make_info("Ignored information", 1, 1, 2, 3),
+ make_error("Error On Other Line", 2, 1, 1, 5),
+ })
+
+ return vim.diagnostic.count(diagnostic_bufnr, {lnum = 2})
+ ]]
+ )
end)
end)
describe('config()', function()
it('works with global, namespace, and ephemeral options', function()
- eq(1, exec_lua [[
+ eq(
+ 1,
+ exec_lua [[
vim.diagnostic.config({
virtual_text = false,
})
@@ -947,9 +1163,12 @@ end)
})
return count_extmarks(diagnostic_bufnr, diagnostic_ns)
- ]])
+ ]]
+ )
- eq(1, exec_lua [[
+ eq(
+ 1,
+ exec_lua [[
vim.diagnostic.config({
virtual_text = false,
})
@@ -964,9 +1183,12 @@ end)
}, {virtual_text = true})
return count_extmarks(diagnostic_bufnr, diagnostic_ns)
- ]])
+ ]]
+ )
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
vim.diagnostic.config({
virtual_text = false,
})
@@ -981,9 +1203,12 @@ end)
}, {virtual_text = true})
return count_extmarks(diagnostic_bufnr, diagnostic_ns)
- ]])
+ ]]
+ )
- eq(1, exec_lua [[
+ eq(
+ 1,
+ exec_lua [[
vim.diagnostic.config({
virtual_text = false,
})
@@ -1000,7 +1225,8 @@ end)
})
return count_extmarks(diagnostic_bufnr, diagnostic_ns)
- ]])
+ ]]
+ )
end)
it('can use functions for config values', function()
@@ -1013,7 +1239,10 @@ end)
})
]]
- eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(
+ 1,
+ exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]]
+ )
eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
-- Now, don't enable virtual text.
@@ -1024,13 +1253,17 @@ end)
}, diagnostic_ns)
]]
- eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(
+ 1,
+ exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]]
+ )
eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
end)
it('allows filtering by severity', function()
local get_extmark_count_with_severity = function(min_severity)
- return exec_lua([[
+ return exec_lua(
+ [[
vim.diagnostic.config({
underline = false,
virtual_text = {
@@ -1043,15 +1276,17 @@ end)
})
return count_extmarks(diagnostic_bufnr, diagnostic_ns)
- ]], min_severity)
+ ]],
+ min_severity
+ )
end
-- No messages with Error or higher
- eq(0, get_extmark_count_with_severity("ERROR"))
+ eq(0, get_extmark_count_with_severity('ERROR'))
-- But now we don't filter it
- eq(1, get_extmark_count_with_severity("WARN"))
- eq(1, get_extmark_count_with_severity("HINT"))
+ eq(1, get_extmark_count_with_severity('WARN'))
+ eq(1, get_extmark_count_with_severity('HINT'))
end)
it('allows sorting by severity', function()
@@ -1080,9 +1315,19 @@ end)
table.insert(virt_texts, (string.gsub(virt_text[i][2], "DiagnosticVirtualText", "")))
end
+ local ns = vim.diagnostic.get_namespace(diagnostic_ns)
+ local sign_ns = ns.user_data.sign_ns
local signs = {}
- for _, v in ipairs(vim.fn.sign_getplaced(diagnostic_bufnr, {group = "*"})[1].signs) do
- table.insert(signs, (string.gsub(v.name, "DiagnosticSign", "")))
+ local all_signs = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, sign_ns, 0, -1, {type = 'sign', details = true})
+ table.sort(all_signs, function(a, b)
+ return a[1] > b[1]
+ end)
+
+ for _, v in ipairs(all_signs) do
+ local s = v[4].sign_hl_group:gsub('DiagnosticSign', "")
+ if not vim.tbl_contains(signs, s) then
+ signs[#signs + 1] = s
+ end
end
return {virt_texts, signs}
@@ -1093,16 +1338,16 @@ end)
-- Virt texts are defined lowest priority to highest, signs from
-- highest to lowest
- eq({'Warn', 'Error', 'Info'}, result[1])
- eq({'Info', 'Error', 'Warn'}, result[2])
+ eq({ 'Warn', 'Error', 'Info' }, result[1])
+ eq({ 'Info', 'Error', 'Warn' }, result[2])
result = exec_lua [[return get_virt_text_and_signs(true)]]
- eq({'Info', 'Warn', 'Error'}, result[1])
- eq({'Error', 'Warn', 'Info'}, result[2])
+ eq({ 'Info', 'Warn', 'Error' }, result[1])
+ eq({ 'Error', 'Warn', 'Info' }, result[2])
result = exec_lua [[return get_virt_text_and_signs({ reverse = true })]]
- eq({'Error', 'Warn', 'Info'}, result[1])
- eq({'Info', 'Warn', 'Error'}, result[2])
+ eq({ 'Error', 'Warn', 'Info' }, result[1])
+ eq({ 'Info', 'Warn', 'Error' }, result[2])
end)
it('can show diagnostic sources in virtual text', function()
@@ -1185,8 +1430,8 @@ end)
local extmarks = get_virt_text_extmarks(diagnostic_ns)
return {extmarks[1][4].virt_text, extmarks[2][4].virt_text}
]]
- eq(" 👀 Warning", result[1][3][1])
- eq(" 🔥 Error", result[2][3][1])
+ eq(' 👀 Warning', result[1][3][1])
+ eq(' 🔥 Error', result[2][3][1])
end)
it('includes source for formatted diagnostics', function()
@@ -1213,12 +1458,14 @@ end)
local extmarks = get_virt_text_extmarks(diagnostic_ns)
return {extmarks[1][4].virt_text, extmarks[2][4].virt_text}
]]
- eq(" some_linter: 👀 Warning", result[1][3][1])
- eq(" another_linter: 🔥 Error", result[2][3][1])
+ eq(' some_linter: 👀 Warning', result[1][3][1])
+ eq(' another_linter: 🔥 Error', result[2][3][1])
end)
it('can add a prefix to virtual text', function()
- eq('E Some error', exec_lua [[
+ eq(
+ 'E Some error',
+ exec_lua [[
local diagnostics = {
make_error('Some error', 0, 0, 0, 0),
}
@@ -1235,9 +1482,12 @@ end)
local prefix = extmarks[1][4].virt_text[2][1]
local message = extmarks[1][4].virt_text[3][1]
return prefix .. message
- ]])
+ ]]
+ )
- eq('[(1/1) err-code] Some error', exec_lua [[
+ eq(
+ '[(1/1) err-code] Some error',
+ exec_lua [[
local diagnostics = {
make_error('Some error', 0, 0, 0, 0, nil, 'err-code'),
}
@@ -1254,11 +1504,14 @@ end)
local prefix = extmarks[1][4].virt_text[2][1]
local message = extmarks[1][4].virt_text[3][1]
return prefix .. message
- ]])
+ ]]
+ )
end)
it('can add a suffix to virtual text', function()
- eq(' Some error ✘', exec_lua [[
+ eq(
+ ' Some error ✘',
+ exec_lua [[
local diagnostics = {
make_error('Some error', 0, 0, 0, 0),
}
@@ -1274,9 +1527,12 @@ end)
local extmarks = get_virt_text_extmarks(diagnostic_ns)
local virt_text = extmarks[1][4].virt_text[3][1]
return virt_text
- ]])
+ ]]
+ )
- eq(' Some error [err-code]', exec_lua [[
+ eq(
+ ' Some error [err-code]',
+ exec_lua [[
local diagnostics = {
make_error('Some error', 0, 0, 0, 0, nil, 'err-code'),
}
@@ -1292,20 +1548,23 @@ end)
local extmarks = get_virt_text_extmarks(diagnostic_ns)
local virt_text = extmarks[1][4].virt_text[3][1]
return virt_text
- ]])
+ ]]
+ )
end)
end)
describe('set()', function()
it('validates its arguments', function()
- matches("expected a list of diagnostics",
- pcall_err(exec_lua, [[vim.diagnostic.set(1, 0, {lnum = 1, col = 2})]]))
+ matches(
+ 'expected a list of diagnostics',
+ pcall_err(exec_lua, [[vim.diagnostic.set(1, 0, {lnum = 1, col = 2})]])
+ )
end)
it('can perform updates after insert_leave', function()
exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
+ api.nvim_input('o')
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
-- Save the diagnostics
exec_lua [[
@@ -1318,21 +1577,27 @@ end)
]]
-- No diagnostics displayed yet.
- eq({mode='i', blocking=false}, nvim("get_mode"))
- eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
+ eq(
+ 1,
+ exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]]
+ )
eq(0, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ api.nvim_input('<esc>')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
- eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(
+ 1,
+ exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]]
+ )
eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
end)
it('does not perform updates when not needed', function()
exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
+ api.nvim_input('o')
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
-- Save the diagnostics
exec_lua [[
@@ -1354,24 +1619,30 @@ end)
]]
-- No diagnostics displayed yet.
- eq({mode='i', blocking=false}, nvim("get_mode"))
- eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
+ eq(
+ 1,
+ exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]]
+ )
eq(0, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
eq(0, exec_lua [[return DisplayCount]])
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ api.nvim_input('<esc>')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
- eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(
+ 1,
+ exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]]
+ )
eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
eq(1, exec_lua [[return DisplayCount]])
-- Go in and out of insert mode one more time.
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
+ api.nvim_input('o')
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ api.nvim_input('<esc>')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
-- Should not have set the virtual text again.
eq(1, exec_lua [[return DisplayCount]])
@@ -1379,8 +1650,8 @@ end)
it('never sets virtual text, in combination with insert leave', function()
exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
+ api.nvim_input('o')
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
-- Save the diagnostics
exec_lua [[
@@ -1403,24 +1674,30 @@ end)
]]
-- No diagnostics displayed yet.
- eq({mode='i', blocking=false}, nvim("get_mode"))
- eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
+ eq(
+ 1,
+ exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]]
+ )
eq(0, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
eq(0, exec_lua [[return DisplayCount]])
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ api.nvim_input('<esc>')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
- eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(
+ 1,
+ exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]]
+ )
eq(1, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
eq(0, exec_lua [[return DisplayCount]])
-- Go in and out of insert mode one more time.
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
+ api.nvim_input('o')
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ api.nvim_input('<esc>')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
-- Should not have set the virtual text still.
eq(0, exec_lua [[return DisplayCount]])
@@ -1428,8 +1705,8 @@ end)
it('can perform updates while in insert mode, if desired', function()
exec_lua [[vim.api.nvim_set_current_buf(diagnostic_bufnr)]]
- nvim("input", "o")
- eq({mode='i', blocking=false}, nvim("get_mode"))
+ api.nvim_input('o')
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
-- Save the diagnostics
exec_lua [[
@@ -1443,49 +1720,126 @@ end)
]]
-- Diagnostics are displayed, because the user wanted them that way!
- eq({mode='i', blocking=false}, nvim("get_mode"))
- eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq({ mode = 'i', blocking = false }, api.nvim_get_mode())
+ eq(
+ 1,
+ exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]]
+ )
eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
- nvim("input", "<esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ api.nvim_input('<esc>')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
- eq(1, exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]])
+ eq(
+ 1,
+ exec_lua [[return count_diagnostics(diagnostic_bufnr, vim.diagnostic.severity.ERROR, diagnostic_ns)]]
+ )
eq(2, exec_lua [[return count_extmarks(diagnostic_bufnr, diagnostic_ns)]])
end)
it('can set diagnostics without displaying them', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
vim.diagnostic.disable(diagnostic_bufnr, diagnostic_ns)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
})
return count_extmarks(diagnostic_bufnr, diagnostic_ns)
- ]])
+ ]]
+ )
- eq(2, exec_lua [[
+ eq(
+ 2,
+ exec_lua [[
vim.diagnostic.enable(diagnostic_bufnr, diagnostic_ns)
return count_extmarks(diagnostic_bufnr, diagnostic_ns)
- ]])
+ ]]
+ )
end)
it('can set display options', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
}, { virtual_text = false, underline = false })
return count_extmarks(diagnostic_bufnr, diagnostic_ns)
- ]])
+ ]]
+ )
- eq(1, exec_lua [[
+ eq(
+ 1,
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic From Server 1:1', 1, 1, 1, 1),
}, { virtual_text = true, underline = false })
return count_extmarks(diagnostic_bufnr, diagnostic_ns)
- ]])
+ ]]
+ )
end)
- it('sets signs', function()
+ it('sets and clears signs #26193 #26555', function()
+ do
+ local result = exec_lua [[
+ vim.diagnostic.config({
+ signs = true,
+ })
+
+ local diagnostics = {
+ make_error('Error', 1, 1, 1, 2),
+ make_warning('Warning', 3, 3, 3, 3),
+ }
+
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
+
+ local ns = vim.diagnostic.get_namespace(diagnostic_ns)
+ local sign_ns = ns.user_data.sign_ns
+
+ local signs = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, sign_ns, 0, -1, {type ='sign', details = true})
+ local result = {}
+ for _, s in ipairs(signs) do
+ result[#result + 1] = { lnum = s[2] + 1, name = s[4].sign_hl_group }
+ end
+ return result
+ ]]
+
+ eq({ 2, 'DiagnosticSignError' }, { result[1].lnum, result[1].name })
+ eq({ 4, 'DiagnosticSignWarn' }, { result[2].lnum, result[2].name })
+ end
+
+ do
+ local result = exec_lua [[
+ vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {})
+
+ local ns = vim.diagnostic.get_namespace(diagnostic_ns)
+ local sign_ns = ns.user_data.sign_ns
+
+ return vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, sign_ns, 0, -1, {type ='sign', details = true})
+ ]]
+
+ eq({}, result)
+ end
+ end)
+
+ it('respects legacy signs placed with :sign define or sign_define #26618', function()
+ -- Legacy signs for diagnostics were deprecated in 0.10 and will be removed in 0.12
+ eq(0, helpers.fn.has('nvim-0.12'))
+
+ helpers.command(
+ 'sign define DiagnosticSignError text= texthl= linehl=ErrorMsg numhl=ErrorMsg'
+ )
+ helpers.command(
+ 'sign define DiagnosticSignWarn text= texthl= linehl=WarningMsg numhl=WarningMsg'
+ )
+ helpers.command(
+ 'sign define DiagnosticSignInfo text= texthl= linehl=Underlined numhl=Underlined'
+ )
+ helpers.command(
+ 'sign define DiagnosticSignHint text= texthl= linehl=Underlined numhl=Underlined'
+ )
+
local result = exec_lua [[
vim.diagnostic.config({
signs = true,
@@ -1498,17 +1852,46 @@ end)
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, diagnostics)
- return vim.fn.sign_getplaced(diagnostic_bufnr, {group = '*'})[1].signs
+ local ns = vim.diagnostic.get_namespace(diagnostic_ns)
+ local sign_ns = ns.user_data.sign_ns
+
+ local signs = vim.api.nvim_buf_get_extmarks(diagnostic_bufnr, sign_ns, 0, -1, {type ='sign', details = true})
+ local result = {}
+ for _, s in ipairs(signs) do
+ result[#result + 1] = {
+ lnum = s[2] + 1,
+ name = s[4].sign_hl_group,
+ text = s[4].sign_text or '',
+ numhl = s[4].number_hl_group,
+ linehl = s[4].line_hl_group,
+ }
+ end
+ return result
]]
- eq({2, 'DiagnosticSignError'}, {result[1].lnum, result[1].name})
- eq({4, 'DiagnosticSignWarn'}, {result[2].lnum, result[2].name})
+ eq({
+ lnum = 2,
+ name = 'DiagnosticSignError',
+ text = '',
+ numhl = 'ErrorMsg',
+ linehl = 'ErrorMsg',
+ }, result[1])
+
+ eq({
+ lnum = 4,
+ name = 'DiagnosticSignWarn',
+ text = '',
+ numhl = 'WarningMsg',
+ linehl = 'WarningMsg',
+ }, result[2])
end)
end)
describe('open_float()', function()
it('can display a header', function()
- eq({'Diagnostics:', '1. Syntax error'}, exec_lua [[
+ eq(
+ { 'Diagnostics:', '1. Syntax error' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
}
@@ -1518,9 +1901,12 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq({"We're no strangers to love...", '1. Syntax error'}, exec_lua [[
+ eq(
+ { "We're no strangers to love...", '1. Syntax error' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
}
@@ -1530,9 +1916,12 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq({'You know the rules', '1. Syntax error'}, exec_lua [[
+ eq(
+ { 'You know the rules', '1. Syntax error' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
}
@@ -1542,11 +1931,14 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
end)
it('can show diagnostics from the whole buffer', function()
- eq({'1. Syntax error', '2. Some warning'}, exec_lua [[
+ eq(
+ { '1. Syntax error', '2. Some warning' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
make_warning("Some warning", 1, 1, 1, 3),
@@ -1557,12 +1949,15 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
end)
it('can show diagnostics from a single line', function()
-- Using cursor position
- eq({'1. Some warning'}, exec_lua [[
+ eq(
+ { '1. Some warning' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
make_warning("Some warning", 1, 1, 1, 3),
@@ -1574,10 +1969,13 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
-- With specified position
- eq({'1. Some warning'}, exec_lua [[
+ eq(
+ { '1. Some warning' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
make_warning("Some warning", 1, 1, 1, 3),
@@ -1589,12 +1987,15 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
end)
it('can show diagnostics from a specific position', function()
-- Using cursor position
- eq({'Syntax error'}, exec_lua [[
+ eq(
+ { 'Syntax error' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 1, 1, 1, 2),
make_warning("Some warning", 1, 3, 1, 4),
@@ -1606,10 +2007,13 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
-- With specified position
- eq({'Some warning'}, exec_lua [[
+ eq(
+ { 'Some warning' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 1, 1, 1, 2),
make_warning("Some warning", 1, 3, 1, 4),
@@ -1621,10 +2025,13 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
-- With column position past the end of the line. #16062
- eq({'Syntax error'}, exec_lua [[
+ eq(
+ { 'Syntax error' },
+ exec_lua [[
local first_line_len = #vim.api.nvim_buf_get_lines(diagnostic_bufnr, 0, 1, true)[1]
local diagnostics = {
make_error("Syntax error", 0, first_line_len + 1, 1, 0),
@@ -1636,14 +2043,19 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
- end)
-
- it('creates floating window and returns float bufnr and winnr if current line contains diagnostics', function()
- -- Two lines:
- -- Diagnostic:
- -- 1. <msg>
- eq(2, exec_lua [[
+ ]]
+ )
+ end)
+
+ it(
+ 'creates floating window and returns float bufnr and winnr if current line contains diagnostics',
+ function()
+ -- Two lines:
+ -- Diagnostic:
+ -- 1. <msg>
+ eq(
+ 2,
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
}
@@ -1653,11 +2065,15 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return #lines
- ]])
- end)
+ ]]
+ )
+ end
+ )
it('only reports diagnostics from the current buffer when bufnr is omitted #15710', function()
- eq(2, exec_lua [[
+ eq(
+ 2,
+ exec_lua [[
local other_bufnr = vim.api.nvim_create_buf(true, false)
local buf_1_diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
@@ -1672,11 +2088,14 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return #lines
- ]])
+ ]]
+ )
end)
it('allows filtering by namespace', function()
- eq(2, exec_lua [[
+ eq(
+ 2,
+ exec_lua [[
local ns_1_diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
}
@@ -1690,13 +2109,18 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return #lines
- ]])
+ ]]
+ )
end)
- it('creates floating window and returns float bufnr and winnr without header, if requested', function()
- -- One line (since no header):
- -- 1. <msg>
- eq(1, exec_lua [[
+ it(
+ 'creates floating window and returns float bufnr and winnr without header, if requested',
+ function()
+ -- One line (since no header):
+ -- 1. <msg>
+ eq(
+ 1,
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
}
@@ -1706,11 +2130,15 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return #lines
- ]])
- end)
+ ]]
+ )
+ end
+ )
it('clamps diagnostic line numbers within the valid range', function()
- eq(1, exec_lua [[
+ eq(
+ 1,
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 6, 0, 6, 0),
}
@@ -1720,13 +2148,16 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return #lines
- ]])
+ ]]
+ )
end)
it('can show diagnostic source', function()
exec_lua [[vim.api.nvim_win_set_buf(0, diagnostic_bufnr)]]
- eq({"1. Syntax error"}, exec_lua [[
+ eq(
+ { '1. Syntax error' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3, "source x"),
}
@@ -1738,9 +2169,12 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq({"1. source x: Syntax error"}, exec_lua [[
+ eq(
+ { '1. source x: Syntax error' },
+ exec_lua [[
local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, {
header = false,
source = "always",
@@ -1748,9 +2182,12 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq({"1. source x: Syntax error", "2. source y: Another error"}, exec_lua [[
+ eq(
+ { '1. source x: Syntax error', '2. source y: Another error' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3, "source x"),
make_error("Another error", 0, 1, 0, 3, "source y"),
@@ -1763,13 +2200,16 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
end)
it('respects severity_sort', function()
exec_lua [[vim.api.nvim_win_set_buf(0, diagnostic_bufnr)]]
- eq({"1. Syntax error", "2. Info", "3. Error", "4. Warning"}, exec_lua [[
+ eq(
+ { '1. Syntax error', '2. Info', '3. Error', '4. Warning' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
make_info('Info', 0, 3, 0, 4),
@@ -1785,28 +2225,36 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq({"1. Syntax error", "2. Error", "3. Warning", "4. Info"}, exec_lua [[
+ eq(
+ { '1. Syntax error', '2. Error', '3. Warning', '4. Info' },
+ exec_lua [[
vim.diagnostic.config({severity_sort = true})
local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { header = false })
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq({"1. Info", "2. Warning", "3. Error", "4. Syntax error"}, exec_lua [[
+ eq(
+ { '1. Info', '2. Warning', '3. Error', '4. Syntax error' },
+ exec_lua [[
vim.diagnostic.config({severity_sort = { reverse = true } })
local float_bufnr, winnr = vim.diagnostic.open_float(diagnostic_bufnr, { header = false })
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
end)
it('can filter by severity', function()
local count_diagnostics_with_severity = function(min_severity, max_severity)
- return exec_lua([[
+ return exec_lua(
+ [[
local min_severity, max_severity = ...
vim.diagnostic.config({
float = {
@@ -1829,19 +2277,24 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return #lines
- ]], min_severity, max_severity)
+ ]],
+ min_severity,
+ max_severity
+ )
end
- eq(2, count_diagnostics_with_severity("ERROR"))
- eq(3, count_diagnostics_with_severity("WARN"))
- eq(1, count_diagnostics_with_severity("WARN", "WARN"))
- eq(4, count_diagnostics_with_severity("HINT"))
- eq(0, count_diagnostics_with_severity("HINT", "HINT"))
+ eq(2, count_diagnostics_with_severity('ERROR'))
+ eq(3, count_diagnostics_with_severity('WARN'))
+ eq(1, count_diagnostics_with_severity('WARN', 'WARN'))
+ eq(4, count_diagnostics_with_severity('HINT'))
+ eq(0, count_diagnostics_with_severity('HINT', 'HINT'))
end)
it('can add a prefix to diagnostics', function()
-- Default is to add a number
- eq({'1. Syntax error', '2. Some warning'}, exec_lua [[
+ eq(
+ { '1. Syntax error', '2. Some warning' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
make_warning("Some warning", 1, 1, 1, 3),
@@ -1852,9 +2305,12 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq({'Syntax error', 'Some warning'}, exec_lua [[
+ eq(
+ { 'Syntax error', 'Some warning' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
make_warning("Some warning", 1, 1, 1, 3),
@@ -1865,9 +2321,12 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq({'1. Syntax error', '2. Some warning'}, exec_lua [[
+ eq(
+ { '1. Syntax error', '2. Some warning' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
make_warning("Some warning", 0, 1, 0, 3),
@@ -1887,9 +2346,12 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq({'Syntax error'}, exec_lua [[
+ eq(
+ { 'Syntax error' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
}
@@ -1908,15 +2370,20 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq(".../diagnostic.lua:0: prefix: expected string|table|function, got number",
- pcall_err(exec_lua, [[ vim.diagnostic.open_float({ prefix = 42 }) ]]))
+ eq(
+ '.../diagnostic.lua:0: prefix: expected string|table|function, got number',
+ pcall_err(exec_lua, [[ vim.diagnostic.open_float({ prefix = 42 }) ]])
+ )
end)
it('can add a suffix to diagnostics', function()
-- Default is to render the diagnostic error code
- eq({'1. Syntax error [code-x]', '2. Some warning [code-y]'}, exec_lua [[
+ eq(
+ { '1. Syntax error [code-x]', '2. Some warning [code-y]' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3, nil, "code-x"),
make_warning("Some warning", 1, 1, 1, 3, nil, "code-y"),
@@ -1927,9 +2394,12 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq({'1. Syntax error', '2. Some warning'}, exec_lua [[
+ eq(
+ { '1. Syntax error', '2. Some warning' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3, nil, "code-x"),
make_warning("Some warning", 1, 1, 1, 3, nil, "code-y"),
@@ -1940,10 +2410,13 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
-- Suffix is rendered on the last line of a multiline diagnostic
- eq({'1. Syntax error', ' More context [code-x]'}, exec_lua [[
+ eq(
+ { '1. Syntax error', ' More context [code-x]' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error\nMore context", 0, 1, 0, 3, nil, "code-x"),
}
@@ -1953,14 +2426,19 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
- eq(".../diagnostic.lua:0: suffix: expected string|table|function, got number",
- pcall_err(exec_lua, [[ vim.diagnostic.open_float({ suffix = 42 }) ]]))
+ eq(
+ '.../diagnostic.lua:0: suffix: expected string|table|function, got number',
+ pcall_err(exec_lua, [[ vim.diagnostic.open_float({ suffix = 42 }) ]])
+ )
end)
it('works with the old signature', function()
- eq({'1. Syntax error'}, exec_lua [[
+ eq(
+ { '1. Syntax error' },
+ exec_lua [[
local diagnostics = {
make_error("Syntax error", 0, 1, 0, 3),
}
@@ -1970,7 +2448,8 @@ end)
local lines = vim.api.nvim_buf_get_lines(float_bufnr, 0, -1, false)
vim.api.nvim_win_close(winnr, true)
return lines
- ]])
+ ]]
+ )
end)
end)
@@ -2015,55 +2494,76 @@ end)
describe('match()', function()
it('matches a string', function()
- local msg = "ERROR: george.txt:19:84:Two plus two equals five"
+ local msg = 'ERROR: george.txt:19:84:Two plus two equals five'
local diagnostic = {
severity = exec_lua [[return vim.diagnostic.severity.ERROR]],
lnum = 18,
col = 83,
end_lnum = 18,
end_col = 83,
- message = "Two plus two equals five",
+ message = 'Two plus two equals five',
}
- eq(diagnostic, exec_lua([[
+ eq(
+ diagnostic,
+ exec_lua(
+ [[
return vim.diagnostic.match(..., "^(%w+): [^:]+:(%d+):(%d+):(.+)$", {"severity", "lnum", "col", "message"})
- ]], msg))
+ ]],
+ msg
+ )
+ )
end)
it('returns nil if the pattern fails to match', function()
- eq(NIL, exec_lua [[
+ eq(
+ NIL,
+ exec_lua [[
local msg = "The answer to life, the universe, and everything is"
return vim.diagnostic.match(msg, "This definitely will not match", {})
- ]])
+ ]]
+ )
end)
it('respects default values', function()
- local msg = "anna.txt:1:Happy families are all alike"
+ local msg = 'anna.txt:1:Happy families are all alike'
local diagnostic = {
severity = exec_lua [[return vim.diagnostic.severity.INFO]],
lnum = 0,
col = 0,
end_lnum = 0,
end_col = 0,
- message = "Happy families are all alike",
+ message = 'Happy families are all alike',
}
- eq(diagnostic, exec_lua([[
+ eq(
+ diagnostic,
+ exec_lua(
+ [[
return vim.diagnostic.match(..., "^[^:]+:(%d+):(.+)$", {"lnum", "message"}, nil, {severity = vim.diagnostic.severity.INFO})
- ]], msg))
+ ]],
+ msg
+ )
+ )
end)
it('accepts a severity map', function()
- local msg = "46:FATAL:Et tu, Brute?"
+ local msg = '46:FATAL:Et tu, Brute?'
local diagnostic = {
severity = exec_lua [[return vim.diagnostic.severity.ERROR]],
lnum = 45,
col = 0,
end_lnum = 45,
end_col = 0,
- message = "Et tu, Brute?",
+ message = 'Et tu, Brute?',
}
- eq(diagnostic, exec_lua([[
+ eq(
+ diagnostic,
+ exec_lua(
+ [[
return vim.diagnostic.match(..., "^(%d+):(%w+):(.+)$", {"lnum", "severity", "message"}, {FATAL = vim.diagnostic.severity.ERROR})
- ]], msg))
+ ]],
+ msg
+ )
+ )
end)
end)
@@ -2095,12 +2595,20 @@ end)
describe('handlers', function()
it('checks that a new handler is a table', function()
- matches([[.*handler: expected table, got string.*]], pcall_err(exec_lua, [[ vim.diagnostic.handlers.foo = "bar" ]]))
- matches([[.*handler: expected table, got function.*]], pcall_err(exec_lua, [[ vim.diagnostic.handlers.foo = function() end ]]))
+ matches(
+ [[.*handler: expected table, got string.*]],
+ pcall_err(exec_lua, [[ vim.diagnostic.handlers.foo = "bar" ]])
+ )
+ matches(
+ [[.*handler: expected table, got function.*]],
+ pcall_err(exec_lua, [[ vim.diagnostic.handlers.foo = function() end ]])
+ )
end)
it('can add new handlers', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
local handler_called = false
vim.diagnostic.handlers.test = {
show = function(namespace, bufnr, diagnostics, opts)
@@ -2117,11 +2625,14 @@ end)
make_warning("Warning", 0, 0, 0, 0),
})
return handler_called
- ]])
+ ]]
+ )
end)
it('can disable handlers by setting the corresponding option to false', function()
- eq(false, exec_lua [[
+ eq(
+ false,
+ exec_lua [[
local handler_called = false
vim.diagnostic.handlers.test = {
show = function(namespace, bufnr, diagnostics, opts)
@@ -2134,11 +2645,14 @@ end)
make_warning("Warning", 0, 0, 0, 0),
})
return handler_called
- ]])
+ ]]
+ )
end)
- it('always calls a handler\'s hide function if defined', function()
- eq({false, true}, exec_lua [[
+ it("always calls a handler's hide function if defined", function()
+ eq(
+ { false, true },
+ exec_lua [[
local hide_called = false
local show_called = false
vim.diagnostic.handlers.test = {
@@ -2158,11 +2672,14 @@ end)
})
vim.diagnostic.hide(diagnostic_ns, diagnostic_bufnr)
return {show_called, hide_called}
- ]])
+ ]]
+ )
end)
it('triggers the autocommand when diagnostics are set', function()
- eq({true, true}, exec_lua [[
+ eq(
+ { true, true },
+ exec_lua [[
-- Set a different buffer as current to test that <abuf> is being set properly in
-- DiagnosticChanged callbacks
local tmp = vim.api.nvim_create_buf(false, true)
@@ -2182,11 +2699,14 @@ end)
triggered[1] == diagnostic_bufnr,
triggered[2] == 1,
}
- ]])
- end)
+ ]]
+ )
+ end)
it('triggers the autocommand when diagnostics are cleared', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
local tmp = vim.api.nvim_create_buf(false, true)
vim.api.nvim_set_current_buf(tmp)
vim.g.diagnostic_autocmd_triggered = 0
@@ -2194,11 +2714,14 @@ end)
vim.api.nvim_buf_set_name(diagnostic_bufnr, "test | test")
vim.diagnostic.reset(diagnostic_ns, diagnostic_bufnr)
return vim.g.diagnostic_autocmd_triggered == diagnostic_bufnr
- ]])
- end)
+ ]]
+ )
+ end)
- it("checks if diagnostics are disabled in a buffer", function()
- eq({true, true, true , true}, exec_lua [[
+ it('checks if diagnostics are disabled in a buffer', function()
+ eq(
+ { true, true, true, true },
+ exec_lua [[
vim.diagnostic.set(diagnostic_ns, diagnostic_bufnr, {
make_error('Diagnostic #1', 1, 1, 1, 1),
})
@@ -2210,9 +2733,12 @@ end)
vim.diagnostic.is_disabled(diagnostic_bufnr, diagnostic_ns),
vim.diagnostic.is_disabled(_, diagnostic_ns),
}
- ]])
+ ]]
+ )
- eq({false, false, false , false}, exec_lua [[
+ eq(
+ { false, false, false, false },
+ exec_lua [[
vim.diagnostic.enable()
return {
vim.diagnostic.is_disabled(),
@@ -2220,7 +2746,8 @@ end)
vim.diagnostic.is_disabled(diagnostic_bufnr, diagnostic_ns),
vim.diagnostic.is_disabled(_, diagnostic_ns),
}
- ]])
+ ]]
+ )
end)
end)
end)
diff --git a/test/functional/lua/ffi_spec.lua b/test/functional/lua/ffi_spec.lua
index 3a37b18cd1..c9e8e9d4ca 100644
--- a/test/functional/lua/ffi_spec.lua
+++ b/test/functional/lua/ffi_spec.lua
@@ -11,7 +11,9 @@ describe('ffi.cdef', function()
pending('missing LuaJIT FFI')
end
- eq(12, exec_lua[[
+ eq(
+ 12,
+ exec_lua [[
local ffi = require('ffi')
ffi.cdef('int curwin_col_off(void);')
@@ -19,9 +21,12 @@ describe('ffi.cdef', function()
vim.cmd('set number numberwidth=4 signcolumn=yes:4')
return ffi.C.curwin_col_off()
- ]])
+ ]]
+ )
- eq(20, exec_lua[=[
+ eq(
+ 20,
+ exec_lua [=[
local ffi = require('ffi')
ffi.cdef[[
@@ -38,7 +43,7 @@ describe('ffi.cdef', function()
char *out,
size_t outlen,
char *fmt,
- char *opt_name,
+ int opt_idx,
int opt_scope,
int fillchar,
int maxwidth,
@@ -53,7 +58,7 @@ describe('ffi.cdef', function()
ffi.new('char[1024]'),
1024,
ffi.cast('char*', 'StatusLineOfLength20'),
- nil,
+ -1,
0,
0,
0,
@@ -61,15 +66,19 @@ describe('ffi.cdef', function()
nil,
nil
)
- ]=])
+ ]=]
+ )
-- Check that extern symbols are exported and accessible
- eq(true, exec_lua[[
+ eq(
+ true,
+ exec_lua [[
local ffi = require('ffi')
ffi.cdef('uint64_t display_tick;')
return ffi.C.display_tick >= 0
- ]])
+ ]]
+ )
end)
end)
diff --git a/test/functional/lua/filetype_spec.lua b/test/functional/lua/filetype_spec.lua
index b3d95e1c7f..8b0e0a8beb 100644
--- a/test/functional/lua/filetype_spec.lua
+++ b/test/functional/lua/filetype_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local exec_lua = helpers.exec_lua
local eq = helpers.eq
-local meths = helpers.meths
+local api = helpers.api
local clear = helpers.clear
local pathroot = helpers.pathroot
local command = helpers.command
@@ -19,18 +19,23 @@ describe('vim.filetype', function()
end)
it('works with extensions', function()
- eq('radicalscript', exec_lua [[
+ eq(
+ 'radicalscript',
+ exec_lua [[
vim.filetype.add({
extension = {
rs = 'radicalscript',
},
})
return vim.filetype.match({ filename = 'main.rs' })
- ]])
+ ]]
+ )
end)
it('prioritizes filenames over extensions', function()
- eq('somethingelse', exec_lua [[
+ eq(
+ 'somethingelse',
+ exec_lua [[
vim.filetype.add({
extension = {
rs = 'radicalscript',
@@ -40,20 +45,27 @@ describe('vim.filetype', function()
},
})
return vim.filetype.match({ filename = 'main.rs' })
- ]])
+ ]]
+ )
end)
it('works with filenames', function()
- eq('nim', exec_lua [[
+ eq(
+ 'nim',
+ exec_lua [[
vim.filetype.add({
filename = {
['s_O_m_e_F_i_l_e'] = 'nim',
},
})
return vim.filetype.match({ filename = 's_O_m_e_F_i_l_e' })
- ]])
+ ]]
+ )
- eq('dosini', exec_lua([[
+ eq(
+ 'dosini',
+ exec_lua(
+ [[
local root = ...
vim.filetype.add({
filename = {
@@ -62,11 +74,17 @@ describe('vim.filetype', function()
},
})
return vim.filetype.match({ filename = root .. '/.config/fun/config' })
- ]], root))
+ ]],
+ root
+ )
+ )
end)
it('works with patterns', function()
- eq('markdown', exec_lua([[
+ eq(
+ 'markdown',
+ exec_lua(
+ [[
local root = ...
vim.env.HOME = '/a-funky+home%dir'
vim.filetype.add({
@@ -75,13 +93,18 @@ describe('vim.filetype', function()
}
})
return vim.filetype.match({ filename = '~/blog/why_neovim_is_awesome.txt' })
- ]], root))
+ ]],
+ root
+ )
+ )
end)
it('works with functions', function()
command('new')
command('file relevant_to_me')
- eq('foss', exec_lua [[
+ eq(
+ 'foss',
+ exec_lua [[
vim.filetype.add({
pattern = {
["relevant_to_(%a+)"] = function(path, bufnr, capture)
@@ -92,26 +115,33 @@ describe('vim.filetype', function()
}
})
return vim.filetype.match({ buf = 0 })
- ]])
+ ]]
+ )
end)
it('works with contents #22180', function()
- eq('sh', exec_lua [[
+ eq(
+ 'sh',
+ exec_lua [[
-- Needs to be set so detect#sh doesn't fail
vim.g.ft_ignore_pat = '\\.\\(Z\\|gz\\|bz2\\|zip\\|tgz\\)$'
return vim.filetype.match({ contents = { '#!/usr/bin/env bash' } })
- ]])
+ ]]
+ )
end)
it('considers extension mappings when matching from hashbang', function()
- eq('fooscript', exec_lua [[
+ eq(
+ 'fooscript',
+ exec_lua [[
vim.filetype.add({
extension = {
foo = 'fooscript',
}
})
return vim.filetype.match({ contents = { '#!/usr/bin/env foo' } })
- ]])
+ ]]
+ )
end)
it('can get default option values for filetypes via vim.filetype.get_option()', function()
@@ -120,20 +150,21 @@ describe('vim.filetype', function()
for ft, opts in pairs {
lua = { commentstring = '-- %s' },
vim = { commentstring = '"%s' },
- man = { tagfunc = 'v:lua.require\'man\'.goto_tag' },
- xml = { formatexpr = 'xmlformat#Format()' }
+ man = { tagfunc = "v:lua.require'man'.goto_tag" },
+ xml = { formatexpr = 'xmlformat#Format()' },
} do
for option, value in pairs(opts) do
eq(value, exec_lua([[ return vim.filetype.get_option(...) ]], ft, option))
end
end
-
end)
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.get_option_value('filetype', {}))
+ clear({
+ args = { '--clean', '--cmd', 'autocmd BufRead *.md set filetype=notmarkdown', 'README.md' },
+ })
+ eq('notmarkdown', api.nvim_get_option_value('filetype', {}))
end)
end)
diff --git a/test/functional/lua/fs_spec.lua b/test/functional/lua/fs_spec.lua
index 6bdb9ed79d..6821fe3c5e 100644
--- a/test/functional/lua/fs_spec.lua
+++ b/test/functional/lua/fs_spec.lua
@@ -1,5 +1,4 @@
local helpers = require('test.functional.helpers')(after_each)
-local uv = require('luv')
local clear = helpers.clear
local exec_lua = helpers.exec_lua
@@ -7,8 +6,8 @@ local eq = helpers.eq
local mkdir_p = helpers.mkdir_p
local rmdir = helpers.rmdir
local nvim_dir = helpers.nvim_dir
-local test_build_dir = helpers.test_build_dir
-local test_source_path = helpers.test_source_path
+local test_build_dir = helpers.paths.test_build_dir
+local test_source_path = helpers.paths.test_source_path
local nvim_prog = helpers.nvim_prog
local is_os = helpers.is_os
local mkdir = helpers.mkdir
@@ -55,40 +54,33 @@ describe('vim.fs', function()
it('works', function()
local test_dir = nvim_dir .. '/test'
mkdir_p(test_dir)
- local dirs = exec_lua([[
- local test_dir, test_build_dir = ...
- local dirs = {}
- for dir in vim.fs.parents(test_dir .. "/foo.txt") do
- dirs[#dirs + 1] = dir
- if dir == test_build_dir then
- break
- end
+ local dirs = {}
+ for dir in vim.fs.parents(test_dir .. '/foo.txt') do
+ dirs[#dirs + 1] = dir
+ if dir == test_build_dir then
+ break
end
- return dirs
- ]], test_dir, test_build_dir)
- eq({test_dir, nvim_dir, test_build_dir}, dirs)
+ end
+ eq({ test_dir, nvim_dir, test_build_dir }, dirs)
rmdir(test_dir)
end)
end)
describe('dirname()', function()
it('works', function()
- eq(test_build_dir, exec_lua([[
- local nvim_dir = ...
- return vim.fs.dirname(nvim_dir)
- ]], nvim_dir))
+ eq(test_build_dir, vim.fs.dirname(nvim_dir))
local function test_paths(paths)
for _, path in ipairs(paths) do
eq(
- exec_lua([[
+ exec_lua(
+ [[
local path = ...
return vim.fn.fnamemodify(path,':h'):gsub('\\', '/')
- ]], path),
- exec_lua([[
- local path = ...
- return vim.fs.dirname(path)
- ]], path),
+ ]],
+ path
+ ),
+ vim.fs.dirname(path),
path
)
end
@@ -103,23 +95,19 @@ describe('vim.fs', function()
describe('basename()', function()
it('works', function()
-
- eq(nvim_prog_basename, exec_lua([[
- local nvim_prog = ...
- return vim.fs.basename(nvim_prog)
- ]], nvim_prog))
+ eq(nvim_prog_basename, vim.fs.basename(nvim_prog))
local function test_paths(paths)
for _, path in ipairs(paths) do
eq(
- exec_lua([[
+ exec_lua(
+ [[
local path = ...
return vim.fn.fnamemodify(path,':t'):gsub('\\', '/')
- ]], path),
- exec_lua([[
- local path = ...
- return vim.fs.basename(path)
- ]], path),
+ ]],
+ path
+ ),
+ vim.fs.basename(path),
path
)
end
@@ -145,7 +133,10 @@ describe('vim.fs', function()
end)
it('works', function()
- eq(true, exec_lua([[
+ eq(
+ true,
+ exec_lua(
+ [[
local dir, nvim = ...
for name, type in vim.fs.dir(dir) do
if name == nvim and type == 'file' then
@@ -153,7 +144,11 @@ describe('vim.fs', function()
end
end
return false
- ]], nvim_dir, nvim_prog_basename))
+ ]],
+ nvim_dir,
+ nvim_prog_basename
+ )
+ )
end)
it('works with opts.depth and opts.skip', function()
@@ -171,7 +166,8 @@ describe('vim.fs', function()
io.open('testd/a/b/c/c4', 'w'):close()
local function run(dir, depth, skip)
- local r = exec_lua([[
+ local r = exec_lua(
+ [[
local dir, depth, skip = ...
local r = {}
local skip_f
@@ -186,7 +182,11 @@ describe('vim.fs', function()
r[name] = type_
end
return r
- ]], dir, depth, skip)
+ ]],
+ dir,
+ depth,
+ skip
+ )
return r
end
@@ -212,7 +212,7 @@ describe('vim.fs', function()
exp['a/b/c'] = 'directory'
eq(exp, run('testd', 3))
- eq(exp, run('testd', 999, {'a/b/c'}))
+ eq(exp, run('testd', 999, { 'a/b/c' }))
exp['a/b/c/a4'] = 'file'
exp['a/b/c/b4'] = 'file'
@@ -224,88 +224,92 @@ describe('vim.fs', function()
describe('find()', function()
it('works', function()
- eq({test_build_dir .. "/build"}, exec_lua([[
- local dir = ...
- return vim.fs.find('build', { path = dir, upward = true, type = 'directory' })
- ]], nvim_dir))
- eq({nvim_prog}, exec_lua([[
- local dir, nvim = ...
- return vim.fs.find(nvim, { path = dir, type = 'file' })
- ]], test_build_dir, nvim_prog_basename))
- eq({nvim_dir}, exec_lua([[
- local dir = ...
- local parent, name = dir:match('^(.*/)([^/]+)$')
- return vim.fs.find(name, { path = parent, upward = true, type = 'directory' })
- ]], nvim_dir))
+ eq(
+ { test_build_dir .. '/build' },
+ vim.fs.find('build', { path = nvim_dir, upward = true, type = 'directory' })
+ )
+ eq({ nvim_prog }, vim.fs.find(nvim_prog_basename, { path = test_build_dir, type = 'file' }))
+
+ local parent, name = nvim_dir:match('^(.*/)([^/]+)$')
+ eq({ nvim_dir }, vim.fs.find(name, { path = parent, upward = true, type = 'directory' }))
end)
it('accepts predicate as names', function()
- 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)
- ]], nvim_dir))
- eq({nvim_prog}, exec_lua([[
- local dir, nvim = ...
- return vim.fs.find(function(x) return x == nvim end, { path = dir, type = 'file' })
- ]], test_build_dir, nvim_prog_basename))
- eq({}, exec_lua([[
- local dir = ...
- local opts = { path = dir, upward = true, type = 'directory' }
- return vim.fs.find(function(x) return x == 'no-match' end, opts)
- ]], nvim_dir))
+ local opts = { path = nvim_dir, upward = true, type = 'directory' }
+ eq(
+ { test_build_dir .. '/build' },
+ vim.fs.find(function(x)
+ return x == 'build'
+ end, opts)
+ )
+ eq(
+ { nvim_prog },
+ vim.fs.find(function(x)
+ return x == nvim_prog_basename
+ end, { path = test_build_dir, type = 'file' })
+ )
+ eq(
+ {},
+ vim.fs.find(function(x)
+ return x == 'no-match'
+ end, opts)
+ )
+
+ opts = { path = test_source_path .. '/contrib', limit = math.huge }
eq(
- exec_lua([[
+ exec_lua(
+ [[
local dir = ...
return vim.tbl_map(vim.fs.basename, vim.fn.glob(dir..'/contrib/*', false, true))
- ]], test_source_path),
- exec_lua([[
- local dir = ...
- local opts = { path = dir .. "/contrib", limit = math.huge }
- return vim.tbl_map(vim.fs.basename, vim.fs.find(function(_, d) return d:match('[\\/]contrib$') end, opts))
- ]], test_source_path))
+ ]],
+ test_source_path
+ ),
+ vim.tbl_map(
+ vim.fs.basename,
+ vim.fs.find(function(_, d)
+ return d:match('[\\/]contrib$')
+ end, opts)
+ )
+ )
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))
+ eq('foo/bar/baz', vim.fs.joinpath('foo', 'bar', 'baz'))
+ eq('foo/bar/baz', vim.fs.joinpath('foo', '/bar/', '/baz'))
end)
end)
describe('normalize()', function()
it('works with backward slashes', function()
- eq('C:/Users/jdoe', exec_lua [[ return vim.fs.normalize('C:\\Users\\jdoe') ]])
+ eq('C:/Users/jdoe', vim.fs.normalize('C:\\Users\\jdoe'))
end)
it('removes trailing /', function()
- eq('/home/user', exec_lua [[ return vim.fs.normalize('/home/user/') ]])
+ eq('/home/user', vim.fs.normalize('/home/user/'))
end)
it('works with /', function()
- eq('/', exec_lua [[ return vim.fs.normalize('/') ]])
+ eq('/', vim.fs.normalize('/'))
end)
it('works with ~', function()
- eq(
- exec_lua([[
- local home = ...
- return home .. '/src/foo'
- ]], vim.fs.normalize(uv.os_homedir())),
- exec_lua [[ return vim.fs.normalize('~/src/foo') ]])
+ eq(vim.fs.normalize(vim.uv.os_homedir()) .. '/src/foo', vim.fs.normalize('~/src/foo'))
end)
it('works with environment variables', function()
local xdg_config_home = test_build_dir .. '/.config'
- eq(xdg_config_home .. '/nvim', exec_lua([[
+ eq(
+ xdg_config_home .. '/nvim',
+ exec_lua(
+ [[
vim.env.XDG_CONFIG_HOME = ...
return vim.fs.normalize('$XDG_CONFIG_HOME/nvim')
- ]], xdg_config_home))
+ ]],
+ xdg_config_home
+ )
+ )
end)
if is_os('win') then
it('Last slash is not truncated from root drive', function()
- eq('C:/', exec_lua [[ return vim.fs.normalize('C:/') ]])
+ eq('C:/', vim.fs.normalize('C:/'))
end)
end
end)
diff --git a/test/functional/plugin/lsp/watchfiles_spec.lua b/test/functional/lua/glob_spec.lua
index a8260e0c98..1eac037575 100644
--- a/test/functional/plugin/lsp/watchfiles_spec.lua
+++ b/test/functional/lua/glob_spec.lua
@@ -1,14 +1,20 @@
local helpers = require('test.functional.helpers')(after_each)
-
local eq = helpers.eq
local exec_lua = helpers.exec_lua
-describe('vim.lsp._watchfiles', function()
+describe('glob', function()
before_each(helpers.clear)
after_each(helpers.clear)
local match = function(...)
- return exec_lua('return require("vim.lsp._watchfiles")._match(...)', ...)
+ return exec_lua(
+ [[
+ local pattern = select(1, ...)
+ local str = select(2, ...)
+ return require("vim.glob").to_lpeg(pattern):match(str) ~= nil
+ ]],
+ ...
+ )
end
describe('glob matching', function()
@@ -61,18 +67,16 @@ describe('vim.lsp._watchfiles', function()
eq(true, match('dir/*/file.txt', 'dir/subdir/file.txt'))
eq(false, match('dir/*/file.txt', 'dir/subdir/subdir/file.txt'))
- -- TODO: The spec does not describe this, but VSCode only interprets ** when it's by
+ -- The spec does not describe this, but VSCode only interprets ** when it's by
-- itself in a path segment, and otherwise interprets ** as consecutive * directives.
- -- The following tests show how this behavior should work, but is not yet fully implemented.
- -- Currently, "a**" parses incorrectly as "a" "**" and "**a" parses correctly as "*" "*" "a".
-- see: https://github.com/microsoft/vscode/blob/eef30e7165e19b33daa1e15e92fa34ff4a5df0d3/src/vs/base/common/glob.ts#L112
eq(true, match('a**', 'abc')) -- '**' should parse as two '*'s when not by itself in a path segment
eq(true, match('**c', 'abc'))
- -- eq(false, match('a**', 'ab')) -- each '*' should still represent at least one character
+ eq(false, match('a**', 'ab')) -- each '*' should still represent at least one character
eq(false, match('**c', 'bc'))
eq(true, match('a**', 'abcd'))
eq(true, match('**d', 'abcd'))
- -- eq(false, match('a**', 'abc/d'))
+ eq(false, match('a**', 'abc/d'))
eq(false, match('**d', 'abc/d'))
end)
diff --git a/test/functional/lua/help_spec.lua b/test/functional/lua/help_spec.lua
deleted file mode 100644
index ef1b8ebf3f..0000000000
--- a/test/functional/lua/help_spec.lua
+++ /dev/null
@@ -1,53 +0,0 @@
--- Tests for gen_help_html.lua. Validates :help tags/links and HTML doc generation.
---
--- TODO: extract parts of gen_help_html.lua into Nvim stdlib?
-
-local helpers = require('test.functional.helpers')(after_each)
-local clear = helpers.clear
-local exec_lua = helpers.exec_lua
-local eq = helpers.eq
-local ok = helpers.ok
-
-if helpers.skip(helpers.is_ci('cirrus'), 'No need to run this on Cirrus') then return end
-
-describe(':help docs', function()
- before_each(clear)
- it('validate', function()
- -- If this test fails, try these steps (in order):
- -- 1. Fix/cleanup the :help docs.
- -- 2. Fix the parser: https://github.com/neovim/tree-sitter-vimdoc
- -- 3. File a parser bug, and adjust the tolerance of this test in the meantime.
-
- local rv = exec_lua([[return require('scripts.gen_help_html').validate('./build/runtime/doc')]])
- -- Check that we actually found helpfiles.
- ok(rv.helpfiles > 100, '>100 :help files', rv.helpfiles)
-
- eq({}, rv.parse_errors, 'no parse errors')
- eq(0, rv.err_count, 'no parse errors')
- eq({}, rv.invalid_links, 'invalid tags in :help docs')
- eq({}, rv.invalid_urls, 'invalid URLs in :help docs')
- eq({}, rv.invalid_spelling, 'invalid spelling in :help docs (see spell_dict in scripts/gen_help_html.lua)')
- end)
-
- it('gen_help_html.lua generates HTML', function()
- -- 1. Test that gen_help_html.lua actually works.
- -- 2. Test that parse errors did not increase wildly. Because we explicitly test only a few
- -- :help files, we can be precise about the tolerances here.
-
- local tmpdir = exec_lua('return vim.fs.dirname(vim.fn.tempname())')
- -- Because gen() is slow (~30s), this test is limited to a few files.
- local rv = exec_lua([[
- local to_dir = ...
- return require('scripts.gen_help_html').gen(
- './build/runtime/doc',
- to_dir,
- { 'pi_health.txt', 'help.txt', 'index.txt', 'nvim.txt', }
- )
- ]],
- tmpdir
- )
- eq(4, #rv.helpfiles)
- eq(0, rv.err_count, 'parse errors in :help docs')
- eq({}, rv.invalid_links, 'invalid tags in :help docs')
- end)
-end)
diff --git a/test/functional/lua/highlight_spec.lua b/test/functional/lua/highlight_spec.lua
index 8e499f1e79..197f3139f3 100644
--- a/test/functional/lua/highlight_spec.lua
+++ b/test/functional/lua/highlight_spec.lua
@@ -1,9 +1,11 @@
local helpers = require('test.functional.helpers')(after_each)
local exec_lua = helpers.exec_lua
local eq = helpers.eq
+local neq = helpers.neq
local eval = helpers.eval
local command = helpers.command
local clear = helpers.clear
+local api = helpers.api
describe('vim.highlight.on_yank', function()
before_each(function()
@@ -16,7 +18,7 @@ describe('vim.highlight.on_yank', function()
vim.highlight.on_yank({timeout = 10, on_macro = true, event = {operator = "y", regtype = "v"}})
vim.cmd('bwipeout!')
]])
- helpers.sleep(10)
+ vim.uv.sleep(10)
helpers.feed('<cr>') -- avoid hang if error message exists
eq('', eval('v:errmsg'))
end)
@@ -31,4 +33,34 @@ describe('vim.highlight.on_yank', function()
]])
eq('', eval('v:errmsg'))
end)
+
+ it('does not show in another window', function()
+ command('vsplit')
+ exec_lua([[
+ vim.api.nvim_buf_set_mark(0,"[",1,1,{})
+ vim.api.nvim_buf_set_mark(0,"]",1,1,{})
+ vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}})
+ ]])
+ neq({}, api.nvim_win_get_ns(0))
+ command('wincmd w')
+ eq({}, api.nvim_win_get_ns(0))
+ end)
+
+ it('removes old highlight if new one is created before old one times out', function()
+ command('vnew')
+ exec_lua([[
+ vim.api.nvim_buf_set_mark(0,"[",1,1,{})
+ vim.api.nvim_buf_set_mark(0,"]",1,1,{})
+ vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}})
+ ]])
+ neq({}, api.nvim_win_get_ns(0))
+ command('wincmd w')
+ exec_lua([[
+ vim.api.nvim_buf_set_mark(0,"[",1,1,{})
+ vim.api.nvim_buf_set_mark(0,"]",1,1,{})
+ vim.highlight.on_yank({timeout = math.huge, on_macro = true, event = {operator = "y"}})
+ ]])
+ command('wincmd w')
+ eq({}, api.nvim_win_get_ns(0))
+ end)
end)
diff --git a/test/functional/lua/inspector_spec.lua b/test/functional/lua/inspector_spec.lua
index c369956e56..ad8b5a45a8 100644
--- a/test/functional/lua/inspector_spec.lua
+++ b/test/functional/lua/inspector_spec.lua
@@ -46,9 +46,9 @@ describe('vim.inspect_pos', function()
hl_group_link = 'Normal',
ns_id = 1,
priority = 4096,
- right_gravity = true
+ right_gravity = true,
},
- row = 0
+ row = 0,
},
{
col = 10,
@@ -63,10 +63,10 @@ describe('vim.inspect_pos', function()
hl_group_link = 'Normal',
ns_id = 2,
priority = 4096,
- right_gravity = true
+ right_gravity = true,
},
- row = 0
- }
+ row = 0,
+ },
},
treesitter = {},
semantic_tokens = {},
diff --git a/test/functional/lua/iter_spec.lua b/test/functional/lua/iter_spec.lua
index ffa28e7b11..8d6cf1264b 100644
--- a/test/functional/lua/iter_spec.lua
+++ b/test/functional/lua/iter_spec.lua
@@ -6,11 +6,11 @@ local pcall_err = helpers.pcall_err
describe('vim.iter', function()
it('new() on iterable class instance', function()
local rb = vim.ringbuf(3)
- rb:push("a")
- rb:push("b")
+ rb:push('a')
+ rb:push('b')
local it = vim.iter(rb)
- eq({"a", "b"}, it:totable())
+ eq({ 'a', 'b' }, it:totable())
end)
it('filter()', function()
@@ -20,18 +20,43 @@ describe('vim.iter', function()
local t = { 1, 2, 3, 4, 5 }
eq({ 1, 3, 5 }, vim.iter(t):filter(odd):totable())
- eq({ 2, 4 }, vim.iter(t):filter(function(v) return not odd(v) end):totable())
- eq({}, vim.iter(t):filter(function(v) return v > 5 end):totable())
+ eq(
+ { 2, 4 },
+ vim
+ .iter(t)
+ :filter(function(v)
+ return not odd(v)
+ end)
+ :totable()
+ )
+ eq(
+ {},
+ vim
+ .iter(t)
+ :filter(function(v)
+ return v > 5
+ end)
+ :totable()
+ )
do
local it = vim.iter(ipairs(t))
- it:filter(function(i, v) return i > 1 and v < 5 end)
- it:map(function(_, v) return v * 2 end)
+ it:filter(function(i, v)
+ return i > 1 and v < 5
+ end)
+ it:map(function(_, v)
+ return v * 2
+ end)
eq({ 4, 6, 8 }, it:totable())
end
local it = vim.iter(string.gmatch('the quick brown fox', '%w+'))
- eq({'the', 'fox'}, it:filter(function(s) return #s <= 3 end):totable())
+ eq(
+ { 'the', 'fox' },
+ it:filter(function(s)
+ return #s <= 3
+ end):totable()
+ )
end)
it('map()', function()
@@ -39,11 +64,11 @@ describe('vim.iter', function()
eq(
{ 2, 4, 6, 8, 10 },
vim
- .iter(t)
- :map(function(v)
- return 2 * v
- end)
- :totable()
+ .iter(t)
+ :map(function(v)
+ return 2 * v
+ end)
+ :totable()
)
local it = vim.gsplit(
@@ -59,21 +84,25 @@ describe('vim.iter', function()
eq(
{ 'Lion 2', 'Lion 4' },
vim
- .iter(it)
- :map(function(s)
- local lnum = s:match('(%d+)')
- if lnum and tonumber(lnum) % 2 == 0 then
- return vim.trim(s:gsub('Line', 'Lion'))
- end
- end)
- :totable()
+ .iter(it)
+ :map(function(s)
+ local lnum = s:match('(%d+)')
+ if lnum and tonumber(lnum) % 2 == 0 then
+ return vim.trim(s:gsub('Line', 'Lion'))
+ end
+ end)
+ :totable()
)
end)
it('for loops', function()
- local t = {1, 2, 3, 4, 5}
+ local t = { 1, 2, 3, 4, 5 }
local acc = 0
- for v in vim.iter(t):map(function(v) return v * 3 end) do
+ for v in
+ vim.iter(t):map(function(v)
+ return v * 3
+ end)
+ do
acc = acc + v
end
eq(45, acc)
@@ -81,18 +110,27 @@ describe('vim.iter', function()
it('totable()', function()
do
- local it = vim.iter({1, 2, 3}):map(function(v) return v, v*v end)
- eq({{1, 1}, {2, 4}, {3, 9}}, it:totable())
+ local it = vim.iter({ 1, 2, 3 }):map(function(v)
+ return v, v * v
+ end)
+ eq({ { 1, 1 }, { 2, 4 }, { 3, 9 } }, it:totable())
end
do
local it = vim.iter(string.gmatch('1,4,lol,17,blah,2,9,3', '%d+')):map(tonumber)
- eq({1, 4, 17, 2, 9, 3}, it:totable())
+ eq({ 1, 4, 17, 2, 9, 3 }, it:totable())
end
end)
+ it('join()', function()
+ eq('1, 2, 3', vim.iter({ 1, 2, 3 }):join(', '))
+ eq('a|b|c|d', vim.iter(vim.gsplit('a|b|c|d', '|')):join('|'))
+ end)
+
it('next()', function()
- local it = vim.iter({1, 2, 3}):map(function(v) return 2 * v end)
+ local it = vim.iter({ 1, 2, 3 }):map(function(v)
+ return 2 * v
+ end)
eq(2, it:next())
eq(4, it:next())
eq(6, it:next())
@@ -100,19 +138,19 @@ describe('vim.iter', function()
end)
it('rev()', function()
- eq({3, 2, 1}, vim.iter({1, 2, 3}):rev():totable())
+ eq({ 3, 2, 1 }, vim.iter({ 1, 2, 3 }):rev():totable())
- local it = vim.iter(string.gmatch("abc", "%w"))
+ local it = vim.iter(string.gmatch('abc', '%w'))
matches('rev%(%) requires a list%-like table', pcall_err(it.rev, it))
end)
it('skip()', function()
do
- local t = {4, 3, 2, 1}
+ local t = { 4, 3, 2, 1 }
eq(t, vim.iter(t):skip(0):totable())
- eq({3, 2, 1}, vim.iter(t):skip(1):totable())
- eq({2, 1}, vim.iter(t):skip(2):totable())
- eq({1}, vim.iter(t):skip(#t - 1):totable())
+ eq({ 3, 2, 1 }, vim.iter(t):skip(1):totable())
+ eq({ 2, 1 }, vim.iter(t):skip(2):totable())
+ eq({ 1 }, vim.iter(t):skip(#t - 1):totable())
eq({}, vim.iter(t):skip(#t):totable())
eq({}, vim.iter(t):skip(#t + 1):totable())
end
@@ -121,10 +159,10 @@ describe('vim.iter', function()
local function skip(n)
return vim.iter(vim.gsplit('a|b|c|d', '|')):skip(n):totable()
end
- eq({'a', 'b', 'c', 'd'}, skip(0))
- eq({'b', 'c', 'd'}, skip(1))
- eq({'c', 'd'}, skip(2))
- eq({'d'}, skip(3))
+ eq({ 'a', 'b', 'c', 'd' }, skip(0))
+ eq({ 'b', 'c', 'd' }, skip(1))
+ eq({ 'c', 'd' }, skip(2))
+ eq({ 'd' }, skip(3))
eq({}, skip(4))
eq({}, skip(5))
end
@@ -132,11 +170,11 @@ describe('vim.iter', function()
it('skipback()', function()
do
- local t = {4, 3, 2, 1}
+ local t = { 4, 3, 2, 1 }
eq(t, vim.iter(t):skipback(0):totable())
- eq({4, 3, 2}, vim.iter(t):skipback(1):totable())
- eq({4, 3}, vim.iter(t):skipback(2):totable())
- eq({4}, vim.iter(t):skipback(#t - 1):totable())
+ eq({ 4, 3, 2 }, vim.iter(t):skipback(1):totable())
+ eq({ 4, 3 }, vim.iter(t):skipback(2):totable())
+ eq({ 4 }, vim.iter(t):skipback(#t - 1):totable())
eq({}, vim.iter(t):skipback(#t):totable())
eq({}, vim.iter(t):skipback(#t + 1):totable())
end
@@ -146,14 +184,14 @@ describe('vim.iter', function()
end)
it('slice()', function()
- local t = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
- eq({3, 4, 5, 6, 7}, vim.iter(t):slice(3, 7):totable())
+ local t = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }
+ eq({ 3, 4, 5, 6, 7 }, vim.iter(t):slice(3, 7):totable())
eq({}, vim.iter(t):slice(6, 5):totable())
eq({}, vim.iter(t):slice(0, 0):totable())
- eq({1}, vim.iter(t):slice(1, 1):totable())
- eq({1, 2}, vim.iter(t):slice(1, 2):totable())
- eq({10}, vim.iter(t):slice(10, 10):totable())
- eq({8, 9, 10}, vim.iter(t):slice(8, 11):totable())
+ eq({ 1 }, vim.iter(t):slice(1, 1):totable())
+ eq({ 1, 2 }, vim.iter(t):slice(1, 2):totable())
+ eq({ 10 }, vim.iter(t):slice(10, 10):totable())
+ eq({ 8, 9, 10 }, vim.iter(t):slice(8, 11):totable())
local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
matches('slice%(%) requires a list%-like table', pcall_err(it.slice, it, 1, 3))
@@ -161,7 +199,7 @@ describe('vim.iter', function()
it('nth()', function()
do
- local t = {4, 3, 2, 1}
+ local t = { 4, 3, 2, 1 }
eq(nil, vim.iter(t):nth(0))
eq(4, vim.iter(t):nth(1))
eq(3, vim.iter(t):nth(2))
@@ -185,7 +223,7 @@ describe('vim.iter', function()
it('nthback()', function()
do
- local t = {4, 3, 2, 1}
+ local t = { 4, 3, 2, 1 }
eq(nil, vim.iter(t):nthback(0))
eq(1, vim.iter(t):nthback(1))
eq(2, vim.iter(t):nthback(2))
@@ -198,6 +236,33 @@ describe('vim.iter', function()
matches('skipback%(%) requires a list%-like table', pcall_err(it.nthback, it, 1))
end)
+ it('take()', function()
+ do
+ local t = { 4, 3, 2, 1 }
+ eq({}, vim.iter(t):take(0):totable())
+ eq({ 4 }, vim.iter(t):take(1):totable())
+ eq({ 4, 3 }, vim.iter(t):take(2):totable())
+ eq({ 4, 3, 2 }, vim.iter(t):take(3):totable())
+ eq({ 4, 3, 2, 1 }, vim.iter(t):take(4):totable())
+ eq({ 4, 3, 2, 1 }, vim.iter(t):take(5):totable())
+ end
+
+ do
+ local t = { 4, 3, 2, 1 }
+ local it = vim.iter(t)
+ eq({ 4, 3 }, it:take(2):totable())
+ -- tail is already set from the previous take()
+ eq({ 4, 3 }, it:take(3):totable())
+ end
+
+ do
+ local it = vim.iter(vim.gsplit('a|b|c|d', '|'))
+ eq({ 'a', 'b' }, it:take(2):totable())
+ -- non-array iterators are consumed by take()
+ eq({}, it:take(2):totable())
+ end
+ end)
+
it('any()', function()
local function odd(v)
return v % 2 ~= 0
@@ -214,8 +279,18 @@ describe('vim.iter', function()
end
do
- eq(true, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'd' end))
- eq(false, vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s) return s == 'e' end))
+ eq(
+ true,
+ vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s)
+ return s == 'd'
+ end)
+ )
+ eq(
+ false,
+ vim.iter(vim.gsplit('a|b|c|d', '|')):any(function(s)
+ return s == 'e'
+ end)
+ )
end
end)
@@ -235,8 +310,18 @@ describe('vim.iter', function()
end
do
- eq(true, vim.iter(vim.gsplit('a|a|a|a', '|')):all(function(s) return s == 'a' end))
- eq(false, vim.iter(vim.gsplit('a|a|a|b', '|')):all(function(s) return s == 'a' end))
+ eq(
+ true,
+ vim.iter(vim.gsplit('a|a|a|a', '|')):all(function(s)
+ return s == 'a'
+ end)
+ )
+ eq(
+ false,
+ vim.iter(vim.gsplit('a|a|a|b', '|')):all(function(s)
+ return s == 'a'
+ end)
+ )
end
end)
@@ -248,10 +333,10 @@ describe('vim.iter', function()
it('enumerate()', function()
local it = vim.iter(vim.gsplit('abc', '')):enumerate()
- eq({1, 'a'}, {it:next()})
- eq({2, 'b'}, {it:next()})
- eq({3, 'c'}, {it:next()})
- eq({}, {it:next()})
+ eq({ 1, 'a' }, { it:next() })
+ eq({ 2, 'b' }, { it:next() })
+ eq({ 3, 'c' }, { it:next() })
+ eq({}, { it:next() })
end)
it('peek()', function()
@@ -269,14 +354,21 @@ describe('vim.iter', function()
end)
it('find()', function()
- local t = {3, 6, 9, 12}
+ local t = { 3, 6, 9, 12 }
eq(12, vim.iter(t):find(12))
eq(nil, vim.iter(t):find(15))
- eq(12, vim.iter(t):find(function(v) return v % 4 == 0 end))
+ eq(
+ 12,
+ vim.iter(t):find(function(v)
+ return v % 4 == 0
+ end)
+ )
do
local it = vim.iter(t)
- local pred = function(v) return v % 3 == 0 end
+ local pred = function(v)
+ return v % 3 == 0
+ end
eq(3, it:find(pred))
eq(6, it:find(pred))
eq(9, it:find(pred))
@@ -286,7 +378,9 @@ describe('vim.iter', function()
do
local it = vim.iter(vim.gsplit('AbCdE', ''))
- local pred = function(s) return s:match('[A-Z]') end
+ local pred = function(s)
+ return s:match('[A-Z]')
+ end
eq('A', it:find(pred))
eq('C', it:find(pred))
eq('E', it:find(pred))
@@ -295,7 +389,7 @@ describe('vim.iter', function()
end)
it('rfind()', function()
- local t = {1, 2, 3, 2, 1}
+ local t = { 1, 2, 3, 2, 1 }
do
local it = vim.iter(t)
eq(1, it:rfind(1))
@@ -305,10 +399,12 @@ describe('vim.iter', function()
do
local it = vim.iter(t):enumerate()
- local pred = function(i) return i % 2 ~= 0 end
- eq({5, 1}, {it:rfind(pred)})
- eq({3, 3}, {it:rfind(pred)})
- eq({1, 1}, {it:rfind(pred)})
+ local pred = function(i)
+ return i % 2 ~= 0
+ end
+ eq({ 5, 1 }, { it:rfind(pred) })
+ eq({ 3, 3 }, { it:rfind(pred) })
+ eq({ 1, 1 }, { it:rfind(pred) })
eq(nil, it:rfind(pred))
end
@@ -350,12 +446,52 @@ describe('vim.iter', function()
end)
it('fold()', function()
- local t = {1, 2, 3, 4, 5}
- eq(115, vim.iter(t):fold(100, function(acc, v) return acc + v end))
- eq({5, 4, 3, 2, 1}, vim.iter(t):fold({}, function(acc, v)
- table.insert(acc, 1, v)
- return acc
- end))
+ local t = { 1, 2, 3, 4, 5 }
+ eq(
+ 115,
+ vim.iter(t):fold(100, function(acc, v)
+ return acc + v
+ end)
+ )
+ eq(
+ { 5, 4, 3, 2, 1 },
+ vim.iter(t):fold({}, function(acc, v)
+ table.insert(acc, 1, v)
+ return acc
+ end)
+ )
+ end)
+
+ it('flatten()', function()
+ local t = { { 1, { 2 } }, { { { { 3 } } }, { 4 } }, { 5 } }
+
+ eq(t, vim.iter(t):flatten(-1):totable())
+ eq(t, vim.iter(t):flatten(0):totable())
+ eq({ 1, { 2 }, { { { 3 } } }, { 4 }, 5 }, vim.iter(t):flatten():totable())
+ eq({ 1, 2, { { 3 } }, 4, 5 }, vim.iter(t):flatten(2):totable())
+ eq({ 1, 2, { 3 }, 4, 5 }, vim.iter(t):flatten(3):totable())
+ eq({ 1, 2, 3, 4, 5 }, vim.iter(t):flatten(4):totable())
+
+ local m = { a = 1, b = { 2, 3 }, d = { 4 } }
+ local it = vim.iter(m)
+
+ local flat_err = 'flatten%(%) requires a list%-like table'
+ matches(flat_err, pcall_err(it.flatten, it))
+
+ -- cases from the documentation
+ local simple_example = { 1, { 2 }, { { 3 } } }
+ eq({ 1, 2, { 3 } }, vim.iter(simple_example):flatten():totable())
+
+ local not_list_like = vim.iter({ [2] = 2 })
+ matches(flat_err, pcall_err(not_list_like.flatten, not_list_like))
+
+ local also_not_list_like = vim.iter({ nil, 2 })
+ matches(flat_err, pcall_err(not_list_like.flatten, also_not_list_like))
+
+ local nested_non_lists = vim.iter({ 1, { { a = 2 } }, { { nil } }, { 3 } })
+ eq({ 1, { a = 2 }, { nil }, 3 }, nested_non_lists:flatten():totable())
+ -- only error if we're going deep enough to flatten a dict-like table
+ matches(flat_err, pcall_err(nested_non_lists.flatten, nested_non_lists, math.huge))
end)
it('handles map-like tables', function()
@@ -385,9 +521,12 @@ describe('vim.iter', function()
},
}
- local output = vim.iter(map):map(function(key, value)
- return { [key] = value.file }
- end):totable()
+ local output = vim
+ .iter(map)
+ :map(function(key, value)
+ return { [key] = value.file }
+ end)
+ :totable()
table.sort(output, function(a, b)
return next(a) < next(b)
diff --git a/test/functional/lua/json_spec.lua b/test/functional/lua/json_spec.lua
index 25fdb48eea..d348e2de3c 100644
--- a/test/functional/lua/json_spec.lua
+++ b/test/functional/lua/json_spec.lua
@@ -16,40 +16,44 @@ describe('vim.json.decode()', function()
end)
it('validation', function()
- eq('Expected object key string but found invalid token at character 2',
- pcall_err(exec_lua, [[return vim.json.decode('{a:"b"}')]]))
+ eq(
+ 'Expected object key string but found invalid token at character 2',
+ pcall_err(exec_lua, [[return vim.json.decode('{a:"b"}')]])
+ )
end)
it('options', function()
local jsonstr = '{"arr":[1,2,null],"bar":[3,7],"foo":{"a":"b"},"baz":null}'
eq({
- arr = { 1, 2, vim.NIL },
- bar = { 3, 7 },
- baz = vim.NIL,
- foo = { a = 'b' },
- },
- exec_lua([[return vim.json.decode(..., {})]], jsonstr))
- eq({
- arr = { 1, 2, vim.NIL },
- bar = { 3, 7 },
- -- baz = nil,
- foo = { a = 'b' },
- },
- exec_lua([[return vim.json.decode(..., { luanil = { object = true } })]], jsonstr))
+ arr = { 1, 2, vim.NIL },
+ bar = { 3, 7 },
+ baz = vim.NIL,
+ foo = { a = 'b' },
+ }, exec_lua([[return vim.json.decode(..., {})]], jsonstr))
eq({
- arr = { 1, 2 },
- bar = { 3, 7 },
- baz = vim.NIL,
- foo = { a = 'b' },
- },
- exec_lua([[return vim.json.decode(..., { luanil = { array = true } })]], jsonstr))
+ arr = { 1, 2, vim.NIL },
+ bar = { 3, 7 },
+ -- baz = nil,
+ foo = { a = 'b' },
+ }, exec_lua([[return vim.json.decode(..., { luanil = { object = true } })]], jsonstr))
eq({
+ arr = { 1, 2 },
+ bar = { 3, 7 },
+ baz = vim.NIL,
+ foo = { a = 'b' },
+ }, exec_lua([[return vim.json.decode(..., { luanil = { array = true } })]], jsonstr))
+ eq(
+ {
arr = { 1, 2 },
bar = { 3, 7 },
-- baz = nil,
foo = { a = 'b' },
},
- exec_lua([[return vim.json.decode(..., { luanil = { array = true, object = true } })]], jsonstr))
+ exec_lua(
+ [[return vim.json.decode(..., { luanil = { array = true, object = true } })]],
+ jsonstr
+ )
+ )
end)
it('parses integer numbers', function()
@@ -96,11 +100,15 @@ describe('vim.json.decode()', function()
end)
it('parses containers', function()
- eq({1}, exec_lua([[return vim.json.decode('[1]')]]))
- eq({vim.NIL, 1}, exec_lua([[return vim.json.decode('[null, 1]')]]))
- eq({['1']=2}, exec_lua([[return vim.json.decode('{"1": 2}')]]))
- eq({['1']=2, ['3']={{['4']={['5']={{}, 1}}}}},
- exec_lua([[return vim.json.decode('{"1": 2, "3": [{"4": {"5": [ [], 1]}}]}')]]))
+ eq({ 1 }, exec_lua([[return vim.json.decode('[1]')]]))
+ eq({ vim.NIL, 1 }, exec_lua([[return vim.json.decode('[null, 1]')]]))
+ eq({ ['1'] = 2 }, exec_lua([[return vim.json.decode('{"1": 2}')]]))
+ eq(
+ { ['1'] = 2, ['3'] = { { ['4'] = { ['5'] = { {}, 1 } } } } },
+ exec_lua([[return vim.json.decode('{"1": 2, "3": [{"4": {"5": [ [], 1]}}]}')]])
+ )
+ -- Empty string is a valid key. #20757
+ eq({ [''] = 42 }, exec_lua([[return vim.json.decode('{"": 42}')]]))
end)
it('parses strings properly', function()
@@ -109,8 +117,8 @@ describe('vim.json.decode()', function()
eq('\\/"\t\b\n\r\f', exec_lua([=[return vim.json.decode([["\\\/\"\t\b\n\r\f"]])]=]))
eq('/a', exec_lua([=[return vim.json.decode([["\/a"]])]=]))
-- Unicode characters: 2-byte, 3-byte
- eq('«',exec_lua([=[return vim.json.decode([["«"]])]=]))
- eq('ફ',exec_lua([=[return vim.json.decode([["ફ"]])]=]))
+ eq('«', exec_lua([=[return vim.json.decode([["«"]])]=]))
+ eq('ફ', exec_lua([=[return vim.json.decode([["ફ"]])]=]))
end)
it('parses surrogate pairs properly', function()
@@ -118,11 +126,11 @@ describe('vim.json.decode()', function()
end)
it('accepts all spaces in every position where space may be put', function()
- local s = ' \t\n\r \t\r\n \n\t\r \n\r\t \r\t\n \r\n\t\t \n\r\t \r\n\t\n \r\t\n\r \t\r \n\t\r\n \n \t\r\n \r\t\n\t \r\n\t\r \n\r \t\n\r\t \r \t\n\r \n\t\r\t \n\r\t\n \r\n \t\r\n\t'
+ local s =
+ ' \t\n\r \t\r\n \n\t\r \n\r\t \r\t\n \r\n\t\t \n\r\t \r\n\t\n \r\t\n\r \t\r \n\t\r\n \n \t\r\n \r\t\n\t \r\n\t\r \n\r \t\n\r\t \r \t\n\r \n\t\r\t \n\r\t\n \r\n \t\r\n\t'
local str = ('%s{%s"key"%s:%s[%s"val"%s,%s"val2"%s]%s,%s"key2"%s:%s1%s}%s'):gsub('%%s', s)
- eq({key={'val', 'val2'}, key2=1}, exec_lua([[return vim.json.decode(...)]], str))
+ eq({ key = { 'val', 'val2' }, key2 = 1 }, exec_lua([[return vim.json.decode(...)]], str))
end)
-
end)
describe('vim.json.encode()', function()
@@ -161,10 +169,11 @@ describe('vim.json.encode()', function()
it('dumps dictionaries', function()
eq('{}', exec_lua([[return vim.json.encode(vim.empty_dict())]]))
eq('{"d":[]}', exec_lua([[return vim.json.encode({d={}})]]))
+ -- Empty string is a valid key. #20757
+ eq('{"":42}', exec_lua([[return vim.json.encode({['']=42})]]))
end)
it('dumps vim.NIL', function()
eq('null', exec_lua([[return vim.json.encode(vim.NIL)]]))
end)
-
end)
diff --git a/test/functional/lua/loader_spec.lua b/test/functional/lua/loader_spec.lua
index 34c36b04ef..4e42a18405 100644
--- a/test/functional/lua/loader_spec.lua
+++ b/test/functional/lua/loader_spec.lua
@@ -3,43 +3,77 @@ local helpers = require('test.functional.helpers')(after_each)
local exec_lua = helpers.exec_lua
local command = helpers.command
+local clear = helpers.clear
local eq = helpers.eq
describe('vim.loader', function()
- before_each(helpers.clear)
+ before_each(clear)
+
+ it('can work in compatibility with --luamod-dev #27413', function()
+ clear({ args = { '--luamod-dev' } })
+ exec_lua [[
+ vim.loader.enable()
+
+ require("vim.fs")
+
+ -- try to load other vim submodules as well (Nvim Lua stdlib)
+ for key, _ in pairs(vim._submodules) do
+ local modname = 'vim.' .. key -- e.g. "vim.fs"
+
+ local lhs = vim[key]
+ local rhs = require(modname)
+ assert(
+ lhs == rhs,
+ ('%s != require("%s"), %s != %s'):format(modname, modname, tostring(lhs), tostring(rhs))
+ )
+ end
+ ]]
+ end)
it('handles changing files (#23027)', function()
- exec_lua[[
+ exec_lua [[
vim.loader.enable()
]]
local tmp = helpers.tmpname()
command('edit ' .. tmp)
- eq(1, exec_lua([[
+ eq(
+ 1,
+ exec_lua(
+ [[
vim.api.nvim_buf_set_lines(0, 0, -1, true, {'_G.TEST=1'})
vim.cmd.write()
loadfile(...)()
return _G.TEST
- ]], tmp))
+ ]],
+ tmp
+ )
+ )
-- fs latency
- helpers.sleep(10)
+ vim.uv.sleep(10)
- eq(2, exec_lua([[
+ eq(
+ 2,
+ exec_lua(
+ [[
vim.api.nvim_buf_set_lines(0, 0, -1, true, {'_G.TEST=2'})
vim.cmd.write()
loadfile(...)()
return _G.TEST
- ]], tmp))
+ ]],
+ tmp
+ )
+ )
end)
it('handles % signs in modpath (#24491)', function()
- exec_lua[[
+ exec_lua [[
vim.loader.enable()
]]
- local tmp1, tmp2 = (function (t)
+ local tmp1, tmp2 = (function(t)
assert(os.remove(t))
assert(helpers.mkdir(t))
assert(helpers.mkdir(t .. '/%'))
diff --git a/test/functional/lua/loop_spec.lua b/test/functional/lua/loop_spec.lua
index c0924fa0c0..71eaf29009 100644
--- a/test/functional/lua/loop_spec.lua
+++ b/test/functional/lua/loop_spec.lua
@@ -1,10 +1,10 @@
-- Test suite for testing interactions with API bindings
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local clear = helpers.clear
-local sleep = helpers.sleep
+local sleep = vim.uv.sleep
local feed = helpers.feed
local eq = helpers.eq
local eval = helpers.eval
@@ -15,23 +15,20 @@ local retry = helpers.retry
before_each(clear)
describe('vim.uv', function()
-
it('version', function()
- assert(funcs.luaeval('vim.uv.version()')>=72961, "libuv version too old")
- matches("(%d+)%.(%d+)%.(%d+)", funcs.luaeval('vim.uv.version_string()'))
+ assert(fn.luaeval('vim.uv.version()') >= 72961, 'libuv version too old')
+ matches('(%d+)%.(%d+)%.(%d+)', fn.luaeval('vim.uv.version_string()'))
end)
it('timer', function()
exec_lua('vim.api.nvim_set_var("coroutine_cnt", 0)', {})
- local code=[[
- local uv = vim.uv
-
+ local code = [[
local touch = 0
local function wait(ms)
local this = coroutine.running()
assert(this)
- local timer = uv.new_timer()
+ local timer = vim.uv.new_timer()
timer:start(ms, 0, vim.schedule_wrap(function ()
timer:close()
touch = touch + 1
@@ -51,24 +48,24 @@ describe('vim.uv', function()
end)()
]]
- eq(0, meths.get_var('coroutine_cnt'))
+ eq(0, api.nvim_get_var('coroutine_cnt'))
exec_lua(code)
retry(2, nil, function()
sleep(50)
- eq(2, meths.get_var('coroutine_cnt'))
+ eq(2, api.nvim_get_var('coroutine_cnt'))
end)
- eq(3, meths.get_var('coroutine_cnt_1'))
+ eq(3, api.nvim_get_var('coroutine_cnt_1'))
end)
it('is API safe', function()
- local screen = Screen.new(50,10)
+ local screen = Screen.new(50, 10)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {bold = true, reverse = true},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [5] = {bold = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, reverse = true },
+ [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [5] = { bold = true },
})
-- deferred API functions are disabled, as their safety can't be guaranteed
@@ -96,7 +93,7 @@ describe('vim.uv', function()
]])
feed('<cr>')
eq(false, eval("get(g:, 'valid', v:false)"))
- eq(true, exec_lua("return _G.is_fast"))
+ eq(true, exec_lua('return _G.is_fast'))
-- callbacks can be scheduled to be executed in the main event loop
-- where the entire API is available
@@ -112,18 +109,11 @@ describe('vim.uv', function()
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
howdy |
]])
eq(true, eval("get(g:, 'valid', v:false)"))
- eq(false, exec_lua("return _G.is_fast"))
+ eq(false, exec_lua('return _G.is_fast'))
-- fast (not deferred) API functions are allowed to be called directly
exec_lua([[
@@ -137,17 +127,10 @@ describe('vim.uv', function()
]])
screen:expect([[
sneaky^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
{5:-- INSERT --} |
]])
- eq({blocking=false, mode='n'}, exec_lua("return _G.mode"))
+ eq({ blocking = false, mode = 'n' }, exec_lua('return _G.mode'))
end)
it("is equal to require('luv')", function()
diff --git a/test/functional/lua/luaeval_spec.lua b/test/functional/lua/luaeval_spec.lua
index dfbd2fb18b..b28cfa4dd2 100644
--- a/test/functional/lua/luaeval_spec.lua
+++ b/test/functional/lua/luaeval_spec.lua
@@ -7,12 +7,12 @@ local exc_exec = helpers.exc_exec
local remove_trace = helpers.remove_trace
local exec_lua = helpers.exec_lua
local command = helpers.command
-local meths = helpers.meths
-local funcs = helpers.funcs
+local api = helpers.api
+local fn = helpers.fn
local clear = helpers.clear
local eval = helpers.eval
local feed = helpers.feed
-local NIL = helpers.NIL
+local NIL = vim.NIL
local eq = helpers.eq
before_each(clear)
@@ -39,7 +39,7 @@ describe('luaeval()', function()
describe('second argument', function()
it('is successfully received', function()
local t = {t=true, f=false, --[[n=NIL,]] d={l={'string', 42, 0.42}}}
- eq(t, funcs.luaeval("_A", t))
+ eq(t, fn.luaeval("_A", t))
-- Not tested: nil, funcrefs, returned object identity: behaviour will
-- most likely change.
end)
@@ -47,39 +47,37 @@ describe('luaeval()', function()
describe('lua values', function()
it('are successfully transformed', function()
eq({n=1, f=1.5, s='string', l={4, 2}},
- funcs.luaeval('{n=1, f=1.5, s="string", l={4, 2}}'))
+ fn.luaeval('{n=1, f=1.5, s="string", l={4, 2}}'))
-- Not tested: nil inside containers: behaviour will most likely change.
- eq(NIL, funcs.luaeval('nil'))
- eq({['']=1}, funcs.luaeval('{[""]=1}'))
+ eq(NIL, fn.luaeval('nil'))
+ eq({['']=1}, fn.luaeval('{[""]=1}'))
end)
end)
describe('recursive lua values', function()
it('are successfully transformed', function()
command('lua rawset(_G, "d", {})')
command('lua rawset(d, "d", d)')
- eq('\n{\'d\': {...@0}}', funcs.execute('echo luaeval("d")'))
+ eq('\n{\'d\': {...@0}}', fn.execute('echo luaeval("d")'))
command('lua rawset(_G, "l", {})')
command('lua table.insert(l, l)')
- eq('\n[[...@0]]', funcs.execute('echo luaeval("l")'))
+ eq('\n[[...@0]]', fn.execute('echo luaeval("l")'))
end)
end)
describe('strings with NULs', function()
it('are successfully converted to blobs', function()
command([[let s = luaeval('"\0"')]])
- eq('\000', meths.get_var('s'))
+ eq('\000', api.nvim_get_var('s'))
end)
- it('are successfully converted to special dictionaries in table keys',
- function()
+ it('are successfully converted to special dictionaries in table keys', function()
command([[let d = luaeval('{["\0"]=1}')]])
- eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n'}}, 1}}}, meths.get_var('d'))
- eq(1, funcs.eval('d._TYPE is v:msgpack_types.map'))
- eq(1, funcs.eval('d._VAL[0][0]._TYPE is v:msgpack_types.string'))
+ eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n'}}, 1}}}, api.nvim_get_var('d'))
+ eq(1, fn.eval('d._TYPE is v:msgpack_types.map'))
+ eq(1, fn.eval('d._VAL[0][0]._TYPE is v:msgpack_types.string'))
end)
- it('are successfully converted to blobs from a list',
- function()
+ it('are successfully converted to blobs from a list', function()
command([[let l = luaeval('{"abc", "a\0b", "c\0d", "def"}')]])
- eq({'abc', 'a\000b', 'c\000d', 'def'}, meths.get_var('l'))
+ eq({'abc', 'a\000b', 'c\000d', 'def'}, api.nvim_get_var('l'))
end)
end)
@@ -88,62 +86,68 @@ describe('luaeval()', function()
it('correctly evaluates scalars', function()
-- Also test method call (->) syntax
- eq(1, funcs.luaeval('1'))
+ eq(1, fn.luaeval('1'))
eq(0, eval('"1"->luaeval()->type()'))
- eq(1.5, funcs.luaeval('1.5'))
+ eq(1.5, fn.luaeval('1.5'))
eq(5, eval('"1.5"->luaeval()->type()'))
- eq("test", funcs.luaeval('"test"'))
+ eq("test", fn.luaeval('"test"'))
eq(1, eval('"\'test\'"->luaeval()->type()'))
- eq('', funcs.luaeval('""'))
- eq('\000', funcs.luaeval([['\0']]))
- eq('\000\n\000', funcs.luaeval([['\0\n\0']]))
+ eq('', fn.luaeval('""'))
+ eq('\000', fn.luaeval([['\0']]))
+ eq('\000\n\000', fn.luaeval([['\0\n\0']]))
eq(10, eval([[type(luaeval("'\\0\\n\\0'"))]]))
- eq(true, funcs.luaeval('true'))
- eq(false, funcs.luaeval('false'))
- eq(NIL, funcs.luaeval('nil'))
+ eq(true, fn.luaeval('true'))
+ eq(false, fn.luaeval('false'))
+ eq(NIL, fn.luaeval('nil'))
end)
it('correctly evaluates containers', function()
- eq({}, funcs.luaeval('{}'))
+ eq({}, fn.luaeval('{}'))
eq(3, eval('type(luaeval("{}"))'))
- eq({test=1, foo=2}, funcs.luaeval('{test=1, foo=2}'))
+ eq({test=1, foo=2}, fn.luaeval('{test=1, foo=2}'))
eq(4, eval('type(luaeval("{test=1, foo=2}"))'))
- eq({4, 2}, funcs.luaeval('{4, 2}'))
+ eq({4, 2}, fn.luaeval('{4, 2}'))
eq(3, eval('type(luaeval("{4, 2}"))'))
+ eq({NIL, 20}, fn.luaeval('{[2] = 20}'))
+ eq(3, eval('type(luaeval("{[2] = 20}"))'))
+
+ eq({10, NIL, 30}, fn.luaeval('{[1] = 10, [3] = 30}'))
+ eq(3, eval('type(luaeval("{[1] = 10, [3] = 30}"))'))
+
local level = 30
- eq(nested_by_level[level].o, funcs.luaeval(nested_by_level[level].s))
+ eq(nested_by_level[level].o, fn.luaeval(nested_by_level[level].s))
eq({_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, '\000\n\000\000'}}},
- funcs.luaeval([[{['\0\n\0']='\0\n\0\0'}]]))
+ fn.luaeval([[{['\0\n\0']='\0\n\0\0'}]]))
eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._TYPE is v:msgpack_types.map]]))
eq(1, eval([[luaeval('{["\0\n\0"]="\0\n\0\0"}')._VAL[0][0]._TYPE is v:msgpack_types.string]]))
eq({nested={{_TYPE={}, _VAL={{{_TYPE={}, _VAL={'\n', '\n'}}, '\000\n\000\000'}}}}},
- funcs.luaeval([[{nested={{['\0\n\0']='\0\n\0\0'}}}]]))
+ fn.luaeval([[{nested={{['\0\n\0']='\0\n\0\0'}}}]]))
end)
it('correctly passes scalars as argument', function()
- eq(1, funcs.luaeval('_A', 1))
- eq(1.5, funcs.luaeval('_A', 1.5))
- eq('', funcs.luaeval('_A', ''))
- eq('test', funcs.luaeval('_A', 'test'))
- eq(NIL, funcs.luaeval('_A', NIL))
- eq(true, funcs.luaeval('_A', true))
- eq(false, funcs.luaeval('_A', false))
+ eq(1, fn.luaeval('_A', 1))
+ eq(1.5, fn.luaeval('_A', 1.5))
+ eq('', fn.luaeval('_A', ''))
+ eq('test', fn.luaeval('_A', 'test'))
+ eq(NIL, fn.luaeval('_A', NIL))
+ eq(true, fn.luaeval('_A', true))
+ eq(false, fn.luaeval('_A', false))
end)
it('correctly passes containers as argument', function()
- eq({}, funcs.luaeval('_A', {}))
- eq({test=1}, funcs.luaeval('_A', {test=1}))
- eq({4, 2}, funcs.luaeval('_A', {4, 2}))
+ eq({}, fn.luaeval('_A', {}))
+ eq({test=1}, fn.luaeval('_A', {test=1}))
+ eq({4, 2}, fn.luaeval('_A', {4, 2}))
local level = 28
- eq(nested_by_level[level].o, funcs.luaeval('_A', nested_by_level[level].o))
+ eq(nested_by_level[level].o, fn.luaeval('_A', nested_by_level[level].o))
end)
local function sp(typ, val)
@@ -158,7 +162,7 @@ describe('luaeval()', function()
return sp('map', '[' .. val .. ']')
end
local function luaevalarg(argexpr, expr)
- return eval(([=[
+ return eval((([=[
[
extend(g:, {'_ret': luaeval(%s, %s)})._ret,
type(g:_ret)==type({})&&has_key(g:_ret, '_TYPE')
@@ -168,7 +172,7 @@ describe('luaeval()', function()
get(g:_ret, '_VAL', g:_ret)
]
: [0, g:_ret]][1]
- ]=]):format(expr or '"_A"', argexpr):gsub('\n', ''))
+ ]=]):format(expr or '"_A"', argexpr):gsub('\n', '')))
end
it('correctly passes special dictionaries', function()
@@ -182,7 +186,7 @@ describe('luaeval()', function()
end)
it('issues an error in some cases', function()
- eq("Vim(call):E5100: Cannot convert given lua table: table should either have a sequence of positive integer keys or contain only string keys",
+ eq("Vim(call):E5100: Cannot convert given lua table: table should contain either only integer keys or only string keys",
exc_exec('call luaeval("{1, foo=2}")'))
startswith("Vim(call):E5107: Error loading lua [string \"luaeval()\"]:",
@@ -395,26 +399,26 @@ describe('luaeval()', function()
eq(4, eval([[type(luaeval('{[vim.type_idx]=vim.types.dictionary}'))]]))
eq(3, eval([[type(luaeval('{[vim.type_idx]=vim.types.array}'))]]))
- eq({}, funcs.luaeval('{[vim.type_idx]=vim.types.array}'))
+ eq({}, fn.luaeval('{[vim.type_idx]=vim.types.array}'))
-- Presence of type_idx makes Vim ignore some keys
- eq({42}, funcs.luaeval('{[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}'))
- eq({foo=2}, funcs.luaeval('{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}'))
- eq(10, funcs.luaeval('{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}'))
+ eq({42}, fn.luaeval('{[vim.type_idx]=vim.types.array, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}'))
+ eq({foo=2}, fn.luaeval('{[vim.type_idx]=vim.types.dictionary, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}'))
+ eq(10, fn.luaeval('{[vim.type_idx]=vim.types.float, [vim.val_idx]=10, [5]=1, foo=2, [1]=42}'))
-- The following should not crash
- eq({}, funcs.luaeval('{[vim.type_idx]=vim.types.dictionary}'))
+ eq({}, fn.luaeval('{[vim.type_idx]=vim.types.dictionary}'))
end)
it('correctly converts self-containing containers', function()
- meths.set_var('l', {})
+ api.nvim_set_var('l', {})
eval('add(l, l)')
eq(true, eval('luaeval("_A == _A[1]", l)'))
eq(true, eval('luaeval("_A[1] == _A[1][1]", [l])'))
eq(true, eval('luaeval("_A.d == _A.d[1]", {"d": l})'))
eq(true, eval('luaeval("_A ~= _A[1]", [l])'))
- meths.set_var('d', {foo=42})
+ api.nvim_set_var('d', {foo=42})
eval('extend(d, {"d": d})')
eq(true, eval('luaeval("_A == _A.d", d)'))
eq(true, eval('luaeval("_A[1] == _A[1].d", [d])'))
@@ -437,7 +441,7 @@ describe('luaeval()', function()
local s = ('x'):rep(65536)
eq('Vim(call):E5107: Error loading lua [string "luaeval()"]:1: unexpected symbol near \')\'',
exc_exec([[call luaeval("(']] .. s ..[[' + )")]]))
- eq(s, funcs.luaeval('"' .. s .. '"'))
+ eq(s, fn.luaeval('"' .. s .. '"'))
end)
end)
@@ -474,7 +478,7 @@ describe('v:lua', function()
eq(7, eval('v:lua.foo(3,4,v:null)'))
eq(true, exec_lua([[return _G.val == vim.NIL]]))
eq(NIL, eval('v:lua.mymod.noisy("eval")'))
- eq("hey eval", meths.get_current_line())
+ eq("hey eval", api.nvim_get_current_line())
eq("string: abc", eval('v:lua.mymod.whatis(0z616263)'))
eq("string: ", eval('v:lua.mymod.whatis(v:_null_blob)'))
@@ -490,7 +494,7 @@ describe('v:lua', function()
eq("boop", exec_lua([[return _G.val]]))
eq(NIL, eval('"there"->v:lua.mymod.noisy()'))
- eq("hey there", meths.get_current_line())
+ eq("hey there", api.nvim_get_current_line())
eq({5, 10, 15, 20}, eval('[[1], [2, 3], [4]]->v:lua.vim.tbl_flatten()->map({_, v -> v * 5})'))
eq("Vim:E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)",
@@ -499,7 +503,7 @@ describe('v:lua', function()
it('works in :call', function()
command(":call v:lua.mymod.noisy('command')")
- eq("hey command", meths.get_current_line())
+ eq("hey command", api.nvim_get_current_line())
eq("Vim(call):E5108: Error executing lua [string \"<nvim>\"]:0: attempt to call global 'nonexistent' (a nil value)",
pcall_err(command, 'call v:lua.mymod.crashy()'))
end)
@@ -514,21 +518,19 @@ describe('v:lua', function()
[5] = {bold = true, foreground = Screen.colors.SeaGreen4},
})
screen:attach()
- meths.set_option_value('omnifunc', 'v:lua.mymod.omni', {})
+ api.nvim_set_option_value('omnifunc', 'v:lua.mymod.omni', {})
feed('isome st<c-x><c-o>')
screen:expect{grid=[[
some stuff^ |
{1:~ }{2: stuff }{1: }|
{1:~ }{3: steam }{1: }|
{1:~ }{3: strange things }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{4:-- Omni completion (^O^N^P) }{5:match 1 of 3} |
]]}
- meths.set_option_value('operatorfunc', 'v:lua.mymod.noisy', {})
+ api.nvim_set_option_value('operatorfunc', 'v:lua.mymod.noisy', {})
feed('<Esc>g@g@')
- eq("hey line", meths.get_current_line())
+ eq("hey line", api.nvim_get_current_line())
end)
it('supports packages', function()
@@ -536,6 +538,8 @@ describe('v:lua', function()
eq('\tbadval', eval("v:lua.require'leftpad'('badval')"))
eq(9003, eval("v:lua.require'bar'.doit()"))
eq(9004, eval("v:lua.require'baz-quux'.doit()"))
+ eq(9003, eval("1 ? v:lua.require'bar'.doit() : v:lua.require'baz-quux'.doit()"))
+ eq(9004, eval("0 ? v:lua.require'bar'.doit() : v:lua.require'baz-quux'.doit()"))
end)
it('throw errors for invalid use', function()
diff --git a/test/functional/lua/mpack_spec.lua b/test/functional/lua/mpack_spec.lua
index cc788ed8bb..0b6a6d60bd 100644
--- a/test/functional/lua/mpack_spec.lua
+++ b/test/functional/lua/mpack_spec.lua
@@ -8,16 +8,22 @@ local exec_lua = helpers.exec_lua
describe('lua vim.mpack', function()
before_each(clear)
it('encodes vim.NIL', function()
- eq({true, true, true, true}, exec_lua [[
+ eq(
+ { true, true, true, true },
+ exec_lua [[
local var = vim.mpack.decode(vim.mpack.encode({33, vim.NIL, 77}))
return {var[1]==33, var[2]==vim.NIL, var[3]==77, var[4]==nil}
- ]])
+ ]]
+ )
end)
it('encodes vim.empty_dict()', function()
- eq({{{}, "foo", {}}, true, false}, exec_lua [[
+ eq(
+ { { {}, 'foo', {} }, true, false },
+ exec_lua [[
local var = vim.mpack.decode(vim.mpack.encode({{}, "foo", vim.empty_dict()}))
return {var, vim.tbl_islist(var[1]), vim.tbl_islist(var[3])}
- ]])
+ ]]
+ )
end)
end)
diff --git a/test/functional/lua/overrides_spec.lua b/test/functional/lua/overrides_spec.lua
index c08f3d06a9..ecbdde3bfd 100644
--- a/test/functional/lua/overrides_spec.lua
+++ b/test/functional/lua/overrides_spec.lua
@@ -3,11 +3,11 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local eq = helpers.eq
-local NIL = helpers.NIL
+local NIL = vim.NIL
local feed = helpers.feed
local clear = helpers.clear
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local command = helpers.command
local write_file = helpers.write_file
local exec_capture = helpers.exec_capture
@@ -25,15 +25,15 @@ end)
describe('print', function()
it('returns nothing', function()
- eq(NIL, funcs.luaeval('print("abc")'))
- eq(0, funcs.luaeval('select("#", print("abc"))'))
+ eq(NIL, fn.luaeval('print("abc")'))
+ eq(0, fn.luaeval('select("#", print("abc"))'))
end)
it('allows catching printed text with :execute', function()
- eq('\nabc', funcs.execute('lua print("abc")'))
- eq('\nabc', funcs.execute('luado print("abc")'))
- eq('\nabc', funcs.execute('call luaeval("print(\'abc\')")'))
+ eq('\nabc', fn.execute('lua print("abc")'))
+ eq('\nabc', fn.execute('luado print("abc")'))
+ eq('\nabc', fn.execute('call luaeval("print(\'abc\')")'))
write_file(fname, 'print("abc")')
- eq('\nabc', funcs.execute('luafile ' .. fname))
+ eq('\nabc', fn.execute('luafile ' .. fname))
eq('abc', exec_capture('lua print("abc")'))
eq('abc', exec_capture('luado print("abc")'))
@@ -42,25 +42,36 @@ describe('print', function()
eq('abc', exec_capture('luafile ' .. fname))
end)
it('handles errors in __tostring', function()
- write_file(fname, [[
+ write_file(
+ fname,
+ [[
local meta_nilerr = { __tostring = function() error(nil) end }
local meta_abcerr = { __tostring = function() error("abc") end }
local meta_tblout = { __tostring = function() return {"TEST"} end }
v_nilerr = setmetatable({}, meta_nilerr)
v_abcerr = setmetatable({}, meta_abcerr)
v_tblout = setmetatable({}, meta_tblout)
- ]])
+ ]]
+ )
eq('', exec_capture('luafile ' .. fname))
-- TODO(bfredl): these look weird, print() should not use "E5114:" style errors..
- eq('Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: [NULL]',
- pcall_err(command, 'lua print("foo", v_nilerr, "bar")'))
- eq('Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: Xtest-functional-lua-overrides-luafile:2: abc',
- pcall_err(command, 'lua print("foo", v_abcerr, "bar")'))
- eq('Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>',
- pcall_err(command, 'lua print("foo", v_tblout, "bar")'))
+ eq(
+ 'Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: [NULL]',
+ pcall_err(command, 'lua print("foo", v_nilerr, "bar")')
+ )
+ eq(
+ 'Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: Xtest-functional-lua-overrides-luafile:2: abc',
+ pcall_err(command, 'lua print("foo", v_abcerr, "bar")')
+ )
+ eq(
+ 'Vim(lua):E5108: Error executing lua E5114: Error while converting print argument #2: <Unknown error: lua_tolstring returned NULL for tostring result>',
+ pcall_err(command, 'lua print("foo", v_tblout, "bar")')
+ )
end)
it('coerces error values into strings', function()
- write_file(fname, [[
+ write_file(
+ fname,
+ [[
function string_error() error("my mistake") end
function number_error() error(1234) end
function nil_error() error(nil) end
@@ -82,27 +93,35 @@ describe('print', function()
})
error(err)
end
- ]])
+ ]]
+ )
eq('', exec_capture('luafile ' .. fname))
- eq('Vim(lua):E5108: Error executing lua Xtest-functional-lua-overrides-luafile:1: my mistake',
- pcall_err(command, 'lua string_error()'))
- eq('Vim(lua):E5108: Error executing lua Xtest-functional-lua-overrides-luafile:2: 1234',
- pcall_err(command, 'lua number_error()'))
- eq('Vim(lua):E5108: Error executing lua [NULL]',
- pcall_err(command, 'lua nil_error()'))
- eq('Vim(lua):E5108: Error executing lua [NULL]',
- pcall_err(command, 'lua table_error()'))
- eq('Vim(lua):E5108: Error executing lua Internal Error [11234] my mistake',
- pcall_err(command, 'lua custom_error()'))
- eq('Vim(lua):E5108: Error executing lua [NULL]',
- pcall_err(command, 'lua bad_custom_error()'))
+ eq(
+ 'Vim(lua):E5108: Error executing lua Xtest-functional-lua-overrides-luafile:1: my mistake',
+ pcall_err(command, 'lua string_error()')
+ )
+ eq(
+ 'Vim(lua):E5108: Error executing lua Xtest-functional-lua-overrides-luafile:2: 1234',
+ pcall_err(command, 'lua number_error()')
+ )
+ eq('Vim(lua):E5108: Error executing lua [NULL]', pcall_err(command, 'lua nil_error()'))
+ eq('Vim(lua):E5108: Error executing lua [NULL]', pcall_err(command, 'lua table_error()'))
+ eq(
+ 'Vim(lua):E5108: Error executing lua Internal Error [11234] my mistake',
+ pcall_err(command, 'lua custom_error()')
+ )
+ eq('Vim(lua):E5108: Error executing lua [NULL]', pcall_err(command, 'lua bad_custom_error()'))
end)
it('prints strings with NULs and NLs correctly', function()
- 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^@',
- exec_capture([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\0")]]))
+ api.nvim_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^@',
+ exec_capture([[lua print("abc \0 def\nghi\0\0\0jkl\nTEST\n\n\nT\0")]])
+ )
eq('T^@', exec_capture([[lua print("T\0")]]))
eq('T\n', exec_capture([[lua print("T\n")]]))
end)
@@ -114,7 +133,8 @@ describe('print', function()
eq('abc def', exec_capture('lua print("abc", "", "def")'))
end)
it('defers printing in luv event handlers', function()
- exec_lua([[
+ exec_lua(
+ [[
local cmd = ...
function test()
local timer = vim.uv.new_timer()
@@ -133,7 +153,9 @@ describe('print', function()
print("very slow")
vim.api.nvim_command("sleep 1m") -- force deferred event processing
end
- ]], (is_os('win') and "timeout 1") or "sleep 0.1")
+ ]],
+ (is_os('win') and 'timeout 1') or 'sleep 0.1'
+ )
eq('very slow\nvery fast', exec_capture('lua test()'))
end)
@@ -141,33 +163,34 @@ describe('print', function()
local screen = Screen.new(40, 8)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold = true, foreground=Screen.colors.Blue},
- [1] = {bold = true, foreground = Screen.colors.SeaGreen},
- [2] = {bold = true, reverse = true},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [2] = { bold = true, reverse = true },
})
feed([[:lua print('\na')<CR>]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2: }|
|
a |
{1:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed('<CR>')
feed([[:lua print('b\n\nc')<CR>]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2: }|
b |
|
c |
{1:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
end)
@@ -178,10 +201,10 @@ describe('debug.debug', function()
screen = Screen.new()
screen:attach()
screen:set_default_attr_ids {
- [0] = {bold=true, foreground=255};
- [1] = {bold = true, reverse = true};
- E = {foreground = Screen.colors.Grey100, background = Screen.colors.Red};
- cr = {bold = true, foreground = Screen.colors.SeaGreen4};
+ [0] = { bold = true, foreground = 255 },
+ [1] = { bold = true, reverse = true },
+ E = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ cr = { bold = true, foreground = Screen.colors.SeaGreen4 },
}
end)
@@ -194,33 +217,19 @@ describe('debug.debug', function()
end
]])
feed(':lua Test()\n')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*10
{1: }|
nil |
lua_debug> ^ |
- ]]}
+ ]],
+ }
feed('print("TEST")\n')
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
{1: }|
nil |
lua_debug> print("TEST") |
@@ -228,10 +237,10 @@ describe('debug.debug', function()
lua_debug> ^ |
]])
feed('<C-c>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1: }|
nil |
lua_debug> print("TEST") |
@@ -243,31 +252,21 @@ describe('debug.debug', function()
{E: [string ":lua"]:5: in function 'Test'} |
{E: [string ":lua"]:1: in main chunk} |
Interrupt: {cr:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed('<C-l>:lua Test()\n')
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*10
{1: }|
nil |
lua_debug> ^ |
]])
feed('\n')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{1: }|
nil |
lua_debug> |
@@ -277,56 +276,39 @@ describe('debug.debug', function()
{E: [string ":lua"]:5: in function 'Test'} |
{E: [string ":lua"]:1: in main chunk} |
{cr:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
it("can be safely exited with 'cont'", function()
feed('<cr>')
feed(':lua debug.debug() print("x")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*12
lua_debug> ^ |
- ]]}
+ ]],
+ }
- feed("conttt<cr>") -- misspelled cont; invalid syntax
- screen:expect{grid=[[
+ feed('conttt<cr>') -- misspelled cont; invalid syntax
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
{1: }|
lua_debug> conttt |
{E:E5115: Error while loading debug string: (debug comma}|
{E:nd):1: '=' expected near '<eof>'} |
lua_debug> ^ |
- ]]}
+ ]],
+ }
- feed("cont<cr>") -- exactly "cont", exit now
- screen:expect{grid=[[
+ feed('cont<cr>') -- exactly "cont", exit now
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
{1: }|
lua_debug> conttt |
{E:E5115: Error while loading debug string: (debug comma}|
@@ -334,41 +316,33 @@ describe('debug.debug', function()
lua_debug> cont |
x |
{cr:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*12
|
- ]]}
+ ]],
+ }
end)
end)
describe('os.getenv', function()
it('returns nothing for undefined env var', function()
- eq(NIL, funcs.luaeval('os.getenv("XTEST_1")'))
+ eq(NIL, fn.luaeval('os.getenv("XTEST_1")'))
end)
it('returns env var set by the parent process', function()
local value = 'foo'
- clear({env = {['XTEST_1']=value}})
- eq(value, funcs.luaeval('os.getenv("XTEST_1")'))
+ clear({ env = { ['XTEST_1'] = value } })
+ eq(value, fn.luaeval('os.getenv("XTEST_1")'))
end)
it('returns env var set by let', function()
local value = 'foo'
- meths.command('let $XTEST_1 = "'..value..'"')
- eq(value, funcs.luaeval('os.getenv("XTEST_1")'))
+ command('let $XTEST_1 = "' .. value .. '"')
+ eq(value, fn.luaeval('os.getenv("XTEST_1")'))
end)
end)
@@ -376,6 +350,6 @@ end)
-- luajit or PUC lua 5.1.
describe('bit module', function()
it('works', function()
- eq (9, exec_lua [[ return require'bit'.band(11,13) ]])
+ eq(9, exec_lua [[ return require'bit'.band(11,13) ]])
end)
end)
diff --git a/test/functional/lua/runtime_spec.lua b/test/functional/lua/runtime_spec.lua
index 0b8b2234db..6f36ccfb9e 100644
--- a/test/functional/lua/runtime_spec.lua
+++ b/test/functional/lua/runtime_spec.lua
@@ -4,7 +4,7 @@ local clear = helpers.clear
local eq = helpers.eq
local eval = helpers.eval
local exec = helpers.exec
-local funcs = helpers.funcs
+local fn = helpers.fn
local mkdir_p = helpers.mkdir_p
local rmdir = helpers.rmdir
local write_file = helpers.write_file
@@ -15,8 +15,8 @@ describe('runtime:', function()
local init = 'dummy_init.lua'
setup(function()
- io.open(init, 'w'):close() -- touch init file
- clear{args = {'-u', init}}
+ io.open(init, 'w'):close() -- touch init file
+ clear { args = { '-u', init } }
exec('set rtp+=' .. plug_dir)
exec([[
set shell=doesnotexist
@@ -45,11 +45,11 @@ describe('runtime:', function()
end)
it('lua colorschemes work and are included in cmdline completion', function()
- local colorscheme_file = table.concat({colorscheme_folder, 'new_colorscheme.lua'}, sep)
+ local colorscheme_file = table.concat({ colorscheme_folder, 'new_colorscheme.lua' }, sep)
write_file(colorscheme_file, [[vim.g.lua_colorscheme = 1]])
- eq({'new_colorscheme'}, funcs.getcompletion('new_c', 'color'))
- eq({'colors/new_colorscheme.lua'}, funcs.getcompletion('colors/new_c', 'runtime'))
+ eq({ 'new_colorscheme' }, fn.getcompletion('new_c', 'color'))
+ eq({ 'colors/new_colorscheme.lua' }, fn.getcompletion('colors/new_c', 'runtime'))
exec('colorscheme new_colorscheme')
@@ -64,48 +64,60 @@ describe('runtime:', function()
end)
exec('set pp+=' .. pack_dir)
- local pack_opt_dir = table.concat({pack_dir, 'pack', 'some_name', 'opt'}, sep)
- local colors_opt_dir = table.concat({pack_opt_dir, 'some_pack', 'colors'}, sep)
+ local pack_opt_dir = table.concat({ pack_dir, 'pack', 'some_name', 'opt' }, sep)
+ local colors_opt_dir = table.concat({ pack_opt_dir, 'some_pack', 'colors' }, sep)
mkdir_p(colors_opt_dir)
- local after_colorscheme_folder = table.concat({plug_dir, 'after', 'colors'}, sep)
+ local after_colorscheme_folder = table.concat({ plug_dir, 'after', 'colors' }, sep)
mkdir_p(after_colorscheme_folder)
exec('set rtp+=' .. plug_dir .. '/after')
- write_file(table.concat({colors_opt_dir, 'new_colorscheme.lua'}, sep),
- [[vim.g.colorscheme = 'lua_pp']])
+ write_file(
+ table.concat({ colors_opt_dir, 'new_colorscheme.lua' }, sep),
+ [[vim.g.colorscheme = 'lua_pp']]
+ )
exec('colorscheme new_colorscheme')
eq('lua_pp', eval('g:colorscheme'))
- write_file(table.concat({colors_opt_dir, 'new_colorscheme.vim'}, sep),
- [[let g:colorscheme = 'vim_pp']])
+ write_file(
+ table.concat({ colors_opt_dir, 'new_colorscheme.vim' }, sep),
+ [[let g:colorscheme = 'vim_pp']]
+ )
exec('colorscheme new_colorscheme')
eq('vim_pp', eval('g:colorscheme'))
- write_file(table.concat({after_colorscheme_folder, 'new_colorscheme.lua'}, sep),
- [[vim.g.colorscheme = 'lua_rtp_after']])
+ write_file(
+ table.concat({ after_colorscheme_folder, 'new_colorscheme.lua' }, sep),
+ [[vim.g.colorscheme = 'lua_rtp_after']]
+ )
exec('colorscheme new_colorscheme')
eq('lua_rtp_after', eval('g:colorscheme'))
- write_file(table.concat({after_colorscheme_folder, 'new_colorscheme.vim'}, sep),
- [[let g:colorscheme = 'vim_rtp_after']])
+ write_file(
+ table.concat({ after_colorscheme_folder, 'new_colorscheme.vim' }, sep),
+ [[let g:colorscheme = 'vim_rtp_after']]
+ )
exec('colorscheme new_colorscheme')
eq('vim_rtp_after', eval('g:colorscheme'))
- write_file(table.concat({colorscheme_folder, 'new_colorscheme.lua'}, sep),
- [[vim.g.colorscheme = 'lua_rtp']])
+ write_file(
+ table.concat({ colorscheme_folder, 'new_colorscheme.lua' }, sep),
+ [[vim.g.colorscheme = 'lua_rtp']]
+ )
exec('colorscheme new_colorscheme')
eq('lua_rtp', eval('g:colorscheme'))
- write_file(table.concat({colorscheme_folder, 'new_colorscheme.vim'}, sep),
- [[let g:colorscheme = 'vim_rtp']])
+ write_file(
+ table.concat({ colorscheme_folder, 'new_colorscheme.vim' }, sep),
+ [[let g:colorscheme = 'vim_rtp']]
+ )
exec('colorscheme new_colorscheme')
eq('vim_rtp', eval('g:colorscheme'))
end)
end)
describe('compiler', function()
- local compiler_folder = table.concat({plug_dir, 'compiler'}, sep)
+ local compiler_folder = table.concat({ plug_dir, 'compiler' }, sep)
before_each(function()
mkdir_p(compiler_folder)
end)
@@ -114,8 +126,8 @@ describe('runtime:', function()
local compiler_file = compiler_folder .. sep .. 'new_compiler.lua'
write_file(compiler_file, [[vim.b.lua_compiler = 1]])
- eq({'new_compiler'}, funcs.getcompletion('new_c', 'compiler'))
- eq({'compiler/new_compiler.lua'}, funcs.getcompletion('compiler/new_c', 'runtime'))
+ eq({ 'new_compiler' }, fn.getcompletion('new_c', 'compiler'))
+ eq({ 'compiler/new_compiler.lua' }, fn.getcompletion('compiler/new_c', 'runtime'))
exec('compiler new_compiler')
@@ -123,126 +135,189 @@ describe('runtime:', function()
end)
it("'rtp' order is respected", function()
- local after_compiler_folder = table.concat({plug_dir, 'after', 'compiler'}, sep)
- mkdir_p(table.concat({compiler_folder, 'new_compiler'}, sep))
- mkdir_p(table.concat({after_compiler_folder, 'new_compiler'}, sep))
+ local after_compiler_folder = table.concat({ plug_dir, 'after', 'compiler' }, sep)
+ mkdir_p(table.concat({ compiler_folder, 'new_compiler' }, sep))
+ mkdir_p(table.concat({ after_compiler_folder, 'new_compiler' }, sep))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/compiler/ are loaded after all files in compiler/.
- write_file(table.concat({compiler_folder, 'new_compiler.vim'}, sep), [[let g:seq ..= 'A']])
- write_file(table.concat({compiler_folder, 'new_compiler.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'B']])
- write_file(table.concat({after_compiler_folder, 'new_compiler.vim'}, sep), [[let g:seq ..= 'a']])
- write_file(table.concat({after_compiler_folder, 'new_compiler.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'b']])
+ write_file(table.concat({ compiler_folder, 'new_compiler.vim' }, sep), [[let g:seq ..= 'A']])
+ write_file(
+ table.concat({ compiler_folder, 'new_compiler.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'B']]
+ )
+ write_file(
+ table.concat({ after_compiler_folder, 'new_compiler.vim' }, sep),
+ [[let g:seq ..= 'a']]
+ )
+ write_file(
+ table.concat({ after_compiler_folder, 'new_compiler.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'b']]
+ )
exec('compiler new_compiler')
eq('ABab', eval('g:seq'))
end)
end)
describe('ftplugin', function()
- local ftplugin_folder = table.concat({plug_dir, 'ftplugin'}, sep)
+ local ftplugin_folder = table.concat({ plug_dir, 'ftplugin' }, sep)
it('lua ftplugins work and are included in cmdline completion', function()
mkdir_p(ftplugin_folder)
- local ftplugin_file = table.concat({ftplugin_folder , 'new-ft.lua'}, sep)
- write_file(ftplugin_file , [[vim.b.lua_ftplugin = 1]])
+ local ftplugin_file = table.concat({ ftplugin_folder, 'new-ft.lua' }, sep)
+ write_file(ftplugin_file, [[vim.b.lua_ftplugin = 1]])
- eq({'new-ft'}, funcs.getcompletion('new-f', 'filetype'))
- eq({'ftplugin/new-ft.lua'}, funcs.getcompletion('ftplugin/new-f', 'runtime'))
+ eq({ 'new-ft' }, fn.getcompletion('new-f', 'filetype'))
+ eq({ 'ftplugin/new-ft.lua' }, fn.getcompletion('ftplugin/new-f', 'runtime'))
exec [[set filetype=new-ft]]
eq(1, eval('b:lua_ftplugin'))
end)
it("'rtp' order is respected", function()
- local after_ftplugin_folder = table.concat({plug_dir, 'after', 'ftplugin'}, sep)
- mkdir_p(table.concat({ftplugin_folder, 'new-ft'}, sep))
- mkdir_p(table.concat({after_ftplugin_folder, 'new-ft'}, sep))
+ local after_ftplugin_folder = table.concat({ plug_dir, 'after', 'ftplugin' }, sep)
+ mkdir_p(table.concat({ ftplugin_folder, 'new-ft' }, sep))
+ mkdir_p(table.concat({ after_ftplugin_folder, 'new-ft' }, sep))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/ftplugin/ are loaded after all files in ftplugin/.
- write_file(table.concat({ftplugin_folder, 'new-ft.vim'}, sep), [[let g:seq ..= 'A']])
- write_file(table.concat({ftplugin_folder, 'new-ft.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'B']])
- write_file(table.concat({ftplugin_folder, 'new-ft_a.vim'}, sep), [[let g:seq ..= 'C']])
- write_file(table.concat({ftplugin_folder, 'new-ft_a.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'D']])
- write_file(table.concat({ftplugin_folder, 'new-ft', 'a.vim'}, sep), [[let g:seq ..= 'E']])
- write_file(table.concat({ftplugin_folder, 'new-ft', 'a.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'F']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft.vim'}, sep), [[let g:seq ..= 'a']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'b']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft_a.vim'}, sep), [[let g:seq ..= 'c']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft_a.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'd']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft', 'a.vim'}, sep), [[let g:seq ..= 'e']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft', 'a.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'f']])
+ write_file(table.concat({ ftplugin_folder, 'new-ft.vim' }, sep), [[let g:seq ..= 'A']])
+ write_file(
+ table.concat({ ftplugin_folder, 'new-ft.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'B']]
+ )
+ write_file(table.concat({ ftplugin_folder, 'new-ft_a.vim' }, sep), [[let g:seq ..= 'C']])
+ write_file(
+ table.concat({ ftplugin_folder, 'new-ft_a.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'D']]
+ )
+ write_file(table.concat({ ftplugin_folder, 'new-ft', 'a.vim' }, sep), [[let g:seq ..= 'E']])
+ write_file(
+ table.concat({ ftplugin_folder, 'new-ft', 'a.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'F']]
+ )
+ write_file(table.concat({ after_ftplugin_folder, 'new-ft.vim' }, sep), [[let g:seq ..= 'a']])
+ write_file(
+ table.concat({ after_ftplugin_folder, 'new-ft.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'b']]
+ )
+ write_file(
+ table.concat({ after_ftplugin_folder, 'new-ft_a.vim' }, sep),
+ [[let g:seq ..= 'c']]
+ )
+ write_file(
+ table.concat({ after_ftplugin_folder, 'new-ft_a.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'd']]
+ )
+ write_file(
+ table.concat({ after_ftplugin_folder, 'new-ft', 'a.vim' }, sep),
+ [[let g:seq ..= 'e']]
+ )
+ write_file(
+ table.concat({ after_ftplugin_folder, 'new-ft', 'a.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'f']]
+ )
exec('setfiletype new-ft')
eq('ABCDEFabcdef', eval('g:seq'))
end)
it("'rtp' order is respected with 'fileignorecase'", function()
exec('set fileignorecase')
- local after_ftplugin_folder = table.concat({plug_dir, 'after', 'ftplugin'}, sep)
- mkdir_p(table.concat({ftplugin_folder, 'new-ft'}, sep))
- mkdir_p(table.concat({after_ftplugin_folder, 'new-ft'}, sep))
+ local after_ftplugin_folder = table.concat({ plug_dir, 'after', 'ftplugin' }, sep)
+ mkdir_p(table.concat({ ftplugin_folder, 'new-ft' }, sep))
+ mkdir_p(table.concat({ after_ftplugin_folder, 'new-ft' }, sep))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/ftplugin/ are loaded after all files in ftplugin/.
- write_file(table.concat({ftplugin_folder, 'new-ft.VIM'}, sep), [[let g:seq ..= 'A']])
- write_file(table.concat({ftplugin_folder, 'new-ft.LUA'}, sep), [[vim.g.seq = vim.g.seq .. 'B']])
- write_file(table.concat({ftplugin_folder, 'new-ft_a.vim'}, sep), [[let g:seq ..= 'C']])
- write_file(table.concat({ftplugin_folder, 'new-ft_a.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'D']])
- write_file(table.concat({ftplugin_folder, 'new-ft', 'a.VIM'}, sep), [[let g:seq ..= 'E']])
- write_file(table.concat({ftplugin_folder, 'new-ft', 'a.LUA'}, sep), [[vim.g.seq = vim.g.seq .. 'F']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft.vim'}, sep), [[let g:seq ..= 'a']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'b']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft_a.VIM'}, sep), [[let g:seq ..= 'c']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft_a.LUA'}, sep), [[vim.g.seq = vim.g.seq .. 'd']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft', 'a.vim'}, sep), [[let g:seq ..= 'e']])
- write_file(table.concat({after_ftplugin_folder, 'new-ft', 'a.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'f']])
+ write_file(table.concat({ ftplugin_folder, 'new-ft.VIM' }, sep), [[let g:seq ..= 'A']])
+ write_file(
+ table.concat({ ftplugin_folder, 'new-ft.LUA' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'B']]
+ )
+ write_file(table.concat({ ftplugin_folder, 'new-ft_a.vim' }, sep), [[let g:seq ..= 'C']])
+ write_file(
+ table.concat({ ftplugin_folder, 'new-ft_a.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'D']]
+ )
+ write_file(table.concat({ ftplugin_folder, 'new-ft', 'a.VIM' }, sep), [[let g:seq ..= 'E']])
+ write_file(
+ table.concat({ ftplugin_folder, 'new-ft', 'a.LUA' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'F']]
+ )
+ write_file(table.concat({ after_ftplugin_folder, 'new-ft.vim' }, sep), [[let g:seq ..= 'a']])
+ write_file(
+ table.concat({ after_ftplugin_folder, 'new-ft.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'b']]
+ )
+ write_file(
+ table.concat({ after_ftplugin_folder, 'new-ft_a.VIM' }, sep),
+ [[let g:seq ..= 'c']]
+ )
+ write_file(
+ table.concat({ after_ftplugin_folder, 'new-ft_a.LUA' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'd']]
+ )
+ write_file(
+ table.concat({ after_ftplugin_folder, 'new-ft', 'a.vim' }, sep),
+ [[let g:seq ..= 'e']]
+ )
+ write_file(
+ table.concat({ after_ftplugin_folder, 'new-ft', 'a.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'f']]
+ )
exec('setfiletype new-ft')
eq('ABCDEFabcdef', eval('g:seq'))
end)
end)
describe('indent', function()
- local indent_folder = table.concat({plug_dir, 'indent'}, sep)
+ local indent_folder = table.concat({ plug_dir, 'indent' }, sep)
it('lua indents work and are included in cmdline completion', function()
mkdir_p(indent_folder)
- local indent_file = table.concat({indent_folder , 'new-ft.lua'}, sep)
- write_file(indent_file , [[vim.b.lua_indent = 1]])
+ local indent_file = table.concat({ indent_folder, 'new-ft.lua' }, sep)
+ write_file(indent_file, [[vim.b.lua_indent = 1]])
- eq({'new-ft'}, funcs.getcompletion('new-f', 'filetype'))
- eq({'indent/new-ft.lua'}, funcs.getcompletion('indent/new-f', 'runtime'))
+ eq({ 'new-ft' }, fn.getcompletion('new-f', 'filetype'))
+ eq({ 'indent/new-ft.lua' }, fn.getcompletion('indent/new-f', 'runtime'))
exec [[set filetype=new-ft]]
eq(1, eval('b:lua_indent'))
end)
it("'rtp' order is respected", function()
- local after_indent_folder = table.concat({plug_dir, 'after', 'indent'}, sep)
- mkdir_p(table.concat({indent_folder, 'new-ft'}, sep))
- mkdir_p(table.concat({after_indent_folder, 'new-ft'}, sep))
+ local after_indent_folder = table.concat({ plug_dir, 'after', 'indent' }, sep)
+ mkdir_p(table.concat({ indent_folder, 'new-ft' }, sep))
+ mkdir_p(table.concat({ after_indent_folder, 'new-ft' }, sep))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/indent/ are loaded after all files in indent/.
- write_file(table.concat({indent_folder, 'new-ft.vim'}, sep), [[let g:seq ..= 'A']])
- write_file(table.concat({indent_folder, 'new-ft.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'B']])
- write_file(table.concat({after_indent_folder, 'new-ft.vim'}, sep), [[let g:seq ..= 'a']])
- write_file(table.concat({after_indent_folder, 'new-ft.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'b']])
+ write_file(table.concat({ indent_folder, 'new-ft.vim' }, sep), [[let g:seq ..= 'A']])
+ write_file(
+ table.concat({ indent_folder, 'new-ft.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'B']]
+ )
+ write_file(table.concat({ after_indent_folder, 'new-ft.vim' }, sep), [[let g:seq ..= 'a']])
+ write_file(
+ table.concat({ after_indent_folder, 'new-ft.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'b']]
+ )
exec('setfiletype new-ft')
eq('ABab', eval('g:seq'))
end)
end)
describe('syntax', function()
- local syntax_folder = table.concat({plug_dir, 'syntax'}, sep)
+ local syntax_folder = table.concat({ plug_dir, 'syntax' }, sep)
before_each(function()
mkdir_p(syntax_folder)
- local syntax_file = table.concat({syntax_folder , 'my-lang.lua'}, sep)
- write_file(syntax_file , [[vim.b.current_syntax = 'my-lang']])
+ local syntax_file = table.concat({ syntax_folder, 'my-lang.lua' }, sep)
+ write_file(syntax_file, [[vim.b.current_syntax = 'my-lang']])
exec([[let b:current_syntax = '']])
end)
@@ -263,27 +338,42 @@ describe('runtime:', function()
end)
it('lua syntaxes are included in cmdline completion', function()
- eq({'my-lang'}, funcs.getcompletion('my-l', 'filetype'))
- eq({'my-lang'}, funcs.getcompletion('my-l', 'syntax'))
- eq({'syntax/my-lang.lua'}, funcs.getcompletion('syntax/my-l', 'runtime'))
+ eq({ 'my-lang' }, fn.getcompletion('my-l', 'filetype'))
+ eq({ 'my-lang' }, fn.getcompletion('my-l', 'syntax'))
+ eq({ 'syntax/my-lang.lua' }, fn.getcompletion('syntax/my-l', 'runtime'))
end)
it("'rtp' order is respected", function()
- local after_syntax_folder = table.concat({plug_dir, 'after', 'syntax'}, sep)
- mkdir_p(table.concat({syntax_folder, 'my-lang'}, sep))
- mkdir_p(table.concat({after_syntax_folder, 'my-lang'}, sep))
+ local after_syntax_folder = table.concat({ plug_dir, 'after', 'syntax' }, sep)
+ mkdir_p(table.concat({ syntax_folder, 'my-lang' }, sep))
+ mkdir_p(table.concat({ after_syntax_folder, 'my-lang' }, sep))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/syntax/ are loaded after all files in syntax/.
- write_file(table.concat({syntax_folder, 'my-lang.vim'}, sep), [[let g:seq ..= 'A']])
- write_file(table.concat({syntax_folder, 'my-lang.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'B']])
- write_file(table.concat({syntax_folder, 'my-lang', 'a.vim'}, sep), [[let g:seq ..= 'C']])
- write_file(table.concat({syntax_folder, 'my-lang', 'a.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'D']])
- write_file(table.concat({after_syntax_folder, 'my-lang.vim'}, sep), [[let g:seq ..= 'a']])
- write_file(table.concat({after_syntax_folder, 'my-lang.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'b']])
- write_file(table.concat({after_syntax_folder, 'my-lang', 'a.vim'}, sep), [[let g:seq ..= 'c']])
- write_file(table.concat({after_syntax_folder, 'my-lang', 'a.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'd']])
+ write_file(table.concat({ syntax_folder, 'my-lang.vim' }, sep), [[let g:seq ..= 'A']])
+ write_file(
+ table.concat({ syntax_folder, 'my-lang.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'B']]
+ )
+ write_file(table.concat({ syntax_folder, 'my-lang', 'a.vim' }, sep), [[let g:seq ..= 'C']])
+ write_file(
+ table.concat({ syntax_folder, 'my-lang', 'a.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'D']]
+ )
+ write_file(table.concat({ after_syntax_folder, 'my-lang.vim' }, sep), [[let g:seq ..= 'a']])
+ write_file(
+ table.concat({ after_syntax_folder, 'my-lang.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'b']]
+ )
+ write_file(
+ table.concat({ after_syntax_folder, 'my-lang', 'a.vim' }, sep),
+ [[let g:seq ..= 'c']]
+ )
+ write_file(
+ table.concat({ after_syntax_folder, 'my-lang', 'a.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'd']]
+ )
exec('setfiletype my-lang')
eq('ABCDabcd', eval('g:seq'))
end)
@@ -291,21 +381,23 @@ describe('runtime:', function()
describe('spell', function()
it("loads spell/LANG.{vim,lua} respecting 'rtp' order", function()
- local spell_folder = table.concat({plug_dir, 'spell'}, sep)
- local after_spell_folder = table.concat({plug_dir, 'after', 'spell'}, sep)
- mkdir_p(table.concat({spell_folder, 'Xtest'}, sep))
- mkdir_p(table.concat({after_spell_folder, 'Xtest'}, sep))
+ local spell_folder = table.concat({ plug_dir, 'spell' }, sep)
+ local after_spell_folder = table.concat({ plug_dir, 'after', 'spell' }, sep)
+ mkdir_p(table.concat({ spell_folder, 'Xtest' }, sep))
+ mkdir_p(table.concat({ after_spell_folder, 'Xtest' }, sep))
exec('set rtp+=' .. plug_dir .. '/after')
exec('let g:seq = ""')
-- A .lua file is loaded after a .vim file if they only differ in extension.
-- All files in after/spell/ are loaded after all files in spell/.
- write_file(table.concat({spell_folder, 'Xtest.vim'}, sep), [[let g:seq ..= 'A']])
- write_file(table.concat({spell_folder, 'Xtest.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'B']])
- write_file(table.concat({after_spell_folder, 'Xtest.vim'}, sep), [[let g:seq ..= 'a']])
- write_file(table.concat({after_spell_folder, 'Xtest.lua'}, sep), [[vim.g.seq = vim.g.seq .. 'b']])
+ write_file(table.concat({ spell_folder, 'Xtest.vim' }, sep), [[let g:seq ..= 'A']])
+ write_file(table.concat({ spell_folder, 'Xtest.lua' }, sep), [[vim.g.seq = vim.g.seq .. 'B']])
+ write_file(table.concat({ after_spell_folder, 'Xtest.vim' }, sep), [[let g:seq ..= 'a']])
+ write_file(
+ table.concat({ after_spell_folder, 'Xtest.lua' }, sep),
+ [[vim.g.seq = vim.g.seq .. 'b']]
+ )
exec('set spelllang=Xtest')
eq('ABab', eval('g:seq'))
end)
end)
-
end)
diff --git a/test/functional/lua/secure_spec.lua b/test/functional/lua/secure_spec.lua
index fc20a06390..7aed711b23 100644
--- a/test/functional/lua/secure_spec.lua
+++ b/test/functional/lua/secure_spec.lua
@@ -6,11 +6,11 @@ local clear = helpers.clear
local command = helpers.command
local pathsep = helpers.get_pathsep()
local is_os = helpers.is_os
-local meths = helpers.meths
+local api = helpers.api
local exec_lua = helpers.exec_lua
local feed_command = helpers.feed_command
local feed = helpers.feed
-local funcs = helpers.funcs
+local fn = helpers.fn
local pcall_err = helpers.pcall_err
local matches = helpers.matches
@@ -19,11 +19,14 @@ describe('vim.secure', function()
local xstate = 'Xstate'
setup(function()
- clear{env={XDG_STATE_HOME=xstate}}
+ clear { env = { XDG_STATE_HOME = xstate } }
helpers.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
- helpers.write_file('Xfile', [[
+ helpers.write_file(
+ 'Xfile',
+ [[
let g:foobar = 42
- ]])
+ ]]
+ )
end)
teardown(function()
@@ -35,132 +38,139 @@ describe('vim.secure', function()
local screen = Screen.new(80, 8)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {bold = true, reverse = true},
- [3] = {bold = true, foreground = Screen.colors.SeaGreen},
- [4] = {reverse = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, reverse = true },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [4] = { reverse = true },
})
--- XXX: screen:expect() may fail if this path is too long.
- local cwd = funcs.getcwd()
+ local cwd = fn.getcwd()
-- Need to use feed_command instead of exec_lua because of the confirmation prompt
feed_command([[lua vim.secure.read('Xfile')]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2: }|
:lua vim.secure.read('Xfile') |
- {3:]] .. cwd .. pathsep .. [[Xfile is not trusted.}{MATCH:%s+}|
+ {3:]]
+ .. cwd
+ .. pathsep
+ .. [[Xfile is not trusted.}{MATCH:%s+}|
{3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
- ]]}
+ ]],
+ }
feed('d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
- ]]}
+ ]],
+ }
- local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', cwd .. pathsep .. 'Xfile'), vim.trim(trust))
- eq(helpers.NIL, exec_lua([[return vim.secure.read('Xfile')]]))
+ eq(vim.NIL, exec_lua([[return vim.secure.read('Xfile')]]))
- os.remove(funcs.stdpath('state') .. pathsep .. 'trust')
+ os.remove(fn.stdpath('state') .. pathsep .. 'trust')
feed_command([[lua vim.secure.read('Xfile')]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2: }|
:lua vim.secure.read('Xfile') |
- {3:]] .. cwd .. pathsep .. [[Xfile is not trusted.}{MATCH:%s+}|
+ {3:]]
+ .. cwd
+ .. pathsep
+ .. [[Xfile is not trusted.}{MATCH:%s+}|
{3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
- ]]}
+ ]],
+ }
feed('a')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
- ]]}
+ ]],
+ }
- local hash = funcs.sha256(helpers.read_file('Xfile'))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ local hash = fn.sha256(helpers.read_file('Xfile'))
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, cwd .. pathsep .. 'Xfile'), vim.trim(trust))
- eq(helpers.NIL, exec_lua([[vim.secure.read('Xfile')]]))
+ eq(vim.NIL, exec_lua([[vim.secure.read('Xfile')]]))
- os.remove(funcs.stdpath('state') .. pathsep .. 'trust')
+ os.remove(fn.stdpath('state') .. pathsep .. 'trust')
feed_command([[lua vim.secure.read('Xfile')]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2: }|
:lua vim.secure.read('Xfile') |
- {3:]] .. cwd .. pathsep .. [[Xfile is not trusted.}{MATCH:%s+}|
+ {3:]]
+ .. cwd
+ .. pathsep
+ .. [[Xfile is not trusted.}{MATCH:%s+}|
{3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
- ]]}
+ ]],
+ }
feed('i')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
- ]]}
+ ]],
+ }
-- Trust database is not updated
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(nil, trust)
feed_command([[lua vim.secure.read('Xfile')]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2: }|
:lua vim.secure.read('Xfile') |
- {3:]] .. cwd .. pathsep .. [[Xfile is not trusted.}{MATCH:%s+}|
+ {3:]]
+ .. cwd
+ .. pathsep
+ .. [[Xfile is not trusted.}{MATCH:%s+}|
{3:[i]gnore, (v)iew, (d)eny, (a)llow: }^ |
- ]]}
+ ]],
+ }
feed('v')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^let g:foobar = 42 |
- {1:~ }|
- {1:~ }|
- {2:]] .. funcs.fnamemodify(cwd, ':~') .. pathsep .. [[Xfile [RO]{MATCH:%s+}}|
+ {1:~ }|*2
+ {2:]]
+ .. fn.fnamemodify(cwd, ':~')
+ .. pathsep
+ .. [[Xfile [RO]{MATCH:%s+}}|
|
{1:~ }|
{4:[No Name] }|
|
- ]]}
+ ]],
+ }
-- Trust database is not updated
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(nil, trust)
-- Cannot write file
pcall_err(command, 'write')
- eq(true, meths.get_option_value('readonly', {}))
+ eq(true, api.nvim_get_option_value('readonly', {}))
end)
end)
@@ -168,7 +178,7 @@ describe('vim.secure', function()
local xstate = 'Xstate'
setup(function()
- clear{env={XDG_STATE_HOME=xstate}}
+ clear { env = { XDG_STATE_HOME = xstate } }
helpers.mkdir_p(xstate .. pathsep .. (is_os('win') and 'nvim-data' or 'nvim'))
end)
@@ -185,95 +195,113 @@ describe('vim.secure', function()
end)
it('returns error when passing both path and bufnr', function()
- matches('"path" and "bufnr" are mutually exclusive',
- pcall_err(exec_lua, [[vim.secure.trust({action='deny', bufnr=0, path='test_file'})]]))
+ matches(
+ '"path" and "bufnr" are mutually exclusive',
+ pcall_err(exec_lua, [[vim.secure.trust({action='deny', bufnr=0, path='test_file'})]])
+ )
end)
it('returns error when passing neither path or bufnr', function()
- matches('one of "path" or "bufnr" is required',
- pcall_err(exec_lua, [[vim.secure.trust({action='deny'})]]))
+ matches(
+ 'one of "path" or "bufnr" is required',
+ pcall_err(exec_lua, [[vim.secure.trust({action='deny'})]])
+ )
end)
it('trust then deny then remove a file using bufnr', function()
- local cwd = funcs.getcwd()
- local hash = funcs.sha256(helpers.read_file('test_file'))
+ local cwd = fn.getcwd()
+ local hash = fn.sha256(helpers.read_file('test_file'))
local full_path = cwd .. pathsep .. 'test_file'
command('edit test_file')
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
- local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
+ local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, full_path), vim.trim(trust))
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]]))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]]))
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', full_path), vim.trim(trust))
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]]))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]]))
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq('', vim.trim(trust))
end)
it('deny then trust then remove a file using bufnr', function()
- local cwd = funcs.getcwd()
- local hash = funcs.sha256(helpers.read_file('test_file'))
+ local cwd = fn.getcwd()
+ local hash = fn.sha256(helpers.read_file('test_file'))
local full_path = cwd .. pathsep .. 'test_file'
command('edit test_file')
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]]))
- local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='deny', bufnr=0})}]]))
+ local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', full_path), vim.trim(trust))
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, full_path), vim.trim(trust))
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]]))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='remove', bufnr=0})}]]))
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq('', vim.trim(trust))
end)
it('trust using bufnr then deny then remove a file using path', function()
- local cwd = funcs.getcwd()
- local hash = funcs.sha256(helpers.read_file('test_file'))
+ local cwd = fn.getcwd()
+ local hash = fn.sha256(helpers.read_file('test_file'))
local full_path = cwd .. pathsep .. 'test_file'
command('edit test_file')
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
- local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
+ local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, full_path), vim.trim(trust))
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='deny', path='test_file'})}]]))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq(
+ { true, full_path },
+ exec_lua([[return {vim.secure.trust({action='deny', path='test_file'})}]])
+ )
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', full_path), vim.trim(trust))
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='remove', path='test_file'})}]]))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq(
+ { true, full_path },
+ exec_lua([[return {vim.secure.trust({action='remove', path='test_file'})}]])
+ )
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq('', vim.trim(trust))
end)
it('deny then trust then remove a file using bufnr', function()
- local cwd = funcs.getcwd()
- local hash = funcs.sha256(helpers.read_file('test_file'))
+ local cwd = fn.getcwd()
+ local hash = fn.sha256(helpers.read_file('test_file'))
local full_path = cwd .. pathsep .. 'test_file'
command('edit test_file')
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='deny', path='test_file'})}]]))
- local trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq(
+ { true, full_path },
+ exec_lua([[return {vim.secure.trust({action='deny', path='test_file'})}]])
+ )
+ local trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('! %s', full_path), vim.trim(trust))
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq({ true, full_path }, exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq(string.format('%s %s', hash, full_path), vim.trim(trust))
- eq({true, full_path}, exec_lua([[return {vim.secure.trust({action='remove', path='test_file'})}]]))
- trust = helpers.read_file(funcs.stdpath('state') .. pathsep .. 'trust')
+ eq(
+ { true, full_path },
+ exec_lua([[return {vim.secure.trust({action='remove', path='test_file'})}]])
+ )
+ trust = helpers.read_file(fn.stdpath('state') .. pathsep .. 'trust')
eq('', vim.trim(trust))
end)
it('trust returns error when buffer not associated to file', function()
command('new')
- eq({false, 'buffer is not associated with a file'},
- exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]]))
+ eq(
+ { false, 'buffer is not associated with a file' },
+ exec_lua([[return {vim.secure.trust({action='allow', bufnr=0})}]])
+ )
end)
end)
end)
diff --git a/test/functional/lua/snippet_spec.lua b/test/functional/lua/snippet_spec.lua
index f0b3b44139..e981bc6261 100644
--- a/test/functional/lua/snippet_spec.lua
+++ b/test/functional/lua/snippet_spec.lua
@@ -5,9 +5,11 @@ local clear = helpers.clear
local eq = helpers.eq
local exec_lua = helpers.exec_lua
local feed = helpers.feed
+local fn = helpers.fn
local matches = helpers.matches
local pcall_err = helpers.pcall_err
-local sleep = helpers.sleep
+local poke_eventloop = helpers.poke_eventloop
+local retry = helpers.retry
describe('vim.snippet', function()
before_each(function()
@@ -35,6 +37,12 @@ describe('vim.snippet', function()
eq(expected, buf_lines(0))
end
+ local function wait_for_pum()
+ retry(nil, nil, function()
+ eq(1, fn.pumvisible())
+ end)
+ end
+
--- @param snippet string
--- @param err string
local function test_expand_fail(snippet, err)
@@ -154,7 +162,10 @@ describe('vim.snippet', function()
end)
it('errors with multiple placeholders for the same index', function()
- test_expand_fail('class ${1:Foo} { void ${1:foo}() {} }', 'multiple placeholders for tabstop $1')
+ test_expand_fail(
+ 'class ${1:Foo} { void ${1:foo}() {} }',
+ 'multiple placeholders for tabstop $1'
+ )
end)
it('errors with multiple $0 tabstops', function()
@@ -162,30 +173,36 @@ describe('vim.snippet', function()
end)
it('cancels session when deleting the snippet', function()
- test_expand_success({ 'local function $1()', ' $0', 'end' }, { 'local function ()', ' ', 'end' })
+ test_expand_success(
+ { 'local function $1()', ' $0', 'end' },
+ { 'local function ()', ' ', 'end' }
+ )
feed('<esc>Vjjd')
eq(false, exec_lua('return vim.snippet.active()'))
end)
it('cancels session when inserting outside snippet region', function()
feed('i<cr>')
- test_expand_success({ 'local function $1()', ' $0', 'end' }, { '', 'local function ()', ' ', 'end' })
+ test_expand_success(
+ { 'local function $1()', ' $0', 'end' },
+ { '', 'local function ()', ' ', 'end' }
+ )
feed('<esc>O-- A comment')
eq(false, exec_lua('return vim.snippet.active()'))
end)
- it('inserts choice', function ()
+ it('inserts choice', function()
test_expand_success({ 'console.${1|assert,log,error|}()' }, { 'console.()' })
- sleep(100)
+ wait_for_pum()
feed('<Down><C-y>')
eq({ 'console.log()' }, buf_lines(0))
end)
- it('closes the choice completion menu when jumping', function ()
+ it('closes the choice completion menu when jumping', function()
test_expand_success({ 'console.${1|assert,log,error|}($2)' }, { 'console.()' })
- sleep(100)
+ wait_for_pum()
exec_lua('vim.snippet.jump(1)')
- eq(0, exec_lua('return vim.fn.pumvisible()'))
+ eq(0, fn.pumvisible())
end)
it('jumps to next tabstop after inserting choice', function()
@@ -193,10 +210,34 @@ describe('vim.snippet', function()
{ '${1|public,protected,private|} function ${2:name}() {', '\t$0', '}' },
{ ' function name() {', '\t', '}' }
)
- sleep(100)
+ wait_for_pum()
feed('<C-y><Tab>')
- sleep(10)
+ poke_eventloop()
feed('foo')
eq({ 'public function foo() {', '\t', '}' }, buf_lines(0))
end)
+
+ it('jumps through adjacent tabstops', function()
+ test_expand_success(
+ { 'for i=1,${1:to}${2:,step} do\n\t$3\nend' },
+ { 'for i=1,to,step do', '\t', 'end' }
+ )
+ feed('10')
+ feed('<Tab>')
+ poke_eventloop()
+ feed(',2')
+ eq({ 'for i=1,10,2 do', '\t', 'end' }, buf_lines(0))
+ end)
+
+ it('updates snippet state when built-in completion menu is visible', function()
+ test_expand_success({ '$1 = function($2)\n$3\nend' }, { ' = function()', '', 'end' })
+ -- Show the completion menu.
+ feed('<C-n>')
+ -- Make sure no item is selected.
+ feed('<C-p>')
+ -- Jump forward (the 2nd tabstop).
+ exec_lua('vim.snippet.jump(1)')
+ feed('foo')
+ eq({ ' = function(foo)', '', 'end' }, buf_lines(0))
+ end)
end)
diff --git a/test/functional/lua/spell_spec.lua b/test/functional/lua/spell_spec.lua
index b3de6a0912..e82dd7b4a0 100644
--- a/test/functional/lua/spell_spec.lua
+++ b/test/functional/lua/spell_spec.lua
@@ -11,43 +11,32 @@ describe('vim.spell', function()
describe('.check', function()
local check = function(x, exp)
- return eq(exp, exec_lua("return vim.spell.check(...)", x))
+ return eq(exp, exec_lua('return vim.spell.check(...)', x))
end
it('can handle nil', function()
- eq([[bad argument #1 to 'check' (expected string)]],
- pcall_err(exec_lua, [[vim.spell.check(nil)]]))
+ eq(
+ [[bad argument #1 to 'check' (expected string)]],
+ pcall_err(exec_lua, [[vim.spell.check(nil)]])
+ )
end)
it('can check spellings', function()
check('hello', {})
- check(
- 'helloi',
- {{"helloi", "bad", 1}}
- )
+ check('helloi', { { 'helloi', 'bad', 1 } })
- check(
- 'hello therei',
- {{"therei", "bad", 7}}
- )
+ check('hello therei', { { 'therei', 'bad', 7 } })
- check(
- 'hello. there',
- {{"there", "caps", 8}}
- )
+ check('hello. there', { { 'there', 'caps', 8 } })
- check(
- 'neovim cna chkc spellins. okay?',
- {
- {"neovim" , "bad" , 1},
- {"cna" , "bad" , 8},
- {"chkc" , "bad" , 12},
- {"spellins", "bad" , 17},
- {"okay" , "caps", 27}
- }
- )
+ check('neovim cna chkc spellins. okay?', {
+ { 'neovim', 'bad', 1 },
+ { 'cna', 'bad', 8 },
+ { 'chkc', 'bad', 12 },
+ { 'spellins', 'bad', 17 },
+ { 'okay', 'caps', 27 },
+ })
end)
-
end)
end)
diff --git a/test/functional/lua/system_spec.lua b/test/functional/lua/system_spec.lua
index a988d3f0d7..cb561f0771 100644
--- a/test/functional/lua/system_spec.lua
+++ b/test/functional/lua/system_spec.lua
@@ -4,7 +4,8 @@ local exec_lua = helpers.exec_lua
local eq = helpers.eq
local function system_sync(cmd, opts)
- return exec_lua([[
+ return exec_lua(
+ [[
local cmd, opts = ...
local obj = vim.system(...)
@@ -21,11 +22,15 @@ local function system_sync(cmd, opts)
assert(not proc, 'process still exists')
return res
- ]], cmd, opts)
+ ]],
+ cmd,
+ opts
+ )
end
local function system_async(cmd, opts)
- return exec_lua([[
+ return exec_lua(
+ [[
local cmd, opts = ...
_G.done = false
local obj = vim.system(cmd, opts, function(obj)
@@ -44,7 +49,10 @@ local function system_async(cmd, opts)
assert(not proc, 'process still exists')
return _G.ret
- ]], cmd, opts)
+ ]],
+ cmd,
+ opts
+ )
end
describe('vim.system', function()
@@ -52,10 +60,10 @@ describe('vim.system', function()
clear()
end)
- for name, system in pairs{ sync = system_sync, async = system_async, } do
- describe('('..name..')', function()
+ for name, system in pairs { sync = system_sync, async = system_async } do
+ describe('(' .. name .. ')', function()
it('can run simple commands', function()
- eq('hello\n', system({'echo', 'hello' }, { text = true }).stdout)
+ eq('hello\n', system({ 'echo', 'hello' }, { text = true }).stdout)
end)
it('handle input', function()
@@ -67,7 +75,7 @@ describe('vim.system', function()
code = 124,
signal = 15,
stdout = '',
- stderr = ''
+ stderr = '',
}, system({ 'sleep', '10' }, { timeout = 1000 }))
end)
end)
@@ -97,4 +105,17 @@ describe('vim.system', function()
]])
end)
+ it('SystemObj:wait() does not process non-fast events #27292', function()
+ eq(
+ false,
+ exec_lua([[
+ _G.processed = false
+ local cmd = vim.system({ 'sleep', '1' })
+ vim.schedule(function() _G.processed = true end)
+ cmd:wait()
+ return _G.processed
+ ]])
+ )
+ eq(true, exec_lua([[return _G.processed]]))
+ end)
end)
diff --git a/test/functional/lua/text_spec.lua b/test/functional/lua/text_spec.lua
index 68206557c3..e31aa63768 100644
--- a/test/functional/lua/text_spec.lua
+++ b/test/functional/lua/text_spec.lua
@@ -20,4 +20,3 @@ describe('vim.text', function()
end)
end)
end)
-
diff --git a/test/functional/lua/thread_spec.lua b/test/functional/lua/thread_spec.lua
index e79d26a641..c1981e19d4 100644
--- a/test/functional/lua/thread_spec.lua
+++ b/test/functional/lua/thread_spec.lua
@@ -6,7 +6,7 @@ local feed = helpers.feed
local eq = helpers.eq
local exec_lua = helpers.exec_lua
local next_msg = helpers.next_msg
-local NIL = helpers.NIL
+local NIL = vim.NIL
local pcall_err = helpers.pcall_err
describe('thread', function()
@@ -17,11 +17,11 @@ describe('thread', function()
screen = Screen.new(50, 10)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {bold = true, reverse = true},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [5] = {bold = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, reverse = true },
+ [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [5] = { bold = true },
})
end)
@@ -35,11 +35,7 @@ describe('thread', function()
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2: }|
{3:Error in luv thread:} |
{3:[string "<nvim>"]:2: Error in thread entry func} |
@@ -66,11 +62,7 @@ describe('thread', function()
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2: }|
{3:Error in luv callback, thread:} |
{3:[string "<nvim>"]:6: Error in thread callback} |
@@ -91,14 +83,7 @@ describe('thread', function()
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
print in thread |
]])
end)
@@ -113,14 +98,7 @@ describe('thread', function()
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
{ 1, 2 } |
]])
end)
@@ -172,7 +150,7 @@ describe('thread', function()
thread_test:do_test()
]]
- eq({'notification', 'result', {true}}, next_msg())
+ eq({ 'notification', 'result', { true } }, next_msg())
end)
it('uv', function()
@@ -204,7 +182,7 @@ describe('thread', function()
thread_test:do_test()
]]
- eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ eq({ 'notification', 'result', { { 33, NIL, 'text' } } }, next_msg())
end)
it('json', function()
@@ -219,7 +197,7 @@ describe('thread', function()
thread_test:do_test()
]]
- eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ eq({ 'notification', 'result', { { 33, NIL, 'text' } } }, next_msg())
end)
it('diff', function()
@@ -234,14 +212,18 @@ describe('thread', function()
thread_test:do_test()
]]
- eq({'notification', 'result',
- {table.concat({
+ eq({
+ 'notification',
+ 'result',
+ {
+ table.concat({
'@@ -1 +1 @@',
'-Hello',
'+Helli',
- ''
- }, '\n')}},
- next_msg())
+ '',
+ }, '\n'),
+ },
+ }, next_msg())
end)
end)
end)
@@ -263,28 +245,30 @@ describe('threadpool', function()
work:queue()
]]
- eq({'notification', 'result', {true}}, next_msg())
+ eq({ 'notification', 'result', { true } }, next_msg())
end)
it('with invalid argument', function()
- local status = pcall_err(exec_lua, [[
+ local status = pcall_err(
+ exec_lua,
+ [[
local work = vim.uv.new_thread(function() end, function() end)
work:queue({})
- ]])
+ ]]
+ )
- eq([[Error: thread arg not support type 'function' at 1]],
- status)
+ eq([[Error: thread arg not support type 'function' at 1]], status)
end)
it('with invalid return value', function()
local screen = Screen.new(50, 10)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {bold = true, reverse = true},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [5] = {bold = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, reverse = true },
+ [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [5] = { bold = true },
})
exec_lua [[
@@ -294,11 +278,7 @@ describe('threadpool', function()
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2: }|
{3:Error in luv thread:} |
{3:Error: thread arg not support type 'table' at 1} |
@@ -364,7 +344,7 @@ describe('threadpool', function()
threadpool_test:do_test()
]]
- eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ eq({ 'notification', 'result', { { 33, NIL, 'text' } } }, next_msg())
end)
it('json', function()
@@ -380,7 +360,7 @@ describe('threadpool', function()
threadpool_test:do_test()
]]
- eq({'notification', 'result', {{33, NIL, 'text'}}}, next_msg())
+ eq({ 'notification', 'result', { { 33, NIL, 'text' } } }, next_msg())
end)
it('work', function()
@@ -395,14 +375,18 @@ describe('threadpool', function()
threadpool_test:do_test()
]]
- eq({'notification', 'result',
- {table.concat({
+ eq({
+ 'notification',
+ 'result',
+ {
+ table.concat({
'@@ -1 +1 @@',
'-Hello',
'+Helli',
- ''
- }, '\n')}},
- next_msg())
+ '',
+ }, '\n'),
+ },
+ }, next_msg())
end)
end)
end)
diff --git a/test/functional/lua/ui_event_spec.lua b/test/functional/lua/ui_event_spec.lua
index 373d45da61..3e46018682 100644
--- a/test/functional/lua/ui_event_spec.lua
+++ b/test/functional/lua/ui_event_spec.lua
@@ -4,8 +4,7 @@ local eq = helpers.eq
local exec_lua = helpers.exec_lua
local clear = helpers.clear
local feed = helpers.feed
-local funcs = helpers.funcs
-local inspect = require'vim.inspect'
+local fn = helpers.fn
describe('vim.ui_attach', function()
local screen
@@ -26,60 +25,67 @@ describe('vim.ui_attach', function()
end
]]
- screen = Screen.new(40,5)
+ screen = Screen.new(40, 5)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1};
- [2] = {bold = true};
- [3] = {background = Screen.colors.Grey};
- [4] = {background = Screen.colors.LightMagenta};
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true },
+ [3] = { background = Screen.colors.Grey },
+ [4] = { background = Screen.colors.LightMagenta },
})
screen:attach()
end)
local function expect_events(expected)
- local evs = exec_lua "return get_events(...)"
- eq(expected, evs, inspect(evs))
+ local evs = exec_lua 'return get_events(...)'
+ eq(expected, evs, vim.inspect(evs))
end
it('can receive popupmenu events', function()
exec_lua [[ vim.ui_attach(ns, {ext_popupmenu=true}, on_event) ]]
feed('ifo')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
fo^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:-- INSERT --} |
- ]]}
+ ]],
+ }
- funcs.complete(1, {'food', 'foobar', 'foo'})
- screen:expect{grid=[[
+ fn.complete(1, { 'food', 'foobar', 'foo' })
+ screen:expect {
+ grid = [[
food^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:-- INSERT --} |
- ]]}
+ ]],
+ }
expect_events {
- { "popupmenu_show", { { "food", "", "", "" }, { "foobar", "", "", "" }, { "foo", "", "", "" } }, 0, 0, 0, 1 };
+ {
+ 'popupmenu_show',
+ { { 'food', '', '', '' }, { 'foobar', '', '', '' }, { 'foo', '', '', '' } },
+ 0,
+ 0,
+ 0,
+ 1,
+ },
}
feed '<c-n>'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
foobar^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:-- INSERT --} |
- ]]}
+ ]],
+ }
expect_events {
- { "popupmenu_select", 1 };
+ { 'popupmenu_select', 1 },
}
feed '<c-y>'
screen:expect_unchanged()
expect_events {
- { "popupmenu_hide" };
+ { 'popupmenu_hide' },
}
-- vim.ui_detach() stops events, and reenables builtin pum immediately
@@ -88,26 +94,31 @@ describe('vim.ui_attach', function()
vim.fn.complete(1, {'food', 'foobar', 'foo'})
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
food^ |
{3:food }{1: }|
{4:foobar }{1: }|
{4:foo }{1: }|
{2:-- INSERT --} |
- ]]}
- expect_events {
+ ]],
}
-
+ expect_events {}
end)
it('does not crash on exit', function()
- helpers.funcs.system({
+ fn.system({
helpers.nvim_prog,
- '-u', 'NONE',
- '-i', 'NONE',
- '--cmd', [[ lua ns = vim.api.nvim_create_namespace 'testspace' ]],
- '--cmd', [[ lua vim.ui_attach(ns, {ext_popupmenu=true}, function() end) ]],
- '--cmd', 'quitall!',
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ [[ lua ns = vim.api.nvim_create_namespace 'testspace' ]],
+ '--cmd',
+ [[ lua vim.ui_attach(ns, {ext_popupmenu=true}, function() end) ]],
+ '--cmd',
+ 'quitall!',
})
eq(0, helpers.eval('v:shell_error'))
end)
@@ -136,6 +147,6 @@ describe('vim.ui_attach', function()
{ 'echomsg', { { 0, 'message3' } } },
},
},
- }, actual, inspect(actual))
+ }, actual, vim.inspect(actual))
end)
end)
diff --git a/test/functional/lua/ui_spec.lua b/test/functional/lua/ui_spec.lua
index d4c150c5f2..e769843b19 100644
--- a/test/functional/lua/ui_spec.lua
+++ b/test/functional/lua/ui_spec.lua
@@ -16,7 +16,7 @@ describe('vim.ui', function()
describe('select()', function()
it('can select an item', function()
- local result = exec_lua[[
+ local result = exec_lua [[
local items = {
{ name = 'Item 1' },
{ name = 'Item 2' },
@@ -51,7 +51,7 @@ describe('vim.ui', function()
describe('input()', function()
it('can input text', function()
- local result = exec_lua[[
+ local result = exec_lua [[
local opts = {
prompt = 'Input: ',
}
@@ -117,38 +117,44 @@ describe('vim.ui', function()
it('can return nil when interrupted with Ctrl-C #18144', function()
feed(':lua result = "on_confirm not called"<cr>')
feed(':lua vim.ui.input({}, function(input) result = input end)<cr>')
- poke_eventloop() -- This is needed because Ctrl-C flushes input
+ poke_eventloop() -- This is needed because Ctrl-C flushes input
feed('Inputted Text<c-c>')
eq(true, exec_lua('return (nil == result)'))
end)
- it('can return the identical object when an arbitrary opts.cancelreturn object is given', function()
- feed(':lua fn = function() return 42 end<CR>')
- eq(42, exec_lua('return fn()'))
- feed(':lua vim.ui.input({ cancelreturn = fn }, function(input) result = input end)<cr>')
- feed('cancel<esc>')
- eq(true, exec_lua('return (result == fn)'))
- eq(42, exec_lua('return result()'))
- end)
-
+ it(
+ 'can return the identical object when an arbitrary opts.cancelreturn object is given',
+ function()
+ feed(':lua fn = function() return 42 end<CR>')
+ eq(42, exec_lua('return fn()'))
+ feed(':lua vim.ui.input({ cancelreturn = fn }, function(input) result = input end)<cr>')
+ feed('cancel<esc>')
+ eq(true, exec_lua('return (result == fn)'))
+ eq(42, exec_lua('return result()'))
+ end
+ )
end)
describe('open()', function()
it('validation', function()
if is_os('win') or not is_ci('github') then
- exec_lua[[vim.system = function() return { wait=function() return { code=3} end } end]]
+ exec_lua [[vim.system = function() return { wait=function() return { code=3} end } end]]
end
if not is_os('bsd') then
- matches('vim.ui.open: command failed %(%d%): { "[^"]+", .*"non%-existent%-file" }',
- exec_lua[[local _, err = vim.ui.open('non-existent-file') ; return err]])
+ matches(
+ 'vim.ui.open: command failed %(%d%): { "[^"]+", .*"non%-existent%-file" }',
+ exec_lua [[local _, err = vim.ui.open('non-existent-file') ; return err]]
+ )
end
- exec_lua[[
+ exec_lua [[
vim.fn.has = function() return 0 end
vim.fn.executable = function() return 0 end
]]
- eq('vim.ui.open: no handler found (tried: wslview, xdg-open)',
- exec_lua[[local _, err = vim.ui.open('foo') ; return err]])
+ eq(
+ 'vim.ui.open: no handler found (tried: explorer.exe, xdg-open)',
+ exec_lua [[local _, err = vim.ui.open('foo') ; return err]]
+ )
end)
end)
end)
diff --git a/test/functional/lua/uri_spec.lua b/test/functional/lua/uri_spec.lua
index 416e9e1f02..dacaf95867 100644
--- a/test/functional/lua/uri_spec.lua
+++ b/test/functional/lua/uri_spec.lua
@@ -16,20 +16,23 @@ describe('URI methods', function()
it('file path includes only ascii characters', function()
exec_lua("filepath = '/Foo/Bar/Baz.txt'")
- eq('file:///Foo/Bar/Baz.txt', exec_lua("return vim.uri_from_fname(filepath)"))
+ eq('file:///Foo/Bar/Baz.txt', exec_lua('return vim.uri_from_fname(filepath)'))
end)
it('file path including white space', function()
exec_lua("filepath = '/Foo /Bar/Baz.txt'")
- eq('file:///Foo%20/Bar/Baz.txt', exec_lua("return vim.uri_from_fname(filepath)"))
+ eq('file:///Foo%20/Bar/Baz.txt', exec_lua('return vim.uri_from_fname(filepath)'))
end)
it('file path including Unicode characters', function()
exec_lua("filepath = '/xy/åäö/ɧ/汉语/↥/🤦/🦄/aÌŠ/بÙÙŠÙŽÙ‘.txt'")
-- The URI encoding should be case-insensitive
- eq('file:///xy/%c3%a5%c3%a4%c3%b6/%c9%a7/%e6%b1%89%e8%af%ad/%e2%86%a5/%f0%9f%a4%a6/%f0%9f%a6%84/a%cc%8a/%d8%a8%d9%90%d9%8a%d9%8e%d9%91.txt', exec_lua("return vim.uri_from_fname(filepath)"))
+ eq(
+ 'file:///xy/%c3%a5%c3%a4%c3%b6/%c9%a7/%e6%b1%89%e8%af%ad/%e2%86%a5/%f0%9f%a4%a6/%f0%9f%a6%84/a%cc%8a/%d8%a8%d9%90%d9%8a%d9%8e%d9%91.txt',
+ exec_lua('return vim.uri_from_fname(filepath)')
+ )
end)
end)
@@ -37,19 +40,22 @@ describe('URI methods', function()
it('file path includes only ascii characters', function()
exec_lua([[filepath = 'C:\\Foo\\Bar\\Baz.txt']])
- eq('file:///C:/Foo/Bar/Baz.txt', exec_lua("return vim.uri_from_fname(filepath)"))
+ eq('file:///C:/Foo/Bar/Baz.txt', exec_lua('return vim.uri_from_fname(filepath)'))
end)
it('file path including white space', function()
exec_lua([[filepath = 'C:\\Foo \\Bar\\Baz.txt']])
- eq('file:///C:/Foo%20/Bar/Baz.txt', exec_lua("return vim.uri_from_fname(filepath)"))
+ eq('file:///C:/Foo%20/Bar/Baz.txt', exec_lua('return vim.uri_from_fname(filepath)'))
end)
it('file path including Unicode characters', function()
exec_lua([[filepath = 'C:\\xy\\åäö\\ɧ\\汉语\\↥\\🤦\\🦄\\aÌŠ\\بÙÙŠÙŽÙ‘.txt']])
- eq('file:///C:/xy/%c3%a5%c3%a4%c3%b6/%c9%a7/%e6%b1%89%e8%af%ad/%e2%86%a5/%f0%9f%a4%a6/%f0%9f%a6%84/a%cc%8a/%d8%a8%d9%90%d9%8a%d9%8e%d9%91.txt', exec_lua("return vim.uri_from_fname(filepath)"))
+ eq(
+ 'file:///C:/xy/%c3%a5%c3%a4%c3%b6/%c9%a7/%e6%b1%89%e8%af%ad/%e2%86%a5/%f0%9f%a4%a6/%f0%9f%a6%84/a%cc%8a/%d8%a8%d9%90%d9%8a%d9%8e%d9%91.txt',
+ exec_lua('return vim.uri_from_fname(filepath)')
+ )
end)
end)
end)
@@ -59,19 +65,19 @@ describe('URI methods', function()
it('file path includes only ascii characters', function()
exec_lua("uri = 'file:///Foo/Bar/Baz.txt'")
- eq('/Foo/Bar/Baz.txt', exec_lua("return vim.uri_to_fname(uri)"))
+ eq('/Foo/Bar/Baz.txt', exec_lua('return vim.uri_to_fname(uri)'))
end)
it('local file path without hostname', function()
exec_lua("uri = 'file:/Foo/Bar/Baz.txt'")
- eq('/Foo/Bar/Baz.txt', exec_lua("return vim.uri_to_fname(uri)"))
+ eq('/Foo/Bar/Baz.txt', exec_lua('return vim.uri_to_fname(uri)'))
end)
it('file path including white space', function()
exec_lua("uri = 'file:///Foo%20/Bar/Baz.txt'")
- eq('/Foo /Bar/Baz.txt', exec_lua("return vim.uri_to_fname(uri)"))
+ eq('/Foo /Bar/Baz.txt', exec_lua('return vim.uri_to_fname(uri)'))
end)
it('file path including Unicode characters', function()
@@ -82,6 +88,12 @@ describe('URI methods', function()
eq('/xy/åäö/ɧ/汉语/↥/🤦/🦄/aÌŠ/بÙÙŠÙŽÙ‘.txt', exec_lua(test_case))
end)
+
+ it('file path with uri fragment', function()
+ exec_lua("uri = 'file:///Foo/Bar/Baz.txt#fragment'")
+
+ eq('/Foo/Bar/Baz.txt', exec_lua('return vim.uri_to_fname(uri)'))
+ end)
end)
describe('decode Windows filepath', function()
@@ -133,73 +145,109 @@ describe('URI methods', function()
describe('decode non-file URI', function()
it('uri_to_fname returns non-file URI unchanged', function()
- eq('jdt1.23+x-z://content/%5C/', exec_lua [[
+ eq(
+ 'jdt1.23+x-z://content/%5C/',
+ exec_lua [[
return vim.uri_to_fname('jdt1.23+x-z://content/%5C/')
- ]])
+ ]]
+ )
end)
it('uri_to_fname returns non-file upper-case scheme URI unchanged', function()
- eq('JDT://content/%5C/', exec_lua [[
+ eq(
+ 'JDT://content/%5C/',
+ exec_lua [[
return vim.uri_to_fname('JDT://content/%5C/')
- ]])
+ ]]
+ )
end)
it('uri_to_fname returns non-file scheme URI without authority unchanged', function()
- eq('zipfile:///path/to/archive.zip%3A%3Afilename.txt', exec_lua [[
+ eq(
+ 'zipfile:///path/to/archive.zip%3A%3Afilename.txt',
+ exec_lua [[
return vim.uri_to_fname('zipfile:///path/to/archive.zip%3A%3Afilename.txt')
- ]])
+ ]]
+ )
end)
end)
describe('decode URI without scheme', function()
it('fails because URI must have a scheme', function()
- eq(false, exec_lua [[
+ eq(
+ false,
+ exec_lua [[
return pcall(vim.uri_to_fname, 'not_an_uri.txt')
- ]])
+ ]]
+ )
end)
it('uri_to_fname should not treat comma as a scheme character', function()
- eq(false, exec_lua [[
+ eq(
+ false,
+ exec_lua [[
return pcall(vim.uri_to_fname, 'foo,://bar')
- ]])
+ ]]
+ )
end)
- end)
+ it('uri_to_fname returns non-file schema URI with fragment unchanged', function()
+ eq(
+ 'scheme://path#fragment',
+ exec_lua [[
+ return vim.uri_to_fname('scheme://path#fragment')
+ ]]
+ )
+ end)
+ end)
end)
describe('uri from bufnr', function()
it('Windows paths should not be treated as uris', function()
- skip(not is_os('win'), "Not applicable on non-Windows")
+ skip(not is_os('win'), 'Not applicable on non-Windows')
local file = helpers.tmpname()
write_file(file, 'Test content')
- local test_case = string.format([[
+ local test_case = string.format(
+ [[
local file = '%s'
return vim.uri_from_bufnr(vim.fn.bufadd(file))
- ]], file)
- local expected_uri = 'file:///' .. file:gsub("\\", "/")
- eq(expected_uri, exec_lua(test_case))
- os.remove(file)
+ ]],
+ file
+ )
+ local expected_uri = 'file:///' .. file:gsub('\\', '/')
+ eq(expected_uri, exec_lua(test_case))
+ os.remove(file)
end)
end)
describe('uri to bufnr', function()
it('uri_to_bufnr & uri_from_bufnr returns original uri for non-file uris', function()
- local uri = 'jdt://contents/java.base/java.util/List.class?=sql/%5C/home%5C/user%5C/.jabba%5C/jdk%5C/openjdk%5C@1.14.0%5C/lib%5C/jrt-fs.jar%60java.base=/javadoc_location=/https:%5C/%5C/docs.oracle.com%5C/en%5C/java%5C/javase%5C/14%5C/docs%5C/api%5C/=/%3Cjava.util(List.class'
- local test_case = string.format([[
+ local uri =
+ 'jdt://contents/java.base/java.util/List.class?=sql/%5C/home%5C/user%5C/.jabba%5C/jdk%5C/openjdk%5C@1.14.0%5C/lib%5C/jrt-fs.jar%60java.base=/javadoc_location=/https:%5C/%5C/docs.oracle.com%5C/en%5C/java%5C/javase%5C/14%5C/docs%5C/api%5C/=/%3Cjava.util(List.class'
+ local test_case = string.format(
+ [[
local uri = '%s'
return vim.uri_from_bufnr(vim.uri_to_bufnr(uri))
- ]], uri)
+ ]],
+ uri
+ )
eq(uri, exec_lua(test_case))
end)
- it('uri_to_bufnr & uri_from_bufnr returns original uri for non-file uris without authority', function()
- local uri = 'zipfile:///path/to/archive.zip%3A%3Afilename.txt'
- local test_case = string.format([[
+ it(
+ 'uri_to_bufnr & uri_from_bufnr returns original uri for non-file uris without authority',
+ function()
+ local uri = 'zipfile:///path/to/archive.zip%3A%3Afilename.txt'
+ local test_case = string.format(
+ [[
local uri = '%s'
return vim.uri_from_bufnr(vim.uri_to_bufnr(uri))
- ]], uri)
- eq(uri, exec_lua(test_case))
- end)
+ ]],
+ uri
+ )
+ eq(uri, exec_lua(test_case))
+ end
+ )
end)
end)
diff --git a/test/functional/lua/version_spec.lua b/test/functional/lua/version_spec.lua
index d1c981c388..3bc9e26d41 100644
--- a/test/functional/lua/version_spec.lua
+++ b/test/functional/lua/version_spec.lua
@@ -11,7 +11,6 @@ local function v(ver)
end
describe('version', function()
-
it('package', function()
clear()
eq({ major = 42, minor = 3, patch = 99 }, exec_lua("return vim.version.parse('v42.3.99')"))
@@ -35,7 +34,13 @@ describe('version', function()
['v1.2'] = { major = 1, minor = 2, patch = 0 },
['v1.2.3-prerelease'] = { major = 1, minor = 2, patch = 3, prerelease = 'prerelease' },
['v1.2-prerelease'] = { major = 1, minor = 2, patch = 0, prerelease = 'prerelease' },
- ['v1.2.3-prerelease+build'] = { major = 1, minor = 2, patch = 3, prerelease = 'prerelease', build = 'build' },
+ ['v1.2.3-prerelease+build'] = {
+ major = 1,
+ minor = 2,
+ patch = 3,
+ prerelease = 'prerelease',
+ build = 'build',
+ },
['1.2.3+build'] = { major = 1, minor = 2, patch = 3, build = 'build' },
}
for input, output in pairs(tests) do
@@ -108,86 +113,114 @@ describe('version', function()
describe('cmp()', function()
local testcases = {
- { v1 = 'v0.0.99', v2 = 'v9.0.0', want = -1, },
- { v1 = 'v0.4.0', v2 = 'v0.9.99', want = -1, },
- { v1 = 'v0.2.8', v2 = 'v1.0.9', want = -1, },
- { v1 = 'v0.0.0', v2 = 'v0.0.0', want = 0, },
- { v1 = 'v9.0.0', v2 = 'v0.9.0', want = 1, },
- { v1 = 'v0.9.0', v2 = 'v0.0.0', want = 1, },
- { v1 = 'v0.0.9', v2 = 'v0.0.0', want = 1, },
- { v1 = 'v0.0.9+aaa', v2 = 'v0.0.9+bbb', want = 0, },
+ { v1 = 'v0.0.99', v2 = 'v9.0.0', want = -1 },
+ { v1 = 'v0.4.0', v2 = 'v0.9.99', want = -1 },
+ { v1 = 'v0.2.8', v2 = 'v1.0.9', want = -1 },
+ { v1 = 'v0.0.0', v2 = 'v0.0.0', want = 0 },
+ { v1 = 'v9.0.0', v2 = 'v0.9.0', want = 1 },
+ { v1 = 'v0.9.0', v2 = 'v0.0.0', want = 1 },
+ { v1 = 'v0.0.9', v2 = 'v0.0.0', want = 1 },
+ { v1 = 'v0.0.9+aaa', v2 = 'v0.0.9+bbb', want = 0 },
-- prerelease 💩 https://semver.org/#spec-item-11
- { v1 = 'v1.0.0-alpha', v2 = 'v1.0.0', want = -1, },
- { v1 = '1.0.0', v2 = '1.0.0-alpha', want = 1, },
- { v1 = '1.0.0-2', v2 = '1.0.0-1', want = 1, },
- { v1 = '1.0.0-2', v2 = '1.0.0-9', want = -1, },
- { v1 = '1.0.0-2', v2 = '1.0.0-2.0', want = -1, },
- { v1 = '1.0.0-2.0', v2 = '1.0.0-2', want = 1, },
- { v1 = '1.0.0-2.0', v2 = '1.0.0-2.0', want = 0, },
- { v1 = '1.0.0-alpha', v2 = '1.0.0-alpha', want = 0, },
- { v1 = '1.0.0-alpha', v2 = '1.0.0-beta', want = -1, },
- { v1 = '1.0.0-beta', v2 = '1.0.0-alpha', want = 1, },
- { v1 = '1.0.0-alpha', v2 = '1.0.0-alpha.1', want = -1, },
- { v1 = '1.0.0-alpha.1', v2 = '1.0.0-alpha', want = 1, },
- { v1 = '1.0.0-alpha.beta', v2 = '1.0.0-alpha', want = 1, },
- { v1 = '1.0.0-alpha', v2 = '1.0.0-alpha.beta', want = -1, },
- { v1 = '1.0.0-alpha.beta', v2 = '1.0.0-beta', want = -1, },
- { v1 = '1.0.0-beta.2', v2 = '1.0.0-beta.11', want = -1, },
- { v1 = '1.0.0-beta.20', v2 = '1.0.0-beta.11', want = 1, },
- { v1 = '1.0.0-alpha.20', v2 = '1.0.0-beta.11', want = -1, },
- { v1 = '1.0.0-a.01.x.3', v2 = '1.0.0-a.1.x.003', want = 0, },
- { v1 = 'v0.9.0-dev-92+9', v2 = 'v0.9.0-dev-120+3', want = -1, },
+ { v1 = 'v1.0.0-alpha', v2 = 'v1.0.0', want = -1 },
+ { v1 = '1.0.0', v2 = '1.0.0-alpha', want = 1 },
+ { v1 = '1.0.0-2', v2 = '1.0.0-1', want = 1 },
+ { v1 = '1.0.0-2', v2 = '1.0.0-9', want = -1 },
+ { v1 = '1.0.0-2', v2 = '1.0.0-2.0', want = -1 },
+ { v1 = '1.0.0-2.0', v2 = '1.0.0-2', want = 1 },
+ { v1 = '1.0.0-2.0', v2 = '1.0.0-2.0', want = 0 },
+ { v1 = '1.0.0-alpha', v2 = '1.0.0-alpha', want = 0 },
+ { v1 = '1.0.0-alpha', v2 = '1.0.0-beta', want = -1 },
+ { v1 = '1.0.0-beta', v2 = '1.0.0-alpha', want = 1 },
+ { v1 = '1.0.0-alpha', v2 = '1.0.0-alpha.1', want = -1 },
+ { v1 = '1.0.0-alpha.1', v2 = '1.0.0-alpha', want = 1 },
+ { v1 = '1.0.0-alpha.beta', v2 = '1.0.0-alpha', want = 1 },
+ { v1 = '1.0.0-alpha', v2 = '1.0.0-alpha.beta', want = -1 },
+ { v1 = '1.0.0-alpha.beta', v2 = '1.0.0-beta', want = -1 },
+ { v1 = '1.0.0-beta.2', v2 = '1.0.0-beta.11', want = -1 },
+ { v1 = '1.0.0-beta.20', v2 = '1.0.0-beta.11', want = 1 },
+ { v1 = '1.0.0-alpha.20', v2 = '1.0.0-beta.11', want = -1 },
+ { v1 = '1.0.0-a.01.x.3', v2 = '1.0.0-a.1.x.003', want = 0 },
+ { v1 = 'v0.9.0-dev-92+9', v2 = 'v0.9.0-dev-120+3', want = -1 },
}
for _, tc in ipairs(testcases) do
- local msg = function(s) return ('v1 %s v2'):format(s == 0 and '==' or (s == 1 and '>' or '<')) end
- it(string.format('(v1 = %s, v2 = %s)', tc.v1, tc.v2),
- function()
- local rv = vim.version.cmp(tc.v1, tc.v2, { strict = true })
- ok(tc.want == rv, msg(tc.want), msg(rv))
- end
- )
+ local msg = function(s)
+ return ('v1 %s v2'):format(s == 0 and '==' or (s == 1 and '>' or '<'))
+ end
+ it(string.format('(v1 = %s, v2 = %s)', tc.v1, tc.v2), function()
+ local rv = vim.version.cmp(tc.v1, tc.v2, { strict = true })
+ ok(tc.want == rv, msg(tc.want), msg(rv))
+ end)
end
end)
describe('parse()', function()
describe('strict=true', function()
local testcases = {
- { desc = 'Nvim version', version = 'v0.9.0-dev-1233+g210120dde81e', want = { major = 0, minor = 9, patch = 0, prerelease = 'dev-1233', build = 'g210120dde81e', }, },
- { desc = 'no v', version = '10.20.123', want = { major = 10, minor = 20, patch = 123, prerelease = nil, build = nil, }, },
- { desc = 'with v', version = 'v1.2.3', want = { major = 1, minor = 2, patch = 3 }, },
- { desc = 'prerelease', version = '1.2.3-alpha', want = { major = 1, minor = 2, patch = 3, prerelease = 'alpha' }, },
- { desc = 'prerelease.x', version = '1.2.3-alpha.1', want = { major = 1, minor = 2, patch = 3, prerelease = 'alpha.1' }, },
- { desc = 'build.x', version = '1.2.3+build.15', want = { major = 1, minor = 2, patch = 3, build = 'build.15' }, },
- { desc = 'prerelease and build', version = '1.2.3-rc1+build.15', want = { major = 1, minor = 2, patch = 3, prerelease = 'rc1', build = 'build.15', }, },
+ {
+ desc = 'Nvim version',
+ version = 'v0.9.0-dev-1233+g210120dde81e',
+ want = {
+ major = 0,
+ minor = 9,
+ patch = 0,
+ prerelease = 'dev-1233',
+ build = 'g210120dde81e',
+ },
+ },
+ {
+ desc = 'no v',
+ version = '10.20.123',
+ want = { major = 10, minor = 20, patch = 123, prerelease = nil, build = nil },
+ },
+ {
+ desc = 'with v',
+ version = 'v1.2.3',
+ want = { major = 1, minor = 2, patch = 3 },
+ },
+ {
+ desc = 'prerelease',
+ version = '1.2.3-alpha',
+ want = { major = 1, minor = 2, patch = 3, prerelease = 'alpha' },
+ },
+ {
+ desc = 'prerelease.x',
+ version = '1.2.3-alpha.1',
+ want = { major = 1, minor = 2, patch = 3, prerelease = 'alpha.1' },
+ },
+ {
+ desc = 'build.x',
+ version = '1.2.3+build.15',
+ want = { major = 1, minor = 2, patch = 3, build = 'build.15' },
+ },
+ {
+ desc = 'prerelease and build',
+ version = '1.2.3-rc1+build.15',
+ want = { major = 1, minor = 2, patch = 3, prerelease = 'rc1', build = 'build.15' },
+ },
}
for _, tc in ipairs(testcases) do
- it(
- string.format('%q: version = %q', tc.desc, tc.version),
- function()
- eq(tc.want, vim.version.parse(tc.version))
- end
- )
+ it(string.format('%q: version = %q', tc.desc, tc.version), function()
+ eq(tc.want, vim.version.parse(tc.version))
+ end)
end
end)
describe('strict=false', function()
local testcases = {
- { version = '1.2', want = { major = 1, minor = 2, patch = 0 }, },
- { version = '1', want = { major = 1, minor = 0, patch = 0 }, },
- { version = '1.1-0', want = { major = 1, minor = 1, patch = 0, prerelease = '0' }, },
- { version = '1-1.0', want = { major = 1, minor = 0, patch = 0, prerelease = '1.0' }, },
- { version = 'v1.2.3 ', want = { major = 1, minor = 2, patch = 3 }, },
- { version = ' v1.2.3', want = { major = 1, minor = 2, patch = 3 }, },
- { version = 'tmux 3.2a', want = { major = 3, minor = 2, patch = 0, }, },
+ { version = '1.2', want = { major = 1, minor = 2, patch = 0 } },
+ { version = '1', want = { major = 1, minor = 0, patch = 0 } },
+ { version = '1.1-0', want = { major = 1, minor = 1, patch = 0, prerelease = '0' } },
+ { version = '1-1.0', want = { major = 1, minor = 0, patch = 0, prerelease = '1.0' } },
+ { version = 'v1.2.3 ', want = { major = 1, minor = 2, patch = 3 } },
+ { version = ' v1.2.3', want = { major = 1, minor = 2, patch = 3 } },
+ { version = 'tmux 3.2a', want = { major = 3, minor = 2, patch = 0 } },
}
for _, tc in ipairs(testcases) do
- it(
- string.format('version = %q', tc.version),
- function()
- eq(tc.want, vim.version.parse(tc.version, { strict = false }))
- end
- )
+ it(string.format('version = %q', tc.version), function()
+ eq(tc.want, vim.version.parse(tc.version, { strict = false }))
+ end)
end
end)
@@ -205,8 +238,8 @@ describe('version', function()
{ version = '1.2.3-%?' },
{ version = '1.2.3+%?' },
{ version = '1.2.3+build.0-rc1' },
- { version = '3.2a', },
- { version = 'tmux 3.2a', },
+ { version = '3.2a' },
+ { version = 'tmux 3.2a' },
}
local function quote_empty(s)
@@ -230,8 +263,10 @@ describe('version', function()
}
for _, tc in ipairs(testcases) do
it(string.format('(%s): %s', tc.desc, tostring(tc.version)), function()
- local expected = string.format(type(tc.version) == 'string'
- and 'invalid version: "%s"' or 'invalid version: %s', tostring(tc.version))
+ local expected = string.format(
+ type(tc.version) == 'string' and 'invalid version: "%s"' or 'invalid version: %s',
+ tostring(tc.version)
+ )
matches(expected, pcall_err(vim.version.parse, tc.version, { strict = true }))
end)
end
@@ -253,21 +288,55 @@ describe('version', function()
eq(vim.version.last({ v('2.0.0'), v('1.2.3') }), v('2.0.0'))
end)
+ it('le()', function()
+ eq(true, vim.version.le('1', '1'))
+ eq(true, vim.version.le({ 3, 1, 4 }, '3.1.4'))
+ eq(true, vim.version.le('1', '2'))
+ eq(true, vim.version.le({ 0, 7, 4 }, { 3 }))
+ eq(false, vim.version.le({ 3 }, { 0, 7, 4 }))
+ eq(false, vim.version.le({ major = 3, minor = 3, patch = 0 }, { 3, 2, 0 }))
+ eq(false, vim.version.le('2', '1'))
+ end)
+
it('lt()', function()
+ eq(false, vim.version.lt('1', '1'))
+ eq(false, vim.version.lt({ 3, 1, 4 }, '3.1.4'))
eq(true, vim.version.lt('1', '2'))
- eq(false, vim.version.lt({3}, {0, 7, 4}))
- eq(false, vim.version.lt({major=3, minor=3, patch=0}, {3, 2, 0}))
+ eq(true, vim.version.lt({ 0, 7, 4 }, { 3 }))
+ eq(false, vim.version.lt({ 3 }, { 0, 7, 4 }))
+ eq(false, vim.version.lt({ major = 3, minor = 3, patch = 0 }, { 3, 2, 0 }))
+ eq(false, vim.version.lt('2', '1'))
+ end)
+
+ it('ge()', function()
+ eq(true, vim.version.ge('1', '1'))
+ eq(true, vim.version.ge({ 3, 1, 4 }, '3.1.4'))
+ eq(true, vim.version.ge('2', '1'))
+ eq(true, vim.version.ge({ 3 }, { 0, 7, 4 }))
+ eq(true, vim.version.ge({ major = 3, minor = 3, patch = 0 }, { 3, 2, 0 }))
+ eq(false, vim.version.ge('1', '2'))
+ eq(false, vim.version.ge({ 0, 7, 4 }, { 3 }))
end)
it('gt()', function()
+ eq(false, vim.version.gt('1', '1'))
+ eq(false, vim.version.gt({ 3, 1, 4 }, '3.1.4'))
eq(true, vim.version.gt('2', '1'))
- eq(true, vim.version.gt({3}, {0, 7, 4}))
- eq(true, vim.version.gt({major=3, minor=3, patch=0}, {3, 2, 0}))
+ eq(true, vim.version.gt({ 3 }, { 0, 7, 4 }))
+ eq(true, vim.version.gt({ major = 3, minor = 3, patch = 0 }, { 3, 2, 0 }))
+ eq(false, vim.version.gt('1', '2'))
+ eq(false, vim.version.gt({ 0, 7, 4 }, { 3 }))
end)
it('eq()', function()
eq(true, vim.version.eq('2', '2'))
- eq(true, vim.version.eq({3, 1, 0}, '3.1.0'))
- eq(true, vim.version.eq({major=3, minor=3, patch=0}, {3, 3, 0}))
+ eq(true, vim.version.eq({ 3, 1, 0 }, '3.1.0'))
+ eq(true, vim.version.eq({ major = 3, minor = 3, patch = 0 }, { 3, 3, 0 }))
+ eq(false, vim.version.eq('2', '3'))
+
+ -- semver: v3 == v3.0 == v3.0.0
+ eq(true, vim.version.eq('3', { 3, 0, 0 }))
+ eq(true, vim.version.eq({ 3, 0 }, { 3 }))
+ eq(true, vim.version.eq({ 3, 0, 0 }, { 3 }))
end)
end)
diff --git a/test/functional/lua/vim_spec.lua b/test/functional/lua/vim_spec.lua
index ebe5fc254e..a262d239e8 100644
--- a/test/functional/lua/vim_spec.lua
+++ b/test/functional/lua/vim_spec.lua
@@ -3,22 +3,22 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local nvim_prog = helpers.nvim_prog
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local command = helpers.command
local dedent = helpers.dedent
local insert = helpers.insert
local clear = helpers.clear
local eq = helpers.eq
local ok = helpers.ok
-local pesc = helpers.pesc
+local pesc = vim.pesc
local eval = helpers.eval
local feed = helpers.feed
local pcall_err = helpers.pcall_err
local exec_lua = helpers.exec_lua
local matches = helpers.matches
local exec = helpers.exec
-local NIL = helpers.NIL
+local NIL = vim.NIL
local retry = helpers.retry
local next_msg = helpers.next_msg
local remove_trace = helpers.remove_trace
@@ -39,204 +39,479 @@ describe('lua stdlib', function()
-- Note: Built-in Nvim comparison (on systems lacking `strcasecmp`) works
-- only on ASCII characters.
it('vim.stricmp', function()
- eq(0, funcs.luaeval('vim.stricmp("a", "A")'))
- eq(0, funcs.luaeval('vim.stricmp("A", "a")'))
- eq(0, funcs.luaeval('vim.stricmp("a", "a")'))
- eq(0, funcs.luaeval('vim.stricmp("A", "A")'))
-
- eq(0, funcs.luaeval('vim.stricmp("", "")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0", "\\0")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0\\0", "\\0\\0")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0", "\\0\\0\\0")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0A", "\\0\\0\\0a")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0A")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0a")'))
-
- eq(0, funcs.luaeval('vim.stricmp("a\\0", "A\\0")'))
- eq(0, funcs.luaeval('vim.stricmp("A\\0", "a\\0")'))
- eq(0, funcs.luaeval('vim.stricmp("a\\0", "a\\0")'))
- eq(0, funcs.luaeval('vim.stricmp("A\\0", "A\\0")'))
-
- eq(0, funcs.luaeval('vim.stricmp("\\0a", "\\0A")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0A", "\\0a")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0a", "\\0a")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0A", "\\0A")'))
-
- eq(0, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0A\\0")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0a\\0")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0a\\0")'))
- eq(0, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0A\\0")'))
-
- eq(-1, funcs.luaeval('vim.stricmp("a", "B")'))
- eq(-1, funcs.luaeval('vim.stricmp("A", "b")'))
- eq(-1, funcs.luaeval('vim.stricmp("a", "b")'))
- eq(-1, funcs.luaeval('vim.stricmp("A", "B")'))
-
- eq(-1, funcs.luaeval('vim.stricmp("", "\\0")'))
- eq(-1, funcs.luaeval('vim.stricmp("\\0", "\\0\\0")'))
- eq(-1, funcs.luaeval('vim.stricmp("\\0\\0", "\\0\\0\\0")'))
- eq(-1, funcs.luaeval('vim.stricmp("\\0\\0\\0A", "\\0\\0\\0b")'))
- eq(-1, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0B")'))
- eq(-1, funcs.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0b")'))
-
- eq(-1, funcs.luaeval('vim.stricmp("a\\0", "B\\0")'))
- eq(-1, funcs.luaeval('vim.stricmp("A\\0", "b\\0")'))
- eq(-1, funcs.luaeval('vim.stricmp("a\\0", "b\\0")'))
- eq(-1, funcs.luaeval('vim.stricmp("A\\0", "B\\0")'))
-
- eq(-1, funcs.luaeval('vim.stricmp("\\0a", "\\0B")'))
- eq(-1, funcs.luaeval('vim.stricmp("\\0A", "\\0b")'))
- eq(-1, funcs.luaeval('vim.stricmp("\\0a", "\\0b")'))
- eq(-1, funcs.luaeval('vim.stricmp("\\0A", "\\0B")'))
-
- eq(-1, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0B\\0")'))
- eq(-1, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0b\\0")'))
- eq(-1, funcs.luaeval('vim.stricmp("\\0a\\0", "\\0b\\0")'))
- eq(-1, funcs.luaeval('vim.stricmp("\\0A\\0", "\\0B\\0")'))
-
- eq(1, funcs.luaeval('vim.stricmp("c", "B")'))
- eq(1, funcs.luaeval('vim.stricmp("C", "b")'))
- eq(1, funcs.luaeval('vim.stricmp("c", "b")'))
- eq(1, funcs.luaeval('vim.stricmp("C", "B")'))
-
- eq(1, funcs.luaeval('vim.stricmp("\\0", "")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0\\0", "\\0")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0", "\\0\\0")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0\\0", "\\0\\0\\0")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0C", "\\0\\0\\0b")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0c", "\\0\\0\\0B")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0\\0\\0c", "\\0\\0\\0b")'))
-
- eq(1, funcs.luaeval('vim.stricmp("c\\0", "B\\0")'))
- eq(1, funcs.luaeval('vim.stricmp("C\\0", "b\\0")'))
- eq(1, funcs.luaeval('vim.stricmp("c\\0", "b\\0")'))
- eq(1, funcs.luaeval('vim.stricmp("C\\0", "B\\0")'))
-
- eq(1, funcs.luaeval('vim.stricmp("c\\0", "B")'))
- eq(1, funcs.luaeval('vim.stricmp("C\\0", "b")'))
- eq(1, funcs.luaeval('vim.stricmp("c\\0", "b")'))
- eq(1, funcs.luaeval('vim.stricmp("C\\0", "B")'))
-
- eq(1, funcs.luaeval('vim.stricmp("\\0c", "\\0B")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0C", "\\0b")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0c", "\\0b")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0C", "\\0B")'))
-
- eq(1, funcs.luaeval('vim.stricmp("\\0c\\0", "\\0B\\0")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0b\\0")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0c\\0", "\\0b\\0")'))
- eq(1, funcs.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")'))
- end)
-
- it('vim.deprecate', function()
- -- vim.deprecate(name, alternative, version, plugin, backtrace)
- eq(dedent[[
- foo.bar() is deprecated, use zub.wooo{ok=yay} instead. :help deprecated
- This feature will be removed in Nvim version 2.17]],
- exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '2.17'))
- -- Same message, skipped.
- eq(vim.NIL,
- exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '2.17'))
- -- When `plugin` is specified, don't show ":help deprecated". #22235
- eq(dedent[[
- foo.bar() is deprecated, use zub.wooo{ok=yay} instead.
- This feature will be removed in my-plugin.nvim version 0.3.0]],
- exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.3.0', 'my-plugin.nvim', false))
+ eq(0, fn.luaeval('vim.stricmp("a", "A")'))
+ eq(0, fn.luaeval('vim.stricmp("A", "a")'))
+ eq(0, fn.luaeval('vim.stricmp("a", "a")'))
+ eq(0, fn.luaeval('vim.stricmp("A", "A")'))
+
+ eq(0, fn.luaeval('vim.stricmp("", "")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0", "\\0")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0\\0", "\\0\\0")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0\\0\\0", "\\0\\0\\0")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0\\0\\0A", "\\0\\0\\0a")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0A")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0a")'))
+
+ eq(0, fn.luaeval('vim.stricmp("a\\0", "A\\0")'))
+ eq(0, fn.luaeval('vim.stricmp("A\\0", "a\\0")'))
+ eq(0, fn.luaeval('vim.stricmp("a\\0", "a\\0")'))
+ eq(0, fn.luaeval('vim.stricmp("A\\0", "A\\0")'))
+
+ eq(0, fn.luaeval('vim.stricmp("\\0a", "\\0A")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0A", "\\0a")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0a", "\\0a")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0A", "\\0A")'))
+
+ eq(0, fn.luaeval('vim.stricmp("\\0a\\0", "\\0A\\0")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0A\\0", "\\0a\\0")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0a\\0", "\\0a\\0")'))
+ eq(0, fn.luaeval('vim.stricmp("\\0A\\0", "\\0A\\0")'))
+
+ eq(-1, fn.luaeval('vim.stricmp("a", "B")'))
+ eq(-1, fn.luaeval('vim.stricmp("A", "b")'))
+ eq(-1, fn.luaeval('vim.stricmp("a", "b")'))
+ eq(-1, fn.luaeval('vim.stricmp("A", "B")'))
+
+ eq(-1, fn.luaeval('vim.stricmp("", "\\0")'))
+ eq(-1, fn.luaeval('vim.stricmp("\\0", "\\0\\0")'))
+ eq(-1, fn.luaeval('vim.stricmp("\\0\\0", "\\0\\0\\0")'))
+ eq(-1, fn.luaeval('vim.stricmp("\\0\\0\\0A", "\\0\\0\\0b")'))
+ eq(-1, fn.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0B")'))
+ eq(-1, fn.luaeval('vim.stricmp("\\0\\0\\0a", "\\0\\0\\0b")'))
+
+ eq(-1, fn.luaeval('vim.stricmp("a\\0", "B\\0")'))
+ eq(-1, fn.luaeval('vim.stricmp("A\\0", "b\\0")'))
+ eq(-1, fn.luaeval('vim.stricmp("a\\0", "b\\0")'))
+ eq(-1, fn.luaeval('vim.stricmp("A\\0", "B\\0")'))
+
+ eq(-1, fn.luaeval('vim.stricmp("\\0a", "\\0B")'))
+ eq(-1, fn.luaeval('vim.stricmp("\\0A", "\\0b")'))
+ eq(-1, fn.luaeval('vim.stricmp("\\0a", "\\0b")'))
+ eq(-1, fn.luaeval('vim.stricmp("\\0A", "\\0B")'))
+
+ eq(-1, fn.luaeval('vim.stricmp("\\0a\\0", "\\0B\\0")'))
+ eq(-1, fn.luaeval('vim.stricmp("\\0A\\0", "\\0b\\0")'))
+ eq(-1, fn.luaeval('vim.stricmp("\\0a\\0", "\\0b\\0")'))
+ eq(-1, fn.luaeval('vim.stricmp("\\0A\\0", "\\0B\\0")'))
+
+ eq(1, fn.luaeval('vim.stricmp("c", "B")'))
+ eq(1, fn.luaeval('vim.stricmp("C", "b")'))
+ eq(1, fn.luaeval('vim.stricmp("c", "b")'))
+ eq(1, fn.luaeval('vim.stricmp("C", "B")'))
+
+ eq(1, fn.luaeval('vim.stricmp("\\0", "")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0\\0", "\\0")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0\\0\\0", "\\0\\0")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0\\0\\0\\0", "\\0\\0\\0")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0\\0\\0C", "\\0\\0\\0b")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0\\0\\0c", "\\0\\0\\0B")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0\\0\\0c", "\\0\\0\\0b")'))
+
+ eq(1, fn.luaeval('vim.stricmp("c\\0", "B\\0")'))
+ eq(1, fn.luaeval('vim.stricmp("C\\0", "b\\0")'))
+ eq(1, fn.luaeval('vim.stricmp("c\\0", "b\\0")'))
+ eq(1, fn.luaeval('vim.stricmp("C\\0", "B\\0")'))
+
+ eq(1, fn.luaeval('vim.stricmp("c\\0", "B")'))
+ eq(1, fn.luaeval('vim.stricmp("C\\0", "b")'))
+ eq(1, fn.luaeval('vim.stricmp("c\\0", "b")'))
+ eq(1, fn.luaeval('vim.stricmp("C\\0", "B")'))
+
+ eq(1, fn.luaeval('vim.stricmp("\\0c", "\\0B")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0C", "\\0b")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0c", "\\0b")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0C", "\\0B")'))
+
+ eq(1, fn.luaeval('vim.stricmp("\\0c\\0", "\\0B\\0")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0C\\0", "\\0b\\0")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0c\\0", "\\0b\\0")'))
+ eq(1, fn.luaeval('vim.stricmp("\\0C\\0", "\\0B\\0")'))
end)
- it('vim.startswith', function()
- eq(true, funcs.luaeval('vim.startswith("123", "1")'))
- eq(true, funcs.luaeval('vim.startswith("123", "")'))
- eq(true, funcs.luaeval('vim.startswith("123", "123")'))
- eq(true, funcs.luaeval('vim.startswith("", "")'))
+ local function test_vim_deprecate(current_version)
+ -- vim.deprecate(name, alternative, version, plugin, backtrace)
+ -- See MAINTAIN.md for the soft/hard deprecation policy
- eq(false, funcs.luaeval('vim.startswith("123", " ")'))
- eq(false, funcs.luaeval('vim.startswith("123", "2")'))
- eq(false, funcs.luaeval('vim.startswith("123", "1234")'))
+ describe(('vim.deprecate [current_version = %s]'):format(current_version), function()
+ before_each(function()
+ -- mock vim.version() behavior, should be pinned for consistent testing
+ exec_lua(
+ [[
+ local current_version_mock = vim.version.parse(...)
+ getmetatable(vim.version).__call = function()
+ return current_version_mock
+ end
+ ]],
+ current_version
+ )
+ end)
- matches("prefix: expected string, got nil",
- pcall_err(exec_lua, 'return vim.startswith("123", nil)'))
- matches("s: expected string, got nil",
- pcall_err(exec_lua, 'return vim.startswith(nil, "123")'))
- end)
+ it('when plugin = nil', function()
+ eq(
+ dedent [[
+ foo.bar() is deprecated, use zub.wooo{ok=yay} instead. :help deprecated
+ This feature will be removed in Nvim version 0.10]],
+ exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.10')
+ )
+ -- Same message, skipped.
+ eq(vim.NIL, exec_lua('return vim.deprecate(...)', 'foo.bar()', 'zub.wooo{ok=yay}', '0.10'))
+
+ -- Don't show error if not hard-deprecated (only soft-deprecated)
+ eq(
+ vim.NIL,
+ exec_lua('return vim.deprecate(...)', 'foo.baz()', 'foo.better_baz()', '0.12.0')
+ )
+
+ -- Show error if hard-deprecated
+ eq(
+ dedent [[
+ foo.hard_dep() is deprecated, use vim.new_api() instead. :help deprecated
+ This feature will be removed in Nvim version 0.11]],
+ exec_lua('return vim.deprecate(...)', 'foo.hard_dep()', 'vim.new_api()', '0.11')
+ )
+
+ -- To be deleted in the next major version (1.0)
+ eq(
+ dedent [[
+ foo.baz() is deprecated. :help deprecated
+ This feature will be removed in Nvim version 1.0]],
+ exec_lua [[ return vim.deprecate('foo.baz()', nil, '1.0') ]]
+ )
+ end)
- it('vim.endswith', function()
- eq(true, funcs.luaeval('vim.endswith("123", "3")'))
- eq(true, funcs.luaeval('vim.endswith("123", "")'))
- eq(true, funcs.luaeval('vim.endswith("123", "123")'))
- eq(true, funcs.luaeval('vim.endswith("", "")'))
+ it('when plugin is specified', function()
+ -- When `plugin` is specified, don't show ":help deprecated". #22235
+ eq(
+ dedent [[
+ foo.bar() is deprecated, use zub.wooo{ok=yay} instead.
+ This feature will be removed in my-plugin.nvim version 0.3.0]],
+ exec_lua(
+ 'return vim.deprecate(...)',
+ 'foo.bar()',
+ 'zub.wooo{ok=yay}',
+ '0.3.0',
+ 'my-plugin.nvim',
+ false
+ )
+ )
+
+ -- plugins: no soft deprecation period
+ eq(
+ dedent [[
+ foo.bar() is deprecated, use zub.wooo{ok=yay} instead.
+ This feature will be removed in my-plugin.nvim version 0.11.0]],
+ exec_lua(
+ 'return vim.deprecate(...)',
+ 'foo.bar()',
+ 'zub.wooo{ok=yay}',
+ '0.11.0',
+ 'my-plugin.nvim',
+ false
+ )
+ )
+ end)
+ end)
+ end
- eq(false, funcs.luaeval('vim.endswith("123", " ")'))
- eq(false, funcs.luaeval('vim.endswith("123", "2")'))
- eq(false, funcs.luaeval('vim.endswith("123", "1234")'))
+ test_vim_deprecate('0.10')
+ test_vim_deprecate('0.10-dev+g0000000')
- matches("suffix: expected string, got nil",
- pcall_err(exec_lua, 'return vim.endswith("123", nil)'))
- matches("s: expected string, got nil",
- pcall_err(exec_lua, 'return vim.endswith(nil, "123")'))
+ it('vim.startswith', function()
+ eq(true, fn.luaeval('vim.startswith("123", "1")'))
+ eq(true, fn.luaeval('vim.startswith("123", "")'))
+ eq(true, fn.luaeval('vim.startswith("123", "123")'))
+ eq(true, fn.luaeval('vim.startswith("", "")'))
+
+ eq(false, fn.luaeval('vim.startswith("123", " ")'))
+ eq(false, fn.luaeval('vim.startswith("123", "2")'))
+ eq(false, fn.luaeval('vim.startswith("123", "1234")'))
+
+ matches(
+ 'prefix: expected string, got nil',
+ pcall_err(exec_lua, 'return vim.startswith("123", nil)')
+ )
+ matches('s: expected string, got nil', pcall_err(exec_lua, 'return vim.startswith(nil, "123")'))
+ end)
+
+ it('vim.endswith', function()
+ eq(true, fn.luaeval('vim.endswith("123", "3")'))
+ eq(true, fn.luaeval('vim.endswith("123", "")'))
+ eq(true, fn.luaeval('vim.endswith("123", "123")'))
+ eq(true, fn.luaeval('vim.endswith("", "")'))
+
+ eq(false, fn.luaeval('vim.endswith("123", " ")'))
+ eq(false, fn.luaeval('vim.endswith("123", "2")'))
+ eq(false, fn.luaeval('vim.endswith("123", "1234")'))
+
+ matches(
+ 'suffix: expected string, got nil',
+ pcall_err(exec_lua, 'return vim.endswith("123", nil)')
+ )
+ matches('s: expected string, got nil', pcall_err(exec_lua, 'return vim.endswith(nil, "123")'))
end)
- it("vim.str_utfindex/str_byteindex", function()
+ it('vim.str_utfindex/str_byteindex', function()
exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 aÌŠ بÙÙŠÙŽÙ‘\000ÑŠ"]])
- local indices32 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,29,33,34,35,37,38,40,42,44,46,48,49,51}
- local indices16 = {[0]=0,1,2,3,5,7,9,10,12,13,16,19,20,23,24,28,28,29,33,33,34,35,37,38,40,42,44,46,48,49,51}
- for i,k in pairs(indices32) do
- eq(k, exec_lua("return vim.str_byteindex(_G.test_text, ...)", i), i)
+ local indices32 = {
+ [0] = 0,
+ 1,
+ 2,
+ 3,
+ 5,
+ 7,
+ 9,
+ 10,
+ 12,
+ 13,
+ 16,
+ 19,
+ 20,
+ 23,
+ 24,
+ 28,
+ 29,
+ 33,
+ 34,
+ 35,
+ 37,
+ 38,
+ 40,
+ 42,
+ 44,
+ 46,
+ 48,
+ 49,
+ 51,
+ }
+ local indices16 = {
+ [0] = 0,
+ 1,
+ 2,
+ 3,
+ 5,
+ 7,
+ 9,
+ 10,
+ 12,
+ 13,
+ 16,
+ 19,
+ 20,
+ 23,
+ 24,
+ 28,
+ 28,
+ 29,
+ 33,
+ 33,
+ 34,
+ 35,
+ 37,
+ 38,
+ 40,
+ 42,
+ 44,
+ 46,
+ 48,
+ 49,
+ 51,
+ }
+ for i, k in pairs(indices32) do
+ eq(k, exec_lua('return vim.str_byteindex(_G.test_text, ...)', i), i)
end
- for i,k in pairs(indices16) do
- eq(k, exec_lua("return vim.str_byteindex(_G.test_text, ..., true)", i), i)
+ for i, k in pairs(indices16) do
+ eq(k, exec_lua('return vim.str_byteindex(_G.test_text, ..., true)', i), i)
end
- eq("index out of range", pcall_err(exec_lua, "return vim.str_byteindex(_G.test_text, ...)", #indices32 + 1))
- eq("index out of range", pcall_err(exec_lua, "return vim.str_byteindex(_G.test_text, ..., true)", #indices16 + 1))
+ eq(
+ 'index out of range',
+ pcall_err(exec_lua, 'return vim.str_byteindex(_G.test_text, ...)', #indices32 + 1)
+ )
+ eq(
+ 'index out of range',
+ pcall_err(exec_lua, 'return vim.str_byteindex(_G.test_text, ..., true)', #indices16 + 1)
+ )
local i32, i16 = 0, 0
local len = 51
- for k = 0,len do
+ for k = 0, len do
if indices32[i32] < k then
i32 = i32 + 1
end
if indices16[i16] < k then
i16 = i16 + 1
- if indices16[i16+1] == indices16[i16] then
+ if indices16[i16 + 1] == indices16[i16] then
i16 = i16 + 1
end
end
- eq({i32, i16}, exec_lua("return {vim.str_utfindex(_G.test_text, ...)}", k), k)
+ eq({ i32, i16 }, exec_lua('return {vim.str_utfindex(_G.test_text, ...)}', k), k)
end
- eq("index out of range", pcall_err(exec_lua, "return vim.str_utfindex(_G.test_text, ...)", len + 1))
+ eq(
+ 'index out of range',
+ pcall_err(exec_lua, 'return vim.str_utfindex(_G.test_text, ...)', len + 1)
+ )
end)
- it("vim.str_utf_start", function()
+ it('vim.str_utf_start', function()
exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 aÌŠ بÙÙŠÙŽÙ‘"]])
- local expected_positions = {0,0,0,0,-1,0,-1,0,-1,0,0,-1,0,0,-1,-2,0,-1,-2,0,0,-1,-2,0,0,-1,-2,-3,0,0,-1,-2,-3,0,0,0,-1,0,0,-1,0,-1,0,-1,0,-1,0,-1}
- eq(expected_positions, exec_lua([[
+ local expected_positions = {
+ 0,
+ 0,
+ 0,
+ 0,
+ -1,
+ 0,
+ -1,
+ 0,
+ -1,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ -1,
+ -2,
+ 0,
+ -1,
+ -2,
+ 0,
+ 0,
+ -1,
+ -2,
+ 0,
+ 0,
+ -1,
+ -2,
+ -3,
+ 0,
+ 0,
+ -1,
+ -2,
+ -3,
+ 0,
+ 0,
+ 0,
+ -1,
+ 0,
+ 0,
+ -1,
+ 0,
+ -1,
+ 0,
+ -1,
+ 0,
+ -1,
+ 0,
+ -1,
+ }
+ eq(
+ expected_positions,
+ exec_lua([[
local start_codepoint_positions = {}
for idx = 1, #_G.test_text do
table.insert(start_codepoint_positions, vim.str_utf_start(_G.test_text, idx))
end
return start_codepoint_positions
- ]]))
+ ]])
+ )
end)
- it("vim.str_utf_end", function()
+ it('vim.str_utf_end', function()
exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 aÌŠ بÙÙŠÙŽÙ‘"]])
- local expected_positions = {0,0,0,1,0,1,0,1,0,0,1,0,0,2,1,0,2,1,0,0,2,1,0,0,3,2,1,0,0,3,2,1,0,0,0,1,0,0,1,0,1,0,1,0,1,0,1,0 }
- eq(expected_positions, exec_lua([[
+ local expected_positions = {
+ 0,
+ 0,
+ 0,
+ 1,
+ 0,
+ 1,
+ 0,
+ 1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ 2,
+ 1,
+ 0,
+ 2,
+ 1,
+ 0,
+ 0,
+ 2,
+ 1,
+ 0,
+ 0,
+ 3,
+ 2,
+ 1,
+ 0,
+ 0,
+ 3,
+ 2,
+ 1,
+ 0,
+ 0,
+ 0,
+ 1,
+ 0,
+ 0,
+ 1,
+ 0,
+ 1,
+ 0,
+ 1,
+ 0,
+ 1,
+ 0,
+ 1,
+ 0,
+ }
+ eq(
+ expected_positions,
+ exec_lua([[
local end_codepoint_positions = {}
for idx = 1, #_G.test_text do
table.insert(end_codepoint_positions, vim.str_utf_end(_G.test_text, idx))
end
return end_codepoint_positions
- ]]))
+ ]])
+ )
end)
-
- it("vim.str_utf_pos", function()
+ it('vim.str_utf_pos', function()
exec_lua([[_G.test_text = "xy åäö ɧ 汉语 ↥ 🤦x🦄 aÌŠ بÙÙŠÙŽÙ‘"]])
- local expected_positions = { 1,2,3,4,6,8,10,11,13,14,17,20,21,24,25,29,30,34,35,36,38,39,41,43,45,47 }
- eq(expected_positions, exec_lua("return vim.str_utf_pos(_G.test_text)"))
+ local expected_positions = {
+ 1,
+ 2,
+ 3,
+ 4,
+ 6,
+ 8,
+ 10,
+ 11,
+ 13,
+ 14,
+ 17,
+ 20,
+ 21,
+ 24,
+ 25,
+ 29,
+ 30,
+ 34,
+ 35,
+ 36,
+ 38,
+ 39,
+ 41,
+ 43,
+ 45,
+ 47,
+ }
+ eq(expected_positions, exec_lua('return vim.str_utf_pos(_G.test_text)'))
end)
- it("vim.schedule", function()
+ it('vim.schedule', function()
exec_lua([[
test_table = {}
vim.schedule(function()
@@ -244,13 +519,11 @@ describe('lua stdlib', function()
end)
table.insert(test_table, "yy")
]])
- eq({"yy","xx"}, exec_lua("return test_table"))
+ eq({ 'yy', 'xx' }, exec_lua('return test_table'))
-- Validates args.
- matches('vim.schedule: expected function',
- pcall_err(exec_lua, "vim.schedule('stringly')"))
- matches('vim.schedule: expected function',
- pcall_err(exec_lua, "vim.schedule()"))
+ matches('vim.schedule: expected function', pcall_err(exec_lua, "vim.schedule('stringly')"))
+ matches('vim.schedule: expected function', pcall_err(exec_lua, 'vim.schedule()'))
exec_lua([[
vim.schedule(function()
@@ -258,24 +531,24 @@ describe('lua stdlib', function()
end)
]])
- feed("<cr>")
- matches('big failure\nvery async', remove_trace(eval("v:errmsg")))
+ feed('<cr>')
+ matches('big failure\nvery async', remove_trace(eval('v:errmsg')))
- local screen = Screen.new(60,5)
+ local screen = Screen.new(60, 5)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {bold = true, reverse = true},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, reverse = true },
+ [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
})
screen:attach()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
-- nvim_command causes a Vimscript exception, check that it is properly caught
-- and propagated as an error message in async contexts.. #10809
@@ -284,62 +557,61 @@ describe('lua stdlib', function()
vim.api.nvim_command(":echo 'err")
end)
]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:stack traceback:} |
{3: [C]: in function 'nvim_command'} |
{3: [string "<nvim>"]:2: in function <[string "<nvim>"]:}|
{3:1>} |
{4:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
it('vim.gsplit, vim.split', function()
local tests = {
-- plain trimempty
- { 'a,b', ',', false, false, { 'a', 'b' } },
- { ':aa::::bb:', ':', false, false, { '', 'aa', '', '', '', 'bb', '' } },
- { ':aa::::bb:', ':', false, true, { 'aa', '', '', '', 'bb' } },
- { 'aa::::bb:', ':', false, true, { 'aa', '', '', '', 'bb' } },
- { ':aa::bb:', ':', false, true, { 'aa', '', 'bb' } },
- { '/a/b:/b/\n', '[:\n]', false, true, { '/a/b', '/b/' } },
- { '::ee::ff:', ':', false, false, { '', '', 'ee', '', 'ff', '' } },
- { '::ee::ff::', ':', false, true, { 'ee', '', 'ff' } },
- { 'ab', '.', false, false, { '', '', '' } },
- { 'a1b2c', '[0-9]', false, false, { 'a', 'b', 'c' } },
- { 'xy', '', false, false, { 'x', 'y' } },
- { 'here be dragons', ' ', false, false, { 'here', 'be', 'dragons'} },
- { 'axaby', 'ab?', false, false, { '', 'x', 'y' } },
- { 'f v2v v3v w2w ', '([vw])2%1', false, false, { 'f ', ' v3v ', ' ' } },
- { '', '', false, false, {} },
- { '', '', false, true, {} },
- { '\n', '[:\n]', false, true, {} },
- { '', 'a', false, false, { '' } },
- { 'x*yz*oo*l', '*', true, false, { 'x', 'yz', 'oo', 'l' } },
+ { 'a,b', ',', false, false, { 'a', 'b' } },
+ { ':aa::::bb:', ':', false, false, { '', 'aa', '', '', '', 'bb', '' } },
+ { ':aa::::bb:', ':', false, true, { 'aa', '', '', '', 'bb' } },
+ { 'aa::::bb:', ':', false, true, { 'aa', '', '', '', 'bb' } },
+ { ':aa::bb:', ':', false, true, { 'aa', '', 'bb' } },
+ { '/a/b:/b/\n', '[:\n]', false, true, { '/a/b', '/b/' } },
+ { '::ee::ff:', ':', false, false, { '', '', 'ee', '', 'ff', '' } },
+ { '::ee::ff::', ':', false, true, { 'ee', '', 'ff' } },
+ { 'ab', '.', false, false, { '', '', '' } },
+ { 'a1b2c', '[0-9]', false, false, { 'a', 'b', 'c' } },
+ { 'xy', '', false, false, { 'x', 'y' } },
+ { 'here be dragons', ' ', false, false, { 'here', 'be', 'dragons' } },
+ { 'axaby', 'ab?', false, false, { '', 'x', 'y' } },
+ { 'f v2v v3v w2w ', '([vw])2%1', false, false, { 'f ', ' v3v ', ' ' } },
+ { '', '', false, false, {} },
+ { '', '', false, true, {} },
+ { '\n', '[:\n]', false, true, {} },
+ { '', 'a', false, false, { '' } },
+ { 'x*yz*oo*l', '*', true, false, { 'x', 'yz', 'oo', 'l' } },
}
for _, t in ipairs(tests) do
- eq(t[5], vim.split(t[1], t[2], {plain=t[3], trimempty=t[4]}), t[1])
+ eq(t[5], vim.split(t[1], t[2], { plain = t[3], trimempty = t[4] }), t[1])
end
-- Test old signature
- eq({'x', 'yz', 'oo', 'l'}, vim.split("x*yz*oo*l", "*", true))
+ eq({ 'x', 'yz', 'oo', 'l' }, vim.split('x*yz*oo*l', '*', true))
local loops = {
- { "abc", ".-" },
+ { 'abc', '.-' },
}
for _, t in ipairs(loops) do
- matches("Infinite loop detected", pcall_err(vim.split, t[1], t[2]))
+ matches('Infinite loop detected', pcall_err(vim.split, t[1], t[2]))
end
-- Validates args.
eq(true, pcall(vim.split, 'string', 'string'))
- matches('s: expected string, got number',
- pcall_err(vim.split, 1, 'string'))
- matches('sep: expected string, got number',
- pcall_err(vim.split, 'string', 1))
- matches('opts: expected table, got number',
- pcall_err(vim.split, 'string', 'string', 1))
+ matches('s: expected string, got number', pcall_err(vim.split, 1, 'string'))
+ matches('sep: expected string, got number', pcall_err(vim.split, 'string', 1))
+ matches('opts: expected table, got number', pcall_err(vim.split, 'string', 'string', 1))
end)
it('vim.trim', function()
@@ -348,10 +620,10 @@ describe('lua stdlib', function()
end
local trims = {
- { " a", "a" },
- { " b ", "b" },
- { "\tc" , "c" },
- { "r\n", "r" },
+ { ' a', 'a' },
+ { ' b ', 'b' },
+ { '\tc', 'c' },
+ { 'r\n', 'r' },
}
for _, t in ipairs(trims) do
@@ -359,8 +631,7 @@ describe('lua stdlib', function()
end
-- Validates args.
- matches('s: expected string, got number',
- pcall_err(trim, 2))
+ matches('s: expected string, got number', pcall_err(trim, 2))
end)
it('vim.inspect', function()
@@ -370,21 +641,23 @@ describe('lua stdlib', function()
end
eq('2', inspect(2))
- eq('{+a = {+b = 1+}+}',
- inspect({ a = { b = 1 } }, { newline = '+', indent = '' }))
+ eq('{+a = {+b = 1+}+}', inspect({ a = { b = 1 } }, { newline = '+', indent = '' }))
-- special value vim.inspect.KEY works
- eq('{ KEY_a = "x", KEY_b = "y"}', exec_lua([[
+ eq(
+ '{ KEY_a = "x", KEY_b = "y"}',
+ exec_lua([[
return vim.inspect({a="x", b="y"}, {newline = '', process = function(item, path)
if path[#path] == vim.inspect.KEY then
return 'KEY_'..item
end
return item
end})
- ]]))
+ ]])
+ )
end)
- it("vim.deepcopy", function()
+ it('vim.deepcopy', function()
ok(exec_lua([[
local a = { x = { 1, 2 }, y = 5}
local b = vim.deepcopy(a)
@@ -445,23 +718,27 @@ describe('lua stdlib', function()
return t2.a == vim.NIL
]]))
- matches('Cannot deepcopy object of type thread',
- pcall_err(exec_lua, [[
+ matches(
+ 'Cannot deepcopy object of type thread',
+ pcall_err(
+ exec_lua,
+ [[
local thread = coroutine.create(function () return 0 end)
local t = {thr = thread}
vim.deepcopy(t)
- ]]))
+ ]]
+ )
+ )
end)
it('vim.pesc', function()
eq('foo%-bar', exec_lua([[return vim.pesc('foo-bar')]]))
eq('foo%%%-bar', exec_lua([[return vim.pesc(vim.pesc('foo-bar'))]]))
-- pesc() returns one result. #20751
- eq({'x'}, exec_lua([[return {vim.pesc('x')}]]))
+ eq({ 'x' }, exec_lua([[return {vim.pesc('x')}]]))
-- Validates args.
- matches('s: expected string, got number',
- pcall_err(exec_lua, [[return vim.pesc(2)]]))
+ matches('s: expected string, got number', pcall_err(exec_lua, [[return vim.pesc(2)]]))
end)
it('vim.list_contains', function()
@@ -473,97 +750,131 @@ describe('lua stdlib', function()
eq(true, exec_lua("return vim.tbl_contains({'a','b','c'}, 'c')"))
eq(false, exec_lua("return vim.tbl_contains({'a','b','c'}, 'd')"))
eq(true, exec_lua("return vim.tbl_contains({[2]='a',foo='b',[5] = 'c'}, 'c')"))
- eq(true, exec_lua([[
+ eq(
+ true,
+ exec_lua([[
return vim.tbl_contains({ 'a', { 'b', 'c' } }, function(v)
return vim.deep_equal(v, { 'b', 'c' })
end, { predicate = true })
- ]]))
+ ]])
+ )
end)
it('vim.tbl_keys', function()
- eq({}, exec_lua("return vim.tbl_keys({})"))
+ eq({}, exec_lua('return vim.tbl_keys({})'))
for _, v in pairs(exec_lua("return vim.tbl_keys({'a', 'b', 'c'})")) do
- eq(true, exec_lua("return vim.tbl_contains({ 1, 2, 3 }, ...)", v))
+ eq(true, exec_lua('return vim.tbl_contains({ 1, 2, 3 }, ...)', v))
end
- for _, v in pairs(exec_lua("return vim.tbl_keys({a=1, b=2, c=3})")) do
+ for _, v in pairs(exec_lua('return vim.tbl_keys({a=1, b=2, c=3})')) do
eq(true, exec_lua("return vim.tbl_contains({ 'a', 'b', 'c' }, ...)", v))
end
end)
it('vim.tbl_values', function()
- eq({}, exec_lua("return vim.tbl_values({})"))
+ eq({}, exec_lua('return vim.tbl_values({})'))
for _, v in pairs(exec_lua("return vim.tbl_values({'a', 'b', 'c'})")) do
eq(true, exec_lua("return vim.tbl_contains({ 'a', 'b', 'c' }, ...)", v))
end
- for _, v in pairs(exec_lua("return vim.tbl_values({a=1, b=2, c=3})")) do
- eq(true, exec_lua("return vim.tbl_contains({ 1, 2, 3 }, ...)", v))
+ for _, v in pairs(exec_lua('return vim.tbl_values({a=1, b=2, c=3})')) do
+ eq(true, exec_lua('return vim.tbl_contains({ 1, 2, 3 }, ...)', v))
end
end)
it('vim.tbl_map', function()
- eq({}, exec_lua([[
+ eq(
+ {},
+ exec_lua([[
return vim.tbl_map(function(v) return v * 2 end, {})
- ]]))
- eq({2, 4, 6}, exec_lua([[
+ ]])
+ )
+ eq(
+ { 2, 4, 6 },
+ exec_lua([[
return vim.tbl_map(function(v) return v * 2 end, {1, 2, 3})
- ]]))
- eq({{i=2}, {i=4}, {i=6}}, exec_lua([[
+ ]])
+ )
+ eq(
+ { { i = 2 }, { i = 4 }, { i = 6 } },
+ exec_lua([[
return vim.tbl_map(function(v) return { i = v.i * 2 } end, {{i=1}, {i=2}, {i=3}})
- ]]))
+ ]])
+ )
end)
it('vim.tbl_filter', function()
- eq({}, exec_lua([[
+ eq(
+ {},
+ exec_lua([[
return vim.tbl_filter(function(v) return (v % 2) == 0 end, {})
- ]]))
- eq({2}, exec_lua([[
+ ]])
+ )
+ eq(
+ { 2 },
+ exec_lua([[
return vim.tbl_filter(function(v) return (v % 2) == 0 end, {1, 2, 3})
- ]]))
- eq({{i=2}}, exec_lua([[
+ ]])
+ )
+ eq(
+ { { i = 2 } },
+ exec_lua([[
return vim.tbl_filter(function(v) return (v.i % 2) == 0 end, {{i=1}, {i=2}, {i=3}})
- ]]))
+ ]])
+ )
end)
it('vim.tbl_isarray', function()
- eq(true, exec_lua("return vim.tbl_isarray({})"))
- eq(false, exec_lua("return vim.tbl_isarray(vim.empty_dict())"))
+ eq(true, exec_lua('return vim.tbl_isarray({})'))
+ eq(false, exec_lua('return vim.tbl_isarray(vim.empty_dict())'))
eq(true, exec_lua("return vim.tbl_isarray({'a', 'b', 'c'})"))
eq(false, exec_lua("return vim.tbl_isarray({'a', '32', a='hello', b='baz'})"))
eq(false, exec_lua("return vim.tbl_isarray({1, a='hello', b='baz'})"))
eq(false, exec_lua("return vim.tbl_isarray({a='hello', b='baz', 1})"))
eq(false, exec_lua("return vim.tbl_isarray({1, 2, nil, a='hello'})"))
- eq(true, exec_lua("return vim.tbl_isarray({1, 2, nil, 4})"))
- eq(true, exec_lua("return vim.tbl_isarray({nil, 2, 3, 4})"))
- eq(false, exec_lua("return vim.tbl_isarray({1, [1.5]=2, [3]=3})"))
+ eq(true, exec_lua('return vim.tbl_isarray({1, 2, nil, 4})'))
+ eq(true, exec_lua('return vim.tbl_isarray({nil, 2, 3, 4})'))
+ eq(false, exec_lua('return vim.tbl_isarray({1, [1.5]=2, [3]=3})'))
end)
it('vim.tbl_islist', function()
- eq(true, exec_lua("return vim.tbl_islist({})"))
- eq(false, exec_lua("return vim.tbl_islist(vim.empty_dict())"))
+ eq(true, exec_lua('return vim.tbl_islist({})'))
+ eq(false, exec_lua('return vim.tbl_islist(vim.empty_dict())'))
eq(true, exec_lua("return vim.tbl_islist({'a', 'b', 'c'})"))
eq(false, exec_lua("return vim.tbl_islist({'a', '32', a='hello', b='baz'})"))
eq(false, exec_lua("return vim.tbl_islist({1, a='hello', b='baz'})"))
eq(false, exec_lua("return vim.tbl_islist({a='hello', b='baz', 1})"))
eq(false, exec_lua("return vim.tbl_islist({1, 2, nil, a='hello'})"))
- eq(false, exec_lua("return vim.tbl_islist({1, 2, nil, 4})"))
- eq(false, exec_lua("return vim.tbl_islist({nil, 2, 3, 4})"))
- eq(false, exec_lua("return vim.tbl_islist({1, [1.5]=2, [3]=3})"))
+ eq(false, exec_lua('return vim.tbl_islist({1, 2, nil, 4})'))
+ eq(false, exec_lua('return vim.tbl_islist({nil, 2, 3, 4})'))
+ eq(false, exec_lua('return vim.tbl_islist({1, [1.5]=2, [3]=3})'))
end)
it('vim.tbl_isempty', function()
- eq(true, exec_lua("return vim.tbl_isempty({})"))
- eq(false, exec_lua("return vim.tbl_isempty({ 1, 2, 3 })"))
- eq(false, exec_lua("return vim.tbl_isempty({a=1, b=2, c=3})"))
+ eq(true, exec_lua('return vim.tbl_isempty({})'))
+ eq(false, exec_lua('return vim.tbl_isempty({ 1, 2, 3 })'))
+ eq(false, exec_lua('return vim.tbl_isempty({a=1, b=2, c=3})'))
end)
it('vim.tbl_get', function()
- eq(true, exec_lua("return vim.tbl_get({ test = { nested_test = true }}, 'test', 'nested_test')"))
+ eq(
+ true,
+ exec_lua("return vim.tbl_get({ test = { nested_test = true }}, 'test', 'nested_test')")
+ )
eq(NIL, exec_lua("return vim.tbl_get({ unindexable = true }, 'unindexable', 'missing_key')"))
eq(NIL, exec_lua("return vim.tbl_get({ unindexable = 1 }, 'unindexable', 'missing_key')"))
- eq(NIL, exec_lua("return vim.tbl_get({ unindexable = coroutine.create(function () end) }, 'unindexable', 'missing_key')"))
- eq(NIL, exec_lua("return vim.tbl_get({ unindexable = function () end }, 'unindexable', 'missing_key')"))
+ eq(
+ NIL,
+ exec_lua(
+ "return vim.tbl_get({ unindexable = coroutine.create(function () end) }, 'unindexable', 'missing_key')"
+ )
+ )
+ eq(
+ NIL,
+ exec_lua(
+ "return vim.tbl_get({ unindexable = function () end }, 'unindexable', 'missing_key')"
+ )
+ )
eq(NIL, exec_lua("return vim.tbl_get({}, 'missing_key')"))
- eq(NIL, exec_lua("return vim.tbl_get({})"))
+ eq(NIL, exec_lua('return vim.tbl_get({})'))
eq(1, exec_lua("return select('#', vim.tbl_get({}))"))
eq(1, exec_lua("return select('#', vim.tbl_get({ nested = {} }, 'nested', 'missing_key'))"))
end)
@@ -629,22 +940,34 @@ describe('lua stdlib', function()
return c.x.a == 1 and c.x.b == 2 and c.x.c == nil and count == 1
]]))
- matches('invalid "behavior": nil',
- pcall_err(exec_lua, [[
+ matches(
+ 'invalid "behavior": nil',
+ pcall_err(
+ exec_lua,
+ [[
return vim.tbl_extend()
- ]])
+ ]]
+ )
)
- matches('wrong number of arguments %(given 1, expected at least 3%)',
- pcall_err(exec_lua, [[
+ matches(
+ 'wrong number of arguments %(given 1, expected at least 3%)',
+ pcall_err(
+ exec_lua,
+ [[
return vim.tbl_extend("keep")
- ]])
+ ]]
+ )
)
- matches('wrong number of arguments %(given 2, expected at least 3%)',
- pcall_err(exec_lua, [[
+ matches(
+ 'wrong number of arguments %(given 2, expected at least 3%)',
+ pcall_err(
+ exec_lua,
+ [[
return vim.tbl_extend("keep", {})
- ]])
+ ]]
+ )
)
end)
@@ -717,17 +1040,23 @@ describe('lua stdlib', function()
return vim.tbl_islist(c) and count == 0
]]))
- eq({a = {b = 1}}, exec_lua([[
+ eq(
+ { a = { b = 1 } },
+ exec_lua([[
local a = { a = { b = 1 } }
local b = { a = {} }
return vim.tbl_deep_extend("force", a, b)
- ]]))
+ ]])
+ )
- eq({a = {b = 1}}, exec_lua([[
+ eq(
+ { a = { b = 1 } },
+ exec_lua([[
local a = { a = 123 }
local b = { a = { b = 1} }
return vim.tbl_deep_extend("force", a, b)
- ]]))
+ ]])
+ )
ok(exec_lua([[
local a = { a = {[2] = 3} }
@@ -736,28 +1065,43 @@ describe('lua stdlib', function()
return vim.deep_equal(c, {a = {[3] = 3}})
]]))
- eq({a = 123}, exec_lua([[
+ eq(
+ { a = 123 },
+ exec_lua([[
local a = { a = { b = 1} }
local b = { a = 123 }
return vim.tbl_deep_extend("force", a, b)
- ]]))
+ ]])
+ )
- matches('invalid "behavior": nil',
- pcall_err(exec_lua, [[
+ matches(
+ 'invalid "behavior": nil',
+ pcall_err(
+ exec_lua,
+ [[
return vim.tbl_deep_extend()
- ]])
+ ]]
+ )
)
- matches('wrong number of arguments %(given 1, expected at least 3%)',
- pcall_err(exec_lua, [[
+ matches(
+ 'wrong number of arguments %(given 1, expected at least 3%)',
+ pcall_err(
+ exec_lua,
+ [[
return vim.tbl_deep_extend("keep")
- ]])
+ ]]
+ )
)
- matches('wrong number of arguments %(given 2, expected at least 3%)',
- pcall_err(exec_lua, [[
+ matches(
+ 'wrong number of arguments %(given 2, expected at least 3%)',
+ pcall_err(
+ exec_lua,
+ [[
return vim.tbl_deep_extend("keep", {})
- ]])
+ ]]
+ )
)
end)
@@ -786,23 +1130,28 @@ describe('lua stdlib', function()
end)
it('vim.list_extend', function()
- eq({1,2,3}, exec_lua [[ return vim.list_extend({1}, {2,3}) ]])
- matches('src: expected table, got nil',
- pcall_err(exec_lua, [[ return vim.list_extend({1}, nil) ]]))
- eq({1,2}, exec_lua [[ return vim.list_extend({1}, {2;a=1}) ]])
+ eq({ 1, 2, 3 }, exec_lua [[ return vim.list_extend({1}, {2,3}) ]])
+ matches(
+ 'src: expected table, got nil',
+ pcall_err(exec_lua, [[ return vim.list_extend({1}, nil) ]])
+ )
+ eq({ 1, 2 }, exec_lua [[ return vim.list_extend({1}, {2;a=1}) ]])
eq(true, exec_lua [[ local a = {1} return vim.list_extend(a, {2;a=1}) == a ]])
- eq({2}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 1) ]])
+ eq({ 2 }, exec_lua [[ return vim.list_extend({}, {2;a=1}, 1) ]])
eq({}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 2) ]])
eq({}, exec_lua [[ return vim.list_extend({}, {2;a=1}, 1, -1) ]])
- eq({2}, exec_lua [[ return vim.list_extend({}, {2;a=1}, -1, 2) ]])
+ eq({ 2 }, exec_lua [[ return vim.list_extend({}, {2;a=1}, -1, 2) ]])
end)
it('vim.tbl_add_reverse_lookup', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
local a = { A = 1 }
vim.tbl_add_reverse_lookup(a)
return vim.deep_equal(a, { A = 1; [1] = 'A'; })
- ]])
+ ]]
+ )
-- Throw an error for trying to do it twice (run into an existing key)
local code = [[
local res = {}
@@ -811,17 +1160,19 @@ describe('lua stdlib', function()
assert(vim.deep_equal(a, { A = 1; [1] = 'A'; }))
vim.tbl_add_reverse_lookup(a)
]]
- matches('The reverse lookup found an existing value for "[1A]" while processing key "[1A]"$',
- pcall_err(exec_lua, code))
+ matches(
+ 'The reverse lookup found an existing value for "[1A]" while processing key "[1A]"$',
+ pcall_err(exec_lua, code)
+ )
end)
it('vim.spairs', function()
local res = ''
local table = {
- ccc=1,
- bbb=2,
- ddd=3,
- aaa=4
+ ccc = 1,
+ bbb = 2,
+ ddd = 3,
+ aaa = 4,
}
for key, _ in vim.spairs(table) do
res = res .. key
@@ -848,37 +1199,51 @@ describe('lua stdlib', function()
endfunc
]])
eq(true, exec_lua([[return next(vim.fn.FooFunc(3)) == nil ]]))
- eq(3, eval("g:test"))
+ eq(3, eval('g:test'))
-- compat: nvim_call_function uses "special" value for empty dict
eq(true, exec_lua([[return next(vim.api.nvim_call_function("FooFunc", {5})) == true ]]))
- eq(5, eval("g:test"))
+ eq(5, eval('g:test'))
- eq({2, "foo", true}, exec_lua([[return vim.fn.VarArg(2, "foo", true)]]))
+ eq({ 2, 'foo', true }, exec_lua([[return vim.fn.VarArg(2, "foo", true)]]))
- eq(true, exec_lua([[
+ eq(
+ true,
+ exec_lua([[
local x = vim.fn.Nilly()
return #x == 2 and x[1] == vim.NIL and x[2] == vim.NIL
- ]]))
- eq({NIL, NIL}, exec_lua([[return vim.fn.Nilly()]]))
+ ]])
+ )
+ eq({ NIL, NIL }, exec_lua([[return vim.fn.Nilly()]]))
-- error handling
- eq({false, 'Vim:E897: List or Blob required'}, exec_lua([[return {pcall(vim.fn.add, "aa", "bb")}]]))
+ eq(
+ { false, 'Vim:E897: List or Blob required' },
+ exec_lua([[return {pcall(vim.fn.add, "aa", "bb")}]])
+ )
-- conversion between LuaRef and Vim Funcref
- eq(true, exec_lua([[
+ eq(
+ true,
+ exec_lua([[
local x = vim.fn.VarArg(function() return 'foo' end, function() return 'bar' end)
return #x == 2 and x[1]() == 'foo' and x[2]() == 'bar'
- ]]))
+ ]])
+ )
-- Test for #20211
- eq('a (b) c', exec_lua([[
+ eq(
+ 'a (b) c',
+ exec_lua([[
return vim.fn.substitute('a b c', 'b', function(m) return '(' .. m[1] .. ')' end, 'g')
- ]]))
+ ]])
+ )
end)
it('vim.fn should error when calling API function', function()
- matches('Tried to call API function with vim.fn: use vim.api.nvim_get_current_line instead',
- pcall_err(exec_lua, "vim.fn.nvim_get_current_line()"))
+ matches(
+ 'Tried to call API function with vim.fn: use vim.api.nvim_get_current_line instead',
+ pcall_err(exec_lua, 'vim.fn.nvim_get_current_line()')
+ )
end)
it('vim.fn is allowed in "fast" context by some functions #18306', function()
@@ -891,8 +1256,8 @@ describe('lua stdlib', function()
end)
]])
- helpers.poke_eventloop()
- eq('hello', exec_lua[[return vim.g.fnres]])
+ poke_eventloop()
+ eq('hello', exec_lua [[return vim.g.fnres]])
end)
it('vim.rpcrequest and vim.rpcnotify', function()
@@ -900,52 +1265,60 @@ describe('lua stdlib', function()
chan = vim.fn.jobstart({'cat'}, {rpc=true})
vim.rpcrequest(chan, 'nvim_set_current_line', 'meow')
]])
- eq('meow', meths.get_current_line())
+ eq('meow', api.nvim_get_current_line())
command("let x = [3, 'aa', v:true, v:null]")
- eq(true, exec_lua([[
+ eq(
+ true,
+ exec_lua([[
ret = vim.rpcrequest(chan, 'nvim_get_var', 'x')
return #ret == 4 and ret[1] == 3 and ret[2] == 'aa' and ret[3] == true and ret[4] == vim.NIL
- ]]))
- eq({3, 'aa', true, NIL}, exec_lua([[return ret]]))
+ ]])
+ )
+ eq({ 3, 'aa', true, NIL }, exec_lua([[return ret]]))
- eq({{}, {}, false, true}, exec_lua([[
+ eq(
+ { {}, {}, false, true },
+ exec_lua([[
vim.rpcrequest(chan, 'nvim_exec', 'let xx = {}\nlet yy = []', false)
local dict = vim.rpcrequest(chan, 'nvim_eval', 'xx')
local list = vim.rpcrequest(chan, 'nvim_eval', 'yy')
return {dict, list, vim.tbl_islist(dict), vim.tbl_islist(list)}
- ]]))
+ ]])
+ )
- exec_lua([[
+ exec_lua([[
vim.rpcrequest(chan, 'nvim_set_var', 'aa', {})
vim.rpcrequest(chan, 'nvim_set_var', 'bb', vim.empty_dict())
]])
- eq({1, 1}, eval('[type(g:aa) == type([]), type(g:bb) == type({})]'))
+ eq({ 1, 1 }, eval('[type(g:aa) == type([]), type(g:bb) == type({})]'))
-- error handling
- eq({false, 'Invalid channel: 23'},
- exec_lua([[return {pcall(vim.rpcrequest, 23, 'foo')}]]))
- eq({false, 'Invalid channel: 23'},
- exec_lua([[return {pcall(vim.rpcnotify, 23, 'foo')}]]))
-
- eq({false, 'Vim:E121: Undefined variable: foobar'},
- exec_lua([[return {pcall(vim.rpcrequest, chan, 'nvim_eval', "foobar")}]]))
+ eq({ false, 'Invalid channel: 23' }, exec_lua([[return {pcall(vim.rpcrequest, 23, 'foo')}]]))
+ eq({ false, 'Invalid channel: 23' }, exec_lua([[return {pcall(vim.rpcnotify, 23, 'foo')}]]))
+ eq(
+ { false, 'Vim:E121: Undefined variable: foobar' },
+ exec_lua([[return {pcall(vim.rpcrequest, chan, 'nvim_eval', "foobar")}]])
+ )
-- rpcnotify doesn't wait on request
- eq('meow', exec_lua([[
+ eq(
+ 'meow',
+ exec_lua([[
vim.rpcnotify(chan, 'nvim_set_current_line', 'foo')
return vim.api.nvim_get_current_line()
- ]]))
+ ]])
+ )
retry(10, nil, function()
- eq('foo', meths.get_current_line())
+ eq('foo', api.nvim_get_current_line())
end)
- local screen = Screen.new(50,7)
+ local screen = Screen.new(50, 7)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {bold = true, reverse = true},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, reverse = true },
+ [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
})
screen:attach()
exec_lua([[
@@ -957,7 +1330,8 @@ describe('lua stdlib', function()
vim.rpcrequest(chan, 'nvim_set_current_line', 'bork')
end)
]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:[string "<nvim>"]:6: E5560: rpcrequest must not be}|
{3: called in a lua loop callback} |
{3:stack traceback:} |
@@ -965,35 +1339,42 @@ describe('lua stdlib', function()
{3: [string "<nvim>"]:6: in function <[string }|
{3:"<nvim>"]:2>} |
{4:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed('<cr>')
- eq({3, NIL}, meths.get_var('yy'))
+ eq({ 3, NIL }, api.nvim_get_var('yy'))
exec_lua([[timer:close()]])
end)
it('vim.empty_dict()', function()
- eq({true, false, true, true}, exec_lua([[
+ eq(
+ { true, false, true, true },
+ exec_lua([[
vim.api.nvim_set_var('listy', {})
vim.api.nvim_set_var('dicty', vim.empty_dict())
local listy = vim.fn.eval("listy")
local dicty = vim.fn.eval("dicty")
return {vim.tbl_islist(listy), vim.tbl_islist(dicty), next(listy) == nil, next(dicty) == nil}
- ]]))
+ ]])
+ )
-- vim.empty_dict() gives new value each time
-- equality is not overridden (still by ref)
-- non-empty table uses the usual heuristics (ignores the tag)
- eq({false, {"foo"}, {namey="bar"}}, exec_lua([[
+ eq(
+ { false, { 'foo' }, { namey = 'bar' } },
+ exec_lua([[
local aa = vim.empty_dict()
local bb = vim.empty_dict()
local equally = (aa == bb)
aa[1] = "foo"
bb["namey"] = "bar"
return {equally, aa, bb}
- ]]))
+ ]])
+ )
- eq("{ {}, vim.empty_dict() }", exec_lua("return vim.inspect({{}, vim.empty_dict()})"))
+ eq('{ {}, vim.empty_dict() }', exec_lua('return vim.inspect({{}, vim.empty_dict()})'))
eq('{}', exec_lua([[ return vim.fn.json_encode(vim.empty_dict()) ]]))
eq('{"a": {}, "b": []}', exec_lua([[ return vim.fn.json_encode({a=vim.empty_dict(), b={}}) ]]))
end)
@@ -1028,56 +1409,72 @@ describe('lua stdlib', function()
exec_lua("vim.validate{arg1={2, function(a) return (a % 2) == 0 end, 'even number' }}")
exec_lua("vim.validate{arg1={5, {'n', 's'} }, arg2={ 'foo', {'n', 's'} }}")
- matches('expected table, got number',
- pcall_err(exec_lua, "vim.validate{ 1, 'x' }"))
- matches('invalid type name: x',
- pcall_err(exec_lua, "vim.validate{ arg1={ 1, 'x' }}"))
- matches('invalid type name: 1',
- pcall_err(exec_lua, "vim.validate{ arg1={ 1, 1 }}"))
- matches('invalid type name: nil',
- pcall_err(exec_lua, "vim.validate{ arg1={ 1 }}"))
+ matches('expected table, got number', pcall_err(exec_lua, "vim.validate{ 1, 'x' }"))
+ matches('invalid type name: x', pcall_err(exec_lua, "vim.validate{ arg1={ 1, 'x' }}"))
+ matches('invalid type name: 1', pcall_err(exec_lua, 'vim.validate{ arg1={ 1, 1 }}'))
+ matches('invalid type name: nil', pcall_err(exec_lua, 'vim.validate{ arg1={ 1 }}'))
-- Validated parameters are required by default.
- matches('arg1: expected string, got nil',
- pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's' }}"))
+ matches(
+ 'arg1: expected string, got nil',
+ pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's' }}")
+ )
-- Explicitly required.
- matches('arg1: expected string, got nil',
- pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's', false }}"))
-
- matches('arg1: expected table, got number',
- pcall_err(exec_lua, "vim.validate{arg1={1, 't'}}"))
- matches('arg2: expected string, got number',
- pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}"))
- matches('arg2: expected string, got nil',
- pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
- matches('arg2: expected string, got nil',
- pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}"))
- matches('arg1: expected even number, got 3',
- pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}"))
- matches('arg1: expected %?, got 3',
- pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end}}"))
- matches('arg1: expected number|string, got nil',
- pcall_err(exec_lua, "vim.validate{ arg1={ nil, {'n', 's'} }}"))
+ matches(
+ 'arg1: expected string, got nil',
+ pcall_err(exec_lua, "vim.validate{ arg1={ nil, 's', false }}")
+ )
+
+ matches('arg1: expected table, got number', pcall_err(exec_lua, "vim.validate{arg1={1, 't'}}"))
+ matches(
+ 'arg2: expected string, got number',
+ pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={1, 's'}}")
+ )
+ matches(
+ 'arg2: expected string, got nil',
+ pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}")
+ )
+ matches(
+ 'arg2: expected string, got nil',
+ pcall_err(exec_lua, "vim.validate{arg1={{}, 't'}, arg2={nil, 's'}}")
+ )
+ matches(
+ 'arg1: expected even number, got 3',
+ pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1 end, 'even number'}}")
+ )
+ matches(
+ 'arg1: expected %?, got 3',
+ pcall_err(exec_lua, 'vim.validate{arg1={3, function(a) return a == 1 end}}')
+ )
+ matches(
+ 'arg1: expected number|string, got nil',
+ pcall_err(exec_lua, "vim.validate{ arg1={ nil, {'n', 's'} }}")
+ )
-- Pass an additional message back.
- matches('arg1: expected %?, got 3. Info: TEST_MSG',
- pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1, 'TEST_MSG' end}}"))
+ matches(
+ 'arg1: expected %?, got 3. Info: TEST_MSG',
+ pcall_err(exec_lua, "vim.validate{arg1={3, function(a) return a == 1, 'TEST_MSG' end}}")
+ )
end)
it('vim.is_callable', function()
- eq(true, exec_lua("return vim.is_callable(function()end)"))
- eq(true, exec_lua([[
+ eq(true, exec_lua('return vim.is_callable(function()end)'))
+ eq(
+ true,
+ exec_lua([[
local meta = { __call = function()end }
local function new_callable()
return setmetatable({}, meta)
end
local callable = new_callable()
return vim.is_callable(callable)
- ]]))
+ ]])
+ )
- eq(false, exec_lua("return vim.is_callable(1)"))
+ eq(false, exec_lua('return vim.is_callable(1)'))
eq(false, exec_lua("return vim.is_callable('foo')"))
- eq(false, exec_lua("return vim.is_callable({})"))
+ eq(false, exec_lua('return vim.is_callable({})'))
end)
it('vim.g', function()
@@ -1089,24 +1486,26 @@ describe('lua stdlib', function()
vim.api.nvim_set_var("to_delete", {hello="world"})
]]
- eq('hi', funcs.luaeval "vim.g.testing")
- eq(123, funcs.luaeval "vim.g.other")
- eq(5120.1, funcs.luaeval "vim.g.floaty")
- eq(NIL, funcs.luaeval "vim.g.nonexistent")
- eq(NIL, funcs.luaeval "vim.g.nullvar")
+ eq('hi', fn.luaeval 'vim.g.testing')
+ eq(123, fn.luaeval 'vim.g.other')
+ eq(5120.1, fn.luaeval 'vim.g.floaty')
+ eq(NIL, fn.luaeval 'vim.g.nonexistent')
+ eq(NIL, fn.luaeval 'vim.g.nullvar')
-- lost over RPC, so test locally:
- eq({false, true}, exec_lua [[
+ eq(
+ { false, true },
+ exec_lua [[
return {vim.g.nonexistent == vim.NIL, vim.g.nullvar == vim.NIL}
- ]])
+ ]]
+ )
- eq({hello="world"}, funcs.luaeval "vim.g.to_delete")
+ eq({ hello = 'world' }, fn.luaeval 'vim.g.to_delete')
exec_lua [[
vim.g.to_delete = nil
]]
- eq(NIL, funcs.luaeval "vim.g.to_delete")
+ eq(NIL, fn.luaeval 'vim.g.to_delete')
- matches([[attempt to index .* nil value]],
- pcall_err(exec_lua, 'return vim.g[0].testing'))
+ matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.g[0].testing'))
exec_lua [[
local counter = 0
@@ -1114,7 +1513,7 @@ describe('lua stdlib', function()
local function get_counter() return counter end
vim.g.AddCounter = add_counter
vim.g.GetCounter = get_counter
- vim.g.funcs = {add = add_counter, get = get_counter}
+ vim.g.fn = {add = add_counter, get = get_counter}
vim.g.AddParens = function(s) return '(' .. s .. ')' end
]]
@@ -1127,10 +1526,10 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.g.GetCounter()]]))
exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
- exec_lua([[vim.g.funcs.add()]])
- eq(5, exec_lua([[return vim.g.funcs.get()]]))
- exec_lua([[vim.api.nvim_get_var('funcs').add()]])
- eq(6, exec_lua([[return vim.api.nvim_get_var('funcs').get()]]))
+ exec_lua([[vim.g.fn.add()]])
+ eq(5, exec_lua([[return vim.g.fn.get()]]))
+ exec_lua([[vim.api.nvim_get_var('fn').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_get_var('fn').get()]]))
eq('((foo))', eval([['foo'->AddParens()->AddParens()]]))
exec_lua [[
@@ -1139,7 +1538,7 @@ describe('lua stdlib', function()
local function get_counter() return counter end
vim.api.nvim_set_var('AddCounter', add_counter)
vim.api.nvim_set_var('GetCounter', get_counter)
- vim.api.nvim_set_var('funcs', {add = add_counter, get = get_counter})
+ vim.api.nvim_set_var('fn', {add = add_counter, get = get_counter})
vim.api.nvim_set_var('AddParens', function(s) return '(' .. s .. ')' end)
]]
@@ -1152,10 +1551,10 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.g.GetCounter()]]))
exec_lua([[vim.api.nvim_get_var('AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_get_var('GetCounter')()]]))
- exec_lua([[vim.g.funcs.add()]])
- eq(5, exec_lua([[return vim.g.funcs.get()]]))
- exec_lua([[vim.api.nvim_get_var('funcs').add()]])
- eq(6, exec_lua([[return vim.api.nvim_get_var('funcs').get()]]))
+ exec_lua([[vim.g.fn.add()]])
+ eq(5, exec_lua([[return vim.g.fn.get()]]))
+ exec_lua([[vim.api.nvim_get_var('fn').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_get_var('fn').get()]]))
eq('((foo))', eval([['foo'->AddParens()->AddParens()]]))
exec([[
@@ -1173,12 +1572,12 @@ describe('lua stdlib', function()
local pathsep = helpers.get_pathsep()
local xconfig = 'Xhome' .. pathsep .. 'Xconfig'
local xdata = 'Xhome' .. pathsep .. 'Xdata'
- local autoload_folder = table.concat({xconfig, 'nvim', 'autoload'}, pathsep)
- local autoload_file = table.concat({autoload_folder , 'testload.vim'}, pathsep)
+ local autoload_folder = table.concat({ xconfig, 'nvim', 'autoload' }, pathsep)
+ local autoload_file = table.concat({ autoload_folder, 'testload.vim' }, pathsep)
mkdir_p(autoload_folder)
- write_file(autoload_file , [[let testload#value = 2]])
+ write_file(autoload_file, [[let testload#value = 2]])
- clear{ args_rm={'-u'}, env={ XDG_CONFIG_HOME=xconfig, XDG_DATA_HOME=xdata } }
+ clear { args_rm = { '-u' }, env = { XDG_CONFIG_HOME = xconfig, XDG_DATA_HOME = xdata } }
eq(2, exec_lua("return vim.g['testload#value']"))
rmdir('Xhome')
@@ -1195,26 +1594,28 @@ describe('lua stdlib', function()
vim.api.nvim_buf_set_var(BUF, "testing", "bye")
]]
- eq('hi', funcs.luaeval "vim.b.testing")
- eq('bye', funcs.luaeval "vim.b[BUF].testing")
- eq(123, funcs.luaeval "vim.b.other")
- eq(5120.1, funcs.luaeval "vim.b.floaty")
- eq(NIL, funcs.luaeval "vim.b.nonexistent")
- eq(NIL, funcs.luaeval "vim.b[BUF].nonexistent")
- eq(NIL, funcs.luaeval "vim.b.nullvar")
+ eq('hi', fn.luaeval 'vim.b.testing')
+ eq('bye', fn.luaeval 'vim.b[BUF].testing')
+ eq(123, fn.luaeval 'vim.b.other')
+ eq(5120.1, fn.luaeval 'vim.b.floaty')
+ eq(NIL, fn.luaeval 'vim.b.nonexistent')
+ eq(NIL, fn.luaeval 'vim.b[BUF].nonexistent')
+ eq(NIL, fn.luaeval 'vim.b.nullvar')
-- lost over RPC, so test locally:
- eq({false, true}, exec_lua [[
+ eq(
+ { false, true },
+ exec_lua [[
return {vim.b.nonexistent == vim.NIL, vim.b.nullvar == vim.NIL}
- ]])
+ ]]
+ )
- matches([[attempt to index .* nil value]],
- pcall_err(exec_lua, 'return vim.b[BUF][0].testing'))
+ matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.b[BUF][0].testing'))
- eq({hello="world"}, funcs.luaeval "vim.b.to_delete")
+ eq({ hello = 'world' }, fn.luaeval 'vim.b.to_delete')
exec_lua [[
vim.b.to_delete = nil
]]
- eq(NIL, funcs.luaeval "vim.b.to_delete")
+ eq(NIL, fn.luaeval 'vim.b.to_delete')
exec_lua [[
local counter = 0
@@ -1222,7 +1623,7 @@ describe('lua stdlib', function()
local function get_counter() return counter end
vim.b.AddCounter = add_counter
vim.b.GetCounter = get_counter
- vim.b.funcs = {add = add_counter, get = get_counter}
+ vim.b.fn = {add = add_counter, get = get_counter}
vim.b.AddParens = function(s) return '(' .. s .. ')' end
]]
@@ -1235,10 +1636,10 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.b.GetCounter()]]))
exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
- exec_lua([[vim.b.funcs.add()]])
- eq(5, exec_lua([[return vim.b.funcs.get()]]))
- exec_lua([[vim.api.nvim_buf_get_var(0, 'funcs').add()]])
- eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'funcs').get()]]))
+ exec_lua([[vim.b.fn.add()]])
+ eq(5, exec_lua([[return vim.b.fn.get()]]))
+ exec_lua([[vim.api.nvim_buf_get_var(0, 'fn').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'fn').get()]]))
eq('((foo))', eval([['foo'->b:AddParens()->b:AddParens()]]))
exec_lua [[
@@ -1247,7 +1648,7 @@ describe('lua stdlib', function()
local function get_counter() return counter end
vim.api.nvim_buf_set_var(0, 'AddCounter', add_counter)
vim.api.nvim_buf_set_var(0, 'GetCounter', get_counter)
- vim.api.nvim_buf_set_var(0, 'funcs', {add = add_counter, get = get_counter})
+ vim.api.nvim_buf_set_var(0, 'fn', {add = add_counter, get = get_counter})
vim.api.nvim_buf_set_var(0, 'AddParens', function(s) return '(' .. s .. ')' end)
]]
@@ -1260,10 +1661,10 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.b.GetCounter()]]))
exec_lua([[vim.api.nvim_buf_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_buf_get_var(0, 'GetCounter')()]]))
- exec_lua([[vim.b.funcs.add()]])
- eq(5, exec_lua([[return vim.b.funcs.get()]]))
- exec_lua([[vim.api.nvim_buf_get_var(0, 'funcs').add()]])
- eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'funcs').get()]]))
+ exec_lua([[vim.b.fn.add()]])
+ eq(5, exec_lua([[return vim.b.fn.get()]]))
+ exec_lua([[vim.api.nvim_buf_get_var(0, 'fn').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_buf_get_var(0, 'fn').get()]]))
eq('((foo))', eval([['foo'->b:AddParens()->b:AddParens()]]))
exec([[
@@ -1281,9 +1682,9 @@ describe('lua stdlib', function()
vim.cmd "vnew"
]]
- eq(NIL, funcs.luaeval "vim.b.testing")
- eq(NIL, funcs.luaeval "vim.b.other")
- eq(NIL, funcs.luaeval "vim.b.nonexistent")
+ eq(NIL, fn.luaeval 'vim.b.testing')
+ eq(NIL, fn.luaeval 'vim.b.other')
+ eq(NIL, fn.luaeval 'vim.b.nonexistent')
end)
it('vim.w', function()
@@ -1299,20 +1700,19 @@ describe('lua stdlib', function()
vim.api.nvim_win_set_var(WIN, "testing", "bye")
]]
- eq('hi', funcs.luaeval "vim.w.testing")
- eq('bye', funcs.luaeval "vim.w[WIN].testing")
- eq(123, funcs.luaeval "vim.w.other")
- eq(NIL, funcs.luaeval "vim.w.nonexistent")
- eq(NIL, funcs.luaeval "vim.w[WIN].nonexistent")
+ eq('hi', fn.luaeval 'vim.w.testing')
+ eq('bye', fn.luaeval 'vim.w[WIN].testing')
+ eq(123, fn.luaeval 'vim.w.other')
+ eq(NIL, fn.luaeval 'vim.w.nonexistent')
+ eq(NIL, fn.luaeval 'vim.w[WIN].nonexistent')
- matches([[attempt to index .* nil value]],
- pcall_err(exec_lua, 'return vim.w[WIN][0].testing'))
+ matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.w[WIN][0].testing'))
- eq({hello="world"}, funcs.luaeval "vim.w.to_delete")
+ eq({ hello = 'world' }, fn.luaeval 'vim.w.to_delete')
exec_lua [[
vim.w.to_delete = nil
]]
- eq(NIL, funcs.luaeval "vim.w.to_delete")
+ eq(NIL, fn.luaeval 'vim.w.to_delete')
exec_lua [[
local counter = 0
@@ -1320,7 +1720,7 @@ describe('lua stdlib', function()
local function get_counter() return counter end
vim.w.AddCounter = add_counter
vim.w.GetCounter = get_counter
- vim.w.funcs = {add = add_counter, get = get_counter}
+ vim.w.fn = {add = add_counter, get = get_counter}
vim.w.AddParens = function(s) return '(' .. s .. ')' end
]]
@@ -1333,10 +1733,10 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.w.GetCounter()]]))
exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
- exec_lua([[vim.w.funcs.add()]])
- eq(5, exec_lua([[return vim.w.funcs.get()]]))
- exec_lua([[vim.api.nvim_win_get_var(0, 'funcs').add()]])
- eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'funcs').get()]]))
+ exec_lua([[vim.w.fn.add()]])
+ eq(5, exec_lua([[return vim.w.fn.get()]]))
+ exec_lua([[vim.api.nvim_win_get_var(0, 'fn').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'fn').get()]]))
eq('((foo))', eval([['foo'->w:AddParens()->w:AddParens()]]))
exec_lua [[
@@ -1345,7 +1745,7 @@ describe('lua stdlib', function()
local function get_counter() return counter end
vim.api.nvim_win_set_var(0, 'AddCounter', add_counter)
vim.api.nvim_win_set_var(0, 'GetCounter', get_counter)
- vim.api.nvim_win_set_var(0, 'funcs', {add = add_counter, get = get_counter})
+ vim.api.nvim_win_set_var(0, 'fn', {add = add_counter, get = get_counter})
vim.api.nvim_win_set_var(0, 'AddParens', function(s) return '(' .. s .. ')' end)
]]
@@ -1358,10 +1758,10 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.w.GetCounter()]]))
exec_lua([[vim.api.nvim_win_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_win_get_var(0, 'GetCounter')()]]))
- exec_lua([[vim.w.funcs.add()]])
- eq(5, exec_lua([[return vim.w.funcs.get()]]))
- exec_lua([[vim.api.nvim_win_get_var(0, 'funcs').add()]])
- eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'funcs').get()]]))
+ exec_lua([[vim.w.fn.add()]])
+ eq(5, exec_lua([[return vim.w.fn.get()]]))
+ exec_lua([[vim.api.nvim_win_get_var(0, 'fn').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_win_get_var(0, 'fn').get()]]))
eq('((foo))', eval([['foo'->w:AddParens()->w:AddParens()]]))
exec([[
@@ -1379,9 +1779,9 @@ describe('lua stdlib', function()
vim.cmd "vnew"
]]
- eq(NIL, funcs.luaeval "vim.w.testing")
- eq(NIL, funcs.luaeval "vim.w.other")
- eq(NIL, funcs.luaeval "vim.w.nonexistent")
+ eq(NIL, fn.luaeval 'vim.w.testing')
+ eq(NIL, fn.luaeval 'vim.w.other')
+ eq(NIL, fn.luaeval 'vim.w.nonexistent')
end)
it('vim.t', function()
@@ -1391,21 +1791,20 @@ describe('lua stdlib', function()
vim.api.nvim_tabpage_set_var(0, "to_delete", {hello="world"})
]]
- eq('hi', funcs.luaeval "vim.t.testing")
- eq(123, funcs.luaeval "vim.t.other")
- eq(NIL, funcs.luaeval "vim.t.nonexistent")
- eq('hi', funcs.luaeval "vim.t[0].testing")
- eq(123, funcs.luaeval "vim.t[0].other")
- eq(NIL, funcs.luaeval "vim.t[0].nonexistent")
+ eq('hi', fn.luaeval 'vim.t.testing')
+ eq(123, fn.luaeval 'vim.t.other')
+ eq(NIL, fn.luaeval 'vim.t.nonexistent')
+ eq('hi', fn.luaeval 'vim.t[0].testing')
+ eq(123, fn.luaeval 'vim.t[0].other')
+ eq(NIL, fn.luaeval 'vim.t[0].nonexistent')
- matches([[attempt to index .* nil value]],
- pcall_err(exec_lua, 'return vim.t[0][0].testing'))
+ matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.t[0][0].testing'))
- eq({hello="world"}, funcs.luaeval "vim.t.to_delete")
+ eq({ hello = 'world' }, fn.luaeval 'vim.t.to_delete')
exec_lua [[
vim.t.to_delete = nil
]]
- eq(NIL, funcs.luaeval "vim.t.to_delete")
+ eq(NIL, fn.luaeval 'vim.t.to_delete')
exec_lua [[
local counter = 0
@@ -1413,7 +1812,7 @@ describe('lua stdlib', function()
local function get_counter() return counter end
vim.t.AddCounter = add_counter
vim.t.GetCounter = get_counter
- vim.t.funcs = {add = add_counter, get = get_counter}
+ vim.t.fn = {add = add_counter, get = get_counter}
vim.t.AddParens = function(s) return '(' .. s .. ')' end
]]
@@ -1426,10 +1825,10 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.t.GetCounter()]]))
exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
- exec_lua([[vim.t.funcs.add()]])
- eq(5, exec_lua([[return vim.t.funcs.get()]]))
- exec_lua([[vim.api.nvim_tabpage_get_var(0, 'funcs').add()]])
- eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'funcs').get()]]))
+ exec_lua([[vim.t.fn.add()]])
+ eq(5, exec_lua([[return vim.t.fn.get()]]))
+ exec_lua([[vim.api.nvim_tabpage_get_var(0, 'fn').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'fn').get()]]))
eq('((foo))', eval([['foo'->t:AddParens()->t:AddParens()]]))
exec_lua [[
@@ -1438,7 +1837,7 @@ describe('lua stdlib', function()
local function get_counter() return counter end
vim.api.nvim_tabpage_set_var(0, 'AddCounter', add_counter)
vim.api.nvim_tabpage_set_var(0, 'GetCounter', get_counter)
- vim.api.nvim_tabpage_set_var(0, 'funcs', {add = add_counter, get = get_counter})
+ vim.api.nvim_tabpage_set_var(0, 'fn', {add = add_counter, get = get_counter})
vim.api.nvim_tabpage_set_var(0, 'AddParens', function(s) return '(' .. s .. ')' end)
]]
@@ -1451,47 +1850,46 @@ describe('lua stdlib', function()
eq(3, exec_lua([[return vim.t.GetCounter()]]))
exec_lua([[vim.api.nvim_tabpage_get_var(0, 'AddCounter')()]])
eq(4, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'GetCounter')()]]))
- exec_lua([[vim.t.funcs.add()]])
- eq(5, exec_lua([[return vim.t.funcs.get()]]))
- exec_lua([[vim.api.nvim_tabpage_get_var(0, 'funcs').add()]])
- eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'funcs').get()]]))
+ exec_lua([[vim.t.fn.add()]])
+ eq(5, exec_lua([[return vim.t.fn.get()]]))
+ exec_lua([[vim.api.nvim_tabpage_get_var(0, 'fn').add()]])
+ eq(6, exec_lua([[return vim.api.nvim_tabpage_get_var(0, 'fn').get()]]))
eq('((foo))', eval([['foo'->t:AddParens()->t:AddParens()]]))
exec_lua [[
vim.cmd "tabnew"
]]
- eq(NIL, funcs.luaeval "vim.t.testing")
- eq(NIL, funcs.luaeval "vim.t.other")
- eq(NIL, funcs.luaeval "vim.t.nonexistent")
+ eq(NIL, fn.luaeval 'vim.t.testing')
+ eq(NIL, fn.luaeval 'vim.t.other')
+ eq(NIL, fn.luaeval 'vim.t.nonexistent')
end)
it('vim.env', function()
exec_lua([[vim.fn.setenv('A', 123)]])
- eq('123', funcs.luaeval('vim.env.A'))
+ eq('123', fn.luaeval('vim.env.A'))
exec_lua([[vim.env.A = 456]])
- eq('456', funcs.luaeval('vim.env.A'))
+ eq('456', fn.luaeval('vim.env.A'))
exec_lua([[vim.env.A = nil]])
- eq(NIL, funcs.luaeval('vim.env.A'))
+ eq(NIL, fn.luaeval('vim.env.A'))
- eq(true, funcs.luaeval('vim.env.B == nil'))
+ eq(true, fn.luaeval('vim.env.B == nil'))
command([[let $HOME = 'foo']])
- eq('foo', funcs.expand('~'))
- eq('foo', funcs.luaeval('vim.env.HOME'))
+ eq('foo', fn.expand('~'))
+ eq('foo', fn.luaeval('vim.env.HOME'))
exec_lua([[vim.env.HOME = nil]])
- eq('foo', funcs.expand('~'))
+ eq('foo', fn.expand('~'))
exec_lua([[vim.env.HOME = 'bar']])
- eq('bar', funcs.expand('~'))
- eq('bar', funcs.luaeval('vim.env.HOME'))
+ eq('bar', fn.expand('~'))
+ eq('bar', fn.luaeval('vim.env.HOME'))
end)
it('vim.v', function()
- eq(funcs.luaeval "vim.api.nvim_get_vvar('progpath')", funcs.luaeval "vim.v.progpath")
- eq(false, funcs.luaeval "vim.v['false']")
- eq(NIL, funcs.luaeval "vim.v.null")
- matches([[attempt to index .* nil value]],
- pcall_err(exec_lua, 'return vim.v[0].progpath'))
+ eq(fn.luaeval "vim.api.nvim_get_vvar('progpath')", fn.luaeval 'vim.v.progpath')
+ eq(false, fn.luaeval "vim.v['false']")
+ eq(NIL, fn.luaeval 'vim.v.null')
+ matches([[attempt to index .* nil value]], pcall_err(exec_lua, 'return vim.v[0].progpath'))
eq('Key is read-only: count', pcall_err(exec_lua, [[vim.v.count = 42]]))
eq('Dictionary is locked', pcall_err(exec_lua, [[vim.v.nosuchvar = 42]]))
eq('Key is fixed: errmsg', pcall_err(exec_lua, [[vim.v.errmsg = nil]]))
@@ -1507,69 +1905,72 @@ describe('lua stdlib', function()
eq({}, eval('v:oldfiles'))
feed('i foo foo foo<Esc>0/foo<CR>')
- eq({1, 1}, meths.win_get_cursor(0))
+ eq({ 1, 1 }, api.nvim_win_get_cursor(0))
eq(1, eval('v:searchforward'))
feed('n')
- eq({1, 5}, meths.win_get_cursor(0))
+ eq({ 1, 5 }, api.nvim_win_get_cursor(0))
exec_lua([[vim.v.searchforward = 0]])
eq(0, eval('v:searchforward'))
feed('n')
- eq({1, 1}, meths.win_get_cursor(0))
+ eq({ 1, 1 }, api.nvim_win_get_cursor(0))
exec_lua([[vim.v.searchforward = 1]])
eq(1, eval('v:searchforward'))
feed('n')
- eq({1, 5}, meths.win_get_cursor(0))
+ eq({ 1, 5 }, api.nvim_win_get_cursor(0))
local screen = Screen.new(60, 3)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {background = Screen.colors.Yellow},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { background = Screen.colors.Yellow },
})
screen:attach()
eq(1, eval('v:hlsearch'))
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:foo} {1:^foo} {1:foo} |
{0:~ }|
|
- ]]}
+ ]],
+ }
exec_lua([[vim.v.hlsearch = 0]])
eq(0, eval('v:hlsearch'))
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
foo ^foo foo |
{0:~ }|
|
- ]]}
+ ]],
+ }
exec_lua([[vim.v.hlsearch = 1]])
eq(1, eval('v:hlsearch'))
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:foo} {1:^foo} {1:foo} |
{0:~ }|
|
- ]]}
+ ]],
+ }
end)
it('vim.bo', function()
- eq('', funcs.luaeval "vim.bo.filetype")
+ eq('', fn.luaeval 'vim.bo.filetype')
exec_lua [[
vim.api.nvim_set_option_value("filetype", "markdown", {})
BUF = vim.api.nvim_create_buf(false, true)
vim.api.nvim_set_option_value("modifiable", false, {buf = BUF})
]]
- eq(false, funcs.luaeval "vim.bo.modified")
- eq('markdown', funcs.luaeval "vim.bo.filetype")
- eq(false, funcs.luaeval "vim.bo[BUF].modifiable")
+ eq(false, fn.luaeval 'vim.bo.modified')
+ eq('markdown', fn.luaeval 'vim.bo.filetype')
+ eq(false, fn.luaeval 'vim.bo[BUF].modifiable')
exec_lua [[
vim.bo.filetype = ''
vim.bo[BUF].modifiable = true
]]
- eq('', funcs.luaeval "vim.bo.filetype")
- eq(true, funcs.luaeval "vim.bo[BUF].modifiable")
- matches("Unknown option 'nosuchopt'$",
- pcall_err(exec_lua, 'return vim.bo.nosuchopt'))
- matches("Expected Lua string$",
- pcall_err(exec_lua, 'return vim.bo[0][0].autoread'))
- matches("Invalid buffer id: %-1$",
- pcall_err(exec_lua, 'return vim.bo[-1].filetype'))
+ eq('', fn.luaeval 'vim.bo.filetype')
+ eq(true, fn.luaeval 'vim.bo[BUF].modifiable')
+ matches("Unknown option 'nosuchopt'$", pcall_err(exec_lua, 'return vim.bo.nosuchopt'))
+ matches('Expected Lua string$', pcall_err(exec_lua, 'return vim.bo[0][0].autoread'))
+ matches('Invalid buffer id: %-1$', pcall_err(exec_lua, 'return vim.bo[-1].filetype'))
end)
it('vim.wo', function()
@@ -1578,34 +1979,32 @@ describe('lua stdlib', function()
vim.cmd "split"
vim.api.nvim_set_option_value("cole", 2, {})
]]
- eq(2, funcs.luaeval "vim.wo.cole")
+ eq(2, fn.luaeval 'vim.wo.cole')
exec_lua [[
vim.wo.conceallevel = 0
]]
- eq(0, funcs.luaeval "vim.wo.cole")
- eq(0, funcs.luaeval "vim.wo[0].cole")
- eq(0, funcs.luaeval "vim.wo[1001].cole")
- matches("Unknown option 'notanopt'$",
- pcall_err(exec_lua, 'return vim.wo.notanopt'))
- matches("Invalid window id: %-1$",
- pcall_err(exec_lua, 'return vim.wo[-1].list'))
- eq(2, funcs.luaeval "vim.wo[1000].cole")
+ eq(0, fn.luaeval 'vim.wo.cole')
+ eq(0, fn.luaeval 'vim.wo[0].cole')
+ eq(0, fn.luaeval 'vim.wo[1001].cole')
+ matches("Unknown option 'notanopt'$", pcall_err(exec_lua, 'return vim.wo.notanopt'))
+ matches('Invalid window id: %-1$', pcall_err(exec_lua, 'return vim.wo[-1].list'))
+ eq(2, fn.luaeval 'vim.wo[1000].cole')
exec_lua [[
vim.wo[1000].cole = 0
]]
- eq(0, funcs.luaeval "vim.wo[1000].cole")
+ eq(0, fn.luaeval 'vim.wo[1000].cole')
-- Can handle global-local values
exec_lua [[vim.o.scrolloff = 100]]
exec_lua [[vim.wo.scrolloff = 200]]
- eq(200, funcs.luaeval "vim.wo.scrolloff")
+ eq(200, fn.luaeval 'vim.wo.scrolloff')
exec_lua [[vim.wo.scrolloff = -1]]
- eq(100, funcs.luaeval "vim.wo.scrolloff")
+ eq(100, fn.luaeval 'vim.wo.scrolloff')
exec_lua [[
vim.wo[0][0].scrolloff = 200
vim.cmd "enew"
]]
- eq(100, funcs.luaeval "vim.wo.scrolloff")
+ eq(100, fn.luaeval 'vim.wo.scrolloff')
end)
describe('vim.opt', function()
@@ -1638,7 +2037,7 @@ describe('lua stdlib', function()
vim.opt.wildignore = { 'hello', 'world' }
return vim.o.wildignore
]]
- eq(wildignore, "hello,world")
+ eq(wildignore, 'hello,world')
end)
it('should allow setting tables with shortnames', function()
@@ -1646,7 +2045,7 @@ describe('lua stdlib', function()
vim.opt.wig = { 'hello', 'world' }
return vim.o.wildignore
]]
- eq(wildignore, "hello,world")
+ eq(wildignore, 'hello,world')
end)
it('should error when you attempt to set string values to numeric options', function()
@@ -1668,7 +2067,9 @@ describe('lua stdlib', function()
end)
it('should allow you to set boolean values', function()
- eq({true, false, true}, exec_lua [[
+ eq(
+ { true, false, true },
+ exec_lua [[
local results = {}
vim.opt.autoindent = true
@@ -1681,7 +2082,8 @@ describe('lua stdlib', function()
table.insert(results, vim.bo.autoindent)
return results
- ]])
+ ]]
+ )
end)
it('should change current buffer values and defaults for global local values', function()
@@ -1707,20 +2109,20 @@ describe('lua stdlib', function()
]]
-- Set -> global & local
- eq("global-local", result[1])
- eq("", result[2])
+ eq('global-local', result[1])
+ eq('', result[2])
-- Setlocal -> only local
- eq("global-local", result[3])
- eq("only-local", result[4])
+ eq('global-local', result[3])
+ eq('only-local', result[4])
-- Setglobal -> only global
- eq("only-global", result[5])
- eq("only-local", result[6])
+ eq('only-global', result[5])
+ eq('only-local', result[6])
-- Set -> sets global value and resets local value
- eq("global-local", result[7])
- eq("", result[8])
+ eq('global-local', result[7])
+ eq('', result[8])
end)
it('should allow you to retrieve window opts even if they have not been set', function()
@@ -1735,11 +2137,13 @@ describe('lua stdlib', function()
return result
]]
- eq({false, false, true, true}, result)
+ eq({ false, false, true, true }, result)
end)
it('should allow all sorts of string manipulation', function()
- eq({'hello', 'hello world', 'start hello world'}, exec_lua [[
+ eq(
+ { 'hello', 'hello world', 'start hello world' },
+ exec_lua [[
local results = {}
vim.opt.makeprg = "hello"
@@ -1752,19 +2156,23 @@ describe('lua stdlib', function()
table.insert(results, vim.o.makeprg)
return results
- ]])
+ ]]
+ )
end)
describe('option:get()', function()
it('should work for boolean values', function()
- eq(false, exec_lua [[
+ eq(
+ false,
+ exec_lua [[
vim.opt.number = false
return vim.opt.number:get()
- ]])
+ ]]
+ )
end)
it('should work for number values', function()
- local tabstop = exec_lua[[
+ local tabstop = exec_lua [[
vim.opt.tabstop = 10
return vim.opt.tabstop:get()
]]
@@ -1773,10 +2181,13 @@ describe('lua stdlib', function()
end)
it('should work for string values', function()
- eq("hello world", exec_lua [[
+ eq(
+ 'hello world',
+ exec_lua [[
vim.opt.makeprg = "hello world"
return vim.opt.makeprg:get()
- ]])
+ ]]
+ )
end)
it('should work for set type flaglists', function()
@@ -1806,7 +2217,7 @@ describe('lua stdlib', function()
]]
eq(3, #wildignore)
- eq("*.c", wildignore[1])
+ eq('*.c', wildignore[1])
end)
it('should work for options that are both commalist and flaglist', function()
@@ -1815,14 +2226,14 @@ describe('lua stdlib', function()
return vim.opt.whichwrap:get()
]]
- eq({b = true, s = true}, result)
+ eq({ b = true, s = true }, result)
result = exec_lua [[
vim.opt.whichwrap = { b = true, s = false, h = true }
return vim.opt.whichwrap:get()
]]
- eq({b = true, h = true}, result)
+ eq({ b = true, h = true }, result)
end)
it('should work for key-value pair options', function()
@@ -1832,25 +2243,31 @@ describe('lua stdlib', function()
]]
eq({
- tab = "> ",
- space = "_",
+ tab = '> ',
+ space = '_',
}, listchars)
end)
it('should allow you to add numeric options', function()
- eq(16, exec_lua [[
+ eq(
+ 16,
+ exec_lua [[
vim.opt.tabstop = 12
vim.opt.tabstop = vim.opt.tabstop + 4
return vim.bo.tabstop
- ]])
+ ]]
+ )
end)
it('should allow you to subtract numeric options', function()
- eq(2, exec_lua [[
+ eq(
+ 2,
+ exec_lua [[
vim.opt.tabstop = 4
vim.opt.tabstop = vim.opt.tabstop - 2
return vim.bo.tabstop
- ]])
+ ]]
+ )
end)
end)
@@ -1864,7 +2281,7 @@ describe('lua stdlib', function()
return vim.o.listchars
]]
- eq("eol:~,space:.", listchars)
+ eq('eol:~,space:.', listchars)
end)
it('should allow adding dictionary style', function()
@@ -1879,7 +2296,7 @@ describe('lua stdlib', function()
return vim.o.listchars
]]
- eq("eol:~,space:-", listchars)
+ eq('eol:~,space:-', listchars)
end)
it('should allow adding dictionary style', function()
@@ -1893,7 +2310,7 @@ describe('lua stdlib', function()
return vim.o.listchars
]]
- eq("eol:~,space:_", listchars)
+ eq('eol:~,space:_', listchars)
end)
it('should allow completely new keys', function()
@@ -1907,7 +2324,7 @@ describe('lua stdlib', function()
return vim.o.listchars
]]
- eq("eol:~,space:.,tab:>>>", listchars)
+ eq('eol:~,space:.,tab:>>>', listchars)
end)
it('should allow subtracting dictionary style', function()
@@ -1921,7 +2338,7 @@ describe('lua stdlib', function()
return vim.o.listchars
]]
- eq("eol:~", listchars)
+ eq('eol:~', listchars)
end)
it('should allow subtracting dictionary style', function()
@@ -1935,7 +2352,7 @@ describe('lua stdlib', function()
return vim.o.listchars
]]
- eq("", listchars)
+ eq('', listchars)
end)
it('should allow subtracting dictionary style multiple times', function()
@@ -1949,7 +2366,7 @@ describe('lua stdlib', function()
return vim.o.listchars
]]
- eq("eol:~", listchars)
+ eq('eol:~', listchars)
end)
it('should allow adding a key:value string to a listchars', function()
@@ -1963,7 +2380,7 @@ describe('lua stdlib', function()
return vim.o.listchars
]]
- eq("eol:~,space:.,tab:>~", listchars)
+ eq('eol:~,space:.,tab:>~', listchars)
end)
it('should allow prepending a key:value string to a listchars', function()
@@ -1977,44 +2394,56 @@ describe('lua stdlib', function()
return vim.o.listchars
]]
- eq("eol:~,space:.,tab:>~", listchars)
+ eq('eol:~,space:.,tab:>~', listchars)
end)
end)
it('should automatically set when calling remove', function()
- eq("foo,baz", exec_lua [[
+ eq(
+ 'foo,baz',
+ exec_lua [[
vim.opt.wildignore = "foo,bar,baz"
vim.opt.wildignore:remove("bar")
return vim.o.wildignore
- ]])
+ ]]
+ )
end)
it('should automatically set when calling remove with a table', function()
- eq("foo", exec_lua [[
+ eq(
+ 'foo',
+ exec_lua [[
vim.opt.wildignore = "foo,bar,baz"
vim.opt.wildignore:remove { "bar", "baz" }
return vim.o.wildignore
- ]])
+ ]]
+ )
end)
it('should automatically set when calling append', function()
- eq("foo,bar,baz,bing", exec_lua [[
+ eq(
+ 'foo,bar,baz,bing',
+ exec_lua [[
vim.opt.wildignore = "foo,bar,baz"
vim.opt.wildignore:append("bing")
return vim.o.wildignore
- ]])
+ ]]
+ )
end)
it('should automatically set when calling append with a table', function()
- eq("foo,bar,baz,bing,zap", exec_lua [[
+ eq(
+ 'foo,bar,baz,bing,zap',
+ exec_lua [[
vim.opt.wildignore = "foo,bar,baz"
vim.opt.wildignore:append { "bing", "zap" }
return vim.o.wildignore
- ]])
+ ]]
+ )
end)
it('should allow adding tables', function()
@@ -2106,96 +2535,198 @@ describe('lua stdlib', function()
describe('option types', function()
it('should allow to set option with numeric value', function()
- eq(4, exec_lua [[
+ eq(
+ 4,
+ exec_lua [[
vim.opt.tabstop = 4
return vim.bo.tabstop
- ]])
+ ]]
+ )
- matches("Invalid option type 'string' for 'tabstop'", pcall_err(exec_lua, [[
+ matches(
+ "Invalid option type 'string' for 'tabstop'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.tabstop = '4'
- ]]))
- matches("Invalid option type 'boolean' for 'tabstop'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'boolean' for 'tabstop'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.tabstop = true
- ]]))
- matches("Invalid option type 'table' for 'tabstop'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'table' for 'tabstop'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.tabstop = {4, 2}
- ]]))
- matches("Invalid option type 'function' for 'tabstop'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'function' for 'tabstop'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.tabstop = function()
return 4
end
- ]]))
+ ]]
+ )
+ )
end)
it('should allow to set option with boolean value', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
vim.opt.undofile = true
return vim.bo.undofile
- ]])
+ ]]
+ )
- matches("Invalid option type 'number' for 'undofile'", pcall_err(exec_lua, [[
+ matches(
+ "Invalid option type 'number' for 'undofile'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.undofile = 0
- ]]))
- matches("Invalid option type 'table' for 'undofile'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'table' for 'undofile'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.undofile = {true}
- ]]))
- matches("Invalid option type 'string' for 'undofile'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'string' for 'undofile'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.undofile = 'true'
- ]]))
- matches("Invalid option type 'function' for 'undofile'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'function' for 'undofile'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.undofile = function()
return true
end
- ]]))
+ ]]
+ )
+ )
end)
it('should allow to set option with array or string value', function()
- eq('indent,eol,start', exec_lua [[
+ eq(
+ 'indent,eol,start',
+ exec_lua [[
vim.opt.backspace = {'indent','eol','start'}
return vim.go.backspace
- ]])
- eq('indent,eol,start', exec_lua [[
+ ]]
+ )
+ eq(
+ 'indent,eol,start',
+ exec_lua [[
vim.opt.backspace = 'indent,eol,start'
return vim.go.backspace
- ]])
+ ]]
+ )
- matches("Invalid option type 'boolean' for 'backspace'", pcall_err(exec_lua, [[
+ matches(
+ "Invalid option type 'boolean' for 'backspace'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.backspace = true
- ]]))
- matches("Invalid option type 'number' for 'backspace'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'number' for 'backspace'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.backspace = 2
- ]]))
- matches("Invalid option type 'function' for 'backspace'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'function' for 'backspace'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.backspace = function()
return 'indent,eol,start'
end
- ]]))
+ ]]
+ )
+ )
end)
it('should allow set option with map or string value', function()
- eq("eol:~,space:.", exec_lua [[
+ eq(
+ 'eol:~,space:.',
+ exec_lua [[
vim.opt.listchars = {
eol = "~",
space = ".",
}
return vim.o.listchars
- ]])
- eq("eol:~,space:.,tab:>~", exec_lua [[
+ ]]
+ )
+ eq(
+ 'eol:~,space:.,tab:>~',
+ exec_lua [[
vim.opt.listchars = "eol:~,space:.,tab:>~"
return vim.o.listchars
- ]])
+ ]]
+ )
- matches("Invalid option type 'boolean' for 'listchars'", pcall_err(exec_lua, [[
+ matches(
+ "Invalid option type 'boolean' for 'listchars'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.listchars = true
- ]]))
- matches("Invalid option type 'number' for 'listchars'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'number' for 'listchars'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.listchars = 2
- ]]))
- matches("Invalid option type 'function' for 'listchars'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'function' for 'listchars'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.listchars = function()
return "eol:~,space:.,tab:>~"
end
- ]]))
+ ]]
+ )
+ )
end)
it('should allow set option with set or string value', function()
@@ -2207,23 +2738,44 @@ describe('lua stdlib', function()
return vim.go.whichwrap
]]
- eq(ww, "b,s")
- eq("b,s,<,>,[,]", exec_lua [[
+ eq(ww, 'b,s')
+ eq(
+ 'b,s,<,>,[,]',
+ exec_lua [[
vim.opt.whichwrap = "b,s,<,>,[,]"
return vim.go.whichwrap
- ]])
+ ]]
+ )
- matches("Invalid option type 'boolean' for 'whichwrap'", pcall_err(exec_lua, [[
+ matches(
+ "Invalid option type 'boolean' for 'whichwrap'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.whichwrap = true
- ]]))
- matches("Invalid option type 'number' for 'whichwrap'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'number' for 'whichwrap'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.whichwrap = 2
- ]]))
- matches("Invalid option type 'function' for 'whichwrap'", pcall_err(exec_lua, [[
+ ]]
+ )
+ )
+ matches(
+ "Invalid option type 'function' for 'whichwrap'",
+ pcall_err(
+ exec_lua,
+ [[
vim.opt.whichwrap = function()
return "b,s,<,>,[,]"
end
- ]]))
+ ]]
+ )
+ )
end)
end)
@@ -2234,7 +2786,7 @@ describe('lua stdlib', function()
return { vim.opt.isfname:get(), vim.go.isfname }
]]
- eq({{",", "a", "b", "c"}, "a,b,,,c"}, result)
+ eq({ { ',', 'a', 'b', 'c' }, 'a,b,,,c' }, result)
end)
-- isfname=a,b,c,^,,def
@@ -2244,77 +2796,101 @@ describe('lua stdlib', function()
return { vim.opt.isfname:get(), vim.go.isfname }
]]
- eq({{"^,", "a", "b", "c"}, "a,b,^,,c"}, result)
+ eq({ { '^,', 'a', 'b', 'c' }, 'a,b,^,,c' }, result)
end)
-
-
describe('https://github.com/neovim/neovim/issues/14828', function()
it('gives empty list when item is empty:array', function()
- eq({}, exec_lua [[
+ eq(
+ {},
+ exec_lua [[
vim.cmd("set wildignore=")
return vim.opt.wildignore:get()
- ]])
+ ]]
+ )
- eq({}, exec_lua [[
+ eq(
+ {},
+ exec_lua [[
vim.opt.wildignore = {}
return vim.opt.wildignore:get()
- ]])
+ ]]
+ )
end)
it('gives empty list when item is empty:set', function()
- eq({}, exec_lua [[
+ eq(
+ {},
+ exec_lua [[
vim.cmd("set formatoptions=")
return vim.opt.formatoptions:get()
- ]])
+ ]]
+ )
- eq({}, exec_lua [[
+ eq(
+ {},
+ exec_lua [[
vim.opt.formatoptions = {}
return vim.opt.formatoptions:get()
- ]])
+ ]]
+ )
end)
it('does not append to empty item', function()
- eq({"*.foo", "*.bar"}, exec_lua [[
+ eq(
+ { '*.foo', '*.bar' },
+ exec_lua [[
vim.opt.wildignore = {}
vim.opt.wildignore:append { "*.foo", "*.bar" }
return vim.opt.wildignore:get()
- ]])
+ ]]
+ )
end)
it('does not prepend to empty item', function()
- eq({"*.foo", "*.bar"}, exec_lua [[
+ eq(
+ { '*.foo', '*.bar' },
+ exec_lua [[
vim.opt.wildignore = {}
vim.opt.wildignore:prepend { "*.foo", "*.bar" }
return vim.opt.wildignore:get()
- ]])
+ ]]
+ )
end)
it('append to empty set', function()
- eq({ t = true }, exec_lua [[
+ eq(
+ { t = true },
+ exec_lua [[
vim.opt.formatoptions = {}
vim.opt.formatoptions:append("t")
return vim.opt.formatoptions:get()
- ]])
+ ]]
+ )
end)
it('prepend to empty set', function()
- eq({ t = true }, exec_lua [[
+ eq(
+ { t = true },
+ exec_lua [[
vim.opt.formatoptions = {}
vim.opt.formatoptions:prepend("t")
return vim.opt.formatoptions:get()
- ]])
+ ]]
+ )
end)
end)
end) -- vim.opt
describe('vim.opt_local', function()
it('appends into global value when changing local option value', function()
- eq({ "foo,bar,baz,qux" }, exec_lua [[
+ eq(
+ { 'foo,bar,baz,qux' },
+ exec_lua [[
local result = {}
vim.opt.tags = "foo,bar"
@@ -2324,20 +2900,24 @@ describe('lua stdlib', function()
table.insert(result, vim.bo.tags)
return result
- ]])
+ ]]
+ )
end)
end)
describe('vim.opt_global', function()
it('gets current global option value', function()
- eq({ "yes" }, exec_lua [[
+ eq(
+ { 'yes' },
+ exec_lua [[
local result = {}
vim.cmd "setglobal signcolumn=yes"
table.insert(result, vim.opt_global.signcolumn:get())
return result
- ]])
+ ]]
+ )
end)
end)
@@ -2346,15 +2926,15 @@ describe('lua stdlib', function()
vim.cmd "autocmd BufNew * ++once lua BUF = vim.fn.expand('<abuf>')"
vim.cmd "new"
]]
- eq('2', funcs.luaeval "BUF")
- eq(2, funcs.luaeval "#vim.api.nvim_list_bufs()")
+ eq('2', fn.luaeval 'BUF')
+ eq(2, fn.luaeval '#vim.api.nvim_list_bufs()')
-- vim.cmd can be indexed with a command name
exec_lua [[
vim.cmd.let 'g:var = 2'
]]
- eq(2, funcs.luaeval "vim.g.var")
+ eq(2, fn.luaeval 'vim.g.var')
end)
it('vim.regex', function()
@@ -2363,16 +2943,16 @@ describe('lua stdlib', function()
vim.cmd "set nomagic ignorecase"
re2 = vim.regex"xYz"
]]
- eq({}, exec_lua[[return {re1:match_str("x ac")}]])
- eq({3,7}, exec_lua[[return {re1:match_str("ac abbc")}]])
+ eq({}, exec_lua [[return {re1:match_str("x ac")}]])
+ eq({ 3, 7 }, exec_lua [[return {re1:match_str("ac abbc")}]])
- meths.buf_set_lines(0, 0, -1, true, {"yy", "abc abbc"})
- eq({}, exec_lua[[return {re1:match_line(0, 0)}]])
- eq({0,3}, exec_lua[[return {re1:match_line(0, 1)}]])
- eq({3,7}, exec_lua[[return {re1:match_line(0, 1, 1)}]])
- eq({3,7}, exec_lua[[return {re1:match_line(0, 1, 1, 8)}]])
- eq({}, exec_lua[[return {re1:match_line(0, 1, 1, 7)}]])
- eq({0,3}, exec_lua[[return {re1:match_line(0, 1, 0, 7)}]])
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'yy', 'abc abbc' })
+ eq({}, exec_lua [[return {re1:match_line(0, 0)}]])
+ eq({ 0, 3 }, exec_lua [[return {re1:match_line(0, 1)}]])
+ eq({ 3, 7 }, exec_lua [[return {re1:match_line(0, 1, 1)}]])
+ eq({ 3, 7 }, exec_lua [[return {re1:match_line(0, 1, 1, 8)}]])
+ eq({}, exec_lua [[return {re1:match_line(0, 1, 1, 7)}]])
+ eq({ 0, 3 }, exec_lua [[return {re1:match_line(0, 1, 0, 7)}]])
-- vim.regex() error inside :silent! should not crash. #20546
command([[silent! lua vim.regex('\\z')]])
@@ -2380,46 +2960,49 @@ describe('lua stdlib', function()
end)
it('vim.defer_fn', function()
- eq(false, exec_lua [[
+ eq(
+ false,
+ exec_lua [[
vim.g.test = false
vim.defer_fn(function() vim.g.test = true end, 150)
return vim.g.test
- ]])
+ ]]
+ )
exec_lua [[vim.wait(1000, function() return vim.g.test end)]]
- eq(true, exec_lua[[return vim.g.test]])
+ eq(true, exec_lua [[return vim.g.test]])
end)
describe('vim.region', function()
it('charwise', function()
- insert(dedent( [[
+ insert(dedent([[
text tααt tααt text
text tαxt txtα tex
text tαxt tαxt
]]))
- eq({5,13}, exec_lua[[ return vim.region(0,{0,5},{0,13},'v',false)[0] ]])
- eq({5,15}, exec_lua[[ return vim.region(0,{0,5},{0,13},'v',true)[0] ]])
- eq({5,15}, exec_lua[[ return vim.region(0,{0,5},{0,14},'v',true)[0] ]])
- eq({5,15}, exec_lua[[ return vim.region(0,{0,5},{0,15},'v',false)[0] ]])
- eq({5,17}, exec_lua[[ return vim.region(0,{0,5},{0,15},'v',true)[0] ]])
- eq({5,17}, exec_lua[[ return vim.region(0,{0,5},{0,16},'v',true)[0] ]])
- eq({5,17}, exec_lua[[ return vim.region(0,{0,5},{0,17},'v',false)[0] ]])
- eq({5,18}, exec_lua[[ return vim.region(0,{0,5},{0,17},'v',true)[0] ]])
+ eq({ 5, 13 }, exec_lua [[ return vim.region(0,{0,5},{0,13},'v',false)[0] ]])
+ eq({ 5, 15 }, exec_lua [[ return vim.region(0,{0,5},{0,13},'v',true)[0] ]])
+ eq({ 5, 15 }, exec_lua [[ return vim.region(0,{0,5},{0,14},'v',true)[0] ]])
+ eq({ 5, 15 }, exec_lua [[ return vim.region(0,{0,5},{0,15},'v',false)[0] ]])
+ eq({ 5, 17 }, exec_lua [[ return vim.region(0,{0,5},{0,15},'v',true)[0] ]])
+ eq({ 5, 17 }, exec_lua [[ return vim.region(0,{0,5},{0,16},'v',true)[0] ]])
+ eq({ 5, 17 }, exec_lua [[ return vim.region(0,{0,5},{0,17},'v',false)[0] ]])
+ eq({ 5, 18 }, exec_lua [[ return vim.region(0,{0,5},{0,17},'v',true)[0] ]])
end)
it('blockwise', function()
insert([[αα]])
- eq({0,5}, exec_lua[[ return vim.region(0,{0,0},{0,4},'3',true)[0] ]])
+ eq({ 0, 5 }, exec_lua [[ return vim.region(0,{0,0},{0,4},'3',true)[0] ]])
end)
it('linewise', function()
- insert(dedent( [[
+ insert(dedent([[
text tααt tααt text
text tαxt txtα tex
text tαxt tαxt
]]))
- eq({0,-1}, exec_lua[[ return vim.region(0,{1,5},{1,14},'V',true)[1] ]])
+ eq({ 0, -1 }, exec_lua [[ return vim.region(0,{1,5},{1,14},'V',true)[1] ]])
end)
it('getpos() input', function()
insert('getpos')
- eq({0,6}, exec_lua[[ return vim.region(0,{0,0},'.','v',true)[0] ]])
+ eq({ 0, 6 }, exec_lua [[ return vim.region(0,{0,0},'.','v',true)[0] ]])
end)
end)
@@ -2447,10 +3030,10 @@ describe('lua stdlib', function()
it('allows removing on_key listeners', function()
-- Create some unused namespaces
- meths.create_namespace('unused1')
- meths.create_namespace('unused2')
- meths.create_namespace('unused3')
- meths.create_namespace('unused4')
+ api.nvim_create_namespace('unused1')
+ api.nvim_create_namespace('unused2')
+ api.nvim_create_namespace('unused3')
+ api.nvim_create_namespace('unused4')
insert([[hello world]])
@@ -2518,9 +3101,9 @@ describe('lua stdlib', function()
table.insert(keys, buf)
end)
]]
- insert("hello")
+ insert('hello')
- eq('iworld<ESC>', exec_lua[[return table.concat(keys, '')]])
+ eq('iworld<ESC>', exec_lua [[return table.concat(keys, '')]])
end)
it('can call vim.fn functions on Ctrl-C #17273', function()
@@ -2534,7 +3117,7 @@ describe('lua stdlib', function()
end)
]])
feed('/')
- poke_eventloop() -- This is needed because Ctrl-C flushes input
+ poke_eventloop() -- This is needed because Ctrl-C flushes input
feed('<C-C>')
eq('/', exec_lua([[return _G.ctrl_c_cmdtype]]))
end)
@@ -2542,7 +3125,7 @@ describe('lua stdlib', function()
describe('vim.wait', function()
before_each(function()
- exec_lua[[
+ exec_lua [[
-- high precision timer
get_time = function()
return vim.fn.reltimefloat(vim.fn.reltime())
@@ -2551,11 +3134,13 @@ describe('lua stdlib', function()
end)
it('should run from lua', function()
- exec_lua[[vim.wait(100, function() return true end)]]
+ exec_lua [[vim.wait(100, function() return true end)]]
end)
it('should wait the expected time if false', function()
- eq({time = true, wait_result = {false, -1}}, exec_lua[[
+ eq(
+ { time = true, wait_result = { false, -1 } },
+ exec_lua [[
start_time = get_time()
wait_succeed, wait_fail_val = vim.wait(200, function() return false end)
@@ -2564,11 +3149,14 @@ describe('lua stdlib', function()
time = (start_time + 0.15) < get_time(),
wait_result = {wait_succeed, wait_fail_val}
}
- ]])
+ ]]
+ )
end)
it('should not block other events', function()
- eq({time = true, wait_result = true}, exec_lua[[
+ eq(
+ { time = true, wait_result = true },
+ exec_lua [[
start_time = get_time()
vim.g.timer_result = false
@@ -2586,11 +3174,14 @@ describe('lua stdlib', function()
time = (start_time + 5) > get_time(),
wait_result = wait_result,
}
- ]])
+ ]]
+ )
end)
it('should not process non-fast events when commanded', function()
- eq({wait_result = false}, exec_lua[[
+ eq(
+ { wait_result = false },
+ exec_lua [[
start_time = get_time()
vim.g.timer_result = false
@@ -2606,11 +3197,14 @@ describe('lua stdlib', function()
return {
wait_result = wait_result,
}
- ]])
+ ]]
+ )
end)
it('should work with vim.defer_fn', function()
- eq({time = true, wait_result = true}, exec_lua[[
+ eq(
+ { time = true, wait_result = true },
+ exec_lua [[
start_time = get_time()
vim.defer_fn(function() vim.g.timer_result = true end, 100)
@@ -2620,94 +3214,124 @@ describe('lua stdlib', function()
time = (start_time + 5) > get_time(),
wait_result = wait_result,
}
- ]])
+ ]]
+ )
end)
it('should not crash when callback errors', function()
local result = exec_lua [[
return {pcall(function() vim.wait(1000, function() error("As Expected") end) end)}
]]
- eq({false, '[string "<nvim>"]:1: As Expected'}, {result[1], remove_trace(result[2])})
+ eq({ false, '[string "<nvim>"]:1: As Expected' }, { result[1], remove_trace(result[2]) })
end)
it('if callback is passed, it must be a function', function()
- eq({false, 'vim.wait: if passed, condition must be a function'}, exec_lua [[
+ eq(
+ { false, 'vim.wait: if passed, condition must be a function' },
+ exec_lua [[
return {pcall(function() vim.wait(1000, 13) end)}
- ]])
+ ]]
+ )
end)
it('should allow waiting with no callback, explicit', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
local start_time = vim.uv.hrtime()
vim.wait(50, nil)
return vim.uv.hrtime() - start_time > 25000
- ]])
+ ]]
+ )
end)
it('should allow waiting with no callback, implicit', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
local start_time = vim.uv.hrtime()
vim.wait(50)
return vim.uv.hrtime() - start_time > 25000
- ]])
+ ]]
+ )
end)
it('should call callbacks exactly once if they return true immediately', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
vim.g.wait_count = 0
vim.wait(1000, function()
vim.g.wait_count = vim.g.wait_count + 1
return true
end, 20)
return vim.g.wait_count == 1
- ]])
+ ]]
+ )
end)
it('should call callbacks few times with large `interval`', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
vim.g.wait_count = 0
vim.wait(50, function() vim.g.wait_count = vim.g.wait_count + 1 end, 200)
return vim.g.wait_count < 5
- ]])
+ ]]
+ )
end)
it('should play nice with `not` when fails', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
if not vim.wait(50, function() end) then
return true
end
return false
- ]])
+ ]]
+ )
end)
it('should play nice with `if` when success', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
if vim.wait(50, function() return true end) then
return true
end
return false
- ]])
+ ]]
+ )
end)
it('should return immediately with false if timeout is 0', function()
- eq({false, -1}, exec_lua [[
+ eq(
+ { false, -1 },
+ exec_lua [[
return {
vim.wait(0, function() return false end)
}
- ]])
+ ]]
+ )
end)
it('should work with tables with __call', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
local t = setmetatable({}, {__call = function(...) return true end})
return vim.wait(100, t, 10)
- ]])
+ ]]
+ )
end)
it('should work with tables with __call that change', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
local t = {count = 0}
setmetatable(t, {
__call = function()
@@ -2717,7 +3341,8 @@ describe('lua stdlib', function()
})
return vim.wait(1000, t, 10)
- ]])
+ ]]
+ )
end)
it('should not work with negative intervals', function()
@@ -2738,8 +3363,8 @@ describe('lua stdlib', function()
describe('returns -2 when interrupted', function()
before_each(function()
- local channel = meths.get_api_info()[1]
- meths.set_var('channel', channel)
+ local channel = api.nvim_get_chan_info(0).id
+ api.nvim_set_var('channel', channel)
end)
it('without callback', function()
@@ -2751,9 +3376,9 @@ describe('lua stdlib', function()
end
]])
feed(':lua _G.Wait()<CR>')
- eq({'notification', 'ready', {}}, next_msg(500))
+ eq({ 'notification', 'ready', {} }, next_msg(500))
feed('<C-C>')
- eq({'notification', 'wait', {-2}}, next_msg(500))
+ eq({ 'notification', 'wait', { -2 } }, next_msg(500))
end)
it('with callback', function()
@@ -2765,9 +3390,9 @@ describe('lua stdlib', function()
end
]])
feed(':lua _G.Wait()<CR>')
- eq({'notification', 'ready', {}}, next_msg(500))
+ eq({ 'notification', 'ready', {} }, next_msg(500))
feed('<C-C>')
- eq({'notification', 'wait', {-2}}, next_msg(500))
+ eq({ 'notification', 'wait', { -2 } }, next_msg(500))
end)
end)
@@ -2790,35 +3415,35 @@ describe('lua stdlib', function()
end)
it('vim.notify_once', function()
- local screen = Screen.new(60,5)
+ local screen = Screen.new(60, 5)
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {foreground=Screen.colors.Red},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { foreground = Screen.colors.Red },
})
screen:attach()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
- ]]}
+ ]],
+ }
exec_lua [[vim.notify_once("I'll only tell you this once...", vim.log.levels.WARN)]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{1:I'll only tell you this once...} |
- ]]}
+ ]],
+ }
feed('<C-l>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
- ]]}
+ ]],
+ }
exec_lua [[vim.notify_once("I'll only tell you this once...")]]
screen:expect_unchanged()
end)
@@ -2831,26 +3456,26 @@ describe('lua stdlib', function()
end)
fun("BOB", nil, "MIKE")
]]
- eq({'notification', 'mayday_mayday', {{a='BOB', c='MIKE'}}}, next_msg())
+ eq({ 'notification', 'mayday_mayday', { { a = 'BOB', c = 'MIKE' } } }, next_msg())
-- let's gooooo
exec_lua [[
vim.schedule_wrap(function(...) vim.rpcnotify(1, 'boogalo', select('#', ...)) end)(nil,nil,nil,nil)
]]
- eq({'notification', 'boogalo', {4}}, next_msg())
+ eq({ 'notification', 'boogalo', { 4 } }, next_msg())
end)
end)
describe('vim.api.nvim_buf_call', function()
it('can access buf options', function()
- local buf1 = meths.get_current_buf().id
+ local buf1 = api.nvim_get_current_buf()
local buf2 = exec_lua [[
buf2 = vim.api.nvim_create_buf(false, true)
return buf2
]]
- eq(false, meths.get_option_value('autoindent', {buf=buf1}))
- eq(false, meths.get_option_value('autoindent', {buf=buf2}))
+ eq(false, api.nvim_get_option_value('autoindent', { buf = buf1 }))
+ eq(false, api.nvim_get_option_value('autoindent', { buf = buf2 }))
local val = exec_lua [[
return vim.api.nvim_buf_call(buf2, function()
@@ -2859,9 +3484,9 @@ describe('lua stdlib', function()
end)
]]
- 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(false, api.nvim_get_option_value('autoindent', { buf = buf1 }))
+ eq(true, api.nvim_get_option_value('autoindent', { buf = buf2 }))
+ eq(buf1, api.nvim_get_current_buf())
eq(buf2, val)
end)
@@ -2877,7 +3502,9 @@ describe('lua stdlib', function()
end)
it('can be nested crazily with hidden buffers', function()
- eq(true, exec_lua([[
+ eq(
+ true,
+ exec_lua([[
local function scratch_buf_call(fn)
local buf = vim.api.nvim_create_buf(false, true)
vim.api.nvim_set_option_value('cindent', true, {buf = buf})
@@ -2913,14 +3540,27 @@ describe('lua stdlib', function()
end)
end)
end)
- ]]))
+ ]])
+ )
+ end)
+
+ it('can return values by reference', function()
+ eq(
+ { 4, 7 },
+ exec_lua [[
+ local val = {4, 10}
+ local ref = vim.api.nvim_buf_call(0, function() return val end)
+ ref[2] = 7
+ return val
+ ]]
+ )
end)
end)
describe('vim.api.nvim_win_call', function()
it('can access window options', function()
command('vsplit')
- local win1 = meths.get_current_win().id
+ local win1 = api.nvim_get_current_win()
command('wincmd w')
local win2 = exec_lua [[
win2 = vim.api.nvim_get_current_win()
@@ -2928,8 +3568,8 @@ describe('lua stdlib', function()
]]
command('wincmd p')
- eq('', meths.get_option_value('winhighlight', {win=win1}))
- eq('', meths.get_option_value('winhighlight', {win=win2}))
+ eq('', api.nvim_get_option_value('winhighlight', { win = win1 }))
+ eq('', api.nvim_get_option_value('winhighlight', { win = win2 }))
local val = exec_lua [[
return vim.api.nvim_win_call(win2, function()
@@ -2938,9 +3578,9 @@ describe('lua stdlib', function()
end)
]]
- 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('', api.nvim_get_option_value('winhighlight', { win = win1 }))
+ eq('Normal:Normal', api.nvim_get_option_value('winhighlight', { win = win2 }))
+ eq(win1, api.nvim_get_current_win())
eq(win2, val)
end)
@@ -2978,8 +3618,8 @@ describe('lua stdlib', function()
-- Fixed for win_execute in vim-patch:8.1.2124, but should've applied to nvim_win_call too!
local screen = Screen.new(30, 5)
screen:set_default_attr_ids {
- [1] = {reverse = true},
- [2] = {bold = true, reverse = true},
+ [1] = { reverse = true },
+ [2] = { bold = true, reverse = true },
}
screen:attach()
exec_lua [[
@@ -3012,75 +3652,110 @@ describe('lua stdlib', function()
|
]]
end)
+
+ it('can return values by reference', function()
+ eq(
+ { 7, 10 },
+ exec_lua [[
+ local val = {4, 10}
+ local ref = vim.api.nvim_win_call(0, function() return val end)
+ ref[1] = 7
+ return val
+ ]]
+ )
+ end)
end)
describe('vim.iconv', function()
it('can convert strings', function()
- eq('hello', exec_lua[[
+ eq(
+ 'hello',
+ exec_lua [[
return vim.iconv('hello', 'latin1', 'utf-8')
- ]])
+ ]]
+ )
end)
it('can validate arguments', function()
- eq({false, 'Expected at least 3 arguments'}, exec_lua[[
+ eq(
+ { false, 'Expected at least 3 arguments' },
+ exec_lua [[
return {pcall(vim.iconv, 'hello')}
- ]])
+ ]]
+ )
- eq({false, 'bad argument #3 to \'?\' (expected string)'}, exec_lua[[
+ eq(
+ { false, "bad argument #3 to '?' (expected string)" },
+ exec_lua [[
return {pcall(vim.iconv, 'hello', 'utf-8', true)}
- ]])
+ ]]
+ )
end)
it('can handle bad encodings', function()
- eq(NIL, exec_lua[[
+ eq(
+ NIL,
+ exec_lua [[
return vim.iconv('hello', 'foo', 'bar')
- ]])
+ ]]
+ )
end)
it('can handle strings with NUL bytes', function()
- eq(7, exec_lua[[
+ eq(
+ 7,
+ exec_lua [[
local a = string.char(97, 98, 99, 0, 100, 101, 102) -- abc\0def
return string.len(vim.iconv(a, 'latin1', 'utf-8'))
- ]])
+ ]]
+ )
end)
-
end)
- describe("vim.defaulttable", function()
- it("creates nested table by default", function()
- eq({ b = {c = 1 } }, exec_lua[[
+ describe('vim.defaulttable', function()
+ it('creates nested table by default', function()
+ eq(
+ { b = { c = 1 } },
+ exec_lua [[
local a = vim.defaulttable()
a.b.c = 1
return a
- ]])
+ ]]
+ )
end)
- it("allows to create default objects", function()
- eq({ b = 1 }, exec_lua[[
+ it('allows to create default objects', function()
+ eq(
+ { b = 1 },
+ exec_lua [[
local a = vim.defaulttable(function() return 0 end)
a.b = a.b + 1
return a
- ]])
+ ]]
+ )
end)
it('accepts the key name', function()
- eq({ b = 'b', c = 'c' }, exec_lua [[
+ eq(
+ { b = 'b', c = 'c' },
+ exec_lua [[
local a = vim.defaulttable(function(k) return k end)
local _ = a.b
local _ = a.c
return a
- ]])
+ ]]
+ )
end)
end)
it('vim.lua_omnifunc', function()
- local screen = Screen.new(60,5)
+ local screen = Screen.new(60, 5)
screen:set_default_attr_ids {
- [1] = {foreground = Screen.colors.Blue1, bold = true};
- [2] = {background = Screen.colors.WebGray};
- [3] = {background = Screen.colors.LightMagenta};
- [4] = {bold = true};
- [5] = {foreground = Screen.colors.SeaGreen, bold = true};
+ [1] = { foreground = Screen.colors.Blue1, bold = true },
+ [2] = { background = Screen.colors.WebGray },
+ [3] = { background = Screen.colors.LightMagenta },
+ [4] = { bold = true },
+ [5] = { foreground = Screen.colors.SeaGreen, bold = true },
}
screen:attach()
command [[ set omnifunc=v:lua.vim.lua_omnifunc ]]
@@ -3088,22 +3763,27 @@ describe('lua stdlib', function()
-- Note: the implementation is shared with lua command line completion.
-- More tests for completion in lua/command_line_completion_spec.lua
feed [[ivim.insp<c-x><c-o>]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
vim.inspect^ |
{1:~ }{2: inspect }{1: }|
{1:~ }{3: inspect_pos }{1: }|
{1:~ }|
{4:-- Omni completion (^O^N^P) }{5:match 1 of 2} |
- ]]}
+ ]],
+ }
end)
it('vim.print', function()
-- vim.print() returns its args.
- eq({42, 'abc', { a = { b = 77 }}},
- exec_lua[[return {vim.print(42, 'abc', { a = { b = 77 }})}]])
+ eq(
+ { 42, 'abc', { a = { b = 77 } } },
+ exec_lua [[return {vim.print(42, 'abc', { a = { b = 77 }})}]]
+ )
-- vim.print() pretty-prints the args.
- eq(dedent[[
+ eq(
+ dedent [[
42
abc
@@ -3112,12 +3792,14 @@ describe('lua stdlib', function()
b = 77
}
}]],
- eval[[execute('lua vim.print(42, "abc", { a = { b = 77 }})')]])
+ eval [[execute('lua vim.print(42, "abc", { a = { b = 77 }})')]]
+ )
end)
it('vim.F.if_nil', function()
local function if_nil(...)
- return exec_lua([[
+ return exec_lua(
+ [[
local args = {...}
local nargs = select('#', ...)
for i = 1, nargs do
@@ -3126,7 +3808,9 @@ describe('lua stdlib', function()
end
end
return vim.F.if_nil(unpack(args, 1, nargs))
- ]], ...)
+ ]],
+ ...
+ )
end
local a = NIL
@@ -3142,15 +3826,18 @@ describe('lua stdlib', function()
end)
it('lpeg', function()
- eq(5, exec_lua [[
+ eq(
+ 5,
+ exec_lua [[
local m = vim.lpeg
return m.match(m.R'09'^1, '4504ab')
- ]])
+ ]]
+ )
eq(4, exec_lua [[ return vim.re.match("abcde", '[a-c]+') ]])
end)
- it("vim.ringbuf", function()
+ it('vim.ringbuf', function()
local results = exec_lua([[
local ringbuf = vim.ringbuf(3)
ringbuf:push("a") -- idx: 0
@@ -3178,14 +3865,14 @@ describe('lua stdlib', function()
}
]])
local expected = {
- peeka1 = "a",
- peeka2 = "a",
- pop1 = "a",
+ peeka1 = 'a',
+ peeka2 = 'a',
+ pop1 = 'a',
pop2 = nil,
- pop3 = "b",
- pop4 = "c",
- pop5 = "d",
- pop_after_add_b = "a",
+ pop3 = 'b',
+ pop4 = 'c',
+ pop5 = 'd',
+ pop_after_add_b = 'a',
}
eq(expected, results)
end)
@@ -3193,8 +3880,8 @@ end)
describe('lua: builtin modules', function()
local function do_tests()
- eq(2, exec_lua[[return vim.tbl_count {x=1,y=2}]])
- eq('{ 10, "spam" }', exec_lua[[return vim.inspect {10, 'spam'}]])
+ eq(2, exec_lua [[return vim.tbl_count {x=1,y=2}]])
+ eq('{ 10, "spam" }', exec_lua [[return vim.inspect {10, 'spam'}]])
end
it('works', function()
@@ -3208,17 +3895,21 @@ describe('lua: builtin modules', function()
end)
it('works without runtime', function()
- clear{env={VIMRUNTIME='fixtures/a'}}
+ clear { env = { VIMRUNTIME = 'fixtures/a' } }
do_tests()
end)
-
it('fails when disabled without runtime', function()
clear()
command("let $VIMRUNTIME='fixtures/a'")
-- Use system([nvim,…]) instead of clear() to avoid stderr noise. #21844
- local out = funcs.system({nvim_prog, '--clean', '--luamod-dev',
- [[+call nvim_exec_lua('return vim.tbl_count {x=1,y=2}')]], '+qa!'}):gsub('\r\n', '\n')
+ local out = fn.system({
+ nvim_prog,
+ '--clean',
+ '--luamod-dev',
+ [[+call nvim_exec_lua('return vim.tbl_count {x=1,y=2}')]],
+ '+qa!',
+ }):gsub('\r\n', '\n')
eq(1, eval('v:shell_error'))
matches("'vim%.shared' not found", out)
end)
@@ -3235,7 +3926,7 @@ describe('lua: require("mod") from packages', function()
return err
]]
- matches("unexpected symbol", syntax_error_msg)
+ matches('unexpected symbol', syntax_error_msg)
end)
it('uses the right order of mod.lua vs mod/init.lua', function()
@@ -3252,15 +3943,18 @@ describe('vim.keymap', function()
before_each(clear)
it('can make a mapping', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
return GlobalCount
- ]])
+ ]]
+ )
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
end)
it('can make an expr mapping', function()
@@ -3270,19 +3964,22 @@ describe('vim.keymap', function()
feed('aa')
- eq({'Ï€<M-Ï€>foo<'}, meths.buf_get_lines(0, 0, -1, false))
+ eq({ 'Ï€<M-Ï€>foo<' }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
it('can overwrite a mapping', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
return GlobalCount
- ]])
+ ]]
+ )
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
exec_lua [[
vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount - 1 end)
@@ -3290,19 +3987,22 @@ describe('vim.keymap', function()
feed('asdf\n')
- eq(0, exec_lua[[return GlobalCount]])
+ eq(0, exec_lua [[return GlobalCount]])
end)
it('can unmap a mapping', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end)
return GlobalCount
- ]])
+ ]]
+ )
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
exec_lua [[
vim.keymap.del('n', 'asdf')
@@ -3310,20 +4010,23 @@ describe('vim.keymap', function()
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
end)
it('works with buffer-local mappings', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.keymap.set('n', 'asdf', function() GlobalCount = GlobalCount + 1 end, {buffer=true})
return GlobalCount
- ]])
+ ]]
+ )
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
exec_lua [[
vim.keymap.del('n', 'asdf', {buffer=true})
@@ -3331,33 +4034,63 @@ describe('vim.keymap', function()
feed('asdf\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
eq('\nNo mapping found', helpers.exec_capture('nmap asdf'))
end)
it('does not mutate the opts parameter', function()
- eq(true, exec_lua [[
+ eq(
+ true,
+ exec_lua [[
opts = {buffer=true}
vim.keymap.set('n', 'asdf', function() end, opts)
return opts.buffer
- ]])
- eq(true, exec_lua [[
+ ]]
+ )
+ eq(
+ true,
+ exec_lua [[
vim.keymap.del('n', 'asdf', opts)
return opts.buffer
- ]])
+ ]]
+ )
end)
it('can do <Plug> mappings', function()
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
GlobalCount = 0
vim.keymap.set('n', '<plug>(asdf)', function() GlobalCount = GlobalCount + 1 end)
vim.keymap.set('n', 'ww', '<plug>(asdf)')
return GlobalCount
- ]])
+ ]]
+ )
feed('ww\n')
- eq(1, exec_lua[[return GlobalCount]])
+ eq(1, exec_lua [[return GlobalCount]])
end)
+end)
+describe('Vimscript function exists()', function()
+ it('can check a lua function', function()
+ eq(
+ 1,
+ exec_lua [[
+ _G.test = function() print("hello") end
+ return vim.fn.exists('*v:lua.test')
+ ]]
+ )
+
+ eq(1, fn.exists('*v:lua.require("mpack").decode'))
+ eq(1, fn.exists("*v:lua.require('mpack').decode"))
+ eq(1, fn.exists('*v:lua.require"mpack".decode'))
+ eq(1, fn.exists("*v:lua.require'mpack'.decode"))
+ eq(1, fn.exists("*v:lua.require('vim.lsp').start"))
+ eq(1, fn.exists('*v:lua.require"vim.lsp".start'))
+ eq(1, fn.exists("*v:lua.require'vim.lsp'.start"))
+ eq(0, fn.exists("*v:lua.require'vim.lsp'.unknown"))
+ eq(0, fn.exists('*v:lua.?'))
+ end)
end)
diff --git a/test/functional/lua/watch_spec.lua b/test/functional/lua/watch_spec.lua
index cdcef08a1a..115fee8091 100644
--- a/test/functional/lua/watch_spec.lua
+++ b/test/functional/lua/watch_spec.lua
@@ -2,72 +2,113 @@ local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local exec_lua = helpers.exec_lua
local clear = helpers.clear
+local is_ci = helpers.is_ci
local is_os = helpers.is_os
local skip = helpers.skip
+-- Create a file via a rename to avoid multiple
+-- events which can happen with some backends on some platforms
+local function touch(path)
+ local tmp = helpers.tmpname()
+ io.open(tmp, 'w'):close()
+ assert(vim.uv.fs_rename(tmp, path))
+end
+
describe('vim._watch', function()
before_each(function()
clear()
end)
- describe('watch', function()
- it('detects file changes', function()
- skip(is_os('bsd'), "Stopped working on bsd after 3ca967387c49c754561c3b11a574797504d40f38")
- local root_dir = vim.uv.fs_mkdtemp(vim.fs.dirname(helpers.tmpname()) .. '/nvim_XXXXXXXXXX')
+ local function run(watchfunc)
+ it('detects file changes (watchfunc=' .. watchfunc .. '())', function()
+ if watchfunc == 'fswatch' then
+ skip(is_os('mac'), 'flaky test on mac')
+ skip(
+ not is_ci() and helpers.fn.executable('fswatch') == 0,
+ 'fswatch not installed and not on CI'
+ )
+ skip(is_os('win'), 'not supported on windows')
+ end
- local result = exec_lua(
- [[
- local root_dir = ...
+ if watchfunc == 'watch' then
+ skip(is_os('bsd'), 'Stopped working on bsd after 3ca967387c49c754561c3b11a574797504d40f38')
+ else
+ skip(
+ is_os('bsd'),
+ 'kqueue only reports events on watched folder itself, not contained files #26110'
+ )
+ end
+
+ local root_dir = vim.uv.fs_mkdtemp(vim.fs.dirname(helpers.tmpname()) .. '/nvim_XXXXXXXXXX')
- local events = {}
+ local expected_events = 0
- local expected_events = 0
- local function wait_for_events()
- assert(vim.wait(100, function() return #events == expected_events end), 'Timed out waiting for expected number of events. Current events seen so far: ' .. vim.inspect(events))
- end
+ local function wait_for_event()
+ expected_events = expected_events + 1
+ exec_lua(
+ [[
+ local expected_events = ...
+ assert(
+ vim.wait(3000, function()
+ return #_G.events == expected_events
+ end),
+ string.format(
+ 'Timed out waiting for expected event no. %d. Current events seen so far: %s',
+ expected_events,
+ vim.inspect(events)
+ )
+ )
+ ]],
+ expected_events
+ )
+ end
- local stop = vim._watch.watch(root_dir, {}, function(path, change_type)
- table.insert(events, { path = path, change_type = change_type })
- end)
+ local unwatched_path = root_dir .. '/file.unwatched'
+ local watched_path = root_dir .. '/file'
- -- Only BSD seems to need some extra time for the watch to be ready to respond to events
- if vim.fn.has('bsd') then
- vim.wait(50)
- end
+ exec_lua(
+ [[
+ local root_dir, watchfunc = ...
- local watched_path = root_dir .. '/file'
- local watched, err = io.open(watched_path, 'w')
- assert(not err, err)
+ _G.events = {}
- expected_events = expected_events + 1
- wait_for_events()
+ _G.stop_watch = vim._watch[watchfunc](root_dir, {
+ debounce = 100,
+ include_pattern = vim.lpeg.P(root_dir) * vim.lpeg.P("/file") ^ -1,
+ exclude_pattern = vim.lpeg.P(root_dir .. '/file.unwatched'),
+ }, function(path, change_type)
+ table.insert(_G.events, { path = path, change_type = change_type })
+ end)
+ ]],
+ root_dir,
+ watchfunc
+ )
- watched:close()
- os.remove(watched_path)
+ if watchfunc ~= 'watch' then
+ vim.uv.sleep(200)
+ end
- expected_events = expected_events + 1
- wait_for_events()
+ touch(watched_path)
+ touch(unwatched_path)
- stop()
- -- No events should come through anymore
+ wait_for_event()
- local watched_path = root_dir .. '/file'
- local watched, err = io.open(watched_path, 'w')
- assert(not err, err)
+ os.remove(watched_path)
+ os.remove(unwatched_path)
- vim.wait(50)
+ wait_for_event()
- watched:close()
- os.remove(watched_path)
+ exec_lua [[_G.stop_watch()]]
- vim.wait(50)
+ -- No events should come through anymore
- return events
- ]],
- root_dir
- )
+ vim.uv.sleep(100)
+ touch(watched_path)
+ vim.uv.sleep(100)
+ os.remove(watched_path)
+ vim.uv.sleep(100)
- local expected = {
+ eq({
{
change_type = exec_lua([[return vim._watch.FileChangeType.Created]]),
path = root_dir .. '/file',
@@ -76,103 +117,11 @@ describe('vim._watch', function()
change_type = exec_lua([[return vim._watch.FileChangeType.Deleted]]),
path = root_dir .. '/file',
},
- }
-
- -- kqueue only reports events on the watched path itself, so creating a file within a
- -- watched directory results in a "rename" libuv event on the directory.
- if is_os('bsd') then
- expected = {
- {
- change_type = exec_lua([[return vim._watch.FileChangeType.Created]]),
- path = root_dir,
- },
- {
- change_type = exec_lua([[return vim._watch.FileChangeType.Created]]),
- path = root_dir,
- },
- }
- end
-
- eq(expected, result)
+ }, exec_lua [[return _G.events]])
end)
- end)
+ end
- describe('poll', function()
- it('detects file changes', function()
- skip(is_os('bsd'), "bsd only reports rename on folders if file inside change")
- local root_dir = vim.uv.fs_mkdtemp(vim.fs.dirname(helpers.tmpname()) .. '/nvim_XXXXXXXXXX')
-
- local result = exec_lua(
- [[
- local root_dir = ...
- local lpeg = vim.lpeg
-
- local events = {}
-
- local debounce = 100
- local wait_ms = debounce + 200
-
- local expected_events = 0
- local function wait_for_events()
- assert(vim.wait(wait_ms, function() return #events == expected_events end), 'Timed out waiting for expected number of events. Current events seen so far: ' .. vim.inspect(events))
- end
-
- local incl = lpeg.P(root_dir) * lpeg.P("/file")^-1
- local excl = lpeg.P(root_dir..'/file.unwatched')
- local stop = vim._watch.poll(root_dir, {
- debounce = debounce,
- include_pattern = incl,
- exclude_pattern = excl,
- }, function(path, change_type)
- table.insert(events, { path = path, change_type = change_type })
- end)
-
- local watched_path = root_dir .. '/file'
- local watched, err = io.open(watched_path, 'w')
- assert(not err, err)
- local unwatched_path = root_dir .. '/file.unwatched'
- local unwatched, err = io.open(unwatched_path, 'w')
- assert(not err, err)
-
- expected_events = expected_events + 1
- wait_for_events()
-
- watched:close()
- os.remove(watched_path)
- unwatched:close()
- os.remove(unwatched_path)
-
- expected_events = expected_events + 1
- wait_for_events()
-
- stop()
- -- No events should come through anymore
-
- local watched_path = root_dir .. '/file'
- local watched, err = io.open(watched_path, 'w')
- assert(not err, err)
-
- watched:close()
- os.remove(watched_path)
-
- return events
- ]],
- root_dir
- )
-
- local created = exec_lua([[return vim._watch.FileChangeType.Created]])
- local deleted = exec_lua([[return vim._watch.FileChangeType.Deleted]])
- local expected = {
- {
- change_type = created,
- path = root_dir .. "/file",
- },
- {
- change_type = deleted,
- path = root_dir .. "/file",
- }
- }
- eq(expected, result)
- end)
- end)
+ run('watch')
+ run('watchdirs')
+ run('fswatch')
end)
diff --git a/test/functional/lua/xdiff_spec.lua b/test/functional/lua/xdiff_spec.lua
index 3121ac051f..c21309c2e4 100644
--- a/test/functional/lua/xdiff_spec.lua
+++ b/test/functional/lua/xdiff_spec.lua
@@ -11,7 +11,7 @@ describe('xdiff bindings', function()
describe('can diff text', function()
before_each(function()
- exec_lua[[
+ exec_lua [[
a1 = 'Hello\n'
b1 = 'Helli\n'
@@ -21,15 +21,14 @@ describe('xdiff bindings', function()
end)
it('with no callback', function()
-
eq(
table.concat({
'@@ -1 +1 @@',
'-Hello',
'+Helli',
- ''
+ '',
}, '\n'),
- exec_lua("return vim.diff(a1, b1)")
+ exec_lua('return vim.diff(a1, b1)')
)
eq(
@@ -41,11 +40,10 @@ describe('xdiff bindings', function()
'-foo',
'+bar',
'+baz',
- ''
+ '',
}, '\n'),
- exec_lua("return vim.diff(a2, b2)")
+ exec_lua('return vim.diff(a2, b2)')
)
-
end)
it('with callback', function()
@@ -53,43 +51,55 @@ describe('xdiff bindings', function()
exp[#exp+1] = {sa, ca, sb, cb}
end]])
- eq({{1, 1, 1, 1}}, exec_lua[[
+ eq(
+ { { 1, 1, 1, 1 } },
+ exec_lua [[
exp = {}
assert(vim.diff(a1, b1, {on_hunk = on_hunk}) == nil)
return exp
- ]])
+ ]]
+ )
- eq({{1, 1, 1, 1}, {3, 1, 3, 2}}, exec_lua[[
+ eq(
+ { { 1, 1, 1, 1 }, { 3, 1, 3, 2 } },
+ exec_lua [[
exp = {}
assert(vim.diff(a2, b2, {on_hunk = on_hunk}) == nil)
return exp
- ]])
+ ]]
+ )
-- gives higher precedence to on_hunk over result_type
- eq({{1, 1, 1, 1}, {3, 1, 3, 2}}, exec_lua[[
+ eq(
+ { { 1, 1, 1, 1 }, { 3, 1, 3, 2 } },
+ exec_lua [[
exp = {}
assert(vim.diff(a2, b2, {on_hunk = on_hunk, result_type='indices'}) == nil)
return exp
- ]])
+ ]]
+ )
end)
it('with error callback', function()
- exec_lua[[
+ exec_lua [[
on_hunk = function(sa, ca, sb, cb)
error('ERROR1')
end
]]
- eq([[error running function on_hunk: [string "<nvim>"]:0: ERROR1]],
- pcall_err(exec_lua, [[vim.diff(a1, b1, {on_hunk = on_hunk})]]))
+ eq(
+ [[error running function on_hunk: [string "<nvim>"]:0: ERROR1]],
+ pcall_err(exec_lua, [[vim.diff(a1, b1, {on_hunk = on_hunk})]])
+ )
end)
it('with hunk_lines', function()
- eq({{1, 1, 1, 1}},
- exec_lua([[return vim.diff(a1, b1, {result_type = 'indices'})]]))
+ eq({ { 1, 1, 1, 1 } }, exec_lua([[return vim.diff(a1, b1, {result_type = 'indices'})]]))
- eq({{1, 1, 1, 1}, {3, 1, 3, 2}},
- exec_lua([[return vim.diff(a2, b2, {result_type = 'indices'})]]))
+ eq(
+ { { 1, 1, 1, 1 }, { 3, 1, 3, 2 } },
+ exec_lua([[return vim.diff(a2, b2, {result_type = 'indices'})]])
+ )
end)
it('can run different algorithms', function()
@@ -101,7 +111,8 @@ describe('xdiff bindings', function()
'.bar {',
' margin: 0;',
'}',
- ''}, '\n')
+ '',
+ }, '\n')
local b = table.concat({
'.bar {',
@@ -112,10 +123,12 @@ describe('xdiff bindings', function()
' margin: 0;',
' color: green;',
'}',
- ''}, '\n')
+ '',
+ }, '\n')
eq(
- table.concat({'@@ -1,4 +0,0 @@',
+ table.concat({
+ '@@ -1,4 +0,0 @@',
'-.foo1 {',
'- margin: 0;',
'-}',
@@ -126,31 +139,37 @@ describe('xdiff bindings', function()
'+ margin: 0;',
'+ color: green;',
'+}',
- ''}, '\n'),
- exec_lua([[
+ '',
+ }, '\n'),
+ exec_lua(
+ [[
local args = {...}
return vim.diff(args[1], args[2], {
algorithm = 'patience'
})
- ]], a, b))
+ ]],
+ a,
+ b
+ )
+ )
end)
end)
it('can handle bad args', function()
- eq([[Expected at least 2 arguments]],
- pcall_err(exec_lua, [[vim.diff('a')]]))
-
- eq([[bad argument #1 to 'diff' (expected string)]],
- pcall_err(exec_lua, [[vim.diff(1, 2)]]))
+ eq([[Expected at least 2 arguments]], pcall_err(exec_lua, [[vim.diff('a')]]))
- eq([[bad argument #3 to 'diff' (expected table)]],
- pcall_err(exec_lua, [[vim.diff('a', 'b', true)]]))
+ eq([[bad argument #1 to 'diff' (expected string)]], pcall_err(exec_lua, [[vim.diff(1, 2)]]))
- eq([[unexpected key: bad_key]],
- pcall_err(exec_lua, [[vim.diff('a', 'b', { bad_key = true })]]))
+ eq(
+ [[bad argument #3 to 'diff' (expected table)]],
+ pcall_err(exec_lua, [[vim.diff('a', 'b', true)]])
+ )
- eq([[on_hunk is not a function]],
- pcall_err(exec_lua, [[vim.diff('a', 'b', { on_hunk = true })]]))
+ eq([[invalid key: bad_key]], pcall_err(exec_lua, [[vim.diff('a', 'b', { bad_key = true })]]))
+ eq(
+ [[on_hunk is not a function]],
+ pcall_err(exec_lua, [[vim.diff('a', 'b', { on_hunk = true })]])
+ )
end)
end)
diff --git a/test/functional/options/autochdir_spec.lua b/test/functional/options/autochdir_spec.lua
index c75a98f35b..11f71912a9 100644
--- a/test/functional/options/autochdir_spec.lua
+++ b/test/functional/options/autochdir_spec.lua
@@ -1,8 +1,7 @@
-local luv = require('luv')
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
-local funcs = helpers.funcs
+local fn = helpers.fn
local command = helpers.command
local mkdir = helpers.mkdir
@@ -11,34 +10,34 @@ describe("'autochdir'", function()
local targetdir = 'test/functional/fixtures'
-- By default 'autochdir' is off, thus getcwd() returns the repo root.
- clear(targetdir..'/tty-test.c')
- local rootdir = funcs.getcwd()
+ clear(targetdir .. '/tty-test.c')
+ local rootdir = fn.getcwd()
local expected = rootdir .. '/' .. targetdir
-- With 'autochdir' on, we should get the directory of tty-test.c.
- clear('--cmd', 'set autochdir', targetdir..'/tty-test.c')
- eq(helpers.is_os('win') and expected:gsub('/', '\\') or expected, funcs.getcwd())
+ clear('--cmd', 'set autochdir', targetdir .. '/tty-test.c')
+ eq(helpers.is_os('win') and expected:gsub('/', '\\') or expected, fn.getcwd())
end)
- it('is not overwritten by getwinvar() call #17609',function()
- local curdir = string.gsub(luv.cwd(), '\\', '/')
- local dir_a = curdir..'/Xtest-functional-options-autochdir.dir_a'
- local dir_b = curdir..'/Xtest-functional-options-autochdir.dir_b'
+ it('is not overwritten by getwinvar() call #17609', function()
+ local curdir = vim.uv.cwd():gsub('\\', '/')
+ local dir_a = curdir .. '/Xtest-functional-options-autochdir.dir_a'
+ local dir_b = curdir .. '/Xtest-functional-options-autochdir.dir_b'
mkdir(dir_a)
mkdir(dir_b)
clear()
command('set shellslash')
command('set autochdir')
- command('edit '..dir_a..'/file1')
- eq(dir_a, funcs.getcwd())
- command('lcd '..dir_b)
- eq(dir_b, funcs.getcwd())
+ command('edit ' .. dir_a .. '/file1')
+ eq(dir_a, fn.getcwd())
+ command('lcd ' .. dir_b)
+ eq(dir_b, fn.getcwd())
command('botright vnew ../file2')
- eq(curdir, funcs.getcwd())
+ eq(curdir, fn.getcwd())
command('wincmd w')
- eq(dir_a, funcs.getcwd())
- funcs.getwinvar(2, 'foo')
- eq(dir_a, funcs.getcwd())
+ eq(dir_a, fn.getcwd())
+ fn.getwinvar(2, 'foo')
+ eq(dir_a, fn.getcwd())
helpers.rmdir(dir_a)
helpers.rmdir(dir_b)
end)
diff --git a/test/functional/options/chars_spec.lua b/test/functional/options/chars_spec.lua
index a082204980..e9c20b5da9 100644
--- a/test/functional/options/chars_spec.lua
+++ b/test/functional/options/chars_spec.lua
@@ -1,11 +1,12 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, command = helpers.clear, helpers.command
+local pcall_err = helpers.pcall_err
local eval = helpers.eval
local eq = helpers.eq
-local exc_exec = helpers.exc_exec
local insert = helpers.insert
local feed = helpers.feed
+local api = helpers.api
describe("'fillchars'", function()
local screen
@@ -16,91 +17,124 @@ describe("'fillchars'", function()
screen:attach()
end)
- local function shouldfail(val,errval)
- errval = errval or val
- eq('Vim(set):E474: Invalid argument: fillchars='..errval,
- exc_exec('set fillchars='..val))
- end
-
describe('"eob" flag', function()
it("uses '~' by default", function()
eq('', eval('&fillchars'))
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
]])
end)
+
it('supports whitespace', function()
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
]])
command('set fillchars=eob:\\ ')
screen:expect([[
^ |
- |
- |
- |
- |
+ |*4
]])
end)
+
it('supports multibyte char', function()
command('set fillchars=eob:ñ')
screen:expect([[
^ |
- ñ |
- ñ |
- ñ |
+ ñ |*3
|
]])
end)
+
+ it('supports composing multibyte char', function()
+ command('set fillchars=eob:å̲')
+ screen:expect([[
+ ^ |
+ å̲ |*3
+ |
+ ]])
+ end)
+
it('handles invalid values', function()
- shouldfail('eob:') -- empty string
- shouldfail('eob:馬') -- doublewidth char
- shouldfail('eob:å̲') -- composing chars
- shouldfail('eob:xy') -- two ascii chars
- shouldfail('eob:\255', 'eob:<ff>') -- invalid UTF-8
+ eq(
+ 'Vim(set):E1511: Wrong number of characters for field "eob": fillchars=eob:',
+ pcall_err(command, 'set fillchars=eob:') -- empty string
+ )
+ eq(
+ 'Vim(set):E1512: Wrong character width for field "eob": fillchars=eob:馬',
+ pcall_err(command, 'set fillchars=eob:馬') -- doublewidth char
+ )
+ eq(
+ 'Vim(set):E1511: Wrong number of characters for field "eob": fillchars=eob:xy',
+ pcall_err(command, 'set fillchars=eob:xy') -- two ascii chars
+ )
+ eq(
+ 'Vim(set):E1512: Wrong character width for field "eob": fillchars=eob:<ff>',
+ pcall_err(command, 'set fillchars=eob:\255') -- invalid UTF-8
+ )
end)
end)
+
+ it('"diff" flag', function()
+ screen:try_resize(45, 8)
+ screen:set_default_attr_ids({
+ [1] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue },
+ [2] = { background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { background = Screen.colors.LightBlue },
+ [4] = { reverse = true },
+ [5] = { reverse = true, bold = true },
+ })
+ command('set fillchars=diff:…')
+ insert('a\nb\nc\nd\ne')
+ command('vnew')
+ insert('a\nd\ne\nf')
+ command('windo diffthis')
+ screen:expect([[
+ {1: }a │{1: }a |
+ {1: }{2:……………………………………………………}│{1: }{3:b }|
+ {1: }{2:……………………………………………………}│{1: }{3:c }|
+ {1: }d │{1: }d |
+ {1: }e │{1: }^e |
+ {1: }{3:f }│{1: }{2:……………………………………………………}|
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ |
+ ]])
+ end)
+
it('has global value', function()
screen:try_resize(50, 5)
- insert("foo\nbar")
+ insert('foo\nbar')
command('set laststatus=0')
command('1,2fold')
command('vsplit')
command('set fillchars=fold:x')
screen:expect([[
^+-- 2 lines: fooxxxxxxxx│+-- 2 lines: fooxxxxxxx|
- ~ │~ |
- ~ │~ |
- ~ │~ |
+ ~ │~ |*3
|
]])
end)
+
it('has window-local value', function()
screen:try_resize(50, 5)
- insert("foo\nbar")
+ insert('foo\nbar')
command('set laststatus=0')
command('1,2fold')
command('vsplit')
command('setl fillchars=fold:x')
screen:expect([[
^+-- 2 lines: fooxxxxxxxx│+-- 2 lines: foo·······|
- ~ │~ |
- ~ │~ |
- ~ │~ |
+ ~ │~ |*3
|
]])
end)
+
it('using :set clears window-local value', function()
screen:try_resize(50, 5)
- insert("foo\nbar")
+ insert('foo\nbar')
command('set laststatus=0')
command('setl fillchars=fold:x')
command('1,2fold')
@@ -108,9 +142,7 @@ describe("'fillchars'", function()
command('set fillchars&')
screen:expect([[
^+-- 2 lines: foo········│+-- 2 lines: fooxxxxxxx|
- ~ │~ |
- ~ │~ |
- ~ │~ |
+ ~ │~ |*3
|
]])
end)
@@ -132,12 +164,11 @@ describe("'listchars'", function()
command('set listchars=tab:<->')
screen:expect([[
<------><------>^<------> │<------><------><------>|
- ~ │~ |
- ~ │~ |
- ~ │~ |
+ ~ │~ |*3
|
]])
end)
+
it('has window-local value', function()
feed('i<tab><tab><tab><esc>')
command('set list laststatus=0')
@@ -146,12 +177,11 @@ describe("'listchars'", function()
command('setl listchars<')
screen:expect([[
> > ^> │<------><------><------>|
- ~ │~ |
- ~ │~ |
- ~ │~ |
+ ~ │~ |*3
|
]])
end)
+
it('using :set clears window-local value', function()
feed('i<tab><tab><tab><esc>')
command('set list laststatus=0')
@@ -160,9 +190,31 @@ describe("'listchars'", function()
command('set listchars=tab:>-,eol:$')
screen:expect([[
>------->-------^>-------$│<------><------><------>|
- ~ │~ |
- ~ │~ |
- ~ │~ |
+ ~ │~ |*3
+ |
+ ]])
+ end)
+
+ it('supports composing chars', function()
+ screen:set_default_attr_ids {
+ [1] = { foreground = Screen.colors.Blue1, bold = true },
+ }
+ feed('i<tab><tab><tab>x<esc>')
+ command('set list laststatus=0')
+ -- tricky: the tab value forms three separate one-cell chars,
+ -- thus it should be accepted despite being a mess.
+ command('set listchars=tab:d̞̄̃̒̉̎oÌ€Ì̌̌̂Ìl̞̀̄̆̌̚,eol:å̲')
+ screen:expect([[
+ {1:d̞̄̃̒̉̎oÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂Ìl̞̀̄̆̌̚d̞̄̃̒̉̎oÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂Ìl̞̀̄̆̌̚d̞̄̃̒̉̎oÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂Ìl̞̀̄̆̌̚}^x{1:å̲} |
+ {1:~ }|*3
+ |
+ ]])
+
+ api.nvim__invalidate_glyph_cache()
+ screen:_reset()
+ screen:expect([[
+ {1:d̞̄̃̒̉̎oÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂Ìl̞̀̄̆̌̚d̞̄̃̒̉̎oÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂Ìl̞̀̄̆̌̚d̞̄̃̒̉̎oÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂ÌoÌ€Ì̌̌̂Ìl̞̀̄̆̌̚}^x{1:å̲} |
+ {1:~ }|*3
|
]])
end)
diff --git a/test/functional/options/cursorbind_spec.lua b/test/functional/options/cursorbind_spec.lua
index 498206936a..cafdc83de2 100644
--- a/test/functional/options/cursorbind_spec.lua
+++ b/test/functional/options/cursorbind_spec.lua
@@ -12,10 +12,10 @@ describe("'cursorbind'", function()
it("behaves consistently whether 'cursorline' is set or not vim-patch:8.2.4795", function()
local screen = Screen.new(60, 8)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {bold = true, reverse = true}, -- StatusLine
- [3] = {reverse = true}, -- StatusLineNC
- [4] = {background = Screen.colors.Grey90}, -- CursorLine, CursorColumn
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { bold = true, reverse = true }, -- StatusLine
+ [3] = { reverse = true }, -- StatusLineNC
+ [4] = { background = Screen.colors.Grey90 }, -- CursorLine, CursorColumn
})
screen:attach()
exec([[
@@ -32,10 +32,7 @@ describe("'cursorbind'", function()
feed('20l')
screen:expect([[
a bb cc dd ee ff gg │aa bb cc dd ee ff gg^ hh ii jj kk ll mm |
- {4: }│ {4: } |
- {4: }│ {4: } |
- {4: }│ {4: } |
- {4: }│ {4: } |
+ {4: }│ {4: } |*4
{1:~ }│{1:~ }|
{3:[No Name] [+] }{2:[No Name] [+] }|
|
@@ -43,10 +40,7 @@ describe("'cursorbind'", function()
feed('10l')
screen:expect([[
hh ii jj kk ll mm n│aa bb cc dd ee ff gg hh ii jj ^kk ll mm |
- {4: } │ {4: } |
- {4: } │ {4: } |
- {4: } │ {4: } |
- {4: } │ {4: } |
+ {4: } │ {4: } |*4
{1:~ }│{1:~ }|
{3:[No Name] [+] }{2:[No Name] [+] }|
|
@@ -56,10 +50,7 @@ describe("'cursorbind'", function()
feed('20l')
screen:expect([[
{4:a bb cc dd ee ff gg }│{4:aa bb cc dd ee ff gg^ hh ii jj kk ll mm }|
- {4: }│ {4: } |
- {4: }│ {4: } |
- {4: }│ {4: } |
- {4: }│ {4: } |
+ {4: }│ {4: } |*4
{1:~ }│{1:~ }|
{3:[No Name] [+] }{2:[No Name] [+] }|
|
@@ -67,10 +58,7 @@ describe("'cursorbind'", function()
feed('10l')
screen:expect([[
{4: hh ii jj kk ll mm n}│{4:aa bb cc dd ee ff gg hh ii jj ^kk ll mm }|
- {4: } │ {4: } |
- {4: } │ {4: } |
- {4: } │ {4: } |
- {4: } │ {4: } |
+ {4: } │ {4: } |*4
{1:~ }│{1:~ }|
{3:[No Name] [+] }{2:[No Name] [+] }|
|
@@ -80,10 +68,7 @@ describe("'cursorbind'", function()
feed('40l')
screen:expect([[
kk ll mm nn oo pp qq│ bb cc dd ee ff gg hh ii jj kk ll mm n^n|
- │ |
- │ |
- │ |
- │ |
+ │ |*4
{1:~ }│{1:~ }|
{3:[No Name] [+] }{2:[No Name] [+] }|
|
diff --git a/test/functional/options/defaults_spec.lua b/test/functional/options/defaults_spec.lua
index 7858b626de..d27fa375ee 100644
--- a/test/functional/options/defaults_spec.lua
+++ b/test/functional/options/defaults_spec.lua
@@ -4,7 +4,7 @@ local Screen = require('test.functional.ui.screen')
local assert_alive = helpers.assert_alive
local assert_log = helpers.assert_log
-local meths = helpers.meths
+local api = helpers.api
local command = helpers.command
local clear = helpers.clear
local exc_exec = helpers.exc_exec
@@ -12,13 +12,13 @@ local exec_lua = helpers.exec_lua
local eval = helpers.eval
local eq = helpers.eq
local ok = helpers.ok
-local funcs = helpers.funcs
+local fn = helpers.fn
local insert = helpers.insert
local neq = helpers.neq
local mkdir = helpers.mkdir
local rmdir = helpers.rmdir
local alter_slashes = helpers.alter_slashes
-local tbl_contains = helpers.tbl_contains
+local tbl_contains = vim.tbl_contains
local expect_exit = helpers.expect_exit
local is_os = helpers.is_os
@@ -32,51 +32,39 @@ describe('startup defaults', function()
command('filetype')
screen:expect([[
^ |
- ~ |
- ~ |
- ]]..expected
- )
+ ~ |*2
+ ]] .. expected)
end
it('all ON after `-u NORC`', function()
clear('-u', 'NORC')
- expect_filetype(
- 'filetype detection:ON plugin:ON indent:ON |')
+ expect_filetype('filetype detection:ON plugin:ON indent:ON |')
end)
it('all ON after `:syntax …` #7765', function()
clear('-u', 'NORC', '--cmd', 'syntax on')
- expect_filetype(
- 'filetype detection:ON plugin:ON indent:ON |')
+ expect_filetype('filetype detection:ON plugin:ON indent:ON |')
clear('-u', 'NORC', '--cmd', 'syntax off')
- expect_filetype(
- 'filetype detection:ON plugin:ON indent:ON |')
+ expect_filetype('filetype detection:ON plugin:ON indent:ON |')
end)
it('all OFF after `-u NONE`', function()
clear('-u', 'NONE')
- expect_filetype(
- 'filetype detection:OFF plugin:OFF indent:OFF |')
+ expect_filetype('filetype detection:OFF plugin:OFF indent:OFF |')
end)
it('explicit OFF stays OFF', function()
- clear('-u', 'NORC', '--cmd',
- 'syntax off | filetype off | filetype plugin indent off')
- expect_filetype(
- 'filetype detection:OFF plugin:OFF indent:OFF |')
+ clear('-u', 'NORC', '--cmd', 'syntax off | filetype off | filetype plugin indent off')
+ expect_filetype('filetype detection:OFF plugin:OFF indent:OFF |')
clear('-u', 'NORC', '--cmd', 'syntax off | filetype plugin indent off')
- expect_filetype(
- 'filetype detection:ON plugin:OFF indent:OFF |')
+ expect_filetype('filetype detection:ON plugin:OFF indent:OFF |')
clear('-u', 'NORC', '--cmd', 'filetype indent off')
- expect_filetype(
- 'filetype detection:ON plugin:ON indent:OFF |')
+ expect_filetype('filetype detection:ON plugin:ON indent:OFF |')
clear('-u', 'NORC', '--cmd', 'syntax off | filetype off')
- expect_filetype(
- 'filetype detection:OFF plugin:(on) indent:(on) |')
+ expect_filetype('filetype detection:OFF plugin:(on) indent:(on) |')
-- Swap the order.
clear('-u', 'NORC', '--cmd', 'filetype off | syntax off')
- expect_filetype(
- 'filetype detection:OFF plugin:(on) indent:(on) |')
+ expect_filetype('filetype detection:OFF plugin:(on) indent:(on) |')
end)
it('all ON after early `:filetype … on`', function()
@@ -84,26 +72,20 @@ describe('startup defaults', function()
-- Only an explicit `:filetype … off` sets OFF.
clear('-u', 'NORC', '--cmd', 'filetype on')
- expect_filetype(
- 'filetype detection:ON plugin:ON indent:ON |')
+ expect_filetype('filetype detection:ON plugin:ON indent:ON |')
clear('-u', 'NORC', '--cmd', 'filetype plugin on')
- expect_filetype(
- 'filetype detection:ON plugin:ON indent:ON |')
+ expect_filetype('filetype detection:ON plugin:ON indent:ON |')
clear('-u', 'NORC', '--cmd', 'filetype indent on')
- expect_filetype(
- 'filetype detection:ON plugin:ON indent:ON |')
+ expect_filetype('filetype detection:ON plugin:ON indent:ON |')
end)
it('late `:filetype … off` stays OFF', function()
clear('-u', 'NORC', '-c', 'filetype off')
- expect_filetype(
- 'filetype detection:OFF plugin:(on) indent:(on) |')
+ expect_filetype('filetype detection:OFF plugin:(on) indent:(on) |')
clear('-u', 'NORC', '-c', 'filetype plugin off')
- expect_filetype(
- 'filetype detection:ON plugin:OFF indent:ON |')
+ expect_filetype('filetype detection:ON plugin:OFF indent:ON |')
clear('-u', 'NORC', '-c', 'filetype indent off')
- expect_filetype(
- 'filetype detection:ON plugin:ON indent:OFF |')
+ expect_filetype('filetype detection:ON plugin:ON indent:OFF |')
end)
end)
@@ -167,7 +149,7 @@ describe('startup defaults', function()
]])
-- change "vert" character to single-cell
- funcs.setcellwidths({{0x2502, 0x2502, 1}})
+ fn.setcellwidths({ { 0x2502, 0x2502, 1 } })
screen:expect([[
1 │1 |
^+-- 2 lines: 2----------│+-- 2 lines: 2---------|
@@ -177,7 +159,7 @@ describe('startup defaults', function()
]])
-- change "vert" character to double-cell
- funcs.setcellwidths({{0x2502, 0x2502, 2}})
+ fn.setcellwidths({ { 0x2502, 0x2502, 2 } })
screen:expect([[
1 |1 |
^+-- 2 lines: 2----------|+-- 2 lines: 2---------|
@@ -199,18 +181,22 @@ describe('startup defaults', function()
end)
it("'shadafile' ('viminfofile')", function()
- local env = {XDG_DATA_HOME='Xtest-userdata', XDG_STATE_HOME='Xtest-userstate', XDG_CONFIG_HOME='Xtest-userconfig'}
+ local env = {
+ XDG_DATA_HOME = 'Xtest-userdata',
+ XDG_STATE_HOME = 'Xtest-userstate',
+ XDG_CONFIG_HOME = 'Xtest-userconfig',
+ }
finally(function()
- command('set shadafile=NONE') -- Avoid writing shada file on exit
+ command('set shadafile=NONE') -- Avoid writing shada file on exit
rmdir('Xtest-userstate')
os.remove('Xtest-foo')
end)
- clear{args={}, args_rm={'-i'}, env=env}
+ 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_value('shadafile', {}))
- eq('', meths.get_option_value('viminfofile', {}))
+ eq('', api.nvim_get_option_value('shadafile', {}))
+ eq('', api.nvim_get_option_value('viminfofile', {}))
-- Handles viminfo/viminfofile as alias for shada/shadafile.
eq('\n shadafile=', eval('execute("set shadafile?")'))
eq('\n shadafile=', eval('execute("set viminfofile?")'))
@@ -223,22 +209,22 @@ describe('startup defaults', function()
local f = eval('fnamemodify(@%,":p")')
assert(string.len(f) > 3)
expect_exit(command, 'qall')
- clear{args={}, args_rm={'-i'}, env=env}
+ clear { args = {}, args_rm = { '-i' }, env = env }
eq({ f }, eval('v:oldfiles'))
end)
it("'packpath'", function()
- clear{
- args_rm={'runtimepath'},
+ clear {
+ args_rm = { 'runtimepath' },
}
-- Defaults to &runtimepath.
- eq(meths.get_option_value('runtimepath', {}), meths.get_option_value('packpath', {}))
+ eq(api.nvim_get_option_value('runtimepath', {}), api.nvim_get_option_value('packpath', {}))
-- Does not follow modifications to runtimepath.
- meths.command('set runtimepath+=foo')
- neq(meths.get_option_value('runtimepath', {}), meths.get_option_value('packpath', {}))
- meths.command('set packpath+=foo')
- eq(meths.get_option_value('runtimepath', {}), meths.get_option_value('packpath', {}))
+ command('set runtimepath+=foo')
+ neq(api.nvim_get_option_value('runtimepath', {}), api.nvim_get_option_value('packpath', {}))
+ command('set packpath+=foo')
+ eq(api.nvim_get_option_value('runtimepath', {}), api.nvim_get_option_value('packpath', {}))
end)
it('v:progpath is set to the absolute path', function()
@@ -248,33 +234,37 @@ describe('startup defaults', function()
describe('$NVIM_LOG_FILE', function()
local xdgdir = 'Xtest-startup-xdg-logpath'
- local xdgstatedir = is_os('win') and xdgdir..'/nvim-data' or xdgdir..'/nvim'
+ local xdgstatedir = is_os('win') and xdgdir .. '/nvim-data' or xdgdir .. '/nvim'
after_each(function()
os.remove('Xtest-logpath')
rmdir(xdgdir)
end)
it('is used if expansion succeeds', function()
- clear({env={
- NVIM_LOG_FILE='Xtest-logpath',
- }})
+ clear({ env = {
+ NVIM_LOG_FILE = 'Xtest-logpath',
+ } })
eq('Xtest-logpath', eval('$NVIM_LOG_FILE'))
end)
it('defaults to stdpath("log")/log if empty', function()
eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
- clear({env={
- XDG_STATE_HOME=xdgdir,
- NVIM_LOG_FILE='', -- Empty is invalid.
- }})
- eq(xdgstatedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
+ clear({
+ env = {
+ XDG_STATE_HOME = xdgdir,
+ NVIM_LOG_FILE = '', -- Empty is invalid.
+ },
+ })
+ eq(xdgstatedir .. '/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
end)
it('defaults to stdpath("log")/log if invalid', function()
eq(true, mkdir(xdgdir) and mkdir(xdgstatedir))
- clear({env={
- XDG_STATE_HOME=xdgdir,
- NVIM_LOG_FILE='.', -- Any directory is invalid.
- }})
- eq(xdgstatedir..'/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
+ clear({
+ env = {
+ XDG_STATE_HOME = xdgdir,
+ NVIM_LOG_FILE = '.', -- Any directory is invalid.
+ },
+ })
+ eq(xdgstatedir .. '/log', string.gsub(eval('$NVIM_LOG_FILE'), '\\', '/'))
end)
end)
end)
@@ -291,11 +281,12 @@ describe('XDG defaults', function()
clear()
local rtp = eval('split(&runtimepath, ",")')
local rv = {}
- local expected = (is_os('win')
- and { [[\nvim-data\site]], [[\nvim-data\site\after]], }
- or { '/nvim/site', '/nvim/site/after', })
+ local expected = (
+ is_os('win') and { [[\nvim-data\site]], [[\nvim-data\site\after]] }
+ or { '/nvim/site', '/nvim/site/after' }
+ )
- for _,v in ipairs(rtp) do
+ for _, v in ipairs(rtp) do
local m = string.match(v, [=[[/\]nvim[^/\]*[/\]site.*$]=])
if m and not tbl_contains(rv, m) then
table.insert(rv, m)
@@ -306,28 +297,30 @@ describe('XDG defaults', function()
describe('with empty/broken environment', function()
it('sets correct defaults', function()
- clear({env={
- XDG_CONFIG_HOME=nil,
- XDG_DATA_HOME=nil,
- XDG_CACHE_HOME=nil,
- XDG_STATE_HOME=nil,
- XDG_RUNTIME_DIR=nil,
- XDG_CONFIG_DIRS=nil,
- XDG_DATA_DIRS=nil,
- LOCALAPPDATA=nil,
- HOMEPATH=nil,
- HOMEDRIVE=nil,
- HOME=nil,
- TEMP=nil,
- VIMRUNTIME=nil,
- USER=nil,
- }})
-
- 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)
+ clear({
+ env = {
+ XDG_CONFIG_HOME = nil,
+ XDG_DATA_HOME = nil,
+ XDG_CACHE_HOME = nil,
+ XDG_STATE_HOME = nil,
+ XDG_RUNTIME_DIR = nil,
+ XDG_CONFIG_DIRS = nil,
+ XDG_DATA_DIRS = nil,
+ LOCALAPPDATA = nil,
+ HOMEPATH = nil,
+ HOMEDRIVE = nil,
+ HOME = nil,
+ TEMP = nil,
+ VIMRUNTIME = nil,
+ USER = nil,
+ },
+ })
+
+ eq('.', api.nvim_get_option_value('backupdir', {}))
+ eq('.', api.nvim_get_option_value('viewdir', {}))
+ eq('.', api.nvim_get_option_value('directory', {}))
+ eq('.', api.nvim_get_option_value('undodir', {}))
+ ok((fn.tempname()):len() > 4)
end)
end)
@@ -335,7 +328,7 @@ describe('XDG defaults', function()
local vimruntime = eval('$VIMRUNTIME')
-- libdir is hard to calculate reliably across various ci platforms
-- local libdir = string.gsub(vimruntime, "share/nvim/runtime$", "lib/nvim")
- local libdir = meths._get_lib_dir()
+ local libdir = api.nvim__get_lib_dir()
return vimruntime, libdir
end
@@ -347,20 +340,21 @@ describe('XDG defaults', function()
describe('with too long XDG variables', function()
before_each(function()
clear({
- args_rm={'runtimepath'},
- env={
- NVIM_LOG_FILE=testlog,
- XDG_CONFIG_HOME=(root_path .. ('/x'):rep(4096)),
- XDG_CONFIG_DIRS=(root_path .. ('/a'):rep(2048)
- .. env_sep.. root_path .. ('/b'):rep(2048)
- .. (env_sep .. root_path .. '/c'):rep(512)),
- XDG_DATA_HOME=(root_path .. ('/X'):rep(4096)),
- XDG_RUNTIME_DIR=(root_path .. ('/X'):rep(4096)),
- XDG_STATE_HOME=(root_path .. ('/X'):rep(4096)),
- XDG_DATA_DIRS=(root_path .. ('/A'):rep(2048)
- .. env_sep .. root_path .. ('/B'):rep(2048)
- .. (env_sep .. root_path .. '/C'):rep(512)),
- }})
+ args_rm = { 'runtimepath' },
+ env = {
+ NVIM_LOG_FILE = testlog,
+ XDG_CONFIG_HOME = (root_path .. ('/x'):rep(4096)),
+ XDG_CONFIG_DIRS = (root_path .. ('/a'):rep(2048) .. env_sep .. root_path .. ('/b'):rep(
+ 2048
+ ) .. (env_sep .. root_path .. '/c'):rep(512)),
+ XDG_DATA_HOME = (root_path .. ('/X'):rep(4096)),
+ XDG_RUNTIME_DIR = (root_path .. ('/X'):rep(4096)),
+ XDG_STATE_HOME = (root_path .. ('/X'):rep(4096)),
+ XDG_DATA_DIRS = (root_path .. ('/A'):rep(2048) .. env_sep .. root_path .. ('/B'):rep(
+ 2048
+ ) .. (env_sep .. root_path .. '/C'):rep(512)),
+ },
+ })
end)
it('are correctly set', function()
@@ -370,209 +364,506 @@ describe('XDG defaults', function()
local vimruntime, libdir = vimruntime_and_libdir()
- eq(((root_path .. ('/x'):rep(4096) .. '/nvim'
- .. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim'
- .. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim'
- .. (',' .. root_path .. '/c/nvim'):rep(512)
- .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site'
- .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site'
- .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site'
- .. (',' .. root_path .. '/C/nvim/site'):rep(512)
- .. ',' .. vimruntime
- .. ',' .. libdir
- .. (',' .. root_path .. '/C/nvim/site/after'):rep(512)
- .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site/after'
- .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site/after'
- .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site/after'
- .. (',' .. root_path .. '/c/nvim/after'):rep(512)
- .. ',' .. 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_value('runtimepath', {})):gsub('\\', '/'))
- meths.command('set runtimepath&')
- meths.command('set backupdir&')
- meths.command('set directory&')
- meths.command('set undodir&')
- meths.command('set viewdir&')
- eq(((root_path .. ('/x'):rep(4096) .. '/nvim'
- .. ',' .. root_path .. ('/a'):rep(2048) .. '/nvim'
- .. ',' .. root_path .. ('/b'):rep(2048) .. '/nvim'
- .. (',' .. root_path .. '/c/nvim'):rep(512)
- .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site'
- .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site'
- .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site'
- .. (',' .. root_path .. '/C/nvim/site'):rep(512)
- .. ',' .. vimruntime
- .. ',' .. libdir
- .. (',' .. root_path .. '/C/nvim/site/after'):rep(512)
- .. ',' .. root_path .. ('/B'):rep(2048) .. '/nvim/site/after'
- .. ',' .. root_path .. ('/A'):rep(2048) .. '/nvim/site/after'
- .. ',' .. root_path .. ('/X'):rep(4096) .. '/' .. data_dir .. '/site/after'
- .. (',' .. root_path .. '/c/nvim/after'):rep(512)
- .. ',' .. 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_value('runtimepath', {})):gsub('\\', '/'))
- eq('.,' .. root_path .. ('/X'):rep(4096).. '/' .. state_dir .. '/backup//',
- (meths.get_option_value('backupdir', {}):gsub('\\', '/')))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/swap//',
- (meths.get_option_value('directory', {})):gsub('\\', '/'))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/undo//',
- (meths.get_option_value('undodir', {})):gsub('\\', '/'))
- eq(root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/view//',
- (meths.get_option_value('viewdir', {})):gsub('\\', '/'))
+ eq(
+ (
+ (
+ root_path
+ .. ('/x'):rep(4096)
+ .. '/nvim'
+ .. ','
+ .. root_path
+ .. ('/a'):rep(2048)
+ .. '/nvim'
+ .. ','
+ .. root_path
+ .. ('/b'):rep(2048)
+ .. '/nvim'
+ .. (',' .. root_path .. '/c/nvim'):rep(512)
+ .. ','
+ .. root_path
+ .. ('/X'):rep(4096)
+ .. '/'
+ .. data_dir
+ .. '/site'
+ .. ','
+ .. root_path
+ .. ('/A'):rep(2048)
+ .. '/nvim/site'
+ .. ','
+ .. root_path
+ .. ('/B'):rep(2048)
+ .. '/nvim/site'
+ .. (',' .. root_path .. '/C/nvim/site'):rep(512)
+ .. ','
+ .. vimruntime
+ .. ','
+ .. libdir
+ .. (',' .. root_path .. '/C/nvim/site/after'):rep(512)
+ .. ','
+ .. root_path
+ .. ('/B'):rep(2048)
+ .. '/nvim/site/after'
+ .. ','
+ .. root_path
+ .. ('/A'):rep(2048)
+ .. '/nvim/site/after'
+ .. ','
+ .. root_path
+ .. ('/X'):rep(4096)
+ .. '/'
+ .. data_dir
+ .. '/site/after'
+ .. (',' .. root_path .. '/c/nvim/after'):rep(512)
+ .. ','
+ .. root_path
+ .. ('/b'):rep(2048)
+ .. '/nvim/after'
+ .. ','
+ .. root_path
+ .. ('/a'):rep(2048)
+ .. '/nvim/after'
+ .. ','
+ .. root_path
+ .. ('/x'):rep(4096)
+ .. '/nvim/after'
+ ):gsub('\\', '/')
+ ),
+ (api.nvim_get_option_value('runtimepath', {})):gsub('\\', '/')
+ )
+ command('set runtimepath&')
+ command('set backupdir&')
+ command('set directory&')
+ command('set undodir&')
+ command('set viewdir&')
+ eq(
+ (
+ (
+ root_path
+ .. ('/x'):rep(4096)
+ .. '/nvim'
+ .. ','
+ .. root_path
+ .. ('/a'):rep(2048)
+ .. '/nvim'
+ .. ','
+ .. root_path
+ .. ('/b'):rep(2048)
+ .. '/nvim'
+ .. (',' .. root_path .. '/c/nvim'):rep(512)
+ .. ','
+ .. root_path
+ .. ('/X'):rep(4096)
+ .. '/'
+ .. data_dir
+ .. '/site'
+ .. ','
+ .. root_path
+ .. ('/A'):rep(2048)
+ .. '/nvim/site'
+ .. ','
+ .. root_path
+ .. ('/B'):rep(2048)
+ .. '/nvim/site'
+ .. (',' .. root_path .. '/C/nvim/site'):rep(512)
+ .. ','
+ .. vimruntime
+ .. ','
+ .. libdir
+ .. (',' .. root_path .. '/C/nvim/site/after'):rep(512)
+ .. ','
+ .. root_path
+ .. ('/B'):rep(2048)
+ .. '/nvim/site/after'
+ .. ','
+ .. root_path
+ .. ('/A'):rep(2048)
+ .. '/nvim/site/after'
+ .. ','
+ .. root_path
+ .. ('/X'):rep(4096)
+ .. '/'
+ .. data_dir
+ .. '/site/after'
+ .. (',' .. root_path .. '/c/nvim/after'):rep(512)
+ .. ','
+ .. root_path
+ .. ('/b'):rep(2048)
+ .. '/nvim/after'
+ .. ','
+ .. root_path
+ .. ('/a'):rep(2048)
+ .. '/nvim/after'
+ .. ','
+ .. root_path
+ .. ('/x'):rep(4096)
+ .. '/nvim/after'
+ ):gsub('\\', '/')
+ ),
+ (api.nvim_get_option_value('runtimepath', {})):gsub('\\', '/')
+ )
+ eq(
+ '.,' .. root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/backup//',
+ (api.nvim_get_option_value('backupdir', {}):gsub('\\', '/'))
+ )
+ eq(
+ root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/swap//',
+ (api.nvim_get_option_value('directory', {})):gsub('\\', '/')
+ )
+ eq(
+ root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/undo//',
+ (api.nvim_get_option_value('undodir', {})):gsub('\\', '/')
+ )
+ eq(
+ root_path .. ('/X'):rep(4096) .. '/' .. state_dir .. '/view//',
+ (api.nvim_get_option_value('viewdir', {})):gsub('\\', '/')
+ )
end)
end)
describe('with XDG variables that can be expanded', function()
before_each(function()
clear({
- args_rm={'runtimepath'},
- env={
- NVIM_LOG_FILE=testlog,
- XDG_CONFIG_HOME='$XDG_DATA_HOME',
- XDG_CONFIG_DIRS='$XDG_DATA_DIRS',
- XDG_DATA_HOME='$XDG_CONFIG_HOME',
- XDG_RUNTIME_DIR='$XDG_RUNTIME_DIR',
- XDG_STATE_HOME='$XDG_CONFIG_HOME',
- XDG_DATA_DIRS='$XDG_CONFIG_DIRS',
- }
+ args_rm = { 'runtimepath' },
+ env = {
+ NVIM_LOG_FILE = testlog,
+ XDG_CONFIG_HOME = '$XDG_DATA_HOME',
+ XDG_CONFIG_DIRS = '$XDG_DATA_DIRS',
+ XDG_DATA_HOME = '$XDG_CONFIG_HOME',
+ XDG_RUNTIME_DIR = '$XDG_RUNTIME_DIR',
+ XDG_STATE_HOME = '$XDG_CONFIG_HOME',
+ XDG_DATA_DIRS = '$XDG_CONFIG_DIRS',
+ },
})
end)
after_each(function()
- command('set shadafile=NONE') -- Avoid writing shada file on exit
+ command('set shadafile=NONE') -- Avoid writing shada file on exit
end)
it('are not expanded', function()
if not is_os('win') then
- assert_log('Failed to start server: no such file or directory: %$XDG_RUNTIME_DIR%/', testlog, 10)
+ assert_log(
+ 'Failed to start server: no such file or directory: %$XDG_RUNTIME_DIR%/',
+ testlog,
+ 10
+ )
end
local vimruntime, libdir = vimruntime_and_libdir()
- eq((('$XDG_DATA_HOME/nvim'
- .. ',$XDG_DATA_DIRS/nvim'
- .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site'
- .. ',$XDG_CONFIG_DIRS/nvim/site'
- .. ',' .. vimruntime
- .. ',' .. libdir
- .. ',$XDG_CONFIG_DIRS/nvim/site/after'
- .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after'
- .. ',$XDG_DATA_DIRS/nvim/after'
- .. ',$XDG_DATA_HOME/nvim/after'
- ):gsub('\\', '/')), (meths.get_option_value('runtimepath', {})):gsub('\\', '/'))
- meths.command('set runtimepath&')
- meths.command('set backupdir&')
- meths.command('set directory&')
- meths.command('set undodir&')
- meths.command('set viewdir&')
- eq((('$XDG_DATA_HOME/nvim'
- .. ',$XDG_DATA_DIRS/nvim'
- .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site'
- .. ',$XDG_CONFIG_DIRS/nvim/site'
- .. ',' .. vimruntime
- .. ',' .. libdir
- .. ',$XDG_CONFIG_DIRS/nvim/site/after'
- .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after'
- .. ',$XDG_DATA_DIRS/nvim/after'
- .. ',$XDG_DATA_HOME/nvim/after'
- ):gsub('\\', '/')), (meths.get_option_value('runtimepath', {})):gsub('\\', '/'))
- eq(('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
- meths.get_option_value('backupdir', {}):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
- meths.get_option_value('directory', {}):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
- meths.get_option_value('undodir', {}):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
- meths.get_option_value('viewdir', {}):gsub('\\', '/'))
- meths.command('set all&')
- eq(('$XDG_DATA_HOME/nvim'
+ eq(
+ (
+ (
+ '$XDG_DATA_HOME/nvim'
+ .. ',$XDG_DATA_DIRS/nvim'
+ .. ',$XDG_CONFIG_HOME/'
+ .. data_dir
+ .. '/site'
+ .. ',$XDG_CONFIG_DIRS/nvim/site'
+ .. ','
+ .. vimruntime
+ .. ','
+ .. libdir
+ .. ',$XDG_CONFIG_DIRS/nvim/site/after'
+ .. ',$XDG_CONFIG_HOME/'
+ .. data_dir
+ .. '/site/after'
+ .. ',$XDG_DATA_DIRS/nvim/after'
+ .. ',$XDG_DATA_HOME/nvim/after'
+ ):gsub('\\', '/')
+ ),
+ (api.nvim_get_option_value('runtimepath', {})):gsub('\\', '/')
+ )
+ command('set runtimepath&')
+ command('set backupdir&')
+ command('set directory&')
+ command('set undodir&')
+ command('set viewdir&')
+ eq(
+ (
+ (
+ '$XDG_DATA_HOME/nvim'
+ .. ',$XDG_DATA_DIRS/nvim'
+ .. ',$XDG_CONFIG_HOME/'
+ .. data_dir
+ .. '/site'
+ .. ',$XDG_CONFIG_DIRS/nvim/site'
+ .. ','
+ .. vimruntime
+ .. ','
+ .. libdir
+ .. ',$XDG_CONFIG_DIRS/nvim/site/after'
+ .. ',$XDG_CONFIG_HOME/'
+ .. data_dir
+ .. '/site/after'
+ .. ',$XDG_DATA_DIRS/nvim/after'
+ .. ',$XDG_DATA_HOME/nvim/after'
+ ):gsub('\\', '/')
+ ),
+ (api.nvim_get_option_value('runtimepath', {})):gsub('\\', '/')
+ )
+ eq(
+ ('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
+ api.nvim_get_option_value('backupdir', {}):gsub('\\', '/')
+ )
+ eq(
+ ('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
+ api.nvim_get_option_value('directory', {}):gsub('\\', '/')
+ )
+ eq(
+ ('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
+ api.nvim_get_option_value('undodir', {}):gsub('\\', '/')
+ )
+ eq(
+ ('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
+ api.nvim_get_option_value('viewdir', {}):gsub('\\', '/')
+ )
+ command('set all&')
+ eq(
+ (
+ '$XDG_DATA_HOME/nvim'
.. ',$XDG_DATA_DIRS/nvim'
- .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site'
+ .. ',$XDG_CONFIG_HOME/'
+ .. data_dir
+ .. '/site'
.. ',$XDG_CONFIG_DIRS/nvim/site'
- .. ',' .. vimruntime
- .. ',' .. libdir
+ .. ','
+ .. vimruntime
+ .. ','
+ .. libdir
.. ',$XDG_CONFIG_DIRS/nvim/site/after'
- .. ',$XDG_CONFIG_HOME/' .. data_dir .. '/site/after'
+ .. ',$XDG_CONFIG_HOME/'
+ .. data_dir
+ .. '/site/after'
.. ',$XDG_DATA_DIRS/nvim/after'
.. ',$XDG_DATA_HOME/nvim/after'
- ):gsub('\\', '/'), (meths.get_option_value('runtimepath', {})):gsub('\\', '/'))
- eq(('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
- meths.get_option_value('backupdir', {}):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
- meths.get_option_value('directory', {}):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
- meths.get_option_value('undodir', {}):gsub('\\', '/'))
- eq(('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
- meths.get_option_value('viewdir', {}):gsub('\\', '/'))
- eq(nil, (funcs.tempname()):match('XDG_RUNTIME_DIR'))
+ ):gsub('\\', '/'),
+ (api.nvim_get_option_value('runtimepath', {})):gsub('\\', '/')
+ )
+ eq(
+ ('.,$XDG_CONFIG_HOME/' .. state_dir .. '/backup//'),
+ api.nvim_get_option_value('backupdir', {}):gsub('\\', '/')
+ )
+ eq(
+ ('$XDG_CONFIG_HOME/' .. state_dir .. '/swap//'),
+ api.nvim_get_option_value('directory', {}):gsub('\\', '/')
+ )
+ eq(
+ ('$XDG_CONFIG_HOME/' .. state_dir .. '/undo//'),
+ api.nvim_get_option_value('undodir', {}):gsub('\\', '/')
+ )
+ eq(
+ ('$XDG_CONFIG_HOME/' .. state_dir .. '/view//'),
+ api.nvim_get_option_value('viewdir', {}):gsub('\\', '/')
+ )
+ eq(nil, (fn.tempname()):match('XDG_RUNTIME_DIR'))
end)
end)
describe('with commas', function()
before_each(function()
clear({
- args_rm={'runtimepath'},
- env={
- XDG_CONFIG_HOME=', , ,',
- XDG_CONFIG_DIRS=',-,-,' .. env_sep .. '-,-,-',
- XDG_DATA_HOME=',=,=,',
- XDG_STATE_HOME=',=,=,',
- XDG_DATA_DIRS=',≡,≡,' .. env_sep .. '≡,≡,≡',
- }})
+ args_rm = { 'runtimepath' },
+ env = {
+ XDG_CONFIG_HOME = ', , ,',
+ XDG_CONFIG_DIRS = ',-,-,' .. env_sep .. '-,-,-',
+ XDG_DATA_HOME = ',=,=,',
+ XDG_STATE_HOME = ',=,=,',
+ XDG_DATA_DIRS = ',≡,≡,' .. env_sep .. '≡,≡,≡',
+ },
+ })
end)
it('are escaped properly', function()
local vimruntime, libdir = vimruntime_and_libdir()
local path_sep = is_os('win') and '\\' or '/'
- eq(('\\, \\, \\,' .. path_sep .. 'nvim'
- .. ',\\,-\\,-\\,' .. path_sep .. 'nvim'
- .. ',-\\,-\\,-' .. path_sep .. 'nvim'
- .. ',\\,=\\,=\\,' .. path_sep .. data_dir .. path_sep .. 'site'
- .. ',\\,≡\\,≡\\,' .. path_sep .. 'nvim' .. path_sep .. 'site'
- .. ',≡\\,≡\\,≡' .. path_sep .. 'nvim' .. path_sep .. 'site'
- .. ',' .. vimruntime
- .. ',' .. libdir
- .. ',≡\\,≡\\,≡' .. path_sep .. 'nvim' .. path_sep .. 'site' .. path_sep .. 'after'
- .. ',\\,≡\\,≡\\,' .. path_sep .. 'nvim' .. path_sep .. 'site' .. path_sep .. 'after'
- .. ',\\,=\\,=\\,' .. path_sep.. data_dir .. path_sep .. 'site' .. path_sep .. 'after'
- .. ',-\\,-\\,-' .. path_sep .. 'nvim' .. path_sep .. 'after'
- .. ',\\,-\\,-\\,' .. path_sep .. 'nvim' .. path_sep .. 'after'
- .. ',\\, \\, \\,' .. path_sep .. 'nvim' .. path_sep .. 'after'
- ), meths.get_option_value('runtimepath', {}))
- meths.command('set runtimepath&')
- meths.command('set backupdir&')
- meths.command('set directory&')
- meths.command('set undodir&')
- meths.command('set viewdir&')
- eq(('\\, \\, \\,' .. path_sep .. 'nvim'
- .. ',\\,-\\,-\\,' .. path_sep ..'nvim'
- .. ',-\\,-\\,-' .. path_sep ..'nvim'
- .. ',\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'site'
- .. ',\\,≡\\,≡\\,' .. path_sep ..'nvim' .. path_sep ..'site'
- .. ',≡\\,≡\\,≡' .. path_sep ..'nvim' .. path_sep ..'site'
- .. ',' .. vimruntime
- .. ',' .. libdir
- .. ',≡\\,≡\\,≡' .. path_sep ..'nvim' .. path_sep ..'site' .. path_sep ..'after'
- .. ',\\,≡\\,≡\\,' .. path_sep ..'nvim' .. path_sep ..'site' .. path_sep ..'after'
- .. ',\\,=\\,=\\,' .. path_sep ..'' .. data_dir .. '' .. path_sep ..'site' .. path_sep ..'after'
- .. ',-\\,-\\,-' .. path_sep ..'nvim' .. path_sep ..'after'
- .. ',\\,-\\,-\\,' .. path_sep ..'nvim' .. path_sep ..'after'
- .. ',\\, \\, \\,' .. path_sep ..'nvim' .. path_sep ..'after'
- ), meths.get_option_value('runtimepath', {}))
- eq('.,\\,=\\,=\\,' .. path_sep .. state_dir .. '' .. path_sep ..'backup' .. (path_sep):rep(2),
- meths.get_option_value('backupdir', {}))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'swap' .. (path_sep):rep(2),
- meths.get_option_value('directory', {}))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'undo' .. (path_sep):rep(2),
- meths.get_option_value('undodir', {}))
- eq('\\,=\\,=\\,' .. path_sep ..'' .. state_dir .. '' .. path_sep ..'view' .. (path_sep):rep(2),
- meths.get_option_value('viewdir', {}))
+ eq(
+ (
+ '\\, \\, \\,'
+ .. path_sep
+ .. 'nvim'
+ .. ',\\,-\\,-\\,'
+ .. path_sep
+ .. 'nvim'
+ .. ',-\\,-\\,-'
+ .. path_sep
+ .. 'nvim'
+ .. ',\\,=\\,=\\,'
+ .. path_sep
+ .. data_dir
+ .. path_sep
+ .. 'site'
+ .. ',\\,≡\\,≡\\,'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'site'
+ .. ',≡\\,≡\\,≡'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'site'
+ .. ','
+ .. vimruntime
+ .. ','
+ .. libdir
+ .. ',≡\\,≡\\,≡'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'site'
+ .. path_sep
+ .. 'after'
+ .. ',\\,≡\\,≡\\,'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'site'
+ .. path_sep
+ .. 'after'
+ .. ',\\,=\\,=\\,'
+ .. path_sep
+ .. data_dir
+ .. path_sep
+ .. 'site'
+ .. path_sep
+ .. 'after'
+ .. ',-\\,-\\,-'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'after'
+ .. ',\\,-\\,-\\,'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'after'
+ .. ',\\, \\, \\,'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'after'
+ ),
+ api.nvim_get_option_value('runtimepath', {})
+ )
+ command('set runtimepath&')
+ command('set backupdir&')
+ command('set directory&')
+ command('set undodir&')
+ command('set viewdir&')
+ eq(
+ (
+ '\\, \\, \\,'
+ .. path_sep
+ .. 'nvim'
+ .. ',\\,-\\,-\\,'
+ .. path_sep
+ .. 'nvim'
+ .. ',-\\,-\\,-'
+ .. path_sep
+ .. 'nvim'
+ .. ',\\,=\\,=\\,'
+ .. path_sep
+ .. ''
+ .. data_dir
+ .. ''
+ .. path_sep
+ .. 'site'
+ .. ',\\,≡\\,≡\\,'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'site'
+ .. ',≡\\,≡\\,≡'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'site'
+ .. ','
+ .. vimruntime
+ .. ','
+ .. libdir
+ .. ',≡\\,≡\\,≡'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'site'
+ .. path_sep
+ .. 'after'
+ .. ',\\,≡\\,≡\\,'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'site'
+ .. path_sep
+ .. 'after'
+ .. ',\\,=\\,=\\,'
+ .. path_sep
+ .. ''
+ .. data_dir
+ .. ''
+ .. path_sep
+ .. 'site'
+ .. path_sep
+ .. 'after'
+ .. ',-\\,-\\,-'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'after'
+ .. ',\\,-\\,-\\,'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'after'
+ .. ',\\, \\, \\,'
+ .. path_sep
+ .. 'nvim'
+ .. path_sep
+ .. 'after'
+ ),
+ api.nvim_get_option_value('runtimepath', {})
+ )
+ eq(
+ '.,\\,=\\,=\\,' .. path_sep .. state_dir .. '' .. path_sep .. 'backup' .. (path_sep):rep(2),
+ api.nvim_get_option_value('backupdir', {})
+ )
+ eq(
+ '\\,=\\,=\\,'
+ .. path_sep
+ .. ''
+ .. state_dir
+ .. ''
+ .. path_sep
+ .. 'swap'
+ .. (path_sep):rep(2),
+ api.nvim_get_option_value('directory', {})
+ )
+ eq(
+ '\\,=\\,=\\,'
+ .. path_sep
+ .. ''
+ .. state_dir
+ .. ''
+ .. path_sep
+ .. 'undo'
+ .. (path_sep):rep(2),
+ api.nvim_get_option_value('undodir', {})
+ )
+ eq(
+ '\\,=\\,=\\,'
+ .. path_sep
+ .. ''
+ .. state_dir
+ .. ''
+ .. path_sep
+ .. 'view'
+ .. (path_sep):rep(2),
+ api.nvim_get_option_value('viewdir', {})
+ )
end)
end)
end)
-
describe('stdpath()', function()
-- Windows appends 'nvim-data' instead of just 'nvim' to prevent collisions
-- due to XDG_CONFIG_HOME, XDG_DATA_HOME and XDG_STATE_HOME being the same.
@@ -585,41 +876,45 @@ describe('stdpath()', function()
local env_sep = is_os('win') and ';' or ':'
it('acceptance', function()
- clear() -- Do not explicitly set any env vars.
-
- eq('nvim', funcs.fnamemodify(funcs.stdpath('cache'), ':t'))
- eq('nvim', funcs.fnamemodify(funcs.stdpath('config'), ':t'))
- eq(datadir, funcs.fnamemodify(funcs.stdpath('data'), ':t'))
- eq(statedir, funcs.fnamemodify(funcs.stdpath('state'), ':t'))
- eq('table', type(funcs.stdpath('config_dirs')))
- eq('table', type(funcs.stdpath('data_dirs')))
- eq('string', type(funcs.stdpath('run')))
- assert_alive() -- Check for crash. #8393
+ clear() -- Do not explicitly set any env vars.
+
+ eq('nvim', fn.fnamemodify(fn.stdpath('cache'), ':t'))
+ eq('nvim', fn.fnamemodify(fn.stdpath('config'), ':t'))
+ eq(datadir, fn.fnamemodify(fn.stdpath('data'), ':t'))
+ eq(statedir, fn.fnamemodify(fn.stdpath('state'), ':t'))
+ eq('table', type(fn.stdpath('config_dirs')))
+ eq('table', type(fn.stdpath('data_dirs')))
+ eq('string', type(fn.stdpath('run')))
+ assert_alive() -- Check for crash. #8393
end)
it('reacts to $NVIM_APPNAME', function()
local appname = 'NVIM_APPNAME_TEST' .. ('_'):rep(106)
- clear({env={ NVIM_APPNAME=appname }})
- eq(appname, funcs.fnamemodify(funcs.stdpath('config'), ':t'))
- eq(appname, funcs.fnamemodify(funcs.stdpath('cache'), ':t'))
- eq(maybe_data(appname), funcs.fnamemodify(funcs.stdpath('log'), ':t'))
- eq(maybe_data(appname), funcs.fnamemodify(funcs.stdpath('data'), ':t'))
- eq(maybe_data(appname), funcs.fnamemodify(funcs.stdpath('state'), ':t'))
+ clear({ env = { NVIM_APPNAME = appname } })
+ eq(appname, fn.fnamemodify(fn.stdpath('config'), ':t'))
+ eq(appname, fn.fnamemodify(fn.stdpath('cache'), ':t'))
+ eq(maybe_data(appname), fn.fnamemodify(fn.stdpath('log'), ':t'))
+ eq(maybe_data(appname), fn.fnamemodify(fn.stdpath('data'), ':t'))
+ eq(maybe_data(appname), fn.fnamemodify(fn.stdpath('state'), ':t'))
-- config_dirs and data_dirs are empty on windows, so don't check them on
-- that platform
if not is_os('win') then
- eq(appname, funcs.fnamemodify(funcs.stdpath('config_dirs')[1], ':t'))
- eq(appname, funcs.fnamemodify(funcs.stdpath('data_dirs')[1], ':t'))
+ eq(appname, fn.fnamemodify(fn.stdpath('config_dirs')[1], ':t'))
+ eq(appname, fn.fnamemodify(fn.stdpath('data_dirs')[1], ':t'))
end
- assert_alive() -- Check for crash. #8393
+ assert_alive() -- Check for crash. #8393
-- Check that Nvim rejects invalid APPNAMEs
-- Call jobstart() and jobwait() in the same RPC request to reduce flakiness.
local function test_appname(testAppname, expected_exitcode)
- local lua_code = string.format([[
+ local lua_code = string.format(
+ [[
local child = vim.fn.jobstart({ vim.v.progpath, '--clean', '--headless', '+qall!' }, { env = { NVIM_APPNAME = %q } })
return vim.fn.jobwait({ child }, %d)[1]
- ]], alter_slashes(testAppname), 3000)
+ ]],
+ alter_slashes(testAppname),
+ 3000
+ )
eq(expected_exitcode, exec_lua(lua_code))
end
-- Invalid appnames:
@@ -636,136 +931,149 @@ describe('stdpath()', function()
end)
describe('returns a String', function()
-
- describe('with "config"' , function ()
+ describe('with "config"', function()
it('knows XDG_CONFIG_HOME', function()
- clear({env={
- XDG_CONFIG_HOME=alter_slashes('/home/docwhat/.config'),
- }})
- eq(alter_slashes('/home/docwhat/.config/nvim'), funcs.stdpath('config'))
+ clear({
+ env = {
+ XDG_CONFIG_HOME = alter_slashes('/home/docwhat/.config'),
+ },
+ })
+ eq(alter_slashes('/home/docwhat/.config/nvim'), fn.stdpath('config'))
end)
it('handles changes during runtime', function()
- clear({env={
- XDG_CONFIG_HOME=alter_slashes('/home/original'),
- }})
- eq(alter_slashes('/home/original/nvim'), funcs.stdpath('config'))
- command("let $XDG_CONFIG_HOME='"..alter_slashes('/home/new').."'")
- eq(alter_slashes('/home/new/nvim'), funcs.stdpath('config'))
+ clear({ env = {
+ XDG_CONFIG_HOME = alter_slashes('/home/original'),
+ } })
+ eq(alter_slashes('/home/original/nvim'), fn.stdpath('config'))
+ command("let $XDG_CONFIG_HOME='" .. alter_slashes('/home/new') .. "'")
+ eq(alter_slashes('/home/new/nvim'), fn.stdpath('config'))
end)
it("doesn't expand $VARIABLES", function()
- clear({env={
- XDG_CONFIG_HOME='$VARIABLES',
- VARIABLES='this-should-not-happen',
- }})
- eq(alter_slashes('$VARIABLES/nvim'), funcs.stdpath('config'))
+ clear({
+ env = {
+ XDG_CONFIG_HOME = '$VARIABLES',
+ VARIABLES = 'this-should-not-happen',
+ },
+ })
+ eq(alter_slashes('$VARIABLES/nvim'), fn.stdpath('config'))
end)
it("doesn't expand ~/", function()
- clear({env={
- XDG_CONFIG_HOME=alter_slashes('~/frobnitz'),
- }})
- eq(alter_slashes('~/frobnitz/nvim'), funcs.stdpath('config'))
+ clear({ env = {
+ XDG_CONFIG_HOME = alter_slashes('~/frobnitz'),
+ } })
+ eq(alter_slashes('~/frobnitz/nvim'), fn.stdpath('config'))
end)
end)
- describe('with "data"' , function ()
+ describe('with "data"', function()
it('knows XDG_DATA_HOME', function()
- clear({env={
- XDG_DATA_HOME=alter_slashes('/home/docwhat/.local'),
- }})
- eq(alter_slashes('/home/docwhat/.local/'..datadir), funcs.stdpath('data'))
+ clear({ env = {
+ XDG_DATA_HOME = alter_slashes('/home/docwhat/.local'),
+ } })
+ eq(alter_slashes('/home/docwhat/.local/' .. datadir), fn.stdpath('data'))
end)
it('handles changes during runtime', function()
- clear({env={
- XDG_DATA_HOME=alter_slashes('/home/original'),
- }})
- eq(alter_slashes('/home/original/'..datadir), funcs.stdpath('data'))
- command("let $XDG_DATA_HOME='"..alter_slashes('/home/new').."'")
- eq(alter_slashes('/home/new/'..datadir), funcs.stdpath('data'))
+ clear({ env = {
+ XDG_DATA_HOME = alter_slashes('/home/original'),
+ } })
+ eq(alter_slashes('/home/original/' .. datadir), fn.stdpath('data'))
+ command("let $XDG_DATA_HOME='" .. alter_slashes('/home/new') .. "'")
+ eq(alter_slashes('/home/new/' .. datadir), fn.stdpath('data'))
end)
it("doesn't expand $VARIABLES", function()
- clear({env={
- XDG_DATA_HOME='$VARIABLES',
- VARIABLES='this-should-not-happen',
- }})
- eq(alter_slashes('$VARIABLES/'..datadir), funcs.stdpath('data'))
+ clear({
+ env = {
+ XDG_DATA_HOME = '$VARIABLES',
+ VARIABLES = 'this-should-not-happen',
+ },
+ })
+ eq(alter_slashes('$VARIABLES/' .. datadir), fn.stdpath('data'))
end)
it("doesn't expand ~/", function()
- clear({env={
- XDG_DATA_HOME=alter_slashes('~/frobnitz'),
- }})
- eq(alter_slashes('~/frobnitz/'..datadir), funcs.stdpath('data'))
+ clear({ env = {
+ XDG_DATA_HOME = alter_slashes('~/frobnitz'),
+ } })
+ eq(alter_slashes('~/frobnitz/' .. datadir), fn.stdpath('data'))
end)
end)
- describe('with "state"' , function ()
+ describe('with "state"', function()
it('knows XDG_STATE_HOME', function()
- clear({env={
- XDG_STATE_HOME=alter_slashes('/home/docwhat/.local'),
- }})
- eq(alter_slashes('/home/docwhat/.local/'..statedir), funcs.stdpath('state'))
+ clear({
+ env = {
+ XDG_STATE_HOME = alter_slashes('/home/docwhat/.local'),
+ },
+ })
+ eq(alter_slashes('/home/docwhat/.local/' .. statedir), fn.stdpath('state'))
end)
it('handles changes during runtime', function()
- clear({env={
- XDG_STATE_HOME=alter_slashes('/home/original'),
- }})
- eq(alter_slashes('/home/original/'..statedir), funcs.stdpath('state'))
- command("let $XDG_STATE_HOME='"..alter_slashes('/home/new').."'")
- eq(alter_slashes('/home/new/'..statedir), funcs.stdpath('state'))
+ clear({ env = {
+ XDG_STATE_HOME = alter_slashes('/home/original'),
+ } })
+ eq(alter_slashes('/home/original/' .. statedir), fn.stdpath('state'))
+ command("let $XDG_STATE_HOME='" .. alter_slashes('/home/new') .. "'")
+ eq(alter_slashes('/home/new/' .. statedir), fn.stdpath('state'))
end)
it("doesn't expand $VARIABLES", function()
- clear({env={
- XDG_STATE_HOME='$VARIABLES',
- VARIABLES='this-should-not-happen',
- }})
- eq(alter_slashes('$VARIABLES/'..statedir), funcs.stdpath('state'))
+ clear({
+ env = {
+ XDG_STATE_HOME = '$VARIABLES',
+ VARIABLES = 'this-should-not-happen',
+ },
+ })
+ eq(alter_slashes('$VARIABLES/' .. statedir), fn.stdpath('state'))
end)
it("doesn't expand ~/", function()
- clear({env={
- XDG_STATE_HOME=alter_slashes('~/frobnitz'),
- }})
- eq(alter_slashes('~/frobnitz/'..statedir), funcs.stdpath('state'))
+ clear({ env = {
+ XDG_STATE_HOME = alter_slashes('~/frobnitz'),
+ } })
+ eq(alter_slashes('~/frobnitz/' .. statedir), fn.stdpath('state'))
end)
end)
- describe('with "cache"' , function ()
+ describe('with "cache"', function()
it('knows XDG_CACHE_HOME', function()
- clear({env={
- XDG_CACHE_HOME=alter_slashes('/home/docwhat/.cache'),
- }})
- eq(alter_slashes('/home/docwhat/.cache/nvim'), funcs.stdpath('cache'))
+ clear({
+ env = {
+ XDG_CACHE_HOME = alter_slashes('/home/docwhat/.cache'),
+ },
+ })
+ eq(alter_slashes('/home/docwhat/.cache/nvim'), fn.stdpath('cache'))
end)
it('handles changes during runtime', function()
- clear({env={
- XDG_CACHE_HOME=alter_slashes('/home/original'),
- }})
- eq(alter_slashes('/home/original/nvim'), funcs.stdpath('cache'))
- command("let $XDG_CACHE_HOME='"..alter_slashes('/home/new').."'")
- eq(alter_slashes('/home/new/nvim'), funcs.stdpath('cache'))
+ clear({ env = {
+ XDG_CACHE_HOME = alter_slashes('/home/original'),
+ } })
+ eq(alter_slashes('/home/original/nvim'), fn.stdpath('cache'))
+ command("let $XDG_CACHE_HOME='" .. alter_slashes('/home/new') .. "'")
+ eq(alter_slashes('/home/new/nvim'), fn.stdpath('cache'))
end)
it("doesn't expand $VARIABLES", function()
- clear({env={
- XDG_CACHE_HOME='$VARIABLES',
- VARIABLES='this-should-not-happen',
- }})
- eq(alter_slashes('$VARIABLES/nvim'), funcs.stdpath('cache'))
+ clear({
+ env = {
+ XDG_CACHE_HOME = '$VARIABLES',
+ VARIABLES = 'this-should-not-happen',
+ },
+ })
+ eq(alter_slashes('$VARIABLES/nvim'), fn.stdpath('cache'))
end)
it("doesn't expand ~/", function()
- clear({env={
- XDG_CACHE_HOME=alter_slashes('~/frobnitz'),
- }})
- eq(alter_slashes('~/frobnitz/nvim'), funcs.stdpath('cache'))
+ clear({ env = {
+ XDG_CACHE_HOME = alter_slashes('~/frobnitz'),
+ } })
+ eq(alter_slashes('~/frobnitz/nvim'), fn.stdpath('cache'))
end)
end)
end)
@@ -775,23 +1083,23 @@ describe('stdpath()', function()
local function base_env()
if is_os('win') then
return {
- HOME='C:\\Users\\docwhat', -- technically, is not a usual PATH
- HOMEDRIVE='C:',
- HOMEPATH='\\Users\\docwhat',
- LOCALAPPDATA='C:\\Users\\docwhat\\AppData\\Local',
- TEMP='C:\\Users\\docwhat\\AppData\\Local\\Temp',
- TMPDIR='C:\\Users\\docwhat\\AppData\\Local\\Temp',
- TMP='C:\\Users\\docwhat\\AppData\\Local\\Temp',
+ HOME = 'C:\\Users\\docwhat', -- technically, is not a usual PATH
+ HOMEDRIVE = 'C:',
+ HOMEPATH = '\\Users\\docwhat',
+ LOCALAPPDATA = 'C:\\Users\\docwhat\\AppData\\Local',
+ TEMP = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
+ TMPDIR = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
+ TMP = 'C:\\Users\\docwhat\\AppData\\Local\\Temp',
}
else
return {
- HOME='/home/docwhat',
- HOMEDRIVE='HOMEDRIVE-should-be-ignored',
- HOMEPATH='HOMEPATH-should-be-ignored',
- LOCALAPPDATA='LOCALAPPDATA-should-be-ignored',
- TEMP='TEMP-should-be-ignored',
- TMPDIR='TMPDIR-should-be-ignored',
- TMP='TMP-should-be-ignored',
+ HOME = '/home/docwhat',
+ HOMEDRIVE = 'HOMEDRIVE-should-be-ignored',
+ HOMEPATH = 'HOMEPATH-should-be-ignored',
+ LOCALAPPDATA = 'LOCALAPPDATA-should-be-ignored',
+ TEMP = 'TEMP-should-be-ignored',
+ TMPDIR = 'TMPDIR-should-be-ignored',
+ TMP = 'TMP-should-be-ignored',
}
end
end
@@ -799,12 +1107,12 @@ describe('stdpath()', function()
local function set_paths_via_system(var_name, paths)
local env = base_env()
env[var_name] = table.concat(paths, env_sep)
- clear({env=env})
+ clear({ env = env })
end
local function set_paths_at_runtime(var_name, paths)
- clear({env=base_env()})
- meths.set_var('env_val', table.concat(paths, env_sep))
+ clear({ env = base_env() })
+ api.nvim_set_var('env_val', table.concat(paths, env_sep))
command(('let $%s=g:env_val'):format(var_name))
end
@@ -812,105 +1120,102 @@ describe('stdpath()', function()
describe(msg, function()
it('set via system', function()
set_paths_via_system(env_var_name, paths)
- eq(expected_paths, funcs.stdpath(stdpath_arg))
+ eq(expected_paths, fn.stdpath(stdpath_arg))
end)
it('set at runtime', function()
set_paths_at_runtime(env_var_name, paths)
- eq(expected_paths, funcs.stdpath(stdpath_arg))
+ eq(expected_paths, fn.stdpath(stdpath_arg))
end)
end)
end
- describe('with "config_dirs"' , function ()
+ describe('with "config_dirs"', function()
behaves_like_dir_list_env(
'handles XDG_CONFIG_DIRS with one path',
- 'config_dirs', 'XDG_CONFIG_DIRS',
+ 'config_dirs',
+ 'XDG_CONFIG_DIRS',
{
- alter_slashes('/home/docwhat/.config')
+ alter_slashes('/home/docwhat/.config'),
},
{
- alter_slashes('/home/docwhat/.config/nvim')
- })
+ alter_slashes('/home/docwhat/.config/nvim'),
+ }
+ )
behaves_like_dir_list_env(
'handles XDG_CONFIG_DIRS with two paths',
- 'config_dirs', 'XDG_CONFIG_DIRS',
+ 'config_dirs',
+ 'XDG_CONFIG_DIRS',
{
alter_slashes('/home/docwhat/.config'),
- alter_slashes('/etc/config')
+ alter_slashes('/etc/config'),
},
{
alter_slashes('/home/docwhat/.config/nvim'),
- alter_slashes('/etc/config/nvim')
- })
+ alter_slashes('/etc/config/nvim'),
+ }
+ )
behaves_like_dir_list_env(
"doesn't expand $VAR and $IBLES",
- 'config_dirs', 'XDG_CONFIG_DIRS',
+ 'config_dirs',
+ 'XDG_CONFIG_DIRS',
{ '$HOME', '$TMP' },
{
alter_slashes('$HOME/nvim'),
- alter_slashes('$TMP/nvim')
- })
-
+ alter_slashes('$TMP/nvim'),
+ }
+ )
- behaves_like_dir_list_env(
- "doesn't expand ~/",
- 'config_dirs', 'XDG_CONFIG_DIRS',
- {
- alter_slashes('~/.oldconfig'),
- alter_slashes('~/.olderconfig')
- },
- {
- alter_slashes('~/.oldconfig/nvim'),
- alter_slashes('~/.olderconfig/nvim')
- })
+ behaves_like_dir_list_env("doesn't expand ~/", 'config_dirs', 'XDG_CONFIG_DIRS', {
+ alter_slashes('~/.oldconfig'),
+ alter_slashes('~/.olderconfig'),
+ }, {
+ alter_slashes('~/.oldconfig/nvim'),
+ alter_slashes('~/.olderconfig/nvim'),
+ })
end)
- describe('with "data_dirs"' , function ()
- behaves_like_dir_list_env(
- 'knows XDG_DATA_DIRS with one path',
- 'data_dirs', 'XDG_DATA_DIRS',
- {
- alter_slashes('/home/docwhat/.data')
- },
- {
- alter_slashes('/home/docwhat/.data/nvim')
- })
+ describe('with "data_dirs"', function()
+ behaves_like_dir_list_env('knows XDG_DATA_DIRS with one path', 'data_dirs', 'XDG_DATA_DIRS', {
+ alter_slashes('/home/docwhat/.data'),
+ }, {
+ alter_slashes('/home/docwhat/.data/nvim'),
+ })
behaves_like_dir_list_env(
'knows XDG_DATA_DIRS with two paths',
- 'data_dirs', 'XDG_DATA_DIRS',
+ 'data_dirs',
+ 'XDG_DATA_DIRS',
{
alter_slashes('/home/docwhat/.data'),
- alter_slashes('/etc/local')
+ alter_slashes('/etc/local'),
},
{
alter_slashes('/home/docwhat/.data/nvim'),
alter_slashes('/etc/local/nvim'),
- })
+ }
+ )
behaves_like_dir_list_env(
"doesn't expand $VAR and $IBLES",
- 'data_dirs', 'XDG_DATA_DIRS',
+ 'data_dirs',
+ 'XDG_DATA_DIRS',
{ '$HOME', '$TMP' },
{
alter_slashes('$HOME/nvim'),
- alter_slashes('$TMP/nvim')
- })
+ alter_slashes('$TMP/nvim'),
+ }
+ )
- behaves_like_dir_list_env(
- "doesn't expand ~/",
- 'data_dirs', 'XDG_DATA_DIRS',
- {
- alter_slashes('~/.oldconfig'),
- alter_slashes('~/.olderconfig')
- },
- {
- alter_slashes('~/.oldconfig/nvim'),
- alter_slashes('~/.olderconfig/nvim'),
- })
+ behaves_like_dir_list_env("doesn't expand ~/", 'data_dirs', 'XDG_DATA_DIRS', {
+ alter_slashes('~/.oldconfig'),
+ alter_slashes('~/.olderconfig'),
+ }, {
+ alter_slashes('~/.oldconfig/nvim'),
+ alter_slashes('~/.olderconfig/nvim'),
+ })
end)
end)
@@ -927,3 +1232,22 @@ describe('stdpath()', function()
end)
end)
end)
+
+describe('autocommands', function()
+ it('closes terminal with default shell on success', function()
+ api.nvim_set_option_value('shell', helpers.testprg('shell-test'), {})
+ command('set shellcmdflag=EXIT shellredir= shellpipe= shellquote= shellxquote=')
+
+ -- Should not block other events
+ command('let g:n=0')
+ command('au BufEnter * let g:n = g:n + 1')
+
+ command('terminal')
+ eq(eval('get(g:, "n", 0)'), 1)
+
+ helpers.retry(nil, 1000, function()
+ neq(api.nvim_get_option_value('buftype', { buf = 0 }), 'terminal')
+ eq(eval('get(g:, "n", 0)'), 2)
+ end)
+ end)
+end)
diff --git a/test/functional/options/keymap_spec.lua b/test/functional/options/keymap_spec.lua
index c390e3d943..7be58888bc 100644
--- a/test/functional/options/keymap_spec.lua
+++ b/test/functional/options/keymap_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, feed, eq = helpers.clear, helpers.feed, helpers.eq
-local expect, command, eval = helpers.expect, helpers.command, helpers.eval
+local expect, command, eval = helpers.expect, helpers.command, helpers.eval
local insert, call = helpers.insert, helpers.call
local exec_capture, dedent = helpers.exec_capture, helpers.dedent
@@ -10,7 +10,7 @@ describe("'keymap' / :lmap", function()
clear()
before_each(function()
clear()
- insert("lllaaa")
+ insert('lllaaa')
command('set iminsert=1')
command('set imsearch=1')
command('lmap l a')
@@ -31,7 +31,8 @@ describe("'keymap' / :lmap", function()
command('set keymap=dvorak')
command('set nomore')
local bindings = exec_capture('lmap')
- eq(dedent([[
+ eq(
+ dedent([[
l " @_
l ' @-
@@ -104,20 +105,22 @@ describe("'keymap' / :lmap", function()
l z @;
l { @?
l | @|
- l } @+]]), bindings)
+ l } @+]]),
+ bindings
+ )
end)
end)
describe("'iminsert' option", function()
- it("Uses :lmap in insert mode when ON", function()
+ it('Uses :lmap in insert mode when ON', function()
feed('il<esc>')
expect('alllaaa')
end)
- it("Ignores :lmap in insert mode when OFF", function()
+ it('Ignores :lmap in insert mode when OFF', function()
command('set iminsert=0')
feed('il<esc>')
expect('llllaaa')
end)
- it("Can be toggled with <C-^> in insert mode", function()
+ it('Can be toggled with <C-^> in insert mode', function()
feed('i<C-^>l<C-^>l<esc>')
expect('lalllaaa')
eq(1, eval('&iminsert'))
@@ -126,16 +129,16 @@ describe("'keymap' / :lmap", function()
end)
end)
describe("'imsearch' option", function()
- it("Uses :lmap at search prompt when ON", function()
+ it('Uses :lmap at search prompt when ON', function()
feed('/lll<cr>3x')
expect('lll')
end)
- it("Ignores :lmap at search prompt when OFF", function()
+ it('Ignores :lmap at search prompt when OFF', function()
command('set imsearch=0')
feed('gg/lll<cr>3x')
expect('aaa')
end)
- it("Can be toggled with C-^", function()
+ it('Can be toggled with C-^', function()
eq(1, eval('&imsearch'))
feed('/<C-^>lll<cr>3x')
expect('aaa')
@@ -156,28 +159,28 @@ describe("'keymap' / :lmap", function()
eq(0, eval('&iminsert'))
end)
end)
- it(":lmap not applied to macros", function()
+ it(':lmap not applied to macros', function()
command("call setreg('a', 'il')")
feed('@a')
expect('llllaaa')
eq('il', call('getreg', 'a'))
end)
- it(":lmap applied to macro recording", function()
+ it(':lmap applied to macro recording', function()
feed('qail<esc>q@a')
expect('aalllaaa')
eq('ia', call('getreg', 'a'))
end)
- it(":lmap not applied to mappings", function()
+ it(':lmap not applied to mappings', function()
command('imap t l')
feed('it<esc>')
expect('llllaaa')
end)
- it("mappings applied to keys created with :lmap", function()
+ it('mappings applied to keys created with :lmap', function()
command('imap a x')
feed('il<esc>')
expect('xlllaaa')
end)
- it("mappings not applied to keys gotten with :lnoremap", function()
+ it('mappings not applied to keys gotten with :lnoremap', function()
command('lmapclear')
command('lnoremap l a')
command('imap a x')
@@ -196,7 +199,7 @@ describe("'keymap' / :lmap", function()
feed('@a')
expect('aalllaaa')
end)
- it("is applied when using f/F t/T", function()
+ it('is applied when using f/F t/T', function()
feed('flx')
expect('lllaa')
feed('0ia<esc>4lFlx')
diff --git a/test/functional/options/mousescroll_spec.lua b/test/functional/options/mousescroll_spec.lua
index 38a9692792..96af8987b8 100644
--- a/test/functional/options/mousescroll_spec.lua
+++ b/test/functional/options/mousescroll_spec.lua
@@ -23,11 +23,11 @@ describe("'mousescroll'", function()
local digit_expected = 'Vim(set):E5080: Digit expected: mousescroll='
local function should_fail(val, errorstr)
- eq(errorstr..val, exc_exec('set mousescroll='..val))
+ eq(errorstr .. val, exc_exec('set mousescroll=' .. val))
end
local function should_succeed(val)
- eq(0, exc_exec('set mousescroll='..val))
+ eq(0, exc_exec('set mousescroll=' .. val))
end
before_each(function()
@@ -147,15 +147,15 @@ describe("'mousescroll'", function()
command('set mousescroll=hor:1')
scroll('right')
- eq(9, screencol())
+ eq(9, screencol())
command('set mousescroll=hor:3')
scroll('right')
- eq(6, screencol())
+ eq(6, screencol())
command('set mousescroll=hor:2')
scroll('left')
- eq(8, screencol())
+ eq(8, screencol())
end
it('controls horizontal scrolling in normal mode', function()
diff --git a/test/functional/options/num_options_spec.lua b/test/functional/options/num_options_spec.lua
index 16a53c75e6..0614bcf814 100644
--- a/test/functional/options/num_options_spec.lua
+++ b/test/functional/options/num_options_spec.lua
@@ -1,40 +1,40 @@
-- Tests for :setlocal and :setglobal
local helpers = require('test.functional.helpers')(after_each)
-local clear, feed_command, eval, eq, meths =
- helpers.clear, helpers.feed_command, helpers.eval, helpers.eq, helpers.meths
+local clear, feed_command, eval, eq, api =
+ helpers.clear, helpers.feed_command, helpers.eval, helpers.eq, helpers.api
local function should_fail(opt, value, errmsg)
feed_command('setglobal ' .. opt .. '=' .. value)
- eq(errmsg, eval("v:errmsg"):match("E%d*"))
+ eq(errmsg, eval('v:errmsg'):match('E%d*'))
feed_command('let v:errmsg = ""')
feed_command('setlocal ' .. opt .. '=' .. value)
- eq(errmsg, eval("v:errmsg"):match("E%d*"))
+ eq(errmsg, eval('v:errmsg'):match('E%d*'))
feed_command('let v:errmsg = ""')
- local status, err = pcall(meths.set_option_value, opt, value, {})
+ local status, err = pcall(api.nvim_set_option_value, opt, value, {})
eq(status, false)
- eq(errmsg, err:match("E%d*"))
- eq('', eval("v:errmsg"))
+ eq(errmsg, err:match('E%d*'))
+ eq('', eval('v:errmsg'))
end
local function should_succeed(opt, value)
feed_command('setglobal ' .. opt .. '=' .. value)
feed_command('setlocal ' .. opt .. '=' .. value)
- meths.set_option_value(opt, value, {})
- eq(value, meths.get_option_value(opt, {}))
- eq('', eval("v:errmsg"))
+ api.nvim_set_option_value(opt, value, {})
+ eq(value, api.nvim_get_option_value(opt, {}))
+ eq('', eval('v:errmsg'))
end
describe(':setlocal', function()
before_each(clear)
it('setlocal sets only local value', function()
- eq(0, meths.get_option_value('iminsert', {scope='global'}))
+ eq(0, api.nvim_get_option_value('iminsert', { scope = 'global' }))
feed_command('setlocal iminsert=1')
- eq(0, meths.get_option_value('iminsert', {scope='global'}))
- eq(-1, meths.get_option_value('imsearch', {scope='global'}))
+ eq(0, api.nvim_get_option_value('iminsert', { scope = 'global' }))
+ eq(-1, api.nvim_get_option_value('imsearch', { scope = 'global' }))
feed_command('setlocal imsearch=1')
- eq(-1, meths.get_option_value('imsearch', {scope='global'}))
+ eq(-1, api.nvim_get_option_value('imsearch', { scope = 'global' }))
end)
end)
@@ -77,44 +77,44 @@ describe(':set validation', function()
-- If smaller than 1 this one is set to 'lines'-1
feed_command('setglobal window=-10')
- meths.set_option_value('window', -10, {})
- eq(23, meths.get_option_value('window', {}))
- eq('', eval("v:errmsg"))
+ api.nvim_set_option_value('window', -10, {})
+ eq(23, api.nvim_get_option_value('window', {}))
+ eq('', eval('v:errmsg'))
-- 'scrolloff' and 'sidescrolloff' can have a -1 value when
-- set for the current window, but not globally
feed_command('setglobal scrolloff=-1')
- eq('E487', eval("v:errmsg"):match("E%d*"))
+ eq('E487', eval('v:errmsg'):match('E%d*'))
feed_command('setglobal sidescrolloff=-1')
- eq('E487', eval("v:errmsg"):match("E%d*"))
+ eq('E487', eval('v:errmsg'):match('E%d*'))
feed_command('let v:errmsg=""')
feed_command('setlocal scrolloff=-1')
- eq('', eval("v:errmsg"))
+ eq('', eval('v:errmsg'))
feed_command('setlocal sidescrolloff=-1')
- eq('', eval("v:errmsg"))
+ eq('', eval('v:errmsg'))
end)
it('set wmh/wh wmw/wiw checks', function()
feed_command('set winheight=2')
feed_command('set winminheight=3')
- eq('E591', eval("v:errmsg"):match("E%d*"))
+ eq('E591', eval('v:errmsg'):match('E%d*'))
feed_command('set winwidth=2')
feed_command('set winminwidth=3')
- eq('E592', eval("v:errmsg"):match("E%d*"))
+ eq('E592', eval('v:errmsg'):match('E%d*'))
end)
it('set maxcombine resets to 6', function()
local function setto(value)
feed_command('setglobal maxcombine=' .. value)
feed_command('setlocal maxcombine=' .. value)
- meths.set_option_value('maxcombine', value, {})
- eq(6, meths.get_option_value('maxcombine', {}))
- eq('', eval("v:errmsg"))
+ api.nvim_set_option_value('maxcombine', value, {})
+ eq(6, api.nvim_get_option_value('maxcombine', {}))
+ eq('', eval('v:errmsg'))
end
setto(0)
setto(1)
diff --git a/test/functional/options/shortmess_spec.lua b/test/functional/options/shortmess_spec.lua
index a56e9c09b4..6bc00ca1c5 100644
--- a/test/functional/options/shortmess_spec.lua
+++ b/test/functional/options/shortmess_spec.lua
@@ -22,9 +22,7 @@ describe("'shortmess'", function()
feed(':edit foo<CR>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
"foo" [New] |
]])
eq(1, eval('bufnr("%")'))
@@ -33,9 +31,7 @@ describe("'shortmess'", function()
feed(':edit bar<CR>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
:edit bar |
]])
eq(2, eval('bufnr("%")'))
@@ -47,27 +43,21 @@ describe("'shortmess'", function()
feed(':edit foo<CR>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
"foo" [New] |
]])
eq(1, eval('bufnr("%")'))
feed(':edit bar<CR>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
"bar" [New] |
]])
eq(2, eval('bufnr("%")'))
feed(':bprevious<CR>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
"foo" [New] --No lines in buffer-- |
]])
eq(1, eval('bufnr("%")'))
@@ -76,18 +66,14 @@ describe("'shortmess'", function()
feed(':bnext<CR>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
:bnext |
]])
eq(2, eval('bufnr("%")'))
feed(':bprevious<CR>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
:bprevious |
]])
eq(1, eval('bufnr("%")'))
diff --git a/test/functional/options/tabstop_spec.lua b/test/functional/options/tabstop_spec.lua
index e34f678650..9070db8257 100644
--- a/test/functional/options/tabstop_spec.lua
+++ b/test/functional/options/tabstop_spec.lua
@@ -11,7 +11,7 @@ describe("'tabstop' option", function()
-- NOTE: Setting 'tabstop' to a big number reproduces crash #2838.
-- Disallowing big 'tabstop' would not fix #2838, only hide it.
- it("tabstop=<big-number> does not crash #2838", function()
+ it('tabstop=<big-number> does not crash #2838', function()
-- Insert a <Tab> character for 'tabstop' to work with.
feed('i<Tab><Esc>')
-- Set 'tabstop' to a very high value.
diff --git a/test/functional/plugin/cfilter_spec.lua b/test/functional/plugin/cfilter_spec.lua
index 8b1e75b495..37261d59df 100644
--- a/test/functional/plugin/cfilter_spec.lua
+++ b/test/functional/plugin/cfilter_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
-local funcs = helpers.funcs
+local fn = helpers.fn
describe('cfilter.lua', function()
before_each(function()
@@ -13,16 +13,16 @@ describe('cfilter.lua', function()
for _, list in ipairs({
{
name = 'Cfilter',
- get = funcs.getqflist,
- set = funcs.setqflist,
+ get = fn.getqflist,
+ set = fn.setqflist,
},
{
name = 'Lfilter',
get = function()
- return funcs.getloclist(0)
+ return fn.getloclist(0)
end,
set = function(items)
- return funcs.setloclist(0, items)
+ return fn.setloclist(0, items)
end,
},
}) do
@@ -39,7 +39,7 @@ describe('cfilter.lua', function()
describe((':%s'):format(list.name), function()
it('does not error on empty list', function()
filter('nothing')
- eq({}, funcs.getqflist())
+ eq({}, fn.getqflist())
end)
it('requires an argument', function()
@@ -66,7 +66,7 @@ describe('cfilter.lua', function()
end
local toname = function(qflist)
- return funcs.map(qflist, 'v:val.text')
+ return fn.map(qflist, 'v:val.text')
end
test('filters with no matches', 'does not match', {})
@@ -83,7 +83,7 @@ describe('cfilter.lua', function()
{ filename = 'foo', lnum = 3, text = 'zed' },
})
- funcs.setreg('/', 'ba')
+ fn.setreg('/', 'ba')
filter('/')
eq({ 'bar', 'baz' }, toname(list.get()))
@@ -96,7 +96,7 @@ describe('cfilter.lua', function()
{ filename = 'foo', lnum = 3, text = 'zed' },
})
- funcs.setreg('/', 'ba')
+ fn.setreg('/', 'ba')
filter('/', true)
eq({ 'zed' }, toname(list.get()))
diff --git a/test/functional/plugin/editorconfig_spec.lua b/test/functional/plugin/editorconfig_spec.lua
index ac78003a8c..115c28fbf6 100644
--- a/test/functional/plugin/editorconfig_spec.lua
+++ b/test/functional/plugin/editorconfig_spec.lua
@@ -3,8 +3,8 @@ local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
local pathsep = helpers.get_pathsep()
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local exec_lua = helpers.exec_lua
local testdir = 'Xtest-editorconfig'
@@ -13,7 +13,7 @@ local function test_case(name, expected)
local filename = testdir .. pathsep .. name
command('edit ' .. filename)
for opt, val in pairs(expected) do
- eq(val, meths.get_option_value(opt, {buf=0}), name)
+ eq(val, api.nvim_get_option_value(opt, { buf = 0 }), name)
end
end
@@ -195,15 +195,15 @@ But not this one
end)
it('can be disabled globally', function()
- meths.set_var('editorconfig', false)
- meths.set_option_value('shiftwidth', 42, {})
+ api.nvim_set_var('editorconfig', false)
+ api.nvim_set_option_value('shiftwidth', 42, {})
test_case('3_space.txt', { shiftwidth = 42 })
end)
it('can be disabled per-buffer', function()
- meths.set_option_value('shiftwidth', 42, {})
- local bufnr = funcs.bufadd(testdir .. pathsep .. '3_space.txt')
- meths.buf_set_var(bufnr, 'editorconfig', false)
+ api.nvim_set_option_value('shiftwidth', 42, {})
+ local bufnr = fn.bufadd(testdir .. pathsep .. '3_space.txt')
+ api.nvim_buf_set_var(bufnr, 'editorconfig', false)
test_case('3_space.txt', { shiftwidth = 42 })
test_case('4_space.py', { shiftwidth = 4 })
end)
diff --git a/test/functional/plugin/health_spec.lua b/test/functional/plugin/health_spec.lua
index 50b1d03f36..8564ec7c9b 100644
--- a/test/functional/plugin/health_spec.lua
+++ b/test/functional/plugin/health_spec.lua
@@ -5,12 +5,15 @@ local clear = helpers.clear
local curbuf_contents = helpers.curbuf_contents
local command = helpers.command
local eq, neq, matches = helpers.eq, helpers.neq, helpers.matches
-local getcompletion = helpers.funcs.getcompletion
+local getcompletion = helpers.fn.getcompletion
+local insert = helpers.insert
+local source = helpers.source
+local exec_lua = helpers.exec_lua
describe(':checkhealth', function()
- it("detects invalid $VIMRUNTIME", function()
+ it('detects invalid $VIMRUNTIME', function()
clear({
- env={ VIMRUNTIME='bogus', },
+ env = { VIMRUNTIME = 'bogus' },
})
local status, err = pcall(command, 'checkhealth')
eq(false, status)
@@ -23,32 +26,32 @@ describe(':checkhealth', function()
eq(false, status)
eq("Invalid 'runtimepath'", string.match(err, 'Invalid.*'))
end)
- it("detects invalid $VIM", function()
+ it('detects invalid $VIM', function()
clear()
-- Do this after startup, otherwise it just breaks $VIMRUNTIME.
command("let $VIM='zub'")
- command("checkhealth nvim")
+ command('checkhealth nvim')
matches('ERROR $VIM .* zub', curbuf_contents())
end)
it('completions can be listed via getcompletion()', function()
clear()
eq('nvim', getcompletion('nvim', 'checkhealth')[1])
- eq('provider', getcompletion('prov', 'checkhealth')[1])
+ eq('provider.clipboard', getcompletion('prov', 'checkhealth')[1])
eq('vim.lsp', getcompletion('vim.ls', 'checkhealth')[1])
- neq('vim', getcompletion('^vim', 'checkhealth')[1]) -- should not complete vim.health
+ neq('vim', getcompletion('^vim', 'checkhealth')[1]) -- should not complete vim.health
end)
end)
describe('health.vim', function()
before_each(function()
- clear{args={'-u', 'NORC'}}
+ clear { args = { '-u', 'NORC' } }
-- Provides healthcheck functions
- command("set runtimepath+=test/functional/fixtures")
+ command('set runtimepath+=test/functional/fixtures')
end)
- describe(":checkhealth", function()
- it("functions report_*() render correctly", function()
- command("checkhealth full_render")
+ describe(':checkhealth', function()
+ it('functions report_*() render correctly', function()
+ command('checkhealth full_render')
helpers.expect([[
==============================================================================
@@ -70,8 +73,8 @@ describe('health.vim', function()
]])
end)
- it("concatenates multiple reports", function()
- command("checkhealth success1 success2 test_plug")
+ it('concatenates multiple reports', function()
+ command('checkhealth success1 success2 test_plug')
helpers.expect([[
==============================================================================
@@ -100,8 +103,8 @@ describe('health.vim', function()
]])
end)
- it("lua plugins submodules", function()
- command("checkhealth test_plug.submodule")
+ it('lua plugins submodules', function()
+ command('checkhealth test_plug.submodule')
helpers.expect([[
==============================================================================
@@ -115,8 +118,8 @@ describe('health.vim', function()
]])
end)
- it("... including empty reports", function()
- command("checkhealth test_plug.submodule_empty")
+ it('... including empty reports', function()
+ command('checkhealth test_plug.submodule_empty')
helpers.expect([[
==============================================================================
@@ -126,7 +129,7 @@ describe('health.vim', function()
]])
end)
- it("highlights OK, ERROR", function()
+ it('highlights OK, ERROR', function()
local screen = Screen.new(50, 12)
screen:attach()
screen:set_default_attr_ids({
@@ -135,9 +138,10 @@ describe('health.vim', function()
Heading = { foreground = tonumber('0x6a0dad') },
Bar = { foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGrey },
})
- command("checkhealth foo success1")
- command("set nofoldenable nowrap laststatus=0")
- screen:expect{grid=[[
+ command('checkhealth foo success1')
+ command('set nofoldenable nowrap laststatus=0')
+ screen:expect {
+ grid = [[
^ |
{Bar:──────────────────────────────────────────────────}|
{Heading:foo: } |
@@ -150,15 +154,17 @@ describe('health.vim', function()
{Heading:report 1} |
- {Ok:OK} everything is fine |
|
- ]]}
+ ]],
+ }
end)
- it("fold healthchecks", function()
+ it('fold healthchecks', function()
local screen = Screen.new(50, 7)
screen:attach()
- command("checkhealth foo success1")
- command("set nowrap laststatus=0")
- screen:expect{grid=[[
+ command('checkhealth foo success1')
+ command('set nowrap laststatus=0')
+ screen:expect {
+ grid = [[
^ |
──────────────────────────────────────────────────|
+WE 4 lines: foo: ·······························|
@@ -166,11 +172,12 @@ describe('health.vim', function()
+-- 8 lines: test_plug.success1: require("test_pl|
~ |
|
- ]]}
+ ]],
+ }
end)
- it("gracefully handles invalid healthcheck", function()
- command("checkhealth non_existent_healthcheck")
+ it('gracefully handles invalid healthcheck', function()
+ command('checkhealth non_existent_healthcheck')
-- luacheck: ignore 613
helpers.expect([[
@@ -181,9 +188,9 @@ describe('health.vim', function()
]])
end)
- it("does not use vim.health as a healtcheck", function()
+ it('does not use vim.health as a healtcheck', function()
-- vim.health is not a healthcheck
- command("checkhealth vim")
+ command('checkhealth vim')
helpers.expect([[
ERROR: No healthchecks found.]])
end)
@@ -200,3 +207,187 @@ describe(':checkhealth provider', function()
eq(nil, string.match(curbuf_contents(), 'WRONG!!!'))
end)
end)
+
+describe(':checkhealth window', function()
+ before_each(function()
+ clear { args = { '-u', 'NORC' } }
+ -- Provides healthcheck functions
+ command('set runtimepath+=test/functional/fixtures')
+ command('set nofoldenable nowrap laststatus=0')
+ end)
+
+ it('opens directly if no buffer created', function()
+ local screen = Screen.new(50, 12)
+ screen:attach({ ext_multigrid = true })
+ command('checkhealth success1')
+ screen:expect {
+ grid = [[
+ ## grid 1
+ [2:--------------------------------------------------]|*11
+ [3:--------------------------------------------------]|
+ ## grid 2
+ ^ |
+ ──────────────────────────────────────────────────|
+ ──────────────────────────── |
+ test_plug.success1: require("test_plug.success1. |
+ health").check() |
+ |
+ report 1 |
+ - OK everything is fine |
+ |
+ report 2 |
+ - OK nothing to see here |
+ ## grid 3
+ |
+ ]],
+ }
+ end)
+
+ local function test_health_vsplit(left, emptybuf, mods)
+ local screen = Screen.new(50, 20)
+ screen:attach({ ext_multigrid = true })
+ if not emptybuf then
+ insert('hello')
+ end
+ command(mods .. ' checkhealth success1')
+ screen:expect(
+ ([[
+ ## grid 1
+ %s
+ [3:--------------------------------------------------]|
+ ## grid 2
+ %s |
+ ~ |*18
+ ## grid 3
+ |
+ ## grid 4
+ ^ |
+ ─────────────────────────|*3
+ ─── |
+ test_plug.success1: |
+ require("test_plug. |
+ success1.health").check()|
+ |
+ report 1 |
+ - OK everything is fine |
+ |
+ report 2 |
+ - OK nothing to see here |
+ |
+ ~ |*4
+ ]]):format(
+ left and '[4:-------------------------]│[2:------------------------]|*19'
+ or '[2:------------------------]│[4:-------------------------]|*19',
+ emptybuf and ' ' or 'hello'
+ )
+ )
+ end
+
+ for _, mods in ipairs({ 'vertical', 'leftabove vertical', 'topleft vertical' }) do
+ it(('opens in left vsplit window with :%s and no buffer created'):format(mods), function()
+ test_health_vsplit(true, true, mods)
+ end)
+ it(('opens in left vsplit window with :%s and non-empty buffer'):format(mods), function()
+ test_health_vsplit(true, false, mods)
+ end)
+ end
+
+ for _, mods in ipairs({ 'rightbelow vertical', 'botright vertical' }) do
+ it(('opens in right vsplit window with :%s and no buffer created'):format(mods), function()
+ test_health_vsplit(false, true, mods)
+ end)
+ it(('opens in right vsplit window with :%s and non-empty buffer'):format(mods), function()
+ test_health_vsplit(false, false, mods)
+ end)
+ end
+
+ local function test_health_split(top, emptybuf, mods)
+ local screen = Screen.new(50, 25)
+ screen:attach({ ext_multigrid = true })
+ if not emptybuf then
+ insert('hello')
+ end
+ command(mods .. ' checkhealth success1')
+ screen:expect(
+ ([[
+ ## grid 1
+%s
+ [3:--------------------------------------------------]|
+ ## grid 2
+ %s |
+ ~ |*10
+ ## grid 3
+ |
+ ## grid 4
+ ^ |
+ ──────────────────────────────────────────────────|
+ ──────────────────────────── |
+ test_plug.success1: require("test_plug.success1. |
+ health").check() |
+ |
+ report 1 |
+ - OK everything is fine |
+ |
+ report 2 |
+ - OK nothing to see here |
+ |
+ ]]):format(
+ top
+ and [[
+ [4:--------------------------------------------------]|*12
+ health:// |
+ [2:--------------------------------------------------]|*11]]
+ or ([[
+ [2:--------------------------------------------------]|*11
+ [No Name] %s |
+ [4:--------------------------------------------------]|*12]]):format(
+ emptybuf and ' ' or '[+]'
+ ),
+ emptybuf and ' ' or 'hello'
+ )
+ )
+ end
+
+ for _, mods in ipairs({ 'horizontal', 'leftabove', 'topleft' }) do
+ it(('opens in top split window with :%s and no buffer created'):format(mods), function()
+ test_health_split(true, true, mods)
+ end)
+ it(('opens in top split window with :%s and non-empty buffer'):format(mods), function()
+ test_health_split(true, false, mods)
+ end)
+ end
+
+ for _, mods in ipairs({ 'rightbelow', 'botright' }) do
+ it(('opens in bottom split window with :%s and no buffer created'):format(mods), function()
+ test_health_split(false, true, mods)
+ end)
+ it(('opens in bottom split window with :%s and non-empty buffer'):format(mods), function()
+ test_health_split(false, false, mods)
+ end)
+ end
+
+ it('opens in tab', function()
+ -- create an empty buffer called "my_buff"
+ exec_lua 'vim.api.nvim_create_buf(false, true)'
+ command('file my_buff')
+ command('checkhealth success1')
+ -- define a function that collects all buffers in each tab
+ -- returns a dictionary like {tab1 = ["buf1", "buf2"], tab2 = ["buf3"]}
+ source([[
+ function CollectBuffersPerTab()
+ let buffs = {}
+ for i in range(tabpagenr('$'))
+ let key = 'tab' . (i + 1)
+ let value = []
+ for j in tabpagebuflist(i + 1)
+ call add(value, bufname(j))
+ endfor
+ let buffs[key] = value
+ endfor
+ return buffs
+ endfunction
+ ]])
+ local buffers_per_tab = exec_lua('return vim.fn.CollectBuffersPerTab()')
+ eq(buffers_per_tab, { tab1 = { 'my_buff' }, tab2 = { 'health://' } })
+ end)
+end)
diff --git a/test/functional/plugin/lsp/codelens_spec.lua b/test/functional/plugin/lsp/codelens_spec.lua
index 3d7a15a191..29daf7a066 100644
--- a/test/functional/plugin/lsp/codelens_spec.lua
+++ b/test/functional/plugin/lsp/codelens_spec.lua
@@ -11,17 +11,21 @@ describe('vim.lsp.codelens', function()
after_each(helpers.clear)
it('on_codelens_stores_and_displays_lenses', function()
- local fake_uri = "file:///fake/uri"
- local bufnr = exec_lua([[
+ local fake_uri = 'file:///fake/uri'
+ local bufnr = exec_lua(
+ [[
fake_uri = ...
local bufnr = vim.uri_to_bufnr(fake_uri)
local lines = {'So', 'many', 'lines'}
vim.fn.bufload(bufnr)
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
return bufnr
- ]], fake_uri)
+ ]],
+ fake_uri
+ )
- exec_lua([[
+ exec_lua(
+ [[
local bufnr = ...
local lenses = {
{
@@ -33,14 +37,16 @@ describe('vim.lsp.codelens', function()
},
}
vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr})
- ]], bufnr)
+ ]],
+ bufnr
+ )
local stored_lenses = exec_lua('return vim.lsp.codelens.get(...)', bufnr)
local expected = {
{
range = {
start = { line = 0, character = 0 },
- ['end'] = { line = 0, character = 0 }
+ ['end'] = { line = 0, character = 0 },
},
command = {
title = 'Lens1',
@@ -50,28 +56,35 @@ describe('vim.lsp.codelens', function()
}
eq(expected, stored_lenses)
- local virtual_text_chunks = exec_lua([[
+ local virtual_text_chunks = exec_lua(
+ [[
local bufnr = ...
local ns = vim.lsp.codelens.__namespaces[1]
local extmarks = vim.api.nvim_buf_get_extmarks(bufnr, ns, 0, -1, {})
return vim.api.nvim_buf_get_extmark_by_id(bufnr, ns, extmarks[1][1], { details = true })[3].virt_text
- ]], bufnr)
+ ]],
+ bufnr
+ )
- eq({[1] = {'Lens1', 'LspCodeLens'}}, virtual_text_chunks)
+ eq({ [1] = { 'Lens1', 'LspCodeLens' } }, virtual_text_chunks)
end)
it('can clear all lens', function()
- local fake_uri = "file:///fake/uri"
- local bufnr = exec_lua([[
+ local fake_uri = 'file:///fake/uri'
+ local bufnr = exec_lua(
+ [[
fake_uri = ...
local bufnr = vim.uri_to_bufnr(fake_uri)
local lines = {'So', 'many', 'lines'}
vim.fn.bufload(bufnr)
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines)
return bufnr
- ]], fake_uri)
+ ]],
+ fake_uri
+ )
- exec_lua([[
+ exec_lua(
+ [[
local bufnr = ...
local lenses = {
{
@@ -83,7 +96,9 @@ describe('vim.lsp.codelens', function()
},
}
vim.lsp.codelens.on_codelens(nil, lenses, {method='textDocument/codeLens', client_id=1, bufnr=bufnr})
- ]], bufnr)
+ ]],
+ bufnr
+ )
local stored_lenses = exec_lua('return vim.lsp.codelens.get(...)', bufnr)
eq(1, #stored_lenses)
diff --git a/test/functional/plugin/lsp/completion_spec.lua b/test/functional/plugin/lsp/completion_spec.lua
index 9354654afe..655eb76be6 100644
--- a/test/functional/plugin/lsp/completion_spec.lua
+++ b/test/functional/plugin/lsp/completion_spec.lua
@@ -3,7 +3,6 @@ local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local exec_lua = helpers.exec_lua
-
--- Convert completion results.
---
---@param line string line contents. Mark cursor position with `|`
@@ -13,9 +12,10 @@ local exec_lua = helpers.exec_lua
local function complete(line, candidates, lnum)
lnum = lnum or 0
-- nvim_win_get_cursor returns 0 based column, line:find returns 1 based
- local cursor_col = line:find("|") - 1
- line = line:gsub("|", "")
- return exec_lua([[
+ local cursor_col = line:find('|') - 1
+ line = line:gsub('|', '')
+ return exec_lua(
+ [[
local line, cursor_col, lnum, result = ...
local line_to_cursor = line:sub(1, cursor_col)
local client_start_boundary = vim.fn.match(line_to_cursor, '\\k*$')
@@ -32,18 +32,22 @@ local function complete(line, candidates, lnum)
items = items,
server_start_boundary = server_start_boundary
}
- ]], line, cursor_col, lnum, candidates)
+ ]],
+ line,
+ cursor_col,
+ lnum,
+ candidates
+ )
end
-
-describe("vim.lsp._completion", function()
+describe('vim.lsp._completion', function()
before_each(helpers.clear)
-- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_completion
it('prefers textEdit over label as word', function()
local range0 = {
start = { line = 0, character = 0 },
- ["end"] = { line = 0, character = 0 },
+ ['end'] = { line = 0, character = 0 },
}
local completion_list = {
-- resolves into label
@@ -57,7 +61,12 @@ describe("vim.lsp._completion", function()
{ label = 'foocar', sortText = 'c', insertText = 'foobar' },
{ label = 'foocar', sortText = 'd', insertText = 'foobar' },
-- resolves into textEdit.newText
- { label = 'foocar', sortText = 'e', insertText = 'foodar', textEdit = { newText = 'foobar', range = range0 } },
+ {
+ label = 'foocar',
+ sortText = 'e',
+ insertText = 'foodar',
+ textEdit = { newText = 'foobar', range = range0 },
+ },
{ label = 'foocar', sortText = 'f', textEdit = { newText = 'foobar', range = range0 } },
-- real-world snippet text
{
@@ -65,7 +74,10 @@ describe("vim.lsp._completion", function()
sortText = 'g',
insertText = 'foodar',
insertTextFormat = 2,
- textEdit = { newText = 'foobar(${1:place holder}, ${2:more ...holder{\\}})', range = range0 },
+ textEdit = {
+ newText = 'foobar(${1:place holder}, ${2:more ...holder{\\}})',
+ range = range0,
+ },
},
{
label = 'foocar',
@@ -81,7 +93,7 @@ describe("vim.lsp._completion", function()
insertTextFormat = 2,
},
-- braced tabstop
- { label = 'foocar', sortText = 'j', insertText = 'foodar()${0}', insertTextFormat = 2},
+ { label = 'foocar', sortText = 'j', insertText = 'foodar()${0}', insertTextFormat = 2 },
-- plain text
{
label = 'foocar',
@@ -140,32 +152,32 @@ describe("vim.lsp._completion", function()
result = vim.tbl_map(function(x)
return {
abbr = x.abbr,
- word = x.word
+ word = x.word,
}
end, result.items)
eq(expected, result)
end)
- it("uses correct start boundary", function()
+ it('uses correct start boundary', function()
local completion_list = {
isIncomplete = false,
items = {
{
- filterText = "this_thread",
- insertText = "this_thread",
+ filterText = 'this_thread',
+ insertText = 'this_thread',
insertTextFormat = 1,
kind = 9,
- label = " this_thread",
+ label = ' this_thread',
score = 1.3205767869949,
- sortText = "4056f757this_thread",
+ sortText = '4056f757this_thread',
textEdit = {
- newText = "this_thread",
+ newText = 'this_thread',
range = {
start = { line = 0, character = 7 },
- ["end"] = { line = 0, character = 11 },
+ ['end'] = { line = 0, character = 11 },
},
- }
+ },
},
- }
+ },
}
local expected = {
abbr = ' this_thread',
@@ -176,50 +188,50 @@ describe("vim.lsp._completion", function()
menu = '',
word = 'this_thread',
}
- local result = complete(" std::this|", completion_list)
+ local result = complete(' std::this|', completion_list)
eq(7, result.server_start_boundary)
local item = result.items[1]
item.user_data = nil
eq(expected, item)
end)
- it("should search from start boundary to cursor position", function()
+ it('should search from start boundary to cursor position', function()
local completion_list = {
isIncomplete = false,
items = {
{
- filterText = "this_thread",
- insertText = "this_thread",
+ filterText = 'this_thread',
+ insertText = 'this_thread',
insertTextFormat = 1,
kind = 9,
- label = " this_thread",
+ label = ' this_thread',
score = 1.3205767869949,
- sortText = "4056f757this_thread",
+ sortText = '4056f757this_thread',
textEdit = {
- newText = "this_thread",
+ newText = 'this_thread',
range = {
start = { line = 0, character = 7 },
- ["end"] = { line = 0, character = 11 },
+ ['end'] = { line = 0, character = 11 },
},
- }
+ },
},
{
- filterText = "notthis_thread",
- insertText = "notthis_thread",
+ filterText = 'notthis_thread',
+ insertText = 'notthis_thread',
insertTextFormat = 1,
kind = 9,
- label = " notthis_thread",
+ label = ' notthis_thread',
score = 1.3205767869949,
- sortText = "4056f757this_thread",
+ sortText = '4056f757this_thread',
textEdit = {
- newText = "notthis_thread",
+ newText = 'notthis_thread',
range = {
start = { line = 0, character = 7 },
- ["end"] = { line = 0, character = 11 },
+ ['end'] = { line = 0, character = 11 },
},
- }
+ },
},
- }
+ },
}
local expected = {
abbr = ' this_thread',
@@ -230,10 +242,38 @@ describe("vim.lsp._completion", function()
menu = '',
word = 'this_thread',
}
- local result = complete(" std::this|is", completion_list)
+ local result = complete(' std::this|is', completion_list)
eq(1, #result.items)
local item = result.items[1]
item.user_data = nil
eq(expected, item)
end)
+
+ it('uses defaults from itemDefaults', function()
+ --- @type lsp.CompletionList
+ local completion_list = {
+ isIncomplete = false,
+ itemDefaults = {
+ editRange = {
+ start = { line = 1, character = 1 },
+ ['end'] = { line = 1, character = 4 },
+ },
+ insertTextFormat = 2,
+ data = 'foobar',
+ },
+ items = {
+ {
+ label = 'hello',
+ data = 'item-property-has-priority',
+ textEditText = 'hello',
+ },
+ },
+ }
+ local result = complete('|', completion_list)
+ eq(1, #result.items)
+ local item = result.items[1].user_data.nvim.lsp.completion_item --- @type lsp.CompletionItem
+ eq(2, item.insertTextFormat)
+ eq('item-property-has-priority', item.data)
+ eq({ line = 1, character = 1 }, item.textEdit.range.start)
+ end)
end)
diff --git a/test/functional/plugin/lsp/diagnostic_spec.lua b/test/functional/plugin/lsp/diagnostic_spec.lua
index 1da0222114..705c182df7 100644
--- a/test/functional/plugin/lsp/diagnostic_spec.lua
+++ b/test/functional/plugin/lsp/diagnostic_spec.lua
@@ -12,10 +12,10 @@ describe('vim.lsp.diagnostic', function()
local fake_uri
before_each(function()
- clear {env={
- NVIM_LUA_NOTRACK="1";
- VIMRUNTIME=os.getenv"VIMRUNTIME";
- }}
+ clear { env = {
+ NVIM_LUA_NOTRACK = '1',
+ VIMRUNTIME = os.getenv 'VIMRUNTIME',
+ } }
exec_lua [[
require('vim.lsp')
@@ -76,9 +76,10 @@ describe('vim.lsp.diagnostic', function()
}
]]
- fake_uri = "file:///fake/uri"
+ fake_uri = 'file:///fake/uri'
- exec_lua([[
+ exec_lua(
+ [[
fake_uri = ...
diagnostic_bufnr = vim.uri_to_bufnr(fake_uri)
local lines = {"1st line of text", "2nd line of text", "wow", "cool", "more", "lines"}
@@ -86,7 +87,9 @@ describe('vim.lsp.diagnostic', function()
vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, 1, false, lines)
vim.api.nvim_win_set_buf(0, diagnostic_bufnr)
return diagnostic_bufnr
- ]], fake_uri)
+ ]],
+ fake_uri
+ )
end)
after_each(function()
@@ -113,17 +116,18 @@ describe('vim.lsp.diagnostic', function()
vim.lsp.diagnostic.get_line_diagnostics(diagnostic_bufnr, 1)[1],
}
]]
- eq({code = 42, data = "Hello world"}, result[1].user_data.lsp)
+ eq({ code = 42, data = 'Hello world' }, result[1].user_data.lsp)
eq(42, result[1].code)
eq(42, result[2].code)
- eq("Hello world", result[2].data)
+ eq('Hello world', result[2].data)
end)
end)
- describe("vim.lsp.diagnostic.on_publish_diagnostics", function()
+ describe('vim.lsp.diagnostic.on_publish_diagnostics', function()
it('allows configuring the virtual text via vim.lsp.with', function()
local expected_spacing = 10
- local extmarks = exec_lua([[
+ local extmarks = exec_lua(
+ [[
PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
virtual_text = {
spacing = ...,
@@ -139,7 +143,9 @@ describe('vim.lsp.diagnostic', function()
)
return get_extmarks(diagnostic_bufnr, client_id)
- ]], expected_spacing)
+ ]],
+ expected_spacing
+ )
local virt_text = extmarks[1][4].virt_text
local spacing = virt_text[1][1]
@@ -149,7 +155,8 @@ describe('vim.lsp.diagnostic', function()
it('allows configuring the virtual text via vim.lsp.with using a function', function()
local expected_spacing = 10
- local extmarks = exec_lua([[
+ local extmarks = exec_lua(
+ [[
spacing = ...
PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
@@ -169,7 +176,9 @@ describe('vim.lsp.diagnostic', function()
)
return get_extmarks(diagnostic_bufnr, client_id)
- ]], expected_spacing)
+ ]],
+ expected_spacing
+ )
local virt_text = extmarks[1][4].virt_text
local spacing = virt_text[1][1]
@@ -179,11 +188,12 @@ describe('vim.lsp.diagnostic', function()
it('allows filtering via severity limit', function()
local get_extmark_count_with_severity = function(severity_limit)
- return exec_lua([[
+ return exec_lua(
+ [[
PublishDiagnostics = vim.lsp.with(vim.lsp.diagnostic.on_publish_diagnostics, {
underline = false,
virtual_text = {
- severity_limit = ...
+ severity = { min = ... }
},
})
@@ -196,20 +206,23 @@ describe('vim.lsp.diagnostic', function()
)
return #get_extmarks(diagnostic_bufnr, client_id)
- ]], severity_limit)
+ ]],
+ severity_limit
+ )
end
-- No messages with Error or higher
- eq(0, get_extmark_count_with_severity("Error"))
+ eq(0, get_extmark_count_with_severity('ERROR'))
-- But now we don't filter it
- eq(1, get_extmark_count_with_severity("Warning"))
- eq(1, get_extmark_count_with_severity("Hint"))
+ eq(1, get_extmark_count_with_severity('WARN'))
+ eq(1, get_extmark_count_with_severity('HINT'))
end)
it('correctly handles UTF-16 offsets', function()
- local line = "All 💼 and no 🎉 makes Jack a dull 👦"
- local result = exec_lua([[
+ local line = 'All 💼 and no 🎉 makes Jack a dull 👦'
+ local result = exec_lua(
+ [[
local line = ...
vim.api.nvim_buf_set_lines(diagnostic_bufnr, 0, -1, false, {line})
@@ -225,7 +238,9 @@ describe('vim.lsp.diagnostic', function()
vim.lsp.stop_client(client_id)
vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })
return diags
- ]], line)
+ ]],
+ line
+ )
eq(1, #result)
eq(exec_lua([[return vim.str_byteindex(..., 7, true)]], line), result[1].col)
eq(exec_lua([[return vim.str_byteindex(..., 8, true)]], line), result[1].end_col)
diff --git a/test/functional/plugin/lsp/handler_spec.lua b/test/functional/plugin/lsp/handler_spec.lua
index 3086c23fe8..56e29e7337 100644
--- a/test/functional/plugin/lsp/handler_spec.lua
+++ b/test/functional/plugin/lsp/handler_spec.lua
@@ -8,21 +8,30 @@ local matches = helpers.matches
describe('lsp-handlers', function()
describe('vim.lsp._with_extend', function()
it('should return a table with the default keys', function()
- eq({hello = 'world' }, exec_lua [[
+ eq(
+ { hello = 'world' },
+ exec_lua [[
return vim.lsp._with_extend('test', { hello = 'world' })
- ]])
+ ]]
+ )
end)
it('should override with config keys', function()
- eq({hello = 'universe', other = true}, exec_lua [[
+ eq(
+ { hello = 'universe', other = true },
+ exec_lua [[
return vim.lsp._with_extend('test', { other = true, hello = 'world' }, { hello = 'universe' })
- ]])
+ ]]
+ )
end)
it('should not allow invalid keys', function()
matches(
'.*Invalid option for `test`.*',
- pcall_err(exec_lua, "return vim.lsp._with_extend('test', { hello = 'world' }, { invalid = true })")
+ pcall_err(
+ exec_lua,
+ "return vim.lsp._with_extend('test', { hello = 'world' }, { invalid = true })"
+ )
)
end)
end)
diff --git a/test/functional/plugin/lsp/helpers.lua b/test/functional/plugin/lsp/helpers.lua
index 15e6a62781..97fa108500 100644
--- a/test/functional/plugin/lsp/helpers.lua
+++ b/test/functional/plugin/lsp/helpers.lua
@@ -4,18 +4,20 @@ local clear = helpers.clear
local exec_lua = helpers.exec_lua
local run = helpers.run
local stop = helpers.stop
-local NIL = helpers.NIL
+local NIL = vim.NIL
local M = {}
function M.clear_notrace()
-- problem: here be dragons
-- solution: don't look too closely for dragons
- clear {env={
- NVIM_LUA_NOTRACK="1";
- NVIM_APPNAME="nvim_lsp_test";
- VIMRUNTIME=os.getenv"VIMRUNTIME";
- }}
+ clear {
+ env = {
+ NVIM_LUA_NOTRACK = '1',
+ NVIM_APPNAME = 'nvim_lsp_test',
+ VIMRUNTIME = os.getenv 'VIMRUNTIME',
+ },
+ }
end
M.create_server_definition = [[
@@ -79,7 +81,8 @@ M.fake_lsp_code = 'test/functional/fixtures/fake-lsp-server.lua'
M.fake_lsp_logfile = 'Xtest-fake-lsp.log'
local function fake_lsp_server_setup(test_name, timeout_ms, options, settings)
- exec_lua([=[
+ exec_lua(
+ [=[
lsp = require('vim.lsp')
local test_name, fake_lsp_code, fake_lsp_logfile, timeout, options, settings = ...
TEST_RPC_CLIENT_ID = lsp.start_client {
@@ -115,33 +118,49 @@ local function fake_lsp_server_setup(test_name, timeout_ms, options, settings)
vim.rpcnotify(1, "exit", ...)
end;
}
- ]=], test_name, M.fake_lsp_code, M.fake_lsp_logfile, timeout_ms or 1e3, options or {}, settings or {})
+ ]=],
+ test_name,
+ M.fake_lsp_code,
+ M.fake_lsp_logfile,
+ timeout_ms or 1e3,
+ options or {},
+ settings or {}
+ )
end
function M.test_rpc_server(config)
if config.test_name then
M.clear_notrace()
- fake_lsp_server_setup(config.test_name, config.timeout_ms or 1e3, config.options, config.settings)
+ fake_lsp_server_setup(
+ config.test_name,
+ config.timeout_ms or 1e3,
+ config.options,
+ config.settings
+ )
end
local client = setmetatable({}, {
__index = function(_, name)
-- Workaround for not being able to yield() inside __index for Lua 5.1 :(
-- Otherwise I would just return the value here.
return function(...)
- return exec_lua([=[
+ return exec_lua(
+ [=[
local name = ...
if type(TEST_RPC_CLIENT[name]) == 'function' then
return TEST_RPC_CLIENT[name](select(2, ...))
else
return TEST_RPC_CLIENT[name]
end
- ]=], name, ...)
+ ]=],
+ name,
+ ...
+ )
end
- end;
+ end,
})
local code, signal
local function on_request(method, args)
- if method == "init" then
+ if method == 'init' then
if config.on_init then
config.on_init(client, unpack(args))
end
diff --git a/test/functional/plugin/lsp/incremental_sync_spec.lua b/test/functional/plugin/lsp/incremental_sync_spec.lua
index 724b3efb97..bd1842ceb5 100644
--- a/test/functional/plugin/lsp/incremental_sync_spec.lua
+++ b/test/functional/plugin/lsp/incremental_sync_spec.lua
@@ -1,13 +1,13 @@
-- Test suite for testing interactions with the incremental sync algorithms powering the LSP client
local helpers = require('test.functional.helpers')(after_each)
-local meths = helpers.meths
+local api = helpers.api
local clear = helpers.clear
local eq = helpers.eq
local exec_lua = helpers.exec_lua
local feed = helpers.feed
-before_each(function ()
+before_each(function()
clear()
exec_lua [[
local evname = ...
@@ -52,19 +52,24 @@ before_each(function ()
]]
end)
-local function test_edit(prev_buffer, edit_operations, expected_text_changes, offset_encoding, line_ending)
+local function test_edit(
+ prev_buffer,
+ edit_operations,
+ expected_text_changes,
+ offset_encoding,
+ line_ending
+)
offset_encoding = offset_encoding or 'utf-16'
line_ending = line_ending or '\n'
- meths.buf_set_lines(0, 0, -1, true, prev_buffer)
- exec_lua("return test_register(...)", 0, "test1", offset_encoding, line_ending)
+ api.nvim_buf_set_lines(0, 0, -1, true, prev_buffer)
+ exec_lua('return test_register(...)', 0, 'test1', offset_encoding, line_ending)
for _, edit in ipairs(edit_operations) do
feed(edit)
end
- eq(expected_text_changes, exec_lua("return get_events(...)" ))
+ eq(expected_text_changes, exec_lua('return get_events(...)'))
exec_lua("test_unreg = 'test1'")
-
end
describe('incremental synchronization', function()
@@ -75,18 +80,18 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 0
+ line = 0,
},
['end'] = {
character = 0,
- line = 0
- }
+ line = 0,
+ },
},
rangeLength = 0,
- text = 'a'
- }
+ text = 'a',
+ },
}
- test_edit({""}, {"ia"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ '' }, { 'ia' }, expected_text_changes, 'utf-16', '\n')
end)
it('inserting a character in the middle of a the first line', function()
local expected_text_changes = {
@@ -94,18 +99,18 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 1,
- line = 0
+ line = 0,
},
['end'] = {
character = 1,
- line = 0
- }
+ line = 0,
+ },
},
rangeLength = 0,
- text = 'a'
- }
+ text = 'a',
+ },
}
- test_edit({"ab"}, {"lia"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ 'ab' }, { 'lia' }, expected_text_changes, 'utf-16', '\n')
end)
it('deleting the only character in a buffer', function()
local expected_text_changes = {
@@ -113,18 +118,18 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 0
+ line = 0,
},
['end'] = {
character = 1,
- line = 0
- }
+ line = 0,
+ },
},
rangeLength = 1,
- text = ''
- }
+ text = '',
+ },
}
- test_edit({"a"}, {"x"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ 'a' }, { 'x' }, expected_text_changes, 'utf-16', '\n')
end)
it('deleting a character in the middle of the line', function()
local expected_text_changes = {
@@ -132,18 +137,18 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 1,
- line = 0
+ line = 0,
},
['end'] = {
character = 2,
- line = 0
- }
+ line = 0,
+ },
},
rangeLength = 1,
- text = ''
- }
+ text = '',
+ },
}
- test_edit({"abc"}, {"lx"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ 'abc' }, { 'lx' }, expected_text_changes, 'utf-16', '\n')
end)
it('replacing a character', function()
local expected_text_changes = {
@@ -151,18 +156,18 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 0
+ line = 0,
},
['end'] = {
character = 1,
- line = 0
- }
+ line = 0,
+ },
},
rangeLength = 1,
- text = 'b'
- }
+ text = 'b',
+ },
}
- test_edit({"a"}, {"rb"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ 'a' }, { 'rb' }, expected_text_changes, 'utf-16', '\n')
end)
it('deleting a line', function()
local expected_text_changes = {
@@ -170,18 +175,18 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 0
+ line = 0,
},
['end'] = {
character = 0,
- line = 1
- }
+ line = 1,
+ },
},
rangeLength = 12,
- text = ''
- }
+ text = '',
+ },
}
- test_edit({"hello world"}, {"dd"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ 'hello world' }, { 'dd' }, expected_text_changes, 'utf-16', '\n')
end)
it('deleting an empty line', function()
local expected_text_changes = {
@@ -189,18 +194,18 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 1
+ line = 1,
},
['end'] = {
character = 0,
- line = 2
- }
+ line = 2,
+ },
},
rangeLength = 1,
- text = ''
- }
+ text = '',
+ },
}
- test_edit({"hello world", ""}, {"jdd"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ 'hello world', '' }, { 'jdd' }, expected_text_changes, 'utf-16', '\n')
end)
it('adding a line', function()
local expected_text_changes = {
@@ -212,14 +217,14 @@ describe('incremental synchronization', function()
},
['end'] = {
character = 0,
- line = 1
- }
+ line = 1,
+ },
},
rangeLength = 1,
- text = '\nhello world\n'
- }
+ text = '\nhello world\n',
+ },
}
- test_edit({"hello world"}, {"yyp"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ 'hello world' }, { 'yyp' }, expected_text_changes, 'utf-16', '\n')
end)
it('adding an empty line', function()
local expected_text_changes = {
@@ -227,18 +232,18 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 11,
- line = 0
+ line = 0,
},
['end'] = {
character = 0,
- line = 1
- }
+ line = 1,
+ },
},
rangeLength = 1,
- text = '\n\n'
- }
+ text = '\n\n',
+ },
}
- test_edit({"hello world"}, {"o"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ 'hello world' }, { 'o' }, expected_text_changes, 'utf-16', '\n')
end)
it('adding a line to an empty buffer', function()
local expected_text_changes = {
@@ -246,18 +251,18 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 0
+ line = 0,
},
['end'] = {
character = 0,
- line = 1
- }
+ line = 1,
+ },
},
rangeLength = 1,
- text = '\n\n'
- }
+ text = '\n\n',
+ },
}
- test_edit({""}, {"o"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ '' }, { 'o' }, expected_text_changes, 'utf-16', '\n')
end)
it('insert a line above the current line', function()
local expected_text_changes = {
@@ -265,18 +270,18 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 0
+ line = 0,
},
['end'] = {
character = 0,
- line = 0
- }
+ line = 0,
+ },
},
rangeLength = 0,
- text = '\n'
- }
+ text = '\n',
+ },
}
- test_edit({""}, {"O"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ '' }, { 'O' }, expected_text_changes, 'utf-16', '\n')
end)
end)
describe('multi line edit', function()
@@ -287,115 +292,115 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 4,
- line = 1
+ line = 1,
},
['end'] = {
character = 9,
- line = 1
- }
+ line = 1,
+ },
},
rangeLength = 5,
- text = ''
+ text = '',
},
-- delete "hello world\n" from line 2
{
range = {
['start'] = {
character = 0,
- line = 2
+ line = 2,
},
['end'] = {
character = 0,
- line = 3
- }
+ line = 3,
+ },
},
rangeLength = 12,
- text = ''
+ text = '',
},
-- delete "1234" from beginning of line 2
{
range = {
['start'] = {
character = 0,
- line = 2
+ line = 2,
},
['end'] = {
character = 4,
- line = 2
- }
+ line = 2,
+ },
},
rangeLength = 4,
- text = ''
+ text = '',
},
-- add " asdf" to end of line 1
{
range = {
['start'] = {
character = 4,
- line = 1
+ line = 1,
},
['end'] = {
character = 4,
- line = 1
- }
+ line = 1,
+ },
},
rangeLength = 0,
- text = ' asdf'
+ text = ' asdf',
},
-- delete " asdf\n" from line 2
{
range = {
['start'] = {
character = 0,
- line = 2
+ line = 2,
},
['end'] = {
character = 0,
- line = 3
- }
+ line = 3,
+ },
},
rangeLength = 6,
- text = ''
+ text = '',
},
-- undo entire deletion
{
range = {
['start'] = {
character = 4,
- line = 1
+ line = 1,
},
['end'] = {
character = 9,
- line = 1
- }
+ line = 1,
+ },
},
rangeLength = 5,
- text = "_fdsa\nhello world\n1234 asdf"
+ text = '_fdsa\nhello world\n1234 asdf',
},
-- redo entire deletion
{
range = {
['start'] = {
character = 4,
- line = 1
+ line = 1,
},
['end'] = {
character = 9,
- line = 3
- }
+ line = 3,
+ },
},
rangeLength = 27,
- text = ' asdf'
+ text = ' asdf',
},
}
local original_lines = {
- "\\begin{document}",
- "test_fdsa",
- "hello world",
- "1234 asdf",
- "\\end{document}"
+ '\\begin{document}',
+ 'test_fdsa',
+ 'hello world',
+ '1234 asdf',
+ '\\end{document}',
}
- test_edit(original_lines, {"jf_vejjbhhdu<C-R>"}, expected_text_changes, 'utf-16', '\n')
+ test_edit(original_lines, { 'jf_vejjbhhdu<C-R>' }, expected_text_changes, 'utf-16', '\n')
end)
end)
@@ -404,64 +409,83 @@ describe('incremental synchronization', function()
local expected_text_changes = {
{
range = {
- ["end"] = {
- character = 11,
- line = 2 },
- ["start"] = {
- character = 10,
- line = 2 } },
+ ['end'] = {
+ character = 11,
+ line = 2,
+ },
+ ['start'] = {
+ character = 10,
+ line = 2,
+ },
+ },
rangeLength = 1,
text = '',
- },{
+ },
+ {
range = {
- ["end"] = {
+ ['end'] = {
character = 10,
- line = 2 },
+ line = 2,
+ },
start = {
character = 10,
- line = 2 } },
+ line = 2,
+ },
+ },
rangeLength = 0,
text = '2',
- },{
+ },
+ {
range = {
- ["end"] = {
+ ['end'] = {
character = 11,
- line = 3 },
- ["start"] = {
+ line = 3,
+ },
+ ['start'] = {
character = 10,
- line = 3 } },
+ line = 3,
+ },
+ },
rangeLength = 1,
- text = ''
- },{
+ text = '',
+ },
+ {
range = {
['end'] = {
character = 10,
- line = 3 },
+ line = 3,
+ },
['start'] = {
character = 10,
- line = 3 } },
+ line = 3,
+ },
+ },
rangeLength = 0,
- text = '3' },
+ text = '3',
+ },
{
range = {
['end'] = {
character = 0,
- line = 3 },
+ line = 3,
+ },
['start'] = {
character = 12,
- line = 2 } },
+ line = 2,
+ },
+ },
rangeLength = 1,
- text = '\n'
- }
+ text = '\n',
+ },
}
local original_lines = {
- "\\begin{document}",
- "\\section*{1}",
- "\\section*{1}",
- "\\section*{1}",
- "\\end{document}"
+ '\\begin{document}',
+ '\\section*{1}',
+ '\\section*{1}',
+ '\\section*{1}',
+ '\\end{document}',
}
- test_edit(original_lines, {"3gg$h<C-V>jg<C-A>"}, expected_text_changes, 'utf-16', '\n')
+ test_edit(original_lines, { '3gg$h<C-V>jg<C-A>' }, expected_text_changes, 'utf-16', '\n')
end)
it('join and undo', function()
local expected_text_changes = {
@@ -469,44 +493,46 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 11,
- line = 0
+ line = 0,
},
['end'] = {
character = 11,
- line = 0
- }
+ line = 0,
+ },
},
rangeLength = 0,
- text = ' test3'
- },{
+ text = ' test3',
+ },
+ {
range = {
['start'] = {
character = 0,
- line = 1
+ line = 1,
},
['end'] = {
character = 0,
- line = 2
- }
+ line = 2,
+ },
},
rangeLength = 6,
- text = ''
- },{
+ text = '',
+ },
+ {
range = {
['start'] = {
character = 11,
- line = 0
+ line = 0,
},
['end'] = {
character = 17,
- line = 0
- }
+ line = 0,
+ },
},
rangeLength = 6,
- text = '\ntest3'
+ text = '\ntest3',
},
}
- test_edit({"test1 test2", "test3"}, {"J", "u"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ 'test1 test2', 'test3' }, { 'J', 'u' }, expected_text_changes, 'utf-16', '\n')
end)
end)
@@ -517,18 +543,18 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 0
+ line = 0,
},
['end'] = {
character = 2,
- line = 0
- }
+ line = 0,
+ },
},
rangeLength = 2,
- text = ''
- }
+ text = '',
+ },
}
- test_edit({"🔥"}, {"x"}, expected_text_changes, 'utf-16', '\n')
+ test_edit({ '🔥' }, { 'x' }, expected_text_changes, 'utf-16', '\n')
end)
it('replacing a multibyte character with matching prefix', function()
local expected_text_changes = {
@@ -536,24 +562,24 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 1
+ line = 1,
},
['end'] = {
character = 1,
- line = 1
- }
+ line = 1,
+ },
},
rangeLength = 1,
- text = '⟩'
- }
+ text = '⟩',
+ },
}
-- ⟨ is e29fa8, ⟩ is e29fa9
local original_lines = {
- "\\begin{document}",
- "⟨",
- "\\end{document}",
+ '\\begin{document}',
+ '⟨',
+ '\\end{document}',
}
- test_edit(original_lines, {"jr⟩"}, expected_text_changes, 'utf-16', '\n')
+ test_edit(original_lines, { 'jr⟩' }, expected_text_changes, 'utf-16', '\n')
end)
it('replacing a multibyte character with matching suffix', function()
local expected_text_changes = {
@@ -561,24 +587,24 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 1
+ line = 1,
},
['end'] = {
character = 1,
- line = 1
- }
+ line = 1,
+ },
},
rangeLength = 1,
- text = 'ḟ'
- }
+ text = 'ḟ',
+ },
}
-- ฟ is e0b89f, ḟ is e1b89f
local original_lines = {
- "\\begin{document}",
- "ฟ",
- "\\end{document}",
+ '\\begin{document}',
+ 'ฟ',
+ '\\end{document}',
}
- test_edit(original_lines, {"jrḟ"}, expected_text_changes, 'utf-16', '\n')
+ test_edit(original_lines, { 'jrḟ' }, expected_text_changes, 'utf-16', '\n')
end)
it('inserting before a multibyte character', function()
local expected_text_changes = {
@@ -586,23 +612,23 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 1
+ line = 1,
},
['end'] = {
character = 0,
- line = 1
- }
+ line = 1,
+ },
},
rangeLength = 0,
- text = ' '
- }
+ text = ' ',
+ },
}
local original_lines = {
- "\\begin{document}",
- "→",
- "\\end{document}",
+ '\\begin{document}',
+ '→',
+ '\\end{document}',
}
- test_edit(original_lines, {"ji "}, expected_text_changes, 'utf-16', '\n')
+ test_edit(original_lines, { 'ji ' }, expected_text_changes, 'utf-16', '\n')
end)
it('deleting a multibyte character from a long line', function()
local expected_text_changes = {
@@ -610,23 +636,23 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 85,
- line = 1
+ line = 1,
},
['end'] = {
character = 86,
- line = 1
- }
+ line = 1,
+ },
},
rangeLength = 1,
- text = ''
- }
+ text = '',
+ },
}
local original_lines = {
- "\\begin{document}",
- "→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→",
- "\\end{document}",
+ '\\begin{document}',
+ '→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→→',
+ '\\end{document}',
}
- test_edit(original_lines, {"jx"}, expected_text_changes, 'utf-16', '\n')
+ test_edit(original_lines, { 'jx' }, expected_text_changes, 'utf-16', '\n')
end)
it('deleting multiple lines containing multibyte characters', function()
local expected_text_changes = {
@@ -634,19 +660,25 @@ describe('incremental synchronization', function()
range = {
['start'] = {
character = 0,
- line = 1
+ line = 1,
},
['end'] = {
character = 0,
- line = 3
- }
+ line = 3,
+ },
},
--utf 16 len of 🔥 is 2
rangeLength = 8,
- text = ''
- }
+ text = '',
+ },
}
- test_edit({"a🔥", "b🔥", "c🔥", "d🔥"}, {"j2dd"}, expected_text_changes, 'utf-16', '\n')
+ test_edit(
+ { 'a🔥', 'b🔥', 'c🔥', 'd🔥' },
+ { 'j2dd' },
+ expected_text_changes,
+ 'utf-16',
+ '\n'
+ )
end)
end)
end)
diff --git a/test/functional/plugin/lsp/inlay_hint_spec.lua b/test/functional/plugin/lsp/inlay_hint_spec.lua
index d0d55df72b..192797b312 100644
--- a/test/functional/plugin/lsp/inlay_hint_spec.lua
+++ b/test/functional/plugin/lsp/inlay_hint_spec.lua
@@ -40,7 +40,7 @@ local grid_without_inlay_hints = [[
|
]]
-local grid_with_inlay_hints = [[
+local grid_with_inlay_hints = [[
auto add(int a, int b)-> int { return a + b; } |
|
int main() { |
@@ -60,7 +60,8 @@ before_each(function()
screen:attach()
exec_lua(create_server_definition)
- exec_lua([[
+ exec_lua(
+ [[
local response = ...
server = _create_server({
capabilities = {
@@ -77,7 +78,9 @@ before_each(function()
vim.api.nvim_win_set_buf(0, bufnr)
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
- ]], response)
+ ]],
+ response
+ )
insert(text)
exec_lua([[vim.lsp.inlay_hint.enable(bufnr)]])
@@ -145,7 +148,8 @@ describe('vim.lsp.inlay_hint', function()
paddingRight = false,
}
- exec_lua([[
+ exec_lua(
+ [[
local expected2 = ...
server2 = _create_server({
capabilities = {
@@ -159,7 +163,9 @@ describe('vim.lsp.inlay_hint', function()
})
client2 = vim.lsp.start({ name = 'dummy2', cmd = server2.cmd })
vim.lsp.inlay_hint.enable(bufnr)
- ]], expected2)
+ ]],
+ expected2
+ )
--- @type vim.lsp.inlay_hint.get.ret
local res = exec_lua([[return vim.lsp.inlay_hint.get()]])
diff --git a/test/functional/plugin/lsp/semantic_tokens_spec.lua b/test/functional/plugin/lsp/semantic_tokens_spec.lua
index b7ac53f270..77e39c81c8 100644
--- a/test/functional/plugin/lsp/semantic_tokens_spec.lua
+++ b/test/functional/plugin/lsp/semantic_tokens_spec.lua
@@ -23,21 +23,20 @@ after_each(function()
end)
describe('semantic token highlighting', function()
-
local screen
before_each(function()
screen = Screen.new(40, 16)
screen:attach()
screen:set_default_attr_ids {
- [1] = { bold = true, foreground = Screen.colors.Blue1 };
- [2] = { foreground = Screen.colors.DarkCyan };
- [3] = { foreground = Screen.colors.SlateBlue };
- [4] = { bold = true, foreground = Screen.colors.SeaGreen };
- [5] = { foreground = tonumber('0x6a0dad') };
- [6] = { foreground = Screen.colors.Blue1 };
- [7] = { bold = true, foreground = Screen.colors.DarkCyan };
- [8] = { bold = true, foreground = Screen.colors.SlateBlue };
- [9] = { bold = true, foreground = tonumber('0x6a0dad') };
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.DarkCyan },
+ [3] = { foreground = Screen.colors.SlateBlue },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [5] = { foreground = tonumber('0x6a0dad') },
+ [6] = { foreground = Screen.colors.Blue1 },
+ [7] = { bold = true, foreground = Screen.colors.DarkCyan },
+ [8] = { bold = true, foreground = Screen.colors.SlateBlue },
+ [9] = { bold = true, foreground = tonumber('0x6a0dad') },
}
command([[ hi link @lsp.type.namespace Type ]])
command([[ hi link @lsp.type.function Special ]])
@@ -81,7 +80,8 @@ describe('semantic token highlighting', function()
before_each(function()
exec_lua(create_server_definition)
- exec_lua([[
+ exec_lua(
+ [[
local legend, response, edit_response = ...
server = _create_server({
capabilities = {
@@ -99,7 +99,11 @@ describe('semantic token highlighting', function()
end,
}
})
- ]], legend, response, edit_response)
+ ]],
+ legend,
+ response,
+ edit_response
+ )
end)
it('buffer is highlighted when attached', function()
@@ -112,7 +116,8 @@ describe('semantic token highlighting', function()
insert(text)
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int {8:main}() |
@@ -125,11 +130,10 @@ describe('semantic token highlighting', function()
{6:#endif} |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]] }
+ ]],
+ }
end)
it('use LspTokenUpdate and highlight_token', function()
@@ -151,7 +155,8 @@ describe('semantic token highlighting', function()
insert(text)
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int {9:main}() |
@@ -164,12 +169,10 @@ describe('semantic token highlighting', function()
{6:#endif} |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]] }
-
+ ]],
+ }
end)
it('buffer is unhighlighted when client is detached', function()
@@ -186,7 +189,8 @@ describe('semantic token highlighting', function()
vim.lsp.buf_detach_client(bufnr, client_id)
]])
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int main() |
@@ -199,29 +203,30 @@ describe('semantic token highlighting', function()
#endif |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]] }
+ ]],
+ }
end)
- it('buffer is highlighted and unhighlighted when semantic token highlighting is started and stopped'
- , function()
- exec_lua([[
+ it(
+ 'buffer is highlighted and unhighlighted when semantic token highlighting is started and stopped',
+ function()
+ exec_lua([[
bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr)
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
]])
- insert(text)
+ insert(text)
- exec_lua([[
+ exec_lua([[
vim.notify = function() end
vim.lsp.semantic_tokens.stop(bufnr, client_id)
]])
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int main() |
@@ -234,17 +239,17 @@ describe('semantic token highlighting', function()
#endif |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]] }
+ ]],
+ }
- exec_lua([[
+ exec_lua([[
vim.lsp.semantic_tokens.start(bufnr, client_id)
]])
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int {8:main}() |
@@ -257,12 +262,12 @@ describe('semantic token highlighting', function()
{6:#endif} |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]] }
- end)
+ ]],
+ }
+ end
+ )
it('buffer is re-highlighted when force refreshed', function()
exec_lua([[
@@ -273,7 +278,8 @@ describe('semantic token highlighting', function()
insert(text)
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int {8:main}() |
@@ -286,17 +292,17 @@ describe('semantic token highlighting', function()
{6:#endif} |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]] }
+ ]],
+ }
exec_lua([[
vim.lsp.semantic_tokens.force_refresh(bufnr)
]])
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int {8:main}() |
@@ -309,11 +315,11 @@ describe('semantic token highlighting', function()
{6:#endif} |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], unchanged = true }
+ ]],
+ unchanged = true,
+ }
local messages = exec_lua('return server.messages')
local token_request_count = 0
@@ -352,7 +358,8 @@ describe('semantic token highlighting', function()
]])
insert(text)
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int {8:main}() |
@@ -365,14 +372,14 @@ describe('semantic token highlighting', function()
{6:#endif} |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]] }
+ ]],
+ }
feed_command('%s/int x/int x()/')
feed_command('noh')
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int {8:main}() |
@@ -383,13 +390,11 @@ describe('semantic token highlighting', function()
{6:#else} |
{6: printf("%d\n", x);} |
{6:#endif} |
- } |
- } |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ } |*2
+ {1:~ }|*3
:noh |
- ]] }
+ ]],
+ }
end)
it('prevents starting semantic token highlighting with invalid conditions', function()
@@ -400,7 +405,7 @@ describe('semantic token highlighting', function()
notifications = {}
vim.notify = function(...) table.insert(notifications, 1, {...}) end
]])
- eq(false, exec_lua("return vim.lsp.buf_is_attached(bufnr, client_id)"))
+ eq(false, exec_lua('return vim.lsp.buf_is_attached(bufnr, client_id)'))
insert(text)
@@ -417,7 +422,8 @@ describe('semantic token highlighting', function()
matches('%[LSP%] No client with id %d', notifications[1][1])
end)
- it('opt-out: does not activate semantic token highlighting if disabled in client attach',
+ it(
+ 'opt-out: does not activate semantic token highlighting if disabled in client attach',
function()
exec_lua([[
bufnr = vim.api.nvim_get_current_buf()
@@ -430,11 +436,12 @@ describe('semantic token highlighting', function()
end),
})
]])
- eq(true, exec_lua("return vim.lsp.buf_is_attached(bufnr, client_id)"))
+ eq(true, exec_lua('return vim.lsp.buf_is_attached(bufnr, client_id)'))
insert(text)
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int main() |
@@ -447,11 +454,10 @@ describe('semantic token highlighting', function()
#endif |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]] }
+ ]],
+ }
local notifications = exec_lua([[
local notifications = {}
@@ -461,7 +467,8 @@ describe('semantic token highlighting', function()
]])
eq('[LSP] Server does not support semantic tokens', notifications[1][1])
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int main() |
@@ -474,14 +481,15 @@ describe('semantic token highlighting', function()
#endif |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], unchanged = true }
- end)
+ ]],
+ unchanged = true,
+ }
+ end
+ )
- it('ignores null responses from the server', function()
+ it('ignores null responses from the server', function()
exec_lua([[
local legend, response, edit_response = ...
server2 = _create_server({
@@ -503,11 +511,12 @@ describe('semantic token highlighting', function()
vim.api.nvim_win_set_buf(0, bufnr)
client_id = vim.lsp.start({ name = 'dummy', cmd = server2.cmd })
]])
- eq(true, exec_lua("return vim.lsp.buf_is_attached(bufnr, client_id)"))
+ eq(true, exec_lua('return vim.lsp.buf_is_attached(bufnr, client_id)'))
insert(text)
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int main() |
@@ -520,15 +529,15 @@ describe('semantic token highlighting', function()
#endif |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]] }
+ ]],
+ }
end)
it('does not send delta requests if not supported by server', function()
- exec_lua([[
+ exec_lua(
+ [[
local legend, response, edit_response = ...
server2 = _create_server({
capabilities = {
@@ -549,10 +558,15 @@ describe('semantic token highlighting', function()
bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr)
client_id = vim.lsp.start({ name = 'dummy', cmd = server2.cmd })
- ]], legend, response, edit_response)
+ ]],
+ legend,
+ response,
+ edit_response
+ )
insert(text)
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int {8:main}() |
@@ -565,18 +579,18 @@ describe('semantic token highlighting', function()
{6:#endif} |
} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]] }
+ ]],
+ }
feed_command('%s/int x/int x()/')
feed_command('noh')
-- the highlights don't change because our fake server sent the exact
-- same result for the same method (the full request). "x" would have
-- changed to highlight index 3 had we sent a delta request
- screen:expect { grid = [[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int {8:main}() |
@@ -587,13 +601,11 @@ describe('semantic token highlighting', function()
{6:#else} |
{6: printf("%d\n", x);} |
{6:#endif} |
- } |
- } |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ } |*2
+ {1:~ }|*3
:noh |
- ]] }
+ ]],
+ }
local messages = exec_lua('return server2.messages')
local token_request_count = 0
for _, message in ipairs(messages) do
@@ -631,24 +643,13 @@ describe('semantic token highlighting', function()
},
},
expected_screen = function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
char* {7:foo} = "\n"^; |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*14
|
- ]]}
+ ]],
+ }
end,
},
{
@@ -763,7 +764,8 @@ int main()
},
},
expected_screen = function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
#include <iostream> |
int {8:main}() |
{ |
@@ -774,13 +776,10 @@ int main()
{6: comment} |
{6: #endif} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
- ]]}
+ ]],
+ }
end,
},
{
@@ -824,24 +823,15 @@ b = "as"]],
},
},
expected_screen = function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{6:-- comment} |
local {7:a} = 1 |
{2:b} = "as^" |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*12
|
- ]]}
+ ]],
+ }
end,
},
{
@@ -954,30 +944,24 @@ b = "as"]],
},
},
expected_screen = function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
pub fn {8:main}() { |
break rust; |
//{6:/ what?} |
} |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
|
- ]]}
+ ]],
+ }
end,
},
}) do
it(test.it, function()
exec_lua(create_server_definition)
- exec_lua([[
+ exec_lua(
+ [[
local legend, resp = ...
server = _create_server({
capabilities = {
@@ -995,7 +979,10 @@ b = "as"]],
bufnr = vim.api.nvim_get_current_buf()
vim.api.nvim_win_set_buf(0, bufnr)
client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
- ]], test.legend, test.response)
+ ]],
+ test.legend,
+ test.response
+ )
insert(test.text)
@@ -1037,7 +1024,7 @@ b = "as"]],
end_col = 9,
type = 'variable',
marked = true,
- }
+ },
},
expected2 = {
{
@@ -1050,47 +1037,26 @@ b = "as"]],
end_col = 9,
type = 'variable',
marked = true,
- }
+ },
},
expected_screen1 = function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
char* {7:foo} = "\n"^; |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*14
|
- ]]}
+ ]],
+ }
end,
expected_screen2 = function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
char* {7:foo} = "\n"; |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*13
|
- ]]}
+ ]],
+ }
end,
},
{
@@ -1207,7 +1173,7 @@ int main()
modifiers = {},
type = 'comment',
marked = true,
- }
+ },
},
expected2 = {
{
@@ -1289,10 +1255,11 @@ int main()
modifiers = {},
type = 'comment',
marked = true,
- }
+ },
},
expected_screen1 = function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int {8:main}() |
@@ -1304,15 +1271,14 @@ int main()
{6: printf("%d\n", x);} |
{6:#endif} |
^} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
- ]]}
+ ]],
+ }
end,
expected_screen2 = function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
#include <iostream> |
|
int {8:main}() |
@@ -1325,11 +1291,10 @@ int main()
{6: printf("%d\n", x);} |
{6:^#endif} |
} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
end,
},
{
@@ -1356,55 +1321,33 @@ int main()
end_col = 6,
type = 'variable',
marked = true,
- }
- },
- expected2 = {
+ },
},
+ expected2 = {},
expected_screen1 = function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{7:string} = "test^" |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*14
|
- ]]}
+ ]],
+ }
end,
expected_screen2 = function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*14
|
- ]]}
+ ]],
+ }
end,
},
}) do
it(test.it, function()
exec_lua(create_server_definition)
- exec_lua([[
+ exec_lua(
+ [[
local legend, resp1, resp2 = ...
server = _create_server({
capabilities = {
@@ -1432,7 +1375,11 @@ int main()
semantic_tokens.stop(bufnr, client_id)
semantic_tokens.start(bufnr, client_id, { debounce = 10 })
end)
- ]], test.legend, test.response1, test.response2)
+ ]],
+ test.legend,
+ test.response1,
+ test.response2
+ )
insert(test.text1)
@@ -1447,11 +1394,14 @@ int main()
if test.edit then
feed(test.edit)
else
- exec_lua([[
+ exec_lua(
+ [[
local text = ...
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, vim.fn.split(text, "\n"))
vim.wait(15) -- wait for debounce
- ]], test.text2)
+ ]],
+ test.text2
+ )
end
test.expected_screen2()
diff --git a/test/functional/plugin/lsp/utils_spec.lua b/test/functional/plugin/lsp/utils_spec.lua
index 804dc32f0d..bb9cdb8390 100644
--- a/test/functional/plugin/lsp/utils_spec.lua
+++ b/test/functional/plugin/lsp/utils_spec.lua
@@ -10,7 +10,8 @@ describe('vim.lsp.util', function()
describe('stylize_markdown', function()
local stylize_markdown = function(content, opts)
- return exec_lua([[
+ return exec_lua(
+ [[
local bufnr = vim.uri_to_bufnr("file:///fake/uri")
vim.fn.bufload(bufnr)
@@ -20,14 +21,17 @@ describe('vim.lsp.util', function()
local stripped_content = vim.lsp.util.stylize_markdown(bufnr, content, opts)
return stripped_content
- ]], content, opts)
+ ]],
+ content,
+ opts
+ )
end
it('code fences', function()
local lines = {
- "```lua",
+ '```lua',
"local hello = 'world'",
- "```",
+ '```',
}
local expected = {
"local hello = 'world'",
@@ -38,9 +42,9 @@ describe('vim.lsp.util', function()
it('code fences with whitespace surrounded info string', function()
local lines = {
- "``` lua ",
+ '``` lua ',
"local hello = 'world'",
- "```",
+ '```',
}
local expected = {
"local hello = 'world'",
@@ -51,16 +55,16 @@ describe('vim.lsp.util', function()
it('adds separator after code block', function()
local lines = {
- "```lua",
+ '```lua',
"local hello = 'world'",
- "```",
- "",
- "something",
+ '```',
+ '',
+ 'something',
}
local expected = {
"local hello = 'world'",
- "─────────────────────",
- "something",
+ '─────────────────────',
+ 'something',
}
local opts = { separator = true }
eq(expected, stylize_markdown(lines, opts))
@@ -68,28 +72,28 @@ describe('vim.lsp.util', function()
it('replaces supported HTML entities', function()
local lines = {
- "1 &lt; 2",
- "3 &gt; 2",
- "&quot;quoted&quot;",
- "&apos;apos&apos;",
- "&ensp; &emsp;",
- "&amp;",
+ '1 &lt; 2',
+ '3 &gt; 2',
+ '&quot;quoted&quot;',
+ '&apos;apos&apos;',
+ '&ensp; &emsp;',
+ '&amp;',
}
local expected = {
- "1 < 2",
- "3 > 2",
+ '1 < 2',
+ '3 > 2',
'"quoted"',
"'apos'",
- " ",
- "&",
+ ' ',
+ '&',
}
local opts = {}
eq(expected, stylize_markdown(lines, opts))
end)
end)
- describe('normalize_markdown', function ()
- it('collapses consecutive blank lines', function ()
+ describe('normalize_markdown', function()
+ it('collapses consecutive blank lines', function()
local result = exec_lua [[
local lines = {
'foo',
@@ -102,11 +106,11 @@ describe('vim.lsp.util', function()
}
return vim.lsp.util._normalize_markdown(lines)
]]
- local expected = {'foo', '', 'bar', '', 'baz'}
+ local expected = { 'foo', '', 'bar', '', 'baz' }
eq(expected, result)
end)
- it('removes preceding and trailing empty lines', function ()
+ it('removes preceding and trailing empty lines', function()
local result = exec_lua [[
local lines = {
'',
@@ -117,103 +121,105 @@ describe('vim.lsp.util', function()
}
return vim.lsp.util._normalize_markdown(lines)
]]
- local expected = {'foo', 'bar'}
+ local expected = { 'foo', 'bar' }
eq(expected, result)
end)
end)
- describe("make_floating_popup_options", function ()
-
+ describe('make_floating_popup_options', function()
local function assert_anchor(anchor_bias, expected_anchor)
- local opts = exec_lua([[
+ local opts = exec_lua(
+ [[
local args = { ... }
local anchor_bias = args[1]
return vim.lsp.util.make_floating_popup_options(30, 10, { anchor_bias = anchor_bias })
- ]], anchor_bias)
+ ]],
+ anchor_bias
+ )
- eq(expected_anchor, string.sub(opts.anchor, 1, 1))
+ eq(expected_anchor, string.sub(opts.anchor, 1, 1))
end
local screen
- before_each(function ()
+ before_each(function()
helpers.clear()
screen = Screen.new(80, 80)
screen:attach()
- feed("79i<CR><Esc>") -- fill screen with empty lines
+ feed('79i<CR><Esc>') -- fill screen with empty lines
end)
- describe('when on the first line it places window below', function ()
- before_each(function ()
+ describe('when on the first line it places window below', function()
+ before_each(function()
feed('gg')
end)
- it('for anchor_bias = "auto"', function ()
+ it('for anchor_bias = "auto"', function()
assert_anchor('auto', 'N')
end)
- it('for anchor_bias = "above"', function ()
+ it('for anchor_bias = "above"', function()
assert_anchor('above', 'N')
end)
- it('for anchor_bias = "below"', function ()
+ it('for anchor_bias = "below"', function()
assert_anchor('below', 'N')
end)
end)
- describe('when on the last line it places window above', function ()
- before_each(function ()
+ describe('when on the last line it places window above', function()
+ before_each(function()
feed('G')
end)
- it('for anchor_bias = "auto"', function ()
+ it('for anchor_bias = "auto"', function()
assert_anchor('auto', 'S')
end)
- it('for anchor_bias = "above"', function ()
+ it('for anchor_bias = "above"', function()
assert_anchor('above', 'S')
end)
- it('for anchor_bias = "below"', function ()
+ it('for anchor_bias = "below"', function()
assert_anchor('below', 'S')
end)
end)
- describe('with 20 lines above, 59 lines below', function ()
- before_each(function ()
+ describe('with 20 lines above, 59 lines below', function()
+ before_each(function()
feed('gg20j')
end)
- it('places window below for anchor_bias = "auto"', function ()
+ it('places window below for anchor_bias = "auto"', function()
assert_anchor('auto', 'N')
end)
- it('places window above for anchor_bias = "above"', function ()
+ it('places window above for anchor_bias = "above"', function()
assert_anchor('above', 'S')
end)
- it('places window below for anchor_bias = "below"', function ()
+ it('places window below for anchor_bias = "below"', function()
assert_anchor('below', 'N')
end)
end)
- describe('with 59 lines above, 20 lines below', function ()
- before_each(function ()
+ describe('with 59 lines above, 20 lines below', function()
+ before_each(function()
feed('G20k')
end)
- it('places window above for anchor_bias = "auto"', function ()
+ it('places window above for anchor_bias = "auto"', function()
assert_anchor('auto', 'S')
end)
- it('places window above for anchor_bias = "above"', function ()
+ it('places window above for anchor_bias = "above"', function()
assert_anchor('above', 'S')
end)
- it('places window below for anchor_bias = "below"', function ()
+ it('places window below for anchor_bias = "below"', function()
assert_anchor('below', 'N')
end)
- it('bordered window truncates dimensions correctly', function ()
+ it('bordered window truncates dimensions correctly', function()
local opts = exec_lua([[
return vim.lsp.util.make_floating_popup_options(100, 100, { border = 'single' })
]])
@@ -222,5 +228,4 @@ describe('vim.lsp.util', function()
end)
end)
end)
-
end)
diff --git a/test/functional/plugin/lsp_spec.lua b/test/functional/plugin/lsp_spec.lua
index 56d31a0e44..4826153edb 100644
--- a/test/functional/plugin/lsp_spec.lua
+++ b/test/functional/plugin/lsp_spec.lua
@@ -11,19 +11,20 @@ local eq = helpers.eq
local eval = helpers.eval
local matches = helpers.matches
local pcall_err = helpers.pcall_err
-local pesc = helpers.pesc
+local pesc = vim.pesc
local insert = helpers.insert
-local funcs = helpers.funcs
+local fn = helpers.fn
local retry = helpers.retry
local stop = helpers.stop
-local NIL = helpers.NIL
+local NIL = vim.NIL
local read_file = require('test.helpers').read_file
local write_file = require('test.helpers').write_file
local is_ci = helpers.is_ci
-local meths = helpers.meths
+local api = helpers.api
local is_os = helpers.is_os
local skip = helpers.skip
local mkdir = helpers.mkdir
+local tmpname = helpers.tmpname
local clear_notrace = lsp_helpers.clear_notrace
local create_server_definition = lsp_helpers.create_server_definition
@@ -32,14 +33,16 @@ local fake_lsp_logfile = lsp_helpers.fake_lsp_logfile
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_get_option_value('%s', { buf = %s })", name, bufnr)
- )
+ bufnr = bufnr or 'BUFFER'
+ 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
-if skip(is_os('win')) then return end
+if skip(is_os('win')) then
+ return
+end
teardown(function()
os.remove(fake_lsp_logfile)
@@ -51,8 +54,9 @@ describe('LSP', function()
-- Run an instance of nvim on the file which contains our "scripts".
-- Pass TEST_NAME to pick the script.
- local test_name = "basic_init"
- exec_lua([=[
+ local test_name = 'basic_init'
+ exec_lua(
+ [=[
lsp = require('vim.lsp')
local test_name, fake_lsp_code, fake_lsp_logfile = ...
function test__start_client()
@@ -71,12 +75,16 @@ describe('LSP', function()
}
end
TEST_CLIENT1 = test__start_client()
- ]=], test_name, fake_lsp_code, fake_lsp_logfile)
+ ]=],
+ test_name,
+ fake_lsp_code,
+ fake_lsp_logfile
+ )
end)
after_each(function()
exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })")
- -- exec_lua("lsp.stop_all_clients(true)")
+ -- exec_lua("lsp.stop_all_clients(true)")
end)
describe('server_name specified', function()
@@ -84,14 +92,20 @@ describe('LSP', function()
retry(nil, 4000, function()
eq(1, exec_lua('return #lsp.get_clients()'))
end)
- eq(2, exec_lua([[
+ eq(
+ 2,
+ exec_lua([[
TEST_CLIENT2 = test__start_client()
return TEST_CLIENT2
- ]]))
- eq(3, exec_lua([[
+ ]])
+ )
+ eq(
+ 3,
+ exec_lua([[
TEST_CLIENT3 = test__start_client()
return TEST_CLIENT3
- ]]))
+ ]])
+ )
retry(nil, 4000, function()
eq(3, exec_lua('return #lsp.get_clients()'))
end)
@@ -125,80 +139,62 @@ describe('LSP', function()
end)
end)
end)
-
- describe('lsp._cmd_parts test', function()
- local function _cmd_parts(input)
- return exec_lua([[
- lsp = require('vim.lsp')
- return lsp._cmd_parts(...)
- ]], input)
- end
- it('should valid cmd argument', function()
- eq(true, pcall(_cmd_parts, {"nvim"}))
- eq(true, pcall(_cmd_parts, {"nvim", "--head"}))
- end)
-
- it('should invalid cmd argument', function()
- eq('.../lsp.lua:0: cmd: expected list, got nvim',
- pcall_err(_cmd_parts, 'nvim'))
- eq('.../lsp.lua:0: cmd argument: expected string, got number',
- pcall_err(_cmd_parts, {'nvim', 1}))
- end)
- end)
end)
describe('LSP', function()
describe('basic_init test', function()
after_each(function()
stop()
- exec_lua("lsp.stop_client(lsp.get_clients(), true)")
+ exec_lua('lsp.stop_client(lsp.get_clients(), true)')
exec_lua("vim.api.nvim_exec_autocmds('VimLeavePre', { modeline = false })")
end)
it('should run correctly', function()
local expected_handlers = {
- {NIL, {}, {method="test", client_id=1}};
+ { NIL, {}, { method = 'test', client_id = 1 } },
}
test_rpc_server {
- test_name = "basic_init";
+ test_name = 'basic_init',
on_init = function(client, _)
-- client is a dummy object which will queue up commands to be run
-- once the server initializes. It can't accept lua callbacks or
-- other types that may be unserializable for now.
client.stop()
- end;
+ end,
-- If the program timed out, then code will be nil.
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
-- Note that NIL must be used here.
-- on_handler(err, method, result, client_id)
on_handler = function(...)
- eq(table.remove(expected_handlers), {...})
- end;
+ eq(table.remove(expected_handlers), { ... })
+ end,
}
end)
it('should fail', function()
local expected_handlers = {
- {NIL, {}, {method="test", client_id=1}};
+ { NIL, {}, { method = 'test', client_id = 1 } },
}
test_rpc_server {
- test_name = "basic_init";
+ test_name = 'basic_init',
on_init = function(client)
client.notify('test')
client.stop()
- end;
+ end,
on_exit = function(code, signal)
- eq(101, code, "exit code") -- See fake-lsp-server.lua
- eq(0, signal, "exit signal")
- assert_log(pesc([[assert_eq failed: left == "\"shutdown\"", right == "\"test\""]]),
- fake_lsp_logfile)
- end;
+ eq(101, code, 'exit code') -- See fake-lsp-server.lua
+ eq(0, signal, 'exit signal')
+ assert_log(
+ pesc([[assert_eq failed: left == "\"shutdown\"", right == "\"test\""]]),
+ fake_lsp_logfile
+ )
+ end,
on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
}
end)
@@ -209,8 +205,8 @@ describe('LSP', function()
client.stop()
end,
on_exit = function(code, signal)
- eq(0, code, 'exit code', fake_lsp_logfile)
- eq(0, signal, 'exit signal', fake_lsp_logfile)
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
end,
settings = {
dummy = 1,
@@ -218,10 +214,12 @@ describe('LSP', function()
})
end)
- it("should set the client's offset_encoding when positionEncoding capability is supported", function()
- clear()
- exec_lua(create_server_definition)
- local result = exec_lua([[
+ it(
+ "should set the client's offset_encoding when positionEncoding capability is supported",
+ function()
+ clear()
+ exec_lua(create_server_definition)
+ local result = exec_lua([[
local server = _create_server({
capabilities = {
positionEncoding = "utf-8"
@@ -243,8 +241,9 @@ describe('LSP', function()
end
return client.offset_encoding
]])
- eq('utf-8', result)
- end)
+ eq('utf-8', result)
+ end
+ )
it('should succeed with manual shutdown', function()
if is_ci() then
@@ -254,68 +253,68 @@ describe('LSP', function()
return
end
local expected_handlers = {
- {NIL, {}, {method="shutdown", bufnr=1, client_id=1}};
- {NIL, {}, {method="test", client_id=1}};
+ { NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1 } },
+ { NIL, {}, { method = 'test', client_id = 1 } },
}
test_rpc_server {
- test_name = "basic_init";
+ test_name = 'basic_init',
on_init = function(client)
eq(0, client.server_capabilities().textDocumentSync.change)
client.request('shutdown')
client.notify('exit')
client.stop()
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
}
end)
it('should detach buffer in response to nvim_buf_detach', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_finish";
+ test_name = 'basic_finish',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
]]
- eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)"))
- eq(true, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)"))
+ eq(true, exec_lua('return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)'))
+ eq(true, exec_lua('return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)'))
exec_lua [[
vim.api.nvim_command(BUFFER.."bwipeout")
]]
- end;
+ end,
on_init = function(_client)
client = _client
client.notify('finish')
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
- exec_lua("return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)")
- eq(false, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)"))
+ exec_lua('return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)')
+ eq(false, exec_lua('return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)'))
client.stop()
end
- end;
+ end,
}
end)
it('should fire autocommands on attach and detach', function()
local client
test_rpc_server {
- test_name = "basic_init";
+ test_name = 'basic_init',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -332,69 +331,75 @@ describe('LSP', function()
end,
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
- eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)"))
+ eq(true, exec_lua('return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)'))
client.notify('finish')
- end;
+ end,
on_handler = function(_, _, ctx)
if ctx.method == 'finish' then
- eq('basic_init', meths.get_var('lsp_attached'))
- exec_lua("return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)")
- eq('basic_init', meths.get_var('lsp_detached'))
+ eq('basic_init', api.nvim_get_var('lsp_attached'))
+ exec_lua('return lsp.buf_detach_client(BUFFER, TEST_RPC_CLIENT_ID)')
+ eq('basic_init', api.nvim_get_var('lsp_detached'))
client.stop()
end
- end;
+ end,
}
end)
it('should set default options on attach', function()
local client
test_rpc_server {
- test_name = "set_defaults_all_capabilities";
+ test_name = 'set_defaults_all_capabilities',
on_init = function(_client)
client = _client
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
]]
- end;
+ end,
on_handler = function(_, _, ctx)
if ctx.method == 'test' then
- eq('v:lua.vim.lsp.tagfunc', get_buf_option("tagfunc"))
- eq('v:lua.vim.lsp.omnifunc', get_buf_option("omnifunc"))
- eq('v:lua.vim.lsp.formatexpr()', get_buf_option("formatexpr"))
- eq('', get_buf_option("keywordprg"))
- eq(true, exec_lua[[
+ eq('v:lua.vim.lsp.tagfunc', get_buf_option('tagfunc'))
+ eq('v:lua.vim.lsp.omnifunc', get_buf_option('omnifunc'))
+ eq('v:lua.vim.lsp.formatexpr()', get_buf_option('formatexpr'))
+ eq('', get_buf_option('keywordprg'))
+ eq(
+ true,
+ exec_lua [[
local keymap
vim.api.nvim_buf_call(BUFFER, function()
keymap = vim.fn.maparg("K", "n", false, true)
end)
return keymap.callback == vim.lsp.buf.hover
- ]])
+ ]]
+ )
client.stop()
end
- end;
+ end,
on_exit = function(_, _)
- eq('', get_buf_option("tagfunc"))
- eq('', get_buf_option("omnifunc"))
- eq('', get_buf_option("formatexpr"))
- eq('', exec_lua[[
+ eq('', get_buf_option('tagfunc'))
+ eq('', get_buf_option('omnifunc'))
+ eq('', get_buf_option('formatexpr'))
+ eq(
+ '',
+ exec_lua [[
local keymap
vim.api.nvim_buf_call(BUFFER, function()
keymap = vim.fn.maparg("K", "n", false, false)
end)
return keymap
- ]])
- end;
+ ]]
+ )
+ end,
}
end)
it('should overwrite options set by ftplugins', function()
local client
test_rpc_server {
- test_name = "set_defaults_all_capabilities";
+ test_name = 'set_defaults_all_capabilities',
on_init = function(_client)
client = _client
exec_lua [[
@@ -406,35 +411,35 @@ describe('LSP', function()
]]
-- Sanity check to ensure that some values are set after setting filetype.
- eq('v:lua.require\'man\'.goto_tag', get_buf_option("tagfunc", "BUFFER_1"))
- eq('xmlcomplete#CompleteTags', get_buf_option("omnifunc", "BUFFER_2"))
- eq('xmlformat#Format()', get_buf_option("formatexpr", "BUFFER_2"))
+ eq("v:lua.require'man'.goto_tag", get_buf_option('tagfunc', 'BUFFER_1'))
+ eq('xmlcomplete#CompleteTags', get_buf_option('omnifunc', 'BUFFER_2'))
+ eq('xmlformat#Format()', get_buf_option('formatexpr', 'BUFFER_2'))
exec_lua [[
lsp.buf_attach_client(BUFFER_1, TEST_RPC_CLIENT_ID)
lsp.buf_attach_client(BUFFER_2, TEST_RPC_CLIENT_ID)
]]
- end;
+ end,
on_handler = function(_, _, ctx)
if ctx.method == 'test' then
- eq('v:lua.vim.lsp.tagfunc', get_buf_option("tagfunc", "BUFFER_1"))
- eq('v:lua.vim.lsp.omnifunc', get_buf_option("omnifunc", "BUFFER_2"))
- eq('v:lua.vim.lsp.formatexpr()', get_buf_option("formatexpr", "BUFFER_2"))
+ eq('v:lua.vim.lsp.tagfunc', get_buf_option('tagfunc', 'BUFFER_1'))
+ eq('v:lua.vim.lsp.omnifunc', get_buf_option('omnifunc', 'BUFFER_2'))
+ eq('v:lua.vim.lsp.formatexpr()', get_buf_option('formatexpr', 'BUFFER_2'))
client.stop()
end
- end;
+ end,
on_exit = function(_, _)
- eq('', get_buf_option("tagfunc", "BUFFER_1"))
- eq('', get_buf_option("omnifunc", "BUFFER_2"))
- eq('', get_buf_option("formatexpr", "BUFFER_2"))
- end;
+ eq('', get_buf_option('tagfunc', 'BUFFER_1'))
+ eq('', get_buf_option('omnifunc', 'BUFFER_2'))
+ eq('', get_buf_option('formatexpr', 'BUFFER_2'))
+ end,
}
end)
it('should not overwrite user-defined options', function()
local client
test_rpc_server {
- test_name = "set_defaults_all_capabilities";
+ test_name = 'set_defaults_all_capabilities',
on_init = function(_client)
client = _client
exec_lua [[
@@ -444,20 +449,20 @@ describe('LSP', function()
vim.api.nvim_set_option_value('formatexpr', 'fex', { buf = BUFFER })
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
]]
- end;
+ end,
on_handler = function(_, _, ctx)
if ctx.method == 'test' then
- eq('tfu', get_buf_option("tagfunc"))
- eq('ofu', get_buf_option("omnifunc"))
- eq('fex', get_buf_option("formatexpr"))
+ eq('tfu', get_buf_option('tagfunc'))
+ eq('ofu', get_buf_option('omnifunc'))
+ eq('fex', get_buf_option('formatexpr'))
client.stop()
end
- end;
+ end,
on_exit = function(_, _)
- eq('tfu', get_buf_option("tagfunc"))
- eq('ofu', get_buf_option("omnifunc"))
- eq('fex', get_buf_option("formatexpr"))
- end;
+ eq('tfu', get_buf_option('tagfunc'))
+ eq('ofu', get_buf_option('omnifunc'))
+ eq('fex', get_buf_option('formatexpr'))
+ end,
}
end)
@@ -481,62 +486,76 @@ describe('LSP', function()
num_attached_after = num_attached_after,
}
]])
- eq(true, result ~= nil, "exec_lua must return result")
+ eq(true, result ~= nil, 'exec_lua must return result')
eq(1, result.num_attached_before)
eq(0, result.num_attached_after)
end)
it('client should return settings via workspace/configuration handler', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, { items = {
- { section = "testSetting1" };
- { section = "testSetting2" };
- { section = "test.Setting3" };
- { section = "test.Setting4" };
- }}, { method="workspace/configuration", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ {
+ NIL,
+ {
+ items = {
+ { section = 'testSetting1' },
+ { section = 'testSetting2' },
+ { section = 'test.Setting3' },
+ { section = 'test.Setting4' },
+ },
+ },
+ { method = 'workspace/configuration', client_id = 1 },
+ },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_workspace_configuration";
+ test_name = 'check_workspace_configuration',
on_init = function(_client)
client = _client
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'start' then
exec_lua([=[
local client = vim.lsp.get_client_by_id(TEST_RPC_CLIENT_ID)
- client.config.settings = {
+ client.settings = {
testSetting1 = true;
testSetting2 = false;
test = {Setting3 = 'nested' };
}]=])
end
if ctx.method == 'workspace/configuration' then
- local server_result = exec_lua([=[
+ local server_result = exec_lua(
+ [=[
local method, params = ...
- return require'vim.lsp.handlers'['workspace/configuration'](err, params, {method=method, client_id=TEST_RPC_CLIENT_ID})]=], ctx.method, result)
+ return require'vim.lsp.handlers'['workspace/configuration'](err, params, {method=method, client_id=TEST_RPC_CLIENT_ID})]=],
+ ctx.method,
+ result
+ )
client.notify('workspace/configuration', server_result)
end
if ctx.method == 'shutdown' then
client.stop()
end
- end;
+ end,
}
end)
- it('workspace/configuration returns NIL per section if client was started without config.settings', function()
- local result = nil
- test_rpc_server {
- test_name = 'basic_init';
- on_init = function(c) c.stop() end,
- on_setup = function()
- result = exec_lua [[
+ it(
+ 'workspace/configuration returns NIL per section if client was started without config.settings',
+ function()
+ local result = nil
+ test_rpc_server {
+ test_name = 'basic_init',
+ on_init = function(c)
+ c.stop()
+ end,
+ on_setup = function()
+ result = exec_lua [[
local result = {
items = {
{section = 'foo'},
@@ -545,52 +564,53 @@ describe('LSP', function()
}
return vim.lsp.handlers['workspace/configuration'](nil, result, {client_id=TEST_RPC_CLIENT_ID})
]]
- end
- }
- eq({ NIL, NIL }, result)
- end)
+ end,
+ }
+ eq({ NIL, NIL }, result)
+ end
+ )
it('should verify capabilities sent', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
}
test_rpc_server {
- test_name = "basic_check_capabilities";
+ test_name = 'basic_check_capabilities',
on_init = function(client)
client.stop()
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
eq(full_kind, client.server_capabilities().textDocumentSync.change)
- eq({includeText = false}, client.server_capabilities().textDocumentSync.save)
+ eq({ includeText = false }, client.server_capabilities().textDocumentSync.save)
eq(false, client.server_capabilities().codeLensProvider)
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
}
end)
it('BufWritePost sends didSave with bool textDocumentSync.save', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "text_document_sync_save_bool";
+ test_name = 'text_document_sync_save_bool',
on_init = function(c)
client = c
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
- if ctx.method == "start" then
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
+ if ctx.method == 'start' then
exec_lua([=[
BUFFER = vim.api.nvim_get_current_buf()
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
@@ -599,7 +619,7 @@ describe('LSP', function()
else
client.stop()
end
- end;
+ end,
}
end)
@@ -664,7 +684,7 @@ describe('LSP', function()
local messages = result.messages
eq('textDocument/willSave', messages[3].method)
eq('textDocument/willSaveWaitUntil', messages[4].method)
- eq({'Hello'}, result.lines)
+ eq({ 'Hello' }, result.lines)
end)
it('saveas sends didOpen if filename changed', function()
@@ -685,8 +705,8 @@ describe('LSP', function()
on_handler = function(err, result, ctx)
eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'start' then
- local tmpfile_old = helpers.tmpname()
- local tmpfile_new = helpers.tmpname()
+ local tmpfile_old = tmpname()
+ local tmpfile_new = tmpname()
os.remove(tmpfile_new)
exec_lua(
[=[
@@ -709,22 +729,22 @@ describe('LSP', function()
it('BufWritePost sends didSave including text if server capability is set', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "text_document_sync_save_includeText";
+ test_name = 'text_document_sync_save_includeText',
on_init = function(c)
client = c
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
- if ctx.method == "start" then
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
+ if ctx.method == 'start' then
exec_lua([=[
BUFFER = vim.api.nvim_get_current_buf()
vim.api.nvim_buf_set_lines(BUFFER, 0, -1, true, {"help me"})
@@ -734,16 +754,16 @@ describe('LSP', function()
else
client.stop()
end
- end;
+ end,
}
end)
it('client.supports_methods() should validate capabilities', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
}
test_rpc_server {
- test_name = "capabilities_for_client_supports_method";
+ test_name = 'capabilities_for_client_supports_method',
on_init = function(client)
client.stop()
local expected_sync_capabilities = {
@@ -761,268 +781,285 @@ describe('LSP', function()
eq(true, client.server_capabilities().codeLensProvider.resolveProvider)
-- known methods for resolved capabilities
- eq(true, client.supports_method("textDocument/hover"))
- eq(false, client.supports_method("textDocument/definition"))
+ eq(true, client.supports_method('textDocument/hover'))
+ eq(false, client.supports_method('textDocument/definition'))
-- unknown methods are assumed to be supported.
- eq(true, client.supports_method("unknown-method"))
- end;
+ eq(true, client.supports_method('unknown-method'))
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
}
end)
it('should not call unsupported_method when trying to call an unsupported method', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
}
test_rpc_server {
- test_name = "capabilities_for_client_supports_method";
+ test_name = 'capabilities_for_client_supports_method',
on_setup = function()
- exec_lua([=[
+ exec_lua([=[
BUFFER = vim.api.nvim_get_current_buf()
lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)
vim.lsp.handlers['textDocument/typeDefinition'] = function() end
]=])
- end;
+ end,
on_init = function(client)
client.stop()
- exec_lua("vim.lsp.buf.type_definition()")
+ exec_lua('vim.lsp.buf.type_definition()')
exec_lua [[
vim.api.nvim_command(BUFFER.."bwipeout")
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
}
end)
- it('should not call unsupported_method when no client and trying to call an unsupported method', function()
- local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- }
- test_rpc_server {
- test_name = "capabilities_for_client_supports_method";
- on_setup = function()
+ it(
+ 'should not call unsupported_method when no client and trying to call an unsupported method',
+ function()
+ local expected_handlers = {
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ }
+ test_rpc_server {
+ test_name = 'capabilities_for_client_supports_method',
+ on_setup = function()
exec_lua([=[
vim.lsp.handlers['textDocument/typeDefinition'] = function() end
]=])
- end;
- on_init = function(client)
- client.stop()
- exec_lua("vim.lsp.buf.type_definition()")
- end;
- on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
- on_handler = function(...)
- eq(table.remove(expected_handlers), {...}, "expected handler")
- end;
- }
- end)
+ end,
+ on_init = function(client)
+ client.stop()
+ exec_lua('vim.lsp.buf.type_definition()')
+ end,
+ on_exit = function(code, signal)
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
+ on_handler = function(...)
+ eq(table.remove(expected_handlers), { ... }, 'expected handler')
+ end,
+ }
+ end
+ )
it('should not forward RequestCancelled to callback', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_forward_request_cancelled";
+ test_name = 'check_forward_request_cancelled',
on_init = function(_client)
- _client.request("error_code_test")
+ _client.request('error_code_test')
client = _client
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- eq(0, #expected_handlers, "did not call expected handler")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ eq(0, #expected_handlers, 'did not call expected handler')
+ end,
on_handler = function(err, _, ctx)
- eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler")
- if ctx.method == 'finish' then client.stop() end
- end;
+ eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
+ if ctx.method == 'finish' then
+ client.stop()
+ end
+ end,
}
end)
it('should forward ContentModified to callback', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
- {{code = -32801}, NIL, {method = "error_code_test", bufnr=1, client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { { code = -32801 }, NIL, { method = 'error_code_test', bufnr = 1, client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_forward_content_modified";
+ test_name = 'check_forward_content_modified',
on_init = function(_client)
- _client.request("error_code_test")
+ _client.request('error_code_test')
client = _client
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- eq(0, #expected_handlers, "did not call expected handler")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ eq(0, #expected_handlers, 'did not call expected handler')
+ end,
on_handler = function(err, _, ctx)
- eq(table.remove(expected_handlers), {err, _, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, _, ctx }, 'expected handler')
-- if ctx.method == 'error_code_test' then client.notify("finish") end
- if ctx.method ~= 'finish' then client.notify('finish') end
- if ctx.method == 'finish' then client.stop() end
- end;
+ if ctx.method ~= 'finish' then
+ client.notify('finish')
+ end
+ if ctx.method == 'finish' then
+ client.stop()
+ end
+ end,
}
end)
it('should track pending requests to the language server', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="slow_request", bufnr=1, client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_pending_request_tracked";
+ test_name = 'check_pending_request_tracked',
on_init = function(_client)
client = _client
- client.request("slow_request")
+ client.request('slow_request')
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
- eq("slow_request", request.method)
- eq("pending", request.type)
- client.notify("release")
- end;
+ eq('slow_request', request.method)
+ eq('pending', request.type)
+ client.notify('release')
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- eq(0, #expected_handlers, "did not call expected handler")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ eq(0, #expected_handlers, 'did not call expected handler')
+ end,
on_handler = function(err, _, ctx)
- eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
if ctx.method == 'slow_request' then
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
eq(NIL, request)
- client.notify("finish")
+ client.notify('finish')
+ end
+ if ctx.method == 'finish' then
+ client.stop()
end
- if ctx.method == 'finish' then client.stop() end
- end;
+ end,
}
end)
it('should track cancel requests to the language server', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_cancel_request_tracked";
+ test_name = 'check_cancel_request_tracked',
on_init = function(_client)
client = _client
- client.request("slow_request")
+ client.request('slow_request')
client.cancel_request(2)
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
- eq("slow_request", request.method)
- eq("cancel", request.type)
- client.notify("release")
- end;
+ eq('slow_request', request.method)
+ eq('cancel', request.type)
+ client.notify('release')
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- eq(0, #expected_handlers, "did not call expected handler")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ eq(0, #expected_handlers, 'did not call expected handler')
+ end,
on_handler = function(err, _, ctx)
- eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
eq(NIL, request)
- if ctx.method == 'finish' then client.stop() end
- end;
+ if ctx.method == 'finish' then
+ client.stop()
+ end
+ end,
}
end)
it('should clear pending and cancel requests on reply', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="slow_request", bufnr=1, client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_tracked_requests_cleared";
+ test_name = 'check_tracked_requests_cleared',
on_init = function(_client)
client = _client
- client.request("slow_request")
+ client.request('slow_request')
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
- eq("slow_request", request.method)
- eq("pending", request.type)
+ eq('slow_request', request.method)
+ eq('pending', request.type)
client.cancel_request(2)
request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
- eq("slow_request", request.method)
- eq("cancel", request.type)
- client.notify("release")
- end;
+ eq('slow_request', request.method)
+ eq('cancel', request.type)
+ client.notify('release')
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- eq(0, #expected_handlers, "did not call expected handler")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ eq(0, #expected_handlers, 'did not call expected handler')
+ end,
on_handler = function(err, _, ctx)
- eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
if ctx.method == 'slow_request' then
local request = exec_lua([=[ return TEST_RPC_CLIENT.requests[2] ]=])
eq(NIL, request)
- client.notify("finish")
+ client.notify('finish')
end
- if ctx.method == 'finish' then client.stop() end
- end;
+ if ctx.method == 'finish' then
+ client.stop()
+ end
+ end,
}
end)
it('should trigger LspRequest autocmd when requests table changes', function()
local expected_handlers = {
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="slow_request", bufnr=1, client_id=1}};
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'slow_request', bufnr = 1, client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "check_tracked_requests_cleared";
+ test_name = 'check_tracked_requests_cleared',
on_init = function(_client)
command('let g:requests = 0')
command('autocmd LspRequest * let g:requests+=1')
client = _client
- client.request("slow_request")
+ client.request('slow_request')
eq(1, eval('g:requests'))
client.cancel_request(2)
eq(2, eval('g:requests'))
- client.notify("release")
- end;
+ client.notify('release')
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- eq(0, #expected_handlers, "did not call expected handler")
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ eq(0, #expected_handlers, 'did not call expected handler')
eq(3, eval('g:requests'))
- end;
+ end,
on_handler = function(err, _, ctx)
- eq(table.remove(expected_handlers), {err, {}, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, {}, ctx }, 'expected handler')
if ctx.method == 'slow_request' then
- client.notify("finish")
+ client.notify('finish')
+ end
+ if ctx.method == 'finish' then
+ client.stop()
end
- if ctx.method == 'finish' then client.stop() end
- end;
+ end,
}
end)
it('should not send didOpen if the buffer closes before init', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_finish";
+ test_name = 'basic_finish',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1031,42 +1068,42 @@ describe('LSP', function()
"123";
})
]]
- eq(1, exec_lua("return TEST_RPC_CLIENT_ID"))
- eq(true, exec_lua("return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)"))
- eq(true, exec_lua("return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)"))
+ eq(1, exec_lua('return TEST_RPC_CLIENT_ID'))
+ eq(true, exec_lua('return lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID)'))
+ eq(true, exec_lua('return lsp.buf_is_attached(BUFFER, TEST_RPC_CLIENT_ID)'))
exec_lua [[
vim.api.nvim_command(BUFFER.."bwipeout")
]]
- end;
+ end,
on_init = function(_client)
client = _client
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
eq(full_kind, client.server_capabilities().textDocumentSync.change)
eq(true, client.server_capabilities().textDocumentSync.openClose)
client.notify('finish')
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body sent attaching before init', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open";
+ test_name = 'basic_check_buffer_open',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1078,7 +1115,7 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_init = function(_client)
client = _client
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1087,32 +1124,32 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID), "Already attached, returns true")
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body sent attaching after init', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open";
+ test_name = 'basic_check_buffer_open',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1121,7 +1158,7 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1130,32 +1167,32 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body and didChange full', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change";
+ test_name = 'basic_check_buffer_open_and_change',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1164,7 +1201,7 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1173,11 +1210,11 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1187,23 +1224,23 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body and didChange full with noeol', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_noeol";
+ test_name = 'basic_check_buffer_open_and_change_noeol',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1213,7 +1250,7 @@ describe('LSP', function()
})
vim.bo[BUFFER].eol = false
]]
- end;
+ end,
on_init = function(_client)
client = _client
local full_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1222,11 +1259,11 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1236,37 +1273,41 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should send correct range for inlay hints with noeol', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {
- method="textDocument/inlayHint",
- params = {
- textDocument = {
- uri = 'file://',
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ {
+ NIL,
+ {},
+ {
+ method = 'textDocument/inlayHint',
+ params = {
+ textDocument = {
+ uri = 'file://',
+ },
+ range = {
+ start = { line = 0, character = 0 },
+ ['end'] = { line = 1, character = 3 },
+ },
},
- range = {
- start = { line = 0, character = 0 },
- ['end'] = { line = 1, character = 3 },
- }
+ bufnr = 2,
+ client_id = 1,
},
- bufnr=2,
- client_id=1,
- }};
- {NIL, {}, {method="start", client_id=1}};
+ },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "inlay_hint";
+ test_name = 'inlay_hint',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1276,18 +1317,18 @@ describe('LSP', function()
})
vim.bo[BUFFER].eol = false
]]
- end;
+ end,
on_init = function(_client)
client = _client
eq(true, client.supports_method('textDocument/inlayHint'))
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1297,26 +1338,26 @@ describe('LSP', function()
if ctx.method == 'textDocument/inlayHint' then
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body and didChange incremental', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_incremental";
+ test_name = 'basic_check_buffer_open_and_change_incremental',
options = {
allow_incremental_sync = true,
- };
+ },
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1325,20 +1366,21 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
- local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
+ local sync_kind =
+ exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
eq(sync_kind, client.server_capabilities().textDocumentSync.change)
eq(true, client.server_capabilities().textDocumentSync.openClose)
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1348,26 +1390,26 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body and didChange incremental with debounce', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_incremental";
+ test_name = 'basic_check_buffer_open_and_change_incremental',
options = {
allow_incremental_sync = true,
- debounce_text_changes = 5
- };
+ debounce_text_changes = 5,
+ },
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1376,20 +1418,21 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
- local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
+ local sync_kind =
+ exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
eq(sync_kind, client.server_capabilities().textDocumentSync.change)
eq(true, client.server_capabilities().textDocumentSync.openClose)
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1399,24 +1442,24 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
-- TODO(askhan) we don't support full for now, so we can disable these tests.
pending('should check the body and didChange incremental normal mode editing', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", bufnr=1, client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', bufnr = 1, client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_incremental_editing";
+ test_name = 'basic_check_buffer_open_and_change_incremental_editing',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1425,42 +1468,43 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
- local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
+ local sync_kind =
+ exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Incremental")
eq(sync_kind, client.server_capabilities().textDocumentSync.change)
eq(true, client.server_capabilities().textDocumentSync.openClose)
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
- helpers.command("normal! 1Go")
+ helpers.command('normal! 1Go')
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body and didChange full with 2 changes', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_multi";
+ test_name = 'basic_check_buffer_open_and_change_multi',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1469,7 +1513,7 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1478,11 +1522,11 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
@@ -1495,23 +1539,23 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
it('should check the body and didChange full lifecycle', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_check_buffer_open_and_change_multi_and_close";
+ test_name = 'basic_check_buffer_open_and_change_multi_and_close',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1520,7 +1564,7 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
local sync_kind = exec_lua("return require'vim.lsp.protocol'.TextDocumentSyncKind.Full")
@@ -1529,12 +1573,12 @@ describe('LSP', function()
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
- on_handler = function(err, result,ctx)
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
+ on_handler = function(err, result, ctx)
if ctx.method == 'start' then
exec_lua [[
vim.api.nvim_buf_set_lines(BUFFER, 1, 2, false, {
@@ -1547,55 +1591,58 @@ describe('LSP', function()
]]
client.notify('finish')
end
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
end)
- describe("parsing tests", function()
+ describe('parsing tests', function()
it('should handle invalid content-length correctly', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "invalid_header";
- on_setup = function()
- end;
+ test_name = 'invalid_header',
+ on_setup = function() end,
on_init = function(_client)
client = _client
client.stop(true)
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
- end;
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
+ end,
}
end)
it('should not trim vim.NIL from the end of a list', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="finish", client_id=1}};
- {NIL,{
- arguments = { "EXTRACT_METHOD", {metadata = {}}, 3, 0, 6123, NIL },
- command = "refactor.perform",
- title = "EXTRACT_METHOD"
- }, {method="workspace/executeCommand", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'finish', client_id = 1 } },
+ {
+ NIL,
+ {
+ arguments = { 'EXTRACT_METHOD', { metadata = {} }, 3, 0, 6123, NIL },
+ command = 'refactor.perform',
+ title = 'EXTRACT_METHOD',
+ },
+ { method = 'workspace/executeCommand', client_id = 1 },
+ },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "decode_nil";
+ test_name = 'decode_nil',
on_setup = function()
exec_lua [[
BUFFER = vim.api.nvim_create_buf(false, true)
@@ -1604,23 +1651,23 @@ describe('LSP', function()
"123";
})
]]
- end;
+ end,
on_init = function(_client)
client = _client
exec_lua [[
assert(lsp.buf_attach_client(BUFFER, TEST_RPC_CLIENT_ID))
]]
- end;
+ end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
on_handler = function(err, result, ctx)
- eq(table.remove(expected_handlers), {err, result, ctx}, "expected handler")
+ eq(table.remove(expected_handlers), { err, result, ctx }, 'expected handler')
if ctx.method == 'finish' then
client.stop()
end
- end;
+ end,
}
end)
end)
@@ -1634,10 +1681,10 @@ describe('LSP', function()
local function make_edit(y_0, x_0, y_1, x_1, text)
return {
range = {
- start = { line = y_0, character = x_0 };
- ["end"] = { line = y_1, character = x_1 };
- };
- newText = type(text) == 'table' and table.concat(text, '\n') or (text or "");
+ start = { line = y_0, character = x_0 },
+ ['end'] = { line = y_1, character = x_1 },
+ },
+ newText = type(text) == 'table' and table.concat(text, '\n') or (text or ''),
}
end
@@ -1652,121 +1699,121 @@ describe('LSP', function()
end)
it('applies simple edits', function()
local edits = {
- make_edit(0, 0, 0, 0, {"123"});
- make_edit(1, 0, 1, 1, {"2"});
- make_edit(2, 0, 2, 2, {"3"});
- make_edit(3, 2, 3, 4, {""});
+ make_edit(0, 0, 0, 0, { '123' }),
+ make_edit(1, 0, 1, 1, { '2' }),
+ make_edit(2, 0, 2, 2, { '3' }),
+ make_edit(3, 2, 3, 4, { '' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- '123First line of text';
- '2econd line of text';
- '3ird line of text';
- 'Foth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ '123First line of text',
+ '2econd line of text',
+ '3ird line of text',
+ 'Foth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
end)
it('applies complex edits', function()
local edits = {
- make_edit(0, 0, 0, 0, {"", "12"});
- make_edit(0, 0, 0, 0, {"3", "foo"});
- make_edit(0, 1, 0, 1, {"bar", "123"});
- make_edit(0, #"First ", 0, #"First line of text", {"guy"});
- make_edit(1, 0, 1, #'Second', {"baz"});
- make_edit(2, #'Th', 2, #"Third", {"e next"});
- make_edit(3, #'', 3, #"Fourth", {"another line of text", "before this"});
- make_edit(3, #'Fourth', 3, #"Fourth line of text", {"!"});
+ make_edit(0, 0, 0, 0, { '', '12' }),
+ make_edit(0, 0, 0, 0, { '3', 'foo' }),
+ make_edit(0, 1, 0, 1, { 'bar', '123' }),
+ make_edit(0, #'First ', 0, #'First line of text', { 'guy' }),
+ make_edit(1, 0, 1, #'Second', { 'baz' }),
+ make_edit(2, #'Th', 2, #'Third', { 'e next' }),
+ make_edit(3, #'', 3, #'Fourth', { 'another line of text', 'before this' }),
+ make_edit(3, #'Fourth', 3, #'Fourth line of text', { '!' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- '';
- '123';
- 'fooFbar';
- '123irst guy';
- 'baz line of text';
- 'The next line of text';
- 'another line of text';
- 'before this!';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ '',
+ '123',
+ 'fooFbar',
+ '123irst guy',
+ 'baz line of text',
+ 'The next line of text',
+ 'another line of text',
+ 'before this!',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
end)
it('applies complex edits (reversed range)', function()
local edits = {
- make_edit(0, 0, 0, 0, {"", "12"});
- make_edit(0, 0, 0, 0, {"3", "foo"});
- make_edit(0, 1, 0, 1, {"bar", "123"});
- make_edit(0, #"First line of text", 0, #"First ", {"guy"});
- make_edit(1, #'Second', 1, 0, {"baz"});
- make_edit(2, #"Third", 2, #'Th', {"e next"});
- make_edit(3, #"Fourth", 3, #'', {"another line of text", "before this"});
- make_edit(3, #"Fourth line of text", 3, #'Fourth', {"!"});
+ make_edit(0, 0, 0, 0, { '', '12' }),
+ make_edit(0, 0, 0, 0, { '3', 'foo' }),
+ make_edit(0, 1, 0, 1, { 'bar', '123' }),
+ make_edit(0, #'First line of text', 0, #'First ', { 'guy' }),
+ make_edit(1, #'Second', 1, 0, { 'baz' }),
+ make_edit(2, #'Third', 2, #'Th', { 'e next' }),
+ make_edit(3, #'Fourth', 3, #'', { 'another line of text', 'before this' }),
+ make_edit(3, #'Fourth line of text', 3, #'Fourth', { '!' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- '';
- '123';
- 'fooFbar';
- '123irst guy';
- 'baz line of text';
- 'The next line of text';
- 'another line of text';
- 'before this!';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ '',
+ '123',
+ 'fooFbar',
+ '123irst guy',
+ 'baz line of text',
+ 'The next line of text',
+ 'another line of text',
+ 'before this!',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
end)
it('applies non-ASCII characters edits', function()
local edits = {
- make_edit(4, 3, 4, 4, {"ä"});
+ make_edit(4, 3, 4, 4, { 'ä' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Second line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å ä ɧ 汉语 ↥ 🤦 🦄';
+ 'First line of text',
+ 'Second line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å ä ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
end)
it('applies text edits at the end of the document', function()
local edits = {
- make_edit(5, 0, 5, 0, "foobar");
+ make_edit(5, 0, 5, 0, 'foobar'),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Second line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
- 'foobar';
+ 'First line of text',
+ 'Second line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
+ 'foobar',
}, buf_lines(1))
end)
it('applies multiple text edits at the end of the document', function()
local edits = {
- make_edit(4, 0, 5, 0, "");
- make_edit(5, 0, 5, 0, "foobar");
+ make_edit(4, 0, 5, 0, ''),
+ make_edit(5, 0, 5, 0, 'foobar'),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Second line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'foobar';
+ 'First line of text',
+ 'Second line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'foobar',
}, buf_lines(1))
end)
it('it restores marks', function()
local edits = {
- make_edit(1, 0, 2, 5, "foobar");
- make_edit(4, 0, 5, 0, "barfoo");
+ make_edit(1, 0, 2, 5, 'foobar'),
+ make_edit(4, 0, 5, 0, 'barfoo'),
}
eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 2, 1, {})'))
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'foobar line of text';
- 'Fourth line of text';
- 'barfoo';
+ 'First line of text',
+ 'foobar line of text',
+ 'Fourth line of text',
+ 'barfoo',
}, buf_lines(1))
local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")')
eq({ 2, 1 }, mark)
@@ -1774,16 +1821,16 @@ describe('LSP', function()
it('it restores marks to last valid col', function()
local edits = {
- make_edit(1, 0, 2, 15, "foobar");
- make_edit(4, 0, 5, 0, "barfoo");
+ make_edit(1, 0, 2, 15, 'foobar'),
+ make_edit(4, 0, 5, 0, 'barfoo'),
}
eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 2, 10, {})'))
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'foobarext';
- 'Fourth line of text';
- 'barfoo';
+ 'First line of text',
+ 'foobarext',
+ 'Fourth line of text',
+ 'barfoo',
}, buf_lines(1))
local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")')
eq({ 2, 9 }, mark)
@@ -1791,138 +1838,138 @@ describe('LSP', function()
it('it restores marks to last valid line', function()
local edits = {
- make_edit(1, 0, 4, 5, "foobar");
- make_edit(4, 0, 5, 0, "barfoo");
+ make_edit(1, 0, 4, 5, 'foobar'),
+ make_edit(4, 0, 5, 0, 'barfoo'),
}
eq(true, exec_lua('return vim.api.nvim_buf_set_mark(1, "a", 4, 1, {})'))
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'foobaro';
+ 'First line of text',
+ 'foobaro',
}, buf_lines(1))
local mark = exec_lua('return vim.api.nvim_buf_get_mark(1, "a")')
eq({ 2, 1 }, mark)
end)
describe('cursor position', function()
- it('don\'t fix the cursor if the range contains the cursor', function()
- funcs.nvim_win_set_cursor(0, { 2, 6 })
+ it("don't fix the cursor if the range contains the cursor", function()
+ fn.nvim_win_set_cursor(0, { 2, 6 })
local edits = {
- make_edit(1, 0, 1, 19, 'Second line of text')
+ make_edit(1, 0, 1, 19, 'Second line of text'),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Second line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ 'First line of text',
+ 'Second line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 2, 6 }, funcs.nvim_win_get_cursor(0))
+ eq({ 2, 6 }, fn.nvim_win_get_cursor(0))
end)
it('fix the cursor to the valid col if the content was removed', function()
- funcs.nvim_win_set_cursor(0, { 2, 6 })
+ fn.nvim_win_set_cursor(0, { 2, 6 })
local edits = {
make_edit(1, 0, 1, 6, ''),
- make_edit(1, 6, 1, 19, '')
+ make_edit(1, 6, 1, 19, ''),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- '';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ 'First line of text',
+ '',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 2, 0 }, funcs.nvim_win_get_cursor(0))
+ eq({ 2, 0 }, fn.nvim_win_get_cursor(0))
end)
it('fix the cursor to the valid row if the content was removed', function()
- funcs.nvim_win_set_cursor(0, { 2, 6 })
+ fn.nvim_win_set_cursor(0, { 2, 6 })
local edits = {
make_edit(1, 0, 1, 6, ''),
- make_edit(0, 18, 5, 0, '')
+ make_edit(0, 18, 5, 0, ''),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
+ 'First line of text',
}, buf_lines(1))
- eq({ 1, 17 }, funcs.nvim_win_get_cursor(0))
+ eq({ 1, 17 }, fn.nvim_win_get_cursor(0))
end)
it('fix the cursor row', function()
- funcs.nvim_win_set_cursor(0, { 3, 0 })
+ fn.nvim_win_set_cursor(0, { 3, 0 })
local edits = {
- make_edit(1, 0, 2, 0, '')
+ make_edit(1, 0, 2, 0, ''),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ 'First line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 2, 0 }, funcs.nvim_win_get_cursor(0))
+ eq({ 2, 0 }, fn.nvim_win_get_cursor(0))
end)
it('fix the cursor col', function()
-- append empty last line. See #22636
- exec_lua('vim.api.nvim_buf_set_lines(...)', 1, -1, -1, true, {''})
+ exec_lua('vim.api.nvim_buf_set_lines(...)', 1, -1, -1, true, { '' })
- funcs.nvim_win_set_cursor(0, { 2, 11 })
+ fn.nvim_win_set_cursor(0, { 2, 11 })
local edits = {
- make_edit(1, 7, 1, 11, '')
+ make_edit(1, 7, 1, 11, ''),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Second of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
- '';
+ 'First line of text',
+ 'Second of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
+ '',
}, buf_lines(1))
- eq({ 2, 7 }, funcs.nvim_win_get_cursor(0))
+ eq({ 2, 7 }, fn.nvim_win_get_cursor(0))
end)
it('fix the cursor row and col', function()
- funcs.nvim_win_set_cursor(0, { 2, 12 })
+ fn.nvim_win_set_cursor(0, { 2, 12 })
local edits = {
- make_edit(0, 11, 1, 12, '')
+ make_edit(0, 11, 1, 12, ''),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
eq({
- 'First line of text';
- 'Third line of text';
- 'Fourth line of text';
- 'å å ɧ 汉语 ↥ 🤦 🦄';
+ 'First line of text',
+ 'Third line of text',
+ 'Fourth line of text',
+ 'å å ɧ 汉语 ↥ 🤦 🦄',
}, buf_lines(1))
- eq({ 1, 11 }, funcs.nvim_win_get_cursor(0))
+ eq({ 1, 11 }, fn.nvim_win_get_cursor(0))
end)
end)
describe('with LSP end line after what Vim considers to be the end line', function()
it('applies edits when the last linebreak is considered a new line', function()
local edits = {
- make_edit(0, 0, 5, 0, {"All replaced"});
+ make_edit(0, 0, 5, 0, { 'All replaced' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
- eq({'All replaced'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
+ eq({ 'All replaced' }, buf_lines(1))
end)
- it('applies edits when the end line is 2 larger than vim\'s', function()
+ it("applies edits when the end line is 2 larger than vim's", function()
local edits = {
- make_edit(0, 0, 6, 0, {"All replaced"});
+ make_edit(0, 0, 6, 0, { 'All replaced' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
- eq({'All replaced'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
+ eq({ 'All replaced' }, buf_lines(1))
end)
it('applies edits with a column offset', function()
local edits = {
- make_edit(0, 0, 5, 2, {"All replaced"});
+ make_edit(0, 0, 5, 2, { 'All replaced' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-16")
- eq({'All replaced'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-16')
+ eq({ 'All replaced' }, buf_lines(1))
end)
end)
end)
@@ -1936,33 +1983,39 @@ describe('LSP', function()
describe('with LSP end column out of bounds and start column at 0', function()
it('applies edits at the end of the buffer', function()
local edits = {
- make_edit(0, 0, 1, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'});
+ make_edit(0, 0, 1, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8")
- eq({'#include "whatever.h"', '#include <algorithm>'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8')
+ eq({ '#include "whatever.h"', '#include <algorithm>' }, buf_lines(1))
end)
it('applies edits in the middle of the buffer', function()
local edits = {
- make_edit(0, 0, 0, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'});
+ make_edit(0, 0, 0, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8")
- eq({'#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8')
+ eq(
+ { '#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char' },
+ buf_lines(1)
+ )
end)
end)
describe('with LSP end column out of bounds and start column NOT at 0', function()
it('applies edits at the end of the buffer', function()
local edits = {
- make_edit(0, 2, 1, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'});
+ make_edit(0, 2, 1, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8")
- eq({'Te#include "whatever.h"', '#include <algorithm>'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8')
+ eq({ 'Te#include "whatever.h"', '#include <algorithm>' }, buf_lines(1))
end)
it('applies edits in the middle of the buffer', function()
local edits = {
- make_edit(0, 2, 0, 22, {'#include "whatever.h"\r\n#include <algorithm>\r'});
+ make_edit(0, 2, 0, 22, { '#include "whatever.h"\r\n#include <algorithm>\r' }),
}
- exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, "utf-8")
- eq({'Te#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char'}, buf_lines(1))
+ exec_lua('vim.lsp.util.apply_text_edits(...)', edits, 1, 'utf-8')
+ eq(
+ { 'Te#include "whatever.h"', '#include <algorithm>', 'Test line two 21 char' },
+ buf_lines(1)
+ )
end)
end)
end)
@@ -1972,12 +2025,12 @@ describe('LSP', function()
local text_document_edit = function(editVersion)
return {
edits = {
- make_edit(0, 0, 0, 3, "First ↥ 🤦 🦄")
+ make_edit(0, 0, 0, 3, 'First ↥ 🤦 🦄'),
},
textDocument = {
- uri = "file:///fake/uri";
- version = editVersion
- }
+ uri = 'file:///fake/uri',
+ version = editVersion,
+ },
}
end
before_each(function()
@@ -1991,49 +2044,63 @@ describe('LSP', function()
it('correctly goes ahead with the edit if all is normal', function()
exec_lua("vim.lsp.util.apply_text_document_edit(..., nil, 'utf-16')", text_document_edit(5))
eq({
- 'First ↥ 🤦 🦄 line of text';
- '2nd line of 语text';
+ 'First ↥ 🤦 🦄 line of text',
+ '2nd line of 语text',
}, buf_lines(target_bufnr))
end)
it('always accepts edit with version = 0', function()
- exec_lua([[
+ exec_lua(
+ [[
local args = {...}
local bufnr = select(1, ...)
local text_edit = select(2, ...)
vim.lsp.util.buf_versions[bufnr] = 10
vim.lsp.util.apply_text_document_edit(text_edit, nil, 'utf-16')
- ]], target_bufnr, text_document_edit(0))
+ ]],
+ target_bufnr,
+ text_document_edit(0)
+ )
eq({
- 'First ↥ 🤦 🦄 line of text';
- '2nd line of 语text';
+ 'First ↥ 🤦 🦄 line of text',
+ '2nd line of 语text',
}, buf_lines(target_bufnr))
end)
it('skips the edit if the version of the edit is behind the local buffer ', function()
local apply_edit_mocking_current_version = function(edit, versionedBuf)
- exec_lua([[
+ exec_lua(
+ [[
local args = {...}
local versionedBuf = args[2]
vim.lsp.util.buf_versions[versionedBuf.bufnr] = versionedBuf.currentVersion
vim.lsp.util.apply_text_document_edit(args[1], nil, 'utf-16')
- ]], edit, versionedBuf)
+ ]],
+ edit,
+ versionedBuf
+ )
end
local baseText = {
- '1st line of text';
- '2nd line of 语text';
+ '1st line of text',
+ '2nd line of 语text',
}
eq(baseText, buf_lines(target_bufnr))
-- Apply an edit for an old version, should skip
- apply_edit_mocking_current_version(text_document_edit(2), {currentVersion=7; bufnr=target_bufnr})
+ apply_edit_mocking_current_version(
+ text_document_edit(2),
+ { currentVersion = 7, bufnr = target_bufnr }
+ )
eq(baseText, buf_lines(target_bufnr)) -- no change
-- Sanity check that next version to current does apply change
- apply_edit_mocking_current_version(text_document_edit(8), {currentVersion=7; bufnr=target_bufnr})
+ apply_edit_mocking_current_version(
+ text_document_edit(8),
+ { currentVersion = 7, bufnr = target_bufnr }
+ )
eq({
- 'First ↥ 🤦 🦄 line of text';
- '2nd line of 语text';
+ 'First ↥ 🤦 🦄 line of text',
+ '2nd line of 语text',
}, buf_lines(target_bufnr))
end)
end)
@@ -2041,34 +2108,37 @@ describe('LSP', function()
describe('workspace_apply_edit', function()
it('workspace/applyEdit returns ApplyWorkspaceEditResponse', function()
local expected_handlers = {
- {NIL, {}, {method="test", client_id=1}};
+ { NIL, {}, { method = 'test', client_id = 1 } },
}
test_rpc_server {
- test_name = "basic_init";
+ test_name = 'basic_init',
on_init = function(client, _)
client.stop()
- end;
+ end,
-- If the program timed out, then code will be nil.
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
-- Note that NIL must be used here.
-- on_handler(err, method, result, client_id)
on_handler = function(...)
local expected = {
- applied = true;
- failureReason = nil;
+ applied = true,
+ failureReason = nil,
}
- eq(expected, exec_lua [[
+ eq(
+ expected,
+ exec_lua [[
local apply_edit = {
label = nil;
edit = {};
}
return vim.lsp.handlers['workspace/applyEdit'](nil, apply_edit, {client_id = TEST_RPC_CLIENT_ID})
- ]])
- eq(table.remove(expected_handlers), {...})
- end;
+ ]]
+ )
+ eq(table.remove(expected_handlers), { ... })
+ end,
}
end)
end)
@@ -2078,12 +2148,12 @@ describe('LSP', function()
return {
edits = {
-- NOTE: This is a hack if you have a line longer than 1000 it won't replace it
- make_edit(row, 0, row, 1000, new_line)
+ make_edit(row, 0, row, 1000, new_line),
},
textDocument = {
- uri = "file:///fake/uri";
- version = editVersion
- }
+ uri = 'file:///fake/uri',
+ version = editVersion,
+ },
}
end
@@ -2091,7 +2161,7 @@ describe('LSP', function()
-- We should not stop applying the edits
local make_workspace_edit = function(changes)
return {
- documentChanges = changes
+ documentChanges = changes,
}
end
@@ -2127,7 +2197,7 @@ describe('LSP', function()
it('apply_workspace_edit applies a single edit', function()
local new_lines = {
- "First Line",
+ 'First Line',
}
local edits = {}
@@ -2135,10 +2205,13 @@ describe('LSP', function()
table.insert(edits, replace_line_edit(row - 1, line, changedtick))
end
- eq({
- "First Line",
- "Original Line #2",
- }, exec_lua([[
+ eq(
+ {
+ 'First Line',
+ 'Original Line #2',
+ },
+ exec_lua(
+ [[
local args = {...}
local workspace_edits = args[1]
local target_bufnr = args[2]
@@ -2146,13 +2219,17 @@ describe('LSP', function()
vim.lsp.util.apply_workspace_edit(workspace_edits, 'utf-16')
return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false)
- ]], make_workspace_edit(edits), target_bufnr))
+ ]],
+ make_workspace_edit(edits),
+ target_bufnr
+ )
+ )
end)
it('apply_workspace_edit applies multiple edits', function()
local new_lines = {
- "First Line",
- "Second Line",
+ 'First Line',
+ 'Second Line',
}
local edits = {}
@@ -2160,7 +2237,10 @@ describe('LSP', function()
table.insert(edits, replace_line_edit(row - 1, line, changedtick))
end
- eq(new_lines, exec_lua([[
+ eq(
+ new_lines,
+ exec_lua(
+ [[
local args = {...}
local workspace_edits = args[1]
local target_bufnr = args[2]
@@ -2168,10 +2248,14 @@ describe('LSP', function()
vim.lsp.util.apply_workspace_edit(workspace_edits, 'utf-16')
return vim.api.nvim_buf_get_lines(target_bufnr, 0, -1, false)
- ]], make_workspace_edit(edits), target_bufnr))
+ ]],
+ make_workspace_edit(edits),
+ target_bufnr
+ )
+ )
end)
it('Supports file creation with CreateFile payload', function()
- local tmpfile = helpers.tmpname()
+ local tmpfile = tmpname()
os.remove(tmpfile) -- Should not exist, only interested in a tmpname
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
local edit = {
@@ -2180,29 +2264,32 @@ describe('LSP', function()
kind = 'create',
uri = uri,
},
- }
+ },
}
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
end)
- it('Supports file creation in folder that needs to be created with CreateFile payload', function()
- local tmpfile = helpers.tmpname()
- os.remove(tmpfile) -- Should not exist, only interested in a tmpname
- tmpfile = tmpfile .. '/dummy/x/'
- local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
- local edit = {
- documentChanges = {
- {
- kind = 'create',
- uri = uri,
+ it(
+ 'Supports file creation in folder that needs to be created with CreateFile payload',
+ function()
+ local tmpfile = tmpname()
+ os.remove(tmpfile) -- Should not exist, only interested in a tmpname
+ tmpfile = tmpfile .. '/dummy/x/'
+ local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
+ local edit = {
+ documentChanges = {
+ {
+ kind = 'create',
+ uri = uri,
+ },
},
}
- }
- exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
- end)
+ exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
+ eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
+ end
+ )
it('createFile does not touch file if it exists and ignoreIfExists is set', function()
- local tmpfile = helpers.tmpname()
+ local tmpfile = tmpname()
write_file(tmpfile, 'Dummy content')
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
local edit = {
@@ -2214,14 +2301,14 @@ describe('LSP', function()
ignoreIfExists = true,
},
},
- }
+ },
}
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
eq('Dummy content', read_file(tmpfile))
end)
it('createFile overrides file if overwrite is set', function()
- local tmpfile = helpers.tmpname()
+ local tmpfile = tmpname()
write_file(tmpfile, 'Dummy content')
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
local edit = {
@@ -2234,35 +2321,38 @@ describe('LSP', function()
ignoreIfExists = true, -- overwrite must win over ignoreIfExists
},
},
- }
+ },
}
exec_lua('vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16')
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
eq('', read_file(tmpfile))
end)
it('DeleteFile delete file and buffer', function()
- local tmpfile = helpers.tmpname()
+ local tmpfile = tmpname()
write_file(tmpfile, 'Be gone')
- local uri = exec_lua([[
+ local uri = exec_lua(
+ [[
local fname = select(1, ...)
local bufnr = vim.fn.bufadd(fname)
vim.fn.bufload(bufnr)
return vim.uri_from_fname(fname)
- ]], tmpfile)
+ ]],
+ tmpfile
+ )
local edit = {
documentChanges = {
{
kind = 'delete',
uri = uri,
- }
- }
+ },
+ },
}
eq(true, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit, 'utf-16'))
eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
eq(false, exec_lua('return vim.api.nvim_buf_is_loaded(vim.fn.bufadd(...))', tmpfile))
end)
it('DeleteFile fails if file does not exist and ignoreIfNotExists is false', function()
- local tmpfile = helpers.tmpname()
+ local tmpfile = tmpname()
os.remove(tmpfile)
local uri = exec_lua('return vim.uri_from_fname(...)', tmpfile)
local edit = {
@@ -2272,9 +2362,9 @@ describe('LSP', function()
uri = uri,
options = {
ignoreIfNotExists = false,
- }
- }
- }
+ },
+ },
+ },
}
eq(false, pcall(exec_lua, 'vim.lsp.util.apply_workspace_edit(...)', edit))
eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', tmpfile))
@@ -2285,46 +2375,36 @@ describe('LSP', function()
local pathsep = helpers.get_pathsep()
it('Can rename an existing file', function()
- local old = helpers.tmpname()
+ local old = tmpname()
write_file(old, 'Test content')
- local new = helpers.tmpname()
- os.remove(new) -- only reserve the name, file must not exist for the test scenario
- local lines = exec_lua([[
+ local new = tmpname()
+ os.remove(new) -- only reserve the name, file must not exist for the test scenario
+ local lines = exec_lua(
+ [[
local old = select(1, ...)
local new = select(2, ...)
+ local old_bufnr = vim.fn.bufadd(old)
+ vim.fn.bufload(old_bufnr)
vim.lsp.util.rename(old, new)
-
- -- after rename the target file must have the contents of the source file
- local bufnr = vim.fn.bufadd(new)
- vim.fn.bufload(new)
- return vim.api.nvim_buf_get_lines(bufnr, 0, -1, true)
- ]], old, new)
- eq({'Test content'}, lines)
+ -- the existing buffer is renamed in-place and its contents is kept
+ local new_bufnr = vim.fn.bufadd(new)
+ vim.fn.bufload(new_bufnr)
+ return (old_bufnr == new_bufnr) and vim.api.nvim_buf_get_lines(new_bufnr, 0, -1, true)
+ ]],
+ old,
+ new
+ )
+ eq({ 'Test content' }, lines)
local exists = exec_lua('return vim.uv.fs_stat(...) ~= nil', old)
eq(false, exists)
exists = exec_lua('return vim.uv.fs_stat(...) ~= nil', new)
eq(true, exists)
os.remove(new)
end)
- it("Kills old buffer after renaming an existing file", function()
- local old = helpers.tmpname()
- write_file(old, 'Test content')
- local new = helpers.tmpname()
- os.remove(new) -- only reserve the name, file must not exist for the test scenario
- local lines = exec_lua([[
- local old = select(1, ...)
- local oldbufnr = vim.fn.bufadd(old)
- local new = select(2, ...)
- vim.lsp.util.rename(old, new)
- return vim.fn.bufloaded(oldbufnr)
- ]], old, new)
- eq(0, lines)
- os.remove(new)
- end)
it('Can rename a directory', function()
-- only reserve the name, file must not exist for the test scenario
- local old_dir = helpers.tmpname()
- local new_dir = helpers.tmpname()
+ local old_dir = tmpname()
+ local new_dir = tmpname()
os.remove(old_dir)
os.remove(new_dir)
@@ -2333,64 +2413,211 @@ describe('LSP', function()
local file = 'file.txt'
write_file(old_dir .. pathsep .. file, 'Test content')
- local lines = exec_lua([[
+ local lines = exec_lua(
+ [[
local old_dir = select(1, ...)
local new_dir = select(2, ...)
- local pathsep = select(3, ...)
- local oldbufnr = vim.fn.bufadd(old_dir .. pathsep .. 'file')
-
+ local pathsep = select(3, ...)
+ local file = select(4, ...)
+ local old_bufnr = vim.fn.bufadd(old_dir .. pathsep .. file)
+ vim.fn.bufload(old_bufnr)
vim.lsp.util.rename(old_dir, new_dir)
- return vim.fn.bufloaded(oldbufnr)
- ]], old_dir, new_dir, pathsep)
- eq(0, lines)
+ -- the existing buffer is renamed in-place and its contents is kept
+ local new_bufnr = vim.fn.bufadd(new_dir .. pathsep .. file)
+ vim.fn.bufload(new_bufnr)
+ return (old_bufnr == new_bufnr) and vim.api.nvim_buf_get_lines(new_bufnr, 0, -1, true)
+ ]],
+ old_dir,
+ new_dir,
+ pathsep,
+ file
+ )
+ eq({ 'Test content' }, lines)
eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old_dir))
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new_dir))
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new_dir .. pathsep .. file))
- eq('Test content', read_file(new_dir .. pathsep .. file))
os.remove(new_dir)
end)
- it('Does not rename file if target exists and ignoreIfExists is set or overwrite is false', function()
- local old = helpers.tmpname()
- write_file(old, 'Old File')
- local new = helpers.tmpname()
- write_file(new, 'New file')
+ it('Does not touch buffers that do not match path prefix', function()
+ local old = tmpname()
+ local new = tmpname()
+ os.remove(old)
+ os.remove(new)
+ helpers.mkdir_p(old)
- exec_lua([[
+ local result = exec_lua(
+ [[
+ local old = select(1, ...)
+ local new = select(2, ...)
+
+ local old_prefixed = 'explorer://' .. old
+ local old_suffixed = old .. '.bak'
+ local new_prefixed = 'explorer://' .. new
+ local new_suffixed = new .. '.bak'
+
+ local old_prefixed_buf = vim.fn.bufadd(old_prefixed)
+ local old_suffixed_buf = vim.fn.bufadd(old_suffixed)
+ local new_prefixed_buf = vim.fn.bufadd(new_prefixed)
+ local new_suffixed_buf = vim.fn.bufadd(new_suffixed)
+
+ vim.lsp.util.rename(old, new)
+
+ return
+ vim.api.nvim_buf_is_valid(old_prefixed_buf) and
+ vim.api.nvim_buf_is_valid(old_suffixed_buf) and
+ vim.api.nvim_buf_is_valid(new_prefixed_buf) and
+ vim.api.nvim_buf_is_valid(new_suffixed_buf) and
+ vim.api.nvim_buf_get_name(old_prefixed_buf) == old_prefixed and
+ vim.api.nvim_buf_get_name(old_suffixed_buf) == old_suffixed and
+ vim.api.nvim_buf_get_name(new_prefixed_buf) == new_prefixed and
+ vim.api.nvim_buf_get_name(new_suffixed_buf) == new_suffixed
+ ]],
+ old,
+ new
+ )
+ eq(true, result)
+
+ os.remove(new)
+ end)
+ it(
+ 'Does not rename file if target exists and ignoreIfExists is set or overwrite is false',
+ function()
+ local old = tmpname()
+ write_file(old, 'Old File')
+ local new = tmpname()
+ write_file(new, 'New file')
+
+ exec_lua(
+ [[
local old = select(1, ...)
local new = select(2, ...)
vim.lsp.util.rename(old, new, { ignoreIfExists = true })
- ]], old, new)
+ ]],
+ old,
+ new
+ )
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
- eq('New file', read_file(new))
+ eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
+ eq('New file', read_file(new))
- exec_lua([[
+ exec_lua(
+ [[
local old = select(1, ...)
local new = select(2, ...)
vim.lsp.util.rename(old, new, { overwrite = false })
- ]], old, new)
+ ]],
+ old,
+ new
+ )
- eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
- eq('New file', read_file(new))
+ eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
+ eq('New file', read_file(new))
+ end
+ )
+ it('Maintains undo information for loaded buffer', function()
+ local old = tmpname()
+ write_file(old, 'line')
+ local new = tmpname()
+ os.remove(new)
+
+ local undo_kept = exec_lua(
+ [[
+ local old = select(1, ...)
+ local new = select(2, ...)
+ vim.opt.undofile = true
+ vim.cmd.edit(old)
+ vim.cmd.normal('dd')
+ vim.cmd.write()
+ local undotree = vim.fn.undotree()
+ vim.lsp.util.rename(old, new)
+ -- Renaming uses :saveas, which updates the "last write" information.
+ -- Other than that, the undotree should remain the same.
+ undotree.save_cur = undotree.save_cur + 1
+ undotree.save_last = undotree.save_last + 1
+ undotree.entries[1].save = undotree.entries[1].save + 1
+ return vim.deep_equal(undotree, vim.fn.undotree())
+ ]],
+ old,
+ new
+ )
+ eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
+ eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new))
+ eq(true, undo_kept)
+ end)
+ it('Maintains undo information for unloaded buffer', function()
+ local old = tmpname()
+ write_file(old, 'line')
+ local new = tmpname()
+ os.remove(new)
+
+ local undo_kept = exec_lua(
+ [[
+ local old = select(1, ...)
+ local new = select(2, ...)
+ vim.opt.undofile = true
+ vim.cmd.split(old)
+ vim.cmd.normal('dd')
+ vim.cmd.write()
+ local undotree = vim.fn.undotree()
+ vim.cmd.bdelete()
+ vim.lsp.util.rename(old, new)
+ vim.cmd.edit(new)
+ return vim.deep_equal(undotree, vim.fn.undotree())
+ ]],
+ old,
+ new
+ )
+ eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
+ eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new))
+ eq(true, undo_kept)
+ end)
+ it('Does not rename file when it conflicts with a buffer without file', function()
+ local old = tmpname()
+ write_file(old, 'Old File')
+ local new = tmpname()
+ os.remove(new)
+
+ local lines = exec_lua(
+ [[
+ local old = select(1, ...)
+ local new = select(2, ...)
+ local old_buf = vim.fn.bufadd(old)
+ vim.fn.bufload(old_buf)
+ local conflict_buf = vim.api.nvim_create_buf(true, false)
+ vim.api.nvim_buf_set_name(conflict_buf, new)
+ vim.api.nvim_buf_set_lines(conflict_buf, 0, -1, true, {'conflict'})
+ vim.api.nvim_win_set_buf(0, conflict_buf)
+ vim.lsp.util.rename(old, new)
+ return vim.api.nvim_buf_get_lines(conflict_buf, 0, -1, true)
+ ]],
+ old,
+ new
+ )
+ eq({ 'conflict' }, lines)
+ eq('Old File', read_file(old))
end)
it('Does override target if overwrite is true', function()
- local old = helpers.tmpname()
+ local old = tmpname()
write_file(old, 'Old file')
- local new = helpers.tmpname()
+ local new = tmpname()
write_file(new, 'New file')
- exec_lua([[
+ exec_lua(
+ [[
local old = select(1, ...)
local new = select(2, ...)
vim.lsp.util.rename(old, new, { overwrite = true })
- ]], old, new)
+ ]],
+ old,
+ new
+ )
eq(false, exec_lua('return vim.uv.fs_stat(...) ~= nil', old))
eq(true, exec_lua('return vim.uv.fs_stat(...) ~= nil', new))
- eq('Old file\n', read_file(new))
+ eq('Old file', read_file(new))
end)
end)
@@ -2407,8 +2634,8 @@ describe('LSP', function()
range = {
start = { line = 0, character = 2 },
['end'] = { line = 0, character = 3 },
- }
- }
+ },
+ },
},
}
local actual = exec_lua [[
@@ -2436,7 +2663,7 @@ describe('LSP', function()
col = 3,
text = 'testing',
user_data = {
- targetUri = "file:///fake/uri",
+ targetUri = 'file:///fake/uri',
targetRange = {
start = { line = 0, character = 2 },
['end'] = { line = 0, character = 3 },
@@ -2444,8 +2671,8 @@ describe('LSP', function()
targetSelectionRange = {
start = { line = 0, character = 2 },
['end'] = { line = 0, character = 3 },
- }
- }
+ },
+ },
},
}
local actual = exec_lua [[
@@ -2479,24 +2706,26 @@ describe('LSP', function()
filename = '',
kind = 'File',
lnum = 2,
- text = '[File] TestA'
+ text = '[File] TestA',
},
{
col = 1,
filename = '',
kind = 'Module',
lnum = 4,
- text = '[Module] TestB'
+ text = '[Module] TestB',
},
{
col = 1,
filename = '',
kind = 'Namespace',
lnum = 6,
- text = '[Namespace] TestC'
- }
+ text = '[Namespace] TestC',
+ },
}
- eq(expected, exec_lua [[
+ eq(
+ expected,
+ exec_lua [[
local doc_syms = {
{
deprecated = false,
@@ -2581,7 +2810,8 @@ describe('LSP', function()
}
}
return vim.lsp.util.symbols_to_items(doc_syms, nil)
- ]])
+ ]]
+ )
end)
it('DocumentSymbol has no children', function()
local expected = {
@@ -2590,17 +2820,19 @@ describe('LSP', function()
filename = '',
kind = 'File',
lnum = 2,
- text = '[File] TestA'
+ text = '[File] TestA',
},
{
col = 1,
filename = '',
kind = 'Namespace',
lnum = 6,
- text = '[Namespace] TestC'
- }
+ text = '[Namespace] TestC',
+ },
}
- eq(expected, exec_lua [[
+ eq(
+ expected,
+ exec_lua [[
local doc_syms = {
{
deprecated = false,
@@ -2656,27 +2888,30 @@ describe('LSP', function()
}
}
return vim.lsp.util.symbols_to_items(doc_syms, nil)
- ]])
+ ]]
+ )
end)
end)
it('convert SymbolInformation[] to items', function()
- local expected = {
- {
- col = 1,
- filename = '/test_a',
- kind = 'File',
- lnum = 2,
- text = '[File] TestA'
- },
- {
- col = 1,
- filename = '/test_b',
- kind = 'Module',
- lnum = 4,
- text = '[Module] TestB'
- }
- }
- eq(expected, exec_lua [[
+ local expected = {
+ {
+ col = 1,
+ filename = '/test_a',
+ kind = 'File',
+ lnum = 2,
+ text = '[File] TestA',
+ },
+ {
+ col = 1,
+ filename = '/test_b',
+ kind = 'Module',
+ lnum = 4,
+ text = '[Module] TestB',
+ },
+ }
+ eq(
+ expected,
+ exec_lua [[
local sym_info = {
{
deprecated = false,
@@ -2718,19 +2953,20 @@ describe('LSP', function()
}
}
return vim.lsp.util.symbols_to_items(sym_info, nil)
- ]])
+ ]]
+ )
end)
end)
describe('lsp.util._get_symbol_kind_name', function()
it('returns the name specified by protocol', function()
- eq("File", exec_lua("return vim.lsp.util._get_symbol_kind_name(1)"))
- eq("TypeParameter", exec_lua("return vim.lsp.util._get_symbol_kind_name(26)"))
+ eq('File', exec_lua('return vim.lsp.util._get_symbol_kind_name(1)'))
+ eq('TypeParameter', exec_lua('return vim.lsp.util._get_symbol_kind_name(26)'))
end)
it('returns the name not specified by protocol', function()
- eq("Unknown", exec_lua("return vim.lsp.util._get_symbol_kind_name(nil)"))
- eq("Unknown", exec_lua("return vim.lsp.util._get_symbol_kind_name(vim.NIL)"))
- eq("Unknown", exec_lua("return vim.lsp.util._get_symbol_kind_name(1000)"))
+ eq('Unknown', exec_lua('return vim.lsp.util._get_symbol_kind_name(nil)'))
+ eq('Unknown', exec_lua('return vim.lsp.util._get_symbol_kind_name(vim.NIL)'))
+ eq('Unknown', exec_lua('return vim.lsp.util._get_symbol_kind_name(1000)'))
end)
end)
@@ -2748,20 +2984,20 @@ describe('LSP', function()
local location = function(start_line, start_char, end_line, end_char)
return {
- uri = "file:///fake/uri",
+ uri = 'file:///fake/uri',
range = {
start = { line = start_line, character = start_char },
- ["end"] = { line = end_line, character = end_char },
+ ['end'] = { line = end_line, character = end_char },
},
}
end
local jump = function(msg)
- eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg, "utf-16"))
- eq(target_bufnr, exec_lua[[return vim.fn.bufnr('%')]])
+ eq(true, exec_lua('return vim.lsp.util.jump_to_location(...)', msg, 'utf-16'))
+ eq(target_bufnr, exec_lua [[return vim.fn.bufnr('%')]])
return {
- line = exec_lua[[return vim.fn.line('.')]],
- col = exec_lua[[return vim.fn.col('.')]],
+ line = exec_lua [[return vim.fn.line('.')]],
+ col = exec_lua [[return vim.fn.col('.')]],
}
end
@@ -2773,16 +3009,16 @@ describe('LSP', function()
it('jumps to a LocationLink', function()
local pos = jump({
- targetUri = "file:///fake/uri",
- targetSelectionRange = {
- start = { line = 0, character = 4 },
- ["end"] = { line = 0, character = 4 },
- },
- targetRange = {
- start = { line = 1, character = 5 },
- ["end"] = { line = 1, character = 5 },
- },
- })
+ targetUri = 'file:///fake/uri',
+ targetSelectionRange = {
+ start = { line = 0, character = 4 },
+ ['end'] = { line = 0, character = 4 },
+ },
+ targetRange = {
+ start = { line = 1, character = 5 },
+ ['end'] = { line = 1, character = 5 },
+ },
+ })
eq(1, pos.line)
eq(5, pos.col)
end)
@@ -2791,18 +3027,18 @@ describe('LSP', function()
local pos = jump(location(1, 2, 1, 2))
eq(2, pos.line)
eq(4, pos.col)
- eq('Ã¥', exec_lua[[return vim.fn.expand('<cword>')]])
+ eq('Ã¥', exec_lua [[return vim.fn.expand('<cword>')]])
end)
it('adds current position to jumplist before jumping', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- local mark = funcs.nvim_buf_get_mark(target_bufnr, "'")
+ fn.nvim_win_set_buf(0, target_bufnr)
+ local mark = fn.nvim_buf_get_mark(target_bufnr, "'")
eq({ 1, 0 }, mark)
- funcs.nvim_win_set_cursor(0, { 2, 3 })
+ fn.nvim_win_set_cursor(0, { 2, 3 })
jump(location(0, 9, 0, 9))
- mark = funcs.nvim_buf_get_mark(target_bufnr, "'")
+ mark = fn.nvim_buf_get_mark(target_bufnr, "'")
eq({ 2, 3 }, mark)
end)
end)
@@ -2896,101 +3132,101 @@ describe('LSP', function()
end)
it('does not add current position to jumplist if not focus', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- local mark = funcs.nvim_buf_get_mark(target_bufnr, "'")
+ fn.nvim_win_set_buf(0, target_bufnr)
+ local mark = fn.nvim_buf_get_mark(target_bufnr, "'")
eq({ 1, 0 }, mark)
- funcs.nvim_win_set_cursor(0, { 2, 3 })
+ fn.nvim_win_set_cursor(0, { 2, 3 })
show_document(location(0, 9, 0, 9), false, true)
show_document(location(0, 9, 0, 9, true), false, true)
- mark = funcs.nvim_buf_get_mark(target_bufnr, "'")
+ mark = fn.nvim_buf_get_mark(target_bufnr, "'")
eq({ 1, 0 }, mark)
end)
it('does not change cursor position if not focus and not reuse_win', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- local cursor = funcs.nvim_win_get_cursor(0)
+ fn.nvim_win_set_buf(0, target_bufnr)
+ local cursor = fn.nvim_win_get_cursor(0)
show_document(location(0, 9, 0, 9), false, false)
- eq(cursor, funcs.nvim_win_get_cursor(0))
+ eq(cursor, fn.nvim_win_get_cursor(0))
end)
it('does not change window if not focus', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- local win = funcs.nvim_get_current_win()
+ fn.nvim_win_set_buf(0, target_bufnr)
+ local win = fn.nvim_get_current_win()
-- same document/bufnr
show_document(location(0, 9, 0, 9), false, true)
- eq(win, funcs.nvim_get_current_win())
+ eq(win, fn.nvim_get_current_win())
-- different document/bufnr, new window/split
show_document(location(0, 9, 0, 9, true), false, true)
- eq(2, #funcs.nvim_list_wins())
- eq(win, funcs.nvim_get_current_win())
+ eq(2, #fn.nvim_list_wins())
+ eq(win, fn.nvim_get_current_win())
end)
it("respects 'reuse_win' parameter", function()
- funcs.nvim_win_set_buf(0, target_bufnr)
+ fn.nvim_win_set_buf(0, target_bufnr)
-- does not create a new window if the buffer is already open
show_document(location(0, 9, 0, 9), false, true)
- eq(1, #funcs.nvim_list_wins())
+ eq(1, #fn.nvim_list_wins())
-- creates a new window even if the buffer is already open
show_document(location(0, 9, 0, 9), false, false)
- eq(2, #funcs.nvim_list_wins())
+ eq(2, #fn.nvim_list_wins())
end)
it('correctly sets the cursor of the split if range is given without focus', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
+ fn.nvim_win_set_buf(0, target_bufnr)
show_document(location(0, 9, 0, 9, true), false, true)
- local wins = funcs.nvim_list_wins()
+ local wins = fn.nvim_list_wins()
eq(2, #wins)
table.sort(wins)
- eq({ 1, 0 }, funcs.nvim_win_get_cursor(wins[1]))
- eq({ 1, 9 }, funcs.nvim_win_get_cursor(wins[2]))
+ eq({ 1, 0 }, fn.nvim_win_get_cursor(wins[1]))
+ eq({ 1, 9 }, fn.nvim_win_get_cursor(wins[2]))
end)
it('does not change cursor of the split if not range and not focus', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- funcs.nvim_win_set_cursor(0, { 2, 3 })
+ fn.nvim_win_set_buf(0, target_bufnr)
+ fn.nvim_win_set_cursor(0, { 2, 3 })
exec_lua([[vim.cmd.new()]])
- funcs.nvim_win_set_buf(0, target_bufnr2)
- funcs.nvim_win_set_cursor(0, { 2, 3 })
+ fn.nvim_win_set_buf(0, target_bufnr2)
+ fn.nvim_win_set_cursor(0, { 2, 3 })
show_document({ uri = 'file:///fake/uri2' }, false, true)
- local wins = funcs.nvim_list_wins()
+ local wins = fn.nvim_list_wins()
eq(2, #wins)
- eq({ 2, 3 }, funcs.nvim_win_get_cursor(wins[1]))
- eq({ 2, 3 }, funcs.nvim_win_get_cursor(wins[2]))
+ eq({ 2, 3 }, fn.nvim_win_get_cursor(wins[1]))
+ eq({ 2, 3 }, fn.nvim_win_get_cursor(wins[2]))
end)
it('respects existing buffers', function()
- funcs.nvim_win_set_buf(0, target_bufnr)
- local win = funcs.nvim_get_current_win()
+ fn.nvim_win_set_buf(0, target_bufnr)
+ local win = fn.nvim_get_current_win()
exec_lua([[vim.cmd.new()]])
- funcs.nvim_win_set_buf(0, target_bufnr2)
- funcs.nvim_win_set_cursor(0, { 2, 3 })
- local split = funcs.nvim_get_current_win()
+ fn.nvim_win_set_buf(0, target_bufnr2)
+ fn.nvim_win_set_cursor(0, { 2, 3 })
+ local split = fn.nvim_get_current_win()
-- reuse win for open document/bufnr if called from split
show_document(location(0, 9, 0, 9, true), false, true)
- eq({ 1, 9 }, funcs.nvim_win_get_cursor(split))
- eq(2, #funcs.nvim_list_wins())
+ eq({ 1, 9 }, fn.nvim_win_get_cursor(split))
+ eq(2, #fn.nvim_list_wins())
- funcs.nvim_set_current_win(win)
+ fn.nvim_set_current_win(win)
-- reuse win for open document/bufnr if called outside the split
show_document(location(0, 9, 0, 9, true), false, true)
- eq({ 1, 9 }, funcs.nvim_win_get_cursor(split))
- eq(2, #funcs.nvim_list_wins())
+ eq({ 1, 9 }, fn.nvim_win_get_cursor(split))
+ eq(2, #fn.nvim_list_wins())
end)
end)
@@ -3004,11 +3240,14 @@ describe('LSP', function()
end)
it('calculates size correctly', function()
- eq({19,3}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
+ eq({ 19, 3 }, exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
end)
it('calculates size correctly with wrapping', function()
- eq({15,5}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents,{width = 15, wrap_at = 14})} ]])
+ eq(
+ { 15, 5 },
+ exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents,{width = 15, wrap_at = 14})} ]]
+ )
end)
it('handles NUL bytes in text', function()
@@ -3018,21 +3257,24 @@ describe('LSP', function()
'\020\021\022\023\024\025\026\027\028\029',
} ]])
command('set list listchars=')
- eq({20,3}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
+ eq({ 20, 3 }, exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
command('set display+=uhex')
- eq({40,3}, exec_lua[[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
+ eq({ 40, 3 }, exec_lua [[ return {vim.lsp.util._make_floating_popup_size(contents)} ]])
end)
end)
describe('lsp.util.trim.trim_empty_lines', function()
it('properly trims empty lines', function()
- eq({{"foo", "bar"}}, exec_lua[[ return vim.lsp.util.trim_empty_lines({{ "foo", "bar" }, nil}) ]])
+ eq(
+ { { 'foo', 'bar' } },
+ exec_lua [[ return vim.lsp.util.trim_empty_lines({{ "foo", "bar" }, nil}) ]]
+ )
end)
end)
describe('lsp.util.convert_signature_help_to_markdown_lines', function()
it('can handle negative activeSignature', function()
- local result = exec_lua[[
+ local result = exec_lua [[
local signature_help = {
activeParameter = 0,
activeSignature = -1,
@@ -3046,22 +3288,29 @@ describe('LSP', function()
}
return vim.lsp.util.convert_signature_help_to_markdown_lines(signature_help, 'cs', {','})
]]
- local expected = {'```cs', 'TestEntity.TestEntity()', '```', 'some doc'}
+ local expected = { '```cs', 'TestEntity.TestEntity()', '```', 'some doc' }
eq(expected, result)
end)
end)
describe('lsp.util.get_effective_tabstop', function()
local function test_tabstop(tabsize, shiftwidth)
- exec_lua(string.format([[
+ exec_lua(string.format(
+ [[
vim.bo.shiftwidth = %d
vim.bo.tabstop = 2
- ]], shiftwidth))
+ ]],
+ shiftwidth
+ ))
eq(tabsize, exec_lua('return vim.lsp.util.get_effective_tabstop()'))
end
- it('with shiftwidth = 1', function() test_tabstop(1, 1) end)
- it('with shiftwidth = 0', function() test_tabstop(2, 0) end)
+ it('with shiftwidth = 1', function()
+ test_tabstop(1, 1)
+ end)
+ it('with shiftwidth = 0', function()
+ test_tabstop(2, 0)
+ end)
end)
describe('vim.lsp.buf.outgoing_calls', function()
@@ -3118,20 +3367,22 @@ describe('LSP', function()
return vim.fn.getqflist()
]=])
- local expected = { {
- bufnr = 2,
- col = 5,
- end_col = 0,
- lnum = 4,
- end_lnum = 0,
- module = "",
- nr = 0,
- pattern = "",
- text = "foo",
- type = "",
- valid = 1,
- vcol = 0
- } }
+ local expected = {
+ {
+ bufnr = 2,
+ col = 5,
+ end_col = 0,
+ lnum = 4,
+ end_lnum = 0,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'foo',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ }
eq(expected, qflist)
end)
@@ -3192,20 +3443,22 @@ describe('LSP', function()
return vim.fn.getqflist()
]=])
- local expected = { {
- bufnr = 2,
- col = 5,
- end_col = 0,
- lnum = 4,
- end_lnum = 0,
- module = "",
- nr = 0,
- pattern = "",
- text = "main",
- type = "",
- valid = 1,
- vcol = 0
- } }
+ local expected = {
+ {
+ bufnr = 2,
+ col = 5,
+ end_col = 0,
+ lnum = 4,
+ end_lnum = 0,
+ module = '',
+ nr = 0,
+ pattern = '',
+ text = 'main',
+ type = '',
+ valid = 1,
+ vcol = 0,
+ },
+ }
eq(expected, qflist)
end)
@@ -3214,52 +3467,52 @@ describe('LSP', function()
describe('vim.lsp.buf.rename', function()
for _, test in ipairs({
{
- it = "does not attempt to rename on nil response",
- name = "prepare_rename_nil",
+ it = 'does not attempt to rename on nil response',
+ name = 'prepare_rename_nil',
expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
},
},
{
- it = "handles prepareRename placeholder response",
- name = "prepare_rename_placeholder",
+ it = 'handles prepareRename placeholder response',
+ name = 'prepare_rename_placeholder',
expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, NIL, {method="textDocument/rename", client_id=1, bufnr=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, NIL, { method = 'textDocument/rename', client_id = 1, bufnr = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
},
- expected_text = "placeholder", -- see fake lsp response
+ expected_text = 'placeholder', -- see fake lsp response
},
{
- it = "handles range response",
- name = "prepare_rename_range",
+ it = 'handles range response',
+ name = 'prepare_rename_range',
expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, NIL, {method="textDocument/rename", client_id=1, bufnr=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, NIL, { method = 'textDocument/rename', client_id = 1, bufnr = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
},
- expected_text = "line", -- see test case and fake lsp response
+ expected_text = 'line', -- see test case and fake lsp response
},
{
- it = "handles error",
- name = "prepare_rename_error",
+ it = 'handles error',
+ name = 'prepare_rename_error',
expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
},
},
}) do
- it(test.it, function()
- local client
- test_rpc_server {
- test_name = test.name;
- on_init = function(_client)
- client = _client
- eq(true, client.server_capabilities().renameProvider.prepareProvider)
- end;
- on_setup = function()
- exec_lua([=[
+ it(test.it, function()
+ local client
+ test_rpc_server {
+ test_name = test.name,
+ on_init = function(_client)
+ client = _client
+ eq(true, client.server_capabilities().renameProvider.prepareProvider)
+ end,
+ on_setup = function()
+ exec_lua([=[
local bufnr = vim.api.nvim_get_current_buf()
lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID)
vim.lsp._stubs = {}
@@ -3271,31 +3524,31 @@ describe('LSP', function()
vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, {'', 'this is line two'})
vim.fn.cursor(2, 13) -- the space between "line" and "two"
]=])
- end;
- on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
- end;
- on_handler = function(err, result, ctx)
- -- Don't compare & assert params and version, they're not relevant for the testcase
- -- This allows us to be lazy and avoid declaring them
- ctx.params = nil
- ctx.version = nil
-
- eq(table.remove(test.expected_handlers), {err, result, ctx}, "expected handler")
- if ctx.method == 'start' then
- exec_lua("vim.lsp.buf.rename()")
- end
- if ctx.method == 'shutdown' then
- if test.expected_text then
- eq("New Name: ", exec_lua("return vim.lsp._stubs.input_prompt"))
- eq(test.expected_text, exec_lua("return vim.lsp._stubs.input_text"))
+ end,
+ on_exit = function(code, signal)
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
+ end,
+ on_handler = function(err, result, ctx)
+ -- Don't compare & assert params and version, they're not relevant for the testcase
+ -- This allows us to be lazy and avoid declaring them
+ ctx.params = nil
+ ctx.version = nil
+
+ eq(table.remove(test.expected_handlers), { err, result, ctx }, 'expected handler')
+ if ctx.method == 'start' then
+ exec_lua('vim.lsp.buf.rename()')
end
- client.stop()
- end
- end;
- }
- end)
+ if ctx.method == 'shutdown' then
+ if test.expected_text then
+ eq('New Name: ', exec_lua('return vim.lsp._stubs.input_prompt'))
+ eq(test.expected_text, exec_lua('return vim.lsp._stubs.input_text'))
+ end
+ client.stop()
+ end
+ end,
+ }
+ end)
end
end)
@@ -3303,22 +3556,21 @@ describe('LSP', function()
it('Calls client side command if available', function()
local client
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
test_rpc_server {
test_name = 'code_action_with_resolve',
on_init = function(client_)
client = client_
end,
- on_setup = function()
- end,
+ on_setup = function() end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
end,
on_handler = function(err, result, ctx)
- eq(table.remove(expected_handlers), {err, result, ctx})
+ eq(table.remove(expected_handlers), { err, result, ctx })
if ctx.method == 'start' then
exec_lua([[
vim.lsp.commands['dummy1'] = function(cmd)
@@ -3333,10 +3585,10 @@ describe('LSP', function()
vim.lsp.buf.code_action()
]])
elseif ctx.method == 'shutdown' then
- eq('function', exec_lua[[return type(vim.lsp.commands['dummy2'])]])
+ eq('function', exec_lua [[return type(vim.lsp.commands['dummy2'])]])
client.stop()
end
- end
+ end,
}
end)
it('Calls workspace/executeCommand if no client side command', function()
@@ -3382,22 +3634,21 @@ describe('LSP', function()
it('Filters and automatically applies action if requested', function()
local client
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
test_rpc_server {
test_name = 'code_action_filter',
on_init = function(client_)
client = client_
end,
- on_setup = function()
- end,
+ on_setup = function() end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
end,
on_handler = function(err, result, ctx)
- eq(table.remove(expected_handlers), {err, result, ctx})
+ eq(table.remove(expected_handlers), { err, result, ctx })
if ctx.method == 'start' then
exec_lua([[
vim.lsp.commands['preferred_command'] = function(cmd)
@@ -3428,15 +3679,15 @@ describe('LSP', function()
})
]])
elseif ctx.method == 'shutdown' then
- eq('function', exec_lua[[return type(vim.lsp.commands['executed_preferred'])]])
- eq('function', exec_lua[[return type(vim.lsp.commands['filtered_type_annotate_foo'])]])
- eq('function', exec_lua[[return type(vim.lsp.commands['executed_type_annotate'])]])
+ eq('function', exec_lua [[return type(vim.lsp.commands['executed_preferred'])]])
+ eq('function', exec_lua [[return type(vim.lsp.commands['filtered_type_annotate_foo'])]])
+ eq('function', exec_lua [[return type(vim.lsp.commands['executed_type_annotate'])]])
client.stop()
end
- end
+ end,
}
end)
- it("Fallback to command execution on resolve error", function()
+ it('Fallback to command execution on resolve error', function()
clear()
exec_lua(create_server_definition)
local result = exec_lua([[
@@ -3476,9 +3727,9 @@ describe('LSP', function()
vim.lsp.stop_client(client_id)
return server.messages
]])
- eq("codeAction/resolve", result[4].method)
- eq("workspace/executeCommand", result[5].method)
- eq("command:1", result[5].params.command)
+ eq('codeAction/resolve', result[4].method)
+ eq('workspace/executeCommand', result[5].method)
+ eq('command:1', result[5].params.command)
end)
end)
describe('vim.lsp.commands', function()
@@ -3499,25 +3750,25 @@ describe('LSP', function()
it('uses client commands', function()
local client
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
test_rpc_server {
test_name = 'clientside_commands',
on_init = function(client_)
client = client_
end,
- on_setup = function()
- end,
+ on_setup = function() end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
end,
on_handler = function(err, result, ctx)
- eq(table.remove(expected_handlers), {err, result, ctx})
+ eq(table.remove(expected_handlers), { err, result, ctx })
if ctx.method == 'start' then
- local fake_uri = "file:///fake/uri"
- local cmd = exec_lua([[
+ local fake_uri = 'file:///fake/uri'
+ local cmd = exec_lua(
+ [[
fake_uri = ...
local bufnr = vim.uri_to_bufnr(fake_uri)
vim.fn.bufload(bufnr)
@@ -3539,20 +3790,22 @@ describe('LSP', function()
vim.api.nvim_set_current_buf(bufnr)
vim.lsp.codelens.run()
return cmd_called
- ]], fake_uri)
- eq({ command = 'Dummy', title = 'Lens1' }, cmd)
- elseif ctx.method == 'shutdown' then
- client.stop()
+ ]],
+ fake_uri
+ )
+ eq({ command = 'Dummy', title = 'Lens1' }, cmd)
+ elseif ctx.method == 'shutdown' then
+ client.stop()
end
- end
+ end,
}
end)
it('releases buffer refresh lock', function()
local client
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
test_rpc_server {
test_name = 'codelens_refresh_lock',
@@ -3576,11 +3829,11 @@ describe('LSP', function()
]=])
end,
on_exit = function(code, signal)
- eq(0, code, "exit code")
- eq(0, signal, "exit signal")
+ eq(0, code, 'exit code')
+ eq(0, signal, 'exit signal')
end,
on_handler = function(err, result, ctx)
- eq(table.remove(expected_handlers), {err, result, ctx})
+ eq(table.remove(expected_handlers), { err, result, ctx })
if ctx.method == 'start' then
-- 1. first codelens request errors
local response = exec_lua([=[
@@ -3589,7 +3842,7 @@ describe('LSP', function()
vim.wait(100, function () return CALLED end)
return RESPONSE
]=])
- eq( { err = { code = -32002, message = "ServerNotInitialized" } }, response)
+ eq({ err = { code = -32002, message = 'ServerNotInitialized' } }, response)
-- 2. second codelens request runs
response = exec_lua([=[
@@ -3604,7 +3857,7 @@ describe('LSP', function()
vim.wait(100, function () return cmd_called end)
return cmd_called
]=])
- eq( { command = "Dummy", title = "Lens1" }, response)
+ eq({ command = 'Dummy', title = 'Lens1' }, response)
-- 3. third codelens request runs
response = exec_lua([=[
@@ -3619,20 +3872,20 @@ describe('LSP', function()
vim.wait(100, function () return cmd_called end)
return cmd_called
]=])
- eq( { command = "Dummy", title = "Lens2" }, response)
- elseif ctx.method == 'shutdown' then
- client.stop()
+ eq({ command = 'Dummy', title = 'Lens2' }, response)
+ elseif ctx.method == 'shutdown' then
+ client.stop()
end
- end
+ end,
}
end)
end)
- describe("vim.lsp.buf.format", function()
- it("Aborts with notify if no client matches filter", function()
+ describe('vim.lsp.buf.format', function()
+ it('Aborts with notify if no client matches filter', function()
local client
test_rpc_server {
- test_name = "basic_init",
+ test_name = 'basic_init',
on_init = function(c)
client = c
end,
@@ -3649,25 +3902,25 @@ describe('LSP', function()
vim.notify = notify
return notify_msg
]])
- eq("[LSP] Format request failed, no matching language servers.", notify_msg)
+ eq('[LSP] Format request failed, no matching language servers.', notify_msg)
client.stop()
end,
}
end)
- it("Sends textDocument/formatting request to format buffer", function()
+ it('Sends textDocument/formatting request to format buffer', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_formatting",
+ test_name = 'basic_formatting',
on_init = function(c)
client = c
end,
on_handler = function(_, _, ctx)
table.remove(expected_handlers)
- if ctx.method == "start" then
+ if ctx.method == 'start' then
local notify_msg = exec_lua([[
local bufnr = vim.api.nvim_get_current_buf()
vim.lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID)
@@ -3681,7 +3934,7 @@ describe('LSP', function()
return notify_msg
]])
eq(NIL, notify_msg)
- elseif ctx.method == "shutdown" then
+ elseif ctx.method == 'shutdown' then
client.stop()
end
end,
@@ -3689,18 +3942,18 @@ describe('LSP', function()
end)
it('Can format async', function()
local expected_handlers = {
- {NIL, {}, {method="shutdown", client_id=1}};
- {NIL, {}, {method="start", client_id=1}};
+ { NIL, {}, { method = 'shutdown', client_id = 1 } },
+ { NIL, {}, { method = 'start', client_id = 1 } },
}
local client
test_rpc_server {
- test_name = "basic_formatting",
+ test_name = 'basic_formatting',
on_init = function(c)
client = c
end,
on_handler = function(_, _, ctx)
table.remove(expected_handlers)
- if ctx.method == "start" then
+ if ctx.method == 'start' then
local result = exec_lua([[
local bufnr = vim.api.nvim_get_current_buf()
vim.lsp.buf_attach_client(bufnr, TEST_RPC_CLIENT_ID)
@@ -3724,8 +3977,8 @@ describe('LSP', function()
vim.lsp.handlers['textDocument/formatting'] = handler
return {notify = notify_msg, handler_called = handler_called}
]])
- eq({handler_called=true}, result)
- elseif ctx.method == "shutdown" then
+ eq({ handler_called = true }, result)
+ elseif ctx.method == 'shutdown' then
client.stop()
end
end,
@@ -3749,7 +4002,7 @@ describe('LSP', function()
vim.lsp.stop_client(client_id)
return server.messages
]])
- eq("textDocument/rangeFormatting", result[3].method)
+ eq('textDocument/rangeFormatting', result[3].method)
local expected_range = {
start = { line = 0, character = 0 },
['end'] = { line = 1, character = 4 },
@@ -3784,16 +4037,21 @@ describe('LSP', function()
return server.messages
]])
local expected_methods = {
- "initialize",
- "initialized",
- "textDocument/rangeFormatting",
- "$/cancelRequest",
- "textDocument/rangeFormatting",
- "$/cancelRequest",
- "shutdown",
- "exit",
+ 'initialize',
+ 'initialized',
+ 'textDocument/rangeFormatting',
+ '$/cancelRequest',
+ 'textDocument/rangeFormatting',
+ '$/cancelRequest',
+ 'shutdown',
+ 'exit',
}
- eq(expected_methods, vim.tbl_map(function(x) return x.method end, result))
+ eq(
+ expected_methods,
+ vim.tbl_map(function(x)
+ return x.method
+ end, result)
+ )
-- uses first column of start line and last column of end line
local expected_range = {
start = { line = 0, character = 0 },
@@ -3809,10 +4067,11 @@ describe('LSP', function()
notify_msg = msg
end
]])
- local fail_msg = "[LSP] Format request failed, no matching language servers."
+ local fail_msg = '[LSP] Format request failed, no matching language servers.'
local function check_notify(name, formatting, range_formatting)
- local timeout_msg = "[LSP][" .. name .. "] timeout"
- exec_lua([[
+ local timeout_msg = '[LSP][' .. name .. '] timeout'
+ exec_lua(
+ [[
local formatting, range_formatting, name = ...
local server = _create_server({ capabilities = {
documentFormattingProvider = formatting,
@@ -3821,7 +4080,11 @@ describe('LSP', function()
vim.lsp.start({ name = name, cmd = server.cmd })
notify_msg = nil
vim.lsp.buf.format({ name = name, timeout_ms = 1 })
- ]], formatting, range_formatting, name)
+ ]],
+ formatting,
+ range_formatting,
+ name
+ )
eq(formatting and timeout_msg or fail_msg, exec_lua('return notify_msg'))
exec_lua([[
notify_msg = nil
@@ -3829,12 +4092,111 @@ describe('LSP', function()
]])
eq(range_formatting and timeout_msg or fail_msg, exec_lua('return notify_msg'))
end
- check_notify("none", false, false)
- check_notify("formatting", true, false)
- check_notify("rangeFormatting", false, true)
- check_notify("both", true, true)
+ check_notify('none', false, false)
+ check_notify('formatting', true, false)
+ check_notify('rangeFormatting', false, true)
+ check_notify('both', true, true)
+ end)
+ end)
+
+ describe('vim.lsp.tagfunc', function()
+ before_each(function()
+ clear()
+ ---@type lsp.Location[]
+ local mock_locations = {
+ {
+ range = {
+ ['start'] = { line = 5, character = 23 },
+ ['end'] = { line = 10, character = 0 },
+ },
+ uri = 'test://buf',
+ },
+ {
+ range = {
+ ['start'] = { line = 42, character = 10 },
+ ['end'] = { line = 44, character = 0 },
+ },
+ uri = 'test://another-file',
+ },
+ }
+ exec_lua(create_server_definition)
+ exec_lua(
+ [[
+ _G.mock_locations = ...
+ _G.server = _create_server({
+ ---@type lsp.ServerCapabilities
+ capabilities = {
+ definitionProvider = true,
+ workspaceSymbolProvider = true,
+ },
+ handlers = {
+ ---@return lsp.Location[]
+ ['textDocument/definition'] = function()
+ return { _G.mock_locations[1] }
+ end,
+ ---@return lsp.WorkspaceSymbol[]
+ ['workspace/symbol'] = function(_, request)
+ assert(request.query == 'foobar')
+ return {
+ {
+ name = 'foobar',
+ kind = 13, ---@type lsp.SymbolKind
+ location = _G.mock_locations[1],
+ },
+ {
+ name = 'vim.foobar',
+ kind = 12, ---@type lsp.SymbolKind
+ location = _G.mock_locations[2],
+ }
+ }
+ end,
+ },
+ })
+ _G.client_id = vim.lsp.start({ name = 'dummy', cmd = server.cmd })
+ ]],
+ mock_locations
+ )
+ end)
+ after_each(function()
+ exec_lua [[
+ vim.lsp.stop_client(_G.client_id)
+ ]]
+ end)
+
+ it('with flags=c, returns matching tags using textDocument/definition', function()
+ local result = exec_lua [[
+ return vim.lsp.tagfunc('foobar', 'c')
+ ]]
+ eq({
+ {
+ cmd = '/\\%6l\\%1c/', -- for location (5, 23)
+ filename = 'test://buf',
+ name = 'foobar',
+ },
+ }, result)
+ end)
+
+ it('without flags=c, returns all matching tags using workspace/symbol', function()
+ local result = exec_lua [[
+ return vim.lsp.tagfunc('foobar', '')
+ ]]
+ eq({
+ {
+ cmd = '/\\%6l\\%1c/', -- for location (5, 23)
+ filename = 'test://buf',
+ kind = 'Variable',
+ name = 'foobar',
+ },
+ {
+ cmd = '/\\%43l\\%1c/', -- for location (42, 10)
+ filename = 'test://another-file',
+ kind = 'Function',
+ name = 'vim.foobar',
+ },
+ }, result)
end)
end)
+
describe('cmd', function()
it('can connect to lsp server via rpc.connect', function()
local result = exec_lua [[
@@ -3859,7 +4221,43 @@ describe('LSP', function()
server:shutdown()
return vim.json.decode(init)
]]
- eq(result.method, "initialize")
+ eq(result.method, 'initialize')
+ end)
+ it('can connect to lsp server via rpc.domain_socket_connect', function()
+ local tmpfile
+ if is_os('win') then
+ tmpfile = '\\\\.\\\\pipe\\pipe.test'
+ else
+ tmpfile = tmpname()
+ os.remove(tmpfile)
+ end
+ local result = exec_lua(
+ [[
+ local SOCK = ...
+ local uv = vim.uv
+ local server = uv.new_pipe(false)
+ server:bind(SOCK)
+ local init = nil
+
+ server:listen(127, function(err)
+ assert(not err, err)
+ local client = uv.new_pipe()
+ server:accept(client)
+ client:read_start(require("vim.lsp.rpc").create_read_loop(function(body)
+ init = body
+ client:close()
+ end))
+ end)
+ vim.lsp.start({ name = "dummy", cmd = vim.lsp.rpc.domain_socket_connect(SOCK) })
+ vim.wait(1000, function() return init ~= nil end)
+ assert(init, "server must receive `initialize` request")
+ server:close()
+ server:shutdown()
+ return vim.json.decode(init)
+ ]],
+ tmpfile
+ )
+ eq(result.method, 'initialize')
end)
end)
@@ -3926,9 +4324,9 @@ describe('LSP', function()
{
id = 10,
jsonrpc = '2.0',
- result = false
- }
- }
+ result = false,
+ },
+ },
}
eq(expected, result)
end)
@@ -3936,15 +4334,19 @@ describe('LSP', function()
describe('#dynamic vim.lsp._dynamic', function()
it('supports dynamic registration', function()
- local root_dir = helpers.tmpname()
+ ---@type string
+ local root_dir = tmpname()
os.remove(root_dir)
mkdir(root_dir)
local tmpfile = root_dir .. '/dynamic.foo'
local file = io.open(tmpfile, 'w')
- file:close()
+ if file then
+ file:close()
+ end
exec_lua(create_server_definition)
- local result = exec_lua([[
+ local result = exec_lua(
+ [[
local root_dir, tmpfile = ...
local server = _create_server()
@@ -3952,6 +4354,9 @@ describe('LSP', function()
name = 'dynamic-test',
cmd = server.cmd,
root_dir = root_dir,
+ get_language_id = function()
+ return "dummy-lang"
+ end,
capabilities = {
textDocument = {
formatting = {
@@ -3985,6 +4390,13 @@ describe('LSP', function()
{
id = 'range-formatting',
method = 'textDocument/rangeFormatting',
+ registerOptions = {
+ documentSelector = {
+ {
+ language = "dummy-lang"
+ },
+ }
+ }
},
},
}, { client_id = client_id })
@@ -4002,7 +4414,11 @@ describe('LSP', function()
local function check(method, fname)
local bufnr = fname and vim.fn.bufadd(fname) or nil
local client = vim.lsp.get_client_by_id(client_id)
- result[#result + 1] = {method = method, fname = fname, supported = client.supports_method(method, {bufnr = bufnr})}
+ result[#result + 1] = {
+ method = method,
+ fname = fname,
+ supported = client.supports_method(method, {bufnr = bufnr})
+ }
end
@@ -4013,120 +4429,161 @@ describe('LSP', function()
check("textDocument/completion")
return result
- ]], root_dir, tmpfile)
+ ]],
+ root_dir,
+ tmpfile
+ )
eq(5, #result)
- eq({method = 'textDocument/formatting', supported = false}, result[1])
- eq({method = 'textDocument/formatting', supported = true, fname = tmpfile}, result[2])
- eq({method = 'textDocument/rangeFormatting', supported = true}, result[3])
- eq({method = 'textDocument/rangeFormatting', supported = true, fname = tmpfile}, result[4])
- eq({method = 'textDocument/completion', supported = false}, result[5])
+ eq({ method = 'textDocument/formatting', supported = false }, result[1])
+ eq({ method = 'textDocument/formatting', supported = true, fname = tmpfile }, result[2])
+ eq({ method = 'textDocument/rangeFormatting', supported = true }, result[3])
+ eq({ method = 'textDocument/rangeFormatting', supported = true, fname = tmpfile }, result[4])
+ eq({ method = 'textDocument/completion', supported = false }, result[5])
end)
end)
describe('vim.lsp._watchfiles', function()
- it('sends notifications when files change', function()
- skip(is_os('bsd'), "bsd only reports rename on folders if file inside change")
- local root_dir = helpers.tmpname()
- os.remove(root_dir)
- mkdir(root_dir)
+ local function test_filechanges(watchfunc)
+ it(
+ string.format('sends notifications when files change (watchfunc=%s)', watchfunc),
+ function()
+ if watchfunc == 'fswatch' then
+ skip(
+ not is_ci() and fn.executable('fswatch') == 0,
+ 'fswatch not installed and not on CI'
+ )
+ skip(is_os('win'), 'not supported on windows')
+ skip(is_os('mac'), 'flaky')
+ end
- exec_lua(create_server_definition)
- local result = exec_lua([[
- local root_dir = ...
+ skip(
+ is_os('bsd'),
+ 'kqueue only reports events on watched folder itself, not contained files #26110'
+ )
- local server = _create_server()
- local client_id = vim.lsp.start({
- name = 'watchfiles-test',
- cmd = server.cmd,
- root_dir = root_dir,
- capabilities = {
- workspace = {
- didChangeWatchedFiles = {
- dynamicRegistration = true,
+ local root_dir = tmpname()
+ os.remove(root_dir)
+ mkdir(root_dir)
+
+ exec_lua(create_server_definition)
+ local result = exec_lua(
+ [[
+ local root_dir, watchfunc = ...
+
+ local server = _create_server()
+ local client_id = vim.lsp.start({
+ name = 'watchfiles-test',
+ cmd = server.cmd,
+ root_dir = root_dir,
+ capabilities = {
+ workspace = {
+ didChangeWatchedFiles = {
+ dynamicRegistration = true,
+ },
},
},
- },
- })
+ })
- local expected_messages = 2 -- initialize, initialized
+ require('vim.lsp._watchfiles')._watchfunc = require('vim._watch')[watchfunc]
- local watchfunc = require('vim.lsp._watchfiles')._watchfunc
- local msg_wait_timeout = watchfunc == vim._watch.poll and 2500 or 200
- local function wait_for_messages()
- assert(vim.wait(msg_wait_timeout, function() return #server.messages == expected_messages end), 'Timed out waiting for expected number of messages. Current messages seen so far: ' .. vim.inspect(server.messages))
- end
+ local expected_messages = 0
- wait_for_messages()
+ local msg_wait_timeout = watchfunc == 'watch' and 200 or 2500
- vim.lsp.handlers['client/registerCapability'](nil, {
- registrations = {
- {
- id = 'watchfiles-test-0',
- method = 'workspace/didChangeWatchedFiles',
- registerOptions = {
- watchers = {
- {
- globPattern = '**/watch',
- kind = 7,
+ local function wait_for_message(incr)
+ expected_messages = expected_messages + (incr or 1)
+ assert(
+ vim.wait(msg_wait_timeout, function()
+ return #server.messages == expected_messages
+ end),
+ 'Timed out waiting for expected number of messages. Current messages seen so far: '
+ .. vim.inspect(server.messages)
+ )
+ end
+
+ wait_for_message(2) -- initialize, initialized
+
+ vim.lsp.handlers['client/registerCapability'](nil, {
+ registrations = {
+ {
+ id = 'watchfiles-test-0',
+ method = 'workspace/didChangeWatchedFiles',
+ registerOptions = {
+ watchers = {
+ {
+ globPattern = '**/watch',
+ kind = 7,
+ },
},
},
},
},
- },
- }, { client_id = client_id })
+ }, { client_id = client_id })
- if watchfunc == vim._watch.poll then
- vim.wait(100)
- end
+ if watchfunc ~= 'watch' then
+ vim.wait(100)
+ end
- local path = root_dir .. '/watch'
- local file = io.open(path, 'w')
- file:close()
+ local path = root_dir .. '/watch'
+ local tmp = vim.fn.tempname()
+ io.open(tmp, 'w'):close()
+ vim.uv.fs_rename(tmp, path)
- expected_messages = expected_messages + 1
- wait_for_messages()
+ wait_for_message()
- os.remove(path)
+ os.remove(path)
- expected_messages = expected_messages + 1
- wait_for_messages()
+ wait_for_message()
- return server.messages
- ]], root_dir)
+ vim.lsp.stop_client(client_id)
- local function watched_uri(fname)
- return exec_lua([[
- local root_dir, fname = ...
- return vim.uri_from_fname(root_dir .. '/' .. fname)
- ]], root_dir, fname)
- end
+ return server.messages
+ ]],
+ root_dir,
+ watchfunc
+ )
- eq(4, #result)
- eq('workspace/didChangeWatchedFiles', result[3].method)
- eq({
- changes = {
- {
- type = exec_lua([[return vim.lsp.protocol.FileChangeType.Created]]),
- uri = watched_uri('watch'),
- },
- },
- }, result[3].params)
- eq('workspace/didChangeWatchedFiles', result[4].method)
- eq({
- changes = {
- {
- type = exec_lua([[return vim.lsp.protocol.FileChangeType.Deleted]]),
- uri = watched_uri('watch'),
- },
- },
- }, result[4].params)
- end)
+ local uri = vim.uri_from_fname(root_dir .. '/watch')
+
+ eq(6, #result)
+
+ eq({
+ method = 'workspace/didChangeWatchedFiles',
+ params = {
+ changes = {
+ {
+ type = exec_lua([[return vim.lsp.protocol.FileChangeType.Created]]),
+ uri = uri,
+ },
+ },
+ },
+ }, result[3])
+
+ eq({
+ method = 'workspace/didChangeWatchedFiles',
+ params = {
+ changes = {
+ {
+ type = exec_lua([[return vim.lsp.protocol.FileChangeType.Deleted]]),
+ uri = uri,
+ },
+ },
+ },
+ }, result[4])
+ end
+ )
+ end
+
+ test_filechanges('watch')
+ test_filechanges('watchdirs')
+ test_filechanges('fswatch')
it('correctly registers and unregisters', function()
local root_dir = '/some_dir'
exec_lua(create_server_definition)
- local result = exec_lua([[
+ local result = exec_lua(
+ [[
local root_dir = ...
local server = _create_server()
@@ -4217,13 +4674,19 @@ describe('LSP', function()
wait_for_messages()
return server.messages
- ]], root_dir)
+ ]],
+ root_dir
+ )
local function watched_uri(fname)
- return exec_lua([[
+ return exec_lua(
+ [[
local root_dir, fname = ...
return vim.uri_from_fname(root_dir .. '/' .. fname)
- ]], root_dir, fname)
+ ]],
+ root_dir,
+ fname
+ )
end
eq(4, #result)
@@ -4250,7 +4713,8 @@ describe('LSP', function()
it('correctly handles the registered watch kind', function()
local root_dir = 'some_dir'
exec_lua(create_server_definition)
- local result = exec_lua([[
+ local result = exec_lua(
+ [[
local root_dir = ...
local server = _create_server()
@@ -4323,13 +4787,18 @@ describe('LSP', function()
wait_for_messages()
return server.messages
- ]], root_dir)
+ ]],
+ root_dir
+ )
local function watched_uri(fname)
- return exec_lua([[
+ return exec_lua(
+ [[
local fname = ...
return vim.uri_from_fname('/dir/' .. fname)
- ]], fname)
+ ]],
+ fname
+ )
end
eq(3, #result)
@@ -4391,7 +4860,8 @@ describe('LSP', function()
it('prunes duplicate events', function()
local root_dir = 'some_dir'
exec_lua(create_server_definition)
- local result = exec_lua([[
+ local result = exec_lua(
+ [[
local root_dir = ...
local server = _create_server()
@@ -4449,12 +4919,17 @@ describe('LSP', function()
wait_for_messages()
return server.messages
- ]], root_dir)
+ ]],
+ root_dir
+ )
local function watched_uri(fname)
- return exec_lua([[
+ return exec_lua(
+ [[
return vim.uri_from_fname(...)
- ]], fname)
+ ]],
+ fname
+ )
end
eq(3, #result)
@@ -4489,7 +4964,8 @@ describe('LSP', function()
]])
local function check_registered(capabilities)
- return exec_lua([[
+ return exec_lua(
+ [[
watching = false
local client_id = vim.lsp.start({
name = 'watchfiles-test',
@@ -4528,31 +5004,41 @@ describe('LSP', function()
vim.lsp.stop_client(client_id, true)
return watching
- ]], capabilities)
+ ]],
+ capabilities
+ )
end
- eq(true, check_registered(nil)) -- start{_client}() defaults to make_client_capabilities().
+ eq(true, check_registered(nil)) -- start{_client}() defaults to make_client_capabilities().
eq(false, check_registered(vim.empty_dict()))
- eq(false, check_registered({
+ eq(
+ false,
+ check_registered({
workspace = {
ignoreMe = true,
},
- }))
- eq(false, check_registered({
+ })
+ )
+ eq(
+ false,
+ check_registered({
workspace = {
didChangeWatchedFiles = {
dynamicRegistration = false,
},
},
- }))
- eq(true, check_registered({
+ })
+ )
+ eq(
+ true,
+ check_registered({
workspace = {
didChangeWatchedFiles = {
dynamicRegistration = true,
},
},
- }))
+ })
+ )
end)
end)
end)
-
diff --git a/test/functional/plugin/man_spec.lua b/test/functional/plugin/man_spec.lua
index 815ddbc523..5bfa566729 100644
--- a/test/functional/plugin/man_spec.lua
+++ b/test/functional/plugin/man_spec.lua
@@ -3,13 +3,13 @@ local Screen = require('test.functional.ui.screen')
local command, rawfeed = helpers.command, helpers.rawfeed
local clear = helpers.clear
local exec_lua = helpers.exec_lua
-local funcs = helpers.funcs
+local fn = helpers.fn
local nvim_prog = helpers.nvim_prog
local matches = helpers.matches
local write_file = helpers.write_file
local tmpname = helpers.tmpname
local eq = helpers.eq
-local pesc = helpers.pesc
+local pesc = vim.pesc
local skip = helpers.skip
local is_ci = helpers.is_ci
@@ -33,7 +33,7 @@ local function get_search_history(name)
end
clear()
-if funcs.executable('man') == 0 then
+if fn.executable('man') == 0 then
pending('missing "man" command', function() end)
return
end
@@ -49,7 +49,7 @@ describe(':Man', function()
before_each(function()
command('syntax on')
command('set filetype=man')
- command('syntax off') -- Ignore syntax groups
+ command('syntax off') -- Ignore syntax groups
screen = Screen.new(52, 5)
screen:set_default_attr_ids({
b = { bold = true },
@@ -58,80 +58,87 @@ describe(':Man', function()
bi = { bold = true, italic = true },
biu = { bold = true, italic = true, underline = true },
c = { foreground = Screen.colors.Blue }, -- control chars
- eob = { bold = true, foreground = Screen.colors.Blue } -- empty line '~'s
+ eob = { bold = true, foreground = Screen.colors.Blue }, -- empty line '~'s
})
screen:attach()
end)
it('clears backspaces from text and adds highlights', function()
- rawfeed([[
+ rawfeed(
+ [[
ithis i<C-v><C-h>is<C-v><C-h>s a<C-v><C-h>a test
- with _<C-v><C-h>o_<C-v><C-h>v_<C-v><C-h>e_<C-v><C-h>r_<C-v><C-h>s_<C-v><C-h>t_<C-v><C-h>r_<C-v><C-h>u_<C-v><C-h>c_<C-v><C-h>k text<ESC>]])
+ with _<C-v><C-h>o_<C-v><C-h>v_<C-v><C-h>e_<C-v><C-h>r_<C-v><C-h>s_<C-v><C-h>t_<C-v><C-h>r_<C-v><C-h>u_<C-v><C-h>c_<C-v><C-h>k text<ESC>]]
+ )
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
this i{c:^H}is{c:^H}s a{c:^H}a test |
with _{c:^H}o_{c:^H}v_{c:^H}e_{c:^H}r_{c:^H}s_{c:^H}t_{c:^H}r_{c:^H}u_{c:^H}c_{c:^H}k tex^t |
- {eob:~ }|
- {eob:~ }|
+ {eob:~ }|*2
|
- ]]}
+ ]],
+ }
- exec_lua[[require'man'.init_pager()]]
+ exec_lua [[require'man'.init_pager()]]
screen:expect([[
^this {b:is} {b:a} test |
with {i:overstruck} text |
- {eob:~ }|
- {eob:~ }|
+ {eob:~ }|*2
|
]])
end)
it('clears escape sequences from text and adds highlights', function()
- rawfeed([[
+ rawfeed(
+ [[
ithis <C-v><ESC>[1mis <C-v><ESC>[3ma <C-v><ESC>[4mtest<C-v><ESC>[0m
- <C-v><ESC>[4mwith<C-v><ESC>[24m <C-v><ESC>[4mescaped<C-v><ESC>[24m <C-v><ESC>[4mtext<C-v><ESC>[24m<ESC>]])
+ <C-v><ESC>[4mwith<C-v><ESC>[24m <C-v><ESC>[4mescaped<C-v><ESC>[24m <C-v><ESC>[4mtext<C-v><ESC>[24m<ESC>]]
+ )
- screen:expect{grid=[=[
+ screen:expect {
+ grid = [=[
this {c:^[}[1mis {c:^[}[3ma {c:^[}[4mtest{c:^[}[0m |
{c:^[}[4mwith{c:^[}[24m {c:^[}[4mescaped{c:^[}[24m {c:^[}[4mtext{c:^[}[24^m |
- {eob:~ }|
- {eob:~ }|
+ {eob:~ }|*2
|
- ]=]}
+ ]=],
+ }
- exec_lua[[require'man'.init_pager()]]
+ exec_lua [[require'man'.init_pager()]]
screen:expect([[
^this {b:is }{bi:a }{biu:test} |
{u:with} {u:escaped} {u:text} |
- {eob:~ }|
- {eob:~ }|
+ {eob:~ }|*2
|
]])
end)
it('highlights multibyte text', function()
- rawfeed([[
+ rawfeed(
+ [[
ithis i<C-v><C-h>is<C-v><C-h>s ã‚<C-v><C-h>ã‚ test
- with _<C-v><C-h>ö_<C-v><C-h>v_<C-v><C-h>e_<C-v><C-h>r_<C-v><C-h>s_<C-v><C-h>t_<C-v><C-h>r_<C-v><C-h>u_<C-v><C-h>̃_<C-v><C-h>c_<C-v><C-h>k te<C-v><ESC>[3mxt¶<C-v><ESC>[0m<ESC>]])
- exec_lua[[require'man'.init_pager()]]
+ with _<C-v><C-h>ö_<C-v><C-h>v_<C-v><C-h>e_<C-v><C-h>r_<C-v><C-h>s_<C-v><C-h>t_<C-v><C-h>r_<C-v><C-h>u_<C-v><C-h>̃_<C-v><C-h>c_<C-v><C-h>k te<C-v><ESC>[3mxt¶<C-v><ESC>[0m<ESC>]]
+ )
+ exec_lua [[require'man'.init_pager()]]
screen:expect([[
^this {b:is} {b:ã‚} test |
with {i:överstrũck} te{i:xt¶} |
- {eob:~ }|
- {eob:~ }|
+ {eob:~ }|*2
|
]])
end)
it('highlights underscores based on context', function()
- rawfeed([[
+ rawfeed(
+ [[
i_<C-v><C-h>_b<C-v><C-h>be<C-v><C-h>eg<C-v><C-h>gi<C-v><C-h>in<C-v><C-h>ns<C-v><C-h>s
m<C-v><C-h>mi<C-v><C-h>id<C-v><C-h>d_<C-v><C-h>_d<C-v><C-h>dl<C-v><C-h>le<C-v><C-h>e
- _<C-v><C-h>m_<C-v><C-h>i_<C-v><C-h>d_<C-v><C-h>__<C-v><C-h>d_<C-v><C-h>l_<C-v><C-h>e<ESC>]])
- exec_lua[[require'man'.init_pager()]]
+ _<C-v><C-h>m_<C-v><C-h>i_<C-v><C-h>d_<C-v><C-h>__<C-v><C-h>d_<C-v><C-h>l_<C-v><C-h>e<ESC>]]
+ )
+ exec_lua [[require'man'.init_pager()]]
screen:expect([[
{b:^_begins} |
@@ -147,7 +154,7 @@ describe(':Man', function()
i· ·<C-v><C-h>·
+<C-v><C-h>o
+<C-v><C-h>+<C-v><C-h>o<C-v><C-h>o double<ESC>]])
- exec_lua[[require'man'.init_pager()]]
+ exec_lua [[require'man'.init_pager()]]
screen:expect([[
^· {b:·} |
@@ -164,7 +171,7 @@ describe(':Man', function()
<C-v><C-[>[44m 4 <C-v><C-[>[45m 5 <C-v><C-[>[46m 6 <C-v><C-[>[47m 7 <C-v><C-[>[100m 8 <C-v><C-[>[101m 9
<C-v><C-[>[102m 10 <C-v><C-[>[103m 11 <C-v><C-[>[104m 12 <C-v><C-[>[105m 13 <C-v><C-[>[106m 14 <C-v><C-[>[107m 15
<C-v><C-[>[48:5:16m 16 <ESC>]])
- exec_lua[[require'man'.init_pager()]]
+ exec_lua [[require'man'.init_pager()]]
screen:expect([[
^ 0 1 2 3 |
@@ -178,8 +185,14 @@ describe(':Man', function()
it('q quits in "$MANPAGER mode" (:Man!) #18281', function()
-- This will hang if #18281 regresses.
- local args = {nvim_prog, '--headless', '+autocmd VimLeave * echo "quit works!!"', '+Man!', '+call nvim_input("q")'}
- matches('quit works!!', funcs.system(args, {'manpage contents'}))
+ local args = {
+ nvim_prog,
+ '--headless',
+ '+autocmd VimLeave * echo "quit works!!"',
+ '+Man!',
+ '+call nvim_input("q")',
+ }
+ matches('quit works!!', fn.system(args, { 'manpage contents' }))
end)
it('reports non-existent man pages for absolute paths', function()
@@ -188,41 +201,44 @@ describe(':Man', function()
-- actual_file must be an absolute path to an existent file for us to test against it
matches('^/.+', actual_file)
write_file(actual_file, '')
- local args = {nvim_prog, '--headless', '+:Man ' .. actual_file, '+q'}
- matches(('Error detected while processing command line:\r\n' ..
- 'man.lua: "no manual entry for %s"'):format(pesc(actual_file)),
- funcs.system(args, {''}))
+ local args = { nvim_prog, '--headless', '+:Man ' .. actual_file, '+q' }
+ matches(
+ ('Error detected while processing command line:\r\n' .. 'man.lua: "no manual entry for %s"'):format(
+ pesc(actual_file)
+ ),
+ fn.system(args, { '' })
+ )
os.remove(actual_file)
end)
it('tries variants with spaces, underscores #22503', function()
eq({
- {'', 'NAME WITH SPACES'},
- {'', 'NAME_WITH_SPACES'},
- }, get_search_history('NAME WITH SPACES'))
+ { '', 'NAME WITH SPACES' },
+ { '', 'NAME_WITH_SPACES' },
+ }, get_search_history('NAME WITH SPACES'))
eq({
- {'3', 'some other man'},
- {'3', 'some_other_man'},
- }, get_search_history('3 some other man'))
+ { '3', 'some other man' },
+ { '3', 'some_other_man' },
+ }, get_search_history('3 some other man'))
eq({
- {'3x', 'some other man'},
- {'3x', 'some_other_man'},
- }, get_search_history('3X some 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'))
+ { '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'))
+ { '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'))
+ { '', '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)'))
+ { '1', 'other_man' },
+ { '1', 'other_man' },
+ }, get_search_history('other_man(1)'))
end)
end)
diff --git a/test/functional/plugin/matchparen_spec.lua b/test/functional/plugin/matchparen_spec.lua
index 2670734c1a..530afd16e4 100644
--- a/test/functional/plugin/matchparen_spec.lua
+++ b/test/functional/plugin/matchparen_spec.lua
@@ -3,7 +3,7 @@ local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local command = helpers.command
-local meths = helpers.meths
+local api = helpers.api
local feed = helpers.feed
local eq = helpers.eq
@@ -11,18 +11,18 @@ describe('matchparen', function()
local screen
before_each(function()
- clear{args={'-u', 'NORC'}}
- screen = Screen.new(20,5)
+ clear { args = { '-u', 'NORC' } }
+ screen = Screen.new(20, 5)
screen:attach()
- screen:set_default_attr_ids( {
- [0] = {bold=true, foreground=255},
- [1] = {bold=true},
- } )
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = 255 },
+ [1] = { bold = true },
+ })
end)
it('uses correct column after i_<Up>. Vim patch 7.4.1296', function()
command('set noautoindent nosmartindent nocindent laststatus=0')
- eq(1, meths.get_var('loaded_matchparen'))
+ eq(1, api.nvim_get_var('loaded_matchparen'))
feed('ivoid f_test()<cr>')
feed('{<cr>')
feed('}')
@@ -39,6 +39,5 @@ describe('matchparen', function()
} |
{1:-- INSERT --} |
]])
-
end)
end)
diff --git a/test/functional/plugin/msgpack_spec.lua b/test/functional/plugin/msgpack_spec.lua
index d841cb8ce0..8511e6c703 100644
--- a/test/functional/plugin/msgpack_spec.lua
+++ b/test/functional/plugin/msgpack_spec.lua
@@ -1,14 +1,16 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
-local meths = helpers.meths
-local eq, nvim_eval, nvim_command, exc_exec =
- helpers.eq, helpers.eval, helpers.command, helpers.exc_exec
+local api = helpers.api
+local eq = helpers.eq
+local nvim_eval = helpers.eval
+local nvim_command = helpers.command
+local exc_exec = helpers.exc_exec
local ok = helpers.ok
-local NIL = helpers.NIL
+local NIL = vim.NIL
describe('autoload/msgpack.vim', function()
before_each(function()
- clear{args={'-u', 'NORC'}}
+ clear { args = { '-u', 'NORC' } }
end)
local sp = function(typ, val)
@@ -16,16 +18,15 @@ describe('autoload/msgpack.vim', function()
end
local mapsp = function(...)
local val = ''
- for i=1,(select('#', ...)/2) do
- val = ('%s[%s,%s],'):format(val, select(i * 2 - 1, ...),
- select(i * 2, ...))
+ for i = 1, (select('#', ...) / 2) do
+ val = ('%s[%s,%s],'):format(val, select(i * 2 - 1, ...), select(i * 2, ...))
end
return sp('map', '[' .. val .. ']')
end
- local nan = -(1.0/0.0-1.0/0.0)
- local inf = 1.0/0.0
- local minus_inf = -(1.0/0.0)
+ local nan = -(1.0 / 0.0 - 1.0 / 0.0)
+ local inf = 1.0 / 0.0
+ local minus_inf = -(1.0 / 0.0)
describe('function msgpack#equal', function()
local msgpack_eq = function(expected, a, b)
@@ -39,10 +40,8 @@ describe('autoload/msgpack.vim', function()
msgpack_eq(0, '1', '0')
end)
it('compares integer specials correctly', function()
- msgpack_eq(1, sp('integer', '[-1, 1, 0, 0]'),
- sp('integer', '[-1, 1, 0, 0]'))
- msgpack_eq(0, sp('integer', '[-1, 1, 0, 0]'),
- sp('integer', '[ 1, 1, 0, 0]'))
+ msgpack_eq(1, sp('integer', '[-1, 1, 0, 0]'), sp('integer', '[-1, 1, 0, 0]'))
+ msgpack_eq(0, sp('integer', '[-1, 1, 0, 0]'), sp('integer', '[ 1, 1, 0, 0]'))
end)
it('compares integer specials with raw integer correctly', function()
msgpack_eq(1, sp('integer', '[-1, 0, 0, 1]'), '-1')
@@ -58,27 +57,21 @@ describe('autoload/msgpack.vim', function()
msgpack_eq(0, '"abc\\ndef"', '"abc\\nghi"')
end)
it('compares binary specials correctly', function()
- msgpack_eq(1, sp('binary', '["abc\\n", "def"]'),
- sp('binary', '["abc\\n", "def"]'))
- msgpack_eq(0, sp('binary', '["abc", "def"]'),
- sp('binary', '["abc\\n", "def"]'))
+ msgpack_eq(1, sp('binary', '["abc\\n", "def"]'), sp('binary', '["abc\\n", "def"]'))
+ msgpack_eq(0, sp('binary', '["abc", "def"]'), sp('binary', '["abc\\n", "def"]'))
end)
it('compares binary specials with raw binaries correctly', function()
msgpack_eq(1, sp('binary', '["abc", "def"]'), '"abc\\ndef"')
msgpack_eq(0, sp('binary', '["abc", "def"]'), '"abcdef"')
end)
it('compares string specials correctly', function()
- msgpack_eq(1, sp('string', '["abc\\n", "def"]'),
- sp('string', '["abc\\n", "def"]'))
- msgpack_eq(0, sp('string', '["abc", "def"]'),
- sp('string', '["abc\\n", "def"]'))
+ msgpack_eq(1, sp('string', '["abc\\n", "def"]'), sp('string', '["abc\\n", "def"]'))
+ msgpack_eq(0, sp('string', '["abc", "def"]'), sp('string', '["abc\\n", "def"]'))
end)
it('compares string specials with binary correctly', function()
- msgpack_eq(0, sp('string', '["abc\\n", "def"]'),
- sp('binary', '["abc\\n", "def"]'))
+ msgpack_eq(0, sp('string', '["abc\\n", "def"]'), sp('binary', '["abc\\n", "def"]'))
msgpack_eq(0, sp('string', '["abc", "def"]'), '"abc\\ndef"')
- msgpack_eq(0, sp('binary', '["abc\\n", "def"]'),
- sp('string', '["abc\\n", "def"]'))
+ msgpack_eq(0, sp('binary', '["abc\\n", "def"]'), sp('string', '["abc\\n", "def"]'))
msgpack_eq(0, '"abc\\ndef"', sp('string', '["abc", "def"]'))
end)
it('compares ext specials correctly', function()
@@ -97,44 +90,54 @@ describe('autoload/msgpack.vim', function()
end)
it('compares map specials correctly', function()
msgpack_eq(1, mapsp(), mapsp())
- msgpack_eq(1, mapsp(sp('binary', '[""]'), '""'),
- mapsp(sp('binary', '[""]'), '""'))
- msgpack_eq(1, mapsp(mapsp('1', '1'), mapsp('1', '1')),
- mapsp(mapsp('1', '1'), mapsp('1', '1')))
+ msgpack_eq(1, mapsp(sp('binary', '[""]'), '""'), mapsp(sp('binary', '[""]'), '""'))
+ msgpack_eq(
+ 1,
+ mapsp(mapsp('1', '1'), mapsp('1', '1')),
+ mapsp(mapsp('1', '1'), mapsp('1', '1'))
+ )
msgpack_eq(0, mapsp(), mapsp('1', '1'))
- msgpack_eq(0, mapsp(sp('binary', '["a"]'), '""'),
- mapsp(sp('binary', '[""]'), '""'))
- msgpack_eq(0, mapsp(sp('binary', '[""]'), '"a"'),
- mapsp(sp('binary', '[""]'), '""'))
- msgpack_eq(0, mapsp(sp('binary', '["a"]'), '"a"'),
- mapsp(sp('binary', '[""]'), '""'))
- msgpack_eq(0, mapsp(mapsp('1', '1'), mapsp('1', '1')),
- mapsp(sp('binary', '[""]'), mapsp('1', '1')))
- msgpack_eq(0, mapsp(mapsp('1', '1'), mapsp('1', '1')),
- mapsp(mapsp('2', '1'), mapsp('1', '1')))
- msgpack_eq(0, mapsp(mapsp('1', '1'), mapsp('1', '1')),
- mapsp(mapsp('1', '2'), mapsp('1', '1')))
- msgpack_eq(0, mapsp(mapsp('1', '1'), mapsp('1', '1')),
- mapsp(mapsp('1', '1'), mapsp('2', '1')))
- msgpack_eq(0, mapsp(mapsp('1', '1'), mapsp('1', '1')),
- mapsp(mapsp('1', '1'), mapsp('1', '2')))
- msgpack_eq(1, mapsp(mapsp('2', '1'), mapsp('1', '1'),
- mapsp('1', '1'), mapsp('1', '1')),
- mapsp(mapsp('1', '1'), mapsp('1', '1'),
- mapsp('2', '1'), mapsp('1', '1')))
+ msgpack_eq(0, mapsp(sp('binary', '["a"]'), '""'), mapsp(sp('binary', '[""]'), '""'))
+ msgpack_eq(0, mapsp(sp('binary', '[""]'), '"a"'), mapsp(sp('binary', '[""]'), '""'))
+ msgpack_eq(0, mapsp(sp('binary', '["a"]'), '"a"'), mapsp(sp('binary', '[""]'), '""'))
+ msgpack_eq(
+ 0,
+ mapsp(mapsp('1', '1'), mapsp('1', '1')),
+ mapsp(sp('binary', '[""]'), mapsp('1', '1'))
+ )
+ msgpack_eq(
+ 0,
+ mapsp(mapsp('1', '1'), mapsp('1', '1')),
+ mapsp(mapsp('2', '1'), mapsp('1', '1'))
+ )
+ msgpack_eq(
+ 0,
+ mapsp(mapsp('1', '1'), mapsp('1', '1')),
+ mapsp(mapsp('1', '2'), mapsp('1', '1'))
+ )
+ msgpack_eq(
+ 0,
+ mapsp(mapsp('1', '1'), mapsp('1', '1')),
+ mapsp(mapsp('1', '1'), mapsp('2', '1'))
+ )
+ msgpack_eq(
+ 0,
+ mapsp(mapsp('1', '1'), mapsp('1', '1')),
+ mapsp(mapsp('1', '1'), mapsp('1', '2'))
+ )
+ msgpack_eq(
+ 1,
+ mapsp(mapsp('2', '1'), mapsp('1', '1'), mapsp('1', '1'), mapsp('1', '1')),
+ mapsp(mapsp('1', '1'), mapsp('1', '1'), mapsp('2', '1'), mapsp('1', '1'))
+ )
end)
it('compares map specials with raw maps correctly', function()
msgpack_eq(1, mapsp(), '{}')
msgpack_eq(1, mapsp(sp('string', '["1"]'), '1'), '{"1": 1}')
- msgpack_eq(1, mapsp(sp('string', '["1"]'), sp('integer', '[1, 0, 0, 1]')),
- '{"1": 1}')
- msgpack_eq(0, mapsp(sp('integer', '[1, 0, 0, 1]'), sp('string', '["1"]')),
- '{1: "1"}')
- msgpack_eq(0, mapsp('"1"', sp('integer', '[1, 0, 0, 1]')),
- '{"1": 1}')
- msgpack_eq(0,
- mapsp(sp('string', '["1"]'), '1', sp('string', '["2"]'), '2'),
- '{"1": 1}')
+ msgpack_eq(1, mapsp(sp('string', '["1"]'), sp('integer', '[1, 0, 0, 1]')), '{"1": 1}')
+ msgpack_eq(0, mapsp(sp('integer', '[1, 0, 0, 1]'), sp('string', '["1"]')), '{1: "1"}')
+ msgpack_eq(0, mapsp('"1"', sp('integer', '[1, 0, 0, 1]')), '{"1": 1}')
+ msgpack_eq(0, mapsp(sp('string', '["1"]'), '1', sp('string', '["2"]'), '2'), '{"1": 1}')
msgpack_eq(0, mapsp(sp('string', '["1"]'), '1'), '{"1": 1, "2": 2}')
end)
it('compares raw arrays correctly', function()
@@ -195,8 +198,7 @@ describe('autoload/msgpack.vim', function()
end)
it('compares float specials correctly', function()
msgpack_eq(1, sp('float', '0.0'), sp('float', '0.0'))
- msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'),
- sp('float', '(1.0/0.0-1.0/0.0)'))
+ msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '(1.0/0.0-1.0/0.0)'))
msgpack_eq(1, sp('float', '1.0/0.0'), sp('float', '1.0/0.0'))
msgpack_eq(1, sp('float', '-(1.0/0.0)'), sp('float', '-(1.0/0.0)'))
msgpack_eq(1, sp('float', '0.0'), sp('float', '0.0'))
@@ -206,10 +208,8 @@ describe('autoload/msgpack.vim', function()
msgpack_eq(0, sp('float', '0.0'), sp('float', '-(1.0/0.0)'))
msgpack_eq(0, sp('float', '1.0/0.0'), sp('float', '-(1.0/0.0)'))
msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '-(1.0/0.0)'))
- msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'),
- sp('float', '-(1.0/0.0-1.0/0.0)'))
- msgpack_eq(1, sp('float', '-(1.0/0.0-1.0/0.0)'),
- sp('float', '-(1.0/0.0-1.0/0.0)'))
+ msgpack_eq(1, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '-(1.0/0.0-1.0/0.0)'))
+ msgpack_eq(1, sp('float', '-(1.0/0.0-1.0/0.0)'), sp('float', '-(1.0/0.0-1.0/0.0)'))
msgpack_eq(0, sp('float', '(1.0/0.0-1.0/0.0)'), sp('float', '1.0/0.0'))
end)
it('compares boolean specials correctly', function()
@@ -219,8 +219,7 @@ describe('autoload/msgpack.vim', function()
it('compares nil specials correctly', function()
msgpack_eq(1, sp('nil', '1'), sp('nil', '0'))
end)
- it('compares nil, boolean and integer values with each other correctly',
- function()
+ it('compares nil, boolean and integer values with each other correctly', function()
msgpack_eq(0, sp('boolean', '1'), '1')
msgpack_eq(0, sp('boolean', '1'), sp('nil', '0'))
msgpack_eq(0, sp('boolean', '1'), sp('nil', '1'))
@@ -238,16 +237,11 @@ describe('autoload/msgpack.vim', function()
it('works', function()
eq(1, nvim_eval('msgpack#is_int(1)'))
eq(1, nvim_eval('msgpack#is_int(-1)'))
- eq(1, nvim_eval(('msgpack#is_int(%s)'):format(
- sp('integer', '[1, 0, 0, 1]'))))
- eq(1, nvim_eval(('msgpack#is_int(%s)'):format(
- sp('integer', '[-1, 0, 0, 1]'))))
- eq(0, nvim_eval(('msgpack#is_int(%s)'):format(
- sp('float', '0.0'))))
- eq(0, nvim_eval(('msgpack#is_int(%s)'):format(
- sp('boolean', '0'))))
- eq(0, nvim_eval(('msgpack#is_int(%s)'):format(
- sp('nil', '0'))))
+ eq(1, nvim_eval(('msgpack#is_int(%s)'):format(sp('integer', '[1, 0, 0, 1]'))))
+ eq(1, nvim_eval(('msgpack#is_int(%s)'):format(sp('integer', '[-1, 0, 0, 1]'))))
+ eq(0, nvim_eval(('msgpack#is_int(%s)'):format(sp('float', '0.0'))))
+ eq(0, nvim_eval(('msgpack#is_int(%s)'):format(sp('boolean', '0'))))
+ eq(0, nvim_eval(('msgpack#is_int(%s)'):format(sp('nil', '0'))))
eq(0, nvim_eval('msgpack#is_int("")'))
end)
end)
@@ -256,16 +250,11 @@ describe('autoload/msgpack.vim', function()
it('works', function()
eq(1, nvim_eval('msgpack#is_uint(1)'))
eq(0, nvim_eval('msgpack#is_uint(-1)'))
- eq(1, nvim_eval(('msgpack#is_uint(%s)'):format(
- sp('integer', '[1, 0, 0, 1]'))))
- eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(
- sp('integer', '[-1, 0, 0, 1]'))))
- eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(
- sp('float', '0.0'))))
- eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(
- sp('boolean', '0'))))
- eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(
- sp('nil', '0'))))
+ eq(1, nvim_eval(('msgpack#is_uint(%s)'):format(sp('integer', '[1, 0, 0, 1]'))))
+ eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('integer', '[-1, 0, 0, 1]'))))
+ eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('float', '0.0'))))
+ eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('boolean', '0'))))
+ eq(0, nvim_eval(('msgpack#is_uint(%s)'):format(sp('nil', '0'))))
eq(0, nvim_eval('msgpack#is_uint("")'))
end)
end)
@@ -274,18 +263,20 @@ describe('autoload/msgpack.vim', function()
it('works', function()
local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
eq(epoch, nvim_eval('msgpack#strftime("%Y-%m-%dT%H:%M:%S", 0)'))
- eq(epoch, nvim_eval(
- ('msgpack#strftime("%%Y-%%m-%%dT%%H:%%M:%%S", %s)'):format(sp(
- 'integer', '[1, 0, 0, 0]'))))
+ eq(
+ epoch,
+ nvim_eval(
+ ('msgpack#strftime("%%Y-%%m-%%dT%%H:%%M:%%S", %s)'):format(sp('integer', '[1, 0, 0, 0]'))
+ )
+ )
end)
end)
describe('function msgpack#strptime', function()
it('works', function()
- for _, v in ipairs({0, 10, 100000, 204, 1000000000}) do
+ for _, v in ipairs({ 0, 10, 100000, 204, 1000000000 }) do
local time = os.date('%Y-%m-%dT%H:%M:%S', v)
- eq(v, nvim_eval('msgpack#strptime("%Y-%m-%dT%H:%M:%S", '
- .. '"' .. time .. '")'))
+ eq(v, nvim_eval('msgpack#strptime("%Y-%m-%dT%H:%M:%S", ' .. '"' .. time .. '")'))
end
end)
end)
@@ -367,25 +358,27 @@ describe('autoload/msgpack.vim', function()
string_eq('[[[[{}]]]]', sp('array', '[[[[{}]]]]'))
string_eq('{}', sp('map', '[]'))
string_eq('{2: 10}', sp('map', '[[2, 10]]'))
- string_eq('{{1: 1}: {1: 1}, {2: 1}: {1: 1}}',
- mapsp(mapsp('2', '1'), mapsp('1', '1'),
- mapsp('1', '1'), mapsp('1', '1')))
- string_eq('{{1: 1}: {1: 1}, {2: 1}: {1: 1}}',
- mapsp(mapsp('1', '1'), mapsp('1', '1'),
- mapsp('2', '1'), mapsp('1', '1')))
- string_eq('{[1, 2, {{1: 2}: 1}]: [1, 2, {{1: 2}: 1}]}',
- mapsp(('[1, 2, %s]'):format(mapsp(mapsp('1', '2'), '1')),
- ('[1, 2, %s]'):format(mapsp(mapsp('1', '2'), '1'))))
+ string_eq(
+ '{{1: 1}: {1: 1}, {2: 1}: {1: 1}}',
+ mapsp(mapsp('2', '1'), mapsp('1', '1'), mapsp('1', '1'), mapsp('1', '1'))
+ )
+ string_eq(
+ '{{1: 1}: {1: 1}, {2: 1}: {1: 1}}',
+ mapsp(mapsp('1', '1'), mapsp('1', '1'), mapsp('2', '1'), mapsp('1', '1'))
+ )
+ string_eq(
+ '{[1, 2, {{1: 2}: 1}]: [1, 2, {{1: 2}: 1}]}',
+ mapsp(
+ ('[1, 2, %s]'):format(mapsp(mapsp('1', '2'), '1')),
+ ('[1, 2, %s]'):format(mapsp(mapsp('1', '2'), '1'))
+ )
+ )
string_eq('0x0000000000000000', sp('integer', '[1, 0, 0, 0]'))
string_eq('-0x0000000100000000', sp('integer', '[-1, 0, 2, 0]'))
- string_eq('0x123456789abcdef0',
- sp('integer', '[ 1, 0, 610839793, 448585456]'))
- string_eq('-0x123456789abcdef0',
- sp('integer', '[-1, 0, 610839793, 448585456]'))
- string_eq('0xf23456789abcdef0',
- sp('integer', '[ 1, 3, 1684581617, 448585456]'))
- string_eq('-0x723456789abcdef0',
- sp('integer', '[-1, 1, 1684581617, 448585456]'))
+ string_eq('0x123456789abcdef0', sp('integer', '[ 1, 0, 610839793, 448585456]'))
+ string_eq('-0x123456789abcdef0', sp('integer', '[-1, 0, 610839793, 448585456]'))
+ string_eq('0xf23456789abcdef0', sp('integer', '[ 1, 3, 1684581617, 448585456]'))
+ string_eq('-0x723456789abcdef0', sp('integer', '[-1, 1, 1684581617, 448585456]'))
string_eq('0.0', sp('float', '0.0'))
string_eq('inf', sp('float', '(1.0/0.0)'))
string_eq('-inf', sp('float', '-(1.0/0.0)'))
@@ -466,15 +459,15 @@ describe('autoload/msgpack.vim', function()
nvim_command('let spbln._VAL = 1')
nvim_command('let spnil._VAL = 1')
- eq({_TYPE={}, _VAL={{{}}}}, nvim_eval('sparr2'))
- eq({_TYPE={}, _VAL={{'abc', {{}}}}}, nvim_eval('spmap2'))
- eq({_TYPE={}, _VAL={1, 0, 0, 0}}, nvim_eval('spint2'))
- eq({_TYPE={}, _VAL=1.0}, nvim_eval('spflt2'))
- eq({_TYPE={}, _VAL={2, {'abc', 'def'}}}, nvim_eval('spext2'))
- eq({_TYPE={}, _VAL={'abc', 'def'}}, nvim_eval('spstr2'))
- eq({_TYPE={}, _VAL={'abc', 'def'}}, nvim_eval('spbin2'))
- eq({_TYPE={}, _VAL=0}, nvim_eval('spbln2'))
- eq({_TYPE={}, _VAL=0}, nvim_eval('spnil2'))
+ eq({ _TYPE = {}, _VAL = { { {} } } }, nvim_eval('sparr2'))
+ eq({ _TYPE = {}, _VAL = { { 'abc', { {} } } } }, nvim_eval('spmap2'))
+ eq({ _TYPE = {}, _VAL = { 1, 0, 0, 0 } }, nvim_eval('spint2'))
+ eq({ _TYPE = {}, _VAL = 1.0 }, nvim_eval('spflt2'))
+ eq({ _TYPE = {}, _VAL = { 2, { 'abc', 'def' } } }, nvim_eval('spext2'))
+ eq({ _TYPE = {}, _VAL = { 'abc', 'def' } }, nvim_eval('spstr2'))
+ eq({ _TYPE = {}, _VAL = { 'abc', 'def' } }, nvim_eval('spbin2'))
+ eq({ _TYPE = {}, _VAL = 0 }, nvim_eval('spbln2'))
+ eq({ _TYPE = {}, _VAL = 0 }, nvim_eval('spnil2'))
nvim_command('let sparr._TYPE = []')
nvim_command('let spmap._TYPE = []')
@@ -525,38 +518,40 @@ describe('autoload/msgpack.vim', function()
nvim_command('let flt = 3.0')
nvim_command('let bin = ""')
- eq({{{}}}, nvim_eval('arr2'))
- eq({['1']={}}, nvim_eval('map2'))
+ eq({ { {} } }, nvim_eval('arr2'))
+ eq({ ['1'] = {} }, nvim_eval('map2'))
eq(1, nvim_eval('int2'))
eq(2.0, nvim_eval('flt2'))
eq('abc', nvim_eval('bin2'))
end)
it('works for special v: values like v:true', function()
- meths.set_var('true', true)
- meths.set_var('false', false)
- meths.set_var('nil', NIL)
+ api.nvim_set_var('true', true)
+ api.nvim_set_var('false', false)
+ api.nvim_set_var('nil', NIL)
nvim_command('let true2 = msgpack#deepcopy(true)')
nvim_command('let false2 = msgpack#deepcopy(false)')
nvim_command('let nil2 = msgpack#deepcopy(nil)')
- eq(true, meths.get_var('true'))
- eq(false, meths.get_var('false'))
- eq(NIL, meths.get_var('nil'))
+ eq(true, api.nvim_get_var('true'))
+ eq(false, api.nvim_get_var('false'))
+ eq(NIL, api.nvim_get_var('nil'))
end)
end)
describe('function msgpack#eval', function()
local eval_eq = function(expected_type, expected_val, str, ...)
- nvim_command(('let g:__val = msgpack#eval(\'%s\', %s)'):format(str:gsub(
- '\'', '\'\''), select(1, ...) or '{}'))
+ nvim_command(
+ ("let g:__val = msgpack#eval('%s', %s)"):format(str:gsub("'", "''"), select(1, ...) or '{}')
+ )
eq(expected_type, nvim_eval('msgpack#type(g:__val)'))
local expected_val_full = expected_val
- if (not (({float=true, integer=true})[expected_type]
- and type(expected_val) ~= 'table')
- and expected_type ~= 'array') then
- expected_val_full = {_TYPE={}, _VAL=expected_val_full}
+ if
+ not (({ float = true, integer = true })[expected_type] and type(expected_val) ~= 'table')
+ and expected_type ~= 'array'
+ then
+ expected_val_full = { _TYPE = {}, _VAL = expected_val_full }
end
if expected_val_full == expected_val_full then
eq(expected_val_full, nvim_eval('g:__val'))
@@ -570,68 +565,65 @@ describe('autoload/msgpack.vim', function()
end
it('correctly loads binary strings', function()
- eval_eq('binary', {'abcdef'}, '"abcdef"')
- eval_eq('binary', {'abc', 'def'}, '"abc\\ndef"')
- eval_eq('binary', {'abc\ndef'}, '"abc\\0def"')
- eval_eq('binary', {'\nabc\ndef\n'}, '"\\0abc\\0def\\0"')
- eval_eq('binary', {'abc\n\n\ndef'}, '"abc\\0\\0\\0def"')
- eval_eq('binary', {'abc\n', '\ndef'}, '"abc\\0\\n\\0def"')
- eval_eq('binary', {'abc', '', '', 'def'}, '"abc\\n\\n\\ndef"')
- eval_eq('binary', {'abc', '', '', 'def', ''}, '"abc\\n\\n\\ndef\\n"')
- eval_eq('binary', {'', 'abc', '', '', 'def'}, '"\\nabc\\n\\n\\ndef"')
- eval_eq('binary', {''}, '""')
- eval_eq('binary', {'"'}, '"\\""')
- eval_eq('binary', {'py3 print(sys.version_info)'},
- '"py3 print(sys.version_info)"')
+ eval_eq('binary', { 'abcdef' }, '"abcdef"')
+ eval_eq('binary', { 'abc', 'def' }, '"abc\\ndef"')
+ eval_eq('binary', { 'abc\ndef' }, '"abc\\0def"')
+ eval_eq('binary', { '\nabc\ndef\n' }, '"\\0abc\\0def\\0"')
+ eval_eq('binary', { 'abc\n\n\ndef' }, '"abc\\0\\0\\0def"')
+ eval_eq('binary', { 'abc\n', '\ndef' }, '"abc\\0\\n\\0def"')
+ eval_eq('binary', { 'abc', '', '', 'def' }, '"abc\\n\\n\\ndef"')
+ eval_eq('binary', { 'abc', '', '', 'def', '' }, '"abc\\n\\n\\ndef\\n"')
+ eval_eq('binary', { '', 'abc', '', '', 'def' }, '"\\nabc\\n\\n\\ndef"')
+ eval_eq('binary', { '' }, '""')
+ eval_eq('binary', { '"' }, '"\\""')
+ eval_eq('binary', { 'py3 print(sys.version_info)' }, '"py3 print(sys.version_info)"')
end)
it('correctly loads strings', function()
- eval_eq('string', {'abcdef'}, '="abcdef"')
- eval_eq('string', {'abc', 'def'}, '="abc\\ndef"')
- eval_eq('string', {'abc\ndef'}, '="abc\\0def"')
- eval_eq('string', {'\nabc\ndef\n'}, '="\\0abc\\0def\\0"')
- eval_eq('string', {'abc\n\n\ndef'}, '="abc\\0\\0\\0def"')
- eval_eq('string', {'abc\n', '\ndef'}, '="abc\\0\\n\\0def"')
- eval_eq('string', {'abc', '', '', 'def'}, '="abc\\n\\n\\ndef"')
- eval_eq('string', {'abc', '', '', 'def', ''}, '="abc\\n\\n\\ndef\\n"')
- eval_eq('string', {'', 'abc', '', '', 'def'}, '="\\nabc\\n\\n\\ndef"')
- eval_eq('string', {''}, '=""')
- eval_eq('string', {'"'}, '="\\""')
- eval_eq('string', {'py3 print(sys.version_info)'},
- '="py3 print(sys.version_info)"')
+ eval_eq('string', { 'abcdef' }, '="abcdef"')
+ eval_eq('string', { 'abc', 'def' }, '="abc\\ndef"')
+ eval_eq('string', { 'abc\ndef' }, '="abc\\0def"')
+ eval_eq('string', { '\nabc\ndef\n' }, '="\\0abc\\0def\\0"')
+ eval_eq('string', { 'abc\n\n\ndef' }, '="abc\\0\\0\\0def"')
+ eval_eq('string', { 'abc\n', '\ndef' }, '="abc\\0\\n\\0def"')
+ eval_eq('string', { 'abc', '', '', 'def' }, '="abc\\n\\n\\ndef"')
+ eval_eq('string', { 'abc', '', '', 'def', '' }, '="abc\\n\\n\\ndef\\n"')
+ eval_eq('string', { '', 'abc', '', '', 'def' }, '="\\nabc\\n\\n\\ndef"')
+ eval_eq('string', { '' }, '=""')
+ eval_eq('string', { '"' }, '="\\""')
+ eval_eq('string', { 'py3 print(sys.version_info)' }, '="py3 print(sys.version_info)"')
end)
it('correctly loads ext values', function()
- eval_eq('ext', {0, {'abcdef'}}, '+(0)"abcdef"')
- eval_eq('ext', {0, {'abc', 'def'}}, '+(0)"abc\\ndef"')
- eval_eq('ext', {0, {'abc\ndef'}}, '+(0)"abc\\0def"')
- eval_eq('ext', {0, {'\nabc\ndef\n'}}, '+(0)"\\0abc\\0def\\0"')
- eval_eq('ext', {0, {'abc\n\n\ndef'}}, '+(0)"abc\\0\\0\\0def"')
- eval_eq('ext', {0, {'abc\n', '\ndef'}}, '+(0)"abc\\0\\n\\0def"')
- eval_eq('ext', {0, {'abc', '', '', 'def'}}, '+(0)"abc\\n\\n\\ndef"')
- eval_eq('ext', {0, {'abc', '', '', 'def', ''}},
- '+(0)"abc\\n\\n\\ndef\\n"')
- eval_eq('ext', {0, {'', 'abc', '', '', 'def'}},
- '+(0)"\\nabc\\n\\n\\ndef"')
- eval_eq('ext', {0, {''}}, '+(0)""')
- eval_eq('ext', {0, {'"'}}, '+(0)"\\""')
-
- eval_eq('ext', {-1, {'abcdef'}}, '+(-1)"abcdef"')
- eval_eq('ext', {-1, {'abc', 'def'}}, '+(-1)"abc\\ndef"')
- eval_eq('ext', {-1, {'abc\ndef'}}, '+(-1)"abc\\0def"')
- eval_eq('ext', {-1, {'\nabc\ndef\n'}}, '+(-1)"\\0abc\\0def\\0"')
- eval_eq('ext', {-1, {'abc\n\n\ndef'}}, '+(-1)"abc\\0\\0\\0def"')
- eval_eq('ext', {-1, {'abc\n', '\ndef'}}, '+(-1)"abc\\0\\n\\0def"')
- eval_eq('ext', {-1, {'abc', '', '', 'def'}}, '+(-1)"abc\\n\\n\\ndef"')
- eval_eq('ext', {-1, {'abc', '', '', 'def', ''}},
- '+(-1)"abc\\n\\n\\ndef\\n"')
- eval_eq('ext', {-1, {'', 'abc', '', '', 'def'}},
- '+(-1)"\\nabc\\n\\n\\ndef"')
- eval_eq('ext', {-1, {''}}, '+(-1)""')
- eval_eq('ext', {-1, {'"'}}, '+(-1)"\\""')
-
- eval_eq('ext', {42, {'py3 print(sys.version_info)'}},
- '+(42)"py3 print(sys.version_info)"')
+ eval_eq('ext', { 0, { 'abcdef' } }, '+(0)"abcdef"')
+ eval_eq('ext', { 0, { 'abc', 'def' } }, '+(0)"abc\\ndef"')
+ eval_eq('ext', { 0, { 'abc\ndef' } }, '+(0)"abc\\0def"')
+ eval_eq('ext', { 0, { '\nabc\ndef\n' } }, '+(0)"\\0abc\\0def\\0"')
+ eval_eq('ext', { 0, { 'abc\n\n\ndef' } }, '+(0)"abc\\0\\0\\0def"')
+ eval_eq('ext', { 0, { 'abc\n', '\ndef' } }, '+(0)"abc\\0\\n\\0def"')
+ eval_eq('ext', { 0, { 'abc', '', '', 'def' } }, '+(0)"abc\\n\\n\\ndef"')
+ eval_eq('ext', { 0, { 'abc', '', '', 'def', '' } }, '+(0)"abc\\n\\n\\ndef\\n"')
+ eval_eq('ext', { 0, { '', 'abc', '', '', 'def' } }, '+(0)"\\nabc\\n\\n\\ndef"')
+ eval_eq('ext', { 0, { '' } }, '+(0)""')
+ eval_eq('ext', { 0, { '"' } }, '+(0)"\\""')
+
+ eval_eq('ext', { -1, { 'abcdef' } }, '+(-1)"abcdef"')
+ eval_eq('ext', { -1, { 'abc', 'def' } }, '+(-1)"abc\\ndef"')
+ eval_eq('ext', { -1, { 'abc\ndef' } }, '+(-1)"abc\\0def"')
+ eval_eq('ext', { -1, { '\nabc\ndef\n' } }, '+(-1)"\\0abc\\0def\\0"')
+ eval_eq('ext', { -1, { 'abc\n\n\ndef' } }, '+(-1)"abc\\0\\0\\0def"')
+ eval_eq('ext', { -1, { 'abc\n', '\ndef' } }, '+(-1)"abc\\0\\n\\0def"')
+ eval_eq('ext', { -1, { 'abc', '', '', 'def' } }, '+(-1)"abc\\n\\n\\ndef"')
+ eval_eq('ext', { -1, { 'abc', '', '', 'def', '' } }, '+(-1)"abc\\n\\n\\ndef\\n"')
+ eval_eq('ext', { -1, { '', 'abc', '', '', 'def' } }, '+(-1)"\\nabc\\n\\n\\ndef"')
+ eval_eq('ext', { -1, { '' } }, '+(-1)""')
+ eval_eq('ext', { -1, { '"' } }, '+(-1)"\\""')
+
+ eval_eq(
+ 'ext',
+ { 42, { 'py3 print(sys.version_info)' } },
+ '+(42)"py3 print(sys.version_info)"'
+ )
end)
it('correctly loads floats', function()
@@ -650,17 +642,17 @@ describe('autoload/msgpack.vim', function()
it('correctly loads integers', function()
eval_eq('integer', 10, '10')
eval_eq('integer', -10, '-10')
- eval_eq('integer', { 1, 0, 610839793, 448585456}, ' 0x123456789ABCDEF0')
- eval_eq('integer', {-1, 0, 610839793, 448585456}, '-0x123456789ABCDEF0')
- eval_eq('integer', { 1, 3, 1684581617, 448585456}, ' 0xF23456789ABCDEF0')
- eval_eq('integer', {-1, 1, 1684581617, 448585456}, '-0x723456789ABCDEF0')
- eval_eq('integer', { 1, 0, 0, 0x100}, '0x100')
- eval_eq('integer', {-1, 0, 0, 0x100}, '-0x100')
+ eval_eq('integer', { 1, 0, 610839793, 448585456 }, ' 0x123456789ABCDEF0')
+ eval_eq('integer', { -1, 0, 610839793, 448585456 }, '-0x123456789ABCDEF0')
+ eval_eq('integer', { 1, 3, 1684581617, 448585456 }, ' 0xF23456789ABCDEF0')
+ eval_eq('integer', { -1, 1, 1684581617, 448585456 }, '-0x723456789ABCDEF0')
+ eval_eq('integer', { 1, 0, 0, 0x100 }, '0x100')
+ eval_eq('integer', { -1, 0, 0, 0x100 }, '-0x100')
- eval_eq('integer', ('a'):byte(), '\'a\'')
- eval_eq('integer', 0xAB, '\'«\'')
- eval_eq('integer', 0, '\'\\0\'')
- eval_eq('integer', 10246567, '\'\\10246567\'')
+ eval_eq('integer', ('a'):byte(), "'a'")
+ eval_eq('integer', 0xAB, "'«'")
+ eval_eq('integer', 0, "'\\0'")
+ eval_eq('integer', 10246567, "'\\10246567'")
end)
it('correctly loads constants', function()
@@ -668,71 +660,94 @@ describe('autoload/msgpack.vim', function()
eval_eq('boolean', 0, 'FALSE')
eval_eq('nil', 0, 'NIL')
eval_eq('nil', 0, 'NIL', '{"NIL": 1, "nan": 2, "T": 3}')
- eval_eq('float', nan, 'nan',
- '{"NIL": "1", "nan": "2", "T": "3"}')
+ eval_eq('float', nan, 'nan', '{"NIL": "1", "nan": "2", "T": "3"}')
eval_eq('integer', 3, 'T', '{"NIL": "1", "nan": "2", "T": "3"}')
- eval_eq('integer', {1, 0, 0, 0}, 'T',
- ('{"NIL": "1", "nan": "2", "T": \'%s\'}'):format(
- sp('integer', '[1, 0, 0, 0]')))
+ eval_eq(
+ 'integer',
+ { 1, 0, 0, 0 },
+ 'T',
+ ('{"NIL": "1", "nan": "2", "T": \'%s\'}'):format(sp('integer', '[1, 0, 0, 0]'))
+ )
end)
it('correctly loads maps', function()
eval_eq('map', {}, '{}')
- eval_eq('map', {{{_TYPE={}, _VAL={{1, 2}}}, {_TYPE={}, _VAL={{3, 4}}}}},
- '{{1: 2}: {3: 4}}')
- eval_eq('map', {{{_TYPE={}, _VAL={{1, 2}}}, {_TYPE={}, _VAL={{3, 4}}}},
- {1, 2}},
- '{{1: 2}: {3: 4}, 1: 2}')
-
- eval_eq('map', {{{_TYPE={}, _VAL={
- {{_TYPE={}, _VAL={'py3 print(sys.version_info)'}},
- 2}}},
- {_TYPE={}, _VAL={{3, 4}}}},
- {1, 2}},
- '{{"py3 print(sys.version_info)": 2}: {3: 4}, 1: 2}')
+ eval_eq(
+ 'map',
+ { { { _TYPE = {}, _VAL = { { 1, 2 } } }, { _TYPE = {}, _VAL = { { 3, 4 } } } } },
+ '{{1: 2}: {3: 4}}'
+ )
+ eval_eq(
+ 'map',
+ { { { _TYPE = {}, _VAL = { { 1, 2 } } }, { _TYPE = {}, _VAL = { { 3, 4 } } } }, { 1, 2 } },
+ '{{1: 2}: {3: 4}, 1: 2}'
+ )
+
+ eval_eq('map', {
+ {
+ {
+ _TYPE = {},
+ _VAL = {
+ { { _TYPE = {}, _VAL = { 'py3 print(sys.version_info)' } }, 2 },
+ },
+ },
+ { _TYPE = {}, _VAL = { { 3, 4 } } },
+ },
+ { 1, 2 },
+ }, '{{"py3 print(sys.version_info)": 2}: {3: 4}, 1: 2}')
end)
it('correctly loads arrays', function()
eval_eq('array', {}, '[]')
- eval_eq('array', {1}, '[1]')
- eval_eq('array', {{_TYPE={}, _VAL=1}}, '[TRUE]')
- eval_eq('array', {{{_TYPE={}, _VAL={{1, 2}}}}, {_TYPE={}, _VAL={{3, 4}}}},
- '[[{1: 2}], {3: 4}]')
+ eval_eq('array', { 1 }, '[1]')
+ eval_eq('array', { { _TYPE = {}, _VAL = 1 } }, '[TRUE]')
+ eval_eq(
+ 'array',
+ { { { _TYPE = {}, _VAL = { { 1, 2 } } } }, { _TYPE = {}, _VAL = { { 3, 4 } } } },
+ '[[{1: 2}], {3: 4}]'
+ )
- eval_eq('array', {{_TYPE={}, _VAL={'py3 print(sys.version_info)'}}},
- '["py3 print(sys.version_info)"]')
+ eval_eq(
+ 'array',
+ { { _TYPE = {}, _VAL = { 'py3 print(sys.version_info)' } } },
+ '["py3 print(sys.version_info)"]'
+ )
end)
it('errors out when needed', function()
- eq('empty:Parsed string is empty',
- exc_exec('call msgpack#eval("", {})'))
- eq('unknown:Invalid non-space character: ^',
- exc_exec('call msgpack#eval("^", {})'))
- eq('char-invalid:Invalid integer character literal format: \'\'',
- exc_exec('call msgpack#eval("\'\'", {})'))
- eq('char-invalid:Invalid integer character literal format: \'ab\'',
- exc_exec('call msgpack#eval("\'ab\'", {})'))
- eq('char-invalid:Invalid integer character literal format: \'',
- exc_exec('call msgpack#eval("\'", {})'))
- eq('"-invalid:Invalid string: "',
- exc_exec('call msgpack#eval("\\"", {})'))
- eq('"-invalid:Invalid string: ="',
- exc_exec('call msgpack#eval("=\\"", {})'))
- eq('"-invalid:Invalid string: +(0)"',
- exc_exec('call msgpack#eval("+(0)\\"", {})'))
- eq('0.-nodigits:Decimal dot must be followed by digit(s): .e1',
- exc_exec('call msgpack#eval("0.e1", {})'))
- eq('0x-long:Must have at most 16 hex digits: FEDCBA98765432100',
- exc_exec('call msgpack#eval("0xFEDCBA98765432100", {})'))
- eq('0x-empty:Must have number after 0x: ',
- exc_exec('call msgpack#eval("0x", {})'))
- eq('name-unknown:Unknown name FOO: FOO',
- exc_exec('call msgpack#eval("FOO", {})'))
-
- eq('name-unknown:Unknown name py3: py3 print(sys.version_info)',
- exc_exec('call msgpack#eval("py3 print(sys.version_info)", {})'))
- eq('name-unknown:Unknown name o: o',
- exc_exec('call msgpack#eval("-info", {})'))
+ eq('empty:Parsed string is empty', exc_exec('call msgpack#eval("", {})'))
+ eq('unknown:Invalid non-space character: ^', exc_exec('call msgpack#eval("^", {})'))
+ eq(
+ "char-invalid:Invalid integer character literal format: ''",
+ exc_exec('call msgpack#eval("\'\'", {})')
+ )
+ eq(
+ "char-invalid:Invalid integer character literal format: 'ab'",
+ exc_exec('call msgpack#eval("\'ab\'", {})')
+ )
+ eq(
+ "char-invalid:Invalid integer character literal format: '",
+ exc_exec('call msgpack#eval("\'", {})')
+ )
+ eq('"-invalid:Invalid string: "', exc_exec('call msgpack#eval("\\"", {})'))
+ eq('"-invalid:Invalid string: ="', exc_exec('call msgpack#eval("=\\"", {})'))
+ eq('"-invalid:Invalid string: +(0)"', exc_exec('call msgpack#eval("+(0)\\"", {})'))
+ eq(
+ '0.-nodigits:Decimal dot must be followed by digit(s): .e1',
+ exc_exec('call msgpack#eval("0.e1", {})')
+ )
+ eq(
+ '0x-long:Must have at most 16 hex digits: FEDCBA98765432100',
+ exc_exec('call msgpack#eval("0xFEDCBA98765432100", {})')
+ )
+ eq('0x-empty:Must have number after 0x: ', exc_exec('call msgpack#eval("0x", {})'))
+ eq('name-unknown:Unknown name FOO: FOO', exc_exec('call msgpack#eval("FOO", {})'))
+
+ eq(
+ 'name-unknown:Unknown name py3: py3 print(sys.version_info)',
+ exc_exec('call msgpack#eval("py3 print(sys.version_info)", {})')
+ )
+ eq('name-unknown:Unknown name o: o', exc_exec('call msgpack#eval("-info", {})'))
end)
end)
end)
diff --git a/test/functional/plugin/shada_spec.lua b/test/functional/plugin/shada_spec.lua
index 8d37100607..1c20548321 100644
--- a/test/functional/plugin/shada_spec.lua
+++ b/test/functional/plugin/shada_spec.lua
@@ -1,25 +1,22 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
-local eq, meths, nvim_eval, nvim_command, nvim, exc_exec, funcs, nvim_feed, curbuf =
- helpers.eq, helpers.meths, helpers.eval, helpers.command, helpers.nvim, helpers.exc_exec,
- helpers.funcs, helpers.feed, helpers.curbuf
+local eq, api, nvim_eval, nvim_command, exc_exec, fn, nvim_feed =
+ helpers.eq, helpers.api, helpers.eval, helpers.command, helpers.exc_exec, helpers.fn, helpers.feed
local neq = helpers.neq
local read_file = helpers.read_file
-local mpack = require('mpack')
-
local shada_helpers = require('test.functional.shada.helpers')
local get_shada_rw = shada_helpers.get_shada_rw
local function reset(shada_file)
- clear{ args={'-u', 'NORC', '-i', shada_file or 'NONE', }}
+ clear { args = { '-u', 'NORC', '-i', shada_file or 'NONE' } }
end
local mpack_eq = function(expected, mpack_result)
- local mpack_keys = {'type', 'timestamp', 'length', 'value'}
+ local mpack_keys = { 'type', 'timestamp', 'length', 'value' }
- local unpack = mpack.Unpacker()
+ local unpack = vim.mpack.Unpacker()
local actual = {}
local cur, val
local i = 0
@@ -44,8 +41,7 @@ end
local wshada, _, fname = get_shada_rw('Xtest-functional-plugin-shada.shada')
-local wshada_tmp, _, fname_tmp =
- get_shada_rw('Xtest-functional-plugin-shada.shada.tmp.f')
+local wshada_tmp, _, fname_tmp = get_shada_rw('Xtest-functional-plugin-shada.shada.tmp.f')
describe('autoload/shada.vim', function()
local epoch = os.date('%Y-%m-%dT%H:%M:%S', 0)
@@ -89,29 +85,38 @@ describe('autoload/shada.vim', function()
it('works', function()
eq({}, nvim_eval(mpack2sd('[]')))
- eq({{type=1, timestamp=5, length=1, data=7}},
- nvim_eval(mpack2sd('[1, 5, 1, 7]')))
- eq({{type=1, timestamp=5, length=1, data=7},
- {type=1, timestamp=10, length=1, data=5}},
- nvim_eval(mpack2sd('[1, 5, 1, 7, 1, 10, 1, 5]')))
- eq('zero-uint:Entry 1 has type element which is zero',
- exc_exec('call ' .. mpack2sd('[0, 5, 1, 7]')))
- eq('zero-uint:Entry 1 has type element which is zero',
- exc_exec('call ' .. mpack2sd(('[%s, 5, 1, 7]'):format(
- sp('integer', '[1, 0, 0, 0]')))))
- eq('not-uint:Entry 1 has timestamp element which is not an unsigned integer',
- exc_exec('call ' .. mpack2sd('[1, -1, 1, 7]')))
- eq('not-uint:Entry 1 has length element which is not an unsigned integer',
- exc_exec('call ' .. mpack2sd('[1, 1, -1, 7]')))
- eq('not-uint:Entry 1 has type element which is not an unsigned integer',
- exc_exec('call ' .. mpack2sd('["", 1, -1, 7]')))
+ eq({ { type = 1, timestamp = 5, length = 1, data = 7 } }, nvim_eval(mpack2sd('[1, 5, 1, 7]')))
+ eq({
+ { type = 1, timestamp = 5, length = 1, data = 7 },
+ { type = 1, timestamp = 10, length = 1, data = 5 },
+ }, nvim_eval(mpack2sd('[1, 5, 1, 7, 1, 10, 1, 5]')))
+ eq(
+ 'zero-uint:Entry 1 has type element which is zero',
+ exc_exec('call ' .. mpack2sd('[0, 5, 1, 7]'))
+ )
+ eq(
+ 'zero-uint:Entry 1 has type element which is zero',
+ exc_exec('call ' .. mpack2sd(('[%s, 5, 1, 7]'):format(sp('integer', '[1, 0, 0, 0]'))))
+ )
+ eq(
+ 'not-uint:Entry 1 has timestamp element which is not an unsigned integer',
+ exc_exec('call ' .. mpack2sd('[1, -1, 1, 7]'))
+ )
+ eq(
+ 'not-uint:Entry 1 has length element which is not an unsigned integer',
+ exc_exec('call ' .. mpack2sd('[1, 1, -1, 7]'))
+ )
+ eq(
+ 'not-uint:Entry 1 has type element which is not an unsigned integer',
+ exc_exec('call ' .. mpack2sd('["", 1, -1, 7]'))
+ )
end)
end)
describe('function shada#sd_to_strings', function()
local sd2strings_eq = function(expected, arg)
if type(arg) == 'table' then
- eq(expected, funcs['shada#sd_to_strings'](arg))
+ eq(expected, fn['shada#sd_to_strings'](arg))
else
eq(expected, nvim_eval(('shada#sd_to_strings(%s)'):format(arg)))
end
@@ -124,15 +129,18 @@ describe('autoload/shada.vim', function()
it('works with unknown items', function()
sd2strings_eq({
'Unknown (0x64) with timestamp ' .. epoch .. ':',
- ' = 100'
- }, {{type=100, timestamp=0, length=1, data=100}})
-
- sd2strings_eq({
- 'Unknown (0x4000001180000006) with timestamp ' .. epoch .. ':',
- ' = 100'
- }, ('[{"type": %s, "timestamp": 0, "length": 1, "data": 100}]'):format(
- sp('integer', '[1, 1, 35, 6]')
- ))
+ ' = 100',
+ }, { { type = 100, timestamp = 0, length = 1, data = 100 } })
+
+ sd2strings_eq(
+ {
+ 'Unknown (0x4000001180000006) with timestamp ' .. epoch .. ':',
+ ' = 100',
+ },
+ ('[{"type": %s, "timestamp": 0, "length": 1, "data": 100}]'):format(
+ sp('integer', '[1, 1, 35, 6]')
+ )
+ )
end)
it('works with multiple unknown items', function()
@@ -141,8 +149,10 @@ describe('autoload/shada.vim', function()
' = 100',
'Unknown (0x65) with timestamp ' .. epoch .. ':',
' = 500',
- }, {{type=100, timestamp=0, length=1, data=100},
- {type=101, timestamp=0, length=1, data=500}})
+ }, {
+ { type = 100, timestamp = 0, length = 1, data = 100 },
+ { type = 101, timestamp = 0, length = 1, data = 500 },
+ })
end)
it('works with header items', function()
@@ -150,7 +160,7 @@ describe('autoload/shada.vim', function()
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
- }, {{type=1, timestamp=0, data={generator='test'}}})
+ }, { { type = 1, timestamp = 0, data = { generator = 'test' } } })
sd2strings_eq({
'Header with timestamp ' .. epoch .. ':',
' % Key Description Value',
@@ -158,42 +168,44 @@ describe('autoload/shada.vim', function()
' + b 2',
' + c column 3',
' + d 4',
- }, {{type=1, timestamp=0, data={a=1, b=2, c=3, d=4}}})
+ }, { { type = 1, timestamp = 0, data = { a = 1, b = 2, c = 3, d = 4 } } })
sd2strings_eq({
'Header with timestamp ' .. epoch .. ':',
' % Key Value',
' + t "test"',
- }, {{type=1, timestamp=0, data={t='test'}}})
+ }, { { type = 1, timestamp = 0, data = { t = 'test' } } })
sd2strings_eq({
'Header with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
- }, {{type=1, timestamp=0, data={1, 2, 3}}})
+ }, { { type = 1, timestamp = 0, data = { 1, 2, 3 } } })
end)
it('processes standard keys correctly, even in header', function()
- sd2strings_eq({
- 'Header with timestamp ' .. epoch .. ':',
- ' % Key Description________ Value',
- ' + c column 0',
- ' + f file name "/tmp/foo"',
- ' + l line number 10',
- ' + n name \'@\'',
- ' + rc contents ["abc", "def"]',
- ' + rt type CHARACTERWISE',
- ' + ru is_unnamed FALSE',
- ' + rw block width 10',
- ' + sb search backward TRUE',
- ' + sc smartcase value FALSE',
- ' + se place cursor at end TRUE',
- ' + sh v:hlsearch value TRUE',
- ' + sl has line offset FALSE',
- ' + sm magic value TRUE',
- ' + so offset value 10',
- ' + sp pattern "100"',
- ' + ss is :s pattern TRUE',
- ' + su is last used FALSE',
- }, ([[ [{'type': 1, 'timestamp': 0, 'data': {
+ sd2strings_eq(
+ {
+ 'Header with timestamp ' .. epoch .. ':',
+ ' % Key Description________ Value',
+ ' + c column 0',
+ ' + f file name "/tmp/foo"',
+ ' + l line number 10',
+ " + n name '@'",
+ ' + rc contents ["abc", "def"]',
+ ' + rt type CHARACTERWISE',
+ ' + ru is_unnamed FALSE',
+ ' + rw block width 10',
+ ' + sb search backward TRUE',
+ ' + sc smartcase value FALSE',
+ ' + se place cursor at end TRUE',
+ ' + sh v:hlsearch value TRUE',
+ ' + sl has line offset FALSE',
+ ' + sm magic value TRUE',
+ ' + so offset value 10',
+ ' + sp pattern "100"',
+ ' + ss is :s pattern TRUE',
+ ' + su is last used FALSE',
+ },
+ ([[ [{'type': 1, 'timestamp': 0, 'data': {
'sm': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'sc': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'sl': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
@@ -212,34 +224,37 @@ describe('autoload/shada.vim', function()
'l': 10,
'c': 0,
'f': '/tmp/foo',
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Header with timestamp ' .. epoch .. ':',
- ' % Key Description____ Value',
- ' # Expected integer',
- ' + c column "abc"',
- ' # Expected no NUL bytes',
- ' + f file name "abc\\0def"',
- ' # Value is negative',
- ' + l line number -10',
- ' # Value is negative',
- ' + n name -64',
- ' # Expected array value',
- ' + rc contents "10"',
- ' # Unexpected enum value: expected one of '
- .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
- ' + rt type 10',
- ' # Expected boolean',
- ' + ru is_unnamed 10',
- ' # Expected boolean',
- ' + sc smartcase value NIL',
- ' # Expected boolean',
- ' + sm magic value "TRUE"',
- ' # Expected integer',
- ' + so offset value "TRUE"',
- ' # Expected binary string',
- ' + sp pattern ="abc"',
- }, ([[ [{'type': 1, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Header with timestamp ' .. epoch .. ':',
+ ' % Key Description____ Value',
+ ' # Expected integer',
+ ' + c column "abc"',
+ ' # Expected no NUL bytes',
+ ' + f file name "abc\\0def"',
+ ' # Value is negative',
+ ' + l line number -10',
+ ' # Value is negative',
+ ' + n name -64',
+ ' # Expected array value',
+ ' + rc contents "10"',
+ ' # Unexpected enum value: expected one of '
+ .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
+ ' + rt type 10',
+ ' # Expected boolean',
+ ' + ru is_unnamed 10',
+ ' # Expected boolean',
+ ' + sc smartcase value NIL',
+ ' # Expected boolean',
+ ' + sm magic value "TRUE"',
+ ' # Expected integer',
+ ' + so offset value "TRUE"',
+ ' # Expected binary string',
+ ' + sp pattern ="abc"',
+ },
+ ([[ [{'type': 1, 'timestamp': 0, 'data': {
'sm': 'TRUE',
'sc': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
'so': 'TRUE',
@@ -251,29 +266,36 @@ describe('autoload/shada.vim', function()
'l': -10,
'c': 'abc',
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]},
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Header with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Expected no NUL bytes',
- ' + f file name "abc\\0def"',
- ' # Expected array of binary strings',
- ' + rc contents ["abc", ="abc"]',
- ' # Expected integer',
- ' + rt type "ABC"',
- }, ([[ [{'type': 1, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Header with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Expected no NUL bytes',
+ ' + f file name "abc\\0def"',
+ ' # Expected array of binary strings',
+ ' + rc contents ["abc", ="abc"]',
+ ' # Expected integer',
+ ' + rt type "ABC"',
+ },
+ ([[ [{'type': 1, 'timestamp': 0, 'data': {
'rt': 'ABC',
'rc': ["abc", {'_TYPE': v:msgpack_types.string, '_VAL': ["abc"]}],
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]},
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Header with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Expected no NUL bytes',
- ' + rc contents ["abc", "a\\nd\\0"]',
- }, ([[ [{'type': 1, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Header with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Expected no NUL bytes',
+ ' + rc contents ["abc", "a\\nd\\0"]',
+ },
+ ([[ [{'type': 1, 'timestamp': 0, 'data': {
'rc': ["abc", {'_TYPE': v:msgpack_types.binary, '_VAL': ["a", "d\n"]}],
- }}] ]]):gsub('\n', ''))
+ }}] ]]):gsub('\n', '')
+ )
end)
it('works with search pattern items', function()
@@ -281,59 +303,67 @@ describe('autoload/shada.vim', function()
'Search pattern with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
- }, {{type=2, timestamp=0, data={1, 2, 3}}})
- sd2strings_eq({
- 'Search pattern with timestamp ' .. epoch .. ':',
- ' % Key Description________ Value',
- ' + sp pattern "abc"',
- ' + sh v:hlsearch value FALSE',
- ' + ss is :s pattern FALSE',
- ' + sb search backward FALSE',
- ' + sm magic value TRUE',
- ' + sc smartcase value FALSE',
- ' + sl has line offset FALSE',
- ' + se place cursor at end FALSE',
- ' + so offset value 0',
- ' + su is last used TRUE',
- }, ([[ [{'type': 2, 'timestamp': 0, 'data': {
+ }, { { type = 2, timestamp = 0, data = { 1, 2, 3 } } })
+ sd2strings_eq(
+ {
+ 'Search pattern with timestamp ' .. epoch .. ':',
+ ' % Key Description________ Value',
+ ' + sp pattern "abc"',
+ ' + sh v:hlsearch value FALSE',
+ ' + ss is :s pattern FALSE',
+ ' + sb search backward FALSE',
+ ' + sm magic value TRUE',
+ ' + sc smartcase value FALSE',
+ ' + sl has line offset FALSE',
+ ' + se place cursor at end FALSE',
+ ' + so offset value 0',
+ ' + su is last used TRUE',
+ },
+ ([[ [{'type': 2, 'timestamp': 0, 'data': {
'sp': 'abc',
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Search pattern with timestamp ' .. epoch .. ':',
- ' % Key Description________ Value',
- ' + sp pattern "abc"',
- ' + sh v:hlsearch value FALSE',
- ' + ss is :s pattern FALSE',
- ' + sb search backward FALSE',
- ' + sm magic value TRUE',
- ' + sc smartcase value FALSE',
- ' + sl has line offset FALSE',
- ' + se place cursor at end FALSE',
- ' + so offset value 0',
- ' + su is last used TRUE',
- ' + sX NIL',
- ' + sY NIL',
- ' + sZ NIL',
- }, ([[ [{'type': 2, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Search pattern with timestamp ' .. epoch .. ':',
+ ' % Key Description________ Value',
+ ' + sp pattern "abc"',
+ ' + sh v:hlsearch value FALSE',
+ ' + ss is :s pattern FALSE',
+ ' + sb search backward FALSE',
+ ' + sm magic value TRUE',
+ ' + sc smartcase value FALSE',
+ ' + sl has line offset FALSE',
+ ' + se place cursor at end FALSE',
+ ' + so offset value 0',
+ ' + su is last used TRUE',
+ ' + sX NIL',
+ ' + sY NIL',
+ ' + sZ NIL',
+ },
+ ([[ [{'type': 2, 'timestamp': 0, 'data': {
'sp': 'abc',
'sZ': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
'sY': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
'sX': {'_TYPE': v:msgpack_types.nil, '_VAL': 0},
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Search pattern with timestamp ' .. epoch .. ':',
- ' % Key Description________ Value',
- ' + sp pattern "abc"',
- ' + sh v:hlsearch value FALSE',
- ' + ss is :s pattern FALSE',
- ' + sb search backward FALSE',
- ' + sm magic value TRUE',
- ' + sc smartcase value FALSE',
- ' + sl has line offset FALSE',
- ' + se place cursor at end FALSE',
- ' + so offset value 0',
- ' + su is last used TRUE',
- }, ([[ [{'type': 2, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Search pattern with timestamp ' .. epoch .. ':',
+ ' % Key Description________ Value',
+ ' + sp pattern "abc"',
+ ' + sh v:hlsearch value FALSE',
+ ' + ss is :s pattern FALSE',
+ ' + sb search backward FALSE',
+ ' + sm magic value TRUE',
+ ' + sc smartcase value FALSE',
+ ' + sl has line offset FALSE',
+ ' + se place cursor at end FALSE',
+ ' + so offset value 0',
+ ' + su is last used TRUE',
+ },
+ ([[ [{'type': 2, 'timestamp': 0, 'data': {
'sp': 'abc',
'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
@@ -344,36 +374,42 @@ describe('autoload/shada.vim', function()
'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
'so': 0,
'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Search pattern with timestamp ' .. epoch .. ':',
- ' % Key Description________ Value',
- ' # Required key missing: sp',
- ' + sh v:hlsearch value FALSE',
- ' + ss is :s pattern FALSE',
- ' + sb search backward FALSE',
- ' + sm magic value TRUE',
- ' + sc smartcase value FALSE',
- ' + sl has line offset FALSE',
- ' + se place cursor at end FALSE',
- ' + so offset value 0',
- ' + su is last used TRUE',
- }, ([[ [{'type': 2, 'timestamp': 0, 'data': {
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Search pattern with timestamp ' .. epoch .. ':',
- ' % Key Description________ Value',
- ' + sp pattern ""',
- ' + sh v:hlsearch value TRUE',
- ' + ss is :s pattern TRUE',
- ' + sb search backward TRUE',
- ' + sm magic value FALSE',
- ' + sc smartcase value TRUE',
- ' + sl has line offset TRUE',
- ' + se place cursor at end TRUE',
- ' + so offset value -10',
- ' + su is last used FALSE',
- }, ([[ [{'type': 2, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Search pattern with timestamp ' .. epoch .. ':',
+ ' % Key Description________ Value',
+ ' # Required key missing: sp',
+ ' + sh v:hlsearch value FALSE',
+ ' + ss is :s pattern FALSE',
+ ' + sb search backward FALSE',
+ ' + sm magic value TRUE',
+ ' + sc smartcase value FALSE',
+ ' + sl has line offset FALSE',
+ ' + se place cursor at end FALSE',
+ ' + so offset value 0',
+ ' + su is last used TRUE',
+ },
+ ([[ [{'type': 2, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Search pattern with timestamp ' .. epoch .. ':',
+ ' % Key Description________ Value',
+ ' + sp pattern ""',
+ ' + sh v:hlsearch value TRUE',
+ ' + ss is :s pattern TRUE',
+ ' + sb search backward TRUE',
+ ' + sm magic value FALSE',
+ ' + sc smartcase value TRUE',
+ ' + sl has line offset TRUE',
+ ' + se place cursor at end TRUE',
+ ' + so offset value -10',
+ ' + su is last used FALSE',
+ },
+ ([[ [{'type': 2, 'timestamp': 0, 'data': {
'sp': '',
'sh': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'ss': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
@@ -384,31 +420,34 @@ describe('autoload/shada.vim', function()
'se': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
'so': -10,
'su': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Search pattern with timestamp ' .. epoch .. ':',
- ' % Key Description________ Value',
- ' # Expected binary string',
- ' + sp pattern 0',
- ' # Expected boolean',
- ' + sh v:hlsearch value 0',
- ' # Expected boolean',
- ' + ss is :s pattern 0',
- ' # Expected boolean',
- ' + sb search backward 0',
- ' # Expected boolean',
- ' + sm magic value 0',
- ' # Expected boolean',
- ' + sc smartcase value 0',
- ' # Expected boolean',
- ' + sl has line offset 0',
- ' # Expected boolean',
- ' + se place cursor at end 0',
- ' # Expected integer',
- ' + so offset value ""',
- ' # Expected boolean',
- ' + su is last used 0',
- }, ([[ [{'type': 2, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Search pattern with timestamp ' .. epoch .. ':',
+ ' % Key Description________ Value',
+ ' # Expected binary string',
+ ' + sp pattern 0',
+ ' # Expected boolean',
+ ' + sh v:hlsearch value 0',
+ ' # Expected boolean',
+ ' + ss is :s pattern 0',
+ ' # Expected boolean',
+ ' + sb search backward 0',
+ ' # Expected boolean',
+ ' + sm magic value 0',
+ ' # Expected boolean',
+ ' + sc smartcase value 0',
+ ' # Expected boolean',
+ ' + sl has line offset 0',
+ ' # Expected boolean',
+ ' + se place cursor at end 0',
+ ' # Expected integer',
+ ' + so offset value ""',
+ ' # Expected boolean',
+ ' + su is last used 0',
+ },
+ ([[ [{'type': 2, 'timestamp': 0, 'data': {
'sp': 0,
'sh': 0,
'ss': 0,
@@ -419,7 +458,8 @@ describe('autoload/shada.vim', function()
'se': 0,
'so': '',
'su': 0,
- }}] ]]):gsub('\n', ''))
+ }}] ]]):gsub('\n', '')
+ )
end)
it('works with replacement string items', function()
@@ -427,45 +467,60 @@ describe('autoload/shada.vim', function()
'Replacement string with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
- }, {{type=3, timestamp=0, data={a={10}}}})
- sd2strings_eq({
- 'Replacement string with timestamp ' .. epoch .. ':',
- ' @ Description__________ Value',
- ' # Expected more elements in list'
- }, ([[ [{'type': 3, 'timestamp': 0, 'data': [
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Replacement string with timestamp ' .. epoch .. ':',
- ' @ Description__________ Value',
- ' # Expected binary string',
- ' - :s replacement string 0',
- }, ([[ [{'type': 3, 'timestamp': 0, 'data': [
+ }, { { type = 3, timestamp = 0, data = { a = { 10 } } } })
+ sd2strings_eq(
+ {
+ 'Replacement string with timestamp ' .. epoch .. ':',
+ ' @ Description__________ Value',
+ ' # Expected more elements in list',
+ },
+ ([[ [{'type': 3, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Replacement string with timestamp ' .. epoch .. ':',
+ ' @ Description__________ Value',
+ ' # Expected binary string',
+ ' - :s replacement string 0',
+ },
+ ([[ [{'type': 3, 'timestamp': 0, 'data': [
0,
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Replacement string with timestamp ' .. epoch .. ':',
- ' @ Description__________ Value',
- ' # Expected no NUL bytes',
- ' - :s replacement string "abc\\0def"',
- }, ([[ [{'type': 3, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Replacement string with timestamp ' .. epoch .. ':',
+ ' @ Description__________ Value',
+ ' # Expected no NUL bytes',
+ ' - :s replacement string "abc\\0def"',
+ },
+ ([[ [{'type': 3, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]},
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Replacement string with timestamp ' .. epoch .. ':',
- ' @ Description__________ Value',
- ' - :s replacement string "abc\\ndef"',
- }, ([[ [{'type': 3, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Replacement string with timestamp ' .. epoch .. ':',
+ ' @ Description__________ Value',
+ ' - :s replacement string "abc\\ndef"',
+ },
+ ([[ [{'type': 3, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc", "def"]},
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Replacement string with timestamp ' .. epoch .. ':',
- ' @ Description__________ Value',
- ' - :s replacement string "abc\\ndef"',
- ' - 0',
- }, ([[ [{'type': 3, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Replacement string with timestamp ' .. epoch .. ':',
+ ' @ Description__________ Value',
+ ' - :s replacement string "abc\\ndef"',
+ ' - 0',
+ },
+ ([[ [{'type': 3, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc", "def"]},
0,
- ]}] ]]):gsub('\n', ''))
+ ]}] ]]):gsub('\n', '')
+ )
end)
it('works with history entry items', function()
@@ -473,161 +528,206 @@ describe('autoload/shada.vim', function()
'History entry with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
- }, {{type=4, timestamp=0, data={a={10}}}})
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' # Expected more elements in list'
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' # Expected integer',
- ' - history type ""',
- ' # Expected more elements in list'
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ }, { { type = 4, timestamp = 0, data = { a = { 10 } } } })
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' # Expected more elements in list',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' # Expected integer',
+ ' - history type ""',
+ ' # Expected more elements in list',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
'',
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
.. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
- ' - history type 5',
- ' - contents ""',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ' - history type 5',
+ ' - contents ""',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
5,
''
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
.. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
- ' - history type 5',
- ' - contents ""',
- ' - 32',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ' - history type 5',
+ ' - contents ""',
+ ' - 32',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
5,
'',
0x20
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type CMD',
- ' - contents ""',
- ' - 32',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type CMD',
+ ' - contents ""',
+ ' - 32',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
0,
'',
0x20
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type SEARCH',
- ' - contents ""',
- ' - separator \' \'',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type SEARCH',
+ ' - contents ""',
+ " - separator ' '",
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
1,
'',
0x20
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type SEARCH',
- ' - contents ""',
- ' # Expected more elements in list',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type SEARCH',
+ ' - contents ""',
+ ' # Expected more elements in list',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
1,
'',
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type EXPR',
- ' - contents ""',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type EXPR',
+ ' - contents ""',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
2,
'',
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type INPUT',
- ' - contents ""',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type INPUT',
+ ' - contents ""',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
3,
'',
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type DEBUG',
- ' - contents ""',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type DEBUG',
+ ' - contents ""',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
4,
'',
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type DEBUG',
- ' # Expected binary string',
- ' - contents 10',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type DEBUG',
+ ' # Expected binary string',
+ ' - contents 10',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
4,
10,
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type DEBUG',
- ' # Expected no NUL bytes',
- ' - contents "abc\\0def"',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type DEBUG',
+ ' # Expected no NUL bytes',
+ ' - contents "abc\\0def"',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
4,
{'_TYPE': v:msgpack_types.binary, '_VAL': ["abc\ndef"]},
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type SEARCH',
- ' - contents "abc"',
- ' # Expected integer',
- ' - separator ""',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type SEARCH',
+ ' - contents "abc"',
+ ' # Expected integer',
+ ' - separator ""',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
1,
'abc',
'',
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type SEARCH',
- ' - contents "abc"',
- ' # Value is negative',
- ' - separator -1',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type SEARCH',
+ ' - contents "abc"',
+ ' # Value is negative',
+ ' - separator -1',
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
1,
'abc',
-1,
- ]}] ]]):gsub('\n', ''))
+ ]}] ]]):gsub('\n', '')
+ )
-- Regression: NUL separator must be properly supported
- sd2strings_eq({
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type SEARCH',
- ' - contents ""',
- ' - separator \'\\0\'',
- }, ([[ [{'type': 4, 'timestamp': 0, 'data': [
+ sd2strings_eq(
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type SEARCH',
+ ' - contents ""',
+ " - separator '\\0'",
+ },
+ ([[ [{'type': 4, 'timestamp': 0, 'data': [
1,
'',
0x0
- ]}] ]]):gsub('\n', ''))
+ ]}] ]]):gsub('\n', '')
+ )
end)
it('works with register items', function()
@@ -635,145 +735,172 @@ describe('autoload/shada.vim', function()
'Register with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
- }, {{type=5, timestamp=0, data={1, 2, 3}}})
- sd2strings_eq({
- 'Register with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Required key missing: n',
- ' # Required key missing: rc',
- ' + rw block width 0',
- ' + rt type CHARACTERWISE',
- ' + ru is_unnamed FALSE',
- }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Register with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + n name \' \'',
- ' # Required key missing: rc',
- ' + rw block width 0',
- ' + rt type CHARACTERWISE',
- ' + ru is_unnamed FALSE',
- }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ }, { { type = 5, timestamp = 0, data = { 1, 2, 3 } } })
+ sd2strings_eq(
+ {
+ 'Register with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Required key missing: n',
+ ' # Required key missing: rc',
+ ' + rw block width 0',
+ ' + rt type CHARACTERWISE',
+ ' + ru is_unnamed FALSE',
+ },
+ ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Register with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ " + n name ' '",
+ ' # Required key missing: rc',
+ ' + rw block width 0',
+ ' + rt type CHARACTERWISE',
+ ' + ru is_unnamed FALSE',
+ },
+ ([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Register with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + n name \' \'',
- ' + rc contents ["abc", "def"]',
- ' + rw block width 0',
- ' + rt type CHARACTERWISE',
- ' + ru is_unnamed FALSE',
- }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Register with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ " + n name ' '",
+ ' + rc contents ["abc", "def"]',
+ ' + rw block width 0',
+ ' + rt type CHARACTERWISE',
+ ' + ru is_unnamed FALSE',
+ },
+ ([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ["abc", "def"],
'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 0},
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Register with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + n name \' \'',
- ' + rc contents @',
- ' | - "abcdefghijklmnopqrstuvwxyz"',
- ' | - "abcdefghijklmnopqrstuvwxyz"',
- ' + rw block width 0',
- ' + rt type CHARACTERWISE',
- ' + ru is_unnamed TRUE',
- }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Register with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ " + n name ' '",
+ ' + rc contents @',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' + rw block width 0',
+ ' + rt type CHARACTERWISE',
+ ' + ru is_unnamed TRUE',
+ },
+ ([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
'ru': {'_TYPE': v:msgpack_types.boolean, '_VAL': 1},
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Register with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + n name \' \'',
- ' + rc contents @',
- ' | - "abcdefghijklmnopqrstuvwxyz"',
- ' | - "abcdefghijklmnopqrstuvwxyz"',
- ' + rw block width 0',
- ' + rt type CHARACTERWISE',
- ' + ru is_unnamed FALSE',
- }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Register with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ " + n name ' '",
+ ' + rc contents @',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' + rw block width 0',
+ ' + rt type CHARACTERWISE',
+ ' + ru is_unnamed FALSE',
+ },
+ ([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
'rw': 0,
'rt': 0,
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Register with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + n name \' \'',
- ' + rc contents @',
- ' | - "abcdefghijklmnopqrstuvwxyz"',
- ' | - "abcdefghijklmnopqrstuvwxyz"',
- ' + rw block width 5',
- ' + rt type LINEWISE',
- ' + ru is_unnamed FALSE',
- }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Register with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ " + n name ' '",
+ ' + rc contents @',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' + rw block width 5',
+ ' + rt type LINEWISE',
+ ' + ru is_unnamed FALSE',
+ },
+ ([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
'rw': 5,
'rt': 1,
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Register with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + n name \' \'',
- ' + rc contents @',
- ' | - "abcdefghijklmnopqrstuvwxyz"',
- ' | - "abcdefghijklmnopqrstuvwxyz"',
- ' # Expected integer',
- ' + rw block width ""',
- ' + rt type BLOCKWISE',
- ' # Expected boolean',
- ' + ru is_unnamed ""',
- }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Register with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ " + n name ' '",
+ ' + rc contents @',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' # Expected integer',
+ ' + rw block width ""',
+ ' + rt type BLOCKWISE',
+ ' # Expected boolean',
+ ' + ru is_unnamed ""',
+ },
+ ([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
'rw': "",
'rt': 2,
'ru': ""
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Register with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + n name \' \'',
- ' # Expected array value',
- ' + rc contents 0',
- ' # Value is negative',
- ' + rw block width -1',
- ' # Unexpected enum value: expected one of 0 (CHARACTERWISE), '
- .. '1 (LINEWISE), 2 (BLOCKWISE)',
- ' + rt type 10',
- ' # Expected boolean',
- ' + ru is_unnamed ["abc", "def"]',
- }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Register with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ " + n name ' '",
+ ' # Expected array value',
+ ' + rc contents 0',
+ ' # Value is negative',
+ ' + rw block width -1',
+ ' # Unexpected enum value: expected one of 0 (CHARACTERWISE), '
+ .. '1 (LINEWISE), 2 (BLOCKWISE)',
+ ' + rt type 10',
+ ' # Expected boolean',
+ ' + ru is_unnamed ["abc", "def"]',
+ },
+ ([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': 0,
'rw': -1,
'rt': 10,
'ru': ['abc', 'def'],
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Register with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + n name \' \'',
- ' + rc contents @',
- ' | - "abcdefghijklmnopqrstuvwxyz"',
- ' | - "abcdefghijklmnopqrstuvwxyz"',
- ' + rw block width 5',
- ' + rt type LINEWISE',
- ' # Expected boolean',
- ' + ru is_unnamed 0',
- }, ([[ [{'type': 5, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Register with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ " + n name ' '",
+ ' + rc contents @',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' | - "abcdefghijklmnopqrstuvwxyz"',
+ ' + rw block width 5',
+ ' + rt type LINEWISE',
+ ' # Expected boolean',
+ ' + ru is_unnamed 0',
+ },
+ ([[ [{'type': 5, 'timestamp': 0, 'data': {
'n': 0x20,
'rc': ['abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'],
'rw': 5,
'rt': 1,
'ru': 0,
- }}] ]]):gsub('\n', ''))
+ }}] ]]):gsub('\n', '')
+ )
end)
it('works with variable items', function()
@@ -781,59 +908,77 @@ describe('autoload/shada.vim', function()
'Variable with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
- }, {{type=6, timestamp=0, data={a={10}}}})
- sd2strings_eq({
- 'Variable with timestamp ' .. epoch .. ':',
- ' @ Description Value',
- ' # Expected more elements in list'
- }, ([[ [{'type': 6, 'timestamp': 0, 'data': [
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Variable with timestamp ' .. epoch .. ':',
- ' @ Description Value',
- ' # Expected binary string',
- ' - name 1',
- ' # Expected more elements in list',
- }, ([[ [{'type': 6, 'timestamp': 0, 'data': [
+ }, { { type = 6, timestamp = 0, data = { a = { 10 } } } })
+ sd2strings_eq(
+ {
+ 'Variable with timestamp ' .. epoch .. ':',
+ ' @ Description Value',
+ ' # Expected more elements in list',
+ },
+ ([[ [{'type': 6, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Variable with timestamp ' .. epoch .. ':',
+ ' @ Description Value',
+ ' # Expected binary string',
+ ' - name 1',
+ ' # Expected more elements in list',
+ },
+ ([[ [{'type': 6, 'timestamp': 0, 'data': [
1
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Variable with timestamp ' .. epoch .. ':',
- ' @ Description Value',
- ' # Expected no NUL bytes',
- ' - name "\\0"',
- ' # Expected more elements in list',
- }, ([[ [{'type': 6, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Variable with timestamp ' .. epoch .. ':',
+ ' @ Description Value',
+ ' # Expected no NUL bytes',
+ ' - name "\\0"',
+ ' # Expected more elements in list',
+ },
+ ([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]},
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Variable with timestamp ' .. epoch .. ':',
- ' @ Description Value',
- ' - name "foo"',
- ' # Expected more elements in list',
- }, ([[ [{'type': 6, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Variable with timestamp ' .. epoch .. ':',
+ ' @ Description Value',
+ ' - name "foo"',
+ ' # Expected more elements in list',
+ },
+ ([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]},
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Variable with timestamp ' .. epoch .. ':',
- ' @ Description Value',
- ' - name "foo"',
- ' - value NIL',
- }, ([[ [{'type': 6, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Variable with timestamp ' .. epoch .. ':',
+ ' @ Description Value',
+ ' - name "foo"',
+ ' - value NIL',
+ },
+ ([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]},
{'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
- ]}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Variable with timestamp ' .. epoch .. ':',
- ' @ Description Value',
- ' - name "foo"',
- ' - value NIL',
- ' - NIL',
- }, ([[ [{'type': 6, 'timestamp': 0, 'data': [
+ ]}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Variable with timestamp ' .. epoch .. ':',
+ ' @ Description Value',
+ ' - name "foo"',
+ ' - value NIL',
+ ' - NIL',
+ },
+ ([[ [{'type': 6, 'timestamp': 0, 'data': [
{'_TYPE': v:msgpack_types.binary, '_VAL': ["foo"]},
{'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
{'_TYPE': v:msgpack_types.nil, '_VAL': ["foo"]},
- ]}] ]]):gsub('\n', ''))
+ ]}] ]]):gsub('\n', '')
+ )
end)
it('works with global mark items', function()
@@ -841,110 +986,134 @@ describe('autoload/shada.vim', function()
'Global mark with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
- }, {{type=7, timestamp=0, data={1, 2, 3}}})
- sd2strings_eq({
- 'Global mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Required key missing: n',
- ' # Required key missing: f',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 7, 'timestamp': 0, 'data': {
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Global mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Expected integer',
- ' + n name "foo"',
- ' # Required key missing: f',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 7, 'timestamp': 0, 'data': {
+ }, { { type = 7, timestamp = 0, data = { 1, 2, 3 } } })
+ sd2strings_eq(
+ {
+ 'Global mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Required key missing: n',
+ ' # Required key missing: f',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 7, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Global mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Expected integer',
+ ' + n name "foo"',
+ ' # Required key missing: f',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': 'foo',
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Global mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Required key missing: n',
- ' + f file name "foo"',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 7, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Global mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Required key missing: n',
+ ' + f file name "foo"',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 7, 'timestamp': 0, 'data': {
'f': 'foo',
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Global mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Value is negative',
- ' + n name -10',
- ' # Expected no NUL bytes',
- ' + f file name "\\0"',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 7, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Global mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Value is negative',
+ ' + n name -10',
+ ' # Expected no NUL bytes',
+ ' + f file name "\\0"',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]},
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Global mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + n name \'\\20\'',
- ' + f file name "foo"',
- ' # Value is negative',
- ' + l line number -10',
- ' # Value is negative',
- ' + c column -10',
- }, ([[ [{'type': 7, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Global mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ " + n name '\\20'",
+ ' + f file name "foo"',
+ ' # Value is negative',
+ ' + l line number -10',
+ ' # Value is negative',
+ ' + c column -10',
+ },
+ ([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': 20,
'f': 'foo',
'l': -10,
'c': -10,
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Global mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + n name 128',
- ' + f file name "foo"',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 7, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Global mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + n name 128',
+ ' + f file name "foo"',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': 128,
'f': 'foo',
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Global mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + n name \'\\20\'',
- ' + f file name "foo"',
- ' # Expected integer',
- ' + l line number "FOO"',
- ' # Expected integer',
- ' + c column "foo"',
- ' + mX 10',
- }, ([[ [{'type': 7, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Global mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ " + n name '\\20'",
+ ' + f file name "foo"',
+ ' # Expected integer',
+ ' + l line number "FOO"',
+ ' # Expected integer',
+ ' + c column "foo"',
+ ' + mX 10',
+ },
+ ([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': 20,
'f': 'foo',
'l': 'FOO',
'c': 'foo',
'mX': 10,
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Global mark with timestamp ' .. epoch .. ':',
- ' % Key________ Description Value',
- ' + n name \'A\'',
- ' + f file name "foo"',
- ' + l line number 2',
- ' + c column 200',
- ' + mX 10',
- ' + mYYYYYYYYYY 10',
- }, ([[ [{'type': 7, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Global mark with timestamp ' .. epoch .. ':',
+ ' % Key________ Description Value',
+ " + n name 'A'",
+ ' + f file name "foo"',
+ ' + l line number 2',
+ ' + c column 200',
+ ' + mX 10',
+ ' + mYYYYYYYYYY 10',
+ },
+ ([[ [{'type': 7, 'timestamp': 0, 'data': {
'n': char2nr('A'),
'f': 'foo',
'l': 2,
'c': 200,
'mX': 10,
'mYYYYYYYYYY': 10,
- }}] ]]):gsub('\n', ''))
+ }}] ]]):gsub('\n', '')
+ )
end)
it('works with jump items', function()
@@ -952,93 +1121,114 @@ describe('autoload/shada.vim', function()
'Jump with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
- }, {{type=8, timestamp=0, data={1, 2, 3}}})
- sd2strings_eq({
- 'Jump with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Required key missing: f',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 8, 'timestamp': 0, 'data': {
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Jump with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Required key missing: f',
- ' + l line number 1',
- ' + c column 0',
- ' # Expected integer',
- ' + n name "foo"',
- }, ([[ [{'type': 8, 'timestamp': 0, 'data': {
+ }, { { type = 8, timestamp = 0, data = { 1, 2, 3 } } })
+ sd2strings_eq(
+ {
+ 'Jump with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Required key missing: f',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 8, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Jump with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Required key missing: f',
+ ' + l line number 1',
+ ' + c column 0',
+ ' # Expected integer',
+ ' + n name "foo"',
+ },
+ ([[ [{'type': 8, 'timestamp': 0, 'data': {
'n': 'foo',
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Jump with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + f file name "foo"',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 8, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Jump with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + f file name "foo"',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 8, 'timestamp': 0, 'data': {
'f': 'foo',
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Jump with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Expected no NUL bytes',
- ' + f file name "\\0"',
- ' + l line number 1',
- ' + c column 0',
- ' # Value is negative',
- ' + n name -10',
- }, ([[ [{'type': 8, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Jump with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Expected no NUL bytes',
+ ' + f file name "\\0"',
+ ' + l line number 1',
+ ' + c column 0',
+ ' # Value is negative',
+ ' + n name -10',
+ },
+ ([[ [{'type': 8, 'timestamp': 0, 'data': {
'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]},
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Jump with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + f file name "foo"',
- ' # Value is negative',
- ' + l line number -10',
- ' # Value is negative',
- ' + c column -10',
- }, ([[ [{'type': 8, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Jump with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + f file name "foo"',
+ ' # Value is negative',
+ ' + l line number -10',
+ ' # Value is negative',
+ ' + c column -10',
+ },
+ ([[ [{'type': 8, 'timestamp': 0, 'data': {
'f': 'foo',
'l': -10,
'c': -10,
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Jump with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + f file name "foo"',
- ' # Expected integer',
- ' + l line number "FOO"',
- ' # Expected integer',
- ' + c column "foo"',
- ' + mX 10',
- }, ([[ [{'type': 8, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Jump with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + f file name "foo"',
+ ' # Expected integer',
+ ' + l line number "FOO"',
+ ' # Expected integer',
+ ' + c column "foo"',
+ ' + mX 10',
+ },
+ ([[ [{'type': 8, 'timestamp': 0, 'data': {
'f': 'foo',
'l': 'FOO',
'c': 'foo',
'mX': 10,
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Jump with timestamp ' .. epoch .. ':',
- ' % Key________ Description Value',
- ' + f file name "foo"',
- ' + l line number 2',
- ' + c column 200',
- ' + mX 10',
- ' + mYYYYYYYYYY 10',
- ' + n name \' \'',
- }, ([[ [{'type': 8, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Jump with timestamp ' .. epoch .. ':',
+ ' % Key________ Description Value',
+ ' + f file name "foo"',
+ ' + l line number 2',
+ ' + c column 200',
+ ' + mX 10',
+ ' + mYYYYYYYYYY 10',
+ " + n name ' '",
+ },
+ ([[ [{'type': 8, 'timestamp': 0, 'data': {
'n': 0x20,
'f': 'foo',
'l': 2,
'c': 200,
'mX': 10,
'mYYYYYYYYYY': 10,
- }}] ]]):gsub('\n', ''))
+ }}] ]]):gsub('\n', '')
+ )
end)
it('works with buffer list items', function()
@@ -1046,17 +1236,17 @@ describe('autoload/shada.vim', function()
'Buffer list with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
- }, {{type=9, timestamp=0, data={a={10}}}})
+ }, { { type = 9, timestamp = 0, data = { a = { 10 } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps',
' = [[], []]',
- }, {{type=9, timestamp=0, data={{}, {}}}})
+ }, { { type = 9, timestamp = 0, data = { {}, {} } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' # Expected array of maps',
' = [{="a": 10}, []]',
- }, {{type=9, timestamp=0, data={{a=10}, {}}}})
+ }, { { type = 9, timestamp = 0, data = { { a = 10 }, {} } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
@@ -1064,7 +1254,7 @@ describe('autoload/shada.vim', function()
' + l line number 1',
' + c column 0',
' + a 10',
- }, {{type=9, timestamp=0, data={{a=10}}}})
+ }, { { type = 9, timestamp = 0, data = { { a = 10 } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
@@ -1074,7 +1264,7 @@ describe('autoload/shada.vim', function()
' # Expected integer',
' + c column "10"',
' + a 10',
- }, {{type=9, timestamp=0, data={{l='10', c='10', a=10}}}})
+ }, { { type = 9, timestamp = 0, data = { { l = '10', c = '10', a = 10 } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
@@ -1082,7 +1272,7 @@ describe('autoload/shada.vim', function()
' + l line number 10',
' + c column 10',
' + a 10',
- }, {{type=9, timestamp=0, data={{l=10, c=10, a=10}}}})
+ }, { { type = 9, timestamp = 0, data = { { l = 10, c = 10, a = 10 } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
@@ -1091,14 +1281,14 @@ describe('autoload/shada.vim', function()
' + l line number -10',
' # Value is negative',
' + c column -10',
- }, {{type=9, timestamp=0, data={{l=-10, c=-10}}}})
+ }, { { type = 9, timestamp = 0, data = { { l = -10, c = -10 } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "abc"',
' + l line number 1',
' + c column 0',
- }, {{type=9, timestamp=0, data={{f='abc'}}}})
+ }, { { type = 9, timestamp = 0, data = { { f = 'abc' } } } })
sd2strings_eq({
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
@@ -1112,24 +1302,27 @@ describe('autoload/shada.vim', function()
' + f file name 20',
' + l line number 1',
' + c column 0',
- }, {{type=9, timestamp=0, data={{f=10}, {f=20}}}})
- sd2strings_eq({
- 'Buffer list with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Expected binary string',
- ' + f file name 10',
- ' + l line number 1',
- ' + c column 0',
- '',
- ' % Key Description Value',
- ' # Expected no NUL bytes',
- ' + f file name "\\0"',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 9, 'timestamp': 0, 'data': [
+ }, { { type = 9, timestamp = 0, data = { { f = 10 }, { f = 20 } } } })
+ sd2strings_eq(
+ {
+ 'Buffer list with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Expected binary string',
+ ' + f file name 10',
+ ' + l line number 1',
+ ' + c column 0',
+ '',
+ ' % Key Description Value',
+ ' # Expected no NUL bytes',
+ ' + f file name "\\0"',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 9, 'timestamp': 0, 'data': [
{'f': 10},
{'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]}},
- ]}] ]]):gsub('\n', ''))
+ ]}] ]]):gsub('\n', '')
+ )
end)
it('works with local mark items', function()
@@ -1137,99 +1330,120 @@ describe('autoload/shada.vim', function()
'Local mark with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
- }, {{type=10, timestamp=0, data={1, 2, 3}}})
- sd2strings_eq({
- 'Local mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Required key missing: f',
- ' + n name \'"\'',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 10, 'timestamp': 0, 'data': {
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Local mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Required key missing: f',
- ' # Expected integer',
- ' + n name "foo"',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 10, 'timestamp': 0, 'data': {
+ }, { { type = 10, timestamp = 0, data = { 1, 2, 3 } } })
+ sd2strings_eq(
+ {
+ 'Local mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Required key missing: f',
+ " + n name '\"'",
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 10, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Local mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Required key missing: f',
+ ' # Expected integer',
+ ' + n name "foo"',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 10, 'timestamp': 0, 'data': {
'n': 'foo',
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Local mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + f file name "foo"',
- ' + n name \'"\'',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 10, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Local mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + f file name "foo"',
+ " + n name '\"'",
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 10, 'timestamp': 0, 'data': {
'f': 'foo',
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Local mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Expected no NUL bytes',
- ' + f file name "\\0"',
- ' # Value is negative',
- ' + n name -10',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 10, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Local mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Expected no NUL bytes',
+ ' + f file name "\\0"',
+ ' # Value is negative',
+ ' + n name -10',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 10, 'timestamp': 0, 'data': {
'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]},
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Local mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + f file name "foo"',
- ' + n name \'\\20\'',
- ' # Value is negative',
- ' + l line number -10',
- ' # Value is negative',
- ' + c column -10',
- }, ([[ [{'type': 10, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Local mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + f file name "foo"',
+ " + n name '\\20'",
+ ' # Value is negative',
+ ' + l line number -10',
+ ' # Value is negative',
+ ' + c column -10',
+ },
+ ([[ [{'type': 10, 'timestamp': 0, 'data': {
'n': 20,
'f': 'foo',
'l': -10,
'c': -10,
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Local mark with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + f file name "foo"',
- ' + n name \'\\20\'',
- ' # Expected integer',
- ' + l line number "FOO"',
- ' # Expected integer',
- ' + c column "foo"',
- ' + mX 10',
- }, ([[ [{'type': 10, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Local mark with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + f file name "foo"',
+ " + n name '\\20'",
+ ' # Expected integer',
+ ' + l line number "FOO"',
+ ' # Expected integer',
+ ' + c column "foo"',
+ ' + mX 10',
+ },
+ ([[ [{'type': 10, 'timestamp': 0, 'data': {
'n': 20,
'f': 'foo',
'l': 'FOO',
'c': 'foo',
'mX': 10,
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Local mark with timestamp ' .. epoch .. ':',
- ' % Key________ Description Value',
- ' + f file name "foo"',
- ' + n name \'a\'',
- ' + l line number 2',
- ' + c column 200',
- ' + mX 10',
- ' + mYYYYYYYYYY 10',
- }, ([[ [{'type': 10, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Local mark with timestamp ' .. epoch .. ':',
+ ' % Key________ Description Value',
+ ' + f file name "foo"',
+ " + n name 'a'",
+ ' + l line number 2',
+ ' + c column 200',
+ ' + mX 10',
+ ' + mYYYYYYYYYY 10',
+ },
+ ([[ [{'type': 10, 'timestamp': 0, 'data': {
'n': char2nr('a'),
'f': 'foo',
'l': 2,
'c': 200,
'mX': 10,
'mYYYYYYYYYY': 10,
- }}] ]]):gsub('\n', ''))
+ }}] ]]):gsub('\n', '')
+ )
end)
it('works with change items', function()
@@ -1237,93 +1451,114 @@ describe('autoload/shada.vim', function()
'Change with timestamp ' .. epoch .. ':',
' # Unexpected type: array instead of map',
' = [1, 2, 3]',
- }, {{type=11, timestamp=0, data={1, 2, 3}}})
- sd2strings_eq({
- 'Change with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Required key missing: f',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 11, 'timestamp': 0, 'data': {
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Change with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Required key missing: f',
- ' + l line number 1',
- ' + c column 0',
- ' # Expected integer',
- ' + n name "foo"',
- }, ([[ [{'type': 11, 'timestamp': 0, 'data': {
+ }, { { type = 11, timestamp = 0, data = { 1, 2, 3 } } })
+ sd2strings_eq(
+ {
+ 'Change with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Required key missing: f',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 11, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Change with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Required key missing: f',
+ ' + l line number 1',
+ ' + c column 0',
+ ' # Expected integer',
+ ' + n name "foo"',
+ },
+ ([[ [{'type': 11, 'timestamp': 0, 'data': {
'n': 'foo',
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Change with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + f file name "foo"',
- ' + l line number 1',
- ' + c column 0',
- }, ([[ [{'type': 11, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Change with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + f file name "foo"',
+ ' + l line number 1',
+ ' + c column 0',
+ },
+ ([[ [{'type': 11, 'timestamp': 0, 'data': {
'f': 'foo',
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Change with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Expected no NUL bytes',
- ' + f file name "\\0"',
- ' + l line number 1',
- ' + c column 0',
- ' # Value is negative',
- ' + n name -10',
- }, ([[ [{'type': 11, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Change with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Expected no NUL bytes',
+ ' + f file name "\\0"',
+ ' + l line number 1',
+ ' + c column 0',
+ ' # Value is negative',
+ ' + n name -10',
+ },
+ ([[ [{'type': 11, 'timestamp': 0, 'data': {
'n': -10,
'f': {'_TYPE': v:msgpack_types.binary, '_VAL': ["\n"]},
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Change with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + f file name "foo"',
- ' # Value is negative',
- ' + l line number -10',
- ' # Value is negative',
- ' + c column -10',
- }, ([[ [{'type': 11, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Change with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + f file name "foo"',
+ ' # Value is negative',
+ ' + l line number -10',
+ ' # Value is negative',
+ ' + c column -10',
+ },
+ ([[ [{'type': 11, 'timestamp': 0, 'data': {
'f': 'foo',
'l': -10,
'c': -10,
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Change with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' + f file name "foo"',
- ' # Expected integer',
- ' + l line number "FOO"',
- ' # Expected integer',
- ' + c column "foo"',
- ' + mX 10',
- }, ([[ [{'type': 11, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Change with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' + f file name "foo"',
+ ' # Expected integer',
+ ' + l line number "FOO"',
+ ' # Expected integer',
+ ' + c column "foo"',
+ ' + mX 10',
+ },
+ ([[ [{'type': 11, 'timestamp': 0, 'data': {
'f': 'foo',
'l': 'FOO',
'c': 'foo',
'mX': 10,
- }}] ]]):gsub('\n', ''))
- sd2strings_eq({
- 'Change with timestamp ' .. epoch .. ':',
- ' % Key________ Description Value',
- ' + f file name "foo"',
- ' + l line number 2',
- ' + c column 200',
- ' + mX 10',
- ' + mYYYYYYYYYY 10',
- ' + n name \' \'',
- }, ([[ [{'type': 11, 'timestamp': 0, 'data': {
+ }}] ]]):gsub('\n', '')
+ )
+ sd2strings_eq(
+ {
+ 'Change with timestamp ' .. epoch .. ':',
+ ' % Key________ Description Value',
+ ' + f file name "foo"',
+ ' + l line number 2',
+ ' + c column 200',
+ ' + mX 10',
+ ' + mYYYYYYYYYY 10',
+ " + n name ' '",
+ },
+ ([[ [{'type': 11, 'timestamp': 0, 'data': {
'n': 0x20,
'f': 'foo',
'l': 2,
'c': 200,
'mX': 10,
'mYYYYYYYYYY': 10,
- }}] ]]):gsub('\n', ''))
+ }}] ]]):gsub('\n', '')
+ )
end)
end)
@@ -1337,15 +1572,16 @@ describe('autoload/shada.vim', function()
end)
describe('function shada#strings_to_sd', function()
-
local strings2sd_eq = function(expected, input)
- nvim('set_var', '__input', input)
- nvim_command('let g:__actual = map(shada#strings_to_sd(g:__input), '
- .. '"filter(v:val, \\"v:key[0] isnot# \'_\' '
- .. '&& v:key isnot# \'length\'\\")")')
+ api.nvim_set_var('__input', input)
+ nvim_command(
+ 'let g:__actual = map(shada#strings_to_sd(g:__input), '
+ .. '"filter(v:val, \\"v:key[0] isnot# \'_\' '
+ .. '&& v:key isnot# \'length\'\\")")'
+ )
-- print()
if type(expected) == 'table' then
- nvim('set_var', '__expected', expected)
+ api.nvim_set_var('__expected', expected)
nvim_command('let g:__expected = ModifyVal(g:__expected)')
expected = 'g:__expected'
-- print(nvim_eval('msgpack#string(g:__expected)'))
@@ -1360,29 +1596,36 @@ describe('autoload/shada.vim', function()
end
it('works with multiple items', function()
- strings2sd_eq({{
- type=11, timestamp=0, data={
- f='foo',
- l=2,
- c=200,
- mX=10,
- mYYYYYYYYYY=10,
- n=(' '):byte(),
- }
+ strings2sd_eq({
+ {
+ type = 11,
+ timestamp = 0,
+ data = {
+ f = 'foo',
+ l = 2,
+ c = 200,
+ mX = 10,
+ mYYYYYYYYYY = 10,
+ n = (' '):byte(),
+ },
+ },
+ {
+ type = 1,
+ timestamp = 0,
+ data = {
+ c = 'abc',
+ f = { '!binary', { 'abc\ndef' } },
+ l = -10,
+ n = -64,
+ rc = '10',
+ rt = 10,
+ sc = { '!nil', 0 },
+ sm = 'TRUE',
+ so = 'TRUE',
+ sp = { '!string', { 'abc' } },
+ },
+ },
}, {
- type=1, timestamp=0, data={
- c='abc',
- f={'!binary', {'abc\ndef'}},
- l=-10,
- n=-64,
- rc='10',
- rt=10,
- sc={'!nil', 0},
- sm='TRUE',
- so='TRUE',
- sp={'!string', {'abc'}},
- }
- }}, {
'Change with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
' + f file name "foo"',
@@ -1390,7 +1633,7 @@ describe('autoload/shada.vim', function()
' + c column 200',
' + mX 10',
' + mYYYYYYYYYY 10',
- ' + n name \' \'',
+ " + n name ' '",
'Header with timestamp ' .. epoch .. ':',
' % Key Description____ Value',
' # Expected integer',
@@ -1404,7 +1647,7 @@ describe('autoload/shada.vim', function()
' # Expected array value',
' + rc contents "10"',
' # Unexpected enum value: expected one of '
- .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
+ .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
' + rt type 10',
' # Expected boolean',
' + sc smartcase value NIL',
@@ -1422,23 +1665,37 @@ describe('autoload/shada.vim', function()
end)
it('works with header items', function()
- strings2sd_eq({{type=1, timestamp=0, data={
- generator='test',
- }}}, {
+ strings2sd_eq({ { type = 1, timestamp = 0, data = {
+ generator = 'test',
+ } } }, {
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
})
- strings2sd_eq({{type=1, timestamp=0, data={
- 1, 2, 3,
- }}}, {
- 'Header with timestamp ' .. epoch .. ':',
- ' # Unexpected type: array instead of map',
- ' = [1, 2, 3]',
- })
- strings2sd_eq({{type=1, timestamp=0, data={
- a=1, b=2, c=3, d=4,
- }}}, {
+ strings2sd_eq(
+ { { type = 1, timestamp = 0, data = {
+ 1,
+ 2,
+ 3,
+ } } },
+ {
+ 'Header with timestamp ' .. epoch .. ':',
+ ' # Unexpected type: array instead of map',
+ ' = [1, 2, 3]',
+ }
+ )
+ strings2sd_eq({
+ {
+ type = 1,
+ timestamp = 0,
+ data = {
+ a = 1,
+ b = 2,
+ c = 3,
+ d = 4,
+ },
+ },
+ }, {
'Header with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + a 1',
@@ -1446,18 +1703,24 @@ describe('autoload/shada.vim', function()
' + c column 3',
' + d 4',
})
- strings2sd_eq({{type=1, timestamp=0, data={
- c='abc',
- f={'!binary', {'abc\ndef'}},
- l=-10,
- n=-64,
- rc='10',
- rt=10,
- sc={'!nil', 0},
- sm='TRUE',
- so='TRUE',
- sp={'!string', {'abc'}},
- }}}, {
+ strings2sd_eq({
+ {
+ type = 1,
+ timestamp = 0,
+ data = {
+ c = 'abc',
+ f = { '!binary', { 'abc\ndef' } },
+ l = -10,
+ n = -64,
+ rc = '10',
+ rt = 10,
+ sc = { '!nil', 0 },
+ sm = 'TRUE',
+ so = 'TRUE',
+ sp = { '!string', { 'abc' } },
+ },
+ },
+ }, {
'Header with timestamp ' .. epoch .. ':',
' % Key Description____ Value',
' # Expected integer',
@@ -1471,7 +1734,7 @@ describe('autoload/shada.vim', function()
' # Expected array value',
' + rc contents "10"',
' # Unexpected enum value: expected one of '
- .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
+ .. '0 (CHARACTERWISE), 1 (LINEWISE), 2 (BLOCKWISE)',
' + rt type 10',
' # Expected boolean',
' + sc smartcase value NIL',
@@ -1485,16 +1748,21 @@ describe('autoload/shada.vim', function()
end)
it('works with search pattern items', function()
- strings2sd_eq({{type=2, timestamp=0, data={
- 1, 2, 3
- }}}, {
- 'Search pattern with timestamp ' .. epoch .. ':',
- ' # Unexpected type: array instead of map',
- ' = [1, 2, 3]',
- })
- strings2sd_eq({{type=2, timestamp=0, data={
- sp='abc',
- }}}, {
+ strings2sd_eq(
+ { { type = 2, timestamp = 0, data = {
+ 1,
+ 2,
+ 3,
+ } } },
+ {
+ 'Search pattern with timestamp ' .. epoch .. ':',
+ ' # Unexpected type: array instead of map',
+ ' = [1, 2, 3]',
+ }
+ )
+ strings2sd_eq({ { type = 2, timestamp = 0, data = {
+ sp = 'abc',
+ } } }, {
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + sp pattern "abc"',
@@ -1507,12 +1775,18 @@ describe('autoload/shada.vim', function()
' + so offset value 0',
' + su is last used TRUE',
})
- strings2sd_eq({{type=2, timestamp=0, data={
- sp='abc',
- sX={'!nil', 0},
- sY={'!nil', 0},
- sZ={'!nil', 0},
- }}}, {
+ strings2sd_eq({
+ {
+ type = 2,
+ timestamp = 0,
+ data = {
+ sp = 'abc',
+ sX = { '!nil', 0 },
+ sY = { '!nil', 0 },
+ sZ = { '!nil', 0 },
+ },
+ },
+ }, {
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + sp pattern "abc"',
@@ -1528,8 +1802,7 @@ describe('autoload/shada.vim', function()
' + sY NIL',
' + sZ NIL',
})
- strings2sd_eq({{type=2, timestamp=0, data={'!map', {
- }}}}, {
+ strings2sd_eq({ { type = 2, timestamp = 0, data = { '!map', {} } } }, {
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' # Required key missing: sp',
@@ -1542,17 +1815,23 @@ describe('autoload/shada.vim', function()
' + so offset value 0',
' + su is last used TRUE',
})
- strings2sd_eq({{type=2, timestamp=0, data={
- sp='',
- sh={'!boolean', 1},
- ss={'!boolean', 1},
- sc={'!boolean', 1},
- sl={'!boolean', 1},
- se={'!boolean', 1},
- sm={'!boolean', 0},
- su={'!boolean', 0},
- so=-10,
- }}}, {
+ strings2sd_eq({
+ {
+ type = 2,
+ timestamp = 0,
+ data = {
+ sp = '',
+ sh = { '!boolean', 1 },
+ ss = { '!boolean', 1 },
+ sc = { '!boolean', 1 },
+ sl = { '!boolean', 1 },
+ se = { '!boolean', 1 },
+ sm = { '!boolean', 0 },
+ su = { '!boolean', 0 },
+ so = -10,
+ },
+ },
+ }, {
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' + sp pattern ""',
@@ -1565,17 +1844,23 @@ describe('autoload/shada.vim', function()
' + so offset value -10',
' + su is last used FALSE',
})
- strings2sd_eq({{type=2, timestamp=0, data={
- sp=0,
- sh=0,
- ss=0,
- sc=0,
- sl=0,
- se=0,
- sm=0,
- su=0,
- so='',
- }}}, {
+ strings2sd_eq({
+ {
+ type = 2,
+ timestamp = 0,
+ data = {
+ sp = 0,
+ sh = 0,
+ ss = 0,
+ sc = 0,
+ sl = 0,
+ se = 0,
+ sm = 0,
+ su = 0,
+ so = '',
+ },
+ },
+ }, {
'Search pattern with timestamp ' .. epoch .. ':',
' % Key Description________ Value',
' # Expected binary string',
@@ -1600,38 +1885,41 @@ describe('autoload/shada.vim', function()
end)
it('works with replacement string items', function()
- strings2sd_eq({{type=3, timestamp=0, data={
- a={10}
- }}}, {
+ strings2sd_eq({ { type = 3, timestamp = 0, data = {
+ a = { 10 },
+ } } }, {
'Replacement string with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
})
- strings2sd_eq({{type=3, timestamp=0, data={
- }}}, {
+ strings2sd_eq({ { type = 3, timestamp = 0, data = {} } }, {
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
- ' # Expected more elements in list'
+ ' # Expected more elements in list',
})
- strings2sd_eq({{type=3, timestamp=0, data={
- 0
- }}}, {
+ strings2sd_eq({ { type = 3, timestamp = 0, data = {
+ 0,
+ } } }, {
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' # Expected binary string',
' - :s replacement string 0',
})
- strings2sd_eq({{type=3, timestamp=0, data={
- 'abc\ndef', 0,
- }}}, {
- 'Replacement string with timestamp ' .. epoch .. ':',
- ' @ Description__________ Value',
- ' - :s replacement string "abc\\ndef"',
- ' - 0',
- })
- strings2sd_eq({{type=3, timestamp=0, data={
+ strings2sd_eq(
+ { { type = 3, timestamp = 0, data = {
+ 'abc\ndef',
+ 0,
+ } } },
+ {
+ 'Replacement string with timestamp ' .. epoch .. ':',
+ ' @ Description__________ Value',
+ ' - :s replacement string "abc\\ndef"',
+ ' - 0',
+ }
+ )
+ strings2sd_eq({ { type = 3, timestamp = 0, data = {
'abc\ndef',
- }}}, {
+ } } }, {
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
' - :s replacement string "abc\\ndef"',
@@ -1639,95 +1927,114 @@ describe('autoload/shada.vim', function()
end)
it('works with history entry items', function()
- strings2sd_eq({{type=4, timestamp=0, data={
- a={10},
- }}}, {
+ strings2sd_eq({ { type = 4, timestamp = 0, data = {
+ a = { 10 },
+ } } }, {
'History entry with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
})
- strings2sd_eq({{type=4, timestamp=0, data={
- }}}, {
+ strings2sd_eq({ { type = 4, timestamp = 0, data = {} } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
- ' # Expected more elements in list'
+ ' # Expected more elements in list',
})
- strings2sd_eq({{type=4, timestamp=0, data={
+ strings2sd_eq({ { type = 4, timestamp = 0, data = {
'',
- }}}, {
+ } } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' # Expected integer',
' - history type ""',
- ' # Expected more elements in list'
+ ' # Expected more elements in list',
})
- strings2sd_eq({{type=4, timestamp=0, data={
- 5, '',
- }}}, {
+ strings2sd_eq({ { type = 4, timestamp = 0, data = {
+ 5,
+ '',
+ } } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
- .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
+ .. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
' - history type 5',
' - contents ""',
})
- strings2sd_eq({{type=4, timestamp=0, data={
- 5, '', 32,
- }}}, {
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
+ strings2sd_eq(
+ { { type = 4, timestamp = 0, data = {
+ 5,
+ '',
+ 32,
+ } } },
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' # Unexpected enum value: expected one of 0 (CMD), 1 (SEARCH), '
.. '2 (EXPR), 3 (INPUT), 4 (DEBUG)',
- ' - history type 5',
- ' - contents ""',
- ' - 32',
- })
- strings2sd_eq({{type=4, timestamp=0, data={
- 0, '', 32,
- }}}, {
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type CMD',
- ' - contents ""',
- ' - 32',
- })
- strings2sd_eq({{type=4, timestamp=0, data={
- 1, '', 32,
- }}}, {
- 'History entry with timestamp ' .. epoch .. ':',
- ' @ Description_ Value',
- ' - history type SEARCH',
- ' - contents ""',
- ' - separator \' \'',
- })
- strings2sd_eq({{type=4, timestamp=0, data={
- 1, '',
- }}}, {
+ ' - history type 5',
+ ' - contents ""',
+ ' - 32',
+ }
+ )
+ strings2sd_eq(
+ { { type = 4, timestamp = 0, data = {
+ 0,
+ '',
+ 32,
+ } } },
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type CMD',
+ ' - contents ""',
+ ' - 32',
+ }
+ )
+ strings2sd_eq(
+ { { type = 4, timestamp = 0, data = {
+ 1,
+ '',
+ 32,
+ } } },
+ {
+ 'History entry with timestamp ' .. epoch .. ':',
+ ' @ Description_ Value',
+ ' - history type SEARCH',
+ ' - contents ""',
+ " - separator ' '",
+ }
+ )
+ strings2sd_eq({ { type = 4, timestamp = 0, data = {
+ 1,
+ '',
+ } } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type SEARCH',
' - contents ""',
' # Expected more elements in list',
})
- strings2sd_eq({{type=4, timestamp=0, data={
- 2, '',
- }}}, {
+ strings2sd_eq({ { type = 4, timestamp = 0, data = {
+ 2,
+ '',
+ } } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type EXPR',
' - contents ""',
})
- strings2sd_eq({{type=4, timestamp=0, data={
- 3, ''
- }}}, {
+ strings2sd_eq({ { type = 4, timestamp = 0, data = {
+ 3,
+ '',
+ } } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type INPUT',
' - contents ""',
})
- strings2sd_eq({{type=4, timestamp=0, data={
- 4, ''
- }}}, {
+ strings2sd_eq({ { type = 4, timestamp = 0, data = {
+ 4,
+ '',
+ } } }, {
'History entry with timestamp ' .. epoch .. ':',
' @ Description_ Value',
' - history type DEBUG',
@@ -1736,15 +2043,19 @@ describe('autoload/shada.vim', function()
end)
it('works with register items', function()
- strings2sd_eq({{type=5, timestamp=0, data={
- 1, 2, 3
- }}}, {
- 'Register with timestamp ' .. epoch .. ':',
- ' # Unexpected type: array instead of map',
- ' = [1, 2, 3]',
- })
- strings2sd_eq({{type=5, timestamp=0, data={'!map', {
- }}}}, {
+ strings2sd_eq(
+ { { type = 5, timestamp = 0, data = {
+ 1,
+ 2,
+ 3,
+ } } },
+ {
+ 'Register with timestamp ' .. epoch .. ':',
+ ' # Unexpected type: array instead of map',
+ ' = [1, 2, 3]',
+ }
+ )
+ strings2sd_eq({ { type = 5, timestamp = 0, data = { '!map', {} } } }, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: n',
@@ -1752,121 +2063,166 @@ describe('autoload/shada.vim', function()
' + rw block width 0',
' + rt type CHARACTERWISE',
})
- strings2sd_eq({{type=5, timestamp=0, data={
- n=(' '):byte()
- }}}, {
+ strings2sd_eq({ { type = 5, timestamp = 0, data = {
+ n = (' '):byte(),
+ } } }, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
- ' + n name \' \'',
+ " + n name ' '",
' # Required key missing: rc',
' + rw block width 0',
' + rt type CHARACTERWISE',
})
- strings2sd_eq({{type=5, timestamp=0, data={
- n=(' '):byte(), rc={'abc', 'def'}
- }}}, {
+ strings2sd_eq({
+ {
+ type = 5,
+ timestamp = 0,
+ data = {
+ n = (' '):byte(),
+ rc = { 'abc', 'def' },
+ },
+ },
+ }, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
- ' + n name \' \'',
+ " + n name ' '",
' + rc contents ["abc", "def"]',
' + rw block width 0',
' + rt type CHARACTERWISE',
})
- strings2sd_eq({{type=5, timestamp=0, data={
- n=(' '):byte(),
- rc={'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'},
- }}}, {
+ strings2sd_eq({
+ {
+ type = 5,
+ timestamp = 0,
+ data = {
+ n = (' '):byte(),
+ rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
+ },
+ },
+ }, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
- ' + n name \' \'',
+ " + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' + rw block width 0',
' + rt type CHARACTERWISE',
})
- strings2sd_eq({{type=5, timestamp=0, data={
- n=(' '):byte(),
- rc={'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'},
- rw=5,
- rt=1,
- }}}, {
+ strings2sd_eq({
+ {
+ type = 5,
+ timestamp = 0,
+ data = {
+ n = (' '):byte(),
+ rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
+ rw = 5,
+ rt = 1,
+ },
+ },
+ }, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
- ' + n name \' \'',
+ " + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' + rw block width 5',
' + rt type LINEWISE',
})
- strings2sd_eq({{type=5, timestamp=0, data={
- n=(' '):byte(),
- rc={'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz'},
- rw=5,
- rt=2,
- }}}, {
+ strings2sd_eq({
+ {
+ type = 5,
+ timestamp = 0,
+ data = {
+ n = (' '):byte(),
+ rc = { 'abcdefghijklmnopqrstuvwxyz', 'abcdefghijklmnopqrstuvwxyz' },
+ rw = 5,
+ rt = 2,
+ },
+ },
+ }, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
- ' + n name \' \'',
+ " + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
' + rw block width 5',
' + rt type BLOCKWISE',
})
- strings2sd_eq({{type=5, timestamp=0, data={
- n=(' '):byte(),
- rc=0,
- rw=-1,
- rt=10,
- }}}, {
+ strings2sd_eq({
+ {
+ type = 5,
+ timestamp = 0,
+ data = {
+ n = (' '):byte(),
+ rc = 0,
+ rw = -1,
+ rt = 10,
+ },
+ },
+ }, {
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
- ' + n name \' \'',
+ " + n name ' '",
' # Expected array value',
' + rc contents 0',
' # Value is negative',
' + rw block width -1',
' # Unexpected enum value: expected one of 0 (CHARACTERWISE), '
- .. '1 (LINEWISE), 2 (BLOCKWISE)',
+ .. '1 (LINEWISE), 2 (BLOCKWISE)',
' + rt type 10',
})
end)
it('works with variable items', function()
- strings2sd_eq({{type=6, timestamp=0, data={
- a={10}
- }}}, {
+ strings2sd_eq({ { type = 6, timestamp = 0, data = {
+ a = { 10 },
+ } } }, {
'Variable with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
})
- strings2sd_eq({{type=6, timestamp=0, data={
- }}}, {
+ strings2sd_eq({ { type = 6, timestamp = 0, data = {} } }, {
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
- ' # Expected more elements in list'
+ ' # Expected more elements in list',
})
- strings2sd_eq({{type=6, timestamp=0, data={
+ strings2sd_eq({ { type = 6, timestamp = 0, data = {
'foo',
- }}}, {
+ } } }, {
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' - name "foo"',
' # Expected more elements in list',
})
- strings2sd_eq({{type=6, timestamp=0, data={
- 'foo', {'!nil', 0},
- }}}, {
+ strings2sd_eq({
+ {
+ type = 6,
+ timestamp = 0,
+ data = {
+ 'foo',
+ { '!nil', 0 },
+ },
+ },
+ }, {
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' - name "foo"',
' - value NIL',
})
- strings2sd_eq({{type=6, timestamp=0, data={
- 'foo', {'!nil', 0}, {'!nil', 0}
- }}}, {
+ strings2sd_eq({
+ {
+ type = 6,
+ timestamp = 0,
+ data = {
+ 'foo',
+ { '!nil', 0 },
+ { '!nil', 0 },
+ },
+ },
+ }, {
'Variable with timestamp ' .. epoch .. ':',
' @ Description Value',
' - name "foo"',
@@ -1876,19 +2232,35 @@ describe('autoload/shada.vim', function()
end)
it('works with global mark items', function()
- strings2sd_eq({{type=7, timestamp=0, data={
- 1, 2, 3
- }}}, {
- 'Global mark with timestamp ' .. epoch .. ':',
- ' # Unexpected type: array instead of map',
- ' = [1, 2, 3]',
- })
- strings2sd_eq({{type=7, timestamp=0, data={
- n=('A'):byte(), f='foo', l=2, c=200, mX=10, mYYYYYYYYYY=10,
- }}}, {
+ strings2sd_eq(
+ { { type = 7, timestamp = 0, data = {
+ 1,
+ 2,
+ 3,
+ } } },
+ {
+ 'Global mark with timestamp ' .. epoch .. ':',
+ ' # Unexpected type: array instead of map',
+ ' = [1, 2, 3]',
+ }
+ )
+ strings2sd_eq({
+ {
+ type = 7,
+ timestamp = 0,
+ data = {
+ n = ('A'):byte(),
+ f = 'foo',
+ l = 2,
+ c = 200,
+ mX = 10,
+ mYYYYYYYYYY = 10,
+ },
+ },
+ }, {
'Global mark with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name "foo"',
' + l line number 2',
' + c column 200',
@@ -1898,19 +2270,35 @@ describe('autoload/shada.vim', function()
end)
it('works with jump items', function()
- strings2sd_eq({{type=8, timestamp=0, data={
- 1, 2, 3
- }}}, {
- 'Jump with timestamp ' .. epoch .. ':',
- ' # Unexpected type: array instead of map',
- ' = [1, 2, 3]',
- })
- strings2sd_eq({{type=8, timestamp=0, data={
- n=('A'):byte(), f='foo', l=2, c=200, mX=10, mYYYYYYYYYY=10,
- }}}, {
+ strings2sd_eq(
+ { { type = 8, timestamp = 0, data = {
+ 1,
+ 2,
+ 3,
+ } } },
+ {
+ 'Jump with timestamp ' .. epoch .. ':',
+ ' # Unexpected type: array instead of map',
+ ' = [1, 2, 3]',
+ }
+ )
+ strings2sd_eq({
+ {
+ type = 8,
+ timestamp = 0,
+ data = {
+ n = ('A'):byte(),
+ f = 'foo',
+ l = 2,
+ c = 200,
+ mX = 10,
+ mYYYYYYYYYY = 10,
+ },
+ },
+ }, {
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name "foo"',
' + l line number 2',
' + c column 200',
@@ -1920,23 +2308,27 @@ describe('autoload/shada.vim', function()
end)
it('works with buffer list items', function()
- strings2sd_eq({{type=9, timestamp=0, data={
- a={10}
- }}}, {
+ strings2sd_eq({ { type = 9, timestamp = 0, data = {
+ a = { 10 },
+ } } }, {
'Buffer list with timestamp ' .. epoch .. ':',
' # Unexpected type: map instead of array',
' = {="a": [10]}',
})
- strings2sd_eq({{type=9, timestamp=0, data={
- {a=10}, {}
- }}}, {
- 'Buffer list with timestamp ' .. epoch .. ':',
- ' # Expected array of maps',
- ' = [{="a": 10}, []]',
- })
- strings2sd_eq({{type=9, timestamp=0, data={
- {a=10},
- }}}, {
+ strings2sd_eq(
+ { { type = 9, timestamp = 0, data = {
+ { a = 10 },
+ {},
+ } } },
+ {
+ 'Buffer list with timestamp ' .. epoch .. ':',
+ ' # Expected array of maps',
+ ' = [{="a": 10}, []]',
+ }
+ )
+ strings2sd_eq({ { type = 9, timestamp = 0, data = {
+ { a = 10 },
+ } } }, {
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
@@ -1944,9 +2336,15 @@ describe('autoload/shada.vim', function()
' + c column 0',
' + a 10',
})
- strings2sd_eq({{type=9, timestamp=0, data={
- {l='10', c='10', a=10},
- }}}, {
+ strings2sd_eq({
+ {
+ type = 9,
+ timestamp = 0,
+ data = {
+ { l = '10', c = '10', a = 10 },
+ },
+ },
+ }, {
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Required key missing: f',
@@ -1956,59 +2354,79 @@ describe('autoload/shada.vim', function()
' + c column "10"',
' + a 10',
})
- strings2sd_eq({{type=9, timestamp=0, data={
- {l=10, c=10, a=10},
- }}}, {
- 'Buffer list with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Required key missing: f',
- ' + l line number 10',
- ' + c column 10',
- ' + a 10',
- })
- strings2sd_eq({{type=9, timestamp=0, data={
- {l=-10, c=-10},
- }}}, {
- 'Buffer list with timestamp ' .. epoch .. ':',
- ' % Key Description Value',
- ' # Required key missing: f',
- ' # Value is negative',
- ' + l line number -10',
- ' # Value is negative',
- ' + c column -10',
- })
- strings2sd_eq({{type=9, timestamp=0, data={
- {f='abc'},
- }}}, {
+ strings2sd_eq(
+ { { type = 9, timestamp = 0, data = {
+ { l = 10, c = 10, a = 10 },
+ } } },
+ {
+ 'Buffer list with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Required key missing: f',
+ ' + l line number 10',
+ ' + c column 10',
+ ' + a 10',
+ }
+ )
+ strings2sd_eq(
+ { { type = 9, timestamp = 0, data = {
+ { l = -10, c = -10 },
+ } } },
+ {
+ 'Buffer list with timestamp ' .. epoch .. ':',
+ ' % Key Description Value',
+ ' # Required key missing: f',
+ ' # Value is negative',
+ ' + l line number -10',
+ ' # Value is negative',
+ ' + c column -10',
+ }
+ )
+ strings2sd_eq({ { type = 9, timestamp = 0, data = {
+ { f = 'abc' },
+ } } }, {
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' + f file name "abc"',
' + l line number 1',
' + c column 0',
})
- strings2sd_eq({{type=9, timestamp=0, data={
- {f=10}, {f=20},
- }}}, {
+ strings2sd_eq({
+ {
+ type = 9,
+ timestamp = 0,
+ data = {
+ { f = 10 },
+ { f = 20 },
+ },
+ },
+ }, {
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected binary string',
- ' + f file name \'\\10\'',
+ " + f file name '\\10'",
' + l line number 1',
' + c column 0',
'',
' % Key Description Value',
' # Expected binary string',
- ' + f file name \'\\20\'',
+ " + f file name '\\20'",
' + l line number 1',
' + c column 0',
})
- strings2sd_eq({{type=9, timestamp=0, data={
- {f=10}, {f={'!binary', {'\n'}}},
- }}}, {
+ strings2sd_eq({
+ {
+ type = 9,
+ timestamp = 0,
+ data = {
+ { f = 10 },
+ { f = { '!binary', { '\n' } } },
+ },
+ },
+ }, {
'Buffer list with timestamp ' .. epoch .. ':',
' % Key Description Value',
' # Expected binary string',
- ' + f file name \'\\10\'',
+ " + f file name '\\10'",
' + l line number 1',
' + c column 0',
'',
@@ -2021,19 +2439,35 @@ describe('autoload/shada.vim', function()
end)
it('works with local mark items', function()
- strings2sd_eq({{type=10, timestamp=0, data={
- 1, 2, 3
- }}}, {
- 'Local mark with timestamp ' .. epoch .. ':',
- ' # Unexpected type: array instead of map',
- ' = [1, 2, 3]',
- })
- strings2sd_eq({{type=10, timestamp=0, data={
- n=('A'):byte(), f='foo', l=2, c=200, mX=10, mYYYYYYYYYY=10,
- }}}, {
+ strings2sd_eq(
+ { { type = 10, timestamp = 0, data = {
+ 1,
+ 2,
+ 3,
+ } } },
+ {
+ 'Local mark with timestamp ' .. epoch .. ':',
+ ' # Unexpected type: array instead of map',
+ ' = [1, 2, 3]',
+ }
+ )
+ strings2sd_eq({
+ {
+ type = 10,
+ timestamp = 0,
+ data = {
+ n = ('A'):byte(),
+ f = 'foo',
+ l = 2,
+ c = 200,
+ mX = 10,
+ mYYYYYYYYYY = 10,
+ },
+ },
+ }, {
'Local mark with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name "foo"',
' + l line number 2',
' + c column 200',
@@ -2043,19 +2477,35 @@ describe('autoload/shada.vim', function()
end)
it('works with change items', function()
- strings2sd_eq({{type=11, timestamp=0, data={
- 1, 2, 3
- }}}, {
- 'Change with timestamp ' .. epoch .. ':',
- ' # Unexpected type: array instead of map',
- ' = [1, 2, 3]',
- })
- strings2sd_eq({{type=11, timestamp=0, data={
- n=('A'):byte(), f='foo', l=2, c=200, mX=10, mYYYYYYYYYY=10,
- }}}, {
+ strings2sd_eq(
+ { { type = 11, timestamp = 0, data = {
+ 1,
+ 2,
+ 3,
+ } } },
+ {
+ 'Change with timestamp ' .. epoch .. ':',
+ ' # Unexpected type: array instead of map',
+ ' = [1, 2, 3]',
+ }
+ )
+ strings2sd_eq({
+ {
+ type = 11,
+ timestamp = 0,
+ data = {
+ n = ('A'):byte(),
+ f = 'foo',
+ l = 2,
+ c = 200,
+ mX = 10,
+ mYYYYYYYYYY = 10,
+ },
+ },
+ }, {
'Change with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name "foo"',
' + l line number 2',
' + c column 200',
@@ -2067,7 +2517,7 @@ describe('autoload/shada.vim', function()
describe('function shada#get_binstrings', function()
local getbstrings_eq = function(expected, input)
- local result = funcs['shada#get_binstrings'](input)
+ local result = fn['shada#get_binstrings'](input)
for i, s in ipairs(result) do
result[i] = s:gsub('\n', '\0')
end
@@ -2076,53 +2526,75 @@ describe('autoload/shada.vim', function()
end
it('works', function()
- local version = nvim('get_vvar', 'version')
- getbstrings_eq({{timestamp='current', type=1, value={
- generator='shada.vim',
- version=version,
- }}}, {})
+ local version = api.nvim_get_vvar('version')
getbstrings_eq({
- {timestamp='current', type=1, value={
- generator='shada.vim', version=version
- }},
- {timestamp=0, type=1, value={generator='test'}}
+ {
+ timestamp = 'current',
+ type = 1,
+ value = {
+ generator = 'shada.vim',
+ version = version,
+ },
+ },
+ }, {})
+ getbstrings_eq({
+ {
+ timestamp = 'current',
+ type = 1,
+ value = {
+ generator = 'shada.vim',
+ version = version,
+ },
+ },
+ { timestamp = 0, type = 1, value = { generator = 'test' } },
}, {
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
})
- nvim('set_var', 'shada#add_own_header', 1)
- getbstrings_eq({{timestamp='current', type=1, value={
- generator='shada.vim',
- version=version,
- }}}, {})
+ api.nvim_set_var('shada#add_own_header', 1)
+ getbstrings_eq({
+ {
+ timestamp = 'current',
+ type = 1,
+ value = {
+ generator = 'shada.vim',
+ version = version,
+ },
+ },
+ }, {})
getbstrings_eq({
- {timestamp='current', type=1, value={
- generator='shada.vim', version=version
- }},
- {timestamp=0, type=1, value={generator='test'}}
+ {
+ timestamp = 'current',
+ type = 1,
+ value = {
+ generator = 'shada.vim',
+ version = version,
+ },
+ },
+ { timestamp = 0, type = 1, value = { generator = 'test' } },
}, {
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
})
- nvim('set_var', 'shada#add_own_header', 0)
+ api.nvim_set_var('shada#add_own_header', 0)
getbstrings_eq({}, {})
- getbstrings_eq({{timestamp=0, type=1, value={generator='test'}}}, {
+ getbstrings_eq({ { timestamp = 0, type = 1, value = { generator = 'test' } } }, {
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
})
- nvim('set_var', 'shada#keep_old_header', 0)
+ api.nvim_set_var('shada#keep_old_header', 0)
getbstrings_eq({}, {
'Header with timestamp ' .. epoch .. ':',
' % Key______ Value',
' + generator "test"',
})
getbstrings_eq({
- {type=3, timestamp=0, value={'abc\ndef'}},
- {type=3, timestamp=0, value={'abc\ndef'}},
- {type=3, timestamp=0, value={'abc\ndef'}},
+ { type = 3, timestamp = 0, value = { 'abc\ndef' } },
+ { type = 3, timestamp = 0, value = { 'abc\ndef' } },
+ { type = 3, timestamp = 0, value = { 'abc\ndef' } },
}, {
'Replacement string with timestamp ' .. epoch .. ':',
' @ Description__________ Value',
@@ -2164,8 +2636,8 @@ describe('plugin/shada.vim', function()
wshada('\004\000\009\147\000\196\002ab\196\001a')
wshada_tmp('\004\000\009\147\000\196\002ab\196\001b')
-
- local bufread_commands = meths.get_autocmds({ group = "ShaDaCommands", event = "BufReadCmd" })
+ local bufread_commands =
+ api.nvim_get_autocmds({ group = 'ShaDaCommands', event = 'BufReadCmd' })
eq(2, #bufread_commands--[[, vim.inspect(bufread_commands) ]])
-- Need to set nohidden so that the buffer containing 'fname' is not unloaded
@@ -2181,8 +2653,8 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "a"',
}, nvim_eval('getline(1, "$")'))
- eq(false, nvim('get_option_value', 'modified', {}))
- eq('shada', nvim('get_option_value', 'filetype', {}))
+ eq(false, api.nvim_get_option_value('modified', {}))
+ eq('shada', api.nvim_get_option_value('filetype', {}))
nvim_command('edit ' .. fname_tmp)
eq({
'History entry with timestamp ' .. epoch .. ':',
@@ -2191,8 +2663,8 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "b"',
}, nvim_eval('getline(1, "$")'))
- eq(false, nvim('get_option_value', 'modified', {}))
- eq('shada', nvim('get_option_value', 'filetype', {}))
+ eq(false, api.nvim_get_option_value('modified', {}))
+ eq('shada', api.nvim_get_option_value('filetype', {}))
eq('++opt not supported', exc_exec('edit ++enc=latin1 ' .. fname))
neq({
'History entry with timestamp ' .. epoch .. ':',
@@ -2201,7 +2673,7 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "a"',
}, nvim_eval('getline(1, "$")'))
- neq(true, nvim('get_option_value', 'modified', {}))
+ neq(true, api.nvim_get_option_value('modified', {}))
end)
it('event FileReadCmd', function()
@@ -2217,8 +2689,8 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "a"',
}, nvim_eval('getline(1, "$")'))
- eq(true, nvim('get_option_value', 'modified', {}))
- neq('shada', nvim('get_option_value', 'filetype', {}))
+ eq(true, api.nvim_get_option_value('modified', {}))
+ neq('shada', api.nvim_get_option_value('filetype', {}))
nvim_command('1,$read ' .. fname_tmp)
eq({
'',
@@ -2233,9 +2705,9 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "b"',
}, nvim_eval('getline(1, "$")'))
- eq(true, nvim('get_option_value', 'modified', {}))
- neq('shada', nvim('get_option_value', 'filetype', {}))
- nvim('set_option_value', 'modified', false, {})
+ eq(true, api.nvim_get_option_value('modified', {}))
+ neq('shada', api.nvim_get_option_value('filetype', {}))
+ api.nvim_set_option_value('modified', false, {})
eq('++opt not supported', exc_exec('$read ++enc=latin1 ' .. fname))
eq({
'',
@@ -2250,22 +2722,22 @@ describe('plugin/shada.vim', function()
' - contents "ab"',
' - "b"',
}, nvim_eval('getline(1, "$")'))
- neq(true, nvim('get_option_value', 'modified', {}))
+ neq(true, api.nvim_get_option_value('modified', {}))
end)
it('event BufWriteCmd', function()
reset()
- nvim('set_var', 'shada#add_own_header', 0)
- curbuf('set_lines', 0, 1, true, {
+ api.nvim_set_var('shada#add_own_header', 0)
+ api.nvim_buf_set_lines(0, 0, 1, true, {
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
@@ -2277,50 +2749,56 @@ describe('plugin/shada.vim', function()
eq(table.concat({
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
}, eol) .. eol, read_file(fname .. '.tst'))
- shada_eq({{
- timestamp=0,
- type=8,
- value={c=-200, f={'foo'}, l=2, n=('A'):byte()},
- }, {
- timestamp=0,
- type=8,
- value={c=-200, f={'foo'}, l=2, n=('A'):byte()},
- }}, fname)
- shada_eq({{
- timestamp=0,
- type=8,
- value={c=-200, f={'foo'}, l=2, n=('A'):byte()},
- }, {
- timestamp=0,
- type=8,
- value={c=-200, f={'foo'}, l=2, n=('A'):byte()},
- }}, fname_tmp)
+ shada_eq({
+ {
+ timestamp = 0,
+ type = 8,
+ value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
+ },
+ {
+ timestamp = 0,
+ type = 8,
+ value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
+ },
+ }, fname)
+ shada_eq({
+ {
+ timestamp = 0,
+ type = 8,
+ value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
+ },
+ {
+ timestamp = 0,
+ type = 8,
+ value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
+ },
+ }, fname_tmp)
end)
it('event FileWriteCmd', function()
reset()
- nvim('set_var', 'shada#add_own_header', 0)
- curbuf('set_lines', 0, 1, true, {
+ api.nvim_set_var('shada#add_own_header', 0)
+ api.nvim_buf_set_lines(0, 0, 1, true, {
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
@@ -2332,40 +2810,46 @@ describe('plugin/shada.vim', function()
eq(table.concat({
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
}, eol) .. eol, read_file(fname .. '.tst'))
- shada_eq({{
- timestamp=0,
- type=8,
- value={n=('A'):byte()},
- }}, fname)
- shada_eq({{
- timestamp=0,
- type=8,
- value={n=('A'):byte()},
- }}, fname_tmp)
+ shada_eq(
+ { {
+ timestamp = 0,
+ type = 8,
+ value = { n = ('A'):byte() },
+ } },
+ fname
+ )
+ shada_eq(
+ { {
+ timestamp = 0,
+ type = 8,
+ value = { n = ('A'):byte() },
+ } },
+ fname_tmp
+ )
end)
it('event FileAppendCmd', function()
reset()
- nvim('set_var', 'shada#add_own_header', 0)
- curbuf('set_lines', 0, 1, true, {
+ api.nvim_set_var('shada#add_own_header', 0)
+ api.nvim_buf_set_lines(0, 0, 1, true, {
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
})
- funcs.writefile({''}, fname .. '.tst', 'b')
- funcs.writefile({''}, fname, 'b')
- funcs.writefile({''}, fname_tmp, 'b')
+ fn.writefile({ '' }, fname .. '.tst', 'b')
+ fn.writefile({ '' }, fname, 'b')
+ fn.writefile({ '' }, fname_tmp, 'b')
nvim_command('1,3w >> ' .. fname .. '.tst')
nvim_command('1,3w >> ' .. fname)
nvim_command('1,3w >> ' .. fname_tmp)
@@ -2376,59 +2860,67 @@ describe('plugin/shada.vim', function()
eq(table.concat({
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
}, eol) .. eol, read_file(fname .. '.tst'))
- shada_eq({{
- timestamp=0,
- type=8,
- value={n=('A'):byte()},
- }, {
- timestamp=0,
- type=8,
- value={c=-200, f={'foo'}, l=2, n=('A'):byte()},
- }, {
- timestamp=0,
- type=8,
- value={c=-200, f={'foo'}, l=2, n=('A'):byte()},
- }}, fname)
- shada_eq({{
- timestamp=0,
- type=8,
- value={n=('A'):byte()},
- }, {
- timestamp=0,
- type=8,
- value={c=-200, f={'foo'}, l=2, n=('A'):byte()},
- }, {
- timestamp=0,
- type=8,
- value={c=-200, f={'foo'}, l=2, n=('A'):byte()},
- }}, fname_tmp)
+ shada_eq({
+ {
+ timestamp = 0,
+ type = 8,
+ value = { n = ('A'):byte() },
+ },
+ {
+ timestamp = 0,
+ type = 8,
+ value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
+ },
+ {
+ timestamp = 0,
+ type = 8,
+ value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
+ },
+ }, fname)
+ shada_eq({
+ {
+ timestamp = 0,
+ type = 8,
+ value = { n = ('A'):byte() },
+ },
+ {
+ timestamp = 0,
+ type = 8,
+ value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
+ },
+ {
+ timestamp = 0,
+ type = 8,
+ value = { c = -200, f = { 'foo' }, l = 2, n = ('A'):byte() },
+ },
+ }, fname_tmp)
end)
it('event SourceCmd', function()
reset(fname)
finally(function()
- nvim_command('set shadafile=NONE') -- Avoid writing shada file on exit
+ nvim_command('set shadafile=NONE') -- Avoid writing shada file on exit
end)
wshada('\004\000\006\146\000\196\002ab')
wshada_tmp('\004\001\006\146\000\196\002bc')
eq(0, exc_exec('source ' .. fname))
eq(0, exc_exec('source ' .. fname_tmp))
- eq('bc', funcs.histget(':', -1))
- eq('ab', funcs.histget(':', -2))
+ eq('bc', fn.histget(':', -1))
+ eq('ab', fn.histget(':', -2))
end)
end)
@@ -2439,10 +2931,10 @@ describe('ftplugin/shada.vim', function()
it('sets indentexpr correctly', function()
nvim_command('filetype plugin indent on')
nvim_command('setlocal filetype=shada')
- funcs.setline(1, {
+ fn.setline(1, {
'Jump with timestamp ' .. epoch .. ':',
'% Key________ Description Value',
- '+ n name \'A\'',
+ "+ n name 'A'",
'+ f file name "foo"',
'+ l line number 2',
'+ c column 200',
@@ -2450,7 +2942,7 @@ describe('ftplugin/shada.vim', function()
'+ mYYYYYYYYYY 10',
'Register with timestamp ' .. epoch .. ':',
'% Key Description Value',
- '+ n name \' \'',
+ "+ n name ' '",
'+ rc contents @',
'| - "abcdefghijklmnopqrstuvwxyz"',
'| - "abcdefghijklmnopqrstuvwxyz"',
@@ -2479,7 +2971,7 @@ describe('ftplugin/shada.vim', function()
eq({
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name "foo"',
' + l line number 2',
' + c column 200',
@@ -2487,7 +2979,7 @@ describe('ftplugin/shada.vim', function()
' + mYYYYYYYYYY 10',
'Register with timestamp ' .. epoch .. ':',
' % Key Description Value',
- ' + n name \' \'',
+ " + n name ' '",
' + rc contents @',
' | - "abcdefghijklmnopqrstuvwxyz"',
' | - "abcdefghijklmnopqrstuvwxyz"',
@@ -2511,34 +3003,34 @@ describe('ftplugin/shada.vim', function()
' + f file name 20',
' + l line number 1',
' + c column 0',
- }, funcs.getline(1, funcs.line('$')))
+ }, fn.getline(1, fn.line('$')))
end)
it('sets options correctly', function()
nvim_command('filetype plugin indent on')
nvim_command('setlocal filetype=shada')
- 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', {}))
+ eq(true, api.nvim_get_option_value('expandtab', {}))
+ eq(2, api.nvim_get_option_value('tabstop', {}))
+ eq(2, api.nvim_get_option_value('softtabstop', {}))
+ eq(2, api.nvim_get_option_value('shiftwidth', {}))
end)
it('sets indentkeys correctly', function()
nvim_command('filetype plugin indent on')
nvim_command('setlocal filetype=shada')
- funcs.setline(1, ' Replacement with timestamp ' .. epoch)
+ fn.setline(1, ' Replacement with timestamp ' .. epoch)
nvim_feed('ggA:\027')
- eq('Replacement with timestamp ' .. epoch .. ':', curbuf('get_lines', 0, 1, true)[1])
+ eq('Replacement with timestamp ' .. epoch .. ':', api.nvim_buf_get_lines(0, 0, 1, true)[1])
nvim_feed('o-\027')
- eq({' -'}, curbuf('get_lines', 1, 2, true))
+ eq({ ' -' }, api.nvim_buf_get_lines(0, 1, 2, true))
nvim_feed('ggO+\027')
- eq({'+'}, curbuf('get_lines', 0, 1, true))
+ eq({ '+' }, api.nvim_buf_get_lines(0, 0, 1, true))
nvim_feed('GO*\027')
- eq({' *'}, curbuf('get_lines', 2, 3, true))
+ eq({ ' *' }, api.nvim_buf_get_lines(0, 2, 3, true))
nvim_feed('ggO /\027')
- eq({' /'}, curbuf('get_lines', 0, 1, true))
+ eq({ ' /' }, api.nvim_buf_get_lines(0, 0, 1, true))
nvim_feed('ggOx\027')
- eq({'x'}, curbuf('get_lines', 0, 1, true))
+ eq({ 'x' }, api.nvim_buf_get_lines(0, 0, 1, true))
end)
end)
@@ -2552,24 +3044,24 @@ describe('syntax/shada.vim', function()
nvim_command('set laststatus&')
local screen = Screen.new(60, 37)
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Brown};
- [2] = {foreground = tonumber('0x6a0dad')};
- [3] = {foreground = Screen.colors.Fuchsia};
- [4] = {foreground = Screen.colors.Blue1};
- [5] = {bold = true, foreground = Screen.colors.SeaGreen4};
- [6] = {foreground = Screen.colors.SlateBlue};
- [7] = {bold = true, reverse = true};
- [8] = {bold = true, foreground = Screen.colors.Blue};
+ [1] = { bold = true, foreground = Screen.colors.Brown },
+ [2] = { foreground = tonumber('0x6a0dad') },
+ [3] = { foreground = Screen.colors.Fuchsia },
+ [4] = { foreground = Screen.colors.Blue1 },
+ [5] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [6] = { foreground = Screen.colors.SlateBlue },
+ [7] = { bold = true, reverse = true },
+ [8] = { bold = true, foreground = Screen.colors.Blue },
}
screen:attach()
- curbuf('set_lines', 0, 1, true, {
+ api.nvim_buf_set_lines(0, 0, 1, true, {
'Header with timestamp ' .. epoch .. ':',
' % Key Value',
' + t "test"',
'Jump with timestamp ' .. epoch .. ':',
' % Key________ Description Value',
- ' + n name \'A\'',
+ " + n name 'A'",
' + f file name ["foo"]',
' + l line number 2',
' + c column -200',
@@ -2598,7 +3090,8 @@ describe('syntax/shada.vim', function()
' % Key Description________ Value',
' + se place cursor at end TRUE',
})
- screen:expect{grid=[=[
+ screen:expect {
+ grid = [=[
{1:^Header} with timestamp 1970{1:-}01{1:-}01{1:T}00{1::}00{1::}00: |
{2: % Key Value} |
{1: +} {3:t } {1:"}{3:test}{1:"} |
@@ -2636,7 +3129,8 @@ describe('syntax/shada.vim', function()
{8:~ }|
{7:[No Name] [+] }|
|
- ]=]}
+ ]=],
+ }
nvim_command([[
function GetSyntax()
@@ -2657,15 +3151,20 @@ describe('syntax/shada.vim', function()
return lines
endfunction
]])
- local hname = function(s) return {{'ShaDaEntryHeader', 'ShaDaEntryName'},
- s} end
- local h = function(s) return {{'ShaDaEntryHeader'}, s} end
- local htsnum = function(s) return {
- {'ShaDaEntryHeader', 'ShaDaEntryTimestamp', 'ShaDaEntryTimestampNumber'},
- s
- } end
+ local hname = function(s)
+ return { { 'ShaDaEntryHeader', 'ShaDaEntryName' }, s }
+ end
+ local h = function(s)
+ return { { 'ShaDaEntryHeader' }, s }
+ end
+ local htsnum = function(s)
+ return {
+ { 'ShaDaEntryHeader', 'ShaDaEntryTimestamp', 'ShaDaEntryTimestampNumber' },
+ s,
+ }
+ end
local synhtssep = function(s)
- return {{'ShaDaEntryHeader', 'ShaDaEntryTimestamp'}, s}
+ return { { 'ShaDaEntryHeader', 'ShaDaEntryTimestamp' }, s }
end
local synepoch = {
year = htsnum(os.date('%Y', 0)),
@@ -2675,255 +3174,435 @@ describe('syntax/shada.vim', function()
minute = htsnum(os.date('%M', 0)),
second = htsnum(os.date('%S', 0)),
}
- local msh = function(s) return {{'ShaDaEntryMapShort',
- 'ShaDaEntryMapHeader'}, s} end
- local mlh = function(s) return {{'ShaDaEntryMapLong',
- 'ShaDaEntryMapHeader'}, s} end
- local ah = function(s) return {{'ShaDaEntryArray',
- 'ShaDaEntryArrayHeader'}, s} end
+ local msh = function(s)
+ return {
+ { 'ShaDaEntryMapShort', 'ShaDaEntryMapHeader' },
+ s,
+ }
+ end
+ local mlh = function(s)
+ return { { 'ShaDaEntryMapLong', 'ShaDaEntryMapHeader' }, s }
+ end
+ local ah = function(s)
+ return { { 'ShaDaEntryArray', 'ShaDaEntryArrayHeader' }, s }
+ end
-- luacheck: ignore
- local mses = function(s) return {{'ShaDaEntryMapShort',
- 'ShaDaEntryMapShortEntryStart'}, s} end
- local mles = function(s) return {{'ShaDaEntryMapLong',
- 'ShaDaEntryMapLongEntryStart'}, s} end
- local act = funcs.GetSyntax()
+ local mses = function(s)
+ return {
+ {
+ 'ShaDaEntryMapShort',
+ 'ShaDaEntryMapShortEntryStart',
+ },
+ s,
+ }
+ end
+ local mles = function(s)
+ return {
+ { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongEntryStart' },
+ s,
+ }
+ end
+ local act = fn.GetSyntax()
local ms = function(syn)
return {
- {'ShaDaEntryMap' .. syn, 'ShaDaEntryMap' .. syn .. 'EntryStart'}, ' + '
+ { 'ShaDaEntryMap' .. syn, 'ShaDaEntryMap' .. syn .. 'EntryStart' },
+ ' + ',
}
end
local as = function()
- return {{'ShaDaEntryArray', 'ShaDaEntryArrayEntryStart'}, ' - '}
+ return { { 'ShaDaEntryArray', 'ShaDaEntryArrayEntryStart' }, ' - ' }
+ end
+ local ad = function(s)
+ return {
+ { 'ShaDaEntryArray', 'ShaDaEntryArrayDescription' },
+ s,
+ }
end
- local ad = function(s) return {{'ShaDaEntryArray',
- 'ShaDaEntryArrayDescription'}, s} end
local mbas = function(syn)
return {
- {'ShaDaEntryMap' .. syn, 'ShaDaEntryMapBinArrayStart'},
- ' | - '
+ { 'ShaDaEntryMap' .. syn, 'ShaDaEntryMapBinArrayStart' },
+ ' | - ',
+ }
+ end
+ local msk = function(s)
+ return {
+ { 'ShaDaEntryMapShort', 'ShaDaEntryMapShortKey' },
+ s,
+ }
+ end
+ local mlk = function(s)
+ return {
+ { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongKey' },
+ s,
}
end
- local msk = function(s) return {{'ShaDaEntryMapShort',
- 'ShaDaEntryMapShortKey'}, s} end
- local mlk = function(s) return {{'ShaDaEntryMapLong',
- 'ShaDaEntryMapLongKey'}, s} end
- local mld = function(s) return {{'ShaDaEntryMapLong',
- 'ShaDaEntryMapLongDescription'}, s} end
- local c = function(s) return {{'ShaDaComment'}, s} end
+ local mld = function(s)
+ return {
+ { 'ShaDaEntryMapLong', 'ShaDaEntryMapLongDescription' },
+ s,
+ }
+ end
+ local c = function(s)
+ return { { 'ShaDaComment' }, s }
+ end
local exp = {
{
- hname('Header'), h(' with timestamp '),
- synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'),
- synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'),
- synepoch.minute, synhtssep(':'), synepoch.second, h(':'),
+ hname('Header'),
+ h(' with timestamp '),
+ synepoch.year,
+ synhtssep('-'),
+ synepoch.month,
+ synhtssep('-'),
+ synepoch.day,
+ synhtssep('T'),
+ synepoch.hour,
+ synhtssep(':'),
+ synepoch.minute,
+ synhtssep(':'),
+ synepoch.second,
+ h(':'),
},
{
msh(' % Key Value'),
},
{
- ms('Short'), msk('t '),
- {{'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString',
- 'ShaDaMsgpackStringQuotes'}, '"'},
- {{'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString'}, 'test'},
- {{'ShaDaEntryMapShort', 'ShaDaMsgpackStringQuotes'}, '"'},
+ ms('Short'),
+ msk('t '),
+ {
+ { 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString', 'ShaDaMsgpackStringQuotes' },
+ '"',
+ },
+ { { 'ShaDaEntryMapShort', 'ShaDaMsgpackBinaryString' }, 'test' },
+ { { 'ShaDaEntryMapShort', 'ShaDaMsgpackStringQuotes' }, '"' },
},
{
- hname('Jump'), h(' with timestamp '),
- synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'),
- synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'),
- synepoch.minute, synhtssep(':'), synepoch.second, h(':'),
+ hname('Jump'),
+ h(' with timestamp '),
+ synepoch.year,
+ synhtssep('-'),
+ synepoch.month,
+ synhtssep('-'),
+ synepoch.day,
+ synhtssep('T'),
+ synepoch.hour,
+ synhtssep(':'),
+ synepoch.minute,
+ synhtssep(':'),
+ synepoch.second,
+ h(':'),
},
{
mlh(' % Key________ Description Value'),
},
{
- ms('Long'), mlk('n '), mld('name '),
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackCharacter'}, '\'A\''},
+ ms('Long'),
+ mlk('n '),
+ mld('name '),
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackCharacter' }, "'A'" },
},
{
- ms('Long'), mlk('f '), mld('file name '),
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackArray',
- 'ShaDaMsgpackArrayBraces'}, '['},
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString',
- 'ShaDaMsgpackStringQuotes'}, '"'},
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString'},
- 'foo'},
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes'},
- '"'},
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackArrayBraces'}, ']'},
+ ms('Long'),
+ mlk('f '),
+ mld('file name '),
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
+ {
+ {
+ 'ShaDaEntryMapLong',
+ 'ShaDaMsgpackArray',
+ 'ShaDaMsgpackBinaryString',
+ 'ShaDaMsgpackStringQuotes',
+ },
+ '"',
+ },
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString' }, 'foo' },
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' },
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackArrayBraces' }, ']' },
},
{
- ms('Long'), mlk('l '), mld('line number '),
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackInteger'}, '2'},
+ ms('Long'),
+ mlk('l '),
+ mld('line number '),
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '2' },
},
{
- ms('Long'), mlk('c '), mld('column '),
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackInteger'}, '-200'},
+ ms('Long'),
+ mlk('c '),
+ mld('column '),
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackInteger' }, '-200' },
},
{
- hname('Register'), h(' with timestamp '),
- synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'),
- synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'),
- synepoch.minute, synhtssep(':'), synepoch.second, h(':'),
+ hname('Register'),
+ h(' with timestamp '),
+ synepoch.year,
+ synhtssep('-'),
+ synepoch.month,
+ synhtssep('-'),
+ synepoch.day,
+ synhtssep('T'),
+ synepoch.hour,
+ synhtssep(':'),
+ synepoch.minute,
+ synhtssep(':'),
+ synepoch.second,
+ h(':'),
},
{
mlh(' % Key Description Value'),
},
{
- ms('Long'), mlk('rc '), mld('contents '),
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackMultilineArray'}, '@'},
+ ms('Long'),
+ mlk('rc '),
+ mld('contents '),
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMultilineArray' }, '@' },
},
{
mbas('Long'),
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces'},
- '{'},
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString',
- 'ShaDaMsgpackStringQuotes'}, '"'},
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'},
- 'abcdefghijklmnopqrstuvwxyz'},
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes'},
- '"'},
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon'}, ':'},
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap'}, ' '},
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackFloat'}, '1.0'},
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackMapBraces'}, '}'},
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' },
+ {
+ {
+ 'ShaDaEntryMapLong',
+ 'ShaDaMsgpackMap',
+ 'ShaDaMsgpackBinaryString',
+ 'ShaDaMsgpackStringQuotes',
+ },
+ '"',
+ },
+ {
+ { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' },
+ 'abcdefghijklmnopqrstuvwxyz',
+ },
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap' }, ' ' },
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMap', 'ShaDaMsgpackFloat' }, '1.0' },
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackMapBraces' }, '}' },
},
{
- ms('Long'), mlk('rt '), mld('type '),
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword'}, 'CHARACTERWISE'},
+ ms('Long'),
+ mlk('rt '),
+ mld('type '),
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'CHARACTERWISE' },
},
{
- ms('Long'), mlk('rt '), mld('type '),
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword'}, 'LINEWISE'},
+ ms('Long'),
+ mlk('rt '),
+ mld('type '),
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'LINEWISE' },
},
{
- ms('Long'), mlk('rt '), mld('type '),
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword'}, 'BLOCKWISE'},
+ ms('Long'),
+ mlk('rt '),
+ mld('type '),
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackShaDaKeyword' }, 'BLOCKWISE' },
},
{
- hname('Replacement string'), h(' with timestamp '),
- synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'),
- synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'),
- synepoch.minute, synhtssep(':'), synepoch.second, h(':'),
+ hname('Replacement string'),
+ h(' with timestamp '),
+ synepoch.year,
+ synhtssep('-'),
+ synepoch.month,
+ synhtssep('-'),
+ synepoch.day,
+ synhtssep('T'),
+ synepoch.hour,
+ synhtssep(':'),
+ synepoch.minute,
+ synhtssep(':'),
+ synepoch.second,
+ h(':'),
},
{
ah(' @ Description__________ Value'),
},
{
- as(), ad(':s replacement string '),
- {{'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword'}, 'CMD'},
+ as(),
+ ad(':s replacement string '),
+ { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'CMD' },
},
{
- as(), ad(':s replacement string '),
- {{'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword'}, 'SEARCH'},
+ as(),
+ ad(':s replacement string '),
+ { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'SEARCH' },
},
{
- as(), ad(':s replacement string '),
- {{'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword'}, 'EXPR'},
+ as(),
+ ad(':s replacement string '),
+ { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'EXPR' },
},
{
- as(), ad(':s replacement string '),
- {{'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword'}, 'INPUT'},
+ as(),
+ ad(':s replacement string '),
+ { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'INPUT' },
},
{
- as(), ad(':s replacement string '),
- {{'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword'}, 'DEBUG'},
+ as(),
+ ad(':s replacement string '),
+ { { 'ShaDaEntryArray', 'ShaDaMsgpackShaDaKeyword' }, 'DEBUG' },
},
{
- hname('Buffer list'), h(' with timestamp '),
- synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'),
- synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'),
- synepoch.minute, synhtssep(':'), synepoch.second, h(':'),
+ hname('Buffer list'),
+ h(' with timestamp '),
+ synepoch.year,
+ synhtssep('-'),
+ synepoch.month,
+ synhtssep('-'),
+ synepoch.day,
+ synhtssep('T'),
+ synepoch.hour,
+ synhtssep(':'),
+ synepoch.minute,
+ synhtssep(':'),
+ synepoch.second,
+ h(':'),
},
{
c(' # Expected array of maps'),
},
{
- {{'ShaDaEntryRawMsgpack'}, ' = '},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces'}, '['},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces'},
- '{'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackString'}, '='},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString',
- 'ShaDaMsgpackStringQuotes'}, '"'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'},
- 'a'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes'},
- '"'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon'}, ':'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap'}, ' '},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt'}, '+('},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt',
- 'ShaDaMsgpackExtType'}, '10'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt'}, ')'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString',
- 'ShaDaMsgpackStringQuotes'}, '"'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'},
- 'ac'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString',
- 'ShaDaMsgpackBinaryStringEscape'},
- '\\0'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'},
- 'df'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString',
- 'ShaDaMsgpackBinaryStringEscape'},
- '\\n'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'},
- 'gi'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString',
- 'ShaDaMsgpackBinaryStringEscape'},
- '\\"'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString'},
- 'tt\\.'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes'},
- '"'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackComma'}, ','},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap'}, ' '},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword'},
- 'TRUE'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon'}, ':'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap'}, ' '},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword'},
- 'FALSE'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackMapBraces'}, '}'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackComma'}, ','},
- {{'ShaDaMsgpackArray'}, ' '},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces'},
- '['},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackKeyword'},
- 'NIL'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackComma'}, ','},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray'}, ' '},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt'}, '+('},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt',
- 'ShaDaMsgpackExtType'}, '-10'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt'}, ')'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackBinaryString',
- 'ShaDaMsgpackStringQuotes'}, '"'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes'},
- '"'},
- {{'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces'}, ']'},
- {{'ShaDaMsgpackArrayBraces'}, ']'},
+ { { 'ShaDaEntryRawMsgpack' }, ' = ' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackMapBraces' }, '{' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackString' }, '=' },
+ {
+ {
+ 'ShaDaMsgpackArray',
+ 'ShaDaMsgpackMap',
+ 'ShaDaMsgpackBinaryString',
+ 'ShaDaMsgpackStringQuotes',
+ },
+ '"',
+ },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'a' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, '+(' },
+ {
+ {
+ 'ShaDaMsgpackArray',
+ 'ShaDaMsgpackMap',
+ 'ShaDaMsgpackExt',
+ 'ShaDaMsgpackExtType',
+ },
+ '10',
+ },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackExt' }, ')' },
+ {
+ {
+ 'ShaDaMsgpackArray',
+ 'ShaDaMsgpackMap',
+ 'ShaDaMsgpackBinaryString',
+ 'ShaDaMsgpackStringQuotes',
+ },
+ '"',
+ },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'ac' },
+ {
+ {
+ 'ShaDaMsgpackArray',
+ 'ShaDaMsgpackMap',
+ 'ShaDaMsgpackBinaryString',
+ 'ShaDaMsgpackBinaryStringEscape',
+ },
+ '\\0',
+ },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'df' },
+ {
+ {
+ 'ShaDaMsgpackArray',
+ 'ShaDaMsgpackMap',
+ 'ShaDaMsgpackBinaryString',
+ 'ShaDaMsgpackBinaryStringEscape',
+ },
+ '\\n',
+ },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'gi' },
+ {
+ {
+ 'ShaDaMsgpackArray',
+ 'ShaDaMsgpackMap',
+ 'ShaDaMsgpackBinaryString',
+ 'ShaDaMsgpackBinaryStringEscape',
+ },
+ '\\"',
+ },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackBinaryString' }, 'tt\\.' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackStringQuotes' }, '"' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackComma' }, ',' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'TRUE' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackColon' }, ':' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap' }, ' ' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMap', 'ShaDaMsgpackKeyword' }, 'FALSE' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackMapBraces' }, '}' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' },
+ { { 'ShaDaMsgpackArray' }, ' ' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, '[' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackKeyword' }, 'NIL' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackComma' }, ',' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray' }, ' ' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, '+(' },
+ {
+ {
+ 'ShaDaMsgpackArray',
+ 'ShaDaMsgpackArray',
+ 'ShaDaMsgpackExt',
+ 'ShaDaMsgpackExtType',
+ },
+ '-10',
+ },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackExt' }, ')' },
+ {
+ {
+ 'ShaDaMsgpackArray',
+ 'ShaDaMsgpackArray',
+ 'ShaDaMsgpackBinaryString',
+ 'ShaDaMsgpackStringQuotes',
+ },
+ '"',
+ },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArray', 'ShaDaMsgpackStringQuotes' }, '"' },
+ { { 'ShaDaMsgpackArray', 'ShaDaMsgpackArrayBraces' }, ']' },
+ { { 'ShaDaMsgpackArrayBraces' }, ']' },
},
{
- hname('Buffer list'), h(' with timestamp '),
- synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'),
- synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'),
- synepoch.minute, synhtssep(':'), synepoch.second, h(':'),
+ hname('Buffer list'),
+ h(' with timestamp '),
+ synepoch.year,
+ synhtssep('-'),
+ synepoch.month,
+ synhtssep('-'),
+ synepoch.day,
+ synhtssep('T'),
+ synepoch.hour,
+ synhtssep(':'),
+ synepoch.minute,
+ synhtssep(':'),
+ synepoch.second,
+ h(':'),
},
{
mlh(' % Key Description Value'),
},
- {
- },
+ {},
{
mlh(' % Key Description Value'),
},
{
- hname('Header'), h(' with timestamp '),
- synepoch.year, synhtssep('-'), synepoch.month, synhtssep('-'),
- synepoch.day, synhtssep('T'), synepoch.hour, synhtssep(':'),
- synepoch.minute, synhtssep(':'), synepoch.second, h(':'),
+ hname('Header'),
+ h(' with timestamp '),
+ synepoch.year,
+ synhtssep('-'),
+ synepoch.month,
+ synhtssep('-'),
+ synepoch.day,
+ synhtssep('T'),
+ synepoch.hour,
+ synhtssep(':'),
+ synepoch.minute,
+ synhtssep(':'),
+ synepoch.second,
+ h(':'),
},
{
mlh(' % Key Description________ Value'),
@@ -2932,7 +3611,7 @@ describe('syntax/shada.vim', function()
mles(' + '),
mlk('se '),
mld('place cursor at end '),
- {{'ShaDaEntryMapLong', 'ShaDaMsgpackKeyword'}, 'TRUE'},
+ { { 'ShaDaEntryMapLong', 'ShaDaMsgpackKeyword' }, 'TRUE' },
},
}
eq(exp, act)
diff --git a/test/functional/plugin/tohtml_spec.lua b/test/functional/plugin/tohtml_spec.lua
new file mode 100644
index 0000000000..2ac0fe1fa3
--- /dev/null
+++ b/test/functional/plugin/tohtml_spec.lua
@@ -0,0 +1,372 @@
+local Screen = require('test.functional.ui.screen')
+local helpers = require('test.functional.helpers')(after_each)
+
+local clear = helpers.clear
+local exec = helpers.exec
+local exec_lua = helpers.exec_lua
+local eq = helpers.eq
+local fn = helpers.fn
+local api = helpers.api
+local insert = helpers.insert
+
+local function html_syntax_match()
+ local styles =
+ vim.split(api.nvim_exec2([[/<style>/+,/<\/style>/-p]], { output = true }).output, '\n')
+ local attrnames = {
+ ['font%-weight: bold'] = 'bold',
+ ['text%-decoration%-line: [^;]*underline'] = 'underline',
+ ['font%-style: italic'] = 'italic',
+ ['text%-decoration%-line: [^;]*line%-through'] = 'strikethrough',
+ }
+ local hls = {}
+ for _, style in ipairs(styles) do
+ local attr = {}
+ for match, attrname in pairs(attrnames) do
+ if style:find(match) then
+ ---@type boolean
+ attr[attrname] = true
+ end
+ end
+ if style:find('text%-decoration%-style: wavy') and attr.underline then
+ ---@type boolean
+ attr.underline = nil
+ attr.undercurl = true
+ end
+ attr.bg = style:match('background%-color: #(%x+)')
+ if attr.bg then
+ attr.bg = tonumber(attr.bg, 16)
+ end
+ attr.fg = style:match('[^%-]color: #(%x+)')
+ if attr.fg then
+ attr.fg = tonumber(attr.fg, 16)
+ end
+ if style:match('^%.(%w+)') then
+ ---@type table
+ hls[style:match('^%.(%w+)')] = attr
+ end
+ end
+ local whitelist = {
+ 'fg',
+ 'bg',
+ --'sp',
+ --'blend',
+ 'bold',
+ --'standout',
+ 'underline',
+ 'undercurl',
+ --'underdouble',
+ --'underdotted',
+ --'underdashed',
+ 'strikethrough',
+ 'italic',
+ --'reverse',
+ --'nocombine',
+ }
+ for name, attrs_old in
+ pairs(api.nvim_get_hl(0, { link = true }) --[[@as table<string,table>]])
+ do
+ ---@type table
+ local other = hls[name:gsub('%.', '-'):gsub('@', '-')]
+ if other then
+ local attrs = {}
+ for _, attrname in ipairs(whitelist) do
+ ---@type table
+ attrs[attrname] = attrs_old[attrname]
+ end
+ eq(attrs, other)
+ end
+ end
+ return hls
+end
+
+local function html_to_extmarks()
+ local buf = api.nvim_get_current_buf()
+ local ns = api.nvim_create_namespace 'test-namespace'
+ api.nvim_buf_clear_namespace(buf, ns, 0, -1)
+ exec 'silent! norm! ggd/^<pre>$\rddG3dk'
+ local stack = {}
+ exec [[set filetype=]]
+ exec [[silent! %s/</¤/g]]
+ exec [[silent! %s/&quot;/"/g]]
+ exec [[silent! %s/&amp;/\&/g]]
+ exec [[silent! %s/&gt;/>/g]]
+ exec [[silent! %s/&lt;/</g]]
+ for _, match in
+ ipairs(
+ fn.matchbufline(buf, [[¤span class="\([^"]\+\)">\|¤/span>]], 1, '$', { submatches = true }) --[[@as (table[])]]
+ )
+ do
+ if match.text == '¤/span>' then
+ local val = table.remove(stack)
+ api.nvim_buf_set_extmark(buf, ns, val.lnum - 1, val.byteidx, {
+ hl_group = val.submatches[1],
+ end_row = match.lnum - 1,
+ end_col = match.byteidx,
+ })
+ else
+ table.insert(stack, match)
+ end
+ end
+ exec [[silent! %s/¤\/span>//g]]
+ exec [[silent! %s/¤span[^>]*>//g]]
+end
+
+---@param screen test.functional.ui.screen
+---@param func function?
+local function run_tohtml_and_assert(screen, func)
+ exec('norm! ggO-;')
+ screen:expect({ any = vim.pesc('-^;') })
+ exec('norm! :\rh')
+ screen:expect({ any = vim.pesc('^-;') })
+ local expected = screen:get_snapshot()
+ do
+ (func or exec)('TOhtml')
+ end
+ exec('only')
+ html_syntax_match()
+ html_to_extmarks()
+ exec('norm! gg0f;')
+ screen:expect({ any = vim.pesc('-^;') })
+ exec('norm! :\rh')
+ screen:expect({ grid = expected.grid, attr_ids = expected.attr_ids })
+end
+
+describe(':TOhtml', function()
+ --- @type test.functional.ui.screen
+ local screen
+ before_each(function()
+ clear({ args = { '--clean' } })
+ screen = Screen.new(80, 80)
+ screen:attach({ term_name = 'xterm' })
+ exec('colorscheme default')
+ end)
+
+ it('expected internal html generated', function()
+ insert([[line]])
+ exec('set termguicolors')
+ local bg = fn.synIDattr(fn.hlID('Normal'), 'bg#', 'gui')
+ local fg = fn.synIDattr(fn.hlID('Normal'), 'fg#', 'gui')
+ exec_lua [[
+ local outfile = vim.fn.tempname() .. '.html'
+ local html = require('tohtml').tohtml(0,{title="title",font="dumyfont"})
+ vim.fn.writefile(html, outfile)
+ vim.cmd.split(outfile)
+ ]]
+ local out_file = api.nvim_buf_get_name(api.nvim_get_current_buf())
+ eq({
+ '<!DOCTYPE html>',
+ '<html>',
+ '<head>',
+ '<meta charset="UTF-8">',
+ '<title>title</title>',
+ ('<meta name="colorscheme" content="%s"></meta>'):format(api.nvim_get_var('colors_name')),
+ '<style>',
+ '* {font-family: dumyfont,monospace}',
+ ('body {background-color: %s; color: %s}'):format(bg, fg),
+ '</style>',
+ '</head>',
+ '<body style="display: flex">',
+ '<pre>',
+ 'line',
+ '',
+ '</pre>',
+ '</body>',
+ '</html>',
+ }, fn.readfile(out_file))
+ end)
+
+ it('highlight attributes generated', function()
+ --Make sure to uncomment the attribute in `html_syntax_match()`
+ exec('hi LINE gui=' .. table.concat({
+ 'bold',
+ 'underline',
+ 'italic',
+ 'strikethrough',
+ }, ','))
+ exec('hi UNDERCURL gui=undercurl')
+ exec('syn keyword LINE line')
+ exec('syn keyword UNDERCURL undercurl')
+ insert('line\nundercurl')
+ run_tohtml_and_assert(screen)
+ end)
+
+ it('syntax', function()
+ insert [[
+ function main()
+ print("hello world")
+ end
+ ]]
+ exec('set termguicolors')
+ exec('syntax enable')
+ exec('setf lua')
+ run_tohtml_and_assert(screen)
+ end)
+
+ it('diff', function()
+ exec('set diffopt=')
+ insert [[
+ diffadd
+ nochage
+ diffchange1
+ ]]
+ exec('new')
+ insert [[
+ nochage
+ diffchange2
+ diffremove
+ ]]
+ exec('set diff')
+ exec('close')
+ exec('set diff')
+ run_tohtml_and_assert(screen)
+ end)
+
+ it('treesitter', function()
+ insert [[
+ function main()
+ print("hello world")
+ end
+ ]]
+ exec('setf lua')
+ exec_lua('vim.treesitter.start()')
+ run_tohtml_and_assert(screen)
+ end)
+
+ it('matchadd', function()
+ insert [[
+ line
+ ]]
+ fn.matchadd('Visual', 'line')
+ run_tohtml_and_assert(screen)
+ end)
+
+ describe('conceallevel', function()
+ local function run(level)
+ insert([[
+ line0
+ line1
+ line2
+ line3
+ ]])
+ local ns = api.nvim_create_namespace ''
+ fn.matchadd('Conceal', 'line1', 3, 5, { conceal = 'a' })
+ api.nvim_buf_set_extmark(0, ns, 2, 0, { conceal = 'a', end_col = 5 })
+ exec(':syntax match Conceal "line3" conceal cchar=a')
+ exec('set conceallevel=' .. level)
+ run_tohtml_and_assert(screen)
+ end
+ it('conceallevel=0', function()
+ run(0)
+ end)
+ it('conceallevel=1', function()
+ run(1)
+ end)
+ it('conceallevel=2', function()
+ run(2)
+ end)
+ it('conceallevel=3', function()
+ run(3)
+ end)
+ end)
+
+ describe('extmarks', function()
+ it('virt_text', function()
+ insert [[
+ line1
+ line2
+ line3
+ line4
+ ]]
+ local ns = api.nvim_create_namespace ''
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'foo' } } })
+ api.nvim_buf_set_extmark(
+ 0,
+ ns,
+ 1,
+ 0,
+ { virt_text = { { 'foo' } }, virt_text_pos = 'overlay' }
+ )
+ api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = { { 'foo' } }, virt_text_pos = 'inline' })
+ --api.nvim_buf_set_extmark(0,ns,3,0,{virt_text={{'foo'}},virt_text_pos='right_align'})
+ run_tohtml_and_assert(screen)
+ end)
+ it('highlight', function()
+ insert [[
+ line1
+ ]]
+ local ns = api.nvim_create_namespace ''
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 2, hl_group = 'Visual' })
+ run_tohtml_and_assert(screen)
+ end)
+ it('virt_line', function()
+ insert [[
+ line1
+ line2
+ ]]
+ local ns = api.nvim_create_namespace ''
+ api.nvim_buf_set_extmark(0, ns, 1, 0, { end_col = 2, virt_lines = { { { 'foo' } } } })
+ run_tohtml_and_assert(screen)
+ end)
+ end)
+
+ it('listchars', function()
+ exec('setlocal list')
+ exec(
+ 'setlocal listchars=eol:$,tab:<->,space:-,multispace:++,lead:_,leadmultispace:##,trail:&,nbsp:%'
+ )
+ fn.setline(1, '\tfoo\t')
+ fn.setline(2, ' foo foo ')
+ fn.setline(3, ' foo foo ')
+ fn.setline(4, 'foo\194\160 \226\128\175foo')
+ run_tohtml_and_assert(screen)
+ exec('new|only')
+ fn.setline(1, '\tfoo\t')
+ exec('setlocal list')
+ exec('setlocal listchars=tab:a-')
+ run_tohtml_and_assert(screen)
+ end)
+
+ it('folds', function()
+ insert([[
+ line1
+ line2
+ ]])
+ exec('set foldtext=foldtext()')
+ exec('%fo')
+ run_tohtml_and_assert(screen)
+ end)
+
+ it('statuscol', function()
+ local function run()
+ local buf = api.nvim_get_current_buf()
+ run_tohtml_and_assert(screen, function()
+ exec_lua [[
+ local outfile = vim.fn.tempname() .. '.html'
+ local html = require('tohtml').tohtml(0,{number_lines=true})
+ vim.fn.writefile(html, outfile)
+ vim.cmd.split(outfile)
+ ]]
+ end)
+ api.nvim_set_current_buf(buf)
+ end
+ insert([[
+ line1
+ line2
+ ]])
+ exec('setlocal relativenumber')
+ run()
+ exec('setlocal norelativenumber')
+ exec('setlocal number')
+ run()
+ exec('setlocal relativenumber')
+ run()
+ exec('setlocal signcolumn=yes:2')
+ run()
+ exec('setlocal foldcolumn=2')
+ run()
+ exec('setlocal norelativenumber')
+ run()
+ exec('setlocal signcolumn=no')
+ run()
+ end)
+end)
diff --git a/test/functional/plugin/tutor_spec.lua b/test/functional/plugin/tutor_spec.lua
index bd214e9c03..99538e1db0 100644
--- a/test/functional/plugin/tutor_spec.lua
+++ b/test/functional/plugin/tutor_spec.lua
@@ -25,7 +25,8 @@ describe(':Tutor', function()
end)
it('applies {unix:…,win:…} transform', function()
- local expected = is_os('win') and [[
+ local expected = is_os('win')
+ and [[
{0: }^ |
{0: } 3. To verify that a file was retrieved, cursor back and notice that there |
{0: } are now two copies of Lesson 5.3, the original and the retrieved version. |
@@ -56,7 +57,8 @@ describe(':Tutor', function()
{0: } 5. {2::r !dir} reads the output of the dir command and |
{0: } puts it below the cursor position. |
{0: } |
- ]] or [[
+ ]]
+ or [[
{0: }^ |
{0: } 3. To verify that a file was retrieved, cursor back and notice that there |
{0: } are now two copies of Lesson 5.3, the original and the retrieved version. |
diff --git a/test/functional/plugin/vim_syntax_spec.lua b/test/functional/plugin/vim_syntax_spec.lua
new file mode 100644
index 0000000000..9396bbce5c
--- /dev/null
+++ b/test/functional/plugin/vim_syntax_spec.lua
@@ -0,0 +1,40 @@
+local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
+local clear = helpers.clear
+local exec = helpers.exec
+local api = helpers.api
+
+describe('Vimscript syntax highlighting', function()
+ local screen
+
+ before_each(function()
+ clear()
+ helpers.add_builddir_to_rtp()
+ exec([[
+ setfiletype vim
+ syntax on
+ ]])
+ screen = Screen.new()
+ screen:set_default_attr_ids({
+ [0] = { foreground = Screen.colors.Blue, bold = true },
+ [1] = { foreground = Screen.colors.Brown, bold = true },
+ [2] = { foreground = tonumber('0x6a0dad') },
+ })
+ screen:attach()
+ end)
+
+ it('prefixed boolean options are highlighted properly', function()
+ api.nvim_buf_set_lines(0, 0, -1, true, {
+ 'set number incsearch hlsearch',
+ 'set nonumber noincsearch nohlsearch',
+ 'set invnumber invincsearch invhlsearch',
+ })
+ screen:expect([[
+ {1:^set} {2:number} {2:incsearch} {2:hlsearch} |
+ {1:set} {2:nonumber} {2:noincsearch} {2:nohlsearch} |
+ {1:set} {2:invnumber} {2:invincsearch} {2:invhlsearch} |
+ {0:~ }|*10
+ |
+ ]])
+ end)
+end)
diff --git a/test/functional/preload.lua b/test/functional/preload.lua
index 6a5a2e907e..49f1eff0da 100644
--- a/test/functional/preload.lua
+++ b/test/functional/preload.lua
@@ -3,12 +3,12 @@
-- for more information about this.
local helpers = require('test.functional.helpers')(nil)
require('test.functional.ui.screen')
-local busted = require("busted")
+local busted = require('busted')
local is_os = helpers.is_os
if is_os('win') then
local ffi = require('ffi')
- ffi.cdef[[
+ ffi.cdef [[
typedef int errno_t;
errno_t _set_fmode(int mode);
]]
@@ -17,10 +17,10 @@ end
local testid = (function()
local id = 0
- return (function()
+ return function()
id = id + 1
return id
- end)
+ end
end)()
-- Global before_each. https://github.com/Olivine-Labs/busted/issues/613
@@ -29,13 +29,11 @@ local function before_each(_element, _parent)
_G._nvim_test_id = id
return nil, true
end
-busted.subscribe({ 'test', 'start' },
- before_each,
- {
- -- Ensure our --helper is handled before --output (see busted/runner.lua).
- priority = 1,
- -- Don't generate a test-id for skipped tests. /shrug
- predicate = function (element, _, status)
- return not ((element.descriptor == 'pending' or status == 'pending'))
- end
- })
+busted.subscribe({ 'test', 'start' }, before_each, {
+ -- Ensure our --helper is handled before --output (see busted/runner.lua).
+ priority = 1,
+ -- Don't generate a test-id for skipped tests. /shrug
+ predicate = function(element, _, status)
+ return not (element.descriptor == 'pending' or status == 'pending')
+ end,
+})
diff --git a/test/functional/provider/clipboard_spec.lua b/test/functional/provider/clipboard_spec.lua
index 0099183302..0c4fd7aaa0 100644
--- a/test/functional/provider/clipboard_spec.lua
+++ b/test/functional/provider/clipboard_spec.lua
@@ -3,12 +3,13 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
-local feed_command, expect, eq, eval, source = helpers.feed_command, helpers.expect, helpers.eq, helpers.eval, helpers.source
+local feed_command, expect, eq, eval, source =
+ helpers.feed_command, helpers.expect, helpers.eq, helpers.eval, helpers.source
local command = helpers.command
-local meths = helpers.meths
+local api = helpers.api
local function basic_register_test(noblock)
- insert("some words")
+ insert('some words')
feed('^dwP')
expect('some words')
@@ -81,9 +82,9 @@ local function basic_register_test(noblock)
-- pasting in visual does unnamed delete of visual selection
feed('ggdG')
- insert("one and two and three")
+ insert('one and two and three')
feed('"ayiwbbviw"ap^viwp$viw"-p')
- expect("two and three and one")
+ expect('two and three and one')
end
describe('clipboard', function()
@@ -93,10 +94,10 @@ describe('clipboard', function()
clear()
screen = Screen.new(72, 4)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [2] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [3] = {bold = true, reverse = true};
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [2] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [3] = { bold = true, reverse = true },
})
screen:attach()
end)
@@ -112,15 +113,13 @@ describe('clipboard', function()
feed('"+yl')
screen:expect([[
^a |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
clipboard: No provider. Try ":checkhealth" or ":h clipboard". |
]])
feed('"+p')
screen:expect([[
a^a |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
clipboard: No provider. Try ":checkhealth" or ":h clipboard". |
]])
end)
@@ -132,22 +131,19 @@ describe('clipboard', function()
feed('yl')
screen:expect([[
^a |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
clipboard: No provider. Try ":checkhealth" or ":h clipboard". |
]])
feed(':<CR>')
screen:expect([[
^a |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
: |
]])
feed('p')
screen:expect([[
a^a |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
: |
]])
end)
@@ -157,8 +153,7 @@ describe('clipboard', function()
feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
clipboard: No provider. Try ":checkhealth" or ":h clipboard". |
]])
end)
@@ -166,12 +161,14 @@ describe('clipboard', function()
it('`:redir @+>|bogus_cmd|redir END` + invalid g:clipboard must not recurse #7184', function()
command("let g:clipboard = 'bogus'")
feed_command('redir @+> | bogus_cmd | redir END')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3: }|
clipboard: No provider. Try ":checkhealth" or ":h clipboard". |
{1:E492: Not an editor command: bogus_cmd | redir END} |
{2:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
it('invalid g:clipboard shows hint if :redir is not active', function()
@@ -184,15 +181,14 @@ describe('clipboard', function()
feed_command('let @+="foo"')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
clipboard: No provider. Try ":checkhealth" or ":h clipboard". |
]])
end)
it('valid g:clipboard', function()
-- provider#clipboard#Executable() only checks the structure.
- meths.set_var('clipboard', {
+ api.nvim_set_var('clipboard', {
['name'] = 'clippy!',
['copy'] = { ['+'] = 'any command', ['*'] = 'some other' },
['paste'] = { ['+'] = 'any command', ['*'] = 'some other' },
@@ -238,11 +234,11 @@ describe('clipboard', function()
eq('plus', eval("getreg('+')"))
command('call setreg("*", "star", "v")')
- eq({{'star'}, 'v'}, eval("g:dummy_clipboard_star"))
+ eq({ { 'star' }, 'v' }, eval('g:dummy_clipboard_star'))
command('call setreg("*", "star", "V")')
- eq({{'star', ''}, 'V'}, eval("g:dummy_clipboard_star"))
+ eq({ { 'star', '' }, 'V' }, eval('g:dummy_clipboard_star'))
command('call setreg("*", "star", "b")')
- eq({{'star', ''}, 'b'}, eval("g:dummy_clipboard_star"))
+ eq({ { 'star', '' }, 'b' }, eval('g:dummy_clipboard_star'))
end)
describe('g:clipboard[paste] Vimscript function', function()
@@ -310,43 +306,41 @@ describe('clipboard (with fake clipboard.vim)', function()
end)
it('`:redir @+>` invokes clipboard once-per-message', function()
- eq(0, eval("g:clip_called_set"))
+ eq(0, eval('g:clip_called_set'))
feed_command('redir @+> | :silent echo system("cat CONTRIBUTING.md") | redir END')
-- Assuming CONTRIBUTING.md has >100 lines.
- assert(eval("g:clip_called_set") > 100)
+ assert(eval('g:clip_called_set') > 100)
end)
it('`:redir @">` does NOT invoke clipboard', function()
-- :redir to a non-clipboard register, with `:set clipboard=unnamed` does
-- NOT propagate to the clipboard. This is consistent with Vim.
- command("set clipboard=unnamedplus")
- eq(0, eval("g:clip_called_set"))
+ command('set clipboard=unnamedplus')
+ eq(0, eval('g:clip_called_set'))
feed_command('redir @"> | :silent echo system("cat CONTRIBUTING.md") | redir END')
- eq(0, eval("g:clip_called_set"))
+ eq(0, eval('g:clip_called_set'))
end)
- it('`:redir @+>|bogus_cmd|redir END` must not recurse #7184',
- function()
+ it('`:redir @+>|bogus_cmd|redir END` must not recurse #7184', function()
local screen = Screen.new(72, 4)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
})
feed_command('redir @+> | bogus_cmd | redir END')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1:E492: Not an editor command: bogus_cmd | redir END} |
]])
end)
it('has independent "* and unnamed registers by default', function()
- insert("some words")
+ insert('some words')
feed('^"*dwdw"*P')
expect('some ')
- eq({{'some '}, 'v'}, eval("g:test_clip['*']"))
+ eq({ { 'some ' }, 'v' }, eval("g:test_clip['*']"))
eq('words', eval("getreg('\"', 1)"))
end)
@@ -364,31 +358,31 @@ describe('clipboard (with fake clipboard.vim)', function()
second line
first line]])
-- linewise selection should be encoded as an extra newline
- eq({{'third line', ''}, 'V'}, eval("g:test_clip['+']"))
- eq({{'second line', ''}, 'V'}, eval("g:test_clip['*']"))
+ eq({ { 'third line', '' }, 'V' }, eval("g:test_clip['+']"))
+ eq({ { 'second line', '' }, 'V' }, eval("g:test_clip['*']"))
end)
it('handles null bytes when pasting and in getreg', function()
- insert("some\022000text\n\022000very binary\022000")
+ insert('some\022000text\n\022000very binary\022000')
feed('"*y-+"*p')
- eq({{'some\ntext', '\nvery binary\n',''}, 'V'}, eval("g:test_clip['*']"))
- expect("some\00text\n\00very binary\00\nsome\00text\n\00very binary\00")
+ eq({ { 'some\ntext', '\nvery binary\n', '' }, 'V' }, eval("g:test_clip['*']"))
+ expect('some\00text\n\00very binary\00\nsome\00text\n\00very binary\00')
-- test getreg/getregtype
eq('some\ntext\n\nvery binary\n\n', eval("getreg('*', 1)"))
- eq("V", eval("getregtype('*')"))
+ eq('V', eval("getregtype('*')"))
-- getreg supports three arguments
eq('some\ntext\n\nvery binary\n\n', eval("getreg('*', 1, 0)"))
- eq({'some\ntext', '\nvery binary\n'}, eval("getreg('*', 1, 1)"))
+ eq({ 'some\ntext', '\nvery binary\n' }, eval("getreg('*', 1, 1)"))
end)
it('autodetects regtype', function()
feed_command("let g:test_clip['*'] = ['linewise stuff','']")
feed_command("let g:test_clip['+'] = ['charwise','stuff']")
- eq("V", eval("getregtype('*')"))
- eq("v", eval("getregtype('+')"))
- insert("just some text")
+ eq('V', eval("getregtype('*')"))
+ eq('v', eval("getregtype('+')"))
+ insert('just some text')
feed('"*p"+p')
expect([[
just some text
@@ -405,12 +399,12 @@ describe('clipboard (with fake clipboard.vim)', function()
expect([[
very much
blocktext]])
- eq("\0225", eval("getregtype('*')"))
+ eq('\0225', eval("getregtype('*')"))
feed('gg4l<c-v>j4l"+ygg"+P')
expect([[
muchvery much
ktextblocktext]])
- eq({{' much', 'ktext', ''}, 'b'}, eval("g:test_clip['+']"))
+ eq({ { ' much', 'ktext', '' }, 'b' }, eval("g:test_clip['+']"))
end)
it('supports setreg()', function()
@@ -434,8 +428,8 @@ describe('clipboard (with fake clipboard.vim)', function()
it('supports :let @+ (issue #1427)', function()
feed_command("let @+ = 'some'")
feed_command("let @* = ' other stuff'")
- eq({{'some'}, 'v'}, eval("g:test_clip['+']"))
- eq({{' other stuff'}, 'v'}, eval("g:test_clip['*']"))
+ eq({ { 'some' }, 'v' }, eval("g:test_clip['+']"))
+ eq({ { ' other stuff' }, 'v' }, eval("g:test_clip['*']"))
feed('"+p"*p')
expect('some other stuff')
feed_command("let @+ .= ' more'")
@@ -446,14 +440,13 @@ describe('clipboard (with fake clipboard.vim)', function()
it('pastes unnamed register if the provider fails', function()
insert('the text')
feed('yy')
- feed_command("let g:cliperror = 1")
+ feed_command('let g:cliperror = 1')
feed('"*p')
expect([[
the text
the text]])
end)
-
describe('with clipboard=unnamed', function()
-- the basic behavior of unnamed register should be the same
-- even when handled by clipboard provider
@@ -466,20 +459,20 @@ describe('clipboard (with fake clipboard.vim)', function()
end)
it('works with pure text clipboard', function()
- feed_command("let g:cliplossy = 1")
+ feed_command('let g:cliplossy = 1')
-- expect failure for block mode
basic_register_test(true)
end)
it('links the "* and unnamed registers', function()
-- with cb=unnamed, "* and unnamed will be the same register
- insert("some words")
+ insert('some words')
feed('^"*dwdw"*P')
expect('words')
- eq({{'words'}, 'v'}, eval("g:test_clip['*']"))
+ eq({ { 'words' }, 'v' }, eval("g:test_clip['*']"))
-- "+ shouldn't have changed
- eq({''}, eval("g:test_clip['+']"))
+ eq({ '' }, eval("g:test_clip['+']"))
feed_command("let g:test_clip['*'] = ['linewise stuff','']")
feed('p')
@@ -508,23 +501,23 @@ describe('clipboard (with fake clipboard.vim)', function()
end)
it('yanks visual selection when pasting', function()
- insert("indeed visual")
+ insert('indeed visual')
feed_command("let g:test_clip['*'] = [['clipboard'], 'c']")
- feed("viwp")
- eq({{'visual'}, 'v'}, eval("g:test_clip['*']"))
- expect("indeed clipboard")
+ feed('viwp')
+ eq({ { 'visual' }, 'v' }, eval("g:test_clip['*']"))
+ expect('indeed clipboard')
-- explicit "* should do the same
feed_command("let g:test_clip['*'] = [['star'], 'c']")
feed('viw"*p')
- eq({{'clipboard'}, 'v'}, eval("g:test_clip['*']"))
- expect("indeed star")
+ eq({ { 'clipboard' }, 'v' }, eval("g:test_clip['*']"))
+ expect('indeed star')
end)
it('unnamed operations work even if the provider fails', function()
insert('the text')
feed('yy')
- feed_command("let g:cliperror = 1")
+ feed_command('let g:cliperror = 1')
feed('p')
expect([[
the text
@@ -549,10 +542,10 @@ describe('clipboard (with fake clipboard.vim)', function()
it('works in the cmdline window', function()
feed('q:itext<esc>yy')
- eq({{'text', ''}, 'V'}, eval("g:test_clip['*']"))
+ eq({ { 'text', '' }, 'V' }, eval("g:test_clip['*']"))
command("let g:test_clip['*'] = [['star'], 'c']")
feed('p')
- eq('textstar', meths.get_current_line())
+ eq('textstar', api.nvim_get_current_line())
end)
it('Block paste works correctly', function()
@@ -577,13 +570,13 @@ describe('clipboard (with fake clipboard.vim)', function()
it('links the "+ and unnamed registers', function()
eq('+', eval('v:register'))
- insert("one two")
+ insert('one two')
feed('^"+dwdw"+P')
expect('two')
- eq({{'two'}, 'v'}, eval("g:test_clip['+']"))
+ eq({ { 'two' }, 'v' }, eval("g:test_clip['+']"))
-- "* shouldn't have changed
- eq({''}, eval("g:test_clip['*']"))
+ eq({ '' }, eval("g:test_clip['*']"))
feed_command("let g:test_clip['+'] = ['three']")
feed('p')
@@ -600,14 +593,14 @@ describe('clipboard (with fake clipboard.vim)', function()
text
really unnamed
really unnamed]])
- eq({{'really unnamed', ''}, 'V'}, eval("g:test_clip['+']"))
- eq({{'really unnamed', ''}, 'V'}, eval("g:test_clip['*']"))
+ eq({ { 'really unnamed', '' }, 'V' }, eval("g:test_clip['+']"))
+ eq({ { 'really unnamed', '' }, 'V' }, eval("g:test_clip['*']"))
-- unnamedplus takes precedence when pasting
eq('+', eval('v:register'))
feed_command("let g:test_clip['+'] = ['the plus','']")
feed_command("let g:test_clip['*'] = ['the star','']")
- feed("p")
+ feed('p')
expect([[
text
really unnamed
@@ -640,14 +633,14 @@ describe('clipboard (with fake clipboard.vim)', function()
end)
it('supports :put', function()
- insert("a line")
+ insert('a line')
feed_command("let g:test_clip['*'] = ['some text']")
feed_command("let g:test_clip['+'] = ['more', 'text', '']")
- feed_command(":put *")
+ feed_command(':put *')
expect([[
a line
some text]])
- feed_command(":put +")
+ feed_command(':put +')
expect([[
a line
some text
@@ -660,11 +653,11 @@ describe('clipboard (with fake clipboard.vim)', function()
screen:attach()
feed_command("let g:test_clip['*'] = ['some', 'star data','']")
feed_command("let g:test_clip['+'] = ['such', 'plus', 'stuff']")
- feed_command("registers")
- screen:expect([[
+ feed_command('registers')
+ screen:expect(
+ [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{4: }|
:registers |
{1:Type Name Content} |
@@ -672,12 +665,15 @@ describe('clipboard (with fake clipboard.vim)', function()
c "+ such{2:^J}plus{2:^J}stuff |
c ": let g:test_clip['+'] = ['such', 'plus', 'stuff'] |
{3:Press ENTER or type command to continue}^ |
- ]], {
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {bold = true, foreground = Screen.colors.Fuchsia},
- [2] = {foreground = Screen.colors.Blue},
- [3] = {bold = true, foreground = Screen.colors.SeaGreen},
- [4] = {bold = true, reverse = true}})
+ ]],
+ {
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { bold = true, foreground = Screen.colors.Fuchsia },
+ [2] = { foreground = Screen.colors.Blue },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [4] = { bold = true, reverse = true },
+ }
+ )
feed('<cr>') -- clear out of Press ENTER screen
end)
@@ -694,22 +690,28 @@ describe('clipboard (with fake clipboard.vim)', function()
feed_command("let g:test_clip['*'] = ['stuff']")
feed_command('redir @*>')
-- it is made empty
- eq({{''}, 'v'}, eval("g:test_clip['*']"))
+ eq({ { '' }, 'v' }, eval("g:test_clip['*']"))
feed_command('let g:test = doesnotexist')
feed('<cr>')
- eq({{
- '',
- '',
- 'E121: Undefined variable: doesnotexist',
- }, 'v'}, eval("g:test_clip['*']"))
+ eq(
+ { {
+ '',
+ '',
+ 'E121: Undefined variable: doesnotexist',
+ }, 'v' },
+ eval("g:test_clip['*']")
+ )
feed_command(':echo "Howdy!"')
- eq({{
- '',
- '',
- 'E121: Undefined variable: doesnotexist',
- '',
- 'Howdy!',
- }, 'v'}, eval("g:test_clip['*']"))
+ eq({
+ {
+ '',
+ '',
+ 'E121: Undefined variable: doesnotexist',
+ '',
+ 'Howdy!',
+ },
+ 'v',
+ }, eval("g:test_clip['*']"))
end)
it('handles middleclick correctly', function()
@@ -717,7 +719,7 @@ describe('clipboard (with fake clipboard.vim)', function()
local screen = Screen.new(30, 5)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
})
screen:attach()
insert([[
@@ -728,8 +730,7 @@ describe('clipboard (with fake clipboard.vim)', function()
screen:expect([[
the ^source |
a target |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -739,7 +740,7 @@ describe('clipboard (with fake clipboard.vim)', function()
the a target]])
-- on error, fall back to unnamed register
- feed_command("let g:cliperror = 1")
+ feed_command('let g:cliperror = 1')
feed('<MiddleMouse><6,1>')
expect([[
the source
@@ -762,4 +763,11 @@ describe('clipboard (with fake clipboard.vim)', function()
expect('some some')
eq('some', eval('getreg("*")'))
end)
+
+ it('does not fall back to unnamed register with getreg() #24257', function()
+ eval('setreg("", "wrong")')
+ command('let g:cliperror = 1')
+ eq('', eval('getreg("*")'))
+ eq('', eval('getreg("+")'))
+ end)
end)
diff --git a/test/functional/provider/define_spec.lua b/test/functional/provider/define_spec.lua
index 12efbec326..657f1a0d8a 100644
--- a/test/functional/provider/define_spec.lua
+++ b/test/functional/provider/define_spec.lua
@@ -1,7 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
-local eval, command, nvim = helpers.eval, helpers.command, helpers.nvim
+local eval, command = helpers.eval, helpers.command
local eq, run, stop = helpers.eq, helpers.run, helpers.stop
local clear = helpers.clear
+local api = helpers.api
local function get_prefix(sync)
if sync then
@@ -11,7 +12,7 @@ local function get_prefix(sync)
end
local function call(fn, arguments)
- command('call '..fn..'('..arguments..')')
+ command('call ' .. fn .. '(' .. arguments .. ')')
end
local function clear_and_init(init)
@@ -44,24 +45,24 @@ end
local function command_specs_for(fn, sync, first_arg_factory, init)
local prefix = get_prefix(sync)
- describe(prefix..' command created by', function()
+ describe(prefix .. ' command created by', function()
before_each(clear_and_init(init))
describe(fn, function()
local args
before_each(function()
- args = first_arg_factory()..', "test-handler", '
+ args = first_arg_factory() .. ', "test-handler", '
if sync then
args = args .. '1'
else
args = args .. '0'
end
- args = args..', "RpcCommand"'
+ args = args .. ', "RpcCommand"'
end)
it('without options', function()
- call(fn, args..', {}')
+ call(fn, args .. ', {}')
local function on_setup()
command('RpcCommand')
end
@@ -75,14 +76,14 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with nargs', function()
- call(fn, args..', {"nargs": "*"}')
+ call(fn, args .. ', {"nargs": "*"}')
local function on_setup()
command('RpcCommand arg1 arg2 arg3')
end
local function handler(method, arguments)
eq('test-handler', method)
- eq({'arg1', 'arg2', 'arg3'}, arguments[1])
+ eq({ 'arg1', 'arg2', 'arg3' }, arguments[1])
return ''
end
@@ -90,14 +91,14 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with nargs/double-quote', function()
- call(fn, args..', {"nargs": "*"}')
+ call(fn, args .. ', {"nargs": "*"}')
local function on_setup()
command('RpcCommand "arg1" "arg2" "arg3"')
end
local function handler(method, arguments)
eq('test-handler', method)
- eq({'"arg1"', '"arg2"', '"arg3"'}, arguments[1])
+ eq({ '"arg1"', '"arg2"', '"arg3"' }, arguments[1])
return ''
end
@@ -105,14 +106,14 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with range', function()
- call(fn,args..', {"range": ""}')
+ call(fn, args .. ', {"range": ""}')
local function on_setup()
command('1,1RpcCommand')
end
local function handler(method, arguments)
eq('test-handler', method)
- eq({1, 1}, arguments[1])
+ eq({ 1, 1 }, arguments[1])
return ''
end
@@ -120,15 +121,15 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with nargs/range', function()
- call(fn, args..', {"nargs": "1", "range": ""}')
+ call(fn, args .. ', {"nargs": "1", "range": ""}')
local function on_setup()
command('1,1RpcCommand arg')
end
local function handler(method, arguments)
eq('test-handler', method)
- eq({'arg'}, arguments[1])
- eq({1, 1}, arguments[2])
+ eq({ 'arg' }, arguments[1])
+ eq({ 1, 1 }, arguments[2])
return ''
end
@@ -136,14 +137,14 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with nargs/count', function()
- call(fn, args..', {"nargs": "1", "count": "5"}')
+ call(fn, args .. ', {"nargs": "1", "count": "5"}')
local function on_setup()
command('5RpcCommand arg')
end
local function handler(method, arguments)
eq('test-handler', method)
- eq({'arg'}, arguments[1])
+ eq({ 'arg' }, arguments[1])
eq(5, arguments[2])
return ''
end
@@ -152,14 +153,14 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with nargs/count/bang', function()
- call(fn, args..', {"nargs": "1", "count": "5", "bang": ""}')
+ call(fn, args .. ', {"nargs": "1", "count": "5", "bang": ""}')
local function on_setup()
command('5RpcCommand! arg')
end
local function handler(method, arguments)
eq('test-handler', method)
- eq({'arg'}, arguments[1])
+ eq({ 'arg' }, arguments[1])
eq(5, arguments[2])
eq(1, arguments[3])
return ''
@@ -169,15 +170,14 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with nargs/count/bang/register', function()
- call(fn, args..', {"nargs": "1", "count": "5", "bang": "",'..
- ' "register": ""}')
+ call(fn, args .. ', {"nargs": "1", "count": "5", "bang": "",' .. ' "register": ""}')
local function on_setup()
command('5RpcCommand! b arg')
end
local function handler(method, arguments)
eq('test-handler', method)
- eq({'arg'}, arguments[1])
+ eq({ 'arg' }, arguments[1])
eq(5, arguments[2])
eq(1, arguments[3])
eq('b', arguments[4])
@@ -188,8 +188,12 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
it('with nargs/count/bang/register/eval', function()
- call(fn, args..', {"nargs": "1", "count": "5", "bang": "",'..
- ' "register": "", "eval": "@<reg>"}')
+ call(
+ fn,
+ args
+ .. ', {"nargs": "1", "count": "5", "bang": "",'
+ .. ' "register": "", "eval": "@<reg>"}'
+ )
local function on_setup()
command('let @b = "regb"')
command('5RpcCommand! b arg')
@@ -197,7 +201,7 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
local function handler(method, arguments)
eq('test-handler', method)
- eq({'arg'}, arguments[1])
+ eq({ 'arg' }, arguments[1])
eq(5, arguments[2])
eq(1, arguments[3])
eq('b', arguments[4])
@@ -211,28 +215,27 @@ local function command_specs_for(fn, sync, first_arg_factory, init)
end)
end
-
local function autocmd_specs_for(fn, sync, first_arg_factory, init)
local prefix = get_prefix(sync)
- describe(prefix..' autocmd created by', function()
+ describe(prefix .. ' autocmd created by', function()
before_each(clear_and_init(init))
describe(fn, function()
local args
before_each(function()
- args = first_arg_factory()..', "test-handler", '
+ args = first_arg_factory() .. ', "test-handler", '
if sync then
args = args .. '1'
else
args = args .. '0'
end
- args = args..', "BufEnter"'
+ args = args .. ', "BufEnter"'
end)
it('without options', function()
- call(fn, args..', {}')
+ call(fn, args .. ', {}')
local function on_setup()
command('doautocmd BufEnter x.c')
end
@@ -246,7 +249,7 @@ local function autocmd_specs_for(fn, sync, first_arg_factory, init)
end)
it('with eval', function()
- call(fn, args..[[, {'eval': 'expand("<afile>")'}]])
+ call(fn, args .. [[, {'eval': 'expand("<afile>")'}]])
local function on_setup()
command('doautocmd BufEnter x.c')
end
@@ -263,28 +266,27 @@ local function autocmd_specs_for(fn, sync, first_arg_factory, init)
end)
end
-
local function function_specs_for(fn, sync, first_arg_factory, init)
local prefix = get_prefix(sync)
- describe(prefix..' function created by', function()
+ describe(prefix .. ' function created by', function()
before_each(clear_and_init(init))
describe(fn, function()
local args
before_each(function()
- args = first_arg_factory()..', "test-handler", '
+ args = first_arg_factory() .. ', "test-handler", '
if sync then
args = args .. '1'
else
args = args .. '0'
end
- args = args..', "TestFunction"'
+ args = args .. ', "TestFunction"'
end)
it('without options', function()
- call(fn, args..', {}')
+ call(fn, args .. ', {}')
local function on_setup()
if sync then
eq('rv', eval('TestFunction(1, "a", ["b", "c"])'))
@@ -295,7 +297,7 @@ local function function_specs_for(fn, sync, first_arg_factory, init)
local function handler(method, arguments)
eq('test-handler', method)
- eq({{1, 'a', {'b', 'c'}}}, arguments)
+ eq({ { 1, 'a', { 'b', 'c' } } }, arguments)
return 'rv'
end
@@ -303,7 +305,7 @@ local function function_specs_for(fn, sync, first_arg_factory, init)
end)
it('with eval', function()
- call(fn, args..[[, {'eval': '2 + 2'}]])
+ call(fn, args .. [[, {'eval': '2 + 2'}]])
local function on_setup()
if sync then
eq('rv', eval('TestFunction(1, "a", ["b", "c"])'))
@@ -314,7 +316,7 @@ local function function_specs_for(fn, sync, first_arg_factory, init)
local function handler(method, arguments)
eq('test-handler', method)
- eq({{1, 'a', {'b', 'c'}}, 4}, arguments)
+ eq({ { 1, 'a', { 'b', 'c' } }, 4 }, arguments)
return 'rv'
end
@@ -327,14 +329,14 @@ local function function_specs_for(fn, sync, first_arg_factory, init)
bar
baz
zub]])
- call(fn, args..[[, {'range': ''}]])
+ call(fn, args .. [[, {'range': ''}]])
local function on_setup()
command('2,3call TestFunction(1, "a", ["b", "c"])')
end
local function handler(method, arguments)
eq('test-handler', method)
- eq({{1, 'a', {'b', 'c'}}, {2, 3}}, arguments)
+ eq({ { 1, 'a', { 'b', 'c' } }, { 2, 3 } }, arguments)
return 'rv'
end
@@ -342,14 +344,14 @@ local function function_specs_for(fn, sync, first_arg_factory, init)
end)
it('with eval/range', function()
- call(fn, args..[[, {'eval': '4', 'range': ''}]])
+ call(fn, args .. [[, {'eval': '4', 'range': ''}]])
local function on_setup()
command('%call TestFunction(1, "a", ["b", "c"])')
end
local function handler(method, arguments)
eq('test-handler', method)
- eq({{1, 'a', {'b', 'c'}}, {1, 1}, 4}, arguments)
+ eq({ { 1, 'a', { 'b', 'c' } }, { 1, 1 }, 4 }, arguments)
return 'rv'
end
@@ -360,7 +362,7 @@ local function function_specs_for(fn, sync, first_arg_factory, init)
end
local function channel()
- return nvim('get_api_info')[1]
+ return api.nvim_get_chan_info(0).id
end
local function host()
@@ -368,7 +370,7 @@ local function host()
end
local function register()
- eval('remote#host#Register("busted", "busted", '..channel()..')')
+ eval('remote#host#Register("busted", "busted", ' .. channel() .. ')')
end
command_specs_for('remote#define#CommandOnChannel', true, channel)
diff --git a/test/functional/provider/nodejs_spec.lua b/test/functional/provider/nodejs_spec.lua
index 187f1c0412..1769239cb0 100644
--- a/test/functional/provider/nodejs_spec.lua
+++ b/test/functional/provider/nodejs_spec.lua
@@ -10,7 +10,10 @@ do
clear()
local reason = missing_provider('node')
if reason then
- pending(string.format("Missing nodejs host, or nodejs version is too old (%s)", reason), function() end)
+ pending(
+ string.format('Missing nodejs host, or nodejs version is too old (%s)', reason),
+ function() end
+ )
return
end
end
@@ -20,24 +23,31 @@ before_each(function()
end)
describe('nodejs host', function()
- teardown(function ()
+ teardown(function()
os.remove('Xtest-nodejs-hello.js')
os.remove('Xtest-nodejs-hello-plugin.js')
end)
it('works', function()
local fname = 'Xtest-nodejs-hello.js'
- write_file(fname, [[
+ write_file(
+ fname,
+ [[
const neovim = require('neovim');
const nvim = neovim.attach({socket: process.env.NVIM});
nvim.command('let g:job_out = "hello"');
- ]])
- command('let g:job_id = jobstart(["node", "'..fname..'"])')
- retry(nil, 3000, function() eq('hello', eval('g:job_out')) end)
+ ]]
+ )
+ command('let g:job_id = jobstart(["node", "' .. fname .. '"])')
+ retry(nil, 3000, function()
+ eq('hello', eval('g:job_out'))
+ end)
end)
it('plugin works', function()
local fname = 'Xtest-nodejs-hello-plugin.js'
- write_file(fname, [[
+ write_file(
+ fname,
+ [[
const neovim = require('neovim');
const nvim = neovim.attach({socket: process.env.NVIM});
@@ -49,8 +59,11 @@ describe('nodejs host', function()
const PluginClass = neovim.Plugin(TestPlugin);
const plugin = new neovim.NvimPlugin(null, PluginClass, nvim);
plugin.instance.hello();
- ]])
- command('let g:job_id = jobstart(["node", "'..fname..'"])')
- retry(nil, 3000, function() eq('hello-plugin', eval('g:job_out')) end)
+ ]]
+ )
+ command('let g:job_id = jobstart(["node", "' .. fname .. '"])')
+ retry(nil, 3000, function()
+ eq('hello-plugin', eval('g:job_out'))
+ end)
end)
end)
diff --git a/test/functional/provider/perl_spec.lua b/test/functional/provider/perl_spec.lua
index 8049f0f3e2..e9a031eb07 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 meths = helpers.meths
+local api = helpers.api
local insert = helpers.insert
local expect = helpers.expect
local feed = helpers.feed
@@ -14,7 +14,10 @@ do
clear()
local reason = missing_provider('perl')
if reason then
- pending(string.format("Missing perl host, or perl version is too old (%s)", reason), function() end)
+ pending(
+ string.format('Missing perl host, or perl version is too old (%s)', reason),
+ function() end
+ )
return
end
end
@@ -30,7 +33,7 @@ describe('legacy perl provider', function()
it(':perl command', function()
command('perl $vim->vars->{set_by_perl} = [100, 0];')
- eq({100, 0}, eval('g:set_by_perl'))
+ eq({ 100, 0 }, eval('g:set_by_perl'))
end)
it(':perlfile command', function()
@@ -45,7 +48,7 @@ describe('legacy perl provider', function()
-- :perldo 1; doesn't change $_,
-- the buffer should not be changed
command('normal :perldo 1;')
- eq(false, meths.get_option_value('modified', {}))
+ eq(false, api.nvim_get_option_value('modified', {}))
-- insert some text
insert('abc\ndef\nghi')
expect([[
@@ -61,19 +64,21 @@ describe('legacy perl provider', function()
end)
it('perleval()', function()
- eq({1, 2, {['key'] = 'val'}}, eval([[perleval('[1, 2, {"key" => "val"}]')]]))
+ eq({ 1, 2, { ['key'] = 'val' } }, eval([[perleval('[1, 2, {"key" => "val"}]')]]))
end)
end)
describe('perl provider', function()
- teardown(function ()
+ teardown(function()
os.remove('Xtest-perl-hello.pl')
os.remove('Xtest-perl-hello-plugin.pl')
end)
it('works', function()
local fname = 'Xtest-perl-hello.pl'
- write_file(fname, [[
+ write_file(
+ fname,
+ [[
package main;
use strict;
use warnings;
@@ -84,14 +89,19 @@ describe('perl provider', function()
my $nvim = Neovim::Ext::from_session($session);
$nvim->command('let g:job_out = "hello"');
1;
- ]])
- command('let g:job_id = jobstart(["perl", "'..fname..'"])')
- retry(nil, 3000, function() eq('hello', eval('g:job_out')) end)
+ ]]
+ )
+ command('let g:job_id = jobstart(["perl", "' .. fname .. '"])')
+ retry(nil, 3000, function()
+ eq('hello', eval('g:job_out'))
+ end)
end)
it('plugin works', function()
local fname = 'Xtest-perl-hello-plugin.pl'
- write_file(fname, [[
+ write_file(
+ fname,
+ [[
package TestPlugin;
use strict;
use warnings;
@@ -118,8 +128,11 @@ describe('perl provider', function()
my $plugin = TestPlugin->new($nvim);
$plugin->test_command();
1;
- ]])
- command('let g:job_id = jobstart(["perl", "'..fname..'"])')
- retry(nil, 3000, function() eq('hello-plugin', eval('g:job_out')) end)
+ ]]
+ )
+ command('let g:job_id = jobstart(["perl", "' .. fname .. '"])')
+ retry(nil, 3000, function()
+ eq('hello-plugin', eval('g:job_out'))
+ end)
end)
end)
diff --git a/test/functional/provider/provider_spec.lua b/test/functional/provider/provider_spec.lua
index b1c326d04c..cccd1a1184 100644
--- a/test/functional/provider/provider_spec.lua
+++ b/test/functional/provider/provider_spec.lua
@@ -1,4 +1,3 @@
-
local helpers = require('test.functional.helpers')(after_each)
local clear, eval = helpers.clear, helpers.eval
local command = helpers.command
@@ -14,14 +13,18 @@ describe('providers', function()
command('set loadplugins')
-- Using test-fixture with broken impl:
-- test/functional/fixtures/autoload/provider/python.vim
- eq('Vim:provider: python3: missing required variable g:loaded_python3_provider',
- pcall_err(eval, "has('python3')"))
+ eq(
+ 'Vim:provider: python3: missing required variable g:loaded_python3_provider',
+ pcall_err(eval, "has('python3')")
+ )
end)
it('with g:loaded_xx_provider, missing #Call()', function()
-- Using test-fixture with broken impl:
-- test/functional/fixtures/autoload/provider/ruby.vim
- eq('Vim:provider: ruby: g:loaded_ruby_provider=2 but provider#ruby#Call is not defined',
- pcall_err(eval, "has('ruby')"))
+ eq(
+ 'Vim:provider: ruby: g:loaded_ruby_provider=2 but provider#ruby#Call is not defined',
+ pcall_err(eval, "has('ruby')")
+ )
end)
end)
diff --git a/test/functional/provider/python3_spec.lua b/test/functional/provider/python3_spec.lua
index d9c44c3315..80b3552e82 100644
--- a/test/functional/provider/python3_spec.lua
+++ b/test/functional/provider/python3_spec.lua
@@ -8,19 +8,28 @@ local source = helpers.source
local missing_provider = helpers.missing_provider
local matches = helpers.matches
local pcall_err = helpers.pcall_err
-local funcs = helpers.funcs
+local fn = helpers.fn
local dedent = helpers.dedent
do
clear()
- local reason = missing_provider('python3')
+ local reason = missing_provider('python')
if reason then
it(':python3 reports E319 if provider is missing', function()
local expected = [[Vim%(py3.*%):E319: No "python3" provider found.*]]
matches(expected, pcall_err(command, 'py3 print("foo")'))
matches(expected, pcall_err(command, 'py3file foo'))
end)
- pending(string.format('Python 3 (or the pynvim module) is broken/missing (%s)', reason), function() end)
+ it('feature test when Python 3 provider is missing', function()
+ eq(0, eval('has("python3")'))
+ eq(0, eval('has("python3_compiled")'))
+ eq(0, eval('has("python3_dynamic")'))
+ eq(0, eval('has("pythonx")'))
+ end)
+ pending(
+ string.format('Python 3 (or the pynvim module) is broken/missing (%s)', reason),
+ function() end
+ )
return
end
end
@@ -35,31 +44,40 @@ describe('python3 provider', function()
eq(1, eval('has("python3")'))
eq(1, eval('has("python3_compiled")'))
eq(1, eval('has("python3_dynamic")'))
+ eq(1, eval('has("pythonx")'))
eq(0, eval('has("python3_dynamic_")'))
eq(0, eval('has("python3_")'))
end)
it('python3_execute', function()
command('python3 vim.vars["set_by_python3"] = [100, 0]')
- eq({100, 0}, eval('g:set_by_python3'))
+ eq({ 100, 0 }, eval('g:set_by_python3'))
end)
it('does not truncate error message <1 MB', function()
-- XXX: Python limits the error name to 200 chars, so this test is
-- mostly bogus.
local very_long_symbol = string.rep('a', 1200)
- feed_command(':silent! py3 print('..very_long_symbol..' b)')
+ feed_command(':silent! py3 print(' .. very_long_symbol .. ' b)')
-- Error message will contain this (last) line.
- matches(string.format(dedent([[
+ matches(
+ string.format(
+ dedent([[
^Error invoking 'python_execute' on channel 3 %%(python3%%-script%%-host%%):
File "<string>", line 1
print%%(%s b%%)
%%C*
- SyntaxError: invalid syntax%%C*$]]), very_long_symbol), eval('v:errmsg'))
+ SyntaxError: invalid syntax%%C*$]]),
+ very_long_symbol
+ ),
+ eval('v:errmsg')
+ )
end)
it('python3_execute with nested commands', function()
- command([[python3 vim.command('python3 vim.command("python3 vim.command(\'let set_by_nested_python3 = 555\')")')]])
+ command(
+ [[python3 vim.command('python3 vim.command("python3 vim.command(\'let set_by_nested_python3 = 555\')")')]]
+ )
eq(555, eval('g:set_by_nested_python3'))
end)
@@ -70,7 +88,7 @@ describe('python3 provider', function()
line3
line4]])
feed('ggjvj:python3 vim.vars["range"] = vim.current.range[:]<CR>')
- eq({'line2', 'line3'}, eval('g:range'))
+ eq({ 'line2', 'line3' }, eval('g:range'))
end)
it('py3file', function()
@@ -102,7 +120,7 @@ describe('python3 provider', function()
describe('py3eval()', function()
it('works', function()
- eq({1, 2, {['key'] = 'val'}}, funcs.py3eval('[1, 2, {"key": "val"}]'))
+ eq({ 1, 2, { ['key'] = 'val' } }, fn.py3eval('[1, 2, {"key": "val"}]'))
end)
it('errors out when given non-string', function()
@@ -131,7 +149,7 @@ describe('python3 provider', function()
command 'set pyxversion=3' -- no error
eq('Vim(set):E474: Invalid argument: pyxversion=2', pcall_err(command, 'set pyxversion=2'))
command 'set pyxversion=0' -- allowed, but equivalent to pyxversion=3
- eq(3, eval'&pyxversion')
+ eq(3, eval '&pyxversion')
end)
it('RPC call to expand("<afile>") during BufDelete #5245 #5617', function()
@@ -146,7 +164,7 @@ describe('python3 provider', function()
autocmd BufDelete * python3 foo()
autocmd BufUnload * python3 foo()]=])
feed_command("exe 'split' tempname()")
- feed_command("bwipeout!")
+ feed_command('bwipeout!')
feed_command('help help')
assert_alive()
end)
@@ -155,11 +173,11 @@ end)
describe('python2 feature test', function()
-- python2 is not supported, so correct behaviour is to return 0
it('works', function()
- eq(0, funcs.has('python2'))
- eq(0, funcs.has('python'))
- eq(0, funcs.has('python_compiled'))
- eq(0, funcs.has('python_dynamic'))
- eq(0, funcs.has('python_dynamic_'))
- eq(0, funcs.has('python_'))
+ eq(0, fn.has('python2'))
+ eq(0, fn.has('python'))
+ eq(0, fn.has('python_compiled'))
+ eq(0, fn.has('python_dynamic'))
+ eq(0, fn.has('python_dynamic_'))
+ eq(0, fn.has('python_'))
end)
end)
diff --git a/test/functional/provider/ruby_spec.lua b/test/functional/provider/ruby_spec.lua
index d3b967dfbe..9b2531a23c 100644
--- a/test/functional/provider/ruby_spec.lua
+++ b/test/functional/provider/ruby_spec.lua
@@ -8,9 +8,9 @@ local exc_exec = helpers.exc_exec
local expect = helpers.expect
local feed = helpers.feed
local feed_command = helpers.feed_command
-local funcs = helpers.funcs
+local fn = helpers.fn
local insert = helpers.insert
-local meths = helpers.meths
+local api = helpers.api
local missing_provider = helpers.missing_provider
local matches = helpers.matches
local write_file = helpers.write_file
@@ -36,19 +36,19 @@ end)
describe('ruby feature test', function()
it('works', function()
- eq(1, funcs.has('ruby'))
+ eq(1, fn.has('ruby'))
end)
end)
describe(':ruby command', function()
it('evaluates ruby', function()
command('ruby VIM.command("let g:set_by_ruby = [100, 0]")')
- eq({100, 0}, meths.get_var('set_by_ruby'))
+ eq({ 100, 0 }, api.nvim_get_var('set_by_ruby'))
end)
it('supports nesting', function()
command([[ruby VIM.command('ruby VIM.command("let set_by_nested_ruby = 555")')]])
- eq(555, meths.get_var('set_by_nested_ruby'))
+ eq(555, api.nvim_get_var('set_by_nested_ruby'))
end)
end)
@@ -57,7 +57,7 @@ describe(':rubyfile command', function()
local fname = 'rubyfile.rb'
write_file(fname, 'VIM.command("let set_by_rubyfile = 123")')
command('rubyfile rubyfile.rb')
- eq(123, meths.get_var('set_by_rubyfile'))
+ eq(123, api.nvim_get_var('set_by_rubyfile'))
os.remove(fname)
end)
end)
@@ -97,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, meths.get_option_value('modified', {}))
+ eq(false, api.nvim_get_option_value('modified', {}))
end)
end)
@@ -112,11 +112,11 @@ end)
describe('rubyeval()', function()
it('evaluates ruby objects', function()
- eq({1, 2, {['key'] = 'val'}}, funcs.rubyeval('[1, 2, {key: "val"}]'))
+ eq({ 1, 2, { ['key'] = 'val' } }, fn.rubyeval('[1, 2, {key: "val"}]'))
end)
it('returns nil for empty strings', function()
- eq(helpers.NIL, funcs.rubyeval(''))
+ eq(vim.NIL, fn.rubyeval(''))
end)
it('errors out when given non-string', function()
diff --git a/test/functional/script/luacats_grammar_spec.lua b/test/functional/script/luacats_grammar_spec.lua
new file mode 100644
index 0000000000..c3ac9fe722
--- /dev/null
+++ b/test/functional/script/luacats_grammar_spec.lua
@@ -0,0 +1,154 @@
+local helpers = require('test.functional.helpers')(after_each)
+local eq = helpers.eq
+
+local grammar = require('scripts/luacats_grammar')
+
+describe('luacats grammar', function()
+ --- @param text string
+ --- @param exp table<string,string>
+ local function test(text, exp)
+ it(string.format('can parse %q', text), function()
+ eq(exp, grammar:match(text))
+ end)
+ end
+
+ test('@param hello vim.type', {
+ kind = 'param',
+ name = 'hello',
+ type = 'vim.type',
+ })
+
+ test('@param hello vim.type this is a description', {
+ kind = 'param',
+ name = 'hello',
+ type = 'vim.type',
+ desc = 'this is a description',
+ })
+
+ test('@param hello vim.type|string this is a description', {
+ kind = 'param',
+ name = 'hello',
+ type = 'vim.type|string',
+ desc = 'this is a description',
+ })
+
+ test('@param hello vim.type?|string? this is a description', {
+ kind = 'param',
+ name = 'hello',
+ type = 'vim.type?|string?',
+ desc = 'this is a description',
+ })
+
+ test('@return string hello this is a description', {
+ kind = 'return',
+ {
+ name = 'hello',
+ type = 'string',
+ },
+ desc = 'this is a description',
+ })
+
+ test('@return fun() hello this is a description', {
+ kind = 'return',
+ {
+ name = 'hello',
+ type = 'fun()',
+ },
+ desc = 'this is a description',
+ })
+
+ test('@return fun(a: string[]): string hello this is a description', {
+ kind = 'return',
+ {
+ name = 'hello',
+ type = 'fun(a: string[]): string',
+ },
+ desc = 'this is a description',
+ })
+
+ test('@return fun(a: table<string,any>): string hello this is a description', {
+ kind = 'return',
+ {
+ name = 'hello',
+ type = 'fun(a: table<string,any>): string',
+ },
+ desc = 'this is a description',
+ })
+
+ test('@param ... string desc', {
+ kind = 'param',
+ name = '...',
+ type = 'string',
+ desc = 'desc',
+ })
+
+ test('@param level (integer|string) desc', {
+ kind = 'param',
+ name = 'level',
+ type = 'integer|string',
+ desc = 'desc',
+ })
+
+ test('@return (string command) the command and arguments', {
+ kind = 'return',
+ {
+ name = 'command',
+ type = 'string',
+ },
+ desc = 'the command and arguments',
+ })
+
+ test('@return (string command, string[] args) the command and arguments', {
+ kind = 'return',
+ {
+ name = 'command',
+ type = 'string',
+ },
+ {
+ name = 'args',
+ type = 'string[]',
+ },
+ desc = 'the command and arguments',
+ })
+
+ test('@param rfc "rfc2396" | "rfc2732" | "rfc3986" | nil', {
+ kind = 'param',
+ name = 'rfc',
+ type = '"rfc2396" | "rfc2732" | "rfc3986" | nil',
+ })
+
+ test('@param offset_encoding "utf-8" | "utf-16" | "utf-32" | nil', {
+ kind = 'param',
+ name = 'offset_encoding',
+ type = '"utf-8" | "utf-16" | "utf-32" | nil',
+ })
+
+ -- handle a : after the param type
+ test('@param a b: desc', {
+ kind = 'param',
+ name = 'a',
+ type = 'b',
+ desc = 'desc',
+ })
+
+ test(
+ '@field prefix? string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)',
+ {
+ kind = 'field',
+ name = 'prefix?',
+ type = 'string|table|(fun(diagnostic:vim.Diagnostic,i:integer,total:integer): string, string)',
+ }
+ )
+
+ test('@field [integer] integer', {
+ kind = 'field',
+ name = '[integer]',
+ type = 'integer',
+ })
+
+ test('@field [1] integer', {
+ kind = 'field',
+ name = '[1]',
+ type = 'integer',
+ })
+end)
diff --git a/test/functional/script/luacats_parser_spec.lua b/test/functional/script/luacats_parser_spec.lua
new file mode 100644
index 0000000000..e10aa81003
--- /dev/null
+++ b/test/functional/script/luacats_parser_spec.lua
@@ -0,0 +1,106 @@
+local helpers = require('test.functional.helpers')(after_each)
+local eq = helpers.eq
+
+local parser = require('scripts/luacats_parser')
+
+--- @param name string
+--- @param text string
+--- @param exp table<string,string>
+local function test(name, text, exp)
+ exp = vim.deepcopy(exp, true)
+ it(name, function()
+ eq(exp, parser.parse_str(text, 'myfile.lua'))
+ end)
+end
+
+describe('luacats parser', function()
+ local exp = {
+ myclass = {
+ kind = 'class',
+ module = 'myfile.lua',
+ name = 'myclass',
+ fields = {
+ { kind = 'field', name = 'myclass', type = 'integer' },
+ },
+ },
+ }
+
+ test(
+ 'basic class',
+ [[
+ --- @class myclass
+ --- @field myclass integer
+ ]],
+ exp
+ )
+
+ exp.myclass.inlinedoc = true
+
+ test(
+ 'class with @inlinedoc (1)',
+ [[
+ --- @class myclass
+ --- @inlinedoc
+ --- @field myclass integer
+ ]],
+ exp
+ )
+
+ test(
+ 'class with @inlinedoc (2)',
+ [[
+ --- @inlinedoc
+ --- @class myclass
+ --- @field myclass integer
+ ]],
+ exp
+ )
+
+ exp.myclass.inlinedoc = nil
+ exp.myclass.nodoc = true
+
+ test(
+ 'class with @nodoc',
+ [[
+ --- @nodoc
+ --- @class myclass
+ --- @field myclass integer
+ ]],
+ exp
+ )
+
+ exp.myclass.nodoc = nil
+ exp.myclass.access = 'private'
+
+ test(
+ 'class with (private)',
+ [[
+ --- @class (private) myclass
+ --- @field myclass integer
+ ]],
+ exp
+ )
+
+ exp.myclass.fields[1].desc = 'Field\ndocumentation'
+
+ test(
+ 'class with field doc above',
+ [[
+ --- @class (private) myclass
+ --- Field
+ --- documentation
+ --- @field myclass integer
+ ]],
+ exp
+ )
+
+ exp.myclass.fields[1].desc = 'Field documentation'
+ test(
+ 'class with field doc inline',
+ [[
+ --- @class (private) myclass
+ --- @field myclass integer Field documentation
+ ]],
+ exp
+ )
+end)
diff --git a/test/functional/script/text_utils_spec.lua b/test/functional/script/text_utils_spec.lua
new file mode 100644
index 0000000000..190c617e1d
--- /dev/null
+++ b/test/functional/script/text_utils_spec.lua
@@ -0,0 +1,60 @@
+local helpers = require('test.functional.helpers')(after_each)
+local exec_lua = helpers.exec_lua
+local eq = helpers.eq
+
+local function md_to_vimdoc(text, start_indent, indent, text_width)
+ return exec_lua(
+ [[
+ local text, start_indent, indent, text_width = ...
+ start_indent = start_indent or 0
+ indent = indent or 0
+ text_width = text_width or 70
+ local text_utils = require('scripts/text_utils')
+ return text_utils.md_to_vimdoc(table.concat(text, '\n'), start_indent, indent, text_width)
+ ]],
+ text,
+ start_indent,
+ indent,
+ text_width
+ )
+end
+
+local function test(what, act, exp, ...)
+ local argc, args = select('#', ...), { ... }
+ it(what, function()
+ eq(table.concat(exp, '\n'), md_to_vimdoc(act, unpack(args, 1, argc)))
+ end)
+end
+
+describe('md_to_vimdoc', function()
+ before_each(function()
+ helpers.clear()
+ end)
+
+ test('can render para after fenced code', {
+ '- Para1',
+ ' ```',
+ ' code',
+ ' ```',
+ ' Para2',
+ }, {
+ '• Para1 >',
+ ' code',
+ '<',
+ ' Para2',
+ '',
+ })
+
+ test('start_indent only applies to first line', {
+ 'para1',
+ '',
+ 'para2',
+ }, {
+ 'para1',
+ '',
+ ' para2',
+ '',
+ }, 0, 10, 78)
+
+ test('inline 1', { '(`string`)' }, { '(`string`)', '' })
+end)
diff --git a/test/functional/shada/buffers_spec.lua b/test/functional/shada/buffers_spec.lua
index b1c4ded541..9fead98fed 100644
--- a/test/functional/shada/buffers_spec.lua
+++ b/test/functional/shada/buffers_spec.lua
@@ -1,7 +1,6 @@
-- shada buffer list saving/reading support
local helpers = require('test.functional.helpers')(after_each)
-local nvim_command, funcs, eq, curbufmeths, meths =
- helpers.command, helpers.funcs, helpers.eq, helpers.curbufmeths, helpers.meths
+local nvim_command, fn, eq, api = helpers.command, helpers.fn, helpers.eq, helpers.api
local expect_exit = helpers.expect_exit
local shada_helpers = require('test.functional.shada.helpers')
@@ -18,10 +17,10 @@ describe('shada support code', function()
nvim_command('edit ' .. testfilename_2)
expect_exit(nvim_command, 'qall')
reset('set shada+=%')
- eq(3, funcs.bufnr('$'))
- eq('', funcs.bufname(1))
- eq(testfilename, funcs.bufname(2))
- eq(testfilename_2, funcs.bufname(3))
+ eq(3, fn.bufnr('$'))
+ eq('', fn.bufname(1))
+ eq(testfilename, fn.bufname(2))
+ eq(testfilename_2, fn.bufname(3))
end)
it('does not restore buffer list without % in &shada', function()
@@ -30,8 +29,8 @@ describe('shada support code', function()
nvim_command('edit ' .. testfilename_2)
expect_exit(nvim_command, 'qall')
reset()
- eq(1, funcs.bufnr('$'))
- eq('', funcs.bufname(1))
+ eq(1, fn.bufnr('$'))
+ eq('', fn.bufname(1))
end)
it('does not dump buffer list without % in &shada', function()
@@ -40,44 +39,44 @@ describe('shada support code', function()
nvim_command('edit ' .. testfilename_2)
expect_exit(nvim_command, 'qall')
reset('set shada+=%')
- eq(1, funcs.bufnr('$'))
- eq('', funcs.bufname(1))
+ eq(1, fn.bufnr('$'))
+ eq('', fn.bufname(1))
end)
it('does not dump unlisted buffer', function()
reset('set shada+=%')
nvim_command('edit ' .. testfilename)
nvim_command('edit ' .. testfilename_2)
- meths.set_option_value('buflisted', false, {})
+ api.nvim_set_option_value('buflisted', false, {})
expect_exit(nvim_command, 'qall')
reset('set shada+=%')
- eq(2, funcs.bufnr('$'))
- eq('', funcs.bufname(1))
- eq(testfilename, funcs.bufname(2))
+ eq(2, fn.bufnr('$'))
+ eq('', fn.bufname(1))
+ eq(testfilename, fn.bufname(2))
end)
it('does not dump quickfix buffer', function()
reset('set shada+=%')
nvim_command('edit ' .. testfilename)
nvim_command('edit ' .. testfilename_2)
- meths.set_option_value('buftype', 'quickfix', {})
+ api.nvim_set_option_value('buftype', 'quickfix', {})
expect_exit(nvim_command, 'qall')
reset('set shada+=%')
- eq(2, funcs.bufnr('$'))
- eq('', funcs.bufname(1))
- eq(testfilename, funcs.bufname(2))
+ eq(2, fn.bufnr('$'))
+ eq('', fn.bufname(1))
+ eq(testfilename, fn.bufname(2))
end)
it('does not dump unnamed buffers', function()
reset('set shada+=% hidden')
- curbufmeths.set_lines(0, 1, true, {'foo'})
+ api.nvim_buf_set_lines(0, 0, 1, true, { 'foo' })
nvim_command('enew')
- curbufmeths.set_lines(0, 1, true, {'bar'})
- eq(2, funcs.bufnr('$'))
+ api.nvim_buf_set_lines(0, 0, 1, true, { 'bar' })
+ eq(2, fn.bufnr('$'))
expect_exit(nvim_command, 'qall!')
reset('set shada+=% hidden')
- eq(1, funcs.bufnr('$'))
- eq('', funcs.bufname(1))
+ eq(1, fn.bufnr('$'))
+ eq('', fn.bufname(1))
end)
it('restores 1 buffer with %1 in &shada, #5759', function()
@@ -86,8 +85,8 @@ describe('shada support code', function()
nvim_command('edit ' .. testfilename_2)
expect_exit(nvim_command, 'qall')
reset('set shada+=%1')
- eq(2, funcs.bufnr('$'))
- eq('', funcs.bufname(1))
- eq(testfilename, funcs.bufname(2))
+ eq(2, fn.bufnr('$'))
+ eq('', fn.bufname(1))
+ eq(testfilename, fn.bufname(2))
end)
end)
diff --git a/test/functional/shada/compatibility_spec.lua b/test/functional/shada/compatibility_spec.lua
index fb656735dd..bc4e9675c6 100644
--- a/test/functional/shada/compatibility_spec.lua
+++ b/test/functional/shada/compatibility_spec.lua
@@ -1,11 +1,11 @@
-- ShaDa compatibility support
local helpers = require('test.functional.helpers')(after_each)
-local nvim_command, funcs, eq = helpers.command, helpers.funcs, helpers.eq
+local nvim_command, fn, eq = helpers.command, helpers.fn, helpers.eq
local exc_exec = helpers.exc_exec
local shada_helpers = require('test.functional.shada.helpers')
-local reset, clear, get_shada_rw = shada_helpers.reset, shada_helpers.clear,
- shada_helpers.get_shada_rw
+local reset, clear, get_shada_rw =
+ shada_helpers.reset, shada_helpers.clear, shada_helpers.get_shada_rw
local read_shada_file = shada_helpers.read_shada_file
local wshada, sdrcmd, shada_fname = get_shada_rw('Xtest-functional-shada-compatibility.shada')
@@ -49,11 +49,11 @@ describe('ShaDa forward compatibility support code', function()
end
end
eq(true, found)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada! ' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
it('works with s/search pattern item with BOOL unknown (sX) key value', function()
@@ -81,11 +81,11 @@ describe('ShaDa forward compatibility support code', function()
end
end
eq(true, found)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada!' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
it('works with replacement item with BOOL additional value in list', function()
@@ -114,22 +114,32 @@ describe('ShaDa forward compatibility support code', function()
end
end
eq(true, found)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada!' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
- for _, v in ipairs({{name='global mark', mpack='\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161nA'},
- {name='jump', mpack='\008\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\002'},
- {name='local mark', mpack='\010\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161na'},
- {name='change', mpack='\011\001\015\130\162mX\195\161f\196\006' .. mock_file_path .. 'c'},
- }) do
+ for _, v in ipairs({
+ {
+ name = 'global mark',
+ mpack = '\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161nA',
+ },
+ {
+ name = 'jump',
+ mpack = '\008\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\002',
+ },
+ {
+ name = 'local mark',
+ mpack = '\010\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161na',
+ },
+ { name = 'change', mpack = '\011\001\015\130\162mX\195\161f\196\006' .. mock_file_path .. 'c' },
+ }) do
it('works with ' .. v.name .. ' item with BOOL unknown (mX) key value', function()
nvim_command('silent noautocmd edit ' .. mock_file_path .. 'c')
- eq('' .. mock_file_path .. 'c', funcs.bufname('%'))
- funcs.setline('.', {'1', '2', '3'})
+ eq('' .. mock_file_path .. 'c', fn.bufname('%'))
+ fn.setline('.', { '1', '2', '3' })
wshada(v.mpack)
eq(0, exc_exec(sdrcmd(true)))
os.remove(shada_fname)
@@ -145,7 +155,7 @@ describe('ShaDa forward compatibility support code', function()
eq(true, found)
eq(0, exc_exec(sdrcmd()))
nvim_command('bwipeout!')
- funcs.setpos('\'A', {0, 1, 1, 0})
+ fn.setpos("'A", { 0, 1, 1, 0 })
os.remove(shada_fname)
nvim_command('wshada ' .. shada_fname)
found = false
@@ -157,21 +167,25 @@ describe('ShaDa forward compatibility support code', function()
end
end
eq(false, found)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada!' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
if v.name == 'global mark' or v.name == 'local mark' then
it('works with ' .. v.name .. ' item with <C-a> name', function()
nvim_command('silent noautocmd edit ' .. mock_file_path .. 'c')
- eq('' .. mock_file_path .. 'c', funcs.bufname('%'))
- funcs.setline('.', {'1', '2', '3'})
- wshada(v.mpack:gsub('n.$', 'n\001')
- .. v.mpack:gsub('n.$', 'n\002')
- .. v.mpack:gsub('n.$', 'n\003'):gsub('' .. mock_file_path .. 'c', '' .. mock_file_path2 .. 'f'))
+ eq('' .. mock_file_path .. 'c', fn.bufname('%'))
+ fn.setline('.', { '1', '2', '3' })
+ wshada(
+ v.mpack:gsub('n.$', 'n\001')
+ .. v.mpack:gsub('n.$', 'n\002')
+ .. v.mpack
+ :gsub('n.$', 'n\003')
+ :gsub('' .. mock_file_path .. 'c', '' .. mock_file_path2 .. 'f')
+ )
eq(0, exc_exec(sdrcmd(true)))
nvim_command('wshada ' .. shada_fname)
local found = 0
@@ -199,11 +213,11 @@ describe('ShaDa forward compatibility support code', function()
end
end
eq(0, found)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada!' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
end
end
@@ -231,11 +245,11 @@ describe('ShaDa forward compatibility support code', function()
end
end
eq(false, found)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada!' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
it('works with register item with <C-a> name', function()
@@ -267,18 +281,18 @@ describe('ShaDa forward compatibility support code', function()
end
end
eq(0, found)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada!' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
it('works with register item with type 10', function()
wshada('\005\001\019\132\161na\162rX\194\162rc\145\196\001-\162rt\010')
eq(0, exc_exec(sdrcmd(true)))
- eq({}, funcs.getreg('a', 1, 1))
- eq('', funcs.getregtype('a'))
+ eq({}, fn.getreg('a', 1, 1))
+ eq('', fn.getregtype('a'))
nvim_command('wshada ' .. shada_fname)
local found = 0
for i, v in ipairs(read_shada_file(shada_fname)) do
@@ -305,19 +319,19 @@ describe('ShaDa forward compatibility support code', function()
end
end
eq(0, found)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada!' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
it('works with buffer list item with BOOL unknown (bX) key', function()
nvim_command('set shada+=%')
wshada('\009\000\016\145\130\161f\196\006' .. mock_file_path .. 'c\162bX\195')
eq(0, exc_exec(sdrcmd()))
- eq(2, funcs.bufnr('$'))
- eq('' .. mock_file_path .. 'c', funcs.bufname(2))
+ eq(2, fn.bufnr('$'))
+ eq('' .. mock_file_path .. 'c', fn.bufname(2))
os.remove(shada_fname)
nvim_command('wshada ' .. shada_fname)
local found = false
@@ -340,11 +354,11 @@ describe('ShaDa forward compatibility support code', function()
end
eq(false, found)
nvim_command('bwipeout!')
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada!' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
it('works with history item with BOOL additional value in list', function()
@@ -363,8 +377,8 @@ describe('ShaDa forward compatibility support code', function()
eq(true, found)
eq(0, exc_exec(sdrcmd()))
os.remove(shada_fname)
- funcs.histadd(':', '--')
- funcs.histadd(':', '-')
+ fn.histadd(':', '--')
+ fn.histadd(':', '-')
nvim_command('wshada ' .. shada_fname)
found = false
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -374,11 +388,11 @@ describe('ShaDa forward compatibility support code', function()
end
end
eq(true, found)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada!' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
it('works with history item with type 10', function()
@@ -411,11 +425,11 @@ describe('ShaDa forward compatibility support code', function()
end
end
eq(0, found)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada!' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
it('works with item with 100 type', function()
@@ -448,10 +462,10 @@ describe('ShaDa forward compatibility support code', function()
end
end
eq(0, found)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
nvim_command('rshada!' .. shada_fname)
- funcs.garbagecollect(1)
- funcs.garbagecollect(1)
+ fn.garbagecollect(1)
+ fn.garbagecollect(1)
end)
end)
diff --git a/test/functional/shada/errors_spec.lua b/test/functional/shada/errors_spec.lua
index ebfd73cf85..233f03e5c0 100644
--- a/test/functional/shada/errors_spec.lua
+++ b/test/functional/shada/errors_spec.lua
@@ -1,14 +1,12 @@
-- ShaDa errors handling support
local helpers = require('test.functional.helpers')(after_each)
-local nvim_command, eq, exc_exec =
- helpers.command, helpers.eq, helpers.exc_exec
+local nvim_command, eq, exc_exec = helpers.command, helpers.eq, helpers.exc_exec
local shada_helpers = require('test.functional.shada.helpers')
local reset, clear, get_shada_rw =
shada_helpers.reset, shada_helpers.clear, shada_helpers.get_shada_rw
-local wshada, sdrcmd, shada_fname, clean =
- get_shada_rw('Xtest-functional-shada-errors.shada')
+local wshada, sdrcmd, shada_fname, clean = get_shada_rw('Xtest-functional-shada-errors.shada')
describe('ShaDa error handling', function()
before_each(reset)
@@ -29,17 +27,26 @@ describe('ShaDa error handling', function()
it('fails on zero', function()
wshada('\000')
- eq('Vim(rshada):E576: Error while reading ShaDa file: expected positive integer at position 0, but got nothing', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E576: Error while reading ShaDa file: expected positive integer at position 0, but got nothing',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on missing item', function()
wshada('\000\000\000')
- eq('Vim(rshada):E576: Error while reading ShaDa file: there is an item at position 0 that must not be there: Missing items are for internal uses only', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E576: Error while reading ShaDa file: there is an item at position 0 that must not be there: Missing items are for internal uses only',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on -2 type', function()
wshada('\254\000\000')
- eq('Vim(rshada):E576: Error while reading ShaDa file: expected positive integer at position 0', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E576: Error while reading ShaDa file: expected positive integer at position 0',
+ exc_exec(sdrcmd())
+ )
end)
it('does not fail on header with zero length', function()
@@ -50,22 +57,34 @@ describe('ShaDa error handling', function()
it('fails on search pattern item with zero length', function()
wshada('\002\000\000')
- eq('Vim(rshada):E576: Failed to parse ShaDa file: incomplete msgpack string at position 3', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E576: Failed to parse ShaDa file: incomplete msgpack string at position 3',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with -2 timestamp', function()
wshada('\002\254\000')
- eq('Vim(rshada):E576: Error while reading ShaDa file: expected positive integer at position 1', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E576: Error while reading ShaDa file: expected positive integer at position 1',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with -2 length', function()
wshada('\002\000\254')
- eq('Vim(rshada):E576: Error while reading ShaDa file: expected positive integer at position 2', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E576: Error while reading ShaDa file: expected positive integer at position 2',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with length greater then file length', function()
wshada('\002\000\002\000')
- eq('Vim(rshada):E576: Error while reading ShaDa file: last entry specified that it occupies 2 bytes, but file ended earlier', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E576: Error while reading ShaDa file: last entry specified that it occupies 2 bytes, but file ended earlier',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with invalid byte', function()
@@ -80,334 +99,523 @@ describe('ShaDa error handling', function()
-- get MSGPACK_UNPACK_PARSE_ERROR and not MSGPACK_UNPACK_CONTINUE or
-- MSGPACK_UNPACK_EXTRA_BYTES.
wshada('\002\000\001\193')
- eq('Vim(rshada):E576: Failed to parse ShaDa file due to a msgpack parser error at position 3', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E576: Failed to parse ShaDa file due to a msgpack parser error at position 3',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with incomplete map', function()
wshada('\002\000\001\129')
- eq('Vim(rshada):E576: Failed to parse ShaDa file: incomplete msgpack string at position 3', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E576: Failed to parse ShaDa file: incomplete msgpack string at position 3',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item without a pattern', function()
wshada('\002\000\005\129\162sX\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has no pattern', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has no pattern',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern with extra bytes', function()
wshada('\002\000\002\128\000')
- eq('Vim(rshada):E576: Failed to parse ShaDa file: extra bytes in msgpack string at position 3', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E576: Failed to parse ShaDa file: extra bytes in msgpack string at position 3',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with NIL value', function()
wshada('\002\000\001\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 is not a dictionary', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 is not a dictionary',
+ exc_exec(sdrcmd())
+ )
end)
-- sp entry is here because it causes an allocation.
it('fails on search pattern item with BIN key', function()
wshada('\002\000\014\131\162sp\196\001a\162sX\192\196\000\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has key which is not a string', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has key which is not a string',
+ exc_exec(sdrcmd())
+ )
end)
-- sp entry is here because it causes an allocation.
it('fails on search pattern item with empty key', function()
wshada('\002\000\013\131\162sp\196\001a\162sX\192\160\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has empty key', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has empty key',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with NIL magic key value', function()
wshada('\002\000\009\130\162sX\192\162sm\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sm key value which is not a boolean', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sm key value which is not a boolean',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with NIL smartcase key value', function()
wshada('\002\000\009\130\162sX\192\162sc\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sc key value which is not a boolean', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sc key value which is not a boolean',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with NIL search_backward key value', function()
wshada('\002\000\009\130\162sX\192\162sb\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sb key value which is not a boolean', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sb key value which is not a boolean',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with NIL has_line_offset key value', function()
wshada('\002\000\009\130\162sX\192\162sl\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sl key value which is not a boolean', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sl key value which is not a boolean',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with NIL place_cursor_at_end key value', function()
wshada('\002\000\009\130\162sX\192\162se\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has se key value which is not a boolean', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has se key value which is not a boolean',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with NIL is_last_used key value', function()
wshada('\002\000\009\130\162sX\192\162su\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has su key value which is not a boolean', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has su key value which is not a boolean',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with NIL is_substitute_pattern key value', function()
wshada('\002\000\009\130\162sX\192\162ss\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has ss key value which is not a boolean', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has ss key value which is not a boolean',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with NIL highlighted key value', function()
wshada('\002\000\009\130\162sX\192\162sh\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sh key value which is not a boolean', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sh key value which is not a boolean',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with NIL offset key value', function()
wshada('\002\000\009\130\162sX\192\162so\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has so key value which is not an integer', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has so key value which is not an integer',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with NIL pat key value', function()
wshada('\002\000\009\130\162sX\192\162sp\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sp key value which is not a binary', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sp key value which is not a binary',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search pattern item with STR pat key value', function()
wshada('\002\000\011\130\162sX\192\162sp\162sp')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sp key value which is not a binary', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search pattern entry at position 0 has sp key value which is not a binary',
+ exc_exec(sdrcmd())
+ )
end)
- for _, v in ipairs({{name='global mark', mpack='\007'},
- {name='jump', mpack='\008'},
- {name='local mark', mpack='\010'},
- {name='change', mpack='\011'},
- }) do
- local is_mark_test = ({['global mark']=true, ['local mark']=true})[v.name]
+ for _, v in ipairs({
+ { name = 'global mark', mpack = '\007' },
+ { name = 'jump', mpack = '\008' },
+ { name = 'local mark', mpack = '\010' },
+ { name = 'change', mpack = '\011' },
+ }) do
+ local is_mark_test = ({ ['global mark'] = true, ['local mark'] = true })[v.name]
it('fails on ' .. v.name .. ' item with NIL value', function()
wshada(v.mpack .. '\000\001\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 is not a dictionary', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 is not a dictionary',
+ exc_exec(sdrcmd())
+ )
end)
-- f entry is here because it causes an allocation.
it('fails on ' .. v.name .. ' item with BIN key', function()
wshada(v.mpack .. '\000\013\131\161f\196\001/\162mX\192\196\000\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has key which is not a string', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has key which is not a string',
+ exc_exec(sdrcmd())
+ )
end)
-- f entry is here because it causes an allocation.
it('fails on ' .. v.name .. ' item with empty key', function()
wshada(v.mpack .. '\000\012\131\161f\196\001/\162mX\192\160\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has empty key', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has empty key',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on ' .. v.name .. ' item without f key', function()
wshada(v.mpack .. '\000\008\130\162mX\192\161l\001')
- eq('Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 is missing file name', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 is missing file name',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on ' .. v.name .. ' item with zero l key', function()
wshada(v.mpack .. '\000\013\131\162mX\192\161f\196\001/\161l\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has invalid line number', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has invalid line number',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on ' .. v.name .. ' item with negative l key', function()
wshada(v.mpack .. '\000\013\131\162mX\192\161f\196\001/\161l\255')
- eq('Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has invalid line number', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has invalid line number',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on ' .. v.name .. ' item with negative c key', function()
wshada(v.mpack .. '\000\013\131\162mX\192\161f\196\001/\161c\255')
- eq('Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has invalid column number', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has invalid column number',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on ' .. v.name .. ' item with STR n key value', function()
wshada(v.mpack .. '\000\011\130\162mX\192\161n\163spa')
- eq(is_mark_test and 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has n key value which is not an unsigned integer' or 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has n key which is only valid for local and global mark entries', exc_exec(sdrcmd()))
+ eq(
+ is_mark_test
+ and 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has n key value which is not an unsigned integer'
+ or 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has n key which is only valid for local and global mark entries',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on ' .. v.name .. ' item with STR l key value', function()
wshada(v.mpack .. '\000\010\130\162mX\192\161l\162sp')
- eq('Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has l key value which is not an integer', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has l key value which is not an integer',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on ' .. v.name .. ' item with STR c key value', function()
wshada(v.mpack .. '\000\010\130\162mX\192\161c\162sp')
- eq('Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has c key value which is not an integer', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has c key value which is not an integer',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on ' .. v.name .. ' item with STR f key value', function()
wshada(v.mpack .. '\000\010\130\162mX\192\161f\162sp')
- eq('Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has f key value which is not a binary', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: mark entry at position 0 has f key value which is not a binary',
+ exc_exec(sdrcmd())
+ )
end)
end
it('fails on register item with NIL value', function()
wshada('\005\000\001\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 is not a dictionary', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 is not a dictionary',
+ exc_exec(sdrcmd())
+ )
end)
-- rc entry is here because it causes an allocation
it('fails on register item with BIN key', function()
wshada('\005\000\015\131\162rc\145\196\001a\162rX\192\196\000\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has key which is not a string', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has key which is not a string',
+ exc_exec(sdrcmd())
+ )
end)
-- rc entry is here because it causes an allocation
it('fails on register item with BIN key', function()
wshada('\005\000\014\131\162rc\145\196\001a\162rX\192\160\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has empty key', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has empty key',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on register item with NIL rt key value', function()
wshada('\005\000\009\130\162rX\192\162rt\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has rt key value which is not an unsigned integer', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has rt key value which is not an unsigned integer',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on register item with NIL rw key value', function()
wshada('\005\000\009\130\162rX\192\162rw\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has rw key value which is not an unsigned integer', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has rw key value which is not an unsigned integer',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on register item with NIL rc key value', function()
wshada('\005\000\009\130\162rX\192\162rc\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has rc key with non-array value', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has rc key with non-array value',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on register item with empty rc key value', function()
wshada('\005\000\009\130\162rX\192\162rc\144')
- eq('Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has rc key with empty array', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has rc key with empty array',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on register item with NIL in rc array', function()
wshada('\005\000\013\130\162rX\192\162rc\146\196\001a\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has rc array with non-binary value', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has rc array with non-binary value',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on register item without rc array', function()
wshada('\005\000\009\129\162rX\146\196\001a\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has missing rc array', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: register entry at position 0 has missing rc array',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on history item with NIL value', function()
wshada('\004\000\001\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 is not an array', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 is not an array',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on history item with empty value', function()
wshada('\004\000\001\144')
- eq('Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 does not have enough elements', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 does not have enough elements',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on history item with single element value', function()
wshada('\004\000\002\145\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 does not have enough elements', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 does not have enough elements',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on history item with NIL first item', function()
wshada('\004\000\003\146\192\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 has wrong history type type', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 has wrong history type type',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on history item with FIXUINT second item', function()
wshada('\004\000\003\146\000\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 has wrong history string type', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 has wrong history string type',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on history item with second item with zero byte', function()
wshada('\004\000\007\146\000\196\003ab\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 contains string with zero byte inside', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: history entry at position 0 contains string with zero byte inside',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search history item without third item', function()
wshada('\004\000\007\146\001\196\003abc')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search history entry at position 0 does not have separator character', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search history entry at position 0 does not have separator character',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on search history item with NIL third item', function()
wshada('\004\000\007\147\001\196\002ab\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: search history entry at position 0 has wrong history separator type', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: search history entry at position 0 has wrong history separator type',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on variable item with NIL value', function()
wshada('\006\000\001\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 is not an array', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 is not an array',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on variable item with empty value', function()
wshada('\006\000\001\144')
- eq('Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 does not have enough elements', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 does not have enough elements',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on variable item with single element value', function()
wshada('\006\000\002\145\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 does not have enough elements', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 does not have enough elements',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on variable item with NIL first item', function()
wshada('\006\000\003\146\192\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 has wrong variable name type', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 has wrong variable name type',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on variable item with BIN value and type value != VAR_TYPE_BLOB', function()
wshada('\006\000\007\147\196\001\065\196\000\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 has wrong variable type', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: variable entry at position 0 has wrong variable type',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on replacement item with NIL value', function()
wshada('\003\000\001\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: sub string entry at position 0 is not an array', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: sub string entry at position 0 is not an array',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on replacement item with empty value', function()
wshada('\003\000\001\144')
- eq('Vim(rshada):E575: Error while reading ShaDa file: sub string entry at position 0 does not have enough elements', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: sub string entry at position 0 does not have enough elements',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on replacement item with NIL first item', function()
wshada('\003\000\002\145\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: sub string entry at position 0 has wrong sub string type', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: sub string entry at position 0 has wrong sub string type',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on buffer list item with NIL value', function()
nvim_command('set shada+=%')
wshada('\009\000\001\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: buffer list entry at position 0 is not an array', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: buffer list entry at position 0 is not an array',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on buffer list item with NIL item in the array', function()
nvim_command('set shada+=%')
wshada('\009\000\008\146\129\161f\196\001/\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: buffer list at position 0 contains entry that is not a dictionary', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: buffer list at position 0 contains entry that is not a dictionary',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on buffer list item with empty item', function()
nvim_command('set shada+=%')
wshada('\009\000\008\146\129\161f\196\001/\128')
- eq('Vim(rshada):E575: Error while reading ShaDa file: buffer list at position 0 contains entry that does not have a file name', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: buffer list at position 0 contains entry that does not have a file name',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on buffer list item with NIL l key', function()
nvim_command('set shada+=%')
wshada('\009\000\017\146\129\161f\196\001/\130\161f\196\002/a\161l\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: buffer list entry entry at position 0 has l key value which is not an integer', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: buffer list entry entry at position 0 has l key value which is not an integer',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on buffer list item with zero l key', function()
nvim_command('set shada+=%')
wshada('\009\000\017\146\129\161f\196\001/\130\161f\196\002/a\161l\000')
- eq('Vim(rshada):E575: Error while reading ShaDa file: buffer list at position 0 contains entry with invalid line number', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: buffer list at position 0 contains entry with invalid line number',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on buffer list item with negative l key', function()
nvim_command('set shada+=%')
wshada('\009\000\017\146\129\161f\196\001/\130\161f\196\002/a\161l\255')
- eq('Vim(rshada):E575: Error while reading ShaDa file: buffer list at position 0 contains entry with invalid line number', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: buffer list at position 0 contains entry with invalid line number',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on buffer list item with negative c key', function()
nvim_command('set shada+=%')
wshada('\009\000\017\146\129\161f\196\001/\130\161f\196\002/a\161c\255')
- eq('Vim(rshada):E575: Error while reading ShaDa file: buffer list at position 0 contains entry with invalid column number', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: buffer list at position 0 contains entry with invalid column number',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on buffer list item with NIL c key', function()
nvim_command('set shada+=%')
wshada('\009\000\017\146\129\161f\196\001/\130\161f\196\002/a\161c\192')
- eq('Vim(rshada):E575: Error while reading ShaDa file: buffer list entry entry at position 0 has c key value which is not an integer', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E575: Error while reading ShaDa file: buffer list entry entry at position 0 has c key value which is not an integer',
+ exc_exec(sdrcmd())
+ )
end)
it('fails on invalid ShaDa file (viminfo file)', function()
@@ -480,40 +688,229 @@ $
+ 65 0
+ 65 0
]])
- eq('Vim(rshada):E576: Failed to parse ShaDa file: extra bytes in msgpack string at position 3', exc_exec(sdrcmd()))
- eq('Vim(wshada):E576: Failed to parse ShaDa file: extra bytes in msgpack string at position 3', exc_exec('wshada ' .. shada_fname))
+ eq(
+ 'Vim(rshada):E576: Failed to parse ShaDa file: extra bytes in msgpack string at position 3',
+ exc_exec(sdrcmd())
+ )
+ eq(
+ 'Vim(wshada):E576: Failed to parse ShaDa file: extra bytes in msgpack string at position 3',
+ exc_exec('wshada ' .. shada_fname)
+ )
eq(0, exc_exec('wshada! ' .. shada_fname))
end)
it('fails on invalid ShaDa file (wrapper script)', function()
wshada('#!/bin/sh\n\npowerline "$@" 2>&1 | tee -a powerline\n')
- eq('Vim(rshada):E576: Failed to parse ShaDa file: extra bytes in msgpack string at position 3', exc_exec(sdrcmd()))
- eq('Vim(wshada):E576: Failed to parse ShaDa file: extra bytes in msgpack string at position 3', exc_exec('wshada ' .. shada_fname))
+ eq(
+ 'Vim(rshada):E576: Failed to parse ShaDa file: extra bytes in msgpack string at position 3',
+ exc_exec(sdrcmd())
+ )
+ eq(
+ 'Vim(wshada):E576: Failed to parse ShaDa file: extra bytes in msgpack string at position 3',
+ exc_exec('wshada ' .. shada_fname)
+ )
eq(0, exc_exec('wshada! ' .. shada_fname))
end)
it('fails on invalid ShaDa file (failing skip in second item)', function()
wshada('\001\000\001\128#!/')
- eq('Vim(rshada):E576: Error while reading ShaDa file: last entry specified that it occupies 47 bytes, but file ended earlier', exc_exec(sdrcmd()))
- eq('Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 47 bytes, but file ended earlier', exc_exec('wshada ' .. shada_fname))
+ eq(
+ 'Vim(rshada):E576: Error while reading ShaDa file: last entry specified that it occupies 47 bytes, but file ended earlier',
+ exc_exec(sdrcmd())
+ )
+ eq(
+ 'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 47 bytes, but file ended earlier',
+ exc_exec('wshada ' .. shada_fname)
+ )
eq(0, exc_exec('wshada! ' .. shada_fname))
end)
it('errors with too large items', function()
wshada({
- 1, 206, 70, 90, 31, 179, 86, 133, 169, 103, 101, 110, 101, 114, 97,
- 116, 111, 114, 196, 4, 145, 145, 145, 145, 145, 145, 96, 96, 96, 96,
- 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96, 96,
- 96, 96, 145, 145, 145, 145, 111, 110, 196, 25, 78, 86, 73, 77, 32,
- 118, 1, 46, 50, 46, 48, 45, 51, 48, 51, 45, 103, 98, 54, 55,
- 52, 102, 100, 50, 99, 169, 109, 97, 120, 95, 107, 98, 121, 116, 101,
- 10, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207, 207,
- 207, 207, 207, 207, 207, 207, 207, 207, 16, 8, 206, 89, 90, 30, 253,
- 35, 129, 161, 102, 196, 30, 47, 100, 101, 118, 47, 115, 104, 109, 47,
- 102, 117, 122, 122, 105, 110, 103, 45, 110, 118, 105, 109, 45, 115, 104,
- 97, 100, 97, 47, 108, 115, 2, 206, 89, 90, 30, 251, 13, 130, 162,
- 115, 112, 196, 3, 102, 111, 111, 162, 115, 99, 195, 3, 146, 10, 0,
+ 1,
+ 206,
+ 70,
+ 90,
+ 31,
+ 179,
+ 86,
+ 133,
+ 169,
+ 103,
+ 101,
+ 110,
+ 101,
+ 114,
+ 97,
+ 116,
+ 111,
+ 114,
+ 196,
+ 4,
+ 145,
+ 145,
+ 145,
+ 145,
+ 145,
+ 145,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 96,
+ 145,
+ 145,
+ 145,
+ 145,
+ 111,
+ 110,
+ 196,
+ 25,
+ 78,
+ 86,
+ 73,
+ 77,
+ 32,
+ 118,
+ 1,
+ 46,
+ 50,
+ 46,
+ 48,
+ 45,
+ 51,
+ 48,
+ 51,
+ 45,
+ 103,
+ 98,
+ 54,
+ 55,
+ 52,
+ 102,
+ 100,
+ 50,
+ 99,
+ 169,
+ 109,
+ 97,
+ 120,
+ 95,
+ 107,
+ 98,
+ 121,
+ 116,
+ 101,
+ 10,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 207,
+ 16,
+ 8,
+ 206,
+ 89,
+ 90,
+ 30,
+ 253,
+ 35,
+ 129,
+ 161,
+ 102,
+ 196,
+ 30,
+ 47,
+ 100,
+ 101,
+ 118,
+ 47,
+ 115,
+ 104,
+ 109,
+ 47,
+ 102,
+ 117,
+ 122,
+ 122,
+ 105,
+ 110,
+ 103,
+ 45,
+ 110,
+ 118,
+ 105,
+ 109,
+ 45,
+ 115,
+ 104,
+ 97,
+ 100,
+ 97,
+ 47,
+ 108,
+ 115,
+ 2,
+ 206,
+ 89,
+ 90,
+ 30,
+ 251,
+ 13,
+ 130,
+ 162,
+ 115,
+ 112,
+ 196,
+ 3,
+ 102,
+ 111,
+ 111,
+ 162,
+ 115,
+ 99,
+ 195,
+ 3,
+ 146,
+ 10,
+ 0,
})
- eq('Vim(rshada):E576: Error while reading ShaDa file: there is an item at position 93 that is stated to be too long', exc_exec(sdrcmd()))
+ eq(
+ 'Vim(rshada):E576: Error while reading ShaDa file: there is an item at position 93 that is stated to be too long',
+ exc_exec(sdrcmd())
+ )
end)
end)
diff --git a/test/functional/shada/helpers.lua b/test/functional/shada/helpers.lua
index cd99d38345..baa27889f3 100644
--- a/test/functional/shada/helpers.lua
+++ b/test/functional/shada/helpers.lua
@@ -1,10 +1,8 @@
local helpers = require('test.functional.helpers')(nil)
-local meths = helpers.meths
+local api = helpers.api
local write_file = helpers.write_file
local concat_tables = helpers.concat_tables
-local mpack = require('mpack')
-
local tmpname = helpers.tmpname()
-- o={
@@ -17,19 +15,20 @@ local function reset(o)
o = o and o or {}
local args_rm = o.args_rm or {}
table.insert(args_rm, '-i')
- local args={
- '-i', o.shadafile or tmpname,
+ local args = {
+ '-i',
+ o.shadafile or tmpname,
}
if type(o) == 'string' then
- args = concat_tables(args, {'--cmd', o})
+ args = concat_tables(args, { '--cmd', o })
elseif o.args then
args = concat_tables(args, o.args)
end
- helpers.clear{
- args_rm=args_rm,
- args=args,
+ helpers.clear {
+ args_rm = args_rm,
+ args = args,
}
- meths.set_var('tmpname', tmpname)
+ api.nvim_set_var('tmpname', tmpname)
end
local clear = function()
@@ -57,13 +56,13 @@ local get_shada_rw = function(fname)
return wshada, sdrcmd, fname, clean
end
-local mpack_keys = {'type', 'timestamp', 'length', 'value'}
+local mpack_keys = { 'type', 'timestamp', 'length', 'value' }
local read_shada_file = function(fname)
local fd = io.open(fname, 'r')
local mstring = fd:read('*a')
fd:close()
- local unpack = mpack.Unpacker()
+ local unpack = vim.mpack.Unpacker()
local ret = {}
local cur, val
local i = 0
@@ -81,8 +80,8 @@ local read_shada_file = function(fname)
end
return {
- reset=reset,
- clear=clear,
- get_shada_rw=get_shada_rw,
- read_shada_file=read_shada_file,
+ reset = reset,
+ clear = clear,
+ get_shada_rw = get_shada_rw,
+ read_shada_file = read_shada_file,
}
diff --git a/test/functional/shada/history_spec.lua b/test/functional/shada/history_spec.lua
index 433db3171e..c8a19bb082 100644
--- a/test/functional/shada/history_spec.lua
+++ b/test/functional/shada/history_spec.lua
@@ -1,7 +1,7 @@
-- ShaDa history saving/reading support
local helpers = require('test.functional.helpers')(after_each)
-local nvim_command, funcs, meths, nvim_feed, eq =
- helpers.command, helpers.funcs, helpers.meths, helpers.feed, helpers.eq
+local nvim_command, fn, api, nvim_feed, eq =
+ helpers.command, helpers.fn, helpers.api, helpers.feed, helpers.eq
local assert_alive = helpers.assert_alive
local expect_exit = helpers.expect_exit
@@ -13,134 +13,131 @@ describe('ShaDa support code', function()
after_each(clear)
it('is able to dump and read back command-line history', function()
- nvim_command('set shada=\'0')
+ nvim_command("set shada='0")
nvim_feed(':" Test\n')
nvim_command('wshada')
reset()
- nvim_command('set shada=\'0')
+ nvim_command("set shada='0")
nvim_command('rshada')
- eq('" Test', funcs.histget(':', -1))
+ eq('" Test', fn.histget(':', -1))
end)
it('is able to dump and read back 2 items in command-line history', function()
- nvim_command('set shada=\'0 history=2')
+ nvim_command("set shada='0 history=2")
nvim_feed(':" Test\n')
nvim_feed(':" Test 2\n')
expect_exit(nvim_command, 'qall')
reset()
- nvim_command('set shada=\'0 history=2')
+ nvim_command("set shada='0 history=2")
nvim_command('rshada')
- eq('" Test 2', funcs.histget(':', -1))
- eq('" Test', funcs.histget(':', -2))
+ eq('" Test 2', fn.histget(':', -1))
+ eq('" Test', fn.histget(':', -2))
end)
- it('respects &history when dumping',
- function()
- nvim_command('set shada=\'0 history=1')
+ it('respects &history when dumping', function()
+ nvim_command("set shada='0 history=1")
nvim_feed(':" Test\n')
nvim_feed(':" Test 2\n')
nvim_command('wshada')
reset()
- nvim_command('set shada=\'0 history=2')
+ nvim_command("set shada='0 history=2")
nvim_command('rshada')
- eq('" Test 2', funcs.histget(':', -1))
- eq('', funcs.histget(':', -2))
+ eq('" Test 2', fn.histget(':', -1))
+ eq('', fn.histget(':', -2))
end)
- it('respects &history when loading',
- function()
- nvim_command('set shada=\'0 history=2')
+ it('respects &history when loading', function()
+ nvim_command("set shada='0 history=2")
nvim_feed(':" Test\n')
nvim_feed(':" Test 2\n')
nvim_command('wshada')
reset()
- nvim_command('set shada=\'0 history=1')
+ nvim_command("set shada='0 history=1")
nvim_command('rshada')
- eq('" Test 2', funcs.histget(':', -1))
- eq('', funcs.histget(':', -2))
+ eq('" Test 2', fn.histget(':', -1))
+ eq('', fn.histget(':', -2))
end)
it('dumps only requested amount of command-line history items', function()
- nvim_command('set shada=\'0,:1')
+ nvim_command("set shada='0,:1")
nvim_feed(':" Test\n')
nvim_feed(':" Test 2\n')
nvim_command('wshada')
-- Regression test: :wshada should not alter or free history.
- eq('" Test 2', funcs.histget(':', -1))
- eq('" Test', funcs.histget(':', -2))
+ eq('" Test 2', fn.histget(':', -1))
+ eq('" Test', fn.histget(':', -2))
reset()
- nvim_command('set shada=\'0')
+ nvim_command("set shada='0")
nvim_command('rshada')
- eq('" Test 2', funcs.histget(':', -1))
- eq('', funcs.histget(':', -2))
+ eq('" Test 2', fn.histget(':', -1))
+ eq('', fn.histget(':', -2))
end)
it('does not respect number in &shada when loading history', function()
- nvim_command('set shada=\'0')
+ nvim_command("set shada='0")
nvim_feed(':" Test\n')
nvim_feed(':" Test 2\n')
nvim_command('wshada')
reset()
- nvim_command('set shada=\'0,:1')
+ nvim_command("set shada='0,:1")
nvim_command('rshada')
- eq('" Test 2', funcs.histget(':', -1))
- eq('" Test', funcs.histget(':', -2))
+ eq('" Test 2', fn.histget(':', -1))
+ eq('" Test', fn.histget(':', -2))
end)
it('dumps and loads all kinds of histories', function()
nvim_command('debuggreedy')
- nvim_feed(':debug echo "Test"\n" Test 2\nc\n') -- Debug history.
- nvim_feed(':call input("")\nTest 2\n') -- Input history.
- nvim_feed('"="Test"\nyy') -- Expression history.
- nvim_feed('/Test\n') -- Search history
- nvim_feed(':" Test\n') -- Command-line history
+ nvim_feed(':debug echo "Test"\n" Test 2\nc\n') -- Debug history.
+ nvim_feed(':call input("")\nTest 2\n') -- Input history.
+ nvim_feed('"="Test"\nyy') -- Expression history.
+ nvim_feed('/Test\n') -- Search history
+ nvim_feed(':" Test\n') -- Command-line history
nvim_command('0debuggreedy')
nvim_command('wshada')
reset()
nvim_command('rshada')
- eq('" Test', funcs.histget(':', -1))
- eq('Test', funcs.histget('/', -1))
- eq('"Test"', funcs.histget('=', -1))
- eq('Test 2', funcs.histget('@', -1))
- eq('c', funcs.histget('>', -1))
+ eq('" Test', fn.histget(':', -1))
+ eq('Test', fn.histget('/', -1))
+ eq('"Test"', fn.histget('=', -1))
+ eq('Test 2', fn.histget('@', -1))
+ eq('c', fn.histget('>', -1))
end)
it('dumps and loads last search pattern with offset', function()
- meths.set_option_value('wrapscan', false, {})
- funcs.setline('.', {'foo', 'bar--'})
+ api.nvim_set_option_value('wrapscan', false, {})
+ fn.setline('.', { 'foo', 'bar--' })
nvim_feed('gg0/a/e+1\n')
- eq({0, 2, 3, 0}, funcs.getpos('.'))
+ eq({ 0, 2, 3, 0 }, fn.getpos('.'))
nvim_command('wshada')
reset()
- meths.set_option_value('wrapscan', false, {})
- funcs.setline('.', {'foo', 'bar--'})
+ api.nvim_set_option_value('wrapscan', false, {})
+ fn.setline('.', { 'foo', 'bar--' })
nvim_feed('gg0n')
- eq({0, 2, 3, 0}, funcs.getpos('.'))
- eq(1, meths.get_vvar('searchforward'))
+ eq({ 0, 2, 3, 0 }, fn.getpos('.'))
+ eq(1, api.nvim_get_vvar('searchforward'))
end)
- it('dumps and loads last search pattern with offset and backward direction',
- function()
- meths.set_option_value('wrapscan', false, {})
- funcs.setline('.', {'foo', 'bar--'})
+ it('dumps and loads last search pattern with offset and backward direction', function()
+ api.nvim_set_option_value('wrapscan', false, {})
+ fn.setline('.', { 'foo', 'bar--' })
nvim_feed('G$?a?e+1\n')
- eq({0, 2, 3, 0}, funcs.getpos('.'))
+ eq({ 0, 2, 3, 0 }, fn.getpos('.'))
nvim_command('wshada')
reset()
- meths.set_option_value('wrapscan', false, {})
- funcs.setline('.', {'foo', 'bar--'})
+ api.nvim_set_option_value('wrapscan', false, {})
+ fn.setline('.', { 'foo', 'bar--' })
nvim_feed('G$n')
- eq({0, 2, 3, 0}, funcs.getpos('.'))
- eq(0, meths.get_vvar('searchforward'))
+ eq({ 0, 2, 3, 0 }, fn.getpos('.'))
+ eq(0, api.nvim_get_vvar('searchforward'))
end)
it('saves v:hlsearch=1', function()
nvim_command('set hlsearch shada-=h')
nvim_feed('/test\n')
- eq(1, meths.get_vvar('hlsearch'))
+ eq(1, api.nvim_get_vvar('hlsearch'))
expect_exit(nvim_command, 'qall')
reset()
- eq(1, meths.get_vvar('hlsearch'))
+ eq(1, api.nvim_get_vvar('hlsearch'))
end)
it('saves v:hlsearch=0 with :nohl', function()
@@ -149,27 +146,27 @@ describe('ShaDa support code', function()
nvim_command('nohlsearch')
expect_exit(nvim_command, 'qall')
reset()
- eq(0, meths.get_vvar('hlsearch'))
+ eq(0, api.nvim_get_vvar('hlsearch'))
end)
it('saves v:hlsearch=0 with default &shada', function()
nvim_command('set hlsearch')
nvim_feed('/test\n')
- eq(1, meths.get_vvar('hlsearch'))
+ eq(1, api.nvim_get_vvar('hlsearch'))
expect_exit(nvim_command, 'qall')
reset()
- eq(0, meths.get_vvar('hlsearch'))
+ eq(0, api.nvim_get_vvar('hlsearch'))
end)
it('dumps and loads last substitute pattern and replacement string', function()
- funcs.setline('.', {'foo', 'bar'})
+ fn.setline('.', { 'foo', 'bar' })
nvim_command('%s/f/g/g')
- eq('goo', funcs.getline(1))
+ eq('goo', fn.getline(1))
nvim_command('wshada')
reset()
- funcs.setline('.', {'foo', 'bar'})
+ fn.setline('.', { 'foo', 'bar' })
nvim_command('&')
- eq('goo', funcs.getline(1))
+ eq('goo', fn.getline(1))
end)
it('dumps and loads history with UTF-8 characters', function()
@@ -177,52 +174,48 @@ describe('ShaDa support code', function()
nvim_feed(':echo "«"\n')
expect_exit(nvim_command, 'qall')
reset()
- eq('echo "«"', funcs.histget(':', -1))
+ eq('echo "«"', fn.histget(':', -1))
end)
- it('dumps and loads replacement with UTF-8 characters',
- function()
+ it('dumps and loads replacement with UTF-8 characters', function()
nvim_command('substitute/./«/ge')
expect_exit(nvim_command, 'qall!')
reset()
- funcs.setline('.', {'.'})
+ fn.setline('.', { '.' })
nvim_command('&')
- eq('«', funcs.getline('.'))
+ eq('«', fn.getline('.'))
end)
- it('dumps and loads substitute pattern with UTF-8 characters',
- function()
+ it('dumps and loads substitute pattern with UTF-8 characters', function()
nvim_command('substitute/«/./ge')
expect_exit(nvim_command, 'qall!')
reset()
- funcs.setline('.', {'«\171'})
+ fn.setline('.', { '«\171' })
nvim_command('&')
- eq('.\171', funcs.getline('.'))
+ eq('.\171', fn.getline('.'))
end)
- it('dumps and loads search pattern with UTF-8 characters',
- function()
+ it('dumps and loads search pattern with UTF-8 characters', function()
nvim_command('silent! /«/')
nvim_command('set shada+=/0')
expect_exit(nvim_command, 'qall!')
reset()
- funcs.setline('.', {'\171«'})
+ fn.setline('.', { '\171«' })
nvim_command('~&')
- eq('\171', funcs.getline('.'))
- eq('', funcs.histget('/', -1))
+ eq('\171', fn.getline('.'))
+ eq('', fn.histget('/', -1))
end)
- it('dumps and loads search pattern with 8-bit single-byte',
- function()
+ it('dumps and loads search pattern with 8-bit single-byte', function()
-- \171 is U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK in latin1
nvim_command('silent! /\171/')
nvim_command('set shada+=/0')
expect_exit(nvim_command, 'qall!')
reset()
- funcs.setline('.', {'\171«'})
+ fn.setline('.', { '\171«' })
nvim_command('~&')
- eq('«', funcs.getline('.'))
- eq('', funcs.histget('/', -1))
+ eq('«', fn.getline('.'))
+ eq('', fn.histget('/', -1))
end)
it('does not crash when dumping last search pattern (#10945)', function()
@@ -239,12 +232,11 @@ describe('ShaDa support code', function()
end)
it('does not crash when number of history save to zero (#11497)', function()
- nvim_command('set shada=\'10')
+ nvim_command("set shada='10")
nvim_feed(':" Test\n')
nvim_command('wshada')
- nvim_command('set shada=\'10,:0')
+ nvim_command("set shada='10,:0")
nvim_command('wshada')
assert_alive()
end)
-
end)
diff --git a/test/functional/shada/marks_spec.lua b/test/functional/shada/marks_spec.lua
index 7f03022ab8..3f29a02506 100644
--- a/test/functional/shada/marks_spec.lua
+++ b/test/functional/shada/marks_spec.lua
@@ -1,8 +1,6 @@
-- ShaDa marks saving/reading support
local helpers = require('test.functional.helpers')(after_each)
-local meths, curwinmeths, curbufmeths, nvim_command, funcs, eq =
- helpers.meths, helpers.curwinmeths, helpers.curbufmeths, helpers.command,
- helpers.funcs, helpers.eq
+local api, nvim_command, fn, eq = helpers.api, helpers.command, helpers.fn, helpers.eq
local feed = helpers.feed
local exc_exec, exec_capture = helpers.exc_exec, helpers.exec_capture
local expect_exit = helpers.expect_exit
@@ -11,7 +9,7 @@ local shada_helpers = require('test.functional.shada.helpers')
local reset, clear = shada_helpers.reset, shada_helpers.clear
local nvim_current_line = function()
- return curwinmeths.get_cursor()[1]
+ return api.nvim_win_get_cursor(0)[1]
end
describe('ShaDa support code', function()
@@ -45,7 +43,7 @@ describe('ShaDa support code', function()
reset()
nvim_command('rshada')
nvim_command('normal! `A')
- eq(testfilename, funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq(testfilename, fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
eq(1, nvim_current_line())
nvim_command('normal! `B')
eq(2, nvim_current_line())
@@ -63,16 +61,16 @@ describe('ShaDa support code', function()
eq('Vim(normal):E20: Mark not set', exc_exec('normal! `A'))
end)
- it('does read back global mark even with `\'0` and `f0` in shada', function()
+ it("does read back global mark even with `'0` and `f0` in shada", function()
nvim_command('edit ' .. testfilename)
nvim_command('mark A')
nvim_command('2')
nvim_command('kB')
nvim_command('wshada')
- reset('set shada=\'0,f0')
+ reset("set shada='0,f0")
nvim_command('language C')
nvim_command('normal! `A')
- eq(testfilename, funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq(testfilename, fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
eq(1, nvim_current_line())
end)
@@ -85,7 +83,7 @@ describe('ShaDa support code', function()
reset()
nvim_command('edit ' .. testfilename)
nvim_command('normal! `a')
- eq(testfilename, funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq(testfilename, fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
eq(1, nvim_current_line())
nvim_command('normal! `b')
eq(2, nvim_current_line())
@@ -115,12 +113,12 @@ describe('ShaDa support code', function()
it('is able to populate v:oldfiles', function()
nvim_command('edit ' .. testfilename)
- local tf_full = curbufmeths.get_name()
+ local tf_full = api.nvim_buf_get_name(0)
nvim_command('edit ' .. testfilename_2)
- local tf_full_2 = curbufmeths.get_name()
+ local tf_full_2 = api.nvim_buf_get_name(0)
expect_exit(nvim_command, 'qall')
reset()
- local oldfiles = meths.get_vvar('oldfiles')
+ local oldfiles = api.nvim_get_vvar('oldfiles')
table.sort(oldfiles)
eq(2, #oldfiles)
eq(testfilename, oldfiles[1]:sub(-#testfilename))
@@ -128,7 +126,7 @@ describe('ShaDa support code', function()
eq(tf_full, oldfiles[1])
eq(tf_full_2, oldfiles[2])
nvim_command('rshada!')
- oldfiles = meths.get_vvar('oldfiles')
+ oldfiles = api.nvim_get_vvar('oldfiles')
table.sort(oldfiles)
eq(2, #oldfiles)
eq(testfilename, oldfiles[1]:sub(-#testfilename))
@@ -160,13 +158,12 @@ describe('ShaDa support code', function()
nvim_command('wshada')
nvim_command('quit')
nvim_command('rshada')
- nvim_command('normal! \15') -- <C-o>
- eq(testfilename_2, funcs.bufname('%'))
- eq({2, 0}, curwinmeths.get_cursor())
+ nvim_command('normal! \15') -- <C-o>
+ eq(testfilename_2, fn.bufname('%'))
+ eq({ 2, 0 }, api.nvim_win_get_cursor(0))
end)
- it('is able to dump and restore jump list with different times (slow!)',
- function()
+ it('is able to dump and restore jump list with different times (slow!)', function()
nvim_command('edit ' .. testfilename_2)
nvim_command('sleep 2')
nvim_command('normal! G')
@@ -182,19 +179,19 @@ describe('ShaDa support code', function()
reset()
nvim_command('redraw')
nvim_command('edit ' .. testfilename)
- eq(testfilename, funcs.bufname('%'))
+ eq(testfilename, fn.bufname('%'))
eq(1, nvim_current_line())
nvim_command('execute "normal! \\<C-o>"')
- eq(testfilename, funcs.bufname('%'))
+ eq(testfilename, fn.bufname('%'))
eq(2, nvim_current_line())
nvim_command('execute "normal! \\<C-o>"')
- eq(testfilename_2, funcs.bufname('%'))
+ eq(testfilename_2, fn.bufname('%'))
eq(1, nvim_current_line())
nvim_command('execute "normal! \\<C-o>"')
- eq(testfilename_2, funcs.bufname('%'))
+ eq(testfilename_2, fn.bufname('%'))
eq(2, nvim_current_line())
nvim_command('execute "normal! \\<C-o>"')
- eq(testfilename_2, funcs.bufname('%'))
+ eq(testfilename_2, fn.bufname('%'))
eq(2, nvim_current_line())
end)
@@ -218,35 +215,41 @@ describe('ShaDa support code', function()
-- -c temporary sets lnum to zero to make `+/pat` work, so calling setpcmark()
-- during -c used to add item with zero lnum to jump list.
- it('does not create incorrect file for non-existent buffers when writing from -c',
- function()
- local argv = helpers.new_argv{
- args_rm={
+ it('does not create incorrect file for non-existent buffers when writing from -c', function()
+ local argv = helpers.new_argv {
+ args_rm = {
'-i',
- '--embed', -- no --embed
+ '--embed', -- no --embed
+ },
+ args = {
+ '-i',
+ api.nvim_get_var('tmpname'), -- Use same shada file as parent.
+ '--cmd',
+ 'silent edit ' .. non_existent_testfilename,
+ '-c',
+ 'qall',
},
- args={
- '-i', meths.get_var('tmpname'), -- Use same shada file as parent.
- '--cmd', 'silent edit '..non_existent_testfilename,
- '-c', 'qall'},
}
- eq('', funcs.system(argv))
+ eq('', fn.system(argv))
eq(0, exc_exec('rshada'))
end)
- it('does not create incorrect file for non-existent buffers opened from -c',
- function()
- local argv = helpers.new_argv{
- args_rm={
+ it('does not create incorrect file for non-existent buffers opened from -c', function()
+ local argv = helpers.new_argv {
+ args_rm = {
+ '-i',
+ '--embed', -- no --embed
+ },
+ args = {
'-i',
- '--embed', -- no --embed
+ api.nvim_get_var('tmpname'), -- Use same shada file as parent.
+ '-c',
+ 'silent edit ' .. non_existent_testfilename,
+ '-c',
+ 'autocmd VimEnter * qall',
},
- args={
- '-i', meths.get_var('tmpname'), -- Use same shada file as parent.
- '-c', 'silent edit '..non_existent_testfilename,
- '-c', 'autocmd VimEnter * qall'},
}
- eq('', funcs.system(argv))
+ eq('', fn.system(argv))
eq(0, exc_exec('rshada'))
end)
diff --git a/test/functional/shada/merging_spec.lua b/test/functional/shada/merging_spec.lua
index dad7aa851d..1b5c0eab5d 100644
--- a/test/functional/shada/merging_spec.lua
+++ b/test/functional/shada/merging_spec.lua
@@ -1,17 +1,15 @@
-- ShaDa merging data support
local helpers = require('test.functional.helpers')(after_each)
-local nvim_command, funcs, curbufmeths, eq =
- helpers.command, helpers.funcs,
- helpers.curbufmeths, helpers.eq
+local nvim_command, fn, eq = helpers.command, helpers.fn, helpers.eq
local exc_exec, exec_capture = helpers.exc_exec, helpers.exec_capture
+local api = helpers.api
local shada_helpers = require('test.functional.shada.helpers')
local reset, clear, get_shada_rw =
shada_helpers.reset, shada_helpers.clear, shada_helpers.get_shada_rw
local read_shada_file = shada_helpers.read_shada_file
-local wshada, sdrcmd, shada_fname =
- get_shada_rw('Xtest-functional-shada-merging.shada')
+local wshada, sdrcmd, shada_fname = get_shada_rw('Xtest-functional-shada-merging.shada')
local mock_file_path = '/a/b/'
if helpers.is_os('win') then
@@ -25,8 +23,7 @@ describe('ShaDa history merging code', function()
os.remove(shada_fname)
end)
- it('takes item with greater timestamp from Neovim instance when reading',
- function()
+ it('takes item with greater timestamp from Neovim instance when reading', function()
wshada('\004\001\009\147\000\196\002ab\196\001a')
eq(0, exc_exec(sdrcmd()))
wshada('\004\000\009\147\000\196\002ab\196\001b')
@@ -44,8 +41,7 @@ describe('ShaDa history merging code', function()
eq(1, found)
end)
- it('takes item with equal timestamp from Neovim instance when reading',
- function()
+ it('takes item with equal timestamp from Neovim instance when reading', function()
wshada('\004\000\009\147\000\196\002ab\196\001a')
eq(0, exc_exec(sdrcmd()))
wshada('\004\000\009\147\000\196\002ab\196\001b')
@@ -63,8 +59,7 @@ describe('ShaDa history merging code', function()
eq(1, found)
end)
- it('takes item with greater timestamp from ShaDa when reading',
- function()
+ it('takes item with greater timestamp from ShaDa when reading', function()
wshada('\004\000\009\147\000\196\002ab\196\001a')
eq(0, exc_exec(sdrcmd()))
wshada('\004\001\009\147\000\196\002ab\196\001b')
@@ -82,8 +77,7 @@ describe('ShaDa history merging code', function()
eq(1, found)
end)
- it('takes item with greater timestamp from Neovim instance when writing',
- function()
+ it('takes item with greater timestamp from Neovim instance when writing', function()
wshada('\004\001\009\147\000\196\002ab\196\001a')
eq(0, exc_exec(sdrcmd()))
wshada('\004\000\009\147\000\196\002ab\196\001b')
@@ -99,8 +93,7 @@ describe('ShaDa history merging code', function()
eq(1, found)
end)
- it('takes item with equal timestamp from Neovim instance when writing',
- function()
+ it('takes item with equal timestamp from Neovim instance when writing', function()
wshada('\004\000\009\147\000\196\002ab\196\001a')
eq(0, exc_exec(sdrcmd()))
wshada('\004\000\009\147\000\196\002ab\196\001b')
@@ -116,8 +109,7 @@ describe('ShaDa history merging code', function()
eq(1, found)
end)
- it('takes item with greater timestamp from ShaDa when writing',
- function()
+ it('takes item with greater timestamp from ShaDa when writing', function()
wshada('\004\000\009\147\000\196\002ab\196\001a')
eq(0, exc_exec(sdrcmd()))
wshada('\004\001\009\147\000\196\002ab\196\001b')
@@ -133,20 +125,20 @@ describe('ShaDa history merging code', function()
eq(1, found)
end)
- it('correctly reads history items with messed up timestamps',
- function()
- wshada('\004\010\009\147\000\196\002ab\196\001a'
- .. '\004\010\009\147\000\196\002ac\196\001a'
- .. '\004\005\009\147\000\196\002ad\196\001a'
- .. '\004\100\009\147\000\196\002ae\196\001a'
- .. '\004\090\009\147\000\196\002af\196\001a'
- )
+ it('correctly reads history items with messed up timestamps', function()
+ wshada(
+ '\004\010\009\147\000\196\002ab\196\001a'
+ .. '\004\010\009\147\000\196\002ac\196\001a'
+ .. '\004\005\009\147\000\196\002ad\196\001a'
+ .. '\004\100\009\147\000\196\002ae\196\001a'
+ .. '\004\090\009\147\000\196\002af\196\001a'
+ )
eq(0, exc_exec(sdrcmd()))
os.remove(shada_fname)
eq(0, exc_exec('wshada! ' .. shada_fname))
- local items = {'ad', 'ab', 'ac', 'af', 'ae'}
+ local items = { 'ad', 'ab', 'ac', 'af', 'ae' }
for i, v in ipairs(items) do
- eq(v, funcs.histget(':', i))
+ eq(v, fn.histget(':', i))
end
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -159,16 +151,16 @@ describe('ShaDa history merging code', function()
eq(#items, found)
end)
- it('correctly reorders history items with messed up timestamps when writing',
- function()
- wshada('\004\010\009\147\000\196\002ab\196\001a'
- .. '\004\010\009\147\000\196\002ac\196\001a'
- .. '\004\005\009\147\000\196\002ad\196\001a'
- .. '\004\100\009\147\000\196\002ae\196\001a'
- .. '\004\090\009\147\000\196\002af\196\001a'
- )
+ it('correctly reorders history items with messed up timestamps when writing', function()
+ wshada(
+ '\004\010\009\147\000\196\002ab\196\001a'
+ .. '\004\010\009\147\000\196\002ac\196\001a'
+ .. '\004\005\009\147\000\196\002ad\196\001a'
+ .. '\004\100\009\147\000\196\002ae\196\001a'
+ .. '\004\090\009\147\000\196\002af\196\001a'
+ )
eq(0, exc_exec('wshada ' .. shada_fname))
- local items = {'ad', 'ab', 'ac', 'af', 'ae'}
+ local items = { 'ad', 'ab', 'ac', 'af', 'ae' }
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == 4 and v.value[1] == 0 then
@@ -180,24 +172,24 @@ describe('ShaDa history merging code', function()
eq(#items, found)
end)
- it('correctly merges history items with duplicate mid entry when writing',
- function()
+ it('correctly merges history items with duplicate mid entry when writing', function()
-- Regression test: ShaDa code used to crash here.
-- Conditions:
-- 1. Entry which is duplicate to non-last entry.
-- 2. At least one more non-duplicate entry.
- wshada('\004\000\009\147\000\196\002ab\196\001a'
- .. '\004\001\009\147\000\196\002ac\196\001a'
- .. '\004\002\009\147\000\196\002ad\196\001a'
- .. '\004\003\009\147\000\196\002ac\196\001a'
- .. '\004\004\009\147\000\196\002af\196\001a'
- .. '\004\005\009\147\000\196\002ae\196\001a'
- .. '\004\006\009\147\000\196\002ag\196\001a'
- .. '\004\007\009\147\000\196\002ah\196\001a'
- .. '\004\008\009\147\000\196\002ai\196\001a'
- )
+ wshada(
+ '\004\000\009\147\000\196\002ab\196\001a'
+ .. '\004\001\009\147\000\196\002ac\196\001a'
+ .. '\004\002\009\147\000\196\002ad\196\001a'
+ .. '\004\003\009\147\000\196\002ac\196\001a'
+ .. '\004\004\009\147\000\196\002af\196\001a'
+ .. '\004\005\009\147\000\196\002ae\196\001a'
+ .. '\004\006\009\147\000\196\002ag\196\001a'
+ .. '\004\007\009\147\000\196\002ah\196\001a'
+ .. '\004\008\009\147\000\196\002ai\196\001a'
+ )
eq(0, exc_exec('wshada ' .. shada_fname))
- local items = {'ab', 'ad', 'ac', 'af', 'ae', 'ag', 'ah', 'ai'}
+ local items = { 'ab', 'ad', 'ac', 'af', 'ae', 'ag', 'ah', 'ai' }
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == 4 and v.value[1] == 0 then
@@ -209,20 +201,20 @@ describe('ShaDa history merging code', function()
eq(#items, found)
end)
- it('correctly merges history items with duplicate adj entry when writing',
- function()
- wshada('\004\000\009\147\000\196\002ab\196\001a'
- .. '\004\001\009\147\000\196\002ac\196\001a'
- .. '\004\002\009\147\000\196\002ad\196\001a'
- .. '\004\003\009\147\000\196\002ad\196\001a'
- .. '\004\004\009\147\000\196\002af\196\001a'
- .. '\004\005\009\147\000\196\002ae\196\001a'
- .. '\004\006\009\147\000\196\002ag\196\001a'
- .. '\004\007\009\147\000\196\002ah\196\001a'
- .. '\004\008\009\147\000\196\002ai\196\001a'
- )
+ it('correctly merges history items with duplicate adj entry when writing', function()
+ wshada(
+ '\004\000\009\147\000\196\002ab\196\001a'
+ .. '\004\001\009\147\000\196\002ac\196\001a'
+ .. '\004\002\009\147\000\196\002ad\196\001a'
+ .. '\004\003\009\147\000\196\002ad\196\001a'
+ .. '\004\004\009\147\000\196\002af\196\001a'
+ .. '\004\005\009\147\000\196\002ae\196\001a'
+ .. '\004\006\009\147\000\196\002ag\196\001a'
+ .. '\004\007\009\147\000\196\002ah\196\001a'
+ .. '\004\008\009\147\000\196\002ai\196\001a'
+ )
eq(0, exc_exec('wshada ' .. shada_fname))
- local items = {'ab', 'ac', 'ad', 'af', 'ae', 'ag', 'ah', 'ai'}
+ local items = { 'ab', 'ac', 'ad', 'af', 'ae', 'ag', 'ah', 'ai' }
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == 4 and v.value[1] == 0 then
@@ -242,48 +234,43 @@ describe('ShaDa search pattern support code', function()
os.remove(shada_fname)
end)
- it('uses last search pattern with gt timestamp from instance when reading',
- function()
+ it('uses last search pattern with gt timestamp from instance when reading', function()
wshada('\002\001\011\130\162sX\194\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\000\011\130\162sX\194\162sp\196\001?')
eq(0, exc_exec(sdrcmd()))
- eq('-', funcs.getreg('/'))
+ eq('-', fn.getreg('/'))
end)
- it('uses last search pattern with gt tstamp from file when reading with bang',
- function()
+ it('uses last search pattern with gt tstamp from file when reading with bang', function()
wshada('\002\001\011\130\162sX\194\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\000\011\130\162sX\194\162sp\196\001?')
eq(0, exc_exec(sdrcmd(true)))
- eq('?', funcs.getreg('/'))
+ eq('?', fn.getreg('/'))
end)
- it('uses last search pattern with eq timestamp from instance when reading',
- function()
+ it('uses last search pattern with eq timestamp from instance when reading', function()
wshada('\002\001\011\130\162sX\194\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\001\011\130\162sX\194\162sp\196\001?')
eq(0, exc_exec(sdrcmd()))
- eq('-', funcs.getreg('/'))
+ eq('-', fn.getreg('/'))
end)
- it('uses last search pattern with gt timestamp from file when reading',
- function()
+ it('uses last search pattern with gt timestamp from file when reading', function()
wshada('\002\001\011\130\162sX\194\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\002\011\130\162sX\194\162sp\196\001?')
eq(0, exc_exec(sdrcmd()))
- eq('?', funcs.getreg('/'))
+ eq('?', fn.getreg('/'))
end)
- it('uses last search pattern with gt timestamp from instance when writing',
- function()
+ it('uses last search pattern with gt timestamp from instance when writing', function()
wshada('\002\001\011\130\162sX\194\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\000\011\130\162sX\194\162sp\196\001?')
- eq('-', funcs.getreg('/'))
+ eq('-', fn.getreg('/'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -294,12 +281,11 @@ describe('ShaDa search pattern support code', function()
eq(1, found)
end)
- it('uses last search pattern with eq timestamp from instance when writing',
- function()
+ it('uses last search pattern with eq timestamp from instance when writing', function()
wshada('\002\001\011\130\162sX\194\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\001\011\130\162sX\194\162sp\196\001?')
- eq('-', funcs.getreg('/'))
+ eq('-', fn.getreg('/'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -310,12 +296,11 @@ describe('ShaDa search pattern support code', function()
eq(1, found)
end)
- it('uses last search pattern with gt timestamp from file when writing',
- function()
+ it('uses last search pattern with gt timestamp from file when writing', function()
wshada('\002\001\011\130\162sX\194\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\002\011\130\162sX\194\162sp\196\001?')
- eq('-', funcs.getreg('/'))
+ eq('-', fn.getreg('/'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -326,48 +311,43 @@ describe('ShaDa search pattern support code', function()
eq(1, found)
end)
- it('uses last s/ pattern with gt timestamp from instance when reading',
- function()
+ it('uses last s/ pattern with gt timestamp from instance when reading', function()
wshada('\002\001\011\130\162ss\195\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\000\011\130\162ss\195\162sp\196\001?')
eq(0, exc_exec(sdrcmd()))
- eq('-', funcs.getreg('/'))
+ eq('-', fn.getreg('/'))
end)
- it('uses last s/ pattern with gt timestamp from file when reading with !',
- function()
+ it('uses last s/ pattern with gt timestamp from file when reading with !', function()
wshada('\002\001\011\130\162ss\195\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\000\011\130\162ss\195\162sp\196\001?')
eq(0, exc_exec(sdrcmd(true)))
- eq('?', funcs.getreg('/'))
+ eq('?', fn.getreg('/'))
end)
- it('uses last s/ pattern with eq timestamp from instance when reading',
- function()
+ it('uses last s/ pattern with eq timestamp from instance when reading', function()
wshada('\002\001\011\130\162ss\195\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\001\011\130\162ss\195\162sp\196\001?')
eq(0, exc_exec(sdrcmd()))
- eq('-', funcs.getreg('/'))
+ eq('-', fn.getreg('/'))
end)
- it('uses last s/ pattern with gt timestamp from file when reading',
- function()
+ it('uses last s/ pattern with gt timestamp from file when reading', function()
wshada('\002\001\011\130\162ss\195\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\002\011\130\162ss\195\162sp\196\001?')
eq(0, exc_exec(sdrcmd()))
- eq('?', funcs.getreg('/'))
+ eq('?', fn.getreg('/'))
end)
- it('uses last s/ pattern with gt timestamp from instance when writing',
- function()
+ it('uses last s/ pattern with gt timestamp from instance when writing', function()
wshada('\002\001\011\130\162ss\195\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\000\011\130\162ss\195\162sp\196\001?')
- eq('-', funcs.getreg('/'))
+ eq('-', fn.getreg('/'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -378,12 +358,11 @@ describe('ShaDa search pattern support code', function()
eq(1, found)
end)
- it('uses last s/ pattern with eq timestamp from instance when writing',
- function()
+ it('uses last s/ pattern with eq timestamp from instance when writing', function()
wshada('\002\001\011\130\162ss\195\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\001\011\130\162ss\195\162sp\196\001?')
- eq('-', funcs.getreg('/'))
+ eq('-', fn.getreg('/'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -394,12 +373,11 @@ describe('ShaDa search pattern support code', function()
eq(1, found)
end)
- it('uses last s/ pattern with gt timestamp from file when writing',
- function()
+ it('uses last s/ pattern with gt timestamp from file when writing', function()
wshada('\002\001\011\130\162ss\195\162sp\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\002\002\011\130\162ss\195\162sp\196\001?')
- eq('-', funcs.getreg('/'))
+ eq('-', fn.getreg('/'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -418,52 +396,47 @@ describe('ShaDa replacement string support code', function()
os.remove(shada_fname)
end)
- it('uses last replacement with gt timestamp from instance when reading',
- function()
+ it('uses last replacement with gt timestamp from instance when reading', function()
wshada('\003\001\004\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\003\000\004\145\196\001?')
eq(0, exc_exec(sdrcmd()))
nvim_command('s/.*/~')
- eq('-', funcs.getline('.'))
+ eq('-', fn.getline('.'))
nvim_command('bwipeout!')
end)
- it('uses last replacement with gt timestamp from file when reading with bang',
- function()
+ it('uses last replacement with gt timestamp from file when reading with bang', function()
wshada('\003\001\004\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\003\000\004\145\196\001?')
eq(0, exc_exec(sdrcmd(true)))
nvim_command('s/.*/~')
- eq('?', funcs.getline('.'))
+ eq('?', fn.getline('.'))
nvim_command('bwipeout!')
end)
- it('uses last replacement with eq timestamp from instance when reading',
- function()
+ it('uses last replacement with eq timestamp from instance when reading', function()
wshada('\003\001\004\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\003\001\004\145\196\001?')
eq(0, exc_exec(sdrcmd()))
nvim_command('s/.*/~')
- eq('-', funcs.getline('.'))
+ eq('-', fn.getline('.'))
nvim_command('bwipeout!')
end)
- it('uses last replacement with gt timestamp from file when reading',
- function()
+ it('uses last replacement with gt timestamp from file when reading', function()
wshada('\003\001\004\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\003\002\004\145\196\001?')
eq(0, exc_exec(sdrcmd()))
nvim_command('s/.*/~')
- eq('?', funcs.getline('.'))
+ eq('?', fn.getline('.'))
nvim_command('bwipeout!')
end)
- it('uses last replacement with gt timestamp from instance when writing',
- function()
+ it('uses last replacement with gt timestamp from instance when writing', function()
wshada('\003\001\004\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\003\000\004\145\196\001?')
@@ -477,8 +450,7 @@ describe('ShaDa replacement string support code', function()
eq(1, found)
end)
- it('uses last replacement with eq timestamp from instance when writing',
- function()
+ it('uses last replacement with eq timestamp from instance when writing', function()
wshada('\003\001\004\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\003\001\004\145\196\001?')
@@ -492,8 +464,7 @@ describe('ShaDa replacement string support code', function()
eq(1, found)
end)
- it('uses last replacement with gt timestamp from file when writing',
- function()
+ it('uses last replacement with gt timestamp from file when writing', function()
wshada('\003\001\004\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\003\002\004\145\196\001?')
@@ -515,21 +486,20 @@ describe('ShaDa marks support code', function()
os.remove(shada_fname)
end)
- it('uses last A mark with gt timestamp from instance when reading',
- function()
+ it('uses last A mark with gt timestamp from instance when reading', function()
wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
eq(0, exc_exec(sdrcmd()))
wshada('\007\000\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
eq(0, exc_exec(sdrcmd()))
nvim_command('normal! `A')
- eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
end)
it('can merge with file with mark 9 as the only numeric mark', function()
wshada('\007\001\014\130\161f\196\006' .. mock_file_path .. '-\161n9')
eq(0, exc_exec(sdrcmd()))
nvim_command('normal! `9oabc')
- eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = {}
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -538,37 +508,66 @@ describe('ShaDa marks support code', function()
found[name] = (found[name] or 0) + 1
end
end
- eq({['0']=1, ['1']=1}, found)
+ eq({ ['0'] = 1, ['1'] = 1 }, found)
end)
it('removes duplicates while merging', function()
- wshada('\007\001\014\130\161f\196\006' .. mock_file_path .. '-\161n9'
- .. '\007\001\014\130\161f\196\006' .. mock_file_path .. '-\161n9')
+ wshada(
+ '\007\001\014\130\161f\196\006'
+ .. mock_file_path
+ .. '-\161n9'
+ .. '\007\001\014\130\161f\196\006'
+ .. mock_file_path
+ .. '-\161n9'
+ )
eq(0, exc_exec(sdrcmd()))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == 7 and v.value.f == mock_file_path .. '-' then
- print(require('test.helpers').format_luav(v))
+ print(require('test.format_string').format_luav(v))
found = found + 1
end
end
eq(1, found)
end)
- it('does not leak when no append is performed due to too many marks',
- function()
- wshada('\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'a\161n0'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'b\161n1'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161n2'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'd\161n3'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'e\161n4'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'f\161n5'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'g\161n6'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'h\161n7'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'i\161n8'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'j\161n9'
- .. '\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'k\161n9')
+ it('does not leak when no append is performed due to too many marks', function()
+ wshada(
+ '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'a\161n0'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'b\161n1'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161n2'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'd\161n3'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'e\161n4'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'f\161n5'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'g\161n6'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'h\161n7'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'i\161n8'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'j\161n9'
+ .. '\007\001\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'k\161n9'
+ )
eq(0, exc_exec(sdrcmd()))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = {}
@@ -577,22 +576,45 @@ describe('ShaDa marks support code', function()
found[#found + 1] = v.value.f:sub(#v.value.f)
end
end
- eq({'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}, found)
- end)
-
- it('does not leak when last mark in file removes some of the earlier ones',
- function()
- wshada('\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'a\161n0'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'b\161n1'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161n2'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'd\161n3'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'e\161n4'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'f\161n5'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'g\161n6'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'h\161n7'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'i\161n8'
- .. '\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'j\161n9'
- .. '\007\003\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'k\161n9')
+ eq({ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' }, found)
+ end)
+
+ it('does not leak when last mark in file removes some of the earlier ones', function()
+ wshada(
+ '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'a\161n0'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'b\161n1'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161n2'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'd\161n3'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'e\161n4'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'f\161n5'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'g\161n6'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'h\161n7'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'i\161n8'
+ .. '\007\002\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'j\161n9'
+ .. '\007\003\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'k\161n9'
+ )
eq(0, exc_exec(sdrcmd()))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = {}
@@ -601,46 +623,42 @@ describe('ShaDa marks support code', function()
found[#found + 1] = v.value.f:sub(#v.value.f)
end
end
- eq({'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k'}, found)
+ eq({ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k' }, found)
end)
- it('uses last A mark with gt timestamp from file when reading with !',
- function()
+ it('uses last A mark with gt timestamp from file when reading with !', function()
wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
eq(0, exc_exec(sdrcmd()))
wshada('\007\000\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
eq(0, exc_exec(sdrcmd(true)))
nvim_command('normal! `A')
- eq('?', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq('?', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
end)
- it('uses last A mark with eq timestamp from instance when reading',
- function()
+ it('uses last A mark with eq timestamp from instance when reading', function()
wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
eq(0, exc_exec(sdrcmd()))
wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
eq(0, exc_exec(sdrcmd()))
nvim_command('normal! `A')
- eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
end)
- it('uses last A mark with gt timestamp from file when reading',
- function()
+ it('uses last A mark with gt timestamp from file when reading', function()
wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
eq(0, exc_exec(sdrcmd()))
wshada('\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
eq(0, exc_exec(sdrcmd()))
nvim_command('normal! `A')
- eq('?', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq('?', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
end)
- it('uses last A mark with gt timestamp from instance when writing',
- function()
+ it('uses last A mark with gt timestamp from instance when writing', function()
wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
eq(0, exc_exec(sdrcmd()))
wshada('\007\000\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
nvim_command('normal! `A')
- eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = {}
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -649,16 +667,15 @@ describe('ShaDa marks support code', function()
found[name] = (found[name] or 0) + 1
end
end
- eq({['0']=1, A=1}, found)
+ eq({ ['0'] = 1, A = 1 }, found)
end)
- it('uses last A mark with eq timestamp from instance when writing',
- function()
+ it('uses last A mark with eq timestamp from instance when writing', function()
wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
eq(0, exc_exec(sdrcmd()))
wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
nvim_command('normal! `A')
- eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = {}
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -667,7 +684,7 @@ describe('ShaDa marks support code', function()
found[name] = (found[name] or 0) + 1
end
end
- eq({['0']=1, A=1}, found)
+ eq({ ['0'] = 1, A = 1 }, found)
end)
it('uses last A mark with gt timestamp from file when writing', function()
@@ -675,7 +692,7 @@ describe('ShaDa marks support code', function()
eq(0, exc_exec(sdrcmd()))
wshada('\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
nvim_command('normal! `A')
- eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = {}
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -686,70 +703,69 @@ describe('ShaDa marks support code', function()
found[name] = t
end
end
- eq({['0']={[mock_file_path .. '-']=1}, A={[mock_file_path .. '?']=1}}, found)
+ eq({ ['0'] = { [mock_file_path .. '-'] = 1 }, A = { [mock_file_path .. '?'] = 1 } }, found)
end)
- it('uses last a mark with gt timestamp from instance when reading',
- function()
+ it('uses last a mark with gt timestamp from instance when reading', function()
nvim_command('edit ' .. mock_file_path .. '-')
- funcs.setline(1, {'-', '?'})
+ fn.setline(1, { '-', '?' })
wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
eq(0, exc_exec(sdrcmd()))
wshada('\010\000\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
eq(0, exc_exec(sdrcmd()))
nvim_command('normal! `a')
- eq('-', funcs.getline('.'))
+ eq('-', fn.getline('.'))
end)
- it('uses last a mark with gt timestamp from file when reading with !',
- function()
+ it('uses last a mark with gt timestamp from file when reading with !', function()
nvim_command('edit ' .. mock_file_path .. '-')
- funcs.setline(1, {'-', '?'})
+ fn.setline(1, { '-', '?' })
wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
eq(0, exc_exec(sdrcmd()))
wshada('\010\000\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
eq(0, exc_exec(sdrcmd(true)))
nvim_command('normal! `a')
- eq('?', funcs.getline('.'))
+ eq('?', fn.getline('.'))
end)
- it('uses last a mark with eq timestamp from instance when reading',
- function()
+ it('uses last a mark with eq timestamp from instance when reading', function()
nvim_command('edit ' .. mock_file_path .. '-')
- funcs.setline(1, {'-', '?'})
+ fn.setline(1, { '-', '?' })
wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
eq(0, exc_exec(sdrcmd()))
wshada('\010\001\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
eq(0, exc_exec(sdrcmd()))
nvim_command('normal! `a')
- eq('-', funcs.getline('.'))
+ eq('-', fn.getline('.'))
end)
- it('uses last a mark with gt timestamp from file when reading',
- function()
+ it('uses last a mark with gt timestamp from file when reading', function()
nvim_command('edit ' .. mock_file_path .. '-')
- funcs.setline(1, {'-', '?'})
+ fn.setline(1, { '-', '?' })
wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
eq(0, exc_exec(sdrcmd()))
wshada('\010\002\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
eq(0, exc_exec(sdrcmd()))
nvim_command('normal! `a')
- eq('?', funcs.getline('.'))
+ eq('?', fn.getline('.'))
end)
- it('uses last a mark with gt timestamp from instance when writing',
- function()
+ it('uses last a mark with gt timestamp from instance when writing', function()
nvim_command('edit ' .. mock_file_path .. '-')
- funcs.setline(1, {'-', '?'})
+ fn.setline(1, { '-', '?' })
wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
eq(0, exc_exec(sdrcmd()))
wshada('\010\000\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
nvim_command('normal! `a')
- eq('-', funcs.getline('.'))
+ eq('-', fn.getline('.'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
- if v.type == 10 and v.value.f == '' .. mock_file_path .. '-' and v.value.n == ('a'):byte() then
+ if
+ v.type == 10
+ and v.value.f == '' .. mock_file_path .. '-'
+ and v.value.n == ('a'):byte()
+ then
eq(true, v.value.l == 1 or v.value.l == nil)
found = found + 1
end
@@ -757,19 +773,22 @@ describe('ShaDa marks support code', function()
eq(1, found)
end)
- it('uses last a mark with eq timestamp from instance when writing',
- function()
+ it('uses last a mark with eq timestamp from instance when writing', function()
nvim_command('edit ' .. mock_file_path .. '-')
- funcs.setline(1, {'-', '?'})
+ fn.setline(1, { '-', '?' })
wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
eq(0, exc_exec(sdrcmd()))
wshada('\010\001\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
nvim_command('normal! `a')
- eq('-', funcs.getline('.'))
+ eq('-', fn.getline('.'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
- if v.type == 10 and v.value.f == '' .. mock_file_path .. '-' and v.value.n == ('a'):byte() then
+ if
+ v.type == 10
+ and v.value.f == '' .. mock_file_path .. '-'
+ and v.value.n == ('a'):byte()
+ then
eq(true, v.value.l == 1 or v.value.l == nil)
found = found + 1
end
@@ -777,19 +796,22 @@ describe('ShaDa marks support code', function()
eq(1, found)
end)
- it('uses last a mark with gt timestamp from file when writing',
- function()
+ it('uses last a mark with gt timestamp from file when writing', function()
nvim_command('edit ' .. mock_file_path .. '-')
- funcs.setline(1, {'-', '?'})
+ fn.setline(1, { '-', '?' })
wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
eq(0, exc_exec(sdrcmd()))
wshada('\010\002\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
nvim_command('normal! `a')
- eq('-', funcs.fnamemodify(curbufmeths.get_name(), ':t'))
+ eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
- if v.type == 10 and v.value.f == '' .. mock_file_path .. '-' and v.value.n == ('a'):byte() then
+ if
+ v.type == 10
+ and v.value.f == '' .. mock_file_path .. '-'
+ and v.value.n == ('a'):byte()
+ then
eq(2, v.value.l)
found = found + 1
end
@@ -805,87 +827,80 @@ describe('ShaDa registers support code', function()
os.remove(shada_fname)
end)
- it('uses last a register with gt timestamp from instance when reading',
- function()
+ it('uses last a register with gt timestamp from instance when reading', function()
wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\005\000\015\131\161na\162rX\194\162rc\145\196\001?')
eq(0, exc_exec(sdrcmd()))
- eq('-', funcs.getreg('a'))
+ eq('-', fn.getreg('a'))
end)
- it('uses last a register with gt timestamp from file when reading with !',
- function()
+ it('uses last a register with gt timestamp from file when reading with !', function()
wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\005\000\015\131\161na\162rX\194\162rc\145\196\001?')
eq(0, exc_exec(sdrcmd(true)))
- eq('?', funcs.getreg('a'))
+ eq('?', fn.getreg('a'))
end)
- it('uses last a register with eq timestamp from instance when reading',
- function()
+ it('uses last a register with eq timestamp from instance when reading', function()
wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001?')
eq(0, exc_exec(sdrcmd()))
- eq('-', funcs.getreg('a'))
+ eq('-', fn.getreg('a'))
end)
- it('uses last a register with gt timestamp from file when reading',
- function()
+ it('uses last a register with gt timestamp from file when reading', function()
wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\005\002\015\131\161na\162rX\194\162rc\145\196\001?')
eq(0, exc_exec(sdrcmd()))
- eq('?', funcs.getreg('a'))
+ eq('?', fn.getreg('a'))
end)
- it('uses last a register with gt timestamp from instance when writing',
- function()
+ it('uses last a register with gt timestamp from instance when writing', function()
wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\005\000\015\131\161na\162rX\194\162rc\145\196\001?')
- eq('-', funcs.getreg('a'))
+ eq('-', fn.getreg('a'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == 5 and v.value.n == ('a'):byte() then
- eq({'-'}, v.value.rc)
+ eq({ '-' }, v.value.rc)
found = found + 1
end
end
eq(1, found)
end)
- it('uses last a register with eq timestamp from instance when writing',
- function()
+ it('uses last a register with eq timestamp from instance when writing', function()
wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001?')
- eq('-', funcs.getreg('a'))
+ eq('-', fn.getreg('a'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == 5 and v.value.n == ('a'):byte() then
- eq({'-'}, v.value.rc)
+ eq({ '-' }, v.value.rc)
found = found + 1
end
end
eq(1, found)
end)
- it('uses last a register with gt timestamp from file when writing',
- function()
+ it('uses last a register with gt timestamp from file when writing', function()
wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
eq(0, exc_exec(sdrcmd()))
wshada('\005\002\015\131\161na\162rX\194\162rc\145\196\001?')
- eq('-', funcs.getreg('a'))
+ eq('-', fn.getreg('a'))
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == 5 and v.value.n == ('a'):byte() then
- eq({'?'}, v.value.rc)
+ eq({ '?' }, v.value.rc)
found = found + 1
end
end
@@ -901,39 +916,84 @@ describe('ShaDa jumps support code', function()
end)
it('merges jumps when reading', function()
- wshada('\008\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\002'
- .. '\008\004\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'd\161l\002'
- .. '\008\007\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'e\161l\002')
- eq(0, exc_exec(sdrcmd()))
- wshada('\008\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\002'
- .. '\008\004\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'd\161l\003'
- .. '\008\007\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'f\161l\002')
- eq(0, exc_exec(sdrcmd()))
- eq('', curbufmeths.get_name())
- eq( ' jump line col file/text\n'
- .. ' 5 2 0 ' .. mock_file_path .. 'c\n'
- .. ' 4 2 0 ' .. mock_file_path .. 'd\n'
- .. ' 3 3 0 ' .. mock_file_path .. 'd\n'
- .. ' 2 2 0 ' .. mock_file_path .. 'e\n'
- .. ' 1 2 0 ' .. mock_file_path .. 'f\n'
- .. '>', exec_capture('jumps'))
+ wshada(
+ '\008\001\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\002'
+ .. '\008\004\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'd\161l\002'
+ .. '\008\007\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'e\161l\002'
+ )
+ eq(0, exc_exec(sdrcmd()))
+ wshada(
+ '\008\001\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\002'
+ .. '\008\004\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'd\161l\003'
+ .. '\008\007\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'f\161l\002'
+ )
+ eq(0, exc_exec(sdrcmd()))
+ eq('', api.nvim_buf_get_name(0))
+ eq(
+ ' jump line col file/text\n'
+ .. ' 5 2 0 '
+ .. mock_file_path
+ .. 'c\n'
+ .. ' 4 2 0 '
+ .. mock_file_path
+ .. 'd\n'
+ .. ' 3 3 0 '
+ .. mock_file_path
+ .. 'd\n'
+ .. ' 2 2 0 '
+ .. mock_file_path
+ .. 'e\n'
+ .. ' 1 2 0 '
+ .. mock_file_path
+ .. 'f\n'
+ .. '>',
+ exec_capture('jumps')
+ )
end)
it('merges jumps when writing', function()
- wshada('\008\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\002'
- .. '\008\004\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'd\161l\002'
- .. '\008\007\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'e\161l\002')
- eq(0, exc_exec(sdrcmd()))
- wshada('\008\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\002'
- .. '\008\004\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'd\161l\003'
- .. '\008\007\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'f\161l\002')
+ wshada(
+ '\008\001\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\002'
+ .. '\008\004\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'd\161l\002'
+ .. '\008\007\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'e\161l\002'
+ )
+ eq(0, exc_exec(sdrcmd()))
+ wshada(
+ '\008\001\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\002'
+ .. '\008\004\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'd\161l\003'
+ .. '\008\007\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'f\161l\002'
+ )
eq(0, exc_exec('wshada ' .. shada_fname))
local jumps = {
- {file='' .. mock_file_path .. 'c', line=2},
- {file='' .. mock_file_path .. 'd', line=2},
- {file='' .. mock_file_path .. 'd', line=3},
- {file='' .. mock_file_path .. 'e', line=2},
- {file='' .. mock_file_path .. 'f', line=2},
+ { file = '' .. mock_file_path .. 'c', line = 2 },
+ { file = '' .. mock_file_path .. 'd', line = 2 },
+ { file = '' .. mock_file_path .. 'd', line = 3 },
+ { file = '' .. mock_file_path .. 'e', line = 2 },
+ { file = '' .. mock_file_path .. 'f', line = 2 },
}
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -949,25 +1009,28 @@ describe('ShaDa jumps support code', function()
it('merges JUMPLISTSIZE jumps when writing', function()
local jumps = {}
local shada = ''
- for i = 1,100 do
- shada = shada .. ('\008%c\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l%c'
- ):format(i, i)
- jumps[i] = {file='' .. mock_file_path .. 'c', line=i}
+ for i = 1, 100 do
+ shada = shada
+ .. ('\008%c\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l%c'):format(i, i)
+ jumps[i] = { file = '' .. mock_file_path .. 'c', line = i }
end
wshada(shada)
eq(0, exc_exec(sdrcmd()))
shada = ''
- for i = 1,101 do
+ for i = 1, 101 do
local t = i * 2
- shada = shada .. (
- '\008\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'
- ):format(t, t)
- jumps[(t > #jumps + 1) and (#jumps + 1) or t] = {file='' .. mock_file_path .. 'c', line=t}
+ shada = shada
+ .. ('\008\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'):format(
+ t,
+ t
+ )
+ jumps[(t > #jumps + 1) and (#jumps + 1) or t] =
+ { file = '' .. mock_file_path .. 'c', line = t }
end
wshada(shada)
eq(0, exc_exec('wshada ' .. shada_fname))
local shift = #jumps - 100
- for i = 1,100 do
+ for i = 1, 100 do
jumps[i] = jumps[i + shift]
end
local found = 0
@@ -992,40 +1055,75 @@ describe('ShaDa changes support code', function()
it('merges changes when reading', function()
nvim_command('edit ' .. mock_file_path .. 'c')
nvim_command('keepjumps call setline(1, range(7))')
- wshada('\011\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\001'
- .. '\011\004\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\002'
- .. '\011\007\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\003')
- eq(0, exc_exec(sdrcmd()))
- wshada('\011\001\018\131\162mX\194\161f\196\006' .. mock_file_path .. 'c\161l\001'
- .. '\011\004\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\005'
- .. '\011\008\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\004')
- eq(0, exc_exec(sdrcmd()))
- eq( 'change line col text\n'
- .. ' 5 1 0 0\n'
- .. ' 4 2 0 1\n'
- .. ' 3 5 0 4\n'
- .. ' 2 3 0 2\n'
- .. ' 1 4 0 3\n'
- .. '>', exec_capture('changes'))
+ wshada(
+ '\011\001\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\001'
+ .. '\011\004\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\002'
+ .. '\011\007\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\003'
+ )
+ eq(0, exc_exec(sdrcmd()))
+ wshada(
+ '\011\001\018\131\162mX\194\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\001'
+ .. '\011\004\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\005'
+ .. '\011\008\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\004'
+ )
+ eq(0, exc_exec(sdrcmd()))
+ eq(
+ 'change line col text\n'
+ .. ' 5 1 0 0\n'
+ .. ' 4 2 0 1\n'
+ .. ' 3 5 0 4\n'
+ .. ' 2 3 0 2\n'
+ .. ' 1 4 0 3\n'
+ .. '>',
+ exec_capture('changes')
+ )
end)
it('merges changes when writing', function()
nvim_command('edit ' .. mock_file_path .. 'c')
nvim_command('keepjumps call setline(1, range(7))')
- wshada('\011\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\001'
- .. '\011\004\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\002'
- .. '\011\007\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\003')
- eq(0, exc_exec(sdrcmd()))
- wshada('\011\001\018\131\162mX\194\161f\196\006' .. mock_file_path .. 'c\161l\001'
- .. '\011\004\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\005'
- .. '\011\008\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\004')
+ wshada(
+ '\011\001\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\001'
+ .. '\011\004\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\002'
+ .. '\011\007\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\003'
+ )
+ eq(0, exc_exec(sdrcmd()))
+ wshada(
+ '\011\001\018\131\162mX\194\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\001'
+ .. '\011\004\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\005'
+ .. '\011\008\018\131\162mX\195\161f\196\006'
+ .. mock_file_path
+ .. 'c\161l\004'
+ )
eq(0, exc_exec('wshada ' .. shada_fname))
local changes = {
- {line=1},
- {line=2},
- {line=5},
- {line=3},
- {line=4},
+ { line = 1 },
+ { line = 2 },
+ { line = 5 },
+ { line = 3 },
+ { line = 4 },
}
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -1042,25 +1140,27 @@ describe('ShaDa changes support code', function()
nvim_command('keepjumps call setline(1, range(202))')
local changes = {}
local shada = ''
- for i = 1,100 do
- shada = shada .. ('\011%c\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l%c'
- ):format(i, i)
- changes[i] = {line=i}
+ for i = 1, 100 do
+ shada = shada
+ .. ('\011%c\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l%c'):format(i, i)
+ changes[i] = { line = i }
end
wshada(shada)
eq(0, exc_exec(sdrcmd()))
shada = ''
- for i = 1,101 do
+ for i = 1, 101 do
local t = i * 2
- shada = shada .. (
- '\011\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'
- ):format(t, t)
- changes[(t > #changes + 1) and (#changes + 1) or t] = {line=t}
+ shada = shada
+ .. ('\011\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'):format(
+ t,
+ t
+ )
+ changes[(t > #changes + 1) and (#changes + 1) or t] = { line = t }
end
wshada(shada)
eq(0, exc_exec('wshada ' .. shada_fname))
local shift = #changes - 100
- for i = 1,100 do
+ for i = 1, 100 do
changes[i] = changes[i + shift]
end
local found = 0
@@ -1073,36 +1173,37 @@ describe('ShaDa changes support code', function()
eq(found, 100)
end)
- it('merges JUMPLISTSIZE changes when writing, with new items between old',
- function()
+ it('merges JUMPLISTSIZE changes when writing, with new items between old', function()
nvim_command('edit ' .. mock_file_path .. 'c')
nvim_command('keepjumps call setline(1, range(202))')
local shada = ''
- for i = 1,101 do
+ for i = 1, 101 do
local t = i * 2
- shada = shada .. (
- '\011\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'
- ):format(t, t)
+ shada = shada
+ .. ('\011\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'):format(
+ t,
+ t
+ )
end
wshada(shada)
eq(0, exc_exec(sdrcmd()))
shada = ''
- for i = 1,100 do
- shada = shada .. ('\011%c\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l%c'
- ):format(i, i)
+ for i = 1, 100 do
+ shada = shada
+ .. ('\011%c\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l%c'):format(i, i)
end
local changes = {}
for i = 1, 100 do
- changes[i] = {line=i}
+ changes[i] = { line = i }
end
for i = 1, 101 do
local t = i * 2
- changes[(t > #changes + 1) and (#changes + 1) or t] = {line=t}
+ changes[(t > #changes + 1) and (#changes + 1) or t] = { line = t }
end
wshada(shada)
eq(0, exc_exec('wshada ' .. shada_fname))
local shift = #changes - 100
- for i = 1,100 do
+ for i = 1, 100 do
changes[i] = changes[i + shift]
end
local found = 0
diff --git a/test/functional/shada/registers_spec.lua b/test/functional/shada/registers_spec.lua
index 6aaa54cce8..ef15ab9a05 100644
--- a/test/functional/shada/registers_spec.lua
+++ b/test/functional/shada/registers_spec.lua
@@ -1,6 +1,6 @@
-- ShaDa registers saving/reading support
local helpers = require('test.functional.helpers')(after_each)
-local nvim_command, funcs, eq = helpers.command, helpers.funcs, helpers.eq
+local nvim_command, fn, eq = helpers.command, helpers.fn, helpers.eq
local shada_helpers = require('test.functional.shada.helpers')
local reset, clear = shada_helpers.reset, shada_helpers.clear
@@ -8,15 +8,15 @@ local expect_exit = helpers.expect_exit
local setreg = function(name, contents, typ)
if type(contents) == 'string' then
- contents = {contents}
+ contents = { contents }
end
- funcs.setreg(name, contents, typ)
+ fn.setreg(name, contents, typ)
end
local getreg = function(name)
return {
- funcs.getreg(name, 1, 1),
- funcs.getregtype(name),
+ fn.getreg(name, 1, 1),
+ fn.getregtype(name),
}
end
@@ -25,159 +25,154 @@ describe('ShaDa support code', function()
after_each(clear)
it('is able to dump and restore registers and their type', function()
- setreg('c', {'d', 'e', ''}, 'c')
- setreg('l', {'a', 'b', 'cde'}, 'l')
- setreg('b', {'bca', 'abc', 'cba'}, 'b3')
+ setreg('c', { 'd', 'e', '' }, 'c')
+ setreg('l', { 'a', 'b', 'cde' }, 'l')
+ setreg('b', { 'bca', 'abc', 'cba' }, 'b3')
expect_exit(nvim_command, 'qall')
reset()
- eq({{'d', 'e', ''}, 'v'}, getreg('c'))
- eq({{'a', 'b', 'cde'}, 'V'}, getreg('l'))
- eq({{'bca', 'abc', 'cba'}, '\0223'}, getreg('b'))
+ eq({ { 'd', 'e', '' }, 'v' }, getreg('c'))
+ eq({ { 'a', 'b', 'cde' }, 'V' }, getreg('l'))
+ eq({ { 'bca', 'abc', 'cba' }, '\0223' }, getreg('b'))
end)
it('does not dump registers with zero <', function()
- nvim_command('set shada=\'0,<0')
- setreg('c', {'d', 'e', ''}, 'c')
- setreg('l', {'a', 'b', 'cde'}, 'l')
- setreg('b', {'bca', 'abc', 'cba'}, 'b3')
+ nvim_command("set shada='0,<0")
+ setreg('c', { 'd', 'e', '' }, 'c')
+ setreg('l', { 'a', 'b', 'cde' }, 'l')
+ setreg('b', { 'bca', 'abc', 'cba' }, 'b3')
expect_exit(nvim_command, 'qall')
reset()
- eq({{}, ''}, getreg('c'))
- eq({{}, ''}, getreg('l'))
- eq({{}, ''}, getreg('b'))
+ eq({ {}, '' }, getreg('c'))
+ eq({ {}, '' }, getreg('l'))
+ eq({ {}, '' }, getreg('b'))
end)
it('does restore registers with zero <', function()
- setreg('c', {'d', 'e', ''}, 'c')
- setreg('l', {'a', 'b', 'cde'}, 'l')
- setreg('b', {'bca', 'abc', 'cba'}, 'b3')
+ setreg('c', { 'd', 'e', '' }, 'c')
+ setreg('l', { 'a', 'b', 'cde' }, 'l')
+ setreg('b', { 'bca', 'abc', 'cba' }, 'b3')
expect_exit(nvim_command, 'qall')
- reset('set shada=\'0,<0')
- eq({{'d', 'e', ''}, 'v'}, getreg('c'))
- eq({{'a', 'b', 'cde'}, 'V'}, getreg('l'))
- eq({{'bca', 'abc', 'cba'}, '\0223'}, getreg('b'))
+ reset("set shada='0,<0")
+ eq({ { 'd', 'e', '' }, 'v' }, getreg('c'))
+ eq({ { 'a', 'b', 'cde' }, 'V' }, getreg('l'))
+ eq({ { 'bca', 'abc', 'cba' }, '\0223' }, getreg('b'))
end)
it('does not dump registers with zero "', function()
nvim_command('set shada=\'0,\\"0')
- setreg('c', {'d', 'e', ''}, 'c')
- setreg('l', {'a', 'b', 'cde'}, 'l')
- setreg('b', {'bca', 'abc', 'cba'}, 'b3')
+ setreg('c', { 'd', 'e', '' }, 'c')
+ setreg('l', { 'a', 'b', 'cde' }, 'l')
+ setreg('b', { 'bca', 'abc', 'cba' }, 'b3')
expect_exit(nvim_command, 'qall')
reset()
- eq({{}, ''}, getreg('c'))
- eq({{}, ''}, getreg('l'))
- eq({{}, ''}, getreg('b'))
+ eq({ {}, '' }, getreg('c'))
+ eq({ {}, '' }, getreg('l'))
+ eq({ {}, '' }, getreg('b'))
end)
it('does restore registers with zero "', function()
- setreg('c', {'d', 'e', ''}, 'c')
- setreg('l', {'a', 'b', 'cde'}, 'l')
- setreg('b', {'bca', 'abc', 'cba'}, 'b3')
+ setreg('c', { 'd', 'e', '' }, 'c')
+ setreg('l', { 'a', 'b', 'cde' }, 'l')
+ setreg('b', { 'bca', 'abc', 'cba' }, 'b3')
expect_exit(nvim_command, 'qall')
reset('set shada=\'0,\\"0')
- eq({{'d', 'e', ''}, 'v'}, getreg('c'))
- eq({{'a', 'b', 'cde'}, 'V'}, getreg('l'))
- eq({{'bca', 'abc', 'cba'}, '\0223'}, getreg('b'))
+ eq({ { 'd', 'e', '' }, 'v' }, getreg('c'))
+ eq({ { 'a', 'b', 'cde' }, 'V' }, getreg('l'))
+ eq({ { 'bca', 'abc', 'cba' }, '\0223' }, getreg('b'))
end)
it('does dump registers with zero ", but non-zero <', function()
nvim_command('set shada=\'0,\\"0,<50')
- setreg('c', {'d', 'e', ''}, 'c')
- setreg('l', {'a', 'b', 'cde'}, 'l')
- setreg('b', {'bca', 'abc', 'cba'}, 'b3')
+ setreg('c', { 'd', 'e', '' }, 'c')
+ setreg('l', { 'a', 'b', 'cde' }, 'l')
+ setreg('b', { 'bca', 'abc', 'cba' }, 'b3')
expect_exit(nvim_command, 'qall')
reset()
- eq({{'d', 'e', ''}, 'v'}, getreg('c'))
- eq({{'a', 'b', 'cde'}, 'V'}, getreg('l'))
- eq({{'bca', 'abc', 'cba'}, '\0223'}, getreg('b'))
+ eq({ { 'd', 'e', '' }, 'v' }, getreg('c'))
+ eq({ { 'a', 'b', 'cde' }, 'V' }, getreg('l'))
+ eq({ { 'bca', 'abc', 'cba' }, '\0223' }, getreg('b'))
end)
it('does limit number of lines according to <', function()
- nvim_command('set shada=\'0,<2')
- setreg('o', {'d'}, 'c')
- setreg('t', {'a', 'b', 'cde'}, 'l')
+ nvim_command("set shada='0,<2")
+ setreg('o', { 'd' }, 'c')
+ setreg('t', { 'a', 'b', 'cde' }, 'l')
expect_exit(nvim_command, 'qall')
reset()
- eq({{'d'}, 'v'}, getreg('o'))
- eq({{}, ''}, getreg('t'))
+ eq({ { 'd' }, 'v' }, getreg('o'))
+ eq({ {}, '' }, getreg('t'))
end)
it('does limit number of lines according to "', function()
nvim_command('set shada=\'0,\\"2')
- setreg('o', {'d'}, 'c')
- setreg('t', {'a', 'b', 'cde'}, 'l')
+ setreg('o', { 'd' }, 'c')
+ setreg('t', { 'a', 'b', 'cde' }, 'l')
expect_exit(nvim_command, 'qall')
reset()
- eq({{'d'}, 'v'}, getreg('o'))
- eq({{}, ''}, getreg('t'))
+ eq({ { 'd' }, 'v' }, getreg('o'))
+ eq({ {}, '' }, getreg('t'))
end)
it('does limit number of lines according to < rather then "', function()
nvim_command('set shada=\'0,\\"2,<3')
- setreg('o', {'d'}, 'c')
- setreg('t', {'a', 'b', 'cde'}, 'l')
- setreg('h', {'abc', 'acb', 'bac', 'bca', 'cab', 'cba'}, 'b3')
+ setreg('o', { 'd' }, 'c')
+ setreg('t', { 'a', 'b', 'cde' }, 'l')
+ setreg('h', { 'abc', 'acb', 'bac', 'bca', 'cab', 'cba' }, 'b3')
expect_exit(nvim_command, 'qall')
reset()
- eq({{'d'}, 'v'}, getreg('o'))
- eq({{'a', 'b', 'cde'}, 'V'}, getreg('t'))
- eq({{}, ''}, getreg('h'))
+ eq({ { 'd' }, 'v' }, getreg('o'))
+ eq({ { 'a', 'b', 'cde' }, 'V' }, getreg('t'))
+ eq({ {}, '' }, getreg('h'))
end)
- it('dumps and loads register correctly with utf-8 contents',
- function()
+ it('dumps and loads register correctly with utf-8 contents', function()
reset()
- setreg('e', {'«'}, 'c')
+ setreg('e', { '«' }, 'c')
expect_exit(nvim_command, 'qall')
reset()
- eq({{'«'}, 'v'}, getreg('e'))
+ eq({ { '«' }, 'v' }, getreg('e'))
end)
- it('dumps and loads history correctly with 8-bit single-byte',
- function()
+ it('dumps and loads history correctly with 8-bit single-byte', function()
reset()
-- \171 is U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK in latin1
- setreg('e', {'\171«'}, 'c')
+ setreg('e', { '\171«' }, 'c')
expect_exit(nvim_command, 'qall')
reset()
- eq({{'\171«'}, 'v'}, getreg('e'))
+ eq({ { '\171«' }, 'v' }, getreg('e'))
end)
- it('has a blank unnamed register if it wasn\'t set and register 0 is empty',
- function()
- setreg('1', {'one'}, 'c')
- setreg('2', {'two'}, 'c')
- setreg('a', {'a'}, 'c')
+ it("has a blank unnamed register if it wasn't set and register 0 is empty", function()
+ setreg('1', { 'one' }, 'c')
+ setreg('2', { 'two' }, 'c')
+ setreg('a', { 'a' }, 'c')
expect_exit(nvim_command, 'qall')
reset()
- eq({{}, ''}, getreg('0'))
- eq({{'one'}, 'v'}, getreg('1'))
- eq({{}, ''}, getreg('"'))
- eq({{'a'}, 'v'}, getreg('a'))
+ eq({ {}, '' }, getreg('0'))
+ eq({ { 'one' }, 'v' }, getreg('1'))
+ eq({ {}, '' }, getreg('"'))
+ eq({ { 'a' }, 'v' }, getreg('a'))
end)
- it('defaults the unnamed register to register 0 if it wasn\'t set',
- function()
- setreg('0', {'zero'}, 'c')
- setreg('1', {'one'}, 'c')
- setreg('2', {'two'}, 'c')
+ it("defaults the unnamed register to register 0 if it wasn't set", function()
+ setreg('0', { 'zero' }, 'c')
+ setreg('1', { 'one' }, 'c')
+ setreg('2', { 'two' }, 'c')
expect_exit(nvim_command, 'qall')
reset()
- eq({{'zero'}, 'v'}, getreg('0'))
- eq({{'one'}, 'v'}, getreg('1'))
- eq({{'zero'}, 'v'}, getreg('"'))
+ eq({ { 'zero' }, 'v' }, getreg('0'))
+ eq({ { 'one' }, 'v' }, getreg('1'))
+ eq({ { 'zero' }, 'v' }, getreg('"'))
end)
- it('remembers which register was the unnamed register when loading',
- function()
- setreg('0', {'zero'}, 'c')
- setreg('1', {'one'}, 'cu')
- setreg('2', {'two'}, 'c')
+ it('remembers which register was the unnamed register when loading', function()
+ setreg('0', { 'zero' }, 'c')
+ setreg('1', { 'one' }, 'cu')
+ setreg('2', { 'two' }, 'c')
expect_exit(nvim_command, 'qall')
reset()
- eq({{'zero'}, 'v'}, getreg('0'))
- eq({{'one'}, 'v'}, getreg('1'))
- eq({{'one'}, 'v'}, getreg('"'))
+ eq({ { 'zero' }, 'v' }, getreg('0'))
+ eq({ { 'one' }, 'v' }, getreg('1'))
+ eq({ { 'one' }, 'v' }, getreg('"'))
end)
end)
diff --git a/test/functional/shada/shada_spec.lua b/test/functional/shada/shada_spec.lua
index 3a3238eb34..6eb318015d 100644
--- a/test/functional/shada/shada_spec.lua
+++ b/test/functional/shada/shada_spec.lua
@@ -1,25 +1,20 @@
-- Other ShaDa tests
local helpers = require('test.functional.helpers')(after_each)
-local meths, nvim_command, funcs, eq =
- helpers.meths, helpers.command, helpers.funcs, helpers.eq
+local api, nvim_command, fn, eq = helpers.api, helpers.command, helpers.fn, helpers.eq
local write_file, spawn, set_session, nvim_prog, exc_exec =
- helpers.write_file, helpers.spawn, helpers.set_session, helpers.nvim_prog,
- helpers.exc_exec
+ helpers.write_file, helpers.spawn, helpers.set_session, helpers.nvim_prog, helpers.exc_exec
local is_os = helpers.is_os
local skip = helpers.skip
-local luv = require('luv')
-local paths = require('test.cmakeconfig.paths')
-
-local mpack = require('mpack')
+local uv = vim.uv
+local paths = helpers.paths
local shada_helpers = require('test.functional.shada.helpers')
local reset, clear, get_shada_rw =
shada_helpers.reset, shada_helpers.clear, shada_helpers.get_shada_rw
local read_shada_file = shada_helpers.read_shada_file
-local wshada, _, shada_fname, clean =
- get_shada_rw('Xtest-functional-shada-shada.shada')
+local wshada, _, shada_fname, clean = get_shada_rw('Xtest-functional-shada-shada.shada')
local dirname = 'Xtest-functional-shada-shada.d'
local dirshada = dirname .. '/main.shada'
@@ -29,12 +24,16 @@ describe('ShaDa support code', function()
after_each(function()
clear()
clean()
- luv.fs_rmdir(dirname)
+ uv.fs_rmdir(dirname)
end)
it('preserves `s` item size limit with unknown entries', function()
- wshada('\100\000\207\000\000\000\000\000\000\004\000\218\003\253' .. ('-'):rep(1024 - 3)
- .. '\100\000\207\000\000\000\000\000\000\004\001\218\003\254' .. ('-'):rep(1025 - 3))
+ wshada(
+ '\100\000\207\000\000\000\000\000\000\004\000\218\003\253'
+ .. ('-'):rep(1024 - 3)
+ .. '\100\000\207\000\000\000\000\000\000\004\001\218\003\254'
+ .. ('-'):rep(1025 - 3)
+ )
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -58,8 +57,8 @@ describe('ShaDa support code', function()
local hist1 = ('-'):rep(1024 - 5)
local hist2 = ('-'):rep(1025 - 5)
nvim_command('set shada-=s10 shada+=s1')
- funcs.histadd(':', hist1)
- funcs.histadd(':', hist2)
+ fn.histadd(':', hist1)
+ fn.histadd(':', hist2)
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -73,35 +72,53 @@ describe('ShaDa support code', function()
it('leaves .tmp.a in-place when there is error in original ShaDa', function()
wshada('Some text file')
- eq('Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', exc_exec('wshada ' .. shada_fname))
+ eq(
+ 'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier',
+ exc_exec('wshada ' .. shada_fname)
+ )
eq(1, read_shada_file(shada_fname .. '.tmp.a')[1].type)
end)
- it('does not leave .tmp.a in-place when there is error in original ShaDa, but writing with bang', function()
- wshada('Some text file')
- eq(0, exc_exec('wshada! ' .. shada_fname))
- eq(1, read_shada_file(shada_fname)[1].type)
- eq(nil, luv.fs_stat(shada_fname .. '.tmp.a'))
- end)
+ it(
+ 'does not leave .tmp.a in-place when there is error in original ShaDa, but writing with bang',
+ function()
+ wshada('Some text file')
+ eq(0, exc_exec('wshada! ' .. shada_fname))
+ eq(1, read_shada_file(shada_fname)[1].type)
+ eq(nil, uv.fs_stat(shada_fname .. '.tmp.a'))
+ end
+ )
it('leaves .tmp.b in-place when there is error in original ShaDa and it has .tmp.a', function()
wshada('Some text file')
- eq('Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', exc_exec('wshada ' .. shada_fname))
- eq('Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', exc_exec('wshada ' .. shada_fname))
+ eq(
+ 'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier',
+ exc_exec('wshada ' .. shada_fname)
+ )
+ eq(
+ 'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier',
+ exc_exec('wshada ' .. shada_fname)
+ )
eq(1, read_shada_file(shada_fname .. '.tmp.a')[1].type)
eq(1, read_shada_file(shada_fname .. '.tmp.b')[1].type)
end)
- it('leaves .tmp.z in-place when there is error in original ShaDa and it has .tmp.a … .tmp.x', function()
- wshada('Some text file')
- local i = ('a'):byte()
- while i < ('z'):byte() do
- write_file(shada_fname .. ('.tmp.%c'):format(i), 'Some text file', true)
- i = i + 1
+ it(
+ 'leaves .tmp.z in-place when there is error in original ShaDa and it has .tmp.a … .tmp.x',
+ function()
+ wshada('Some text file')
+ local i = ('a'):byte()
+ while i < ('z'):byte() do
+ write_file(shada_fname .. ('.tmp.%c'):format(i), 'Some text file', true)
+ i = i + 1
+ end
+ eq(
+ 'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier',
+ exc_exec('wshada ' .. shada_fname)
+ )
+ eq(1, read_shada_file(shada_fname .. '.tmp.z')[1].type)
end
- eq('Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', exc_exec('wshada ' .. shada_fname))
- eq(1, read_shada_file(shada_fname .. '.tmp.z')[1].type)
- end)
+ )
it('errors out when there are .tmp.a … .tmp.z ShaDa files', function()
wshada('')
@@ -110,33 +127,36 @@ describe('ShaDa support code', function()
write_file(shada_fname .. ('.tmp.%c'):format(i), '', true)
i = i + 1
end
- eq('Vim(wshada):E138: All Xtest-functional-shada-shada.shada.tmp.X files exist, cannot write ShaDa file!', exc_exec('wshada ' .. shada_fname))
+ eq(
+ 'Vim(wshada):E138: All Xtest-functional-shada-shada.shada.tmp.X files exist, cannot write ShaDa file!',
+ exc_exec('wshada ' .. shada_fname)
+ )
end)
it('reads correctly various timestamps', function()
local msgpack = {
- '\100', -- Positive fixnum 100
- '\204\255', -- uint 8 255
- '\205\010\003', -- uint 16 2563
- '\206\255\010\030\004', -- uint 32 4278853124
- '\207\005\100\060\250\255\010\030\004', -- uint 64 388502516579048964
+ '\100', -- Positive fixnum 100
+ '\204\255', -- uint 8 255
+ '\205\010\003', -- uint 16 2563
+ '\206\255\010\030\004', -- uint 32 4278853124
+ '\207\005\100\060\250\255\010\030\004', -- uint 64 388502516579048964
}
local s = '\100'
local e = '\001\192'
wshada(s .. table.concat(msgpack, e .. s) .. e)
eq(0, exc_exec('wshada ' .. shada_fname))
local found = 0
- local typ = mpack.decode(s)
+ local typ = vim.mpack.decode(s)
for _, v in ipairs(read_shada_file(shada_fname)) do
if v.type == typ then
found = found + 1
- eq(mpack.decode(msgpack[found]), v.timestamp)
+ eq(vim.mpack.decode(msgpack[found]), v.timestamp)
end
end
eq(#msgpack, found)
end)
- local marklike = {[7]=true, [8]=true, [10]=true, [11]=true}
+ local marklike = { [7] = true, [8] = true, [10] = true, [11] = true }
local find_file = function(fname)
local found = {}
for _, v in ipairs(read_shada_file(shada_fname)) do
@@ -155,7 +175,7 @@ describe('ShaDa support code', function()
it('correctly uses shada-r option', function()
nvim_command('set shellslash')
- meths.set_var('__home', paths.test_source_path)
+ api.nvim_set_var('__home', paths.test_source_path)
nvim_command('let $HOME = __home')
nvim_command('unlet __home')
nvim_command('edit ~/README.md')
@@ -163,104 +183,107 @@ describe('ShaDa support code', function()
nvim_command('undo')
nvim_command('set shada+=%')
nvim_command('wshada! ' .. shada_fname)
- local readme_fname = funcs.resolve(paths.test_source_path) .. '/README.md'
- eq({[7]=2, [8]=2, [9]=1, [10]=4, [11]=1}, find_file(readme_fname))
+ local readme_fname = fn.resolve(paths.test_source_path) .. '/README.md'
+ eq({ [7] = 2, [8] = 2, [9] = 1, [10] = 4, [11] = 1 }, find_file(readme_fname))
nvim_command('set shada+=r~')
nvim_command('wshada! ' .. shada_fname)
eq({}, find_file(readme_fname))
nvim_command('set shada-=r~')
nvim_command('wshada! ' .. shada_fname)
- eq({[7]=2, [8]=2, [9]=1, [10]=4, [11]=1}, find_file(readme_fname))
- nvim_command('set shada+=r' .. funcs.escape(
- funcs.escape(paths.test_source_path, '$~'), ' "\\,'))
+ eq({ [7] = 2, [8] = 2, [9] = 1, [10] = 4, [11] = 1 }, find_file(readme_fname))
+ nvim_command('set shada+=r' .. fn.escape(fn.escape(paths.test_source_path, '$~'), ' "\\,'))
nvim_command('wshada! ' .. shada_fname)
eq({}, find_file(readme_fname))
end)
it('correctly ignores case with shada-r option', function()
nvim_command('set shellslash')
- local pwd = funcs.getcwd()
+ local pwd = fn.getcwd()
local relfname = 'абв/test'
local fname = pwd .. '/' .. relfname
- meths.set_var('__fname', fname)
+ api.nvim_set_var('__fname', fname)
nvim_command('silent! edit `=__fname`')
- funcs.setline(1, {'a', 'b', 'c', 'd'})
+ fn.setline(1, { 'a', 'b', 'c', 'd' })
nvim_command('normal! GmAggmaAabc')
nvim_command('undo')
nvim_command('set shada+=%')
nvim_command('wshada! ' .. shada_fname)
- eq({[7]=2, [8]=2, [9]=1, [10]=4, [11]=2}, find_file(fname))
+ eq({ [7] = 2, [8] = 2, [9] = 1, [10] = 4, [11] = 2 }, find_file(fname))
nvim_command('set shada+=r' .. pwd .. '/ÐБВ')
nvim_command('wshada! ' .. shada_fname)
eq({}, find_file(fname))
end)
it('is able to set &shada after &viminfo', function()
- 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', {}))
+ api.nvim_set_option_value('viminfo', "'10", {})
+ eq("'10", api.nvim_get_option_value('viminfo', {}))
+ eq("'10", api.nvim_get_option_value('shada', {}))
+ api.nvim_set_option_value('shada', '', {})
+ eq('', api.nvim_get_option_value('viminfo', {}))
+ eq('', api.nvim_get_option_value('shada', {}))
end)
it('is able to set all& after setting &shada', function()
- meths.set_option_value('shada', '\'10', {})
- eq('\'10', meths.get_option_value('viminfo', {}))
- eq('\'10', meths.get_option_value('shada', {}))
+ api.nvim_set_option_value('shada', "'10", {})
+ eq("'10", api.nvim_get_option_value('viminfo', {}))
+ eq("'10", api.nvim_get_option_value('shada', {}))
nvim_command('set all&')
- eq('!,\'100,<50,s10,h', meths.get_option_value('viminfo', {}))
- eq('!,\'100,<50,s10,h', meths.get_option_value('shada', {}))
+ eq("!,'100,<50,s10,h", api.nvim_get_option_value('viminfo', {}))
+ eq("!,'100,<50,s10,h", api.nvim_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_value('viminfo', {}))
- eq('\'10', meths.get_option_value('shada', {}))
+ nvim_command("set viminfo='10")
+ eq("'10", api.nvim_get_option_value('viminfo', {}))
+ eq("'10", api.nvim_get_option_value('shada', {}))
nvim_command('set shada=')
- eq('', meths.get_option_value('viminfo', {}))
- eq('', meths.get_option_value('shada', {}))
+ eq('', api.nvim_get_option_value('viminfo', {}))
+ eq('', api.nvim_get_option_value('shada', {}))
end)
it('setting &shada gives proper error message on missing number', function()
- eq([[Vim(set):E526: Missing number after <">: shada="]],
- exc_exec([[set shada=\"]]))
- for _, c in ipairs({"'", "/", ":", "<", "@", "s"}) do
- eq(([[Vim(set):E526: Missing number after <%s>: shada=%s]]):format(c, c),
- exc_exec(([[set shada=%s]]):format(c)))
+ eq([[Vim(set):E526: Missing number after <">: shada="]], exc_exec([[set shada=\"]]))
+ for _, c in ipairs({ "'", '/', ':', '<', '@', 's' }) do
+ eq(
+ ([[Vim(set):E526: Missing number after <%s>: shada=%s]]):format(c, c),
+ exc_exec(([[set shada=%s]]):format(c))
+ )
end
end)
it('does not crash when ShaDa file directory is not writable', function()
skip(is_os('win'))
- funcs.mkdir(dirname, '', 0)
- eq(0, funcs.filewritable(dirname))
- reset{shadafile=dirshada, args={'--cmd', 'set shada='}}
- 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_value('shada', '', {})
+ fn.mkdir(dirname, '', 0)
+ eq(0, fn.filewritable(dirname))
+ reset { shadafile = dirshada, args = { '--cmd', 'set shada=' } }
+ api.nvim_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')
+ )
+ api.nvim_set_option_value('shada', '', {})
end)
end)
describe('ShaDa support code', function()
it('does not write NONE file', function()
- local session = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed',
- '--headless', '--cmd', 'qall'}, true)
+ local session = spawn(
+ { nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed', '--headless', '--cmd', 'qall' },
+ true
+ )
session:close()
- eq(nil, luv.fs_stat('NONE'))
- eq(nil, luv.fs_stat('NONE.tmp.a'))
+ eq(nil, uv.fs_stat('NONE'))
+ eq(nil, uv.fs_stat('NONE.tmp.a'))
end)
it('does not read NONE file', function()
write_file('NONE', '\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
- local session = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed',
- '--headless'}, true)
+ local session = spawn({ nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed', '--headless' }, true)
set_session(session)
- eq('', funcs.getreg('a'))
+ eq('', fn.getreg('a'))
session:close()
os.remove('NONE')
end)
diff --git a/test/functional/shada/variables_spec.lua b/test/functional/shada/variables_spec.lua
index a91b7eb193..d70f5deded 100644
--- a/test/functional/shada/variables_spec.lua
+++ b/test/functional/shada/variables_spec.lua
@@ -1,7 +1,7 @@
-- ShaDa variables saving/reading support
local helpers = require('test.functional.helpers')(after_each)
-local meths, funcs, nvim_command, eq, eval =
- helpers.meths, helpers.funcs, helpers.command, helpers.eq, helpers.eval
+local api, fn, nvim_command, eq, eval =
+ helpers.api, helpers.fn, helpers.command, helpers.eq, helpers.eval
local expect_exit = helpers.expect_exit
local shada_helpers = require('test.functional.shada.helpers')
@@ -12,24 +12,23 @@ describe('ShaDa support code', function()
after_each(clear)
it('is able to dump and read back string variable', function()
- meths.set_var('STRVAR', 'foo')
+ api.nvim_set_var('STRVAR', 'foo')
nvim_command('set shada+=!')
nvim_command('wshada')
reset()
nvim_command('set shada+=!')
nvim_command('rshada')
- eq('foo', meths.get_var('STRVAR'))
+ eq('foo', api.nvim_get_var('STRVAR'))
end)
local autotest = function(tname, varname, varval, val_is_expr)
- it('is able to dump and read back ' .. tname .. ' variable automatically',
- function()
+ it('is able to dump and read back ' .. tname .. ' variable automatically', function()
reset('set shada+=!')
if val_is_expr then
nvim_command('let g:' .. varname .. ' = ' .. varval)
- varval = meths.get_var(varname)
+ varval = api.nvim_get_var(varname)
else
- meths.set_var(varname, varval)
+ api.nvim_set_var(varname, varval)
end
local vartype = eval('type(g:' .. varname .. ')')
-- Exit during `reset` is not a regular exit: it does not write shada
@@ -37,15 +36,15 @@ describe('ShaDa support code', function()
expect_exit(nvim_command, 'qall')
reset('set shada+=!')
eq(vartype, eval('type(g:' .. varname .. ')'))
- eq(varval, meths.get_var(varname))
+ eq(varval, api.nvim_get_var(varname))
end)
end
autotest('string', 'STRVAR', 'foo')
autotest('number', 'NUMVAR', 42)
autotest('float', 'FLTVAR', 42.5)
- autotest('dictionary', 'DCTVAR', {a=10})
- autotest('list', 'LSTVAR', {{a=10}, {b=10.5}, {c='str'}})
+ autotest('dictionary', 'DCTVAR', { a = 10 })
+ autotest('list', 'LSTVAR', { { a = 10 }, { b = 10.5 }, { c = 'str' } })
autotest('true', 'TRUEVAR', true)
autotest('false', 'FALSEVAR', false)
autotest('null', 'NULLVAR', 'v:null', true)
@@ -54,111 +53,110 @@ describe('ShaDa support code', function()
autotest('blob (with NULs)', 'BLOBVARNULS', '0z004e554c7300', true)
it('does not read back variables without `!` in &shada', function()
- meths.set_var('STRVAR', 'foo')
+ api.nvim_set_var('STRVAR', 'foo')
nvim_command('set shada+=!')
nvim_command('wshada')
reset('set shada-=!')
nvim_command('rshada')
- eq(0, funcs.exists('g:STRVAR'))
+ eq(0, fn.exists('g:STRVAR'))
end)
it('does not dump variables without `!` in &shada', function()
nvim_command('set shada-=!')
- meths.set_var('STRVAR', 'foo')
+ api.nvim_set_var('STRVAR', 'foo')
nvim_command('wshada')
reset()
nvim_command('set shada+=!')
nvim_command('rshada')
- eq(0, funcs.exists('g:STRVAR'))
+ eq(0, fn.exists('g:STRVAR'))
end)
it('does not dump session variables', function()
nvim_command('set shada+=!')
- meths.set_var('StrVar', 'foo')
+ api.nvim_set_var('StrVar', 'foo')
nvim_command('wshada')
reset()
nvim_command('set shada+=!')
nvim_command('rshada')
- eq(0, funcs.exists('g:StrVar'))
+ eq(0, fn.exists('g:StrVar'))
end)
it('does not dump regular variables', function()
nvim_command('set shada+=!')
- meths.set_var('str_var', 'foo')
+ api.nvim_set_var('str_var', 'foo')
nvim_command('wshada')
reset()
nvim_command('set shada+=!')
nvim_command('rshada')
- eq(0, funcs.exists('g:str_var'))
+ eq(0, fn.exists('g:str_var'))
end)
- it('dumps and loads variables correctly with utf-8 strings',
- function()
+ it('dumps and loads variables correctly with utf-8 strings', function()
reset()
- meths.set_var('STRVAR', '«')
- meths.set_var('LSTVAR', {'«'})
- meths.set_var('DCTVAR', {['«']='«'})
- meths.set_var('NESTEDVAR', {['«']={{'«'}, {['«']='«'}, {a='Test'}}})
+ api.nvim_set_var('STRVAR', '«')
+ api.nvim_set_var('LSTVAR', { '«' })
+ api.nvim_set_var('DCTVAR', { ['«'] = '«' })
+ api.nvim_set_var('NESTEDVAR', { ['«'] = { { '«' }, { ['«'] = '«' }, { a = 'Test' } } })
expect_exit(nvim_command, 'qall')
reset()
- eq('«', meths.get_var('STRVAR'))
- eq({'«'}, meths.get_var('LSTVAR'))
- eq({['«']='«'}, meths.get_var('DCTVAR'))
- eq({['«']={{'«'}, {['«']='«'}, {a='Test'}}}, meths.get_var('NESTEDVAR'))
+ eq('«', api.nvim_get_var('STRVAR'))
+ eq({ '«' }, api.nvim_get_var('LSTVAR'))
+ eq({ ['«'] = '«' }, api.nvim_get_var('DCTVAR'))
+ eq({ ['«'] = { { '«' }, { ['«'] = '«' }, { a = 'Test' } } }, api.nvim_get_var('NESTEDVAR'))
end)
- it('dumps and loads variables correctly with 8-bit strings',
- function()
+ it('dumps and loads variables correctly with 8-bit strings', function()
reset()
-- \171 is U+00AB LEFT-POINTING DOUBLE ANGLE QUOTATION MARK in latin1
-- This is invalid unicode, but we should still dump and restore it.
- meths.set_var('STRVAR', '\171')
- meths.set_var('LSTVAR', {'\171'})
- meths.set_var('DCTVAR', {['«\171']='«\171'})
- meths.set_var('NESTEDVAR', {['\171']={{'\171«'}, {['\171']='\171'},
- {a='Test'}}})
+ api.nvim_set_var('STRVAR', '\171')
+ api.nvim_set_var('LSTVAR', { '\171' })
+ api.nvim_set_var('DCTVAR', { ['«\171'] = '«\171' })
+ api.nvim_set_var(
+ 'NESTEDVAR',
+ { ['\171'] = { { '\171«' }, { ['\171'] = '\171' }, { a = 'Test' } } }
+ )
expect_exit(nvim_command, 'qall')
reset()
- eq('\171', meths.get_var('STRVAR'))
- eq({'\171'}, meths.get_var('LSTVAR'))
- eq({['«\171']='«\171'}, meths.get_var('DCTVAR'))
- eq({['\171']={{'\171«'}, {['\171']='\171'}, {a='Test'}}},
- meths.get_var('NESTEDVAR'))
+ eq('\171', api.nvim_get_var('STRVAR'))
+ eq({ '\171' }, api.nvim_get_var('LSTVAR'))
+ eq({ ['«\171'] = '«\171' }, api.nvim_get_var('DCTVAR'))
+ eq(
+ { ['\171'] = { { '\171«' }, { ['\171'] = '\171' }, { a = 'Test' } } },
+ api.nvim_get_var('NESTEDVAR')
+ )
end)
- it('ignore when a funcref is stored in a variable',
- function()
+ it('ignore when a funcref is stored in a variable', function()
nvim_command('let F = function("tr")')
- meths.set_var('U', '10')
+ api.nvim_set_var('U', '10')
nvim_command('set shada+=!')
nvim_command('wshada')
reset()
nvim_command('set shada+=!')
nvim_command('rshada')
- eq('10', meths.get_var('U'))
+ eq('10', api.nvim_get_var('U'))
end)
- it('ignore when a partial is stored in a variable',
- function()
+ it('ignore when a partial is stored in a variable', function()
nvim_command('let P = { -> 1 }')
- meths.set_var('U', '10')
+ api.nvim_set_var('U', '10')
nvim_command('set shada+=!')
nvim_command('wshada')
reset()
nvim_command('set shada+=!')
nvim_command('rshada')
- eq('10', meths.get_var('U'))
+ eq('10', api.nvim_get_var('U'))
end)
- it('ignore when a self-referencing list is stored in a variable',
- function()
- meths.set_var('L', {})
+ it('ignore when a self-referencing list is stored in a variable', function()
+ api.nvim_set_var('L', {})
nvim_command('call add(L, L)')
- meths.set_var('U', '10')
+ api.nvim_set_var('U', '10')
nvim_command('set shada+=!')
nvim_command('wshada')
reset()
nvim_command('rshada')
- eq('10', meths.get_var('U'))
+ eq('10', api.nvim_get_var('U'))
end)
end)
diff --git a/test/functional/terminal/altscreen_spec.lua b/test/functional/terminal/altscreen_spec.lua
index cbe5e06005..c3be9ec6ca 100644
--- a/test/functional/terminal/altscreen_spec.lua
+++ b/test/functional/terminal/altscreen_spec.lua
@@ -1,12 +1,14 @@
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
-local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf
+local clear, eq, api = helpers.clear, helpers.eq, helpers.api
local feed = helpers.feed
local feed_data = thelpers.feed_data
local enter_altscreen = thelpers.enter_altscreen
local exit_altscreen = thelpers.exit_altscreen
-if helpers.skip(helpers.is_os('win')) then return end
+if helpers.skip(helpers.is_os('win')) then
+ return
+end
describe(':terminal altscreen', function()
local screen
@@ -14,8 +16,17 @@ describe(':terminal altscreen', function()
before_each(function()
clear()
screen = thelpers.screen_setup()
- feed_data({'line1', 'line2', 'line3', 'line4', 'line5', 'line6',
- 'line7', 'line8', ''})
+ feed_data({
+ 'line1',
+ 'line2',
+ 'line3',
+ 'line4',
+ 'line5',
+ 'line6',
+ 'line7',
+ 'line8',
+ '',
+ })
screen:expect([[
line4 |
line5 |
@@ -27,15 +38,11 @@ describe(':terminal altscreen', function()
]])
enter_altscreen()
screen:expect([[
- |
- |
- |
- |
- |
+ |*5
{1: } |
{3:-- TERMINAL --} |
]])
- eq(10, curbuf('line_count'))
+ eq(10, api.nvim_buf_line_count(0))
end)
it('wont clear lines already in the scrollback', function()
@@ -45,9 +52,7 @@ describe(':terminal altscreen', function()
line1 |
line2 |
line3 |
- |
- |
- |
+ |*3
]])
end)
@@ -79,8 +84,17 @@ describe(':terminal altscreen', function()
describe('with lines printed after the screen height limit', function()
before_each(function()
- feed_data({'line9', 'line10', 'line11', 'line12', 'line13',
- 'line14', 'line15', 'line16', ''})
+ feed_data({
+ 'line9',
+ 'line10',
+ 'line11',
+ 'line12',
+ 'line13',
+ 'line14',
+ 'line15',
+ 'line16',
+ '',
+ })
screen:expect([[
line12 |
line13 |
@@ -93,7 +107,7 @@ describe(':terminal altscreen', function()
end)
it('wont modify line count', function()
- eq(10, curbuf('line_count'))
+ eq(10, api.nvim_buf_line_count(0))
end)
it('wont modify lines in the scrollback', function()
@@ -114,8 +128,7 @@ describe(':terminal altscreen', function()
local function wait_removal()
screen:try_resize(screen._width, screen._height - 2)
screen:expect([[
- |
- |
+ |*2
rows: 4, cols: 50 |
{1: } |
{3:-- TERMINAL --} |
@@ -127,12 +140,11 @@ describe(':terminal altscreen', function()
feed('<c-\\><c-n>4k')
screen:expect([[
^ |
- |
- |
+ |*2
rows: 4, cols: 50 |
|
]])
- eq(9, curbuf('line_count'))
+ eq(9, api.nvim_buf_line_count(0))
end)
describe('and after exit', function()
diff --git a/test/functional/terminal/api_spec.lua b/test/functional/terminal/api_spec.lua
index 93641fc576..79cc5016da 100644
--- a/test/functional/terminal/api_spec.lua
+++ b/test/functional/terminal/api_spec.lua
@@ -2,67 +2,70 @@ local helpers = require('test.functional.helpers')(after_each)
local child_session = require('test.functional.terminal.helpers')
local ok = helpers.ok
-if helpers.skip(helpers.is_os('win')) then return end
+if helpers.skip(helpers.is_os('win')) then
+ return
+end
describe('api', function()
local screen
- local socket_name = "./Xtest_functional_api.sock"
+ local socket_name = './Xtest_functional_api.sock'
before_each(function()
helpers.clear()
os.remove(socket_name)
- screen = child_session.screen_setup(0, '["'..helpers.nvim_prog
- ..'", "-u", "NONE", "-i", "NONE", "--cmd", "'..helpers.nvim_set..'"]')
+ screen = child_session.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ helpers.nvim_set .. ' notermguicolors',
+ })
end)
after_each(function()
os.remove(socket_name)
end)
- it("qa! RPC request during insert-mode", function()
- screen:expect{grid=[[
+ it('qa! RPC request during insert-mode', function()
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*4
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
-- Start the socket from the child nvim.
- child_session.feed_data(":echo serverstart('"..socket_name.."')\n")
+ child_session.feed_data(":echo serverstart('" .. socket_name .. "')\n")
-- Wait for socket creation.
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- ]]..socket_name..[[ |
+ {4:~ }|*4
+ ]] .. socket_name .. [[ |
{3:-- TERMINAL --} |
]])
local socket_session1 = helpers.connect(socket_name)
local socket_session2 = helpers.connect(socket_name)
- child_session.feed_data("i[tui] insert-mode")
+ child_session.feed_data('i[tui] insert-mode')
-- Wait for stdin to be processed.
screen:expect([[
[tui] insert-mode{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*4
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- ok((socket_session1:request("nvim_ui_attach", 42, 6, {rgb=true})))
- ok((socket_session2:request("nvim_ui_attach", 25, 30, {rgb=true})))
+ ok((socket_session1:request('nvim_ui_attach', 42, 6, { rgb = true })))
+ ok((socket_session2:request('nvim_ui_attach', 25, 30, { rgb = true })))
- socket_session1:notify("nvim_input", "\n[socket 1] this is more than 25 columns")
- socket_session2:notify("nvim_input", "\n[socket 2] input")
+ socket_session1:notify('nvim_input', '\n[socket 1] this is more than 25 columns')
+ socket_session2:notify('nvim_input', '\n[socket 2] input')
screen:expect([[
[tui] insert-mode |
@@ -74,6 +77,6 @@ describe('api', function()
{3:-- TERMINAL --} |
]])
- socket_session1:request("nvim_command", "qa!")
+ socket_session1:request('nvim_command', 'qa!')
end)
end)
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
index 6fcd029a5b..376b7b849e 100644
--- a/test/functional/terminal/buffer_spec.lua
+++ b/test/functional/terminal/buffer_spec.lua
@@ -1,23 +1,24 @@
local helpers = require('test.functional.helpers')(after_each)
+local Screen = require('test.functional.ui.screen')
local thelpers = require('test.functional.terminal.helpers')
local assert_alive = helpers.assert_alive
-local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
+local feed, clear = helpers.feed, helpers.clear
local poke_eventloop = helpers.poke_eventloop
+local nvim_prog = helpers.nvim_prog
local eval, feed_command, source = helpers.eval, helpers.feed_command, helpers.source
local pcall_err = helpers.pcall_err
local eq, neq = helpers.eq, helpers.neq
-local meths = helpers.meths
+local api = helpers.api
local retry = helpers.retry
local write_file = helpers.write_file
local command = helpers.command
local exc_exec = helpers.exc_exec
local matches = helpers.matches
local exec_lua = helpers.exec_lua
-local sleep = helpers.sleep
-local funcs = helpers.funcs
+local sleep = vim.uv.sleep
+local fn = helpers.fn
local is_os = helpers.is_os
local skip = helpers.skip
-local nvim_prog = helpers.nvim_prog
describe(':terminal buffer', function()
local screen
@@ -31,13 +32,19 @@ describe(':terminal buffer', function()
it('terminal-mode forces various options', function()
feed([[<C-\><C-N>]])
command('setlocal cursorline cursorlineopt=both cursorcolumn scrolloff=4 sidescrolloff=7')
- eq({ 'both', 1, 1, 4, 7 }, eval('[&l:cursorlineopt, &l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]'))
+ eq(
+ { 'both', 1, 1, 4, 7 },
+ eval('[&l:cursorlineopt, &l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]')
+ )
eq('nt', eval('mode(1)'))
-- Enter terminal-mode ("insert" mode in :terminal).
feed('i')
eq('t', eval('mode(1)'))
- eq({ 'number', 1, 0, 0, 0 }, eval('[&l:cursorlineopt, &l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]'))
+ eq(
+ { 'number', 1, 0, 0, 0 },
+ eval('[&l:cursorlineopt, &l:cursorline, &l:cursorcolumn, &l:scrolloff, &l:sidescrolloff]')
+ )
end)
it('terminal-mode does not change cursorlineopt if cursorline is disabled', function()
@@ -59,11 +66,7 @@ describe(':terminal buffer', function()
feed('<c-\\><c-n>:set bufhidden=wipe<cr>:enew<cr>')
screen:expect([[
^ |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*5
:enew |
]])
end)
@@ -72,11 +75,7 @@ describe(':terminal buffer', function()
feed(':bnext:l<esc>')
screen:expect([[
^ |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*5
|
]])
end)
@@ -88,21 +87,17 @@ describe(':terminal buffer', function()
screen:expect([[
tty ready |
{2:^ } |
- |
- |
- |
- |
- |
+ |*5
]])
end)
it('does not create swap files', function()
- local swapfile = nvim('exec', 'swapname', true):gsub('\n', '')
+ local swapfile = api.nvim_exec('swapname', true):gsub('\n', '')
eq(nil, io.open(swapfile))
end)
it('does not create undofiles files', function()
- local undofile = nvim('eval', 'undofile(bufname("%"))')
+ local undofile = api.nvim_eval('undofile(bufname("%"))')
eq(nil, io.open(undofile))
end)
end)
@@ -112,10 +107,7 @@ describe(':terminal buffer', function()
screen:expect([[
tty ready |
{2:^ } |
- |
- |
- |
- |
+ |*4
{8:E21: Cannot make changes, 'modifiable' is off} |
]])
end)
@@ -126,22 +118,16 @@ describe(':terminal buffer', function()
feed('"ap"ap')
screen:expect([[
^tty ready |
- appended tty ready |
- appended tty ready |
+ appended tty ready |*2
{2: } |
- |
- |
+ |*2
:let @a = "appended " . @a |
]])
-- operator count is also taken into consideration
feed('3"ap')
screen:expect([[
^tty ready |
- appended tty ready |
- appended tty ready |
- appended tty ready |
- appended tty ready |
- appended tty ready |
+ appended tty ready |*5
:let @a = "appended " . @a |
]])
end)
@@ -154,17 +140,14 @@ describe(':terminal buffer', function()
^tty ready |
appended tty ready |
{2: } |
- |
- |
- |
+ |*3
:put a |
]])
-- line argument is only used to move the cursor
feed_command('6put a')
screen:expect([[
tty ready |
- appended tty ready |
- appended tty ready |
+ appended tty ready |*2
{2: } |
|
^ |
@@ -176,34 +159,24 @@ describe(':terminal buffer', function()
feed('<c-\\><c-n>:bd!<cr>')
screen:expect([[
^ |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*5
:bd! |
]])
feed_command('bnext')
screen:expect([[
^ |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*5
:bnext |
]])
end)
it('handles loss of focus gracefully', function()
-- Change the statusline to avoid printing the file name, which varies.
- nvim('set_option_value', 'statusline', '==========', {})
+ api.nvim_set_option_value('statusline', '==========', {})
-- Save the buffer number of the terminal for later testing.
local tbuf = eval('bufnr("%")')
- local exitcmd = is_os('win')
- and "['cmd', '/c', 'exit']"
- or "['sh', '-c', 'exit']"
+ local exitcmd = is_os('win') and "['cmd', '/c', 'exit']" or "['sh', '-c', 'exit']"
source([[
function! SplitWindow(id, data, event)
new
@@ -211,7 +184,7 @@ describe(':terminal buffer', function()
endfunction
startinsert
- call jobstart(]]..exitcmd..[[, {'on_exit': function("SplitWindow")})
+ call jobstart(]] .. exitcmd .. [[, {'on_exit': function("SplitWindow")})
call feedkeys("\<C-\>", 't') " vim will expect <C-n>, but be exited out of
" the terminal before it can be entered.
]])
@@ -228,7 +201,7 @@ describe(':terminal buffer', function()
]])
neq(tbuf, eval('bufnr("%")'))
- feed_command('quit!') -- Should exit the new window, not the terminal.
+ feed_command('quit!') -- Should exit the new window, not the terminal.
eq(tbuf, eval('bufnr("%")'))
end)
@@ -243,46 +216,46 @@ describe(':terminal buffer', function()
feed_command('terminal')
feed('<c-\\><c-n>')
feed_command('confirm bdelete')
- screen:expect{any='Close "term://'}
+ screen:expect { any = 'Close "term://' }
end)
it('with &confirm', function()
feed_command('terminal')
feed('<c-\\><c-n>')
feed_command('bdelete')
- screen:expect{any='E89'}
+ screen:expect { any = 'E89' }
feed('<cr>')
eq('terminal', eval('&buftype'))
feed_command('set confirm | bdelete')
- screen:expect{any='Close "term://'}
+ screen:expect { any = 'Close "term://' }
feed('y')
neq('terminal', eval('&buftype'))
end)
end)
it('it works with set rightleft #11438', function()
- skip(is_os('win'))
local columns = eval('&columns')
feed(string.rep('a', columns))
command('set rightleft')
screen:expect([[
ydaer ytt|
{1:a}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- |
- |
- |
- |
+ |*4
{3:-- TERMINAL --} |
]])
command('bdelete!')
end)
it('requires bang (!) to close a running job #15402', function()
- skip(is_os('win'), "Test freezes the CI and makes it time out")
+ 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%)$',
- exc_exec(cmd))
+ matches(
+ '^Vim%('
+ .. cmd:gsub('%%', '')
+ .. '%):E89: term://.*tty%-test.* will be killed %(add %! to override%)$',
+ exc_exec(cmd)
+ )
end
command('call jobstop(&channel)')
assert(0 >= eval('jobwait([&channel], 1000)[0]'))
@@ -299,51 +272,97 @@ describe(':terminal buffer', function()
it('does not segfault when pasting empty register #13955', function()
feed('<c-\\><c-n>')
- feed_command('put a') -- register a is empty
+ feed_command('put a') -- register a is empty
helpers.assert_alive()
end)
it([[can use temporary normal mode <c-\><c-o>]], function()
- eq('t', funcs.mode(1))
+ eq('t', fn.mode(1))
feed [[<c-\><c-o>]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
tty ready |
{2:^ } |
- |
- |
- |
- |
+ |*4
{3:-- (terminal) --} |
- ]]}
- eq('ntT', funcs.mode(1))
+ ]],
+ }
+ eq('ntT', fn.mode(1))
feed [[:let g:x = 17]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
tty ready |
{2: } |
- |
- |
- |
- |
+ |*4
:let g:x = 17^ |
- ]]}
+ ]],
+ }
feed [[<cr>]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
tty ready |
{1: } |
- |
- |
- |
- |
+ |*4
{3:-- TERMINAL --} |
- ]]}
- eq('t', funcs.mode(1))
+ ]],
+ }
+ eq('t', fn.mode(1))
end)
it('writing to an existing file with :w fails #13549', function()
- eq('Vim(write):E13: File exists (add ! to override)',
- pcall_err(command, 'write test/functional/fixtures/tty-test.c'))
+ eq(
+ 'Vim(write):E13: File exists (add ! to override)',
+ pcall_err(command, 'write test/functional/fixtures/tty-test.c')
+ )
+ end)
+
+ it('emits TermRequest events #26972', function()
+ command('new')
+ local term = api.nvim_open_term(0, {})
+ local termbuf = api.nvim_get_current_buf()
+
+ -- Test that autocommand buffer is associated with the terminal buffer, not the current buffer
+ command('au TermRequest * let g:termbuf = +expand("<abuf>")')
+ command('wincmd p')
+
+ -- cwd will be inserted in a file URI, which cannot contain backs
+ local cwd = fn.getcwd():gsub('\\', '/')
+ local parent = cwd:match('^(.+/)')
+ local expected = '\027]7;file://host' .. parent
+ api.nvim_chan_send(term, string.format('%s\027\\', expected))
+ eq(expected, eval('v:termrequest'))
+ eq(termbuf, eval('g:termbuf'))
+ end)
+
+ it('TermReqeust synchronization #27572', function()
+ command('new')
+ command('autocmd! nvim_terminal TermRequest')
+ local term = exec_lua([[
+ _G.input = {}
+ local term = vim.api.nvim_open_term(0, {
+ on_input = function(_, _, _, data)
+ table.insert(_G.input, data)
+ end,
+ force_crlf = false,
+ })
+ vim.api.nvim_create_autocmd('TermRequest', {
+ callback = function(args)
+ if args.data == '\027]11;?' then
+ table.insert(_G.input, '\027]11;rgb:0000/0000/0000\027\\')
+ end
+ end
+ })
+ return term
+ ]])
+ api.nvim_chan_send(term, '\027]11;?\007\027[5n\027]11;?\007\027[5n')
+ eq({
+ '\027]11;rgb:0000/0000/0000\027\\',
+ '\027[0n',
+ '\027]11;rgb:0000/0000/0000\027\\',
+ '\027[0n',
+ }, exec_lua('return _G.input'))
end)
end)
@@ -351,7 +370,7 @@ describe('No heap-buffer-overflow when using', function()
local testfilename = 'Xtestfile-functional-terminal-buffers_spec'
before_each(function()
- write_file(testfilename, "aaaaaaaaaaaaaaaaaaaaaaaaaaaa")
+ write_file(testfilename, 'aaaaaaaaaaaaaaaaaaaaaaaaaaaa')
end)
after_each(function()
@@ -414,10 +433,12 @@ end)
it('terminal truncates number of composing characters to 5', function()
clear()
- local chan = meths.open_term(0, {})
+ local chan = api.nvim_open_term(0, {})
local composing = ('a̳'):sub(2)
- meths.chan_send(chan, 'a' .. composing:rep(8))
- retry(nil, nil, function() eq('a' .. composing:rep(5), meths.get_current_line()) end)
+ api.nvim_chan_send(chan, 'a' .. composing:rep(8))
+ retry(nil, nil, function()
+ eq('a' .. composing:rep(5), api.nvim_get_current_line())
+ end)
end)
describe('terminal input', function()
@@ -447,31 +468,80 @@ end)
describe('terminal input', function()
it('sends various special keys with modifiers', function()
clear()
- local screen = thelpers.screen_setup(0,
- string.format([=[["%s", "-u", "NONE", "-i", "NONE", "--cmd", "startinsert"]]=], nvim_prog))
- screen:expect{grid=[[
+ local screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ 'set notermguicolors',
+ '--cmd',
+ 'startinsert',
+ })
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] 0,1 All}|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
for _, key in ipairs({
- '<M-Tab>', '<M-CR>', '<M-Esc>',
- '<BS>', '<S-Tab>', '<Insert>', '<Del>', '<PageUp>', '<PageDown>',
- '<S-Up>', '<C-Up>', '<Up>', '<S-Down>', '<C-Down>', '<Down>',
- '<S-Left>', '<C-Left>', '<Left>', '<S-Right>', '<C-Right>', '<Right>',
- '<S-Home>', '<C-Home>', '<Home>', '<S-End>', '<C-End>', '<End>',
- '<C-LeftMouse>', '<C-LeftRelease>', '<2-LeftMouse>', '<2-LeftRelease>',
- '<S-RightMouse>', '<S-RightRelease>', '<2-RightMouse>', '<2-RightRelease>',
- '<M-MiddleMouse>', '<M-MiddleRelease>', '<2-MiddleMouse>', '<2-MiddleRelease>',
- '<S-ScrollWheelUp>', '<S-ScrollWheelDown>', '<ScrollWheelUp>', '<ScrollWheelDown>',
- '<S-ScrollWheelLeft>', '<S-ScrollWheelRight>', '<ScrollWheelLeft>', '<ScrollWheelRight>',
+ '<M-Tab>',
+ '<M-CR>',
+ '<M-Esc>',
+ '<BS>',
+ '<S-Tab>',
+ '<Insert>',
+ '<Del>',
+ '<PageUp>',
+ '<PageDown>',
+ '<S-Up>',
+ '<C-Up>',
+ '<Up>',
+ '<S-Down>',
+ '<C-Down>',
+ '<Down>',
+ '<S-Left>',
+ '<C-Left>',
+ '<Left>',
+ '<S-Right>',
+ '<C-Right>',
+ '<Right>',
+ '<S-Home>',
+ '<C-Home>',
+ '<Home>',
+ '<S-End>',
+ '<C-End>',
+ '<End>',
+ '<C-LeftMouse>',
+ '<C-LeftRelease>',
+ '<2-LeftMouse>',
+ '<2-LeftRelease>',
+ '<S-RightMouse>',
+ '<S-RightRelease>',
+ '<2-RightMouse>',
+ '<2-RightRelease>',
+ '<M-MiddleMouse>',
+ '<M-MiddleRelease>',
+ '<2-MiddleMouse>',
+ '<2-MiddleRelease>',
+ '<S-ScrollWheelUp>',
+ '<S-ScrollWheelDown>',
+ '<ScrollWheelUp>',
+ '<ScrollWheelDown>',
+ '<S-ScrollWheelLeft>',
+ '<S-ScrollWheelRight>',
+ '<ScrollWheelLeft>',
+ '<ScrollWheelRight>',
}) do
feed('<CR><C-V>' .. key)
- retry(nil, nil, function() eq(key, meths.get_current_line()) end)
+ retry(nil, nil, function()
+ eq(key, api.nvim_get_current_line())
+ end)
end
end)
end)
@@ -484,7 +554,7 @@ if is_os('win') then
clear()
feed_command('set modifiable swapfile undolevels=20')
poke_eventloop()
- local cmd = '["cmd.exe","/K","PROMPT=$g$s"]'
+ local cmd = { 'cmd.exe', '/K', 'PROMPT=$g$s' }
screen = thelpers.screen_setup(nil, cmd)
end)
@@ -549,11 +619,70 @@ describe('termopen()', function()
it('disallowed when textlocked and in cmdwin buffer', function()
command("autocmd TextYankPost <buffer> ++once call termopen('foo')")
- matches("Vim%(call%):E565: Not allowed to change text or change window$",
- pcall_err(command, "normal! yy"))
+ matches(
+ 'Vim%(call%):E565: Not allowed to change text or change window$',
+ pcall_err(command, 'normal! yy')
+ )
+
+ feed('q:')
+ eq(
+ 'Vim:E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
+ pcall_err(fn.termopen, 'bar')
+ )
+ end)
+
+ describe('$COLORTERM value', function()
+ if skip(is_os('win'), 'Not applicable for Windows') then
+ return
+ end
- feed("q:")
- eq("Vim:E11: Invalid in command-line window; <CR> executes, CTRL-C quits",
- pcall_err(funcs.termopen, "bar"))
+ before_each(function()
+ -- Outer value should never be propagated to :terminal
+ fn.setenv('COLORTERM', 'wrongvalue')
+ end)
+
+ local function test_term_colorterm(expected, opts)
+ local screen = Screen.new(50, 4)
+ screen:attach()
+ fn.termopen({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--headless',
+ '-c',
+ 'echo $COLORTERM | quit',
+ }, opts)
+ screen:expect(([[
+ ^%s{MATCH:%%s+}|
+ [Process exited 0] |
+ |*2
+ ]]):format(expected))
+ end
+
+ describe("with 'notermguicolors'", function()
+ before_each(function()
+ command('set notermguicolors')
+ end)
+ it('is empty by default', function()
+ test_term_colorterm('')
+ end)
+ it('can be overridden', function()
+ test_term_colorterm('expectedvalue', { env = { COLORTERM = 'expectedvalue' } })
+ end)
+ end)
+
+ describe("with 'termguicolors'", function()
+ before_each(function()
+ command('set termguicolors')
+ end)
+ it('is "truecolor" by default', function()
+ test_term_colorterm('truecolor')
+ end)
+ it('can be overridden', function()
+ test_term_colorterm('expectedvalue', { env = { COLORTERM = 'expectedvalue' } })
+ end)
+ end)
end)
end)
diff --git a/test/functional/terminal/channel_spec.lua b/test/functional/terminal/channel_spec.lua
index 8510df5347..9615534c87 100644
--- a/test/functional/terminal/channel_spec.lua
+++ b/test/functional/terminal/channel_spec.lua
@@ -8,7 +8,7 @@ local pcall_err = helpers.pcall_err
local feed = helpers.feed
local poke_eventloop = helpers.poke_eventloop
local is_os = helpers.is_os
-local meths = helpers.meths
+local api = helpers.api
local async_meths = helpers.async_meths
local testprg = helpers.testprg
local assert_alive = helpers.assert_alive
@@ -26,9 +26,11 @@ describe('terminal channel is closed and later released if', function()
command([[let id = nvim_open_term(0, {})]])
local chans = eval('len(nvim_list_chans())')
-- channel hasn't been released yet
- eq("Vim(call):Can't send data to closed stream",
- pcall_err(command, [[bdelete! | call chansend(id, 'test')]]))
- feed('<Ignore>') -- add input to separate two RPC requests
+ eq(
+ "Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[bdelete! | call chansend(id, 'test')]])
+ )
+ feed('<Ignore>') -- add input to separate two RPC requests
-- channel has been released after one main loop iteration
eq(chans - 1, eval('len(nvim_list_chans())'))
end)
@@ -37,15 +39,17 @@ describe('terminal channel is closed and later released if', function()
command('let id = nvim_open_term(0, {})')
local chans = eval('len(nvim_list_chans())')
-- channel has been closed but not released
- eq("Vim(call):Can't send data to closed stream",
- pcall_err(command, [[call chanclose(id) | call chansend(id, 'test')]]))
- screen:expect({any='%[Terminal closed%]'})
+ eq(
+ "Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[call chanclose(id) | call chansend(id, 'test')]])
+ )
+ screen:expect({ any = '%[Terminal closed%]' })
eq(chans, eval('len(nvim_list_chans())'))
-- delete terminal
feed('i<CR>')
-- need to first process input
poke_eventloop()
- feed('<Ignore>') -- add input to separate two RPC requests
+ feed('<Ignore>') -- add input to separate two RPC requests
-- channel has been released after another main loop iteration
eq(chans - 1, eval('len(nvim_list_chans())'))
end)
@@ -54,14 +58,18 @@ describe('terminal channel is closed and later released if', function()
command('let id = nvim_open_term(0, {})')
local chans = eval('len(nvim_list_chans())')
-- channel has been closed but not released
- eq("Vim(call):Can't send data to closed stream",
- pcall_err(command, [[call chanclose(id) | call chansend(id, 'test')]]))
- screen:expect({any='%[Terminal closed%]'})
+ eq(
+ "Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[call chanclose(id) | call chansend(id, 'test')]])
+ )
+ screen:expect({ any = '%[Terminal closed%]' })
eq(chans, eval('len(nvim_list_chans())'))
-- channel still hasn't been released yet
- eq("Vim(call):Can't send data to closed stream",
- pcall_err(command, [[bdelete | call chansend(id, 'test')]]))
- feed('<Ignore>') -- add input to separate two RPC requests
+ eq(
+ "Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[bdelete | call chansend(id, 'test')]])
+ )
+ feed('<Ignore>') -- add input to separate two RPC requests
-- channel has been released after one main loop iteration
eq(chans - 1, eval('len(nvim_list_chans())'))
end)
@@ -70,16 +78,18 @@ describe('terminal channel is closed and later released if', function()
command([[let id = termopen('echo')]])
local chans = eval('len(nvim_list_chans())')
-- wait for process to exit
- screen:expect({any='%[Process exited 0%]'})
+ screen:expect({ any = '%[Process exited 0%]' })
-- process has exited but channel has't been released
- eq("Vim(call):Can't send data to closed stream",
- pcall_err(command, [[call chansend(id, 'test')]]))
+ eq(
+ "Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[call chansend(id, 'test')]])
+ )
eq(chans, eval('len(nvim_list_chans())'))
-- delete terminal
feed('i<CR>')
-- need to first process input
poke_eventloop()
- feed('<Ignore>') -- add input to separate two RPC requests
+ feed('<Ignore>') -- add input to separate two RPC requests
-- channel has been released after another main loop iteration
eq(chans - 1, eval('len(nvim_list_chans())'))
end)
@@ -89,34 +99,38 @@ describe('terminal channel is closed and later released if', function()
command([[let id = termopen('echo')]])
local chans = eval('len(nvim_list_chans())')
-- wait for process to exit
- screen:expect({any='%[Process exited 0%]'})
+ screen:expect({ any = '%[Process exited 0%]' })
-- process has exited but channel hasn't been released
- eq("Vim(call):Can't send data to closed stream",
- pcall_err(command, [[call chansend(id, 'test')]]))
+ eq(
+ "Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[call chansend(id, 'test')]])
+ )
eq(chans, eval('len(nvim_list_chans())'))
-- channel still hasn't been released yet
- eq("Vim(call):Can't send data to closed stream",
- pcall_err(command, [[bdelete | call chansend(id, 'test')]]))
- feed('<Ignore>') -- add input to separate two RPC requests
+ eq(
+ "Vim(call):Can't send data to closed stream",
+ pcall_err(command, [[bdelete | call chansend(id, 'test')]])
+ )
+ feed('<Ignore>') -- add input to separate two RPC requests
-- channel has been released after one main loop iteration
eq(chans - 1, eval('len(nvim_list_chans())'))
end)
end)
it('chansend sends lines to terminal channel in proper order', function()
- clear({args = {'--cmd', 'set laststatus=2'}})
+ clear({ args = { '--cmd', 'set laststatus=2' } })
local screen = Screen.new(100, 20)
screen:attach()
- local shells = is_os('win') and {'cmd.exe', 'pwsh.exe -nop', 'powershell.exe -nop'} or {'sh'}
+ local shells = is_os('win') and { 'cmd.exe', 'pwsh.exe -nop', 'powershell.exe -nop' } or { 'sh' }
for _, sh in ipairs(shells) do
command([[let id = termopen(']] .. sh .. [[')]])
command([[call chansend(id, ['echo "hello"', 'echo "world"', ''])]])
- screen:expect{
- any=[[echo "hello".*echo "world"]]
+ screen:expect {
+ any = [[echo "hello".*echo "world"]],
}
command('bdelete!')
- screen:expect{
- any='%[No Name%]'
+ screen:expect {
+ any = '%[No Name%]',
}
end
end)
@@ -126,76 +140,139 @@ describe('no crash when TermOpen autocommand', function()
before_each(function()
clear()
- meths.set_option_value('shell', testprg('shell-test'), {})
+ api.nvim_set_option_value('shell', testprg('shell-test'), {})
command('set shellcmdflag=EXE shellredir= shellpipe= shellquote= shellxquote=')
screen = Screen.new(60, 4)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue};
+ [0] = { bold = true, foreground = Screen.colors.Blue },
})
screen:attach()
end)
it('processes job exit event when using termopen()', function()
command([[autocmd TermOpen * call input('')]])
- async_meths.command('terminal foobar')
- screen:expect{grid=[[
+ async_meths.nvim_command('terminal foobar')
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
^ |
- ]]}
+ ]],
+ }
feed('<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ready $ foobar |
|
[Process exited 0] |
|
- ]]}
+ ]],
+ }
feed('i<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]]}
+ ]],
+ }
assert_alive()
end)
it('wipes buffer and processes events when using termopen()', function()
command([[autocmd TermOpen * bwipe! | call input('')]])
- async_meths.command('terminal foobar')
- screen:expect{grid=[[
+ async_meths.nvim_command('terminal foobar')
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
^ |
- ]]}
+ ]],
+ }
feed('<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]]}
+ ]],
+ }
assert_alive()
end)
it('wipes buffer and processes events when using nvim_open_term()', function()
command([[autocmd TermOpen * bwipe! | call input('')]])
- async_meths.open_term(0, {})
- screen:expect{grid=[[
+ async_meths.nvim_open_term(0, {})
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
^ |
- ]]}
+ ]],
+ }
feed('<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]]}
+ ]],
+ }
assert_alive()
end)
end)
+
+describe('nvim_open_term', function()
+ local screen
+
+ before_each(function()
+ clear()
+ screen = Screen.new(8, 10)
+ screen:attach()
+ end)
+
+ it('with force_crlf=true converts newlines', function()
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_create_buf(false, true)
+ local term = api.nvim_open_term(buf, { force_crlf = true })
+ api.nvim_win_set_buf(win, buf)
+ api.nvim_chan_send(term, 'here\nthere\nfoo\r\nbar\n\ntest')
+ screen:expect {
+ grid = [[
+ ^here |
+ there |
+ foo |
+ bar |
+ |
+ test |
+ |*4
+ ]],
+ }
+ api.nvim_chan_send(term, '\nfirst')
+ screen:expect {
+ grid = [[
+ ^here |
+ there |
+ foo |
+ bar |
+ |
+ test |
+ first |
+ |*3
+ ]],
+ }
+ end)
+
+ it('with force_crlf=false does not convert newlines', function()
+ local win = api.nvim_get_current_win()
+ local buf = api.nvim_create_buf(false, true)
+ local term = api.nvim_open_term(buf, { force_crlf = false })
+ api.nvim_win_set_buf(win, buf)
+ api.nvim_chan_send(term, 'here\nthere')
+ screen:expect { grid = [[
+ ^here |
+ there |
+ |*8
+ ]] }
+ end)
+end)
diff --git a/test/functional/terminal/cursor_spec.lua b/test/functional/terminal/cursor_spec.lua
index 8285bcc26e..73fd97203e 100644
--- a/test/functional/terminal/cursor_spec.lua
+++ b/test/functional/terminal/cursor_spec.lua
@@ -1,9 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local thelpers = require('test.functional.terminal.helpers')
-local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
+local feed, clear = helpers.feed, helpers.clear
local testprg, command = helpers.testprg, helpers.command
-local nvim_prog = helpers.nvim_prog
local eq, eval = helpers.eq, helpers.eval
local matches = helpers.matches
local poke_eventloop = helpers.poke_eventloop
@@ -20,16 +19,12 @@ describe(':terminal cursor', function()
screen = thelpers.screen_setup()
end)
-
it('moves the screen cursor when focused', function()
thelpers.feed_data('testing cursor')
screen:expect([[
tty ready |
testing cursor{1: } |
- |
- |
- |
- |
+ |*4
{3:-- TERMINAL --} |
]])
end)
@@ -39,11 +34,7 @@ describe(':terminal cursor', function()
screen:expect([[
tty ready |
{2:^ } |
- |
- |
- |
- |
- |
+ |*5
]])
end)
@@ -94,21 +85,14 @@ describe(':terminal cursor', function()
hide_cursor()
screen:expect([[
tty ready |
- |
- |
- |
- |
- |
+ |*5
{3:-- TERMINAL --} |
]])
show_cursor()
screen:expect([[
tty ready |
{1: } |
- |
- |
- |
- |
+ |*4
{3:-- TERMINAL --} |
]])
-- same for when the terminal is unfocused
@@ -117,42 +101,33 @@ describe(':terminal cursor', function()
screen:expect([[
tty ready |
^ |
- |
- |
- |
- |
- |
+ |*5
]])
show_cursor()
screen:expect([[
tty ready |
{2:^ } |
- |
- |
- |
- |
- |
+ |*5
]])
end)
end)
end)
-
describe('cursor with customized highlighting', function()
local screen
before_each(function()
clear()
- nvim('command', 'highlight TermCursor ctermfg=45 ctermbg=46 cterm=NONE')
- nvim('command', 'highlight TermCursorNC ctermfg=55 ctermbg=56 cterm=NONE')
+ command('highlight TermCursor ctermfg=45 ctermbg=46 cterm=NONE')
+ command('highlight TermCursorNC ctermfg=55 ctermbg=56 cterm=NONE')
screen = Screen.new(50, 7)
screen:set_default_attr_ids({
- [1] = {foreground = 45, background = 46},
- [2] = {foreground = 55, background = 56},
- [3] = {bold = true},
+ [1] = { foreground = 45, background = 46 },
+ [2] = { foreground = 55, background = 56 },
+ [3] = { bold = true },
})
- screen:attach({rgb=false})
- command('call termopen(["'..testprg('tty-test')..'"])')
+ screen:attach({ rgb = false })
+ command('call termopen(["' .. testprg('tty-test') .. '"])')
feed('i')
poke_eventloop()
end)
@@ -161,21 +136,14 @@ describe('cursor with customized highlighting', function()
screen:expect([[
tty ready |
{1: } |
- |
- |
- |
- |
+ |*4
{3:-- TERMINAL --} |
]])
feed('<c-\\><c-n>')
screen:expect([[
tty ready |
{2:^ } |
- |
- |
- |
- |
- |
+ |*5
]])
end)
end)
@@ -184,20 +152,37 @@ describe('buffer cursor position is correct in terminal without number column',
local screen
local function setup_ex_register(str)
- screen = thelpers.screen_setup(0, '["'..nvim_prog
- ..[[", "-u", "NONE", "-i", "NONE", "-E", "--cmd", "let @r = ']]..str..[['", ]]
+ screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '-E',
+ '--cmd',
+ string.format('let @r = "%s"', str),
-- <Left> and <Right> don't always work
- ..[["--cmd", "cnoremap <C-X> <Left>", "--cmd", "cnoremap <C-O> <Right>"]]..']', 70)
+ '--cmd',
+ 'cnoremap <C-X> <Left>',
+ '--cmd',
+ 'cnoremap <C-O> <Right>',
+ '--cmd',
+ 'set notermguicolors',
+ }, {
+ cols = 70,
+ })
+ screen:set_default_attr_ids({
+ [1] = { foreground = 253, background = 11 },
+ [2] = { reverse = true },
+ [3] = { bold = true },
+ [4] = { background = 11 },
+ })
-- Also check for real cursor position, as it is used for stuff like input methods
screen._handle_busy_start = function() end
screen._handle_busy_stop = function() end
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :{1:^ } |
+ :{2:^ } |
{3:-- TERMINAL --} |
]])
end
@@ -212,76 +197,58 @@ describe('buffer cursor position is correct in terminal without number column',
it('at the end', function()
feed('<C-R>r')
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :aaaaaaaa{1:^ } |
+ :aaaaaaaa{2:^ } |
{3:-- TERMINAL --} |
]])
- eq({6, 9}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 9 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :aaaaaaa^a{2: } |
+ :aaaaaaa^a{4: } |
|
]])
- eq({6, 8}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 8 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the end', function()
feed('<C-R>r<C-X><C-X>')
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :aaaaaa{1:^a}a |
+ :aaaaaa{2:^a}a |
{3:-- TERMINAL --} |
]])
- eq({6, 7}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 7 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :aaaaa^a{2:a}a |
+ :aaaaa^a{4:a}a |
|
]])
- eq({6, 6}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 6 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the start', function()
feed('<C-R>r<C-B><C-O>')
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :a{1:^a}aaaaaa |
+ :a{2:^a}aaaaaa |
{3:-- TERMINAL --} |
]])
- eq({6, 2}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 2 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :^a{2:a}aaaaaa |
+ :^a{4:a}aaaaaa |
|
]])
- eq({6, 1}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
end)
end)
@@ -293,164 +260,135 @@ describe('buffer cursor position is correct in terminal without number column',
it('at the end', function()
feed('<C-R>r')
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µµµµµµµµ{1:^ } |
+ :µµµµµµµµ{2:^ } |
{3:-- TERMINAL --} |
]])
- eq({6, 17}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 17 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µµµµµµµ^µ{2: } |
+ :µµµµµµµ^µ{4: } |
|
]])
- eq({6, 15}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 15 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the end', function()
feed('<C-R>r<C-X><C-X>')
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µµµµµµ{1:^µ}µ |
+ :µµµµµµ{2:^µ}µ |
{3:-- TERMINAL --} |
]])
- eq({6, 13}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 13 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µµµµµ^µ{2:µ}µ |
+ :µµµµµ^µ{4:µ}µ |
|
]])
- eq({6, 11}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 11 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the start', function()
feed('<C-R>r<C-B><C-O>')
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µ{1:^µ}µµµµµµ |
+ :µ{2:^µ}µµµµµµ |
{3:-- TERMINAL --} |
]])
- eq({6, 3}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 3 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :^µ{2:µ}µµµµµµ |
+ :^µ{4:µ}µµµµµµ |
|
]])
- eq({6, 1}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
end)
end)
- describe('in a line with single-cell composed multibyte characters and no trailing spaces,', function()
- if skip(is_os('win'), "Encoding problem?") then return end
-
- before_each(function()
- setup_ex_register('µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳')
- end)
-
- it('at the end', function()
- feed('<C-R>r')
- screen:expect([[
- |
- |
- |
- |
+ describe(
+ 'in a line with single-cell composed multibyte characters and no trailing spaces,',
+ function()
+ if skip(is_os('win'), 'Encoding problem?') then
+ return
+ end
+
+ before_each(function()
+ setup_ex_register('µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳')
+ end)
+
+ it('at the end', function()
+ feed('<C-R>r')
+ screen:expect([[
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{1:^ } |
+ :µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{2:^ } |
{3:-- TERMINAL --} |
]])
- eq({6, 33}, eval('nvim_win_get_cursor(0)'))
- feed([[<C-\><C-N>]])
- screen:expect([[
- |
- |
- |
- |
+ eq({ 6, 33 }, eval('nvim_win_get_cursor(0)'))
+ feed([[<C-\><C-N>]])
+ screen:expect([[
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳{2: } |
+ :µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳{4: } |
|
]])
- eq({6, 29}, eval('nvim_win_get_cursor(0)'))
- end)
+ eq({ 6, 29 }, eval('nvim_win_get_cursor(0)'))
+ end)
- it('near the end', function()
- feed('<C-R>r<C-X><C-X>')
- screen:expect([[
- |
- |
- |
- |
+ it('near the end', function()
+ feed('<C-R>r<C-X><C-X>')
+ screen:expect([[
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µ̳µ̳µ̳µ̳µ̳µ̳{1:^µ̳}µ̳ |
+ :µ̳µ̳µ̳µ̳µ̳µ̳{2:^µ̳}µ̳ |
{3:-- TERMINAL --} |
]])
- eq({6, 25}, eval('nvim_win_get_cursor(0)'))
- feed([[<C-\><C-N>]])
- screen:expect([[
- |
- |
- |
- |
+ eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
+ feed([[<C-\><C-N>]])
+ screen:expect([[
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µ̳µ̳µ̳µ̳µ̳^µ̳{2:µ̳}µ̳ |
+ :µ̳µ̳µ̳µ̳µ̳^µ̳{4:µ̳}µ̳ |
|
]])
- eq({6, 21}, eval('nvim_win_get_cursor(0)'))
- end)
+ eq({ 6, 21 }, eval('nvim_win_get_cursor(0)'))
+ end)
- it('near the start', function()
- feed('<C-R>r<C-B><C-O>')
- screen:expect([[
- |
- |
- |
- |
+ it('near the start', function()
+ feed('<C-R>r<C-B><C-O>')
+ screen:expect([[
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :µ̳{1:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
+ :µ̳{2:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
{3:-- TERMINAL --} |
]])
- eq({6, 5}, eval('nvim_win_get_cursor(0)'))
- feed([[<C-\><C-N>]])
- screen:expect([[
- |
- |
- |
- |
+ eq({ 6, 5 }, eval('nvim_win_get_cursor(0)'))
+ feed([[<C-\><C-N>]])
+ screen:expect([[
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :^µ̳{2:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
+ :^µ̳{4:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
|
]])
- eq({6, 1}, eval('nvim_win_get_cursor(0)'))
- end)
- end)
+ eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
+ end)
+ end
+ )
describe('in a line with double-cell multibyte characters and no trailing spaces,', function()
- if skip(is_os('win'), "Encoding problem?") then return end
+ if skip(is_os('win'), 'Encoding problem?') then
+ return
+ end
before_each(function()
setup_ex_register('哦哦哦哦哦哦哦哦')
@@ -459,76 +397,58 @@ describe('buffer cursor position is correct in terminal without number column',
it('at the end', function()
feed('<C-R>r')
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :哦哦哦哦哦哦哦哦{1:^ } |
+ :哦哦哦哦哦哦哦哦{2:^ } |
{3:-- TERMINAL --} |
]])
- eq({6, 25}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :哦哦哦哦哦哦哦^哦{2: } |
+ :哦哦哦哦哦哦哦^哦{4: } |
|
]])
- eq({6, 22}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 22 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the end', function()
feed('<C-R>r<C-X><C-X>')
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :哦哦哦哦哦哦{1:^哦}哦 |
+ :哦哦哦哦哦哦{2:^哦}哦 |
{3:-- TERMINAL --} |
]])
- eq({6, 19}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 19 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :哦哦哦哦哦^哦{2:哦}哦 |
+ :哦哦哦哦哦^哦{4:哦}哦 |
|
]])
- eq({6, 16}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 16 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the start', function()
feed('<C-R>r<C-B><C-O>')
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :哦{1:^哦}哦哦哦哦哦哦 |
+ :哦{2:^哦}哦哦哦哦哦哦 |
{3:-- TERMINAL --} |
]])
- eq({6, 4}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 4 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :^哦{2:哦}哦哦哦哦哦哦 |
+ :^哦{4:哦}哦哦哦哦哦哦 |
|
]])
- eq({6, 1}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
end)
end)
@@ -536,27 +456,21 @@ describe('buffer cursor position is correct in terminal without number column',
setup_ex_register('aaaaaaaa ')
feed('<C-R>r')
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :aaaaaaaa {1:^ } |
+ :aaaaaaaa {2:^ } |
{3:-- TERMINAL --} |
]])
matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()'))
- eq({6, 13}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 13 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
- |
- |
- |
- |
+ |*4
Entering Ex mode. Type "visual" to go to Normal mode. |
- :aaaaaaaa ^ {2: } |
+ :aaaaaaaa ^ {4: } |
|
]])
- eq({6, 12}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 12 }, eval('nvim_win_get_cursor(0)'))
end)
end)
@@ -564,10 +478,31 @@ describe('buffer cursor position is correct in terminal with number column', fun
local screen
local function setup_ex_register(str)
- screen = thelpers.screen_setup(0, '["'..nvim_prog
- ..[[", "-u", "NONE", "-i", "NONE", "-E", "--cmd", "let @r = ']]..str..[['", ]]
+ screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '-E',
+ '--cmd',
+ string.format('let @r = "%s"', str),
-- <Left> and <Right> don't always work
- ..[["--cmd", "cnoremap <C-X> <Left>", "--cmd", "cnoremap <C-O> <Right>"]]..']', 70)
+ '--cmd',
+ 'cnoremap <C-X> <Left>',
+ '--cmd',
+ 'cnoremap <C-O> <Right>',
+ '--cmd',
+ 'set notermguicolors',
+ }, {
+ cols = 70,
+ })
+ screen:set_default_attr_ids({
+ [1] = { foreground = 253, background = 11 },
+ [2] = { reverse = true },
+ [3] = { bold = true },
+ [4] = { background = 11 },
+ [7] = { foreground = 130 },
+ })
-- Also check for real cursor position, as it is used for stuff like input methods
screen._handle_busy_start = function() end
screen._handle_busy_stop = function() end
@@ -577,7 +512,7 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:{1:^ } |
+ {7: 6 }:{2:^ } |
{3:-- TERMINAL --} |
]])
end
@@ -600,10 +535,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:aaaaaaaa{1:^ } |
+ {7: 6 }:aaaaaaaa{2:^ } |
{3:-- TERMINAL --} |
]])
- eq({6, 9}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 9 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
{7: 1 } |
@@ -611,10 +546,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:aaaaaaa^a{2: } |
+ {7: 6 }:aaaaaaa^a{4: } |
|
]])
- eq({6, 8}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 8 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the end', function()
@@ -625,10 +560,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:aaaaaa{1:^a}a |
+ {7: 6 }:aaaaaa{2:^a}a |
{3:-- TERMINAL --} |
]])
- eq({6, 7}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 7 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
{7: 1 } |
@@ -636,10 +571,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:aaaaa^a{2:a}a |
+ {7: 6 }:aaaaa^a{4:a}a |
|
]])
- eq({6, 6}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 6 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the start', function()
@@ -650,10 +585,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:a{1:^a}aaaaaa |
+ {7: 6 }:a{2:^a}aaaaaa |
{3:-- TERMINAL --} |
]])
- eq({6, 2}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 2 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
{7: 1 } |
@@ -661,10 +596,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:^a{2:a}aaaaaa |
+ {7: 6 }:^a{4:a}aaaaaa |
|
]])
- eq({6, 1}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
end)
end)
@@ -681,10 +616,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µµµµµµµµ{1:^ } |
+ {7: 6 }:µµµµµµµµ{2:^ } |
{3:-- TERMINAL --} |
]])
- eq({6, 17}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 17 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
{7: 1 } |
@@ -692,10 +627,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µµµµµµµ^µ{2: } |
+ {7: 6 }:µµµµµµµ^µ{4: } |
|
]])
- eq({6, 15}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 15 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the end', function()
@@ -706,10 +641,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µµµµµµ{1:^µ}µ |
+ {7: 6 }:µµµµµµ{2:^µ}µ |
{3:-- TERMINAL --} |
]])
- eq({6, 13}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 13 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
{7: 1 } |
@@ -717,10 +652,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µµµµµ^µ{2:µ}µ |
+ {7: 6 }:µµµµµ^µ{4:µ}µ |
|
]])
- eq({6, 11}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 11 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the start', function()
@@ -731,10 +666,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µ{1:^µ}µµµµµµ |
+ {7: 6 }:µ{2:^µ}µµµµµµ |
{3:-- TERMINAL --} |
]])
- eq({6, 3}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 3 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
{7: 1 } |
@@ -742,98 +677,105 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:^µ{2:µ}µµµµµµ |
+ {7: 6 }:^µ{4:µ}µµµµµµ |
|
]])
- eq({6, 1}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
end)
end)
- describe('in a line with single-cell composed multibyte characters and no trailing spaces,', function()
- if skip(is_os('win'), "Encoding problem?") then return end
+ describe(
+ 'in a line with single-cell composed multibyte characters and no trailing spaces,',
+ function()
+ if skip(is_os('win'), 'Encoding problem?') then
+ return
+ end
- before_each(function()
- setup_ex_register('µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳')
- end)
+ before_each(function()
+ setup_ex_register('µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳')
+ end)
- it('at the end', function()
- feed('<C-R>r')
- screen:expect([[
+ it('at the end', function()
+ feed('<C-R>r')
+ screen:expect([[
{7: 1 } |
{7: 2 } |
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{1:^ } |
+ {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳µ̳{2:^ } |
{3:-- TERMINAL --} |
]])
- eq({6, 33}, eval('nvim_win_get_cursor(0)'))
- feed([[<C-\><C-N>]])
- screen:expect([[
+ eq({ 6, 33 }, eval('nvim_win_get_cursor(0)'))
+ feed([[<C-\><C-N>]])
+ screen:expect([[
{7: 1 } |
{7: 2 } |
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳{2: } |
+ {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳µ̳^µ̳{4: } |
|
]])
- eq({6, 29}, eval('nvim_win_get_cursor(0)'))
- end)
+ eq({ 6, 29 }, eval('nvim_win_get_cursor(0)'))
+ end)
- it('near the end', function()
- feed('<C-R>r<C-X><C-X>')
- screen:expect([[
+ it('near the end', function()
+ feed('<C-R>r<C-X><C-X>')
+ screen:expect([[
{7: 1 } |
{7: 2 } |
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳{1:^µ̳}µ̳ |
+ {7: 6 }:µ̳µ̳µ̳µ̳µ̳µ̳{2:^µ̳}µ̳ |
{3:-- TERMINAL --} |
]])
- eq({6, 25}, eval('nvim_win_get_cursor(0)'))
- feed([[<C-\><C-N>]])
- screen:expect([[
+ eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
+ feed([[<C-\><C-N>]])
+ screen:expect([[
{7: 1 } |
{7: 2 } |
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µ̳µ̳µ̳µ̳µ̳^µ̳{2:µ̳}µ̳ |
+ {7: 6 }:µ̳µ̳µ̳µ̳µ̳^µ̳{4:µ̳}µ̳ |
|
]])
- eq({6, 21}, eval('nvim_win_get_cursor(0)'))
- end)
+ eq({ 6, 21 }, eval('nvim_win_get_cursor(0)'))
+ end)
- it('near the start', function()
- feed('<C-R>r<C-B><C-O>')
- screen:expect([[
+ it('near the start', function()
+ feed('<C-R>r<C-B><C-O>')
+ screen:expect([[
{7: 1 } |
{7: 2 } |
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:µ̳{1:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
+ {7: 6 }:µ̳{2:^µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
{3:-- TERMINAL --} |
]])
- eq({6, 5}, eval('nvim_win_get_cursor(0)'))
- feed([[<C-\><C-N>]])
- screen:expect([[
+ eq({ 6, 5 }, eval('nvim_win_get_cursor(0)'))
+ feed([[<C-\><C-N>]])
+ screen:expect([[
{7: 1 } |
{7: 2 } |
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:^µ̳{2:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
+ {7: 6 }:^µ̳{4:µ̳}µ̳µ̳µ̳µ̳µ̳µ̳ |
|
]])
- eq({6, 1}, eval('nvim_win_get_cursor(0)'))
- end)
- end)
+ eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
+ end)
+ end
+ )
describe('in a line with double-cell multibyte characters and no trailing spaces,', function()
- if skip(is_os('win'), "Encoding problem?") then return end
+ if skip(is_os('win'), 'Encoding problem?') then
+ return
+ end
before_each(function()
setup_ex_register('哦哦哦哦哦哦哦哦')
@@ -847,10 +789,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:哦哦哦哦哦哦哦哦{1:^ } |
+ {7: 6 }:哦哦哦哦哦哦哦哦{2:^ } |
{3:-- TERMINAL --} |
]])
- eq({6, 25}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 25 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
{7: 1 } |
@@ -858,10 +800,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:哦哦哦哦哦哦哦^哦{2: } |
+ {7: 6 }:哦哦哦哦哦哦哦^哦{4: } |
|
]])
- eq({6, 22}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 22 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the end', function()
@@ -872,10 +814,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:哦哦哦哦哦哦{1:^哦}哦 |
+ {7: 6 }:哦哦哦哦哦哦{2:^哦}哦 |
{3:-- TERMINAL --} |
]])
- eq({6, 19}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 19 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
{7: 1 } |
@@ -883,10 +825,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:哦哦哦哦哦^哦{2:哦}哦 |
+ {7: 6 }:哦哦哦哦哦^哦{4:哦}哦 |
|
]])
- eq({6, 16}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 16 }, eval('nvim_win_get_cursor(0)'))
end)
it('near the start', function()
@@ -897,10 +839,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:哦{1:^哦}哦哦哦哦哦哦 |
+ {7: 6 }:哦{2:^哦}哦哦哦哦哦哦 |
{3:-- TERMINAL --} |
]])
- eq({6, 4}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 4 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
{7: 1 } |
@@ -908,10 +850,10 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:^哦{2:哦}哦哦哦哦哦哦 |
+ {7: 6 }:^哦{4:哦}哦哦哦哦哦哦 |
|
]])
- eq({6, 1}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 1 }, eval('nvim_win_get_cursor(0)'))
end)
end)
@@ -924,11 +866,11 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:aaaaaaaa {1:^ } |
+ {7: 6 }:aaaaaaaa {2:^ } |
{3:-- TERMINAL --} |
]])
matches('^:aaaaaaaa [ ]*$', eval('nvim_get_current_line()'))
- eq({6, 13}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 13 }, eval('nvim_win_get_cursor(0)'))
feed([[<C-\><C-N>]])
screen:expect([[
{7: 1 } |
@@ -936,9 +878,9 @@ describe('buffer cursor position is correct in terminal with number column', fun
{7: 3 } |
{7: 4 } |
{7: 5 }Entering Ex mode. Type "visual" to go to Normal mode. |
- {7: 6 }:aaaaaaaa ^ {2: } |
+ {7: 6 }:aaaaaaaa ^ {4: } |
|
]])
- eq({6, 12}, eval('nvim_win_get_cursor(0)'))
+ eq({ 6, 12 }, eval('nvim_win_get_cursor(0)'))
end)
end)
diff --git a/test/functional/terminal/edit_spec.lua b/test/functional/terminal/edit_spec.lua
index 29361bc0fa..f7ceb0a68b 100644
--- a/test/functional/terminal/edit_spec.lua
+++ b/test/functional/terminal/edit_spec.lua
@@ -1,72 +1,68 @@
local helpers = require('test.functional.helpers')(after_each)
local screen = require('test.functional.ui.screen')
-local curbufmeths = helpers.curbufmeths
-local curwinmeths = helpers.curwinmeths
local testprg = helpers.testprg
local command = helpers.command
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local clear = helpers.clear
local eq = helpers.eq
local matches = helpers.matches
-local pesc = helpers.pesc
+local pesc = vim.pesc
describe(':edit term://*', function()
local get_screen = function(columns, lines)
local scr = screen.new(columns, lines)
- scr:attach({rgb=false})
+ scr:attach({ rgb = false })
return scr
end
before_each(function()
clear()
- meths.set_option_value('shell', testprg('shell-test'), {})
- meths.set_option_value('shellcmdflag', 'EXE', {})
+ api.nvim_set_option_value('shell', testprg('shell-test'), {})
+ api.nvim_set_option_value('shellcmdflag', 'EXE', {})
end)
it('runs TermOpen event', function()
- meths.set_var('termopen_runs', {})
+ api.nvim_set_var('termopen_runs', {})
command('autocmd TermOpen * :call add(g:termopen_runs, expand("<amatch>"))')
command('edit term://')
- local termopen_runs = meths.get_var('termopen_runs')
+ local termopen_runs = api.nvim_get_var('termopen_runs')
eq(1, #termopen_runs)
- local cwd = funcs.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '')
- matches('^term://'..pesc(cwd)..'//%d+:$', termopen_runs[1])
+ local cwd = fn.fnamemodify('.', ':p:~'):gsub([[[\/]*$]], '')
+ matches('^term://' .. pesc(cwd) .. '//%d+:$', termopen_runs[1])
end)
it("runs TermOpen early enough to set buffer-local 'scrollback'", function()
local columns, lines = 20, 4
local scr = get_screen(columns, lines)
local rep = 97
- meths.set_option_value('shellcmdflag', 'REP ' .. rep, {})
- command('set shellxquote=') -- win: avoid extra quotes
+ api.nvim_set_option_value('shellcmdflag', 'REP ' .. rep, {})
+ command('set shellxquote=') -- win: avoid extra quotes
local sb = 10
- command('autocmd TermOpen * :setlocal scrollback='..tostring(sb)
- ..'|call feedkeys("G", "n")')
+ command(
+ 'autocmd TermOpen * :setlocal scrollback=' .. tostring(sb) .. '|call feedkeys("G", "n")'
+ )
command('edit term://foobar')
local bufcontents = {}
- local winheight = curwinmeths.get_height()
+ local winheight = api.nvim_win_get_height(0)
local buf_cont_start = rep - sb - winheight + 2
- for i = buf_cont_start,(rep - 1) do
+ for i = buf_cont_start, (rep - 1) do
bufcontents[#bufcontents + 1] = ('%d: foobar'):format(i)
end
bufcontents[#bufcontents + 1] = ''
bufcontents[#bufcontents + 1] = '[Process exited 0]'
local exp_screen = '\n'
- for i = 1,(winheight - 1) do
+ for i = 1, (winheight - 1) do
local line = bufcontents[#bufcontents - winheight + i]
- exp_screen = (exp_screen
- .. line
- .. (' '):rep(columns - #line)
- .. '|\n')
+ exp_screen = (exp_screen .. line .. (' '):rep(columns - #line) .. '|\n')
end
- exp_screen = exp_screen..'^[Process exited 0] |\n'
+ exp_screen = exp_screen .. '^[Process exited 0] |\n'
- exp_screen = exp_screen..(' '):rep(columns)..'|\n'
+ exp_screen = exp_screen .. (' '):rep(columns) .. '|\n'
scr:expect(exp_screen)
- eq(bufcontents, curbufmeths.get_lines(0, -1, true))
+ eq(bufcontents, api.nvim_buf_get_lines(0, 0, -1, true))
end)
end)
diff --git a/test/functional/terminal/ex_terminal_spec.lua b/test/functional/terminal/ex_terminal_spec.lua
index f628e261a2..92d37fc04a 100644
--- a/test/functional/terminal/ex_terminal_spec.lua
+++ b/test/functional/terminal/ex_terminal_spec.lua
@@ -1,11 +1,12 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local assert_alive = helpers.assert_alive
-local clear, poke_eventloop, nvim = helpers.clear, helpers.poke_eventloop, helpers.nvim
+local clear, poke_eventloop = helpers.clear, helpers.poke_eventloop
local testprg, source, eq = helpers.testprg, helpers.source, helpers.eq
local feed = helpers.feed
local feed_command, eval = helpers.feed_command, helpers.eval
-local funcs = helpers.funcs
+local fn = helpers.fn
+local api = helpers.api
local retry = helpers.retry
local ok = helpers.ok
local command = helpers.command
@@ -19,10 +20,10 @@ describe(':terminal', function()
before_each(function()
clear()
screen = Screen.new(50, 4)
- screen:attach({rgb=false})
+ screen:attach({ rgb = false })
end)
- it("does not interrupt Press-ENTER prompt #2748", function()
+ it('does not interrupt Press-ENTER prompt #2748', function()
-- Ensure that :messages shows Press-ENTER.
source([[
echomsg "msg1"
@@ -30,14 +31,14 @@ describe(':terminal', function()
echomsg "msg3"
]])
-- Invoke a command that emits frequent terminal activity.
- feed([[:terminal "]]..testprg('shell-test')..[[" REP 9999 !terminal_output!<cr>]])
+ feed([[:terminal "]] .. testprg('shell-test') .. [[" REP 9999 !terminal_output!<cr>]])
feed([[<C-\><C-N>]])
poke_eventloop()
-- Wait for some terminal activity.
retry(nil, 4000, function()
- ok(funcs.line('$') > 6)
+ ok(fn.line('$') > 6)
end)
- feed_command("messages")
+ feed_command('messages')
screen:expect([[
msg1 |
msg2 |
@@ -46,36 +47,40 @@ describe(':terminal', function()
]])
end)
- it("reads output buffer on terminal reporting #4151", function()
+ it('reads output buffer on terminal reporting #4151', function()
skip(is_ci('cirrus') or is_os('win'))
if is_os('win') then
- feed_command([[terminal powershell -NoProfile -NoLogo -Command Write-Host -NoNewline "\"$([char]27)[6n\""; Start-Sleep -Milliseconds 500 ]])
+ feed_command(
+ [[terminal powershell -NoProfile -NoLogo -Command Write-Host -NoNewline "\"$([char]27)[6n\""; Start-Sleep -Milliseconds 500 ]]
+ )
else
feed_command([[terminal printf '\e[6n'; sleep 0.5 ]])
end
- screen:expect{any='%^%[%[1;1R'}
+ screen:expect { any = '%^%[%[1;1R' }
end)
- it("in normal-mode :split does not move cursor", function()
+ it('in normal-mode :split does not move cursor', function()
if is_os('win') then
- feed_command([[terminal for /L \\%I in (1,0,2) do ( echo foo & ping -w 100 -n 1 127.0.0.1 > nul )]])
+ feed_command(
+ [[terminal for /L \\%I in (1,0,2) do ( echo foo & ping -w 100 -n 1 127.0.0.1 > nul )]]
+ )
else
feed_command([[terminal while true; do echo foo; sleep .1; done]])
end
- feed([[<C-\><C-N>M]]) -- move cursor away from last line
+ feed([[<C-\><C-N>M]]) -- move cursor away from last line
poke_eventloop()
- eq(3, eval("line('$')")) -- window height
- eq(2, eval("line('.')")) -- cursor is in the middle
+ eq(3, eval("line('$')")) -- window height
+ eq(2, eval("line('.')")) -- cursor is in the middle
feed_command('vsplit')
- eq(2, eval("line('.')")) -- cursor stays where we put it
+ eq(2, eval("line('.')")) -- cursor stays where we put it
feed_command('split')
- eq(2, eval("line('.')")) -- cursor stays where we put it
+ eq(2, eval("line('.')")) -- cursor stays where we put it
end)
it('Enter/Leave does not increment jumplist #3723', function()
feed_command('terminal')
local function enter_and_leave()
- local lines_before = funcs.line('$')
+ local lines_before = fn.line('$')
-- Create a new line (in the shell). For a normal buffer this
-- increments the jumplist; for a terminal-buffer it should not. #3723
feed('i')
@@ -86,44 +91,44 @@ describe(':terminal', function()
poke_eventloop()
-- Wait for >=1 lines to be created.
retry(nil, 4000, function()
- ok(funcs.line('$') > lines_before)
+ ok(fn.line('$') > lines_before)
end)
end
enter_and_leave()
enter_and_leave()
enter_and_leave()
- ok(funcs.line('$') > 6) -- Verify assumption.
- local jumps = funcs.split(funcs.execute('jumps'), '\n')
+ ok(fn.line('$') > 6) -- Verify assumption.
+ local jumps = fn.split(fn.execute('jumps'), '\n')
eq(' jump line col file/text', jumps[1])
eq(3, #jumps)
end)
it('nvim_get_mode() in :terminal', function()
command('terminal')
- eq({ blocking=false, mode='nt' }, nvim('get_mode'))
+ eq({ blocking = false, mode = 'nt' }, api.nvim_get_mode())
feed('i')
- eq({ blocking=false, mode='t' }, nvim('get_mode'))
+ eq({ blocking = false, mode = 't' }, api.nvim_get_mode())
feed([[<C-\><C-N>]])
- eq({ blocking=false, mode='nt' }, nvim('get_mode'))
+ eq({ blocking = false, mode = 'nt' }, api.nvim_get_mode())
end)
it(':stopinsert RPC request exits terminal-mode #7807', function()
command('terminal')
feed('i[tui] insert-mode')
- eq({ blocking=false, mode='t' }, nvim('get_mode'))
+ eq({ blocking = false, mode = 't' }, api.nvim_get_mode())
command('stopinsert')
- feed('<Ignore>') -- Add input to separate two RPC requests
- eq({ blocking=false, mode='nt' }, nvim('get_mode'))
+ feed('<Ignore>') -- Add input to separate two RPC requests
+ eq({ blocking = false, mode = 'nt' }, api.nvim_get_mode())
end)
- it(':stopinsert in normal mode doesn\'t break insert mode #9889', function()
+ it(":stopinsert in normal mode doesn't break insert mode #9889", function()
command('terminal')
- eq({ blocking=false, mode='nt' }, nvim('get_mode'))
+ eq({ blocking = false, mode = 'nt' }, api.nvim_get_mode())
command('stopinsert')
- feed('<Ignore>') -- Add input to separate two RPC requests
- eq({ blocking=false, mode='nt' }, nvim('get_mode'))
+ feed('<Ignore>') -- Add input to separate two RPC requests
+ eq({ blocking = false, mode = 'nt' }, api.nvim_get_mode())
feed('a')
- eq({ blocking=false, mode='t' }, nvim('get_mode'))
+ eq({ blocking = false, mode = 't' }, api.nvim_get_mode())
end)
it('switching to terminal buffer in Insert mode goes to Terminal mode #7164', function()
@@ -134,77 +139,73 @@ describe(':terminal', function()
command('autocmd InsertLeave * let g:events += ["InsertLeave"]')
command('autocmd TermEnter * let g:events += ["TermEnter"]')
command('inoremap <F2> <Cmd>wincmd p<CR>')
- eq({ blocking=false, mode='i' }, nvim('get_mode'))
+ eq({ blocking = false, mode = 'i' }, api.nvim_get_mode())
feed('<F2>')
- eq({ blocking=false, mode='t' }, nvim('get_mode'))
- eq({'InsertLeave', 'TermEnter'}, eval('g:events'))
+ eq({ blocking = false, mode = 't' }, api.nvim_get_mode())
+ eq({ 'InsertLeave', 'TermEnter' }, eval('g:events'))
+ end)
+
+ it('switching to terminal buffer immediately after :stopinsert #27031', function()
+ command('terminal')
+ command('vnew')
+ feed('i')
+ eq({ blocking = false, mode = 'i' }, api.nvim_get_mode())
+ command('stopinsert | wincmd p')
+ eq({ blocking = false, mode = 'nt' }, api.nvim_get_mode())
end)
end)
-describe(':terminal (with fake shell)', function()
+local function test_terminal_with_fake_shell(backslash)
+ -- shell-test.c is a fake shell that prints its arguments and exits.
+ local shell_path = testprg('shell-test')
+ if backslash then
+ shell_path = shell_path:gsub('/', [[\]])
+ end
+
local screen
before_each(function()
clear()
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_value', 'shell', testprg('shell-test'), {})
- nvim('set_option_value', 'shellcmdflag', 'EXE', {})
- nvim('set_option_value', 'shellxquote', '', {})
+ screen:attach({ rgb = false })
+ api.nvim_set_option_value('shell', shell_path, {})
+ api.nvim_set_option_value('shellcmdflag', 'EXE', {})
+ api.nvim_set_option_value('shellxquote', '', {}) -- win: avoid extra quotes
end)
- -- Invokes `:terminal {cmd}` using a fake shell (shell-test.c) which prints
- -- the {cmd} and exits immediately.
- -- When no argument is given and the exit code is zero, the terminal buffer
- -- closes automatically.
- local function terminal_with_fake_shell(cmd)
- feed_command("terminal "..(cmd and cmd or ""))
- end
-
it('with no argument, acts like termopen()', function()
- skip(is_os('win'))
- -- Use the EXIT subcommand to end the process with a non-zero exit code to
- -- prevent the buffer from closing automatically
- nvim('set_option_value', 'shellcmdflag', 'EXIT', {})
- terminal_with_fake_shell(1)
- retry(nil, 4 * screen.timeout, function()
+ command('autocmd! nvim_terminal TermClose')
+ feed_command('terminal')
screen:expect([[
- ^ |
- [Process exited 1] |
+ ^ready $ |
+ [Process exited 0] |
|
- :terminal 1 |
+ :terminal |
]])
- end)
end)
it("with no argument, and 'shell' is set to empty string", function()
- nvim('set_option_value', 'shell', '', {})
- terminal_with_fake_shell()
+ api.nvim_set_option_value('shell', '', {})
+ feed_command('terminal')
screen:expect([[
^ |
- ~ |
- ~ |
+ ~ |*2
E91: 'shell' option is empty |
]])
end)
it("with no argument, but 'shell' has arguments, acts like termopen()", function()
- skip(is_os('win'))
- nvim('set_option_value', 'shell', testprg('shell-test')..' -t jeff', {})
- terminal_with_fake_shell()
+ api.nvim_set_option_value('shell', shell_path .. ' INTERACT', {})
+ feed_command('terminal')
screen:expect([[
- ^jeff $ |
- [Process exited 0] |
- |
+ ^interact $ |
+ |*2
:terminal |
]])
end)
it('executes a given command through the shell', function()
- skip(is_os('win'))
- command('set shellxquote=') -- win: avoid extra quotes
- terminal_with_fake_shell('echo hi')
+ feed_command('terminal echo hi')
screen:expect([[
^ready $ echo hi |
|
@@ -214,10 +215,8 @@ describe(':terminal (with fake shell)', function()
end)
it("executes a given command through the shell, when 'shell' has arguments", function()
- skip(is_os('win'))
- nvim('set_option_value', 'shell', testprg('shell-test')..' -t jeff', {})
- command('set shellxquote=') -- win: avoid extra quotes
- terminal_with_fake_shell('echo hi')
+ api.nvim_set_option_value('shell', shell_path .. ' -t jeff', {})
+ feed_command('terminal echo hi')
screen:expect([[
^jeff $ echo hi |
|
@@ -227,9 +226,7 @@ describe(':terminal (with fake shell)', function()
end)
it('allows quotes and slashes', function()
- skip(is_os('win'))
- command('set shellxquote=') -- win: avoid extra quotes
- terminal_with_fake_shell([[echo 'hello' \ "world"]])
+ feed_command([[terminal echo 'hello' \ "world"]])
screen:expect([[
^ready $ echo 'hello' \ "world" |
|
@@ -242,38 +239,39 @@ describe(':terminal (with fake shell)', function()
source([[
autocmd BufNew * set shell=foo
terminal]])
- -- Verify that BufNew actually fired (else the test is invalid).
+ -- Verify that BufNew actually fired (else the test is invalid).
eq('foo', eval('&shell'))
end)
it('ignores writes if the backing stream closes', function()
- terminal_with_fake_shell()
- feed('iiXXXXXXX')
- poke_eventloop()
- -- Race: Though the shell exited (and streams were closed by SIGCHLD
- -- handler), :terminal cleanup is pending on the main-loop.
- -- This write should be ignored (not crash, #5445).
- feed('iiYYYYYYY')
- assert_alive()
+ command('autocmd! nvim_terminal TermClose')
+ feed_command('terminal')
+ feed('iiXXXXXXX')
+ poke_eventloop()
+ -- Race: Though the shell exited (and streams were closed by SIGCHLD
+ -- handler), :terminal cleanup is pending on the main-loop.
+ -- This write should be ignored (not crash, #5445).
+ feed('iiYYYYYYY')
+ assert_alive()
end)
it('works with findfile()', function()
+ command('autocmd! nvim_terminal TermClose')
feed_command('terminal')
- eq('term://', string.match(eval('bufname("%")'), "^term://"))
+ eq('term://', string.match(eval('bufname("%")'), '^term://'))
eq('scripts/shadacat.py', eval('findfile("scripts/shadacat.py", ".")'))
end)
it('works with :find', function()
- skip(is_os('win'))
- nvim('set_option_value', 'shellcmdflag', 'EXIT', {})
- terminal_with_fake_shell(1)
+ command('autocmd! nvim_terminal TermClose')
+ feed_command('terminal')
screen:expect([[
- ^ |
- [Process exited 1] |
+ ^ready $ |
+ [Process exited 0] |
|
- :terminal 1 |
+ :terminal |
]])
- eq('term://', string.match(eval('bufname("%")'), "^term://"))
+ eq('term://', string.match(eval('bufname("%")'), '^term://'))
feed([[<C-\><C-N>]])
feed_command([[find */shadacat.py]])
if is_os('win') then
@@ -284,19 +282,15 @@ describe(':terminal (with fake shell)', function()
end)
it('works with gf', function()
- skip(is_os('win'))
- command('set shellxquote=') -- win: avoid extra quotes
- terminal_with_fake_shell([[echo "scripts/shadacat.py"]])
- retry(nil, 4 * screen.timeout, function()
+ feed_command([[terminal echo "scripts/shadacat.py"]])
screen:expect([[
^ready $ echo "scripts/shadacat.py" |
|
[Process exited 0] |
:terminal echo "scripts/shadacat.py" |
]])
- end)
feed([[<C-\><C-N>]])
- eq('term://', string.match(eval('bufname("%")'), "^term://"))
+ eq('term://', string.match(eval('bufname("%")'), '^term://'))
feed([[ggf"lgf]])
eq('scripts/shadacat.py', eval('bufname("%")'))
end)
@@ -311,4 +305,29 @@ describe(':terminal (with fake shell)', function()
terminal]])
end
end)
+
+ describe('exit does not have long delay #27615', function()
+ for _, ut in ipairs({ 5, 50, 500, 5000, 50000, 500000 }) do
+ it(('with updatetime=%d'):format(ut), function()
+ api.nvim_set_option_value('updatetime', ut, {})
+ api.nvim_set_option_value('shellcmdflag', 'EXIT', {})
+ feed_command('terminal 42')
+ screen:expect([[
+ ^ |
+ [Process exited 42] |
+ |
+ :terminal 42 |
+ ]])
+ end)
+ end
+ end)
+end
+
+describe(':terminal (with fake shell)', function()
+ test_terminal_with_fake_shell(false)
+ if is_os('win') then
+ describe("when 'shell' uses backslashes", function()
+ test_terminal_with_fake_shell(true)
+ end)
+ end
end)
diff --git a/test/functional/terminal/helpers.lua b/test/functional/terminal/helpers.lua
index 62d3dd67a3..05db1b3c8c 100644
--- a/test/functional/terminal/helpers.lua
+++ b/test/functional/terminal/helpers.lua
@@ -5,11 +5,12 @@ local helpers = require('test.functional.helpers')(nil)
local Screen = require('test.functional.ui.screen')
local testprg = helpers.testprg
local exec_lua = helpers.exec_lua
-local nvim = helpers.nvim
+local api = helpers.api
+local nvim_prog = helpers.nvim_prog
local function feed_data(data)
if type(data) == 'table' then
- data = table.concat(data, '\n')
+ data = table.concat(data, '\n')
end
exec_lua('vim.api.nvim_chan_send(vim.b.terminal_job_id, ...)', data)
end
@@ -20,7 +21,7 @@ end
local function make_lua_executor(session)
return function(code, ...)
- local status, rv = session:request('nvim_exec_lua', code, {...})
+ local status, rv = session:request('nvim_exec_lua', code, { ... })
if not status then
session:stop()
error(rv[2])
@@ -32,76 +33,108 @@ end
-- some helpers for controlling the terminal. the codes were taken from
-- infocmp xterm-256color which is less what libvterm understands
-- civis/cnorm
-local function hide_cursor() feed_termcode('[?25l') end
-local function show_cursor() feed_termcode('[?25h') end
+local function hide_cursor()
+ feed_termcode('[?25l')
+end
+local function show_cursor()
+ feed_termcode('[?25h')
+end
-- smcup/rmcup
-local function enter_altscreen() feed_termcode('[?1049h') end
-local function exit_altscreen() feed_termcode('[?1049l') end
+local function enter_altscreen()
+ feed_termcode('[?1049h')
+end
+local function exit_altscreen()
+ feed_termcode('[?1049l')
+end
-- character attributes
-local function set_fg(num) feed_termcode('[38;5;'..num..'m') end
-local function set_bg(num) feed_termcode('[48;5;'..num..'m') end
-local function set_bold() feed_termcode('[1m') end
-local function set_italic() feed_termcode('[3m') end
-local function set_underline() feed_termcode('[4m') end
-local function set_underdouble() feed_termcode('[4:2m') end
-local function set_undercurl() feed_termcode('[4:3m') end
-local function set_strikethrough() feed_termcode('[9m') end
-local function clear_attrs() feed_termcode('[0;10m') end
+local function set_fg(num)
+ feed_termcode('[38;5;' .. num .. 'm')
+end
+local function set_bg(num)
+ feed_termcode('[48;5;' .. num .. 'm')
+end
+local function set_bold()
+ feed_termcode('[1m')
+end
+local function set_italic()
+ feed_termcode('[3m')
+end
+local function set_underline()
+ feed_termcode('[4m')
+end
+local function set_underdouble()
+ feed_termcode('[4:2m')
+end
+local function set_undercurl()
+ feed_termcode('[4:3m')
+end
+local function set_strikethrough()
+ feed_termcode('[9m')
+end
+local function clear_attrs()
+ feed_termcode('[0;10m')
+end
-- mouse
-local function enable_mouse() feed_termcode('[?1002h') end
-local function disable_mouse() feed_termcode('[?1002l') end
+local function enable_mouse()
+ feed_termcode('[?1002h')
+end
+local function disable_mouse()
+ feed_termcode('[?1002l')
+end
-local default_command = '["'..testprg('tty-test')..'"]'
+local default_command = { testprg('tty-test') }
-local function screen_setup(extra_rows, command, cols, opts)
+local function screen_setup(extra_rows, command, cols, env, screen_opts)
extra_rows = extra_rows and extra_rows or 0
command = command and command or default_command
cols = cols and cols or 50
- nvim('command', 'highlight TermCursor cterm=reverse')
- nvim('command', 'highlight TermCursorNC ctermbg=11')
+ api.nvim_command('highlight TermCursor cterm=reverse')
+ api.nvim_command('highlight TermCursorNC ctermbg=11')
local screen = Screen.new(cols, 7 + extra_rows)
screen:set_default_attr_ids({
- [1] = {reverse = true}, -- focused cursor
- [2] = {background = 11}, -- unfocused cursor
- [3] = {bold = true},
- [4] = {foreground = 12},
- [5] = {bold = true, reverse = true},
- -- 6 was a duplicate item
- [7] = {foreground = 130},
- [8] = {foreground = 15, background = 1}, -- error message
- [9] = {foreground = 4},
- [10] = {foreground = 121}, -- "Press ENTER" in embedded :terminal session.
- [11] = {foreground = tonumber('0x00000b')},
- [12] = {underline = true},
- [13] = {underline = true, reverse = true},
- [14] = {underline = true, reverse = true, bold = true},
- [15] = {underline = true, foreground = 12},
+ [1] = { reverse = true }, -- focused cursor
+ [2] = { background = 11 }, -- unfocused cursor
+ [3] = { bold = true },
+ [4] = { foreground = 12 }, -- NonText in :terminal session
+ [5] = { bold = true, reverse = true },
+ [6] = { foreground = 81 }, -- SpecialKey in :terminal session
+ [7] = { foreground = 130 }, -- LineNr in host session
+ [8] = { foreground = 15, background = 1 }, -- ErrorMsg in :terminal session
+ [9] = { foreground = 4 },
+ [10] = { foreground = 121 }, -- MoreMsg in :terminal session
+ [11] = { foreground = 11 }, -- LineNr in :terminal session
+ [12] = { underline = true },
+ [13] = { underline = true, reverse = true },
+ [14] = { underline = true, reverse = true, bold = true },
+ [15] = { underline = true, foreground = 12 },
+ [16] = { background = 248, foreground = 0 }, -- Visual in :terminal session
})
- screen:attach(opts or {rgb=false})
+ screen:attach(screen_opts or { rgb = false })
- nvim('command', 'enew | call termopen('..command..')')
- nvim('input', '<CR>')
- local vim_errmsg = nvim('eval', 'v:errmsg')
- if vim_errmsg and "" ~= vim_errmsg then
+ api.nvim_command('enew')
+ api.nvim_call_function('termopen', { command, env and { env = env } or nil })
+ api.nvim_input('<CR>')
+ local vim_errmsg = api.nvim_eval('v:errmsg')
+ if vim_errmsg and '' ~= vim_errmsg then
error(vim_errmsg)
end
- nvim('command', 'setlocal scrollback=10')
- nvim('command', 'startinsert')
- nvim('input', '<Ignore>') -- Add input to separate two RPC requests
+ api.nvim_command('setlocal scrollback=10')
+ api.nvim_command('startinsert')
+ api.nvim_input('<Ignore>') -- Add input to separate two RPC requests
-- tty-test puts the terminal into raw mode and echoes input. Tests work by
-- feeding termcodes to control the display and asserting by screen:expect.
- if command == default_command and opts == nil then
+ if command == default_command and screen_opts == nil then
-- Wait for "tty ready" to be printed before each test or the terminal may
-- still be in canonical mode (will echo characters for example).
local empty_line = (' '):rep(cols)
local expected = {
- 'tty ready'..(' '):rep(cols - 9),
- '{1: }' ..(' '):rep(cols - 1),
+ 'tty ready' .. (' '):rep(cols - 9),
+ '{1: }' .. (' '):rep(cols - 1),
empty_line,
empty_line,
empty_line,
@@ -112,16 +145,28 @@ local function screen_setup(extra_rows, command, cols, opts)
end
table.insert(expected, '{3:-- TERMINAL --}' .. ((' '):rep(cols - 14)))
- screen:expect(table.concat(expected, '|\n')..'|')
+ screen:expect(table.concat(expected, '|\n') .. '|')
else
-- This eval also acts as a poke_eventloop().
- if 0 == nvim('eval', "exists('b:terminal_job_id')") then
- error("terminal job failed to start")
+ if 0 == api.nvim_eval("exists('b:terminal_job_id')") then
+ error('terminal job failed to start')
end
end
return screen
end
+local function setup_child_nvim(args, opts)
+ opts = opts or {}
+ local argv = { nvim_prog, unpack(args) }
+
+ local env = opts.env or {}
+ if not env.VIMRUNTIME then
+ env.VIMRUNTIME = os.getenv('VIMRUNTIME')
+ end
+
+ return screen_setup(0, argv, opts.cols, env)
+end
+
return {
feed_data = feed_data,
feed_termcode = feed_termcode,
@@ -141,5 +186,6 @@ return {
clear_attrs = clear_attrs,
enable_mouse = enable_mouse,
disable_mouse = disable_mouse,
- screen_setup = screen_setup
+ screen_setup = screen_setup,
+ setup_child_nvim = setup_child_nvim,
}
diff --git a/test/functional/terminal/highlight_spec.lua b/test/functional/terminal/highlight_spec.lua
index 2ac45771d4..ec057c6766 100644
--- a/test/functional/terminal/highlight_spec.lua
+++ b/test/functional/terminal/highlight_spec.lua
@@ -1,11 +1,12 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local thelpers = require('test.functional.terminal.helpers')
-local feed, clear, nvim = helpers.feed, helpers.clear, helpers.nvim
+local feed, clear = helpers.feed, helpers.clear
+local api = helpers.api
local testprg, command = helpers.testprg, helpers.command
local nvim_prog_abs = helpers.nvim_prog_abs
local eq, eval = helpers.eq, helpers.eval
-local funcs = helpers.funcs
+local fn = helpers.fn
local nvim_set = helpers.nvim_set
local is_os = helpers.is_os
local skip = helpers.skip
@@ -17,30 +18,27 @@ describe(':terminal highlight', function()
clear()
screen = Screen.new(50, 7)
screen:set_default_attr_ids({
- [1] = {foreground = 45},
- [2] = {background = 46},
- [3] = {foreground = 45, background = 46},
- [4] = {bold = true, italic = true, underline = true, strikethrough = true},
- [5] = {bold = true},
- [6] = {foreground = 12},
- [7] = {bold = true, reverse = true},
- [8] = {background = 11},
- [9] = {foreground = 130},
- [10] = {reverse = true},
- [11] = {background = 11},
- [12] = {bold = true, underdouble = true},
- [13] = {italic = true, undercurl = true},
+ [1] = { foreground = 45 },
+ [2] = { background = 46 },
+ [3] = { foreground = 45, background = 46 },
+ [4] = { bold = true, italic = true, underline = true, strikethrough = true },
+ [5] = { bold = true },
+ [6] = { foreground = 12 },
+ [7] = { bold = true, reverse = true },
+ [8] = { background = 11 },
+ [9] = { foreground = 130 },
+ [10] = { reverse = true },
+ [11] = { background = 11 },
+ [12] = { bold = true, underdouble = true },
+ [13] = { italic = true, undercurl = true },
})
- screen:attach({rgb=false})
+ screen:attach({ rgb = false })
command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
feed('i')
screen:expect([[
tty ready |
{10: } |
- |
- |
- |
- |
+ |*4
{5:-- TERMINAL --} |
]])
end)
@@ -64,10 +62,7 @@ describe(':terminal highlight', function()
screen:expect(sub([[
tty ready |
{NUM:text}text{10: } |
- |
- |
- |
- |
+ |*4
{5:-- TERMINAL --} |
]]))
end
@@ -79,7 +74,7 @@ describe(':terminal highlight', function()
pass_attrs()
local lines = {}
for i = 1, 8 do
- table.insert(lines, 'line'..tostring(i))
+ table.insert(lines, 'line' .. tostring(i))
end
table.insert(lines, '')
thelpers.feed_data(lines)
@@ -106,8 +101,12 @@ describe(':terminal highlight', function()
end)
end
- descr('foreground', 1, function() thelpers.set_fg(45) end)
- descr('background', 2, function() thelpers.set_bg(46) end)
+ descr('foreground', 1, function()
+ thelpers.set_fg(45)
+ end)
+ descr('background', 2, function()
+ thelpers.set_bg(46)
+ end)
descr('foreground and background', 3, function()
thelpers.set_fg(45)
thelpers.set_bg(46)
@@ -133,20 +132,41 @@ it(':terminal highlight has lower precedence than editor #9964', function()
local screen = Screen.new(30, 4)
screen:set_default_attr_ids({
-- "Normal" highlight emitted by the child nvim process.
- N_child = {foreground = tonumber('0x4040ff'), background = tonumber('0xffff40'), fg_indexed=true, bg_indexed=true},
+ N_child = {
+ foreground = tonumber('0x4040ff'),
+ background = tonumber('0xffff40'),
+ fg_indexed = true,
+ bg_indexed = true,
+ },
-- "Search" highlight in the parent nvim process.
- S = {background = Screen.colors.Green, italic = true, foreground = Screen.colors.Red},
+ S = { background = Screen.colors.Green, italic = true, foreground = Screen.colors.Red },
-- "Question" highlight in the parent nvim process.
-- note: bg is indexed as it comes from the (cterm) child, while fg isn't as it comes from (rgb) parent
- Q = {background = tonumber('0xffff40'), bold = true, foreground = Screen.colors.SeaGreen4, bg_indexed=true},
+ Q = {
+ background = tonumber('0xffff40'),
+ bold = true,
+ foreground = Screen.colors.SeaGreen4,
+ bg_indexed = true,
+ },
})
- screen:attach({rgb=true})
+ screen:attach({ rgb = true })
-- Child nvim process in :terminal (with cterm colors).
- funcs.termopen({
- nvim_prog_abs(), '-n', '-u', 'NORC', '-i', 'NONE', '--cmd', nvim_set,
+ fn.termopen({
+ nvim_prog_abs(),
+ '-n',
+ '-u',
+ 'NORC',
+ '-i',
+ 'NONE',
+ '--cmd',
+ nvim_set .. ' notermguicolors',
'+hi Normal ctermfg=Blue ctermbg=Yellow',
'+norm! ichild nvim',
'+norm! oline 2',
+ }, {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+ },
})
screen:expect([[
{N_child:^child nvim }|
@@ -179,10 +199,10 @@ describe(':terminal highlight forwarding', function()
screen = Screen.new(50, 7)
screen:set_rgb_cterm(true)
screen:set_default_attr_ids({
- [1] = {{reverse = true}, {reverse = true}},
- [2] = {{bold = true}, {bold = true}},
- [3] = {{fg_indexed = true, foreground = tonumber('0xe0e000')}, {foreground = 3}},
- [4] = {{foreground = tonumber('0xff8000')}, {}},
+ [1] = { { reverse = true }, { reverse = true } },
+ [2] = { { bold = true }, { bold = true } },
+ [3] = { { fg_indexed = true, foreground = tonumber('0xe0e000') }, { foreground = 3 } },
+ [4] = { { foreground = tonumber('0xff8000') }, {} },
})
screen:attach()
command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
@@ -190,10 +210,7 @@ describe(':terminal highlight forwarding', function()
screen:expect([[
tty ready |
{1: } |
- |
- |
- |
- |
+ |*4
{2:-- TERMINAL --} |
]])
end)
@@ -206,19 +223,17 @@ describe(':terminal highlight forwarding', function()
thelpers.feed_data('color')
thelpers.clear_attrs()
thelpers.feed_data('text')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
tty ready |
{3:text}{4:color}text{1: } |
- |
- |
- |
- |
+ |*4
{2:-- TERMINAL --} |
- ]]}
+ ]],
+ }
end)
end)
-
describe(':terminal highlight with custom palette', function()
local screen
@@ -226,26 +241,23 @@ describe(':terminal highlight with custom palette', function()
clear()
screen = Screen.new(50, 7)
screen:set_default_attr_ids({
- [1] = {foreground = tonumber('0x123456')}, -- no fg_indexed when overridden
- [2] = {foreground = 12},
- [3] = {bold = true, reverse = true},
- [5] = {background = 11},
- [6] = {foreground = 130},
- [7] = {reverse = true},
- [8] = {background = 11},
- [9] = {bold = true},
+ [1] = { foreground = tonumber('0x123456') }, -- no fg_indexed when overridden
+ [2] = { foreground = 12 },
+ [3] = { bold = true, reverse = true },
+ [5] = { background = 11 },
+ [6] = { foreground = 130 },
+ [7] = { reverse = true },
+ [8] = { background = 11 },
+ [9] = { bold = true },
})
- screen:attach({rgb=true})
- nvim('set_var', 'terminal_color_3', '#123456')
+ screen:attach({ rgb = true })
+ api.nvim_set_var('terminal_color_3', '#123456')
command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
feed('i')
screen:expect([[
tty ready |
{7: } |
- |
- |
- |
- |
+ |*4
{9:-- TERMINAL --} |
]])
end)
@@ -259,10 +271,7 @@ describe(':terminal highlight with custom palette', function()
screen:expect([[
tty ready |
{1:text}text{7: } |
- |
- |
- |
- |
+ |*4
{9:-- TERMINAL --} |
]])
end)
@@ -275,35 +284,37 @@ describe('synIDattr()', function()
screen = Screen.new(50, 7)
command('highlight Normal ctermfg=252 guifg=#ff0000 guibg=Black')
-- Salmon #fa8072 Maroon #800000
- command('highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon cterm=strikethrough gui=strikethrough')
+ command(
+ 'highlight Keyword ctermfg=79 guifg=Salmon guisp=Maroon cterm=strikethrough gui=strikethrough'
+ )
end)
it('returns cterm-color if RGB-capable UI is _not_ attached', function()
eq('252', eval('synIDattr(hlID("Normal"), "fg")'))
eq('252', eval('synIDattr(hlID("Normal"), "fg#")'))
- eq('', eval('synIDattr(hlID("Normal"), "bg")'))
- eq('', eval('synIDattr(hlID("Normal"), "bg#")'))
- eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
- eq('79', eval('synIDattr(hlID("Keyword"), "fg#")'))
- eq('', eval('synIDattr(hlID("Keyword"), "sp")'))
- eq('', eval('synIDattr(hlID("Keyword"), "sp#")'))
+ eq('', eval('synIDattr(hlID("Normal"), "bg")'))
+ eq('', eval('synIDattr(hlID("Normal"), "bg#")'))
+ eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
+ eq('79', eval('synIDattr(hlID("Keyword"), "fg#")'))
+ eq('', eval('synIDattr(hlID("Keyword"), "sp")'))
+ eq('', eval('synIDattr(hlID("Keyword"), "sp#")'))
end)
it('returns gui-color if "gui" arg is passed', function()
- eq('Black', eval('synIDattr(hlID("Normal"), "bg", "gui")'))
+ eq('Black', eval('synIDattr(hlID("Normal"), "bg", "gui")'))
eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp", "gui")'))
end)
it('returns gui-color if RGB-capable UI is attached', function()
- screen:attach({rgb=true})
+ screen:attach({ rgb = true })
eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg")'))
- eq('Black', eval('synIDattr(hlID("Normal"), "bg")'))
- eq('Salmon', eval('synIDattr(hlID("Keyword"), "fg")'))
- eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp")'))
+ eq('Black', eval('synIDattr(hlID("Normal"), "bg")'))
+ eq('Salmon', eval('synIDattr(hlID("Keyword"), "fg")'))
+ eq('Maroon', eval('synIDattr(hlID("Keyword"), "sp")'))
end)
it('returns #RRGGBB value for fg#/bg#/sp#', function()
- screen:attach({rgb=true})
+ screen:attach({ rgb = true })
eq('#ff0000', eval('synIDattr(hlID("Normal"), "fg#")'))
eq('#000000', eval('synIDattr(hlID("Normal"), "bg#")'))
eq('#fa8072', eval('synIDattr(hlID("Keyword"), "fg#")'))
@@ -311,19 +322,24 @@ describe('synIDattr()', function()
end)
it('returns color number if non-GUI', function()
- screen:attach({rgb=false})
+ screen:attach({ rgb = false })
eq('252', eval('synIDattr(hlID("Normal"), "fg")'))
eq('79', eval('synIDattr(hlID("Keyword"), "fg")'))
end)
it('returns "1" if group has given highlight attribute', function()
local hl_attrs = {
- 'underline', 'undercurl', 'underdouble', 'underdotted', 'underdashed', 'strikethrough'
+ 'underline',
+ 'undercurl',
+ 'underdouble',
+ 'underdotted',
+ 'underdashed',
+ 'strikethrough',
}
- for _,hl_attr in ipairs(hl_attrs) do
+ for _, hl_attr in ipairs(hl_attrs) do
local context = 'using ' .. hl_attr .. ' attr'
command('highlight Keyword cterm=' .. hl_attr .. ' gui=' .. hl_attr)
- eq('', eval('synIDattr(hlID("Normal"), "'.. hl_attr .. '")'), context)
+ eq('', eval('synIDattr(hlID("Normal"), "' .. hl_attr .. '")'), context)
eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '")'), context)
eq('1', eval('synIDattr(hlID("Keyword"), "' .. hl_attr .. '", "gui")'), context)
end
@@ -340,14 +356,10 @@ describe('fg/bg special colors', function()
end)
it('resolve to "Normal" values', function()
- eq(eval('synIDattr(hlID("Normal"), "bg")'),
- eval('synIDattr(hlID("Visual"), "fg")'))
- eq(eval('synIDattr(hlID("Normal"), "bg#")'),
- eval('synIDattr(hlID("Visual"), "fg#")'))
- eq(eval('synIDattr(hlID("Normal"), "fg")'),
- eval('synIDattr(hlID("Visual"), "bg")'))
- eq(eval('synIDattr(hlID("Normal"), "fg#")'),
- eval('synIDattr(hlID("Visual"), "bg#")'))
+ eq(eval('synIDattr(hlID("Normal"), "bg")'), eval('synIDattr(hlID("Visual"), "fg")'))
+ eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")'))
+ eq(eval('synIDattr(hlID("Normal"), "fg")'), eval('synIDattr(hlID("Visual"), "bg")'))
+ eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")'))
eq('bg', eval('synIDattr(hlID("Visual"), "fg", "gui")'))
eq('bg', eval('synIDattr(hlID("Visual"), "fg#", "gui")'))
eq('fg', eval('synIDattr(hlID("Visual"), "bg", "gui")'))
@@ -357,23 +369,20 @@ describe('fg/bg special colors', function()
end)
it('resolve to "Normal" values in RGB-capable UI', function()
- screen:attach({rgb=true})
+ screen:attach({ rgb = true })
eq('bg', eval('synIDattr(hlID("Visual"), "fg")'))
- eq(eval('synIDattr(hlID("Normal"), "bg#")'),
- eval('synIDattr(hlID("Visual"), "fg#")'))
+ eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "fg#")'))
eq('fg', eval('synIDattr(hlID("Visual"), "bg")'))
- eq(eval('synIDattr(hlID("Normal"), "fg#")'),
- eval('synIDattr(hlID("Visual"), "bg#")'))
+ eq(eval('synIDattr(hlID("Normal"), "fg#")'), eval('synIDattr(hlID("Visual"), "bg#")'))
eq('bg', eval('synIDattr(hlID("Visual"), "sp")'))
- eq(eval('synIDattr(hlID("Normal"), "bg#")'),
- eval('synIDattr(hlID("Visual"), "sp#")'))
+ eq(eval('synIDattr(hlID("Normal"), "bg#")'), eval('synIDattr(hlID("Visual"), "sp#")'))
end)
it('resolve after the "Normal" group is modified', function()
- screen:attach({rgb=true})
+ screen:attach({ rgb = true })
local new_guibg = '#282c34'
local new_guifg = '#abb2bf'
- command('highlight Normal guifg='..new_guifg..' guibg='..new_guibg)
+ command('highlight Normal guifg=' .. new_guifg .. ' guibg=' .. new_guibg)
eq(new_guibg, eval('synIDattr(hlID("Visual"), "fg#")'))
eq(new_guifg, eval('synIDattr(hlID("Visual"), "bg#")'))
eq(new_guibg, eval('synIDattr(hlID("Visual"), "sp#")'))
diff --git a/test/functional/terminal/mouse_spec.lua b/test/functional/terminal/mouse_spec.lua
index 3291a38e03..0395d5ee16 100644
--- a/test/functional/terminal/mouse_spec.lua
+++ b/test/functional/terminal/mouse_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
local clear, eq, eval = helpers.clear, helpers.eq, helpers.eval
-local feed, nvim, command = helpers.feed, helpers.nvim, helpers.command
+local feed, api, command = helpers.feed, helpers.api, helpers.command
local feed_data = thelpers.feed_data
local is_os = helpers.is_os
local skip = helpers.skip
@@ -11,14 +11,14 @@ describe(':terminal mouse', function()
before_each(function()
clear()
- nvim('set_option_value', 'statusline', '==========', {})
+ api.nvim_set_option_value('statusline', '==========', {})
command('highlight StatusLine cterm=NONE')
command('highlight StatusLineNC cterm=NONE')
command('highlight VertSplit cterm=NONE')
screen = thelpers.screen_setup()
local lines = {}
for i = 1, 30 do
- table.insert(lines, 'line'..tostring(i))
+ table.insert(lines, 'line' .. tostring(i))
end
table.insert(lines, '')
feed_data(lines)
@@ -243,6 +243,134 @@ describe(':terminal mouse', function()
{3:-- TERMINAL --} |
]])
end)
+
+ it('will lose focus if statusline is clicked', function()
+ command('set laststatus=2')
+ screen:expect([[
+ line29 |
+ line30 |
+ mouse enabled |
+ rows: 5, cols: 50 |
+ {1: } |
+ ========== |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<LeftMouse><0,5>')
+ screen:expect([[
+ line29 |
+ line30 |
+ mouse enabled |
+ rows: 5, cols: 50 |
+ {2:^ } |
+ ========== |
+ |
+ ]])
+ feed('<LeftDrag><0,4>')
+ screen:expect([[
+ mouse enabled |
+ rows: 5, cols: 50 |
+ rows: 4, cols: 50 |
+ {2:^ } |
+ ========== |
+ |*2
+ ]])
+ end)
+
+ it('will lose focus if right separator is clicked', function()
+ command('rightbelow vnew | wincmd p | startinsert')
+ screen:expect([[
+ line29 │ |
+ line30 │{4:~ }|
+ mouse enabled │{4:~ }|
+ rows: 5, cols: 24 │{4:~ }|
+ {1: } │{4:~ }|
+ ========== ========== |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<LeftMouse><24,0>')
+ screen:expect([[
+ line29 │ |
+ line30 │{4:~ }|
+ mouse enabled │{4:~ }|
+ rows: 5, cols: 24 │{4:~ }|
+ {2:^ } │{4:~ }|
+ ========== ========== |
+ |
+ ]])
+ feed('<LeftDrag><23,0>')
+ screen:expect([[
+ line30 │ |
+ mouse enabled │{4:~ }|
+ rows: 5, cols: 24 │{4:~ }|
+ rows: 5, cols: 23 │{4:~ }|
+ {2:^ } │{4:~ }|
+ ========== ========== |
+ |
+ ]])
+ end)
+
+ it('will lose focus if winbar/tabline is clicked', function()
+ command('setlocal winbar=WINBAR')
+ screen:expect([[
+ {3:WINBAR }|
+ line29 |
+ line30 |
+ mouse enabled |
+ rows: 5, cols: 50 |
+ {1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<LeftMouse><0,0>')
+ screen:expect([[
+ {3:WINBAR }|
+ line29 |
+ line30 |
+ mouse enabled |
+ rows: 5, cols: 50 |
+ {2:^ } |
+ |
+ ]])
+ command('set showtabline=2 tabline=TABLINE | startinsert')
+ screen:expect([[
+ {1:TABLINE }|
+ {3:WINBAR }|
+ mouse enabled |
+ rows: 5, cols: 50 |
+ rows: 4, cols: 50 |
+ {1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<LeftMouse><0,0>')
+ screen:expect([[
+ {1:TABLINE }|
+ {3:WINBAR }|
+ mouse enabled |
+ rows: 5, cols: 50 |
+ rows: 4, cols: 50 |
+ {2:^ } |
+ |
+ ]])
+ command('setlocal winbar= | startinsert')
+ screen:expect([[
+ {1:TABLINE }|
+ mouse enabled |
+ rows: 5, cols: 50 |
+ rows: 4, cols: 50 |
+ rows: 5, cols: 50 |
+ {1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ feed('<LeftMouse><0,0>')
+ screen:expect([[
+ {1:TABLINE }|
+ mouse enabled |
+ rows: 5, cols: 50 |
+ rows: 4, cols: 50 |
+ rows: 5, cols: 50 |
+ {2:^ } |
+ |
+ ]])
+ end)
end)
describe('with a split window and other buffer', function()
@@ -386,7 +514,7 @@ describe(':terminal mouse', function()
end)
it('handles terminal size when switching buffers', function()
- nvim('set_option_value', 'hidden', true, {})
+ api.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 1e278e4cff..858e23984d 100644
--- a/test/functional/terminal/scrollback_spec.lua
+++ b/test/functional/terminal/scrollback_spec.lua
@@ -1,14 +1,13 @@
local Screen = require('test.functional.ui.screen')
local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers')
-local clear, eq, curbuf = helpers.clear, helpers.eq, helpers.curbuf
+local clear, eq = helpers.clear, helpers.eq
local feed, testprg = helpers.feed, helpers.testprg
local eval = helpers.eval
local command = helpers.command
local poke_eventloop = helpers.poke_eventloop
local retry = helpers.retry
-local meths = helpers.meths
-local nvim = helpers.nvim
+local api = helpers.api
local feed_data = thelpers.feed_data
local pcall_err = helpers.pcall_err
local exec_lua = helpers.exec_lua
@@ -28,7 +27,7 @@ describe(':terminal scrollback', function()
before_each(function()
local lines = {}
for i = 1, 30 do
- table.insert(lines, 'line'..tostring(i))
+ table.insert(lines, 'line' .. tostring(i))
end
table.insert(lines, '')
feed_data(lines)
@@ -59,7 +58,7 @@ describe(':terminal scrollback', function()
describe('with cursor at last row', function()
before_each(function()
- feed_data({'line1', 'line2', 'line3', 'line4', ''})
+ feed_data({ 'line1', 'line2', 'line3', 'line4', '' })
screen:expect([[
tty ready |
line1 |
@@ -72,7 +71,9 @@ describe(':terminal scrollback', function()
end)
describe('and 1 line is printed', function()
- before_each(function() feed_data({'line5', ''}) end)
+ before_each(function()
+ feed_data({ 'line5', '' })
+ end)
it('will hide the top line', function()
screen:expect([[
@@ -84,11 +85,13 @@ describe(':terminal scrollback', function()
{1: } |
{3:-- TERMINAL --} |
]])
- eq(7, curbuf('line_count'))
+ eq(7, api.nvim_buf_line_count(0))
end)
describe('and then 3 more lines are printed', function()
- before_each(function() feed_data({'line6', 'line7', 'line8'}) end)
+ before_each(function()
+ feed_data({ 'line6', 'line7', 'line8' })
+ end)
it('will hide the top 4 lines', function()
screen:expect([[
@@ -137,7 +140,6 @@ describe(':terminal scrollback', function()
end)
end)
-
describe('and height decreased by 1', function()
local function will_hide_top_line()
feed([[<C-\><C-N>]])
@@ -167,7 +169,7 @@ describe(':terminal scrollback', function()
{2:^ } |
|
]])
- eq(8, curbuf('line_count'))
+ eq(8, api.nvim_buf_line_count(0))
feed([[3k]])
screen:expect([[
^line4 |
@@ -184,7 +186,9 @@ describe(':terminal scrollback', function()
-- XXX: Can't test this reliably on Windows unless the cursor is _moved_
-- by the resize. http://docs.libuv.org/en/v1.x/signal.html
-- See also: https://github.com/rprichard/winpty/issues/110
- if skip(is_os('win')) then return end
+ if skip(is_os('win')) then
+ return
+ end
describe('and the height is decreased by 2', function()
before_each(function()
@@ -199,7 +203,7 @@ describe(':terminal scrollback', function()
|
{3:-- TERMINAL --} |
]])
- eq(4, curbuf('line_count'))
+ eq(4, api.nvim_buf_line_count(0))
end
it('will delete the last two empty lines', will_delete_last_two_lines)
@@ -217,7 +221,7 @@ describe(':terminal scrollback', function()
{1: } |
{3:-- TERMINAL --} |
]])
- eq(4, curbuf('line_count'))
+ eq(4, api.nvim_buf_line_count(0))
feed('<c-\\><c-n>gg')
screen:expect([[
^tty ready |
@@ -239,7 +243,7 @@ describe(':terminal scrollback', function()
describe('with 4 lines hidden in the scrollback', function()
before_each(function()
- feed_data({'line1', 'line2', 'line3', 'line4', ''})
+ feed_data({ 'line1', 'line2', 'line3', 'line4', '' })
screen:expect([[
tty ready |
line1 |
@@ -256,14 +260,16 @@ describe(':terminal scrollback', function()
{1: } |
{3:-- TERMINAL --} |
]])
- eq(7, curbuf('line_count'))
+ eq(7, api.nvim_buf_line_count(0))
end)
describe('and the height is increased by 1', function()
-- XXX: Can't test this reliably on Windows unless the cursor is _moved_
-- by the resize. http://docs.libuv.org/en/v1.x/signal.html
-- See also: https://github.com/rprichard/winpty/issues/110
- if skip(is_os('win')) then return end
+ if skip(is_os('win')) then
+ return
+ end
local function pop_then_push()
screen:try_resize(screen._width, screen._height + 1)
screen:expect([[
@@ -280,7 +286,7 @@ describe(':terminal scrollback', function()
describe('and then by 3', function()
before_each(function()
pop_then_push()
- eq(8, curbuf('line_count'))
+ eq(8, api.nvim_buf_line_count(0))
screen:try_resize(screen._width, screen._height + 3)
end)
@@ -295,7 +301,7 @@ describe(':terminal scrollback', function()
{1: } |
{3:-- TERMINAL --} |
]])
- eq(9, curbuf('line_count'))
+ eq(9, api.nvim_buf_line_count(0))
feed('<c-\\><c-n>gg')
screen:expect([[
^tty ready |
@@ -335,7 +341,7 @@ describe(':terminal scrollback', function()
]])
-- since there's an empty line after the cursor, the buffer line
-- count equals the terminal screen height
- eq(11, curbuf('line_count'))
+ eq(11, api.nvim_buf_line_count(0))
end)
end)
end)
@@ -347,7 +353,7 @@ describe(':terminal prints more lines than the screen height and exits', functio
it('will push extra lines to scrollback', function()
clear()
local screen = Screen.new(30, 7)
- screen:attach({rgb=false})
+ screen:attach({ rgb = false })
command(("call termopen(['%s', '10']) | startinsert"):format(testprg('tty-test')))
screen:expect([[
line6 |
@@ -362,11 +368,7 @@ describe(':terminal prints more lines than the screen height and exits', functio
-- closes the buffer correctly after pressing a key
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*5
|
]])
end)
@@ -378,62 +380,71 @@ describe("'scrollback' option", function()
end)
local function set_fake_shell()
- nvim('set_option_value', 'shell', string.format('"%s" INTERACT', testprg('shell-test')), {})
+ api.nvim_set_option_value('shell', string.format('"%s" INTERACT', testprg('shell-test')), {})
end
local function expect_lines(expected, epsilon)
local ep = epsilon and epsilon or 0
local actual = eval("line('$')")
if expected > actual + ep and expected < actual - ep then
- error('expected (+/- '..ep..'): '..expected..', actual: '..tostring(actual))
+ error('expected (+/- ' .. ep .. '): ' .. expected .. ', actual: ' .. tostring(actual))
end
end
it('set to 0 behaves as 1', function()
local screen
if is_os('win') then
- screen = thelpers.screen_setup(nil, "['cmd.exe']", 30)
+ screen = thelpers.screen_setup(nil, { 'cmd.exe' }, 30)
else
- screen = thelpers.screen_setup(nil, "['sh']", 30)
+ screen = thelpers.screen_setup(nil, { 'sh' }, 30)
end
- meths.set_option_value('scrollback', 0, {})
+ api.nvim_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)
+ screen:expect { any = '30: line ' }
+ retry(nil, nil, function()
+ expect_lines(7)
+ end)
end)
it('deletes lines (only) if necessary', function()
local screen
if is_os('win') then
command([[let $PROMPT='$$']])
- screen = thelpers.screen_setup(nil, "['cmd.exe']", 30)
+ screen = thelpers.screen_setup(nil, { 'cmd.exe' }, 30)
else
command('let $PS1 = "$"')
- screen = thelpers.screen_setup(nil, "['sh']", 30)
+ screen = thelpers.screen_setup(nil, { 'sh' }, 30)
end
- meths.set_option_value('scrollback', 200, {})
+ api.nvim_set_option_value('scrollback', 200, {})
-- Wait for prompt.
- screen:expect{any='%$'}
+ screen:expect { any = '%$' }
feed_data(('%s REP 31 line%s'):format(testprg('shell-test'), is_os('win') and '\r' or '\n'))
- screen:expect{any='30: line '}
+ screen:expect { any = '30: line ' }
- retry(nil, nil, function() expect_lines(33, 2) end)
- meths.set_option_value('scrollback', 10, {})
+ retry(nil, nil, function()
+ expect_lines(33, 2)
+ end)
+ api.nvim_set_option_value('scrollback', 10, {})
poke_eventloop()
- retry(nil, nil, function() expect_lines(16) end)
- meths.set_option_value('scrollback', 10000, {})
- retry(nil, nil, function() expect_lines(16) end)
+ retry(nil, nil, function()
+ expect_lines(16)
+ end)
+ api.nvim_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.
command('sleep 100m')
feed_data(('%s REP 41 line%s'):format(testprg('shell-test'), is_os('win') and '\r' or '\n'))
if is_os('win') then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
37: line |
38: line |
39: line |
@@ -441,9 +452,11 @@ describe("'scrollback' option", function()
|
${1: } |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
else
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
36: line |
37: line |
38: line |
@@ -451,7 +464,8 @@ describe("'scrollback' option", function()
40: line |
{MATCH:.*}|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
end
expect_lines(58)
@@ -465,11 +479,11 @@ describe("'scrollback' option", function()
local screen = thelpers.screen_setup(nil, nil, 30)
local lines = {}
for i = 1, 30 do
- table.insert(lines, 'line'..tostring(i))
+ table.insert(lines, 'line' .. tostring(i))
end
table.insert(lines, '')
feed_data(lines)
- screen:expect([[
+ screen:expect([[
line26 |
line27 |
line28 |
@@ -478,32 +492,33 @@ describe("'scrollback' option", function()
{1: } |
{3:-- TERMINAL --} |
]])
- local term_height = 6 -- Actual terminal screen height, not the scrollback
+ local term_height = 6 -- Actual terminal screen height, not the scrollback
-- Initial
- local scrollback = meths.get_option_value('scrollback', {})
+ local scrollback = api.nvim_get_option_value('scrollback', {})
eq(scrollback + term_height, eval('line("$")'))
-- Reduction
scrollback = scrollback - 2
- meths.set_option_value('scrollback', scrollback, {})
+ api.nvim_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, meths.get_option_value('scrollback', {}))
+ eq(10000, api.nvim_get_option_value('scrollback', {}))
end)
it('error if set to invalid value', function()
- eq('Vim(set):E474: Invalid argument: scrollback=-2',
- pcall_err(command, 'set scrollback=-2'))
- eq('Vim(set):E474: Invalid argument: scrollback=100001',
- pcall_err(command, 'set scrollback=100001'))
+ eq('Vim(set):E474: Invalid argument: scrollback=-2', pcall_err(command, 'set scrollback=-2'))
+ eq(
+ 'Vim(set):E474: Invalid argument: scrollback=100001',
+ pcall_err(command, 'set scrollback=100001')
+ )
end)
it('defaults to -1 on normal buffers', function()
command('new')
- eq(-1, meths.get_option_value('scrollback', {}))
+ eq(-1, api.nvim_get_option_value('scrollback', {}))
end)
it(':setlocal in a :terminal buffer', function()
@@ -512,50 +527,49 @@ describe("'scrollback' option", function()
-- _Global_ scrollback=-1 defaults :terminal to 10_000.
command('setglobal scrollback=-1')
command('terminal')
- eq(10000, meths.get_option_value('scrollback', {}))
+ eq(10000, api.nvim_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, meths.get_option_value('scrollback', {}))
+ retry(nil, nil, function() -- Fixup happens on refresh, not immediately.
+ eq(100000, api.nvim_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, meths.get_option_value('scrollback', {}))
+ eq(100000, api.nvim_get_option_value('scrollback', {}))
end)
it(':setlocal in a normal buffer', function()
command('new')
-- :setlocal to -1.
command('setlocal scrollback=-1')
- eq(-1, meths.get_option_value('scrollback', {}))
+ eq(-1, api.nvim_get_option_value('scrollback', {}))
-- :setlocal to anything except -1. Currently, this just has no effect.
command('setlocal scrollback=42')
- eq(42, meths.get_option_value('scrollback', {}))
+ eq(42, api.nvim_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, meths.get_option_value('scrollback', {}))
+ command('set scrollback=42') -- set global value
+ eq(42, api.nvim_get_option_value('scrollback', {}))
command('terminal')
- eq(42, meths.get_option_value('scrollback', {})) -- inherits global default
+ eq(42, api.nvim_get_option_value('scrollback', {})) -- inherits global default
command('setlocal scrollback=99')
- eq(99, meths.get_option_value('scrollback', {}))
- command('set scrollback<') -- reset to global default
- eq(42, meths.get_option_value('scrollback', {}))
- command('setglobal scrollback=734') -- new global default
- eq(42, meths.get_option_value('scrollback', {})) -- local value did not change
+ eq(99, api.nvim_get_option_value('scrollback', {}))
+ command('set scrollback<') -- reset to global default
+ eq(42, api.nvim_get_option_value('scrollback', {}))
+ command('setglobal scrollback=734') -- new global default
+ eq(42, api.nvim_get_option_value('scrollback', {})) -- local value did not change
command('terminal')
- eq(734, meths.get_option_value('scrollback', {}))
+ eq(734, api.nvim_get_option_value('scrollback', {}))
end)
-
end)
-describe("pending scrollback line handling", function()
+describe('pending scrollback line handling', function()
local screen
before_each(function()
@@ -563,9 +577,9 @@ describe("pending scrollback line handling", function()
screen = Screen.new(30, 7)
screen:attach()
screen:set_default_attr_ids {
- [1] = {foreground = Screen.colors.Brown},
- [2] = {reverse = true},
- [3] = {bold = true},
+ [1] = { foreground = Screen.colors.Brown },
+ [2] = { reverse = true },
+ [3] = { bold = true },
}
end)
@@ -580,41 +594,42 @@ describe("pending scrollback line handling", function()
]]
screen:expect [[
{1: 1 }^a |
- {1: 2 } a |
- {1: 3 } a |
- {1: 4 } a |
- {1: 5 } a |
- {1: 6 } a |
+ {1: 2 }a |
+ {1: 3 }a |
+ {1: 4 }a |
+ {1: 5 }a |
+ {1: 6 }a |
|
]]
feed('G')
screen:expect [[
- {1: 7 } a |
- {1: 8 } a |
- {1: 9 } a |
- {1: 10 } a |
- {1: 11 } a |
- {1: 12 } ^a |
+ {1: 7 }a |
+ {1: 8 }a |
+ {1: 9 }a |
+ {1: 10 }a |
+ {1: 11 }a |
+ {1: 12 }^a |
|
]]
assert_alive()
end)
- it("does not crash after nvim_buf_call #14891", function()
- skip(is_os('win'))
- exec_lua [[
+ it('does not crash after nvim_buf_call #14891', function()
+ exec_lua(
+ [[
local bufnr = vim.api.nvim_create_buf(false, true)
+ local args = ...
vim.api.nvim_buf_call(bufnr, function()
- vim.fn.termopen({"echo", ("hi\n"):rep(11)})
+ vim.fn.termopen(args)
end)
vim.api.nvim_win_set_buf(0, bufnr)
- vim.cmd("startinsert")
- ]]
+ vim.cmd('startinsert')
+ ]],
+ is_os('win') and { 'cmd.exe', '/c', 'for /L %I in (1,1,12) do @echo hi' }
+ or { 'printf', ('hi\n'):rep(12) }
+ )
screen:expect [[
- hi |
- hi |
- hi |
- |
+ hi |*4
|
[Process exited 0]{2: } |
{3:-- TERMINAL --} |
diff --git a/test/functional/terminal/tui_spec.lua b/test/functional/terminal/tui_spec.lua
index b17eed00f9..94690524d3 100644
--- a/test/functional/terminal/tui_spec.lua
+++ b/test/functional/terminal/tui_spec.lua
@@ -20,16 +20,19 @@ local nvim_prog = helpers.nvim_prog
local nvim_set = helpers.nvim_set
local ok = helpers.ok
local read_file = helpers.read_file
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local is_ci = helpers.is_ci
local is_os = helpers.is_os
local new_pipename = helpers.new_pipename
local spawn_argv = helpers.spawn_argv
local set_session = helpers.set_session
local write_file = helpers.write_file
+local eval = helpers.eval
-if helpers.skip(is_os('win')) then return end
+if helpers.skip(is_os('win')) then
+ return
+end
describe('TUI', function()
local screen
@@ -39,14 +42,21 @@ describe('TUI', function()
before_each(function()
clear()
local child_server = new_pipename()
- screen = thelpers.screen_setup(0,
- string.format([=[["%s", "--listen", "%s", "-u", "NONE", "-i", "NONE", "--cmd", "%s laststatus=2 background=dark"]]=],
- nvim_prog, child_server, nvim_set))
+ screen = thelpers.setup_child_nvim({
+ '--listen',
+ child_server,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ nvim_set .. ' notermguicolors laststatus=2 background=dark',
+ '--cmd',
+ 'colorscheme vim',
+ })
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
|
{3:-- TERMINAL --} |
@@ -75,7 +85,7 @@ describe('TUI', function()
it('rapid resize #7572 #7628', function()
helpers.skip(helpers.is_asan(), 'Test extra unstable with ASAN. See #23762')
-- Need buffer rows to provoke the behavior.
- feed_data(":edit test/functional/fixtures/bigfile.txt\n")
+ feed_data(':edit test/functional/fixtures/bigfile.txt\n')
screen:expect([[
{1:0}000;<control>;Cc;0;BN;;;;;N;NULL;;;; |
0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;; |
@@ -102,21 +112,26 @@ describe('TUI', function()
screen:try_resize(57, 17)
command('call jobresize(b:terminal_job_id, 57, 17)')
retry(nil, nil, function()
- eq({true, 57}, {child_session:request('nvim_win_get_width', 0)})
+ eq({ true, 57 }, { child_session:request('nvim_win_get_width', 0) })
end)
end)
it('accepts resize while pager is active', function()
- child_session:request('nvim_exec2', [[
+ child_session:request(
+ 'nvim_exec2',
+ [[
set more
func! ManyErr()
for i in range(20)
echoerr "FAIL ".i
endfor
endfunc
- ]], {})
+ ]],
+ {}
+ )
feed_data(':call ManyErr()\r')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{8:Error detected while processing function ManyErr:} |
{11:line 2:} |
{8:FAIL 0} |
@@ -124,24 +139,27 @@ describe('TUI', function()
{8:FAIL 2} |
{10:-- More --}{1: } |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
- screen:try_resize(50,10)
- screen:expect{grid=[[
+ 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} |
- |
- |
+ |*2
{10:-- More --}{1: } |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
feed_data('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{8:Error detected while processing function ManyErr:} |
{11:line 2:} |
{8:FAIL 0} |
@@ -152,10 +170,12 @@ describe('TUI', function()
{8:FAIL 5} |
{10:-- More --}{1: } |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
- screen:try_resize(50,7)
- screen:expect{grid=[[
+ screen:try_resize(50, 7)
+ screen:expect {
+ grid = [[
{8:FAIL 1} |
{8:FAIL 2} |
{8:FAIL 3} |
@@ -163,28 +183,34 @@ describe('TUI', function()
{8:FAIL 5} |
{10:-- More --}{1: } |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
- screen:try_resize(50,5)
- screen:expect{grid=[[
+ screen:try_resize(50, 5)
+ screen:expect {
+ grid = [[
{8:FAIL 3} |
{8:FAIL 4} |
{8:FAIL 5} |
{10:-- More --}{1: } |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
feed_data('g')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
:call ManyErr() |
{8:Error detected while processing function ManyErr:} |
{11:line 2:} |
{10:-- More --}{1: } |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
- screen:try_resize(50,10)
- screen:expect{grid=[[
+ screen:try_resize(50, 10)
+ screen:expect {
+ grid = [[
:call ManyErr() |
{8:Error detected while processing function ManyErr:} |
{11:line 2:} |
@@ -195,21 +221,19 @@ describe('TUI', function()
{8:FAIL 4} |
{10:-- More --}{1: } |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
feed_data('\003')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*6
{5:[No Name] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
end)
it('accepts basic utf-8 input', function()
@@ -238,8 +262,8 @@ describe('TUI', function()
it('interprets leading <Esc> byte as ALT modifier in normal-mode', function()
local keys = 'dfghjkl'
for c in keys:gmatch('.') do
- feed_data(':nnoremap <a-'..c..'> ialt-'..c..'<cr><esc>\r')
- feed_data('\027'..c)
+ feed_data(':nnoremap <a-' .. c .. '> ialt-' .. c .. '<cr><esc>\r')
+ feed_data('\027' .. c)
end
screen:expect([[
alt-j |
@@ -268,9 +292,7 @@ describe('TUI', function()
feed_data('i\022\027j')
screen:expect([[
<M-j>{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
@@ -278,17 +300,19 @@ describe('TUI', function()
end)
it('interprets <Esc>[27u as <Esc>', function()
- child_session:request('nvim_exec2', [[
+ child_session:request(
+ 'nvim_exec2',
+ [[
nnoremap <M-;> <Nop>
nnoremap <Esc> AESC<Esc>
nnoremap ; Asemicolon<Esc>
- ]], {})
+ ]],
+ {}
+ )
feed_data('\027[27u;')
screen:expect([[
ESCsemicolo{1:n} |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
@@ -302,9 +326,7 @@ describe('TUI', function()
feed_data('i\022\027\000')
screen:expect([[
<M-C-Space>{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
@@ -316,25 +338,25 @@ describe('TUI', function()
feed_data('\022\007') -- ctrl+g
feed_data('\022\022') -- ctrl+v
feed_data('\022\013') -- ctrl+m
- local attrs = screen:get_default_attr_ids()
- attrs[11] = {foreground = 81}
screen:expect([[
- {11:^G^V^M}{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {6:^G^V^M}{1: } |
+ {4:~ }|*3
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
- ]], attrs)
+ ]])
end)
local function test_mouse_wheel(esc)
- child_session:request('nvim_exec2', [[
+ child_session:request(
+ 'nvim_exec2',
+ [[
set number nostartofline nowrap mousescroll=hor:1,ver:1
call setline(1, repeat([join(range(10), '----')], 10))
vsplit
- ]], {})
+ ]],
+ {}
+ )
screen:expect([[
{11: 1 }{1:0}----1----2----3----4│{11: 1 }0----1----2----3----|
{11: 2 }0----1----2----3----4│{11: 2 }0----1----2----3----|
@@ -348,7 +370,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<65;8;1M')
else
- meths.input_mouse('wheel', 'down', '', 0, 0, 7)
+ api.nvim_input_mouse('wheel', 'down', '', 0, 0, 7)
end
screen:expect([[
{11: 2 }{1:0}----1----2----3----4│{11: 1 }0----1----2----3----|
@@ -363,7 +385,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<65;48;1M')
else
- meths.input_mouse('wheel', 'down', '', 0, 0, 47)
+ api.nvim_input_mouse('wheel', 'down', '', 0, 0, 47)
end
screen:expect([[
{11: 2 }{1:0}----1----2----3----4│{11: 2 }0----1----2----3----|
@@ -378,7 +400,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<67;8;1M')
else
- meths.input_mouse('wheel', 'right', '', 0, 0, 7)
+ api.nvim_input_mouse('wheel', 'right', '', 0, 0, 7)
end
screen:expect([[
{11: 2 }{1:-}---1----2----3----4-│{11: 2 }0----1----2----3----|
@@ -393,7 +415,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<67;48;1M')
else
- meths.input_mouse('wheel', 'right', '', 0, 0, 47)
+ api.nvim_input_mouse('wheel', 'right', '', 0, 0, 47)
end
screen:expect([[
{11: 2 }{1:-}---1----2----3----4-│{11: 2 }----1----2----3----4|
@@ -408,7 +430,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<69;8;1M')
else
- meths.input_mouse('wheel', 'down', 'S', 0, 0, 7)
+ api.nvim_input_mouse('wheel', 'down', 'S', 0, 0, 7)
end
screen:expect([[
{11: 5 }{1:-}---1----2----3----4-│{11: 2 }----1----2----3----4|
@@ -423,7 +445,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<69;48;1M')
else
- meths.input_mouse('wheel', 'down', 'S', 0, 0, 47)
+ api.nvim_input_mouse('wheel', 'down', 'S', 0, 0, 47)
end
screen:expect([[
{11: 5 }{1:-}---1----2----3----4-│{11: 5 }----1----2----3----4|
@@ -438,7 +460,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<71;8;1M')
else
- meths.input_mouse('wheel', 'right', 'S', 0, 0, 7)
+ api.nvim_input_mouse('wheel', 'right', 'S', 0, 0, 7)
end
screen:expect([[
{11: 5 }{1:-}---6----7----8----9 │{11: 5 }----1----2----3----4|
@@ -453,7 +475,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<71;48;1M')
else
- meths.input_mouse('wheel', 'right', 'S', 0, 0, 47)
+ api.nvim_input_mouse('wheel', 'right', 'S', 0, 0, 47)
end
screen:expect([[
{11: 5 }{1:-}---6----7----8----9 │{11: 5 }5----6----7----8----|
@@ -468,7 +490,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<64;8;1M')
else
- meths.input_mouse('wheel', 'up', '', 0, 0, 7)
+ api.nvim_input_mouse('wheel', 'up', '', 0, 0, 7)
end
screen:expect([[
{11: 4 }----6----7----8----9 │{11: 5 }5----6----7----8----|
@@ -483,7 +505,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<64;48;1M')
else
- meths.input_mouse('wheel', 'up', '', 0, 0, 47)
+ api.nvim_input_mouse('wheel', 'up', '', 0, 0, 47)
end
screen:expect([[
{11: 4 }----6----7----8----9 │{11: 4 }5----6----7----8----|
@@ -498,7 +520,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<66;8;1M')
else
- meths.input_mouse('wheel', 'left', '', 0, 0, 7)
+ api.nvim_input_mouse('wheel', 'left', '', 0, 0, 7)
end
screen:expect([[
{11: 4 }5----6----7----8----9│{11: 4 }5----6----7----8----|
@@ -513,7 +535,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<66;48;1M')
else
- meths.input_mouse('wheel', 'left', '', 0, 0, 47)
+ api.nvim_input_mouse('wheel', 'left', '', 0, 0, 47)
end
screen:expect([[
{11: 4 }5----6----7----8----9│{11: 4 }-5----6----7----8---|
@@ -528,7 +550,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<68;8;1M')
else
- meths.input_mouse('wheel', 'up', 'S', 0, 0, 7)
+ api.nvim_input_mouse('wheel', 'up', 'S', 0, 0, 7)
end
screen:expect([[
{11: 1 }5----6----7----8----9│{11: 4 }-5----6----7----8---|
@@ -543,7 +565,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<68;48;1M')
else
- meths.input_mouse('wheel', 'up', 'S', 0, 0, 47)
+ api.nvim_input_mouse('wheel', 'up', 'S', 0, 0, 47)
end
screen:expect([[
{11: 1 }5----6----7----8----9│{11: 1 }-5----6----7----8---|
@@ -558,7 +580,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<70;8;1M')
else
- meths.input_mouse('wheel', 'left', 'S', 0, 0, 7)
+ api.nvim_input_mouse('wheel', 'left', 'S', 0, 0, 7)
end
screen:expect([[
{11: 1 }0----1----2----3----4│{11: 1 }-5----6----7----8---|
@@ -573,7 +595,7 @@ describe('TUI', function()
if esc then
feed_data('\027[<70;48;1M')
else
- meths.input_mouse('wheel', 'left', 'S', 0, 0, 47)
+ api.nvim_input_mouse('wheel', 'left', 'S', 0, 0, 47)
end
screen:expect([[
{11: 1 }0----1----2----3----4│{11: 1 }0----1----2----3----|
@@ -597,7 +619,9 @@ describe('TUI', function()
end)
local function test_mouse_popup(esc)
- child_session:request('nvim_exec2', [[
+ child_session:request(
+ 'nvim_exec2',
+ [[
call setline(1, 'popup menu test')
set mouse=a mousemodel=popup
@@ -607,11 +631,13 @@ describe('TUI', function()
menu PopUp.baz :let g:menustr = 'baz'<CR>
highlight Pmenu ctermbg=NONE ctermfg=NONE cterm=underline,reverse
highlight PmenuSel ctermbg=NONE ctermfg=NONE cterm=underline,reverse,bold
- ]], {})
+ ]],
+ {}
+ )
if esc then
feed_data('\027[<2;5;1M')
else
- meths.input_mouse('right', 'press', '', 0, 0, 4)
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 4)
end
screen:expect([[
{1:p}opup menu test |
@@ -625,13 +651,27 @@ describe('TUI', function()
if esc then
feed_data('\027[<2;5;1m')
else
- meths.input_mouse('right', 'release', '', 0, 0, 4)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 4)
end
screen:expect_unchanged()
if esc then
+ feed_data('\027[<64;5;1M')
+ else
+ api.nvim_input_mouse('wheel', 'up', '', 0, 0, 4)
+ end
+ screen:expect([[
+ {1:p}opup menu test |
+ {4:~ }{14: foo }{4: }|
+ {4:~ }{13: bar }{4: }|
+ {4:~ }{13: baz }{4: }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ if esc then
feed_data('\027[<35;7;4M')
else
- meths.input_mouse('move', '', '', 0, 3, 6)
+ api.nvim_input_mouse('move', '', '', 0, 3, 6)
end
screen:expect([[
{1:p}opup menu test |
@@ -643,15 +683,27 @@ describe('TUI', function()
{3:-- TERMINAL --} |
]])
if esc then
+ feed_data('\027[<65;7;4M')
+ else
+ api.nvim_input_mouse('wheel', 'down', '', 0, 3, 6)
+ end
+ screen:expect([[
+ {1:p}opup menu test |
+ {4:~ }{13: foo }{4: }|
+ {4:~ }{14: bar }{4: }|
+ {4:~ }{13: baz }{4: }|
+ {5:[No Name] [+] }|
+ |
+ {3:-- TERMINAL --} |
+ ]])
+ if esc then
feed_data('\027[<0;7;3M')
else
- meths.input_mouse('left', 'press', '', 0, 2, 6)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 6)
end
screen:expect([[
{1:p}opup menu test |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
:let g:menustr = 'bar' |
{3:-- TERMINAL --} |
@@ -659,18 +711,17 @@ describe('TUI', function()
if esc then
feed_data('\027[<0;7;3m')
else
- meths.input_mouse('left', 'release', '', 0, 2, 6)
+ api.nvim_input_mouse('left', 'release', '', 0, 2, 6)
end
screen:expect_unchanged()
if esc then
feed_data('\027[<2;45;3M')
else
- meths.input_mouse('right', 'press', '', 0, 2, 44)
+ api.nvim_input_mouse('right', 'press', '', 0, 2, 44)
end
screen:expect([[
{1:p}opup menu test |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{4:~ }{13: foo }{4: }|
{5:[No Name] [+] }{13: bar }{5: }|
:let g:menustr = 'bar' {13: baz } |
@@ -679,12 +730,11 @@ describe('TUI', function()
if esc then
feed_data('\027[<34;48;6M')
else
- meths.input_mouse('right', 'drag', '', 0, 5, 47)
+ api.nvim_input_mouse('right', 'drag', '', 0, 5, 47)
end
screen:expect([[
{1:p}opup menu test |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{4:~ }{13: foo }{4: }|
{5:[No Name] [+] }{13: bar }{5: }|
:let g:menustr = 'bar' {14: baz } |
@@ -693,13 +743,11 @@ describe('TUI', function()
if esc then
feed_data('\027[<2;48;6m')
else
- meths.input_mouse('right', 'release', '', 0, 5, 47)
+ api.nvim_input_mouse('right', 'release', '', 0, 5, 47)
end
screen:expect([[
{1:p}opup menu test |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
:let g:menustr = 'baz' |
{3:-- TERMINAL --} |
@@ -718,78 +766,72 @@ describe('TUI', function()
it('accepts keypad keys from kitty keyboard protocol #19180', function()
feed_data('i')
- feed_data(funcs.nr2char(57399)) -- KP_0
- feed_data(funcs.nr2char(57400)) -- KP_1
- feed_data(funcs.nr2char(57401)) -- KP_2
- feed_data(funcs.nr2char(57402)) -- KP_3
- feed_data(funcs.nr2char(57403)) -- KP_4
- feed_data(funcs.nr2char(57404)) -- KP_5
- feed_data(funcs.nr2char(57405)) -- KP_6
- feed_data(funcs.nr2char(57406)) -- KP_7
- feed_data(funcs.nr2char(57407)) -- KP_8
- feed_data(funcs.nr2char(57408)) -- KP_9
- feed_data(funcs.nr2char(57409)) -- KP_DECIMAL
- feed_data(funcs.nr2char(57410)) -- KP_DIVIDE
- feed_data(funcs.nr2char(57411)) -- KP_MULTIPLY
- feed_data(funcs.nr2char(57412)) -- KP_SUBTRACT
- feed_data(funcs.nr2char(57413)) -- KP_ADD
- feed_data(funcs.nr2char(57414)) -- KP_ENTER
- feed_data(funcs.nr2char(57415)) -- KP_EQUAL
+ feed_data(fn.nr2char(57399)) -- KP_0
+ feed_data(fn.nr2char(57400)) -- KP_1
+ feed_data(fn.nr2char(57401)) -- KP_2
+ feed_data(fn.nr2char(57402)) -- KP_3
+ feed_data(fn.nr2char(57403)) -- KP_4
+ feed_data(fn.nr2char(57404)) -- KP_5
+ feed_data(fn.nr2char(57405)) -- KP_6
+ feed_data(fn.nr2char(57406)) -- KP_7
+ feed_data(fn.nr2char(57407)) -- KP_8
+ feed_data(fn.nr2char(57408)) -- KP_9
+ feed_data(fn.nr2char(57409)) -- KP_DECIMAL
+ feed_data(fn.nr2char(57410)) -- KP_DIVIDE
+ feed_data(fn.nr2char(57411)) -- KP_MULTIPLY
+ feed_data(fn.nr2char(57412)) -- KP_SUBTRACT
+ feed_data(fn.nr2char(57413)) -- KP_ADD
+ feed_data(fn.nr2char(57414)) -- KP_ENTER
+ feed_data(fn.nr2char(57415)) -- KP_EQUAL
screen:expect([[
0123456789./*-+ |
={1: } |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- feed_data(funcs.nr2char(57417)) -- KP_LEFT
+ feed_data(fn.nr2char(57417)) -- KP_LEFT
screen:expect([[
0123456789./*-+ |
{1:=} |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- feed_data(funcs.nr2char(57418)) -- KP_RIGHT
+ feed_data(fn.nr2char(57418)) -- KP_RIGHT
screen:expect([[
0123456789./*-+ |
={1: } |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- feed_data(funcs.nr2char(57419)) -- KP_UP
+ feed_data(fn.nr2char(57419)) -- KP_UP
screen:expect([[
0{1:1}23456789./*-+ |
= |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- feed_data(funcs.nr2char(57420)) -- KP_DOWN
+ feed_data(fn.nr2char(57420)) -- KP_DOWN
screen:expect([[
0123456789./*-+ |
={1: } |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- feed_data(funcs.nr2char(57425)) -- KP_INSERT
+ feed_data(fn.nr2char(57425)) -- KP_INSERT
screen:expect([[
0123456789./*-+ |
={1: } |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
{3:-- REPLACE --} |
{3:-- TERMINAL --} |
@@ -798,8 +840,7 @@ describe('TUI', function()
screen:expect([[
0123456789./*-+ |
{1:=} |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
@@ -808,8 +849,7 @@ describe('TUI', function()
screen:expect([[
{1:0}123456789./*-+ |
= |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
@@ -818,52 +858,51 @@ describe('TUI', function()
screen:expect([[
0123456789{1:.}/*-+ |
= |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
]])
- feed_data(funcs.nr2char(57426)) -- KP_DELETE
+ feed_data(fn.nr2char(57426)) -- KP_DELETE
screen:expect([[
0123456789{1:/}*-+ |
= |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
]])
- feed_data(funcs.nr2char(57423)) -- KP_HOME
+ feed_data(fn.nr2char(57423)) -- KP_HOME
screen:expect([[
{1:0}123456789/*-+ |
= |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
]])
- feed_data(funcs.nr2char(57424)) -- KP_END
+ feed_data(fn.nr2char(57424)) -- KP_END
screen:expect([[
0123456789/*-{1:+} |
= |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
]])
- child_session:request('nvim_exec2', [[
+ child_session:request(
+ 'nvim_exec2',
+ [[
tab split
tabnew
highlight Tabline ctermbg=NONE ctermfg=NONE cterm=underline
- ]], {})
+ ]],
+ {}
+ )
screen:expect([[
{12: + [No Name] + [No Name] }{3: [No Name] }{1: }{12:X}|
{1: } |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] }|
|
{3:-- TERMINAL --} |
@@ -882,8 +921,7 @@ describe('TUI', function()
screen:expect([[
{12: + [No Name] + [No Name] }{3: [No Name] }{1: }{12:X}|
{1: } |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] }|
|
{3:-- TERMINAL --} |
@@ -892,20 +930,19 @@ describe('TUI', function()
it('supports Super and Meta modifiers', function()
feed_data('i')
- feed_data('\022\027[106;9u') -- Super + j
- feed_data('\022\027[107;33u') -- Meta + k
- feed_data('\022\027[13;41u') -- Super + Meta + Enter
- feed_data('\022\027[127;48u') -- Shift + Alt + Ctrl + Super + Meta + Backspace
+ feed_data('\022\027[106;9u') -- Super + j
+ feed_data('\022\027[107;33u') -- Meta + k
+ feed_data('\022\027[13;41u') -- Super + Meta + Enter
+ feed_data('\022\027[127;48u') -- Shift + Alt + Ctrl + Super + Meta + Backspace
feed_data('\n')
- feed_data('\022\027[57376;9u') -- Super + F13
- feed_data('\022\027[57377;33u') -- Meta + F14
- feed_data('\022\027[57378;41u') -- Super + Meta + F15
- feed_data('\022\027[57379;48u') -- Shift + Alt + Ctrl + Super + Meta + F16
+ feed_data('\022\027[57376;9u') -- Super + F13
+ feed_data('\022\027[57377;33u') -- Meta + F14
+ feed_data('\022\027[57378;41u') -- Super + Meta + F15
+ feed_data('\022\027[57379;48u') -- Shift + Alt + Ctrl + Super + Meta + F16
screen:expect([[
<D-j><T-k><T-D-CR><M-T-C-S-D-BS> |
<D-F13><T-F14><T-D-F15><M-T-C-S-D-F16>{1: } |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
@@ -917,61 +954,54 @@ describe('TUI', function()
feed_data('i""\027i\027[200~')
screen:expect([[
"{1:"} |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
feed_data('pasted from terminal')
- expect_child_buf_lines({'"pasted from terminal"'})
+ expect_child_buf_lines({ '"pasted from terminal"' })
screen:expect([[
"pasted from terminal{1:"} |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- feed_data('\027[201~') -- End paste.
- feed_data('\027[27u') -- ESC: go to Normal mode.
+ feed_data('\027[201~') -- End paste.
+ feed_data('\027[27u') -- ESC: go to Normal mode.
wait_for_mode('n')
screen:expect([[
"pasted from termina{1:l}" |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
]])
-- Dot-repeat/redo.
feed_data('2.')
- expect_child_buf_lines({'"pasted from terminapasted from terminalpasted from terminall"'})
+ expect_child_buf_lines({ '"pasted from terminapasted from terminalpasted from terminall"' })
screen:expect([[
"pasted from terminapasted from terminalpasted fro|
m termina{1:l}l" |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
]])
-- Undo.
feed_data('u')
- expect_child_buf_lines({'"pasted from terminal"'})
+ expect_child_buf_lines({ '"pasted from terminal"' })
feed_data('u')
- expect_child_buf_lines({'""'})
+ expect_child_buf_lines({ '""' })
feed_data('u')
- expect_child_buf_lines({''})
+ expect_child_buf_lines({ '' })
end)
it('paste: select-mode', function()
feed_data('ithis is line 1\nthis is line 2\nline 3 is here\n\027')
wait_for_mode('n')
- screen:expect{grid=[[
+ screen:expect([[
this is line 1 |
this is line 2 |
line 3 is here |
@@ -979,33 +1009,40 @@ describe('TUI', function()
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]])
-- Select-mode. Use <C-n> to move down.
feed_data('gg04lgh\14\14')
- wait_for_mode('s')
+ screen:expect([[
+ this{16: is line 1} |
+ {16:this is line 2} |
+ {16:line}{1: }3 is here |
+ |
+ {5:[No Name] [+] }|
+ {3:-- SELECT --} |
+ {3:-- TERMINAL --} |
+ ]])
feed_data('\027[200~')
feed_data('just paste itâ„¢')
feed_data('\027[201~')
- screen:expect{grid=[[
+ screen:expect([[
thisjust paste it{1:â„¢}3 is here |
|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]])
-- Undo.
feed_data('u')
- expect_child_buf_lines{
+ expect_child_buf_lines {
'this is line 1',
'this is line 2',
'line 3 is here',
'',
}
-- Redo.
- feed_data('\18') -- <C-r>
- expect_child_buf_lines{
+ feed_data('\18') -- <C-r>
+ expect_child_buf_lines {
'thisjust paste itâ„¢3 is here',
'',
}
@@ -1013,32 +1050,28 @@ describe('TUI', function()
it('paste: terminal mode', function()
if is_ci('github') then
- pending("tty-test complains about not owning the terminal -- actions/runner#241")
+ pending('tty-test complains about not owning the terminal -- actions/runner#241')
end
child_exec_lua('vim.o.statusline="^^^^^^^"')
child_exec_lua('vim.cmd.terminal(...)', testprg('tty-test'))
feed_data('i')
- screen:expect{grid=[[
+ screen:expect([[
tty ready |
{1: } |
- |
- |
+ |*2
{5:^^^^^^^ }|
- {3:-- TERMINAL --} |
- {3:-- TERMINAL --} |
- ]]}
+ {3:-- TERMINAL --} |*2
+ ]])
feed_data('\027[200~')
feed_data('hallo')
feed_data('\027[201~')
- screen:expect{grid=[[
+ screen:expect([[
tty ready |
hallo{1: } |
- |
- |
+ |*2
{5:^^^^^^^ }|
- {3:-- TERMINAL --} |
- {3:-- TERMINAL --} |
- ]]}
+ {3:-- TERMINAL --} |*2
+ ]])
end)
it('paste: normal-mode (+CRLF #10872)', function()
@@ -1046,99 +1079,98 @@ describe('TUI', function()
wait_for_mode('c')
feed_data('\n')
wait_for_mode('n')
- local expected_lf = {'line 1', 'ESC:\027 / CR: \rx'}
- local expected_crlf = {'line 1', 'ESC:\027 / CR: ', 'x'}
+ local expected_lf = { 'line 1', 'ESC:\027 / CR: \rx' }
+ local expected_crlf = { 'line 1', 'ESC:\027 / CR: ', 'x' }
local expected_grid1 = [[
line 1 |
- ESC:{11:^[} / CR: |
+ ESC:{6:^[} / CR: |
{1:x} |
{4:~ }|
{5:[No Name] [+] 3,1 All}|
|
{3:-- TERMINAL --} |
]]
- local expected_attr = {
- [1] = {reverse = true},
- [3] = {bold = true},
- [4] = {foreground = tonumber('0x00000c')},
- [5] = {bold = true, reverse = true},
- [11] = {foreground = tonumber('0x000051')},
- [12] = {reverse = true, foreground = tonumber('0x000051')},
- }
-- "bracketed paste"
- feed_data('\027[200~'..table.concat(expected_lf,'\n')..'\027[201~')
- screen:expect{grid=expected_grid1, attr_ids=expected_attr}
+ feed_data('\027[200~' .. table.concat(expected_lf, '\n') .. '\027[201~')
+ screen:expect(expected_grid1)
-- Dot-repeat/redo.
feed_data('.')
- screen:expect{grid=[[
- ESC:{11:^[} / CR: |
+ screen:expect([[
+ ESC:{6:^[} / CR: |
xline 1 |
- ESC:{11:^[} / CR: |
+ ESC:{6:^[} / CR: |
{1:x} |
{5:[No Name] [+] 5,1 Bot}|
|
{3:-- TERMINAL --} |
- ]], attr_ids=expected_attr}
+ ]])
-- Undo.
feed_data('u')
expect_child_buf_lines(expected_crlf)
feed_data('u')
- expect_child_buf_lines({''})
+ expect_child_buf_lines({ '' })
feed_data(':echo')
wait_for_mode('c')
feed_data('\n')
wait_for_mode('n')
-- CRLF input
- feed_data('\027[200~'..table.concat(expected_lf,'\r\n')..'\027[201~')
- screen:expect{grid=expected_grid1, attr_ids=expected_attr}
+ feed_data('\027[200~' .. table.concat(expected_lf, '\r\n') .. '\027[201~')
+ screen:expect(expected_grid1)
expect_child_buf_lines(expected_crlf)
end)
it('paste: cmdline-mode inserts 1 line', function()
- feed_data('ifoo\n') -- Insert some text (for dot-repeat later).
- feed_data('\027:""') -- Enter Cmdline-mode.
- feed_data('\027[D') -- <Left> to place cursor between quotes.
+ feed_data('ifoo\n') -- Insert some text (for dot-repeat later).
+ feed_data('\027:""') -- Enter Cmdline-mode.
+ feed_data('\027[D') -- <Left> to place cursor between quotes.
wait_for_mode('c')
+ screen:expect([[
+ foo |
+ |
+ {4:~ }|*2
+ {5:[No Name] [+] }|
+ :"{1:"} |
+ {3:-- TERMINAL --} |
+ ]])
-- "bracketed paste"
feed_data('\027[200~line 1\nline 2\n')
wait_for_mode('c')
feed_data('line 3\nline 4\n\027[201~')
wait_for_mode('c')
- screen:expect{grid=[[
+ screen:expect([[
foo |
|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
:"line 1{1:"} |
{3:-- TERMINAL --} |
- ]]}
+ ]])
-- Dot-repeat/redo.
feed_data('\027[27u')
wait_for_mode('n')
feed_data('.')
- screen:expect{grid=[[
- foo |
- foo |
+ screen:expect([[
+ foo |*2
{1: } |
{4:~ }|
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]])
end)
it('paste: cmdline-mode collects chunks of unfinished line', function()
local function expect_cmdline(expected)
retry(nil, nil, function()
- local _, cmdline = child_session:request(
- 'nvim_call_function', 'getcmdline', {})
+ local _, cmdline = child_session:request('nvim_call_function', 'getcmdline', {})
eq(expected, cmdline)
+ local _, pos = child_session:request('nvim_call_function', 'getcmdpos', {})
+ eq(#expected, pos) -- Cursor is just before the last char.
end)
end
- feed_data('\027:""') -- Enter Cmdline-mode.
- feed_data('\027[D') -- <Left> to place cursor between quotes.
- wait_for_mode('c')
+ feed_data('\027:""') -- Enter Cmdline-mode.
+ feed_data('\027[D') -- <Left> to place cursor between quotes.
+ expect_cmdline('""')
feed_data('\027[200~stuff 1 ')
expect_cmdline('"stuff 1 "')
-- Discards everything after the first line.
@@ -1153,27 +1185,30 @@ describe('TUI', function()
end)
it('paste: recovers from vim.paste() failure', function()
- child_session:request('nvim_exec_lua', [[
+ child_session:request(
+ 'nvim_exec_lua',
+ [[
_G.save_paste_fn = vim.paste
-- Stack traces for this test are non-deterministic, so disable them
_G.debug.traceback = function(msg) return msg end
vim.paste = function(lines, phase) error("fake fail") end
- ]], {})
+ ]],
+ {}
+ )
-- Prepare something for dot-repeat/redo.
feed_data('ifoo\n\027[27u')
wait_for_mode('n')
- screen:expect{grid=[[
+ screen:expect([[
foo |
{1: } |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]])
-- Start pasting...
feed_data('\027[200~line 1\nline 2\n')
- screen:expect{grid=[[
+ screen:expect([[
foo |
|
{5: }|
@@ -1181,44 +1216,39 @@ describe('TUI', function()
{8:ake fail} |
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |
- ]]}
+ ]])
-- Remaining chunks are discarded after vim.paste() failure.
feed_data('line 3\nline 4\n')
feed_data('line 5\nline 6\n')
feed_data('line 7\nline 8\n')
-- Stop paste.
feed_data('\027[201~')
- feed_data('\n') -- <CR>
- expect_child_buf_lines({'foo',''})
- --Dot-repeat/redo is not modified by failed paste.
+ feed_data('\n') -- <CR> to dismiss hit-enter prompt
+ expect_child_buf_lines({ 'foo', '' })
+ -- Dot-repeat/redo is not modified by failed paste.
feed_data('.')
- screen:expect{grid=[[
- foo |
- foo |
+ screen:expect([[
+ foo |*2
{1: } |
{4:~ }|
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]])
-- Editor should still work after failed/drained paste.
feed_data('ityped input...\027[27u')
- screen:expect{grid=[[
- foo |
- foo |
+ screen:expect([[
+ foo |*2
typed input..{1:.} |
{4:~ }|
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]])
-- Paste works if vim.paste() succeeds.
- child_session:request('nvim_exec_lua', [[
- vim.paste = _G.save_paste_fn
- ]], {})
+ child_session:request('nvim_exec_lua', [[vim.paste = _G.save_paste_fn]], {})
feed_data('\027[200~line A\nline B\n\027[201~')
- feed_data('\n') -- <CR>
- screen:expect{grid=[[
+ screen:expect([[
foo |
typed input...line A |
line B |
@@ -1226,28 +1256,36 @@ describe('TUI', function()
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]])
end)
it('paste: vim.paste() cancel (retval=false) #10865', function()
-- This test only exercises the "cancel" case. Use-case would be "dangling
-- paste", but that is not implemented yet. #10865
- child_session:request('nvim_exec_lua', [[
+ child_session:request(
+ 'nvim_exec_lua',
+ [[
vim.paste = function(lines, phase) return false end
- ]], {})
+ ]],
+ {}
+ )
feed_data('\027[200~line A\nline B\n\027[201~')
feed_data('ifoo\n\027[27u')
- expect_child_buf_lines({'foo',''})
+ expect_child_buf_lines({ 'foo', '' })
end)
it("paste: 'nomodifiable' buffer", function()
child_session:request('nvim_command', 'set nomodifiable')
- child_session:request('nvim_exec_lua', [[
+ child_session:request(
+ 'nvim_exec_lua',
+ [[
-- Truncate the error message to hide the line number
_G.debug.traceback = function(msg) return msg:sub(-49) end
- ]], {})
+ ]],
+ {}
+ )
feed_data('\027[200~fail 1\nfail 2\n\027[201~')
- screen:expect{grid=[[
+ screen:expect([[
|
{4:~ }|
{5: }|
@@ -1255,11 +1293,11 @@ describe('TUI', function()
{8:hanges, 'modifiable' is off} |
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |
- ]]}
- feed_data('\n') -- <Enter>
+ ]])
+ feed_data('\n') -- <Enter> to dismiss hit-enter prompt
child_session:request('nvim_command', 'set modifiable')
feed_data('\027[200~success 1\nsuccess 2\n\027[201~')
- screen:expect{grid=[[
+ screen:expect([[
success 1 |
success 2 |
{1: } |
@@ -1267,7 +1305,7 @@ describe('TUI', function()
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]])
end)
it('paste: exactly 64 bytes #10311', function()
@@ -1275,20 +1313,19 @@ describe('TUI', function()
feed_data('i')
wait_for_mode('i')
-- "bracketed paste"
- feed_data('\027[200~'..expected..'\027[201~')
- expect_child_buf_lines({expected})
+ feed_data('\027[200~' .. expected .. '\027[201~')
+ expect_child_buf_lines({ expected })
feed_data(' end')
- expected = expected..' end'
+ expected = expected .. ' end'
screen:expect([[
zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz|
zzzzzzzzzzzzzz end{1: } |
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- expect_child_buf_lines({expected})
+ expect_child_buf_lines({ expected })
end)
it('paste: less-than sign in cmdline #11088', function()
@@ -1296,16 +1333,14 @@ describe('TUI', function()
feed_data(':')
wait_for_mode('c')
-- "bracketed paste"
- feed_data('\027[200~'..expected..'\027[201~')
- screen:expect{grid=[[
+ feed_data('\027[200~' .. expected .. '\027[201~')
+ screen:expect([[
|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
:<{1: } |
{3:-- TERMINAL --} |
- ]]}
+ ]])
end)
it('paste: big burst of input', function()
@@ -1317,7 +1352,7 @@ describe('TUI', function()
feed_data('i')
wait_for_mode('i')
-- "bracketed paste"
- feed_data('\027[200~'..table.concat(t, '\n')..'\027[201~')
+ feed_data('\027[200~' .. table.concat(t, '\n') .. '\027[201~')
expect_child_buf_lines(t)
feed_data(' end')
screen:expect([[
@@ -1329,7 +1364,7 @@ describe('TUI', function()
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- feed_data('\027[27u') -- ESC: go to Normal mode.
+ feed_data('\027[27u') -- ESC: go to Normal mode.
wait_for_mode('n')
-- Dot-repeat/redo.
feed_data('.')
@@ -1347,9 +1382,10 @@ describe('TUI', function()
it('paste: forwards spurious "start paste" code', function()
-- If multiple "start paste" sequences are sent without a corresponding
-- "stop paste" sequence, only the first occurrence should be consumed.
-
+ feed_data('i')
+ wait_for_mode('i')
-- Send the "start paste" sequence.
- feed_data('i\027[200~')
+ feed_data('\027[200~')
feed_data('\npasted from terminal (1)\n')
-- Send spurious "start paste" sequence.
feed_data('\027[200~')
@@ -1357,7 +1393,7 @@ describe('TUI', function()
-- Send the "stop paste" sequence.
feed_data('\027[201~')
- screen:expect{grid=[[
+ screen:expect([[
|
pasted from terminal (1) |
{6:^[}[200~ |
@@ -1365,27 +1401,19 @@ describe('TUI', function()
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
- ]], attr_ids={
- [1] = {reverse = true},
- [2] = {background = tonumber('0x00000b')},
- [3] = {bold = true},
- [4] = {foreground = tonumber('0x00000c')},
- [5] = {bold = true, reverse = true},
- [6] = {foreground = tonumber('0x000051')},
- }}
+ ]])
end)
it('paste: ignores spurious "stop paste" code', function()
-- If "stop paste" sequence is received without a preceding "start paste"
-- sequence, it should be ignored.
feed_data('i')
+ wait_for_mode('i')
-- Send "stop paste" sequence.
feed_data('\027[201~')
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
@@ -1394,23 +1422,13 @@ describe('TUI', function()
it('paste: split "start paste" code', function()
feed_data('i')
- screen:expect{grid=[[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]]}
+ wait_for_mode('i')
-- Send split "start paste" sequence.
feed_data('\027[2')
feed_data('00~pasted from terminal\027[201~')
screen:expect([[
pasted from terminal{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
@@ -1419,23 +1437,13 @@ describe('TUI', function()
it('paste: split "stop paste" code', function()
feed_data('i')
- screen:expect{grid=[[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]]}
+ wait_for_mode('i')
-- Send split "stop paste" sequence.
feed_data('\027[200~pasted from terminal\027[20')
feed_data('1~')
screen:expect([[
pasted from terminal{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
@@ -1443,7 +1451,9 @@ describe('TUI', function()
end)
it('paste: streamed paste with isolated "stop paste" code', function()
- child_session:request('nvim_exec_lua', [[
+ child_session:request(
+ 'nvim_exec_lua',
+ [[
_G.paste_phases = {}
vim.paste = (function(overridden)
return function(lines, phase)
@@ -1451,57 +1461,47 @@ describe('TUI', function()
overridden(lines, phase)
end
end)(vim.paste)
- ]], {})
+ ]],
+ {}
+ )
feed_data('i')
- screen:expect{grid=[[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] }|
- {3:-- INSERT --} |
- {3:-- TERMINAL --} |
- ]]}
- feed_data('\027[200~pasted') -- phase 1
+ wait_for_mode('i')
+ feed_data('\027[200~pasted') -- phase 1
screen:expect([[
pasted{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- feed_data(' from terminal') -- phase 2
+ feed_data(' from terminal') -- phase 2
screen:expect([[
pasted from terminal{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
-- Send isolated "stop paste" sequence.
- feed_data('\027[201~') -- phase 3
+ feed_data('\027[201~') -- phase 3
screen:expect_unchanged()
local _, rv = child_session:request('nvim_exec_lua', [[return _G.paste_phases]], {})
- eq({1, 2, 3}, rv)
+ eq({ 1, 2, 3 }, rv)
end)
it('allows termguicolors to be set at runtime', function()
screen:set_option('rgb', true)
screen:set_default_attr_ids({
- [1] = {reverse = true},
- [2] = {foreground = tonumber('0x4040ff'), fg_indexed=true},
- [3] = {bold = true, reverse = true},
- [4] = {bold = true},
- [5] = {reverse = true, foreground = tonumber('0xe0e000'), fg_indexed=true},
- [6] = {foreground = tonumber('0xe0e000'), fg_indexed=true},
- [7] = {reverse = true, foreground = Screen.colors.SeaGreen4},
- [8] = {foreground = Screen.colors.SeaGreen4},
- [9] = {bold = true, foreground = Screen.colors.Blue1},
- [10] = {foreground = Screen.colors.Blue},
+ [1] = { reverse = true },
+ [2] = { foreground = tonumber('0x4040ff'), fg_indexed = true },
+ [3] = { bold = true, reverse = true },
+ [4] = { bold = true },
+ [5] = { reverse = true, foreground = tonumber('0xe0e000'), fg_indexed = true },
+ [6] = { foreground = tonumber('0xe0e000'), fg_indexed = true },
+ [7] = { reverse = true, foreground = Screen.colors.SeaGreen4 },
+ [8] = { foreground = Screen.colors.SeaGreen4 },
+ [9] = { bold = true, foreground = Screen.colors.Blue1 },
+ [10] = { foreground = Screen.colors.Blue },
})
feed_data(':hi SpecialKey ctermfg=3 guifg=SeaGreen\n')
@@ -1511,9 +1511,7 @@ describe('TUI', function()
feed_data(':set termguicolors?\n')
screen:expect([[
{5:^}{6:G} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
{3:[No Name] [+] }|
notermguicolors |
{4:-- TERMINAL --} |
@@ -1522,9 +1520,7 @@ describe('TUI', function()
feed_data(':set termguicolors\n')
screen:expect([[
{7:^}{8:G} |
- {9:~}{10: }|
- {9:~}{10: }|
- {9:~}{10: }|
+ {9:~}{10: }|*3
{3:[No Name] [+] }|
:set termguicolors |
{4:-- TERMINAL --} |
@@ -1533,9 +1529,7 @@ describe('TUI', function()
feed_data(':set notermguicolors\n')
screen:expect([[
{5:^}{6:G} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
{3:[No Name] [+] }|
:set notermguicolors |
{4:-- TERMINAL --} |
@@ -1544,50 +1538,54 @@ describe('TUI', function()
it('forwards :term palette colors with termguicolors', function()
if is_ci('github') then
- pending("tty-test complains about not owning the terminal -- actions/runner#241")
+ pending('tty-test complains about not owning the terminal -- actions/runner#241')
end
screen:set_rgb_cterm(true)
screen:set_default_attr_ids({
- [1] = {{reverse = true}, {reverse = true}},
- [2] = {{bold = true, reverse = true}, {bold = true, reverse = true}},
- [3] = {{bold = true}, {bold = true}},
- [4] = {{fg_indexed = true, foreground = tonumber('0xe0e000')}, {foreground = 3}},
- [5] = {{foreground = tonumber('0xff8000')}, {}},
+ [1] = { { reverse = true }, { reverse = true } },
+ [2] = { { bold = true, reverse = true }, { bold = true, reverse = true } },
+ [3] = { { bold = true }, { bold = true } },
+ [4] = { { fg_indexed = true, foreground = tonumber('0xe0e000') }, { foreground = 3 } },
+ [5] = { { foreground = tonumber('0xff8000') }, {} },
})
child_exec_lua('vim.o.statusline="^^^^^^^"')
child_exec_lua('vim.o.termguicolors=true')
child_exec_lua('vim.cmd.terminal(...)', testprg('tty-test'))
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:t}ty ready |
- |
- |
- |
+ |*3
{2:^^^^^^^ }|
|
{3:-- TERMINAL --} |
- ]]}
- feed_data(':call chansend(&channel, "\\033[38;5;3mtext\\033[38:2:255:128:0mcolor\\033[0;10mtext")\n')
- screen:expect{grid=[[
+ ]],
+ }
+ feed_data(
+ ':call chansend(&channel, "\\033[38;5;3mtext\\033[38:2:255:128:0mcolor\\033[0;10mtext")\n'
+ )
+ screen:expect {
+ grid = [[
{1:t}ty ready |
{4:text}{5:color}text |
- |
- |
+ |*2
{2:^^^^^^^ }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
feed_data(':set notermguicolors\n')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:t}ty ready |
{4:text}colortext |
- |
- |
+ |*2
{2:^^^^^^^ }|
:set notermguicolors |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
end)
it('in nvim_list_uis()', function()
@@ -1613,7 +1611,7 @@ describe('TUI', function()
term_background = '',
term_colors = 256,
term_name = exp_term,
- width = 50
+ width = 50,
},
}
local _, rv = child_session:request('nvim_list_uis')
@@ -1621,10 +1619,17 @@ describe('TUI', function()
end)
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_buf_set_lines',
+ 0,
+ 0,
+ -1,
+ true,
+ { ('℃'):rep(60), ('℃'):rep(60) }
+ )
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})
+ child_session:request('nvim_set_option_value', 'listchars', 'eol:$', { win = 0 })
feed_data('gg')
local singlewidth_screen = [[
{13:℃}{12:℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃℃}|
@@ -1651,9 +1656,9 @@ describe('TUI', function()
screen:expect(doublewidth_screen)
child_session:request('nvim_set_option_value', 'ambiwidth', 'single', {})
screen:expect(singlewidth_screen)
- child_session:request('nvim_call_function', 'setcellwidths', {{{0x2103, 0x2103, 2}}})
+ child_session:request('nvim_call_function', 'setcellwidths', { { { 0x2103, 0x2103, 2 } } })
screen:expect(doublewidth_screen)
- child_session:request('nvim_call_function', 'setcellwidths', {{{0x2103, 0x2103, 1}}})
+ child_session:request('nvim_call_function', 'setcellwidths', { { { 0x2103, 0x2103, 1 } } })
screen:expect(singlewidth_screen)
end)
@@ -1661,92 +1666,106 @@ describe('TUI', function()
helpers.skip(is_os('mac'), 'FIXME: crashes/errors on macOS')
screen:try_resize(77, 855)
retry(nil, nil, function()
- eq({true, 852}, {child_session:request('nvim_win_get_height', 0)})
+ eq({ true, 852 }, { child_session:request('nvim_win_get_height', 0) })
end)
-- Use full screen message so that redrawing afterwards is more deterministic.
child_session:notify('nvim_command', 'intro')
- screen:expect({any = 'Nvim'})
+ screen:expect({ any = 'Nvim' })
-- Going to top-left corner needs 3 bytes.
-- Setting underline attribute needs 9 bytes.
- -- The whole line needs 3 + 9 + 65515 + 3 = 65530 bytes.
+ -- The whole line needs 3 + 9 + 65513 + 3 = 65528 bytes.
-- The cursor_address that comes after will overflow the 65535-byte buffer.
- local line = ('a'):rep(65515) .. '℃'
- child_session:notify('nvim_exec_lua', [[
+ local line = ('a'):rep(65513) .. '℃'
+ child_session:notify(
+ 'nvim_exec_lua',
+ [[
vim.api.nvim_buf_set_lines(0, 0, -1, true, {...})
vim.o.cursorline = true
- ]], {line, 'b'})
+ ]],
+ { line, 'b' }
+ )
-- Close the :intro message and redraw the lines.
feed_data('\n')
screen:expect(
- '{13:a}{12:' .. ('a'):rep(76) .. '}|\n'
- .. ('{12:' .. ('a'):rep(77) .. '}|\n'):rep(849)
- .. '{12:' .. ('a'):rep(65) .. '℃' .. (' '):rep(11) .. '}|\n' .. dedent([[
+ '{13:a}{12:'
+ .. ('a'):rep(76)
+ .. '}|\n'
+ .. ('{12:' .. ('a'):rep(77) .. '}|\n'):rep(849)
+ .. '{12:'
+ .. ('a'):rep(63)
+ .. '℃'
+ .. (' '):rep(13)
+ .. '}|\n'
+ .. dedent([[
b |
{5:[No Name] [+] }|
|
- {3:-- TERMINAL --} |]]))
+ {3:-- TERMINAL --} |]])
+ )
end)
it('visual bell (padding) does not crash #21610', function()
feed_data ':set visualbell\n'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
:set visualbell |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
-- move left is enough to invoke the bell
feed_data 'h'
-- visual change to show we process events after this
feed_data 'i'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
end)
it('no assert failure on deadly signal #21896', function()
exec_lua([[vim.uv.kill(vim.fn.jobpid(vim.bo.channel), 'sigterm')]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
Vim: Caught deadly signal 'SIGTERM' |
- |
- |
+ |*2
[Process exited 1]{1: } |
- |
- |
+ |*2
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
end)
it('no stack-use-after-scope with cursor color #22432', function()
screen:set_option('rgb', true)
command('set termguicolors')
- child_session:request('nvim_exec2', [[
+ child_session:request(
+ 'nvim_exec2',
+ [[
set tgc
hi Cursor guifg=Red guibg=Green
set guicursor=n:block-Cursor/lCursor
- ]], {})
+ ]],
+ {}
+ )
screen:set_default_attr_ids({
- [1] = {reverse = true},
- [2] = {bold = true, foreground = Screen.colors.Blue},
- [3] = {foreground = Screen.colors.Blue},
- [4] = {reverse = true, bold = true},
- [5] = {bold = true},
+ [1] = { reverse = true },
+ [2] = { bold = true, foreground = Screen.colors.Blue },
+ [3] = { foreground = Screen.colors.Blue },
+ [4] = { reverse = true, bold = true },
+ [5] = { bold = true },
})
screen:expect([[
{1: } |
- {2:~}{3: }|
- {2:~}{3: }|
- {2:~}{3: }|
+ {2:~}{3: }|*3
{4:[No Name] }|
|
{5:-- TERMINAL --} |
@@ -1754,9 +1773,7 @@ describe('TUI', function()
feed_data('i')
screen:expect([[
{1: } |
- {2:~}{3: }|
- {2:~}{3: }|
- {2:~}{3: }|
+ {2:~}{3: }|*3
{4:[No Name] }|
{5:-- INSERT --} |
{5:-- TERMINAL --} |
@@ -1764,12 +1781,10 @@ describe('TUI', function()
end)
it('redraws on SIGWINCH even if terminal size is unchanged #23411', function()
- child_session:request('nvim_echo', {{'foo'}}, false, {})
+ child_session:request('nvim_echo', { { 'foo' } }, false, {})
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
foo |
{3:-- TERMINAL --} |
@@ -1777,9 +1792,7 @@ describe('TUI', function()
exec_lua([[vim.uv.kill(vim.fn.jobpid(vim.bo.channel), 'sigwinch')]])
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
|
{3:-- TERMINAL --} |
@@ -1787,14 +1800,14 @@ describe('TUI', function()
end)
it('supports hiding cursor', function()
- child_session:request('nvim_command',
- "let g:id = jobstart([v:progpath, '--clean', '--headless'])")
+ child_session:request(
+ 'nvim_command',
+ "let g:id = jobstart([v:progpath, '--clean', '--headless'])"
+ )
feed_data(':call jobwait([g:id])\n')
screen:expect([[
|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
:call jobwait([g:id]) |
{3:-- TERMINAL --} |
@@ -1802,14 +1815,73 @@ describe('TUI', function()
feed_data('\003')
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
Type :qa and press <Enter> to exit Nvim |
{3:-- TERMINAL --} |
]])
end)
+
+ it('cursor is not hidden on incsearch with no match', function()
+ feed_data('ifoo\027')
+ feed_data('/foo')
+ screen:expect([[
+ {1:foo} |
+ {4:~ }|*3
+ {5:[No Name] [+] }|
+ /foo{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ screen:sleep(10)
+ feed_data('b')
+ screen:expect([[
+ foo |
+ {4:~ }|*3
+ {5:[No Name] [+] }|
+ /foob{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ screen:sleep(10)
+ feed_data('a')
+ screen:expect([[
+ foo |
+ {4:~ }|*3
+ {5:[No Name] [+] }|
+ /fooba{1: } |
+ {3:-- TERMINAL --} |
+ ]])
+ end)
+
+ it('emits hyperlinks with OSC 8', function()
+ exec_lua([[
+ local buf = vim.api.nvim_get_current_buf()
+ _G.urls = {}
+ vim.api.nvim_create_autocmd('TermRequest', {
+ buffer = buf,
+ callback = function(args)
+ local req = args.data
+ if not req then
+ return
+ end
+ local url = req:match('\027]8;;(.*)$')
+ if url ~= nil then
+ table.insert(_G.urls, url)
+ end
+ end,
+ })
+ ]])
+ child_exec_lua([[
+ vim.api.nvim_buf_set_lines(0, 0, 0, true, {'Hello'})
+ local ns = vim.api.nvim_create_namespace('test')
+ vim.api.nvim_buf_set_extmark(0, ns, 0, 1, {
+ end_col = 3,
+ url = 'https://example.com',
+ })
+ ]])
+ retry(nil, 1000, function()
+ eq({ 'https://example.com', '' }, exec_lua([[return _G.urls]]))
+ end)
+ end)
end)
describe('TUI', function()
@@ -1818,25 +1890,34 @@ describe('TUI', function()
it('resize at startup #17285 #15044 #11330', function()
local screen = Screen.new(50, 10)
screen:set_default_attr_ids({
- [1] = {reverse = true},
- [2] = {bold = true, foreground = Screen.colors.Blue},
- [3] = {bold = true},
- [4] = {foreground = tonumber('0x4040ff'), fg_indexed = true},
- [5] = {bold = true, reverse = true},
+ [1] = { reverse = true },
+ [2] = { bold = true, foreground = Screen.colors.Blue },
+ [3] = { bold = true },
+ [4] = { foreground = tonumber('0x4040ff'), fg_indexed = true },
+ [5] = { bold = true, reverse = true },
})
screen:attach()
+ fn.termopen({
+ nvim_prog,
+ '--clean',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ 'set notermguicolors',
+ '--cmd',
+ 'let start = reltime() | while v:true | if reltimefloat(reltime(start)) > 2 | break | endif | endwhile',
+ }, {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+ },
+ })
exec([[
- call termopen([v:progpath, '--clean', '--cmd', 'let start = reltime() | while v:true | if reltimefloat(reltime(start)) > 2 | break | endif | endwhile'])
sleep 500m
vs new
]])
screen:expect([[
^ │ |
- {2:~ }│{4:~ }|
- {2:~ }│{4:~ }|
- {2:~ }│{4:~ }|
- {2:~ }│{4:~ }|
- {2:~ }│{4:~ }|
+ {2:~ }│{4:~ }|*5
{2:~ }│{5:[No Name] 0,0-1 All}|
{2:~ }│ |
{5:new }{1:{MATCH:<.*[/\]nvim }}|
@@ -1849,43 +1930,53 @@ describe('TUI', function()
pending('missing LuaJIT FFI')
end
local script_file = 'Xargv0.lua'
- write_file(script_file, [=[
+ write_file(
+ script_file,
+ [=[
local ffi = require('ffi')
ffi.cdef([[int execl(const char *, const char *, ...);]])
- ffi.C.execl(vim.v.progpath, 'Xargv0nvim', '--clean')
- ]=])
+ ffi.C.execl(vim.v.progpath, 'Xargv0nvim', '--clean', nil)
+ ]=]
+ )
finally(function()
os.remove(script_file)
end)
- local screen = thelpers.screen_setup(0, string.format([=[["%s", "--clean", "-l", "%s"]]=],
- nvim_prog, script_file))
- screen:expect{grid=[[
+ local screen = thelpers.setup_child_nvim({ '--clean', '-l', script_file })
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
+ ~ |*3
+ [No Name] 0,0-1 All|
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
feed_data(':put =v:argv + [v:progname]\n')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
Xargv0nvim |
--embed |
--clean |
{1:X}argv0nvim |
- {5:[No Name] [+] 5,1 Bot}|
+ [No Name] [+] 5,1 Bot|
4 more lines |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
end)
it('with non-tty (pipe) stdout/stderr', function()
finally(function()
os.remove('testF')
end)
- local screen = thelpers.screen_setup(0, '"'..nvim_prog
- ..' -u NONE -i NONE --cmd \'set noswapfile noshowcmd noruler\' --cmd \'normal iabc\' > /dev/null 2>&1 && cat testF && rm testF"')
+ local screen = thelpers.screen_setup(
+ 0,
+ ('"%s" -u NONE -i NONE --cmd "set noswapfile noshowcmd noruler" --cmd "normal iabc" > /dev/null 2>&1 && cat testF && rm testF'):format(
+ nvim_prog
+ ),
+ nil,
+ { VIMRUNTIME = os.getenv('VIMRUNTIME') }
+ )
feed_data(':w testF\n:q\n')
screen:expect([[
:w testF |
@@ -1899,24 +1990,32 @@ describe('TUI', function()
end)
it('<C-h> #10134', function()
- local screen = thelpers.screen_setup(0, '["'..nvim_prog
- ..[[", "-u", "NONE", "-i", "NONE", "--cmd", "set noruler", "--cmd", ':nnoremap <C-h> :echomsg "\<C-h\>"<CR>']]..']')
- screen:expect{grid=[[
+ local screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ 'set noruler notermguicolors',
+ '--cmd',
+ ':nnoremap <C-h> :echomsg "\\<C-h\\>"<CR>',
+ })
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
command([[call chansend(b:terminal_job_id, "\<C-h>")]])
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
<C-h> |
{3:-- TERMINAL --} |
@@ -1924,19 +2023,31 @@ describe('TUI', function()
end)
it('draws line with many trailing spaces correctly #24955', function()
- local screen = thelpers.screen_setup(0, '["'..nvim_prog..[[", "-u", "NONE", "-i", "NONE"]]
- ..[[, "--cmd", "call setline(1, ['1st line' .. repeat(' ', 153), '2nd line'])"]]..']', 80)
- screen:expect{grid=[[
+ local screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'set notermguicolors',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ 'call setline(1, ["1st line" .. repeat(" ", 153), "2nd line"])',
+ }, { cols = 80 })
+ screen:expect {
+ grid = [[
{1:1}st line |
- |
- |
+ |*2
2nd line |
{5:[No Name] [+] 1,1 All}|
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
feed_data('$')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
1st line |
|
{1: } |
@@ -1944,41 +2055,93 @@ describe('TUI', function()
{5:[No Name] [+] 1,161 All}|
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
+ end)
+
+ it('no heap-buffer-overflow when changing &columns', function()
+ -- Set a different bg colour and change $TERM to something dumber so the `print_spaces()`
+ -- codepath in `clear_region()` is hit.
+ local screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'set notermguicolors | highlight Normal ctermbg=red',
+ '--cmd',
+ 'call setline(1, ["a"->repeat(&columns)])',
+ }, { env = { TERM = 'ansi' } })
+
+ screen:expect {
+ grid = [[
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ ~ |*3
+ [No Name] [+] 1,1 All|
+ |
+ -- TERMINAL -- |
+ ]],
+ attr_ids = {},
+ }
+
+ feed_data(':set columns=12\n')
+ screen:expect {
+ grid = [[
+ aaaaaaaaaaaa |*4
+ < [+] 1,1 |
+ |
+ -- TERMINAL -- |
+ ]],
+ attr_ids = {},
+ }
+
+ -- Wider than TUI, so screen state will look weird.
+ -- Wait for the statusline to redraw to confirm that the TUI lives and ASAN is happy.
+ feed_data(':set columns=99|set stl=redrawn%m\n')
+ screen:expect({ any = 'redrawn%[%+%]' })
end)
end)
describe('TUI UIEnter/UILeave', function()
it('fires exactly once, after VimEnter', function()
clear()
- local screen = thelpers.screen_setup(0,
- '["'..nvim_prog..'", "-u", "NONE", "-i", "NONE"'
- ..[[, "--cmd", "set noswapfile noshowcmd noruler"]]
- ..[[, "--cmd", "let g:evs = []"]]
- ..[[, "--cmd", "autocmd UIEnter * :call add(g:evs, 'UIEnter')"]]
- ..[[, "--cmd", "autocmd UILeave * :call add(g:evs, 'UILeave')"]]
- ..[[, "--cmd", "autocmd VimEnter * :call add(g:evs, 'VimEnter')"]]
- ..']'
- )
- screen:expect{grid=[[
+ local screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ 'set noswapfile noshowcmd noruler notermguicolors',
+ '--cmd',
+ 'let g:evs = []',
+ '--cmd',
+ 'autocmd UIEnter * :call add(g:evs, "UIEnter")',
+ '--cmd',
+ 'autocmd UILeave * :call add(g:evs, "UILeave")',
+ '--cmd',
+ 'autocmd VimEnter * :call add(g:evs, "VimEnter")',
+ })
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
|
{3:-- TERMINAL --} |
- ]]}
- feed_data(":echo g:evs\n")
- screen:expect{grid=[[
+ ]],
+ }
+ feed_data(':echo g:evs\n')
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
['VimEnter', 'UIEnter'] |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
end)
end)
@@ -1989,25 +2152,36 @@ describe('TUI FocusGained/FocusLost', function()
before_each(function()
clear()
local child_server = new_pipename()
- screen = thelpers.screen_setup(0,
- string.format(
- [=[["%s", "--listen", "%s", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile noshowcmd noruler"]]=],
- nvim_prog, child_server))
+ screen = thelpers.setup_child_nvim({
+ '--listen',
+ child_server,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ 'set noswapfile noshowcmd noruler notermguicolors background=dark',
+ })
+
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
|
{3:-- TERMINAL --} |
]])
child_session = helpers.connect(child_server)
- child_session:request('nvim_exec2', [[
+ child_session:request(
+ 'nvim_exec2',
+ [[
autocmd FocusGained * echo 'gained'
autocmd FocusLost * echo 'lost'
- ]], {})
- feed_data("\034\016") -- CTRL-\ CTRL-N
+ ]],
+ {}
+ )
+ feed_data('\034\016') -- CTRL-\ CTRL-N
end)
it('in normal-mode', function()
@@ -2015,9 +2189,7 @@ describe('TUI FocusGained/FocusLost', function()
feed_data('\027[I')
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
gained |
{3:-- TERMINAL --} |
@@ -2026,9 +2198,7 @@ describe('TUI FocusGained/FocusLost', function()
feed_data('\027[O')
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
lost |
{3:-- TERMINAL --} |
@@ -2039,22 +2209,20 @@ describe('TUI FocusGained/FocusLost', function()
it('in insert-mode', function()
feed_data(':set noshowmode\r')
feed_data('i')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
:set noshowmode |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
retry(2, 3 * screen.timeout, function()
feed_data('\027[I')
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
gained |
{3:-- TERMINAL --} |
@@ -2062,9 +2230,7 @@ describe('TUI FocusGained/FocusLost', function()
feed_data('\027[O')
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
lost |
{3:-- TERMINAL --} |
@@ -2079,34 +2245,37 @@ describe('TUI FocusGained/FocusLost', function()
feed_data('\027[I')
screen:expect([[
|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
:{1: } |
{3:-- TERMINAL --} |
]])
feed_data('\027[O')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
:{1: } |
{3:-- TERMINAL --} |
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
end)
it('in cmdline-mode', function()
-- Set up autocmds that modify the buffer, instead of just calling :echo.
-- This is how we can test handling of focus gained/lost during cmdline-mode.
-- See commit: 5cc87d4dabd02167117be7a978b5c8faaa975419.
- child_session:request('nvim_exec2', [[
+ child_session:request(
+ 'nvim_exec2',
+ [[
autocmd!
autocmd FocusLost * call append(line('$'), 'lost')
autocmd FocusGained * call append(line('$'), 'gained')
- ]], {})
+ ]],
+ {}
+ )
retry(2, 3 * screen.timeout, function()
-- Enter cmdline-mode.
feed_data(':')
@@ -2118,44 +2287,46 @@ describe('TUI FocusGained/FocusLost', function()
-- Exit cmdline-mode. Redraws from timers/events are blocked during
-- cmdline-mode, so the buffer won't be updated until we exit cmdline-mode.
feed_data('\n')
- screen:expect{any='lost'..(' '):rep(46)..'|\ngained'}
+ screen:expect { any = 'lost' .. (' '):rep(46) .. '|\ngained' }
end)
end)
it('in terminal-mode', function()
- feed_data(':set shell='..testprg('shell-test')..' shellcmdflag=EXE\n')
+ feed_data(':set shell=' .. testprg('shell-test') .. ' shellcmdflag=EXE\n')
feed_data(':set noshowmode laststatus=0\n')
feed_data(':terminal zia\n')
-- Wait for terminal to be ready.
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:r}eady $ zia |
|
[Process exited 0] |
- |
- |
+ |*2
:terminal zia |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
feed_data('\027[I')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:r}eady $ zia |
|
[Process exited 0] |
- |
- |
+ |*2
gained |
{3:-- TERMINAL --} |
- ]], timeout=(4 * screen.timeout)}
+ ]],
+ timeout = (4 * screen.timeout),
+ }
feed_data('\027[O')
screen:expect([[
{1:r}eady $ zia |
|
[Process exited 0] |
- |
- |
+ |*2
lost |
{3:-- TERMINAL --} |
]])
@@ -2164,8 +2335,9 @@ describe('TUI FocusGained/FocusLost', function()
it('in press-enter prompt', function()
feed_data(":echom 'msg1'|echom 'msg2'|echom 'msg3'|echom 'msg4'|echom 'msg5'\n")
-- Execute :messages to provoke the press-enter prompt.
- feed_data(":messages\n")
- screen:expect{grid=[[
+ feed_data(':messages\n')
+ screen:expect {
+ grid = [[
msg1 |
msg2 |
msg3 |
@@ -2173,10 +2345,12 @@ describe('TUI FocusGained/FocusLost', function()
msg5 |
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
feed_data('\027[I')
feed_data('\027[I')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
msg1 |
msg2 |
msg3 |
@@ -2184,7 +2358,9 @@ describe('TUI FocusGained/FocusLost', function()
msg5 |
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
end)
end)
@@ -2194,97 +2370,108 @@ describe("TUI 't_Co' (terminal colors)", function()
local screen
local function assert_term_colors(term, colorterm, maxcolors)
- clear({env={TERM=term}, args={}})
- -- This is ugly because :term/termopen() forces TERM=xterm-256color.
- -- TODO: Revisit this after jobstart/termopen accept `env` dict.
- screen = thelpers.screen_setup(0, string.format(
- [=[['sh', '-c', 'LANG=C TERM=%s %s %s -u NONE -i NONE --cmd "%s"']]=],
- term or "",
- (colorterm ~= nil and "COLORTERM="..colorterm or ""),
- nvim_prog,
- nvim_set))
+ clear({ env = { TERM = term }, args = {} })
+ screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ nvim_set .. ' notermguicolors',
+ }, {
+ env = {
+ LANG = 'C',
+ TERM = term or '',
+ COLORTERM = colorterm or '',
+ },
+ })
local tline
- if maxcolors == 8 or maxcolors == 16 then
- tline = "~ "
+ if maxcolors == 8 then
+ tline = '{9:~ }'
+ elseif maxcolors == 16 then
+ tline = '~ '
else
- tline = "{4:~ }"
+ tline = '{4:~ }'
end
- screen:expect(string.format([[
+ screen:expect(string.format(
+ [[
{1: } |
- %s|
- %s|
- %s|
- %s|
+ %s|*4
|
{3:-- TERMINAL --} |
- ]], tline, tline, tline, tline))
+ ]],
+ tline
+ ))
- feed_data(":echo &t_Co\n")
- screen:expect(string.format([[
+ feed_data(':echo &t_Co\n')
+ screen:expect(string.format(
+ [[
{1: } |
- %s|
- %s|
- %s|
- %s|
+ %s|*4
%-3s |
{3:-- TERMINAL --} |
- ]], tline, tline, tline, tline, tostring(maxcolors and maxcolors or "")))
+ ]],
+ tline,
+ tostring(maxcolors and maxcolors or '')
+ ))
end
-- ansi and no terminal type at all:
- it("no TERM uses 8 colors", function()
+ it('no TERM uses 8 colors', function()
assert_term_colors(nil, nil, 8)
end)
- it("TERM=ansi no COLORTERM uses 8 colors", function()
- assert_term_colors("ansi", nil, 8)
+ it('TERM=ansi no COLORTERM uses 8 colors', function()
+ assert_term_colors('ansi', nil, 8)
end)
- it("TERM=ansi with COLORTERM=anything-no-number uses 16 colors", function()
- assert_term_colors("ansi", "yet-another-term", 16)
+ it('TERM=ansi with COLORTERM=anything-no-number uses 16 colors', function()
+ assert_term_colors('ansi', 'yet-another-term', 16)
end)
- it("unknown TERM COLORTERM with 256 in name uses 256 colors", function()
- assert_term_colors("ansi", "yet-another-term-256color", 256)
+ it('unknown TERM COLORTERM with 256 in name uses 256 colors', function()
+ assert_term_colors('ansi', 'yet-another-term-256color', 256)
end)
- it("TERM=ansi-256color sets 256 colours", function()
- assert_term_colors("ansi-256color", nil, 256)
+ it('TERM=ansi-256color sets 256 colours', function()
+ assert_term_colors('ansi-256color', nil, 256)
end)
-- Unknown terminal types:
- it("unknown TERM no COLORTERM sets 8 colours", function()
- assert_term_colors("yet-another-term", nil, 8)
+ it('unknown TERM no COLORTERM sets 8 colours', function()
+ assert_term_colors('yet-another-term', nil, 8)
end)
- it("unknown TERM with COLORTERM=anything-no-number uses 16 colors", function()
- assert_term_colors("yet-another-term", "yet-another-term", 16)
+ it('unknown TERM with COLORTERM=anything-no-number uses 16 colors', function()
+ assert_term_colors('yet-another-term', 'yet-another-term', 16)
end)
- it("unknown TERM with 256 in name sets 256 colours", function()
- assert_term_colors("yet-another-term-256color", nil, 256)
+ it('unknown TERM with 256 in name sets 256 colours', function()
+ assert_term_colors('yet-another-term-256color', nil, 256)
end)
- it("unknown TERM COLORTERM with 256 in name uses 256 colors", function()
- assert_term_colors("yet-another-term", "yet-another-term-256color", 256)
+ it('unknown TERM COLORTERM with 256 in name uses 256 colors', function()
+ assert_term_colors('yet-another-term', 'yet-another-term-256color', 256)
end)
-- Linux kernel terminal emulator:
- it("TERM=linux uses 256 colors", function()
- assert_term_colors("linux", nil, 256)
+ it('TERM=linux uses 256 colors', function()
+ assert_term_colors('linux', nil, 256)
end)
- it("TERM=linux-16color uses 256 colors", function()
- assert_term_colors("linux-16color", nil, 256)
+ it('TERM=linux-16color uses 256 colors', function()
+ assert_term_colors('linux-16color', nil, 256)
end)
- it("TERM=linux-256color uses 256 colors", function()
- assert_term_colors("linux-256color", nil, 256)
+ it('TERM=linux-256color uses 256 colors', function()
+ assert_term_colors('linux-256color', nil, 256)
end)
-- screen:
@@ -2293,28 +2480,28 @@ describe("TUI 't_Co' (terminal colors)", function()
-- Linux and MacOS have a screen entry in external terminfo with 8 colours,
-- which is raised to 16 by COLORTERM.
- it("TERM=screen no COLORTERM uses 8/256 colors", function()
+ it('TERM=screen no COLORTERM uses 8/256 colors', function()
if is_os('freebsd') then
- assert_term_colors("screen", nil, 256)
+ assert_term_colors('screen', nil, 256)
else
- assert_term_colors("screen", nil, 8)
+ assert_term_colors('screen', nil, 8)
end
end)
- it("TERM=screen COLORTERM=screen uses 16/256 colors", function()
+ it('TERM=screen COLORTERM=screen uses 16/256 colors', function()
if is_os('freebsd') then
- assert_term_colors("screen", "screen", 256)
+ assert_term_colors('screen', 'screen', 256)
else
- assert_term_colors("screen", "screen", 16)
+ assert_term_colors('screen', 'screen', 16)
end
end)
- it("TERM=screen COLORTERM=screen-256color uses 256 colors", function()
- assert_term_colors("screen", "screen-256color", 256)
+ it('TERM=screen COLORTERM=screen-256color uses 256 colors', function()
+ assert_term_colors('screen', 'screen-256color', 256)
end)
- it("TERM=screen-256color no COLORTERM uses 256 colors", function()
- assert_term_colors("screen-256color", nil, 256)
+ it('TERM=screen-256color no COLORTERM uses 256 colors', function()
+ assert_term_colors('screen-256color', nil, 256)
end)
-- tmux:
@@ -2323,38 +2510,38 @@ describe("TUI 't_Co' (terminal colors)", function()
-- Linux has a tmux entry in external terminfo with 8 colours,
-- which is raised to 256.
- it("TERM=tmux no COLORTERM uses 256 colors", function()
- assert_term_colors("tmux", nil, 256)
+ it('TERM=tmux no COLORTERM uses 256 colors', function()
+ assert_term_colors('tmux', nil, 256)
end)
- it("TERM=tmux COLORTERM=tmux uses 256 colors", function()
- assert_term_colors("tmux", "tmux", 256)
+ it('TERM=tmux COLORTERM=tmux uses 256 colors', function()
+ assert_term_colors('tmux', 'tmux', 256)
end)
- it("TERM=tmux COLORTERM=tmux-256color uses 256 colors", function()
- assert_term_colors("tmux", "tmux-256color", 256)
+ it('TERM=tmux COLORTERM=tmux-256color uses 256 colors', function()
+ assert_term_colors('tmux', 'tmux-256color', 256)
end)
- it("TERM=tmux-256color no COLORTERM uses 256 colors", function()
- assert_term_colors("tmux-256color", nil, 256)
+ it('TERM=tmux-256color no COLORTERM uses 256 colors', function()
+ assert_term_colors('tmux-256color', nil, 256)
end)
-- xterm and imitators:
- it("TERM=xterm uses 256 colors", function()
- assert_term_colors("xterm", nil, 256)
+ it('TERM=xterm uses 256 colors', function()
+ assert_term_colors('xterm', nil, 256)
end)
- it("TERM=xterm COLORTERM=gnome-terminal uses 256 colors", function()
- assert_term_colors("xterm", "gnome-terminal", 256)
+ it('TERM=xterm COLORTERM=gnome-terminal uses 256 colors', function()
+ assert_term_colors('xterm', 'gnome-terminal', 256)
end)
- it("TERM=xterm COLORTERM=mate-terminal uses 256 colors", function()
- assert_term_colors("xterm", "mate-terminal", 256)
+ it('TERM=xterm COLORTERM=mate-terminal uses 256 colors', function()
+ assert_term_colors('xterm', 'mate-terminal', 256)
end)
- it("TERM=xterm-256color uses 256 colors", function()
- assert_term_colors("xterm-256color", nil, 256)
+ it('TERM=xterm-256color uses 256 colors', function()
+ assert_term_colors('xterm-256color', nil, 256)
end)
-- rxvt and stterm:
@@ -2364,44 +2551,44 @@ describe("TUI 't_Co' (terminal colors)", function()
-- Linux has an rxvt, an st, and an st-16color entry in external terminfo
-- with 8, 8, and 16 colours respectively, which are raised to 256.
- it("TERM=rxvt no COLORTERM uses 256 colors", function()
- assert_term_colors("rxvt", nil, 256)
+ it('TERM=rxvt no COLORTERM uses 256 colors', function()
+ assert_term_colors('rxvt', nil, 256)
end)
- it("TERM=rxvt COLORTERM=rxvt uses 256 colors", function()
- assert_term_colors("rxvt", "rxvt", 256)
+ it('TERM=rxvt COLORTERM=rxvt uses 256 colors', function()
+ assert_term_colors('rxvt', 'rxvt', 256)
end)
- it("TERM=rxvt-256color uses 256 colors", function()
- assert_term_colors("rxvt-256color", nil, 256)
+ it('TERM=rxvt-256color uses 256 colors', function()
+ assert_term_colors('rxvt-256color', nil, 256)
end)
- it("TERM=st no COLORTERM uses 256 colors", function()
- assert_term_colors("st", nil, 256)
+ it('TERM=st no COLORTERM uses 256 colors', function()
+ assert_term_colors('st', nil, 256)
end)
- it("TERM=st COLORTERM=st uses 256 colors", function()
- assert_term_colors("st", "st", 256)
+ it('TERM=st COLORTERM=st uses 256 colors', function()
+ assert_term_colors('st', 'st', 256)
end)
- it("TERM=st COLORTERM=st-256color uses 256 colors", function()
- assert_term_colors("st", "st-256color", 256)
+ it('TERM=st COLORTERM=st-256color uses 256 colors', function()
+ assert_term_colors('st', 'st-256color', 256)
end)
- it("TERM=st-16color no COLORTERM uses 8/256 colors", function()
- assert_term_colors("st", nil, 256)
+ it('TERM=st-16color no COLORTERM uses 8/256 colors', function()
+ assert_term_colors('st', nil, 256)
end)
- it("TERM=st-16color COLORTERM=st uses 16/256 colors", function()
- assert_term_colors("st", "st", 256)
+ it('TERM=st-16color COLORTERM=st uses 16/256 colors', function()
+ assert_term_colors('st', 'st', 256)
end)
- it("TERM=st-16color COLORTERM=st-256color uses 256 colors", function()
- assert_term_colors("st", "st-256color", 256)
+ it('TERM=st-16color COLORTERM=st-256color uses 256 colors', function()
+ assert_term_colors('st', 'st-256color', 256)
end)
- it("TERM=st-256color uses 256 colors", function()
- assert_term_colors("st-256color", nil, 256)
+ it('TERM=st-256color uses 256 colors', function()
+ assert_term_colors('st-256color', nil, 256)
end)
-- gnome and vte:
@@ -2411,54 +2598,53 @@ describe("TUI 't_Co' (terminal colors)", function()
-- external terminfo with 8, 8, 256, and 256 colours respectively, which are
-- raised to 256.
- it("TERM=gnome no COLORTERM uses 256 colors", function()
- assert_term_colors("gnome", nil, 256)
+ it('TERM=gnome no COLORTERM uses 256 colors', function()
+ assert_term_colors('gnome', nil, 256)
end)
- it("TERM=gnome COLORTERM=gnome uses 256 colors", function()
- assert_term_colors("gnome", "gnome", 256)
+ it('TERM=gnome COLORTERM=gnome uses 256 colors', function()
+ assert_term_colors('gnome', 'gnome', 256)
end)
- it("TERM=gnome COLORTERM=gnome-256color uses 256 colors", function()
- assert_term_colors("gnome", "gnome-256color", 256)
+ it('TERM=gnome COLORTERM=gnome-256color uses 256 colors', function()
+ assert_term_colors('gnome', 'gnome-256color', 256)
end)
- it("TERM=gnome-256color uses 256 colors", function()
- assert_term_colors("gnome-256color", nil, 256)
+ it('TERM=gnome-256color uses 256 colors', function()
+ assert_term_colors('gnome-256color', nil, 256)
end)
- it("TERM=vte no COLORTERM uses 256 colors", function()
- assert_term_colors("vte", nil, 256)
+ it('TERM=vte no COLORTERM uses 256 colors', function()
+ assert_term_colors('vte', nil, 256)
end)
- it("TERM=vte COLORTERM=vte uses 256 colors", function()
- assert_term_colors("vte", "vte", 256)
+ it('TERM=vte COLORTERM=vte uses 256 colors', function()
+ assert_term_colors('vte', 'vte', 256)
end)
- it("TERM=vte COLORTERM=vte-256color uses 256 colors", function()
- assert_term_colors("vte", "vte-256color", 256)
+ it('TERM=vte COLORTERM=vte-256color uses 256 colors', function()
+ assert_term_colors('vte', 'vte-256color', 256)
end)
- it("TERM=vte-256color uses 256 colors", function()
- assert_term_colors("vte-256color", nil, 256)
+ it('TERM=vte-256color uses 256 colors', function()
+ assert_term_colors('vte-256color', nil, 256)
end)
-- others:
-- TODO(blueyed): this is made pending, since it causes failure + later hang
-- when using non-compatible libvterm (#9494/#10179).
- pending("TERM=interix uses 8 colors", function()
- assert_term_colors("interix", nil, 8)
+ pending('TERM=interix uses 8 colors', function()
+ assert_term_colors('interix', nil, 8)
end)
- it("TERM=iTerm.app uses 256 colors", function()
- assert_term_colors("iTerm.app", nil, 256)
+ it('TERM=iTerm.app uses 256 colors', function()
+ assert_term_colors('iTerm.app', nil, 256)
end)
- it("TERM=iterm uses 256 colors", function()
- assert_term_colors("iterm", nil, 256)
+ it('TERM=iterm uses 256 colors', function()
+ assert_term_colors('iterm', nil, 256)
end)
-
end)
-- These tests require `thelpers` because --headless/--embed
@@ -2468,39 +2654,43 @@ describe("TUI 'term' option", function()
local function assert_term(term_envvar, term_expected)
clear()
- -- This is ugly because :term/termopen() forces TERM=xterm-256color.
- -- TODO: Revisit this after jobstart/termopen accept `env` dict.
- local cmd = string.format(
- [=[['sh', '-c', 'LANG=C TERM=%s %s -u NONE -i NONE --cmd "%s"']]=],
- term_envvar or "",
- nvim_prog,
- nvim_set)
- screen = thelpers.screen_setup(0, cmd)
+ screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ nvim_set .. ' notermguicolors',
+ }, {
+ env = {
+ LANG = 'C',
+ TERM = term_envvar or '',
+ },
+ })
local full_timeout = screen.timeout
- screen.timeout = 250 -- We want screen:expect() to fail quickly.
- retry(nil, 2 * full_timeout, function() -- Wait for TUI thread to set 'term'.
+ retry(nil, 2 * full_timeout, function() -- Wait for TUI thread to set 'term'.
feed_data(":echo 'term='.(&term)\n")
- screen:expect{any='term='..term_expected}
+ screen:expect { any = 'term=' .. term_expected, timeout = 250 }
end)
end
it('gets builtin term if $TERM is invalid', function()
- assert_term("foo", "builtin_ansi")
+ assert_term('foo', 'builtin_ansi')
end)
it('gets system-provided term if $TERM is valid', function()
if is_os('openbsd') then
- assert_term("xterm", "xterm")
- elseif is_os('bsd') then -- BSD lacks terminfo, builtin is always used.
- assert_term("xterm", "builtin_xterm")
+ assert_term('xterm', 'xterm')
+ elseif is_os('bsd') then -- BSD lacks terminfo, builtin is always used.
+ assert_term('xterm', 'builtin_xterm')
elseif is_os('mac') then
- local status, _ = pcall(assert_term, "xterm", "xterm")
+ local status, _ = pcall(assert_term, 'xterm', 'xterm')
if not status then
- pending("macOS: unibilium could not find terminfo")
+ pending('macOS: unibilium could not find terminfo')
end
else
- assert_term("xterm", "xterm")
+ assert_term('xterm', 'xterm')
end
end)
@@ -2510,12 +2700,11 @@ describe("TUI 'term' option", function()
assert_term('conemu', 'builtin_conemu')
assert_term('vtpcon', 'builtin_vtpcon')
end)
-
end)
-- These tests require `thelpers` because --headless/--embed
-- does not initialize the TUI.
-describe("TUI", function()
+describe('TUI', function()
local screen
local logfile = 'Xtest_tui_verbose_log'
after_each(function()
@@ -2525,284 +2714,398 @@ describe("TUI", function()
-- Runs (child) `nvim` in a TTY (:terminal), to start the builtin TUI.
local function nvim_tui(extra_args)
clear()
- -- This is ugly because :term/termopen() forces TERM=xterm-256color.
- -- TODO: Revisit this after jobstart/termopen accept `env` dict.
- local cmd = string.format(
- [=[['sh', '-c', 'LANG=C %s -u NONE -i NONE %s --cmd "%s"']]=],
- nvim_prog,
- extra_args or "",
- nvim_set)
- screen = thelpers.screen_setup(0, cmd)
+ screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ nvim_set .. ' notermguicolors',
+ extra_args,
+ }, {
+ env = {
+ LANG = 'C',
+ },
+ })
end
it('-V3log logs terminfo values', function()
- nvim_tui('-V3'..logfile)
+ nvim_tui('-V3' .. logfile)
-- Wait for TUI to start.
feed_data('Gitext')
screen:expect([[
text{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*4
{3:-- INSERT --} |
{3:-- TERMINAL --} |
]])
- retry(nil, 3000, function() -- Wait for log file to be flushed.
+ retry(nil, 3000, function() -- Wait for log file to be flushed.
local log = read_file('Xtest_tui_verbose_log') or ''
eq('--- Terminal info --- {{{\n', string.match(log, '%-%-%- Terminal.-\n')) -- }}}
ok(#log > 50)
end)
end)
-end)
-
--- See test/unit/tui_spec.lua for unit tests.
-describe('TUI bg color', function()
- local screen
-
- local function setup_bg_test()
- clear()
- screen = thelpers.screen_setup(0, '["'..nvim_prog
- ..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile", '
- ..'"-c", "autocmd OptionSet background echo \\"did OptionSet, yay!\\""]')
- end
-
- before_each(setup_bg_test)
+ it('does not crash on large inputs #26099', function()
+ nvim_tui()
- it('triggers OptionSet event on unsplit terminal-response', function()
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
+ {4:~ }|*4
|
{3:-- TERMINAL --} |
]])
- feed_data('\027]11;rgb:ffff/ffff/ffff\027\\')
- screen:expect{any='did OptionSet, yay!'}
- feed_data(':echo "new_bg=".&background\n')
- screen:expect{any='new_bg=light'}
+ feed_data(string.format('\027]52;c;%s\027\\', string.rep('A', 8192)))
- setup_bg_test()
- screen:expect([[
+ screen:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
+ {4:~ }|*4
|
{3:-- TERMINAL --} |
+ ]],
+ unchanged = true,
+ }
+ end)
+
+ it('queries the terminal for truecolor support', function()
+ clear()
+ exec_lua([[
+ vim.api.nvim_create_autocmd('TermRequest', {
+ callback = function(args)
+ local req = args.data
+ local payload = req:match('^\027P%+q([%x;]+)$')
+ if payload then
+ local t = {}
+ for cap in vim.gsplit(payload, ';') do
+ local resp = string.format('\027P1+r%s\027\\', payload)
+ vim.api.nvim_chan_send(vim.bo[args.buf].channel, resp)
+ t[vim.text.hexdecode(cap)] = true
+ end
+ vim.g.xtgettcap = t
+ return true
+ end
+ end,
+ })
]])
- feed_data('\027]11;rgba:ffff/ffff/ffff/8000\027\\')
- screen:expect{any='did OptionSet, yay!'}
- feed_data(':echo "new_bg=".&background\n')
- screen:expect{any='new_bg=light'}
+ local child_server = new_pipename()
+ screen = thelpers.setup_child_nvim({
+ '--listen',
+ child_server,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ }, {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+
+ -- Force COLORTERM to be unset and use a TERM that does not contain Tc or RGB in terminfo.
+ -- This will force the nested nvim instance to query with XTGETTCAP
+ COLORTERM = '',
+ TERM = 'xterm-256colors',
+ },
+ })
+
+ screen:expect({ any = '%[No Name%]' })
+
+ local child_session = helpers.connect(child_server)
+ retry(nil, 1000, function()
+ eq({
+ Tc = true,
+ RGB = true,
+ setrgbf = true,
+ setrgbb = true,
+ }, eval("get(g:, 'xtgettcap', '')"))
+ eq({ true, 1 }, { child_session:request('nvim_eval', '&termguicolors') })
+ end)
end)
- it('triggers OptionSet event with split terminal-response', function()
- screen:expect([[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
- |
- {3:-- TERMINAL --} |
+ it('queries the terminal for OSC 52 support', function()
+ clear()
+ exec_lua([[
+ vim.api.nvim_create_autocmd('TermRequest', {
+ callback = function(args)
+ local req = args.data
+ local payload = req:match('^\027P%+q([%x;]+)$')
+ if payload and vim.text.hexdecode(payload) == 'Ms' then
+ vim.g.xtgettcap = 'Ms'
+ local resp = string.format('\027P1+r%s=%s\027\\', payload, vim.text.hexencode('\027]52;;\027\\'))
+ vim.api.nvim_chan_send(vim.bo[args.buf].channel, resp)
+ return true
+ end
+ end,
+ })
]])
- -- Send a background response with the OSC command part split.
- feed_data('\027]11;rgb')
- feed_data(':ffff/ffff/ffff\027\\')
- screen:expect{any='did OptionSet, yay!'}
- feed_data(':echo "new_bg=".&background\n')
- screen:expect{any='new_bg=light'}
+ local child_server = new_pipename()
+ screen = thelpers.setup_child_nvim({
+ '--listen',
+ child_server,
+ -- Use --clean instead of -u NONE to load the osc52 plugin
+ '--clean',
+ }, {
+ env = {
+ VIMRUNTIME = os.getenv('VIMRUNTIME'),
+
+ -- Only queries when SSH_TTY is set
+ SSH_TTY = '/dev/pts/1',
+ },
+ })
- setup_bg_test()
- screen:expect([[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
- |
- {3:-- TERMINAL --} |
- ]])
- -- Send a background response with the Pt portion split.
- feed_data('\027]11;rgba:ffff/fff')
- feed_data('f/ffff/8000\027\\')
- screen:expect{any='did OptionSet, yay!'}
+ screen:expect({ any = '%[No Name%]' })
- feed_data(':echo "new_bg=".&background\n')
- screen:expect{any='new_bg=light'}
+ local child_session = helpers.connect(child_server)
+ retry(nil, 1000, function()
+ eq('Ms', eval("get(g:, 'xtgettcap', '')"))
+ eq({ true, 'OSC 52' }, { child_session:request('nvim_eval', 'g:clipboard.name') })
+ end)
end)
+end)
- it('not triggers OptionSet event with invalid terminal-response', function()
- screen:expect([[
- {1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {5:[No Name] 0,0-1 All}|
- |
- {3:-- TERMINAL --} |
- ]])
- feed_data('\027]11;rgb:ffff/ffff/ffff/8000\027\\')
- screen:expect_unchanged()
+describe('TUI bg color', function()
+ before_each(clear)
+
+ it('is properly set in a nested Nvim instance when background=dark', function()
+ command('highlight clear Normal')
+ command('set background=dark') -- set outer Nvim background
+ local child_server = new_pipename()
+ local screen = thelpers.setup_child_nvim({
+ '--listen',
+ child_server,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ 'set noswapfile',
+ })
+ screen:expect({ any = '%[No Name%]' })
+ local child_session = helpers.connect(child_server)
+ retry(nil, nil, function()
+ eq({ true, 'dark' }, { child_session:request('nvim_eval', '&background') })
+ end)
+ end)
- feed_data(':echo "new_bg=".&background\n')
- screen:expect{any='new_bg=dark'}
+ it('is properly set in a nested Nvim instance when background=light', function()
+ command('highlight clear Normal')
+ command('set background=light') -- set outer Nvim background
+ local child_server = new_pipename()
+ local screen = thelpers.setup_child_nvim({
+ '--listen',
+ child_server,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ 'set noswapfile',
+ })
+ screen:expect({ any = '%[No Name%]' })
+ local child_session = helpers.connect(child_server)
+ retry(nil, nil, function()
+ eq({ true, 'light' }, { child_session:request('nvim_eval', '&background') })
+ end)
+ end)
+
+ it('queries the terminal for background color', function()
+ exec_lua([[
+ vim.api.nvim_create_autocmd('TermRequest', {
+ callback = function(args)
+ local req = args.data
+ if req == '\027]11;?' then
+ vim.g.oscrequest = true
+ return true
+ end
+ end,
+ })
+ ]])
+ thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ 'set noswapfile',
+ })
+ retry(nil, 1000, function()
+ eq(true, eval("get(g:, 'oscrequest', v:false)"))
+ end)
+ end)
- setup_bg_test()
+ it('triggers OptionSet from automatic background processing', function()
+ local screen = thelpers.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ 'set noswapfile',
+ '-c',
+ 'autocmd OptionSet background echo "did OptionSet, yay!"',
+ })
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {3:~} |*3
{5:[No Name] 0,0-1 All}|
- |
+ did OptionSet, yay! |
{3:-- TERMINAL --} |
]])
- feed_data('\027]11;rgba:ffff/foo/ffff/8000\027\\')
- screen:expect_unchanged()
-
- feed_data(':echo "new_bg=".&background\n')
- screen:expect{any='new_bg=dark'}
end)
end)
-- These tests require `thelpers` because --headless/--embed
-- does not initialize the TUI.
-describe("TUI as a client", function()
-
- it("connects to remote instance (with its own TUI)", function()
+describe('TUI as a client', function()
+ it('connects to remote instance (with its own TUI)', function()
local server_super = spawn_argv(false) -- equivalent to clear()
local client_super = spawn_argv(true)
set_session(server_super)
local server_pipe = new_pipename()
- local screen_server = thelpers.screen_setup(0,
- string.format([=[["%s", "--listen", "%s", "-u", "NONE", "-i", "NONE", "--cmd", "%s laststatus=2 background=dark"]]=],
- nvim_prog, server_pipe, nvim_set))
+ local screen_server = thelpers.setup_child_nvim({
+ '--listen',
+ server_pipe,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ nvim_set .. ' notermguicolors laststatus=2 background=dark',
+ })
- feed_data("iHello, World")
- screen_server:expect{grid=[[
+ feed_data('iHello, World')
+ screen_server:expect {
+ grid = [[
Hello, World{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
- ]]}
- feed_data("\027")
- screen_server:expect{grid=[[
+ ]],
+ }
+ feed_data('\027')
+ screen_server:expect {
+ grid = [[
Hello, Worl{1:d} |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
set_session(client_super)
- local screen_client = thelpers.screen_setup(0,
- string.format([=[["%s", "--server", "%s", "--remote-ui"]]=],
- nvim_prog, server_pipe))
+ local screen_client = thelpers.setup_child_nvim({
+ '--server',
+ server_pipe,
+ '--remote-ui',
+ })
- screen_client:expect{grid=[[
+ screen_client:expect {
+ grid = [[
Hello, Worl{1:d} |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
-- grid smaller than containing terminal window is cleared properly
feed_data(":call setline(1,['a'->repeat(&columns)]->repeat(&lines))\n")
- feed_data("0:set lines=3\n")
- screen_server:expect{grid=[[
+ feed_data('0:set lines=3\n')
+ screen_server:expect {
+ grid = [[
{1:a}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{5:[No Name] [+] }|
- |
- |
- |
- |
+ |*4
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
- feed_data(":q!\n")
+ feed_data(':q!\n')
server_super:close()
client_super:close()
end)
- it("connects to remote instance (--headless)", function()
+ it('connects to remote instance (--headless)', function()
local server = spawn_argv(false) -- equivalent to clear()
local client_super = spawn_argv(true)
set_session(server)
- local server_pipe = meths.get_vvar('servername')
+ local server_pipe = api.nvim_get_vvar('servername')
server:request('nvim_input', 'iHalloj!<Esc>')
+ server:request('nvim_command', 'set notermguicolors')
set_session(client_super)
- local screen_client = thelpers.screen_setup(0,
- string.format([=[["%s", "--server", "%s", "--remote-ui"]]=],
- nvim_prog, server_pipe))
+ local screen_client = thelpers.setup_child_nvim({
+ '--server',
+ server_pipe,
+ '--remote-ui',
+ })
- screen_client:expect{grid=[[
+ screen_client:expect {
+ grid = [[
Halloj{1:!} |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*4
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
-- No heap-use-after-free when receiving UI events after deadly signal #22184
server:request('nvim_input', ('a'):rep(1000))
exec_lua([[vim.uv.kill(vim.fn.jobpid(vim.bo.channel), 'sigterm')]])
- screen_client:expect{grid=[[
+ screen_client:expect {
+ grid = [[
Vim: Caught deadly signal 'SIGTERM' |
- |
- |
+ |*2
[Process exited 1]{1: } |
- |
- |
+ |*2
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
- eq(0, meths.get_vvar('shell_error'))
+ eq(0, api.nvim_get_vvar('shell_error'))
-- exits on input eof #22244
- funcs.system({nvim_prog, '--server', server_pipe, '--remote-ui'})
- eq(1, meths.get_vvar('shell_error'))
+ fn.system({ nvim_prog, '--server', server_pipe, '--remote-ui' })
+ eq(1, api.nvim_get_vvar('shell_error'))
client_super:close()
server:close()
end)
- it("throws error when no server exists", function()
+ it('throws error when no server exists', function()
clear()
- local screen = thelpers.screen_setup(0,
- string.format([=[["%s", "--server", "127.0.0.1:2436546", "--remote-ui"]]=],
- nvim_prog), 60)
+ local screen = thelpers.setup_child_nvim({
+ '--server',
+ '127.0.0.1:2436546',
+ '--remote-ui',
+ }, { cols = 60 })
screen:expect([[
Remote ui failed to start: {MATCH:.*}|
|
[Process exited 1]{1: } |
- |
- |
- |
+ |*3
{3:-- TERMINAL --} |
]])
end)
@@ -2813,89 +3116,98 @@ describe("TUI as a client", function()
set_session(server_super)
local server_pipe = new_pipename()
- local screen_server = thelpers.screen_setup(0,
- string.format([=[["%s", "--listen", "%s", "-u", "NONE", "-i", "NONE", "--cmd", "%s laststatus=2 background=dark"]]=],
- nvim_prog, server_pipe, nvim_set))
- screen_server:expect{grid=[[
+ local screen_server = thelpers.setup_child_nvim({
+ '--listen',
+ server_pipe,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ nvim_set .. ' notermguicolors laststatus=2 background=dark',
+ })
+ screen_server:expect {
+ grid = [[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
- feed_data("iHello, World")
- screen_server:expect{grid=[[
+ feed_data('iHello, World')
+ screen_server:expect {
+ grid = [[
Hello, World{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
{3:-- INSERT --} |
{3:-- TERMINAL --} |
- ]]}
- feed_data("\027")
- screen_server:expect{grid=[[
+ ]],
+ }
+ feed_data('\027')
+ screen_server:expect {
+ grid = [[
Hello, Worl{1:d} |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
set_session(client_super)
- local screen_client = thelpers.screen_setup(0,
- string.format([=[["%s", "--server", "%s", "--remote-ui"]]=],
- nvim_prog, server_pipe))
+ local screen_client = thelpers.setup_child_nvim({
+ '--server',
+ server_pipe,
+ '--remote-ui',
+ })
- screen_client:expect{grid=[[
+ screen_client:expect {
+ grid = [[
Hello, Worl{1:d} |
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*3
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
-- quitting the server
set_session(server_super)
- feed_data(status and ':' .. status .. 'cquit!\n' or ":quit!\n")
+ feed_data(status and ':' .. status .. 'cquit!\n' or ':quit!\n')
status = status and status or 0
- screen_server:expect{grid=[[
+ screen_server:expect {
+ grid = [[
|
[Process exited ]] .. status .. [[]{1: }{MATCH:%s+}|
- |
- |
- |
- |
+ |*4
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
-- assert that client has exited
- screen_client:expect{grid=[[
+ screen_client:expect {
+ grid = [[
|
[Process exited ]] .. status .. [[]{1: }{MATCH:%s+}|
- |
- |
- |
- |
+ |*4
{3:-- TERMINAL --} |
- ]]}
+ ]],
+ }
server_super:close()
client_super:close()
end
- describe("exits when server quits", function()
- it("with :quit", function()
+ describe('exits when server quits', function()
+ it('with :quit', function()
test_remote_tui_quit()
end)
- it("with :cquit", function()
+ it('with :cquit', function()
test_remote_tui_quit(42)
end)
end)
diff --git a/test/functional/terminal/window_spec.lua b/test/functional/terminal/window_spec.lua
index 39fc2c2562..3781933cad 100644
--- a/test/functional/terminal/window_spec.lua
+++ b/test/functional/terminal/window_spec.lua
@@ -22,13 +22,15 @@ describe(':terminal window', function()
skip(is_os('win'))
-- Test has hardcoded assumptions of dimensions.
eq(7, eval('&lines'))
- feed_data('\n\n\n') -- Add blank lines.
+ feed_data('\n\n\n') -- Add blank lines.
-- Terminal/shell contents must exceed the height of this window.
command('topleft 1split')
eq('terminal', eval('&buftype'))
feed([[i<cr>]])
-- Check topline _while_ in terminal-mode.
- retry(nil, nil, function() eq(6, eval('winsaveview()["topline"]')) end)
+ retry(nil, nil, function()
+ eq(6, eval('winsaveview()["topline"]'))
+ end)
end)
describe("with 'number'", function()
@@ -121,11 +123,7 @@ describe(':terminal window', function()
screen:expect([[
tty ready |
{2:^ } |
- |
- |
- |
- |
- |
+ |*5
]])
feed(':set colorcolumn=20<CR>i')
end)
@@ -134,10 +132,7 @@ describe(':terminal window', function()
screen:expect([[
tty ready |
{1: } |
- |
- |
- |
- |
+ |*4
{3:-- TERMINAL --} |
]])
end)
@@ -146,7 +141,7 @@ describe(':terminal window', function()
describe('with fold set', function()
before_each(function()
feed([[<C-\><C-N>:set foldenable foldmethod=manual<CR>i]])
- feed_data({'line1', 'line2', 'line3', 'line4', ''})
+ feed_data({ 'line1', 'line2', 'line3', 'line4', '' })
screen:expect([[
tty ready |
line1 |
@@ -179,54 +174,35 @@ describe(':terminal with multigrid', function()
before_each(function()
clear()
- screen = thelpers.screen_setup(0,nil,50,{ext_multigrid=true})
+ screen = thelpers.screen_setup(0, nil, 50, nil, { ext_multigrid = true })
end)
it('resizes to requested size', function()
screen:expect([[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*6
[3:--------------------------------------------------]|
## grid 2
tty ready |
{1: } |
- |
- |
- |
- |
+ |*4
## grid 3
{3:-- TERMINAL --} |
]])
screen:try_resize_grid(2, 20, 10)
if is_os('win') then
- screen:expect{any="rows: 10, cols: 20"}
+ screen:expect { any = 'rows: 10, cols: 20' }
else
screen:expect([[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*6
[3:--------------------------------------------------]|
## grid 2
tty ready |
rows: 10, cols: 20 |
{1: } |
- |
- |
- |
- |
- |
- |
- |
+ |*7
## grid 3
{3:-- TERMINAL --} |
]])
@@ -234,16 +210,11 @@ describe(':terminal with multigrid', function()
screen:try_resize_grid(2, 70, 3)
if is_os('win') then
- screen:expect{any="rows: 3, cols: 70"}
+ screen:expect { any = 'rows: 3, cols: 70' }
else
screen:expect([[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*6
[3:--------------------------------------------------]|
## grid 2
rows: 10, cols: 20 |
@@ -256,16 +227,11 @@ describe(':terminal with multigrid', function()
screen:try_resize_grid(2, 0, 0)
if is_os('win') then
- screen:expect{any="rows: 6, cols: 50"}
+ screen:expect { any = 'rows: 6, cols: 50' }
else
screen:expect([[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*6
[3:--------------------------------------------------]|
## grid 2
tty ready |
diff --git a/test/functional/terminal/window_split_tab_spec.lua b/test/functional/terminal/window_split_tab_spec.lua
index da14531fa2..17411e2724 100644
--- a/test/functional/terminal/window_split_tab_spec.lua
+++ b/test/functional/terminal/window_split_tab_spec.lua
@@ -7,8 +7,8 @@ local feed_command = helpers.feed_command
local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
-local meths = helpers.meths
-local sleep = helpers.sleep
+local api = helpers.api
+local sleep = vim.uv.sleep
local retry = helpers.retry
local is_os = helpers.is_os
@@ -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_value('statusline', '==========', {})
+ api.nvim_set_option_value('statusline', '==========', {})
command('highlight StatusLine cterm=NONE')
command('highlight StatusLineNC cterm=NONE')
command('highlight VertSplit cterm=NONE')
@@ -35,7 +35,7 @@ describe(':terminal', function()
command('terminal')
command('vsplit foo')
eq(3, eval("winnr('$')"))
- feed('ZQ') -- Close split, should not crash. #7538
+ feed('ZQ') -- Close split, should not crash. #7538
assert_alive()
end)
@@ -50,8 +50,7 @@ describe(':terminal', function()
tty ready |
rows: 5, cols: 50 |
{2: } |
- |
- |
+ |*2
========== |
:2split |
]])
@@ -63,31 +62,23 @@ describe(':terminal', function()
^tty ready |
rows: 5, cols: 50 |
{2: } |
- |
- |
+ |*2
========== |
:wincmd p |
]])
end)
it('does not change size if updated when not visible in any window #19665', function()
- local channel = meths.get_option_value('channel', {})
+ local channel = api.nvim_get_option_value('channel', {})
command('enew')
sleep(100)
- meths.chan_send(channel, 'foo')
+ api.nvim_chan_send(channel, 'foo')
sleep(100)
command('bprevious')
screen:expect([[
tty ready |
^foo{2: } |
- |
- |
- |
- |
- |
- |
- |
- |
+ |*8
]])
end)
@@ -100,9 +91,9 @@ describe(':terminal', function()
-- win: SIGWINCH is unreliable, use a weaker test. #7506
retry(3, 30000, function()
screen:try_resize(w1, h1)
- screen:expect{any='rows: 7, cols: 47'}
+ screen:expect { any = 'rows: 7, cols: 47' }
screen:try_resize(w2, h2)
- screen:expect{any='rows: 4, cols: 41'}
+ screen:expect { any = 'rows: 4, cols: 41' }
end)
return
end
@@ -112,9 +103,7 @@ describe(':terminal', function()
tty ready |
rows: 7, cols: 47 |
{2: } |
- |
- |
- |
+ |*3
^ |
|
]])
@@ -133,8 +122,7 @@ describe(':terminal', function()
command('split')
command('terminal')
feed('a<Cmd>wincmd j<CR>')
- eq(2, eval("winnr()"))
+ eq(2, eval('winnr()'))
eq('t', eval('mode(1)'))
end)
-
end)
diff --git a/test/functional/treesitter/fold_spec.lua b/test/functional/treesitter/fold_spec.lua
index a8abbc002b..9428432f66 100644
--- a/test/functional/treesitter/fold_spec.lua
+++ b/test/functional/treesitter/fold_spec.lua
@@ -5,6 +5,7 @@ local insert = helpers.insert
local exec_lua = helpers.exec_lua
local command = helpers.command
local feed = helpers.feed
+local poke_eventloop = helpers.poke_eventloop
local Screen = require('test.functional.ui.screen')
before_each(clear)
@@ -12,6 +13,11 @@ before_each(clear)
describe('treesitter foldexpr', function()
clear()
+ before_each(function()
+ -- open folds to avoid deleting entire folded region
+ exec_lua([[vim.opt.foldlevel = 9]])
+ end)
+
local test_text = [[
void ui_refresh(void)
{
@@ -33,6 +39,12 @@ void ui_refresh(void)
}
}]]
+ local function parse(lang)
+ exec_lua(
+ ([[vim.treesitter.get_parser(0, %s):parse()]]):format(lang and '"' .. lang .. '"' or 'nil')
+ )
+ end
+
local function get_fold_levels()
return exec_lua([[
local res = {}
@@ -43,10 +55,10 @@ void ui_refresh(void)
]])
end
- it("can compute fold levels", function()
+ it('can compute fold levels', function()
insert(test_text)
- exec_lua([[vim.treesitter.get_parser(0, "c")]])
+ parse('c')
eq({
[1] = '>1',
@@ -67,16 +79,17 @@ void ui_refresh(void)
[16] = '3',
[17] = '3',
[18] = '2',
- [19] = '1' }, get_fold_levels())
-
+ [19] = '1',
+ }, get_fold_levels())
end)
- it("recomputes fold levels after lines are added/removed", function()
+ it('recomputes fold levels after lines are added/removed', function()
insert(test_text)
- exec_lua([[vim.treesitter.get_parser(0, "c")]])
+ parse('c')
command('1,2d')
+ poke_eventloop()
eq({
[1] = '0',
@@ -95,9 +108,11 @@ void ui_refresh(void)
[14] = '2',
[15] = '2',
[16] = '1',
- [17] = '0' }, get_fold_levels())
+ [17] = '0',
+ }, get_fold_levels())
command('1put!')
+ poke_eventloop()
eq({
[1] = '>1',
@@ -118,26 +133,295 @@ void ui_refresh(void)
[16] = '3',
[17] = '3',
[18] = '2',
- [19] = '1' }, get_fold_levels())
+ [19] = '1',
+ }, get_fold_levels())
+ end)
+
+ it('handles changes close to start/end of folds', function()
+ insert([[
+# h1
+t1
+# h2
+t2]])
+
+ exec_lua([[vim.treesitter.query.set('markdown', 'folds', '(section) @fold')]])
+ parse('markdown')
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>1',
+ [4] = '1',
+ }, get_fold_levels())
+
+ feed('2ggo<Esc>')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ [4] = '>1',
+ [5] = '1',
+ }, get_fold_levels())
+
+ feed('dd')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>1',
+ [4] = '1',
+ }, get_fold_levels())
+
+ feed('2ggdd')
+ poke_eventloop()
+
+ eq({
+ [1] = '0',
+ [2] = '>1',
+ [3] = '1',
+ }, get_fold_levels())
+
+ feed('u')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>1',
+ [4] = '1',
+ }, get_fold_levels())
+
+ feed('3ggdd')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ }, get_fold_levels())
+
+ feed('u')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>1',
+ [4] = '1',
+ }, get_fold_levels())
+
+ feed('3ggI#<Esc>')
+ parse()
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>2',
+ [4] = '2',
+ }, get_fold_levels())
+
+ feed('x')
+ parse()
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>1',
+ [4] = '1',
+ }, get_fold_levels())
end)
- it("updates folds in all windows", function()
+ it('handles changes that trigger multiple on_bytes', function()
+ insert([[
+function f()
+ asdf()
+ asdf()
+end
+-- comment]])
+
+ exec_lua(
+ [[vim.treesitter.query.set('lua', 'folds', '[(function_declaration) (parameters) (arguments)] @fold')]]
+ )
+ parse('lua')
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ [4] = '1',
+ [5] = '0',
+ }, get_fold_levels())
+
+ command('1,4join')
+ poke_eventloop()
+
+ eq({
+ [1] = '0',
+ [2] = '0',
+ }, get_fold_levels())
+
+ feed('u')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ [4] = '1',
+ [5] = '0',
+ }, get_fold_levels())
+ end)
+
+ it('handles multiple folds that overlap at the end and start', function()
+ insert([[
+function f()
+ g(
+ function()
+ asdf()
+ end, function()
+ end
+ )
+end]])
+
+ exec_lua(
+ [[vim.treesitter.query.set('lua', 'folds', '[(function_declaration) (function_definition) (parameters) (arguments)] @fold')]]
+ )
+ parse('lua')
+
+ -- If fold1.stop = fold2.start, then move fold1's stop up so that fold2.start gets proper level.
+ eq({
+ [1] = '>1',
+ [2] = '>2',
+ [3] = '>3',
+ [4] = '3',
+ [5] = '>3',
+ [6] = '3',
+ [7] = '2',
+ [8] = '1',
+ }, get_fold_levels())
+
+ command('1,8join')
+ feed('u')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '>2',
+ [3] = '>3',
+ [4] = '3',
+ [5] = '>3',
+ [6] = '3',
+ [7] = '2',
+ [8] = '1',
+ }, get_fold_levels())
+ end)
+
+ it('handles multiple folds that start at the same line', function()
+ insert([[
+function f(a)
+ if #(g({
+ k = v,
+ })) > 0 then
+ return
+ end
+end]])
+
+ exec_lua(
+ [[vim.treesitter.query.set('lua', 'folds', '[(if_statement) (function_declaration) (parameters) (arguments) (table_constructor)] @fold')]]
+ )
+ parse('lua')
+
+ eq({
+ [1] = '>1',
+ [2] = '>3',
+ [3] = '3',
+ [4] = '3',
+ [5] = '2',
+ [6] = '2',
+ [7] = '1',
+ }, get_fold_levels())
+
+ command('2,6join')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ }, get_fold_levels())
+
+ feed('u')
+ poke_eventloop()
+
+ eq({
+ [1] = '>1',
+ [2] = '>3',
+ [3] = '3',
+ [4] = '3',
+ [5] = '2',
+ [6] = '2',
+ [7] = '1',
+ }, get_fold_levels())
+ end)
+
+ it('takes account of relevant options', function()
+ insert([[
+# h1
+t1
+## h2
+t2
+### h3
+t3]])
+
+ exec_lua([[vim.treesitter.query.set('markdown', 'folds', '(section) @fold')]])
+ parse('markdown')
+
+ command([[set foldminlines=2]])
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '>2',
+ [4] = '2',
+ [5] = '2',
+ [6] = '2',
+ }, get_fold_levels())
+
+ command([[set foldminlines=1 foldnestmax=1]])
+
+ eq({
+ [1] = '>1',
+ [2] = '1',
+ [3] = '1',
+ [4] = '1',
+ [5] = '1',
+ [6] = '1',
+ }, get_fold_levels())
+ end)
+
+ it('updates folds in all windows', function()
local screen = Screen.new(60, 48)
screen:attach()
screen:set_default_attr_ids({
- [1] = {background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue};
- [2] = {bold = true, foreground = Screen.colors.Blue1};
- [3] = {bold = true, reverse = true};
- [4] = {reverse = true};
+ [1] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue },
+ [2] = { bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { bold = true, reverse = true },
+ [4] = { reverse = true },
})
- exec_lua([[vim.treesitter.get_parser(0, "c")]])
- command([[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=9]])
+ parse('c')
+ command([[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1]])
command('split')
insert(test_text)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:-}void ui_refresh(void) |
{1:│}{ |
{1:│} int width = INT_MAX, height = INT_MAX; |
@@ -157,10 +441,7 @@ void ui_refresh(void)
{1:3} } |
{1:2} } |
{1:│}^} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*4
{3:[No Name] [+] }|
{1:-}void ui_refresh(void) |
{1:│}{ |
@@ -181,16 +462,16 @@ void ui_refresh(void)
{1:3} } |
{1:2} } |
{1:│}} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
{4:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
command('1,2d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: } ^int width = INT_MAX, height = INT_MAX; |
{1: } bool ext_widgets[kUIExtCount]; |
{1:-} for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
@@ -208,12 +489,7 @@ void ui_refresh(void)
{1:2} } |
{1:│} } |
{1: }} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*6
{3:[No Name] [+] }|
{1: } int width = INT_MAX, height = INT_MAX; |
{1: } bool ext_widgets[kUIExtCount]; |
@@ -232,19 +508,16 @@ void ui_refresh(void)
{1:2} } |
{1:│} } |
{1: }} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*5
{4:[No Name] [+] }|
|
- ]]}
-
+ ]],
+ }
feed([[O<C-u><C-r>"<BS><Esc>]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:-}void ui_refresh(void) |
{1:│}^{ |
{1:│} int width = INT_MAX, height = INT_MAX; |
@@ -264,10 +537,7 @@ void ui_refresh(void)
{1:3} } |
{1:2} } |
{1:│}} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*4
{3:[No Name] [+] }|
{1:-}void ui_refresh(void) |
{1:│}{ |
@@ -288,21 +558,21 @@ void ui_refresh(void)
{1:3} } |
{1:2} } |
{1:│}} |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
{4:[No Name] [+] }|
|
- ]]}
-
+ ]],
+ }
end)
it("doesn't open folds in diff mode", function()
local screen = Screen.new(60, 36)
screen:attach()
- exec_lua([[vim.treesitter.get_parser(0, "c")]])
- command([[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=9]])
+ parse('c')
+ command(
+ [[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=9]]
+ )
insert(test_text)
command('16d')
@@ -312,7 +582,8 @@ void ui_refresh(void)
command('windo diffthis')
feed('do')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:+ }{2:+-- 9 lines: void ui_refresh(void)·······················}|
{1: } for (size_t i = 0; i < ui_count; i++) { |
{1: } UI *ui = uis[i]; |
@@ -324,12 +595,7 @@ void ui_refresh(void)
{1: } } |
{1: } } |
{1: }} |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*6
{4:[No Name] [+] }|
{1:+ }{2:+-- 9 lines: void ui_refresh(void)·······················}|
{1: } for (size_t i = 0; i < ui_count; i++) { |
@@ -342,133 +608,70 @@ void ui_refresh(void)
{1: } ^} |
{1: } } |
{1: }} |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*5
{5:[No Name] [+] }|
|
- ]], attr_ids={
- [1] = {background = Screen.colors.Grey, foreground = Screen.colors.Blue4};
- [2] = {background = Screen.colors.LightGrey, foreground = Screen.colors.Blue4};
- [3] = {foreground = Screen.colors.Blue, bold = true};
- [4] = {reverse = true};
- [5] = {reverse = true, bold = true};
- }}
- end)
-
-end)
-
-describe('treesitter foldtext', function()
- local test_text = [[
-void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *))
-{
- int width = INT_MAX, height = INT_MAX;
- bool ext_widgets[kUIExtCount];
- for (UIExtension i = 0; (int)i < kUIExtCount; i++) {
- ext_widgets[i] = true;
- }
-
- bool inclusive = ui_override();
- for (size_t i = 0; i < ui_count; i++) {
- UI *ui = uis[i];
- width = MIN(ui->width, width);
- height = MIN(ui->height, height);
- foo = BAR(ui->bazaar, bazaar);
- for (UIExtension j = 0; (int)j < kUIExtCount; j++) {
- ext_widgets[j] &= (ui->ui_ext[j] || inclusive);
+ ]],
+ attr_ids = {
+ [1] = { background = Screen.colors.Grey, foreground = Screen.colors.Blue4 },
+ [2] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Blue4 },
+ [3] = { foreground = Screen.colors.Blue, bold = true },
+ [4] = { reverse = true },
+ [5] = { reverse = true, bold = true },
+ },
}
- }
-}]]
- local screen
+ end)
- before_each(function()
- screen = Screen.new(60, 5)
+ it("doesn't open folds that are not touched", function()
+ local screen = Screen.new(40, 8)
screen:set_default_attr_ids({
- [0] = {foreground = Screen.colors.Blue, bold = true},
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray};
- [2] = {bold = true, background = Screen.colors.LightGray, foreground = Screen.colors.SeaGreen};
- [3] = {foreground = Screen.colors.DarkCyan, background = Screen.colors.LightGray};
- [4] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.LightGray};
- [5] = {bold = true, background = Screen.colors.LightGray, foreground = Screen.colors.Brown};
- [6] = {background = Screen.colors.Red1};
- [7] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Red};
- [8] = {foreground = Screen.colors.Brown, bold = true, background = Screen.colors.Red};
- [9] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.Red};
- [10] = {bold = true};
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray },
+ [2] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray },
+ [3] = { foreground = Screen.colors.Blue1, bold = true },
+ [4] = { bold = true },
})
screen:attach()
- end)
- it('displays highlighted content', function()
- command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext() updatetime=50]])
- insert(test_text)
- exec_lua([[vim.treesitter.get_parser(0, "c")]])
-
- feed('ggVGzf')
- screen:expect{grid=[[
- {2:^void}{1: }{3:qsort}{4:(}{2:void}{1: }{5:*}{3:base}{4:,}{1: }{2:size_t}{1: }{3:nel}{4:,}{1: }{2:size_t}{1: }{3:width}{4:,}{1: }{2:int}{1: }{4:(}{5:*}{3:compa}|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
- ]]}
- end)
-
- it('handles deep nested captures', function()
- command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext() updatetime=50]])
insert([[
-function FoldInfo.new()
- return setmetatable({
- start_counts = {},
- stop_counts = {},
- levels0 = {},
- levels = {},
- }, FoldInfo)
-end]])
- exec_lua([[vim.treesitter.get_parser(0, "lua")]])
-
- feed('ggjVGkzfgg')
- screen:expect{grid=[[
- ^function FoldInfo.new() |
- {1: }{5:return}{1: }{4:setmetatable({}{1:·····································}|
- end |
- {0:~ }|
- |
- ]]}
-
- command('hi! Visual guibg=Red')
- feed('GVgg')
- screen:expect{grid=[[
- ^f{6:unction FoldInfo.new()} |
- {7: }{8:return}{7: }{9:setmetatable({}{7:·····································}|
- {6:end} |
- {0:~ }|
- {10:-- VISUAL LINE --} |
- ]]}
-
- feed('10l<C-V>')
- screen:expect{grid=[[
- {6:function F}^oldInfo.new() |
- {7: }{8:return}{7: }{9:se}{4:tmetatable({}{1:·····································}|
- {6:end} |
- {0:~ }|
- {10:-- VISUAL BLOCK --} |
- ]]}
- end)
-
- it('falls back to default', function()
- command([[set foldmethod=manual foldtext=v:lua.vim.treesitter.foldtext()]])
- insert(test_text)
+# h1
+t1
+# h2
+t2]])
+ exec_lua([[vim.treesitter.query.set('markdown', 'folds', '(section) @fold')]])
+ parse('markdown')
+ command(
+ [[set foldmethod=expr foldexpr=v:lua.vim.treesitter.foldexpr() foldcolumn=1 foldlevel=0]]
+ )
+
+ feed('ggzojo')
+ poke_eventloop()
+
+ screen:expect {
+ grid = [[
+ {1:-}# h1 |
+ {1:│}t1 |
+ {1:│}^ |
+ {1:+}{2:+-- 2 lines: # h2·····················}|
+ {3:~ }|*3
+ {4:-- INSERT --} |
+ ]],
+ }
- feed('ggVGzf')
- screen:expect{grid=[[
- {1:^+-- 19 lines: void qsort(void *base, size_t nel, size_t widt}|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
- ]]}
+ feed('<Esc>u')
+ -- TODO(tomtomjhj): `u` spuriously opens the fold (#26499).
+ feed('zMggzo')
+
+ feed('dd')
+ poke_eventloop()
+
+ screen:expect {
+ grid = [[
+ {1:-}^t1 |
+ {1:-}# h2 |
+ {1:│}t2 |
+ {3:~ }|*4
+ 1 line less; before #2 {MATCH:.*}|
+ ]],
+ }
end)
end)
diff --git a/test/functional/treesitter/highlight_spec.lua b/test/functional/treesitter/highlight_spec.lua
index e037c9e215..2bf230fe69 100644
--- a/test/functional/treesitter/highlight_spec.lua
+++ b/test/functional/treesitter/highlight_spec.lua
@@ -6,7 +6,7 @@ local insert = helpers.insert
local exec_lua = helpers.exec_lua
local feed = helpers.feed
local command = helpers.command
-local meths = helpers.meths
+local api = helpers.api
local eq = helpers.eq
before_each(clear)
@@ -100,17 +100,7 @@ local injection_grid_c = [[
return 42; \ |
} |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
|
]]
@@ -121,17 +111,7 @@ local injection_grid_expected_c = [[
{4:return} {5:42}; \ |
} |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
|
]]
@@ -142,17 +122,17 @@ describe('treesitter highlighting (C)', function()
screen = Screen.new(65, 18)
screen:attach()
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Blue1};
- [2] = {foreground = Screen.colors.Blue1};
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4};
- [4] = {bold = true, foreground = Screen.colors.Brown};
- [5] = {foreground = Screen.colors.Magenta};
- [6] = {foreground = Screen.colors.Red};
- [7] = {bold = true, foreground = Screen.colors.SlateBlue};
- [8] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red};
- [9] = {foreground = Screen.colors.Magenta, background = Screen.colors.Red};
- [10] = {foreground = Screen.colors.Red, background = Screen.colors.Red};
- [11] = {foreground = Screen.colors.Cyan4};
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Blue1 },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [4] = { bold = true, foreground = Screen.colors.Brown },
+ [5] = { foreground = Screen.colors.Magenta },
+ [6] = { foreground = Screen.colors.Red },
+ [7] = { bold = true, foreground = Screen.colors.SlateBlue },
+ [8] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [9] = { foreground = Screen.colors.Magenta, background = Screen.colors.Red },
+ [10] = { foreground = Screen.colors.Red, background = Screen.colors.Red },
+ [11] = { foreground = Screen.colors.Cyan4 },
}
exec_lua([[ hl_query = ... ]], hl_query_c)
@@ -162,7 +142,8 @@ describe('treesitter highlighting (C)', function()
it('is updated with edits', function()
insert(hl_text_c)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
/// Schedule Lua callback on main loop's event queue |
static int nlua_schedule(lua_State *const lstate) |
{ |
@@ -178,17 +159,18 @@ describe('treesitter highlighting (C)', function()
1, (void *)(ptrdiff_t)cb); |
return 0; |
^} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
exec_lua [[
local parser = vim.treesitter.get_parser(0, "c")
local highlighter = vim.treesitter.highlighter
test_hl = highlighter.new(parser, {queries = {c = hl_query}})
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -204,14 +186,15 @@ describe('treesitter highlighting (C)', function()
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
^} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
- feed("5Goc<esc>dd")
+ feed('5Goc<esc>dd')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -227,13 +210,14 @@ describe('treesitter highlighting (C)', function()
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
feed('7Go*/<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -252,10 +236,12 @@ describe('treesitter highlighting (C)', function()
} |
{1:~ }|
|
- ]]}
+ ]],
+ }
feed('3Go/*<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -274,11 +260,13 @@ describe('treesitter highlighting (C)', function()
{4:return} {5:0}; |
{8:}} |
|
- ]]}
+ ]],
+ }
- feed("gg$")
- feed("~")
- screen:expect{grid=[[
+ feed('gg$')
+ feed('~')
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queu^E} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -297,11 +285,12 @@ describe('treesitter highlighting (C)', function()
{4:return} {5:0}; |
{8:}} |
|
- ]]}
-
+ ]],
+ }
- feed("re")
- screen:expect{grid=[[
+ feed('re')
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queu^e} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -320,7 +309,8 @@ describe('treesitter highlighting (C)', function()
{4:return} {5:0}; |
{8:}} |
|
- ]]}
+ ]],
+ }
end)
it('is updated with :sort', function()
@@ -329,7 +319,8 @@ describe('treesitter highlighting (C)', function()
local parser = vim.treesitter.get_parser(0, "c")
test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query}})
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:int} width = {5:INT_MAX}, height = {5:INT_MAX}; |
{3:bool} ext_widgets[kUIExtCount]; |
{4:for} ({3:UIExtension} i = {5:0}; ({3:int})i < kUIExtCount; i++) { |
@@ -348,10 +339,12 @@ describe('treesitter highlighting (C)', function()
} |
^} |
|
- ]]}
+ ]],
+ }
- feed ":sort<cr>"
- screen:expect{grid=[[
+ feed ':sort<cr>'
+ screen:expect {
+ grid = [[
^ |
ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
{3:UI} *ui = uis[i]; |
@@ -366,15 +359,16 @@ describe('treesitter highlighting (C)', function()
{4:for} ({3:UIExtension} i = {5:0}; ({3:int})i < kUIExtCount; i++) { |
{4:for} ({3:size_t} i = {5:0}; i < ui_count; i++) { |
{3:int} width = {5:INT_MAX}, height = {5:INT_MAX}; |
- } |
- } |
+ } |*2
{3:void} ui_refresh({3:void}) |
:sort |
- ]]}
+ ]],
+ }
- feed "u"
+ feed 'u'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:int} width = {5:INT_MAX}, height = {5:INT_MAX}; |
{3:bool} ext_widgets[kUIExtCount]; |
{4:for} ({3:UIExtension} i = {5:0}; ({3:int})i < kUIExtCount; i++) { |
@@ -393,17 +387,19 @@ describe('treesitter highlighting (C)', function()
} |
^} |
19 changes; before #2 {MATCH:.*}|
- ]]}
+ ]],
+ }
end)
- it("supports with custom parser", function()
+ it('supports with custom parser', function()
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.SeaGreen4};
+ [1] = { bold = true, foreground = Screen.colors.SeaGreen4 },
}
insert(test_text_c)
- screen:expect{ grid= [[
+ screen:expect {
+ grid = [[
int width = INT_MAX, height = INT_MAX; |
bool ext_widgets[kUIExtCount]; |
for (UIExtension i = 0; (int)i < kUIExtCount; i++) { |
@@ -422,7 +418,8 @@ describe('treesitter highlighting (C)', function()
} |
^} |
|
- ]] }
+ ]],
+ }
exec_lua [[
parser = vim.treesitter.get_parser(0, "c")
@@ -438,7 +435,8 @@ describe('treesitter highlighting (C)', function()
local hl = vim.treesitter.highlighter.new(parser, {queries = {c = "(identifier) @type"}})
]]
- screen:expect{ grid = [[
+ screen:expect {
+ grid = [[
int {1:width} = {1:INT_MAX}, {1:height} = {1:INT_MAX}; |
bool {1:ext_widgets}[{1:kUIExtCount}]; |
for (UIExtension {1:i} = 0; (int)i < kUIExtCount; i++) { |
@@ -457,13 +455,14 @@ describe('treesitter highlighting (C)', function()
} |
^} |
|
- ]] }
+ ]],
+ }
end)
- it("supports injected languages", function()
+ it('supports injected languages', function()
insert(injection_text_c)
- screen:expect{grid=injection_grid_c}
+ screen:expect { grid = injection_grid_c }
exec_lua [[
local parser = vim.treesitter.get_parser(0, "c", {
@@ -473,13 +472,13 @@ describe('treesitter highlighting (C)', function()
test_hl = highlighter.new(parser, {queries = {c = hl_query}})
]]
- screen:expect{grid=injection_grid_expected_c}
+ screen:expect { grid = injection_grid_expected_c }
end)
it("supports injecting by ft name in metadata['injection.language']", function()
insert(injection_text_c)
- screen:expect{grid=injection_grid_c}
+ screen:expect { grid = injection_grid_c }
exec_lua [[
vim.treesitter.language.register("c", "foo")
@@ -490,10 +489,10 @@ describe('treesitter highlighting (C)', function()
test_hl = highlighter.new(parser, {queries = {c = hl_query}})
]]
- screen:expect{grid=injection_grid_expected_c}
+ screen:expect { grid = injection_grid_expected_c }
end)
- it("supports overriding queries, like ", function()
+ it('supports overriding queries, like ', function()
insert([[
int x = INT_MAX;
#define READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
@@ -510,29 +509,21 @@ describe('treesitter highlighting (C)', function()
vim.treesitter.highlighter.new(vim.treesitter.get_parser(0, "c"))
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:int} x = {5:INT_MAX}; |
#define {5:READ_STRING}(x, y) ({3:char} *)read_string((x), ({3:size_t})(y)) |
#define foo {3:void} main() { \ |
{4:return} {5:42}; \ |
} |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
|
- ]]}
+ ]],
+ }
end)
- it("supports highlighting with custom highlight groups", function()
+ it('supports highlighting with custom highlight groups', function()
insert(hl_text_c)
exec_lua [[
@@ -540,7 +531,8 @@ describe('treesitter highlighting (C)', function()
test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query}})
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -556,15 +548,16 @@ describe('treesitter highlighting (C)', function()
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
^} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
-- This will change ONLY the literal strings to look like comments
-- The only literal string is the "vim.schedule: expected function" in this test.
exec_lua [[vim.cmd("highlight link @string.nonexistent_specializer comment")]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:/// Schedule Lua callback on main loop's event queue} |
{3:static} {3:int} {11:nlua_schedule}({3:lua_State} *{3:const} lstate) |
{ |
@@ -580,14 +573,14 @@ describe('treesitter highlighting (C)', function()
{5:1}, ({3:void} *)({3:ptrdiff_t})cb); |
{4:return} {5:0}; |
^} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
- screen:expect{ unchanged=true }
+ ]],
+ }
+ screen:expect { unchanged = true }
end)
- it("supports highlighting with priority", function()
+ it('supports highlighting with priority', function()
insert([[
int x = INT_MAX;
#define READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
@@ -601,120 +594,80 @@ describe('treesitter highlighting (C)', function()
test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = hl_query..'\n((translation_unit) @constant (#set! "priority" 101))\n'}})
]]
-- expect everything to have Constant highlight
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{12:int}{8: x = INT_MAX;} |
{8:#define READ_STRING(x, y) (}{12:char}{8: *)read_string((x), (}{12:size_t}{8:)(y))} |
{8:#define foo }{12:void}{8: main() { \} |
{8: }{12:return}{8: 42; \} |
{8: }} |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- |
- ]], attr_ids={
- [1] = {bold = true, foreground = Screen.colors.Blue1};
- [8] = {foreground = Screen.colors.Magenta1};
- -- bold will not be overwritten at the moment
- [12] = {bold = true, foreground = Screen.colors.Magenta1};
- }}
+ {1:~ }|*11
+ |
+ ]],
+ attr_ids = {
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [8] = { foreground = Screen.colors.Magenta1 },
+ -- bold will not be overwritten at the moment
+ [12] = { bold = true, foreground = Screen.colors.Magenta1 },
+ },
+ }
eq({
- {capture='constant', metadata = { priority='101' }, lang='c' };
- {capture='type', metadata = { }, lang='c' };
+ { capture = 'constant', metadata = { priority = '101' }, lang = 'c' },
+ { capture = 'type', metadata = {}, lang = 'c' },
}, exec_lua [[ return vim.treesitter.get_captures_at_pos(0, 0, 2) ]])
- end)
+ end)
- it("allows to use captures with dots (don't use fallback when specialization of foo exists)", function()
- insert([[
+ it(
+ "allows to use captures with dots (don't use fallback when specialization of foo exists)",
+ function()
+ insert([[
char* x = "Will somebody ever read this?";
]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
char* x = "Will somebody ever read this?"; |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*15
|
- ]]}
+ ]],
+ }
- command [[
+ command [[
hi link @foo.bar Type
hi link @foo String
]]
- exec_lua [[
+ exec_lua [[
local parser = vim.treesitter.get_parser(0, "c", {})
local highlighter = vim.treesitter.highlighter
test_hl = highlighter.new(parser, {queries = {c = "(primitive_type) @foo.bar (string_literal) @foo"}})
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:char}* x = {5:"Will somebody ever read this?"}; |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*15
|
- ]]}
+ ]],
+ }
- -- clearing specialization reactivates fallback
- command [[ hi clear @foo.bar ]]
- screen:expect{grid=[[
+ -- clearing specialization reactivates fallback
+ command [[ hi clear @foo.bar ]]
+ screen:expect {
+ grid = [[
{5:char}* x = {5:"Will somebody ever read this?"}; |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*15
|
- ]]}
- end)
+ ]],
+ }
+ end
+ )
- it("supports conceal attribute", function()
+ it('supports conceal attribute', function()
insert(hl_text_c)
-- conceal can be empty or a single cchar.
@@ -723,15 +676,16 @@ describe('treesitter highlighting (C)', function()
local parser = vim.treesitter.get_parser(0, "c")
test_hl = vim.treesitter.highlighter.new(parser, {queries = {c = [[
("static" @keyword
- (set! conceal "R"))
+ (#set! conceal "R"))
((identifier) @Identifier
- (set! conceal "")
- (eq? @Identifier "lstate"))
+ (#set! conceal "")
+ (#eq? @Identifier "lstate"))
]]}})
]=]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
/// Schedule Lua callback on main loop's event queue |
{4:R} int nlua_schedule(lua_State *const ) |
{ |
@@ -747,33 +701,60 @@ describe('treesitter highlighting (C)', function()
1, (void *)(ptrdiff_t)cb); |
return 0; |
^} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
end)
- it("@foo.bar groups has the correct fallback behavior", function()
- local get_hl = function(name) return meths.get_hl_by_name(name,1).foreground end
- meths.set_hl(0, "@foo", {fg = 1})
- meths.set_hl(0, "@foo.bar", {fg = 2})
- meths.set_hl(0, "@foo.bar.baz", {fg = 3})
-
- eq(1, get_hl"@foo")
- eq(1, get_hl"@foo.a.b.c.d")
- eq(2, get_hl"@foo.bar")
- eq(2, get_hl"@foo.bar.a.b.c.d")
- eq(3, get_hl"@foo.bar.baz")
- eq(3, get_hl"@foo.bar.baz.d")
+ it('@foo.bar groups has the correct fallback behavior', function()
+ local get_hl = function(name)
+ return api.nvim_get_hl_by_name(name, 1).foreground
+ end
+ api.nvim_set_hl(0, '@foo', { fg = 1 })
+ api.nvim_set_hl(0, '@foo.bar', { fg = 2 })
+ api.nvim_set_hl(0, '@foo.bar.baz', { fg = 3 })
+
+ eq(1, get_hl '@foo')
+ eq(1, get_hl '@foo.a.b.c.d')
+ eq(2, get_hl '@foo.bar')
+ eq(2, get_hl '@foo.bar.a.b.c.d')
+ eq(3, get_hl '@foo.bar.baz')
+ eq(3, get_hl '@foo.bar.baz.d')
-- lookup is case insensitive
- eq(2, get_hl"@FOO.BAR.SPAM")
+ eq(2, get_hl '@FOO.BAR.SPAM')
+
+ api.nvim_set_hl(0, '@foo.missing.exists', { fg = 3 })
+ eq(1, get_hl '@foo.missing')
+ eq(3, get_hl '@foo.missing.exists')
+ eq(3, get_hl '@foo.missing.exists.bar')
+ eq(nil, get_hl '@total.nonsense.but.a.lot.of.dots')
+ end)
- meths.set_hl(0, "@foo.missing.exists", {fg = 3})
- eq(1, get_hl"@foo.missing")
- eq(3, get_hl"@foo.missing.exists")
- eq(3, get_hl"@foo.missing.exists.bar")
- eq(nil, get_hl"@total.nonsense.but.a.lot.of.dots")
+ it('supports multiple nodes assigned to the same capture #17060', function()
+ insert([[
+ int x = 4;
+ int y = 5;
+ int z = 6;
+ ]])
+
+ exec_lua([[
+ local query = '((declaration)+ @string)'
+ vim.treesitter.query.set('c', 'highlights', query)
+ vim.treesitter.highlighter.new(vim.treesitter.get_parser(0, 'c'))
+ ]])
+
+ screen:expect {
+ grid = [[
+ {5:int x = 4;} |
+ {5:int y = 5;} |
+ {5:int z = 6;} |
+ ^ |
+ {1:~ }|*13
+ |
+ ]],
+ }
end)
end)
@@ -784,16 +765,16 @@ describe('treesitter highlighting (help)', function()
screen = Screen.new(40, 6)
screen:attach()
screen:set_default_attr_ids {
- [1] = {foreground = Screen.colors.Blue1};
- [2] = {bold = true, foreground = Screen.colors.Blue1};
- [3] = {bold = true, foreground = Screen.colors.Brown};
- [4] = {foreground = Screen.colors.Cyan4};
- [5] = {foreground = Screen.colors.Magenta1};
+ [1] = { foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { bold = true, foreground = Screen.colors.Brown },
+ [4] = { foreground = Screen.colors.Cyan4 },
+ [5] = { foreground = Screen.colors.Magenta1 },
}
end)
- it("correctly redraws added/removed injections", function()
- insert[[
+ it('correctly redraws added/removed injections', function()
+ insert [[
>ruby
-- comment
local this_is = 'actually_lua'
@@ -805,38 +786,43 @@ describe('treesitter highlighting (help)', function()
vim.treesitter.start()
]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:>ruby} |
{1: -- comment} |
{1: local this_is = 'actually_lua'} |
- < |
+ {1:<} |
^ |
|
- ]]}
+ ]],
+ }
- helpers.curbufmeths.set_text(0, 1, 0, 5, {'lua'})
+ helpers.api.nvim_buf_set_text(0, 0, 1, 0, 5, { 'lua' })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:>lua} |
{1: -- comment} |
{1: }{3:local}{1: }{4:this_is}{1: }{3:=}{1: }{5:'actually_lua'} |
- < |
+ {1:<} |
^ |
|
- ]]}
+ ]],
+ }
- helpers.curbufmeths.set_text(0, 1, 0, 4, {'ruby'})
+ helpers.api.nvim_buf_set_text(0, 0, 1, 0, 4, { 'ruby' })
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:>ruby} |
{1: -- comment} |
{1: local this_is = 'actually_lua'} |
- < |
+ {1:<} |
^ |
|
- ]]}
+ ]],
+ }
end)
-
end)
describe('treesitter highlighting (nested injections)', function()
@@ -846,15 +832,15 @@ describe('treesitter highlighting (nested injections)', function()
screen = Screen.new(80, 7)
screen:attach()
screen:set_default_attr_ids {
- [1] = {foreground = Screen.colors.SlateBlue};
- [2] = {bold = true, foreground = Screen.colors.Brown};
- [3] = {foreground = Screen.colors.Cyan4};
- [4] = {foreground = Screen.colors.Fuchsia};
+ [1] = { foreground = Screen.colors.SlateBlue },
+ [2] = { bold = true, foreground = Screen.colors.Brown },
+ [3] = { foreground = Screen.colors.Cyan4 },
+ [4] = { foreground = Screen.colors.Fuchsia },
}
end)
- it("correctly redraws nested injections (GitHub #25252)", function()
- insert[=[
+ it('correctly redraws nested injections (GitHub #25252)', function()
+ insert [=[
function foo() print("Lua!") end
local lorem = {
@@ -875,9 +861,10 @@ vim.cmd([[
]]
-- invalidate the language tree
- feed("ggi--[[<ESC>04x")
+ feed('ggi--[[<ESC>04x')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:^function} {3:foo}{1:()} {1:print(}{4:"Lua!"}{1:)} {2:end} |
|
{2:local} {3:lorem} {2:=} {1:{} |
@@ -885,12 +872,14 @@ vim.cmd([[
{3:bar} {2:=} {1:{},} |
{1:}} |
|
- ]]}
+ ]],
+ }
-- spam newline insert/delete to invalidate Lua > Vim > Lua region
- feed("3jo<ESC>ddko<ESC>ddko<ESC>ddko<ESC>ddk0")
+ feed('3jo<ESC>ddko<ESC>ddko<ESC>ddko<ESC>ddk0')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:function} {3:foo}{1:()} {1:print(}{4:"Lua!"}{1:)} {2:end} |
|
{2:local} {3:lorem} {2:=} {1:{} |
@@ -898,7 +887,7 @@ vim.cmd([[
{3:bar} {2:=} {1:{},} |
{1:}} |
|
- ]]}
+ ]],
+ }
end)
-
end)
diff --git a/test/functional/treesitter/inspect_tree_spec.lua b/test/functional/treesitter/inspect_tree_spec.lua
new file mode 100644
index 0000000000..a3d44ff906
--- /dev/null
+++ b/test/functional/treesitter/inspect_tree_spec.lua
@@ -0,0 +1,115 @@
+local helpers = require('test.functional.helpers')(after_each)
+local clear = helpers.clear
+local insert = helpers.insert
+local dedent = helpers.dedent
+local eq = helpers.eq
+local exec_lua = helpers.exec_lua
+local feed = helpers.feed
+
+describe('vim.treesitter.inspect_tree', function()
+ before_each(clear)
+
+ local expect_tree = function(x)
+ local expected = vim.split(vim.trim(dedent(x)), '\n')
+ local actual = helpers.buf_lines(0) ---@type string[]
+ eq(expected, actual)
+ end
+
+ it('working', function()
+ insert([[
+ print()
+ ]])
+
+ exec_lua([[
+ vim.treesitter.start(0, 'lua')
+ vim.treesitter.inspect_tree()
+ ]])
+
+ expect_tree [[
+ (chunk ; [0, 0] - [2, 0]
+ (function_call ; [0, 0] - [0, 7]
+ name: (identifier) ; [0, 0] - [0, 5]
+ arguments: (arguments))) ; [0, 5] - [0, 7]
+ ]]
+ end)
+
+ it('can toggle to show anonymous nodes', function()
+ insert([[
+ print()
+ ]])
+
+ exec_lua([[
+ vim.treesitter.start(0, 'lua')
+ vim.treesitter.inspect_tree()
+ ]])
+ feed('a')
+
+ expect_tree [[
+ (chunk ; [0, 0] - [2, 0]
+ (function_call ; [0, 0] - [0, 7]
+ name: (identifier) ; [0, 0] - [0, 5]
+ arguments: (arguments ; [0, 5] - [0, 7]
+ "(" ; [0, 5] - [0, 6]
+ ")"))) ; [0, 6] - [0, 7]
+ ]]
+ end)
+
+ it('works for injected trees', function()
+ insert([[
+ ```lua
+ return
+ ```
+ ]])
+
+ exec_lua([[
+ vim.treesitter.start(0, 'markdown')
+ vim.treesitter.get_parser():parse()
+ vim.treesitter.inspect_tree()
+ ]])
+
+ expect_tree [[
+ (document ; [0, 0] - [4, 0]
+ (section ; [0, 0] - [4, 0]
+ (fenced_code_block ; [0, 0] - [3, 0]
+ (fenced_code_block_delimiter) ; [0, 0] - [0, 3]
+ (info_string ; [0, 3] - [0, 6]
+ (language)) ; [0, 3] - [0, 6]
+ (block_continuation) ; [1, 0] - [1, 0]
+ (code_fence_content ; [1, 0] - [2, 0]
+ (chunk ; [1, 0] - [2, 0]
+ (return_statement)) ; [1, 0] - [1, 6]
+ (block_continuation)) ; [2, 0] - [2, 0]
+ (fenced_code_block_delimiter)))) ; [2, 0] - [2, 3]
+ ]]
+ end)
+
+ it('can toggle to show languages', function()
+ insert([[
+ ```lua
+ return
+ ```
+ ]])
+
+ exec_lua([[
+ vim.treesitter.start(0, 'markdown')
+ vim.treesitter.get_parser():parse()
+ vim.treesitter.inspect_tree()
+ ]])
+ feed('I')
+
+ expect_tree [[
+ (document ; [0, 0] - [4, 0] markdown
+ (section ; [0, 0] - [4, 0] markdown
+ (fenced_code_block ; [0, 0] - [3, 0] markdown
+ (fenced_code_block_delimiter) ; [0, 0] - [0, 3] markdown
+ (info_string ; [0, 3] - [0, 6] markdown
+ (language)) ; [0, 3] - [0, 6] markdown
+ (block_continuation) ; [1, 0] - [1, 0] markdown
+ (code_fence_content ; [1, 0] - [2, 0] markdown
+ (chunk ; [1, 0] - [2, 0] lua
+ (return_statement)) ; [1, 0] - [1, 6] lua
+ (block_continuation)) ; [2, 0] - [2, 0] markdown
+ (fenced_code_block_delimiter)))) ; [2, 0] - [2, 3] markdown
+ ]]
+ end)
+end)
diff --git a/test/functional/treesitter/language_spec.lua b/test/functional/treesitter/language_spec.lua
index 9b871a72fb..65d9e0e81c 100644
--- a/test/functional/treesitter/language_spec.lua
+++ b/test/functional/treesitter/language_spec.lua
@@ -13,27 +13,43 @@ before_each(clear)
describe('treesitter language API', function()
-- error tests not requiring a parser library
it('handles missing language', function()
- eq(".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
- pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')"))
+ eq(
+ ".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
+ pcall_err(exec_lua, "parser = vim.treesitter.get_parser(0, 'borklang')")
+ )
-- actual message depends on platform
- matches("Failed to load parser for language 'borklang': uv_dlopen: .+",
- pcall_err(exec_lua, "parser = vim.treesitter.language.add('borklang', { path = 'borkbork.so' })"))
+ matches(
+ "Failed to load parser for language 'borklang': uv_dlopen: .+",
+ pcall_err(
+ exec_lua,
+ "parser = vim.treesitter.language.add('borklang', { path = 'borkbork.so' })"
+ )
+ )
eq(false, exec_lua("return pcall(vim.treesitter.language.add, 'borklang')"))
- eq(false, exec_lua("return pcall(vim.treesitter.language.add, 'borklang', { path = 'borkbork.so' })"))
+ eq(
+ false,
+ exec_lua("return pcall(vim.treesitter.language.add, 'borklang', { path = 'borkbork.so' })")
+ )
- eq(".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
- pcall_err(exec_lua, "parser = vim.treesitter.language.inspect('borklang')"))
+ eq(
+ ".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
+ pcall_err(exec_lua, "parser = vim.treesitter.language.inspect('borklang')")
+ )
- matches("Failed to load parser: uv_dlsym: .+",
- pcall_err(exec_lua, 'vim.treesitter.language.add("c", { symbol_name = "borklang" })'))
+ matches(
+ 'Failed to load parser: uv_dlsym: .+',
+ pcall_err(exec_lua, 'vim.treesitter.language.add("c", { symbol_name = "borklang" })')
+ )
end)
it('shows error for invalid language name', function()
- eq(".../language.lua:0: '/foo/' is not a valid language name",
- pcall_err(exec_lua, 'vim.treesitter.language.add("/foo/")'))
+ eq(
+ ".../language.lua:0: '/foo/' is not a valid language name",
+ pcall_err(exec_lua, 'vim.treesitter.language.add("/foo/")')
+ )
end)
it('inspects language', function()
@@ -52,40 +68,45 @@ describe('treesitter language API', function()
return {keys, lang.fields, symbols}
]]))
- eq({fields=true, symbols=true, _abi_version=true}, keys)
+ eq({ fields = true, symbols = true, _abi_version = true }, keys)
local fset = {}
- for _,f in pairs(fields) do
- eq("string", type(f))
+ for _, f in pairs(fields) do
+ eq('string', type(f))
fset[f] = true
end
- eq(true, fset["directive"])
- eq(true, fset["initializer"])
+ eq(true, fset['directive'])
+ eq(true, fset['initializer'])
local has_named, has_anonymous
- for _,s in pairs(symbols) do
- eq("string", type(s[1]))
- eq("boolean", type(s[2]))
- if s[1] == "for_statement" and s[2] == true then
+ for _, s in pairs(symbols) do
+ eq('string', type(s[1]))
+ eq('boolean', type(s[2]))
+ if s[1] == 'for_statement' and s[2] == true then
has_named = true
- elseif s[1] == "|=" and s[2] == false then
+ elseif s[1] == '|=' and s[2] == false then
has_anonymous = true
end
end
- eq({true,true}, {has_named,has_anonymous})
+ eq({ true, true }, { has_named, has_anonymous })
end)
- it('checks if vim.treesitter.get_parser tries to create a new parser on filetype change', function ()
- command("set filetype=c")
- -- Should not throw an error when filetype is c
- eq('c', exec_lua("return vim.treesitter.get_parser(0):lang()"))
- command("set filetype=borklang")
- -- Should throw an error when filetype changes to borklang
- eq(".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
- pcall_err(exec_lua, "new_parser = vim.treesitter.get_parser(0, 'borklang')"))
- end)
+ it(
+ 'checks if vim.treesitter.get_parser tries to create a new parser on filetype change',
+ function()
+ command('set filetype=c')
+ -- Should not throw an error when filetype is c
+ eq('c', exec_lua('return vim.treesitter.get_parser(0):lang()'))
+ command('set filetype=borklang')
+ -- Should throw an error when filetype changes to borklang
+ eq(
+ ".../language.lua:0: no parser for 'borklang' language, see :help treesitter-parsers",
+ pcall_err(exec_lua, "new_parser = vim.treesitter.get_parser(0, 'borklang')")
+ )
+ end
+ )
- it('retrieve the tree given a range', function ()
+ it('retrieve the tree given a range', function()
insert([[
int main() {
int x = 3;
@@ -99,7 +120,7 @@ describe('treesitter language API', function()
eq('<node translation_unit>', exec_lua('return tostring(tree:root())'))
end)
- it('retrieve the node given a range', function ()
+ it('retrieve the node given a range', function()
insert([[
int main() {
int x = 3;
@@ -113,4 +134,3 @@ describe('treesitter language API', function()
eq('<node primitive_type>', exec_lua('return tostring(node)'))
end)
end)
-
diff --git a/test/functional/treesitter/node_spec.lua b/test/functional/treesitter/node_spec.lua
index eef75d0e91..f114d36823 100644
--- a/test/functional/treesitter/node_spec.lua
+++ b/test/functional/treesitter/node_spec.lua
@@ -9,7 +9,7 @@ local assert_alive = helpers.assert_alive
before_each(clear)
local function lua_eval(lua_expr)
- return exec_lua("return " .. lua_expr)
+ return exec_lua('return ' .. lua_expr)
end
describe('treesitter node API', function()
@@ -40,6 +40,20 @@ describe('treesitter node API', function()
assert_alive()
end)
+ it('get_node() with lang given', function()
+ -- this buffer doesn't have filetype set!
+ insert('local foo = function() end')
+ exec_lua([[
+ node = vim.treesitter.get_node({
+ bufnr = 0,
+ pos = { 0, 6 }, -- on "foo"
+ lang = 'lua',
+ })
+ ]])
+ eq('foo', lua_eval('vim.treesitter.get_node_text(node, 0)'))
+ eq('identifier', lua_eval('node:type()'))
+ end)
+
it('can move between siblings', function()
insert([[
int main(int x, int y, int z) {
@@ -48,14 +62,13 @@ describe('treesitter node API', function()
]])
exec_lua([[
- query = require"vim.treesitter.query"
parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1]
root = tree:root()
lang = vim.treesitter.language.inspect('c')
function node_text(node)
- return query.get_node_text(node, 0)
+ return vim.treesitter.get_node_text(node, 0)
end
]])
diff --git a/test/functional/treesitter/parser_spec.lua b/test/functional/treesitter/parser_spec.lua
index 6f386115ae..875b772fec 100644
--- a/test/functional/treesitter/parser_spec.lua
+++ b/test/functional/treesitter/parser_spec.lua
@@ -8,11 +8,13 @@ local exec_lua = helpers.exec_lua
local pcall_err = helpers.pcall_err
local feed = helpers.feed
local is_os = helpers.is_os
+local api = helpers.api
+local fn = helpers.fn
describe('treesitter parser API', function()
before_each(function()
clear()
- exec_lua[[
+ exec_lua [[
vim.g.__ts_debug = 1
]]
end)
@@ -30,59 +32,62 @@ describe('treesitter parser API', function()
lang = vim.treesitter.language.inspect('c')
]])
- eq("<tree>", exec_lua("return tostring(tree)"))
- eq("<node translation_unit>", exec_lua("return tostring(root)"))
- eq({0,0,3,0}, exec_lua("return {root:range()}"))
-
- eq(1, exec_lua("return root:child_count()"))
- exec_lua("child = root:child(0)")
- eq("<node function_definition>", exec_lua("return tostring(child)"))
- eq({0,0,2,1}, exec_lua("return {child:range()}"))
-
- eq("function_definition", exec_lua("return child:type()"))
- eq(true, exec_lua("return child:named()"))
- eq("number", type(exec_lua("return child:symbol()")))
- eq({'function_definition', true}, exec_lua("return lang.symbols[child:symbol()]"))
-
- exec_lua("anon = root:descendant_for_range(0,8,0,9)")
- eq("(", exec_lua("return anon:type()"))
- eq(false, exec_lua("return anon:named()"))
- eq("number", type(exec_lua("return anon:symbol()")))
- eq({'(', false}, exec_lua("return lang.symbols[anon:symbol()]"))
-
- exec_lua("descendant = root:descendant_for_range(1,2,1,12)")
- eq("<node declaration>", exec_lua("return tostring(descendant)"))
- eq({1,2,1,12}, exec_lua("return {descendant:range()}"))
- eq("(declaration type: (primitive_type) declarator: (init_declarator declarator: (identifier) value: (number_literal)))", exec_lua("return descendant:sexpr()"))
-
- feed("2G7|ay")
+ eq('<tree>', exec_lua('return tostring(tree)'))
+ eq('<node translation_unit>', exec_lua('return tostring(root)'))
+ eq({ 0, 0, 3, 0 }, exec_lua('return {root:range()}'))
+
+ eq(1, exec_lua('return root:child_count()'))
+ exec_lua('child = root:child(0)')
+ eq('<node function_definition>', exec_lua('return tostring(child)'))
+ eq({ 0, 0, 2, 1 }, exec_lua('return {child:range()}'))
+
+ eq('function_definition', exec_lua('return child:type()'))
+ eq(true, exec_lua('return child:named()'))
+ eq('number', type(exec_lua('return child:symbol()')))
+ eq({ 'function_definition', true }, exec_lua('return lang.symbols[child:symbol()]'))
+
+ exec_lua('anon = root:descendant_for_range(0,8,0,9)')
+ eq('(', exec_lua('return anon:type()'))
+ eq(false, exec_lua('return anon:named()'))
+ eq('number', type(exec_lua('return anon:symbol()')))
+ eq({ '(', false }, exec_lua('return lang.symbols[anon:symbol()]'))
+
+ exec_lua('descendant = root:descendant_for_range(1,2,1,12)')
+ eq('<node declaration>', exec_lua('return tostring(descendant)'))
+ eq({ 1, 2, 1, 12 }, exec_lua('return {descendant:range()}'))
+ eq(
+ '(declaration type: (primitive_type) declarator: (init_declarator declarator: (identifier) value: (number_literal)))',
+ exec_lua('return descendant:sexpr()')
+ )
+
+ feed('2G7|ay')
exec_lua([[
tree2 = parser:parse()[1]
root2 = tree2:root()
descendant2 = root2:descendant_for_range(1,2,1,13)
]])
- eq(false, exec_lua("return tree2 == tree1"))
- eq(false, exec_lua("return root2 == root"))
- eq("<node declaration>", exec_lua("return tostring(descendant2)"))
- eq({1,2,1,13}, exec_lua("return {descendant2:range()}"))
+ eq(false, exec_lua('return tree2 == tree1'))
+ eq(false, exec_lua('return root2 == root'))
+ eq('<node declaration>', exec_lua('return tostring(descendant2)'))
+ eq({ 1, 2, 1, 13 }, exec_lua('return {descendant2:range()}'))
- eq(true, exec_lua("return child == child"))
+ eq(true, exec_lua('return child == child'))
-- separate lua object, but represents same node
- eq(true, exec_lua("return child == root:child(0)"))
- eq(false, exec_lua("return child == descendant2"))
- eq(false, exec_lua("return child == nil"))
- eq(false, exec_lua("return child == tree"))
+ eq(true, exec_lua('return child == root:child(0)'))
+ eq(false, exec_lua('return child == descendant2'))
+ eq(false, exec_lua('return child == nil'))
+ eq(false, exec_lua('return child == tree'))
- eq("string", exec_lua("return type(child:id())"))
- eq(true, exec_lua("return child:id() == child:id()"))
+ eq('string', exec_lua('return type(child:id())'))
+ eq(true, exec_lua('return child:id() == child:id()'))
-- separate lua object, but represents same node
- eq(true, exec_lua("return child:id() == root:child(0):id()"))
- eq(false, exec_lua("return child:id() == descendant2:id()"))
- eq(false, exec_lua("return child:id() == nil"))
- eq(false, exec_lua("return child:id() == tree"))
+ eq(true, exec_lua('return child:id() == root:child(0):id()'))
+ eq(false, exec_lua('return child:id() == descendant2:id()'))
+ eq(false, exec_lua('return child:id() == nil'))
+ eq(false, exec_lua('return child:id() == tree'))
-- unchanged buffer: return the same tree
- eq(true, exec_lua("return parser:parse()[1] == tree2"))
+ eq(true, exec_lua('return parser:parse()[1] == tree2'))
end)
local test_text = [[
@@ -107,7 +112,7 @@ void ui_refresh(void)
}]]
it('allows to iterate over nodes children', function()
- insert(test_text);
+ insert(test_text)
local res = exec_lua([[
parser = vim.treesitter.get_parser(0, "c")
@@ -122,26 +127,28 @@ void ui_refresh(void)
]])
eq({
- {"primitive_type", "type"},
- {"function_declarator", "declarator"},
- {"compound_statement", "body"}
+ { 'primitive_type', 'type' },
+ { 'function_declarator', 'declarator' },
+ { 'compound_statement', 'body' },
}, res)
end)
it('does not get parser for empty filetype', function()
- insert(test_text);
+ insert(test_text)
- eq('.../treesitter.lua:0: There is no parser available for buffer 1 and one'
- .. ' could not be created because lang could not be determined. Either'
- .. ' pass lang or set the buffer filetype',
- pcall_err(exec_lua, 'vim.treesitter.get_parser(0)'))
+ eq(
+ '.../treesitter.lua:0: There is no parser available for buffer 1 and one'
+ .. ' could not be created because lang could not be determined. Either'
+ .. ' pass lang or set the buffer filetype',
+ pcall_err(exec_lua, 'vim.treesitter.get_parser(0)')
+ )
-- Must provide language for buffers with an empty filetype
exec_lua("vim.treesitter.get_parser(0, 'c')")
end)
it('allows to get a child by field', function()
- insert(test_text);
+ insert(test_text)
local res = exec_lua([[
parser = vim.treesitter.get_parser(0, "c")
@@ -155,7 +162,7 @@ void ui_refresh(void)
return res
]])
- eq({{ "primitive_type", 0, 0, 0, 4 }}, res)
+ eq({ { 'primitive_type', 0, 0, 0, 4 } }, res)
local res_fail = exec_lua([[
parser = vim.treesitter.get_parser(0, "c")
@@ -166,14 +173,14 @@ void ui_refresh(void)
assert(res_fail)
end)
- local query = [[
- ((call_expression function: (identifier) @minfunc (argument_list (identifier) @min_id)) (eq? @minfunc "MIN"))
+ local test_query = [[
+ ((call_expression function: (identifier) @minfunc (argument_list (identifier) @min_id)) (#eq? @minfunc "MIN"))
"for" @keyword
(primitive_type) @type
(field_expression argument: (identifier) @fieldarg)
]]
- it("supports runtime queries", function()
+ it('supports runtime queries', function()
local ret = exec_lua [[
return vim.treesitter.query.get("c", "highlights").captures[1]
]]
@@ -181,10 +188,11 @@ void ui_refresh(void)
eq('variable', ret)
end)
- it("supports caching queries", function()
- local long_query = query:rep(100)
+ it('supports caching queries', function()
+ local long_query = test_query:rep(100)
local function q(n)
- return exec_lua ([[
+ return exec_lua(
+ [[
local query, n = ...
local before = vim.uv.hrtime()
for i=1,n,1 do
@@ -192,7 +200,10 @@ void ui_refresh(void)
end
local after = vim.uv.hrtime()
return after - before
- ]], long_query, n)
+ ]],
+ long_query,
+ n
+ )
end
local firstrun = q(1)
@@ -200,13 +211,17 @@ void ui_refresh(void)
-- First run should be at least 200x slower than an 100 subsequent runs.
local factor = is_os('win') and 100 or 200
- assert(factor * manyruns < firstrun, ('firstrun: %f ms, manyruns: %f ms'):format(firstrun / 1e6, manyruns / 1e6))
+ assert(
+ factor * manyruns < firstrun,
+ ('firstrun: %f ms, manyruns: %f ms'):format(firstrun / 1e6, manyruns / 1e6)
+ )
end)
it('support query and iter by capture', function()
insert(test_text)
- local res = exec_lua([[
+ local res = exec_lua(
+ [[
cquery = vim.treesitter.query.parse("c", ...)
parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1]
@@ -216,50 +231,124 @@ void ui_refresh(void)
table.insert(res, {cquery.captures[cid], node:type(), node:range()})
end
return res
- ]], query)
+ ]],
+ test_query
+ )
eq({
- { "type", "primitive_type", 8, 2, 8, 6 },
- { "keyword", "for", 9, 2, 9, 5 },
- { "type", "primitive_type", 9, 7, 9, 13 },
- { "minfunc", "identifier", 11, 12, 11, 15 },
- { "fieldarg", "identifier", 11, 16, 11, 18 },
- { "min_id", "identifier", 11, 27, 11, 32 },
- { "minfunc", "identifier", 12, 13, 12, 16 },
- { "fieldarg", "identifier", 12, 17, 12, 19 },
- { "min_id", "identifier", 12, 29, 12, 35 },
- { "fieldarg", "identifier", 13, 14, 13, 16 }
+ { 'type', 'primitive_type', 8, 2, 8, 6 },
+ { 'keyword', 'for', 9, 2, 9, 5 },
+ { 'type', 'primitive_type', 9, 7, 9, 13 },
+ { 'minfunc', 'identifier', 11, 12, 11, 15 },
+ { 'fieldarg', 'identifier', 11, 16, 11, 18 },
+ { 'min_id', 'identifier', 11, 27, 11, 32 },
+ { 'minfunc', 'identifier', 12, 13, 12, 16 },
+ { 'fieldarg', 'identifier', 12, 17, 12, 19 },
+ { 'min_id', 'identifier', 12, 29, 12, 35 },
+ { 'fieldarg', 'identifier', 13, 14, 13, 16 },
}, res)
end)
it('support query and iter by match', function()
insert(test_text)
- local res = exec_lua([[
+ local res = exec_lua(
+ [[
cquery = vim.treesitter.query.parse("c", ...)
parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1]
res = {}
- for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14) do
+ for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14, { all = true }) do
-- can't transmit node over RPC. just check the name and range
local mrepr = {}
- for cid,node in pairs(match) do
- table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ for cid, nodes in pairs(match) do
+ for _, node in ipairs(nodes) do
+ table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ end
end
table.insert(res, {pattern, mrepr})
end
return res
- ]], query)
+ ]],
+ test_query
+ )
+
+ eq({
+ { 3, { { 'type', 'primitive_type', 8, 2, 8, 6 } } },
+ { 2, { { 'keyword', 'for', 9, 2, 9, 5 } } },
+ { 3, { { 'type', 'primitive_type', 9, 7, 9, 13 } } },
+ { 4, { { 'fieldarg', 'identifier', 11, 16, 11, 18 } } },
+ {
+ 1,
+ { { 'minfunc', 'identifier', 11, 12, 11, 15 }, { 'min_id', 'identifier', 11, 27, 11, 32 } },
+ },
+ { 4, { { 'fieldarg', 'identifier', 12, 17, 12, 19 } } },
+ {
+ 1,
+ { { 'minfunc', 'identifier', 12, 13, 12, 16 }, { 'min_id', 'identifier', 12, 29, 12, 35 } },
+ },
+ { 4, { { 'fieldarg', 'identifier', 13, 14, 13, 16 } } },
+ }, res)
+ end)
+
+ it('support query and iter by capture for quantifiers', function()
+ insert(test_text)
+
+ local res = exec_lua(
+ [[
+ cquery = vim.treesitter.query.parse("c", ...)
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()[1]
+ res = {}
+ for cid, node in cquery:iter_captures(tree:root(), 0, 7, 14) do
+ -- can't transmit node over RPC. just check the name and range
+ table.insert(res, {cquery.captures[cid], node:type(), node:range()})
+ end
+ return res
+ ]],
+ '(expression_statement (assignment_expression (call_expression)))+ @funccall'
+ )
eq({
- { 3, { { "type", "primitive_type", 8, 2, 8, 6 } } },
- { 2, { { "keyword", "for", 9, 2, 9, 5 } } },
- { 3, { { "type", "primitive_type", 9, 7, 9, 13 } } },
- { 4, { { "fieldarg", "identifier", 11, 16, 11, 18 } } },
- { 1, { { "minfunc", "identifier", 11, 12, 11, 15 }, { "min_id", "identifier", 11, 27, 11, 32 } } },
- { 4, { { "fieldarg", "identifier", 12, 17, 12, 19 } } },
- { 1, { { "minfunc", "identifier", 12, 13, 12, 16 }, { "min_id", "identifier", 12, 29, 12, 35 } } },
- { 4, { { "fieldarg", "identifier", 13, 14, 13, 16 } } }
+ { 'funccall', 'expression_statement', 11, 4, 11, 34 },
+ { 'funccall', 'expression_statement', 12, 4, 12, 37 },
+ { 'funccall', 'expression_statement', 13, 4, 13, 34 },
+ }, res)
+ end)
+
+ it('support query and iter by match for quantifiers', function()
+ insert(test_text)
+
+ local res = exec_lua(
+ [[
+ cquery = vim.treesitter.query.parse("c", ...)
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()[1]
+ res = {}
+ for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14, { all = true }) do
+ -- can't transmit node over RPC. just check the name and range
+ local mrepr = {}
+ for cid, nodes in pairs(match) do
+ for _, node in ipairs(nodes) do
+ table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ end
+ end
+ table.insert(res, {pattern, mrepr})
+ end
+ return res
+ ]],
+ '(expression_statement (assignment_expression (call_expression)))+ @funccall'
+ )
+
+ eq({
+ {
+ 1,
+ {
+ { 'funccall', 'expression_statement', 11, 4, 11, 34 },
+ { 'funccall', 'expression_statement', 12, 4, 12, 37 },
+ { 'funccall', 'expression_statement', 13, 4, 13, 34 },
+ },
+ },
}, res)
end)
@@ -286,7 +375,9 @@ def run
a = <<~E
end]]
insert(text)
- eq('', exec_lua[[
+ eq(
+ '',
+ exec_lua [[
local fake_node = {}
function fake_node:start()
return 3, 0, 23
@@ -301,7 +392,8 @@ end]]
return 3, 0, 3, 0
end
return vim.treesitter.get_node_text(fake_node, 0)
- ]])
+ ]]
+ )
end)
it('support getting empty text if node range is zero width', function()
@@ -338,11 +430,13 @@ end]]
parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1]
res = {}
- for pattern, match in cquery:iter_matches(tree:root(), 0) do
+ for pattern, match in cquery:iter_matches(tree:root(), 0, 0, -1, { all = true }) do
-- can't transmit node over RPC. just check the name and range
local mrepr = {}
- for cid,node in pairs(match) do
- table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ for cid, nodes in pairs(match) do
+ for _, node in ipairs(nodes) do
+ table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ end
end
table.insert(res, {pattern, mrepr})
end
@@ -350,12 +444,12 @@ end]]
]])
eq({
- { 2, { { "times", '*', 0, 4, 0, 5 } } },
- { 5, { { "string", 'string_literal', 0, 16, 0, 20 } } },
- { 4, { { "escape", 'escape_sequence', 0, 17, 0, 19 } } },
- { 3, { { "paren", '(', 0, 22, 0, 23 } } },
- { 1, { { "plus", '+', 0, 25, 0, 26 } } },
- { 2, { { "times", '*', 0, 30, 0, 31 } } },
+ { 2, { { 'times', '*', 0, 4, 0, 5 } } },
+ { 5, { { 'string', 'string_literal', 0, 16, 0, 20 } } },
+ { 4, { { 'escape', 'escape_sequence', 0, 17, 0, 19 } } },
+ { 3, { { 'paren', '(', 0, 22, 0, 23 } } },
+ { 1, { { 'plus', '+', 0, 25, 0, 26 } } },
+ { 2, { { 'times', '*', 0, 30, 0, 31 } } },
}, res)
end)
@@ -394,54 +488,63 @@ end]]
end
]])
- local res0 = exec_lua([[return get_query_result(...)]],
- [[((primitive_type) @c-keyword (#any-of? @c-keyword "int" "float"))]])
+ local res0 = exec_lua(
+ [[return get_query_result(...)]],
+ [[((primitive_type) @c-keyword (#any-of? @c-keyword "int" "float"))]]
+ )
eq({
- { "c-keyword", "primitive_type", { 2, 2, 2, 5 }, "int" },
- { "c-keyword", "primitive_type", { 3, 4, 3, 7 }, "int" },
+ { 'c-keyword', 'primitive_type', { 2, 2, 2, 5 }, 'int' },
+ { 'c-keyword', 'primitive_type', { 3, 4, 3, 7 }, 'int' },
}, res0)
- local res1 = exec_lua([[return get_query_result(...)]],
+ local res1 = exec_lua(
+ [[return get_query_result(...)]],
[[
((string_literal) @fizzbuzz-strings (#any-of? @fizzbuzz-strings
"\"number= %d FizzBuzz\\n\""
"\"number= %d Fizz\\n\""
"\"number= %d Buzz\\n\""
))
- ]])
+ ]]
+ )
eq({
- { "fizzbuzz-strings", "string_literal", { 6, 15, 6, 38 }, "\"number= %d FizzBuzz\\n\""},
- { "fizzbuzz-strings", "string_literal", { 8, 15, 8, 34 }, "\"number= %d Fizz\\n\""},
- { "fizzbuzz-strings", "string_literal", { 10, 15, 10, 34 }, "\"number= %d Buzz\\n\""},
+ { 'fizzbuzz-strings', 'string_literal', { 6, 15, 6, 38 }, '"number= %d FizzBuzz\\n"' },
+ { 'fizzbuzz-strings', 'string_literal', { 8, 15, 8, 34 }, '"number= %d Fizz\\n"' },
+ { 'fizzbuzz-strings', 'string_literal', { 10, 15, 10, 34 }, '"number= %d Buzz\\n"' },
}, res1)
end)
- it('allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`', function()
- insert('char* astring = "Hello World!";')
+ it(
+ 'allow loading query with escaped quotes and capture them with `lua-match?` and `vim-match?`',
+ function()
+ insert('char* astring = "Hello World!";')
- local res = exec_lua([[
+ local res = exec_lua([[
cquery = vim.treesitter.query.parse("c", '([_] @quote (#vim-match? @quote "^\\"$")) ([_] @quote (#lua-match? @quote "^\\"$"))')
parser = vim.treesitter.get_parser(0, "c")
tree = parser:parse()[1]
res = {}
- for pattern, match in cquery:iter_matches(tree:root(), 0) do
+ for pattern, match in cquery:iter_matches(tree:root(), 0, 0, -1, { all = true }) do
-- can't transmit node over RPC. just check the name and range
local mrepr = {}
- for cid,node in pairs(match) do
- table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ for cid, nodes in pairs(match) do
+ for _, node in ipairs(nodes) do
+ table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ end
end
table.insert(res, {pattern, mrepr})
end
return res
]])
- eq({
- { 1, { { "quote", '"', 0, 16, 0, 17 } } },
- { 2, { { "quote", '"', 0, 16, 0, 17 } } },
- { 1, { { "quote", '"', 0, 29, 0, 30 } } },
- { 2, { { "quote", '"', 0, 29, 0, 30 } } },
- }, res)
- end)
+ eq({
+ { 1, { { 'quote', '"', 0, 16, 0, 17 } } },
+ { 2, { { 'quote', '"', 0, 16, 0, 17 } } },
+ { 1, { { 'quote', '"', 0, 29, 0, 30 } } },
+ { 2, { { 'quote', '"', 0, 29, 0, 30 } } },
+ }, res)
+ end
+ )
it('allows to add predicates', function()
insert([[
@@ -450,44 +553,250 @@ end]]
}
]])
- local custom_query = "((identifier) @main (#is-main? @main))"
+ local custom_query = '((identifier) @main (#is-main? @main))'
- local res = exec_lua([[
- local query = vim.treesitter.query
+ do
+ local res = exec_lua(
+ [[
+ local query = vim.treesitter.query
+
+ local function is_main(match, pattern, bufnr, predicate)
+ local nodes = match[ predicate[2] ]
+ for _, node in ipairs(nodes) do
+ if vim.treesitter.get_node_text(node, bufnr) == 'main' then
+ return true
+ end
+ end
+ return false
+ end
+
+ local parser = vim.treesitter.get_parser(0, "c")
- local function is_main(match, pattern, bufnr, predicate)
- local node = match[ predicate[2] ]
+ -- Time bomb: update this in 0.12
+ if vim.fn.has('nvim-0.12') == 1 then
+ return 'Update this test to remove this message and { all = true } from add_predicate'
+ end
+ query.add_predicate("is-main?", is_main, { all = true })
+
+ local query = query.parse("c", ...)
+
+ local nodes = {}
+ for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
+ table.insert(nodes, {node:range()})
+ end
+
+ return nodes
+ ]],
+ custom_query
+ )
- return query.get_node_text(node, bufnr)
+ eq({ { 0, 4, 0, 8 } }, res)
end
- local parser = vim.treesitter.get_parser(0, "c")
+ -- Once with the old API. Remove this whole 'do' block in 0.12
+ do
+ local res = exec_lua(
+ [[
+ local query = vim.treesitter.query
- query.add_predicate("is-main?", is_main)
+ local function is_main(match, pattern, bufnr, predicate)
+ local node = match[ predicate[2] ]
- local query = query.parse("c", ...)
+ return vim.treesitter.get_node_text(node, bufnr) == 'main'
+ end
- local nodes = {}
- for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
- table.insert(nodes, {node:range()})
+ local parser = vim.treesitter.get_parser(0, "c")
+
+ query.add_predicate("is-main?", is_main, true)
+
+ local query = query.parse("c", ...)
+
+ local nodes = {}
+ for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
+ table.insert(nodes, {node:range()})
+ end
+
+ return nodes
+ ]],
+ custom_query
+ )
+
+ -- Remove this 'do' block in 0.12
+ eq(0, fn.has('nvim-0.12'))
+ eq({ { 0, 4, 0, 8 } }, res)
end
- return nodes
- ]], custom_query)
+ do
+ local res = exec_lua [[
+ local query = vim.treesitter.query
- eq({{0, 4, 0, 8}}, res)
+ local t = {}
+ for _, v in ipairs(query.list_predicates()) do
+ t[v] = true
+ end
- local res_list = exec_lua[[
- local query = vim.treesitter.query
+ return t
+ ]]
- local list = query.list_predicates()
+ eq(true, res['is-main?'])
+ end
+ end)
- table.sort(list)
+ it('supports "all" and "any" semantics for predicates on quantified captures #24738', function()
+ local query_all = [[
+ (((comment (comment_content))+) @bar
+ (#lua-match? @bar "Yes"))
+ ]]
+
+ local query_any = [[
+ (((comment (comment_content))+) @bar
+ (#any-lua-match? @bar "Yes"))
+ ]]
+
+ local function test(input, query)
+ api.nvim_buf_set_lines(0, 0, -1, true, vim.split(dedent(input), '\n'))
+ return exec_lua(
+ [[
+ local parser = vim.treesitter.get_parser(0, "lua")
+ local query = vim.treesitter.query.parse("lua", ...)
+ local nodes = {}
+ for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
+ nodes[#nodes+1] = { node:range() }
+ end
+ return nodes
+ ]],
+ query
+ )
+ end
+
+ eq(
+ {},
+ test(
+ [[
+ -- Yes
+ -- No
+ -- Yes
+ ]],
+ query_all
+ )
+ )
+
+ eq(
+ {
+ { 0, 2, 0, 8 },
+ { 1, 2, 1, 8 },
+ { 2, 2, 2, 8 },
+ },
+ test(
+ [[
+ -- Yes
+ -- Yes
+ -- Yes
+ ]],
+ query_all
+ )
+ )
+
+ eq(
+ {},
+ test(
+ [[
+ -- No
+ -- No
+ -- No
+ ]],
+ query_any
+ )
+ )
+
+ eq(
+ {
+ { 0, 2, 0, 7 },
+ { 1, 2, 1, 8 },
+ { 2, 2, 2, 7 },
+ },
+ test(
+ [[
+ -- No
+ -- Yes
+ -- No
+ ]],
+ query_any
+ )
+ )
+ end)
+
+ it('supports any- prefix to match any capture when using quantifiers #24738', function()
+ insert([[
+ -- Comment
+ -- Comment
+ -- Comment
+ ]])
- return list
+ local query = [[
+ (((comment (comment_content))+) @bar
+ (#lua-match? @bar "Comment"))
]]
- eq({ 'any-of?', 'contains?', 'eq?', 'has-ancestor?', 'has-parent?', 'is-main?', 'lua-match?', 'match?', 'vim-match?' }, res_list)
+ local result = exec_lua(
+ [[
+ local parser = vim.treesitter.get_parser(0, "lua")
+ local query = vim.treesitter.query.parse("lua", ...)
+ local nodes = {}
+ for _, node in query:iter_captures(parser:parse()[1]:root(), 0) do
+ nodes[#nodes+1] = { node:range() }
+ end
+ return nodes
+ ]],
+ query
+ )
+
+ eq({
+ { 0, 2, 0, 12 },
+ { 1, 2, 1, 12 },
+ { 2, 2, 2, 12 },
+ }, result)
+ end)
+
+ it('supports the old broken version of iter_matches #24738', function()
+ -- Delete this test in 0.12 when iter_matches is removed
+ eq(0, fn.has('nvim-0.12'))
+
+ insert(test_text)
+ local res = exec_lua(
+ [[
+ cquery = vim.treesitter.query.parse("c", ...)
+ parser = vim.treesitter.get_parser(0, "c")
+ tree = parser:parse()[1]
+ res = {}
+ for pattern, match in cquery:iter_matches(tree:root(), 0, 7, 14) do
+ local mrepr = {}
+ for cid, node in pairs(match) do
+ table.insert(mrepr, {cquery.captures[cid], node:type(), node:range()})
+ end
+ table.insert(res, {pattern, mrepr})
+ end
+ return res
+ ]],
+ test_query
+ )
+
+ eq({
+ { 3, { { 'type', 'primitive_type', 8, 2, 8, 6 } } },
+ { 2, { { 'keyword', 'for', 9, 2, 9, 5 } } },
+ { 3, { { 'type', 'primitive_type', 9, 7, 9, 13 } } },
+ { 4, { { 'fieldarg', 'identifier', 11, 16, 11, 18 } } },
+ {
+ 1,
+ { { 'minfunc', 'identifier', 11, 12, 11, 15 }, { 'min_id', 'identifier', 11, 27, 11, 32 } },
+ },
+ { 4, { { 'fieldarg', 'identifier', 12, 17, 12, 19 } } },
+ {
+ 1,
+ { { 'minfunc', 'identifier', 12, 13, 12, 16 }, { 'min_id', 'identifier', 12, 29, 12, 35 } },
+ },
+ { 4, { { 'fieldarg', 'identifier', 13, 14, 13, 16 } } },
+ }, res)
end)
it('allows to set simple ranges', function()
@@ -498,7 +807,7 @@ end]]
return { parser:parse()[1]:root():range() }
]]
- eq({0, 0, 19, 0}, res)
+ eq({ 0, 0, 19, 0 }, res)
-- The following sets the included ranges for the current parser
-- As stated here, this only includes the function (thus the whole buffer, without the last line)
@@ -509,7 +818,7 @@ end]]
return { parser:parse(true)[1]:root():range() }
]]
- eq({0, 0, 18, 1}, res2)
+ eq({ 0, 0, 18, 1 }, res2)
eq({ { { 0, 0, 0, 18, 1, 512 } } }, exec_lua [[ return parser:included_regions() ]])
@@ -522,7 +831,7 @@ end]]
eq(range_tbl, { { { 0, 0, 0, 17, 1, 508 } } })
end)
- it("allows to set complex ranges", function()
+ it('allows to set complex ranges', function()
insert(test_text)
local res = exec_lua [[
@@ -552,10 +861,11 @@ end]]
{ 8, 2, 8, 33 },
{ 9, 7, 9, 20 },
{ 10, 4, 10, 20 },
- { 14, 9, 14, 27 } }, res)
+ { 14, 9, 14, 27 },
+ }, res)
end)
- it("allows to create string parsers", function()
+ it('allows to create string parsers', function()
local ret = exec_lua [[
local parser = vim.treesitter.get_string_parser("int foo = 42;", "c")
return { parser:parse()[1]:root():range() }
@@ -564,35 +874,39 @@ end]]
eq({ 0, 0, 0, 13 }, ret)
end)
- it("allows to run queries with string parsers", function()
+ it('allows to run queries with string parsers', function()
local txt = [[
int foo = 42;
int bar = 13;
]]
- local ret = exec_lua([[
+ local ret = exec_lua(
+ [[
local str = ...
local parser = vim.treesitter.get_string_parser(str, "c")
local nodes = {}
- local query = vim.treesitter.query.parse("c", '((identifier) @id (eq? @id "foo"))')
+ local query = vim.treesitter.query.parse("c", '((identifier) @id (#eq? @id "foo"))')
for _, node in query:iter_captures(parser:parse()[1]:root(), str) do
table.insert(nodes, { node:range() })
end
- return nodes]], txt)
+ return nodes]],
+ txt
+ )
- eq({ {0, 10, 0, 13} }, ret)
+ eq({ { 0, 10, 0, 13 } }, ret)
end)
- it("should use node range when omitted", function()
+ it('should use node range when omitted', function()
local txt = [[
int foo = 42;
int bar = 13;
]]
- local ret = exec_lua([[
+ local ret = exec_lua(
+ [[
local str = ...
local parser = vim.treesitter.get_string_parser(str, "c")
@@ -604,12 +918,14 @@ end]]
table.insert(nodes, { node:range() })
end
- return nodes]], txt)
+ return nodes]],
+ txt
+ )
- eq({ {1, 10, 1, 13} }, ret)
+ eq({ { 1, 10, 1, 13 } }, ret)
end)
- describe("when creating a language tree", function()
+ describe('when creating a language tree', function()
local function get_ranges()
return exec_lua([[
local result = {}
@@ -629,8 +945,8 @@ int x = INT_MAX;
]])
end)
- describe("when parsing regions independently", function()
- it("should inject a language", function()
+ describe('when parsing regions independently', function()
+ it('should inject a language', function()
exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
injections = {
@@ -638,32 +954,32 @@ int x = INT_MAX;
parser:parse(true)
]])
- eq("table", exec_lua("return type(parser:children().c)"))
- eq(5, exec_lua("return #parser:children().c:trees()"))
+ eq('table', exec_lua('return type(parser:children().c)'))
+ eq(5, exec_lua('return #parser:children().c:trees()'))
eq({
- {0, 0, 7, 0}, -- root tree
- {3, 14, 3, 17}, -- VALUE 123
- {4, 15, 4, 18}, -- VALUE1 123
- {5, 15, 5, 18}, -- VALUE2 123
- {1, 26, 1, 63}, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- {2, 29, 2, 66} -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 7, 0 }, -- root tree
+ { 3, 14, 3, 17 }, -- VALUE 123
+ { 4, 15, 4, 18 }, -- VALUE1 123
+ { 5, 15, 5, 18 }, -- VALUE2 123
+ { 1, 26, 1, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ { 2, 29, 2, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
helpers.feed('ggo<esc>')
- eq(5, exec_lua("return #parser:children().c:trees()"))
+ eq(5, exec_lua('return #parser:children().c:trees()'))
eq({
- {0, 0, 8, 0}, -- root tree
- {4, 14, 4, 17}, -- VALUE 123
- {5, 15, 5, 18}, -- VALUE1 123
- {6, 15, 6, 18}, -- VALUE2 123
- {2, 26, 2, 63}, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- {3, 29, 3, 66} -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 8, 0 }, -- root tree
+ { 4, 14, 4, 17 }, -- VALUE 123
+ { 5, 15, 5, 18 }, -- VALUE1 123
+ { 6, 15, 6, 18 }, -- VALUE2 123
+ { 2, 26, 2, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ { 3, 29, 3, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
end)
end)
- describe("when parsing regions combined", function()
- it("should inject a language", function()
+ describe('when parsing regions combined', function()
+ it('should inject a language', function()
exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
injections = {
@@ -671,33 +987,45 @@ int x = INT_MAX;
parser:parse(true)
]])
- eq("table", exec_lua("return type(parser:children().c)"))
- eq(2, exec_lua("return #parser:children().c:trees()"))
+ eq('table', exec_lua('return type(parser:children().c)'))
+ eq(2, exec_lua('return #parser:children().c:trees()'))
eq({
- {0, 0, 7, 0}, -- root tree
- {3, 14, 5, 18}, -- VALUE 123
- -- VALUE1 123
- -- VALUE2 123
- {1, 26, 2, 66} -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 7, 0 }, -- root tree
+ { 3, 14, 5, 18 }, -- VALUE 123
+ -- VALUE1 123
+ -- VALUE2 123
+ { 1, 26, 2, 66 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
helpers.feed('ggo<esc>')
- eq("table", exec_lua("return type(parser:children().c)"))
- eq(2, exec_lua("return #parser:children().c:trees()"))
+ eq('table', exec_lua('return type(parser:children().c)'))
+ eq(2, exec_lua('return #parser:children().c:trees()'))
eq({
- {0, 0, 8, 0}, -- root tree
- {4, 14, 6, 18}, -- VALUE 123
- -- VALUE1 123
- -- VALUE2 123
- {2, 26, 3, 66} -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 8, 0 }, -- root tree
+ { 4, 14, 6, 18 }, -- VALUE 123
+ -- VALUE1 123
+ -- VALUE2 123
+ { 2, 26, 3, 66 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ }, get_ranges())
+
+ helpers.feed('7ggI//<esc>')
+ exec_lua([[parser:parse({6, 7})]])
+ eq('table', exec_lua('return type(parser:children().c)'))
+ eq(2, exec_lua('return #parser:children().c:trees()'))
+ eq({
+ { 0, 0, 8, 0 }, -- root tree
+ { 4, 14, 5, 18 }, -- VALUE 123
+ -- VALUE1 123
+ { 2, 26, 3, 66 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
end)
end)
- describe("when using injection.self", function()
- it("should inject the source language", function()
+ describe('when using injection.self', function()
+ it('should inject the source language', function()
exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
injections = {
@@ -705,32 +1033,32 @@ int x = INT_MAX;
parser:parse(true)
]])
- eq("table", exec_lua("return type(parser:children().c)"))
- eq(5, exec_lua("return #parser:children().c:trees()"))
+ eq('table', exec_lua('return type(parser:children().c)'))
+ eq(5, exec_lua('return #parser:children().c:trees()'))
eq({
- {0, 0, 7, 0}, -- root tree
- {3, 14, 3, 17}, -- VALUE 123
- {4, 15, 4, 18}, -- VALUE1 123
- {5, 15, 5, 18}, -- VALUE2 123
- {1, 26, 1, 63}, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- {2, 29, 2, 66} -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 7, 0 }, -- root tree
+ { 3, 14, 3, 17 }, -- VALUE 123
+ { 4, 15, 4, 18 }, -- VALUE1 123
+ { 5, 15, 5, 18 }, -- VALUE2 123
+ { 1, 26, 1, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ { 2, 29, 2, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
helpers.feed('ggo<esc>')
- eq(5, exec_lua("return #parser:children().c:trees()"))
+ eq(5, exec_lua('return #parser:children().c:trees()'))
eq({
- {0, 0, 8, 0}, -- root tree
- {4, 14, 4, 17}, -- VALUE 123
- {5, 15, 5, 18}, -- VALUE1 123
- {6, 15, 6, 18}, -- VALUE2 123
- {2, 26, 2, 63}, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- {3, 29, 3, 66} -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 8, 0 }, -- root tree
+ { 4, 14, 4, 17 }, -- VALUE 123
+ { 5, 15, 5, 18 }, -- VALUE1 123
+ { 6, 15, 6, 18 }, -- VALUE2 123
+ { 2, 26, 2, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ { 3, 29, 3, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
end)
end)
- describe("when using the offset directive", function()
- it("should shift the range by the directive amount", function()
+ describe('when using the offset directive', function()
+ it('should shift the range by the directive amount', function()
exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
injections = {
@@ -738,18 +1066,18 @@ int x = INT_MAX;
parser:parse(true)
]])
- eq("table", exec_lua("return type(parser:children().c)"))
+ eq('table', exec_lua('return type(parser:children().c)'))
eq({
- {0, 0, 7, 0}, -- root tree
- {3, 16, 3, 16}, -- VALUE 123
- {4, 17, 4, 17}, -- VALUE1 123
- {5, 17, 5, 17}, -- VALUE2 123
- {1, 26, 1, 63}, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
- {2, 29, 2, 66} -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
+ { 0, 0, 7, 0 }, -- root tree
+ { 3, 16, 3, 16 }, -- VALUE 123
+ { 4, 17, 4, 17 }, -- VALUE1 123
+ { 5, 17, 5, 17 }, -- VALUE2 123
+ { 1, 26, 1, 63 }, -- READ_STRING(x, y) (char *)read_string((x), (size_t)(y))
+ { 2, 29, 2, 66 }, -- READ_STRING_OK(x, y) (char *)read_string((x), (size_t)(y))
}, get_ranges())
end)
- it("should list all directives", function()
- local res_list = exec_lua[[
+ it('should list all directives', function()
+ local res_list = exec_lua [[
local query = vim.treesitter.query
local list = query.list_directives()
@@ -764,7 +1092,7 @@ int x = INT_MAX;
end)
end)
- describe("when getting the language for a range", function()
+ describe('when getting the language for a range', function()
before_each(function()
insert([[
int x = INT_MAX;
@@ -772,7 +1100,7 @@ int x = INT_MAX;
]])
end)
- it("should return the correct language tree", function()
+ it('should return the correct language tree', function()
local result = exec_lua([[
parser = vim.treesitter.get_parser(0, "c", {
injections = { c = '(preproc_def (preproc_arg) @injection.content (#set! injection.language "c"))'}})
@@ -787,9 +1115,9 @@ int x = INT_MAX;
end)
end)
- describe("when getting/setting match data", function()
- describe("when setting for the whole match", function()
- it("should set/get the data correctly", function()
+ describe('when getting/setting match data', function()
+ describe('when setting for the whole match', function()
+ it('should set/get the data correctly', function()
insert([[
int x = 3;
]])
@@ -800,18 +1128,18 @@ int x = INT_MAX;
query = vim.treesitter.query.parse("c", '((number_literal) @number (#set! "key" "value"))')
parser = vim.treesitter.get_parser(0, "c")
- for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do
+ for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0, 0, -1, { all = true }) do
result = metadata.key
end
return result
]])
- eq(result, "value")
+ eq(result, 'value')
end)
- describe("when setting a key on a capture", function()
- it("it should create the nested table", function()
+ describe('when setting a key on a capture', function()
+ it('it should create the nested table', function()
insert([[
int x = 3;
]])
@@ -823,17 +1151,17 @@ int x = INT_MAX;
query = vim.treesitter.query.parse("c", '((number_literal) @number (#set! @number "key" "value"))')
parser = vim.treesitter.get_parser(0, "c")
- for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do
+ for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0, 0, -1, { all = true }) do
for _, nested_tbl in pairs(metadata) do
return nested_tbl.key
end
end
]])
- eq(result, "value")
+ eq(result, 'value')
end)
- it("it should not overwrite the nested table", function()
+ it('it should not overwrite the nested table', function()
insert([[
int x = 3;
]])
@@ -845,15 +1173,15 @@ int x = INT_MAX;
query = vim.treesitter.query.parse("c", '((number_literal) @number (#set! @number "key" "value") (#set! @number "key2" "value2"))')
parser = vim.treesitter.get_parser(0, "c")
- for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0) do
+ for pattern, match, metadata in query:iter_matches(parser:parse()[1]:root(), 0, 0, -1, { all = true }) do
for _, nested_tbl in pairs(metadata) do
return nested_tbl
end
end
]])
local expected = {
- ["key"] = "value",
- ["key2"] = "value2",
+ ['key'] = 'value',
+ ['key2'] = 'value2',
}
eq(expected, result)
@@ -878,7 +1206,8 @@ int x = INT_MAX;
]])
local function run_query()
- return exec_lua([[
+ return exec_lua(
+ [[
local query = vim.treesitter.query.parse("c", ...)
parser = vim.treesitter.get_parser()
tree = parser:parse()[1]
@@ -887,23 +1216,24 @@ int x = INT_MAX;
table.insert(res, {query.captures[id], node:range()})
end
return res
- ]], query0)
+ ]],
+ query0
+ )
end
eq({
{ 'function', 0, 0, 2, 1 },
- { 'declaration', 1, 2, 1, 12 }
+ { 'declaration', 1, 2, 1, 12 },
}, run_query())
- helpers.command'normal ggO'
+ helpers.command 'normal ggO'
insert('int a;')
eq({
{ 'declaration', 0, 0, 0, 6 },
{ 'function', 1, 0, 3, 1 },
- { 'declaration', 2, 2, 2, 12 }
+ { 'declaration', 2, 2, 2, 12 },
}, run_query())
-
end)
it('handles ranges when source is a multiline string (#20419)', function()
@@ -926,7 +1256,8 @@ int x = INT_MAX;
]]
]==]
- local r = exec_lua([[
+ local r = exec_lua(
+ [[
local parser = vim.treesitter.get_string_parser(..., 'lua')
parser:parse(true)
local ranges = {}
@@ -934,19 +1265,22 @@ int x = INT_MAX;
ranges[tree:lang()] = { tstree:root():range(true) }
end)
return ranges
- ]], source)
+ ]],
+ source
+ )
eq({
lua = { 0, 6, 6, 16, 4, 438 },
query = { 6, 20, 113, 15, 6, 431 },
- vim = { 1, 0, 16, 4, 6, 89 }
+ 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 rb = exec_lua(
+ [[
local r, source = ...
local add_bytes = require('vim.treesitter._range').add_bytes
for lang, range in pairs(r) do
@@ -954,13 +1288,15 @@ int x = INT_MAX;
r[lang] = add_bytes(source, r[lang])
end
return r
- ]], r, source)
+ ]],
+ r,
+ source
+ )
eq(rb, r)
-
end)
- it("does not produce empty injection ranges (#23409)", function()
+ it('does not produce empty injection ranges (#23409)', function()
insert [[
Examples: >lua
local a = {}
@@ -977,7 +1313,7 @@ int x = INT_MAX;
parser1:parse(true)
]]
- eq(0, exec_lua("return #vim.tbl_keys(parser1:children())"))
+ eq(0, exec_lua('return #vim.tbl_keys(parser1:children())'))
exec_lua [[
parser2 = require('vim.treesitter.languagetree').new(0, "vimdoc", {
@@ -988,13 +1324,12 @@ int x = INT_MAX;
parser2:parse(true)
]]
- eq(1, exec_lua("return #vim.tbl_keys(parser2:children())"))
- eq( { { { 1, 0, 21, 2, 0, 42 } } }, exec_lua("return parser2:children().lua:included_regions()"))
-
+ eq(1, exec_lua('return #vim.tbl_keys(parser2:children())'))
+ eq({ { { 1, 0, 21, 2, 0, 42 } } }, exec_lua('return parser2:children().lua:included_regions()'))
end)
- it("parsers injections incrementally", function()
- insert(dedent[[
+ it('parsers injections incrementally', function()
+ insert(dedent [[
>lua
local a = {}
<
@@ -1033,26 +1368,38 @@ int x = INT_MAX;
]]
--- Do not parse injections by default
- eq(0, exec_lua [[
+ eq(
+ 0,
+ exec_lua [[
parser:parse()
return #vim.tbl_keys(parser:children())
- ]])
+ ]]
+ )
--- Only parse injections between lines 0, 2
- eq(1, exec_lua [[
+ eq(
+ 1,
+ exec_lua [[
parser:parse({0, 2})
return #parser:children().lua:trees()
- ]])
+ ]]
+ )
- eq(2, exec_lua [[
+ eq(
+ 2,
+ exec_lua [[
parser:parse({2, 6})
return #parser:children().lua:trees()
- ]])
+ ]]
+ )
- eq(7, exec_lua [[
+ eq(
+ 7,
+ exec_lua [[
parser:parse(true)
return #parser:children().lua:trees()
- ]])
+ ]]
+ )
end)
it('fails to load queries', function()
@@ -1062,43 +1409,48 @@ int x = INT_MAX;
-- Invalid node type
test(
- '.../query.lua:0: Query error at 1:2. Invalid node type "dentifier":\n'..
- '(dentifier) @variable\n'..
- ' ^',
- '(dentifier) @variable')
+ '.../query.lua:0: Query error at 1:2. Invalid node type "dentifier":\n'
+ .. '(dentifier) @variable\n'
+ .. ' ^',
+ '(dentifier) @variable'
+ )
-- Impossible pattern
test(
- '.../query.lua:0: Query error at 1:13. Impossible pattern:\n'..
- '(identifier (identifier) @variable)\n'..
- ' ^',
- '(identifier (identifier) @variable)')
+ '.../query.lua:0: Query error at 1:13. Impossible pattern:\n'
+ .. '(identifier (identifier) @variable)\n'
+ .. ' ^',
+ '(identifier (identifier) @variable)'
+ )
-- Invalid syntax
test(
- '.../query.lua:0: Query error at 1:13. Invalid syntax:\n'..
- '(identifier @variable\n'..
- ' ^',
- '(identifier @variable')
+ '.../query.lua:0: Query error at 1:13. Invalid syntax:\n'
+ .. '(identifier @variable\n'
+ .. ' ^',
+ '(identifier @variable'
+ )
-- Invalid field name
test(
- '.../query.lua:0: Query error at 1:15. Invalid field name "invalid_field":\n'..
- '((identifier) invalid_field: (identifier))\n'..
- ' ^',
- '((identifier) invalid_field: (identifier))')
+ '.../query.lua:0: Query error at 1:15. Invalid field name "invalid_field":\n'
+ .. '((identifier) invalid_field: (identifier))\n'
+ .. ' ^',
+ '((identifier) invalid_field: (identifier))'
+ )
-- Invalid capture name
test(
- '.../query.lua:0: Query error at 3:2. Invalid capture name "ok.capture":\n'..
- '@ok.capture\n'..
- ' ^',
- '((identifier) @id \n(#eq? @id\n@ok.capture\n))')
+ '.../query.lua:0: Query error at 3:2. Invalid capture name "ok.capture":\n'
+ .. '@ok.capture\n'
+ .. ' ^',
+ '((identifier) @id \n(#eq? @id\n@ok.capture\n))'
+ )
end)
describe('is_valid()', function()
before_each(function()
- insert(dedent[[
+ insert(dedent [[
Treesitter integration *treesitter*
Nvim integrates the `tree-sitter` library for incremental parsing of buffers:
@@ -1137,7 +1489,7 @@ int x = INT_MAX;
describe('when adding content with injections', function()
before_each(function()
feed('G')
- insert(dedent[[
+ insert(dedent [[
>lua
local a = {}
<
@@ -1156,23 +1508,29 @@ int x = INT_MAX;
eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
end)
- it('is fully valid after a range parse that leads to parsing not parsed injections', function()
- exec_lua('vim.treesitter.get_parser():parse({5, 7})')
- eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
- eq(true, exec_lua('return vim.treesitter.get_parser():is_valid()'))
- end)
-
- it('is valid excluding, invalid including children after a range parse that does not lead to parsing not parsed injections', function()
- exec_lua('vim.treesitter.get_parser():parse({2, 4})')
- eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
- eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
- end)
+ it(
+ 'is fully valid after a range parse that leads to parsing not parsed injections',
+ function()
+ exec_lua('vim.treesitter.get_parser():parse({5, 7})')
+ eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
+ eq(true, exec_lua('return vim.treesitter.get_parser():is_valid()'))
+ end
+ )
+
+ it(
+ 'is valid excluding, invalid including children after a range parse that does not lead to parsing not parsed injections',
+ function()
+ exec_lua('vim.treesitter.get_parser():parse({2, 4})')
+ eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
+ eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
+ end
+ )
end)
describe('when removing content with injections', function()
before_each(function()
feed('G')
- insert(dedent[[
+ insert(dedent [[
>lua
local a = {}
<
@@ -1205,11 +1563,14 @@ int x = INT_MAX;
eq(true, exec_lua('return vim.treesitter.get_parser():is_valid()'))
end)
- it('is valid excluding, invalid including children after a range parse that does not lead to parsing modified child tree', function()
- exec_lua('vim.treesitter.get_parser():parse({2, 4})')
- eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
- eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
- end)
+ it(
+ 'is valid excluding, invalid including children after a range parse that does not lead to parsing modified child tree',
+ function()
+ exec_lua('vim.treesitter.get_parser():parse({2, 4})')
+ eq(true, exec_lua('return vim.treesitter.get_parser():is_valid(true)'))
+ eq(false, exec_lua('return vim.treesitter.get_parser():is_valid()'))
+ end
+ )
end)
end)
end)
diff --git a/test/functional/treesitter/utils_spec.lua b/test/functional/treesitter/utils_spec.lua
index 9c07959098..2734c22499 100644
--- a/test/functional/treesitter/utils_spec.lua
+++ b/test/functional/treesitter/utils_spec.lua
@@ -11,7 +11,6 @@ describe('treesitter utils', function()
before_each(clear)
it('can find an ancestor', function()
-
insert([[
int main() {
int x = 3;
diff --git a/test/functional/ui/bufhl_spec.lua b/test/functional/ui/bufhl_spec.lua
index 81e514c9aa..896f75a681 100644
--- a/test/functional/ui/bufhl_spec.lua
+++ b/test/functional/ui/bufhl_spec.lua
@@ -3,9 +3,10 @@ local Screen = require('test.functional.ui.screen')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command, neq = helpers.command, helpers.neq
-local meths = helpers.meths
-local curbufmeths, eq = helpers.curbufmeths, helpers.eq
+local api = helpers.api
+local eq = helpers.eq
local pcall_err = helpers.pcall_err
+local set_virtual_text = api.nvim_buf_set_virtual_text
describe('Buffer highlighting', function()
local screen
@@ -16,31 +17,31 @@ describe('Buffer highlighting', function()
screen = Screen.new(40, 8)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold=true, foreground=Screen.colors.Blue},
- [2] = {foreground = Screen.colors.Fuchsia}, -- String
- [3] = {foreground = Screen.colors.Brown, bold = true}, -- Statement
- [4] = {foreground = Screen.colors.SlateBlue}, -- Special
- [5] = {bold = true, foreground = Screen.colors.SlateBlue},
- [6] = {foreground = Screen.colors.DarkCyan}, -- Identifier
- [7] = {bold = true},
- [8] = {underline = true, bold = true, foreground = Screen.colors.SlateBlue},
- [9] = {foreground = Screen.colors.SlateBlue, underline = true},
- [10] = {foreground = Screen.colors.Red},
- [11] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [12] = {foreground = Screen.colors.Blue1},
- [13] = {background = Screen.colors.LightGrey},
- [14] = {background = Screen.colors.Gray90},
- [15] = {background = Screen.colors.Gray90, bold = true, foreground = Screen.colors.Brown},
- [16] = {foreground = Screen.colors.Magenta, background = Screen.colors.Gray90},
- [17] = {foreground = Screen.colors.Magenta, background = Screen.colors.LightRed},
- [18] = {background = Screen.colors.LightRed},
- [19] = {foreground = Screen.colors.Blue1, background = Screen.colors.LightRed},
- [20] = {underline = true, bold = true, foreground = Screen.colors.Cyan4},
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { foreground = Screen.colors.Fuchsia }, -- String
+ [3] = { foreground = Screen.colors.Brown, bold = true }, -- Statement
+ [4] = { foreground = Screen.colors.SlateBlue }, -- Special
+ [5] = { bold = true, foreground = Screen.colors.SlateBlue },
+ [6] = { foreground = Screen.colors.DarkCyan }, -- Identifier
+ [7] = { bold = true },
+ [8] = { underline = true, bold = true, foreground = Screen.colors.SlateBlue },
+ [9] = { foreground = Screen.colors.SlateBlue, underline = true },
+ [10] = { foreground = Screen.colors.Red },
+ [11] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [12] = { foreground = Screen.colors.Blue1 },
+ [13] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey },
+ [14] = { background = Screen.colors.Gray90 },
+ [15] = { background = Screen.colors.Gray90, bold = true, foreground = Screen.colors.Brown },
+ [16] = { foreground = Screen.colors.Magenta, background = Screen.colors.Gray90 },
+ [17] = { foreground = Screen.colors.Magenta, background = Screen.colors.LightRed },
+ [18] = { background = Screen.colors.LightRed },
+ [19] = { foreground = Screen.colors.Blue1, background = Screen.colors.LightRed },
+ [20] = { underline = true, bold = true, foreground = Screen.colors.Cyan4 },
})
end)
- local add_highlight = curbufmeths.add_highlight
- local clear_namespace = curbufmeths.clear_namespace
+ local add_highlight = api.nvim_buf_add_highlight
+ local clear_namespace = api.nvim_buf_clear_namespace
it('works', function()
insert([[
@@ -51,49 +52,35 @@ describe('Buffer highlighting', function()
screen:expect([[
these are some lines |
with colorful tex^t |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
- add_highlight(-1, "String", 0 , 10, 14)
- add_highlight(-1, "Statement", 1 , 5, -1)
+ add_highlight(0, -1, 'String', 0, 10, 14)
+ add_highlight(0, -1, 'Statement', 1, 5, -1)
screen:expect([[
these are {2:some} lines |
with {3:colorful tex^t} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
- feed("ggo<esc>")
+ feed('ggo<esc>')
screen:expect([[
these are {2:some} lines |
^ |
with {3:colorful text} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
- clear_namespace(-1, 0, -1)
+ clear_namespace(0, -1, 0, -1)
screen:expect([[
these are some lines |
^ |
with colorful text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
end)
@@ -107,89 +94,79 @@ describe('Buffer highlighting', function()
combining highlights
from different sources]])
- command("hi ImportantWord gui=bold cterm=bold")
- id1 = add_highlight(0, "ImportantWord", 0, 2, 8)
- add_highlight(id1, "ImportantWord", 1, 12, -1)
- add_highlight(id1, "ImportantWord", 2, 0, 9)
- add_highlight(id1, "ImportantWord", 3, 5, 14)
+ command('hi ImportantWord gui=bold cterm=bold')
+ id1 = add_highlight(0, 0, 'ImportantWord', 0, 2, 8)
+ add_highlight(0, id1, 'ImportantWord', 1, 12, -1)
+ add_highlight(0, id1, 'ImportantWord', 2, 0, 9)
+ add_highlight(0, id1, 'ImportantWord', 3, 5, 14)
-- add_highlight can be called like this to get a new source
-- without adding any highlight
- id2 = add_highlight(0, "", 0, 0, 0)
+ id2 = add_highlight(0, 0, '', 0, 0, 0)
neq(id1, id2)
- add_highlight(id2, "Special", 0, 2, 8)
- add_highlight(id2, "Identifier", 1, 3, 8)
- add_highlight(id2, "Special", 1, 14, 20)
- add_highlight(id2, "Underlined", 2, 6, 12)
- add_highlight(id2, "Underlined", 3, 0, 9)
+ add_highlight(0, id2, 'Special', 0, 2, 8)
+ add_highlight(0, id2, 'Identifier', 1, 3, 8)
+ add_highlight(0, id2, 'Special', 1, 14, 20)
+ add_highlight(0, id2, 'Underlined', 2, 6, 12)
+ add_highlight(0, id2, 'Underlined', 3, 0, 9)
screen:expect([[
a {5:longer} example |
in {6:order} to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} source^s |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
end)
it('and clearing the first added', function()
- clear_namespace(id1, 0, -1)
+ clear_namespace(0, id1, 0, -1)
screen:expect([[
a {4:longer} example |
in {6:order} to de{4:monstr}ate |
combin{9:ing hi}ghlights |
{9:from diff}erent source^s |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
end)
it('and clearing using deprecated name', function()
- curbufmeths.clear_highlight(id1, 0, -1)
+ api.nvim_buf_clear_highlight(0, id1, 0, -1)
screen:expect([[
a {4:longer} example |
in {6:order} to de{4:monstr}ate |
combin{9:ing hi}ghlights |
{9:from diff}erent source^s |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
end)
it('and clearing the second added', function()
- clear_namespace(id2, 0, -1)
+ clear_namespace(0, id2, 0, -1)
screen:expect([[
a {7:longer} example |
in order to {7:demonstrate} |
{7:combining} highlights |
from {7:different} source^s |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
end)
it('and clearing line ranges', function()
- clear_namespace(-1, 0, 1)
- clear_namespace(id1, 1, 2)
- clear_namespace(id2, 2, -1)
+ clear_namespace(0, -1, 0, 1)
+ clear_namespace(0, id1, 1, 2)
+ clear_namespace(0, id2, 2, -1)
screen:expect([[
a longer example |
in {6:order} to de{4:monstr}ate |
{7:combining} highlights |
from {7:different} source^s |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
end)
@@ -201,9 +178,7 @@ describe('Buffer highlighting', function()
^ |
in {6:order} to {7:de}{5:monstr}{7:ate} |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
@@ -211,231 +186,229 @@ describe('Buffer highlighting', function()
-- the deleted line wrapping around. we should invalidate
-- highlights when they are completely inside deleted text
command('3move 4')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
|
{8:from different sources} |
{8:^in }{20:order}{8: to demonstrate} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
--screen:expect([[
-- a {5:longer} example |
-- |
-- {9:from }{8:diff}{7:erent} sources |
-- ^in {6:order} to {7:de}{5:monstr}{7:ate} |
- -- {1:~ }|
- -- {1:~ }|
- -- {1:~ }|
+ -- {1:~ }|*3
-- |
--]])
command('undo')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
^ |
in {6:order} to {7:de}{5:monstr}{7:ate} |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
1 change; before #4 {MATCH:.*}|
- ]]}
+ ]],
+ }
command('undo')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^a {5:longer} example |
in {6:order} to {7:de}{5:monstr}{7:ate} |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
1 line less; before #3 {MATCH:.*}|
- ]]}
+ ]],
+ }
command('undo')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
in {6:order} to {7:de}{5:monstr}{7:ate} |
{7:^combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
1 more line; before #2 {MATCH:.*}|
- ]]}
+ ]],
+ }
end)
it('and moving lines around', function()
command('2move 3')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
{7:combin}{8:ing}{9: hi}ghlights |
^in {6:order} to {7:de}{5:monstr}{7:ate} |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
command('1,2move 4')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
in {6:order} to {7:de}{5:monstr}{7:ate} |
{9:from }{8:diff}{7:erent} sources |
a {5:longer} example |
{7:^combin}{8:ing}{9: hi}ghlights |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
command('undo')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
{7:combin}{8:ing}{9: hi}ghlights |
^in {6:order} to {7:de}{5:monstr}{7:ate} |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
2 changes; before #3 {MATCH:.*}|
- ]]}
+ ]],
+ }
command('undo')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
^in {6:order} to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
1 change; before #2 {MATCH:.*}|
- ]]}
+ ]],
+ }
end)
it('and adjusting columns', function()
-- insert before
feed('ggiquite <esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
quite^ a {5:longer} example |
in {6:order} to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
feed('u')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^a {5:longer} example |
in {6:order} to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
1 change; before #2 {MATCH:.*}|
- ]]}
+ ]],
+ }
-- change/insert in the middle
feed('+fesAAAA')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
in {6:ordAAAA^r} to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{7:-- INSERT --} |
- ]]}
+ ]],
+ }
feed('<esc>tdD')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
in {6:ordAAAAr} t^o |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
feed('u')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
in {6:ordAAAAr} to^ {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
1 change; before #4 {MATCH:.*}|
- ]]}
+ ]],
+ }
feed('u')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
in {6:ord^er} to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
1 change; before #3 {MATCH:.*}|
- ]]}
+ ]],
+ }
end)
it('and joining lines', function()
feed('ggJJJ')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example in {6:order} to {7:de}{5:monstr}{7:ate}|
{7:combin}{8:ing}{9: hi}ghlights^ {9:from }{8:diff}{7:erent} sou|
rces |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
- ]]}
+ ]],
+ }
feed('uuu')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^a {5:longer} example |
in {6:order} to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
1 more line; before #2 {MATCH:.*}|
- ]]}
+ ]],
+ }
end)
it('and splitting lines', function()
feed('2Gtti<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
in {6:order} |
^ to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{7:-- INSERT --} |
- ]]}
+ ]],
+ }
feed('<esc>tsi<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
in {6:order} |
to {7:de}{5:mo} |
@@ -444,61 +417,53 @@ describe('Buffer highlighting', function()
{9:from }{8:diff}{7:erent} sources |
{1:~ }|
{7:-- INSERT --} |
- ]]}
+ ]],
+ }
feed('<esc>u')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
in {6:order} |
to {7:de}{5:mo^nstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
1 line less; before #3 {MATCH:.*}|
- ]]}
+ ]],
+ }
feed('<esc>u')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
a {5:longer} example |
in {6:order}^ to {7:de}{5:monstr}{7:ate} |
{7:combin}{8:ing}{9: hi}ghlights |
{9:from }{8:diff}{7:erent} sources |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
1 line less; before #2 {MATCH:.*}|
- ]]}
+ ]],
+ }
end)
end)
pending('prioritizes latest added highlight', function()
insert([[
three overlapping colors]])
- add_highlight(0, "Identifier", 0, 6, 17)
- add_highlight(0, "String", 0, 14, 23)
- local id = add_highlight(0, "Special", 0, 0, 9)
+ add_highlight(0, 0, 'Identifier', 0, 6, 17)
+ add_highlight(0, 0, 'String', 0, 14, 23)
+ local id = add_highlight(0, 0, 'Special', 0, 0, 9)
screen:expect([[
{4:three ove}{6:rlapp}{2:ing color}^s |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
- clear_namespace(id, 0, 1)
+ clear_namespace(0, id, 0, 1)
screen:expect([[
three {6:overlapp}{2:ing color}^s |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end)
@@ -506,96 +471,76 @@ describe('Buffer highlighting', function()
it('prioritizes earlier highlight groups (TEMP)', function()
insert([[
three overlapping colors]])
- add_highlight(0, "Identifier", 0, 6, 17)
- add_highlight(0, "String", 0, 14, 23)
- local id = add_highlight(0, "Special", 0, 0, 9)
+ add_highlight(0, 0, 'Identifier', 0, 6, 17)
+ add_highlight(0, 0, 'String', 0, 14, 23)
+ local id = add_highlight(0, 0, 'Special', 0, 0, 9)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{4:three }{6:overlapp}{2:ing color}^s |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
- ]]}
+ ]],
+ }
- clear_namespace(id, 0, 1)
- screen:expect{grid=[[
+ clear_namespace(0, id, 0, 1)
+ screen:expect {
+ grid = [[
three {6:overlapp}{2:ing color}^s |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
- ]]}
+ ]],
+ }
end)
it('respects priority', function()
- local set_extmark = curbufmeths.set_extmark
- local id = meths.create_namespace('')
+ local id = api.nvim_create_namespace('')
insert [[foobar]]
- set_extmark(id, 0, 0, {
+ api.nvim_buf_set_extmark(0, id, 0, 0, {
end_line = 0,
end_col = 5,
- hl_group = "Statement",
- priority = 100
+ hl_group = 'Statement',
+ priority = 100,
})
- set_extmark(id, 0, 0, {
+ api.nvim_buf_set_extmark(0, id, 0, 0, {
end_line = 0,
end_col = 6,
- hl_group = "String",
- priority = 1
+ hl_group = 'String',
+ priority = 1,
})
screen:expect [[
{3:fooba}{2:^r} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]]
- clear_namespace(id, 0, -1)
- screen:expect{grid=[[
+ clear_namespace(0, id, 0, -1)
+ screen:expect {
+ grid = [[
fooba^r |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
- ]]}
+ ]],
+ }
- set_extmark(id, 0, 0, {
+ api.nvim_buf_set_extmark(0, id, 0, 0, {
end_line = 0,
end_col = 6,
- hl_group = "String",
- priority = 1
+ hl_group = 'String',
+ priority = 1,
})
- set_extmark(id, 0, 0, {
+ api.nvim_buf_set_extmark(0, id, 0, 0, {
end_line = 0,
end_col = 5,
- hl_group = "Statement",
- priority = 100
+ hl_group = 'Statement',
+ priority = 100,
})
screen:expect [[
{3:fooba}{2:^r} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]]
end)
@@ -603,17 +548,12 @@ describe('Buffer highlighting', function()
it('works with multibyte text', function()
insert([[
Ta båten över sjön!]])
- add_highlight(-1, "Identifier", 0, 3, 9)
- add_highlight(-1, "String", 0, 16, 21)
+ add_highlight(0, -1, 'Identifier', 0, 3, 9)
+ add_highlight(0, -1, 'String', 0, 16, 21)
screen:expect([[
Ta {6:båten} över {2:sjön}^! |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end)
@@ -621,33 +561,22 @@ describe('Buffer highlighting', function()
it('works with new syntax groups', function()
insert([[
fancy code in a new fancy language]])
- add_highlight(-1, "FancyLangItem", 0, 0, 5)
+ add_highlight(0, -1, 'FancyLangItem', 0, 0, 5)
screen:expect([[
fancy code in a new fancy languag^e |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
command('hi FancyLangItem guifg=red')
screen:expect([[
{10:fancy} code in a new fancy languag^e |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end)
describe('virtual text decorations', function()
- local set_virtual_text = curbufmeths.set_virtual_text
local id1, id2
before_each(function()
insert([[
@@ -661,16 +590,18 @@ describe('Buffer highlighting', function()
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, |
x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
- id1 = set_virtual_text(0, 0, {{"=", "Statement"}, {" 3", "Number"}}, {})
- set_virtual_text(id1, 1, {{"ERROR:", "ErrorMsg"}, {" invalid syntax"}}, {})
- id2 = set_virtual_text(0, 2, {{"Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."}}, {})
+ id1 = set_virtual_text(0, 0, 0, { { '=', 'Statement' }, { ' 3', 'Number' } }, {})
+ set_virtual_text(0, id1, 1, { { 'ERROR:', 'ErrorMsg' }, { ' invalid syntax' } }, {})
+ id2 = set_virtual_text(0, 0, 2, {
+ {
+ 'Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.',
+ },
+ }, {})
neq(id2, id1)
-
end)
it('works', function()
@@ -680,278 +611,298 @@ describe('Buffer highlighting', function()
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
- clear_namespace(id1, 0, -1)
+ clear_namespace(0, id1, 0, -1)
screen:expect([[
^1 + 2 |
3 + |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
-- Handles doublewidth chars, leaving a space if truncating
-- in the middle of a char
- eq(-1, set_virtual_text(-1, 1, {{"æš—x事zz速野谷質çµè‚²å‰¯ä½æ–°è¦šä¸¸æ´»è§£çµ‚事", "Comment"}}, {}))
+ eq(
+ -1,
+ set_virtual_text(
+ 0,
+ -1,
+ 1,
+ { { 'æš—x事zz速野谷質çµè‚²å‰¯ä½æ–°è¦šä¸¸æ´»è§£çµ‚事', 'Comment' } },
+ {}
+ )
+ )
screen:expect([[
^1 + 2 |
3 + {12:æš—x事zz速野谷質çµè‚²å‰¯ä½æ–°è¦šä¸¸æ´»è§£çµ‚ }|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
- feed("2Gx")
+ feed('2Gx')
screen:expect([[
1 + 2 |
^ + {12:æš—x事zz速野谷質çµè‚²å‰¯ä½æ–°è¦šä¸¸æ´»è§£çµ‚事}|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
- feed("2Gdd")
+ feed('2Gdd')
-- TODO(bfredl): currently decorations get moved from a deleted line
-- to the next one. We might want to add "invalidation" when deleting
-- over a decoration.
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
1 + 2 |
^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, {12:æš—x事zz速野谷質çµè‚²}|
x = 4 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
--screen:expect([[
-- 1 + 2 |
-- ^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
-- , 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
-- x = 4 |
- -- {1:~ }|
- -- {1:~ }|
- -- {1:~ }|
+ -- {1:~ }|*3
-- |
--]])
end)
it('validates contents', function()
-- this used to leak memory
- eq("Invalid 'chunk': expected Array, got String", pcall_err(set_virtual_text, id1, 0, {"texty"}, {}))
- eq("Invalid 'chunk': expected Array, got String", pcall_err(set_virtual_text, id1, 0, {{"very"}, "texty"}, {}))
+ eq(
+ "Invalid 'chunk': expected Array, got String",
+ pcall_err(set_virtual_text, 0, id1, 0, { 'texty' }, {})
+ )
+ eq(
+ "Invalid 'chunk': expected Array, got String",
+ pcall_err(set_virtual_text, 0, id1, 0, { { 'very' }, 'texty' }, {})
+ )
end)
it('can be retrieved', function()
- local get_extmarks = curbufmeths.get_extmarks
- local line_count = curbufmeths.line_count
-
- local s1 = {{'Köttbullar', 'Comment'}, {'Kräuterbutter'}}
- local s2 = {{'ã“ã‚“ã«ã¡ã¯', 'Comment'}}
-
- set_virtual_text(id1, 0, s1, {})
- eq({{1, 0, 0, {
- ns_id = 1,
- priority = 0,
- virt_text = s1,
- -- other details
- right_gravity = true,
- virt_text_pos = 'eol',
- virt_text_hide = false,
- }}}, get_extmarks(id1, {0,0}, {0, -1}, {details=true}))
-
- local lastline = line_count()
- set_virtual_text(id1, line_count(), s2, {})
- eq({{3, lastline, 0, {
- ns_id = 1,
- priority = 0,
- virt_text = s2,
- -- other details
- right_gravity = true,
- virt_text_pos = 'eol',
- virt_text_hide = false,
- }}}, get_extmarks(id1, {lastline,0}, {lastline, -1}, {details=true}))
-
- eq({}, get_extmarks(id1, {lastline+9000,0}, {lastline+9000, -1}, {}))
+ local get_extmarks = api.nvim_buf_get_extmarks
+ local line_count = api.nvim_buf_line_count
+
+ local s1 = { { 'Köttbullar', 'Comment' }, { 'Kräuterbutter' } }
+ local s2 = { { 'ã“ã‚“ã«ã¡ã¯', 'Comment' } }
+
+ set_virtual_text(0, id1, 0, s1, {})
+ eq({
+ {
+ 1,
+ 0,
+ 0,
+ {
+ ns_id = 1,
+ priority = 0,
+ virt_text = s1,
+ -- other details
+ right_gravity = true,
+ virt_text_repeat_linebreak = false,
+ virt_text_pos = 'eol',
+ virt_text_hide = false,
+ },
+ },
+ }, get_extmarks(0, id1, { 0, 0 }, { 0, -1 }, { details = true }))
+
+ local lastline = line_count(0)
+ set_virtual_text(0, id1, line_count(0), s2, {})
+ eq({
+ {
+ 3,
+ lastline,
+ 0,
+ {
+ ns_id = 1,
+ priority = 0,
+ virt_text = s2,
+ -- other details
+ right_gravity = true,
+ virt_text_repeat_linebreak = false,
+ virt_text_pos = 'eol',
+ virt_text_hide = false,
+ },
+ },
+ }, get_extmarks(0, id1, { lastline, 0 }, { lastline, -1 }, { details = true }))
+
+ eq({}, get_extmarks(0, id1, { lastline + 9000, 0 }, { lastline + 9000, -1 }, {}))
end)
it('is not highlighted by visual selection', function()
- feed("ggVG")
+ feed('ggVG')
screen:expect([[
{13:1 + 2} {3:=}{2: 3} |
{13:3 +} {11:ERROR:} invalid syntax |
{13:5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}|
{13:, 5, 5, 5, 5, 5, 5, } Lorem ipsum dolor s|
^x{13: = 4} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{7:-- VISUAL LINE --} |
]])
- feed("<esc>")
+ feed('<esc>')
screen:expect([[
1 + 2 {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
^x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
-- special case: empty line has extra eol highlight
- feed("ggd$")
+ feed('ggd$')
screen:expect([[
^ {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
- feed("jvk")
+ feed('jvk')
screen:expect([[
^ {3:=}{2: 3} |
{13:3} + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{7:-- VISUAL --} |
]])
- feed("o")
+ feed('o')
screen:expect([[
{13: }{3:=}{2: 3} |
^3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{7:-- VISUAL --} |
]])
end)
-
it('works with listchars', function()
- command("set list listchars+=eol:$")
+ command('set list listchars+=eol:$')
screen:expect([[
^1 + 2{1:$}{3:=}{2: 3} |
3 +{1:$}{11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5,{1:-$}Lorem ipsum dolor s|
x = 4{1:$} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
- clear_namespace(-1, 0, -1)
+ clear_namespace(0, -1, 0, -1)
screen:expect([[
^1 + 2{1:$} |
3 +{1:$} |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5,{1:-$} |
x = 4{1:$} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
end)
it('works with cursorline', function()
- command("set cursorline")
+ command('set cursorline')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{14:^1 + 2 }{3:=}{2: 3}{14: }|
3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
feed('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
1 + 2 {3:=}{2: 3} |
{14:^3 + }{11:ERROR:} invalid syntax{14: }|
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
-
+ ]],
+ }
feed('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
1 + 2 {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
{14:^5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5}|
{14:, 5, 5, 5, 5, 5, 5, }Lorem ipsum dolor s|
x = 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
end)
it('works with color column', function()
- eq(-1, set_virtual_text(-1, 3, {{"暗x事", "Comment"}}, {}))
- screen:expect{grid=[[
+ eq(-1, set_virtual_text(0, -1, 3, { { '暗x事', 'Comment' } }, {}))
+ screen:expect {
+ grid = [[
^1 + 2 {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 {12:暗x事} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
- command("set colorcolumn=9")
- screen:expect{grid=[[
+ command('set colorcolumn=9')
+ screen:expect {
+ grid = [[
^1 + 2 {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
5, 5, 5,{18: }5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 {12:暗x事} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]]}
+ ]],
+ }
end)
end)
it('and virtual text use the same namespace counter', function()
- local set_virtual_text = curbufmeths.set_virtual_text
- eq(1, add_highlight(0, "String", 0 , 0, -1))
- eq(2, set_virtual_text(0, 0, {{"= text", "Comment"}}, {}))
- eq(3, meths.create_namespace("my-ns"))
- eq(4, add_highlight(0, "String", 0 , 0, -1))
- eq(5, set_virtual_text(0, 0, {{"= text", "Comment"}}, {}))
- eq(6, meths.create_namespace("other-ns"))
+ eq(1, add_highlight(0, 0, 'String', 0, 0, -1))
+ eq(2, set_virtual_text(0, 0, 0, { { '= text', 'Comment' } }, {}))
+ eq(3, api.nvim_create_namespace('my-ns'))
+ eq(4, add_highlight(0, 0, 'String', 0, 0, -1))
+ eq(5, set_virtual_text(0, 0, 0, { { '= text', 'Comment' } }, {}))
+ eq(6, api.nvim_create_namespace('other-ns'))
end)
end)
diff --git a/test/functional/ui/cmdline_highlight_spec.lua b/test/functional/ui/cmdline_highlight_spec.lua
index e4766103c2..6c4000ba41 100644
--- a/test/functional/ui/cmdline_highlight_spec.lua
+++ b/test/functional/ui/cmdline_highlight_spec.lua
@@ -4,13 +4,12 @@ local Screen = require('test.functional.ui.screen')
local eq = helpers.eq
local feed = helpers.feed
local clear = helpers.clear
-local meths = helpers.meths
-local funcs = helpers.funcs
+local api = helpers.api
+local fn = helpers.fn
local source = helpers.source
local exec_capture = helpers.exec_capture
local dedent = helpers.dedent
local command = helpers.command
-local curbufmeths = helpers.curbufmeths
local screen
@@ -138,36 +137,35 @@ before_each(function()
endfunction
]])
screen:set_default_attr_ids({
- RBP1={background = Screen.colors.Red},
- RBP2={background = Screen.colors.Yellow},
- RBP3={background = Screen.colors.Green},
- RBP4={background = Screen.colors.Blue},
- EOB={bold = true, foreground = Screen.colors.Blue1},
- ERR={foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- SK={foreground = Screen.colors.Blue},
- PE={bold = true, foreground = Screen.colors.SeaGreen4},
- NUM={foreground = Screen.colors.Blue2},
- NPAR={foreground = Screen.colors.Yellow},
- SQ={foreground = Screen.colors.Blue3},
- SB={foreground = Screen.colors.Blue4},
- E={foreground = Screen.colors.Red, background = Screen.colors.Blue},
- M={bold = true},
- MSEP={bold = true, reverse = true};
+ RBP1 = { background = Screen.colors.Red },
+ RBP2 = { background = Screen.colors.Yellow },
+ RBP3 = { background = Screen.colors.Green },
+ RBP4 = { background = Screen.colors.Blue },
+ EOB = { bold = true, foreground = Screen.colors.Blue1 },
+ ERR = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ SK = { foreground = Screen.colors.Blue },
+ PE = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ NUM = { foreground = Screen.colors.Blue2 },
+ NPAR = { foreground = Screen.colors.Yellow },
+ SQ = { foreground = Screen.colors.Blue3 },
+ SB = { foreground = Screen.colors.Blue4 },
+ E = { foreground = Screen.colors.Red, background = Screen.colors.Blue },
+ M = { bold = true },
+ MSEP = { bold = true, reverse = true },
})
end)
local function set_color_cb(funcname, callback_return, id)
- meths.set_var('id', id or '')
- if id and id ~= '' and funcs.exists('*' .. funcname .. 'N') then
- command(('let g:Nvim_color_input%s = {cmdline -> %sN(%s, cmdline)}'):format(
- id, funcname, id))
+ api.nvim_set_var('id', id or '')
+ if id and id ~= '' and fn.exists('*' .. funcname .. 'N') then
+ command(('let g:Nvim_color_input%s = {cmdline -> %sN(%s, cmdline)}'):format(id, funcname, id))
if callback_return then
- meths.set_var('callback_return' .. id, callback_return)
+ api.nvim_set_var('callback_return' .. id, callback_return)
end
else
- meths.set_var('Nvim_color_input', funcname)
+ api.nvim_set_var('Nvim_color_input', funcname)
if callback_return then
- meths.set_var('callback_return', callback_return)
+ api.nvim_set_var('callback_return', callback_return)
end
end
end
@@ -178,142 +176,94 @@ end
describe('Command-line coloring', function()
it('works', function()
set_color_cb('RainBowParens')
- meths.set_option_value('more', false, {})
+ api.nvim_set_option_value('more', false, {})
start_prompt()
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:^ |
]])
feed('e')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:e^ |
]])
feed('cho ')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo ^ |
]])
feed('(')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo {RBP1:(}^ |
]])
feed('(')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo {RBP1:(}{RBP2:(}^ |
]])
feed('42')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo {RBP1:(}{RBP2:(}42^ |
]])
feed('))')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo {RBP1:(}{RBP2:(}42{RBP2:)}{RBP1:)}^ |
]])
feed('<BS>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo {RBP1:(}{RBP2:(}42{RBP2:)}^ |
]])
redraw_input()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo {RBP1:(}{RBP2:(}42{RBP2:)}^ |
- ]], reset=true}
+ ]],
+ reset = true,
+ }
end)
- for _, func_part in ipairs({'', 'n', 'msg'}) do
+ for _, func_part in ipairs({ '', 'n', 'msg' }) do
it('disables :echo' .. func_part .. ' messages', function()
set_color_cb('Echo' .. func_part .. 'ing')
start_prompt('echo')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo^ |
]])
end)
end
- it('does the right thing when hl start appears to split multibyte char',
- function()
+ it('does the right thing when hl start appears to split multibyte char', function()
set_color_cb('SplitMultibyteStart')
start_prompt('echo "«')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*2
{MSEP: }|
:echo " |
{ERR:E5405: Chunk 0 start 7 splits multibyte }|
{ERR:character} |
:echo "«^ |
- ]]}
+ ]],
+ }
feed('»')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*2
{MSEP: }|
:echo " |
{ERR:E5405: Chunk 0 start 7 splits multibyte }|
@@ -321,14 +271,12 @@ describe('Command-line coloring', function()
:echo "«»^ |
]])
end)
- it('does the right thing when hl end appears to split multibyte char',
- function()
+ it('does the right thing when hl end appears to split multibyte char', function()
set_color_cb('SplitMultibyteEnd')
start_prompt('echo "«')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*2
{MSEP: }|
:echo " |
{ERR:E5406: Chunk 0 end 7 splits multibyte ch}|
@@ -355,12 +303,7 @@ describe('Command-line coloring', function()
start_prompt('e')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:e^ |
]])
eq('', exec_capture('messages'))
@@ -370,12 +313,7 @@ describe('Command-line coloring', function()
start_prompt('e')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:e^ |
]])
eq('', exec_capture('messages'))
@@ -385,12 +323,7 @@ describe('Command-line coloring', function()
start_prompt('e')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:e^ |
]])
eq('', exec_capture('messages'))
@@ -414,8 +347,7 @@ describe('Command-line coloring', function()
start_prompt('let x = "«»«»«»«»«»"')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*2
{MSEP: }|
:let x = " |
{ERR:E5405: Chunk 0 start 10 splits multibyte}|
@@ -425,38 +357,27 @@ describe('Command-line coloring', function()
feed('\n')
screen:expect([[
^ |
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
|
]])
feed('\n')
- eq('let x = "«»«»«»«»«»"', meths.get_var('out'))
+ eq('let x = "«»«»«»«»«»"', api.nvim_get_var('out'))
local msg = '\nE5405: Chunk 0 start 10 splits multibyte character'
- eq(msg:rep(1), funcs.execute('messages'))
+ eq(msg:rep(1), fn.execute('messages'))
end)
it('allows interrupting callback with <C-c>', function()
set_color_cb('Halting')
start_prompt('echo 42')
screen:expect([[
^ |
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
|
]])
screen:sleep(500)
feed('<C-c>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*2
{MSEP: }|
: |
{ERR:E5407: Callback has thrown an exception:}|
@@ -466,36 +387,21 @@ describe('Command-line coloring', function()
redraw_input()
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo 42^ |
]])
feed('\n')
screen:expect([[
^ |
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo 42 |
]])
feed('\n')
- eq('echo 42', meths.get_var('out'))
+ eq('echo 42', api.nvim_get_var('out'))
feed('<C-c>')
screen:expect([[
^ |
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
Type :qa and pre...nter> to exit Nvim |
]])
end)
@@ -504,12 +410,7 @@ describe('Command-line coloring', function()
start_prompt('echo ("<C-v><CR><C-v><Nul><C-v><NL>")')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo {RBP1:(}"{SK:^M^@^@}"{RBP1:)}^ |
]])
end)
@@ -519,9 +420,7 @@ describe('Command-line coloring', function()
start_prompt('#')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{MSEP: }|
: |
{ERR:E5400: Callback should return list} |
@@ -529,13 +428,11 @@ describe('Command-line coloring', function()
]])
feed('<CR><CR><CR>')
- set_color_cb('ReturningGlobal', {{0, 1, 'Normal'}, 42})
+ set_color_cb('ReturningGlobal', { { 0, 1, 'Normal' }, 42 })
start_prompt('#')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{MSEP: }|
: |
{ERR:E5401: List item 1 is not a List} |
@@ -543,12 +440,11 @@ describe('Command-line coloring', function()
]])
feed('<CR><CR><CR>')
- set_color_cb('ReturningGlobal2', {{0, 1, 'Normal'}, {1}})
+ set_color_cb('ReturningGlobal2', { { 0, 1, 'Normal' }, { 1 } })
start_prompt('+')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*2
{MSEP: }|
:+ |
{ERR:E5402: List item 1 has incorrect length:}|
@@ -557,12 +453,11 @@ describe('Command-line coloring', function()
]])
feed('<CR><CR><CR>')
- set_color_cb('ReturningGlobal2', {{0, 1, 'Normal'}, {2, 3, 'Normal'}})
+ set_color_cb('ReturningGlobal2', { { 0, 1, 'Normal' }, { 2, 3, 'Normal' } })
start_prompt('+')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*2
{MSEP: }|
:+ |
{ERR:E5403: Chunk 1 start 2 not in range [1, }|
@@ -571,13 +466,11 @@ describe('Command-line coloring', function()
]])
feed('<CR><CR><CR>')
- set_color_cb('ReturningGlobal2', {{0, 1, 'Normal'}, {1, 3, 'Normal'}})
+ set_color_cb('ReturningGlobal2', { { 0, 1, 'Normal' }, { 1, 3, 'Normal' } })
start_prompt('+')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{MSEP: }|
:+ |
{ERR:E5404: Chunk 1 end 3 not in range (1, 2]}|
@@ -585,7 +478,7 @@ describe('Command-line coloring', function()
]])
end)
it('does not error out when called from a errorred out cycle', function()
- set_color_cb('ReturningGlobal', {{0, 1, 'Normal'}})
+ set_color_cb('ReturningGlobal', { { 0, 1, 'Normal' } })
feed(dedent([[
:set regexpengine=2
:for pat in [' \ze*', ' \zs*']
@@ -607,117 +500,79 @@ describe('Command-line coloring', function()
:
:
]]))
- eq({'', ':', 'E888 detected for \\ze*', ':', 'E888 detected for \\zs*'},
- curbufmeths.get_lines(0, -1, false))
- eq('', funcs.execute('messages'))
+ eq(
+ { '', ':', 'E888 detected for \\ze*', ':', 'E888 detected for \\zs*' },
+ api.nvim_buf_get_lines(0, 0, -1, false)
+ )
+ eq('', fn.execute('messages'))
end)
it('allows nesting input()s', function()
- set_color_cb('ReturningGlobal', {{0, 1, 'RBP1'}}, '')
+ set_color_cb('ReturningGlobal', { { 0, 1, 'RBP1' } }, '')
start_prompt('1')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:{RBP1:1}^ |
]])
- set_color_cb('ReturningGlobal', {{0, 1, 'RBP2'}}, '1')
+ set_color_cb('ReturningGlobal', { { 0, 1, 'RBP2' } }, '1')
start_prompt('2')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:{RBP2:2}^ |
]])
- set_color_cb('ReturningGlobal', {{0, 1, 'RBP3'}}, '2')
+ set_color_cb('ReturningGlobal', { { 0, 1, 'RBP3' } }, '2')
start_prompt('3')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:{RBP3:3}^ |
]])
- set_color_cb('ReturningGlobal', {{0, 1, 'RBP4'}}, '3')
+ set_color_cb('ReturningGlobal', { { 0, 1, 'RBP4' } }, '3')
start_prompt('4')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:{RBP4:4}^ |
]])
feed('<CR>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:{RBP3:3}4^ |
]])
feed('<CR>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:{RBP2:2}34^ |
]])
feed('<CR>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:{RBP1:1}234^ |
]])
feed('<CR><CR><C-l>')
screen:expect([[
^ |
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
|
]])
- eq('1234', meths.get_var('out'))
- eq('234', meths.get_var('out1'))
- eq('34', meths.get_var('out2'))
- eq('4', meths.get_var('out3'))
- eq(0, funcs.exists('g:out4'))
+ eq('1234', api.nvim_get_var('out'))
+ eq('234', api.nvim_get_var('out1'))
+ eq('34', api.nvim_get_var('out2'))
+ eq('4', api.nvim_get_var('out3'))
+ eq(0, fn.exists('g:out4'))
end)
it('runs callback with the same data only once', function()
local function new_recording_calls(...)
- eq({...}, meths.get_var('recording_calls'))
- meths.set_var('recording_calls', {})
+ eq({ ... }, api.nvim_get_var('recording_calls'))
+ api.nvim_set_var('recording_calls', {})
end
set_color_cb('Recording')
start_prompt('')
@@ -726,22 +581,21 @@ describe('Command-line coloring', function()
-- new_recording_calls(expected_result) -- (actual_before_fix)
--
feed('a')
- new_recording_calls('a') -- ('a', 'a')
+ new_recording_calls('a') -- ('a', 'a')
feed('b')
new_recording_calls('ab') -- ('a', 'ab', 'ab')
feed('c')
- new_recording_calls('abc') -- ('ab', 'abc', 'abc')
+ new_recording_calls('abc') -- ('ab', 'abc', 'abc')
feed('<BS>')
- new_recording_calls('ab') -- ('abc', 'ab', 'ab')
+ new_recording_calls('ab') -- ('abc', 'ab', 'ab')
feed('<BS>')
- new_recording_calls('a') -- ('ab', 'a', 'a')
+ new_recording_calls('a') -- ('ab', 'a', 'a')
feed('<BS>')
- new_recording_calls() -- ('a')
+ new_recording_calls() -- ('a')
feed('<CR><CR>')
- eq('', meths.get_var('out'))
+ eq('', api.nvim_get_var('out'))
end)
- it('does not crash when callback has caught not-a-editor-command exception',
- function()
+ it('does not crash when callback has caught not-a-editor-command exception', function()
source([[
function CaughtExc(cmdline) abort
try
@@ -754,30 +608,25 @@ describe('Command-line coloring', function()
]])
set_color_cb('CaughtExc')
start_prompt('1')
- eq(1, meths.eval('1'))
+ eq(1, api.nvim_eval('1'))
end)
end)
describe('Ex commands coloring', function()
it('works', function()
- meths.set_var('Nvim_color_cmdline', 'RainBowParens')
+ api.nvim_set_var('Nvim_color_cmdline', 'RainBowParens')
feed(':echo (((1)))')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:echo {RBP1:(}{RBP2:(}{RBP3:(}1{RBP3:)}{RBP2:)}{RBP1:)}^ |
]])
end)
it('still executes command-line even if errored out', function()
- meths.set_var('Nvim_color_cmdline', 'SplitMultibyteStart')
+ api.nvim_set_var('Nvim_color_cmdline', 'SplitMultibyteStart')
feed(':let x = "«"\n')
- eq('«', meths.get_var('x'))
+ eq('«', api.nvim_get_var('x'))
local msg = 'E5405: Chunk 0 start 10 splits multibyte character'
- eq('\n'..msg, funcs.execute('messages'))
+ eq('\n' .. msg, fn.execute('messages'))
end)
it('does not error out when called from a errorred out cycle', function()
-- Apparently when there is a cycle in which one of the commands errors out
@@ -794,16 +643,17 @@ describe('Ex commands coloring', function()
: endtry
:endfor
]]))
- eq({'', 'E888 detected for \\ze*', 'E888 detected for \\zs*'},
- curbufmeths.get_lines(0, -1, false))
- eq('', funcs.execute('messages'))
+ eq(
+ { '', 'E888 detected for \\ze*', 'E888 detected for \\zs*' },
+ api.nvim_buf_get_lines(0, 0, -1, false)
+ )
+ eq('', fn.execute('messages'))
end)
it('does not crash when using `n` in debug mode', function()
feed(':debug execute "echo 1"\n')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*2
{MSEP: }|
Entering Debug mode. Type "cont" to con|
tinue. |
@@ -824,12 +674,7 @@ describe('Ex commands coloring', function()
feed('\n')
screen:expect([[
^ |
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
|
]])
end)
@@ -838,8 +683,7 @@ describe('Ex commands coloring', function()
feed(':#x')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*2
{MSEP: }|
:# |
{ERR:Error detected while processing :} |
@@ -858,11 +702,13 @@ describe('Ex commands coloring', function()
{PE:Press ENTER or type command to continue}^ |
]])
feed('<CR>')
- eq('Error detected while processing :\nE605: Exception not caught: 42\nE749: Empty buffer',
- exec_capture('messages'))
+ eq(
+ 'Error detected while processing :\nE605: Exception not caught: 42\nE749: Empty buffer',
+ exec_capture('messages')
+ )
end)
it('errors out when failing to get callback', function()
- meths.set_var('Nvim_color_cmdline', 42)
+ api.nvim_set_var('Nvim_color_cmdline', 42)
feed(':#')
screen:expect([[
|
@@ -878,77 +724,52 @@ describe('Ex commands coloring', function()
end)
describe('Expressions coloring support', function()
it('works', function()
- meths.command('hi clear NvimNumber')
- meths.command('hi clear NvimNestingParenthesis')
- meths.command('hi NvimNumber guifg=Blue2')
- meths.command('hi NvimNestingParenthesis guifg=Yellow')
+ command('hi clear NvimNumber')
+ command('hi clear NvimNestingParenthesis')
+ command('hi NvimNumber guifg=Blue2')
+ command('hi NvimNestingParenthesis guifg=Yellow')
feed(':echo <C-r>=(((1)))')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
={NPAR:(((}{NUM:1}{NPAR:)))}^ |
]])
end)
it('does not use Nvim_color_expr', function()
- meths.set_var('Nvim_color_expr', 42)
+ api.nvim_set_var('Nvim_color_expr', 42)
-- Used to error out due to failing to get callback.
- meths.command('hi clear NvimNumber')
- meths.command('hi NvimNumber guifg=Blue2')
+ command('hi clear NvimNumber')
+ command('hi NvimNumber guifg=Blue2')
feed(':<C-r>=1')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
={NUM:1}^ |
]])
end)
it('works correctly with non-ASCII and control characters', function()
- meths.command('hi clear NvimStringBody')
- meths.command('hi clear NvimStringQuote')
- meths.command('hi clear NvimInvalid')
- meths.command('hi NvimStringQuote guifg=Blue3')
- meths.command('hi NvimStringBody guifg=Blue4')
- meths.command('hi NvimInvalid guifg=Red guibg=Blue')
+ command('hi clear NvimStringBody')
+ command('hi clear NvimStringQuote')
+ command('hi clear NvimInvalid')
+ command('hi NvimStringQuote guifg=Blue3')
+ command('hi NvimStringBody guifg=Blue4')
+ command('hi NvimInvalid guifg=Red guibg=Blue')
feed('i<C-r>="«»"«»')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
={SQ:"}{SB:«»}{SQ:"}{E:«»}^ |
]])
feed('<C-c>')
screen:expect([[
^ |
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
{M:-- INSERT --} |
]])
feed('<Esc>')
screen:expect([[
^ |
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
|
]])
feed(':<C-\\>e"<C-v><C-x>"<C-v><C-x>')
@@ -956,35 +777,20 @@ describe('Expressions coloring support', function()
-- highlighting.
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
={SQ:"}{SB:^X}{SQ:"}{ERR:^X}^ |
]])
feed('<C-c>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
:^ |
]])
- funcs.setreg('a', {'\192'})
+ fn.setreg('a', { '\192' })
feed('<C-r>="<C-r><C-r>a"<C-r><C-r>a"foo"')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*6
={SQ:"}{SB:<c0>}{SQ:"}{E:<c0>"}{SB:foo}{E:"}^ |
]])
end)
diff --git a/test/functional/ui/cmdline_spec.lua b/test/functional/ui/cmdline_spec.lua
index 188b9ee87b..0eb5770819 100644
--- a/test/functional/ui/cmdline_spec.lua
+++ b/test/functional/ui/cmdline_spec.lua
@@ -9,22 +9,22 @@ local exec = helpers.exec
local eval = helpers.eval
local eq = helpers.eq
local is_os = helpers.is_os
-local meths = helpers.meths
+local api = helpers.api
local function new_screen(opt)
local screen = Screen.new(25, 5)
screen:attach(opt)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {reverse = true},
- [3] = {bold = true, reverse = true},
- [4] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [5] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [6] = {foreground = Screen.colors.Magenta},
- [7] = {bold = true, foreground = Screen.colors.Brown},
- [8] = {background = Screen.colors.LightGrey},
- [9] = {bold = true},
- [10] = {background = Screen.colors.Yellow1};
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { reverse = true },
+ [3] = { bold = true, reverse = true },
+ [4] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [5] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [6] = { foreground = Screen.colors.Magenta },
+ [7] = { bold = true, foreground = Screen.colors.Brown },
+ [8] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey },
+ [9] = { bold = true },
+ [10] = { background = Screen.colors.Yellow1 },
})
return screen
end
@@ -34,370 +34,445 @@ local function test_cmdline(linegrid)
before_each(function()
clear()
- screen = new_screen({rgb=true, ext_cmdline=true, ext_linegrid=linegrid})
+ screen = new_screen({ rgb = true, ext_cmdline = true, ext_linegrid = linegrid })
end)
it('works', function()
feed(':')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{""}},
- pos = 0,
- }}}
+ ]],
+ cmdline = { {
+ firstc = ':',
+ content = { { '' } },
+ pos = 0,
+ } },
+ }
feed('sign')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign"}},
- pos = 4,
- }}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign' } },
+ pos = 4,
+ },
+ },
+ }
feed('<Left>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign"}},
- pos = 3,
- }}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign' } },
+ pos = 3,
+ },
+ },
+ }
feed('<bs>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sin"}},
- pos = 2,
- }}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sin' } },
+ pos = 2,
+ },
+ },
+ }
feed('<Esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
end)
- it("works with input()", function()
+ it('works with input()', function()
feed(':call input("input", "default")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- prompt = "input",
- content = {{"default"}},
- pos = 7,
- }}}
+ ]],
+ cmdline = {
+ {
+ prompt = 'input',
+ content = { { 'default' } },
+ pos = 7,
+ },
+ },
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
end)
- it("works with special chars and nested cmdline", function()
+ it('works with special chars and nested cmdline', function()
feed(':xx<c-r>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"xx"}},
- pos = 2,
- special = {'"', true},
- }}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'xx' } },
+ pos = 2,
+ special = { '"', true },
+ },
+ },
+ }
feed('=')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"xx"}},
- pos = 2,
- special = {'"', true},
- }, {
- firstc = "=",
- content = {{""}},
- pos = 0,
- }}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'xx' } },
+ pos = 2,
+ special = { '"', true },
+ },
+ {
+ firstc = '=',
+ content = { { '' } },
+ pos = 0,
+ },
+ },
+ }
feed('1+2')
- local expectation = {{
- firstc = ":",
- content = {{"xx"}},
- pos = 2,
- special = {'"', true},
- }, {
- firstc = "=",
- content = {{"1", 6}, {"+", 7}, {"2", 6}},
- pos = 3,
- }}
-
- screen:expect{grid=[[
+ local expectation = {
+ {
+ firstc = ':',
+ content = { { 'xx' } },
+ pos = 2,
+ special = { '"', true },
+ },
+ {
+ firstc = '=',
+ content = { { '1', 6 }, { '+', 7 }, { '2', 6 } },
+ pos = 3,
+ },
+ }
+
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline=expectation}
+ ]],
+ cmdline = expectation,
+ }
-- erase information, so we check if it is retransmitted
- command("mode")
- screen:expect{grid=[[
+ command('mode')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline=expectation, reset=true}
-
+ ]],
+ cmdline = expectation,
+ reset = true,
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"xx3"}},
- pos = 3,
- }}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'xx3' } },
+ pos = 3,
+ },
+ },
+ }
feed('<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
end)
- it("works with function definitions", function()
+ it('works with function definitions', function()
feed(':function Foo()<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- indent = 2,
- firstc = ":",
- content = {{""}},
- pos = 0,
- }}, cmdline_block = {
- {{'function Foo()'}},
- }}
+ ]],
+ cmdline = {
+ {
+ indent = 2,
+ firstc = ':',
+ content = { { '' } },
+ pos = 0,
+ },
+ },
+ cmdline_block = {
+ { { 'function Foo()' } },
+ },
+ }
feed('line1<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- indent = 2,
- firstc = ":",
- content = {{""}},
- pos = 0,
- }}, cmdline_block = {
- {{'function Foo()'}},
- {{' line1'}},
- }}
-
- command("mode")
- screen:expect{grid=[[
+ ]],
+ cmdline = {
+ {
+ indent = 2,
+ firstc = ':',
+ content = { { '' } },
+ pos = 0,
+ },
+ },
+ cmdline_block = {
+ { { 'function Foo()' } },
+ { { ' line1' } },
+ },
+ }
+
+ command('mode')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- indent = 2,
- firstc = ":",
- content = {{""}},
- pos = 0,
- }}, cmdline_block = {
- {{'function Foo()'}},
- {{' line1'}},
- }, reset=true}
+ ]],
+ cmdline = {
+ {
+ indent = 2,
+ firstc = ':',
+ content = { { '' } },
+ pos = 0,
+ },
+ },
+ cmdline_block = {
+ { { 'function Foo()' } },
+ { { ' line1' } },
+ },
+ reset = true,
+ }
feed('endfunction<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
-- Try once more, to check buffer is reinitialized. #8007
feed(':function Bar()<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- indent = 2,
- firstc = ":",
- content = {{""}},
- pos = 0,
- }}, cmdline_block = {
- {{'function Bar()'}},
- }}
+ ]],
+ cmdline = {
+ {
+ indent = 2,
+ firstc = ':',
+ content = { { '' } },
+ pos = 0,
+ },
+ },
+ cmdline_block = {
+ { { 'function Bar()' } },
+ },
+ }
feed('endfunction<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
-
+ ]],
+ }
end)
- it("works with cmdline window", function()
+ it('works with cmdline window', function()
feed(':make')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"make"}},
- pos = 4,
- }}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'make' } },
+ pos = 4,
+ },
+ },
+ }
feed('<c-f>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{2:[No Name] }|
{1::}mak^e |
{3:[Command Line] }|
|
- ]]}
+ ]],
+ }
-- nested cmdline
feed(':yank')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{2:[No Name] }|
{1::}mak^e |
{3:[Command Line] }|
|
- ]], cmdline={nil, {
- firstc = ":",
- content = {{"yank"}},
- pos = 4,
- }}}
-
- command("mode")
- screen:expect{grid=[[
+ ]],
+ cmdline = {
+ nil,
+ {
+ firstc = ':',
+ content = { { 'yank' } },
+ pos = 4,
+ },
+ },
+ }
+
+ command('mode')
+ screen:expect {
+ grid = [[
|
{2:[No Name] }|
{1::}mak^e |
{3:[Command Line] }|
|
- ]], cmdline={nil, {
- firstc = ":",
- content = {{"yank"}},
- pos = 4,
- }}, reset=true}
-
- feed("<c-c>")
- screen:expect{grid=[[
+ ]],
+ cmdline = {
+ nil,
+ {
+ firstc = ':',
+ content = { { 'yank' } },
+ pos = 4,
+ },
+ },
+ reset = true,
+ }
+
+ feed('<c-c>')
+ screen:expect {
+ grid = [[
|
{2:[No Name] }|
{1::}mak^e |
{3:[Command Line] }|
|
- ]]}
+ ]],
+ }
- feed("<c-c>")
- screen:expect{grid=[[
+ feed('<c-c>')
+ screen:expect {
+ grid = [[
^ |
{2:[No Name] }|
{1::}make |
{3:[Command Line] }|
|
- ]], cmdline={{
- firstc = ":",
- content = {{"make"}},
- pos = 4,
- }}}
-
- command("redraw!")
- screen:expect{grid=[[
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'make' } },
+ pos = 4,
+ },
+ },
+ }
+
+ command('redraw!')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"make"}},
- pos = 4,
- }}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'make' } },
+ pos = 4,
+ },
+ },
+ }
end)
it('works with inputsecret()', function()
feed(":call inputsecret('secret:')<cr>abc123")
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- prompt = "secret:",
- content = {{"******"}},
- pos = 6,
- }}}
+ ]],
+ cmdline = {
+ {
+ prompt = 'secret:',
+ content = { { '******' } },
+ pos = 6,
+ },
+ },
+ }
end)
it('works with highlighted cmdline', function()
@@ -427,23 +502,33 @@ local function test_cmdline(linegrid)
"map <f5> :let x = input({'prompt':'>'})<cr>
]])
screen:set_default_attr_ids({
- RBP1={background = Screen.colors.Red},
- RBP2={background = Screen.colors.Yellow},
- EOB={bold = true, foreground = Screen.colors.Blue1},
+ RBP1 = { background = Screen.colors.Red },
+ RBP2 = { background = Screen.colors.Yellow },
+ EOB = { bold = true, foreground = Screen.colors.Blue1 },
})
feed('<f5>(a(b)a)')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
|
- ]], cmdline={{
- prompt = '>',
- content = {{'(', 'RBP1'}, {'a'}, {'(', 'RBP2'}, {'b'},
- { ')', 'RBP2'}, {'a'}, {')', 'RBP1'}},
- pos = 7,
- }}}
+ ]],
+ cmdline = {
+ {
+ prompt = '>',
+ content = {
+ { '(', 'RBP1' },
+ { 'a' },
+ { '(', 'RBP2' },
+ { 'b' },
+ { ')', 'RBP2' },
+ { 'a' },
+ { ')', 'RBP1' },
+ },
+ pos = 7,
+ },
+ },
+ }
end)
it('works together with ext_wildmenu', function()
@@ -461,79 +546,102 @@ local function test_cmdline(linegrid)
screen:set_option('ext_wildmenu', true)
feed(':sign <tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign define"}},
- pos = 11,
- }}, wildmenu_items=expected, wildmenu_pos=0}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign define' } },
+ pos = 11,
+ },
+ },
+ wildmenu_items = expected,
+ wildmenu_pos = 0,
+ }
feed('<tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign jump"}},
- pos = 9,
- }}, wildmenu_items=expected, wildmenu_pos=1}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign jump' } },
+ pos = 9,
+ },
+ },
+ wildmenu_items = expected,
+ wildmenu_pos = 1,
+ }
feed('<left><left>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign "}},
- pos = 5,
- }}, wildmenu_items=expected, wildmenu_pos=-1}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign ' } },
+ pos = 5,
+ },
+ },
+ wildmenu_items = expected,
+ wildmenu_pos = -1,
+ }
feed('<right>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign define"}},
- pos = 11,
- }}, wildmenu_items=expected, wildmenu_pos=0}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign define' } },
+ pos = 11,
+ },
+ },
+ wildmenu_items = expected,
+ wildmenu_pos = 0,
+ }
feed('a')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign definea"}},
- pos = 12,
- }}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign definea' } },
+ pos = 12,
+ },
+ },
+ }
end)
it('works together with ext_popupmenu', function()
local expected = {
- {'define', '', '', ''},
- {'jump', '', '', ''},
- {'list', '', '', ''},
- {'place', '', '', ''},
- {'undefine', '', '', ''},
- {'unplace', '', '', ''},
+ { 'define', '', '', '' },
+ { 'jump', '', '', '' },
+ { 'list', '', '', '' },
+ { 'place', '', '', '' },
+ { 'undefine', '', '', '' },
+ { 'unplace', '', '', '' },
}
command('set wildmode=full')
@@ -541,90 +649,115 @@ local function test_cmdline(linegrid)
screen:set_option('ext_popupmenu', true)
feed(':sign <tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign define"}},
- pos = 11,
- }}, popupmenu={items=expected, pos=0, anchor={-1, 0, 5}}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign define' } },
+ pos = 11,
+ },
+ },
+ popupmenu = { items = expected, pos = 0, anchor = { -1, 0, 5 } },
+ }
feed('<tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign jump"}},
- pos = 9,
- }}, popupmenu={items=expected, pos=1, anchor={-1, 0, 5}}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign jump' } },
+ pos = 9,
+ },
+ },
+ popupmenu = { items = expected, pos = 1, anchor = { -1, 0, 5 } },
+ }
feed('<left><left>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign "}},
- pos = 5,
- }}, popupmenu={items=expected, pos=-1, anchor={-1, 0, 5}}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign ' } },
+ pos = 5,
+ },
+ },
+ popupmenu = { items = expected, pos = -1, anchor = { -1, 0, 5 } },
+ }
feed('<right>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign define"}},
- pos = 11,
- }}, popupmenu={items=expected, pos=0, anchor={-1, 0, 5}}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign define' } },
+ pos = 11,
+ },
+ },
+ popupmenu = { items = expected, pos = 0, anchor = { -1, 0, 5 } },
+ }
feed('a')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign definea"}},
- pos = 12,
- }}}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign definea' } },
+ pos = 12,
+ },
+ },
+ }
feed('<esc>')
-- check positioning with multibyte char in pattern
- command("e långfile1")
- command("sp långfile2")
+ command('e långfile1')
+ command('sp långfile2')
feed(':b lå<tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
{3:långfile2 }|
|
{2:långfile1 }|
|
- ]], popupmenu={
- anchor = { -1, 0, 2 },
- items = {{ "långfile1", "", "", "" }, { "långfile2", "", "", "" }},
- pos = 0
- }, cmdline={{
- content = {{ "b långfile1" }},
- firstc = ":",
- pos = 12
- }}}
+ ]],
+ popupmenu = {
+ anchor = { -1, 0, 2 },
+ items = { { 'långfile1', '', '', '' }, { 'långfile2', '', '', '' } },
+ pos = 0,
+ },
+ cmdline = {
+ {
+ content = { { 'b långfile1' } },
+ firstc = ':',
+ pos = 12,
+ },
+ },
+ }
end)
it('ext_wildmenu takes precedence over ext_popupmenu', function()
@@ -643,17 +776,22 @@ local function test_cmdline(linegrid)
screen:set_option('ext_popupmenu', true)
feed(':sign <tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- firstc = ":",
- content = {{"sign define"}},
- pos = 11,
- }}, wildmenu_items=expected, wildmenu_pos=0}
+ ]],
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'sign define' } },
+ pos = 11,
+ },
+ },
+ wildmenu_items = expected,
+ wildmenu_pos = 0,
+ }
end)
it("doesn't send invalid events when aborting mapping #10000", function()
@@ -661,85 +799,100 @@ local function test_cmdline(linegrid)
command('cnoremap ab c')
feed(':xa')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]], cmdline={{
- content = { { "x" } },
- firstc = ":",
- pos = 1,
- special = { "a", false }
- }}}
+ ]],
+ cmdline = {
+ {
+ content = { { 'x' } },
+ firstc = ':',
+ pos = 1,
+ special = { 'a', false },
+ },
+ },
+ }
-- This used to send an invalid event where pos where larger than the total
-- length of content. Checked in _handle_cmdline_show.
feed('<esc>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
end)
-
end
-- the representation of cmdline and cmdline_block contents changed with ext_linegrid
-- (which uses indexed highlights) so make sure to test both
-describe('ui/ext_cmdline', function() test_cmdline(true) end)
-describe('ui/ext_cmdline (legacy highlights)', function() test_cmdline(false) end)
+describe('ui/ext_cmdline', function()
+ test_cmdline(true)
+end)
+describe('ui/ext_cmdline (legacy highlights)', function()
+ test_cmdline(false)
+end)
describe('cmdline redraw', function()
local screen
before_each(function()
clear()
- screen = new_screen({rgb=true})
+ screen = new_screen({ rgb = true })
end)
it('with timer', function()
feed(':012345678901234567890123456789')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{3: }|
:012345678901234567890123|
456789^ |
- ]]}
+ ]],
+ }
command('call timer_start(0, {-> 1})')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{3: }|
:012345678901234567890123|
456789^ |
- ]], unchanged=true, timeout=100}
+ ]],
+ unchanged = true,
+ timeout = 100,
+ }
end)
it('with <Cmd>', function()
if is_os('bsd') then
pending('FIXME #10804')
end
- command('cmap a <Cmd>call sin(0)<CR>') -- no-op
+ command('cmap a <Cmd>call sin(0)<CR>') -- no-op
feed(':012345678901234567890123456789')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{3: }|
:012345678901234567890123|
456789^ |
- ]]}
+ ]],
+ }
feed('a')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{3: }|
:012345678901234567890123|
456789^ |
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
end)
it('after pressing Ctrl-C in cmdwin in Visual mode #18967', function()
@@ -748,26 +901,20 @@ describe('cmdline redraw', function()
feed('q:iabc<Esc>vhh')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:[No Name] }|
{1::}^a{8:bc} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:[Command Line] }|
{9:-- VISUAL --} |
]])
feed('<C-C>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:[No Name] }|
{1::}a{8:bc} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:[Command Line] }|
:^abc |
]])
@@ -775,80 +922,80 @@ describe('cmdline redraw', function()
it('with rightleftcmd', function()
command('set rightleft rightleftcmd=search shortmess+=s')
- meths.buf_set_lines(0, 0, -1, true, {"let's rock!"})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(0, 0, -1, true, { "let's rock!" })
+ screen:expect {
+ grid = [[
!kcor s'te^l|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*3
|
- ]]}
+ ]],
+ }
feed '/'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
!kcor s'tel|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*3
^ /|
- ]]}
+ ]],
+ }
feed "let's"
-- note: cursor looks off but looks alright in real use
-- when rendered as a block so it touches the end of the text
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
!kcor {2:s'tel}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*3
^ s'tel/|
- ]]}
+ ]],
+ }
-- cursor movement
- feed "<space>"
- screen:expect{grid=[[
+ feed '<space>'
+ screen:expect {
+ grid = [[
!kcor{2: s'tel}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*3
^ s'tel/|
- ]]}
+ ]],
+ }
- feed "rock"
- screen:expect{grid=[[
+ feed 'rock'
+ screen:expect {
+ grid = [[
!{2:kcor s'tel}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*3
^ kcor s'tel/|
- ]]}
+ ]],
+ }
- feed "<right>"
- screen:expect{grid=[[
+ feed '<right>'
+ screen:expect {
+ grid = [[
!{2:kcor s'tel}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*3
^kcor s'tel/|
- ]]}
+ ]],
+ }
- feed "<left>"
- screen:expect{grid=[[
+ feed '<left>'
+ screen:expect {
+ grid = [[
!{2:kcor s'tel}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*3
^ kcor s'tel/|
- ]]}
+ ]],
+ }
- feed "<cr>"
- screen:expect{grid=[[
+ feed '<cr>'
+ screen:expect {
+ grid = [[
!{10:kcor s'te^l}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*3
kcor s'tel/ |
- ]]}
+ ]],
+ }
end)
end)
@@ -863,48 +1010,52 @@ describe('statusline is redrawn on entering cmdline', function()
it('from normal mode', function()
command('set statusline=%{mode()}')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:n }|
|
- ]]}
+ ]],
+ }
feed(':')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:c }|
:^ |
- ]]}
+ ]],
+ }
end)
it('from normal mode when : is mapped', function()
command('set statusline=%{mode()}')
command('nnoremap ; :')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:n }|
|
- ]]}
+ ]],
+ }
feed(';')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:c }|
:^ |
- ]]}
+ ]],
+ }
end)
it('with scrolled messages', function()
- screen:try_resize(35,14)
+ screen:try_resize(35, 14)
exec([[
let g:count = 0
autocmd CmdlineEnter * let g:count += 1
@@ -914,30 +1065,28 @@ describe('statusline is redrawn on entering cmdline', function()
setlocal winbar=%{mode()}%{g:count}
]])
feed(':echoerr doesnotexist<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{9:c1 }|
|
{3:c1 }|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{3: }|
{4:E121: Undefined variable: doesnotex}|
{4:ist} |
{5:Press ENTER or type command to cont}|
{5:inue}^ |
- ]]}
+ ]],
+ }
feed(':echoerr doesnotexist<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{9:c2 }|
|
{3:c2 }|
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3: }|
{4:E121: Undefined variable: doesnotex}|
{4:ist} |
@@ -946,10 +1095,12 @@ describe('statusline is redrawn on entering cmdline', function()
{4:ist} |
{5:Press ENTER or type command to cont}|
{5:inue}^ |
- ]]}
+ ]],
+ }
feed(':echoerr doesnotexist<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{9:c3 }|
|
{3:c3 }|
@@ -964,61 +1115,60 @@ describe('statusline is redrawn on entering cmdline', function()
{4:ist} |
{5:Press ENTER or type command to cont}|
{5:inue}^ |
- ]]}
+ ]],
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{9:n3 }|
^ |
{3:n3 }|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
{2:[No Name] }|
|
- ]]}
+ ]],
+ }
end)
describe('if custom statusline is set by', function()
before_each(function()
command('set statusline=')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:[No Name] }|
|
- ]]}
+ ]],
+ }
end)
it('CmdlineEnter autocommand', function()
command('autocmd CmdlineEnter * set statusline=command')
feed(':')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:command }|
:^ |
- ]]}
+ ]],
+ }
end)
it('ModeChanged autocommand', function()
command('autocmd ModeChanged *:c set statusline=command')
feed(':')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:command }|
:^ |
- ]]}
+ ]],
+ }
end)
end)
end)
@@ -1027,9 +1177,9 @@ it('tabline is not redrawn in Ex mode #24122', function()
clear()
local screen = Screen.new(60, 5)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, reverse = true}, -- MsgSeparator
- [2] = {reverse = true}, -- TabLineFill
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, reverse = true }, -- MsgSeparator
+ [2] = { reverse = true }, -- TabLineFill
})
screen:attach()
@@ -1044,28 +1194,32 @@ it('tabline is not redrawn in Ex mode #24122', function()
]])
feed('gQ')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:foo }|
|
{1: }|
Entering Ex mode. Type "visual" to go to Normal mode. |
:^ |
- ]]}
+ ]],
+ }
feed('echo 1<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }|
Entering Ex mode. Type "visual" to go to Normal mode. |
:echo 1 |
1 |
:^ |
- ]]}
+ ]],
+ }
end)
-describe("cmdline height", function()
+describe('cmdline height', function()
before_each(clear)
- it("does not crash resized screen #14263", function()
+ it('does not crash resized screen #14263', function()
local screen = Screen.new(25, 10)
screen:attach()
command('set cmdheight=9999')
@@ -1089,329 +1243,341 @@ describe('cmdheight=0', function()
clear()
screen = Screen.new(25, 5)
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Blue};
- [2] = {bold = true, reverse = true};
- [3] = {bold = true};
- [4] = {foreground = Screen.colors.White, background = Screen.colors.Red};
- [5] = {foreground = Screen.colors.SeaGreen4, bold = true};
- [6] = {reverse = true};
- [7] = {background = Screen.colors.Yellow};
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { bold = true, reverse = true },
+ [3] = { bold = true },
+ [4] = { foreground = Screen.colors.White, background = Screen.colors.Red },
+ [5] = { foreground = Screen.colors.SeaGreen4, bold = true },
+ [6] = { reverse = true },
+ [7] = { background = Screen.colors.Yellow },
}
screen:attach()
end)
- it("with redrawdebug=invalid resize -1", function()
- command("set redrawdebug=invalid cmdheight=0 noruler laststatus=0")
- screen:expect{grid=[[
+ it('with redrawdebug=invalid resize -1', function()
+ command('set redrawdebug=invalid cmdheight=0 noruler laststatus=0')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
- feed(":resize -1<CR>")
- screen:expect{grid=[[
+ {1:~ }|*4
+ ]],
+ }
+ feed(':resize -1<CR>')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
assert_alive()
end)
- it("with cmdheight=1 noruler laststatus=2", function()
- command("set cmdheight=1 noruler laststatus=2")
- screen:expect{grid=[[
+ it('with cmdheight=1 noruler laststatus=2', function()
+ command('set cmdheight=1 noruler laststatus=2')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:[No Name] }|
|
- ]]}
+ ]],
+ }
end)
- it("with cmdheight=0 noruler laststatus=2", function()
- command("set cmdheight=0 noruler laststatus=2")
- screen:expect{grid=[[
+ it('with cmdheight=0 noruler laststatus=2', function()
+ command('set cmdheight=0 noruler laststatus=2')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:[No Name] }|
- ]]}
+ ]],
+ }
end)
- it("with cmdheight=0 ruler laststatus=0", function()
- command("set cmdheight=0 ruler laststatus=0")
- screen:expect{grid=[[
+ it('with cmdheight=0 ruler laststatus=0', function()
+ command('set cmdheight=0 ruler laststatus=0')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
end)
- it("with cmdheight=0 ruler laststatus=0", function()
- command("set cmdheight=0 noruler laststatus=0 showmode")
+ it('with cmdheight=0 ruler laststatus=0', function()
+ command('set cmdheight=0 noruler laststatus=0 showmode')
feed('i')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={}}
+ {1:~ }|*4
+ ]],
+ showmode = {},
+ }
feed('<Esc>')
eq(0, eval('&cmdheight'))
end)
- it("with cmdheight=0 ruler rulerformat laststatus=0", function()
- command("set cmdheight=0 noruler laststatus=0 rulerformat=%l,%c%= showmode")
+ it('with cmdheight=0 ruler rulerformat laststatus=0', function()
+ command('set cmdheight=0 noruler laststatus=0 rulerformat=%l,%c%= showmode')
feed('i')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={}}
+ {1:~ }|*4
+ ]],
+ showmode = {},
+ }
feed('<Esc>')
eq(0, eval('&cmdheight'))
end)
- it("with showmode", function()
- command("set cmdheight=1 noruler laststatus=0 showmode")
+ it('with showmode', function()
+ command('set cmdheight=1 noruler laststatus=0 showmode')
feed('i')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{3:-- INSERT --} |
- ]]}
+ ]],
+ }
feed('<Esc>')
eq(1, eval('&cmdheight'))
end)
- it("when using command line", function()
- command("set cmdheight=0 noruler laststatus=0")
+ it('when using command line', function()
+ command('set cmdheight=0 noruler laststatus=0')
feed(':')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
:^ |
- ]]}
+ ]],
+ }
eq(0, eval('&cmdheight'))
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={}}
+ {1:~ }|*4
+ ]],
+ showmode = {},
+ }
eq(0, eval('&cmdheight'))
end)
- it("when using input()", function()
- command("set cmdheight=0 noruler laststatus=0")
+ it('when using input()', function()
+ command('set cmdheight=0 noruler laststatus=0')
feed(':call input("foo >")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{2: }|
:call input("foo >") |
foo >^ |
- ]]}
+ ]],
+ }
eq(0, eval('&cmdheight'))
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={}}
+ {1:~ }|*4
+ ]],
+ showmode = {},
+ }
eq(0, eval('&cmdheight'))
end)
- it("with winbar and splits", function()
- command("set cmdheight=0 noruler laststatus=3 winbar=foo")
+ it('with winbar and splits', function()
+ command('set cmdheight=0 noruler laststatus=3 winbar=foo')
feed(':split<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2: }|
:split |
{4:E36: Not enough room} |
{5:Press ENTER or type comma}|
{5:nd to continue}^ |
- ]]}
+ ]],
+ }
feed('<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:foo }|
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:[No Name] }|
- ]]}
+ ]],
+ }
feed(':')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:foo }|
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
:^ |
- ]]}
+ ]],
+ }
feed('<Esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:foo }|
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:[No Name] }|
- ]], showmode={}}
+ ]],
+ showmode = {},
+ }
eq(0, eval('&cmdheight'))
assert_alive()
end)
- it("when macro with lastline", function()
- command("set cmdheight=0 display=lastline")
+ it('when macro with lastline', function()
+ command('set cmdheight=0 display=lastline')
feed('qq')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
feed('q')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], unchanged=true}
+ {1:~ }|*4
+ ]],
+ unchanged = true,
+ }
end)
- it("when substitute text", function()
- command("set cmdheight=0 noruler laststatus=3")
+ it('when substitute text', function()
+ command('set cmdheight=0 noruler laststatus=3')
feed('ifoo<ESC>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
fo^o |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:[No Name] [+] }|
- ]]}
+ ]],
+ }
feed(':%s/foo/bar/gc<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{6:foo} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{5:replace wi...q/l/^E/^Y)?}^ |
- ]]}
+ ]],
+ }
feed('y')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^bar |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:[No Name] [+] }|
- ]]}
+ ]],
+ }
assert_alive()
end)
- it("when window resize", function()
- command("set cmdheight=0")
+ it('when window resize', function()
+ command('set cmdheight=0')
feed('<C-w>+')
eq(0, eval('&cmdheight'))
end)
- it("with non-silent mappings with cmdline", function()
- command("set cmdheight=0")
- command("map <f3> :nohlsearch<cr>")
+ it('with non-silent mappings with cmdline', function()
+ command('set cmdheight=0')
+ command('map <f3> :nohlsearch<cr>')
feed('iaabbaa<esc>/aa<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{7:^aa}bb{7:aa} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
feed('<f3>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^aabbaa |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
end)
it('with silent! at startup', function()
- clear{args={'-c', 'set cmdheight=0', '-c', 'autocmd VimEnter * silent! call Foo()'}}
+ clear { args = { '-c', 'set cmdheight=0', '-c', 'autocmd VimEnter * silent! call Foo()' } }
screen:attach()
-- doesn't crash while not displaying silent! error message
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
end)
it('with multigrid', function()
- clear{args={'--cmd', 'set cmdheight=0'}}
- screen:attach{ext_multigrid=true}
- meths.buf_set_lines(0, 0, -1, true, {'p'})
- screen:expect{grid=[[
+ clear { args = { '--cmd', 'set cmdheight=0' } }
+ screen:attach { ext_multigrid = true }
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'p' })
+ screen:expect {
+ grid = [[
## grid 1
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
+ [2:-------------------------]|*5
## grid 2
^p |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 0,
+ botline = 2,
+ curline = 0,
+ curcol = 0,
+ linecount = 1,
+ sum_scroll_delta = 0,
+ },
+ },
+ }
feed '/p'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
+ [2:-------------------------]|*4
[3:-------------------------]|
## grid 2
{6:p} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
/p^ |
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 0,
+ botline = 2,
+ curline = 0,
+ curcol = 0,
+ linecount = 1,
+ sum_scroll_delta = 0,
+ },
+ },
+ }
end)
it('winbar is redrawn on entering cmdline and :redrawstatus #20336', function()
@@ -1423,8 +1589,7 @@ describe('cmdheight=0', function()
screen:expect([[
{3:c :}|
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
:^ |
]])
feed('echo')
@@ -1432,16 +1597,14 @@ describe('cmdheight=0', function()
screen:expect([[
{3:c :}|
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
:echo^ |
]])
command('redrawstatus')
screen:expect([[
{3:c :echo}|
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
:echo^ |
]])
end)
@@ -1452,28 +1615,17 @@ describe('cmdheight=0', function()
command('vsplit')
screen:expect([[
^ │ |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*8
]])
feed(':')
command('split')
feed('<Esc>')
screen:expect([[
^ │ |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*3
{2:[No Name] }│{1:~ }|
│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*3
]])
command('resize 2')
screen:expect([[
@@ -1481,25 +1633,17 @@ describe('cmdheight=0', function()
{1:~ }│{1:~ }|
{2:[No Name] }│{1:~ }|
│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*5
]])
feed(':')
command('wincmd =')
feed('<Esc>')
screen:expect([[
^ │ |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*3
{2:[No Name] }│{1:~ }|
│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*3
]])
end)
@@ -1508,10 +1652,7 @@ describe('cmdheight=0', function()
feed('d')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]])
assert_alive()
end)
@@ -1521,52 +1662,48 @@ describe('cmdheight=0', function()
command('resize +1')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:[No Name] }|
|
]])
command('set cmdheight=0')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:[No Name] }|
- ]]}
+ ]],
+ }
command('resize -1')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:[No Name] }|
|
- ]]}
+ ]],
+ }
command('resize +1')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:[No Name] }|
]])
end)
- it("cannot be resized at all with external messages", function()
+ it('cannot be resized at all with external messages', function()
clear()
- screen = new_screen({rgb=true, ext_messages=true})
+ screen = new_screen({ rgb = true, ext_messages = true })
command('set laststatus=2 mouse=a')
command('resize -1')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{3:[No Name] }|
]])
- meths.input_mouse('left', 'press', '', 0, 6, 10)
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 10)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 0, 5, 10)
+ api.nvim_input_mouse('left', 'drag', '', 0, 5, 10)
screen:expect_unchanged()
end)
end)
diff --git a/test/functional/ui/cursor_spec.lua b/test/functional/ui/cursor_spec.lua
index 05057ca080..871e9a0790 100644
--- a/test/functional/ui/cursor_spec.lua
+++ b/test/functional/ui/cursor_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, meths = helpers.clear, helpers.meths
+local clear, api = helpers.clear, helpers.api
local eq = helpers.eq
local command = helpers.command
@@ -27,7 +27,8 @@ describe('ui/cursor', function()
attr = {},
attr_lm = {},
mouse_shape = 0,
- short_name = 'n' },
+ short_name = 'n',
+ },
[2] = {
blinkoff = 0,
blinkon = 0,
@@ -40,7 +41,8 @@ describe('ui/cursor', function()
attr = {},
attr_lm = {},
mouse_shape = 0,
- short_name = 'v' },
+ short_name = 'v',
+ },
[3] = {
blinkoff = 0,
blinkon = 0,
@@ -53,7 +55,8 @@ describe('ui/cursor', function()
attr = {},
attr_lm = {},
mouse_shape = 0,
- short_name = 'i' },
+ short_name = 'i',
+ },
[4] = {
blinkoff = 0,
blinkon = 0,
@@ -66,7 +69,8 @@ describe('ui/cursor', function()
attr = {},
attr_lm = {},
mouse_shape = 0,
- short_name = 'r' },
+ short_name = 'r',
+ },
[5] = {
blinkoff = 0,
blinkon = 0,
@@ -79,7 +83,8 @@ describe('ui/cursor', function()
attr = {},
attr_lm = {},
mouse_shape = 0,
- short_name = 'c' },
+ short_name = 'c',
+ },
[6] = {
blinkoff = 0,
blinkon = 0,
@@ -92,7 +97,8 @@ describe('ui/cursor', function()
attr = {},
attr_lm = {},
mouse_shape = 0,
- short_name = 'ci' },
+ short_name = 'ci',
+ },
[7] = {
blinkoff = 0,
blinkon = 0,
@@ -105,7 +111,8 @@ describe('ui/cursor', function()
attr = {},
attr_lm = {},
mouse_shape = 0,
- short_name = 'cr' },
+ short_name = 'cr',
+ },
[8] = {
blinkoff = 0,
blinkon = 0,
@@ -118,7 +125,8 @@ describe('ui/cursor', function()
attr = {},
attr_lm = {},
mouse_shape = 0,
- short_name = 'o' },
+ short_name = 'o',
+ },
[9] = {
blinkoff = 0,
blinkon = 0,
@@ -131,35 +139,43 @@ describe('ui/cursor', function()
attr = {},
attr_lm = {},
mouse_shape = 0,
- short_name = 've' },
+ short_name = 've',
+ },
[10] = {
name = 'cmdline_hover',
mouse_shape = 0,
- short_name = 'e' },
+ short_name = 'e',
+ },
[11] = {
name = 'statusline_hover',
mouse_shape = 0,
- short_name = 's' },
+ short_name = 's',
+ },
[12] = {
name = 'statusline_drag',
mouse_shape = 0,
- short_name = 'sd' },
+ short_name = 'sd',
+ },
[13] = {
name = 'vsep_hover',
mouse_shape = 0,
- short_name = 'vs' },
+ short_name = 'vs',
+ },
[14] = {
name = 'vsep_drag',
mouse_shape = 0,
- short_name = 'vd' },
+ short_name = 'vd',
+ },
[15] = {
name = 'more',
mouse_shape = 0,
- short_name = 'm' },
+ short_name = 'm',
+ },
[16] = {
name = 'more_lastline',
mouse_shape = 0,
- short_name = 'ml' },
+ short_name = 'ml',
+ },
[17] = {
blinkoff = 0,
blinkon = 0,
@@ -171,8 +187,9 @@ describe('ui/cursor', function()
id_lm = 0,
attr = {},
attr_lm = {},
- short_name = 'sm' },
- }
+ short_name = 'sm',
+ },
+ }
screen:expect(function()
-- Default 'guicursor', published on startup.
@@ -184,38 +201,55 @@ describe('ui/cursor', function()
-- Event is published ONLY if the cursor style changed.
screen._mode_info = nil
command("echo 'test'")
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
test |
- ]], condition=function()
- eq(nil, screen._mode_info)
- end}
+ ]],
+ condition = function()
+ eq(nil, screen._mode_info)
+ end,
+ }
-- Change the cursor style.
helpers.command('hi Cursor guibg=DarkGray')
- helpers.command('set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr-o:hor20'
- ..',a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor'
- ..',sm:block-blinkwait175-blinkoff150-blinkon175')
+ helpers.command(
+ 'set guicursor=n-v-c:block,i-ci-ve:ver25,r-cr-o:hor20'
+ .. ',a:blinkwait700-blinkoff400-blinkon250-Cursor/lCursor'
+ .. ',sm:block-blinkwait175-blinkoff150-blinkon175'
+ )
-- Update the expected values.
for _, m in ipairs(expected_mode_info) do
if m.name == 'showmatch' then
- if m.blinkon then m.blinkon = 175 end
- if m.blinkoff then m.blinkoff = 150 end
- if m.blinkwait then m.blinkwait = 175 end
+ if m.blinkon then
+ m.blinkon = 175
+ end
+ if m.blinkoff then
+ m.blinkoff = 150
+ end
+ if m.blinkwait then
+ m.blinkwait = 175
+ end
else
- if m.blinkon then m.blinkon = 250 end
- if m.blinkoff then m.blinkoff = 400 end
- if m.blinkwait then m.blinkwait = 700 end
+ if m.blinkon then
+ m.blinkon = 250
+ end
+ if m.blinkoff then
+ m.blinkoff = 400
+ end
+ if m.blinkwait then
+ m.blinkwait = 700
+ end
end
if m.hl_id then
- m.hl_id = 64
- m.attr = {background = Screen.colors.DarkGray}
+ m.hl_id = 64
+ m.attr = { background = Screen.colors.DarkGray }
+ end
+ if m.id_lm then
+ m.id_lm = 69
end
- if m.id_lm then m.id_lm = 67 end
end
-- Assert the new expectation.
@@ -232,10 +266,10 @@ describe('ui/cursor', function()
-- Update the expected values.
for _, m in ipairs(expected_mode_info) do
if m.hl_id then
- m.attr = {background = Screen.colors.Red}
+ m.attr = { background = Screen.colors.Red }
end
if m.id_lm then
- m.attr_lm = {background = Screen.colors.Green}
+ m.attr_lm = { background = Screen.colors.Green }
end
end
-- Assert the new expectation.
@@ -250,23 +284,27 @@ describe('ui/cursor', function()
for _, m in ipairs(expected_mode_info) do
if m.hl_id then
- m.attr = {background = Screen.colors.Red, blend = 100}
+ m.attr = { background = Screen.colors.Red, blend = 100 }
end
end
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
test |
- ]], condition=function()
- eq(expected_mode_info, screen._mode_info)
- end
+ ]],
+ condition = function()
+ eq(expected_mode_info, screen._mode_info)
+ end,
}
-- Another cursor style.
- meths.set_option_value('guicursor', 'n-v-c:ver35-blinkwait171-blinkoff172-blinkon173'
- ..',ve:hor35,o:ver50,i-ci:block,r-cr:hor90,sm:ver42', {})
+ api.nvim_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,9 +326,13 @@ describe('ui/cursor', function()
end)
-- If there is no setting for guicursor, it becomes the default setting.
- meths.set_option_value('guicursor', 'n:ver35-blinkwait171-blinkoff172-blinkon173-Cursor/lCursor', {})
+ api.nvim_set_option_value(
+ 'guicursor',
+ 'n:ver35-blinkwait171-blinkoff172-blinkon173-Cursor/lCursor',
+ {}
+ )
screen:expect(function()
- for _,m in ipairs(screen._mode_info) do
+ for _, m in ipairs(screen._mode_info) do
if m.name ~= 'normal' then
eq('block', m.cursor_shape or 'block')
eq(0, m.blinkon or 0)
@@ -304,7 +346,7 @@ describe('ui/cursor', function()
end)
it("empty 'guicursor' sets cursor_shape=block in all modes", function()
- meths.set_option_value('guicursor', '', {})
+ api.nvim_set_option_value('guicursor', '', {})
screen:expect(function()
-- Empty 'guicursor' sets enabled=false.
eq(false, screen._cursor_style_enabled)
@@ -318,5 +360,4 @@ describe('ui/cursor', function()
end
end)
end)
-
end)
diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua
index e8fcfc46fc..e57e719192 100644
--- a/test/functional/ui/decorations_spec.lua
+++ b/test/functional/ui/decorations_spec.lua
@@ -7,9 +7,8 @@ local insert = helpers.insert
local exec_lua = helpers.exec_lua
local exec = helpers.exec
local expect_events = helpers.expect_events
-local meths = helpers.meths
-local funcs = helpers.funcs
-local curbufmeths = helpers.curbufmeths
+local api = helpers.api
+local fn = helpers.fn
local command = helpers.command
local eq = helpers.eq
local assert_alive = helpers.assert_alive
@@ -40,6 +39,7 @@ describe('decorations providers', function()
[16] = {special = Screen.colors.Red, undercurl = true},
[17] = {foreground = Screen.colors.Red},
[18] = {bold = true, foreground = Screen.colors.SeaGreen};
+ [19] = {bold = true};
}
end)
@@ -212,9 +212,7 @@ describe('decorations providers', function()
{15:i} am not capitalized. |
I am a {16:speling} {16:mistakke}. |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
@@ -227,9 +225,7 @@ describe('decorations providers', function()
{15:^i} am not capitalized. |
I am a {16:speling} {16:mistakke}. |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
@@ -242,24 +238,20 @@ describe('decorations providers', function()
{15:i} am not capitalized. |
I am a {16:^speling} {16:mistakke}. |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
-- spell=false with higher priority does disable spell
- local ns = meths.create_namespace "spell"
- local id = curbufmeths.set_extmark(ns, 0, 0, { priority = 30, end_row = 2, end_col = 23, spell = false })
+ local ns = api.nvim_create_namespace "spell"
+ local id = api.nvim_buf_set_extmark(0, ns, 0, 0, { priority = 30, end_row = 2, end_col = 23, spell = false })
screen:expect{grid=[[
I am well written text. |
i am not capitalized. |
I am a ^speling mistakke. |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
@@ -269,24 +261,20 @@ describe('decorations providers', function()
i am not capitalized. |
I am a ^speling mistakke. |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{17:search hit BOTTOM, continuing at TOP} |
]]}
command('echo ""')
-- spell=false with lower priority doesn't disable spell
- curbufmeths.set_extmark(ns, 0, 0, { id = id, priority = 10, end_row = 2, end_col = 23, spell = false })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { id = id, priority = 10, end_row = 2, end_col = 23, spell = false })
screen:expect{grid=[[
I am well written text. |
{15:i} am not capitalized. |
I am a {16:^speling} {16:mistakke}. |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
@@ -296,9 +284,7 @@ describe('decorations providers', function()
{15:i} am not capitalized. |
I am a {16:speling} {16:^mistakke}. |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
@@ -320,7 +306,7 @@ describe('decorations providers', function()
LineNr = {italic=true, bg="Magenta"};
Comment = {fg="#FF0000", bg = 80*256+40};
CursorLine = {link="ErrorMsg"};
- } do meths.set_hl(ns1, k, v) end
+ } do api.nvim_set_hl(ns1, k, v) end
screen:expect{grid=[[
{3: 1 }{4:// just to see if there was an accid}|
@@ -341,7 +327,7 @@ describe('decorations providers', function()
|
]]}
- meths.set_hl_ns(ns1)
+ api.nvim_set_hl_ns(ns1)
screen:expect{grid=[[
{10: 1 }{11:// just to see if there was an accid}|
{10: }{11:ent} |
@@ -401,7 +387,7 @@ describe('decorations providers', function()
highlight link LinkGroup OriginalGroup
]]
- meths.buf_set_virtual_text(0, 0, 2, {{'- not red', 'LinkGroup'}}, {})
+ api.nvim_buf_set_virtual_text(0, 0, 2, {{'- not red', 'LinkGroup'}}, {})
screen:expect{grid=[[
// just to see if there was an accident |
// on Mulholland Drive |
@@ -413,8 +399,8 @@ describe('decorations providers', function()
|
]]}
- meths.set_hl(ns1, 'LinkGroup', {fg = 'Blue'})
- meths.set_hl_ns(ns1)
+ api.nvim_set_hl(ns1, 'LinkGroup', {fg = 'Blue'})
+ api.nvim_set_hl_ns(ns1)
screen:expect{grid=[[
// just to see if there was an accident |
@@ -437,7 +423,7 @@ describe('decorations providers', function()
highlight link LinkGroup OriginalGroup
]]
- meths.buf_set_virtual_text(0, 0, 2, {{'- not red', 'LinkGroup'}}, {})
+ api.nvim_buf_set_virtual_text(0, 0, 2, {{'- not red', 'LinkGroup'}}, {})
screen:expect{grid=[[
// just to see if there was an accident |
// on Mulholland Drive |
@@ -449,8 +435,8 @@ describe('decorations providers', function()
|
]]}
- meths.set_hl(ns1, 'LinkGroup', {fg = 'Blue', default=true})
- meths.set_hl_ns(ns1)
+ api.nvim_set_hl(ns1, 'LinkGroup', {fg = 'Blue', default=true})
+ api.nvim_set_hl_ns(ns1)
feed 'k'
screen:expect{grid=[[
@@ -629,9 +615,9 @@ describe('decorations providers', function()
vim.api.nvim_buf_set_lines(0, 0, -1, false, lines)
]])
setup_provider([[
- local function on_do(kind, winid, bufnr, topline, botline_guess)
+ local function on_do(kind, winid, bufnr, topline, botline)
if kind == 'win' then
- if topline < 100 and botline_guess > 100 then
+ if topline < 100 and botline > 100 then
api.nvim_buf_set_extmark(bufnr, ns1, 99, -1, { sign_text = 'X' })
else
api.nvim_buf_clear_namespace(bufnr, ns1, 0, -1)
@@ -640,7 +626,7 @@ describe('decorations providers', function()
end
]])
command([[autocmd CursorMoved * call line('w$')]])
- meths.win_set_cursor(0, {100, 0})
+ api.nvim_win_set_cursor(0, {100, 0})
screen:expect([[
{14: }hello97 |
{14: }hello98 |
@@ -651,7 +637,7 @@ describe('decorations providers', function()
{14: }hello103 |
|
]])
- meths.win_set_cursor(0, {1, 0})
+ api.nvim_win_set_cursor(0, {1, 0})
screen:expect([[
^hello1 |
hello2 |
@@ -669,7 +655,7 @@ describe('decorations providers', function()
eok = true
]])
setup_provider([[
- local function on_do(kind, winid, bufnr, topline, botline_guess)
+ local function on_do(kind, winid, bufnr, topline, botline)
if kind == 'line' then
api.nvim_buf_set_extmark(bufnr, ns1, 1, -1, { sign_text = 'X' })
eok = pcall(api.nvim_buf_clear_namespace, bufnr, ns1, 0, -1)
@@ -701,6 +687,77 @@ describe('decorations providers', function()
{18:Press ENTER or type command to continue}^ |
]]}
end)
+
+ it('can add new providers during redraw #26652', function()
+ setup_provider [[
+ local ns = api.nvim_create_namespace('test_no_add')
+ function on_do(...)
+ api.nvim_set_decoration_provider(ns, {})
+ end
+ ]]
+
+ helpers.assert_alive()
+ end)
+
+ it('supports subpriorities (order of definitions in a query file #27131)', function()
+ insert(mulholland)
+ setup_provider [[
+ local test_ns = api.nvim_create_namespace('mulholland')
+ function on_do(event, ...)
+ if event == "line" then
+ local win, buf, line = ...
+ api.nvim_buf_set_extmark(buf, test_ns, line, 0, {
+ end_row = line + 1,
+ hl_eol = true,
+ hl_group = 'Comment',
+ ephemeral = true,
+ priority = 100,
+ _subpriority = 20,
+ })
+
+ -- This extmark is set last but has a lower subpriority, so the first extmark "wins"
+ api.nvim_buf_set_extmark(buf, test_ns, line, 0, {
+ end_row = line + 1,
+ hl_eol = true,
+ hl_group = 'String',
+ ephemeral = true,
+ priority = 100,
+ _subpriority = 10,
+ })
+ end
+ end
+ ]]
+
+ screen:expect{grid=[[
+ {4:// just to see if there was an accident }|
+ {4:// on Mulholland Drive }|
+ {4:try_start(); }|
+ {4:bufref_T save_buf; }|
+ {4:switch_buffer(&save_buf, buf); }|
+ {4:posp = getmark(mark, false); }|
+ {4:restore_buffer(&save_buf);^ }|
+ |
+ ]]}
+ end)
+
+ it('is not invoked repeatedly in Visual mode with vim.schedule() #20235', function()
+ exec_lua([[_G.cnt = 0]])
+ setup_provider([[
+ function on_do(event, ...)
+ if event == 'win' then
+ vim.schedule(function() end)
+ _G.cnt = _G.cnt + 1
+ end
+ end
+ ]])
+ feed('v')
+ screen:expect([[
+ ^ |
+ {1:~ }|*6
+ {19:-- VISUAL --} |
+ ]])
+ eq(2, exec_lua([[return _G.cnt]]))
+ end)
end)
local example_text = [[
@@ -749,14 +806,14 @@ describe('extmark decorations', function()
[23] = {foreground = Screen.colors.Magenta1, background = Screen.colors.LightGrey};
[24] = {bold = true};
[25] = {background = Screen.colors.LightRed};
- [26] = {background=Screen.colors.DarkGrey, foreground=Screen.colors.LightGrey};
- [27] = {background = Screen.colors.Plum1};
+ [26] = {background = Screen.colors.DarkGrey, foreground = Screen.colors.LightGrey};
+ [27] = {background = Screen.colors.LightGrey, foreground = Screen.colors.Black};
[28] = {underline = true, foreground = Screen.colors.SlateBlue};
- [29] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.LightGray, underline = true};
- [30] = {foreground = Screen.colors.DarkCyan, background = Screen.colors.LightGray, underline = true};
+ [29] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.LightGrey, underline = true};
+ [30] = {foreground = Screen.colors.DarkCyan, background = Screen.colors.LightGrey, underline = true};
[31] = {underline = true, foreground = Screen.colors.DarkCyan};
[32] = {underline = true};
- [33] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray};
+ [33] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey};
[34] = {background = Screen.colors.Yellow};
[35] = {background = Screen.colors.Yellow, bold = true, foreground = Screen.colors.Blue};
[36] = {foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.Red};
@@ -765,9 +822,12 @@ describe('extmark decorations', function()
[39] = {foreground = Screen.colors.Blue1, background = Screen.colors.LightCyan1, bold = true};
[40] = {reverse = true};
[41] = {bold = true, reverse = true};
+ [42] = {undercurl = true, special = Screen.colors.Red};
+ [43] = {background = Screen.colors.Yellow, undercurl = true, special = Screen.colors.Red};
+ [44] = {background = Screen.colors.LightMagenta};
}
- ns = meths.create_namespace 'test'
+ ns = api.nvim_create_namespace 'test'
end)
it('empty virtual text at eol should not break colorcolumn #17860', function()
@@ -787,11 +847,10 @@ describe('extmark decorations', function()
colpos = colpos+1 {25: } |
end {25: } |
end {25: } |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
- meths.buf_set_extmark(0, ns, 4, 0, { virt_text={{''}}, virt_text_pos='eol'})
+ api.nvim_buf_set_extmark(0, ns, 4, 0, { virt_text={{''}}, virt_text_pos='eol'})
screen:expect_unchanged()
end)
@@ -800,19 +859,19 @@ describe('extmark decorations', function()
feed 'gg'
for i = 1,9 do
- meths.buf_set_extmark(0, ns, i, 0, { virt_text={{'|', 'LineNr'}}, virt_text_pos='overlay'})
+ api.nvim_buf_set_extmark(0, ns, i, 0, { virt_text={{'|', 'LineNr'}}, virt_text_pos='overlay'})
if i == 3 or (i >= 6 and i <= 9) then
- meths.buf_set_extmark(0, ns, i, 4, { virt_text={{'|', 'NonText'}}, virt_text_pos='overlay'})
+ api.nvim_buf_set_extmark(0, ns, i, 4, { virt_text={{'|', 'NonText'}}, virt_text_pos='overlay'})
end
end
- meths.buf_set_extmark(0, ns, 9, 10, { virt_text={{'foo'}, {'bar', 'MoreMsg'}, {'!!', 'ErrorMsg'}}, virt_text_pos='overlay'})
+ api.nvim_buf_set_extmark(0, ns, 9, 10, { virt_text={{'foo'}, {'bar', 'MoreMsg'}, {'!!', 'ErrorMsg'}}, virt_text_pos='overlay'})
-- can "float" beyond end of line
- meths.buf_set_extmark(0, ns, 5, 28, { virt_text={{'loopy', 'ErrorMsg'}}, virt_text_pos='overlay'})
+ api.nvim_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'):rep(10), 'ErrorMsg'}}, virt_text_pos='overlay'})
+ api.nvim_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'})
+ api.nvim_buf_set_extmark(0, ns, 6, 16, { virt_text={{''}}, virt_text_pos='overlay'})
screen:expect{grid=[[
^for _,item in ipairs(items) do |
@@ -827,8 +886,7 @@ describe('extmark decorations', function()
{2:|} {1:|} cofoo{3:bar}{4:!!}olpos+1 |
end |
end |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
@@ -857,18 +915,17 @@ describe('extmark decorations', function()
s+1 |
end |
end |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
-- 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'})
+ api.nvim_buf_set_lines(0, 0, 1, true, {'for _,item in ipairs(items) do -- å¤å¤å¤'})
+ api.nvim_buf_set_lines(0, 10, 12, true, {' end -- ??????????', 'end -- ?å¤å¤å¤å¤?å¤å¤'})
+ api.nvim_buf_set_extmark(0, ns, 0, 35, { virt_text={{'A', 'ErrorMsg'}, {'AA'}}, virt_text_pos='overlay'})
+ api.nvim_buf_set_extmark(0, ns, 10, 19, { virt_text={{'å£å£å£', 'ErrorMsg'}}, virt_text_pos='overlay'})
+ api.nvim_buf_set_extmark(0, ns, 11, 21, { virt_text={{'å£å£å£', 'ErrorMsg'}}, virt_text_pos='overlay'})
+ api.nvim_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 å¤ |
@@ -892,8 +949,7 @@ describe('extmark decorations', function()
s+1 |
end -- ???????{4:å£ }|
end -- {4:å£å£} å¤å¤{4:å£å£ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
@@ -914,7 +970,7 @@ describe('extmark decorations', function()
|
]]}
- meths.buf_clear_namespace(0, ns, 0, -1)
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
screen:expect{grid=[[
^for _,item in ipairs(items) do -- å¤å¤å¤ |
local text, hl_id_cell, count = unpack(item) |
@@ -936,8 +992,8 @@ describe('extmark decorations', function()
screen:try_resize(50, 6)
insert(('ab'):rep(100))
for i = 0, 9 do
- meths.buf_set_extmark(0, ns, 0, 42 + i, { virt_text={{tostring(i), 'ErrorMsg'}}, virt_text_pos='overlay'})
- meths.buf_set_extmark(0, ns, 0, 91 + i, { virt_text={{tostring(i), 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide=true})
+ api.nvim_buf_set_extmark(0, ns, 0, 42 + i, { virt_text={{tostring(i), 'ErrorMsg'}}, virt_text_pos='overlay'})
+ api.nvim_buf_set_extmark(0, ns, 0, 91 + i, { virt_text={{tostring(i), 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide=true})
end
screen:expect{grid=[[
ababababababababababababababababababababab{4:01234567}|
@@ -962,7 +1018,7 @@ describe('extmark decorations', function()
screen:expect{grid=[[
ababababababababababababababababababababab{4:01234567}|
{1:++}{4:89}abababababababababababababababababababa{4:0123456}|
- {1:++}^a{18:babab}ababababababababababababababababababababab|
+ {1:++}^a{27:babab}ababababababababababababababababababababab|
{1:++}abababababababababababababababababababababababab|
{1:++}ababab |
{24:-- VISUAL --} |
@@ -972,7 +1028,7 @@ describe('extmark decorations', function()
screen:expect{grid=[[
ababababababababababababababababababababab{4:01234567}|
{1:++}{4:89}abababababababababababababababababababa{4:0123456}|
- {1:++}{18:ababa}^bababababababababababababababababababababab|
+ {1:++}{27:ababa}^bababababababababababababababababababababab|
{1:++}abababababababababababababababababababababababab|
{1:++}ababab |
{24:-- VISUAL --} |
@@ -981,8 +1037,8 @@ describe('extmark decorations', function()
feed('gk')
screen:expect{grid=[[
ababababababababababababababababababababab{4:01234567}|
- {1:++}{4:89}aba^b{18:ababababababababababababababababababababab}|
- {1:++}{18:a}{4:89}babababababababababababababababababababababab|
+ {1:++}{4:89}aba^b{27:ababababababababababababababababababababab}|
+ {1:++}{27:a}{4:89}babababababababababababababababababababababab|
{1:++}abababababababababababababababababababababababab|
{1:++}ababab |
{24:-- VISUAL --} |
@@ -991,7 +1047,7 @@ describe('extmark decorations', function()
feed('o')
screen:expect{grid=[[
ababababababababababababababababababababab{4:01234567}|
- {1:++}{4:89}aba{18:bababababababababababababababababababababab}|
+ {1:++}{4:89}aba{27:bababababababababababababababababababababab}|
{1:++}^a{4:89}babababababababababababababababababababababab|
{1:++}abababababababababababababababababababababababab|
{1:++}ababab |
@@ -1033,9 +1089,9 @@ describe('extmark decorations', function()
it('virt_text_hide hides overlay virtual text when extmark is off-screen', function()
screen:try_resize(50, 3)
command('set nowrap')
- meths.buf_set_lines(0, 0, -1, true, {'-- ' .. ('…'):rep(57)})
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text={{'?????', 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide=true})
- meths.buf_set_extmark(0, ns, 0, 123, { virt_text={{'!!!!!', 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide=true})
+ api.nvim_buf_set_lines(0, 0, -1, true, {'-- ' .. ('…'):rep(57)})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text={{'?????', 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide=true})
+ api.nvim_buf_set_extmark(0, ns, 0, 123, { virt_text={{'!!!!!', 'ErrorMsg'}}, virt_text_pos='overlay', virt_text_hide=true})
screen:expect{grid=[[
{4:^?????}……………………………………………………………………………………………………{4:!!!!!}……|
{1:~ }|
@@ -1088,10 +1144,10 @@ describe('extmark decorations', function()
it('overlay virtual text works on and after a TAB #24022', function()
screen:try_resize(40, 3)
- meths.buf_set_lines(0, 0, -1, true, {'\t\tline 1'})
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'AA', 'Search'}}, virt_text_pos = 'overlay', hl_mode = 'combine' })
- meths.buf_set_extmark(0, ns, 0, 1, { virt_text = {{'BB', 'Search'}}, virt_text_pos = 'overlay', hl_mode = 'combine' })
- meths.buf_set_extmark(0, ns, 0, 2, { virt_text = {{'CC', 'Search'}}, virt_text_pos = 'overlay', hl_mode = 'combine' })
+ api.nvim_buf_set_lines(0, 0, -1, true, {'\t\tline 1'})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'AA', 'Search'}}, virt_text_pos = 'overlay', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 0, 1, { virt_text = {{'BB', 'Search'}}, virt_text_pos = 'overlay', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = {{'CC', 'Search'}}, virt_text_pos = 'overlay', hl_mode = 'combine' })
screen:expect{grid=[[
{34:AA} ^ {34:BB} {34:CC}ne 1 |
{1:~ }|
@@ -1125,19 +1181,19 @@ describe('extmark decorations', function()
colpos {5:=} colpos{5:+}{13:1} |
{5:end} |
{5:end} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
command 'hi Blendy guibg=Red blend=30'
- meths.buf_set_extmark(0, ns, 1, 5, { virt_text={{'blendy text - here', 'Blendy'}}, virt_text_pos='overlay', hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 2, 5, { virt_text={{'combining color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='combine'})
- meths.buf_set_extmark(0, ns, 3, 5, { virt_text={{'replacing color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='replace'})
+ command 'hi! Visual guifg=NONE guibg=LightGrey'
+ api.nvim_buf_set_extmark(0, ns, 1, 5, { virt_text={{'blendy text - here', 'Blendy'}}, virt_text_pos='overlay', hl_mode='blend'})
+ api.nvim_buf_set_extmark(0, ns, 2, 5, { virt_text={{'combining color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='combine'})
+ api.nvim_buf_set_extmark(0, ns, 3, 5, { virt_text={{'replacing color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='replace'})
- meths.buf_set_extmark(0, ns, 4, 5, { virt_text={{'blendy text - here', 'Blendy'}}, virt_text_pos='overlay', hl_mode='blend', virt_text_hide=true})
- meths.buf_set_extmark(0, ns, 5, 5, { virt_text={{'combining color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='combine', virt_text_hide=true})
- meths.buf_set_extmark(0, ns, 6, 5, { virt_text={{'replacing color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='replace', virt_text_hide=true})
+ api.nvim_buf_set_extmark(0, ns, 4, 5, { virt_text={{'blendy text - here', 'Blendy'}}, virt_text_pos='overlay', hl_mode='blend', virt_text_hide=true})
+ api.nvim_buf_set_extmark(0, ns, 5, 5, { virt_text={{'combining color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='combine', virt_text_hide=true})
+ api.nvim_buf_set_extmark(0, ns, 6, 5, { virt_text={{'replacing color', 'Blendy'}}, virt_text_pos='overlay', hl_mode='replace', virt_text_hide=true})
screen:expect{grid=[[
{5:^for} _,item {5:in} {6:ipairs}(items) {5:do} |
@@ -1152,8 +1208,7 @@ describe('extmark decorations', function()
colpos {5:=} colpos{5:+}{13:1} |
{5:end} |
{5:end} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
@@ -1171,8 +1226,7 @@ describe('extmark decorations', function()
colpos {5:=} colpos{5:+}{13:1} |
{5:end} |
{5:end} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{24:-- VISUAL LINE --} |
]]}
@@ -1190,8 +1244,7 @@ describe('extmark decorations', function()
colpos {5:=} colpos{5:+}{13:1} |
{5:end} |
{5:end} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{24:-- VISUAL LINE --} |
]]}
end)
@@ -1199,17 +1252,17 @@ describe('extmark decorations', function()
it('can have virtual text of right_align and fixed win_col position', function()
insert(example_text)
feed 'gg'
- meths.buf_set_extmark(0, ns, 1, 0, { virt_text={{'Very', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 1, 0, { virt_text={{'VERY', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 2, 10, { virt_text={{'Much', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 2, 10, { virt_text={{'MUCH', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 3, 14, { virt_text={{'Error', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 3, 14, { virt_text={{'ERROR', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 7, 21, { virt_text={{'-', 'NonText'}}, virt_text_win_col=4, hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 7, 21, { virt_text={{'-', 'NonText'}}, virt_text_pos='right_align', hl_mode='blend'})
+ api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text={{'Very', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
+ api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text={{'VERY', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
+ api.nvim_buf_set_extmark(0, ns, 2, 10, { virt_text={{'Much', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
+ api.nvim_buf_set_extmark(0, ns, 2, 10, { virt_text={{'MUCH', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
+ api.nvim_buf_set_extmark(0, ns, 3, 14, { virt_text={{'Error', 'ErrorMsg'}}, virt_text_win_col=31, hl_mode='blend'})
+ api.nvim_buf_set_extmark(0, ns, 3, 14, { virt_text={{'ERROR', 'ErrorMsg'}}, virt_text_pos='right_align', hl_mode='blend'})
+ api.nvim_buf_set_extmark(0, ns, 7, 21, { virt_text={{'-', 'NonText'}}, virt_text_win_col=4, hl_mode='blend'})
+ api.nvim_buf_set_extmark(0, ns, 7, 21, { virt_text={{'-', 'NonText'}}, virt_text_pos='right_align', hl_mode='blend'})
-- empty virt_text should not change anything
- meths.buf_set_extmark(0, ns, 8, 0, { virt_text={{''}}, virt_text_win_col=14, hl_mode='blend'})
- meths.buf_set_extmark(0, ns, 8, 0, { virt_text={{''}}, virt_text_pos='right_align', hl_mode='blend'})
+ api.nvim_buf_set_extmark(0, ns, 8, 0, { virt_text={{''}}, virt_text_win_col=14, hl_mode='blend'})
+ api.nvim_buf_set_extmark(0, ns, 8, 0, { virt_text={{''}}, virt_text_pos='right_align', hl_mode='blend'})
screen:expect{grid=[[
^for _,item in ipairs(items) do |
@@ -1224,8 +1277,7 @@ describe('extmark decorations', function()
colpos = colpos+1 |
end |
end |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
@@ -1262,8 +1314,7 @@ describe('extmark decorations', function()
colpos = colpos+1 |
end |
end |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
: |
]]}
@@ -1305,7 +1356,7 @@ describe('extmark decorations', function()
|
]]}
- meths.buf_set_extmark(0, ns, 4, 50, { virt_text={{'EOL', 'NonText'}} })
+ api.nvim_buf_set_extmark(0, ns, 4, 50, { virt_text={{'EOL', 'NonText'}} })
screen:expect{grid=[[
for _,item in ipairs(items) do |
local text, hl_id_cell, cou{4:Very} unpack(ite{4:VERY}|
@@ -1461,17 +1512,16 @@ describe('extmark decorations', function()
it('virtual text win_col out of window does not break display #25645', function()
screen:try_resize(51, 6)
command('vnew')
- meths.buf_set_lines(0, 0, -1, false, { string.rep('a', 50) })
+ api.nvim_buf_set_lines(0, 0, -1, false, { string.rep('a', 50) })
screen:expect{grid=[[
^aaaaaaaaaaaaaaaaaaaaaaaaa│ |
aaaaaaaaaaaaaaaaaaaaaaaaa│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*2
{41:[No Name] [+] }{40:[No Name] }|
|
]]}
local extmark_opts = { virt_text_win_col = 35, virt_text = { { ' ', 'Comment' } } }
- meths.buf_set_extmark(0, ns, 0, 0, extmark_opts)
+ api.nvim_buf_set_extmark(0, ns, 0, 0, extmark_opts)
screen:expect_unchanged()
assert_alive()
end)
@@ -1487,9 +1537,9 @@ describe('extmark decorations', function()
-- XXX: the behavior of overlay virtual text at non-zero column is strange:
-- 1. With 'wrap' it is never shown.
-- 2. With 'nowrap' it is shown only if the extmark is hidden before leftcol.
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'AA', 'Underlined'}}, hl_mode = 'combine', virt_text_pos = 'overlay' })
- meths.buf_set_extmark(0, ns, 0, 5, { virt_text = {{'BB', 'Underlined'}}, hl_mode = 'combine', virt_text_win_col = 10 })
- meths.buf_set_extmark(0, ns, 0, 2, { virt_text = {{'CC', 'Underlined'}}, hl_mode = 'combine', virt_text_pos = 'right_align' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'AA', 'Underlined'}}, hl_mode = 'combine', virt_text_pos = 'overlay' })
+ api.nvim_buf_set_extmark(0, ns, 0, 5, { virt_text = {{'BB', 'Underlined'}}, hl_mode = 'combine', virt_text_win_col = 10 })
+ api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = {{'CC', 'Underlined'}}, hl_mode = 'combine', virt_text_pos = 'right_align' })
screen:expect{grid=[[
{29:AA}{33:- 2 lin}{29:BB}{33:: 11111·····························}{29:CC}|
3333^3 |
@@ -1532,9 +1582,9 @@ describe('extmark decorations', function()
ddddd
eeeee]])
command('windo diffthis')
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'AA', 'Underlined'}}, virt_text_pos = 'overlay' })
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'BB', 'Underlined'}}, virt_text_win_col = 10 })
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'CC', 'Underlined'}}, virt_text_pos = 'right_align' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'AA', 'Underlined'}}, virt_text_pos = 'overlay' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'BB', 'Underlined'}}, virt_text_win_col = 10 })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'CC', 'Underlined'}}, virt_text_pos = 'right_align' })
screen:expect{grid=[[
{37: }{38:aaaaa }│{37: }{39:------------------------}|
{37: }bbbbb │{37: }{28:AA}bbb {28:BB} {28:CC}|
@@ -1577,14 +1627,13 @@ describe('extmark decorations', function()
{'d', {'BgTwo', 'FgZwei'}};
{'X', {'BgTwo', 'FgZwei', 'VeryBold'}};
}
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'eol' })
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'right_align' })
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'inline' })
- meths.buf_set_extmark(0, ns, 0, 0, { virt_lines = { vt, vt } })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'eol' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'right_align' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = vt, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_lines = { vt, vt } })
screen:expect{grid=[[
{2:a}{3:b}{4:c}{5:d}{6:X}#^# {2:a}{3:b}{4:c}{5:d}{6:X} {2:a}{3:b}{4:c}{5:d}{6:X}|
- {2:a}{3:b}{4:c}{5:d}{6:X} |
- {2:a}{3:b}{4:c}{5:d}{6:X} |
+ {2:a}{3:b}{4:c}{5:d}{6:X} |*2
{1:~ }|
|
]]}
@@ -1597,19 +1646,7 @@ describe('extmark decorations', function()
]]
screen:expect{grid=[[
^ a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*13
|
]]}
@@ -1619,19 +1656,7 @@ describe('extmark decorations', function()
]]
screen:expect{grid=[[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*13
|
]]}
assert_alive()
@@ -1640,43 +1665,40 @@ describe('extmark decorations', function()
it('conceal with conceal char #19007', function()
screen:try_resize(50, 5)
insert('foo\n')
- meths.buf_set_extmark(0, ns, 0, 0, {end_col=0, end_row=2, conceal='X'})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {end_col=0, end_row=2, conceal='X'})
command('set conceallevel=2')
screen:expect([[
{26:X} |
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
command('set conceallevel=1')
screen:expect_unchanged()
- eq("conceal char has to be printable", pcall_err(meths.buf_set_extmark, 0, ns, 0, 0, {end_col=0, end_row=2, conceal='\255'}))
+ eq("conceal char has to be printable", pcall_err(api.nvim_buf_set_extmark, 0, ns, 0, 0, {end_col=0, end_row=2, conceal='\255'}))
end)
it('conceal with composed conceal char', function()
screen:try_resize(50, 5)
insert('foo\n')
- meths.buf_set_extmark(0, ns, 0, 0, {end_col=0, end_row=2, conceal='ẍ̲'})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {end_col=0, end_row=2, conceal='ẍ̲'})
command('set conceallevel=2')
screen:expect([[
{26:ẍ̲} |
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
command('set conceallevel=1')
screen:expect_unchanged()
-- this is rare, but could happen. Save at least the first codepoint
- meths._invalidate_glyph_cache()
+ api.nvim__invalidate_glyph_cache()
screen:expect{grid=[[
{26:x} |
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
end)
@@ -1684,30 +1706,28 @@ describe('extmark decorations', function()
it('conceal without conceal char #24782', function()
screen:try_resize(50, 5)
insert('foobar\n')
- meths.buf_set_extmark(0, ns, 0, 0, {end_col=3, conceal=''})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {end_col=3, conceal=''})
command('set listchars=conceal:?')
command('let &conceallevel=1')
screen:expect([[
{26:?}bar |
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
command('let &conceallevel=2')
screen:expect([[
bar |
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
end)
it('conceal works just before truncated double-width char #21486', function()
screen:try_resize(40, 4)
- meths.buf_set_lines(0, 0, -1, true, {'', ('a'):rep(37) .. '<>å¤'})
- meths.buf_set_extmark(0, ns, 1, 37, {end_col=39, conceal=''})
+ api.nvim_buf_set_lines(0, 0, -1, true, {'', ('a'):rep(37) .. '<>å¤'})
+ api.nvim_buf_set_extmark(0, ns, 1, 37, {end_col=39, conceal=''})
command('setlocal conceallevel=2')
screen:expect{grid=[[
^ |
@@ -1724,6 +1744,35 @@ describe('extmark decorations', function()
]]}
end)
+ it('redraws properly when adding/removing conceal on non-current line', function()
+ screen:try_resize(50, 5)
+ api.nvim_buf_set_lines(0, 0, -1, true, {'abcd', 'efgh','ijkl', 'mnop'})
+ command('setlocal conceallevel=2')
+ screen:expect{grid=[[
+ ^abcd |
+ efgh |
+ ijkl |
+ mnop |
+ |
+ ]]}
+ api.nvim_buf_set_extmark(0, ns, 2, 1, {end_col=3, conceal=''})
+ screen:expect{grid=[[
+ ^abcd |
+ efgh |
+ il |
+ mnop |
+ |
+ ]]}
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
+ screen:expect{grid=[[
+ ^abcd |
+ efgh |
+ ijkl |
+ mnop |
+ |
+ ]]}
+ end)
+
it('avoids redraw issue #20651', function()
exec_lua[[
vim.cmd.normal'10oXXX'
@@ -1748,25 +1797,16 @@ describe('extmark decorations', function()
]]
for _ = 1, 3 do
- helpers.sleep(10)
+ vim.uv.sleep(10)
feed 'j'
end
screen:expect{grid=[[
- {27: } |
- XXX |
- XXX |
+ {44: } |
+ XXX |*2
^XXX HELLO |
- XXX |
- XXX |
- XXX |
- XXX |
- XXX |
- XXX |
- XXX |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ XXX |*7
+ {1:~ }|*3
|
]]}
@@ -1790,32 +1830,32 @@ describe('extmark decorations', function()
[6] = {bold = true, undercurl = true, special = Screen.colors.Red};
})
- meths.buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUL', priority = 20 })
- meths.buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUC', priority = 30 })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUL', priority = 20 })
+ api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUC', priority = 30 })
screen:expect([[
{1:aaa}{4:bbb}{1:aa^a} |
{0:~ }|
|
]])
- meths.buf_clear_namespace(0, ns, 0, -1)
- meths.buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUC', priority = 20 })
- meths.buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUL', priority = 30 })
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUC', priority = 20 })
+ api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUL', priority = 30 })
screen:expect([[
{2:aaa}{3:bbb}{2:aa^a} |
{0:~ }|
|
]])
- meths.buf_clear_namespace(0, ns, 0, -1)
- meths.buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUL', priority = 30 })
- meths.buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUC', priority = 20 })
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUL', priority = 30 })
+ api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUC', priority = 20 })
screen:expect([[
{1:aaa}{3:bbb}{1:aa^a} |
{0:~ }|
|
]])
- meths.buf_clear_namespace(0, ns, 0, -1)
- meths.buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUC', priority = 30 })
- meths.buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUL', priority = 20 })
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUC', priority = 30 })
+ api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestUL', priority = 20 })
screen:expect([[
{2:aaa}{4:bbb}{2:aa^a} |
{0:~ }|
@@ -1824,14 +1864,14 @@ describe('extmark decorations', function()
-- When only one highlight group has an underline attribute, it should always take effect.
for _, d in ipairs({-5, 5}) do
- meths.buf_clear_namespace(0, ns, 0, -1)
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
screen:expect([[
aaabbbaa^a |
{0:~ }|
|
]])
- meths.buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUL', priority = 25 + d })
- meths.buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestBold', priority = 25 - d })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUL', priority = 25 + d })
+ api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestBold', priority = 25 - d })
screen:expect([[
{1:aaa}{5:bbb}{1:aa^a} |
{0:~ }|
@@ -1839,14 +1879,14 @@ describe('extmark decorations', function()
]])
end
for _, d in ipairs({-5, 5}) do
- meths.buf_clear_namespace(0, ns, 0, -1)
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
screen:expect([[
aaabbbaa^a |
{0:~ }|
|
]])
- meths.buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUC', priority = 25 + d })
- meths.buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestBold', priority = 25 - d })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 9, hl_group = 'TestUC', priority = 25 + d })
+ api.nvim_buf_set_extmark(0, ns, 0, 3, { end_col = 6, hl_group = 'TestBold', priority = 25 - d })
screen:expect([[
{2:aaa}{6:bbb}{2:aa^a} |
{0:~ }|
@@ -1863,10 +1903,11 @@ describe('extmark decorations', function()
feed('gg')
command('set ft=lua')
command('syntax on')
- meths.buf_set_extmark(0, ns, 0, 0, { end_col = 3, hl_mode = 'combine', hl_group = 'Visual' })
+ command('hi default MyMark guibg=LightGrey')
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 3, hl_mode = 'combine', hl_group = 'MyMark' })
command('hi default MyLine gui=underline')
command('sign define CurrentLine linehl=MyLine')
- funcs.sign_place(6, 'Test', 'CurrentLine', '', { lnum = 1 })
+ fn.sign_place(6, 'Test', 'CurrentLine', '', { lnum = 1 })
screen:expect{grid=[[
{30:^fun}{31:ction}{32: Func() }|
{6:end} |
@@ -1877,8 +1918,8 @@ describe('extmark decorations', function()
it('highlight works after TAB with sidescroll #14201', function()
screen:try_resize(50, 3)
command('set nowrap')
- meths.buf_set_lines(0, 0, -1, true, {'\tword word word word'})
- meths.buf_set_extmark(0, ns, 0, 1, { end_col = 3, hl_group = 'ErrorMsg' })
+ api.nvim_buf_set_lines(0, 0, -1, true, {'\tword word word word'})
+ api.nvim_buf_set_extmark(0, ns, 0, 1, { end_col = 3, hl_group = 'ErrorMsg' })
screen:expect{grid=[[
^ {4:wo}rd word word word |
{1:~ }|
@@ -1906,16 +1947,16 @@ describe('extmark decorations', function()
it('highlights the beginning of a TAB char correctly #23734', function()
screen:try_resize(50, 3)
- meths.buf_set_lines(0, 0, -1, true, {'this is the\ttab'})
- meths.buf_set_extmark(0, ns, 0, 11, { end_col = 15, hl_group = 'ErrorMsg' })
+ api.nvim_buf_set_lines(0, 0, -1, true, {'this is the\ttab'})
+ api.nvim_buf_set_extmark(0, ns, 0, 11, { end_col = 15, hl_group = 'ErrorMsg' })
screen:expect{grid=[[
^this is the{4: tab} |
{1:~ }|
|
]]}
- meths.buf_clear_namespace(0, ns, 0, -1)
- meths.buf_set_extmark(0, ns, 0, 12, { end_col = 15, hl_group = 'ErrorMsg' })
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
+ api.nvim_buf_set_extmark(0, ns, 0, 12, { end_col = 15, hl_group = 'ErrorMsg' })
screen:expect{grid=[[
^this is the {4:tab} |
{1:~ }|
@@ -1925,50 +1966,62 @@ describe('extmark decorations', function()
it('highlight applies to a full TAB on line with matches #20885', function()
screen:try_resize(50, 3)
- meths.buf_set_lines(0, 0, -1, true, {'\t-- match1', ' -- match2'})
- funcs.matchadd('Underlined', 'match')
- meths.buf_set_extmark(0, ns, 0, 0, { end_row = 1, end_col = 0, hl_group = 'Visual' })
- meths.buf_set_extmark(0, ns, 1, 0, { end_row = 2, end_col = 0, hl_group = 'Visual' })
+ api.nvim_buf_set_lines(0, 0, -1, true, {'\t-- match1', ' -- match2'})
+ fn.matchadd('NonText', 'match')
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { end_row = 1, end_col = 0, hl_group = 'Search' })
+ api.nvim_buf_set_extmark(0, ns, 1, 0, { end_row = 2, end_col = 0, hl_group = 'Search' })
screen:expect{grid=[[
- {18: ^ -- }{29:match}{18:1} |
- {18: -- }{29:match}{18:2} |
+ {34: ^ -- }{35:match}{34:1} |
+ {34: -- }{35:match}{34:2} |
|
]]}
end)
pending('highlight applies to a full TAB in visual block mode', function()
screen:try_resize(50, 8)
- meths.buf_set_lines(0, 0, -1, true, {'asdf', '\tasdf', '\tasdf', '\tasdf', 'asdf'})
- meths.buf_set_extmark(0, ns, 0, 0, {end_row = 5, end_col = 0, hl_group = 'Underlined'})
+ command('hi! Visual guifg=NONE guibg=LightGrey')
+ api.nvim_buf_set_lines(0, 0, -1, true, {'asdf', '\tasdf', '\tasdf', '\tasdf', 'asdf'})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {end_row = 5, end_col = 0, hl_group = 'Underlined'})
screen:expect([[
{28:^asdf} |
- {28: asdf} |
- {28: asdf} |
- {28: asdf} |
+ {28: asdf} |*3
{28:asdf} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
feed('<C-V>Gll')
screen:expect([[
{29:asd}{28:f} |
- {29: }{28: asdf} |
- {29: }{28: asdf} |
- {29: }{28: asdf} |
+ {29: }{28: asdf} |*3
{29:as}{28:^df} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{24:-- VISUAL BLOCK --} |
]])
end)
+ it('highlight works properly with multibyte text and spell #26771', function()
+ insert('å£å£\n')
+ screen:try_resize(50, 3)
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { end_col = 3, hl_group = 'Search' })
+ screen:expect([[
+ {34:å£}å£ |
+ ^ |
+ |
+ ]])
+ command('setlocal spell')
+ screen:expect([[
+ {43:å£}{42:å£} |
+ ^ |
+ |
+ ]])
+ end)
+
it('supports multiline highlights', function()
insert(example_text)
feed 'gg'
for _,i in ipairs {1,2,3,5,6,7} do
for _,j in ipairs {2,5,10,15} do
- meths.buf_set_extmark(0, ns, i, j, { end_col=j+2, hl_group = 'NonText'})
+ api.nvim_buf_set_extmark(0, ns, i, j, { end_col=j+2, hl_group = 'NonText'})
end
end
screen:expect{grid=[[
@@ -1984,8 +2037,7 @@ describe('extmark decorations', function()
colpos = colpos+1 |
end |
end |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
feed'5<c-e>'
@@ -1997,17 +2049,11 @@ describe('extmark decorations', function()
colpos = colpos+1 |
end |
end |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
|
]]}
- meths.buf_set_extmark(0, ns, 1, 0, { end_line=8, end_col=10, hl_group = 'ErrorMsg'})
+ api.nvim_buf_set_extmark(0, ns, 1, 0, { end_line=8, end_col=10, hl_group = 'ErrorMsg'})
screen:expect{grid=[[
{4:^ }{36: }{4:f}{36:or}{4: _ }{36:= }{4:1, }{36:(c}{4:ount or 1) do} |
{4: }{36: }{4: }{36: }{4: lo}{36:ca}{4:l c}{36:el}{4:l = line[colpos]} |
@@ -2016,13 +2062,7 @@ describe('extmark decorations', function()
colpos = colpos+1 |
end |
end |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
|
]]}
end)
@@ -2031,7 +2071,7 @@ describe('extmark decorations', function()
screen:try_resize(50, 5)
insert(example_text)
feed'gg'
- meths.buf_set_extmark(0, ns, 0, 6, { end_col=13, hl_group = 'NonText', undo_restore=val})
+ api.nvim_buf_set_extmark(0, ns, 0, 6, { end_col=13, hl_group = 'NonText', undo_restore=val})
screen:expect{grid=[[
^for _,{1:item in} ipairs(items) do |
local text, hl_id_cell, count = unpack(item) |
@@ -2040,7 +2080,7 @@ describe('extmark decorations', function()
|
]]}
- meths.buf_set_text(0, 0, 4, 0, 8, {''})
+ api.nvim_buf_set_text(0, 0, 4, 0, 8, {''})
screen:expect{grid=[[
^for {1:em in} ipairs(items) do |
local text, hl_id_cell, count = unpack(item) |
@@ -2078,7 +2118,7 @@ describe('extmark decorations', function()
eq({ { 1, 0, 8, { end_col = 13, end_right_gravity = false, end_row = 0,
hl_eol = false, hl_group = "NonText", undo_restore = false,
ns_id = 1, priority = 4096, right_gravity = true } } },
- meths.buf_get_extmarks(0, ns, {0,0}, {0, -1}, {details=true}))
+ api.nvim_buf_get_extmarks(0, ns, {0,0}, {0, -1}, {details=true}))
end)
it('virtual text works with rightleft', function()
@@ -2086,10 +2126,10 @@ describe('extmark decorations', function()
insert('abcdefghijklmn')
feed('0')
command('set rightleft')
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'EOL', 'Underlined'}}})
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'right_align', 'Underlined'}}, virt_text_pos = 'right_align' })
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'win_col', 'Underlined'}}, virt_text_win_col = 20 })
- meths.buf_set_extmark(0, ns, 0, 2, { virt_text = {{'overlayed', 'Underlined'}}, virt_text_pos = 'overlay' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'EOL', 'Underlined'}}})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'right_align', 'Underlined'}}, virt_text_pos = 'right_align' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'win_col', 'Underlined'}}, virt_text_win_col = 20 })
+ api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = {{'overlayed', 'Underlined'}}, virt_text_pos = 'overlay' })
screen:expect{grid=[[
{28:ngila_thgir} {28:loc_niw} {28:LOE} nml{28:deyalrevo}b^a|
{1: ~}|
@@ -2135,7 +2175,74 @@ describe('extmark decorations', function()
]]}
end)
- it('works with double width char and rightleft', function()
+ it('virtual text overwrites double-width char properly', function()
+ screen:try_resize(50, 3)
+ insert('abcdefghijå£klmnopqrstuå£vwxå£yz')
+ feed('0')
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'!!!!!', 'Underlined'}}, virt_text_win_col = 11 })
+ screen:expect{grid=[[
+ ^abcdefghij {28:!!!!!}opqrstuå£vwxå£yz |
+ {1:~ }|
+ |
+ ]]}
+ feed('8x')
+ screen:expect{grid=[[
+ ^ijå£klmnopq{28:!!!!!} vwxå£yz |
+ {1:~ }|
+ |
+ ]]}
+ feed('3l5x')
+ screen:expect{grid=[[
+ ijå£^pqrstu {28:!!!!!} yz |
+ {1:~ }|
+ |
+ ]]}
+ feed('5x')
+ screen:expect{grid=[[
+ ijå£^uå£vwx {28:!!!!!} |
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('virtual text blending space does not overwrite double-width char', function()
+ screen:try_resize(50, 3)
+ insert('abcdefghijå£klmnopqrstuå£vwxå£yz')
+ feed('0')
+ command('hi Blendy guibg=Red blend=30')
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{' ! ! ', 'Blendy'}}, virt_text_win_col = 8, hl_mode = 'blend' })
+ screen:expect{grid=[[
+ ^abcdefgh{10:i}{7:!}{10:å£}{7:!}{10:l}mnopqrstuå£vwxå£yz |
+ {1:~ }|
+ |
+ ]]}
+ feed('x')
+ screen:expect{grid=[[
+ ^bcdefghi{10:j}{7:!}{10: k}{7:!}{10:m}nopqrstuå£vwxå£yz |
+ {1:~ }|
+ |
+ ]]}
+ feed('x')
+ screen:expect{grid=[[
+ ^cdefghij{10: }{7:!}{10:kl}{7:!}{10:n}opqrstuå£vwxå£yz |
+ {1:~ }|
+ |
+ ]]}
+ feed('x')
+ screen:expect{grid=[[
+ ^defghijå£{7:!}{10:lm}{7:!}{10:o}pqrstuå£vwxå£yz |
+ {1:~ }|
+ |
+ ]]}
+ feed('7x')
+ screen:expect{grid=[[
+ ^å£klmnop{10:q}{7:!}{10:st}{7:!}{10:å£}vwxå£yz |
+ {1:~ }|
+ |
+ ]]}
+ end)
+
+ it('virtual text works with double-width char and rightleft', function()
screen:try_resize(50, 3)
insert('abcdefghijå£klmnopqrstuå£vwxå£yz')
feed('0')
@@ -2145,10 +2252,10 @@ describe('extmark decorations', function()
{1: ~}|
|
]]}
- meths.buf_set_extmark(0, ns, 0, 2, { virt_text = {{'overlayed', 'Underlined'}}, virt_text_pos = 'overlay' })
- meths.buf_set_extmark(0, ns, 0, 14, { virt_text = {{'å¤', 'Underlined'}}, virt_text_pos = 'overlay' })
- meths.buf_set_extmark(0, ns, 0, 20, { virt_text = {{'\t', 'Underlined'}}, virt_text_pos = 'overlay' })
- meths.buf_set_extmark(0, ns, 0, 29, { virt_text = {{'å¤', 'Underlined'}}, virt_text_pos = 'overlay' })
+ api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = {{'overlayed', 'Underlined'}}, virt_text_pos = 'overlay' })
+ api.nvim_buf_set_extmark(0, ns, 0, 14, { virt_text = {{'å¤', 'Underlined'}}, virt_text_pos = 'overlay' })
+ api.nvim_buf_set_extmark(0, ns, 0, 20, { virt_text = {{'\t', 'Underlined'}}, virt_text_pos = 'overlay' })
+ api.nvim_buf_set_extmark(0, ns, 0, 29, { virt_text = {{'å¤', 'Underlined'}}, virt_text_pos = 'overlay' })
screen:expect{grid=[[
zy {28:å¤}wv {28: }qpon{28:å¤}k {28:deyalrevo}b^a|
{1: ~}|
@@ -2156,16 +2263,231 @@ describe('extmark decorations', function()
]]}
end)
+ it('virtual text is drawn correctly after delete and undo #27368', function()
+ insert('aaa\nbbb\nccc\nddd\neee')
+ command('vsplit')
+ api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = {{'EOL'}} })
+ feed('3gg')
+ screen:expect{grid=[[
+ aaa │aaa |
+ bbb │bbb |
+ ^ccc EOL │ccc EOL |
+ ddd │ddd |
+ eee │eee |
+ {1:~ }│{1:~ }|*8
+ {41:[No Name] [+] }{40:[No Name] [+] }|
+ |
+ ]]}
+ feed('dd')
+ screen:expect{grid=[[
+ aaa │aaa |
+ bbb │bbb |
+ ^ddd EOL │ddd EOL |
+ eee │eee |
+ {1:~ }│{1:~ }|*9
+ {41:[No Name] [+] }{40:[No Name] [+] }|
+ |
+ ]]}
+ command('silent undo')
+ screen:expect{grid=[[
+ aaa │aaa |
+ bbb │bbb |
+ ^ccc EOL │ccc EOL |
+ ddd │ddd |
+ eee │eee |
+ {1:~ }│{1:~ }|*8
+ {41:[No Name] [+] }{40:[No Name] [+] }|
+ |
+ ]]}
+ end)
+
it('works with both hl_group and sign_hl_group', function()
screen:try_resize(screen._width, 3)
insert('abcdefghijklmn')
- meths.buf_set_extmark(0, ns, 0, 0, {sign_text='S', sign_hl_group='NonText', hl_group='Error', end_col=14})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text='S', sign_hl_group='NonText', hl_group='Error', end_col=14})
screen:expect{grid=[[
{1:S }{4:abcdefghijklm^n} |
{1:~ }|
|
]]}
end)
+
+ it('virt_text_repeat_linebreak repeats virtual text on wrapped lines', function()
+ screen:try_resize(40, 5)
+ api.nvim_set_option_value('breakindent', true, {})
+ insert(example_text)
+ api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text = {{'│', 'NonText'}}, virt_text_pos = 'overlay', virt_text_repeat_linebreak = true })
+ api.nvim_buf_set_extmark(0, ns, 1, 3, { virt_text = {{'│', 'NonText'}}, virt_text_pos = 'overlay', virt_text_repeat_linebreak = true })
+ command('norm gg')
+ screen:expect{grid=[[
+ ^for _,item in ipairs(items) do |
+ {1:│} {1:│}local text, hl_id_cell, count = unpa|
+ {1:│} {1:│}ck(item) |
+ if hl_id_cell ~= nil then |
+ |
+ ]]}
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
+ api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text = {{'│', 'NonText'}}, virt_text_repeat_linebreak = true, virt_text_win_col = 0 })
+ api.nvim_buf_set_extmark(0, ns, 1, 0, { virt_text = {{'│', 'NonText'}}, virt_text_repeat_linebreak = true, virt_text_win_col = 2 })
+ screen:expect{grid=[[
+ ^for _,item in ipairs(items) do |
+ {1:│} {1:│} local text, hl_id_cell, count = unpa|
+ {1:│} {1:│} ck(item) |
+ if hl_id_cell ~= nil then |
+ |
+ ]]}
+ end)
+
+ it('supports URLs', function()
+ insert(example_text)
+
+ local url = 'https://example.com'
+
+ screen:set_default_attr_ids({
+ e = { bold = true, foreground = Screen.colors.Blue },
+ u = { url = url },
+ })
+
+ api.nvim_buf_set_extmark(0, ns, 1, 4, {
+ end_col = 14,
+ url = url,
+ })
+
+ screen:expect{grid=[[
+ for _,item in ipairs(items) do |
+ {u: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 |
+ en^d |
+ {e:~ }|
+ {e:~ }|
+ |
+ ]]}
+ end)
+
+ it('can replace marks in place with different decorations #27211', function()
+ local mark = api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_lines = {{{"foo", "ErrorMsg"}}}, })
+ screen:expect{grid=[[
+ ^ |
+ {4:foo} |
+ {1:~ }|*12
+ |
+ ]]}
+
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {
+ id = mark,
+ virt_text = { { "testing", "NonText" } },
+ virt_text_pos = "inline",
+ })
+ screen:expect{grid=[[
+ {1:^testing} |
+ {1:~ }|*13
+ |
+ ]]}
+
+ api.nvim_buf_del_extmark(0, ns, mark)
+ screen:expect{grid=[[
+ ^ |
+ {1:~ }|*13
+ |
+ ]]}
+
+ helpers.assert_alive()
+ end)
+
+ it('priority ordering of overlay or win_col virtual text at same position', function()
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'A'}}, virt_text_pos = 'overlay', priority = 100 })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'A'}}, virt_text_win_col = 30, priority = 100 })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'BB'}}, virt_text_pos = 'overlay', priority = 90 })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'BB'}}, virt_text_win_col = 30, priority = 90 })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'CCC'}}, virt_text_pos = 'overlay', priority = 80 })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'CCC'}}, virt_text_win_col = 30, priority = 80 })
+ screen:expect([[
+ ^ABC ABC |
+ {1:~ }|*13
+ |
+ ]])
+ end)
+
+ it('priority ordering of inline and non-inline virtual text at same char', function()
+ insert(('?'):rep(40) .. ('!'):rep(30))
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'A'}}, virt_text_pos = 'overlay', priority = 10 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'a'}}, virt_text_win_col = 15, priority = 10 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'BBBB'}}, virt_text_pos = 'inline', priority = 15 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'C'}}, virt_text_pos = 'overlay', priority = 20 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'c'}}, virt_text_win_col = 17, priority = 20 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'DDDD'}}, virt_text_pos = 'inline', priority = 25 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'E'}}, virt_text_pos = 'overlay', priority = 30 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'e'}}, virt_text_win_col = 19, priority = 30 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'FFFF'}}, virt_text_pos = 'inline', priority = 35 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'G'}}, virt_text_pos = 'overlay', priority = 40 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'g'}}, virt_text_win_col = 21, priority = 40 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'HHHH'}}, virt_text_pos = 'inline', priority = 45 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'I'}}, virt_text_pos = 'overlay', priority = 50 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'i'}}, virt_text_win_col = 23, priority = 50 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'JJJJ'}}, virt_text_pos = 'inline', priority = 55 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'K'}}, virt_text_pos = 'overlay', priority = 60 })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = {{'k'}}, virt_text_win_col = 25, priority = 60 })
+ screen:expect([[
+ ???????????????a?c?e????????????????????ABBBCDDDEF|
+ FFGHHHIJJJK!!!!!!!!!!g!i!k!!!!!!!!!!!!!^! |
+ {1:~ }|*12
+ |
+ ]])
+ feed('02x$')
+ screen:expect([[
+ ???????????????a?c?e??????????????????ABBBCDDDEFFF|
+ GHHHIJJJK!!!!!!!!!!!!g!i!k!!!!!!!!!!!^! |
+ {1:~ }|*12
+ |
+ ]])
+ feed('02x$')
+ screen:expect([[
+ ???????????????a?c?e?g??????????????ABBBCDDDEFFFGH|
+ HHIJJJK!!!!!!!!!!!!!!!!i!k!!!!!!!!!^! |
+ {1:~ }|*12
+ |
+ ]])
+ feed('02x$')
+ screen:expect([[
+ ???????????????a?c?e?g????????????ABBBCDDDEFFFGHHH|
+ IJJJK!!!!!!!!!!!!!!!!!!i!k!!!!!!!^! |
+ {1:~ }|*12
+ |
+ ]])
+ command('set nowrap')
+ feed('0')
+ screen:expect([[
+ ^???????????????a?c?e?g?i?k????????ABBBCDDDEFFFGHHH|
+ {1:~ }|*13
+ |
+ ]])
+ feed('2x')
+ screen:expect([[
+ ^???????????????a?c?e?g?i?k??????ABBBCDDDEFFFGHHHIJ|
+ {1:~ }|*13
+ |
+ ]])
+ feed('2x')
+ screen:expect([[
+ ^???????????????a?c?e?g?i?k????ABBBCDDDEFFFGHHHIJJJ|
+ {1:~ }|*13
+ |
+ ]])
+ feed('2x')
+ screen:expect([[
+ ^???????????????a?c?e?g?i?k??ABBBCDDDEFFFGHHHIJJJK!|
+ {1:~ }|*13
+ |
+ ]])
+ end)
end)
describe('decorations: inline virtual text', function()
@@ -2181,7 +2503,7 @@ describe('decorations: inline virtual text', function()
[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};
+ [7] = {background = Screen.colors.LightGrey, foreground = Screen.colors.Black};
[8] = {bold = true};
[9] = {background = Screen.colors.Plum1};
[10] = {foreground = Screen.colors.SlateBlue};
@@ -2198,7 +2520,7 @@ describe('decorations: inline virtual text', function()
[21] = {reverse = true, foreground = Screen.colors.SlateBlue}
}
- ns = meths.create_namespace 'test'
+ ns = api.nvim_create_namespace 'test'
end)
@@ -2219,7 +2541,7 @@ describe('decorations: inline virtual text', function()
|
]]}
- meths.buf_set_extmark(0, ns, 1, 14, {virt_text={{': ', 'Special'}, {'string', 'Type'}}, virt_text_pos='inline'})
+ api.nvim_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|
@@ -2279,9 +2601,9 @@ describe('decorations: inline virtual text', function()
|
]]}
- meths.buf_set_extmark(0, ns, 0, 5, {virt_text={{''}, {''}}, virt_text_pos='inline'})
- meths.buf_set_extmark(0, ns, 1, 14, {virt_text={{''}, {': ', 'Special'}}, virt_text_pos='inline'})
- meths.buf_set_extmark(0, ns, 1, 48, {virt_text={{''}, {''}}, virt_text_pos='inline'})
+ api.nvim_buf_set_extmark(0, ns, 0, 5, {virt_text={{''}, {''}}, virt_text_pos='inline'})
+ api.nvim_buf_set_extmark(0, ns, 1, 14, {virt_text={{''}, {': ', 'Special'}}, virt_text_pos='inline'})
+ api.nvim_buf_set_extmark(0, ns, 1, 48, {virt_text={{''}, {''}}, virt_text_pos='inline'})
screen:expect{grid=[[
^for _,item in ipairs(items) do |
local text{10:: }, hl_id_cell, count = unpack(item)|
@@ -2295,7 +2617,7 @@ describe('decorations: inline virtual text', function()
|
]]}
- meths.buf_set_extmark(0, ns, 1, 14, {virt_text={{''}, {'string', 'Type'}}, virt_text_pos='inline'})
+ api.nvim_buf_set_extmark(0, ns, 1, 14, {virt_text={{''}, {'string', 'Type'}}, virt_text_pos='inline'})
feed('V')
screen:expect{grid=[[
^f{7:or _,item in ipairs(items) do} |
@@ -2327,8 +2649,8 @@ describe('decorations: inline virtual text', function()
it('Normal mode "gM" command works properly', function()
command([[call setline(1, '123456789')]])
- meths.buf_set_extmark(0, ns, 0, 2, { virt_text = { { 'bbb', 'Special' } }, virt_text_pos = 'inline' })
- meths.buf_set_extmark(0, ns, 0, 7, { virt_text = { { 'bbb', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 2, { virt_text = { { 'bbb', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 7, { virt_text = { { 'bbb', 'Special' } }, virt_text_pos = 'inline' })
feed('gM')
screen:expect{grid=[[
12{10:bbb}34^567{10:bbb}89 |
@@ -2340,8 +2662,8 @@ describe('decorations: inline virtual text', function()
local function test_normal_gj_gk()
screen:try_resize(60, 6)
command([[call setline(1, repeat([repeat('a', 55)], 2))]])
- meths.buf_set_extmark(0, ns, 0, 40, { virt_text = { { ('b'):rep(10), 'Special' } }, virt_text_pos = 'inline' })
- meths.buf_set_extmark(0, ns, 1, 40, { virt_text = { { ('b'):rep(10), 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = { { ('b'):rep(10), 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 1, 40, { virt_text = { { ('b'):rep(10), 'Special' } }, virt_text_pos = 'inline' })
screen:expect{grid=[[
^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa{10:bbbbbbbbbb}aaaaaaaaaa|
aaaaa |
@@ -2419,8 +2741,8 @@ describe('decorations: inline virtual text', function()
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' })
+ api.nvim_buf_set_extmark(0, ns, 0, 4, { virt_text = { { ' virtual text ', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 4, { virt_text = { { ' virtual text ', 'Special' } }, virt_text_pos = 'inline' })
feed '^'
feed '4l'
screen:expect{grid=[[
@@ -2433,7 +2755,7 @@ describe('decorations: inline virtual text', function()
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' })
+ api.nvim_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 |
@@ -2444,7 +2766,7 @@ describe('decorations: inline virtual text', function()
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' })
+ api.nvim_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 |
@@ -2455,7 +2777,7 @@ describe('decorations: inline virtual text', function()
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' })
+ api.nvim_buf_set_extmark(0, ns, 0, 4, { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
feed '^'
feed '3l'
feed 'a'
@@ -2481,7 +2803,7 @@ describe('decorations: inline virtual text', function()
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' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
screen:expect{grid=[[
{10:^virtual text} |
{1:~ }|
@@ -2495,8 +2817,8 @@ describe('decorations: inline virtual text', function()
call setline(1, ['', 'aaa', '', 'bbbbbb'])
normal gg0
]])
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = { { string.rep('X', 60), 'Special' } }, virt_text_pos = 'inline' })
- meths.buf_set_extmark(0, ns, 2, 0, { virt_text = { { string.rep('X', 61), 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { string.rep('X', 60), 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = { { string.rep('X', 61), 'Special' } }, virt_text_pos = 'inline' })
feed('$')
screen:expect{grid=[[
{10:^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
@@ -2504,8 +2826,7 @@ describe('decorations: inline virtual text', function()
{10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
{10:X} |
bbbbbb |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
feed('j')
@@ -2515,8 +2836,7 @@ describe('decorations: inline virtual text', function()
{10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
{10:X} |
bbbbbb |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
feed('j')
@@ -2526,8 +2846,7 @@ describe('decorations: inline virtual text', function()
{10:^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
{10:X} |
bbbbbb |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
feed('j')
@@ -2537,8 +2856,7 @@ describe('decorations: inline virtual text', function()
{10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
{10:X} |
bbbbb^b |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
feed('0<C-V>2l2k')
@@ -2548,8 +2866,7 @@ describe('decorations: inline virtual text', function()
{10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
{10:X} |
{7:bbb}bbb |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{8:-- VISUAL BLOCK --} |
]]}
feed([[<Esc>/aaa\n\%V<CR>]])
@@ -2559,8 +2876,7 @@ describe('decorations: inline virtual text', function()
{10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
{10:X} |
bbbbbb |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{16:search hit BOTTOM, continuing at TOP} |
]]}
feed('3ggic')
@@ -2570,8 +2886,7 @@ describe('decorations: inline virtual text', function()
c{10:^XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
{10:XX} |
bbbbbb |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{8:-- INSERT --} |
]]}
feed([[<Esc>/aaa\nc\%V<CR>]])
@@ -2581,8 +2896,7 @@ describe('decorations: inline virtual text', function()
{12:c}{10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
{10:XX} |
bbbbbb |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{16:search hit BOTTOM, continuing at TOP} |
]]}
end)
@@ -2594,7 +2908,7 @@ describe('decorations: inline virtual text', function()
feed('<TAB>')
feed('test')
feed('<ESC>')
- meths.buf_set_extmark(0, ns, 0, 1, { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_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 |
@@ -2635,7 +2949,7 @@ describe('decorations: inline virtual text', 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' })
+ api.nvim_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:~ }|
@@ -2646,10 +2960,10 @@ describe('decorations: inline virtual text', function()
it('search highlight is correct', function()
insert('foo foo foo bar\nfoo foo foo bar')
feed('gg0')
- meths.buf_set_extmark(0, ns, 0, 9, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
- meths.buf_set_extmark(0, ns, 0, 9, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
- meths.buf_set_extmark(0, ns, 1, 9, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
- meths.buf_set_extmark(0, ns, 1, 9, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
+ api.nvim_buf_set_extmark(0, ns, 0, 9, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 9, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 1, 9, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 1, 9, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
screen:expect{grid=[[
^foo foo f{10:AAABBB}oo bar |
foo foo f{10:CCCDDD}oo bar |
@@ -2663,7 +2977,7 @@ describe('decorations: inline virtual text', function()
/foo^ |
]]}
- meths.buf_set_extmark(0, ns, 0, 13, { virt_text = { { 'EEE', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 0, 13, { virt_text = { { 'EEE', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
feed('<C-G>')
screen:expect{grid=[[
{12:foo} {12:foo} {13:f}{10:AAA}{21:BBB}{13:oo} b{10:EEE}ar |
@@ -2675,10 +2989,10 @@ describe('decorations: inline virtual text', function()
it('Visual select highlight is correct', function()
insert('foo foo foo bar\nfoo foo foo bar')
feed('gg0')
- meths.buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
- meths.buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
- meths.buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
- meths.buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
+ api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
feed('8l')
screen:expect{grid=[[
foo foo {10:AAABBB}^foo bar |
@@ -2694,7 +3008,7 @@ describe('decorations: inline virtual text', function()
{8:-- VISUAL BLOCK --} |
]]}
- meths.buf_set_extmark(0, ns, 0, 10, { virt_text = { { 'EEE', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 0, 10, { virt_text = { { 'EEE', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
screen:expect{grid=[[
foo fo{7:o }{10:AAA}{20:BBB}{7:f}o{10:EEE}o bar |
foo fo^o{7: }{20:CCC}{10:DDD}{7:f}oo bar |
@@ -2704,12 +3018,12 @@ describe('decorations: inline virtual text', function()
it('inside highlight range of another extmark', function()
insert('foo foo foo bar\nfoo foo foo bar')
- meths.buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
- meths.buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
- meths.buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
- meths.buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
- meths.buf_set_extmark(0, ns, 0, 4, { end_col = 11, hl_group = 'Search' })
- meths.buf_set_extmark(0, ns, 1, 4, { end_col = 11, hl_group = 'Search' })
+ api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
+ api.nvim_buf_set_extmark(0, ns, 0, 4, { end_col = 11, hl_group = 'Search' })
+ api.nvim_buf_set_extmark(0, ns, 1, 4, { end_col = 11, hl_group = 'Search' })
screen:expect{grid=[[
foo {12:foo }{10:AAA}{19:BBB}{12:foo} bar |
foo {12:foo }{19:CCC}{10:DDD}{12:foo} ba^r |
@@ -2719,10 +3033,10 @@ describe('decorations: inline virtual text', function()
it('inside highlight range of syntax', function()
insert('foo foo foo bar\nfoo foo foo bar')
- meths.buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
- meths.buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
- meths.buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
- meths.buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
+ api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'AAA', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { 'BBB', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'CCC', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 1, 8, { virt_text = { { 'DDD', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
command([[syntax match Search 'foo \zsfoo foo\ze bar']])
screen:expect{grid=[[
foo {12:foo }{10:AAA}{19:BBB}{12:foo} bar |
@@ -2734,7 +3048,7 @@ describe('decorations: inline virtual text', function()
it('cursor position is correct when inserting around a virtual text with left gravity', function()
screen:try_resize(27, 4)
insert(('a'):rep(15))
- meths.buf_set_extmark(0, ns, 0, 8, { virt_text = { { ('>'):rep(43), 'Special' } }, virt_text_pos = 'inline', right_gravity = false })
+ api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = { { ('>'):rep(43), 'Special' } }, virt_text_pos = 'inline', right_gravity = false })
command('setlocal showbreak=+ breakindent breakindentopt=shift:2')
feed('08l')
screen:expect{grid=[[
@@ -2805,8 +3119,8 @@ describe('decorations: inline virtual text', function()
screen:try_resize(30, 4)
command('setlocal showbreak=+ breakindent breakindentopt=shift:2')
insert(('a'):rep(15))
- meths.buf_set_extmark(0, ns, 0, 8, { virt_text = {{ ('>'):rep(32), 'Special' }}, virt_text_pos = 'inline', right_gravity = false })
- meths.buf_set_extmark(0, ns, 0, 8, { virt_text = {{ ('<'):rep(32), 'Special' }}, virt_text_pos = 'inline', right_gravity = true })
+ api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = {{ ('>'):rep(32), 'Special' }}, virt_text_pos = 'inline', right_gravity = false })
+ api.nvim_buf_set_extmark(0, ns, 0, 8, { virt_text = {{ ('<'):rep(32), 'Special' }}, virt_text_pos = 'inline', right_gravity = true })
feed('08l')
screen:expect{grid=[[
aaaaaaaa{10:>>>>>>>>>>>>>>>>>>>>>>}|
@@ -2903,8 +3217,8 @@ describe('decorations: inline virtual text', function()
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' })
+ api.nvim_buf_set_extmark(0, ns, 0, 50, { virt_text = { { 'virtual text', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_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|
@@ -2916,7 +3230,7 @@ describe('decorations: inline virtual text', function()
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' })
+ api.nvim_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|
@@ -2928,7 +3242,7 @@ describe('decorations: inline virtual text', function()
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' })
+ api.nvim_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 |
@@ -2940,7 +3254,7 @@ describe('decorations: inline virtual text', function()
it('highlighting does not extend with no wrap and 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' })
+ api.nvim_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|
@@ -2952,7 +3266,7 @@ describe('decorations: inline virtual text', function()
it('hidden virtual text does not interfere with Visual highlight', function()
insert('abcdef')
command('set nowrap')
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'XXX', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'XXX', 'Special' } }, virt_text_pos = 'inline' })
feed('V2zl')
screen:expect{grid=[[
{10:X}{7:abcde}^f |
@@ -2979,7 +3293,7 @@ describe('decorations: inline virtual text', function()
test
test]])
command('set number')
- meths.buf_set_extmark(0, ns, 0, 1, { virt_text = { { string.rep('X', 55), 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_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}|
@@ -2992,7 +3306,7 @@ describe('decorations: inline virtual text', function()
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' })
+ api.nvim_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=[[
@@ -3010,7 +3324,7 @@ describe('decorations: inline virtual text', function()
it('smoothscroll works correctly when virtual text wraps', function()
insert('foobar')
- meths.buf_set_extmark(0, ns, 0, 3, { virt_text = { { string.rep('X', 55), 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 3, { virt_text = { { string.rep('X', 55), 'Special' } }, virt_text_pos = 'inline' })
command('setlocal smoothscroll')
screen:expect{grid=[[
foo{10:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX}|
@@ -3036,9 +3350,9 @@ describe('decorations: inline virtual text', function()
]])
insert('aaa\tbbb')
command("set diff")
- meths.buf_set_extmark(0, ns, 0, 1, { virt_text = { { 'test', 'Special' } }, virt_text_pos = 'inline', right_gravity = false })
- meths.buf_set_extmark(0, ns, 5, 0, { virt_text = { { '!', 'Special' } }, virt_text_pos = 'inline' })
- meths.buf_set_extmark(0, ns, 5, 3, { virt_text = { { '' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 1, { virt_text = { { 'test', 'Special' } }, virt_text_pos = 'inline', right_gravity = false })
+ api.nvim_buf_set_extmark(0, ns, 5, 0, { virt_text = { { '!', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 5, 3, { virt_text = { { '' } }, virt_text_pos = 'inline' })
command("vnew")
insert([[
000
@@ -3052,13 +3366,11 @@ describe('decorations: inline virtual text', function()
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 }│{9:000}{5:9}{9: }|*2
{9:000 }│{5:9}{9:000 }|
{9:000 }│{9:000}{5:9}{9: }|
{9:aaabbb }│{14:!}{9:aaa}{5: }{9:bbb }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*2
{15:[No Name] [+] }{13:[No Name] [+] }|
|
]]}
@@ -3066,13 +3378,11 @@ describe('decorations: inline virtual text', function()
feed('zl')
screen:expect{grid=[[
{9:000 }│{14:test}{9:000 }|
- {9:000 }│{9:00}{5:9}{9: }|
- {9:000 }│{9:00}{5:9}{9: }|
+ {9:000 }│{9:00}{5:9}{9: }|*2
{9:000 }│{9:000 }|
{9:000 }│{9:00}{5:9}{9: }|
{9:aaabbb }│{9:aaa}{5: }{9:bb^b }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*2
{13:[No Name] [+] }{15:[No Name] [+] }|
|
]]}
@@ -3081,8 +3391,8 @@ describe('decorations: inline virtual text', function()
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' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { string.rep('a', 55), 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_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 |
@@ -3094,7 +3404,7 @@ describe('decorations: inline virtual text', function()
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' })
+ api.nvim_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 |
@@ -3112,8 +3422,8 @@ describe('decorations: inline virtual text', function()
bbbbb
ccccc]])
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = {{'foo'}}, virt_text_pos = 'inline' })
- meths.buf_set_extmark(0, ns, 2, 0, { virt_text = {{'bar'}}, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = {{'foo'}}, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 2, 0, { virt_text = {{'bar'}}, virt_text_pos = 'inline' })
screen:expect{grid=[[
fooaaaaa |
bbbbb |
@@ -3141,44 +3451,37 @@ describe('decorations: inline virtual text', function()
screen:expect{grid=[[
{18:^+-- 2 lines: aaaaa·······························································}|
{17:+-- 2 lines: ccccc·······························································}|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
feed('j')
screen:expect{grid=[[
{17:+-- 2 lines: aaaaa·······························································}|
{18:^+-- 2 lines: ccccc·······························································}|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
end)
it('does not crash at right edge of wide window #23848', function()
screen:try_resize(82, 5)
- meths.buf_set_extmark(0, ns, 0, 0, {virt_text = {{('a'):rep(82)}, {'b'}}, virt_text_pos = 'inline'})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_text = {{('a'):rep(82)}, {'b'}}, virt_text_pos = 'inline'})
screen:expect{grid=[[
^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
b |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
command('set nowrap')
screen:expect{grid=[[
^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
feed('82i0<Esc>0')
screen:expect{grid=[[
^0000000000000000000000000000000000000000000000000000000000000000000000000000000000|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
command('set wrap')
@@ -3196,7 +3499,7 @@ describe('decorations: inline virtual text', function()
setlocal nowrap list listchars=extends:!
call setline(1, repeat('a', 51))
]])
- meths.buf_set_extmark(0, ns, 0, 50, { virt_text = { { 'bbb', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 50, { virt_text = { { 'bbb', 'Special' } }, virt_text_pos = 'inline' })
feed('20l')
screen:expect{grid=[[
aaaaaaaaaaaaaaaaaaaa^aaaaaaaaaaaaaaaaaaaaaaaaaaaaa{1:!}|
@@ -3233,7 +3536,7 @@ describe('decorations: inline virtual text', function()
command('set nowrap')
command('set list')
command('set listchars+=extends:c')
- meths.buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'test', 'Special' } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { virt_text = { { 'test', 'Special' } }, virt_text_pos = 'inline' })
insert(string.rep('a', 50))
feed('gg0')
screen:expect{grid=[[
@@ -3246,8 +3549,8 @@ describe('decorations: inline virtual text', function()
it('blockwise Visual highlight with double-width virtual text (replace)', function()
screen:try_resize(60, 6)
insert('123456789\n123456789\n123456789\n123456789')
- meths.buf_set_extmark(0, ns, 1, 1, { virt_text = { { '-å£-', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
- meths.buf_set_extmark(0, ns, 2, 2, { virt_text = { { 'å£', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
+ api.nvim_buf_set_extmark(0, ns, 1, 1, { virt_text = { { '-å£-', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
+ api.nvim_buf_set_extmark(0, ns, 2, 2, { virt_text = { { 'å£', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'replace' })
feed('gg0')
screen:expect{grid=[[
^123456789 |
@@ -3316,8 +3619,8 @@ describe('decorations: inline virtual text', function()
it('blockwise Visual highlight with double-width virtual text (combine)', function()
screen:try_resize(60, 6)
insert('123456789\n123456789\n123456789\n123456789')
- meths.buf_set_extmark(0, ns, 1, 1, { virt_text = { { '-å£-', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
- meths.buf_set_extmark(0, ns, 2, 2, { virt_text = { { 'å£', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 1, 1, { virt_text = { { '-å£-', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
+ api.nvim_buf_set_extmark(0, ns, 2, 2, { virt_text = { { 'å£', 'Special' } }, virt_text_pos = 'inline', hl_mode = 'combine' })
feed('gg0')
screen:expect{grid=[[
^123456789 |
@@ -3392,7 +3695,7 @@ describe('decorations: inline virtual text', function()
call setline(1, repeat('a', 28))
normal! $
]])
- meths.buf_set_extmark(0, ns, 0, 27, { virt_text = { { ('123'):rep(23) } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 27, { virt_text = { { ('123'):rep(23) } }, virt_text_pos = 'inline' })
feed(':<CR>') -- Have a screen line that doesn't start with spaces
screen:expect{grid=[[
1 aaaaaaaaaaaaaaaaaaaaaaaaaa|
@@ -3416,26 +3719,20 @@ describe('decorations: inline virtual text', function()
{1:+}23123123123123123123123|
{1:+}12312312312312312312312|
{1:+}3^a |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}12312312312312312312312|
{1:+}3^a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}3^a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
: |
]]}
feed('zbi')
@@ -3480,26 +3777,20 @@ describe('decorations: inline virtual text', function()
{1:+}31231231231231231231231|
{1:+}23123123123123123123123|
{1:+}^a |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}23123123123123123123123|
{1:+}^a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}^a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
: |
]]}
feed('023x$')
@@ -3516,26 +3807,20 @@ describe('decorations: inline virtual text', function()
{1:+}31231231231231231231231|
{1:+}23123123123123123123123|
{1:+}^a |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}23123123123123123123123|
{1:+}^a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
: |
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}^a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
: |
]]}
feed('zbi')
@@ -3552,8 +3837,7 @@ describe('decorations: inline virtual text', function()
1 ^12312312312312312312312312|
{1:+}31231231231231231231231|
{1:+}23123123123123123123a |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{8:-- INSERT --} |
]]}
feed('<Esc>')
@@ -3561,26 +3845,20 @@ describe('decorations: inline virtual text', function()
1 12312312312312312312312312|
{1:+}31231231231231231231231|
{1:+}23123123123123123123^a |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}31231231231231231231231|
{1:+}23123123123123123123^a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:+}23123123123123123123^a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]]}
feed('zbx')
@@ -3588,8 +3866,7 @@ describe('decorations: inline virtual text', function()
1 ^12312312312312312312312312|
{1:+}31231231231231231231231|
{1:+}23123123123123123123 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
feed('26ia<Esc>a')
@@ -3631,7 +3908,7 @@ describe('decorations: inline virtual text', function()
call setline(1, repeat("\t", 4) .. 'a')
normal! $
]])
- meths.buf_set_extmark(0, ns, 0, 3, { virt_text = { { ('12'):rep(32) } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 3, { virt_text = { { ('12'):rep(32) } }, virt_text_pos = 'inline' })
screen:expect{grid=[[
{1:<------><------><------>}121212|
121212121212121212121212121212|
@@ -3645,26 +3922,20 @@ describe('decorations: inline virtual text', function()
{1:<<<}212121212121212121212121212|
1212121212121212121212121212{1:<-}|
{1:----->}^a |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:<<<}2121212121212121212121212{1:<-}|
{1:----->}^a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:<<<-->}^a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]]}
feed('zbh')
@@ -3708,26 +3979,20 @@ describe('decorations: inline virtual text', function()
{1:<<<}212121212121212121212121212|
1212121212121212121212121212 |
^ a |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:<<<}2121212121212121212121212 |
^ a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
feed('<C-E>')
screen:expect{grid=[[
{1:<<<} ^ a |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]]}
end)
@@ -3739,13 +4004,12 @@ describe('decorations: inline virtual text', function()
call setline(1, repeat('a', 50) .. ' ' .. repeat('c', 45))
normal! $
]])
- meths.buf_set_extmark(0, ns, 0, 50, { virt_text = { { ('b'):rep(10) } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 50, { virt_text = { { ('b'):rep(10) } }, virt_text_pos = 'inline' })
screen:expect{grid=[[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{1:+}bbbbbbbbbb |
{1:+}cccccccccccccccccccccccccccccccccccccccccccc^c |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
feed('05x$')
@@ -3753,8 +4017,7 @@ describe('decorations: inline virtual text', function()
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbb|
{1:+}bbbbb |
{1:+}cccccccccccccccccccccccccccccccccccccccccccc^c |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
end)
@@ -3764,7 +4027,7 @@ describe('decorations: inline virtual text', function()
call setline(1, repeat('a', 40) .. 'å£' .. '12345')
normal! $
]])
- meths.buf_set_extmark(0, ns, 0, 40, { virt_text = { { ('b'):rep(9) } }, virt_text_pos = 'inline' })
+ api.nvim_buf_set_extmark(0, ns, 0, 40, { virt_text = { { ('b'):rep(9) } }, virt_text_pos = 'inline' })
screen:expect{grid=[[
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbb{1:>}|
å£1234^5 |
@@ -3791,7 +4054,7 @@ describe('decorations: virtual lines', function()
[9] = {foreground = Screen.colors.Brown};
}
- ns = meths.create_namespace 'test'
+ ns = api.nvim_create_namespace 'test'
end)
local example_text2 = [[
@@ -3806,16 +4069,31 @@ if (h->n_buckets < new_n_buckets) { // expand
it('works with one line', function()
insert(example_text2)
- feed 'gg'
- meths.buf_set_extmark(0, ns, 1, 33, {
+ feed '2gg'
+ screen:expect{grid=[[
+ 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 && val_size) { |
+ char *new_vals = krealloc( h->vals_buf, new_n_|
+ buckets * val_size); |
+ h->vals_buf = new_vals; |
+ } |
+ } |
+ {1:~ }|
+ |
+ ]]}
+
+ api.nvim_buf_set_extmark(0, ns, 1, 33, {
virt_lines={ {{">> ", "NonText"}, {"krealloc", "Identifier"}, {": change the size of an allocation"}}};
virt_lines_above=true;
})
screen:expect{grid=[[
- ^if (h->n_buckets < new_n_buckets) { // expand |
+ if (h->n_buckets < new_n_buckets) { // expand |
{1:>> }{2:krealloc}: change the size of an allocation |
- khkey_t *new_keys = (khkey_t *)krealloc((void *)|
+ ^khkey_t *new_keys = (khkey_t *)krealloc((void *)|
h->keys, new_n_buckets * sizeof(khkey_t)); |
h->keys = new_keys; |
if (kh_is_map && val_size) { |
@@ -3876,10 +4154,9 @@ if (h->n_buckets < new_n_buckets) { // expand
|
]]}
- meths.buf_set_extmark(0, ns, 5, 0, {
+ api.nvim_buf_set_extmark(0, ns, 5, 0, {
virt_lines = { {{"^^ REVIEW:", "Todo"}, {" new_vals variable seems unnecessary?", "Comment"}} };
})
- -- TODO: what about the cursor??
screen:expect{grid=[[
if (h->n_buckets < new_n_buckets) { // expand |
khkey_t *new_keys = (khkey_t *) |
@@ -3895,8 +4172,7 @@ if (h->n_buckets < new_n_buckets) { // expand
|
]]}
- meths.buf_clear_namespace(0, ns, 0, -1)
- -- Cursor should be drawn on the correct line. #22704
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
screen:expect{grid=[[
if (h->n_buckets < new_n_buckets) { // expand |
khkey_t *new_keys = (khkey_t *) |
@@ -3932,7 +4208,7 @@ if (h->n_buckets < new_n_buckets) { // expand
|
]]}
- meths.buf_set_extmark(0, ns, 0, 0, {
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {
virt_lines={
{{"refactor(khash): ", "Special"}, {"take size of values as parameter"}};
{{"Author: Dev Devsson, "}, {"Tue Aug 31 10:13:37 2021", "Comment"}};
@@ -3993,7 +4269,7 @@ if (h->n_buckets < new_n_buckets) { // expand
|
]]}
- local id = meths.buf_set_extmark(0, ns, 7, 0, {
+ local id = api.nvim_buf_set_extmark(0, ns, 7, 0, {
virt_lines={{{"Grugg"}}};
right_gravity=false;
})
@@ -4076,7 +4352,7 @@ if (h->n_buckets < new_n_buckets) { // expand
|
]]}
- meths.buf_del_extmark(0, ns, id)
+ api.nvim_buf_del_extmark(0, ns, id)
screen:expect{grid=[[
if (h->n_buckets < new_n_buckets) { // expand |
khkey_t *new_keys = (khkey_t *)krealloc((void *)|
@@ -4112,7 +4388,7 @@ if (h->n_buckets < new_n_buckets) { // expand
|
]]}
- local id = meths.buf_set_extmark(0, ns, 8, 0, {
+ local id = api.nvim_buf_set_extmark(0, ns, 8, 0, {
virt_lines={{{"Grugg"}}};
virt_lines_above = true,
})
@@ -4158,9 +4434,7 @@ if (h->n_buckets < new_n_buckets) { // expand
^char *new_vals = krealloc( h->vals_buf, new_n_|
buckets * val_size); |
Grugg |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
@@ -4168,31 +4442,14 @@ if (h->n_buckets < new_n_buckets) { // expand
screen:expect{grid=[[
^ |
Grugg |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*9
--No lines in buffer-- |
]]}
- meths.buf_del_extmark(0, ns, id)
+ api.nvim_buf_del_extmark(0, ns, id)
screen:expect{grid=[[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
--No lines in buffer-- |
]]}
end)
@@ -4201,19 +4458,11 @@ if (h->n_buckets < new_n_buckets) { // expand
command([[syntax region foo keepend start='^foo' end='^$']])
command('syntax sync minlines=100')
insert('foo')
- meths.buf_set_extmark(0, ns, 0, 0, {virt_lines = {{{'bar', 'Comment'}}}})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_lines = {{{'bar', 'Comment'}}}})
screen:expect([[
fo^o |
{6:bar} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*9
|
]])
end)
@@ -4223,7 +4472,7 @@ if (h->n_buckets < new_n_buckets) { // expand
insert("aa\nbb\ncc\ndd\nee\nff\ngg\nhh")
feed 'gg'
- meths.buf_set_extmark(0, ns, 6, 0, {
+ api.nvim_buf_set_extmark(0, ns, 6, 0, {
virt_lines={
{{"they see me"}};
{{"scrolling", "Special"}};
@@ -4325,8 +4574,7 @@ if (h->n_buckets < new_n_buckets) { // expand
they |
{7:hatin'} |
^hh |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
@@ -4335,9 +4583,7 @@ if (h->n_buckets < new_n_buckets) { // expand
they |
{7:hatin'} |
^hh |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
@@ -4345,21 +4591,14 @@ if (h->n_buckets < new_n_buckets) { // expand
screen:expect{grid=[[
{7:hatin'} |
^hh |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]]}
feed '<c-e>'
screen:expect{grid=[[
^hh |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]]}
end)
@@ -4383,7 +4622,7 @@ if (h->n_buckets < new_n_buckets) { // expand
|
]]}
- local markid = meths.buf_set_extmark(0, ns, 2, 0, {
+ local markid = api.nvim_buf_set_extmark(0, ns, 2, 0, {
virt_lines={
{{"Some special", "Special"}};
{{"remark about codes", "Comment"}};
@@ -4405,7 +4644,7 @@ if (h->n_buckets < new_n_buckets) { // expand
|
]]}
- meths.buf_set_extmark(0, ns, 2, 0, {
+ api.nvim_buf_set_extmark(0, ns, 2, 0, {
virt_lines={
{{"Some special", "Special"}};
{{"remark about codes", "Comment"}};
@@ -4433,7 +4672,7 @@ if (h->n_buckets < new_n_buckets) { // expand
it('works with hard TABs', function()
insert(example_text2)
feed 'gg'
- meths.buf_set_extmark(0, ns, 1, 0, {
+ api.nvim_buf_set_extmark(0, ns, 1, 0, {
virt_lines={ {{">>", "NonText"}, {"\tvery\ttabby", "Identifier"}, {"text\twith\ttabs"}}};
})
screen:expect{grid=[[
@@ -4507,8 +4746,8 @@ if (h->n_buckets < new_n_buckets) { // expand
bbb
ccc
ddd]])
- meths.buf_set_extmark(0, ns, 0, 0, {end_row = 2, virt_lines = {{{'VIRT LINE 1', 'NonText'}}}})
- meths.buf_set_extmark(0, ns, 3, 0, {end_col = 2, virt_lines = {{{'VIRT LINE 2', 'NonText'}}}})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {end_row = 2, virt_lines = {{{'VIRT LINE 1', 'NonText'}}}})
+ api.nvim_buf_set_extmark(0, ns, 3, 0, {end_col = 2, virt_lines = {{{'VIRT LINE 2', 'NonText'}}}})
screen:expect{grid=[[
aaa |
{1:VIRT LINE 1} |
@@ -4529,8 +4768,8 @@ if (h->n_buckets < new_n_buckets) { // expand
ccc
ddd]])
command('set number rightleft')
- meths.buf_set_extmark(0, ns, 0, 0, {virt_lines = {{{'VIRT LINE 1', 'NonText'}}}, virt_lines_leftcol = true})
- meths.buf_set_extmark(0, ns, 3, 0, {virt_lines = {{{'VIRT LINE 2', 'NonText'}}}})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_lines = {{{'VIRT LINE 1', 'NonText'}}}, virt_lines_leftcol = true})
+ api.nvim_buf_set_extmark(0, ns, 3, 0, {virt_lines = {{{'VIRT LINE 2', 'NonText'}}}})
screen:expect{grid=[[
aaa{9: 1 }|
{1:1 ENIL TRIV}|
@@ -4550,7 +4789,7 @@ if (h->n_buckets < new_n_buckets) { // expand
line3
line4
line5]])
- meths.buf_set_extmark(0, ns, 0, 0, {virt_lines={{{"foo"}}, {{"bar"}}, {{"baz"}}}})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {virt_lines={{{"foo"}}, {{"bar"}}, {{"baz"}}}})
screen:expect{grid=[[
line1 |
foo |
@@ -4560,32 +4799,29 @@ if (h->n_buckets < new_n_buckets) { // expand
line3 |
line4 |
line^5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
feed('gg')
- feed('dd')
+ feed('yyp')
screen:expect{grid=[[
- ^line2 |
+ line1 |
foo |
bar |
baz |
+ ^line1 |
+ line2 |
line3 |
line4 |
line5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]]}
- feed('yyp')
+ feed('dd')
screen:expect{grid=[[
- line2 |
+ line1 |
foo |
bar |
baz |
@@ -4593,11 +4829,22 @@ if (h->n_buckets < new_n_buckets) { // expand
line3 |
line4 |
line5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]]}
+
+ feed('kdd')
+ screen:expect([[
+ ^line2 |
+ foo |
+ bar |
+ baz |
+ line3 |
+ line4 |
+ line5 |
+ {1:~ }|*4
+ |
+ ]])
end)
end)
@@ -4612,10 +4859,11 @@ describe('decorations: signs', function()
[1] = {foreground = Screen.colors.Blue4, background = Screen.colors.Grey};
[2] = {foreground = Screen.colors.Blue1, bold = true};
[3] = {background = Screen.colors.Yellow1, foreground = Screen.colors.Blue1};
+ [4] = {foreground = Screen.colors.Gray100, background = Screen.colors.Red};
}
- ns = meths.create_namespace 'test'
- meths.set_option_value('signcolumn', 'auto:9', {})
+ ns = api.nvim_create_namespace 'test'
+ api.nvim_set_option_value('signcolumn', 'auto:9', {})
end)
local example_test3 = [[
@@ -4630,7 +4878,7 @@ l5
insert(example_test3)
feed 'gg'
- meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S'})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S'})
screen:expect{grid=[[
{1: }^l1 |
@@ -4639,19 +4887,16 @@ l5
{1: }l4 |
{1: }l5 |
{1: } |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
]]}
-
end)
it('can add a single sign (with end row)', function()
insert(example_test3)
feed 'gg'
- meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row=1})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row=1})
screen:expect{grid=[[
{1: }^l1 |
@@ -4660,19 +4905,16 @@ l5
{1: }l4 |
{1: }l5 |
{1: } |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
]]}
-
end)
it('can add a single sign and text highlight', function()
insert(example_test3)
feed 'gg'
- meths.buf_set_extmark(0, ns, 1, 0, {sign_text='S', hl_group='Todo', end_col=1})
+ api.nvim_buf_set_extmark(0, ns, 1, 0, {sign_text='S', hl_group='Todo', end_col=1})
screen:expect{grid=[[
{1: }^l1 |
S {3:l}2 |
@@ -4680,20 +4922,18 @@ l5
{1: }l4 |
{1: }l5 |
{1: } |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
]]}
- meths.buf_clear_namespace(0, ns, 0, -1)
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
end)
it('can add multiple signs (single extmark)', function()
insert(example_test3)
feed 'gg'
- meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row = 2})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S', end_row = 2})
screen:expect{grid=[[
{1: }^l1 |
@@ -4702,20 +4942,17 @@ l5
{1: }l4 |
{1: }l5 |
{1: } |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
]]}
-
end)
it('can add multiple signs (multiple extmarks)', function()
insert(example_test3)
feed'gg'
- meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S1'})
- meths.buf_set_extmark(0, ns, 3, -1, {sign_text='S2', end_row = 4})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S1'})
+ api.nvim_buf_set_extmark(0, ns, 3, -1, {sign_text='S2', end_row = 4})
screen:expect{grid=[[
{1: }^l1 |
@@ -4724,9 +4961,7 @@ l5
S2l4 |
S2l5 |
{1: } |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
]]}
end)
@@ -4735,8 +4970,8 @@ l5
insert(example_test3)
feed 'gg'
- meths.buf_set_extmark(0, ns, 3, -1, {sign_text='S1'})
- meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S2', end_row = 3})
+ api.nvim_buf_set_extmark(0, ns, 3, -1, {sign_text='S1'})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S2', end_row = 3})
screen:expect{grid=[[
{1: }^l1 |
S2{1: }l2 |
@@ -4744,9 +4979,7 @@ l5
S1S2l4 |
{1: }l5 |
{1: } |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
]]}
end)
@@ -4756,8 +4989,8 @@ l5
insert(example_test3)
feed 'gg'
- meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S1', end_row=2})
- meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S2', end_row=3})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S1', end_row=2})
+ api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S2', end_row=3})
screen:expect{grid=[[
{1: }^l1 |
@@ -4766,9 +4999,7 @@ l5
S2{1: }l4 |
{1: }l5 |
{1: } |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
]]}
end)
@@ -4777,8 +5008,8 @@ l5
insert(example_test3)
feed 'gg'
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S1', end_row=0})
- meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S2', end_row=1})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1', end_row=0})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S2', end_row=1})
screen:expect{grid=[[
S1^l1 |
@@ -4787,9 +5018,7 @@ l5
{1: }l4 |
{1: }l5 |
{1: } |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
]]}
end)
@@ -4801,10 +5030,10 @@ l5
helpers.command('sign define Oldsign text=x')
helpers.command([[exe 'sign place 42 line=2 name=Oldsign buffer=' . bufnr('')]])
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S1'})
- meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S2'})
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S4'})
- meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1'})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S2'})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S4'})
+ api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
screen:expect{grid=[[
S1S4^l1 |
@@ -4813,9 +5042,7 @@ l5
{1: }l4 |
{1: }l5 |
{1: } |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
]]}
end)
@@ -4827,11 +5054,11 @@ l5
helpers.command('sign define Oldsign text=x')
helpers.command([[exe 'sign place 42 line=2 name=Oldsign buffer=' . bufnr('')]])
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S1'})
- meths.buf_set_extmark(0, ns, 1, -1, {sign_text='S2'})
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S3', end_row = 4})
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S4'})
- meths.buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1'})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S2'})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S3', end_row = 4})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S4'})
+ api.nvim_buf_set_extmark(0, ns, 2, -1, {sign_text='S5'})
screen:expect{grid=[[
S1S3S4^l1 |
@@ -4840,9 +5067,7 @@ l5
S3{1: }l4 |
S3{1: }l5 |
{1: } |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
]]}
end)
@@ -4853,21 +5078,16 @@ l5
feed 'gg'
feed '2<C-e>'
- meths.buf_set_extmark(0, ns, 1, -1, {sign_text='X', end_row=3})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='X', end_row=3})
screen:expect{grid=[[
X {1: }^l3 |
X {1: }l4 |
{1: }l5 |
{1: } |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*5
|
]]}
-
end)
it('can add lots of signs', function()
@@ -4875,29 +5095,22 @@ l5
command 'normal 10oa b c d e f g h'
for i = 1, 10 do
- meths.buf_set_extmark(0, ns, i, 0, { end_col = 1, hl_group='Todo' })
- meths.buf_set_extmark(0, ns, i, 2, { end_col = 3, hl_group='Todo' })
- meths.buf_set_extmark(0, ns, i, 4, { end_col = 5, hl_group='Todo' })
- meths.buf_set_extmark(0, ns, i, 6, { end_col = 7, hl_group='Todo' })
- meths.buf_set_extmark(0, ns, i, 8, { end_col = 9, hl_group='Todo' })
- meths.buf_set_extmark(0, ns, i, 10, { end_col = 11, hl_group='Todo' })
- meths.buf_set_extmark(0, ns, i, 12, { end_col = 13, hl_group='Todo' })
- meths.buf_set_extmark(0, ns, i, 14, { end_col = 15, hl_group='Todo' })
- meths.buf_set_extmark(0, ns, i, -1, { sign_text='W' })
- meths.buf_set_extmark(0, ns, i, -1, { sign_text='X' })
- meths.buf_set_extmark(0, ns, i, -1, { sign_text='Y' })
- meths.buf_set_extmark(0, ns, i, -1, { sign_text='Z' })
+ api.nvim_buf_set_extmark(0, ns, i, 0, { end_col = 1, hl_group='Todo' })
+ api.nvim_buf_set_extmark(0, ns, i, 2, { end_col = 3, hl_group='Todo' })
+ api.nvim_buf_set_extmark(0, ns, i, 4, { end_col = 5, hl_group='Todo' })
+ api.nvim_buf_set_extmark(0, ns, i, 6, { end_col = 7, hl_group='Todo' })
+ api.nvim_buf_set_extmark(0, ns, i, 8, { end_col = 9, hl_group='Todo' })
+ api.nvim_buf_set_extmark(0, ns, i, 10, { end_col = 11, hl_group='Todo' })
+ api.nvim_buf_set_extmark(0, ns, i, 12, { end_col = 13, hl_group='Todo' })
+ api.nvim_buf_set_extmark(0, ns, i, 14, { end_col = 15, hl_group='Todo' })
+ api.nvim_buf_set_extmark(0, ns, i, -1, { sign_text='W' })
+ api.nvim_buf_set_extmark(0, ns, i, -1, { sign_text='X' })
+ api.nvim_buf_set_extmark(0, ns, i, -1, { sign_text='Y' })
+ api.nvim_buf_set_extmark(0, ns, i, -1, { sign_text='Z' })
end
screen:expect{grid=[[
- W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
- W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
- W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
- W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
- W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
- W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
- W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
- W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |
+ W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:h} |*8
W X Y Z {3:a} {3:b} {3:c} {3:d} {3:e} {3:f} {3:g} {3:^h} |
|
]]}
@@ -4911,10 +5124,10 @@ l5
command('sign define Oldsign text=O3')
command([[exe 'sign place 42 line=1 name=Oldsign priority=10 buffer=' . bufnr('')]])
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S4', priority=100})
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S2', priority=5})
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S5', priority=200})
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S1', priority=1})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S4', priority=100})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S2', priority=5})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S5', priority=200})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1', priority=1})
screen:expect{grid=[[
S1S2O3S4S5^l1 |
@@ -4923,7 +5136,7 @@ l5
]]}
-- Check truncation works too
- meths.set_option_value('signcolumn', 'auto', {})
+ api.nvim_set_option_value('signcolumn', 'auto', {})
screen:expect{grid=[[
S5^l1 |
@@ -4952,10 +5165,10 @@ l5
|
]]}
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S1', priority=1})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1', priority=1})
screen:expect_unchanged()
- meths.buf_set_extmark(0, ns, 0, -1, {sign_text='S5', priority=200})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S5', priority=200})
screen:expect{grid=[[
O3O3O3O3O3O3O3O3S5^ |
{2:~ }|
@@ -4967,16 +5180,237 @@ l5
it('does not set signcolumn for signs without text', function()
screen:try_resize(20, 3)
- meths.set_option_value('signcolumn', 'auto', {})
+ api.nvim_set_option_value('signcolumn', 'auto', {})
insert(example_test3)
feed 'gg'
- meths.buf_set_extmark(0, ns, 0, -1, {number_hl_group='Error'})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {number_hl_group='Error'})
screen:expect{grid=[[
^l1 |
l2 |
|
]]}
end)
+
+ it('correct width when removing multiple signs from sentinel line', function()
+ screen:try_resize(20, 4)
+ insert(example_test3)
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1', end_row=3})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {invalidate = true, sign_text='S2'})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {invalidate = true, sign_text='S3'})
+ feed('2Gdd')
+
+ screen:expect{grid=[[
+ S1l1 |
+ S1^l3 |
+ S1l4 |
+ |
+ ]]}
+ end)
+
+ it('correct width with multiple overlapping signs', function()
+ screen:try_resize(20, 4)
+ insert(example_test3)
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S1'})
+ api.nvim_buf_set_extmark(0, ns, 0, -1, {sign_text='S2', end_row=2})
+ api.nvim_buf_set_extmark(0, ns, 1, -1, {sign_text='S3', end_row=2})
+ feed('gg')
+
+ local s1 = [[
+ S1S2^l1 |
+ S2S3l2 |
+ S2S3l3 |
+ |
+ ]]
+ screen:expect{grid=s1}
+ -- Correct width when :move'ing a line with signs
+ command('move2')
+ screen:expect{grid=[[
+ S3{1: }l2 |
+ S1S2S3^l1 |
+ {1: }l3 |
+ |
+ ]]}
+ command('silent undo')
+ screen:expect{grid=s1}
+ command('d')
+ screen:expect{grid=[[
+ S1S2S3^l2 |
+ S2S3{1: }l3 |
+ {1: }l4 |
+ |
+ ]]}
+ command('d')
+ screen:expect{grid=[[
+ S1S2S3^l3 |
+ {1: }l4 |
+ {1: }l5 |
+ |
+ ]]}
+ end)
+
+ it('correct width when adding and removing multiple signs', function()
+ screen:try_resize(20, 4)
+ insert(example_test3)
+ feed('gg')
+ command([[
+ let ns = nvim_create_namespace('')
+ call nvim_buf_set_extmark(0, ns, 0, 0, {'sign_text':'S1', 'end_row':3})
+ let s1 = nvim_buf_set_extmark(0, ns, 2, 0, {'sign_text':'S2', 'end_row':4})
+ let s2 = nvim_buf_set_extmark(0, ns, 5, 0, {'sign_text':'S3'})
+ let s3 = nvim_buf_set_extmark(0, ns, 6, 0, {'sign_text':'S3'})
+ let s4 = nvim_buf_set_extmark(0, ns, 5, 0, {'sign_text':'S3'})
+ let s5 = nvim_buf_set_extmark(0, ns, 6, 0, {'sign_text':'S3'})
+ redraw!
+ call nvim_buf_del_extmark(0, ns, s2)
+ call nvim_buf_del_extmark(0, ns, s3)
+ call nvim_buf_del_extmark(0, ns, s4)
+ call nvim_buf_del_extmark(0, ns, s5)
+ redraw!
+ call nvim_buf_del_extmark(0, ns, s1)
+ ]])
+ screen:expect{grid=[[
+ S1^l1 |
+ S1l2 |
+ S1l3 |
+ |
+ ]]}
+ end)
+
+ it('correct width when deleting lines', function()
+ screen:try_resize(20, 4)
+ insert(example_test3)
+ feed('gg')
+ command([[
+ let ns = nvim_create_namespace('')
+ call nvim_buf_set_extmark(0, ns, 4, 0, {'sign_text':'S1'})
+ call nvim_buf_set_extmark(0, ns, 4, 0, {'sign_text':'S2'})
+ let s3 = nvim_buf_set_extmark(0, ns, 5, 0, {'sign_text':'S3'})
+ call nvim_buf_del_extmark(0, ns, s3)
+ norm 4Gdd
+ ]])
+ screen:expect{grid=[[
+ {1: }l3 |
+ S1S2l5 |
+ {1: }^ |
+ |
+ ]]}
+ end)
+
+ it('correct width when splitting lines with signs on different columns', function()
+ screen:try_resize(20, 4)
+ insert(example_test3)
+ feed('gg')
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text='S1'})
+ api.nvim_buf_set_extmark(0, ns, 0, 1, {sign_text='S2'})
+ feed('a<cr><esc>')
+ screen:expect{grid=[[
+ S1l |
+ S2^1 |
+ {1: }l2 |
+ |
+ ]]}
+ end)
+
+ it('correct width after wiping a buffer', function()
+ screen:try_resize(20, 4)
+ insert(example_test3)
+ feed('gg')
+ local buf = api.nvim_get_current_buf()
+ api.nvim_buf_set_extmark(buf, ns, 0, 0, { sign_text = 'h' })
+ screen:expect{grid=[[
+ h ^l1 |
+ {1: }l2 |
+ {1: }l3 |
+ |
+ ]]}
+ api.nvim_win_set_buf(0, api.nvim_create_buf(false, true))
+ api.nvim_buf_delete(buf, {unload=true, force=true})
+ api.nvim_buf_set_lines(buf, 0, -1, false, {''})
+ api.nvim_win_set_buf(0, buf)
+ screen:expect{grid=[[
+ ^ |
+ {2:~ }|*2
+ |
+ ]]}
+ end)
+
+ it('correct width with moved marks before undo savepos', function()
+ screen:try_resize(20, 4)
+ insert(example_test3)
+ feed('gg')
+ exec_lua([[
+ local ns = vim.api.nvim_create_namespace('')
+ vim.api.nvim_buf_set_extmark(0, ns, 0, 0, { sign_text = 'S1' })
+ vim.api.nvim_buf_set_extmark(0, ns, 1, 0, { sign_text = 'S2' })
+ local s3 = vim.api.nvim_buf_set_extmark(0, ns, 2, 0, { sign_text = 'S3' })
+ local s4 = vim.api.nvim_buf_set_extmark(0, ns, 2, 0, { sign_text = 'S4' })
+ vim.schedule(function()
+ vim.cmd('silent d3')
+ vim.api.nvim_buf_set_extmark(0, ns, 2, 0, { id = s3, sign_text = 'S3' })
+ vim.api.nvim_buf_set_extmark(0, ns, 2, 0, { id = s4, sign_text = 'S4' })
+ vim.cmd('silent undo')
+ vim.api.nvim_buf_del_extmark(0, ns, s3)
+ end)
+ ]])
+
+ screen:expect{grid=[[
+ S1^l1 |
+ S2l2 |
+ S4l3 |
+ |
+ ]]}
+ end)
+
+ it('no crash with sign after many marks #27137', function()
+ screen:try_resize(20, 4)
+ insert('a')
+ for _ = 0, 104 do
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {hl_group = 'Error', end_col = 1})
+ end
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text = 'S1'})
+
+ screen:expect{grid=[[
+ S1{4:^a} |
+ {2:~ }|*2
+ |
+ ]]}
+ end)
+
+ it('correct sort order with multiple namespaces and same id', function()
+ local ns2 = api.nvim_create_namespace('')
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {sign_text = 'S1', id = 1})
+ api.nvim_buf_set_extmark(0, ns2, 0, 0, {sign_text = 'S2', id = 1})
+
+ screen:expect{grid=[[
+ S1S2^ |
+ {2:~ }|*8
+ |
+ ]]}
+ end)
+
+ it('correct number of signs after deleting text (#27046)', function()
+ command('call setline(1, ["foo"]->repeat(31))')
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {end_row = 0, sign_text = 'S1'})
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {end_row = 0, end_col = 3, hl_group = 'Error'})
+ api.nvim_buf_set_extmark(0, ns, 9, 0, {end_row = 9, sign_text = 'S2'})
+ api.nvim_buf_set_extmark(0, ns, 9, 0, {end_row = 9, end_col = 3, hl_group = 'Error'})
+ api.nvim_buf_set_extmark(0, ns, 19, 0, {end_row = 19, sign_text = 'S3'})
+ api.nvim_buf_set_extmark(0, ns, 19, 0, {end_row = 19, end_col = 3, hl_group = 'Error'})
+ api.nvim_buf_set_extmark(0, ns, 29, 0, {end_row = 29, sign_text = 'S4'})
+ api.nvim_buf_set_extmark(0, ns, 29, 0, {end_row = 29, end_col = 3, hl_group = 'Error'})
+ api.nvim_buf_set_extmark(0, ns, 30, 0, {end_row = 30, sign_text = 'S5'})
+ api.nvim_buf_set_extmark(0, ns, 30, 0, {end_row = 30, end_col = 3, hl_group = 'Error'})
+ command('0d29')
+
+ screen:expect{grid=[[
+ S1S2S3S4{4:^foo} |
+ S5{1: }{4:foo} |
+ {2:~ }|*7
+ 29 fewer lines |
+ ]]}
+
+ api.nvim_buf_clear_namespace(0, ns, 0, -1)
+ end)
end)
describe('decorations: virt_text', function()
@@ -5002,9 +5436,9 @@ describe('decorations: virt_text', function()
command 'normal 4ohello'
command 'normal aVIRTUAL'
- local ns = meths.create_namespace('test')
+ local ns = api.nvim_create_namespace('test')
- meths.buf_set_extmark(0, ns, 2, 0, {
+ api.nvim_buf_set_extmark(0, ns, 2, 0, {
virt_text = {{"hello", "String"}},
virt_text_win_col = 20,
})
@@ -5015,10 +5449,7 @@ describe('decorations: virt_text', function()
{1: 2 }hello {2:hello} |
{1: 1 }hello |
{1:5 }helloVIRTUA^L |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*4
|
]]}
@@ -5031,10 +5462,7 @@ describe('decorations: virt_text', function()
{1: 1 }hello {2:hello} |
{1:4 }hell^o |
{1: 1 }helloVIRTUAL |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*4
|
]]}
end)
@@ -5044,34 +5472,379 @@ describe('decorations: virt_text', function()
screen:expect{grid=[[
|
- hello |
- hello |
- hello |
- hello |
+ hello |*4
hell^o |
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*3
|
]]}
- local ns = meths.create_namespace('ns')
+ local ns = api.nvim_create_namespace('ns')
for row = 1, 5 do
- meths.buf_set_extmark(0, ns, row, 0, { id = 1, virt_text = {{'world', 'Normal'}} })
+ api.nvim_buf_set_extmark(0, ns, row, 0, { id = 1, virt_text = {{'world', 'Normal'}} })
end
screen:expect{grid=[[
|
- hello |
- hello |
- hello |
- hello |
+ hello |*4
hell^o world |
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*3
|
]]}
end)
+end)
+describe('decorations: window scoped', function()
+ local screen, ns
+ before_each(function()
+ clear()
+ screen = Screen.new(20, 10)
+ screen:attach()
+ screen:set_default_attr_ids {
+ [1] = { foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Blue1, bold = true },
+ }
+
+ ns = api.nvim_create_namespace 'test'
+
+ insert('12345')
+ end)
+
+ local noextmarks = {
+ grid = [[
+ 1234^5 |
+ {2:~ }|*8
+ |
+ ]]}
+
+ local function set_scoped_extmark(line, col, opts)
+ return api.nvim_buf_set_extmark(0, ns, line, col, vim.tbl_extend('error', { scoped = true }, opts))
+ end
+
+ it('hl_group', function()
+ set_scoped_extmark(0, 0, {
+ hl_group = 'Comment',
+ end_col = 3,
+ })
+
+ screen:expect(noextmarks)
+
+ api.nvim_win_add_ns(0, ns)
+
+ screen:expect {
+ grid = [[
+ {1:123}4^5 |
+ {2:~ }|*8
+ |
+ ]]}
+
+ command 'split'
+ command 'only'
+
+ screen:expect(noextmarks)
+ end)
+
+ it('virt_text', function()
+ set_scoped_extmark(0, 0, {
+ virt_text = { { 'a', 'Comment' } },
+ virt_text_pos = 'eol',
+ })
+ set_scoped_extmark(0, 5, {
+ virt_text = { { 'b', 'Comment' } },
+ virt_text_pos = 'inline',
+ })
+ set_scoped_extmark(0, 1, {
+ virt_text = { { 'c', 'Comment' } },
+ virt_text_pos = 'overlay',
+ })
+ set_scoped_extmark(0, 1, {
+ virt_text = { { 'd', 'Comment' } },
+ virt_text_pos = 'right_align',
+ })
+
+ screen:expect(noextmarks)
+
+ api.nvim_win_add_ns(0, ns)
+
+ screen:expect {
+ grid = [[
+ 1{1:c}34^5{1:b} {1:a} {1:d}|
+ {2:~ }|*8
+ |
+ ]]}
+
+ command 'split'
+ command 'only'
+
+ screen:expect(noextmarks)
+ end)
+
+ it('virt_lines', function()
+ set_scoped_extmark(0, 0, {
+ virt_lines = { { { 'a', 'Comment' } } },
+ })
+
+ screen:expect(noextmarks)
+
+ api.nvim_win_add_ns(0, ns)
+
+ screen:expect {
+ grid = [[
+ 1234^5 |
+ {1:a} |
+ {2:~ }|*7
+ |
+ ]]}
+
+ command 'split'
+ command 'only'
+
+ screen:expect(noextmarks)
+ end)
+
+ it('redraws correctly with inline virt_text and wrapping', function()
+ set_scoped_extmark(0, 2, {
+ virt_text = {{ ('b'):rep(18), 'Comment' }},
+ virt_text_pos = 'inline'
+ })
+
+ screen:expect(noextmarks)
+
+ api.nvim_win_add_ns(0, ns)
+
+ screen:expect {
+ grid = [[
+ 12{1:bbbbbbbbbbbbbbbbbb}|
+ 34^5 |
+ {2:~ }|*7
+ |
+ ]]}
+
+ api.nvim_win_remove_ns(0, ns)
+
+ screen:expect(noextmarks)
+ end)
+
+ pending('sign_text', function()
+ -- TODO(altermo): The window signcolumn width is calculated wrongly (when `signcolumn=auto`)
+ -- This happens in function `win_redraw_signcols` on line containing `buf_meta_total(buf, kMTMetaSignText) > 0`
+ set_scoped_extmark(0, 0, {
+ sign_text = 'a',
+ sign_hl_group = 'Comment',
+ })
+
+ screen:expect(noextmarks)
+
+ api.nvim_win_add_ns(0, ns)
+
+ screen:expect {
+ grid = [[
+ a 1234^5 |
+ {2:~ }|*8
+ |
+ ]]}
+
+ command 'split'
+ command 'only'
+
+ screen:expect(noextmarks)
+ end)
+
+ it('statuscolumn hl group', function()
+ local attrs = screen:get_default_attr_ids()
+ table.insert(attrs, {
+ foreground = Screen.colors.Brown,
+ })
+ screen:set_default_attr_ids(attrs)
+
+ set_scoped_extmark(0, 0, {
+ number_hl_group='comment',
+ })
+ set_scoped_extmark(0, 0, {
+ line_hl_group='comment',
+ })
+
+ command 'set number'
+
+ screen:expect {
+ grid = [[
+ {3: 1 }1234^5 |
+ {2:~ }|*8
+ |
+ ]]}
+
+ api.nvim_win_add_ns(0, ns)
+
+ screen:expect {
+ grid = [[
+ {1: 1 1234^5 }|
+ {2:~ }|*8
+ |
+ ]]}
+
+ command 'split'
+ command 'only'
+
+ screen:expect {
+ grid = [[
+ {3: 1 }1234^5 |
+ {2:~ }|*8
+ |
+ ]]}
+ end)
+
+ it('spell', function()
+ local attrs = screen:get_default_attr_ids()
+ table.insert(attrs, {
+ special = Screen.colors.Red, undercurl = true
+ })
+ screen:set_default_attr_ids(attrs)
+ api.nvim_buf_set_lines(0,0,-1,true,{'aa'})
+
+ set_scoped_extmark(0, 0, {
+ spell=true,
+ end_col=2,
+ })
+
+ command 'set spelloptions=noplainbuffer'
+ command 'set spell'
+ command 'syntax off'
+
+ screen:expect {
+ grid = [[
+ a^a |
+ {2:~ }|*8
+ |
+ ]]}
+
+ api.nvim_win_add_ns(0, ns)
+
+ screen:expect {
+ grid = [[
+ {3:a^a} |
+ {2:~ }|*8
+ |
+ ]]}
+
+ command 'split'
+ command 'only'
+
+ screen:expect {
+ grid = [[
+ a^a |
+ {2:~ }|*8
+ |
+ ]]}
+ end)
+
+ it('url', function()
+ local url = 'https://example.com'
+ local attrs = screen:get_default_attr_ids()
+ table.insert(attrs, {
+ url = url,
+ })
+ screen:set_default_attr_ids(attrs)
+
+ set_scoped_extmark(0, 0, {
+ end_col=3,
+ url=url,
+ })
+
+ screen:expect(noextmarks)
+
+ api.nvim_win_add_ns(0, ns)
+
+ screen:expect {
+ grid = [[
+ {3:123}4^5 |
+ {2:~ }|*8
+ |
+ ]]}
+
+ command 'split'
+ command 'only'
+
+ screen:expect(noextmarks)
+ end)
+
+ it('change extmarks scoped option', function()
+ local id = set_scoped_extmark(0, 0, {
+ hl_group = 'Comment',
+ end_col = 3,
+ })
+
+ api.nvim_win_add_ns(0, ns)
+
+ screen:expect {
+ grid = [[
+ {1:123}4^5 |
+ {2:~ }|*8
+ |
+ ]]}
+
+ command 'split'
+ command 'only'
+
+ screen:expect(noextmarks)
+
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {
+ id = id,
+ hl_group = 'Comment',
+ end_col = 3,
+ scoped = false,
+ })
+
+ screen:expect {
+ grid = [[
+ {1:123}4^5 |
+ {2:~ }|*8
+ |
+ ]]}
+
+ api.nvim_buf_set_extmark(0, ns, 0, 0, {
+ id = id,
+ hl_group = 'Comment',
+ end_col = 3,
+ scoped = true,
+ })
+
+ screen:expect(noextmarks)
+ end)
+
+ it('change namespace scope', function()
+ set_scoped_extmark(0, 0, {
+ hl_group = 'Comment',
+ end_col = 3,
+ })
+
+ eq(true, api.nvim_win_add_ns(0, ns))
+ eq({ ns }, api.nvim_win_get_ns(0))
+
+ screen:expect {
+ grid = [[
+ {1:123}4^5 |
+ {2:~ }|*8
+ |
+ ]]}
+
+ command 'split'
+ command 'only'
+ eq({}, api.nvim_win_get_ns(0))
+
+ screen:expect(noextmarks)
+
+ eq(true, api.nvim_win_add_ns(0, ns))
+ eq({ ns }, api.nvim_win_get_ns(0))
+
+ screen:expect {
+ grid = [[
+ {1:123}4^5 |
+ {2:~ }|*8
+ |
+ ]]}
+
+ eq(true, api.nvim_win_remove_ns(0, ns))
+ eq({}, api.nvim_win_get_ns(0))
+
+ screen:expect(noextmarks)
+ end)
end)
diff --git a/test/functional/ui/diff_spec.lua b/test/functional/ui/diff_spec.lua
index 92b7235885..e0dfde35f2 100644
--- a/test/functional/ui/diff_spec.lua
+++ b/test/functional/ui/diff_spec.lua
@@ -9,7 +9,9 @@ local write_file = helpers.write_file
local dedent = helpers.dedent
local exec = helpers.exec
local eq = helpers.eq
-local meths = helpers.meths
+local api = helpers.api
+
+before_each(clear)
describe('Diff mode screen', function()
local fname = 'Xtest-functional-diff-screen-1'
@@ -21,7 +23,6 @@ describe('Diff mode screen', function()
end
setup(function()
- clear()
os.remove(fname)
os.remove(fname_2)
end)
@@ -32,7 +33,6 @@ describe('Diff mode screen', function()
end)
before_each(function()
- clear()
feed(':e ' .. fname_2 .. '<cr>')
feed(':vnew ' .. fname .. '<cr>')
feed(':diffthis<cr>')
@@ -41,21 +41,21 @@ describe('Diff mode screen', function()
screen = Screen.new(40, 16)
screen:attach()
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
- [2] = {background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1},
- [3] = {reverse = true},
- [4] = {background = Screen.colors.LightBlue},
- [5] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey},
- [6] = {bold = true, foreground = Screen.colors.Blue1},
- [7] = {bold = true, reverse = true},
- [8] = {bold = true, background = Screen.colors.Red},
- [9] = {background = Screen.colors.LightMagenta},
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray },
+ [2] = { background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { reverse = true },
+ [4] = { background = Screen.colors.LightBlue },
+ [5] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey },
+ [6] = { bold = true, foreground = Screen.colors.Blue1 },
+ [7] = { bold = true, reverse = true },
+ [8] = { bold = true, background = Screen.colors.Red },
+ [9] = { background = Screen.colors.LightMagenta },
})
end)
it('Add a line in beginning of file 2', function()
- write_file(fname, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false)
- write_file(fname_2, "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false)
+ write_file(fname, '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n', false)
+ write_file(fname_2, '0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n', false)
reread()
feed(':set diffopt=filler<cr>')
@@ -68,12 +68,7 @@ describe('Diff mode screen', function()
{1: }5 │{1: }5 |
{1: }6 │{1: }6 |
{1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=filler |
]])
@@ -88,23 +83,18 @@ describe('Diff mode screen', function()
{1: }5 │{1: }5 |
{1: }6 │{1: }6 |
{1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=internal |
]])
end)
it('Add a line in beginning of file 1', function()
- write_file(fname, "0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false)
- write_file(fname_2, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false)
+ write_file(fname, '0\n1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n', false)
+ write_file(fname_2, '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n', false)
reread()
- feed(":set diffopt=filler<cr>")
+ feed(':set diffopt=filler<cr>')
screen:expect([[
{1: }{4:^0 }│{1: }{2:-----------------}|
{1: }1 │{1: }1 |
@@ -114,17 +104,12 @@ describe('Diff mode screen', function()
{1: }5 │{1: }5 |
{1: }6 │{1: }6 |
{1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=filler |
]])
- feed(":set diffopt+=internal<cr>")
+ feed(':set diffopt+=internal<cr>')
screen:expect([[
{1: }{4:^0 }│{1: }{2:-----------------}|
{1: }1 │{1: }1 |
@@ -134,23 +119,18 @@ describe('Diff mode screen', function()
{1: }5 │{1: }5 |
{1: }6 │{1: }6 |
{1:+ }{5:+-- 4 lines: 7···}│{1:+ }{5:+-- 4 lines: 7··}|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=internal |
]])
end)
it('Add a line at the end of file 2', function()
- write_file(fname, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false)
- write_file(fname_2, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", false)
+ write_file(fname, '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n', false)
+ write_file(fname_2, '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n', false)
reread()
- feed(":set diffopt=filler<cr>")
+ feed(':set diffopt=filler<cr>')
screen:expect([[
{1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}|
{1: }5 │{1: }5 |
@@ -160,17 +140,12 @@ describe('Diff mode screen', function()
{1: }9 │{1: }9 |
{1: }10 │{1: }10 |
{1: }{2:------------------}│{1: }{4:11 }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=filler |
]])
- feed(":set diffopt+=internal<cr>")
+ feed(':set diffopt+=internal<cr>')
screen:expect([[
{1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}|
{1: }5 │{1: }5 |
@@ -180,12 +155,7 @@ describe('Diff mode screen', function()
{1: }9 │{1: }9 |
{1: }10 │{1: }10 |
{1: }{2:------------------}│{1: }{4:11 }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=internal |
]])
@@ -205,11 +175,11 @@ describe('Diff mode screen', function()
end)
it('Add a line at the end of file 1', function()
- write_file(fname, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", false)
- write_file(fname_2, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false)
+ write_file(fname, '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n', false)
+ write_file(fname_2, '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n', false)
reread()
- feed(":set diffopt=filler<cr>")
+ feed(':set diffopt=filler<cr>')
screen:expect([[
{1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}|
{1: }5 │{1: }5 |
@@ -219,17 +189,12 @@ describe('Diff mode screen', function()
{1: }9 │{1: }9 |
{1: }10 │{1: }10 |
{1: }{4:11 }│{1: }{2:-----------------}|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=filler |
]])
- feed(":set diffopt+=internal<cr>")
+ feed(':set diffopt+=internal<cr>')
screen:expect([[
{1:+ }{5:^+-- 4 lines: 1···}│{1:+ }{5:+-- 4 lines: 1··}|
{1: }5 │{1: }5 |
@@ -239,12 +204,7 @@ describe('Diff mode screen', function()
{1: }9 │{1: }9 |
{1: }10 │{1: }10 |
{1: }{4:11 }│{1: }{2:-----------------}|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=internal |
]])
@@ -264,8 +224,8 @@ describe('Diff mode screen', function()
end)
it('Add a line in the middle of file 2, remove on at the end of file 1', function()
- write_file(fname, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", false)
- write_file(fname_2, "1\n2\n3\n4\n4\n5\n6\n7\n8\n9\n10\n", false)
+ write_file(fname, '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n', false)
+ write_file(fname_2, '1\n2\n3\n4\n4\n5\n6\n7\n8\n9\n10\n', false)
reread()
feed(':set diffopt=filler<cr>')
@@ -282,8 +242,7 @@ describe('Diff mode screen', function()
{1: }9 │{1: }9 |
{1: }10 │{1: }10 |
{1: }{4:11 }│{1: }{2:-----------------}|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*2
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=filler |
]])
@@ -302,16 +261,15 @@ describe('Diff mode screen', function()
{1: }9 │{1: }9 |
{1: }10 │{1: }10 |
{1: }{4:11 }│{1: }{2:-----------------}|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*2
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=internal |
]])
end)
it('Add a line in the middle of file 1, remove on at the end of file 2', function()
- write_file(fname, "1\n2\n3\n4\n4\n5\n6\n7\n8\n9\n10\n", false)
- write_file(fname_2, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n", false)
+ write_file(fname, '1\n2\n3\n4\n4\n5\n6\n7\n8\n9\n10\n', false)
+ write_file(fname_2, '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n', false)
reread()
feed(':set diffopt=filler<cr>')
@@ -328,8 +286,7 @@ describe('Diff mode screen', function()
{1: }9 │{1: }9 |
{1: }10 │{1: }10 |
{1: }{2:------------------}│{1: }{4:11 }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*2
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=filler |
]])
@@ -348,8 +305,7 @@ describe('Diff mode screen', function()
{1: }9 │{1: }9 |
{1: }10 │{1: }10 |
{1: }{2:------------------}│{1: }{4:11 }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*2
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=internal |
]])
@@ -567,7 +523,7 @@ int main(int argc, char **argv)
it('internal', function()
reread()
- feed(":set diffopt=internal,filler<cr>")
+ feed(':set diffopt=internal,filler<cr>')
screen:expect([[
{1: }^def finalize(value│{1: }def finalize(valu|
{1: } │{1: } |
@@ -578,11 +534,7 @@ int main(int argc, char **argv)
{1: }{2:------------------}│{1: }{4: values.each do }|
{1: } v.finalize │{1: } v.finalize |
{1: } end │{1: } end |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*5
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=internal,filler |
]])
@@ -601,11 +553,7 @@ int main(int argc, char **argv)
{1: } values.each do |│{1: } values.each do |
{1: } v.finalize │{1: } v.finalize |
{1: } end │{1: } end |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*5
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
|
]])
@@ -625,11 +573,7 @@ int main(int argc, char **argv)
{1: } values.each do |│{1: } values.each do |
{1: } v.finalize │{1: } v.finalize |
{1: } end │{1: } end |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*5
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
: |
]])
@@ -637,26 +581,14 @@ int main(int argc, char **argv)
end)
it('Diff the same file', function()
- write_file(fname, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false)
- write_file(fname_2, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n", false)
+ write_file(fname, '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n', false)
+ write_file(fname_2, '1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n', false)
reread()
feed(':set diffopt=filler<cr>')
screen:expect([[
{1:+ }{5:^+-- 10 lines: 1···}│{1:+ }{5:+-- 10 lines: 1··}|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*13
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=filler |
]])
@@ -664,45 +596,21 @@ int main(int argc, char **argv)
feed(':set diffopt+=internal<cr>')
screen:expect([[
{1:+ }{5:^+-- 10 lines: 1···}│{1:+ }{5:+-- 10 lines: 1··}|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*13
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=internal |
]])
end)
it('Diff an empty file', function()
- write_file(fname, "", false)
- write_file(fname_2, "", false)
+ write_file(fname, '', false)
+ write_file(fname_2, '', false)
reread()
feed(':set diffopt=filler<cr>')
screen:expect([[
{1:- }^ │{1:- } |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*13
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=filler |
]])
@@ -710,27 +618,15 @@ int main(int argc, char **argv)
feed(':set diffopt+=internal<cr>')
screen:expect([[
{1:- }^ │{1:- } |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*13
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=internal |
]])
end)
it('diffopt+=icase', function()
- write_file(fname, "a\nb\ncd\n", false)
- write_file(fname_2, "A\nb\ncDe\n", false)
+ write_file(fname, 'a\nb\ncd\n', false)
+ write_file(fname_2, 'A\nb\ncDe\n', false)
reread()
feed(':set diffopt=filler,icase<cr>')
@@ -738,17 +634,7 @@ int main(int argc, char **argv)
{1: }^a │{1: }A |
{1: }b │{1: }b |
{1: }{9:cd }│{1: }{9:cD}{8:e}{9: }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*11
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=filler,icase |
]])
@@ -758,17 +644,7 @@ int main(int argc, char **argv)
{1: }^a │{1: }A |
{1: }b │{1: }b |
{1: }{9:cd }│{1: }{9:cD}{8:e}{9: }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*11
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=internal |
]])
@@ -778,7 +654,8 @@ int main(int argc, char **argv)
setup(function()
local f1 = 'int main()\n{\n printf("Hello, World!");\n return 0;\n}\n'
write_file(fname, f1, false)
- local f2 = 'int main()\n{\n if (0)\n {\n printf("Hello, World!");\n return 0;\n }\n}\n'
+ local f2 =
+ 'int main()\n{\n if (0)\n {\n printf("Hello, World!");\n return 0;\n }\n}\n'
write_file(fname_2, f2, false)
feed(':diffupdate!<cr>')
end)
@@ -795,12 +672,7 @@ int main(int argc, char **argv)
{1: } return 0; │{1: } return 0; |
{1: }{2:------------------}│{1: }{4: } }|
{1: }} │{1: }} |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=filler,iwhite |
]])
@@ -818,12 +690,7 @@ int main(int argc, char **argv)
{1: } return 0; │{1: } return 0; |
{1: }{2:------------------}│{1: }{4: } }|
{1: }} │{1: }} |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=filler,iwhite,internal |
]])
@@ -842,19 +709,12 @@ int main(int argc, char **argv)
feed(':set diffopt=internal,filler,iblank<cr>')
screen:expect([[
{1: }^a │{1: }a |
- {1: }{4: }│{1: }{2:-----------------}|
- {1: }{4: }│{1: }{2:-----------------}|
+ {1: }{4: }│{1: }{2:-----------------}|*2
{1: }cd │{1: }cd |
{1: }ef │{1: } |
{1: }{8:xxx}{9: }│{1: }ef |
{6:~ }│{1: }{8:yyy}{9: }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*7
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=internal,filler,iblank |
]])
@@ -871,14 +731,7 @@ int main(int argc, char **argv)
{1: }cd │{1: }ef |
{1: }ef │{1: }{8:yyy}{9: }|
{1: }{8:xxx}{9: }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*8
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
: |
]])
@@ -895,14 +748,7 @@ int main(int argc, char **argv)
{1: }cd │{1: }ef |
{1: }ef │{1: }{8:yyy}{9: }|
{1: }{8:xxx}{9: }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*8
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
: |
]])
@@ -919,14 +765,7 @@ int main(int argc, char **argv)
{1: }cd │{1: }ef |
{1: }ef │{1: }{8:yyy}{9: }|
{1: }{8:xxx}{9: }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*8
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
: |
]])
@@ -953,12 +792,7 @@ int main(int argc, char **argv)
{1: }foo │{1: }foo |
{1: }{2:------------------}│{1: }{4: }|
{1: }bar │{1: }bar |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
: |
]])
@@ -977,12 +811,7 @@ int main(int argc, char **argv)
{1: }foo │{1: }foo |
{1: }{2:------------------}│{1: }{4: }|
{1: }bar │{1: }bar |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
: |
]])
@@ -993,7 +822,9 @@ int main(int argc, char **argv)
-- This was scrolling for 'cursorbind' but 'scrollbind' is more important
it('scrolling works correctly vim-patch:8.2.5155', function()
screen:try_resize(40, 12)
- write_file(fname, dedent([[
+ write_file(
+ fname,
+ dedent([[
line 1
line 2
line 3
@@ -1007,8 +838,12 @@ int main(int argc, char **argv)
// Common block
// two
// containing
- // four lines]]), false)
- write_file(fname_2, dedent([[
+ // four lines]]),
+ false
+ )
+ write_file(
+ fname_2,
+ dedent([[
line 1
line 2
line 3
@@ -1041,7 +876,9 @@ int main(int argc, char **argv)
// Common block
// two
// containing
- // four lines]]), false)
+ // four lines]]),
+ false
+ )
reread()
feed('<C-W><C-W>jjjj')
@@ -1116,9 +953,7 @@ int main(int argc, char **argv)
{1: } ui.setupUI(Mai│{1: } ui.setupUI(Ma|
{1: } MainWindow.sho│{1: } MainWindow.sh|
{1: } sys.exit(app.e│{1: } sys.exit(app.|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*3
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt=internal,filler |
]])
@@ -1137,9 +972,7 @@ int main(int argc, char **argv)
{1: } ui.setupUI(Mai│{1: } ui.setupUI(Ma|
{1: } MainWindow.sho│{1: } MainWindow.sh|
{1: } ^sys.exit(app.e│{1: } sys.exit(app.|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*3
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=linematch:20 |
]])
@@ -1163,17 +996,7 @@ ccca]]
{1: }^DDD │{1: }DDD |
{1: }{2:------------------}│{1: }{4:AAA }|
{1: }{8:_a}{9:a }│{1: }{8:ccc}{9:a }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*11
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
|
]])
@@ -1182,17 +1005,7 @@ ccca]]
{1: }^DDD │{1: }DDD |
{1: }{8:_}{9:aa }│{1: }{8:A}{9:AA }|
{1: }{2:------------------}│{1: }{4:ccca }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*11
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=icase |
]])
@@ -1212,53 +1025,38 @@ AAAB]]
it('diffopt+=linematch:20,iwhiteall', function()
reread()
feed(':set diffopt=internal,filler,linematch:20<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }^BB │{1: }BB |
{1: }{9: AA}{8:A}{9: }│{1: }{9: AA}{8:B}{9: }|
{1: }{2:------------------}│{1: }{4:AAAB }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*11
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
|
- ]]}
+ ]],
+ }
feed(':set diffopt+=iwhiteall<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }^BB │{1: }BB |
{1: }{2:------------------}│{1: }{4: AAB }|
{1: }{9: AAA }│{1: }{9:AAA}{8:B}{9: }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*11
{7:<onal-diff-screen-1 }{3:<l-diff-screen-1.2 }|
:set diffopt+=iwhiteall |
- ]]}
+ ]],
+ }
end)
end)
it('redraws with a change to non-current buffer', function()
- write_file(fname, "aaa\nbbb\nccc\n\nxx", false)
- write_file(fname_2, "aaa\nbbb\nccc\n\nyy", false)
+ write_file(fname, 'aaa\nbbb\nccc\n\nxx', false)
+ write_file(fname_2, 'aaa\nbbb\nccc\n\nyy', false)
reread()
- local buf = meths.get_current_buf()
+ local buf = api.nvim_get_current_buf()
command('botright new')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }aaa │{1: }aaa |
{1: }bbb │{1: }bbb |
{1: }ccc │{1: }ccc |
@@ -1267,18 +1065,15 @@ AAAB]]
{6:~ }│{6:~ }|
{3:<onal-diff-screen-1 <l-diff-screen-1.2 }|
^ |
- {6:~ }|
- {6:~ }|
- {6:~ }|
- {6:~ }|
- {6:~ }|
- {6:~ }|
+ {6:~ }|*6
{7:[No Name] }|
:e |
- ]]}
+ ]],
+ }
- meths.buf_set_lines(buf, 1, 2, true, {'BBB'})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(buf, 1, 2, true, { 'BBB' })
+ screen:expect {
+ grid = [[
{1: }aaa │{1: }aaa |
{1: }{8:BBB}{9: }│{1: }{8:bbb}{9: }|
{1: }ccc │{1: }ccc |
@@ -1287,24 +1082,21 @@ AAAB]]
{6:~ }│{6:~ }|
{3:<-diff-screen-1 [+] <l-diff-screen-1.2 }|
^ |
- {6:~ }|
- {6:~ }|
- {6:~ }|
- {6:~ }|
- {6:~ }|
- {6:~ }|
+ {6:~ }|*6
{7:[No Name] }|
:e |
- ]]}
+ ]],
+ }
end)
- it('redraws with a change current buffer in another window', function()
- write_file(fname, "aaa\nbbb\nccc\n\nxx", false)
- write_file(fname_2, "aaa\nbbb\nccc\n\nyy", false)
+ it('redraws with a change current buffer in another window', function()
+ write_file(fname, 'aaa\nbbb\nccc\n\nxx', false)
+ write_file(fname_2, 'aaa\nbbb\nccc\n\nyy', false)
reread()
- local buf = meths.get_current_buf()
+ local buf = api.nvim_get_current_buf()
command('botright split | diffoff')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }aaa │{1: }aaa |
{1: }bbb │{1: }bbb |
{1: }ccc │{1: }ccc |
@@ -1317,14 +1109,15 @@ AAAB]]
ccc |
|
xx |
- {6:~ }|
- {6:~ }|
+ {6:~ }|*2
{7:Xtest-functional-diff-screen-1 }|
:e |
- ]]}
+ ]],
+ }
- meths.buf_set_lines(buf, 1, 2, true, {'BBB'})
- screen:expect{grid=[[
+ api.nvim_buf_set_lines(buf, 1, 2, true, { 'BBB' })
+ screen:expect {
+ grid = [[
{1: }aaa │{1: }aaa |
{1: }{8:BBB}{9: }│{1: }{8:bbb}{9: }|
{1: }ccc │{1: }ccc |
@@ -1337,38 +1130,41 @@ AAAB]]
ccc |
|
xx |
- {6:~ }|
- {6:~ }|
+ {6:~ }|*2
{7:Xtest-functional-diff-screen-1 [+] }|
:e |
- ]]}
+ ]],
+ }
end)
end)
it('win_update redraws lines properly', function()
local screen
- clear()
screen = Screen.new(50, 10)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [3] = {background = Screen.colors.Red, foreground = Screen.colors.Grey100, special = Screen.colors.Yellow},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [5] = {special = Screen.colors.Yellow},
- [6] = {special = Screen.colors.Yellow, bold = true, foreground = Screen.colors.SeaGreen4},
- [7] = {foreground = Screen.colors.Grey0, background = Screen.colors.Grey100},
- [8] = {foreground = Screen.colors.Gray90, background = Screen.colors.Grey100},
- [9] = {foreground = tonumber('0x00000c'), background = Screen.colors.Grey100},
- [10] = {background = Screen.colors.Grey100, bold = true, foreground = tonumber('0xe5e5ff')},
- [11] = {background = Screen.colors.Grey100, bold = true, foreground = tonumber('0x2b8452')},
- [12] = {bold = true, reverse = true},
- [13] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
- [14] = {reverse = true},
- [15] = {background = Screen.colors.LightBlue},
- [16] = {background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1},
- [17] = {bold = true, background = Screen.colors.Red},
- [18] = {background = Screen.colors.LightMagenta},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = {
+ background = Screen.colors.Red,
+ foreground = Screen.colors.Grey100,
+ special = Screen.colors.Yellow,
+ },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [5] = { special = Screen.colors.Yellow },
+ [6] = { special = Screen.colors.Yellow, bold = true, foreground = Screen.colors.SeaGreen4 },
+ [7] = { foreground = Screen.colors.Grey0, background = Screen.colors.Grey100 },
+ [8] = { foreground = Screen.colors.Gray90, background = Screen.colors.Grey100 },
+ [9] = { foreground = tonumber('0x00000c'), background = Screen.colors.Grey100 },
+ [10] = { background = Screen.colors.Grey100, bold = true, foreground = tonumber('0xe5e5ff') },
+ [11] = { background = Screen.colors.Grey100, bold = true, foreground = tonumber('0x2b8452') },
+ [12] = { bold = true, reverse = true },
+ [13] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray },
+ [14] = { reverse = true },
+ [15] = { background = Screen.colors.LightBlue },
+ [16] = { background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1 },
+ [17] = { bold = true, background = Screen.colors.Red },
+ [18] = { background = Screen.colors.LightMagenta },
})
insert([[
@@ -1378,18 +1174,18 @@ it('win_update redraws lines properly', function()
2
1a
]])
- command("vnew left")
+ command('vnew left')
insert([[
2
2a
2b
]])
- command("windo diffthis")
- command("windo 1")
- screen:expect{grid=[[
+ command('windo diffthis')
+ command('windo 1')
+ screen:expect {
+ grid = [[
{13: }{16:-----------------------}│{13: }{15:^1 }|
- {13: }{16:-----------------------}│{13: }{15: }|
- {13: }{16:-----------------------}│{13: }{15: }|
+ {13: }{16:-----------------------}│{13: }{15: }|*2
{13: }2 │{13: }2 |
{13: }{17:2}{18:a }│{13: }{17:1}{18:a }|
{13: }{15:2b }│{13: }{16:----------------------}|
@@ -1397,13 +1193,15 @@ it('win_update redraws lines properly', function()
{1:~ }│{1:~ }|
{14:left [+] }{12:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
feed('<C-e>')
feed('<C-e>')
feed('<C-y>')
feed('<C-y>')
feed('<C-y>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{13: }{16:-----------------------}│{13: }{15:1 }|
{13: }{16:-----------------------}│{13: }{15: }|
{13: }{16:-----------------------}│{13: }{15:^ }|
@@ -1414,26 +1212,26 @@ it('win_update redraws lines properly', function()
{1:~ }│{1:~ }|
{14:left [+] }{12:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
end)
-- oldtest: Test_diff_rnu()
it('diff updates line numbers below filler lines', function()
- clear()
local screen = Screen.new(40, 14)
screen:attach()
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
- [2] = {background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1},
- [3] = {reverse = true},
- [4] = {background = Screen.colors.LightBlue},
- [5] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey},
- [6] = {bold = true, foreground = Screen.colors.Blue1},
- [7] = {bold = true, reverse = true},
- [8] = {bold = true, background = Screen.colors.Red},
- [9] = {background = Screen.colors.LightMagenta},
- [10] = {bold = true, foreground = Screen.colors.Brown},
- [11] = {foreground = Screen.colors.Brown},
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray },
+ [2] = { background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { reverse = true },
+ [4] = { background = Screen.colors.LightBlue },
+ [5] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey },
+ [6] = { bold = true, foreground = Screen.colors.Blue1 },
+ [7] = { bold = true, reverse = true },
+ [8] = { bold = true, background = Screen.colors.Red },
+ [9] = { background = Screen.colors.LightMagenta },
+ [10] = { bold = true, foreground = Screen.colors.Brown },
+ [11] = { foreground = Screen.colors.Brown },
})
exec([[
call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b'])
@@ -1447,8 +1245,7 @@ it('diff updates line numbers below filler lines', function()
{1: }a │{11: 1 }a |
{1: }a │{11: 2 }a |
{1: }{8:x}{9: }│{11: 3 }{8:y}{9: }|
- {1: }{4:x }│{11: }{2:----------------}|
- {1: }{4:x }│{11: }{2:----------------}|
+ {1: }{4:x }│{11: }{2:----------------}|*2
{1: }b │{11: 4 }b |
{1: }b │{11: 5 }b |
{1: }b │{11: 6 }b |
@@ -1464,8 +1261,7 @@ it('diff updates line numbers below filler lines', function()
{1: }a │{10:2 }^a |
{1: }a │{11: 1 }a |
{1: }{8:x}{9: }│{11: 2 }{8:y}{9: }|
- {1: }{4:x }│{11: }{2:----------------}|
- {1: }{4:x }│{11: }{2:----------------}|
+ {1: }{4:x }│{11: }{2:----------------}|*2
{1: }b │{11: 3 }b |
{1: }b │{11: 4 }b |
{1: }b │{11: 5 }b |
@@ -1481,8 +1277,7 @@ it('diff updates line numbers below filler lines', function()
{1: }a │{11: 1 }a |
{1: }a │{10:3 }^a |
{1: }{8:x}{9: }│{11: 1 }{8:y}{9: }|
- {1: }{4:x }│{11: }{2:----------------}|
- {1: }{4:x }│{11: }{2:----------------}|
+ {1: }{4:x }│{11: }{2:----------------}|*2
{1: }b │{11: 2 }b |
{1: }b │{11: 3 }b |
{1: }b │{11: 4 }b |
@@ -1496,18 +1291,17 @@ end)
-- oldtest: Test_diff_with_scroll_and_change()
it('Align the filler lines when changing text in diff mode', function()
- clear()
local screen = Screen.new(40, 20)
screen:attach()
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray};
- [2] = {background = Screen.colors.LightCyan, foreground = Screen.colors.Blue1, bold = true};
- [3] = {reverse = true};
- [4] = {background = Screen.colors.LightBlue};
- [5] = {background = Screen.colors.LightMagenta};
- [6] = {background = Screen.colors.Red, bold = true};
- [7] = {foreground = Screen.colors.Blue1, bold = true};
- [8] = {reverse = true, bold = true};
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray },
+ [2] = { background = Screen.colors.LightCyan, foreground = Screen.colors.Blue1, bold = true },
+ [3] = { reverse = true },
+ [4] = { background = Screen.colors.LightBlue },
+ [5] = { background = Screen.colors.LightMagenta },
+ [6] = { background = Screen.colors.Red, bold = true },
+ [7] = { foreground = Screen.colors.Blue1, bold = true },
+ [8] = { reverse = true, bold = true },
})
exec([[
call setline(1, range(1, 15))
@@ -1517,7 +1311,8 @@ it('Align the filler lines when changing text in diff mode', function()
wincmd h
exe "normal Gl5\<C-E>"
]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }{2:------------------}│{1: }{4:6 }|
{1: }{2:------------------}│{1: }{4:7 }|
{1: }{2:------------------}│{1: }{4:8 }|
@@ -1528,19 +1323,14 @@ it('Align the filler lines when changing text in diff mode', function()
{1: }13 │{1: }13 |
{1: }14 │{1: }14 |
{1:- }1^5 │{1:- }15 |
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
+ {7:~ }│{7:~ }|*8
{8:[No Name] [+] }{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
feed('ax<Esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }{2:------------------}│{1: }{4:6 }|
{1: }{2:------------------}│{1: }{4:7 }|
{1: }{2:------------------}│{1: }{4:8 }|
@@ -1551,19 +1341,14 @@ it('Align the filler lines when changing text in diff mode', function()
{1: }13 │{1: }13 |
{1: }14 │{1: }14 |
{1: }{5:15}{6:^x}{5: }│{1: }{5:15 }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
+ {7:~ }│{7:~ }|*8
{8:[No Name] [+] }{3:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
feed('<C-W>lay<Esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }{2:-----------------}│{1: }{4:6 }|
{1: }{2:-----------------}│{1: }{4:7 }|
{1: }{2:-----------------}│{1: }{4:8 }|
@@ -1574,52 +1359,41 @@ it('Align the filler lines when changing text in diff mode', function()
{1: }13 │{1: }13 |
{1: }14 │{1: }14 |
{1: }{5:15}{6:x}{5: }│{1: }{5:15}{6:^y}{5: }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
+ {7:~ }│{7:~ }|*8
{3:[No Name] [+] }{8:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
end)
it("diff mode doesn't restore invalid 'foldcolumn' value #21647", function()
- clear()
local screen = Screen.new(60, 6)
screen:set_default_attr_ids({
- [0] = {foreground = Screen.colors.Blue, bold = true};
+ [0] = { foreground = Screen.colors.Blue, bold = true },
})
screen:attach()
- eq('0', meths.get_option_value('foldcolumn', {}))
+ eq('0', api.nvim_get_option_value('foldcolumn', {}))
command('diffsplit | bd')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
- eq('0', meths.get_option_value('foldcolumn', {}))
+ eq('0', api.nvim_get_option_value('foldcolumn', {}))
end)
-- oldtest: Test_diff_binary()
it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', function()
- clear()
local screen = Screen.new(40, 20)
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray};
- [2] = {reverse = true};
- [3] = {background = Screen.colors.LightBlue};
- [4] = {background = Screen.colors.LightMagenta};
- [5] = {background = Screen.colors.Red, bold = true};
- [6] = {foreground = Screen.colors.Blue, bold = true};
- [7] = {background = Screen.colors.Red, foreground = Screen.colors.Blue, bold = true};
- [8] = {reverse = true, bold = true};
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray },
+ [2] = { reverse = true },
+ [3] = { background = Screen.colors.LightBlue },
+ [4] = { background = Screen.colors.LightMagenta },
+ [5] = { background = Screen.colors.Red, bold = true },
+ [6] = { foreground = Screen.colors.Blue, bold = true },
+ [7] = { background = Screen.colors.Red, foreground = Screen.colors.Blue, bold = true },
+ [8] = { reverse = true, bold = true },
})
screen:attach()
exec([[
@@ -1641,17 +1415,7 @@ it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', fun
{1: }{5:E}{4: }│{1: }{5:e}{4: }|
{1: }f │{1: }f |
{1: }g │{1: }g |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*11
{8:[No Name] [+] }{2:[No Name] [+] }|
|
]])
@@ -1667,17 +1431,7 @@ it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', fun
{1: }E │{1: }e |
{1: }f │{1: }f |
{1: }g │{1: }g |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*11
{8:[No Name] [+] }{2:[No Name] [+] }|
|
]])
@@ -1693,17 +1447,7 @@ it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', fun
{1: }{5:E}{4: }│{1: }{5:e}{4: }|
{1: }f │{1: }f |
{1: }g │{1: }g |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*11
{8:[No Name] [+] }{2:[No Name] [+] }|
|
]])
@@ -1719,18 +1463,36 @@ it('diff mode works properly if file contains NUL bytes vim-patch:8.2.3925', fun
{1: }E │{1: }e |
{1: }f │{1: }f |
{1: }g │{1: }g |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*11
{8:[No Name] [+] }{2:[No Name] [+] }|
|
]])
end)
+
+-- oldtest: Test_diff_breakindent_after_filler()
+it("diff mode draws 'breakindent' correctly after filler lines", function()
+ local screen = Screen.new(45, 8)
+ screen:attach()
+ screen:set_default_attr_ids({
+ [1] = { background = Screen.colors.Grey, foreground = Screen.colors.DarkBlue },
+ [2] = { background = Screen.colors.LightBlue },
+ [3] = { background = Screen.colors.LightCyan, bold = true, foreground = Screen.colors.Blue },
+ [4] = { foreground = Screen.colors.Blue, bold = true },
+ })
+ exec([[
+ set laststatus=0 diffopt+=followwrap breakindent breakindentopt=min:0
+ call setline(1, ['a', ' ' .. repeat('c', 50)])
+ vnew
+ call setline(1, ['a', 'b', ' ' .. repeat('c', 50)])
+ windo diffthis
+ norm! G$
+ ]])
+ screen:expect([[
+ {1: }a │{1: }a |
+ {1: }{2:b }│{1: }{3:--------------------}|
+ {1: } cccccccccccccccccc│{1: } cccccccccccccccccc|*2
+ {1: } cccccccccccccc │{1: } ccccccccccccc^c |
+ {4:~ }│{4:~ }|*2
+ |
+ ]])
+end)
diff --git a/test/functional/ui/embed_spec.lua b/test/functional/ui/embed_spec.lua
index 9729f65355..0445476780 100644
--- a/test/functional/ui/embed_spec.lua
+++ b/test/functional/ui/embed_spec.lua
@@ -1,56 +1,53 @@
-local uv = require'luv'
+local uv = vim.uv
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local api = helpers.api
local feed = helpers.feed
local eq = helpers.eq
local neq = helpers.neq
local clear = helpers.clear
local ok = helpers.ok
-local funcs = helpers.funcs
+local fn = helpers.fn
local nvim_prog = helpers.nvim_prog
local retry = helpers.retry
+local write_file = helpers.write_file
local function test_embed(ext_linegrid)
local screen
local function startup(...)
- clear{args_rm={'--headless'}, args={...}}
+ clear { args_rm = { '--headless' }, args = { ... } }
-- attach immediately after startup, for early UI
screen = Screen.new(60, 8)
- screen:attach{ext_linegrid=ext_linegrid}
+ screen:attach { ext_linegrid = ext_linegrid }
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [2] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [3] = {bold = true, foreground = Screen.colors.Blue1},
- [4] = {bold = true, foreground = Screen.colors.Green},
- [5] = {bold = true, reverse = true},
+ [1] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [2] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [3] = { bold = true, foreground = Screen.colors.Blue1 },
+ [4] = { bold = true, foreground = Screen.colors.Green },
+ [5] = { bold = true, reverse = true },
+ [6] = { foreground = Screen.colors.NvimLightGrey3, background = Screen.colors.NvimDarkGrey3 },
+ [7] = { foreground = Screen.colors.NvimDarkRed },
+ [8] = { foreground = Screen.colors.NvimDarkCyan },
})
end
it('can display errors', function()
startup('--cmd', 'echoerr invalid+')
screen:expect([[
- |
- |
- |
- |
- |
- Error detected while processing pre-vimrc command line: |
- E121: Undefined variable: invalid |
- Press ENTER or type command to continue^ |
+ |*4
+ {6: }|
+ {7:Error detected while processing pre-vimrc command line:} |
+ {7:E121: Undefined variable: invalid} |
+ {8:Press ENTER or type command to continue}^ |
]])
feed('<cr>')
screen:expect([[
^ |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*6
|
]])
end)
@@ -61,36 +58,39 @@ local function test_embed(ext_linegrid)
end
startup('--cmd', 'echoerr "foo"', '--cmd', 'color default', '--cmd', 'echoerr "bar"')
screen:expect([[
- |
- |
- |
- {5: }|
- Error detected while processing pre-vimrc command line: |
- foo |
- {1:bar} |
- {4:Press ENTER or type command to continue}^ |
+ |*3
+ {6: }|
+ {7:Error detected while processing pre-vimrc command line:} |
+ {7:foo} |
+ {7:bar} |
+ {8:Press ENTER or type command to continue}^ |
]])
end)
it("doesn't erase output when setting Normal colors", function()
startup('--cmd', 'echoerr "foo"', '--cmd', 'hi Normal guibg=Green', '--cmd', 'echoerr "bar"')
- screen:expect{grid=[[
- |
- |
- |
- |
- Error detected while processing pre-vimrc command line: |
- foo |
- bar |
- Press ENTER or type command to continue^ |
- ]], condition=function()
- eq(Screen.colors.Green, screen.default_colors.rgb_bg)
- end}
+ screen:expect {
+ grid = [[
+ |*3
+ {6: }|
+ {7:Error detected while processing pre-vimrc command line:} |
+ {7:foo} |
+ {7:bar} |
+ {8:Press ENTER or type command to continue}^ |
+ ]],
+ condition = function()
+ eq(Screen.colors.Green, screen.default_colors.rgb_bg)
+ end,
+ }
end)
end
-describe('--embed UI on startup (ext_linegrid=true)', function() test_embed(true) end)
-describe('--embed UI on startup (ext_linegrid=false)', function() test_embed(false) end)
+describe('--embed UI on startup (ext_linegrid=true)', function()
+ test_embed(true)
+end)
+describe('--embed UI on startup (ext_linegrid=false)', function()
+ test_embed(false)
+end)
describe('--embed UI', function()
it('can pass stdin', function()
@@ -99,43 +99,186 @@ describe('--embed UI', function()
local writer = assert(uv.new_pipe(false))
writer:open(pipe.write)
- clear {args_rm={'--headless'}, io_extra=pipe.read}
+ clear { args_rm = { '--headless' }, io_extra = pipe.read }
-- attach immediately after startup, for early UI
local screen = Screen.new(40, 8)
- screen.rpc_async = true -- Avoid hanging. #24888
- screen:attach {stdin_fd=3}
+ screen.rpc_async = true -- Avoid hanging. #24888
+ screen:attach { stdin_fd = 3 }
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Blue1};
- [2] = {bold = true};
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true },
}
- writer:write "hello nvim\nfrom external input\n"
- writer:shutdown(function() writer:close() end)
+ writer:write 'hello nvim\nfrom external input\n'
+ writer:shutdown(function()
+ writer:close()
+ end)
- screen:expect{grid=[[
+ screen:expect [[
^hello nvim |
from external input |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
- ]]}
+ ]]
-- stdin (rpc input) still works
feed 'o'
- screen:expect{grid=[[
+ screen:expect [[
hello nvim |
^ |
from external input |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{2:-- INSERT --} |
- ]]}
+ ]]
+ end)
+
+ it('can pass stdin to -q - #17523', function()
+ write_file(
+ 'Xbadfile.c',
+ [[
+ /* some file with an error */
+ main() {
+ functionCall(arg; arg, arg);
+ return 666
+ }
+ ]]
+ )
+ finally(function()
+ os.remove('Xbadfile.c')
+ end)
+
+ local pipe = assert(uv.pipe())
+
+ local writer = assert(uv.new_pipe(false))
+ writer:open(pipe.write)
+
+ clear { args_rm = { '--headless' }, args = { '-q', '-' }, io_extra = pipe.read }
+
+ -- attach immediately after startup, for early UI
+ local screen = Screen.new(60, 8)
+ screen.rpc_async = true -- Avoid hanging. #24888
+ screen:attach { stdin_fd = 3 }
+ screen:set_default_attr_ids {
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true },
+ }
+
+ writer:write [[Xbadfile.c:4:12: error: expected ';' before '}' token]]
+ writer:shutdown(function()
+ writer:close()
+ end)
+
+ screen:expect [[
+ /* some file with an error */ |
+ main() { |
+ functionCall(arg; arg, arg); |
+ return 66^6 |
+ } |
+ {1:~ }|*2
+ (1 of 1): error: expected ';' before '}' token |
+ ]]
+
+ -- stdin (rpc input) still works
+ feed 'A'
+ screen:expect [[
+ /* some file with an error */ |
+ main() { |
+ functionCall(arg; arg, arg); |
+ return 666^ |
+ } |
+ {1:~ }|*2
+ {2:-- INSERT --} |
+ ]]
+
+ eq('-', api.nvim_get_option_value('errorfile', {}))
+ end)
+
+ it('only sets background colors once even if overridden', function()
+ local screen, current, seen
+ local function handle_default_colors_set(_, _, rgb_bg, _, _, _)
+ seen[rgb_bg] = true
+ current = rgb_bg
+ end
+ local function startup(...)
+ seen = {}
+ current = nil
+ clear { args_rm = { '--headless' }, args = { ... } }
+
+ -- attach immediately after startup, for early UI
+ screen = Screen.new(40, 8)
+ screen._handle_default_colors_set = handle_default_colors_set
+ screen:attach()
+ end
+
+ startup()
+ screen:expect {
+ condition = function()
+ eq(16777215, current)
+ end,
+ }
+ eq({ [16777215] = true }, seen)
+
+ -- NB: by accident how functional/helpers.lua currently handles the default color scheme, the
+ -- above is sufficient to test the behavior. But in case that workaround is removed, we need
+ -- a test with an explicit override like below, so do it to remain safe.
+ startup('--cmd', 'hi NORMAL guibg=#FF00FF')
+ screen:expect {
+ condition = function()
+ eq(16711935, current)
+ end,
+ }
+ eq({ [16711935] = true }, seen) -- we only saw the last one, despite 16777215 was set internally earlier
+ end)
+
+ it('updates cwd of attached UI #21771', function()
+ clear { args_rm = { '--headless' } }
+
+ local screen = Screen.new(40, 8)
+ screen:attach()
+
+ screen:expect {
+ condition = function()
+ eq(helpers.paths.test_source_path, screen.pwd)
+ end,
+ }
+
+ -- Change global cwd
+ helpers.command(string.format('cd %s/src/nvim', helpers.paths.test_source_path))
+
+ screen:expect {
+ condition = function()
+ eq(string.format('%s/src/nvim', helpers.paths.test_source_path), screen.pwd)
+ end,
+ }
+
+ -- Split the window and change the cwd in the split
+ helpers.command('new')
+ helpers.command(string.format('lcd %s/test', helpers.paths.test_source_path))
+
+ screen:expect {
+ condition = function()
+ eq(string.format('%s/test', helpers.paths.test_source_path), screen.pwd)
+ end,
+ }
+
+ -- Move to the original window
+ helpers.command('wincmd p')
+
+ screen:expect {
+ condition = function()
+ eq(string.format('%s/src/nvim', helpers.paths.test_source_path), screen.pwd)
+ end,
+ }
+
+ -- Change global cwd again
+ helpers.command(string.format('cd %s', helpers.paths.test_source_path))
+
+ screen:expect {
+ condition = function()
+ eq(helpers.paths.test_source_path, screen.pwd)
+ end,
+ }
end)
end)
@@ -144,8 +287,18 @@ describe('--embed --listen UI', function()
helpers.skip(helpers.is_os('win'))
clear()
local child_server = assert(helpers.new_pipename())
- funcs.jobstart({nvim_prog, '--embed', '--listen', child_server, '--clean'})
- retry(nil, nil, function() neq(nil, uv.fs_stat(child_server)) end)
+ fn.jobstart({
+ nvim_prog,
+ '--embed',
+ '--listen',
+ child_server,
+ '--clean',
+ '--cmd',
+ 'colorscheme vim',
+ })
+ retry(nil, nil, function()
+ neq(nil, uv.fs_stat(child_server))
+ end)
local child_session = helpers.connect(child_server)
@@ -154,11 +307,15 @@ describe('--embed --listen UI', function()
eq(2, #api_info)
ok(api_info[1] > 2, 'channel_id > 2', api_info[1])
- child_session:request('nvim_exec2', [[
+ child_session:request(
+ 'nvim_exec2',
+ [[
let g:evs = []
autocmd UIEnter * call add(g:evs, $"UIEnter:{v:event.chan}")
autocmd VimEnter * call add(g:evs, "VimEnter")
- ]], {})
+ ]],
+ {}
+ )
-- VimEnter and UIEnter shouldn't be triggered until after attach
local var_ok, var = child_session:request('nvim_get_var', 'evs')
@@ -167,21 +324,22 @@ describe('--embed --listen UI', function()
local child_screen = Screen.new(40, 6)
child_screen:attach(nil, child_session)
- child_screen:expect{grid=[[
+ child_screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:[No Name] 0,0-1 All}|
|
- ]], attr_ids={
- [1] = {foreground = Screen.colors.Blue, bold = true};
- [2] = {reverse = true, bold = true};
- }}
+ ]],
+ attr_ids = {
+ [1] = { foreground = Screen.colors.Blue, bold = true },
+ [2] = { reverse = true, bold = true },
+ },
+ }
-- VimEnter and UIEnter should now be triggered
var_ok, var = child_session:request('nvim_get_var', 'evs')
ok(var_ok)
- eq({'VimEnter', ('UIEnter:%d'):format(api_info[1])}, var)
+ eq({ 'VimEnter', ('UIEnter:%d'):format(api_info[1]) }, var)
end)
end)
diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua
index 2902b4a4a5..cdb3b79963 100644
--- a/test/functional/ui/float_spec.lua
+++ b/test/functional/ui/float_spec.lua
@@ -1,6 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local global_helpers = require('test.helpers')
local os = require('os')
local clear, feed = helpers.clear, helpers.feed
local assert_alive = helpers.assert_alive
@@ -12,14 +11,15 @@ local expect = helpers.expect
local exec = helpers.exec
local exec_lua = helpers.exec_lua
local insert = helpers.insert
-local meths = helpers.meths
-local curbufmeths = helpers.curbufmeths
-local funcs = helpers.funcs
+local api = helpers.api
+local fn = helpers.fn
local run = helpers.run
local pcall_err = helpers.pcall_err
-local tbl_contains = global_helpers.tbl_contains
-local curbuf, curwin, curtab = helpers.curbuf, helpers.curwin, helpers.curtab
-local NIL = helpers.NIL
+local tbl_contains = vim.tbl_contains
+local curbuf = helpers.api.nvim_get_current_buf
+local curwin = helpers.api.nvim_get_current_win
+local curtab = helpers.api.nvim_get_current_tabpage
+local NIL = vim.NIL
describe('float window', function()
before_each(function()
@@ -31,36 +31,36 @@ describe('float window', function()
-- Create three windows and test that ":wincmd <direction>" changes to the
-- first window, if the previous window is invalid.
command('split')
- meths.open_win(0, true, {width=10, height=10, relative='editor', row=0, col=0})
- eq(1002, funcs.win_getid())
- eq('editor', meths.win_get_config(1002).relative)
+ api.nvim_open_win(0, true, {width=10, height=10, relative='editor', row=0, col=0})
+ eq(1002, fn.win_getid())
+ eq('editor', api.nvim_win_get_config(1002).relative)
command([[
call nvim_win_close(1001, v:false)
wincmd j
]])
- eq(1000, funcs.win_getid())
+ eq(1000, fn.win_getid())
end)
it('win_execute() should work' , function()
- local buf = meths.create_buf(false, false)
- meths.buf_set_lines(buf, 0, -1, true, {'the floatwin', 'abc', 'def'})
- local win = meths.open_win(buf, false, {relative='win', width=16, height=1, row=0, col=10})
- local line = funcs.win_execute(win, 'echo getline(1)')
+ local buf = api.nvim_create_buf(false, false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'the floatwin', 'abc', 'def'})
+ local win = api.nvim_open_win(buf, false, {relative='win', width=16, height=1, row=0, col=10})
+ local line = fn.win_execute(win, 'echo getline(1)')
eq('\nthe floatwin', line)
- eq('\n1', funcs.win_execute(win, 'echo line(".",'..win.id..')'))
- eq('\n3', funcs.win_execute(win, 'echo line("$",'..win.id..')'))
- eq('\n0', funcs.win_execute(win, 'echo line("$", 123456)'))
- funcs.win_execute(win, 'bwipe!')
+ eq('\n1', fn.win_execute(win, 'echo line(".",'..win..')'))
+ eq('\n3', fn.win_execute(win, 'echo line("$",'..win..')'))
+ eq('\n0', fn.win_execute(win, 'echo line("$", 123456)'))
+ fn.win_execute(win, 'bwipe!')
end)
it("win_execute() call commands that are not allowed when 'hidden' is not set" , function()
command('set nohidden')
- local buf = meths.create_buf(false, false)
- meths.buf_set_lines(buf, 0, -1, true, {'the floatwin'})
- local win = meths.open_win(buf, true, {relative='win', width=16, height=1, row=0, col=10})
- eq('Vim(close):E37: No write since last change (add ! to override)', pcall_err(funcs.win_execute, win, 'close'))
- eq('Vim(bdelete):E89: No write since last change for buffer 2 (add ! to override)', pcall_err(funcs.win_execute, win, 'bdelete'))
- funcs.win_execute(win, 'bwipe!')
+ local buf = api.nvim_create_buf(false, false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'the floatwin'})
+ local win = api.nvim_open_win(buf, true, {relative='win', width=16, height=1, row=0, col=10})
+ eq('Vim(close):E37: No write since last change (add ! to override)', pcall_err(fn.win_execute, win, 'close'))
+ eq('Vim(bdelete):E89: No write since last change for buffer 2 (add ! to override)', pcall_err(fn.win_execute, win, 'bdelete'))
+ fn.win_execute(win, 'bwipe!')
end)
it('closed immediately by autocmd #11383', function()
@@ -104,14 +104,20 @@ describe('float window', function()
end)
it('open with WinNew autocmd', function()
- local res = exec_lua([[
- local triggerd = false
+ local new_triggered_before_enter, new_curwin, win = unpack(exec_lua([[
+ local enter_triggered = false
+ local new_triggered_before_enter = false
+ local new_curwin
local buf = vim.api.nvim_create_buf(true, true)
+ vim.api.nvim_create_autocmd('WinEnter', {
+ callback = function()
+ enter_triggered = true
+ end
+ })
vim.api.nvim_create_autocmd('WinNew', {
- callback = function(opt)
- if opt.buf == buf then
- triggerd = true
- end
+ callback = function()
+ new_triggered_before_enter = not enter_triggered
+ new_curwin = vim.api.nvim_get_current_win()
end
})
local opts = {
@@ -120,10 +126,11 @@ describe('float window', function()
width = 1, height = 1,
noautocmd = false,
}
- vim.api.nvim_open_win(buf, true, opts)
- return triggerd
- ]])
- eq(true, res)
+ local win = vim.api.nvim_open_win(buf, true, opts)
+ return {new_triggered_before_enter, new_curwin, win}
+ ]]))
+ eq(true, new_triggered_before_enter)
+ eq(win, new_curwin)
end)
it('opened with correct height', function()
@@ -193,7 +200,7 @@ describe('float window', function()
end)
it('opened with correct position relative to the mouse', function()
- meths.input_mouse('left', 'press', '', 0, 10, 10)
+ api.nvim_input_mouse('left', 'press', '', 0, 10, 10)
local pos = exec_lua([[
local bufnr = vim.api.nvim_create_buf(false, true)
@@ -480,67 +487,67 @@ describe('float window', function()
it('no crash with bufpos and non-existent window', function()
command('new')
- local closed_win = meths.get_current_win().id
+ local closed_win = api.nvim_get_current_win()
command('close')
- local buf = meths.create_buf(false,false)
- meths.open_win(buf, true, {relative='win', win=closed_win, width=1, height=1, bufpos={0,0}})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_open_win(buf, true, {relative='win', win=closed_win, width=1, height=1, bufpos={0,0}})
assert_alive()
end)
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.set_option_value('fillchars', NIL, {win=float_win.id})
+ local float_win = api.nvim_open_win(0, true, float_opts)
+ api.nvim_set_option_value('fillchars', NIL, {win=float_win})
float_opts.style = 'minimal'
- meths.win_set_config(float_win, float_opts)
+ api.nvim_win_set_config(float_win, float_opts)
assert_alive()
end)
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.set_option_value('number', true, { win = float_win })
+ local float_win = api.nvim_open_win(0, true, float_opts)
+ api.nvim_set_option_value('number', true, { win = float_win })
float_opts.row = 2
- meths.win_set_config(float_win, float_opts)
- eq(false, meths.get_option_value('number', { win = float_win }))
+ api.nvim_win_set_config(float_win, float_opts)
+ eq(false, api.nvim_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.set_option_value('number', true, { win = float_win })
+ local float_win = api.nvim_open_win(0, true, float_opts)
+ api.nvim_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.get_option_value('number', { win = float_win }))
+ api.nvim_win_set_config(float_win, float_opts)
+ eq(true, api.nvim_get_option_value('number', { win = float_win }))
end)
it("'scroll' is computed correctly when opening float with splitkeep=screen #20684", function()
- meths.set_option_value('splitkeep', 'screen', {})
+ api.nvim_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.get_option_value('scroll', {win=float_win.id}))
+ local float_win = api.nvim_open_win(0, true, float_opts)
+ eq(5, api.nvim_get_option_value('scroll', {win=float_win}))
end)
it(':unhide works when there are floating windows', function()
local float_opts = {relative = 'editor', row = 1, col = 1, width = 5, height = 5}
local w0 = curwin()
- meths.open_win(0, false, float_opts)
- meths.open_win(0, false, float_opts)
- eq(3, #meths.list_wins())
+ api.nvim_open_win(0, false, float_opts)
+ api.nvim_open_win(0, false, float_opts)
+ eq(3, #api.nvim_list_wins())
command('unhide')
- eq({ w0 }, meths.list_wins())
+ eq({ w0 }, api.nvim_list_wins())
end)
it(':all works when there are floating windows', function()
command('args Xa.txt')
local float_opts = {relative = 'editor', row = 1, col = 1, width = 5, height = 5}
local w0 = curwin()
- meths.open_win(0, false, float_opts)
- meths.open_win(0, false, float_opts)
- eq(3, #meths.list_wins())
+ api.nvim_open_win(0, false, float_opts)
+ api.nvim_open_win(0, false, float_opts)
+ eq(3, #api.nvim_list_wins())
command('all')
- eq({ w0 }, meths.list_wins())
+ eq({ w0 }, api.nvim_list_wins())
end)
describe('with only one tabpage,', function()
@@ -548,42 +555,42 @@ describe('float window', function()
local old_buf, old_win
before_each(function()
insert('foo')
- old_buf = curbuf().id
- old_win = curwin().id
+ old_buf = curbuf()
+ old_win = curwin()
end)
describe('closing the last non-floating window gives E444', function()
before_each(function()
- meths.open_win(old_buf, true, float_opts)
+ api.nvim_open_win(old_buf, true, float_opts)
end)
it('if called from non-floating window', function()
- meths.set_current_win(old_win)
+ api.nvim_set_current_win(old_win)
eq('Vim:E444: Cannot close last window',
- pcall_err(meths.win_close, old_win, false))
+ pcall_err(api.nvim_win_close, old_win, false))
end)
it('if called from floating window', function()
eq('Vim:E444: Cannot close last window',
- pcall_err(meths.win_close, old_win, false))
+ pcall_err(api.nvim_win_close, old_win, false))
end)
end)
describe("deleting the last non-floating window's buffer", function()
describe('leaves one window with an empty buffer when there is only one buffer', function()
local same_buf_float
before_each(function()
- same_buf_float = meths.open_win(old_buf, false, float_opts).id
+ same_buf_float = api.nvim_open_win(old_buf, false, float_opts)
end)
after_each(function()
- eq(old_win, curwin().id)
+ eq(old_win, curwin())
expect('')
- eq(1, #meths.list_wins())
+ eq(1, #api.nvim_list_wins())
end)
it('if called from non-floating window', function()
- meths.buf_delete(old_buf, {force = true})
+ api.nvim_buf_delete(old_buf, {force = true})
end)
it('if called from floating window', function()
- meths.set_current_win(same_buf_float)
+ api.nvim_set_current_win(same_buf_float)
command('autocmd WinLeave * let g:win_leave = nvim_get_current_win()')
command('autocmd WinEnter * let g:win_enter = nvim_get_current_win()')
- meths.buf_delete(old_buf, {force = true})
+ api.nvim_buf_delete(old_buf, {force = true})
eq(same_buf_float, eval('g:win_leave'))
eq(old_win, eval('g:win_enter'))
end)
@@ -591,67 +598,67 @@ describe('float window', function()
describe('closes other windows with that buffer when there are other buffers', function()
local same_buf_float, other_buf, other_buf_float
before_each(function()
- same_buf_float = meths.open_win(old_buf, false, float_opts).id
- other_buf = meths.create_buf(true, false).id
- other_buf_float = meths.open_win(other_buf, true, float_opts).id
+ same_buf_float = api.nvim_open_win(old_buf, false, float_opts)
+ other_buf = api.nvim_create_buf(true, false)
+ other_buf_float = api.nvim_open_win(other_buf, true, float_opts)
insert('bar')
- meths.set_current_win(old_win)
+ api.nvim_set_current_win(old_win)
end)
after_each(function()
- eq(other_buf, curbuf().id)
+ eq(other_buf, curbuf())
expect('bar')
- eq(2, #meths.list_wins())
+ eq(2, #api.nvim_list_wins())
end)
it('if called from non-floating window', function()
- meths.buf_delete(old_buf, {force = true})
- eq(old_win, curwin().id)
+ api.nvim_buf_delete(old_buf, {force = true})
+ eq(old_win, curwin())
end)
it('if called from floating window with the same buffer', function()
- meths.set_current_win(same_buf_float)
+ api.nvim_set_current_win(same_buf_float)
command('autocmd WinLeave * let g:win_leave = nvim_get_current_win()')
command('autocmd WinEnter * let g:win_enter = nvim_get_current_win()')
- meths.buf_delete(old_buf, {force = true})
+ api.nvim_buf_delete(old_buf, {force = true})
eq(same_buf_float, eval('g:win_leave'))
eq(old_win, eval('g:win_enter'))
- eq(old_win, curwin().id)
+ eq(old_win, curwin())
end)
-- TODO: this case is too hard to deal with
pending('if called from floating window with another buffer', function()
- meths.set_current_win(other_buf_float)
- meths.buf_delete(old_buf, {force = true})
+ api.nvim_set_current_win(other_buf_float)
+ api.nvim_buf_delete(old_buf, {force = true})
end)
end)
describe('creates an empty buffer when there is only one listed buffer', function()
local same_buf_float, unlisted_buf_float
before_each(function()
- same_buf_float = meths.open_win(old_buf, false, float_opts).id
- local unlisted_buf = meths.create_buf(true, false).id
- unlisted_buf_float = meths.open_win(unlisted_buf, true, float_opts).id
+ same_buf_float = api.nvim_open_win(old_buf, false, float_opts)
+ local unlisted_buf = api.nvim_create_buf(true, false)
+ unlisted_buf_float = api.nvim_open_win(unlisted_buf, true, float_opts)
insert('unlisted')
command('set nobuflisted')
- meths.set_current_win(old_win)
+ api.nvim_set_current_win(old_win)
end)
after_each(function()
expect('')
- eq(2, #meths.list_wins())
+ eq(2, #api.nvim_list_wins())
end)
it('if called from non-floating window', function()
- meths.buf_delete(old_buf, {force = true})
- eq(old_win, curwin().id)
+ api.nvim_buf_delete(old_buf, {force = true})
+ eq(old_win, curwin())
end)
it('if called from floating window with the same buffer', function()
- meths.set_current_win(same_buf_float)
+ api.nvim_set_current_win(same_buf_float)
command('autocmd WinLeave * let g:win_leave = nvim_get_current_win()')
command('autocmd WinEnter * let g:win_enter = nvim_get_current_win()')
- meths.buf_delete(old_buf, {force = true})
+ api.nvim_buf_delete(old_buf, {force = true})
eq(same_buf_float, eval('g:win_leave'))
eq(old_win, eval('g:win_enter'))
- eq(old_win, curwin().id)
+ eq(old_win, curwin())
end)
-- TODO: this case is too hard to deal with
pending('if called from floating window with an unlisted buffer', function()
- meths.set_current_win(unlisted_buf_float)
- meths.buf_delete(old_buf, {force = true})
+ api.nvim_set_current_win(unlisted_buf_float)
+ api.nvim_buf_delete(old_buf, {force = true})
end)
end)
end)
@@ -662,21 +669,21 @@ describe('float window', function()
command('botright vnew')
insert('unlisted')
command('set nobuflisted')
- meths.set_current_win(old_win)
- same_buf_float = meths.open_win(old_buf, false, float_opts).id
+ api.nvim_set_current_win(old_win)
+ same_buf_float = api.nvim_open_win(old_buf, false, float_opts)
end)
after_each(function()
expect('')
- eq(2, #meths.list_wins())
+ eq(2, #api.nvim_list_wins())
end)
it('if called from non-floating window with the deleted buffer', function()
- meths.buf_delete(old_buf, {force = true})
- eq(old_win, curwin().id)
+ api.nvim_buf_delete(old_buf, {force = true})
+ eq(old_win, curwin())
end)
it('if called from floating window with the deleted buffer', function()
- meths.set_current_win(same_buf_float)
- meths.buf_delete(old_buf, {force = true})
- eq(same_buf_float, curwin().id)
+ api.nvim_set_current_win(same_buf_float)
+ api.nvim_buf_delete(old_buf, {force = true})
+ eq(same_buf_float, curwin())
end)
end)
end)
@@ -688,63 +695,63 @@ describe('float window', function()
before_each(function()
insert('unlisted')
command('set nobuflisted')
- unlisted_buf = curbuf().id
+ unlisted_buf = curbuf()
command('tabnew')
insert('foo')
- old_buf = curbuf().id
- old_win = curwin().id
+ old_buf = curbuf()
+ old_win = curwin()
end)
describe('without splits, deleting the last listed buffer creates an empty buffer', function()
local same_buf_float
before_each(function()
- meths.set_current_win(old_win)
- same_buf_float = meths.open_win(old_buf, false, float_opts).id
+ api.nvim_set_current_win(old_win)
+ same_buf_float = api.nvim_open_win(old_buf, false, float_opts)
end)
after_each(function()
expect('')
- eq(2, #meths.list_wins())
- eq(2, #meths.list_tabpages())
+ eq(2, #api.nvim_list_wins())
+ eq(2, #api.nvim_list_tabpages())
end)
it('if called from non-floating window', function()
- meths.buf_delete(old_buf, {force = true})
- eq(old_win, curwin().id)
+ api.nvim_buf_delete(old_buf, {force = true})
+ eq(old_win, curwin())
end)
it('if called from non-floating window in another tabpage', function()
command('tab split')
- eq(3, #meths.list_tabpages())
- meths.buf_delete(old_buf, {force = true})
+ eq(3, #api.nvim_list_tabpages())
+ api.nvim_buf_delete(old_buf, {force = true})
end)
it('if called from floating window with the same buffer', function()
- meths.set_current_win(same_buf_float)
+ api.nvim_set_current_win(same_buf_float)
command('autocmd WinLeave * let g:win_leave = nvim_get_current_win()')
command('autocmd WinEnter * let g:win_enter = nvim_get_current_win()')
- meths.buf_delete(old_buf, {force = true})
+ api.nvim_buf_delete(old_buf, {force = true})
eq(same_buf_float, eval('g:win_leave'))
eq(old_win, eval('g:win_enter'))
- eq(old_win, curwin().id)
+ eq(old_win, curwin())
end)
end)
describe('with splits, deleting the last listed buffer creates an empty buffer', function()
local same_buf_float
before_each(function()
command('botright vsplit')
- meths.set_current_buf(unlisted_buf)
- meths.set_current_win(old_win)
- same_buf_float = meths.open_win(old_buf, false, float_opts).id
+ api.nvim_set_current_buf(unlisted_buf)
+ api.nvim_set_current_win(old_win)
+ same_buf_float = api.nvim_open_win(old_buf, false, float_opts)
end)
after_each(function()
expect('')
- eq(3, #meths.list_wins())
- eq(2, #meths.list_tabpages())
+ eq(3, #api.nvim_list_wins())
+ eq(2, #api.nvim_list_tabpages())
end)
it('if called from non-floating window with the deleted buffer', function()
- meths.buf_delete(old_buf, {force = true})
- eq(old_win, curwin().id)
+ api.nvim_buf_delete(old_buf, {force = true})
+ eq(old_win, curwin())
end)
it('if called from floating window with the deleted buffer', function()
- meths.set_current_win(same_buf_float)
- meths.buf_delete(old_buf, {force = true})
- eq(same_buf_float, curwin().id)
+ api.nvim_set_current_win(same_buf_float)
+ api.nvim_buf_delete(old_buf, {force = true})
+ eq(same_buf_float, curwin())
end)
end)
end)
@@ -753,48 +760,48 @@ describe('float window', function()
local float_opts = {relative = 'editor', row = 1, col = 1, width = 1, height = 1}
local old_tabpage, old_buf, old_win
before_each(function()
- old_tabpage = curtab().id
+ old_tabpage = curtab()
insert('oldtab')
command('tabnew')
- old_buf = curbuf().id
- old_win = curwin().id
+ old_buf = curbuf()
+ old_win = curwin()
end)
describe('closing the last non-floating window', function()
describe('closes the tabpage when all floating windows are closeable', function()
local same_buf_float
before_each(function()
- same_buf_float = meths.open_win(old_buf, false, float_opts).id
+ same_buf_float = api.nvim_open_win(old_buf, false, float_opts)
end)
after_each(function()
- eq(old_tabpage, curtab().id)
+ eq(old_tabpage, curtab())
expect('oldtab')
- eq(1, #meths.list_tabpages())
+ eq(1, #api.nvim_list_tabpages())
end)
it('if called from non-floating window', function()
- meths.win_close(old_win, false)
+ api.nvim_win_close(old_win, false)
end)
it('if called from floating window', function()
- meths.set_current_win(same_buf_float)
- meths.win_close(old_win, false)
+ api.nvim_set_current_win(same_buf_float)
+ api.nvim_win_close(old_win, false)
end)
end)
describe('gives E5601 when there are non-closeable floating windows', function()
local other_buf_float
before_each(function()
command('set nohidden')
- local other_buf = meths.create_buf(true, false).id
- other_buf_float = meths.open_win(other_buf, true, float_opts).id
+ local other_buf = api.nvim_create_buf(true, false)
+ other_buf_float = api.nvim_open_win(other_buf, true, float_opts)
insert('foo')
- meths.set_current_win(old_win)
+ api.nvim_set_current_win(old_win)
end)
it('if called from non-floating window', function()
eq('Vim:E5601: Cannot close window, only floating window would remain',
- pcall_err(meths.win_close, old_win, false))
+ pcall_err(api.nvim_win_close, old_win, false))
end)
it('if called from floating window', function()
- meths.set_current_win(other_buf_float)
+ api.nvim_set_current_win(other_buf_float)
eq('Vim:E5601: Cannot close window, only floating window would remain',
- pcall_err(meths.win_close, old_win, false))
+ pcall_err(api.nvim_win_close, old_win, false))
end)
end)
end)
@@ -802,27 +809,27 @@ describe('float window', function()
describe('closes the tabpage when all floating windows are closeable', function()
local same_buf_float, other_buf, other_buf_float
before_each(function()
- same_buf_float = meths.open_win(old_buf, false, float_opts).id
- other_buf = meths.create_buf(true, false).id
- other_buf_float = meths.open_win(other_buf, true, float_opts).id
- meths.set_current_win(old_win)
+ same_buf_float = api.nvim_open_win(old_buf, false, float_opts)
+ other_buf = api.nvim_create_buf(true, false)
+ other_buf_float = api.nvim_open_win(other_buf, true, float_opts)
+ api.nvim_set_current_win(old_win)
end)
after_each(function()
- eq(old_tabpage, curtab().id)
+ eq(old_tabpage, curtab())
expect('oldtab')
- eq(1, #meths.list_tabpages())
+ eq(1, #api.nvim_list_tabpages())
end)
it('if called from non-floating window', function()
- meths.buf_delete(old_buf, {force = false})
+ api.nvim_buf_delete(old_buf, {force = false})
end)
it('if called from floating window with the same buffer', function()
- meths.set_current_win(same_buf_float)
- meths.buf_delete(old_buf, {force = false})
+ api.nvim_set_current_win(same_buf_float)
+ api.nvim_buf_delete(old_buf, {force = false})
end)
-- TODO: this case is too hard to deal with
pending('if called from floating window with another buffer', function()
- meths.set_current_win(other_buf_float)
- meths.buf_delete(old_buf, {force = false})
+ api.nvim_set_current_win(other_buf_float)
+ api.nvim_buf_delete(old_buf, {force = false})
end)
end)
-- TODO: what to do when there are non-closeable floating windows?
@@ -862,36 +869,27 @@ describe('float window', function()
[24] = {foreground = Screen.colors.Black, background = Screen.colors.Grey80};
[25] = {blend = 100, background = Screen.colors.Gray0};
[26] = {blend = 80, background = Screen.colors.Gray0};
- [27] = {background = Screen.colors.LightGray};
- [28] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray};
+ [27] = {foreground = Screen.colors.Black, background = Screen.colors.LightGrey};
+ [28] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey};
}
screen:set_default_attr_ids(attrs)
end)
it('can be created and reconfigured', 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})
+ local buf = api.nvim_create_buf(false,false)
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
local expected_pos = {
- [4]={{id=1001}, 'NW', 1, 2, 5, true},
+ [4]={1001, 'NW', 1, 2, 5, true},
}
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -904,33 +902,23 @@ describe('float window', function()
{0:~ }|
{0:~ }{1: }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
- meths.win_set_config(win, {relative='editor', row=0, col=10})
+ api.nvim_win_set_config(win, {relative='editor', row=0, col=10})
expected_pos[4][4] = 0
expected_pos[4][5] = 10
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -941,43 +929,27 @@ describe('float window', function()
screen:expect([[
^ {1: } |
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end
- meths.win_close(win, false)
+ api.nvim_win_close(win, false)
if multigrid then
screen:expect([[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
]])
else
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end
@@ -985,39 +957,29 @@ describe('float window', function()
it('window position fixed', function()
command('rightbelow 20vsplit')
- local buf = meths.create_buf(false,false)
- local win = meths.open_win(buf, false, {
+ local buf = api.nvim_create_buf(false,false)
+ local win = api.nvim_open_win(buf, false, {
relative='win', width=15, height=2, row=2, col=10, anchor='NW', fixed=true})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
+ [2:-------------------]{5:│}[4:--------------------]|*5
{5:[No Name] }{4:[No Name] }|
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 5
{1: }|
{2:~ }|
]], float_pos={
- [5] = {{id = 1002}, "NW", 4, 2, 10, true};
+ [5] = {1002, "NW", 4, 2, 10, true};
}}
else
screen:expect([[
@@ -1031,7 +993,7 @@ describe('float window', function()
]])
end
- meths.win_set_config(win, {fixed=false})
+ api.nvim_win_set_config(win, {fixed=false})
if multigrid then
screen:expect_unchanged()
@@ -1055,29 +1017,20 @@ describe('float window', function()
-- or something.
command("set redrawdebug=compositor")
command("set wd=1")
- local buf = meths.create_buf(false,false)
- local win = meths.open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
+ local buf = api.nvim_create_buf(false,false)
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
local expected_pos = {
- [4]={{id=1001}, 'NW', 1, 2, 5, true},
+ [4]={1001, 'NW', 1, 2, 5, true},
}
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -1090,33 +1043,23 @@ describe('float window', function()
{0:~ }|
{0:~ }{1: }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
- meths.win_set_config(win, {relative='editor', row=0, col=10})
+ api.nvim_win_set_config(win, {relative='editor', row=0, col=10})
expected_pos[4][4] = 0
expected_pos[4][5] = 10
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -1127,84 +1070,70 @@ describe('float window', function()
screen:expect([[
^ {1: } |
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end
- meths.win_close(win, false)
+ api.nvim_win_close(win, false)
if multigrid then
screen:expect([[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
]])
else
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end
end)
it('return their configuration', function()
- local buf = meths.create_buf(false, false)
- local win = meths.open_win(buf, false, {relative='editor', width=20, height=2, row=3, col=5, zindex=60})
+ local buf = api.nvim_create_buf(false, false)
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=20, height=2, row=3, col=5, zindex=60})
local expected = {anchor='NW', col=5, external=false, focusable=true, height=2, relative='editor', row=3, width=20, zindex=60, hide=false}
- eq(expected, meths.win_get_config(win))
+ eq(expected, api.nvim_win_get_config(win))
+ eq(true, exec_lua([[
+ local expected, win = ...
+ local actual = vim.api.nvim_win_get_config(win)
+ for k,v in pairs(expected) do
+ if v ~= actual[k] then
+ error(k)
+ end
+ end
+ return true]], expected, win))
- eq({relative='', external=false, focusable=true, hide=false}, meths.win_get_config(0))
+ eq({external=false, focusable=true, hide=false, relative='',split="left",width=40,height=6}, api.nvim_win_get_config(0))
if multigrid then
- meths.win_set_config(win, {external=true, width=10, height=1})
- eq({external=true,focusable=true,width=10,height=1,relative='',hide=false}, meths.win_get_config(win))
+ api.nvim_win_set_config(win, {external=true, width=10, height=1})
+ eq({external=true,focusable=true,width=10,height=1,relative='',hide=false}, api.nvim_win_get_config(win))
end
end)
it('defaults to NormalFloat highlight and inherited options', function()
command('set number')
- command('hi NormalFloat guibg=#333333')
+ command('hi NormalFloat guibg=#333333 guifg=NONE')
feed('ix<cr>y<cr><esc>gg')
- local win = meths.open_win(0, false, {relative='editor', width=20, height=4, row=4, col=10})
+ local win = api.nvim_open_win(0, false, {relative='editor', width=20, height=4, row=4, col=10})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
{14: 1 }^x |
{14: 2 }y |
{14: 3 } |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
@@ -1212,7 +1141,7 @@ describe('float window', function()
{18: 2 }{15:y }|
{18: 3 }{15: }|
{16:~ }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+ ]], float_pos={[4] = {1001, "NW", 1, 4, 10, true}}}
else
screen:expect([[
{14: 1 }^x |
@@ -1225,41 +1154,30 @@ describe('float window', function()
]])
end
- local buf = meths.create_buf(false, true)
- meths.win_set_buf(win, buf)
+ local buf = api.nvim_create_buf(false, true)
+ api.nvim_win_set_buf(win, buf)
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
{14: 1 }^x |
{14: 2 }y |
{14: 3 } |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
{18: 1 }{15: }|
- {16:~ }|
- {16:~ }|
- {16:~ }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+ {16:~ }|*3
+ ]], float_pos={[4] = {1001, "NW", 1, 4, 10, true}}}
else
screen:expect([[
{14: 1 }^x |
{14: 2 }y |
{14: 3 } {18: 1 }{15: } |
- {0:~ }{16:~ }{0: }|
- {0:~ }{16:~ }{0: }|
- {0:~ }{16:~ }{0: }|
+ {0:~ }{16:~ }{0: }|*3
|
]])
end
@@ -1271,42 +1189,33 @@ describe('float window', function()
command('set colorcolumn=1')
command('set cursorline')
command('set foldcolumn=1')
- command('hi NormalFloat guibg=#333333')
+ command('hi NormalFloat guibg=#333333 guifg=NONE')
feed('ix<cr>y<cr><esc>gg')
- local win = meths.open_win(0, false, {relative='editor', width=20, height=4, row=4, col=10, style='minimal'})
+ local win = api.nvim_open_win(0, false, {relative='editor', width=20, height=4, row=4, col=10, style='minimal'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
{19: }{20: 1 }{22:^x}{21: }|
{19: }{14: 2 }{22:y} |
{19: }{14: 3 }{22: } |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
{15:x }|
{15:y }|
- {15: }|
- {15: }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+ {15: }|*2
+ ]], float_pos={[4] = {1001, "NW", 1, 4, 10, true}}}
else
screen:expect{grid=[[
{19: }{20: 1 }{22:^x}{21: }|
{19: }{14: 2 }{22:y} |
{19: }{14: 3 }{22: } {15:x } |
{0:~ }{15:y }{0: }|
- {0:~ }{15: }{0: }|
- {0:~ }{15: }{0: }|
+ {0:~ }{15: }{0: }|*2
|
]]}
end
@@ -1317,20 +1226,13 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
{19: }{17:ðŒ¢Ì€Ì̂̃̅̄ðŒ¢Ì€Ì̂̃̅̄}{20: 1 }{22:^x}{21: }|
{19: }{14: 2 }{22:y} |
{19: }{14: 3 }{22: } |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
@@ -1338,7 +1240,7 @@ describe('float window', function()
{19: }{15:y }|
{19: }{15: }|
{15: }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+ ]], float_pos={[4] = {1001, "NW", 1, 4, 10, true}}}
else
screen:expect([[
@@ -1353,41 +1255,29 @@ describe('float window', function()
end
command('sign unplace 1 buffer=1')
- local buf = meths.create_buf(false, true)
- meths.win_set_buf(win, buf)
+ local buf = api.nvim_create_buf(false, true)
+ api.nvim_win_set_buf(win, buf)
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
{19: }{20: 1 }{22:^x}{21: }|
{19: }{14: 2 }{22:y} |
{19: }{14: 3 }{22: } |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
- {15: }|
- {15: }|
- {15: }|
- {15: }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+ {15: }|*4
+ ]], float_pos={[4] = {1001, "NW", 1, 4, 10, true}}}
else
screen:expect([[
{19: }{20: 1 }{22:^x}{21: }|
{19: }{14: 2 }{22:y} |
{19: }{14: 3 }{22: } {15: } |
- {0:~ }{15: }{0: }|
- {0:~ }{15: }{0: }|
- {0:~ }{15: }{0: }|
+ {0:~ }{15: }{0: }|*3
|
]])
end
@@ -1399,42 +1289,33 @@ describe('float window', function()
command('set colorcolumn=1')
command('set cursorline')
command('set foldcolumn=1')
- command('hi NormalFloat guibg=#333333')
+ command('hi NormalFloat guibg=#333333 guifg=NONE')
feed('ix<cr>y<cr><esc>gg')
- local win = meths.open_win(0, false, {relative='editor', width=20, height=4, row=4, col=10, style='minimal'})
+ local win = api.nvim_open_win(0, false, {relative='editor', width=20, height=4, row=4, col=10, style='minimal'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
{19: }{20: 1 }{22:^x}{21: }|
{19: }{14: 2 }{22:y} |
{19: }{14: 3 }{22: } |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
{15:x }|
{15:y }|
- {15: }|
- {15: }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+ {15: }|*2
+ ]], float_pos={[4] = {1001, "NW", 1, 4, 10, true}}}
else
screen:expect{grid=[[
{19: }{20: 1 }{22:^x}{21: }|
{19: }{14: 2 }{22:y} |
{19: }{14: 3 }{22: } {15:x } |
{0:~ }{15:y }{0: }|
- {0:~ }{15: }{0: }|
- {0:~ }{15: }{0: }|
+ {0:~ }{15: }{0: }|*2
|
]]}
end
@@ -1445,20 +1326,13 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
{19: }{17:ðŒ¢Ì€Ì̂̃̅̄ðŒ¢Ì€Ì̂̃̅̄}{20: 1 }{22:^x}{21: }|
{19: }{14: 2 }{22:y} |
{19: }{14: 3 }{22: } |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
@@ -1466,7 +1340,7 @@ describe('float window', function()
{19: }{15:y }|
{19: }{15: }|
{15: }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+ ]], float_pos={[4] = {1001, "NW", 1, 4, 10, true}}}
else
screen:expect([[
@@ -1481,41 +1355,29 @@ describe('float window', function()
end
command('sign unplace 1 buffer=1')
- local buf = meths.create_buf(false, true)
- meths.win_set_buf(win, buf)
+ local buf = api.nvim_create_buf(false, true)
+ api.nvim_win_set_buf(win, buf)
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
{19: }{20: 1 }{22:^x}{21: }|
{19: }{14: 2 }{22:y} |
{19: }{14: 3 }{22: } |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
- {15: }|
- {15: }|
- {15: }|
- {15: }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+ {15: }|*4
+ ]], float_pos={[4] = {1001, "NW", 1, 4, 10, true}}}
else
screen:expect([[
{19: }{20: 1 }{22:^x}{21: }|
{19: }{14: 2 }{22:y} |
{19: }{14: 3 }{22: } {15: } |
- {0:~ }{15: }{0: }|
- {0:~ }{15: }{0: }|
- {0:~ }{15: }{0: }|
+ {0:~ }{15: }{0: }|*3
|
]])
end
@@ -1528,70 +1390,52 @@ describe('float window', function()
command('set cursorline')
command('set foldcolumn=1')
command('set statuscolumn=%l%s%C')
- command('hi NormalFloat guibg=#333333')
+ command('hi NormalFloat guibg=#333333 guifg=NONE')
feed('ix<cr>y<cr><esc>gg')
- meths.open_win(0, false, {relative='editor', width=20, height=4, row=4, col=10, style='minimal'})
+ api.nvim_open_win(0, false, {relative='editor', width=20, height=4, row=4, col=10, style='minimal'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
{20:1}{19: }{20: }{22:^x}{21: }|
{14:2}{19: }{14: }{22:y} |
{14:3}{19: }{14: }{22: } |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
{15:x }|
{15:y }|
- {15: }|
- {15: }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 4, 10, true}}}
+ {15: }|*2
+ ]], float_pos={[4] = {1001, "NW", 1, 4, 10, true}}}
else
screen:expect{grid=[[
{20:1}{19: }{20: }{22:^x}{21: }|
{14:2}{19: }{14: }{22:y} |
{14:3}{19: }{14: }{22: } {15:x } |
{0:~ }{15:y }{0: }|
- {0:~ }{15: }{0: }|
- {0:~ }{15: }{0: }|
+ {0:~ }{15: }{0: }|*2
|
]]}
end
end)
it('can have border', function()
- local buf = meths.create_buf(false, false)
- meths.buf_set_lines(buf, 0, -1, true, {' halloj! ',
+ local buf = api.nvim_create_buf(false, false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {' halloj! ',
' BORDAA '})
- local win = meths.open_win(buf, false, {relative='editor', width=9, height=2, row=2, col=5, border="double"})
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=9, height=2, row=2, col=5, border="double"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -1600,10 +1444,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -1617,24 +1461,15 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {border="single"})
+ api.nvim_win_set_config(win, {border="single"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -1643,10 +1478,10 @@ describe('float window', function()
{5:│}{1: BORDAA }{5:│}|
{5:└─────────┘}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -1660,24 +1495,15 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {border="rounded"})
+ api.nvim_win_set_config(win, {border="rounded"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -1686,10 +1512,10 @@ describe('float window', function()
{5:│}{1: BORDAA }{5:│}|
{5:╰─────────╯}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -1703,24 +1529,15 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {border="solid"})
+ api.nvim_win_set_config(win, {border="solid"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -1729,10 +1546,10 @@ describe('float window', function()
{5: }{1: BORDAA }{5: }|
{5: }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -1747,24 +1564,15 @@ describe('float window', function()
end
-- support: ascii char, UTF-8 char, composed char, highlight per char
- meths.win_set_config(win, {border={"x", {"å", "ErrorMsg"}, {"\\"}, {"n̈̊", "Search"}}})
+ api.nvim_win_set_config(win, {border={"x", {"å", "ErrorMsg"}, {"\\"}, {"n̈̊", "Search"}}})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -1773,10 +1581,10 @@ describe('float window', function()
{17:n̈̊}{1: BORDAA }{17:n̈̊}|
{5:\}{7:ååååååååå}{5:x}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -1790,34 +1598,25 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {border="none"})
+ api.nvim_win_set_config(win, {border="none"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{1: halloj! }|
{1: BORDAA }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -1825,40 +1624,30 @@ describe('float window', function()
{0:~ }|
{0:~ }{1: halloj! }{0: }|
{0:~ }{1: BORDAA }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]]}
end
- meths.win_set_config(win, {border={"", "", "", ">", "", "", "", "<"}})
+ api.nvim_win_set_config(win, {border={"", "", "", ">", "", "", "", "<"}})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{5:<}{1: halloj! }{5:>}|
{5:<}{1: BORDAA }{5:>}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -1866,30 +1655,20 @@ describe('float window', function()
{0:~ }|
{0:~ }{5:<}{1: halloj! }{5:>}{0: }|
{0:~ }{5:<}{1: BORDAA }{5:>}{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]]}
end
- meths.win_set_config(win, {border={"", "_", "", "", "", "-", "", ""}})
+ api.nvim_win_set_config(win, {border={"", "_", "", "", "", "-", "", ""}})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -1898,10 +1677,10 @@ describe('float window', function()
{1: BORDAA }|
{5:---------}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -1923,16 +1702,11 @@ describe('float window', function()
of border shadow
]]
- meths.win_set_config(win, {border="shadow"})
+ api.nvim_win_set_config(win, {border="shadow"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
neeed some dummy |
@@ -1948,10 +1722,10 @@ describe('float window', function()
{1: BORDAA }{26: }|
{25: }{26: }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 6, curline = 5, curcol = 0, linecount = 6, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 6, curline = 5, curcol = 0, linecount = 6, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -1967,13 +1741,13 @@ describe('float window', function()
end)
it('validates title title_pos', function()
- local buf = meths.create_buf(false,false)
+ local buf = api.nvim_create_buf(false,false)
eq("title requires border to be set",
- pcall_err(meths.open_win,buf, false, {
+ pcall_err(api.nvim_open_win,buf, false, {
relative='editor', width=9, height=2, row=2, col=5, title='Title',
}))
eq("title_pos requires title to be set",
- pcall_err(meths.open_win,buf, false, {
+ pcall_err(api.nvim_open_win,buf, false, {
relative='editor', width=9, height=2, row=2, col=5,
border='single', title_pos='left',
}))
@@ -2001,13 +1775,13 @@ describe('float window', function()
end)
it('validates footer footer_pos', function()
- local buf = meths.create_buf(false,false)
+ local buf = api.nvim_create_buf(false,false)
eq("footer requires border to be set",
- pcall_err(meths.open_win,buf, false, {
+ pcall_err(api.nvim_open_win,buf, false, {
relative='editor', width=9, height=2, row=2, col=5, footer='Footer',
}))
eq("footer_pos requires footer to be set",
- pcall_err(meths.open_win,buf, false, {
+ pcall_err(api.nvim_open_win,buf, false, {
relative='editor', width=9, height=2, row=2, col=5,
border='single', footer_pos='left',
}))
@@ -2035,10 +1809,10 @@ describe('float window', function()
end)
it('center aligned title longer than window width #25746', function()
- local buf = meths.create_buf(false, false)
- meths.buf_set_lines(buf, 0, -1, true, {' halloj! ',
+ local buf = api.nvim_create_buf(false, false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {' halloj! ',
' BORDAA '})
- local win = meths.open_win(buf, false, {
+ local win = api.nvim_open_win(buf, false, {
relative='editor', width=9, height=2, row=2, col=5, border="double",
title = "abcdefghijklmnopqrstuvwxyz",title_pos = "center",
})
@@ -2046,20 +1820,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2068,10 +1833,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2085,15 +1850,15 @@ describe('float window', function()
]]}
end
- meths.win_close(win, false)
+ api.nvim_win_close(win, false)
assert_alive()
end)
it('border with title', function()
- local buf = meths.create_buf(false, false)
- meths.buf_set_lines(buf, 0, -1, true, {' halloj! ',
+ local buf = api.nvim_create_buf(false, false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {' halloj! ',
' BORDAA '})
- local win = meths.open_win(buf, false, {
+ local win = api.nvim_open_win(buf, false, {
relative='editor', width=9, height=2, row=2, col=5, border="double",
title = "Left",title_pos = "left",
})
@@ -2101,20 +1866,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2123,10 +1879,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2140,24 +1896,15 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {title= "Center",title_pos="center"})
+ api.nvim_win_set_config(win, {title= "Center",title_pos="center"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2166,10 +1913,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2183,24 +1930,15 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {title= "Right",title_pos="right"})
+ api.nvim_win_set_config(win, {title= "Right",title_pos="right"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2209,10 +1947,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2226,24 +1964,15 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {title= { {"🦄"},{"BB"}},title_pos="right"})
+ api.nvim_win_set_config(win, {title= { {"🦄"},{"BB"}},title_pos="right"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2252,10 +1981,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2271,10 +2000,10 @@ describe('float window', function()
end)
it('border with footer', function()
- local buf = meths.create_buf(false, false)
- meths.buf_set_lines(buf, 0, -1, true, {' halloj! ',
+ local buf = api.nvim_create_buf(false, false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {' halloj! ',
' BORDAA '})
- local win = meths.open_win(buf, false, {
+ local win = api.nvim_open_win(buf, false, {
relative='editor', width=9, height=2, row=2, col=5, border="double",
footer = "Left",footer_pos = "left",
})
@@ -2282,20 +2011,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2304,10 +2024,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚}{11:Left}{5:â•â•â•â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2321,24 +2041,15 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {footer= "Center",footer_pos="center"})
+ api.nvim_win_set_config(win, {footer= "Center",footer_pos="center"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2347,10 +2058,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•}{11:Center}{5:â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2364,24 +2075,15 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {footer= "Right",footer_pos="right"})
+ api.nvim_win_set_config(win, {footer= "Right",footer_pos="right"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2390,10 +2092,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•}{11:Right}{5:â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2407,24 +2109,15 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {footer= { {"🦄"},{"BB"}},footer_pos="right"})
+ api.nvim_win_set_config(win, {footer= { {"🦄"},{"BB"}},footer_pos="right"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2433,10 +2126,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•}🦄BB{5:â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2452,10 +2145,10 @@ describe('float window', function()
end)
it('border with title and footer', function()
- local buf = meths.create_buf(false, false)
- meths.buf_set_lines(buf, 0, -1, true, {' halloj! ',
+ local buf = api.nvim_create_buf(false, false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {' halloj! ',
' BORDAA '})
- local win = meths.open_win(buf, false, {
+ local win = api.nvim_open_win(buf, false, {
relative='editor', width=9, height=2, row=2, col=5, border="double",
title = "Left", title_pos = "left", footer = "Right", footer_pos = "right",
})
@@ -2463,20 +2156,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2485,10 +2169,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•}{11:Right}{5:â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2502,24 +2186,15 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {title= "Center",title_pos="center",footer= "Center",footer_pos="center"})
+ api.nvim_win_set_config(win, {title= "Center",title_pos="center",footer= "Center",footer_pos="center"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2528,10 +2203,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•}{11:Center}{5:â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2545,24 +2220,15 @@ describe('float window', function()
]]}
end
- meths.win_set_config(win, {title= "Right",title_pos="right",footer= "Left",footer_pos="left"})
+ api.nvim_win_set_config(win, {title= "Right",title_pos="right",footer= "Left",footer_pos="left"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2571,10 +2237,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚}{11:Left}{5:â•â•â•â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2590,27 +2256,18 @@ describe('float window', function()
command('hi B0 guibg=Red guifg=Black')
command('hi B1 guifg=White')
- meths.win_set_config(win, {
+ api.nvim_win_set_config(win, {
title = {{"🦄"}, {"BB", {"B0", "B1"}}}, title_pos = "right",
footer= {{"🦄"}, {"BB", {"B0", "B1"}}}, footer_pos = "right",
})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -2619,10 +2276,10 @@ describe('float window', function()
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•}🦄{7:BB}{5:â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true }
+ [4] = { 1001, "NW", 1, 2, 5, true }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2638,51 +2295,34 @@ describe('float window', function()
end)
it('terminates border on edge of viewport when window extends past viewport', function()
- local buf = meths.create_buf(false, false)
- meths.open_win(buf, false, {relative='editor', width=40, height=7, row=0, col=0, border="single", zindex=201})
+ local buf = api.nvim_create_buf(false, false)
+ api.nvim_open_win(buf, false, {relative='editor', width=40, height=7, row=0, col=0, border="single", zindex=201})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{5:┌────────────────────────────────────────â”}|
{5:│}{1: }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
+ {5:│}{2:~ }{5:│}|*6
{5:└────────────────────────────────────────┘}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 0, 0, true, 201 }
+ [4] = { 1001, "NW", 1, 0, 0, true, 201 }
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
{5:^┌──────────────────────────────────────â”}|
{5:│}{1: }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
+ {5:│}{2:~ }{5:│}|*4
{5:└──────────────────────────────────────┘}|
]]}
end
@@ -2690,35 +2330,20 @@ describe('float window', function()
it('with border show popupmenu', function()
screen:try_resize(40,10)
- local buf = meths.create_buf(false, false)
- meths.buf_set_lines(buf, 0, -1, true, {'aaa aab ',
+ local buf = api.nvim_create_buf(false, false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'aaa aab ',
'abb acc ', ''})
- meths.open_win(buf, true, {relative='editor', width=9, height=3, row=0, col=5, border="double"})
+ api.nvim_open_win(buf, true, {relative='editor', width=9, height=3, row=0, col=5, border="double"})
feed 'G'
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*9
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
## grid 3
|
## grid 4
@@ -2728,10 +2353,10 @@ describe('float window', function()
{5:â•‘}{1:^ }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 0, 5, true };
+ [4] = { 1001, "NW", 1, 0, 5, true };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 2, curcol = 0, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 2, curcol = 0, linecount = 3, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2740,10 +2365,7 @@ describe('float window', function()
{0:~ }{5:â•‘}{1:abb acc }{5:â•‘}{0: }|
{0:~ }{5:â•‘}{1:^ }{5:â•‘}{0: }|
{0:~ }{5:╚â•â•â•â•â•â•â•â•â•â•}{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]]}
end
@@ -2752,26 +2374,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*9
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
## grid 3
{3:-- }{8:match 1 of 4} |
## grid 4
@@ -2786,11 +2393,11 @@ describe('float window', function()
{1: abb }|
{13: acc }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 0, 5, true, 50 };
- [5] = { { id = -1 }, "NW", 4, 4, 0, false, 100 };
+ [4] = { 1001, "NW", 1, 0, 5, true, 50 };
+ [5] = { -1, "NW", 4, 4, 0, false, 100 };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 2, curcol = 3, linecount=3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 2, curcol = 3, linecount=3, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2811,26 +2418,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*9
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
## grid 3
|
## grid 4
@@ -2840,10 +2432,10 @@ describe('float window', function()
{5:â•‘}{1:ac^c }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 0, 5, true };
+ [4] = { 1001, "NW", 1, 0, 5, true };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 2, curcol = 2, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 2, curcol = 2, linecount = 3, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2852,10 +2444,7 @@ describe('float window', function()
{0:~ }{5:â•‘}{1:abb acc }{5:â•‘}{0: }|
{0:~ }{5:â•‘}{1:ac^c }{5:â•‘}{0: }|
{0:~ }{5:╚â•â•â•â•â•â•â•â•â•â•}{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]]}
end
@@ -2869,26 +2458,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*9
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
## grid 3
:popup Test |
## grid 4
@@ -2902,11 +2476,11 @@ describe('float window', function()
{1: bar }|
{1: baz }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 0, 5, true };
- [5] = { { id = -1 }, "NW", 4, 4, 2, false, 250 };
+ [4] = { 1001, "NW", 1, 0, 5, true };
+ [5] = { -1, "NW", 4, 4, 2, false, 250 };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 2, curcol = 2, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 2, curcol = 2, linecount = 3, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -2917,8 +2491,7 @@ describe('float window', function()
{0:~ }{5:╚â•}{1: foo }{5:â•â•â•â•}{0: }|
{0:~ }{1: bar }{0: }|
{0:~ }{1: baz }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:popup Test |
]]}
end
@@ -2926,29 +2499,20 @@ describe('float window', function()
it('show ruler of current floating window', function()
command 'set ruler'
- local buf = meths.create_buf(false, false)
- meths.buf_set_lines(buf, 0, -1, true, {'aaa aab ',
+ local buf = api.nvim_create_buf(false, false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'aaa aab ',
'abb acc '})
- meths.open_win(buf, true, {relative='editor', width=9, height=3, row=0, col=5})
+ api.nvim_open_win(buf, true, {relative='editor', width=9, height=3, row=0, col=5})
feed 'gg'
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
1,1 All |
## grid 4
@@ -2956,19 +2520,17 @@ describe('float window', function()
{1:abb acc }|
{2:~ }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 0, 5, true, 50};
+ [4] = {1001, "NW", 1, 0, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
{1:^aaa aab } |
{0:~ }{1:abb acc }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
1,1 All |
]]}
end
@@ -2977,20 +2539,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
1,5 All |
## grid 4
@@ -2998,19 +2551,17 @@ describe('float window', function()
{1:abb acc }|
{2:~ }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 0, 5, true, 50};
+ [4] = {1001, "NW", 1, 0, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 0, curcol = 4, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 4, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
{1:aaa ^aab } |
{0:~ }{1:abb acc }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
1,5 All |
]]}
end
@@ -3018,44 +2569,31 @@ describe('float window', function()
it("correct ruler position in current float with 'rulerformat' set", function()
command 'set ruler rulerformat=fish:<><'
- meths.open_win(0, true, {relative='editor', width=9, height=3, row=0, col=5})
+ api.nvim_open_win(0, true, {relative='editor', width=9, height=3, row=0, col=5})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
fish:<>< |
## grid 4
{1:^ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 0, 5, true, 50};
+ [4] = {1001, "NW", 1, 0, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
{1:^ } |
- {0:~ }{2:~ }{0: }|
- {0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }{2:~ }{0: }|*2
+ {0:~ }|*3
fish:<>< |
]]}
end
@@ -3064,60 +2602,40 @@ describe('float window', function()
it('does not show ruler of not-last current float during ins-completion', function()
screen:try_resize(50,9)
command 'set ruler showmode'
- meths.open_win(0, false, {relative='editor', width=3, height=3, row=0, col=0})
- meths.open_win(0, false, {relative='editor', width=3, height=3, row=0, col=5})
+ api.nvim_open_win(0, false, {relative='editor', width=3, height=3, row=0, col=0})
+ api.nvim_open_win(0, false, {relative='editor', width=3, height=3, row=0, col=5})
feed '<c-w>w'
- neq('', meths.win_get_config(0).relative)
- neq(funcs.winnr '$', funcs.winnr())
+ neq('', api.nvim_win_get_config(0).relative)
+ neq(fn.winnr '$', fn.winnr())
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*8
[3:--------------------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
## grid 3
0,0-1 All |
## grid 4
{1: }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
## grid 5
{1:^ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
]], float_pos={
- [5] = {{id = 1002}, "NW", 1, 0, 5, true, 50};
- [4] = {{id = 1001}, "NW", 1, 0, 0, true, 50};
+ [5] = {1002, "NW", 1, 0, 5, true, 50};
+ [4] = {1001, "NW", 1, 0, 0, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
{1: } {1:^ } |
- {2:~ }{0: }{2:~ }{0: }|
- {2:~ }{0: }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {2:~ }{0: }{2:~ }{0: }|*2
+ {0:~ }|*5
0,0-1 All |
]]}
end
@@ -3125,52 +2643,32 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*8
[3:--------------------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
## grid 3
{3:-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)} |
## grid 4
{1: }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
## grid 5
{1:^ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
]], float_pos={
- [5] = {{id = 1002}, "NW", 1, 0, 5, true, 50};
- [4] = {{id = 1001}, "NW", 1, 0, 0, true, 50};
+ [5] = {1002, "NW", 1, 0, 5, true, 50};
+ [4] = {1001, "NW", 1, 0, 0, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
{1: } {1:^ } |
- {2:~ }{0: }{2:~ }{0: }|
- {2:~ }{0: }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {2:~ }{0: }{2:~ }{0: }|*2
+ {0:~ }|*5
{3:-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)} |
]]}
end
@@ -3178,111 +2676,72 @@ describe('float window', function()
it('can have minimum size', function()
insert("the background text")
- local buf = meths.create_buf(false, true)
- meths.buf_set_lines(buf, 0, -1, true, {'x'})
- local win = meths.open_win(buf, false, {relative='win', width=1, height=1, row=0, col=4, focusable=false})
+ local buf = api.nvim_create_buf(false, true)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'x'})
+ local win = api.nvim_open_win(buf, false, {relative='win', width=1, height=1, row=0, col=4, focusable=false})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
the background tex^t |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{1:x}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 2, 0, 4, false}
+ [4] = {1001, "NW", 2, 0, 4, false}
}}
else
screen:expect([[
the {1:x}ackground tex^t |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end
- meths.win_set_config(win, {relative='win', row=0, col=15})
+ api.nvim_win_set_config(win, {relative='win', row=0, col=15})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
the background tex^t |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{1:x}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 2, 0, 15, false}
+ [4] = {1001, "NW", 2, 0, 15, false}
}}
else
screen:expect([[
the background {1:x}ex^t |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end
- meths.win_close(win,false)
+ api.nvim_win_close(win,false)
if multigrid then
screen:expect([[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
the background tex^t |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
]])
else
screen:expect([[
the background tex^t |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end
@@ -3303,23 +2762,19 @@ describe('float window', function()
command('sargument 6')
local float_opts = { relative = 'editor', row = 6, col = 0, width = 40, height = 1 }
- meths.win_set_config(w3, float_opts)
- meths.win_set_config(w4, float_opts)
+ api.nvim_win_set_config(w3, float_opts)
+ api.nvim_win_set_config(w4, float_opts)
command('wincmd =')
if multigrid then
screen:expect{grid=[[
## grid 1
- [8:----------------------------------------]|
- [8:----------------------------------------]|
+ [8:----------------------------------------]|*2
{4:X6 }|
- [7:----------------------------------------]|
- [7:----------------------------------------]|
+ [7:----------------------------------------]|*2
{5:X5 }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*2
{5:X2 }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:X1 }|
[3:----------------------------------------]|
## grid 2
@@ -3341,15 +2796,15 @@ describe('float window', function()
^ |
{0:~ }|
]], float_pos={
- [5] = {{id = 1002}, "NW", 1, 6, 0, true, 50};
- [6] = {{id = 1003}, "NW", 1, 6, 0, true, 50};
+ [5] = {1002, "NW", 1, 6, 0, true, 50};
+ [6] = {1003, "NW", 1, 6, 0, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [6] = {win = {id = 1003}, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [7] = {win = {id = 1004}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [8] = {win = {id = 1005}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [6] = {win = 1003, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [7] = {win = 1004, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [8] = {win = 1005, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -3401,12 +2856,12 @@ describe('float window', function()
## grid 10
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [7] = {win = {id = 1004}, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [8] = {win = {id = 1005}, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [9] = {win = {id = 1006}, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [10] = {win = {id = 1007}, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [7] = {win = 1004, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [8] = {win = 1005, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [9] = {win = 1006, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [10] = {win = 1007, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -3437,47 +2892,47 @@ describe('float window', function()
end)
it('API has proper error messages', function()
- local buf = meths.create_buf(false,false)
+ local buf = api.nvim_create_buf(false,false)
eq("Invalid key: 'bork'",
- pcall_err(meths.open_win,buf, false, {width=20,height=2,bork=true}))
- eq("'win' key is only valid with relative='win'",
- pcall_err(meths.open_win,buf, false, {width=20,height=2,relative='editor',row=0,col=0,win=0}))
+ pcall_err(api.nvim_open_win, buf, false, {width=20,height=2,bork=true}))
+ eq("'win' key is only valid with relative='win' and relative=''",
+ pcall_err(api.nvim_open_win, buf, false, {width=20,height=2,relative='editor',row=0,col=0,win=0}))
+ eq("floating windows cannot have 'vertical'",
+ pcall_err(api.nvim_open_win, buf, false, {width=20,height=2,relative='editor',row=0,col=0,vertical=true}))
+ eq("floating windows cannot have 'split'",
+ pcall_err(api.nvim_open_win, buf, false, {width=20,height=2,relative='editor',row=0,col=0,split="left"}))
eq("Only one of 'relative' and 'external' must be used",
- pcall_err(meths.open_win,buf, false, {width=20,height=2,relative='editor',row=0,col=0,external=true}))
+ pcall_err(api.nvim_open_win, buf, false, {width=20,height=2,relative='editor',row=0,col=0,external=true}))
eq("Invalid value of 'relative' key",
- pcall_err(meths.open_win,buf, false, {width=20,height=2,relative='shell',row=0,col=0}))
+ pcall_err(api.nvim_open_win, buf, false, {width=20,height=2,relative='shell',row=0,col=0}))
eq("Invalid value of 'anchor' key",
- pcall_err(meths.open_win,buf, false, {width=20,height=2,relative='editor',row=0,col=0,anchor='bottom'}))
+ pcall_err(api.nvim_open_win, buf, false, {width=20,height=2,relative='editor',row=0,col=0,anchor='bottom'}))
eq("'relative' requires 'row'/'col' or 'bufpos'",
- pcall_err(meths.open_win,buf, false, {width=20,height=2,relative='editor'}))
+ pcall_err(api.nvim_open_win, buf, false, {width=20,height=2,relative='editor'}))
eq("'width' key must be a positive Integer",
- pcall_err(meths.open_win,buf, false, {width=-1,height=2,relative='editor', row=0, col=0}))
+ pcall_err(api.nvim_open_win, buf, false, {width=-1,height=2,relative='editor', row=0, col=0}))
eq("'height' key must be a positive Integer",
- pcall_err(meths.open_win,buf, false, {width=20,height=-1,relative='editor', row=0, col=0}))
+ pcall_err(api.nvim_open_win, buf, false, {width=20,height=-1,relative='editor', row=0, col=0}))
eq("'height' key must be a positive Integer",
- pcall_err(meths.open_win,buf, false, {width=20,height=0,relative='editor', row=0, col=0}))
+ pcall_err(api.nvim_open_win, buf, false, {width=20,height=0,relative='editor', row=0, col=0}))
eq("Must specify 'width'",
- pcall_err(meths.open_win,buf, false, {relative='editor', row=0, col=0}))
+ pcall_err(api.nvim_open_win, buf, false, {relative='editor', row=0, col=0}))
eq("Must specify 'height'",
- pcall_err(meths.open_win,buf, false, {relative='editor', row=0, col=0, width=2}))
+ pcall_err(api.nvim_open_win, buf, false, {relative='editor', row=0, col=0, width=2}))
end)
it('can be placed relative window or cursor', function()
screen:try_resize(40,9)
- meths.buf_set_lines(0, 0, -1, true, {'just some', 'example text'})
+ api.nvim_buf_set_lines(0, 0, -1, true, {'just some', 'example text'})
feed('gge')
- local oldwin = meths.get_current_win()
+ local oldwin = api.nvim_get_current_win()
command('below split')
if multigrid then
screen:expect([[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*3
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*3
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -3505,19 +2960,15 @@ describe('float window', function()
]])
end
- local buf = meths.create_buf(false,false)
+ local buf = api.nvim_create_buf(false,false)
-- no 'win' arg, relative default window
- local win = meths.open_win(buf, false, {relative='win', width=20, height=2, row=0, col=10})
+ local win = api.nvim_open_win(buf, false, {relative='win', width=20, height=2, row=0, col=10})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*3
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*3
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -3534,7 +2985,7 @@ describe('float window', function()
{1: }|
{2:~ }|
]], float_pos={
- [5] = {{id = 1002}, "NW", 4, 0, 10, true}
+ [5] = {1002, "NW", 4, 0, 10, true}
}}
else
screen:expect([[
@@ -3550,17 +3001,13 @@ describe('float window', function()
]])
end
- meths.win_set_config(win, {relative='cursor', row=1, col=-2})
+ api.nvim_win_set_config(win, {relative='cursor', row=1, col=-2})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*3
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*3
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -3577,7 +3024,7 @@ describe('float window', function()
{1: }|
{2:~ }|
]], float_pos={
- [5] = {{id = 1002}, "NW", 4, 1, 1, true}
+ [5] = {1002, "NW", 4, 1, 1, true}
}}
else
screen:expect([[
@@ -3593,17 +3040,13 @@ describe('float window', function()
]])
end
- meths.win_set_config(win, {relative='cursor', row=0, col=0, anchor='SW'})
+ api.nvim_win_set_config(win, {relative='cursor', row=0, col=0, anchor='SW'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*3
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*3
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -3620,7 +3063,7 @@ describe('float window', function()
{1: }|
{2:~ }|
]], float_pos={
- [5] = {{id = 1002}, "SW", 4, 0, 3, true}
+ [5] = {1002, "SW", 4, 0, 3, true}
}}
else
screen:expect([[
@@ -3636,17 +3079,13 @@ describe('float window', function()
]])
end
- meths.win_set_config(win, {relative='win', win=oldwin, row=1, col=10, anchor='NW'})
+ api.nvim_win_set_config(win, {relative='win', win=oldwin, row=1, col=10, anchor='NW'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*3
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*3
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -3663,7 +3102,7 @@ describe('float window', function()
{1: }|
{2:~ }|
]], float_pos={
- [5] = {{id = 1002}, "NW", 2, 1, 10, true}
+ [5] = {1002, "NW", 2, 1, 10, true}
}}
else
screen:expect([[
@@ -3679,17 +3118,13 @@ describe('float window', function()
]])
end
- meths.win_set_config(win, {relative='win', win=oldwin, row=3, col=39, anchor='SE'})
+ api.nvim_win_set_config(win, {relative='win', win=oldwin, row=3, col=39, anchor='SE'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*3
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*3
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -3706,7 +3141,7 @@ describe('float window', function()
{1: }|
{2:~ }|
]], float_pos={
- [5] = {{id = 1002}, "SE", 2, 3, 39, true}
+ [5] = {1002, "SE", 2, 3, 39, true}
}}
else
screen:expect([[
@@ -3722,17 +3157,13 @@ describe('float window', function()
]])
end
- meths.win_set_config(win, {relative='win', win=0, row=0, col=50, anchor='NE'})
+ api.nvim_win_set_config(win, {relative='win', win=0, row=0, col=50, anchor='NE'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*3
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*3
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -3749,7 +3180,7 @@ describe('float window', function()
{1: }|
{2:~ }|
]], float_pos={
- [5] = {{id = 1002}, "NE", 4, 0, 50, true}
+ [5] = {1002, "NE", 4, 0, 50, true}
}, win_viewport = {
[2] = {
topline = 0,
@@ -3758,7 +3189,7 @@ describe('float window', function()
curcol = 3,
linecount = 2,
sum_scroll_delta = 0,
- win = { id = 1000 },
+ win = 1000,
},
[4] = {
topline = 0,
@@ -3767,7 +3198,7 @@ describe('float window', function()
curcol = 3,
linecount = 2,
sum_scroll_delta = 0,
- win = { id = 1001 }
+ win = 1001
},
[5] = {
topline = 0,
@@ -3776,7 +3207,7 @@ describe('float window', function()
curcol = 0,
linecount = 1,
sum_scroll_delta = 0,
- win = { id = 1002 }
+ win = 1002
}
}}
else
@@ -3796,108 +3227,78 @@ describe('float window', function()
it('always anchor to corner including border', function()
screen:try_resize(40,13)
- meths.buf_set_lines(0, 0, -1, true, {'just some example text', 'some more example text'})
+ api.nvim_buf_set_lines(0, 0, -1, true, {'just some example text', 'some more example text'})
feed('ggeee')
command('below split')
if multigrid then
screen:expect([[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*5
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*5
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
just some example text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
just some exampl^e text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
]])
else
screen:expect([[
just some example text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{5:[No Name] [+] }|
just some exampl^e text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{4:[No Name] [+] }|
|
]])
end
- local buf = meths.create_buf(false, false)
- meths.buf_set_lines(buf, 0, -1, true, {' halloj! ',
+ local buf = api.nvim_create_buf(false, false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {' halloj! ',
' BORDAA '})
- local win = meths.open_win(buf, false, {relative='cursor', width=9, height=2, row=1, col=-2, border="double"})
+ local win = api.nvim_open_win(buf, false, {relative='cursor', width=9, height=2, row=1, col=-2, border="double"})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*5
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*5
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
just some example text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
just some exampl^e text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 5
{5:â•”â•â•â•â•â•â•â•â•â•â•—}|
{5:â•‘}{1: halloj! }{5:â•‘}|
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [5] = {{id = 1002}, "NW", 4, 1, 14, true}
+ [5] = {1002, "NW", 4, 1, 14, true}
}}
else
screen:expect([[
just some example text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{5:[No Name] [+] }|
just some exampl^e text |
some more exam{5:â•”â•â•â•â•â•â•â•â•â•â•—} |
@@ -3909,52 +3310,38 @@ describe('float window', function()
]])
end
- meths.win_set_config(win, {relative='cursor', row=0, col=-2, anchor='NE'})
+ api.nvim_win_set_config(win, {relative='cursor', row=0, col=-2, anchor='NE'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*5
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*5
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
just some example text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
just some exampl^e text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 5
{5:â•”â•â•â•â•â•â•â•â•â•â•—}|
{5:â•‘}{1: halloj! }{5:â•‘}|
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [5] = {{id = 1002}, "NE", 4, 0, 14, true}
+ [5] = {1002, "NE", 4, 0, 14, true}
}}
else
screen:expect([[
just some example text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{5:[No Name] [+] }|
jus{5:â•”â•â•â•â•â•â•â•â•â•â•—}pl^e text |
som{5:â•‘}{1: halloj! }{5:â•‘}ple text |
@@ -3966,44 +3353,32 @@ describe('float window', function()
]])
end
- meths.win_set_config(win, {relative='cursor', row=1, col=-2, anchor='SE'})
+ api.nvim_win_set_config(win, {relative='cursor', row=1, col=-2, anchor='SE'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*5
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*5
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
just some example text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
just some exampl^e text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 5
{5:â•”â•â•â•â•â•â•â•â•â•â•—}|
{5:â•‘}{1: halloj! }{5:â•‘}|
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [5] = {{id = 1002}, "SE", 4, 1, 14, true}
+ [5] = {1002, "SE", 4, 1, 14, true}
}}
else
screen:expect([[
@@ -4015,52 +3390,38 @@ describe('float window', function()
{5:[Noâ•‘}{1: BORDAA }{5:â•‘ }|
jus{5:╚â•â•â•â•â•â•â•â•â•â•}pl^e text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{4:[No Name] [+] }|
|
]])
end
- meths.win_set_config(win, {relative='cursor', row=0, col=-2, anchor='SW'})
+ api.nvim_win_set_config(win, {relative='cursor', row=0, col=-2, anchor='SW'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*5
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*5
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
just some example text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
just some exampl^e text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 5
{5:â•”â•â•â•â•â•â•â•â•â•â•—}|
{5:â•‘}{1: halloj! }{5:â•‘}|
{5:â•‘}{1: BORDAA }{5:â•‘}|
{5:╚â•â•â•â•â•â•â•â•â•â•}|
]], float_pos={
- [5] = {{id = 1002}, "SW", 4, 0, 14, true}
+ [5] = {1002, "SW", 4, 0, 14, true}
}}
else
screen:expect([[
@@ -4072,9 +3433,7 @@ describe('float window', function()
{5:[No Name] [+] ╚â•â•â•â•â•â•â•â•â•â• }|
just some exampl^e text |
some more example text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{4:[No Name] [+] }|
|
]])
@@ -4121,20 +3480,12 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
- |
- |
- |
+ |*3
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
## grid 3
|
## grid 5
@@ -4154,14 +3505,14 @@ describe('float window', function()
## grid 12
{1:8 }|
]], float_pos={
- [5] = {{id = 1002}, "NW", 1, 1, 10, true, 50};
- [6] = {{id = 1003}, "NW", 1, 1, 30, true, 50};
- [7] = {{id = 1004}, "NE", 5, 1, 0, true, 50};
- [8] = {{id = 1005}, "NE", 6, 1, 0, true, 50};
- [9] = {{id = 1006}, "SE", 7, 0, 0, true, 50};
- [10] = {{id = 1007}, "SE", 8, 0, 0, true, 50};
- [11] = {{id = 1008}, "SW", 9, 0, 5, true, 50};
- [12] = {{id = 1009}, "SW", 10, 0, 5, true, 50};
+ [5] = {1002, "NW", 1, 1, 10, true, 50};
+ [6] = {1003, "NW", 1, 1, 30, true, 50};
+ [7] = {1004, "NE", 5, 1, 0, true, 50};
+ [8] = {1005, "NE", 6, 1, 0, true, 50};
+ [9] = {1006, "SE", 7, 0, 0, true, 50};
+ [10] = {1007, "SE", 8, 0, 0, true, 50};
+ [11] = {1008, "SW", 9, 0, 5, true, 50};
+ [12] = {1009, "SW", 10, 0, 5, true, 50};
}}
else
screen:expect([[
@@ -4169,8 +3520,7 @@ describe('float window', function()
{1:5 } {1:1 } {1:6 } {1:2 } |
{1:3 } {1:4 } |
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -4197,20 +3547,12 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
- |
- |
- |
+ |*3
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
## grid 3
|
## grid 5
@@ -4230,14 +3572,14 @@ describe('float window', function()
## grid 12
{1:8 }|
]], float_pos={
- [5] = {{id = 1002}, "NE", 8, 1, 0, true, 50};
- [6] = {{id = 1003}, "NE", 12, 1, 0, true, 50};
- [7] = {{id = 1004}, "SE", 5, 0, 0, true, 50};
- [8] = {{id = 1005}, "NW", 1, 1, 30, true, 50};
- [9] = {{id = 1006}, "SW", 10, 0, 5, true, 50};
- [10] = {{id = 1007}, "SE", 6, 0, 0, true, 50};
- [11] = {{id = 1008}, "SW", 7, 0, 5, true, 50};
- [12] = {{id = 1009}, "NW", 1, 1, 10, true, 50};
+ [5] = {1002, "NE", 8, 1, 0, true, 50};
+ [6] = {1003, "NE", 12, 1, 0, true, 50};
+ [7] = {1004, "SE", 5, 0, 0, true, 50};
+ [8] = {1005, "NW", 1, 1, 30, true, 50};
+ [9] = {1006, "SW", 10, 0, 5, true, 50};
+ [10] = {1007, "SE", 6, 0, 0, true, 50};
+ [11] = {1008, "SW", 7, 0, 5, true, 50};
+ [12] = {1009, "NW", 1, 1, 10, true, 50};
}}
else
screen:expect([[
@@ -4245,8 +3587,7 @@ describe('float window', function()
{1:6 } {1:8 } {1:3 } {1:4 } |
{1:2 } {1:1 } |
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -4275,15 +3616,12 @@ describe('float window', function()
it('can be placed relative text in a window', function()
screen:try_resize(30,5)
- local firstwin = meths.get_current_win().id
- meths.buf_set_lines(0, 0, -1, true, {'just some', 'example text that is wider than the window', '', '', 'more text'})
+ local firstwin = api.nvim_get_current_win()
+ api.nvim_buf_set_lines(0, 0, -1, true, {'just some', 'example text that is wider than the window', '', '', 'more text'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
+ [2:------------------------------]|*4
[3:------------------------------]|
## grid 2
^just some |
@@ -4298,22 +3636,18 @@ describe('float window', function()
^just some |
example text that is wider tha|
n the window |
- |
- |
+ |*2
]]}
end
- local buf = meths.create_buf(false,false)
- meths.buf_set_lines(buf, 0, -1, true, {'some info!'})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'some info!'})
- local win = meths.open_win(buf, false, {relative='win', width=12, height=1, bufpos={1,32}})
+ local win = api.nvim_open_win(buf, false, {relative='win', width=12, height=1, bufpos={1,32}})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
+ [2:------------------------------]|*4
[3:------------------------------]|
## grid 2
^just some |
@@ -4325,7 +3659,7 @@ describe('float window', function()
## grid 4
{1:some info! }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 2, 3, 2, true }
+ [4] = { 1001, "NW", 2, 3, 2, true }
}}
else
screen:expect{grid=[[
@@ -4337,36 +3671,31 @@ describe('float window', function()
]]}
end
eq({relative='win', width=12, height=1, bufpos={1,32}, anchor='NW', hide=false,
- external=false, col=0, row=1, win=firstwin, focusable=true, zindex=50}, meths.win_get_config(win))
+ external=false, col=0, row=1, win=firstwin, focusable=true, zindex=50}, api.nvim_win_get_config(win))
feed('<c-e>')
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
+ [2:------------------------------]|*4
[3:------------------------------]|
## grid 2
^example text that is wider tha|
n the window |
- |
- |
+ |*2
## grid 3
|
## grid 4
{1:some info! }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 2, 2, 2, true },
+ [4] = { 1001, "NW", 2, 2, 2, true },
}}
else
screen:expect{grid=[[
^example text that is wider tha|
n the window |
{1:some info! } |
- |
- |
+ |*2
]]}
end
@@ -4375,22 +3704,18 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*4
[3:---------------------------------------------]|
## grid 2
^example text that is wider than the window |
- |
- |
+ |*2
more text |
## grid 3
|
## grid 4
{1:some info! }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 2, 1, 32, true }
+ [4] = { 1001, "NW", 2, 1, 32, true }
}}
else
-- note: appears misaligned due to cursor
@@ -4407,32 +3732,20 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
+ [2:-------------------------]|*9
[3:-------------------------]|
## grid 2
^example text that is wide|
r than the window |
- |
- |
+ |*2
more text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
{1:some info! }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 2, 2, 7, true }
+ [4] = { 1001, "NW", 2, 2, 7, true }
}}
else
screen:expect{grid=[[
@@ -4441,56 +3754,37 @@ describe('float window', function()
{1:some info! } |
|
more text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]]}
end
- meths.win_set_config(win, {relative='win', bufpos={1,32}, anchor='SW'})
+ api.nvim_win_set_config(win, {relative='win', bufpos={1,32}, anchor='SW'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
+ [2:-------------------------]|*9
[3:-------------------------]|
## grid 2
^example text that is wide|
r than the window |
- |
- |
+ |*2
more text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
{1:some info! }|
]], float_pos={
- [4] = { { id = 1001 }, "SW", 2, 1, 7, true }
+ [4] = { 1001, "SW", 2, 1, 7, true }
}}
else
screen:expect{grid=[[
^example{1:some info! }s wide|
r than the window |
- |
- |
+ |*2
more text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]]}
end
@@ -4500,15 +3794,7 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----]{5:│}[5:--------------------]|
- [2:----]{5:│}[5:--------------------]|
- [2:----]{5:│}[5:--------------------]|
- [2:----]{5:│}[5:--------------------]|
- [2:----]{5:│}[5:--------------------]|
- [2:----]{5:│}[5:--------------------]|
- [2:----]{5:│}[5:--------------------]|
- [2:----]{5:│}[5:--------------------]|
- [2:----]{5:│}[5:--------------------]|
+ [2:----]{5:│}[5:--------------------]|*9
[3:-------------------------]|
## grid 2
exam|
@@ -4526,16 +3812,9 @@ describe('float window', function()
{1:some info! }|
## grid 5
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
]], float_pos={
- [4] = { { id = 1001 }, "SW", 2, 8, 0, true }
+ [4] = { 1001, "SW", 2, 8, 0, true }
}}
else
screen:expect{grid=[[
@@ -4553,36 +3832,24 @@ describe('float window', function()
end
command('close')
- meths.win_set_config(win, {relative='win', bufpos={1,32}, anchor='NW', col=-2})
+ api.nvim_win_set_config(win, {relative='win', bufpos={1,32}, anchor='NW', col=-2})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
+ [2:-------------------------]|*9
[3:-------------------------]|
## grid 2
^example text that is wide|
r than the window |
- |
- |
+ |*2
more text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
{1:some info! }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 2, 2, 5, true }
+ [4] = { 1001, "NW", 2, 2, 5, true }
}}
else
screen:expect{grid=[[
@@ -4591,44 +3858,29 @@ describe('float window', function()
{1:some info! } |
|
more text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]]}
end
- meths.win_set_config(win, {relative='win', bufpos={1,32}, row=2})
+ api.nvim_win_set_config(win, {relative='win', bufpos={1,32}, row=2})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
+ [2:-------------------------]|*9
[3:-------------------------]|
## grid 2
^example text that is wide|
r than the window |
- |
- |
+ |*2
more text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
{1:some info! }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 2, 3, 7, true }
+ [4] = { 1001, "NW", 2, 3, 7, true }
}}
else
screen:expect{grid=[[
@@ -4637,10 +3889,7 @@ describe('float window', function()
|
{1:some info! } |
more text |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]]}
end
@@ -4649,44 +3898,24 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
+ [2:-------------------------]|*9
[3:-------------------------]|
## grid 2
{28:^+-- 5 lines: just some··}|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
## grid 3
|
## grid 4
{1:some info! }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 2, 2, 0, true }
+ [4] = { 1001, "NW", 2, 2, 0, true }
}}
else
screen:expect{grid=[[
{28:^+-- 5 lines: just some··}|
{0:~ }|
{1:some info! }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
|
]]}
end
@@ -4699,57 +3928,44 @@ describe('float window', function()
if multigrid then
screen:expect([[
## grid 1
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
+ [2:------------------------------]|*4
[3:------------------------------]|
## grid 2
that is wider than the windo^w |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
]])
else
screen:expect([[
that is wider than the windo^w |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
end
- local buf = meths.create_buf(false,true)
- meths.buf_set_lines(buf, 0, -1, true, {'some floaty text'})
- meths.open_win(buf, false, {relative='editor', width=20, height=1, row=3, col=1})
+ local buf = api.nvim_create_buf(false,true)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'some floaty text'})
+ api.nvim_open_win(buf, false, {relative='editor', width=20, height=1, row=3, col=1})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
+ [2:------------------------------]|*4
[3:------------------------------]|
## grid 2
that is wider than the windo^w |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
{1:some floaty text }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 3, 1, true}
+ [4] = {1001, "NW", 1, 3, 1, true}
}}
else
screen:expect([[
that is wider than the windo^w |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{0:~}{1:some floaty text }{0: }|
|
]])
@@ -4763,19 +3979,15 @@ describe('float window', function()
local screen2 = Screen.new(40,7)
screen2:attach(nil, session2)
screen2:set_default_attr_ids(attrs)
- local buf = meths.create_buf(false,false)
- meths.open_win(buf, true, {relative='editor', width=20, height=2, row=2, col=5})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_open_win(buf, true, {relative='editor', width=20, height=2, row=2, col=5})
local expected_pos = {
- [2]={{id=1001}, 'NW', 1, 2, 5}
+ [2]={1001, 'NW', 1, 2, 5}
}
screen:expect{grid=[[
## grid 1
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
## grid 2
{1:^ }|
@@ -4786,8 +3998,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^ }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
@@ -4795,29 +4006,20 @@ describe('float window', function()
it('handles resized screen', function()
- local buf = meths.create_buf(false,false)
- meths.buf_set_lines(buf, 0, -1, true, {'such', 'very', 'float'})
- local win = meths.open_win(buf, false, {relative='editor', width=15, height=4, row=2, col=10})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'such', 'very', 'float'})
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=15, height=4, row=2, col=10})
local expected_pos = {
- [4]={{id=1001}, 'NW', 1, 2, 10, true},
+ [4]={1001, 'NW', 1, 2, 10, true},
}
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -4842,16 +4044,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*4
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 3
|
## grid 4
@@ -4874,14 +4071,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*3
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
## grid 3
|
## grid 4
@@ -4903,8 +4097,7 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
[3:----------------------------------------]|
## grid 2
^ |
@@ -4928,8 +4121,7 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
[3:----------------------------------------]|
## grid 2
|
@@ -4954,20 +4146,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -4988,25 +4171,16 @@ describe('float window', function()
]])
end
- meths.win_set_config(win, {height=3})
+ api.nvim_win_set_config(win, {height=3})
feed('gg')
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -5030,20 +4204,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:--------------------------]|
- [2:--------------------------]|
- [2:--------------------------]|
- [2:--------------------------]|
- [2:--------------------------]|
- [2:--------------------------]|
+ [2:--------------------------]|*6
[3:--------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -5067,20 +4232,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
+ [2:-------------------------]|*6
[3:-------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -5104,20 +4260,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:------------------------]|
- [2:------------------------]|
- [2:------------------------]|
- [2:------------------------]|
- [2:------------------------]|
- [2:------------------------]|
+ [2:------------------------]|*6
[3:------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -5141,20 +4288,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------]|
- [2:----------------]|
- [2:----------------]|
- [2:----------------]|
- [2:----------------]|
- [2:----------------]|
+ [2:----------------]|*6
[3:----------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -5178,20 +4316,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:---------------]|
- [2:---------------]|
- [2:---------------]|
- [2:---------------]|
- [2:---------------]|
- [2:---------------]|
+ [2:---------------]|*6
[3:---------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -5215,20 +4344,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:--------------]|
- [2:--------------]|
- [2:--------------]|
- [2:--------------]|
- [2:--------------]|
- [2:--------------]|
+ [2:--------------]|*6
[3:--------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -5252,20 +4372,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:------------]|
- [2:------------]|
- [2:------------]|
- [2:------------]|
- [2:------------]|
- [2:------------]|
+ [2:------------]|*6
[3:------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -5312,20 +4423,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -5348,14 +4450,14 @@ describe('float window', function()
it('does not crash with inccommand #9379', function()
local expected_pos = {
- [4]={{id=1001}, 'NW', 1, 2, 0, true},
+ [4]={1001, 'NW', 1, 2, 0, true},
}
command("set inccommand=split")
command("set laststatus=2")
- local buf = meths.create_buf(false,false)
- meths.open_win(buf, true, {relative='editor', width=30, height=3, row=2, col=0})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_open_win(buf, true, {relative='editor', width=30, height=3, row=2, col=0})
insert([[
foo
@@ -5365,19 +4467,12 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*5
{5:[No Name] }|
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
@@ -5402,11 +4497,7 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*5
{5:[Preview] }|
[3:----------------------------------------]|
## grid 2
@@ -5435,19 +4526,12 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*5
{5:[No Name] }|
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
@@ -5469,52 +4553,39 @@ describe('float window', function()
end)
it('does not crash when set cmdheight #9680', function()
- local buf = meths.create_buf(false,false)
- meths.open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
command("set cmdheight=2")
- eq(1, meths.eval('1'))
+ eq(1, api.nvim_eval('1'))
end)
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}).id
- meths.set_option_value('winhl', 'Normal:ErrorMsg', {win=win})
+ local buf = api.nvim_create_buf(false,false)
+ local win = api.nvim_open_win(buf, true, {relative='editor', width=12, height=4, row=2, col=5})
+ api.nvim_set_option_value('winhl', 'Normal:ErrorMsg', {win=win})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{7:^ }|
- {12:~ }|
- {12:~ }|
- {12:~ }|
+ {12:~ }|*3
]], float_pos={
- [4] = {{ id = 1001 }, "NW", 1, 2, 5, true},
+ [4] = {1001, "NW", 1, 2, 5, true},
}}
else
screen:expect([[
|
{0:~ }|
{0:~ }{7:^ }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
+ {0:~ }{12:~ }{0: }|*3
|
]])
end
@@ -5522,38 +4593,27 @@ describe('float window', function()
it('with builtin popupmenu', function()
feed('ix ')
- funcs.complete(3, {'aa', 'word', 'longtext'})
+ fn.complete(3, {'aa', 'word', 'longtext'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 4
{7:x aa^ }|
- {12:~ }|
- {12:~ }|
- {12:~ }|
+ {12:~ }|*3
## grid 5
{13: aa }|
{1: word }|
{1: longtext }|
]], float_pos={
- [4] = {{ id = 1001 }, "NW", 1, 2, 5, true, 50},
- [5] = {{ id = -1 }, "NW", 4, 1, 1, false, 100}
+ [4] = {1001, "NW", 1, 2, 5, true, 50},
+ [5] = {-1, "NW", 4, 1, 1, false, 100}
}}
else
screen:expect([[
@@ -5571,29 +4631,18 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{7:x a^a }|
- {12:~ }|
- {12:~ }|
- {12:~ }|
+ {12:~ }|*3
]], float_pos={
- [4] = {{ id = 1001 }, "NW", 1, 2, 5, true},
+ [4] = {1001, "NW", 1, 2, 5, true},
}}
else
@@ -5601,46 +4650,33 @@ describe('float window', function()
|
{0:~ }|
{0:~ }{7:x a^a }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
+ {0:~ }{12:~ }{0: }|*3
|
]])
end
feed('<c-w>wi')
- funcs.complete(1, {'xx', 'yy', 'zz'})
+ fn.complete(1, {'xx', 'yy', 'zz'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
xx^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 4
{7:x aa }|
- {12:~ }|
- {12:~ }|
- {12:~ }|
+ {12:~ }|*3
## grid 5
{13:xx }|
{1:yy }|
{1:zz }|
]], float_pos={
- [4] = {{ id = 1001 }, "NW", 1, 2, 5, true, 50},
- [5] = {{ id = -1 }, "NW", 2, 1, 0, false, 100}
+ [4] = {1001, "NW", 1, 2, 5, true, 50},
+ [5] = {-1, "NW", 2, 1, 0, false, 100}
}}
else
screen:expect([[
@@ -5648,8 +4684,7 @@ describe('float window', function()
{13:xx }{0: }|
{1:yy }{7: }{0: }|
{1:zz }{12: }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
+ {0:~ }{12:~ }{0: }|*2
{3:-- INSERT --} |
]])
end
@@ -5658,38 +4693,25 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
xx^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 4
{7:x aa }|
- {12:~ }|
- {12:~ }|
- {12:~ }|
+ {12:~ }|*3
]], float_pos={
- [4] = {{ id = 1001 }, "NW", 1, 2, 5, true},
+ [4] = {1001, "NW", 1, 2, 5, true},
}}
else
screen:expect([[
xx^ |
{0:~ }|
{0:~ }{7:x aa }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
+ {0:~ }{12:~ }{0: }|*3
{3:-- INSERT --} |
]])
end
@@ -5701,33 +4723,22 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
:sign un^ |
## grid 4
{7: }|
- {12:~ }|
- {12:~ }|
- {12:~ }|
+ {12:~ }|*3
## grid 5
{1: undefine }|
{1: unplace }|
]], float_pos={
- [5] = {{id = -1}, "SW", 1, 6, 5, false, 250};
- [4] = {{id = 1001}, "NW", 1, 2, 5, true, 50};
+ [5] = {-1, "SW", 1, 6, 5, false, 250};
+ [4] = {1001, "NW", 1, 2, 5, true, 50};
}}
else
screen:expect{grid=[[
@@ -5745,34 +4756,23 @@ describe('float window', function()
it('with ext_popupmenu', function()
screen:set_option('ext_popupmenu', true)
feed('ix ')
- funcs.complete(3, {'aa', 'word', 'longtext'})
+ fn.complete(3, {'aa', 'word', 'longtext'})
local items = {{"aa", "", "", ""}, {"word", "", "", ""}, {"longtext", "", "", ""}}
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 4
{7:x aa^ }|
- {12:~ }|
- {12:~ }|
- {12:~ }|
+ {12:~ }|*3
]], float_pos={
- [4] = {{ id = 1001 }, "NW", 1, 2, 5, true},
+ [4] = {1001, "NW", 1, 2, 5, true},
}, popupmenu={
anchor = {4, 0, 2}, items = items, pos = 0
}}
@@ -5781,9 +4781,7 @@ describe('float window', function()
|
{0:~ }|
{0:~ }{7:x aa^ }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
+ {0:~ }{12:~ }{0: }|*3
{3:-- INSERT --} |
]], popupmenu={
anchor = {1, 2, 7}, items = items, pos = 0
@@ -5794,71 +4792,47 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{7:x a^a }|
- {12:~ }|
- {12:~ }|
- {12:~ }|
+ {12:~ }|*3
]], float_pos={
- [4] = {{ id = 1001 }, "NW", 1, 2, 5, true},
+ [4] = {1001, "NW", 1, 2, 5, true},
}}
else
screen:expect([[
|
{0:~ }|
{0:~ }{7:x a^a }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
+ {0:~ }{12:~ }{0: }|*3
|
]])
end
feed('<c-w>wi')
- funcs.complete(1, {'xx', 'yy', 'zz'})
+ fn.complete(1, {'xx', 'yy', 'zz'})
items = {{"xx", "", "", ""}, {"yy", "", "", ""}, {"zz", "", "", ""}}
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
xx^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 4
{7:x aa }|
- {12:~ }|
- {12:~ }|
- {12:~ }|
+ {12:~ }|*3
]], float_pos={
- [4] = {{ id = 1001 }, "NW", 1, 2, 5, true},
+ [4] = {1001, "NW", 1, 2, 5, true},
}, popupmenu={
anchor = {2, 0, 0}, items = items, pos = 0
}}
@@ -5867,9 +4841,7 @@ describe('float window', function()
xx^ |
{0:~ }|
{0:~ }{7:x aa }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
+ {0:~ }{12:~ }{0: }|*3
{3:-- INSERT --} |
]], popupmenu={
anchor = {1, 0, 0}, items = items, pos = 0
@@ -5880,38 +4852,25 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
xx^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 4
{7:x aa }|
- {12:~ }|
- {12:~ }|
- {12:~ }|
+ {12:~ }|*3
]], float_pos={
- [4] = {{ id = 1001 }, "NW", 1, 2, 5, true},
+ [4] = {1001, "NW", 1, 2, 5, true},
}}
else
screen:expect([[
xx^ |
{0:~ }|
{0:~ }{7:x aa }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
- {0:~ }{12:~ }{0: }|
+ {0:~ }{12:~ }{0: }|*3
{3:-- INSERT --} |
]])
end
@@ -5921,26 +4880,17 @@ describe('float window', function()
describe('float shown after pum', function()
local win
before_each(function()
- command('hi NormalFloat guibg=#333333')
+ command('hi NormalFloat guibg=#333333 guifg=NONE')
feed('i')
- funcs.complete(1, {'aa', 'word', 'longtext'})
+ fn.complete(1, {'aa', 'word', 'longtext'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
aa^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 4
@@ -5948,7 +4898,7 @@ describe('float window', function()
{1:word }|
{1:longtext }|
]], float_pos={
- [4] = {{id = -1}, "NW", 2, 1, 0, false, 100}}
+ [4] = {-1, "NW", 2, 1, 0, false, 100}}
}
else
screen:expect([[
@@ -5956,32 +4906,22 @@ describe('float window', function()
{13:aa }{0: }|
{1:word }{0: }|
{1:longtext }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- INSERT --} |
]])
end
- local buf = meths.create_buf(false,true)
- meths.buf_set_lines(buf,0,-1,true,{"some info", "about item"})
- win = meths.open_win(buf, false, {relative='cursor', width=12, height=2, row=1, col=10})
+ local buf = api.nvim_create_buf(false,true)
+ api.nvim_buf_set_lines(buf,0,-1,true,{"some info", "about item"})
+ win = api.nvim_open_win(buf, false, {relative='cursor', width=12, height=2, row=1, col=10})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
aa^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 4
@@ -5992,8 +4932,8 @@ describe('float window', function()
{15:some info }|
{15:about item }|
]], float_pos={
- [4] = {{id = -1}, "NW", 2, 1, 0, false, 100},
- [5] = {{id = 1001}, "NW", 2, 1, 12, true, 50},
+ [4] = {-1, "NW", 2, 1, 0, false, 100},
+ [5] = {1001, "NW", 2, 1, 12, true, 50},
}}
else
screen:expect([[
@@ -6001,8 +4941,7 @@ describe('float window', function()
{13:aa }{15:e info }{0: }|
{1:word }{15:ut item }{0: }|
{1:longtext }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- INSERT --} |
]])
end
@@ -6013,93 +4952,60 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
aa^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 5
{15:some info }|
{15:about item }|
]], float_pos={
- [5] = {{id = 1001}, "NW", 2, 1, 12, true},
+ [5] = {1001, "NW", 2, 1, 12, true},
}}
else
screen:expect([[
aa^ |
{0:~ }{15:some info }{0: }|
{0:~ }{15:about item }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:-- INSERT --} |
]])
end
- meths.win_close(win, false)
+ api.nvim_win_close(win, false)
if multigrid then
screen:expect([[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
aa^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
]])
else
screen:expect([[
aa^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- INSERT --} |
]])
end
end)
it('and close float first', function()
- meths.win_close(win, false)
+ api.nvim_win_close(win, false)
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
aa^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 4
@@ -6107,7 +5013,7 @@ describe('float window', function()
{1:word }|
{1:longtext }|
]], float_pos={
- [4] = {{id = -1}, "NW", 2, 1, 0, false, 100},
+ [4] = {-1, "NW", 2, 1, 0, false, 100},
}}
else
screen:expect([[
@@ -6115,8 +5021,7 @@ describe('float window', function()
{13:aa }{0: }|
{1:word }{0: }|
{1:longtext }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- INSERT --} |
]])
end
@@ -6125,31 +5030,18 @@ describe('float window', function()
if multigrid then
screen:expect([[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
aa^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
]])
else
screen:expect([[
aa^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{3:-- INSERT --} |
]])
end
@@ -6157,38 +5049,29 @@ describe('float window', function()
end)
it("can use Normal as background", function()
- local buf = meths.create_buf(false,false)
- meths.buf_set_lines(buf,0,-1,true,{"here", "float"})
- local win = meths.open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
- meths.set_option_value('winhl', 'Normal:Normal', {win=win})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_buf_set_lines(buf,0,-1,true,{"here", "float"})
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
+ api.nvim_set_option_value('winhl', 'Normal:Normal', {win=win})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
here |
float |
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 2, 5, true, 50};
+ [4] = {1001, "NW", 1, 2, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -6196,8 +5079,7 @@ describe('float window', function()
{0:~ }|
{0:~ }here {0: }|
{0:~ }float {0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]]}
end
@@ -6210,30 +5092,21 @@ describe('float window', function()
-- the default, but be explicit:
command("set laststatus=1")
command("set hidden")
- meths.buf_set_lines(0,0,-1,true,{"x"})
- local buf = meths.create_buf(false,false)
- win = meths.open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
- meths.buf_set_lines(buf,0,-1,true,{"y"})
+ api.nvim_buf_set_lines(0,0,-1,true,{"x"})
+ local buf = api.nvim_create_buf(false,false)
+ win = api.nvim_open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
+ api.nvim_buf_set_lines(buf,0,-1,true,{"y"})
expected_pos = {
- [4]={{id=1001}, 'NW', 1, 2, 5, true}
+ [4]={1001, 'NW', 1, 2, 5, true}
}
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6246,8 +5119,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -6258,20 +5130,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6284,8 +5147,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -6294,20 +5156,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6320,34 +5173,24 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
end)
it("w with focusable=false", function()
- meths.win_set_config(win, {focusable=false})
+ api.nvim_win_set_config(win, {focusable=false})
expected_pos[4][6] = false
feed("<c-w>wi") -- i to provoke redraw
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 4
@@ -6360,8 +5203,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- INSERT --} |
]])
end
@@ -6370,20 +5212,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6396,8 +5229,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -6408,20 +5240,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6434,8 +5257,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -6444,20 +5266,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6470,8 +5283,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -6479,23 +5291,14 @@ describe('float window', function()
it("focus by mouse", function()
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6503,36 +5306,26 @@ describe('float window', function()
{2:~ }|
]], float_pos=expected_pos}
else
- meths.input_mouse('left', 'press', '', 0, 2, 5)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
screen:expect([[
x |
{0:~ }|
{0:~ }{1:^y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 2, 0, 0)
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6540,41 +5333,32 @@ describe('float window', function()
{2:~ }|
]], float_pos=expected_pos}
else
- meths.input_mouse('left', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
^x |
{0:~ }|
{0:~ }{1:y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
end)
it("focus by mouse (focusable=false)", function()
- meths.win_set_config(win, {focusable=false})
- meths.buf_set_lines(0, -1, -1, true, {"a"})
+ api.nvim_win_set_config(win, {focusable=false})
+ api.nvim_buf_set_lines(0, -1, -1, true, {"a"})
expected_pos[4][6] = false
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
a |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
@@ -6582,36 +5366,27 @@ describe('float window', function()
{2:~ }|
]], float_pos=expected_pos}
else
- meths.input_mouse('left', 'press', '', 0, 2, 5)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
screen:expect([[
x |
^a |
{0:~ }{1:y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 2, 0, 0)
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
a |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
@@ -6619,14 +5394,13 @@ describe('float window', function()
{2:~ }|
]], float_pos=expected_pos, unchanged=true}
else
- meths.input_mouse('left', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
^x |
a |
{0:~ }{1:y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -6637,20 +5411,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- INSERT --} |
## grid 4
@@ -6663,8 +5428,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- INSERT --} |
]])
end
@@ -6673,20 +5437,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6699,8 +5454,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -6709,20 +5463,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6735,8 +5480,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -6748,20 +5492,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6774,8 +5509,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -6784,34 +5518,23 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{1:^y }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
]], float_pos=expected_pos}
else
screen:expect([[
x |
{0:~ }|
{0:~ }{1:^y }{0: }|
- {0:~ }{2:~ }{0: }|
- {0:~ }{2:~ }{0: }|
+ {0:~ }{2:~ }{0: }|*2
{0:~ }|
|
]])
@@ -6821,20 +5544,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6845,9 +5559,7 @@ describe('float window', function()
x |
{0:~ }|
{0:~ }{1:^y }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
end
@@ -6856,36 +5568,23 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{1:^y }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
]], float_pos=expected_pos}
else
screen:expect([[
x |
{0:~ }|
{0:~ }{1:^y }{0: }|
- {0:~ }{2:~ }{0: }|
- {0:~ }{2:~ }{0: }|
- {0:~ }{2:~ }{0: }|
+ {0:~ }{2:~ }{0: }|*3
|
]])
end
@@ -6894,38 +5593,21 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{1:^y }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*5
]], float_pos=expected_pos}
else
screen:expect([[
x {1:^y } |
- {0:~ }{2:~ }{0: }|
- {0:~ }{2:~ }{0: }|
- {0:~ }{2:~ }{0: }|
- {0:~ }{2:~ }{0: }|
- {0:~ }{2:~ }{0: }|
+ {0:~ }{2:~ }{0: }|*5
|
]])
end
@@ -6936,20 +5618,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6962,8 +5635,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -6972,20 +5644,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -6998,8 +5661,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -7008,20 +5670,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -7034,8 +5687,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -7044,20 +5696,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -7070,8 +5713,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -7080,20 +5722,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -7106,8 +5739,7 @@ describe('float window', function()
{0:~ }|
{1:^y }|
{2:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -7118,11 +5750,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{4:[No Name] [+] }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7153,11 +5783,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{5:[No Name] [+] }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7188,11 +5816,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{5:[No Name] [+] }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7224,11 +5850,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{4:[No Name] [+] }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7261,11 +5885,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{4:[No Name] [+] }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7296,11 +5918,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{5:[No Name] [+] }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7331,11 +5951,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{5:[No Name] [+] }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7368,11 +5986,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{4:[No Name] }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7405,11 +6021,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{4:[No Name] }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7442,19 +6056,12 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
+ [5:--------------------]{5:│}[2:-------------------]|*5
{4:[No Name] [+] }{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
@@ -7462,10 +6069,7 @@ describe('float window', function()
{2:~ }|
## grid 5
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
]], float_pos=expected_pos}
else
screen:expect([[
@@ -7485,19 +6089,12 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
+ [5:--------------------]{5:│}[2:-------------------]|*5
{4:[No Name] }{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
:vnew |
## grid 4
@@ -7505,10 +6102,7 @@ describe('float window', function()
{2:~ }|
## grid 5
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
]], float_pos=expected_pos}
else
screen:expect([[
@@ -7528,19 +6122,12 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
- [5:--------------------]{5:│}[2:-------------------]|
+ [5:--------------------]{5:│}[2:-------------------]|*5
{4:[No Name] }{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
:vnew |
## grid 4
@@ -7548,10 +6135,7 @@ describe('float window', function()
{2:~ }|
## grid 5
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
]], float_pos=expected_pos}
else
screen:expect([[
@@ -7592,24 +6176,15 @@ describe('float window', function()
-- enter first float
feed('<c-w><c-w>')
-- enter second float
- meths.open_win(0, true, {relative='editor', width=20, height=2, row=4, col=8})
+ api.nvim_open_win(0, true, {relative='editor', width=20, height=2, row=4, col=8})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -7619,8 +6194,8 @@ describe('float window', function()
{1:^y }|
{2:~ }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 2, 5, true},
- [5] = {{id = 1002}, "NW", 1, 4, 8, true}
+ [4] = {1001, "NW", 1, 2, 5, true},
+ [5] = {1002, "NW", 1, 4, 8, true}
}}
else
screen:expect([[
@@ -7638,27 +6213,18 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
:quit |
## grid 4
{1:^y }|
{2:~ }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 2, 5, true},
+ [4] = {1001, "NW", 1, 2, 5, true},
}}
else
screen:expect([[
@@ -7666,8 +6232,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:quit |
]])
end
@@ -7676,31 +6241,18 @@ describe('float window', function()
if multigrid then
screen:expect([[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
:quit |
]])
else
screen:expect([[
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
:quit |
]])
end
@@ -7713,31 +6265,18 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
]]}
else
screen:expect([[
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end
@@ -7748,20 +6287,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [3:----------------------------------------]|
- [3:----------------------------------------]|
- [3:----------------------------------------]|
+ [2:----------------------------------------]|*4
+ [3:----------------------------------------]|*3
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{7:E5601: Cannot close window, only floatin}|
{7:g window would remain} |
@@ -7787,20 +6317,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -7813,8 +6334,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{1:^y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
@@ -7825,11 +6345,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{4:[No Name] [+] }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7860,31 +6378,18 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 3
|
## grid 5
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
]]}
else
screen:expect([[
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end
@@ -7895,11 +6400,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{5:[No Name] [+] }|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7930,13 +6433,10 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*2
{5:[No Name] [+] }|
[2:----------------------------------------]|
- [3:----------------------------------------]|
- [3:----------------------------------------]|
- [3:----------------------------------------]|
+ [3:----------------------------------------]|*3
## grid 2
x |
{0:~ }|
@@ -7969,11 +6469,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*2
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -7998,23 +6496,16 @@ describe('float window', function()
end
if multigrid then
- meths.win_set_config(0, {external=true, width=30, height=2})
+ api.nvim_win_set_config(0, {external=true, width=30, height=2})
expected_pos = {[4]={external=true}}
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*5
{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
@@ -8023,7 +6514,7 @@ describe('float window', function()
]], float_pos=expected_pos}
else
eq("UI doesn't support external windows",
- pcall_err(meths.win_set_config, 0, {external=true, width=30, height=2}))
+ pcall_err(api.nvim_win_set_config, 0, {external=true, width=30, height=2}))
return
end
@@ -8031,11 +6522,9 @@ describe('float window', function()
if multigrid then
screen:expect([[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*2
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -8051,24 +6540,15 @@ describe('float window', function()
end)
it('J (float with border)', function()
- meths.win_set_config(win, {relative='editor', width=20, height=2, row=2, col=5, border='single'})
+ api.nvim_win_set_config(win, {relative='editor', width=20, height=2, row=2, col=5, border='single'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -8093,11 +6573,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*2
{5:[No Name] [+] }|
- [4:----------------------------------------]|
- [4:----------------------------------------]|
+ [4:----------------------------------------]|*2
{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -8128,11 +6606,9 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [6:--------------------]{5:│}[5:-------------------]|
- [6:--------------------]{5:│}[5:-------------------]|
+ [6:--------------------]{5:│}[5:-------------------]|*2
{5:[No Name] [+] [No Name] [+] }|
- [7:--------------------]{5:│}[2:-------------------]|
- [7:--------------------]{5:│}[2:-------------------]|
+ [7:--------------------]{5:│}[2:-------------------]|*2
{4:[No Name] [+] }{5:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -8169,17 +6645,15 @@ describe('float window', function()
for i = 1,5 do
feed(i.."<c-w>w")
feed_command("enew")
- curbufmeths.set_lines(0,-1,true,{tostring(i)})
+ api.nvim_buf_set_lines(0, 0,-1,true,{tostring(i)})
end
if multigrid then
screen:expect{grid=[[
## grid 1
- [6:-------------------]{5:│}[5:--------------------]|
- [6:-------------------]{5:│}[5:--------------------]|
+ [6:-------------------]{5:│}[5:--------------------]|*2
{5:[No Name] [+] [No Name] [+] }|
- [7:-------------------]{5:│}[2:--------------------]|
- [7:-------------------]{5:│}[2:--------------------]|
+ [7:-------------------]{5:│}[2:--------------------]|*2
{5:[No Name] [+] [No Name] [+] }|
[3:----------------------------------------]|
## grid 2
@@ -8227,7 +6701,7 @@ describe('float window', function()
for i = 1,5 do
feed(i.."<c-w>w")
feed('<c-w>'..k)
- local nr = funcs.winnr()
+ local nr = fn.winnr()
eq(v[i],nr, "when using <c-w>"..k.." from window "..i)
end
end
@@ -8238,7 +6712,7 @@ describe('float window', function()
if j ~= i then
feed(j.."<c-w>w")
feed('<c-w>p')
- local nr = funcs.winnr()
+ local nr = fn.winnr()
eq(i,nr, "when using <c-w>p to window "..i.." from window "..j)
end
end
@@ -8253,19 +6727,11 @@ describe('float window', function()
screen:expect{grid=[[
## grid 1
{9: }{10:2}{9:+ [No Name] }{3: [No Name] }{5: }{9:X}|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*5
[3:----------------------------------------]|
## grid 2 (hidden)
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
:tabnew |
## grid 4 (hidden)
@@ -8273,19 +6739,13 @@ describe('float window', function()
{2:~ }|
## grid 5
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
]]}
else
screen:expect([[
{9: }{10:2}{9:+ [No Name] }{3: [No Name] }{5: }{9:X}|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
:tabnew |
]])
end
@@ -8295,18 +6755,11 @@ describe('float window', function()
screen:expect{grid=[[
## grid 1
{3: }{11:2}{3:+ [No Name] }{9: [No Name] }{5: }{9:X}|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*5
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
:tabnext |
## grid 4
@@ -8314,10 +6767,7 @@ describe('float window', function()
{2:~ }|
## grid 5 (hidden)
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
]], float_pos=expected_pos}
else
screen:expect([[
@@ -8325,8 +6775,7 @@ describe('float window', function()
^x |
{0:~ }{1:y }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:tabnext |
]])
end
@@ -8336,18 +6785,11 @@ describe('float window', function()
screen:expect{grid=[[
## grid 1
{9: }{10:2}{9:+ [No Name] }{3: [No Name] }{5: }{9:X}|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*5
[3:----------------------------------------]|
## grid 2 (hidden)
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
:tabnext |
## grid 4 (hidden)
@@ -8355,19 +6797,13 @@ describe('float window', function()
{2:~ }|
## grid 5
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
]]}
else
screen:expect([[
{9: }{10:2}{9:+ [No Name] }{3: [No Name] }{5: }{9:X}|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
:tabnext |
]])
end
@@ -8376,42 +6812,29 @@ describe('float window', function()
it(":tabnew and :tabnext (external)", function()
if multigrid then
-- also test external window wider than main screen
- meths.win_set_config(win, {external=true, width=65, height=4})
+ api.nvim_win_set_config(win, {external=true, width=65, height=4})
expected_pos = {[4]={external=true}}
feed(":tabnew<cr>")
screen:expect{grid=[[
## grid 1
{9: + [No Name] }{3: }{11:2}{3:+ [No Name] }{5: }{9:X}|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*5
[3:----------------------------------------]|
## grid 2 (hidden)
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
:tabnew |
## grid 4
y |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 5
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
]], float_pos=expected_pos}
else
eq("UI doesn't support external windows",
- pcall_err(meths.win_set_config, 0, {external=true, width=65, height=4}))
+ pcall_err(api.nvim_win_set_config, 0, {external=true, width=65, height=4}))
end
feed(":tabnext<cr>")
@@ -8419,31 +6842,19 @@ describe('float window', function()
screen:expect{grid=[[
## grid 1
{3: }{11:2}{3:+ [No Name] }{9: [No Name] }{5: }{9:X}|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*5
[3:----------------------------------------]|
## grid 2
^x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
:tabnext |
## grid 4
y |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 5 (hidden)
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
]], float_pos=expected_pos}
end
@@ -8452,57 +6863,36 @@ describe('float window', function()
screen:expect{grid=[[
## grid 1
{9: + [No Name] }{3: }{11:2}{3:+ [No Name] }{5: }{9:X}|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
- [5:----------------------------------------]|
+ [5:----------------------------------------]|*5
[3:----------------------------------------]|
## grid 2 (hidden)
x |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
:tabnext |
## grid 4
y |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
## grid 5
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
]], float_pos=expected_pos}
end
end)
end)
it("left drag changes visual selection in float window", function()
- local buf = meths.create_buf(false,false)
- meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'})
- meths.open_win(buf, false, {relative='editor', width=20, height=3, row=2, col=5})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'})
+ api.nvim_open_win(buf, false, {relative='editor', width=20, height=3, row=2, col=5})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -8510,29 +6900,20 @@ describe('float window', function()
{1:bar }|
{1:baz }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 2, 5, true, 50};
+ [4] = {1001, "NW", 1, 2, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
}}
- meths.input_mouse('left', 'press', '', 4, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -8540,29 +6921,20 @@ describe('float window', function()
{1:bar }|
{1:baz }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 2, 5, true, 50};
+ [4] = {1001, "NW", 1, 2, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
}}
- meths.input_mouse('left', 'drag', '', 4, 1, 2)
+ api.nvim_input_mouse('left', 'drag', '', 4, 1, 2)
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- VISUAL --} |
## grid 4
@@ -8570,10 +6942,10 @@ describe('float window', function()
{27:ba}{1:^r }|
{1:baz }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 2, 5, true, 50};
+ [4] = {1001, "NW", 1, 2, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -8586,7 +6958,7 @@ describe('float window', function()
|
]]}
- meths.input_mouse('left', 'press', '', 0, 2, 5)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
screen:expect{grid=[[
|
{0:~ }|
@@ -8597,7 +6969,7 @@ describe('float window', function()
|
]]}
- meths.input_mouse('left', 'drag', '', 0, 3, 7)
+ api.nvim_input_mouse('left', 'drag', '', 0, 3, 7)
screen:expect{grid=[[
|
{0:~ }|
@@ -8611,26 +6983,17 @@ describe('float window', function()
end)
it("left drag changes visual selection in float window with border", function()
- local buf = meths.create_buf(false,false)
- meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'})
- meths.open_win(buf, false, {relative='editor', width=20, height=3, row=0, col=5, border='single'})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'})
+ api.nvim_open_win(buf, false, {relative='editor', width=20, height=3, row=0, col=5, border='single'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -8640,29 +7003,20 @@ describe('float window', function()
{5:│}{1:baz }{5:│}|
{5:└────────────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 0, 5, true, 50};
+ [4] = {1001, "NW", 1, 0, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
}}
- meths.input_mouse('left', 'press', '', 4, 1, 1)
+ api.nvim_input_mouse('left', 'press', '', 4, 1, 1)
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -8672,29 +7026,20 @@ describe('float window', function()
{5:│}{1:baz }{5:│}|
{5:└────────────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 0, 5, true, 50};
+ [4] = {1001, "NW", 1, 0, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
}}
- meths.input_mouse('left', 'drag', '', 4, 2, 3)
+ api.nvim_input_mouse('left', 'drag', '', 4, 2, 3)
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- VISUAL --} |
## grid 4
@@ -8704,10 +7049,10 @@ describe('float window', function()
{5:│}{1:baz }{5:│}|
{5:└────────────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 0, 5, true, 50};
+ [4] = {1001, "NW", 1, 0, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -8720,7 +7065,7 @@ describe('float window', function()
|
]]}
- meths.input_mouse('left', 'press', '', 0, 1, 6)
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 6)
screen:expect{grid=[[
{5:┌────────────────────â”} |
{0:~ }{5:│}{1:^foo }{5:│}{0: }|
@@ -8731,7 +7076,7 @@ describe('float window', function()
|
]]}
- meths.input_mouse('left', 'drag', '', 0, 2, 8)
+ api.nvim_input_mouse('left', 'drag', '', 0, 2, 8)
screen:expect{grid=[[
{5:┌────────────────────â”} |
{0:~ }{5:│}{27:foo}{1: }{5:│}{0: }|
@@ -8745,27 +7090,18 @@ describe('float window', function()
end)
it("left drag changes visual selection in float window with winbar", 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.set_option_value('winbar', 'floaty bar', {win=float_win.id})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'})
+ local float_win = api.nvim_open_win(buf, false, {relative='editor', width=20, height=4, row=1, col=5})
+ api.nvim_set_option_value('winbar', 'floaty bar', {win=float_win})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -8774,29 +7110,20 @@ describe('float window', function()
{1:bar }|
{1:baz }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 5, true, 50};
+ [4] = {1001, "NW", 1, 1, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
}}
- meths.input_mouse('left', 'press', '', 4, 1, 0)
+ api.nvim_input_mouse('left', 'press', '', 4, 1, 0)
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -8805,29 +7132,20 @@ describe('float window', function()
{1:bar }|
{1:baz }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 5, true, 50};
+ [4] = {1001, "NW", 1, 1, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
}}
- meths.input_mouse('left', 'drag', '', 4, 2, 2)
+ api.nvim_input_mouse('left', 'drag', '', 4, 2, 2)
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
{3:-- VISUAL --} |
## grid 4
@@ -8836,10 +7154,10 @@ describe('float window', function()
{27:ba}{1:^r }|
{1:baz }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 5, true, 50};
+ [4] = {1001, "NW", 1, 1, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 3, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -8852,7 +7170,7 @@ describe('float window', function()
|
]]}
- meths.input_mouse('left', 'press', '', 0, 2, 5)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 5)
screen:expect{grid=[[
|
{0:~ }{3:floaty bar }{0: }|
@@ -8863,7 +7181,7 @@ describe('float window', function()
|
]]}
- meths.input_mouse('left', 'drag', '', 0, 3, 7)
+ api.nvim_input_mouse('left', 'drag', '', 0, 3, 7)
screen:expect{grid=[[
|
{0:~ }{3:floaty bar }{0: }|
@@ -8877,116 +7195,89 @@ describe('float window', function()
end)
it('left drag changes visual selection if float window is turned into a split', function()
- local buf = meths.create_buf(false,false)
- meths.buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'})
- meths.open_win(buf, true, {relative='editor', width=20, height=3, row=2, col=5})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'foo', 'bar', 'baz'})
+ api.nvim_open_win(buf, true, {relative='editor', width=20, height=3, row=2, col=5})
command('wincmd L')
if multigrid then
screen:expect([[
## grid 1
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
+ [2:-------------------]{5:│}[4:--------------------]|*5
{5:[No Name] }{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
^foo |
bar |
baz |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
]])
- meths.input_mouse('left', 'press', '', 4, 2, 2)
+ api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
screen:expect([[
## grid 1
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
+ [2:-------------------]{5:│}[4:--------------------]|*5
{5:[No Name] }{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
foo |
bar |
ba^z |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
]])
- meths.input_mouse('left', 'drag', '', 4, 1, 1)
+ api.nvim_input_mouse('left', 'drag', '', 4, 1, 1)
screen:expect([[
## grid 1
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
- [2:-------------------]{5:│}[4:--------------------]|
+ [2:-------------------]{5:│}[4:--------------------]|*5
{5:[No Name] }{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
{3:-- VISUAL --} |
## grid 4
foo |
b^a{27:r} |
{27:baz} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
]])
else
screen:expect([[
{5:│}^foo |
{0:~ }{5:│}bar |
{0:~ }{5:│}baz |
- {0:~ }{5:│}{0:~ }|
- {0:~ }{5:│}{0:~ }|
+ {0:~ }{5:│}{0:~ }|*2
{5:[No Name] }{4:[No Name] [+] }|
|
]])
- meths.input_mouse('left', 'press', '', 0, 2, 22)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 22)
screen:expect([[
{5:│}foo |
{0:~ }{5:│}bar |
{0:~ }{5:│}ba^z |
- {0:~ }{5:│}{0:~ }|
- {0:~ }{5:│}{0:~ }|
+ {0:~ }{5:│}{0:~ }|*2
{5:[No Name] }{4:[No Name] [+] }|
|
]])
- meths.input_mouse('left', 'drag', '', 0, 1, 21)
+ api.nvim_input_mouse('left', 'drag', '', 0, 1, 21)
screen:expect([[
{5:│}foo |
{0:~ }{5:│}b^a{27:r} |
{0:~ }{5:│}{27:baz} |
- {0:~ }{5:│}{0:~ }|
- {0:~ }{5:│}{0:~ }|
+ {0:~ }{5:│}{0:~ }|*2
{5:[No Name] }{4:[No Name] [+] }|
{3:-- VISUAL --} |
]])
@@ -8994,46 +7285,33 @@ describe('float window', function()
end)
it('left click sets correct curswant in float window with border', function()
- local buf = meths.create_buf(false,false)
- meths.buf_set_lines(buf, 0, -1, true, {'', '', ''})
- meths.open_win(buf, false, {relative='editor', width=20, height=3, row=0, col=5, border='single'})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'', '', ''})
+ api.nvim_open_win(buf, false, {relative='editor', width=20, height=3, row=0, col=5, border='single'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{5:┌────────────────────â”}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
+ {5:│}{1: }{5:│}|*3
{5:└────────────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 0, 5, true, 50};
+ [4] = {1001, "NW", 1, 0, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
^ {5:┌────────────────────â”} |
- {0:~ }{5:│}{1: }{5:│}{0: }|
- {0:~ }{5:│}{1: }{5:│}{0: }|
- {0:~ }{5:│}{1: }{5:│}{0: }|
+ {0:~ }{5:│}{1: }{5:│}{0: }|*3
{0:~ }{5:└────────────────────┘}{0: }|
{0:~ }|
|
@@ -9041,45 +7319,36 @@ describe('float window', function()
end
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 3, 1)
+ api.nvim_input_mouse('left', 'press', '', 4, 3, 1)
else
- meths.input_mouse('left', 'press', '', 0, 3, 6)
+ api.nvim_input_mouse('left', 'press', '', 0, 3, 6)
end
- eq({0, 3, 1, 0, 1}, funcs.getcurpos())
+ eq({0, 3, 1, 0, 1}, fn.getcurpos())
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 3, 2)
+ api.nvim_input_mouse('left', 'press', '', 4, 3, 2)
else
- meths.input_mouse('left', 'press', '', 0, 3, 7)
+ api.nvim_input_mouse('left', 'press', '', 0, 3, 7)
end
- eq({0, 3, 1, 0, 2}, funcs.getcurpos())
+ eq({0, 3, 1, 0, 2}, fn.getcurpos())
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 3, 10)
+ api.nvim_input_mouse('left', 'press', '', 4, 3, 10)
else
- meths.input_mouse('left', 'press', '', 0, 3, 15)
+ api.nvim_input_mouse('left', 'press', '', 0, 3, 15)
end
- eq({0, 3, 1, 0, 10}, funcs.getcurpos())
+ eq({0, 3, 1, 0, 10}, fn.getcurpos())
command('setlocal foldcolumn=1')
feed('zfkgg')
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -9089,10 +7358,10 @@ describe('float window', function()
{5:│}{2:~ }{5:│}|
{5:└────────────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 0, 5, true, 50};
+ [4] = {1001, "NW", 1, 0, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 4, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 4, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -9107,23 +7376,14 @@ describe('float window', function()
end
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 2, 1)
+ api.nvim_input_mouse('left', 'press', '', 4, 2, 1)
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -9133,13 +7393,13 @@ describe('float window', function()
{5:│}{19:│}{1: }{5:│}|
{5:└────────────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 0, 5, true, 50};
+ [4] = {1001, "NW", 1, 0, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 3, sum_scroll_delta = 0};
}}
else
- meths.input_mouse('left', 'press', '', 0, 2, 6)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 6)
screen:expect{grid=[[
{5:┌────────────────────â”} |
{0:~ }{5:│}{19: }{1:^ }{5:│}{0: }|
@@ -9152,25 +7412,25 @@ describe('float window', function()
end
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 2, 2)
+ api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
else
- meths.input_mouse('left', 'press', '', 0, 2, 7)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 7)
end
- eq({0, 2, 1, 0, 1}, funcs.getcurpos())
+ eq({0, 2, 1, 0, 1}, fn.getcurpos())
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 2, 3)
+ api.nvim_input_mouse('left', 'press', '', 4, 2, 3)
else
- meths.input_mouse('left', 'press', '', 0, 2, 8)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 8)
end
- eq({0, 2, 1, 0, 2}, funcs.getcurpos())
+ eq({0, 2, 1, 0, 2}, fn.getcurpos())
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 2, 11)
+ api.nvim_input_mouse('left', 'press', '', 4, 2, 11)
else
- meths.input_mouse('left', 'press', '', 0, 2, 16)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 16)
end
- eq({0, 2, 1, 0, 10}, funcs.getcurpos())
+ eq({0, 2, 1, 0, 10}, fn.getcurpos())
end)
it("'winblend' option", function()
@@ -9188,8 +7448,8 @@ describe('float window', function()
[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},
+ [13] = {foreground = Screen.colors.Black, background = Screen.colors.LightGray, blend = 30},
+ [14] = {foreground = Screen.colors.Black, background = Screen.colors.Grey88},
[15] = {foreground = tonumber('0x939393'), background = Screen.colors.Grey88},
[16] = {background = Screen.colors.Grey90};
[17] = {blend = 100};
@@ -9214,20 +7474,13 @@ describe('float window', function()
occaecat cupidatat non proident, sunt in culpa
qui officia deserunt mollit anim id est
laborum.]])
- local buf = meths.create_buf(false,false)
- meths.buf_set_lines(buf, 0, -1, true, {"test", "", "popup text"})
- local win = meths.open_win(buf, false, {relative='editor', width=15, height=3, row=2, col=5})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {"test", "", "popup text"})
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=15, height=3, row=2, col=5})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*8
[3:--------------------------------------------------]|
## grid 2
Ut enim ad minim veniam, quis nostrud |
@@ -9244,7 +7497,7 @@ describe('float window', function()
{1:test }|
{1: }|
{1:popup text }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 2, 5, true}}}
+ ]], float_pos={[4] = {1001, "NW", 1, 2, 5, true}}}
else
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
@@ -9259,18 +7512,11 @@ describe('float window', function()
]])
end
- meths.set_option_value("winblend", 30, {win=win.id})
+ api.nvim_set_option_value("winblend", 30, {win=win})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*8
[3:--------------------------------------------------]|
## grid 2
Ut enim ad minim veniam, quis nostrud |
@@ -9287,7 +7533,7 @@ describe('float window', function()
{9:test }|
{9: }|
{9:popup text }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 2, 5, true}}, unchanged=true}
+ ]], float_pos={[4] = {1001, "NW", 1, 2, 5, true}}, unchanged=true}
else
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
@@ -9303,18 +7549,11 @@ describe('float window', function()
end
-- Check that 'winblend' works with NormalNC highlight
- meths.set_option_value('winhighlight', 'NormalNC:Visual', {win = win})
+ api.nvim_set_option_value('winhighlight', 'NormalNC:Visual', {win = win})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*8
[3:--------------------------------------------------]|
## grid 2
Ut enim ad minim veniam, quis nostrud |
@@ -9331,7 +7570,7 @@ describe('float window', function()
{13:test }|
{13: }|
{13:popup text }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 2, 5, true}}}
+ ]], float_pos={[4] = {1001, "NW", 1, 2, 5, true}}}
else
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
@@ -9355,18 +7594,11 @@ describe('float window', function()
command('hi clear NormalNC')
command('hi SpecialRegion guifg=Red blend=0')
- meths.buf_add_highlight(buf, -1, "SpecialRegion", 2, 0, -1)
+ api.nvim_buf_add_highlight(buf, -1, "SpecialRegion", 2, 0, -1)
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*8
[3:--------------------------------------------------]|
## grid 2
Ut enim ad minim veniam, quis nostrud |
@@ -9383,7 +7615,7 @@ describe('float window', function()
{9:test }|
{9: }|
{10:popup text}{9: }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 2, 5, true}}}
+ ]], float_pos={[4] = {1001, "NW", 1, 2, 5, true}}}
else
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
@@ -9402,14 +7634,7 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*8
[3:--------------------------------------------------]|
## grid 2
Ut enim ad minim veniam, quis nostrud |
@@ -9426,7 +7651,7 @@ describe('float window', function()
{9:test }|
{9: }|
{11:popup text}{9: }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 2, 5, true}}, unchanged=true}
+ ]], float_pos={[4] = {1001, "NW", 1, 2, 5, true}}, unchanged=true}
else
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
@@ -9443,17 +7668,10 @@ describe('float window', function()
-- Test scrolling by mouse
if multigrid then
- meths.input_mouse('wheel', 'down', '', 4, 2, 2)
+ api.nvim_input_mouse('wheel', 'down', '', 4, 2, 2)
screen:expect{grid=[[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*8
[3:--------------------------------------------------]|
## grid 2
Ut enim ad minim veniam, quis nostrud |
@@ -9468,11 +7686,10 @@ describe('float window', function()
|
## grid 4
{11:popup text}{9: }|
- {12:~ }|
- {12:~ }|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 2, 5, true}}}
+ {12:~ }|*2
+ ]], float_pos={[4] = {1001, "NW", 1, 2, 5, true}}}
else
- meths.input_mouse('wheel', 'down', '', 0, 4, 7)
+ api.nvim_input_mouse('wheel', 'down', '', 0, 4, 7)
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
exercitation ullamco laboris nisi ut aliquip ex |
@@ -9487,22 +7704,15 @@ describe('float window', function()
end
-- Check that 'winblend' applies to border/title/footer
- meths.win_set_config(win, {border='single', title='Title', footer='Footer'})
- meths.set_option_value('winblend', 100, {win=win.id})
- meths.set_option_value("cursorline", true, {win=0})
+ api.nvim_win_set_config(win, {border='single', title='Title', footer='Footer'})
+ api.nvim_set_option_value('winblend', 100, {win=win})
+ api.nvim_set_option_value("cursorline", true, {win=0})
command('hi clear VertSplit')
feed('k0')
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
- [2:--------------------------------------------------]|
+ [2:--------------------------------------------------]|*8
[3:--------------------------------------------------]|
## grid 2
Ut enim ad minim veniam, quis nostrud |
@@ -9518,10 +7728,9 @@ describe('float window', function()
## grid 4
{17:┌}{23:Title}{17:──────────â”}|
{17:│}{11:popup text}{18: }{17:│}|
- {17:│}{19:~ }{17:│}|
- {17:│}{19:~ }{17:│}|
+ {17:│}{19:~ }{17:│}|*2
{17:└}{23:Footer}{17:─────────┘}|
- ]], float_pos={[4] = {{id = 1001}, "NW", 1, 2, 5, true}}}
+ ]], float_pos={[4] = {1001, "NW", 1, 2, 5, true}}}
else
screen:expect([[
Ut enim ad minim veniam, quis nostrud |
@@ -9541,63 +7750,44 @@ describe('float window', function()
insert([[
# TODO: 测试字典信æ¯çš„准确性
# FIXME: 测试字典信æ¯çš„准确性]])
- local buf = meths.create_buf(false,false)
- meths.buf_set_lines(buf, 0, -1, true, {'å£', 'å£'})
- local win = meths.open_win(buf, false, {relative='editor', width=5, height=3, row=0, col=11, style='minimal'})
+ local buf = api.nvim_create_buf(false,false)
+ api.nvim_buf_set_lines(buf, 0, -1, true, {'å£', 'å£'})
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=5, height=3, row=0, col=11, style='minimal'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
# TODO: 测试字典信æ¯çš„准确性 |
# FIXME: 测试字典信æ¯çš„准确^性 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
## grid 4
- {1:å£ }|
- {1:å£ }|
+ {1:å£ }|*2
{1: }|
- ]], float_pos={ [4] = { { id = 1001 }, "NW", 1, 0, 11, true } }}
+ ]], float_pos={ [4] = { 1001, "NW", 1, 0, 11, true } }}
else
screen:expect([[
# TODO: 测 {1:å£ }ä¿¡æ¯çš„准确性 |
# FIXME: 测{1:å£ } ä¿¡æ¯çš„准确^性 |
{0:~ }{1: }{0: }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
end
- meths.win_close(win, false)
+ api.nvim_win_close(win, false)
if multigrid then
screen:expect([[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
# TODO: 测试字典信æ¯çš„准确性 |
# FIXME: 测试字典信æ¯çš„准确^性 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
## grid 3
|
]])
@@ -9605,10 +7795,7 @@ describe('float window', function()
screen:expect([[
# TODO: 测试字典信æ¯çš„准确性 |
# FIXME: 测试字典信æ¯çš„准确^性 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end
@@ -9616,9 +7803,9 @@ describe('float window', function()
-- The interaction between 'winblend' and doublewidth chars in the background
-- does not look very good. But check no chars get incorrectly placed
-- 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.set_option_value('winblend', 30, {win=win.id})
+ api.nvim_buf_set_lines(buf, 0, -1, true, {" x x x xx", " x x x x"})
+ win = api.nvim_open_win(buf, false, {relative='editor', width=12, height=3, row=0, col=11, style='minimal'})
+ api.nvim_set_option_value('winblend', 30, {win=win})
screen:set_default_attr_ids({
[1] = {foreground = tonumber('0xb282b2'), background = tonumber('0xffcfff')},
[2] = {foreground = Screen.colors.Grey0, background = tonumber('0xffcfff')},
@@ -9629,20 +7816,12 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
# TODO: 测试字典信æ¯çš„准确性 |
# FIXME: 测试字典信æ¯çš„准确^性 |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*4
## grid 3
|
## grid 5
@@ -9650,38 +7829,28 @@ describe('float window', function()
{5: x x x x}|
{5: }|
]], float_pos={
- [5] = { { id = 1002 }, "NW", 1, 0, 11, true }
+ [5] = { 1002, "NW", 1, 0, 11, true }
}}
else
screen:expect([[
# TODO: 测 {2: x x x}{1:æ¯}{2: xx} 确性 |
# FIXME: 测{1:试}{2:x x x}{1:æ¯}{2: x}准确^性 |
{3:~ }{4: }{3: }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*3
|
]])
end
- meths.win_set_config(win, {relative='editor', row=0, col=12})
+ api.nvim_win_set_config(win, {relative='editor', row=0, col=12})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
# TODO: 测试字典信æ¯çš„准确性 |
# FIXME: 测试字典信æ¯çš„准确^性 |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*4
## grid 3
|
## grid 5
@@ -9689,16 +7858,14 @@ describe('float window', function()
{5: x x x x}|
{5: }|
]], float_pos={
- [5] = { { id = 1002 }, "NW", 1, 0, 12, true }
+ [5] = { 1002, "NW", 1, 0, 12, true }
}}
else
screen:expect([[
# TODO: 测试{2: x x}{1:信}{2:x }{1:的}{2:xx}确性 |
# FIXME: 测 {2: x x}{1:信}{2:x }{1:的}{2:x} 确^性 |
{3:~ }{4: }{3: }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*3
|
]])
end
@@ -9735,20 +7902,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
## grid 4
@@ -9757,20 +7915,14 @@ describe('float window', function()
{2:longest}|
## grid 5
{2:---------}|
- {2:- -}|
- {2:- -}|
- {2: }|
- {2: }|
+ {2:- -}|*2
+ {2: }|*2
]], attr_ids={
[1] = {foreground = Screen.colors.Blue1, bold = true};
[2] = {background = Screen.colors.LightMagenta};
}, float_pos={
- [4] = { {
- id = 1001
- }, "NW", 1, 1, 1, true },
- [5] = { {
- id = 1002
- }, "NW", 1, 0, 0, true }
+ [4] = { 1001, "NW", 1, 1, 1, true },
+ [5] = { 1002, "NW", 1, 0, 0, true }
}}
else
screen:expect([[
@@ -9803,20 +7955,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
## grid 4
@@ -9825,16 +7968,14 @@ describe('float window', function()
{2:n}|
## grid 5
{2:---}|
- {2:- -}|
- {2:- -}|
- {2: }|
- {2: }|
+ {2:- -}|*2
+ {2: }|*2
]], attr_ids={
[1] = {foreground = Screen.colors.Blue1, bold = true};
[2] = {background = Screen.colors.LightMagenta};
}, float_pos={
- [4] = { { id = 1001 }, "NW", 1, 1, 1, true },
- [5] = { { id = 1002 }, "NW", 1, 0, 0, true }
+ [4] = { 1001, "NW", 1, 1, 1, true },
+ [5] = { 1002, "NW", 1, 0, 0, true }
}}
else
screen:expect([[
@@ -9850,37 +7991,28 @@ describe('float window', function()
end)
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.set_option_value("winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg", {win=win.id})
+ local buf = api.nvim_create_buf(false,false)
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
+ api.nvim_set_option_value("winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg", {win=win})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{7: }|
{7:~ }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true };
+ [4] = { 1001, "NW", 1, 2, 5, true };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -9888,8 +8020,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{7: }{0: }|
{0:~ }{7:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]]}
end
@@ -9906,20 +8037,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -9932,14 +8054,14 @@ describe('float window', function()
{17:^ }|
{17:~ }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true };
- [5] = { { id = 1002 }, "NW", 1, 3, 8, true };
- [6] = { { id = 1003 }, "NW", 1, 4, 10, true };
+ [4] = { 1001, "NW", 1, 2, 5, true };
+ [5] = { 1002, "NW", 1, 3, 8, true };
+ [6] = { 1003, "NW", 1, 4, 10, true };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0};
- [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0};
+ [6] = {win = 1003, topline = 0, botline = 2, curline = 0, curcol = 0, linecount=1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -9955,37 +8077,28 @@ describe('float window', function()
end)
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.set_option_value("winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg", {win=win.id})
+ local buf = api.nvim_create_buf(false,false)
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=20, height=2, row=2, col=5})
+ api.nvim_set_option_value("winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg", {win=win})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{7: }|
{7:~ }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true };
+ [4] = { 1001, "NW", 1, 2, 5, true };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -9993,8 +8106,7 @@ describe('float window', function()
{0:~ }|
{0:~ }{7: }{0: }|
{0:~ }{7:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]]}
end
@@ -10011,20 +8123,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -10037,14 +8140,14 @@ describe('float window', function()
{1: }|
{1:~ }|
]], float_pos={
- [4] = { { id = 1001 }, "NW", 1, 2, 5, true };
- [5] = { { id = 1002 }, "NW", 1, 4, 10, true };
- [6] = { { id = 1003 }, "NW", 1, 3, 8, true };
+ [4] = { 1001, "NW", 1, 2, 5, true };
+ [5] = { 1002, "NW", 1, 4, 10, true };
+ [6] = { 1003, "NW", 1, 3, 8, true };
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [6] = {win = 1003, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -10060,54 +8163,42 @@ describe('float window', function()
end)
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.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.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.set_option_value("winhl", "Normal:Question,EndOfBuffer:Question", {win=win3.id})
+ local buf = api.nvim_create_buf(false,false)
+ local win1 = api.nvim_open_win(buf, false, {relative='editor', width=20, height=3, row=1, col=5, zindex=30})
+ api.nvim_set_option_value("winhl", "Normal:ErrorMsg,EndOfBuffer:ErrorMsg", {win=win1})
+ local win2 = api.nvim_open_win(buf, false, {relative='editor', width=20, height=3, row=2, col=6, zindex=50})
+ api.nvim_set_option_value("winhl", "Normal:Search,EndOfBuffer:Search", {win=win2})
+ local win3 = api.nvim_open_win(buf, false, {relative='editor', width=20, height=3, row=3, col=7, zindex=40})
+ api.nvim_set_option_value("winhl", "Normal:Question,EndOfBuffer:Question", {win=win3})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{7: }|
- {7:~ }|
- {7:~ }|
+ {7:~ }|*2
## grid 5
{17: }|
- {17:~ }|
- {17:~ }|
+ {17:~ }|*2
## grid 6
{8: }|
- {8:~ }|
- {8:~ }|
+ {8:~ }|*2
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 5, true, 30};
- [5] = {{id = 1002}, "NW", 1, 2, 6, true, 50};
- [6] = {{id = 1003}, "NW", 1, 3, 7, true, 40};
+ [4] = {1001, "NW", 1, 1, 5, true, 30};
+ [5] = {1002, "NW", 1, 2, 6, true, 50};
+ [6] = {1003, "NW", 1, 3, 7, true, 40};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [6] = {win = {id = 1003}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [6] = {win = 1003, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -10123,27 +8214,18 @@ describe('float window', function()
end)
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.set_option_value('winbar', 'floaty bar', {win=win1.id})
+ local buf = api.nvim_create_buf(false,false)
+ local win1 = api.nvim_open_win(buf, false, {relative='editor', width=15, height=3, row=1, col=5})
+ api.nvim_set_option_value('winbar', 'floaty bar', {win=win1})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -10151,10 +8233,10 @@ describe('float window', function()
{1: }|
{2:~ }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 5, true, 50};
+ [4] = {1001, "NW", 1, 1, 5, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -10162,54 +8244,42 @@ describe('float window', function()
{0:~ }{3:floaty bar }{0: }|
{0:~ }{1: }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]]}
end
-- resize and add a border
- meths.win_set_config(win1, {relative='editor', width=15, height=4, row=0, col=4, border = 'single'})
+ api.nvim_win_set_config(win1, {relative='editor', width=15, height=4, row=0, col=4, border = 'single'})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{5:┌───────────────â”}|
{5:│}{3:floaty bar }{5:│}|
{5:│}{1: }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
+ {5:│}{2:~ }{5:│}|*2
{5:└───────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 0, 4, true, 50};
+ [4] = {1001, "NW", 1, 0, 4, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
^ {5:┌───────────────â”} |
{0:~ }{5:│}{3:floaty bar }{5:│}{0: }|
{0:~ }{5:│}{1: }{5:│}{0: }|
- {0:~ }{5:│}{2:~ }{5:│}{0: }|
- {0:~ }{5:│}{2:~ }{5:│}{0: }|
+ {0:~ }{5:│}{2:~ }{5:│}{0: }|*2
{0:~ }{5:└───────────────┘}{0: }|
|
]]}
@@ -10219,55 +8289,33 @@ describe('float window', function()
it('it can be resized with messages and cmdheight=0 #20106', function()
screen:try_resize(40,9)
command 'set cmdheight=0'
- local buf = meths.create_buf(false,true)
- local win = meths.open_win(buf, false, {relative='editor', width=40, height=4, anchor='SW', row=9, col=0, style='minimal', border="single", noautocmd=true})
+ local buf = api.nvim_create_buf(false,true)
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=40, height=4, anchor='SW', row=9, col=0, style='minimal', border="single", noautocmd=true})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*9
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
## grid 3
## grid 4
{5:┌────────────────────────────────────────â”}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
+ {5:│}{1: }{5:│}|*4
{5:└────────────────────────────────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "SW", 1, 9, 0, true, 50};
+ [4] = {1001, "SW", 1, 9, 0, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{5:┌──────────────────────────────────────â”}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
+ {5:│}{1: }{5:│}|*4
{5:└──────────────────────────────────────┘}|
]]}
end
@@ -10281,144 +8329,83 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*9
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
## grid 3
## grid 4
{5:┌────────────────────────────────────────â”}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
+ {5:│}{1: }{5:│}|*2
{5:└────────────────────────────────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "SW", 1, 9, 0, true, 50};
+ [4] = {1001, "SW", 1, 9, 0, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{5:┌──────────────────────────────────────â”}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
+ {5:│}{1: }{5:│}|*2
{5:└──────────────────────────────────────┘}|
]]}
end
- meths.win_close(win, true)
+ api.nvim_win_close(win, true)
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*9
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
## grid 3
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
]]}
end
end)
it('it can be resized with messages and cmdheight=1', function()
screen:try_resize(40,9)
- local buf = meths.create_buf(false,true)
- local win = meths.open_win(buf, false, {relative='editor', width=40, height=4, anchor='SW', row=8, col=0, style='minimal', border="single", noautocmd=true})
+ local buf = api.nvim_create_buf(false,true)
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=40, height=4, anchor='SW', row=8, col=0, style='minimal', border="single", noautocmd=true})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*8
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
## grid 3
|
## grid 4
{5:┌────────────────────────────────────────â”}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
+ {5:│}{1: }{5:│}|*4
{5:└────────────────────────────────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "SW", 1, 8, 0, true, 50};
+ [4] = {1001, "SW", 1, 8, 0, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
^ |
{0:~ }|
{5:┌──────────────────────────────────────â”}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
+ {5:│}{1: }{5:│}|*4
{5:└──────────────────────────────────────┘}|
|
]]}
@@ -10436,48 +8423,30 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [3:----------------------------------------]|
- [3:----------------------------------------]|
+ [2:----------------------------------------]|*7
+ [3:----------------------------------------]|*2
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
## grid 3
|
{8:Press ENTER or type command to continue}^ |
## grid 4
{5:┌────────────────────────────────────────â”}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
+ {5:│}{1: }{5:│}|*4
{5:└────────────────────────────────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "SW", 1, 8, 0, true, 50};
+ [4] = {1001, "SW", 1, 8, 0, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
|
{0:~ }|
{5:┌──────────────────────────────────────â”}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
+ {5:│}{1: }{5:│}|*3
{4: }|
|
{8:Press ENTER or type command to continue}^ |
@@ -10488,88 +8457,52 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*8
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
## grid 3
|
## grid 4
{5:┌────────────────────────────────────────â”}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
+ {5:│}{1: }{5:│}|*2
{5:└────────────────────────────────────────┘}|
]], float_pos={
- [4] = {{id = 1001}, "SW", 1, 8, 0, true, 50};
+ [4] = {1001, "SW", 1, 8, 0, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{5:┌──────────────────────────────────────â”}|
- {5:│}{1: }{5:│}|
- {5:│}{1: }{5:│}|
+ {5:│}{1: }{5:│}|*2
{5:└──────────────────────────────────────┘}|
|
]]}
end
- meths.win_close(win, true)
+ api.nvim_win_close(win, true)
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*8
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
|
]]}
end
@@ -10578,9 +8511,9 @@ describe('float window', function()
describe('no crash after moving and closing float window #21547', function()
local function test_float_move_close(cmd)
local float_opts = {relative = 'editor', row = 1, col = 1, width = 10, height = 10}
- meths.open_win(meths.create_buf(false, false), true, float_opts)
+ api.nvim_open_win(api.nvim_create_buf(false, false), true, float_opts)
if multigrid then
- screen:expect({float_pos = {[4] = {{id = 1001}, 'NW', 1, 1, 1, true}}})
+ screen:expect({float_pos = {[4] = {1001, 'NW', 1, 1, 1, true}}})
end
command(cmd)
exec_lua([[
@@ -10605,26 +8538,17 @@ describe('float window', function()
it(':sleep cursor placement #22639', function()
local float_opts = {relative = 'editor', row = 1, col = 1, width = 4, height = 3}
- local win = meths.open_win(meths.create_buf(false, false), true, float_opts)
+ local win = api.nvim_open_win(api.nvim_create_buf(false, false), true, float_opts)
feed('iab<CR>cd<Esc>')
feed(':sleep 100')
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
:sleep 100^ |
## grid 4
@@ -10632,10 +8556,10 @@ describe('float window', function()
{1:cd }|
{2:~ }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50};
+ [4] = {1001, "NW", 1, 1, 1, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -10643,8 +8567,7 @@ describe('float window', function()
{0:~}{1:ab }{0: }|
{0:~}{1:cd }{0: }|
{0:~}{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:sleep 100^ |
]]}
end
@@ -10653,20 +8576,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
:sleep 100 |
## grid 4
@@ -10674,10 +8588,10 @@ describe('float window', function()
{1:c^d }|
{2:~ }|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50};
+ [4] = {1001, "NW", 1, 1, 1, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -10685,33 +8599,23 @@ describe('float window', function()
{0:~}{1:ab }{0: }|
{0:~}{1:c^d }{0: }|
{0:~}{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:sleep 100 |
]]}
end
feed('<C-C>')
screen:expect_unchanged()
- meths.win_set_config(win, {border = 'single'})
+ api.nvim_win_set_config(win, {border = 'single'})
feed(':sleep 100')
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
:sleep 100^ |
## grid 4
@@ -10721,10 +8625,10 @@ describe('float window', function()
{5:│}{2:~ }{5:│}|
{5:└────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50};
+ [4] = {1001, "NW", 1, 1, 1, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -10742,20 +8646,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
:sleep 100 |
## grid 4
@@ -10765,10 +8660,10 @@ describe('float window', function()
{5:│}{2:~ }{5:│}|
{5:└────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50};
+ [4] = {1001, "NW", 1, 1, 1, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -10789,20 +8684,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
:sleep 100^ |
## grid 4
@@ -10812,10 +8698,10 @@ describe('float window', function()
{5:│}{1:cd }{5:│}|
{5:└────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50};
+ [4] = {1001, "NW", 1, 1, 1, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -10833,20 +8719,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
:sleep 100 |
## grid 4
@@ -10856,10 +8733,10 @@ describe('float window', function()
{5:│}{1:c^d }{5:│}|
{5:└────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50};
+ [4] = {1001, "NW", 1, 1, 1, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 1, curcol = 1, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -10878,26 +8755,17 @@ describe('float window', function()
it('with rightleft and border #22640', function()
local float_opts = {relative='editor', width=5, height=3, row=1, col=1, border='single'}
- meths.open_win(meths.create_buf(false, false), true, float_opts)
+ api.nvim_open_win(api.nvim_create_buf(false, false), true, float_opts)
command('setlocal rightleft')
feed('iabc<CR>def<Esc>')
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
@@ -10907,10 +8775,10 @@ describe('float window', function()
{5:│}{2: ~}{5:│}|
{5:└─────┘}|
]], float_pos={
- [4] = {{id = 1001}, "NW", 1, 1, 1, true, 50};
+ [4] = {1001, "NW", 1, 1, 1, true, 50};
}, win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 2, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 3, curline = 1, curcol = 2, linecount = 2, sum_scroll_delta = 0};
}}
else
screen:expect{grid=[[
@@ -10926,29 +8794,20 @@ describe('float window', function()
end)
it('float window with hide option', function()
- local buf = meths.create_buf(false,false)
- local win = meths.open_win(buf, false, {relative='editor', width=10, height=2, row=2, col=5, hide = true})
+ local buf = api.nvim_create_buf(false,false)
+ local win = api.nvim_open_win(buf, false, {relative='editor', width=10, height=2, row=2, col=5, hide = true})
local expected_pos = {
- [4]={{id=1001}, 'NW', 1, 2, 5, true},
+ [4]={1001, 'NW', 1, 2, 5, true},
}
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
@@ -10959,33 +8818,20 @@ describe('float window', function()
else
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end
- meths.win_set_config(win, {hide = false})
+ api.nvim_win_set_config(win, {hide = false})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
@@ -10999,30 +8845,20 @@ describe('float window', function()
{0:~ }|
{0:~ }{1: }{0: }|
{0:~ }{2:~ }{0: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end
- meths.win_set_config(win, {hide=true})
+ api.nvim_win_set_config(win, {hide=true})
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
@@ -11033,85 +8869,55 @@ describe('float window', function()
else
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end
end)
it(':fclose command #9663', function()
- local buf_a = meths.create_buf(false,false)
- local buf_b = meths.create_buf(false,false)
- local buf_c = meths.create_buf(false,false)
- local buf_d = meths.create_buf(false,false)
+ local buf_a = api.nvim_create_buf(false,false)
+ local buf_b = api.nvim_create_buf(false,false)
+ local buf_c = api.nvim_create_buf(false,false)
+ local buf_d = api.nvim_create_buf(false,false)
local config_a = {relative='editor', width=11, height=11, row=5, col=5, border ='single', zindex=50}
local config_b = {relative='editor', width=8, height=8, row=7, col=7, border ='single', zindex=70}
local config_c = {relative='editor', width=4, height=4, row=9, col=9, border ='single',zindex=90}
local config_d = {relative='editor', width=2, height=2, row=10, col=10, border ='single',zindex=100}
- meths.open_win(buf_a, false, config_a)
- meths.open_win(buf_b, false, config_b)
- meths.open_win(buf_c, false, config_c)
- meths.open_win(buf_d, false, config_d)
+ api.nvim_open_win(buf_a, false, config_a)
+ api.nvim_open_win(buf_b, false, config_b)
+ api.nvim_open_win(buf_c, false, config_c)
+ api.nvim_open_win(buf_d, false, config_d)
local expected_pos = {
- [4]={{id=1001}, 'NW', 1, 5, 5, true, 50},
- [5]={{id=1002}, 'NW', 1, 7, 7, true, 70},
- [6]={{id=1003}, 'NW', 1, 9, 9, true, 90},
- [7]={{id=1004}, 'NW', 1, 10, 10, true, 100},
+ [4]={1001, 'NW', 1, 5, 5, true, 50},
+ [5]={1002, 'NW', 1, 7, 7, true, 70},
+ [6]={1003, 'NW', 1, 9, 9, true, 90},
+ [7]={1004, 'NW', 1, 10, 10, true, 100},
}
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{5:┌───────────â”}|
{5:│}{1: }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
+ {5:│}{2:~ }{5:│}|*10
{5:└───────────┘}|
## grid 5
{5:┌────────â”}|
{5:│}{1: }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
+ {5:│}{2:~ }{5:│}|*7
{5:└────────┘}|
## grid 6
{5:┌────â”}|
{5:│}{1: }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
+ {5:│}{2:~ }{5:│}|*3
{5:└────┘}|
## grid 7
{5:┌──â”}|
@@ -11136,63 +8942,35 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{5:┌───────────â”}|
{5:│}{1: }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
+ {5:│}{2:~ }{5:│}|*10
{5:└───────────┘}|
## grid 5
{5:┌────────â”}|
{5:│}{1: }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
+ {5:│}{2:~ }{5:│}|*7
{5:└────────┘}|
## grid 6
{5:┌────â”}|
{5:│}{1: }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
+ {5:│}{2:~ }{5:│}|*3
{5:└────┘}|
]], float_pos=expected_pos}
else
screen:expect([[
^ {5:┌─┌─┌────â”─â”â”} |
{0:~ }{5:│}{1: }{5:│}{1: }{5:│}{1: }{5:│}{1: }{5:││}{0: }|
- {0:~ }{5:│}{2:~}{5:│}{2:~}{5:│}{2:~ }{5:│}{2: }{5:││}{0: }|
- {0:~ }{5:│}{2:~}{5:│}{2:~}{5:│}{2:~ }{5:│}{2: }{5:││}{0: }|
- {0:~ }{5:│}{2:~}{5:│}{2:~}{5:│}{2:~ }{5:│}{2: }{5:││}{0: }|
+ {0:~ }{5:│}{2:~}{5:│}{2:~}{5:│}{2:~ }{5:│}{2: }{5:││}{0: }|*3
{0:~ }{5:│}{2:~}{5:│}{2:~}{5:└────┘}{2: }{5:││}{0: }|
|
]])
@@ -11203,57 +8981,30 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
## grid 4
{5:┌───────────â”}|
{5:│}{1: }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
+ {5:│}{2:~ }{5:│}|*10
{5:└───────────┘}|
## grid 5
{5:┌────────â”}|
{5:│}{1: }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
- {5:│}{2:~ }{5:│}|
+ {5:│}{2:~ }{5:│}|*7
{5:└────────┘}|
]], float_pos=expected_pos}
else
screen:expect([[
^ {5:┌─┌────────â”â”} |
{0:~ }{5:│}{1: }{5:│}{1: }{5:││}{0: }|
- {0:~ }{5:│}{2:~}{5:│}{2:~ }{5:││}{0: }|
- {0:~ }{5:│}{2:~}{5:│}{2:~ }{5:││}{0: }|
- {0:~ }{5:│}{2:~}{5:│}{2:~ }{5:││}{0: }|
- {0:~ }{5:│}{2:~}{5:│}{2:~ }{5:││}{0: }|
+ {0:~ }{5:│}{2:~}{5:│}{2:~ }{5:││}{0: }|*4
|
]])
end
@@ -11262,20 +9013,11 @@ describe('float window', function()
if multigrid then
screen:expect{grid=[[
## grid 1
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
- [2:----------------------------------------]|
+ [2:----------------------------------------]|*6
[3:----------------------------------------]|
## grid 2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
## grid 3
|
@@ -11283,15 +9025,82 @@ describe('float window', function()
else
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end
end)
+
+ it('correctly placed in or above message area', function()
+ local float_opts = {relative='editor', width=5, height=1, row=100, col=1, border = 'single'}
+ api.nvim_set_option_value('cmdheight', 3, {})
+ command("echo 'cmdline'")
+ local win = api.nvim_open_win(api.nvim_create_buf(false, false), true, float_opts)
+ -- Not hidden behind message area but placed above it.
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|*4
+ [3:----------------------------------------]|*3
+ ## grid 2
+ |
+ {0:~ }|*3
+ ## grid 3
+ cmdline |
+ |*2
+ ## grid 4
+ {5:┌─────â”}|
+ {5:│}{1:^ }{5:│}|
+ {5:└─────┘}|
+ ]], float_pos={
+ [4] = {1001, "NW", 1, 100, 1, true, 50};
+ }, win_viewport={
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ }}
+ else
+ screen:expect{grid=[[
+ |
+ {0:~}{5:┌─────â”}{0: }|
+ {0:~}{5:│}{1:^ }{5:│}{0: }|
+ {0:~}{5:└─────┘}{0: }|
+ cmdline |
+ |*2
+ ]]}
+ end
+ -- Not placed above message area and visible on top of it.
+ api.nvim_win_set_config(win, {zindex = 300})
+ if multigrid then
+ screen:expect{grid=[[
+ ## grid 1
+ [2:----------------------------------------]|*4
+ [3:----------------------------------------]|*3
+ ## grid 2
+ |
+ {0:~ }|*3
+ ## grid 3
+ cmdline |
+ |*2
+ ## grid 4
+ {5:┌─────â”}|
+ {5:│}{1:^ }{5:│}|
+ {5:└─────┘}|
+ ]], float_pos={
+ [4] = {1001, "NW", 1, 100, 1, true, 300};
+ }, win_viewport={
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 1, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ }}
+ else
+ screen:expect{grid=[[
+ |
+ {0:~ }|*3
+ c{5:┌─────â”} |
+ {5:│}{1:^ }{5:│} |
+ {5:└─────┘} |
+ ]]}
+ end
+ end)
end
describe('with ext_multigrid', function()
diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua
index 1addf7088e..7f13b6bd03 100644
--- a/test/functional/ui/fold_spec.lua
+++ b/test/functional/ui/fold_spec.lua
@@ -4,12 +4,11 @@ local clear, feed, eq = helpers.clear, helpers.feed, helpers.eq
local command = helpers.command
local feed_command = helpers.feed_command
local insert = helpers.insert
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local exec = helpers.exec
local assert_alive = helpers.assert_alive
-
local content1 = [[
This is a
valid English
@@ -18,7 +17,7 @@ local content1 = [[
in his cave.
]]
-describe("folded lines", function()
+describe('folded lines', function()
before_each(function()
clear()
command('hi VertSplit gui=reverse')
@@ -28,280 +27,338 @@ describe("folded lines", function()
local screen
before_each(function()
screen = Screen.new(45, 8)
- screen:attach({rgb=true, ext_multigrid=multigrid})
+ screen:attach({ rgb = true, ext_multigrid = multigrid })
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {reverse = true},
- [3] = {bold = true, reverse = true},
- [4] = {foreground = Screen.colors.White, background = Screen.colors.Red},
- [5] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey},
- [6] = {background = Screen.colors.Yellow},
- [7] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
- [8] = {foreground = Screen.colors.Brown },
- [9] = {bold = true, foreground = Screen.colors.Brown},
- [10] = {background = Screen.colors.LightGrey, underline = true},
- [11] = {bold = true},
- [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},
- [16] = {background = Screen.colors.LightGrey},
- [17] = {background = Screen.colors.Yellow, foreground = Screen.colors.Red},
- [18] = {background = Screen.colors.LightGrey, bold = true, foreground = Screen.colors.Blue},
- [19] = {background = Screen.colors.Yellow, foreground = Screen.colors.DarkBlue},
- [20] = {background = Screen.colors.Red, bold = true, foreground = Screen.colors.Blue},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { reverse = true },
+ [3] = { bold = true, reverse = true },
+ [4] = { foreground = Screen.colors.White, background = Screen.colors.Red },
+ [5] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey },
+ [6] = { background = Screen.colors.Yellow },
+ [7] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray },
+ [8] = { foreground = Screen.colors.Brown },
+ [9] = { bold = true, foreground = Screen.colors.Brown },
+ [10] = { background = Screen.colors.LightGrey, underline = true },
+ [11] = { bold = true },
+ [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 },
+ [16] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey },
+ [17] = { background = Screen.colors.Yellow, foreground = Screen.colors.Red },
+ [18] = {
+ background = Screen.colors.LightGrey,
+ bold = true,
+ foreground = Screen.colors.Blue,
+ },
+ [19] = { background = Screen.colors.Yellow, foreground = Screen.colors.DarkBlue },
+ [20] = { background = Screen.colors.Red, bold = true, foreground = Screen.colors.Blue },
})
end)
- it("work with more than one signcolumn", function()
- command("set signcolumn=yes:9")
- feed("i<cr><esc>")
- feed("vkzf")
+ it('with more than one signcolumn', function()
+ command('set signcolumn=yes:9')
+ feed('i<cr><esc>')
+ feed('vkzf')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{7: }{5:^+-- 2 lines: ·············}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
|
]])
else
screen:expect([[
{7: }{5:^+-- 2 lines: ·············}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end
end)
- local function test_folded_cursorline()
- command("set number cursorline foldcolumn=2")
- command("hi link CursorLineFold Search")
- insert(content1)
- feed("ggzf3jj")
- if multigrid then
- screen:expect([[
- ## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [3:---------------------------------------------]|
- ## grid 2
- {7:+ }{8: 1 }{5:+-- 4 lines: This is a················}|
- {6: }{9: 5 }{12:^in his cave. }|
- {7: }{8: 6 } |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ## grid 3
- |
- ]])
- else
- screen:expect([[
- {7:+ }{8: 1 }{5:+-- 4 lines: This is a················}|
- {6: }{9: 5 }{12:^in his cave. }|
- {7: }{8: 6 } |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- |
- ]])
+ local function test_folded_cursorline(foldtext)
+ if not foldtext then
+ command('set foldtext=')
end
- feed("k")
- if multigrid then
- screen:expect([[
- ## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [3:---------------------------------------------]|
- ## grid 2
- {6:+ }{9: 1 }{13:^+-- 4 lines: This is a················}|
- {7: }{8: 5 }in his cave. |
- {7: }{8: 6 } |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ## grid 3
- |
- ]])
- else
- screen:expect([[
- {6:+ }{9: 1 }{13:^+-- 4 lines: This is a················}|
- {7: }{8: 5 }in his cave. |
- {7: }{8: 6 } |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- |
- ]])
+ command('set number cursorline foldcolumn=2')
+ command('hi link CursorLineFold Search')
+ insert(content1)
+ feed('ggzf3jj')
+
+ if multigrid then
+ if foldtext then
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|*7
+ [3:---------------------------------------------]|
+ ## grid 2
+ {7:+ }{8: 1 }{5:+-- 4 lines: This is a················}|
+ {6: }{9: 5 }{12:^in his cave. }|
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ ## grid 3
+ |
+ ]])
+ else
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|*7
+ [3:---------------------------------------------]|
+ ## grid 2
+ {7:+ }{8: 1 }{5:This is a······························}|
+ {6: }{9: 5 }{12:^in his cave. }|
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ ## grid 3
+ |
+ ]])
+ end
+ else
+ if foldtext then
+ screen:expect([[
+ {7:+ }{8: 1 }{5:+-- 4 lines: This is a················}|
+ {6: }{9: 5 }{12:^in his cave. }|
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ |
+ ]])
+ else
+ screen:expect([[
+ {7:+ }{8: 1 }{5:This is a······························}|
+ {6: }{9: 5 }{12:^in his cave. }|
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ |
+ ]])
+ end
+ end
+
+ feed('k')
+
+ if multigrid then
+ if foldtext then
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|*7
+ [3:---------------------------------------------]|
+ ## grid 2
+ {6:+ }{9: 1 }{13:^+-- 4 lines: This is a················}|
+ {7: }{8: 5 }in his cave. |
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ ## grid 3
+ |
+ ]])
+ else
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|*7
+ [3:---------------------------------------------]|
+ ## grid 2
+ {6:+ }{9: 1 }{13:^This is a······························}|
+ {7: }{8: 5 }in his cave. |
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ ## grid 3
+ |
+ ]])
+ end
+ else
+ if foldtext then
+ screen:expect([[
+ {6:+ }{9: 1 }{13:^+-- 4 lines: This is a················}|
+ {7: }{8: 5 }in his cave. |
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ |
+ ]])
+ else
+ screen:expect([[
+ {6:+ }{9: 1 }{13:^This is a······························}|
+ {7: }{8: 5 }in his cave. |
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ |
+ ]])
+ end
end
+
-- CursorLine is applied correctly with screenrow motions #22232
- feed("jgk")
+ feed('jgk')
screen:expect_unchanged()
-- CursorLine is applied correctly when closing a fold when cursor is not at fold start
- feed("zo4Gzc")
+ feed('zo4Gzc')
screen:expect_unchanged()
- command("set cursorlineopt=line")
- if multigrid then
- screen:expect([[
- ## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [3:---------------------------------------------]|
- ## grid 2
- {7:+ }{8: 1 }{13:^+-- 4 lines: This is a················}|
- {7: }{8: 5 }in his cave. |
- {7: }{8: 6 } |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ## grid 3
- |
- ]])
- else
- screen:expect([[
- {7:+ }{8: 1 }{13:^+-- 4 lines: This is a················}|
- {7: }{8: 5 }in his cave. |
- {7: }{8: 6 } |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- |
- ]])
- end
- command("set relativenumber cursorlineopt=number")
- if multigrid then
- screen:expect([[
- ## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [3:---------------------------------------------]|
- ## grid 2
- {6:+ }{9:1 }{5:^+-- 4 lines: This is a················}|
- {7: }{8: 1 }in his cave. |
- {7: }{8: 2 } |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ## grid 3
- |
- ]])
- else
- screen:expect([[
- {6:+ }{9:1 }{5:^+-- 4 lines: This is a················}|
- {7: }{8: 1 }in his cave. |
- {7: }{8: 2 } |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- |
- ]])
+ command('set cursorlineopt=line')
+
+ if multigrid then
+ if foldtext then
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|*7
+ [3:---------------------------------------------]|
+ ## grid 2
+ {7:+ }{8: 1 }{13:^+-- 4 lines: This is a················}|
+ {7: }{8: 5 }in his cave. |
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ ## grid 3
+ |
+ ]])
+ else
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|*7
+ [3:---------------------------------------------]|
+ ## grid 2
+ {7:+ }{8: 1 }{13:^This is a······························}|
+ {7: }{8: 5 }in his cave. |
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ ## grid 3
+ |
+ ]])
+ end
+ else
+ if foldtext then
+ screen:expect([[
+ {7:+ }{8: 1 }{13:^+-- 4 lines: This is a················}|
+ {7: }{8: 5 }in his cave. |
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ |
+ ]])
+ else
+ screen:expect([[
+ {7:+ }{8: 1 }{13:^This is a······························}|
+ {7: }{8: 5 }in his cave. |
+ {7: }{8: 6 } |
+ {1:~ }|*4
+ |
+ ]])
+ end
+ end
+
+ command('set relativenumber cursorlineopt=number')
+
+ if multigrid then
+ if foldtext then
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|*7
+ [3:---------------------------------------------]|
+ ## grid 2
+ {6:+ }{9:1 }{5:^+-- 4 lines: This is a················}|
+ {7: }{8: 1 }in his cave. |
+ {7: }{8: 2 } |
+ {1:~ }|*4
+ ## grid 3
+ |
+ ]])
+ else
+ screen:expect([[
+ ## grid 1
+ [2:---------------------------------------------]|*7
+ [3:---------------------------------------------]|
+ ## grid 2
+ {6:+ }{9:1 }{5:^This is a······························}|
+ {7: }{8: 1 }in his cave. |
+ {7: }{8: 2 } |
+ {1:~ }|*4
+ ## grid 3
+ |
+ ]])
+ end
+ else
+ if foldtext then
+ screen:expect([[
+ {6:+ }{9:1 }{5:^+-- 4 lines: This is a················}|
+ {7: }{8: 1 }in his cave. |
+ {7: }{8: 2 } |
+ {1:~ }|*4
+ |
+ ]])
+ else
+ screen:expect([[
+ {6:+ }{9:1 }{5:^This is a······························}|
+ {7: }{8: 1 }in his cave. |
+ {7: }{8: 2 } |
+ {1:~ }|*4
+ |
+ ]])
+ end
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)
+ local function cursorline_tests(foldtext)
+ local sfx = not foldtext and ' (transparent foldtext)' or ''
+ it('with high-priority CursorLine' .. sfx, function()
+ command('hi! CursorLine guibg=NONE guifg=Red gui=NONE')
+ test_folded_cursorline(foldtext)
+ end)
+
+ it('with low-priority CursorLine' .. sfx, 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(foldtext)
+ end)
+ end
+
+ cursorline_tests(true)
+ cursorline_tests(false)
end)
- it("work with spell", function()
- command("set spell")
+ it('with spell', function()
+ command('set spell')
insert(content1)
- feed("gg")
- feed("zf3j")
+ feed('gg')
+ feed('zf3j')
if not multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{5:^+-- 4 lines: This is a······················}|
in his cave. |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
- ]]}
+ ]],
+ }
end
end)
- it("work with matches", function()
+ it('with matches', function()
insert(content1)
- command("highlight MyWord gui=bold guibg=red guifg=white")
+ command('highlight MyWord gui=bold guibg=red guifg=white')
command("call matchadd('MyWord', '\\V' . 'test', -1)")
- feed("gg")
- feed("zf3j")
+ feed('gg')
+ feed('zf3j')
if not multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{5:^+-- 4 lines: This is a······················}|
in his cave. |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
- ]]}
+ ]],
+ }
end
end)
- it("works with multibyte fillchars", function()
+ it('with multibyte fillchars', function()
insert([[
aa
bb
@@ -309,22 +366,16 @@ describe("folded lines", function()
dd
ee
ff]])
- command("set fillchars+=foldopen:▾,foldsep:│,foldclose:▸")
+ command('set fillchars+=foldopen:▾,foldsep:│,foldclose:▸')
feed_command('1')
- command("set foldcolumn=2")
+ command('set foldcolumn=2')
feed('zf4j')
feed('zf2j')
feed('zO')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{7:▾▾}^aa |
@@ -350,17 +401,11 @@ describe("folded lines", function()
]])
end
- feed_command("set rightleft")
+ feed_command('set rightleft')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
a^a{7:▾▾}|
@@ -386,77 +431,47 @@ describe("folded lines", function()
]])
end
- feed_command("set norightleft")
+ feed_command('set norightleft')
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 0, 1)
+ api.nvim_input_mouse('left', 'press', '', 2, 0, 1)
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{7:▾▸}{5:^+--- 5 lines: aa··························}|
{7:│ }ff |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
:set norightleft |
]])
else
- meths.input_mouse('left', 'press', '', 0, 0, 1)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 1)
screen:expect([[
{7:▾▸}{5:^+--- 5 lines: aa··························}|
{7:│ }ff |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:set norightleft |
]])
end
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 2, 0, 0)
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{7:▸ }{5:^+-- 6 lines: aa···························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
:set norightleft |
]])
else
- meths.input_mouse('left', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
{7:▸ }{5:^+-- 6 lines: aa···························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
:set norightleft |
]])
end
@@ -464,53 +479,35 @@ describe("folded lines", function()
-- Add a winbar to avoid double-clicks
command('setlocal winbar=!!!!!!')
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 1, 0)
+ api.nvim_input_mouse('left', 'press', '', 2, 1, 0)
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{11:!!!!!! }|
{7:▾▸}{5:^+--- 5 lines: aa··························}|
{7:│ }ff |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
:set norightleft |
]])
else
- meths.input_mouse('left', 'press', '', 0, 1, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 0)
screen:expect([[
{11:!!!!!! }|
{7:▾▸}{5:^+--- 5 lines: aa··························}|
{7:│ }ff |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
:set norightleft |
]])
end
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 1, 1)
+ api.nvim_input_mouse('left', 'press', '', 2, 1, 1)
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{11:!!!!!! }|
@@ -524,7 +521,7 @@ describe("folded lines", function()
:set norightleft |
]])
else
- meths.input_mouse('left', 'press', '', 0, 1, 1)
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 1)
screen:expect([[
{11:!!!!!! }|
{7:▾▾}^aa |
@@ -538,7 +535,7 @@ describe("folded lines", function()
end
end)
- it("works with split", function()
+ it('with split', function()
insert([[
aa
bb
@@ -547,12 +544,12 @@ describe("folded lines", function()
ee
ff]])
feed_command('2')
- command("set foldcolumn=1")
+ command('set foldcolumn=1')
feed('zf3j')
feed_command('1')
feed('zf2j')
feed('zO')
- feed_command("rightbelow new")
+ feed_command('rightbelow new')
insert([[
aa
bb
@@ -561,20 +558,17 @@ describe("folded lines", function()
ee
ff]])
feed_command('2')
- command("set foldcolumn=1")
+ command('set foldcolumn=1')
feed('zf3j')
feed_command('1')
feed('zf2j')
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*2
{2:[No Name] [+] }|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
+ [4:---------------------------------------------]|*3
{3:[No Name] [+] }|
[3:---------------------------------------------]|
## grid 2
@@ -588,7 +582,7 @@ describe("folded lines", function()
{7:│}ff |
]])
else
- meths.input_mouse('left', 'press', '', 0, 3, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 3, 0)
screen:expect([[
{7:-}aa |
{7:-}bb |
@@ -602,15 +596,12 @@ describe("folded lines", function()
end
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 1, 0)
+ api.nvim_input_mouse('left', 'press', '', 4, 1, 0)
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*2
{2:[No Name] [+] }|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
+ [4:---------------------------------------------]|*3
{3:[No Name] [+] }|
[3:---------------------------------------------]|
## grid 2
@@ -624,7 +615,7 @@ describe("folded lines", function()
{7:2}cc |
]])
else
- meths.input_mouse('left', 'press', '', 0, 4, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 4, 0)
screen:expect([[
{7:-}aa |
{7:-}bb |
@@ -638,15 +629,12 @@ describe("folded lines", function()
end
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 1, 0)
+ api.nvim_input_mouse('left', 'press', '', 2, 1, 0)
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*2
{3:[No Name] [+] }|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
+ [4:---------------------------------------------]|*3
{2:[No Name] [+] }|
[3:---------------------------------------------]|
## grid 2
@@ -660,7 +648,7 @@ describe("folded lines", function()
{7:2}cc |
]])
else
- meths.input_mouse('left', 'press', '', 0, 1, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 0)
screen:expect([[
{7:-}aa |
{7:+}{5:^+--- 4 lines: bb···························}|
@@ -674,15 +662,12 @@ describe("folded lines", function()
end
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 2, 0, 0)
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*2
{3:[No Name] [+] }|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
+ [4:---------------------------------------------]|*3
{2:[No Name] [+] }|
[3:---------------------------------------------]|
## grid 2
@@ -696,7 +681,7 @@ describe("folded lines", function()
{7:2}cc |
]])
else
- meths.input_mouse('left', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
{7:+}{5:^+-- 6 lines: aa····························}|
{1:~ }|
@@ -710,7 +695,7 @@ describe("folded lines", function()
end
end)
- it("works with vsplit", function()
+ it('with vsplit', function()
insert([[
aa
bb
@@ -719,12 +704,12 @@ describe("folded lines", function()
ee
ff]])
feed_command('2')
- command("set foldcolumn=1")
+ command('set foldcolumn=1')
feed('zf3j')
feed_command('1')
feed('zf2j')
feed('zO')
- feed_command("rightbelow vnew")
+ feed_command('rightbelow vnew')
insert([[
aa
bb
@@ -733,20 +718,15 @@ describe("folded lines", function()
ee
ff]])
feed_command('2')
- command("set foldcolumn=1")
+ command('set foldcolumn=1')
feed('zf3j')
feed_command('1')
feed('zf2j')
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
screen:expect([[
## grid 1
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
+ [2:----------------------]{2:│}[4:----------------------]|*6
{2:[No Name] [+] }{3:[No Name] [+] }|
[3:---------------------------------------------]|
## grid 2
@@ -762,12 +742,10 @@ describe("folded lines", function()
{7:-}^aa |
{7:+}{5:+--- 4 lines: bb····}|
{7:│}ff |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
]])
else
- meths.input_mouse('left', 'press', '', 0, 0, 23)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 23)
screen:expect([[
{7:-}aa {2:│}{7:-}^aa |
{7:-}bb {2:│}{7:+}{5:+--- 4 lines: bb····}|
@@ -781,15 +759,10 @@ describe("folded lines", function()
end
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 1, 0)
+ api.nvim_input_mouse('left', 'press', '', 4, 1, 0)
screen:expect([[
## grid 1
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
+ [2:----------------------]{2:│}[4:----------------------]|*6
{2:[No Name] [+] }{3:[No Name] [+] }|
[3:---------------------------------------------]|
## grid 2
@@ -810,7 +783,7 @@ describe("folded lines", function()
{7:│}ff |
]])
else
- meths.input_mouse('left', 'press', '', 0, 1, 23)
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 23)
screen:expect([[
{7:-}aa {2:│}{7:-}^aa |
{7:-}bb {2:│}{7:-}bb |
@@ -824,24 +797,17 @@ describe("folded lines", function()
end
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 1, 0)
+ api.nvim_input_mouse('left', 'press', '', 2, 1, 0)
screen:expect([[
## grid 1
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
+ [2:----------------------]{2:│}[4:----------------------]|*6
{3:[No Name] [+] }{2:[No Name] [+] }|
[3:---------------------------------------------]|
## grid 2
{7:-}aa |
{7:+}{5:^+--- 4 lines: bb····}|
{7:│}ff |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
:1 |
## grid 4
@@ -853,7 +819,7 @@ describe("folded lines", function()
{7:│}ff |
]])
else
- meths.input_mouse('left', 'press', '', 0, 1, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 0)
screen:expect([[
{7:-}aa {2:│}{7:-}aa |
{7:+}{5:^+--- 4 lines: bb····}{2:│}{7:-}bb |
@@ -867,24 +833,15 @@ describe("folded lines", function()
end
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 2, 0, 0)
screen:expect([[
## grid 1
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
- [2:----------------------]{2:│}[4:----------------------]|
+ [2:----------------------]{2:│}[4:----------------------]|*6
{3:[No Name] [+] }{2:[No Name] [+] }|
[3:---------------------------------------------]|
## grid 2
{7:+}{5:^+-- 6 lines: aa·····}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
:1 |
## grid 4
@@ -896,7 +853,7 @@ describe("folded lines", function()
{7:│}ff |
]])
else
- meths.input_mouse('left', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
{7:+}{5:^+-- 6 lines: aa·····}{2:│}{7:-}aa |
{1:~ }{2:│}{7:-}bb |
@@ -910,7 +867,7 @@ describe("folded lines", function()
end
end)
- it("works with tab", function()
+ it('with tabpages', function()
insert([[
aa
bb
@@ -919,23 +876,18 @@ describe("folded lines", function()
ee
ff]])
feed_command('2')
- command("set foldcolumn=2")
+ command('set foldcolumn=2')
feed('zf3j')
feed_command('1')
feed('zf2j')
feed('zO')
- feed_command("tab split")
+ feed_command('tab split')
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 1, 1)
+ api.nvim_input_mouse('left', 'press', '', 4, 1, 1)
screen:expect([[
## grid 1
{10: + [No Name] }{11: + [No Name] }{2: }{10:X}|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
+ [4:---------------------------------------------]|*6
[3:---------------------------------------------]|
## grid 2 (hidden)
{7:- }aa |
@@ -951,35 +903,26 @@ describe("folded lines", function()
{7:- }^aa |
{7:│+}{5:+--- 4 lines: bb··························}|
{7:│ }ff |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
]])
else
- meths.input_mouse('left', 'press', '', 0, 2, 1)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 1)
screen:expect([[
{10: + [No Name] }{11: + [No Name] }{2: }{10:X}|
{7:- }^aa |
{7:│+}{5:+--- 4 lines: bb··························}|
{7:│ }ff |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
:tab split |
]])
end
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 4, 0, 0)
screen:expect([[
## grid 1
{10: + [No Name] }{11: + [No Name] }{2: }{10:X}|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
+ [4:---------------------------------------------]|*6
[3:---------------------------------------------]|
## grid 2 (hidden)
{7:- }aa |
@@ -993,138 +936,90 @@ describe("folded lines", function()
:tab split |
## grid 4
{7:+ }{5:^+-- 6 lines: aa···························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]])
else
- meths.input_mouse('left', 'press', '', 0, 1, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 0)
screen:expect([[
{10: + [No Name] }{11: + [No Name] }{2: }{10:X}|
{7:+ }{5:^+-- 6 lines: aa···························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:tab split |
]])
end
- feed_command("tabnext")
+ feed_command('tabnext')
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 1, 1)
+ api.nvim_input_mouse('left', 'press', '', 2, 1, 1)
screen:expect([[
## grid 1
{11: + [No Name] }{10: + [No Name] }{2: }{10:X}|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*6
[3:---------------------------------------------]|
## grid 2
{7:- }^aa |
{7:│+}{5:+--- 4 lines: bb··························}|
{7:│ }ff |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
:tabnext |
## grid 4 (hidden)
{7:+ }{5:+-- 6 lines: aa···························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]])
else
- meths.input_mouse('left', 'press', '', 0, 2, 1)
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 1)
screen:expect([[
{11: + [No Name] }{10: + [No Name] }{2: }{10:X}|
{7:- }^aa |
{7:│+}{5:+--- 4 lines: bb··························}|
{7:│ }ff |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
:tabnext |
]])
end
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 2, 0, 0)
screen:expect([[
## grid 1
{11: + [No Name] }{10: + [No Name] }{2: }{10:X}|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*6
[3:---------------------------------------------]|
## grid 2
{7:+ }{5:^+-- 6 lines: aa···························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
:tabnext |
## grid 4 (hidden)
{7:+ }{5:+-- 6 lines: aa···························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]])
else
- meths.input_mouse('left', 'press', '', 0, 1, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 0)
screen:expect([[
{11: + [No Name] }{10: + [No Name] }{2: }{10:X}|
{7:+ }{5:^+-- 6 lines: aa···························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:tabnext |
]])
end
end)
- it("works with multibyte text", function()
- eq(true, meths.get_option_value('arabicshape', {}))
+ it('with multibyte text', function()
+ eq(true, api.nvim_get_option_value('arabicshape', {}))
insert([[
Ã¥ 语 x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢͟ العَرَبÙيَّة
möre text]])
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
Ã¥ 语 x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ ﺎﻠﻋَﺮَﺒÙﻳَّﺓ |
möre tex^t |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
]])
@@ -1132,11 +1027,7 @@ describe("folded lines", function()
screen:expect([[
Ã¥ 语 x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ ﺎﻠﻋَﺮَﺒÙﻳَّﺓ |
möre tex^t |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
end
@@ -1145,215 +1036,119 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{5:^+-- 2 lines: Ã¥ 语 x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ ﺎﻠﻋَﺮَﺒÙﻳَّﺓ·················}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
|
]])
else
screen:expect([[
{5:^+-- 2 lines: Ã¥ 语 x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ ﺎﻠﻋَﺮَﺒÙﻳَّﺓ·················}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end
- feed_command("set noarabicshape")
+ feed_command('set noarabicshape')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{5:^+-- 2 lines: Ã¥ 语 x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ العَرَبÙيَّة·················}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
:set noarabicshape |
]])
else
screen:expect([[
{5:^+-- 2 lines: Ã¥ 语 x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ العَرَبÙيَّة·················}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
:set noarabicshape |
]])
end
- feed_command("set number foldcolumn=2")
+ feed_command('set number foldcolumn=2')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{7:+ }{8: 1 }{5:^+-- 2 lines: Ã¥ 语 x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ العَرَبÙيَّة···········}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
:set number foldcolumn=2 |
]])
else
screen:expect([[
{7:+ }{8: 1 }{5:^+-- 2 lines: Ã¥ 语 x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ العَرَبÙيَّة···········}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
:set number foldcolumn=2 |
]])
end
-- Note: too much of the folded line gets cut off.This is a vim bug.
- feed_command("set rightleft")
+ feed_command('set rightleft')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{5:Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Ø©ÙŠÙŽÙ‘Ø¨ÙØ±ÙŽØ¹ÙŽÙ„ا x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ 语 Ã¥ :senil 2 --^+}{8: 1 }{7: +}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*6
## grid 3
:set rightleft |
]])
else
screen:expect([[
{5:Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Ø©ÙŠÙŽÙ‘Ø¨ÙØ±ÙŽØ¹ÙŽÙ„ا x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ 语 Ã¥ :senil 2 --^+}{8: 1 }{7: +}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*6
:set rightleft |
]])
end
- feed_command("set nonumber foldcolumn=0")
+ feed_command('set nonumber foldcolumn=0')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{5:Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Ø©ÙŠÙŽÙ‘Ø¨ÙØ±ÙŽØ¹ÙŽÙ„ا x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ 语 Ã¥ :senil 2 --^+}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*6
## grid 3
:set nonumber foldcolumn=0 |
]])
else
screen:expect([[
{5:Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Ø©ÙŠÙŽÙ‘Ø¨ÙØ±ÙŽØ¹ÙŽÙ„ا x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ 语 Ã¥ :senil 2 --^+}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*6
:set nonumber foldcolumn=0 |
]])
end
- feed_command("set arabicshape")
+ feed_command('set arabicshape')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{5:·················ﺔﻴَّﺑÙïº®ÙŽï»ŒÙŽï»Ÿïº x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ 语 Ã¥ :senil 2 --^+}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*6
## grid 3
:set arabicshape |
]])
else
screen:expect([[
{5:·················ﺔﻴَّﺑÙïº®ÙŽï»ŒÙŽï»Ÿïº x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ 语 Ã¥ :senil 2 --^+}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*6
:set arabicshape |
]])
end
@@ -1362,22 +1157,12 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
ﺔﻴَّﺑÙﺮَﻌَ^ï»Ÿïº x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ 语 Ã¥|
txet eröm|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*5
## grid 3
:set arabicshape |
]])
@@ -1385,11 +1170,7 @@ describe("folded lines", function()
screen:expect([[
ﺔﻴَّﺑÙﺮَﻌَ^ï»Ÿïº x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ 语 Ã¥|
txet eröm|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*5
:set arabicshape |
]])
end
@@ -1398,22 +1179,12 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
Ø©ÙŠÙŽÙ‘Ø¨ÙØ±ÙŽØ¹ÙŽ^لا x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ 语 Ã¥|
txet eröm|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*5
## grid 3
:set noarabicshape |
]])
@@ -1421,229 +1192,179 @@ describe("folded lines", function()
screen:expect([[
Ø©ÙŠÙŽÙ‘Ø¨ÙØ±ÙŽØ¹ÙŽ^لا x̨̣̘̫̲͚͎̎͂̀̂͛͛̾͢ 语 Ã¥|
txet eröm|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*5
:set noarabicshape |
]])
end
-
end)
- it("work in cmdline window", function()
- feed_command("set foldmethod=manual")
- feed_command("let x = 1")
- feed_command("/alpha")
- feed_command("/omega")
+ it('in cmdline window', function()
+ feed_command('set foldmethod=manual foldcolumn=1')
+ feed_command('let x = 1')
+ feed_command('/alpha')
+ feed_command('/omega')
- feed("<cr>q:")
+ feed('<cr>q:')
if multigrid then
screen:expect([[
## grid 1
[2:---------------------------------------------]|
{2:[No Name] }|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
+ [4:---------------------------------------------]|*4
{3:[Command Line] }|
[3:---------------------------------------------]|
## grid 2
- |
+ {7: } |
## grid 3
: |
## grid 4
- {1::}set foldmethod=manual |
- {1::}let x = 1 |
- {1::}^ |
+ {1::}{7: }set foldmethod=manual foldcolumn=1 |
+ {1::}{7: }let x = 1 |
+ {1::}{7: }^ |
{1:~ }|
]])
else
screen:expect([[
- |
+ {7: } |
{2:[No Name] }|
- {1::}set foldmethod=manual |
- {1::}let x = 1 |
- {1::}^ |
+ {1::}{7: }set foldmethod=manual foldcolumn=1 |
+ {1::}{7: }let x = 1 |
+ {1::}{7: }^ |
{1:~ }|
{3:[Command Line] }|
: |
]])
end
- feed("kzfk")
+ feed('kzfk')
if multigrid then
screen:expect([[
## grid 1
[2:---------------------------------------------]|
{2:[No Name] }|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
- [4:---------------------------------------------]|
+ [4:---------------------------------------------]|*4
{3:[Command Line] }|
[3:---------------------------------------------]|
## grid 2
- |
+ {7: } |
## grid 3
: |
## grid 4
- {1::}{5:^+-- 2 lines: set foldmethod=manual·········}|
- {1::} |
- {1:~ }|
- {1:~ }|
+ {1::}{7:+}{5:^+-- 2 lines: set foldmethod=manual foldcol}|
+ {1::}{7: } |
+ {1:~ }|*2
]])
else
screen:expect([[
- |
+ {7: } |
{2:[No Name] }|
- {1::}{5:^+-- 2 lines: set foldmethod=manual·········}|
- {1::} |
- {1:~ }|
- {1:~ }|
+ {1::}{7:+}{5:^+-- 2 lines: set foldmethod=manual foldcol}|
+ {1::}{7: } |
+ {1:~ }|*2
{3:[Command Line] }|
: |
]])
end
- feed("<cr>")
+ feed('<cr>')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
- ^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {7: }^ |
+ {1:~ }|*6
## grid 3
: |
]])
else
screen:expect([[
- ^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {7: }^ |
+ {1:~ }|*6
: |
]])
end
- feed("/<c-f>")
+ feed('/<c-f>')
if multigrid then
screen:expect([[
## grid 1
[2:---------------------------------------------]|
{2:[No Name] }|
- [5:---------------------------------------------]|
- [5:---------------------------------------------]|
- [5:---------------------------------------------]|
- [5:---------------------------------------------]|
+ [5:---------------------------------------------]|*4
{3:[Command Line] }|
[3:---------------------------------------------]|
## grid 2
- |
+ {7: } |
## grid 3
/ |
## grid 5
- {1:/}alpha |
- {1:/}{6:omega} |
- {1:/}^ |
+ {1:/}{7: }alpha |
+ {1:/}{7: }{6:omega} |
+ {1:/}{7: }^ |
{1:~ }|
]])
else
screen:expect([[
- |
+ {7: } |
{2:[No Name] }|
- {1:/}alpha |
- {1:/}{6:omega} |
- {1:/}^ |
+ {1:/}{7: }alpha |
+ {1:/}{7: }{6:omega} |
+ {1:/}{7: }^ |
{1:~ }|
{3:[Command Line] }|
/ |
]])
end
- feed("ggzfG")
+ feed('ggzfG')
if multigrid then
screen:expect([[
## grid 1
[2:---------------------------------------------]|
{2:[No Name] }|
- [5:---------------------------------------------]|
- [5:---------------------------------------------]|
- [5:---------------------------------------------]|
- [5:---------------------------------------------]|
+ [5:---------------------------------------------]|*4
{3:[Command Line] }|
[3:---------------------------------------------]|
## grid 2
- |
+ {7: } |
## grid 3
/ |
## grid 5
- {1:/}{5:^+-- 3 lines: alpha·························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:/}{7:+}{5:^+-- 3 lines: alpha························}|
+ {1:~ }|*3
]])
else
screen:expect([[
- |
+ {7: } |
{2:[No Name] }|
- {1:/}{5:^+-- 3 lines: alpha·························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:/}{7:+}{5:^+-- 3 lines: alpha························}|
+ {1:~ }|*3
{3:[Command Line] }|
/ |
]])
end
-
end)
- it("work with autoresize", function()
+ it('foldcolumn autoresize', function()
+ fn.setline(1, 'line 1')
+ fn.setline(2, 'line 2')
+ fn.setline(3, 'line 3')
+ fn.setline(4, 'line 4')
- funcs.setline(1, 'line 1')
- funcs.setline(2, 'line 2')
- funcs.setline(3, 'line 3')
- funcs.setline(4, 'line 4')
-
- feed("zfj")
- command("set foldcolumn=0")
+ feed('zfj')
+ command('set foldcolumn=0')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{5:^+-- 2 lines: line 1·························}|
line 3 |
line 4 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
]])
@@ -1652,34 +1373,22 @@ describe("folded lines", function()
{5:^+-- 2 lines: line 1·························}|
line 3 |
line 4 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
end
-- should adapt to the current nesting of folds (e.g., 1)
- command("set foldcolumn=auto:1")
+ command('set foldcolumn=auto:1')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{7:+}{5:^+-- 2 lines: line 1························}|
{7: }line 3 |
{7: }line 4 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
]])
@@ -1688,267 +1397,140 @@ describe("folded lines", function()
{7:+}{5:^+-- 2 lines: line 1························}|
{7: }line 3 |
{7: }line 4 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
end
- command("set foldcolumn=auto")
+ command('set foldcolumn=auto')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{7:+}{5:^+-- 2 lines: line 1························}|
{7: }line 3 |
{7: }line 4 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
else
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{7:+}{5:^+-- 2 lines: line 1························}|
{7: }line 3 |
{7: }line 4 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
end
-- fdc should not change with a new fold as the maximum is 1
- feed("zf3j")
+ feed('zf3j')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{7:+}{5:^+-- 4 lines: line 1························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
|
]])
else
screen:expect([[
{7:+}{5:^+-- 4 lines: line 1························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end
- command("set foldcolumn=auto:1")
- if multigrid then screen:expect{grid=[[
+ command('set foldcolumn=auto:1')
+ if multigrid then
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{7:+}{5:^+-- 4 lines: line 1························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
else
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{7:+}{5:^+-- 4 lines: line 1························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
end
-- relax the maximum fdc thus fdc should expand to
-- accommodate the current number of folds
- command("set foldcolumn=auto:4")
+ command('set foldcolumn=auto:4')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{7:+ }{5:^+-- 4 lines: line 1·······················}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
|
]])
else
screen:expect([[
{7:+ }{5:^+-- 4 lines: line 1·······················}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end
end)
- it('does not crash when foldtext is longer than columns #12988', function()
+ it('no crash when foldtext is longer than columns #12988', function()
exec([[
function! MyFoldText() abort
return repeat('-', &columns + 100)
endfunction
]])
command('set foldtext=MyFoldText()')
- feed("i<cr><esc>")
- feed("vkzf")
+ feed('i<cr><esc>')
+ feed('vkzf')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{5:^---------------------------------------------}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
|
]])
else
screen:expect([[
{5:^---------------------------------------------}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end
assert_alive()
end)
- it('work correctly with :move #18668', function()
- screen:try_resize(45, 12)
- exec([[
- set foldmethod=expr foldexpr=indent(v:lnum)
- let content = ['', '', 'Line1', ' Line2', ' Line3',
- \ 'Line4', ' Line5', ' Line6',
- \ 'Line7', ' Line8', ' Line9']
- call append(0, content)
- normal! zM
- call cursor(4, 1)
- move 2
- move 1
- ]])
- if multigrid then
- screen:expect([[
- ## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [3:---------------------------------------------]|
- ## grid 2
- |
- {5:^+-- 2 lines: Line2··························}|
- |
- Line1 |
- Line4 |
- {5:+-- 2 lines: Line5··························}|
- Line7 |
- {5:+-- 2 lines: Line8··························}|
- |
- {1:~ }|
- {1:~ }|
- ## grid 3
- |
- ]])
- else
- screen:expect([[
- |
- {5:^+-- 2 lines: Line2··························}|
- |
- Line1 |
- Line4 |
- {5:+-- 2 lines: Line5··························}|
- Line7 |
- {5:+-- 2 lines: Line8··························}|
- |
- {1:~ }|
- {1:~ }|
- |
- ]])
- end
- end)
-
it('fold text is shown when text has been scrolled to the right #19123', function()
insert(content1)
command('set number nowrap')
@@ -1957,13 +1539,7 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{8: 1 }^This is a |
@@ -1971,8 +1547,7 @@ describe("folded lines", function()
{8: 3 }{5:+-- 2 lines: sentence composed by·······}|
{8: 5 }in his cave. |
{8: 6 } |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
|
]])
@@ -1983,8 +1558,7 @@ describe("folded lines", function()
{8: 3 }{5:+-- 2 lines: sentence composed by·······}|
{8: 5 }in his cave. |
{8: 6 } |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
end
@@ -1993,13 +1567,7 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{8: 1 }^his is a |
@@ -2007,8 +1575,7 @@ describe("folded lines", function()
{8: 3 }{5:+-- 2 lines: sentence composed by·······}|
{8: 5 }n his cave. |
{8: 6 } |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
|
]])
@@ -2019,34 +1586,52 @@ describe("folded lines", function()
{8: 3 }{5:+-- 2 lines: sentence composed by·······}|
{8: 5 }n his cave. |
{8: 6 } |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
end
end)
it('fold attached virtual lines are drawn and scrolled correctly #21837', function()
- funcs.setline(1, 'line 1')
- funcs.setline(2, 'line 2')
- funcs.setline(3, 'line 3')
- funcs.setline(4, 'line 4')
- feed("zfj")
- local ns = meths.create_namespace('ns')
- meths.buf_set_extmark(0, ns, 0, 0, { virt_lines_above = true, virt_lines = {{{"virt_line above line 1", ""}}} })
- meths.buf_set_extmark(0, ns, 1, 0, { virt_lines = {{{"virt_line below line 2", ""}}} })
- meths.buf_set_extmark(0, ns, 2, 0, { virt_lines_above = true, virt_lines = {{{"virt_line above line 3", ""}}} })
- meths.buf_set_extmark(0, ns, 3, 0, { virt_lines = {{{"virt_line below line 4", ""}}} })
- if multigrid then
- screen:expect{grid=[[
- ## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ fn.setline(1, 'line 1')
+ fn.setline(2, 'line 2')
+ fn.setline(3, 'line 3')
+ fn.setline(4, 'line 4')
+ feed('zfj')
+ local ns = api.nvim_create_namespace('ns')
+ api.nvim_buf_set_extmark(
+ 0,
+ ns,
+ 0,
+ 0,
+ { virt_lines_above = true, virt_lines = { { { 'virt_line above line 1', '' } } } }
+ )
+ api.nvim_buf_set_extmark(
+ 0,
+ ns,
+ 1,
+ 0,
+ { virt_lines = { { { 'virt_line below line 2', '' } } } }
+ )
+ api.nvim_buf_set_extmark(
+ 0,
+ ns,
+ 2,
+ 0,
+ { virt_lines_above = true, virt_lines = { { { 'virt_line above line 3', '' } } } }
+ )
+ api.nvim_buf_set_extmark(
+ 0,
+ ns,
+ 3,
+ 0,
+ { virt_lines = { { { 'virt_line below line 4', '' } } } }
+ )
+ if multigrid then
+ screen:expect {
+ grid = [[
+ ## grid 1
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{5:^+-- 2 lines: line 1·························}|
@@ -2054,13 +1639,22 @@ describe("folded lines", function()
line 3 |
line 4 |
virt_line below line 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
|
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 5, curline = 0, curcol = 0, linecount = 4, sum_scroll_delta = 0};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 0,
+ botline = 5,
+ curline = 0,
+ curcol = 0,
+ linecount = 4,
+ sum_scroll_delta = 0,
+ },
+ },
+ }
else
screen:expect([[
{5:^+-- 2 lines: line 1·························}|
@@ -2068,62 +1662,53 @@ describe("folded lines", function()
line 3 |
line 4 |
virt_line below line 4 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
end
feed('jzfj')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{5:+-- 2 lines: line 1·························}|
{5:^+-- 2 lines: line 3·························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 5, curline = 2, curcol = 0, linecount = 4, sum_scroll_delta = 0};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 0,
+ botline = 5,
+ curline = 2,
+ curcol = 0,
+ linecount = 4,
+ sum_scroll_delta = 0,
+ },
+ },
+ }
else
screen:expect([[
{5:+-- 2 lines: line 1·························}|
{5:^+-- 2 lines: line 3·························}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
end
feed('kzo<C-Y>')
- funcs.setline(5, 'line 5')
+ fn.setline(5, 'line 5')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
virt_line above line 1 |
@@ -2135,9 +1720,19 @@ describe("folded lines", function()
{1:~ }|
## grid 3
|
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 6, curline = 0, curcol = 0, linecount = 5, sum_scroll_delta = -1};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 0,
+ botline = 6,
+ curline = 0,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = -1,
+ },
+ },
+ }
else
screen:expect([[
virt_line above line 1 |
@@ -2151,7 +1746,7 @@ describe("folded lines", function()
]])
end
- meths.input_mouse('left', 'press', '', multigrid and 2 or 0, 4, 0)
+ api.nvim_input_mouse('left', 'press', '', multigrid and 2 or 0, 4, 0)
eq({
screencol = 1,
screenrow = 5,
@@ -2161,20 +1756,21 @@ describe("folded lines", function()
line = 3,
column = 1,
coladd = 0,
- }, funcs.getmousepos())
-
- meths.buf_set_extmark(0, ns, 1, 0, { virt_lines = {{{"more virt_line below line 2", ""}}} })
+ }, fn.getmousepos())
+
+ api.nvim_buf_set_extmark(
+ 0,
+ ns,
+ 1,
+ 0,
+ { virt_lines = { { { 'more virt_line below line 2', '' } } } }
+ )
feed('G<C-E>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
line 1 |
@@ -2186,9 +1782,19 @@ describe("folded lines", function()
{1:~ }|
## grid 3
|
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 0};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 0,
+ botline = 6,
+ curline = 4,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 0,
+ },
+ },
+ }
else
screen:expect([[
line 1 |
@@ -2204,15 +1810,10 @@ describe("folded lines", function()
feed('<C-E>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
line 2 |
@@ -2220,13 +1821,22 @@ describe("folded lines", function()
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^line 5 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
|
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 1, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 1};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 1,
+ botline = 6,
+ curline = 4,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 1,
+ },
+ },
+ }
else
screen:expect([[
line 2 |
@@ -2234,312 +1844,301 @@ describe("folded lines", function()
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^line 5 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
end
feed('<C-E>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
virt_line below line 2 |
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^line 5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 2};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 2,
+ botline = 6,
+ curline = 4,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 2,
+ },
+ },
+ }
else
screen:expect([[
virt_line below line 2 |
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^line 5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
end
feed('<C-E>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^line 5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 3};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 2,
+ botline = 6,
+ curline = 4,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 3,
+ },
+ },
+ }
else
screen:expect([[
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^line 5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
end
feed('<C-E>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{5:+-- 2 lines: line 3·························}|
^line 5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 4};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 2,
+ botline = 6,
+ curline = 4,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 4,
+ },
+ },
+ }
else
screen:expect([[
{5:+-- 2 lines: line 3·························}|
^line 5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
end
feed('<C-E>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
^line 5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
|
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 4, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 5};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 4,
+ botline = 6,
+ curline = 4,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 5,
+ },
+ },
+ }
else
screen:expect([[
^line 5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end
feed('3<C-Y>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
virt_line below line 2 |
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^line 5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 2};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 2,
+ botline = 6,
+ curline = 4,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 2,
+ },
+ },
+ }
else
screen:expect([[
virt_line below line 2 |
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^line 5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
end
- meths.input_mouse('left', 'press', '3', multigrid and 2 or 0, 3, 0)
+ api.nvim_input_mouse('left', 'press', '3', multigrid and 2 or 0, 3, 0)
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
virt_line below line 2 |
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^l{16:ine 5} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
{11:-- VISUAL LINE --} |
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 2};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 2,
+ botline = 6,
+ curline = 4,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 2,
+ },
+ },
+ }
else
screen:expect([[
virt_line below line 2 |
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^l{16:ine 5} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{11:-- VISUAL LINE --} |
]])
end
- meths.input_mouse('left', 'drag', '3', multigrid and 2 or 0, 7, 0)
+ api.nvim_input_mouse('left', 'drag', '3', multigrid and 2 or 0, 7, 0)
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^l{16:ine 5} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
{11:-- VISUAL LINE --} |
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 0, linecount = 5, sum_scroll_delta = 3};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 2,
+ botline = 6,
+ curline = 4,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 3,
+ },
+ },
+ }
else
screen:expect([[
more virt_line below line 2 |
{5:+-- 2 lines: line 3·························}|
^l{16:ine 5} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{11:-- VISUAL LINE --} |
]])
end
- meths.input_mouse('left', 'drag', '3', multigrid and 2 or 0, 7, 5)
+ api.nvim_input_mouse('left', 'drag', '3', multigrid and 2 or 0, 7, 5)
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{5:+-- 2 lines: line 3·························}|
{16:line }^5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
{11:-- VISUAL LINE --} |
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 2, botline = 6, curline = 4, curcol = 5, linecount = 5, sum_scroll_delta = 4};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 2,
+ botline = 6,
+ curline = 4,
+ curcol = 5,
+ linecount = 5,
+ sum_scroll_delta = 4,
+ },
+ },
+ }
else
screen:expect([[
{5:+-- 2 lines: line 3·························}|
{16:line }^5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{11:-- VISUAL LINE --} |
]])
end
@@ -2547,12 +2146,10 @@ describe("folded lines", function()
feed('<Esc>gg')
command('botright 1split | wincmd w')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*4
{3:[No Name] [+] }|
[4:---------------------------------------------]|
{2:[No Name] [+] }|
@@ -2566,10 +2163,28 @@ describe("folded lines", function()
|
## grid 4
line 1 |
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 5, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 5, sum_scroll_delta = 0};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 0,
+ botline = 3,
+ curline = 0,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 0,
+ },
+ [4] = {
+ win = 1001,
+ topline = 0,
+ botline = 2,
+ curline = 0,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 0,
+ },
+ },
+ }
else
screen:expect([[
^line 1 |
@@ -2585,12 +2200,10 @@ describe("folded lines", function()
feed('<C-Y>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*4
{3:[No Name] [+] }|
[4:---------------------------------------------]|
{2:[No Name] [+] }|
@@ -2604,10 +2217,28 @@ describe("folded lines", function()
|
## grid 4
line 1 |
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 0, linecount = 5, sum_scroll_delta = -1};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 5, sum_scroll_delta = 0};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 0,
+ botline = 3,
+ curline = 0,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = -1,
+ },
+ [4] = {
+ win = 1001,
+ topline = 0,
+ botline = 2,
+ curline = 0,
+ curcol = 0,
+ linecount = 5,
+ sum_scroll_delta = 0,
+ },
+ },
+ }
else
screen:expect([[
virt_line above line 1 |
@@ -2623,7 +2254,7 @@ describe("folded lines", function()
end)
it('Folded and Visual highlights are combined #19691', function()
- command('hi! Visual guibg=Red')
+ command('hi! Visual guifg=NONE guibg=Red')
insert([[
" foofoofoofoofoofoo
" å£ {{{1
@@ -2640,13 +2271,7 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{14:" foofoofoofoofo}ofoo |
@@ -2654,8 +2279,7 @@ describe("folded lines", function()
{14:" barbarbarbarba}rbar |
{15:+-- 3 lines: " }{5:å£Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·}|
{14:" bazbazbazbazb}^azbaz |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
{11:-- VISUAL BLOCK --} |
]])
@@ -2666,8 +2290,7 @@ describe("folded lines", function()
{14:" barbarbarbarba}rbar |
{15:+-- 3 lines: " }{5:å£Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·Â·}|
{14:" bazbazbazbazb}^azbaz |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{11:-- VISUAL BLOCK --} |
]])
end
@@ -2676,13 +2299,7 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{14:" foofoofoofoofoo}foo |
@@ -2690,8 +2307,7 @@ describe("folded lines", function()
{14:" barbarbarbarbar}bar |
{15:+-- 3 lines: " å£}{5:···························}|
{14:" bazbazbazbazba}^zbaz |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
{11:-- VISUAL BLOCK --} |
]])
@@ -2702,8 +2318,7 @@ describe("folded lines", function()
{14:" barbarbarbarbar}bar |
{15:+-- 3 lines: " å£}{5:···························}|
{14:" bazbazbazbazba}^zbaz |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{11:-- VISUAL BLOCK --} |
]])
end
@@ -2712,13 +2327,7 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{14:" foofoofoofoofoof}oo |
@@ -2726,8 +2335,7 @@ describe("folded lines", function()
{14:" barbarbarbarbarb}ar |
{15:+-- 3 lines: " å£}{5:···························}|
{14:" bazbazbazbazbaz}^baz |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
{11:-- VISUAL BLOCK --} |
]])
@@ -2738,8 +2346,7 @@ describe("folded lines", function()
{14:" barbarbarbarbarb}ar |
{15:+-- 3 lines: " å£}{5:···························}|
{14:" bazbazbazbazbaz}^baz |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{11:-- VISUAL BLOCK --} |
]])
end
@@ -2748,13 +2355,7 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{14:" foofoofoofoofoofoo} |
@@ -2762,8 +2363,7 @@ describe("folded lines", function()
{14:" barbarbarbarbarbar} |
{15:+-- 3 lines: " å£Â·Â·}{5:·························}|
{14:" bazbazbazbazbazba}^z |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
{11:-- VISUAL BLOCK --} |
]])
@@ -2774,8 +2374,7 @@ describe("folded lines", function()
{14:" barbarbarbarbarbar} |
{15:+-- 3 lines: " å£Â·Â·}{5:·························}|
{14:" bazbazbazbazbazba}^z |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{11:-- VISUAL BLOCK --} |
]])
end
@@ -2784,13 +2383,7 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
" foofoofoofoofo{14:ofoo} |
@@ -2798,8 +2391,7 @@ describe("folded lines", function()
" barbarbarbarba{14:rbar} |
{5:+-- 3 lines: " }{15:å£Â·Â·}{5:·························}|
" bazbazbazbazba^z{14:baz} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
{11:-- VISUAL BLOCK --} |
]])
@@ -2810,8 +2402,7 @@ describe("folded lines", function()
" barbarbarbarba{14:rbar} |
{5:+-- 3 lines: " }{15:å£Â·Â·}{5:·························}|
" bazbazbazbazba^z{14:baz} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{11:-- VISUAL BLOCK --} |
]])
end
@@ -2820,13 +2411,7 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
" foofoofoofoofoo{14:foo} |
@@ -2834,8 +2419,7 @@ describe("folded lines", function()
" barbarbarbarbar{14:bar} |
{5:+-- 3 lines: " }{15:å£Â·Â·}{5:·························}|
" bazbazbazbazbaz^b{14:az} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
{11:-- VISUAL BLOCK --} |
]])
@@ -2846,8 +2430,7 @@ describe("folded lines", function()
" barbarbarbarbar{14:bar} |
{5:+-- 3 lines: " }{15:å£Â·Â·}{5:·························}|
" bazbazbazbazbaz^b{14:az} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{11:-- VISUAL BLOCK --} |
]])
end
@@ -2864,22 +2447,13 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{2:line} 1 |
{5:+-- 2 lines: line 2·························}|
{6:line} 4 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
/line^ |
]])
@@ -2888,34 +2462,22 @@ describe("folded lines", function()
{2:line} 1 |
{5:+-- 2 lines: line 2·························}|
{6:line} 4 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
/line^ |
]])
end
feed('<Esc>')
- funcs.matchadd('Search', 'line')
+ fn.matchadd('Search', 'line')
if multigrid then
screen:expect([[
## grid 1
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
- [2:---------------------------------------------]|
+ [2:---------------------------------------------]|*7
[3:---------------------------------------------]|
## grid 2
{6:line} 1 |
{5:+-- 2 lines: line 2·························}|
{6:line} ^4 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
]])
@@ -2924,28 +2486,29 @@ describe("folded lines", function()
{6:line} 1 |
{5:+-- 2 lines: line 2·························}|
{6:line} ^4 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
end
end)
- it('support foldtext with virtual text format', function()
+ it('foldtext with virtual text format', function()
screen:try_resize(30, 7)
insert(content1)
- command("hi! CursorLine guibg=NONE guifg=Red gui=NONE")
+ command('hi! CursorLine guibg=NONE guifg=Red gui=NONE')
command('hi F0 guibg=Red guifg=Black')
command('hi F1 guifg=White')
- meths.set_option_value('cursorline', true, {})
- meths.set_option_value('foldcolumn', '4', {})
- meths.set_option_value('foldtext', '['
- .. '["â–¶", ["F0", "F1"]], '
- .. '[v:folddashes], '
- .. '["\t", "Search"], '
- .. '[getline(v:foldstart), "NonText"]]', {})
+ api.nvim_set_option_value('cursorline', true, {})
+ api.nvim_set_option_value('foldcolumn', '4', {})
+ api.nvim_set_option_value(
+ 'foldtext',
+ '['
+ .. '["â–¶", ["F0", "F1"]], '
+ .. '[v:folddashes], '
+ .. '["\t", "Search"], '
+ .. '[getline(v:foldstart), "NonText"]]',
+ {}
+ )
command('3,4fold')
command('5,6fold')
@@ -2953,20 +2516,12 @@ describe("folded lines", function()
if multigrid then
screen:expect([[
## grid 1
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
+ [2:------------------------------]|*6
[3:------------------------------]|
## grid 2
{7: }This is a |
{7:+ }{4:^▶}{13:-}{17: }{18:valid English}{13:·····}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
]])
@@ -2974,33 +2529,24 @@ describe("folded lines", function()
screen:expect([[
{7: }This is a |
{7:+ }{4:^▶}{13:-}{17: }{18:valid English}{13:·····}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
end
- eq('â–¶-\tvalid English', funcs.foldtextresult(2))
+ eq('â–¶-\tvalid English', fn.foldtextresult(2))
feed('zo')
if multigrid then
screen:expect([[
## grid 1
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
+ [2:------------------------------]|*6
[3:------------------------------]|
## grid 2
{7: }This is a |
{7:- }valid English |
{7:│+ }{4:▶}{5:--}{19: }{18:sentence composed }|
{7:│+ }{4:^▶}{13:--}{17: }{18:in his cave.}{13:······}|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
|
]])
@@ -3010,33 +2556,26 @@ describe("folded lines", function()
{7:- }valid English |
{7:│+ }{4:▶}{5:--}{19: }{18:sentence composed }|
{7:│+ }{4:^▶}{13:--}{17: }{18:in his cave.}{13:······}|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
end
- eq('â–¶--\tsentence composed by', funcs.foldtextresult(3))
- eq('â–¶--\tin his cave.', funcs.foldtextresult(5))
+ eq('â–¶--\tsentence composed by', fn.foldtextresult(3))
+ eq('â–¶--\tin his cave.', fn.foldtextresult(5))
- command('hi! Visual guibg=Red')
+ command('hi! Visual guifg=NONE guibg=Red')
feed('V2k')
if multigrid then
screen:expect([[
## grid 1
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
+ [2:------------------------------]|*6
[3:------------------------------]|
## grid 2
{7: }This is a |
{7:- }^v{14:alid English} |
{7:│+ }{4:▶}{15:--}{19: }{20:sentence composed }|
{7:│+ }{4:▶}{15:--}{19: }{20:in his cave.}{15:······}|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
{11:-- VISUAL LINE --} |
]])
@@ -3046,30 +2585,23 @@ describe("folded lines", function()
{7:- }^v{14:alid English} |
{7:│+ }{4:▶}{15:--}{19: }{20:sentence composed }|
{7:│+ }{4:▶}{15:--}{19: }{20:in his cave.}{15:······}|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{11:-- VISUAL LINE --} |
]])
end
- meths.set_option_value('rightleft', true, {})
+ api.nvim_set_option_value('rightleft', true, {})
if multigrid then
screen:expect([[
## grid 1
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
- [2:------------------------------]|
+ [2:------------------------------]|*6
[3:------------------------------]|
## grid 2
a si sihT{7: }|
{14:hsilgnE dila}^v{7: -}|
{20: desopmoc ecnetnes}{19: }{15:--}{4:▶}{7: +│}|
{15:······}{20:.evac sih ni}{19: }{15:--}{4:▶}{7: +│}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*2
## grid 3
{11:-- VISUAL LINE --} |
]])
@@ -3079,15 +2611,128 @@ describe("folded lines", function()
{14:hsilgnE dila}^v{7: -}|
{20: desopmoc ecnetnes}{19: }{15:--}{4:▶}{7: +│}|
{15:······}{20:.evac sih ni}{19: }{15:--}{4:▶}{7: +│}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*2
+ {11:-- VISUAL LINE --} |
+ ]])
+ end
+ end)
+
+ it('transparent foldtext', function()
+ screen:try_resize(30, 7)
+ insert(content1)
+ command('hi! CursorLine guibg=NONE guifg=Red gui=NONE')
+ command('hi F0 guibg=Red guifg=Black')
+ command('hi F1 guifg=White')
+ api.nvim_set_option_value('cursorline', true, {})
+ api.nvim_set_option_value('foldcolumn', '4', {})
+ api.nvim_set_option_value('foldtext', '', {})
+
+ command('3,4fold')
+ command('5,6fold')
+ command('2,6fold')
+ if multigrid then
+ screen:expect([[
+ ## grid 1
+ [2:------------------------------]|*6
+ [3:------------------------------]|
+ ## grid 2
+ {7: }This is a |
+ {7:+ }{13:^valid English·············}|
+ {1:~ }|*4
+ ## grid 3
+ |
+ ]])
+ else
+ screen:expect([[
+ {7: }This is a |
+ {7:+ }{13:^valid English·············}|
+ {1:~ }|*4
+ |
+ ]])
+ end
+
+ feed('zo')
+ if multigrid then
+ screen:expect([[
+ ## grid 1
+ [2:------------------------------]|*6
+ [3:------------------------------]|
+ ## grid 2
+ {7: }This is a |
+ {7:- }valid English |
+ {7:│+ }{5:sentence composed by······}|
+ {7:│+ }{13:^in his cave.··············}|
+ {1:~ }|*2
+ ## grid 3
+ |
+ ]])
+ else
+ screen:expect([[
+ {7: }This is a |
+ {7:- }valid English |
+ {7:│+ }{5:sentence composed by······}|
+ {7:│+ }{13:^in his cave.··············}|
+ {1:~ }|*2
+ |
+ ]])
+ end
+
+ command('hi! Visual guifg=NONE guibg=Red')
+ feed('V2k')
+ if multigrid then
+ screen:expect([[
+ ## grid 1
+ [2:------------------------------]|*6
+ [3:------------------------------]|
+ ## grid 2
+ {7: }This is a |
+ {7:- }^v{14:alid English} |
+ {7:│+ }{15:sentence composed by······}|
+ {7:│+ }{15:in his cave.··············}|
+ {1:~ }|*2
+ ## grid 3
+ {11:-- VISUAL LINE --} |
+ ]])
+ else
+ screen:expect([[
+ {7: }This is a |
+ {7:- }^v{14:alid English} |
+ {7:│+ }{15:sentence composed by······}|
+ {7:│+ }{15:in his cave.··············}|
+ {1:~ }|*2
+ {11:-- VISUAL LINE --} |
+ ]])
+ end
+
+ api.nvim_set_option_value('rightleft', true, {})
+ if multigrid then
+ screen:expect([[
+ ## grid 1
+ [2:------------------------------]|*6
+ [3:------------------------------]|
+ ## grid 2
+ a si sihT{7: }|
+ {14:hsilgnE dila}^v{7: -}|
+ {15:······yb desopmoc ecnetnes}{7: +│}|
+ {15:··············.evac sih ni}{7: +│}|
+ {1: ~}|*2
+ ## grid 3
+ {11:-- VISUAL LINE --} |
+ ]])
+ else
+ screen:expect([[
+ a si sihT{7: }|
+ {14:hsilgnE dila}^v{7: -}|
+ {15:······yb desopmoc ecnetnes}{7: +│}|
+ {15:··············.evac sih ni}{7: +│}|
+ {1: ~}|*2
{11:-- VISUAL LINE --} |
]])
end
end)
end
- describe("with ext_multigrid", function()
+ describe('with ext_multigrid', function()
with_ext_multigrid(true)
end)
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 7776e024b0..727dc38829 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -5,9 +5,8 @@ local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command, exec = helpers.command, helpers.exec
local eval = helpers.eval
local feed_command, eq = helpers.feed_command, helpers.eq
-local curbufmeths = helpers.curbufmeths
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local exec_lua = helpers.exec_lua
describe('colorscheme compatibility', function()
@@ -16,8 +15,8 @@ describe('colorscheme compatibility', function()
end)
it('&t_Co exists and is set to 256 by default', function()
- eq(1, funcs.exists('&t_Co'))
- eq(1, funcs.exists('+t_Co'))
+ eq(1, fn.exists('&t_Co'))
+ eq(1, fn.exists('+t_Co'))
eq('256', eval('&t_Co'))
end)
end)
@@ -30,13 +29,14 @@ describe('highlight: `:syntax manual`', function()
before_each(function()
clear()
- screen = Screen.new(20,5)
+ screen = Screen.new(20, 5)
screen:attach()
- --syntax highlight for vimcscripts "echo"
- screen:set_default_attr_ids( {
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {bold=true, foreground=Screen.colors.Brown}
- } )
+ -- syntax highlight for vimscript's "echo"
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { bold = true, foreground = Screen.colors.Brown },
+ [2] = { foreground = Screen.colors.Magenta1 },
+ })
end)
after_each(function()
@@ -57,10 +57,8 @@ describe('highlight: `:syntax manual`', function()
command('bn')
feed_command('bp')
screen:expect([[
- {1:^echo} 1 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {1:^echo} {2:1} |
+ {0:~ }|*3
:bp |
]])
end)
@@ -77,20 +75,17 @@ describe('highlight: `:syntax manual`', function()
command('set nohidden')
command('w')
command('silent bn')
- eq("tmp1.vim", eval("fnamemodify(bufname('%'), ':t')"))
+ eq('tmp1.vim', eval("fnamemodify(bufname('%'), ':t')"))
feed_command('silent bp')
- eq("Xtest-functional-ui-highlight.tmp.vim", eval("fnamemodify(bufname('%'), ':t')"))
+ eq('Xtest-functional-ui-highlight.tmp.vim', eval("fnamemodify(bufname('%'), ':t')"))
screen:expect([[
- {1:^echo} 1 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {1:^echo} {2:1} |
+ {0:~ }|*3
:silent bp |
]])
end)
end)
-
describe('highlight defaults', function()
local screen
@@ -98,16 +93,16 @@ describe('highlight defaults', function()
clear()
screen = Screen.new()
screen:set_default_attr_ids {
- [0] = {bold=true, foreground=Screen.colors.Blue};
- [1] = {reverse = true, bold = true};
- [2] = {reverse = true};
- [3] = {bold = true};
- [4] = {bold = true, foreground = Screen.colors.SeaGreen};
- [5] = {foreground = Screen.colors.Red1, background = Screen.colors.WebGreen};
- [6] = {background = Screen.colors.Red1, foreground = Screen.colors.Grey100};
- [7] = {foreground = Screen.colors.Red};
- [8] = {foreground = Screen.colors.Blue};
- [9] = {italic = true};
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { reverse = true, bold = true },
+ [2] = { reverse = true },
+ [3] = { bold = true },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [5] = { foreground = Screen.colors.Red1, background = Screen.colors.WebGreen },
+ [6] = { background = Screen.colors.Red1, foreground = Screen.colors.Grey100 },
+ [7] = { foreground = Screen.colors.Red },
+ [8] = { foreground = Screen.colors.Blue },
+ [9] = { italic = true },
}
screen:attach()
end)
@@ -116,17 +111,10 @@ describe('highlight defaults', function()
feed_command('sp', 'vsp', 'vsp')
screen:expect([[
^ │ │ |
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
+ {0:~ }│{0:~ }│{0:~ }|*5
{1:[No Name] }{2:[No Name] [No Name] }|
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:[No Name] }|
:vsp |
]])
@@ -134,17 +122,10 @@ describe('highlight defaults', function()
feed('<c-w>j')
screen:expect([[
│ │ |
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
+ {0:~ }│{0:~ }│{0:~ }|*5
{2:[No Name] [No Name] [No Name] }|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{1:[No Name] }|
:vsp |
]])
@@ -154,51 +135,30 @@ describe('highlight defaults', function()
feed('<c-w>k<c-w>l')
screen:expect([[
│^ │ |
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
+ {0:~ }│{0:~ }│{0:~ }|*5
{2:[No Name] }{1:[No Name] }{2:[No Name] }|
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:[No Name] }|
:vsp |
]])
feed('<c-w>l')
screen:expect([[
│ │^ |
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
+ {0:~ }│{0:~ }│{0:~ }|*5
{2:[No Name] [No Name] }{1:[No Name] }|
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:[No Name] }|
:vsp |
]])
feed('<c-w>h<c-w>h')
screen:expect([[
^ │ │ |
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
+ {0:~ }│{0:~ }│{0:~ }|*5
{1:[No Name] }{2:[No Name] [No Name] }|
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{2:[No Name] }|
:vsp |
]])
@@ -209,8 +169,7 @@ describe('highlight defaults', function()
screen:try_resize(53, 4)
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:-- INSERT --} |
]])
end)
@@ -219,8 +178,7 @@ describe('highlight defaults', function()
screen:try_resize(53, 4)
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
@@ -243,8 +201,7 @@ describe('highlight defaults', function()
feed('i')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
-- INSERT -- |
]])
feed('<esc>')
@@ -253,8 +210,7 @@ describe('highlight defaults', function()
feed('i')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{5:-- INSERT --} |
]])
end)
@@ -266,16 +222,16 @@ describe('highlight defaults', function()
insert('neovim')
screen:expect([[
{6:neovi^m} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
- feed_command("hi ErrorMsg term=NONE cterm=NONE ctermfg=NONE ctermbg=NONE"
- .. " gui=NONE guifg=NONE guibg=NONE guisp=NONE")
+ feed_command(
+ 'hi ErrorMsg term=NONE cterm=NONE ctermfg=NONE ctermbg=NONE'
+ .. ' gui=NONE guifg=NONE guibg=NONE guisp=NONE'
+ )
screen:expect([[
neovi^m |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
@@ -284,18 +240,19 @@ describe('highlight defaults', function()
screen:try_resize(53, 4)
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
- feed_command("hi NonTextAlt guifg=Red")
- feed_command("hi! link NonText NonTextAlt")
- screen:expect([[
+ feed_command('hi NonTextAlt guifg=Red')
+ feed_command('hi! link NonText NonTextAlt')
+ screen:expect(
+ [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:hi! link NonText NonTextAlt |
- ]], {[0] = {foreground=Screen.colors.Red}})
+ ]],
+ { [0] = { foreground = Screen.colors.Red } }
+ )
end)
it('Cursor after `:hi clear|syntax reset` #6508', function()
@@ -310,90 +267,199 @@ describe('highlight defaults', function()
insert(' ne \t o\tv im ')
screen:expect([[
ne{7:.>----.}o{7:>-----}v{7:..}im{7:*^*¬} |
- {7:~ }|
- {7:~ }|
+ {7:~ }|*2
|
]])
feed_command('highlight Whitespace gui=NONE guifg=#0000FF')
screen:expect([[
ne{8:.>----.}o{8:>-----}v{8:..}im{8:*^*}{7:¬} |
- {7:~ }|
- {7:~ }|
+ {7:~ }|*2
:highlight Whitespace gui=NONE guifg=#0000FF |
]])
end)
it('are sent to UIs', function()
screen:try_resize(53, 4)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], hl_groups={EndOfBuffer=0, MsgSeparator=1}}
+ ]],
+ hl_groups = { EndOfBuffer = 0, MsgSeparator = 1 },
+ }
command('highlight EndOfBuffer gui=italic')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {9:~ }|
- {9:~ }|
+ {9:~ }|*2
|
- ]], hl_groups={EndOfBuffer=9, MsgSeparator=1}}
+ ]],
+ hl_groups = { EndOfBuffer = 9, MsgSeparator = 1 },
+ }
command('highlight clear EndOfBuffer')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], hl_groups={EndOfBuffer=0, MsgSeparator=1}}
+ ]],
+ hl_groups = { EndOfBuffer = 0, MsgSeparator = 1 },
+ }
end)
end)
describe('highlight', function()
before_each(clear)
- it('visual', function()
- local screen = Screen.new(20,4)
+ it('Visual', function()
+ local screen = Screen.new(45, 5)
screen:attach()
screen:set_default_attr_ids({
- [1] = {background = Screen.colors.LightGrey},
- [2] = {bold = true, foreground = Screen.colors.Blue1},
- [3] = {bold = true},
+ [1] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey },
+ [2] = { bold = true, foreground = Screen.colors.Blue },
+ [3] = { bold = true },
+ [4] = { reverse = true, bold = true },
+ [5] = { reverse = true },
+ [6] = { background = Screen.colors.Grey90 },
})
insert([[
line1 foo bar
+ abcdefghijklmnopqrs
+ ABCDEFGHIJKLMNOPQRS
]])
+ feed('gg')
+ command('vsplit')
-- Non-blinking block cursor: does NOT highlight char-at-cursor.
command('set guicursor=a:block-blinkon0')
- feed('gg$vhhh')
+ feed('V')
screen:expect([[
- line1 foo^ {1:bar} |
- |
- {2:~ }|
- {3:-- VISUAL --} |
+ {1: }^l{1:ine1 foo bar} │{1: line1 foo bar} |
+ abcdefghijklmnopqrs │abcdefghijklmnopqrs |
+ ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL LINE --} |
+ ]])
+
+ feed('<Esc>$vhhh')
+ screen:expect([[
+ line1 foo^ {1:bar} │ line1 foo{1: bar} |
+ abcdefghijklmnopqrs │abcdefghijklmnopqrs |
+ ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL --} |
]])
-- Vertical cursor: highlights char-at-cursor. #8983
command('set guicursor=a:block-blinkon175')
screen:expect([[
- line1 foo{1:^ bar} |
- |
- {2:~ }|
- {3:-- VISUAL --} |
+ line1 foo{1:^ bar} │ line1 foo{1: bar} |
+ abcdefghijklmnopqrs │abcdefghijklmnopqrs |
+ ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL --} |
+ ]])
+
+ command('set selection=exclusive')
+ screen:expect([[
+ line1 foo{1:^ ba}r │ line1 foo{1: ba}r |
+ abcdefghijklmnopqrs │abcdefghijklmnopqrs |
+ ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL --} |
+ ]])
+
+ feed('o')
+ screen:expect([[
+ line1 foo{1: ba}^r │ line1 foo{1: ba}r |
+ abcdefghijklmnopqrs │abcdefghijklmnopqrs |
+ ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL --} |
+ ]])
+
+ feed('V')
+ screen:expect([[
+ {1: line1 foo ba^r} │{1: line1 foo bar} |
+ abcdefghijklmnopqrs │abcdefghijklmnopqrs |
+ ABCDEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL LINE --} |
+ ]])
+
+ command('set cursorcolumn')
+ feed('<C-V>')
+ screen:expect([[
+ line1 foo{1: ba}^r │ line1 foo{1: ba}r |
+ abcdefghijklmn{6:o}pqrs │abcdefghijklmnopqrs |
+ ABCDEFGHIJKLMN{6:O}PQRS │ABCDEFGHIJKLMNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL BLOCK --} |
+ ]])
+
+ command('set selection&')
+ screen:expect([[
+ line1 foo{1: ba^r} │ line1 foo{1: bar} |
+ abcdefghijklmn{6:o}pqrs │abcdefghijklmnopqrs |
+ ABCDEFGHIJKLMN{6:O}PQRS │ABCDEFGHIJKLMNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL BLOCK --} |
+ ]])
+
+ feed('^')
+ screen:expect([[
+ {1:^line1 foo }bar │ {1:line1 foo }bar |
+ ab{6:c}defghijklmnopqrs │abcdefghijklmnopqrs |
+ AB{6:C}DEFGHIJKLMNOPQRS │ABCDEFGHIJKLMNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL BLOCK --} |
+ ]])
+
+ feed('2j')
+ screen:expect([[
+ {1:line1 foo }bar │ {1:line1 foo }bar |
+ ab{1:cdefghijkl}mnopqrs │ab{1:cdefghijkl}mnopqrs |
+ AB{1:^CDEFGHIJKL}MNOPQRS │AB{1:CDEFGHIJKL}MNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL BLOCK --} |
+ ]])
+
+ command('set nocursorcolumn')
+ feed('O')
+ screen:expect([[
+ {1:line1 foo }bar │ {1:line1 foo }bar |
+ ab{1:cdefghijkl}mnopqrs │ab{1:cdefghijkl}mnopqrs |
+ AB{1:CDEFGHIJK^L}MNOPQRS │AB{1:CDEFGHIJKL}MNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL BLOCK --} |
+ ]])
+
+ command('set selection=exclusive')
+ screen:expect([[
+ {1:line1 foo} bar │ {1:line1 foo} bar |
+ ab{1:cdefghijk}lmnopqrs │ab{1:cdefghijk}lmnopqrs |
+ AB{1:CDEFGHIJK}^LMNOPQRS │AB{1:CDEFGHIJK}LMNOPQRS |
+ {4:[No Name] [+] }{5:[No Name] [+] }|
+ {3:-- VISUAL BLOCK --} |
]])
end)
it('cterm=standout gui=standout', function()
- local screen = Screen.new(20,5)
+ local screen = Screen.new(20, 5)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {standout = true, bold = true, underline = true,
- background = Screen.colors.Gray90, foreground = Screen.colors.Blue1},
- [3] = {standout = true, underline = true,
- background = Screen.colors.Gray90}
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = {
+ standout = true,
+ bold = true,
+ underline = true,
+ background = Screen.colors.Gray90,
+ foreground = Screen.colors.Blue1,
+ },
+ [3] = { standout = true, underline = true, background = Screen.colors.Gray90 },
})
feed_command('hi CursorLine cterm=standout,underline gui=standout,underline')
feed_command('set cursorline')
@@ -409,7 +475,7 @@ describe('highlight', function()
end)
it('strikethrough', function()
- local screen = Screen.new(25,6)
+ local screen = Screen.new(25, 6)
screen:attach()
feed_command('syntax on')
feed_command('syn keyword TmpKeyword foo')
@@ -420,27 +486,34 @@ describe('highlight', function()
foo bar
foobarfoobar
]])
- screen:expect([[
+ screen:expect(
+ [[
{1:foo} |
{1:foo} bar |
foobarfoobar |
^ |
{2:~ }|
|
- ]], {
- [1] = {strikethrough = true},
- [2] = {bold = true, foreground = Screen.colors.Blue1},
- })
+ ]],
+ {
+ [1] = { strikethrough = true },
+ [2] = { bold = true, foreground = Screen.colors.Blue1 },
+ }
+ )
end)
it('nocombine', function()
- local screen = Screen.new(25,6)
- screen:set_default_attr_ids{
- [1] = {foreground = Screen.colors.SlateBlue, underline = true},
- [2] = {bold = true, foreground = Screen.colors.Blue1},
- [3] = {underline = true, reverse = true, foreground = Screen.colors.SlateBlue},
- [4] = {background = Screen.colors.Yellow, reverse = true, foreground = Screen.colors.SlateBlue},
- [5] = {foreground = Screen.colors.Red},
+ local screen = Screen.new(25, 6)
+ screen:set_default_attr_ids {
+ [1] = { foreground = Screen.colors.SlateBlue, underline = true },
+ [2] = { bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { underline = true, reverse = true, foreground = Screen.colors.SlateBlue },
+ [4] = {
+ background = Screen.colors.Yellow,
+ reverse = true,
+ foreground = Screen.colors.SlateBlue,
+ },
+ [5] = { foreground = Screen.colors.Red },
}
screen:attach()
feed_command('syntax on')
@@ -451,37 +524,39 @@ describe('highlight', function()
foobar
foobar
]])
- screen:expect{grid=[[
- {1:foobar} |
- {1:foobar} |
+ screen:expect {
+ grid = [[
+ {1:foobar} |*2
^ |
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
|
- ]]}
+ ]],
+ }
feed('/foo')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:foo}{1:bar} |
{4:foo}{1:bar} |
|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
/foo^ |
- ]]}
+ ]],
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{4:^foo}{1:bar} |
{4:foo}{1:bar} |
|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
{5:search hit...uing at TOP} |
- ]]}
+ ]],
+ }
end)
it('guisp (special/undercurl)', function()
- local screen = Screen.new(25,10)
+ local screen = Screen.new(25, 10)
screen:attach()
feed_command('syntax on')
feed_command('syn keyword TmpKeyword neovim')
@@ -505,7 +580,8 @@ describe('highlight', function()
specialwithfg
]])
feed('Go<tab>neovim tabbed')
- screen:expect([[
+ screen:expect(
+ [[
{1:neovim} |
awesome {1:neovim} |
wordcontainingneovim |
@@ -516,20 +592,24 @@ describe('highlight', function()
{1:neovim} tabbed^ |
{0:~ }|
{5:-- INSERT --} |
- ]], {
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {background = Screen.colors.Yellow, foreground = Screen.colors.Red,
- special = Screen.colors.Red},
- [2] = {special = Screen.colors.Red},
- [3] = {special = Screen.colors.Red, background = Screen.colors.Yellow},
- [4] = {foreground = Screen.colors.Red, special = Screen.colors.Red},
- [5] = {bold=true},
- })
-
+ ]],
+ {
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = {
+ background = Screen.colors.Yellow,
+ foreground = Screen.colors.Red,
+ special = Screen.colors.Red,
+ },
+ [2] = { special = Screen.colors.Red },
+ [3] = { special = Screen.colors.Red, background = Screen.colors.Yellow },
+ [4] = { foreground = Screen.colors.Red, special = Screen.colors.Red },
+ [5] = { bold = true },
+ }
+ )
end)
it("'diff', syntax and extmark #23722", function()
- local screen = Screen.new(25,10)
+ local screen = Screen.new(25, 10)
screen:attach()
exec([[
new
@@ -539,28 +619,34 @@ describe('highlight', function()
syn match WarningMsg "^.*$"
call nvim_buf_add_highlight(0, -1, 'ErrorMsg', 1, 2, 8)
]])
- screen:expect([[
+ screen:expect(
+ [[
{1: }^ |
{1: }{2:01}{3:234 67}{2:89}{5: }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{7:[No Name] [+] }|
{1: } |
{1: }{6:-----------------------}|
{4:~ }|
{8:[No Name] }|
|
- ]], {
- [0] = {Screen.colors.WebGray, foreground = Screen.colors.DarkBlue},
- [1] = {background = Screen.colors.Grey, foreground = Screen.colors.Blue4},
- [2] = {foreground = Screen.colors.Red, background = Screen.colors.LightBlue},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.LightBlue},
- [4] = {bold = true, foreground = Screen.colors.Blue},
- [5] = {background = Screen.colors.LightBlue},
- [6] = {bold = true, background = Screen.colors.LightCyan, foreground = Screen.colors.Blue1},
- [7] = {reverse = true, bold = true},
- [8] = {reverse = true},
- })
+ ]],
+ {
+ [0] = { Screen.colors.WebGray, foreground = Screen.colors.DarkBlue },
+ [1] = { background = Screen.colors.Grey, foreground = Screen.colors.Blue4 },
+ [2] = { foreground = Screen.colors.Red, background = Screen.colors.LightBlue },
+ [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.LightBlue },
+ [4] = { bold = true, foreground = Screen.colors.Blue },
+ [5] = { background = Screen.colors.LightBlue },
+ [6] = {
+ bold = true,
+ background = Screen.colors.LightCyan,
+ foreground = Screen.colors.Blue1,
+ },
+ [7] = { reverse = true, bold = true },
+ [8] = { reverse = true },
+ }
+ )
end)
end)
@@ -569,62 +655,55 @@ describe("'listchars' highlight", function()
before_each(function()
clear()
- screen = Screen.new(20,5)
+ screen = Screen.new(20, 5)
screen:attach()
end)
it("'cursorline' and 'cursorcolumn'", function()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {background=Screen.colors.Grey90}
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { background = Screen.colors.Grey90 },
})
feed_command('highlight clear ModeMsg')
feed_command('set cursorline')
feed('i')
screen:expect([[
{1:^ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
-- INSERT -- |
]])
feed('abcdefg<cr>kkasdf')
screen:expect([[
abcdefg |
{1:kkasdf^ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
-- INSERT -- |
]])
feed('<esc>')
screen:expect([[
abcdefg |
{1:kkasd^f }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed_command('set nocursorline')
screen:expect([[
abcdefg |
kkasd^f |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:set nocursorline |
]])
feed('k')
screen:expect([[
abcde^fg |
kkasdf |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:set nocursorline |
]])
feed('jjji<cr><cr><cr><esc>')
screen:expect([[
kkasd |
- |
- |
+ |*2
^f |
|
]])
@@ -650,22 +729,22 @@ describe("'listchars' highlight", function()
it("'cursorline' and with 'listchars' option", function()
screen:set_default_attr_ids({
- [1] = {background=Screen.colors.Grey90},
+ [1] = { background = Screen.colors.Grey90 },
[2] = {
- foreground=Screen.colors.Red,
- background=Screen.colors.Grey90,
+ foreground = Screen.colors.Red,
+ background = Screen.colors.Grey90,
},
[3] = {
- background=Screen.colors.Grey90,
- foreground=Screen.colors.Blue,
- bold=true,
+ background = Screen.colors.Grey90,
+ foreground = Screen.colors.Blue,
+ bold = true,
},
[4] = {
- foreground=Screen.colors.Blue,
- bold=true,
+ foreground = Screen.colors.Blue,
+ bold = true,
},
[5] = {
- foreground=Screen.colors.Red,
+ foreground = Screen.colors.Red,
},
})
feed_command('highlight clear ModeMsg')
@@ -717,8 +796,7 @@ describe("'listchars' highlight", function()
feed('$')
screen:expect([[
{3:<}{1:r}{2:.}{1:sit}{2:.}{1:ame^t}{3:¬}{1: }|
- {4:<} |
- {4:<} |
+ {4:<} |*2
{4:~ }|
:set cursorline |
]])
@@ -734,66 +812,42 @@ describe("'listchars' highlight", function()
it("'listchar' with wrap", function()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
})
feed_command('set wrap')
feed_command('set listchars=eol:¬,precedes:< list')
feed('90ia<esc>')
screen:expect([[
{0:<}aaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaa|*2
aaaaaaaaa^a{0:¬} |
|
]])
feed('0')
screen:expect([[
^aaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaa|*3
|
]])
end)
it("'listchar' in visual mode", function()
screen:set_default_attr_ids({
- [1] = {background=Screen.colors.Grey90},
- [2] = {
- foreground=Screen.colors.Red,
- background=Screen.colors.Grey90,
- },
- [3] = {
- background=Screen.colors.Grey90,
- foreground=Screen.colors.Blue,
- bold=true,
- },
- [4] = {
- foreground=Screen.colors.Blue,
- bold=true,
- },
- [5] = {
- foreground=Screen.colors.Red,
- },
- [6] = {
- background=Screen.colors.LightGrey,
- },
- [7] = {
- background=Screen.colors.LightGrey,
- foreground=Screen.colors.Red,
- },
- [8] = {
- background=Screen.colors.LightGrey,
- foreground=Screen.colors.Blue,
- bold=true,
- },
+ [1] = { background = Screen.colors.Grey90 },
+ [2] = { foreground = Screen.colors.Red, background = Screen.colors.Grey90 },
+ [3] = { background = Screen.colors.Grey90, foreground = Screen.colors.Blue, bold = true },
+ [4] = { foreground = Screen.colors.Blue, bold = true },
+ [5] = { foreground = Screen.colors.Red },
+ [6] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black },
+ [7] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Red },
+ [8] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Blue, bold = true },
})
- feed_command('highlight clear ModeMsg')
- feed_command('highlight Whitespace guifg=#FF0000')
- feed_command('set cursorline')
- feed_command('set tabstop=8')
- feed_command('set nowrap')
- feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
+ command('highlight clear ModeMsg')
+ command('highlight Whitespace guifg=#FF0000')
+ command('set cursorline')
+ command('set tabstop=8')
+ command('set nowrap')
+ command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
feed('i\t abcd <cr>\t abcd Lorem ipsum dolor sit amet<cr><esc>kkk0')
screen:expect([[
{2:^>-------.}{1:abcd}{2:*}{3:¬}{1: }|
@@ -830,10 +884,10 @@ describe("'listchars' highlight", function()
it("'cursorline' with :match", function()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {background=Screen.colors.Grey90},
- [2] = {foreground=Screen.colors.Red},
- [3] = {foreground=Screen.colors.X11Green, background=Screen.colors.Red1},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { background = Screen.colors.Grey90 },
+ [2] = { foreground = Screen.colors.Red },
+ [3] = { foreground = Screen.colors.X11Green, background = Screen.colors.Red1 },
})
feed_command('highlight clear ModeMsg')
feed_command('highlight Whitespace guifg=#FF0000')
@@ -842,25 +896,19 @@ describe("'listchars' highlight", function()
feed('ia \t bc \t <esc>')
screen:expect([[
a bc ^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
feed_command('set listchars=space:.,eol:¬,tab:>-,extends:>,precedes:<,trail:* list')
screen:expect([[
a{2:.>-----.}bc{2:*>---*^*}{0:¬} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
feed_command('match Error /\\s\\+$/')
screen:expect([[
a{2:.>-----.}bc{3:*>---*^*}{0:¬} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
end)
@@ -870,15 +918,15 @@ describe('CursorLine and CursorLineNr highlights', function()
before_each(clear)
it('overridden by Error, ColorColumn if fg not set', function()
- local screen = Screen.new(50,5)
+ local screen = Screen.new(50, 5)
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.SlateBlue},
- [2] = {bold = true, foreground = Screen.colors.Brown},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [4] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.Gray90},
- [5] = {background = Screen.colors.Gray90},
- [6] = {bold = true, foreground = Screen.colors.Blue1},
- [7] = {background = Screen.colors.LightRed},
+ [1] = { foreground = Screen.colors.SlateBlue },
+ [2] = { bold = true, foreground = Screen.colors.Brown },
+ [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [4] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Gray90 },
+ [5] = { background = Screen.colors.Gray90 },
+ [6] = { bold = true, foreground = Screen.colors.Blue1 },
+ [7] = { background = Screen.colors.LightRed },
})
screen:attach()
@@ -906,12 +954,12 @@ describe('CursorLine and CursorLineNr highlights', function()
end)
it("overridden by NonText in 'showbreak' characters", function()
- local screen = Screen.new(20,5)
+ local screen = Screen.new(20, 5)
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.Yellow, background = Screen.colors.Blue};
- [2] = {foreground = Screen.colors.Black, background = Screen.colors.White};
- [3] = {foreground = Screen.colors.Yellow, background = Screen.colors.White};
- [4] = {foreground = Screen.colors.Yellow};
+ [1] = { foreground = Screen.colors.Yellow, background = Screen.colors.Blue },
+ [2] = { foreground = Screen.colors.Black, background = Screen.colors.White },
+ [3] = { foreground = Screen.colors.Yellow, background = Screen.colors.White },
+ [4] = { foreground = Screen.colors.Yellow },
})
screen:attach()
@@ -957,13 +1005,13 @@ describe('CursorLine and CursorLineNr highlights', function()
end)
it("'cursorlineopt' screenline", function()
- local screen = Screen.new(20,5)
+ local screen = Screen.new(20, 5)
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.Black, background = Screen.colors.White};
- [2] = {foreground = Screen.colors.Yellow};
- [3] = {foreground = Screen.colors.Red, background = Screen.colors.Green};
- [4] = {foreground = Screen.colors.Green, background = Screen.colors.Red};
- [5] = {bold = true}, -- ModeMsg
+ [1] = { foreground = Screen.colors.Black, background = Screen.colors.White },
+ [2] = { foreground = Screen.colors.Yellow },
+ [3] = { foreground = Screen.colors.Red, background = Screen.colors.Green },
+ [4] = { foreground = Screen.colors.Green, background = Screen.colors.Red },
+ [5] = { bold = true }, -- ModeMsg
})
screen:attach()
@@ -1088,16 +1136,16 @@ describe('CursorLine and CursorLineNr highlights', function()
-- oldtest: Test_cursorline_after_yank()
it('always updated. vim-patch:8.1.0849', function()
- local screen = Screen.new(50,5)
+ local screen = Screen.new(50, 5)
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.SlateBlue},
- [2] = {bold = true, foreground = Screen.colors.Brown},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [4] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.Gray90},
- [5] = {background = Screen.colors.Gray90},
- [6] = {bold = true, foreground = Screen.colors.Blue1},
- [7] = {background = Screen.colors.LightRed},
- [8] = {foreground = Screen.colors.Brown},
+ [1] = { foreground = Screen.colors.SlateBlue },
+ [2] = { bold = true, foreground = Screen.colors.Brown },
+ [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [4] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Gray90 },
+ [5] = { background = Screen.colors.Gray90 },
+ [6] = { bold = true, foreground = Screen.colors.Blue1 },
+ [7] = { background = Screen.colors.LightRed },
+ [8] = { foreground = Screen.colors.Brown },
})
screen:attach()
command('set cursorline relativenumber')
@@ -1122,18 +1170,18 @@ describe('CursorLine and CursorLineNr highlights', function()
-- oldtest: Test_cursorline_with_visualmode()
it('with visual area. vim-patch:8.1.1001', function()
- local screen = Screen.new(50,5)
+ local screen = Screen.new(50, 5)
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.SlateBlue},
- [2] = {bold = true, foreground = Screen.colors.Brown},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [4] = {foreground = Screen.colors.SlateBlue, background = Screen.colors.Gray90},
- [5] = {background = Screen.colors.Gray90},
- [6] = {bold = true, foreground = Screen.colors.Blue1},
- [7] = {background = Screen.colors.LightRed},
- [8] = {foreground = Screen.colors.Brown},
- [9] = {background = Screen.colors.LightGrey},
- [10] = {bold = true},
+ [1] = { foreground = Screen.colors.SlateBlue },
+ [2] = { bold = true, foreground = Screen.colors.Brown },
+ [3] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [4] = { foreground = Screen.colors.SlateBlue, background = Screen.colors.Gray90 },
+ [5] = { background = Screen.colors.Gray90 },
+ [6] = { bold = true, foreground = Screen.colors.Blue1 },
+ [7] = { background = Screen.colors.LightRed },
+ [8] = { foreground = Screen.colors.Brown },
+ [9] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey },
+ [10] = { bold = true },
})
screen:attach()
command('set cursorline')
@@ -1142,8 +1190,7 @@ describe('CursorLine and CursorLineNr highlights', function()
screen:expect([[
{9:abc} |
^a{9:bc} |
- abc |
- abc |
+ abc |*2
{10:-- VISUAL LINE --} |
]])
end)
@@ -1152,8 +1199,8 @@ describe('CursorLine and CursorLineNr highlights', function()
it('is updated if cursor is moved up from timer vim-patch:8.2.4591', function()
local screen = Screen.new(50, 8)
screen:set_default_attr_ids({
- [1] = {background = Screen.colors.Gray90}, -- CursorLine
- [2] = {bold = true, foreground = Screen.colors.Blue1}, -- NonText
+ [1] = { background = Screen.colors.Gray90 }, -- CursorLine
+ [2] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText
})
screen:attach()
exec([[
@@ -1167,40 +1214,41 @@ describe('CursorLine and CursorLineNr highlights', function()
call timer_start(300, 'Func')
]])
- screen:expect({grid = [[
+ screen:expect({
+ grid = [[
aaaaa |
bbbbb |
ccccc |
{1:^ddddd }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
- ]], timeout = 100})
- screen:expect({grid = [[
+ ]],
+ timeout = 100,
+ })
+ screen:expect({
+ grid = [[
aaaaa |
{1:^bbbbb }|
ccccc |
ddddd |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
- ]]})
+ ]],
+ })
end)
it('with split windows in diff mode', function()
- local screen = Screen.new(50,12)
+ local screen = Screen.new(50, 12)
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
- [2] = {bold = true, background = Screen.colors.Red},
- [3] = {background = Screen.colors.LightMagenta},
- [4] = {reverse = true},
- [5] = {background = Screen.colors.LightBlue},
- [6] = {background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1},
- [7] = {background = Screen.colors.Red, foreground = Screen.colors.White},
- [8] = {bold = true, foreground = Screen.colors.Blue1},
- [9] = {bold = true, reverse = true},
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray },
+ [2] = { bold = true, background = Screen.colors.Red },
+ [3] = { background = Screen.colors.LightMagenta },
+ [4] = { reverse = true },
+ [5] = { background = Screen.colors.LightBlue },
+ [6] = { background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1 },
+ [7] = { background = Screen.colors.Red, foreground = Screen.colors.White },
+ [8] = { bold = true, foreground = Screen.colors.Blue1 },
+ [9] = { bold = true, reverse = true },
})
screen:attach()
@@ -1210,20 +1258,19 @@ describe('CursorLine and CursorLineNr highlights', function()
feed('<esc>gg')
command('vsplit')
command('enew')
- feed('iline 1 some text<cr>line 2 moRe text!<cr>extra line!<cr>extra line!<cr>extra line!<cr>last line ...<cr>')
+ feed(
+ 'iline 1 some text<cr>line 2 moRe text!<cr>extra line!<cr>extra line!<cr>extra line!<cr>last line ...<cr>'
+ )
feed('<esc>gg')
command('windo diffthis')
screen:expect([[
{1: }{7:line 1 some text }│{1: }{7:^line 1 some text }|
{1: }{3:line 2 mo}{2:Re text!}{3: }│{1: }{3:line 2 mo}{2:re text}{3: }|
{1: }{5:extra line! }│{1: }{6:----------------------}|
- {1: }extra line! │{1: }extra line! |
- {1: }extra line! │{1: }extra line! |
+ {1: }extra line! │{1: }extra line! |*2
{1: }last line ... │{1: }last line ... |
{1: } │{1: } |
- {8:~ }│{8:~ }|
- {8:~ }│{8:~ }|
- {8:~ }│{8:~ }|
+ {8:~ }│{8:~ }|*3
{4:[No Name] [+] }{9:[No Name] [+] }|
|
]])
@@ -1232,13 +1279,10 @@ describe('CursorLine and CursorLineNr highlights', function()
{1: }line 1 some text │{1: }line 1 some text |
{1: }{3:line 2 mo}{2:Re text!}{3: }│{1: }{3:line 2 mo}{2:re text}{3: }|
{1: }{5:extra line! }│{1: }{6:----------------------}|
- {1: }extra line! │{1: }extra line! |
- {1: }extra line! │{1: }extra line! |
+ {1: }extra line! │{1: }extra line! |*2
{1: }last line ... │{1: }last line ... |
{1: }{7: }│{1: }{7:^ }|
- {8:~ }│{8:~ }|
- {8:~ }│{8:~ }|
- {8:~ }│{8:~ }|
+ {8:~ }│{8:~ }|*3
{4:[No Name] [+] }{9:[No Name] [+] }|
|
]])
@@ -1247,50 +1291,52 @@ describe('CursorLine and CursorLineNr highlights', function()
-- Rendered as underline in a diff-line. #9028
command('hi CursorLine ctermbg=red ctermfg=NONE guibg=red guifg=NONE')
feed('kkkk')
- screen:expect([[
+ screen:expect(
+ [[
{1: }line 1 some text │{1: }line 1 some text |
{1: }{11:line 2 mo}{12:Re text!}{11: }│{1: }{11:^line 2 mo}{12:re text}{11: }|
{1: }{5:extra line! }│{1: }{6:----------------------}|
- {1: }extra line! │{1: }extra line! |
- {1: }extra line! │{1: }extra line! |
+ {1: }extra line! │{1: }extra line! |*2
{1: }last line ... │{1: }last line ... |
{1: } │{1: } |
- {8:~ }│{8:~ }|
- {8:~ }│{8:~ }|
- {8:~ }│{8:~ }|
+ {8:~ }│{8:~ }|*3
{4:[No Name] [+] }{9:[No Name] [+] }|
|
- ]], {
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
- [2] = {bold = true, background = Screen.colors.Red},
- [3] = {background = Screen.colors.LightMagenta},
- [4] = {reverse = true},
- [5] = {background = Screen.colors.LightBlue},
- [6] = {background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1},
- [7] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [8] = {bold = true, foreground = Screen.colors.Blue1},
- [9] = {bold = true, reverse = true},
- [10] = {bold = true},
- [11] = {underline = true,
- background = Screen.colors.LightMagenta},
- [12] = {bold = true, underline = true,
- background = Screen.colors.Red},
- })
+ ]],
+ {
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray },
+ [2] = { bold = true, background = Screen.colors.Red },
+ [3] = { background = Screen.colors.LightMagenta },
+ [4] = { reverse = true },
+ [5] = { background = Screen.colors.LightBlue },
+ [6] = {
+ background = Screen.colors.LightCyan1,
+ bold = true,
+ foreground = Screen.colors.Blue1,
+ },
+ [7] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [8] = { bold = true, foreground = Screen.colors.Blue1 },
+ [9] = { bold = true, reverse = true },
+ [10] = { bold = true },
+ [11] = { underline = true, background = Screen.colors.LightMagenta },
+ [12] = { bold = true, underline = true, background = Screen.colors.Red },
+ }
+ )
end)
-- oldtest: Test_diff_with_cursorline_number()
it('CursorLineNr shows correctly just below filler lines', function()
- local screen = Screen.new(50,12)
+ local screen = Screen.new(50, 12)
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
- [2] = {background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1},
- [3] = {reverse = true},
- [4] = {background = Screen.colors.LightBlue},
- [5] = {background = Screen.colors.Red, foreground = Screen.colors.White},
- [6] = {background = Screen.colors.White, bold = true, foreground = Screen.colors.Black},
- [7] = {bold = true, foreground = Screen.colors.Blue1},
- [8] = {bold = true, reverse = true},
- [9] = {foreground = Screen.colors.Brown},
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray },
+ [2] = { background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { reverse = true },
+ [4] = { background = Screen.colors.LightBlue },
+ [5] = { background = Screen.colors.Red, foreground = Screen.colors.White },
+ [6] = { background = Screen.colors.White, bold = true, foreground = Screen.colors.Black },
+ [7] = { bold = true, foreground = Screen.colors.Blue1 },
+ [8] = { bold = true, reverse = true },
+ [9] = { foreground = Screen.colors.Brown },
})
screen:attach()
@@ -1308,12 +1354,7 @@ describe('CursorLine and CursorLineNr highlights', function()
{1: }{6: 1 }{5:^foo }│{1: }{6: 2 }{5:foo }|
{1: }{9: 2 }foo │{1: }{9: 3 }foo |
{1: }{9: 3 }bar │{1: }{9: 4 }bar |
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
+ {7:~ }│{7:~ }|*6
{8:[No Name] [+] }{3:[No Name] [+] }|
|
]])
@@ -1323,12 +1364,7 @@ describe('CursorLine and CursorLineNr highlights', function()
{1: }{6: 1 }^foo │{1: }{6: 2 }{5:foo }|
{1: }{9: 2 }foo │{1: }{9: 3 }foo |
{1: }{9: 3 }bar │{1: }{9: 4 }bar |
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
- {7:~ }│{7:~ }|
+ {7:~ }│{7:~ }|*6
{8:[No Name] [+] }{3:[No Name] [+] }|
|
]])
@@ -1341,9 +1377,9 @@ describe('CursorColumn highlight', function()
clear()
screen = Screen.new(50, 8)
screen:set_default_attr_ids({
- [1] = {background = Screen.colors.Gray90}, -- CursorColumn
- [2] = {bold = true, foreground = Screen.colors.Blue1}, -- NonText
- [3] = {bold = true}, -- ModeMsg
+ [1] = { background = Screen.colors.Gray90 }, -- CursorColumn
+ [2] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText
+ [3] = { bold = true }, -- ModeMsg
})
screen:attach()
end)
@@ -1357,44 +1393,28 @@ describe('CursorColumn highlight', function()
screen:expect([[
1234567{1:8}9 |
a ^ b |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*5
|
]])
feed('i')
screen:expect([[
1{1:2}3456789 |
a^ b |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*5
{3:-- INSERT --} |
]])
feed('<C-O>')
screen:expect([[
1234567{1:8}9 |
a ^ b |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*5
{3:-- (insert) --} |
]])
feed('i')
screen:expect([[
1{1:2}3456789 |
a^ b |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*5
{3:-- INSERT --} |
]])
end)
@@ -1412,26 +1432,27 @@ describe('CursorColumn highlight', function()
call timer_start(300, 'Func')
]])
- screen:expect({grid = [[
+ screen:expect({
+ grid = [[
aaaa{1:a} |
bbbb{1:b} |
cccc{1:c} |
dddd^d |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
- ]], timeout = 100})
- screen:expect({grid = [[
+ ]],
+ timeout = 100,
+ })
+ screen:expect({
+ grid = [[
^aaaaa |
{1:b}bbbb |
{1:c}cccc |
{1:d}dddd |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
- ]]})
+ ]],
+ })
end)
end)
@@ -1442,15 +1463,15 @@ describe('ColorColumn highlight', function()
clear()
screen = Screen.new(40, 15)
screen:set_default_attr_ids({
- [1] = {background = Screen.colors.LightRed}, -- ColorColumn
- [2] = {background = Screen.colors.Grey90}, -- CursorLine
- [3] = {foreground = Screen.colors.Brown}, -- LineNr
- [4] = {foreground = Screen.colors.Brown, bold = true}, -- CursorLineNr
- [5] = {foreground = Screen.colors.Blue, bold = true}, -- NonText
- [6] = {foreground = Screen.colors.Blue, background = Screen.colors.LightRed, bold = true},
- [7] = {reverse = true, bold = true}, -- StatusLine
- [8] = {reverse = true}, -- StatusLineNC
- [9] = {background = Screen.colors.Grey90, foreground = Screen.colors.Red},
+ [1] = { background = Screen.colors.LightRed }, -- ColorColumn
+ [2] = { background = Screen.colors.Grey90 }, -- CursorLine
+ [3] = { foreground = Screen.colors.Brown }, -- LineNr
+ [4] = { foreground = Screen.colors.Brown, bold = true }, -- CursorLineNr
+ [5] = { foreground = Screen.colors.Blue, bold = true }, -- NonText
+ [6] = { foreground = Screen.colors.Blue, background = Screen.colors.LightRed, bold = true },
+ [7] = { reverse = true, bold = true }, -- StatusLine
+ [8] = { reverse = true }, -- StatusLineNC
+ [9] = { background = Screen.colors.Grey90, foreground = Screen.colors.Red },
})
screen:attach()
end)
@@ -1472,16 +1493,12 @@ describe('ColorColumn highlight', function()
{4: 1 }11{1:1}11111{1:1}1 |
{3: 2 }22{1:2}22222{1:2}22 |
{3: 3 }33{1:3}33333{1:3}3 |
- {5:~ }|
- {5:~ }|
- {5:~ }|
+ {5:~ }|*3
{8:X }|
{4: 1 }^11{1:1}11111{1:1}1 |
{3: 2 }22{1:2}22222{1:2}22 |
{3: 3 }33{1:3}33333{1:3}3 |
- {5:~ }|
- {5:~ }|
- {5:~ }|
+ {5:~ }|*3
{7:X }|
|
]])
@@ -1496,18 +1513,7 @@ describe('ColorColumn highlight', function()
screen:expect([[
^The quick brown fox jumped over the {1: }|
{1: } {1:l}azy dogs |
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
+ {5:~ }|*12
|
]])
end)
@@ -1521,18 +1527,7 @@ describe('ColorColumn highlight', function()
screen:expect([[
^The quick brown fox jumped over the laz{1:y}|
{6:+}{5:+}{6:+}{5:>\} dogs |
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
+ {5:~ }|*12
|
]])
end)
@@ -1557,33 +1552,36 @@ describe('ColorColumn highlight', function()
end)
end)
-describe("MsgSeparator highlight and msgsep fillchar", function()
+describe('MsgSeparator highlight and msgsep fillchar', function()
local screen
before_each(function()
clear()
- screen = Screen.new(50,5)
+ screen = Screen.new(50, 5)
screen:set_default_attr_ids({
- [1] = {bold=true, foreground=Screen.colors.Blue},
- [2] = {bold=true, reverse=true},
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [4] = {background = Screen.colors.Cyan, bold = true, reverse = true},
- [5] = {bold = true, background = Screen.colors.Magenta},
- [6] = {background = Screen.colors.WebGray},
- [7] = {background = Screen.colors.WebGray, bold = true, foreground = Screen.colors.SeaGreen4},
- [8] = {foreground = Screen.colors.Grey0, background = Screen.colors.Gray60},
- [9] = {foreground = Screen.colors.Grey40, background = Screen.colors.Gray60},
- [10] = {foreground = tonumber('0x000019'), background = Screen.colors.Gray60},
- [11] = {background = Screen.colors.Gray60, bold = true, foreground = tonumber('0x666699')},
- [12] = {background = Screen.colors.Gray60, bold = true, foreground = tonumber('0x297d4e')},
- [13] = {background = tonumber('0xff4cff'), bold = true, foreground = tonumber('0xb200ff')},
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { bold = true, reverse = true },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [4] = { background = Screen.colors.Cyan, bold = true, reverse = true },
+ [5] = { bold = true, background = Screen.colors.Magenta },
+ [6] = { background = Screen.colors.WebGray },
+ [7] = {
+ background = Screen.colors.WebGray,
+ bold = true,
+ foreground = Screen.colors.SeaGreen4,
+ },
+ [8] = { foreground = Screen.colors.Grey0, background = Screen.colors.Gray60 },
+ [9] = { foreground = Screen.colors.Grey40, background = Screen.colors.Gray60 },
+ [10] = { foreground = tonumber('0x000019'), background = Screen.colors.Gray60 },
+ [11] = { background = Screen.colors.Gray60, bold = true, foreground = tonumber('0x666699') },
+ [12] = { background = Screen.colors.Gray60, bold = true, foreground = tonumber('0x297d4e') },
+ [13] = { background = tonumber('0xff4cff'), bold = true, foreground = tonumber('0xb200ff') },
})
screen:attach()
end)
- it("works", function()
-
+ it('works', function()
-- defaults
- feed_command("ls")
+ feed_command('ls')
screen:expect([[
|
{2: }|
@@ -1593,8 +1591,8 @@ describe("MsgSeparator highlight and msgsep fillchar", function()
]])
feed('<cr>')
- feed_command("set fillchars+=msgsep:-")
- feed_command("ls")
+ feed_command('set fillchars+=msgsep:-')
+ feed_command('ls')
screen:expect([[
|
{2:--------------------------------------------------}|
@@ -1604,8 +1602,8 @@ describe("MsgSeparator highlight and msgsep fillchar", function()
]])
-- linked to StatusLine per default
- feed_command("hi StatusLine guibg=Cyan")
- feed_command("ls")
+ feed_command('hi StatusLine guibg=Cyan')
+ feed_command('ls')
screen:expect([[
|
{4:--------------------------------------------------}|
@@ -1615,9 +1613,9 @@ describe("MsgSeparator highlight and msgsep fillchar", function()
]])
-- but can be unlinked
- feed_command("hi clear MsgSeparator")
- feed_command("hi MsgSeparator guibg=Magenta gui=bold")
- feed_command("ls")
+ feed_command('hi clear MsgSeparator')
+ feed_command('hi MsgSeparator guibg=Magenta gui=bold')
+ feed_command('ls')
screen:expect([[
|
{5:--------------------------------------------------}|
@@ -1627,169 +1625,63 @@ describe("MsgSeparator highlight and msgsep fillchar", function()
]])
end)
- it("and MsgArea", function()
- feed_command("hi MsgArea guibg=Gray")
- screen:expect{grid=[[
+ it('and MsgArea', function()
+ feed_command('hi MsgArea guibg=Gray')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{6: }|
- ]]}
- feed(":ls")
- screen:expect{grid=[[
+ ]],
+ }
+ feed(':ls')
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{6::ls^ }|
- ]]}
- feed(":<cr>")
- screen:expect{grid=[[
+ ]],
+ }
+ feed(':<cr>')
+ screen:expect {
+ grid = [[
|
{2: }|
{6::ls: }|
{6: 1 %a "[No Name]" line 1 }|
{7:Press ENTER or type command to continue}{6:^ }|
- ]]}
+ ]],
+ }
-- support madness^Wblending of message "overlay"
- feed_command("hi MsgArea blend=20")
- feed_command("hi clear MsgSeparator")
- feed_command("hi MsgSeparator blend=30 guibg=Magenta")
- screen:expect{grid=[[
+ feed_command('hi MsgArea blend=20')
+ feed_command('hi clear MsgSeparator')
+ feed_command('hi MsgSeparator blend=30 guibg=Magenta')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{8::hi}{9: }{8:MsgSeparator}{9: }{8:blend=30}{9: }{8:guibg=Magenta}{9: }|
- ]]}
- feed(":ls")
- screen:expect{grid=[[
+ ]],
+ }
+ feed(':ls')
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{8::ls}{9:^ }|
- ]]}
- feed("<cr>")
- screen:expect{grid=[[
+ ]],
+ }
+ feed('<cr>')
+ screen:expect {
+ grid = [[
|
{13:~ }|
{10::ls}{11: }|
{11:~ }{10:1}{11: }{10:%a}{11: }{10:"[No}{11: }{10:Name]"}{11: }{10:line}{11: }{10:1}{11: }|
{12:Press}{9: }{12:ENTER}{9: }{12:or}{9: }{12:type}{9: }{12:command}{9: }{12:to}{9: }{12:continue}{9:^ }|
- ]]}
- end)
-end)
-
-describe("'number' and 'relativenumber' highlight", function()
- before_each(clear)
-
- it('LineNr, LineNrAbove and LineNrBelow', function()
- local screen = Screen.new(20,10)
- screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.Red},
- [2] = {foreground = Screen.colors.Blue},
- [3] = {foreground = Screen.colors.Green},
- })
- screen:attach()
- command('set number relativenumber')
- command('call setline(1, range(50))')
- command('highlight LineNr guifg=Red')
- feed('4j')
- screen:expect([[
- {1: 4 }0 |
- {1: 3 }1 |
- {1: 2 }2 |
- {1: 1 }3 |
- {1:5 }^4 |
- {1: 1 }5 |
- {1: 2 }6 |
- {1: 3 }7 |
- {1: 4 }8 |
- |
- ]])
- command('highlight LineNrAbove guifg=Blue')
- screen:expect([[
- {2: 4 }0 |
- {2: 3 }1 |
- {2: 2 }2 |
- {2: 1 }3 |
- {1:5 }^4 |
- {1: 1 }5 |
- {1: 2 }6 |
- {1: 3 }7 |
- {1: 4 }8 |
- |
- ]])
- command('highlight LineNrBelow guifg=Green')
- screen:expect([[
- {2: 4 }0 |
- {2: 3 }1 |
- {2: 2 }2 |
- {2: 1 }3 |
- {1:5 }^4 |
- {3: 1 }5 |
- {3: 2 }6 |
- {3: 3 }7 |
- {3: 4 }8 |
- |
- ]])
- feed('3j')
- screen:expect([[
- {2: 7 }0 |
- {2: 6 }1 |
- {2: 5 }2 |
- {2: 4 }3 |
- {2: 3 }4 |
- {2: 2 }5 |
- {2: 1 }6 |
- {1:8 }^7 |
- {3: 1 }8 |
- |
- ]])
- end)
-
- -- oldtest: Test_relativenumber_callback()
- it('relative number highlight is updated if cursor is moved from timer', function()
- local screen = Screen.new(50, 8)
- screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.Brown}, -- LineNr
- [2] = {bold = true, foreground = Screen.colors.Blue1}, -- NonText
- })
- screen:attach()
- exec([[
- call setline(1, ['aaaaa', 'bbbbb', 'ccccc', 'ddddd'])
- set relativenumber
- call cursor(4, 1)
-
- func Func(timer)
- call cursor(1, 1)
- endfunc
-
- call timer_start(300, 'Func')
- ]])
- screen:expect({grid = [[
- {1: 3 }aaaaa |
- {1: 2 }bbbbb |
- {1: 1 }ccccc |
- {1: 0 }^ddddd |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- |
- ]], timeout = 100})
- screen:expect({grid = [[
- {1: 0 }^aaaaa |
- {1: 1 }bbbbb |
- {1: 2 }ccccc |
- {1: 3 }ddddd |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- |
- ]]})
+ ]],
+ }
end)
end)
@@ -1798,54 +1690,57 @@ describe("'winhighlight' highlight", function()
before_each(function()
clear()
- screen = Screen.new(20,8)
+ screen = Screen.new(20, 8)
screen:attach()
screen:set_default_attr_ids {
- [0] = {bold=true, foreground=Screen.colors.Blue};
- [1] = {background = Screen.colors.DarkBlue};
- [2] = {background = Screen.colors.DarkBlue, bold = true, foreground = Screen.colors.Blue1};
- [3] = {bold = true, reverse = true};
- [4] = {reverse = true};
- [5] = {background = Screen.colors.DarkGreen};
- [6] = {background = Screen.colors.DarkGreen, bold = true, foreground = Screen.colors.Blue1};
- [7] = {background = Screen.colors.DarkMagenta};
- [8] = {background = Screen.colors.DarkMagenta, bold = true, foreground = Screen.colors.Blue1};
- [9] = {foreground = Screen.colors.Brown};
- [10] = {foreground = Screen.colors.Brown, background = Screen.colors.DarkBlue};
- [11] = {background = Screen.colors.DarkBlue, bold = true, reverse = true};
- [12] = {background = Screen.colors.DarkGreen, reverse = true};
- [13] = {background = Screen.colors.Magenta4, reverse = true};
- [14] = {background = Screen.colors.DarkBlue, reverse = true};
- [15] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red};
- [16] = {foreground = Screen.colors.Blue1};
- [17] = {background = Screen.colors.LightRed};
- [18] = {background = Screen.colors.Gray90};
- [19] = {foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray};
- [20] = {background = Screen.colors.LightGrey, underline = true};
- [21] = {bold = true};
- [22] = {bold = true, foreground = Screen.colors.SeaGreen4};
- [23] = {background = Screen.colors.LightMagenta};
- [24] = {background = Screen.colors.WebGray};
- [25] = {bold = true, foreground = Screen.colors.Green1};
- [26] = {background = Screen.colors.Red};
- [27] = {background = Screen.colors.DarkBlue, bold = true, foreground = Screen.colors.Green1};
- [28] = {bold = true, foreground = Screen.colors.Brown};
- [29] = {foreground = Screen.colors.Blue1, background = Screen.colors.Red, bold = true};
- [30] = {background = tonumber('0xff8800')};
- [31] = {background = tonumber('0xff8800'), bold = true, foreground = Screen.colors.Blue};
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { background = Screen.colors.DarkBlue },
+ [2] = { background = Screen.colors.DarkBlue, bold = true, foreground = Screen.colors.Blue1 },
+ [3] = { bold = true, reverse = true },
+ [4] = { reverse = true },
+ [5] = { background = Screen.colors.DarkGreen },
+ [6] = { background = Screen.colors.DarkGreen, bold = true, foreground = Screen.colors.Blue1 },
+ [7] = { background = Screen.colors.DarkMagenta },
+ [8] = {
+ background = Screen.colors.DarkMagenta,
+ bold = true,
+ foreground = Screen.colors.Blue1,
+ },
+ [9] = { foreground = Screen.colors.Brown },
+ [10] = { foreground = Screen.colors.Brown, background = Screen.colors.DarkBlue },
+ [11] = { background = Screen.colors.DarkBlue, bold = true, reverse = true },
+ [12] = { background = Screen.colors.DarkGreen, reverse = true },
+ [13] = { background = Screen.colors.Magenta4, reverse = true },
+ [14] = { background = Screen.colors.DarkBlue, reverse = true },
+ [15] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [16] = { foreground = Screen.colors.Blue1 },
+ [17] = { background = Screen.colors.LightRed },
+ [18] = { background = Screen.colors.Gray90 },
+ [19] = { foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray },
+ [20] = { background = Screen.colors.LightGrey, underline = true },
+ [21] = { bold = true },
+ [22] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [23] = { background = Screen.colors.LightMagenta },
+ [24] = { background = Screen.colors.WebGray },
+ [25] = { bold = true, foreground = Screen.colors.Green1 },
+ [26] = { background = Screen.colors.Red },
+ [27] = { background = Screen.colors.DarkBlue, bold = true, foreground = Screen.colors.Green1 },
+ [28] = { bold = true, foreground = Screen.colors.Brown },
+ [29] = { foreground = Screen.colors.Blue1, background = Screen.colors.Red, bold = true },
+ [30] = { background = tonumber('0xff8800') },
+ [31] = { background = tonumber('0xff8800'), bold = true, foreground = Screen.colors.Blue },
}
- command("hi Background1 guibg=DarkBlue")
- command("hi Background2 guibg=DarkGreen")
+ command('hi Background1 guibg=DarkBlue')
+ command('hi Background2 guibg=DarkGreen')
end)
it('works for background color', function()
- insert("aa")
- command("split")
- command("set winhl=Normal:Background1")
+ insert('aa')
+ command('split')
+ command('set winhl=Normal:Background1')
screen:expect([[
{1:a^a }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
{3:[No Name] [+] }|
aa |
{0:~ }|
@@ -1853,11 +1748,10 @@ describe("'winhighlight' highlight", function()
|
]])
- command("enew")
+ command('enew')
screen:expect([[
{1:^ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
{3:[No Name] }|
aa |
{0:~ }|
@@ -1874,84 +1768,64 @@ describe("'winhighlight' highlight", function()
command('setlocal winhl=Normal:Background1')
screen:expect([[
{1: ^aa}|
- {2: ~}|
- {2: ~}|
- {2: ~}|
- {2: ~}|
+ {2: ~}|*4
|
]])
command('botright vsplit')
screen:expect([[
{1: aa│ ^aa}|
- {2: ~}{1:│}{2: ~}|
- {2: ~}{1:│}{2: ~}|
- {2: ~}{1:│}{2: ~}|
+ {2: ~}{1:│}{2: ~}|*3
{4:[No Name] [+] }{3:[No Name] [+] }|
|
]])
end)
it('handles undefined groups', function()
- command("set winhl=Normal:Background1")
+ command('set winhl=Normal:Background1')
screen:expect([[
{1:^ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*6
|
]])
- command("set winhl=xxx:yyy")
+ command('set winhl=xxx:yyy')
eq('xxx:yyy', eval('&winhl'))
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
|
- ]]}
+ ]],
+ }
end)
it('can be changed to define different groups', function()
- command("set winhl=EndOfBuffer:Background1")
- screen:expect{grid=[[
+ command('set winhl=EndOfBuffer:Background1')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
- ]]}
+ ]],
+ }
- command("set winhl=Normal:ErrorMsg")
- screen:expect{grid=[[
+ command('set winhl=Normal:ErrorMsg')
+ screen:expect {
+ grid = [[
{15:^ }|
- {29:~ }|
- {29:~ }|
- {29:~ }|
- {29:~ }|
- {29:~ }|
- {29:~ }|
+ {29:~ }|*6
|
- ]]}
+ ]],
+ }
end)
it('works local to the window', function()
- insert("aa")
- command("split")
- command("setlocal winhl=Normal:Background1")
+ insert('aa')
+ command('split')
+ command('setlocal winhl=Normal:Background1')
screen:expect([[
{1:a^a }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
{3:[No Name] [+] }|
aa |
{0:~ }|
@@ -1959,11 +1833,10 @@ describe("'winhighlight' highlight", function()
|
]])
- command("enew")
+ command('enew')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] }|
aa |
{0:~ }|
@@ -1971,11 +1844,10 @@ describe("'winhighlight' highlight", function()
|
]])
- command("bnext")
+ command('bnext')
screen:expect([[
{1:^aa }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
{3:[No Name] [+] }|
aa |
{0:~ }|
@@ -1985,13 +1857,12 @@ describe("'winhighlight' highlight", function()
end)
it('for inactive window background works', function()
- command("set winhl=Normal:Background1,NormalNC:Background2")
+ command('set winhl=Normal:Background1,NormalNC:Background2')
-- tests global value is copied across split
- command("split")
+ command('split')
screen:expect([[
{1:^ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
{3:[No Name] }|
{5: }|
{6:~ }|
@@ -1999,11 +1870,10 @@ describe("'winhighlight' highlight", function()
|
]])
- feed("<c-w><c-w>")
+ feed('<c-w><c-w>')
screen:expect([[
{5: }|
- {6:~ }|
- {6:~ }|
+ {6:~ }|*2
{4:[No Name] }|
{1:^ }|
{2:~ }|
@@ -2011,11 +1881,10 @@ describe("'winhighlight' highlight", function()
|
]])
- feed("<c-w><c-w>")
+ feed('<c-w><c-w>')
screen:expect([[
{1:^ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
{3:[No Name] }|
{5: }|
{6:~ }|
@@ -2025,13 +1894,12 @@ describe("'winhighlight' highlight", function()
end)
it('works with NormalNC', function()
- command("hi NormalNC guibg=DarkMagenta")
+ command('hi NormalNC guibg=DarkMagenta')
-- tests global value is copied across split
- command("split")
+ command('split')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] }|
{7: }|
{8:~ }|
@@ -2039,11 +1907,10 @@ describe("'winhighlight' highlight", function()
|
]])
- command("wincmd w")
+ command('wincmd w')
screen:expect([[
{7: }|
- {8:~ }|
- {8:~ }|
+ {8:~ }|*2
{4:[No Name] }|
^ |
{0:~ }|
@@ -2051,13 +1918,11 @@ describe("'winhighlight' highlight", function()
|
]])
-
-- winbg=Normal:... overrides global NormalNC
- command("set winhl=Normal:Background1")
+ command('set winhl=Normal:Background1')
screen:expect([[
{7: }|
- {8:~ }|
- {8:~ }|
+ {8:~ }|*2
{4:[No Name] }|
{1:^ }|
{2:~ }|
@@ -2065,11 +1930,10 @@ describe("'winhighlight' highlight", function()
|
]])
- command("wincmd w")
+ command('wincmd w')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] }|
{1: }|
{2:~ }|
@@ -2077,12 +1941,11 @@ describe("'winhighlight' highlight", function()
|
]])
- command("wincmd w")
- command("set winhl=Normal:Background1,NormalNC:Background2")
+ command('wincmd w')
+ command('set winhl=Normal:Background1,NormalNC:Background2')
screen:expect([[
{7: }|
- {8:~ }|
- {8:~ }|
+ {8:~ }|*2
{4:[No Name] }|
{1:^ }|
{2:~ }|
@@ -2090,11 +1953,10 @@ describe("'winhighlight' highlight", function()
|
]])
- command("wincmd w")
+ command('wincmd w')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] }|
{5: }|
{6:~ }|
@@ -2104,30 +1966,32 @@ describe("'winhighlight' highlight", function()
end)
it('updates background to changed linked group', function()
- command("split")
- command("setlocal winhl=Normal:FancyGroup") -- does not yet exist
- screen:expect{grid=[[
+ command('split')
+ command('setlocal winhl=Normal:FancyGroup') -- does not yet exist
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] }|
|
{0:~ }|
{4:[No Name] }|
|
- ]]}
+ ]],
+ }
- command("hi FancyGroup guibg=#FF8800") -- nice orange
- screen:expect{grid=[[
+ command('hi FancyGroup guibg=#FF8800') -- nice orange
+ screen:expect {
+ grid = [[
{30:^ }|
- {31:~ }|
- {31:~ }|
+ {31:~ }|*2
{3:[No Name] }|
|
{0:~ }|
{4:[No Name] }|
|
- ]]}
+ ]],
+ }
end)
it('background applies also to non-text', function()
@@ -2144,10 +2008,7 @@ describe("'winhighlight' highlight", function()
{9: 1 } ^Lorem ipsum do|
{9: } {0:↪}lor sit |
{9: } {0:↪}amet{0:-} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
@@ -2156,10 +2017,7 @@ describe("'winhighlight' highlight", function()
{10: 1 }{1: ^Lorem ipsum do}|
{10: }{1: }{2:↪}{1:lor sit }|
{10: }{1: }{2:↪}{1:amet}{2:-}{1: }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*4
|
]])
@@ -2168,12 +2026,7 @@ describe("'winhighlight' highlight", function()
feed('3w')
screen:expect([[
{10: 1 }{2:â®}{1: dolor ^sit ame}{2:â¯}|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*6
|
]])
end)
@@ -2188,11 +2041,7 @@ describe("'winhighlight' highlight", function()
screen:expect([[
{25:the} {26:foobar} was {26:fooba}|
{26:^r} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
@@ -2202,28 +2051,22 @@ describe("'winhighlight' highlight", function()
screen:expect([[
{27:the}{1: }{26:foobar}{1: was }{26:fooba}|
{26:^r}{1: }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*5
|
]])
end)
it('can override NonText, Conceal and EndOfBuffer', function()
- curbufmeths.set_lines(0,-1,true, {"raa\000"})
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'raa\000' })
command('call matchaddpos("Conceal", [[1,2]], 0, -1, {"conceal": "#"})')
command('set cole=2 cocu=nvic')
command('split')
command('call matchaddpos("Conceal", [[1,2]], 0, -1, {"conceal": "#"})')
- command('set winhl=SpecialKey:ErrorMsg,EndOfBuffer:Background1,'
- ..'Conceal:Background2')
+ command('set winhl=SpecialKey:ErrorMsg,EndOfBuffer:Background1,' .. 'Conceal:Background2')
screen:expect([[
^r{5:#}a{15:^@} |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:[No Name] [+] }|
r{19:#}a{16:^@} |
{0:~ }|
@@ -2240,8 +2083,7 @@ describe("'winhighlight' highlight", function()
feed('k')
command('split')
- command('set winhl=LineNr:Background1,CursorColumn:Background2,'
- ..'ColorColumn:ErrorMsg')
+ command('set winhl=LineNr:Background1,CursorColumn:Background2,' .. 'ColorColumn:ErrorMsg')
screen:expect([[
{1: 1 }v{15:e}ry tex^t |
{1: 2 }m{15:o}re tex{5:t} |
@@ -2261,22 +2103,14 @@ describe("'winhighlight' highlight", function()
screen:expect([[
{20: No Name] }{15: No Name]}{20:X}|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
- command("tabnext")
+ command('tabnext')
screen:expect([[
{21: No Name] }{1: No Name]}{20:X}|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
end)
@@ -2284,12 +2118,12 @@ describe("'winhighlight' highlight", function()
it('can override popupmenu', function()
insert('word wording wordy')
command('split')
- command('set winhl=Pmenu:Background1,PmenuSel:Background2,'
- ..'PmenuSbar:ErrorMsg,PmenuThumb:Normal')
+ command(
+ 'set winhl=Pmenu:Background1,PmenuSel:Background2,' .. 'PmenuSbar:ErrorMsg,PmenuThumb:Normal'
+ )
screen:expect([[
word wording word^y |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] [+] }|
word wording wordy |
{0:~ }|
@@ -2327,40 +2161,43 @@ describe("'winhighlight' highlight", function()
command('set cursorline number')
command('split')
command('set winhl=CursorLine:Background1')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{28: 1 }{1:^ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] }|
{28: 1 }{18: }|
{0:~ }|
{4:[No Name] }|
|
- ]]}
+ ]],
+ }
command('set winhl=CursorLineNr:Background2,CursorLine:Background1')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{5: 1 }{1:^ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] }|
{28: 1 }{18: }|
{0:~ }|
{4:[No Name] }|
|
- ]]}
+ ]],
+ }
feed('<c-w>w')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{5: 1 }{1: }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{4:[No Name] }|
{28: 1 }{18:^ }|
{0:~ }|
{3:[No Name] }|
|
- ]]}
+ ]],
+ }
end)
it('can override StatusLine and StatusLineNC', function()
@@ -2368,8 +2205,7 @@ describe("'winhighlight' highlight", function()
command('split')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1:[No Name] }|
|
{0:~ }|
@@ -2394,8 +2230,7 @@ describe("'winhighlight' highlight", function()
]])
end)
-
- it("can override syntax groups", function()
+ it('can override syntax groups', function()
command('syntax on')
command('syntax keyword Foobar foobar')
command('syntax keyword Article the')
@@ -2405,17 +2240,14 @@ describe("'winhighlight' highlight", function()
screen:expect([[
{25:the} {26:foobar} was {26:fooba}|
{26:^r} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
]])
command('split')
command('set winhl=Foobar:Background1,Article:ErrorMsg')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{15:the} {1:foobar} was {1:fooba}|
{1:^r} |
{0:~ }|
@@ -2424,21 +2256,23 @@ describe("'winhighlight' highlight", function()
{26:r} |
{4:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
end)
it('can be disabled in newly opened window #19823', function()
command('split | set winhl=Normal:ErrorMsg | set winhl=')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] }|
|
{0:~ }|
{4:[No Name] }|
|
- ]]}
+ ]],
+ }
helpers.assert_alive()
end)
@@ -2452,7 +2286,8 @@ describe("'winhighlight' highlight", function()
insert [[
some text
more text]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
some text |
more tex^t |
{0:~ }|
@@ -2461,10 +2296,12 @@ describe("'winhighlight' highlight", function()
more text |
{4:[No Name] }{1:1,1 All}|
|
- ]]}
+ ]],
+ }
command 'set winhl=Background1:Background2'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
some text |
more tex^t |
{0:~ }|
@@ -2473,10 +2310,12 @@ describe("'winhighlight' highlight", function()
more text |
{4:[No Name] }{1:1,1 All}|
|
- ]]}
+ ]],
+ }
feed 'k'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
some tex^t |
more text |
{0:~ }|
@@ -2485,7 +2324,8 @@ describe("'winhighlight' highlight", function()
more text |
{4:[No Name] }{1:1,1 All}|
|
- ]]}
+ ]],
+ }
end)
it('can link to empty highlight group', function()
@@ -2493,16 +2333,17 @@ describe("'winhighlight' highlight", function()
command 'set winhl=NormalNC:Normal'
command 'split'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] }|
|
{0:~ }|
{4:[No Name] }|
|
- ]]}
+ ]],
+ }
end)
end)
@@ -2512,97 +2353,82 @@ describe('highlight namespaces', function()
before_each(function()
clear()
- screen = Screen.new(25,10)
+ screen = Screen.new(25, 10)
screen:attach()
screen:set_default_attr_ids {
- [1] = {foreground = Screen.colors.Blue, bold = true};
- [2] = {background = Screen.colors.DarkGrey};
- [3] = {italic = true, foreground = Screen.colors.DarkCyan, background = Screen.colors.DarkOrange4};
- [4] = {background = Screen.colors.Magenta4};
- [5] = {background = Screen.colors.Magenta4, foreground = Screen.colors.Crimson};
- [6] = {bold = true, reverse = true};
- [7] = {reverse = true};
- [8] = {foreground = Screen.colors.Gray20};
- [9] = {foreground = Screen.colors.Blue};
- [10] = {bold = true, foreground = Screen.colors.SeaGreen};
+ [1] = { foreground = Screen.colors.Blue, bold = true },
+ [2] = { background = Screen.colors.DarkGrey },
+ [3] = {
+ italic = true,
+ foreground = Screen.colors.DarkCyan,
+ background = Screen.colors.DarkOrange4,
+ },
+ [4] = { background = Screen.colors.Magenta4 },
+ [5] = { background = Screen.colors.Magenta4, foreground = Screen.colors.Crimson },
+ [6] = { bold = true, reverse = true },
+ [7] = { reverse = true },
+ [8] = { foreground = Screen.colors.Gray20 },
+ [9] = { foreground = Screen.colors.Blue },
+ [10] = { bold = true, foreground = Screen.colors.SeaGreen },
}
- ns1 = meths.create_namespace 'grungy'
- ns2 = meths.create_namespace 'ultrared'
+ ns1 = api.nvim_create_namespace 'grungy'
+ ns2 = api.nvim_create_namespace 'ultrared'
- meths.set_hl(ns1, 'Normal', {bg='DarkGrey'})
- meths.set_hl(ns1, 'NonText', {bg='DarkOrange4', fg='DarkCyan', italic=true})
- meths.set_hl(ns2, 'Normal', {bg='DarkMagenta'})
- meths.set_hl(ns2, 'NonText', {fg='Crimson'})
+ api.nvim_set_hl(ns1, 'Normal', { bg = 'DarkGrey' })
+ api.nvim_set_hl(ns1, 'NonText', { bg = 'DarkOrange4', fg = 'DarkCyan', italic = true })
+ api.nvim_set_hl(ns2, 'Normal', { bg = 'DarkMagenta' })
+ api.nvim_set_hl(ns2, 'NonText', { fg = 'Crimson' })
end)
it('can be used globally', function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
|
- ]]}
+ ]],
+ }
- meths.set_hl_ns(ns1)
- screen:expect{grid=[[
+ api.nvim_set_hl_ns(ns1)
+ screen:expect {
+ grid = [[
{2:^ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*8
|
- ]]}
+ ]],
+ }
- meths.set_hl_ns(ns2)
- screen:expect{grid=[[
+ api.nvim_set_hl_ns(ns2)
+ screen:expect {
+ grid = [[
{4:^ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
+ {5:~ }|*8
|
- ]]}
+ ]],
+ }
- meths.set_hl_ns(0)
- screen:expect{grid=[[
+ api.nvim_set_hl_ns(0)
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
|
- ]]}
+ ]],
+ }
end)
it('can be used per window', function()
- local win1 = meths.get_current_win()
+ local win1 = api.nvim_get_current_win()
command 'split'
- local win2 = meths.get_current_win()
+ local win2 = api.nvim_get_current_win()
command 'split'
- meths.win_set_hl_ns(win1, ns1)
- meths.win_set_hl_ns(win2, ns2)
+ api.nvim_win_set_hl_ns(win1, ns1)
+ api.nvim_win_set_hl_ns(win2, ns2)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
{1:~ }|
{6:[No Name] }|
@@ -2613,36 +2439,27 @@ describe('highlight namespaces', function()
{3:~ }|
{7:[No Name] }|
|
- ]]}
+ ]],
+ }
end)
it('redraws correctly when ns=0', function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
|
- ]]}
+ ]],
+ }
- meths.set_hl(0, 'EndOfBuffer', {fg='#333333'})
- screen:expect{grid=[[
+ api.nvim_set_hl(0, 'EndOfBuffer', { fg = '#333333' })
+ screen:expect {
+ grid = [[
^ |
- {8:~ }|
- {8:~ }|
- {8:~ }|
- {8:~ }|
- {8:~ }|
- {8:~ }|
- {8:~ }|
- {8:~ }|
+ {8:~ }|*8
|
- ]]}
+ ]],
+ }
end)
it('winhl does not accept invalid value #24586', function()
@@ -2653,18 +2470,19 @@ describe('highlight namespaces', function()
return { msg, vim.wo[curwin].winhl }
]])
eq({
- "Vim(set):E5248: Invalid character in group name",
- "Normal:Visual",
- },res)
+ 'Vim(set):E5248: Invalid character in group name',
+ 'Normal:Visual',
+ }, res)
end)
it('Normal in set_hl #25474', function()
- meths.set_hl(0, 'Normal', {bg='#333333'})
+ command('highlight Ignore guifg=bg ctermfg=White')
+ api.nvim_set_hl(0, 'Normal', { bg = '#333333' })
command('highlight Ignore')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{6: }|
|
Ignore {8:xxx} {9:ctermf}|
@@ -2672,6 +2490,7 @@ describe('highlight namespaces', function()
bg |
{10:Press ENTER or type comma}|
{10:nd to continue}^ |
- ]]}
+ ]],
+ }
end)
end)
diff --git a/test/functional/ui/hlstate_spec.lua b/test/functional/ui/hlstate_spec.lua
index 55f873e827..8b36ad5431 100644
--- a/test/functional/ui/hlstate_spec.lua
+++ b/test/functional/ui/hlstate_spec.lua
@@ -3,7 +3,7 @@ local Screen = require('test.functional.ui.screen')
local clear, insert = helpers.clear, helpers.insert
local command = helpers.command
-local meths = helpers.meths
+local api = helpers.api
local testprg = helpers.testprg
local thelpers = require('test.functional.terminal.helpers')
local skip = helpers.skip
@@ -17,127 +17,157 @@ describe('ext_hlstate detailed highlights', function()
command('syntax on')
command('hi VertSplit gui=reverse')
screen = Screen.new(40, 8)
- screen:attach({ext_hlstate=true})
+ screen:attach({ ext_hlstate = true })
end)
after_each(function()
screen:detach()
end)
-
it('work with combined UI and syntax highlights', function()
insert([[
these are some lines
with colorful text]])
- meths.buf_add_highlight(0, -1, "String", 0 , 10, 14)
- meths.buf_add_highlight(0, -1, "Statement", 1 , 5, -1)
- command("/th co")
+ api.nvim_buf_add_highlight(0, -1, 'String', 0, 10, 14)
+ api.nvim_buf_add_highlight(0, -1, 'Statement', 1, 5, -1)
+ command('/th co')
- screen:expect([[
+ screen:expect(
+ [[
these are {1:some} lines |
^wi{2:th }{4:co}{3:lorful text} |
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
+ {5:~ }|*5
{8:search hit BOTTOM, continuing at TOP}{7: }|
- ]], {
- [1] = {{foreground = Screen.colors.Magenta},
- {{hi_name = "Constant", kind = "syntax"}}},
- [2] = {{background = Screen.colors.Yellow},
- {{hi_name = "Search", ui_name = "Search", kind = "ui"}}},
- [3] = {{bold = true, foreground = Screen.colors.Brown},
- {{hi_name = "Statement", kind = "syntax"}}},
- [4] = {{bold = true, background = Screen.colors.Yellow, foreground = Screen.colors.Brown}, {3, 2}},
- [5] = {{bold = true, foreground = Screen.colors.Blue1},
- {{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
- [6] = {{foreground = Screen.colors.Red},
- {{hi_name = "WarningMsg", ui_name = "WarningMsg", kind = "ui"}}},
- [7] = {{}, {{hi_name = "MsgArea", ui_name = "MsgArea", kind = "ui"}}},
- [8] = {{foreground = Screen.colors.Red}, {7, 6}},
- })
+ ]],
+ {
+ [1] = {
+ { foreground = Screen.colors.Magenta },
+ { { hi_name = 'Constant', kind = 'syntax' } },
+ },
+ [2] = {
+ { background = Screen.colors.Yellow },
+ { { hi_name = 'Search', ui_name = 'Search', kind = 'ui' } },
+ },
+ [3] = {
+ { bold = true, foreground = Screen.colors.Brown },
+ { { hi_name = 'Statement', kind = 'syntax' } },
+ },
+ [4] = {
+ { bold = true, background = Screen.colors.Yellow, foreground = Screen.colors.Brown },
+ { 3, 2 },
+ },
+ [5] = {
+ { bold = true, foreground = Screen.colors.Blue1 },
+ { { hi_name = 'NonText', ui_name = 'EndOfBuffer', kind = 'ui' } },
+ },
+ [6] = {
+ { foreground = Screen.colors.Red },
+ { { hi_name = 'WarningMsg', ui_name = 'WarningMsg', kind = 'ui' } },
+ },
+ [7] = { {}, { { hi_name = 'MsgArea', ui_name = 'MsgArea', kind = 'ui' } } },
+ [8] = { { foreground = Screen.colors.Red }, { 7, 6 } },
+ }
+ )
end)
it('work with cleared UI highlights', function()
screen:set_default_attr_ids({
- [1] = {{}, {{hi_name = "Normal", ui_name = "WinSeparator", kind = "ui"}}},
- [2] = {{bold = true, foreground = Screen.colors.Blue1},
- {{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
- [3] = {{bold = true, reverse = true},
- {{hi_name = "StatusLine", ui_name = "StatusLine", kind = "ui"}}} ,
- [4] = {{reverse = true},
- {{hi_name = "StatusLineNC", ui_name = "StatusLineNC" , kind = "ui"}}},
- [5] = {{}, {{hi_name = "StatusLine", ui_name = "StatusLine", kind = "ui"}}},
- [6] = {{}, {{hi_name = "StatusLineNC", ui_name = "StatusLineNC", kind = "ui"}}},
- [7] = {{}, {{hi_name = "MsgArea", ui_name = "MsgArea", kind = "ui"}}},
+ [1] = { {}, { { hi_name = 'Normal', ui_name = 'WinSeparator', kind = 'ui' } } },
+ [2] = {
+ { bold = true, foreground = Screen.colors.Blue1 },
+ { { hi_name = 'NonText', ui_name = 'EndOfBuffer', kind = 'ui' } },
+ },
+ [3] = {
+ { bold = true, reverse = true },
+ { { hi_name = 'StatusLine', ui_name = 'StatusLine', kind = 'ui' } },
+ },
+ [4] = {
+ { reverse = true },
+ { { hi_name = 'StatusLineNC', ui_name = 'StatusLineNC', kind = 'ui' } },
+ },
+ [5] = { {}, { { hi_name = 'StatusLine', ui_name = 'StatusLine', kind = 'ui' } } },
+ [6] = { {}, { { hi_name = 'StatusLineNC', ui_name = 'StatusLineNC', kind = 'ui' } } },
+ [7] = { {}, { { hi_name = 'MsgArea', ui_name = 'MsgArea', kind = 'ui' } } },
})
- command("hi clear VertSplit")
- command("vsplit")
+ command('hi clear WinSeparator')
+ command('vsplit')
screen:expect([[
^ {1:│} |
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|*5
{3:[No Name] }{4:[No Name] }|
{7: }|
]])
- command("hi clear StatusLine | hi clear StatuslineNC")
+ command('hi clear StatusLine | hi clear StatuslineNC')
screen:expect([[
^ {1:│} |
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|*5
{5:[No Name] }{6:[No Name] }|
{7: }|
]])
-- redrawing is done even if visible highlights didn't change
- command("wincmd w")
+ command('wincmd w')
screen:expect([[
{1:│}^ |
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
- {2:~ }{1:│}{2:~ }|
+ {2:~ }{1:│}{2:~ }|*5
{6:[No Name] }{5:[No Name] }|
{7: }|
]])
-
end)
- it("work with window-local highlights", function()
+ it('work with window-local highlights', function()
screen:set_default_attr_ids({
- [1] = {{foreground = Screen.colors.Brown}, {{hi_name = "LineNr", ui_name = "LineNr", kind = "ui"}}},
- [2] = {{bold = true, foreground = Screen.colors.Blue1}, {{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
- [3] = {{bold = true, reverse = true}, {{hi_name = "StatusLine", ui_name = "StatusLine", kind = "ui"}}},
- [4] = {{reverse = true}, {{hi_name = "StatusLineNC", ui_name = "StatusLineNC", kind = "ui"}}},
- [5] = {{background = Screen.colors.Red, foreground = Screen.colors.Grey100}, {{hi_name = "ErrorMsg", ui_name = "LineNr", kind = "ui"}}},
- [6] = {{bold = true, reverse = true}, {{hi_name = "Normal", ui_name = "Normal", kind = "ui"}}},
- [7] = {{foreground = Screen.colors.Brown, bold = true, reverse = true}, {6, 1}},
- [8] = {{foreground = Screen.colors.Blue1, bold = true, reverse = true}, {6, 14}},
- [9] = {{bold = true, foreground = Screen.colors.Brown}, {{hi_name = "NormalNC", ui_name = "NormalNC", kind = "ui"}}},
- [10] = {{bold = true, foreground = Screen.colors.Brown}, {9, 1}},
- [11] = {{bold = true, foreground = Screen.colors.Blue1}, {9, 14}},
- [12] = {{}, {{hi_name = "MsgArea", ui_name = "MsgArea", kind = "ui"}}},
- [13] = {{background = Screen.colors.Red1, foreground = Screen.colors.Gray100}, {{ui_name = "LineNr", kind = "ui", hi_name = "LineNr"}}};
- [14] = {{bold = true, foreground = Screen.colors.Blue}, {{ui_name = "EndOfBuffer", kind = "ui", hi_name = "EndOfBuffer"}}};
+ [1] = {
+ { foreground = Screen.colors.Brown },
+ { { hi_name = 'LineNr', ui_name = 'LineNr', kind = 'ui' } },
+ },
+ [2] = {
+ { bold = true, foreground = Screen.colors.Blue1 },
+ { { hi_name = 'NonText', ui_name = 'EndOfBuffer', kind = 'ui' } },
+ },
+ [3] = {
+ { bold = true, reverse = true },
+ { { hi_name = 'StatusLine', ui_name = 'StatusLine', kind = 'ui' } },
+ },
+ [4] = {
+ { reverse = true },
+ { { hi_name = 'StatusLineNC', ui_name = 'StatusLineNC', kind = 'ui' } },
+ },
+ [5] = {
+ { background = Screen.colors.Red, foreground = Screen.colors.Grey100 },
+ { { hi_name = 'ErrorMsg', ui_name = 'LineNr', kind = 'ui' } },
+ },
+ [6] = {
+ { bold = true, reverse = true },
+ { { hi_name = 'Normal', ui_name = 'Normal', kind = 'ui' } },
+ },
+ [7] = { { foreground = Screen.colors.Brown, bold = true, reverse = true }, { 6, 1 } },
+ [8] = { { foreground = Screen.colors.Blue1, bold = true, reverse = true }, { 6, 14 } },
+ [9] = {
+ { bold = true, foreground = Screen.colors.Brown },
+ { { hi_name = 'NormalNC', ui_name = 'NormalNC', kind = 'ui' } },
+ },
+ [10] = { { bold = true, foreground = Screen.colors.Brown }, { 9, 1 } },
+ [11] = { { bold = true, foreground = Screen.colors.Blue1 }, { 9, 14 } },
+ [12] = { {}, { { hi_name = 'MsgArea', ui_name = 'MsgArea', kind = 'ui' } } },
+ [13] = {
+ { background = Screen.colors.Red1, foreground = Screen.colors.Gray100 },
+ { { ui_name = 'LineNr', kind = 'ui', hi_name = 'LineNr' } },
+ },
+ [14] = {
+ { bold = true, foreground = Screen.colors.Blue },
+ { { ui_name = 'EndOfBuffer', kind = 'ui', hi_name = 'EndOfBuffer' } },
+ },
})
- command("set number")
- command("split")
+ command('set number')
+ command('split')
-- NormalNC is not applied if not set, to avoid spurious redraws
screen:expect([[
{1: 1 }^ |
- {2:~ }|
- {2:~ }|
+ {2:~ }|*2
{3:[No Name] }|
{1: 1 } |
{2:~ }|
@@ -145,23 +175,23 @@ describe('ext_hlstate detailed highlights', function()
{12: }|
]])
- command("set winhl=LineNr:ErrorMsg")
- screen:expect{grid=[[
+ command('set winhl=LineNr:ErrorMsg')
+ screen:expect {
+ grid = [[
{13: 1 }^ |
- {14:~ }|
- {14:~ }|
+ {14:~ }|*2
{3:[No Name] }|
{1: 1 } |
{2:~ }|
{4:[No Name] }|
{12: }|
- ]]}
+ ]],
+ }
- command("set winhl=Normal:MsgSeparator,NormalNC:Statement")
+ command('set winhl=Normal:MsgSeparator,NormalNC:Statement')
screen:expect([[
{7: 1 }{6:^ }|
- {8:~ }|
- {8:~ }|
+ {8:~ }|*2
{3:[No Name] }|
{1: 1 } |
{2:~ }|
@@ -169,11 +199,10 @@ describe('ext_hlstate detailed highlights', function()
{12: }|
]])
- command("wincmd w")
+ command('wincmd w')
screen:expect([[
{10: 1 }{9: }|
- {11:~ }|
- {11:~ }|
+ {11:~ }|*2
{4:[No Name] }|
{1: 1 }^ |
{2:~ }|
@@ -182,27 +211,28 @@ describe('ext_hlstate detailed highlights', function()
]])
end)
- it("work with :terminal", function()
+ it('work with :terminal', function()
skip(is_os('win'))
screen:set_default_attr_ids({
- [1] = {{}, {{hi_name = "TermCursorNC", ui_name = "TermCursorNC", kind = "ui"}}},
- [2] = {{foreground = tonumber('0x00ccff'), fg_indexed=true}, {{kind = "term"}}},
- [3] = {{bold = true, foreground = tonumber('0x00ccff'), fg_indexed=true}, {{kind = "term"}}},
- [4] = {{foreground = tonumber('0x00ccff'), fg_indexed=true}, {2, 1}},
- [5] = {{foreground = tonumber('0x40ffff'), fg_indexed=true}, {{kind = "term"}}},
- [6] = {{foreground = tonumber('0x40ffff'), fg_indexed=true}, {5, 1}},
- [7] = {{}, {{hi_name = "MsgArea", ui_name = "MsgArea", kind = "ui"}}},
+ [1] = { {}, { { hi_name = 'TermCursorNC', ui_name = 'TermCursorNC', kind = 'ui' } } },
+ [2] = { { foreground = tonumber('0x00ccff'), fg_indexed = true }, { { kind = 'term' } } },
+ [3] = {
+ { bold = true, foreground = tonumber('0x00ccff'), fg_indexed = true },
+ {
+ { kind = 'term' },
+ },
+ },
+ [4] = { { foreground = tonumber('0x00ccff'), fg_indexed = true }, { 2, 1 } },
+ [5] = { { foreground = tonumber('0x40ffff'), fg_indexed = true }, { { kind = 'term' } } },
+ [6] = { { foreground = tonumber('0x40ffff'), fg_indexed = true }, { 5, 1 } },
+ [7] = { {}, { { hi_name = 'MsgArea', ui_name = 'MsgArea', kind = 'ui' } } },
})
command(("enew | call termopen(['%s'])"):format(testprg('tty-test')))
screen:expect([[
^tty ready |
{1: } |
- |
- |
- |
- |
- |
+ |*5
{7: }|
]])
@@ -217,10 +247,7 @@ describe('ext_hlstate detailed highlights', function()
^tty ready |
x {5:y z} |
{1: } |
- |
- |
- |
- |
+ |*4
{7: }|
]])
else
@@ -228,72 +255,337 @@ describe('ext_hlstate detailed highlights', function()
^tty ready |
x {2:y }{3:z} |
{1: } |
- |
- |
- |
- |
+ |*4
{7: }|
]])
end
- thelpers.feed_termcode("[A")
- thelpers.feed_termcode("[2C")
+ thelpers.feed_termcode('[A')
+ thelpers.feed_termcode('[2C')
if is_os('win') then
screen:expect([[
^tty ready |
x {6:y}{5: z} |
- |
- |
- |
- |
- |
+ |*5
{7: }|
]])
else
screen:expect([[
^tty ready |
x {4:y}{2: }{3:z} |
- |
- |
- |
- |
- |
+ |*5
{7: }|
]])
end
end)
- it("can use independent cterm and rgb colors", function()
+ it('can use independent cterm and rgb colors', function()
-- tell test module to save all attributes (doesn't change nvim options)
screen:set_rgb_cterm(true)
screen:set_default_attr_ids({
- [1] = {{bold = true, foreground = Screen.colors.Blue1}, {foreground = 12}, {{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
- [2] = {{reverse = true, foreground = Screen.colors.Red}, {foreground = 10, italic=true}, {{hi_name = "NonText", ui_name = "EndOfBuffer", kind = "ui"}}},
- [3] = {{}, {}, {{hi_name = "MsgArea", ui_name = "MsgArea", kind = "ui"}}},
+ [1] = {
+ { bold = true, foreground = Screen.colors.Blue1 },
+ { foreground = 12 },
+ { { hi_name = 'NonText', ui_name = 'EndOfBuffer', kind = 'ui' } },
+ },
+ [2] = {
+ { reverse = true, foreground = Screen.colors.Red },
+ { foreground = 10, italic = true },
+ { { hi_name = 'NonText', ui_name = 'EndOfBuffer', kind = 'ui' } },
+ },
+ [3] = { {}, {}, { { hi_name = 'MsgArea', ui_name = 'MsgArea', kind = 'ui' } } },
})
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
{3: }|
]])
- command("hi NonText guifg=Red gui=reverse ctermfg=Green cterm=italic")
+ command('hi NonText guifg=Red gui=reverse ctermfg=Green cterm=italic')
screen:expect([[
^ |
+ {2:~ }|*6
+ {3: }|
+ ]])
+ end)
+
+ it('combines deleted extmark highlights', function()
+ insert([[
+ line1
+ line2
+ line3
+ line4
+ line5
+ line6]])
+
+ screen:expect {
+ grid = [[
+ line1 |
+ line2 |
+ line3 |
+ line4 |
+ line5 |
+ line^6 |
+ {1:~ }|
+ {2: }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.Blue, bold = true },
+ { { ui_name = 'EndOfBuffer', hi_name = 'NonText', kind = 'ui' } },
+ },
+ [2] = { {}, { { ui_name = 'MsgArea', hi_name = 'MsgArea', kind = 'ui' } } },
+ },
+ }
+
+ local ns = api.nvim_create_namespace('test')
+
+ local add_indicator = function(line, col)
+ api.nvim_buf_set_extmark(0, ns, line, col, {
+ hl_mode = 'combine',
+ priority = 2,
+ right_gravity = false,
+ virt_text = { { '|', 'Delimiter' } },
+ virt_text_win_col = 0,
+ virt_text_pos = 'overlay',
+ })
+ end
+
+ add_indicator(1, 0)
+ add_indicator(2, 0)
+ add_indicator(3, 0)
+ add_indicator(4, 0)
+
+ screen:expect {
+ grid = [[
+ line1 |
+ {1:|} line2 |
+ {1:|} line3 |
+ {1:|} line4 |
+ {1:|} line5 |
+ line^6 |
{2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {3: }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { hi_name = 'Special', kind = 'syntax' } },
+ },
+ [2] = {
+ { bold = true, foreground = Screen.colors.Blue },
+ { { ui_name = 'EndOfBuffer', kind = 'ui', hi_name = 'NonText' } },
+ },
+ [3] = { {}, { { ui_name = 'MsgArea', kind = 'ui', hi_name = 'MsgArea' } } },
+ },
+ }
+
+ helpers.feed('3ggV2jd')
+ --screen:redraw_debug()
+ screen:expect {
+ grid = [[
+ line1 |
+ {1:|} line2 |
+ {2:^|}ine6 |
+ {3:~ }|*4
+ {4:3 fewer lines }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { kind = 'syntax', hi_name = 'Special' } },
+ },
+ [2] = { { foreground = Screen.colors.SlateBlue }, { 1, 1, 1 } },
+ [3] = {
+ { bold = true, foreground = Screen.colors.Blue },
+ { { kind = 'ui', ui_name = 'EndOfBuffer', hi_name = 'NonText' } },
+ },
+ [4] = { {}, { { kind = 'ui', ui_name = 'MsgArea', hi_name = 'MsgArea' } } },
+ },
+ }
+ end)
+
+ it('removes deleted extmark highlights with invalidate', function()
+ insert([[
+ line1
+ line2
+ line3
+ line4
+ line5
+ line6]])
+
+ screen:expect {
+ grid = [[
+ line1 |
+ line2 |
+ line3 |
+ line4 |
+ line5 |
+ line^6 |
+ {1:~ }|
+ {2: }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.Blue, bold = true },
+ { { ui_name = 'EndOfBuffer', hi_name = 'NonText', kind = 'ui' } },
+ },
+ [2] = { {}, { { ui_name = 'MsgArea', hi_name = 'MsgArea', kind = 'ui' } } },
+ },
+ }
+
+ local ns = api.nvim_create_namespace('test')
+
+ local add_indicator = function(line, col)
+ api.nvim_buf_set_extmark(0, ns, line, col, {
+ hl_mode = 'combine',
+ priority = 2,
+ right_gravity = false,
+ virt_text = { { '|', 'Delimiter' } },
+ virt_text_win_col = 0,
+ virt_text_pos = 'overlay',
+ invalidate = true,
+ })
+ end
+
+ add_indicator(1, 0)
+ add_indicator(2, 0)
+ add_indicator(3, 0)
+ add_indicator(4, 0)
+
+ screen:expect {
+ grid = [[
+ line1 |
+ {1:|} line2 |
+ {1:|} line3 |
+ {1:|} line4 |
+ {1:|} line5 |
+ line^6 |
{2:~ }|
{3: }|
- ]])
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { hi_name = 'Special', kind = 'syntax' } },
+ },
+ [2] = {
+ { bold = true, foreground = Screen.colors.Blue },
+ { { ui_name = 'EndOfBuffer', kind = 'ui', hi_name = 'NonText' } },
+ },
+ [3] = { {}, { { ui_name = 'MsgArea', kind = 'ui', hi_name = 'MsgArea' } } },
+ },
+ }
+ helpers.feed('3ggV2jd')
+ --screen:redraw_debug()
+ screen:expect {
+ grid = [[
+ line1 |
+ {1:|} line2 |
+ ^line6 |
+ {2:~ }|*4
+ {3:3 fewer lines }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { kind = 'syntax', hi_name = 'Special' } },
+ },
+ [2] = {
+ { foreground = Screen.colors.Blue, bold = true },
+ { { kind = 'ui', ui_name = 'EndOfBuffer', hi_name = 'NonText' } },
+ },
+ [3] = { {}, { { kind = 'ui', ui_name = 'MsgArea', hi_name = 'MsgArea' } } },
+ },
+ }
+ end)
+
+ it('does not hang when combining too many highlights', function()
+ local num_lines = 500
+ insert('first line\n')
+ for _ = 1, num_lines do
+ insert([[
+ line
+ ]])
+ end
+ insert('last line')
+
+ helpers.feed('gg')
+ screen:expect {
+ grid = [[
+ ^first line |
+ line |*6
+ {1: }|
+ ]],
+ attr_ids = {
+ [1] = { {}, { { kind = 'ui', hi_name = 'MsgArea', ui_name = 'MsgArea' } } },
+ },
+ }
+ local ns = api.nvim_create_namespace('test')
+
+ local add_indicator = function(line, col)
+ api.nvim_buf_set_extmark(0, ns, line, col, {
+ hl_mode = 'combine',
+ priority = 2,
+ right_gravity = false,
+ virt_text = { { '|', 'Delimiter' } },
+ virt_text_win_col = 0,
+ virt_text_pos = 'overlay',
+ })
+ end
+
+ for i = 1, num_lines do
+ add_indicator(i, 0)
+ end
+
+ screen:expect {
+ grid = [[
+ ^first line |
+ {1:|} line |*6
+ {2: }|
+ ]],
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { kind = 'syntax', hi_name = 'Special' } },
+ },
+ [2] = { {}, { { kind = 'ui', ui_name = 'MsgArea', hi_name = 'MsgArea' } } },
+ },
+ }
+
+ helpers.feed(string.format('3ggV%ijd', num_lines - 2))
+ --screen:redraw_debug(nil, nil, 100000)
+
+ local expected_ids = {}
+ for i = 1, num_lines - 1 do
+ expected_ids[i] = 1
+ end
+ screen:expect {
+ grid = string.format(
+ [[
+ first line |
+ {1:|} line |
+ {2:^|}ast line |
+ {3:~ }|*4
+ {4:%-40s}|
+ ]],
+ tostring(num_lines - 1) .. ' fewer lines'
+ ),
+ attr_ids = {
+ [1] = {
+ { foreground = Screen.colors.SlateBlue },
+ { { kind = 'syntax', hi_name = 'Special' } },
+ },
+ [2] = { { foreground = Screen.colors.SlateBlue }, expected_ids },
+ [3] = {
+ { foreground = Screen.colors.Blue, bold = true },
+ { { kind = 'ui', hi_name = 'NonText', ui_name = 'EndOfBuffer' } },
+ },
+ [4] = { {}, { { kind = 'ui', hi_name = 'MsgArea', ui_name = 'MsgArea' } } },
+ },
+ timeout = 100000,
+ }
end)
end)
diff --git a/test/functional/ui/inccommand_spec.lua b/test/functional/ui/inccommand_spec.lua
index 3ee67a710c..29c8c43ca1 100644
--- a/test/functional/ui/inccommand_spec.lua
+++ b/test/functional/ui/inccommand_spec.lua
@@ -4,18 +4,17 @@ local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
-local feed_command = helpers.feed_command
local expect = helpers.expect
local feed = helpers.feed
local insert = helpers.insert
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local neq = helpers.neq
local ok = helpers.ok
local retry = helpers.retry
local source = helpers.source
local poke_eventloop = helpers.poke_eventloop
-local nvim = helpers.nvim
-local sleep = helpers.sleep
+local sleep = vim.uv.sleep
local testprg = helpers.testprg
local assert_alive = helpers.assert_alive
@@ -32,7 +31,7 @@ local multiline_text = [[
7 8 9
]]
-local multimatch_text = [[
+local multimatch_text = [[
a bdc eae a fgl lzia r
x
]]
@@ -62,70 +61,70 @@ local long_multiline_text = [[
local function common_setup(screen, inccommand, text)
if screen then
- command("syntax on")
- command("set nohlsearch")
- command("hi Substitute guifg=red guibg=yellow")
+ command('syntax on')
+ command('set nohlsearch')
+ command('hi Substitute guifg=red guibg=yellow')
screen:attach()
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.Fuchsia},
- [2] = {foreground = Screen.colors.Brown, bold = true},
- [3] = {foreground = Screen.colors.SlateBlue},
- [4] = {bold = true, foreground = Screen.colors.SlateBlue},
- [5] = {foreground = Screen.colors.DarkCyan},
- [6] = {bold = true},
- [7] = {underline = true, bold = true, foreground = Screen.colors.SlateBlue},
- [8] = {foreground = Screen.colors.Slateblue, underline = true},
- [9] = {background = Screen.colors.Yellow},
- [10] = {reverse = true},
- [11] = {reverse = true, bold=true},
- [12] = {foreground = Screen.colors.Red, background = Screen.colors.Yellow},
- [13] = {bold = true, foreground = Screen.colors.SeaGreen},
- [14] = {foreground = Screen.colors.White, background = Screen.colors.Red},
- [15] = {bold=true, foreground=Screen.colors.Blue},
- [16] = {background=Screen.colors.Grey90}, -- cursorline
- [17] = {foreground = Screen.colors.Blue1},
- vis = {background=Screen.colors.LightGrey}
+ [1] = { foreground = Screen.colors.Fuchsia },
+ [2] = { foreground = Screen.colors.Brown, bold = true },
+ [3] = { foreground = Screen.colors.SlateBlue },
+ [4] = { bold = true, foreground = Screen.colors.SlateBlue },
+ [5] = { foreground = Screen.colors.DarkCyan },
+ [6] = { bold = true },
+ [7] = { underline = true, bold = true, foreground = Screen.colors.SlateBlue },
+ [8] = { foreground = Screen.colors.Slateblue, underline = true },
+ [9] = { background = Screen.colors.Yellow },
+ [10] = { reverse = true },
+ [11] = { reverse = true, bold = true },
+ [12] = { foreground = Screen.colors.Red, background = Screen.colors.Yellow },
+ [13] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [14] = { foreground = Screen.colors.White, background = Screen.colors.Red },
+ [15] = { bold = true, foreground = Screen.colors.Blue },
+ [16] = { background = Screen.colors.Grey90 }, -- cursorline
+ [17] = { foreground = Screen.colors.Blue1 },
+ vis = { background = Screen.colors.LightGrey },
})
end
- command("set inccommand=" .. (inccommand or ""))
+ command('set inccommand=' .. (inccommand or ''))
if text then
insert(text)
end
end
-describe(":substitute, inccommand=split interactivity", function()
+describe(':substitute, inccommand=split interactivity', function()
before_each(function()
clear()
- common_setup(nil, "split", default_text)
+ common_setup(nil, 'split', default_text)
end)
-- Test the tests: verify that the `1==bufnr('$')` assertion
-- in the "no preview" tests (below) actually means something.
- it("previews interactive cmdline", function()
+ it('previews interactive cmdline', function()
feed(':%s/tw/MO/g')
retry(nil, 1000, function()
eq(2, eval("bufnr('$')"))
end)
end)
- it("no preview if invoked by a script", function()
+ it('no preview if invoked by a script', function()
source('%s/tw/MO/g')
poke_eventloop()
eq(1, eval("bufnr('$')"))
-- sanity check: assert the buffer state
- expect(default_text:gsub("tw", "MO"))
+ expect(default_text:gsub('tw', 'MO'))
end)
- it("no preview if invoked by feedkeys()", function()
+ it('no preview if invoked by feedkeys()', function()
-- in a script...
source([[:call feedkeys(":%s/tw/MO/g\<CR>")]])
-- or interactively...
feed([[:call feedkeys(":%s/bs/BUU/g\<lt>CR>")<CR>]])
eq(1, eval("bufnr('$')"))
-- sanity check: assert the buffer state
- expect(default_text:gsub("tw", "MO"):gsub("bs", "BUU"))
+ expect(default_text:gsub('tw', 'MO'):gsub('bs', 'BUU'))
end)
end)
@@ -133,17 +132,17 @@ describe(":substitute, 'inccommand' preserves", function()
before_each(clear)
it('listed buffers (:ls)', function()
- local screen = Screen.new(30,10)
- common_setup(screen, "split", "ABC")
+ local screen = Screen.new(30, 10)
+ common_setup(screen, 'split', 'ABC')
- feed_command("%s/AB/BA/")
- feed_command("ls")
+ feed(':%s/AB/BA/')
+ poke_eventloop()
+ feed('<CR>')
+ feed(':ls<CR>')
screen:expect([[
BAC |
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*3
{11: }|
:ls |
1 %a + "[No Name]" |
@@ -153,43 +152,68 @@ describe(":substitute, 'inccommand' preserves", function()
]])
end)
- for _, case in pairs{"", "split", "nosplit"} do
- it("various delimiters (inccommand="..case..")", function()
+ it("'[ and '] marks #26439", function()
+ local screen = Screen.new(30, 10)
+ common_setup(screen, 'nosplit', ('abc\ndef\n'):rep(50))
+
+ feed('ggyG')
+ local X = api.nvim_get_vvar('maxcol')
+ eq({ 0, 1, 1, 0 }, fn.getpos("'["))
+ eq({ 0, 101, X, 0 }, fn.getpos("']"))
+
+ feed(":'[,']s/def/")
+ poke_eventloop()
+ eq({ 0, 1, 1, 0 }, fn.getpos("'["))
+ eq({ 0, 101, X, 0 }, fn.getpos("']"))
+
+ feed('DEF/g')
+ poke_eventloop()
+ eq({ 0, 1, 1, 0 }, fn.getpos("'["))
+ eq({ 0, 101, X, 0 }, fn.getpos("']"))
+
+ feed('<CR>')
+ expect(('abc\nDEF\n'):rep(50))
+ end)
+
+ for _, case in pairs { '', 'split', 'nosplit' } do
+ it('various delimiters (inccommand=' .. case .. ')', function()
insert(default_text)
- feed_command("set inccommand=" .. case)
+ command('set inccommand=' .. case)
local delims = { '/', '#', ';', '%', ',', '@', '!' }
- for _,delim in pairs(delims) do
- feed_command("%s"..delim.."lines"..delim.."LINES"..delim.."g")
+ for _, delim in pairs(delims) do
+ feed(':%s' .. delim .. 'lines' .. delim .. 'LINES' .. delim .. 'g')
+ poke_eventloop()
+ feed('<CR>')
expect([[
Inc substitution on
two LINES
]])
- feed_command("undo")
+ command('undo')
end
end)
end
- for _, case in pairs{"", "split", "nosplit"} do
- it("'undolevels' (inccommand="..case..")", function()
- feed_command("set undolevels=139")
- feed_command("setlocal undolevels=34")
- feed_command("split") -- Show the buffer in multiple windows
- feed_command("set inccommand=" .. case)
- insert("as")
- feed(":%s/as/glork/")
+ for _, case in pairs { '', 'split', 'nosplit' } do
+ it("'undolevels' (inccommand=" .. case .. ')', function()
+ command('set undolevels=139')
+ command('setlocal undolevels=34')
+ command('split') -- Show the buffer in multiple windows
+ command('set inccommand=' .. case)
+ insert('as')
+ feed(':%s/as/glork/')
poke_eventloop()
- feed("<enter>")
- eq(meths.get_option_value('undolevels', {scope='global'}), 139)
- eq(meths.get_option_value('undolevels', {buf=0}), 34)
+ feed('<enter>')
+ eq(api.nvim_get_option_value('undolevels', { scope = 'global' }), 139)
+ eq(api.nvim_get_option_value('undolevels', { buf = 0 }), 34)
end)
end
- for _, case in ipairs({"", "split", "nosplit"}) do
- it("empty undotree() (inccommand="..case..")", function()
- feed_command("set undolevels=1000")
- feed_command("set inccommand=" .. case)
- local expected_undotree = eval("undotree()")
+ for _, case in ipairs({ '', 'split', 'nosplit' }) do
+ it('empty undotree() (inccommand=' .. case .. ')', function()
+ command('set undolevels=1000')
+ command('set inccommand=' .. case)
+ local expected_undotree = eval('undotree()')
-- Start typing an incomplete :substitute command.
feed([[:%s/e/YYYY/g]])
@@ -198,15 +222,15 @@ describe(":substitute, 'inccommand' preserves", function()
feed([[<C-\><C-N>]])
-- The undo tree should be unchanged.
- eq(expected_undotree, eval("undotree()"))
- eq({}, eval("undotree()")["entries"])
+ eq(expected_undotree, eval('undotree()'))
+ eq({}, eval('undotree()')['entries'])
end)
end
- for _, case in ipairs({"", "split", "nosplit"}) do
- it("undotree() with branches (inccommand="..case..")", function()
- feed_command("set undolevels=1000")
- feed_command("set inccommand=" .. case)
+ for _, case in ipairs({ '', 'split', 'nosplit' }) do
+ it('undotree() with branches (inccommand=' .. case .. ')', function()
+ command('set undolevels=1000')
+ command('set inccommand=' .. case)
-- Make some changes.
feed([[isome text 1<C-\><C-N>]])
feed([[osome text 2<C-\><C-N>]])
@@ -224,8 +248,8 @@ describe(":substitute, 'inccommand' preserves", function()
some text 1
some text 3XX
some text 5]])
- local expected_undotree = eval("undotree()")
- eq(5, #expected_undotree["entries"]) -- sanity
+ local expected_undotree = eval('undotree()')
+ eq(5, #expected_undotree['entries']) -- sanity
-- Start typing an incomplete :substitute command.
feed([[:%s/e/YYYY/g]])
@@ -234,31 +258,31 @@ describe(":substitute, 'inccommand' preserves", function()
feed([[<C-\><C-N>]])
-- The undo tree should be unchanged.
- eq(expected_undotree, eval("undotree()"))
+ eq(expected_undotree, eval('undotree()'))
end)
end
- for _, case in pairs{"", "split", "nosplit"} do
- it("b:changedtick (inccommand="..case..")", function()
- feed_command("set inccommand=" .. case)
+ for _, case in pairs { '', 'split', 'nosplit' } do
+ it('b:changedtick (inccommand=' .. case .. ')', function()
+ command('set inccommand=' .. case)
feed([[isome text 1<C-\><C-N>]])
feed([[osome text 2<C-\><C-N>]])
- local expected_tick = eval("b:changedtick")
+ local expected_tick = eval('b:changedtick')
ok(expected_tick > 0)
expect([[
some text 1
some text 2]])
- feed(":%s/e/XXX/")
+ feed(':%s/e/XXX/')
poke_eventloop()
- eq(expected_tick, eval("b:changedtick"))
+ eq(expected_tick, eval('b:changedtick'))
end)
end
- for _, case in ipairs({'', 'split', 'nosplit'}) do
- it('previous substitute string ~ (inccommand='..case..') #12109', function()
- local screen = Screen.new(30,10)
+ for _, case in ipairs({ '', 'split', 'nosplit' }) do
+ it('previous substitute string ~ (inccommand=' .. case .. ') #12109', function()
+ local screen = Screen.new(30, 10)
common_setup(screen, case, default_text)
feed(':%s/Inc/SUB<CR>')
@@ -323,47 +347,51 @@ describe(":substitute, 'inccommand' preserves", function()
end)
describe(":substitute, 'inccommand' preserves undo", function()
- local cases = { "", "split", "nosplit" }
+ local cases = { '', 'split', 'nosplit' }
local substrings = {
- ":%s/1",
- ":%s/1/",
- ":%s/1/<bs>",
- ":%s/1/a",
- ":%s/1/a<bs>",
- ":%s/1/ax",
- ":%s/1/ax<bs>",
- ":%s/1/ax<bs><bs>",
- ":%s/1/ax<bs><bs><bs>",
- ":%s/1/ax/",
- ":%s/1/ax/<bs>",
- ":%s/1/ax/<bs>/",
- ":%s/1/ax/g",
- ":%s/1/ax/g<bs>",
- ":%s/1/ax/g<bs><bs>"
+ { ':%s/', '1' },
+ { ':%s/', '1', '/' },
+ { ':%s/', '1', '/', '<bs>' },
+ { ':%s/', '1', '/', 'a' },
+ { ':%s/', '1', '/', 'a', '<bs>' },
+ { ':%s/', '1', '/', 'a', 'x' },
+ { ':%s/', '1', '/', 'a', 'x', '<bs>' },
+ { ':%s/', '1', '/', 'a', 'x', '<bs>', '<bs>' },
+ { ':%s/', '1', '/', 'a', 'x', '<bs>', '<bs>', '<bs>' },
+ { ':%s/', '1', '/', 'a', 'x', '/' },
+ { ':%s/', '1', '/', 'a', 'x', '/', '<bs>' },
+ { ':%s/', '1', '/', 'a', 'x', '/', '<bs>', '/' },
+ { ':%s/', '1', '/', 'a', 'x', '/', 'g' },
+ { ':%s/', '1', '/', 'a', 'x', '/', 'g', '<bs>' },
+ { ':%s/', '1', '/', 'a', 'x', '/', 'g', '<bs>', '<bs>' },
}
local function test_sub(substring, split, redoable)
command('bwipe!')
- feed_command("set inccommand=" .. split)
+ command('set inccommand=' .. split)
- insert("1")
- feed("o2<esc>")
- feed_command("undo")
- feed("o3<esc>")
+ insert('1')
+ feed('o2<esc>')
+ command('undo')
+ feed('o3<esc>')
if redoable then
- feed("o4<esc>")
- feed_command("undo")
+ feed('o4<esc>')
+ command('undo')
+ end
+ for _, s in pairs(substring) do
+ feed(s)
end
- feed(substring.. "<enter>")
- feed_command("undo")
+ poke_eventloop()
+ feed('<enter>')
+ command('undo')
- feed("g-")
+ feed('g-')
expect([[
1
2]])
- feed("g+")
+ feed('g+')
expect([[
1
3]])
@@ -371,30 +399,34 @@ describe(":substitute, 'inccommand' preserves undo", function()
local function test_notsub(substring, split, redoable)
command('bwipe!')
- feed_command("set inccommand=" .. split)
+ command('set inccommand=' .. split)
- insert("1")
- feed("o2<esc>")
- feed_command("undo")
- feed("o3<esc>")
+ insert('1')
+ feed('o2<esc>')
+ command('undo')
+ feed('o3<esc>')
if redoable then
- feed("o4<esc>")
- feed_command("undo")
+ feed('o4<esc>')
+ command('undo')
+ end
+ for _, s in pairs(substring) do
+ feed(s)
end
- feed(substring .. "<esc>")
+ poke_eventloop()
+ feed('<esc>')
- feed("g-")
+ feed('g-')
expect([[
1
2]])
- feed("g+")
+ feed('g+')
expect([[
1
3]])
if redoable then
- feed("<c-r>")
+ feed('<c-r>')
expect([[
1
3
@@ -402,20 +434,19 @@ describe(":substitute, 'inccommand' preserves undo", function()
end
end
-
local function test_threetree(substring, split)
command('bwipe!')
- feed_command("set inccommand=" .. split)
-
- insert("1")
- feed("o2<esc>")
- feed("o3<esc>")
- feed("uu")
- feed("oa<esc>")
- feed("ob<esc>")
- feed("uu")
- feed("oA<esc>")
- feed("oB<esc>")
+ command('set inccommand=' .. split)
+
+ insert('1')
+ feed('o2<esc>')
+ feed('o3<esc>')
+ feed('uu')
+ feed('oa<esc>')
+ feed('ob<esc>')
+ feed('uu')
+ feed('oA<esc>')
+ feed('oB<esc>')
-- This is the undo tree (x-Axis is timeline), we're at B now
-- ----------------A - B
@@ -424,33 +455,45 @@ describe(":substitute, 'inccommand' preserves undo", function()
-- |/
-- 1 - 2 - 3
- feed("2u")
- feed(substring .. "<esc>")
+ feed('2u')
+ for _, s in pairs(substring) do
+ feed(s)
+ poke_eventloop()
+ end
+ feed('<esc>')
expect([[
1]])
- feed("g-")
+ feed('g-')
expect([[
]])
- feed("g+")
+ feed('g+')
expect([[
1]])
- feed("<c-r>")
+ feed('<c-r>')
expect([[
1
A]])
- feed("g-") -- go to b
- feed("2u")
- feed(substring .. "<esc>")
- feed("<c-r>")
+ feed('g-') -- go to b
+ feed('2u')
+ for _, s in pairs(substring) do
+ feed(s)
+ poke_eventloop()
+ end
+ feed('<esc>')
+ feed('<c-r>')
expect([[
1
a]])
- feed("g-") -- go to 3
- feed("2u")
- feed(substring .. "<esc>")
- feed("<c-r>")
+ feed('g-') -- go to 3
+ feed('2u')
+ for _, s in pairs(substring) do
+ feed(s)
+ poke_eventloop()
+ end
+ feed('<esc>')
+ feed('<c-r>')
expect([[
1
2]])
@@ -458,37 +501,37 @@ describe(":substitute, 'inccommand' preserves undo", function()
before_each(clear)
- it("at a non-leaf of the undo tree", function()
- for _, case in pairs(cases) do
- for _, str in pairs(substrings) do
- for _, redoable in pairs({true}) do
- test_sub(str, case, redoable)
- end
- end
- end
+ it('at a non-leaf of the undo tree', function()
+ for _, case in pairs(cases) do
+ for _, str in pairs(substrings) do
+ for _, redoable in pairs({ true }) do
+ test_sub(str, case, redoable)
+ end
+ end
+ end
end)
- it("at a leaf of the undo tree", function()
+ it('at a leaf of the undo tree', function()
for _, case in pairs(cases) do
for _, str in pairs(substrings) do
- for _, redoable in pairs({false}) do
+ for _, redoable in pairs({ false }) do
test_sub(str, case, redoable)
end
end
end
end)
- it("when interrupting substitution", function()
+ it('when interrupting substitution', function()
for _, case in pairs(cases) do
for _, str in pairs(substrings) do
- for _, redoable in pairs({true,false}) do
+ for _, redoable in pairs({ true, false }) do
test_notsub(str, case, redoable)
end
end
end
end)
- it("in a complex undo scenario", function()
+ it('in a complex undo scenario', function()
for _, case in pairs(cases) do
for _, str in pairs(substrings) do
test_threetree(str, case)
@@ -500,28 +543,32 @@ describe(":substitute, 'inccommand' preserves undo", function()
for _, case in pairs(cases) do
clear()
common_setup(nil, case, default_text)
- feed_command("set undolevels=0")
+ command('set undolevels=0')
- feed("1G0")
- insert("X")
- feed(":%s/tw/MO/<esc>")
- feed_command("undo")
+ feed('1G0')
+ insert('X')
+ feed(':%s/tw/MO/')
+ poke_eventloop()
+ feed('<esc>')
+ command('undo')
expect(default_text)
- feed_command("undo")
- expect(default_text:gsub("Inc", "XInc"))
- feed_command("undo")
+ command('undo')
+ expect(default_text:gsub('Inc', 'XInc'))
+ command('undo')
- feed_command("%s/tw/MO/g")
- expect(default_text:gsub("tw", "MO"))
- feed_command("undo")
+ feed(':%s/tw/MO/g')
+ poke_eventloop()
+ feed('<CR>')
+ expect(default_text:gsub('tw', 'MO'))
+ command('undo')
expect(default_text)
- feed_command("undo")
- expect(default_text:gsub("tw", "MO"))
+ command('undo')
+ expect(default_text:gsub('tw', 'MO'))
end
end)
it('with undolevels=1', function()
- local screen = Screen.new(20,10)
+ local screen = Screen.new(20, 10)
for _, case in pairs(cases) do
clear()
@@ -530,46 +577,43 @@ describe(":substitute, 'inccommand' preserves undo", function()
Inc substitution on |
two lines |
^ |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
|
]])
- feed_command("set undolevels=1")
-
- feed("1G0")
- insert("X")
- feed("IY<esc>")
- feed(":%s/tw/MO/<esc>")
- -- feed_command("undo") here would cause "Press ENTER".
- feed("u")
- expect(default_text:gsub("Inc", "XInc"))
- feed("u")
+ command('set undolevels=1')
+
+ feed('1G0')
+ insert('X')
+ feed('IY<esc>')
+ feed(':%s/tw/MO/')
+ poke_eventloop()
+ feed('<esc>')
+ feed('u')
+ expect(default_text:gsub('Inc', 'XInc'))
+ feed('u')
expect(default_text)
- feed(":%s/tw/MO/g<enter>")
- feed(":%s/MO/GO/g<enter>")
- feed(":%s/GO/NO/g<enter>")
- feed("u")
- expect(default_text:gsub("tw", "GO"))
- feed("u")
- expect(default_text:gsub("tw", "MO"))
- feed("u")
+ feed(':%s/tw/MO/g')
+ poke_eventloop()
+ feed('<enter>')
+ feed(':%s/MO/GO/g')
+ poke_eventloop()
+ feed('<enter>')
+ feed(':%s/GO/NO/g')
+ poke_eventloop()
+ feed('<enter>')
+ feed('u')
+ expect(default_text:gsub('tw', 'GO'))
+ feed('u')
+ expect(default_text:gsub('tw', 'MO'))
+ feed('u')
- if case == "split" then
+ if case == 'split' then
screen:expect([[
Inc substitution on |
^MOo lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
Already ...t change |
]])
else
@@ -577,12 +621,7 @@ describe(":substitute, 'inccommand' preserves undo", function()
Inc substitution on |
^MOo lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
Already ...t change |
]])
end
@@ -590,37 +629,33 @@ describe(":substitute, 'inccommand' preserves undo", function()
end)
it('with undolevels=2', function()
- local screen = Screen.new(20,10)
+ local screen = Screen.new(20, 10)
for _, case in pairs(cases) do
clear()
common_setup(screen, case, default_text)
- feed_command("set undolevels=2")
-
- feed("2GAx<esc>")
- feed("Ay<esc>")
- feed("Az<esc>")
- feed(":%s/tw/AR<esc>")
- -- feed_command("undo") here would cause "Press ENTER".
- feed("u")
- expect(default_text:gsub("lines", "linesxy"))
- feed("u")
- expect(default_text:gsub("lines", "linesx"))
- feed("u")
+ command('set undolevels=2')
+
+ feed('2GAx<esc>')
+ feed('Ay<esc>')
+ feed('Az<esc>')
+ feed(':%s/tw/AR')
+ poke_eventloop()
+ feed('<esc>')
+ feed('u')
+ expect(default_text:gsub('lines', 'linesxy'))
+ feed('u')
+ expect(default_text:gsub('lines', 'linesx'))
+ feed('u')
expect(default_text)
- feed("u")
+ feed('u')
- if case == "split" then
+ if case == 'split' then
screen:expect([[
Inc substitution on |
two line^s |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
Already ...t change |
]])
else
@@ -628,39 +663,37 @@ describe(":substitute, 'inccommand' preserves undo", function()
Inc substitution on |
two line^s |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
Already ...t change |
]])
end
- feed(":%s/tw/MO/g<enter>")
- feed(":%s/MO/GO/g<enter>")
- feed(":%s/GO/NO/g<enter>")
- feed(":%s/NO/LO/g<enter>")
- feed("u")
- expect(default_text:gsub("tw", "NO"))
- feed("u")
- expect(default_text:gsub("tw", "GO"))
- feed("u")
- expect(default_text:gsub("tw", "MO"))
- feed("u")
-
- if case == "split" then
+ feed(':%s/tw/MO/g')
+ poke_eventloop()
+ feed('<enter>')
+ feed(':%s/MO/GO/g')
+ poke_eventloop()
+ feed('<enter>')
+ feed(':%s/GO/NO/g')
+ poke_eventloop()
+ feed('<enter>')
+ feed(':%s/NO/LO/g')
+ poke_eventloop()
+ feed('<enter>')
+ feed('u')
+ expect(default_text:gsub('tw', 'NO'))
+ feed('u')
+ expect(default_text:gsub('tw', 'GO'))
+ feed('u')
+ expect(default_text:gsub('tw', 'MO'))
+ feed('u')
+
+ if case == 'split' then
screen:expect([[
Inc substitution on |
^MOo lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
Already ...t change |
]])
else
@@ -668,12 +701,7 @@ describe(":substitute, 'inccommand' preserves undo", function()
Inc substitution on |
^MOo lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
Already ...t change |
]])
end
@@ -681,27 +709,23 @@ describe(":substitute, 'inccommand' preserves undo", function()
end)
it('with undolevels=-1', function()
- local screen = Screen.new(20,10)
+ local screen = Screen.new(20, 10)
for _, case in pairs(cases) do
clear()
common_setup(screen, case, default_text)
- feed_command("set undolevels=-1")
- feed(":%s/tw/MO/g<enter>")
- -- feed_command("undo") here will result in a "Press ENTER" prompt
- feed("u")
- if case == "split" then
+ command('set undolevels=-1')
+ feed(':%s/tw/MO/g')
+ poke_eventloop()
+ feed('<enter>')
+ feed('u')
+ if case == 'split' then
screen:expect([[
Inc substitution on |
^MOo lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
Already ...t change |
]])
else
@@ -709,12 +733,7 @@ describe(":substitute, 'inccommand' preserves undo", function()
Inc substitution on |
^MOo lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
Already ...t change |
]])
end
@@ -723,41 +742,37 @@ describe(":substitute, 'inccommand' preserves undo", function()
clear()
common_setup(screen, case, default_text)
- feed_command("set undolevels=-1")
- feed("1G")
- feed("IL<esc>")
- feed(":%s/tw/MO/g<esc>")
- feed("u")
+ command('set undolevels=-1')
+ feed('1G')
+ feed('IL<esc>')
+ feed(':%s/tw/MO/g')
+ poke_eventloop()
+ feed('<esc>')
+ feed('u')
screen:expect([[
^LInc substitution on|
two lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
Already ...t change |
]])
end
end)
-
end)
-describe(":substitute, inccommand=split", function()
+describe(':substitute, inccommand=split', function()
local screen
before_each(function()
clear()
- screen = Screen.new(30,15)
- common_setup(screen, "split", default_text .. default_text)
+ screen = Screen.new(30, 15)
+ common_setup(screen, 'split', default_text .. default_text)
end)
it("preserves 'modified' buffer flag", function()
- feed_command("set nomodified")
- feed(":%s/tw")
+ command('set nomodified')
+ feed(':%s/tw')
screen:expect([[
Inc substitution on |
{12:tw}o lines |
@@ -767,30 +782,26 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] }|
|2| {12:tw}o lines |
|4| {12:tw}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:%s/tw^ |
]])
- feed([[<C-\><C-N>]]) -- Cancel the :substitute command.
- eq(0, eval("&modified"))
+ feed([[<C-\><C-N>]]) -- Cancel the :substitute command.
+ eq(0, eval('&modified'))
end)
- it("shows preview when cmd modifiers are present", function()
+ it('shows preview when cmd modifiers are present', function()
-- one modifier
feed(':keeppatterns %s/tw/to')
- screen:expect{any=[[{12:to}o lines]]}
+ screen:expect { any = [[{12:to}o lines]] }
feed('<Esc>')
- screen:expect{any=[[two lines]]}
+ screen:expect { any = [[two lines]] }
-- multiple modifiers
feed(':keeppatterns silent %s/tw/to')
- screen:expect{any=[[{12:to}o lines]]}
+ screen:expect { any = [[{12:to}o lines]] }
feed('<Esc>')
- screen:expect{any=[[two lines]]}
+ screen:expect { any = [[two lines]] }
-- non-modifier prefix
feed(':silent tabedit %s/tw/to')
@@ -800,27 +811,19 @@ describe(":substitute, inccommand=split", function()
Inc substitution on |
two lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*9
:silent tabedit %s/tw/to^ |
]])
feed('<Esc>')
-- leading colons
feed(':::%s/tw/to')
- screen:expect{any=[[{12:to}o lines]]}
+ screen:expect { any = [[{12:to}o lines]] }
feed('<Esc>')
- screen:expect{any=[[two lines]]}
+ screen:expect { any = [[two lines]] }
end)
- it("ignores new-window modifiers when splitting the preview window", function()
+ it('ignores new-window modifiers when splitting the preview window', function()
-- one modifier
feed(':topleft %s/tw/to')
screen:expect([[
@@ -832,16 +835,12 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| {12:to}o lines |
|4| {12:to}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:topleft %s/tw/to^ |
]])
feed('<Esc>')
- screen:expect{any=[[two lines]]}
+ screen:expect { any = [[two lines]] }
-- multiple modifiers
feed(':topleft vert %s/tw/to')
@@ -854,20 +853,16 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| {12:to}o lines |
|4| {12:to}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:topleft vert %s/tw/to^ |
]])
feed('<Esc>')
- screen:expect{any=[[two lines]]}
+ screen:expect { any = [[two lines]] }
end)
it('shows split window when typing the pattern', function()
- feed(":%s/tw")
+ feed(':%s/tw')
screen:expect([[
Inc substitution on |
{12:tw}o lines |
@@ -877,18 +872,14 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| {12:tw}o lines |
|4| {12:tw}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:%s/tw^ |
]])
end)
it('shows preview with empty replacement', function()
- feed(":%s/tw/")
+ feed(':%s/tw/')
screen:expect([[
Inc substitution on |
o lines |
@@ -898,16 +889,12 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| o lines |
|4| o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:%s/tw/^ |
]])
- feed("x")
+ feed('x')
screen:expect([[
Inc substitution on |
{12:x}o lines |
@@ -917,16 +904,12 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| {12:x}o lines |
|4| {12:x}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:%s/tw/x^ |
]])
- feed("<bs>")
+ feed('<bs>')
screen:expect([[
Inc substitution on |
o lines |
@@ -936,19 +919,14 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| o lines |
|4| o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:%s/tw/^ |
]])
-
end)
it('shows split window when typing replacement', function()
- feed(":%s/tw/XX")
+ feed(':%s/tw/XX')
screen:expect([[
Inc substitution on |
{12:XX}o lines |
@@ -958,41 +936,29 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| {12:XX}o lines |
|4| {12:XX}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:%s/tw/XX^ |
]])
end)
it('does not show split window for :s/', function()
- feed("2gg")
- feed(":s/tw")
+ feed('2gg')
+ feed(':s/tw')
screen:expect([[
Inc substitution on |
{12:tw}o lines |
Inc substitution on |
two lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*9
:s/tw^ |
]])
end)
it("'hlsearch' is active, 'cursorline' is not", function()
- feed_command("set hlsearch cursorline")
- feed("gg")
+ command('set hlsearch cursorline')
+ feed('gg')
-- Assert that 'cursorline' is active.
screen:expect([[
@@ -1001,19 +967,11 @@ describe(":substitute, inccommand=split", function()
Inc substitution on |
two lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- :set hlsearch cursorline |
+ {15:~ }|*9
+ |
]])
- feed(":%s/tw")
+ feed(':%s/tw')
-- 'cursorline' is NOT active during preview.
screen:expect([[
Inc substitution on |
@@ -1024,11 +982,7 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|2| {12:tw}o lines |
|4| {12:tw}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:%s/tw^ |
]])
@@ -1046,12 +1000,7 @@ describe(":substitute, inccommand=split", function()
two lines |
{11:[No Name] [+] }|
|1| {12:123} {12:123} {12:123} |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{10:[Preview] }|
:%s/M/123/g^ |
]])
@@ -1068,33 +1017,20 @@ describe(":substitute, inccommand=split", function()
|
{11:[No Name] [+] }|
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{10:[Preview] }|
:%s/Inx^ |
]])
end)
it('previews correctly when previewhight is small', function()
- feed_command('set cwh=3')
- feed_command('set hls')
+ command('set cwh=3')
+ command('set hls')
feed('ggdG')
insert(string.rep('abc abc abc\n', 20))
feed(':%s/abc/MMM/g')
screen:expect([[
- {12:MMM} {12:MMM} {12:MMM} |
- {12:MMM} {12:MMM} {12:MMM} |
- {12:MMM} {12:MMM} {12:MMM} |
- {12:MMM} {12:MMM} {12:MMM} |
- {12:MMM} {12:MMM} {12:MMM} |
- {12:MMM} {12:MMM} {12:MMM} |
- {12:MMM} {12:MMM} {12:MMM} |
- {12:MMM} {12:MMM} {12:MMM} |
- {12:MMM} {12:MMM} {12:MMM} |
+ {12:MMM} {12:MMM} {12:MMM} |*9
{11:[No Name] [+] }|
| 1| {12:MMM} {12:MMM} {12:MMM} |
| 2| {12:MMM} {12:MMM} {12:MMM} |
@@ -1105,7 +1041,9 @@ describe(":substitute, inccommand=split", function()
end)
it('actually replaces text', function()
- feed(":%s/tw/XX/g<Enter>")
+ feed(':%s/tw/XX/g')
+ poke_eventloop()
+ feed('<Enter>')
screen:expect([[
Inc substitution on |
@@ -1113,32 +1051,24 @@ describe(":substitute, inccommand=split", function()
Inc substitution on |
^XXo lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*9
:%s/tw/XX/g |
]])
end)
it('shows correct line numbers with many lines', function()
- feed("gg")
- feed("2yy")
- feed("2000p")
- feed_command("1,1000s/tw/BB/g")
+ feed('gg')
+ feed('2yy')
+ feed('2000p')
+ command('1,1000s/tw/BB/g')
- feed(":%s/tw/X")
+ feed(':%s/tw/X')
screen:expect([[
+ Inc substitution on |
BBo lines |
Inc substitution on |
{12:X}o lines |
Inc substitution on |
- {12:X}o lines |
{11:[No Name] [+] }|
|1001| {12:X}o lines |
|1003| {12:X}o lines |
@@ -1155,58 +1085,52 @@ describe(":substitute, inccommand=split", function()
it('does not spam the buffer numbers', function()
-- The preview buffer is re-used (unless user deleted it), so buffer numbers
-- will not increase on each keystroke.
- feed(":%s/tw/Xo/g")
+ feed(':%s/tw/Xo/g')
-- Delete and re-type the g a few times.
- feed("<BS>")
+ feed('<BS>')
poke_eventloop()
- feed("g")
+ feed('g')
poke_eventloop()
- feed("<BS>")
+ feed('<BS>')
poke_eventloop()
- feed("g")
+ feed('g')
poke_eventloop()
- feed("<CR>")
+ feed('<CR>')
poke_eventloop()
- feed(":vs tmp<enter>")
- eq(3, helpers.call('bufnr', '$'))
+ feed(':vs tmp<enter>')
+ eq(3, fn.bufnr('$'))
end)
it('works with the n flag', function()
- feed(":%s/tw/Mix/n<Enter>")
+ feed(':%s/tw/Mix/n')
+ poke_eventloop()
+ feed('<Enter>')
screen:expect([[
Inc substitution on |
two lines |
Inc substitution on |
two lines |
^ |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*9
2 matches on 2 lines |
]])
end)
it("deactivates if 'redrawtime' is exceeded #5602", function()
-- prevent redraws from 'incsearch'
- meths.set_option_value('incsearch', false, {})
+ api.nvim_set_option_value('incsearch', false, {})
-- Assert that 'inccommand' is ENABLED initially.
- eq("split", eval("&inccommand"))
+ eq('split', eval('&inccommand'))
-- Set 'redrawtime' to minimal value, to ensure timeout is triggered.
- feed_command("set redrawtime=1 nowrap")
+ command('set redrawtime=1 nowrap')
-- Load a big file.
- feed_command("silent edit! test/functional/fixtures/bigfile_oneline.txt")
+ command('silent edit! test/functional/fixtures/bigfile_oneline.txt')
-- Start :substitute with a slow pattern.
feed([[:%s/B.*N/x]])
poke_eventloop()
-- Assert that 'inccommand' is DISABLED in cmdline mode.
- eq("", eval("&inccommand"))
+ eq('', eval('&inccommand'))
-- Assert that preview cleared (or never manifested).
screen:expect([[
0000;<control>;Cc;0;BN;;;;;N;N|
@@ -1228,7 +1152,7 @@ describe(":substitute, inccommand=split", function()
-- Assert that 'inccommand' is again ENABLED after leaving cmdline mode.
feed([[<C-\><C-N>]])
- eq("split", eval("&inccommand"))
+ eq('split', eval('&inccommand'))
end)
it("deactivates if 'foldexpr' is slow #9557", function()
@@ -1264,12 +1188,12 @@ describe(":substitute, inccommand=split", function()
end)
end)
- it("clears preview if non-previewable command is edited #5585", function()
+ it('clears preview if non-previewable command is edited #5585', function()
feed('gg')
-- Put a non-previewable command in history.
- feed_command("echo 'foo'")
+ feed(":echo 'foo'<CR>")
-- Start an incomplete :substitute command.
- feed(":1,2s/t/X")
+ feed(':1,2s/t/X')
screen:expect([[
Inc subs{12:X}itution on |
@@ -1280,17 +1204,13 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|1| Inc subs{12:X}itution on |
|2| {12:X}wo lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:1,2s/t/X^ |
]])
-- Select the previous command.
- feed("<C-P>")
+ feed('<C-P>')
-- Assert that preview was cleared.
screen:expect([[
Inc substitution on |
@@ -1298,22 +1218,14 @@ describe(":substitute, inccommand=split", function()
Inc substitution on |
two lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*9
:echo 'foo'^ |
]])
end)
it([[preview changes correctly with c_CTRL-R_= and c_CTRL-\_e]], function()
feed('gg')
- feed(":1,2s/t/X")
+ feed(':1,2s/t/X')
screen:expect([[
Inc subs{12:X}itution on |
{12:X}wo lines |
@@ -1323,11 +1235,7 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|1| Inc subs{12:X}itution on |
|2| {12:X}wo lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:1,2s/t/X^ |
]])
@@ -1343,11 +1251,7 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|1| Inc subs{12:X}itution on |
|2| {12:X}wo lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
={1:'Y'}^ |
]])
@@ -1363,11 +1267,7 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|1| Inc subs{12:XY}itution on |
|2| {12:XY}wo lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:1,2s/t/XY^ |
]])
@@ -1383,11 +1283,7 @@ describe(":substitute, inccommand=split", function()
{11:[No Name] [+] }|
|1| Inc subs{12:XY}itution on |
|2| {12:XY}wo lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
={1:'echo'}^ |
]])
@@ -1400,76 +1296,61 @@ describe(":substitute, inccommand=split", function()
Inc substitution on |
two lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*9
:echo^ |
]])
end)
-
end)
-describe("inccommand=nosplit", function()
+describe('inccommand=nosplit', function()
local screen
before_each(function()
clear()
- screen = Screen.new(20,10)
- common_setup(screen, "nosplit", default_text .. default_text)
+ screen = Screen.new(20, 10)
+ common_setup(screen, 'nosplit', default_text .. default_text)
end)
- it("works with :smagic, :snomagic", function()
- feed_command("set hlsearch")
- insert("Line *.3.* here")
+ it('works with :smagic, :snomagic', function()
+ command('set hlsearch')
+ insert('Line *.3.* here')
- feed(":%smagic/3.*/X") -- start :smagic command
+ feed(':%smagic/3.*/X') -- start :smagic command
screen:expect([[
Inc substitution on |
two lines |
Inc substitution on |
two lines |
Line *.{12:X} |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:%smagic/3.*/X^ |
]])
- feed([[<C-\><C-N>]]) -- cancel
- feed(":%snomagic/3.*/X") -- start :snomagic command
+ feed([[<C-\><C-N>]]) -- cancel
+ feed(':%snomagic/3.*/X') -- start :snomagic command
screen:expect([[
Inc substitution on |
two lines |
Inc substitution on |
two lines |
Line *.{12:X} here |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:%snomagic/3.*/X^ |
]])
end)
- it("shows preview when cmd modifiers are present", function()
+ it('shows preview when cmd modifiers are present', function()
-- one modifier
feed(':keeppatterns %s/tw/to')
- screen:expect{any=[[{12:to}o lines]]}
+ screen:expect { any = [[{12:to}o lines]] }
feed('<Esc>')
- screen:expect{any=[[two lines]]}
+ screen:expect { any = [[two lines]] }
-- multiple modifiers
feed(':keeppatterns silent %s/tw/to')
- screen:expect{any=[[{12:to}o lines]]}
+ screen:expect { any = [[{12:to}o lines]] }
feed('<Esc>')
- screen:expect{any=[[two lines]]}
+ screen:expect { any = [[two lines]] }
-- non-modifier prefix
feed(':silent tabedit %s/tw/to')
@@ -1479,22 +1360,21 @@ describe("inccommand=nosplit", function()
Inc substitution on |
two lines |
|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*2
{11: }|
:silent tabedit %s/t|
w/to^ |
]])
end)
- it("does not show window after toggling :set inccommand", function()
- feed(":%s/tw/OKOK")
- feed("<Esc>")
- command("set icm=split")
- feed(":%s/tw/OKOK")
- feed("<Esc>")
- command("set icm=nosplit")
- feed(":%s/tw/OKOK")
+ it('does not show window after toggling :set inccommand', function()
+ feed(':%s/tw/OKOK')
+ feed('<Esc>')
+ command('set icm=split')
+ feed(':%s/tw/OKOK')
+ feed('<Esc>')
+ command('set icm=nosplit')
+ feed(':%s/tw/OKOK')
poke_eventloop()
screen:expect([[
Inc substitution on |
@@ -1502,79 +1382,64 @@ describe("inccommand=nosplit", function()
Inc substitution on |
{12:OKOK}o lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:%s/tw/OKOK^ |
]])
end)
it('never shows preview buffer', function()
- feed_command("set hlsearch")
+ command('set hlsearch')
- feed(":%s/tw")
+ feed(':%s/tw')
screen:expect([[
Inc substitution on |
{12:tw}o lines |
Inc substitution on |
{12:tw}o lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:%s/tw^ |
]])
- feed("/BM")
+ feed('/BM')
screen:expect([[
Inc substitution on |
{12:BM}o lines |
Inc substitution on |
{12:BM}o lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:%s/tw/BM^ |
]])
- feed("/")
+ feed('/')
screen:expect([[
Inc substitution on |
{12:BM}o lines |
Inc substitution on |
{12:BM}o lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:%s/tw/BM/^ |
]])
- feed("<enter>")
+ feed('<enter>')
screen:expect([[
Inc substitution on |
BMo lines |
Inc substitution on |
^BMo lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:%s/tw/BM/ |
]])
end)
- it("clears preview if non-previewable command is edited", function()
+ it('clears preview if non-previewable command is edited', function()
-- Put a non-previewable command in history.
- feed_command("echo 'foo'")
+ feed(":echo 'foo'<CR>")
-- Start an incomplete :substitute command.
- feed(":1,2s/t/X")
+ feed(':1,2s/t/X')
screen:expect([[
Inc subs{12:X}itution on |
@@ -1582,15 +1447,12 @@ describe("inccommand=nosplit", function()
Inc substitution on |
two lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:1,2s/t/X^ |
]])
-- Select the previous command.
- feed("<C-P>")
+ feed('<C-P>')
-- Assert that preview was cleared.
screen:expect([[
Inc substitution on |
@@ -1598,15 +1460,12 @@ describe("inccommand=nosplit", function()
Inc substitution on |
two lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:echo 'foo'^ |
]])
end)
- it("does not execute trailing bar-separated commands #7494", function()
+ it('does not execute trailing bar-separated commands #7494', function()
feed(':%s/two/three/g|q!')
screen:expect([[
Inc substitution on |
@@ -1614,16 +1473,13 @@ describe("inccommand=nosplit", function()
Inc substitution on |
{12:three} lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:%s/two/three/g|q!^ |
]])
eq(eval('v:null'), eval('v:exiting'))
end)
- it("does not break bar-separated command #8796", function()
+ it('does not break bar-separated command #8796', function()
source([[
function! F()
if v:false | return | endif
@@ -1631,17 +1487,14 @@ describe("inccommand=nosplit", function()
]])
command('call timer_start(10, {-> F()}, {"repeat":-1})')
feed(':%s/')
- sleep(20) -- Allow some timer activity.
+ sleep(20) -- Allow some timer activity.
screen:expect([[
Inc substitution on |
two lines |
Inc substitution on |
two lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:%s/^ |
]])
end)
@@ -1649,19 +1502,21 @@ end)
describe(":substitute, 'inccommand' with a failing expression", function()
local screen
- local cases = { "", "split", "nosplit" }
+ local cases = { '', 'split', 'nosplit' }
local function refresh(case)
clear()
- screen = Screen.new(20,10)
+ screen = Screen.new(20, 10)
common_setup(screen, case, default_text)
end
it('in the pattern does nothing', function()
for _, case in pairs(cases) do
refresh(case)
- feed_command("set inccommand=" .. case)
- feed(":silent! %s/tw\\(/LARD/<enter>")
+ command('set inccommand=' .. case)
+ feed(':silent! %s/tw\\(/LARD/')
+ poke_eventloop()
+ feed('<enter>')
expect(default_text)
end
end)
@@ -1669,13 +1524,15 @@ describe(":substitute, 'inccommand' with a failing expression", function()
it('in the replacement deletes the matches', function()
for _, case in pairs(cases) do
refresh(case)
- local replacements = { "\\='LARD", "\\=xx_novar__xx" }
+ local replacements = { "\\='LARD", '\\=xx_novar__xx' }
for _, repl in pairs(replacements) do
- feed_command("set inccommand=" .. case)
- feed(":silent! %s/tw/" .. repl .. "/<enter>")
- expect(default_text:gsub("tw", ""))
- feed_command("undo")
+ command('set inccommand=' .. case)
+ feed(':silent! %s/tw/' .. repl .. '/')
+ poke_eventloop()
+ feed('<enter>')
+ expect(default_text:gsub('tw', ''))
+ command('undo')
end
end
end)
@@ -1689,12 +1546,7 @@ describe(":substitute, 'inccommand' with a failing expression", function()
Inc substitution on |
two lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
:100s/^ |
]])
@@ -1703,88 +1555,101 @@ describe(":substitute, 'inccommand' with a failing expression", function()
Inc substitution on |
two lines |
^ |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{14:E16: Invalid range} |
]])
end
end)
-
end)
describe("'inccommand' and :cnoremap", function()
- local cases = { "", "split", "nosplit" }
+ local cases = { '', 'split', 'nosplit' }
local screen
local function refresh(case, visual)
clear()
- screen = visual and Screen.new(80,10) or nil
+ screen = visual and Screen.new(80, 10) or nil
common_setup(screen, case, default_text)
end
it('work with remapped characters', function()
for _, case in pairs(cases) do
refresh(case)
- local cmd = "%s/lines/LINES/g"
+ local cmd = '%s/lines/LINES/g'
for i = 1, string.len(cmd) do
local c = string.sub(cmd, i, i)
- feed_command("cnoremap ".. c .. " " .. c)
+ command('cnoremap ' .. c .. ' ' .. c)
end
- feed_command(cmd)
+ feed(':' .. cmd)
+ poke_eventloop()
+ feed('<CR>')
expect([[
Inc substitution on
two LINES
]])
- end
+ end
end)
it('work when mappings move the cursor', function()
for _, case in pairs(cases) do
refresh(case)
- feed_command("cnoremap ,S LINES/<left><left><left><left><left><left>")
+ command('cnoremap ,S LINES/<left><left><left><left><left><left>')
- feed(":%s/lines/,Sor three <enter>")
+ feed(':%s/lines/')
+ poke_eventloop()
+ feed(',S')
+ poke_eventloop()
+ feed('or three <enter>')
+ poke_eventloop()
expect([[
Inc substitution on
two or three LINES
]])
- feed_command("cnoremap ;S /X/<left><left><left>")
- feed(":%s/;SI<enter>")
+ command('cnoremap ;S /X/<left><left><left>')
+ feed(':%s/')
+ poke_eventloop()
+ feed(';S')
+ poke_eventloop()
+ feed('I<enter>')
expect([[
Xnc substitution on
two or three LXNES
]])
- feed_command("cnoremap ,T //Y/<left><left><left>")
- feed(":%s,TX<enter>")
+ command('cnoremap ,T //Y/<left><left><left>')
+ feed(':%s')
+ poke_eventloop()
+ feed(',T')
+ poke_eventloop()
+ feed('X<enter>')
expect([[
Ync substitution on
two or three LYNES
]])
- feed_command("cnoremap ;T s//Z/<left><left><left>")
- feed(":%;TY<enter>")
+ command('cnoremap ;T s//Z/<left><left><left>')
+ feed(':%')
+ poke_eventloop()
+ feed(';T')
+ poke_eventloop()
+ feed('Y<enter>')
expect([[
Znc substitution on
two or three LZNES
]])
- end
+ end
end)
it('still works with a broken mapping', function()
for _, case in pairs(cases) do
refresh(case, true)
- feed_command("cnoremap <expr> x execute('bwipeout!')[-1].'x'")
+ command("cnoremap <expr> x execute('bwipeout!')[-1].'x'")
- feed(":%s/tw/tox<enter>")
- screen:expect{any=[[{14:^E565:]]}
+ feed(':%s/tw/tox<enter>')
+ screen:expect { any = [[{14:^E565:]] }
feed('<c-c>')
-- error thrown b/c of the mapping
@@ -1799,20 +1664,24 @@ describe("'inccommand' and :cnoremap", function()
it('work when temporarily moving the cursor', function()
for _, case in pairs(cases) do
refresh(case)
- feed_command("cnoremap <expr> x cursor(1, 1)[-1].'x'")
+ command("cnoremap <expr> x cursor(1, 1)[-1].'x'")
- feed(":%s/tw/tox/g<enter>")
- expect(default_text:gsub("tw", "tox"))
+ feed(':%s/tw/tox')
+ poke_eventloop()
+ feed('/g<enter>')
+ expect(default_text:gsub('tw', 'tox'))
end
end)
it("work when a mapping disables 'inccommand'", function()
for _, case in pairs(cases) do
refresh(case)
- feed_command("cnoremap <expr> x execute('set inccommand=')[-1]")
+ command("cnoremap <expr> x execute('set inccommand=')[-1]")
- feed(":%s/tw/toxa/g<enter>")
- expect(default_text:gsub("tw", "toa"))
+ feed(':%s/tw/tox')
+ poke_eventloop()
+ feed('a/g<enter>')
+ expect(default_text:gsub('tw', 'toa'))
end
end)
@@ -1822,12 +1691,12 @@ describe("'inccommand' and :cnoremap", function()
source([[cnoremap x <C-\>eextend(g:, {'fo': getcmdline()})
\.fo<CR><C-c>:new<CR>:bw!<CR>:<C-r>=remove(g:, 'fo')<CR>x]])
- feed(":%s/tw/tox")
- feed("/<enter>")
- expect(default_text:gsub("tw", "tox"))
+ feed(':%s/tw/tox')
+ poke_eventloop()
+ feed('/<enter>')
+ expect(default_text:gsub('tw', 'tox'))
end
end)
-
end)
describe("'inccommand' autocommands", function()
@@ -1868,9 +1737,9 @@ describe("'inccommand' autocommands", function()
}
local function bufferlist(t)
- local s = ""
+ local s = ''
for _, buffer in pairs(t) do
- s = s .. ", " .. tostring(buffer)
+ s = s .. ', ' .. tostring(buffer)
end
return s
end
@@ -1882,12 +1751,12 @@ describe("'inccommand' autocommands", function()
end
local function register_autocmd(event)
- meths.set_var(event .. "_fired", {})
- feed_command("autocmd " .. event .. " * call add(g:" .. event .. "_fired, expand('<abuf>'))")
+ api.nvim_set_var(event .. '_fired', {})
+ command('autocmd ' .. event .. ' * call add(g:' .. event .. "_fired, expand('<abuf>'))")
end
it('are not fired when splitting', function()
- common_setup(nil, "split", default_text)
+ common_setup(nil, 'split', default_text)
local eventsObserved = {}
for event, _ in pairs(eventsExpected) do
@@ -1895,162 +1764,112 @@ describe("'inccommand' autocommands", function()
register_autocmd(event)
end
- feed(":%s/tw")
+ feed(':%s/tw')
for event, _ in pairs(eventsExpected) do
- eventsObserved[event].open = meths.get_var(event .. "_fired")
- meths.set_var(event .. "_fired", {})
+ eventsObserved[event].open = api.nvim_get_var(event .. '_fired')
+ api.nvim_set_var(event .. '_fired', {})
end
- feed("/<enter>")
+ feed('/<enter>')
for event, _ in pairs(eventsExpected) do
- eventsObserved[event].close = meths.get_var(event .. "_fired")
+ eventsObserved[event].close = api.nvim_get_var(event .. '_fired')
end
for event, _ in pairs(eventsExpected) do
- eq(event .. bufferlist(eventsExpected[event].open),
- event .. bufferlist(eventsObserved[event].open))
- eq(event .. bufferlist(eventsExpected[event].close),
- event .. bufferlist(eventsObserved[event].close))
+ eq(
+ event .. bufferlist(eventsExpected[event].open),
+ event .. bufferlist(eventsObserved[event].open)
+ )
+ eq(
+ event .. bufferlist(eventsExpected[event].close),
+ event .. bufferlist(eventsObserved[event].close)
+ )
end
end)
-
end)
describe("'inccommand' split windows", function()
local screen
local function refresh()
clear()
- screen = Screen.new(40,30)
- common_setup(screen, "split", default_text)
+ screen = Screen.new(40, 30)
+ common_setup(screen, 'split', default_text)
end
it('work after more splits', function()
refresh()
- feed("gg")
- feed_command("vsplit")
- feed_command("split")
- feed(":%s/tw")
+ feed('gg')
+ command('vsplit')
+ command('split')
+ feed(':%s/tw')
screen:expect([[
Inc substitution on │Inc substitution on|
{12:tw}o lines │{12:tw}o lines |
│ |
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
+ {15:~ }│{15:~ }|*11
{11:[No Name] [+] }│{15:~ }|
Inc substitution on │{15:~ }|
{12:tw}o lines │{15:~ }|
│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
+ {15:~ }│{15:~ }|*2
{10:[No Name] [+] [No Name] [+] }|
|2| {12:tw}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{10:[Preview] }|
:%s/tw^ |
]])
- feed("<esc>")
- feed_command("only")
- feed_command("split")
- feed_command("vsplit")
+ feed('<esc>')
+ command('only')
+ command('split')
+ command('vsplit')
- feed(":%s/tw")
+ feed(':%s/tw')
screen:expect([[
Inc substitution on │Inc substitution on|
{12:tw}o lines │{12:tw}o lines |
│ |
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
- {15:~ }│{15:~ }|
+ {15:~ }│{15:~ }|*11
{11:[No Name] [+] }{10:[No Name] [+] }|
Inc substitution on |
{12:tw}o lines |
|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*2
{10:[No Name] [+] }|
|2| {12:tw}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{10:[Preview] }|
:%s/tw^ |
]])
end)
local settings = {
- "splitbelow",
- "splitright",
- "noequalalways",
- "equalalways eadirection=ver",
- "equalalways eadirection=hor",
- "equalalways eadirection=both",
+ 'splitbelow',
+ 'splitright',
+ 'noequalalways',
+ 'equalalways eadirection=ver',
+ 'equalalways eadirection=hor',
+ 'equalalways eadirection=both',
}
- it("are not affected by various settings", function()
+ it('are not affected by various settings', function()
for _, setting in pairs(settings) do
refresh()
- feed_command("set " .. setting)
+ command('set ' .. setting)
- feed(":%s/tw")
+ feed(':%s/tw')
screen:expect([[
Inc substitution on |
{12:tw}o lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*17
{11:[No Name] [+] }|
|2| {12:tw}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{10:[Preview] }|
:%s/tw^ |
]])
@@ -2060,7 +1879,7 @@ describe("'inccommand' split windows", function()
it("don't open if there's not enough room", function()
refresh()
screen:try_resize(40, 3)
- feed("gg:%s/tw")
+ feed('gg:%s/tw')
screen:expect([[
Inc substitution on |
{12:tw}o lines |
@@ -2074,43 +1893,43 @@ describe("'inccommand' with 'gdefault'", function()
clear()
end)
- it("does not lock up #7244", function()
- common_setup(nil, "nosplit", "{")
- command("set gdefault")
- feed(":s/{\\n")
- eq({mode='c', blocking=false}, nvim("get_mode"))
- feed("/A<Enter>")
- expect("A")
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ it('does not lock up #7244', function()
+ common_setup(nil, 'nosplit', '{')
+ command('set gdefault')
+ feed(':s/{\\n')
+ eq({ mode = 'c', blocking = false }, api.nvim_get_mode())
+ feed('/A<Enter>')
+ expect('A')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
- it("with multiline text and range, does not lock up #7244", function()
- common_setup(nil, "nosplit", "{\n\n{")
- command("set gdefault")
- feed(":%s/{\\n")
- eq({mode='c', blocking=false}, nvim("get_mode"))
- feed("/A<Enter>")
- expect("A\nA")
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ it('with multiline text and range, does not lock up #7244', function()
+ common_setup(nil, 'nosplit', '{\n\n{')
+ command('set gdefault')
+ feed(':%s/{\\n')
+ eq({ mode = 'c', blocking = false }, api.nvim_get_mode())
+ feed('/A<Enter>')
+ expect('A\nA')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
- it("does not crash on zero-width matches #7485", function()
- common_setup(nil, "split", default_text)
- command("set gdefault")
- feed("gg")
- feed("Vj")
- feed(":s/\\%V")
- eq({mode='c', blocking=false}, nvim("get_mode"))
- feed("<Esc>")
- eq({mode='n', blocking=false}, nvim("get_mode"))
+ it('does not crash on zero-width matches #7485', function()
+ common_setup(nil, 'split', default_text)
+ command('set gdefault')
+ feed('gg')
+ feed('Vj')
+ feed(':s/\\%V')
+ eq({ mode = 'c', blocking = false }, api.nvim_get_mode())
+ feed('<Esc>')
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
end)
- it("removes highlights after abort for a zero-width match", function()
- local screen = Screen.new(30,5)
- common_setup(screen, "nosplit", default_text)
- command("set gdefault")
+ it('removes highlights after abort for a zero-width match', function()
+ local screen = Screen.new(30, 5)
+ common_setup(screen, 'nosplit', default_text)
+ command('set gdefault')
- feed(":%s/\\%1c/a/")
+ feed(':%s/\\%1c/a/')
screen:expect([[
{12:a}Inc substitution on |
{12:a}two lines |
@@ -2119,7 +1938,7 @@ describe("'inccommand' with 'gdefault'", function()
:%s/\%1c/a/^ |
]])
- feed("<Esc>")
+ feed('<Esc>')
screen:expect([[
Inc substitution on |
two lines |
@@ -2128,21 +1947,20 @@ describe("'inccommand' with 'gdefault'", function()
|
]])
end)
-
end)
-describe(":substitute", function()
+describe(':substitute', function()
local screen
before_each(function()
clear()
- screen = Screen.new(30,15)
+ screen = Screen.new(30, 15)
end)
- it("inccommand=split, highlights multiline substitutions", function()
- common_setup(screen, "split", multiline_text)
- feed("gg")
+ it('inccommand=split, highlights multiline substitutions', function()
+ common_setup(screen, 'split', multiline_text)
+ feed('gg')
- feed(":%s/2\\_.*X")
+ feed(':%s/2\\_.*X')
screen:expect([[
1 {12:2 3} |
{12:A B C} |
@@ -2154,33 +1972,25 @@ describe(":substitute", function()
|2|{12: A B C} |
|3|{12: 4 5 6} |
|4|{12: X} Y Z |
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*3
{10:[Preview] }|
:%s/2\_.*X^ |
]])
- feed("/MMM")
+ feed('/MMM')
screen:expect([[
1 {12:MMM} Y Z |
7 8 9 |
|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*2
{11:[No Name] [+] }|
|1| 1 {12:MMM} Y Z |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{10:[Preview] }|
:%s/2\_.*X/MMM^ |
]])
- feed("\\rK\\rLLL")
+ feed('\\rK\\rLLL')
screen:expect([[
1 {12:MMM} |
{12:K} |
@@ -2191,113 +2001,77 @@ describe(":substitute", function()
|1| 1 {12:MMM} |
|2|{12: K} |
|3|{12: LLL} Y Z |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
{10:[Preview] }|
:%s/2\_.*X/MMM\rK\rLLL^ |
]])
end)
- it("inccommand=nosplit, highlights multiline substitutions", function()
- common_setup(screen, "nosplit", multiline_text)
- feed("gg")
+ it('inccommand=nosplit, highlights multiline substitutions', function()
+ common_setup(screen, 'nosplit', multiline_text)
+ feed('gg')
- feed(":%s/2\\_.*X/MMM")
+ feed(':%s/2\\_.*X/MMM')
screen:expect([[
1 {12:MMM} Y Z |
7 8 9 |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*11
:%s/2\_.*X/MMM^ |
]])
- feed("\\rK\\rLLL")
+ feed('\\rK\\rLLL')
screen:expect([[
1 {12:MMM} |
{12:K} |
{12:LLL} Y Z |
7 8 9 |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*9
:%s/2\_.*X/MMM\rK\rLLL^ |
]])
end)
- it("inccommand=split, highlights multiple matches on a line", function()
- common_setup(screen, "split", multimatch_text)
- command("set gdefault")
- feed("gg")
+ it('inccommand=split, highlights multiple matches on a line', function()
+ common_setup(screen, 'split', multimatch_text)
+ command('set gdefault')
+ feed('gg')
- feed(":%s/a/XLK")
+ feed(':%s/a/XLK')
screen:expect([[
{12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:XLK} r|
x |
|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*2
{11:[No Name] [+] }|
|1| {12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:X}|
{12:LK} r |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:%s/a/XLK^ |
]])
end)
- it("inccommand=nosplit, highlights multiple matches on a line", function()
- common_setup(screen, "nosplit", multimatch_text)
- command("set gdefault")
- feed("gg")
+ it('inccommand=nosplit, highlights multiple matches on a line', function()
+ common_setup(screen, 'nosplit', multimatch_text)
+ command('set gdefault')
+ feed('gg')
- feed(":%s/a/XLK")
+ feed(':%s/a/XLK')
screen:expect([[
{12:XLK} bdc e{12:XLK}e {12:XLK} fgl lzi{12:XLK} r|
x |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*11
:%s/a/XLK^ |
]])
end)
- it("inccommand=split, with \\zs", function()
- common_setup(screen, "split", multiline_text)
- feed("gg")
+ it('inccommand=split, with \\zs', function()
+ common_setup(screen, 'split', multiline_text)
+ feed('gg')
- feed(":%s/[0-9]\\n\\zs[A-Z]/OKO")
+ feed(':%s/[0-9]\\n\\zs[A-Z]/OKO')
screen:expect([[
{12:OKO} B C |
4 5 6 |
@@ -2309,19 +2083,17 @@ describe(":substitute", function()
|2| {12:OKO} B C |
|3| 4 5 6 |
|4| {12:OKO} Y Z |
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*3
{10:[Preview] }|
:%s/[0-9]\n\zs[A-Z]/OKO^ |
]])
end)
- it("inccommand=nosplit, with \\zs", function()
- common_setup(screen, "nosplit", multiline_text)
- feed("gg")
+ it('inccommand=nosplit, with \\zs', function()
+ common_setup(screen, 'nosplit', multiline_text)
+ feed('gg')
- feed(":%s/[0-9]\\n\\zs[A-Z]/OKO")
+ feed(':%s/[0-9]\\n\\zs[A-Z]/OKO')
screen:expect([[
1 2 3 |
{12:OKO} B C |
@@ -2329,65 +2101,41 @@ describe(":substitute", function()
{12:OKO} Y Z |
7 8 9 |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*8
:%s/[0-9]\n\zs[A-Z]/OKO^ |
]])
end)
- it("inccommand=split, substitutions of different length", function()
- common_setup(screen, "split", "T T123 T2T TTT T090804\nx")
+ it('inccommand=split, substitutions of different length', function()
+ common_setup(screen, 'split', 'T T123 T2T TTT T090804\nx')
- feed(":%s/T\\([0-9]\\+\\)/\\1\\1/g")
+ feed(':%s/T\\([0-9]\\+\\)/\\1\\1/g')
screen:expect([[
T {12:123123} {12:22}T TTT {12:090804090804} |
x |
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*3
{11:[No Name] [+] }|
|1| T {12:123123} {12:22}T TTT {12:090804090}|
{12:804} |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
{10:[Preview] }|
:%s/T\([0-9]\+\)/\1\1/g^ |
]])
end)
- it("inccommand=nosplit, substitutions of different length", function()
- common_setup(screen, "nosplit", "T T123 T2T TTT T090804\nx")
+ it('inccommand=nosplit, substitutions of different length', function()
+ common_setup(screen, 'nosplit', 'T T123 T2T TTT T090804\nx')
- feed(":%s/T\\([0-9]\\+\\)/\\1\\1/g")
+ feed(':%s/T\\([0-9]\\+\\)/\\1\\1/g')
screen:expect([[
T {12:123123} {12:22}T TTT {12:090804090804} |
x |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*12
:%s/T\([0-9]\+\)/\1\1/g^ |
]])
end)
- it("inccommand=split, contraction of lines", function()
+ it('inccommand=split, contraction of lines', function()
local text = [[
T T123 T T123 T2T TT T23423424
x
@@ -2396,8 +2144,8 @@ describe(":substitute", function()
alx
]]
- common_setup(screen, "split", text)
- feed(":%s/[QR]\\n")
+ common_setup(screen, 'split', text)
+ feed(':%s/[QR]\\n')
screen:expect([[
afa {12:Q} |
adf la;lkd {12:R} |
@@ -2408,15 +2156,12 @@ describe(":substitute", function()
|3| afa {12:Q} |
|4|{12: }adf la;lkd {12:R} |
|5|{12: }alx |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
{10:[Preview] }|
:%s/[QR]\n^ |
]])
- feed("/KKK")
+ feed('/KKK')
screen:expect([[
T T123 T T123 T2T TT T23423424|
x |
@@ -2425,18 +2170,13 @@ describe(":substitute", function()
{15:~ }|
{11:[No Name] [+] }|
|3| afa {12:KKK}adf la;lkd {12:KKK}alx |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{10:[Preview] }|
:%s/[QR]\n/KKK^ |
]])
end)
- it("inccommand=nosplit, contraction of lines", function()
+ it('inccommand=nosplit, contraction of lines', function()
local text = [[
T T123 T T123 T2T TT T23423424
x
@@ -2445,28 +2185,19 @@ describe(":substitute", function()
alx
]]
- common_setup(screen, "nosplit", text)
- feed(":%s/[QR]\\n/KKK")
+ common_setup(screen, 'nosplit', text)
+ feed(':%s/[QR]\\n/KKK')
screen:expect([[
T T123 T T123 T2T TT T23423424|
x |
afa {12:KKK}adf la;lkd {12:KKK}alx |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*10
:%s/[QR]\n/KKK^ |
]])
end)
- it("inccommand=split, contraction of two subsequent NL chars", function()
+ it('inccommand=split, contraction of two subsequent NL chars', function()
local text = [[
AAA AA
@@ -2478,9 +2209,10 @@ describe(":substitute", function()
-- This used to crash, but more than 20 highlight entries are required
-- to reproduce it (so that the marktree has multiple nodes)
- common_setup(screen, "split", string.rep(text,10))
- feed(":%s/\\n\\n/<c-v><c-m>/g")
- screen:expect{grid=[[
+ common_setup(screen, 'split', string.rep(text, 10))
+ feed(':%s/\\n\\n/<c-v><c-m>/g')
+ screen:expect {
+ grid = [[
CCC CC |
AAA AA |
BBB BB |
@@ -2496,11 +2228,12 @@ describe(":substitute", function()
| 7|{12: }AAA AA |
{10:[Preview] }|
:%s/\n\n/{17:^M}/g^ |
- ]]}
+ ]],
+ }
assert_alive()
end)
- it("inccommand=nosplit, contraction of two subsequent NL chars", function()
+ it('inccommand=nosplit, contraction of two subsequent NL chars', function()
local text = [[
AAA AA
@@ -2510,9 +2243,10 @@ describe(":substitute", function()
]]
- common_setup(screen, "nosplit", string.rep(text,10))
- feed(":%s/\\n\\n/<c-v><c-m>/g")
- screen:expect{grid=[[
+ common_setup(screen, 'nosplit', string.rep(text, 10))
+ feed(':%s/\\n\\n/<c-v><c-m>/g')
+ screen:expect {
+ grid = [[
CCC CC |
AAA AA |
BBB BB |
@@ -2528,13 +2262,14 @@ describe(":substitute", function()
CCC CC |
|
:%s/\n\n/{17:^M}/g^ |
- ]]}
+ ]],
+ }
assert_alive()
end)
- it("inccommand=split, multibyte text", function()
- common_setup(screen, "split", multibyte_text)
- feed(":%s/£.*ѫ/X¥¥")
+ it('inccommand=split, multibyte text', function()
+ common_setup(screen, 'split', multibyte_text)
+ feed(':%s/£.*ѫ/X¥¥')
screen:expect([[
a{12:X¥¥}¥KOL |
£ ¥ libm |
@@ -2545,15 +2280,12 @@ describe(":substitute", function()
|1| {12:X¥¥} PEPPERS |
|2| {12:X¥¥} |
|3| a{12:X¥¥}¥KOL |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
{10:[Preview] }|
:%s/£.*ѫ/X¥¥^ |
]])
- feed("\\ra££ ¥")
+ feed('\\ra££ ¥')
screen:expect([[
a{12:X¥¥} |
{12:a££ ¥}¥KOL |
@@ -2573,9 +2305,9 @@ describe(":substitute", function()
]])
end)
- it("inccommand=nosplit, multibyte text", function()
- common_setup(screen, "nosplit", multibyte_text)
- feed(":%s/£.*ѫ/X¥¥")
+ it('inccommand=nosplit, multibyte text', function()
+ common_setup(screen, 'nosplit', multibyte_text)
+ feed(':%s/£.*ѫ/X¥¥')
screen:expect([[
{12:X¥¥} PEPPERS |
{12:X¥¥} |
@@ -2583,18 +2315,11 @@ describe(":substitute", function()
£ ¥ libm |
£ ¥ |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*8
:%s/£.*ѫ/X¥¥^ |
]])
- feed("\\ra££ ¥")
+ feed('\\ra££ ¥')
screen:expect([[
{12:X¥¥} |
{12:a££ ¥} PEPPERS |
@@ -2605,20 +2330,16 @@ describe(":substitute", function()
£ ¥ libm |
£ ¥ |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*5
:%s/£.*ѫ/X¥¥\ra££ ¥^ |
]])
end)
- it("inccommand=split, small cmdwinheight", function()
- common_setup(screen, "split", long_multiline_text)
- command("set cmdwinheight=2")
+ it('inccommand=split, small cmdwinheight', function()
+ common_setup(screen, 'split', long_multiline_text)
+ command('set cmdwinheight=2')
- feed(":%s/[a-z]")
+ feed(':%s/[a-z]')
screen:expect([[
X Y Z |
7 8 9 |
@@ -2637,7 +2358,7 @@ describe(":substitute", function()
:%s/[a-z]^ |
]])
- feed("/JLKR £")
+ feed('/JLKR £')
screen:expect([[
X Y Z |
7 8 9 |
@@ -2656,7 +2377,7 @@ describe(":substitute", function()
:%s/[a-z]/JLKR £^ |
]])
- feed("\\rѫ ab \\rXXXX")
+ feed('\\rѫ ab \\rXXXX')
screen:expect([[
7 8 9 |
K L M |
@@ -2676,11 +2397,11 @@ describe(":substitute", function()
]])
end)
- it("inccommand=split, large cmdwinheight", function()
- common_setup(screen, "split", long_multiline_text)
- command("set cmdwinheight=11")
+ it('inccommand=split, large cmdwinheight', function()
+ common_setup(screen, 'split', long_multiline_text)
+ command('set cmdwinheight=11')
- feed(":%s/. .$")
+ feed(':%s/. .$')
screen:expect([[
t {12:œ ¥} |
{11:[No Name] [+] }|
@@ -2699,7 +2420,7 @@ describe(":substitute", function()
:%s/. .$^ |
]])
- feed("/ YYY")
+ feed('/ YYY')
screen:expect([[
t {12: YYY} |
{11:[No Name] [+] }|
@@ -2718,7 +2439,7 @@ describe(":substitute", function()
:%s/. .$/ YYY^ |
]])
- feed("\\r KKK")
+ feed('\\r KKK')
screen:expect([[
a {12: YYY} |
{11:[No Name] [+] }|
@@ -2738,28 +2459,22 @@ describe(":substitute", function()
]])
end)
- it("inccommand=split, lookaround", function()
- common_setup(screen, "split", "something\neverything\nsomeone")
+ it('inccommand=split, lookaround', function()
+ common_setup(screen, 'split', 'something\neverything\nsomeone')
feed([[:%s/\(some\)\@<lt>=thing/one/]])
screen:expect([[
some{12:one} |
everything |
someone |
- {15:~ }|
- {15:~ }|
+ {15:~ }|*2
{11:[No Name] [+] }|
|1| some{12:one} |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{10:[Preview] }|
:%s/\(some\)\@<=thing/one/^ |
]])
- feed("<C-c>")
+ feed('<C-c>')
feed('gg')
poke_eventloop()
feed([[:%s/\(some\)\@<lt>!thing/one/]])
@@ -2767,16 +2482,10 @@ describe(":substitute", function()
something |
every{12:one} |
someone |
- {15:~ }|
- {15:~ }|
+ {15:~ }|*2
{11:[No Name] [+] }|
|2| every{12:one} |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{10:[Preview] }|
:%s/\(some\)\@<!thing/one/^ |
]])
@@ -2788,16 +2497,10 @@ describe(":substitute", function()
{12:every}thing |
everything |
someone |
- {15:~ }|
- {15:~ }|
+ {15:~ }|*2
{11:[No Name] [+] }|
|1| {12:every}thing |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{10:[Preview] }|
:%s/some\(thing\)\@=/every/^ |
]])
@@ -2809,16 +2512,10 @@ describe(":substitute", function()
something |
everything |
{12:every}one |
- {15:~ }|
- {15:~ }|
+ {15:~ }|*2
{11:[No Name] [+] }|
|3| {12:every}one |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*6
{10:[Preview] }|
:%s/some\(thing\)\@!/every/^ |
]])
@@ -2826,7 +2523,7 @@ describe(":substitute", function()
it("doesn't prompt to swap cmd range", function()
screen = Screen.new(50, 8) -- wide to avoid hit-enter prompt
- common_setup(screen, "split", default_text)
+ common_setup(screen, 'split', default_text)
feed(':2,1s/tw/MO/g')
-- substitution preview should have been made, without prompting
@@ -2834,9 +2531,7 @@ describe(":substitute", function()
{12:MO}o lines |
{11:[No Name] [+] }|
|2| {12:MO}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*3
{10:[Preview] }|
:2,1s/tw/MO/g^ |
]])
@@ -2847,9 +2542,7 @@ describe(":substitute", function()
{12:MO}o lines |
{11:[No Name] [+] }|
|2| {12:MO}o lines |
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*3
{10:[Preview] }|
{13:Backwards range given, OK to swap (y/n)?}^ |
]])
@@ -2859,10 +2552,7 @@ describe(":substitute", function()
Inc substitution on |
^MOo lines |
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
{13:Backwards range given, OK to swap (y/n)?}y |
]])
end)
@@ -2874,19 +2564,19 @@ it(':substitute with inccommand during :terminal activity', function()
end
retry(2, 40000, function()
clear()
- local screen = Screen.new(30,15)
+ local screen = Screen.new(30, 15)
- command("set cmdwinheight=3")
+ command('set cmdwinheight=3')
feed(([[:terminal "%s" REP 5000 xxx<cr>]]):format(testprg('shell-test')))
command('file term')
- feed('G') -- Follow :terminal output.
+ feed('G') -- Follow :terminal output.
command('new')
common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz')
command('wincmd =')
feed('gg')
feed(':%s/foo/ZZZ')
- sleep(20) -- Allow some terminal activity.
+ sleep(20) -- Allow some terminal activity.
poke_eventloop()
screen:sleep(0)
screen:expect_unchanged()
@@ -2895,7 +2585,7 @@ end)
it(':substitute with inccommand, timer-induced :redraw #9777', function()
clear()
- local screen = Screen.new(30,12)
+ local screen = Screen.new(30, 12)
command('set cmdwinheight=3')
command('call timer_start(10, {-> execute("redraw")}, {"repeat":-1})')
command('call timer_start(10, {-> execute("redrawstatus")}, {"repeat":-1})')
@@ -2903,14 +2593,12 @@ it(':substitute with inccommand, timer-induced :redraw #9777', function()
feed('gg')
feed(':%s/foo/ZZZ')
- sleep(20) -- Allow some timer activity.
+ sleep(20) -- Allow some timer activity.
screen:expect([[
{12:ZZZ} bar baz |
bar baz fox |
bar {12:ZZZ} baz |
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*3
{11:[No Name] [+] }|
|1| {12:ZZZ} bar baz |
|3| bar {12:ZZZ} baz |
@@ -2922,12 +2610,17 @@ end)
it(':substitute with inccommand, allows :redraw before first separator is typed #18857', function()
clear()
- local screen = Screen.new(30,6)
+ local screen = Screen.new(30, 6)
common_setup(screen, 'split', 'foo bar baz\nbar baz fox\nbar foo baz')
command('hi! link NormalFloat CursorLine')
- local float_buf = meths.create_buf(false, true)
- meths.open_win(float_buf, false, {
- relative = 'editor', height = 1, width = 5, row = 3, col = 0, focusable = false,
+ local float_buf = api.nvim_create_buf(false, true)
+ api.nvim_open_win(float_buf, false, {
+ relative = 'editor',
+ height = 1,
+ width = 5,
+ row = 3,
+ col = 0,
+ focusable = false,
})
feed(':')
screen:expect([[
@@ -2947,7 +2640,7 @@ it(':substitute with inccommand, allows :redraw before first separator is typed
{15:~ }|
:%s^ |
]])
- meths.buf_set_lines(float_buf, 0, -1, true, {'foo'})
+ api.nvim_buf_set_lines(float_buf, 0, -1, true, { 'foo' })
command('redraw')
screen:expect([[
foo bar baz |
@@ -2966,10 +2659,7 @@ it(':substitute with inccommand, does not crash if range contains invalid marks'
feed([[:'a,'bs]])
screen:expect([[
test |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:'a,'bs^ |
]])
-- v:errmsg shouldn't be set either before the first separator is typed
@@ -2977,10 +2667,7 @@ it(':substitute with inccommand, does not crash if range contains invalid marks'
feed('/')
screen:expect([[
test |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:'a,'bs/^ |
]])
end)
@@ -3030,17 +2717,14 @@ it(':substitute with inccommand, no unnecessary redraw if preview is not shown',
-- now inccommand is shown, so screen is redrawn
screen:expect([[
{12:test} |
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:s/test^ |
]])
end)
it(":substitute doesn't crash with inccommand, if undo is empty #12932", function()
clear()
- local screen = Screen.new(10,5)
+ local screen = Screen.new(10, 5)
command('set undolevels=-1')
common_setup(screen, 'split', 'test')
feed(':%s/test')
@@ -3050,9 +2734,7 @@ it(":substitute doesn't crash with inccommand, if undo is empty #12932", functio
feed('f')
screen:expect([[
{12:f} |
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*3
:%s/test/f^ |
]])
assert_alive()
@@ -3062,7 +2744,7 @@ it(':substitute with inccommand works properly if undo is not synced #20029', fu
clear()
local screen = Screen.new(30, 6)
common_setup(screen, 'nosplit', 'foo\nbar\nbaz')
- meths.set_keymap('x', '<F2>', '<Esc>`<Oaaaaa asdf<Esc>`>obbbbb asdf<Esc>V`<k:s/asdf/', {})
+ api.nvim_set_keymap('x', '<F2>', '<Esc>`<Oaaaaa asdf<Esc>`>obbbbb asdf<Esc>V`<k:s/asdf/', {})
feed('gg0<C-V>lljj<F2>')
screen:expect([[
aaaaa |
@@ -3127,10 +2809,31 @@ end)
it('long :%s/ with inccommand does not collapse cmdline', function()
clear()
- local screen = Screen.new(10,5)
+ local screen = Screen.new(10, 5)
common_setup(screen, 'nosplit')
- feed(':%s/AAAAAAA', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A',
- 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A')
+ feed(
+ ':%s/AAAAAAA',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A',
+ 'A'
+ )
screen:expect([[
|
{11: }|
@@ -3147,10 +2850,7 @@ it("with 'inccommand' typing invalid `={expr}` does not show error", function()
feed(':edit `=`')
screen:expect([[
|
- {15:~ }|
- {15:~ }|
- {15:~ }|
- {15:~ }|
+ {15:~ }|*4
:edit `=`^ |
]])
end)
@@ -3195,3 +2895,54 @@ it("'inccommand' cannot be changed during preview #23136", function()
feed(':%s/foo/bar<C-E><C-E><C-E>')
assert_alive()
end)
+
+it("'inccommand' value can be changed multiple times #27086", function()
+ clear()
+ local screen = Screen.new(30, 20)
+ common_setup(screen, 'split', 'foo1\nfoo2\nfoo3')
+ for _ = 1, 3 do
+ feed(':%s/foo/bar')
+ screen:expect([[
+ {12:bar}1 |
+ {12:bar}2 |
+ {12:bar}3 |
+ {15:~ }|*7
+ {11:[No Name] [+] }|
+ |1| {12:bar}1 |
+ |2| {12:bar}2 |
+ |3| {12:bar}3 |
+ {15:~ }|*4
+ {10:[Preview] }|
+ :%s/foo/bar^ |
+ ]])
+ feed('<Esc>')
+ command('set inccommand=nosplit')
+ feed(':%s/foo/bar')
+ screen:expect([[
+ {12:bar}1 |
+ {12:bar}2 |
+ {12:bar}3 |
+ {15:~ }|*16
+ :%s/foo/bar^ |
+ ]])
+ feed('<Esc>')
+ command('set inccommand=split')
+ end
+end)
+
+it("'inccommand' disables preview if preview buffer can't be created #27086", function()
+ clear()
+ api.nvim_buf_set_name(0, '[Preview]')
+ local screen = Screen.new(30, 20)
+ common_setup(screen, 'split', 'foo1\nfoo2\nfoo3')
+ eq('split', api.nvim_get_option_value('inccommand', {}))
+ feed(':%s/foo/bar')
+ screen:expect([[
+ {12:bar}1 |
+ {12:bar}2 |
+ {12:bar}3 |
+ {15:~ }|*16
+ :%s/foo/bar^ |
+ ]])
+ eq('nosplit', api.nvim_get_option_value('inccommand', {}))
+end)
diff --git a/test/functional/ui/inccommand_user_spec.lua b/test/functional/ui/inccommand_user_spec.lua
index da7508fad1..a714df72b7 100644
--- a/test/functional/ui/inccommand_user_spec.lua
+++ b/test/functional/ui/inccommand_user_spec.lua
@@ -1,6 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
+local api = helpers.api
local clear = helpers.clear
+local eq = helpers.eq
local exec_lua = helpers.exec_lua
local insert = helpers.insert
local feed = helpers.feed
@@ -236,16 +238,16 @@ describe("'inccommand' for user commands", function()
clear()
screen = Screen.new(40, 17)
screen:set_default_attr_ids({
- [1] = {background = Screen.colors.Yellow1},
- [2] = {foreground = Screen.colors.Blue1, bold = true},
- [3] = {reverse = true},
- [4] = {reverse = true, bold = true},
- [5] = {foreground = Screen.colors.Blue},
+ [1] = { background = Screen.colors.Yellow1 },
+ [2] = { foreground = Screen.colors.Blue1, bold = true },
+ [3] = { reverse = true },
+ [4] = { reverse = true, bold = true },
+ [5] = { foreground = Screen.colors.Blue },
})
screen:attach()
exec_lua(setup_replace_cmd)
command('set cmdwinheight=5')
- insert[[
+ insert [[
text on line 1
more text on line 2
oh no, even more text
@@ -270,13 +272,7 @@ describe("'inccommand' for user commands", function()
why won't it stop |
make the {1:cats} stop |
|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*7
:Replace text cats^ |
]])
end)
@@ -318,13 +314,7 @@ describe("'inccommand' for user commands", function()
why won't it stop |
make the text stop |
^ |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*7
|
]])
end)
@@ -342,13 +332,7 @@ describe("'inccommand' for user commands", function()
why won't it stop |
make the cats stop |
^ |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*7
:Replace text cats |
]])
end)
@@ -366,13 +350,7 @@ describe("'inccommand' for user commands", function()
why won't it stop |
make the text stop |
|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*7
:.Replace text cats^ |
]])
end)
@@ -425,13 +403,7 @@ describe("'inccommand' for user commands", function()
why won't it stop |
make the cats stop |
|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*7
:C^ |
]])
assert_alive()
@@ -481,13 +453,7 @@ describe("'inccommand' for user commands", function()
why won't it stop |
make the text stop |
a.a.a.a. |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*7
:Test a.a.a.a.^ |
]])
feed('<C-V><Esc>u')
@@ -501,13 +467,7 @@ describe("'inccommand' for user commands", function()
why won't it stop |
make the text stop |
a.a.a. |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*7
:Test a.a.a.a.{5:^[}u^ |
]])
feed('<Esc>')
@@ -521,13 +481,7 @@ describe("'inccommand' for user commands", function()
why won't it stop |
make the text stop |
^ |
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*7
|
]])
end
@@ -543,6 +497,22 @@ describe("'inccommand' for user commands", function()
test_preview_break_undo()
end)
end)
+
+ it('disables preview if preview buffer cannot be created #27086', function()
+ command('set inccommand=split')
+ api.nvim_buf_set_name(0, '[Preview]')
+ exec_lua([[
+ vim.api.nvim_create_user_command('Test', function() end, {
+ nargs = '*',
+ preview = function(_, _, _)
+ return 2
+ end
+ })
+ ]])
+ eq('split', api.nvim_get_option_value('inccommand', {}))
+ feed(':Test')
+ eq('nosplit', api.nvim_get_option_value('inccommand', {}))
+ end)
end)
describe("'inccommand' with multiple buffers", function()
@@ -552,21 +522,21 @@ describe("'inccommand' with multiple buffers", function()
clear()
screen = Screen.new(40, 17)
screen:set_default_attr_ids({
- [1] = {background = Screen.colors.Yellow1},
- [2] = {foreground = Screen.colors.Blue1, bold = true},
- [3] = {reverse = true},
- [4] = {reverse = true, bold = true}
+ [1] = { background = Screen.colors.Yellow1 },
+ [2] = { foreground = Screen.colors.Blue1, bold = true },
+ [3] = { reverse = true },
+ [4] = { reverse = true, bold = true },
})
screen:attach()
exec_lua(setup_replace_cmd)
command('set cmdwinheight=10')
- insert[[
+ insert [[
foo bar baz
bar baz foo
baz foo bar
]]
command('vsplit | enew')
- insert[[
+ insert [[
bar baz foo
baz foo bar
foo bar baz
@@ -581,17 +551,7 @@ describe("'inccommand' with multiple buffers", function()
baz {1:bar} bar │ bar baz {1:bar} |
{1:bar} bar baz │ baz {1:bar} bar |
│ |
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
+ {2:~ }│{2:~ }|*11
{4:[No Name] [+] }{3:[No Name] [+] }|
:Replace foo bar^ |
]])
@@ -601,17 +561,7 @@ describe("'inccommand' with multiple buffers", function()
baz bar bar │ bar baz bar |
bar bar baz │ baz bar bar |
^ │ |
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
+ {2:~ }│{2:~ }|*11
{4:[No Name] [+] }{3:[No Name] [+] }|
:Replace foo bar |
]])
@@ -645,17 +595,7 @@ describe("'inccommand' with multiple buffers", function()
baz bar bar │ bar baz bar |
bar bar baz │ baz bar bar |
^ │ |
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
- {2:~ }│{2:~ }|
+ {2:~ }│{2:~ }|*11
{4:[No Name] [+] }{3:[No Name] [+] }|
:Replace foo bar |
]])
diff --git a/test/functional/ui/input_spec.lua b/test/functional/ui/input_spec.lua
index 05d55b94fb..b2899bf82d 100644
--- a/test/functional/ui/input_spec.lua
+++ b/test/functional/ui/input_spec.lua
@@ -4,10 +4,10 @@ local feed, next_msg, eq = helpers.feed, helpers.next_msg, helpers.eq
local command = helpers.command
local expect = helpers.expect
local curbuf_contents = helpers.curbuf_contents
-local meths = helpers.meths
+local api = helpers.api
local exec_lua = helpers.exec_lua
local write_file = helpers.write_file
-local funcs = helpers.funcs
+local fn = helpers.fn
local eval = helpers.eval
local Screen = require('test.functional.ui.screen')
@@ -15,17 +15,24 @@ before_each(clear)
describe('mappings', function()
local add_mapping = function(mapping, send)
- local cmd = "nnoremap "..mapping.." :call rpcnotify(1, 'mapped', '"
- ..send:gsub('<', '<lt>').."')<cr>"
+ local cmd = 'nnoremap '
+ .. mapping
+ .. " :call rpcnotify(1, 'mapped', '"
+ .. send:gsub('<', '<lt>')
+ .. "')<cr>"
feed_command(cmd)
end
local check_mapping = function(mapping, expected)
feed(mapping)
- eq({'notification', 'mapped', {expected}}, next_msg())
+ eq({ 'notification', 'mapped', { expected } }, next_msg())
end
before_each(function()
+ add_mapping('<A-l>', '<A-l>')
+ add_mapping('<A-L>', '<A-L>')
+ add_mapping('<D-l>', '<D-l>')
+ add_mapping('<D-L>', '<D-L>')
add_mapping('<C-L>', '<C-L>')
add_mapping('<C-S-L>', '<C-S-L>')
add_mapping('<s-up>', '<s-up>')
@@ -35,30 +42,40 @@ describe('mappings', function()
add_mapping('<c-s-a-d-up>', '<c-s-a-d-up>')
add_mapping('<c-d-a>', '<c-d-a>')
add_mapping('<d-1>', '<d-1>')
- add_mapping('<khome>','<khome>')
- add_mapping('<kup>','<kup>')
- add_mapping('<kpageup>','<kpageup>')
- add_mapping('<kleft>','<kleft>')
- add_mapping('<korigin>','<korigin>')
- add_mapping('<kright>','<kright>')
- add_mapping('<kend>','<kend>')
- add_mapping('<kdown>','<kdown>')
- add_mapping('<kpagedown>','<kpagedown>')
- add_mapping('<kinsert>','<kinsert>')
- add_mapping('<kdel>','<kdel>')
- add_mapping('<kdivide>','<kdivide>')
- add_mapping('<kmultiply>','<kmultiply>')
- add_mapping('<kminus>','<kminus>')
- add_mapping('<kplus>','<kplus>')
- add_mapping('<kenter>','<kenter>')
- add_mapping('<kcomma>','<kcomma>')
- add_mapping('<kequal>','<kequal>')
- add_mapping('<f38>','<f38>')
- add_mapping('<f63>','<f63>')
+ add_mapping('<khome>', '<khome>')
+ add_mapping('<kup>', '<kup>')
+ add_mapping('<kpageup>', '<kpageup>')
+ add_mapping('<kleft>', '<kleft>')
+ add_mapping('<korigin>', '<korigin>')
+ add_mapping('<kright>', '<kright>')
+ add_mapping('<kend>', '<kend>')
+ add_mapping('<kdown>', '<kdown>')
+ add_mapping('<kpagedown>', '<kpagedown>')
+ add_mapping('<kinsert>', '<kinsert>')
+ add_mapping('<kdel>', '<kdel>')
+ add_mapping('<kdivide>', '<kdivide>')
+ add_mapping('<kmultiply>', '<kmultiply>')
+ add_mapping('<kminus>', '<kminus>')
+ add_mapping('<kplus>', '<kplus>')
+ add_mapping('<kenter>', '<kenter>')
+ add_mapping('<kcomma>', '<kcomma>')
+ add_mapping('<kequal>', '<kequal>')
+ add_mapping('<f38>', '<f38>')
+ add_mapping('<f63>', '<f63>')
end)
it('ok', function()
+ check_mapping('<A-l>', '<A-l>')
+ check_mapping('<A-L>', '<A-L>')
+ check_mapping('<A-S-l>', '<A-L>')
+ check_mapping('<A-S-L>', '<A-L>')
+ check_mapping('<D-l>', '<D-l>')
+ check_mapping('<D-L>', '<D-L>')
+ check_mapping('<D-S-l>', '<D-L>')
+ check_mapping('<D-S-L>', '<D-L>')
+ check_mapping('<C-l>', '<C-L>')
check_mapping('<C-L>', '<C-L>')
+ check_mapping('<C-S-l>', '<C-S-L>')
check_mapping('<C-S-L>', '<C-S-L>')
check_mapping('<s-up>', '<s-up>')
check_mapping('<c-s-up>', '<c-s-up>')
@@ -75,44 +92,44 @@ describe('mappings', function()
check_mapping('<c-d-a>', '<c-d-a>')
check_mapping('<d-c-a>', '<c-d-a>')
check_mapping('<d-1>', '<d-1>')
- check_mapping('<khome>','<khome>')
- check_mapping('<KP7>','<khome>')
- check_mapping('<kup>','<kup>')
- check_mapping('<KP8>','<kup>')
- check_mapping('<kpageup>','<kpageup>')
- check_mapping('<KP9>','<kpageup>')
- check_mapping('<kleft>','<kleft>')
- check_mapping('<KP4>','<kleft>')
- check_mapping('<korigin>','<korigin>')
- check_mapping('<KP5>','<korigin>')
- check_mapping('<kright>','<kright>')
- check_mapping('<KP6>','<kright>')
- check_mapping('<kend>','<kend>')
- check_mapping('<KP1>','<kend>')
- check_mapping('<kdown>','<kdown>')
- check_mapping('<KP2>','<kdown>')
- check_mapping('<kpagedown>','<kpagedown>')
- check_mapping('<KP3>','<kpagedown>')
- check_mapping('<kinsert>','<kinsert>')
- check_mapping('<KP0>','<kinsert>')
- check_mapping('<kdel>','<kdel>')
- check_mapping('<KPPeriod>','<kdel>')
- check_mapping('<kdivide>','<kdivide>')
- check_mapping('<KPDiv>','<kdivide>')
- check_mapping('<kmultiply>','<kmultiply>')
- check_mapping('<KPMult>','<kmultiply>')
- check_mapping('<kminus>','<kminus>')
- check_mapping('<KPMinus>','<kminus>')
- check_mapping('<kplus>','<kplus>')
- check_mapping('<KPPlus>','<kplus>')
- check_mapping('<kenter>','<kenter>')
- check_mapping('<KPEnter>','<kenter>')
- check_mapping('<kcomma>','<kcomma>')
- check_mapping('<KPComma>','<kcomma>')
- check_mapping('<kequal>','<kequal>')
- check_mapping('<KPEquals>','<kequal>')
- check_mapping('<f38>','<f38>')
- check_mapping('<f63>','<f63>')
+ check_mapping('<khome>', '<khome>')
+ check_mapping('<KP7>', '<khome>')
+ check_mapping('<kup>', '<kup>')
+ check_mapping('<KP8>', '<kup>')
+ check_mapping('<kpageup>', '<kpageup>')
+ check_mapping('<KP9>', '<kpageup>')
+ check_mapping('<kleft>', '<kleft>')
+ check_mapping('<KP4>', '<kleft>')
+ check_mapping('<korigin>', '<korigin>')
+ check_mapping('<KP5>', '<korigin>')
+ check_mapping('<kright>', '<kright>')
+ check_mapping('<KP6>', '<kright>')
+ check_mapping('<kend>', '<kend>')
+ check_mapping('<KP1>', '<kend>')
+ check_mapping('<kdown>', '<kdown>')
+ check_mapping('<KP2>', '<kdown>')
+ check_mapping('<kpagedown>', '<kpagedown>')
+ check_mapping('<KP3>', '<kpagedown>')
+ check_mapping('<kinsert>', '<kinsert>')
+ check_mapping('<KP0>', '<kinsert>')
+ check_mapping('<kdel>', '<kdel>')
+ check_mapping('<KPPeriod>', '<kdel>')
+ check_mapping('<kdivide>', '<kdivide>')
+ check_mapping('<KPDiv>', '<kdivide>')
+ check_mapping('<kmultiply>', '<kmultiply>')
+ check_mapping('<KPMult>', '<kmultiply>')
+ check_mapping('<kminus>', '<kminus>')
+ check_mapping('<KPMinus>', '<kminus>')
+ check_mapping('<kplus>', '<kplus>')
+ check_mapping('<KPPlus>', '<kplus>')
+ check_mapping('<kenter>', '<kenter>')
+ check_mapping('<KPEnter>', '<kenter>')
+ check_mapping('<kcomma>', '<kcomma>')
+ check_mapping('<KPComma>', '<kcomma>')
+ check_mapping('<kequal>', '<kequal>')
+ check_mapping('<KPEquals>', '<kequal>')
+ check_mapping('<f38>', '<f38>')
+ check_mapping('<f63>', '<f63>')
end)
it('support meta + multibyte char mapping', function()
@@ -151,7 +168,7 @@ describe('input split utf sequences', function()
it('ok', function()
local str = 'â–º'
feed('i' .. str:sub(1, 1))
- helpers.sleep(10)
+ vim.uv.sleep(10)
feed(str:sub(2, 3))
expect('â–º')
end)
@@ -160,7 +177,7 @@ describe('input split utf sequences', function()
command('inoremap â–º E296BA')
local str = 'â–º'
feed('i' .. str:sub(1, 1))
- helpers.sleep(10)
+ vim.uv.sleep(10)
feed(str:sub(2, 3))
expect('E296BA')
end)
@@ -241,7 +258,7 @@ it('Ctrl-6 is Ctrl-^ vim-patch:8.1.2333', function()
command('split aaa')
command('edit bbb')
feed('<C-6>')
- eq('aaa', funcs.bufname())
+ eq('aaa', fn.bufname())
end)
it('c_CTRL-R_CTRL-R, i_CTRL-R_CTRL-R, i_CTRL-G_CTRL-K work properly vim-patch:8.1.2346', function()
@@ -262,20 +279,18 @@ it('c_CTRL-R_CTRL-R, i_CTRL-R_CTRL-R, i_CTRL-G_CTRL-K work properly vim-patch:8.
end)
it('typing a simplifiable key at hit-enter prompt triggers mapping vim-patch:8.2.0839', function()
- local screen = Screen.new(60,8)
+ local screen = Screen.new(60, 8)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {bold = true, reverse = true}, -- MsgSeparator
- [3] = {bold = true, foreground = Screen.colors.SeaGreen}, -- MoreMsg
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { bold = true, reverse = true }, -- MsgSeparator
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
})
screen:attach()
command([[nnoremap <C-6> <Cmd>echo 'hit ctrl-6'<CR>]])
feed_command('ls')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2: }|
:ls |
1 %a "[No Name]" line 1 |
@@ -284,12 +299,7 @@ it('typing a simplifiable key at hit-enter prompt triggers mapping vim-patch:8.2
feed('<C-6>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
hit ctrl-6 |
]])
end)
@@ -307,7 +317,7 @@ it('unsimplified mapping works when there was a partial match vim-patch:8.2.4504
command('nnoremap <C-J> a')
command('nnoremap <NL> x')
command('nnoremap <C-J>x <Nop>')
- funcs.setline(1, 'x')
+ fn.setline(1, 'x')
-- CTRL-J b should have trigger the <C-J> mapping and then insert "b"
feed('<C-J>b<Esc>')
expect('xb')
@@ -319,49 +329,41 @@ describe('input non-printable chars', function()
end)
it("doesn't crash when echoing them back", function()
- write_file("Xtest-overwrite", [[foobar]])
- local screen = Screen.new(60,8)
+ write_file('Xtest-overwrite', [[foobar]])
+ local screen = Screen.new(60, 8)
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Blue1};
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red};
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4};
- [4] = {bold = true, reverse = true};
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [4] = { bold = true, reverse = true },
}
screen:attach()
- command("set shortmess-=F")
+ command('set shortmess-=F')
- feed_command("e Xtest-overwrite")
+ feed_command('e Xtest-overwrite')
screen:expect([[
^foobar |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
"Xtest-overwrite" [noeol] 1L, 6B |
]])
-- The timestamp is in second resolution, wait two seconds to be sure.
screen:sleep(2000)
- write_file("Xtest-overwrite", [[smurf]])
- feed_command("w")
+ write_file('Xtest-overwrite', [[smurf]])
+ feed_command('w')
screen:expect([[
foobar |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{4: }|
"Xtest-overwrite" |
{2:WARNING: The file has been changed since reading it!!!} |
{3:Do you really want to write to it (y/n)?}^ |
]])
- feed("u")
+ feed('u')
screen:expect([[
foobar |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{4: }|
"Xtest-overwrite" |
{2:WARNING: The file has been changed since reading it!!!} |
@@ -369,7 +371,7 @@ describe('input non-printable chars', function()
{3:Do you really want to write to it (y/n)?}^ |
]])
- feed("\005")
+ feed('\005')
screen:expect([[
foobar |
{1:~ }|
@@ -381,7 +383,7 @@ describe('input non-printable chars', function()
{3:Do you really want to write to it (y/n)?}^ |
]])
- feed("n")
+ feed('n')
screen:expect([[
foobar |
{4: }|
@@ -393,23 +395,23 @@ describe('input non-printable chars', function()
{3:Press ENTER or type command to continue}^ |
]])
- feed("<cr>")
+ feed('<cr>')
screen:expect([[
^foobar |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end)
end)
-describe("event processing and input", function()
+describe('event processing and input', function()
it('not blocked by event bursts', function()
- meths.set_keymap('', '<f2>', "<cmd>lua vim.rpcnotify(1, 'stop') winning = true <cr>", {noremap=true})
+ api.nvim_set_keymap(
+ '',
+ '<f2>',
+ "<cmd>lua vim.rpcnotify(1, 'stop') winning = true <cr>",
+ { noremap = true }
+ )
exec_lua [[
winning = false
@@ -425,9 +427,9 @@ describe("event processing and input", function()
burst(true)
]]
- eq({'notification', 'start', {}}, next_msg())
+ eq({ 'notification', 'start', {} }, next_msg())
feed '<f2>'
- eq({'notification', 'stop', {}}, next_msg())
+ eq({ 'notification', 'stop', {} }, next_msg())
end)
end)
@@ -436,8 +438,8 @@ describe('display is updated', function()
before_each(function()
screen = Screen.new(60, 8)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1}, -- NonText
- [2] = {bold = true}, -- ModeMsg
+ [1] = { bold = true, foreground = Screen.colors.Blue1 }, -- NonText
+ [2] = { bold = true }, -- ModeMsg
})
screen:attach()
end)
@@ -449,11 +451,7 @@ describe('display is updated', function()
screen:expect([[
abc |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
]])
end)
@@ -465,11 +463,7 @@ describe('display is updated', function()
screen:expect([[
abc |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
]])
end)
diff --git a/test/functional/ui/linematch_spec.lua b/test/functional/ui/linematch_spec.lua
index ef47ea7ed0..40df5cadf1 100644
--- a/test/functional/ui/linematch_spec.lua
+++ b/test/functional/ui/linematch_spec.lua
@@ -39,32 +39,33 @@ describe('Diff mode screen with 3 diffs open', function()
screen = Screen.new(100, 16)
screen:attach()
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray};
- [2] = {foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.LightCyan1};
- [3] = {reverse = true};
- [4] = {background = Screen.colors.LightBlue};
- [5] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray};
- [6] = {foreground = Screen.colors.Blue1, bold = true};
- [7] = {reverse = true, bold = true};
- [8] = {background = Screen.colors.Red1, bold = true};
- [10] = {foreground = Screen.colors.Brown};
- [9] = {background = Screen.colors.Plum1};
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray },
+ [2] = { foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.LightCyan1 },
+ [3] = { reverse = true },
+ [4] = { background = Screen.colors.LightBlue },
+ [5] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray },
+ [6] = { foreground = Screen.colors.Blue1, bold = true },
+ [7] = { reverse = true, bold = true },
+ [8] = { background = Screen.colors.Red1, bold = true },
+ [10] = { foreground = Screen.colors.Brown },
+ [9] = { background = Screen.colors.Plum1 },
})
feed('<c-w>=')
feed(':windo set nu!<cr>')
end)
- describe('setup the diff screen to look like a merge conflict with 3 files in diff mode', function()
- before_each(function()
-
- local f1 = [[
+ describe(
+ 'setup the diff screen to look like a merge conflict with 3 files in diff mode',
+ function()
+ before_each(function()
+ local f1 = [[
common line
AAA
AAA
AAA
]]
- local f2 = [[
+ local f2 = [[
common line
<<<<<<< HEAD
@@ -77,7 +78,7 @@ describe('Diff mode screen with 3 diffs open', function()
BBB
>>>>>>> branch1
]]
- local f3 = [[
+ local f3 = [[
common line
BBB
@@ -85,16 +86,16 @@ describe('Diff mode screen with 3 diffs open', function()
BBB
]]
- write_file(fname, f1, false)
- write_file(fname_2, f2, false)
- write_file(fname_3, f3, false)
- reread()
- end)
+ write_file(fname, f1, false)
+ write_file(fname_2, f2, false)
+ write_file(fname_3, f3, false)
+ reread()
+ end)
- it('get from window 1', function()
- feed('1<c-w>w')
- feed(':2,6diffget screen-1.2<cr>')
- screen:expect([[
+ it('get from window 1', function()
+ feed('1<c-w>w')
+ feed(':2,6diffget screen-1.2<cr>')
+ screen:expect([[
{1: }{10: 1 }^ │{1: }{10: 1 } │{1: }{10: 1 } |
{1: }{10: 2 }common line │{1: }{10: 2 }common line │{1: }{10: 2 }common line |
{1: }{10: 3 }{9:<<<<<<< HEAD }│{1: }{10: 3 }{9:<<<<<<< HEAD }│{1: }{10: }{2:---------------------------}|
@@ -107,17 +108,16 @@ describe('Diff mode screen with 3 diffs open', function()
{1: }{10: 10 }{9: BBB }│{1: }{10: 10 }{9: BBB }│{1: }{10: }{2:---------------------------}|
{1: }{10: 11 }{9:>>>>>>> branch1 }│{1: }{10: 11 }{9:>>>>>>> branch1 }│{1: }{10: }{2:---------------------------}|
{1: }{10: 12 } │{1: }{10: 12 } │{1: }{10: 6 } |
- {6:~ }│{6:~ }│{6:~ }|
- {6:~ }│{6:~ }│{6:~ }|
+ {6:~ }│{6:~ }│{6:~ }|*2
{7:<-functional-diff-screen-1.3 [+] }{3:<est-functional-diff-screen-1.2 Xtest-functional-diff-screen-1 }|
:2,6diffget screen-1.2 |
]])
- end)
+ end)
- it('get from window 2', function()
- feed('2<c-w>w')
- feed(':5,7diffget screen-1.3<cr>')
- screen:expect([[
+ it('get from window 2', function()
+ feed('2<c-w>w')
+ feed(':5,7diffget screen-1.3<cr>')
+ screen:expect([[
{1: }{10: 1 } │{1: }{10: 1 }^ │{1: }{10: 1 } |
{1: }{10: 2 }common line │{1: }{10: 2 }common line │{1: }{10: 2 }common line |
{1: }{10: }{2:---------------------------}│{1: }{10: 3 }{4:<<<<<<< HEAD }│{1: }{10: }{2:---------------------------}|
@@ -127,20 +127,16 @@ describe('Diff mode screen with 3 diffs open', function()
{1: }{10: 5 }{9: }{8:BBB}{9: }│{1: }{10: 7 }{9: }{8:BBB}{9: }│{1: }{10: 5 }{9: }{8:AAA}{9: }|
{1: }{10: }{2:---------------------------}│{1: }{10: 8 }{4:>>>>>>> branch1 }│{1: }{10: }{2:---------------------------}|
{1: }{10: 6 } │{1: }{10: 9 } │{1: }{10: 6 } |
- {6:~ }│{6:~ }│{6:~ }|
- {6:~ }│{6:~ }│{6:~ }|
- {6:~ }│{6:~ }│{6:~ }|
- {6:~ }│{6:~ }│{6:~ }|
- {6:~ }│{6:~ }│{6:~ }|
+ {6:~ }│{6:~ }│{6:~ }|*5
{3:<test-functional-diff-screen-1.3 }{7:<functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }|
:5,7diffget screen-1.3 |
]])
- end)
+ end)
- it('get from window 3', function()
- feed('3<c-w>w')
- feed(':5,6diffget screen-1.2<cr>')
- screen:expect([[
+ it('get from window 3', function()
+ feed('3<c-w>w')
+ feed(':5,6diffget screen-1.2<cr>')
+ screen:expect([[
{1: }{10: 1 } │{1: }{10: 1 } │{1: }{10: 1 }^ |
{1: }{10: 2 }common line │{1: }{10: 2 }common line │{1: }{10: 2 }common line |
{1: }{10: }{2:---------------------------}│{1: }{10: 3 }{4:<<<<<<< HEAD }│{1: }{10: }{2:---------------------------}|
@@ -153,17 +149,16 @@ describe('Diff mode screen with 3 diffs open', function()
{1: }{10: 5 } BBB │{1: }{10: 10 } BBB │{1: }{10: 9 } BBB |
{1: }{10: }{2:---------------------------}│{1: }{10: 11 }{9:>>>>>>> branch1 }│{1: }{10: 10 }{9:>>>>>>> branch1 }|
{1: }{10: 6 } │{1: }{10: 12 } │{1: }{10: 11 } |
- {6:~ }│{6:~ }│{6:~ }|
- {6:~ }│{6:~ }│{6:~ }|
+ {6:~ }│{6:~ }│{6:~ }|*2
{3:<test-functional-diff-screen-1.3 <est-functional-diff-screen-1.2 }{7:<st-functional-diff-screen-1 [+] }|
:5,6diffget screen-1.2 |
]])
- end)
+ end)
- it('put from window 2 - part', function()
- feed('2<c-w>w')
- feed(':6,8diffput screen-1<cr>')
- screen:expect([[
+ it('put from window 2 - part', function()
+ feed('2<c-w>w')
+ feed(':6,8diffput screen-1<cr>')
+ screen:expect([[
{1: }{10: 1 } │{1: }{10: 1 }^ │{1: }{10: 1 } |
{1: }{10: 2 }common line │{1: }{10: 2 }common line │{1: }{10: 2 }common line |
{1: }{10: }{2:---------------------------}│{1: }{10: 3 }{4:<<<<<<< HEAD }│{1: }{10: }{2:---------------------------}|
@@ -176,17 +171,15 @@ describe('Diff mode screen with 3 diffs open', function()
{1: }{10: 5 } BBB │{1: }{10: 10 } BBB │{1: }{10: 7 } BBB |
{1: }{10: }{2:---------------------------}│{1: }{10: 11 }{4:>>>>>>> branch1 }│{1: }{10: }{2:---------------------------}|
{1: }{10: 6 } │{1: }{10: 12 } │{1: }{10: 8 } |
- {6:~ }│{6:~ }│{6:~ }|
- {6:~ }│{6:~ }│{6:~ }|
+ {6:~ }│{6:~ }│{6:~ }|*2
{3:<test-functional-diff-screen-1.3 }{7:<est-functional-diff-screen-1.2 }{3:<st-functional-diff-screen-1 [+] }|
:6,8diffput screen-1 |
]])
-
- end)
- it('put from window 2 - part to end', function()
- feed('2<c-w>w')
- feed(':6,11diffput screen-1<cr>')
- screen:expect([[
+ end)
+ it('put from window 2 - part to end', function()
+ feed('2<c-w>w')
+ feed(':6,11diffput screen-1<cr>')
+ screen:expect([[
{1: }{10: 1 } │{1: }{10: 1 }^ │{1: }{10: 1 } |
{1: }{10: 2 }common line │{1: }{10: 2 }common line │{1: }{10: 2 }common line |
{1: }{10: }{2:---------------------------}│{1: }{10: 3 }{4:<<<<<<< HEAD }│{1: }{10: }{2:---------------------------}|
@@ -199,14 +192,13 @@ describe('Diff mode screen with 3 diffs open', function()
{1: }{10: 5 } BBB │{1: }{10: 10 } BBB │{1: }{10: 9 } BBB |
{1: }{10: }{2:---------------------------}│{1: }{10: 11 }{9:>>>>>>> branch1 }│{1: }{10: 10 }{9:>>>>>>> branch1 }|
{1: }{10: 6 } │{1: }{10: 12 } │{1: }{10: 11 } |
- {6:~ }│{6:~ }│{6:~ }|
- {6:~ }│{6:~ }│{6:~ }|
+ {6:~ }│{6:~ }│{6:~ }|*2
{3:<test-functional-diff-screen-1.3 }{7:<est-functional-diff-screen-1.2 }{3:<st-functional-diff-screen-1 [+] }|
:6,11diffput screen-1 |
]])
-
- end)
- end)
+ end)
+ end
+ )
end)
describe('Diff mode screen with 2 diffs open', function()
@@ -238,16 +230,16 @@ describe('Diff mode screen with 2 diffs open', function()
screen = Screen.new(100, 20)
screen:attach()
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray};
- [2] = {foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.LightCyan1};
- [3] = {reverse = true};
- [4] = {background = Screen.colors.LightBlue};
- [5] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray};
- [6] = {foreground = Screen.colors.Blue1, bold = true};
- [7] = {reverse = true, bold = true};
- [8] = {background = Screen.colors.Red1, bold = true};
- [10] = {foreground = Screen.colors.Brown};
- [9] = {background = Screen.colors.Plum1};
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Gray },
+ [2] = { foreground = Screen.colors.Blue1, bold = true, background = Screen.colors.LightCyan1 },
+ [3] = { reverse = true },
+ [4] = { background = Screen.colors.LightBlue },
+ [5] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGray },
+ [6] = { foreground = Screen.colors.Blue1, bold = true },
+ [7] = { reverse = true, bold = true },
+ [8] = { background = Screen.colors.Red1, bold = true },
+ [10] = { foreground = Screen.colors.Brown },
+ [9] = { background = Screen.colors.Plum1 },
})
feed('<c-w>=')
feed(':windo set nu!<cr>')
@@ -310,12 +302,7 @@ something
{1: }{10: }{2:-------------------------------------------}│{1: }{10: 16 }{4:DEF }|
{1: }{10: 15 }something │{1: }{10: 17 }something |
{1: }{10: 16 } │{1: }{10: 18 } |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }|
:5,9diffget |
]])
@@ -339,9 +326,7 @@ something
{1: }{10: }{2:-------------------------------------------}│{1: }{10: 13 }{4:DEF }|
{1: }{10: 12 }something │{1: }{10: 14 }something |
{1: }{10: 13 } │{1: }{10: 15 } |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*3
{3:Xtest-functional-diff-screen-1.2 }{7:Xtest-functional-diff-screen-1 [+] }|
:5,10diffget |
]])
@@ -363,15 +348,10 @@ something
{1: }{10: 11 }common line │{1: }{10: 11 }common line |
{1: }{10: 12 }something │{1: }{10: 12 }something |
{1: }{10: 13 } │{1: }{10: 13 } |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*5
{3:Xtest-functional-diff-screen-1.2 }{7:Xtest-functional-diff-screen-1 [+] }|
:4,17diffget |
]])
-
end)
it('get all from window 1', function()
feed('1<c-w>w')
@@ -776,7 +756,6 @@ something
{3:Xtest-functional-diff-screen-1.2 [+] }{7:Xtest-functional-diff-screen-1 }|
:e |
]])
-
end)
end)
describe('setup a diff with 2 files and set linematch:30', function()
@@ -804,19 +783,7 @@ d
{1: }{10: 3 }{9:d }│{1: }{10: 2 }{8:// }{9:d }|
{1: }{10: }{2:-------------------------------------------}│{1: }{10: 3 }{4:// d }|
{1: }{10: 4 } │{1: }{10: 4 } |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*13
{7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }|
:e |
]])
@@ -853,17 +820,7 @@ void testFunction () {
{1: }{10: }{2:-------------------------------------------}│{1: }{10: 5 }{4: } }|
{1: }{10: 4 }} │{1: }{10: 6 }} |
{1: }{10: 5 } │{1: }{10: 7 } |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*11
{7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }|
:e |
]])
@@ -903,15 +860,7 @@ void testFunction () {
{1: }{10: 7 }{4:?B }│{1: }{10: }{2:--------------------------------------------}|
{1: }{10: 8 }{4:?C }│{1: }{10: }{2:--------------------------------------------}|
{1: }{10: 9 } │{1: }{10: 4 } |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*9
{7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }|
:e |
]])
@@ -951,15 +900,7 @@ void testFunction () {
{1: }{10: 7 }{8:?}{9:C }│{1: }{10: 3 }{8:!}{9:C }|
{1: }{10: 8 }{4:?C }│{1: }{10: }{2:--------------------------------------------}|
{1: }{10: 9 } │{1: }{10: 4 } |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*9
{7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }|
:e |
]])
@@ -1006,10 +947,12 @@ something
reread()
end)
- it('enable linematch for the longest diff block by increasing the number argument passed to linematch', function()
- feed('1<c-w>w')
- -- linematch is disabled for the longest diff because it's combined line length is over 10
- screen:expect([[
+ it(
+ 'enable linematch for the longest diff block by increasing the number argument passed to linematch',
+ function()
+ feed('1<c-w>w')
+ -- linematch is disabled for the longest diff because it's combined line length is over 10
+ screen:expect([[
{1: }{10: 1 }^common line │{1: }{10: 1 }common line |
{1: }{10: 2 }{4:DEF }│{1: }{10: }{2:--------------------------------------------}|
{1: }{10: 3 }{8:GHI}{9: }│{1: }{10: 2 }{8:HIL}{9: }|
@@ -1031,10 +974,10 @@ something
{7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }|
:e |
]])
- -- enable it by increasing the number
- feed(":set diffopt-=linematch:10<cr>")
- feed(":set diffopt+=linematch:30<cr>")
- screen:expect([[
+ -- enable it by increasing the number
+ feed(':set diffopt-=linematch:10<cr>')
+ feed(':set diffopt+=linematch:30<cr>')
+ screen:expect([[
{1: }{10: 1 }^common line │{1: }{10: 1 }common line |
{1: }{10: 2 }{4:DEF }│{1: }{10: }{2:--------------------------------------------}|
{1: }{10: 3 }{8:GHI}{9: }│{1: }{10: 2 }{8:HIL}{9: }|
@@ -1056,7 +999,8 @@ something
{7:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 }|
:set diffopt+=linematch:30 |
]])
- end)
+ end
+ )
it('get all from second window', function()
feed('2<c-w>w')
feed(':1,12diffget<cr>')
@@ -1099,20 +1043,17 @@ something
{1: }{10: 10 }common line │{1: }{10: 10 }common line |
{1: }{10: 11 }something │{1: }{10: 11 }something |
{1: }{10: 12 } │{1: }{10: 12 } |
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
- {6:~ }│{6:~ }|
+ {6:~ }│{6:~ }|*6
{7:Xtest-functional-diff-screen-1.2 [+] }{3:Xtest-functional-diff-screen-1 }|
:1,19diffget |
]])
end)
- it('get part of the non linematched diff block in window 2 line 7 - 8 (non line matched block)', function()
- feed('2<c-w>w')
- feed(':7,8diffget<cr>')
- screen:expect([[
+ it(
+ 'get part of the non linematched diff block in window 2 line 7 - 8 (non line matched block)',
+ function()
+ feed('2<c-w>w')
+ feed(':7,8diffget<cr>')
+ screen:expect([[
{1: }{10: 1 }common line │{1: }{10: 1 }^common line |
{1: }{10: 2 }{4:DEF }│{1: }{10: }{2:--------------------------------------------}|
{1: }{10: 3 }{8:GHI}{9: }│{1: }{10: 2 }{8:HIL}{9: }|
@@ -1134,11 +1075,14 @@ something
{3:Xtest-functional-diff-screen-1.2 }{7:Xtest-functional-diff-screen-1 [+] }|
:7,8diffget |
]])
- end)
- it('get part of the non linematched diff block in window 2 line 8 - 10 (line matched block)', function()
- feed('2<c-w>w')
- feed(':8,10diffget<cr>')
- screen:expect([[
+ end
+ )
+ it(
+ 'get part of the non linematched diff block in window 2 line 8 - 10 (line matched block)',
+ function()
+ feed('2<c-w>w')
+ feed(':8,10diffget<cr>')
+ screen:expect([[
{1: }{10: 1 }common line │{1: }{10: 1 }^common line |
{1: }{10: 2 }{4:DEF }│{1: }{10: }{2:--------------------------------------------}|
{1: }{10: 3 }{8:GHI}{9: }│{1: }{10: 2 }{8:HIL}{9: }|
@@ -1160,7 +1104,8 @@ something
{3:Xtest-functional-diff-screen-1.2 }{7:Xtest-functional-diff-screen-1 [+] }|
:8,10diffget |
]])
- end)
+ end
+ )
end)
end)
@@ -1173,13 +1118,13 @@ describe('regressions', function()
screen = Screen.new(100, 20)
screen:attach()
-- line must be greater than MATCH_CHAR_MAX_LEN
- helpers.curbufmeths.set_lines(0, -1, false, { string.rep('a', 1000)..'hello' })
+ helpers.api.nvim_buf_set_lines(0, 0, -1, false, { string.rep('a', 1000) .. 'hello' })
helpers.exec 'vnew'
- helpers.curbufmeths.set_lines(0, -1, false, { string.rep('a', 1010)..'world' })
+ helpers.api.nvim_buf_set_lines(0, 0, -1, false, { string.rep('a', 1010) .. 'world' })
helpers.exec 'windo diffthis'
end)
- it("properly computes filler lines for hunks bigger than linematch limit", function()
+ it('properly computes filler lines for hunks bigger than linematch limit', function()
clear()
feed(':set diffopt+=linematch:10<cr>')
screen = Screen.new(100, 20)
@@ -1188,12 +1133,13 @@ describe('regressions', function()
for i = 0, 29 do
lines[#lines + 1] = tostring(i)
end
- helpers.curbufmeths.set_lines(0, -1, false, lines)
+ helpers.api.nvim_buf_set_lines(0, 0, -1, false, lines)
helpers.exec 'vnew'
- helpers.curbufmeths.set_lines(0, -1, false, { '00', '29' })
+ helpers.api.nvim_buf_set_lines(0, 0, -1, false, { '00', '29' })
helpers.exec 'windo diffthis'
feed('<C-e>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }{2:------------------------------------------------}│{1: }{3:^1 }|
{1: }{2:------------------------------------------------}│{1: }{3:2 }|
{1: }{2:------------------------------------------------}│{1: }{3:3 }|
@@ -1214,12 +1160,18 @@ describe('regressions', function()
{1: }29 │{1: }{3:18 }|
{4:[No Name] [+] }{5:[No Name] [+] }|
|
- ]], attr_ids={
- [1] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Grey};
- [2] = {bold = true, background = Screen.colors.LightCyan, foreground = Screen.colors.Blue1};
- [3] = {background = Screen.colors.LightBlue};
- [4] = {reverse = true};
- [5] = {reverse = true, bold = true};
- }}
+ ]],
+ attr_ids = {
+ [1] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Grey },
+ [2] = {
+ bold = true,
+ background = Screen.colors.LightCyan,
+ foreground = Screen.colors.Blue1,
+ },
+ [3] = { background = Screen.colors.LightBlue },
+ [4] = { reverse = true },
+ [5] = { reverse = true, bold = true },
+ },
+ }
end)
end)
diff --git a/test/functional/ui/messages_spec.lua b/test/functional/ui/messages_spec.lua
index 1d11a12af4..31b1464589 100644
--- a/test/functional/ui/messages_spec.lua
+++ b/test/functional/ui/messages_spec.lua
@@ -5,9 +5,9 @@ local eval = helpers.eval
local eq = helpers.eq
local command = helpers.command
local set_method_error = helpers.set_method_error
-local meths = helpers.meths
+local api = helpers.api
local async_meths = helpers.async_meths
-local test_build_dir = helpers.test_build_dir
+local test_build_dir = helpers.paths.test_build_dir
local nvim_prog = helpers.nvim_prog
local exec = helpers.exec
local exec_capture = helpers.exec_capture
@@ -17,7 +17,7 @@ local poke_eventloop = helpers.poke_eventloop
local assert_alive = helpers.assert_alive
local is_os = helpers.is_os
local is_ci = helpers.is_ci
-local funcs = helpers.funcs
+local fn = helpers.fn
local skip = helpers.skip
describe('ui/ext_messages', function()
@@ -27,18 +27,18 @@ describe('ui/ext_messages', function()
before_each(function()
clear()
screen = Screen.new(25, 5)
- screen:attach({rgb=true, ext_messages=true, ext_popupmenu=true})
+ screen:attach({ rgb = true, ext_messages = true, ext_popupmenu = true })
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [3] = {bold = true},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [5] = {foreground = Screen.colors.Blue1},
- [6] = {bold = true, reverse = true},
- [7] = {background = Screen.colors.Yellow},
- [8] = {foreground = Screen.colors.Red},
- [9] = {special = Screen.colors.Red, undercurl = true},
- [10] = {foreground = Screen.colors.Brown};
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = { bold = true },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [5] = { foreground = Screen.colors.Blue1 },
+ [6] = { bold = true, reverse = true },
+ [7] = { background = Screen.colors.Yellow },
+ [8] = { foreground = Screen.colors.Red },
+ [9] = { special = Screen.colors.Red, undercurl = true },
+ [10] = { foreground = Screen.colors.Brown },
})
end)
after_each(function()
@@ -48,25 +48,26 @@ describe('ui/ext_messages', function()
it('msg_clear follows msg_show kind of confirm', function()
feed('iline 1<esc>')
feed(':call confirm("test")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
line ^1 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={ {
- content = {{"\ntest\n[O]k: ", 4}},
- kind = 'confirm',
- }}}
+ {1:~ }|*4
+ ]],
+ messages = {
+ {
+ content = { { '\ntest\n[O]k: ', 4 } },
+ kind = 'confirm',
+ },
+ },
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
line ^1 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
end)
it('msg_show kind=confirm,confirm_sub,emsg,wmsg,quickfix', function()
@@ -74,293 +75,335 @@ describe('ui/ext_messages', function()
-- kind=confirm
feed(':echo confirm("test")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
line 1 |
line ^2 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={ {
- content = {{"\ntest\n[O]k: ", 4}},
- kind = 'confirm',
- }}}
+ {1:~ }|*3
+ ]],
+ messages = {
+ {
+ content = { { '\ntest\n[O]k: ', 4 } },
+ kind = 'confirm',
+ },
+ },
+ }
feed('<cr><cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
line 1 |
line ^2 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={ {
- content = { { "\ntest\n[O]k: ", 4 } },
- kind = "confirm"
- }, {
- content = { { "1" } },
- kind = "echo"
- }, {
- content = { { "Press ENTER or type command to continue", 4 } },
- kind = "return_prompt"
- } }}
+ {1:~ }|*3
+ ]],
+ messages = {
+ {
+ content = { { '\ntest\n[O]k: ', 4 } },
+ kind = 'confirm',
+ },
+ {
+ content = { { '1' } },
+ kind = 'echo',
+ },
+ {
+ content = { { 'Press ENTER or type command to continue', 4 } },
+ kind = 'return_prompt',
+ },
+ },
+ }
feed('<cr><cr>')
-- kind=confirm_sub
feed(':%s/i/X/gc<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
l{7:i}ne 1 |
l{8:i}ne ^2 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], attr_ids={
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [3] = {bold = true},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [5] = {foreground = Screen.colors.Blue1},
- [6] = {bold = true, reverse = true},
- [7] = {reverse = true},
- [8] = {background = Screen.colors.Yellow},
- }, messages={ {
- content = { { "replace with X (y/n/a/q/l/^E/^Y)?", 4 } },
- kind = "confirm_sub"
- } }}
+ {1:~ }|*3
+ ]],
+ attr_ids = {
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = { bold = true },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [5] = { foreground = Screen.colors.Blue1 },
+ [6] = { bold = true, reverse = true },
+ [7] = { reverse = true },
+ [8] = { background = Screen.colors.Yellow },
+ },
+ messages = {
+ {
+ content = { { 'replace with X (y/n/a/q/l/^E/^Y)?', 4 } },
+ kind = 'confirm_sub',
+ },
+ },
+ }
feed('nq')
-- kind=wmsg (editing readonly file)
command('write ' .. fname)
command('set readonly nohls')
feed('G$x')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
line 1 |
{MATCH:.*}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], attr_ids={
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [7] = {foreground = Screen.colors.Red},
- }, messages={ {
- content = { { "W10: Warning: Changing a readonly file", 7 } },
- kind = "wmsg"
- }
- }}
+ {1:~ }|*3
+ ]],
+ attr_ids = {
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [7] = { foreground = Screen.colors.Red },
+ },
+ messages = {
+ {
+ content = { { 'W10: Warning: Changing a readonly file', 7 } },
+ kind = 'wmsg',
+ },
+ },
+ }
-- kind=wmsg ('wrapscan' after search reaches EOF)
feed('uG$/i<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
l^ine 1 |
line 2 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], attr_ids={
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [3] = {bold = true},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [5] = {foreground = Screen.colors.Blue1},
- [6] = {bold = true, reverse = true},
- [7] = {foreground = Screen.colors.Red},
- }, messages={ {
- content = { { "search hit BOTTOM, continuing at TOP", 7 } },
- kind = "wmsg"
- } }}
+ {1:~ }|*3
+ ]],
+ attr_ids = {
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = { bold = true },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [5] = { foreground = Screen.colors.Blue1 },
+ [6] = { bold = true, reverse = true },
+ [7] = { foreground = Screen.colors.Red },
+ },
+ messages = {
+ {
+ content = { { 'search hit BOTTOM, continuing at TOP', 7 } },
+ kind = 'wmsg',
+ },
+ },
+ }
-- kind=emsg after :throw
feed(':throw "foo"<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
l^ine 1 |
line 2 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={ {
- content = { { "Error detected while processing :", 2 } },
- kind = "emsg"
- }, {
- content = { { "E605: Exception not caught: foo", 2 } },
- kind = ""
- }, {
- content = { { "Press ENTER or type command to continue", 4 } },
- kind = "return_prompt"
- } }
+ {1:~ }|*3
+ ]],
+ messages = {
+ {
+ content = { { 'Error detected while processing :', 2 } },
+ kind = 'emsg',
+ },
+ {
+ content = { { 'E605: Exception not caught: foo', 2 } },
+ kind = '',
+ },
+ {
+ content = { { 'Press ENTER or type command to continue', 4 } },
+ kind = 'return_prompt',
+ },
+ },
}
-- kind=quickfix after :cnext
feed('<c-c>')
command("caddexpr [expand('%').':1:line1',expand('%').':2:line2']")
feed(':cnext<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
line 1 |
^line 2 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={ {
- content = { { "(2 of 2): line2" } },
- kind = "quickfix"
- } }}
+ {1:~ }|*3
+ ]],
+ messages = {
+ {
+ content = { { '(2 of 2): line2' } },
+ kind = 'quickfix',
+ },
+ },
+ }
end)
it(':echoerr', function()
feed(':echoerr "raa"<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{"raa", 2}},
- kind = "echoerr",
- }}}
+ {1:~ }|*4
+ ]],
+ messages = { {
+ content = { { 'raa', 2 } },
+ kind = 'echoerr',
+ } },
+ }
-- cmdline in a later input cycle clears error message
feed(':')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], cmdline={{
- firstc = ":",
- content = {{ "" }},
- pos = 0,
- }}}
-
+ {1:~ }|*4
+ ]],
+ cmdline = { {
+ firstc = ':',
+ content = { { '' } },
+ pos = 0,
+ } },
+ }
feed('echoerr "bork" | echoerr "fail"<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{ "bork", 2 }},
- kind = "echoerr"
- }, {
- content = {{ "fail", 2 }},
- kind = "echoerr"
- }, {
- content = {{ "Press ENTER or type command to continue", 4 }},
- kind = "return_prompt"
- }}}
+ {1:~ }|*4
+ ]],
+ messages = {
+ {
+ content = { { 'bork', 2 } },
+ kind = 'echoerr',
+ },
+ {
+ content = { { 'fail', 2 } },
+ kind = 'echoerr',
+ },
+ {
+ content = { { 'Press ENTER or type command to continue', 4 } },
+ kind = 'return_prompt',
+ },
+ },
+ }
feed(':echoerr "extrafail"<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = { { "bork", 2 } },
- kind = "echoerr"
- }, {
- content = { { "fail", 2 } },
- kind = "echoerr"
- }, {
- content = { { "extrafail", 2 } },
- kind = "echoerr"
- }, {
- content = { { "Press ENTER or type command to continue", 4 } },
- kind = "return_prompt"
- }}}
+ {1:~ }|*4
+ ]],
+ messages = {
+ {
+ content = { { 'bork', 2 } },
+ kind = 'echoerr',
+ },
+ {
+ content = { { 'fail', 2 } },
+ kind = 'echoerr',
+ },
+ {
+ content = { { 'extrafail', 2 } },
+ kind = 'echoerr',
+ },
+ {
+ content = { { 'Press ENTER or type command to continue', 4 } },
+ kind = 'return_prompt',
+ },
+ },
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
-- cmdline without interleaving wait/display keeps the error message
feed(':echoerr "problem" | let x = input("foo> ")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{ "problem", 2 }},
- kind = "echoerr"
- }}, cmdline={{
- prompt = "foo> ",
- content = {{ "" }},
- pos = 0,
- }}}
+ {1:~ }|*4
+ ]],
+ messages = { {
+ content = { { 'problem', 2 } },
+ kind = 'echoerr',
+ } },
+ cmdline = {
+ {
+ prompt = 'foo> ',
+ content = { { '' } },
+ pos = 0,
+ },
+ },
+ }
feed('solution<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
eq('solution', eval('x'))
- feed(":messages<cr>")
- screen:expect{grid=[[
+ feed(':messages<cr>')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], msg_history={
- {kind="echoerr", content={{"raa", 2}}},
- {kind="echoerr", content={{"bork", 2}}},
- {kind="echoerr", content={{"fail", 2}}},
- {kind="echoerr", content={{"extrafail", 2}}},
- {kind="echoerr", content={{"problem", 2}}}
- }, messages={{
- content = {{ "Press ENTER or type command to continue", 4 }},
- kind = "return_prompt"
- }}}
+ {1:~ }|*4
+ ]],
+ msg_history = {
+ { kind = 'echoerr', content = { { 'raa', 2 } } },
+ { kind = 'echoerr', content = { { 'bork', 2 } } },
+ { kind = 'echoerr', content = { { 'fail', 2 } } },
+ { kind = 'echoerr', content = { { 'extrafail', 2 } } },
+ { kind = 'echoerr', content = { { 'problem', 2 } } },
+ },
+ messages = {
+ {
+ content = { { 'Press ENTER or type command to continue', 4 } },
+ kind = 'return_prompt',
+ },
+ },
+ }
feed '<cr>'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
end)
it(':echoerr multiline', function()
exec_lua([[vim.g.multi = table.concat({ "bork", "fail" }, "\n")]])
feed(':echoerr g:multi<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{ "bork\nfail", 2 }},
- kind = "echoerr"
- }}}
+ {1:~ }|*4
+ ]],
+ messages = { {
+ content = { { 'bork\nfail', 2 } },
+ kind = 'echoerr',
+ } },
+ }
feed(':messages<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{ "Press ENTER or type command to continue", 4 }},
- kind = "return_prompt"
- }}, msg_history={{
- content = {{ "bork\nfail", 2 }},
- kind = "echoerr"
- }}}
+ {1:~ }|*4
+ ]],
+ messages = {
+ {
+ content = { { 'Press ENTER or type command to continue', 4 } },
+ kind = 'return_prompt',
+ },
+ },
+ msg_history = {
+ {
+ content = { { 'bork\nfail', 2 } },
+ kind = 'echoerr',
+ },
+ },
+ }
end)
it('shortmess-=S', function()
@@ -368,470 +411,533 @@ describe('ui/ext_messages', function()
feed('iline 1\nline 2<esc>')
feed('/line<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{7:^line} 1 |
{7:line} 2 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={
- {content = {{"/line W [1/2]"}}, kind = "search_count"}
- }}
+ {1:~ }|*3
+ ]],
+ messages = {
+ { content = { { '/line W [1/2]' } }, kind = 'search_count' },
+ },
+ }
feed('n')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{7:line} 1 |
{7:^line} 2 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={
- {content = {{"/line [2/2]"}}, kind = "search_count"}
- }}
+ {1:~ }|*3
+ ]],
+ messages = {
+ { content = { { '/line [2/2]' } }, kind = 'search_count' },
+ },
+ }
end)
it(':hi Group output', function()
feed(':hi ErrorMsg<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={
- {content = {{"\nErrorMsg " }, {"xxx", 2}, {" "},
- {"ctermfg=", 5 }, { "15 " }, { "ctermbg=", 5 }, { "1 " },
- {"guifg=", 5 }, { "White " }, { "guibg=", 5 }, { "Red" }},
- kind = ""}
- }}
+ {1:~ }|*4
+ ]],
+ messages = {
+ {
+ content = {
+ { '\nErrorMsg ' },
+ { 'xxx', 2 },
+ { ' ' },
+ { 'ctermfg=', 5 },
+ { '15 ' },
+ { 'ctermbg=', 5 },
+ { '1 ' },
+ { 'guifg=', 5 },
+ { 'White ' },
+ { 'guibg=', 5 },
+ { 'Red' },
+ },
+ kind = '',
+ },
+ },
+ }
end)
it("doesn't crash with column adjustment #10069", function()
feed(':let [x,y] = [1,2]<cr>')
feed(':let x y<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={
- {content = {{ "x #1" }}, kind = ""},
- {content = {{ "y #2" }}, kind = ""},
- {content = {{ "Press ENTER or type command to continue", 4 }}, kind = "return_prompt"}
- }}
+ {1:~ }|*4
+ ]],
+ messages = {
+ { content = { { 'x #1' } }, kind = '' },
+ { content = { { 'y #2' } }, kind = '' },
+ { content = { { 'Press ENTER or type command to continue', 4 } }, kind = 'return_prompt' },
+ },
+ }
end)
it('&showmode', function()
command('imap <f2> <cmd>echomsg "stuff"<cr>')
feed('i')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={{"-- INSERT --", 3}}}
+ {1:~ }|*4
+ ]],
+ showmode = { { '-- INSERT --', 3 } },
+ }
feed('alphpabet<cr>alphanum<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
alphpabet |
alphanum |
^ |
- {1:~ }|
- {1:~ }|
- ]], showmode={ { "-- INSERT --", 3 } }}
+ {1:~ }|*2
+ ]],
+ showmode = { { '-- INSERT --', 3 } },
+ }
feed('<c-x>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
alphpabet |
alphanum |
^ |
- {1:~ }|
- {1:~ }|
- ]], showmode={ { "-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)", 3 } }}
+ {1:~ }|*2
+ ]],
+ showmode = { { '-- ^X mode (^]^D^E^F^I^K^L^N^O^Ps^U^V^Y)', 3 } },
+ }
feed('<c-p>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
alphpabet |
alphanum |
alphanum^ |
- {1:~ }|
- {1:~ }|
- ]], popupmenu={
- anchor = { 1, 2, 0 },
- items = { { "alphpabet", "", "", "" }, { "alphanum", "", "", "" } },
- pos = 1
- }, showmode={ { "-- Keyword Local completion (^N^P) ", 3 }, { "match 1 of 2", 4 } }}
+ {1:~ }|*2
+ ]],
+ popupmenu = {
+ anchor = { 1, 2, 0 },
+ items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } },
+ pos = 1,
+ },
+ showmode = { { '-- Keyword Local completion (^N^P) ', 3 }, { 'match 1 of 2', 4 } },
+ }
-- echomsg and showmode don't overwrite each other, this is the same
-- as the TUI behavior with cmdheight=2 or larger.
feed('<f2>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
alphpabet |
alphanum |
alphanum^ |
- {1:~ }|
- {1:~ }|
- ]], popupmenu={
- anchor = { 1, 2, 0 },
- items = { { "alphpabet", "", "", "" }, { "alphanum", "", "", "" } },
- pos = 1
- }, messages={ {
- content = { { "stuff" } },
- kind = "echomsg"
- } }, showmode={ { "-- Keyword Local completion (^N^P) ", 3 }, { "match 1 of 2", 4 } }}
+ {1:~ }|*2
+ ]],
+ popupmenu = {
+ anchor = { 1, 2, 0 },
+ items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } },
+ pos = 1,
+ },
+ messages = { {
+ content = { { 'stuff' } },
+ kind = 'echomsg',
+ } },
+ showmode = { { '-- Keyword Local completion (^N^P) ', 3 }, { 'match 1 of 2', 4 } },
+ }
feed('<c-p>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
alphpabet |
alphanum |
alphpabet^ |
- {1:~ }|
- {1:~ }|
- ]], popupmenu={
- anchor = { 1, 2, 0 },
- items = { { "alphpabet", "", "", "" }, { "alphanum", "", "", "" } },
- pos = 0
- }, messages={ {
- content = { { "stuff" } },
- kind = "echomsg"
- } }, showmode={ { "-- Keyword Local completion (^N^P) ", 3 }, { "match 2 of 2", 4 } }}
-
- feed("<esc>:messages<cr>")
- screen:expect{grid=[[
+ {1:~ }|*2
+ ]],
+ popupmenu = {
+ anchor = { 1, 2, 0 },
+ items = { { 'alphpabet', '', '', '' }, { 'alphanum', '', '', '' } },
+ pos = 0,
+ },
+ messages = { {
+ content = { { 'stuff' } },
+ kind = 'echomsg',
+ } },
+ showmode = { { '-- Keyword Local completion (^N^P) ', 3 }, { 'match 2 of 2', 4 } },
+ }
+
+ feed('<esc>:messages<cr>')
+ screen:expect {
+ grid = [[
alphpabet |
alphanum |
alphpabe^t |
- {1:~ }|
- {1:~ }|
- ]], msg_history={{
- content = {{ "stuff" }},
- kind = "echomsg",
- }}, messages={{
- content = {{ "Press ENTER or type command to continue", 4}},
- kind = "return_prompt"
- }}}
+ {1:~ }|*2
+ ]],
+ msg_history = { {
+ content = { { 'stuff' } },
+ kind = 'echomsg',
+ } },
+ messages = {
+ {
+ content = { { 'Press ENTER or type command to continue', 4 } },
+ kind = 'return_prompt',
+ },
+ },
+ }
end)
it('&showmode with macro-recording message', function()
feed('qq')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={ { "recording @q", 3 } }}
+ {1:~ }|*4
+ ]],
+ showmode = { { 'recording @q', 3 } },
+ }
feed('i')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={ { "-- INSERT --recording @q", 3 } }}
+ {1:~ }|*4
+ ]],
+ showmode = { { '-- INSERT --recording @q', 3 } },
+ }
feed('<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={ { "recording @q", 3 } }}
+ {1:~ }|*4
+ ]],
+ showmode = { { 'recording @q', 3 } },
+ }
feed('q')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]])
end)
it('shows macro-recording message with &noshowmode', function()
- command("set noshowmode")
+ command('set noshowmode')
feed('qq')
-- also check mode to avoid immediate success
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={ { "recording @q", 3 } }, mode="normal"}
+ {1:~ }|*4
+ ]],
+ showmode = { { 'recording @q', 3 } },
+ mode = 'normal',
+ }
feed('i')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={ { "recording @q", 3 } }, mode="insert"}
+ {1:~ }|*4
+ ]],
+ showmode = { { 'recording @q', 3 } },
+ mode = 'insert',
+ }
feed('<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={ { "recording @q", 3 } }, mode="normal"}
+ {1:~ }|*4
+ ]],
+ showmode = { { 'recording @q', 3 } },
+ mode = 'normal',
+ }
feed('q')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], mode="normal"}
+ {1:~ }|*4
+ ]],
+ mode = 'normal',
+ }
end)
it('supports &showcmd and &ruler', function()
command('set showcmd ruler')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], ruler={ { "0,0-1 All" } }}
+ {1:~ }|*4
+ ]],
+ ruler = { { '0,0-1 All' } },
+ }
feed('i')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showmode={ { "-- INSERT --", 3 } }, ruler={ { "0,1 All" } }}
+ {1:~ }|*4
+ ]],
+ showmode = { { '-- INSERT --', 3 } },
+ ruler = { { '0,1 All' } },
+ }
feed('abcde<cr>12345<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
abcde |
1234^5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], ruler={ { "2,5 All" } }}
+ {1:~ }|*3
+ ]],
+ ruler = { { '2,5 All' } },
+ }
feed('d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
abcde |
1234^5 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showcmd={ { "d" } }, ruler={ { "2,5 All" } }}
+ {1:~ }|*3
+ ]],
+ showcmd = { { 'd' } },
+ ruler = { { '2,5 All' } },
+ }
feed('<esc>^')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
abcde |
^12345 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], ruler={ { "2,1 All" } }}
+ {1:~ }|*3
+ ]],
+ ruler = { { '2,1 All' } },
+ }
feed('d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
abcde |
^12345 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showcmd={ { "d" } }, ruler={ { "2,1 All" } }}
+ {1:~ }|*3
+ ]],
+ showcmd = { { 'd' } },
+ ruler = { { '2,1 All' } },
+ }
feed('i')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
abcde |
^12345 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], showcmd={ { "di" } }, ruler={ { "2,1 All" } }}
+ {1:~ }|*3
+ ]],
+ showcmd = { { 'di' } },
+ ruler = { { '2,1 All' } },
+ }
feed('w')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
abcde |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], ruler={ { "2,0-1 All" } }}
+ {1:~ }|*3
+ ]],
+ ruler = { { '2,0-1 All' } },
+ }
-- when ruler is part of statusline it is not externalized.
-- this will be added as part of future ext_statusline support
- command("set laststatus=2")
+ command('set laststatus=2')
screen:expect([[
abcde |
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{6:<o Name] [+] 2,0-1 All}|
]])
end)
it('keeps history of message of different kinds', function()
feed(':echomsg "howdy"<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{ "howdy" }}, kind = "echomsg"}
- }}
+ {1:~ }|*4
+ ]],
+ messages = { {
+ content = { { 'howdy' } },
+ kind = 'echomsg',
+ } },
+ }
-- always test a message without kind. If this one gets promoted to a
-- category, add a new message without kind.
feed('<c-c>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{ "Type :qa and press <Enter> to exit Nvim" }},
- kind = ""}
- }}
+ {1:~ }|*4
+ ]],
+ messages = {
+ {
+ content = { { 'Type :qa and press <Enter> to exit Nvim' } },
+ kind = '',
+ },
+ },
+ }
feed(':echoerr "bork"<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{ "bork", 2 }}, kind = "echoerr"}
- }}
+ {1:~ }|*4
+ ]],
+ messages = { {
+ content = { { 'bork', 2 } },
+ kind = 'echoerr',
+ } },
+ }
feed(':echo "xyz"<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{ "xyz" }}, kind = "echo"}
- }}
+ {1:~ }|*4
+ ]],
+ messages = { {
+ content = { { 'xyz' } },
+ kind = 'echo',
+ } },
+ }
feed(':call nosuchfunction()<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{ "E117: Unknown function: nosuchfunction", 2 }},
- kind = "emsg"}
- }}
+ {1:~ }|*4
+ ]],
+ messages = {
+ {
+ content = { { 'E117: Unknown function: nosuchfunction', 2 } },
+ kind = 'emsg',
+ },
+ },
+ }
feed(':messages<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], msg_history={
- {kind="echomsg", content={{"howdy"}}},
- {kind="", content={{"Type :qa and press <Enter> to exit Nvim"}}},
- {kind="echoerr", content={{"bork", 2}}},
- {kind="emsg", content={{"E117: Unknown function: nosuchfunction", 2}}}
- }, messages={{
- content = {{ "Press ENTER or type command to continue", 4}},
- kind = "return_prompt"
- }}}
+ {1:~ }|*4
+ ]],
+ msg_history = {
+ { kind = 'echomsg', content = { { 'howdy' } } },
+ { kind = '', content = { { 'Type :qa and press <Enter> to exit Nvim' } } },
+ { kind = 'echoerr', content = { { 'bork', 2 } } },
+ { kind = 'emsg', content = { { 'E117: Unknown function: nosuchfunction', 2 } } },
+ },
+ messages = {
+ {
+ content = { { 'Press ENTER or type command to continue', 4 } },
+ kind = 'return_prompt',
+ },
+ },
+ }
end)
it('implies ext_cmdline and ignores cmdheight', function()
eq(0, eval('&cmdheight'))
feed(':set cmdheight=1')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], cmdline={{
- content = { { "set cmdheight=1" } },
- firstc = ":",
- pos = 15 }
- }}
+ {1:~ }|*4
+ ]],
+ cmdline = {
+ {
+ content = { { 'set cmdheight=1' } },
+ firstc = ':',
+ pos = 15,
+ },
+ },
+ }
feed('<cr>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]])
eq(0, eval('&cmdheight'))
feed(':set cmdheight=0')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], cmdline={{
- content = { { "set cmdheight=0" } },
- firstc = ":",
- pos = 15 }
- }}
+ {1:~ }|*4
+ ]],
+ cmdline = {
+ {
+ content = { { 'set cmdheight=0' } },
+ firstc = ':',
+ pos = 15,
+ },
+ },
+ }
feed('<cr>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]])
eq(0, eval('&cmdheight'))
end)
it('supports multiline messages from lua', function()
feed(':lua error("such\\nmultiline\\nerror")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{[[E5108: Error executing lua [string ":lua"]:1: such
+ {1:~ }|*4
+ ]],
+ messages = {
+ {
+ content = {
+ {
+ [[E5108: Error executing lua [string ":lua"]:1: such
multiline
error
stack traceback:
[C]: in function 'error'
- [string ":lua"]:1: in main chunk]], 2}},
- kind = "lua_error",
- }}}
+ [string ":lua"]:1: in main chunk]],
+ 2,
+ },
+ },
+ kind = 'lua_error',
+ },
+ },
+ }
end)
it('supports multiline messages from rpc', function()
feed(':call rpcrequest(1, "test_method")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{"Error invoking 'test_method' on channel 1:\ncomplete\nerror\n\nmessage", 2}},
- kind = "rpc_error"
- }}, request_cb=function (name)
- if name == "test_method" then
- set_method_error("complete\nerror\n\nmessage")
- end
- end}
+ {1:~ }|*4
+ ]],
+ messages = {
+ {
+ content = {
+ { "Error invoking 'test_method' on channel 1:\ncomplete\nerror\n\nmessage", 2 },
+ },
+ kind = 'rpc_error',
+ },
+ },
+ request_cb = function(name)
+ if name == 'test_method' then
+ set_method_error('complete\nerror\n\nmessage')
+ end
+ end,
+ }
end)
it('supports multiline messages for :map', function()
@@ -841,10 +947,18 @@ stack traceback:
command('nnoremap j k')
feed(':map<cr>')
- screen:expect{messages={{
- content = {{ "\nn Q @@\nn Y y$\nn j " }, { "*", 5 }, { " k" }},
- kind = ''
- }}}
+ screen:expect {
+ messages = {
+ {
+ content = {
+ { '\nn Q @@\nn Y y$\nn j ' },
+ { '*', 5 },
+ { ' k' },
+ },
+ kind = '',
+ },
+ },
+ }
end)
it('wildmode=list', function()
@@ -853,23 +967,23 @@ stack traceback:
command('set wildmenu wildmode=list')
feed(':set wildm<tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={{
- content = {{'wildmenu wildmode'}},
+ {1:~ }|*6
+ ]],
+ messages = { {
+ content = { { 'wildmenu wildmode' } },
kind = '',
- }},
- cmdline={{
- firstc = ':',
- content = {{ 'set wildm' }},
- pos = 9,
- }}}
+ } },
+ cmdline = {
+ {
+ firstc = ':',
+ content = { { 'set wildm' } },
+ pos = 9,
+ },
+ },
+ }
end)
it('hides prompt_for_number messages', function()
@@ -877,89 +991,110 @@ stack traceback:
feed('ihelllo<esc>')
feed('z=')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{9:helllo} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{1:^~ }|
- ]], messages={
- {content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\nType number and <Enter> or click with the mouse (q or empty cancels): ' } }, kind = ""}
- }}
+ ]],
+ messages = {
+ {
+ content = {
+ {
+ 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\nType number and <Enter> or click with the mouse (q or empty cancels): ',
+ },
+ },
+ kind = '',
+ },
+ },
+ }
feed('1')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{9:helllo} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{1:^~ }|
- ]], messages={
- {content = { { 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\nType number and <Enter> or click with the mouse (q or empty cancels): ' } }, kind = ""},
- { content = { { "1" } }, kind = "" }
- }}
+ ]],
+ messages = {
+ {
+ content = {
+ {
+ 'Change "helllo" to:\n 1 "Hello"\n 2 "Hallo"\n 3 "Hullo"\nType number and <Enter> or click with the mouse (q or empty cancels): ',
+ },
+ },
+ kind = '',
+ },
+ { content = { { '1' } }, kind = '' },
+ },
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^Hello |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
end)
it('supports nvim_echo messages with multiple attrs', function()
- async_meths.echo({{'wow, ',"Search"}, {"such\n\nvery ", "ErrorMsg"}, {"color", "LineNr"}}, true, {})
- screen:expect{grid=[[
+ async_meths.nvim_echo(
+ { { 'wow, ', 'Search' }, { 'such\n\nvery ', 'ErrorMsg' }, { 'color', 'LineNr' } },
+ true,
+ {}
+ )
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={
- { content = { { "wow, ", 7 }, { "such\n\nvery ", 2 }, { "color", 10 } }, kind = "echomsg" }
- }}
+ {1:~ }|*4
+ ]],
+ messages = {
+ { content = { { 'wow, ', 7 }, { 'such\n\nvery ', 2 }, { 'color', 10 } }, kind = 'echomsg' },
+ },
+ }
feed ':ls<cr>'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={
- { content = { { '\n 1 %a "[No Name]" line 1' } }, kind = "" }
- }}
+ {1:~ }|*4
+ ]],
+ messages = {
+ { content = { { '\n 1 %a "[No Name]" line 1' } }, kind = '' },
+ },
+ }
feed ':messages<cr>'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]], messages={
- { content = { { "Press ENTER or type command to continue", 4 } }, kind = "return_prompt" }
- }, msg_history={
- { content = { { "wow, ", 7 }, { "such\n\nvery ", 2 }, { "color", 10 } }, kind = "echomsg" }
- }}
+ {1:~ }|*4
+ ]],
+ messages = {
+ { content = { { 'Press ENTER or type command to continue', 4 } }, kind = 'return_prompt' },
+ },
+ msg_history = {
+ { content = { { 'wow, ', 7 }, { 'such\n\nvery ', 2 }, { 'color', 10 } }, kind = 'echomsg' },
+ },
+ }
feed '<cr>'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
end)
it('does not truncate messages', function()
- command('write '.. fname)
- screen:expect({messages={
- {content = { { string.format('"%s" [New] 0L, 0B written', fname) } }, kind = "" }
- }})
+ command('write ' .. fname)
+ screen:expect({
+ messages = {
+ { content = { { string.format('"%s" [New] 0L, 0B written', fname) } }, kind = '' },
+ },
+ })
end)
end)
@@ -968,26 +1103,27 @@ describe('ui/builtin messages', function()
before_each(function()
clear()
screen = Screen.new(60, 7)
- screen:attach({rgb=true, ext_popupmenu=true})
- screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Blue1};
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red};
- [3] = {bold = true, reverse = true};
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4};
- [5] = {foreground = Screen.colors.Blue1};
- [6] = {bold = true, foreground = Screen.colors.Magenta};
- [7] = {background = Screen.colors.Grey20};
- [8] = {reverse = true};
- [9] = {background = Screen.colors.LightRed};
- [10] = {background = Screen.colors.Yellow};
- [11] = {foreground = Screen.colors.Brown};
+ screen:attach({ rgb = true, ext_popupmenu = true })
+ screen:set_default_attr_ids {
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = { bold = true, reverse = true },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [5] = { foreground = Screen.colors.Blue1 },
+ [6] = { bold = true, foreground = Screen.colors.Magenta },
+ [7] = { background = Screen.colors.Grey20 },
+ [8] = { reverse = true },
+ [9] = { background = Screen.colors.LightRed },
+ [10] = { background = Screen.colors.Yellow },
+ [11] = { foreground = Screen.colors.Brown },
}
end)
it('supports multiline messages from rpc', function()
feed(':call rpcrequest(1, "test_method")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3: }|
{2:Error invoking 'test_method' on channel 1:} |
{2:complete} |
@@ -995,20 +1131,21 @@ describe('ui/builtin messages', function()
|
{2:message} |
{4:Press ENTER or type command to continue}^ |
- ]], request_cb=function (name)
- if name == "test_method" then
- set_method_error("complete\nerror\n\nmessage")
- end
- end}
+ ]],
+ request_cb = function(name)
+ if name == 'test_method' then
+ set_method_error('complete\nerror\n\nmessage')
+ end
+ end,
+ }
end)
it(':hi Group output', function()
- screen:try_resize(70,7)
+ screen:try_resize(70, 7)
feed(':hi ErrorMsg<cr>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3: }|
:hi ErrorMsg |
ErrorMsg {2:xxx} {5:ctermfg=}15 {5:ctermbg=}1 {5:guifg=}White {5:guibg=}Red |
@@ -1016,7 +1153,7 @@ describe('ui/builtin messages', function()
]])
feed('<cr>')
- screen:try_resize(30,7)
+ screen:try_resize(30, 7)
feed(':hi ErrorMsg<cr>')
screen:expect([[
:hi ErrorMsg |
@@ -1030,14 +1167,13 @@ describe('ui/builtin messages', function()
feed('<cr>')
-- screen size doesn't affect internal output #10285
- eq('ErrorMsg xxx ctermfg=15 ctermbg=1 guifg=White guibg=Red',
- exec_capture("hi ErrorMsg"))
+ eq('ErrorMsg xxx ctermfg=15 ctermbg=1 guifg=White guibg=Red', exec_capture('hi ErrorMsg'))
end)
it(':syntax list langGroup output', function()
- command("syntax on")
- command("set syntax=vim")
- screen:try_resize(110,7)
+ command('syntax on')
+ command('set syntax=vim')
+ screen:try_resize(110, 7)
feed(':syntax list vimComment<cr>')
screen:expect([[
{6:--- Syntax items ---} |
@@ -1050,7 +1186,7 @@ describe('ui/builtin messages', function()
]])
feed('<cr>')
- screen:try_resize(55,7)
+ screen:try_resize(55, 7)
feed(':syntax list vimComment<cr>')
screen:expect([[
|
@@ -1065,12 +1201,14 @@ describe('ui/builtin messages', function()
-- ignore final whitespace inside string
-- luacheck: push ignore
- eq([[--- Syntax items ---
+ eq(
+ [[--- Syntax items ---
vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vimCommentGroup,vimCommentString
match /\<endif\s\+".*$/ms=s+5,lc=5 contains=@vimCommentGroup,vimCommentString
match /\<else\s\+".*$/ms=s+4,lc=4 contains=@vimCommentGroup,vimCommentString
links to Comment]],
- exec_capture('syntax list vimComment'))
+ exec_capture('syntax list vimComment')
+ )
-- luacheck: pop
end)
@@ -1090,103 +1228,91 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
endfunc
]])
feed(':call T1()<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
message T1 |
- ]]}
+ ]],
+ }
feed(':call T2()<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
message T2 |
- ]]}
+ ]],
+ }
feed(':call T3()<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
message T3 |
- ]]}
+ ]],
+ }
end)
it('supports ruler with laststatus=0', function()
- command("set ruler laststatus=0")
- screen:expect{grid=[[
+ command('set ruler laststatus=0')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
0,0-1 All |
- ]]}
+ ]],
+ }
- command("hi MsgArea guibg=#333333")
- screen:expect{grid=[[
+ command('hi MsgArea guibg=#333333')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{7: 0,0-1 All }|
- ]]}
+ ]],
+ }
- command("set rulerformat=%15(%c%V\\ %p%%%)")
- screen:expect{grid=[[
+ command('set rulerformat=%15(%c%V\\ %p%%%)')
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{7: 0,0-1 100% }|
- ]]}
+ ]],
+ }
end)
it('supports echo with CRLF line separators', function()
feed(':echo "line 1\\r\\nline 2"<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3: }|
line 1 |
line 2 |
{4:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed('<cr>:echo "abc\\rz"<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
zbc |
- ]]}
+ ]],
+ }
end)
it('redraws UPD_NOT_VALID correctly after message', function()
-- edge case: only one window was set UPD_NOT_VALID. Original report
-- used :make, but fake it using one command to set the current
-- window UPD_NOT_VALID and another to show a long message.
- command("set more")
+ command('set more')
feed(':new<cr><c-w><c-w>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{8:[No Name] }|
@@ -1194,10 +1320,12 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
{1:~ }|
{3:[No Name] }|
:new |
- ]]}
+ ]],
+ }
feed(':set colorcolumn=10 | digraphs<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
:set colorcolumn=10 | digraphs |
NU {5:^@} 10 SH {5:^A} 1 SX {5:^B} 2 EX {5:^C} 3 |
ET {5:^D} 4 EQ {5:^E} 5 AK {5:^F} 6 BL {5:^G} 7 |
@@ -1205,10 +1333,12 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
FF {5:^L} 12 CR {5:^M} 13 SO {5:^N} 14 SI {5:^O} 15 |
DL {5:^P} 16 D1 {5:^Q} 17 D2 {5:^R} 18 D3 {5:^S} 19 |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('q')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{8:[No Name] }|
@@ -1216,11 +1346,13 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
{1:~ }|
{3:[No Name] }|
|
- ]]}
+ ]],
+ }
-- edge case: just covers statusline
feed(':set colorcolumn=5 | lua error("x\\n\\nx")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:E5108: Error executing lua [string ":lua"]:1: x} |
|
{2:x} |
@@ -1228,10 +1360,12 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
{2: [C]: in function 'error'} |
{2: [string ":lua"]:1: in main chunk} |
{4:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{8:[No Name] }|
@@ -1239,35 +1373,43 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
{1:~ }|
{3:[No Name] }|
|
- ]]}
+ ]],
+ }
-- edge case: just covers lowest window line
feed(':set colorcolumn=5 | lua error("x\\n\\n\\nx")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:E5108: Error executing lua [string ":lua"]:1: x} |
- |
- |
+ |*2
{2:x} |
{2:stack traceback:} |
{2: [C]: in function 'error'} |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('<cr>')
- screen:expect{grid=[[
- |
- |
+ screen:expect {
+ grid = [[
+ |*2
{2:x} |
{2:stack traceback:} |
{2: [C]: in function 'error'} |
{2: [string ":lua"]:1: in main chunk} |
{4:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
it('supports nvim_echo messages with multiple attrs', function()
- async_meths.echo({{'wow, ',"Search"}, {"such\n\nvery ", "ErrorMsg"}, {"color", "LineNr"}}, true, {})
- screen:expect{grid=[[
+ async_meths.nvim_echo(
+ { { 'wow, ', 'Search' }, { 'such\n\nvery ', 'ErrorMsg' }, { 'color', 'LineNr' } },
+ true,
+ {}
+ )
+ screen:expect {
+ grid = [[
|
{1:~ }|
{3: }|
@@ -1275,21 +1417,21 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
|
{2:very }{11:color} |
{4:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed '<cr>'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
- ]]}
+ ]],
+ }
feed ':messages<cr>'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{3: }|
@@ -1297,12 +1439,13 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
|
{2:very }{11:color} |
{4:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
it('prints lines in Ex mode correctly with a burst of carriage returns #19341', function()
command('set number')
- meths.buf_set_lines(0, 0, 0, true, {'aaa', 'bbb', 'ccc'})
+ api.nvim_buf_set_lines(0, 0, 0, true, { 'aaa', 'bbb', 'ccc' })
feed('gggQ<CR><CR>1<CR><CR>vi')
screen:expect([[
Entering Ex mode. Type "visual" to go to Normal mode. |
@@ -1319,8 +1462,7 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
{11: 2 }^bbb |
{11: 3 }ccc |
{11: 4 } |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
end)
@@ -1339,19 +1481,21 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
endfunc
]]):format(to_block))
feed(':call PrintAndWait()<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{3: }|
aaa |
bbb^ |
- ]], timeout=timeout}
+ ]],
+ timeout = timeout,
+ }
if type(to_unblock) == 'string' then
feed(to_unblock)
end
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{3: }|
@@ -1359,7 +1503,8 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
bbb |
ccc |
{4:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end
it('getchar()', function()
@@ -1375,17 +1520,18 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
end)
end)
- it('consecutive calls to win_move_statusline() work after multiline message #21014',function()
- async_meths.exec([[
+ it('consecutive calls to win_move_statusline() work after multiline message #21014', function()
+ async_meths.nvim_exec(
+ [[
echo "\n"
call win_move_statusline(0, -4)
call win_move_statusline(0, 4)
- ]], false)
+ ]],
+ false
+ )
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{3: }|
|
{4:Press ENTER or type command to continue}^ |
@@ -1393,14 +1539,10 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
feed('<CR>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
- eq(1, meths.get_option_value('cmdheight', {}))
+ eq(1, api.nvim_get_option_value('cmdheight', {}))
end)
it('using nvim_echo in VimResized does not cause hit-enter prompt #26139', function()
@@ -1408,12 +1550,27 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
screen:try_resize(60, 5)
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
- eq({ mode = 'n', blocking = false }, meths.get_mode())
+ eq({ mode = 'n', blocking = false }, api.nvim_get_mode())
+ end)
+
+ it('bottom of screen is cleared after increasing &cmdheight #20360', function()
+ command('set laststatus=2')
+ screen:expect([[
+ ^ |
+ {1:~ }|*4
+ {3:[No Name] }|
+ |
+ ]])
+ command('set cmdheight=4')
+ screen:expect([[
+ ^ |
+ {1:~ }|
+ {3:[No Name] }|
+ |*4
+ ]])
end)
end)
@@ -1432,17 +1589,17 @@ describe('ui/ext_messages', function()
local screen
before_each(function()
- clear{args_rm={'--headless'}, args={"--cmd", "set shortmess-=I"}}
+ clear { args_rm = { '--headless' }, args = { '--cmd', 'set shortmess-=I' } }
screen = Screen.new(80, 24)
- screen:attach({rgb=true, ext_messages=true, ext_popupmenu=true})
+ screen:attach({ rgb = true, ext_messages = true, ext_popupmenu = true })
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [3] = {bold = true},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [5] = {foreground = Screen.colors.Blue1},
- [6] = {reverse = true},
- [7] = {bold = true, reverse = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = { bold = true },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [5] = { foreground = Screen.colors.Blue1 },
+ [6] = { reverse = true },
+ [7] = { bold = true, reverse = true },
})
end)
@@ -1451,10 +1608,7 @@ describe('ui/ext_messages', function()
-- Note parts of it depends on version or is indeterministic. We ignore those parts.
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{MATCH:.*}|
{1:~ }|
{1:~ }Nvim is open source and freely distributable{1: }|
@@ -1467,50 +1621,21 @@ describe('ui/ext_messages', function()
{1:~ }|
{1:~{MATCH: +}}type :help news{5:<Enter>} to see changes in v{MATCH:%d+%.%d+}{1:{MATCH: +}}|
{1:~ }|
- {MATCH:.*}|
- {MATCH:.*}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {MATCH:.*}|*2
+ {1:~ }|*5
]])
- feed("<c-l>")
+ feed('<c-l>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*23
]])
- feed(":intro<cr>")
- screen:expect{grid=[[
+ feed(':intro<cr>')
+ screen:expect {
+ grid = [[
^ |
- |
- |
- |
- |
+ |*4
{MATCH:.*}|
|
Nvim is open source and freely distributable |
@@ -1523,116 +1648,68 @@ describe('ui/ext_messages', function()
|
{MATCH: +}type :help news{5:<Enter>} to see changes in v{MATCH:%d+%.%d+ +}|
|
- {MATCH:.*}|
- {MATCH:.*}|
- |
- |
- |
- |
- |
- ]], messages={
- {content = { { "Press ENTER or type command to continue", 4 } }, kind = "return_prompt" }
- }}
+ {MATCH:.*}|*2
+ |*5
+ ]],
+ messages = {
+ { content = { { 'Press ENTER or type command to continue', 4 } }, kind = 'return_prompt' },
+ },
+ }
end)
it('supports global statusline', function()
- feed(":set laststatus=3<cr>")
- feed(":sp<cr>")
- feed(":set cmdheight<cr>")
- screen:expect({grid=[[
+ feed(':set laststatus=3<cr>')
+ feed(':sp<cr>')
+ feed(':set cmdheight<cr>')
+ screen:expect({
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
────────────────────────────────────────────────────────────────────────────────|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
{7:[No Name] }|
- ]], messages={
- {content = { { " cmdheight=0" } }, kind = "" }
- }})
+ ]],
+ messages = {
+ { content = { { ' cmdheight=0' } }, kind = '' },
+ },
+ })
- feed("<c-w>+")
- feed(":set laststatus<cr>")
- screen:expect({grid=[[
+ feed('<c-w>+')
+ feed(':set laststatus<cr>')
+ screen:expect({
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
────────────────────────────────────────────────────────────────────────────────|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*9
{7:[No Name] }|
- ]], messages={
- {content = { { " laststatus=3" } }, kind = "" }
- }})
+ ]],
+ messages = {
+ { content = { { ' laststatus=3' } }, kind = '' },
+ },
+ })
- feed(":set mouse=a<cr>")
- meths.input_mouse('left', 'press', '', 0, 12, 10)
+ feed(':set mouse=a<cr>')
+ api.nvim_input_mouse('left', 'press', '', 0, 12, 10)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 0, 11, 10)
- feed("<c-l>")
- feed(":set cmdheight<cr>")
- screen:expect({grid=[[
+ api.nvim_input_mouse('left', 'drag', '', 0, 11, 10)
+ feed('<c-l>')
+ feed(':set cmdheight<cr>')
+ screen:expect({
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
────────────────────────────────────────────────────────────────────────────────|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
{7:[No Name] }|
- ]], messages={
- {content = { { " cmdheight=0" } }, kind = "" }
- }})
+ ]],
+ messages = {
+ { content = { { ' cmdheight=0' } }, kind = '' },
+ },
+ })
end)
end)
@@ -1640,9 +1717,9 @@ describe('ui/msg_puts_printf', function()
it('output multibyte characters correctly', function()
local screen
local cmd = ''
- local locale_dir = test_build_dir..'/share/locale/ja/LC_MESSAGES'
+ local locale_dir = test_build_dir .. '/share/locale/ja/LC_MESSAGES'
- clear({env={LANG='ja_JP.UTF-8'}})
+ clear({ env = { LANG = 'ja_JP.UTF-8' } })
screen = Screen.new(25, 5)
screen:attach()
@@ -1654,7 +1731,7 @@ describe('ui/msg_puts_printf', function()
cmd = 'chcp 932 > NULL & '
end
else
- if (exc_exec('lang ja_JP.UTF-8') ~= 0) then
+ if exc_exec('lang ja_JP.UTF-8') ~= 0 then
pending('Locale ja_JP.UTF-8 not supported', function() end)
return
elseif is_ci() then
@@ -1664,11 +1741,13 @@ describe('ui/msg_puts_printf', function()
end
end
- os.execute('cmake -E make_directory '..locale_dir)
- os.execute('cmake -E copy '..test_build_dir..'/src/nvim/po/ja.mo '..locale_dir..'/nvim.mo')
+ os.execute('cmake -E make_directory ' .. locale_dir)
+ os.execute(
+ 'cmake -E copy ' .. test_build_dir .. '/src/nvim/po/ja.mo ' .. locale_dir .. '/nvim.mo'
+ )
- cmd = cmd..'"'..nvim_prog..'" -u NONE -i NONE -Es -V1'
- command([[call termopen(']]..cmd..[[')]])
+ cmd = cmd .. '"' .. nvim_prog .. '" -u NONE -i NONE -Es -V1'
+ command([[call termopen(']] .. cmd .. [[')]])
screen:expect([[
^Exモードã«å…¥ã‚Šã¾ã™. ノー |
ãƒžãƒ«ãƒ¢ãƒ¼ãƒ‰ã«æˆ»ã‚‹ã«ã¯"visu|
@@ -1677,7 +1756,7 @@ describe('ui/msg_puts_printf', function()
|
]])
- os.execute('cmake -E remove_directory '..test_build_dir..'/share')
+ os.execute('cmake -E remove_directory ' .. test_build_dir .. '/share')
end)
end)
@@ -1689,92 +1768,108 @@ describe('pager', function()
screen = Screen.new(35, 8)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [3] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red, special=Screen.colors.Yellow},
- [4] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [5] = {special = Screen.colors.Yellow},
- [6] = {special = Screen.colors.Yellow, bold = true, foreground = Screen.colors.SeaGreen4},
- [7] = {foreground = Screen.colors.Grey0, background = Screen.colors.Grey100},
- [8] = {foreground = Screen.colors.Gray90, background = Screen.colors.Grey100},
- [9] = {foreground = tonumber('0x00000c'), background = Screen.colors.Grey100},
- [10] = {background = Screen.colors.Grey100, bold = true, foreground = tonumber('0xe5e5ff')},
- [11] = {background = Screen.colors.Grey100, bold = true, foreground = tonumber ('0x2b8452')},
- [12] = {bold = true, reverse = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [3] = {
+ foreground = Screen.colors.Grey100,
+ background = Screen.colors.Red,
+ special = Screen.colors.Yellow,
+ },
+ [4] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [5] = { special = Screen.colors.Yellow },
+ [6] = { special = Screen.colors.Yellow, bold = true, foreground = Screen.colors.SeaGreen4 },
+ [7] = { foreground = Screen.colors.Grey0, background = Screen.colors.Grey100 },
+ [8] = { foreground = Screen.colors.Gray90, background = Screen.colors.Grey100 },
+ [9] = { foreground = tonumber('0x00000c'), background = Screen.colors.Grey100 },
+ [10] = { background = Screen.colors.Grey100, bold = true, foreground = tonumber('0xe5e5ff') },
+ [11] = { background = Screen.colors.Grey100, bold = true, foreground = tonumber('0x2b8452') },
+ [12] = { bold = true, reverse = true },
})
- command("set more")
+ command('set more')
- exec_lua('_G.x = ...', [[
+ exec_lua(
+ '_G.x = ...',
+ [[
Lorem ipsum dolor sit amet, consectetur
adipisicing elit, sed do eiusmod tempor
incididunt ut labore et dolore magna aliqua.
Ut enim ad minim veniam, quis nostrud xercitation
ullamco laboris nisi ut
-aliquip ex ea commodo consequat.]])
+aliquip ex ea commodo consequat.]]
+ )
end)
it('can be quit with echon', function()
- screen:try_resize(25,5)
+ screen:try_resize(25, 5)
feed(':echon join(map(range(0, &lines*10), "v:val"), "\\n")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
0 |
1 |
2 |
3 |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('q')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
end)
it('can be quit with Lua #11224 #16537', function()
-- NOTE: adds "4" to message history, although not displayed initially
-- (triggered the more prompt).
- screen:try_resize(40,5)
+ screen:try_resize(40, 5)
feed(':lua for i=0,10 do print(i) end<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
0 |
1 |
2 |
3 |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('q')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
feed(':mess<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
0 |
1 |
2 |
3 |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
1 |
2 |
3 |
4 |
{4:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed('<cr>')
end)
it('handles wrapped lines with line scroll', function()
feed(':lua error(_G.x)<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:E5108: Error executing lua [string }|
{2:":lua"]:1: Lorem ipsum dolor sit am}|
{2:et, consectetur} |
@@ -1783,10 +1878,12 @@ aliquip ex ea commodo consequat.]])
{2:incididunt ut labore et dolore magn}|
{2:a aliqua.} |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:":lua"]:1: Lorem ipsum dolor sit am}|
{2:et, consectetur} |
{2:adipisicing elit, sed do eiusmod te}|
@@ -1795,10 +1892,12 @@ aliquip ex ea commodo consequat.]])
{2:a aliqua.} |
{2:Ut enim ad minim veniam, quis nostr}|
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('k')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:E5108: Error executing lua [string }|
{2:":lua"]:1: Lorem ipsum dolor sit am}|
{2:et, consectetur} |
@@ -1807,10 +1906,12 @@ aliquip ex ea commodo consequat.]])
{2:incididunt ut labore et dolore magn}|
{2:a aliqua.} |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:":lua"]:1: Lorem ipsum dolor sit am}|
{2:et, consectetur} |
{2:adipisicing elit, sed do eiusmod te}|
@@ -1819,12 +1920,14 @@ aliquip ex ea commodo consequat.]])
{2:a aliqua.} |
{2:Ut enim ad minim veniam, quis nostr}|
{4:-- More --}^ |
- ]]}
+ ]],
+ }
end)
it('handles wrapped lines with page scroll', function()
feed(':lua error(_G.x)<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:E5108: Error executing lua [string }|
{2:":lua"]:1: Lorem ipsum dolor sit am}|
{2:et, consectetur} |
@@ -1833,9 +1936,11 @@ aliquip ex ea commodo consequat.]])
{2:incididunt ut labore et dolore magn}|
{2:a aliqua.} |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:mpor} |
{2:incididunt ut labore et dolore magn}|
{2:a aliqua.} |
@@ -1844,9 +1949,11 @@ aliquip ex ea commodo consequat.]])
{2:ullamco laboris nisi ut} |
{2:aliquip ex ea commodo consequat.} |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('u')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:E5108: Error executing lua [string }|
{2:":lua"]:1: Lorem ipsum dolor sit am}|
{2:et, consectetur} |
@@ -1855,9 +1962,11 @@ aliquip ex ea commodo consequat.]])
{2:incididunt ut labore et dolore magn}|
{2:a aliqua.} |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:mpor} |
{2:incididunt ut labore et dolore magn}|
{2:a aliqua.} |
@@ -1866,14 +1975,16 @@ aliquip ex ea commodo consequat.]])
{2:ullamco laboris nisi ut} |
{2:aliquip ex ea commodo consequat.} |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
end)
it('handles wrapped lines with line scroll and MsgArea highlight', function()
- command("hi MsgArea guisp=Yellow")
+ command('hi MsgArea guisp=Yellow')
feed(':lua error(_G.x)<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:E5108: Error executing lua [string }|
{3:":lua"]:1: Lorem ipsum dolor sit am}|
{3:et, consectetur}{5: }|
@@ -1882,10 +1993,12 @@ aliquip ex ea commodo consequat.]])
{3:incididunt ut labore et dolore magn}|
{3:a aliqua.}{5: }|
{6:-- More --}{5:^ }|
- ]]}
+ ]],
+ }
feed('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:":lua"]:1: Lorem ipsum dolor sit am}|
{3:et, consectetur}{5: }|
{3:adipisicing elit, sed do eiusmod te}|
@@ -1894,10 +2007,12 @@ aliquip ex ea commodo consequat.]])
{3:a aliqua.}{5: }|
{3:Ut enim ad minim veniam, quis nostr}|
{6:-- More --}{5:^ }|
- ]]}
+ ]],
+ }
feed('k')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:E5108: Error executing lua [string }|
{3:":lua"]:1: Lorem ipsum dolor sit am}|
{3:et, consectetur}{5: }|
@@ -1906,10 +2021,12 @@ aliquip ex ea commodo consequat.]])
{3:incididunt ut labore et dolore magn}|
{3:a aliqua.}{5: }|
{6:-- More --}{5:^ }|
- ]]}
+ ]],
+ }
feed('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:":lua"]:1: Lorem ipsum dolor sit am}|
{3:et, consectetur}{5: }|
{3:adipisicing elit, sed do eiusmod te}|
@@ -1918,13 +2035,15 @@ aliquip ex ea commodo consequat.]])
{3:a aliqua.}{5: }|
{3:Ut enim ad minim veniam, quis nostr}|
{6:-- More --}{5:^ }|
- ]]}
+ ]],
+ }
end)
it('handles wrapped lines with page scroll and MsgArea highlight', function()
- command("hi MsgArea guisp=Yellow")
+ command('hi MsgArea guisp=Yellow')
feed(':lua error(_G.x)<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:E5108: Error executing lua [string }|
{3:":lua"]:1: Lorem ipsum dolor sit am}|
{3:et, consectetur}{5: }|
@@ -1933,9 +2052,11 @@ aliquip ex ea commodo consequat.]])
{3:incididunt ut labore et dolore magn}|
{3:a aliqua.}{5: }|
{6:-- More --}{5:^ }|
- ]]}
+ ]],
+ }
feed('d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:mpor}{5: }|
{3:incididunt ut labore et dolore magn}|
{3:a aliqua.}{5: }|
@@ -1944,9 +2065,11 @@ aliquip ex ea commodo consequat.]])
{3:ullamco laboris nisi ut}{5: }|
{3:aliquip ex ea commodo consequat.}{5: }|
{6:-- More --}{5:^ }|
- ]]}
+ ]],
+ }
feed('u')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:E5108: Error executing lua [string }|
{3:":lua"]:1: Lorem ipsum dolor sit am}|
{3:et, consectetur}{5: }|
@@ -1955,9 +2078,11 @@ aliquip ex ea commodo consequat.]])
{3:incididunt ut labore et dolore magn}|
{3:a aliqua.}{5: }|
{6:-- More --}{5:^ }|
- ]]}
+ ]],
+ }
feed('d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{3:mpor}{5: }|
{3:incididunt ut labore et dolore magn}|
{3:a aliqua.}{5: }|
@@ -1966,52 +2091,60 @@ aliquip ex ea commodo consequat.]])
{3:ullamco laboris nisi ut}{5: }|
{3:aliquip ex ea commodo consequat.}{5: }|
{6:-- More --}{5:^ }|
- ]]}
+ ]],
+ }
end)
it('preserves MsgArea highlighting after more prompt', function()
- screen:try_resize(70,6)
- command("hi MsgArea guisp=Yellow")
- command("map x Lorem ipsum labore et dolore magna aliqua")
- command("map y adipisicing elit")
- command("map z incididunt ut")
- command("map a labore et dolore")
- command("map b ex ea commodo")
- command("map xx yy")
- command("map xy yz")
+ screen:try_resize(70, 6)
+ command('hi MsgArea guisp=Yellow')
+ command('map x Lorem ipsum labore et dolore magna aliqua')
+ command('map y adipisicing elit')
+ command('map z incididunt ut')
+ command('map a labore et dolore')
+ command('map b ex ea commodo')
+ command('map xx yy')
+ command('map xy yz')
feed(':map<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{5: a labore et dolore }|
{5: b ex ea commodo }|
{5: xy yz }|
{5: xx yy }|
{5: x Lorem ipsum labore et dolore magna aliqua }|
{6:-- More --}{5:^ }|
- ]]}
+ ]],
+ }
feed('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{5: b ex ea commodo }|
{5: xy yz }|
{5: xx yy }|
{5: x Lorem ipsum labore et dolore magna aliqua }|
{5: y adipisicing elit }|
{6:-- More --}{5:^ }|
- ]]}
+ ]],
+ }
feed('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{5: xy yz }|
{5: xx yy }|
{5: x Lorem ipsum labore et dolore magna aliqua }|
{5: y adipisicing elit }|
{5: z incididunt ut }|
{6:Press ENTER or type command to continue}{5:^ }|
- ]]}
+ ]],
+ }
end)
it('clears "-- more --" message', function()
- command("hi MsgArea guisp=Yellow blend=10")
+ command('hi MsgArea guisp=Yellow blend=10')
feed(':echon join(range(20), "\\n")<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{7:0}{8: }|
{9:1}{10: }|
{9:2}{10: }|
@@ -2020,10 +2153,12 @@ aliquip ex ea commodo consequat.]])
{9:5}{10: }|
{9:6}{10: }|
{11:--}{8: }{11:More}{8: }{11:--}{8:^ }|
- ]]}
+ ]],
+ }
feed('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{7:1}{8: }|
{9:2}{10: }|
{9:3}{10: }|
@@ -2032,10 +2167,12 @@ aliquip ex ea commodo consequat.]])
{9:6}{10: }|
{9:7}{10: }|
{11:--}{8: }{11:More}{8: }{11:--}{8:^ }|
- ]]}
+ ]],
+ }
feed('k')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{7:0}{8: }|
{9:1}{10: }|
{9:2}{10: }|
@@ -2044,10 +2181,12 @@ aliquip ex ea commodo consequat.]])
{9:5}{10: }|
{9:6}{10: }|
{11:--}{8: }{11:More}{8: }{11:--}{8:^ }|
- ]]}
+ ]],
+ }
feed('j')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{7:1}{8: }|
{9:2}{10: }|
{9:3}{10: }|
@@ -2056,52 +2195,54 @@ aliquip ex ea commodo consequat.]])
{9:6}{10: }|
{9:7}{10: }|
{11:--}{8: }{11:More}{8: }{11:--}{8:^ }|
- ]]}
+ ]],
+ }
end)
it('with :!cmd does not crash on resize', function()
- skip(funcs.executable('sleep') == 0, 'missing "sleep" command')
+ skip(fn.executable('sleep') == 0, 'missing "sleep" command')
feed(':!sleep 1<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{12: }|
:!sleep 1 |
|
- ]]}
+ ]],
+ }
-- not processed while command is executing
- async_meths.ui_try_resize(35, 5)
+ async_meths.nvim_ui_try_resize(35, 5)
-- TODO(bfredl): ideally it should be processed just
-- before the "press ENTER" prompt though
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{12: }|
:!sleep 1 |
|
{4:Press ENTER or type command to cont}|
{4:inue}^ |
- ]]}
+ ]],
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
- ]]}
+ ]],
+ }
end)
it('can be resized', function()
feed(':lua error(_G.x)<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:E5108: Error executing lua [string }|
{2:":lua"]:1: Lorem ipsum dolor sit am}|
{2:et, consectetur} |
@@ -2110,22 +2251,26 @@ aliquip ex ea commodo consequat.]])
{2:incididunt ut labore et dolore magn}|
{2:a aliqua.} |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
-- responds to resize, but text is not reflown
screen:try_resize(45, 5)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:adipisicing elit, sed do eiusmod te} |
{2:mpor} |
{2:incididunt ut labore et dolore magn} |
{2:a aliqua.} |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
-- can create empty space, as the command hasn't output the text below yet.
-- text is not reflown; existing lines get cut
screen:try_resize(30, 12)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
:lua error(_G.x) |
{2:E5108: Error executing lua [st}|
{2:":lua"]:1: Lorem ipsum dolor s}|
@@ -2134,16 +2279,16 @@ aliquip ex ea commodo consequat.]])
{2:mpore} |
{2:incididunt ut labore et dolore}|
{2:a aliqua.} |
- |
- |
- |
+ |*3
{4:-- More --}^ |
- ]]}
+ ]],
+ }
-- continues in a mostly consistent state, but only new lines are
-- wrapped at the new screen size.
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:E5108: Error executing lua [st}|
{2:":lua"]:1: Lorem ipsum dolor s}|
{2:et, consectetur} |
@@ -2156,10 +2301,12 @@ aliquip ex ea commodo consequat.]])
{2:ullamco laboris nisi ut} |
{2:aliquip ex ea commodo consequa}|
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{2:":lua"]:1: Lorem ipsum dolor s}|
{2:et, consectetur} |
{2:adipisicing elit, sed do eiusm}|
@@ -2172,29 +2319,24 @@ aliquip ex ea commodo consequat.]])
{2:aliquip ex ea commodo consequa}|
{2:t.} |
{4:-- More --}^ |
- ]]}
+ ]],
+ }
feed('q')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
|
- ]]}
+ ]],
+ }
end)
it('with cmdheight=0 does not crash with g<', function()
command('set cmdheight=0')
feed(':ls<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{12: }|
@@ -2203,22 +2345,20 @@ aliquip ex ea commodo consequat.]])
line 1 |
{4:Press ENTER or type command to cont}|
{4:inue}^ |
- ]]}
+ ]],
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*7
+ ]],
+ }
feed('g<lt>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{12: }|
@@ -2227,18 +2367,15 @@ aliquip ex ea commodo consequat.]])
line 1 |
{4:Press ENTER or type command to cont}|
{4:inue}^ |
- ]]}
+ ]],
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*7
+ ]],
+ }
end)
end)
diff --git a/test/functional/ui/mode_spec.lua b/test/functional/ui/mode_spec.lua
index e870d6f25f..8d7fae3e91 100644
--- a/test/functional/ui/mode_spec.lua
+++ b/test/functional/ui/mode_spec.lua
@@ -11,39 +11,45 @@ describe('ui mode_change event', function()
before_each(function()
clear()
screen = Screen.new(25, 4)
- screen:attach({rgb= true})
- screen:set_default_attr_ids( {
- [0] = {bold=true, foreground=255},
- [1] = {bold=true, reverse=true},
- [2] = {bold=true},
- [3] = {reverse=true},
- [4] = {background=Screen.colors.Red, foreground=Screen.colors.White}, -- ErrorMsg
+ screen:attach({ rgb = true })
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = 255 },
+ [1] = { bold = true, reverse = true },
+ [2] = { bold = true },
+ [3] = { reverse = true },
+ [4] = { background = Screen.colors.Red, foreground = Screen.colors.White }, -- ErrorMsg
})
end)
it('works in normal mode', function()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], mode="normal"}
+ ]],
+ mode = 'normal',
+ }
feed('d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], mode="operator"}
+ ]],
+ mode = 'operator',
+ }
feed('<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], mode="normal"}
+ ]],
+ mode = 'normal',
+ }
end)
-- oldtest: Test_mouse_shape_after_failed_change()
@@ -52,185 +58,226 @@ describe('ui mode_change event', function()
command('set nomodifiable')
feed('c')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], mode="operator"}
+ ]],
+ mode = 'operator',
+ }
feed('c')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{4:E21: Cannot make changes, 'modifiable' is off} |
- ]], mode="normal"}
+ ]],
+ mode = 'normal',
+ }
end)
-- oldtest: Test_mouse_shape_after_cancelling_gr()
it('is restored to Normal mode after cancelling "gr"', function()
feed('gr')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], mode="replace"}
+ ]],
+ mode = 'replace',
+ }
feed('<Esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], mode="normal"}
+ ]],
+ mode = 'normal',
+ }
end)
it('works in insert mode', function()
feed('i')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:-- INSERT --} |
- ]], mode="insert"}
+ ]],
+ mode = 'insert',
+ }
feed('word<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
wor^d |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], mode="normal"}
+ ]],
+ mode = 'normal',
+ }
local matchtime = 0
- command("set showmatch")
+ command('set showmatch')
retry(nil, nil, function()
matchtime = matchtime + 1
- local screen_timeout = 1000 * matchtime -- fail faster for retry.
+ local screen_timeout = 1000 * matchtime -- fail faster for retry.
- command("set matchtime=" .. matchtime) -- tenths of seconds
+ command('set matchtime=' .. matchtime) -- tenths of seconds
feed('a(stuff')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
word(stuff^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:-- INSERT --} |
- ]], mode="insert", timeout=screen_timeout}
+ ]],
+ mode = 'insert',
+ timeout = screen_timeout,
+ }
feed(')')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
word^(stuff) |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:-- INSERT --} |
- ]], mode="showmatch", timeout=screen_timeout}
+ ]],
+ mode = 'showmatch',
+ timeout = screen_timeout,
+ }
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
word(stuff)^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:-- INSERT --} |
- ]], mode="insert", timeout=screen_timeout}
+ ]],
+ mode = 'insert',
+ timeout = screen_timeout,
+ }
end)
end)
it('works in replace mode', function()
feed('R')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:-- REPLACE --} |
- ]], mode="replace"}
+ ]],
+ mode = 'replace',
+ }
feed('word<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
wor^d |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], mode="normal"}
+ ]],
+ mode = 'normal',
+ }
end)
it('works in cmdline mode', function()
feed(':')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:^ |
- ]], mode="cmdline_normal"}
+ ]],
+ mode = 'cmdline_normal',
+ }
feed('x<left>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:^x |
- ]], mode="cmdline_insert"}
+ ]],
+ mode = 'cmdline_insert',
+ }
feed('<insert>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:^x |
- ]], mode="cmdline_replace"}
-
+ ]],
+ mode = 'cmdline_replace',
+ }
feed('<right>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:x^ |
- ]], mode="cmdline_normal"}
+ ]],
+ mode = 'cmdline_normal',
+ }
feed('<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], mode="normal"}
+ ]],
+ mode = 'normal',
+ }
end)
it('works in visual mode', function()
- insert("text")
+ insert('text')
feed('v')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
tex^t |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:-- VISUAL --} |
- ]], mode="visual"}
+ ]],
+ mode = 'visual',
+ }
feed('<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
tex^t |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], mode="normal"}
+ ]],
+ mode = 'normal',
+ }
command('set selection=exclusive')
feed('v')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
tex^t |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:-- VISUAL --} |
- ]], mode="visual_select"}
+ ]],
+ mode = 'visual_select',
+ }
feed('<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
tex^t |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], mode="normal"}
+ ]],
+ mode = 'normal',
+ }
end)
end)
-
diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua
index 1356ba3db8..0f30bf4471 100644
--- a/test/functional/ui/mouse_spec.lua
+++ b/test/functional/ui/mouse_spec.lua
@@ -1,8 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths
+local clear, feed, api = helpers.clear, helpers.feed, helpers.api
local insert, feed_command = helpers.insert, helpers.feed_command
-local eq, funcs = helpers.eq, helpers.funcs
+local eq, fn = helpers.eq, helpers.fn
local poke_eventloop = helpers.poke_eventloop
local command = helpers.command
local exec = helpers.exec
@@ -12,8 +12,8 @@ describe('ui/mouse/input', function()
before_each(function()
clear()
- meths.set_option_value('mouse', 'a', {})
- meths.set_option_value('list', true, {})
+ api.nvim_set_option_value('mouse', 'a', {})
+ api.nvim_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:$')
@@ -21,21 +21,21 @@ describe('ui/mouse/input', function()
screen = Screen.new(25, 5)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {background = Screen.colors.LightGrey},
- [2] = {bold = true},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black },
+ [2] = { bold = true },
[3] = {
foreground = Screen.colors.Blue,
background = Screen.colors.LightGrey,
bold = true,
},
- [4] = {reverse = true},
- [5] = {bold = true, reverse = true},
- [6] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [7] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [8] = {foreground = Screen.colors.Brown},
+ [4] = { reverse = true },
+ [5] = { bold = true, reverse = true },
+ [6] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [7] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [8] = { foreground = Screen.colors.Brown },
})
- command("set mousemodel=extend")
+ command('set mousemodel=extend')
feed('itesting<cr>mouse<cr>support and selection<esc>')
screen:expect([[
testing |
@@ -48,13 +48,16 @@ describe('ui/mouse/input', function()
it('single left click moves cursor', function()
feed('<LeftMouse><2,1>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
testing |
mo^use |
support and selection |
{0:~ }|
|
- ]], mouse_enabled=true}
+ ]],
+ mouse_enabled = true,
+ }
feed('<LeftMouse><0,0>')
screen:expect([[
^testing |
@@ -66,15 +69,18 @@ describe('ui/mouse/input', function()
end)
it("in external ui works with unset 'mouse'", function()
- meths.set_option_value('mouse', '', {})
+ api.nvim_set_option_value('mouse', '', {})
feed('<LeftMouse><2,1>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
testing |
mo^use |
support and selection |
{0:~ }|
|
- ]], mouse_enabled=false}
+ ]],
+ mouse_enabled = false,
+ }
feed('<LeftMouse><0,0>')
screen:expect([[
^testing |
@@ -135,11 +141,11 @@ describe('ui/mouse/input', function()
describe('tab drag', function()
before_each(function()
- screen:set_default_attr_ids( {
- [0] = {bold=true, foreground=Screen.colors.Blue},
- tab = { background=Screen.colors.LightGrey, underline=true },
- sel = { bold=true },
- fill = { reverse=true }
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ tab = { background = Screen.colors.LightGrey, underline = true },
+ sel = { bold = true },
+ fill = { reverse = true },
})
end)
@@ -151,24 +157,21 @@ describe('ui/mouse/input', function()
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftMouse><4,0>')
screen:expect([[
{sel: + foo }{tab: + bar }{fill: }{tab:X}|
this is fo^o |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftDrag><14,0>')
screen:expect([[
{tab: + bar }{sel: + foo }{fill: }{tab:X}|
this is fo^o |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
@@ -181,24 +184,27 @@ describe('ui/mouse/input', function()
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftMouse><11,0>')
- screen:expect{grid=[[
+ -- Prevent the case where screen:expect() with "unchanged" returns too early,
+ -- causing the click position to be overwritten by the next drag.
+ poke_eventloop()
+ screen:expect {
+ grid = [[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
feed('<LeftDrag><6,0>')
screen:expect([[
{sel: + bar }{tab: + foo }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
@@ -211,24 +217,21 @@ describe('ui/mouse/input', function()
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftMouse><4,0>')
screen:expect([[
{sel: + foo }{tab: + bar }{fill: }{tab:X}|
this is fo^o |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftDrag><7,0>')
screen:expect([[
{tab: + bar }{sel: + foo }{fill: }{tab:X}|
this is fo^o |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
@@ -241,32 +244,31 @@ describe('ui/mouse/input', function()
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftMouse><4,0>')
screen:expect([[
{sel: + foo }{tab: + bar }{fill: }{tab:X}|
this is fo^o |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftDrag><4,1>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{sel: + foo }{tab: + bar }{fill: }{tab:X}|
this is fo^o |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
feed('<LeftDrag><14,1>')
screen:expect([[
{tab: + bar }{sel: + foo }{fill: }{tab:X}|
this is fo^o |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
@@ -279,32 +281,37 @@ describe('ui/mouse/input', function()
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftMouse><11,0>')
- screen:expect{grid=[[
+ -- Prevent the case where screen:expect() with "unchanged" returns too early,
+ -- causing the click position to be overwritten by the next drag.
+ poke_eventloop()
+ screen:expect {
+ grid = [[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
feed('<LeftDrag><11,1>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
feed('<LeftDrag><6,1>')
screen:expect([[
{sel: + bar }{tab: + foo }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
@@ -317,32 +324,31 @@ describe('ui/mouse/input', function()
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftMouse><4,0>')
screen:expect([[
{sel: + foo }{tab: + bar }{fill: }{tab:X}|
this is fo^o |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftDrag><4,1>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{sel: + foo }{tab: + bar }{fill: }{tab:X}|
this is fo^o |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
feed('<LeftDrag><7,1>')
screen:expect([[
{tab: + bar }{sel: + foo }{fill: }{tab:X}|
this is fo^o |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
@@ -350,11 +356,11 @@ describe('ui/mouse/input', function()
describe('tabline', function()
before_each(function()
- screen:set_default_attr_ids( {
- [0] = {bold=true, foreground=Screen.colors.Blue},
- tab = { background=Screen.colors.LightGrey, underline=true },
- sel = { bold=true },
- fill = { reverse=true }
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ tab = { background = Screen.colors.LightGrey, underline = true },
+ sel = { bold = true },
+ fill = { reverse = true },
})
end)
@@ -366,22 +372,20 @@ describe('ui/mouse/input', function()
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftMouse><4,0>')
screen:expect([[
{sel: + foo }{tab: + bar }{fill: }{tab:X}|
this is fo^o |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
it('left click in default tabline (position 24) closes tab', function()
- meths.set_option_value('hidden', true, {})
+ api.nvim_set_option_value('hidden', true, {})
feed_command('%delete')
insert('this is foo')
feed_command('silent file foo | tabnew | file bar')
@@ -389,22 +393,19 @@ describe('ui/mouse/input', function()
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<LeftMouse><24,0>')
screen:expect([[
this is fo^o |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
end)
it('double click in default tabline (position 4) opens new tab', function()
- meths.set_option_value('hidden', true, {})
+ api.nvim_set_option_value('hidden', true, {})
feed_command('%delete')
insert('this is foo')
feed_command('silent file foo | tabnew | file bar')
@@ -412,16 +413,14 @@ describe('ui/mouse/input', function()
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
this is ba^r{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<2-LeftMouse><4,0>')
screen:expect([[
{sel: Name] }{tab: + foo + bar }{fill: }{tab:X}|
{0:^$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
@@ -439,8 +438,8 @@ describe('ui/mouse/input', function()
return call('Test', a:000 + [2])
endfunction
]])
- meths.set_option_value('tabline', '%@Test@test%X-%5@Test2@test2', {})
- meths.set_option_value('showtabline', 2, {})
+ api.nvim_set_option_value('tabline', '%@Test@test%X-%5@Test2@test2', {})
+ api.nvim_set_option_value('showtabline', 2, {})
screen:expect([[
{fill:test-test2 }|
testing |
@@ -448,59 +447,65 @@ describe('ui/mouse/input', function()
support and selectio^n |
|
]])
- meths.set_var('reply', {})
+ api.nvim_set_var('reply', {})
end)
local check_reply = function(expected)
- eq(expected, meths.get_var('reply'))
- meths.set_var('reply', {})
+ eq(expected, api.nvim_get_var('reply'))
+ api.nvim_set_var('reply', {})
end
- local test_click = function(name, click_str, click_num, mouse_button,
- modifiers)
-
+ local test_click = function(name, click_str, click_num, mouse_button, modifiers)
local function doit(do_click)
- eq(1, funcs.has('tablineat'))
- do_click(0,3)
- check_reply({0, click_num, mouse_button, modifiers})
- do_click(0,4)
+ eq(1, fn.has('tablineat'))
+ do_click(0, 3)
+ check_reply({ 0, click_num, mouse_button, modifiers })
+ do_click(0, 4)
check_reply({})
- do_click(0,6)
- check_reply({5, click_num, mouse_button, modifiers, 2})
- do_click(0,13)
- check_reply({5, click_num, mouse_button, modifiers, 2})
+ do_click(0, 6)
+ check_reply({ 5, click_num, mouse_button, modifiers, 2 })
+ do_click(0, 13)
+ check_reply({ 5, click_num, mouse_button, modifiers, 2 })
end
it(name .. ' works (pseudokey)', function()
- doit(function (row,col)
- feed(click_str .. '<' .. col .. ',' .. row .. '>')
+ doit(function(row, col)
+ feed(click_str .. '<' .. col .. ',' .. row .. '>')
end)
end)
it(name .. ' works (nvim_input_mouse)', function()
- doit(function (row,col)
- local buttons = {l='left',m='middle',r='right'}
+ doit(function(row, col)
+ local buttons = { l = 'left', m = 'middle', r = 'right' }
local modstr = (click_num > 1) and tostring(click_num) or ''
for char in string.gmatch(modifiers, '%w') do
modstr = modstr .. char .. '-' -- - not needed but should be accepted
end
- meths.input_mouse(buttons[mouse_button], 'press', modstr, 0, row, col)
+ api.nvim_input_mouse(buttons[mouse_button], 'press', modstr, 0, row, col)
end)
end)
end
test_click('single left click', '<LeftMouse>', 1, 'l', ' ')
test_click('shifted single left click', '<S-LeftMouse>', 1, 'l', 's ')
- test_click('shifted single left click with alt modifier',
- '<S-A-LeftMouse>', 1, 'l', 's a ')
- test_click('shifted single left click with alt and ctrl modifiers',
- '<S-C-A-LeftMouse>', 1, 'l', 'sca ')
+ test_click('shifted single left click with alt modifier', '<S-A-LeftMouse>', 1, 'l', 's a ')
+ test_click(
+ 'shifted single left click with alt and ctrl modifiers',
+ '<S-C-A-LeftMouse>',
+ 1,
+ 'l',
+ 'sca '
+ )
-- <C-RightMouse> does not work
- test_click('shifted single right click with alt modifier',
- '<S-A-RightMouse>', 1, 'r', 's a ')
+ test_click('shifted single right click with alt modifier', '<S-A-RightMouse>', 1, 'r', 's a ')
-- Modifiers do not work with MiddleMouse
- test_click('shifted single middle click with alt and ctrl modifiers',
- '<MiddleMouse>', 1, 'm', ' ')
+ test_click(
+ 'shifted single middle click with alt and ctrl modifiers',
+ '<MiddleMouse>',
+ 1,
+ 'm',
+ ' '
+ )
-- Modifiers do not work with N-*Mouse
test_click('double left click', '<2-LeftMouse>', 2, 'l', ' ')
test_click('triple left click', '<3-LeftMouse>', 3, 'l', ' ')
@@ -552,15 +557,15 @@ describe('ui/mouse/input', function()
it('left drag changes visual selection after tab click', function()
screen:set_default_attr_ids({
- [0] = {bold=true, foreground=Screen.colors.Blue},
- tab = { background=Screen.colors.LightGrey, underline=true },
- sel = { bold=true },
- fill = { reverse=true },
- vis = { background=Screen.colors.LightGrey }
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ tab = { background = Screen.colors.LightGrey, underline = true },
+ sel = { bold = true },
+ fill = { reverse = true },
+ vis = { background = Screen.colors.LightGrey, foreground = Screen.colors.Black },
})
feed_command('silent file foo | tabnew | file bar')
insert('this is bar')
- feed_command('tabprevious') -- go to first tab
+ feed_command('tabprevious') -- go to first tab
screen:expect([[
{sel: + foo }{tab: + bar }{fill: }{tab:X}|
testing |
@@ -568,28 +573,26 @@ describe('ui/mouse/input', function()
support and selectio^n |
:tabprevious |
]])
- feed('<LeftMouse><10,0><LeftRelease>') -- go to second tab
+ feed('<LeftMouse><10,0><LeftRelease>') -- go to second tab
helpers.poke_eventloop()
feed('<LeftMouse><0,1>')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
^this is bar{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
:tabprevious |
]])
feed('<LeftDrag><4,1>')
screen:expect([[
{tab: + foo }{sel: + bar }{fill: }{tab:X}|
{vis:this}^ is bar{0:$} |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{sel:-- VISUAL --} |
]])
end)
it('left drag changes visual selection in split layout', function()
- screen:try_resize(53,14)
+ screen:try_resize(53, 14)
command('set mouse=a')
command('vsplit')
command('wincmd l')
@@ -597,58 +600,52 @@ describe('ui/mouse/input', function()
command('enew')
feed('ifoo\nbar<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
testing │testing |
mouse │mouse |
support and selection │support and selection |
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
+ {0:~ }│{0:~ }|*2
{0:~ }│{4:[No Name] [+] }|
{0:~ }│foo{0:$} |
{0:~ }│ba^r{0:$} |
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
+ {0:~ }│{0:~ }|*4
{4:[No Name] [+] }{5:[No Name] [+] }|
|
- ]]}
+ ]],
+ }
- meths.input_mouse('left', 'press', '', 0, 6, 27)
- screen:expect{grid=[[
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 27)
+ screen:expect {
+ grid = [[
testing │testing |
mouse │mouse |
support and selection │support and selection |
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
+ {0:~ }│{0:~ }|*2
{0:~ }│{4:[No Name] [+] }|
{0:~ }│^foo{0:$} |
{0:~ }│bar{0:$} |
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
+ {0:~ }│{0:~ }|*4
{4:[No Name] [+] }{5:[No Name] [+] }|
|
- ]]}
- meths.input_mouse('left', 'drag', '', 0, 7, 30)
+ ]],
+ }
+ api.nvim_input_mouse('left', 'drag', '', 0, 7, 30)
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
testing │testing |
mouse │mouse |
support and selection │support and selection |
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
+ {0:~ }│{0:~ }|*2
{0:~ }│{4:[No Name] [+] }|
{0:~ }│{1:foo}{3:$} |
{0:~ }│{1:bar}{0:^$} |
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
+ {0:~ }│{0:~ }|*4
{4:[No Name] [+] }{5:[No Name] [+] }|
{2:-- VISUAL --} |
- ]]}
+ ]],
+ }
end)
it('two clicks will enter VISUAL and dragging selects words', function()
@@ -788,7 +785,7 @@ describe('ui/mouse/input', function()
end)
it('ctrl + left click will search for a tag', function()
- meths.set_option_value('tags', './non-existent-tags-file', {})
+ api.nvim_set_option_value('tags', './non-existent-tags-file', {})
feed('<C-LeftMouse><0,0>')
screen:expect([[
{6:E433: No tags file} |
@@ -800,10 +797,29 @@ describe('ui/mouse/input', function()
feed('<cr>')
end)
+ it('x1 and x2 can be triggered by api', function()
+ api.nvim_set_var('x1_pressed', 0)
+ api.nvim_set_var('x1_released', 0)
+ api.nvim_set_var('x2_pressed', 0)
+ api.nvim_set_var('x2_released', 0)
+ command('nnoremap <X1Mouse> <Cmd>let g:x1_pressed += 1<CR>')
+ command('nnoremap <X1Release> <Cmd>let g:x1_released += 1<CR>')
+ command('nnoremap <X2Mouse> <Cmd>let g:x2_pressed += 1<CR>')
+ command('nnoremap <X2Release> <Cmd>let g:x2_released += 1<CR>')
+ api.nvim_input_mouse('x1', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('x1', 'release', '', 0, 0, 0)
+ api.nvim_input_mouse('x2', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('x2', 'release', '', 0, 0, 0)
+ eq(1, api.nvim_get_var('x1_pressed'), 'x1 pressed once')
+ eq(1, api.nvim_get_var('x1_released'), 'x1 released once')
+ eq(1, api.nvim_get_var('x2_pressed'), 'x2 pressed once')
+ eq(1, api.nvim_get_var('x2_released'), 'x2 released once')
+ end)
+
it('dragging vertical separator', function()
screen:try_resize(45, 5)
command('setlocal nowrap')
- local oldwin = meths.get_current_win().id
+ local oldwin = api.nvim_get_current_win()
command('rightbelow vnew')
screen:expect([[
testing │{0:^$} |
@@ -812,9 +828,9 @@ describe('ui/mouse/input', function()
{4:[No Name] [+] }{5:[No Name] }|
|
]])
- meths.input_mouse('left', 'press', '', 0, 0, 22)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 22)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 0, 1, 12)
+ api.nvim_input_mouse('left', 'drag', '', 0, 1, 12)
screen:expect([[
testing │{0:^$} |
mouse │{0:~ }|
@@ -822,7 +838,7 @@ describe('ui/mouse/input', function()
{4:< Name] [+] }{5:[No Name] }|
|
]])
- meths.input_mouse('left', 'drag', '', 0, 2, 2)
+ api.nvim_input_mouse('left', 'drag', '', 0, 2, 2)
screen:expect([[
te│{0:^$} |
mo│{0:~ }|
@@ -830,18 +846,17 @@ describe('ui/mouse/input', function()
{4:< }{5:[No Name] }|
|
]])
- meths.input_mouse('left', 'release', '', 0, 2, 2)
- meths.set_option_value('statuscolumn', 'foobar', { win = oldwin })
+ api.nvim_input_mouse('left', 'release', '', 0, 2, 2)
+ api.nvim_set_option_value('statuscolumn', 'foobar', { win = oldwin })
screen:expect([[
{8:fo}│{0:^$} |
- {8:fo}│{0:~ }|
- {8:fo}│{0:~ }|
+ {8:fo}│{0:~ }|*2
{4:< }{5:[No Name] }|
|
]])
- meths.input_mouse('left', 'press', '', 0, 0, 2)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 2)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 0, 1, 12)
+ api.nvim_input_mouse('left', 'drag', '', 0, 1, 12)
screen:expect([[
{8:foobar}testin│{0:^$} |
{8:foobar}mouse │{0:~ }|
@@ -849,7 +864,7 @@ describe('ui/mouse/input', function()
{4:< Name] [+] }{5:[No Name] }|
|
]])
- meths.input_mouse('left', 'drag', '', 0, 2, 22)
+ api.nvim_input_mouse('left', 'drag', '', 0, 2, 22)
screen:expect([[
{8:foobar}testing │{0:^$} |
{8:foobar}mouse │{0:~ }|
@@ -857,7 +872,7 @@ describe('ui/mouse/input', function()
{4:[No Name] [+] }{5:[No Name] }|
|
]])
- meths.input_mouse('left', 'release', '', 0, 2, 22)
+ api.nvim_input_mouse('left', 'release', '', 0, 2, 22)
end)
local function wheel(use_api)
@@ -892,7 +907,7 @@ describe('ui/mouse/input', function()
:vsp |
]])
if use_api then
- meths.input_mouse('wheel', 'down', '', 0, 0, 0)
+ api.nvim_input_mouse('wheel', 'down', '', 0, 0, 0)
else
feed('<ScrollWheelDown><0,0>')
end
@@ -913,7 +928,7 @@ describe('ui/mouse/input', function()
:vsp |
]])
if use_api then
- meths.input_mouse('wheel', 'up', '', 0, 0, 27)
+ api.nvim_input_mouse('wheel', 'up', '', 0, 0, 27)
else
feed('<ScrollWheelUp><27,0>')
end
@@ -934,8 +949,8 @@ describe('ui/mouse/input', function()
:vsp |
]])
if use_api then
- meths.input_mouse('wheel', 'up', '', 0, 7, 27)
- meths.input_mouse('wheel', 'up', '', 0, 7, 27)
+ api.nvim_input_mouse('wheel', 'up', '', 0, 7, 27)
+ api.nvim_input_mouse('wheel', 'up', '', 0, 7, 27)
else
feed('<ScrollWheelUp><27,7><ScrollWheelUp>')
end
@@ -967,27 +982,25 @@ describe('ui/mouse/input', function()
it('horizontal scrolling (pseudokey)', function()
command('set sidescroll=0')
- feed("<esc>:set nowrap<cr>")
+ feed('<esc>:set nowrap<cr>')
- feed("a <esc>20Ab<esc>")
+ feed('a <esc>20Ab<esc>')
screen:expect([[
- |
- |
+ |*2
bbbbbbbbbbbbbbb^b |
{0:~ }|
|
]])
- feed("<ScrollWheelLeft><0,0>")
+ feed('<ScrollWheelLeft><0,0>')
screen:expect([[
- |
- |
+ |*2
n bbbbbbbbbbbbbbbbbbb^b |
{0:~ }|
|
]])
- feed("^<ScrollWheelRight><0,0>")
+ feed('^<ScrollWheelRight><0,0>')
screen:expect([[
g |
|
@@ -999,28 +1012,26 @@ describe('ui/mouse/input', function()
it('horizontal scrolling (nvim_input_mouse)', function()
command('set sidescroll=0')
- feed("<esc>:set nowrap<cr>")
+ feed('<esc>:set nowrap<cr>')
- feed("a <esc>20Ab<esc>")
+ feed('a <esc>20Ab<esc>')
screen:expect([[
- |
- |
+ |*2
bbbbbbbbbbbbbbb^b |
{0:~ }|
|
]])
- meths.input_mouse('wheel', 'left', '', 0, 0, 27)
+ api.nvim_input_mouse('wheel', 'left', '', 0, 0, 27)
screen:expect([[
- |
- |
+ |*2
n bbbbbbbbbbbbbbbbbbb^b |
{0:~ }|
|
]])
- feed("^")
- meths.input_mouse('wheel', 'right', '', 0, 0, 0)
+ feed('^')
+ api.nvim_input_mouse('wheel', 'right', '', 0, 0, 0)
screen:expect([[
g |
|
@@ -1034,7 +1045,7 @@ describe('ui/mouse/input', function()
command('set nowrap')
command('set sidescrolloff=4')
- feed("I <esc>020ib<esc>0")
+ feed('I <esc>020ib<esc>0')
screen:expect([[
testing |
mouse |
@@ -1043,7 +1054,7 @@ describe('ui/mouse/input', function()
|
]])
- meths.input_mouse('wheel', 'right', '', 0, 0, 27)
+ api.nvim_input_mouse('wheel', 'right', '', 0, 0, 27)
screen:expect([[
g |
|
@@ -1063,7 +1074,7 @@ describe('ui/mouse/input', function()
|
]])
- meths.input_mouse('wheel', 'right', '', 0, 0, 27)
+ api.nvim_input_mouse('wheel', 'right', '', 0, 0, 27)
screen:expect([[
g |
|
@@ -1083,8 +1094,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c: X } {0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1094,8 +1104,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c: X } {0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1105,8 +1114,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c: X } {0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1116,8 +1124,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} {c: }t2{c: } {c: }t^3{c: } {c: }|
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c: X } {0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1127,8 +1134,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
{c:^>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c: X } {0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1138,8 +1144,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
{c:>} ç§ã¯^猫ãŒå¤§å¥½ã{0:>---}{c: X } {0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1149,11 +1154,9 @@ describe('ui/mouse/input', function()
{0:>--->--->---} {c: }t2{c: } {c: }t3{c: } {c: }|
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c: ^X } {0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
-
end) -- level 1 - non wrapped
it('(level 1) click on wrapped lines', function()
@@ -1166,8 +1169,7 @@ describe('ui/mouse/input', function()
t4{c: } |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c: X} |
{c: } ✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><0,2>')
@@ -1177,8 +1179,7 @@ describe('ui/mouse/input', function()
^t4{c: } |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c: X} |
{c: } ✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><8,3>')
@@ -1188,8 +1189,7 @@ describe('ui/mouse/input', function()
t4{c: } |
{c:>} ç§ã¯çŒ«^ãŒå¤§å¥½ã{0:>---}{c: X} |
{c: } ✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><21,3>')
@@ -1199,8 +1199,7 @@ describe('ui/mouse/input', function()
t4{c: } |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c: ^X} |
{c: } ✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><4,4>')
@@ -1210,12 +1209,10 @@ describe('ui/mouse/input', function()
t4{c: } |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c: X} |
{c: } ✨^ðŸˆâœ¨ |
- |
- |
+ |*2
]])
end) -- level 1 - wrapped
-
it('(level 2) click on non-wrapped lines', function()
feed_command('let &conceallevel=2', 'echo')
@@ -1225,8 +1222,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} t2 t3 t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1236,8 +1232,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} ^t2 t3 t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1247,19 +1242,17 @@ describe('ui/mouse/input', function()
{0:>--->--->---} t2 t^3 t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
- feed('<esc><LeftMouse><0,2>') -- Weirdness
+ feed('<esc><LeftMouse><0,2>') -- Weirdness
screen:expect([[
Section{0:>>--->--->---}t1 |
{0:>--->--->---} t2 t3 t4 |
{c:^>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1269,8 +1262,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} t2 t3 t4 |
{c:>} ç§ã¯çŒ«^ãŒå¤§å¥½ã{0:>---}{c:X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1280,8 +1272,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} t2 t3 t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:^X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end) -- level 2 - non wrapped
@@ -1295,8 +1286,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} t2 t3 t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{sm:-- INSERT --} |
]])
@@ -1306,8 +1296,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} ^t2 t3 t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{sm:-- INSERT --} |
]])
@@ -1317,19 +1306,17 @@ describe('ui/mouse/input', function()
{0:>--->--->---} t2 t^3 t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{sm:-- INSERT --} |
]])
- feed('<LeftMouse><0,2>') -- Weirdness
+ feed('<LeftMouse><0,2>') -- Weirdness
screen:expect([[
Section{0:>>--->--->---}t1 |
{0:>--->--->---} t2 t3 t4 |
{c:^>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{sm:-- INSERT --} |
]])
@@ -1339,8 +1326,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} t2 t3 t4 |
{c:>} ç§ã¯çŒ«^ãŒå¤§å¥½ã{0:>---}{c:X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{sm:-- INSERT --} |
]])
@@ -1350,8 +1336,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} t2 t3 t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:^X} ✨{0:>}|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{sm:-- INSERT --} |
]])
end) -- level 2 - non wrapped (insert mode)
@@ -1366,8 +1351,7 @@ describe('ui/mouse/input', function()
t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><14,1>')
@@ -1377,8 +1361,7 @@ describe('ui/mouse/input', function()
t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><18,1>')
@@ -1388,8 +1371,7 @@ describe('ui/mouse/input', function()
t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
-- NOTE: The click would ideally be on the 't' in 't4', but wrapping
@@ -1405,8 +1387,7 @@ describe('ui/mouse/input', function()
t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><1,2>')
@@ -1416,8 +1397,7 @@ describe('ui/mouse/input', function()
t^4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><0,3>')
@@ -1427,8 +1407,7 @@ describe('ui/mouse/input', function()
t4 |
{c:^>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><20,3>')
@@ -1438,8 +1417,7 @@ describe('ui/mouse/input', function()
t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:^X} |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><1,4>')
@@ -1449,8 +1427,7 @@ describe('ui/mouse/input', function()
t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} |
^✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><5,4>')
@@ -1460,8 +1437,7 @@ describe('ui/mouse/input', function()
t4 |
{c:>} ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>---}{c:X} |
✨ðŸˆ^✨ |
- |
- |
+ |*2
]])
end) -- level 2 - wrapped
@@ -1474,8 +1450,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} t2 t3 t4 |
^ ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>----} ✨ðŸˆ|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1485,8 +1460,7 @@ describe('ui/mouse/input', function()
{0:>--->--->---} t2 t3 t4 |
^ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>----} ✨ðŸˆ|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
@@ -1496,20 +1470,18 @@ describe('ui/mouse/input', function()
{0:>--->--->---} t2 t3 t4 |
ç§ã¯çŒ«ãŒå¤§å¥½^ã{0:>----} ✨ðŸˆ|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
feed('<esc><LeftMouse><20,2>')
- feed('zH') -- FIXME: unnecessary horizontal scrolling
+ feed('zH') -- FIXME: unnecessary horizontal scrolling
screen:expect([[
Section{0:>>--->--->---}t1 |
{0:>--->--->---} t2 t3 t4 |
ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>----}^ ✨ðŸˆ|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end) -- level 3 - non wrapped
@@ -1524,8 +1496,7 @@ describe('ui/mouse/input', function()
t4 |
ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>----} |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><18,1>')
@@ -1535,8 +1506,7 @@ describe('ui/mouse/input', function()
t4 |
ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>----} |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><1,2>')
@@ -1546,8 +1516,7 @@ describe('ui/mouse/input', function()
t^4 |
ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>----} |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><0,3>')
@@ -1557,8 +1526,7 @@ describe('ui/mouse/input', function()
t4 |
^ ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>----} |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><20,3>')
@@ -1568,8 +1536,7 @@ describe('ui/mouse/input', function()
t4 |
ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>----}^ |
✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><1,4>')
@@ -1579,8 +1546,7 @@ describe('ui/mouse/input', function()
t4 |
ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>----} |
^✨ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><3,4>')
@@ -1590,8 +1556,7 @@ describe('ui/mouse/input', function()
t4 |
ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>----} |
✨^ðŸˆâœ¨ |
- |
- |
+ |*2
]])
feed('<esc><LeftMouse><5,4>')
@@ -1601,10 +1566,8 @@ describe('ui/mouse/input', function()
t4 |
ç§ã¯çŒ«ãŒå¤§å¥½ã{0:>----} |
✨ðŸˆ^✨ |
- |
- |
+ |*2
]])
-
end) -- level 3 - wrapped
end
@@ -1648,66 +1611,65 @@ describe('ui/mouse/input', function()
describe('(matchadd())', function()
before_each(function()
- funcs.matchadd('Conceal', [[\*]])
- funcs.matchadd('Conceal', [[cats]], 10, -1, { conceal = 'X' })
- funcs.matchadd('Conceal', [[\n\@<=x]], 10, -1, { conceal = '>' })
+ fn.matchadd('Conceal', [[\*]])
+ fn.matchadd('Conceal', [[cats]], 10, -1, { conceal = 'X' })
+ fn.matchadd('Conceal', [[\n\@<=x]], 10, -1, { conceal = '>' })
end)
test_mouse_click_conceal()
end)
describe('(extmarks)', function()
before_each(function()
- local ns = meths.create_namespace('conceal')
- meths.buf_set_extmark(0, ns, 0, 11, { end_col = 12, conceal = '' })
- meths.buf_set_extmark(0, ns, 0, 14, { end_col = 15, conceal = '' })
- meths.buf_set_extmark(0, ns, 1, 5, { end_col = 6, conceal = '' })
- meths.buf_set_extmark(0, ns, 1, 8, { end_col = 9, conceal = '' })
- meths.buf_set_extmark(0, ns, 1, 10, { end_col = 11, conceal = '' })
- meths.buf_set_extmark(0, ns, 1, 13, { end_col = 14, conceal = '' })
- meths.buf_set_extmark(0, ns, 1, 15, { end_col = 16, conceal = '' })
- meths.buf_set_extmark(0, ns, 1, 18, { end_col = 19, conceal = '' })
- meths.buf_set_extmark(0, ns, 2, 24, { end_col = 25, conceal = '' })
- meths.buf_set_extmark(0, ns, 2, 29, { end_col = 30, conceal = '' })
- meths.buf_set_extmark(0, ns, 2, 25, { end_col = 29, conceal = 'X' })
- meths.buf_set_extmark(0, ns, 2, 0, { end_col = 1, conceal = '>' })
+ local ns = api.nvim_create_namespace('conceal')
+ api.nvim_buf_set_extmark(0, ns, 0, 11, { end_col = 12, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 0, 14, { end_col = 15, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 5, { end_col = 6, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 8, { end_col = 9, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 10, { end_col = 11, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 13, { end_col = 14, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 15, { end_col = 16, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 1, 18, { end_col = 19, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 2, 24, { end_col = 25, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 2, 29, { end_col = 30, conceal = '' })
+ api.nvim_buf_set_extmark(0, ns, 2, 25, { end_col = 29, conceal = 'X' })
+ api.nvim_buf_set_extmark(0, ns, 2, 0, { end_col = 1, conceal = '>' })
end)
test_mouse_click_conceal()
end)
-
end)
it('getmousepos() works correctly', function()
- local winwidth = meths.get_option_value('winwidth', {})
+ local winwidth = api.nvim_get_option_value('winwidth', {})
-- Set winwidth=1 so that window sizes don't change.
- meths.set_option_value('winwidth', 1, {})
+ api.nvim_set_option_value('winwidth', 1, {})
command('tabedit')
- local tabpage = meths.get_current_tabpage()
+ local tabpage = api.nvim_get_current_tabpage()
insert('hello')
command('vsplit')
local opts = {
- relative='editor',
- width=12,
- height=1,
- col=8,
- row=1,
- anchor='NW',
- style='minimal',
- border='single',
- focusable=1
+ relative = 'editor',
+ width = 12,
+ height = 1,
+ col = 8,
+ row = 1,
+ anchor = 'NW',
+ style = 'minimal',
+ border = 'single',
+ focusable = 1,
}
- local float = meths.open_win(meths.get_current_buf(), false, opts)
+ local float = api.nvim_open_win(api.nvim_get_current_buf(), false, opts)
command('redraw')
- local lines = meths.get_option_value('lines', {})
- local columns = meths.get_option_value('columns', {})
+ local lines = api.nvim_get_option_value('lines', {})
+ local columns = api.nvim_get_option_value('columns', {})
-- Test that screenrow and screencol are set properly for all positions.
for row = 0, lines - 1 do
for col = 0, columns - 1 do
-- Skip the X button that would close the tab.
if row ~= 0 or col ~= columns - 1 then
- meths.input_mouse('left', 'press', '', 0, row, col)
- meths.set_current_tabpage(tabpage)
- local mousepos = funcs.getmousepos()
+ api.nvim_input_mouse('left', 'press', '', 0, row, col)
+ api.nvim_set_current_tabpage(tabpage)
+ local mousepos = fn.getmousepos()
eq(row + 1, mousepos.screenrow)
eq(col + 1, mousepos.screencol)
-- All other values should be 0 when clicking on the command line.
@@ -1730,20 +1692,24 @@ describe('ui/mouse/input', function()
for win_col = 0, opts.width + 1 do
local row = win_row + opts.row
local col = win_col + opts.col
- meths.input_mouse('left', 'press', '', 0, row, col)
- local mousepos = funcs.getmousepos()
- eq(float.id, mousepos.winid)
+ api.nvim_input_mouse('left', 'press', '', 0, row, col)
+ local mousepos = fn.getmousepos()
+ eq(float, mousepos.winid)
eq(win_row + 1, mousepos.winrow)
eq(win_col + 1, mousepos.wincol)
local line = 0
local column = 0
local coladd = 0
- if win_row > 0 and win_row < opts.height + 1
- and win_col > 0 and win_col < opts.width + 1 then
+ if
+ win_row > 0
+ and win_row < opts.height + 1
+ and win_col > 0
+ and win_col < opts.width + 1
+ then
-- Because of border, win_row and win_col don't need to be
-- incremented by 1.
- line = math.min(win_row, funcs.line('$'))
- column = math.min(win_col, #funcs.getline(line) + 1)
+ line = math.min(win_row, fn.line('$'))
+ column = math.min(win_col, #fn.getline(line) + 1)
coladd = win_col - column
end
eq(line, mousepos.line)
@@ -1755,19 +1721,19 @@ describe('ui/mouse/input', function()
-- Test that mouse position values are properly set for the floating
-- window, after removing the border.
opts.border = 'none'
- meths.win_set_config(float, opts)
+ api.nvim_win_set_config(float, opts)
command('redraw')
for win_row = 0, opts.height - 1 do
for win_col = 0, opts.width - 1 do
local row = win_row + opts.row
local col = win_col + opts.col
- meths.input_mouse('left', 'press', '', 0, row, col)
- local mousepos = funcs.getmousepos()
- eq(float.id, mousepos.winid)
+ api.nvim_input_mouse('left', 'press', '', 0, row, col)
+ local mousepos = fn.getmousepos()
+ eq(float, mousepos.winid)
eq(win_row + 1, mousepos.winrow)
eq(win_col + 1, mousepos.wincol)
- local line = math.min(win_row + 1, funcs.line('$'))
- local column = math.min(win_col + 1, #funcs.getline(line) + 1)
+ local line = math.min(win_row + 1, fn.line('$'))
+ local column = math.min(win_col + 1, #fn.getline(line) + 1)
local coladd = win_col + 1 - column
eq(line, mousepos.line)
eq(column, mousepos.column)
@@ -1780,20 +1746,20 @@ describe('ui/mouse/input', function()
-- that getmousepos() does not consider unfocusable floats. (see discussion
-- in PR #14937 for details).
opts.focusable = false
- meths.win_set_config(float, opts)
+ api.nvim_win_set_config(float, opts)
command('redraw')
for nr = 1, 2 do
- for win_row = 0, funcs.winheight(nr) - 1 do
- for win_col = 0, funcs.winwidth(nr) - 1 do
- local row = win_row + funcs.win_screenpos(nr)[1] - 1
- local col = win_col + funcs.win_screenpos(nr)[2] - 1
- meths.input_mouse('left', 'press', '', 0, row, col)
- local mousepos = funcs.getmousepos()
- eq(funcs.win_getid(nr), mousepos.winid)
+ for win_row = 0, fn.winheight(nr) - 1 do
+ for win_col = 0, fn.winwidth(nr) - 1 do
+ local row = win_row + fn.win_screenpos(nr)[1] - 1
+ local col = win_col + fn.win_screenpos(nr)[2] - 1
+ api.nvim_input_mouse('left', 'press', '', 0, row, col)
+ local mousepos = fn.getmousepos()
+ eq(fn.win_getid(nr), mousepos.winid)
eq(win_row + 1, mousepos.winrow)
eq(win_col + 1, mousepos.wincol)
- local line = math.min(win_row + 1, funcs.line('$'))
- local column = math.min(win_col + 1, #funcs.getline(line) + 1)
+ local line = math.min(win_row + 1, fn.line('$'))
+ local column = math.min(win_col + 1, #fn.getline(line) + 1)
local coladd = win_col + 1 - column
eq(line, mousepos.line)
eq(column, mousepos.column)
@@ -1804,34 +1770,34 @@ describe('ui/mouse/input', function()
-- Restore state and release mouse.
command('tabclose!')
- meths.set_option_value('winwidth', winwidth, {})
- meths.input_mouse('left', 'release', '', 0, 0, 0)
+ api.nvim_set_option_value('winwidth', winwidth, {})
+ api.nvim_input_mouse('left', 'release', '', 0, 0, 0)
end)
it('scroll keys are not translated into multiclicks and can be mapped #6211 #6989', function()
- meths.set_var('mouse_up', 0)
- meths.set_var('mouse_up2', 0)
+ api.nvim_set_var('mouse_up', 0)
+ api.nvim_set_var('mouse_up2', 0)
command('nnoremap <ScrollWheelUp> <Cmd>let g:mouse_up += 1<CR>')
command('nnoremap <2-ScrollWheelUp> <Cmd>let g:mouse_up2 += 1<CR>')
feed('<ScrollWheelUp><0,0>')
feed('<ScrollWheelUp><0,0>')
- meths.input_mouse('wheel', 'up', '', 0, 0, 0)
- meths.input_mouse('wheel', 'up', '', 0, 0, 0)
- eq(4, meths.get_var('mouse_up'))
- eq(0, meths.get_var('mouse_up2'))
+ api.nvim_input_mouse('wheel', 'up', '', 0, 0, 0)
+ api.nvim_input_mouse('wheel', 'up', '', 0, 0, 0)
+ eq(4, api.nvim_get_var('mouse_up'))
+ eq(0, api.nvim_get_var('mouse_up2'))
end)
it('<MouseMove> is not translated into multiclicks and can be mapped', function()
- meths.set_var('mouse_move', 0)
- meths.set_var('mouse_move2', 0)
+ api.nvim_set_var('mouse_move', 0)
+ api.nvim_set_var('mouse_move2', 0)
command('nnoremap <MouseMove> <Cmd>let g:mouse_move += 1<CR>')
command('nnoremap <2-MouseMove> <Cmd>let g:mouse_move2 += 1<CR>')
feed('<MouseMove><0,0>')
feed('<MouseMove><0,0>')
- meths.input_mouse('move', '', '', 0, 0, 0)
- meths.input_mouse('move', '', '', 0, 0, 0)
- eq(4, meths.get_var('mouse_move'))
- eq(0, meths.get_var('mouse_move2'))
+ api.nvim_input_mouse('move', '', '', 0, 0, 0)
+ api.nvim_input_mouse('move', '', '', 0, 0, 0)
+ eq(4, api.nvim_get_var('mouse_move'))
+ eq(0, api.nvim_get_var('mouse_move2'))
end)
it('feeding <MouseMove> in Normal mode does not use uninitialized memory #19480', function()
@@ -1858,127 +1824,127 @@ describe('ui/mouse/input', function()
vmenu PopUp.baz y:<C-U>let g:menustr = 'baz'<CR>
]])
- meths.win_set_cursor(0, {1, 0})
- meths.input_mouse('right', 'press', '', 0, 0, 4)
- meths.input_mouse('right', 'release', '', 0, 0, 4)
+ api.nvim_win_set_cursor(0, { 1, 0 })
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 4)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 4)
feed('<Down><Down><CR>')
- eq('bar', meths.get_var('menustr'))
- eq({1, 4}, meths.win_get_cursor(0))
+ eq('bar', api.nvim_get_var('menustr'))
+ eq({ 1, 4 }, api.nvim_win_get_cursor(0))
-- Test for right click in visual mode inside the selection
- funcs.setreg('"', '')
- meths.win_set_cursor(0, {1, 9})
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 9 })
feed('vee')
- meths.input_mouse('right', 'press', '', 0, 0, 11)
- meths.input_mouse('right', 'release', '', 0, 0, 11)
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 11)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 11)
feed('<Down><CR>')
- eq({1, 9}, meths.win_get_cursor(0))
- eq('ran away', funcs.getreg('"'))
+ eq({ 1, 9 }, api.nvim_win_get_cursor(0))
+ eq('ran away', fn.getreg('"'))
-- Test for right click in visual mode right before the selection
- funcs.setreg('"', '')
- meths.win_set_cursor(0, {1, 9})
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 9 })
feed('vee')
- meths.input_mouse('right', 'press', '', 0, 0, 8)
- meths.input_mouse('right', 'release', '', 0, 0, 8)
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 8)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 8)
feed('<Down><CR>')
- eq({1, 8}, meths.win_get_cursor(0))
- eq('', funcs.getreg('"'))
+ eq({ 1, 8 }, api.nvim_win_get_cursor(0))
+ eq('', fn.getreg('"'))
-- Test for right click in visual mode right after the selection
- funcs.setreg('"', '')
- meths.win_set_cursor(0, {1, 9})
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 9 })
feed('vee')
- meths.input_mouse('right', 'press', '', 0, 0, 17)
- meths.input_mouse('right', 'release', '', 0, 0, 17)
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 17)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 17)
feed('<Down><CR>')
- eq({1, 17}, meths.win_get_cursor(0))
- eq('', funcs.getreg('"'))
+ eq({ 1, 17 }, api.nvim_win_get_cursor(0))
+ eq('', fn.getreg('"'))
-- Test for right click in block-wise visual mode inside the selection
- funcs.setreg('"', '')
- meths.win_set_cursor(0, {1, 15})
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 15 })
feed('<C-V>j3l')
- meths.input_mouse('right', 'press', '', 0, 1, 16)
- meths.input_mouse('right', 'release', '', 0, 1, 16)
+ api.nvim_input_mouse('right', 'press', '', 0, 1, 16)
+ api.nvim_input_mouse('right', 'release', '', 0, 1, 16)
feed('<Down><CR>')
- eq({1, 15}, meths.win_get_cursor(0))
- eq('\0224', funcs.getregtype('"'))
+ eq({ 1, 15 }, api.nvim_win_get_cursor(0))
+ eq('\0224', fn.getregtype('"'))
-- Test for right click in block-wise visual mode outside the selection
- funcs.setreg('"', '')
- meths.win_set_cursor(0, {1, 15})
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 15 })
feed('<C-V>j3l')
- meths.input_mouse('right', 'press', '', 0, 1, 1)
- meths.input_mouse('right', 'release', '', 0, 1, 1)
+ api.nvim_input_mouse('right', 'press', '', 0, 1, 1)
+ api.nvim_input_mouse('right', 'release', '', 0, 1, 1)
feed('<Down><CR>')
- eq({2, 1}, meths.win_get_cursor(0))
- eq('v', funcs.getregtype('"'))
- eq('', funcs.getreg('"'))
+ eq({ 2, 1 }, api.nvim_win_get_cursor(0))
+ eq('v', fn.getregtype('"'))
+ eq('', fn.getreg('"'))
-- Test for right click in line-wise visual mode inside the selection
- funcs.setreg('"', '')
- meths.win_set_cursor(0, {1, 15})
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 15 })
feed('V')
- meths.input_mouse('right', 'press', '', 0, 0, 9)
- meths.input_mouse('right', 'release', '', 0, 0, 9)
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 9)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 9)
feed('<Down><CR>')
- eq({1, 0}, meths.win_get_cursor(0)) -- After yanking, the cursor goes to 1,1
- eq('V', funcs.getregtype('"'))
- eq(1, #funcs.getreg('"', 1, true))
+ eq({ 1, 0 }, api.nvim_win_get_cursor(0)) -- After yanking, the cursor goes to 1,1
+ eq('V', fn.getregtype('"'))
+ eq(1, #fn.getreg('"', 1, true))
-- Test for right click in multi-line line-wise visual mode inside the selection
- funcs.setreg('"', '')
- meths.win_set_cursor(0, {1, 15})
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 15 })
feed('Vj')
- meths.input_mouse('right', 'press', '', 0, 1, 19)
- meths.input_mouse('right', 'release', '', 0, 1, 19)
+ api.nvim_input_mouse('right', 'press', '', 0, 1, 19)
+ api.nvim_input_mouse('right', 'release', '', 0, 1, 19)
feed('<Down><CR>')
- eq({1, 0}, meths.win_get_cursor(0)) -- After yanking, the cursor goes to 1,1
- eq('V', funcs.getregtype('"'))
- eq(2, #funcs.getreg('"', 1, true))
+ eq({ 1, 0 }, api.nvim_win_get_cursor(0)) -- After yanking, the cursor goes to 1,1
+ eq('V', fn.getregtype('"'))
+ eq(2, #fn.getreg('"', 1, true))
-- Test for right click in line-wise visual mode outside the selection
- funcs.setreg('"', '')
- meths.win_set_cursor(0, {1, 15})
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 15 })
feed('V')
- meths.input_mouse('right', 'press', '', 0, 1, 9)
- meths.input_mouse('right', 'release', '', 0, 1, 9)
+ api.nvim_input_mouse('right', 'press', '', 0, 1, 9)
+ api.nvim_input_mouse('right', 'release', '', 0, 1, 9)
feed('<Down><CR>')
- eq({2, 9}, meths.win_get_cursor(0))
- eq('', funcs.getreg('"'))
+ eq({ 2, 9 }, api.nvim_win_get_cursor(0))
+ eq('', fn.getreg('"'))
-- Try clicking outside the window
- funcs.setreg('"', '')
- meths.win_set_cursor(0, {2, 1})
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 2, 1 })
feed('vee')
- meths.input_mouse('right', 'press', '', 0, 6, 1)
- meths.input_mouse('right', 'release', '', 0, 6, 1)
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 1)
+ api.nvim_input_mouse('right', 'release', '', 0, 6, 1)
feed('<Down><CR>')
- eq(2, funcs.winnr())
- eq('', funcs.getreg('"'))
+ eq(2, fn.winnr())
+ eq('', fn.getreg('"'))
-- Test for right click in visual mode inside the selection with vertical splits
command('wincmd t')
command('rightbelow vsplit')
- funcs.setreg('"', '')
- meths.win_set_cursor(0, {1, 9})
+ fn.setreg('"', '')
+ api.nvim_win_set_cursor(0, { 1, 9 })
feed('vee')
- meths.input_mouse('right', 'press', '', 0, 0, 52)
- meths.input_mouse('right', 'release', '', 0, 0, 52)
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 52)
+ api.nvim_input_mouse('right', 'release', '', 0, 0, 52)
feed('<Down><CR>')
- eq({1, 9}, meths.win_get_cursor(0))
- eq('ran away', funcs.getreg('"'))
+ eq({ 1, 9 }, api.nvim_win_get_cursor(0))
+ eq('ran away', fn.getreg('"'))
-- Test for right click inside visual selection at bottom of window with winbar
command('setlocal winbar=WINBAR')
feed('2yyP')
- funcs.setreg('"', '')
+ fn.setreg('"', '')
feed('G$vbb')
- meths.input_mouse('right', 'press', '', 0, 4, 61)
- meths.input_mouse('right', 'release', '', 0, 4, 61)
+ api.nvim_input_mouse('right', 'press', '', 0, 4, 61)
+ api.nvim_input_mouse('right', 'release', '', 0, 4, 61)
feed('<Down><CR>')
- eq({4, 20}, meths.win_get_cursor(0))
- eq('the moon', funcs.getreg('"'))
+ eq({ 4, 20 }, api.nvim_win_get_cursor(0))
+ eq('the moon', fn.getreg('"'))
end)
end)
diff --git a/test/functional/ui/multibyte_spec.lua b/test/functional/ui/multibyte_spec.lua
index d72bf27d6b..c2fc763401 100644
--- a/test/functional/ui/multibyte_spec.lua
+++ b/test/functional/ui/multibyte_spec.lua
@@ -5,51 +5,49 @@ local command = helpers.command
local feed = helpers.feed
local feed_command = helpers.feed_command
local insert = helpers.insert
-local funcs = helpers.funcs
-local meths = helpers.meths
-local split = helpers.split
+local fn = helpers.fn
+local api = helpers.api
+local split = vim.split
local dedent = helpers.dedent
-describe("multibyte rendering", function()
+describe('multibyte rendering', function()
local screen
before_each(function()
clear()
screen = Screen.new(60, 6)
- screen:attach({rgb=true})
+ screen:attach({ rgb = true })
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue},
- [2] = {background = Screen.colors.WebGray},
- [3] = {background = Screen.colors.LightMagenta},
- [4] = {bold = true},
- [5] = {foreground = Screen.colors.Blue},
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { background = Screen.colors.WebGray },
+ [3] = { background = Screen.colors.LightMagenta },
+ [4] = { bold = true },
+ [5] = { foreground = Screen.colors.Blue },
+ [6] = { reverse = true, bold = true },
+ [7] = { reverse = true },
})
end)
- it("works with composed char at start of line", function()
+ it('works with composed char at start of line', function()
insert([[
ÌŠ
x]])
- feed("gg")
- -- verify the modifier in fact is alone
- feed_command("ascii")
+ feed('gg')
+ -- verify the modifier in fact is alone
+ feed_command('ascii')
screen:expect([[
^ ÌŠ |
x |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
< ÌŠ> 778, Hex 030a, Octal 1412 |
]])
-- a char inserted before will spontaneously merge with it
- feed("ia<esc>")
- feed_command("ascii")
+ feed('ia<esc>')
+ feed_command('ascii')
screen:expect([[
^aÌŠ |
x |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
<a> 97, Hex 61, Octal 141 < ÌŠ> 778, Hex 030a, Octal 1412 |
]])
end)
@@ -58,10 +56,7 @@ describe("multibyte rendering", function()
feed('58a <esc>a馬<esc>')
screen:expect([[
^馬|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
]])
@@ -69,9 +64,7 @@ describe("multibyte rendering", function()
screen:expect([[
^ {1:>}|
馬 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
@@ -79,9 +72,7 @@ describe("multibyte rendering", function()
screen:expect([[
{1:>}|
^馬 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
end)
@@ -91,20 +82,17 @@ describe("multibyte rendering", function()
screen:expect([[
ab ^ |
-馬 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{4:-- INSERT --} |
]])
- -- check double-with char is temporarily hidden when overlapped
- funcs.complete(4, {'xx', 'yy'})
+ -- check double-width char is temporarily hidden when overlapped
+ fn.complete(4, { 'xx', 'yy' })
screen:expect([[
ab xx^ |
- {2: xx } |
{1:~ }{3: yy }{1: }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{4:-- INSERT --} |
]])
@@ -113,29 +101,60 @@ describe("multibyte rendering", function()
screen:expect([[
ab xxz^ |
-馬 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{4:-- INSERT --} |
]])
end)
+ it('no stray chars when splitting left of window with double-width chars', function()
+ api.nvim_buf_set_lines(0, 0, -1, true, {
+ ('å£'):rep(16),
+ 'a' .. ('å£'):rep(16),
+ 'aa' .. ('å£'):rep(16),
+ 'aaa' .. ('å£'):rep(16),
+ 'aaaa' .. ('å£'):rep(16),
+ })
+ screen:expect([[
+ ^å£å£å£å£å£å£å£å£å£å£å£å£å£å£å£å£ |
+ aå£å£å£å£å£å£å£å£å£å£å£å£å£å£å£å£ |
+ aaå£å£å£å£å£å£å£å£å£å£å£å£å£å£å£å£ |
+ aaaå£å£å£å£å£å£å£å£å£å£å£å£å£å£å£å£ |
+ aaaaå£å£å£å£å£å£å£å£å£å£å£å£å£å£å£å£ |
+ |
+ ]])
+
+ command('20vnew')
+ screen:expect([[
+ ^ │å£å£å£å£å£å£å£å£å£å£å£å£å£å£å£å£ |
+ {1:~ }│aå£å£å£å£å£å£å£å£å£å£å£å£å£å£å£å£ |
+ {1:~ }│aaå£å£å£å£å£å£å£å£å£å£å£å£å£å£å£å£ |
+ {1:~ }│aaaå£å£å£å£å£å£å£å£å£å£å£å£å£å£å£å£ |
+ {6:[No Name] }{7:[No Name] [+] }|
+ |
+ ]])
+ end)
+
it('0xffff is shown as 4 hex digits', function()
command([[call setline(1, "\uFFFF!!!")]])
feed('$')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{5:<ffff>}!!^! |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
- ]]}
+ ]],
+ }
end)
it('works with a lot of unicode (zalgo) text', function()
screen:try_resize(65, 10)
- meths.buf_set_lines(0,0,-1,true, split(dedent [[
+ api.nvim_buf_set_lines(
+ 0,
+ 0,
+ -1,
+ true,
+ split(
+ dedent [[
L̓̉̑̒̌̚ơ̗̌̒̄̀rÌ̈̈̎̕Ìè̇̅̄̄Ìm̖̟̟̅̄̚ ̛̓̑̆̇ÌiÌ…Ì—Ì̟̞̜p̗̞̜̉̆̕sÌŸÌœÌÌ‘Ì̘ū̟̞̎̃̉mÌ̘ÌÌÌÌ™ Ì̖̌̇̉̚d̞̄̃̒̉̎oÌ€Ì̌̌̂Ìl̞̀̄̆̌̚ȯ̖̞̋̀Ìr̓̇̌̃̃̚ Ì€ÌÌ—Ì̘Ìs̜̀̎̎̑̕iÌ̟̗̄̄̚tÌŽÌ̆̓ÌÌ’ ̘̇̔̓̊̚aÌ‘Ì̛̟̗̅m̜̟̙̞̈̓e̘Ì̞̟̔̆t̂̂̈̑̔Ì,Ì…ÌœÌ„ÌœÌ–Ì Ì›ÌšÌŠÌ—Ì“Ì†cÌ̟̆Ì̈̔ȯ̖̖̑ÌÌ€n̜̟̎̊̃̚sÌ̟̇̎̒̚e̙̚Ì̈̓̌cÌ̈Ì̙̅̕ť̇̄̇̆̓e̛̓̌̈̓̈tÌ̟̀̉̆̅uÌ̞̎̂̄̚rÌ€Ì˜Ì…ÌˆÌ…Ì Ì“ÌÌ̞̇̉ãÌ̀̆̅̕d̆Ì̛̉̆̋iÌÌ̞̟̃̚pÌŠÌ̛̜̂̓iÌ‘Ì̅̃̋̚s̛̕Ì̇Ì̃č̛̞̀̂ÌiÌÌ—ÌŒÌ̘̎n̔̎Ì̒̂̕ǧ̗̜̋̇̂ ̛̜̔̄̎̃ê̛̔̆̇̕lÌÌ̘̊ÌÌĩÌÌ›ÌÌÌ„tÌÌÌŸÌ€ÌÌŽ,ÌÌ™Ì†Ì‰Ì˜Ì Ì‹Ì‚Ì̄̌̅s̓̌̈Ì̙̇e̛̗̋̒̎ÌdÌŠÌ̜̗̊̚
ď̘̋̌̌̕oÌ̗̌̔̇̕ Ì™ÌÌ̄̄̉è̛̛̞̌̌iÌ̜̖̈̆̚uÌ̇̈̓̃̓ŝ̛̞̙̉̋mÌœÌ̂̄̋̂ȯ̈̎̎̅̕d̜̙̓̔̋̑ ̞̗̄̂̂̚tÌŠÌÌ̃ÌÌ„e̛̘̜̞̓̑mÌŠÌ…Ì̉̌̕p̈̂̇̀ÌÌ›ỏ̙̘̈̉̔rÌ‹Ì̘̞̃̚ ̄̀̇̅̇Ìỉ̛̖Ì̓̈nÌŽÌ̛̛̕̕c̛̛̊̅ÌÌĭ̗̓̀ÌÌd̞̜̋̚ÌÌ…i̟̙̇̄̊̄d̞̊̂̀̇̚uÌ•Ì̉̉̑̃nÌ̇̄Ì̜̋ť̗̜̞̋̉ Ì’Ì“Ì̌̓̚uÌ̖̙̀̚̕t̖̘̎̉̂̌ ÌÌ„Ì̛̌̂l̛̟̃Ì̑̋aÌÌ”ÌÌÌ…Ì›bÌ…Ì̙̜̗̒ơ̖̌̒̄̆r̒̇̓̎̈̄e̛̛̖̅Ì̇ ̖̗̜̃ÌÌe̛̛̘̅̔̌ẗ̛̙̕ÌÌ— ̖̟̇̋̌̈d̞̙̀̉̑̕ŏ̂ÌÌÌÌ‘l̞̟̗̓̓̀ơ̘̎̃̄̂r̗̗̔̆ÌÌ–ẻ̖̋Ì̞̅ ̌̇Ì̜̈̊m̈̉̇̄̒̀a̜̞̘̔̅̆g̗̖̈̃̈̉n̙̖̄̈̉̄â̛̄Ì̜̃ Ì̛̎̕̕̚ā̊ÌÌ̆̌l̟̙̞̃̒Ìi̖̇̎̃̀̋q̇̒̆ÌÌŸÌŠủ̚Ì̌̇̑ã̛̘̉̚Ì.ÌÌ›ÌÌÌÌŠ
UÌ̙̎̈Ì̆tÌÌŒÌ€ÌœÌ”Ì Ì‰Ì̞̇̈̃e̟̟̊̄̕̕nÌ’Ì“Ì̜̆̕i̖̒̌̅̇̚m̞̊̃̔̊̂ ̛̜̊̎̄̂a̘̜̋̒̚̚dÌŠÌŽÌ‡Ì‚ÌŸÌ Ì̜̖̑̉̕m̜̒̎̅̄̚iÌ̖̓̂ÌÌ•n̙̉̒̑̀̔ỉ̖̌̒ÌÌm̛̖̘̅̆̎ ̖̉̎̒̌̕v̖̞̀̔ÌÌŽe̖̙̗̒̎̉n̛̗̎̀̂ÌiÌžÌ̗̒̕̚ȧ̟̜̚ÌÌ…m̆̉ÌÌ̇̈,ÌÌÌŽÌÌÌ ÌœÌžÌ™Ì̘̆q̙̖̙̅̓̂ủ̇̚Ì̀̔iÌÌÌ̙̟̟sÌÌ–ÌÌ̂̇ ̛̘̋̈̕̕n̞̜̜ÌÌŽÌ›o̗̜̔̔̈̆s̞̘̘̄̒̋tÌ…Ì‹Ì̛̔̈ȓ̓̒Ì̇̅ủ̜̄̃̒ÌdÌŠÌÌ™Ì̘̚ Ì„Ì̛̟̞̔eÌ—Ì̛̃ÌÌ€x̞̖̃̄̂̅e̖̅̇Ì̔̃r̗̞̖̔̎̚c̘̜̆̊ÌÌ–i̙̕Ì̙̈̂tÌÌ̖̓̋̂ă̖̄̆̑̒tÌ̜̟̉̑Ìi̛̞̞̘̒̑ǒ̜̆̅̃̉ṅ̖̜̒̎̚
@@ -144,11 +163,14 @@ describe("multibyte rendering", function()
ē̟̊̇̕̚s̖̘̘̒̄̑s̛̘̀̊̆̇e̒̚ÌÌ̛̘ ̉̅̑̂ÌÌŽc̛̟̙̎̋̓i̇̒Ì̜̆̆lÌ„Ì̟̆̊̌lÌ̊̋̃̆̌ủ̗̙̒̔̚m̛̘̘̅ÌÌ– ̖̙̈̎̂̕dÌ̞̟̋̈̔ơ̟̌̃̄Ìl̗̙̂̉ÌÌ’õ̒̃̄̄̚rÌÌ—ÌÌÌŠÌê̞Ì̞̋̈ ̜̔̒̎̃̚e̞̟̞̒̃̄uÌ̛̖̄̑̃ ̛̗̜̄̓̎f̛̖̞̅̓̃ü̞̕Ì̆̋g̜̑Ì̞̑̆iÌ̛̚Ì̘̅à̜̖̌̆̎t̙̎̉̂ÌÌ™ ̋̔̈̎̎̉nÌ“Ì̞̔̊̕ư̘̅̋̔̚lÌ̗̒̄̀̚l̞̗̘̓ÌÌ™â̘̔̒̎̚ ̖̓̋̉̃̆p̛̛̘̋̌̀ä̔Ì̙̒̕rÌ‹Ì̟̟̖̋ì̗̙̎̓̓ȃ̔̋̑̚̕tÌ„Ì̎̓̂̋uÌ̛̈̂̑̃r̖̓̋̊̚̚.̒̆̑̆̊̎ ÌÌšÌ̘̜̂EÌ…Ì̞̇ÌÌ‚xÌ„Ì̈̌̉̕cÌ•Ì̘̃̉̃è̂̑Ì̘̑pÌ‘Ì̘̂̌̆tÌ”ÌÌ…Ì̌̂ȇ̞̈̚̕ÌuÌ̞̜̋̚ÌrÌ̗̉̆ÌÌ
sÌŒÌ̟̔ÌÌ€iÌÌŸÌÌÌ…Ìn̑̆̇̒̆̚tÌ’ÌÌ…ÌÌ‹Ì Ì‘ÌšÌ—ÌŒÌ‹Ì‡ơ̙̗̟̆̅c̙̞̙̎̊̎cÌ̘̟̔̊̊a̛̒̓̉ÌÌe̜̘̙̒̅̇cÌÌ•ÌÌ‚Ì̇ả̓Ì̎̂̚t̗̗̗̟̒̃ Ì’Ì“Ì̇Ì̘c̟̞̉Ì̓̄uÌ̙̗̅ÌÌpÌ̋̈ÌÌ…Ì›i̓̒Ì̖̈̄d̞̃̈̌̆Ìa̛̗̎̋Ì̉t̞̙̀̊̆̇a̛̙̒̆̉̚t̜̟̘̉̓̚ ÌÌ̘̗̇̕n̛̘̑ÌÌ‚Ìō̑̋̉ÌÌň̞̊̆̄̃ ̙̙̙̜̄Ìp̒̆̋̋̓Ìr̖̖̅̉̚Ìơ̜̆̑̈̚i̟̒̀̃̂̌dÌ̃̚Ì̛̋ë̖̞̙̗̓n̛̘̓̒̅̎t̟̗̙̊̆̚,̘̙̔̊̚̕ ̟̗̘̜̑̔sÌ̜̀̓̌Ìû̞̙̅̇Ìn̘̗̒̃̎Ìt̗̅̀̅̊̈ ̗̖̅̅̀̄iÌ›Ì̖̅̋̂n̙̓Ì̓̎̚ ̞̋̅̋̃̚c̗̒̀̆̌̎ū̞̂̑̌̓lÌÌ›ÌÌÌ‘Ìp̆̌̎̈̚Ìa̖̙̒̅̈̌ ÌÌ̜̂̈̀q̔̚ÌÌÌ’Ì–uÌ”Ì̛̂̎̊ǐ̛̟̖̘̕
o̖̜̔̋̅̚f̛̊̀̉̕ÌfÌ̉̀̔̃̃iÌ̘̎Ì̔̎c̙̅̑̂ÌÌ…ȋ̛̜̀̒̚aÌ‹Ì̇Ì̀̋ ̖̘̒̅̃̒d̗̘̓̈̇̋eÌÌÌÌŽÌ’Ì„š̙̒̊̉̋eÌ–Ì“Ì̀̕Ìr̗̞̂̅̇̄ù̘̇Ì̉̀nÌ̑̀̄ÌÌt̟̀̂̊̄̚ ÌŸÌÌ‚ÌÌÌm̜̗̈̂̚Ìő̞̊̑̇̒lÌ‘Ì̘Ì̔̄l̛̛̇̃̋̊i̓̋̒̃̉̌tÌ—ÌœÌ̛̀̋ ̙̟̒̂̌Ìa̙̔̆ÌÌ…ÌnÌ̙̙̗̆̅iÌ•ÌÌ”Ì̊̃mÌ–Ì’ÌÌŸÌšÌ ÌƒÌƒÌ‘ÌŒÌÌ›ǐ̘̉̔̅̚dÌ€ÌÌŒÌÌ’Ì— ̖̓̑̚ÌÌŠȇ̞̟̖̌̕š̙̙̈̔̀t̂̉̒Ì̄̄ ̊̋̌Ì̗̄l̛̞̜̙̘̔aÌŠÌÌ‚ÌÌÌ…b̜̆̇̈̉̌ǒ̜̙̎̃̆r̀̄ÌÌÌ•Ìű̊̕ÌÌŠÌ›m̜̒̕ÌÌ—Ìš.̟̘̀̒̌̚]],
- '\n'))
+ '\n'
+ )
+ )
-- tests that we can handle overflow of the buffer
-- for redraw events (4096 bytes) gracefully
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^L̓̉̑̒̌̚ơ̗̌̒̄̀rÌ̈̈̎̕Ìè̇̅̄̄Ìm̖̟̟̅̄̚ ̛̓̑̆̇ÌiÌ…Ì—Ì̟̞̜p̗̞̜̉̆̕sÌŸÌœÌÌ‘Ì̘ū̟̞̎̃̉mÌ̘ÌÌÌÌ™ Ì̖̌̇̉̚d̞̄̃̒̉̎oÌ€Ì̌̌̂Ìl̞̀̄̆̌̚ȯ̖̞̋̀Ìr̓̇̌̃̃̚ Ì€ÌÌ—Ì̘Ìs̜̀̎̎̑̕iÌ̟̗̄̄̚tÌŽÌ̆̓ÌÌ’ ̘̇̔̓̊̚aÌ‘Ì̛̟̗̅m̜̟̙̞̈̓e̘Ì̞̟̔̆t̂̂̈̑̔Ì,Ì…ÌœÌ„ÌœÌ–Ì Ì›ÌšÌŠÌ—Ì“Ì†cÌ̟̆Ì̈̔ȯ̖̖̑ÌÌ€n̜̟̎̊̃̚sÌ̟̇̎̒̚e̙̚Ì̈̓̌cÌ̈Ì̙̅̕ť̇̄̇̆̓e̛̓̌̈̓̈tÌ̟̀̉̆̅uÌ̞̎̂̄̚rÌ€Ì˜Ì…ÌˆÌ…Ì Ì“ÌÌ̞̇̉ãÌ̀̆̅̕d̆Ì̛̉̆̋iÌÌ̞̟̃̚pÌŠÌ̛̜̂̓iÌ‘Ì̅̃̋̚s̛̕Ì̇Ì̃č̛̞̀̂ÌiÌÌ—ÌŒÌ̘̎n̔̎Ì̒̂̕ǧ̗̜̋̇̂ ̛̜̔̄̎̃ê̛̔̆̇̕lÌÌ̘̊ÌÌĩÌÌ›ÌÌÌ„tÌÌÌŸÌ€ÌÌŽ,ÌÌ™Ì†Ì‰Ì˜Ì Ì‹Ì‚Ì̄̌̅s̓̌̈Ì̙̇e̛̗̋̒̎ÌdÌŠÌ̜̗̊̚ |
ď̘̋̌̌̕oÌ̗̌̔̇̕ Ì™ÌÌ̄̄̉è̛̛̞̌̌iÌ̜̖̈̆̚uÌ̇̈̓̃̓ŝ̛̞̙̉̋mÌœÌ̂̄̋̂ȯ̈̎̎̅̕d̜̙̓̔̋̑ ̞̗̄̂̂̚tÌŠÌÌ̃ÌÌ„e̛̘̜̞̓̑mÌŠÌ…Ì̉̌̕p̈̂̇̀ÌÌ›ỏ̙̘̈̉̔rÌ‹Ì̘̞̃̚ ̄̀̇̅̇Ìỉ̛̖Ì̓̈nÌŽÌ̛̛̕̕c̛̛̊̅ÌÌĭ̗̓̀ÌÌd̞̜̋̚ÌÌ…i̟̙̇̄̊̄d̞̊̂̀̇̚uÌ•Ì̉̉̑̃nÌ̇̄Ì̜̋ť̗̜̞̋̉ Ì’Ì“Ì̌̓̚uÌ̖̙̀̚̕t̖̘̎̉̂̌ ÌÌ„Ì̛̌̂l̛̟̃Ì̑̋aÌÌ”ÌÌÌ…Ì›bÌ…Ì̙̜̗̒ơ̖̌̒̄̆r̒̇̓̎̈̄e̛̛̖̅Ì̇ ̖̗̜̃ÌÌe̛̛̘̅̔̌ẗ̛̙̕ÌÌ— ̖̟̇̋̌̈d̞̙̀̉̑̕ŏ̂ÌÌÌÌ‘l̞̟̗̓̓̀ơ̘̎̃̄̂r̗̗̔̆ÌÌ–ẻ̖̋Ì̞̅ ̌̇Ì̜̈̊m̈̉̇̄̒̀a̜̞̘̔̅̆g̗̖̈̃̈̉n̙̖̄̈̉̄â̛̄Ì̜̃ Ì̛̎̕̕̚ā̊ÌÌ̆̌l̟̙̞̃̒Ìi̖̇̎̃̀̋q̇̒̆ÌÌŸÌŠủ̚Ì̌̇̑ã̛̘̉̚Ì.ÌÌ›ÌÌÌÌŠ |
UÌ̙̎̈Ì̆tÌÌŒÌ€ÌœÌ”Ì Ì‰Ì̞̇̈̃e̟̟̊̄̕̕nÌ’Ì“Ì̜̆̕i̖̒̌̅̇̚m̞̊̃̔̊̂ ̛̜̊̎̄̂a̘̜̋̒̚̚dÌŠÌŽÌ‡Ì‚ÌŸÌ Ì̜̖̑̉̕m̜̒̎̅̄̚iÌ̖̓̂ÌÌ•n̙̉̒̑̀̔ỉ̖̌̒ÌÌm̛̖̘̅̆̎ ̖̉̎̒̌̕v̖̞̀̔ÌÌŽe̖̙̗̒̎̉n̛̗̎̀̂ÌiÌžÌ̗̒̕̚ȧ̟̜̚ÌÌ…m̆̉ÌÌ̇̈,ÌÌÌŽÌÌÌ ÌœÌžÌ™Ì̘̆q̙̖̙̅̓̂ủ̇̚Ì̀̔iÌÌÌ̙̟̟sÌÌ–ÌÌ̂̇ ̛̘̋̈̕̕n̞̜̜ÌÌŽÌ›o̗̜̔̔̈̆s̞̘̘̄̒̋tÌ…Ì‹Ì̛̔̈ȓ̓̒Ì̇̅ủ̜̄̃̒ÌdÌŠÌÌ™Ì̘̚ Ì„Ì̛̟̞̔eÌ—Ì̛̃ÌÌ€x̞̖̃̄̂̅e̖̅̇Ì̔̃r̗̞̖̔̎̚c̘̜̆̊ÌÌ–i̙̕Ì̙̈̂tÌÌ̖̓̋̂ă̖̄̆̑̒tÌ̜̟̉̑Ìi̛̞̞̘̒̑ǒ̜̆̅̃̉ṅ̖̜̒̎̚ |
@@ -159,12 +181,14 @@ describe("multibyte rendering", function()
o̖̜̔̋̅̚f̛̊̀̉̕ÌfÌ̉̀̔̃̃iÌ̘̎Ì̔̎c̙̅̑̂ÌÌ…ȋ̛̜̀̒̚aÌ‹Ì̇Ì̀̋ ̖̘̒̅̃̒d̗̘̓̈̇̋eÌÌÌÌŽÌ’Ì„š̙̒̊̉̋eÌ–Ì“Ì̀̕Ìr̗̞̂̅̇̄ù̘̇Ì̉̀nÌ̑̀̄ÌÌt̟̀̂̊̄̚ ÌŸÌÌ‚ÌÌÌm̜̗̈̂̚Ìő̞̊̑̇̒lÌ‘Ì̘Ì̔̄l̛̛̇̃̋̊i̓̋̒̃̉̌tÌ—ÌœÌ̛̀̋ ̙̟̒̂̌Ìa̙̔̆ÌÌ…ÌnÌ̙̙̗̆̅iÌ•ÌÌ”Ì̊̃mÌ–Ì’ÌÌŸÌšÌ ÌƒÌƒÌ‘ÌŒÌÌ›ǐ̘̉̔̅̚dÌ€ÌÌŒÌÌ’Ì— ̖̓̑̚ÌÌŠȇ̞̟̖̌̕š̙̙̈̔̀t̂̉̒Ì̄̄ ̊̋̌Ì̗̄l̛̞̜̙̘̔aÌŠÌÌ‚ÌÌÌ…b̜̆̇̈̉̌ǒ̜̙̎̃̆r̀̄ÌÌÌ•Ìű̊̕ÌÌŠÌ›m̜̒̕ÌÌ—Ìš.̟̘̀̒̌̚ |
{1:~ }|
|
- ]]}
+ ]],
+ }
-- nvim will reset the zalgo text^W^W glyph cache if it gets too full.
-- this should be exceedingly rare, but fake it to make sure it works
- meths._invalidate_glyph_cache()
- screen:expect{grid=[[
+ api.nvim__invalidate_glyph_cache()
+ screen:expect {
+ grid = [[
^L̓̉̑̒̌̚ơ̗̌̒̄̀rÌ̈̈̎̕Ìè̇̅̄̄Ìm̖̟̟̅̄̚ ̛̓̑̆̇ÌiÌ…Ì—Ì̟̞̜p̗̞̜̉̆̕sÌŸÌœÌÌ‘Ì̘ū̟̞̎̃̉mÌ̘ÌÌÌÌ™ Ì̖̌̇̉̚d̞̄̃̒̉̎oÌ€Ì̌̌̂Ìl̞̀̄̆̌̚ȯ̖̞̋̀Ìr̓̇̌̃̃̚ Ì€ÌÌ—Ì̘Ìs̜̀̎̎̑̕iÌ̟̗̄̄̚tÌŽÌ̆̓ÌÌ’ ̘̇̔̓̊̚aÌ‘Ì̛̟̗̅m̜̟̙̞̈̓e̘Ì̞̟̔̆t̂̂̈̑̔Ì,Ì…ÌœÌ„ÌœÌ–Ì Ì›ÌšÌŠÌ—Ì“Ì†cÌ̟̆Ì̈̔ȯ̖̖̑ÌÌ€n̜̟̎̊̃̚sÌ̟̇̎̒̚e̙̚Ì̈̓̌cÌ̈Ì̙̅̕ť̇̄̇̆̓e̛̓̌̈̓̈tÌ̟̀̉̆̅uÌ̞̎̂̄̚rÌ€Ì˜Ì…ÌˆÌ…Ì Ì“ÌÌ̞̇̉ãÌ̀̆̅̕d̆Ì̛̉̆̋iÌÌ̞̟̃̚pÌŠÌ̛̜̂̓iÌ‘Ì̅̃̋̚s̛̕Ì̇Ì̃č̛̞̀̂ÌiÌÌ—ÌŒÌ̘̎n̔̎Ì̒̂̕ǧ̗̜̋̇̂ ̛̜̔̄̎̃ê̛̔̆̇̕lÌÌ̘̊ÌÌĩÌÌ›ÌÌÌ„tÌÌÌŸÌ€ÌÌŽ,ÌÌ™Ì†Ì‰Ì˜Ì Ì‹Ì‚Ì̄̌̅s̓̌̈Ì̙̇e̛̗̋̒̎ÌdÌŠÌ̜̗̊̚ |
ď̘̋̌̌̕oÌ̗̌̔̇̕ Ì™ÌÌ̄̄̉è̛̛̞̌̌iÌ̜̖̈̆̚uÌ̇̈̓̃̓ŝ̛̞̙̉̋mÌœÌ̂̄̋̂ȯ̈̎̎̅̕d̜̙̓̔̋̑ ̞̗̄̂̂̚tÌŠÌÌ̃ÌÌ„e̛̘̜̞̓̑mÌŠÌ…Ì̉̌̕p̈̂̇̀ÌÌ›ỏ̙̘̈̉̔rÌ‹Ì̘̞̃̚ ̄̀̇̅̇Ìỉ̛̖Ì̓̈nÌŽÌ̛̛̕̕c̛̛̊̅ÌÌĭ̗̓̀ÌÌd̞̜̋̚ÌÌ…i̟̙̇̄̊̄d̞̊̂̀̇̚uÌ•Ì̉̉̑̃nÌ̇̄Ì̜̋ť̗̜̞̋̉ Ì’Ì“Ì̌̓̚uÌ̖̙̀̚̕t̖̘̎̉̂̌ ÌÌ„Ì̛̌̂l̛̟̃Ì̑̋aÌÌ”ÌÌÌ…Ì›bÌ…Ì̙̜̗̒ơ̖̌̒̄̆r̒̇̓̎̈̄e̛̛̖̅Ì̇ ̖̗̜̃ÌÌe̛̛̘̅̔̌ẗ̛̙̕ÌÌ— ̖̟̇̋̌̈d̞̙̀̉̑̕ŏ̂ÌÌÌÌ‘l̞̟̗̓̓̀ơ̘̎̃̄̂r̗̗̔̆ÌÌ–ẻ̖̋Ì̞̅ ̌̇Ì̜̈̊m̈̉̇̄̒̀a̜̞̘̔̅̆g̗̖̈̃̈̉n̙̖̄̈̉̄â̛̄Ì̜̃ Ì̛̎̕̕̚ā̊ÌÌ̆̌l̟̙̞̃̒Ìi̖̇̎̃̀̋q̇̒̆ÌÌŸÌŠủ̚Ì̌̇̑ã̛̘̉̚Ì.ÌÌ›ÌÌÌÌŠ |
UÌ̙̎̈Ì̆tÌÌŒÌ€ÌœÌ”Ì Ì‰Ì̞̇̈̃e̟̟̊̄̕̕nÌ’Ì“Ì̜̆̕i̖̒̌̅̇̚m̞̊̃̔̊̂ ̛̜̊̎̄̂a̘̜̋̒̚̚dÌŠÌŽÌ‡Ì‚ÌŸÌ Ì̜̖̑̉̕m̜̒̎̅̄̚iÌ̖̓̂ÌÌ•n̙̉̒̑̀̔ỉ̖̌̒ÌÌm̛̖̘̅̆̎ ̖̉̎̒̌̕v̖̞̀̔ÌÌŽe̖̙̗̒̎̉n̛̗̎̀̂ÌiÌžÌ̗̒̕̚ȧ̟̜̚ÌÌ…m̆̉ÌÌ̇̈,ÌÌÌŽÌÌÌ ÌœÌžÌ™Ì̘̆q̙̖̙̅̓̂ủ̇̚Ì̀̔iÌÌÌ̙̟̟sÌÌ–ÌÌ̂̇ ̛̘̋̈̕̕n̞̜̜ÌÌŽÌ›o̗̜̔̔̈̆s̞̘̘̄̒̋tÌ…Ì‹Ì̛̔̈ȓ̓̒Ì̇̅ủ̜̄̃̒ÌdÌŠÌÌ™Ì̘̚ Ì„Ì̛̟̞̔eÌ—Ì̛̃ÌÌ€x̞̖̃̄̂̅e̖̅̇Ì̔̃r̗̞̖̔̎̚c̘̜̆̊ÌÌ–i̙̕Ì̙̈̂tÌÌ̖̓̋̂ă̖̄̆̑̒tÌ̜̟̉̑Ìi̛̞̞̘̒̑ǒ̜̆̅̃̉ṅ̖̜̒̎̚ |
@@ -175,7 +199,9 @@ describe("multibyte rendering", function()
o̖̜̔̋̅̚f̛̊̀̉̕ÌfÌ̉̀̔̃̃iÌ̘̎Ì̔̎c̙̅̑̂ÌÌ…ȋ̛̜̀̒̚aÌ‹Ì̇Ì̀̋ ̖̘̒̅̃̒d̗̘̓̈̇̋eÌÌÌÌŽÌ’Ì„š̙̒̊̉̋eÌ–Ì“Ì̀̕Ìr̗̞̂̅̇̄ù̘̇Ì̉̀nÌ̑̀̄ÌÌt̟̀̂̊̄̚ ÌŸÌÌ‚ÌÌÌm̜̗̈̂̚Ìő̞̊̑̇̒lÌ‘Ì̘Ì̔̄l̛̛̇̃̋̊i̓̋̒̃̉̌tÌ—ÌœÌ̛̀̋ ̙̟̒̂̌Ìa̙̔̆ÌÌ…ÌnÌ̙̙̗̆̅iÌ•ÌÌ”Ì̊̃mÌ–Ì’ÌÌŸÌšÌ ÌƒÌƒÌ‘ÌŒÌÌ›ǐ̘̉̔̅̚dÌ€ÌÌŒÌÌ’Ì— ̖̓̑̚ÌÌŠȇ̞̟̖̌̕š̙̙̈̔̀t̂̉̒Ì̄̄ ̊̋̌Ì̗̄l̛̞̜̙̘̔aÌŠÌÌ‚ÌÌÌ…b̜̆̇̈̉̌ǒ̜̙̎̃̆r̀̄ÌÌÌ•Ìű̊̕ÌÌŠÌ›m̜̒̕ÌÌ—Ìš.̟̘̀̒̌̚ |
{1:~ }|
|
- ]], reset=true}
+ ]],
+ reset = true,
+ }
end)
it('works with arabic input and arabicshape', function()
@@ -183,24 +209,22 @@ describe("multibyte rendering", function()
command('set noarabicshape')
feed('isghl!<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^!مالس|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*4
|
- ]]}
+ ]],
+ }
command('set arabicshape')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^!ﻡﻼﺳ|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*4
|
- ]]}
+ ]],
+ }
end)
it('works with arabic input and arabicshape and norightleft', function()
@@ -208,25 +232,22 @@ describe("multibyte rendering", function()
command('set noarabicshape')
feed('isghl!<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
سلام^! |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
- ]]}
+ ]],
+ }
command('set arabicshape')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
ﺱﻼﻣ^! |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
- ]]}
-
+ ]],
+ }
end)
it('works with arabicshape and multiple composing chars', function()
@@ -236,27 +257,25 @@ describe("multibyte rendering", function()
-- If we would increase the schar_t size, say from 32 to 64 bytes, we need to extend the
-- test text with even more zalgo energy to still touch this edge case.
- meths.buf_set_lines(0,0,-1,true, {"سلام̀Ì့̂̃̄̅̆̇̈̉̊̋̌"})
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'سلام̀Ì့̂̃̄̅̆̇̈̉̊̋̌' })
command('set noarabicshape')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^سلام̀Ì့̂̃̄̅̆̇̈̉̊̋̌ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
- ]]}
+ ]],
+ }
command('set arabicshape')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ﺱﻼﻣ̀Ì̂̃̄̅̆̇̈̉̊̋̌ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
|
- ]]}
+ ]],
+ }
end)
end)
@@ -267,9 +286,9 @@ describe('multibyte rendering: statusline', function()
clear()
screen = Screen.new(40, 4)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {bold = true, reverse = true},
- [3] = {background = Screen.colors.Red, foreground = Screen.colors.Gray100};
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, reverse = true },
+ [3] = { background = Screen.colors.Red, foreground = Screen.colors.Gray100 },
})
screen:attach()
command('set laststatus=2')
@@ -325,34 +344,40 @@ describe('multibyte rendering: statusline', function()
it('hidden group %( %) does not cause invalid unicode', function()
command("let &statusline = '%#StatColorHi2#%(✓%#StatColorHi2#%) Q≡'")
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
{1:~ }|
{2: Q≡ }|
|
- ]]}
+ ]],
+ }
end)
it('unprintable chars in filename with default stl', function()
- command("file 🧑â€ðŸ’»")
+ command('file 🧑â€ðŸ’»')
-- TODO: this is wrong but avoids a crash
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
{1:~ }|
{2:🧑�💻 }|
|
- ]]}
+ ]],
+ }
end)
it('unprintable chars in filename with custom stl', function()
command('set statusline=xx%#ErrorMsg#%f%##yy')
- command("file 🧑â€ðŸ’»")
+ command('file 🧑â€ðŸ’»')
-- TODO: this is also wrong but also avoids a crash
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
{1:~ }|
{2:xx}{3:🧑<200d>💻}{2:yy }|
|
- ]]}
+ ]],
+ }
end)
end)
diff --git a/test/functional/ui/multigrid_spec.lua b/test/functional/ui/multigrid_spec.lua
index 5b982df2b5..c1d3af085f 100644
--- a/test/functional/ui/multigrid_spec.lua
+++ b/test/functional/ui/multigrid_spec.lua
@@ -3,9 +3,9 @@ local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local feed, command, insert = helpers.feed, helpers.command, helpers.insert
local eq = helpers.eq
-local funcs = helpers.funcs
-local meths = helpers.meths
-local curwin = helpers.curwin
+local fn = helpers.fn
+local api = helpers.api
+local curwin = helpers.api.nvim_get_current_win
local poke_eventloop = helpers.poke_eventloop
@@ -36,7 +36,7 @@ describe('ext_multigrid', function()
[17] = {background = Screen.colors.LightGrey, underline = true, bold = true, foreground = Screen.colors.Magenta},
[18] = {bold = true, foreground = Screen.colors.Magenta},
[19] = {foreground = Screen.colors.Brown},
- [20] = {background = Screen.colors.LightGrey},
+ [20] = {background = Screen.colors.LightGrey, foreground = Screen.colors.Black},
[21] = {background = Screen.colors.LightMagenta},
[22] = {background = Screen.colors.LightMagenta, bold = true, foreground = Screen.colors.Blue},
[23] = {background = Screen.colors.Grey90},
@@ -47,33 +47,12 @@ describe('ext_multigrid', function()
it('default initial screen', function()
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
]]}
@@ -83,144 +62,71 @@ describe('ext_multigrid', function()
command('vsplit')
screen:expect{grid=[[
## grid 1
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
+ [4:--------------------------]│[2:--------------------------]|*12
{11:[No Name] }{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
]], condition=function()
eq({
- [2] = { win = {id=1000}, startrow = 0, startcol = 27, width = 26, height = 12 },
- [4] = { win = {id=1001}, startrow = 0, startcol = 0, width = 26, height = 12 }
+ [2] = { win = 1000, startrow = 0, startcol = 27, width = 26, height = 12 },
+ [4] = { win = 1001, startrow = 0, startcol = 0, width = 26, height = 12 }
}, screen.win_position)
end}
command('wincmd l')
command('split')
screen:expect{grid=[[
## grid 1
- [4:--------------------------]│[5:--------------------------]|
- [4:--------------------------]│[5:--------------------------]|
- [4:--------------------------]│[5:--------------------------]|
- [4:--------------------------]│[5:--------------------------]|
- [4:--------------------------]│[5:--------------------------]|
- [4:--------------------------]│[5:--------------------------]|
+ [4:--------------------------]│[5:--------------------------]|*6
[4:--------------------------]│{11:[No Name] }|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
+ [4:--------------------------]│[2:--------------------------]|*5
{12:[No Name] [No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 5
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]], condition=function()
eq({
- [2] = { win = {id=1000}, startrow = 7, startcol = 27, width = 26, height = 5 },
- [4] = { win = {id=1001}, startrow = 0, startcol = 0, width = 26, height = 12 },
- [5] = { win = {id=1002}, startrow = 0, startcol = 27, width = 26, height = 6 }
+ [2] = { win = 1000, startrow = 7, startcol = 27, width = 26, height = 5 },
+ [4] = { win = 1001, startrow = 0, startcol = 0, width = 26, height = 12 },
+ [5] = { win = 1002, startrow = 0, startcol = 27, width = 26, height = 6 }
}, screen.win_position)
end}
command('wincmd h')
command('q')
screen:expect{grid=[[
## grid 1
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
+ [5:-----------------------------------------------------]|*6
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 5
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]], condition=function()
eq({
- [2] = { win = {id=1000}, startrow = 7, startcol = 0, width = 53, height = 5 },
- [5] = { win = {id=1002}, startrow = 0, startcol = 0, width = 53, height = 6 }
+ [2] = { win = 1000, startrow = 7, startcol = 0, width = 53, height = 5 },
+ [5] = { win = 1002, startrow = 0, startcol = 0, width = 53, height = 6 }
}, screen.win_position)
end}
end)
@@ -231,35 +137,19 @@ describe('ext_multigrid', function()
command('sp')
screen:expect([[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]])
end)
@@ -268,35 +158,19 @@ describe('ext_multigrid', function()
command('resize 8')
screen:expect([[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*8
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*3
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
]])
end)
@@ -306,162 +180,77 @@ describe('ext_multigrid', function()
command('vsp')
screen:expect{grid=[[
## grid 1
- [6:--------------------]│[5:----------------]│[4:---------------]|
- [6:--------------------]│[5:----------------]│[4:---------------]|
- [6:--------------------]│[5:----------------]│[4:---------------]|
- [6:--------------------]│[5:----------------]│[4:---------------]|
- [6:--------------------]│[5:----------------]│[4:---------------]|
- [6:--------------------]│[5:----------------]│[4:---------------]|
+ [6:--------------------]│[5:----------------]│[4:---------------]|*6
{11:[No Name] }{12:[No Name] [No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 5
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 6
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
insert('hello')
screen:expect{grid=[[
## grid 1
- [6:--------------------]│[5:----------------]│[4:---------------]|
- [6:--------------------]│[5:----------------]│[4:---------------]|
- [6:--------------------]│[5:----------------]│[4:---------------]|
- [6:--------------------]│[5:----------------]│[4:---------------]|
- [6:--------------------]│[5:----------------]│[4:---------------]|
- [6:--------------------]│[5:----------------]│[4:---------------]|
+ [6:--------------------]│[5:----------------]│[4:---------------]|*6
{11:[No Name] [+] }{12:[No Name] [+] [No Name] [+] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
hello |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
hello |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 5
hello |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 6
hell^o |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
end)
it('closes splits', function ()
command('sp')
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
command('q')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
]]}
@@ -473,48 +262,17 @@ describe('ext_multigrid', function()
command('vsp')
screen:expect{grid=[[
## grid 1
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
+ [4:--------------------------]│[2:--------------------------]|*12
{11:[No Name] }{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
]]}
end)
it('resizes grids', function ()
@@ -522,48 +280,17 @@ describe('ext_multigrid', function()
command('vertical resize 10')
screen:expect{grid=[[
## grid 1
- [4:----------]│[2:------------------------------------------]|
- [4:----------]│[2:------------------------------------------]|
- [4:----------]│[2:------------------------------------------]|
- [4:----------]│[2:------------------------------------------]|
- [4:----------]│[2:------------------------------------------]|
- [4:----------]│[2:------------------------------------------]|
- [4:----------]│[2:------------------------------------------]|
- [4:----------]│[2:------------------------------------------]|
- [4:----------]│[2:------------------------------------------]|
- [4:----------]│[2:------------------------------------------]|
- [4:----------]│[2:------------------------------------------]|
- [4:----------]│[2:------------------------------------------]|
+ [4:----------]│[2:------------------------------------------]|*12
{11:<No Name] }{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
]]}
end)
it('splits horizontally', function ()
@@ -571,173 +298,69 @@ describe('ext_multigrid', function()
command('sp')
screen:expect{grid=[[
## grid 1
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
+ [5:--------------------------]│[2:--------------------------]|*6
{11:[No Name] }│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
+ [4:--------------------------]│[2:--------------------------]|*5
{12:[No Name] [No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
## grid 4
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 5
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
insert('hello')
screen:expect{grid=[[
## grid 1
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
+ [5:--------------------------]│[2:--------------------------]|*6
{11:[No Name] [+] }│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
+ [4:--------------------------]│[2:--------------------------]|*5
{12:[No Name] [+] [No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
hello |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
## grid 4
hello |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 5
hell^o |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
end)
it('closes splits', function ()
command('vsp')
screen:expect{grid=[[
## grid 1
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
+ [4:--------------------------]│[2:--------------------------]|*12
{11:[No Name] }{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
]]}
command('q')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
]]}
@@ -750,17 +373,12 @@ describe('ext_multigrid', function()
screen:try_resize(25, 6)
screen:expect{grid=[[
## grid 1
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
- [2:-------------------------]|
+ [2:-------------------------]|*4
{11:[No Name] }|
[3:-------------------------]|
## grid 2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
]]}
@@ -799,26 +417,12 @@ describe('ext_multigrid', function()
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
]]}
@@ -831,41 +435,12 @@ describe('ext_multigrid', function()
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*19
## grid 3
|
]]}
@@ -879,52 +454,30 @@ describe('ext_multigrid', function()
end)
it('winwidth() winheight() getwininfo() return inner width and height #19743', function()
- eq(60, funcs.winwidth(0))
- eq(20, funcs.winheight(0))
- local win_info = funcs.getwininfo(curwin().id)[1]
+ eq(60, fn.winwidth(0))
+ eq(20, fn.winheight(0))
+ local win_info = fn.getwininfo(curwin())[1]
eq(60, win_info.width)
eq(20, win_info.height)
end)
+ it("'scroll' option works properly", function()
+ eq(10, api.nvim_get_option_value('scroll', { win = 0 }))
+ api.nvim_set_option_value('scroll', 15, { win = 0 })
+ eq(15, api.nvim_get_option_value('scroll', { win = 0 }))
+ end)
+
it('gets written till grid width', function()
insert(('a'):rep(60).."\n")
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*18
## grid 3
|
]]}
@@ -936,82 +489,24 @@ describe('ext_multigrid', function()
feed('0')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
^aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa哦|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*19
## grid 3
|
]]}
feed('g$')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa^哦|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*19
## grid 3
|
]]}
@@ -1021,41 +516,14 @@ describe('ext_multigrid', function()
insert(('b'):rep(160).."\n")
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
- bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb|*2
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*16
## grid 3
|
]]}
@@ -1063,18 +531,7 @@ describe('ext_multigrid', function()
command('setlocal cursorline cursorlineopt=screenline')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
@@ -1082,22 +539,7 @@ describe('ext_multigrid', function()
{23:^bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb}|
bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*16
## grid 3
|
]]}
@@ -1108,41 +550,12 @@ describe('ext_multigrid', function()
' long message"')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*19
## grid 3
this is a very very very...ry very very long message |
]]}
@@ -1153,41 +566,13 @@ describe('ext_multigrid', function()
feed('kzfgg')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
{13:^+-- 2 lines: this is a fold································}|
this is outside fold |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*18
## grid 3
|
]]}
@@ -1197,46 +582,18 @@ describe('ext_multigrid', function()
insert(('c'):rep(1111))
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
+ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|*18
cccccccccccccccccccccccccccccc^c |
{1:~ }|
## grid 3
|
]]}
- local float_buf = meths.create_buf(false, false)
- meths.open_win(float_buf, false, {
+ local float_buf = api.nvim_create_buf(false, false)
+ api.nvim_open_win(float_buf, false, {
relative = 'win',
win = curwin(),
bufpos = {0, 1018},
@@ -1246,51 +603,20 @@ describe('ext_multigrid', function()
})
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
- cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|
+ cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc|*18
cccccccccccccccccccccccccccccc^c |
{1:~ }|
## grid 3
|
## grid 4
{21: }|
- {22:~ }|
- {22:~ }|
- {22:~ }|
- {22:~ }|
+ {22:~ }|*4
]], float_pos={
- [4] = {{id = 1001}, "SE", 2, 16, 58, true, 50};
+ [4] = {1001, "SE", 2, 16, 58, true, 50};
}}
end)
@@ -1299,48 +625,20 @@ describe('ext_multigrid', function()
feed('A<C-X><C-N>')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
+ |*14
foo bar foo bar foo bar foo bar foo bar foo bar foo bar foo^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
{7:-- Keyword Local completion (^N^P) }{15:match 1 of 2} |
## grid 4
{24: foo}|
{21: bar}|
]], float_pos={
- [4] = {{id = -1}, "NW", 2, 15, 55, false, 100};
+ [4] = {-1, "NW", 2, 15, 55, false, 100};
}}
feed('<C-E><Esc>')
@@ -1348,48 +646,21 @@ describe('ext_multigrid', function()
feed('o<C-X><C-N>')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
+ |*14
rab oof rab oof rab oof rab oof rab oof rab oof rab oof|
^ oof|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*4
## grid 3
{7:-- Keyword Local completion (^N^P) }{15:match 1 of 2} |
## grid 4
{24: oof}|
{21: rab}|
]], float_pos={
- [4] = {{id = -1}, "NW", 2, 16, 45, false, 100};
+ [4] = {-1, "NW", 2, 16, 45, false, 100};
}}
feed('<C-E><Esc>')
@@ -1397,48 +668,21 @@ describe('ext_multigrid', function()
feed(':sign un<Tab>')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
- |
+ |*14
rab oof rab oof rab oof rab oof rab oof rab oof rab oof|
|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*4
## grid 3
:sign undefine^ |
## grid 4
{24: undefine }|
{21: unplace }|
]], float_pos={
- [4] = {{id = -1}, "SW", 1, 13, 5, false, 250};
+ [4] = {-1, "SW", 1, 13, 5, false, 250};
}}
end)
end)
@@ -1448,67 +692,34 @@ describe('ext_multigrid', function()
command('vsp')
screen:expect{grid=[[
## grid 1
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
+ [5:--------------------------]│[4:--------------------------]|*6
{11:[No Name] }{12:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 5
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
feed(":echoerr 'very' | echoerr 'much' | echoerr 'fail'<cr>")
screen:expect{grid=[[
## grid 1
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
+ [5:--------------------------]│[4:--------------------------]|*6
{11:[No Name] }{12:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*3
+ [3:-----------------------------------------------------]|*4
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
{14:very} |
{14:much} |
@@ -1516,59 +727,31 @@ describe('ext_multigrid', function()
{15:Press ENTER or type command to continue}^ |
## grid 4
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 5
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
feed('<cr>')
screen:expect{grid=[[
## grid 1
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
+ [5:--------------------------]│[4:--------------------------]|*6
{11:[No Name] }{12:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 5
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
command([[
@@ -1580,26 +763,10 @@ describe('ext_multigrid', function()
feed(":call ErrMsg()<cr>")
screen:expect{grid=[[
## grid 1
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
+ [3:-----------------------------------------------------]|*14
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
{14:Error detected while processing function ErrMsg:} |
{19:line 2:} |
@@ -1617,59 +784,31 @@ describe('ext_multigrid', function()
{15:Press ENTER or type command to continue}^ |
## grid 4
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 5
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
feed("<c-c>")
screen:expect{grid=[[
## grid 1
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
- [5:--------------------------]│[4:--------------------------]|
+ [5:--------------------------]│[4:--------------------------]|*6
{11:[No Name] }{12:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 5
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
end)
@@ -1677,48 +816,17 @@ describe('ext_multigrid', function()
command('vsp')
screen:expect{grid=[[
## grid 1
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
+ [4:--------------------------]│[2:--------------------------]|*12
{11:[No Name] }{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
]]}
@@ -1727,232 +835,93 @@ describe('ext_multigrid', function()
screen:expect{grid=[[
## grid 1
{16: }{17:2}{16: [No Name] }{7: [No Name] }{12: }{16:X}|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
+ [5:-----------------------------------------------------]|*11
{11:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
## grid 4 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 5
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
]]}
command('sp')
screen:expect{grid=[[
## grid 1
{16: }{17:2}{16: [No Name] }{7: }{18:2}{7: [No Name] }{12: }{16:X}|
- [6:-----------------------------------------------------]|
- [6:-----------------------------------------------------]|
- [6:-----------------------------------------------------]|
- [6:-----------------------------------------------------]|
- [6:-----------------------------------------------------]|
+ [6:-----------------------------------------------------]|*5
{11:[No Name] }|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
+ [5:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
## grid 4 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 5
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 6
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]]}
command('tabnext')
screen:expect{grid=[[
## grid 1
{7: }{18:2}{7: [No Name] }{16: }{17:2}{16: [No Name] }{12: }{16:X}|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
+ [4:--------------------------]│[2:--------------------------]|*11
{11:[No Name] }{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
## grid 5 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 6 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]]}
command('tabnext')
screen:expect{grid=[[
## grid 1
{16: }{17:2}{16: [No Name] }{7: }{18:2}{7: [No Name] }{12: }{16:X}|
- [6:-----------------------------------------------------]|
- [6:-----------------------------------------------------]|
- [6:-----------------------------------------------------]|
- [6:-----------------------------------------------------]|
- [6:-----------------------------------------------------]|
+ [6:-----------------------------------------------------]|*5
{11:[No Name] }|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
- [5:-----------------------------------------------------]|
+ [5:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
## grid 3
|
## grid 4 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
## grid 5
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 6
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]]}
command('tabnext')
@@ -1960,117 +929,43 @@ describe('ext_multigrid', function()
screen:expect{grid=[[
## grid 1
{16: }{17:2}{16: [No Name] }{17:2}{16: [No Name] }{7: [No Name] }{12: }{16:X}|
- [7:-----------------------------------------------------]|
- [7:-----------------------------------------------------]|
- [7:-----------------------------------------------------]|
- [7:-----------------------------------------------------]|
- [7:-----------------------------------------------------]|
- [7:-----------------------------------------------------]|
- [7:-----------------------------------------------------]|
- [7:-----------------------------------------------------]|
- [7:-----------------------------------------------------]|
- [7:-----------------------------------------------------]|
- [7:-----------------------------------------------------]|
+ [7:-----------------------------------------------------]|*11
{11:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
## grid 3
|
## grid 4 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
## grid 5 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 6 (hidden)
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 7
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
]]}
command('tabclose')
command('tabclose')
screen:expect{grid=[[
## grid 1
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
+ [4:--------------------------]│[2:--------------------------]|*12
{11:[No Name] }{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
]]}
end)
@@ -2078,67 +973,27 @@ describe('ext_multigrid', function()
insert('some text\nto be clicked')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicke^d |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
## grid 3
|
]]}
- meths.input_mouse('left', 'press', '', 2, 0, 5)
+ api.nvim_input_mouse('left', 'press', '', 2, 0, 5)
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some ^text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
## grid 3
|
]]}
@@ -2148,128 +1003,75 @@ describe('ext_multigrid', function()
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
## grid 4
Lorem ipsum dolor sit amet, consectetur adipiscing el|
it, sed do eiusm^o |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]]}
- meths.input_mouse('left', 'press', '', 2, 1, 6)
+ api.nvim_input_mouse('left', 'press', '', 2, 1, 6)
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{12:[No Name] [+] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be ^clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
## grid 4
Lorem ipsum dolor sit amet, consectetur adipiscing el|
it, sed do eiusmo |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]]}
- meths.input_mouse('left', 'press', '', 4, 1, 4)
+ api.nvim_input_mouse('left', 'press', '', 4, 1, 4)
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
## grid 4
Lorem ipsum dolor sit amet, consectetur adipiscing el|
it, ^sed do eiusmo |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]]}
screen:try_resize_grid(4, 80, 2)
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
## grid 4
@@ -2277,29 +1079,18 @@ describe('ext_multigrid', function()
{1:~ }|
]]}
- meths.input_mouse('left', 'press', '', 4, 0, 64)
+ api.nvim_input_mouse('left', 'press', '', 4, 0, 64)
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
## grid 4
@@ -2308,36 +1099,23 @@ describe('ext_multigrid', function()
]]}
-- XXX: mouse_check_grid() doesn't work properly when clicking on grid 1
- meths.input_mouse('left', 'press', '', 1, 6, 20)
+ api.nvim_input_mouse('left', 'press', '', 1, 6, 20)
-- TODO(bfredl): "batching" input_mouse is formally not supported yet.
-- Normally it should work fine in async context when nvim is not blocked,
-- but add a poke_eventloop be sure.
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 1, 4, 20)
+ api.nvim_input_mouse('left', 'drag', '', 1, 4, 20)
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{11:[No Name] [+] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*7
{12:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
## grid 4
@@ -2348,28 +1126,15 @@ describe('ext_multigrid', function()
feed('<c-w><c-w><c-w>v')
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{12:[No Name] [+] }|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
- [5:--------------------------]│[2:--------------------------]|
+ [5:--------------------------]│[2:--------------------------]|*7
{11:[No Name] [+] }{12:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
## grid 4
@@ -2378,40 +1143,23 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be ^clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
- meths.input_mouse('left', 'press', '', 1, 8, 26)
+ api.nvim_input_mouse('left', 'press', '', 1, 8, 26)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 1, 6, 30)
+ api.nvim_input_mouse('left', 'drag', '', 1, 6, 30)
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{12:[No Name] [+] }|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*7
{11:[No Name] [+] }{12:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
## grid 4
@@ -2420,41 +1168,24 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be ^clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
command('aunmenu PopUp | vmenu PopUp.Copy y')
- funcs.setreg('"', '')
- meths.input_mouse('left', 'press', '2', 2, 1, 6)
+ fn.setreg('"', '')
+ api.nvim_input_mouse('left', 'press', '2', 2, 1, 6)
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{12:[No Name] [+] }|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*7
{12:[No Name] [+] }{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be {20:clicke}^d |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
{7:-- VISUAL --} |
## grid 4
@@ -2463,38 +1194,21 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be {20:clicked} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
- meths.input_mouse('right', 'press', '', 2, 1, 6)
- meths.input_mouse('right', 'release', '', 2, 1, 6)
+ api.nvim_input_mouse('right', 'press', '', 2, 1, 6)
+ api.nvim_input_mouse('right', 'release', '', 2, 1, 6)
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{12:[No Name] [+] }|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*7
{12:[No Name] [+] }{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be {20:clicke}^d |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
{7:-- VISUAL --} |
## grid 4
@@ -2503,41 +1217,24 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be {20:clicked} |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 6
{21: Copy }|
]], float_pos={
- [6] = {{id = -1}, "NW", 2, 2, 5, false, 250};
+ [6] = {-1, "NW", 2, 2, 5, false, 250};
}}
feed('<Down><CR>')
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{12:[No Name] [+] }|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*7
{12:[No Name] [+] }{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be ^clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
## grid 4
@@ -2546,40 +1243,23 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
- eq('clicked', funcs.getreg('"'))
+ eq('clicked', fn.getreg('"'))
- funcs.setreg('"', '')
- meths.input_mouse('left', 'press', '2', 4, 0, 64)
+ fn.setreg('"', '')
+ api.nvim_input_mouse('left', 'press', '2', 4, 0, 64)
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{11:[No Name] [+] }|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*7
{12:[No Name] [+] [No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
{7:-- VISUAL --} |
## grid 4
@@ -2588,38 +1268,21 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
- meths.input_mouse('right', 'press', '', 4, 0, 64)
- meths.input_mouse('right', 'release', '', 4, 0, 64)
+ api.nvim_input_mouse('right', 'press', '', 4, 0, 64)
+ api.nvim_input_mouse('right', 'release', '', 4, 0, 64)
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{11:[No Name] [+] }|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*7
{12:[No Name] [+] [No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
{7:-- VISUAL --} |
## grid 4
@@ -2628,41 +1291,24 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 6
{21: Copy }|
]], float_pos={
- [6] = {{id = -1}, "NW", 4, 1, 63, false, 250};
+ [6] = {-1, "NW", 4, 1, 63, false, 250};
}}
feed('<Down><CR>')
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{11:[No Name] [+] }|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*7
{12:[No Name] [+] [No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
## grid 4
@@ -2671,38 +1317,23 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]]}
- eq('eiusmo', funcs.getreg('"'))
+ eq('eiusmo', fn.getreg('"'))
command('wincmd J')
screen:try_resize_grid(4, 7, 10)
screen:expect{grid=[[
## grid 1
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*5
{12:[No Name] [+] [No Name] [+] }|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
## grid 4
@@ -2719,35 +1350,22 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
]]}
- funcs.setreg('"', '')
- meths.input_mouse('left', 'press', '2', 4, 9, 1)
+ fn.setreg('"', '')
+ api.nvim_input_mouse('left', 'press', '2', 4, 9, 1)
screen:expect{grid=[[
## grid 1
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*5
{12:[No Name] [+] [No Name] [+] }|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
{7:-- VISUAL --} |
## grid 4
@@ -2764,34 +1382,21 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
]]}
- meths.input_mouse('right', 'press', '', 4, 9, 1)
- meths.input_mouse('right', 'release', '', 4, 9, 1)
+ api.nvim_input_mouse('right', 'press', '', 4, 9, 1)
+ api.nvim_input_mouse('right', 'release', '', 4, 9, 1)
screen:expect{grid=[[
## grid 1
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*5
{12:[No Name] [+] [No Name] [+] }|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
{7:-- VISUAL --} |
## grid 4
@@ -2808,37 +1413,24 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 6
{21: Copy }|
]], float_pos={
- [6] = {{id = -1}, "SW", 4, 9, 0, false, 250};
+ [6] = {-1, "SW", 4, 9, 0, false, 250};
}}
feed('<Down><CR>')
screen:expect{grid=[[
## grid 1
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*5
{12:[No Name] [+] [No Name] [+] }|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
## grid 4
@@ -2855,35 +1447,22 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
]]}
- eq('eiusmo', funcs.getreg('"'))
+ eq('eiusmo', fn.getreg('"'))
screen:try_resize_grid(4, 7, 11)
screen:expect{grid=[[
## grid 1
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*5
{12:[No Name] [+] [No Name] [+] }|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
## grid 4
@@ -2901,35 +1480,22 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
]]}
- funcs.setreg('"', '')
- meths.input_mouse('left', 'press', '2', 4, 9, 1)
+ fn.setreg('"', '')
+ api.nvim_input_mouse('left', 'press', '2', 4, 9, 1)
screen:expect{grid=[[
## grid 1
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*5
{12:[No Name] [+] [No Name] [+] }|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
{7:-- VISUAL --} |
## grid 4
@@ -2947,34 +1513,21 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
]]}
- meths.input_mouse('right', 'press', '', 4, 9, 1)
- meths.input_mouse('right', 'release', '', 4, 9, 1)
+ api.nvim_input_mouse('right', 'press', '', 4, 9, 1)
+ api.nvim_input_mouse('right', 'release', '', 4, 9, 1)
screen:expect{grid=[[
## grid 1
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*5
{12:[No Name] [+] [No Name] [+] }|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
{7:-- VISUAL --} |
## grid 4
@@ -2992,37 +1545,24 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 6
{21: Copy }|
]], float_pos={
- [6] = {{id = -1}, "NW", 4, 10, 0, false, 250};
+ [6] = {-1, "NW", 4, 10, 0, false, 250};
}}
feed('<Down><CR>')
screen:expect{grid=[[
## grid 1
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
- [5:------------------------------]│[2:----------------------]|
+ [5:------------------------------]│[2:----------------------]|*5
{12:[No Name] [+] [No Name] [+] }|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:-----------------------------------------------------]|
## grid 2
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
## grid 4
@@ -3040,11 +1580,9 @@ describe('ext_multigrid', function()
## grid 5
some text |
to be clicked |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
]]}
- eq('eiusmo', funcs.getreg('"'))
+ eq('eiusmo', fn.getreg('"'))
end)
it('supports mouse drag with mouse=a', function()
@@ -3055,54 +1593,29 @@ describe('ext_multigrid', function()
command('enew')
feed('ifoo\nbar<esc>')
- meths.input_mouse('left', 'press', '', 5, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 5, 0, 0)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 5, 1, 2)
+ api.nvim_input_mouse('left', 'drag', '', 5, 1, 2)
screen:expect{grid=[[
## grid 1
- [4:--------------------------]│[5:--------------------------]|
- [4:--------------------------]│[5:--------------------------]|
- [4:--------------------------]│[5:--------------------------]|
- [4:--------------------------]│[5:--------------------------]|
- [4:--------------------------]│[5:--------------------------]|
- [4:--------------------------]│[5:--------------------------]|
+ [4:--------------------------]│[5:--------------------------]|*6
[4:--------------------------]│{11:[No Name] [+] }|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
- [4:--------------------------]│[2:--------------------------]|
+ [4:--------------------------]│[2:--------------------------]|*5
{12:[No Name] [No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
{7:-- VISUAL --} |
## grid 4
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
## grid 5
{20:foo} |
{20:ba}^r |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]]}
end)
@@ -3110,25 +1623,16 @@ describe('ext_multigrid', function()
screen:try_resize(48, 8)
screen:expect{grid=[[
## grid 1
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*6
{11:[No Name] }|
[3:------------------------------------------------]|
## grid 2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
]], win_viewport={
- [2] = {win = { id = 1000 }, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}
}}
insert([[
Lorem ipsum dolor sit amet, consectetur
@@ -3145,12 +1649,7 @@ describe('ext_multigrid', function()
screen:expect{grid=[[
## grid 1
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3163,19 +1662,14 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 5, botline = 11, curline = 10, curcol = 7, linecount = 11, sum_scroll_delta = 5},
+ [2] = {win = 1000, topline = 5, botline = 11, curline = 10, curcol = 7, linecount = 11, sum_scroll_delta = 5},
}}
feed('<c-u>')
screen:expect{grid=[[
## grid 1
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3188,18 +1682,15 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 2, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 2},
+ [2] = {win = 1000, topline = 2, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 2},
}}
command("split")
screen:expect{grid=[[
## grid 1
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
+ [4:------------------------------------------------]|*3
{11:[No Name] [+] }|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*2
{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3212,19 +1703,16 @@ describe('ext_multigrid', function()
reprehenderit in voluptate velit esse cillum |
^dolore eu fugiat nulla pariatur. Excepteur sint |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 6},
- [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 5},
+ [2] = {win = 1000, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 6},
+ [4] = {win = 1001, topline = 5, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 5},
}}
feed("b")
screen:expect{grid=[[
## grid 1
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
+ [4:------------------------------------------------]|*3
{11:[No Name] [+] }|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*2
{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3237,19 +1725,16 @@ describe('ext_multigrid', function()
reprehenderit in voluptate velit esse ^cillum |
dolore eu fugiat nulla pariatur. Excepteur sint |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 6},
- [4] = {win = {id = 1001}, topline = 5, botline = 9, curline = 6, curcol = 38, linecount = 11, sum_scroll_delta = 5},
+ [2] = {win = 1000, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 6},
+ [4] = {win = 1001, topline = 5, botline = 9, curline = 6, curcol = 38, linecount = 11, sum_scroll_delta = 5},
}}
feed("2k")
screen:expect{grid=[[
## grid 1
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
+ [4:------------------------------------------------]|*3
{11:[No Name] [+] }|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*2
{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3262,20 +1747,17 @@ describe('ext_multigrid', function()
ea commodo consequat. Duis aute irure dolor in |
reprehenderit in voluptate velit esse cillum |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 6},
- [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38, linecount = 11, sum_scroll_delta = 4},
+ [2] = {win = 1000, topline = 6, botline = 9, curline = 7, curcol = 0, linecount = 11, sum_scroll_delta = 6},
+ [4] = {win = 1001, topline = 4, botline = 8, curline = 4, curcol = 38, linecount = 11, sum_scroll_delta = 4},
}}
-- handles non-current window
- meths.win_set_cursor(1000, {1, 10})
+ api.nvim_win_set_cursor(1000, {1, 10})
screen:expect{grid=[[
## grid 1
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
+ [4:------------------------------------------------]|*3
{11:[No Name] [+] }|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*2
{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3288,20 +1770,17 @@ describe('ext_multigrid', function()
ea commodo consequat. Duis aute irure dolor in |
reprehenderit in voluptate velit esse cillum |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0},
- [4] = {win = {id = 1001}, topline = 4, botline = 8, curline = 4, curcol = 38, linecount = 11, sum_scroll_delta = 4},
+ [2] = {win = 1000, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0},
+ [4] = {win = 1001, topline = 4, botline = 8, curline = 4, curcol = 38, linecount = 11, sum_scroll_delta = 4},
}}
-- sum_scroll_delta works with folds
feed('zfj')
screen:expect{grid=[[
## grid 1
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
+ [4:------------------------------------------------]|*3
{11:[No Name] [+] }|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*2
{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3314,19 +1793,16 @@ describe('ext_multigrid', function()
reprehenderit in voluptate velit esse cillum |
dolore eu fugiat nulla pariatur. Excepteur sint |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0},
- [4] = {win = {id = 1001}, topline = 4, botline = 9, curline = 4, curcol = 38, linecount = 11, sum_scroll_delta = 4},
+ [2] = {win = 1000, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0},
+ [4] = {win = 1001, topline = 4, botline = 9, curline = 4, curcol = 38, linecount = 11, sum_scroll_delta = 4},
}}
feed('<c-e>')
screen:expect{grid=[[
## grid 1
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
- [4:------------------------------------------------]|
+ [4:------------------------------------------------]|*3
{11:[No Name] [+] }|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*2
{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3339,19 +1815,14 @@ describe('ext_multigrid', function()
dolore eu fugiat nulla pariatur. Excepteur sint |
occaecat cupidatat non proident, sunt in culpa |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0},
- [4] = {win = {id = 1001}, topline = 6, botline = 10, curline = 6, curcol = 0, linecount = 11, sum_scroll_delta = 5},
+ [2] = {win = 1000, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0},
+ [4] = {win = 1001, topline = 6, botline = 10, curline = 6, curcol = 0, linecount = 11, sum_scroll_delta = 5},
}}
command('close | 21vsplit | setlocal number smoothscroll')
screen:expect{grid=[[
## grid 1
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
+ [5:---------------------]│[2:--------------------------]|*6
{11:[No Name] [+] }{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3371,19 +1842,14 @@ describe('ext_multigrid', function()
{19: } sed do eiusmod t|
{19: }empor |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 0, botline = 3, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
}}
feed('5<C-E>')
screen:expect{grid=[[
## grid 1
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
+ [5:---------------------]│[2:--------------------------]|*6
{11:[No Name] [+] }{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3403,19 +1869,14 @@ describe('ext_multigrid', function()
{19: 4 }Ut enim ad minim |
{19: }veniam, quis n{1:@@@}|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 1, botline = 4, curline = 1, curcol = 38, linecount = 11, sum_scroll_delta = 5};
+ [2] = {win = 1000, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 1, botline = 4, curline = 1, curcol = 38, linecount = 11, sum_scroll_delta = 5};
}}
feed('<C-Y>')
screen:expect{grid=[[
## grid 1
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
+ [5:---------------------]│[2:--------------------------]|*6
{11:[No Name] [+] }{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3435,19 +1896,14 @@ describe('ext_multigrid', function()
{19: }na aliqua. |
{19: 4 }Ut enim ad min{1:@@@}|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 1, botline = 4, curline = 1, curcol = 38, linecount = 11, sum_scroll_delta = 4};
+ [2] = {win = 1000, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 1, botline = 4, curline = 1, curcol = 38, linecount = 11, sum_scroll_delta = 4};
}}
command('set cpoptions+=n')
screen:expect{grid=[[
## grid 1
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
+ [5:---------------------]│[2:--------------------------]|*6
{11:[No Name] [+] }{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3467,19 +1923,14 @@ describe('ext_multigrid', function()
liqua. |
{19: 4 }Ut enim ad min{1:@@@}|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 1, botline = 4, curline = 1, curcol = 38, linecount = 11, sum_scroll_delta = 4};
+ [2] = {win = 1000, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 1, botline = 4, curline = 1, curcol = 38, linecount = 11, sum_scroll_delta = 4};
}}
feed('4<C-E>')
screen:expect{grid=[[
## grid 1
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
+ [5:---------------------]│[2:--------------------------]|*6
{11:[No Name] [+] }{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3499,19 +1950,14 @@ describe('ext_multigrid', function()
mco laboris nisi ut a|
liquip ex |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 2, botline = 6, curline = 2, curcol = 43, linecount = 11, sum_scroll_delta = 8};
+ [2] = {win = 1000, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 2, botline = 6, curline = 2, curcol = 43, linecount = 11, sum_scroll_delta = 8};
}}
feed('2<C-Y>')
screen:expect{grid=[[
## grid 1
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
+ [5:---------------------]│[2:--------------------------]|*6
{11:[No Name] [+] }{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3531,19 +1977,14 @@ describe('ext_multigrid', function()
veniam, quis nostrud |
{19: 5 }exercitation u{1:@@@}|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 2, botline = 5, curline = 2, curcol = 43, linecount = 11, sum_scroll_delta = 6};
+ [2] = {win = 1000, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 2, botline = 5, curline = 2, curcol = 43, linecount = 11, sum_scroll_delta = 6};
}}
command('setlocal numberwidth=12')
screen:expect{grid=[[
## grid 1
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
+ [5:---------------------]│[2:--------------------------]|*6
{11:[No Name] [+] }{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3563,19 +2004,14 @@ describe('ext_multigrid', function()
d minim veniam, quis |
nostrud |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 2, botline = 5, curline = 2, curcol = 43, linecount = 11, sum_scroll_delta = 6};
+ [2] = {win = 1000, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 2, botline = 5, curline = 2, curcol = 43, linecount = 11, sum_scroll_delta = 6};
}}
feed('2<C-E>')
screen:expect{grid=[[
## grid 1
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
+ [5:---------------------]│[2:--------------------------]|*6
{11:[No Name] [+] }{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3595,19 +2031,14 @@ describe('ext_multigrid', function()
{19: 5 }exercitat|
ion ullamco labori{1:@@@}|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 2, botline = 5, curline = 2, curcol = 43, linecount = 11, sum_scroll_delta = 8};
+ [2] = {win = 1000, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 2, botline = 5, curline = 2, curcol = 43, linecount = 11, sum_scroll_delta = 8};
}}
feed('<C-E>')
screen:expect{grid=[[
## grid 1
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
- [5:---------------------]│[2:--------------------------]|
+ [5:---------------------]│[2:--------------------------]|*6
{11:[No Name] [+] }{12:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3627,8 +2058,8 @@ describe('ext_multigrid', function()
ion ullamco laboris n|
isi ut aliquip ex |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
- [5] = {win = {id = 1002}, topline = 3, botline = 6, curline = 3, curcol = 36, linecount = 11, sum_scroll_delta = 9};
+ [2] = {win = 1000, topline = 0, botline = 4, curline = 0, curcol = 10, linecount = 11, sum_scroll_delta = 0};
+ [5] = {win = 1002, topline = 3, botline = 6, curline = 3, curcol = 36, linecount = 11, sum_scroll_delta = 9};
}}
end)
@@ -3637,18 +2068,7 @@ describe('ext_multigrid', function()
command('edit test/functional/fixtures/bigfile.txt')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
@@ -3667,23 +2087,12 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 13, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 13, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
}}
feed('G')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
@@ -3702,23 +2111,12 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 30580, botline = 30592, curline = 30591, curcol = 0, linecount = 30592, sum_scroll_delta = 30580};
+ [2] = {win = 1000, topline = 30580, botline = 30592, curline = 30591, curcol = 0, linecount = 30592, sum_scroll_delta = 30580};
}}
feed('gg')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
@@ -3737,23 +2135,12 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 13, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 13, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
}}
command('setlocal wrap')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
@@ -3772,23 +2159,12 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 10, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 10, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
}}
feed('G')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
@@ -3807,23 +2183,12 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 30586, botline = 30592, curline = 30591, curcol = 0, linecount = 30592, sum_scroll_delta = 30588};
+ [2] = {win = 1000, topline = 30586, botline = 30592, curline = 30591, curcol = 0, linecount = 30592, sum_scroll_delta = 30588};
}}
feed('gg')
screen:expect{grid=[[
## grid 1
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*12
{11:test/functional/fixtures/bigfile.txt }|
[3:-----------------------------------------------------]|
## grid 2
@@ -3842,7 +2207,7 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 10, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 10, curline = 0, curcol = 0, linecount = 30592, sum_scroll_delta = 0};
}}
end)
@@ -3850,25 +2215,16 @@ describe('ext_multigrid', function()
screen:try_resize(48, 8)
screen:expect{grid=[[
## grid 1
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*6
{11:[No Name] }|
[3:------------------------------------------------]|
## grid 2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
]], win_viewport={
- [2] = {win = { id = 1000 }, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0}
}}
insert([[
Lorem ipsum dolor sit amet, consectetur
@@ -3885,12 +2241,7 @@ describe('ext_multigrid', function()
screen:expect{grid=[[
## grid 1
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3903,21 +2254,16 @@ describe('ext_multigrid', function()
## grid 3
|
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 5, botline = 11, curline = 10, curcol = 7, linecount = 11, sum_scroll_delta = 5},
+ [2] = {win = 1000, topline = 5, botline = 11, curline = 10, curcol = 7, linecount = 11, sum_scroll_delta = 5},
}}
- meths.input_mouse('left', 'press', '', 1,5, 1)
+ api.nvim_input_mouse('left', 'press', '', 1,5, 1)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 1, 6, 1)
+ api.nvim_input_mouse('left', 'drag', '', 1, 6, 1)
screen:expect{grid=[[
## grid 1
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
- [2:------------------------------------------------]|
+ [2:------------------------------------------------]|*6
{11:[No Name] [+] }|
[3:------------------------------------------------]|
## grid 2
@@ -3930,7 +2276,7 @@ describe('ext_multigrid', function()
## grid 3
{7:-- VISUAL --} |
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 6, botline = 12, curline = 10, curcol = 1, linecount = 11, sum_scroll_delta = 6},
+ [2] = {win = 1000, topline = 6, botline = 12, curline = 10, curcol = 1, linecount = 11, sum_scroll_delta = 6},
}}
end)
@@ -3938,38 +2284,22 @@ describe('ext_multigrid', function()
command('split')
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
-- XXX: hack to get notifications. Could use next_msg() also.
@@ -3983,256 +2313,155 @@ describe('ext_multigrid', function()
command('setlocal winbar=very%=bar')
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
{7:very bar}|
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
eq({}, win_pos)
command('setlocal winbar=')
screen:expect{grid=[[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
- [4] = {win = {id = 1001}, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [2] = {win = 1000, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
+ [4] = {win = 1001, topline = 0, botline = 2, curline = 0, curcol = 0, linecount = 1, sum_scroll_delta = 0};
}}
eq({}, win_pos)
end)
it('with winbar dragging statusline with mouse works correctly', function()
- meths.set_option_value('winbar', 'Set Up The Bars', {})
+ api.nvim_set_option_value('winbar', 'Set Up The Bars', {})
command('split')
screen:expect([[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*6
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
{7:Set Up The Bars }|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
|
## grid 4
{7:Set Up The Bars }|
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
]])
- meths.input_mouse('left', 'press', '', 1, 6, 20)
+ api.nvim_input_mouse('left', 'press', '', 1, 6, 20)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 1, 7, 20)
+ api.nvim_input_mouse('left', 'drag', '', 1, 7, 20)
screen:expect([[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*7
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*4
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
{7:Set Up The Bars }|
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
|
## grid 4
{7:Set Up The Bars }|
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
]])
- meths.input_mouse('left', 'drag', '', 1, 4, 20)
+ api.nvim_input_mouse('left', 'drag', '', 1, 4, 20)
screen:expect([[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*7
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
{7:Set Up The Bars }|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
## grid 4
{7:Set Up The Bars }|
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
]])
- meths.input_mouse('left', 'press', '', 1, 12, 10)
+ api.nvim_input_mouse('left', 'press', '', 1, 12, 10)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 1, 10, 10)
+ api.nvim_input_mouse('left', 'drag', '', 1, 10, 10)
screen:expect([[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*5
{12:[No Name] }|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
- [3:-----------------------------------------------------]|
+ [3:-----------------------------------------------------]|*3
## grid 2
{7:Set Up The Bars }|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
- |
- |
- |
+ |*3
## grid 4
{7:Set Up The Bars }|
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
]])
- eq(3, meths.get_option_value('cmdheight', {}))
+ eq(3, api.nvim_get_option_value('cmdheight', {}))
- meths.input_mouse('left', 'drag', '', 1, 12, 10)
+ api.nvim_input_mouse('left', 'drag', '', 1, 12, 10)
screen:expect([[
## grid 1
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
- [4:-----------------------------------------------------]|
+ [4:-----------------------------------------------------]|*4
{11:[No Name] }|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
- [2:-----------------------------------------------------]|
+ [2:-----------------------------------------------------]|*7
{12:[No Name] }|
[3:-----------------------------------------------------]|
## grid 2
{7:Set Up The Bars }|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
## grid 3
|
## grid 4
{7:Set Up The Bars }|
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
]])
- eq(1, meths.get_option_value('cmdheight', {}))
+ eq(1, api.nvim_get_option_value('cmdheight', {}))
end)
end)
diff --git a/test/functional/ui/options_spec.lua b/test/functional/ui/options_spec.lua
index 2c649709c6..98af82a7c5 100644
--- a/test/functional/ui/options_spec.lua
+++ b/test/functional/ui/options_spec.lua
@@ -9,45 +9,48 @@ local eval = helpers.eval
describe('UI receives option updates', function()
local screen
- local function reset(opts, ...)
+ local function reset(screen_opts, clear_opts)
local defaults = {
- ambiwidth='single',
- arabicshape=true,
- emoji=true,
- guifont='',
- guifontwide='',
- linespace=0,
- pumblend=0,
- mousefocus=false,
- mousehide=true,
- mousemoveevent=false,
- showtabline=1,
- termguicolors=false,
- termsync=true,
- ttimeout=true,
- ttimeoutlen=50,
- verbose=0,
- ext_cmdline=false,
- ext_popupmenu=false,
- ext_tabline=false,
- ext_wildmenu=false,
- ext_linegrid=false,
- ext_hlstate=false,
- ext_multigrid=false,
- ext_messages=false,
- ext_termcolors=false,
+ ambiwidth = 'single',
+ arabicshape = true,
+ emoji = true,
+ guifont = '',
+ guifontwide = '',
+ linespace = 0,
+ pumblend = 0,
+ mousefocus = false,
+ mousehide = true,
+ mousemoveevent = false,
+ showtabline = 1,
+ termguicolors = false,
+ termsync = true,
+ ttimeout = true,
+ ttimeoutlen = 50,
+ verbose = 0,
+ ext_cmdline = false,
+ ext_popupmenu = false,
+ ext_tabline = false,
+ ext_wildmenu = false,
+ ext_linegrid = false,
+ ext_hlstate = false,
+ ext_multigrid = false,
+ ext_messages = false,
+ ext_termcolors = false,
}
- clear(...)
- screen = Screen.new(20,5)
- screen:attach(opts)
+ clear_opts = shallowcopy(clear_opts or {})
+ clear_opts.args_rm = clear_opts.args_rm or {}
+ table.insert(clear_opts.args_rm or {}, '--cmd')
+ clear(clear_opts)
+ screen = Screen.new(20, 5)
+ screen:attach(screen_opts)
-- NB: UI test suite can be run in both "linegrid" and legacy grid mode.
-- In both cases check that the received value is the one requested.
defaults.ext_linegrid = screen._options.ext_linegrid or false
return defaults
end
- it("for defaults", function()
+ it('for defaults', function()
local expected = reset()
screen:expect(function()
eq(expected, screen.options)
@@ -55,9 +58,9 @@ describe('UI receives option updates', function()
end)
it('on attach #11372', function()
- clear{args_rm={'--headless'}}
+ clear { args_rm = { '--headless' } }
local evs = {}
- screen = Screen.new(20,5)
+ screen = Screen.new(20, 5)
-- Override mouse_on/mouse_off handlers.
function screen:_handle_mouse_on()
table.insert(evs, 'mouse_on')
@@ -67,109 +70,109 @@ describe('UI receives option updates', function()
end
screen:attach()
screen:expect(function()
- eq({'mouse_on'}, evs)
+ eq({ 'mouse_on' }, evs)
end)
- command("set mouse=")
+ command('set mouse=')
screen:expect(function()
- eq({'mouse_on', 'mouse_off'}, evs)
+ eq({ 'mouse_on', 'mouse_off' }, evs)
end)
- command("set mouse&")
+ command('set mouse&')
screen:expect(function()
- eq({'mouse_on', 'mouse_off', 'mouse_on'}, evs)
+ eq({ 'mouse_on', 'mouse_off', 'mouse_on' }, evs)
end)
screen:detach()
- eq({'mouse_on', 'mouse_off', 'mouse_on'}, evs)
+ eq({ 'mouse_on', 'mouse_off', 'mouse_on' }, evs)
screen:attach()
screen:expect(function()
- eq({'mouse_on', 'mouse_off', 'mouse_on', 'mouse_on'}, evs)
+ eq({ 'mouse_on', 'mouse_off', 'mouse_on', 'mouse_on' }, evs)
end)
end)
- it("when setting options", function()
+ it('when setting options', function()
local expected = reset()
local defaults = shallowcopy(expected)
- command("set termguicolors")
+ command('set termguicolors')
expected.termguicolors = true
screen:expect(function()
eq(expected, screen.options)
end)
- command("set pumblend=50")
+ command('set pumblend=50')
expected.pumblend = 50
screen:expect(function()
- eq(expected, screen.options)
+ eq(expected, screen.options)
end)
-- check handling of out-of-bounds value
- command("set pumblend=-1")
+ command('set pumblend=-1')
expected.pumblend = 0
screen:expect(function()
- eq(expected, screen.options)
+ eq(expected, screen.options)
end)
- command("set guifont=Comic\\ Sans")
- expected.guifont = "Comic Sans"
+ command('set guifont=Comic\\ Sans')
+ expected.guifont = 'Comic Sans'
screen:expect(function()
eq(expected, screen.options)
end)
- command("set showtabline=0")
+ command('set showtabline=0')
expected.showtabline = 0
screen:expect(function()
eq(expected, screen.options)
end)
- command("set linespace=13")
+ command('set linespace=13')
expected.linespace = 13
screen:expect(function()
eq(expected, screen.options)
end)
- command("set linespace=-11")
+ command('set linespace=-11')
expected.linespace = -11
screen:expect(function()
eq(expected, screen.options)
end)
- command("set mousefocus")
+ command('set mousefocus')
expected.mousefocus = true
screen:expect(function()
eq(expected, screen.options)
end)
- command("set nomousehide")
+ command('set nomousehide')
expected.mousehide = false
screen:expect(function()
eq(expected, screen.options)
end)
- command("set mousemoveevent")
+ command('set mousemoveevent')
expected.mousemoveevent = true
screen:expect(function()
eq(expected, screen.options)
end)
- command("set nottimeout")
+ command('set nottimeout')
expected.ttimeout = false
screen:expect(function()
eq(expected, screen.options)
end)
- command("set ttimeoutlen=100")
+ command('set ttimeoutlen=100')
expected.ttimeoutlen = 100
screen:expect(function()
eq(expected, screen.options)
end)
- command("set all&")
+ command('set all&')
screen:expect(function()
eq(defaults, screen.options)
end)
end)
it('with UI extensions', function()
- local expected = reset({ext_cmdline=true, ext_wildmenu=true})
+ local expected = reset({ ext_cmdline = true, ext_wildmenu = true })
expected.ext_cmdline = true
expected.ext_wildmenu = true
@@ -191,37 +194,43 @@ describe('UI receives option updates', function()
end)
local function startup_test(headless)
- local expected = reset(nil, {args_rm=(headless and {} or {'--headless'}),
- args={'--cmd', 'set guifont=Comic\\ Sans\\ 12'}})
- expected.guifont = "Comic Sans 12"
+ local expected = reset(nil, {
+ args_rm = (headless and {} or { '--headless' }),
+ args = { '--cmd', 'set guifont=Comic\\ Sans\\ 12' },
+ })
+ expected.guifont = 'Comic Sans 12'
screen:expect(function()
eq(expected, screen.options)
end)
end
- it('from startup options with --headless', function() startup_test(true) end)
- it('from startup options with --embed', function() startup_test(false) end)
+ it('from startup options with --headless', function()
+ startup_test(true)
+ end)
+ it('from startup options with --embed', function()
+ startup_test(false)
+ end)
end)
describe('UI can set terminal option', function()
local screen
before_each(function()
-- by default we implicitly "--cmd 'set bg=light'" which ruins everything
- clear{args_rm={'--cmd'}}
- screen = Screen.new(20,5)
+ clear { args_rm = { '--cmd' } }
+ screen = Screen.new(20, 5)
end)
it('term_name', function()
eq('nvim', eval '&term')
- screen:attach {term_name='xterm'}
+ screen:attach { term_name = 'xterm' }
eq('xterm', eval '&term')
end)
it('term_colors', function()
eq('256', eval '&t_Co')
- screen:attach {term_colors=8}
+ screen:attach { term_colors = 8 }
eq('8', eval '&t_Co')
end)
end)
diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua
index 7b93b74eac..5e340af89c 100644
--- a/test/functional/ui/output_spec.lua
+++ b/test/functional/ui/output_spec.lua
@@ -15,38 +15,42 @@ local set_shell_powershell = helpers.set_shell_powershell
local skip = helpers.skip
local is_os = helpers.is_os
-clear() -- for has_powershell()
+clear() -- for has_powershell()
-describe("shell command :!", function()
+describe('shell command :!', function()
local screen
before_each(function()
clear()
- screen = child_session.screen_setup(0, '["'..helpers.nvim_prog..
- '", "-u", "NONE", "-i", "NONE", "--cmd", "'..helpers.nvim_set..'"]')
+ screen = child_session.setup_child_nvim({
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--cmd',
+ 'colorscheme vim',
+ '--cmd',
+ helpers.nvim_set .. ' notermguicolors',
+ })
screen:expect([[
{1: } |
- {4:~ }|
- {4:~ }|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*4
|
{3:-- TERMINAL --} |
]])
end)
after_each(function()
- child_session.feed_data("\3") -- Ctrl-C
+ child_session.feed_data('\3') -- Ctrl-C
end)
- it("displays output without LF/EOF. #4646 #4569 #3772", function()
+ it('displays output without LF/EOF. #4646 #4569 #3772', function()
skip(is_os('win'))
-- NOTE: We use a child nvim (within a :term buffer)
-- to avoid triggering a UI flush.
- child_session.feed_data(":!printf foo; sleep 200\n")
+ child_session.feed_data(':!printf foo; sleep 200\n')
screen:expect([[
|
- {4:~ }|
- {4:~ }|
+ {4:~ }|*2
{5: }|
:!printf foo; sleep 200 |
foo |
@@ -54,18 +58,19 @@ describe("shell command :!", function()
]])
end)
- it("throttles shell-command output greater than ~10KB", function()
+ it('throttles shell-command output greater than ~10KB', function()
skip(is_os('openbsd'), 'FIXME #10804')
skip(is_os('win'))
- child_session.feed_data((":!%s REP 30001 foo\n"):format(testprg('shell-test')))
+ child_session.feed_data((':!%s REP 30001 foo\n'):format(testprg('shell-test')))
-- If we observe any line starting with a dot, then throttling occurred.
-- Avoid false failure on slow systems.
- screen:expect{any="\n%.", timeout=20000}
+ screen:expect { any = '\n%.', timeout = 20000 }
-- Final chunk of output should always be displayed, never skipped.
-- (Throttling is non-deterministic, this test is merely a sanity check.)
- screen:expect([[
+ screen:expect(
+ [[
29997: foo |
29998: foo |
29999: foo |
@@ -73,27 +78,29 @@ describe("shell command :!", function()
|
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |
- ]], {
- -- test/functional/helpers.lua defaults to background=light.
- [1] = {reverse = true},
- [3] = {bold = true},
- [10] = {foreground = 2},
- })
+ ]],
+ {
+ -- test/functional/helpers.lua defaults to background=light.
+ [1] = { reverse = true },
+ [3] = { bold = true },
+ [10] = { foreground = 2 },
+ }
+ )
end)
end)
-describe("shell command :!", function()
+describe('shell command :!', function()
before_each(function()
clear()
end)
- it("cat a binary file #4142", function()
+ it('cat a binary file #4142', function()
feed(":exe 'silent !cat '.shellescape(v:progpath)<CR>")
assert_alive()
end)
it([[display \x08 char #4142]], function()
- feed(":silent !echo \08<CR>")
+ feed(':silent !echo \08<CR>')
assert_alive()
end)
@@ -101,32 +108,37 @@ describe("shell command :!", function()
skip(is_os('win'), 'missing printf')
local screen = Screen.new(50, 4)
screen:set_default_attr_ids {
- [1] = {bold = true, reverse = true};
- [2] = {bold = true, foreground = Screen.colors.SeaGreen};
- [3] = {foreground = Screen.colors.Blue};
+ [1] = { bold = true, reverse = true },
+ [2] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [3] = { foreground = Screen.colors.Blue },
}
screen:attach()
-- Print TAB chars. #2958
feed([[:!printf '1\t2\t3'<CR>]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }|
:!printf '1\t2\t3' |
1 2 3 |
{2:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed([[<CR>]])
-- Print BELL control code. #4338
screen.bell = false
feed([[:!printf '\007\007\007\007text'<CR>]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }|
:!printf '\007\007\007\007text' |
text |
{2:Press ENTER or type command to continue}^ |
- ]], condition=function()
- eq(true, screen.bell)
- end}
+ ]],
+ condition = function()
+ eq(true, screen.bell)
+ end,
+ }
feed([[<CR>]])
-- Print BS control code.
@@ -143,8 +155,7 @@ describe("shell command :!", function()
feed([[:!printf '\n'<CR>]])
screen:expect([[
:!printf '\n' |
- |
- |
+ |*2
{2:Press ENTER or type command to continue}^ |
]])
feed([[<CR>]])
@@ -158,12 +169,12 @@ describe("shell command :!", function()
write_file('bang_filter_spec/f1', 'f1')
write_file('bang_filter_spec/f2', 'f2')
write_file('bang_filter_spec/f3', 'f3')
- screen = Screen.new(53,10)
+ screen = Screen.new(53, 10)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Blue1},
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [4] = {bold = true, reverse = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Blue1 },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [4] = { bold = true, reverse = true },
})
screen:attach()
end)
@@ -173,19 +184,19 @@ describe("shell command :!", function()
end)
it("doesn't truncate Last line of shell output #3269", function()
- command(is_os('win')
- and [[nnoremap <silent>\l :!dir /b bang_filter_spec<cr>]]
- or [[nnoremap <silent>\l :!ls bang_filter_spec<cr>]])
- local result = (is_os('win')
- and [[:!dir /b bang_filter_spec]]
- or [[:!ls bang_filter_spec ]])
+ command(
+ is_os('win') and [[nnoremap <silent>\l :!dir /b bang_filter_spec<cr>]]
+ or [[nnoremap <silent>\l :!ls bang_filter_spec<cr>]]
+ )
+ local result = (
+ is_os('win') and [[:!dir /b bang_filter_spec]] or [[:!ls bang_filter_spec ]]
+ )
feed([[\l]])
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{4: }|
- ]]..result..[[ |
+ ]] .. result .. [[ |
f1 |
f2 |
f3 |
@@ -197,7 +208,8 @@ describe("shell command :!", function()
it('handles binary and multibyte data', function()
feed_command('!cat test/functional/fixtures/shell_data.txt')
screen.bell = false
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
{1:~ }|
{4: }|
@@ -208,20 +220,22 @@ describe("shell command :!", function()
t {2:<ff>} |
|
{3:Press ENTER or type command to continue}^ |
- ]], condition=function()
- eq(true, screen.bell)
- end}
+ ]],
+ condition = function()
+ eq(true, screen.bell)
+ end,
+ }
end)
it('handles multibyte sequences split over buffer boundaries', function()
- command('cd '..nvim_dir)
+ command('cd ' .. nvim_dir)
local cmd = is_os('win') and '!shell-test UTF-8 ' or '!./shell-test UTF-8'
feed_command(cmd)
-- Note: only the first example of split composed char works
screen:expect([[
|
{4: }|
- :]]..cmd..[[ |
+ :]] .. cmd .. [[ |
Ã¥ |
ref: å̲ |
1: å̲ |
diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua
index a6cd216d84..1f0d20f66d 100644
--- a/test/functional/ui/popupmenu_spec.lua
+++ b/test/functional/ui/popupmenu_spec.lua
@@ -4,10 +4,10 @@ local assert_alive = helpers.assert_alive
local clear, feed = helpers.clear, helpers.feed
local source = helpers.source
local insert = helpers.insert
-local meths = helpers.meths
+local api = helpers.api
local async_meths = helpers.async_meths
local command = helpers.command
-local funcs = helpers.funcs
+local fn = helpers.fn
local eq = helpers.eq
local pcall_err = helpers.pcall_err
local exec_lua = helpers.exec_lua
@@ -18,16 +18,16 @@ describe('ui/ext_popupmenu', function()
before_each(function()
clear()
screen = Screen.new(60, 8)
- screen:attach({rgb=true, ext_popupmenu=true})
+ screen:attach({ rgb = true, ext_popupmenu = true })
screen:set_default_attr_ids({
- [1] = {bold=true, foreground=Screen.colors.Blue},
- [2] = {bold = true},
- [3] = {reverse = true},
- [4] = {bold = true, reverse = true},
- [5] = {bold = true, foreground = Screen.colors.SeaGreen},
- [6] = {background = Screen.colors.WebGray},
- [7] = {background = Screen.colors.LightMagenta},
- [8] = {foreground = Screen.colors.Red},
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { bold = true },
+ [3] = { reverse = true },
+ [4] = { bold = true, reverse = true },
+ [5] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [6] = { background = Screen.colors.WebGray },
+ [7] = { background = Screen.colors.LightMagenta },
+ [8] = { foreground = Screen.colors.Red },
})
source([[
function! TestComplete() abort
@@ -38,447 +38,399 @@ describe('ui/ext_popupmenu', function()
end)
local expected = {
- {'fo', 'x', 'the foo', 'foo-y'},
- {'bar', '', '', ''},
- {'spam', '', '', ''},
+ { 'fo', 'x', 'the foo', 'foo-y' },
+ { 'bar', '', '', '' },
+ { 'spam', '', '', '' },
}
it('works', function()
feed('o<C-r>=TestComplete()<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
foo^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=0,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = 0,
+ anchor = { 1, 1, 0 },
+ },
+ }
feed('<c-p>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=-1,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = -1,
+ anchor = { 1, 1, 0 },
+ },
+ }
-- down moves the selection in the menu, but does not insert anything
feed('<down><down>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=1,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = 1,
+ anchor = { 1, 1, 0 },
+ },
+ }
feed('<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
bar^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]]}
+ ]],
+ }
end)
it('can be controlled by API', function()
feed('o<C-r>=TestComplete()<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
foo^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=0,
- anchor={1,1,0},
- }}
-
- meths.select_popupmenu_item(1,false,false,{})
- screen:expect{grid=[[
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = 0,
+ anchor = { 1, 1, 0 },
+ },
+ }
+
+ api.nvim_select_popupmenu_item(1, false, false, {})
+ screen:expect {
+ grid = [[
|
foo^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=1,
- anchor={1,1,0},
- }}
-
- meths.select_popupmenu_item(2,true,false,{})
- screen:expect{grid=[[
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = 1,
+ anchor = { 1, 1, 0 },
+ },
+ }
+
+ api.nvim_select_popupmenu_item(2, true, false, {})
+ screen:expect {
+ grid = [[
|
spam^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=2,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = 2,
+ anchor = { 1, 1, 0 },
+ },
+ }
- meths.select_popupmenu_item(0,true,true,{})
+ api.nvim_select_popupmenu_item(0, true, true, {})
screen:expect([[
|
foo^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
]])
-
feed('<c-w><C-r>=TestComplete()<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
foo^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=0,
- anchor={1,1,0},
- }}
-
- meths.select_popupmenu_item(-1,false,false,{})
- screen:expect{grid=[[
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = 0,
+ anchor = { 1, 1, 0 },
+ },
+ }
+
+ api.nvim_select_popupmenu_item(-1, false, false, {})
+ screen:expect {
+ grid = [[
|
foo^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=-1,
- anchor={1,1,0},
- }}
-
- meths.select_popupmenu_item(1,true,false,{})
- screen:expect{grid=[[
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = -1,
+ anchor = { 1, 1, 0 },
+ },
+ }
+
+ api.nvim_select_popupmenu_item(1, true, false, {})
+ screen:expect {
+ grid = [[
|
bar^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=1,
- anchor={1,1,0},
- }}
-
- meths.select_popupmenu_item(-1,true,false,{})
- screen:expect{grid=[[
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = 1,
+ anchor = { 1, 1, 0 },
+ },
+ }
+
+ api.nvim_select_popupmenu_item(-1, true, false, {})
+ screen:expect {
+ grid = [[
|
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=-1,
- anchor={1,1,0},
- }}
-
- meths.select_popupmenu_item(0,true,false,{})
- screen:expect{grid=[[
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = -1,
+ anchor = { 1, 1, 0 },
+ },
+ }
+
+ api.nvim_select_popupmenu_item(0, true, false, {})
+ screen:expect {
+ grid = [[
|
foo^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=0,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = 0,
+ anchor = { 1, 1, 0 },
+ },
+ }
- meths.select_popupmenu_item(-1,true,true,{})
+ api.nvim_select_popupmenu_item(-1, true, true, {})
screen:expect([[
|
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
]])
command('set wildmenu')
command('set wildoptions=pum')
local expected_wildpum = {
- { "define", "", "", "" },
- { "jump", "", "", "" },
- { "list", "", "", "" },
- { "place", "", "", "" },
- { "undefine", "", "", "" },
- { "unplace", "", "", "" },
+ { 'define', '', '', '' },
+ { 'jump', '', '', '' },
+ { 'list', '', '', '' },
+ { 'place', '', '', '' },
+ { 'undefine', '', '', '' },
+ { 'unplace', '', '', '' },
}
feed('<Esc>:sign <Tab>')
- screen:expect({grid = [[
- |
- |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ screen:expect({
+ grid = [[
+ |*2
+ {1:~ }|*5
:sign define^ |
- ]], popupmenu = {
- items = expected_wildpum,
- pos = 0,
- anchor = { 1, 7, 6 },
- }})
-
- meths.select_popupmenu_item(-1, true, false, {})
- screen:expect({grid = [[
- |
- |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ ]],
+ popupmenu = {
+ items = expected_wildpum,
+ pos = 0,
+ anchor = { 1, 7, 6 },
+ },
+ })
+
+ api.nvim_select_popupmenu_item(-1, true, false, {})
+ screen:expect({
+ grid = [[
+ |*2
+ {1:~ }|*5
:sign ^ |
- ]], popupmenu = {
- items = expected_wildpum,
- pos = -1,
- anchor = { 1, 7, 6 },
- }})
-
- meths.select_popupmenu_item(5, true, false, {})
- screen:expect({grid = [[
- |
- |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ ]],
+ popupmenu = {
+ items = expected_wildpum,
+ pos = -1,
+ anchor = { 1, 7, 6 },
+ },
+ })
+
+ api.nvim_select_popupmenu_item(5, true, false, {})
+ screen:expect({
+ grid = [[
+ |*2
+ {1:~ }|*5
:sign unplace^ |
- ]], popupmenu = {
- items = expected_wildpum,
- pos = 5,
- anchor = { 1, 7, 6 },
- }})
-
- meths.select_popupmenu_item(-1, true, true, {})
- screen:expect({grid = [[
- |
- |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ ]],
+ popupmenu = {
+ items = expected_wildpum,
+ pos = 5,
+ anchor = { 1, 7, 6 },
+ },
+ })
+
+ api.nvim_select_popupmenu_item(-1, true, true, {})
+ screen:expect({
+ grid = [[
+ |*2
+ {1:~ }|*5
:sign ^ |
- ]]})
+ ]],
+ })
feed('<Tab>')
- screen:expect({grid = [[
- |
- |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ screen:expect({
+ grid = [[
+ |*2
+ {1:~ }|*5
:sign define^ |
- ]], popupmenu = {
- items = expected_wildpum,
- pos = 0,
- anchor = { 1, 7, 6 },
- }})
-
- meths.select_popupmenu_item(5, true, true, {})
- screen:expect({grid = [[
- |
- |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ ]],
+ popupmenu = {
+ items = expected_wildpum,
+ pos = 0,
+ anchor = { 1, 7, 6 },
+ },
+ })
+
+ api.nvim_select_popupmenu_item(5, true, true, {})
+ screen:expect({
+ grid = [[
+ |*2
+ {1:~ }|*5
:sign unplace^ |
- ]]})
+ ]],
+ })
local function test_pum_select_mappings()
screen:set_option('ext_popupmenu', true)
feed('<Esc>A<C-r>=TestComplete()<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
foo^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=0,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = 0,
+ anchor = { 1, 1, 0 },
+ },
+ }
feed('<f1>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
spam^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=2,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = 2,
+ anchor = { 1, 1, 0 },
+ },
+ }
feed('<f2>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
spam^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=-1,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = -1,
+ anchor = { 1, 1, 0 },
+ },
+ }
feed('<f3>')
screen:expect([[
|
bar^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
]])
feed('<Esc>:sign <Tab>')
- screen:expect({grid = [[
+ screen:expect({
+ grid = [[
|
bar |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:sign define^ |
- ]], popupmenu = {
- items = expected_wildpum,
- pos = 0,
- anchor = { 1, 7, 6 },
- }})
+ ]],
+ popupmenu = {
+ items = expected_wildpum,
+ pos = 0,
+ anchor = { 1, 7, 6 },
+ },
+ })
feed('<f1>')
- screen:expect({grid = [[
+ screen:expect({
+ grid = [[
|
bar |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:sign list^ |
- ]], popupmenu = {
- items = expected_wildpum,
- pos = 2,
- anchor = { 1, 7, 6 },
- }})
+ ]],
+ popupmenu = {
+ items = expected_wildpum,
+ pos = 2,
+ anchor = { 1, 7, 6 },
+ },
+ })
feed('<f2>')
- screen:expect({grid = [[
+ screen:expect({
+ grid = [[
|
bar |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:sign ^ |
- ]], popupmenu = {
- items = expected_wildpum,
- pos = -1,
- anchor = { 1, 7, 6 },
- }})
+ ]],
+ popupmenu = {
+ items = expected_wildpum,
+ pos = -1,
+ anchor = { 1, 7, 6 },
+ },
+ })
feed('<f3>')
- screen:expect({grid = [[
+ screen:expect({
+ grid = [[
|
bar |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:sign jump^ |
- ]]})
+ ]],
+ })
-- also should work for builtin popupmenu
screen:set_option('ext_popupmenu', false)
@@ -489,8 +441,7 @@ describe('ui/ext_popupmenu', function()
{6:fo x the foo }{1: }|
{7:bar }{1: }|
{7:spam }{1: }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:-- INSERT --} |
]])
@@ -501,8 +452,7 @@ describe('ui/ext_popupmenu', function()
{7:fo x the foo }{1: }|
{7:bar }{1: }|
{6:spam }{1: }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:-- INSERT --} |
]])
@@ -513,8 +463,7 @@ describe('ui/ext_popupmenu', function()
{7:fo x the foo }{1: }|
{7:bar }{1: }|
{7:spam }{1: }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:-- INSERT --} |
]])
@@ -522,11 +471,7 @@ describe('ui/ext_popupmenu', function()
screen:expect([[
|
bar^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
]])
@@ -570,11 +515,7 @@ describe('ui/ext_popupmenu', function()
screen:expect([[
|
bar |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:sign jump^ |
]])
end
@@ -602,8 +543,7 @@ describe('ui/ext_popupmenu', function()
{6:aa }{1: }|
{7:bb }{1: }|
{7:cc }{1: }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:-- Keyword Local completion (^N^P) }{5:match 1 of 3} |
]])
@@ -614,8 +554,7 @@ describe('ui/ext_popupmenu', function()
{7:aa }{1: }|
{7:bb }{1: }|
{6:cc }{1: }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:-- Keyword Local completion (^N^P) }{5:match 3 of 3} |
]])
@@ -626,8 +565,7 @@ describe('ui/ext_popupmenu', function()
{7:aa }{1: }|
{7:bb }{1: }|
{7:cc }{1: }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:-- Keyword Local completion (^N^P) }{8:Back at original} |
]])
@@ -635,11 +573,7 @@ describe('ui/ext_popupmenu', function()
screen:expect([[
aa bb cc |
bb^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
]])
end)
@@ -659,52 +593,49 @@ describe('ui/ext_popupmenu', function()
it('can set pum height', function()
source_complete_month()
local month_expected = {
- {'January', '', '', ''},
- {'February', '', '', ''},
- {'March', '', '', ''},
- {'April', '', '', ''},
- {'May', '', '', ''},
- {'June', '', '', ''},
- {'July', '', '', ''},
- {'August', '', '', ''},
- {'September', '', '', ''},
- {'October', '', '', ''},
- {'November', '', '', ''},
- {'December', '', '', ''},
+ { 'January', '', '', '' },
+ { 'February', '', '', '' },
+ { 'March', '', '', '' },
+ { 'April', '', '', '' },
+ { 'May', '', '', '' },
+ { 'June', '', '', '' },
+ { 'July', '', '', '' },
+ { 'August', '', '', '' },
+ { 'September', '', '', '' },
+ { 'October', '', '', '' },
+ { 'November', '', '', '' },
+ { 'December', '', '', '' },
}
local pum_height = 6
feed('o<C-r>=TestCompleteMonth()<CR>')
- meths.ui_pum_set_height(pum_height)
+ api.nvim_ui_pum_set_height(pum_height)
feed('<PageDown>')
-- pos becomes pum_height-2 because it is subtracting 2 to keep some
-- context in ins_compl_key2count()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
January^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=month_expected,
- pos=pum_height-2,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = month_expected,
+ pos = pum_height - 2,
+ anchor = { 1, 1, 0 },
+ },
+ }
end)
it('an error occurs if set 0 or less', function()
- meths.ui_pum_set_height(1)
- eq('Expected pum height > 0',
- pcall_err(meths.ui_pum_set_height, 0))
+ api.nvim_ui_pum_set_height(1)
+ eq('Expected pum height > 0', pcall_err(api.nvim_ui_pum_set_height, 0))
end)
it('an error occurs when ext_popupmenu is false', function()
- meths.ui_pum_set_height(1)
+ api.nvim_ui_pum_set_height(1)
screen:set_option('ext_popupmenu', false)
- eq('It must support the ext_popupmenu option',
- pcall_err(meths.ui_pum_set_height, 1))
+ eq('It must support the ext_popupmenu option', pcall_err(api.nvim_ui_pum_set_height, 1))
end)
end)
@@ -712,239 +643,205 @@ describe('ui/ext_popupmenu', function()
it('can set pum bounds', function()
source_complete_month()
local month_expected = {
- {'January', '', '', ''},
- {'February', '', '', ''},
- {'March', '', '', ''},
- {'April', '', '', ''},
- {'May', '', '', ''},
- {'June', '', '', ''},
- {'July', '', '', ''},
- {'August', '', '', ''},
- {'September', '', '', ''},
- {'October', '', '', ''},
- {'November', '', '', ''},
- {'December', '', '', ''},
+ { 'January', '', '', '' },
+ { 'February', '', '', '' },
+ { 'March', '', '', '' },
+ { 'April', '', '', '' },
+ { 'May', '', '', '' },
+ { 'June', '', '', '' },
+ { 'July', '', '', '' },
+ { 'August', '', '', '' },
+ { 'September', '', '', '' },
+ { 'October', '', '', '' },
+ { 'November', '', '', '' },
+ { 'December', '', '', '' },
}
local pum_height = 6
feed('o<C-r>=TestCompleteMonth()<CR>')
- meths.ui_pum_set_height(pum_height)
+ api.nvim_ui_pum_set_height(pum_height)
-- set bounds w h r c
- meths.ui_pum_set_bounds(10.5, 5.2, 6.3, 7.4)
+ api.nvim_ui_pum_set_bounds(10.5, 5.2, 6.3, 7.4)
feed('<PageDown>')
-- pos becomes pum_height-2 because it is subtracting 2 to keep some
-- context in ins_compl_key2count()
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
January^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=month_expected,
- pos=pum_height-2,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = month_expected,
+ pos = pum_height - 2,
+ anchor = { 1, 1, 0 },
+ },
+ }
end)
it('no error occurs if row or col set less than 0', function()
- meths.ui_pum_set_bounds(1.0, 1.0, 0.0, 1.5)
- meths.ui_pum_set_bounds(1.0, 1.0, -1.0, 0.0)
- meths.ui_pum_set_bounds(1.0, 1.0, 0.0, -1.0)
+ api.nvim_ui_pum_set_bounds(1.0, 1.0, 0.0, 1.5)
+ api.nvim_ui_pum_set_bounds(1.0, 1.0, -1.0, 0.0)
+ api.nvim_ui_pum_set_bounds(1.0, 1.0, 0.0, -1.0)
end)
it('an error occurs if width or height set 0 or less', function()
- meths.ui_pum_set_bounds(1.0, 1.0, 0.0, 1.5)
- eq('Expected width > 0',
- pcall_err(meths.ui_pum_set_bounds, 0.0, 1.0, 1.0, 0.0))
- eq('Expected height > 0',
- pcall_err(meths.ui_pum_set_bounds, 1.0, -1.0, 1.0, 0.0))
+ api.nvim_ui_pum_set_bounds(1.0, 1.0, 0.0, 1.5)
+ eq('Expected width > 0', pcall_err(api.nvim_ui_pum_set_bounds, 0.0, 1.0, 1.0, 0.0))
+ eq('Expected height > 0', pcall_err(api.nvim_ui_pum_set_bounds, 1.0, -1.0, 1.0, 0.0))
end)
it('an error occurs when ext_popupmenu is false', function()
- meths.ui_pum_set_bounds(1.0, 1.0, 0.0, 1.5)
+ api.nvim_ui_pum_set_bounds(1.0, 1.0, 0.0, 1.5)
screen:set_option('ext_popupmenu', false)
- eq('UI must support the ext_popupmenu option',
- pcall_err(meths.ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5))
+ eq(
+ 'UI must support the ext_popupmenu option',
+ pcall_err(api.nvim_ui_pum_set_bounds, 1.0, 1.0, 0.0, 1.5)
+ )
end)
end)
it('<PageUP>, <PageDown> works without ui_pum_set_height', function()
source_complete_month()
local month_expected = {
- {'January', '', '', ''},
- {'February', '', '', ''},
- {'March', '', '', ''},
- {'April', '', '', ''},
- {'May', '', '', ''},
- {'June', '', '', ''},
- {'July', '', '', ''},
- {'August', '', '', ''},
- {'September', '', '', ''},
- {'October', '', '', ''},
- {'November', '', '', ''},
- {'December', '', '', ''},
+ { 'January', '', '', '' },
+ { 'February', '', '', '' },
+ { 'March', '', '', '' },
+ { 'April', '', '', '' },
+ { 'May', '', '', '' },
+ { 'June', '', '', '' },
+ { 'July', '', '', '' },
+ { 'August', '', '', '' },
+ { 'September', '', '', '' },
+ { 'October', '', '', '' },
+ { 'November', '', '', '' },
+ { 'December', '', '', '' },
}
feed('o<C-r>=TestCompleteMonth()<CR>')
feed('<PageDown>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
January^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=month_expected,
- pos=3,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = month_expected,
+ pos = 3,
+ anchor = { 1, 1, 0 },
+ },
+ }
feed('<PageUp>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
January^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=month_expected,
- pos=0,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = month_expected,
+ pos = 0,
+ anchor = { 1, 1, 0 },
+ },
+ }
end)
it('works with wildoptions=pum', function()
- screen:try_resize(32,10)
+ screen:try_resize(32, 10)
command('set wildmenu')
command('set wildoptions=pum')
local wild_expected = {
- {'define', '', '', ''},
- {'jump', '', '', ''},
- {'list', '', '', ''},
- {'place', '', '', ''},
- {'undefine', '', '', ''},
- {'unplace', '', '', ''},
+ { 'define', '', '', '' },
+ { 'jump', '', '', '' },
+ { 'list', '', '', '' },
+ { 'place', '', '', '' },
+ { 'undefine', '', '', '' },
+ { 'unplace', '', '', '' },
}
feed(':sign ')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign ^ |
]])
- eq(0, funcs.wildmenumode())
+ eq(0, fn.wildmenumode())
feed('<tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign define^ |
- ]], popupmenu={items=wild_expected, pos=0, anchor={1, 9, 6}}}
- eq(1, funcs.wildmenumode())
+ ]],
+ popupmenu = { items = wild_expected, pos = 0, anchor = { 1, 9, 6 } },
+ }
+ eq(1, fn.wildmenumode())
feed('<left>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign ^ |
- ]], popupmenu={items=wild_expected, pos=-1, anchor={1, 9, 6}}}
+ ]],
+ popupmenu = { items = wild_expected, pos = -1, anchor = { 1, 9, 6 } },
+ }
feed('<left>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign unplace^ |
- ]], popupmenu={items=wild_expected, pos=5, anchor={1, 9, 6}}}
+ ]],
+ popupmenu = { items = wild_expected, pos = 5, anchor = { 1, 9, 6 } },
+ }
feed('x')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign unplacex^ |
]])
feed('<esc>')
-- #10042: make sure shift-tab also triggers the pum
feed(':sign <S-tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign unplace^ |
- ]], popupmenu={items=wild_expected, pos=5, anchor={1, 9, 6}}}
+ ]],
+ popupmenu = { items = wild_expected, pos = 5, anchor = { 1, 9, 6 } },
+ }
feed('<esc>')
- eq(0, funcs.wildmenumode())
+ eq(0, fn.wildmenumode())
-- check positioning with multibyte char in pattern
- command("e långfile1")
- command("sp långfile2")
+ command('e långfile1')
+ command('sp långfile2')
feed(':b lå<tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{4:långfile2 }|
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:långfile1 }|
:b långfile1^ |
- ]], popupmenu={
- anchor = {1, 9, 3},
- items = {{"långfile1", "", "", "" }, {"långfile2", "", "", ""}},
- pos = 0,
- }}
-
+ ]],
+ popupmenu = {
+ anchor = { 1, 9, 3 },
+ items = { { 'långfile1', '', '', '' }, { 'långfile2', '', '', '' } },
+ pos = 0,
+ },
+ }
end)
it('does not interfere with mousemodel=popup', function()
@@ -957,68 +854,58 @@ describe('ui/ext_popupmenu', function()
menu PopUp.baz :let g:menustr = 'baz'<CR>
]])
feed('o<C-r>=TestComplete()<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
foo^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=0,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = 0,
+ anchor = { 1, 1, 0 },
+ },
+ }
feed('<c-p>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
- ]], popupmenu={
- items=expected,
- pos=-1,
- anchor={1,1,0},
- }}
+ ]],
+ popupmenu = {
+ items = expected,
+ pos = -1,
+ anchor = { 1, 1, 0 },
+ },
+ }
feed('<esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
- ]]}
+ ]],
+ }
feed('<RightMouse><0,0>')
screen:expect([[
|
{7:^foo } |
{7:bar }{1: }|
{7:baz }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
feed('<esc>')
screen:expect([[
|
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
|
]])
end)
@@ -1030,51 +917,51 @@ describe("builtin popupmenu 'pumblend'", function()
it('RGB-color', function()
local screen = Screen.new(60, 14)
screen:set_default_attr_ids({
- [1] = {background = Screen.colors.Yellow},
- [2] = {bold = true, reverse = true},
- [3] = {bold = true, foreground = Screen.colors.Brown},
- [4] = {foreground = Screen.colors.Blue1},
- [5] = {reverse = true},
- [6] = {background = Screen.colors.Gray55, foreground = Screen.colors.Grey45},
- [7] = {background = Screen.colors.Gray55, foreground = Screen.colors.Grey0},
- [8] = {background = tonumber('0x191919'), foreground = Screen.colors.Grey0},
- [9] = {background = tonumber('0xffc1ff'), foreground = tonumber('0xe5a8e5')},
- [10] = {background = tonumber('0xffc1ff'), foreground = Screen.colors.Grey0},
- [11] = {foreground = tonumber('0xffc1ff'), background = tonumber('0xe5a8e5'), bold = true},
- [12] = {foreground = Screen.colors.Grey55, background = Screen.colors.Gray45, bold = true},
- [13] = {background = tonumber('0xffc1e5'), foreground = Screen.colors.Grey0},
- [14] = {background = tonumber('0xffc1e5'), foreground = tonumber('0xe5a8e5')},
- [15] = {background = tonumber('0xffc1ff'), foreground = tonumber('0x080202')},
- [16] = {background = tonumber('0xffc1ff'), bold = true, foreground = tonumber('0xf6ace9')},
- [17] = {background = tonumber('0xffc1ff'), foreground = tonumber('0xe5a8ff')},
- [18] = {background = tonumber('0xe5a8e5'), foreground = tonumber('0xffc1ff')},
- [19] = {background = Screen.colors.Gray45, foreground = Screen.colors.Grey55},
- [20] = {bold = true},
- [21] = {bold = true, foreground = Screen.colors.SeaGreen4},
- [22] = {background = Screen.colors.WebGray},
- [23] = {background = Screen.colors.Grey0},
- [24] = {background = Screen.colors.LightMagenta},
- [25] = {background = Screen.colors.Gray75, foreground = Screen.colors.Grey25},
- [26] = {background = Screen.colors.Gray75, foreground = Screen.colors.Grey0},
- [27] = {background = Screen.colors.Gray50, foreground = Screen.colors.Grey0},
- [28] = {background = tonumber('0xffddff'), foreground = tonumber('0x7f5d7f')},
- [29] = {background = tonumber('0xffddff'), foreground = Screen.colors.Grey0},
- [30] = {foreground = tonumber('0xffddff'), background = tonumber('0x7f5d7f'), bold = true},
- [31] = {foreground = tonumber('0xffddff'), background = Screen.colors.Grey0, bold = true},
- [32] = {foreground = Screen.colors.Gray75, background = Screen.colors.Grey25, bold = true},
- [33] = {background = tonumber('0xffdd7f'), foreground = Screen.colors.Grey0},
- [34] = {background = tonumber('0xffdd7f'), foreground = tonumber('0x7f5d7f')},
- [35] = {background = tonumber('0xffddff'), bold = true, foreground = tonumber('0x290a0a')},
- [36] = {background = tonumber('0xffddff'), bold = true, foreground = tonumber('0xd27294')},
- [37] = {background = tonumber('0xffddff'), foreground = tonumber('0x7f5dff')},
- [38] = {background = tonumber('0x7f5d7f'), foreground = tonumber('0xffddff')},
- [39] = {background = Screen.colors.Grey0, foreground = tonumber('0xffddff')},
- [40] = {background = Screen.colors.Gray25, foreground = Screen.colors.Grey75},
- [41] = {background = tonumber('0xffddff'), foreground = tonumber('0x00003f')},
- [42] = {foreground = tonumber('0x0c0c0c'), background = tonumber('0xe5a8e5')},
- [43] = {background = tonumber('0x7f5d7f'), bold = true, foreground = tonumber('0x3f3f3f')},
- [44] = {foreground = tonumber('0x3f3f3f'), background = tonumber('0x7f5d7f')},
- [45] = {background = Screen.colors.WebGray, blend=0},
+ [1] = { background = Screen.colors.Yellow },
+ [2] = { bold = true, reverse = true },
+ [3] = { bold = true, foreground = Screen.colors.Brown },
+ [4] = { foreground = Screen.colors.Blue1 },
+ [5] = { reverse = true },
+ [6] = { background = Screen.colors.Gray55, foreground = Screen.colors.Grey45 },
+ [7] = { background = Screen.colors.Gray55, foreground = Screen.colors.Grey0 },
+ [8] = { background = tonumber('0x191919'), foreground = Screen.colors.Grey0 },
+ [9] = { background = tonumber('0xffc1ff'), foreground = tonumber('0xe5a8e5') },
+ [10] = { background = tonumber('0xffc1ff'), foreground = Screen.colors.Grey0 },
+ [11] = { foreground = tonumber('0xffc1ff'), background = tonumber('0xe5a8e5'), bold = true },
+ [12] = { foreground = Screen.colors.Grey55, background = Screen.colors.Gray45, bold = true },
+ [13] = { background = tonumber('0xffc1e5'), foreground = Screen.colors.Grey0 },
+ [14] = { background = tonumber('0xffc1e5'), foreground = tonumber('0xe5a8e5') },
+ [15] = { background = tonumber('0xffc1ff'), foreground = tonumber('0x080202') },
+ [16] = { background = tonumber('0xffc1ff'), bold = true, foreground = tonumber('0xf6ace9') },
+ [17] = { background = tonumber('0xffc1ff'), foreground = tonumber('0xe5a8ff') },
+ [18] = { background = tonumber('0xe5a8e5'), foreground = tonumber('0xffc1ff') },
+ [19] = { background = Screen.colors.Gray45, foreground = Screen.colors.Grey55 },
+ [20] = { bold = true },
+ [21] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ [22] = { background = Screen.colors.WebGray },
+ [23] = { background = Screen.colors.Grey0 },
+ [24] = { background = Screen.colors.LightMagenta },
+ [25] = { background = Screen.colors.Gray75, foreground = Screen.colors.Grey25 },
+ [26] = { background = Screen.colors.Gray75, foreground = Screen.colors.Grey0 },
+ [27] = { background = Screen.colors.Gray50, foreground = Screen.colors.Grey0 },
+ [28] = { background = tonumber('0xffddff'), foreground = tonumber('0x7f5d7f') },
+ [29] = { background = tonumber('0xffddff'), foreground = Screen.colors.Grey0 },
+ [30] = { foreground = tonumber('0xffddff'), background = tonumber('0x7f5d7f'), bold = true },
+ [31] = { foreground = tonumber('0xffddff'), background = Screen.colors.Grey0, bold = true },
+ [32] = { foreground = Screen.colors.Gray75, background = Screen.colors.Grey25, bold = true },
+ [33] = { background = tonumber('0xffdd7f'), foreground = Screen.colors.Grey0 },
+ [34] = { background = tonumber('0xffdd7f'), foreground = tonumber('0x7f5d7f') },
+ [35] = { background = tonumber('0xffddff'), bold = true, foreground = tonumber('0x290a0a') },
+ [36] = { background = tonumber('0xffddff'), bold = true, foreground = tonumber('0xd27294') },
+ [37] = { background = tonumber('0xffddff'), foreground = tonumber('0x7f5dff') },
+ [38] = { background = tonumber('0x7f5d7f'), foreground = tonumber('0xffddff') },
+ [39] = { background = Screen.colors.Grey0, foreground = tonumber('0xffddff') },
+ [40] = { background = Screen.colors.Gray25, foreground = Screen.colors.Grey75 },
+ [41] = { background = tonumber('0xffddff'), foreground = tonumber('0x00003f') },
+ [42] = { foreground = tonumber('0x0c0c0c'), background = tonumber('0xe5a8e5') },
+ [43] = { background = tonumber('0x7f5d7f'), bold = true, foreground = tonumber('0x3f3f3f') },
+ [44] = { foreground = tonumber('0x3f3f3f'), background = tonumber('0x7f5d7f') },
+ [45] = { background = Screen.colors.WebGray, blend = 0 },
})
screen:attach()
command('syntax on')
@@ -1168,7 +1055,7 @@ describe("builtin popupmenu 'pumblend'", function()
{20:-- Keyword Local completion (^N^P) }{21:match 1 of 65} |
]])
- meths.input_mouse('wheel', 'down', '', 0, 9, 40)
+ api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
screen:expect([[
Lorem ipsum d{1:ol}or sit amet, consectetur |
adipisicing elit, sed do eiusmod tempor |
@@ -1228,18 +1115,18 @@ describe("builtin popupmenu 'pumblend'", function()
it('256-color (non-RGB)', function()
local screen = Screen.new(60, 8)
screen:set_default_attr_ids({
- [1] = {foreground = Screen.colors.Grey0, background = tonumber('0x000007')},
- [2] = {foreground = tonumber('0x000055'), background = tonumber('0x000007')},
- [3] = {foreground = tonumber('0x00008f'), background = Screen.colors.Grey0},
- [4] = {foreground = Screen.colors.Grey0, background = tonumber('0x0000e1')},
- [5] = {foreground = tonumber('0x0000d1'), background = tonumber('0x0000e1')},
- [6] = {foreground = Screen.colors.NavyBlue, background = tonumber('0x0000f8')},
- [7] = {foreground = tonumber('0x0000a5'), background = tonumber('0x0000f8')},
- [8] = {foreground = tonumber('0x00000c')},
- [9] = {bold = true},
- [10] = {foreground = tonumber('0x000002')},
+ [1] = { foreground = Screen.colors.Grey0, background = tonumber('0x000007') },
+ [2] = { foreground = tonumber('0x000055'), background = tonumber('0x000007') },
+ [3] = { foreground = tonumber('0x00008f'), background = Screen.colors.Grey0 },
+ [4] = { foreground = Screen.colors.Grey0, background = tonumber('0x0000e1') },
+ [5] = { foreground = tonumber('0x0000d1'), background = tonumber('0x0000e1') },
+ [6] = { foreground = Screen.colors.NavyBlue, background = tonumber('0x0000f8') },
+ [7] = { foreground = tonumber('0x0000a5'), background = tonumber('0x0000f8') },
+ [8] = { foreground = tonumber('0x00000c') },
+ [9] = { bold = true },
+ [10] = { foreground = tonumber('0x000002') },
})
- screen:attach({rgb=false})
+ screen:attach({ rgb = false })
command('set notermguicolors pumblend=10')
insert([[
Lorem ipsum dolor sit amet, consectetur
@@ -1271,21 +1158,21 @@ describe('builtin popupmenu', function()
screen = Screen.new(32, 20)
screen:set_default_attr_ids({
-- popup selected item / scrollbar track
- ['s'] = {background = Screen.colors.WebGray},
+ ['s'] = { background = Screen.colors.WebGray },
-- popup non-selected item
- ['n'] = {background = Screen.colors.LightMagenta},
+ ['n'] = { background = Screen.colors.LightMagenta },
-- popup scrollbar knob
- ['c'] = {background = Screen.colors.Grey0},
- [1] = {bold = true, foreground = Screen.colors.Blue},
- [2] = {bold = true},
- [3] = {reverse = true},
- [4] = {bold = true, reverse = true},
- [5] = {bold = true, foreground = Screen.colors.SeaGreen},
- [6] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [7] = {background = Screen.colors.Yellow}, -- Search
- [8] = {foreground = Screen.colors.Red},
+ ['c'] = { background = Screen.colors.Grey0 },
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { bold = true },
+ [3] = { reverse = true },
+ [4] = { bold = true, reverse = true },
+ [5] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [6] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [7] = { background = Screen.colors.Yellow }, -- Search
+ [8] = { foreground = Screen.colors.Red },
})
- screen:attach({ext_multigrid=multigrid})
+ screen:attach({ ext_multigrid = multigrid })
end)
it('with preview-window above', function()
@@ -1293,49 +1180,24 @@ describe('builtin popupmenu', function()
feed('iaa bb cc dd ee ff gg hh ii jj<cr>')
feed('<c-x><c-n>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
+ [4:--------------------------------]|*8
{3:[No Name] [Preview][+] }|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*9
{4:[No Name] [+] }|
[3:--------------------------------]|
## grid 2
aa bb cc dd ee ff gg hh ii jj |
aa^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
## grid 3
{2:-- }{5:match 1 of 10} |
## grid 4
aa bb cc dd ee ff gg hh ii jj |
aa |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 5
{s:aa }{c: }|
{n:bb }{c: }|
@@ -1345,19 +1207,16 @@ describe('builtin popupmenu', function()
{n:ff }{c: }|
{n:gg }{s: }|
{n:hh }{s: }|
- ]], float_pos={
- [5] = {{id = -1}, "NW", 2, 2, 0, false, 100};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'NW', 2, 2, 0, false, 100 },
+ },
+ }
else
screen:expect([[
aa bb cc dd ee ff gg hh ii jj |
aa |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
{3:[No Name] [Preview][+] }|
aa bb cc dd ee ff gg hh ii jj |
aa^ |
@@ -1379,49 +1238,24 @@ describe('builtin popupmenu', function()
feed('iaa bb cc dd ee ff gg hh ii jj<cr>')
feed('<c-x><c-n>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*9
{4:[No Name] [+] }|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
+ [4:--------------------------------]|*8
{3:[No Name] [Preview][+] }|
[3:--------------------------------]|
## grid 2
aa bb cc dd ee ff gg hh ii jj |
aa^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
## grid 3
{2:-- }{5:match 1 of 10} |
## grid 4
aa bb cc dd ee ff gg hh ii jj |
aa |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 5
{s:aa }{c: }|
{n:bb }{c: }|
@@ -1431,9 +1265,11 @@ describe('builtin popupmenu', function()
{n:ff }{c: }|
{n:gg }{s: }|
{n:hh }{s: }|
- ]], float_pos={
- [5] = {{id = -1}, "NW", 2, 2, 0, false, 100};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'NW', 2, 2, 0, false, 100 },
+ },
+ }
else
screen:expect([[
aa bb cc dd ee ff gg hh ii jj |
@@ -1448,12 +1284,7 @@ describe('builtin popupmenu', function()
{n:hh }{s: }{4: }|
aa bb cc dd ee ff gg hh ii jj |
aa |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
{3:[No Name] [Preview][+] }|
{2:-- }{5:match 1 of 10} |
]])
@@ -1467,26 +1298,12 @@ describe('builtin popupmenu', function()
feed('kk<cr>ll<cr>mm<cr>nn<cr>oo<cr>')
feed('<c-x><c-n>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
+ [4:--------------------------------]|*4
{3:[No Name] [Preview][+] }|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*13
{4:[No Name] [+] }|
[3:--------------------------------]|
## grid 2
@@ -1524,9 +1341,11 @@ describe('builtin popupmenu', function()
{n:kk }{c: }|
{n:ll }{s: }|
{n:mm }{s: }|
- ]], float_pos={
- [5] = {{id = -1}, "SW", 2, 12, 0, false, 100};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'SW', 2, 12, 0, false, 100 },
+ },
+ }
else
screen:expect([[
aa |
@@ -1559,26 +1378,12 @@ describe('builtin popupmenu', function()
feed('ff<cr>gg<cr>hh<cr>ii<cr>jj<cr>')
feed('<c-x><c-n>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
+ [4:--------------------------------]|*8
{3:[No Name] [Preview][+] }|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*9
{4:[No Name] [+] }|
[3:--------------------------------]|
## grid 2
@@ -1612,9 +1417,11 @@ describe('builtin popupmenu', function()
{n:gg }{c: }|
{n:hh }{c: }|
{n:ii }{s: }|
- ]], float_pos={
- [5] = {{id = -1}, "SW", 2, 8, 0, false, 100};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'SW', 2, 8, 0, false, 100 },
+ },
+ }
else
screen:expect([[
aa |
@@ -1647,26 +1454,12 @@ describe('builtin popupmenu', function()
feed('ff<cr>gg<cr>hh<cr>ii<cr>jj<cr>')
feed('<c-x><c-n>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*9
{4:[No Name] [+] }|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
- [4:--------------------------------]|
+ [4:--------------------------------]|*8
{3:[No Name] [Preview][+] }|
[3:--------------------------------]|
## grid 2
@@ -1699,9 +1492,11 @@ describe('builtin popupmenu', function()
{n:ff }{c: }|
{n:gg }{s: }|
{n:hh }{s: }|
- ]], float_pos={
- [5] = {{id = -1}, "SW", 2, 8, 0, false, 100};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'SW', 2, 8, 0, false, 100 },
+ },
+ }
else
screen:expect([[
{s:aa }{c: } |
@@ -1747,43 +1542,19 @@ describe('builtin popupmenu', function()
{n:one }{1: }|
{n:two }{1: }|
{n:three }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*15
{2:-- }{8:Back at original} |
]])
feed('<C-N>')
screen:expect([[
1info |
- |
- {1:~ }|
+ {1:~ }|*2
{3:[Scratch] [Preview] }|
one^ |
{s:one }{1: }|
{n:two }{1: }|
{n:three }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*10
{4:[No Name] [+] }|
{2:-- }{5:match 1 of 3} |
]])
@@ -1814,46 +1585,203 @@ describe('builtin popupmenu', function()
end)
end
+ describe('floating window preview #popup', function()
+ it('pum popup preview', function()
+ --row must > 10
+ screen:try_resize(30, 11)
+ exec([[
+ funct Omni_test(findstart, base)
+ if a:findstart
+ return col(".") - 1
+ endif
+ return [#{word: "one", info: "1info"}, #{word: "two", info: "2info"}, #{word: "three"}]
+ endfunc
+ set omnifunc=Omni_test
+ set completeopt=menu,popup
+
+ funct Set_info()
+ let comp_info = complete_info()
+ if comp_info['selected'] == 2
+ call nvim_complete_set(comp_info['selected'], {"info": "3info"})
+ endif
+ endfunc
+ autocmd CompleteChanged * call Set_info()
+ ]])
+ feed('Gi<C-x><C-o>')
+
+ --floating preview in right
+ if multigrid then
+ screen:expect {
+ grid = [[
+ ## grid 1
+ [2:------------------------------]|*10
+ [3:------------------------------]|
+ ## grid 2
+ one^ |
+ {1:~ }|*9
+ ## grid 3
+ {2:-- }{5:match 1 of 3} |
+ ## grid 4
+ {n:1info}|
+ {n: }|
+ ## grid 5
+ {s:one }|
+ {n:two }|
+ {n:three }|
+ ]],
+ float_pos = {
+ [5] = { -1, 'NW', 2, 1, 0, false, 100 },
+ [4] = { 1001, 'NW', 1, 1, 15, true, 50 },
+ },
+ }
+ else
+ screen:expect {
+ grid = [[
+ one^ |
+ {s:one }{n:1info}{1: }|
+ {n:two }{1: }|
+ {n:three }{1: }|
+ {1:~ }|*6
+ {2:-- }{5:match 1 of 3} |
+ ]],
+ unchanged = true,
+ }
+ end
+
+ -- test nvim_complete_set_info
+ feed('<C-N><C-N>')
+ vim.uv.sleep(10)
+ if multigrid then
+ screen:expect {
+ grid = [[
+ ## grid 1
+ [2:------------------------------]|*10
+ [3:------------------------------]|
+ ## grid 2
+ three^ |
+ {1:~ }|*9
+ ## grid 3
+ {2:-- }{5:match 3 of 3} |
+ ## grid 4
+ {n:3info}|
+ {n: }|
+ ## grid 5
+ {n:one }|
+ {n:two }|
+ {s:three }|
+ ]],
+ float_pos = {
+ [5] = { -1, 'NW', 2, 1, 0, false, 100 },
+ [4] = { 1001, 'NW', 1, 1, 15, true, 50 },
+ },
+ }
+ else
+ screen:expect {
+ grid = [[
+ three^ |
+ {n:one 3info}{1: }|
+ {n:two }{1: }|
+ {s:three }{1: }|
+ {1:~ }|*6
+ {2:-- }{5:match 3 of 3} |
+ ]],
+ }
+ end
+ -- make sure info has set
+ feed('<C-y>')
+ eq('3info', exec_lua('return vim.v.completed_item.info'))
+
+ -- preview in left
+ feed('<ESC>cc')
+ insert(('test'):rep(5))
+ feed('i<C-x><C-o>')
+ if multigrid then
+ screen:expect {
+ grid = [[
+ ## grid 1
+ [2:------------------------------]|*10
+ [3:------------------------------]|
+ ## grid 2
+ itesttesttesttesttesone^t |
+ {1:~ }|*9
+ ## grid 3
+ {2:-- }{5:match 1 of 3} |
+ ## grid 5
+ {s: one }|
+ {n: two }|
+ {n: three }|
+ ## grid 6
+ {n:1info}|
+ {n: }|
+ ]],
+ float_pos = {
+ [5] = { -1, 'NW', 2, 1, 19, false, 100 },
+ [6] = { 1002, 'NW', 1, 1, 1, true, 50 },
+ },
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 0,
+ botline = 2,
+ curline = 0,
+ curcol = 23,
+ linecount = 1,
+ sum_scroll_delta = 0,
+ },
+ [6] = {
+ win = 1002,
+ topline = 0,
+ botline = 2,
+ curline = 0,
+ curcol = 0,
+ linecount = 1,
+ sum_scroll_delta = 0,
+ },
+ },
+ }
+ else
+ screen:expect {
+ grid = [[
+ itesttesttesttesttesone^t |
+ {1:~}{n:1info}{1: }{s: one }{1: }|
+ {1:~}{n: }{1: }{n: two }{1: }|
+ {1:~ }{n: three }{1: }|
+ {1:~ }|*6
+ {2:-- }{5:match 1 of 3} |
+ ]],
+ }
+ end
+ end)
+ end)
+
it('with vsplits', function()
screen:try_resize(32, 8)
insert('aaa aab aac\n')
feed(':vsplit<cr>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [4:--------------------]│[2:-----------]|
- [4:--------------------]│[2:-----------]|
- [4:--------------------]│[2:-----------]|
- [4:--------------------]│[2:-----------]|
- [4:--------------------]│[2:-----------]|
- [4:--------------------]│[2:-----------]|
+ [4:--------------------]│[2:-----------]|*6
{4:[No Name] [+] }{3:<Name] [+] }|
[3:--------------------------------]|
## grid 2
aaa aab aac|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
:vsplit |
## grid 4
aaa aab aac |
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- ]]}
+ {1:~ }|*4
+ ]],
+ }
else
screen:expect([[
aaa aab aac │aaa aab aac|
^ │ |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
{4:[No Name] [+] }{3:<Name] [+] }|
:vsplit |
]])
@@ -1861,39 +1789,31 @@ describe('builtin popupmenu', function()
feed('ibbb a<c-x><c-n>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [4:--------------------]│[2:-----------]|
- [4:--------------------]│[2:-----------]|
- [4:--------------------]│[2:-----------]|
- [4:--------------------]│[2:-----------]|
- [4:--------------------]│[2:-----------]|
- [4:--------------------]│[2:-----------]|
+ [4:--------------------]│[2:-----------]|*6
{4:[No Name] [+] }{3:<Name] [+] }|
[3:--------------------------------]|
## grid 2
aaa aab aac|
bbb aaa |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
{2:-- }{5:match 1 of 3} |
## grid 4
aaa aab aac |
bbb aaa^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 5
{s: aaa }|
{n: aab }|
{n: aac }|
- ]], float_pos={
- [5] = {{id = -1}, "NW", 4, 2, 3, false, 100};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'NW', 4, 2, 3, false, 100 },
+ },
+ }
else
screen:expect([[
aaa aab aac │aaa aab aac|
@@ -1909,39 +1829,33 @@ describe('builtin popupmenu', function()
feed('<esc><c-w><c-w>oc a<c-x><c-n>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
+ [4:-----------]│[2:--------------------]|*6
{3:<Name] [+] }{4:[No Name] [+] }|
[3:--------------------------------]|
## grid 2
aaa aab aac |
bbb aaa |
c aaa^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
{2:-- }{5:match 1 of 3} |
## grid 4
aaa aab aac|
bbb aaa |
c aaa |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 5
{s: aaa }|
{n: aab }|
{n: aac }|
- ]], float_pos={
- [5] = {{id = -1}, "NW", 2, 3, 1, false, 100};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'NW', 2, 3, 1, false, 100 },
+ },
+ }
else
screen:expect([[
aaa aab aac│aaa aab aac |
@@ -1957,23 +1871,17 @@ describe('builtin popupmenu', function()
feed('bcdef ccc a<c-x><c-n>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
+ [4:-----------]│[2:--------------------]|*6
{3:<Name] [+] }{4:[No Name] [+] }|
[3:--------------------------------]|
## grid 2
aaa aab aac |
bbb aaa |
c aaabcdef ccc aaa^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
## grid 3
{2:-- }{5:match 1 of 4} |
## grid 4
@@ -1981,16 +1889,17 @@ describe('builtin popupmenu', function()
bbb aaa |
c aaabcdef |
ccc aaa |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 5
{s: aaa }|
{n: aab }|
{n: aac }|
{n: aaabcdef}|
- ]], float_pos={
- [5] = {{id = -1}, "NW", 2, 3, 11, false, 100};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'NW', 2, 3, 11, false, 100 },
+ },
+ }
else
screen:expect([[
aaa aab aac│aaa aab aac |
@@ -2006,14 +1915,10 @@ describe('builtin popupmenu', function()
feed('\n<c-x><c-n>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
- [4:-----------]│[2:--------------------]|
+ [4:-----------]│[2:--------------------]|*6
{3:<Name] [+] }{4:[No Name] [+] }|
[3:--------------------------------]|
## grid 2
@@ -2021,8 +1926,7 @@ describe('builtin popupmenu', function()
bbb aaa |
c aaabcdef ccc aaa |
aaa^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
## grid 3
{2:-- }{5:match 1 of 6} |
## grid 4
@@ -2036,9 +1940,11 @@ describe('builtin popupmenu', function()
{s: aaa }{c: }|
{n: aab }{s: }|
{n: aac }{s: }|
- ]], float_pos={
- [5] = {{id = -1}, "NW", 2, 4, -1, false, 100};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'NW', 2, 4, -1, false, 100 },
+ },
+ }
else
screen:expect([[
aaa aab aac│aaa aab aac |
@@ -2055,10 +1961,10 @@ describe('builtin popupmenu', function()
if not multigrid then
it('with split and scroll', function()
- screen:try_resize(60,14)
- command("split")
- command("set completeopt+=noinsert")
- command("set mouse=a")
+ screen:try_resize(60, 14)
+ command('split')
+ command('set completeopt+=noinsert')
+ command('set mouse=a')
insert([[
Lorem ipsum dolor sit amet, consectetur
adipisicing elit, sed do eiusmod tempor
@@ -2108,7 +2014,7 @@ describe('builtin popupmenu', function()
{2:-- Keyword Local completion (^N^P) }{5:match 1 of 65} |
]])
- meths.input_mouse('wheel', 'down', '', 0, 9, 40)
+ api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
screen:expect([[
Est ^ |
L{n: sunt }{s: }sit amet, consectetur |
@@ -2144,7 +2050,7 @@ describe('builtin popupmenu', function()
{2:-- Keyword Local completion (^N^P) }{5:match 1 of 65} |
]])
- meths.input_mouse('wheel', 'up', '', 0, 9, 40)
+ api.nvim_input_mouse('wheel', 'up', '', 0, 9, 40)
screen:expect([[
Est e^ |
L{n: elit } sit amet, consectetur |
@@ -2180,7 +2086,7 @@ describe('builtin popupmenu', function()
{2:-- Keyword Local completion (^N^P) }{5:match 1 of 65} |
]])
- meths.input_mouse('wheel', 'down', '', 0, 9, 40)
+ api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
screen:expect([[
Est es^ |
L{n: esse } sit amet, consectetur |
@@ -2234,7 +2140,7 @@ describe('builtin popupmenu', function()
{2:-- Keyword Local completion (^N^P) }{5:match 22 of 65} |
]])
- meths.input_mouse('wheel', 'down', '', 0, 9, 40)
+ api.nvim_input_mouse('wheel', 'down', '', 0, 9, 40)
screen:expect([[
Est eu^ |
L{n: elit } sit amet, consectetur |
@@ -2252,7 +2158,7 @@ describe('builtin popupmenu', function()
{2:-- Keyword Local completion (^N^P) }{5:match 22 of 65} |
]])
- funcs.complete(4, {'ea', 'eeeeeeeeeeeeeeeeee', 'ei', 'eo', 'eu', 'ey', 'eå', 'eä', 'eö'})
+ fn.complete(4, { 'ea', 'eeeeeeeeeeeeeeeeee', 'ei', 'eo', 'eu', 'ey', 'eå', 'eä', 'eö' })
screen:expect([[
Est eu^ |
{s: ea }t amet, consectetur |
@@ -2270,7 +2176,7 @@ describe('builtin popupmenu', function()
{2:-- Keyword Local completion (^N^P) }{5:match 1 of 9} |
]])
- funcs.complete(4, {'ea', 'eee', 'ei', 'eo', 'eu', 'ey', 'eå', 'eä', 'eö'})
+ fn.complete(4, { 'ea', 'eee', 'ei', 'eo', 'eu', 'ey', 'eå', 'eä', 'eö' })
screen:expect([[
Est eu^ |
{s: ea }r sit amet, consectetur |
@@ -2306,7 +2212,7 @@ describe('builtin popupmenu', function()
{2:-- INSERT --} |
]])
- funcs.complete(6, {'foo', 'bar'})
+ fn.complete(6, { 'foo', 'bar' })
screen:expect([[
Esteee^ |
Lo{s: foo }sit amet, consectetur |
@@ -2345,29 +2251,16 @@ describe('builtin popupmenu', function()
it('can be moved due to wrap or resize', function()
feed('isome long prefix before the ')
- command("set completeopt+=noinsert,noselect")
- command("set linebreak")
- funcs.complete(29, {'word', 'choice', 'text', 'thing'})
+ command('set completeopt+=noinsert,noselect')
+ command('set linebreak')
+ fn.complete(29, { 'word', 'choice', 'text', 'thing' })
screen:expect([[
some long prefix before the ^ |
{1:~ }{n: word }|
{1:~ }{n: choice}|
{1:~ }{n: text }|
{1:~ }{n: thing }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*14
{2:-- INSERT --} |
]])
@@ -2379,19 +2272,7 @@ describe('builtin popupmenu', function()
{n:choice }{1: }|
{n:text }{1: }|
{s:thing }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*13
{2:-- INSERT --} |
]])
@@ -2402,24 +2283,11 @@ describe('builtin popupmenu', function()
{1:~ }{n: choice}|
{1:~ }{s: text }|
{1:~ }{n: thing }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*14
{2:-- INSERT --} |
]])
- screen:try_resize(30,8)
+ screen:try_resize(30, 8)
screen:expect([[
some long prefix before the |
text^ |
@@ -2431,19 +2299,18 @@ describe('builtin popupmenu', function()
{2:-- INSERT --} |
]])
- screen:try_resize(50,8)
+ screen:try_resize(50, 8)
screen:expect([[
some long prefix before the text^ |
{1:~ }{n: word }{1: }|
{1:~ }{n: choice }{1: }|
{1:~ }{s: text }{1: }|
{1:~ }{n: thing }{1: }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:-- INSERT --} |
]])
- screen:try_resize(25,10)
+ screen:try_resize(25, 10)
screen:expect([[
some long prefix before |
the text^ |
@@ -2451,13 +2318,11 @@ describe('builtin popupmenu', function()
{1:~ }{n: choice }{1: }|
{1:~ }{s: text }{1: }|
{1:~ }{n: thing }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:-- INSERT --} |
]])
- screen:try_resize(12,5)
+ screen:try_resize(12, 5)
screen:expect([[
some long |
prefix |
@@ -2467,14 +2332,14 @@ describe('builtin popupmenu', function()
]])
-- can't draw the pum, but check we don't crash
- screen:try_resize(12,2)
+ screen:try_resize(12, 2)
screen:expect([[
{1:<<<}t^ |
{2:-- INSERT --}|
]])
-- but state is preserved, pum reappears
- screen:try_resize(20,8)
+ screen:try_resize(20, 8)
screen:expect([[
some long prefix |
before the text^ |
@@ -2489,34 +2354,21 @@ describe('builtin popupmenu', function()
it('with VimResized autocmd', function()
feed('isome long prefix before the ')
- command("set completeopt+=noinsert,noselect")
- command("autocmd VimResized * redraw!")
- command("set linebreak")
- funcs.complete(29, {'word', 'choice', 'text', 'thing'})
+ command('set completeopt+=noinsert,noselect')
+ command('autocmd VimResized * redraw!')
+ command('set linebreak')
+ fn.complete(29, { 'word', 'choice', 'text', 'thing' })
screen:expect([[
some long prefix before the ^ |
{1:~ }{n: word }|
{1:~ }{n: choice}|
{1:~ }{n: text }|
{1:~ }{n: thing }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*14
{2:-- INSERT --} |
]])
- screen:try_resize(16,10)
+ screen:try_resize(16, 10)
screen:expect([[
some long |
prefix before |
@@ -2525,60 +2377,29 @@ describe('builtin popupmenu', function()
{1:~ }{n: choice }|
{1:~ }{n: text }|
{1:~ }{n: thing }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:-- INSERT --} |
]])
end)
it('with rightleft window', function()
- command("set rl wildoptions+=pum")
+ command('set rl wildoptions+=pum')
feed('isome rightleft ')
screen:expect([[
^ tfelthgir emos|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*18
{2:-- INSERT --} |
]])
- command("set completeopt+=noinsert,noselect")
- funcs.complete(16, {'word', 'choice', 'text', 'thing'})
+ command('set completeopt+=noinsert,noselect')
+ fn.complete(16, { 'word', 'choice', 'text', 'thing' })
screen:expect([[
^ tfelthgir emos|
{1: }{n: drow }{1: ~}|
{1: }{n: eciohc }{1: ~}|
{1: }{n: txet }{1: ~}|
{1: }{n: gniht }{1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*14
{2:-- INSERT --} |
]])
@@ -2589,87 +2410,32 @@ describe('builtin popupmenu', function()
{1: }{n: eciohc }{1: ~}|
{1: }{n: txet }{1: ~}|
{1: }{n: gniht }{1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*14
{2:-- INSERT --} |
]])
feed('<c-y>')
screen:expect([[
^ drow tfelthgir emos|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*18
{2:-- INSERT --} |
]])
-- not rightleft on the cmdline
feed('<esc>:sign ')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
drow tfelthgir emos|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*18
:sign ^ |
- ]]}
+ ]],
+ }
feed('<tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
drow tfelthgir emos|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*12
{1: }{s: define }{1: ~}|
{1: }{n: jump }{1: ~}|
{1: }{n: list }{1: ~}|
@@ -2677,7 +2443,8 @@ describe('builtin popupmenu', function()
{1: }{n: undefine }{1: ~}|
{1: }{n: unplace }{1: ~}|
:sign define^ |
- ]]}
+ ]],
+ }
end)
end
@@ -2688,34 +2455,30 @@ describe('builtin popupmenu', function()
command('set completeopt+=noinsert,noselect')
command('set pumheight=2')
feed('isome rightleft ')
- funcs.complete(16, {'word', 'choice', 'text', 'thing'})
+ fn.complete(16, { 'word', 'choice', 'text', 'thing' })
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
+ [2:-------------------]│[4:--------------------]|*4
{3:[No Name] [+] }{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
tfelthgir emos|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*3
## grid 3
{2:-- INSERT --} |
## grid 4
^ tfelthgir emos|
- {1: ~}|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*3
## grid 5
{c: }{n: drow }|
{s: }{n: eciohc }|
- ]], float_pos={
- [5] = {{id = -1}, "NW", 4, 1, -11, false, 100};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'NW', 4, 1, -11, false, 100 },
+ },
+ }
else
screen:expect([[
tfelthgir emos│ ^ tfelthgir emos|
@@ -2727,34 +2490,32 @@ describe('builtin popupmenu', function()
]])
end
feed('<C-E><CR>')
- funcs.complete(1, {'word', 'choice', 'text', 'thing'})
+ fn.complete(1, { 'word', 'choice', 'text', 'thing' })
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
+ [2:-------------------]│[4:--------------------]|*4
{3:[No Name] [+] }{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
tfelthgir emos|
|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*2
## grid 3
{2:-- INSERT --} |
## grid 4
tfelthgir emos|
^ |
- {1: ~}|
- {1: ~}|
+ {1: ~}|*2
## grid 5
{c: }{n: drow}|
{s: }{n: eciohc}|
- ]], float_pos={
- [5] = {{id = -1}, "NW", 4, 2, 4, false, 100};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'NW', 4, 2, 4, false, 100 },
+ },
+ }
else
screen:expect([[
tfelthgir emos│ tfelthgir emos|
@@ -2766,35 +2527,31 @@ describe('builtin popupmenu', function()
]])
end
feed('<C-E>')
- async_meths.call_function('input', {'', '', 'sign'})
+ async_meths.nvim_call_function('input', { '', '', 'sign' })
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
+ [2:-------------------]│[4:--------------------]|*4
{3:[No Name] [+] }{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
tfelthgir emos|
|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*2
## grid 3
^ |
## grid 4
tfelthgir emos|
|
- {1: ~}|
- {1: ~}|
- ]]}
+ {1: ~}|*2
+ ]],
+ }
else
screen:expect([[
tfelthgir emos│ tfelthgir emos|
│ |
- {1: ~}│{1: ~}|
- {1: ~}│{1: ~}|
+ {1: ~}│{1: ~}|*2
{3:[No Name] [+] }{4:[No Name] [+] }|
^ |
]])
@@ -2802,32 +2559,30 @@ describe('builtin popupmenu', function()
command('set wildoptions+=pum')
feed('<Tab>')
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
- [2:-------------------]│[4:--------------------]|
+ [2:-------------------]│[4:--------------------]|*4
{3:[No Name] [+] }{4:[No Name] [+] }|
[3:----------------------------------------]|
## grid 2
tfelthgir emos|
|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*2
## grid 3
define^ |
## grid 4
tfelthgir emos|
|
- {1: ~}|
- {1: ~}|
+ {1: ~}|*2
## grid 5
{s:define }{c: }|
{n:jump }{s: }|
- ]], float_pos={
- [5] = {{id = -1}, "SW", 1, 5, 0, false, 250};
- }}
+ ]],
+ float_pos = {
+ [5] = { -1, 'SW', 1, 5, 0, false, 250 },
+ },
+ }
else
screen:expect([[
tfelthgir emos│ tfelthgir emos|
@@ -2842,10 +2597,10 @@ describe('builtin popupmenu', function()
if not multigrid then
it('with multiline messages', function()
- screen:try_resize(40,8)
+ screen:try_resize(40, 8)
feed('ixx<cr>')
command('imap <f2> <cmd>echoerr "very"\\|echoerr "much"\\|echoerr "error"<cr>')
- funcs.complete(1, {'word', 'choice', 'text', 'thing'})
+ fn.complete(1, { 'word', 'choice', 'text', 'thing' })
screen:expect([[
xx |
word^ |
@@ -2893,7 +2648,7 @@ describe('builtin popupmenu', function()
{2:-- INSERT --} |
]])
- command("split")
+ command('split')
screen:expect([[
xx |
choice^ |
@@ -2905,8 +2660,9 @@ describe('builtin popupmenu', function()
{2:-- INSERT --} |
]])
- meths.input_mouse('wheel', 'down', '', 0, 6, 15)
- screen:expect{grid=[[
+ api.nvim_input_mouse('wheel', 'down', '', 0, 6, 15)
+ screen:expect {
+ grid = [[
xx |
choice^ |
{n:word }{1: }|
@@ -2915,21 +2671,25 @@ describe('builtin popupmenu', function()
{n:thing }{1: }|
{3:[No Name] [+] }|
{2:-- INSERT --} |
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
end)
it('with kind, menu and abbr attributes', function()
- screen:try_resize(40,8)
+ screen:try_resize(40, 8)
feed('ixx ')
- funcs.complete(4, {{word='wordey', kind= 'x', menu='extrainfo'}, 'thing', {word='secret', abbr='sneaky', menu='bar'}})
+ fn.complete(4, {
+ { word = 'wordey', kind = 'x', menu = 'extrainfo' },
+ 'thing',
+ { word = 'secret', abbr = 'sneaky', menu = 'bar' },
+ })
screen:expect([[
xx wordey^ |
{1:~ }{s: wordey x extrainfo }{1: }|
{1:~ }{n: thing }{1: }|
{1:~ }{n: sneaky bar }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:-- INSERT --} |
]])
@@ -2939,9 +2699,7 @@ describe('builtin popupmenu', function()
{1:~ }{n: wordey x extrainfo }{1: }|
{1:~ }{n: thing }{1: }|
{1:~ }{n: sneaky bar }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:-- INSERT --} |
]])
@@ -2951,51 +2709,36 @@ describe('builtin popupmenu', function()
{1:~ }{n: wordey x extrainfo }{1: }|
{1:~ }{n: thing }{1: }|
{1:~ }{s: sneaky bar }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:-- INSERT --} |
]])
feed('<esc>')
screen:expect([[
xx secre^t |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
|
]])
end)
it('wildoptions=pum', function()
- screen:try_resize(32,10)
+ screen:try_resize(32, 10)
command('set wildmenu')
command('set wildoptions=pum')
command('set shellslash')
- command("cd test/functional/fixtures/wildpum")
+ command('cd test/functional/fixtures/wildpum')
feed(':sign ')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign ^ |
]])
feed('<Tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{s: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3008,8 +2751,7 @@ describe('builtin popupmenu', function()
feed('<Right><Right>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{s: list }{1: }|
@@ -3022,8 +2764,7 @@ describe('builtin popupmenu', function()
feed('<C-N>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3036,8 +2777,7 @@ describe('builtin popupmenu', function()
feed('<C-P>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{s: list }{1: }|
@@ -3050,8 +2790,7 @@ describe('builtin popupmenu', function()
feed('<Left>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{s: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3065,14 +2804,7 @@ describe('builtin popupmenu', function()
feed('<C-E>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign ^ |
]])
@@ -3080,14 +2812,7 @@ describe('builtin popupmenu', function()
feed('<Tab><C-P><C-P><C-Y>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign unplace^ |
]])
@@ -3095,8 +2820,7 @@ describe('builtin popupmenu', function()
feed('<C-U>sign define <Tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{s: culhl= }{1: }|
{1:~ }{n: icon= }{1: }|
{1:~ }{n: linehl= }{1: }|
@@ -3109,8 +2833,7 @@ describe('builtin popupmenu', function()
feed('<Space><Tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{s: culhl= }{1: }|
{1:~ }{n: icon= }{1: }|
{1:~ }{n: linehl= }{1: }|
@@ -3123,12 +2846,7 @@ describe('builtin popupmenu', function()
feed('<C-U>e Xnamedi<Tab><Tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
{1:~ }{s: XdirA/ }{1: }|
{1:~ }{n: XfileA }{1: }|
:e Xnamedir/XdirA/^ |
@@ -3138,12 +2856,7 @@ describe('builtin popupmenu', function()
feed('<Down>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
{1:~ }{s: XdirB/ }{1: }|
{1:~ }{n: XfileB }{1: }|
:e Xnamedir/XdirA/XdirB/^ |
@@ -3153,12 +2866,7 @@ describe('builtin popupmenu', function()
feed('<Up>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
{1:~ }{s: XdirA/ }{1: }|
{1:~ }{n: XfileA }{1: }|
:e Xnamedir/XdirA/^ |
@@ -3169,12 +2877,7 @@ describe('builtin popupmenu', function()
feed(':<C-U>sign <Tab><C-A>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
{4: }|
:sign define jump list place und|
efine unplace^ |
@@ -3184,12 +2887,7 @@ describe('builtin popupmenu', function()
feed('<Left>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
{4: }|
:sign define jump list place und|
efine unplac^e |
@@ -3201,11 +2899,7 @@ describe('builtin popupmenu', function()
feed('<C-U>sign <Tab><C-D>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4: }|
:sign define |
define |
@@ -3216,8 +2910,7 @@ describe('builtin popupmenu', function()
feed('<C-U><CR>:sign <S-Tab><C-P>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3231,14 +2924,7 @@ describe('builtin popupmenu', function()
feed('<C-U><CR>:sign <Tab><Esc>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
|
]])
@@ -3246,14 +2932,7 @@ describe('builtin popupmenu', function()
feed(':sign <Tab>x')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign definex^ |
]])
@@ -3264,10 +2943,7 @@ describe('builtin popupmenu', function()
{3:[No Name] }|
{1::}sign define |
{1::}sign defin^e |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{4:[Command Line] }|
:sign define |
]])
@@ -3277,12 +2953,7 @@ describe('builtin popupmenu', function()
feed(':sign u<Tab><C-N><C-N>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
{1:~ }{n: undefine }{1: }|
{1:~ }{n: unplace }{1: }|
:sign u^ |
@@ -3292,10 +2963,7 @@ describe('builtin popupmenu', function()
feed('<C-U>bu<Tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{s: bufdo }{1: }|
{n: buffer }{1: }|
{n: buffers }{1: }|
@@ -3307,14 +2975,7 @@ describe('builtin popupmenu', function()
feed('<C-E><C-U>sign <Tab><BS>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign defin^ |
]])
@@ -3322,14 +2983,7 @@ describe('builtin popupmenu', function()
feed('<C-E><C-U>sign <Tab><C-W>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign ^ |
]])
@@ -3337,14 +2991,7 @@ describe('builtin popupmenu', function()
feed('<C-E><C-U>sign <Tab><C-U>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:^ |
]])
@@ -3353,14 +3000,7 @@ describe('builtin popupmenu', function()
feed('sign xyz<Esc>:sign <Tab><C-E><Up>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:sign xyz^ |
]])
@@ -3371,9 +3011,7 @@ describe('builtin popupmenu', function()
feed(':cn<Tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{4: }|
:cn |
cnewer cnoreabbrev |
@@ -3384,9 +3022,7 @@ describe('builtin popupmenu', function()
feed('s')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{4: }|
:cn |
cnewer cnoreabbrev |
@@ -3402,11 +3038,7 @@ describe('builtin popupmenu', function()
feed(':e ã‚ã„ã†/<Tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{1:~ }{s: 123 }{1: }|
{1:~ }{n: abc }{1: }|
{1:~ }{n: xyz }{1: }|
@@ -3418,8 +3050,7 @@ describe('builtin popupmenu', function()
feed(':sign <Tab><PageDown>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3431,8 +3062,7 @@ describe('builtin popupmenu', function()
feed('<PageDown>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3444,8 +3074,7 @@ describe('builtin popupmenu', function()
feed('<PageDown>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3457,8 +3086,7 @@ describe('builtin popupmenu', function()
feed('<PageDown>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{s: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3470,8 +3098,7 @@ describe('builtin popupmenu', function()
feed('<C-U>sign <Tab><Right><Right><PageDown>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3485,8 +3112,7 @@ describe('builtin popupmenu', function()
feed('<C-U>sign <Tab><PageUp>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3498,8 +3124,7 @@ describe('builtin popupmenu', function()
feed('<PageUp>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3511,8 +3136,7 @@ describe('builtin popupmenu', function()
feed('<PageUp>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{s: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3524,8 +3148,7 @@ describe('builtin popupmenu', function()
feed('<PageUp>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{s: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3539,12 +3162,7 @@ describe('builtin popupmenu', function()
feed('<Esc>:set wildchazz<Left><Left><Tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
{1:~ }{s: wildchar }{1: }|
{1:~ }{n: wildcharm }{1: }|
:set wildchar^zz |
@@ -3552,14 +3170,7 @@ describe('builtin popupmenu', function()
feed('<C-E>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:set wildcha^zz |
]])
@@ -3567,28 +3178,19 @@ describe('builtin popupmenu', function()
feed('<Esc>:set wildchazz<Left><Left><Tab><C-Y>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
:set wildchar^zz |
]])
feed('<Esc>')
-- check positioning with multibyte char in pattern
- command("e långfile1")
- command("sp långfile2")
+ command('e långfile1')
+ command('sp långfile2')
feed(':b lå<tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{4:långfile2 }|
|
{1:~ }|
@@ -3598,7 +3200,7 @@ describe('builtin popupmenu', function()
]])
-- check doesn't crash on screen resize
- screen:try_resize(20,6)
+ screen:try_resize(20, 6)
screen:expect([[
|
{1:~ }|
@@ -3608,20 +3210,13 @@ describe('builtin popupmenu', function()
:b långfile1^ |
]])
- screen:try_resize(50,15)
+ screen:try_resize(50, 15)
screen:expect([[
|
{1:~ }|
{4:långfile2 }|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
{1:~ }{s: långfile1 }{1: }|
{3:lå}{n: långfile2 }{3: }|
:b långfile1^ |
@@ -3636,21 +3231,14 @@ describe('builtin popupmenu', function()
{1:~ }|
{4:långfile2 }|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
{1:~ }{n: långfile1 }{1: }|
{3:lå}{n: långfile2 }{3: }|
:b långfile^ |
]])
feed('<esc>')
- command("close")
+ command('close')
command('set wildmode=full')
-- special case: when patterns ends with "/", show menu items aligned
@@ -3658,17 +3246,7 @@ describe('builtin popupmenu', function()
feed(':e compdir/<tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
{1:~ }{s: file1 }{1: }|
{1:~ }{n: file2 }{1: }|
:e compdir/file1^ |
@@ -3676,29 +3254,27 @@ describe('builtin popupmenu', function()
end)
it('wildoptions=pum with scrolled messages', function()
- screen:try_resize(40,10)
+ screen:try_resize(40, 10)
command('set wildmenu')
command('set wildoptions=pum')
feed(':echoerr "fail"|echoerr "error"<cr>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4: }|
{6:fail} |
{6:error} |
{5:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
feed(':sign <tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{s: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3706,25 +3282,24 @@ describe('builtin popupmenu', function()
{6:fail} {n: undefine } |
{6:error}{n: unplace } |
:sign define^ |
- ]]}
+ ]],
+ }
feed('d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4: }|
{6:fail} |
{6:error} |
:sign defined^ |
- ]]}
+ ]],
+ }
end)
it('wildoptions=pum and wildmode=longest,full #11622', function()
- screen:try_resize(30,8)
+ screen:try_resize(30, 8)
command('set wildmenu')
command('set wildoptions=pum')
command('set wildmode=longest,full')
@@ -3732,56 +3307,49 @@ describe('builtin popupmenu', function()
-- With 'wildmode' set to 'longest,full', completing a match should display
-- the longest match, the wildmenu should not be displayed.
feed(':sign u<Tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
:sign un^ |
- ]]}
- eq(0, funcs.wildmenumode())
+ ]],
+ }
+ eq(0, fn.wildmenumode())
-- pressing <Tab> should display the wildmenu
feed('<Tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{1:~ }{s: undefine }{1: }|
{1:~ }{n: unplace }{1: }|
:sign undefine^ |
- ]]}
- eq(1, funcs.wildmenumode())
+ ]],
+ }
+ eq(1, fn.wildmenumode())
-- pressing <Tab> second time should select the next entry in the menu
feed('<Tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{1:~ }{n: undefine }{1: }|
{1:~ }{s: unplace }{1: }|
:sign unplace^ |
- ]]}
+ ]],
+ }
end)
it('wildoptions=pum with a wrapped line in buffer vim-patch:8.2.4655', function()
screen:try_resize(32, 10)
- meths.buf_set_lines(0, 0, -1, true, { ('a'):rep(100) })
+ api.nvim_buf_set_lines(0, 0, -1, true, { ('a'):rep(100) })
command('set wildoptions+=pum')
feed('$')
feed(':sign <Tab>')
screen:expect([[
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
- aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|*3
aaaa {s: define } |
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3805,8 +3373,7 @@ describe('builtin popupmenu', function()
feed(':sign <C-E>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{s: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3820,8 +3387,7 @@ describe('builtin popupmenu', function()
feed('<C-E>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: define }{1: }|
{1:~ }{s: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3834,14 +3400,7 @@ describe('builtin popupmenu', function()
feed('<Esc>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
|
]])
@@ -3851,8 +3410,7 @@ describe('builtin popupmenu', function()
feed(':sign <Esc>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{s: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3865,14 +3423,7 @@ describe('builtin popupmenu', function()
feed('<Esc>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
|
]])
@@ -3882,8 +3433,7 @@ describe('builtin popupmenu', function()
feed([[:sign <C-\><C-\>]])
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{s: define }{1: }|
{1:~ }{n: jump }{1: }|
{1:~ }{n: list }{1: }|
@@ -3896,93 +3446,65 @@ describe('builtin popupmenu', function()
feed('<C-N>')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*8
|
]])
end)
end
it("'pumheight'", function()
- screen:try_resize(32,8)
+ screen:try_resize(32, 8)
feed('isome long prefix before the ')
- command("set completeopt+=noinsert,noselect")
- command("set linebreak")
- command("set pumheight=2")
- funcs.complete(29, {'word', 'choice', 'text', 'thing'})
+ command('set completeopt+=noinsert,noselect')
+ command('set linebreak')
+ command('set pumheight=2')
+ fn.complete(29, { 'word', 'choice', 'text', 'thing' })
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*7
[3:--------------------------------]|
## grid 2
some long prefix before the ^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
{2:-- INSERT --} |
## grid 4
{n: word }{c: }|
{n: choice}{s: }|
- ]], float_pos={
- [4] = {{id = -1}, "NW", 2, 1, 24, false, 100};
- }}
+ ]],
+ float_pos = {
+ [4] = { -1, 'NW', 2, 1, 24, false, 100 },
+ },
+ }
else
screen:expect([[
some long prefix before the ^ |
{1:~ }{n: word }{c: }|
{1:~ }{n: choice}{s: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{2:-- INSERT --} |
]])
end
end)
it("'pumwidth'", function()
- screen:try_resize(32,8)
+ screen:try_resize(32, 8)
feed('isome long prefix before the ')
- command("set completeopt+=noinsert,noselect")
- command("set linebreak")
- command("set pumwidth=8")
- funcs.complete(29, {'word', 'choice', 'text', 'thing'})
+ command('set completeopt+=noinsert,noselect')
+ command('set linebreak')
+ command('set pumwidth=8')
+ fn.complete(29, { 'word', 'choice', 'text', 'thing' })
if multigrid then
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*7
[3:--------------------------------]|
## grid 2
some long prefix before the ^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
{2:-- INSERT --} |
## grid 4
@@ -3990,9 +3512,11 @@ describe('builtin popupmenu', function()
{n: choice}|
{n: text }|
{n: thing }|
- ]], float_pos={
- [4] = {{id = -1}, "NW", 2, 1, 25, false, 100};
- }}
+ ]],
+ float_pos = {
+ [4] = { -1, 'NW', 2, 1, 25, false, 100 },
+ },
+ }
else
screen:expect([[
some long prefix before the ^ |
@@ -4000,8 +3524,7 @@ describe('builtin popupmenu', function()
{1:~ }{n: choice}|
{1:~ }{n: text }|
{1:~ }{n: thing }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:-- INSERT --} |
]])
end
@@ -4009,16 +3532,16 @@ describe('builtin popupmenu', function()
it('does not crash when displayed in the last column with rightleft #12032', function()
local col = 30
- local items = {'word', 'choice', 'text', 'thing'}
+ local items = { 'word', 'choice', 'text', 'thing' }
local max_len = 0
for _, v in ipairs(items) do
max_len = max_len < #v and #v or max_len
end
screen:try_resize(col, 8)
command('set rightleft')
- command('call setline(1, repeat(" ", &columns - '..max_len..'))')
+ command('call setline(1, repeat(" ", &columns - ' .. max_len .. '))')
feed('$i')
- funcs.complete(col - max_len, items)
+ fn.complete(col - max_len, items)
feed('<c-y>')
assert_alive()
end)
@@ -4027,91 +3550,66 @@ describe('builtin popupmenu', function()
screen:try_resize(32, 8)
command('set completeopt+=menuone,noselect')
feed('i' .. string.rep(' ', 13))
- funcs.complete(14, {'哦哦哦哦哦哦哦哦哦哦'})
+ fn.complete(14, { '哦哦哦哦哦哦哦哦哦哦' })
if multigrid then
- screen:expect({grid=[[
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*7
[3:--------------------------------]|
## grid 2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
{2:-- INSERT --} |
## grid 4
{n: 哦哦哦哦哦哦哦哦哦>}|
- ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 12, false, 100}}})
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 12, false, 100 } },
+ })
else
screen:expect([[
^ |
{1:~ }{n: 哦哦哦哦哦哦哦哦哦>}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{2:-- INSERT --} |
]])
end
end)
it('truncates double-width character correctly with scrollbar', function()
- screen:try_resize(32,8)
+ screen:try_resize(32, 8)
command('set completeopt+=noselect')
command('set pumheight=4')
feed('i' .. string.rep(' ', 12))
local items = {}
for _ = 1, 8 do
- table.insert(items, {word = '哦哦哦哦哦哦哦哦哦哦', equal = 1, dup = 1})
+ table.insert(items, { word = '哦哦哦哦哦哦哦哦哦哦', equal = 1, dup = 1 })
end
- funcs.complete(13, items)
+ fn.complete(13, items)
if multigrid then
- screen:expect({grid=[[
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*7
[3:--------------------------------]|
## grid 2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
## grid 3
{2:-- INSERT --} |
## grid 4
- {n: 哦哦哦哦哦哦哦哦哦>}{c: }|
- {n: 哦哦哦哦哦哦哦哦哦>}{c: }|
- {n: 哦哦哦哦哦哦哦哦哦>}{s: }|
- {n: 哦哦哦哦哦哦哦哦哦>}{s: }|
- ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 11, false, 100}}})
+ {n: 哦哦哦哦哦哦哦哦哦>}{c: }|*2
+ {n: 哦哦哦哦哦哦哦哦哦>}{s: }|*2
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 11, false, 100 } },
+ })
else
screen:expect([[
^ |
- {1:~ }{n: 哦哦哦哦哦哦哦哦哦>}{c: }|
- {1:~ }{n: 哦哦哦哦哦哦哦哦哦>}{c: }|
- {1:~ }{n: 哦哦哦哦哦哦哦哦哦>}{s: }|
- {1:~ }{n: 哦哦哦哦哦哦哦哦哦>}{s: }|
- {1:~ }|
- {1:~ }|
+ {1:~ }{n: 哦哦哦哦哦哦哦哦哦>}{c: }|*2
+ {1:~ }{n: 哦哦哦哦哦哦哦哦哦>}{s: }|*2
+ {1:~ }|*2
{2:-- INSERT --} |
]])
end
@@ -4130,28 +3628,24 @@ describe('builtin popupmenu', function()
]])
if multigrid then
- meths.input_mouse('right', 'press', '', 2, 0, 4)
- screen:expect({grid=[[
+ api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
{n: foo }|
{n: bar }|
{n: baz }|
- ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 3, false, 250}}})
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250 } },
+ })
else
feed('<RightMouse><4,0>')
screen:expect([[
@@ -4165,27 +3659,23 @@ describe('builtin popupmenu', function()
end
feed('<Down>')
if multigrid then
- screen:expect({grid=[[
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
{s: foo }|
{n: bar }|
{n: baz }|
- ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 3, false, 250}}})
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250 } },
+ })
else
screen:expect([[
^popup menu test |
@@ -4198,27 +3688,23 @@ describe('builtin popupmenu', function()
end
feed('<Down>')
if multigrid then
- screen:expect({grid=[[
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
|
## grid 4
{n: foo }|
{s: bar }|
{n: baz }|
- ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 3, false, 250}}})
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250 } },
+ })
else
screen:expect([[
^popup menu test |
@@ -4231,124 +3717,158 @@ describe('builtin popupmenu', function()
end
feed('<CR>')
if multigrid then
- screen:expect({grid=[[
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
:let g:menustr = 'bar' |
- ]]})
+ ]],
+ })
else
screen:expect([[
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
:let g:menustr = 'bar' |
]])
end
- eq('bar', meths.get_var('menustr'))
+ eq('bar', api.nvim_get_var('menustr'))
if multigrid then
- meths.input_mouse('right', 'press', '', 2, 2, 20)
- screen:expect({grid=[[
+ api.nvim_input_mouse('right', 'press', '', 2, 2, 20)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
:let g:menustr = 'bar' |
## grid 4
{n: foo }|
{n: bar }|
{n: baz }|
- ]], float_pos={[4] = {{id = -1}, 'NW', 2, 3, 19, false, 250}}})
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 3, 19, false, 250 } },
+ })
else
feed('<RightMouse><20,2>')
screen:expect([[
^popup menu test |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{1:~ }{n: foo }{1: }|
{1:~ }{n: bar }{1: }|
:let g:menustr = 'b{n: baz } |
]])
end
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 2, 2)
- screen:expect({grid=[[
+ api.nvim_input_mouse('right', 'press', '', 2, 0, 18)
+ screen:expect {
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
+ {1:~ }|*4
+ ## grid 3
+ :let g:menustr = 'bar' |
+ ## grid 4
+ {n: foo }|
+ {n: bar }|
+ {n: baz }|
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 17, false, 250 } },
+ }
+ else
+ feed('<RightMouse><18,0>')
+ screen:expect([[
+ ^popup menu test |
+ {1:~ }{n: foo }{1: }|
+ {1:~ }{n: bar }{1: }|
+ {1:~ }{n: baz }{1: }|
{1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ :let g:menustr = 'bar' |
+ ]])
+ end
+ if multigrid then
+ api.nvim_input_mouse('right', 'press', '', 4, 1, 3)
+ screen:expect({
+ grid = [[
+ ## grid 1
+ [2:--------------------------------]|*5
+ [3:--------------------------------]|
+ ## grid 2
+ ^popup menu test |
+ {1:~ }|*4
+ ## grid 3
+ :let g:menustr = 'bar' |
+ ## grid 4
+ {n: foo }|
+ {n: bar }|
+ {n: baz }|
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 3, 19, false, 250 } },
+ })
+ else
+ feed('<RightMouse><20,2>')
+ screen:expect([[
+ ^popup menu test |
+ {1:~ }|*2
+ {1:~ }{n: foo }{1: }|
+ {1:~ }{n: bar }{1: }|
+ :let g:menustr = 'b{n: baz } |
+ ]])
+ end
+ if multigrid then
+ api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
+ screen:expect({
+ grid = [[
+ ## grid 1
+ [2:--------------------------------]|*5
+ [3:--------------------------------]|
+ ## grid 2
+ ^popup menu test |
+ {1:~ }|*4
## grid 3
:let g:menustr = 'baz' |
- ]]})
+ ]],
+ })
else
- feed('<LeftMouse><22,5>')
+ feed('<LeftMouse><21,5>')
screen:expect([[
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
:let g:menustr = 'baz' |
]])
end
- eq('baz', meths.get_var('menustr'))
+ eq('baz', api.nvim_get_var('menustr'))
if multigrid then
- meths.input_mouse('right', 'press', '', 2, 0, 4)
- screen:expect({grid=[[
+ api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
:let g:menustr = 'baz' |
## grid 4
{n: foo }|
{n: bar }|
{n: baz }|
- ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 3, false, 250}}})
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250 } },
+ })
else
feed('<RightMouse><4,0>')
screen:expect([[
@@ -4361,28 +3881,24 @@ describe('builtin popupmenu', function()
]])
end
if multigrid then
- meths.input_mouse('right', 'drag', '', 2, 3, 6)
- screen:expect({grid=[[
+ api.nvim_input_mouse('right', 'drag', '', 2, 3, 6)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
:let g:menustr = 'baz' |
## grid 4
{n: foo }|
{n: bar }|
{s: baz }|
- ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 3, false, 250}}})
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250 } },
+ })
else
feed('<RightDrag><6,3>')
screen:expect([[
@@ -4395,61 +3911,49 @@ describe('builtin popupmenu', function()
]])
end
if multigrid then
- meths.input_mouse('right', 'release', '', 2, 1, 6)
- screen:expect({grid=[[
+ api.nvim_input_mouse('right', 'release', '', 2, 1, 6)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
:let g:menustr = 'foo' |
- ]]})
+ ]],
+ })
else
feed('<RightRelease><6,1>')
screen:expect([[
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
:let g:menustr = 'foo' |
]])
end
- eq('foo', meths.get_var('menustr'))
+ eq('foo', api.nvim_get_var('menustr'))
eq(false, screen.options.mousemoveevent)
if multigrid then
- meths.input_mouse('right', 'press', '', 2, 0, 4)
- screen:expect({grid=[[
+ api.nvim_input_mouse('right', 'press', '', 2, 0, 4)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
## grid 3
:let g:menustr = 'foo' |
## grid 4
{n: foo }|
{n: bar }|
{n: baz }|
- ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 3, false, 250}}})
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250 } },
+ })
else
feed('<RightMouse><4,0>')
screen:expect([[
@@ -4463,28 +3967,55 @@ describe('builtin popupmenu', function()
end
eq(true, screen.options.mousemoveevent)
if multigrid then
- meths.input_mouse('move', '', '', 2, 3, 6)
- screen:expect({grid=[[
+ api.nvim_input_mouse('wheel', 'up', '', 2, 0, 4)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
+ {1:~ }|*4
+ ## grid 3
+ :let g:menustr = 'foo' |
+ ## grid 4
+ {s: foo }|
+ {n: bar }|
+ {n: baz }|
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250 } },
+ })
+ else
+ feed('<ScrollWheelUp><4,0>')
+ screen:expect([[
+ ^popup menu test |
+ {1:~ }{s: foo }{1: }|
+ {1:~ }{n: bar }{1: }|
+ {1:~ }{n: baz }{1: }|
{1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ :let g:menustr = 'foo' |
+ ]])
+ end
+ eq(true, screen.options.mousemoveevent)
+ if multigrid then
+ api.nvim_input_mouse('move', '', '', 4, 2, 3)
+ screen:expect({
+ grid = [[
+ ## grid 1
+ [2:--------------------------------]|*5
+ [3:--------------------------------]|
+ ## grid 2
+ ^popup menu test |
+ {1:~ }|*4
## grid 3
:let g:menustr = 'foo' |
## grid 4
{n: foo }|
{n: bar }|
{s: baz }|
- ]], float_pos={[4] = {{id = -1}, 'NW', 2, 1, 3, false, 250}}})
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250 } },
+ })
else
feed('<MouseMove><6,3>')
screen:expect([[
@@ -4498,48 +4029,70 @@ describe('builtin popupmenu', function()
end
eq(true, screen.options.mousemoveevent)
if multigrid then
- meths.input_mouse('left', 'press', '', 2, 2, 6)
- screen:expect({grid=[[
+ api.nvim_input_mouse('wheel', 'down', '', 4, 2, 3)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*5
[3:--------------------------------]|
## grid 2
^popup menu test |
+ {1:~ }|*4
+ ## grid 3
+ :let g:menustr = 'foo' |
+ ## grid 4
+ {n: foo }|
+ {s: bar }|
+ {n: baz }|
+ ]],
+ float_pos = { [4] = { -1, 'NW', 2, 1, 3, false, 250 } },
+ })
+ else
+ feed('<ScrollWheelDown><6,3>')
+ screen:expect([[
+ ^popup menu test |
+ {1:~ }{n: foo }{1: }|
+ {1:~ }{s: bar }{1: }|
+ {1:~ }{n: baz }{1: }|
{1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ :let g:menustr = 'foo' |
+ ]])
+ end
+ eq(true, screen.options.mousemoveevent)
+ if multigrid then
+ api.nvim_input_mouse('left', 'press', '', 4, 1, 3)
+ screen:expect({
+ grid = [[
+ ## grid 1
+ [2:--------------------------------]|*5
+ [3:--------------------------------]|
+ ## grid 2
+ ^popup menu test |
+ {1:~ }|*4
## grid 3
:let g:menustr = 'bar' |
- ]]})
+ ]],
+ })
else
feed('<LeftMouse><6,2>')
screen:expect([[
^popup menu test |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
:let g:menustr = 'bar' |
]])
end
eq(false, screen.options.mousemoveevent)
- eq('bar', meths.get_var('menustr'))
+ eq('bar', api.nvim_get_var('menustr'))
command('set laststatus=0 | botright split')
if multigrid then
- meths.input_mouse('right', 'press', '', 5, 1, 20)
- screen:expect({grid=[[
+ api.nvim_input_mouse('right', 'press', '', 5, 1, 20)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*2
{3:[No Name] [+] }|
- [5:--------------------------------]|
- [5:--------------------------------]|
+ [5:--------------------------------]|*2
[3:--------------------------------]|
## grid 2
popup menu test |
@@ -4553,7 +4106,9 @@ describe('builtin popupmenu', function()
## grid 5
^popup menu test |
{1:~ }|
- ]], float_pos={[4] = {{id = -1}, "SW", 5, 1, 19, false, 250}}})
+ ]],
+ float_pos = { [4] = { -1, 'SW', 5, 1, 19, false, 250 } },
+ })
else
feed('<RightMouse><20,4>')
screen:expect([[
@@ -4566,14 +4121,13 @@ describe('builtin popupmenu', function()
]])
end
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 2, 2)
- screen:expect({grid=[[
+ api.nvim_input_mouse('left', 'press', '', 4, 2, 2)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*2
{3:[No Name] [+] }|
- [5:--------------------------------]|
- [5:--------------------------------]|
+ [5:--------------------------------]|*2
[3:--------------------------------]|
## grid 2
popup menu test |
@@ -4583,9 +4137,10 @@ describe('builtin popupmenu', function()
## grid 5
^popup menu test |
{1:~ }|
- ]]})
+ ]],
+ })
else
- feed('<LeftMouse><22,3>')
+ feed('<LeftMouse><21,3>')
screen:expect([[
popup menu test |
{1:~ }|
@@ -4595,18 +4150,17 @@ describe('builtin popupmenu', function()
:let g:menustr = 'baz' |
]])
end
- eq('baz', meths.get_var('menustr'))
+ eq('baz', api.nvim_get_var('menustr'))
command('set winwidth=1 | rightbelow vsplit')
if multigrid then
- meths.input_mouse('right', 'press', '', 6, 1, 14)
- screen:expect({grid=[[
+ api.nvim_input_mouse('right', 'press', '', 6, 1, 14)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*2
{3:[No Name] [+] }|
- [5:---------------]│[6:----------------]|
- [5:---------------]│[6:----------------]|
+ [5:---------------]│[6:----------------]|*2
[3:--------------------------------]|
## grid 2
popup menu test |
@@ -4623,7 +4177,9 @@ describe('builtin popupmenu', function()
## grid 6
^popup menu test |
{1:~ }|
- ]], float_pos={[4] = {{id = -1}, "SW", 6, 1, 12, false, 250}}})
+ ]],
+ float_pos = { [4] = { -1, 'SW', 6, 1, 12, false, 250 } },
+ })
else
feed('<RightMouse><30,4>')
screen:expect([[
@@ -4636,14 +4192,13 @@ describe('builtin popupmenu', function()
]])
end
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 0, 2)
- screen:expect({grid=[[
+ api.nvim_input_mouse('left', 'press', '', 4, 0, 2)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*2
{3:[No Name] [+] }|
- [5:---------------]│[6:----------------]|
- [5:---------------]│[6:----------------]|
+ [5:---------------]│[6:----------------]|*2
[3:--------------------------------]|
## grid 2
popup menu test |
@@ -4656,7 +4211,8 @@ describe('builtin popupmenu', function()
## grid 6
^popup menu test |
{1:~ }|
- ]]})
+ ]],
+ })
else
feed('<LeftMouse><31,1>')
screen:expect([[
@@ -4668,18 +4224,17 @@ describe('builtin popupmenu', function()
:let g:menustr = 'foo' |
]])
end
- eq('foo', meths.get_var('menustr'))
+ eq('foo', api.nvim_get_var('menustr'))
command('setlocal winbar=WINBAR')
if multigrid then
- meths.input_mouse('right', 'press', '', 6, 1, 14)
- screen:expect({grid=[[
+ api.nvim_input_mouse('right', 'press', '', 6, 1, 14)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*2
{3:[No Name] [+] }|
- [5:---------------]│[6:----------------]|
- [5:---------------]│[6:----------------]|
+ [5:---------------]│[6:----------------]|*2
[3:--------------------------------]|
## grid 2
popup menu test |
@@ -4696,7 +4251,9 @@ describe('builtin popupmenu', function()
## grid 6
{2:WINBAR }|
^popup menu test |
- ]], float_pos={[4] = {{id = -1}, "SW", 6, 1, 12, false, 250}}})
+ ]],
+ float_pos = { [4] = { -1, 'SW', 6, 1, 12, false, 250 } },
+ })
else
feed('<RightMouse><30,4>')
screen:expect([[
@@ -4709,14 +4266,13 @@ describe('builtin popupmenu', function()
]])
end
if multigrid then
- meths.input_mouse('left', 'press', '', 4, 1, 2)
- screen:expect({grid=[[
+ api.nvim_input_mouse('left', 'press', '', 4, 1, 2)
+ screen:expect({
+ grid = [[
## grid 1
- [2:--------------------------------]|
- [2:--------------------------------]|
+ [2:--------------------------------]|*2
{3:[No Name] [+] }|
- [5:---------------]│[6:----------------]|
- [5:---------------]│[6:----------------]|
+ [5:---------------]│[6:----------------]|*2
[3:--------------------------------]|
## grid 2
popup menu test |
@@ -4729,7 +4285,8 @@ describe('builtin popupmenu', function()
## grid 6
{2:WINBAR }|
^popup menu test |
- ]]})
+ ]],
+ })
else
feed('<LeftMouse><31,2>')
screen:expect([[
@@ -4741,7 +4298,7 @@ describe('builtin popupmenu', function()
:let g:menustr = 'bar' |
]])
end
- eq('bar', meths.get_var('menustr'))
+ eq('bar', api.nvim_get_var('menustr'))
end)
if not multigrid then
@@ -4779,13 +4336,7 @@ describe('builtin popupmenu', function()
{1:~ }{n: Select Line }{1: }|
{1:~ }{n: Select Block }{1: }|
{1:~ }{n: Select All }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
:popup PopUp |
]])
@@ -4804,13 +4355,7 @@ describe('builtin popupmenu', function()
{1:~ }{n: Select Line }{1: }|
{1:~ }{n: Select Block }{1: }|
{1:~ }{n: Select All }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
:popup PopUp |
]])
@@ -4829,13 +4374,7 @@ describe('builtin popupmenu', function()
{1:~ }{n: Select Line }{1: }|
{1:~ }{n: Select Block }{1: }|
{1:~ }{n: Select All }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
:popup PopUp |
]])
@@ -4859,13 +4398,7 @@ describe('builtin popupmenu', function()
{1:~ }{n: Select Line }{1: }|
{1:~ }{n: Select Block }{1: }|
{1:~ }{n: Select All }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*7
changed |
]])
@@ -4875,22 +4408,7 @@ describe('builtin popupmenu', function()
one two three four five |
and one two {7:^X}three four five |
one more two three four five |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*16
pasted |
]])
@@ -4911,12 +4429,7 @@ describe('builtin popupmenu', function()
{1:~ }{n: Select Line }{1: }|
{1:~ }{n: Select Block }{1: }|
{1:~ }{n: Select All }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*6
:popup PopUp |
]])
@@ -4951,9 +4464,7 @@ describe('builtin popupmenu', function()
{s:aword1 W extra text 1 }{1: }|
{n:aword2 W extra text 2 }{1: }|
{n:aword3 W extra text 3 }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:-- }{5:match 1 of 3} |
]])
end)
@@ -4967,21 +4478,22 @@ describe('builtin popupmenu', function()
hi PmenuExtraSel guifg=Black guibg=Grey
]])
local attrs = screen:get_default_attr_ids()
- attrs.kn = {foreground = Screen.colors.Red, background = Screen.colors.Magenta}
- attrs.ks = {foreground = Screen.colors.Red, background = Screen.colors.Grey}
- attrs.xn = {foreground = Screen.colors.White, background = Screen.colors.Magenta}
- attrs.xs = {foreground = Screen.colors.Black, background = Screen.colors.Grey}
+ attrs.kn = { foreground = Screen.colors.Red, background = Screen.colors.Magenta }
+ attrs.ks = { foreground = Screen.colors.Red, background = Screen.colors.Grey }
+ attrs.xn = { foreground = Screen.colors.White, background = Screen.colors.Magenta }
+ attrs.xs = { foreground = Screen.colors.Black, background = Screen.colors.Grey }
feed('iaw<C-X><C-u>')
- screen:expect([[
+ screen:expect(
+ [[
aword1^ |
{s:aword1 }{ks:W }{xs:extra text 1 }{1: }|
{n:aword2 }{kn:W }{xn:extra text 2 }{1: }|
{n:aword3 }{kn:W }{xn:extra text 3 }{1: }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
{2:-- }{5:match 1 of 3} |
- ]], attrs)
+ ]],
+ attrs
+ )
end)
end)
end
diff --git a/test/functional/ui/quickfix_spec.lua b/test/functional/ui/quickfix_spec.lua
index df43871e60..40f8ef353a 100644
--- a/test/functional/ui/quickfix_spec.lua
+++ b/test/functional/ui/quickfix_spec.lua
@@ -1,9 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, feed, meths = helpers.clear, helpers.feed, helpers.meths
+local clear, feed, api = helpers.clear, helpers.feed, helpers.api
local insert, command = helpers.insert, helpers.command
-
describe('quickfix selection highlight', function()
local screen
@@ -14,20 +13,20 @@ describe('quickfix selection highlight', function()
screen:attach()
screen:set_default_attr_ids({
[1] = { bold = true, foreground = Screen.colors.Blue },
- [2] = {reverse = true},
- [3] = {foreground = Screen.colors.Brown},
- [4] = {bold = true, reverse = true},
- [5] = {background = Screen.colors.Green},
- [6] = {foreground = Screen.colors.Brown, background = Screen.colors.Green},
- [7] = {background = Screen.colors.Red},
- [8] = {foreground = Screen.colors.Brown, background = Screen.colors.Red},
- [9] = {background = Screen.colors.Fuchsia},
- [10] = {foreground = Screen.colors.Red, background = Screen.colors.Fuchsia},
- [11] = {foreground = Screen.colors.Red},
- [12] = {foreground = Screen.colors.Brown, background = Screen.colors.Fuchsia},
+ [2] = { reverse = true },
+ [3] = { foreground = Screen.colors.Brown },
+ [4] = { bold = true, reverse = true },
+ [5] = { background = Screen.colors.Green },
+ [6] = { foreground = Screen.colors.Brown, background = Screen.colors.Green },
+ [7] = { background = Screen.colors.Red },
+ [8] = { foreground = Screen.colors.Brown, background = Screen.colors.Red },
+ [9] = { background = Screen.colors.Fuchsia },
+ [10] = { foreground = Screen.colors.Red, background = Screen.colors.Fuchsia },
+ [11] = { foreground = Screen.colors.Red },
+ [12] = { foreground = Screen.colors.Brown, background = Screen.colors.Fuchsia },
})
- meths.set_option_value('errorformat', '%m %l', {})
+ api.nvim_set_option_value('errorformat', '%m %l', {})
command('syntax on')
command('highlight Search guibg=Green')
@@ -49,9 +48,7 @@ describe('quickfix selection highlight', function()
Line 4 |
Line 5 |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
end)
@@ -89,7 +86,7 @@ describe('quickfix selection highlight', function()
end)
it('using QuickFixLine highlight group', function()
- command('highlight QuickFixLine guibg=Red')
+ command('highlight QuickFixLine guibg=Red guifg=NONE gui=NONE')
command('copen')
@@ -124,7 +121,7 @@ describe('quickfix selection highlight', function()
it('combines with CursorLine', function()
command('set cursorline')
- command('highlight QuickFixLine guifg=Red')
+ command('highlight QuickFixLine guifg=Red guibg=NONE gui=NONE')
command('highlight CursorLine guibg=Fuchsia')
command('copen')
@@ -160,7 +157,7 @@ describe('quickfix selection highlight', function()
it('QuickFixLine background takes precedence over CursorLine', function()
command('set cursorline')
- command('highlight QuickFixLine guibg=Red')
+ command('highlight QuickFixLine guibg=Red guifg=NONE gui=NONE')
command('highlight CursorLine guibg=Fuchsia')
command('copen')
diff --git a/test/functional/ui/screen.lua b/test/functional/ui/screen.lua
index 810a68d387..e8d7d5c72d 100644
--- a/test/functional/ui/screen.lua
+++ b/test/functional/ui/screen.lua
@@ -72,23 +72,44 @@
local helpers = require('test.functional.helpers')(nil)
local busted = require('busted')
-local deepcopy = helpers.deepcopy
+local deepcopy = vim.deepcopy
local shallowcopy = helpers.shallowcopy
local concat_tables = helpers.concat_tables
-local pesc = helpers.pesc
+local pesc = vim.pesc
local run_session = helpers.run_session
local eq = helpers.eq
local dedent = helpers.dedent
local get_session = helpers.get_session
local create_callindex = helpers.create_callindex
-local inspect = require('vim.inspect')
+local inspect = vim.inspect
local function isempty(v)
return type(v) == 'table' and next(v) == nil
end
+--- @class test.functional.ui.screen.Grid
+--- @field rows table[][]
+--- @field width integer
+--- @field height integer
+
--- @class test.functional.ui.screen
+--- @field colors table<string,integer>
+--- @field colornames table<integer,string>
+--- @field uimeths table<string,function>
+--- @field options? table<string,any>
+--- @field timeout integer
+--- @field win_position table<integer,table<string,integer>>
+--- @field float_pos table<integer,table>
+--- @field cmdline table<integer,table>
+--- @field cmdline_block table[]
+--- @field hl_groups table<string,integer>
+--- @field messages table<integer,table>
+--- @field private _cursor {grid:integer,row:integer,col:integer}
+--- @field private _grids table<integer,test.functional.ui.screen.Grid>
+--- @field private _grid_win_extmarks table<integer,table>
+--- @field private _attr_table table<integer,table>
+--- @field private _hl_info table<integer,table>
local Screen = {}
Screen.__index = Screen
@@ -103,13 +124,14 @@ end
local default_screen_timeout = default_timeout_factor * 3500
-function Screen._init_colors(session)
+local function _init_colors()
+ local session = get_session()
local status, rv = session:request('nvim_get_color_map')
if not status then
error('failed to get color map')
end
- local colors = rv
- local colornames = {}
+ local colors = rv --- @type table<string,integer>
+ local colornames = {} --- @type table<integer,string>
for name, rgb in pairs(colors) do
-- we disregard the case that colornames might not be unique, as
-- this is just a helper to get any canonical name of a color
@@ -119,17 +141,14 @@ function Screen._init_colors(session)
Screen.colornames = colornames
end
+--- @param width? integer
+--- @param height? integer
+--- @return test.functional.ui.screen
function Screen.new(width, height)
if not Screen.colors then
- Screen._init_colors(get_session())
+ _init_colors()
end
- if not width then
- width = 53
- end
- if not height then
- height = 14
- end
local self = setmetatable({
timeout = default_screen_timeout,
title = '',
@@ -140,6 +159,7 @@ function Screen.new(width, height)
suspended = false,
mode = 'normal',
options = {},
+ pwd = '',
popupmenu = nil,
cmdline = {},
cmdline_block = {},
@@ -161,30 +181,35 @@ function Screen.new(width, height)
_default_attr_ids = nil,
mouse_enabled = true,
_attrs = {},
- _hl_info = {[0]={}},
- _attr_table = {[0]={{},{}}},
+ _hl_info = { [0] = {} },
+ _attr_table = { [0] = { {}, {} } },
_clear_attrs = nil,
_new_attrs = false,
- _width = width,
- _height = height,
+ _width = width or 53,
+ _height = height or 14,
_grids = {},
_grid_win_extmarks = {},
_cursor = {
- grid = 1, row = 1, col = 1
+ grid = 1,
+ row = 1,
+ col = 1,
},
_busy = false,
}, Screen)
+
local function ui(method, ...)
if self.rpc_async then
- self._session:notify('nvim_ui_'..method, ...)
+ self._session:notify('nvim_ui_' .. method, ...)
else
- local status, rv = self._session:request('nvim_ui_'..method, ...)
+ local status, rv = self._session:request('nvim_ui_' .. method, ...)
if not status then
error(rv[2])
end
end
end
+
self.uimeths = create_callindex(ui)
+
return self
end
@@ -200,13 +225,21 @@ function Screen:set_rgb_cterm(val)
self._rgb_cterm = val
end
+--- @class test.functional.ui.screen.Opts
+--- @field ext_linegrid? boolean
+--- @field ext_multigrid? boolean
+--- @field ext_newgrid? boolean
+--- @field ext_popupmenu? boolean
+--- @field ext_wildmenu? boolean
+--- @field rgb? boolean
+--- @field _debug_float? boolean
+
+--- @param options test.functional.ui.screen.Opts
+--- @param session? test.Session
function Screen:attach(options, session)
- if session == nil then
- session = get_session()
- end
- if options == nil then
- options = {}
- end
+ session = session or get_session()
+ options = options or {}
+
if options.ext_linegrid == nil then
options.ext_linegrid = true
end
@@ -241,106 +274,178 @@ function Screen:try_resize_grid(grid, columns, rows)
self.uimeths.try_resize_grid(grid, columns, rows)
end
+--- @param option 'ext_linegrid'|'ext_multigrid'|'ext_popupmenu'|'ext_wildmenu'|'rgb'
+--- @param value boolean
function Screen:set_option(option, value)
self.uimeths.set_option(option, value)
+ --- @diagnostic disable-next-line:no-unknown
self._options[option] = value
end
-- canonical order of ext keys, used to generate asserts
local ext_keys = {
- 'popupmenu', 'cmdline', 'cmdline_block', 'wildmenu_items', 'wildmenu_pos',
- 'messages', 'msg_history', 'showmode', 'showcmd', 'ruler', 'float_pos', 'win_viewport'
+ 'popupmenu',
+ 'cmdline',
+ 'cmdline_block',
+ 'wildmenu_items',
+ 'wildmenu_pos',
+ 'messages',
+ 'msg_history',
+ 'showmode',
+ 'showcmd',
+ 'ruler',
+ 'float_pos',
+ 'win_viewport',
}
--- Asserts that the screen state eventually matches an expected state.
---
--- Can be called with positional args:
--- screen:expect(grid, [attr_ids])
--- screen:expect(condition)
--- or keyword args (supports more options):
--- screen:expect{grid=[[...]], cmdline={...}, condition=function() ... end}
---
---
--- grid: Expected screen state (string). Each line represents a screen
--- row. Last character of each row (typically "|") is stripped.
--- Common indentation is stripped.
--- "{MATCH:x}" in a line is matched against Lua pattern `x`.
--- attr_ids: Expected text attributes. Screen rows are transformed according
--- to this table, as follows: each substring S composed of
--- characters having the same attributes will be substituted by
--- "{K:S}", where K is a key in `attr_ids`. Any unexpected
--- attributes in the final state are an error.
--- Use screen:set_default_attr_ids() to define attributes for many
--- expect() calls.
--- extmarks: Expected win_extmarks accumulated for the grids. For each grid,
--- the win_extmark messages are accumulated into an array.
--- condition: Function asserting some arbitrary condition. Return value is
--- ignored, throw an error (use eq() or similar) to signal failure.
--- any: Lua pattern string expected to match a screen line. NB: the
--- following chars are magic characters
--- ( ) . % + - * ? [ ^ $
--- and must be escaped with a preceding % for a literal match.
--- mode: Expected mode as signaled by "mode_change" event
--- unchanged: Test that the screen state is unchanged since the previous
--- expect(...). Any flush event resulting in a different state is
--- considered an error. Not observing any events until timeout
--- is acceptable.
--- intermediate:Test that the final state is the same as the previous expect,
--- but expect an intermediate state that is different. If possible
--- it is better to use an explicit screen:expect(...) for this
--- intermediate state.
--- reset: Reset the state internal to the test Screen before starting to
--- receive updates. This should be used after command("redraw!")
--- or some other mechanism that will invoke "redraw!", to check
--- that all screen state is transmitted again. This includes
--- state related to ext_ features as mentioned below.
--- timeout: maximum time that will be waited until the expected state is
--- seen (or maximum time to observe an incorrect change when
--- `unchanged` flag is used)
---
--- The following keys should be used to expect the state of various ext_
--- features. Note that an absent key will assert that the item is currently
--- NOT present on the screen, also when positional form is used.
---
--- popupmenu: Expected ext_popupmenu state,
--- cmdline: Expected ext_cmdline state, as an array of cmdlines of
--- different level.
--- cmdline_block: Expected ext_cmdline block (for function definitions)
--- wildmenu_items: Expected items for ext_wildmenu
--- wildmenu_pos: Expected position for ext_wildmenu
+local expect_keys = {
+ grid = true,
+ attr_ids = true,
+ condition = true,
+ mouse_enabled = true,
+ any = true,
+ mode = true,
+ unchanged = true,
+ intermediate = true,
+ reset = true,
+ timeout = true,
+ request_cb = true,
+ hl_groups = true,
+ extmarks = true,
+}
+
+for _, v in ipairs(ext_keys) do
+ expect_keys[v] = true
+end
+
+--- @class test.function.ui.screen.Expect
+---
+--- Expected screen state (string). Each line represents a screen
+--- row. Last character of each row (typically "|") is stripped.
+--- Common indentation is stripped.
+--- "{MATCH:x}" in a line is matched against Lua pattern `x`.
+--- "*n" at the end of a line means it repeats `n` times.
+--- @field grid? string
+---
+--- Expected text attributes. Screen rows are transformed according
+--- to this table, as follows: each substring S composed of
+--- characters having the same attributes will be substituted by
+--- "{K:S}", where K is a key in `attr_ids`. Any unexpected
+--- attributes in the final state are an error.
+--- Use an empty table for a text-only (no attributes) expectation.
+--- Use screen:set_default_attr_ids() to define attributes for many
+--- expect() calls.
+--- @field attr_ids? table<integer,table<string,any>>
+---
+--- Expected win_extmarks accumulated for the grids. For each grid,
+--- the win_extmark messages are accumulated into an array.
+--- @field extmarks? table<integer,table>
+---
+--- Function asserting some arbitrary condition. Return value is
+--- ignored, throw an error (use eq() or similar) to signal failure.
+--- @field condition? fun()
+---
+--- Lua pattern string expected to match a screen line. NB: the
+--- following chars are magic characters
+--- ( ) . % + - * ? [ ^ $
+--- and must be escaped with a preceding % for a literal match.
+--- @field any? string
+---
+--- Expected mode as signaled by "mode_change" event
+--- @field mode? string
+---
+--- Test that the screen state is unchanged since the previous
+--- expect(...). Any flush event resulting in a different state is
+--- considered an error. Not observing any events until timeout
+--- is acceptable.
+--- @field unchanged? boolean
+---
+--- Test that the final state is the same as the previous expect,
+--- but expect an intermediate state that is different. If possible
+--- it is better to use an explicit screen:expect(...) for this
+--- intermediate state.
+--- @field intermediate? boolean
+---
+--- Reset the state internal to the test Screen before starting to
+--- receive updates. This should be used after command("redraw!")
+--- or some other mechanism that will invoke "redraw!", to check
+--- that all screen state is transmitted again. This includes
+--- state related to ext_ features as mentioned below.
+--- @field reset? boolean
+---
+--- maximum time that will be waited until the expected state is
+--- seen (or maximum time to observe an incorrect change when
+--- `unchanged` flag is used)
+--- @field timeout? integer
+---
+--- @field mouse_enabled? boolean
+---
+--- @field win_viewport? table<integer,table<string,integer>>
+--- @field float_pos? {[1]:integer,[2]:integer}
+--- @field hl_groups? table<string,integer>
+---
+--- The following keys should be used to expect the state of various ext_
+--- features. Note that an absent key will assert that the item is currently
+--- NOT present on the screen, also when positional form is used.
+---
+--- Expected ext_popupmenu state,
+--- @field popupmenu? table
+---
+--- Expected ext_cmdline state, as an array of cmdlines of
+--- different level.
+--- @field cmdline? table
+---
+--- Expected ext_cmdline block (for function definitions)
+--- @field cmdline_block? table
+---
+--- items for ext_wildmenu
+--- @field wildmenu_items? table
+---
+--- position for ext_wildmenu
+--- @field wildmenu_pos? table
+
+--- Asserts that the screen state eventually matches an expected state.
+---
+--- Can be called with positional args:
+--- screen:expect(grid, [attr_ids])
+--- screen:expect(condition)
+--- or keyword args (supports more options):
+--- screen:expect{grid=[[...]], cmdline={...}, condition=function() ... end}
+---
+--- @param expected string|function|test.function.ui.screen.Expect
+--- @param attr_ids? table<integer,table<string,any>>
function Screen:expect(expected, attr_ids, ...)
- local grid, condition = nil, nil
- local expected_rows = {}
- assert(next({...}) == nil, "invalid args to expect()")
- if type(expected) == "table" then
- assert(not (attr_ids ~= nil))
- local is_key = {grid=true, attr_ids=true, condition=true, mouse_enabled=true,
- any=true, mode=true, unchanged=true, intermediate=true,
- reset=true, timeout=true, request_cb=true, hl_groups=true, extmarks=true}
- for _, v in ipairs(ext_keys) do
- is_key[v] = true
- end
- for k, _ in pairs(expected) do
- if not is_key[k] then
- error("Screen:expect: Unknown keyword argument '"..k.."'")
+ --- @type string, fun()
+ local grid, condition
+
+ assert(next({ ... }) == nil, 'invalid args to expect()')
+
+ if type(expected) == 'table' then
+ assert(attr_ids == nil)
+ for k, _ in
+ pairs(expected --[[@as table<string,any>]])
+ do
+ if not expect_keys[k] then
+ error("Screen:expect: Unknown keyword argument '" .. k .. "'")
end
end
grid = expected.grid
attr_ids = expected.attr_ids
condition = expected.condition
- assert(not (expected.any ~= nil and grid ~= nil))
- elseif type(expected) == "string" then
+ assert(expected.any == nil or grid == nil)
+ elseif type(expected) == 'string' then
grid = expected
expected = {}
- elseif type(expected) == "function" then
- assert(not (attr_ids ~= nil))
+ elseif type(expected) == 'function' then
+ assert(attr_ids == nil)
condition = expected
expected = {}
else
assert(false)
end
- if grid ~= nil then
+ local expected_rows = {} --- @type string[]
+ if grid then
-- Remove the last line and dedent. Note that gsub returns more then one
-- value.
grid = dedent(grid:gsub('\n[ ]+$', ''), 0)
@@ -348,15 +453,23 @@ function Screen:expect(expected, attr_ids, ...)
table.insert(expected_rows, row)
end
end
+
local attr_state = {
- ids = attr_ids or self._default_attr_ids,
+ ids = attr_ids or self._default_attr_ids,
}
+
+ if isempty(attr_ids) then
+ attr_state.ids = nil
+ end
+
if self._options.ext_linegrid then
attr_state.id_to_index = self:linegrid_check_attrs(attr_state.ids or {})
end
+
self._new_attrs = false
self:_wait(function()
- if condition ~= nil then
+ if condition then
+ --- @type boolean, string
local status, res = pcall(condition)
if not status then
return tostring(res)
@@ -369,27 +482,47 @@ function Screen:expect(expected, attr_ids, ...)
local actual_rows = self:render(not expected.any, attr_state)
- if expected.any ~= nil then
+ if expected.any then
-- Search for `any` anywhere in the screen lines.
local actual_screen_str = table.concat(actual_rows, '\n')
- if nil == string.find(actual_screen_str, expected.any) then
+ if not actual_screen_str:find(expected.any) then
return (
'Failed to match any screen lines.\n'
- .. 'Expected (anywhere): "' .. expected.any .. '"\n'
- .. 'Actual:\n |' .. table.concat(actual_rows, '\n |') .. '\n\n')
+ .. 'Expected (anywhere): "'
+ .. expected.any
+ .. '"\n'
+ .. 'Actual:\n |'
+ .. table.concat(actual_rows, '\n |')
+ .. '\n\n'
+ )
end
end
- if grid ~= nil then
- local err_msg, msg_expected_rows = nil, {}
+ if grid then
+ for i, row in ipairs(expected_rows) do
+ local count --- @type integer?
+ row, count = row:match('^(.*%|)%*(%d+)$')
+ if row then
+ count = tonumber(count)
+ table.remove(expected_rows, i)
+ for _ = 1, count do
+ table.insert(expected_rows, i, row)
+ end
+ end
+ end
+ local err_msg = nil
-- `expected` must match the screen lines exactly.
if #actual_rows ~= #expected_rows then
- err_msg = "Expected screen height " .. #expected_rows
- .. ' differs from actual height ' .. #actual_rows .. '.'
+ err_msg = 'Expected screen height '
+ .. #expected_rows
+ .. ' differs from actual height '
+ .. #actual_rows
+ .. '.'
end
+ local msg_expected_rows = shallowcopy(expected_rows)
+ local msg_actual_rows = shallowcopy(actual_rows)
for i, row in ipairs(expected_rows) do
- msg_expected_rows[i] = row
- local pat = nil
+ local pat = nil --- @type string?
if actual_rows[i] and row ~= actual_rows[i] then
local after = row
while true do
@@ -398,6 +531,7 @@ function Screen:expect(expected, attr_ids, ...)
pat = pat and (pat .. pesc(after))
break
end
+ --- @type string
pat = (pat or '') .. pesc(after:sub(1, s - 1)) .. m
after = after:sub(e + 1)
end
@@ -405,7 +539,7 @@ function Screen:expect(expected, attr_ids, ...)
if row ~= actual_rows[i] and (not pat or not actual_rows[i]:match(pat)) then
msg_expected_rows[i] = '*' .. msg_expected_rows[i]
if i <= #actual_rows then
- actual_rows[i] = '*' .. actual_rows[i]
+ msg_actual_rows[i] = '*' .. msg_actual_rows[i]
end
if err_msg == nil then
err_msg = 'Row ' .. tostring(i) .. ' did not match.'
@@ -414,11 +548,18 @@ function Screen:expect(expected, attr_ids, ...)
end
if err_msg ~= nil then
return (
- err_msg..'\nExpected:\n |'..table.concat(msg_expected_rows, '\n |')..'\n'
- ..'Actual:\n |'..table.concat(actual_rows, '\n |')..'\n\n'..[[
+ err_msg
+ .. '\nExpected:\n |'
+ .. table.concat(msg_expected_rows, '\n |')
+ .. '\n'
+ .. 'Actual:\n |'
+ .. table.concat(msg_actual_rows, '\n |')
+ .. '\n\n'
+ .. [[
To print the expect() call that would assert the current screen state, use
screen:snapshot_util(). In case of non-deterministic failures, use
-screen:redraw_debug() to show all intermediate screen states. ]])
+screen:redraw_debug() to show all intermediate screen states.]]
+ )
end
end
@@ -447,12 +588,18 @@ screen:redraw_debug() to show all intermediate screen states. ]])
end
-- Convert assertion errors into invalid screen state descriptions.
- for _, k in ipairs(concat_tables(ext_keys, {'mode', 'mouse_enabled'})) do
+ for _, k in ipairs(concat_tables(ext_keys, { 'mode', 'mouse_enabled' })) do
-- Empty states are considered the default and need not be mentioned.
- if (not (expected[k] == nil and isempty(extstate[k]))) then
+ if not (expected[k] == nil and isempty(extstate[k])) then
local status, res = pcall(eq, expected[k], extstate[k], k)
if not status then
- return (tostring(res)..'\nHint: full state of "'..k..'":\n '..inspect(extstate[k]))
+ return (
+ tostring(res)
+ .. '\nHint: full state of "'
+ .. k
+ .. '":\n '
+ .. inspect(extstate[k])
+ )
end
end
end
@@ -461,7 +608,7 @@ screen:redraw_debug() to show all intermediate screen states. ]])
for name, id in pairs(expected.hl_groups) do
local expected_hl = attr_state.ids[id]
local actual_hl = self._attr_table[self.hl_groups[name]][(self._options.rgb and 1) or 2]
- local status, res = pcall(eq, expected_hl, actual_hl, "highlight "..name)
+ local status, res = pcall(eq, expected_hl, actual_hl, 'highlight ' .. name)
if not status then
return tostring(res)
end
@@ -472,9 +619,10 @@ screen:redraw_debug() to show all intermediate screen states. ]])
for gridid, expected_marks in pairs(expected.extmarks) do
local stored_marks = self._grid_win_extmarks[gridid]
if stored_marks == nil then
- return 'no win_extmark for grid '..tostring(gridid)
+ return 'no win_extmark for grid ' .. tostring(gridid)
end
- local status, res = pcall(eq, expected_marks, stored_marks, "extmarks for grid "..tostring(gridid))
+ local status, res =
+ pcall(eq, expected_marks, stored_marks, 'extmarks for grid ' .. tostring(gridid))
if not status then
return tostring(res)
end
@@ -482,7 +630,7 @@ screen:redraw_debug() to show all intermediate screen states. ]])
for gridid, _ in pairs(self._grid_win_extmarks) do
local expected_marks = expected.extmarks[gridid]
if expected_marks == nil then
- return 'unexpected win_extmark for grid '..tostring(gridid)
+ return 'unexpected win_extmark for grid ' .. tostring(gridid)
end
end
end
@@ -490,7 +638,6 @@ screen:redraw_debug() to show all intermediate screen states. ]])
end
function Screen:expect_unchanged(intermediate, waittime_ms, ignore_attrs)
- waittime_ms = waittime_ms and waittime_ms or 100
-- Collect the current screen state.
local kwargs = self:get_snapshot(nil, ignore_attrs)
@@ -505,8 +652,12 @@ function Screen:expect_unchanged(intermediate, waittime_ms, ignore_attrs)
self:expect(kwargs)
end
+--- @private
+--- @param check fun(): string
+--- @param flags table<string,any>
function Screen:_wait(check, flags)
- local err, checked = false, false
+ local err --- @type string?
+ local checked = false
local success_seen = false
local failure_after_success = false
local did_flush = true
@@ -537,16 +688,18 @@ function Screen:_wait(check, flags)
-- For an "unchanged" test, flags.timeout is the time during which the state
-- must not change, so always wait this full time.
- if (flags.unchanged or flags.intermediate) and flags.timeout ~= nil then
- minimal_timeout = timeout
+ if flags.unchanged then
+ minimal_timeout = flags.timeout or default_timeout_factor * 20
end
assert(timeout >= minimal_timeout)
local did_minimal_timeout = false
local function notification_cb(method, args)
- assert(method == 'redraw', string.format(
- 'notification_cb: unexpected method (%s, args=%s)', method, inspect(args)))
+ assert(
+ method == 'redraw',
+ string.format('notification_cb: unexpected method (%s, args=%s)', method, inspect(args))
+ )
did_flush = self:_redraw(args)
if not did_flush then
return
@@ -557,12 +710,12 @@ function Screen:_wait(check, flags)
intermediate_seen = true
end
- if not err then
+ if not err and (not flags.intermediate or intermediate_seen) then
success_seen = true
if did_minimal_timeout then
self._session:stop()
end
- elseif success_seen and #args > 0 then
+ elseif err and success_seen and #args > 0 then
success_seen = false
failure_after_success = true
-- print(inspect(args))
@@ -572,7 +725,7 @@ function Screen:_wait(check, flags)
end
local eof = run_session(self._session, flags.request_cb, notification_cb, nil, minimal_timeout)
if not did_flush then
- err = "no flush received"
+ err = 'no flush received'
elseif not checked then
err = check()
if not err and flags.unchanged then
@@ -583,12 +736,13 @@ function Screen:_wait(check, flags)
if not success_seen and not eof then
did_minimal_timeout = true
- eof = run_session(self._session, flags.request_cb, notification_cb, nil, timeout-minimal_timeout)
+ eof =
+ run_session(self._session, flags.request_cb, notification_cb, nil, timeout - minimal_timeout)
end
local did_warn = false
if warn_immediate and immediate_seen then
- print([[
+ print([[
warning: Screen test succeeded immediately. Try to avoid this unless the
purpose of the test really requires it.]])
@@ -622,21 +776,24 @@ between asynchronous (feed(), nvim_input()) and synchronous API calls.
did_warn = true
end
-
if err then
- if eof then err = err..'\n\n'..eof[2] end
- busted.fail(err, 3)
+ if eof then
+ err = err .. '\n\n' .. eof[2]
+ end
+ busted.fail(err .. '\n\nSnapshot:\n' .. self:_print_snapshot(), 3)
elseif did_warn then
- if eof then print(eof[2]) end
+ if eof then
+ print(eof[2])
+ end
local tb = debug.traceback()
local index = string.find(tb, '\n%s*%[C]')
- print(string.sub(tb,1,index))
+ print(string.sub(tb, 1, index))
end
if flags.intermediate then
- assert(intermediate_seen, "expected intermediate screen state before final screen state")
+ assert(intermediate_seen, 'expected intermediate screen state before final screen state')
elseif flags.unchanged then
- assert(not intermediate_seen, "expected screen state to be unchanged")
+ assert(not intermediate_seen, 'expected screen state to be unchanged')
end
end
@@ -648,23 +805,31 @@ function Screen:sleep(ms, request_cb)
run_session(self._session, request_cb, notification_cb, nil, ms)
end
+--- @private
+--- @param updates {[1]:string, [integer]:any[]}[]
function Screen:_redraw(updates)
local did_flush = false
for k, update in ipairs(updates) do
-- print('--', inspect(update))
local method = update[1]
for i = 2, #update do
- local handler_name = '_handle_'..method
+ local handler_name = '_handle_' .. method
+ --- @type function
local handler = self[handler_name]
- assert(handler ~= nil, "missing handler: Screen:"..handler_name)
+ assert(handler ~= nil, 'missing handler: Screen:' .. handler_name)
local status, res = pcall(handler, self, unpack(update[i]))
if not status then
- error(handler_name..' failed'
- ..'\n payload: '..inspect(update)
- ..'\n error: '..tostring(res))
+ error(
+ handler_name
+ .. ' failed'
+ .. '\n payload: '
+ .. inspect(update)
+ .. '\n error: '
+ .. tostring(res)
+ )
end
end
- if k == #updates and method == "flush" then
+ if k == #updates and method == 'flush' then
did_flush = true
end
end
@@ -674,12 +839,15 @@ end
function Screen:_handle_resize(width, height)
self:_handle_grid_resize(1, width, height)
self._scroll_region = {
- top = 1, bot = height, left = 1, right = width
+ top = 1,
+ bot = height,
+ left = 1,
+ right = width,
}
self._grid = self._grids[1]
end
-local function min(x,y)
+local function min(x, y)
if x < y then
return x
else
@@ -692,14 +860,14 @@ function Screen:_handle_grid_resize(grid, width, height)
for _ = 1, height do
local cols = {}
for _ = 1, width do
- table.insert(cols, {text = ' ', attrs = self._clear_attrs, hl_id = 0})
+ table.insert(cols, { text = ' ', attrs = self._clear_attrs, hl_id = 0 })
end
table.insert(rows, cols)
end
if grid > 1 and self._grids[grid] ~= nil then
local old = self._grids[grid]
- for i = 1, min(height,old.height) do
- for j = 1, min(width,old.width) do
+ for i = 1, min(height, old.height) do
+ for j = 1, min(width, old.width) do
rows[i][j] = old.rows[i][j]
end
end
@@ -710,13 +878,12 @@ function Screen:_handle_grid_resize(grid, width, height)
self._cursor.col = 1
end
self._grids[grid] = {
- rows=rows,
- width=width,
- height=height,
+ rows = rows,
+ width = width,
+ height = height,
}
end
-
function Screen:_handle_msg_set_pos(grid, row, scrolled, char)
self.msg_grid = grid
self.msg_grid_pos = row
@@ -724,8 +891,7 @@ function Screen:_handle_msg_set_pos(grid, row, scrolled, char)
self.msg_sep_char = char
end
-function Screen:_handle_flush()
-end
+function Screen:_handle_flush() end
function Screen:_reset()
-- TODO: generalize to multigrid later
@@ -740,18 +906,20 @@ function Screen:_reset()
self._grid_win_extmarks = {}
end
+--- @param cursor_style_enabled boolean
+--- @param mode_info table[]
function Screen:_handle_mode_info_set(cursor_style_enabled, mode_info)
self._cursor_style_enabled = cursor_style_enabled
for _, item in pairs(mode_info) do
- -- attr IDs are not stable, but their value should be
- if item.attr_id ~= nil then
- item.attr = self._attr_table[item.attr_id][1]
- item.attr_id = nil
- end
- if item.attr_id_lm ~= nil then
- item.attr_lm = self._attr_table[item.attr_id_lm][1]
- item.attr_id_lm = nil
- end
+ -- attr IDs are not stable, but their value should be
+ if item.attr_id ~= nil then
+ item.attr = self._attr_table[item.attr_id][1]
+ item.attr_id = nil
+ end
+ if item.attr_id_lm ~= nil then
+ item.attr_lm = self._attr_table[item.attr_id_lm][1]
+ item.attr_id_lm = nil
+ end
end
self._mode_info = mode_info
end
@@ -763,7 +931,10 @@ function Screen:_handle_clear()
-- newer clients, to check we remain compatible with both kind of clients,
-- ensure the scroll region is in a reset state.
local expected_region = {
- top = 1, bot = self._grid.height, left = 1, right = self._grid.width
+ top = 1,
+ bot = self._grid.height,
+ left = 1,
+ right = self._grid.width,
}
eq(expected_region, self._scroll_region)
self:_handle_grid_clear(1)
@@ -804,14 +975,24 @@ function Screen:_handle_win_pos(grid, win, startrow, startcol, width, height)
startrow = startrow,
startcol = startcol,
width = width,
- height = height
+ height = height,
}
self.float_pos[grid] = nil
end
-function Screen:_handle_win_viewport(grid, win, topline, botline, curline, curcol, linecount, scroll_delta)
+function Screen:_handle_win_viewport(
+ grid,
+ win,
+ topline,
+ botline,
+ curline,
+ curcol,
+ linecount,
+ scroll_delta
+)
-- accumulate scroll delta
- local last_scroll_delta = self.win_viewport[grid] and self.win_viewport[grid].sum_scroll_delta or 0
+ local last_scroll_delta = self.win_viewport[grid] and self.win_viewport[grid].sum_scroll_delta
+ or 0
self.win_viewport[grid] = {
win = win,
topline = topline,
@@ -819,18 +1000,18 @@ function Screen:_handle_win_viewport(grid, win, topline, botline, curline, curco
curline = curline,
curcol = curcol,
linecount = linecount,
- sum_scroll_delta = scroll_delta + last_scroll_delta
+ sum_scroll_delta = scroll_delta + last_scroll_delta,
}
end
function Screen:_handle_win_float_pos(grid, ...)
self.win_position[grid] = nil
- self.float_pos[grid] = {...}
+ self.float_pos[grid] = { ... }
end
function Screen:_handle_win_external_pos(grid)
self.win_position[grid] = nil
- self.float_pos[grid] = {external=true}
+ self.float_pos[grid] = { external = true }
end
function Screen:_handle_win_hide(grid)
@@ -846,7 +1027,7 @@ function Screen:_handle_win_extmark(grid, ...)
if self._grid_win_extmarks[grid] == nil then
self._grid_win_extmarks[grid] = {}
end
- table.insert(self._grid_win_extmarks[grid], {...})
+ table.insert(self._grid_win_extmarks[grid], { ... })
end
function Screen:_handle_busy_start()
@@ -866,7 +1047,7 @@ function Screen:_handle_mouse_off()
end
function Screen:_handle_mode_change(mode, idx)
- assert(mode == self._mode_info[idx+1].name)
+ assert(mode == self._mode_info[idx + 1].name)
self.mode = mode
end
@@ -882,17 +1063,24 @@ function Screen:_handle_scroll(count)
local bot = self._scroll_region.bot
local left = self._scroll_region.left
local right = self._scroll_region.right
- self:_handle_grid_scroll(1, top-1, bot, left-1, right, count, 0)
+ self:_handle_grid_scroll(1, top - 1, bot, left - 1, right, count, 0)
end
+--- @param g any
+--- @param top integer
+--- @param bot integer
+--- @param left integer
+--- @param right integer
+--- @param rows integer
+--- @param cols integer
function Screen:_handle_grid_scroll(g, top, bot, left, right, rows, cols)
- top = top+1
- left = left+1
+ top = top + 1
+ left = left + 1
assert(cols == 0)
local grid = self._grids[g]
+ --- @type integer, integer, integer
local start, stop, step
-
if rows > 0 then
start = top
stop = bot - rows
@@ -921,11 +1109,13 @@ function Screen:_handle_grid_scroll(g, top, bot, left, right, rows, cols)
end
function Screen:_handle_hl_attr_define(id, rgb_attrs, cterm_attrs, info)
- self._attr_table[id] = {rgb_attrs, cterm_attrs}
+ self._attr_table[id] = { rgb_attrs, cterm_attrs }
self._hl_info[id] = info
self._new_attrs = true
end
+--- @param name string
+--- @param id integer
function Screen:_handle_hl_group_set(name, id)
self.hl_groups[name] = id
end
@@ -933,9 +1123,8 @@ end
function Screen:get_hl(val)
if self._options.ext_newgrid then
return self._attr_table[val][1]
- else
- return val
end
+ return val
end
function Screen:_handle_highlight_set(attrs)
@@ -951,14 +1140,18 @@ function Screen:_handle_put(str)
self._cursor.col = self._cursor.col + 1
end
+--- @param grid integer
+--- @param row integer
+--- @param col integer
+--- @param items integer[][]
function Screen:_handle_grid_line(grid, row, col, items)
assert(self._options.ext_linegrid)
assert(#items > 0)
- local line = self._grids[grid].rows[row+1]
- local colpos = col+1
+ local line = self._grids[grid].rows[row + 1]
+ local colpos = col + 1
local hl_id = 0
- for _,item in ipairs(items) do
- local text, hl_id_cell, count = unpack(item)
+ for _, item in ipairs(items) do
+ local text, hl_id_cell, count = item[1], item[2], item[3]
if hl_id_cell ~= nil then
hl_id = hl_id_cell
end
@@ -966,7 +1159,7 @@ function Screen:_handle_grid_line(grid, row, col, items)
local cell = line[colpos]
cell.text = text
cell.hl_id = hl_id
- colpos = colpos+1
+ colpos = colpos + 1
end
end
end
@@ -981,11 +1174,11 @@ end
function Screen:_handle_default_colors_set(rgb_fg, rgb_bg, rgb_sp, cterm_fg, cterm_bg)
self.default_colors = {
- rgb_fg=rgb_fg,
- rgb_bg=rgb_bg,
- rgb_sp=rgb_sp,
- cterm_fg=cterm_fg,
- cterm_bg=cterm_bg
+ rgb_fg = rgb_fg,
+ rgb_bg = rgb_bg,
+ rgb_sp = rgb_sp,
+ cterm_fg = cterm_fg,
+ cterm_bg = cterm_bg,
}
end
@@ -1021,8 +1214,12 @@ function Screen:_handle_option_set(name, value)
self.options[name] = value
end
+function Screen:_handle_chdir(path)
+ self.pwd = vim.fs.normalize(path, { expand_env = false })
+end
+
function Screen:_handle_popupmenu_show(items, selected, row, col, grid)
- self.popupmenu = {items=items, pos=selected, anchor={grid, row, col}}
+ self.popupmenu = { items = items, pos = selected, anchor = { grid, row, col } }
end
function Screen:_handle_popupmenu_select(selected)
@@ -1034,9 +1231,15 @@ function Screen:_handle_popupmenu_hide()
end
function Screen:_handle_cmdline_show(content, pos, firstc, prompt, indent, level)
- if firstc == '' then firstc = nil end
- if prompt == '' then prompt = nil end
- if indent == 0 then indent = nil end
+ if firstc == '' then
+ firstc = nil
+ end
+ if prompt == '' then
+ prompt = nil
+ end
+ if indent == 0 then
+ indent = nil
+ end
-- check position is valid #10000
local len = 0
@@ -1045,8 +1248,13 @@ function Screen:_handle_cmdline_show(content, pos, firstc, prompt, indent, level
end
assert(pos <= len)
- self.cmdline[level] = {content=content, pos=pos, firstc=firstc,
- prompt=prompt, indent=indent}
+ self.cmdline[level] = {
+ content = content,
+ pos = pos,
+ firstc = firstc,
+ prompt = prompt,
+ indent = indent,
+ }
end
function Screen:_handle_cmdline_hide(level)
@@ -1055,7 +1263,7 @@ end
function Screen:_handle_cmdline_special_char(char, shift, level)
-- cleared by next cmdline_show on the same level
- self.cmdline[level].special = {char, shift}
+ self.cmdline[level].special = { char, shift }
end
function Screen:_handle_cmdline_pos(pos, level)
@@ -1067,7 +1275,7 @@ function Screen:_handle_cmdline_block_show(block)
end
function Screen:_handle_cmdline_block_append(item)
- self.cmdline_block[#self.cmdline_block+1] = item
+ self.cmdline_block[#self.cmdline_block + 1] = item
end
function Screen:_handle_cmdline_block_hide()
@@ -1091,7 +1299,7 @@ function Screen:_handle_msg_show(kind, chunks, replace_last)
if not replace_last or pos == 0 then
pos = pos + 1
end
- self.messages[pos] = {kind=kind, content=chunks}
+ self.messages[pos] = { kind = kind, content = chunks }
end
function Screen:_handle_msg_clear()
@@ -1140,19 +1348,23 @@ function Screen:_row_repr(gridnr, rownr, attr_state, cursor)
local has_windows = self._options.ext_multigrid and gridnr == 1
local row = self._grids[gridnr].rows[rownr]
if has_windows and self.msg_grid and self.msg_grid_pos < rownr then
- return '['..self.msg_grid..':'..string.rep('-',#row)..']'
+ return '[' .. self.msg_grid .. ':' .. string.rep('-', #row) .. ']'
end
while i <= #row do
local did_window = false
if has_windows then
- for id,pos in pairs(self.win_position) do
- if i-1 == pos.startcol and pos.startrow <= rownr-1 and rownr-1 < pos.startrow + pos.height then
+ for id, pos in pairs(self.win_position) do
+ if
+ i - 1 == pos.startcol
+ and pos.startrow <= rownr - 1
+ and rownr - 1 < pos.startrow + pos.height
+ then
if current_attr_id then
-- close current attribute bracket
table.insert(rv, '}')
current_attr_id = nil
end
- table.insert(rv, '['..id..':'..string.rep('-',pos.width)..']')
+ table.insert(rv, '[' .. id .. ':' .. string.rep('-', pos.width) .. ']')
i = i + pos.width
did_window = true
end
@@ -1183,7 +1395,7 @@ function Screen:_row_repr(gridnr, rownr, attr_state, cursor)
end
-- return the line representation, but remove empty attribute brackets and
-- trailing whitespace
- return table.concat(rv, '')--:gsub('%s+$', '')
+ return table.concat(rv, '') --:gsub('%s+$', '')
end
function Screen:_extstate_repr(attr_state)
@@ -1201,29 +1413,29 @@ function Screen:_extstate_repr(attr_state)
local messages = {}
for i, entry in ipairs(self.messages) do
- messages[i] = {kind=entry.kind, content=self:_chunks_repr(entry.content, attr_state)}
+ messages[i] = { kind = entry.kind, content = self:_chunks_repr(entry.content, attr_state) }
end
local msg_history = {}
for i, entry in ipairs(self.msg_history) do
- msg_history[i] = {kind=entry[1], content=self:_chunks_repr(entry[2], attr_state)}
+ msg_history[i] = { kind = entry[1], content = self:_chunks_repr(entry[2], attr_state) }
end
local win_viewport = (next(self.win_viewport) and self.win_viewport) or nil
return {
- popupmenu=self.popupmenu,
- cmdline=cmdline,
- cmdline_block=cmdline_block,
- wildmenu_items=self.wildmenu_items,
- wildmenu_pos=self.wildmenu_pos,
- messages=messages,
- showmode=self:_chunks_repr(self.showmode, attr_state),
- showcmd=self:_chunks_repr(self.showcmd, attr_state),
- ruler=self:_chunks_repr(self.ruler, attr_state),
- msg_history=msg_history,
- float_pos=self.float_pos,
- win_viewport=win_viewport,
+ popupmenu = self.popupmenu,
+ cmdline = cmdline,
+ cmdline_block = cmdline_block,
+ wildmenu_items = self.wildmenu_items,
+ wildmenu_pos = self.wildmenu_pos,
+ messages = messages,
+ showmode = self:_chunks_repr(self.showmode, attr_state),
+ showcmd = self:_chunks_repr(self.showcmd, attr_state),
+ ruler = self:_chunks_repr(self.ruler, attr_state),
+ msg_history = msg_history,
+ float_pos = self.float_pos,
+ win_viewport = win_viewport,
}
end
@@ -1238,14 +1450,14 @@ function Screen:_chunks_repr(chunks, attr_state)
attrs = hl
end
local attr_id = self:_get_attr_id(attr_state, attrs, hl)
- repr_chunks[i] = {text, attr_id}
+ repr_chunks[i] = { text, attr_id }
end
return repr_chunks
end
-- Generates tests. Call it where Screen:expect() would be. Waits briefly, then
-- dumps the current screen state in the form of Screen:expect().
--- Use snapshot_util({},true) to generate a text-only (no attributes) test.
+-- Use snapshot_util({}) to generate a text-only (no attributes) test.
--
-- @see Screen:redraw_debug()
function Screen:snapshot_util(attrs, ignore, request_cb)
@@ -1259,7 +1471,7 @@ function Screen:redraw_debug(attrs, ignore, timeout)
assert(method == 'redraw')
for _, update in ipairs(args) do
-- mode_info_set is quite verbose, comment out the condition to debug it.
- if update[1] ~= "mode_info_set" then
+ if update[1] ~= 'mode_info_set' then
print(inspect(update))
end
end
@@ -1273,17 +1485,25 @@ function Screen:redraw_debug(attrs, ignore, timeout)
run_session(self._session, nil, notification_cb, nil, timeout)
end
+--- @param headers boolean
+--- @param attr_state any
+--- @param preview? boolean
+--- @return string[]
function Screen:render(headers, attr_state, preview)
headers = headers and (self._options.ext_multigrid or self._options._debug_float)
local rv = {}
- for igrid,grid in vim.spairs(self._grids) do
+ for igrid, grid in vim.spairs(self._grids) do
if headers then
- local suffix = ""
- if igrid > 1 and self.win_position[igrid] == nil
- and self.float_pos[igrid] == nil and self.msg_grid ~= igrid then
- suffix = " (hidden)"
+ local suffix = ''
+ if
+ igrid > 1
+ and self.win_position[igrid] == nil
+ and self.float_pos[igrid] == nil
+ and self.msg_grid ~= igrid
+ then
+ suffix = ' (hidden)'
end
- table.insert(rv, "## grid "..igrid..suffix)
+ table.insert(rv, '## grid ' .. igrid .. suffix)
end
local height = grid.height
if igrid == self.msg_grid then
@@ -1291,8 +1511,8 @@ function Screen:render(headers, attr_state, preview)
end
for i = 1, height do
local cursor = self._cursor.grid == igrid and self._cursor.row == i
- local prefix = (headers or preview) and " " or ""
- table.insert(rv, prefix..self:_row_repr(igrid, i, attr_state, cursor).."|")
+ local prefix = (headers or preview) and ' ' or ''
+ table.insert(rv, prefix .. self:_row_repr(igrid, i, attr_state, cursor) .. '|')
end
end
return rv
@@ -1301,15 +1521,22 @@ end
-- Returns the current screen state in the form of a screen:expect()
-- keyword-args map.
function Screen:get_snapshot(attrs, ignore)
- attrs = attrs or self._default_attr_ids
if ignore == nil then
ignore = self._default_attr_ignore
end
local attr_state = {
- ids = {},
- ignore = ignore,
- mutable = true, -- allow _row_repr to add missing highlights
+ ids = {},
+ ignore = ignore,
+ mutable = true, -- allow _row_repr to add missing highlights
}
+ if attrs == nil then
+ attrs = self._default_attr_ids
+ elseif isempty(attrs) then
+ attrs = nil
+ attr_state.ids = nil
+ else
+ attr_state.modified = true
+ end
if attrs ~= nil then
for i, a in pairs(attrs) do
@@ -1317,11 +1544,22 @@ function Screen:get_snapshot(attrs, ignore)
end
end
if self._options.ext_linegrid then
- attr_state.id_to_index = self:linegrid_check_attrs(attr_state.ids)
+ attr_state.id_to_index = self:linegrid_check_attrs(attr_state.ids or {})
end
local lines = self:render(true, attr_state, true)
+ for i, row in ipairs(lines) do
+ local count = 1
+ while i < #lines and lines[i + 1] == row do
+ count = count + 1
+ table.remove(lines, i + 1)
+ end
+ if count > 1 then
+ lines[i] = lines[i] .. '*' .. count
+ end
+ end
+
local ext_state = self:_extstate_repr(attr_state)
for k, v in pairs(ext_state) do
if isempty(v) then
@@ -1353,33 +1591,50 @@ local function fmt_ext_state(name, state)
return item
end
end
- if name == "win_viewport" then
- local str = "{\n"
- for k,v in pairs(state) do
- str = (str.." ["..k.."] = {win = {id = "..v.win.id.."}, topline = "
- ..v.topline..", botline = "..v.botline..", curline = "..v.curline
- ..", curcol = "..v.curcol..", linecount = "..v.linecount..", sum_scroll_delta = "..v.sum_scroll_delta.."};\n")
+ if name == 'win_viewport' then
+ local str = '{\n'
+ for k, v in pairs(state) do
+ str = (
+ str
+ .. ' ['
+ .. k
+ .. '] = {win = '
+ .. v.win
+ .. ', topline = '
+ .. v.topline
+ .. ', botline = '
+ .. v.botline
+ .. ', curline = '
+ .. v.curline
+ .. ', curcol = '
+ .. v.curcol
+ .. ', linecount = '
+ .. v.linecount
+ .. ', sum_scroll_delta = '
+ .. v.sum_scroll_delta
+ .. '};\n'
+ )
end
- return str .. "}"
- elseif name == "float_pos" then
- local str = "{\n"
- for k,v in pairs(state) do
- str = str.." ["..k.."] = {{id = "..v[1].id.."}"
+ return str .. '}'
+ elseif name == 'float_pos' then
+ local str = '{\n'
+ for k, v in pairs(state) do
+ str = str .. ' [' .. k .. '] = {' .. v[1]
for i = 2, #v do
- str = str..", "..inspect(v[i])
+ str = str .. ', ' .. inspect(v[i])
end
- str = str .. "};\n"
+ str = str .. '};\n'
end
- return str .. "}"
+ return str .. '}'
else
-- TODO(bfredl): improve formatting of more states
- return inspect(state,{process=remove_all_metatables})
+ return inspect(state, { process = remove_all_metatables })
end
end
-function Screen:print_snapshot(attrs, ignore)
+function Screen:_print_snapshot(attrs, ignore)
local kwargs, ext_state, attr_state = self:get_snapshot(attrs, ignore)
- local attrstr = ""
+ local attrstr = ''
if attr_state.modified then
local attrstrs = {}
for i, a in pairs(attr_state.ids) do
@@ -1387,23 +1642,29 @@ function Screen:print_snapshot(attrs, ignore)
if self._options.ext_linegrid then
dict = self:_pprint_hlitem(a)
else
- dict = "{"..self:_pprint_attrs(a).."}"
+ dict = '{' .. self:_pprint_attrs(a) .. '}'
end
- local keyval = (type(i) == "number") and "["..tostring(i).."]" or i
- table.insert(attrstrs, " "..keyval.." = "..dict..";")
+ local keyval = (type(i) == 'number') and '[' .. tostring(i) .. ']' or i
+ table.insert(attrstrs, ' ' .. keyval .. ' = ' .. dict .. ';')
end
- attrstr = (", attr_ids={\n"..table.concat(attrstrs, "\n").."\n}")
+ attrstr = (', attr_ids={\n' .. table.concat(attrstrs, '\n') .. '\n}')
+ elseif isempty(attrs) then
+ attrstr = ', attr_ids={}'
end
- print( "\nscreen:expect{grid=[[")
- print(kwargs.grid)
- io.stdout:write( "]]"..attrstr)
+ local result = 'screen:expect{grid=[[\n' .. kwargs.grid .. '\n]]' .. attrstr
for _, k in ipairs(ext_keys) do
- if ext_state[k] ~= nil and not (k == "win_viewport" and not self.options.ext_multigrid) then
- io.stdout:write(", "..k.."="..fmt_ext_state(k, ext_state[k]))
+ if ext_state[k] ~= nil and not (k == 'win_viewport' and not self.options.ext_multigrid) then
+ result = result .. ', ' .. k .. '=' .. fmt_ext_state(k, ext_state[k])
end
end
- print("}\n")
+ result = result .. '}'
+
+ return result
+end
+
+function Screen:print_snapshot(attrs, ignore)
+ print('\n' .. self:_print_snapshot(attrs, ignore) .. '\n')
io.stdout:flush()
end
@@ -1422,7 +1683,7 @@ function Screen:_insert_hl_id(attr_state, hl_id)
else
info[1] = {}
for k, v in pairs(raw_info[1]) do
- if k ~= "id" then
+ if k ~= 'id' then
info[1][k] = v
end
end
@@ -1432,9 +1693,9 @@ function Screen:_insert_hl_id(attr_state, hl_id)
local entry = self._attr_table[hl_id]
local attrval
if self._rgb_cterm then
- attrval = {entry[1], entry[2], info} -- unpack() doesn't work
+ attrval = { entry[1], entry[2], info } -- unpack() doesn't work
elseif self._options.ext_hlstate then
- attrval = {entry[1], info}
+ attrval = { entry[1], info }
else
attrval = self._options.rgb and entry[1] or entry[2]
end
@@ -1450,17 +1711,17 @@ function Screen:linegrid_check_attrs(attrs)
local iinfo = self._hl_info[i]
local matchinfo = {}
if #iinfo > 1 then
- for k,item in ipairs(iinfo) do
+ for k, item in ipairs(iinfo) do
matchinfo[k] = id_to_index[item.id]
end
else
matchinfo = iinfo
end
- for k,v in pairs(attrs) do
+ for k, v in pairs(attrs) do
local attr, info, attr_rgb, attr_cterm
if self._rgb_cterm then
attr_rgb, attr_cterm, info = unpack(v)
- attr = {attr_rgb, attr_cterm}
+ attr = { attr_rgb, attr_cterm }
info = info or {}
elseif self._options.ext_hlstate then
attr, info = unpack(v)
@@ -1472,12 +1733,12 @@ function Screen:linegrid_check_attrs(attrs)
if #info == #matchinfo then
local match = false
if #info == 1 then
- if self:_equal_info(info[1],matchinfo[1]) then
+ if self:_equal_info(info[1], matchinfo[1]) then
match = true
end
else
match = true
- for j = 1,#info do
+ for j = 1, #info do
if info[j] ~= matchinfo[j] then
match = false
end
@@ -1489,32 +1750,34 @@ function Screen:linegrid_check_attrs(attrs)
end
end
end
- if self:_equal_attr_def(self._rgb_cterm and {{}, {}} or {}, def_attr) and #self._hl_info[i] == 0 then
- id_to_index[i] = ""
+ if
+ self:_equal_attr_def(self._rgb_cterm and { {}, {} } or {}, def_attr)
+ and #self._hl_info[i] == 0
+ then
+ id_to_index[i] = ''
end
end
return id_to_index
end
-
function Screen:_pprint_hlitem(item)
- -- print(inspect(item))
- local multi = self._rgb_cterm or self._options.ext_hlstate
- local cterm = (not self._rgb_cterm and not self._options.rgb)
- local attrdict = "{"..self:_pprint_attrs(multi and item[1] or item, cterm).."}"
- local attrdict2, hlinfo
- local descdict = ""
- if self._rgb_cterm then
- attrdict2 = ", {"..self:_pprint_attrs(item[2], true).."}"
- hlinfo = item[3]
- else
- attrdict2 = ""
- hlinfo = item[2]
- end
- if self._options.ext_hlstate then
- descdict = ", {"..self:_pprint_hlinfo(hlinfo).."}"
- end
- return (multi and "{" or "")..attrdict..attrdict2..descdict..(multi and "}" or "")
+ -- print(inspect(item))
+ local multi = self._rgb_cterm or self._options.ext_hlstate
+ local cterm = (not self._rgb_cterm and not self._options.rgb)
+ local attrdict = '{' .. self:_pprint_attrs(multi and item[1] or item, cterm) .. '}'
+ local attrdict2, hlinfo
+ local descdict = ''
+ if self._rgb_cterm then
+ attrdict2 = ', {' .. self:_pprint_attrs(item[2], true) .. '}'
+ hlinfo = item[3]
+ else
+ attrdict2 = ''
+ hlinfo = item[2]
+ end
+ if self._options.ext_hlstate then
+ descdict = ', {' .. self:_pprint_hlinfo(hlinfo) .. '}'
+ end
+ return (multi and '{' or '') .. attrdict .. attrdict2 .. descdict .. (multi and '}' or '')
end
function Screen:_pprint_hlinfo(states)
@@ -1522,37 +1785,37 @@ function Screen:_pprint_hlinfo(states)
local items = {}
for f, v in pairs(states[1]) do
local desc = tostring(v)
- if type(v) == type("") then
- desc = '"'..desc..'"'
+ if type(v) == type('') then
+ desc = '"' .. desc .. '"'
end
- table.insert(items, f.." = "..desc)
+ table.insert(items, f .. ' = ' .. desc)
end
- return "{"..table.concat(items, ", ").."}"
+ return '{' .. table.concat(items, ', ') .. '}'
else
- return table.concat(states, ", ")
+ return table.concat(states, ', ')
end
end
-
function Screen:_pprint_attrs(attrs, cterm)
- local items = {}
- for f, v in pairs(attrs) do
- local desc = tostring(v)
- if f == "foreground" or f == "background" or f == "special" then
- if Screen.colornames[v] ~= nil then
- desc = "Screen.colors."..Screen.colornames[v]
- elseif cterm then
- desc = tostring(v)
- else
- desc = string.format("tonumber('0x%06x')",v)
- end
+ local items = {}
+ for f, v in pairs(attrs) do
+ local desc = tostring(v)
+ if f == 'foreground' or f == 'background' or f == 'special' then
+ if Screen.colornames[v] ~= nil then
+ desc = 'Screen.colors.' .. Screen.colornames[v]
+ elseif cterm then
+ desc = tostring(v)
+ else
+ desc = string.format("tonumber('0x%06x')", v)
end
- table.insert(items, f.." = "..desc)
end
- return table.concat(items, ", ")
+ table.insert(items, f .. ' = ' .. desc)
+ end
+ return table.concat(items, ', ')
end
-local function backward_find_meaningful(tbl, from) -- luacheck: no unused
+---@diagnostic disable-next-line: unused-local, unused-function
+local function backward_find_meaningful(tbl, from) -- luacheck: no unused
for i = from or #tbl, 1, -1 do
if tbl[i] ~= ' ' then
return i + 1
@@ -1568,7 +1831,7 @@ function Screen:_get_attr_id(attr_state, attrs, hl_id)
if self._options.ext_linegrid then
local id = attr_state.id_to_index[hl_id]
- if id == "" then -- sentinel for empty it
+ if id == '' then -- sentinel for empty it
return nil
elseif id ~= nil then
return id
@@ -1579,7 +1842,7 @@ function Screen:_get_attr_id(attr_state, attrs, hl_id)
return id
end
local kind = self._options.rgb and 1 or 2
- return "UNEXPECTED "..self:_pprint_attrs(self._attr_table[hl_id][kind])
+ return 'UNEXPECTED ' .. self:_pprint_attrs(self._attr_table[hl_id][kind])
else
if self:_equal_attrs(attrs, {}) then
-- ignore this attrs
@@ -1587,49 +1850,57 @@ function Screen:_get_attr_id(attr_state, attrs, hl_id)
end
for id, a in pairs(attr_state.ids) do
if self:_equal_attrs(a, attrs) then
- return id
- end
+ return id
+ end
end
if attr_state.mutable then
table.insert(attr_state.ids, attrs)
attr_state.modified = true
return #attr_state.ids
end
- return "UNEXPECTED "..self:_pprint_attrs(attrs)
+ return 'UNEXPECTED ' .. self:_pprint_attrs(attrs)
end
end
function Screen:_equal_attr_def(a, b)
if self._rgb_cterm then
- return self:_equal_attrs(a[1],b[1]) and self:_equal_attrs(a[2],b[2])
+ return self:_equal_attrs(a[1], b[1]) and self:_equal_attrs(a[2], b[2])
elseif self._options.rgb then
- return self:_equal_attrs(a,b[1])
+ return self:_equal_attrs(a, b[1])
else
- return self:_equal_attrs(a,b[2])
+ return self:_equal_attrs(a, b[2])
end
end
function Screen:_equal_attrs(a, b)
- return a.bold == b.bold and a.standout == b.standout and
- a.underline == b.underline and a.undercurl == b.undercurl and
- a.underdouble == b.underdouble and a.underdotted == b.underdotted and
- a.underdashed == b.underdashed and a.italic == b.italic and
- a.reverse == b.reverse and a.foreground == b.foreground and
- a.background == b.background and a.special == b.special and a.blend == b.blend and
- a.strikethrough == b.strikethrough and
- a.fg_indexed == b.fg_indexed and a.bg_indexed == b.bg_indexed
+ return a.bold == b.bold
+ and a.standout == b.standout
+ and a.underline == b.underline
+ and a.undercurl == b.undercurl
+ and a.underdouble == b.underdouble
+ and a.underdotted == b.underdotted
+ and a.underdashed == b.underdashed
+ and a.italic == b.italic
+ and a.reverse == b.reverse
+ and a.foreground == b.foreground
+ and a.background == b.background
+ and a.special == b.special
+ and a.blend == b.blend
+ and a.strikethrough == b.strikethrough
+ and a.fg_indexed == b.fg_indexed
+ and a.bg_indexed == b.bg_indexed
+ and a.url == b.url
end
function Screen:_equal_info(a, b)
- return a.kind == b.kind and a.hi_name == b.hi_name and
- a.ui_name == b.ui_name
+ return a.kind == b.kind and a.hi_name == b.hi_name and a.ui_name == b.ui_name
end
function Screen:_attr_index(attrs, attr)
if not attrs then
return nil
end
- for i,a in pairs(attrs) do
+ for i, a in pairs(attrs) do
if self:_equal_attrs(a, attr) then
return i
end
diff --git a/test/functional/ui/screen_basic_spec.lua b/test/functional/ui/screen_basic_spec.lua
index 7cc1accd3f..42e2b4d4b5 100644
--- a/test/functional/ui/screen_basic_spec.lua
+++ b/test/functional/ui/screen_basic_spec.lua
@@ -4,39 +4,39 @@ local spawn, set_session, clear = helpers.spawn, helpers.set_session, helpers.cl
local feed, command = helpers.feed, helpers.command
local insert = helpers.insert
local eq = helpers.eq
-local funcs, meths = helpers.funcs, helpers.meths
+local fn, api = helpers.fn, helpers.api
describe('screen', function()
local screen
- local nvim_argv = {helpers.nvim_prog, '-u', 'NONE', '-i', 'NONE', '-N',
- '--cmd', 'set shortmess+=I background=light noswapfile belloff= noshowcmd noruler',
- '--embed'}
+ local nvim_argv = {
+ helpers.nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '-n',
+ '--cmd',
+ 'set shortmess+=I background=light noswapfile belloff= noshowcmd noruler',
+ '--cmd',
+ 'colorscheme vim',
+ '--embed',
+ }
before_each(function()
local screen_nvim = spawn(nvim_argv)
set_session(screen_nvim)
screen = Screen.new()
screen:attach()
- screen:set_default_attr_ids( {
- [0] = {bold=true, foreground=255},
- [1] = {bold=true, reverse=true},
- } )
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = 255 },
+ [1] = { bold = true, reverse = true },
+ })
end)
it('default initial screen', function()
- screen:expect([[
+ screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*11
{1:[No Name] }|
|
]])
@@ -49,18 +49,23 @@ local function screen_tests(linegrid)
before_each(function()
clear()
screen = Screen.new()
- screen:attach({rgb=true,ext_linegrid=linegrid})
- screen:set_default_attr_ids( {
- [0] = {bold=true, foreground=255},
- [1] = {bold=true, reverse=true},
- [2] = {bold=true},
- [3] = {reverse=true},
- [4] = {background = Screen.colors.LightGrey, underline = true},
- [5] = {background = Screen.colors.LightGrey, underline = true, bold = true, foreground = Screen.colors.Fuchsia},
- [6] = {bold = true, foreground = Screen.colors.Fuchsia},
- [7] = {bold = true, foreground = Screen.colors.SeaGreen},
- [8] = {foreground = Screen.colors.White, background = Screen.colors.Red},
- } )
+ screen:attach({ rgb = true, ext_linegrid = linegrid })
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = 255 },
+ [1] = { bold = true, reverse = true },
+ [2] = { bold = true },
+ [3] = { reverse = true },
+ [4] = { background = Screen.colors.LightGrey, underline = true },
+ [5] = {
+ background = Screen.colors.LightGrey,
+ underline = true,
+ bold = true,
+ foreground = Screen.colors.Fuchsia,
+ },
+ [6] = { bold = true, foreground = Screen.colors.Fuchsia },
+ [7] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [8] = { foreground = Screen.colors.White, background = Screen.colors.Red },
+ })
end)
describe('bell/visual bell', function()
@@ -83,7 +88,7 @@ local function screen_tests(linegrid)
describe(':set title', function()
it('is forwarded to the UI', function()
local expected = 'test-title'
- command('set titlestring='..expected)
+ command('set titlestring=' .. expected)
command('set title')
screen:expect(function()
eq(expected, screen.title)
@@ -100,7 +105,7 @@ local function screen_tests(linegrid)
describe(':set icon', function()
it('is forwarded to the UI', function()
local expected = 'test-icon'
- command('set iconstring='..expected)
+ command('set iconstring=' .. expected)
command('set icon')
screen:expect(function()
eq(expected, screen.icon)
@@ -119,74 +124,46 @@ local function screen_tests(linegrid)
command('set laststatus=2')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*11
{1:[No Name] }|
|
]])
feed('<c-l>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*11
{1:[No Name] }|
|
- ]], reset=true}
+ ]],
+ reset = true,
+ }
command('split')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{1:[No Name] }|
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:[No Name] }|
|
]])
feed('<c-l>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{1:[No Name] }|
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:[No Name] }|
|
- ]], reset=true}
+ ]],
+ reset = true,
+ }
end)
end)
@@ -196,17 +173,10 @@ local function screen_tests(linegrid)
command('sp')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{1:[No Name] }|
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:[No Name] }|
|
]])
@@ -217,17 +187,10 @@ local function screen_tests(linegrid)
command('resize 8')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
{1:[No Name] }|
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{3:[No Name] }|
|
]])
@@ -239,34 +202,20 @@ local function screen_tests(linegrid)
command('vsp')
screen:expect([[
^ │ │ |
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
+ {0:~ }│{0:~ }│{0:~ }|*5
{1:[No Name] }{3:[No Name] [No Name] }|
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:[No Name] }|
|
]])
insert('hello')
screen:expect([[
hell^o │hello │hello |
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
+ {0:~ }│{0:~ }│{0:~ }|*5
{1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }|
hello |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:[No Name] [+] }|
|
]])
@@ -282,17 +231,10 @@ local function screen_tests(linegrid)
insert('hello')
screen:expect([[
hell^o │hello │hello |
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
+ {0:~ }│{0:~ }│{0:~ }|*5
{1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }|
hello |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{3:[No Name] [+] }|
|
]])
@@ -302,33 +244,17 @@ local function screen_tests(linegrid)
screen:expect([[
{4: }{5:4}{4:+ [No Name] }{2: + [No Name] }{3: }{4:X}|
hell^o2 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*11
|
]])
command('tabprevious')
screen:expect([[
{2: }{6:4}{2:+ [No Name] }{4: + [No Name] }{3: }{4:X}|
hell^o │hello │hello |
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
- {0:~ }│{0:~ }│{0:~ }|
+ {0:~ }│{0:~ }│{0:~ }|*5
{1:[No Name] [+] }{3:[No Name] [+] [No Name] [+] }|
hello |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{3:[No Name] [+] }|
|
]])
@@ -339,34 +265,14 @@ local function screen_tests(linegrid)
screen:expect([[
{4: [No Name] }{2: [No Name] }{3: }{4:X}|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*11
|
]])
- feed(':echo "'..string.rep('x\\n', 11)..'"<cr>')
+ feed(':echo "' .. string.rep('x\\n', 11) .. '"<cr>')
screen:expect([[
{1: }|
- x |
- x |
- x |
- x |
- x |
- x |
- x |
- x |
- x |
- x |
- x |
+ x |*11
|
{7:Press ENTER or type command to continue}^ |
]])
@@ -375,34 +281,13 @@ local function screen_tests(linegrid)
screen:expect([[
{4: [No Name] }{2: [No Name] }{3: }{4:X}|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*11
|
]])
- feed(':echo "'..string.rep('x\\n', 12)..'"<cr>')
+ feed(':echo "' .. string.rep('x\\n', 12) .. '"<cr>')
screen:expect([[
- x |
- x |
- x |
- x |
- x |
- x |
- x |
- x |
- x |
- x |
- x |
- x |
+ x |*12
|
{7:Press ENTER or type command to continue}^ |
]])
@@ -411,20 +296,9 @@ local function screen_tests(linegrid)
screen:expect([[
{4: [No Name] }{2: [No Name] }{3: }{4:X}|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*11
|
]])
-
end)
it('redraws properly with :tab split right after scroll', function()
@@ -433,17 +307,7 @@ local function screen_tests(linegrid)
command('vsplit')
screen:expect([[
^foo │foo |
- foo │foo |
- foo │foo |
- foo │foo |
- foo │foo |
- foo │foo |
- foo │foo |
- foo │foo |
- foo │foo |
- foo │foo |
- foo │foo |
- foo │foo |
+ foo │foo |*11
{1:[No Name] [+] }{3:[No Name] [+] }|
|
]])
@@ -451,17 +315,8 @@ local function screen_tests(linegrid)
feed('<PageDown>')
screen:expect([[
^foo │foo |
- foo │foo |
- foo │foo |
- foo │foo |
- bar │foo |
- bar │foo |
- bar │foo |
- bar │foo |
- bar │foo |
- bar │foo |
- bar │foo |
- bar │foo |
+ foo │foo |*3
+ bar │foo |*8
{1:[No Name] [+] }{3:[No Name] [+] }|
|
]])
@@ -469,17 +324,8 @@ local function screen_tests(linegrid)
screen:expect([[
{4: }{5:2}{4:+ [No Name] }{2: + [No Name] }{3: }{4:X}|
^foo |
- foo |
- foo |
- foo |
- bar |
- bar |
- bar |
- bar |
- bar |
- bar |
- bar |
- bar |
+ foo |*3
+ bar |*8
|
]])
end)
@@ -491,17 +337,7 @@ local function screen_tests(linegrid)
screen:expect([[
{2: + [No Name] }{4: [No Name] }{3: }{4:X}|
hell^o |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*11
|
]])
@@ -509,17 +345,7 @@ local function screen_tests(linegrid)
screen:expect([[
{4: + [No Name] }{2: [No Name] }{3: }{4:X}|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*11
|
]])
end)
@@ -532,16 +358,7 @@ local function screen_tests(linegrid)
line 1 |
line 2 |
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*10
{2:-- INSERT --} |
]])
end)
@@ -557,17 +374,7 @@ local function screen_tests(linegrid)
screen:expect([[
0123^456 |
789 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*11
1,5 All |
]])
end)
@@ -578,18 +385,7 @@ local function screen_tests(linegrid)
feed(':ls')
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*12
:ls^ |
]])
end)
@@ -598,15 +394,7 @@ local function screen_tests(linegrid)
feed(':ls<cr>')
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
{1: }|
:ls |
1 %a "[No Name]" line 1 |
@@ -783,9 +571,7 @@ local function screen_tests(linegrid)
feed('iresize')
screen:expect([[
resize^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{2:-- INSERT --} |
]])
end)
@@ -811,38 +597,27 @@ 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_value('showtabline', 2, {})
+ api.nvim_set_option_value('showtabline', 2, {})
screen:expect([[
{2: + [No Name] }{3: }|
resiz^e |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
screen:try_resize(30, 6)
screen:expect([[
{2: + [No Name] }{3: }|
resiz^e |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
- eq(29, meths.get_var('echospace'))
+ eq(29, api.nvim_get_var('echospace'))
end)
it('messages from the same Ex command as resize are visible #22225', function()
feed(':set columns=20 | call<CR>')
screen:expect([[
- |
- |
- |
- |
- |
- |
- |
- |
- |
+ |*9
{1: }|
{8:E471: Argument requi}|
{8:red} |
@@ -852,53 +627,25 @@ local function screen_tests(linegrid)
feed('<CR>')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*12
|
]])
feed(':set columns=0<CR>')
screen:expect([[
- |
- |
- |
- |
- |
- {1: }|
- {8:E594: Need a}|
- {8:t least 12 c}|
- {8:olumns: colu}|
- {8:mns=0} |
- {7:Press ENTER }|
- {7:or type comm}|
- {7:and to conti}|
- {7:nue}^ |
+ |
+ {0:~ }|*7
+ {1: }|
+ {8:E594: Need at least }|
+ {8:12 columns: columns=}|
+ {8:0} |
+ {7:Press ENTER or type }|
+ {7:command to continue}^ |
]])
feed('<CR>')
screen:expect([[
- ^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
+ ^ |
+ {0:~ }|*12
+ |
]])
end)
end)
@@ -909,15 +656,7 @@ local function screen_tests(linegrid)
feed(':ls<CR>')
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
{1: }|
:ls |
1 %a "[No Name]" line 1 |
@@ -926,18 +665,7 @@ local function screen_tests(linegrid)
feed('<F1>')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*12
TEST |
]])
end)
@@ -950,45 +678,23 @@ local function screen_tests(linegrid)
feed('ifooj')
screen:expect([[
foo^j |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*12
{2:-- INSERT --} |
]])
feed('k')
screen:expect([[
fo^o |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*12
|
]])
end)
end
-describe("Screen (char-based)", function()
+describe('Screen (char-based)', function()
screen_tests(false)
end)
-describe("Screen (line-based)", function()
+describe('Screen (line-based)', function()
screen_tests(true)
end)
@@ -997,41 +703,75 @@ describe('Screen default colors', function()
local function startup(light, termcolors)
local extra = (light and ' background=light') or ''
- local nvim_argv = {helpers.nvim_prog, '-u', 'NONE', '-i', 'NONE', '-N',
- '--cmd', 'set shortmess+=I noswapfile belloff= noshowcmd noruler'..extra,
- '--embed'}
+ local nvim_argv = {
+ helpers.nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '-N',
+ '--cmd',
+ 'set shortmess+=I noswapfile belloff= noshowcmd noruler' .. extra,
+ '--cmd',
+ 'colorscheme vim',
+ '--embed',
+ }
local screen_nvim = spawn(nvim_argv)
set_session(screen_nvim)
screen = Screen.new()
- screen:attach(termcolors and {rgb=true,ext_termcolors=true} or {rgb=true})
+ screen:attach(termcolors and { rgb = true, ext_termcolors = true } or { rgb = true })
end
it('are dark per default', function()
startup(false, false)
- screen:expect{condition=function()
- eq({rgb_bg=0, rgb_fg=Screen.colors.White, rgb_sp=Screen.colors.Red,
- cterm_bg=0, cterm_fg=0}, screen.default_colors)
- end}
+ screen:expect {
+ condition = function()
+ eq({
+ rgb_bg = 0,
+ rgb_fg = Screen.colors.White,
+ rgb_sp = Screen.colors.Red,
+ cterm_bg = 0,
+ cterm_fg = 0,
+ }, screen.default_colors)
+ end,
+ }
end)
it('can be set to light', function()
startup(true, false)
- screen:expect{condition=function()
- eq({rgb_fg=Screen.colors.White, rgb_bg=0, rgb_sp=Screen.colors.Red,
- cterm_bg=0, cterm_fg=0}, screen.default_colors)
- end}
+ screen:expect {
+ condition = function()
+ eq({
+ rgb_bg = Screen.colors.White,
+ rgb_fg = 0,
+ rgb_sp = Screen.colors.Red,
+ cterm_bg = 0,
+ cterm_fg = 0,
+ }, screen.default_colors)
+ end,
+ }
end)
it('can be handled by external terminal', function()
startup(false, true)
- screen:expect{condition=function()
- eq({rgb_bg=-1, rgb_fg=-1, rgb_sp=-1, cterm_bg=0, cterm_fg=0}, screen.default_colors)
- end}
+ screen:expect {
+ condition = function()
+ eq(
+ { rgb_bg = -1, rgb_fg = -1, rgb_sp = -1, cterm_bg = 0, cterm_fg = 0 },
+ screen.default_colors
+ )
+ end,
+ }
startup(true, true)
- screen:expect{condition=function()
- eq({rgb_bg=-1, rgb_fg=-1, rgb_sp=-1, cterm_bg=0, cterm_fg=0}, screen.default_colors)
- end}
+ screen:expect {
+ condition = function()
+ eq(
+ { rgb_bg = -1, rgb_fg = -1, rgb_sp = -1, cterm_bg = 0, cterm_fg = 0 },
+ screen.default_colors
+ )
+ end,
+ }
end)
end)
@@ -1039,46 +779,48 @@ 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_value('lines', {}))
- eq(99, meths.get_option_value('window', {}))
- eq(99, meths.win_get_height(0))
+ eq(100, api.nvim_get_option_value('lines', {}))
+ eq(99, api.nvim_get_option_value('window', {}))
+ eq(99, api.nvim_win_get_height(0))
feed('1000o<Esc>')
- eq(903, funcs.line('w0'))
+ eq(903, fn.line('w0'))
feed('<C-B>')
- eq(806, funcs.line('w0'))
+ eq(806, fn.line('w0'))
feed('<C-B>')
- eq(709, funcs.line('w0'))
+ eq(709, fn.line('w0'))
feed('<C-F>')
- eq(806, funcs.line('w0'))
+ eq(806, fn.line('w0'))
feed('<C-F>')
- eq(903, funcs.line('w0'))
+ eq(903, fn.line('w0'))
feed('G')
screen:try_resize(50, 50)
- 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'))
+ eq(50, api.nvim_get_option_value('lines', {}))
+ eq(49, api.nvim_get_option_value('window', {}))
+ eq(49, api.nvim_win_get_height(0))
+ eq(953, fn.line('w0'))
feed('<C-B>')
- eq(906, funcs.line('w0'))
+ eq(906, fn.line('w0'))
feed('<C-B>')
- eq(859, funcs.line('w0'))
+ eq(859, fn.line('w0'))
feed('<C-F>')
- eq(906, funcs.line('w0'))
+ eq(906, fn.line('w0'))
feed('<C-F>')
- eq(953, funcs.line('w0'))
+ eq(953, fn.line('w0'))
end)
it("showcmd doesn't cause empty grid_line with redrawdebug=compositor #22593", function()
clear()
local screen = Screen.new(30, 2)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
})
screen:attach()
command('set showcmd redrawdebug=compositor')
feed('d')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
d |
- ]]}
+ ]],
+ }
end)
diff --git a/test/functional/ui/searchhl_spec.lua b/test/functional/ui/searchhl_spec.lua
index dc7ef666bd..a05436cf55 100644
--- a/test/functional/ui/searchhl_spec.lua
+++ b/test/functional/ui/searchhl_spec.lua
@@ -5,7 +5,7 @@ local command = helpers.command
local feed_command = helpers.feed_command
local eq = helpers.eq
local eval = helpers.eval
-local funcs = helpers.funcs
+local fn = helpers.fn
local testprg = helpers.testprg
describe('search highlighting', function()
@@ -15,46 +15,50 @@ describe('search highlighting', function()
clear()
screen = Screen.new(40, 7)
screen:attach()
- screen:set_default_attr_ids( {
- [1] = {bold=true, foreground=Screen.colors.Blue},
- [2] = {background = Screen.colors.Yellow}, -- Search
- [3] = {reverse = true},
- [4] = {foreground = Screen.colors.Red}, -- WarningMsg
- [5] = {bold = true, reverse = true}, -- StatusLine
- [6] = {foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey}, -- Folded
+ screen:set_default_attr_ids({
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { background = Screen.colors.Yellow }, -- Search
+ [3] = { reverse = true },
+ [4] = { foreground = Screen.colors.Red }, -- WarningMsg
+ [5] = { bold = true, reverse = true }, -- StatusLine
+ [6] = { foreground = Screen.colors.Blue4, background = Screen.colors.LightGrey }, -- Folded
})
end)
it('is disabled by ":set nohlsearch"', function()
feed_command('set nohlsearch')
- insert("some text\nmore text")
- feed("gg/text<cr>")
+ insert('some text\nmore text')
+ feed('gg/text<cr>')
screen:expect([[
some ^text |
more text |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
/text |
]])
end)
it('is disabled in folded text', function()
- insert("some text\nmore text")
+ insert('some text\nmore text')
feed_command('1,2fold')
- feed("gg/text")
- screen:expect{grid=[[
+ feed('gg/text')
+ screen:expect {
+ grid = [[
{6:+-- 2 lines: some text·················}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
/text^ |
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 8, linecount = 2, sum_scroll_delta = 0};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 0,
+ botline = 3,
+ curline = 0,
+ curcol = 8,
+ linecount = 2,
+ sum_scroll_delta = 0,
+ },
+ },
+ }
end)
local function test_search_hl()
@@ -66,7 +70,7 @@ describe('search highlighting', function()
]])
-- 'hlsearch' is enabled by default. #2859
- feed("gg/text<cr>")
+ feed('gg/text<cr>')
screen:expect([[
some {2:^text} |
more {2:text}stuff |
@@ -78,7 +82,7 @@ describe('search highlighting', function()
]])
-- overlapping matches not allowed
- feed("3nx")
+ feed('3nx')
screen:expect([[
some {2:text} |
more {2:text}stuff |
@@ -89,7 +93,7 @@ describe('search highlighting', function()
/text |
]])
- feed("ggn*") -- search for entire word
+ feed('ggn*') -- search for entire word
screen:expect([[
some {2:text} |
more textstuff |
@@ -100,7 +104,7 @@ describe('search highlighting', function()
/\<text\> |
]])
- feed_command("nohlsearch")
+ feed_command('nohlsearch')
screen:expect([[
some text |
more textstuff |
@@ -119,7 +123,7 @@ describe('search highlighting', function()
it("works when 'winhighlight' doesn't change Search highlight", function()
command('setlocal winhl=NonText:Underlined')
local attrs = screen:get_default_attr_ids()
- attrs[1] = {foreground = Screen.colors.SlateBlue, underline = true}
+ attrs[1] = { foreground = Screen.colors.SlateBlue, underline = true }
screen:set_default_attr_ids(attrs)
test_search_hl()
end)
@@ -127,7 +131,7 @@ describe('search highlighting', function()
it("works when 'winhighlight' changes Search highlight", function()
command('setlocal winhl=Search:Underlined')
local attrs = screen:get_default_attr_ids()
- attrs[2] = {foreground = Screen.colors.SlateBlue, underline = true}
+ attrs[2] = { foreground = Screen.colors.SlateBlue, underline = true }
screen:set_default_attr_ids(attrs)
test_search_hl()
end)
@@ -135,9 +139,9 @@ describe('search highlighting', function()
describe('CurSearch highlight', function()
before_each(function()
screen:set_default_attr_ids({
- [1] = {background = Screen.colors.Yellow}, -- Search
- [2] = {foreground = Screen.colors.White, background = Screen.colors.Black}, -- CurSearch
- [3] = {foreground = Screen.colors.Red}, -- WarningMsg
+ [1] = { background = Screen.colors.Yellow }, -- Search
+ [2] = { foreground = Screen.colors.White, background = Screen.colors.Black }, -- CurSearch
+ [3] = { foreground = Screen.colors.Red }, -- WarningMsg
})
command('highlight CurSearch guibg=Black guifg=White')
end)
@@ -152,7 +156,8 @@ describe('search highlighting', function()
humans think is impossible.]])
feed('/bee<CR>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
There is no way that a {2:^bee} should be |
able to fly. Its wings are too small |
to get its fat little body off the |
@@ -160,10 +165,12 @@ describe('search highlighting', function()
anyway because {1:bee}s don't care what |
humans think is impossible. |
{3:search hit BOTTOM, continuing at TOP} |
- ]]}
+ ]],
+ }
feed('nn')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
There is no way that a {1:bee} should be |
able to fly. Its wings are too small |
to get its fat little body off the |
@@ -171,10 +178,12 @@ describe('search highlighting', function()
anyway because {2:^bee}s don't care what |
humans think is impossible. |
/bee |
- ]]}
+ ]],
+ }
feed('N')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
There is no way that a {1:bee} should be |
able to fly. Its wings are too small |
to get its fat little body off the |
@@ -182,7 +191,8 @@ describe('search highlighting', function()
anyway because {1:bee}s don't care what |
humans think is impossible. |
?bee |
- ]]}
+ ]],
+ }
end)
it('works for multiline match', function()
@@ -273,54 +283,42 @@ describe('search highlighting', function()
end)
it('highlights after EOL', function()
- insert("\n\n\n\n\n\n")
+ insert('\n\n\n\n\n\n')
- feed("gg/^<cr>")
+ feed('gg/^<cr>')
screen:expect([[
{2: } |
{2:^ } |
- {2: } |
- {2: } |
- {2: } |
- {2: } |
+ {2: } |*4
/^ |
]])
-- Test that highlights are preserved after moving the cursor.
- feed("j")
+ feed('j')
screen:expect([[
- {2: } |
- {2: } |
+ {2: } |*2
{2:^ } |
- {2: } |
- {2: } |
- {2: } |
+ {2: } |*3
/^ |
]])
-- Repeat the test in rightleft mode.
- command("nohlsearch")
- command("set rightleft")
- feed("gg/^<cr>")
+ command('nohlsearch')
+ command('set rightleft')
+ feed('gg/^<cr>')
screen:expect([[
{2: }|
{2:^ }|
- {2: }|
- {2: }|
- {2: }|
- {2: }|
+ {2: }|*4
^/ |
]])
- feed("j")
+ feed('j')
screen:expect([[
- {2: }|
- {2: }|
+ {2: }|*2
{2:^ }|
- {2: }|
- {2: }|
- {2: }|
+ {2: }|*3
^/ |
]])
end)
@@ -338,7 +336,7 @@ describe('search highlighting', function()
:file term |
]])
- feed('G') -- Follow :terminal output.
+ feed('G') -- Follow :terminal output.
feed(':vnew<CR>')
insert([[
foo bar baz
@@ -349,8 +347,7 @@ describe('search highlighting', function()
{3:foo} bar baz │{MATCH:%d+}: {2:foo}{MATCH:%s+}|
bar baz {2:foo} │{MATCH:%d+}: {2:foo}{MATCH:%s+}|
bar {2:foo} baz │{MATCH:%d+}: {2:foo}{MATCH:%s+}|
- {1:~ }│{MATCH:.*}|
- {1:~ }│{MATCH:.*}|
+ {1:~ }│{MATCH:.*}|*2
{5:[No Name] [+] }{3:term }|
/foo^ |
]])
@@ -364,82 +361,61 @@ describe('search highlighting', function()
the first line
in a little file]])
command('vsplit')
- feed("gg/li")
+ feed('gg/li')
screen:expect([[
the first {3:li}ne │the first {2:li}ne |
in a {2:li}ttle file │in a {2:li}ttle file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/li^ |
]])
-- check that consecutive matches are caught by C-g/C-t
- feed("<C-g>")
+ feed('<C-g>')
screen:expect([[
the first {2:li}ne │the first {2:li}ne |
in a {3:li}ttle file │in a {2:li}ttle file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/li^ |
]])
- feed("<C-t>")
+ feed('<C-t>')
screen:expect([[
the first {3:li}ne │the first {2:li}ne |
in a {2:li}ttle file │in a {2:li}ttle file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/li^ |
]])
- feed("t")
+ feed('t')
screen:expect([[
the first line │the first line |
in a {3:lit}tle file │in a {2:lit}tle file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/lit^ |
]])
- feed("<cr>")
+ feed('<cr>')
screen:expect([[
the first line │the first line |
in a {2:^lit}tle file │in a {2:lit}tle file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/lit |
]])
- feed("/fir")
+ feed('/fir')
screen:expect([[
the {3:fir}st line │the {2:fir}st line |
in a little file │in a little file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/fir^ |
]])
-- incsearch have priority over hlsearch
- feed("<esc>/ttle")
+ feed('<esc>/ttle')
screen:expect([[
the first line │the first line |
in a li{3:ttle} file │in a li{2:ttle} file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/ttle^ |
]])
@@ -448,10 +424,7 @@ describe('search highlighting', function()
screen:expect([[
the first line │the first line |
in a {2:^lit}tle file │in a {2:lit}tle file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
|
]])
eq('lit', eval('@/'))
@@ -461,10 +434,7 @@ describe('search highlighting', function()
screen:expect([[
the first line │the first line |
in a ^little file │in a little file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
:noh |
]])
@@ -472,20 +442,14 @@ describe('search highlighting', function()
screen:expect([[
the {3:first} line │the {2:first} line |
in a little file │in a little file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/first^ |
]])
feed('<esc>')
screen:expect([[
the first line │the first line |
in a ^little file │in a little file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
|
]])
@@ -494,43 +458,34 @@ describe('search highlighting', function()
command([[let @/ = 'i']])
-- moves to next match of previous search pattern, just like /<cr>
feed('/<c-g><cr>')
- eq({0, 1, 6, 0}, funcs.getpos('.'))
+ eq({ 0, 1, 6, 0 }, fn.getpos('.'))
-- moves to next match of previous search pattern, just like /<cr>
feed('/<cr>')
- eq({0, 1, 12, 0}, funcs.getpos('.'))
+ eq({ 0, 1, 12, 0 }, fn.getpos('.'))
-- moves to next match of previous search pattern, just like /<cr>
feed('/<c-t><cr>')
- eq({0, 2, 1, 0}, funcs.getpos('.'))
+ eq({ 0, 2, 1, 0 }, fn.getpos('.'))
-- 8.0.1304, test that C-g and C-t works with incsearch and empty pattern
feed('<esc>/fi<CR>')
screen:expect([[
the {2:fi}rst line │the {2:fi}rst line |
in a little {2:^fi}le │in a little {2:fi}le |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/fi |
]])
feed('//')
screen:expect([[
the {3:fi}rst line │the {2:fi}rst line |
in a little {2:fi}le │in a little {2:fi}le |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
//^ |
]])
feed('<C-g>')
screen:expect([[
the {2:fi}rst line │the {2:fi}rst line |
in a little {3:fi}le │in a little {2:fi}le |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
//^ |
]])
feed('<Esc>')
@@ -541,10 +496,7 @@ describe('search highlighting', function()
screen:expect([[
the first line │the first line |
in a little {3:file} │in a little {2:file} |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/file^ |
]])
feed('<Esc>')
@@ -557,10 +509,7 @@ describe('search highlighting', function()
screen:expect([[
the {3:first} line │the {2:first} line |
in a little file │in a little file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/first^ |
]])
feed('<Esc>')
@@ -570,10 +519,7 @@ describe('search highlighting', function()
screen:expect([[
the first line │the first line |
in a {3:little} file │in a {2:little} file |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
/little^ |
]])
feed('<Esc>')
@@ -586,37 +532,28 @@ describe('search highlighting', function()
not the match you're looking for
the match is here]])
- feed("gg/mat/e")
+ feed('gg/mat/e')
screen:expect([[
not the {3:mat}ch you're looking for |
the {2:mat}ch is here |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
/mat/e^ |
]])
-- Search with count and /e offset fixed in Vim patch 7.4.532.
- feed("<esc>2/mat/e")
+ feed('<esc>2/mat/e')
screen:expect([[
not the {2:mat}ch you're looking for |
the {3:mat}ch is here |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
/mat/e^ |
]])
- feed("<cr>")
+ feed('<cr>')
screen:expect([[
not the {2:mat}ch you're looking for |
the {2:ma^t}ch is here |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
/mat/e |
]])
end)
@@ -628,8 +565,7 @@ describe('search highlighting', function()
screen:expect([[
|
a repeated {2:^line } |
- {2:a} repeated {2:line } |
- {2:a} repeated {2:line } |
+ {2:a} repeated {2:line } |*2
{2:a} repeated line |
{1:~ }|
{4:search hit BOTTOM, continuing at TOP} |
@@ -650,83 +586,80 @@ describe('search highlighting', function()
it('works with matchadd and syntax', function()
screen:set_default_attr_ids {
- [1] = {bold=true, foreground=Screen.colors.Blue};
- [2] = {background = Screen.colors.Yellow};
- [3] = {reverse = true};
- [4] = {foreground = Screen.colors.Red};
- [5] = {bold = true, background = Screen.colors.Green};
- [6] = {italic = true, background = Screen.colors.Magenta};
- [7] = {bold = true, background = Screen.colors.Yellow};
- [8] = {foreground = Screen.colors.Blue4, background = Screen.colors.LightGray};
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { background = Screen.colors.Yellow },
+ [3] = { reverse = true },
+ [4] = { foreground = Screen.colors.Red },
+ [5] = { bold = true, background = Screen.colors.Green },
+ [6] = { italic = true, background = Screen.colors.Magenta },
+ [7] = { bold = true, background = Screen.colors.Yellow },
+ [8] = { foreground = Screen.colors.Blue4, background = Screen.colors.LightGray },
}
feed_command('set hlsearch')
insert [[
very special text
]]
- feed_command("syntax on")
- feed_command("highlight MyGroup guibg=Green gui=bold")
- feed_command("highlight MyGroup2 guibg=Magenta gui=italic")
+ feed_command('syntax on')
+ feed_command('highlight MyGroup guibg=Green gui=bold')
+ feed_command('highlight MyGroup2 guibg=Magenta gui=italic')
feed_command("call matchadd('MyGroup', 'special')")
feed_command("call matchadd('MyGroup2', 'text', 0)")
-- searchhl and matchadd matches are exclusive, only the highest priority
-- is used (and matches with lower priorities are not combined)
- feed_command("/ial te")
- screen:expect{grid=[[
+ feed_command('/ial te')
+ screen:expect {
+ grid = [[
very {5:spec^ial}{2: te}{6:xt} |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{4:search hit BOTTOM, continuing at TOP} |
- ]], win_viewport={
- [2] = {win = {id = 1000}, topline = 0, botline = 3, curline = 0, curcol = 11, linecount = 2, sum_scroll_delta = 0};
- }}
+ ]],
+ win_viewport = {
+ [2] = {
+ win = 1000,
+ topline = 0,
+ botline = 3,
+ curline = 0,
+ curcol = 11,
+ linecount = 2,
+ sum_scroll_delta = 0,
+ },
+ },
+ }
-- check highlights work also in folds
- feed("zf4j")
- screen:expect{grid=[[
+ feed('zf4j')
+ screen:expect {
+ grid = [[
{8:^+-- 2 lines: very special text·········}|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
{4:search hit BOTTOM, continuing at TOP} |
- ]]}
- command("%foldopen")
+ ]],
+ }
+ command('%foldopen')
screen:expect([[
very {5:spec^ial}{2: te}{6:xt} |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
{4:search hit BOTTOM, continuing at TOP} |
]])
- feed_command("call clearmatches()")
+ feed_command('call clearmatches()')
screen:expect([[
very spec{2:^ial te}xt |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
:call clearmatches() |
]])
-- searchhl has priority over syntax, but in this case
-- nonconflicting attributes are combined
- feed_command("syntax keyword MyGroup special")
+ feed_command('syntax keyword MyGroup special')
screen:expect([[
very {5:spec}{7:^ial}{2: te}xt |
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*4
:syntax keyword MyGroup special |
]])
end)
@@ -737,13 +670,8 @@ describe('search highlighting', function()
feed(':%g@a/b')
screen:expect([[
{3:a/b}/c |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
:%g@a/b^ |
]])
end)
end)
-
diff --git a/test/functional/ui/sign_spec.lua b/test/functional/ui/sign_spec.lua
index b12e79bd42..847a918dc9 100644
--- a/test/functional/ui/sign_spec.lua
+++ b/test/functional/ui/sign_spec.lua
@@ -1,8 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local clear, feed, command = helpers.clear, helpers.feed, helpers.command
-local source = helpers.source
-local meths = helpers.meths
+local api, clear, eq = helpers.api, helpers.clear, helpers.eq
+local eval, exec, feed = helpers.eval, helpers.exec, helpers.feed
describe('Signs', function()
local screen
@@ -11,90 +10,68 @@ describe('Signs', function()
clear()
screen = Screen.new()
screen:attach()
- screen:set_default_attr_ids( {
- [0] = {bold=true, foreground=255},
- [1] = {background = Screen.colors.Yellow},
- [2] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.Grey},
- [3] = {background = Screen.colors.Gray90},
- [4] = {bold = true, reverse = true},
- [5] = {reverse = true},
- [6] = {foreground = Screen.colors.Brown},
- [7] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey},
- [8] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
- [9] = {bold = true, foreground = Screen.colors.Magenta},
- [10] = {foreground = Screen.colors.Blue1},
- [11] = {bold = true, foreground = Screen.colors.SeaGreen4},
- } )
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = 255 },
+ [1] = { background = Screen.colors.Yellow },
+ [2] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.Grey },
+ [3] = { background = Screen.colors.Gray90 },
+ [4] = { bold = true, reverse = true },
+ [5] = { reverse = true },
+ [6] = { foreground = Screen.colors.Brown },
+ [7] = { foreground = Screen.colors.DarkBlue, background = Screen.colors.LightGrey },
+ [8] = { foreground = Screen.colors.Grey100, background = Screen.colors.Red },
+ [9] = { bold = true, foreground = Screen.colors.Magenta },
+ [10] = { foreground = Screen.colors.Blue1 },
+ [11] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ })
end)
describe(':sign place', function()
it('allows signs with combining characters', function()
feed('ia<cr>b<cr><esc>')
- command('sign define piet1 text=ðŒ¢Ì€Ì̂̃̅̄ðŒ¢Ì€Ì̂̃̅̄ texthl=Search')
- command('sign define piet2 text=𠜎̀Ì̂̃̄̅ texthl=Search')
- command('sign place 1 line=1 name=piet1 buffer=1')
- command('sign place 2 line=2 name=piet2 buffer=1')
+ exec([[
+ sign define piet1 text=ðŒ¢Ì€Ì̂̃̅̄ðŒ¢Ì€Ì̂̃̅̄ texthl=Search
+ sign define piet2 text=𠜎̀Ì̂̃̄̅ texthl=Search
+ sign place 1 line=1 name=piet1 buffer=1
+ sign place 2 line=2 name=piet2 buffer=1
+ ]])
screen:expect([[
{1:ðŒ¢Ì€Ì̂̃̅̄ðŒ¢Ì€Ì̂̃̅̄}a |
{1:𠜎̀Ì̂̃̄̅}b |
{2: }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*10
|
]])
end)
it('shadows previously placed signs', function()
feed('ia<cr>b<cr>c<cr><esc>')
- command('sign define piet text=>> texthl=Search')
- command('sign define pietx text=>! texthl=Search')
- command('sign place 1 line=1 name=piet buffer=1')
- command('sign place 2 line=3 name=piet buffer=1')
- command('sign place 3 line=1 name=pietx buffer=1')
+ exec([[
+ sign define piet text=>> texthl=Search
+ sign define pietx text=>! texthl=Search
+ sign place 1 line=1 name=piet buffer=1
+ sign place 2 line=3 name=piet buffer=1
+ sign place 3 line=1 name=pietx buffer=1
+ ]])
screen:expect([[
{1:>!}a |
{2: }b |
{1:>>}c |
{2: }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
end)
it('allows signs with no text', function()
feed('ia<cr>b<cr><esc>')
- command('sign define piet1 text= texthl=Search')
- command('sign place 1 line=1 name=piet1 buffer=1')
+ exec('sign define piet1 text= texthl=Search')
+ exec('sign place 1 line=1 name=piet1 buffer=1')
screen:expect([[
a |
b |
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*10
|
]])
end)
@@ -104,7 +81,7 @@ describe('Signs', function()
-- This used to cause a crash due to :sign using a special redraw
-- (not updating nvim's specific highlight data structures)
-- without proper redraw first, as split just flags for redraw later.
- source([[
+ exec([[
set cursorline
sign define piet text=>> texthl=Search
split
@@ -115,8 +92,7 @@ describe('Signs', function()
{1:>>}b |
{2: }c |
{2: } |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{4:[No Name] [+] }|
{2: }{3:a }|
{1:>>}b |
@@ -130,58 +106,45 @@ describe('Signs', function()
it('can combine text, linehl and numhl', function()
feed('ia<cr>b<cr>c<cr><esc>')
- command('set number')
- command('sign define piet text=>> texthl=Search')
- command('sign define pietx linehl=ErrorMsg')
- command('sign define pietxx numhl=Folded')
- command('sign place 1 line=1 name=piet buffer=1')
- command('sign place 2 line=2 name=pietx buffer=1')
- command('sign place 3 line=3 name=pietxx buffer=1')
- command('sign place 4 line=4 name=piet buffer=1')
- command('sign place 5 line=4 name=pietx buffer=1')
- command('sign place 6 line=4 name=pietxx buffer=1')
+ exec([[
+ set number
+ sign define piet text=>> texthl=Search
+ sign define pietx linehl=ErrorMsg
+ sign define pietxx numhl=Folded
+ sign place 1 line=1 name=piet buffer=1
+ sign place 2 line=2 name=pietx buffer=1
+ sign place 3 line=3 name=pietxx buffer=1
+ sign place 4 line=4 name=piet buffer=1
+ sign place 5 line=4 name=pietx buffer=1
+ sign place 6 line=4 name=pietxx buffer=1
+ ]])
screen:expect([[
{1:>>}{6: 1 }a |
{2: }{6: 2 }{8:b }|
{2: }{7: 3 }c |
{1:>>}{7: 4 }{8:^ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
-- Check that 'statuscolumn' correctly applies numhl
- command('set statuscolumn=%s%=%l\\ ')
+ exec('set statuscolumn=%s%=%l\\ ')
screen:expect_unchanged()
end)
it('highlights the cursorline sign with culhl', function()
feed('ia<cr>b<cr>c<esc>')
- command('sign define piet text=>> texthl=Search culhl=ErrorMsg')
- command('sign place 1 line=1 name=piet buffer=1')
- command('sign place 2 line=2 name=piet buffer=1')
- command('sign place 3 line=3 name=piet buffer=1')
- command('set cursorline')
+ exec([[
+ sign define piet text=>> texthl=Search culhl=ErrorMsg
+ sign place 1 line=1 name=piet buffer=1
+ sign place 2 line=2 name=piet buffer=1
+ sign place 3 line=3 name=piet buffer=1
+ set cursorline
+ ]])
screen:expect([[
{1:>>}a |
{1:>>}b |
{8:>>}{3:^c }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*10
|
]])
feed('k')
@@ -189,411 +152,304 @@ describe('Signs', function()
{1:>>}a |
{8:>>}{3:^b }|
{1:>>}c |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*10
|
]])
- command('set nocursorline')
+ exec('set nocursorline')
screen:expect([[
{1:>>}a |
{1:>>}^b |
{1:>>}c |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*10
|
]])
- command('set cursorline cursorlineopt=line')
+ exec('set cursorline cursorlineopt=line')
screen:expect([[
{1:>>}a |
{1:>>}{3:^b }|
{1:>>}c |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*10
|
]])
- command('set cursorlineopt=number')
- command('hi! link SignColumn IncSearch')
+ exec('set cursorlineopt=number')
+ exec('hi! link SignColumn IncSearch')
feed('Go<esc>2G')
screen:expect([[
{1:>>}a |
{8:>>}^b |
{1:>>}c |
{5: } |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
-- Check that 'statuscolumn' cursorline/signcolumn highlights are the same (#21726)
- command('set statuscolumn=%s')
+ exec('set statuscolumn=%s')
screen:expect_unchanged()
end)
it('multiple signs #9295', function()
feed('ia<cr>b<cr>c<cr><esc>')
- command('set number')
- command('set signcolumn=yes:2')
- command('sign define pietSearch text=>> texthl=Search')
- command('sign define pietError text=XX texthl=Error')
- command('sign define pietWarn text=WW texthl=Warning')
- command('sign place 1 line=1 name=pietSearch buffer=1')
- command('sign place 2 line=1 name=pietError buffer=1')
- -- Line 2 helps checking that signs in the same line are ordered by Id.
- command('sign place 4 line=2 name=pietSearch buffer=1')
- command('sign place 3 line=2 name=pietError buffer=1')
+ exec([[
+ set number
+ set signcolumn=yes:2
+ sign define pietSearch text=>> texthl=Search
+ sign define pietError text=XX texthl=Error
+ sign define pietWarn text=WW texthl=Warning
+ sign place 6 line=3 name=pietSearch buffer=1
+ sign place 7 line=3 name=pietWarn buffer=1
+ sign place 5 line=3 name=pietError buffer=1
+ ]])
-- Line 3 checks that with a limit over the maximum number
-- of signs, the ones with the highest Ids are being picked,
-- and presented by their sorted Id order.
- command('sign place 6 line=3 name=pietSearch buffer=1')
- command('sign place 7 line=3 name=pietWarn buffer=1')
- command('sign place 5 line=3 name=pietError buffer=1')
+ screen:expect([[
+ {2: }{6: 1 }a |
+ {2: }{6: 2 }b |
+ {1:>>}WW{6: 3 }c |
+ {2: }{6: 4 }^ |
+ {0:~ }|*9
+ |
+ ]])
+ exec([[
+ sign place 1 line=1 name=pietSearch buffer=1
+ sign place 2 line=1 name=pietError buffer=1
+ " Line 2 helps checking that signs in the same line are ordered by Id.
+ sign place 4 line=2 name=pietSearch buffer=1
+ sign place 3 line=2 name=pietError buffer=1
+ ]])
screen:expect([[
{1:>>}{8:XX}{6: 1 }a |
{8:XX}{1:>>}{6: 2 }b |
{1:>>}WW{6: 3 }c |
{2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
-- With the default setting, we get the sign with the top id.
- command('set signcolumn=yes:1')
+ exec('set signcolumn=yes:1')
screen:expect([[
{8:XX}{6: 1 }a |
{1:>>}{6: 2 }b |
WW{6: 3 }c |
{2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
-- "auto:3" accommodates all the signs we defined so far.
- command('set signcolumn=auto:3')
- screen:expect([[
+ exec('set signcolumn=auto:3')
+ local s3 = [[
{1:>>}{8:XX}{2: }{6: 1 }a |
{8:XX}{1:>>}{2: }{6: 2 }b |
{8:XX}{1:>>}WW{6: 3 }c |
{2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
- ]])
+ ]]
+ screen:expect(s3)
-- Check "yes:9".
- command('set signcolumn=yes:9')
+ exec('set signcolumn=yes:9')
screen:expect([[
{1:>>}{8:XX}{2: }{6: 1 }a |
{8:XX}{1:>>}{2: }{6: 2 }b |
{8:XX}{1:>>}WW{2: }{6: 3 }c |
{2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
-- Check "auto:N" larger than the maximum number of signs defined in
-- a single line (same result as "auto:3").
- command('set signcolumn=auto:4')
- screen:expect{grid=[[
- {1:>>}{8:XX}{2: }{6: 1 }a |
- {8:XX}{1:>>}{2: }{6: 2 }b |
- {8:XX}{1:>>}WW{6: 3 }c |
- {2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- |
- ]]}
+ exec('set signcolumn=auto:4')
+ screen:expect(s3)
-- line deletion deletes signs.
- command('2d')
+ exec('3move1')
+ exec('2d')
screen:expect([[
- {1:>>}{8:XX}{2: }{6: 1 }a |
- {8:XX}{1:>>}WW{6: 2 }^c |
- {2: }{6: 3 } |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {1:>>}{8:XX}{6: 1 }a |
+ {8:XX}{1:>>}{6: 2 }^b |
+ {2: }{6: 3 } |
+ {0:~ }|*10
+ |
+ ]])
+ -- character deletion does not delete signs.
+ feed('x')
+ screen:expect([[
+ {1:>>}{8:XX}{6: 1 }a |
+ {8:XX}{1:>>}{6: 2 }^ |
+ {2: }{6: 3 } |
+ {0:~ }|*10
|
]])
end)
it('auto-resize sign column with minimum size (#13783)', function()
feed('ia<cr>b<cr>c<cr><esc>')
- command('set number')
+ exec('set number')
-- sign column should always accommodate at the minimum size
- command('set signcolumn=auto:1-3')
+ exec('set signcolumn=auto:1-3')
screen:expect([[
{2: }{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
{2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
-- should support up to 8 signs at minimum
- command('set signcolumn=auto:8-9')
+ exec('set signcolumn=auto:8-9')
screen:expect([[
{2: }{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
{2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
-- should keep the same sign size when signs are not exceeding
-- the minimum
- command('set signcolumn=auto:2-5')
- command('sign define pietSearch text=>> texthl=Search')
- command('sign place 1 line=1 name=pietSearch buffer=1')
+ exec('set signcolumn=auto:2-5')
+ exec('sign define pietSearch text=>> texthl=Search')
+ exec('sign place 1 line=1 name=pietSearch buffer=1')
screen:expect([[
{1:>>}{2: }{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
{2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
-- should resize itself when signs are exceeding minimum but
-- not over the maximum
- command('sign place 2 line=1 name=pietSearch buffer=1')
- command('sign place 3 line=1 name=pietSearch buffer=1')
- command('sign place 4 line=1 name=pietSearch buffer=1')
+ exec([[
+ sign place 2 line=1 name=pietSearch buffer=1
+ sign place 3 line=1 name=pietSearch buffer=1
+ sign place 4 line=1 name=pietSearch buffer=1
+ ]])
screen:expect([[
{1:>>>>>>>>}{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
{2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
-- should not increase size because sign with existing id is moved
- command('sign place 4 line=1 name=pietSearch buffer=1')
+ exec('sign place 4 line=1 name=pietSearch buffer=1')
screen:expect_unchanged()
- command('sign unplace 4')
+ exec('sign unplace 4')
screen:expect([[
{1:>>>>>>}{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
{2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
- command('sign place 4 line=1 name=pietSearch buffer=1')
+ exec('sign place 4 line=1 name=pietSearch buffer=1')
-- should keep the column at maximum size when signs are
-- exceeding the maximum
- command('sign place 5 line=1 name=pietSearch buffer=1')
- command('sign place 6 line=1 name=pietSearch buffer=1')
- command('sign place 7 line=1 name=pietSearch buffer=1')
- command('sign place 8 line=1 name=pietSearch buffer=1')
+ exec([[
+ sign place 5 line=1 name=pietSearch buffer=1
+ sign place 6 line=1 name=pietSearch buffer=1
+ sign place 7 line=1 name=pietSearch buffer=1
+ sign place 8 line=1 name=pietSearch buffer=1
+ ]])
screen:expect([[
{1:>>>>>>>>>>}{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
{2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
end)
it('ignores signs with no icon and text when calculating the signcolumn width', function()
feed('ia<cr>b<cr>c<cr><esc>')
- command('set number')
- command('set signcolumn=auto:2')
- command('sign define pietSearch text=>> texthl=Search')
- command('sign define pietError text= texthl=Error')
- command('sign place 2 line=1 name=pietError buffer=1')
+ exec([[
+ set number
+ set signcolumn=auto:2
+ sign define pietSearch text=>> texthl=Search
+ sign define pietError text= texthl=Error
+ sign place 2 line=1 name=pietError buffer=1
+ ]])
-- no signcolumn with only empty sign
screen:expect([[
{6: 1 }a |
{6: 2 }b |
{6: 3 }c |
{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
-- single column with 1 sign with text and one sign without
- command('sign place 1 line=1 name=pietSearch buffer=1')
+ exec('sign place 1 line=1 name=pietSearch buffer=1')
screen:expect([[
{1:>>}{6: 1 }a |
{2: }{6: 2 }b |
{2: }{6: 3 }c |
{2: }{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
end)
- it('shows the line number when signcolumn=number but no marks on a line have text', function()
+ it('signcolumn=number', function()
feed('ia<cr>b<cr>c<cr><esc>')
- command('set number signcolumn=number')
- command('sign define pietSearch text=>> texthl=Search numhl=Error')
- command('sign define pietError text= texthl=Search numhl=Error')
- command('sign place 1 line=1 name=pietSearch buffer=1')
- command('sign place 2 line=2 name=pietError buffer=1')
+ exec([[
+ set number signcolumn=number
+ sign define pietSearch text=>> texthl=Search numhl=Error
+ sign define pietError text= texthl=Search numhl=Error
+ sign place 1 line=1 name=pietSearch buffer=1
+ sign place 2 line=2 name=pietError buffer=1
+ ]])
+ -- line number should be drawn if sign has no text
-- no signcolumn, line number for "a" is Search, for "b" is Error, for "c" is LineNr
screen:expect([[
{1: >> }a |
{8: 2 }b |
{6: 3 }c |
{6: 4 }^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
+ |
+ ]])
+ -- number column on wrapped part of a line should be empty
+ feed('gg100aa<Esc>')
+ screen:expect([[
+ {1: >> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {8: }aa^a |
+ {8: 2 }b |
+ {6: 3 }c |
+ {6: 4 } |
+ {0:~ }|*7
+ |
+ ]])
+ api.nvim_buf_set_extmark(0, api.nvim_create_namespace('test'), 0, 0, {
+ virt_lines = { { { 'VIRT LINES' } } },
+ virt_lines_above = true,
+ })
+ feed('<C-Y>')
+ -- number column on virtual lines should be empty
+ screen:expect([[
+ {6: }VIRT LINES |
+ {1: >> }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {8: }aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {8: }aa^a |
+ {8: 2 }b |
+ {6: 3 }c |
+ {6: 4 } |
+ {0:~ }|*6
|
]])
end)
it('can have 32bit sign IDs', function()
- command('sign define piet text=>> texthl=Search')
- command('sign place 100000 line=1 name=piet buffer=1')
+ exec('sign define piet text=>> texthl=Search')
+ exec('sign place 100000 line=1 name=piet buffer=1')
feed(':sign place<cr>')
screen:expect([[
{1:>>} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
{4: }|
:sign place |
{9:--- Signs ---} |
@@ -606,72 +462,45 @@ describe('Signs', function()
feed('<cr>')
screen:expect([[
{1:>>}^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*12
|
]])
end)
end)
it('signcolumn width is updated when removing all signs after deleting lines', function()
- meths.buf_set_lines(0, 0, 1, true, {'a', 'b', 'c', 'd', 'e'})
- command('sign define piet text=>>')
- command('sign place 10001 line=1 name=piet')
- command('sign place 10002 line=5 name=piet')
- command('2delete')
- command('sign unplace 10001')
+ api.nvim_buf_set_lines(0, 0, 1, true, { 'a', 'b', 'c', 'd', 'e' })
+ exec('sign define piet text=>>')
+ exec('sign place 10001 line=1 name=piet')
+ exec('sign place 10002 line=5 name=piet')
+ exec('2delete')
+ exec('sign unplace 10001')
screen:expect([[
{2: }a |
{2: }^c |
{2: }d |
>>e |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
- command('sign unplace 10002')
+ exec('sign unplace 10002')
screen:expect([[
a |
^c |
d |
e |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*9
|
]])
end)
it('signcolumn width is updated when removing all signs after inserting lines', function()
- meths.buf_set_lines(0, 0, 1, true, {'a', 'b', 'c', 'd', 'e'})
- command('sign define piet text=>>')
- command('sign place 10001 line=1 name=piet')
- command('sign place 10002 line=5 name=piet')
- command('copy .')
- command('sign unplace 10001')
+ api.nvim_buf_set_lines(0, 0, 1, true, { 'a', 'b', 'c', 'd', 'e' })
+ exec('sign define piet text=>>')
+ exec('sign place 10001 line=1 name=piet')
+ exec('sign place 10002 line=5 name=piet')
+ exec('copy .')
+ exec('sign unplace 10001')
screen:expect([[
{2: }a |
{2: }^a |
@@ -679,16 +508,10 @@ describe('Signs', function()
{2: }c |
{2: }d |
>>e |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
|
]])
- command('sign unplace 10002')
+ exec('sign unplace 10002')
screen:expect([[
a |
^a |
@@ -696,20 +519,14 @@ describe('Signs', function()
c |
d |
e |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
|
]])
end)
it('numhl highlight is applied when signcolumn=no', function()
screen:try_resize(screen._width, 4)
- command([[
+ exec([[
set nu scl=no
call setline(1, ['line1', 'line2', 'line3'])
call nvim_buf_set_extmark(0, nvim_create_namespace('test'), 0, 0, {'number_hl_group':'Error'})
@@ -723,4 +540,39 @@ describe('Signs', function()
|
]])
end)
+
+ it('no negative b_signcols.count with undo after initializing', function()
+ exec([[
+ set signcolumn=auto:2
+ call setline(1, 'a')
+ call nvim_buf_set_extmark(0, nvim_create_namespace(''), 0, 0, {'sign_text':'S1'})
+ delete | redraw | undo
+ ]])
+ end)
+
+ it('sign not shown on line it was previously on after undo', function()
+ exec([[
+ call setline(1, range(1, 4))
+ call nvim_buf_set_extmark(0, nvim_create_namespace(''), 1, 0, {'sign_text':'S1'})
+ ]])
+ exec('norm 2Gdd')
+ exec('silent undo')
+ screen:expect([[
+ {2: }1 |
+ S1^2 |
+ {2: }3 |
+ {2: }4 |
+ {0:~ }|*9
+ |
+ ]])
+ end)
+
+ it('sign_undefine() frees all signs', function()
+ exec([[
+ sign define 1 text=1
+ sign define 2 text=2
+ call sign_undefine()
+ ]])
+ eq({}, eval('sign_getdefined()'))
+ end)
end)
diff --git a/test/functional/ui/spell_spec.lua b/test/functional/ui/spell_spec.lua
index d18e19e5b2..8b5644ee42 100644
--- a/test/functional/ui/spell_spec.lua
+++ b/test/functional/ui/spell_spec.lua
@@ -6,8 +6,7 @@ local clear = helpers.clear
local exec = helpers.exec
local feed = helpers.feed
local insert = helpers.insert
-local meths = helpers.meths
-local curbufmeths = helpers.curbufmeths
+local api = helpers.api
local is_os = helpers.is_os
describe("'spell'", function()
@@ -17,23 +16,26 @@ describe("'spell'", function()
clear()
screen = Screen.new(80, 8)
screen:attach()
- screen:set_default_attr_ids( {
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {special = Screen.colors.Red, undercurl = true},
- [2] = {special = Screen.colors.Blue, undercurl = true},
- [3] = {foreground = tonumber('0x6a0dad')},
- [4] = {foreground = Screen.colors.Magenta},
- [5] = {bold = true, foreground = Screen.colors.SeaGreen},
- [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},
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { special = Screen.colors.Red, undercurl = true },
+ [2] = { special = Screen.colors.Blue, undercurl = true },
+ [3] = { foreground = tonumber('0x6a0dad') },
+ [4] = { foreground = Screen.colors.Magenta },
+ [5] = { bold = true, foreground = Screen.colors.SeaGreen },
+ [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
+ if is_os('openbsd') then
+ pending('FIXME #12104', function() end)
+ return
+ end
exec('set spell')
insert([[
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod
@@ -54,7 +56,6 @@ describe("'spell'", function()
{0:~ }|
|
]])
-
end)
-- oldtest: Test_spell_screendump()
@@ -125,8 +126,7 @@ describe("'spell'", function()
Not |
and her^e |
and here. |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
-- Undo also updates the next line (go to command line to remove message)
@@ -137,8 +137,7 @@ describe("'spell'", function()
Not |
and here^. |
{2:and} here. |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
-- Folding an empty line does not remove Cap in next line
@@ -149,8 +148,7 @@ describe("'spell'", function()
Not |
{10:^+-- 2 lines: and here.·························································}|
{2:and} here. |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
-- Folding the end of a sentence does not remove Cap in next line
@@ -161,9 +159,7 @@ describe("'spell'", function()
{2:another} missing cap her^e |
{10:+-- 2 lines: Not·······························································}|
{2:and} here. |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
-- Cap is correctly applied in the first row of a window
@@ -172,10 +168,7 @@ describe("'spell'", function()
{2:another} missing cap her^e |
{10:+-- 2 lines: Not·······························································}|
{2:and} here. |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
-- Adding an empty line does not remove Cap in "mod_bot" area
@@ -186,8 +179,7 @@ describe("'spell'", function()
{2:another} missing cap here |
{10:+-- 2 lines: Not·······························································}|
{2:and} here. |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
-- Multiple empty lines does not remove Cap in the line after
@@ -220,9 +212,7 @@ describe("'spell'", function()
test test test test$ |
|
{2:end} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{9:-- INSERT --} |
]])
feed('x')
@@ -231,9 +221,7 @@ describe("'spell'", function()
test test test test$ |
|
{2:end} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{9:-- INSERT --} |
]])
end)
@@ -251,10 +239,7 @@ describe("'spell'", function()
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:spelin^g}{7: }{8:mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
feed(']s')
@@ -262,10 +247,7 @@ describe("'spell'", function()
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:speling}{7: }{8:^mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
feed(']s')
@@ -273,24 +255,18 @@ describe("'spell'", function()
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:^speling}{7: }{8:mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{6:search hit BOTTOM, continuing at TOP} |
]])
exec('echo ""')
- local ns = meths.create_namespace("spell")
+ local ns = api.nvim_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 })
+ local id = api.nvim_buf_set_extmark(0, ns, 1, 4, { end_row = 1, end_col = 10, spell = true })
screen:expect([[
{3:#include }{4:<stdbool.h>} |
{5:bool} {1:func}({5:void}); |
{7:// I am a }{8:^speling}{7: }{8:mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
feed('[s')
@@ -298,23 +274,17 @@ describe("'spell'", function()
{3:#include }{4:<stdbool.h>} |
{5:bool} {1:^func}({5:void}); |
{7:// I am a }{8:speling}{7: }{8:mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
- curbufmeths.del_extmark(ns, id)
+ api.nvim_buf_del_extmark(0, ns, id)
-- extmark with spell=false disables spell
- id = curbufmeths.set_extmark(ns, 2, 18, { end_row = 2, end_col = 26, spell = false })
+ id = api.nvim_buf_set_extmark(0, ns, 2, 18, { end_row = 2, end_col = 26, spell = false })
screen:expect([[
{3:#include }{4:<stdbool.h>} |
{5:bool} ^func({5:void}); |
{7:// I am a }{8:speling}{7: mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
feed('[s')
@@ -322,22 +292,16 @@ describe("'spell'", function()
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:^speling}{7: mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{6:search hit TOP, continuing at BOTTOM} |
]])
exec('echo ""')
- curbufmeths.del_extmark(ns, id)
+ api.nvim_buf_del_extmark(0, ns, id)
screen:expect([[
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:^speling}{7: }{8:mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
feed(']s')
@@ -345,10 +309,7 @@ describe("'spell'", function()
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:speling}{7: }{8:^mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
-- "noplainbuffer" shouldn't change spellchecking behavior with syntax enabled
@@ -359,10 +320,7 @@ describe("'spell'", function()
{3:#include }{4:<stdbool.h>} |
{5:bool} func({5:void}); |
{7:// I am a }{8:^speling}{7: }{8:mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
-- no spellchecking with "noplainbuffer" and syntax disabled
@@ -371,10 +329,7 @@ describe("'spell'", function()
#include <stdbool.h> |
bool func(void); |
// I am a ^speling mistakke |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
feed(']s')
@@ -382,10 +337,7 @@ describe("'spell'", function()
#include <stdbool.h> |
bool func(void); |
// I am a ^speling mistakke |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{6:search hit BOTTOM, continuing at TOP} |
]])
exec('echo ""')
@@ -395,10 +347,7 @@ describe("'spell'", function()
#include <{1:stdbool}.h> |
{1:bool} {1:func}(void); |
// I am a {1:^speling} {1:mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
feed('[s')
@@ -406,10 +355,7 @@ describe("'spell'", function()
#include <{1:stdbool}.h> |
{1:bool} {1:^func}(void); |
// I am a {1:speling} {1:mistakke} |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end)
@@ -421,8 +367,8 @@ describe("'spell'", function()
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 })
+ local ns = api.nvim_create_namespace('spell')
+ api.nvim_buf_set_extmark(0, ns, 0, 0, { hl_group = 'WarningMsg', end_col = 43 })
screen:expect([[
{6:^This is some text without any spell errors.}|
{0:~ }|
diff --git a/test/functional/ui/statuscolumn_spec.lua b/test/functional/ui/statuscolumn_spec.lua
index 6eaf15cfad..41406a5860 100644
--- a/test/functional/ui/statuscolumn_spec.lua
+++ b/test/functional/ui/statuscolumn_spec.lua
@@ -7,11 +7,11 @@ local exec = helpers.exec
local eval = helpers.eval
local exec_lua = helpers.exec_lua
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
local pcall_err = helpers.pcall_err
local assert_alive = helpers.assert_alive
-local mousemodels = { "extend", "popup", "popup_setpos" }
+local mousemodels = { 'extend', 'popup', 'popup_setpos' }
describe('statuscolumn', function()
local screen
@@ -23,7 +23,9 @@ describe('statuscolumn', function()
end)
it("fails with invalid 'statuscolumn'", function()
- command([[set stc=%{v:relnum?v:relnum:(v:lnum==5?invalid:v:lnum)}\ ]])
+ command(
+ [[set stc=%{v:relnum?v:relnum:(v:lnum==5?'truncate':v:lnum)}%{!v:relnum&&v:lnum==5?invalid:''}\ ]]
+ )
screen:expect([[
4 aaaaa |
3 aaaaa |
@@ -43,6 +45,22 @@ describe('statuscolumn', function()
command('norm 5G')
eq('Vim(redraw):E121: Undefined variable: invalid', pcall_err(command, 'redraw!'))
eq('', eval('&statuscolumn'))
+ screen:expect([[
+ 4 aaaaa |
+ 5 ^aaaaa |
+ 6 aaaaa |
+ 7 aaaaa |
+ 8 aaaaa |
+ 9 aaaaa |
+ 10 aaaaa |
+ 11 aaaaa |
+ 12 aaaaa |
+ 13 aaaaa |
+ 14 aaaaa |
+ 15 aaaaa |
+ 16 aaaaa |
+ |
+ ]])
end)
it("widens with irregular 'statuscolumn' width", function()
@@ -59,6 +77,18 @@ describe('statuscolumn', function()
1 aaaaa |
|
]])
+ -- Doesn't crash when trying to fill click defs that do not fit (#26845)
+ command('norm gg')
+ command([=[
+ set stc=%@Click@%{v:relnum?v:relnum:(v:lnum==5?'bbbbb':v:lnum)}%T
+ norm 5Gzt | redraw!
+ ]=])
+ screen:expect([[
+ bbbbba^eaaa |
+ 1 aaaaa |
+ 2 aaaaa |
+ |
+ ]])
end)
it("works with 'number' and 'relativenumber'", function()
@@ -125,12 +155,14 @@ describe('statuscolumn', function()
end)
it("works with highlighted 'statuscolumn'", function()
- command([[set stc=%#NonText#%{&nu?v:lnum:''}]] ..
- [[%=%{&rnu&&(v:lnum%2)?'\ '.v:relnum:''}]] ..
- [[%#LineNr#%{&rnu&&!(v:lnum%2)?'\ '.v:relnum:''}│]])
+ command(
+ [[set stc=%#NonText#%{&nu?v:lnum:''}]]
+ .. [[%=%{&rnu&&(v:lnum%2)?'\ '.v:relnum:''}]]
+ .. [[%#LineNr#%{&rnu&&!(v:lnum%2)?'\ '.v:relnum:''}│]]
+ )
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {foreground = Screen.colors.Brown},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { foreground = Screen.colors.Brown },
})
screen:expect([[
{0:4 }{1:│}aaaaa |
@@ -188,13 +220,13 @@ describe('statuscolumn', function()
command([[set stc=%C%s%=%{v:virtnum?'':v:lnum}│\ ]])
command("call setline(1,repeat([repeat('aaaaa',10)],16))")
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue},
- [1] = {foreground = Screen.colors.Brown},
- [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] = {foreground = Screen.colors.Red},
- [6] = {foreground = Screen.colors.Red, background = Screen.colors.LightGrey},
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { foreground = Screen.colors.Brown },
+ [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] = { foreground = Screen.colors.Red },
+ [6] = { foreground = Screen.colors.Red, background = Screen.colors.LightGrey },
})
command('hi! CursorLine guifg=Red guibg=NONE')
screen:expect([[
@@ -418,7 +450,9 @@ describe('statuscolumn', function()
vim.api.nvim_buf_set_extmark(0, ns, 4, 0, { virt_lines = {{{"virt_line", ""}}} })
]])
command('set foldcolumn=0 signcolumn=no')
- command([[set stc=%{v:virtnum<0?'virtual':(!v:virtnum?'buffer':'wrapped')}%=%{'\ '.v:virtnum.'\ '.v:lnum}]])
+ command(
+ [[set stc=%{v:virtnum<0?'virtual':(!v:virtnum?'buffer':'wrapped')}%=%{'\ '.v:virtnum.'\ '.v:lnum}]]
+ )
screen:expect([[
{1:buffer 0 4}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
{1:wrapped 1 4}aaaaaaaa |
@@ -451,9 +485,7 @@ describe('statuscolumn', function()
{4:wrapped 1 15}{5:aaaaaaaaa^ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa}|
{4:wrapped 2 15}{5:aaaaaaaaaaaaaaaaaaa }|
{1:virtual-1 15}END |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
-- Also test virt_lines when 'cpoptions' includes "n"
@@ -478,19 +510,57 @@ describe('statuscolumn', function()
{0:~ }|
|
]])
+ -- Also test "col_rows" code path for 'relativenumber' cursor movement
+ command([[
+ set cpoptions-=n nocursorline relativenumber
+ set stc=%{v:virtnum<0?'virtual':(!v:virtnum?'buffer':'wrapped')}%=%{'\ '.v:virtnum.'\ '.v:lnum.'\ '.v:relnum}
+ ]])
+ screen:expect([[
+ {1:buffer 0 12 3}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 12 3}aaaaaaaaaaa |
+ {1:buffer 0 13 2}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 13 2}aaaaaaaaaaa |
+ {1:buffer 0 14 1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 14 1}aaaaaaaaaaa |
+ {1:buffer 0 15 0}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 15 0}aaaaaaaaaaa^ aaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 2 15 0}aaaaaaaaaaaaaaaaaaaaaaa |
+ {1:virtual-3 15 0}virt_line1 |
+ {1:virtual-2 15 0}virt_line2 |
+ {1:virtual-1 15 0}END |
+ {0:~ }|
+ |
+ ]])
+ feed('kk')
+ screen:expect([[
+ {1:buffer 0 12 1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 12 1}aaaaaaaaaaa |
+ {1:buffer 0 13 0}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 13 0}aaaaaaaaaa^a |
+ {1:buffer 0 14 1}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 14 1}aaaaaaaaaaa |
+ {1:buffer 0 15 2}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 1 15 2}aaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaa|
+ {1:wrapped 2 15 2}aaaaaaaaaaaaaaaaaaaaaaa |
+ {1:virtual-3 15 2}virt_line1 |
+ {1:virtual-2 15 2}virt_line2 |
+ {1:virtual-1 15 2}END |
+ {0:~ }|
+ |
+ ]])
end)
it('does not corrupt the screen with minwid sign item', function()
screen:try_resize(screen._width, 3)
screen:set_default_attr_ids({
- [0] = {foreground = Screen.colors.Brown},
- [1] = {foreground = Screen.colors.Blue4, background = Screen.colors.Gray},
+ [0] = { foreground = Screen.colors.Brown },
+ [1] = { foreground = Screen.colors.Blue4, background = Screen.colors.Gray },
})
command([[set stc=%6s\ %l]])
exec_lua('vim.api.nvim_buf_set_extmark(0, ns, 7, 0, {sign_text = "ð’€€"})')
screen:expect([[
- {0: ð’€€ 8}^aaaaa |
- {0: }{1: }{0: 9}aaaaa |
+ {0: ð’€€ 8 }^aaaaa |
+ {0: }{1: }{0: 9 }aaaaa |
|
]])
end)
@@ -511,92 +581,85 @@ describe('statuscolumn', function()
end)
it('clicks work with mousemodel=' .. model, function()
- meths.set_option_value('statuscolumn', '%0@MyClickFunc@%=%l%T', {})
- meths.input_mouse('left', 'press', '', 0, 0, 0)
- eq('0 1 l 4', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 0, 0)
- eq('0 2 l 4', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 0, 0)
- eq('0 3 l 4', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 0, 0)
- eq('0 4 l 4', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 3, 0)
- eq('0 1 r 7', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 3, 0)
- eq('0 2 r 7', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 3, 0)
- eq('0 3 r 7', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 3, 0)
- eq('0 4 r 7', eval("g:testvar"))
+ api.nvim_set_option_value('statuscolumn', '%0@MyClickFunc@%=%l%T', {})
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
+ eq('0 1 l 4', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
+ eq('0 2 l 4', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
+ eq('0 3 l 4', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
+ eq('0 4 l 4', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 3, 0)
+ eq('0 1 r 7', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 3, 0)
+ eq('0 2 r 7', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 3, 0)
+ eq('0 3 r 7', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 3, 0)
+ eq('0 4 r 7', eval('g:testvar'))
command('rightbelow vsplit')
- meths.input_mouse('left', 'press', '', 0, 0, 27)
- eq('0 1 l 4', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 3, 27)
- eq('0 1 r 7', eval("g:testvar"))
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 27)
+ eq('0 1 l 4', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 3, 27)
+ eq('0 1 r 7', eval('g:testvar'))
command('setlocal rightleft')
- meths.input_mouse('left', 'press', '', 0, 0, 52)
- eq('0 1 l 4', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 3, 52)
- eq('0 1 r 7', eval("g:testvar"))
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 52)
+ eq('0 1 l 4', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 3, 52)
+ eq('0 1 r 7', eval('g:testvar'))
command('wincmd H')
- meths.input_mouse('left', 'press', '', 0, 0, 25)
- eq('0 1 l 4', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 3, 25)
- eq('0 1 r 7', eval("g:testvar"))
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 25)
+ eq('0 1 l 4', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 3, 25)
+ eq('0 1 r 7', eval('g:testvar'))
command('close')
command('set laststatus=2 winbar=%f')
command('let g:testvar = ""')
-- Check that winbar click doesn't register as statuscolumn click
- meths.input_mouse('right', 'press', '', 0, 0, 0)
- eq('', eval("g:testvar"))
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 0)
+ eq('', eval('g:testvar'))
-- Check that statusline click doesn't register as statuscolumn click
- meths.input_mouse('right', 'press', '', 0, 12, 0)
- eq('', eval("g:testvar"))
+ api.nvim_input_mouse('right', 'press', '', 0, 12, 0)
+ eq('', eval('g:testvar'))
-- Check that cmdline click doesn't register as statuscolumn click
- meths.input_mouse('right', 'press', '', 0, 13, 0)
- eq('', eval("g:testvar"))
+ api.nvim_input_mouse('right', 'press', '', 0, 13, 0)
+ eq('', eval('g:testvar'))
end)
it('clicks and highlights work with control characters', function()
- meths.set_option_value('statuscolumn', '\t%#NonText#\1%0@MyClickFunc@\t\1%T\t%##\1', {})
- screen:expect{grid=[[
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
+ api.nvim_set_option_value('statuscolumn', '\t%#NonText#\1%0@MyClickFunc@\t\1%T\t%##\1', {})
+ screen:expect {
+ grid = [[
+ {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |*4
{1:^I}{0:^A^I^A^I}{1:^A}^aaaaa |
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
- {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |
+ {1:^I}{0:^A^I^A^I}{1:^A}aaaaa |*8
|
- ]], attr_ids={
- [0] = {foreground = Screen.colors.Blue, bold = true}; -- NonText
- [1] = {foreground = Screen.colors.Brown}; -- LineNr
- }}
- meths.input_mouse('right', 'press', '', 0, 4, 3)
- eq('', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 5, 8)
- eq('', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 4)
- eq('0 1 r 10', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 7, 7)
- eq('0 1 l 11', eval("g:testvar"))
+ ]],
+ attr_ids = {
+ [0] = { foreground = Screen.colors.Blue, bold = true }, -- NonText
+ [1] = { foreground = Screen.colors.Brown }, -- LineNr
+ },
+ }
+ api.nvim_input_mouse('right', 'press', '', 0, 4, 3)
+ eq('', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 5, 8)
+ eq('', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 4)
+ eq('0 1 r 10', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 7, 7)
+ eq('0 1 l 11', eval('g:testvar'))
end)
it('popupmenu callback does not drag mouse on close', function()
screen:try_resize(screen._width, 2)
screen:set_default_attr_ids({
- [0] = {foreground = Screen.colors.Brown},
- [1] = {background = Screen.colors.Plum1},
+ [0] = { foreground = Screen.colors.Brown },
+ [1] = { background = Screen.colors.Plum1 },
})
- meths.set_option_value('statuscolumn', '%0@MyClickFunc@%l%T', {})
+ api.nvim_set_option_value('statuscolumn', '%0@MyClickFunc@%l%T', {})
exec([[
function! MyClickFunc(minwid, clicks, button, mods)
let g:testvar = printf("%d %d %s %d", a:minwid, a:clicks, a:button, getmousepos().line)
@@ -605,26 +668,26 @@ describe('statuscolumn', function()
endfunction
]])
-- clicking an item does not drag mouse
- meths.input_mouse('left', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
{0:8 }^aaaaa |
{1: Echo } |
]])
- meths.input_mouse('left', 'press', '', 0, 1, 5)
- meths.input_mouse('left', 'release', '', 0, 1, 5)
+ api.nvim_input_mouse('left', 'press', '', 0, 1, 5)
+ api.nvim_input_mouse('left', 'release', '', 0, 1, 5)
screen:expect([[
{0:8 }^aaaaa |
0 1 l 8 |
]])
command('echo')
-- clicking outside to close the menu does not drag mouse
- meths.input_mouse('left', 'press', '', 0, 0, 0)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
screen:expect([[
{0:8 }^aaaaa |
{1: Echo } |
]])
- meths.input_mouse('left', 'press', '', 0, 0, 10)
- meths.input_mouse('left', 'release', '', 0, 0, 10)
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 10)
+ api.nvim_input_mouse('left', 'release', '', 0, 0, 10)
screen:expect([[
{0:8 }^aaaaa |
|
@@ -661,7 +724,9 @@ describe('statuscolumn', function()
it('works with foldcolumn', function()
-- Fits maximum multibyte foldcolumn #21759
command([[set stc=%C%=%l\ fdc=9 fillchars=foldsep:ð’€€]])
- for _ = 0,8 do command('norm zfjzo') end
+ for _ = 0, 8 do
+ command('norm zfjzo')
+ end
-- 'statuscolumn' is not drawn for `virt_lines_leftcol` lines
exec_lua([[
vim.api.nvim_buf_set_extmark(0, ns, 6, 0, {
@@ -685,7 +750,7 @@ describe('statuscolumn', function()
14 aaaaa |
|
]])
- command('set stc=') -- also for the default fold column
+ command('set stc=') -- also for the default fold column
screen:expect_unchanged()
-- 'statuscolumn' is not too wide with custom (bogus) fold column
command([[set stc=%{foldlevel(v:lnum)>0?repeat('-',foldlevel(v:lnum)):''}%=%l\ ]])
@@ -702,8 +767,7 @@ describe('statuscolumn', function()
---------8 aaaaa |
virt |
---------9 aaaaa |
- ~ |
- ~ |
+ ~ |*2
|
]])
end)
@@ -718,11 +782,7 @@ describe('statuscolumn', function()
[No Name] [+] |
:1set stc=%^l |
:2 |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*5
[Command Line] |
: |
]])
@@ -749,9 +809,7 @@ describe('statuscolumn', function()
screen:expect([[
aaaaa |
^aaaaa |
- aaaaa |
- aaaaa |
- aaaaa |
+ aaaaa |*3
|
]])
-- width correctly estimated with "w_nrwidth_line_count" when setting 'nu'
@@ -766,7 +824,7 @@ describe('statuscolumn', function()
]])
end)
- it("has correct width with custom sign column when (un)placing signs", function()
+ it('has correct width with custom sign column when (un)placing signs', function()
screen:try_resize(screen._width, 3)
exec_lua([[
vim.cmd.norm('gg')
@@ -823,13 +881,13 @@ describe('statuscolumn', function()
2 ssssaaaaa |
|
]])
- exec_lua("vim.api.nvim_buf_del_extmark(0, ns, id1)")
+ exec_lua('vim.api.nvim_buf_del_extmark(0, ns, id1)')
screen:expect([[
1 ^aaaaa |
2 ssaaaaa |
|
]])
- exec_lua("vim.api.nvim_buf_del_extmark(0, ns, id2)")
+ exec_lua('vim.api.nvim_buf_del_extmark(0, ns, id2)')
screen:expect([[
1 ^aaaaa |
2 aaaaa |
@@ -845,7 +903,7 @@ describe('statuscolumn', function()
]])
end)
- it("is only evaluated twice, once to estimate and once to draw", function()
+ it('is only evaluated twice, once to estimate and once to draw', function()
command([[
let g:stcnr = 0
func! Stc()
@@ -869,4 +927,17 @@ describe('statuscolumn', function()
|
]])
end)
+
+ it('line increase properly redraws buffer text with relativenumber #27709', function()
+ screen:try_resize(33, 4)
+ command([[set rnu nuw=3 stc=%l\ ]])
+ command('call setline(1, range(1, 99))')
+ feed('Gyyp')
+ screen:expect([[
+ 98 98 |
+ 99 99 |
+ 100 ^99 |
+ |
+ ]])
+ end)
end)
diff --git a/test/functional/ui/statusline_spec.lua b/test/functional/ui/statusline_spec.lua
index 182e0cdadf..fee4b64d44 100644
--- a/test/functional/ui/statusline_spec.lua
+++ b/test/functional/ui/statusline_spec.lua
@@ -5,14 +5,14 @@ local clear = helpers.clear
local command = helpers.command
local feed = helpers.feed
local eq = helpers.eq
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local exec = helpers.exec
local exec_lua = helpers.exec_lua
local eval = helpers.eval
-local sleep = helpers.sleep
+local sleep = vim.uv.sleep
-local mousemodels = { "extend", "popup", "popup_setpos" }
+local mousemodels = { 'extend', 'popup', 'popup_setpos' }
for _, model in ipairs(mousemodels) do
describe('statusline clicks with mousemodel=' .. model, function()
@@ -22,8 +22,8 @@ for _, model in ipairs(mousemodels) do
clear()
screen = Screen.new(40, 8)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}; -- NonText
- [1] = {bold = true, reverse = true}; -- StatusLine
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, reverse = true }, -- StatusLine
})
screen:attach()
command('set laststatus=2 mousemodel=' .. model)
@@ -39,80 +39,84 @@ for _, model in ipairs(mousemodels) do
end)
it('works', function()
- meths.set_option_value('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
- meths.input_mouse('left', 'press', '', 0, 6, 16)
- eq('', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 29)
- eq('', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 6, 17)
- eq('0 1 l', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 6, 17)
- eq('0 2 l', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 6, 17)
- eq('0 3 l', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 6, 17)
- eq('0 4 l', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 28)
- eq('0 1 r', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 28)
- eq('0 2 r', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 28)
- eq('0 3 r', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 28)
- eq('0 4 r', eval("g:testvar"))
+ api.nvim_set_option_value('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 16)
+ eq('', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 29)
+ eq('', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 17)
+ eq('0 1 l', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 17)
+ eq('0 2 l', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 17)
+ eq('0 3 l', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 17)
+ eq('0 4 l', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 28)
+ eq('0 1 r', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 28)
+ eq('0 2 r', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 28)
+ eq('0 3 r', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 28)
+ eq('0 4 r', eval('g:testvar'))
end)
it('works with control characters and highlight', function()
- meths.set_option_value('statusline', '\t%#NonText#\1%0@MyClickFunc@\t\1%T\t%##\1', {})
- screen:expect{grid=[[
+ api.nvim_set_option_value('statusline', '\t%#NonText#\1%0@MyClickFunc@\t\1%T\t%##\1', {})
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{1:^I}{0:^A^I^A^I}{1:^A }|
|
- ]]}
- meths.input_mouse('right', 'press', '', 0, 6, 3)
- eq('', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 6, 8)
- eq('', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 4)
- eq('0 1 r', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 6, 7)
- eq('0 1 l', eval("g:testvar"))
+ ]],
+ }
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 3)
+ eq('', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 8)
+ eq('', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 4)
+ eq('0 1 r', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 7)
+ eq('0 1 l', eval('g:testvar'))
end)
it('works for winbar', function()
- 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)
- eq('0 1 r', eval("g:testvar"))
+ api.nvim_set_option_value('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 17)
+ eq('0 1 l', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 0, 17)
+ eq('0 1 r', eval('g:testvar'))
end)
it('works for winbar in floating window', function()
- meths.open_win(0, true, { width=30, height=4, relative='editor', row=1, col=5,
- border = "single" })
- meths.set_option_value('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T',
- { scope = 'local' })
- meths.input_mouse('left', 'press', '', 0, 2, 23)
- eq('0 1 l', eval("g:testvar"))
+ api.nvim_open_win(
+ 0,
+ true,
+ { width = 30, height = 4, relative = 'editor', row = 1, col = 5, border = 'single' }
+ )
+ api.nvim_set_option_value(
+ 'winbar',
+ 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T',
+ { scope = 'local' }
+ )
+ api.nvim_input_mouse('left', 'press', '', 0, 2, 23)
+ eq('0 1 l', eval('g:testvar'))
end)
it('works when there are multiple windows', function()
command('split')
- 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)
- eq('0 1 r', eval("g:testvar"))
- meths.input_mouse('middle', 'press', '', 0, 3, 17)
- eq('0 1 m', eval("g:testvar"))
- meths.input_mouse('left', 'press', '', 0, 6, 17)
- eq('0 1 l', eval("g:testvar"))
+ api.nvim_set_option_value('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
+ api.nvim_set_option_value('winbar', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 17)
+ eq('0 1 l', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 4, 17)
+ eq('0 1 r', eval('g:testvar'))
+ api.nvim_input_mouse('middle', 'press', '', 0, 3, 17)
+ eq('0 1 m', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 17)
+ eq('0 1 l', eval('g:testvar'))
end)
it('works with Lua function', function()
@@ -121,101 +125,107 @@ for _, model in ipairs(mousemodels) do
vim.g.testvar = string.format("%d %d %s", minwid, clicks, button)
end
]])
- 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"))
+ api.nvim_set_option_value(
+ 'statusline',
+ 'Not clicky stuff %0@v:lua.clicky_func@Clicky stuff%T',
+ {}
+ )
+ api.nvim_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_value('statusline', '%2TNot clicky stuff%T', {})
- meths.input_mouse('left', 'press', '', 0, 6, 0)
- eq(1, meths.get_current_tabpage().id)
- meths.set_option_value('statusline', '%2XNot clicky stuff%X', {})
- meths.input_mouse('left', 'press', '', 0, 6, 0)
- eq(2, #meths.list_tabpages())
+ api.nvim_set_option_value('statusline', '%2TNot clicky stuff%T', {})
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 0)
+ eq(1, api.nvim_get_current_tabpage())
+ api.nvim_set_option_value('statusline', '%2XNot clicky stuff%X', {})
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 0)
+ eq(2, #api.nvim_list_tabpages())
end)
it("right click works when statusline isn't focused #18994", function()
- 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)
- eq('0 2 r', eval("g:testvar"))
+ api.nvim_set_option_value('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 17)
+ eq('0 1 r', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 17)
+ eq('0 2 r', eval('g:testvar'))
end)
- it("works with modifiers #18994", function()
- meths.set_option_value('statusline', 'Not clicky stuff %0@MyClickFunc@Clicky stuff%T', {})
+ it('works with modifiers #18994', function()
+ api.nvim_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"))
- meths.input_mouse('right', 'press', 'S', 0, 6, 17)
- eq('0 1 r(s )', eval("g:testvar"))
- meths.input_mouse('left', 'press', 'A', 0, 6, 17)
- eq('0 1 l( a )', eval("g:testvar"))
- meths.input_mouse('right', 'press', 'A', 0, 6, 17)
- eq('0 1 r( a )', eval("g:testvar"))
- meths.input_mouse('left', 'press', 'AS', 0, 6, 17)
- eq('0 1 l(s a )', eval("g:testvar"))
- meths.input_mouse('right', 'press', 'AS', 0, 6, 17)
- eq('0 1 r(s a )', eval("g:testvar"))
- meths.input_mouse('left', 'press', 'T', 0, 6, 17)
- eq('0 1 l( m)', eval("g:testvar"))
- meths.input_mouse('right', 'press', 'T', 0, 6, 17)
- eq('0 1 r( m)', eval("g:testvar"))
- meths.input_mouse('left', 'press', 'TS', 0, 6, 17)
- eq('0 1 l(s m)', eval("g:testvar"))
- meths.input_mouse('right', 'press', 'TS', 0, 6, 17)
- eq('0 1 r(s m)', eval("g:testvar"))
- meths.input_mouse('left', 'press', 'C', 0, 6, 17)
- eq('0 1 l( c )', eval("g:testvar"))
+ api.nvim_input_mouse('left', 'press', 'S', 0, 6, 17)
+ eq('0 1 l(s )', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', 'S', 0, 6, 17)
+ eq('0 1 r(s )', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', 'A', 0, 6, 17)
+ eq('0 1 l( a )', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', 'A', 0, 6, 17)
+ eq('0 1 r( a )', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', 'AS', 0, 6, 17)
+ eq('0 1 l(s a )', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', 'AS', 0, 6, 17)
+ eq('0 1 r(s a )', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', 'T', 0, 6, 17)
+ eq('0 1 l( m)', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', 'T', 0, 6, 17)
+ eq('0 1 r( m)', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', 'TS', 0, 6, 17)
+ eq('0 1 l(s m)', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', 'TS', 0, 6, 17)
+ eq('0 1 r(s m)', eval('g:testvar'))
+ api.nvim_input_mouse('left', 'press', 'C', 0, 6, 17)
+ eq('0 1 l( c )', eval('g:testvar'))
-- <C-RightMouse> is for tag jump
end)
- it("works for global statusline with vertical splits #19186", function()
+ it('works for global statusline with vertical splits #19186', function()
command('set laststatus=3')
- meths.set_option_value('statusline', '%0@MyClickFunc@Clicky stuff%T %= %0@MyClickFunc@Clicky stuff%T', {})
+ api.nvim_set_option_value(
+ 'statusline',
+ '%0@MyClickFunc@Clicky stuff%T %= %0@MyClickFunc@Clicky stuff%T',
+ {}
+ )
command('vsplit')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ │ |
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
- {0:~ }│{0:~ }|
+ {0:~ }│{0:~ }|*5
{1:Clicky stuff Clicky stuff}|
|
- ]]}
+ ]],
+ }
-- clickable area on the right
- meths.input_mouse('left', 'press', '', 0, 6, 35)
- eq('0 1 l', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 35)
- eq('0 1 r', eval("g:testvar"))
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 35)
+ eq('0 1 l', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 35)
+ eq('0 1 r', eval('g:testvar'))
-- clickable area on the left
- meths.input_mouse('left', 'press', '', 0, 6, 5)
- eq('0 1 l', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 5)
- eq('0 1 r', eval("g:testvar"))
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 5)
+ eq('0 1 l', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 5)
+ eq('0 1 r', eval('g:testvar'))
end)
it('no memory leak with zero-width click labels', function()
command([[
let &stl = '%@Test@%T%@MyClickFunc@%=%T%@Test@'
]])
- meths.input_mouse('left', 'press', '', 0, 6, 0)
- eq('0 1 l', eval("g:testvar"))
- meths.input_mouse('right', 'press', '', 0, 6, 39)
- eq('0 1 r', eval("g:testvar"))
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 0)
+ eq('0 1 l', eval('g:testvar'))
+ api.nvim_input_mouse('right', 'press', '', 0, 6, 39)
+ eq('0 1 r', eval('g:testvar'))
end)
it('no memory leak with truncated click labels', function()
command([[
let &stl = '%@MyClickFunc@foo%X' .. repeat('a', 40) .. '%<t%@Test@bar%X%@Test@baz'
]])
- meths.input_mouse('left', 'press', '', 0, 6, 2)
- eq('0 1 l', eval("g:testvar"))
+ api.nvim_input_mouse('left', 'press', '', 0, 6, 2)
+ eq('0 1 l', eval('g:testvar'))
end)
end)
end
@@ -228,11 +238,11 @@ describe('global statusline', function()
screen = Screen.new(60, 16)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue};
- [2] = {bold = true, reverse = true};
- [3] = {bold = true};
- [4] = {reverse = true};
- [5] = {bold = true, foreground = Screen.colors.Fuchsia};
+ [1] = { bold = true, foreground = Screen.colors.Blue },
+ [2] = { bold = true, reverse = true },
+ [3] = { bold = true },
+ [4] = { reverse = true },
+ [5] = { bold = true, foreground = Screen.colors.Fuchsia },
})
command('set laststatus=3')
command('set ruler')
@@ -241,39 +251,16 @@ describe('global statusline', function()
it('works', function()
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*13
{2:[No Name] 0,0-1 All}|
|
]])
feed('i<CR><CR>')
screen:expect([[
- |
- |
+ |*2
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*11
{2:[No Name] [+] 3,1 All}|
{3:-- INSERT --} |
]])
@@ -283,9 +270,7 @@ describe('global statusline', function()
command('vsplit | split | vsplit | vsplit | wincmd l | split | 2wincmd l | split')
screen:expect([[
│ │ │^ |
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
+ {1:~ }│{1:~ }│{1:~}│{1:~ }|*3
{1:~ }├────────────────┤{1:~}│{1:~ }|
{1:~ }│ │{1:~}│{1:~ }|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
@@ -293,9 +278,7 @@ describe('global statusline', function()
{1:~ }│{1:~ }│{1:~}│ |
────────────────────┴────────────────┴─┤{1:~ }|
│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*3
{2:[No Name] 0,0-1 All}|
|
]])
@@ -305,39 +288,14 @@ describe('global statusline', function()
command('set laststatus=1')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*14
0,0-1 All |
]])
command('set laststatus=3')
screen:expect([[
^ |
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*13
{2:[No Name] 0,0-1 All}|
|
]])
@@ -346,9 +304,7 @@ describe('global statusline', function()
command('set laststatus=2')
screen:expect([[
│ │ │^ |
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
+ {1:~ }│{1:~ }│{1:~}│{1:~ }|*3
{1:~ }│{4:< Name] 0,0-1 }│{1:~}│{1:~ }|
{1:~ }│ │{1:~}│{1:~ }|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
@@ -356,9 +312,7 @@ describe('global statusline', function()
{1:~ }│{1:~ }│{1:~}│ |
{4:<No Name] 0,0-1 All < Name] 0,0-1 <}│{1:~ }|
│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*3
{4:[No Name] 0,0-1 All <No Name] 0,0-1 All}|
|
]])
@@ -366,9 +320,7 @@ describe('global statusline', function()
command('set laststatus=3')
screen:expect([[
│ │ │^ |
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
+ {1:~ }│{1:~ }│{1:~}│{1:~ }|*3
{1:~ }├────────────────┤{1:~}│{1:~ }|
{1:~ }│ │{1:~}│{1:~ }|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
@@ -376,9 +328,7 @@ describe('global statusline', function()
{1:~ }│{1:~ }│{1:~}│ |
────────────────────┴────────────────┴─┤{1:~ }|
│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*3
{2:[No Name] 0,0-1 All}|
|
]])
@@ -386,9 +336,7 @@ describe('global statusline', function()
command('set laststatus=0')
screen:expect([[
│ │ │^ |
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
+ {1:~ }│{1:~ }│{1:~}│{1:~ }|*3
{1:~ }│{4:< Name] 0,0-1 }│{1:~}│{1:~ }|
{1:~ }│ │{1:~}│{1:~ }|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
@@ -396,19 +344,14 @@ describe('global statusline', function()
{1:~ }│{1:~ }│{1:~}│ |
{4:<No Name] 0,0-1 All < Name] 0,0-1 <}│{1:~ }|
│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*4
0,0-1 All |
]])
command('set laststatus=3')
screen:expect([[
│ │ │^ |
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
- {1:~ }│{1:~ }│{1:~}│{1:~ }|
+ {1:~ }│{1:~ }│{1:~}│{1:~ }|*3
{1:~ }├────────────────┤{1:~}│{1:~ }|
{1:~ }│ │{1:~}│{1:~ }|
{1:~ }│{1:~ }│{1:~}│{1:~ }|
@@ -416,55 +359,49 @@ describe('global statusline', function()
{1:~ }│{1:~ }│{1:~}│ |
────────────────────┴────────────────┴─┤{1:~ }|
│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*3
{2:[No Name] 0,0-1 All}|
|
]])
end)
it('win_move_statusline() can reduce cmdheight to 1', function()
- eq(1, meths.get_option_value('cmdheight', {}))
- funcs.win_move_statusline(0, -1)
- eq(2, meths.get_option_value('cmdheight', {}))
- funcs.win_move_statusline(0, -1)
- eq(3, meths.get_option_value('cmdheight', {}))
- funcs.win_move_statusline(0, 1)
- eq(2, meths.get_option_value('cmdheight', {}))
- funcs.win_move_statusline(0, 1)
- eq(1, meths.get_option_value('cmdheight', {}))
+ eq(1, api.nvim_get_option_value('cmdheight', {}))
+ fn.win_move_statusline(0, -1)
+ eq(2, api.nvim_get_option_value('cmdheight', {}))
+ fn.win_move_statusline(0, -1)
+ eq(3, api.nvim_get_option_value('cmdheight', {}))
+ fn.win_move_statusline(0, 1)
+ eq(2, api.nvim_get_option_value('cmdheight', {}))
+ fn.win_move_statusline(0, 1)
+ eq(1, api.nvim_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_value('cmdheight', {}))
- meths.input_mouse('left', 'drag', '', 0, 13, 10)
- eq(2, meths.get_option_value('cmdheight', {}))
- meths.input_mouse('left', 'drag', '', 0, 12, 10)
- eq(3, meths.get_option_value('cmdheight', {}))
- meths.input_mouse('left', 'drag', '', 0, 13, 10)
- eq(2, meths.get_option_value('cmdheight', {}))
- meths.input_mouse('left', 'drag', '', 0, 14, 10)
- eq(1, meths.get_option_value('cmdheight', {}))
- meths.input_mouse('left', 'drag', '', 0, 15, 10)
- eq(1, meths.get_option_value('cmdheight', {}))
- meths.input_mouse('left', 'drag', '', 0, 14, 10)
- eq(1, meths.get_option_value('cmdheight', {}))
+ api.nvim_input_mouse('left', 'press', '', 0, 14, 10)
+ eq(1, api.nvim_get_option_value('cmdheight', {}))
+ api.nvim_input_mouse('left', 'drag', '', 0, 13, 10)
+ eq(2, api.nvim_get_option_value('cmdheight', {}))
+ api.nvim_input_mouse('left', 'drag', '', 0, 12, 10)
+ eq(3, api.nvim_get_option_value('cmdheight', {}))
+ api.nvim_input_mouse('left', 'drag', '', 0, 13, 10)
+ eq(2, api.nvim_get_option_value('cmdheight', {}))
+ api.nvim_input_mouse('left', 'drag', '', 0, 14, 10)
+ eq(1, api.nvim_get_option_value('cmdheight', {}))
+ api.nvim_input_mouse('left', 'drag', '', 0, 15, 10)
+ eq(1, api.nvim_get_option_value('cmdheight', {}))
+ api.nvim_input_mouse('left', 'drag', '', 0, 14, 10)
+ eq(1, api.nvim_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_value('cmdheight', 1, {})
+ api.nvim_set_option_value('cmdheight', 1, {})
feed('L')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
────────────────────────────────────────────────────────────|
0000;<control>;Cc;0;BN;;;;;N;NULL;;;; |
0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;; |
@@ -479,11 +416,7 @@ describe('global statusline', function()
feed('j')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
────────────────────────────────────────────────────────────|
0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;; |
0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; |
@@ -495,15 +428,11 @@ describe('global statusline', function()
{2:test/functional/fixtures/bigfile.txt 8,1 0%}|
|
]])
- meths.set_option_value('showtabline', 2, {})
+ api.nvim_set_option_value('showtabline', 2, {})
screen:expect([[
{3: }{5:2}{3: t/f/f/bigfile.txt }{4: }|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
────────────────────────────────────────────────────────────|
0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; |
0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; |
@@ -514,15 +443,11 @@ describe('global statusline', function()
{2:test/functional/fixtures/bigfile.txt 8,1 0%}|
|
]])
- meths.set_option_value('cmdheight', 0, {})
+ api.nvim_set_option_value('cmdheight', 0, {})
screen:expect([[
{3: }{5:2}{3: t/f/f/bigfile.txt }{4: }|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
────────────────────────────────────────────────────────────|
0001;<control>;Cc;0;BN;;;;;N;START OF HEADING;;;; |
0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; |
@@ -533,15 +458,11 @@ describe('global statusline', function()
^0007;<control>;Cc;0;BN;;;;;N;BELL;;;; |
{2:test/functional/fixtures/bigfile.txt 8,1 0%}|
]])
- meths.set_option_value('cmdheight', 1, {})
+ api.nvim_set_option_value('cmdheight', 1, {})
screen:expect([[
{3: }{5:2}{3: t/f/f/bigfile.txt }{4: }|
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*5
────────────────────────────────────────────────────────────|
0002;<control>;Cc;0;BN;;;;;N;START OF TEXT;;;; |
0003;<control>;Cc;0;BN;;;;;N;END OF TEXT;;;; |
@@ -557,8 +478,8 @@ end)
it('statusline does not crash if it has Arabic characters #19447', function()
clear()
- meths.set_option_value('statusline', 'غً', {})
- meths.set_option_value('laststatus', 2, {})
+ api.nvim_set_option_value('statusline', 'غً', {})
+ api.nvim_set_option_value('laststatus', 2, {})
command('redraw!')
assert_alive()
end)
@@ -567,8 +488,8 @@ it('statusline is redrawn with :resize from <Cmd> mapping #19629', function()
clear()
local screen = Screen.new(40, 8)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, reverse = true}, -- StatusLine
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, reverse = true }, -- StatusLine
})
screen:attach()
exec([[
@@ -579,22 +500,14 @@ it('statusline is redrawn with :resize from <Cmd> mapping #19629', function()
feed('<Up>')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
{1:[No Name] }|
- |
- |
+ |*2
]])
feed('<Down>')
screen:expect([[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
{1:[No Name] }|
|
]])
@@ -604,9 +517,9 @@ it('showcmdloc=statusline does not show if statusline is too narrow', function()
clear()
local screen = Screen.new(40, 8)
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [1] = {bold = true, reverse = true}, -- StatusLine
- [2] = {reverse = true}, -- StatusLineNC
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { bold = true, reverse = true }, -- StatusLine
+ [2] = { reverse = true }, -- StatusLineNC
})
screen:attach()
command('set showcmd')
@@ -614,11 +527,7 @@ it('showcmdloc=statusline does not show if statusline is too narrow', function()
command('1vsplit')
screen:expect([[
^ │ |
- {0:~}│{0:~ }|
- {0:~}│{0:~ }|
- {0:~}│{0:~ }|
- {0:~}│{0:~ }|
- {0:~}│{0:~ }|
+ {0:~}│{0:~ }|*5
{1:< }{2:[No Name] }|
|
]])
@@ -668,8 +577,7 @@ it('statusline is redrawn on various state changes', function()
screen:expect([[
^ |
~ |
- |
- |
+ |*2
]])
feed('qQ')
screen:expect([[
@@ -682,8 +590,7 @@ it('statusline is redrawn on various state changes', function()
screen:expect([[
^ |
~ |
- |
- |
+ |*2
]])
-- Visual mode change #23932
@@ -741,13 +648,13 @@ it('ruler is redrawn in cmdline with redrawstatus #22804', function()
]])
end)
-it("shows correct ruler in cmdline with no statusline", function()
+it('shows correct ruler in cmdline with no statusline', function()
clear()
local screen = Screen.new(30, 8)
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
- [2] = {bold = true, reverse = true}, -- StatusLine
- [3] = {reverse = true}, -- StatusLineNC
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { bold = true, reverse = true }, -- StatusLine
+ [3] = { reverse = true }, -- StatusLineNC
}
screen:attach()
-- Use long ruler to check 'ruler' with 'rulerformat' set has correct width.
@@ -765,12 +672,10 @@ it("shows correct ruler in cmdline with no statusline", function()
command '1wincmd w'
screen:expect [[
^ |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:[No Name] 1longlonglong }|
│ |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*2
3longlonglong |
]]
-- Window 2 is current. It has no statusline, so cmdline should show its
@@ -778,24 +683,20 @@ it("shows correct ruler in cmdline with no statusline", function()
command '2wincmd w'
screen:expect [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:[No Name] 1longlonglong }|
^ │ |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*2
2longlonglong |
]]
-- Window 3 is current. Cmdline should again show its ruler.
command '3wincmd w'
screen:expect [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:[No Name] 1longlonglong }|
│^ |
- {1:~ }│{1:~ }|
- {1:~ }│{1:~ }|
+ {1:~ }│{1:~ }|*2
3longlonglong |
]]
end)
@@ -805,15 +706,72 @@ it('uses "stl" and "stlnc" fillchars even if they are the same #19803', function
local screen = Screen.new(53, 4)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue}, -- NonText
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
})
command('hi clear StatusLine')
command('hi clear StatusLineNC')
command('vsplit')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ │ |
{1:~ }│{1:~ }|
[No Name] [No Name] |
|
- ]]}
+ ]],
+ }
+end)
+
+it('showcmdloc=statusline works with vertical splits', function()
+ clear()
+ local screen = Screen.new(53, 4)
+ screen:set_default_attr_ids {
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { bold = true, reverse = true }, -- StatusLine
+ [3] = { reverse = true }, -- StatusLineNC
+ }
+ screen:attach()
+ command('rightbelow vsplit')
+ command('set showcmd showcmdloc=statusline')
+ feed('1234')
+ screen:expect([[
+ │^ |
+ {1:~ }│{1:~ }|
+ {3:[No Name] }{2:[No Name] 1234 }|
+ |
+ ]])
+ feed('<Esc>')
+ command('set laststatus=3')
+ feed('1234')
+ screen:expect([[
+ │^ |
+ {1:~ }│{1:~ }|
+ {2:[No Name] 1234 }|
+ |
+ ]])
+end)
+
+it('keymap is shown with vertical splits #27269', function()
+ clear()
+ local screen = Screen.new(53, 4)
+ screen:set_default_attr_ids {
+ [1] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [2] = { bold = true, reverse = true }, -- StatusLine
+ [3] = { reverse = true }, -- StatusLineNC
+ }
+ screen:attach()
+ command('setlocal keymap=dvorak')
+ command('rightbelow vsplit')
+ screen:expect([[
+ │^ |
+ {1:~ }│{1:~ }|
+ {3:[No Name] <en-dv> }{2:[No Name] <en-dv> }|
+ |
+ ]])
+ command('set laststatus=3')
+ screen:expect([[
+ │^ |
+ {1:~ }│{1:~ }|
+ {2:[No Name] <en-dv> }|
+ |
+ ]])
end)
diff --git a/test/functional/ui/syntax_conceal_spec.lua b/test/functional/ui/syntax_conceal_spec.lua
index 1391985823..5afc7dfe6c 100644
--- a/test/functional/ui/syntax_conceal_spec.lua
+++ b/test/functional/ui/syntax_conceal_spec.lua
@@ -11,26 +11,25 @@ describe('Screen', function()
before_each(function()
clear()
- screen = Screen.new(nil,10)
+ screen = Screen.new(nil, 10)
screen:attach()
- screen:set_default_attr_ids( {
- [0] = {bold=true, foreground=Screen.colors.Blue},
- [1] = {foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray},
- [2] = {bold = true, reverse = true},
- [3] = {reverse = true},
- [4] = {bold = true},
- [5] = {background = Screen.colors.Yellow},
- [6] = {background = Screen.colors.LightGrey},
- } )
+ screen:set_default_attr_ids({
+ [0] = { bold = true, foreground = Screen.colors.Blue },
+ [1] = { foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray },
+ [2] = { bold = true, reverse = true },
+ [3] = { reverse = true },
+ [4] = { bold = true },
+ [5] = { background = Screen.colors.Yellow },
+ [6] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey },
+ })
end)
- describe("match and conceal", function()
-
+ describe('match and conceal', function()
before_each(function()
- command("let &conceallevel=1")
+ command('let &conceallevel=1')
end)
- describe("multiple", function()
+ describe('multiple', function()
before_each(function()
insert([[
&&
@@ -43,124 +42,88 @@ describe('Screen', function()
command("syn match dAmpersand '[&][&]' conceal cchar=∧")
end)
- it("double characters.", function()
+ it('double characters.', function()
screen:expect([[
- {1:∧} |
- {1:∧} |
- {1:∧} |
- {1:∧} |
- {1:∧} |
- {1:∧} |
+ {1:∧} |*6
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
it('double characters and move the cursor one line up.', function()
- feed("k")
+ feed('k')
screen:expect([[
- {1:∧} |
- {1:∧} |
- {1:∧} |
- {1:∧} |
- {1:∧} |
+ {1:∧} |*5
^&& |
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
it('double characters and move the cursor to the beginning of the file.', function()
- feed("gg")
+ feed('gg')
screen:expect([[
^&& |
- {1:∧} |
- {1:∧} |
- {1:∧} |
- {1:∧} |
- {1:∧} |
+ {1:∧} |*5
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
it('double characters and move the cursor to the second line in the file.', function()
- feed("ggj")
+ feed('ggj')
screen:expect([[
{1:∧} |
^&& |
- {1:∧} |
- {1:∧} |
- {1:∧} |
- {1:∧} |
+ {1:∧} |*4
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
end)
- it('double characters and then move the cursor to the beginning of the file and back to the end of the file.', function()
- feed("ggG")
- screen:expect([[
- {1:∧} |
- {1:∧} |
- {1:∧} |
- {1:∧} |
- {1:∧} |
- {1:∧} |
+ it(
+ 'double characters and then move the cursor to the beginning of the file and back to the end of the file.',
+ function()
+ feed('ggG')
+ screen:expect([[
+ {1:∧} |*6
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
]])
- end)
+ end
+ )
end) -- multiple
- it("keyword instances in initially in the document.", function()
- feed("2ilambda<cr><ESC>")
- command("let &conceallevel=1")
- command("syn keyword kLambda lambda conceal cchar=λ")
+ it('keyword instances in initially in the document.', function()
+ feed('2ilambda<cr><ESC>')
+ command('let &conceallevel=1')
+ command('syn keyword kLambda lambda conceal cchar=λ')
screen:expect([[
- {1:λ} |
- {1:λ} |
+ {1:λ} |*2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
|
]])
end) -- Keyword
- describe("regions in the document", function()
-
+ describe('regions in the document', function()
before_each(function()
- feed("2")
- insert("<r> a region of text </r>\n")
- command("let &conceallevel=1")
+ feed('2')
+ insert('<r> a region of text </r>\n')
+ command('let &conceallevel=1')
end)
it('initially and conceal it.', function()
command("syn region rText start='<r>' end='</r>' conceal cchar=R")
screen:expect([[
- {1:R} |
- {1:R} |
+ {1:R} |*2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
|
]])
end)
@@ -170,246 +133,183 @@ describe('Screen', function()
-- be replaced with cchar.
command("syn region rText matchgroup=rMatch start='<r>' end='</r>' concealends cchar=-")
screen:expect([[
- {1: } a region of text {1:-} |
- {1: } a region of text {1:-} |
+ {1: } a region of text {1:-} |*2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
|
]])
end)
- it('that are nested and conceal the nested region\'s start and end tags.', function()
- command("syn region rText contains=rText matchgroup=rMatch start='<r>' end='</r>' concealends cchar=-")
- insert("<r> A region with <r> a nested <r> nested region.</r> </r> </r>\n")
+ it("that are nested and conceal the nested region's start and end tags.", function()
+ command(
+ "syn region rText contains=rText matchgroup=rMatch start='<r>' end='</r>' concealends cchar=-"
+ )
+ insert('<r> A region with <r> a nested <r> nested region.</r> </r> </r>\n')
screen:expect([[
- {1: } a region of text {1:-} |
- {1: } a region of text {1:-} |
+ {1: } a region of text {1:-} |*2
{1: } A region with {1: } a nested {1: } nested region.{1:-} |
{1:-} {1:-} |
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end)
end) -- regions in the document
- describe("a region of text", function()
+ describe('a region of text', function()
before_each(function()
- command("syntax conceal on")
- feed("2")
- insert("<r> a region of text </r>\n")
+ command('syntax conceal on')
+ feed('2')
+ insert('<r> a region of text </r>\n')
command("syn region rText start='<r>' end='</r>' cchar=-")
end)
- it("and turn on implicit concealing", function()
+ it('and turn on implicit concealing', function()
screen:expect([[
- {1:-} |
- {1:-} |
+ {1:-} |*2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*6
|
]])
end)
- it("and then turn on, then off, and then back on implicit concealing.", function()
- command("syntax conceal off")
- feed("2")
- insert("<i> italian text </i>\n")
+ it('and then turn on, then off, and then back on implicit concealing.', function()
+ command('syntax conceal off')
+ feed('2')
+ insert('<i> italian text </i>\n')
command("syn region iText start='<i>' end='</i>' cchar=*")
screen:expect([[
- {1:-} |
- {1:-} |
- <i> italian text </i> |
- <i> italian text </i> |
+ {1:-} |*2
+ <i> italian text </i> |*2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
- command("syntax conceal on")
+ command('syntax conceal on')
command("syn region iText start='<i>' end='</i>' cchar=*")
screen:expect([[
- {1:-} |
- {1:-} |
- {1:*} |
- {1:*} |
+ {1:-} |*2
+ {1:*} |*2
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end)
end) -- a region of text (implicit concealing)
- it("cursor position is correct when entering Insert mode with cocu=ni #13916", function()
+ it('cursor position is correct when entering Insert mode with cocu=ni #13916', function()
insert([[foobarfoobarfoobar]])
-- move to end of line
- feed("$")
- command("set concealcursor=ni")
- command("syn match Foo /foobar/ conceal cchar=&")
+ feed('$')
+ command('set concealcursor=ni')
+ command('syn match Foo /foobar/ conceal cchar=&')
screen:expect([[
{1:&&&}^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
|
]])
- feed("i")
+ feed('i')
-- cursor should stay in place, not jump to column 16
screen:expect([[
{1:&&&}^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*8
{4:-- INSERT --} |
]])
end)
end) -- match and conceal
- describe("let the conceal level be", function()
+ describe('let the conceal level be', function()
before_each(function()
- insert("// No Conceal\n")
+ insert('// No Conceal\n')
insert('"Conceal without a cchar"\n')
- insert("+ With cchar\n\n")
+ insert('+ With cchar\n\n')
command("syn match noConceal '^//.*$'")
- command("syn match concealNoCchar '\".\\{-}\"$' conceal")
+ command('syn match concealNoCchar \'".\\{-}"$\' conceal')
command("syn match concealWCchar '^+.\\{-}$' conceal cchar=C")
end)
- it("0. No concealing.", function()
- command("let &conceallevel=0")
+ it('0. No concealing.', function()
+ command('let &conceallevel=0')
screen:expect([[
// No Conceal |
"Conceal without a cchar" |
+ With cchar |
|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end)
- it("1. Conceal using cchar or reference listchars.", function()
- command("let &conceallevel=1")
+ it('1. Conceal using cchar or reference listchars.', function()
+ command('let &conceallevel=1')
screen:expect([[
// No Conceal |
{1: } |
{1:C} |
|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end)
- it("2. Hidden unless cchar is set.", function()
- command("let &conceallevel=2")
+ it('2. Hidden unless cchar is set.', function()
+ command('let &conceallevel=2')
screen:expect([[
// No Conceal |
|
{1:C} |
|
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end)
- it("3. Hide all concealed text.", function()
- command("let &conceallevel=3")
+ it('3. Hide all concealed text.', function()
+ command('let &conceallevel=3')
screen:expect([[
// No Conceal |
- |
- |
- |
+ |*3
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
|
]])
end)
end) -- conceallevel
-
- describe("cursor movement", function()
+ describe('cursor movement', function()
before_each(function()
- command("syn keyword concealy barf conceal cchar=b")
- command("set cole=2")
+ command('syn keyword concealy barf conceal cchar=b')
+ command('set cole=2')
feed('5Ofoo barf bar barf eggs<esc>')
screen:expect([[
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
foo barf bar barf egg^s |
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
-
end)
it('between windows', function()
feed('k')
- command("split")
+ command('split')
screen:expect([[
foo {1:b} bar {1:b} eggs |
foo barf bar barf egg^s |
foo {1:b} bar {1:b} eggs |
|
{2:[No Name] [+] }|
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*3
{3:[No Name] [+] }|
|
]])
feed('<c-w>w')
screen:expect([[
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*3
|
{3:[No Name] [+] }|
foo {1:b} bar {1:b} eggs |
@@ -423,29 +323,20 @@ describe('Screen', function()
it('in insert mode', function()
feed('i')
screen:expect([[
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
foo barf bar barf egg^s |
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{4:-- INSERT --} |
]])
feed('<up>')
screen:expect([[
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*3
foo barf bar barf egg^s |
foo {1:b} bar {1:b} eggs |
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{4:-- INSERT --} |
]])
end)
@@ -455,73 +346,47 @@ describe('Screen', function()
feed('gg')
screen:expect([[
^foo barf bar barf eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
feed('i')
screen:expect([[
^foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{4:-- INSERT --} |
]])
feed('<esc>')
screen:expect([[
^foo barf bar barf eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
feed('v')
screen:expect([[
^foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{4:-- VISUAL --} |
]])
feed('<esc>')
screen:expect([[
^foo barf bar barf eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
-
end)
it('between modes cocu=n', function()
@@ -529,71 +394,45 @@ describe('Screen', function()
feed('gg')
screen:expect([[
^foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
feed('i')
screen:expect([[
^foo barf bar barf eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{4:-- INSERT --} |
]])
feed('<esc>')
screen:expect([[
^foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
-
feed('v')
screen:expect([[
^foo barf bar barf eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
{4:-- VISUAL --} |
]])
feed('<esc>')
screen:expect([[
^foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*4
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
end)
@@ -601,15 +440,10 @@ describe('Screen', function()
it('and open line', function()
feed('o')
screen:expect([[
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*5
^ |
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{4:-- INSERT --} |
]])
end)
@@ -618,15 +452,10 @@ describe('Screen', function()
command('set cocu=i')
feed('o')
screen:expect([[
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*5
^ |
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{4:-- INSERT --} |
]])
end)
@@ -639,12 +468,9 @@ describe('Screen', function()
^foo barf bar barf eggs |
foo {1:b} bar {1:b} eggs x |
foo {1:b} bar {1:b} eggs xy |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
end)
@@ -655,12 +481,9 @@ describe('Screen', function()
foo barf bar barf eggs |
foo {1:b} bar {1:b} eggs x |
foo {1:b} bar {1:b} eggs xy |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
/^ |
]])
@@ -669,12 +492,9 @@ describe('Screen', function()
foo {1:b} bar {1:b} eggs |
foo barf bar barf eggs {3:x} |
foo {1:b} bar {1:b} eggs {5:x}y |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
/x^ |
]])
@@ -683,12 +503,9 @@ describe('Screen', function()
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs x |
foo barf bar barf eggs {3:xy} |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
/xy^ |
]])
@@ -697,12 +514,9 @@ describe('Screen', function()
foo barf bar barf eggs |
foo {1:b} bar {1:b} eggs x |
foo {1:b} bar {1:b} eggs xy |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
/^ |
]])
end)
@@ -717,12 +531,9 @@ describe('Screen', function()
foo barf bar barf eggs |
foo {1:b} bar {1:b} eggs x |
foo {1:b} bar {1:b} eggs xy |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
/^ |
]])
@@ -731,12 +542,9 @@ describe('Screen', function()
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs {3:x} |
foo {1:b} bar {1:b} eggs {5:x}y |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
/x^ |
]])
@@ -745,12 +553,9 @@ describe('Screen', function()
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs x |
foo {1:b} bar {1:b} eggs {3:xy} |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
/xy^ |
]])
@@ -759,12 +564,9 @@ describe('Screen', function()
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs x |
foo {1:b} bar {1:b} eggs xy |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
/^ |
]])
@@ -773,12 +575,9 @@ describe('Screen', function()
^foo barf bar barf eggs |
foo {1:b} bar {1:b} eggs x |
foo {1:b} bar {1:b} eggs xy |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
end)
@@ -789,12 +588,9 @@ describe('Screen', function()
^foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs x |
foo {1:b} bar {1:b} eggs xy |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
@@ -805,12 +601,9 @@ describe('Screen', function()
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs x |
foo {1:b} bar {1:b} eggs xy |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
/^ |
]])
@@ -819,12 +612,9 @@ describe('Screen', function()
foo {1:b} bar {1:b} eggs |
foo barf bar barf eggs {3:x} |
foo {1:b} bar {1:b} eggs {5:x}y |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
/x^ |
]])
@@ -833,12 +623,9 @@ describe('Screen', function()
foo barf bar barf eggs |
foo {1:b} bar {1:b} eggs x |
foo {1:b} bar {1:b} eggs xy |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
/^ |
]])
@@ -847,12 +634,9 @@ describe('Screen', function()
^foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs x |
foo {1:b} bar {1:b} eggs xy |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
]])
end)
@@ -863,44 +647,33 @@ describe('Screen', function()
feed('10Ofoo barf bar barf eggs<esc>')
feed(':3<cr>o a<Esc>ggV')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^f{6:oo }{1:b}{6: bar }{1:b}{6: eggs} |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
a |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*5
{4:-- VISUAL LINE --} |
- ]]}
+ ]],
+ }
feed(string.rep('j', 15))
- screen:expect{grid=[[
- {6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
- {6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
- {6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
- {6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
- {6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
- {6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
- {6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
- {6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
+ screen:expect {
+ grid = [[
+ {6:foo }{1:b}{6: bar }{1:b}{6: eggs} |*8
^f{6:oo }{1:b}{6: bar }{1:b}{6: eggs} |
{4:-- VISUAL LINE --} |
- ]]}
+ ]],
+ }
feed(string.rep('k', 15))
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^f{6:oo }{1:b}{6: bar }{1:b}{6: eggs} |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*2
a |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
- foo {1:b} bar {1:b} eggs |
+ foo {1:b} bar {1:b} eggs |*5
{4:-- VISUAL LINE --} |
- ]]}
+ ]],
+ }
end)
end)
@@ -913,41 +686,37 @@ describe('Screen', function()
bbb
ccc
]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
aaa |
bbb |
ccc |
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
- ]]}
+ ]],
+ }
-- XXX: hack to get notifications, and check only a single line is
-- updated. Could use next_msg() also.
local orig_handle_grid_line = screen._handle_grid_line
local grid_lines = {}
function screen._handle_grid_line(self, grid, row, col, items)
- table.insert(grid_lines, {row, col, items})
+ table.insert(grid_lines, { row, col, items })
orig_handle_grid_line(self, grid, row, col, items)
end
feed('k')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
aaa |
bbb |
^ccc |
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
- ]]}
- eq({{2, 0, {{'c', 0, 3}, {' ', 0, 50}}}, {3, 0, {{' ', 0, 53}}}}, grid_lines)
+ ]],
+ }
+ eq({ { 2, 0, { { 'c', 0, 3 }, { ' ', 0, 50 } } }, { 3, 0, { { ' ', 0, 53 } } } }, grid_lines)
end)
it('K_EVENT should not cause extra redraws with concealcursor #13196', function()
@@ -960,43 +729,39 @@ describe('Screen', function()
bbb
ccc
]])
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
aaa |
bbb |
ccc |
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
- ]]}
+ ]],
+ }
-- XXX: hack to get notifications, and check only a single line is
-- updated. Could use next_msg() also.
local orig_handle_grid_line = screen._handle_grid_line
local grid_lines = {}
function screen._handle_grid_line(self, grid, row, col, items)
- table.insert(grid_lines, {row, col, items})
+ table.insert(grid_lines, { row, col, items })
orig_handle_grid_line(self, grid, row, col, items)
end
feed('k')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
aaa |
bbb |
^ccc |
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*5
|
- ]]}
- eq({{2, 0, {{'c', 0, 3}, {' ', 0, 50}}}}, grid_lines)
+ ]],
+ }
+ eq({ { 2, 0, { { 'c', 0, 3 }, { ' ', 0, 50 } } } }, grid_lines)
grid_lines = {}
- poke_eventloop() -- causes K_EVENT key
+ poke_eventloop() -- causes K_EVENT key
screen:expect_unchanged()
eq({}, grid_lines) -- no redraw was done
end)
@@ -1015,7 +780,8 @@ describe('Screen', function()
command('set nomodified')
command('so')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^3split |
let m matchadd('Conceal', '') |
setl conceallevel2 concealcursornc |
@@ -1026,16 +792,18 @@ describe('Screen', function()
normal gg |
{3:Xcolesearch }|
|
- ]]}
+ ]],
+ }
-- Jump to something that is beyond the bottom of the window,
-- so there's a scroll down.
- feed("/expr<CR>")
+ feed('/expr<CR>')
-- Are the concealed parts of the current line really hidden?
-- Is the window's cursor column properly updated for hidden
-- parts of the current line?
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
setl conceallevel2 concealcursornc |
normal gg |
"{5:^expr} |
@@ -1046,7 +814,8 @@ describe('Screen', function()
normal gg |
{3:Xcolesearch }|
/expr |
- ]]}
+ ]],
+ }
end)
-- oldtest: Test_cursor_column_in_concealed_line_after_leftcol_change()
@@ -1064,18 +833,14 @@ describe('Screen', function()
-- Are the concealed parts of the current line really hidden?
-- Is the window's cursor column properly updated for conceal?
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^c |
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*7
|
- ]]}
+ ]],
+ }
end)
end)
end)
diff --git a/test/functional/ui/tabline_spec.lua b/test/functional/ui/tabline_spec.lua
index befdb7c5d1..1c90b17e57 100644
--- a/test/functional/ui/tabline_spec.lua
+++ b/test/functional/ui/tabline_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, command, eq = helpers.clear, helpers.command, helpers.eq
local insert = helpers.insert
-local meths = helpers.meths
+local api = helpers.api
local assert_alive = helpers.assert_alive
describe('ui/ext_tabline', function()
@@ -12,7 +12,7 @@ describe('ui/ext_tabline', function()
before_each(function()
clear()
screen = Screen.new(25, 5)
- screen:attach({rgb=true, ext_tabline=true})
+ screen:attach({ rgb = true, ext_tabline = true })
function screen:_handle_tabline_update(curtab, tabs, curbuf, buffers)
event_curtab = curtab
event_tabs = tabs
@@ -22,73 +22,77 @@ describe('ui/ext_tabline', function()
end)
it('publishes UI events', function()
- command("tabedit another-tab")
+ command('tabedit another-tab')
local expected_tabs = {
- {tab = { id = 1 }, name = '[No Name]'},
- {tab = { id = 2 }, name = 'another-tab'},
+ { tab = 1, name = '[No Name]' },
+ { tab = 2, name = 'another-tab' },
}
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
- ]], condition=function()
- eq({ id = 2 }, event_curtab)
- eq(expected_tabs, event_tabs)
- end}
+ ]],
+ condition = function()
+ eq(2, event_curtab)
+ eq(expected_tabs, event_tabs)
+ end,
+ }
- command("tabNext")
- screen:expect{grid=[[
+ command('tabNext')
+ screen:expect {
+ grid = [[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
- ]], condition=function()
- eq({ id = 1 }, event_curtab)
- eq(expected_tabs, event_tabs)
- end}
+ ]],
+ condition = function()
+ eq(1, event_curtab)
+ eq(expected_tabs, event_tabs)
+ end,
+ }
end)
it('buffer UI events', function()
- local expected_buffers_initial= {
- {buffer = { id = 1 }, name = '[No Name]'},
+ local expected_buffers_initial = {
+ { buffer = 1, name = '[No Name]' },
}
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
- ]], condition=function()
- eq({ id = 1}, event_curbuf)
- eq(expected_buffers_initial, event_buffers)
- end}
+ ]],
+ condition = function()
+ eq(1, event_curbuf)
+ eq(expected_buffers_initial, event_buffers)
+ end,
+ }
- command("badd another-buffer")
- command("bnext")
+ command('badd another-buffer')
+ command('bnext')
local expected_buffers = {
- {buffer = { id = 1 }, name = '[No Name]'},
- {buffer = { id = 2 }, name = 'another-buffer'},
+ { buffer = 1, name = '[No Name]' },
+ { buffer = 2, name = 'another-buffer' },
}
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
- ]], condition=function()
- eq({ id = 2 }, event_curbuf)
- eq(expected_buffers, event_buffers)
- end}
+ ]],
+ condition = function()
+ eq(2, event_curbuf)
+ eq(expected_buffers, event_buffers)
+ end,
+ }
end)
end)
-describe("tabline", function()
+describe('tabline', function()
local screen
before_each(function()
@@ -96,29 +100,31 @@ describe("tabline", function()
screen = Screen.new(42, 5)
screen:attach()
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}; -- NonText
- [1] = {reverse = true}; -- TabLineFill
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { reverse = true }, -- TabLineFill
})
end)
it('redraws when tabline option is set', function()
command('set tabline=asdf')
command('set showtabline=2')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:asdf }|
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]]}
+ ]],
+ }
command('set tabline=jkl')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:jkl }|
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]]}
+ ]],
+ }
end)
it('click definitions do not leak memory #21765', function()
@@ -132,46 +138,64 @@ describe("tabline", function()
command('tabnew')
insert('tab2')
command('tabprev')
- meths.set_option_value('tabline', '%1Tå£å£%2Ta' .. ('b'):rep(38) .. '%999Xc', {})
- screen:expect{grid=[[
+ api.nvim_set_option_value('tabline', '%1Tå£å£%2Ta' .. ('b'):rep(38) .. '%999Xc', {})
+ screen:expect {
+ grid = [[
{1:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }|
tab^1 |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]]}
+ ]],
+ }
assert_alive()
- meths.input_mouse('left', 'press', '', 0, 0, 1)
- screen:expect{grid=[[
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 1)
+ screen:expect {
+ grid = [[
{1:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }|
tab^2 |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]]}
- meths.input_mouse('left', 'press', '', 0, 0, 0)
- screen:expect{grid=[[
+ ]],
+ }
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 0)
+ screen:expect {
+ grid = [[
{1:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }|
tab^1 |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]]}
- meths.input_mouse('left', 'press', '', 0, 0, 39)
- screen:expect{grid=[[
+ ]],
+ }
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 39)
+ screen:expect {
+ grid = [[
{1:<abbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbc }|
tab^2 |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
|
- ]]}
- meths.input_mouse('left', 'press', '', 0, 0, 40)
- screen:expect{grid=[[
+ ]],
+ }
+ api.nvim_input_mouse('left', 'press', '', 0, 0, 40)
+ screen:expect {
+ grid = [[
tab^1 |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
- ]]}
+ ]],
+ }
+ end)
+
+ it('middle-click closes tab', function()
+ command('tabnew')
+ command('tabnew')
+ command('tabnew')
+ command('tabprev')
+ eq({ 3, 4 }, api.nvim_eval('[tabpagenr(), tabpagenr("$")]'))
+ api.nvim_input_mouse('middle', 'press', '', 0, 0, 1)
+ eq({ 2, 3 }, api.nvim_eval('[tabpagenr(), tabpagenr("$")]'))
+ api.nvim_input_mouse('middle', 'press', '', 0, 0, 20)
+ eq({ 2, 2 }, api.nvim_eval('[tabpagenr(), tabpagenr("$")]'))
+ api.nvim_input_mouse('middle', 'press', '', 0, 0, 1)
+ eq({ 1, 1 }, api.nvim_eval('[tabpagenr(), tabpagenr("$")]'))
end)
end)
diff --git a/test/functional/ui/title_spec.lua b/test/functional/ui/title_spec.lua
index 66c0ff5c9c..8060d3a460 100644
--- a/test/functional/ui/title_spec.lua
+++ b/test/functional/ui/title_spec.lua
@@ -2,12 +2,12 @@ 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 curwin = helpers.api.nvim_get_current_win
local eq = helpers.eq
local exec_lua = helpers.exec_lua
local feed = helpers.feed
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local is_os = helpers.is_os
describe('title', function()
@@ -43,13 +43,13 @@ describe('title', function()
local buf2
before_each(function()
- command('edit '..file1)
- buf2 = funcs.bufadd(file2)
+ command('edit ' .. file1)
+ buf2 = fn.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>]])
+ command([[inoremap <F2> <C-R>=setbufvar(]] .. buf2 .. [[, '&autoindent', 1) ?? ''<CR>]])
feed('i<F2><Esc>')
command('redraw!')
screen:expect(function()
@@ -58,7 +58,7 @@ describe('title', function()
end)
it('an RPC call to nvim_set_option_value in a hidden buffer', function()
- meths.set_option_value('autoindent', true, { buf = buf2 })
+ api.nvim_set_option_value('autoindent', true, { buf = buf2 })
command('redraw!')
screen:expect(function()
eq(expected, screen.title)
@@ -66,11 +66,14 @@ describe('title', function()
end)
it('a Lua callback calling nvim_set_option_value in a hidden buffer', function()
- exec_lua(string.format([[
+ exec_lua(string.format(
+ [[
vim.schedule(function()
vim.api.nvim_set_option_value('autoindent', true, { buf = %d })
end)
- ]], buf2))
+ ]],
+ buf2
+ ))
command('redraw!')
screen:expect(function()
eq(expected, screen.title)
@@ -78,11 +81,14 @@ describe('title', function()
end)
it('a Lua callback calling nvim_buf_call in a hidden buffer', function()
- exec_lua(string.format([[
+ exec_lua(string.format(
+ [[
vim.schedule(function()
vim.api.nvim_buf_call(%d, function() end)
end)
- ]], buf2))
+ ]],
+ buf2
+ ))
command('redraw!')
screen:expect(function()
eq(expected, screen.title)
@@ -90,9 +96,9 @@ describe('title', function()
end)
it('setting the buffer of another window using RPC', function()
- local oldwin = curwin().id
+ local oldwin = curwin()
command('split')
- meths.win_set_buf(oldwin, buf2)
+ api.nvim_win_set_buf(oldwin, buf2)
command('redraw!')
screen:expect(function()
eq(expected, screen.title)
@@ -100,13 +106,17 @@ describe('title', function()
end)
it('setting the buffer of another window using Lua callback', function()
- local oldwin = curwin().id
+ local oldwin = curwin()
command('split')
- exec_lua(string.format([[
+ exec_lua(string.format(
+ [[
vim.schedule(function()
vim.api.nvim_win_set_buf(%d, %d)
end)
- ]], oldwin, buf2))
+ ]],
+ oldwin,
+ buf2
+ ))
command('redraw!')
screen:expect(function()
eq(expected, screen.title)
@@ -114,8 +124,12 @@ describe('title', function()
end)
it('creating a floating window using RPC', function()
- meths.open_win(buf2, false, {
- relative = 'editor', width = 5, height = 5, row = 0, col = 0,
+ api.nvim_open_win(buf2, false, {
+ relative = 'editor',
+ width = 5,
+ height = 5,
+ row = 0,
+ col = 0,
})
command('redraw!')
screen:expect(function()
@@ -124,11 +138,14 @@ describe('title', function()
end)
it('creating a floating window using Lua callback', function()
- exec_lua(string.format([[
+ exec_lua(string.format(
+ [[
vim.api.nvim_open_win(%d, false, {
relative = 'editor', width = 5, height = 5, row = 0, col = 0,
})
- ]], buf2))
+ ]],
+ buf2
+ ))
command('redraw!')
screen:expect(function()
eq(expected, screen.title)
diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua
index 3201135b67..667dd64d62 100644
--- a/test/functional/ui/wildmode_spec.lua
+++ b/test/functional/ui/wildmode_spec.lua
@@ -1,8 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, feed, command = helpers.clear, helpers.feed, helpers.command
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local eq = helpers.eq
local eval = helpers.eval
local retry = helpers.retry
@@ -20,97 +20,99 @@ describe("'wildmenu'", function()
-- oldtest: Test_wildmenu_screendump()
it('works', function()
screen:set_default_attr_ids({
- [0] = {bold = true, foreground = Screen.colors.Blue}; -- NonText
- [1] = {foreground = Screen.colors.Black, background = Screen.colors.Yellow}; -- WildMenu
- [2] = {bold = true, reverse = true}; -- StatusLine
+ [0] = { bold = true, foreground = Screen.colors.Blue }, -- NonText
+ [1] = { foreground = Screen.colors.Black, background = Screen.colors.Yellow }, -- WildMenu
+ [2] = { bold = true, reverse = true }, -- StatusLine
})
-- Test simple wildmenu
feed(':sign <Tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1:define}{2: jump list > }|
:sign define^ |
- ]]}
+ ]],
+ }
feed('<Tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:define }{1:jump}{2: list > }|
:sign jump^ |
- ]]}
+ ]],
+ }
feed('<Tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:define jump }{1:list}{2: > }|
:sign list^ |
- ]]}
+ ]],
+ }
-- Looped back to the original value
feed('<Tab><Tab><Tab><Tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:define jump list > }|
:sign ^ |
- ]]}
+ ]],
+ }
-- Test that the wild menu is cleared properly
feed('<Space>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
:sign ^ |
- ]]}
+ ]],
+ }
-- Test that a different wildchar still works
feed('<Esc>')
command('set wildchar=<Esc>')
feed(':sign <Esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{1:define}{2: jump list > }|
:sign define^ |
- ]]}
+ ]],
+ }
-- Double-<Esc> is a hard-coded method to escape while wildchar=<Esc>. Make
-- sure clean up is properly done in edge case like this.
feed('<Esc>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*3
|
- ]]}
+ ]],
+ }
end)
it('C-E to cancel wildmenu completion restore original input', function()
feed(':sign <tab>')
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
define jump list > |
:sign define^ |
]])
feed('<C-E>')
screen:expect([[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
:sign ^ |
]])
end)
@@ -119,17 +121,14 @@ describe("'wildmenu'", function()
feed(':sign <tab>')
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
define jump list > |
:sign define^ |
]])
feed('<tab><C-Y>')
screen:expect([[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
:sign jump^ |
]])
end)
@@ -139,8 +138,7 @@ describe("'wildmenu'", function()
feed(':sign <tab>')
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
define jump list > |
:sign define^ |
]])
@@ -154,16 +152,14 @@ describe("'wildmenu'", function()
feed(':sign <tab>')
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
define jump list > |
:sign define^ |
]])
feed('<space>')
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
[No Name] |
:sign define ^ |
]])
@@ -174,8 +170,7 @@ describe("'wildmenu'", function()
feed(':j<Tab><Tab><Tab>')
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
join jumps |
:j^ |
]])
@@ -183,8 +178,7 @@ describe("'wildmenu'", function()
feed('<BS><Tab>')
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
! # & < = > @ > |
:!^ |
]])
@@ -194,52 +188,51 @@ describe("'wildmenu'", function()
command('set wildmenu wildmode=full')
command('set scrollback=4')
feed((':terminal "%s" REP 5000 !terminal_output!<cr>'):format(testprg('shell-test')))
- feed('G') -- Follow :terminal output.
- feed([[:sign <Tab>]]) -- Invoke wildmenu.
+ feed('G') -- Follow :terminal output.
+ feed([[:sign <Tab>]]) -- Invoke wildmenu.
-- NB: in earlier versions terminal output was redrawn during cmdline mode.
-- For now just assert that the screen remains unchanged.
- screen:expect{any='define jump list > |\n:sign define^ |'}
+ screen:expect { any = 'define jump list > |\n:sign define^ |' }
screen:expect_unchanged()
-- cmdline CTRL-D display should also be preserved.
feed([[<C-U>]])
- feed([[sign <C-D>]]) -- Invoke cmdline CTRL-D.
- screen:expect{grid=[[
+ feed([[sign <C-D>]]) -- Invoke cmdline CTRL-D.
+ screen:expect {
+ grid = [[
:sign |
define place |
jump undefine |
list unplace |
:sign ^ |
- ]]}
+ ]],
+ }
screen:expect_unchanged()
-- Exiting cmdline should show the buffer.
feed([[<C-\><C-N>]])
- screen:expect{any=[[!terminal_output!]]}
+ screen:expect { any = [[!terminal_output!]] }
end)
it('ignores :redrawstatus called from a timer #7108', function()
command('set wildmenu wildmode=full')
command([[call timer_start(10, {->execute('redrawstatus')}, {'repeat':-1})]])
feed([[<C-\><C-N>]])
- feed([[:sign <Tab>]]) -- Invoke wildmenu.
- screen:expect{grid=[[
+ feed([[:sign <Tab>]]) -- Invoke wildmenu.
+ screen:expect {
+ grid = [[
|
- ~ |
- ~ |
+ ~ |*2
define jump list > |
:sign define^ |
- ]]}
+ ]],
+ }
screen:expect_unchanged()
end)
it('with laststatus=0, :vsplit, :term #2255', function()
- -- Because this test verifies a _lack_ of activity after screen:sleep(), we
- -- must wait the full timeout. So make it reasonable.
- screen.timeout = 1000
-
if not is_os('win') then
- command('set shell=sh') -- Need a predictable "$" prompt.
+ command('set shell=sh') -- Need a predictable "$" prompt.
command('let $PS1 = "$"')
end
command('set laststatus=0')
@@ -256,11 +249,13 @@ describe("'wildmenu'", function()
end)
feed([[<C-\><C-N>]])
- feed([[:<Tab>]]) -- Invoke wildmenu.
+ feed([[:<Tab>]]) -- Invoke wildmenu.
-- Check only the last 2 lines, because the shell output is
-- system-dependent.
- screen:expect{any='! # & < = > @ > |\n:!^'}
- screen:expect_unchanged()
+ screen:expect { any = '! # & < = > @ > |\n:!^' }
+ -- Because this test verifies a _lack_ of activity, we must wait the full timeout.
+ -- So make it reasonable.
+ screen:expect_unchanged(false, 1000)
end)
it('wildmode=list,full and messages interaction #10092', function()
@@ -282,21 +277,16 @@ describe("'wildmenu'", function()
feed('<tab>') -- trigger wildmode full
screen:expect([[
[No Name] |
- |
- |
+ |*2
:set wildm |
- wildmenu wildmode |
- wildmenu wildmode |
+ wildmenu wildmode |*2
:set wildmenu^ |
]])
feed('<Esc>')
screen:expect([[
[No Name] |
^ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
|
]])
end)
@@ -311,18 +301,13 @@ describe("'wildmenu'", function()
feed(':sign u<tab>')
screen:expect([[
|
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*5
:sign un^ |
]])
feed('<tab>') -- trigger wildmode list
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
|
:sign un |
undefine unplace |
@@ -331,11 +316,7 @@ describe("'wildmenu'", function()
feed('<Esc>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*5
|
]])
@@ -343,8 +324,7 @@ describe("'wildmenu'", function()
feed(':sign un<tab>')
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
|
:sign un |
undefine unplace |
@@ -355,11 +335,7 @@ describe("'wildmenu'", function()
feed('<Esc>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*5
|
]])
end)
@@ -372,8 +348,7 @@ describe("'wildmenu'", function()
feed(':sign u<tab>')
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
|
:sign u |
undefine unplace |
@@ -382,8 +357,7 @@ describe("'wildmenu'", function()
feed('<tab>') -- trigger wildmode longest
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
|
:sign u |
undefine unplace |
@@ -392,11 +366,7 @@ describe("'wildmenu'", function()
feed('<Esc>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*5
|
]])
end)
@@ -409,8 +379,7 @@ describe("'wildmenu'", function()
feed('<c-d>')
screen:expect([[
|
- ~ |
- ~ |
+ ~ |*2
|
:set wildm |
wildmenu wildmode |
@@ -418,8 +387,7 @@ describe("'wildmenu'", function()
]])
feed('<c-d>')
screen:expect([[
- |
- |
+ |*2
:set wildm |
wildmenu wildmode |
:set wildm |
@@ -429,10 +397,7 @@ describe("'wildmenu'", function()
feed('<Esc>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
[No Name] |
|
]])
@@ -440,28 +405,29 @@ describe("'wildmenu'", function()
it('works with c_CTRL_Z standard mapping', function()
screen:set_default_attr_ids {
- [1] = {bold = true, foreground = Screen.colors.Blue1};
- [2] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow};
- [3] = {bold = true, reverse = true};
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey0, background = Screen.colors.Yellow },
+ [3] = { bold = true, reverse = true },
}
-- Wildcharm? where we are going we aint't no need no wildcharm.
- eq(0, meths.get_option_value('wildcharm', {}))
+ eq(0, api.nvim_get_option_value('wildcharm', {}))
-- Don't mess the defaults yet (neovim is about backwards compatibility)
- eq(9, meths.get_option_value('wildchar', {}))
+ eq(9, api.nvim_get_option_value('wildchar', {}))
-- Lol what is cnoremap? Some say it can define mappings.
command 'set wildchar=0'
- eq(0, meths.get_option_value('wildchar', {}))
+ eq(0, api.nvim_get_option_value('wildchar', {}))
command 'cnoremap <f2> <c-z>'
feed(':syntax <f2>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:case}{3: clear cluster > }|
:syntax case^ |
- ]]}
+ ]],
+ }
feed '<esc>'
command 'set wildmode=longest:full,full'
@@ -469,31 +435,32 @@ describe("'wildmenu'", function()
command [[cnoremap <expr> <tab> luaeval("not rawset(_G, 'coin', not coin).coin") ? "<c-z>" : "c"]]
feed ':syntax <tab>'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
:syntax c^ |
- ]]}
+ ]],
+ }
feed '<tab>'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{3:case clear cluster > }|
:syntax c^ |
- ]]}
+ ]],
+ }
feed '<tab>'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
:syntax cc^ |
- ]]}
+ ]],
+ }
end)
end)
@@ -503,9 +470,9 @@ describe('command line completion', function()
clear()
screen = Screen.new(40, 5)
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {foreground = Screen.colors.Grey0, background = Screen.colors.Yellow},
- [3] = {bold = true, reverse = true},
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { foreground = Screen.colors.Grey0, background = Screen.colors.Yellow },
+ [3] = { bold = true, reverse = true },
})
screen:attach()
end)
@@ -514,17 +481,15 @@ describe('command line completion', function()
end)
it('lists directories with empty PATH', function()
- local tmp = funcs.tempname()
- command('e '.. tmp)
+ local tmp = fn.tempname()
+ command('e ' .. tmp)
command('cd %:h')
command("call mkdir('Xtest-functional-viml-compl-dir')")
command('let $PATH=""')
feed(':!<tab><bs>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
:!Xtest-functional-viml-compl-dir^ |
]])
end)
@@ -535,71 +500,63 @@ describe('command line completion', function()
feed(':!echo $XTEST_<tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:XTEST_1}{3: XTEST_2 }|
:!echo $XTEST_1^ |
]])
end)
it('completes (multibyte) env var names #9655', function()
- clear({env={
- ['XTEST_1Aaã‚B']='foo',
- ['XTEST_2']='bar',
- }})
+ clear({ env = {
+ ['XTEST_1Aaã‚B'] = 'foo',
+ ['XTEST_2'] = 'bar',
+ } })
screen:attach()
command('set wildmenu wildmode=full')
feed(':!echo $XTEST_<tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2:XTEST_1Aaã‚B}{3: XTEST_2 }|
:!echo $XTEST_1Aaã‚B^ |
]])
end)
it('does not leak memory with <S-Tab> with wildmenu and only one match #19874', function()
- meths.set_option_value('wildmenu', true, {})
- meths.set_option_value('wildmode', 'full', {})
- meths.set_option_value('wildoptions', 'pum', {})
+ api.nvim_set_option_value('wildmenu', true, {})
+ api.nvim_set_option_value('wildmode', 'full', {})
+ api.nvim_set_option_value('wildoptions', 'pum', {})
feed(':sign unpla<S-Tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
:sign unplace^ |
]])
feed('<Space>buff<Tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
:sign unplace buffer=^ |
]])
end)
it('does not show matches with <S-Tab> without wildmenu with wildmode=full', function()
- meths.set_option_value('wildmenu', false, {})
- meths.set_option_value('wildmode', 'full', {})
+ api.nvim_set_option_value('wildmenu', false, {})
+ api.nvim_set_option_value('wildmode', 'full', {})
feed(':sign <S-Tab>')
screen:expect([[
|
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
:sign unplace^ |
]])
end)
it('shows matches with <S-Tab> without wildmenu with wildmode=list', function()
- meths.set_option_value('wildmenu', false, {})
- meths.set_option_value('wildmode', 'list', {})
+ api.nvim_set_option_value('wildmenu', false, {})
+ api.nvim_set_option_value('wildmode', 'list', {})
feed(':sign <S-Tab>')
screen:expect([[
@@ -618,64 +575,72 @@ describe('ui/ext_wildmenu', function()
before_each(function()
clear()
screen = Screen.new(25, 5)
- screen:attach({rgb=true, ext_wildmenu=true})
+ screen:attach({ rgb = true, ext_wildmenu = true })
end)
it('works with :sign <tab>', function()
local expected = {
- 'define',
- 'jump',
- 'list',
- 'place',
- 'undefine',
- 'unplace',
+ 'define',
+ 'jump',
+ 'list',
+ 'place',
+ 'undefine',
+ 'unplace',
}
command('set wildmode=full')
command('set wildmenu')
feed(':sign <tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
:sign define^ |
- ]], wildmenu_items=expected, wildmenu_pos=0}
+ ]],
+ wildmenu_items = expected,
+ wildmenu_pos = 0,
+ }
feed('<tab>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
:sign jump^ |
- ]], wildmenu_items=expected, wildmenu_pos=1}
+ ]],
+ wildmenu_items = expected,
+ wildmenu_pos = 1,
+ }
feed('<left><left>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
:sign ^ |
- ]], wildmenu_items=expected, wildmenu_pos=-1}
+ ]],
+ wildmenu_items = expected,
+ wildmenu_pos = -1,
+ }
feed('<right>')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
:sign define^ |
- ]], wildmenu_items=expected, wildmenu_pos=0}
+ ]],
+ wildmenu_items = expected,
+ wildmenu_pos = 0,
+ }
feed('a')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- ~ |
- ~ |
- ~ |
+ ~ |*3
:sign definea^ |
- ]]}
+ ]],
+ }
end)
end)
diff --git a/test/functional/ui/winbar_spec.lua b/test/functional/ui/winbar_spec.lua
index 78bbcd3a63..c2a52c0f21 100644
--- a/test/functional/ui/winbar_spec.lua
+++ b/test/functional/ui/winbar_spec.lua
@@ -3,12 +3,11 @@ local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local command = helpers.command
local insert = helpers.insert
-local meths = helpers.meths
+local api = helpers.api
local eq = helpers.eq
local poke_eventloop = helpers.poke_eventloop
local feed = helpers.feed
-local funcs = helpers.funcs
-local curwin = helpers.curwin
+local fn = helpers.fn
local pcall_err = helpers.pcall_err
describe('winbar', function()
@@ -19,59 +18,50 @@ describe('winbar', function()
screen = Screen.new(60, 13)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true},
- [2] = {reverse = true},
- [3] = {bold = true, foreground = Screen.colors.Blue},
- [4] = {bold = true, reverse = true},
- [5] = {bold = true, foreground = Screen.colors.Red},
- [6] = {foreground = Screen.colors.Blue},
- [7] = {background = Screen.colors.LightGrey},
- [8] = {background = Screen.colors.LightMagenta},
- [9] = {bold = true, foreground = Screen.colors.Blue, background = Screen.colors.LightMagenta},
- [10] = {background = Screen.colors.LightGrey, underline = true},
- [11] = {background = Screen.colors.LightGrey, underline = true, bold = true, foreground = Screen.colors.Magenta},
+ [1] = { bold = true },
+ [2] = { reverse = true },
+ [3] = { bold = true, foreground = Screen.colors.Blue },
+ [4] = { bold = true, reverse = true },
+ [5] = { bold = true, foreground = Screen.colors.Red },
+ [6] = { foreground = Screen.colors.Blue },
+ [7] = { foreground = Screen.colors.Black, background = Screen.colors.LightGrey },
+ [8] = { background = Screen.colors.LightMagenta },
+ [9] = {
+ bold = true,
+ foreground = Screen.colors.Blue,
+ background = Screen.colors.LightMagenta,
+ },
+ [10] = { background = Screen.colors.LightGrey, underline = true },
+ [11] = {
+ background = Screen.colors.LightGrey,
+ underline = true,
+ bold = true,
+ foreground = Screen.colors.Magenta,
+ },
})
- meths.set_option_value('winbar', 'Set Up The Bars', {})
+ api.nvim_set_option_value('winbar', 'Set Up The Bars', {})
end)
it('works', function()
screen:expect([[
{1:Set Up The Bars }|
^ |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*10
|
]])
-- winbar is excluded from the heights returned by winheight() and getwininfo()
- eq(11, funcs.winheight(0))
- local win_info = funcs.getwininfo(curwin().id)[1]
+ eq(11, fn.winheight(0))
+ local win_info = fn.getwininfo(api.nvim_get_current_win())[1]
eq(11, win_info.height)
eq(1, win_info.winbar)
end)
- it('works with custom \'fillchars\' value', function()
+ it("works with custom 'fillchars' value", function()
command('set fillchars=wbr:+')
screen:expect([[
{1:Set Up The Bars+++++++++++++++++++++++++++++++++++++++++++++}|
^ |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*10
|
]])
end)
@@ -81,16 +71,7 @@ describe('winbar', function()
screen:expect([[
{5:Set Up The Bars }|
^ |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*10
|
]])
end)
@@ -151,20 +132,17 @@ describe('winbar', function()
]])
end)
- it('works when switching value of \'winbar\'', function()
+ it("works when switching value of 'winbar'", function()
command('belowright vsplit | split | split | set winbar=')
screen:expect([[
│^ |
- {3:~ }│{3:~ }|
- {3:~ }│{3:~ }|
+ {3:~ }│{3:~ }|*2
{3:~ }│{4:[No Name] }|
{3:~ }│ |
- {3:~ }│{3:~ }|
- {3:~ }│{3:~ }|
+ {3:~ }│{3:~ }|*2
{3:~ }│{2:[No Name] }|
{3:~ }│ |
- {3:~ }│{3:~ }|
- {3:~ }│{3:~ }|
+ {3:~ }│{3:~ }|*2
{2:[No Name] [No Name] }|
|
]])
@@ -206,54 +184,36 @@ describe('winbar', function()
insert [[
just some
random text]]
- meths.set_option_value('winbar', 'Hello, I am a ruler: %l,%c', {})
- screen:expect{grid=[[
+ api.nvim_set_option_value('winbar', 'Hello, I am a ruler: %l,%c', {})
+ screen:expect {
+ grid = [[
{1:Hello, I am a ruler: 2,11 }|
just some |
random tex^t |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*9
|
- ]]}
+ ]],
+ }
feed 'b'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:Hello, I am a ruler: 2,8 }|
just some |
random ^text |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*9
|
- ]]}
+ ]],
+ }
feed 'k'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:Hello, I am a ruler: 1,8 }|
just so^me |
random text |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*9
|
- ]]}
+ ]],
+ }
end)
it('works with laststatus=3', function()
@@ -261,15 +221,7 @@ describe('winbar', function()
screen:expect([[
{1:Set Up The Bars }|
^ |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*9
{4:[No Name] }|
|
]])
@@ -295,14 +247,7 @@ describe('winbar', function()
{10: }{11:4}{10: [No Name] }{1: [No Name] }{2: }{10:X}|
{1:Set Up The Bars }|
^ |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*8
{4:[No Name] }|
|
]])
@@ -319,7 +264,7 @@ describe('winbar', function()
line sin(theta)
line 8]])
- meths.input_mouse('left', 'press', '', 0, 5, 1)
+ api.nvim_input_mouse('left', 'press', '', 0, 5, 1)
screen:expect([[
{1:Set Up The Bars }|
line 1 |
@@ -330,14 +275,12 @@ describe('winbar', function()
line i |
line sin(theta) |
line 8 |
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*3
|
]])
- eq({5, 1}, meths.win_get_cursor(0))
+ eq({ 5, 1 }, api.nvim_win_get_cursor(0))
- meths.input_mouse('left', 'drag', '', 0, 6, 2)
+ api.nvim_input_mouse('left', 'drag', '', 0, 6, 2)
screen:expect([[
{1:Set Up The Bars }|
line 1 |
@@ -348,14 +291,12 @@ describe('winbar', function()
{7:li}^ne i |
line sin(theta) |
line 8 |
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*3
{1:-- VISUAL --} |
]])
- eq({6, 2}, meths.win_get_cursor(0))
+ eq({ 6, 2 }, api.nvim_win_get_cursor(0))
- meths.input_mouse('left', 'drag', '', 0, 1, 2)
+ api.nvim_input_mouse('left', 'drag', '', 0, 1, 2)
screen:expect([[
{1:Set Up The Bars }|
li^n{7:e 1} |
@@ -366,16 +307,14 @@ describe('winbar', function()
line i |
line sin(theta) |
line 8 |
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*3
{1:-- VISUAL --} |
]])
- eq({1, 2}, meths.win_get_cursor(0))
+ eq({ 1, 2 }, api.nvim_win_get_cursor(0))
- meths.input_mouse('left', 'drag', '', 0, 0, 2)
+ api.nvim_input_mouse('left', 'drag', '', 0, 0, 2)
screen:expect_unchanged()
- eq({1, 2}, meths.win_get_cursor(0))
+ eq({ 1, 2 }, api.nvim_win_get_cursor(0))
end)
it('dragging statusline with mouse works correctly', function()
@@ -383,92 +322,72 @@ describe('winbar', function()
screen:expect([[
{1:Set Up The Bars }|
^ |
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*3
{4:[No Name] }|
{1:Set Up The Bars }|
|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*3
{2:[No Name] }|
|
]])
- meths.input_mouse('left', 'press', '', 1, 5, 10)
+ api.nvim_input_mouse('left', 'press', '', 1, 5, 10)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 1, 6, 10)
+ api.nvim_input_mouse('left', 'drag', '', 1, 6, 10)
screen:expect([[
{1:Set Up The Bars }|
^ |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*4
{4:[No Name] }|
{1:Set Up The Bars }|
|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*2
{2:[No Name] }|
|
]])
- meths.input_mouse('left', 'drag', '', 1, 4, 10)
+ api.nvim_input_mouse('left', 'drag', '', 1, 4, 10)
screen:expect([[
{1:Set Up The Bars }|
^ |
- {3:~ }|
- {3:~ }|
+ {3:~ }|*2
{4:[No Name] }|
{1:Set Up The Bars }|
|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*4
{2:[No Name] }|
|
]])
- meths.input_mouse('left', 'press', '', 1, 11, 10)
+ api.nvim_input_mouse('left', 'press', '', 1, 11, 10)
poke_eventloop()
- meths.input_mouse('left', 'drag', '', 1, 9, 10)
+ api.nvim_input_mouse('left', 'drag', '', 1, 9, 10)
screen:expect([[
{1:Set Up The Bars }|
^ |
- {3:~ }|
- {3:~ }|
+ {3:~ }|*2
{4:[No Name] }|
{1:Set Up The Bars }|
|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*2
{2:[No Name] }|
- |
- |
- |
+ |*3
]])
- eq(3, meths.get_option_value('cmdheight', {}))
+ eq(3, api.nvim_get_option_value('cmdheight', {}))
- meths.input_mouse('left', 'drag', '', 1, 11, 10)
+ api.nvim_input_mouse('left', 'drag', '', 1, 11, 10)
screen:expect([[
{1:Set Up The Bars }|
^ |
- {3:~ }|
- {3:~ }|
+ {3:~ }|*2
{4:[No Name] }|
{1:Set Up The Bars }|
|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*4
{2:[No Name] }|
|
]])
- eq(1, meths.get_option_value('cmdheight', {}))
+ eq(1, api.nvim_get_option_value('cmdheight', {}))
end)
it('properly equalizes window height for window-local value', function()
@@ -493,40 +412,34 @@ describe('winbar', function()
end)
it('requires window-local value for floating windows', function()
- local win = meths.open_win(0, false, { relative = 'editor', row = 2, col = 10, height = 7,
- width = 30 })
- meths.set_option_value('winbar', 'bar', {})
- screen:expect{grid=[[
+ local win = api.nvim_open_win(
+ 0,
+ false,
+ { relative = 'editor', row = 2, col = 10, height = 7, width = 30 }
+ )
+ api.nvim_set_option_value('winbar', 'bar', {})
+ screen:expect {
+ grid = [[
{1:bar }|
^ |
{3:~ }{8: }{3: }|
- {3:~ }{9:~ }{3: }|
- {3:~ }{9:~ }{3: }|
- {3:~ }{9:~ }{3: }|
- {3:~ }{9:~ }{3: }|
- {3:~ }{9:~ }{3: }|
- {3:~ }{9:~ }{3: }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- |
- ]]}
- meths.set_option_value('winbar', 'floaty bar', { scope = 'local', win = win.id })
- screen:expect{grid=[[
+ {3:~ }{9:~ }{3: }|*6
+ {3:~ }|*3
+ |
+ ]],
+ }
+ api.nvim_set_option_value('winbar', 'floaty bar', { scope = 'local', win = win })
+ screen:expect {
+ grid = [[
{1:bar }|
^ |
{3:~ }{1:floaty bar }{3: }|
{3:~ }{8: }{3: }|
- {3:~ }{9:~ }{3: }|
- {3:~ }{9:~ }{3: }|
- {3:~ }{9:~ }{3: }|
- {3:~ }{9:~ }{3: }|
- {3:~ }{9:~ }{3: }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }{9:~ }{3: }|*5
+ {3:~ }|*3
|
- ]]}
+ ]],
+ }
end)
it('works correctly when moving a split', function()
@@ -537,8 +450,7 @@ describe('winbar', function()
screen:expect([[
{1:foo }│ |
^ │{3:~ }|
- {3:~ }│{3:~ }|
- {3:~ }│{3:~ }|
+ {3:~ }│{3:~ }|*2
{4:[No Name] }{2:[No Name] }|
|
]])
@@ -547,8 +459,7 @@ describe('winbar', function()
screen:expect([[
│{1:foo }|
{3:~ }│^ |
- {3:~ }│{3:~ }|
- {3:~ }│{3:~ }|
+ {3:~ }│{3:~ }|*2
{2:[No Name] }{4:[No Name] }|
|
]])
@@ -558,8 +469,7 @@ describe('winbar', function()
screen:expect([[
{1:foo }│^ |
│{3:~ }|
- {3:~ }│{3:~ }|
- {3:~ }│{3:~ }|
+ {3:~ }│{3:~ }|*2
{2:[No Name] }{4:[No Name] }|
|
]])
@@ -571,14 +481,7 @@ describe('winbar', function()
^ |
{4:[No Name] }|
|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*8
{2:[No Name] }|
|
]])
@@ -589,12 +492,7 @@ describe('winbar', function()
{4:[No Name] }|
{1:a }|
|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*6
{2:[No Name] }|
|
]])
@@ -628,12 +526,12 @@ describe('local winbar with tabs', function()
screen = Screen.new(60, 10)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true},
- [2] = {reverse = true},
- [3] = {bold = true, foreground = Screen.colors.Blue},
- [4] = {underline = true, background = Screen.colors.LightGray}
+ [1] = { bold = true },
+ [2] = { reverse = true },
+ [3] = { bold = true, foreground = Screen.colors.Blue },
+ [4] = { underline = true, background = Screen.colors.LightGray },
})
- meths.set_option_value('winbar', 'foo', { scope = 'local', win = 0 })
+ api.nvim_set_option_value('winbar', 'foo', { scope = 'local', win = 0 })
end)
it('works', function()
@@ -641,28 +539,19 @@ describe('local winbar with tabs', function()
screen:expect([[
{4: [No Name] }{1: [No Name] }{2: }{4:X}|
^ |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*7
|
]])
command('tabnext')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: [No Name] }{4: [No Name] }{2: }{4:X}|
{1:foo }|
^ |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*6
|
- ]]}
+ ]],
+ }
end)
it('can edit new empty buffer #19458', function()
@@ -670,68 +559,65 @@ describe('local winbar with tabs', function()
some
goofy
text]]
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1:foo }|
some |
goofy |
tex^t |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*5
|
- ]]}
+ ]],
+ }
-- this used to throw an E315 ml_get error
command 'tabedit'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{4: + [No Name] }{1: [No Name] }{2: }{4:X}|
^ |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*7
|
- ]]}
+ ]],
+ }
command 'tabprev'
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: + [No Name] }{4: [No Name] }{2: }{4:X}|
{1:foo }|
some |
goofy |
tex^t |
- {3:~ }|
- {3:~ }|
- {3:~ }|
- {3:~ }|
+ {3:~ }|*4
|
- ]]}
+ ]],
+ }
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>")',
- }})
+ 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},
+ [0] = { foreground = Screen.colors.Blue, bold = true },
+ [1] = { bold = true },
+ [2] = { bold = true, reverse = true },
})
screen:expect([[
{1:(winbar) }|
^ |
- {0:~ }|
- {0:~ }|
+ {0:~ }|*2
{2:(statusline) }|
|
]])
diff --git a/test/functional/vimscript/api_functions_spec.lua b/test/functional/vimscript/api_functions_spec.lua
index 0a7e7c1137..4985768bb0 100644
--- a/test/functional/vimscript/api_functions_spec.lua
+++ b/test/functional/vimscript/api_functions_spec.lua
@@ -1,35 +1,35 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
-local luv = require('luv')
local neq, eq, command = helpers.neq, helpers.eq, helpers.command
-local clear, curbufmeths = helpers.clear, helpers.curbufmeths
+local clear = helpers.clear
local exc_exec, expect, eval = helpers.exc_exec, helpers.expect, helpers.eval
+local exec_lua = helpers.exec_lua
local insert, pcall_err = helpers.insert, helpers.pcall_err
local matches = helpers.matches
-local meths = helpers.meths
+local api = helpers.api
local feed = helpers.feed
describe('eval-API', function()
before_each(clear)
- it("work", function()
+ it('work', function()
command("call nvim_command('let g:test = 1')")
eq(1, eval("nvim_get_var('test')"))
- local buf = eval("nvim_get_current_buf()")
- command("call nvim_buf_set_lines("..buf..", 0, -1, v:true, ['aa', 'bb'])")
+ local buf = eval('nvim_get_current_buf()')
+ command('call nvim_buf_set_lines(' .. buf .. ", 0, -1, v:true, ['aa', 'bb'])")
expect([[
aa
bb]])
- command("call nvim_win_set_cursor(0, [1, 1])")
+ command('call nvim_win_set_cursor(0, [1, 1])')
command("call nvim_input('ax<esc>')")
expect([[
aax
bb]])
end)
- it("throw errors for invalid arguments", function()
+ it('throw errors for invalid arguments', 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)
@@ -37,100 +37,134 @@ describe('eval-API', function()
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)
+ eq(
+ 'Vim(call):E5555: API call: Wrong type for argument 4 when calling nvim_buf_set_lines, expecting Boolean',
+ err
+ )
err = exc_exec('call nvim_buf_set_lines(0, 0, -1, v:true, "string")')
- eq('Vim(call):E5555: API call: Wrong type for argument 5 when calling nvim_buf_set_lines, expecting ArrayOf(String)', err)
+ eq(
+ 'Vim(call):E5555: API call: Wrong type for argument 5 when calling nvim_buf_set_lines, expecting ArrayOf(String)',
+ err
+ )
err = exc_exec('call nvim_buf_get_number("0")')
- eq('Vim(call):E5555: API call: Wrong type for argument 1 when calling nvim_buf_get_number, expecting Buffer', err)
+ eq(
+ 'Vim(call):E5555: API call: Wrong type for argument 1 when calling nvim_buf_get_number, expecting Buffer',
+ err
+ )
err = exc_exec('call nvim_buf_line_count(17)')
eq('Vim(call):E5555: API call: Invalid buffer id: 17', err)
end)
it('cannot change text or window if textlocked', function()
- command("autocmd TextYankPost <buffer> ++once call nvim_buf_set_lines(0, 0, -1, v:false, [])")
- matches('Vim%(call%):E5555: API call: E565: Not allowed to change text or change window$',
- pcall_err(command, "normal! yy"))
-
- command("autocmd TextYankPost <buffer> ++once call nvim_open_term(0, {})")
- matches('Vim%(call%):E5555: API call: E565: Not allowed to change text or change window$',
- pcall_err(command, "normal! yy"))
+ command('autocmd TextYankPost <buffer> ++once call nvim_buf_set_lines(0, 0, -1, v:false, [])')
+ matches(
+ 'Vim%(call%):E5555: API call: E565: Not allowed to change text or change window$',
+ pcall_err(command, 'normal! yy')
+ )
+
+ command('autocmd TextYankPost <buffer> ++once call nvim_open_term(0, {})')
+ matches(
+ 'Vim%(call%):E5555: API call: E565: Not allowed to change text or change window$',
+ pcall_err(command, 'normal! yy')
+ )
-- Functions checking textlock should also not be usable from <expr> mappings.
- command("inoremap <expr> <f2> nvim_win_close(0, 1)")
- eq('Vim(normal):E5555: API call: E565: Not allowed to change text or change window',
- pcall_err(command, [[execute "normal i\<f2>"]]))
+ command('inoremap <expr> <f2> nvim_win_close(0, 1)')
+ eq(
+ 'Vim(normal):E5555: API call: E565: Not allowed to change text or change window',
+ pcall_err(command, [[execute "normal i\<f2>"]])
+ )
-- Text-changing functions gave a "Failed to save undo information" error when called from an
-- <expr> mapping outside do_cmdline() (msg_list == NULL), so use feed() to test this.
command("inoremap <expr> <f2> nvim_buf_set_text(0, 0, 0, 0, 0, ['hi'])")
- meths.set_vvar('errmsg', '')
- feed("i<f2><esc>")
- eq('E5555: API call: E565: Not allowed to change text or change window',
- meths.get_vvar('errmsg'))
+ api.nvim_set_vvar('errmsg', '')
+ feed('i<f2><esc>')
+ eq(
+ 'E5555: API call: E565: Not allowed to change text or change window',
+ api.nvim_get_vvar('errmsg')
+ )
-- Some functions checking textlock (usually those that may change the current window or buffer)
-- also ought to not be usable in the cmdwin.
- local old_win = meths.get_current_win()
- feed("q:")
- eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
- pcall_err(meths.set_current_win, old_win))
+ local old_win = api.nvim_get_current_win()
+ feed('q:')
+ eq(
+ 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
+ pcall_err(api.nvim_set_current_win, old_win)
+ )
-- But others, like nvim_buf_set_lines(), which just changes text, is OK.
- curbufmeths.set_lines(0, -1, 1, {"wow!"})
- eq({'wow!'}, curbufmeths.get_lines(0, -1, 1))
+ api.nvim_buf_set_lines(0, 0, -1, 1, { 'wow!' })
+ eq({ 'wow!' }, api.nvim_buf_get_lines(0, 0, -1, 1))
-- Turning the cmdwin buffer into a terminal buffer would be pretty weird.
- eq('E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
- pcall_err(meths.open_term, 0, {}))
+ eq(
+ 'E11: Invalid in command-line window; <CR> executes, CTRL-C quits',
+ pcall_err(api.nvim_open_term, 0, {})
+ )
+
+ matches(
+ 'E11: Invalid in command%-line window; <CR> executes, CTRL%-C quits$',
+ pcall_err(
+ exec_lua,
+ [[
+ local cmdwin_buf = vim.api.nvim_get_current_buf()
+ vim.api.nvim_buf_call(vim.api.nvim_create_buf(false, true), function()
+ vim.api.nvim_open_term(cmdwin_buf, {})
+ end)
+ ]]
+ )
+ )
-- But turning a different buffer into a terminal from the cmdwin is OK.
- local term_buf = meths.create_buf(false, true)
- meths.open_term(term_buf, {})
- eq('terminal', meths.get_option_value("buftype", {buf = term_buf}))
+ local term_buf = api.nvim_create_buf(false, true)
+ api.nvim_open_term(term_buf, {})
+ eq('terminal', api.nvim_get_option_value('buftype', { buf = term_buf }))
end)
- it("use buffer numbers and windows ids as handles", function()
+ it('use buffer numbers and windows ids as handles', function()
local screen = Screen.new(40, 8)
screen:attach()
local bnr = eval("bufnr('')")
- local bhnd = eval("nvim_get_current_buf()")
- local wid = eval("win_getid()")
- local whnd = eval("nvim_get_current_win()")
+ local bhnd = eval('nvim_get_current_buf()')
+ local wid = eval('win_getid()')
+ local whnd = eval('nvim_get_current_win()')
eq(bnr, bhnd)
eq(wid, whnd)
- command("new") -- creates new buffer and new window
+ command('new') -- creates new buffer and new window
local bnr2 = eval("bufnr('')")
- local bhnd2 = eval("nvim_get_current_buf()")
- local wid2 = eval("win_getid()")
- local whnd2 = eval("nvim_get_current_win()")
+ local bhnd2 = eval('nvim_get_current_buf()')
+ local wid2 = eval('win_getid()')
+ local whnd2 = eval('nvim_get_current_win()')
eq(bnr2, bhnd2)
eq(wid2, whnd2)
neq(bnr, bnr2)
neq(wid, wid2)
-- 0 is synonymous to the current buffer
- eq(bnr2, eval("nvim_buf_get_number(0)"))
+ eq(bnr2, eval('nvim_buf_get_number(0)'))
- command("bn") -- show old buffer in new window
- eq(bnr, eval("nvim_get_current_buf()"))
+ command('bn') -- show old buffer in new window
+ eq(bnr, eval('nvim_get_current_buf()'))
eq(bnr, eval("bufnr('')"))
- eq(bnr, eval("nvim_buf_get_number(0)"))
- eq(wid2, eval("win_getid()"))
- eq(whnd2, eval("nvim_get_current_win()"))
+ eq(bnr, eval('nvim_buf_get_number(0)'))
+ eq(wid2, eval('win_getid()'))
+ eq(whnd2, eval('nvim_get_current_win()'))
end)
- it("get_lines and set_lines use NL to represent NUL", function()
- curbufmeths.set_lines(0, -1, true, {"aa\0", "b\0b"})
- eq({'aa\n', 'b\nb'}, eval("nvim_buf_get_lines(0, 0, -1, 1)"))
+ it('get_lines and set_lines use NL to represent NUL', function()
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'aa\0', 'b\0b' })
+ eq({ 'aa\n', 'b\nb' }, eval('nvim_buf_get_lines(0, 0, -1, 1)'))
command('call nvim_buf_set_lines(0, 1, 2, v:true, ["xx", "\\nyy"])')
- eq({'aa\0', 'xx', '\0yy'}, curbufmeths.get_lines(0, -1, 1))
+ eq({ 'aa\0', 'xx', '\0yy' }, api.nvim_buf_get_lines(0, 0, -1, 1))
end)
- it("that are FUNC_ATTR_NOEVAL cannot be called", function()
+ it('that are FUNC_ATTR_NOEVAL cannot be called', function()
-- Deprecated vim_ prefix is not exported.
local err = exc_exec('call vim_get_current_buffer("foo")')
eq('Vim(call):E117: Unknown function: vim_get_current_buffer', err)
@@ -150,29 +184,24 @@ describe('eval-API', function()
end)
it('have metadata accessible with api_info()', function()
- local api_keys = eval("sort(keys(api_info()))")
- eq({'error_types', 'functions', 'types',
- 'ui_events', 'ui_options', 'version'}, api_keys)
+ local api_keys = eval('sort(keys(api_info()))')
+ eq({ 'error_types', 'functions', 'types', 'ui_events', 'ui_options', 'version' }, api_keys)
end)
it('are highlighted by vim.vim syntax file', function()
- if luv.fs_stat("build/runtime/syntax/vim/generated.vim").uid == nil then
- pending("runtime was not built, skipping test")
- return
- end
local screen = Screen.new(40, 8)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold = true, foreground = Screen.colors.Brown},
- [2] = {foreground = Screen.colors.DarkCyan},
- [3] = {foreground = Screen.colors.SlateBlue},
- [4] = {foreground = Screen.colors.Fuchsia},
- [5] = {bold = true, foreground = Screen.colors.Blue},
+ [1] = { bold = true, foreground = Screen.colors.Brown },
+ [2] = { foreground = Screen.colors.DarkCyan },
+ [3] = { foreground = Screen.colors.SlateBlue },
+ [4] = { foreground = Screen.colors.Fuchsia },
+ [5] = { bold = true, foreground = Screen.colors.Blue },
})
- command("set ft=vim")
- command("set rtp^=build/runtime/")
- command("syntax on")
+ command('set ft=vim')
+ command('set rtp^=build/runtime/')
+ command('syntax on')
insert([[
call bufnr('%')
call nvim_input('typing...')
@@ -182,18 +211,17 @@ describe('eval-API', function()
{1:call} {2:bufnr}{3:(}{4:'%'}{3:)} |
{1:call} {2:nvim_input}{3:(}{4:'typing...'}{3:)} |
{1:call} not_a_function{3:(}{4:42}{3:^)} |
- {5:~ }|
- {5:~ }|
- {5:~ }|
- {5:~ }|
+ {5:~ }|*4
|
]])
end)
it('cannot be called from sandbox', function()
- eq('Vim(call):E48: Not allowed in sandbox',
- pcall_err(command, "sandbox call nvim_input('ievil')"))
- eq({''}, meths.buf_get_lines(0, 0, -1, true))
+ eq(
+ 'Vim(call):E48: Not allowed in sandbox',
+ pcall_err(command, "sandbox call nvim_input('ievil')")
+ )
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, true))
end)
it('converts blobs to API strings', function()
diff --git a/test/functional/vimscript/buf_functions_spec.lua b/test/functional/vimscript/buf_functions_spec.lua
index 2a5720fbd7..931fe640a9 100644
--- a/test/functional/vimscript/buf_functions_spec.lua
+++ b/test/functional/vimscript/buf_functions_spec.lua
@@ -1,17 +1,11 @@
local helpers = require('test.functional.helpers')(after_each)
-local luv = require('luv')
-
local eq = helpers.eq
local clear = helpers.clear
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local command = helpers.command
local exc_exec = helpers.exc_exec
-local bufmeths = helpers.bufmeths
-local curbufmeths = helpers.curbufmeths
-local curwinmeths = helpers.curwinmeths
-local curtabmeths = helpers.curtabmeths
local get_pathsep = helpers.get_pathsep
local rmdir = helpers.rmdir
local pcall_err = helpers.pcall_err
@@ -23,30 +17,47 @@ local dirname = fname .. '.d'
before_each(clear)
-for _, func in ipairs({'bufname(%s)', 'bufnr(%s)', 'bufwinnr(%s)',
- 'getbufline(%s, 1)', 'getbufvar(%s, "changedtick")',
- 'setbufvar(%s, "f", 0)'}) do
+for _, func in ipairs({
+ 'bufname(%s)',
+ 'bufnr(%s)',
+ 'bufwinnr(%s)',
+ 'getbufline(%s, 1)',
+ 'getbufvar(%s, "changedtick")',
+ 'setbufvar(%s, "f", 0)',
+}) do
local funcname = func:match('%w+')
describe(funcname .. '() function', function()
it('errors out when receives v:true/v:false/v:null', function()
-- Not compatible with Vim: in Vim it always results in buffer not found
-- without any error messages.
- for _, var in ipairs({'v:true', 'v:false'}) do
- eq('Vim(call):E5299: Expected a Number or a String, Boolean found',
- exc_exec('call ' .. func:format(var)))
+ for _, var in ipairs({ 'v:true', 'v:false' }) do
+ eq(
+ 'Vim(call):E5299: Expected a Number or a String, Boolean found',
+ exc_exec('call ' .. func:format(var))
+ )
end
- eq('Vim(call):E5300: Expected a Number or a String',
- exc_exec('call ' .. func:format('v:null')))
+ eq(
+ 'Vim(call):E5300: Expected a Number or a String',
+ exc_exec('call ' .. func:format('v:null'))
+ )
end)
it('errors out when receives invalid argument', function()
- eq('Vim(call):E745: Expected a Number or a String, List found',
- exc_exec('call ' .. func:format('[]')))
- eq('Vim(call):E728: Expected a Number or a String, Dictionary found',
- exc_exec('call ' .. func:format('{}')))
- eq('Vim(call):E805: Expected a Number or a String, Float found',
- exc_exec('call ' .. func:format('0.0')))
- eq('Vim(call):E703: Expected a Number or a String, Funcref found',
- exc_exec('call ' .. func:format('function("tr")')))
+ eq(
+ 'Vim(call):E745: Expected a Number or a String, List found',
+ exc_exec('call ' .. func:format('[]'))
+ )
+ eq(
+ 'Vim(call):E728: Expected a Number or a String, Dictionary found',
+ exc_exec('call ' .. func:format('{}'))
+ )
+ eq(
+ 'Vim(call):E805: Expected a Number or a String, Float found',
+ exc_exec('call ' .. func:format('0.0'))
+ )
+ eq(
+ 'Vim(call):E703: Expected a Number or a String, Funcref found',
+ exc_exec('call ' .. func:format('function("tr")'))
+ )
end)
end)
end
@@ -54,12 +65,12 @@ end
describe('bufname() function', function()
it('returns empty string when buffer was not found', function()
command('file ' .. fname)
- eq('', funcs.bufname(2))
- eq('', funcs.bufname('non-existent-buffer'))
- eq('', funcs.bufname('#'))
+ eq('', fn.bufname(2))
+ eq('', fn.bufname('non-existent-buffer'))
+ eq('', fn.bufname('#'))
command('edit ' .. fname2)
- eq(2, funcs.bufnr('%'))
- eq('', funcs.bufname('X'))
+ eq(2, fn.bufnr('%'))
+ eq('', fn.bufname('X'))
end)
before_each(function()
mkdir(dirname)
@@ -68,80 +79,80 @@ describe('bufname() function', function()
rmdir(dirname)
end)
it('returns expected buffer name', function()
- eq('', funcs.bufname('%')) -- Buffer has no name yet
+ eq('', fn.bufname('%')) -- Buffer has no name yet
command('file ' .. fname)
- local wd = luv.cwd()
+ local wd = vim.uv.cwd()
local sep = get_pathsep()
- local curdirname = funcs.fnamemodify(wd, ':t')
- for _, arg in ipairs({'%', 1, 'X', wd}) do
- eq(fname, funcs.bufname(arg))
- meths.set_current_dir('..')
- eq(curdirname .. sep .. fname, funcs.bufname(arg))
- meths.set_current_dir(curdirname)
- meths.set_current_dir(dirname)
- eq(wd .. sep .. fname, funcs.bufname(arg))
- meths.set_current_dir('..')
- eq(fname, funcs.bufname(arg))
+ local curdirname = fn.fnamemodify(wd, ':t')
+ for _, arg in ipairs({ '%', 1, 'X', wd }) do
+ eq(fname, fn.bufname(arg))
+ api.nvim_set_current_dir('..')
+ eq(curdirname .. sep .. fname, fn.bufname(arg))
+ api.nvim_set_current_dir(curdirname)
+ api.nvim_set_current_dir(dirname)
+ eq(wd .. sep .. fname, fn.bufname(arg))
+ api.nvim_set_current_dir('..')
+ eq(fname, fn.bufname(arg))
command('enew')
end
- eq('', funcs.bufname('%'))
- eq('', funcs.bufname('$'))
- eq(2, funcs.bufnr('%'))
+ eq('', fn.bufname('%'))
+ eq('', fn.bufname('$'))
+ eq(2, fn.bufnr('%'))
end)
end)
describe('bufnr() function', function()
it('returns -1 when buffer was not found', function()
command('file ' .. fname)
- eq(-1, funcs.bufnr(2))
- eq(-1, funcs.bufnr('non-existent-buffer'))
- eq(-1, funcs.bufnr('#'))
+ eq(-1, fn.bufnr(2))
+ eq(-1, fn.bufnr('non-existent-buffer'))
+ eq(-1, fn.bufnr('#'))
command('edit ' .. fname2)
- eq(2, funcs.bufnr('%'))
- eq(-1, funcs.bufnr('X'))
+ eq(2, fn.bufnr('%'))
+ eq(-1, fn.bufnr('X'))
end)
it('returns expected buffer number', function()
- eq(1, funcs.bufnr('%'))
+ eq(1, fn.bufnr('%'))
command('file ' .. fname)
- local wd = luv.cwd()
- local curdirname = funcs.fnamemodify(wd, ':t')
- eq(1, funcs.bufnr(fname))
- eq(1, funcs.bufnr(wd))
- eq(1, funcs.bufnr(curdirname))
- eq(1, funcs.bufnr('X'))
+ local wd = vim.uv.cwd()
+ local curdirname = fn.fnamemodify(wd, ':t')
+ eq(1, fn.bufnr(fname))
+ eq(1, fn.bufnr(wd))
+ eq(1, fn.bufnr(curdirname))
+ eq(1, fn.bufnr('X'))
end)
it('returns number of last buffer with "$"', function()
- eq(1, funcs.bufnr('$'))
+ eq(1, fn.bufnr('$'))
command('new')
- eq(2, funcs.bufnr('$'))
+ eq(2, fn.bufnr('$'))
command('new')
- eq(3, funcs.bufnr('$'))
+ eq(3, fn.bufnr('$'))
command('only')
- eq(3, funcs.bufnr('$'))
- eq(3, funcs.bufnr('%'))
+ eq(3, fn.bufnr('$'))
+ eq(3, fn.bufnr('%'))
command('buffer 1')
- eq(3, funcs.bufnr('$'))
- eq(1, funcs.bufnr('%'))
+ eq(3, fn.bufnr('$'))
+ eq(1, fn.bufnr('%'))
command('bwipeout 2')
- eq(3, funcs.bufnr('$'))
- eq(1, funcs.bufnr('%'))
+ eq(3, fn.bufnr('$'))
+ eq(1, fn.bufnr('%'))
command('bwipeout 3')
- eq(1, funcs.bufnr('$'))
- eq(1, funcs.bufnr('%'))
+ eq(1, fn.bufnr('$'))
+ eq(1, fn.bufnr('%'))
command('new')
- eq(4, funcs.bufnr('$'))
+ eq(4, fn.bufnr('$'))
end)
end)
describe('bufwinnr() function', function()
it('returns -1 when buffer was not found', function()
command('file ' .. fname)
- eq(-1, funcs.bufwinnr(2))
- eq(-1, funcs.bufwinnr('non-existent-buffer'))
- eq(-1, funcs.bufwinnr('#'))
- command('split ' .. fname2) -- It would be OK if there was one window
- eq(2, funcs.bufnr('%'))
- eq(-1, funcs.bufwinnr('X'))
+ eq(-1, fn.bufwinnr(2))
+ eq(-1, fn.bufwinnr('non-existent-buffer'))
+ eq(-1, fn.bufwinnr('#'))
+ command('split ' .. fname2) -- It would be OK if there was one window
+ eq(2, fn.bufnr('%'))
+ eq(-1, fn.bufwinnr('X'))
end)
before_each(function()
mkdir(dirname)
@@ -150,162 +161,162 @@ describe('bufwinnr() function', function()
rmdir(dirname)
end)
it('returns expected window number', function()
- eq(1, funcs.bufwinnr('%'))
+ eq(1, fn.bufwinnr('%'))
command('file ' .. fname)
command('vsplit')
command('split ' .. fname2)
- eq(2, funcs.bufwinnr(fname))
- eq(1, funcs.bufwinnr(fname2))
- eq(-1, funcs.bufwinnr(fname:sub(1, #fname - 1)))
- meths.set_current_dir(dirname)
- eq(2, funcs.bufwinnr(fname))
- eq(1, funcs.bufwinnr(fname2))
- eq(-1, funcs.bufwinnr(fname:sub(1, #fname - 1)))
- eq(1, funcs.bufwinnr('%'))
- eq(2, funcs.bufwinnr(1))
- eq(1, funcs.bufwinnr(2))
- eq(-1, funcs.bufwinnr(3))
- eq(1, funcs.bufwinnr('$'))
+ eq(2, fn.bufwinnr(fname))
+ eq(1, fn.bufwinnr(fname2))
+ eq(-1, fn.bufwinnr(fname:sub(1, #fname - 1)))
+ api.nvim_set_current_dir(dirname)
+ eq(2, fn.bufwinnr(fname))
+ eq(1, fn.bufwinnr(fname2))
+ eq(-1, fn.bufwinnr(fname:sub(1, #fname - 1)))
+ eq(1, fn.bufwinnr('%'))
+ eq(2, fn.bufwinnr(1))
+ eq(1, fn.bufwinnr(2))
+ eq(-1, fn.bufwinnr(3))
+ eq(1, fn.bufwinnr('$'))
end)
end)
describe('getbufline() function', function()
it('returns empty list when buffer was not found', function()
command('file ' .. fname)
- eq({}, funcs.getbufline(2, 1))
- eq({}, funcs.getbufline('non-existent-buffer', 1))
- eq({}, funcs.getbufline('#', 1))
+ eq({}, fn.getbufline(2, 1))
+ eq({}, fn.getbufline('non-existent-buffer', 1))
+ eq({}, fn.getbufline('#', 1))
command('edit ' .. fname2)
- eq(2, funcs.bufnr('%'))
- eq({}, funcs.getbufline('X', 1))
+ eq(2, fn.bufnr('%'))
+ eq({}, fn.getbufline('X', 1))
end)
it('returns empty list when range is invalid', function()
- eq({}, funcs.getbufline(1, 0))
- curbufmeths.set_lines(0, 1, false, {'foo', 'bar', 'baz'})
- eq({}, funcs.getbufline(1, 2, 1))
- eq({}, funcs.getbufline(1, -10, -20))
- eq({}, funcs.getbufline(1, -2, -1))
- eq({}, funcs.getbufline(1, -1, 9999))
+ eq({}, fn.getbufline(1, 0))
+ api.nvim_buf_set_lines(0, 0, 1, false, { 'foo', 'bar', 'baz' })
+ eq({}, fn.getbufline(1, 2, 1))
+ eq({}, fn.getbufline(1, -10, -20))
+ eq({}, fn.getbufline(1, -2, -1))
+ eq({}, fn.getbufline(1, -1, 9999))
end)
it('returns expected lines', function()
- meths.set_option_value('hidden', true, {})
+ api.nvim_set_option_value('hidden', true, {})
command('file ' .. fname)
- curbufmeths.set_lines(0, 1, false, {'foo\0', '\0bar', 'baz'})
+ api.nvim_buf_set_lines(0, 0, 1, false, { 'foo\0', '\0bar', 'baz' })
command('edit ' .. fname2)
- curbufmeths.set_lines(0, 1, false, {'abc\0', '\0def', 'ghi'})
- eq({'foo\n', '\nbar', 'baz'}, funcs.getbufline(1, 1, 9999))
- eq({'abc\n', '\ndef', 'ghi'}, funcs.getbufline(2, 1, 9999))
- eq({'foo\n', '\nbar', 'baz'}, funcs.getbufline(1, 1, '$'))
- eq({'baz'}, funcs.getbufline(1, '$', '$'))
- eq({'baz'}, funcs.getbufline(1, '$', 9999))
+ api.nvim_buf_set_lines(0, 0, 1, false, { 'abc\0', '\0def', 'ghi' })
+ eq({ 'foo\n', '\nbar', 'baz' }, fn.getbufline(1, 1, 9999))
+ eq({ 'abc\n', '\ndef', 'ghi' }, fn.getbufline(2, 1, 9999))
+ eq({ 'foo\n', '\nbar', 'baz' }, fn.getbufline(1, 1, '$'))
+ eq({ 'baz' }, fn.getbufline(1, '$', '$'))
+ eq({ 'baz' }, fn.getbufline(1, '$', 9999))
end)
end)
describe('getbufvar() function', function()
it('returns empty list when buffer was not found', function()
command('file ' .. fname)
- eq('', funcs.getbufvar(2, '&autoindent'))
- eq('', funcs.getbufvar('non-existent-buffer', '&autoindent'))
- eq('', funcs.getbufvar('#', '&autoindent'))
+ eq('', fn.getbufvar(2, '&autoindent'))
+ eq('', fn.getbufvar('non-existent-buffer', '&autoindent'))
+ eq('', fn.getbufvar('#', '&autoindent'))
command('edit ' .. fname2)
- eq(2, funcs.bufnr('%'))
- eq('', funcs.getbufvar('X', '&autoindent'))
+ eq(2, fn.bufnr('%'))
+ eq('', fn.getbufvar('X', '&autoindent'))
end)
it('returns empty list when variable/option/etc was not found', function()
command('file ' .. fname)
- eq('', funcs.getbufvar(1, '&autondent'))
- eq('', funcs.getbufvar(1, 'changedtic'))
+ eq('', fn.getbufvar(1, '&autondent'))
+ eq('', fn.getbufvar(1, 'changedtic'))
end)
it('returns expected option value', function()
- eq(0, funcs.getbufvar(1, '&autoindent'))
- eq(0, funcs.getbufvar(1, '&l:autoindent'))
- eq(0, funcs.getbufvar(1, '&g:autoindent'))
+ eq(0, fn.getbufvar(1, '&autoindent'))
+ eq(0, fn.getbufvar(1, '&l:autoindent'))
+ eq(0, fn.getbufvar(1, '&g:autoindent'))
-- Also works with global-only options
- eq(1, funcs.getbufvar(1, '&hidden'))
- eq(1, funcs.getbufvar(1, '&l:hidden'))
- eq(1, funcs.getbufvar(1, '&g:hidden'))
+ eq(1, fn.getbufvar(1, '&hidden'))
+ eq(1, fn.getbufvar(1, '&l:hidden'))
+ eq(1, fn.getbufvar(1, '&g:hidden'))
-- Also works with window-local options
- eq(0, funcs.getbufvar(1, '&number'))
- eq(0, funcs.getbufvar(1, '&l:number'))
- eq(0, funcs.getbufvar(1, '&g:number'))
+ eq(0, fn.getbufvar(1, '&number'))
+ eq(0, fn.getbufvar(1, '&l:number'))
+ eq(0, fn.getbufvar(1, '&g:number'))
command('new')
-- But with window-local options it probably does not what you expect
- command("setl number")
+ command('setl number')
-- (note that current window’s buffer is 2, but getbufvar() receives 1)
- eq({id=2}, curwinmeths.get_buf())
- eq(1, funcs.getbufvar(1, '&number'))
- eq(1, funcs.getbufvar(1, '&l:number'))
+ eq(2, api.nvim_win_get_buf(0))
+ eq(1, fn.getbufvar(1, '&number'))
+ eq(1, fn.getbufvar(1, '&l:number'))
-- You can get global value though, if you find this useful.
- eq(0, funcs.getbufvar(1, '&g:number'))
+ eq(0, fn.getbufvar(1, '&g:number'))
end)
it('returns expected variable value', function()
- eq(2, funcs.getbufvar(1, 'changedtick'))
- curbufmeths.set_lines(0, 1, false, {'abc\0', '\0def', 'ghi'})
- eq(3, funcs.getbufvar(1, 'changedtick'))
- curbufmeths.set_var('test', true)
- eq(true, funcs.getbufvar(1, 'test'))
- eq({test=true, changedtick=3}, funcs.getbufvar(1, ''))
+ eq(2, fn.getbufvar(1, 'changedtick'))
+ api.nvim_buf_set_lines(0, 0, 1, false, { 'abc\0', '\0def', 'ghi' })
+ eq(3, fn.getbufvar(1, 'changedtick'))
+ api.nvim_buf_set_var(0, 'test', true)
+ eq(true, fn.getbufvar(1, 'test'))
+ eq({ test = true, changedtick = 3 }, fn.getbufvar(1, ''))
command('new')
- eq(3, funcs.getbufvar(1, 'changedtick'))
- eq(true, funcs.getbufvar(1, 'test'))
- eq({test=true, changedtick=3}, funcs.getbufvar(1, ''))
+ eq(3, fn.getbufvar(1, 'changedtick'))
+ eq(true, fn.getbufvar(1, 'test'))
+ eq({ test = true, changedtick = 3 }, fn.getbufvar(1, ''))
end)
end)
describe('setbufvar() function', function()
it('throws the error or ignores the input when buffer was not found', function()
command('file ' .. fname)
- eq(0,
- exc_exec('call setbufvar(2, "&autoindent", 0)'))
- eq('Vim(call):E94: No matching buffer for non-existent-buffer',
- exc_exec('call setbufvar("non-existent-buffer", "&autoindent", 0)'))
- eq(0,
- exc_exec('call setbufvar("#", "&autoindent", 0)'))
+ eq(0, exc_exec('call setbufvar(2, "&autoindent", 0)'))
+ eq(
+ 'Vim(call):E94: No matching buffer for non-existent-buffer',
+ exc_exec('call setbufvar("non-existent-buffer", "&autoindent", 0)')
+ )
+ eq(0, exc_exec('call setbufvar("#", "&autoindent", 0)'))
command('edit ' .. fname2)
- eq(2, funcs.bufnr('%'))
- eq('Vim(call):E93: More than one match for X',
- exc_exec('call setbufvar("X", "&autoindent", 0)'))
+ eq(2, fn.bufnr('%'))
+ eq(
+ 'Vim(call):E93: More than one match for X',
+ exc_exec('call setbufvar("X", "&autoindent", 0)')
+ )
end)
it('may set options, including window-local and global values', function()
- local buf1 = meths.get_current_buf()
- eq(false, meths.get_option_value('number', {}))
+ local buf1 = api.nvim_get_current_buf()
+ eq(false, api.nvim_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, 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(2, api.nvim_buf_get_number(api.nvim_win_get_buf(0)))
+ fn.setbufvar(1, '&number', true)
+ local windows = api.nvim_tabpage_list_wins(0)
+ eq(false, api.nvim_get_option_value('number', { win = windows[1] }))
+ eq(true, api.nvim_get_option_value('number', { win = windows[2] }))
+ eq(false, api.nvim_get_option_value('number', { win = windows[3] }))
+ eq(false, api.nvim_get_option_value('number', { win = api.nvim_get_current_win() }))
- eq(true, meths.get_option_value('hidden', {}))
- funcs.setbufvar(1, '&hidden', 0)
- eq(false, meths.get_option_value('hidden', {}))
+ eq(true, api.nvim_get_option_value('hidden', {}))
+ fn.setbufvar(1, '&hidden', 0)
+ eq(false, api.nvim_get_option_value('hidden', {}))
- eq(false, meths.get_option_value('autoindent', {buf=buf1.id}))
- funcs.setbufvar(1, '&autoindent', true)
- eq(true, meths.get_option_value('autoindent', {buf=buf1.id}))
- eq('Vim(call):E355: Unknown option: xxx',
- exc_exec('call setbufvar(1, "&xxx", 0)'))
+ eq(false, api.nvim_get_option_value('autoindent', { buf = buf1 }))
+ fn.setbufvar(1, '&autoindent', true)
+ eq(true, api.nvim_get_option_value('autoindent', { buf = buf1 }))
+ eq('Vim(call):E355: Unknown option: xxx', exc_exec('call setbufvar(1, "&xxx", 0)'))
end)
it('may set variables', function()
- local buf1 = meths.get_current_buf()
+ local buf1 = api.nvim_get_current_buf()
command('split')
command('new')
- eq(2, curbufmeths.get_number())
- funcs.setbufvar(1, 'number', true)
- eq(true, bufmeths.get_var(buf1, 'number'))
- eq('Vim(call):E461: Illegal variable name: b:',
- exc_exec('call setbufvar(1, "", 0)'))
- eq(true, bufmeths.get_var(buf1, 'number'))
- eq('Vim:E46: Cannot change read-only variable "b:changedtick"',
- pcall_err(funcs.setbufvar, 1, 'changedtick', true))
- eq(2, funcs.getbufvar(1, 'changedtick'))
+ eq(2, api.nvim_buf_get_number(0))
+ fn.setbufvar(1, 'number', true)
+ eq(true, api.nvim_buf_get_var(buf1, 'number'))
+ eq('Vim(call):E461: Illegal variable name: b:', exc_exec('call setbufvar(1, "", 0)'))
+ eq(true, api.nvim_buf_get_var(buf1, 'number'))
+ eq(
+ 'Vim:E46: Cannot change read-only variable "b:changedtick"',
+ pcall_err(fn.setbufvar, 1, 'changedtick', true)
+ )
+ eq(2, fn.getbufvar(1, 'changedtick'))
end)
it('throws error when setting a string option to a boolean value vim-patch:9.0.0090', function()
- eq('Vim:E928: String required',
- pcall_err(funcs.setbufvar, '', '&errorformat', true))
+ eq('Vim:E928: String required', pcall_err(fn.setbufvar, '', '&errorformat', true))
end)
end)
diff --git a/test/functional/vimscript/changedtick_spec.lua b/test/functional/vimscript/changedtick_spec.lua
index 8533fac9ec..85928921c5 100644
--- a/test/functional/vimscript/changedtick_spec.lua
+++ b/test/functional/vimscript/changedtick_spec.lua
@@ -4,35 +4,34 @@ local eq = helpers.eq
local eval = helpers.eval
local feed = helpers.feed
local clear = helpers.clear
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local command = helpers.command
local exc_exec = helpers.exc_exec
local pcall_err = helpers.pcall_err
local exec_capture = helpers.exec_capture
-local curbufmeths = helpers.curbufmeths
before_each(clear)
local function changedtick()
- local ct = curbufmeths.get_changedtick()
- eq(ct, curbufmeths.get_var('changedtick'))
- eq(ct, curbufmeths.get_var('changedtick'))
+ local ct = api.nvim_buf_get_changedtick(0)
+ eq(ct, api.nvim_buf_get_var(0, 'changedtick'))
+ eq(ct, api.nvim_buf_get_var(0, 'changedtick'))
eq(ct, eval('b:changedtick'))
eq(ct, eval('b:["changedtick"]'))
eq(ct, eval('b:.changedtick'))
- eq(ct, funcs.getbufvar('%', 'changedtick'))
- eq(ct, funcs.getbufvar('%', '').changedtick)
+ eq(ct, fn.getbufvar('%', 'changedtick'))
+ eq(ct, fn.getbufvar('%', '').changedtick)
eq(ct, eval('b:').changedtick)
return ct
end
describe('b:changedtick', function()
-- Ported tests from Vim-8.0.333
- it('increments', function() -- Test_changedtick_increments
+ it('increments', function() -- Test_changedtick_increments
-- New buffer has an empty line, tick starts at 2
eq(2, changedtick())
- funcs.setline(1, 'hello')
+ fn.setline(1, 'hello')
eq(3, changedtick())
eq(0, exc_exec('undo'))
-- Somehow undo counts as two changes
@@ -41,54 +40,74 @@ describe('b:changedtick', function()
it('is present in b: dictionary', function()
eq(2, changedtick())
command('let d = b:')
- eq(2, meths.get_var('d').changedtick)
+ eq(2, api.nvim_get_var('d').changedtick)
end)
it('increments at bdel', function()
command('new')
eq(2, changedtick())
- local bnr = curbufmeths.get_number()
+ local bnr = api.nvim_buf_get_number(0)
eq(2, bnr)
command('bdel')
- eq(3, funcs.getbufvar(bnr, 'changedtick'))
- eq(1, curbufmeths.get_number())
+ eq(3, fn.getbufvar(bnr, 'changedtick'))
+ eq(1, api.nvim_buf_get_number(0))
end)
it('fails to be changed by user', function()
local ct = changedtick()
local ctn = ct + 100500
eq(0, exc_exec('let d = b:'))
- eq('Vim(let):E46: Cannot change read-only variable "b:changedtick"',
- pcall_err(command, 'let b:changedtick = ' .. ctn))
- eq('Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
- pcall_err(command, 'let b:["changedtick"] = ' .. ctn))
- eq('Vim(let):E46: Cannot change read-only variable "b:.changedtick"',
- pcall_err(command, 'let b:.changedtick = ' .. ctn))
- eq('Vim(let):E46: Cannot change read-only variable "d.changedtick"',
- pcall_err(command, 'let d.changedtick = ' .. ctn))
- eq('Key is read-only: changedtick',
- pcall_err(curbufmeths.set_var, 'changedtick', ctn))
+ eq(
+ 'Vim(let):E46: Cannot change read-only variable "b:changedtick"',
+ pcall_err(command, 'let b:changedtick = ' .. ctn)
+ )
+ eq(
+ 'Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
+ pcall_err(command, 'let b:["changedtick"] = ' .. ctn)
+ )
+ eq(
+ 'Vim(let):E46: Cannot change read-only variable "b:.changedtick"',
+ pcall_err(command, 'let b:.changedtick = ' .. ctn)
+ )
+ eq(
+ 'Vim(let):E46: Cannot change read-only variable "d.changedtick"',
+ pcall_err(command, 'let d.changedtick = ' .. ctn)
+ )
+ eq('Key is read-only: changedtick', pcall_err(api.nvim_buf_set_var, 0, 'changedtick', ctn))
- eq('Vim(unlet):E795: Cannot delete variable b:changedtick',
- pcall_err(command, 'unlet b:changedtick'))
- eq('Vim(unlet):E46: Cannot change read-only variable "b:.changedtick"',
- pcall_err(command, 'unlet b:.changedtick'))
- eq('Vim(unlet):E46: Cannot change read-only variable "b:["changedtick"]"',
- pcall_err(command, 'unlet b:["changedtick"]'))
- eq('Vim(unlet):E46: Cannot change read-only variable "d.changedtick"',
- pcall_err(command, 'unlet d.changedtick'))
- eq('Key is read-only: changedtick',
- pcall_err(curbufmeths.del_var, 'changedtick'))
+ eq(
+ 'Vim(unlet):E795: Cannot delete variable b:changedtick',
+ pcall_err(command, 'unlet b:changedtick')
+ )
+ eq(
+ 'Vim(unlet):E46: Cannot change read-only variable "b:.changedtick"',
+ pcall_err(command, 'unlet b:.changedtick')
+ )
+ eq(
+ 'Vim(unlet):E46: Cannot change read-only variable "b:["changedtick"]"',
+ pcall_err(command, 'unlet b:["changedtick"]')
+ )
+ eq(
+ 'Vim(unlet):E46: Cannot change read-only variable "d.changedtick"',
+ pcall_err(command, 'unlet d.changedtick')
+ )
+ eq('Key is read-only: changedtick', pcall_err(api.nvim_buf_del_var, 0, 'changedtick'))
eq(ct, changedtick())
- eq('Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
- pcall_err(command, 'let b:["changedtick"] += ' .. ctn))
- eq('Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
- pcall_err(command, 'let b:["changedtick"] -= ' .. ctn))
- eq('Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
- pcall_err(command, 'let b:["changedtick"] .= ' .. ctn))
+ eq(
+ 'Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
+ pcall_err(command, 'let b:["changedtick"] += ' .. ctn)
+ )
+ eq(
+ 'Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
+ pcall_err(command, 'let b:["changedtick"] -= ' .. ctn)
+ )
+ eq(
+ 'Vim(let):E46: Cannot change read-only variable "b:["changedtick"]"',
+ pcall_err(command, 'let b:["changedtick"] .= ' .. ctn)
+ )
eq(ct, changedtick())
- funcs.setline(1, 'hello')
+ fn.setline(1, 'hello')
eq(ct + 1, changedtick())
end)
@@ -97,39 +116,55 @@ describe('b:changedtick', function()
end)
it('fails to unlock b:changedtick', function()
eq(0, exc_exec('let d = b:'))
- eq(0, funcs.islocked('b:changedtick'))
- eq(0, funcs.islocked('d.changedtick'))
- eq('Vim(unlockvar):E940: Cannot lock or unlock variable b:changedtick',
- pcall_err(command, 'unlockvar b:changedtick'))
- eq('Vim(unlockvar):E46: Cannot change read-only variable "d.changedtick"',
- pcall_err(command, 'unlockvar d.changedtick'))
- eq(0, funcs.islocked('b:changedtick'))
- eq(0, funcs.islocked('d.changedtick'))
- eq('Vim(lockvar):E940: Cannot lock or unlock variable b:changedtick',
- pcall_err(command, 'lockvar b:changedtick'))
- eq('Vim(lockvar):E46: Cannot change read-only variable "d.changedtick"',
- pcall_err(command, 'lockvar d.changedtick'))
- eq(0, funcs.islocked('b:changedtick'))
- eq(0, funcs.islocked('d.changedtick'))
+ eq(0, fn.islocked('b:changedtick'))
+ eq(0, fn.islocked('d.changedtick'))
+ eq(
+ 'Vim(unlockvar):E940: Cannot lock or unlock variable b:changedtick',
+ pcall_err(command, 'unlockvar b:changedtick')
+ )
+ eq(
+ 'Vim(unlockvar):E46: Cannot change read-only variable "d.changedtick"',
+ pcall_err(command, 'unlockvar d.changedtick')
+ )
+ eq(0, fn.islocked('b:changedtick'))
+ eq(0, fn.islocked('d.changedtick'))
+ eq(
+ 'Vim(lockvar):E940: Cannot lock or unlock variable b:changedtick',
+ pcall_err(command, 'lockvar b:changedtick')
+ )
+ eq(
+ 'Vim(lockvar):E46: Cannot change read-only variable "d.changedtick"',
+ pcall_err(command, 'lockvar d.changedtick')
+ )
+ eq(0, fn.islocked('b:changedtick'))
+ eq(0, fn.islocked('d.changedtick'))
end)
it('is being completed', function()
feed(':echo b:<Tab><Home>let cmdline="<End>"<CR>')
- eq('echo b:changedtick', meths.get_var('cmdline'))
+ eq('echo b:changedtick', api.nvim_get_var('cmdline'))
end)
it('cannot be changed by filter() or map()', function()
eq(2, changedtick())
- eq('Vim(call):E795: Cannot delete variable filter() argument',
- pcall_err(command, 'call filter(b:, 0)'))
- eq('Vim(call):E742: Cannot change value of map() argument',
- pcall_err(command, 'call map(b:, 0)'))
- eq('Vim(call):E742: Cannot change value of map() argument',
- pcall_err(command, 'call map(b:, "v:val")'))
+ eq(
+ 'Vim(call):E795: Cannot delete variable filter() argument',
+ pcall_err(command, 'call filter(b:, 0)')
+ )
+ eq(
+ 'Vim(call):E742: Cannot change value of map() argument',
+ pcall_err(command, 'call map(b:, 0)')
+ )
+ eq(
+ 'Vim(call):E742: Cannot change value of map() argument',
+ pcall_err(command, 'call map(b:, "v:val")')
+ )
eq(2, changedtick())
end)
it('cannot be remove()d', function()
eq(2, changedtick())
- eq('Vim(call):E795: Cannot delete variable remove() argument',
- pcall_err(command, 'call remove(b:, "changedtick")'))
+ eq(
+ 'Vim(call):E795: Cannot delete variable remove() argument',
+ pcall_err(command, 'call remove(b:, "changedtick")')
+ )
eq(2, changedtick())
end)
it('does not inherit VAR_FIXED when copying dictionary over', function()
diff --git a/test/functional/vimscript/container_functions_spec.lua b/test/functional/vimscript/container_functions_spec.lua
index 5bef3fce05..1b34ea0165 100644
--- a/test/functional/vimscript/container_functions_spec.lua
+++ b/test/functional/vimscript/container_functions_spec.lua
@@ -2,23 +2,23 @@ local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
local eval = helpers.eval
-local meths = helpers.meths
+local api = helpers.api
local clear = helpers.clear
before_each(clear)
describe('extend()', function()
it('succeeds to extend list with itself', function()
- meths.set_var('l', {1, {}})
- eq({1, {}, 1, {}}, eval('extend(l, l)'))
- eq({1, {}, 1, {}}, meths.get_var('l'))
+ api.nvim_set_var('l', { 1, {} })
+ eq({ 1, {}, 1, {} }, eval('extend(l, l)'))
+ eq({ 1, {}, 1, {} }, api.nvim_get_var('l'))
- meths.set_var('l', {1, {}})
- eq({1, {}, 1, {}}, eval('extend(l, l, 0)'))
- eq({1, {}, 1, {}}, meths.get_var('l'))
+ api.nvim_set_var('l', { 1, {} })
+ eq({ 1, {}, 1, {} }, eval('extend(l, l, 0)'))
+ eq({ 1, {}, 1, {} }, api.nvim_get_var('l'))
- meths.set_var('l', {1, {}})
- eq({1, 1, {}, {}}, eval('extend(l, l, 1)'))
- eq({1, 1, {}, {}}, meths.get_var('l'))
+ api.nvim_set_var('l', { 1, {} })
+ eq({ 1, 1, {}, {} }, eval('extend(l, l, 1)'))
+ eq({ 1, 1, {}, {} }, api.nvim_get_var('l'))
end)
end)
diff --git a/test/functional/vimscript/ctx_functions_spec.lua b/test/functional/vimscript/ctx_functions_spec.lua
index 17607f0794..dc60a474f3 100644
--- a/test/functional/vimscript/ctx_functions_spec.lua
+++ b/test/functional/vimscript/ctx_functions_spec.lua
@@ -6,25 +6,24 @@ local command = helpers.command
local eq = helpers.eq
local eval = helpers.eval
local feed = helpers.feed
-local map = helpers.tbl_map
-local nvim = helpers.nvim
+local map = vim.tbl_map
+local api = helpers.api
local parse_context = helpers.parse_context
local exec_capture = helpers.exec_capture
local source = helpers.source
-local trim = helpers.trim
+local trim = vim.trim
local write_file = helpers.write_file
local pcall_err = helpers.pcall_err
describe('context functions', function()
local fname1 = 'Xtest-functional-eval-ctx1'
local fname2 = 'Xtest-functional-eval-ctx2'
- local outofbounds =
- 'Vim:E475: Invalid value for argument index: out of bounds'
+ local outofbounds = 'Vim:E475: Invalid value for argument index: out of bounds'
before_each(function()
clear()
- write_file(fname1, "1\n2\n3")
- write_file(fname2, "a\nb\nc")
+ write_file(fname1, '1\n2\n3')
+ write_file(fname2, 'a\nb\nc')
end)
after_each(function()
@@ -34,98 +33,125 @@ describe('context functions', function()
describe('ctxpush/ctxpop', function()
it('saves and restores registers properly', function()
- local regs = {'1', '2', '3', 'a'}
- local vals = {'1', '2', '3', 'hjkl'}
+ local regs = { '1', '2', '3', 'a' }
+ local vals = { '1', '2', '3', 'hjkl' }
feed('i1<cr>2<cr>3<c-[>ddddddqahjklq')
- eq(vals, map(function(r) return trim(call('getreg', r)) end, regs))
+ eq(
+ vals,
+ map(function(r)
+ return trim(call('getreg', r))
+ end, regs)
+ )
call('ctxpush')
- call('ctxpush', {'regs'})
-
- map(function(r) call('setreg', r, {}) end, regs)
- eq({'', '', '', ''},
- map(function(r) return trim(call('getreg', r)) end, regs))
+ call('ctxpush', { 'regs' })
+
+ map(function(r)
+ call('setreg', r, {})
+ end, regs)
+ eq(
+ { '', '', '', '' },
+ map(function(r)
+ return trim(call('getreg', r))
+ end, regs)
+ )
call('ctxpop')
- eq(vals, map(function(r) return trim(call('getreg', r)) end, regs))
-
- map(function(r) call('setreg', r, {}) end, regs)
- eq({'', '', '', ''},
- map(function(r) return trim(call('getreg', r)) end, regs))
+ eq(
+ vals,
+ map(function(r)
+ return trim(call('getreg', r))
+ end, regs)
+ )
+
+ map(function(r)
+ call('setreg', r, {})
+ end, regs)
+ eq(
+ { '', '', '', '' },
+ map(function(r)
+ return trim(call('getreg', r))
+ end, regs)
+ )
call('ctxpop')
- eq(vals, map(function(r) return trim(call('getreg', r)) end, regs))
+ eq(
+ vals,
+ map(function(r)
+ return trim(call('getreg', r))
+ end, regs)
+ )
end)
it('saves and restores jumplist properly', function()
- command('edit '..fname1)
+ command('edit ' .. fname1)
feed('G')
feed('gg')
- command('edit '..fname2)
+ command('edit ' .. fname2)
local jumplist = call('getjumplist')
call('ctxpush')
- call('ctxpush', {'jumps'})
+ call('ctxpush', { 'jumps' })
command('clearjumps')
- eq({{}, 0}, call('getjumplist'))
+ eq({ {}, 0 }, call('getjumplist'))
call('ctxpop')
eq(jumplist, call('getjumplist'))
command('clearjumps')
- eq({{}, 0}, call('getjumplist'))
+ eq({ {}, 0 }, call('getjumplist'))
call('ctxpop')
eq(jumplist, call('getjumplist'))
end)
it('saves and restores buffer list properly', function()
- command('edit '..fname1)
- command('edit '..fname2)
+ command('edit ' .. fname1)
+ command('edit ' .. fname2)
command('edit TEST')
local bufs = call('map', call('getbufinfo'), 'v:val.name')
call('ctxpush')
- call('ctxpush', {'bufs'})
+ call('ctxpush', { 'bufs' })
command('%bwipeout')
- eq({''}, call('map', call('getbufinfo'), 'v:val.name'))
+ eq({ '' }, call('map', call('getbufinfo'), 'v:val.name'))
call('ctxpop')
- eq({'', unpack(bufs)}, call('map', call('getbufinfo'), 'v:val.name'))
+ eq({ '', unpack(bufs) }, call('map', call('getbufinfo'), 'v:val.name'))
command('%bwipeout')
- eq({''}, call('map', call('getbufinfo'), 'v:val.name'))
+ eq({ '' }, call('map', call('getbufinfo'), 'v:val.name'))
call('ctxpop')
- eq({'', unpack(bufs)}, call('map', call('getbufinfo'), 'v:val.name'))
+ eq({ '', unpack(bufs) }, call('map', call('getbufinfo'), 'v:val.name'))
end)
it('saves and restores global variables properly', function()
- nvim('set_var', 'one', 1)
- nvim('set_var', 'Two', 2)
- nvim('set_var', 'THREE', 3)
- eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]'))
+ api.nvim_set_var('one', 1)
+ api.nvim_set_var('Two', 2)
+ api.nvim_set_var('THREE', 3)
+ eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
call('ctxpush')
- call('ctxpush', {'gvars'})
+ call('ctxpush', { 'gvars' })
- nvim('del_var', 'one')
- nvim('del_var', 'Two')
- nvim('del_var', 'THREE')
+ api.nvim_del_var('one')
+ api.nvim_del_var('Two')
+ api.nvim_del_var('THREE')
eq('Vim:E121: Undefined variable: g:one', pcall_err(eval, 'g:one'))
eq('Vim:E121: Undefined variable: g:Two', pcall_err(eval, 'g:Two'))
eq('Vim:E121: Undefined variable: g:THREE', pcall_err(eval, 'g:THREE'))
call('ctxpop')
- eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]'))
+ eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
- nvim('del_var', 'one')
- nvim('del_var', 'Two')
- nvim('del_var', 'THREE')
+ api.nvim_del_var('one')
+ api.nvim_del_var('Two')
+ api.nvim_del_var('THREE')
eq('Vim:E121: Undefined variable: g:one', pcall_err(eval, 'g:one'))
eq('Vim:E121: Undefined variable: g:Two', pcall_err(eval, 'g:Two'))
eq('Vim:E121: Undefined variable: g:THREE', pcall_err(eval, 'g:THREE'))
call('ctxpop')
- eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]'))
+ eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
end)
it('saves and restores script functions properly', function()
@@ -164,28 +190,30 @@ describe('context functions', function()
]])
eq('Hello, World!', exec_capture([[call Greet('World')]]))
- eq('Hello, World!'..
- '\nHello, One!'..
- '\nHello, Two!'..
- '\nHello, Three!',
- exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ eq(
+ 'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
+ exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
+ )
call('SaveSFuncs')
call('DeleteSFuncs')
- eq('function Greet, line 1: Vim(call):E117: Unknown function: s:greet',
- pcall_err(command, [[call Greet('World')]]))
- eq('function GreetAll, line 1: Vim(call):E117: Unknown function: s:greet_all',
- pcall_err(command, [[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ eq(
+ 'function Greet, line 1: Vim(call):E117: Unknown function: s:greet',
+ pcall_err(command, [[call Greet('World')]])
+ )
+ eq(
+ 'function GreetAll, line 1: Vim(call):E117: Unknown function: s:greet_all',
+ pcall_err(command, [[call GreetAll('World', 'One', 'Two', 'Three')]])
+ )
call('RestoreFuncs')
eq('Hello, World!', exec_capture([[call Greet('World')]]))
- eq('Hello, World!'..
- '\nHello, One!'..
- '\nHello, Two!'..
- '\nHello, Three!',
- exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ eq(
+ 'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
+ exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
+ )
end)
it('saves and restores functions properly', function()
@@ -203,28 +231,28 @@ describe('context functions', function()
]])
eq('Hello, World!', exec_capture([[call Greet('World')]]))
- eq('Hello, World!'..
- '\nHello, One!'..
- '\nHello, Two!'..
- '\nHello, Three!',
- exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ eq(
+ 'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
+ exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
+ )
- call('ctxpush', {'funcs'})
+ call('ctxpush', { 'funcs' })
command('delfunction Greet')
command('delfunction GreetAll')
eq('Vim:E117: Unknown function: Greet', pcall_err(call, 'Greet', 'World'))
- eq('Vim:E117: Unknown function: GreetAll',
- pcall_err(call, 'GreetAll', 'World', 'One', 'Two', 'Three'))
+ eq(
+ 'Vim:E117: Unknown function: GreetAll',
+ pcall_err(call, 'GreetAll', 'World', 'One', 'Two', 'Three')
+ )
call('ctxpop')
eq('Hello, World!', exec_capture([[call Greet('World')]]))
- eq('Hello, World!'..
- '\nHello, One!'..
- '\nHello, Two!'..
- '\nHello, Three!',
- exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]]))
+ eq(
+ 'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
+ exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
+ )
end)
it('errors out when context stack is empty', function()
@@ -268,41 +296,41 @@ describe('context functions', function()
it('returns context dictionary at index in context stack', function()
feed('i1<cr>2<cr>3<c-[>ddddddqahjklq')
- command('edit! '..fname1)
+ command('edit! ' .. fname1)
feed('G')
feed('gg')
- command('edit '..fname2)
- nvim('set_var', 'one', 1)
- nvim('set_var', 'Two', 2)
- nvim('set_var', 'THREE', 3)
+ command('edit ' .. fname2)
+ api.nvim_set_var('one', 1)
+ api.nvim_set_var('Two', 2)
+ api.nvim_set_var('THREE', 3)
local with_regs = {
['regs'] = {
- {['rt'] = 1, ['rc'] = {'1'}, ['n'] = 49, ['ru'] = true},
- {['rt'] = 1, ['rc'] = {'2'}, ['n'] = 50},
- {['rt'] = 1, ['rc'] = {'3'}, ['n'] = 51},
- {['rc'] = {'hjkl'}, ['n'] = 97},
- }
+ { ['rt'] = 1, ['rc'] = { '1' }, ['n'] = 49, ['ru'] = true },
+ { ['rt'] = 1, ['rc'] = { '2' }, ['n'] = 50 },
+ { ['rt'] = 1, ['rc'] = { '3' }, ['n'] = 51 },
+ { ['rc'] = { 'hjkl' }, ['n'] = 97 },
+ },
}
local with_jumps = {
- ['jumps'] = eval(([[
+ ['jumps'] = eval((([[
filter(map(add(
getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }),
'filter(
{ "f": expand("#".v:val.bufnr.":p"), "l": v:val.lnum },
{ k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
- ]]):gsub('\n', ''))
+ ]]):gsub('\n', ''))),
}
local with_bufs = {
['bufs'] = eval([[
filter(map(getbufinfo(), '{ "f": v:val.name }'), '!empty(v:val.f)')
- ]])
+ ]]),
}
local with_gvars = {
- ['gvars'] = {{'one', 1}, {'Two', 2}, {'THREE', 3}}
+ ['gvars'] = { { 'one', 1 }, { 'Two', 2 }, { 'THREE', 3 } },
}
local with_all = {
@@ -316,25 +344,25 @@ describe('context functions', function()
eq(with_all, parse_context(call('ctxget')))
eq(with_all, parse_context(call('ctxget', 0)))
- call('ctxpush', {'gvars'})
+ call('ctxpush', { 'gvars' })
eq(with_gvars, parse_context(call('ctxget')))
eq(with_gvars, parse_context(call('ctxget', 0)))
eq(with_all, parse_context(call('ctxget', 1)))
- call('ctxpush', {'bufs'})
+ call('ctxpush', { 'bufs' })
eq(with_bufs, parse_context(call('ctxget')))
eq(with_bufs, parse_context(call('ctxget', 0)))
eq(with_gvars, parse_context(call('ctxget', 1)))
eq(with_all, parse_context(call('ctxget', 2)))
- call('ctxpush', {'jumps'})
+ call('ctxpush', { 'jumps' })
eq(with_jumps, parse_context(call('ctxget')))
eq(with_jumps, parse_context(call('ctxget', 0)))
eq(with_bufs, parse_context(call('ctxget', 1)))
eq(with_gvars, parse_context(call('ctxget', 2)))
eq(with_all, parse_context(call('ctxget', 3)))
- call('ctxpush', {'regs'})
+ call('ctxpush', { 'regs' })
eq(with_regs, parse_context(call('ctxget')))
eq(with_regs, parse_context(call('ctxget', 0)))
eq(with_jumps, parse_context(call('ctxget', 1)))
@@ -368,43 +396,45 @@ describe('context functions', function()
describe('ctxset()', function()
it('errors out when index is out of bounds', function()
- eq(outofbounds, pcall_err(call, 'ctxset', {dummy = 1}))
+ eq(outofbounds, pcall_err(call, 'ctxset', { dummy = 1 }))
call('ctxpush')
- eq(outofbounds, pcall_err(call, 'ctxset', {dummy = 1}, 1))
+ eq(outofbounds, pcall_err(call, 'ctxset', { dummy = 1 }, 1))
call('ctxpop')
- eq(outofbounds, pcall_err(call, 'ctxset', {dummy = 1}, 0))
+ eq(outofbounds, pcall_err(call, 'ctxset', { dummy = 1 }, 0))
end)
it('errors when context dictionary is invalid', function()
call('ctxpush')
- eq('Vim:E474: Failed to convert list to msgpack string buffer',
- pcall_err(call, 'ctxset', { regs = { {} }, jumps = { {} } }))
+ eq(
+ 'Vim:E474: Failed to convert list to msgpack string buffer',
+ pcall_err(call, 'ctxset', { regs = { {} }, jumps = { {} } })
+ )
end)
it('sets context dictionary at index in context stack', function()
- nvim('set_var', 'one', 1)
- nvim('set_var', 'Two', 2)
- nvim('set_var', 'THREE', 3)
+ api.nvim_set_var('one', 1)
+ api.nvim_set_var('Two', 2)
+ api.nvim_set_var('THREE', 3)
call('ctxpush')
local ctx1 = call('ctxget')
- nvim('set_var', 'one', 'a')
- nvim('set_var', 'Two', 'b')
- nvim('set_var', 'THREE', 'c')
+ api.nvim_set_var('one', 'a')
+ api.nvim_set_var('Two', 'b')
+ api.nvim_set_var('THREE', 'c')
call('ctxpush')
call('ctxpush')
local ctx2 = call('ctxget')
- eq({'a', 'b' ,'c'}, eval('[g:one, g:Two, g:THREE]'))
+ eq({ 'a', 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
call('ctxset', ctx1)
call('ctxset', ctx2, 2)
call('ctxpop')
- eq({1, 2 ,3}, eval('[g:one, g:Two, g:THREE]'))
+ eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
call('ctxpop')
- eq({'a', 'b' ,'c'}, eval('[g:one, g:Two, g:THREE]'))
- nvim('set_var', 'one', 1.5)
- eq({1.5, 'b' ,'c'}, eval('[g:one, g:Two, g:THREE]'))
+ eq({ 'a', 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
+ api.nvim_set_var('one', 1.5)
+ eq({ 1.5, 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
call('ctxpop')
- eq({'a', 'b' ,'c'}, eval('[g:one, g:Two, g:THREE]'))
+ eq({ 'a', 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
end)
end)
end)
diff --git a/test/functional/vimscript/environ_spec.lua b/test/functional/vimscript/environ_spec.lua
index 52218d3cc9..0763def84e 100644
--- a/test/functional/vimscript/environ_spec.lua
+++ b/test/functional/vimscript/environ_spec.lua
@@ -1,23 +1,23 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
-local environ = helpers.funcs.environ
-local exists = helpers.funcs.exists
-local system = helpers.funcs.system
+local environ = helpers.fn.environ
+local exists = helpers.fn.exists
+local system = helpers.fn.system
local nvim_prog = helpers.nvim_prog
local command = helpers.command
local eval = helpers.eval
-local setenv = helpers.funcs.setenv
+local setenv = helpers.fn.setenv
describe('environment variables', function()
it('environ() handles empty env variable', function()
- clear({env={EMPTY_VAR=""}})
- eq("", environ()['EMPTY_VAR'])
+ clear({ env = { EMPTY_VAR = '' } })
+ eq('', environ()['EMPTY_VAR'])
eq(nil, environ()['DOES_NOT_EXIST'])
end)
it('exists() handles empty env variable', function()
- clear({env={EMPTY_VAR=""}})
+ clear({ env = { EMPTY_VAR = '' } })
eq(1, exists('$EMPTY_VAR'))
eq(0, exists('$DOES_NOT_EXIST'))
end)
@@ -46,23 +46,32 @@ describe('empty $HOME', function()
end
local function write_and_test_tilde()
- system({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--headless',
- '-c', 'write test_empty_home', '+q'})
+ system({
+ nvim_prog,
+ '-u',
+ 'NONE',
+ '-i',
+ 'NONE',
+ '--headless',
+ '-c',
+ 'write test_empty_home',
+ '+q',
+ })
eq(false, tilde_in_cwd())
end
it("'~' folder not created in cwd if $HOME and related env not defined", function()
- command("unlet $HOME")
+ command('unlet $HOME')
write_and_test_tilde()
command("let $HOMEDRIVE='C:'")
command("let $USERPROFILE='C:\\'")
write_and_test_tilde()
- command("unlet $HOMEDRIVE")
+ command('unlet $HOMEDRIVE')
write_and_test_tilde()
- command("unlet $USERPROFILE")
+ command('unlet $USERPROFILE')
write_and_test_tilde()
command("let $HOME='%USERPROFILE%'")
diff --git a/test/functional/vimscript/errorlist_spec.lua b/test/functional/vimscript/errorlist_spec.lua
index 077d816903..1e405e7e64 100644
--- a/test/functional/vimscript/errorlist_spec.lua
+++ b/test/functional/vimscript/errorlist_spec.lua
@@ -4,10 +4,10 @@ local clear = helpers.clear
local command = helpers.command
local eq = helpers.eq
local exc_exec = helpers.exc_exec
-local get_cur_win_var = helpers.curwinmeths.get_var
+local get_win_var = helpers.api.nvim_win_get_var
describe('setqflist()', function()
- local setqflist = helpers.funcs.setqflist
+ local setqflist = helpers.fn.setqflist
before_each(clear)
@@ -24,26 +24,29 @@ describe('setqflist()', function()
end)
it('sets w:quickfix_title', function()
- setqflist({''}, 'r', 'foo')
+ setqflist({ '' }, 'r', 'foo')
command('copen')
- eq('foo', get_cur_win_var('quickfix_title'))
- setqflist({}, 'r', {['title'] = 'qf_title'})
- eq('qf_title', get_cur_win_var('quickfix_title'))
+ eq('foo', get_win_var(0, 'quickfix_title'))
+ setqflist({}, 'r', { ['title'] = 'qf_title' })
+ eq('qf_title', get_win_var(0, 'quickfix_title'))
end)
it('allows string {what} for backwards compatibility', function()
setqflist({}, 'r', '5')
command('copen')
- eq('5', get_cur_win_var('quickfix_title'))
+ eq('5', get_win_var(0, 'quickfix_title'))
end)
it('requires a dict for {what}', function()
- eq('Vim(call):E715: Dictionary required', exc_exec('call setqflist([], "r", function("function"))'))
+ eq(
+ 'Vim(call):E715: Dictionary required',
+ exc_exec('call setqflist([], "r", function("function"))')
+ )
end)
end)
describe('setloclist()', function()
- local setloclist = helpers.funcs.setloclist
+ local setloclist = helpers.fn.setloclist
before_each(clear)
@@ -64,20 +67,20 @@ describe('setloclist()', function()
setloclist(1, {}, 'r', 'foo')
setloclist(2, {}, 'r', 'bar')
command('lopen')
- eq('bar', get_cur_win_var('quickfix_title'))
+ eq('bar', get_win_var(0, 'quickfix_title'))
command('lclose | wincmd w | lopen')
- eq('foo', get_cur_win_var('quickfix_title'))
+ eq('foo', get_win_var(0, 'quickfix_title'))
end)
it("doesn't crash when when window is closed in the middle #13721", function()
helpers.insert([[
hello world]])
- command("vsplit")
- command("autocmd WinLeave * :call nvim_win_close(0, v:true)")
+ command('vsplit')
+ command('autocmd WinLeave * :call nvim_win_close(0, v:true)')
- command("call setloclist(0, [])")
- command("lopen")
+ command('call setloclist(0, [])')
+ command('lopen')
helpers.assert_alive()
end)
diff --git a/test/functional/vimscript/eval_spec.lua b/test/functional/vimscript/eval_spec.lua
index ab0ffccd4d..e337959810 100644
--- a/test/functional/vimscript/eval_spec.lua
+++ b/test/functional/vimscript/eval_spec.lua
@@ -15,37 +15,39 @@ local Screen = require('test.functional.ui.screen')
local mkdir = helpers.mkdir
local clear = helpers.clear
local eq = helpers.eq
+local exec = helpers.exec
local exc_exec = helpers.exc_exec
local exec_lua = helpers.exec_lua
local exec_capture = helpers.exec_capture
local eval = helpers.eval
local command = helpers.command
local write_file = helpers.write_file
-local meths = helpers.meths
-local sleep = helpers.sleep
+local api = helpers.api
+local sleep = vim.uv.sleep
local matches = helpers.matches
local pcall_err = helpers.pcall_err
local assert_alive = helpers.assert_alive
local poke_eventloop = helpers.poke_eventloop
local feed = helpers.feed
+local expect_exit = helpers.expect_exit
describe('Up to MAX_FUNC_ARGS arguments are handled by', function()
- local max_func_args = 20 -- from eval.h
- local range = helpers.funcs.range
+ local max_func_args = 20 -- from eval.h
+ local range = helpers.fn.range
before_each(clear)
it('printf()', function()
- local printf = helpers.funcs.printf
- local rep = helpers.funcs['repeat']
+ local printf = helpers.fn.printf
+ local rep = helpers.fn['repeat']
local expected = '2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,'
- eq(expected, printf(rep('%d,', max_func_args-1), unpack(range(2, max_func_args))))
+ eq(expected, printf(rep('%d,', max_func_args - 1), unpack(range(2, max_func_args))))
local ret = exc_exec('call printf("", 2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)')
eq('Vim(call):E740: Too many arguments for function printf', ret)
end)
it('rpcnotify()', function()
- local rpcnotify = helpers.funcs.rpcnotify
+ local rpcnotify = helpers.fn.rpcnotify
local ret = rpcnotify(0, 'foo', unpack(range(3, max_func_args)))
eq(1, ret)
ret = exc_exec('call rpcnotify(0, "foo", 3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21)')
@@ -53,15 +55,15 @@ describe('Up to MAX_FUNC_ARGS arguments are handled by', function()
end)
end)
-describe("backtick expansion", function()
+describe('backtick expansion', function()
setup(function()
clear()
- mkdir("test-backticks")
- write_file("test-backticks/file1", "test file 1")
- write_file("test-backticks/file2", "test file 2")
- write_file("test-backticks/file3", "test file 3")
- mkdir("test-backticks/subdir")
- write_file("test-backticks/subdir/file4", "test file 4")
+ mkdir('test-backticks')
+ write_file('test-backticks/file1', 'test file 1')
+ write_file('test-backticks/file2', 'test file 2')
+ write_file('test-backticks/file3', 'test file 3')
+ mkdir('test-backticks/subdir')
+ write_file('test-backticks/subdir/file4', 'test file 4')
-- Long path might cause "Press ENTER" prompt; use :silent to avoid it.
command('silent cd test-backticks')
end)
@@ -72,30 +74,30 @@ describe("backtick expansion", function()
it("with default 'shell'", function()
if helpers.is_os('win') then
- command(":silent args `dir /b *2`")
+ command(':silent args `dir /b *2`')
else
- command(":silent args `echo ***2`")
+ command(':silent args `echo ***2`')
end
- eq({ "file2", }, eval("argv()"))
+ eq({ 'file2' }, eval('argv()'))
if helpers.is_os('win') then
- command(":silent args `dir /s/b *4`")
- eq({ "subdir\\file4", }, eval("map(argv(), 'fnamemodify(v:val, \":.\")')"))
+ command(':silent args `dir /s/b *4`')
+ eq({ 'subdir\\file4' }, eval('map(argv(), \'fnamemodify(v:val, ":.")\')'))
else
- command(":silent args `echo */*4`")
- eq({ "subdir/file4", }, eval("argv()"))
+ command(':silent args `echo */*4`')
+ eq({ 'subdir/file4' }, eval('argv()'))
end
end)
- it("with shell=fish", function()
+ it('with shell=fish', function()
if eval("executable('fish')") == 0 then
pending('missing "fish" command')
return
end
- command("set shell=fish")
- command(":silent args `echo ***2`")
- eq({ "file2", }, eval("argv()"))
- command(":silent args `echo */*4`")
- eq({ "subdir/file4", }, eval("argv()"))
+ command('set shell=fish')
+ command(':silent args `echo ***2`')
+ eq({ 'file2' }, eval('argv()'))
+ command(':silent args `echo */*4`')
+ eq({ 'subdir/file4' }, eval('argv()'))
end)
end)
@@ -104,7 +106,9 @@ describe('List support code', function()
local min_dur = 8
local len = 131072
- if not pending('does not actually allows interrupting with just got_int', function() end) then return end
+ if not pending('does not actually allows interrupting with just got_int', function() end) then
+ return
+ end
-- The following tests are confirmed to work with os_breakcheck() just before
-- `if (got_int) {break;}` in tv_list_copy and list_join_inner() and not to
-- work without.
@@ -117,7 +121,7 @@ describe('List support code', function()
let bl = range(%u)
let dur = reltimestr(reltime(rt))
]]):format(len))
- dur = tonumber(meths.get_var('dur'))
+ dur = tonumber(api.nvim_get_var('dur'))
if dur >= min_dur then
-- print(('Using len %u, dur %g'):format(len, dur))
break
@@ -132,7 +136,7 @@ describe('List support code', function()
feed('<C-c>')
poke_eventloop()
command('let t_dur = reltimestr(reltime(t_rt))')
- local t_dur = tonumber(meths.get_var('t_dur'))
+ local t_dur = tonumber(api.nvim_get_var('t_dur'))
if t_dur >= dur / 8 then
eq(nil, ('Took too long to cancel: %g >= %g'):format(t_dur, dur / 8))
end
@@ -143,7 +147,7 @@ describe('List support code', function()
feed('<C-c>')
poke_eventloop()
command('let t_dur = reltimestr(reltime(t_rt))')
- local t_dur = tonumber(meths.get_var('t_dur'))
+ local t_dur = tonumber(api.nvim_get_var('t_dur'))
print(('t_dur: %g'):format(t_dur))
if t_dur >= dur / 8 then
eq(nil, ('Took too long to cancel: %g >= %g'):format(t_dur, dur / 8))
@@ -151,7 +155,7 @@ describe('List support code', function()
end)
end)
-describe("uncaught exception", function()
+describe('uncaught exception', function()
before_each(clear)
it('is not forgotten #13490', function()
@@ -162,11 +166,14 @@ describe("uncaught exception", function()
-- from processing the others.
-- Only the first thrown exception should be rethrown from the :try below, though.
for i = 1, 3 do
- write_file('throw' .. i .. '.vim', ([[
+ write_file(
+ 'throw' .. i .. '.vim',
+ ([[
let result ..= '%d'
throw 'throw%d'
let result ..= 'X'
- ]]):format(i, i))
+ ]]):format(i, i)
+ )
end
finally(function()
for i = 1, 3 do
@@ -182,9 +189,9 @@ describe("uncaught exception", function()
it('multiline exception remains multiline #25350', function()
local screen = Screen.new(80, 11)
screen:set_default_attr_ids({
- [1] = {bold = true, reverse = true}; -- MsgSeparator
- [2] = {foreground = Screen.colors.White, background = Screen.colors.Red}; -- ErrorMsg
- [3] = {bold = true, foreground = Screen.colors.SeaGreen}; -- MoreMsg
+ [1] = { bold = true, reverse = true }, -- MsgSeparator
+ [2] = { foreground = Screen.colors.White, background = Screen.colors.Red }, -- ErrorMsg
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen }, -- MoreMsg
})
screen:attach()
exec_lua([[
@@ -193,7 +200,8 @@ describe("uncaught exception", function()
end
]])
feed(':try\rlua _G.Oops()\rendtry\r')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
{1: }|
:try |
: lua _G.Oops() |
@@ -205,7 +213,8 @@ describe("uncaught exception", function()
{2: [string "<nvim>"]:2: in function 'Oops'} |
{2: [string ":lua"]:1: in main chunk} |
{3:Press ENTER or type command to continue}^ |
- ]]}
+ ]],
+ }
end)
end)
@@ -215,16 +224,23 @@ describe('listing functions using :function', function()
it('works for lambda functions with <lambda> #20466', function()
command('let A = {-> 1}')
local num = exec_capture('echo A'):match("function%('<lambda>(%d+)'%)")
- eq(([[
+ eq(
+ ([[
function <lambda>%s(...)
1 return 1
- endfunction]]):format(num), exec_capture(('function <lambda>%s'):format(num)))
+ endfunction]]):format(num),
+ exec_capture(('function <lambda>%s'):format(num))
+ )
end)
it('does not crash if another function is deleted while listing', function()
local screen = Screen.new(80, 24)
screen:attach()
- matches('Vim%(function%):E454: Function list was modified$', pcall_err(exec_lua, [=[
+ matches(
+ 'Vim%(function%):E454: Function list was modified$',
+ pcall_err(
+ exec_lua,
+ [=[
vim.cmd([[
func Func1()
endfunc
@@ -245,14 +261,20 @@ describe('listing functions using :function', function()
vim.cmd('function')
vim.ui_detach(ns)
- ]=]))
+ ]=]
+ )
+ )
assert_alive()
end)
it('does not crash if the same function is deleted while listing', function()
local screen = Screen.new(80, 24)
screen:attach()
- matches('Vim%(function%):E454: Function list was modified$', pcall_err(exec_lua, [=[
+ matches(
+ 'Vim%(function%):E454: Function list was modified$',
+ pcall_err(
+ exec_lua,
+ [=[
vim.cmd([[
func Func1()
endfunc
@@ -273,7 +295,9 @@ describe('listing functions using :function', function()
vim.cmd('function')
vim.ui_detach(ns)
- ]=]))
+ ]=]
+ )
+ )
assert_alive()
end)
end)
@@ -281,7 +305,9 @@ end)
it('no double-free in garbage collection #16287', function()
clear()
-- Don't use exec() here as using a named script reproduces the issue better.
- write_file('Xgarbagecollect.vim', [[
+ write_file(
+ 'Xgarbagecollect.vim',
+ [[
func Foo() abort
let s:args = [a:000]
let foo0 = ""
@@ -304,7 +330,8 @@ it('no double-free in garbage collection #16287', function()
set updatetime=1
call Foo()
call Foo()
- ]])
+ ]]
+ )
finally(function()
os.remove('Xgarbagecollect.vim')
end)
@@ -312,3 +339,14 @@ it('no double-free in garbage collection #16287', function()
sleep(10)
assert_alive()
end)
+
+it('no heap-use-after-free with EXITFREE and partial as prompt callback', function()
+ clear()
+ exec([[
+ func PromptCallback(text)
+ endfunc
+ setlocal buftype=prompt
+ call prompt_setcallback('', funcref('PromptCallback'))
+ ]])
+ expect_exit(command, 'qall!')
+end)
diff --git a/test/functional/vimscript/executable_spec.lua b/test/functional/vimscript/executable_spec.lua
index 2b8e3f6218..1d95f6088e 100644
--- a/test/functional/vimscript/executable_spec.lua
+++ b/test/functional/vimscript/executable_spec.lua
@@ -1,7 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
local eq, clear, call, write_file, command =
- helpers.eq, helpers.clear, helpers.call, helpers.write_file,
- helpers.command
+ helpers.eq, helpers.clear, helpers.call, helpers.write_file, helpers.command
local exc_exec = helpers.exc_exec
local eval = helpers.eval
local is_os = helpers.is_os
@@ -21,9 +20,15 @@ describe('executable()', function()
if is_os('win') then
it('exepath respects shellslash', function()
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
- eq([[test\functional\fixtures\bin\null.CMD]], call('fnamemodify', call('exepath', 'null'), ':.'))
+ eq(
+ [[test\functional\fixtures\bin\null.CMD]],
+ call('fnamemodify', call('exepath', 'null'), ':.')
+ )
command('set shellslash')
- eq('test/functional/fixtures/bin/null.CMD', call('fnamemodify', call('exepath', 'null'), ':.'))
+ eq(
+ 'test/functional/fixtures/bin/null.CMD',
+ call('fnamemodify', call('exepath', 'null'), ':.')
+ )
end)
it('stdpath respects shellslash', function()
@@ -34,14 +39,18 @@ describe('executable()', function()
end
it('fails for invalid values', function()
- for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do
- eq('Vim(call):E1174: String required for argument 1',
- exc_exec('call executable('..input..')'))
+ for _, input in ipairs({ 'v:null', 'v:true', 'v:false', '{}', '[]' }) do
+ eq(
+ 'Vim(call):E1174: String required for argument 1',
+ exc_exec('call executable(' .. input .. ')')
+ )
end
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
- for _, input in ipairs({'v:null', 'v:true', 'v:false'}) do
- eq('Vim(call):E1174: String required for argument 1',
- exc_exec('call executable('..input..')'))
+ for _, input in ipairs({ 'v:null', 'v:true', 'v:false' }) do
+ eq(
+ 'Vim(call):E1174: String required for argument 1',
+ exc_exec('call executable(' .. input .. ')')
+ )
end
end)
@@ -59,8 +68,7 @@ describe('executable()', function()
-- Windows: siblings are in Nvim's "pseudo-$PATH".
local expected = is_os('win') and 1 or 0
if is_os('win') then
- eq('arg1=lemon;arg2=sky;arg3=tree;',
- call('system', sibling_exe..' lemon sky tree'))
+ eq('arg1=lemon;arg2=sky;arg3=tree;', call('system', sibling_exe .. ' lemon sky tree'))
end
eq(expected, call('executable', sibling_exe))
end)
@@ -70,9 +78,9 @@ describe('executable()', function()
clear()
write_file('Xtest_not_executable', 'non-executable file')
write_file('Xtest_executable', 'executable file (exec-bit set)')
- if not is_os('win') then -- N/A for Windows.
- call('system', {'chmod', '-x', 'Xtest_not_executable'})
- call('system', {'chmod', '+x', 'Xtest_executable'})
+ if not is_os('win') then -- N/A for Windows.
+ call('system', { 'chmod', '-x', 'Xtest_not_executable' })
+ call('system', { 'chmod', '+x', 'Xtest_executable' })
end
end)
@@ -103,144 +111,142 @@ describe('executable() (Windows)', function()
return
end
- local exts = {'bat', 'exe', 'com', 'cmd'}
+ local exts = { 'bat', 'exe', 'com', 'cmd' }
setup(function()
for _, ext in ipairs(exts) do
- write_file('test_executable_'..ext..'.'..ext, '')
+ write_file('test_executable_' .. ext .. '.' .. ext, '')
end
write_file('test_executable_zzz.zzz', '')
end)
teardown(function()
for _, ext in ipairs(exts) do
- os.remove('test_executable_'..ext..'.'..ext)
+ os.remove('test_executable_' .. ext .. '.' .. ext)
end
os.remove('test_executable_zzz.zzz')
end)
it('tries default extensions on a filename if $PATHEXT is empty', function()
-- Empty $PATHEXT defaults to ".com;.exe;.bat;.cmd".
- clear({env={PATHEXT=''}})
- for _,ext in ipairs(exts) do
- eq(1, call('executable', 'test_executable_'..ext))
+ clear({ env = { PATHEXT = '' } })
+ for _, ext in ipairs(exts) do
+ eq(1, call('executable', 'test_executable_' .. ext))
end
eq(0, call('executable', 'test_executable_zzz'))
end)
it('tries default extensions on a filepath if $PATHEXT is empty', function()
-- Empty $PATHEXT defaults to ".com;.exe;.bat;.cmd".
- clear({env={PATHEXT=''}})
- for _,ext in ipairs(exts) do
- eq(1, call('executable', '.\\test_executable_'..ext))
+ clear({ env = { PATHEXT = '' } })
+ for _, ext in ipairs(exts) do
+ eq(1, call('executable', '.\\test_executable_' .. ext))
end
eq(0, call('executable', '.\\test_executable_zzz'))
end)
it('system([…]), jobstart([…]) use $PATHEXT #9569', function()
-- Empty $PATHEXT defaults to ".com;.exe;.bat;.cmd".
- clear({env={PATHEXT=''}})
+ clear({ env = { PATHEXT = '' } })
-- Invoking `cmdscript` should find/execute `cmdscript.cmd`.
- eq('much success\n', call('system', {'test/functional/fixtures/cmdscript'}))
- assert(0 < call('jobstart', {'test/functional/fixtures/cmdscript'}))
+ eq('much success\n', call('system', { 'test/functional/fixtures/cmdscript' }))
+ assert(0 < call('jobstart', { 'test/functional/fixtures/cmdscript' }))
end)
it('full path with extension', function()
-- Empty $PATHEXT defaults to ".com;.exe;.bat;.cmd".
- clear({env={PATHEXT=''}})
+ clear({ env = { PATHEXT = '' } })
-- Some executable we can expect in the test env.
local exe = 'printargs-test'
local exedir = eval("fnamemodify(v:progpath, ':h')")
- local exepath = exedir..'/'..exe..'.exe'
+ local exepath = exedir .. '/' .. exe .. '.exe'
eq(1, call('executable', exepath))
- eq('arg1=lemon;arg2=sky;arg3=tree;',
- call('system', exepath..' lemon sky tree'))
+ eq('arg1=lemon;arg2=sky;arg3=tree;', call('system', exepath .. ' lemon sky tree'))
end)
it('full path without extension', function()
-- Empty $PATHEXT defaults to ".com;.exe;.bat;.cmd".
- clear({env={PATHEXT=''}})
+ clear({ env = { PATHEXT = '' } })
-- Some executable we can expect in the test env.
local exe = 'printargs-test'
local exedir = eval("fnamemodify(v:progpath, ':h')")
- local exepath = exedir..'/'..exe
- eq('arg1=lemon;arg2=sky;arg3=tree;',
- call('system', exepath..' lemon sky tree'))
- eq(1, call('executable', exepath))
+ local exepath = exedir .. '/' .. exe
+ eq('arg1=lemon;arg2=sky;arg3=tree;', call('system', exepath .. ' lemon sky tree'))
+ eq(1, call('executable', exepath))
end)
it('respects $PATHEXT when trying extensions on a filename', function()
- clear({env={PATHEXT='.zzz'}})
- for _,ext in ipairs(exts) do
- eq(0, call('executable', 'test_executable_'..ext))
+ clear({ env = { PATHEXT = '.zzz' } })
+ for _, ext in ipairs(exts) do
+ eq(0, call('executable', 'test_executable_' .. ext))
end
eq(1, call('executable', 'test_executable_zzz'))
end)
it('respects $PATHEXT when trying extensions on a filepath', function()
- clear({env={PATHEXT='.zzz'}})
- for _,ext in ipairs(exts) do
- eq(0, call('executable', '.\\test_executable_'..ext))
+ clear({ env = { PATHEXT = '.zzz' } })
+ for _, ext in ipairs(exts) do
+ eq(0, call('executable', '.\\test_executable_' .. ext))
end
eq(1, call('executable', '.\\test_executable_zzz'))
end)
- it("with weird $PATHEXT", function()
- clear({env={PATHEXT=';'}})
+ it('with weird $PATHEXT', function()
+ clear({ env = { PATHEXT = ';' } })
eq(0, call('executable', '.\\test_executable_zzz'))
- clear({env={PATHEXT=';;;.zzz;;'}})
+ clear({ env = { PATHEXT = ';;;.zzz;;' } })
eq(1, call('executable', '.\\test_executable_zzz'))
end)
it("unqualified filename, Unix-style 'shell'", function()
- clear({env={PATHEXT=''}})
+ clear({ env = { PATHEXT = '' } })
command('set shell=sh')
- for _,ext in ipairs(exts) do
- eq(1, call('executable', 'test_executable_'..ext..'.'..ext))
+ for _, ext in ipairs(exts) do
+ eq(1, call('executable', 'test_executable_' .. ext .. '.' .. ext))
end
eq(1, call('executable', 'test_executable_zzz.zzz'))
end)
it("relative path, Unix-style 'shell' (backslashes)", function()
- clear({env={PATHEXT=''}})
+ clear({ env = { PATHEXT = '' } })
command('set shell=bash.exe')
- for _,ext in ipairs(exts) do
- eq(1, call('executable', '.\\test_executable_'..ext..'.'..ext))
- eq(1, call('executable', './test_executable_'..ext..'.'..ext))
+ for _, ext in ipairs(exts) do
+ eq(1, call('executable', '.\\test_executable_' .. ext .. '.' .. ext))
+ eq(1, call('executable', './test_executable_' .. ext .. '.' .. ext))
end
eq(1, call('executable', '.\\test_executable_zzz.zzz'))
eq(1, call('executable', './test_executable_zzz.zzz'))
end)
it('unqualified filename, $PATHEXT contains dot', function()
- clear({env={PATHEXT='.;.zzz'}})
- for _,ext in ipairs(exts) do
- eq(1, call('executable', 'test_executable_'..ext..'.'..ext))
+ clear({ env = { PATHEXT = '.;.zzz' } })
+ for _, ext in ipairs(exts) do
+ eq(1, call('executable', 'test_executable_' .. ext .. '.' .. ext))
end
eq(1, call('executable', 'test_executable_zzz.zzz'))
- clear({env={PATHEXT='.zzz;.'}})
- for _,ext in ipairs(exts) do
- eq(1, call('executable', 'test_executable_'..ext..'.'..ext))
+ clear({ env = { PATHEXT = '.zzz;.' } })
+ for _, ext in ipairs(exts) do
+ eq(1, call('executable', 'test_executable_' .. ext .. '.' .. ext))
end
eq(1, call('executable', 'test_executable_zzz.zzz'))
end)
it('relative path, $PATHEXT contains dot (backslashes)', function()
- clear({env={PATHEXT='.;.zzz'}})
- for _,ext in ipairs(exts) do
- eq(1, call('executable', '.\\test_executable_'..ext..'.'..ext))
- eq(1, call('executable', './test_executable_'..ext..'.'..ext))
+ clear({ env = { PATHEXT = '.;.zzz' } })
+ for _, ext in ipairs(exts) do
+ eq(1, call('executable', '.\\test_executable_' .. ext .. '.' .. ext))
+ eq(1, call('executable', './test_executable_' .. ext .. '.' .. ext))
end
eq(1, call('executable', '.\\test_executable_zzz.zzz'))
eq(1, call('executable', './test_executable_zzz.zzz'))
end)
it('ignores case of extension', function()
- clear({env={PATHEXT='.ZZZ'}})
+ clear({ env = { PATHEXT = '.ZZZ' } })
eq(1, call('executable', 'test_executable_zzz.zzz'))
end)
it('relative path does not search $PATH', function()
- clear({env={PATHEXT=''}})
+ clear({ env = { PATHEXT = '' } })
eq(0, call('executable', './System32/notepad.exe'))
eq(0, call('executable', '.\\System32\\notepad.exe'))
eq(0, call('executable', '../notepad.exe'))
diff --git a/test/functional/vimscript/execute_spec.lua b/test/functional/vimscript/execute_spec.lua
index bb28938708..29488ed31c 100644
--- a/test/functional/vimscript/execute_spec.lua
+++ b/test/functional/vimscript/execute_spec.lua
@@ -5,7 +5,7 @@ local clear = helpers.clear
local source = helpers.source
local exc_exec = helpers.exc_exec
local pcall_err = helpers.pcall_err
-local funcs = helpers.funcs
+local fn = helpers.fn
local Screen = require('test.functional.ui.screen')
local command = helpers.command
local feed = helpers.feed
@@ -22,16 +22,16 @@ describe('execute()', function()
silent! messages
redir END
]])
- eq(eval('g:__redir_output'), funcs.execute('messages'))
+ eq(eval('g:__redir_output'), fn.execute('messages'))
end)
it('captures the concatenated outputs of a List of commands', function()
- eq("foobar", funcs.execute({'echon "foo"', 'echon "bar"'}))
- eq("\nfoo\nbar", funcs.execute({'echo "foo"', 'echo "bar"'}))
+ eq('foobar', fn.execute({ 'echon "foo"', 'echon "bar"' }))
+ eq('\nfoo\nbar', fn.execute({ 'echo "foo"', 'echo "bar"' }))
end)
it('supports nested execute("execute(...)")', function()
- eq('42', funcs.execute([[echon execute("echon execute('echon 42')")]]))
+ eq('42', fn.execute([[echon execute("echon execute('echon 42')")]]))
end)
it('supports nested :redir to a variable', function()
@@ -54,7 +54,7 @@ describe('execute()', function()
return a
endfunction
]])
- eq('top1bar1foobar2bar3', funcs.execute('echon "top1"|call g:Bar()'))
+ eq('top1bar1foobar2bar3', fn.execute('echon "top1"|call g:Bar()'))
end)
it('supports nested :redir to a register', function()
@@ -76,17 +76,17 @@ describe('execute()', function()
return @a
endfunction
]])
- eq('top1bar1foobar2bar3', funcs.execute('echon "top1"|call g:Bar()'))
+ eq('top1bar1foobar2bar3', fn.execute('echon "top1"|call g:Bar()'))
-- :redir itself doesn't nest, so the redirection ends in g:Foo
eq('bar1foo', eval('@a'))
end)
it('captures a transformed string', function()
- eq('^A', funcs.execute('echon "\\<C-a>"'))
+ eq('^A', fn.execute('echon "\\<C-a>"'))
end)
it('returns empty string if the argument list is empty', function()
- eq('', funcs.execute({}))
+ eq('', fn.execute({}))
eq(0, exc_exec('let g:ret = execute(v:_null_list)'))
eq('', eval('g:ret'))
end)
@@ -104,27 +104,31 @@ describe('execute()', function()
end)
it('captures output with highlights', function()
- eq('\nErrorMsg xxx ctermfg=15 ctermbg=1 guifg=White guibg=Red',
- eval('execute("hi ErrorMsg")'))
+ eq(
+ '\nErrorMsg xxx ctermfg=15 ctermbg=1 guifg=White guibg=Red',
+ eval('execute("hi ErrorMsg")')
+ )
end)
it('does not corrupt the command display #5422', function()
local screen = Screen.new(70, 7)
screen:attach()
feed(':echo execute("hi ErrorMsg")<CR>')
- screen:expect([[
+ screen:expect(
+ [[
|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
{2: }|
|
ErrorMsg xxx ctermfg=15 ctermbg=1 guifg=White guibg=Red |
{3:Press ENTER or type command to continue}^ |
- ]], {
- [1] = {bold = true, foreground = Screen.colors.Blue1},
- [2] = {bold = true, reverse = true},
- [3] = {bold = true, foreground = Screen.colors.SeaGreen4},
- })
+ ]],
+ {
+ [1] = { bold = true, foreground = Screen.colors.Blue1 },
+ [2] = { bold = true, reverse = true },
+ [3] = { bold = true, foreground = Screen.colors.SeaGreen4 },
+ }
+ )
feed('<CR>')
end)
@@ -187,30 +191,21 @@ describe('execute()', function()
feed([[:call Test1()<cr>]])
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
ABCD |
]])
feed([[:call Test2()<cr>]])
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
1234ABCD |
]])
feed([[:call Test3()<cr>]])
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
1234ABCDXZYZ |
]])
@@ -231,10 +226,7 @@ describe('execute()', function()
feed([[:call Test5()<cr>]])
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*4
1234ABCD |
]])
@@ -263,7 +255,7 @@ describe('execute()', function()
-- with how nvim currently displays the output.
it('captures shell-command output', function()
local win_lf = is_os('win') and '\13' or ''
- eq('\n:!echo foo\r\n\nfoo'..win_lf..'\n', funcs.execute('!echo foo'))
+ eq('\n:!echo foo\r\n\nfoo' .. win_lf .. '\n', fn.execute('!echo foo'))
end)
describe('{silent} argument', function()
@@ -273,9 +265,7 @@ describe('execute()', function()
command('let g:mes = execute("echon 42", "")')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
42 |
]])
eq('42', eval('g:mes'))
@@ -283,10 +273,14 @@ describe('execute()', function()
it('gives E493 instead of prompting on backwards range for ""', function()
command('split')
- eq('Vim(windo):E493: Backwards range given: 2,1windo echo',
- pcall_err(funcs.execute, '2,1windo echo', ''))
- eq('Vim(windo):E493: Backwards range given: 2,1windo echo',
- pcall_err(funcs.execute, {'2,1windo echo'}, ''))
+ eq(
+ 'Vim(windo):E493: Backwards range given: 2,1windo echo',
+ pcall_err(fn.execute, '2,1windo echo', '')
+ )
+ eq(
+ 'Vim(windo):E493: Backwards range given: 2,1windo echo',
+ pcall_err(fn.execute, { '2,1windo echo' }, '')
+ )
end)
it('captures but does not display output for "silent"', function()
@@ -295,21 +289,20 @@ describe('execute()', function()
command('let g:mes = execute("echon 42")')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
]])
eq('42', eval('g:mes'))
command('let g:mes = execute("echon 13", "silent")')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
^ |
- ~ |
- ~ |
- ~ |
+ ~ |*3
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
eq('13', eval('g:mes'))
end)
diff --git a/test/functional/vimscript/exepath_spec.lua b/test/functional/vimscript/exepath_spec.lua
index da3d61cbe0..01033a2140 100644
--- a/test/functional/vimscript/exepath_spec.lua
+++ b/test/functional/vimscript/exepath_spec.lua
@@ -1,6 +1,5 @@
local helpers = require('test.functional.helpers')(after_each)
-local eq, clear, call =
- helpers.eq, helpers.clear, helpers.call
+local eq, clear, call = helpers.eq, helpers.clear, helpers.call
local command = helpers.command
local exc_exec = helpers.exc_exec
local matches = helpers.matches
@@ -14,20 +13,26 @@ local find_dummies = function(ext_pat)
matches('null' .. ext_pat, call('exepath', 'null'))
matches('true' .. ext_pat, call('exepath', 'true'))
matches('false' .. ext_pat, call('exepath', 'false'))
- command("let $PATH = '"..tmp_path.."'")
+ command("let $PATH = '" .. tmp_path .. "'")
end
describe('exepath()', function()
before_each(clear)
it('fails for invalid values', function()
- for _, input in ipairs({'v:null', 'v:true', 'v:false', '{}', '[]'}) do
- eq('Vim(call):E1174: String required for argument 1', exc_exec('call exepath('..input..')'))
+ for _, input in ipairs({ 'v:null', 'v:true', 'v:false', '{}', '[]' }) do
+ eq(
+ 'Vim(call):E1174: String required for argument 1',
+ exc_exec('call exepath(' .. input .. ')')
+ )
end
eq('Vim(call):E1175: Non-empty string required for argument 1', exc_exec('call exepath("")'))
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
- for _, input in ipairs({'v:null', 'v:true', 'v:false'}) do
- eq('Vim(call):E1174: String required for argument 1', exc_exec('call exepath('..input..')'))
+ for _, input in ipairs({ 'v:null', 'v:true', 'v:false' }) do
+ eq(
+ 'Vim(call):E1174: String required for argument 1',
+ exc_exec('call exepath(' .. input .. ')')
+ )
end
end)
@@ -40,24 +45,30 @@ describe('exepath()', function()
it('append extension if omitted', function()
local filename = 'cmd'
local pathext = '.exe'
- clear({env={PATHEXT=pathext}})
- eq(call('exepath', filename..pathext), call('exepath', filename))
+ clear({ env = { PATHEXT = pathext } })
+ eq(call('exepath', filename .. pathext), call('exepath', filename))
end)
- it('returns file WITH extension if files both with and without extension exist in $PATH', function()
- local ext_pat = '%.CMD$'
- find_dummies(ext_pat)
- set_shell_powershell()
- find_dummies(ext_pat)
- end)
+ it(
+ 'returns file WITH extension if files both with and without extension exist in $PATH',
+ function()
+ local ext_pat = '%.CMD$'
+ find_dummies(ext_pat)
+ set_shell_powershell()
+ find_dummies(ext_pat)
+ end
+ )
else
it('returns 1 for commands in $PATH (not Windows)', function()
local exe = 'ls'
matches(exe .. '$', call('exepath', exe))
end)
- it('returns file WITHOUT extension if files both with and without extension exist in $PATH', function()
- find_dummies('$')
- end)
+ it(
+ 'returns file WITHOUT extension if files both with and without extension exist in $PATH',
+ function()
+ find_dummies('$')
+ end
+ )
end
end)
diff --git a/test/functional/vimscript/fnamemodify_spec.lua b/test/functional/vimscript/fnamemodify_spec.lua
index c3ecdd853c..4a134fe23c 100644
--- a/test/functional/vimscript/fnamemodify_spec.lua
+++ b/test/functional/vimscript/fnamemodify_spec.lua
@@ -1,8 +1,8 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
-local fnamemodify = helpers.funcs.fnamemodify
-local getcwd = helpers.funcs.getcwd
+local fnamemodify = helpers.fn.fnamemodify
+local getcwd = helpers.fn.getcwd
local command = helpers.command
local write_file = helpers.write_file
local alter_slashes = helpers.alter_slashes
@@ -31,7 +31,7 @@ describe('fnamemodify()', function()
eq(root, fnamemodify([[\]], ':p:h'))
eq(root, fnamemodify([[\]], ':p'))
command('set shellslash')
- root = string.sub(root, 1, -2)..'/'
+ root = string.sub(root, 1, -2) .. '/'
eq(root, fnamemodify([[\]], ':p:h'))
eq(root, fnamemodify([[\]], ':p'))
eq(root, fnamemodify([[/]], ':p:h'))
@@ -44,7 +44,7 @@ describe('fnamemodify()', function()
end)
it('handles examples from ":help filename-modifiers"', function()
- local filename = "src/version.c"
+ local filename = 'src/version.c'
local cwd = getcwd()
eq_slashconvert(cwd .. '/src/version.c', fnamemodify(filename, ':p'))
@@ -70,7 +70,7 @@ describe('fnamemodify()', function()
end)
it('handles advanced examples from ":help filename-modifiers"', function()
- local filename = "src/version.c.gz"
+ local filename = 'src/version.c.gz'
eq('gz', fnamemodify(filename, ':e'))
eq('c.gz', fnamemodify(filename, ':e:e'))
diff --git a/test/functional/vimscript/getline_spec.lua b/test/functional/vimscript/getline_spec.lua
index 3c56bde094..08e7711b8c 100644
--- a/test/functional/vimscript/getline_spec.lua
+++ b/test/functional/vimscript/getline_spec.lua
@@ -8,7 +8,7 @@ local expect = helpers.expect
describe('getline()', function()
before_each(function()
clear()
- call('setline', 1, {'a', 'b', 'c'})
+ call('setline', 1, { 'a', 'b', 'c' })
expect([[
a
b
@@ -33,7 +33,7 @@ describe('getline()', function()
end)
it('returns value of valid range', function()
- eq({'a', 'b'}, call('getline', 1, 2))
- eq({'a', 'b', 'c'}, call('getline', 1, 4))
+ eq({ 'a', 'b' }, call('getline', 1, 2))
+ eq({ 'a', 'b', 'c' }, call('getline', 1, 4))
end)
end)
diff --git a/test/functional/vimscript/glob_spec.lua b/test/functional/vimscript/glob_spec.lua
index 948a63f050..77351f95fa 100644
--- a/test/functional/vimscript/glob_spec.lua
+++ b/test/functional/vimscript/glob_spec.lua
@@ -1,4 +1,3 @@
-local luv = require('luv')
local helpers = require('test.functional.helpers')(after_each)
local clear, command, eval, eq = helpers.clear, helpers.command, helpers.eval, helpers.eq
local mkdir = helpers.mkdir
@@ -12,14 +11,14 @@ before_each(function()
end)
after_each(function()
- luv.fs_rmdir('test-glob')
+ vim.uv.fs_rmdir('test-glob')
end)
describe('glob()', function()
it("glob('.*') returns . and .. ", function()
- eq({'.', '..'}, eval("glob('.*', 0, 1)"))
+ eq({ '.', '..' }, eval("glob('.*', 0, 1)"))
-- Do it again to verify scandir_next_with_dots() internal state.
- eq({'.', '..'}, eval("glob('.*', 0, 1)"))
+ eq({ '.', '..' }, eval("glob('.*', 0, 1)"))
end)
it("glob('*') returns an empty list ", function()
eq({}, eval("glob('*', 0, 1)"))
diff --git a/test/functional/vimscript/has_spec.lua b/test/functional/vimscript/has_spec.lua
index 78a761d370..82b3db5b67 100644
--- a/test/functional/vimscript/has_spec.lua
+++ b/test/functional/vimscript/has_spec.lua
@@ -3,7 +3,7 @@ local Screen = require('test.functional.ui.screen')
local clear = helpers.clear
local connect = helpers.connect
local eq = helpers.eq
-local funcs = helpers.funcs
+local fn = helpers.fn
local is_os = helpers.is_os
local nvim_prog = helpers.nvim_prog
@@ -11,85 +11,83 @@ describe('has()', function()
before_each(clear)
it('"nvim-x.y.z"', function()
- eq(0, funcs.has("nvim-"))
- eq(0, funcs.has("nvim- "))
- eq(0, funcs.has("nvim- \t "))
- eq(0, funcs.has("nvim-0. 1. 1"))
- eq(0, funcs.has("nvim-0. 1.1"))
- eq(0, funcs.has("nvim-0.1. 1"))
- eq(0, funcs.has("nvim-a"))
- eq(0, funcs.has("nvim-a.b.c"))
- eq(0, funcs.has("nvim-0.b.c"))
- eq(0, funcs.has("nvim-0.0.c"))
- eq(0, funcs.has("nvim-0.b.0"))
- eq(0, funcs.has("nvim-a.b.0"))
- eq(0, funcs.has("nvim-.0.0.0"))
- eq(0, funcs.has("nvim-.0"))
- eq(0, funcs.has("nvim-0."))
- eq(0, funcs.has("nvim-0.."))
- eq(0, funcs.has("nvim-."))
- eq(0, funcs.has("nvim-.."))
- eq(0, funcs.has("nvim-..."))
- eq(0, funcs.has("nvim-42"))
- eq(0, funcs.has("nvim-9999"))
- eq(0, funcs.has("nvim-99.001.05"))
+ eq(0, fn.has('nvim-'))
+ eq(0, fn.has('nvim- '))
+ eq(0, fn.has('nvim- \t '))
+ eq(0, fn.has('nvim-0. 1. 1'))
+ eq(0, fn.has('nvim-0. 1.1'))
+ eq(0, fn.has('nvim-0.1. 1'))
+ eq(0, fn.has('nvim-a'))
+ eq(0, fn.has('nvim-a.b.c'))
+ eq(0, fn.has('nvim-0.b.c'))
+ eq(0, fn.has('nvim-0.0.c'))
+ eq(0, fn.has('nvim-0.b.0'))
+ eq(0, fn.has('nvim-a.b.0'))
+ eq(0, fn.has('nvim-.0.0.0'))
+ eq(0, fn.has('nvim-.0'))
+ eq(0, fn.has('nvim-0.'))
+ eq(0, fn.has('nvim-0..'))
+ eq(0, fn.has('nvim-.'))
+ eq(0, fn.has('nvim-..'))
+ eq(0, fn.has('nvim-...'))
+ eq(0, fn.has('nvim-42'))
+ eq(0, fn.has('nvim-9999'))
+ eq(0, fn.has('nvim-99.001.05'))
- eq(1, funcs.has("nvim"))
- eq(1, funcs.has("nvim-0"))
- eq(1, funcs.has("nvim-0.1"))
- eq(1, funcs.has("nvim-0.0.0"))
- eq(1, funcs.has("nvim-0.1.1."))
- eq(1, funcs.has("nvim-0.1.1.abc"))
- eq(1, funcs.has("nvim-0.1.1.."))
- eq(1, funcs.has("nvim-0.1.1.. .."))
- eq(1, funcs.has("nvim-0.1.1.... "))
- eq(1, funcs.has("nvim-0.0.0"))
- eq(1, funcs.has("nvim-0.0.1"))
- eq(1, funcs.has("nvim-0.1.0"))
- eq(1, funcs.has("nvim-0.1.1"))
- eq(1, funcs.has("nvim-0.1.5"))
- eq(1, funcs.has("nvim-0000.001.05"))
- eq(1, funcs.has("nvim-0.01.005"))
- eq(1, funcs.has("nvim-00.001.05"))
+ eq(1, fn.has('nvim'))
+ eq(1, fn.has('nvim-0'))
+ eq(1, fn.has('nvim-0.1'))
+ eq(1, fn.has('nvim-0.0.0'))
+ eq(1, fn.has('nvim-0.1.1.'))
+ eq(1, fn.has('nvim-0.1.1.abc'))
+ eq(1, fn.has('nvim-0.1.1..'))
+ eq(1, fn.has('nvim-0.1.1.. ..'))
+ eq(1, fn.has('nvim-0.1.1.... '))
+ eq(1, fn.has('nvim-0.0.0'))
+ eq(1, fn.has('nvim-0.0.1'))
+ eq(1, fn.has('nvim-0.1.0'))
+ eq(1, fn.has('nvim-0.1.1'))
+ eq(1, fn.has('nvim-0.1.5'))
+ eq(1, fn.has('nvim-0000.001.05'))
+ eq(1, fn.has('nvim-0.01.005'))
+ eq(1, fn.has('nvim-00.001.05'))
end)
it('"unnamedplus"', function()
- if (not is_os('win')) and funcs.has("clipboard") == 1 then
- eq(1, funcs.has("unnamedplus"))
+ if (not is_os('win')) and fn.has('clipboard') == 1 then
+ eq(1, fn.has('unnamedplus'))
else
- eq(0, funcs.has("unnamedplus"))
+ eq(0, fn.has('unnamedplus'))
end
end)
it('"wsl"', function()
- local luv = require('luv')
- local is_wsl =
- luv.os_uname()['release']:lower():match('microsoft') and true or false
+ local is_wsl = vim.uv.os_uname()['release']:lower():match('microsoft') and true or false
if is_wsl then
- eq(1, funcs.has('wsl'))
+ eq(1, fn.has('wsl'))
else
- eq(0, funcs.has('wsl'))
+ eq(0, fn.has('wsl'))
end
end)
it('"gui_running"', function()
- eq(0, funcs.has('gui_running'))
- local tui = Screen.new(50,15)
- local gui_session = connect(funcs.serverstart())
- local gui = Screen.new(50,15)
- eq(0, funcs.has('gui_running'))
- tui:attach({ext_linegrid=true, rgb=true, stdin_tty=true, stdout_tty=true})
- gui:attach({ext_multigrid=true, rgb=true}, gui_session)
- eq(1, funcs.has('gui_running'))
+ eq(0, fn.has('gui_running'))
+ local tui = Screen.new(50, 15)
+ local gui_session = connect(fn.serverstart())
+ local gui = Screen.new(50, 15)
+ eq(0, fn.has('gui_running'))
+ tui:attach({ ext_linegrid = true, rgb = true, stdin_tty = true, stdout_tty = true })
+ gui:attach({ ext_multigrid = true, rgb = true }, gui_session)
+ eq(1, fn.has('gui_running'))
tui:detach()
- eq(1, funcs.has('gui_running'))
+ eq(1, fn.has('gui_running'))
gui:detach()
- eq(0, funcs.has('gui_running'))
+ eq(0, fn.has('gui_running'))
end)
it('does not change v:shell_error', function()
- funcs.system({nvim_prog, '-es', '+73cquit'})
- funcs.has('python3') -- use a call whose implementation shells out
- eq(73, funcs.eval('v:shell_error'))
+ fn.system({ nvim_prog, '-es', '+73cquit' })
+ fn.has('python3') -- use a call whose implementation shells out
+ eq(73, fn.eval('v:shell_error'))
end)
end)
diff --git a/test/functional/vimscript/hostname_spec.lua b/test/functional/vimscript/hostname_spec.lua
index 7d4baa7213..62520e8222 100644
--- a/test/functional/vimscript/hostname_spec.lua
+++ b/test/functional/vimscript/hostname_spec.lua
@@ -13,8 +13,10 @@ describe('hostname()', function()
ok(string.len(actual) > 0)
if call('executable', 'hostname') == 1 then
local expected = string.gsub(call('system', 'hostname'), '[\n\r]', '')
- eq((is_os('win') and expected:upper() or expected),
- (is_os('win') and actual:upper() or actual))
+ eq(
+ (is_os('win') and expected:upper() or expected),
+ (is_os('win') and actual:upper() or actual)
+ )
end
end)
end)
diff --git a/test/functional/vimscript/input_spec.lua b/test/functional/vimscript/input_spec.lua
index e1179d29cc..b749d5a7f0 100644
--- a/test/functional/vimscript/input_spec.lua
+++ b/test/functional/vimscript/input_spec.lua
@@ -3,14 +3,14 @@ local Screen = require('test.functional.ui.screen')
local eq = helpers.eq
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
local clear = helpers.clear
local source = helpers.source
local command = helpers.command
local exc_exec = helpers.exc_exec
local pcall_err = helpers.pcall_err
local async_meths = helpers.async_meths
-local NIL = helpers.NIL
+local NIL = vim.NIL
local screen
@@ -55,14 +55,14 @@ before_each(function()
endfunction
]])
screen:set_default_attr_ids({
- EOB={bold = true, foreground = Screen.colors.Blue1},
- T={foreground=Screen.colors.Red},
- RBP1={background=Screen.colors.Red},
- RBP2={background=Screen.colors.Yellow},
- RBP3={background=Screen.colors.Green},
- RBP4={background=Screen.colors.Blue},
- SEP={bold = true, reverse = true},
- CONFIRM={bold = true, foreground = Screen.colors.SeaGreen4},
+ EOB = { bold = true, foreground = Screen.colors.Blue1 },
+ T = { foreground = Screen.colors.Red },
+ RBP1 = { background = Screen.colors.Red },
+ RBP2 = { background = Screen.colors.Yellow },
+ RBP3 = { background = Screen.colors.Green },
+ RBP4 = { background = Screen.colors.Blue },
+ SEP = { bold = true, reverse = true },
+ CONFIRM = { bold = true, foreground = Screen.colors.SeaGreen4 },
})
end)
@@ -89,9 +89,7 @@ describe('input()', function()
command('redraw!')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:Foo}^ |
]])
end)
@@ -100,144 +98,125 @@ describe('input()', function()
feed([[:call input(1, 2)<CR>]])
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:1}2^ |
]])
feed('<BS>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:1}^ |
]])
end)
it('allows unequal numeric values when using {opts} dictionary', function()
command('echohl Test')
- meths.set_var('opts', {prompt=1, default=2, cancelreturn=3})
+ api.nvim_set_var('opts', { prompt = 1, default = 2, cancelreturn = 3 })
feed([[:echo input(opts)<CR>]])
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:1}2^ |
]])
feed('<BS>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:1}^ |
]])
feed('<Esc>')
screen:expect([[
^ |
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:3} |
]])
end)
it('works with redraw', function()
command('echohl Test')
- meths.set_var('opts', {prompt='Foo>', default='Bar'})
+ api.nvim_set_var('opts', { prompt = 'Foo>', default = 'Bar' })
feed([[:echo inputdialog(opts)<CR>]])
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:Foo>}Bar^ |
]])
command('mode')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:Foo>}Bar^ |
- ]], reset=true}
+ ]],
+ reset = true,
+ }
feed('<BS>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:Foo>}Ba^ |
]])
command('mode')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:Foo>}Ba^ |
- ]], reset=true}
+ ]],
+ reset = true,
+ }
end)
it('allows omitting everything with dictionary argument', function()
command('echohl Test')
feed([[:call input({})<CR>]])
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
^ |
]])
end)
it('supports completion', function()
feed(':let var = input("", "", "custom,CustomCompl")<CR>')
feed('<Tab><CR>')
- eq('TEST', meths.get_var('var'))
+ eq('TEST', api.nvim_get_var('var'))
feed(':let var = input({"completion": "customlist,CustomListCompl"})<CR>')
feed('<Tab><CR>')
- eq('FOO', meths.get_var('var'))
+ eq('FOO', api.nvim_get_var('var'))
end)
it('supports cancelreturn', function()
feed(':let var = input({"cancelreturn": "BAR"})<CR>')
feed('<Esc>')
- eq('BAR', meths.get_var('var'))
+ eq('BAR', api.nvim_get_var('var'))
feed(':let var = input({"cancelreturn": []})<CR>')
feed('<Esc>')
- eq({}, meths.get_var('var'))
+ eq({}, api.nvim_get_var('var'))
feed(':let var = input({"cancelreturn": v:false})<CR>')
feed('<Esc>')
- eq(false, meths.get_var('var'))
+ eq(false, api.nvim_get_var('var'))
feed(':let var = input({"cancelreturn": v:null})<CR>')
feed('<Esc>')
- eq(NIL, meths.get_var('var'))
+ eq(NIL, api.nvim_get_var('var'))
end)
it('supports default string', function()
feed(':let var = input("", "DEF1")<CR>')
feed('<CR>')
- eq('DEF1', meths.get_var('var'))
+ eq('DEF1', api.nvim_get_var('var'))
feed(':let var = input({"default": "DEF2"})<CR>')
feed('<CR>')
- eq('DEF2', meths.get_var('var'))
+ eq('DEF2', api.nvim_get_var('var'))
end)
it('errors out on invalid inputs', function()
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call input([])'))
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call input("", [])'))
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call input("", "", [])'))
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call input({"prompt": []})'))
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call input({"default": []})'))
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call input({"completion": []})'))
- eq('Vim(call):E5050: {opts} must be the only argument',
- exc_exec('call input({}, "default")'))
- eq('Vim(call):E118: Too many arguments for function: input',
- exc_exec('call input("prompt> ", "default", "file", "extra")'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call input([])'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call input("", [])'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call input("", "", [])'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call input({"prompt": []})'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call input({"default": []})'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call input({"completion": []})'))
+ eq('Vim(call):E5050: {opts} must be the only argument', exc_exec('call input({}, "default")'))
+ eq(
+ 'Vim(call):E118: Too many arguments for function: input',
+ exc_exec('call input("prompt> ", "default", "file", "extra")')
+ )
end)
it('supports highlighting', function()
command('nnoremap <expr> X input({"highlight": "RainBowParens"})[-1]')
@@ -245,9 +224,7 @@ describe('input()', function()
feed('(())')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{RBP1:(}{RBP2:()}{RBP1:)}^ |
]])
end)
@@ -294,9 +271,7 @@ describe('inputdialog()', function()
command('redraw!')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:Foo}^ |
]])
end)
@@ -305,135 +280,119 @@ describe('inputdialog()', function()
feed([[:call inputdialog(1, 2)<CR>]])
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:1}2^ |
]])
feed('<BS>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:1}^ |
]])
end)
it('allows unequal numeric values when using {opts} dictionary', function()
command('echohl Test')
- meths.set_var('opts', {prompt=1, default=2, cancelreturn=3})
+ api.nvim_set_var('opts', { prompt = 1, default = 2, cancelreturn = 3 })
feed([[:echo input(opts)<CR>]])
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:1}2^ |
]])
feed('<BS>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:1}^ |
]])
feed('<Esc>')
screen:expect([[
^ |
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:3} |
]])
end)
it('works with redraw', function()
command('echohl Test')
- meths.set_var('opts', {prompt='Foo>', default='Bar'})
+ api.nvim_set_var('opts', { prompt = 'Foo>', default = 'Bar' })
feed([[:echo input(opts)<CR>]])
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:Foo>}Bar^ |
]])
command('mode')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:Foo>}Bar^ |
- ]], reset=true}
+ ]],
+ reset = true,
+ }
feed('<BS>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:Foo>}Ba^ |
]])
command('mode')
- screen:expect{grid=[[
+ screen:expect {
+ grid = [[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{T:Foo>}Ba^ |
- ]], reset=true}
+ ]],
+ reset = true,
+ }
end)
it('allows omitting everything with dictionary argument', function()
command('echohl Test')
feed(':echo inputdialog({})<CR>')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
^ |
]])
end)
it('supports completion', function()
feed(':let var = inputdialog({"completion": "customlist,CustomListCompl"})<CR>')
feed('<Tab><CR>')
- eq('FOO', meths.get_var('var'))
+ eq('FOO', api.nvim_get_var('var'))
end)
it('supports cancelreturn', function()
feed(':let var = inputdialog("", "", "CR1")<CR>')
feed('<Esc>')
- eq('CR1', meths.get_var('var'))
+ eq('CR1', api.nvim_get_var('var'))
feed(':let var = inputdialog({"cancelreturn": "BAR"})<CR>')
feed('<Esc>')
- eq('BAR', meths.get_var('var'))
+ eq('BAR', api.nvim_get_var('var'))
end)
it('supports default string', function()
feed(':let var = inputdialog("", "DEF1")<CR>')
feed('<CR>')
- eq('DEF1', meths.get_var('var'))
+ eq('DEF1', api.nvim_get_var('var'))
feed(':let var = inputdialog({"default": "DEF2"})<CR>')
feed('<CR>')
- eq('DEF2', meths.get_var('var'))
+ eq('DEF2', api.nvim_get_var('var'))
end)
it('errors out on invalid inputs', function()
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call inputdialog([])'))
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call inputdialog("", [])'))
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call inputdialog("", "", [])'))
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call inputdialog({"prompt": []})'))
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call inputdialog({"default": []})'))
- eq('Vim(call):E730: Using a List as a String',
- exc_exec('call inputdialog({"completion": []})'))
- eq('Vim(call):E5050: {opts} must be the only argument',
- exc_exec('call inputdialog({}, "default")'))
- eq('Vim(call):E118: Too many arguments for function: inputdialog',
- exc_exec('call inputdialog("prompt> ", "default", "file", "extra")'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call inputdialog([])'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call inputdialog("", [])'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call inputdialog("", "", [])'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call inputdialog({"prompt": []})'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call inputdialog({"default": []})'))
+ eq('Vim(call):E730: Using a List as a String', exc_exec('call inputdialog({"completion": []})'))
+ eq(
+ 'Vim(call):E5050: {opts} must be the only argument',
+ exc_exec('call inputdialog({}, "default")')
+ )
+ eq(
+ 'Vim(call):E118: Too many arguments for function: inputdialog',
+ exc_exec('call inputdialog("prompt> ", "default", "file", "extra")')
+ )
end)
it('supports highlighting', function()
command('nnoremap <expr> X inputdialog({"highlight": "RainBowParens"})[-1]')
@@ -441,9 +400,7 @@ describe('inputdialog()', function()
feed('(())')
screen:expect([[
|
- {EOB:~ }|
- {EOB:~ }|
- {EOB:~ }|
+ {EOB:~ }|*3
{RBP1:(}{RBP2:()}{RBP1:)}^ |
]])
end)
@@ -452,84 +409,91 @@ end)
describe('confirm()', function()
-- oldtest: Test_confirm()
it('works', function()
- meths.set_option_value('more', false, {}) -- Avoid hit-enter prompt
- meths.set_option_value('laststatus', 2, {})
+ api.nvim_set_option_value('more', false, {}) -- Avoid hit-enter prompt
+ api.nvim_set_option_value('laststatus', 2, {})
-- screen:expect() calls are needed to avoid feeding input too early
- screen:expect({any = '%[No Name%]'})
+ screen:expect({ any = '%[No Name%]' })
- async_meths.command([[let a = confirm('Press O to proceed')]])
- screen:expect({any = '{CONFIRM:.+: }'})
+ async_meths.nvim_command([[let a = confirm('Press O to proceed')]])
+ screen:expect({ any = '{CONFIRM:.+: }' })
feed('o')
- screen:expect({any = '%[No Name%]'})
- eq(1, meths.get_var('a'))
+ screen:expect({ any = '%[No Name%]' })
+ eq(1, api.nvim_get_var('a'))
- async_meths.command([[let a = 'Are you sure?'->confirm("&Yes\n&No")]])
- screen:expect({any = '{CONFIRM:.+: }'})
+ async_meths.nvim_command([[let a = 'Are you sure?'->confirm("&Yes\n&No")]])
+ screen:expect({ any = '{CONFIRM:.+: }' })
feed('y')
- screen:expect({any = '%[No Name%]'})
- eq(1, meths.get_var('a'))
+ screen:expect({ any = '%[No Name%]' })
+ eq(1, api.nvim_get_var('a'))
- async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
- screen:expect({any = '{CONFIRM:.+: }'})
+ async_meths.nvim_command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
+ screen:expect({ any = '{CONFIRM:.+: }' })
feed('n')
- screen:expect({any = '%[No Name%]'})
- eq(2, meths.get_var('a'))
+ screen:expect({ any = '%[No Name%]' })
+ eq(2, api.nvim_get_var('a'))
-- Not possible to match Vim's CTRL-C test here as CTRL-C always sets got_int in Nvim.
-- confirm() should return 0 when pressing ESC.
- async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
- screen:expect({any = '{CONFIRM:.+: }'})
+ async_meths.nvim_command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
+ screen:expect({ any = '{CONFIRM:.+: }' })
feed('<Esc>')
- screen:expect({any = '%[No Name%]'})
- eq(0, meths.get_var('a'))
+ screen:expect({ any = '%[No Name%]' })
+ eq(0, api.nvim_get_var('a'))
-- Default choice is returned when pressing <CR>.
- async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
- screen:expect({any = '{CONFIRM:.+: }'})
+ async_meths.nvim_command([[let a = confirm('Are you sure?', "&Yes\n&No")]])
+ screen:expect({ any = '{CONFIRM:.+: }' })
feed('<CR>')
- screen:expect({any = '%[No Name%]'})
- eq(1, meths.get_var('a'))
+ screen:expect({ any = '%[No Name%]' })
+ eq(1, api.nvim_get_var('a'))
- async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No", 2)]])
- screen:expect({any = '{CONFIRM:.+: }'})
+ async_meths.nvim_command([[let a = confirm('Are you sure?', "&Yes\n&No", 2)]])
+ screen:expect({ any = '{CONFIRM:.+: }' })
feed('<CR>')
- screen:expect({any = '%[No Name%]'})
- eq(2, meths.get_var('a'))
+ screen:expect({ any = '%[No Name%]' })
+ eq(2, api.nvim_get_var('a'))
- async_meths.command([[let a = confirm('Are you sure?', "&Yes\n&No", 0)]])
- screen:expect({any = '{CONFIRM:.+: }'})
+ async_meths.nvim_command([[let a = confirm('Are you sure?', "&Yes\n&No", 0)]])
+ screen:expect({ any = '{CONFIRM:.+: }' })
feed('<CR>')
- screen:expect({any = '%[No Name%]'})
- eq(0, meths.get_var('a'))
+ screen:expect({ any = '%[No Name%]' })
+ eq(0, api.nvim_get_var('a'))
-- Test with the {type} 4th argument
- for _, type in ipairs({'Error', 'Question', 'Info', 'Warning', 'Generic'}) do
- async_meths.command(([[let a = confirm('Are you sure?', "&Yes\n&No", 1, '%s')]]):format(type))
- screen:expect({any = '{CONFIRM:.+: }'})
+ for _, type in ipairs({ 'Error', 'Question', 'Info', 'Warning', 'Generic' }) do
+ async_meths.nvim_command(
+ ([[let a = confirm('Are you sure?', "&Yes\n&No", 1, '%s')]]):format(type)
+ )
+ screen:expect({ any = '{CONFIRM:.+: }' })
feed('y')
- screen:expect({any = '%[No Name%]'})
- eq(1, meths.get_var('a'))
+ screen:expect({ any = '%[No Name%]' })
+ eq(1, api.nvim_get_var('a'))
end
- eq('Vim(call):E730: Using a List as a String',
- pcall_err(command, 'call confirm([])'))
- eq('Vim(call):E730: Using a List as a String',
- pcall_err(command, 'call confirm("Are you sure?", [])'))
- eq('Vim(call):E745: Using a List as a Number',
- pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", [])'))
- eq('Vim(call):E730: Using a List as a String',
- pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", 0, [])'))
+ eq('Vim(call):E730: Using a List as a String', pcall_err(command, 'call confirm([])'))
+ eq(
+ 'Vim(call):E730: Using a List as a String',
+ pcall_err(command, 'call confirm("Are you sure?", [])')
+ )
+ eq(
+ 'Vim(call):E745: Using a List as a Number',
+ pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", [])')
+ )
+ eq(
+ 'Vim(call):E730: Using a List as a String',
+ pcall_err(command, 'call confirm("Are you sure?", "&Yes\n&No\n", 0, [])')
+ )
end)
- it("shows dialog even if :silent #8788", function()
+ it('shows dialog even if :silent #8788', function()
command("autocmd BufNewFile * call confirm('test')")
local function check_and_clear(edit_line)
screen:expect([[
|
{SEP: }|
- ]]..edit_line..[[
+ ]] .. edit_line .. [[
{CONFIRM:test} |
{CONFIRM:[O]k: }^ |
]])
@@ -556,7 +520,7 @@ describe('confirm()', function()
feed(':call nvim_command("edit x")<cr>')
check_and_clear(':call nvim_command("edit |\n')
- async_meths.command('edit x')
+ async_meths.nvim_command('edit x')
check_and_clear(' |\n')
end)
end)
diff --git a/test/functional/vimscript/json_functions_spec.lua b/test/functional/vimscript/json_functions_spec.lua
index a9dab8431c..ef0359263e 100644
--- a/test/functional/vimscript/json_functions_spec.lua
+++ b/test/functional/vimscript/json_functions_spec.lua
@@ -1,13 +1,13 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local eq = helpers.eq
local eval = helpers.eval
local command = helpers.command
local exc_exec = helpers.exc_exec
local pcall_err = helpers.pcall_err
-local NIL = helpers.NIL
+local NIL = vim.NIL
local source = helpers.source
describe('json_decode() function', function()
@@ -59,467 +59,577 @@ describe('json_decode() function', function()
before_each(restart)
local speq = function(expected, actual_expr)
- eq(1, funcs.EvalEq(expected, actual_expr))
+ eq(1, fn.EvalEq(expected, actual_expr))
end
it('accepts readfile()-style list', function()
- eq({Test=1}, funcs.json_decode({
- '{',
- '\t"Test": 1',
- '}',
- }))
+ eq(
+ { Test = 1 },
+ fn.json_decode({
+ '{',
+ '\t"Test": 1',
+ '}',
+ })
+ )
end)
it('accepts strings with newlines', function()
- eq({Test=1}, funcs.json_decode([[
+ eq(
+ { Test = 1 },
+ fn.json_decode([[
{
"Test": 1
}
- ]]))
+ ]])
+ )
end)
it('parses null, true, false', function()
- eq(NIL, funcs.json_decode('null'))
- eq(true, funcs.json_decode('true'))
- eq(false, funcs.json_decode('false'))
+ eq(NIL, fn.json_decode('null'))
+ eq(true, fn.json_decode('true'))
+ eq(false, fn.json_decode('false'))
end)
it('fails to parse incomplete null, true, false', function()
- eq('Vim(call):E474: Expected null: n',
- exc_exec('call json_decode("n")'))
- eq('Vim(call):E474: Expected null: nu',
- exc_exec('call json_decode("nu")'))
- eq('Vim(call):E474: Expected null: nul',
- exc_exec('call json_decode("nul")'))
- eq('Vim(call):E474: Expected null: nul\n\t',
- exc_exec('call json_decode("nul\\n\\t")'))
-
- eq('Vim(call):E474: Expected true: t',
- exc_exec('call json_decode("t")'))
- eq('Vim(call):E474: Expected true: tr',
- exc_exec('call json_decode("tr")'))
- eq('Vim(call):E474: Expected true: tru',
- exc_exec('call json_decode("tru")'))
- eq('Vim(call):E474: Expected true: tru\t\n',
- exc_exec('call json_decode("tru\\t\\n")'))
-
- eq('Vim(call):E474: Expected false: f',
- exc_exec('call json_decode("f")'))
- eq('Vim(call):E474: Expected false: fa',
- exc_exec('call json_decode("fa")'))
- eq('Vim(call):E474: Expected false: fal',
- exc_exec('call json_decode("fal")'))
- eq('Vim(call):E474: Expected false: fal <',
- exc_exec('call json_decode(" fal <")'))
- eq('Vim(call):E474: Expected false: fals',
- exc_exec('call json_decode("fals")'))
+ eq('Vim(call):E474: Expected null: n', exc_exec('call json_decode("n")'))
+ eq('Vim(call):E474: Expected null: nu', exc_exec('call json_decode("nu")'))
+ eq('Vim(call):E474: Expected null: nul', exc_exec('call json_decode("nul")'))
+ eq('Vim(call):E474: Expected null: nul\n\t', exc_exec('call json_decode("nul\\n\\t")'))
+
+ eq('Vim(call):E474: Expected true: t', exc_exec('call json_decode("t")'))
+ eq('Vim(call):E474: Expected true: tr', exc_exec('call json_decode("tr")'))
+ eq('Vim(call):E474: Expected true: tru', exc_exec('call json_decode("tru")'))
+ eq('Vim(call):E474: Expected true: tru\t\n', exc_exec('call json_decode("tru\\t\\n")'))
+
+ eq('Vim(call):E474: Expected false: f', exc_exec('call json_decode("f")'))
+ eq('Vim(call):E474: Expected false: fa', exc_exec('call json_decode("fa")'))
+ eq('Vim(call):E474: Expected false: fal', exc_exec('call json_decode("fal")'))
+ eq('Vim(call):E474: Expected false: fal <', exc_exec('call json_decode(" fal <")'))
+ eq('Vim(call):E474: Expected false: fals', exc_exec('call json_decode("fals")'))
end)
it('parses integer numbers', function()
- eq(100000, funcs.json_decode('100000'))
- eq(-100000, funcs.json_decode('-100000'))
- eq(100000, funcs.json_decode(' 100000 '))
- eq(-100000, funcs.json_decode(' -100000 '))
- eq(0, funcs.json_decode('0'))
- eq(0, funcs.json_decode('-0'))
+ eq(100000, fn.json_decode('100000'))
+ eq(-100000, fn.json_decode('-100000'))
+ eq(100000, fn.json_decode(' 100000 '))
+ eq(-100000, fn.json_decode(' -100000 '))
+ eq(0, fn.json_decode('0'))
+ eq(0, fn.json_decode('-0'))
end)
it('fails to parse +numbers and .number', function()
- eq('Vim(call):E474: Unidentified byte: +1000',
- exc_exec('call json_decode("+1000")'))
- eq('Vim(call):E474: Unidentified byte: .1000',
- exc_exec('call json_decode(".1000")'))
+ eq('Vim(call):E474: Unidentified byte: +1000', exc_exec('call json_decode("+1000")'))
+ eq('Vim(call):E474: Unidentified byte: .1000', exc_exec('call json_decode(".1000")'))
end)
it('fails to parse numbers with leading zeroes', function()
- eq('Vim(call):E474: Leading zeroes are not allowed: 00.1',
- exc_exec('call json_decode("00.1")'))
- eq('Vim(call):E474: Leading zeroes are not allowed: 01',
- exc_exec('call json_decode("01")'))
- eq('Vim(call):E474: Leading zeroes are not allowed: -01',
- exc_exec('call json_decode("-01")'))
- eq('Vim(call):E474: Leading zeroes are not allowed: -001.0',
- exc_exec('call json_decode("-001.0")'))
+ eq('Vim(call):E474: Leading zeroes are not allowed: 00.1', exc_exec('call json_decode("00.1")'))
+ eq('Vim(call):E474: Leading zeroes are not allowed: 01', exc_exec('call json_decode("01")'))
+ eq('Vim(call):E474: Leading zeroes are not allowed: -01', exc_exec('call json_decode("-01")'))
+ eq(
+ 'Vim(call):E474: Leading zeroes are not allowed: -001.0',
+ exc_exec('call json_decode("-001.0")')
+ )
end)
it('fails to parse incomplete numbers', function()
- eq('Vim(call):E474: Missing number after minus sign: -.1',
- exc_exec('call json_decode("-.1")'))
- eq('Vim(call):E474: Missing number after minus sign: -',
- exc_exec('call json_decode("-")'))
- eq('Vim(call):E474: Missing number after decimal dot: -1.',
- exc_exec('call json_decode("-1.")'))
- eq('Vim(call):E474: Missing number after decimal dot: 0.',
- exc_exec('call json_decode("0.")'))
- eq('Vim(call):E474: Missing exponent: 0.0e',
- exc_exec('call json_decode("0.0e")'))
- eq('Vim(call):E474: Missing exponent: 0.0e+',
- exc_exec('call json_decode("0.0e+")'))
- eq('Vim(call):E474: Missing exponent: 0.0e-',
- exc_exec('call json_decode("0.0e-")'))
- eq('Vim(call):E474: Missing exponent: 0.0e-',
- exc_exec('call json_decode("0.0e-")'))
- eq('Vim(call):E474: Missing number after decimal dot: 1.e5',
- exc_exec('call json_decode("1.e5")'))
- eq('Vim(call):E474: Missing number after decimal dot: 1.e+5',
- exc_exec('call json_decode("1.e+5")'))
- eq('Vim(call):E474: Missing number after decimal dot: 1.e+',
- exc_exec('call json_decode("1.e+")'))
+ eq('Vim(call):E474: Missing number after minus sign: -.1', exc_exec('call json_decode("-.1")'))
+ eq('Vim(call):E474: Missing number after minus sign: -', exc_exec('call json_decode("-")'))
+ eq('Vim(call):E474: Missing number after decimal dot: -1.', exc_exec('call json_decode("-1.")'))
+ eq('Vim(call):E474: Missing number after decimal dot: 0.', exc_exec('call json_decode("0.")'))
+ eq('Vim(call):E474: Missing exponent: 0.0e', exc_exec('call json_decode("0.0e")'))
+ eq('Vim(call):E474: Missing exponent: 0.0e+', exc_exec('call json_decode("0.0e+")'))
+ eq('Vim(call):E474: Missing exponent: 0.0e-', exc_exec('call json_decode("0.0e-")'))
+ eq('Vim(call):E474: Missing exponent: 0.0e-', exc_exec('call json_decode("0.0e-")'))
+ eq(
+ 'Vim(call):E474: Missing number after decimal dot: 1.e5',
+ exc_exec('call json_decode("1.e5")')
+ )
+ eq(
+ 'Vim(call):E474: Missing number after decimal dot: 1.e+5',
+ exc_exec('call json_decode("1.e+5")')
+ )
+ eq(
+ 'Vim(call):E474: Missing number after decimal dot: 1.e+',
+ exc_exec('call json_decode("1.e+")')
+ )
end)
it('parses floating-point numbers', function()
-- Also test method call (->) syntax
eq('100000.0', eval('"100000.0"->json_decode()->string()'))
- eq(100000.5, funcs.json_decode('100000.5'))
- eq(-100000.5, funcs.json_decode('-100000.5'))
- eq(-100000.5e50, funcs.json_decode('-100000.5e50'))
- eq(100000.5e50, funcs.json_decode('100000.5e50'))
- eq(100000.5e50, funcs.json_decode('100000.5e+50'))
- eq(-100000.5e-50, funcs.json_decode('-100000.5e-50'))
- eq(100000.5e-50, funcs.json_decode('100000.5e-50'))
- eq(100000e-50, funcs.json_decode('100000e-50'))
- eq(0.5, funcs.json_decode('0.5'))
- eq(0.005, funcs.json_decode('0.005'))
- eq(0.005, funcs.json_decode('0.00500'))
- eq(0.5, funcs.json_decode('0.00500e+002'))
- eq(0.00005, funcs.json_decode('0.00500e-002'))
-
- eq(-0.0, funcs.json_decode('-0.0'))
- eq(-0.0, funcs.json_decode('-0.0e0'))
- eq(-0.0, funcs.json_decode('-0.0e+0'))
- eq(-0.0, funcs.json_decode('-0.0e-0'))
- eq(-0.0, funcs.json_decode('-0e-0'))
- eq(-0.0, funcs.json_decode('-0e-2'))
- eq(-0.0, funcs.json_decode('-0e+2'))
-
- eq(0.0, funcs.json_decode('0.0'))
- eq(0.0, funcs.json_decode('0.0e0'))
- eq(0.0, funcs.json_decode('0.0e+0'))
- eq(0.0, funcs.json_decode('0.0e-0'))
- eq(0.0, funcs.json_decode('0e-0'))
- eq(0.0, funcs.json_decode('0e-2'))
- eq(0.0, funcs.json_decode('0e+2'))
+ eq(100000.5, fn.json_decode('100000.5'))
+ eq(-100000.5, fn.json_decode('-100000.5'))
+ eq(-100000.5e50, fn.json_decode('-100000.5e50'))
+ eq(100000.5e50, fn.json_decode('100000.5e50'))
+ eq(100000.5e50, fn.json_decode('100000.5e+50'))
+ eq(-100000.5e-50, fn.json_decode('-100000.5e-50'))
+ eq(100000.5e-50, fn.json_decode('100000.5e-50'))
+ eq(100000e-50, fn.json_decode('100000e-50'))
+ eq(0.5, fn.json_decode('0.5'))
+ eq(0.005, fn.json_decode('0.005'))
+ eq(0.005, fn.json_decode('0.00500'))
+ eq(0.5, fn.json_decode('0.00500e+002'))
+ eq(0.00005, fn.json_decode('0.00500e-002'))
+
+ eq(-0.0, fn.json_decode('-0.0'))
+ eq(-0.0, fn.json_decode('-0.0e0'))
+ eq(-0.0, fn.json_decode('-0.0e+0'))
+ eq(-0.0, fn.json_decode('-0.0e-0'))
+ eq(-0.0, fn.json_decode('-0e-0'))
+ eq(-0.0, fn.json_decode('-0e-2'))
+ eq(-0.0, fn.json_decode('-0e+2'))
+
+ eq(0.0, fn.json_decode('0.0'))
+ eq(0.0, fn.json_decode('0.0e0'))
+ eq(0.0, fn.json_decode('0.0e+0'))
+ eq(0.0, fn.json_decode('0.0e-0'))
+ eq(0.0, fn.json_decode('0e-0'))
+ eq(0.0, fn.json_decode('0e-2'))
+ eq(0.0, fn.json_decode('0e+2'))
end)
it('fails to parse numbers with spaces inside', function()
- eq('Vim(call):E474: Missing number after minus sign: - 1000',
- exc_exec('call json_decode("- 1000")'))
- eq('Vim(call):E474: Missing number after decimal dot: 0. ',
- exc_exec('call json_decode("0. ")'))
- eq('Vim(call):E474: Missing number after decimal dot: 0. 0',
- exc_exec('call json_decode("0. 0")'))
- eq('Vim(call):E474: Missing exponent: 0.0e 1',
- exc_exec('call json_decode("0.0e 1")'))
- eq('Vim(call):E474: Missing exponent: 0.0e+ 1',
- exc_exec('call json_decode("0.0e+ 1")'))
- eq('Vim(call):E474: Missing exponent: 0.0e- 1',
- exc_exec('call json_decode("0.0e- 1")'))
+ eq(
+ 'Vim(call):E474: Missing number after minus sign: - 1000',
+ exc_exec('call json_decode("- 1000")')
+ )
+ eq('Vim(call):E474: Missing number after decimal dot: 0. ', exc_exec('call json_decode("0. ")'))
+ eq(
+ 'Vim(call):E474: Missing number after decimal dot: 0. 0',
+ exc_exec('call json_decode("0. 0")')
+ )
+ eq('Vim(call):E474: Missing exponent: 0.0e 1', exc_exec('call json_decode("0.0e 1")'))
+ eq('Vim(call):E474: Missing exponent: 0.0e+ 1', exc_exec('call json_decode("0.0e+ 1")'))
+ eq('Vim(call):E474: Missing exponent: 0.0e- 1', exc_exec('call json_decode("0.0e- 1")'))
end)
it('fails to parse "," and ":"', function()
- eq('Vim(call):E474: Comma not inside container: , ',
- exc_exec('call json_decode(" , ")'))
- eq('Vim(call):E474: Colon not inside container: : ',
- exc_exec('call json_decode(" : ")'))
+ eq('Vim(call):E474: Comma not inside container: , ', exc_exec('call json_decode(" , ")'))
+ eq('Vim(call):E474: Colon not inside container: : ', exc_exec('call json_decode(" : ")'))
end)
it('parses empty containers', function()
- eq({}, funcs.json_decode('[]'))
+ eq({}, fn.json_decode('[]'))
eq('[]', eval('string(json_decode("[]"))'))
end)
it('fails to parse "[" and "{"', function()
- eq('Vim(call):E474: Unexpected end of input: {',
- exc_exec('call json_decode("{")'))
- eq('Vim(call):E474: Unexpected end of input: [',
- exc_exec('call json_decode("[")'))
+ eq('Vim(call):E474: Unexpected end of input: {', exc_exec('call json_decode("{")'))
+ eq('Vim(call):E474: Unexpected end of input: [', exc_exec('call json_decode("[")'))
end)
it('fails to parse "}" and "]"', function()
- eq('Vim(call):E474: No container to close: ]',
- exc_exec('call json_decode("]")'))
- eq('Vim(call):E474: No container to close: }',
- exc_exec('call json_decode("}")'))
+ eq('Vim(call):E474: No container to close: ]', exc_exec('call json_decode("]")'))
+ eq('Vim(call):E474: No container to close: }', exc_exec('call json_decode("}")'))
end)
- it('fails to parse containers which are closed by different brackets',
- function()
- eq('Vim(call):E474: Closing dictionary with square bracket: ]',
- exc_exec('call json_decode("{]")'))
- eq('Vim(call):E474: Closing list with curly bracket: }',
- exc_exec('call json_decode("[}")'))
+ it('fails to parse containers which are closed by different brackets', function()
+ eq(
+ 'Vim(call):E474: Closing dictionary with square bracket: ]',
+ exc_exec('call json_decode("{]")')
+ )
+ eq('Vim(call):E474: Closing list with curly bracket: }', exc_exec('call json_decode("[}")'))
end)
it('fails to parse concat inside container', function()
- eq('Vim(call):E474: Expected comma before list item: []]',
- exc_exec('call json_decode("[[][]]")'))
- eq('Vim(call):E474: Expected comma before list item: {}]',
- exc_exec('call json_decode("[{}{}]")'))
- eq('Vim(call):E474: Expected comma before list item: ]',
- exc_exec('call json_decode("[1 2]")'))
- eq('Vim(call):E474: Expected comma before dictionary key: ": 4}',
- exc_exec('call json_decode("{\\"1\\": 2 \\"3\\": 4}")'))
- eq('Vim(call):E474: Expected colon before dictionary value: , "3" 4}',
- exc_exec('call json_decode("{\\"1\\" 2, \\"3\\" 4}")'))
+ eq(
+ 'Vim(call):E474: Expected comma before list item: []]',
+ exc_exec('call json_decode("[[][]]")')
+ )
+ eq(
+ 'Vim(call):E474: Expected comma before list item: {}]',
+ exc_exec('call json_decode("[{}{}]")')
+ )
+ eq('Vim(call):E474: Expected comma before list item: ]', exc_exec('call json_decode("[1 2]")'))
+ eq(
+ 'Vim(call):E474: Expected comma before dictionary key: ": 4}',
+ exc_exec('call json_decode("{\\"1\\": 2 \\"3\\": 4}")')
+ )
+ eq(
+ 'Vim(call):E474: Expected colon before dictionary value: , "3" 4}',
+ exc_exec('call json_decode("{\\"1\\" 2, \\"3\\" 4}")')
+ )
end)
it('fails to parse containers with leading comma or colon', function()
- eq('Vim(call):E474: Leading comma: ,}',
- exc_exec('call json_decode("{,}")'))
- eq('Vim(call):E474: Leading comma: ,]',
- exc_exec('call json_decode("[,]")'))
- eq('Vim(call):E474: Using colon not in dictionary: :]',
- exc_exec('call json_decode("[:]")'))
- eq('Vim(call):E474: Unexpected colon: :}',
- exc_exec('call json_decode("{:}")'))
+ eq('Vim(call):E474: Leading comma: ,}', exc_exec('call json_decode("{,}")'))
+ eq('Vim(call):E474: Leading comma: ,]', exc_exec('call json_decode("[,]")'))
+ eq('Vim(call):E474: Using colon not in dictionary: :]', exc_exec('call json_decode("[:]")'))
+ eq('Vim(call):E474: Unexpected colon: :}', exc_exec('call json_decode("{:}")'))
end)
it('fails to parse containers with trailing comma', function()
- eq('Vim(call):E474: Trailing comma: ]',
- exc_exec('call json_decode("[1,]")'))
- eq('Vim(call):E474: Trailing comma: }',
- exc_exec('call json_decode("{\\"1\\": 2,}")'))
+ eq('Vim(call):E474: Trailing comma: ]', exc_exec('call json_decode("[1,]")'))
+ eq('Vim(call):E474: Trailing comma: }', exc_exec('call json_decode("{\\"1\\": 2,}")'))
end)
it('fails to parse dictionaries with missing value', function()
- eq('Vim(call):E474: Expected value after colon: }',
- exc_exec('call json_decode("{\\"1\\":}")'))
- eq('Vim(call):E474: Expected value: }',
- exc_exec('call json_decode("{\\"1\\"}")'))
+ eq('Vim(call):E474: Expected value after colon: }', exc_exec('call json_decode("{\\"1\\":}")'))
+ eq('Vim(call):E474: Expected value: }', exc_exec('call json_decode("{\\"1\\"}")'))
end)
it('fails to parse containers with two commas or colons', function()
- eq('Vim(call):E474: Duplicate comma: , "2": 2}',
- exc_exec('call json_decode("{\\"1\\": 1,, \\"2\\": 2}")'))
- eq('Vim(call):E474: Duplicate comma: , "2", 2]',
- exc_exec('call json_decode("[\\"1\\", 1,, \\"2\\", 2]")'))
- eq('Vim(call):E474: Duplicate colon: : 2}',
- exc_exec('call json_decode("{\\"1\\": 1, \\"2\\":: 2}")'))
- eq('Vim(call):E474: Comma after colon: , 2}',
- exc_exec('call json_decode("{\\"1\\": 1, \\"2\\":, 2}")'))
- eq('Vim(call):E474: Unexpected colon: : "2": 2}',
- exc_exec('call json_decode("{\\"1\\": 1,: \\"2\\": 2}")'))
- eq('Vim(call):E474: Unexpected colon: :, "2": 2}',
- exc_exec('call json_decode("{\\"1\\": 1:, \\"2\\": 2}")'))
+ eq(
+ 'Vim(call):E474: Duplicate comma: , "2": 2}',
+ exc_exec('call json_decode("{\\"1\\": 1,, \\"2\\": 2}")')
+ )
+ eq(
+ 'Vim(call):E474: Duplicate comma: , "2", 2]',
+ exc_exec('call json_decode("[\\"1\\", 1,, \\"2\\", 2]")')
+ )
+ eq(
+ 'Vim(call):E474: Duplicate colon: : 2}',
+ exc_exec('call json_decode("{\\"1\\": 1, \\"2\\":: 2}")')
+ )
+ eq(
+ 'Vim(call):E474: Comma after colon: , 2}',
+ exc_exec('call json_decode("{\\"1\\": 1, \\"2\\":, 2}")')
+ )
+ eq(
+ 'Vim(call):E474: Unexpected colon: : "2": 2}',
+ exc_exec('call json_decode("{\\"1\\": 1,: \\"2\\": 2}")')
+ )
+ eq(
+ 'Vim(call):E474: Unexpected colon: :, "2": 2}',
+ exc_exec('call json_decode("{\\"1\\": 1:, \\"2\\": 2}")')
+ )
end)
it('fails to parse concat of two values', function()
- eq('Vim(call):E474: Trailing characters: []',
- exc_exec('call json_decode("{}[]")'))
+ eq('Vim(call):E474: Trailing characters: []', exc_exec('call json_decode("{}[]")'))
end)
it('parses containers', function()
- eq({1}, funcs.json_decode('[1]'))
- eq({NIL, 1}, funcs.json_decode('[null, 1]'))
- eq({['1']=2}, funcs.json_decode('{"1": 2}'))
- eq({['1']=2, ['3']={{['4']={['5']={{}, 1}}}}},
- funcs.json_decode('{"1": 2, "3": [{"4": {"5": [[], 1]}}]}'))
+ eq({ 1 }, fn.json_decode('[1]'))
+ eq({ NIL, 1 }, fn.json_decode('[null, 1]'))
+ eq({ ['1'] = 2 }, fn.json_decode('{"1": 2}'))
+ eq(
+ { ['1'] = 2, ['3'] = { { ['4'] = { ['5'] = { {}, 1 } } } } },
+ fn.json_decode('{"1": 2, "3": [{"4": {"5": [[], 1]}}]}')
+ )
end)
it('fails to parse incomplete strings', function()
- eq('Vim(call):E474: Expected string end: \t"',
- exc_exec('call json_decode("\\t\\"")'))
- eq('Vim(call):E474: Expected string end: \t"abc',
- exc_exec('call json_decode("\\t\\"abc")'))
- eq('Vim(call):E474: Unfinished escape sequence: \t"abc\\',
- exc_exec('call json_decode("\\t\\"abc\\\\")'))
- eq('Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u',
- exc_exec('call json_decode("\\t\\"abc\\\\u")'))
- eq('Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u0',
- exc_exec('call json_decode("\\t\\"abc\\\\u0")'))
- eq('Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u00',
- exc_exec('call json_decode("\\t\\"abc\\\\u00")'))
- eq('Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u000',
- exc_exec('call json_decode("\\t\\"abc\\\\u000")'))
- eq('Vim(call):E474: Expected four hex digits after \\u: \\u" ',
- exc_exec('call json_decode("\\t\\"abc\\\\u\\" ")'))
- eq('Vim(call):E474: Expected four hex digits after \\u: \\u0" ',
- exc_exec('call json_decode("\\t\\"abc\\\\u0\\" ")'))
- eq('Vim(call):E474: Expected four hex digits after \\u: \\u00" ',
- exc_exec('call json_decode("\\t\\"abc\\\\u00\\" ")'))
- eq('Vim(call):E474: Expected four hex digits after \\u: \\u000" ',
- exc_exec('call json_decode("\\t\\"abc\\\\u000\\" ")'))
- eq('Vim(call):E474: Expected string end: \t"abc\\u0000',
- exc_exec('call json_decode("\\t\\"abc\\\\u0000")'))
+ eq('Vim(call):E474: Expected string end: \t"', exc_exec('call json_decode("\\t\\"")'))
+ eq('Vim(call):E474: Expected string end: \t"abc', exc_exec('call json_decode("\\t\\"abc")'))
+ eq(
+ 'Vim(call):E474: Unfinished escape sequence: \t"abc\\',
+ exc_exec('call json_decode("\\t\\"abc\\\\")')
+ )
+ eq(
+ 'Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u',
+ exc_exec('call json_decode("\\t\\"abc\\\\u")')
+ )
+ eq(
+ 'Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u0',
+ exc_exec('call json_decode("\\t\\"abc\\\\u0")')
+ )
+ eq(
+ 'Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u00',
+ exc_exec('call json_decode("\\t\\"abc\\\\u00")')
+ )
+ eq(
+ 'Vim(call):E474: Unfinished unicode escape sequence: \t"abc\\u000',
+ exc_exec('call json_decode("\\t\\"abc\\\\u000")')
+ )
+ eq(
+ 'Vim(call):E474: Expected four hex digits after \\u: \\u" ',
+ exc_exec('call json_decode("\\t\\"abc\\\\u\\" ")')
+ )
+ eq(
+ 'Vim(call):E474: Expected four hex digits after \\u: \\u0" ',
+ exc_exec('call json_decode("\\t\\"abc\\\\u0\\" ")')
+ )
+ eq(
+ 'Vim(call):E474: Expected four hex digits after \\u: \\u00" ',
+ exc_exec('call json_decode("\\t\\"abc\\\\u00\\" ")')
+ )
+ eq(
+ 'Vim(call):E474: Expected four hex digits after \\u: \\u000" ',
+ exc_exec('call json_decode("\\t\\"abc\\\\u000\\" ")')
+ )
+ eq(
+ 'Vim(call):E474: Expected string end: \t"abc\\u0000',
+ exc_exec('call json_decode("\\t\\"abc\\\\u0000")')
+ )
end)
it('fails to parse unknown escape sequences', function()
- eq('Vim(call):E474: Unknown escape sequence: \\a"',
- exc_exec('call json_decode("\\t\\"\\\\a\\"")'))
+ eq(
+ 'Vim(call):E474: Unknown escape sequence: \\a"',
+ exc_exec('call json_decode("\\t\\"\\\\a\\"")')
+ )
end)
it('parses strings properly', function()
- eq('\n', funcs.json_decode('"\\n"'))
- eq('', funcs.json_decode('""'))
- eq('\\/"\t\b\n\r\f', funcs.json_decode([["\\\/\"\t\b\n\r\f"]]))
- eq('/a', funcs.json_decode([["\/a"]]))
+ eq('\n', fn.json_decode('"\\n"'))
+ eq('', fn.json_decode('""'))
+ eq('\\/"\t\b\n\r\f', fn.json_decode([["\\\/\"\t\b\n\r\f"]]))
+ eq('/a', fn.json_decode([["\/a"]]))
-- Unicode characters: 2-byte, 3-byte, 4-byte
- eq({
- '«',
- 'ફ',
- '\240\144\128\128',
- }, funcs.json_decode({
- '[',
- '"«",',
- '"ફ",',
- '"\240\144\128\128"',
- ']',
- }))
+ eq(
+ {
+ '«',
+ 'ફ',
+ '\240\144\128\128',
+ },
+ fn.json_decode({
+ '[',
+ '"«",',
+ '"ફ",',
+ '"\240\144\128\128"',
+ ']',
+ })
+ )
end)
it('fails on strings with invalid bytes', function()
- eq('Vim(call):E474: Only UTF-8 strings allowed: \255"',
- exc_exec('call json_decode("\\t\\"\\xFF\\"")'))
- eq('Vim(call):E474: ASCII control characters cannot be present inside string: ',
- exc_exec('call json_decode(["\\"\\n\\""])'))
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \255"',
+ exc_exec('call json_decode("\\t\\"\\xFF\\"")')
+ )
+ eq(
+ 'Vim(call):E474: ASCII control characters cannot be present inside string: ',
+ exc_exec('call json_decode(["\\"\\n\\""])')
+ )
-- 0xC2 starts 2-byte unicode character
- eq('Vim(call):E474: Only UTF-8 strings allowed: \194"',
- exc_exec('call json_decode("\\t\\"\\xC2\\"")'))
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \194"',
+ exc_exec('call json_decode("\\t\\"\\xC2\\"")')
+ )
-- 0xE0 0xAA starts 3-byte unicode character
- eq('Vim(call):E474: Only UTF-8 strings allowed: \224"',
- exc_exec('call json_decode("\\t\\"\\xE0\\"")'))
- eq('Vim(call):E474: Only UTF-8 strings allowed: \224\170"',
- exc_exec('call json_decode("\\t\\"\\xE0\\xAA\\"")'))
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \224"',
+ exc_exec('call json_decode("\\t\\"\\xE0\\"")')
+ )
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \224\170"',
+ exc_exec('call json_decode("\\t\\"\\xE0\\xAA\\"")')
+ )
-- 0xF0 0x90 0x80 starts 4-byte unicode character
- eq('Vim(call):E474: Only UTF-8 strings allowed: \240"',
- exc_exec('call json_decode("\\t\\"\\xF0\\"")'))
- eq('Vim(call):E474: Only UTF-8 strings allowed: \240\144"',
- exc_exec('call json_decode("\\t\\"\\xF0\\x90\\"")'))
- eq('Vim(call):E474: Only UTF-8 strings allowed: \240\144\128"',
- exc_exec('call json_decode("\\t\\"\\xF0\\x90\\x80\\"")'))
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \240"',
+ exc_exec('call json_decode("\\t\\"\\xF0\\"")')
+ )
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \240\144"',
+ exc_exec('call json_decode("\\t\\"\\xF0\\x90\\"")')
+ )
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \240\144\128"',
+ exc_exec('call json_decode("\\t\\"\\xF0\\x90\\x80\\"")')
+ )
-- 0xF9 0x80 0x80 0x80 starts 5-byte unicode character
- eq('Vim(call):E474: Only UTF-8 strings allowed: \249"',
- exc_exec('call json_decode("\\t\\"\\xF9\\"")'))
- eq('Vim(call):E474: Only UTF-8 strings allowed: \249\128"',
- exc_exec('call json_decode("\\t\\"\\xF9\\x80\\"")'))
- eq('Vim(call):E474: Only UTF-8 strings allowed: \249\128\128"',
- exc_exec('call json_decode("\\t\\"\\xF9\\x80\\x80\\"")'))
- eq('Vim(call):E474: Only UTF-8 strings allowed: \249\128\128\128"',
- exc_exec('call json_decode("\\t\\"\\xF9\\x80\\x80\\x80\\"")'))
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \249"',
+ exc_exec('call json_decode("\\t\\"\\xF9\\"")')
+ )
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \249\128"',
+ exc_exec('call json_decode("\\t\\"\\xF9\\x80\\"")')
+ )
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \249\128\128"',
+ exc_exec('call json_decode("\\t\\"\\xF9\\x80\\x80\\"")')
+ )
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \249\128\128\128"',
+ exc_exec('call json_decode("\\t\\"\\xF9\\x80\\x80\\x80\\"")')
+ )
-- 0xFC 0x90 0x80 0x80 0x80 starts 6-byte unicode character
- eq('Vim(call):E474: Only UTF-8 strings allowed: \252"',
- exc_exec('call json_decode("\\t\\"\\xFC\\"")'))
- eq('Vim(call):E474: Only UTF-8 strings allowed: \252\144"',
- exc_exec('call json_decode("\\t\\"\\xFC\\x90\\"")'))
- eq('Vim(call):E474: Only UTF-8 strings allowed: \252\144\128"',
- exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\"")'))
- eq('Vim(call):E474: Only UTF-8 strings allowed: \252\144\128\128"',
- exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\x80\\"")'))
- eq('Vim(call):E474: Only UTF-8 strings allowed: \252\144\128\128\128"',
- exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\x80\\x80\\"")'))
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \252"',
+ exc_exec('call json_decode("\\t\\"\\xFC\\"")')
+ )
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \252\144"',
+ exc_exec('call json_decode("\\t\\"\\xFC\\x90\\"")')
+ )
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \252\144\128"',
+ exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\"")')
+ )
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \252\144\128\128"',
+ exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\x80\\"")')
+ )
+ eq(
+ 'Vim(call):E474: Only UTF-8 strings allowed: \252\144\128\128\128"',
+ exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\x80\\x80\\"")')
+ )
-- Specification does not allow unquoted characters above 0x10FFFF
- eq('Vim(call):E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \249\128\128\128\128"',
- exc_exec('call json_decode("\\t\\"\\xF9\\x80\\x80\\x80\\x80\\"")'))
- eq('Vim(call):E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \252\144\128\128\128\128"',
- exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\x80\\x80\\x80\\"")'))
+ eq(
+ 'Vim(call):E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \249\128\128\128\128"',
+ exc_exec('call json_decode("\\t\\"\\xF9\\x80\\x80\\x80\\x80\\"")')
+ )
+ eq(
+ 'Vim(call):E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \252\144\128\128\128\128"',
+ exc_exec('call json_decode("\\t\\"\\xFC\\x90\\x80\\x80\\x80\\x80\\"")')
+ )
-- '"\249\128\128\128\128"',
-- '"\252\144\128\128\128\128"',
end)
it('parses surrogate pairs properly', function()
- eq('\240\144\128\128', funcs.json_decode('"\\uD800\\uDC00"'))
- eq('\237\160\128a\237\176\128', funcs.json_decode('"\\uD800a\\uDC00"'))
- eq('\237\160\128\t\237\176\128', funcs.json_decode('"\\uD800\\t\\uDC00"'))
+ eq('\240\144\128\128', fn.json_decode('"\\uD800\\uDC00"'))
+ eq('\237\160\128a\237\176\128', fn.json_decode('"\\uD800a\\uDC00"'))
+ eq('\237\160\128\t\237\176\128', fn.json_decode('"\\uD800\\t\\uDC00"'))
- eq('\237\160\128', funcs.json_decode('"\\uD800"'))
- eq('\237\160\128a', funcs.json_decode('"\\uD800a"'))
- eq('\237\160\128\t', funcs.json_decode('"\\uD800\\t"'))
+ eq('\237\160\128', fn.json_decode('"\\uD800"'))
+ eq('\237\160\128a', fn.json_decode('"\\uD800a"'))
+ eq('\237\160\128\t', fn.json_decode('"\\uD800\\t"'))
- eq('\237\176\128', funcs.json_decode('"\\uDC00"'))
- eq('\237\176\128a', funcs.json_decode('"\\uDC00a"'))
- eq('\237\176\128\t', funcs.json_decode('"\\uDC00\\t"'))
+ eq('\237\176\128', fn.json_decode('"\\uDC00"'))
+ eq('\237\176\128a', fn.json_decode('"\\uDC00a"'))
+ eq('\237\176\128\t', fn.json_decode('"\\uDC00\\t"'))
- eq('\237\176\128', funcs.json_decode('"\\uDC00"'))
- eq('a\237\176\128', funcs.json_decode('"a\\uDC00"'))
- eq('\t\237\176\128', funcs.json_decode('"\\t\\uDC00"'))
+ eq('\237\176\128', fn.json_decode('"\\uDC00"'))
+ eq('a\237\176\128', fn.json_decode('"a\\uDC00"'))
+ eq('\t\237\176\128', fn.json_decode('"\\t\\uDC00"'))
- eq('\237\160\128¬', funcs.json_decode('"\\uD800\\u00AC"'))
+ eq('\237\160\128¬', fn.json_decode('"\\uD800\\u00AC"'))
- eq('\237\160\128\237\160\128', funcs.json_decode('"\\uD800\\uD800"'))
+ eq('\237\160\128\237\160\128', fn.json_decode('"\\uD800\\uD800"'))
end)
local sp_decode_eq = function(expected, json)
- meths.set_var('__json', json)
+ api.nvim_set_var('__json', json)
speq(expected, 'json_decode(g:__json)')
command('unlet! g:__json')
end
it('parses strings with NUL properly', function()
- sp_decode_eq({_TYPE='string', _VAL={'\n'}}, '"\\u0000"')
- sp_decode_eq({_TYPE='string', _VAL={'\n', '\n'}}, '"\\u0000\\n\\u0000"')
- sp_decode_eq({_TYPE='string', _VAL={'\n«\n'}}, '"\\u0000\\u00AB\\u0000"')
+ sp_decode_eq({ _TYPE = 'string', _VAL = { '\n' } }, '"\\u0000"')
+ sp_decode_eq({ _TYPE = 'string', _VAL = { '\n', '\n' } }, '"\\u0000\\n\\u0000"')
+ sp_decode_eq({ _TYPE = 'string', _VAL = { '\n«\n' } }, '"\\u0000\\u00AB\\u0000"')
end)
it('parses dictionaries with duplicate keys to special maps', function()
- sp_decode_eq({_TYPE='map', _VAL={{'a', 1}, {'a', 2}}},
- '{"a": 1, "a": 2}')
- sp_decode_eq({_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'a', 2}}},
- '{"b": 3, "a": 1, "a": 2}')
- sp_decode_eq({_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}}},
- '{"b": 3, "a": 1, "c": 4, "a": 2}')
- sp_decode_eq({_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}, {'c', 4}}},
- '{"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}')
- sp_decode_eq({{_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}, {'c', 4}}}},
- '[{"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}]')
- sp_decode_eq({{d={_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}, {'c', 4}}}}},
- '[{"d": {"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}}]')
- sp_decode_eq({1, {d={_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}, {'c', 4}}}}},
- '[1, {"d": {"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}}]')
- sp_decode_eq({1, {a={}, d={_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'a', 2}, {'c', 4}}}}},
- '[1, {"a": [], "d": {"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}}]')
- end)
-
- it('parses dictionaries with empty keys to special maps', function()
- sp_decode_eq({_TYPE='map', _VAL={{'', 4}}},
- '{"": 4}')
- sp_decode_eq({_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'d', 2}, {'', 4}}},
- '{"b": 3, "a": 1, "c": 4, "d": 2, "": 4}')
- sp_decode_eq({_TYPE='map', _VAL={{'', 3}, {'a', 1}, {'c', 4}, {'d', 2}, {'', 4}}},
- '{"": 3, "a": 1, "c": 4, "d": 2, "": 4}')
- sp_decode_eq({{_TYPE='map', _VAL={{'', 3}, {'a', 1}, {'c', 4}, {'d', 2}, {'', 4}}}},
- '[{"": 3, "a": 1, "c": 4, "d": 2, "": 4}]')
+ sp_decode_eq({ _TYPE = 'map', _VAL = { { 'a', 1 }, { 'a', 2 } } }, '{"a": 1, "a": 2}')
+ sp_decode_eq(
+ { _TYPE = 'map', _VAL = { { 'b', 3 }, { 'a', 1 }, { 'a', 2 } } },
+ '{"b": 3, "a": 1, "a": 2}'
+ )
+ sp_decode_eq(
+ { _TYPE = 'map', _VAL = { { 'b', 3 }, { 'a', 1 }, { 'c', 4 }, { 'a', 2 } } },
+ '{"b": 3, "a": 1, "c": 4, "a": 2}'
+ )
+ sp_decode_eq(
+ { _TYPE = 'map', _VAL = { { 'b', 3 }, { 'a', 1 }, { 'c', 4 }, { 'a', 2 }, { 'c', 4 } } },
+ '{"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}'
+ )
+ sp_decode_eq(
+ { { _TYPE = 'map', _VAL = { { 'b', 3 }, { 'a', 1 }, { 'c', 4 }, { 'a', 2 }, { 'c', 4 } } } },
+ '[{"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}]'
+ )
+ sp_decode_eq({
+ {
+ d = {
+ _TYPE = 'map',
+ _VAL = { { 'b', 3 }, { 'a', 1 }, { 'c', 4 }, { 'a', 2 }, { 'c', 4 } },
+ },
+ },
+ }, '[{"d": {"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}}]')
+ sp_decode_eq({
+ 1,
+ {
+ d = {
+ _TYPE = 'map',
+ _VAL = { { 'b', 3 }, { 'a', 1 }, { 'c', 4 }, { 'a', 2 }, { 'c', 4 } },
+ },
+ },
+ }, '[1, {"d": {"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}}]')
+ sp_decode_eq({
+ 1,
+ {
+ a = {},
+ d = {
+ _TYPE = 'map',
+ _VAL = {
+ { 'b', 3 },
+ { 'a', 1 },
+ { 'c', 4 },
+ { 'a', 2 },
+ {
+ 'c',
+ 4,
+ },
+ },
+ },
+ },
+ }, '[1, {"a": [], "d": {"b": 3, "a": 1, "c": 4, "a": 2, "c": 4}}]')
+ sp_decode_eq(
+ { _TYPE = 'map', _VAL = { { '', 3 }, { 'a', 1 }, { 'c', 4 }, { 'd', 2 }, { '', 4 } } },
+ '{"": 3, "a": 1, "c": 4, "d": 2, "": 4}'
+ )
+ sp_decode_eq(
+ { { _TYPE = 'map', _VAL = { { '', 3 }, { 'a', 1 }, { 'c', 4 }, { 'd', 2 }, { '', 4 } } } },
+ '[{"": 3, "a": 1, "c": 4, "d": 2, "": 4}]'
+ )
+ end)
+
+ it('parses dictionaries with empty keys', function()
+ eq({ [''] = 4 }, fn.json_decode('{"": 4}'))
+ eq(
+ { b = 3, a = 1, c = 4, d = 2, [''] = 4 },
+ fn.json_decode('{"b": 3, "a": 1, "c": 4, "d": 2, "": 4}')
+ )
end)
it('parses dictionaries with keys with NUL bytes to special maps', function()
- sp_decode_eq({_TYPE='map', _VAL={{{_TYPE='string', _VAL={'a\n', 'b'}}, 4}}},
- '{"a\\u0000\\nb": 4}')
- sp_decode_eq({_TYPE='map', _VAL={{{_TYPE='string', _VAL={'a\n', 'b', ''}}, 4}}},
- '{"a\\u0000\\nb\\n": 4}')
- sp_decode_eq({_TYPE='map', _VAL={{'b', 3}, {'a', 1}, {'c', 4}, {'d', 2}, {{_TYPE='string', _VAL={'\n'}}, 4}}},
- '{"b": 3, "a": 1, "c": 4, "d": 2, "\\u0000": 4}')
+ sp_decode_eq(
+ { _TYPE = 'map', _VAL = { { { _TYPE = 'string', _VAL = { 'a\n', 'b' } }, 4 } } },
+ '{"a\\u0000\\nb": 4}'
+ )
+ sp_decode_eq(
+ { _TYPE = 'map', _VAL = { { { _TYPE = 'string', _VAL = { 'a\n', 'b', '' } }, 4 } } },
+ '{"a\\u0000\\nb\\n": 4}'
+ )
+ sp_decode_eq({
+ _TYPE = 'map',
+ _VAL = {
+ { 'b', 3 },
+ { 'a', 1 },
+ { 'c', 4 },
+ { 'd', 2 },
+ {
+ { _TYPE = 'string', _VAL = { '\n' } },
+ 4,
+ },
+ },
+ }, '{"b": 3, "a": 1, "c": 4, "d": 2, "\\u0000": 4}')
end)
it('parses U+00C3 correctly', function()
- eq('\195\131', funcs.json_decode('"\195\131"'))
+ eq('\195\131', fn.json_decode('"\195\131"'))
end)
it('fails to parse empty string', function()
- eq('Vim(call):E474: Attempt to decode a blank string',
- exc_exec('call json_decode("")'))
- eq('Vim(call):E474: Attempt to decode a blank string',
- exc_exec('call json_decode([])'))
- eq('Vim(call):E474: Attempt to decode a blank string',
- exc_exec('call json_decode([""])'))
- eq('Vim(call):E474: Attempt to decode a blank string',
- exc_exec('call json_decode(" ")'))
- eq('Vim(call):E474: Attempt to decode a blank string',
- exc_exec('call json_decode("\\t")'))
- eq('Vim(call):E474: Attempt to decode a blank string',
- exc_exec('call json_decode("\\n")'))
- eq('Vim(call):E474: Attempt to decode a blank string',
- exc_exec('call json_decode(" \\t\\n \\n\\t\\t \\n\\t\\n \\n \\t\\n\\t ")'))
+ eq('Vim(call):E474: Attempt to decode a blank string', exc_exec('call json_decode("")'))
+ eq('Vim(call):E474: Attempt to decode a blank string', exc_exec('call json_decode([])'))
+ eq('Vim(call):E474: Attempt to decode a blank string', exc_exec('call json_decode([""])'))
+ eq('Vim(call):E474: Attempt to decode a blank string', exc_exec('call json_decode(" ")'))
+ eq('Vim(call):E474: Attempt to decode a blank string', exc_exec('call json_decode("\\t")'))
+ eq('Vim(call):E474: Attempt to decode a blank string', exc_exec('call json_decode("\\n")'))
+ eq(
+ 'Vim(call):E474: Attempt to decode a blank string',
+ exc_exec('call json_decode(" \\t\\n \\n\\t\\t \\n\\t\\n \\n \\t\\n\\t ")')
+ )
end)
it('accepts all spaces in every position where space may be put', function()
- local s = ' \t\n\r \t\r\n \n\t\r \n\r\t \r\t\n \r\n\t\t \n\r\t \r\n\t\n \r\t\n\r \t\r \n\t\r\n \n \t\r\n \r\t\n\t \r\n\t\r \n\r \t\n\r\t \r \t\n\r \n\t\r\t \n\r\t\n \r\n \t\r\n\t'
+ local s =
+ ' \t\n\r \t\r\n \n\t\r \n\r\t \r\t\n \r\n\t\t \n\r\t \r\n\t\n \r\t\n\r \t\r \n\t\r\n \n \t\r\n \r\t\n\t \r\n\t\r \n\r \t\n\r\t \r \t\n\r \n\t\r\t \n\r\t\n \r\n \t\r\n\t'
local str = ('%s{%s"key"%s:%s[%s"val"%s,%s"val2"%s]%s,%s"key2"%s:%s1%s}%s'):gsub('%%s', s)
- eq({key={'val', 'val2'}, key2=1}, funcs.json_decode(str))
+ eq({ key = { 'val', 'val2' }, key2 = 1 }, fn.json_decode(str))
end)
- it('does not overflow when writing error message about decoding ["", ""]',
- function()
- eq('Vim(call):E474: Attempt to decode a blank string',
- pcall_err(command, 'call json_decode(["", ""])'))
+ it('does not overflow when writing error message about decoding ["", ""]', function()
+ eq(
+ 'Vim(call):E474: Attempt to decode a blank string',
+ pcall_err(command, 'call json_decode(["", ""])')
+ )
end)
end)
@@ -530,12 +640,12 @@ describe('json_encode() function', function()
end)
it('dumps strings', function()
- eq('"Test"', funcs.json_encode('Test'))
- eq('""', funcs.json_encode(''))
- eq('"\\t"', funcs.json_encode('\t'))
- eq('"\\n"', funcs.json_encode('\n'))
- eq('"\\u001B"', funcs.json_encode('\27'))
- eq('"þÿþ"', funcs.json_encode('þÿþ'))
+ eq('"Test"', fn.json_encode('Test'))
+ eq('""', fn.json_encode(''))
+ eq('"\\t"', fn.json_encode('\t'))
+ eq('"\\n"', fn.json_encode('\n'))
+ eq('"\\u001B"', fn.json_encode('\27'))
+ eq('"þÿþ"', fn.json_encode('þÿþ'))
end)
it('dumps blobs', function()
@@ -544,43 +654,50 @@ describe('json_encode() function', function()
end)
it('dumps numbers', function()
- eq('0', funcs.json_encode(0))
- eq('10', funcs.json_encode(10))
- eq('-10', funcs.json_encode(-10))
+ eq('0', fn.json_encode(0))
+ eq('10', fn.json_encode(10))
+ eq('-10', fn.json_encode(-10))
end)
it('dumps floats', function()
-- Also test method call (->) syntax
eq('0.0', eval('0.0->json_encode()'))
- eq('10.5', funcs.json_encode(10.5))
- eq('-10.5', funcs.json_encode(-10.5))
- eq('-1.0e-5', funcs.json_encode(-1e-5))
+ eq('10.5', fn.json_encode(10.5))
+ eq('-10.5', fn.json_encode(-10.5))
+ eq('-1.0e-5', fn.json_encode(-1e-5))
eq('1.0e50', eval('1.0e50->json_encode()'))
end)
it('fails to dump NaN and infinite values', function()
- eq('Vim(call):E474: Unable to represent NaN value in JSON',
- exc_exec('call json_encode(str2float("nan"))'))
- eq('Vim(call):E474: Unable to represent infinity in JSON',
- exc_exec('call json_encode(str2float("inf"))'))
- eq('Vim(call):E474: Unable to represent infinity in JSON',
- exc_exec('call json_encode(-str2float("inf"))'))
+ eq(
+ 'Vim(call):E474: Unable to represent NaN value in JSON',
+ exc_exec('call json_encode(str2float("nan"))')
+ )
+ eq(
+ 'Vim(call):E474: Unable to represent infinity in JSON',
+ exc_exec('call json_encode(str2float("inf"))')
+ )
+ eq(
+ 'Vim(call):E474: Unable to represent infinity in JSON',
+ exc_exec('call json_encode(-str2float("inf"))')
+ )
end)
it('dumps lists', function()
- eq('[]', funcs.json_encode({}))
- eq('[[]]', funcs.json_encode({{}}))
- eq('[[], []]', funcs.json_encode({{}, {}}))
+ eq('[]', fn.json_encode({}))
+ eq('[[]]', fn.json_encode({ {} }))
+ eq('[[], []]', fn.json_encode({ {}, {} }))
end)
it('dumps dictionaries', function()
eq('{}', eval('json_encode({})'))
- eq('{"d": []}', funcs.json_encode({d={}}))
- eq('{"d": [], "e": []}', funcs.json_encode({d={}, e={}}))
+ eq('{"d": []}', fn.json_encode({ d = {} }))
+ eq('{"d": [], "e": []}', fn.json_encode({ d = {}, e = {} }))
+ -- Empty keys are allowed per JSON spec (and Vim dicts, and msgpack).
+ eq('{"": []}', fn.json_encode({ [''] = {} }))
end)
- it('cannot dump generic mapping with generic mapping keys and values',
- function()
+ it('cannot dump generic mapping with generic mapping keys and values', function()
command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
command('let todumpv1 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
command('let todumpv2 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
@@ -673,33 +790,43 @@ describe('json_encode() function', function()
end)
it('fails to dump a function reference', function()
- eq('Vim(call):E474: Error while dumping encode_tv2json() argument, itself: attempt to dump function reference',
- exc_exec('call json_encode(function("tr"))'))
+ eq(
+ 'Vim(call):E474: Error while dumping encode_tv2json() argument, itself: attempt to dump function reference',
+ exc_exec('call json_encode(function("tr"))')
+ )
end)
it('fails to dump a partial', function()
command('function T() dict\nendfunction')
- eq('Vim(call):E474: Error while dumping encode_tv2json() argument, itself: attempt to dump function reference',
- exc_exec('call json_encode(function("T", [1, 2], {}))'))
+ eq(
+ 'Vim(call):E474: Error while dumping encode_tv2json() argument, itself: attempt to dump function reference',
+ exc_exec('call json_encode(function("T", [1, 2], {}))')
+ )
end)
it('fails to dump a function reference in a list', function()
- eq('Vim(call):E474: Error while dumping encode_tv2json() argument, index 0: attempt to dump function reference',
- exc_exec('call json_encode([function("tr")])'))
+ eq(
+ 'Vim(call):E474: Error while dumping encode_tv2json() argument, index 0: attempt to dump function reference',
+ exc_exec('call json_encode([function("tr")])')
+ )
end)
it('fails to dump a recursive list', function()
command('let todump = [[[]]]')
command('call add(todump[0][0], todump)')
- eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
- exc_exec('call json_encode(todump)'))
+ eq(
+ 'Vim(call):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('call json_encode(todump)')
+ )
end)
it('fails to dump a recursive dict', function()
command('let todump = {"d": {"d": {}}}')
command('call extend(todump.d.d, {"d": todump})')
- eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
- exc_exec('call json_encode([todump])'))
+ eq(
+ 'Vim(call):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('call json_encode([todump])')
+ )
end)
it('can dump dict with two same dicts inside', function()
@@ -717,58 +844,77 @@ describe('json_encode() function', function()
it('fails to dump a recursive list in a special dict', function()
command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
command('call add(todump._VAL, todump)')
- eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
- exc_exec('call json_encode(todump)'))
+ eq(
+ 'Vim(call):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('call json_encode(todump)')
+ )
end)
it('fails to dump a recursive (val) map in a special dict', function()
command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
command('call add(todump._VAL, ["", todump])')
- eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
- exc_exec('call json_encode([todump])'))
+ eq(
+ 'Vim(call):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('call json_encode([todump])')
+ )
end)
it('fails to dump a recursive (val) map in a special dict, _VAL reference', function()
command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [["", []]]}')
command('call add(todump._VAL[0][1], todump._VAL)')
- eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
- exc_exec('call json_encode(todump)'))
+ eq(
+ 'Vim(call):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('call json_encode(todump)')
+ )
end)
- it('fails to dump a recursive (val) special list in a special dict',
- function()
+ it('fails to dump a recursive (val) special list in a special dict', function()
command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
command('call add(todump._VAL, ["", todump._VAL])')
- eq('Vim(call):E724: unable to correctly dump variable with self-referencing container',
- exc_exec('call json_encode(todump)'))
+ eq(
+ 'Vim(call):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('call json_encode(todump)')
+ )
end)
it('fails when called with no arguments', function()
- eq('Vim(call):E119: Not enough arguments for function: json_encode',
- exc_exec('call json_encode()'))
+ eq(
+ 'Vim(call):E119: Not enough arguments for function: json_encode',
+ exc_exec('call json_encode()')
+ )
end)
it('fails when called with two arguments', function()
- eq('Vim(call):E118: Too many arguments for function: json_encode',
- exc_exec('call json_encode(["", ""], 1)'))
+ eq(
+ 'Vim(call):E118: Too many arguments for function: json_encode',
+ exc_exec('call json_encode(["", ""], 1)')
+ )
end)
it('ignores improper values in &isprint', function()
- meths.set_option_value('isprint', '1', {})
+ api.nvim_set_option_value('isprint', '1', {})
eq(1, eval('"\1" =~# "\\\\p"'))
- eq('"\\u0001"', funcs.json_encode('\1'))
+ eq('"\\u0001"', fn.json_encode('\1'))
end)
it('fails when using surrogate character in a UTF-8 string', function()
- eq('Vim(call):E474: UTF-8 string contains code point which belongs to a surrogate pair: \237\160\128',
- exc_exec('call json_encode("\237\160\128")'))
- eq('Vim(call):E474: UTF-8 string contains code point which belongs to a surrogate pair: \237\175\191',
- exc_exec('call json_encode("\237\175\191")'))
+ eq(
+ 'Vim(call):E474: UTF-8 string contains code point which belongs to a surrogate pair: \237\160\128',
+ exc_exec('call json_encode("\237\160\128")')
+ )
+ eq(
+ 'Vim(call):E474: UTF-8 string contains code point which belongs to a surrogate pair: \237\175\191',
+ exc_exec('call json_encode("\237\175\191")')
+ )
end)
it('dumps control characters as expected', function()
- eq([["\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000B\f\r\u000E\u000F\u0010\u0011\u0012\u0013"]],
- eval('json_encode({"_TYPE": v:msgpack_types.string, "_VAL": ["\n\1\2\3\4\5\6\7\8\9", "\11\12\13\14\15\16\17\18\19"]})'))
+ eq(
+ [["\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\b\t\n\u000B\f\r\u000E\u000F\u0010\u0011\u0012\u0013"]],
+ eval(
+ 'json_encode({"_TYPE": v:msgpack_types.string, "_VAL": ["\n\1\2\3\4\5\6\7\8\9", "\11\12\13\14\15\16\17\18\19"]})'
+ )
+ )
end)
it('can dump NULL string', function()
@@ -788,9 +934,13 @@ describe('json_encode() function', function()
end)
it('fails to parse NULL strings and lists', function()
- eq('Vim(call):E474: Attempt to decode a blank string',
- exc_exec('call json_decode($XXX_UNEXISTENT_VAR_XXX)'))
- eq('Vim(call):E474: Attempt to decode a blank string',
- exc_exec('call json_decode(v:_null_list)'))
+ eq(
+ 'Vim(call):E474: Attempt to decode a blank string',
+ exc_exec('call json_decode($XXX_UNEXISTENT_VAR_XXX)')
+ )
+ eq(
+ 'Vim(call):E474: Attempt to decode a blank string',
+ exc_exec('call json_decode(v:_null_list)')
+ )
end)
end)
diff --git a/test/functional/vimscript/lang_spec.lua b/test/functional/vimscript/lang_spec.lua
index 90437f2ee1..2dde90e334 100644
--- a/test/functional/vimscript/lang_spec.lua
+++ b/test/functional/vimscript/lang_spec.lua
@@ -7,7 +7,7 @@ describe('vimscript', function()
it('parses `<SID>` with turkish locale', function()
if exc_exec('lang ctype tr_TR.UTF-8') ~= 0 then
- pending("Locale tr_TR.UTF-8 not supported")
+ pending('Locale tr_TR.UTF-8 not supported')
return
end
source([[
@@ -22,10 +22,10 @@ describe('vimscript', function()
it('str2float is not affected by locale', function()
if exc_exec('lang ctype sv_SE.UTF-8') ~= 0 then
- pending("Locale sv_SE.UTF-8 not supported")
+ pending('Locale sv_SE.UTF-8 not supported')
return
end
- clear{env={LANG="", LC_NUMERIC="sv_SE.UTF-8"}}
+ clear { env = { LANG = '', LC_NUMERIC = 'sv_SE.UTF-8' } }
eq(2.2, eval('str2float("2.2")'))
end)
end)
diff --git a/test/functional/vimscript/let_spec.lua b/test/functional/vimscript/let_spec.lua
index 11417c5846..15d4b189b8 100644
--- a/test/functional/vimscript/let_spec.lua
+++ b/test/functional/vimscript/let_spec.lua
@@ -4,7 +4,7 @@ local eq = helpers.eq
local clear = helpers.clear
local command = helpers.command
local eval = helpers.eval
-local meths = helpers.meths
+local api = helpers.api
local exec = helpers.exec
local exec_capture = helpers.exec_capture
local expect_exit = helpers.expect_exit
@@ -15,21 +15,24 @@ before_each(clear)
describe(':let', function()
it('correctly lists variables with curly-braces', function()
- meths.set_var('v', {0})
+ api.nvim_set_var('v', { 0 })
eq('v [0]', exec_capture('let {"v"}'))
end)
it('correctly lists variables with subscript', function()
- meths.set_var('v', {0})
+ api.nvim_set_var('v', { 0 })
eq('v[0] #0', exec_capture('let v[0]'))
eq('g:["v"][0] #0', exec_capture('let g:["v"][0]'))
eq('{"g:"}["v"][0] #0', exec_capture('let {"g:"}["v"][0]'))
end)
- it(":unlet self-referencing node in a List graph #6070", function()
+ it(':unlet self-referencing node in a List graph #6070', function()
-- :unlet-ing a self-referencing List must not allow GC on indirectly
-- referenced in-scope Lists. Before #6070 this caused use-after-free.
- expect_exit(1000, source, [=[
+ expect_exit(
+ 1000,
+ source,
+ [=[
let [l1, l2] = [[], []]
echo 'l1:' . id(l1)
echo 'l2:' . id(l2)
@@ -45,10 +48,11 @@ describe(':let', function()
unlet l4
call garbagecollect(1)
call feedkeys(":\e:echo l1 l3\n:echo 42\n:cq\n", "t")
- ]=])
+ ]=]
+ )
end)
- it("multibyte env var #8398 #9267", function()
+ it('multibyte env var #8398 #9267', function()
command("let $NVIM_TEST_LET = 'AìaB'")
eq('AìaB', eval('$NVIM_TEST_LET'))
command("let $NVIM_TEST_LET = 'Aaã‚B'")
@@ -56,12 +60,14 @@ describe(':let', function()
local mbyte = [[\p* .ม .ม .ม .ม่ .ม่ .ม่ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹֻ ֹֻ ֹֻ
.Ö¹Ö» .Ö¹Ö» .Ö¹Ö» Ö»Ö¹ Ö»Ö¹ Ö»Ö¹ .Ö»Ö¹ .Ö»Ö¹ .Ö»Ö¹ Ö¹ Ö¹ Ö¹ .Ö¹ .Ö¹ .Ö¹ Ö¹ Ö¹ Ö¹ .Ö¹ .Ö¹ .Ö¹ Ö¹Ö» Ö¹Ö»
.ֹֻ .ֹֻ .ֹֻ a a a ca ca ca à à à]]
- command("let $NVIM_TEST_LET = '"..mbyte.."'")
+ command("let $NVIM_TEST_LET = '" .. mbyte .. "'")
eq(mbyte, eval('$NVIM_TEST_LET'))
end)
- it("multibyte env var to child process #8398 #9267", function()
- local cmd_get_child_env = ("let g:env_from_child = system(['%s', 'NVIM_TEST_LET'])"):format(testprg('printenv-test'))
+ it('multibyte env var to child process #8398 #9267', function()
+ local cmd_get_child_env = ("let g:env_from_child = system(['%s', 'NVIM_TEST_LET'])"):format(
+ testprg('printenv-test')
+ )
command("let $NVIM_TEST_LET = 'AìaB'")
command(cmd_get_child_env)
eq(eval('$NVIM_TEST_LET'), eval('g:env_from_child'))
@@ -73,12 +79,12 @@ describe(':let', function()
local mbyte = [[\p* .ม .ม .ม .ม่ .ม่ .ม่ ֹ ֹ ֹ .ֹ .ֹ .ֹ ֹֻ ֹֻ ֹֻ
.Ö¹Ö» .Ö¹Ö» .Ö¹Ö» Ö»Ö¹ Ö»Ö¹ Ö»Ö¹ .Ö»Ö¹ .Ö»Ö¹ .Ö»Ö¹ Ö¹ Ö¹ Ö¹ .Ö¹ .Ö¹ .Ö¹ Ö¹ Ö¹ Ö¹ .Ö¹ .Ö¹ .Ö¹ Ö¹Ö» Ö¹Ö»
.ֹֻ .ֹֻ .ֹֻ a a a ca ca ca à à à]]
- command("let $NVIM_TEST_LET = '"..mbyte.."'")
+ command("let $NVIM_TEST_LET = '" .. mbyte .. "'")
command(cmd_get_child_env)
eq(eval('$NVIM_TEST_LET'), eval('g:env_from_child'))
end)
- it("release of list assigned to l: variable does not trigger assertion #12387, #12430", function()
+ it('release of list assigned to l: variable does not trigger assertion #12387, #12430', function()
source([[
func! s:f()
let l:x = [1]
@@ -94,17 +100,17 @@ describe(':let', function()
end)
it('can apply operator to boolean option', function()
- eq(true, meths.get_option_value('equalalways', {}))
+ eq(true, api.nvim_get_option_value('equalalways', {}))
command('let &equalalways -= 1')
- eq(false, meths.get_option_value('equalalways', {}))
+ eq(false, api.nvim_get_option_value('equalalways', {}))
command('let &equalalways += 1')
- eq(true, meths.get_option_value('equalalways', {}))
+ eq(true, api.nvim_get_option_value('equalalways', {}))
command('let &equalalways *= 1')
- eq(true, meths.get_option_value('equalalways', {}))
+ eq(true, api.nvim_get_option_value('equalalways', {}))
command('let &equalalways /= 1')
- eq(true, meths.get_option_value('equalalways', {}))
+ eq(true, api.nvim_get_option_value('equalalways', {}))
command('let &equalalways %= 1')
- eq(false, meths.get_option_value('equalalways', {}))
+ eq(false, api.nvim_get_option_value('equalalways', {}))
end)
end)
diff --git a/test/functional/vimscript/map_functions_spec.lua b/test/functional/vimscript/map_functions_spec.lua
index acba5e9708..59d427ca90 100644
--- a/test/functional/vimscript/map_functions_spec.lua
+++ b/test/functional/vimscript/map_functions_spec.lua
@@ -7,9 +7,8 @@ local exec = helpers.exec
local exec_lua = helpers.exec_lua
local expect = helpers.expect
local feed = helpers.feed
-local funcs = helpers.funcs
-local meths = helpers.meths
-local nvim = helpers.nvim
+local fn = helpers.fn
+local api = helpers.api
local source = helpers.source
local command = helpers.command
local exec_capture = helpers.exec_capture
@@ -19,65 +18,65 @@ describe('maparg()', function()
before_each(clear)
local foo_bar_map_table = {
- lhs='foo',
- lhsraw='foo',
- script=0,
- silent=0,
- rhs='bar',
- expr=0,
- sid=0,
- scriptversion=1,
- buffer=0,
- nowait=0,
- mode='n',
- mode_bits=0x01,
- abbr=0,
- noremap=1,
- lnum=0,
- }
+ lhs = 'foo',
+ lhsraw = 'foo',
+ script = 0,
+ silent = 0,
+ rhs = 'bar',
+ expr = 0,
+ sid = 0,
+ scriptversion = 1,
+ buffer = 0,
+ nowait = 0,
+ mode = 'n',
+ mode_bits = 0x01,
+ abbr = 0,
+ noremap = 1,
+ lnum = 0,
+ }
it('returns a dictionary', function()
- nvim('command', 'nnoremap foo bar')
- eq('bar', funcs.maparg('foo'))
- eq(foo_bar_map_table, funcs.maparg('foo', 'n', false, true))
+ command('nnoremap foo bar')
+ eq('bar', fn.maparg('foo'))
+ eq(foo_bar_map_table, fn.maparg('foo', 'n', false, true))
end)
it('returns 1 for silent when <silent> is used', function()
- nvim('command', 'nnoremap <silent> foo bar')
- eq(1, funcs.maparg('foo', 'n', false, true)['silent'])
+ command('nnoremap <silent> foo bar')
+ eq(1, fn.maparg('foo', 'n', false, true)['silent'])
- nvim('command', 'nnoremap baz bat')
- eq(0, funcs.maparg('baz', 'n', false, true)['silent'])
+ command('nnoremap baz bat')
+ eq(0, fn.maparg('baz', 'n', false, true)['silent'])
end)
it('returns an empty string when no map is present', function()
- eq('', funcs.maparg('not a mapping'))
+ eq('', fn.maparg('not a mapping'))
end)
it('returns an empty dictionary when no map is present and dict is requested', function()
- eq({}, funcs.maparg('not a mapping', 'n', false, true))
+ eq({}, fn.maparg('not a mapping', 'n', false, true))
end)
it('returns the same value for noremap and <script>', function()
- nvim('command', 'inoremap <script> hello world')
- nvim('command', 'inoremap this that')
+ command('inoremap <script> hello world')
+ command('inoremap this that')
eq(
- funcs.maparg('hello', 'i', false, true)['noremap'],
- funcs.maparg('this', 'i', false, true)['noremap']
- )
+ fn.maparg('hello', 'i', false, true)['noremap'],
+ fn.maparg('this', 'i', false, true)['noremap']
+ )
end)
it('returns a boolean for buffer', function()
-- Open enough windows to know we aren't on buffer number 1
- nvim('command', 'new')
- nvim('command', 'new')
- nvim('command', 'new')
- nvim('command', 'cnoremap <buffer> this that')
- eq(1, funcs.maparg('this', 'c', false, true)['buffer'])
+ command('new')
+ command('new')
+ command('new')
+ command('cnoremap <buffer> this that')
+ eq(1, fn.maparg('this', 'c', false, true)['buffer'])
-- Global will return 0 always
- nvim('command', 'nnoremap other another')
- eq(0, funcs.maparg('other', 'n', false, true)['buffer'])
+ command('nnoremap other another')
+ eq(0, fn.maparg('other', 'n', false, true)['buffer'])
end)
it('returns script numbers', function()
@@ -88,8 +87,8 @@ describe('maparg()', function()
nnoremap fizz :call <SID>maparg_test_function()<CR>
]])
- eq(1, funcs.maparg('fizz', 'n', false, true)['sid'])
- eq('testing', nvim('call_function', '<SNR>1_maparg_test_function', {}))
+ eq(1, fn.maparg('fizz', 'n', false, true)['sid'])
+ eq('testing', api.nvim_call_function('<SNR>1_maparg_test_function', {}))
end)
it('works with <F12> and others', function()
@@ -104,7 +103,7 @@ describe('maparg()', function()
]])
eq(1, eval('g:maparg_test_var'))
- eq(':let g:maparg_test_var = 1<CR>', funcs.maparg('<F12>', 'n', false, true)['rhs'])
+ eq(':let g:maparg_test_var = 1<CR>', fn.maparg('<F12>', 'n', false, true)['rhs'])
end)
it('works with <expr>', function()
@@ -127,7 +126,7 @@ describe('maparg()', function()
]])
eq(1, eval('g:counter'))
- local map_dict = funcs.maparg('<C-L>', 'i', false, true)
+ local map_dict = fn.maparg('<C-L>', 'i', false, true)
eq(1, map_dict['expr'])
eq('i', map_dict['mode'])
end)
@@ -135,7 +134,7 @@ describe('maparg()', function()
it('works with combining characters', function()
-- Using addacutes to make combining character better visible
local function ac(s)
- local acute = '\204\129' -- U+0301 COMBINING ACUTE ACCENT
+ local acute = '\204\129' -- U+0301 COMBINING ACUTE ACCENT
local ret = s:gsub('`', acute)
return ret
end
@@ -144,10 +143,10 @@ describe('maparg()', function()
nnoremap c` d
nnoremap e` f`
]]))
- eq(ac('b`'), funcs.maparg(ac('a')))
- eq(ac(''), funcs.maparg(ac('c')))
- eq(ac('d'), funcs.maparg(ac('c`')))
- eq(ac('f`'), funcs.maparg(ac('e`')))
+ eq(ac('b`'), fn.maparg(ac('a')))
+ eq(ac(''), fn.maparg(ac('c')))
+ eq(ac('d'), fn.maparg(ac('c`')))
+ eq(ac('f`'), fn.maparg(ac('e`')))
local function acmap(lhs, rhs)
return {
@@ -170,35 +169,45 @@ describe('maparg()', function()
}
end
- eq({}, funcs.maparg(ac('c'), 'n', 0, 1))
- eq(acmap('a', 'b`'), funcs.maparg(ac('a'), 'n', 0, 1))
- eq(acmap('c`', 'd'), funcs.maparg(ac('c`'), 'n', 0, 1))
- eq(acmap('e`', 'f`'), funcs.maparg(ac('e`'), 'n', 0, 1))
+ eq({}, fn.maparg(ac('c'), 'n', 0, 1))
+ eq(acmap('a', 'b`'), fn.maparg(ac('a'), 'n', 0, 1))
+ eq(acmap('c`', 'd'), fn.maparg(ac('c`'), 'n', 0, 1))
+ eq(acmap('e`', 'f`'), fn.maparg(ac('e`'), 'n', 0, 1))
end)
end)
describe('mapset()', function()
before_each(clear)
+ it('can restore mapping with backslash in lhs', function()
+ api.nvim_set_keymap('n', '\\ab', 'a', {})
+ eq('\nn \\ab a', exec_capture('nmap \\ab'))
+ local mapargs = fn.maparg('\\ab', 'n', false, true)
+ api.nvim_set_keymap('n', '\\ab', 'b', {})
+ eq('\nn \\ab b', exec_capture('nmap \\ab'))
+ fn.mapset('n', false, mapargs)
+ eq('\nn \\ab a', exec_capture('nmap \\ab'))
+ end)
+
it('can restore mapping description from the dict returned by maparg()', function()
- meths.set_keymap('n', 'lhs', 'rhs', {desc = 'map description'})
- eq('\nn lhs rhs\n map description', exec_capture("nmap lhs"))
- local mapargs = funcs.maparg('lhs', 'n', false, true)
- meths.set_keymap('n', 'lhs', 'rhs', {desc = 'MAP DESCRIPTION'})
- eq('\nn lhs rhs\n MAP DESCRIPTION', exec_capture("nmap lhs"))
- funcs.mapset('n', false, mapargs)
- eq('\nn lhs rhs\n map description', exec_capture("nmap lhs"))
+ api.nvim_set_keymap('n', 'lhs', 'rhs', { desc = 'map description' })
+ eq('\nn lhs rhs\n map description', exec_capture('nmap lhs'))
+ local mapargs = fn.maparg('lhs', 'n', false, true)
+ api.nvim_set_keymap('n', 'lhs', 'rhs', { desc = 'MAP DESCRIPTION' })
+ eq('\nn lhs rhs\n MAP DESCRIPTION', exec_capture('nmap lhs'))
+ fn.mapset('n', false, mapargs)
+ eq('\nn lhs rhs\n map description', exec_capture('nmap lhs'))
end)
it('can restore "replace_keycodes" from the dict returned by maparg()', function()
- meths.set_keymap('i', 'foo', [['<l' .. 't>']], {expr = true, replace_keycodes = true})
+ api.nvim_set_keymap('i', 'foo', [['<l' .. 't>']], { expr = true, replace_keycodes = true })
feed('Afoo')
expect('<')
- local mapargs = funcs.maparg('foo', 'i', false, true)
- meths.set_keymap('i', 'foo', [['<l' .. 't>']], {expr = true})
+ local mapargs = fn.maparg('foo', 'i', false, true)
+ api.nvim_set_keymap('i', 'foo', [['<l' .. 't>']], { expr = true })
feed('foo')
expect('<<lt>')
- funcs.mapset('i', false, mapargs)
+ fn.mapset('i', false, mapargs)
feed('foo')
expect('<<lt><')
end)
@@ -208,23 +217,26 @@ describe('mapset()', function()
eq('\ni foo * bar', exec_capture('iabbr foo'))
feed('ifoo ')
expect('bar ')
- local mapargs = funcs.maparg('foo', 'i', true, true)
+ local mapargs = fn.maparg('foo', 'i', true, true)
command('inoreabbr foo BAR')
eq('\ni foo * BAR', exec_capture('iabbr foo'))
feed('foo ')
expect('bar BAR ')
- funcs.mapset('i', true, mapargs)
+ fn.mapset('i', true, mapargs)
eq('\ni foo * bar', exec_capture('iabbr foo'))
feed('foo<Esc>')
expect('bar BAR bar')
end)
it('can restore Lua callback from the dict returned by maparg()', function()
- eq(0, exec_lua([[
+ eq(
+ 0,
+ exec_lua([[
GlobalCount = 0
vim.api.nvim_set_keymap('n', 'asdf', '', {callback = function() GlobalCount = GlobalCount + 1 end })
return GlobalCount
- ]]))
+ ]])
+ )
feed('asdf')
eq(1, exec_lua([[return GlobalCount]]))
@@ -252,9 +264,13 @@ describe('mapset()', function()
end)
it('does not leak memory if lhs is missing', function()
- eq('Vim:E460: Entries missing in mapset() dict argument',
- pcall_err(exec_lua, [[vim.fn.mapset('n', false, {rhs = 'foo'})]]))
- eq('Vim:E460: Entries missing in mapset() dict argument',
- pcall_err(exec_lua, [[vim.fn.mapset('n', false, {callback = function() end})]]))
+ eq(
+ 'Vim:E460: Entries missing in mapset() dict argument',
+ pcall_err(exec_lua, [[vim.fn.mapset('n', false, {rhs = 'foo'})]])
+ )
+ eq(
+ 'Vim:E460: Entries missing in mapset() dict argument',
+ pcall_err(exec_lua, [[vim.fn.mapset('n', false, {callback = function() end})]])
+ )
end)
end)
diff --git a/test/functional/vimscript/match_functions_spec.lua b/test/functional/vimscript/match_functions_spec.lua
index 9f168c913a..3db612e472 100644
--- a/test/functional/vimscript/match_functions_spec.lua
+++ b/test/functional/vimscript/match_functions_spec.lua
@@ -3,155 +3,198 @@ local Screen = require('test.functional.ui.screen')
local eq = helpers.eq
local clear = helpers.clear
-local funcs = helpers.funcs
+local fn = helpers.fn
local command = helpers.command
local exc_exec = helpers.exc_exec
before_each(clear)
describe('setmatches()', function()
- it('correctly handles case when both group and pattern entries are numbers',
- function()
+ it('correctly handles case when both group and pattern entries are numbers', function()
command('hi def link 1 PreProc')
- eq(0, funcs.setmatches({{group=1, pattern=2, id=3, priority=4}}))
- eq({{
- group='1',
- pattern='2',
- id=3,
- priority=4,
- }}, funcs.getmatches())
- eq(0, funcs.setmatches({{group=1, pattern=2, id=3, priority=4, conceal=5}}))
- eq({{
- group='1',
- pattern='2',
- id=3,
- priority=4,
- conceal='5',
- }}, funcs.getmatches())
- eq(0, funcs.setmatches({{group=1, pos1={2}, pos2={6}, id=3, priority=4, conceal=5}}))
- eq({{
- group='1',
- pos1={2},
- pos2={6},
- id=3,
- priority=4,
- conceal='5',
- }}, funcs.getmatches())
+ eq(0, fn.setmatches({ { group = 1, pattern = 2, id = 3, priority = 4 } }))
+ eq({
+ {
+ group = '1',
+ pattern = '2',
+ id = 3,
+ priority = 4,
+ },
+ }, fn.getmatches())
+ eq(0, fn.setmatches({ { group = 1, pattern = 2, id = 3, priority = 4, conceal = 5 } }))
+ eq({
+ {
+ group = '1',
+ pattern = '2',
+ id = 3,
+ priority = 4,
+ conceal = '5',
+ },
+ }, fn.getmatches())
+ eq(
+ 0,
+ fn.setmatches({
+ { group = 1, pos1 = { 2 }, pos2 = { 6 }, id = 3, priority = 4, conceal = 5 },
+ })
+ )
+ eq({
+ {
+ group = '1',
+ pos1 = { 2 },
+ pos2 = { 6 },
+ id = 3,
+ priority = 4,
+ conceal = '5',
+ },
+ }, fn.getmatches())
end)
it('does not fail if highlight group is not defined', function()
- eq(0, funcs.setmatches{{group=1, pattern=2, id=3, priority=4}})
- eq({{group='1', pattern='2', id=3, priority=4}},
- funcs.getmatches())
- eq(0, funcs.setmatches{{group=1, pos1={2}, pos2={6}, id=3, priority=4, conceal=5}})
- eq({{group='1', pos1={2}, pos2={6}, id=3, priority=4, conceal='5'}},
- funcs.getmatches())
+ eq(0, fn.setmatches { { group = 1, pattern = 2, id = 3, priority = 4 } })
+ eq({ { group = '1', pattern = '2', id = 3, priority = 4 } }, fn.getmatches())
+ eq(
+ 0,
+ fn.setmatches {
+ { group = 1, pos1 = { 2 }, pos2 = { 6 }, id = 3, priority = 4, conceal = 5 },
+ }
+ )
+ eq(
+ { { group = '1', pos1 = { 2 }, pos2 = { 6 }, id = 3, priority = 4, conceal = '5' } },
+ fn.getmatches()
+ )
end)
end)
describe('matchadd()', function()
- it('correctly works when first two arguments and conceal are numbers at once',
- function()
+ it('correctly works when first two arguments and conceal are numbers at once', function()
command('hi def link 1 PreProc')
- eq(4, funcs.matchadd(1, 2, 3, 4, {conceal=5}))
- eq({{
- group='1',
- pattern='2',
- priority=3,
- id=4,
- conceal='5',
- }}, funcs.getmatches())
+ eq(4, fn.matchadd(1, 2, 3, 4, { conceal = 5 }))
+ eq({
+ {
+ group = '1',
+ pattern = '2',
+ priority = 3,
+ id = 4,
+ conceal = '5',
+ },
+ }, fn.getmatches())
end)
end)
describe('matchaddpos()', function()
it('errors out on invalid input', function()
command('hi clear PreProc')
- eq('Vim(let):E5030: Empty list at position 0',
- exc_exec('let val = matchaddpos("PreProc", [[]])'))
- eq('Vim(let):E5030: Empty list at position 1',
- exc_exec('let val = matchaddpos("PreProc", [1, v:_null_list])'))
- eq('Vim(let):E5031: List or number required at position 1',
- exc_exec('let val = matchaddpos("PreProc", [1, v:_null_dict])'))
+ eq(
+ 'Vim(let):E5030: Empty list at position 0',
+ exc_exec('let val = matchaddpos("PreProc", [[]])')
+ )
+ eq(
+ 'Vim(let):E5030: Empty list at position 1',
+ exc_exec('let val = matchaddpos("PreProc", [1, v:_null_list])')
+ )
+ eq(
+ 'Vim(let):E5031: List or number required at position 1',
+ exc_exec('let val = matchaddpos("PreProc", [1, v:_null_dict])')
+ )
end)
it('works with 0 lnum', function()
command('hi clear PreProc')
- eq(4, funcs.matchaddpos('PreProc', {1}, 3, 4))
- eq({{
- group='PreProc',
- pos1 = {1},
- priority=3,
- id=4,
- }}, funcs.getmatches())
- funcs.matchdelete(4)
- eq(4, funcs.matchaddpos('PreProc', {{0}, 1}, 3, 4))
- eq({{
- group='PreProc',
- pos1 = {1},
- priority=3,
- id=4,
- }}, funcs.getmatches())
- funcs.matchdelete(4)
- eq(4, funcs.matchaddpos('PreProc', {0, 1}, 3, 4))
- eq({{
- group='PreProc',
- pos1 = {1},
- priority=3,
- id=4,
- }}, funcs.getmatches())
+ eq(4, fn.matchaddpos('PreProc', { 1 }, 3, 4))
+ eq({
+ {
+ group = 'PreProc',
+ pos1 = { 1 },
+ priority = 3,
+ id = 4,
+ },
+ }, fn.getmatches())
+ fn.matchdelete(4)
+ eq(4, fn.matchaddpos('PreProc', { { 0 }, 1 }, 3, 4))
+ eq({
+ {
+ group = 'PreProc',
+ pos1 = { 1 },
+ priority = 3,
+ id = 4,
+ },
+ }, fn.getmatches())
+ fn.matchdelete(4)
+ eq(4, fn.matchaddpos('PreProc', { 0, 1 }, 3, 4))
+ eq({
+ {
+ group = 'PreProc',
+ pos1 = { 1 },
+ priority = 3,
+ id = 4,
+ },
+ }, fn.getmatches())
end)
it('works with negative numbers', function()
command('hi clear PreProc')
- eq(4, funcs.matchaddpos('PreProc', {-10, 1}, 3, 4))
- eq({{
- group='PreProc',
- pos1 = {1},
- priority=3,
- id=4,
- }}, funcs.getmatches())
- funcs.matchdelete(4)
- eq(4, funcs.matchaddpos('PreProc', {{-10}, 1}, 3, 4))
- eq({{
- group='PreProc',
- pos1 = {1},
- priority=3,
- id=4,
- }}, funcs.getmatches())
- funcs.matchdelete(4)
- eq(4, funcs.matchaddpos('PreProc', {{2, -1}, 1}, 3, 4))
- eq({{
- group='PreProc',
- pos1 = {1},
- priority=3,
- id=4,
- }}, funcs.getmatches())
- funcs.matchdelete(4)
- eq(4, funcs.matchaddpos('PreProc', {{2, 0, -1}, 1}, 3, 4))
- eq({{
- group='PreProc',
- pos1 = {1},
- priority=3,
- id=4,
- }}, funcs.getmatches())
+ eq(4, fn.matchaddpos('PreProc', { -10, 1 }, 3, 4))
+ eq({
+ {
+ group = 'PreProc',
+ pos1 = { 1 },
+ priority = 3,
+ id = 4,
+ },
+ }, fn.getmatches())
+ fn.matchdelete(4)
+ eq(4, fn.matchaddpos('PreProc', { { -10 }, 1 }, 3, 4))
+ eq({
+ {
+ group = 'PreProc',
+ pos1 = { 1 },
+ priority = 3,
+ id = 4,
+ },
+ }, fn.getmatches())
+ fn.matchdelete(4)
+ eq(4, fn.matchaddpos('PreProc', { { 2, -1 }, 1 }, 3, 4))
+ eq({
+ {
+ group = 'PreProc',
+ pos1 = { 1 },
+ priority = 3,
+ id = 4,
+ },
+ }, fn.getmatches())
+ fn.matchdelete(4)
+ eq(4, fn.matchaddpos('PreProc', { { 2, 0, -1 }, 1 }, 3, 4))
+ eq({
+ {
+ group = 'PreProc',
+ pos1 = { 1 },
+ priority = 3,
+ id = 4,
+ },
+ }, fn.getmatches())
end)
it('works with zero length', function()
local screen = Screen.new(40, 5)
screen:attach()
- funcs.setline(1, 'abcdef')
+ fn.setline(1, 'abcdef')
command('hi PreProc guifg=Red')
- eq(4, funcs.matchaddpos('PreProc', {{1, 2, 0}}, 3, 4))
- eq({{
- group='PreProc',
- pos1 = {1, 2, 0},
- priority=3,
- id=4,
- }}, funcs.getmatches())
- screen:expect([[
+ eq(4, fn.matchaddpos('PreProc', { { 1, 2, 0 } }, 3, 4))
+ eq({
+ {
+ group = 'PreProc',
+ pos1 = { 1, 2, 0 },
+ priority = 3,
+ id = 4,
+ },
+ }, fn.getmatches())
+ screen:expect(
+ [[
^a{1:b}cdef |
- {2:~ }|
- {2:~ }|
- {2:~ }|
+ {2:~ }|*3
|
- ]], {[1] = {foreground = Screen.colors.Red}, [2] = {bold = true, foreground = Screen.colors.Blue1}})
+ ]],
+ {
+ [1] = { foreground = Screen.colors.Red },
+ [2] = { bold = true, foreground = Screen.colors.Blue1 },
+ }
+ )
end)
end)
diff --git a/test/functional/vimscript/minmax_functions_spec.lua b/test/functional/vimscript/minmax_functions_spec.lua
index 91106bef1e..c4a986bc8c 100644
--- a/test/functional/vimscript/minmax_functions_spec.lua
+++ b/test/functional/vimscript/minmax_functions_spec.lua
@@ -4,18 +4,21 @@ local eq = helpers.eq
local eval = helpers.eval
local command = helpers.command
local clear = helpers.clear
-local funcs = helpers.funcs
+local fn = helpers.fn
local pcall_err = helpers.pcall_err
before_each(clear)
-for _, func in ipairs({'min', 'max'}) do
+for _, func in ipairs({ 'min', 'max' }) do
describe(func .. '()', function()
- it('gives a single error message when multiple values failed conversions',
- function()
- eq('Vim(echo):E745: Using a List as a Number',
- pcall_err(command, 'echo ' .. func .. '([-5, [], [], [], 5])'))
- eq('Vim(echo):E745: Using a List as a Number',
- pcall_err(command, 'echo ' .. func .. '({1:-5, 2:[], 3:[], 4:[], 5:5})'))
+ it('gives a single error message when multiple values failed conversions', function()
+ eq(
+ 'Vim(echo):E745: Using a List as a Number',
+ pcall_err(command, 'echo ' .. func .. '([-5, [], [], [], 5])')
+ )
+ eq(
+ 'Vim(echo):E745: Using a List as a Number',
+ pcall_err(command, 'echo ' .. func .. '({1:-5, 2:[], 3:[], 4:[], 5:5})')
+ )
for errmsg, errinput in pairs({
['Vim(echo):E745: Using a List as a Number'] = '[]',
['Vim(echo):E805: Using a Float as a Number'] = '0.0',
@@ -27,22 +30,30 @@ for _, func in ipairs({'min', 'max'}) do
end
end)
it('works with arrays/dictionaries with zero items', function()
- eq(0, funcs[func]({}))
+ eq(0, fn[func]({}))
eq(0, eval(func .. '({})'))
end)
it('works with arrays/dictionaries with one item', function()
- eq(5, funcs[func]({5}))
- eq(5, funcs[func]({test=5}))
+ eq(5, fn[func]({ 5 }))
+ eq(5, fn[func]({ test = 5 }))
end)
it('works with NULL arrays/dictionaries', function()
eq(0, eval(func .. '(v:_null_list)'))
eq(0, eval(func .. '(v:_null_dict)'))
end)
it('errors out for invalid types', function()
- for _, errinput in ipairs({'1', 'v:true', 'v:false', 'v:null',
- 'function("tr")', '""'}) do
- eq(('Vim(echo):E712: Argument of %s() must be a List or Dictionary'):format(func),
- pcall_err(command, 'echo ' .. func .. '(' .. errinput .. ')'))
+ for _, errinput in ipairs({
+ '1',
+ 'v:true',
+ 'v:false',
+ 'v:null',
+ 'function("tr")',
+ '""',
+ }) do
+ eq(
+ ('Vim(echo):E712: Argument of %s() must be a List or Dictionary'):format(func),
+ pcall_err(command, 'echo ' .. func .. '(' .. errinput .. ')')
+ )
end
end)
end)
diff --git a/test/functional/vimscript/modeline_spec.lua b/test/functional/vimscript/modeline_spec.lua
index b2346079a1..ae63a66f43 100644
--- a/test/functional/vimscript/modeline_spec.lua
+++ b/test/functional/vimscript/modeline_spec.lua
@@ -2,7 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
local assert_alive = helpers.assert_alive
local clear, command, write_file = helpers.clear, helpers.command, helpers.write_file
-describe("modeline", function()
+describe('modeline', function()
local tempfile = helpers.tmpname()
before_each(clear)
diff --git a/test/functional/vimscript/msgpack_functions_spec.lua b/test/functional/vimscript/msgpack_functions_spec.lua
index de5a721efe..609a706155 100644
--- a/test/functional/vimscript/msgpack_functions_spec.lua
+++ b/test/functional/vimscript/msgpack_functions_spec.lua
@@ -1,9 +1,9 @@
local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
-local funcs = helpers.funcs
+local fn = helpers.fn
local eval, eq = helpers.eval, helpers.eq
local command = helpers.command
-local nvim = helpers.nvim
+local api = helpers.api
local exc_exec = helpers.exc_exec
local is_os = helpers.is_os
@@ -12,7 +12,7 @@ describe('msgpack*() functions', function()
local obj_test = function(msg, obj)
it(msg, function()
- nvim('set_var', 'obj', obj)
+ api.nvim_set_var('obj', obj)
eq(obj, eval('msgpackparse(msgpackdump(g:obj))'))
eq(obj, eval('msgpackparse(msgpackdump(g:obj, "B"))'))
end)
@@ -20,17 +20,18 @@ describe('msgpack*() functions', function()
-- Regression test: msgpack_list_write was failing to write buffer with zero
-- length.
- obj_test('are able to dump and restore {"file": ""}', {{file=''}})
+ obj_test('are able to dump and restore {"file": ""}', { { file = '' } })
-- Regression test: msgpack_list_write was failing to write buffer with NL at
-- the end.
- obj_test('are able to dump and restore {0, "echo mpack"}', {{0, 'echo mpack'}})
- obj_test('are able to dump and restore "Test\\n"', {'Test\n'})
+ obj_test('are able to dump and restore {0, "echo mpack"}', { { 0, 'echo mpack' } })
+ obj_test('are able to dump and restore "Test\\n"', { 'Test\n' })
-- Regression test: msgpack_list_write was failing to write buffer with NL
-- inside.
- obj_test('are able to dump and restore "Test\\nTest 2"', {'Test\nTest 2'})
+ obj_test('are able to dump and restore "Test\\nTest 2"', { 'Test\nTest 2' })
-- Test that big objects (requirement: dump to something that is bigger then
-- IOSIZE) are also fine. This particular object is obtained by concatenating
-- 5 identical shada files.
+ -- stylua: ignore
local big_obj = {
1, 1436711454, 78, {
encoding="utf-8",
@@ -330,19 +331,18 @@ describe('msgpack*() functions', function()
}
obj_test('are able to dump and restore rather big object', big_obj)
- obj_test('are able to dump and restore floating-point value', {0.125})
+ obj_test('are able to dump and restore floating-point value', { 0.125 })
it('can restore and dump UINT64_MAX', function()
command('let dumped = ["\\xCF" . repeat("\\xFF", 8)]')
command('let parsed = msgpackparse(dumped)')
command('let dumped2 = msgpackdump(parsed)')
- eq(1, eval('type(parsed[0]) == type(0) ' ..
- '|| parsed[0]._TYPE is v:msgpack_types.integer'))
+ eq(1, eval('type(parsed[0]) == type(0) ' .. '|| parsed[0]._TYPE is v:msgpack_types.integer'))
if eval('type(parsed[0]) == type(0)') == 1 then
command('call assert_equal(0xFFFFFFFFFFFFFFFF, parsed[0])')
eq({}, eval('v:errors'))
else
- eq({_TYPE={}, _VAL={1, 3, 0x7FFFFFFF, 0x7FFFFFFF}}, eval('parsed[0]'))
+ eq({ _TYPE = {}, _VAL = { 1, 3, 0x7FFFFFFF, 0x7FFFFFFF } }, eval('parsed[0]'))
end
eq(1, eval('dumped ==# dumped2'))
end)
@@ -351,13 +351,12 @@ describe('msgpack*() functions', function()
command('let dumped = ["\\xD3\\x80" . repeat("\\n", 7)]')
command('let parsed = msgpackparse(dumped)')
command('let dumped2 = msgpackdump(parsed)')
- eq(1, eval('type(parsed[0]) == type(0) ' ..
- '|| parsed[0]._TYPE is v:msgpack_types.integer'))
+ eq(1, eval('type(parsed[0]) == type(0) ' .. '|| parsed[0]._TYPE is v:msgpack_types.integer'))
if eval('type(parsed[0]) == type(0)') == 1 then
command('call assert_equal(-0x7fffffffffffffff - 1, parsed[0])')
eq({}, eval('v:errors'))
else
- eq({_TYPE={}, _VAL={-1, 2, 0, 0}}, eval('parsed[0]'))
+ eq({ _TYPE = {}, _VAL = { -1, 2, 0, 0 } }, eval('parsed[0]'))
end
eq(1, eval('dumped ==# dumped2'))
end)
@@ -366,7 +365,7 @@ describe('msgpack*() functions', function()
command('let dumped = ["\\xC4\\x01\\n"]')
command('let parsed = msgpackparse(dumped)')
command('let dumped2 = msgpackdump(parsed)')
- eq({'\000'}, eval('parsed'))
+ eq({ '\000' }, eval('parsed'))
eq(1, eval('dumped ==# dumped2'))
end)
@@ -374,7 +373,7 @@ describe('msgpack*() functions', function()
command('let dumped = ["\\xA1\\n"]')
command('let parsed = msgpackparse(dumped)')
command('let dumped2 = msgpackdump(parsed)')
- eq({{_TYPE={}, _VAL={'\n'}}}, eval('parsed'))
+ eq({ { _TYPE = {}, _VAL = { '\n' } } }, eval('parsed'))
eq(1, eval('parsed[0]._TYPE is v:msgpack_types.string'))
eq(1, eval('dumped ==# dumped2'))
end)
@@ -383,19 +382,19 @@ describe('msgpack*() functions', function()
command('let dumped = ["\\xC4\\x01", ""]')
command('let parsed = msgpackparse(dumped)')
command('let dumped2 = msgpackdump(parsed)')
- eq({"\n"}, eval('parsed'))
+ eq({ '\n' }, eval('parsed'))
eq(1, eval('dumped ==# dumped2'))
end)
it('dump and restore special mapping with floating-point value', function()
command('let todump = {"_TYPE": v:msgpack_types.float, "_VAL": 0.125}')
- eq({0.125}, eval('msgpackparse(msgpackdump([todump]))'))
+ eq({ 0.125 }, eval('msgpackparse(msgpackdump([todump]))'))
end)
end)
local blobstr = function(list)
local l = {}
- for i,v in ipairs(list) do
+ for i, v in ipairs(list) do
l[i] = v:gsub('\n', '\000')
end
return table.concat(l, '\n')
@@ -403,10 +402,11 @@ end
-- Test msgpackparse() with a readfile()-style list and a blob argument
local parse_eq = function(expect, list_arg)
- local blob_expr = '0z' .. blobstr(list_arg):gsub('(.)', function(c)
- return ('%.2x'):format(c:byte())
- end)
- eq(expect, funcs.msgpackparse(list_arg))
+ local blob_expr = '0z'
+ .. blobstr(list_arg):gsub('(.)', function(c)
+ return ('%.2x'):format(c:byte())
+ end)
+ eq(expect, fn.msgpackparse(list_arg))
command('let g:parsed = msgpackparse(' .. blob_expr .. ')')
eq(expect, eval('g:parsed'))
end
@@ -415,33 +415,33 @@ describe('msgpackparse() function', function()
before_each(clear)
it('restores nil as v:null', function()
- parse_eq(eval('[v:null]'), {'\192'})
+ parse_eq(eval('[v:null]'), { '\192' })
end)
it('restores boolean false as v:false', function()
- parse_eq({false}, {'\194'})
+ parse_eq({ false }, { '\194' })
end)
it('restores boolean true as v:true', function()
- parse_eq({true}, {'\195'})
+ parse_eq({ true }, { '\195' })
end)
it('restores FIXSTR as special dict', function()
- parse_eq({{_TYPE={}, _VAL={'ab'}}}, {'\162ab'})
+ parse_eq({ { _TYPE = {}, _VAL = { 'ab' } } }, { '\162ab' })
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.string'))
end)
it('restores BIN 8 as string', function()
- parse_eq({'ab'}, {'\196\002ab'})
+ parse_eq({ 'ab' }, { '\196\002ab' })
end)
it('restores FIXEXT1 as special dictionary', function()
- parse_eq({{_TYPE={}, _VAL={0x10, {"", ""}}}}, {'\212\016', ''})
+ parse_eq({ { _TYPE = {}, _VAL = { 0x10, { '', '' } } } }, { '\212\016', '' })
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.ext'))
end)
it('restores MAP with BIN key as special dictionary', function()
- parse_eq({{_TYPE={}, _VAL={{'a', ''}}}}, {'\129\196\001a\196\n'})
+ parse_eq({ { _TYPE = {}, _VAL = { { 'a', '' } } } }, { '\129\196\001a\196\n' })
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map'))
end)
@@ -449,72 +449,93 @@ describe('msgpackparse() function', function()
command('let dumped = ["\\x82\\xA1a\\xC4\\n\\xA1a\\xC4\\n"]')
-- FIXME Internal error bug, can't use parse_eq() here
command('silent! let parsed = msgpackparse(dumped)')
- eq({{_TYPE={}, _VAL={ {{_TYPE={}, _VAL={'a'}}, ''},
- {{_TYPE={}, _VAL={'a'}}, ''}}} }, eval('parsed'))
+ eq({
+ {
+ _TYPE = {},
+ _VAL = {
+ { { _TYPE = {}, _VAL = { 'a' } }, '' },
+ { { _TYPE = {}, _VAL = { 'a' } }, '' },
+ },
+ },
+ }, eval('parsed'))
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map'))
eq(1, eval('g:parsed[0]._VAL[0][0]._TYPE is v:msgpack_types.string'))
eq(1, eval('g:parsed[0]._VAL[1][0]._TYPE is v:msgpack_types.string'))
end)
it('restores MAP with MAP key as special dictionary', function()
- parse_eq({{_TYPE={}, _VAL={{{}, ''}}}}, {'\129\128\196\n'})
+ parse_eq({ { _TYPE = {}, _VAL = { { {}, '' } } } }, { '\129\128\196\n' })
eq(1, eval('g:parsed[0]._TYPE is v:msgpack_types.map'))
end)
it('msgpackparse(systemlist(...)) does not segfault. #3135', function()
- local cmd = "sort(keys(msgpackparse(systemlist('"
- ..helpers.nvim_prog.." --api-info'))[0]))"
+ local cmd = "sort(keys(msgpackparse(systemlist('" .. helpers.nvim_prog .. " --api-info'))[0]))"
eval(cmd)
- eval(cmd) -- do it again (try to force segfault)
- local api_info = eval(cmd) -- do it again
+ eval(cmd) -- do it again (try to force segfault)
+ local api_info = eval(cmd) -- do it again
if is_os('win') then
helpers.assert_alive()
pending('msgpackparse() has a bug on windows')
return
end
- eq({'error_types', 'functions', 'types',
- 'ui_events', 'ui_options', 'version'}, api_info)
+ eq({ 'error_types', 'functions', 'types', 'ui_events', 'ui_options', 'version' }, api_info)
end)
it('fails when called with no arguments', function()
- eq('Vim(call):E119: Not enough arguments for function: msgpackparse',
- exc_exec('call msgpackparse()'))
+ eq(
+ 'Vim(call):E119: Not enough arguments for function: msgpackparse',
+ exc_exec('call msgpackparse()')
+ )
end)
it('fails when called with two arguments', function()
- eq('Vim(call):E118: Too many arguments for function: msgpackparse',
- exc_exec('call msgpackparse(["", ""], 1)'))
+ eq(
+ 'Vim(call):E118: Too many arguments for function: msgpackparse',
+ exc_exec('call msgpackparse(["", ""], 1)')
+ )
end)
it('fails to parse a string', function()
- eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
- exc_exec('call msgpackparse("abcdefghijklmnopqrstuvwxyz")'))
+ eq(
+ 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
+ exc_exec('call msgpackparse("abcdefghijklmnopqrstuvwxyz")')
+ )
end)
it('fails to parse a number', function()
- eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
- exc_exec('call msgpackparse(127)'))
+ eq(
+ 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
+ exc_exec('call msgpackparse(127)')
+ )
end)
it('fails to parse a dictionary', function()
- eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
- exc_exec('call msgpackparse({})'))
+ eq(
+ 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
+ exc_exec('call msgpackparse({})')
+ )
end)
it('fails to parse a funcref', function()
- eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
- exc_exec('call msgpackparse(function("tr"))'))
+ eq(
+ 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
+ exc_exec('call msgpackparse(function("tr"))')
+ )
end)
it('fails to parse a partial', function()
command('function T() dict\nendfunction')
- eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
- exc_exec('call msgpackparse(function("T", [1, 2], {}))'))
+ eq(
+ 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
+ exc_exec('call msgpackparse(function("T", [1, 2], {}))')
+ )
end)
it('fails to parse a float', function()
- eq('Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
- exc_exec('call msgpackparse(0.0)'))
+ eq(
+ 'Vim(call):E899: Argument of msgpackparse() must be a List or Blob',
+ exc_exec('call msgpackparse(0.0)')
+ )
end)
it('fails on incomplete msgpack string', function()
@@ -541,11 +562,11 @@ describe('msgpackdump() function', function()
end
it('dumps string as BIN 8', function()
- dump_eq({'\196\004Test'}, '["Test"]')
+ dump_eq({ '\196\004Test' }, '["Test"]')
end)
it('dumps blob as BIN 8', function()
- dump_eq({'\196\005Bl\nb!'}, '[0z426c006221]')
+ dump_eq({ '\196\005Bl\nb!' }, '[0z426c006221]')
end)
it('can dump generic mapping with generic mapping keys and values', function()
@@ -553,209 +574,245 @@ describe('msgpackdump() function', function()
command('let todumpv1 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
command('let todumpv2 = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
command('call add(todump._VAL, [todumpv1, todumpv2])')
- dump_eq({'\129\128\128'}, '[todump]')
+ dump_eq({ '\129\128\128' }, '[todump]')
end)
it('can dump v:true', function()
- dump_eq({'\195'}, '[v:true]')
+ dump_eq({ '\195' }, '[v:true]')
end)
it('can dump v:false', function()
- dump_eq({'\194'}, '[v:false]')
+ dump_eq({ '\194' }, '[v:false]')
end)
it('can dump v:null', function()
- dump_eq({'\192'}, '[v:null]')
+ dump_eq({ '\192' }, '[v:null]')
end)
it('can dump special bool mapping (true)', function()
command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 1}')
- dump_eq({'\195'}, '[todump]')
+ dump_eq({ '\195' }, '[todump]')
end)
it('can dump special bool mapping (false)', function()
command('let todump = {"_TYPE": v:msgpack_types.boolean, "_VAL": 0}')
- dump_eq({'\194'}, '[todump]')
+ dump_eq({ '\194' }, '[todump]')
end)
it('can dump special nil mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.nil, "_VAL": 0}')
- dump_eq({'\192'}, '[todump]')
+ dump_eq({ '\192' }, '[todump]')
end)
it('can dump special ext mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.ext, "_VAL": [5, ["",""]]}')
- dump_eq({'\212\005', ''}, '[todump]')
+ dump_eq({ '\212\005', '' }, '[todump]')
end)
it('can dump special array mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": [5, [""]]}')
- dump_eq({'\146\005\145\196\n'}, '[todump]')
+ dump_eq({ '\146\005\145\196\n' }, '[todump]')
end)
it('can dump special UINT64_MAX mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.integer}')
command('let todump._VAL = [1, 3, 0x7FFFFFFF, 0x7FFFFFFF]')
- dump_eq({'\207\255\255\255\255\255\255\255\255'}, '[todump]')
+ dump_eq({ '\207\255\255\255\255\255\255\255\255' }, '[todump]')
end)
it('can dump special INT64_MIN mapping', function()
command('let todump = {"_TYPE": v:msgpack_types.integer}')
command('let todump._VAL = [-1, 2, 0, 0]')
- dump_eq({'\211\128\n\n\n\n\n\n\n'}, '[todump]')
+ dump_eq({ '\211\128\n\n\n\n\n\n\n' }, '[todump]')
end)
it('fails to dump a function reference', function()
command('let Todump = function("tr")')
- eq('Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, itself: attempt to dump function reference',
- exc_exec('call msgpackdump([Todump])'))
+ eq(
+ 'Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, itself: attempt to dump function reference',
+ exc_exec('call msgpackdump([Todump])')
+ )
end)
it('fails to dump a partial', function()
command('function T() dict\nendfunction')
command('let Todump = function("T", [1, 2], {})')
- eq('Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, itself: attempt to dump function reference',
- exc_exec('call msgpackdump([Todump])'))
+ eq(
+ 'Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, itself: attempt to dump function reference',
+ exc_exec('call msgpackdump([Todump])')
+ )
end)
it('fails to dump a function reference in a list', function()
command('let todump = [function("tr")]')
- eq('Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, index 0: attempt to dump function reference',
- exc_exec('call msgpackdump([todump])'))
+ eq(
+ 'Vim(call):E5004: Error while dumping msgpackdump() argument, index 0, index 0: attempt to dump function reference',
+ exc_exec('call msgpackdump([todump])')
+ )
end)
it('fails to dump a recursive list', function()
command('let todump = [[[]]]')
command('call add(todump[0][0], todump)')
- eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0, index 0, index 0',
- exc_exec('call msgpackdump([todump])'))
+ eq(
+ 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0, index 0, index 0',
+ exc_exec('call msgpackdump([todump])')
+ )
end)
it('fails to dump a recursive dict', function()
command('let todump = {"d": {"d": {}}}')
command('call extend(todump.d.d, {"d": todump})')
- eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key \'d\', key \'d\', key \'d\'',
- exc_exec('call msgpackdump([todump])'))
+ eq(
+ "Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key 'd', key 'd', key 'd'",
+ exc_exec('call msgpackdump([todump])')
+ )
end)
it('can dump dict with two same dicts inside', function()
command('let inter = {}')
command('let todump = {"a": inter, "b": inter}')
- dump_eq({"\130\161a\128\161b\128"}, '[todump]')
+ dump_eq({ '\130\161a\128\161b\128' }, '[todump]')
end)
it('can dump list with two same lists inside', function()
command('let inter = []')
command('let todump = [inter, inter]')
- dump_eq({"\146\144\144"}, '[todump]')
+ dump_eq({ '\146\144\144' }, '[todump]')
end)
it('fails to dump a recursive list in a special dict', function()
command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
command('call add(todump._VAL, todump)')
- eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0',
- exc_exec('call msgpackdump([todump])'))
+ eq(
+ 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0',
+ exc_exec('call msgpackdump([todump])')
+ )
end)
it('fails to dump a recursive (key) map in a special dict', function()
command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
command('call add(todump._VAL, [todump, 0])')
- eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0',
- exc_exec('call msgpackdump([todump])'))
+ eq(
+ 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0',
+ exc_exec('call msgpackdump([todump])')
+ )
end)
it('fails to dump a recursive (val) map in a special dict', function()
command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": []}')
command('call add(todump._VAL, [0, todump])')
- eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key 0 at index 0 from special map',
- exc_exec('call msgpackdump([todump])'))
+ eq(
+ 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key 0 at index 0 from special map',
+ exc_exec('call msgpackdump([todump])')
+ )
end)
it('fails to dump a recursive (key) map in a special dict, _VAL reference', function()
command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}')
command('call add(todump._VAL[0][0], todump._VAL)')
- eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key [[[[...@0], []]]] at index 0 from special map, index 0',
- exc_exec('call msgpackdump([todump])'))
+ eq(
+ 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key [[[[...@0], []]]] at index 0 from special map, index 0',
+ exc_exec('call msgpackdump([todump])')
+ )
end)
it('fails to dump a recursive (val) map in a special dict, _VAL reference', function()
command('let todump = {"_TYPE": v:msgpack_types.map, "_VAL": [[[], []]]}')
command('call add(todump._VAL[0][1], todump._VAL)')
- eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key [] at index 0 from special map, index 0',
- exc_exec('call msgpackdump([todump])'))
+ eq(
+ 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in key [] at index 0 from special map, index 0',
+ exc_exec('call msgpackdump([todump])')
+ )
end)
- it('fails to dump a recursive (val) special list in a special dict',
- function()
+ it('fails to dump a recursive (val) special list in a special dict', function()
command('let todump = {"_TYPE": v:msgpack_types.array, "_VAL": []}')
command('call add(todump._VAL, [0, todump._VAL])')
- eq('Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0, index 1',
- exc_exec('call msgpackdump([todump])'))
+ eq(
+ 'Vim(call):E5005: Unable to dump msgpackdump() argument, index 0: container references itself in index 0, index 1',
+ exc_exec('call msgpackdump([todump])')
+ )
end)
it('fails when called with no arguments', function()
- eq('Vim(call):E119: Not enough arguments for function: msgpackdump',
- exc_exec('call msgpackdump()'))
+ eq(
+ 'Vim(call):E119: Not enough arguments for function: msgpackdump',
+ exc_exec('call msgpackdump()')
+ )
end)
it('fails when called with three arguments', function()
- eq('Vim(call):E118: Too many arguments for function: msgpackdump',
- exc_exec('call msgpackdump(["", ""], 1, 2)'))
+ eq(
+ 'Vim(call):E118: Too many arguments for function: msgpackdump',
+ exc_exec('call msgpackdump(["", ""], 1, 2)')
+ )
end)
it('fails to dump a string', function()
- eq('Vim(call):E686: Argument of msgpackdump() must be a List',
- exc_exec('call msgpackdump("abcdefghijklmnopqrstuvwxyz")'))
+ eq(
+ 'Vim(call):E686: Argument of msgpackdump() must be a List',
+ exc_exec('call msgpackdump("abcdefghijklmnopqrstuvwxyz")')
+ )
end)
it('fails to dump a number', function()
- eq('Vim(call):E686: Argument of msgpackdump() must be a List',
- exc_exec('call msgpackdump(127)'))
+ eq(
+ 'Vim(call):E686: Argument of msgpackdump() must be a List',
+ exc_exec('call msgpackdump(127)')
+ )
end)
it('fails to dump a dictionary', function()
- eq('Vim(call):E686: Argument of msgpackdump() must be a List',
- exc_exec('call msgpackdump({})'))
+ eq('Vim(call):E686: Argument of msgpackdump() must be a List', exc_exec('call msgpackdump({})'))
end)
it('fails to dump a funcref', function()
- eq('Vim(call):E686: Argument of msgpackdump() must be a List',
- exc_exec('call msgpackdump(function("tr"))'))
+ eq(
+ 'Vim(call):E686: Argument of msgpackdump() must be a List',
+ exc_exec('call msgpackdump(function("tr"))')
+ )
end)
it('fails to dump a partial', function()
command('function T() dict\nendfunction')
- eq('Vim(call):E686: Argument of msgpackdump() must be a List',
- exc_exec('call msgpackdump(function("T", [1, 2], {}))'))
+ eq(
+ 'Vim(call):E686: Argument of msgpackdump() must be a List',
+ exc_exec('call msgpackdump(function("T", [1, 2], {}))')
+ )
end)
it('fails to dump a float', function()
- eq('Vim(call):E686: Argument of msgpackdump() must be a List',
- exc_exec('call msgpackdump(0.0)'))
+ eq(
+ 'Vim(call):E686: Argument of msgpackdump() must be a List',
+ exc_exec('call msgpackdump(0.0)')
+ )
end)
it('fails to dump special value', function()
- for _, val in ipairs({'v:true', 'v:false', 'v:null'}) do
- eq('Vim(call):E686: Argument of msgpackdump() must be a List',
- exc_exec('call msgpackdump(' .. val .. ')'))
+ for _, val in ipairs({ 'v:true', 'v:false', 'v:null' }) do
+ eq(
+ 'Vim(call):E686: Argument of msgpackdump() must be a List',
+ exc_exec('call msgpackdump(' .. val .. ')')
+ )
end
end)
it('can dump NULL string', function()
- dump_eq({'\196\n'}, '[$XXX_UNEXISTENT_VAR_XXX]')
- dump_eq({'\196\n'}, '[{"_TYPE": v:msgpack_types.binary, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]')
- dump_eq({'\160'}, '[{"_TYPE": v:msgpack_types.string, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]')
+ dump_eq({ '\196\n' }, '[$XXX_UNEXISTENT_VAR_XXX]')
+ dump_eq({ '\196\n' }, '[{"_TYPE": v:msgpack_types.binary, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]')
+ dump_eq({ '\160' }, '[{"_TYPE": v:msgpack_types.string, "_VAL": [$XXX_UNEXISTENT_VAR_XXX]}]')
end)
it('can dump NULL blob', function()
- eq({'\196\n'}, eval('msgpackdump([v:_null_blob])'))
+ eq({ '\196\n' }, eval('msgpackdump([v:_null_blob])'))
end)
it('can dump NULL list', function()
- eq({'\144'}, eval('msgpackdump([v:_null_list])'))
+ eq({ '\144' }, eval('msgpackdump([v:_null_list])'))
end)
it('can dump NULL dictionary', function()
- eq({'\128'}, eval('msgpackdump([v:_null_dict])'))
+ eq({ '\128' }, eval('msgpackdump([v:_null_dict])'))
end)
end)
diff --git a/test/functional/vimscript/null_spec.lua b/test/functional/vimscript/null_spec.lua
index d4c36d835b..805cd13844 100644
--- a/test/functional/vimscript/null_spec.lua
+++ b/test/functional/vimscript/null_spec.lua
@@ -1,23 +1,22 @@
local helpers = require('test.functional.helpers')(after_each)
-local curbufmeths = helpers.curbufmeths
local exc_exec = helpers.exc_exec
local command = helpers.command
local clear = helpers.clear
-local meths = helpers.meths
-local funcs = helpers.funcs
+local api = helpers.api
+local fn = helpers.fn
local eq = helpers.eq
local function redir_exec(cmd)
- meths.set_var('__redir_exec_cmd', cmd)
+ api.nvim_set_var('__redir_exec_cmd', cmd)
command([[
redir => g:__redir_exec_output
silent! execute g:__redir_exec_cmd
redir END
]])
- local ret = meths.get_var('__redir_exec_output')
- meths.del_var('__redir_exec_output')
- meths.del_var('__redir_exec_cmd')
+ local ret = api.nvim_get_var('__redir_exec_output')
+ api.nvim_del_var('__redir_exec_output')
+ api.nvim_del_var('__redir_exec_cmd')
return ret
end
@@ -40,12 +39,11 @@ describe('NULL', function()
end
local null_expr_test = function(name, expr, err, val, after)
it(name, function()
- eq((err == 0) and ('') or ('\n' .. err),
- redir_exec('let g:_var = ' .. expr))
+ eq((err == 0) and '' or ('\n' .. err), redir_exec('let g:_var = ' .. expr))
if val == nil then
- eq(0, funcs.exists('g:_var'))
+ eq(0, fn.exists('g:_var'))
else
- eq(val, meths.get_var('_var'))
+ eq(val, api.nvim_get_var('_var'))
end
if after ~= nil then
after()
@@ -58,25 +56,31 @@ describe('NULL', function()
null_expr_test('is equal to empty list (reverse order)', '[] == L', 0, 1)
-- Correct behaviour
- null_test('can be :unlet item with error message for empty list', ':unlet L[0]',
- 'Vim(unlet):E684: List index out of range: 0')
- null_expr_test('can be indexed with error message for empty list', 'L[0]',
- 'E684: List index out of range: 0', nil)
+ null_test(
+ 'can be :unlet item with error message for empty list',
+ ':unlet L[0]',
+ 'Vim(unlet):E684: List index out of range: 0'
+ )
+ null_expr_test(
+ 'can be indexed with error message for empty list',
+ 'L[0]',
+ 'E684: List index out of range: 0',
+ nil
+ )
null_expr_test('can be splice-indexed', 'L[:]', 0, {})
null_expr_test('is not locked', 'islocked("v:_null_list")', 0, 0)
null_test('is accepted by :for', 'for x in L|throw x|endfor', 0)
null_expr_test('does not crash append()', 'append(0, L)', 0, 0, function()
- eq({''}, curbufmeths.get_lines(0, -1, false))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
null_expr_test('does not crash setline()', 'setline(1, L)', 0, 0, function()
- eq({''}, curbufmeths.get_lines(0, -1, false))
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, false))
end)
null_expr_test('is identical to itself', 'L is L', 0, 1)
null_expr_test('can be sliced', 'L[:]', 0, {})
null_expr_test('can be copied', 'copy(L)', 0, {})
null_expr_test('can be deepcopied', 'deepcopy(L)', 0, {})
- null_expr_test('does not crash when indexed', 'L[1]',
- 'E684: List index out of range: 1', nil)
+ null_expr_test('does not crash when indexed', 'L[1]', 'E684: List index out of range: 1', nil)
null_expr_test('does not crash call()', 'call("arglistid", L)', 0, 0)
null_expr_test('does not crash col()', 'col(L)', 0, 0)
null_expr_test('does not crash virtcol()', 'virtcol(L)', 0, 0)
@@ -96,44 +100,92 @@ describe('NULL', function()
null_test('does not crash lockvar', 'lockvar! L', 0)
null_expr_test('can be added to itself', '(L + L)', 0, {})
null_expr_test('can be added to itself', '(L + L) is L', 0, 1)
- null_expr_test('can be added to non-empty list', '([1] + L)', 0, {1})
- null_expr_test('can be added to non-empty list (reversed)', '(L + [1])', 0, {1})
+ null_expr_test('can be added to non-empty list', '([1] + L)', 0, { 1 })
+ null_expr_test('can be added to non-empty list (reversed)', '(L + [1])', 0, { 1 })
null_expr_test('is equal to itself', 'L == L', 0, 1)
null_expr_test('is not not equal to itself', 'L != L', 0, 0)
null_expr_test('counts correctly', 'count([L], L)', 0, 1)
null_expr_test('makes map() return v:_null_list', 'map(L, "v:val") is# L', 0, 1)
null_expr_test('makes filter() return v:_null_list', 'filter(L, "1") is# L', 0, 1)
- null_test('is treated by :let as empty list', ':let [l] = L', 'Vim(let):E688: More targets than List items')
- null_expr_test('is accepted as an empty list by inputlist()', '[feedkeys("\\n"), inputlist(L)]',
- 'Type number and <Enter> or click with the mouse (q or empty cancels): ', {0, 0})
- null_expr_test('is accepted as an empty list by writefile()',
- ('[writefile(L, "%s"), readfile("%s")]'):format(tmpfname, tmpfname),
- 0, {0, {}})
- null_expr_test('makes add() error out', 'add(L, 0)',
- 'E742: Cannot change value of add() argument', 1)
- null_expr_test('makes insert() error out', 'insert(L, 1)',
- 'E742: Cannot change value of insert() argument', 0)
- null_expr_test('does not crash remove()', 'remove(L, 0)',
- 'E742: Cannot change value of remove() argument', 0)
- null_expr_test('makes reverse() error out', 'reverse(L)',
- 'E742: Cannot change value of reverse() argument', 0)
- null_expr_test('makes sort() error out', 'sort(L)',
- 'E742: Cannot change value of sort() argument', 0)
- null_expr_test('makes uniq() error out', 'uniq(L)',
- 'E742: Cannot change value of uniq() argument', 0)
- null_expr_test('does not crash extend()', 'extend(L, [1])', 'E742: Cannot change value of extend() argument', 0)
- null_expr_test('does not crash extend() (second position)', 'extend([1], L)', 0, {1})
+ null_test(
+ 'is treated by :let as empty list',
+ ':let [l] = L',
+ 'Vim(let):E688: More targets than List items'
+ )
+ null_expr_test(
+ 'is accepted as an empty list by inputlist()',
+ '[feedkeys("\\n"), inputlist(L)]',
+ 'Type number and <Enter> or click with the mouse (q or empty cancels): ',
+ { 0, 0 }
+ )
+ null_expr_test(
+ 'is accepted as an empty list by writefile()',
+ ('[writefile(L, "%s"), readfile("%s")]'):format(tmpfname, tmpfname),
+ 0,
+ { 0, {} }
+ )
+ null_expr_test(
+ 'makes add() error out',
+ 'add(L, 0)',
+ 'E742: Cannot change value of add() argument',
+ 1
+ )
+ null_expr_test(
+ 'makes insert() error out',
+ 'insert(L, 1)',
+ 'E742: Cannot change value of insert() argument',
+ 0
+ )
+ null_expr_test(
+ 'does not crash remove()',
+ 'remove(L, 0)',
+ 'E742: Cannot change value of remove() argument',
+ 0
+ )
+ null_expr_test(
+ 'makes reverse() error out',
+ 'reverse(L)',
+ 'E742: Cannot change value of reverse() argument',
+ 0
+ )
+ null_expr_test(
+ 'makes sort() error out',
+ 'sort(L)',
+ 'E742: Cannot change value of sort() argument',
+ 0
+ )
+ null_expr_test(
+ 'makes uniq() error out',
+ 'uniq(L)',
+ 'E742: Cannot change value of uniq() argument',
+ 0
+ )
+ null_expr_test(
+ 'does not crash extend()',
+ 'extend(L, [1])',
+ 'E742: Cannot change value of extend() argument',
+ 0
+ )
+ null_expr_test('does not crash extend() (second position)', 'extend([1], L)', 0, { 1 })
null_expr_test('makes join() return empty string', 'join(L, "")', 0, '')
null_expr_test('makes msgpackdump() return empty list', 'msgpackdump(L)', 0, {})
null_expr_test('does not crash system()', 'system("cat", L)', 0, '')
null_expr_test('does not crash setreg', 'setreg("x", L)', 0, 0)
null_expr_test('does not crash systemlist()', 'systemlist("cat", L)', 0, {})
- null_test('does not make Neovim crash when v:oldfiles gets assigned to that', ':let v:oldfiles = L|oldfiles', 0)
- null_expr_test('does not make complete() crash or error out',
- 'execute(":normal i\\<C-r>=complete(1, L)[-1]\\n")',
- 0, '', function()
- eq({''}, curbufmeths.get_lines(0, -1, false))
- end)
+ null_test(
+ 'does not make Neovim crash when v:oldfiles gets assigned to that',
+ ':let v:oldfiles = L|oldfiles',
+ 0
+ )
+ null_expr_test(
+ 'does not make complete() crash or error out',
+ 'execute(":normal i\\<C-r>=complete(1, L)[-1]\\n")',
+ 0,
+ '',
+ function()
+ eq({ '' }, api.nvim_buf_get_lines(0, 0, -1, false))
+ end
+ )
null_expr_test('is accepted by setmatches()', 'setmatches(L)', 0, 0)
null_expr_test('is accepted by setqflist()', 'setqflist(L)', 0, 0)
null_expr_test('is accepted by setloclist()', 'setloclist(1, L)', 0, 0)
@@ -143,11 +195,15 @@ describe('NULL', function()
end)
describe('dict', function()
it('does not crash when indexing NULL dict', function()
- eq('\nE716: Key not present in Dictionary: "test"',
- redir_exec('echo v:_null_dict.test'))
+ eq('\nE716: Key not present in Dictionary: "test"', redir_exec('echo v:_null_dict.test'))
end)
- null_expr_test('makes extend error out', 'extend(D, {})', 'E742: Cannot change value of extend() argument', 0)
- null_expr_test('makes extend do nothing', 'extend({1: 2}, D)', 0, {['1']=2})
+ null_expr_test(
+ 'makes extend error out',
+ 'extend(D, {})',
+ 'E742: Cannot change value of extend() argument',
+ 0
+ )
+ null_expr_test('makes extend do nothing', 'extend({1: 2}, D)', 0, { ['1'] = 2 })
null_expr_test('does not crash map()', 'map(D, "v:val")', 0, {})
null_expr_test('does not crash filter()', 'filter(D, "1")', 0, {})
null_expr_test('makes map() return v:_null_dict', 'map(D, "v:val") is# D', 0, 1)
@@ -158,7 +214,12 @@ describe('NULL', function()
null_test('does not crash :execute', 'execute S', 0)
null_expr_test('does not crash execute()', 'execute(S)', 0, '')
null_expr_test('does not crash executable()', 'executable(S)', 0, 0)
- null_expr_test('makes timer_start() error out', 'timer_start(0, S)', 'E921: Invalid callback argument', -1)
+ null_expr_test(
+ 'makes timer_start() error out',
+ 'timer_start(0, S)',
+ 'E921: Invalid callback argument',
+ -1
+ )
null_expr_test('does not crash filereadable()', 'filereadable(S)', 0, 0)
null_expr_test('does not crash filewritable()', 'filewritable(S)', 0, 0)
null_expr_test('does not crash fnamemodify()', 'fnamemodify(S, S)', 0, '')
@@ -169,7 +230,7 @@ describe('NULL', function()
null_expr_test('does not crash glob()', 'glob(S)', 0, '')
null_expr_test('does not crash globpath()', 'globpath(S, S)', 0, '')
null_expr_test('does not crash mkdir()', 'mkdir(S)', 0, 0)
- null_expr_test('does not crash sort()', 'sort(["b", S, "a"])', 0, {'', 'a', 'b'})
+ null_expr_test('does not crash sort()', 'sort(["b", S, "a"])', 0, { '', 'a', 'b' })
null_expr_test('does not crash split()', 'split(S)', 0, {})
null_test('can be used to set an option', 'let &grepprg = S', 0)
diff --git a/test/functional/vimscript/operators_spec.lua b/test/functional/vimscript/operators_spec.lua
index 4d07bc1b05..64f6b60238 100644
--- a/test/functional/vimscript/operators_spec.lua
+++ b/test/functional/vimscript/operators_spec.lua
@@ -7,22 +7,22 @@ describe('Division operator', function()
before_each(clear)
it('returns infinity on {positive}/0.0', function()
- eq('str2float(\'inf\')', eval('string(1.0/0.0)'))
- eq('str2float(\'inf\')', eval('string(1.0e-100/0.0)'))
- eq('str2float(\'inf\')', eval('string(1.0e+100/0.0)'))
- eq('str2float(\'inf\')', eval('string((1.0/0.0)/0.0)'))
+ eq("str2float('inf')", eval('string(1.0/0.0)'))
+ eq("str2float('inf')", eval('string(1.0e-100/0.0)'))
+ eq("str2float('inf')", eval('string(1.0e+100/0.0)'))
+ eq("str2float('inf')", eval('string((1.0/0.0)/0.0)'))
end)
it('returns -infinity on {negative}/0.0', function()
- eq('-str2float(\'inf\')', eval('string((-1.0)/0.0)'))
- eq('-str2float(\'inf\')', eval('string((-1.0e-100)/0.0)'))
- eq('-str2float(\'inf\')', eval('string((-1.0e+100)/0.0)'))
- eq('-str2float(\'inf\')', eval('string((-1.0/0.0)/0.0)'))
+ eq("-str2float('inf')", eval('string((-1.0)/0.0)'))
+ eq("-str2float('inf')", eval('string((-1.0e-100)/0.0)'))
+ eq("-str2float('inf')", eval('string((-1.0e+100)/0.0)'))
+ eq("-str2float('inf')", eval('string((-1.0/0.0)/0.0)'))
end)
it('returns NaN on 0.0/0.0', function()
- eq('str2float(\'nan\')', eval('string(0.0/0.0)'))
- eq('str2float(\'nan\')', eval('string(-(0.0/0.0))'))
- eq('str2float(\'nan\')', eval('string((-0.0)/0.0)'))
+ eq("str2float('nan')", eval('string(0.0/0.0)'))
+ eq("str2float('nan')", eval('string(-(0.0/0.0))'))
+ eq("str2float('nan')", eval('string((-0.0)/0.0)'))
end)
end)
diff --git a/test/functional/vimscript/printf_spec.lua b/test/functional/vimscript/printf_spec.lua
index 27e24c4118..4fa4ea7f4c 100644
--- a/test/functional/vimscript/printf_spec.lua
+++ b/test/functional/vimscript/printf_spec.lua
@@ -3,56 +3,56 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
local eval = helpers.eval
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local exc_exec = helpers.exc_exec
describe('printf()', function()
before_each(clear)
it('works with zero and %b', function()
- eq('0', funcs.printf('%lb', 0))
- eq('0', funcs.printf('%llb', 0))
- eq('0', funcs.printf('%zb', 0))
+ eq('0', fn.printf('%lb', 0))
+ eq('0', fn.printf('%llb', 0))
+ eq('0', fn.printf('%zb', 0))
end)
it('works with one and %b', function()
- eq('1', funcs.printf('%b', 1))
- eq('1', funcs.printf('%lb', 1))
- eq('1', funcs.printf('%llb', 1))
- eq('1', funcs.printf('%zb', 1))
+ eq('1', fn.printf('%b', 1))
+ eq('1', fn.printf('%lb', 1))
+ eq('1', fn.printf('%llb', 1))
+ eq('1', fn.printf('%zb', 1))
end)
it('works with 0xff and %b', function()
- eq('11111111', funcs.printf('%b', 0xff))
- eq('11111111', funcs.printf('%lb', 0xff))
- eq('11111111', funcs.printf('%llb', 0xff))
- eq('11111111', funcs.printf('%zb', 0xff))
+ eq('11111111', fn.printf('%b', 0xff))
+ eq('11111111', fn.printf('%lb', 0xff))
+ eq('11111111', fn.printf('%llb', 0xff))
+ eq('11111111', fn.printf('%zb', 0xff))
end)
it('accepts width modifier with %b', function()
- eq(' 1', funcs.printf('%3b', 1))
+ eq(' 1', fn.printf('%3b', 1))
end)
it('accepts prefix modifier with %b', function()
- eq('0b1', funcs.printf('%#b', 1))
+ eq('0b1', fn.printf('%#b', 1))
end)
it('writes capital B with %B', function()
- eq('0B1', funcs.printf('%#B', 1))
+ eq('0B1', fn.printf('%#B', 1))
end)
it('accepts prefix, zero-fill and width modifiers with %b', function()
- eq('0b001', funcs.printf('%#05b', 1))
+ eq('0b001', fn.printf('%#05b', 1))
end)
it('accepts prefix and width modifiers with %b', function()
- eq(' 0b1', funcs.printf('%#5b', 1))
+ eq(' 0b1', fn.printf('%#5b', 1))
end)
it('does not write prefix for zero with prefix and width modifier used with %b', function()
- eq(' 0', funcs.printf('%#5b', 0))
+ eq(' 0', fn.printf('%#5b', 0))
end)
it('accepts precision modifier with %b', function()
- eq('00000', funcs.printf('%.5b', 0))
+ eq('00000', fn.printf('%.5b', 0))
end)
it('accepts all modifiers with %b at once', function()
-- zero-fill modifier is ignored when used with left-align
-- force-sign and add-blank are ignored
-- use-grouping-characters modifier is ignored always
- eq('0b00011 ', funcs.printf('% \'+#0-10.5b', 3))
+ eq('0b00011 ', fn.printf("% '+#0-10.5b", 3))
end)
it('errors out when %b modifier is used for a list', function()
eq('Vim(call):E745: Using a List as a Number', exc_exec('call printf("%b", [])'))
@@ -65,12 +65,12 @@ describe('printf()', function()
local seen_rets = {}
-- Collect all args in an array to avoid possible allocation of the same
-- address after freeing unreferenced values.
- meths.set_var('__args', {})
+ api.nvim_set_var('__args', {})
local function check_printf(expr, is_null)
eq(0, exc_exec('call add(__args, ' .. expr .. ')'))
eq(0, exc_exec('let __result = printf("%p", __args[-1])'))
local id_ret = eval('id(__args[-1])')
- eq(id_ret, meths.get_var('__result'))
+ eq(id_ret, api.nvim_get_var('__result'))
if is_null then
if null_ret then
eq(null_ret, id_ret)
@@ -81,7 +81,7 @@ describe('printf()', function()
eq(nil, seen_rets[id_ret])
seen_rets[id_ret] = expr
end
- meths.del_var('__result')
+ api.nvim_del_var('__result')
end
check_printf('v:_null_list', true)
check_printf('v:_null_dict', true)
diff --git a/test/functional/vimscript/reltime_spec.lua b/test/functional/vimscript/reltime_spec.lua
index 6d661402a6..7cdb78e4ce 100644
--- a/test/functional/vimscript/reltime_spec.lua
+++ b/test/functional/vimscript/reltime_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
-local clear, eq, ok = helpers.clear, helpers.eq, helpers.ok
-local neq, command, funcs = helpers.neq, helpers.command, helpers.funcs
-local reltime, reltimestr, reltimefloat = funcs.reltime, funcs.reltimestr, funcs.reltimefloat
+local clear, eq, ok = helpers.clear, helpers.eq, helpers.ok
+local neq, command, fn = helpers.neq, helpers.command, helpers.fn
+local reltime, reltimestr, reltimefloat = fn.reltime, fn.reltimestr, fn.reltimefloat
describe('reltimestr(), reltimefloat()', function()
before_each(clear)
@@ -15,7 +15,7 @@ describe('reltimestr(), reltimefloat()', function()
neq('0.0', reltimestr(elapsed))
ok(reltimefloat(elapsed) > 0.0)
-- original vim test for < 0.1, but easily fails on travis
- ok(nil ~= string.match(reltimestr(elapsed), "0%."))
+ ok(nil ~= string.match(reltimestr(elapsed), '0%.'))
ok(reltimefloat(elapsed) < 1.0)
local same = reltime(now, now)
@@ -29,7 +29,7 @@ describe('reltimestr(), reltimefloat()', function()
neq('0.0', reltimestr(differs))
ok(reltimefloat(differs) > 0.0)
-- original vim test for < 0.1, but easily fails on travis
- ok(nil ~= string.match(reltimestr(differs), "0%."))
+ ok(nil ~= string.match(reltimestr(differs), '0%.'))
ok(reltimefloat(differs) < 1.0)
end)
diff --git a/test/functional/vimscript/screenchar_spec.lua b/test/functional/vimscript/screenchar_spec.lua
index 767e3c57ef..48b6893865 100644
--- a/test/functional/vimscript/screenchar_spec.lua
+++ b/test/functional/vimscript/screenchar_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, eq, neq = helpers.clear, helpers.eq, helpers.neq
-local command, meths, funcs = helpers.command, helpers.meths, helpers.funcs
-local tbl_deep_extend = helpers.tbl_deep_extend
+local command, api, fn = helpers.command, helpers.api, helpers.fn
+local tbl_deep_extend = vim.tbl_deep_extend
-- Set up two overlapping floating windows
local setup_floating_windows = function()
@@ -14,15 +14,15 @@ local setup_floating_windows = function()
border = 'none',
}
- local bufnr_1 = meths.create_buf(false, true)
- meths.buf_set_lines(bufnr_1, 0, -1, true, { 'aa' })
+ local bufnr_1 = api.nvim_create_buf(false, true)
+ api.nvim_buf_set_lines(bufnr_1, 0, -1, true, { 'aa' })
local opts_1 = tbl_deep_extend('force', { row = 0, col = 0, zindex = 11 }, base_opts)
- meths.open_win(bufnr_1, false, opts_1)
+ api.nvim_open_win(bufnr_1, false, opts_1)
- local bufnr_2 = meths.create_buf(false, true)
- meths.buf_set_lines(bufnr_2, 0, -1, true, { 'bb' })
+ local bufnr_2 = api.nvim_create_buf(false, true)
+ api.nvim_buf_set_lines(bufnr_2, 0, -1, true, { 'bb' })
local opts_2 = tbl_deep_extend('force', { row = 0, col = 1, zindex = 10 }, base_opts)
- meths.open_win(bufnr_2, false, opts_2)
+ api.nvim_open_win(bufnr_2, false, opts_2)
command('redraw')
end
@@ -32,38 +32,38 @@ describe('screenchar() and family respect floating windows', function()
clear()
-- These commands result into visible text `aabc`.
-- `aab` - from floating windows, `c` - from text in regular window.
- meths.buf_set_lines(0, 0, -1, true, { 'cccc' })
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'cccc' })
setup_floating_windows()
end)
it('screenattr()', function()
- local attr_1 = funcs.screenattr(1, 1)
- local attr_2 = funcs.screenattr(1, 2)
- local attr_3 = funcs.screenattr(1, 3)
- local attr_4 = funcs.screenattr(1, 4)
+ local attr_1 = fn.screenattr(1, 1)
+ local attr_2 = fn.screenattr(1, 2)
+ local attr_3 = fn.screenattr(1, 3)
+ local attr_4 = fn.screenattr(1, 4)
eq(attr_1, attr_2)
eq(attr_1, attr_3)
neq(attr_1, attr_4)
end)
it('screenchar()', function()
- eq(97, funcs.screenchar(1, 1))
- eq(97, funcs.screenchar(1, 2))
- eq(98, funcs.screenchar(1, 3))
- eq(99, funcs.screenchar(1, 4))
+ eq(97, fn.screenchar(1, 1))
+ eq(97, fn.screenchar(1, 2))
+ eq(98, fn.screenchar(1, 3))
+ eq(99, fn.screenchar(1, 4))
end)
it('screenchars()', function()
- eq({ 97 }, funcs.screenchars(1, 1))
- eq({ 97 }, funcs.screenchars(1, 2))
- eq({ 98 }, funcs.screenchars(1, 3))
- eq({ 99 }, funcs.screenchars(1, 4))
+ eq({ 97 }, fn.screenchars(1, 1))
+ eq({ 97 }, fn.screenchars(1, 2))
+ eq({ 98 }, fn.screenchars(1, 3))
+ eq({ 99 }, fn.screenchars(1, 4))
end)
it('screenstring()', function()
- eq('a', funcs.screenstring(1, 1))
- eq('a', funcs.screenstring(1, 2))
- eq('b', funcs.screenstring(1, 3))
- eq('c', funcs.screenstring(1, 4))
+ eq('a', fn.screenstring(1, 1))
+ eq('a', fn.screenstring(1, 2))
+ eq('b', fn.screenstring(1, 3))
+ eq('c', fn.screenstring(1, 4))
end)
end)
diff --git a/test/functional/vimscript/screenpos_spec.lua b/test/functional/vimscript/screenpos_spec.lua
index 8b8276457d..b951d830a6 100644
--- a/test/functional/vimscript/screenpos_spec.lua
+++ b/test/functional/vimscript/screenpos_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
-local clear, eq, meths = helpers.clear, helpers.eq, helpers.meths
-local command, funcs = helpers.command, helpers.funcs
+local clear, eq, api = helpers.clear, helpers.eq, helpers.api
+local command, fn = helpers.command, helpers.fn
local feed = helpers.feed
before_each(clear)
@@ -8,66 +8,72 @@ before_each(clear)
describe('screenpos() function', function()
it('works in floating window with border', function()
local opts = {
- relative='editor',
- height=8,
- width=12,
- row=6,
- col=8,
- anchor='NW',
- style='minimal',
- border='none',
- focusable=1
+ relative = 'editor',
+ height = 8,
+ width = 12,
+ row = 6,
+ col = 8,
+ anchor = 'NW',
+ style = 'minimal',
+ border = 'none',
+ focusable = 1,
}
- local float = meths.open_win(meths.create_buf(false, true), false, opts)
+ local float = api.nvim_open_win(api.nvim_create_buf(false, true), false, opts)
command('redraw')
- eq({row = 7, col = 9, endcol = 9, curscol = 9}, funcs.screenpos(float, 1, 1))
+ eq({ row = 7, col = 9, endcol = 9, curscol = 9 }, fn.screenpos(float, 1, 1))
-- only left border
- opts.border = {'', '', '', '', '', '', '', '|'}
- meths.win_set_config(float, opts)
+ opts.border = { '', '', '', '', '', '', '', '|' }
+ api.nvim_win_set_config(float, opts)
command('redraw')
- eq({row = 7, col = 10, endcol = 10, curscol = 10}, funcs.screenpos(float, 1, 1))
+ eq({ row = 7, col = 10, endcol = 10, curscol = 10 }, fn.screenpos(float, 1, 1))
-- only top border
- opts.border = {'', '_', '', '', '', '', '', ''}
- meths.win_set_config(float, opts)
+ opts.border = { '', '_', '', '', '', '', '', '' }
+ api.nvim_win_set_config(float, opts)
command('redraw')
- eq({row = 8, col = 9, endcol = 9, curscol = 9}, funcs.screenpos(float, 1, 1))
+ eq({ row = 8, col = 9, endcol = 9, curscol = 9 }, fn.screenpos(float, 1, 1))
-- both left and top border
opts.border = 'single'
- meths.win_set_config(float, opts)
+ api.nvim_win_set_config(float, opts)
command('redraw')
- eq({row = 8, col = 10, endcol = 10, curscol = 10}, funcs.screenpos(float, 1, 1))
+ eq({ row = 8, col = 10, endcol = 10, curscol = 10 }, fn.screenpos(float, 1, 1))
end)
it('works for folded line with virt_lines attached to line above', function()
- meths.buf_set_lines(0, 0, -1, true, {'aaa', 'bbb', 'ccc', 'ddd'})
- local ns = meths.create_namespace('')
- meths.buf_set_extmark(0, ns, 0, 0, { virt_lines = {{{'abb'}}, {{'acc'}}, {{'add'}}} })
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'aaa', 'bbb', 'ccc', 'ddd' })
+ local ns = api.nvim_create_namespace('')
+ api.nvim_buf_set_extmark(
+ 0,
+ ns,
+ 0,
+ 0,
+ { virt_lines = { { { 'abb' } }, { { 'acc' } }, { { 'add' } } } }
+ )
command('2,3fold')
- eq({row = 5, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 2, 1))
- eq({row = 5, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 3, 1))
- eq({row = 6, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 4, 1))
+ eq({ row = 5, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 2, 1))
+ eq({ row = 5, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 3, 1))
+ eq({ row = 6, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 4, 1))
feed('<C-E>')
- eq({row = 4, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 2, 1))
- eq({row = 4, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 3, 1))
- eq({row = 5, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 4, 1))
+ eq({ row = 4, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 2, 1))
+ eq({ row = 4, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 3, 1))
+ eq({ row = 5, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 4, 1))
feed('<C-E>')
- eq({row = 3, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 2, 1))
- eq({row = 3, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 3, 1))
- eq({row = 4, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 4, 1))
+ eq({ row = 3, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 2, 1))
+ eq({ row = 3, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 3, 1))
+ eq({ row = 4, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 4, 1))
feed('<C-E>')
- eq({row = 2, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 2, 1))
- eq({row = 2, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 3, 1))
- eq({row = 3, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 4, 1))
+ eq({ row = 2, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 2, 1))
+ eq({ row = 2, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 3, 1))
+ eq({ row = 3, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 4, 1))
feed('<C-E>')
- eq({row = 1, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 2, 1))
- eq({row = 1, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 3, 1))
- eq({row = 2, col = 1, endcol = 1, curscol = 1}, funcs.screenpos(0, 4, 1))
+ eq({ row = 1, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 2, 1))
+ eq({ row = 1, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 3, 1))
+ eq({ row = 2, col = 1, endcol = 1, curscol = 1 }, fn.screenpos(0, 4, 1))
end)
end)
diff --git a/test/functional/vimscript/server_spec.lua b/test/functional/vimscript/server_spec.lua
index c89a0c4e93..360fcf0dfe 100644
--- a/test/functional/vimscript/server_spec.lua
+++ b/test/functional/vimscript/server_spec.lua
@@ -1,7 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local assert_log = helpers.assert_log
local eq, neq, eval = helpers.eq, helpers.neq, helpers.eval
-local clear, funcs, meths = helpers.clear, helpers.funcs, helpers.meths
+local clear, fn, api = helpers.clear, helpers.fn, helpers.api
local ok = helpers.ok
local matches = helpers.matches
local pcall_err = helpers.pcall_err
@@ -11,8 +11,8 @@ local is_os = helpers.is_os
local testlog = 'Xtest-server-log'
local function clear_serverlist()
- for _, server in pairs(funcs.serverlist()) do
- funcs.serverstop(server)
+ for _, server in pairs(fn.serverlist()) do
+ fn.serverstop(server)
end
end
@@ -24,120 +24,119 @@ describe('server', function()
it('serverstart() stores sockets in $XDG_RUNTIME_DIR', function()
local dir = 'Xtest_xdg_run'
mkdir(dir)
- clear({ env={ XDG_RUNTIME_DIR=dir } })
- matches(dir, funcs.stdpath('run'))
+ clear({ env = { XDG_RUNTIME_DIR = dir } })
+ matches(dir, fn.stdpath('run'))
if not is_os('win') then
- matches(dir, funcs.serverstart())
+ matches(dir, fn.serverstart())
end
end)
-
it('serverstart(), serverstop() does not set $NVIM', function()
clear()
local s = eval('serverstart()')
- assert(s ~= nil and s:len() > 0, "serverstart() returned empty")
+ assert(s ~= nil and s:len() > 0, 'serverstart() returned empty')
eq('', eval('$NVIM'))
eq('', eval('$NVIM_LISTEN_ADDRESS'))
- eq(1, eval("serverstop('"..s.."')"))
+ eq(1, eval("serverstop('" .. s .. "')"))
eq('', eval('$NVIM_LISTEN_ADDRESS'))
end)
it('sets new v:servername if $NVIM_LISTEN_ADDRESS is invalid', function()
- clear({env={NVIM_LISTEN_ADDRESS='.'}})
+ clear({ env = { NVIM_LISTEN_ADDRESS = '.' } })
-- Cleared on startup.
eq('', eval('$NVIM_LISTEN_ADDRESS'))
- local servers = funcs.serverlist()
+ local servers = fn.serverlist()
eq(1, #servers)
- ok(string.len(servers[1]) > 4) -- "~/.local/state/nvim…/…" or "\\.\pipe\…"
+ ok(string.len(servers[1]) > 4) -- "~/.local/state/nvim…/…" or "\\.\pipe\…"
end)
it('sets v:servername at startup or if all servers were stopped', function()
clear()
- local initial_server = meths.get_vvar('servername')
- assert(initial_server ~= nil and initial_server:len() > 0,
- 'v:servername was not initialized')
+ local initial_server = api.nvim_get_vvar('servername')
+ assert(initial_server ~= nil and initial_server:len() > 0, 'v:servername was not initialized')
-- v:servername is readonly so we cannot unset it--but we can test that it
-- does not get set again thereafter.
- local s = funcs.serverstart()
- assert(s ~= nil and s:len() > 0, "serverstart() returned empty")
+ local s = fn.serverstart()
+ assert(s ~= nil and s:len() > 0, 'serverstart() returned empty')
neq(initial_server, s)
-- serverstop() does _not_ modify v:servername...
- eq(1, funcs.serverstop(s))
- eq(initial_server, meths.get_vvar('servername'))
+ eq(1, fn.serverstop(s))
+ eq(initial_server, api.nvim_get_vvar('servername'))
-- ...unless we stop _all_ servers.
- eq(1, funcs.serverstop(funcs.serverlist()[1]))
- eq('', meths.get_vvar('servername'))
+ eq(1, fn.serverstop(fn.serverlist()[1]))
+ eq('', api.nvim_get_vvar('servername'))
-- v:servername and $NVIM take the next available server.
- local servername = (is_os('win') and [[\\.\pipe\Xtest-functional-server-pipe]]
- or './Xtest-functional-server-socket')
- funcs.serverstart(servername)
- eq(servername, meths.get_vvar('servername'))
+ local servername = (
+ is_os('win') and [[\\.\pipe\Xtest-functional-server-pipe]]
+ or './Xtest-functional-server-socket'
+ )
+ fn.serverstart(servername)
+ eq(servername, api.nvim_get_vvar('servername'))
-- Not set in the current process, only in children.
eq('', eval('$NVIM'))
end)
it('serverstop() returns false for invalid input', function()
- clear{env={
- NVIM_LOG_FILE=testlog,
- NVIM_LISTEN_ADDRESS='.',
- }}
+ clear { env = {
+ NVIM_LOG_FILE = testlog,
+ NVIM_LISTEN_ADDRESS = '.',
+ } }
eq(0, eval("serverstop('')"))
eq(0, eval("serverstop('bogus-socket-name')"))
assert_log('Not listening on bogus%-socket%-name', testlog, 10)
end)
it('parses endpoints', function()
- clear{env={
- NVIM_LOG_FILE=testlog,
- NVIM_LISTEN_ADDRESS='.',
- }}
+ clear { env = {
+ NVIM_LOG_FILE = testlog,
+ NVIM_LISTEN_ADDRESS = '.',
+ } }
clear_serverlist()
- eq({}, funcs.serverlist())
+ eq({}, fn.serverlist())
- local s = funcs.serverstart('127.0.0.1:0') -- assign random port
+ local s = fn.serverstart('127.0.0.1:0') -- assign random port
if #s > 0 then
assert(string.match(s, '127.0.0.1:%d+'))
- eq(s, funcs.serverlist()[1])
+ eq(s, fn.serverlist()[1])
clear_serverlist()
end
- s = funcs.serverstart('127.0.0.1:') -- assign random port
+ s = fn.serverstart('127.0.0.1:') -- assign random port
if #s > 0 then
assert(string.match(s, '127.0.0.1:%d+'))
- eq(s, funcs.serverlist()[1])
+ eq(s, fn.serverlist()[1])
clear_serverlist()
end
local expected = {}
local v4 = '127.0.0.1:12345'
- local status, _ = pcall(funcs.serverstart, v4)
+ local status, _ = pcall(fn.serverstart, v4)
if status then
table.insert(expected, v4)
- pcall(funcs.serverstart, v4) -- exists already; ignore
+ pcall(fn.serverstart, v4) -- exists already; ignore
assert_log('Failed to start server: address already in use: 127%.0%.0%.1', testlog, 10)
end
local v6 = '::1:12345'
- status, _ = pcall(funcs.serverstart, v6)
+ status, _ = pcall(fn.serverstart, v6)
if status then
table.insert(expected, v6)
- pcall(funcs.serverstart, v6) -- exists already; ignore
+ pcall(fn.serverstart, v6) -- exists already; ignore
assert_log('Failed to start server: address already in use: ::1', testlog, 10)
end
- eq(expected, funcs.serverlist())
+ eq(expected, fn.serverlist())
clear_serverlist()
-- Address without slashes is a "name" which is appended to a generated path. #8519
- matches([[.*[/\\]xtest1%.2%.3%.4[^/\\]*]], funcs.serverstart('xtest1.2.3.4'))
+ matches([[.*[/\\]xtest1%.2%.3%.4[^/\\]*]], fn.serverstart('xtest1.2.3.4'))
clear_serverlist()
- eq('Vim:Failed to start server: invalid argument',
- pcall_err(funcs.serverstart, '127.0.0.1:65536')) -- invalid port
- eq({}, funcs.serverlist())
+ eq('Vim:Failed to start server: invalid argument', pcall_err(fn.serverstart, '127.0.0.1:65536')) -- invalid port
+ eq({}, fn.serverlist())
end)
it('serverlist() returns the list of servers', function()
@@ -146,11 +145,12 @@ describe('server', function()
local n = eval('len(serverlist())')
-- Add some servers.
- local servs = (is_os('win')
- and { [[\\.\pipe\Xtest-pipe0934]], [[\\.\pipe\Xtest-pipe4324]] }
- or { [[./Xtest-pipe0934]], [[./Xtest-pipe4324]] })
+ local servs = (
+ is_os('win') and { [[\\.\pipe\Xtest-pipe0934]], [[\\.\pipe\Xtest-pipe4324]] }
+ or { [[./Xtest-pipe0934]], [[./Xtest-pipe4324]] }
+ )
for _, s in ipairs(servs) do
- eq(s, eval("serverstart('"..s.."')"))
+ eq(s, eval("serverstart('" .. s .. "')"))
end
local new_servs = eval('serverlist()')
@@ -160,7 +160,7 @@ describe('server', function()
-- The new servers should be at the end of the list.
for i = 1, #servs do
eq(servs[i], new_servs[i + n])
- eq(1, eval("serverstop('"..servs[i].."')"))
+ eq(1, eval("serverstop('" .. servs[i] .. "')"))
end
-- After serverstop() the servers should NOT be in the list.
eq(n, eval('len(serverlist())'))
@@ -172,22 +172,20 @@ describe('startup --listen', function()
clear()
local cmd = { unpack(helpers.nvim_argv) }
table.insert(cmd, '--listen')
- matches('nvim.*: Argument missing after: "%-%-listen"', funcs.system(cmd))
+ matches('nvim.*: Argument missing after: "%-%-listen"', fn.system(cmd))
cmd = { unpack(helpers.nvim_argv) }
table.insert(cmd, '--listen2')
- matches('nvim.*: Garbage after option argument: "%-%-listen2"', funcs.system(cmd))
+ matches('nvim.*: Garbage after option argument: "%-%-listen2"', fn.system(cmd))
end)
it('sets v:servername, overrides $NVIM_LISTEN_ADDRESS', function()
- local addr = (is_os('win') and [[\\.\pipe\Xtest-listen-pipe]]
- or './Xtest-listen-pipe')
- clear({ env={ NVIM_LISTEN_ADDRESS='./Xtest-env-pipe' },
- args={ '--listen', addr } })
- eq(addr, meths.get_vvar('servername'))
+ local addr = (is_os('win') and [[\\.\pipe\Xtest-listen-pipe]] or './Xtest-listen-pipe')
+ clear({ env = { NVIM_LISTEN_ADDRESS = './Xtest-env-pipe' }, args = { '--listen', addr } })
+ eq(addr, api.nvim_get_vvar('servername'))
-- Address without slashes is a "name" which is appended to a generated path. #8519
- clear({ args={ '--listen', 'test-name' } })
- matches([[.*[/\\]test%-name[^/\\]*]], meths.get_vvar('servername'))
+ clear({ args = { '--listen', 'test-name' } })
+ matches([[.*[/\\]test%-name[^/\\]*]], api.nvim_get_vvar('servername'))
end)
end)
diff --git a/test/functional/vimscript/setpos_spec.lua b/test/functional/vimscript/setpos_spec.lua
index 02e550dcc0..a26e48f469 100644
--- a/test/functional/vimscript/setpos_spec.lua
+++ b/test/functional/vimscript/setpos_spec.lua
@@ -1,6 +1,6 @@
local helpers = require('test.functional.helpers')(after_each)
-local setpos = helpers.funcs.setpos
-local getpos = helpers.funcs.getpos
+local setpos = helpers.fn.setpos
+local getpos = helpers.fn.getpos
local insert = helpers.insert
local clear = helpers.clear
local command = helpers.command
@@ -8,7 +8,6 @@ local eval = helpers.eval
local eq = helpers.eq
local exc_exec = helpers.exc_exec
-
describe('setpos() function', function()
before_each(function()
clear()
@@ -23,42 +22,42 @@ describe('setpos() function', function()
Line of text 3]])
end)
it('can set the current cursor position', function()
- setpos(".", {0, 2, 1, 0})
- eq({0, 2, 1, 0}, getpos("."))
- setpos(".", {2, 1, 1, 0})
- eq({0, 1, 1, 0}, getpos("."))
+ setpos('.', { 0, 2, 1, 0 })
+ eq({ 0, 2, 1, 0 }, getpos('.'))
+ setpos('.', { 2, 1, 1, 0 })
+ eq({ 0, 1, 1, 0 }, getpos('.'))
local ret = exc_exec('call setpos(".", [1, 1, 1, 0])')
eq(0, ret)
end)
it('can set lowercase marks in the current buffer', function()
- setpos("'d", {0, 2, 1, 0})
- eq({0, 2, 1, 0}, getpos("'d"))
+ setpos("'d", { 0, 2, 1, 0 })
+ eq({ 0, 2, 1, 0 }, getpos("'d"))
command('undo')
command('call setpos("\'d", [2, 3, 1, 0])')
- eq({0, 3, 1, 0}, getpos("'d"))
+ eq({ 0, 3, 1, 0 }, getpos("'d"))
end)
it('can set lowercase marks in other buffers', function()
- local retval = setpos("'d", {1, 2, 1, 0})
+ local retval = setpos("'d", { 1, 2, 1, 0 })
eq(0, retval)
- setpos("'d", {1, 2, 1, 0})
- eq({0, 0, 0, 0}, getpos("'d"))
+ setpos("'d", { 1, 2, 1, 0 })
+ eq({ 0, 0, 0, 0 }, getpos("'d"))
command('wincmd w')
eq(1, eval('bufnr("%")'))
- eq({0, 2, 1, 0}, getpos("'d"))
+ eq({ 0, 2, 1, 0 }, getpos("'d"))
end)
it("fails when setting a mark in a buffer that doesn't exist", function()
- local retval = setpos("'d", {3, 2, 1, 0})
+ local retval = setpos("'d", { 3, 2, 1, 0 })
eq(-1, retval)
- eq({0, 0, 0, 0}, getpos("'d"))
- retval = setpos("'D", {3, 2, 1, 0})
+ eq({ 0, 0, 0, 0 }, getpos("'d"))
+ retval = setpos("'D", { 3, 2, 1, 0 })
eq(-1, retval)
- eq({0, 0, 0, 0}, getpos("'D"))
+ eq({ 0, 0, 0, 0 }, getpos("'D"))
end)
it('can set uppercase marks', function()
- setpos("'D", {2, 2, 3, 0})
- eq({2, 2, 3, 0}, getpos("'D"))
+ setpos("'D", { 2, 2, 3, 0 })
+ eq({ 2, 2, 3, 0 }, getpos("'D"))
-- Can set a mark in another buffer
- setpos("'D", {1, 2, 2, 0})
- eq({1, 2, 2, 0}, getpos("'D"))
+ setpos("'D", { 1, 2, 2, 0 })
+ eq({ 1, 2, 2, 0 }, getpos("'D"))
end)
end)
diff --git a/test/functional/vimscript/sort_spec.lua b/test/functional/vimscript/sort_spec.lua
index e09949a0f2..bd3d0da146 100644
--- a/test/functional/vimscript/sort_spec.lua
+++ b/test/functional/vimscript/sort_spec.lua
@@ -1,11 +1,11 @@
local helpers = require('test.functional.helpers')(after_each)
local eq = helpers.eq
-local NIL = helpers.NIL
+local NIL = vim.NIL
local eval = helpers.eval
local clear = helpers.clear
-local meths = helpers.meths
-local funcs = helpers.funcs
+local api = helpers.api
+local fn = helpers.fn
local command = helpers.command
local exc_exec = helpers.exc_exec
local pcall_err = helpers.pcall_err
@@ -14,31 +14,41 @@ before_each(clear)
describe('sort()', function()
it('errors out when sorting special values', function()
- eq('Vim(call):E362: Using a boolean value as a Float',
- exc_exec('call sort([v:true, v:false], "f")'))
+ eq(
+ 'Vim(call):E362: Using a boolean value as a Float',
+ exc_exec('call sort([v:true, v:false], "f")')
+ )
end)
- it('sorts “wrong†values between -0.0001 and 0.0001, preserving order',
- function()
- meths.set_var('list', {true, false, NIL, {}, {a=42}, 'check',
- 0.0001, -0.0001})
+ it('sorts “wrong†values between -0.0001 and 0.0001, preserving order', function()
+ api.nvim_set_var('list', {
+ true,
+ false,
+ NIL,
+ {},
+ { a = 42 },
+ 'check',
+ 0.0001,
+ -0.0001,
+ })
command('call insert(g:list, function("tr"))')
- local error_lines = funcs.split(
- funcs.execute('silent! call sort(g:list, "f")'), '\n')
+ local error_lines = fn.split(fn.execute('silent! call sort(g:list, "f")'), '\n')
local errors = {}
for _, err in ipairs(error_lines) do
errors[err] = true
end
eq({
- ['E362: Using a boolean value as a Float']=true,
- ['E891: Using a Funcref as a Float']=true,
- ['E892: Using a String as a Float']=true,
- ['E893: Using a List as a Float']=true,
- ['E894: Using a Dictionary as a Float']=true,
- ['E907: Using a special value as a Float']=true,
+ ['E362: Using a boolean value as a Float'] = true,
+ ['E891: Using a Funcref as a Float'] = true,
+ ['E892: Using a String as a Float'] = true,
+ ['E893: Using a List as a Float'] = true,
+ ['E894: Using a Dictionary as a Float'] = true,
+ ['E907: Using a special value as a Float'] = true,
}, errors)
- eq('[-1.0e-4, function(\'tr\'), v:true, v:false, v:null, [], {\'a\': 42}, \'check\', 1.0e-4]',
- eval('string(g:list)'))
+ eq(
+ "[-1.0e-4, function('tr'), v:true, v:false, v:null, [], {'a': 42}, 'check', 1.0e-4]",
+ eval('string(g:list)')
+ )
end)
it('can yield E702 and stop sorting after that', function()
@@ -50,7 +60,9 @@ describe('sort()', function()
return (a:a > a:b) - (a:a < a:b)
endfunction
]])
- eq('Vim(let):E745: Using a List as a Number',
- pcall_err(command, 'let sl = sort([1, 0, [], 3, 2], "Cmp")'))
+ eq(
+ 'Vim(let):E745: Using a List as a Number',
+ pcall_err(command, 'let sl = sort([1, 0, [], 3, 2], "Cmp")')
+ )
end)
end)
diff --git a/test/functional/vimscript/special_vars_spec.lua b/test/functional/vimscript/special_vars_spec.lua
index 217f0b2c2b..590d409141 100644
--- a/test/functional/vimscript/special_vars_spec.lua
+++ b/test/functional/vimscript/special_vars_spec.lua
@@ -1,12 +1,12 @@
local helpers = require('test.functional.helpers')(after_each)
local exc_exec = helpers.exc_exec
local command = helpers.command
-local funcs = helpers.funcs
+local fn = helpers.fn
local clear = helpers.clear
local eval = helpers.eval
local eq = helpers.eq
-local meths = helpers.meths
-local NIL = helpers.NIL
+local api = helpers.api
+local NIL = vim.NIL
describe('Special values', function()
before_each(clear)
@@ -25,15 +25,15 @@ describe('Special values', function()
end)
it('work with empty()', function()
- eq(0, funcs.empty(true))
- eq(1, funcs.empty(false))
- eq(1, funcs.empty(NIL))
+ eq(0, fn.empty(true))
+ eq(1, fn.empty(false))
+ eq(1, fn.empty(NIL))
end)
it('can be stringified and eval’ed back', function()
- eq(true, funcs.eval(funcs.string(true)))
- eq(false, funcs.eval(funcs.string(false)))
- eq(NIL, funcs.eval(funcs.string(NIL)))
+ eq(true, fn.eval(fn.string(true)))
+ eq(false, fn.eval(fn.string(false)))
+ eq(NIL, fn.eval(fn.string(NIL)))
end)
it('work with is/isnot properly', function()
@@ -98,8 +98,8 @@ describe('Special values', function()
eq(0, eval('0 + v:false'))
eq(-1, eval('0 - v:true'))
- eq( 0, eval('0 - v:null'))
- eq( 0, eval('0 - v:false'))
+ eq(0, eval('0 - v:null'))
+ eq(0, eval('0 - v:false'))
eq(1, eval('1 * v:true'))
eq(0, eval('1 * v:null'))
@@ -107,8 +107,8 @@ describe('Special values', function()
end)
it('does not work with +=/-=/.=', function()
- meths.set_var('true', true)
- meths.set_var('false', false)
+ api.nvim_set_var('true', true)
+ api.nvim_set_var('false', false)
command('let null = v:null')
eq('Vim(let):E734: Wrong variable type for +=', exc_exec('let true += 1'))
@@ -125,9 +125,9 @@ describe('Special values', function()
end)
it('work with . (concat) properly', function()
- eq("v:true", eval('"" . v:true'))
- eq("v:null", eval('"" . v:null'))
- eq("v:false", eval('"" . v:false'))
+ eq('v:true', eval('"" . v:true'))
+ eq('v:null', eval('"" . v:null'))
+ eq('v:false', eval('"" . v:false'))
end)
it('work with ?? (falsy operator)', function()
@@ -137,19 +137,19 @@ describe('Special values', function()
end)
it('work with type()', function()
- eq(6, funcs.type(true))
- eq(6, funcs.type(false))
- eq(7, funcs.type(NIL))
+ eq(6, fn.type(true))
+ eq(6, fn.type(false))
+ eq(7, fn.type(NIL))
end)
it('work with copy() and deepcopy()', function()
- eq(true, funcs.deepcopy(true))
- eq(false, funcs.deepcopy(false))
- eq(NIL, funcs.deepcopy(NIL))
+ eq(true, fn.deepcopy(true))
+ eq(false, fn.deepcopy(false))
+ eq(NIL, fn.deepcopy(NIL))
- eq(true, funcs.copy(true))
- eq(false, funcs.copy(false))
- eq(NIL, funcs.copy(NIL))
+ eq(true, fn.copy(true))
+ eq(false, fn.copy(false))
+ eq(NIL, fn.copy(NIL))
end)
it('fails in index', function()
@@ -159,20 +159,20 @@ describe('Special values', function()
end)
it('is accepted by assert_true and assert_false', function()
- funcs.assert_false(false)
- funcs.assert_false(true)
- funcs.assert_false(NIL)
+ fn.assert_false(false)
+ fn.assert_false(true)
+ fn.assert_false(NIL)
- funcs.assert_true(false)
- funcs.assert_true(true)
- funcs.assert_true(NIL)
+ fn.assert_true(false)
+ fn.assert_true(true)
+ fn.assert_true(NIL)
eq({
'Expected False but got v:true',
'Expected False but got v:null',
'Expected True but got v:false',
'Expected True but got v:null',
- }, meths.get_vvar('errors'))
+ }, api.nvim_get_vvar('errors'))
end)
describe('compat', function()
diff --git a/test/functional/vimscript/state_spec.lua b/test/functional/vimscript/state_spec.lua
index 0508b8b1da..7179806e36 100644
--- a/test/functional/vimscript/state_spec.lua
+++ b/test/functional/vimscript/state_spec.lua
@@ -4,7 +4,7 @@ local eq = helpers.eq
local exec = helpers.exec
local exec_lua = helpers.exec_lua
local feed = helpers.feed
-local meths = helpers.meths
+local api = helpers.api
local poke_eventloop = helpers.poke_eventloop
before_each(clear)
@@ -12,7 +12,7 @@ before_each(clear)
describe('state() function', function()
-- oldtest: Test_state()
it('works', function()
- meths.ui_attach(80, 24, {}) -- Allow hit-enter-prompt
+ api.nvim_ui_attach(80, 24, {}) -- Allow hit-enter-prompt
exec_lua([[
function _G.Get_state_mode()
@@ -42,34 +42,34 @@ describe('state() function', function()
-- Using a timer callback
feed([[:call RunTimer()<CR>]])
- poke_eventloop() -- Process pending input
- poke_eventloop() -- Process time_event
+ poke_eventloop() -- Process pending input
+ poke_eventloop() -- Process time_event
eq({ 'c', 'n' }, exec_lua('return _G.res'))
-- Halfway a mapping
feed([[:call v:lua.Run_timer()<CR>;]])
- meths.get_mode() -- Process pending input and luv timer callback
+ api.nvim_get_mode() -- Process pending input and luv timer callback
feed(';')
eq({ 'mS', 'n' }, exec_lua('return _G.res'))
-- An operator is pending
feed([[:call RunTimer()<CR>y]])
- poke_eventloop() -- Process pending input
- poke_eventloop() -- Process time_event
+ poke_eventloop() -- Process pending input
+ poke_eventloop() -- Process time_event
feed('y')
eq({ 'oSc', 'n' }, exec_lua('return _G.res'))
-- A register was specified
feed([[:call RunTimer()<CR>"r]])
- poke_eventloop() -- Process pending input
- poke_eventloop() -- Process time_event
+ poke_eventloop() -- Process pending input
+ poke_eventloop() -- Process time_event
feed('yy')
eq({ 'oSc', 'n' }, exec_lua('return _G.res'))
-- Insert mode completion
feed([[:call RunTimer()<CR>Got<C-N>]])
- poke_eventloop() -- Process pending input
- poke_eventloop() -- Process time_event
+ poke_eventloop() -- Process pending input
+ poke_eventloop() -- Process time_event
feed('<Esc>')
eq({ 'aSc', 'i' }, exec_lua('return _G.res'))
@@ -79,7 +79,7 @@ describe('state() function', function()
-- messages scrolled
feed([[:call v:lua.Run_timer() | echo "one\ntwo\nthree"<CR>]])
- meths.get_mode() -- Process pending input and luv timer callback
+ api.nvim_get_mode() -- Process pending input and luv timer callback
feed('<CR>')
eq({ 'Ss', 'r' }, exec_lua('return _G.res'))
end)
diff --git a/test/functional/vimscript/string_spec.lua b/test/functional/vimscript/string_spec.lua
index cb7e93f264..6a7fe1bad9 100644
--- a/test/functional/vimscript/string_spec.lua
+++ b/test/functional/vimscript/string_spec.lua
@@ -2,12 +2,12 @@ local helpers = require('test.functional.helpers')(after_each)
local clear = helpers.clear
local eq = helpers.eq
local command = helpers.command
-local meths = helpers.meths
+local api = helpers.api
local eval = helpers.eval
local exc_exec = helpers.exc_exec
local pcall_err = helpers.pcall_err
-local funcs = helpers.funcs
-local NIL = helpers.NIL
+local fn = helpers.fn
+local NIL = vim.NIL
local source = helpers.source
describe('string() function', function()
@@ -15,17 +15,17 @@ describe('string() function', function()
describe('used to represent floating-point values', function()
it('dumps NaN values', function()
- eq('str2float(\'nan\')', eval('string(str2float(\'nan\'))'))
+ eq("str2float('nan')", eval("string(str2float('nan'))"))
end)
it('dumps infinite values', function()
- eq('str2float(\'inf\')', eval('string(str2float(\'inf\'))'))
- eq('-str2float(\'inf\')', eval('string(str2float(\'-inf\'))'))
+ eq("str2float('inf')", eval("string(str2float('inf'))"))
+ eq("-str2float('inf')", eval("string(str2float('-inf'))"))
end)
it('dumps regular values', function()
- eq('1.5', funcs.string(1.5))
- eq('1.56e-20', funcs.string(1.56000e-020))
+ eq('1.5', fn.string(1.5))
+ eq('1.56e-20', fn.string(1.56000e-020))
eq('0.0', eval('string(0.0)'))
end)
@@ -33,64 +33,62 @@ describe('string() function', function()
eq('v:true', eval('string(v:true)'))
eq('v:false', eval('string(v:false)'))
eq('v:null', eval('string(v:null)'))
- eq('v:true', funcs.string(true))
- eq('v:false', funcs.string(false))
- eq('v:null', funcs.string(NIL))
+ eq('v:true', fn.string(true))
+ eq('v:false', fn.string(false))
+ eq('v:null', fn.string(NIL))
end)
- it('dumps values with at most six digits after the decimal point',
- function()
- eq('1.234568e-20', funcs.string(1.23456789123456789123456789e-020))
- eq('1.234568', funcs.string(1.23456789123456789123456789))
+ it('dumps values with at most six digits after the decimal point', function()
+ eq('1.234568e-20', fn.string(1.23456789123456789123456789e-020))
+ eq('1.234568', fn.string(1.23456789123456789123456789))
end)
- it('dumps values with at most seven digits before the decimal point',
- function()
- eq('1234567.891235', funcs.string(1234567.89123456789123456789))
- eq('1.234568e7', funcs.string(12345678.9123456789123456789))
+ it('dumps values with at most seven digits before the decimal point', function()
+ eq('1234567.891235', fn.string(1234567.89123456789123456789))
+ eq('1.234568e7', fn.string(12345678.9123456789123456789))
end)
it('dumps negative values', function()
- eq('-1.5', funcs.string(-1.5))
- eq('-1.56e-20', funcs.string(-1.56000e-020))
- eq('-1.234568e-20', funcs.string(-1.23456789123456789123456789e-020))
- eq('-1.234568', funcs.string(-1.23456789123456789123456789))
- eq('-1234567.891235', funcs.string(-1234567.89123456789123456789))
- eq('-1.234568e7', funcs.string(-12345678.9123456789123456789))
+ eq('-1.5', fn.string(-1.5))
+ eq('-1.56e-20', fn.string(-1.56000e-020))
+ eq('-1.234568e-20', fn.string(-1.23456789123456789123456789e-020))
+ eq('-1.234568', fn.string(-1.23456789123456789123456789))
+ eq('-1234567.891235', fn.string(-1234567.89123456789123456789))
+ eq('-1.234568e7', fn.string(-12345678.9123456789123456789))
end)
end)
describe('used to represent numbers', function()
it('dumps regular values', function()
- eq('0', funcs.string(0))
- eq('-1', funcs.string(-1))
- eq('1', funcs.string(1))
+ eq('0', fn.string(0))
+ eq('-1', fn.string(-1))
+ eq('1', fn.string(1))
end)
it('dumps large values', function()
- eq('2147483647', funcs.string(2^31-1))
- eq('-2147483648', funcs.string(-2^31))
+ eq('2147483647', fn.string(2 ^ 31 - 1))
+ eq('-2147483648', fn.string(-2 ^ 31))
end)
end)
describe('used to represent strings', function()
it('dumps regular strings', function()
- eq('\'test\'', funcs.string('test'))
+ eq("'test'", fn.string('test'))
end)
it('dumps empty strings', function()
- eq('\'\'', funcs.string(''))
+ eq("''", fn.string(''))
end)
- it('dumps strings with \' inside', function()
- eq('\'\'\'\'\'\'\'\'', funcs.string('\'\'\''))
- eq('\'a\'\'b\'\'\'\'\'', funcs.string('a\'b\'\''))
- eq('\'\'\'b\'\'\'\'d\'', funcs.string('\'b\'\'d'))
- eq('\'a\'\'b\'\'c\'\'d\'', funcs.string('a\'b\'c\'d'))
+ it("dumps strings with ' inside", function()
+ eq("''''''''", fn.string("'''"))
+ eq("'a''b'''''", fn.string("a'b''"))
+ eq("'''b''''d'", fn.string("'b''d"))
+ eq("'a''b''c''d'", fn.string("a'b'c'd"))
end)
it('dumps NULL strings', function()
- eq('\'\'', eval('string($XXX_UNEXISTENT_VAR_XXX)'))
+ eq("''", eval('string($XXX_UNEXISTENT_VAR_XXX)'))
end)
it('dumps NULL lists', function()
@@ -119,16 +117,16 @@ describe('string() function', function()
end)
it('dumps references to built-in functions', function()
- eq('function(\'function\')', eval('string(function("function"))'))
+ eq("function('function')", eval('string(function("function"))'))
end)
it('dumps references to user functions', function()
- eq('function(\'Test1\')', eval('string(function("Test1"))'))
- eq('function(\'g:Test3\')', eval('string(function("g:Test3"))'))
+ eq("function('Test1')", eval('string(function("Test1"))'))
+ eq("function('g:Test3')", eval('string(function("g:Test3"))'))
end)
it('dumps references to script functions', function()
- eq('function(\'<SNR>1_Test2\')', eval('string(Test2_f)'))
+ eq("function('<SNR>1_Test2')", eval('string(Test2_f)'))
end)
it('dumps partials with self referencing a partial', function()
@@ -139,96 +137,119 @@ describe('string() function', function()
let TestDictRef = function('TestDict', d)
let d.tdr = TestDictRef
]])
- eq("Vim(echo):E724: unable to correctly dump variable with self-referencing container",
- pcall_err(command, 'echo string(d.tdr)'))
+ eq(
+ 'Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ pcall_err(command, 'echo string(d.tdr)')
+ )
end)
it('dumps automatically created partials', function()
- eq('function(\'<SNR>1_Test2\', {\'f\': function(\'<SNR>1_Test2\')})',
- eval('string({"f": Test2_f}.f)'))
- eq('function(\'<SNR>1_Test2\', [1], {\'f\': function(\'<SNR>1_Test2\', [1])})',
- eval('string({"f": function(Test2_f, [1])}.f)'))
+ eq(
+ "function('<SNR>1_Test2', {'f': function('<SNR>1_Test2')})",
+ eval('string({"f": Test2_f}.f)')
+ )
+ eq(
+ "function('<SNR>1_Test2', [1], {'f': function('<SNR>1_Test2', [1])})",
+ eval('string({"f": function(Test2_f, [1])}.f)')
+ )
end)
it('dumps manually created partials', function()
- eq('function(\'Test3\', [1, 2], {})',
- eval('string(function("Test3", [1, 2], {}))'))
- eq('function(\'Test3\', {})',
- eval('string(function("Test3", {}))'))
- eq('function(\'Test3\', [1, 2])',
- eval('string(function("Test3", [1, 2]))'))
+ eq("function('Test3', [1, 2], {})", eval('string(function("Test3", [1, 2], {}))'))
+ eq("function('Test3', {})", eval('string(function("Test3", {}))'))
+ eq("function('Test3', [1, 2])", eval('string(function("Test3", [1, 2]))'))
end)
- it('does not crash or halt when dumping partials with reference cycles in self',
- function()
- meths.set_var('d', {v=true})
- eq([[Vim(echo):E724: unable to correctly dump variable with self-referencing container]],
- pcall_err(command, 'echo string(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))'))
+ it('does not crash or halt when dumping partials with reference cycles in self', function()
+ api.nvim_set_var('d', { v = true })
+ eq(
+ [[Vim(echo):E724: unable to correctly dump variable with self-referencing container]],
+ pcall_err(command, 'echo string(extend(extend(g:d, {"f": g:Test2_f}), {"p": g:d.f}))')
+ )
end)
- it('does not show errors when dumping partials referencing the same dictionary',
- function()
+ it('does not show errors when dumping partials referencing the same dictionary', function()
command('let d = {}')
-- Regression for “eval/typval_encode: Dump empty dictionary before
-- checking for refcycleâ€, results in error.
- eq('[function(\'tr\', {}), function(\'tr\', {})]', eval('string([function("tr", d), function("tr", d)])'))
+ eq(
+ "[function('tr', {}), function('tr', {})]",
+ eval('string([function("tr", d), function("tr", d)])')
+ )
-- Regression for “eval: Work with reference cycles in partials (self)
-- properlyâ€, results in crash.
eval('extend(d, {"a": 1})')
- eq('[function(\'tr\', {\'a\': 1}), function(\'tr\', {\'a\': 1})]', eval('string([function("tr", d), function("tr", d)])'))
+ eq(
+ "[function('tr', {'a': 1}), function('tr', {'a': 1})]",
+ eval('string([function("tr", d), function("tr", d)])')
+ )
end)
- it('does not crash or halt when dumping partials with reference cycles in arguments',
- function()
- meths.set_var('l', {})
+ it('does not crash or halt when dumping partials with reference cycles in arguments', function()
+ api.nvim_set_var('l', {})
eval('add(l, l)')
-- Regression: the below line used to crash (add returns original list and
-- there was error in dumping partials). Tested explicitly in
-- test/unit/api/private_helpers_spec.lua.
eval('add(l, function("Test1", l))')
- eq([=[Vim(echo):E724: unable to correctly dump variable with self-referencing container]=],
- pcall_err(command, 'echo string(function("Test1", l))'))
- end)
-
- it('does not crash or halt when dumping partials with reference cycles in self and arguments',
- function()
- meths.set_var('d', {v=true})
- meths.set_var('l', {})
- eval('add(l, l)')
- eval('add(l, function("Test1", l))')
- eval('add(l, function("Test1", d))')
- eq([=[Vim(echo):E724: unable to correctly dump variable with self-referencing container]=],
- pcall_err(command, 'echo string(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))'))
- end)
+ eq(
+ [=[Vim(echo):E724: unable to correctly dump variable with self-referencing container]=],
+ pcall_err(command, 'echo string(function("Test1", l))')
+ )
+ end)
+
+ it(
+ 'does not crash or halt when dumping partials with reference cycles in self and arguments',
+ function()
+ api.nvim_set_var('d', { v = true })
+ api.nvim_set_var('l', {})
+ eval('add(l, l)')
+ eval('add(l, function("Test1", l))')
+ eval('add(l, function("Test1", d))')
+ eq(
+ [=[Vim(echo):E724: unable to correctly dump variable with self-referencing container]=],
+ pcall_err(
+ command,
+ 'echo string(extend(extend(g:d, {"f": g:Test2_f}), {"p": function(g:d.f, l)}))'
+ )
+ )
+ end
+ )
end)
describe('used to represent lists', function()
it('dumps empty list', function()
- eq('[]', funcs.string({}))
+ eq('[]', fn.string({}))
end)
it('dumps nested lists', function()
- eq('[[[[[]]]]]', funcs.string({{{{{}}}}}))
+ eq('[[[[[]]]]]', fn.string({ { { { {} } } } }))
end)
it('dumps nested non-empty lists', function()
- eq('[1, [[3, [[5], 4]], 2]]', funcs.string({1, {{3, {{5}, 4}}, 2}}))
+ eq('[1, [[3, [[5], 4]], 2]]', fn.string({ 1, { { 3, { { 5 }, 4 } }, 2 } }))
end)
it('errors when dumping recursive lists', function()
- meths.set_var('l', {})
+ api.nvim_set_var('l', {})
eval('add(l, l)')
- eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
- exc_exec('echo string(l)'))
+ eq(
+ 'Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('echo string(l)')
+ )
end)
it('dumps recursive lists despite the error', function()
- meths.set_var('l', {})
+ api.nvim_set_var('l', {})
eval('add(l, l)')
- eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
- pcall_err(command, 'echo string(l)'))
- eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
- pcall_err(command, 'echo string([l])'))
+ eq(
+ 'Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ pcall_err(command, 'echo string(l)')
+ )
+ eq(
+ 'Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ pcall_err(command, 'echo string([l])')
+ )
end)
end)
@@ -240,28 +261,34 @@ describe('string() function', function()
it('dumps list with two same empty dictionaries, also in partials', function()
command('let d = {}')
eq('[{}, {}]', eval('string([d, d])'))
- eq('[function(\'tr\', {}), {}]', eval('string([function("tr", d), d])'))
- eq('[{}, function(\'tr\', {})]', eval('string([d, function("tr", d)])'))
+ eq("[function('tr', {}), {}]", eval('string([function("tr", d), d])'))
+ eq("[{}, function('tr', {})]", eval('string([d, function("tr", d)])'))
end)
it('dumps non-empty dictionary', function()
- eq('{\'t\'\'est\': 1}', funcs.string({['t\'est']=1}))
+ eq("{'t''est': 1}", fn.string({ ["t'est"] = 1 }))
end)
it('errors when dumping recursive dictionaries', function()
- meths.set_var('d', {d=1})
+ api.nvim_set_var('d', { d = 1 })
eval('extend(d, {"d": d})')
- eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
- exc_exec('echo string(d)'))
+ eq(
+ 'Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ exc_exec('echo string(d)')
+ )
end)
it('dumps recursive dictionaries despite the error', function()
- meths.set_var('d', {d=1})
+ api.nvim_set_var('d', { d = 1 })
eval('extend(d, {"d": d})')
- eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
- pcall_err(command, 'echo string(d)'))
- eq('Vim(echo):E724: unable to correctly dump variable with self-referencing container',
- pcall_err(command, 'echo string({"out": d})'))
+ eq(
+ 'Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ pcall_err(command, 'echo string(d)')
+ )
+ eq(
+ 'Vim(echo):E724: unable to correctly dump variable with self-referencing container',
+ pcall_err(command, 'echo string({"out": d})')
+ )
end)
end)
end)
diff --git a/test/functional/vimscript/system_spec.lua b/test/functional/vimscript/system_spec.lua
index 90aab48d61..d44f68e152 100644
--- a/test/functional/vimscript/system_spec.lua
+++ b/test/functional/vimscript/system_spec.lua
@@ -4,9 +4,14 @@ local helpers = require('test.functional.helpers')(after_each)
local assert_alive = helpers.assert_alive
local testprg = helpers.testprg
-local eq, call, clear, eval, feed_command, feed, nvim =
- helpers.eq, helpers.call, helpers.clear, helpers.eval, helpers.feed_command,
- helpers.feed, helpers.nvim
+local eq, call, clear, eval, feed_command, feed, api =
+ helpers.eq,
+ helpers.call,
+ helpers.clear,
+ helpers.eval,
+ helpers.feed_command,
+ helpers.feed,
+ helpers.api
local command = helpers.command
local insert = helpers.insert
local expect = helpers.expect
@@ -19,14 +24,14 @@ local Screen = require('test.functional.ui.screen')
local function create_file_with_nuls(name)
return function()
- feed('ipart1<C-V>000part2<C-V>000part3<ESC>:w '..name..'<CR>')
- eval('1') -- wait for the file to be created
+ feed('ipart1<C-V>000part2<C-V>000part3<ESC>:w ' .. name .. '<CR>')
+ eval('1') -- wait for the file to be created
end
end
local function delete_file(name)
return function()
- eval("delete('"..name.."')")
+ eval("delete('" .. name .. "')")
end
end
@@ -35,8 +40,10 @@ describe('system()', function()
describe('command passed as a List', function()
it('throws error if cmd[0] is not executable', function()
- eq("Vim:E475: Invalid value for argument cmd: 'this-should-not-exist' is not executable",
- pcall_err(call, 'system', { 'this-should-not-exist' }))
+ eq(
+ "Vim:E475: Invalid value for argument cmd: 'this-should-not-exist' is not executable",
+ pcall_err(call, 'system', { 'this-should-not-exist' })
+ )
eq(-1, eval('v:shell_error'))
end)
@@ -51,8 +58,10 @@ describe('system()', function()
eq(0, eval('v:shell_error'))
-- Provoke a non-zero v:shell_error.
- eq("Vim:E475: Invalid value for argument cmd: 'this-should-not-exist' is not executable",
- pcall_err(call, 'system', { 'this-should-not-exist' }))
+ eq(
+ "Vim:E475: Invalid value for argument cmd: 'this-should-not-exist' is not executable",
+ pcall_err(call, 'system', { 'this-should-not-exist' })
+ )
local old_val = eval('v:shell_error')
eq(-1, old_val)
@@ -65,8 +74,8 @@ describe('system()', function()
end)
it('quotes arguments correctly #5280', function()
- local out = call('system',
- { testprg('printargs-test'), [[1]], [[2 "3]], [[4 ' 5]], [[6 ' 7']] })
+ local out =
+ call('system', { testprg('printargs-test'), [[1]], [[2 "3]], [[4 ' 5]], [[6 ' 7']] })
eq(0, eval('v:shell_error'))
eq([[arg1=1;arg2=2 "3;arg3=4 ' 5;arg4=6 ' 7';]], out)
@@ -75,22 +84,29 @@ describe('system()', function()
eq(0, eval('v:shell_error'))
eq([[arg1='1;arg2=2 "3;]], out)
- out = call('system', { testprg('printargs-test'), "A\nB" })
+ out = call('system', { testprg('printargs-test'), 'A\nB' })
eq(0, eval('v:shell_error'))
- eq("arg1=A\nB;", out)
+ eq('arg1=A\nB;', out)
end)
it('calls executable in $PATH', function()
- if 0 == eval("executable('python3')") then pending("missing `python3`") end
- eq("foo\n", eval([[system(['python3', '-c', 'print("foo")'])]]))
+ if 0 == eval("executable('python3')") then
+ pending('missing `python3`')
+ end
+ eq('foo\n', eval([[system(['python3', '-c', 'print("foo")'])]]))
eq(0, eval('v:shell_error'))
end)
it('does NOT run in shell', function()
if is_os('win') then
- eq("%PATH%\n", eval("system(['powershell', '-NoProfile', '-NoLogo', '-ExecutionPolicy', 'RemoteSigned', '-Command', 'Write-Output', '%PATH%'])"))
+ eq(
+ '%PATH%\n',
+ eval(
+ "system(['powershell', '-NoProfile', '-NoLogo', '-ExecutionPolicy', 'RemoteSigned', '-Command', 'Write-Output', '%PATH%'])"
+ )
+ )
else
- eq("* $PATH %PATH%\n", eval("system(['echo', '*', '$PATH', '%PATH%'])"))
+ eq('* $PATH %PATH%\n', eval("system(['echo', '*', '$PATH', '%PATH%'])"))
end
end)
end)
@@ -133,7 +149,12 @@ describe('system()', function()
eval([[system('"ping" "-n" "1" "127.0.0.1"')]])
eq(0, eval('v:shell_error'))
eq('"a b"\n', eval([[system('cmd /s/c "cmd /s/c "cmd /s/c "echo "a b""""')]]))
- eq('"a b"\n', eval([[system('powershell -NoProfile -NoLogo -ExecutionPolicy RemoteSigned -Command Write-Output ''\^"a b\^"''')]]))
+ eq(
+ '"a b"\n',
+ eval(
+ [[system('powershell -NoProfile -NoLogo -ExecutionPolicy RemoteSigned -Command Write-Output ''\^"a b\^"''')]]
+ )
+ )
end
it('with shell=cmd.exe', function()
@@ -177,7 +198,7 @@ describe('system()', function()
it('powershell w/ UTF-8 text #13713', function()
if not helpers.has_powershell() then
- pending("powershell not found", function() end)
+ pending('powershell not found', function() end)
return
end
helpers.set_shell_powershell()
@@ -193,32 +214,21 @@ describe('system()', function()
feed(':call system("echo")<cr>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*12
:call system("echo") |
]])
end)
it('prints verbose information', function()
- nvim('set_option_value', 'shell', 'fake_shell', {})
- nvim('set_option_value', 'shellcmdflag', 'cmdflag', {})
+ api.nvim_set_option_value('shell', 'fake_shell', {})
+ api.nvim_set_option_value('shellcmdflag', 'cmdflag', {})
screen:try_resize(72, 14)
feed(':4verbose echo system("echo hi")<cr>')
if is_os('win') then
- screen:expect{any=[[Executing command: "'fake_shell' 'cmdflag' '"echo hi"'"]]}
+ screen:expect { any = [[Executing command: "'fake_shell' 'cmdflag' '"echo hi"'"]] }
else
- screen:expect{any=[[Executing command: "'fake_shell' 'cmdflag' 'echo hi'"]]}
+ screen:expect { any = [[Executing command: "'fake_shell' 'cmdflag' 'echo hi'"]] }
end
feed('<cr>')
end)
@@ -237,94 +247,50 @@ describe('system()', function()
feed(':edit ' .. tempfile .. '<cr>')
- local command_total_time = tonumber(helpers.funcs.split(helpers.funcs.getline(7))[2])
- local command_self_time = tonumber(helpers.funcs.split(helpers.funcs.getline(7))[3])
+ local command_total_time = tonumber(helpers.fn.split(helpers.fn.getline(7))[2])
+ local command_self_time = tonumber(helpers.fn.split(helpers.fn.getline(7))[3])
helpers.neq(nil, command_total_time)
helpers.neq(nil, command_self_time)
end)
it('`yes` interrupted with CTRL-C', function()
- feed(':call system("' .. (is_os('win')
- and 'for /L %I in (1,0,2) do @echo y'
- or 'yes') .. '")<cr>')
+ feed(
+ ':call system("'
+ .. (is_os('win') and 'for /L %I in (1,0,2) do @echo y' or 'yes')
+ .. '")<cr>'
+ )
screen:expect([[
|
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
-]] .. (is_os('win')
- and [[
- :call system("for /L %I in (1,0,2) do @echo y") |]]
- or [[
+ ~ |*12
+]] .. (is_os('win') and [[
+ :call system("for /L %I in (1,0,2) do @echo y") |]] or [[
:call system("yes") |]]))
feed('foo<c-c>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*12
Type :qa and press <Enter> to exit Nvim |
]])
end)
it('`yes` interrupted with mapped CTRL-C', function()
command('nnoremap <C-C> i')
- feed(':call system("' .. (is_os('win')
- and 'for /L %I in (1,0,2) do @echo y'
- or 'yes') .. '")<cr>')
+ feed(
+ ':call system("'
+ .. (is_os('win') and 'for /L %I in (1,0,2) do @echo y' or 'yes')
+ .. '")<cr>'
+ )
screen:expect([[
|
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
-]] .. (is_os('win')
- and [[
- :call system("for /L %I in (1,0,2) do @echo y") |]]
- or [[
+ ~ |*12
+]] .. (is_os('win') and [[
+ :call system("for /L %I in (1,0,2) do @echo y") |]] or [[
:call system("yes") |]]))
feed('foo<c-c>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*12
-- INSERT -- |
]])
end)
@@ -333,17 +299,19 @@ describe('system()', function()
describe('passing no input', function()
it('returns the program output', function()
if is_os('win') then
- eq("echoed\n", eval('system("echo echoed")'))
+ eq('echoed\n', eval('system("echo echoed")'))
else
- eq("echoed", eval('system("printf echoed")'))
+ eq('echoed', eval('system("printf echoed")'))
end
end)
it('to backgrounded command does not crash', function()
-- This is indeterminate, just exercise the codepath. May get E5677.
- feed_command('call system(has("win32") ? "start /b /wait cmd /c echo echoed" : "printf echoed &")')
- local v_errnum = string.match(eval("v:errmsg"), "^E%d*:")
+ feed_command(
+ 'call system(has("win32") ? "start /b /wait cmd /c echo echoed" : "printf echoed &")'
+ )
+ local v_errnum = string.match(eval('v:errmsg'), '^E%d*:')
if v_errnum then
- eq("E5677:", v_errnum)
+ eq('E5677:', v_errnum)
end
assert_alive()
end)
@@ -351,19 +319,19 @@ describe('system()', function()
describe('passing input', function()
it('returns the program output', function()
- eq("input", eval('system("cat -", "input")'))
+ eq('input', eval('system("cat -", "input")'))
end)
it('to backgrounded command does not crash', function()
-- This is indeterminate, just exercise the codepath. May get E5677.
feed_command('call system(has("win32") ? "start /b /wait more" : "cat - &", "input")')
- local v_errnum = string.match(eval("v:errmsg"), "^E%d*:")
+ local v_errnum = string.match(eval('v:errmsg'), '^E%d*:')
if v_errnum then
- eq("E5677:", v_errnum)
+ eq('E5677:', v_errnum)
end
assert_alive()
end)
it('works with an empty string', function()
- eq("test\n", eval('system("echo test", "")'))
+ eq('test\n', eval('system("echo test", "")'))
assert_alive()
end)
end)
@@ -378,7 +346,7 @@ describe('system()', function()
input[#input + 1] = '01234567890ABCDEFabcdef'
end
input = table.concat(input, '\n')
- nvim('set_var', 'input', input)
+ api.nvim_set_var('input', input)
eq(input, eval('system("cat -", g:input)'))
end)
end)
@@ -387,8 +355,7 @@ describe('system()', function()
it('is treated as a buffer id', function()
command("put ='text in buffer 1'")
eq('\ntext in buffer 1\n', eval('system("cat", 1)'))
- eq('Vim(echo):E86: Buffer 42 does not exist',
- exc_exec('echo system("cat", 42)'))
+ eq('Vim(echo):E86: Buffer 42 does not exist', exc_exec('echo system("cat", 42)'))
end)
end)
@@ -399,14 +366,13 @@ describe('system()', function()
after_each(delete_file(fname))
it('replaces NULs by SOH characters', function()
- eq('part1\001part2\001part3\n', eval([[system('"cat" "]]..fname..[["')]]))
+ eq('part1\001part2\001part3\n', eval([[system('"cat" "]] .. fname .. [["')]]))
end)
end)
describe('input passed as List', function()
it('joins List items with linefeed characters', function()
- eq('line1\nline2\nline3',
- eval("system('cat -', ['line1', 'line2', 'line3'])"))
+ eq('line1\nline2\nline3', eval("system('cat -', ['line1', 'line2', 'line3'])"))
end)
-- Notice that NULs are converted to SOH when the data is read back. This
@@ -415,15 +381,19 @@ describe('system()', function()
-- characters(see the following tests with `systemlist()` below)
describe('with linefeed characters inside List items', function()
it('converts linefeed characters to NULs', function()
- eq('l1\001p2\nline2\001a\001b\nl3',
- eval([[system('cat -', ["l1\np2", "line2\na\nb", 'l3'])]]))
+ eq(
+ 'l1\001p2\nline2\001a\001b\nl3',
+ eval([[system('cat -', ["l1\np2", "line2\na\nb", 'l3'])]])
+ )
end)
end)
describe('with leading/trailing whitespace characters on items', function()
it('preserves whitespace, replacing linefeeds by NULs', function()
- eq('line \nline2\001\n\001line3',
- eval([[system('cat -', ['line ', "line2\n", "\nline3"])]]))
+ eq(
+ 'line \nline2\001\n\001line3',
+ eval([[system('cat -', ['line ', "line2\n", "\nline3"])]])
+ )
end)
end)
end)
@@ -431,7 +401,7 @@ describe('system()', function()
it("with a program that doesn't close stdout will exit properly after passing input", function()
local out = eval(string.format("system('%s', 'clip-data')", testprg('streams-test')))
assert(out:sub(0, 5) == 'pid: ', out)
- os_kill(out:match("%d+"))
+ os_kill(out:match('%d+'))
end)
end)
@@ -477,18 +447,7 @@ describe('systemlist()', function()
feed(':call systemlist("echo")<cr>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*12
:call systemlist("echo") |
]])
end)
@@ -497,35 +456,13 @@ describe('systemlist()', function()
feed(':call systemlist("yes | xargs")<cr>')
screen:expect([[
|
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*12
:call systemlist("yes | xargs") |
]])
feed('<c-c>')
screen:expect([[
^ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
- ~ |
+ ~ |*12
Type :qa and press <Enter> to exit Nvim |
]])
end)
@@ -533,7 +470,7 @@ describe('systemlist()', function()
describe('passing string with linefeed characters as input', function()
it('splits the output on linefeed characters', function()
- eq({'abc', 'def', 'ghi'}, eval([[systemlist("cat -", "abc\ndef\nghi")]]))
+ eq({ 'abc', 'def', 'ghi' }, eval([[systemlist("cat -", "abc\ndef\nghi")]]))
end)
end)
@@ -543,7 +480,7 @@ describe('systemlist()', function()
for _ = 1, 0xffff do
input[#input + 1] = '01234567890ABCDEFabcdef'
end
- nvim('set_var', 'input', input)
+ api.nvim_set_var('input', input)
eq(input, eval('systemlist("cat -", g:input)'))
end)
end)
@@ -558,75 +495,77 @@ describe('systemlist()', function()
after_each(delete_file(fname))
it('replaces NULs by newline characters', function()
- eq({'part1\npart2\npart3'}, eval([[systemlist('"cat" "]]..fname..[["')]]))
+ eq({ 'part1\npart2\npart3' }, eval([[systemlist('"cat" "]] .. fname .. [["')]]))
end)
end)
describe('input passed as List', function()
it('joins list items with linefeed characters', function()
- eq({'line1', 'line2', 'line3'},
- eval("systemlist('cat -', ['line1', 'line2', 'line3'])"))
+ eq({ 'line1', 'line2', 'line3' }, eval("systemlist('cat -', ['line1', 'line2', 'line3'])"))
end)
-- Unlike `system()` which uses SOH to represent NULs, with `systemlist()`
-- input and output are the same.
describe('with linefeed characters inside list items', function()
it('converts linefeed characters to NULs', function()
- eq({'l1\np2', 'line2\na\nb', 'l3'},
- eval([[systemlist('cat -', ["l1\np2", "line2\na\nb", 'l3'])]]))
+ eq(
+ { 'l1\np2', 'line2\na\nb', 'l3' },
+ eval([[systemlist('cat -', ["l1\np2", "line2\na\nb", 'l3'])]])
+ )
end)
end)
describe('with leading/trailing whitespace characters on items', function()
it('preserves whitespace, replacing linefeeds by NULs', function()
- eq({'line ', 'line2\n', '\nline3'},
- eval([[systemlist('cat -', ['line ', "line2\n", "\nline3"])]]))
+ eq(
+ { 'line ', 'line2\n', '\nline3' },
+ eval([[systemlist('cat -', ['line ', "line2\n", "\nline3"])]])
+ )
end)
end)
end)
describe('handles empty lines', function()
it('in the middle', function()
- eq({'line one','','line two'}, eval("systemlist('cat',['line one','','line two'])"))
+ eq({ 'line one', '', 'line two' }, eval("systemlist('cat',['line one','','line two'])"))
end)
it('in the beginning', function()
- eq({'','line one','line two'}, eval("systemlist('cat',['','line one','line two'])"))
+ eq({ '', 'line one', 'line two' }, eval("systemlist('cat',['','line one','line two'])"))
end)
end)
describe('when keepempty option is', function()
it('0, ignores trailing newline', function()
- eq({'aa','bb'}, eval("systemlist('cat',['aa','bb'],0)"))
- eq({'aa','bb'}, eval("systemlist('cat',['aa','bb',''],0)"))
+ eq({ 'aa', 'bb' }, eval("systemlist('cat',['aa','bb'],0)"))
+ eq({ 'aa', 'bb' }, eval("systemlist('cat',['aa','bb',''],0)"))
end)
it('1, preserves trailing newline', function()
- eq({'aa','bb'}, eval("systemlist('cat',['aa','bb'],1)"))
- eq({'aa','bb',''}, eval("systemlist('cat',['aa','bb',''],2)"))
+ eq({ 'aa', 'bb' }, eval("systemlist('cat',['aa','bb'],1)"))
+ eq({ 'aa', 'bb', '' }, eval("systemlist('cat',['aa','bb',''],2)"))
end)
end)
it("with a program that doesn't close stdout will exit properly after passing input", function()
local out = eval(string.format("systemlist('%s', 'clip-data')", testprg('streams-test')))
assert(out[1]:sub(0, 5) == 'pid: ', out)
- os_kill(out[1]:match("%d+"))
+ os_kill(out[1]:match('%d+'))
end)
it('powershell w/ UTF-8 text #13713', function()
if not helpers.has_powershell() then
- pending("powershell not found", function() end)
+ pending('powershell not found', function() end)
return
end
helpers.set_shell_powershell()
- eq({is_os('win') and 'ã‚\r' or 'ã‚'}, eval([[systemlist('Write-Output ã‚')]]))
+ eq({ is_os('win') and 'ã‚\r' or 'ã‚' }, eval([[systemlist('Write-Output ã‚')]]))
-- Sanity test w/ default encoding
-- * on Windows, expected to default to Western European enc
-- * on Linux, expected to default to UTF8
command([[let &shellcmdflag = '-NoLogo -NoProfile -ExecutionPolicy RemoteSigned -Command ']])
- eq({is_os('win') and '?\r' or 'ã‚'}, eval([[systemlist('Write-Output ã‚')]]))
+ eq({ is_os('win') and '?\r' or 'ã‚' }, eval([[systemlist('Write-Output ã‚')]]))
end)
-
end)
describe('shell :!', function()
@@ -643,13 +582,13 @@ describe('shell :!', function()
2]])
if is_os('win') then
feed(':4verbose %!sort /R<cr>')
- screen:expect{
- any=[[Executing command: .?& { Get%-Content .* | & sort /R } 2>&1 | %%{ "$_" } | Out%-File .*; exit $LastExitCode"]]
+ screen:expect {
+ any = [[Executing command: .?& { Get%-Content .* | & sort /R } 2>&1 | %%{ "$_" } | Out%-File .*; exit $LastExitCode"]],
}
else
feed(':4verbose %!sort -r<cr>')
- screen:expect{
- any=[[Executing command: .?& { Get%-Content .* | & sort %-r } 2>&1 | %%{ "$_" } | Out%-File .*; exit $LastExitCode"]]
+ screen:expect {
+ any = [[Executing command: .?& { Get%-Content .* | & sort %-r } 2>&1 | %%{ "$_" } | Out%-File .*; exit $LastExitCode"]],
}
end
feed('<CR>')
@@ -673,20 +612,19 @@ describe('shell :!', function()
2]])
feed(':4verbose %w !sort<cr>')
if is_os('win') then
- screen:expect{
- any=[[Executing command: .?sort %< .*]]
+ screen:expect {
+ any = [[Executing command: .?sort %< .*]],
}
else
- screen:expect{
- any=[[Executing command: .?%(sort%) %< .*]]
-
+ screen:expect {
+ any = [[Executing command: .?%(sort%) %< .*]],
}
end
feed('<CR>')
helpers.set_shell_powershell(true)
feed(':4verbose %w !sort<cr>')
- screen:expect{
- any=[[Executing command: .?& { Get%-Content .* | & sort }]]
+ screen:expect {
+ any = [[Executing command: .?& { Get%-Content .* | & sort }]],
}
feed('<CR>')
helpers.expect_exit(command, 'qall!')
diff --git a/test/functional/vimscript/timer_spec.lua b/test/functional/vimscript/timer_spec.lua
index a58cd6ae7f..046d451888 100644
--- a/test/functional/vimscript/timer_spec.lua
+++ b/test/functional/vimscript/timer_spec.lua
@@ -1,10 +1,10 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local feed, eq, eval, ok = helpers.feed, helpers.eq, helpers.eval, helpers.ok
-local source, nvim_async, run = helpers.source, helpers.nvim_async, helpers.run
-local clear, command, funcs = helpers.clear, helpers.command, helpers.funcs
+local source, async_meths, run = helpers.source, helpers.async_meths, helpers.run
+local clear, command, fn = helpers.clear, helpers.command, helpers.fn
local exc_exec = helpers.exc_exec
-local curbufmeths = helpers.curbufmeths
+local api = helpers.api
local load_adjust = helpers.load_adjust
local retry = helpers.retry
@@ -22,20 +22,20 @@ describe('timers', function()
it('works one-shot', function()
eq(0, eval("[timer_start(10, 'MyHandler'), g:val][1]"))
run(nil, nil, nil, load_adjust(100))
- eq(1,eval("g:val"))
+ eq(1, eval('g:val'))
end)
it('works one-shot when repeat=0', function()
eq(0, eval("[timer_start(10, 'MyHandler', {'repeat': 0}), g:val][1]"))
run(nil, nil, nil, load_adjust(100))
- eq(1, eval("g:val"))
+ eq(1, eval('g:val'))
end)
it('works with repeat two', function()
eq(0, eval("[timer_start(10, 'MyHandler', {'repeat': 2}), g:val][1]"))
run(nil, nil, nil, load_adjust(20))
retry(nil, load_adjust(300), function()
- eq(2, eval("g:val"))
+ eq(2, eval('g:val'))
end)
end)
@@ -52,12 +52,12 @@ describe('timers', function()
endfunc
]])
eval("timer_start(10, 'MyHandler', {'repeat': -1})")
- nvim_async("command", "sleep 10")
- eq(-1, eval("g:val")) -- timer did nothing yet.
- nvim_async("command", "let g:val = 0")
+ async_meths.nvim_command('sleep 10')
+ eq(-1, eval('g:val')) -- timer did nothing yet.
+ async_meths.nvim_command('let g:val = 0')
run(nil, nil, nil, load_adjust(20))
retry(nil, nil, function()
- eq(2, eval("g:val"))
+ eq(2, eval('g:val'))
end)
end)
@@ -65,52 +65,53 @@ describe('timers', function()
-- timer_start does still not invoke the callback immediately
eq(0, eval("[timer_start(0, 'MyHandler', {'repeat': 1000}), g:val][1]"))
retry(nil, nil, function()
- eq(1000, eval("g:val"))
+ eq(1000, eval('g:val'))
end)
end)
it('can be started during sleep', function()
- nvim_async("command", "sleep 10")
+ async_meths.nvim_command('sleep 10')
-- this also tests that remote requests works during sleep
eq(0, eval("[timer_start(10, 'MyHandler', {'repeat': 2}), g:val][1]"))
run(nil, nil, nil, load_adjust(20))
- retry(nil, load_adjust(300), function() eq(2,eval("g:val")) end)
+ retry(nil, load_adjust(300), function()
+ eq(2, eval('g:val'))
+ end)
end)
it('are paused when event processing is disabled', function()
command("call timer_start(5, 'MyHandler', {'repeat': -1})")
run(nil, nil, nil, load_adjust(10))
- local count = eval("g:val")
+ local count = eval('g:val')
-- shows two line error message and thus invokes the return prompt.
-- if we start to allow event processing here, we need to change this test.
feed(':throw "fatal error"<CR>')
run(nil, nil, nil, load_adjust(30))
- feed("<cr>")
- local diff = eval("g:val") - count
- assert(0 <= diff and diff <= 4,
- 'expected (0 <= diff <= 4), got: '..tostring(diff))
+ feed('<cr>')
+ local diff = eval('g:val') - count
+ assert(0 <= diff and diff <= 4, 'expected (0 <= diff <= 4), got: ' .. tostring(diff))
end)
it('are triggered in blocking getchar() call', function()
command("call timer_start(5, 'MyHandler', {'repeat': -1})")
- nvim_async("command", "let g:val = 0 | let g:c = getchar()")
+ async_meths.nvim_command('let g:val = 0 | let g:c = getchar()')
retry(nil, nil, function()
- local val = eval("g:val")
+ local val = eval('g:val')
ok(val >= 2, '>= 2', tostring(val))
- eq(0, eval("getchar(1)"))
+ eq(0, eval('getchar(1)'))
end)
- feed("c")
- eq(99, eval("g:c"))
+ feed('c')
+ eq(99, eval('g:c'))
end)
it('can invoke redraw in blocking getchar() call', function()
local screen = Screen.new(40, 6)
screen:attach()
screen:set_default_attr_ids({
- [1] = {bold=true, foreground=Screen.colors.Blue},
+ [1] = { bold = true, foreground = Screen.colors.Blue },
})
- curbufmeths.set_lines(0, -1, true, {"ITEM 1", "ITEM 2"})
+ api.nvim_buf_set_lines(0, 0, -1, true, { 'ITEM 1', 'ITEM 2' })
source([[
let g:cont = 0
func! AddItem(timer)
@@ -127,48 +128,49 @@ describe('timers', function()
redraw
endfunc
]])
- nvim_async("command", "let g:c2 = getchar()")
- nvim_async("command", "call timer_start("..load_adjust(100)..", 'AddItem', {'repeat': -1})")
+ async_meths.nvim_command('let g:c2 = getchar()')
+ async_meths.nvim_command(
+ 'call timer_start(' .. load_adjust(100) .. ", 'AddItem', {'repeat': -1})"
+ )
screen:expect([[
^ITEM 1 |
ITEM 2 |
- {1:~ }|
- {1:~ }|
- {1:~ }|
+ {1:~ }|*3
|
]])
- nvim_async("command", "let g:cont = 1")
+ async_meths.nvim_command('let g:cont = 1')
screen:expect([[
^ITEM 1 |
ITEM 2 |
ITEM 3 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
]])
- feed("3")
- eq(51, eval("g:c2"))
- screen:expect{grid=[[
+ feed('3')
+ eq(51, eval('g:c2'))
+ screen:expect {
+ grid = [[
^ITEM 1 |
ITEM 2 |
ITEM 3 |
- {1:~ }|
- {1:~ }|
+ {1:~ }|*2
|
- ]], unchanged=true}
+ ]],
+ unchanged = true,
+ }
end)
it('can be stopped', function()
local t_init_val = eval("[timer_start(5, 'MyHandler', {'repeat': -1}), g:val]")
eq(0, t_init_val[2])
run(nil, nil, nil, load_adjust(30))
- funcs.timer_stop(t_init_val[1])
- local count = eval("g:val")
+ fn.timer_stop(t_init_val[1])
+ local count = eval('g:val')
run(nil, load_adjust(300), nil, load_adjust(30))
- local count2 = eval("g:val")
+ local count2 = eval('g:val')
-- when count is eval:ed after timer_stop this should be non-racy
eq(count, count2)
end)
@@ -184,10 +186,10 @@ describe('timers', function()
endif
endfunc
]])
- eq(0, eval("g:val"))
+ eq(0, eval('g:val'))
command("call timer_start(10, 'MyHandler', {'repeat': -1})")
retry(nil, nil, function()
- eq(3, eval("g:val"))
+ eq(3, eval('g:val'))
end)
end)
@@ -201,8 +203,8 @@ describe('timers', function()
command("call timer_start(2, 'MyHandler', {'repeat': 3})")
command("call timer_start(4, 'MyHandler2', {'repeat': 2})")
retry(nil, nil, function()
- eq(3, eval("g:val"))
- eq(2, eval("g:val2"))
+ eq(3, eval('g:val'))
+ eq(2, eval('g:val2'))
end)
end)
@@ -218,15 +220,14 @@ describe('timers', function()
command("call timer_start(5, 'MyHandler', {'repeat': 1})")
run(nil, nil, nil, load_adjust(20))
retry(nil, load_adjust(150), function()
- eq(1, eval("g:val"))
+ eq(1, eval('g:val'))
end)
end)
-
it("doesn't mess up the cmdline", function()
local screen = Screen.new(40, 6)
screen:attach()
- screen:set_default_attr_ids( {[0] = {bold=true, foreground=255}} )
+ screen:set_default_attr_ids({ [0] = { bold = true, foreground = 255 } })
source([[
let g:val = 0
func! MyHandler(timer)
@@ -241,13 +242,10 @@ describe('timers', function()
endfunc
]])
command("call timer_start(100, 'MyHandler', {'repeat': -1})")
- feed(":good")
+ feed(':good')
screen:expect([[
|
- {0:~ }|
- {0:~ }|
- {0:~ }|
- {0:~ }|
+ {0:~ }|*4
:good^ |
]])
command('let g:val = 1')
@@ -262,7 +260,7 @@ describe('timers', function()
call execute('echo ''execute() should be disallowed''', '')
endfunction
]]
- eq("Vim(call):E48: Not allowed in sandbox", exc_exec("sandbox call timer_start(0, 'Scary')"))
+ eq('Vim(call):E48: Not allowed in sandbox', exc_exec("sandbox call timer_start(0, 'Scary')"))
end)
it('can be triggered after an empty string <expr> mapping #17257', function()
@@ -270,6 +268,6 @@ describe('timers', function()
screen:attach()
command([=[imap <expr> <F2> [timer_start(0, { _ -> execute("throw 'x'", "") }), ''][-1]]=])
feed('i<F2>')
- screen:expect({any='E605: Exception not caught: x'})
+ screen:expect({ any = 'E605: Exception not caught: x' })
end)
end)
diff --git a/test/functional/vimscript/uniq_spec.lua b/test/functional/vimscript/uniq_spec.lua
index 43ad4a7640..8fd4004be4 100644
--- a/test/functional/vimscript/uniq_spec.lua
+++ b/test/functional/vimscript/uniq_spec.lua
@@ -10,8 +10,10 @@ before_each(clear)
describe('uniq()', function()
it('errors out when processing special values', function()
- eq('Vim(call):E362: Using a boolean value as a Float',
- exc_exec('call uniq([v:true, v:false], "f")'))
+ eq(
+ 'Vim(call):E362: Using a boolean value as a Float',
+ exc_exec('call uniq([v:true, v:false], "f")')
+ )
end)
it('can yield E882 and stop filtering after that', function()
@@ -23,7 +25,9 @@ describe('uniq()', function()
return (a:a > a:b) - (a:a < a:b)
endfunction
]])
- eq('Vim(let):E745: Using a List as a Number',
- pcall_err(command, 'let fl = uniq([0, 0, [], 1, 1], "Cmp")'))
+ eq(
+ 'Vim(let):E745: Using a List as a Number',
+ pcall_err(command, 'let fl = uniq([0, 0, [], 1, 1], "Cmp")')
+ )
end)
end)
diff --git a/test/functional/vimscript/vvar_event_spec.lua b/test/functional/vimscript/vvar_event_spec.lua
index eec8aa917a..68eda05363 100644
--- a/test/functional/vimscript/vvar_event_spec.lua
+++ b/test/functional/vimscript/vvar_event_spec.lua
@@ -12,4 +12,3 @@ describe('v:event', function()
eq(false, pcall(command, 'let v:event.mykey = {}'))
end)
end)
-
diff --git a/test/functional/vimscript/wait_spec.lua b/test/functional/vimscript/wait_spec.lua
index ee95e02a7f..50cdb2cfb4 100644
--- a/test/functional/vimscript/wait_spec.lua
+++ b/test/functional/vimscript/wait_spec.lua
@@ -7,14 +7,14 @@ local eq = helpers.eq
local feed = helpers.feed
local feed_command = helpers.feed_command
local next_msg = helpers.next_msg
-local nvim = helpers.nvim
+local api = helpers.api
local source = helpers.source
local pcall_err = helpers.pcall_err
before_each(function()
clear()
- local channel = nvim('get_api_info')[1]
- nvim('set_var', 'channel', channel)
+ local channel = api.nvim_get_chan_info(0).id
+ api.nvim_set_var('channel', channel)
end)
describe('wait()', function()
@@ -36,11 +36,12 @@ describe('wait()', function()
end)
it('returns -2 when interrupted', function()
- feed_command('call rpcnotify(g:channel, "ready") | '..
- 'call rpcnotify(g:channel, "wait", wait(-1, 0))')
- eq({'notification', 'ready', {}}, next_msg())
+ feed_command(
+ 'call rpcnotify(g:channel, "ready") | ' .. 'call rpcnotify(g:channel, "wait", wait(-1, 0))'
+ )
+ eq({ 'notification', 'ready', {} }, next_msg())
feed('<c-c>')
- eq({'notification', 'wait', {-2}}, next_msg())
+ eq({ 'notification', 'wait', { -2 } }, next_msg())
end)
it('returns -3 on error', function()
@@ -60,13 +61,13 @@ describe('wait()', function()
-- XXX: flaky (#11137)
helpers.retry(nil, nil, function()
- nvim('set_var', 'counter', 0)
+ api.nvim_set_var('counter', 0)
eq(-1, call('wait', 20, 'Count() >= 5', 99999))
end)
- nvim('set_var', 'counter', 0)
+ api.nvim_set_var('counter', 0)
eq(0, call('wait', 10000, 'Count() >= 5', 5))
- eq(5, nvim('get_var', 'counter'))
+ eq(5, api.nvim_get_var('counter'))
end)
it('validates args', function()
diff --git a/test/functional/vimscript/writefile_spec.lua b/test/functional/vimscript/writefile_spec.lua
index 88c19bd839..051e3794a3 100644
--- a/test/functional/vimscript/writefile_spec.lua
+++ b/test/functional/vimscript/writefile_spec.lua
@@ -1,11 +1,10 @@
local helpers = require('test.functional.helpers')(after_each)
-local luv = require('luv')
local mkdir = helpers.mkdir
local clear = helpers.clear
local eq = helpers.eq
-local funcs = helpers.funcs
-local meths = helpers.meths
+local fn = helpers.fn
+local api = helpers.api
local exc_exec = helpers.exc_exec
local read_file = helpers.read_file
local write_file = helpers.write_file
@@ -28,149 +27,175 @@ end)
after_each(function()
os.remove(fname)
os.remove(dfname)
- luv.fs_rmdir(ddname)
- luv.fs_rmdir(dname)
+ vim.uv.fs_rmdir(ddname)
+ vim.uv.fs_rmdir(dname)
end)
describe('writefile()', function()
it('writes empty list to a file', function()
eq(nil, read_file(fname))
- eq(0, funcs.writefile({}, fname))
+ eq(0, fn.writefile({}, fname))
eq('', read_file(fname))
os.remove(fname)
eq(nil, read_file(fname))
- eq(0, funcs.writefile({}, fname, 'b'))
+ eq(0, fn.writefile({}, fname, 'b'))
eq('', read_file(fname))
os.remove(fname)
eq(nil, read_file(fname))
- eq(0, funcs.writefile({}, fname, 'ab'))
+ eq(0, fn.writefile({}, fname, 'ab'))
eq('', read_file(fname))
os.remove(fname)
eq(nil, read_file(fname))
- eq(0, funcs.writefile({}, fname, 'a'))
+ eq(0, fn.writefile({}, fname, 'a'))
eq('', read_file(fname))
end)
it('writes list with an empty string to a file', function()
- eq(0, exc_exec(
- ('call writefile([$XXX_NONEXISTENT_VAR_XXX], "%s", "b")'):format(
- fname)))
+ eq(0, exc_exec(('call writefile([$XXX_NONEXISTENT_VAR_XXX], "%s", "b")'):format(fname)))
eq('', read_file(fname))
- eq(0, exc_exec(('call writefile([$XXX_NONEXISTENT_VAR_XXX], "%s")'):format(
- fname)))
+ eq(0, exc_exec(('call writefile([$XXX_NONEXISTENT_VAR_XXX], "%s")'):format(fname)))
eq('\n', read_file(fname))
end)
it('writes list with a null string to a file', function()
- eq(0, exc_exec(
- ('call writefile([v:_null_string], "%s", "b")'):format(
- fname)))
+ eq(0, exc_exec(('call writefile([v:_null_string], "%s", "b")'):format(fname)))
eq('', read_file(fname))
- eq(0, exc_exec(('call writefile([v:_null_string], "%s")'):format(
- fname)))
+ eq(0, exc_exec(('call writefile([v:_null_string], "%s")'):format(fname)))
eq('\n', read_file(fname))
end)
it('appends to a file', function()
eq(nil, read_file(fname))
- eq(0, funcs.writefile({'abc', 'def', 'ghi'}, fname))
+ eq(0, fn.writefile({ 'abc', 'def', 'ghi' }, fname))
eq('abc\ndef\nghi\n', read_file(fname))
- eq(0, funcs.writefile({'jkl'}, fname, 'a'))
+ eq(0, fn.writefile({ 'jkl' }, fname, 'a'))
eq('abc\ndef\nghi\njkl\n', read_file(fname))
os.remove(fname)
eq(nil, read_file(fname))
- eq(0, funcs.writefile({'abc', 'def', 'ghi'}, fname, 'b'))
+ eq(0, fn.writefile({ 'abc', 'def', 'ghi' }, fname, 'b'))
eq('abc\ndef\nghi', read_file(fname))
- eq(0, funcs.writefile({'jkl'}, fname, 'ab'))
+ eq(0, fn.writefile({ 'jkl' }, fname, 'ab'))
eq('abc\ndef\nghijkl', read_file(fname))
end)
it('correctly treats NLs', function()
- eq(0, funcs.writefile({'\na\nb\n'}, fname, 'b'))
+ eq(0, fn.writefile({ '\na\nb\n' }, fname, 'b'))
eq('\0a\0b\0', read_file(fname))
- eq(0, funcs.writefile({'a\n\n\nb'}, fname, 'b'))
+ eq(0, fn.writefile({ 'a\n\n\nb' }, fname, 'b'))
eq('a\0\0\0b', read_file(fname))
end)
it('writes with s and S', function()
- eq(0, funcs.writefile({'\na\nb\n'}, fname, 'bs'))
+ eq(0, fn.writefile({ '\na\nb\n' }, fname, 'bs'))
eq('\0a\0b\0', read_file(fname))
- eq(0, funcs.writefile({'a\n\n\nb'}, fname, 'bS'))
+ eq(0, fn.writefile({ 'a\n\n\nb' }, fname, 'bS'))
eq('a\0\0\0b', read_file(fname))
end)
it('correctly overwrites file', function()
- eq(0, funcs.writefile({'\na\nb\n'}, fname, 'b'))
+ eq(0, fn.writefile({ '\na\nb\n' }, fname, 'b'))
eq('\0a\0b\0', read_file(fname))
- eq(0, funcs.writefile({'a\n'}, fname, 'b'))
+ eq(0, fn.writefile({ 'a\n' }, fname, 'b'))
eq('a\0', read_file(fname))
end)
it('shows correct file name when supplied numbers', function()
- meths.set_current_dir(dname)
- eq('Vim(call):E482: Can\'t open file 2 for writing: illegal operation on a directory',
- pcall_err(command, ('call writefile([42], %s)'):format(ddname_tail)))
+ api.nvim_set_current_dir(dname)
+ eq(
+ "Vim(call):E482: Can't open file 2 for writing: illegal operation on a directory",
+ pcall_err(command, ('call writefile([42], %s)'):format(ddname_tail))
+ )
end)
it('writefile(..., "p") creates missing parent directories', function()
os.remove(dname)
eq(nil, read_file(dfname))
- eq(0, funcs.writefile({'abc', 'def', 'ghi'}, dfname, 'p'))
+ eq(0, fn.writefile({ 'abc', 'def', 'ghi' }, dfname, 'p'))
eq('abc\ndef\nghi\n', read_file(dfname))
os.remove(dfname)
os.remove(dname)
eq(nil, read_file(dfname))
- eq(0, funcs.writefile({'\na\nb\n'}, dfname, 'pb'))
+ eq(0, fn.writefile({ '\na\nb\n' }, dfname, 'pb'))
eq('\0a\0b\0', read_file(dfname))
os.remove(dfname)
os.remove(dname)
- eq('Vim(call):E32: No file name',
- pcall_err(command, ('call writefile([], "%s", "p")'):format(dfname .. '.d/')))
- eq(('Vim(call):E482: Can\'t open file ./ for writing: illegal operation on a directory'),
- pcall_err(command, 'call writefile([], "./", "p")'))
- eq(('Vim(call):E482: Can\'t open file . for writing: illegal operation on a directory'),
- pcall_err(command, 'call writefile([], ".", "p")'))
+ eq(
+ 'Vim(call):E32: No file name',
+ pcall_err(command, ('call writefile([], "%s", "p")'):format(dfname .. '.d/'))
+ )
+ eq(
+ "Vim(call):E482: Can't open file ./ for writing: illegal operation on a directory",
+ pcall_err(command, 'call writefile([], "./", "p")')
+ )
+ eq(
+ "Vim(call):E482: Can't open file . for writing: illegal operation on a directory",
+ pcall_err(command, 'call writefile([], ".", "p")')
+ )
end)
it('errors out with invalid arguments', function()
write_file(fname, 'TEST')
- eq('Vim(call):E119: Not enough arguments for function: writefile',
- pcall_err(command, 'call writefile()'))
- eq('Vim(call):E119: Not enough arguments for function: writefile',
- pcall_err(command, 'call writefile([])'))
- eq('Vim(call):E118: Too many arguments for function: writefile',
- pcall_err(command, ('call writefile([], "%s", "b", 1)'):format(fname)))
- for _, arg in ipairs({'0', '0.0', 'function("tr")', '{}', '"test"'}) do
- eq('Vim(call):E475: Invalid argument: writefile() first argument must be a List or a Blob',
- pcall_err(command, ('call writefile(%s, "%s", "b")'):format(arg, fname)))
+ eq(
+ 'Vim(call):E119: Not enough arguments for function: writefile',
+ pcall_err(command, 'call writefile()')
+ )
+ eq(
+ 'Vim(call):E119: Not enough arguments for function: writefile',
+ pcall_err(command, 'call writefile([])')
+ )
+ eq(
+ 'Vim(call):E118: Too many arguments for function: writefile',
+ pcall_err(command, ('call writefile([], "%s", "b", 1)'):format(fname))
+ )
+ for _, arg in ipairs({ '0', '0.0', 'function("tr")', '{}', '"test"' }) do
+ eq(
+ 'Vim(call):E475: Invalid argument: writefile() first argument must be a List or a Blob',
+ pcall_err(command, ('call writefile(%s, "%s", "b")'):format(arg, fname))
+ )
end
- for _, args in ipairs({'[], %s, "b"', '[], "' .. fname .. '", %s'}) do
- eq('Vim(call):E730: Using a List as a String',
- pcall_err(command, ('call writefile(%s)'):format(args:format('[]'))))
- eq('Vim(call):E731: Using a Dictionary as a String',
- pcall_err(command, ('call writefile(%s)'):format(args:format('{}'))))
- eq('Vim(call):E729: Using a Funcref as a String',
- pcall_err(command, ('call writefile(%s)'):format(args:format('function("tr")'))))
+ for _, args in ipairs({ '[], %s, "b"', '[], "' .. fname .. '", %s' }) do
+ eq(
+ 'Vim(call):E730: Using a List as a String',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('[]')))
+ )
+ eq(
+ 'Vim(call):E731: Using a Dictionary as a String',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('{}')))
+ )
+ eq(
+ 'Vim(call):E729: Using a Funcref as a String',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('function("tr")')))
+ )
end
- eq('Vim(call):E5060: Unknown flag: «»',
- pcall_err(command, ('call writefile([], "%s", "bs«»")'):format(fname)))
+ eq(
+ 'Vim(call):E5060: Unknown flag: «»',
+ pcall_err(command, ('call writefile([], "%s", "bs«»")'):format(fname))
+ )
eq('TEST', read_file(fname))
end)
it('does not write to file if error in list', function()
local args = '["tset"] + repeat([%s], 3), "' .. fname .. '"'
- eq('Vim(call):E805: Expected a Number or a String, Float found',
- pcall_err(command, ('call writefile(%s)'):format(args:format('0.0'))))
+ eq(
+ 'Vim(call):E805: Expected a Number or a String, Float found',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('0.0')))
+ )
eq(nil, read_file(fname))
write_file(fname, 'TEST')
- eq('Vim(call):E745: Expected a Number or a String, List found',
- pcall_err(command, ('call writefile(%s)'):format(args:format('[]'))))
+ eq(
+ 'Vim(call):E745: Expected a Number or a String, List found',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('[]')))
+ )
eq('TEST', read_file(fname))
- eq('Vim(call):E728: Expected a Number or a String, Dictionary found',
- pcall_err(command, ('call writefile(%s)'):format(args:format('{}'))))
+ eq(
+ 'Vim(call):E728: Expected a Number or a String, Dictionary found',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('{}')))
+ )
eq('TEST', read_file(fname))
- eq('Vim(call):E703: Expected a Number or a String, Funcref found',
- pcall_err(command, ('call writefile(%s)'):format(args:format('function("tr")'))))
+ eq(
+ 'Vim(call):E703: Expected a Number or a String, Funcref found',
+ pcall_err(command, ('call writefile(%s)'):format(args:format('function("tr")')))
+ )
eq('TEST', read_file(fname))
end)
end)
diff --git a/test/helpers.lua b/test/helpers.lua
index f9405c011d..3d53aa3be9 100644
--- a/test/helpers.lua
+++ b/test/helpers.lua
@@ -1,31 +1,31 @@
-local shared = vim
-local assert = require('luassert')
+local luaassert = require('luassert')
local busted = require('busted')
-local luv = require('luv')
+local uv = vim.uv
local Paths = require('test.cmakeconfig.paths')
-assert:set_parameter('TableFormatLevel', 100)
+luaassert:set_parameter('TableFormatLevel', 100)
local quote_me = '[^.%w%+%-%@%_%/]' -- complement (needn't quote)
+
+--- @param str string
+--- @return string
local function shell_quote(str)
if string.find(str, quote_me) or str == '' then
return '"' .. str:gsub('[$%%"\\]', '\\%0') .. '"'
- else
- return str
end
+ return str
end
--- @class test.helpers
local module = {
- REMOVE_THIS = {},
+ paths = Paths,
}
--- @param p string
--- @return string
local function relpath(p)
p = vim.fs.normalize(p)
- local cwd = luv.cwd()
- return p:gsub("^" .. cwd)
+ return (p:gsub('^' .. uv.cwd, ''))
end
--- @param path string
@@ -34,84 +34,73 @@ function module.isdir(path)
if not path then
return false
end
- local stat = luv.fs_stat(path)
+ local stat = uv.fs_stat(path)
if not stat then
return false
end
return stat.type == 'directory'
end
---- @param path string
---- @return boolean
-function module.isfile(path)
- if not path then
- return false
- end
- local stat = luv.fs_stat(path)
- if not stat then
- return false
- end
- return stat.type == 'file'
-end
-
+--- @param ... string|string[]
--- @return string
function module.argss_to_cmd(...)
- local cmd = ''
+ local cmd = {} --- @type string[]
for i = 1, select('#', ...) do
local arg = select(i, ...)
if type(arg) == 'string' then
- cmd = cmd .. ' ' ..shell_quote(arg)
+ cmd[#cmd + 1] = shell_quote(arg)
else
+ --- @cast arg string[]
for _, subarg in ipairs(arg) do
- cmd = cmd .. ' ' .. shell_quote(subarg)
+ cmd[#cmd + 1] = shell_quote(subarg)
end
end
end
- return cmd
+ return table.concat(cmd, ' ')
end
function module.popen_r(...)
return io.popen(module.argss_to_cmd(...), 'r')
end
--- sleeps the test runner (_not_ the nvim instance)
-function module.sleep(ms)
- luv.sleep(ms)
-end
-
--- Calls fn() until it succeeds, up to `max` times or until `max_ms`
--- milliseconds have passed.
+--- Calls fn() until it succeeds, up to `max` times or until `max_ms`
+--- milliseconds have passed.
+--- @param max integer?
+--- @param max_ms integer?
+--- @param fn function
+--- @return any
function module.retry(max, max_ms, fn)
- assert(max == nil or max > 0)
- assert(max_ms == nil or max_ms > 0)
+ luaassert(max == nil or max > 0)
+ luaassert(max_ms == nil or max_ms > 0)
local tries = 1
local timeout = (max_ms and max_ms or 10000)
- local start_time = luv.now()
+ local start_time = uv.now()
while true do
+ --- @type boolean, any
local status, result = pcall(fn)
if status then
return result
end
- luv.update_time() -- Update cached value of luv.now() (libuv: uv_now()).
- if (max and tries >= max) or (luv.now() - start_time > timeout) then
- busted.fail(string.format("retry() attempts: %d\n%s", tries, tostring(result)), 2)
+ uv.update_time() -- Update cached value of luv.now() (libuv: uv_now()).
+ if (max and tries >= max) or (uv.now() - start_time > timeout) then
+ busted.fail(string.format('retry() attempts: %d\n%s', tries, tostring(result)), 2)
end
tries = tries + 1
- luv.sleep(20) -- Avoid hot loop...
+ uv.sleep(20) -- Avoid hot loop...
end
end
local check_logs_useless_lines = {
- ['Warning: noted but unhandled ioctl']=1,
- ['could cause spurious value errors to appear']=2,
- ['See README_MISSING_SYSCALL_OR_IOCTL for guidance']=3,
+ ['Warning: noted but unhandled ioctl'] = 1,
+ ['could cause spurious value errors to appear'] = 2,
+ ['See README_MISSING_SYSCALL_OR_IOCTL for guidance'] = 3,
}
function module.eq(expected, actual, context)
- return assert.are.same(expected, actual, context)
+ return luaassert.are.same(expected, actual, context)
end
function module.neq(expected, actual, context)
- return assert.are_not.same(expected, actual, context)
+ return luaassert.are_not.same(expected, actual, context)
end
--- Asserts that `cond` is true, or prints a message.
@@ -120,20 +109,26 @@ end
--- @param expected (any) description of expected result
--- @param actual (any) description of actual result
function module.ok(cond, expected, actual)
- assert((not expected and not actual) or (expected and actual), 'if "expected" is given, "actual" is also required')
+ luaassert(
+ (not expected and not actual) or (expected and actual),
+ 'if "expected" is given, "actual" is also required'
+ )
local msg = expected and ('expected %s, got: %s'):format(expected, tostring(actual)) or nil
- return assert(cond, msg)
+ return luaassert(cond, msg)
end
local function epicfail(state, arguments, _)
state.failure_message = arguments[1]
return false
end
-assert:register("assertion", "epicfail", epicfail)
+luaassert:register('assertion', 'epicfail', epicfail)
function module.fail(msg)
- return assert.epicfail(msg)
+ return luaassert.epicfail(msg)
end
+--- @param pat string
+--- @param actual string
+--- @return boolean
function module.matches(pat, actual)
if nil ~= string.match(actual, pat) then
return true
@@ -146,37 +141,55 @@ end
--- Retries for 1 second in case of filesystem delay.
---
---@param pat (string) Lua pattern to match lines in the log file
----@param logfile (string) Full path to log file (default=$NVIM_LOG_FILE)
----@param nrlines (number) Search up to this many log lines
----@param inverse (boolean) Assert that the pattern does NOT match.
+---@param logfile? (string) Full path to log file (default=$NVIM_LOG_FILE)
+---@param nrlines? (number) Search up to this many log lines
+---@param inverse? (boolean) Assert that the pattern does NOT match.
function module.assert_log(pat, logfile, nrlines, inverse)
logfile = logfile or os.getenv('NVIM_LOG_FILE') or '.nvimlog'
- assert(logfile ~= nil, 'no logfile')
+ luaassert(logfile ~= nil, 'no logfile')
nrlines = nrlines or 10
inverse = inverse or false
module.retry(nil, 1000, function()
local lines = module.read_file_list(logfile, -nrlines) or {}
- local msg = string.format('Pattern %q %sfound in log (last %d lines): %s:\n%s',
- pat, (inverse and '' or 'not '), nrlines, logfile, ' '..table.concat(lines, '\n '))
- for _,line in ipairs(lines) do
+ local msg = string.format(
+ 'Pattern %q %sfound in log (last %d lines): %s:\n%s',
+ pat,
+ (inverse and '' or 'not '),
+ nrlines,
+ logfile,
+ ' ' .. table.concat(lines, '\n ')
+ )
+ for _, line in ipairs(lines) do
if line:match(pat) then
- if inverse then error(msg) else return end
+ if inverse then
+ error(msg)
+ else
+ return
+ end
end
end
- if not inverse then error(msg) end
+ if not inverse then
+ error(msg)
+ end
end)
end
--- Asserts that `pat` does NOT match any line in the tail of `logfile`.
---
--- @see assert_log
+--- @param pat (string) Lua pattern to match lines in the log file
+--- @param logfile? (string) Full path to log file (default=$NVIM_LOG_FILE)
+--- @param nrlines? (number) Search up to this many log lines
function module.assert_nolog(pat, logfile, nrlines)
return module.assert_log(pat, logfile, nrlines, true)
end
+--- @param fn fun(...): any
+--- @param ... any
+--- @return boolean, any
function module.pcall(fn, ...)
- assert(type(fn) == 'function')
+ luaassert(type(fn) == 'function')
local status, rv = pcall(fn, ...)
if status then
return status, rv
@@ -186,9 +199,10 @@ function module.pcall(fn, ...)
-- C:/long/path/foo.lua:186: Expected string, got number
-- to:
-- .../foo.lua:0: Expected string, got number
- local errmsg = tostring(rv):gsub('([%s<])vim[/\\]([^%s:/\\]+):%d+', '%1\xffvim\xff%2:0')
- :gsub('[^%s<]-[/\\]([^%s:/\\]+):%d+', '.../%1:0')
- :gsub('\xffvim\xff', 'vim/')
+ local errmsg = tostring(rv)
+ :gsub('([%s<])vim[/\\]([^%s:/\\]+):%d+', '%1\xffvim\xff%2:0')
+ :gsub('[^%s<]-[/\\]([^%s:/\\]+):%d+', '.../%1:0')
+ :gsub('\xffvim\xff', 'vim/')
-- Scrub numbers in paths/stacktraces:
-- shared.lua:0: in function 'gsplit'
@@ -221,8 +235,10 @@ end
-- -- Match Lua pattern.
-- matches('e[or]+$', pcall_err(function(a, b) error('some error') end, 'arg1', 'arg2'))
--
+--- @param fn function
+--- @return string
function module.pcall_err_withfile(fn, ...)
- assert(type(fn) == 'function')
+ luaassert(type(fn) == 'function')
local status, rv = module.pcall(fn, ...)
if status == true then
error('expected failure, but got success')
@@ -230,20 +246,31 @@ function module.pcall_err_withfile(fn, ...)
return rv
end
+--- @param fn function
+--- @param ... any
+--- @return string
function module.pcall_err_withtrace(fn, ...)
local errmsg = module.pcall_err_withfile(fn, ...)
- return errmsg:gsub('^%.%.%./helpers%.lua:0: ', '')
- :gsub('^Error executing lua:- ' ,'')
- :gsub('^%[string "<nvim>"%]:0: ' ,'')
+ return (
+ errmsg
+ :gsub('^%.%.%./helpers%.lua:0: ', '')
+ :gsub('^Error executing lua:- ', '')
+ :gsub('^%[string "<nvim>"%]:0: ', '')
+ )
end
-function module.pcall_err(...)
- return module.remove_trace(module.pcall_err_withtrace(...))
+--- @param fn function
+--- @param ... any
+--- @return string
+function module.pcall_err(fn, ...)
+ return module.remove_trace(module.pcall_err_withtrace(fn, ...))
end
+--- @param s string
+--- @return string
function module.remove_trace(s)
- return (s:gsub("\n%s*stack traceback:.*", ""))
+ return (s:gsub('\n%s*stack traceback:.*', ''))
end
-- initial_path: directory to recurse into
@@ -251,12 +278,14 @@ end
-- exc_re: exclude pattern(s) (string or table)
function module.glob(initial_path, re, exc_re)
exc_re = type(exc_re) == 'table' and exc_re or { exc_re }
- local paths_to_check = {initial_path}
- local ret = {}
- local checked_files = {}
+ local paths_to_check = { initial_path } --- @type string[]
+ local ret = {} --- @type string[]
+ local checked_files = {} --- @type table<string,true>
local function is_excluded(path)
for _, pat in pairs(exc_re) do
- if path:match(pat) then return true end
+ if path:match(pat) then
+ return true
+ end
end
return false
end
@@ -271,7 +300,7 @@ function module.glob(initial_path, re, exc_re)
local full_path = cur_path .. '/' .. e
local checked_path = full_path:sub(#initial_path + 1)
if (not is_excluded(checked_path)) and e:sub(1, 1) ~= '.' then
- local stat = luv.fs_stat(full_path)
+ local stat = uv.fs_stat(full_path)
if stat then
local check_key = stat.dev .. ':' .. tostring(stat.ino)
if not checked_files[check_key] then
@@ -296,9 +325,9 @@ function module.check_logs()
for tail in vim.fs.dir(log_dir) do
if tail:sub(1, 30) == 'valgrind-' or tail:find('san%.') then
local file = log_dir .. '/' .. tail
- local fd = io.open(file)
+ local fd = assert(io.open(file))
local start_msg = ('='):rep(20) .. ' File ' .. file .. ' ' .. ('='):rep(20)
- local lines = {}
+ local lines = {} --- @type string[]
local warning_line = 0
for line in fd:lines() do
local cur_warning_line = check_logs_useless_lines[line]
@@ -310,6 +339,7 @@ function module.check_logs()
end
fd:close()
if #lines > 0 then
+ --- @type boolean?, file*?
local status, f
local out = io.stdout
if os.getenv('SYMBOLIZER') then
@@ -317,8 +347,9 @@ function module.check_logs()
end
out:write(start_msg .. '\n')
if status then
+ assert(f)
for line in f:lines() do
- out:write('= '..line..'\n')
+ out:write('= ' .. line .. '\n')
end
f:close()
else
@@ -331,76 +362,67 @@ function module.check_logs()
end
end
end
- assert(0 == #runtime_errors, string.format(
- 'Found runtime errors in logfile(s): %s',
- table.concat(runtime_errors, ', ')))
+ luaassert(
+ 0 == #runtime_errors,
+ string.format('Found runtime errors in logfile(s): %s', table.concat(runtime_errors, ', '))
+ )
end
function module.sysname()
- local platform = luv.os_uname()
- if platform and platform.sysname then
- return platform.sysname:lower()
- end
+ return uv.os_uname().sysname:lower()
end
+--- @param s 'win'|'mac'|'freebsd'|'openbsd'|'bsd'
+--- @return boolean
function module.is_os(s)
- if not (s == 'win'
- or s == 'mac'
- or s == 'freebsd'
- or s == 'openbsd'
- or s == 'bsd') then
- error('unknown platform: '..tostring(s))
- end
- return not not ((s == 'win' and (module.sysname():find('windows') or module.sysname():find('mingw')))
+ if not (s == 'win' or s == 'mac' or s == 'freebsd' or s == 'openbsd' or s == 'bsd') then
+ error('unknown platform: ' .. tostring(s))
+ end
+ return not not (
+ (s == 'win' and (module.sysname():find('windows') or module.sysname():find('mingw')))
or (s == 'mac' and module.sysname() == 'darwin')
or (s == 'freebsd' and module.sysname() == 'freebsd')
or (s == 'openbsd' and module.sysname() == 'openbsd')
- or (s == 'bsd' and module.sysname():find('bsd')))
+ or (s == 'bsd' and module.sysname():find('bsd'))
+ )
end
local function tmpdir_get()
return os.getenv('TMPDIR') and os.getenv('TMPDIR') or os.getenv('TEMP')
end
--- Is temp directory `dir` defined local to the project workspace?
+--- Is temp directory `dir` defined local to the project workspace?
+--- @param dir string?
+--- @return boolean
local function tmpdir_is_local(dir)
- return not not (dir and string.find(dir, 'Xtest'))
+ return not not (dir and dir:find('Xtest'))
end
+local tmpname_id = 0
+local tmpdir = tmpdir_get()
+
--- Creates a new temporary file for use by tests.
-module.tmpname = (function()
- local seq = 0
- local tmpdir = tmpdir_get()
- return (function()
- if tmpdir_is_local(tmpdir) then
- -- Cannot control os.tmpname() dir, so hack our own tmpname() impl.
- seq = seq + 1
- -- "…/Xtest_tmpdir/T42.7"
- local fname = ('%s/%s.%d'):format(tmpdir, (_G._nvim_test_id or 'nvim-test'), seq)
- io.open(fname, 'w'):close()
- return fname
- else
- local fname = os.tmpname()
- if module.is_os('win') and fname:sub(1, 2) == '\\s' then
- -- In Windows tmpname() returns a filename starting with
- -- special sequence \s, prepend $TEMP path
- return tmpdir..fname
- elseif fname:match('^/tmp') and module.is_os('mac') then
- -- In OS X /tmp links to /private/tmp
- return '/private'..fname
- else
- return fname
- end
- end
- end)
-end)()
+function module.tmpname()
+ if tmpdir_is_local(tmpdir) then
+ -- Cannot control os.tmpname() dir, so hack our own tmpname() impl.
+ tmpname_id = tmpname_id + 1
+ -- "…/Xtest_tmpdir/T42.7"
+ local fname = ('%s/%s.%d'):format(tmpdir, (_G._nvim_test_id or 'nvim-test'), tmpname_id)
+ io.open(fname, 'w'):close()
+ return fname
+ end
-function module.hasenv(name)
- local env = os.getenv(name)
- if env and env ~= '' then
- return env
+ local fname = os.tmpname()
+ if module.is_os('win') and fname:sub(1, 2) == '\\s' then
+ -- In Windows tmpname() returns a filename starting with
+ -- special sequence \s, prepend $TEMP path
+ return tmpdir .. fname
+ elseif module.is_os('mac') and fname:match('^/tmp') then
+ -- In OS X /tmp links to /private/tmp
+ return '/private' .. fname
end
- return nil
+
+ return fname
end
local function deps_prefix()
@@ -416,22 +438,27 @@ function module.check_cores(app, force) -- luacheck: ignore
return
end
app = app or 'build/bin/nvim' -- luacheck: ignore
+ --- @type string, string?, string[]
local initial_path, re, exc_re
- local gdb_db_cmd = 'gdb -n -batch -ex "thread apply all bt full" "$_NVIM_TEST_APP" -c "$_NVIM_TEST_CORE"'
+ local gdb_db_cmd =
+ 'gdb -n -batch -ex "thread apply all bt full" "$_NVIM_TEST_APP" -c "$_NVIM_TEST_CORE"'
local lldb_db_cmd = 'lldb -Q -o "bt all" -f "$_NVIM_TEST_APP" -c "$_NVIM_TEST_CORE"'
local random_skip = false
-- Workspace-local $TMPDIR, scrubbed and pattern-escaped.
-- "./Xtest-tmpdir/" => "Xtest%-tmpdir"
- local local_tmpdir = (tmpdir_is_local(tmpdir_get())
- and relpath(tmpdir_get()):gsub('^[ ./]+',''):gsub('%/+$',''):gsub('([^%w])', '%%%1')
- or nil)
- local db_cmd
- if module.hasenv('NVIM_TEST_CORE_GLOB_DIRECTORY') then
- initial_path = os.getenv('NVIM_TEST_CORE_GLOB_DIRECTORY')
+ local local_tmpdir = (
+ tmpdir_is_local(tmpdir_get())
+ and relpath(tmpdir_get()):gsub('^[ ./]+', ''):gsub('%/+$', ''):gsub('([^%w])', '%%%1')
+ or nil
+ )
+ local db_cmd --- @type string
+ local test_glob_dir = os.getenv('NVIM_TEST_CORE_GLOB_DIRECTORY')
+ if test_glob_dir and test_glob_dir ~= '' then
+ initial_path = test_glob_dir
re = os.getenv('NVIM_TEST_CORE_GLOB_RE')
exc_re = { os.getenv('NVIM_TEST_CORE_EXC_RE'), local_tmpdir }
db_cmd = os.getenv('NVIM_TEST_CORE_DB_CMD') or gdb_db_cmd
- random_skip = os.getenv('NVIM_TEST_CORE_RANDOM_SKIP')
+ random_skip = os.getenv('NVIM_TEST_CORE_RANDOM_SKIP') ~= ''
elseif module.is_os('mac') then
initial_path = '/cores'
re = nil
@@ -444,7 +471,7 @@ function module.check_cores(app, force) -- luacheck: ignore
else
re = '/core[^/]*$'
end
- exc_re = { '^/%.deps$', '^/%'..deps_prefix()..'$', local_tmpdir, '^/%node_modules$' }
+ exc_re = { '^/%.deps$', '^/%' .. deps_prefix() .. '$', local_tmpdir, '^/%node_modules$' }
db_cmd = gdb_db_cmd
random_skip = true
end
@@ -457,7 +484,7 @@ function module.check_cores(app, force) -- luacheck: ignore
local found_cores = 0
local out = io.stdout
for _, core in ipairs(cores) do
- local len = 80 - #core - #('Core file ') - 2
+ local len = 80 - #core - #'Core file ' - 2
local esigns = ('='):rep(len / 2)
out:write(('\n%s Core file %s %s\n'):format(esigns, core, esigns))
out:flush()
@@ -471,7 +498,7 @@ function module.check_cores(app, force) -- luacheck: ignore
end
tests_skipped = 0
if found_cores > 0 then
- error("crash detected (see above)")
+ error('crash detected (see above)')
end
end
@@ -489,21 +516,28 @@ function module.repeated_read_cmd(...)
return nil
end
+--- @generic T
+--- @param orig T
+--- @return T
function module.shallowcopy(orig)
if type(orig) ~= 'table' then
return orig
end
- local copy = {}
+ --- @cast orig table<any,any>
+ local copy = {} --- @type table<any,any>
for orig_key, orig_value in pairs(orig) do
copy[orig_key] = orig_value
end
return copy
end
+--- @param d1 table<any,any>
+--- @param d2 table<any,any>
+--- @return table<any,any>
function module.mergedicts_copy(d1, d2)
local ret = module.shallowcopy(d1)
for k, v in pairs(d2) do
- if d2[k] == module.REMOVE_THIS then
+ if d2[k] == vim.NIL then
ret[k] = nil
elseif type(d1[k]) == 'table' and type(v) == 'table' then
ret[k] = module.mergedicts_copy(d1[k], v)
@@ -514,16 +548,18 @@ function module.mergedicts_copy(d1, d2)
return ret
end
--- dictdiff: find a diff so that mergedicts_copy(d1, diff) is equal to d2
---
--- Note: does not do copies of d2 values used.
+--- dictdiff: find a diff so that mergedicts_copy(d1, diff) is equal to d2
+---
+--- Note: does not do copies of d2 values used.
+--- @param d1 table<any,any>
+--- @param d2 table<any,any>
function module.dictdiff(d1, d2)
- local ret = {}
+ local ret = {} --- @type table<any,any>
local hasdiff = false
for k, v in pairs(d1) do
if d2[k] == nil then
hasdiff = true
- ret[k] = module.REMOVE_THIS
+ ret[k] = vim.NIL
elseif type(v) == type(d2[k]) then
if type(v) == 'table' then
local subdiff = module.dictdiff(v, d2[k])
@@ -554,17 +590,11 @@ function module.dictdiff(d1, d2)
end
end
-function module.updated(d, d2)
- for k, v in pairs(d2) do
- d[k] = v
- end
- return d
-end
-
-- Concat list-like tables.
function module.concat_tables(...)
- local ret = {}
+ local ret = {} --- @type table<any,any>
for i = 1, select('#', ...) do
+ --- @type table<any,any>
local tbl = select(i, ...)
if tbl then
for _, v in ipairs(tbl) do
@@ -597,203 +627,48 @@ function module.dedent(str, leave_indent)
-- create a pattern for the indent
indent = indent:gsub('%s', '[ \t]')
-- strip it from the first line
- str = str:gsub('^'..indent, left_indent)
+ str = str:gsub('^' .. indent, left_indent)
-- strip it from the remaining lines
- str = str:gsub('[\n]'..indent, '\n' .. left_indent)
+ str = str:gsub('[\n]' .. indent, '\n' .. left_indent)
return str
end
-local function format_float(v)
- -- On windows exponent appears to have three digits and not two
- local ret = ('%.6e'):format(v)
- local l, f, es, e = ret:match('^(%-?%d)%.(%d+)e([+%-])0*(%d%d+)$')
- return l .. '.' .. f .. 'e' .. es .. e
-end
-
-local SUBTBL = {
- '\\000', '\\001', '\\002', '\\003', '\\004',
- '\\005', '\\006', '\\007', '\\008', '\\t',
- '\\n', '\\011', '\\012', '\\r', '\\014',
- '\\015', '\\016', '\\017', '\\018', '\\019',
- '\\020', '\\021', '\\022', '\\023', '\\024',
- '\\025', '\\026', '\\027', '\\028', '\\029',
- '\\030', '\\031',
-}
-
--- Formats Lua value `v`.
---
--- TODO(justinmk): redundant with vim.inspect() ?
---
--- "Nice table formatting similar to screen:snapshot_util()".
--- Commit: 520c0b91a528
-function module.format_luav(v, indent, opts)
- opts = opts or {}
- local linesep = '\n'
- local next_indent_arg = nil
- local indent_shift = opts.indent_shift or ' '
- local next_indent
- local nl = '\n'
- if indent == nil then
- indent = ''
- linesep = ''
- next_indent = ''
- nl = ' '
- else
- next_indent_arg = indent .. indent_shift
- next_indent = indent .. indent_shift
- end
- local ret = ''
- if type(v) == 'string' then
- if opts.literal_strings then
- ret = v
- else
- local quote = opts.dquote_strings and '"' or '\''
- ret = quote .. tostring(v):gsub(
- opts.dquote_strings and '["\\]' or '[\'\\]',
- '\\%0'):gsub(
- '[%z\1-\31]', function(match)
- return SUBTBL[match:byte() + 1]
- end) .. quote
- end
- elseif type(v) == 'table' then
- if v == module.REMOVE_THIS then
- ret = 'REMOVE_THIS'
- else
- local processed_keys = {}
- ret = '{' .. linesep
- local non_empty = false
- local format_luav = module.format_luav
- for i, subv in ipairs(v) do
- ret = ('%s%s%s,%s'):format(ret, next_indent,
- format_luav(subv, next_indent_arg, opts), nl)
- processed_keys[i] = true
- non_empty = true
- end
- for k, subv in pairs(v) do
- if not processed_keys[k] then
- if type(k) == 'string' and k:match('^[a-zA-Z_][a-zA-Z0-9_]*$') then
- ret = ret .. next_indent .. k .. ' = '
- else
- ret = ('%s%s[%s] = '):format(ret, next_indent,
- format_luav(k, nil, opts))
- end
- ret = ret .. format_luav(subv, next_indent_arg, opts) .. ',' .. nl
- non_empty = true
- end
- end
- if nl == ' ' and non_empty then
- ret = ret:sub(1, -3)
- end
- ret = ret .. indent .. '}'
- end
- elseif type(v) == 'number' then
- if v % 1 == 0 then
- ret = ('%d'):format(v)
- else
- ret = format_float(v)
- end
- elseif type(v) == 'nil' then
- ret = 'nil'
- elseif type(v) == 'boolean' then
- ret = (v and 'true' or 'false')
- else
- print(type(v))
- -- Not implemented yet
- assert(false)
- end
- return ret
-end
-
--- Like Python repr(), "{!r}".format(s)
---
--- Commit: 520c0b91a528
-function module.format_string(fmt, ...)
- local i = 0
- local args = {...}
- local function getarg()
- i = i + 1
- return args[i]
- end
- local ret = fmt:gsub('%%[0-9*]*%.?[0-9*]*[cdEefgGiouXxqsr%%]', function(match)
- local subfmt = match:gsub('%*', function()
- return tostring(getarg())
- end)
- local arg = nil
- if subfmt:sub(-1) ~= '%' then
- arg = getarg()
- end
- if subfmt:sub(-1) == 'r' or subfmt:sub(-1) == 'q' then
- -- %r is like built-in %q, but it is supposed to single-quote strings and
- -- not double-quote them, and also work not only for strings.
- -- Builtin %q is replaced here as it gives invalid and inconsistent with
- -- luajit results for e.g. "\e" on lua: luajit transforms that into `\27`,
- -- lua leaves as-is.
- arg = module.format_luav(arg, nil, {dquote_strings = (subfmt:sub(-1) == 'q')})
- subfmt = subfmt:sub(1, -2) .. 's'
- end
- if subfmt == '%e' then
- return format_float(arg)
- else
- return subfmt:format(arg)
- end
- end)
- return ret
-end
-
function module.intchar2lua(ch)
ch = tonumber(ch)
return (20 <= ch and ch < 127) and ('%c'):format(ch) or ch
end
-local fixtbl_metatable = {
- __newindex = function()
- assert(false)
- end,
-}
-
-function module.fixtbl(tbl)
- return setmetatable(tbl, fixtbl_metatable)
-end
-
-function module.fixtbl_rec(tbl)
- local fixtbl_rec = module.fixtbl_rec
- for _, v in pairs(tbl) do
- if type(v) == 'table' then
- fixtbl_rec(v)
- end
- end
- return module.fixtbl(tbl)
-end
-
+--- @param str string
+--- @return string
function module.hexdump(str)
local len = string.len(str)
- local dump = ""
- local hex = ""
- local asc = ""
+ local dump = ''
+ local hex = ''
+ local asc = ''
for i = 1, len do
if 1 == i % 8 then
- dump = dump .. hex .. asc .. "\n"
- hex = string.format("%04x: ", i - 1)
- asc = ""
+ dump = dump .. hex .. asc .. '\n'
+ hex = string.format('%04x: ', i - 1)
+ asc = ''
end
local ord = string.byte(str, i)
- hex = hex .. string.format("%02x ", ord)
+ hex = hex .. string.format('%02x ', ord)
if ord >= 32 and ord <= 126 then
asc = asc .. string.char(ord)
else
- asc = asc .. "."
+ asc = asc .. '.'
end
end
- return dump .. hex .. string.rep(" ", 8 - len % 8) .. asc
+ return dump .. hex .. string.rep(' ', 8 - len % 8) .. asc
end
--- Reads text lines from `filename` into a table.
---
--- filename: path to file
--- start: start line (1-indexed), negative means "lines before end" (tail)
+--- Reads text lines from `filename` into a table.
+--- @param filename string path to file
+--- @param start? integer start line (1-indexed), negative means "lines before end" (tail)
+--- @return string[]?
function module.read_file_list(filename, start)
local lnum = (start ~= nil and type(start) == 'number') and start or 1
local tail = (lnum < 0)
@@ -805,16 +680,16 @@ function module.read_file_list(filename, start)
-- There is no need to read more than the last 2MB of the log file, so seek
-- to that.
- local file_size = file:seek("end")
+ local file_size = file:seek('end')
local offset = file_size - 2000000
if offset < 0 then
offset = 0
end
- file:seek("set", offset)
+ file:seek('set', offset)
local lines = {}
local i = 1
- local line = file:read("*l")
+ local line = file:read('*l')
while line ~= nil do
if i >= start then
table.insert(lines, line)
@@ -823,15 +698,15 @@ function module.read_file_list(filename, start)
end
end
i = i + 1
- line = file:read("*l")
+ line = file:read('*l')
end
file:close()
return lines
end
--- Reads the entire contents of `filename` into a string.
---
--- filename: path to file
+--- Reads the entire contents of `filename` into a string.
+--- @param filename string
+--- @return string?
function module.read_file(filename)
local file = io.open(filename, 'r')
if not file then
@@ -844,9 +719,10 @@ end
-- Dedent the given text and write it to the file name.
function module.write_file(name, text, no_dedent, append)
- local file = io.open(name, (append and 'a' or 'w'))
+ local file = assert(io.open(name, (append and 'a' or 'w')))
if type(text) == 'table' then
-- Byte blob
+ --- @type string[]
local bytes = text
text = ''
for _, char in ipairs(bytes) do
@@ -860,9 +736,11 @@ function module.write_file(name, text, no_dedent, append)
file:close()
end
+--- @param name? 'cirrus'|'github'
+--- @return boolean
function module.is_ci(name)
local any = (name == nil)
- assert(any or name == 'github' or name == 'cirrus')
+ luaassert(any or name == 'github' or name == 'cirrus')
local gh = ((any or name == 'github') and nil ~= os.getenv('GITHUB_ACTIONS'))
local cirrus = ((any or name == 'cirrus') and nil ~= os.getenv('CIRRUS_CI'))
return gh or cirrus
@@ -875,24 +753,27 @@ function module.read_nvim_log(logfile, ci_rename)
local is_ci = module.is_ci()
local keep = is_ci and 100 or 10
local lines = module.read_file_list(logfile, -keep) or {}
- local log = (('-'):rep(78)..'\n'
- ..string.format('$NVIM_LOG_FILE: %s\n', logfile)
- ..(#lines > 0 and '(last '..tostring(keep)..' lines)\n' or '(empty)\n'))
- for _,line in ipairs(lines) do
- log = log..line..'\n'
- end
- log = log..('-'):rep(78)..'\n'
+ local log = (
+ ('-'):rep(78)
+ .. '\n'
+ .. string.format('$NVIM_LOG_FILE: %s\n', logfile)
+ .. (#lines > 0 and '(last ' .. tostring(keep) .. ' lines)\n' or '(empty)\n')
+ )
+ for _, line in ipairs(lines) do
+ log = log .. line .. '\n'
+ end
+ log = log .. ('-'):rep(78) .. '\n'
if is_ci and ci_rename then
os.rename(logfile, logfile .. '.displayed')
end
return log
end
+--- @param path string
+--- @return boolean?
function module.mkdir(path)
-- 493 is 0755 in decimal
- return luv.fs_mkdir(path, 493)
+ return (uv.fs_mkdir(path, 493))
end
-module = shared.tbl_extend('error', module, Paths, shared, require('test.deprecated'))
-
return module
diff --git a/test/lua_runner.lua b/test/lua_runner.lua
index 686df9feec..158412b04c 100644
--- a/test/lua_runner.lua
+++ b/test/lua_runner.lua
@@ -1,9 +1,13 @@
local platform = vim.uv.os_uname()
local deps_install_dir = table.remove(_G.arg, 1)
local subcommand = table.remove(_G.arg, 1)
-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;
+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
local uv = vim.uv
@@ -15,14 +19,14 @@ local system = {}
package.loaded['system.core'] = system
function system.monotime()
uv.update_time()
- return uv.now()*1e-3
+ return uv.now() * 1e-3
end
function system.gettime()
local sec, usec = uv.gettimeofday()
- return sec+usec*1e-6
+ return sec + usec * 1e-6
end
function system.sleep(sec)
- uv.sleep(sec*1e3)
+ uv.sleep(sec * 1e3)
end
local term = {}
@@ -31,7 +35,7 @@ function term.isatty(_)
return uv.guess_handle(1) == 'tty'
end
-local lfs = {_VERSION = 'fake'}
+local lfs = { _VERSION = 'fake' }
package.loaded['lfs'] = lfs
function lfs.attributes(path, attr)
@@ -39,9 +43,11 @@ function lfs.attributes(path, attr)
if attr == 'mode' then
return stat and stat.type or ''
elseif attr == 'modification' then
- if not stat then return nil end
+ if not stat then
+ return nil
+ end
local mtime = stat.mtime
- return mtime.sec + mtime.nsec*1e-9
+ return mtime.sec + mtime.nsec * 1e-9
else
error('not implemented')
end
@@ -74,9 +80,9 @@ function lfs.mkdir(dir)
return uv.fs_mkdir(dir, 493) -- octal 755
end
-if subcommand == "busted" then
+if subcommand == 'busted' then
require 'busted.runner'({ standalone = false })
-elseif subcommand == "luacheck" then
+elseif subcommand == 'luacheck' then
require 'luacheck.main'
else
error 'unknown subcommand'
diff --git a/test/old/testdir/Makefile b/test/old/testdir/Makefile
index b5ca6a17b0..20272a24c7 100644
--- a/test/old/testdir/Makefile
+++ b/test/old/testdir/Makefile
@@ -41,13 +41,13 @@ ifdef USE_VALGRIND
--leak-check=yes \
--track-origins=yes
# VALGRIND_TOOL := exp-sgcheck
- TOOL := valgrind -q \
- -q \
- $(VALGRIND_TOOL) \
- --suppressions=../../.valgrind.supp \
- --error-exitcode=123 \
- --log-file=valgrind-\%p.$* \
- $(VGDB) \
+ TOOL := valgrind -q \
+ -q \
+ $(VALGRIND_TOOL) \
+ --suppressions=../../../src/.valgrind.supp \
+ --error-exitcode=123 \
+ --log-file=valgrind-\%p.$* \
+ $(VGDB) \
--trace-children=yes
else
ifdef USE_GDB
@@ -121,7 +121,8 @@ CLEAN_FILES := *.out \
.*.swo \
.gdbinit \
$(TMPDIR) \
- del
+ del \
+ $(ROOT)/runtime/doc/.*.swp
clean:
$(RM) -rf $(CLEAN_FILES)
diff --git a/test/old/testdir/crash/poc_did_set_langmap b/test/old/testdir/crash/poc_did_set_langmap
new file mode 100644
index 0000000000..f77145b9d1
--- /dev/null
+++ b/test/old/testdir/crash/poc_did_set_langmap
@@ -0,0 +1 @@
+se lmap=°xÿ7sil;drlmap=°xÿ7sil;drmo: pm31 3" \ No newline at end of file
diff --git a/test/old/testdir/crash/poc_ex_substitute b/test/old/testdir/crash/poc_ex_substitute
new file mode 100644
index 0000000000..bcf1286512
--- /dev/null
+++ b/test/old/testdir/crash/poc_ex_substitute
Binary files differ
diff --git a/test/old/testdir/crash/poc_suggest_trie_walk b/test/old/testdir/crash/poc_suggest_trie_walk
new file mode 100644
index 0000000000..c79b6eeb5c
--- /dev/null
+++ b/test/old/testdir/crash/poc_suggest_trie_walk
Binary files differ
diff --git a/test/old/testdir/crash/poc_win_enter_ext b/test/old/testdir/crash/poc_win_enter_ext
new file mode 100644
index 0000000000..73f53b575b
--- /dev/null
+++ b/test/old/testdir/crash/poc_win_enter_ext
Binary files differ
diff --git a/test/old/testdir/runnvim.vim b/test/old/testdir/runnvim.vim
index 2db60d05b3..578614c8a1 100644
--- a/test/old/testdir/runnvim.vim
+++ b/test/old/testdir/runnvim.vim
@@ -7,6 +7,8 @@ function s:logger.on_exit(id, data, event)
call add(self.d_events, [a:event, ['']])
endfunction
+let s:logger.env = #{VIMRUNTIME: $VIMRUNTIME}
+
" Replace non-printable chars by special sequence, or "<%x>".
let s:escaped_char = {"\n": '\n', "\r": '\r', "\t": '\t'}
function! s:escape_non_printable(char) abort
@@ -23,8 +25,7 @@ function Main()
set lines=25
set columns=80
enew
- " FIXME: using termopen() hangs on Windows CI
- let job = has('win32') ? jobstart(args, s:logger) : termopen(args, s:logger)
+ let job = termopen(args, s:logger)
let results = jobwait([job], 5 * 60 * 1000)
" TODO(ZyX-I): Get colors
let screen = getline(1, '$')
diff --git a/test/old/testdir/runtest.vim b/test/old/testdir/runtest.vim
index 928bf7693f..2d8ba60a7e 100644
--- a/test/old/testdir/runtest.vim
+++ b/test/old/testdir/runtest.vim
@@ -120,6 +120,8 @@ lang mess C
" Nvim: append runtime from build dir, which contains the generated doc/tags.
let &runtimepath ..= ',' .. expand($BUILD_DIR) .. '/runtime/'
+" Nvim: append libdir from build dir, which contains the bundled TS parsers.
+let &runtimepath ..= ',' .. expand($BUILD_DIR) .. '/lib/nvim/'
let s:t_bold = &t_md
let s:t_normal = &t_me
diff --git a/test/old/testdir/setup.vim b/test/old/testdir/setup.vim
index 7546b342e6..091fb95806 100644
--- a/test/old/testdir/setup.vim
+++ b/test/old/testdir/setup.vim
@@ -93,3 +93,6 @@ let $HOME = expand(getcwd() . '/XfakeHOME')
if !isdirectory($HOME)
call mkdir($HOME)
endif
+
+" Use Vim's default color scheme
+colorscheme vim
diff --git a/test/old/testdir/test_autocmd.vim b/test/old/testdir/test_autocmd.vim
index 7926411dcd..4d88573a1f 100644
--- a/test/old/testdir/test_autocmd.vim
+++ b/test/old/testdir/test_autocmd.vim
@@ -2533,7 +2533,25 @@ func Test_TextChangedI_with_setline()
call assert_equal('', getline(1))
call assert_equal('', getline(2))
- call test_override('starting', 0)
+ call test_override('char_avail', 0)
+ bwipe!
+endfunc
+
+func Test_TextChanged_with_norm()
+ " For unknown reason this fails on MS-Windows
+ CheckNotMSWindows
+ CheckFeature terminal
+ let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3})
+ call assert_equal('running', term_getstatus(buf))
+ call term_sendkeys(buf, ":let g:a=0\<cr>")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":au! TextChanged * :let g:a+=1\<cr>")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":norm! ia\<cr>")
+ call term_wait(buf, 50)
+ call term_sendkeys(buf, ":echo g:a\<cr>")
+ call term_wait(buf, 50)
+ call WaitForAssert({-> assert_match('^1.*$', term_getline(buf, 3))})
bwipe!
endfunc
@@ -3822,4 +3840,44 @@ func Test_autocmd_shortmess()
delfunc SetupVimTest_shm
endfunc
+func Test_autocmd_invalidates_undo_on_textchanged()
+ CheckRunVimInTerminal
+ let script =<< trim END
+ set hidden
+ " create quickfix list (at least 2 lines to move line)
+ vimgrep /u/j %
+
+ " enter quickfix window
+ cwindow
+
+ " set modifiable
+ setlocal modifiable
+
+ " set autocmd to clear quickfix list
+
+ autocmd! TextChanged <buffer> call setqflist([])
+ " move line
+ move+1
+ END
+ call writefile(script, 'XTest_autocmd_invalidates_undo_on_textchanged', 'D')
+ let buf = RunVimInTerminal('XTest_autocmd_invalidates_undo_on_textchanged', {'rows': 20})
+ call term_sendkeys(buf, ":so %\<cr>")
+ call term_sendkeys(buf, "G")
+ call WaitForAssert({-> assert_match('^XTest_autocmd_invalidates_undo_on_textchanged\s*$', term_getline(buf, 20))}, 1000)
+
+ call StopVimInTerminal(buf)
+endfunc
+
+func Test_autocmd_creates_new_buffer_on_bufleave()
+ e a.txt
+ e b.txt
+ setlocal bufhidden=wipe
+ autocmd BufLeave <buffer> diffsplit c.txt
+ bn
+ call assert_equal(1, winnr('$'))
+ call assert_equal('a.txt', bufname('%'))
+ bw a.txt
+ bw c.txt
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_breakindent.vim b/test/old/testdir/test_breakindent.vim
index 301e2d0e40..636ec6f285 100644
--- a/test/old/testdir/test_breakindent.vim
+++ b/test/old/testdir/test_breakindent.vim
@@ -450,7 +450,7 @@ func Test_breakindent12()
\ "~ ",
\ ]
call s:compare_lines(expect, lines)
- call s:close_windows('set nuw=4 listchars=')
+ call s:close_windows('set nuw=4 listchars&')
endfunc
func Test_breakindent12_vartabs()
@@ -467,7 +467,7 @@ func Test_breakindent12_vartabs()
\ "~ ",
\ ]
call s:compare_lines(expect, lines)
- call s:close_windows('set nuw=4 listchars= vts&')
+ call s:close_windows('set nuw=4 listchars& vts&')
endfunc
func Test_breakindent13()
@@ -773,7 +773,7 @@ func Test_breakindent20_list()
\ "shall make no law ",
\ ]
call s:compare_lines(expect, lines)
- " set minimum indent
+ " set minimum text width
setl briopt=min:5
redraw!
let lines = s:screen_lines2(1, 6, 20)
@@ -963,6 +963,29 @@ func Test_cursor_position_with_showbreak()
call StopVimInTerminal(buf)
endfunc
+func Test_visual_starts_before_skipcol()
+ CheckScreendump
+
+ let lines =<< trim END
+ 1new
+ setlocal breakindent
+ call setline(1, "\t" .. join(range(100)))
+ END
+ call writefile(lines, 'XvisualStartsBeforeSkipcol', 'D')
+ let buf = RunVimInTerminal('-S XvisualStartsBeforeSkipcol', #{rows: 6})
+
+ call term_sendkeys(buf, "v$")
+ call VerifyScreenDump(buf, 'Test_visual_starts_before_skipcol_1', {})
+ call term_sendkeys(buf, "\<Esc>:setlocal showbreak=+++\<CR>gv")
+ call VerifyScreenDump(buf, 'Test_visual_starts_before_skipcol_2', {})
+ call term_sendkeys(buf, "\<Esc>:setlocal breakindentopt+=sbr\<CR>gv")
+ call VerifyScreenDump(buf, 'Test_visual_starts_before_skipcol_3', {})
+ call term_sendkeys(buf, "\<Esc>:setlocal nobreakindent\<CR>gv")
+ call VerifyScreenDump(buf, 'Test_visual_starts_before_skipcol_4', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_no_spurious_match()
let s:input = printf('- y %s y %s', repeat('x', 50), repeat('x', 50))
call s:test_windows('setl breakindent breakindentopt=list:-1 formatlistpat=^- hls')
@@ -1103,5 +1126,83 @@ func Test_linebreak_list()
bwipe!
endfunc
+func Test_breakindent_change_display_uhex()
+ call s:test_windows('setl briopt=min:0 list listchars=eol:$')
+ redraw!
+ let lines = s:screen_lines(line('.'), 20)
+ let expect = [
+ \ "^Iabcdefghijklmnopqr",
+ \ " stuvwxyzABCDEFGHIJ",
+ \ " KLMNOP$ "
+ \ ]
+ call s:compare_lines(expect, lines)
+ set display+=uhex
+ redraw!
+ let lines = s:screen_lines(line('.'), 20)
+ let expect = [
+ \ "<09>abcdefghijklmnop",
+ \ " qrstuvwxyzABCDEF",
+ \ " GHIJKLMNOP$ "
+ \ ]
+ call s:compare_lines(expect, lines)
+ set display&
+
+ call s:close_windows()
+endfunc
+
+func Test_breakindent_list_split()
+ 10new
+ 61vsplit
+ setlocal tabstop=8 breakindent list listchars=tab:<->,eol:$
+ put =s:input
+ 30vsplit
+ setlocal listchars=eol:$
+ let expect = [
+ \ "^IabcdefghijklmnopqrstuvwxyzAB|<------>abcdefghijklmnopqrstuv",
+ \ " CDEFGHIJKLMNOP$ | wxyzABCDEFGHIJKLMNOP$ ",
+ \ "~ |~ "
+ \ ]
+ redraw!
+ let lines = s:screen_lines(line('.'), 61)
+ call s:compare_lines(expect, lines)
+ wincmd p
+ redraw!
+ let lines = s:screen_lines(line('.'), 61)
+ call s:compare_lines(expect, lines)
+
+ bwipe!
+endfunc
+
+func Test_breakindent_min_with_signcol()
+ call s:test_windows('setl briopt=min:15 signcolumn=yes')
+ redraw!
+ let expect = [
+ \ " abcdefghijklmn",
+ \ " opqrstuvwxyzABC",
+ \ " DEFGHIJKLMNOP "
+ \ ]
+ let lines = s:screen_lines(line('.'), 20)
+ call s:compare_lines(expect, lines)
+ setl briopt=min:17
+ redraw!
+ let expect = [
+ \ " abcdefghijklmn",
+ \ " opqrstuvwxyzABCDE",
+ \ " FGHIJKLMNOP "
+ \ ]
+ let lines = s:screen_lines(line('.'), 20)
+ call s:compare_lines(expect, lines)
+ setl briopt=min:19
+ redraw!
+ let expect = [
+ \ " abcdefghijklmn",
+ \ " opqrstuvwxyzABCDEF",
+ \ " GHIJKLMNOP "
+ \ ]
+ let lines = s:screen_lines(line('.'), 20)
+ call s:compare_lines(expect, lines)
+
+ call s:close_windows()
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_cmdline.vim b/test/old/testdir/test_cmdline.vim
index 3f13218c5b..b8eb9a2b8b 100644
--- a/test/old/testdir/test_cmdline.vim
+++ b/test/old/testdir/test_cmdline.vim
@@ -431,11 +431,11 @@ func Test_highlight_completion()
" A cleared group does not show up in completions.
hi Anders ctermfg=green
- call assert_equal(['Aardig', 'Anders'], getcompletion('A', 'highlight'))
+ call assert_equal(['Aardig', 'Added', 'Anders'], getcompletion('A', 'highlight'))
hi clear Aardig
- call assert_equal(['Anders'], getcompletion('A', 'highlight'))
+ call assert_equal(['Added', 'Anders'], getcompletion('A', 'highlight'))
hi clear Anders
- call assert_equal([], getcompletion('A', 'highlight'))
+ call assert_equal(['Added'], getcompletion('A', 'highlight'))
endfunc
func Test_getcompletion()
@@ -532,6 +532,13 @@ func Test_getcompletion()
let l = getcompletion('horse', 'filetype')
call assert_equal([], l)
+ if has('keymap')
+ let l = getcompletion('acc', 'keymap')
+ call assert_true(index(l, 'accents') >= 0)
+ let l = getcompletion('nullkeymap', 'keymap')
+ call assert_equal([], l)
+ endif
+
let l = getcompletion('z', 'syntax')
call assert_true(index(l, 'zimbu') >= 0)
let l = getcompletion('emacs', 'syntax')
@@ -672,7 +679,7 @@ func Test_getcompletion()
bw Xtest\
endif
- call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E871:')
+ call assert_fails("call getcompletion('\\\\@!\\\\@=', 'buffer')", 'E866:')
call assert_fails('call getcompletion("", "burp")', 'E475:')
call assert_fails('call getcompletion("abc", [])', 'E1174:')
endfunc
@@ -857,10 +864,28 @@ func Test_cmdline_remove_char()
let &encoding = encoding_save
endfunc
-func Test_cmdline_keymap_ctrl_hat()
- if !has('keymap')
- return
+func Test_cmdline_del_utf8()
+ let @s = '⒌'
+ call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx')
+ call assert_equal('",,', @:)
+
+ let @s = 'a̳'
+ call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx')
+ call assert_equal('",,', @:)
+
+ let @s = 'β̳'
+ call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx')
+ call assert_equal('",,', @:)
+
+ if has('arabic')
+ let @s = 'لا'
+ call feedkeys(":\"\<C-R>s,,\<C-B>\<Right>\<Del>\<CR>", 'tx')
+ call assert_equal('",,', @:)
endif
+endfunc
+
+func Test_cmdline_keymap_ctrl_hat()
+ CheckFeature keymap
set keymap=esperanto
call feedkeys(":\"Jxauxdo \<C-^>Jxauxdo \<C-^>Jxauxdo\<CR>", 'tx')
@@ -1878,7 +1903,7 @@ func Test_cmdwin_tabpage()
tabclose!
endfunc
-func Test_cmdwin_interrupted()
+func Test_cmdwin_interrupted_more_prompt()
CheckScreendump
" aborting the :smile output caused the cmdline window to use the current
@@ -3911,4 +3936,34 @@ func Test_custom_completion_with_glob()
delfunc TestGlobComplete
endfunc
+func Test_window_size_stays_same_after_changing_cmdheight()
+ set laststatus=2
+ let expected = winheight(0)
+ function! Function_name() abort
+ call feedkeys(":"..repeat('x', &columns), 'x')
+ let &cmdheight=2
+ let &cmdheight=1
+ redraw
+ endfunction
+ call Function_name()
+ call assert_equal(expected, winheight(0))
+endfunc
+
+" verify that buffer-completion finds all buffer names matching a pattern
+func Test_buffer_completion()
+ " should return empty list
+ call assert_equal([], getcompletion('', 'buffer'))
+
+ call mkdir('Xbuf_complete', 'R')
+ e Xbuf_complete/Foobar.c
+ e Xbuf_complete/MyFoobar.c
+ e AFoobar.h
+ let expected = ["Xbuf_complete/Foobar.c", "Xbuf_complete/MyFoobar.c", "AFoobar.h"]
+
+ call assert_equal(3, len(getcompletion('Foo', 'buffer')))
+ call assert_equal(expected, getcompletion('Foo', 'buffer'))
+ call feedkeys(":b Foo\<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal("\"b Xbuf_complete/Foobar.c Xbuf_complete/MyFoobar.c AFoobar.h", @:)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_cmdwin.vim b/test/old/testdir/test_cmdwin.vim
index f07fd99f8a..9b1a45708e 100644
--- a/test/old/testdir/test_cmdwin.vim
+++ b/test/old/testdir/test_cmdwin.vim
@@ -93,4 +93,116 @@ func Test_cmdwin_restore_heights()
set cmdheight& showtabline& laststatus&
endfunc
+func Test_cmdwin_temp_curwin()
+ func CheckWraps(expect_wrap)
+ setlocal textwidth=0 wrapmargin=1
+
+ call deletebufline('', 1, '$')
+ let as = repeat('a', winwidth(0) - 2 - &wrapmargin)
+ call setline(1, as .. ' b')
+ normal! gww
+
+ setlocal textwidth& wrapmargin&
+ call assert_equal(a:expect_wrap ? [as, 'b'] : [as .. ' b'], getline(1, '$'))
+ endfunc
+
+ func CheckCmdWin()
+ call assert_equal('command', win_gettype())
+ " textoff and &wrapmargin formatting considers the cmdwin_type char.
+ call assert_equal(1, getwininfo(win_getid())[0].textoff)
+ call CheckWraps(1)
+ endfunc
+
+ func CheckOtherWin()
+ call assert_equal('', win_gettype())
+ call assert_equal(0, getwininfo(win_getid())[0].textoff)
+ call CheckWraps(0)
+ endfunc
+
+ call feedkeys("q::call CheckCmdWin()\<CR>:call win_execute(win_getid(winnr('#')), 'call CheckOtherWin()')\<CR>:q<CR>", 'ntx')
+
+ %bwipe!
+ delfunc CheckWraps
+ delfunc CheckCmdWin
+ delfunc CheckOtherWin
+endfunc
+
+func Test_cmdwin_interrupted()
+ func CheckInterrupted()
+ call feedkeys("q::call assert_equal('', getcmdwintype())\<CR>:call assert_equal('', getcmdtype())\<CR>:q<CR>", 'ntx')
+ endfunc
+
+ augroup CmdWin
+
+ " While opening the cmdwin's split:
+ " Close the cmdwin's window.
+ au WinEnter * ++once quit
+ call CheckInterrupted()
+
+ " Close the old window.
+ au WinEnter * ++once execute winnr('#') 'quit'
+ call CheckInterrupted()
+
+ " Switch back to the old window.
+ au WinEnter * ++once wincmd p
+ call CheckInterrupted()
+
+ " Change the old window's buffer.
+ au WinEnter * ++once call win_execute(win_getid(winnr('#')), 'enew')
+ call CheckInterrupted()
+
+ " Using BufLeave autocmds as cmdwin restrictions do not apply to them when
+ " fired from opening the cmdwin...
+ " After opening the cmdwin's split, while creating the cmdwin's buffer:
+ " Delete the cmdwin's buffer.
+ au BufLeave * ++once bwipe
+ call CheckInterrupted()
+
+ " Close the cmdwin's window.
+ au BufLeave * ++once quit
+ call CheckInterrupted()
+
+ " Close the old window.
+ au BufLeave * ++once execute winnr('#') 'quit'
+ call CheckInterrupted()
+
+ " Switch to a different window.
+ au BufLeave * ++once split
+ call CheckInterrupted()
+
+ " Change the old window's buffer.
+ au BufLeave * ++once call win_execute(win_getid(winnr('#')), 'enew')
+ call CheckInterrupted()
+
+ " However, changing the current buffer is OK and does not interrupt.
+ au BufLeave * ++once edit other
+ call feedkeys("q::let t=getcmdwintype()\<CR>:let b=bufnr()\<CR>:clo<CR>", 'ntx')
+ call assert_equal(':', t)
+ call assert_equal(1, bufloaded('other'))
+ call assert_notequal(b, bufnr('other'))
+
+ augroup END
+
+ " No autocmds should remain, but clear the augroup to be sure.
+ augroup CmdWin
+ au!
+ augroup END
+
+ %bwipe!
+ delfunc CheckInterrupted
+endfunc
+
+func Test_cmdwin_existing_bufname()
+ func CheckName()
+ call assert_equal(1, getbufinfo('')[0].command)
+ call assert_equal(0, getbufinfo('[Command Line]')[0].command)
+ call assert_match('#a\s*"\[Command Line\]"', execute('ls'))
+ call assert_match('%a\s*"\[Command Line\]"', execute('ls'))
+ endfunc
+ file [Command Line]
+ call feedkeys("q::call CheckName()\<CR>:q\<CR>", 'ntx')
+ 0file
+ delfunc CheckName
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_crash.vim b/test/old/testdir/test_crash.vim
index b093b053c5..49e712a901 100644
--- a/test/old/testdir/test_crash.vim
+++ b/test/old/testdir/test_crash.vim
@@ -117,7 +117,7 @@ func Test_crash1_2()
" The following used to crash Vim
let opts = #{cmd: 'sh'}
let vim = GetVimProg()
- let result = 'X_crash1_1_result.txt'
+ let result = 'X_crash1_2_result.txt'
let buf = RunVimInTerminal('sh', opts)
@@ -128,6 +128,38 @@ func Test_crash1_2()
\ ' && echo "crash 1: [OK]" > '.. result .. "\<cr>")
call TermWait(buf, 150)
+ let file = 'crash/poc_win_enter_ext'
+ let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
+ let args = printf(cmn_args, vim, file)
+ call term_sendkeys(buf, args ..
+ \ ' && echo "crash 2: [OK]" >> '.. result .. "\<cr>")
+ call TermWait(buf, 350)
+
+ let file = 'crash/poc_suggest_trie_walk'
+ let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
+ let args = printf(cmn_args, vim, file)
+ call term_sendkeys(buf, args ..
+ \ ' && echo "crash 3: [OK]" >> '.. result .. "\<cr>")
+ call TermWait(buf, 150)
+
+ let file = 'crash/poc_did_set_langmap'
+ let cmn_args = "%s -u NONE -i NONE -n -X -m -n -e -s -S %s -c ':qa!'"
+ let args = printf(cmn_args, vim, file)
+ call term_sendkeys(buf, args ..
+ \ ' ; echo "crash 4: [OK]" >> '.. result .. "\<cr>")
+ call TermWait(buf, 150)
+
+ let file = 'crash/poc_ex_substitute'
+ let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'"
+ let args = printf(cmn_args, vim, file)
+ " just make sure it runs, we don't care about the resulting echo
+ call term_sendkeys(buf, args .. "\<cr>")
+ " There is no output generated in Github CI for the asan clang build.
+ " so just skip generating the ouput.
+ " call term_sendkeys(buf, args ..
+ " \ ' && echo "crash 5: [OK]" >> '.. result .. "\<cr>")
+ call TermWait(buf, 150)
+
" clean up
exe buf .. "bw!"
@@ -135,6 +167,9 @@ func Test_crash1_2()
let expected = [
\ 'crash 1: [OK]',
+ \ 'crash 2: [OK]',
+ \ 'crash 3: [OK]',
+ \ 'crash 4: [OK]',
\ ]
call assert_equal(expected, getline(1, '$'))
diff --git a/test/old/testdir/test_cursor_func.vim b/test/old/testdir/test_cursor_func.vim
index cf131e8dad..5d99963814 100644
--- a/test/old/testdir/test_cursor_func.vim
+++ b/test/old/testdir/test_cursor_func.vim
@@ -206,6 +206,11 @@ func Test_screenpos()
call assert_equal(#{col: 1, row: 2, endcol: 1, curscol: 1}, screenpos(win_getid(), 1, 1))
" nunmenu WinBar.TEST
setlocal winbar&
+ call assert_equal(#{col: 1, row: 1, endcol: 1, curscol: 1}, screenpos(win_getid(), 1, 1))
+
+ call assert_equal(#{col: 0, row: 0, endcol: 0, curscol: 0}, screenpos(0, 0, 1))
+ call assert_equal(#{col: 0, row: 0, endcol: 0, curscol: 0}, screenpos(0, -1, 1))
+ call assert_equal(#{col: 1, row: 1, endcol: 1, curscol: 1}, screenpos(0, 1, -v:maxcol))
endfunc
func Test_screenpos_fold()
diff --git a/test/old/testdir/test_diffmode.vim b/test/old/testdir/test_diffmode.vim
index fd94f4a7b2..9a3e006430 100644
--- a/test/old/testdir/test_diffmode.vim
+++ b/test/old/testdir/test_diffmode.vim
@@ -1083,18 +1083,19 @@ endfunc
func Test_diff_with_cursorline_breakindent()
CheckScreendump
- call writefile([
- \ 'hi CursorLine ctermbg=red ctermfg=white',
- \ 'set noequalalways wrap diffopt=followwrap cursorline breakindent',
- \ '50vnew',
- \ 'call setline(1, [" "," "," "," "])',
- \ 'exe "norm 20Afoo\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abar\<Esc>"',
- \ 'vnew',
- \ 'call setline(1, [" "," "," "," "])',
- \ 'exe "norm 20Abee\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abaz\<Esc>"',
- \ 'windo diffthis',
- \ '2wincmd w',
- \ ], 'Xtest_diff_cursorline_breakindent', 'D')
+ let lines =<< trim END
+ hi CursorLine ctermbg=red ctermfg=white
+ set noequalalways wrap diffopt=followwrap cursorline breakindent
+ 50vnew
+ call setline(1, [' ', ' ', ' ', ' '])
+ exe "norm! 20Afoo\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abar\<Esc>"
+ vnew
+ call setline(1, [' ', ' ', ' ', ' '])
+ exe "norm! 20Abee\<Esc>j20Afoo\<Esc>j20Afoo\<Esc>j20Abaz\<Esc>"
+ windo diffthis
+ 2wincmd w
+ END
+ call writefile(lines, 'Xtest_diff_cursorline_breakindent', 'D')
let buf = RunVimInTerminal('-S Xtest_diff_cursorline_breakindent', {})
call term_sendkeys(buf, "gg0")
@@ -1110,11 +1111,30 @@ func Test_diff_with_cursorline_breakindent()
call StopVimInTerminal(buf)
endfunc
+func Test_diff_breakindent_after_filler()
+ CheckScreendump
+
+ let lines =<< trim END
+ set laststatus=0 diffopt+=followwrap breakindent breakindentopt=min:0
+ call setline(1, ['a', ' ' .. repeat('c', 50)])
+ vnew
+ call setline(1, ['a', 'b', ' ' .. repeat('c', 50)])
+ windo diffthis
+ norm! G$
+ END
+ call writefile(lines, 'Xtest_diff_breakindent_after_filler', 'D')
+ let buf = RunVimInTerminal('-S Xtest_diff_breakindent_after_filler', #{rows: 8, cols: 45})
+ call VerifyScreenDump(buf, 'Test_diff_breakindent_after_filler', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
+endfunc
+
func Test_diff_with_syntax()
CheckScreendump
let lines =<< trim END
- void doNothing() {
+ void doNothing() {
int x = 0;
char *s = "hello";
return 5;
@@ -1122,7 +1142,7 @@ func Test_diff_with_syntax()
END
call writefile(lines, 'Xprogram1.c', 'D')
let lines =<< trim END
- void doSomething() {
+ void doSomething() {
int x = 0;
char *s = "there";
return 5;
@@ -1131,7 +1151,7 @@ func Test_diff_with_syntax()
call writefile(lines, 'Xprogram2.c', 'D')
let lines =<< trim END
- edit Xprogram1.c
+ edit Xprogram1.c
diffsplit Xprogram2.c
END
call writefile(lines, 'Xtest_diff_syntax', 'D')
diff --git a/test/old/testdir/test_display.vim b/test/old/testdir/test_display.vim
index bd90287400..70029dcf3c 100644
--- a/test/old/testdir/test_display.vim
+++ b/test/old/testdir/test_display.vim
@@ -253,12 +253,12 @@ func Test_eob_fillchars()
" default value
" call assert_match('eob:\~', &fillchars)
" invalid values
- call assert_fails(':set fillchars=eob:', 'E474:')
- call assert_fails(':set fillchars=eob:xy', 'E474:')
- call assert_fails(':set fillchars=eob:\255', 'E474:')
- call assert_fails(':set fillchars=eob:<ff>', 'E474:')
- call assert_fails(":set fillchars=eob:\x01", 'E474:')
- call assert_fails(':set fillchars=eob:\\x01', 'E474:')
+ call assert_fails(':set fillchars=eob:', 'E1511:')
+ call assert_fails(':set fillchars=eob:xy', 'E1511:')
+ call assert_fails(':set fillchars=eob:\255', 'E1511:')
+ call assert_fails(':set fillchars=eob:<ff>', 'E1511:')
+ call assert_fails(":set fillchars=eob:\x01", 'E1512:')
+ call assert_fails(':set fillchars=eob:\\x01', 'E1512:')
" default is ~
new
redraw
@@ -412,14 +412,16 @@ func Run_Test_display_lastline(euro)
call StopVimInTerminal(buf)
endfunc
-func Test_display_lastline()
+func Test_display_lastline_dump()
CheckScreendump
call Run_Test_display_lastline('')
call Run_Test_display_lastline('euro_')
+endfunc
- call assert_fails(':set fillchars=lastline:', 'E474:')
- call assert_fails(':set fillchars=lastline:〇', 'E474:')
+func Test_display_lastline_fails()
+ call assert_fails(':set fillchars=lastline:', 'E1511:')
+ call assert_fails(':set fillchars=lastline:〇', 'E1512:')
endfunc
func Test_display_long_lastline()
diff --git a/test/old/testdir/test_edit.vim b/test/old/testdir/test_edit.vim
index 3fe65832c9..67143ab524 100644
--- a/test/old/testdir/test_edit.vim
+++ b/test/old/testdir/test_edit.vim
@@ -2118,5 +2118,39 @@ func Test_edit_overlong_file_name()
bwipe!
endfunc
+func Test_edit_Ctrl_RSB()
+ new
+ let g:triggered = []
+ autocmd InsertCharPre <buffer> let g:triggered += [v:char]
+
+ " i_CTRL-] should not trigger InsertCharPre
+ exe "normal! A\<C-]>"
+ call assert_equal([], g:triggered)
+
+ " i_CTRL-] should expand abbreviations but not trigger InsertCharPre
+ inoreabbr <buffer> f foo
+ exe "normal! Af\<C-]>a"
+ call assert_equal(['f', 'f', 'o', 'o', 'a'], g:triggered)
+ call assert_equal('fooa', getline(1))
+
+ " CTRL-] followed by i_CTRL-V should not expand abbreviations
+ " i_CTRL-V doesn't trigger InsertCharPre
+ call setline(1, '')
+ exe "normal! Af\<C-V>\<C-]>"
+ call assert_equal("f\<C-]>", getline(1))
+
+ let g:triggered = []
+ call setline(1, '')
+
+ " Also test assigning to v:char
+ autocmd InsertCharPre <buffer> let v:char = 'f'
+ exe "normal! Ag\<C-]>h"
+ call assert_equal(['g', 'f', 'o', 'o', 'h'], g:triggered)
+ call assert_equal('ffff', getline(1))
+
+ autocmd! InsertCharPre
+ unlet g:triggered
+ bwipe!
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_excmd.vim b/test/old/testdir/test_excmd.vim
index c729ff4929..b7356c22fa 100644
--- a/test/old/testdir/test_excmd.vim
+++ b/test/old/testdir/test_excmd.vim
@@ -90,23 +90,31 @@ endfunc
" Test for the :drop command
func Test_drop_cmd()
- call writefile(['L1', 'L2'], 'Xfile')
+ call writefile(['L1', 'L2'], 'Xdropfile', 'D')
+ " Test for reusing the current buffer
enew | only
- drop Xfile
+ let expected_nr = bufnr()
+ drop Xdropfile
+ call assert_equal(expected_nr, bufnr())
call assert_equal('L2', getline(2))
" Test for switching to an existing window
below new
- drop Xfile
+ drop Xdropfile
call assert_equal(1, winnr())
- " Test for splitting the current window
+ " Test for splitting the current window (set nohidden)
enew | only
set modified
- drop Xfile
+ drop Xdropfile
call assert_equal(2, winnr('$'))
+ " Not splitting the current window even if modified (set hidden)
+ set hidden
+ enew | only
+ set modified
+ drop Xdropfile
+ call assert_equal(1, winnr('$'))
" Check for setting the argument list
- call assert_equal(['Xfile'], argv())
+ call assert_equal(['Xdropfile'], argv())
enew | only!
- call delete('Xfile')
endfunc
" Test for the :append command
diff --git a/test/old/testdir/test_filetype.vim b/test/old/testdir/test_filetype.vim
index 87044a06b5..303b1585e2 100644
--- a/test/old/testdir/test_filetype.vim
+++ b/test/old/testdir/test_filetype.vim
@@ -140,6 +140,7 @@ func s:GetFilenameChecks() abort
\ 'chatito': ['file.chatito'],
\ 'chill': ['file..ch'],
\ 'chordpro': ['file.chopro', 'file.crd', 'file.cho', 'file.crdpro', 'file.chordpro'],
+ \ 'chuck': ['file.ck'],
\ 'cl': ['file.eni'],
\ 'clean': ['file.dcl', 'file.icl'],
\ 'clojure': ['file.clj', 'file.cljs', 'file.cljx', 'file.cljc'],
@@ -203,7 +204,7 @@ func s:GetFilenameChecks() abort
\ 'dracula': ['file.drac', 'file.drc', 'filelvs', 'filelpe', 'drac.file', 'lpe', 'lvs', 'some-lpe', 'some-lvs'],
\ 'dtd': ['file.dtd'],
\ 'dtrace': ['/usr/lib/dtrace/io.d'],
- \ 'dts': ['file.dts', 'file.dtsi'],
+ \ 'dts': ['file.dts', 'file.dtsi', 'file.dtso', 'file.its'],
\ 'dune': ['jbuild', 'dune', 'dune-project', 'dune-workspace'],
\ 'dylan': ['file.dylan'],
\ 'dylanintr': ['file.intr'],
@@ -226,6 +227,7 @@ func s:GetFilenameChecks() abort
\ 'esqlc': ['file.ec', 'file.EC'],
\ 'esterel': ['file.strl'],
\ 'eterm': ['anyEterm/file.cfg', 'Eterm/file.cfg', 'some-Eterm/file.cfg'],
+ \ 'execline': ['/etc/s6-rc/run', './s6-rc/src/dbus-srv/up', '/sbin/s6-shutdown'],
\ 'exim': ['exim.conf'],
\ 'expect': ['file.exp'],
\ 'exports': ['exports'],
@@ -308,7 +310,7 @@ func s:GetFilenameChecks() abort
\ 'hoon': ['file.hoon'],
\ 'hostconf': ['/etc/host.conf', 'any/etc/host.conf'],
\ 'hostsaccess': ['/etc/hosts.allow', '/etc/hosts.deny', 'any/etc/hosts.allow', 'any/etc/hosts.deny'],
- \ 'html': ['file.html', 'file.htm', 'file.cshtml'],
+ \ 'html': ['file.html', 'file.htm', 'file.cshtml', 'file.component.html'],
\ 'htmlm4': ['file.html.m4'],
\ 'httest': ['file.htt', 'file.htb'],
\ 'hurl': ['file.hurl'],
@@ -339,13 +341,13 @@ func s:GetFilenameChecks() abort
\ 'jproperties': ['file.properties', 'file.properties_xx', 'file.properties_xx_xx', 'some.properties_xx_xx_file', 'org.eclipse.xyz.prefs'],
\ 'json': ['file.json', 'file.jsonp', 'file.json-patch', 'file.geojson', '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'],
+ \ 'jsonc': ['file.jsonc', '.babelrc', '.eslintrc', '.jsfmtrc', '.jshintrc', '.hintrc', '.swrc', 'jsconfig.json', 'tsconfig.json', 'tsconfig.test.json', 'tsconfig-test.json', '.luaurc'],
\ 'jsonl': ['file.jsonl'],
\ 'jsonnet': ['file.jsonnet', 'file.libsonnet'],
\ 'jsp': ['file.jsp'],
\ 'julia': ['file.jl'],
\ 'just': ['justfile', 'Justfile', '.justfile', 'config.just'],
- \ 'kconfig': ['Kconfig', 'Kconfig.debug', 'Kconfig.file'],
+ \ 'kconfig': ['Kconfig', 'Kconfig.debug', 'Kconfig.file', 'Config.in', 'Config.in.host'],
\ 'kdl': ['file.kdl'],
\ 'kivy': ['file.kv'],
\ 'kix': ['file.kix'],
@@ -423,7 +425,6 @@ func s:GetFilenameChecks() abort
\ 'mma': ['file.nb'],
\ 'mmp': ['file.mmp'],
\ 'modconf': ['/etc/modules.conf', '/etc/modules', '/etc/conf.modules', '/etc/modprobe.file', 'any/etc/conf.modules', 'any/etc/modprobe.file', 'any/etc/modules', 'any/etc/modules.conf'],
- \ 'modula2': ['file.m2', 'file.mi'],
\ 'modula3': ['file.m3', 'file.mg', 'file.i3', 'file.ig', 'file.lm3'],
\ 'monk': ['file.isc', 'file.monk', 'file.ssc', 'file.tsc'],
\ 'moo': ['file.moo'],
@@ -437,6 +438,7 @@ func s:GetFilenameChecks() abort
\ 'mojo': ['file.mojo', 'file.🔥'],
\ 'mupad': ['file.mu'],
\ 'mush': ['file.mush'],
+ \ 'mustache': ['file.mustache'],
\ 'muttrc': ['Muttngrc', 'Muttrc', '.muttngrc', '.muttngrc-file', '.muttrc', '.muttrc-file', '/.mutt/muttngrc', '/.mutt/muttngrc-file', '/.mutt/muttrc', '/.mutt/muttrc-file', '/.muttng/muttngrc', '/.muttng/muttngrc-file', '/.muttng/muttrc', '/.muttng/muttrc-file', '/etc/Muttrc.d/file', '/etc/Muttrc.d/file.rc', 'Muttngrc-file', 'Muttrc-file', 'any/.mutt/muttngrc', 'any/.mutt/muttngrc-file', 'any/.mutt/muttrc', 'any/.mutt/muttrc-file', 'any/.muttng/muttngrc', 'any/.muttng/muttngrc-file', 'any/.muttng/muttrc', 'any/.muttng/muttrc-file', 'any/etc/Muttrc.d/file', 'muttngrc', 'muttngrc-file', 'muttrc', 'muttrc-file'],
\ 'mysql': ['file.mysql'],
\ 'n1ql': ['file.n1ql', 'file.nql'],
@@ -470,6 +472,7 @@ func s:GetFilenameChecks() abort
\ 'opl': ['file.OPL', 'file.OPl', 'file.OpL', 'file.Opl', 'file.oPL', 'file.oPl', 'file.opL', 'file.opl'],
\ 'ora': ['file.ora'],
\ 'org': ['file.org', 'file.org_archive'],
+ \ 'pacmanlog': ['pacman.log'],
\ 'pamconf': ['/etc/pam.conf', '/etc/pam.d/file', 'any/etc/pam.conf', 'any/etc/pam.d/file'],
\ 'pamenv': ['/etc/security/pam_env.conf', '/home/user/.pam_environment', '.pam_environment', 'pam_env.conf'],
\ 'papp': ['file.papp', 'file.pxml', 'file.pxsl'],
@@ -578,7 +581,7 @@ func s:GetFilenameChecks() abort
\ 'services': ['/etc/services', 'any/etc/services'],
\ 'setserial': ['/etc/serial.conf', 'any/etc/serial.conf'],
\ 'sexplib': ['file.sexp'],
- \ 'sh': ['.bashrc', '.bash_profile', '.bash-profile', '.bash_logout', '.bash-logout', '.bash_aliases', '.bash-aliases', '/tmp/bash-fc-3Ozjlw', '/tmp/bash-fc.3Ozjlw', 'PKGBUILD', 'APKBUILD', 'file.bash', '/usr/share/doc/bash-completion/filter.sh', '/etc/udev/cdsymlinks.conf', 'any/etc/udev/cdsymlinks.conf'],
+ \ 'sh': ['.bashrc', '.bash_profile', '.bash-profile', '.bash_logout', '.bash-logout', '.bash_aliases', '.bash-aliases', '/tmp/bash-fc-3Ozjlw', '/tmp/bash-fc.3Ozjlw', 'PKGBUILD', 'APKBUILD', 'file.bash', '/usr/share/doc/bash-completion/filter.sh', '/etc/udev/cdsymlinks.conf', 'any/etc/udev/cdsymlinks.conf', 'file.bats'],
\ 'sieve': ['file.siv', 'file.sieve'],
\ 'sil': ['file.sil'],
\ 'simula': ['file.sim'],
@@ -826,6 +829,7 @@ let s:script_checks = {
\ ['#!/path/itclsh'],
\ ['#!/path/itkwish']],
\ 'expect': [['#!/path/expect']],
+ \ 'execline': [['#!/sbin/execlineb -S0'], ['#!/usr/bin/execlineb']],
\ 'gnuplot': [['#!/path/gnuplot']],
\ 'make': [['#!/path/make']],
\ 'nix': [['#!/path/nix-shell']],
@@ -877,6 +881,7 @@ let s:script_env_checks = {
\ 'perl': [['#!/usr/bin/env VAR=val perl']],
\ 'scala': [['#!/usr/bin/env VAR=val VVAR=vval scala']],
\ 'awk': [['#!/usr/bin/env VAR=val -i awk']],
+ \ 'execline': [['#!/usr/bin/env execlineb']],
\ 'scheme': [['#!/usr/bin/env VAR=val --ignore-environment scheme']],
\ 'python': [['#!/usr/bin/env VAR=val -S python -w -T']],
\ 'wml': [['#!/usr/bin/env VAR=val --split-string wml']],
@@ -1506,79 +1511,89 @@ func Test_mod_file()
filetype on
" *.mod defaults to Modsim III
- call writefile(['locks like Modsim III'], 'modfile.mod')
- split modfile.mod
+ call writefile(['locks like Modsim III'], 'Xfile.mod', 'D')
+ split Xfile.mod
call assert_equal('modsim3', &filetype)
bwipe!
" Users preference set by g:filetype_mod
let g:filetype_mod = 'lprolog'
- split modfile.mod
+ split Xfile.mod
call assert_equal('lprolog', &filetype)
unlet g:filetype_mod
bwipe!
+ " LambdaProlog module
+ call writefile(['module lpromod.'], 'Xfile.mod')
+ split Xfile.mod
+ call assert_equal('lprolog', &filetype)
+ bwipe!
+
+ " LambdaProlog with comment and empty lines prior module
+ call writefile(['', '% with', '% comment', '', 'module lpromod.'], 'Xfile.mod')
+ split Xfile.mod
+ call assert_equal('lprolog', &filetype)
+ bwipe!
+
" RAPID header start with a line containing only "%%%",
" but is not always present.
- call writefile(['%%%'], 'modfile.mod')
- split modfile.mod
+ call writefile(['%%%'], 'Xfile.mod')
+ split Xfile.mod
call assert_equal('rapid', &filetype)
bwipe!
- call delete('modfile.mod')
" RAPID supports umlauts in module names, leading spaces,
" the .mod extension is not case sensitive.
- call writefile([' module ÜmlautModule'], 'modfile.Mod')
- split modfile.Mod
+ call writefile([' module ÜmlautModule'], 'Xfile.Mod', 'D')
+ split Xfile.Mod
call assert_equal('rapid', &filetype)
bwipe!
- call delete('modfile.Mod')
" RAPID is not case sensitive, embedded spaces, sysmodule,
" file starts with empty line(s).
- call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'modfile.MOD')
- split modfile.MOD
+ call writefile(['', 'MODULE rapidmödüle (SYSMODULE,NOSTEPIN)'], 'Xfile.MOD', 'D')
+ split Xfile.MOD
call assert_equal('rapid', &filetype)
bwipe!
" Modula-2 MODULE not start of line
- call writefile(['IMPLEMENTATION MODULE Module2Mod;'], 'modfile.MOD')
- split modfile.MOD
+ call writefile(['IMPLEMENTATION MODULE Module2Mod;'], 'Xfile.mod')
+ split Xfile.mod
call assert_equal('modula2', &filetype)
+ call assert_equal('pim', b:modula2.dialect)
bwipe!
" Modula-2 with comment and empty lines prior MODULE
- call writefile(['', '(* with', ' comment *)', '', 'MODULE Module2Mod;'], 'modfile.MOD')
- split modfile.MOD
+ call writefile(['', '(* with', ' comment *)', '', 'MODULE Module2Mod;'], 'Xfile.mod')
+ split Xfile.mod
call assert_equal('modula2', &filetype)
+ call assert_equal('pim', b:modula2.dialect)
bwipe!
- call delete('modfile.MOD')
- " LambdaProlog module
- call writefile(['module lpromod.'], 'modfile.mod')
- split modfile.mod
- call assert_equal('lprolog', &filetype)
+ " Modula-2 program MODULE with priorty (and uppercase extension)
+ call writefile(['MODULE Module2Mod [42];'], 'Xfile.MOD')
+ split Xfile.MOD
+ call assert_equal('modula2', &filetype)
+ call assert_equal('pim', b:modula2.dialect)
bwipe!
- " LambdaProlog with comment and empty lines prior module
- call writefile(['', '% with', '% comment', '', 'module lpromod.'], 'modfile.mod')
- split modfile.mod
- call assert_equal('lprolog', &filetype)
+ " Modula-2 implementation MODULE with priorty (and uppercase extension)
+ call writefile(['IMPLEMENTATION MODULE Module2Mod [42];'], 'Xfile.MOD')
+ split Xfile.MOD
+ call assert_equal('modula2', &filetype)
+ call assert_equal('pim', b:modula2.dialect)
bwipe!
- call delete('modfile.mod')
" go.mod
- call writefile(['module example.com/M'], 'go.mod')
+ call writefile(['module example.com/M'], 'go.mod', 'D')
split go.mod
call assert_equal('gomod', &filetype)
bwipe!
- call delete('go.mod')
call writefile(['module M'], 'go.mod')
split go.mod
call assert_equal('gomod', &filetype)
bwipe!
- call delete('go.mod')
filetype off
endfunc
@@ -2279,4 +2294,38 @@ func Test_i_file()
filetype off
endfunc
+func Test_def_file()
+ filetype on
+
+ call writefile(['this is the fallback'], 'Xfile.def', 'D')
+ split Xfile.def
+ call assert_equal('def', &filetype)
+ bwipe!
+
+ " Test dist#ft#FTdef()
+
+ let g:filetype_def = 'modula2'
+ split Xfile.def
+ call assert_equal('modula2', &filetype)
+ call assert_equal('pim', b:modula2.dialect)
+ bwipe!
+ unlet g:filetype_def
+
+ " Modula-2
+
+ call writefile(['(* a Modula-2 comment *)'], 'Xfile.def')
+ split Xfile.def
+ call assert_equal('modula2', &filetype)
+ call assert_equal('pim', b:modula2.dialect)
+ bwipe!
+
+ call writefile(['IMPLEMENTATION MODULE Module2Mod;'], 'Xfile.def')
+ split Xfile.def
+ call assert_equal('modula2', &filetype)
+ call assert_equal('pim', b:modula2.dialect)
+ bwipe!
+
+ filetype off
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_filter_map.vim b/test/old/testdir/test_filter_map.vim
index 7658797759..5ef56c5623 100644
--- a/test/old/testdir/test_filter_map.vim
+++ b/test/old/testdir/test_filter_map.vim
@@ -14,6 +14,18 @@ func Test_filter_map_list_expr_string()
call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], 'v:key * 2'))
call assert_equal([9, 9, 9, 9], map([1, 2, 3, 4], 9))
call assert_equal([7, 7, 7], map([1, 2, 3], ' 7 '))
+
+ " foreach()
+ let list01 = [1, 2, 3, 4]
+ let list02 = []
+ call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(list02, v:val * 2)'))
+ call assert_equal([2, 4, 6, 8], list02)
+ let list02 = []
+ call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(list02, v:key * 2)'))
+ call assert_equal([0, 2, 4, 6], list02)
+ let list02 = []
+ call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(list02, 9)'))
+ call assert_equal([9, 9, 9, 9], list02)
endfunc
" dict with expression string
@@ -29,6 +41,14 @@ func Test_filter_map_dict_expr_string()
call assert_equal({"foo": 2, "bar": 4, "baz": 6}, map(copy(dict), 'v:val * 2'))
call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), 'v:key[0]'))
call assert_equal({"foo": 9, "bar": 9, "baz": 9}, map(copy(dict), 9))
+
+ " foreach()
+ let dict01 = {}
+ call assert_equal(dict, foreach(copy(dict), 'let dict01[v:key] = v:val * 2'))
+ call assert_equal({"foo": 2, "bar": 4, "baz": 6}, dict01)
+ let dict01 = {}
+ call assert_equal(dict, foreach(copy(dict), 'let dict01[v:key] = v:key[0]'))
+ call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, dict01)
endfunc
" list with funcref
@@ -54,6 +74,25 @@ func Test_filter_map_list_expr_funcref()
return a:index * 2
endfunc
call assert_equal([0, 2, 4, 6], map([1, 2, 3, 4], function('s:filter4')))
+
+ " foreach()
+ func! s:foreach1(index, val) abort
+ call add(g:test_variable, a:val + 1)
+ return [ 11, 12, 13, 14 ]
+ endfunc
+ let g:test_variable = []
+ call assert_equal([0, 1, 2, 3, 4], foreach(range(5), function('s:foreach1')))
+ call assert_equal([1, 2, 3, 4, 5], g:test_variable)
+ call remove(g:, 'test_variable')
+endfunc
+
+func Test_filter_map_nested()
+ let x = {"x":10}
+ let r = map(range(2), 'filter(copy(x), "1")')
+ call assert_equal([x, x], r)
+
+ let r = map(copy(x), 'filter(copy(x), "1")')
+ call assert_equal({"x": x}, r)
endfunc
" dict with funcref
@@ -81,11 +120,46 @@ func Test_filter_map_dict_expr_funcref()
return a:key[0]
endfunc
call assert_equal({"foo": "f", "bar": "b", "baz": "b"}, map(copy(dict), function('s:filter4')))
+
+ " foreach()
+ func! s:foreach1(key, val) abort
+ call extend(g:test_variable, {a:key: a:val * 2})
+ return [ 11, 12, 13, 14 ]
+ endfunc
+ let g:test_variable = {}
+ call assert_equal(dict, foreach(copy(dict), function('s:foreach1')))
+ call assert_equal({"foo": 2, "bar": 4, "baz": 6}, g:test_variable)
+ call remove(g:, 'test_variable')
+endfunc
+
+func Test_map_filter_locked()
+ let list01 = [1, 2, 3, 4]
+ lockvar 1 list01
+ call assert_fails('call filter(list01, "v:val > 1")', 'E741:')
+ call assert_equal([2, 4, 6, 8], map(list01, 'v:val * 2'))
+ call assert_equal([1, 2, 3, 4], map(list01, 'v:val / 2'))
+ call assert_equal([2, 4, 6, 8], mapnew(list01, 'v:val * 2'))
+ let g:test_variable = []
+ call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(g:test_variable, v:val * 2)'))
+ call remove(g:, 'test_variable')
+ call assert_fails('call filter(list01, "v:val > 1")', 'E741:')
+ unlockvar 1 list01
+ lockvar! list01
+ call assert_fails('call filter(list01, "v:val > 1")', 'E741:')
+ call assert_fails('call map(list01, "v:val * 2")', 'E741:')
+ call assert_equal([2, 4, 6, 8], mapnew(list01, 'v:val * 2'))
+ let g:test_variable = []
+ call assert_equal([1, 2, 3, 4], foreach(list01, 'call add(g:test_variable, v:val * 2)'))
+ call assert_fails('call foreach(list01, "let list01[0] = -1")', 'E741:')
+ call assert_fails('call filter(list01, "v:val > 1")', 'E741:')
+ call remove(g:, 'test_variable')
+ unlockvar! list01
endfunc
func Test_map_filter_fails()
call assert_fails('call map([1], "42 +")', 'E15:')
call assert_fails('call filter([1], "42 +")', 'E15:')
+ call assert_fails('call foreach([1], "let a = }")', 'E15:')
call assert_fails("let l = filter([1, 2, 3], '{}')", 'E728:')
call assert_fails("let l = filter({'k' : 10}, '{}')", 'E728:')
call assert_fails("let l = filter([1, 2], {})", 'E731:')
@@ -99,6 +173,8 @@ func Test_map_filter_fails()
" Nvim doesn't have null partials
" call assert_equal([1, 2, 3], filter([1, 2, 3], test_null_partial()))
call assert_fails("let l = filter([1, 2], {a, b, c -> 1})", 'E119:')
+ call assert_fails('call foreach([1], "xyzzy")', 'E492:')
+ call assert_fails('call foreach([1], "let a = foo")', 'E121:')
endfunc
func Test_map_and_modify()
@@ -116,7 +192,7 @@ endfunc
func Test_filter_and_modify()
let l = [0]
- " cannot change the list halfway a map()
+ " cannot change the list halfway thru filter()
call assert_fails('call filter(l, "remove(l, 0)")', 'E741:')
let d = #{a: 0, b: 0, c: 0}
@@ -126,6 +202,18 @@ func Test_filter_and_modify()
call assert_fails('call filter(b, "remove(b, 0)")', 'E741:')
endfunc
+func Test_foreach_and_modify()
+ let l = [0]
+ " cannot change the list halfway thru foreach()
+ call assert_fails('call foreach(l, "let a = remove(l, 0)")', 'E741:')
+
+ let d = #{a: 0, b: 0, c: 0}
+ call assert_fails('call foreach(d, "let a = remove(d, v:key)")', 'E741:')
+
+ let b = 0z1234
+ call assert_fails('call foreach(b, "let a = remove(b, 0)")', 'E741:')
+endfunc
+
func Test_mapnew_dict()
let din = #{one: 1, two: 2}
let dout = mapnew(din, {k, v -> string(v)})
@@ -153,6 +241,36 @@ func Test_mapnew_blob()
call assert_equal(0z129956, bout)
endfunc
+func Test_foreach_blob()
+ let lines =<< trim END
+ LET g:test_variable = []
+ call assert_equal(0z0001020304, foreach(0z0001020304, 'call add(g:test_variable, v:val)'))
+ call assert_equal([0, 1, 2, 3, 4], g:test_variable)
+ END
+ call CheckLegacyAndVim9Success(lines)
+
+ func! s:foreach1(index, val) abort
+ call add(g:test_variable, a:val)
+ return [ 11, 12, 13, 14 ]
+ endfunc
+ let g:test_variable = []
+ call assert_equal(0z0001020304, foreach(0z0001020304, function('s:foreach1')))
+ call assert_equal([0, 1, 2, 3, 4], g:test_variable)
+
+ let lines =<< trim END
+ def Foreach1(_, val: any): list<number>
+ add(g:test_variable, val)
+ return [ 11, 12, 13, 14 ]
+ enddef
+ g:test_variable = []
+ assert_equal(0z0001020304, foreach(0z0001020304, Foreach1))
+ assert_equal([0, 1, 2, 3, 4], g:test_variable)
+ END
+ call CheckDefSuccess(lines)
+
+ call remove(g:, 'test_variable')
+endfunc
+
" Test for using map(), filter() and mapnew() with a string
func Test_filter_map_string()
" filter()
@@ -212,6 +330,37 @@ func Test_filter_map_string()
END
call CheckLegacyAndVim9Success(lines)
+ " foreach()
+ let lines =<< trim END
+ VAR s = "abc"
+ LET g:test_variable = []
+ call assert_equal(s, foreach(s, 'call add(g:test_variable, v:val)'))
+ call assert_equal(['a', 'b', 'c'], g:test_variable)
+ LET g:test_variable = []
+ LET s = 'ã‚iã†ãˆãŠ'
+ call assert_equal(s, foreach(s, 'call add(g:test_variable, v:val)'))
+ call assert_equal(['ã‚', 'i', 'ã†', 'ãˆ', 'ãŠ'], g:test_variable)
+ END
+ call CheckLegacyAndVim9Success(lines)
+ func! s:foreach1(index, val) abort
+ call add(g:test_variable, a:val)
+ return [ 11, 12, 13, 14 ]
+ endfunc
+ let g:test_variable = []
+ call assert_equal('abcd', foreach('abcd', function('s:foreach1')))
+ call assert_equal(['a', 'b', 'c', 'd'], g:test_variable)
+ let lines =<< trim END
+ def Foreach1(_, val: string): list<number>
+ add(g:test_variable, val)
+ return [ 11, 12, 13, 14 ]
+ enddef
+ g:test_variable = []
+ assert_equal('abcd', foreach('abcd', Foreach1))
+ assert_equal(['a', 'b', 'c', 'd'], g:test_variable)
+ END
+ call CheckDefSuccess(lines)
+ call remove(g:, 'test_variable')
+
let lines =<< trim END
#" map() and filter()
call assert_equal('[ã‚][âˆ][a][😊][â‰][💕][💕][b][💕]', map(filter('ã‚xâˆax😊xâ‰ðŸ’•💕b💕x', '"x" != v:val'), '"[" .. v:val .. "]"'))
diff --git a/test/old/testdir/test_fold.vim b/test/old/testdir/test_fold.vim
index e529a94174..eae6952e72 100644
--- a/test/old/testdir/test_fold.vim
+++ b/test/old/testdir/test_fold.vim
@@ -1578,4 +1578,17 @@ func Test_foldexpr_return_empty_string()
bwipe!
endfunc
+" Make sure that when ending a fold that hasn't been started, it does not
+" start a new fold.
+func Test_foldexpr_end_fold()
+ new
+ setlocal foldmethod=expr
+ let &l:foldexpr = 'v:lnum == 2 ? "<2" : "="'
+ call setline(1, range(1, 3))
+ redraw
+ call assert_equal([0, 0, 0], range(1, 3)->map('foldlevel(v:val)'))
+
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_functions.vim b/test/old/testdir/test_functions.vim
index 88a29968fe..3f9ac94782 100644
--- a/test/old/testdir/test_functions.vim
+++ b/test/old/testdir/test_functions.vim
@@ -1044,6 +1044,192 @@ func Test_matchstrpos()
call assert_equal(['', -1, -1], matchstrpos(v:_null_list, '\a'))
endfunc
+" Test for matchstrlist()
+func Test_matchstrlist()
+ let lines =<< trim END
+ #" Basic match
+ call assert_equal([{'idx': 0, 'byteidx': 1, 'text': 'bout'},
+ \ {'idx': 1, 'byteidx': 1, 'text': 'bove'}],
+ \ matchstrlist(['about', 'above'], 'bo.*'))
+ #" no match
+ call assert_equal([], matchstrlist(['about', 'above'], 'xy.*'))
+ #" empty string
+ call assert_equal([], matchstrlist([''], '.'))
+ #" empty pattern
+ call assert_equal([{'idx': 0, 'byteidx': 0, 'text': ''}], matchstrlist(['abc'], ''))
+ #" method call
+ call assert_equal([{'idx': 0, 'byteidx': 2, 'text': 'it'}], ['editor']->matchstrlist('ed\zsit\zeor'))
+ #" single character matches
+ call assert_equal([{'idx': 0, 'byteidx': 5, 'text': 'r'}],
+ \ ['editor']->matchstrlist('r'))
+ call assert_equal([{'idx': 0, 'byteidx': 0, 'text': 'a'}], ['a']->matchstrlist('a'))
+ call assert_equal([{'idx': 0, 'byteidx': 0, 'text': ''}],
+ \ matchstrlist(['foobar'], '\zs'))
+ #" string with tabs
+ call assert_equal([{'idx': 0, 'byteidx': 1, 'text': 'foo'}],
+ \ matchstrlist(["\tfoobar"], 'foo'))
+ #" string with multibyte characters
+ call assert_equal([{'idx': 0, 'byteidx': 2, 'text': '😊😊'}],
+ \ matchstrlist(["\t\t😊😊"], '\k\+'))
+
+ #" null string
+ call assert_equal([], matchstrlist(v:_null_list, 'abc'))
+ call assert_equal([], matchstrlist([v:_null_string], 'abc'))
+ call assert_equal([{'idx': 0, 'byteidx': 0, 'text': ''}],
+ \ matchstrlist(['abc'], v:_null_string))
+
+ #" sub matches
+ call assert_equal([{'idx': 0, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}], matchstrlist(['acd'], '\(a\)\?\(b\)\?\(c\)\?\(.*\)', {'submatches': v:true}))
+
+ #" null dict argument
+ call assert_equal([{'idx': 0, 'byteidx': 0, 'text': 'vim'}],
+ \ matchstrlist(['vim'], '\w\+', v:_null_dict))
+
+ #" Error cases
+ call assert_fails("echo matchstrlist('abc', 'a')", 'E1211: List required for argument 1')
+ call assert_fails("echo matchstrlist(['abc'], {})", 'E1174: String required for argument 2')
+ call assert_fails("echo matchstrlist(['abc'], '.', [])", 'E1206: Dictionary required for argument 3')
+ call assert_fails("echo matchstrlist(['abc'], 'a', {'submatches': []})", 'E475: Invalid value for argument submatches')
+ call assert_fails("echo matchstrlist(['abc'], '\\@=')", 'E866: (NFA regexp) Misplaced @')
+ END
+ call CheckLegacyAndVim9Success(lines)
+
+ let lines =<< trim END
+ vim9script
+ # non string items
+ matchstrlist([0z10, {'a': 'x'}], 'x')
+ END
+ call CheckSourceSuccess(lines)
+
+ let lines =<< trim END
+ vim9script
+ def Foo()
+ # non string items
+ assert_equal([], matchstrlist([0z10, {'a': 'x'}], 'x'))
+ enddef
+ Foo()
+ END
+ call CheckSourceFailure(lines, 'E1013: Argument 1: type mismatch, expected list<string> but got list<any>', 2)
+endfunc
+
+" Test for matchbufline()
+func Test_matchbufline()
+ let lines =<< trim END
+ #" Basic match
+ new
+ call setline(1, ['about', 'above', 'below'])
+ VAR bnr = bufnr()
+ wincmd w
+ call assert_equal([{'lnum': 1, 'byteidx': 1, 'text': 'bout'},
+ \ {'lnum': 2, 'byteidx': 1, 'text': 'bove'}],
+ \ matchbufline(bnr, 'bo.*', 1, '$'))
+ #" multiple matches in a line
+ call setbufline(bnr, 1, ['about about', 'above above', 'below'])
+ call assert_equal([{'lnum': 1, 'byteidx': 1, 'text': 'bout'},
+ \ {'lnum': 1, 'byteidx': 7, 'text': 'bout'},
+ \ {'lnum': 2, 'byteidx': 1, 'text': 'bove'},
+ \ {'lnum': 2, 'byteidx': 7, 'text': 'bove'}],
+ \ matchbufline(bnr, 'bo\k\+', 1, '$'))
+ #" no match
+ call assert_equal([], matchbufline(bnr, 'xy.*', 1, '$'))
+ #" match on a particular line
+ call assert_equal([{'lnum': 2, 'byteidx': 7, 'text': 'bove'}],
+ \ matchbufline(bnr, 'bo\k\+$', 2, 2))
+ #" match on a particular line
+ call assert_equal([], matchbufline(bnr, 'bo.*', 3, 3))
+ #" empty string
+ call deletebufline(bnr, 1, '$')
+ call assert_equal([], matchbufline(bnr, '.', 1, '$'))
+ #" empty pattern
+ call setbufline(bnr, 1, 'abc')
+ call assert_equal([{'lnum': 1, 'byteidx': 0, 'text': ''}],
+ \ matchbufline(bnr, '', 1, '$'))
+ #" method call
+ call setbufline(bnr, 1, 'editor')
+ call assert_equal([{'lnum': 1, 'byteidx': 2, 'text': 'it'}],
+ \ bnr->matchbufline('ed\zsit\zeor', 1, 1))
+ #" single character matches
+ call assert_equal([{'lnum': 1, 'byteidx': 5, 'text': 'r'}],
+ \ matchbufline(bnr, 'r', 1, '$'))
+ call setbufline(bnr, 1, 'a')
+ call assert_equal([{'lnum': 1, 'byteidx': 0, 'text': 'a'}],
+ \ matchbufline(bnr, 'a', 1, '$'))
+ #" zero-width match
+ call assert_equal([{'lnum': 1, 'byteidx': 0, 'text': ''}],
+ \ matchbufline(bnr, '\zs', 1, '$'))
+ #" string with tabs
+ call setbufline(bnr, 1, "\tfoobar")
+ call assert_equal([{'lnum': 1, 'byteidx': 1, 'text': 'foo'}],
+ \ matchbufline(bnr, 'foo', 1, '$'))
+ #" string with multibyte characters
+ call setbufline(bnr, 1, "\t\t😊😊")
+ call assert_equal([{'lnum': 1, 'byteidx': 2, 'text': '😊😊'}],
+ \ matchbufline(bnr, '\k\+', 1, '$'))
+ #" empty buffer
+ call deletebufline(bnr, 1, '$')
+ call assert_equal([], matchbufline(bnr, 'abc', 1, '$'))
+
+ #" Non existing buffer
+ call setbufline(bnr, 1, 'abc')
+ call assert_fails("echo matchbufline(5000, 'abc', 1, 1)", 'E158: Invalid buffer name: 5000')
+ #" null string
+ call assert_equal([{'lnum': 1, 'byteidx': 0, 'text': ''}],
+ \ matchbufline(bnr, v:_null_string, 1, 1))
+ #" invalid starting line number
+ call assert_equal([], matchbufline(bnr, 'abc', 100, 100))
+ #" ending line number greater than the last line
+ call assert_equal([{'lnum': 1, 'byteidx': 0, 'text': 'abc'}],
+ \ matchbufline(bnr, 'abc', 1, 100))
+ #" ending line number greater than the starting line number
+ call setbufline(bnr, 1, ['one', 'two'])
+ call assert_fails($"echo matchbufline({bnr}, 'abc', 2, 1)", 'E475: Invalid value for argument end_lnum')
+
+ #" sub matches
+ call deletebufline(bnr, 1, '$')
+ call setbufline(bnr, 1, 'acd')
+ call assert_equal([{'lnum': 1, 'byteidx': 0, 'text': 'acd', 'submatches': ['a', '', 'c', 'd', '', '', '', '', '']}],
+ \ matchbufline(bnr, '\(a\)\?\(b\)\?\(c\)\?\(.*\)', 1, '$', {'submatches': v:true}))
+
+ #" null dict argument
+ call assert_equal([{'lnum': 1, 'byteidx': 0, 'text': 'acd'}],
+ \ matchbufline(bnr, '\w\+', '$', '$', v:_null_dict))
+
+ #" Error cases
+ call assert_fails("echo matchbufline([1], 'abc', 1, 1)", 'E1220: String or Number required for argument 1')
+ call assert_fails("echo matchbufline(1, {}, 1, 1)", 'E1174: String required for argument 2')
+ call assert_fails("echo matchbufline(1, 'abc', {}, 1)", 'E1220: String or Number required for argument 3')
+ call assert_fails("echo matchbufline(1, 'abc', 1, {})", 'E1220: String or Number required for argument 4')
+ call assert_fails($"echo matchbufline({bnr}, 'abc', -1, '$')", 'E475: Invalid value for argument lnum')
+ call assert_fails($"echo matchbufline({bnr}, 'abc', 1, -1)", 'E475: Invalid value for argument end_lnum')
+ call assert_fails($"echo matchbufline({bnr}, '\\@=', 1, 1)", 'E866: (NFA regexp) Misplaced @')
+ call assert_fails($"echo matchbufline({bnr}, 'abc', 1, 1, {{'submatches': []}})", 'E475: Invalid value for argument submatches')
+ :%bdelete!
+ call assert_fails($"echo matchbufline({bnr}, 'abc', 1, '$'))", 'E681: Buffer is not loaded')
+ END
+ call CheckLegacyAndVim9Success(lines)
+
+ call assert_fails($"echo matchbufline('', 'abc', 'abc', 1)", 'E475: Invalid value for argument lnum')
+ call assert_fails($"echo matchbufline('', 'abc', 1, 'abc')", 'E475: Invalid value for argument end_lnum')
+
+ let lines =<< trim END
+ vim9script
+ def Foo()
+ echo matchbufline('', 'abc', 'abc', 1)
+ enddef
+ Foo()
+ END
+ call CheckSourceFailure(lines, 'E1030: Using a String as a Number: "abc"', 1)
+
+ let lines =<< trim END
+ vim9script
+ def Foo()
+ echo matchbufline('', 'abc', 1, 'abc')
+ enddef
+ Foo()
+ END
+ call CheckSourceFailure(lines, 'E1030: Using a String as a Number: "abc"', 1)
+endfunc
+
func Test_nextnonblank_prevnonblank()
new
insert
@@ -2485,6 +2671,10 @@ func Test_readdir()
let files = readdir('Xdir', {x -> len(add(l, x)) == 2 ? -1 : 1})
call assert_equal(1, len(files))
+ " Nested readdir() must not crash
+ let files = readdir('Xdir', 'readdir("Xdir", "1") != []')
+ call sort(files)->assert_equal(['bar.txt', 'dir', 'foo.txt'])
+
eval 'Xdir'->delete('rf')
endfunc
diff --git a/test/old/testdir/test_getvar.vim b/test/old/testdir/test_getvar.vim
index 331f3cfe8a..1e29f49fb4 100644
--- a/test/old/testdir/test_getvar.vim
+++ b/test/old/testdir/test_getvar.vim
@@ -83,6 +83,7 @@ func Test_var()
unlet def_dict
+ call assert_equal("", gettabwinvar(9, 2020, ''))
call assert_equal('', gettabwinvar(2, 3, '&nux'))
call assert_equal(1, gettabwinvar(2, 3, '&nux', 1))
tabonly
diff --git a/test/old/testdir/test_goto.vim b/test/old/testdir/test_goto.vim
index 6d029ffda2..c5492ff97b 100644
--- a/test/old/testdir/test_goto.vim
+++ b/test/old/testdir/test_goto.vim
@@ -313,18 +313,23 @@ func Test_gd_string_only()
call XTest_goto_decl('gd', lines, 5, 10)
endfunc
-" Check that setting 'cursorline' does not change curswant
-func Test_cursorline_keep_col()
+" Check that setting some options does not change curswant
+func Test_set_options_keep_col()
new
call setline(1, ['long long long line', 'short line'])
normal ggfi
let pos = getcurpos()
normal j
- set cursorline
+ set invhlsearch spell spelllang=en,cjk spelloptions=camel textwidth=80
+ set cursorline cursorcolumn cursorlineopt=line colorcolumn=+1
+ set background=dark
+ set background=light
normal k
call assert_equal(pos, getcurpos())
bwipe!
- set nocursorline
+ set hlsearch& spell& spelllang& spelloptions& textwidth&
+ set cursorline& cursorcolumn& cursorlineopt& colorcolumn&
+ set background&
endfunc
func Test_gd_local_block()
diff --git a/test/old/testdir/test_highlight.vim b/test/old/testdir/test_highlight.vim
index a83dc34063..bcaa1dac5d 100644
--- a/test/old/testdir/test_highlight.vim
+++ b/test/old/testdir/test_highlight.vim
@@ -541,7 +541,7 @@ func Test_cursorline_after_yank()
call writefile([
\ 'set cul rnu',
\ 'call setline(1, ["","1","2","3",""])',
- \ ], 'Xtest_cursorline_yank')
+ \ ], 'Xtest_cursorline_yank', 'D')
let buf = RunVimInTerminal('-S Xtest_cursorline_yank', {'rows': 8})
call TermWait(buf)
call term_sendkeys(buf, "Gy3k")
@@ -552,25 +552,25 @@ func Test_cursorline_after_yank()
" clean up
call StopVimInTerminal(buf)
- call delete('Xtest_cursorline_yank')
endfunc
-" test for issue https://github.com/vim/vim/issues/4862
+" Test for issue #4862: pasting above 'cursorline' redraws properly.
func Test_put_before_cursorline()
new
only!
- call setline(1, 'A')
+ call setline(1, ['A', 'B', 'C'])
+ call cursor(2, 1)
redraw
- let std_attr = screenattr(1, 1)
+ let std_attr = screenattr(2, 1)
set cursorline
redraw
- let cul_attr = screenattr(1, 1)
+ let cul_attr = screenattr(2, 1)
normal yyP
redraw
- " Line 1 has cursor so it should be highlighted with CursorLine.
- call assert_equal(cul_attr, screenattr(1, 1))
- " And CursorLine highlighting from the second line should be gone.
- call assert_equal(std_attr, screenattr(2, 1))
+ " Line 2 has cursor so it should be highlighted with CursorLine.
+ call assert_equal(cul_attr, screenattr(2, 1))
+ " And CursorLine highlighting from line 3 should be gone.
+ call assert_equal(std_attr, screenattr(3, 1))
set nocursorline
bwipe!
endfunc
@@ -810,6 +810,7 @@ endfunc
" Test for :highlight command errors
func Test_highlight_cmd_errors()
if has('gui_running') || has('nvim')
+ hi! Normal ctermfg=NONE ctermbg=NONE
" This test doesn't fail in the MS-Windows console version.
call assert_fails('hi Xcomment ctermfg=fg', 'E419:')
call assert_fails('hi Xcomment ctermfg=bg', 'E420:')
diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim
index e1c8b82908..917c37c324 100644
--- a/test/old/testdir/test_ins_complete.vim
+++ b/test/old/testdir/test_ins_complete.vim
@@ -108,6 +108,19 @@ func Test_ins_complete()
call delete('Xdir', 'rf')
endfunc
+func Test_ins_complete_invalid_byte()
+ if has('unix') && executable('base64')
+ " this weird command was causing an illegal memory access
+ call writefile(['bm9ybTlvMDCAMM4Dbw4OGA4ODg=='], 'Xinvalid64')
+ call system('base64 -d Xinvalid64 > Xinvalid')
+ call writefile(['qa!'], 'Xexit')
+ call RunVim([], [], " -i NONE -n -X -Z -e -m -s -S Xinvalid -S Xexit")
+ call delete('Xinvalid64')
+ call delete('Xinvalid')
+ call delete('Xexit')
+ endif
+endfunc
+
func Test_omni_dash()
func Omni(findstart, base)
if a:findstart
@@ -2407,4 +2420,18 @@ func Test_complete_info_index()
bwipe!
endfunc
-" vim: shiftwidth=2 sts=2 expandtab
+func Test_complete_changed_complete_info()
+ CheckRunVimInTerminal
+ " this used to crash vim, see #13929
+ let lines =<< trim END
+ set completeopt=menuone
+ autocmd CompleteChanged * call complete_info(['items'])
+ call feedkeys("iii\<cr>\<c-p>")
+ END
+ call writefile(lines, 'Xsegfault', 'D')
+ let buf = RunVimInTerminal('-S Xsegfault', #{rows: 5})
+ call WaitForAssert({-> assert_match('^ii', term_getline(buf, 1))}, 1000)
+ call StopVimInTerminal(buf)
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab nofoldenable
diff --git a/test/old/testdir/test_lispindent.vim b/test/old/testdir/test_lispindent.vim
index 2d6060bba3..76ff4e0fd8 100644
--- a/test/old/testdir/test_lispindent.vim
+++ b/test/old/testdir/test_lispindent.vim
@@ -50,6 +50,7 @@ func Test_lisp_indent()
set lisp
set lispwords&
+ throw 'Skipped: cpo+=p not supported'
let save_copt = &cpoptions
set cpoptions+=p
normal 1G=G
diff --git a/test/old/testdir/test_listchars.vim b/test/old/testdir/test_listchars.vim
index 179bdfa4a0..b82b70746b 100644
--- a/test/old/testdir/test_listchars.vim
+++ b/test/old/testdir/test_listchars.vim
@@ -429,52 +429,52 @@ func Test_listchars_invalid()
call assert_fails('set listchars=leadmultispace', 'E474:')
" Too short
- call assert_fails('set listchars=space:', 'E474:')
- call assert_fails('set listchars=tab:x', 'E474:')
- call assert_fails('set listchars=multispace:', 'E474:')
- call assert_fails('set listchars=leadmultispace:', 'E474:')
+ call assert_fails('set listchars=space:', 'E1511:')
+ call assert_fails('set listchars=tab:x', 'E1511:')
+ call assert_fails('set listchars=multispace:', 'E1511:')
+ call assert_fails('set listchars=leadmultispace:', 'E1511:')
" One occurrence too short
- call assert_fails('set listchars=space:,space:x', 'E474:')
- call assert_fails('set listchars=space:x,space:', 'E474:')
- call assert_fails('set listchars=tab:x,tab:xx', 'E474:')
- call assert_fails('set listchars=tab:xx,tab:x', 'E474:')
- call assert_fails('set listchars=multispace:,multispace:x', 'E474:')
- call assert_fails('set listchars=multispace:x,multispace:', 'E474:')
- call assert_fails('set listchars=leadmultispace:,leadmultispace:x', 'E474:')
- call assert_fails('set listchars=leadmultispace:x,leadmultispace:', 'E474:')
+ call assert_fails('set listchars=space:x,space:', 'E1511:')
+ call assert_fails('set listchars=space:,space:x', 'E1511:')
+ call assert_fails('set listchars=tab:xx,tab:x', 'E1511:')
+ call assert_fails('set listchars=tab:x,tab:xx', 'E1511:')
+ call assert_fails('set listchars=multispace:,multispace:x', 'E1511:')
+ call assert_fails('set listchars=multispace:x,multispace:', 'E1511:')
+ call assert_fails('set listchars=leadmultispace:,leadmultispace:x', 'E1511:')
+ call assert_fails('set listchars=leadmultispace:x,leadmultispace:', 'E1511:')
" Too long
- call assert_fails('set listchars=space:xx', 'E474:')
- call assert_fails('set listchars=tab:xxxx', 'E474:')
+ call assert_fails('set listchars=space:xx', 'E1511:')
+ call assert_fails('set listchars=tab:xxxx', 'E1511:')
" Has double-width character
- call assert_fails('set listchars=space:·', 'E474:')
- call assert_fails('set listchars=tab:·x', 'E474:')
- call assert_fails('set listchars=tab:x·', 'E474:')
- call assert_fails('set listchars=tab:xx·', 'E474:')
- call assert_fails('set listchars=multispace:·', 'E474:')
- call assert_fails('set listchars=multispace:xxx·', 'E474:')
- call assert_fails('set listchars=leadmultispace:·', 'E474:')
- call assert_fails('set listchars=leadmultispace:xxx·', 'E474:')
+ call assert_fails('set listchars=space:·', 'E1512:')
+ call assert_fails('set listchars=tab:·x', 'E1512:')
+ call assert_fails('set listchars=tab:x·', 'E1512:')
+ call assert_fails('set listchars=tab:xx·', 'E1512:')
+ call assert_fails('set listchars=multispace:·', 'E1512:')
+ call assert_fails('set listchars=multispace:xxx·', 'E1512:')
+ call assert_fails('set listchars=leadmultispace:·', 'E1512:')
+ call assert_fails('set listchars=leadmultispace:xxx·', 'E1512:')
" Has control character
- call assert_fails("set listchars=space:\x01", 'E474:')
- call assert_fails("set listchars=tab:\x01x", 'E474:')
- call assert_fails("set listchars=tab:x\x01", 'E474:')
- call assert_fails("set listchars=tab:xx\x01", 'E474:')
- call assert_fails("set listchars=multispace:\x01", 'E474:')
- call assert_fails("set listchars=multispace:xxx\x01", 'E474:')
- call assert_fails('set listchars=space:\\x01', 'E474:')
- call assert_fails('set listchars=tab:\\x01x', 'E474:')
- call assert_fails('set listchars=tab:x\\x01', 'E474:')
- call assert_fails('set listchars=tab:xx\\x01', 'E474:')
- call assert_fails('set listchars=multispace:\\x01', 'E474:')
- call assert_fails('set listchars=multispace:xxx\\x01', 'E474:')
- call assert_fails("set listchars=leadmultispace:\x01", 'E474:')
- call assert_fails('set listchars=leadmultispace:\\x01', 'E474:')
- call assert_fails("set listchars=leadmultispace:xxx\x01", 'E474:')
- call assert_fails('set listchars=leadmultispace:xxx\\x01', 'E474:')
+ call assert_fails("set listchars=space:\x01", 'E1512:')
+ call assert_fails("set listchars=tab:\x01x", 'E1512:')
+ call assert_fails("set listchars=tab:x\x01", 'E1512:')
+ call assert_fails("set listchars=tab:xx\x01", 'E1512:')
+ call assert_fails("set listchars=multispace:\x01", 'E1512:')
+ call assert_fails("set listchars=multispace:xxx\x01", 'E1512:')
+ call assert_fails('set listchars=space:\\x01', 'E1512:')
+ call assert_fails('set listchars=tab:\\x01x', 'E1512:')
+ call assert_fails('set listchars=tab:x\\x01', 'E1512:')
+ call assert_fails('set listchars=tab:xx\\x01', 'E1512:')
+ call assert_fails('set listchars=multispace:\\x01', 'E1512:')
+ call assert_fails('set listchars=multispace:xxx\\x01', 'E1512:')
+ call assert_fails("set listchars=leadmultispace:\x01", 'E1512:')
+ call assert_fails('set listchars=leadmultispace:\\x01', 'E1512:')
+ call assert_fails("set listchars=leadmultispace:xxx\x01", 'E1512:')
+ call assert_fails('set listchars=leadmultispace:xxx\\x01', 'E1512:')
enew!
set ambiwidth& listchars& ff&
diff --git a/test/old/testdir/test_listdict.vim b/test/old/testdir/test_listdict.vim
index fef7c6a9bc..649d5f5c6c 100644
--- a/test/old/testdir/test_listdict.vim
+++ b/test/old/testdir/test_listdict.vim
@@ -456,6 +456,25 @@ func Test_dict_func_remove()
call CheckLegacyAndVim9Failure(lines, 'E716:')
let lines =<< trim END
+ let d = {'a-b': 55}
+ echo d.a-b
+ END
+ call CheckScriptFailure(lines, 'E716: Key not present in Dictionary: "a"')
+
+ let lines =<< trim END
+ vim9script
+ var d = {'a-b': 55}
+ echo d.a-b
+ END
+ call CheckScriptFailure(lines, 'E716: Key not present in Dictionary: "a"')
+
+ let lines =<< trim END
+ var d = {'a-b': 55}
+ echo d.a-b
+ END
+ call CheckDefFailure(lines, 'E1004: White space required before and after ''-''')
+
+ let lines =<< trim END
let d = {1: 'a', 3: 'c'}
call remove(d, [])
END
@@ -1302,7 +1321,7 @@ func Test_listdict_index()
call CheckLegacyAndVim9Failure(['VAR l = [1, 2, 3]', 'LET l[1.1] = 4'], ['E805:', 'E1012:', 'E805:'])
call CheckLegacyAndVim9Failure(['VAR l = [1, 2, 3]', 'LET l[: i] = [4, 5]'], ['E121:', 'E1001:', 'E121:'])
call CheckLegacyAndVim9Failure(['VAR l = [1, 2, 3]', 'LET l[: 3.2] = [4, 5]'], ['E805:', 'E1012:', 'E805:'])
- " call CheckLegacyAndVim9Failure(['VAR t = test_unknown()', 'echo t[0]'], 'E685:')
+ " call CheckLegacyAndVim9Failure(['VAR t = test_unknown()', 'echo t[0]'], ['E685:', 'E909:', 'E685:'])
endfunc
" Test for a null list
diff --git a/test/old/testdir/test_listlbr.vim b/test/old/testdir/test_listlbr.vim
index 6dea94fbf1..e9bf9f3ff2 100644
--- a/test/old/testdir/test_listlbr.vim
+++ b/test/old/testdir/test_listlbr.vim
@@ -375,13 +375,13 @@ endfunc
func Test_linebreak_no_break_after_whitespace_only()
call s:test_windows('setl ts=4 linebreak wrap')
- call setline(1, "\tabcdefghijklmnopqrstuvwxyz" ..
+ call setline(1, "\t abcdefghijklmnopqrstuvwxyz" ..
\ "abcdefghijklmnopqrstuvwxyz")
let lines = s:screen_lines([1, 4], winwidth(0))
let expect = [
-\ " abcdefghijklmnop",
-\ "qrstuvwxyzabcdefghij",
-\ "klmnopqrstuvwxyz ",
+\ " abcdefghijklmn",
+\ "opqrstuvwxyzabcdefgh",
+\ "ijklmnopqrstuvwxyz ",
\ "~ ",
\ ]
call s:compare_lines(expect, lines)
diff --git a/test/old/testdir/test_listlbr_utf8.vim b/test/old/testdir/test_listlbr_utf8.vim
index 1bbbd2d2ae..313ff30cc4 100644
--- a/test/old/testdir/test_listlbr_utf8.vim
+++ b/test/old/testdir/test_listlbr_utf8.vim
@@ -9,6 +9,7 @@ CheckFeature conceal
CheckFeature signs
source view_util.vim
+source screendump.vim
func s:screen_lines(lnum, width) abort
return ScreenLines(a:lnum, a:width)
@@ -358,4 +359,24 @@ func Test_unprintable_char_on_wrap_column()
call s:close_windows()
endfunc
+" Test that Visual selection is drawn correctly when 'linebreak' is set and
+" selection ends before multibyte 'showbreak'.
+func Test_visual_ends_before_showbreak()
+ CheckScreendump
+
+ let lines =<< trim END
+ vim9script
+ &wrap = true
+ &linebreak = true
+ &showbreak = '↪ '
+ ['xxxxx ' .. 'y'->repeat(&columns - 6) .. ' zzzz']->setline(1)
+ normal! wvel
+ END
+ call writefile(lines, 'XvisualEndsBeforeShowbreak', 'D')
+ let buf = RunVimInTerminal('-S XvisualEndsBeforeShowbreak', #{rows: 6})
+ call VerifyScreenDump(buf, 'Test_visual_ends_before_showbreak', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_map_functions.vim b/test/old/testdir/test_map_functions.vim
index 2aeb470a0d..0898242154 100644
--- a/test/old/testdir/test_map_functions.vim
+++ b/test/old/testdir/test_map_functions.vim
@@ -593,7 +593,7 @@ func Test_maplist()
call assert_equal(len(maps_maplist), len(map_set))
" For everything returned by maplist, should be the same as from maparg.
- " Except for "map dup", bacause maparg returns the <buffer> version
+ " Except for "map dup", because maparg returns the <buffer> version
for d in maps_maplist
if d.lhs == 'dup' && d.buffer == 0
continue
diff --git a/test/old/testdir/test_mapping.vim b/test/old/testdir/test_mapping.vim
index 36a46684c1..623228b347 100644
--- a/test/old/testdir/test_mapping.vim
+++ b/test/old/testdir/test_mapping.vim
@@ -108,7 +108,7 @@ func Test_map_langmap()
unmap x
bwipe!
- " 'langnoremap' follows 'langremap' and vise versa
+ " 'langnoremap' follows 'langremap' and vice versa
set langremap
set langnoremap
call assert_equal(0, &langremap)
@@ -235,6 +235,24 @@ func Test_map_meta_multibyte()
iunmap <M-á>
endfunc
+func Test_map_super_quotes()
+ if has('gui_gtk') || has('gui_gtk3') || has("macos")
+ imap <D-"> foo
+ call feedkeys("Go-\<*D-\">-\<Esc>", "xt")
+ call assert_equal("-foo-", getline('$'))
+ set nomodified
+ iunmap <D-">
+ endif
+endfunc
+
+func Test_map_super_multibyte()
+ if has('gui_gtk') || has('gui_gtk3') || has("macos")
+ imap <D-á> foo
+ call assert_match('i <D-á>\s*foo', execute('imap'))
+ iunmap <D-á>
+ endif
+endfunc
+
func Test_abbr_after_line_join()
new
abbr foo bar
diff --git a/test/old/testdir/test_messages.vim b/test/old/testdir/test_messages.vim
index 5ebcb375b6..ac5184645f 100644
--- a/test/old/testdir/test_messages.vim
+++ b/test/old/testdir/test_messages.vim
@@ -167,8 +167,18 @@ func Test_echospace()
call assert_equal(&columns - 12, v:echospace)
set showcmd ruler
call assert_equal(&columns - 29, v:echospace)
+ set showcmdloc=statusline
+ call assert_equal(&columns - 19, v:echospace)
+ set showcmdloc=tabline
+ call assert_equal(&columns - 19, v:echospace)
+ call assert_fails('set showcmdloc=leap', 'E474:')
+ call assert_equal(&columns - 19, v:echospace)
+ set showcmdloc=last
+ call assert_equal(&columns - 29, v:echospace)
+ call assert_fails('set showcmdloc=jump', 'E474:')
+ call assert_equal(&columns - 29, v:echospace)
- set ruler& showcmd&
+ set ruler& showcmd& showcmdloc&
endfunc
func Test_warning_scroll()
diff --git a/test/old/testdir/test_normal.vim b/test/old/testdir/test_normal.vim
index 6a8c15bd48..91c058df9e 100644
--- a/test/old/testdir/test_normal.vim
+++ b/test/old/testdir/test_normal.vim
@@ -2240,7 +2240,7 @@ func Test_normal29_brace()
[DATA]
call assert_equal(expected, getline(1, '$'))
- " Test with { in cpooptions
+ " Test with { in cpoptions
%d
call append(0, text)
" Nvim: no "{" flag in 'cpoptions'.
@@ -2353,19 +2353,19 @@ func Test_normal30_changecase()
norm! 1ggVu
call assert_equal('this is a simple test: äüöß', getline('.'))
norm! VU
- call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
+ call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖẞ', getline('.'))
norm! guu
- call assert_equal('this is a simple test: äüöss', getline('.'))
+ call assert_equal('this is a simple test: äüöß', getline('.'))
norm! gUgU
- call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
+ call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖẞ', getline('.'))
norm! gugu
- call assert_equal('this is a simple test: äüöss', getline('.'))
+ call assert_equal('this is a simple test: äüöß', getline('.'))
norm! gUU
- call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖSS', getline('.'))
+ call assert_equal('THIS IS A SIMPLE TEST: ÄÜÖẞ', getline('.'))
norm! 010~
- call assert_equal('this is a SIMPLE TEST: ÄÜÖSS', getline('.'))
+ call assert_equal('this is a SIMPLE TEST: ÄÜÖẞ', getline('.'))
norm! V~
- call assert_equal('THIS IS A simple test: äüöss', getline('.'))
+ call assert_equal('THIS IS A simple test: äüöß', getline('.'))
call assert_beeps('norm! c~')
%d
call assert_beeps('norm! ~')
@@ -3167,15 +3167,18 @@ endfunc
func Test_normal50_commandline()
CheckFeature timers
CheckFeature cmdline_hist
+
func! DoTimerWork(id)
- call assert_equal('[Command Line]', bufname(''))
+ call assert_equal(1, getbufinfo('')[0].command)
+
" should fail, with E11, but does fail with E23?
"call feedkeys("\<c-^>", 'tm')
- " should also fail with E11
+ " should fail with E11 - "Invalid in command-line window"
call assert_fails(":wincmd p", 'E11')
- " return from commandline window
- call feedkeys("\<cr>")
+
+ " Return from commandline window.
+ call feedkeys("\<CR>", 't')
endfunc
let oldlang=v:lang
@@ -3188,7 +3191,9 @@ func Test_normal50_commandline()
catch /E23/
" no-op
endtry
+
" clean up
+ delfunc DoTimerWork
set updatetime=4000
exe "lang" oldlang
bw!
@@ -4169,4 +4174,21 @@ func Test_normal34_zet_large()
norm! z9765405999999999999
endfunc
-" vim: shiftwidth=2 sts=2 expandtab
+" Test for { and } paragraph movements in a single line
+func Test_brace_single_line()
+ let text =<< trim [DATA]
+ foobar one two three
+ [DATA]
+
+ new
+ call setline(1, text)
+ 1
+ norm! 0}
+
+ call assert_equal([0, 1, 20, 0], getpos('.'))
+ norm! {
+ call assert_equal([0, 1, 1, 0], getpos('.'))
+ bw!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab nofoldenable
diff --git a/test/old/testdir/test_number.vim b/test/old/testdir/test_number.vim
index 1232db80c5..b57c1ed2c5 100644
--- a/test/old/testdir/test_number.vim
+++ b/test/old/testdir/test_number.vim
@@ -146,8 +146,7 @@ func Test_number_with_linewrap1()
call s:close_windows()
endfunc
-" Pending: https://groups.google.com/forum/#!topic/vim_dev/tzNKP7EDWYI
-func XTest_number_with_linewrap2()
+func Test_number_with_linewrap2()
call s:test_windows(3, 20)
normal! 61ia
setl number wrap
@@ -164,8 +163,7 @@ func XTest_number_with_linewrap2()
call s:close_windows()
endfunc
-" Pending: https://groups.google.com/forum/#!topic/vim_dev/tzNKP7EDWYI
-func XTest_number_with_linewrap3()
+func Test_number_with_linewrap3()
call s:test_windows(4, 20)
normal! 81ia
setl number wrap
@@ -174,7 +172,7 @@ func XTest_number_with_linewrap3()
call s:validate_cursor()
let lines = s:screen_lines(1, 4)
let expect = [
-\ "aaaaaaaa",
+\ "<<<aaaaa",
\ "aaaaaaaa",
\ "aaaaaaaa",
\ "a ",
@@ -276,11 +274,9 @@ func Test_relativenumber_colors()
set number relativenumber
hi LineNr ctermfg=red
[CODE]
- call writefile(lines, 'XTest_relnr')
+ call writefile(lines, 'XTest_relnr', 'D')
- " Check that the balloon shows up after a mouse move
let buf = RunVimInTerminal('-S XTest_relnr', {'rows': 10, 'cols': 50})
- call TermWait(buf, 50)
" Default colors
call VerifyScreenDump(buf, 'Test_relnr_colors_1', {})
@@ -295,7 +291,36 @@ func Test_relativenumber_colors()
" clean up
call StopVimInTerminal(buf)
- call delete('XTest_relnr')
+endfunc
+
+func Test_relativenumber_colors_wrapped()
+ CheckScreendump
+
+ let lines =<< trim [CODE]
+ set display=lastline scrolloff=0
+ call setline(1, range(200)->map('v:val->string()->repeat(40)'))
+ 111
+ set number relativenumber
+ hi LineNr ctermbg=red ctermfg=black
+ hi LineNrAbove ctermbg=blue ctermfg=black
+ hi LineNrBelow ctermbg=green ctermfg=black
+ [CODE]
+ call writefile(lines, 'XTest_relnr_wrap', 'D')
+
+ let buf = RunVimInTerminal('-S XTest_relnr_wrap', {'rows': 20, 'cols': 50})
+
+ call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_1', {})
+ call term_sendkeys(buf, "k")
+ call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_2', {})
+ call term_sendkeys(buf, "2j")
+ call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_3', {})
+ call term_sendkeys(buf, "2j")
+ call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_4', {})
+ call term_sendkeys(buf, "k")
+ call VerifyScreenDump(buf, 'Test_relnr_colors_wrapped_5', {})
+
+ " clean up
+ call StopVimInTerminal(buf)
endfunc
func Test_relativenumber_callback()
@@ -313,14 +338,38 @@ func Test_relativenumber_callback()
call timer_start(300, 'Func')
END
- call writefile(lines, 'Xrnu_timer')
+ call writefile(lines, 'Xrnu_timer', 'D')
let buf = RunVimInTerminal('-S Xrnu_timer', #{rows: 8})
call TermWait(buf, 310)
call VerifyScreenDump(buf, 'Test_relativenumber_callback_1', {})
call StopVimInTerminal(buf)
- call delete('Xrnu_timer')
+endfunc
+
+" Test that line numbers below inserted/deleted lines are updated.
+func Test_number_insert_delete_lines()
+ CheckScreendump
+
+ let lines =<< trim END
+ call setline(1, range(1, 7))
+ set number
+ call cursor(2, 1)
+ END
+ call writefile(lines, 'Xnumber_insert_delete_lines', 'D')
+
+ let buf = RunVimInTerminal('-S Xnumber_insert_delete_lines', #{rows: 8})
+ call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_1', {})
+ call term_sendkeys(buf, "dd")
+ call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_2', {})
+ call term_sendkeys(buf, "P")
+ call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_1', {})
+ call term_sendkeys(buf, "2dd")
+ call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_3', {})
+ call term_sendkeys(buf, "P")
+ call VerifyScreenDump(buf, 'Test_number_insert_delete_lines_1', {})
+
+ call StopVimInTerminal(buf)
endfunc
" Test for displaying line numbers with 'rightleft'
diff --git a/test/old/testdir/test_options.vim b/test/old/testdir/test_options.vim
index d69828dc2e..7786f82af2 100644
--- a/test/old/testdir/test_options.vim
+++ b/test/old/testdir/test_options.vim
@@ -439,6 +439,14 @@ func Test_set_completion()
call assert_equal('"set syntax=sshdconfig', @:)
call feedkeys(":set syntax=a\<C-A>\<C-B>\"\<CR>", 'xt')
call assert_equal('"set syntax=' .. getcompletion('a*', 'syntax')->join(), @:)
+
+ if has('keymap')
+ " Expand values for 'keymap'
+ call feedkeys(":set keymap=acc\<Tab>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"set keymap=accents', @:)
+ call feedkeys(":set keymap=a\<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"set keymap=' .. getcompletion('a*', 'keymap')->join(), @:)
+ endif
endfunc
" Test handling of expanding individual string option values
@@ -813,7 +821,7 @@ func Test_set_option_errors()
call assert_fails('set winwidth=9 winminwidth=10', 'E592:')
set winwidth& winminwidth&
call assert_fails("set showbreak=\x01", 'E595:')
- call assert_fails('set t_foo=', 'E846:')
+ " call assert_fails('set t_foo=', 'E846:')
call assert_fails('set tabstop??', 'E488:')
call assert_fails('set wrapscan!!', 'E488:')
call assert_fails('set tabstop&&', 'E488:')
@@ -950,8 +958,10 @@ endfunc
func Test_set_one_column()
let out_mult = execute('set all')->split("\n")
let out_one = execute('set! all')->split("\n")
- " one column should be two to four times as many lines
- call assert_inrange(len(out_mult) * 2, len(out_mult) * 4, len(out_one))
+ call assert_true(len(out_mult) < len(out_one))
+ call assert_equal(out_one[0], '--- Options ---')
+ let options = out_one[1:]->mapnew({_, line -> line[2:]})
+ call assert_equal(sort(copy(options)), options)
endfunc
func Test_set_values()
@@ -1273,6 +1283,44 @@ func Test_shortmess_F2()
" call assert_fails('call test_getvalue("abc")', 'E475:')
endfunc
+func Test_shortmess_F3()
+ call writefile(['foo'], 'X_dummy', 'D')
+
+ set hidden
+ set autoread
+ e X_dummy
+ e Xotherfile
+ call assert_equal(['foo'], getbufline('X_dummy', 1, '$'))
+ set shortmess+=F
+ echo ''
+
+ if has('nanotime')
+ sleep 10m
+ else
+ sleep 2
+ endif
+ call writefile(['bar'], 'X_dummy')
+ bprev
+ call assert_equal('', Screenline(&lines))
+ call assert_equal(['bar'], getbufline('X_dummy', 1, '$'))
+
+ if has('nanotime')
+ sleep 10m
+ else
+ sleep 2
+ endif
+ call writefile(['baz'], 'X_dummy')
+ checktime
+ call assert_equal('', Screenline(&lines))
+ call assert_equal(['baz'], getbufline('X_dummy', 1, '$'))
+
+ set shortmess&
+ set autoread&
+ set hidden&
+ bwipe X_dummy
+ bwipe Xotherfile
+endfunc
+
func Test_local_scrolloff()
set so=5
set siso=7
@@ -1444,8 +1492,10 @@ endfunc
" Test for setting keycodes using set
func Test_opt_set_keycode()
- call assert_fails('set <t_k1=l', 'E474:')
- call assert_fails('set <Home=l', 'E474:')
+ " call assert_fails('set <t_k1=l', 'E474:')
+ " call assert_fails('set <Home=l', 'E474:')
+ call assert_fails('set <t_k1=l', 'E518:')
+ call assert_fails('set <Home=l', 'E518:')
set <t_k9>=abcd
" call assert_equal('abcd', &t_k9)
set <t_k9>&
@@ -2209,4 +2259,34 @@ func Test_set_wrap()
set wrap& smoothscroll& scrolloff&
endfunc
+func Test_delcombine()
+ new
+ set backspace=indent,eol,start
+
+ set delcombine
+ call setline(1, 'β̳̈:β̳̈')
+ normal! 0x
+ call assert_equal('β̈:β̳̈', getline(1))
+ exe "normal! A\<BS>"
+ call assert_equal('β̈:β̈', getline(1))
+ normal! 0x
+ call assert_equal('β:β̈', getline(1))
+ exe "normal! A\<BS>"
+ call assert_equal('β:β', getline(1))
+ normal! 0x
+ call assert_equal(':β', getline(1))
+ exe "normal! A\<BS>"
+ call assert_equal(':', getline(1))
+
+ set nodelcombine
+ call setline(1, 'β̳̈:β̳̈')
+ normal! 0x
+ call assert_equal(':β̳̈', getline(1))
+ exe "normal! A\<BS>"
+ call assert_equal(':', getline(1))
+
+ set backspace& delcombine&
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_popup.vim b/test/old/testdir/test_popup.vim
index fa0df77ab5..56c881b958 100644
--- a/test/old/testdir/test_popup.vim
+++ b/test/old/testdir/test_popup.vim
@@ -1142,6 +1142,10 @@ func Test_CompleteChanged()
let g:event = copy(v:event)
let g:item = get(v:event, 'completed_item', {})
let g:word = get(g:item, 'word', v:null)
+ let l:line = getline('.')
+ if g:word == v:null && l:line == "bc"
+ let g:word = l:line
+ endif
endfunction
augroup AAAAA_Group
au!
@@ -1161,10 +1165,24 @@ func Test_CompleteChanged()
call assert_equal(v:null, g:word)
call feedkeys("a\<C-N>\<C-N>\<C-N>\<C-N>\<C-P>", 'tx')
call assert_equal('foobar', g:word)
+ call feedkeys("S\<C-N>bc", 'tx')
+ call assert_equal("bc", g:word)
+
+ func Omni_test(findstart, base)
+ if a:findstart
+ return col(".")
+ endif
+ return [#{word: "one"}, #{word: "two"}, #{word: "five"}]
+ endfunc
+ set omnifunc=Omni_test
+ set completeopt=menu,menuone
+ call feedkeys("i\<C-X>\<C-O>\<BS>\<BS>\<BS>f", 'tx')
+ call assert_equal('five', g:word)
autocmd! AAAAA_Group
set complete& completeopt&
delfunc! OnPumChange
+ delfunc! Omni_test
bw!
endfunc
diff --git a/test/old/testdir/test_prompt_buffer.vim b/test/old/testdir/test_prompt_buffer.vim
index 3dfbbcece6..41e14ae427 100644
--- a/test/old/testdir/test_prompt_buffer.vim
+++ b/test/old/testdir/test_prompt_buffer.vim
@@ -298,4 +298,49 @@ func Test_prompt_appending_while_hidden()
call StopVimInTerminal(buf)
endfunc
+" Modifying a hidden buffer while leaving a prompt buffer should not prevent
+" stopping of Insert mode, and returning to the prompt buffer later should
+" restore Insert mode.
+func Test_prompt_leave_modify_hidden()
+ call CanTestPromptBuffer()
+
+ let script =<< trim END
+ file hidden
+ set bufhidden=hide
+ enew
+ new prompt
+ set buftype=prompt
+
+ inoremap <buffer> w <Cmd>wincmd w<CR>
+ inoremap <buffer> q <Cmd>bwipe!<CR>
+ autocmd BufLeave prompt call appendbufline('hidden', '$', 'Leave')
+ autocmd BufEnter prompt call appendbufline('hidden', '$', 'Enter')
+ autocmd BufWinLeave prompt call appendbufline('hidden', '$', 'Close')
+ END
+ call writefile(script, 'XpromptLeaveModifyHidden', 'D')
+
+ let buf = RunVimInTerminal('-S XpromptLeaveModifyHidden', {'rows': 10})
+ call TermWait(buf)
+
+ call term_sendkeys(buf, "a")
+ call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))})
+
+ call term_sendkeys(buf, "w")
+ call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))})
+
+ call term_sendkeys(buf, "\<C-W>w")
+ call WaitForAssert({-> assert_match('-- INSERT --', term_getline(buf, 10))})
+
+ call term_sendkeys(buf, "q")
+ call WaitForAssert({-> assert_notmatch('-- INSERT --', term_getline(buf, 10))})
+
+ call term_sendkeys(buf, ":bwipe!\<CR>")
+ call WaitForAssert({-> assert_equal('Leave', term_getline(buf, 2))})
+ call WaitForAssert({-> assert_equal('Enter', term_getline(buf, 3))})
+ call WaitForAssert({-> assert_equal('Leave', term_getline(buf, 4))})
+ call WaitForAssert({-> assert_equal('Close', term_getline(buf, 5))})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_put.vim b/test/old/testdir/test_put.vim
index 6c4bd28386..b1cf268a58 100644
--- a/test/old/testdir/test_put.vim
+++ b/test/old/testdir/test_put.vim
@@ -12,6 +12,16 @@ func Test_put_block()
bwipe!
endfunc
+func Test_put_block_unicode()
+ new
+ call setreg('a', "À\nÀÀ\naaaaaaaaaaaa", "\<C-V>")
+ call setline(1, [' 1', ' 2', ' 3'])
+ exe "norm! \<C-V>jj\"ap"
+ let expected = ['À 1', 'ÀÀ 2', 'aaaaaaaaaaaa3']
+ call assert_equal(expected, getline(1, 3))
+ bw!
+endfunc
+
func Test_put_char_block()
new
call setline(1, ['Line 1', 'Line 2'])
@@ -284,5 +294,33 @@ func Test_put_in_last_displayed_line()
call StopVimInTerminal(buf)
endfunc
+func Test_put_visual_replace_whole_fold()
+ new
+ let lines = repeat(['{{{1', 'foo', 'bar', ''], 2)
+ call setline(1, lines)
+ setlocal foldmethod=marker
+ call setreg('"', 'baz')
+ call setreg('1', '')
+ normal! Vp
+ call assert_equal("{{{1\nfoo\nbar\n\n", getreg('1'))
+ call assert_equal(['baz', '{{{1', 'foo', 'bar', ''], getline(1, '$'))
+
+ bwipe!
+endfunc
+
+func Test_put_visual_replace_fold_marker()
+ new
+ let lines = repeat(['{{{1', 'foo', 'bar', ''], 4)
+ call setline(1, lines)
+ setlocal foldmethod=marker
+ normal! Gkzo
+ call setreg('"', '{{{1')
+ call setreg('1', '')
+ normal! Vp
+ call assert_equal("{{{1\n", getreg('1'))
+ call assert_equal(lines, getline(1, '$'))
+
+ bwipe!
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_python3.vim b/test/old/testdir/test_python3.vim
index 23c63f22d8..c9dbc0b84e 100644
--- a/test/old/testdir/test_python3.vim
+++ b/test/old/testdir/test_python3.vim
@@ -169,7 +169,7 @@ func Test_Catch_Exception_Message()
try
py3 raise RuntimeError( 'TEST' )
catch /.*/
- call assert_match('^Vim(.*):.*RuntimeError: TEST$', v:exception )
+ call assert_match('^Vim(.*):.*RuntimeError: TEST.*$', v:exception )
endtry
endfunc
diff --git a/test/old/testdir/test_pyx3.vim b/test/old/testdir/test_pyx3.vim
index 09ece6f812..89a3cc22ff 100644
--- a/test/old/testdir/test_pyx3.vim
+++ b/test/old/testdir/test_pyx3.vim
@@ -76,7 +76,7 @@ func Test_Catch_Exception_Message()
try
pyx raise RuntimeError( 'TEST' )
catch /.*/
- call assert_match('^Vim(.*):.*RuntimeError: TEST$', v:exception )
+ call assert_match('^Vim(.*):.*RuntimeError: TEST.*$', v:exception )
endtry
endfunc
diff --git a/test/old/testdir/test_regexp_utf8.vim b/test/old/testdir/test_regexp_utf8.vim
index 2253242a7c..97f48a0c09 100644
--- a/test/old/testdir/test_regexp_utf8.vim
+++ b/test/old/testdir/test_regexp_utf8.vim
@@ -599,5 +599,16 @@ func Test_match_too_complicated()
set regexpengine=0
endfunc
+func Test_combining_chars_in_collection()
+ new
+ for i in range(0,2)
+ exe "set re=".i
+ put =['ɔ̃', 'ɔ', '̃ ã', 'abcd']
+ :%s/[ɔ̃]//
+ call assert_equal(['', '', 'ɔ', '̃ ã', 'abcd'], getline(1,'$'))
+ %d
+ endfor
+ bw!
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_registers.vim b/test/old/testdir/test_registers.vim
index 01f9507916..e113bd9e75 100644
--- a/test/old/testdir/test_registers.vim
+++ b/test/old/testdir/test_registers.vim
@@ -175,7 +175,7 @@ func Test_recording_status_in_ex_line()
call assert_equal('recording @x', Screenline(&lines))
set shortmess=q
redraw!
- call assert_equal('recording', Screenline(&lines))
+ call assert_equal('', Screenline(&lines)) " Nvim: shm+=q fully hides message
set shortmess&
norm q
redraw!
@@ -801,6 +801,23 @@ func Test_end_reg_executing()
bwipe!
endfunc
+func Test_reg_executing_in_range_normal()
+ new
+ set showcmd
+ call setline(1, range(10))
+ let g:log = []
+ nnoremap s <Cmd>let g:log += [reg_executing()]<CR>
+ let @r = 's'
+
+ %normal @r
+ call assert_equal(repeat(['r'], 10), g:log)
+
+ nunmap s
+ unlet g:log
+ set showcmd&
+ bwipe!
+endfunc
+
" An operator-pending mode mapping shouldn't be applied to keys typed in
" Insert mode immediately after a character search when replaying.
func Test_replay_charsearch_omap()
@@ -812,6 +829,8 @@ func Test_replay_charsearch_omap()
call timer_start(10, {-> feedkeys(",bar\<Esc>q", 't')})
call feedkeys('qrct[', 'xt!')
call assert_equal(',bar[blah]', getline(1))
+ call assert_equal("ct[\<Ignore>,bar\<Esc>", @r)
+ call assert_equal('ct[<Ignore>,bar<Esc>', keytrans(@r))
undo
call assert_equal('foo[blah]', getline(1))
call feedkeys('@r', 'xt!')
@@ -821,5 +840,88 @@ func Test_replay_charsearch_omap()
bwipe!
endfunc
+" Make sure that y_append is correctly reset
+" and the previous register is working as expected
+func Test_register_y_append_reset()
+ new
+ call setline(1, ['1',
+ \ '2 ----------------------------------------------------',
+ \ '3',
+ \ '4',
+ \ '5 ----------------------------------------------------',
+ \ '6',
+ \ '7',
+ \ '8 ----------------------------------------------------',
+ \ '9',
+ \ '10 aaaaaaa 4.',
+ \ '11 Game Dbl-Figures Leaders:',
+ \ '12 Player Pts FG% 3P% FT% RB AS BL ST TO PF EFF',
+ \ '13 bbbbbbbbb 12 (50 /0 /67 )/ 7/ 3/ 0/ 2/ 3/ 4/+15',
+ \ '14 cccccc 12 (57 /67 /100)/ 2/ 1/ 1/ 0/ 1/ 3/+12',
+ \ '15 ddddddd 10 (63 /0 /0 )/ 1/ 3/ 0/ 3/ 5/ 3/ +9',
+ \ '16 4 5-15 0-3 2-2 5-12 1-1 3-4 33.3 0.0 100 41.7 100 75 12 14',
+ \ '17 F 23-55 2-10 9-11 23-52 3-13 26-29 41.8 20 81.8 44.2 23.1 89.7 57 75',
+ \ '18 4 3 6 3 2 3 3 4 3 3 7 3 1 4 6 -1 -1 +2 -1 -2',
+ \ '19 F 13 19 5 10 4 17 22 9 14 32 13 4 20 17 -1 -13 -4 -3 -3 +5'])
+ 11
+ exe "norm! \"a5dd"
+ norm! j
+ exe "norm! \"bY"
+ norm! 2j
+ exe "norm! \"BY"
+ norm! 4k
+ norm! 5dd
+ norm! 3k
+ " The next put should put the content of the unnamed register, not of
+ " register b!
+ norm! p
+ call assert_equal(['1',
+ \ '2 ----------------------------------------------------',
+ \ '3',
+ \ '4',
+ \ '5 ----------------------------------------------------',
+ \ '6',
+ \ '10 aaaaaaa 4.',
+ \ '16 4 5-15 0-3 2-2 5-12 1-1 3-4 33.3 0.0 100 41.7 100 75 12 14',
+ \ '17 F 23-55 2-10 9-11 23-52 3-13 26-29 41.8 20 81.8 44.2 23.1 89.7 57 75',
+ \ '18 4 3 6 3 2 3 3 4 3 3 7 3 1 4 6 -1 -1 +2 -1 -2',
+ \ '19 F 13 19 5 10 4 17 22 9 14 32 13 4 20 17 -1 -13 -4 -3 -3 +5',
+ \ '7',
+ \ '8 ----------------------------------------------------',
+ \ '9'], getline(1,'$'))
+ bwipe!
+endfunc
+
+func Test_insert_small_delete_replace_mode()
+ new
+ call setline(1, ['foo', 'bar', 'foobar', 'bar'])
+ let @- = 'foo'
+ call cursor(2, 1)
+ exe ":norm! R\<C-R>-\<C-R>-"
+ call assert_equal('foofoo', getline(2))
+ call cursor(3, 1)
+ norm! D
+ call assert_equal(['foo', 'foofoo', '', 'bar'], getline(1, 4))
+ call cursor(4, 2)
+ exe ":norm! R\<C-R>-ZZZZ"
+ call assert_equal(['foo', 'foofoo', '', 'bfoobarZZZZ'], getline(1, 4))
+ call cursor(1, 1)
+ let @- = ''
+ exe ":norm! R\<C-R>-ZZZ"
+ call assert_equal(['ZZZ', 'foofoo', '', 'bfoobarZZZZ'], getline(1, 4))
+ let @- = 'βbβ'
+ call cursor(4, 1)
+ exe ":norm! R\<C-R>-"
+ call assert_equal(['ZZZ', 'foofoo', '', 'βbβobarZZZZ'], getline(1, 4))
+ let @- = 'bβb'
+ call cursor(4, 1)
+ exe ":norm! R\<C-R>-"
+ call assert_equal(['ZZZ', 'foofoo', '', 'bβbobarZZZZ'], getline(1, 4))
+ let @- = 'βbβ'
+ call cursor(4, 1)
+ exe ":norm! R\<C-R>-"
+ call assert_equal(['ZZZ', 'foofoo', '', 'βbβobarZZZZ'], getline(1, 4))
+ bwipe!
+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 f2e7bc6b56..a1987ed3c9 100644
--- a/test/old/testdir/test_scroll_opt.vim
+++ b/test/old/testdir/test_scroll_opt.vim
@@ -923,7 +923,7 @@ func Test_smoothscroll_cursor_top()
exe "norm G3\<C-E>k"
END
call writefile(lines, 'XSmoothScrollCursorTop', 'D')
- let buf = RunVimInTerminal('-u NONE -S XSmoothScrollCursorTop', #{rows: 12, cols:40})
+ let buf = RunVimInTerminal('-u NONE -S XSmoothScrollCursorTop', #{rows: 12, cols: 40})
call VerifyScreenDump(buf, 'Test_smoothscroll_cursor_top', {})
call StopVimInTerminal(buf)
@@ -942,10 +942,25 @@ func Test_smoothscroll_crash()
exe "norm! 0\<c-e>"
END
call writefile(lines, 'XSmoothScrollCrash', 'D')
- let buf = RunVimInTerminal('-u NONE -S XSmoothScrollCrash', #{rows: 12, cols:40})
+ let buf = RunVimInTerminal('-u NONE -S XSmoothScrollCrash', #{rows: 12, cols: 40})
call term_sendkeys(buf, "2\<C-E>\<C-L>")
call StopVimInTerminal(buf)
endfunc
+func Test_smoothscroll_insert_bottom()
+ CheckScreendump
+
+ let lines =<< trim END
+ call setline(1, repeat([repeat('A very long line ...', 10)], 5))
+ set wrap smoothscroll scrolloff=0
+ END
+ call writefile(lines, 'XSmoothScrollInsertBottom', 'D')
+ let buf = RunVimInTerminal('-u NONE -S XSmoothScrollInsertBottom', #{rows: 9, cols: 40})
+ call term_sendkeys(buf, "Go123456789\<CR>")
+ call VerifyScreenDump(buf, 'Test_smoothscroll_insert_bottom', {})
+
+ call StopVimInTerminal(buf)
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_syntax.vim b/test/old/testdir/test_syntax.vim
index 76a21adc57..711b2adf7c 100644
--- a/test/old/testdir/test_syntax.vim
+++ b/test/old/testdir/test_syntax.vim
@@ -197,14 +197,14 @@ func Test_syntax_completion()
" Check that clearing "Aap" avoids it showing up before Boolean.
hi @Aap ctermfg=blue
call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_match('^"syn list @Aap @boolean @character ', @:)
+ call assert_match('^"syn list @Aap @attribute @boolean @character ', @:)
hi clear @Aap
call feedkeys(":syn list \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_match('^"syn list @boolean @character ', @:)
+ call assert_match('^"syn list @attribute @boolean @character ', @:)
call feedkeys(":syn match \<C-A>\<C-B>\"\<CR>", 'tx')
- call assert_match('^"syn match @boolean @character ', @:)
+ call assert_match('^"syn match @attribute @boolean @character ', @:)
syn cluster Aax contains=Aap
call feedkeys(":syn list @A\<C-A>\<C-B>\"\<CR>", 'tx')
@@ -214,7 +214,7 @@ endfunc
func Test_echohl_completion()
call feedkeys(":echohl no\<C-A>\<C-B>\"\<CR>", 'tx')
" call assert_equal('"echohl NonText Normal none', @:)
- call assert_equal('"echohl NonText Normal NormalFloat none', @:)
+ call assert_equal('"echohl NonText Normal NormalFloat NormalNC none', @:)
endfunc
func Test_syntax_arg_skipped()
diff --git a/test/old/testdir/test_tabpage.vim b/test/old/testdir/test_tabpage.vim
index 4e7b09b9e7..0f038c8bee 100644
--- a/test/old/testdir/test_tabpage.vim
+++ b/test/old/testdir/test_tabpage.vim
@@ -156,14 +156,85 @@ func Test_tabpage_drop()
tab split f3
normal! gt
call assert_equal(1, tabpagenr())
+ tab drop f4
+ call assert_equal(1, tabpagenr('#'))
tab drop f3
- call assert_equal(3, tabpagenr())
- call assert_equal(1, tabpagenr('#'))
+ call assert_equal(4, tabpagenr())
+ call assert_equal(2, tabpagenr('#'))
+ bwipe!
bwipe!
bwipe!
bwipe!
call assert_equal(1, tabpagenr('$'))
+
+ call assert_equal(1, winnr('$'))
+ call assert_equal('', bufname(''))
+ call writefile(['L1', 'L2'], 'Xdropfile', 'D')
+
+ " Test for ':tab drop single-file': reuse current buffer
+ let expected_nr = bufnr()
+ tab drop Xdropfile
+ call assert_equal(1, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ bwipe!
+
+ " Test for ':tab drop single-file': not reuse modified buffer
+ set modified
+ let expected_nr = bufnr() + 1
+ tab drop Xdropfile
+ call assert_equal(2, tabpagenr())
+ call assert_equal(2, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ bwipe!
+
+ " Test for ':tab drop single-file': multiple tabs already exist
+ tab split f2
+ tab split f3
+ let expected_nr = bufnr() + 1
+ tab drop Xdropfile
+ call assert_equal(4, tabpagenr())
+ call assert_equal(4, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ %bwipe!
+
+ " Test for ':tab drop multi-files': reuse current buffer
+ let expected_nr = bufnr()
+ tab drop Xdropfile f1 f2 f3
+ call assert_equal(1, tabpagenr())
+ call assert_equal(4, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ %bwipe!
+
+ " Test for ':tab drop multi-files': not reuse modified buffer
+ set modified
+ let expected_nr = bufnr() + 1
+ tab drop Xdropfile f1 f2 f3
+ call assert_equal(2, tabpagenr())
+ call assert_equal(5, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ %bwipe!
+
+ " Test for ':tab drop multi-files': multiple tabs already exist
+ tab split f2
+ tab split f3
+ let expected_nr = bufnr() + 1
+ tab drop a b c
+ call assert_equal(4, tabpagenr())
+ call assert_equal(6, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ let expected_nr = bufnr() + 3
+ tab drop Xdropfile f1 f2 f3
+ call assert_equal(5, tabpagenr())
+ call assert_equal(8, tabpagenr('$'))
+ call assert_equal(expected_nr, bufnr())
+ call assert_equal('L2', getline(2))
+ %bwipe!
endfunc
" Test autocommands
@@ -260,14 +331,14 @@ function Test_tabpage_with_autocmd_tab_drop()
let s:li = []
tab drop test1
- call assert_equal(['BufLeave', 'BufEnter'], s:li)
+ call assert_equal(['BufEnter'], s:li)
let s:li = []
tab drop test2 test3
call assert_equal([
\ 'TabLeave', 'TabEnter', 'TabLeave', 'TabEnter',
\ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter',
- \ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter'], s:li)
+ \ 'TabLeave', 'WinEnter', 'TabEnter', 'BufEnter', 'BufEnter'], s:li)
autocmd! TestTabpageGroup
augroup! TestTabpageGroup
@@ -905,4 +976,40 @@ func Test_tabpage_last_line()
bwipe!
endfunc
+" this was causing an endless loop
+func Test_tabpage_drop_tabmove()
+ augroup TestTabpageTabmove
+ au!
+ autocmd! TabEnter * :if tabpagenr() > 1 | tabmove - | endif
+ augroup end
+ $tab drop XTab_99.log
+ $tab drop XTab_98.log
+ $tab drop XTab_97.log
+
+ autocmd! TestTabpageTabmove
+ augroup! TestTabpageTabmove
+
+ " clean up
+ bwipe!
+ bwipe!
+ bwipe!
+endfunc
+
+" Test that settabvar() shouldn't change the last accessed tabpage.
+func Test_lastused_tabpage_settabvar()
+ tabonly!
+ tabnew
+ tabnew
+ tabnew
+ call assert_equal(3, tabpagenr('#'))
+
+ call settabvar(2, 'myvar', 'tabval')
+ call assert_equal('tabval', gettabvar(2, 'myvar'))
+ call assert_equal(3, tabpagenr('#'))
+
+ bwipe!
+ bwipe!
+ bwipe!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_tagjump.vim b/test/old/testdir/test_tagjump.vim
index 2ef5bd720b..ff1110e070 100644
--- a/test/old/testdir/test_tagjump.vim
+++ b/test/old/testdir/test_tagjump.vim
@@ -907,14 +907,14 @@ func Test_tag_last_search_pat()
\ "first\tXfoo\t/^int first() {}/",
\ "second\tXfoo\t/^int second() {}/",
\ "third\tXfoo\t/^int third() {}/"],
- \ 'Xtags')
+ \ 'Xtags', 'D')
set tags=Xtags
let code =<< trim [CODE]
int first() {}
int second() {}
int third() {}
[CODE]
- call writefile(code, 'Xfoo')
+ call writefile(code, 'Xfoo', 'D')
enew
let save_cpo = &cpo
@@ -924,8 +924,6 @@ func Test_tag_last_search_pat()
call assert_equal('^int second() {}', @/)
let &cpo = save_cpo
- call delete('Xtags')
- call delete('Xfoo')
set tags&
%bwipe
endfunc
@@ -936,27 +934,42 @@ func Test_tag_stack()
for i in range(10, 31)
let l += ["var" .. i .. "\tXfoo\t/^int var" .. i .. ";$/"]
endfor
- call writefile(l, 'Xtags')
+ call writefile(l, 'Xtags', 'D')
set tags=Xtags
let l = []
for i in range(10, 31)
let l += ["int var" .. i .. ";"]
endfor
- call writefile(l, 'Xfoo')
+ call writefile(l, 'Xfoo', 'D')
- " Jump to a tag when the tag stack is full. Oldest entry should be removed.
enew
+ " Jump to a tag when the tag stack is full. Oldest entry should be removed.
for i in range(10, 30)
exe "tag var" .. i
endfor
- let l = gettagstack()
- call assert_equal(20, l.length)
- call assert_equal('var11', l.items[0].tagname)
+ let t = gettagstack()
+ call assert_equal(20, t.length)
+ call assert_equal('var11', t.items[0].tagname)
+ let full = deepcopy(t.items)
tag var31
- let l = gettagstack()
- call assert_equal('var12', l.items[0].tagname)
- call assert_equal('var31', l.items[19].tagname)
+ let t = gettagstack()
+ call assert_equal('var12', t.items[0].tagname)
+ call assert_equal('var31', t.items[19].tagname)
+
+ " Jump to a tag when the tag stack is full, but with user data this time.
+ call foreach(full, {i, item -> extend(item, {'user_data': $'udata{i}'})})
+ call settagstack(0, {'items': full})
+ let t = gettagstack()
+ call assert_equal(20, t.length)
+ call assert_equal('var11', t.items[0].tagname)
+ call assert_equal('udata0', t.items[0].user_data)
+ tag var31
+ let t = gettagstack()
+ call assert_equal('var12', t.items[0].tagname)
+ call assert_equal('udata1', t.items[0].user_data)
+ call assert_equal('var31', t.items[19].tagname)
+ call assert_false(has_key(t.items[19], 'user_data'))
" Use tnext with a single match
call assert_fails('tnext', 'E427:')
@@ -988,8 +1001,6 @@ func Test_tag_stack()
call settagstack(1, {'items' : []})
call assert_fails('pop', 'E73:')
- call delete('Xtags')
- call delete('Xfoo')
set tags&
%bwipe
endfunc
diff --git a/test/old/testdir/test_termdebug.vim b/test/old/testdir/test_termdebug.vim
index 98a4bd3215..33cdaf1611 100644
--- a/test/old/testdir/test_termdebug.vim
+++ b/test/old/testdir/test_termdebug.vim
@@ -18,9 +18,8 @@ if g:GCC->empty()
throw 'Skipped: gcc is not found in $PATH'
endif
-packadd termdebug
-
-func Test_termdebug_basic()
+function s:generate_files(bin_name)
+ let src_name = a:bin_name .. '.c'
let lines =<< trim END
#include <stdio.h>
#include <stdlib.h>
@@ -46,8 +45,21 @@ func Test_termdebug_basic()
return 0;
}
END
- call writefile(lines, 'XTD_basic.c', 'D')
- call system($'{g:GCC} -g -o XTD_basic XTD_basic.c')
+ call writefile(lines, src_name)
+ call system($'{g:GCC} -g -o {a:bin_name} {src_name}')
+endfunction
+
+function s:cleanup_files(bin_name)
+ call delete(a:bin_name)
+ call delete(a:bin_name .. '.c')
+endfunction
+
+packadd termdebug
+
+func Test_termdebug_basic()
+ let bin_name = 'XTD_basic'
+ let src_name = bin_name .. '.c'
+ call s:generate_files(bin_name)
edit XTD_basic.c
Termdebug ./XTD_basic
@@ -149,7 +161,72 @@ func Test_termdebug_basic()
call WaitForAssert({-> assert_equal(1, winnr('$'))})
call assert_equal([], sign_getplaced('', #{group: 'TermDebug'})[0].signs)
- call delete('XTD_basic')
+ call s:cleanup_files(bin_name)
+ %bw!
+endfunc
+
+func Test_termdebug_tbreak()
+ let g:test_is_flaky = 1
+ let bin_name = 'XTD_tbreak'
+ let src_name = bin_name .. '.c'
+
+ eval s:generate_files(bin_name)
+
+ execute 'edit ' .. src_name
+ execute 'Termdebug ./' .. bin_name
+
+ call WaitForAssert({-> assert_equal(3, winnr('$'))})
+ let gdb_buf = winbufnr(1)
+ wincmd b
+
+ let bp_line = 22 " 'return' statement in main
+ let temp_bp_line = 10 " 'if' statement in 'for' loop body
+ execute "Tbreak " .. temp_bp_line
+ execute "Break " .. bp_line
+
+ call Nterm_wait(gdb_buf)
+ redraw!
+ " both temporary and normal breakpoint signs were displayed...
+ call assert_equal([
+ \ {'lnum': temp_bp_line, 'id': 1014, 'name': 'debugBreakpoint1.0',
+ \ 'priority': 110, 'group': 'TermDebug'},
+ \ {'lnum': bp_line, 'id': 2014, 'name': 'debugBreakpoint2.0',
+ \ 'priority': 110, 'group': 'TermDebug'}],
+ \ sign_getplaced('', #{group: 'TermDebug'})[0].signs)
+
+ Run
+ call Nterm_wait(gdb_buf, 400)
+ redraw!
+ " debugPC sign is on the line where the temp. bp was set;
+ " temp. bp sign was removed after hit;
+ " normal bp sign is still present
+ call WaitForAssert({-> assert_equal([
+ \ {'lnum': temp_bp_line, 'id': 12, 'name': 'debugPC', 'priority': 110,
+ \ 'group': 'TermDebug'},
+ \ {'lnum': bp_line, 'id': 2014, 'name': 'debugBreakpoint2.0',
+ \ 'priority': 110, 'group': 'TermDebug'}],
+ \ sign_getplaced('', #{group: 'TermDebug'})[0].signs)})
+
+ Continue
+ call Nterm_wait(gdb_buf)
+ redraw!
+ " debugPC is on the normal breakpoint,
+ " temp. bp on line 10 was only hit once
+ call WaitForAssert({-> assert_equal([
+ \ {'lnum': bp_line, 'id': 12, 'name': 'debugPC', 'priority': 110,
+ \ 'group': 'TermDebug'},
+ \ {'lnum': bp_line, 'id': 2014, 'name': 'debugBreakpoint2.0',
+ \ 'priority': 110, 'group': 'TermDebug'}],
+ "\ sign_getplaced('', #{group: 'TermDebug'})[0].signs)})
+ \ sign_getplaced('', #{group: 'TermDebug'})[0].signs->reverse())})
+
+ wincmd t
+ quit!
+ redraw!
+ call WaitForAssert({-> assert_equal(1, winnr('$'))})
+ call assert_equal([], sign_getplaced('', #{group: 'TermDebug'})[0].signs)
+
+ eval s:cleanup_files(bin_name)
%bw!
endfunc
diff --git a/test/old/testdir/test_textobjects.vim b/test/old/testdir/test_textobjects.vim
index f21d6fcb99..3b86ae97da 100644
--- a/test/old/testdir/test_textobjects.vim
+++ b/test/old/testdir/test_textobjects.vim
@@ -402,7 +402,7 @@ func Test_paragraph()
call assert_beeps("normal Vipip")
exe "normal \<C-C>"
- close!
+ bw!
endfunc
" Tests for text object aw
@@ -608,7 +608,7 @@ func Test_textobj_quote()
normal $hhyi"
call assert_equal('bar', @")
- close!
+ bw!
endfunc
" Test for i(, i<, etc. when cursor is in front of a block
@@ -640,7 +640,133 @@ func Test_textobj_find_paren_forward()
normal 0di)
call assert_equal('foo ()', getline(1))
- close!
+ bw!
+endfunc
+
+func Test_inner_block_empty_paren()
+ new
+ call setline(1, ["(text)()", "", "(text)(", ")", "", "()()", "", "text()"])
+
+ " Example 1
+ call cursor(1, 1)
+ let @" = ''
+ call assert_beeps(':call feedkeys("0f(viby","xt")')
+ call assert_equal(7, getpos('.')[2])
+ call assert_equal('(', @")
+
+ " Example 2
+ call cursor(3, 1)
+ let @" = ''
+ call assert_beeps('call feedkeys("0f(viby", "xt")')
+ call assert_equal(7, getpos('.')[2])
+ call assert_equal('(', @")
+
+ " Example 3
+ call cursor(6, 1)
+ let @" = ''
+ call assert_beeps('call feedkeys("0f(viby", "xt")')
+ call assert_equal(3, getpos('.')[2])
+ call assert_equal('(', @")
+
+ " Change empty inner block
+ call cursor(8, 1)
+ call feedkeys("0cibtext", "xt")
+ call assert_equal("text(text)", getline('.'))
+
+ bwipe!
+endfunc
+
+func Test_inner_block_empty_bracket()
+ new
+ call setline(1, ["[text][]", "", "[text][", "]", "", "[][]", "", "text[]"])
+
+ " Example 1
+ call cursor(1, 1)
+ let @" = ''
+ call assert_beeps(':call feedkeys("0f[viby","xt")')
+ call assert_equal(7, getpos('.')[2])
+ call assert_equal('[', @")
+
+ " Example 2
+ call cursor(3, 1)
+ let @" = ''
+ call assert_beeps('call feedkeys("0f[viby", "xt")')
+ call assert_equal(7, getpos('.')[2])
+ call assert_equal('[', @")
+
+ " Example 3
+ call cursor(6, 1)
+ let @" = ''
+ call assert_beeps('call feedkeys("0f[viby", "xt")')
+ call assert_equal(3, getpos('.')[2])
+ call assert_equal('[', @")
+
+ " Change empty inner block
+ call cursor(8, 1)
+ call feedkeys("0ci[text", "xt")
+ call assert_equal("text[text]", getline('.'))
+
+ bwipe!
+endfunc
+
+func Test_inner_block_empty_brace()
+ new
+ call setline(1, ["{text}{}", "", "{text}{", "}", "", "{}{}", "", "text{}"])
+
+ " Example 1
+ call cursor(1, 1)
+ let @" = ''
+ call assert_beeps(':call feedkeys("0f{viby","xt")')
+ call assert_equal(7, getpos('.')[2])
+ call assert_equal('{', @")
+
+ " Example 2
+ call cursor(3, 1)
+ let @" = ''
+ call assert_beeps('call feedkeys("0f{viby", "xt")')
+ call assert_equal(7, getpos('.')[2])
+ call assert_equal('{', @")
+
+ " Example 3
+ call cursor(6, 1)
+ let @" = ''
+ call assert_beeps('call feedkeys("0f{viby", "xt")')
+ call assert_equal(3, getpos('.')[2])
+ call assert_equal('{', @")
+
+ " Change empty inner block
+ call cursor(8, 1)
+ call feedkeys("0ciBtext", "xt")
+ call assert_equal("text{text}", getline('.'))
+
+ bwipe!
+endfunc
+
+func Test_inner_block_empty_lessthan()
+ new
+ call setline(1, ["<text><>", "", "<text><", ">", "", "<><>"])
+
+ " Example 1
+ call cursor(1, 1)
+ let @" = ''
+ call assert_beeps(':call feedkeys("0f<viby","xt")')
+ call assert_equal(7, getpos('.')[2])
+ call assert_equal('<', @")
+
+ " Example 2
+ call cursor(3, 1)
+ let @" = ''
+ call assert_beeps('call feedkeys("0f<viby", "xt")')
+ call assert_equal(7, getpos('.')[2])
+ call assert_equal('<', @")
+
+ " Example 3
+ call cursor(6, 1)
+ let @" = ''
+ call assert_beeps('call feedkeys("0f<viby", "xt")')
+ call assert_equal(3, getpos('.')[2])
+ call assert_equal('<', @")
+ bwipe!
endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_undo.vim b/test/old/testdir/test_undo.vim
index a06731cc96..a207f4f4e0 100644
--- a/test/old/testdir/test_undo.vim
+++ b/test/old/testdir/test_undo.vim
@@ -588,7 +588,7 @@ funct Test_undofile()
endif
call assert_equal('', undofile(''))
- " Test undofile() with 'undodir' set to to an existing directory.
+ " Test undofile() with 'undodir' set to an existing directory.
call mkdir('Xundodir')
set undodir=Xundodir
let cwd = getcwd()
diff --git a/test/old/testdir/test_utf8_comparisons.vim b/test/old/testdir/test_utf8_comparisons.vim
index f3c86b44fb..2c1972b087 100644
--- a/test/old/testdir/test_utf8_comparisons.vim
+++ b/test/old/testdir/test_utf8_comparisons.vim
@@ -92,3 +92,40 @@ func Test_gap()
call feedkeys("gg0g~ap", "tx")
call assert_equal(["ABCD", "", "defg"], getline(1,3))
endfunc
+
+" test that g~, ~ and gU correctly upper-cases ß
+func Test_uppercase_sharp_ss()
+ new
+ call setline(1, repeat(['ß'], 4))
+
+ call cursor(1, 1)
+ norm! ~
+ call assert_equal('ẞ', getline(line('.')))
+ norm! ~
+ call assert_equal('ß', getline(line('.')))
+
+ call cursor(2, 1)
+ norm! g~l
+ call assert_equal('ẞ', getline(line('.')))
+ norm! g~l
+ call assert_equal('ß', getline(line('.')))
+
+ call cursor(3, 1)
+ norm! gUl
+ call assert_equal('ẞ', getline(line('.')))
+ norm! vgU
+ call assert_equal('ẞ', getline(line('.')))
+ norm! vgu
+ call assert_equal('ß', getline(line('.')))
+ norm! gul
+ call assert_equal('ß', getline(line('.')))
+
+ call cursor(4, 1)
+ norm! vgU
+ call assert_equal('ẞ', getline(line('.')))
+ norm! vgu
+ call assert_equal('ß', getline(line('.')))
+ bw!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_virtualedit.vim b/test/old/testdir/test_virtualedit.vim
index 4780faa706..6448c7a3e3 100644
--- a/test/old/testdir/test_virtualedit.vim
+++ b/test/old/testdir/test_virtualedit.vim
@@ -77,13 +77,30 @@ endfunc
func Test_edit_change()
new
set virtualedit=all
+
call setline(1, "\t⒌")
normal Cx
call assert_equal('x', getline(1))
+
+ call setline(1, "\ta̳")
+ normal Cx
+ call assert_equal('x', getline(1))
+
+ call setline(1, "\tβ̳")
+ normal Cx
+ call assert_equal('x', getline(1))
+
+ if has('arabic')
+ call setline(1, "\tلا")
+ normal Cx
+ call assert_equal('x', getline(1))
+ endif
+
" Do a visual block change
call setline(1, ['a', 'b', 'c'])
exe "normal gg3l\<C-V>2jcx"
call assert_equal(['a x', 'b x', 'c x'], getline(1, '$'))
+
bwipe!
set virtualedit=
endfunc
diff --git a/test/old/testdir/test_visual.vim b/test/old/testdir/test_visual.vim
index 5d70492451..4c5ab9f61f 100644
--- a/test/old/testdir/test_visual.vim
+++ b/test/old/testdir/test_visual.vim
@@ -3,6 +3,7 @@
source shared.vim
source check.vim
source screendump.vim
+source vim9.vim
func Test_block_shift_multibyte()
" Uses double-wide character.
@@ -1010,7 +1011,7 @@ endfunc
" Test for changing case
func Test_visual_change_case()
new
- " gUe must uppercase a whole word, also when ß changes to SS
+ " gUe must uppercase a whole word, also when ß changes to ẞ
exe "normal Gothe youtußeuu end\<Esc>Ypk0wgUe\r"
" gUfx must uppercase until x, inclusive.
exe "normal O- youßtußexu -\<Esc>0fogUfx\r"
@@ -1022,9 +1023,9 @@ func Test_visual_change_case()
exe "normal Oblah di\rdoh dut\<Esc>VkUj\r"
" Uppercase part of two lines
exe "normal ddppi333\<Esc>k0i222\<Esc>fyllvjfuUk"
- call assert_equal(['the YOUTUSSEUU end', '- yOUSSTUSSEXu -',
- \ 'THE YOUTUSSEUU END', '111THE YOUTUSSEUU END', 'BLAH DI', 'DOH DUT',
- \ '222the yoUTUSSEUU END', '333THE YOUTUßeuu end'], getline(2, '$'))
+ call assert_equal(['the YOUTUẞEUU end', '- yOUẞTUẞEXu -',
+ \ 'THE YOUTUẞEUU END', '111THE YOUTUẞEUU END', 'BLAH DI', 'DOH DUT',
+ \ '222the yoUTUẞEUU END', '333THE YOUTUßeuu end'], getline(2, '$'))
bwipe!
endfunc
@@ -1589,6 +1590,353 @@ func Test_Visual_r_CTRL_C()
call feedkeys("\<c-v>$gr\<c-c>", 'tx')
call assert_equal([''], getline(1, 1))
bw!
-endfu
+endfunc
+
+func Test_visual_drag_out_of_window()
+ rightbelow vnew
+ call setline(1, '123456789')
+ set mouse=a
+ func ClickExpr(off)
+ call Ntest_setmouse(1, getwininfo(win_getid())[0].wincol + a:off)
+ return "\<LeftMouse>"
+ endfunc
+ func DragExpr(off)
+ call Ntest_setmouse(1, getwininfo(win_getid())[0].wincol + a:off)
+ return "\<LeftDrag>"
+ endfunc
+
+ nnoremap <expr> <F2> ClickExpr(5)
+ nnoremap <expr> <F3> DragExpr(-1)
+ redraw
+ call feedkeys("\<F2>\<F3>\<LeftRelease>", 'tx')
+ call assert_equal([1, 6], [col('.'), col('v')])
+ call feedkeys("\<Esc>", 'tx')
+
+ nnoremap <expr> <F2> ClickExpr(6)
+ nnoremap <expr> <F3> DragExpr(-2)
+ redraw
+ call feedkeys("\<F2>\<F3>\<LeftRelease>", 'tx')
+ call assert_equal([1, 7], [col('.'), col('v')])
+ call feedkeys("\<Esc>", 'tx')
+
+ nunmap <F2>
+ nunmap <F3>
+ delfunc ClickExpr
+ delfunc DragExpr
+ set mouse&
+ bwipe!
+endfunc
+
+func Test_visual_substitute_visual()
+ new
+ call setline(1, ['one', 'two', 'three'])
+ call feedkeys("Gk\<C-V>j$:s/\\%V\\_.*\\%V/foobar\<CR>", 'tx')
+ call assert_equal(['one', 'foobar'], getline(1, '$'))
+ bwipe!
+endfunc
+
+func Test_visual_getregion()
+ let lines =<< trim END
+ new
+
+ call setline(1, ['one', 'two', 'three'])
+
+ #" Visual mode
+ call cursor(1, 1)
+ call feedkeys("\<ESC>vjl", 'tx')
+ call assert_equal(['one', 'tw'],
+ \ 'v'->getpos()->getregion(getpos('.')))
+ call assert_equal(['one', 'tw'],
+ \ '.'->getpos()->getregion(getpos('v')))
+ call assert_equal(['o'],
+ \ 'v'->getpos()->getregion(getpos('v')))
+ call assert_equal(['w'],
+ \ '.'->getpos()->getregion(getpos('.'), {'type': 'v' }))
+ call assert_equal(['one', 'two'],
+ \ getpos('.')->getregion(getpos('v'), {'type': 'V' }))
+ call assert_equal(['on', 'tw'],
+ \ getpos('.')->getregion(getpos('v'), {'type': "\<C-v>" }))
+
+ #" Line visual mode
+ call cursor(1, 1)
+ call feedkeys("\<ESC>Vl", 'tx')
+ call assert_equal(['one'],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'V' }))
+ call assert_equal(['one'],
+ \ getregion(getpos('.'), getpos('v'), {'type': 'V' }))
+ call assert_equal(['one'],
+ \ getregion(getpos('v'), getpos('v'), {'type': 'V' }))
+ call assert_equal(['one'],
+ \ getregion(getpos('.'), getpos('.'), {'type': 'V' }))
+ call assert_equal(['on'],
+ \ getpos('.')->getregion(getpos('v'), {'type': 'v' }))
+ call assert_equal(['on'],
+ \ getpos('.')->getregion(getpos('v'), {'type': "\<C-v>" }))
+
+ #" Block visual mode
+ call cursor(1, 1)
+ call feedkeys("\<ESC>\<C-v>ll", 'tx')
+ call assert_equal(['one'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call assert_equal(['one'],
+ \ getregion(getpos('.'), getpos('v'), {'type': "\<C-v>" }))
+ call assert_equal(['o'],
+ \ getregion(getpos('v'), getpos('v'), {'type': "\<C-v>" }))
+ call assert_equal(['e'],
+ \ getregion(getpos('.'), getpos('.'), {'type': "\<C-v>" }))
+ call assert_equal(['one'],
+ \ '.'->getpos()->getregion(getpos('v'), {'type': 'V' }))
+ call assert_equal(['one'],
+ \ '.'->getpos()->getregion(getpos('v'), {'type': 'v' }))
+
+ #" Using Marks
+ call setpos("'a", [0, 2, 3, 0])
+ call cursor(1, 1)
+ call assert_equal(['one', 'two'],
+ \ "'a"->getpos()->getregion(getpos('.'), {'type': 'v' }))
+ call assert_equal(['one', 'two'],
+ \ "."->getpos()->getregion(getpos("'a"), {'type': 'v' }))
+ call assert_equal(['one', 'two'],
+ \ "."->getpos()->getregion(getpos("'a"), {'type': 'V' }))
+ call assert_equal(['two'],
+ \ "'a"->getpos()->getregion(getpos("'a"), {'type': 'V' }))
+ call assert_equal(['one', 'two'],
+ \ "."->getpos()->getregion(getpos("'a"), {'type': "\<c-v>" }))
+
+ #" Using List
+ call cursor(1, 1)
+ call assert_equal(['one', 'two'],
+ \ [0, 2, 3, 0]->getregion(getpos('.'), {'type': 'v' }))
+ call assert_equal(['one', 'two'],
+ \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': 'v' }))
+ call assert_equal(['one', 'two'],
+ \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': 'V' }))
+ call assert_equal(['two'],
+ \ [0, 2, 3, 0]->getregion([0, 2, 3, 0], {'type': 'V' }))
+ call assert_equal(['one', 'two'],
+ \ '.'->getpos()->getregion([0, 2, 3, 0], {'type': "\<c-v>" }))
+
+ #" Multiline with line visual mode
+ call cursor(1, 1)
+ call feedkeys("\<ESC>Vjj", 'tx')
+ call assert_equal(['one', 'two', 'three'],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'V' }))
+
+ #" Multiline with block visual mode
+ call cursor(1, 1)
+ call feedkeys("\<ESC>\<C-v>jj", 'tx')
+ call assert_equal(['o', 't', 't'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
+ call cursor(1, 1)
+ call feedkeys("\<ESC>\<C-v>jj$", 'tx')
+ call assert_equal(['one', 'two', 'three'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+
+ #" 'virtualedit'
+ set virtualedit=all
+ call cursor(1, 1)
+ call feedkeys("\<ESC>\<C-v>10ljj$", 'tx')
+ call assert_equal(['one ', 'two ', 'three '],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ set virtualedit&
+
+ #" Invalid position
+ call cursor(1, 1)
+ call feedkeys("\<ESC>vjj$", 'tx')
+ call assert_fails("call getregion(1, 2)", 'E1211:')
+ call assert_fails("call getregion(getpos('.'), {})", 'E1211:')
+ call assert_equal([], getregion(getpos('.'), getpos('.'), {'type': '' }))
+
+ #" using the wrong type
+ call assert_fails(':echo "."->getpos()->getregion("$", [])', 'E1211:')
+
+ #" using a mark from another buffer to current buffer
+ new
+ VAR newbuf = bufnr()
+ call setline(1, range(10))
+ normal! GmA
+ wincmd p
+ call assert_equal([newbuf, 10, 1, 0], getpos("'A"))
+ call assert_equal([], getregion(getpos('.'), getpos("'A"), {'type': 'v' }))
+ call assert_equal([], getregion(getpos("'A"), getpos('.'), {'type': 'v' }))
+ exe $':{newbuf}bwipe!'
+
+ #" using a mark from another buffer to another buffer
+ new
+ VAR anotherbuf = bufnr()
+ call setline(1, range(10))
+ normal! GmA
+ normal! GmB
+ wincmd p
+ call assert_equal([anotherbuf, 10, 1, 0], getpos("'A"))
+ call assert_equal(['9'], getregion(getpos("'B"), getpos("'A"), {'type': 'v' }))
+ exe $':{anotherbuf}bwipe!'
+
+ #" using invalid buffer
+ call assert_equal([], getregion([10000, 10, 1, 0], [10000, 10, 1, 0]))
+ END
+ call CheckLegacyAndVim9Success(lines)
+
+ bwipe!
+
+ let lines =<< trim END
+ #" Selection in starts or ends in the middle of a multibyte character
+ new
+ call setline(1, [
+ \ "abcdefghijk\u00ab",
+ \ "\U0001f1e6\u00ab\U0001f1e7\u00ab\U0001f1e8\u00ab\U0001f1e9",
+ \ "1234567890"
+ \ ])
+ call cursor(1, 3)
+ call feedkeys("\<Esc>\<C-v>ljj", 'xt')
+ call assert_equal(['cd', "\u00ab ", '34'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call cursor(1, 4)
+ call feedkeys("\<Esc>\<C-v>ljj", 'xt')
+ call assert_equal(['de', "\U0001f1e7", '45'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call cursor(1, 5)
+ call feedkeys("\<Esc>\<C-v>jj", 'xt')
+ call assert_equal(['e', ' ', '5'],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>vj", 'xt')
+ call assert_equal(['abcdefghijk«', "\U0001f1e6"],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+
+ #" marks on multibyte chars
+ :set selection=exclusive
+ call setpos("'a", [0, 1, 11, 0])
+ call setpos("'b", [0, 2, 16, 0])
+ call setpos("'c", [0, 2, 0, 0])
+ call cursor(1, 1)
+ call assert_equal(['ghijk', '🇨«🇩'],
+ \ getregion(getpos("'a"), getpos("'b"), {'type': "\<c-v>" }))
+ call assert_equal(['k«', '🇦«🇧«🇨'],
+ \ getregion(getpos("'a"), getpos("'b"), {'type': 'v' }))
+ call assert_equal(['k«'],
+ \ getregion(getpos("'a"), getpos("'c"), {'type': 'v' }))
+
+ #" use inclusive selection, although 'selection' is exclusive
+ call setpos("'a", [0, 1, 11, 0])
+ call setpos("'b", [0, 1, 1, 0])
+ call assert_equal(['abcdefghijk'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': "\<c-v>", 'exclusive': v:false }))
+ call assert_equal(['abcdefghij'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': "\<c-v>", 'exclusive': v:true }))
+ call assert_equal(['abcdefghijk'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': 'v', 'exclusive': 0 }))
+ call assert_equal(['abcdefghij'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': 'v', 'exclusive': 1 }))
+ call assert_equal(['abcdefghijk«'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': 'V', 'exclusive': 0 }))
+ call assert_equal(['abcdefghijk«'],
+ \ getregion(getpos("'a"), getpos("'b"),
+ \ {'type': 'V', 'exclusive': 1 }))
+ :set selection&
+ END
+ call CheckLegacyAndVim9Success(lines)
+
+ bwipe!
+
+ let lines =<< trim END
+ #" Exclusive selection
+ new
+ set selection=exclusive
+ call setline(1, ["a\tc", "x\tz", '', ''])
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v2l", 'xt')
+ call assert_equal(["a\t"],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v$G", 'xt')
+ call assert_equal(["a\tc", "x\tz", ''],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v$j", 'xt')
+ call assert_equal(["a\tc", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>\<C-v>$j", 'xt')
+ call assert_equal(["a\tc", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>\<C-v>$G", 'xt')
+ call assert_equal(["a", "x", '', ''],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>wv2j", 'xt')
+ call assert_equal(["c", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ set selection&
+
+ #" Exclusive selection 2
+ new
+ call setline(1, ["a\tc", "x\tz", '', ''])
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v2l", 'xt')
+ call assert_equal(["a\t"],
+ \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v$G", 'xt')
+ call assert_equal(["a\tc", "x\tz", ''],
+ \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>v$j", 'xt')
+ call assert_equal(["a\tc", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>\<C-v>$j", 'xt')
+ call assert_equal(["a\tc", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'),
+ \ {'exclusive': v:true, 'type': "\<C-v>" }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>\<C-v>$G", 'xt')
+ call assert_equal(["a", "x", '', ''],
+ \ getregion(getpos('v'), getpos('.'),
+ \ {'exclusive': v:true, 'type': "\<C-v>" }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>wv2j", 'xt')
+ call assert_equal(["c", "x\tz"],
+ \ getregion(getpos('v'), getpos('.'), {'exclusive': v:true }))
+
+ #" virtualedit
+ set selection=exclusive
+ set virtualedit=all
+ call cursor(1, 1)
+ call feedkeys("\<Esc>2lv2lj", 'xt')
+ call assert_equal([' c', 'x '],
+ \ getregion(getpos('v'), getpos('.'), {'type': 'v' }))
+ call cursor(1, 1)
+ call feedkeys("\<Esc>2l\<C-v>2l2j", 'xt')
+ call assert_equal([' ', ' ', ' '],
+ \ getregion(getpos('v'), getpos('.'), {'type': "\<C-v>" }))
+ set virtualedit&
+ set selection&
+
+ bwipe!
+ END
+ call CheckLegacyAndVim9Success(lines)
+endfunc
+
+func Test_getregion_invalid_buf()
+ new
+ help
+ call cursor(5, 7)
+ norm! mA
+ call cursor(5, 18)
+ norm! mB
+ call assert_equal(['Move around:'], getregion(getpos("'A"), getpos("'B")))
+ " close the help window
+ q
+ call assert_equal([], getregion(getpos("'A"), getpos("'B")))
+ bwipe!
+endfunc
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/test/old/testdir/test_window_cmd.vim b/test/old/testdir/test_window_cmd.vim
index 152d1bacc7..da1711a0a1 100644
--- a/test/old/testdir/test_window_cmd.vim
+++ b/test/old/testdir/test_window_cmd.vim
@@ -113,6 +113,64 @@ func Test_window_quit()
bw Xa Xb
endfunc
+func Test_window_curwin_not_prevwin()
+ botright split
+ call assert_equal(2, winnr())
+ call assert_equal(1, winnr('#'))
+ quit
+ call assert_equal(1, winnr())
+ call assert_equal(0, winnr('#'))
+
+ botright split
+ botright split
+ call assert_equal(3, winnr())
+ call assert_equal(2, winnr('#'))
+ 1quit
+ call assert_equal(2, winnr())
+ call assert_equal(1, winnr('#'))
+
+ botright split
+ call assert_equal(1, tabpagenr())
+ call assert_equal(3, winnr())
+ call assert_equal(2, winnr('#'))
+ wincmd T
+ call assert_equal(2, tabpagenr())
+ call assert_equal(1, winnr())
+ call assert_equal(0, winnr('#'))
+ tabfirst
+ call assert_equal(1, tabpagenr())
+ call assert_equal(2, winnr())
+ call assert_equal(0, winnr('#'))
+
+ tabonly
+ botright split
+ wincmd t
+ wincmd p
+ call assert_equal(3, winnr())
+ call assert_equal(1, winnr('#'))
+ quit
+ call assert_equal(2, winnr())
+ call assert_equal(1, winnr('#'))
+
+ botright split
+ wincmd t
+ wincmd p
+ call assert_equal(1, tabpagenr())
+ call assert_equal(3, winnr())
+ call assert_equal(1, winnr('#'))
+ wincmd T
+ call assert_equal(2, tabpagenr())
+ call assert_equal(1, winnr())
+ call assert_equal(0, winnr('#'))
+ tabfirst
+ call assert_equal(1, tabpagenr())
+ call assert_equal(2, winnr())
+ call assert_equal(1, winnr('#'))
+
+ tabonly
+ only
+endfunc
+
func Test_window_horizontal_split()
call assert_equal(1, winnr('$'))
3wincmd s
diff --git a/test/old/testdir/vim9.vim b/test/old/testdir/vim9.vim
index 825f01c9d6..218fab6c5e 100644
--- a/test/old/testdir/vim9.vim
+++ b/test/old/testdir/vim9.vim
@@ -2,6 +2,10 @@
" Use a different file name for each run.
let s:sequence = 1
+func CheckDefSuccess(lines)
+ return
+endfunc
+
func CheckDefFailure(lines, error, lnum = -3)
return
endfunc
@@ -42,6 +46,49 @@ func CheckScriptSuccess(lines)
endtry
endfunc
+" :source a list of "lines" and check whether it fails with "error"
+func CheckSourceFailure(lines, error, lnum = -3)
+ if get(a:lines, 0, '') ==# 'vim9script'
+ return
+ endif
+ new
+ call setline(1, a:lines)
+ try
+ call assert_fails('source', a:error, a:lines, a:lnum)
+ finally
+ bw!
+ endtry
+endfunc
+
+" :source a list of "lines" and check whether it fails with the list of
+" "errors"
+func CheckSourceFailureList(lines, errors, lnum = -3)
+ if get(a:lines, 0, '') ==# 'vim9script'
+ return
+ endif
+ new
+ call setline(1, a:lines)
+ try
+ call assert_fails('source', a:errors, a:lines, a:lnum)
+ finally
+ bw!
+ endtry
+endfunc
+
+" :source a list of "lines" and check whether it succeeds
+func CheckSourceSuccess(lines)
+ if get(a:lines, 0, '') ==# 'vim9script'
+ return
+ endif
+ new
+ call setline(1, a:lines)
+ try
+ :source
+ finally
+ bw!
+ endtry
+endfunc
+
func CheckDefAndScriptSuccess(lines)
return
endfunc
diff --git a/test/unit/api/helpers.lua b/test/unit/api/helpers.lua
index 3d306d2b1b..23c5db43f7 100644
--- a/test/unit/api/helpers.lua
+++ b/test/unit/api/helpers.lua
@@ -13,9 +13,11 @@ local int_type = eval_helpers.int_type
local flt_type = eval_helpers.flt_type
local type_key = eval_helpers.type_key
-local api = cimport('./src/nvim/api/private/defs.h',
- './src/nvim/api/private/helpers.h',
- './src/nvim/memory.h')
+local api = cimport(
+ './src/nvim/api/private/defs.h',
+ './src/nvim/api/private/helpers.h',
+ './src/nvim/memory.h'
+)
local obj2lua
@@ -27,8 +29,8 @@ local function init_obj2lua_tab()
end
obj2lua_tab = {
[tonumber(api.kObjectTypeArray)] = function(obj)
- local ret = {[type_key]=list_type}
- for i = 1,tonumber(obj.data.array.size) do
+ local ret = { [type_key] = list_type }
+ for i = 1, tonumber(obj.data.array.size) do
ret[i] = obj2lua(obj.data.array.items[i - 1])
end
if ret[1] then
@@ -38,7 +40,7 @@ local function init_obj2lua_tab()
end,
[tonumber(api.kObjectTypeDictionary)] = function(obj)
local ret = {}
- for i = 1,tonumber(obj.data.dictionary.size) do
+ for i = 1, tonumber(obj.data.dictionary.size) do
local kv_pair = obj.data.dictionary.items[i - 1]
ret[ffi.string(kv_pair.key.data, kv_pair.key.size)] = obj2lua(kv_pair.value)
end
@@ -58,7 +60,7 @@ local function init_obj2lua_tab()
return tonumber(obj.data.floating)
end,
[tonumber(api.kObjectTypeInteger)] = function(obj)
- return {[type_key]=int_type, value=tonumber(obj.data.integer)}
+ return { [type_key] = int_type, value = tonumber(obj.data.integer) }
end,
[tonumber(api.kObjectTypeString)] = function(obj)
return ffi.string(obj.data.string.data, obj.data.string.size)
@@ -68,32 +70,38 @@ end
obj2lua = function(obj)
init_obj2lua_tab()
- return ((obj2lua_tab[tonumber(obj['type'])] or function(obj_inner)
- assert(false, 'Converting ' .. tostring(tonumber(obj_inner['type'])) .. ' is not implementing yet')
- end)(obj))
+ return (
+ (obj2lua_tab[tonumber(obj['type'])] or function(obj_inner)
+ assert(
+ false,
+ 'Converting ' .. tostring(tonumber(obj_inner['type'])) .. ' is not implementing yet'
+ )
+ end)(obj)
+ )
end
local obj = function(typ, data)
- return ffi.gc(ffi.new('Object', {['type']=typ, data=data}),
- api.api_free_object)
+ return ffi.gc(ffi.new('Object', { ['type'] = typ, data = data }), api.api_free_object)
end
local lua2obj
local lua2obj_type_tab = {
[int_type] = function(l)
- return obj(api.kObjectTypeInteger, {integer=l.value})
+ return obj(api.kObjectTypeInteger, { integer = l.value })
end,
[flt_type] = function(l)
- return obj(api.kObjectTypeFloat, {floating=l})
+ return obj(api.kObjectTypeFloat, { floating = l })
end,
[list_type] = function(l)
local len = #l
- local arr = obj(api.kObjectTypeArray, {array={
- size=len,
- capacity=len,
- items=ffi.cast('Object *', api.xmalloc(len * ffi.sizeof('Object'))),
- }})
+ local arr = obj(api.kObjectTypeArray, {
+ array = {
+ size = len,
+ capacity = len,
+ items = ffi.cast('Object *', api.xmalloc(len * ffi.sizeof('Object'))),
+ },
+ })
for i = 1, len do
arr.data.array.items[i - 1] = ffi.gc(lua2obj(l[i]), nil)
end
@@ -103,21 +111,23 @@ local lua2obj_type_tab = {
local kvs = {}
for k, v in pairs(l) do
if type(k) == 'string' then
- kvs[#kvs + 1] = {k, v}
+ kvs[#kvs + 1] = { k, v }
end
end
local len = #kvs
- local dct = obj(api.kObjectTypeDictionary, {dictionary={
- size=len,
- capacity=len,
- items=ffi.cast('KeyValuePair *',
- api.xmalloc(len * ffi.sizeof('KeyValuePair'))),
- }})
+ local dct = obj(api.kObjectTypeDictionary, {
+ dictionary = {
+ size = len,
+ capacity = len,
+ items = ffi.cast('KeyValuePair *', api.xmalloc(len * ffi.sizeof('KeyValuePair'))),
+ },
+ })
for i = 1, len do
local key, val = unpack(kvs[i])
dct.data.dictionary.items[i - 1] = ffi.new(
- 'KeyValuePair', {key=ffi.gc(lua2obj(key), nil).data.string,
- value=ffi.gc(lua2obj(val), nil)})
+ 'KeyValuePair',
+ { key = ffi.gc(lua2obj(key), nil).data.string, value = ffi.gc(lua2obj(val), nil) }
+ )
end
return dct
end,
@@ -137,28 +147,31 @@ lua2obj = function(l)
elseif type(l) == 'number' then
return lua2obj_type_tab[flt_type](l)
elseif type(l) == 'boolean' then
- return obj(api.kObjectTypeBoolean, {boolean=l})
+ return obj(api.kObjectTypeBoolean, { boolean = l })
elseif type(l) == 'string' then
- return obj(api.kObjectTypeString, {string={
- size=#l,
- data=api.xmemdupz(to_cstr(l), #l),
- }})
+ return obj(
+ api.kObjectTypeString,
+ { string = {
+ size = #l,
+ data = api.xmemdupz(to_cstr(l), #l),
+ } }
+ )
elseif l == nil or l == nil_value then
- return obj(api.kObjectTypeNil, {integer=0})
+ return obj(api.kObjectTypeNil, { integer = 0 })
end
end
return {
- list_type=list_type,
- dict_type=dict_type,
- func_type=func_type,
- int_type=int_type,
- flt_type=flt_type,
+ list_type = list_type,
+ dict_type = dict_type,
+ func_type = func_type,
+ int_type = int_type,
+ flt_type = flt_type,
- nil_value=nil_value,
+ nil_value = nil_value,
- type_key=type_key,
+ type_key = type_key,
- obj2lua=obj2lua,
- lua2obj=lua2obj,
+ obj2lua = obj2lua,
+ lua2obj = lua2obj,
}
diff --git a/test/unit/api/private_helpers_spec.lua b/test/unit/api/private_helpers_spec.lua
index dbb4b3ae5a..9843bd5c9e 100644
--- a/test/unit/api/private_helpers_spec.lua
+++ b/test/unit/api/private_helpers_spec.lua
@@ -22,7 +22,7 @@ local api = cimport('./src/nvim/api/private/helpers.h', './src/nvim/api/private/
describe('vim_to_object', function()
local vim_to_object = function(l)
- return obj2lua(api.vim_to_object(lua2typvalt(l)))
+ return obj2lua(api.vim_to_object(lua2typvalt(l), nil, false))
end
local different_output_test = function(name, input, output)
@@ -42,65 +42,77 @@ describe('vim_to_object', function()
simple_test('converts -1.5', -1.5)
simple_test('converts empty string', '')
simple_test('converts non-empty string', 'foobar')
- simple_test('converts integer 10', {[type_key]=int_type, value=10})
+ simple_test('converts integer 10', { [type_key] = int_type, value = 10 })
simple_test('converts empty dictionary', {})
- simple_test('converts dictionary with scalar values', {test=10, test2=true, test3='test'})
- simple_test('converts dictionary with containers inside', {test={}, test2={1, 2}})
- simple_test('converts empty list', {[type_key]=list_type})
- simple_test('converts list with scalar values', {1, 2, 'test', 'foo'})
- simple_test('converts list with containers inside', {{}, {test={}, test3={test4=true}}})
+ simple_test('converts dictionary with scalar values', { test = 10, test2 = true, test3 = 'test' })
+ simple_test('converts dictionary with containers inside', { test = {}, test2 = { 1, 2 } })
+ simple_test('converts empty list', { [type_key] = list_type })
+ simple_test('converts list with scalar values', { 1, 2, 'test', 'foo' })
+ simple_test(
+ 'converts list with containers inside',
+ { {}, { test = {}, test3 = { test4 = true } } }
+ )
local dct = {}
dct.dct = dct
- different_output_test('outputs nil for nested dictionaries (1 level)', dct, {dct=nil_value})
+ different_output_test('outputs nil for nested dictionaries (1 level)', dct, { dct = nil_value })
local lst = {}
lst[1] = lst
- different_output_test('outputs nil for nested lists (1 level)', lst, {nil_value})
-
- local dct2 = {test=true, dict=nil_value}
- dct2.dct = {dct2}
- different_output_test('outputs nil for nested dictionaries (2 level, in list)',
- dct2, {dct={nil_value}, test=true, dict=nil_value})
-
- local dct3 = {test=true, dict=nil_value}
- dct3.dct = {dctin=dct3}
- different_output_test('outputs nil for nested dictionaries (2 level, in dict)',
- dct3, {dct={dctin=nil_value}, test=true, dict=nil_value})
+ different_output_test('outputs nil for nested lists (1 level)', lst, { nil_value })
+
+ local dct2 = { test = true, dict = nil_value }
+ dct2.dct = { dct2 }
+ different_output_test(
+ 'outputs nil for nested dictionaries (2 level, in list)',
+ dct2,
+ { dct = { nil_value }, test = true, dict = nil_value }
+ )
+
+ local dct3 = { test = true, dict = nil_value }
+ dct3.dct = { dctin = dct3 }
+ different_output_test(
+ 'outputs nil for nested dictionaries (2 level, in dict)',
+ dct3,
+ { dct = { dctin = nil_value }, test = true, dict = nil_value }
+ )
local lst2 = {}
- lst2[1] = {lst2}
- different_output_test('outputs nil for nested lists (2 level, in list)', lst2, {{nil_value}})
+ lst2[1] = { lst2 }
+ different_output_test('outputs nil for nested lists (2 level, in list)', lst2, { { nil_value } })
- local lst3 = {nil, true, false, 'ttest'}
- lst3[1] = {lst=lst3}
- different_output_test('outputs nil for nested lists (2 level, in dict)',
- lst3, {{lst=nil_value}, true, false, 'ttest'})
+ local lst3 = { nil, true, false, 'ttest' }
+ lst3[1] = { lst = lst3 }
+ different_output_test(
+ 'outputs nil for nested lists (2 level, in dict)',
+ lst3,
+ { { lst = nil_value }, true, false, 'ttest' }
+ )
itp('outputs empty list for NULL list', function()
- local tt = typvalt('VAR_LIST', {v_list=NULL})
+ local tt = typvalt('VAR_LIST', { v_list = NULL })
eq(nil, tt.vval.v_list)
- eq({[type_key]=list_type}, obj2lua(api.vim_to_object(tt)))
+ eq({ [type_key] = list_type }, obj2lua(api.vim_to_object(tt, nil, false)))
end)
itp('outputs empty dict for NULL dict', function()
- local tt = typvalt('VAR_DICT', {v_dict=NULL})
+ local tt = typvalt('VAR_DICT', { v_dict = NULL })
eq(nil, tt.vval.v_dict)
- eq({}, obj2lua(api.vim_to_object(tt)))
+ eq({}, obj2lua(api.vim_to_object(tt, nil, false)))
end)
itp('regression: partials in a list', function()
local llist = {
{
- [type_key]=func_type,
- value='printf',
- args={'%s'},
- dict={v=1},
+ [type_key] = func_type,
+ value = 'printf',
+ args = { '%s' },
+ dict = { v = 1 },
},
{},
}
local list = lua2typvalt(llist)
eq(llist, typvalt2lua(list))
- eq({nil_value, {}}, obj2lua(api.vim_to_object(list)))
+ eq({ nil_value, {} }, obj2lua(api.vim_to_object(list, nil, false)))
end)
end)
diff --git a/test/unit/buffer_spec.lua b/test/unit/buffer_spec.lua
index 6e08a09295..1ef3e97165 100644
--- a/test/unit/buffer_spec.lua
+++ b/test/unit/buffer_spec.lua
@@ -1,14 +1,13 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local to_cstr = helpers.to_cstr
-local eq = helpers.eq
-local NULL = helpers.NULL
+local eq = helpers.eq
+local NULL = helpers.NULL
-local buffer = helpers.cimport("./src/nvim/buffer.h")
+local buffer = helpers.cimport('./src/nvim/buffer.h')
describe('buffer functions', function()
-
local buflist_new = function(file, flags)
local c_file = to_cstr(file)
return buffer.buflist_new(c_file, c_file, 1, flags)
@@ -36,7 +35,6 @@ describe('buffer functions', function()
end)
describe('buf_valid', function()
-
itp('should view NULL as an invalid buffer', function()
eq(false, buffer.buf_valid(NULL))
end)
@@ -72,11 +70,9 @@ describe('buffer functions', function()
end)
end)
-
describe('buflist_findpat', function()
-
local ALLOW_UNLISTED = 1
- local ONLY_LISTED = 0
+ local ONLY_LISTED = 0
local buflist_findpat = function(pat, allow_unlisted)
return buffer.buflist_findpat(to_cstr(pat), NULL, allow_unlisted, 0, 0)
@@ -95,9 +91,9 @@ describe('buffer functions', function()
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
- eq(buf1.handle, buflist_findpat("test", ONLY_LISTED))
- eq(buf2.handle, buflist_findpat("file", ONLY_LISTED))
- eq(buf3.handle, buflist_findpat("path", ONLY_LISTED))
+ eq(buf1.handle, buflist_findpat('test', ONLY_LISTED))
+ eq(buf2.handle, buflist_findpat('file', ONLY_LISTED))
+ eq(buf3.handle, buflist_findpat('path', ONLY_LISTED))
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0, 0)
@@ -111,7 +107,7 @@ describe('buffer functions', function()
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
-- Then: buf2 is the buffer that is found
- eq(buf2.handle, buflist_findpat("test", ONLY_LISTED))
+ eq(buf2.handle, buflist_findpat('test', ONLY_LISTED))
--}
--{ When: We close buf2
@@ -121,7 +117,7 @@ describe('buffer functions', function()
local buf1 = buflist_new(path1, buffer.BLN_LISTED)
-- Then: buf3 is found since 'file' appears at the end of the name
- eq(buf3.handle, buflist_findpat("file", ONLY_LISTED))
+ eq(buf3.handle, buflist_findpat('file', ONLY_LISTED))
--}
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
@@ -133,7 +129,7 @@ describe('buffer functions', function()
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
- eq(buf3.handle, buflist_findpat("_test_", ONLY_LISTED))
+ eq(buf3.handle, buflist_findpat('_test_', ONLY_LISTED))
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
close_buffer(NULL, buf2, buffer.DOBUF_WIPE, 0, 0)
@@ -145,25 +141,25 @@ describe('buffer functions', function()
local buf3 = buflist_new(path3, buffer.BLN_LISTED)
-- Then: We should find the buffer when it is given a unique pattern
- eq(buf3.handle, buflist_findpat("_test_", ONLY_LISTED))
+ eq(buf3.handle, buflist_findpat('_test_', ONLY_LISTED))
--}
--{ When: We unlist the buffer
close_buffer(NULL, buf3, buffer.DOBUF_DEL, 0, 0)
-- Then: It should not find the buffer when searching only listed buffers
- eq(-1, buflist_findpat("_test_", ONLY_LISTED))
+ eq(-1, buflist_findpat('_test_', ONLY_LISTED))
-- And: It should find the buffer when including unlisted buffers
- eq(buf3.handle, buflist_findpat("_test_", ALLOW_UNLISTED))
+ eq(buf3.handle, buflist_findpat('_test_', ALLOW_UNLISTED))
--}
--{ When: We wipe the buffer
close_buffer(NULL, buf3, buffer.DOBUF_WIPE, 0, 0)
-- Then: It should not find the buffer at all
- eq(-1, buflist_findpat("_test_", ONLY_LISTED))
- eq(-1, buflist_findpat("_test_", ALLOW_UNLISTED))
+ eq(-1, buflist_findpat('_test_', ONLY_LISTED))
+ eq(-1, buflist_findpat('_test_', ALLOW_UNLISTED))
--}
end)
@@ -173,7 +169,7 @@ describe('buffer functions', function()
local buf2 = buflist_new(path2, buffer.BLN_LISTED)
-- Then: The first buffer is preferred when both are listed
- eq(buf1.handle, buflist_findpat("test", ONLY_LISTED))
+ eq(buf1.handle, buflist_findpat('test', ONLY_LISTED))
--}
--{ When: The first buffer is unlisted
@@ -181,13 +177,13 @@ describe('buffer functions', function()
-- Then: The second buffer is preferred because
-- unlisted buffers are not allowed
- eq(buf2.handle, buflist_findpat("test", ONLY_LISTED))
+ eq(buf2.handle, buflist_findpat('test', ONLY_LISTED))
--}
--{ When: We allow unlisted buffers
-- Then: The second buffer is still preferred
-- because listed buffers are preferred to unlisted
- eq(buf2.handle, buflist_findpat("test", ALLOW_UNLISTED))
+ eq(buf2.handle, buflist_findpat('test', ALLOW_UNLISTED))
--}
--{ When: We unlist the second buffer
@@ -196,10 +192,10 @@ describe('buffer functions', function()
-- Then: The first buffer is preferred again
-- because buf1 matches better which takes precedence
-- when both buffers have the same listing status.
- eq(buf1.handle, buflist_findpat("test", ALLOW_UNLISTED))
+ eq(buf1.handle, buflist_findpat('test', ALLOW_UNLISTED))
-- And: Neither buffer is returned when ignoring unlisted
- eq(-1, buflist_findpat("test", ONLY_LISTED))
+ eq(-1, buflist_findpat('test', ONLY_LISTED))
--}
close_buffer(NULL, buf1, buffer.DOBUF_WIPE, 0, 0)
diff --git a/test/unit/charset/vim_str2nr_spec.lua b/test/unit/charset/vim_str2nr_spec.lua
index fc40fa39d4..ad87d026e5 100644
--- a/test/unit/charset/vim_str2nr_spec.lua
+++ b/test/unit/charset/vim_str2nr_spec.lua
@@ -1,4 +1,4 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local bit = require('bit')
local itp = helpers.gen_itp(it)
@@ -26,10 +26,10 @@ local ucnt = 4242
local function arginit(arg)
if arg == 'unum' then
ucnt = ucnt + 1
- return ARGTYPES[arg]({ucnt})
+ return ARGTYPES[arg]({ ucnt })
else
icnt = icnt - 1
- return ARGTYPES[arg]({icnt})
+ return ARGTYPES[arg]({ icnt })
end
end
@@ -44,7 +44,9 @@ local function argreset(arg, args)
end
local function test_vim_str2nr(s, what, exp, maxlen, strict)
- if strict == nil then strict = true end
+ if strict == nil then
+ strict = true
+ end
local bits = {}
for k, _ in pairs(exp) do
bits[#bits + 1] = k
@@ -54,7 +56,7 @@ local function test_vim_str2nr(s, what, exp, maxlen, strict)
for k, _ in pairs(ARGTYPES) do
args[k] = arginit(k)
end
- for case = 0, ((2 ^ (#bits)) - 1) do
+ for case = 0, ((2 ^ #bits) - 1) do
local cv = {}
for b = 0, (#bits - 1) do
if bit.band(case, (2 ^ b)) == 0 then
@@ -66,9 +68,17 @@ local function test_vim_str2nr(s, what, exp, maxlen, strict)
lib.vim_str2nr(s, cv.pre, cv.len, what, cv.num, cv.unum, maxlen, strict, nil)
for cck, ccv in pairs(cv) do
if exp[cck] ~= tonumber(ccv[0]) then
- error(('Failed check (%s = %d) in test (s=%s, w=%u, m=%d, strict=%s): %d'):format(
- cck, exp[cck], s, tonumber(what), maxlen, tostring(strict), tonumber(ccv[0])
- ))
+ error(
+ ('Failed check (%s = %d) in test (s=%s, w=%u, m=%d, strict=%s): %d'):format(
+ cck,
+ exp[cck],
+ s,
+ tonumber(what),
+ maxlen,
+ tostring(strict),
+ tonumber(ccv[0])
+ )
+ )
end
end
end
@@ -82,18 +92,48 @@ end
describe('vim_str2nr()', function()
itp('works fine when it has nothing to do', function()
- test_vim_str2nr('', 0, {len = 0, num = 0, unum = 0, pre = 0}, 0)
- test_vim_str2nr('', lib.STR2NR_ALL, {len = 0, num = 0, unum = 0, pre = 0}, 0)
- test_vim_str2nr('', lib.STR2NR_BIN, {len = 0, num = 0, unum = 0, pre = 0}, 0)
- test_vim_str2nr('', lib.STR2NR_OCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
- test_vim_str2nr('', lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
- test_vim_str2nr('', lib.STR2NR_HEX, {len = 0, num = 0, unum = 0, pre = 0}, 0)
- test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_DEC, {len = 0, num = 0, unum = 0, pre = 0}, 0)
- test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_BIN, {len = 0, num = 0, unum = 0, pre = 0}, 0)
- test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
- test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
- test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT, {len = 0, num = 0, unum = 0, pre = 0}, 0)
- test_vim_str2nr('', lib.STR2NR_FORCE + lib.STR2NR_HEX, {len = 0, num = 0, unum = 0, pre = 0}, 0)
+ test_vim_str2nr('', 0, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
+ test_vim_str2nr('', lib.STR2NR_ALL, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
+ test_vim_str2nr('', lib.STR2NR_BIN, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
+ test_vim_str2nr('', lib.STR2NR_OCT, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
+ test_vim_str2nr('', lib.STR2NR_OOCT, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
+ test_vim_str2nr('', lib.STR2NR_HEX, { len = 0, num = 0, unum = 0, pre = 0 }, 0)
+ test_vim_str2nr(
+ '',
+ lib.STR2NR_FORCE + lib.STR2NR_DEC,
+ { len = 0, num = 0, unum = 0, pre = 0 },
+ 0
+ )
+ test_vim_str2nr(
+ '',
+ lib.STR2NR_FORCE + lib.STR2NR_BIN,
+ { len = 0, num = 0, unum = 0, pre = 0 },
+ 0
+ )
+ test_vim_str2nr(
+ '',
+ lib.STR2NR_FORCE + lib.STR2NR_OCT,
+ { len = 0, num = 0, unum = 0, pre = 0 },
+ 0
+ )
+ test_vim_str2nr(
+ '',
+ lib.STR2NR_FORCE + lib.STR2NR_OOCT,
+ { len = 0, num = 0, unum = 0, pre = 0 },
+ 0
+ )
+ test_vim_str2nr(
+ '',
+ lib.STR2NR_FORCE + lib.STR2NR_OCT + lib.STR2NR_OOCT,
+ { len = 0, num = 0, unum = 0, pre = 0 },
+ 0
+ )
+ test_vim_str2nr(
+ '',
+ lib.STR2NR_FORCE + lib.STR2NR_HEX,
+ { len = 0, num = 0, unum = 0, pre = 0 },
+ 0
+ )
end)
itp('works with decimal numbers', function()
for _, flags in ipairs({
@@ -110,30 +150,30 @@ describe('vim_str2nr()', function()
lib.STR2NR_FORCE + lib.STR2NR_DEC,
}) do
-- Check that all digits are recognized
- test_vim_str2nr( '12345', flags, {len = 5, num = 12345, unum = 12345, pre = 0}, 0)
- test_vim_str2nr( '67890', flags, {len = 5, num = 67890, unum = 67890, pre = 0}, 0)
- test_vim_str2nr( '12345A', flags, {len = 0}, 0)
- test_vim_str2nr( '67890A', flags, {len = 0}, 0)
- test_vim_str2nr( '12345A', flags, {len = 5, num = 12345, unum = 12345, pre = 0}, 0, false)
- test_vim_str2nr( '67890A', flags, {len = 5, num = 67890, unum = 67890, pre = 0}, 0, false)
-
- test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 0)
- test_vim_str2nr( '42', flags, {len = 1, num = 4, unum = 4, pre = 0}, 1)
- test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 2)
- test_vim_str2nr( '42', flags, {len = 2, num = 42, unum = 42, pre = 0}, 3) -- includes NUL byte in maxlen
-
- test_vim_str2nr( '42x', flags, {len = 0}, 0)
- test_vim_str2nr( '42x', flags, {len = 0}, 3)
- test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 0, false)
- test_vim_str2nr( '42x', flags, {len = 2, num = 42, unum = 42, pre = 0}, 3, false)
-
- test_vim_str2nr('-42', flags, {len = 3, num = -42, unum = 42, pre = 0}, 3)
- test_vim_str2nr('-42', flags, {len = 1, num = 0, unum = 0, pre = 0}, 1)
-
- test_vim_str2nr('-42x', flags, {len = 0}, 0)
- test_vim_str2nr('-42x', flags, {len = 0}, 4)
- test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 0, false)
- test_vim_str2nr('-42x', flags, {len = 3, num = -42, unum = 42, pre = 0}, 4, false)
+ test_vim_str2nr('12345', flags, { len = 5, num = 12345, unum = 12345, pre = 0 }, 0)
+ test_vim_str2nr('67890', flags, { len = 5, num = 67890, unum = 67890, pre = 0 }, 0)
+ test_vim_str2nr('12345A', flags, { len = 0 }, 0)
+ test_vim_str2nr('67890A', flags, { len = 0 }, 0)
+ test_vim_str2nr('12345A', flags, { len = 5, num = 12345, unum = 12345, pre = 0 }, 0, false)
+ test_vim_str2nr('67890A', flags, { len = 5, num = 67890, unum = 67890, pre = 0 }, 0, false)
+
+ test_vim_str2nr('42', flags, { len = 2, num = 42, unum = 42, pre = 0 }, 0)
+ test_vim_str2nr('42', flags, { len = 1, num = 4, unum = 4, pre = 0 }, 1)
+ test_vim_str2nr('42', flags, { len = 2, num = 42, unum = 42, pre = 0 }, 2)
+ test_vim_str2nr('42', flags, { len = 2, num = 42, unum = 42, pre = 0 }, 3) -- includes NUL byte in maxlen
+
+ test_vim_str2nr('42x', flags, { len = 0 }, 0)
+ test_vim_str2nr('42x', flags, { len = 0 }, 3)
+ test_vim_str2nr('42x', flags, { len = 2, num = 42, unum = 42, pre = 0 }, 0, false)
+ test_vim_str2nr('42x', flags, { len = 2, num = 42, unum = 42, pre = 0 }, 3, false)
+
+ test_vim_str2nr('-42', flags, { len = 3, num = -42, unum = 42, pre = 0 }, 3)
+ test_vim_str2nr('-42', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+
+ test_vim_str2nr('-42x', flags, { len = 0 }, 0)
+ test_vim_str2nr('-42x', flags, { len = 0 }, 4)
+ test_vim_str2nr('-42x', flags, { len = 3, num = -42, unum = 42, pre = 0 }, 0, false)
+ test_vim_str2nr('-42x', flags, { len = 3, num = -42, unum = 42, pre = 0 }, 4, false)
end
end)
itp('works with binary numbers', function()
@@ -154,66 +194,66 @@ describe('vim_str2nr()', function()
BIN = ('B'):byte()
end
- test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 0)
- test_vim_str2nr( '0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr( '0b101', flags, {len = 0}, 2)
- test_vim_str2nr( '0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
- test_vim_str2nr( '0b101', flags, {len = 3, num = 1, unum = 1, pre = bin}, 3)
- test_vim_str2nr( '0b101', flags, {len = 4, num = 2, unum = 2, pre = bin}, 4)
- test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 5)
- test_vim_str2nr( '0b101', flags, {len = 5, num = 5, unum = 5, pre = bin}, 6)
-
- test_vim_str2nr( '0b1012', flags, {len = 0}, 0)
- test_vim_str2nr( '0b1012', flags, {len = 0}, 6)
- test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 0, false)
- test_vim_str2nr( '0b1012', flags, {len = 5, num = 5, unum = 5, pre = bin}, 6, false)
-
- test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 0)
- test_vim_str2nr('-0b101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr('-0b101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
- test_vim_str2nr('-0b101', flags, {len = 0}, 3)
- test_vim_str2nr('-0b101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
- test_vim_str2nr('-0b101', flags, {len = 4, num = -1, unum = 1, pre = bin}, 4)
- test_vim_str2nr('-0b101', flags, {len = 5, num = -2, unum = 2, pre = bin}, 5)
- test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 6)
- test_vim_str2nr('-0b101', flags, {len = 6, num = -5, unum = 5, pre = bin}, 7)
-
- test_vim_str2nr('-0b1012', flags, {len = 0}, 0)
- test_vim_str2nr('-0b1012', flags, {len = 0}, 7)
- test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 0, false)
- test_vim_str2nr('-0b1012', flags, {len = 6, num = -5, unum = 5, pre = bin}, 7, false)
-
- test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 0)
- test_vim_str2nr( '0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr( '0B101', flags, {len = 0}, 2)
- test_vim_str2nr( '0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
- test_vim_str2nr( '0B101', flags, {len = 3, num = 1, unum = 1, pre = BIN}, 3)
- test_vim_str2nr( '0B101', flags, {len = 4, num = 2, unum = 2, pre = BIN}, 4)
- test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 5)
- test_vim_str2nr( '0B101', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 6)
-
- test_vim_str2nr( '0B1012', flags, {len = 0}, 0)
- test_vim_str2nr( '0B1012', flags, {len = 0}, 6)
- test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 0, false)
- test_vim_str2nr( '0B1012', flags, {len = 5, num = 5, unum = 5, pre = BIN}, 6, false)
-
- test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 0)
- test_vim_str2nr('-0B101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr('-0B101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
- test_vim_str2nr('-0B101', flags, {len = 0}, 3)
- test_vim_str2nr('-0B101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
- test_vim_str2nr('-0B101', flags, {len = 4, num = -1, unum = 1, pre = BIN}, 4)
- test_vim_str2nr('-0B101', flags, {len = 5, num = -2, unum = 2, pre = BIN}, 5)
- test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 6)
- test_vim_str2nr('-0B101', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 7)
-
- test_vim_str2nr('-0B1012', flags, {len = 0}, 0)
- test_vim_str2nr('-0B1012', flags, {len = 0}, 7)
- test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 0, false)
- test_vim_str2nr('-0B1012', flags, {len = 6, num = -5, unum = 5, pre = BIN}, 7, false)
+ test_vim_str2nr('0b101', flags, { len = 5, num = 5, unum = 5, pre = bin }, 0)
+ test_vim_str2nr('0b101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('0b101', flags, { len = 0 }, 2)
+ test_vim_str2nr('0b101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
+ test_vim_str2nr('0b101', flags, { len = 3, num = 1, unum = 1, pre = bin }, 3)
+ test_vim_str2nr('0b101', flags, { len = 4, num = 2, unum = 2, pre = bin }, 4)
+ test_vim_str2nr('0b101', flags, { len = 5, num = 5, unum = 5, pre = bin }, 5)
+ test_vim_str2nr('0b101', flags, { len = 5, num = 5, unum = 5, pre = bin }, 6)
+
+ test_vim_str2nr('0b1012', flags, { len = 0 }, 0)
+ test_vim_str2nr('0b1012', flags, { len = 0 }, 6)
+ test_vim_str2nr('0b1012', flags, { len = 5, num = 5, unum = 5, pre = bin }, 0, false)
+ test_vim_str2nr('0b1012', flags, { len = 5, num = 5, unum = 5, pre = bin }, 6, false)
+
+ test_vim_str2nr('-0b101', flags, { len = 6, num = -5, unum = 5, pre = bin }, 0)
+ test_vim_str2nr('-0b101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('-0b101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr('-0b101', flags, { len = 0 }, 3)
+ test_vim_str2nr('-0b101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
+ test_vim_str2nr('-0b101', flags, { len = 4, num = -1, unum = 1, pre = bin }, 4)
+ test_vim_str2nr('-0b101', flags, { len = 5, num = -2, unum = 2, pre = bin }, 5)
+ test_vim_str2nr('-0b101', flags, { len = 6, num = -5, unum = 5, pre = bin }, 6)
+ test_vim_str2nr('-0b101', flags, { len = 6, num = -5, unum = 5, pre = bin }, 7)
+
+ test_vim_str2nr('-0b1012', flags, { len = 0 }, 0)
+ test_vim_str2nr('-0b1012', flags, { len = 0 }, 7)
+ test_vim_str2nr('-0b1012', flags, { len = 6, num = -5, unum = 5, pre = bin }, 0, false)
+ test_vim_str2nr('-0b1012', flags, { len = 6, num = -5, unum = 5, pre = bin }, 7, false)
+
+ test_vim_str2nr('0B101', flags, { len = 5, num = 5, unum = 5, pre = BIN }, 0)
+ test_vim_str2nr('0B101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('0B101', flags, { len = 0 }, 2)
+ test_vim_str2nr('0B101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
+ test_vim_str2nr('0B101', flags, { len = 3, num = 1, unum = 1, pre = BIN }, 3)
+ test_vim_str2nr('0B101', flags, { len = 4, num = 2, unum = 2, pre = BIN }, 4)
+ test_vim_str2nr('0B101', flags, { len = 5, num = 5, unum = 5, pre = BIN }, 5)
+ test_vim_str2nr('0B101', flags, { len = 5, num = 5, unum = 5, pre = BIN }, 6)
+
+ test_vim_str2nr('0B1012', flags, { len = 0 }, 0)
+ test_vim_str2nr('0B1012', flags, { len = 0 }, 6)
+ test_vim_str2nr('0B1012', flags, { len = 5, num = 5, unum = 5, pre = BIN }, 0, false)
+ test_vim_str2nr('0B1012', flags, { len = 5, num = 5, unum = 5, pre = BIN }, 6, false)
+
+ test_vim_str2nr('-0B101', flags, { len = 6, num = -5, unum = 5, pre = BIN }, 0)
+ test_vim_str2nr('-0B101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('-0B101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr('-0B101', flags, { len = 0 }, 3)
+ test_vim_str2nr('-0B101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
+ test_vim_str2nr('-0B101', flags, { len = 4, num = -1, unum = 1, pre = BIN }, 4)
+ test_vim_str2nr('-0B101', flags, { len = 5, num = -2, unum = 2, pre = BIN }, 5)
+ test_vim_str2nr('-0B101', flags, { len = 6, num = -5, unum = 5, pre = BIN }, 6)
+ test_vim_str2nr('-0B101', flags, { len = 6, num = -5, unum = 5, pre = BIN }, 7)
+
+ test_vim_str2nr('-0B1012', flags, { len = 0 }, 0)
+ test_vim_str2nr('-0B1012', flags, { len = 0 }, 7)
+ test_vim_str2nr('-0B1012', flags, { len = 6, num = -5, unum = 5, pre = BIN }, 0, false)
+ test_vim_str2nr('-0B1012', flags, { len = 6, num = -5, unum = 5, pre = BIN }, 7, false)
if flags > lib.STR2NR_FORCE then
- test_vim_str2nr('-101', flags, {len = 4, num = -5, unum = 5, pre = 0}, 0)
+ test_vim_str2nr('-101', flags, { len = 4, num = -5, unum = 5, pre = 0 }, 0)
end
end
end)
@@ -236,42 +276,42 @@ describe('vim_str2nr()', function()
end
-- Check that all digits are recognized
- test_vim_str2nr( '012345670', flags, {len = 9, num = 2739128, unum = 2739128, pre = oct}, 0)
-
- test_vim_str2nr( '054', flags, {len = 3, num = 44, unum = 44, pre = oct}, 0)
- test_vim_str2nr( '054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr( '054', flags, {len = 2, num = 5, unum = 5, pre = oct}, 2)
- test_vim_str2nr( '054', flags, {len = 3, num = 44, unum = 44, pre = oct}, 3)
- test_vim_str2nr( '0548', flags, {len = 3, num = 44, unum = 44, pre = oct}, 3)
- test_vim_str2nr( '054', flags, {len = 3, num = 44, unum = 44, pre = oct}, 4)
-
- test_vim_str2nr( '054x', flags, {len = 0}, 4)
- test_vim_str2nr( '054x', flags, {len = 0}, 0)
- test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 4, false)
- test_vim_str2nr( '054x', flags, {len = 3, num = 44, unum = 44, pre = oct}, 0, false)
-
- test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 0)
- test_vim_str2nr('-054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr('-054', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
- test_vim_str2nr('-054', flags, {len = 3, num = -5, unum = 5, pre = oct}, 3)
- test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 4)
- test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = oct}, 4)
- test_vim_str2nr('-054', flags, {len = 4, num = -44, unum = 44, pre = oct}, 5)
-
- test_vim_str2nr('-054x', flags, {len = 0}, 5)
- test_vim_str2nr('-054x', flags, {len = 0}, 0)
- test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 5, false)
- test_vim_str2nr('-054x', flags, {len = 4, num = -44, unum = 44, pre = oct}, 0, false)
+ test_vim_str2nr('012345670', flags, { len = 9, num = 2739128, unum = 2739128, pre = oct }, 0)
+
+ test_vim_str2nr('054', flags, { len = 3, num = 44, unum = 44, pre = oct }, 0)
+ test_vim_str2nr('054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('054', flags, { len = 2, num = 5, unum = 5, pre = oct }, 2)
+ test_vim_str2nr('054', flags, { len = 3, num = 44, unum = 44, pre = oct }, 3)
+ test_vim_str2nr('0548', flags, { len = 3, num = 44, unum = 44, pre = oct }, 3)
+ test_vim_str2nr('054', flags, { len = 3, num = 44, unum = 44, pre = oct }, 4)
+
+ test_vim_str2nr('054x', flags, { len = 0 }, 4)
+ test_vim_str2nr('054x', flags, { len = 0 }, 0)
+ test_vim_str2nr('054x', flags, { len = 3, num = 44, unum = 44, pre = oct }, 4, false)
+ test_vim_str2nr('054x', flags, { len = 3, num = 44, unum = 44, pre = oct }, 0, false)
+
+ test_vim_str2nr('-054', flags, { len = 4, num = -44, unum = 44, pre = oct }, 0)
+ test_vim_str2nr('-054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('-054', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr('-054', flags, { len = 3, num = -5, unum = 5, pre = oct }, 3)
+ test_vim_str2nr('-054', flags, { len = 4, num = -44, unum = 44, pre = oct }, 4)
+ test_vim_str2nr('-0548', flags, { len = 4, num = -44, unum = 44, pre = oct }, 4)
+ test_vim_str2nr('-054', flags, { len = 4, num = -44, unum = 44, pre = oct }, 5)
+
+ test_vim_str2nr('-054x', flags, { len = 0 }, 5)
+ test_vim_str2nr('-054x', flags, { len = 0 }, 0)
+ test_vim_str2nr('-054x', flags, { len = 4, num = -44, unum = 44, pre = oct }, 5, false)
+ test_vim_str2nr('-054x', flags, { len = 4, num = -44, unum = 44, pre = oct }, 0, false)
if flags > lib.STR2NR_FORCE then
- test_vim_str2nr('-54', flags, {len = 3, num = -44, unum = 44, pre = 0}, 0)
- test_vim_str2nr('-0548', flags, {len = 0}, 5)
- test_vim_str2nr('-0548', flags, {len = 0}, 0)
- test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 5, false)
- test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 0, false)
+ test_vim_str2nr('-54', flags, { len = 3, num = -44, unum = 44, pre = 0 }, 0)
+ test_vim_str2nr('-0548', flags, { len = 0 }, 5)
+ test_vim_str2nr('-0548', flags, { len = 0 }, 0)
+ test_vim_str2nr('-0548', flags, { len = 4, num = -44, unum = 44, pre = 0 }, 5, false)
+ test_vim_str2nr('-0548', flags, { len = 4, num = -44, unum = 44, pre = 0 }, 0, false)
else
- test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 5)
- test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 0)
+ test_vim_str2nr('-0548', flags, { len = 5, num = -548, unum = 548, pre = 0 }, 5)
+ test_vim_str2nr('-0548', flags, { len = 5, num = -548, unum = 548, pre = 0 }, 0)
end
end
end)
@@ -298,73 +338,73 @@ describe('vim_str2nr()', function()
OCT = ('O'):byte()
end
- test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 0)
- test_vim_str2nr( '0o054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr( '0o054', flags, {len = 0}, 2)
- test_vim_str2nr( '0o054', flags, {len = 3, num = 0, unum = 0, pre = oct}, 3)
- test_vim_str2nr( '0o054', flags, {len = 4, num = 5, unum = 5, pre = oct}, 4)
- test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 5)
- test_vim_str2nr( '0o0548', flags, {len = 5, num = 44, unum = 44, pre = oct}, 5)
- test_vim_str2nr( '0o054', flags, {len = 5, num = 44, unum = 44, pre = oct}, 6)
-
- test_vim_str2nr( '0o054x', flags, {len = 0}, 6)
- test_vim_str2nr( '0o054x', flags, {len = 0}, 0)
- test_vim_str2nr( '0o054x', flags, {len = 5, num = 44, unum = 44, pre = oct}, 6, false)
- test_vim_str2nr( '0o054x', flags, {len = 5, num = 44, unum = 44, pre = oct}, 0, false)
-
- test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 0)
- test_vim_str2nr('-0o054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr('-0o054', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
- test_vim_str2nr('-0o054', flags, {len = 0}, 3)
- test_vim_str2nr('-0o054', flags, {len = 4, num = 0, unum = 0, pre = oct}, 4)
- test_vim_str2nr('-0o054', flags, {len = 5, num = -5, unum = 5, pre = oct}, 5)
- test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 6)
- test_vim_str2nr('-0o0548', flags, {len = 6, num = -44, unum = 44, pre = oct}, 6)
- test_vim_str2nr('-0o054', flags, {len = 6, num = -44, unum = 44, pre = oct}, 7)
-
- test_vim_str2nr('-0o054x', flags, {len = 0}, 7)
- test_vim_str2nr('-0o054x', flags, {len = 0}, 0)
- test_vim_str2nr('-0o054x', flags, {len = 6, num = -44, unum = 44, pre = oct}, 7, false)
- test_vim_str2nr('-0o054x', flags, {len = 6, num = -44, unum = 44, pre = oct}, 0, false)
-
- test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 0)
- test_vim_str2nr( '0O054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr( '0O054', flags, {len = 0}, 2)
- test_vim_str2nr( '0O054', flags, {len = 3, num = 0, unum = 0, pre = OCT}, 3)
- test_vim_str2nr( '0O054', flags, {len = 4, num = 5, unum = 5, pre = OCT}, 4)
- test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 5)
- test_vim_str2nr( '0O0548', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 5)
- test_vim_str2nr( '0O054', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 6)
-
- test_vim_str2nr( '0O054x', flags, {len = 0}, 6)
- test_vim_str2nr( '0O054x', flags, {len = 0}, 0)
- test_vim_str2nr( '0O054x', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 6, false)
- test_vim_str2nr( '0O054x', flags, {len = 5, num = 44, unum = 44, pre = OCT}, 0, false)
-
- test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 0)
- test_vim_str2nr('-0O054', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr('-0O054', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
- test_vim_str2nr('-0O054', flags, {len = 0}, 3)
- test_vim_str2nr('-0O054', flags, {len = 4, num = 0, unum = 0, pre = OCT}, 4)
- test_vim_str2nr('-0O054', flags, {len = 5, num = -5, unum = 5, pre = OCT}, 5)
- test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 6)
- test_vim_str2nr('-0O0548', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 6)
- test_vim_str2nr('-0O054', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 7)
-
- test_vim_str2nr('-0O054x', flags, {len = 0}, 7)
- test_vim_str2nr('-0O054x', flags, {len = 0}, 0)
- test_vim_str2nr('-0O054x', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 7, false)
- test_vim_str2nr('-0O054x', flags, {len = 6, num = -44, unum = 44, pre = OCT}, 0, false)
+ test_vim_str2nr('0o054', flags, { len = 5, num = 44, unum = 44, pre = oct }, 0)
+ test_vim_str2nr('0o054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('0o054', flags, { len = 0 }, 2)
+ test_vim_str2nr('0o054', flags, { len = 3, num = 0, unum = 0, pre = oct }, 3)
+ test_vim_str2nr('0o054', flags, { len = 4, num = 5, unum = 5, pre = oct }, 4)
+ test_vim_str2nr('0o054', flags, { len = 5, num = 44, unum = 44, pre = oct }, 5)
+ test_vim_str2nr('0o0548', flags, { len = 5, num = 44, unum = 44, pre = oct }, 5)
+ test_vim_str2nr('0o054', flags, { len = 5, num = 44, unum = 44, pre = oct }, 6)
+
+ test_vim_str2nr('0o054x', flags, { len = 0 }, 6)
+ test_vim_str2nr('0o054x', flags, { len = 0 }, 0)
+ test_vim_str2nr('0o054x', flags, { len = 5, num = 44, unum = 44, pre = oct }, 6, false)
+ test_vim_str2nr('0o054x', flags, { len = 5, num = 44, unum = 44, pre = oct }, 0, false)
+
+ test_vim_str2nr('-0o054', flags, { len = 6, num = -44, unum = 44, pre = oct }, 0)
+ test_vim_str2nr('-0o054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('-0o054', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr('-0o054', flags, { len = 0 }, 3)
+ test_vim_str2nr('-0o054', flags, { len = 4, num = 0, unum = 0, pre = oct }, 4)
+ test_vim_str2nr('-0o054', flags, { len = 5, num = -5, unum = 5, pre = oct }, 5)
+ test_vim_str2nr('-0o054', flags, { len = 6, num = -44, unum = 44, pre = oct }, 6)
+ test_vim_str2nr('-0o0548', flags, { len = 6, num = -44, unum = 44, pre = oct }, 6)
+ test_vim_str2nr('-0o054', flags, { len = 6, num = -44, unum = 44, pre = oct }, 7)
+
+ test_vim_str2nr('-0o054x', flags, { len = 0 }, 7)
+ test_vim_str2nr('-0o054x', flags, { len = 0 }, 0)
+ test_vim_str2nr('-0o054x', flags, { len = 6, num = -44, unum = 44, pre = oct }, 7, false)
+ test_vim_str2nr('-0o054x', flags, { len = 6, num = -44, unum = 44, pre = oct }, 0, false)
+
+ test_vim_str2nr('0O054', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 0)
+ test_vim_str2nr('0O054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('0O054', flags, { len = 0 }, 2)
+ test_vim_str2nr('0O054', flags, { len = 3, num = 0, unum = 0, pre = OCT }, 3)
+ test_vim_str2nr('0O054', flags, { len = 4, num = 5, unum = 5, pre = OCT }, 4)
+ test_vim_str2nr('0O054', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 5)
+ test_vim_str2nr('0O0548', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 5)
+ test_vim_str2nr('0O054', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 6)
+
+ test_vim_str2nr('0O054x', flags, { len = 0 }, 6)
+ test_vim_str2nr('0O054x', flags, { len = 0 }, 0)
+ test_vim_str2nr('0O054x', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 6, false)
+ test_vim_str2nr('0O054x', flags, { len = 5, num = 44, unum = 44, pre = OCT }, 0, false)
+
+ test_vim_str2nr('-0O054', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 0)
+ test_vim_str2nr('-0O054', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('-0O054', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr('-0O054', flags, { len = 0 }, 3)
+ test_vim_str2nr('-0O054', flags, { len = 4, num = 0, unum = 0, pre = OCT }, 4)
+ test_vim_str2nr('-0O054', flags, { len = 5, num = -5, unum = 5, pre = OCT }, 5)
+ test_vim_str2nr('-0O054', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 6)
+ test_vim_str2nr('-0O0548', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 6)
+ test_vim_str2nr('-0O054', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 7)
+
+ test_vim_str2nr('-0O054x', flags, { len = 0 }, 7)
+ test_vim_str2nr('-0O054x', flags, { len = 0 }, 0)
+ test_vim_str2nr('-0O054x', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 7, false)
+ test_vim_str2nr('-0O054x', flags, { len = 6, num = -44, unum = 44, pre = OCT }, 0, false)
if flags > lib.STR2NR_FORCE then
- test_vim_str2nr('-0548', flags, {len = 0}, 5)
- test_vim_str2nr('-0548', flags, {len = 0}, 0)
- test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 5, false)
- test_vim_str2nr('-0548', flags, {len = 4, num = -44, unum = 44, pre = 0}, 0, false)
- test_vim_str2nr('-055', flags, {len = 4, num = -45, unum = 45, pre = 0}, 0)
+ test_vim_str2nr('-0548', flags, { len = 0 }, 5)
+ test_vim_str2nr('-0548', flags, { len = 0 }, 0)
+ test_vim_str2nr('-0548', flags, { len = 4, num = -44, unum = 44, pre = 0 }, 5, false)
+ test_vim_str2nr('-0548', flags, { len = 4, num = -44, unum = 44, pre = 0 }, 0, false)
+ test_vim_str2nr('-055', flags, { len = 4, num = -45, unum = 45, pre = 0 }, 0)
else
- test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 5)
- test_vim_str2nr('-0548', flags, {len = 5, num = -548, unum = 548, pre = 0}, 0)
+ test_vim_str2nr('-0548', flags, { len = 5, num = -548, unum = 548, pre = 0 }, 5)
+ test_vim_str2nr('-0548', flags, { len = 5, num = -548, unum = 548, pre = 0 }, 0)
end
end
end)
@@ -387,92 +427,92 @@ describe('vim_str2nr()', function()
end
-- Check that all digits are recognized
- test_vim_str2nr('0x12345', flags, {len = 7, num = 74565, unum = 74565, pre = hex}, 0)
- test_vim_str2nr('0x67890', flags, {len = 7, num = 424080, unum = 424080, pre = hex}, 0)
- test_vim_str2nr('0xABCDEF', flags, {len = 8, num = 11259375, unum = 11259375, pre = hex}, 0)
- test_vim_str2nr('0xabcdef', flags, {len = 8, num = 11259375, unum = 11259375, pre = hex}, 0)
-
- test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 0)
- test_vim_str2nr( '0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr( '0x101', flags, {len = 0}, 2)
- test_vim_str2nr( '0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
- test_vim_str2nr( '0x101', flags, {len = 3, num = 1, unum = 1, pre = hex}, 3)
- test_vim_str2nr( '0x101', flags, {len = 4, num = 16, unum = 16, pre = hex}, 4)
- test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 5)
- test_vim_str2nr( '0x101', flags, {len = 5, num = 257, unum =257, pre = hex}, 6)
-
- test_vim_str2nr( '0x101G', flags, {len = 0}, 0)
- test_vim_str2nr( '0x101G', flags, {len = 0}, 6)
- test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 0, false)
- test_vim_str2nr( '0x101G', flags, {len = 5, num = 257, unum =257, pre = hex}, 6, false)
-
- test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 0)
- test_vim_str2nr('-0x101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr('-0x101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
- test_vim_str2nr('-0x101', flags, {len = 0}, 3)
- test_vim_str2nr('-0x101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
- test_vim_str2nr('-0x101', flags, {len = 4, num = -1, unum = 1, pre = hex}, 4)
- test_vim_str2nr('-0x101', flags, {len = 5, num = -16, unum = 16, pre = hex}, 5)
- test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 6)
- test_vim_str2nr('-0x101', flags, {len = 6, num =-257, unum =257, pre = hex}, 7)
-
- test_vim_str2nr('-0x101G', flags, {len = 0}, 0)
- test_vim_str2nr('-0x101G', flags, {len = 0}, 7)
- test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 0, false)
- test_vim_str2nr('-0x101G', flags, {len = 6, num =-257, unum =257, pre = hex}, 7, false)
-
- test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 0)
- test_vim_str2nr( '0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr( '0X101', flags, {len = 0}, 2)
- test_vim_str2nr( '0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
- test_vim_str2nr( '0X101', flags, {len = 3, num = 1, unum = 1, pre = HEX}, 3)
- test_vim_str2nr( '0X101', flags, {len = 4, num = 16, unum = 16, pre = HEX}, 4)
- test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 5)
- test_vim_str2nr( '0X101', flags, {len = 5, num = 257, unum =257, pre = HEX}, 6)
-
- test_vim_str2nr( '0X101G', flags, {len = 0}, 0)
- test_vim_str2nr( '0X101G', flags, {len = 0}, 6)
- test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 0, false)
- test_vim_str2nr( '0X101G', flags, {len = 5, num = 257, unum =257, pre = HEX}, 6, false)
-
- test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 0)
- test_vim_str2nr('-0X101', flags, {len = 1, num = 0, unum = 0, pre = 0 }, 1)
- test_vim_str2nr('-0X101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 2)
- test_vim_str2nr('-0X101', flags, {len = 0}, 3)
- test_vim_str2nr('-0X101', flags, {len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
- test_vim_str2nr('-0X101', flags, {len = 4, num = -1, unum = 1, pre = HEX}, 4)
- test_vim_str2nr('-0X101', flags, {len = 5, num = -16, unum = 16, pre = HEX}, 5)
- test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 6)
- test_vim_str2nr('-0X101', flags, {len = 6, num =-257, unum =257, pre = HEX}, 7)
-
- test_vim_str2nr('-0X101G', flags, {len = 0}, 0)
- test_vim_str2nr('-0X101G', flags, {len = 0}, 7)
- test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 0, false)
- test_vim_str2nr('-0X101G', flags, {len = 6, num =-257, unum =257, pre = HEX}, 7, false)
+ test_vim_str2nr('0x12345', flags, { len = 7, num = 74565, unum = 74565, pre = hex }, 0)
+ test_vim_str2nr('0x67890', flags, { len = 7, num = 424080, unum = 424080, pre = hex }, 0)
+ test_vim_str2nr('0xABCDEF', flags, { len = 8, num = 11259375, unum = 11259375, pre = hex }, 0)
+ test_vim_str2nr('0xabcdef', flags, { len = 8, num = 11259375, unum = 11259375, pre = hex }, 0)
+
+ test_vim_str2nr('0x101', flags, { len = 5, num = 257, unum = 257, pre = hex }, 0)
+ test_vim_str2nr('0x101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('0x101', flags, { len = 0 }, 2)
+ test_vim_str2nr('0x101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
+ test_vim_str2nr('0x101', flags, { len = 3, num = 1, unum = 1, pre = hex }, 3)
+ test_vim_str2nr('0x101', flags, { len = 4, num = 16, unum = 16, pre = hex }, 4)
+ test_vim_str2nr('0x101', flags, { len = 5, num = 257, unum = 257, pre = hex }, 5)
+ test_vim_str2nr('0x101', flags, { len = 5, num = 257, unum = 257, pre = hex }, 6)
+
+ test_vim_str2nr('0x101G', flags, { len = 0 }, 0)
+ test_vim_str2nr('0x101G', flags, { len = 0 }, 6)
+ test_vim_str2nr('0x101G', flags, { len = 5, num = 257, unum = 257, pre = hex }, 0, false)
+ test_vim_str2nr('0x101G', flags, { len = 5, num = 257, unum = 257, pre = hex }, 6, false)
+
+ test_vim_str2nr('-0x101', flags, { len = 6, num = -257, unum = 257, pre = hex }, 0)
+ test_vim_str2nr('-0x101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('-0x101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr('-0x101', flags, { len = 0 }, 3)
+ test_vim_str2nr('-0x101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
+ test_vim_str2nr('-0x101', flags, { len = 4, num = -1, unum = 1, pre = hex }, 4)
+ test_vim_str2nr('-0x101', flags, { len = 5, num = -16, unum = 16, pre = hex }, 5)
+ test_vim_str2nr('-0x101', flags, { len = 6, num = -257, unum = 257, pre = hex }, 6)
+ test_vim_str2nr('-0x101', flags, { len = 6, num = -257, unum = 257, pre = hex }, 7)
+
+ test_vim_str2nr('-0x101G', flags, { len = 0 }, 0)
+ test_vim_str2nr('-0x101G', flags, { len = 0 }, 7)
+ test_vim_str2nr('-0x101G', flags, { len = 6, num = -257, unum = 257, pre = hex }, 0, false)
+ test_vim_str2nr('-0x101G', flags, { len = 6, num = -257, unum = 257, pre = hex }, 7, false)
+
+ test_vim_str2nr('0X101', flags, { len = 5, num = 257, unum = 257, pre = HEX }, 0)
+ test_vim_str2nr('0X101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('0X101', flags, { len = 0 }, 2)
+ test_vim_str2nr('0X101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 2, false)
+ test_vim_str2nr('0X101', flags, { len = 3, num = 1, unum = 1, pre = HEX }, 3)
+ test_vim_str2nr('0X101', flags, { len = 4, num = 16, unum = 16, pre = HEX }, 4)
+ test_vim_str2nr('0X101', flags, { len = 5, num = 257, unum = 257, pre = HEX }, 5)
+ test_vim_str2nr('0X101', flags, { len = 5, num = 257, unum = 257, pre = HEX }, 6)
+
+ test_vim_str2nr('0X101G', flags, { len = 0 }, 0)
+ test_vim_str2nr('0X101G', flags, { len = 0 }, 6)
+ test_vim_str2nr('0X101G', flags, { len = 5, num = 257, unum = 257, pre = HEX }, 0, false)
+ test_vim_str2nr('0X101G', flags, { len = 5, num = 257, unum = 257, pre = HEX }, 6, false)
+
+ test_vim_str2nr('-0X101', flags, { len = 6, num = -257, unum = 257, pre = HEX }, 0)
+ test_vim_str2nr('-0X101', flags, { len = 1, num = 0, unum = 0, pre = 0 }, 1)
+ test_vim_str2nr('-0X101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 2)
+ test_vim_str2nr('-0X101', flags, { len = 0 }, 3)
+ test_vim_str2nr('-0X101', flags, { len = 2, num = 0, unum = 0, pre = 0 }, 3, false)
+ test_vim_str2nr('-0X101', flags, { len = 4, num = -1, unum = 1, pre = HEX }, 4)
+ test_vim_str2nr('-0X101', flags, { len = 5, num = -16, unum = 16, pre = HEX }, 5)
+ test_vim_str2nr('-0X101', flags, { len = 6, num = -257, unum = 257, pre = HEX }, 6)
+ test_vim_str2nr('-0X101', flags, { len = 6, num = -257, unum = 257, pre = HEX }, 7)
+
+ test_vim_str2nr('-0X101G', flags, { len = 0 }, 0)
+ test_vim_str2nr('-0X101G', flags, { len = 0 }, 7)
+ test_vim_str2nr('-0X101G', flags, { len = 6, num = -257, unum = 257, pre = HEX }, 0, false)
+ test_vim_str2nr('-0X101G', flags, { len = 6, num = -257, unum = 257, pre = HEX }, 7, false)
if flags > lib.STR2NR_FORCE then
- test_vim_str2nr('-101', flags, {len = 4, num = -257, unum = 257, pre = 0}, 0)
+ test_vim_str2nr('-101', flags, { len = 4, num = -257, unum = 257, pre = 0 }, 0)
end
end
end)
-- Test_str2nr() in test_functions.vim already tests normal usage
itp('works with weirdly quoted numbers', function()
local flags = lib.STR2NR_DEC + lib.STR2NR_QUOTE
- test_vim_str2nr("'027", flags, {len = 0}, 0)
- test_vim_str2nr("'027", flags, {len = 0}, 0, false)
- test_vim_str2nr("1'2'3'4", flags, {len = 7, num = 1234, unum = 1234, pre = 0}, 0)
+ test_vim_str2nr("'027", flags, { len = 0 }, 0)
+ test_vim_str2nr("'027", flags, { len = 0 }, 0, false)
+ test_vim_str2nr("1'2'3'4", flags, { len = 7, num = 1234, unum = 1234, pre = 0 }, 0)
-- counter-intuitive, but like Vim, strict=true should partially accept
-- these: (' and - are not alphanumeric)
- test_vim_str2nr("7''331", flags, {len = 1, num = 7, unum = 7, pre = 0}, 0)
- test_vim_str2nr("123'x4", flags, {len = 3, num = 123, unum = 123, pre = 0}, 0)
- test_vim_str2nr("1337'", flags, {len = 4, num = 1337, unum = 1337, pre = 0}, 0)
- test_vim_str2nr("-'", flags, {len = 1, num = 0, unum = 0, pre = 0}, 0)
+ test_vim_str2nr("7''331", flags, { len = 1, num = 7, unum = 7, pre = 0 }, 0)
+ test_vim_str2nr("123'x4", flags, { len = 3, num = 123, unum = 123, pre = 0 }, 0)
+ test_vim_str2nr("1337'", flags, { len = 4, num = 1337, unum = 1337, pre = 0 }, 0)
+ test_vim_str2nr("-'", flags, { len = 1, num = 0, unum = 0, pre = 0 }, 0)
flags = lib.STR2NR_HEX + lib.STR2NR_QUOTE
local hex = ('x'):byte()
- test_vim_str2nr("0x'abcd", flags, {len = 0}, 0)
- test_vim_str2nr("0x'abcd", flags, {len = 1, num = 0, unum = 0, pre = 0}, 0, false)
- test_vim_str2nr("0xab''cd", flags, {len = 4, num = 171, unum = 171, pre = hex}, 0)
+ test_vim_str2nr("0x'abcd", flags, { len = 0 }, 0)
+ test_vim_str2nr("0x'abcd", flags, { len = 1, num = 0, unum = 0, pre = 0 }, 0, false)
+ test_vim_str2nr("0xab''cd", flags, { len = 4, num = 171, unum = 171, pre = hex }, 0)
end)
end)
diff --git a/test/unit/eval/decode_spec.lua b/test/unit/eval/decode_spec.lua
index 0c444b33f2..5a8374a2a6 100644
--- a/test/unit/eval/decode_spec.lua
+++ b/test/unit/eval/decode_spec.lua
@@ -6,9 +6,13 @@ local eq = helpers.eq
local neq = helpers.neq
local ffi = helpers.ffi
-local decode = cimport('./src/nvim/eval/decode.h', './src/nvim/eval/typval.h',
- './src/nvim/globals.h', './src/nvim/memory.h',
- './src/nvim/message.h')
+local decode = cimport(
+ './src/nvim/eval/decode.h',
+ './src/nvim/eval/typval.h',
+ './src/nvim/globals.h',
+ './src/nvim/memory.h',
+ './src/nvim/message.h'
+)
describe('json_decode_string()', function()
local char = function(c)
@@ -16,7 +20,7 @@ describe('json_decode_string()', function()
end
itp('does not overflow when running with `n…`, `t…`, `f…`', function()
- local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
+ local rettv = ffi.new('typval_T', { v_type = decode.VAR_UNKNOWN })
decode.emsg_silent = 1
-- This will not crash, but if `len` argument will be ignored it will parse
-- `null` as `null` and if not it will parse `null` as `n`.
@@ -43,7 +47,7 @@ describe('json_decode_string()', function()
end)
itp('does not overflow and crash when running with `n`, `t`, `f`', function()
- local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
+ local rettv = ffi.new('typval_T', { v_type = decode.VAR_UNKNOWN })
decode.emsg_silent = 1
eq(0, decode.json_decode_string(char('n'), 1, rettv))
eq(decode.VAR_UNKNOWN, rettv.v_type)
@@ -54,7 +58,7 @@ describe('json_decode_string()', function()
end)
itp('does not overflow when running with `"…`', function()
- local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
+ local rettv = ffi.new('typval_T', { v_type = decode.VAR_UNKNOWN })
decode.emsg_silent = 1
eq(0, decode.json_decode_string('"t"', 2, rettv))
eq(decode.VAR_UNKNOWN, rettv.v_type)
@@ -63,7 +67,7 @@ describe('json_decode_string()', function()
end)
local check_failure = function(s, len, msg)
- local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
+ local rettv = ffi.new('typval_T', { v_type = decode.VAR_UNKNOWN })
eq(0, decode.json_decode_string(s, len, rettv))
eq(decode.VAR_UNKNOWN, rettv.v_type)
neq(nil, decode.last_msg_hist)
@@ -74,8 +78,7 @@ describe('json_decode_string()', function()
collectgarbage('restart')
check_failure(']test', 1, 'E474: No container to close: ]')
check_failure('[}test', 2, 'E474: Closing list with curly bracket: }')
- check_failure('{]test', 2,
- 'E474: Closing dictionary with square bracket: ]')
+ check_failure('{]test', 2, 'E474: Closing dictionary with square bracket: ]')
check_failure('[1,]test', 4, 'E474: Trailing comma: ]')
check_failure('{"1":}test', 6, 'E474: Expected value after colon: }')
check_failure('{"1"}test', 5, 'E474: Expected value: }')
@@ -93,16 +96,20 @@ describe('json_decode_string()', function()
check_failure('ttest', 1, 'E474: Expected true: t')
check_failure('ftest', 1, 'E474: Expected false: f')
check_failure('"\\test', 2, 'E474: Unfinished escape sequence: "\\')
- check_failure('"\\u"test', 4,
- 'E474: Unfinished unicode escape sequence: "\\u"')
- check_failure('"\\uXXXX"est', 8,
- 'E474: Expected four hex digits after \\u: \\uXXXX"')
+ check_failure('"\\u"test', 4, 'E474: Unfinished unicode escape sequence: "\\u"')
+ check_failure('"\\uXXXX"est', 8, 'E474: Expected four hex digits after \\u: \\uXXXX"')
check_failure('"\\?"test', 4, 'E474: Unknown escape sequence: \\?"')
check_failure(
- '"\t"test', 3,
- 'E474: ASCII control characters cannot be present inside string: \t"')
+ '"\t"test',
+ 3,
+ 'E474: ASCII control characters cannot be present inside string: \t"'
+ )
check_failure('"\194"test', 3, 'E474: Only UTF-8 strings allowed: \194"')
- check_failure('"\252\144\128\128\128\128"test', 8, 'E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \252\144\128\128\128\128"')
+ check_failure(
+ '"\252\144\128\128\128\128"test',
+ 8,
+ 'E474: Only UTF-8 code points up to U+10FFFF are allowed to appear unescaped: \252\144\128\128\128\128"'
+ )
check_failure('"test', 1, 'E474: Expected string end: "')
check_failure('-test', 1, 'E474: Missing number after minus sign: -')
check_failure('-1.test', 3, 'E474: Missing number after decimal dot: -1.')
@@ -117,7 +124,7 @@ describe('json_decode_string()', function()
end)
itp('does not overflow and crash when running with `"`', function()
- local rettv = ffi.new('typval_T', {v_type=decode.VAR_UNKNOWN})
+ local rettv = ffi.new('typval_T', { v_type = decode.VAR_UNKNOWN })
decode.emsg_silent = 1
eq(0, decode.json_decode_string(char('"'), 1, rettv))
eq(decode.VAR_UNKNOWN, rettv.v_type)
diff --git a/test/unit/eval/encode_spec.lua b/test/unit/eval/encode_spec.lua
index 058c55093e..498346d7cc 100644
--- a/test/unit/eval/encode_spec.lua
+++ b/test/unit/eval/encode_spec.lua
@@ -22,80 +22,83 @@ describe('encode_list_write()', function()
itp('writes empty string', function()
local l = list()
eq(0, encode_list_write(l, ''))
- eq({[type_key]=list_type}, lst2tbl(l))
+ eq({ [type_key] = list_type }, lst2tbl(l))
end)
itp('writes ASCII string literal with printable characters', function()
local l = list()
eq(0, encode_list_write(l, 'abc'))
- eq({'abc'}, lst2tbl(l))
+ eq({ 'abc' }, lst2tbl(l))
end)
itp('writes string starting with NL', function()
local l = list()
eq(0, encode_list_write(l, '\nabc'))
- eq({null_string, 'abc'}, lst2tbl(l))
+ eq({ null_string, 'abc' }, lst2tbl(l))
end)
itp('writes string starting with NL twice', function()
local l = list()
eq(0, encode_list_write(l, '\nabc'))
- eq({null_string, 'abc'}, lst2tbl(l))
+ eq({ null_string, 'abc' }, lst2tbl(l))
eq(0, encode_list_write(l, '\nabc'))
- eq({null_string, 'abc', 'abc'}, lst2tbl(l))
+ eq({ null_string, 'abc', 'abc' }, lst2tbl(l))
end)
itp('writes string ending with NL', function()
local l = list()
eq(0, encode_list_write(l, 'abc\n'))
- eq({'abc', null_string}, lst2tbl(l))
+ eq({ 'abc', null_string }, lst2tbl(l))
end)
itp('writes string ending with NL twice', function()
local l = list()
eq(0, encode_list_write(l, 'abc\n'))
- eq({'abc', null_string}, lst2tbl(l))
+ eq({ 'abc', null_string }, lst2tbl(l))
eq(0, encode_list_write(l, 'abc\n'))
- eq({'abc', 'abc', null_string}, lst2tbl(l))
+ eq({ 'abc', 'abc', null_string }, lst2tbl(l))
end)
itp('writes string starting, ending and containing NL twice', function()
local l = list()
eq(0, encode_list_write(l, '\na\nb\n'))
- eq({null_string, 'a', 'b', null_string}, lst2tbl(l))
+ eq({ null_string, 'a', 'b', null_string }, lst2tbl(l))
eq(0, encode_list_write(l, '\na\nb\n'))
- eq({null_string, 'a', 'b', null_string, 'a', 'b', null_string}, lst2tbl(l))
+ eq({ null_string, 'a', 'b', null_string, 'a', 'b', null_string }, lst2tbl(l))
end)
itp('writes string starting, ending and containing NUL with NL between twice', function()
local l = list()
eq(0, encode_list_write(l, '\0\n\0\n\0'))
- eq({'\n', '\n', '\n'}, lst2tbl(l))
+ eq({ '\n', '\n', '\n' }, lst2tbl(l))
eq(0, encode_list_write(l, '\0\n\0\n\0'))
- eq({'\n', '\n', '\n\n', '\n', '\n'}, lst2tbl(l))
+ eq({ '\n', '\n', '\n\n', '\n', '\n' }, lst2tbl(l))
end)
itp('writes string starting, ending and containing NL with NUL between twice', function()
local l = list()
eq(0, encode_list_write(l, '\n\0\n\0\n'))
- eq({null_string, '\n', '\n', null_string}, lst2tbl(l))
+ eq({ null_string, '\n', '\n', null_string }, lst2tbl(l))
eq(0, encode_list_write(l, '\n\0\n\0\n'))
- eq({null_string, '\n', '\n', null_string, '\n', '\n', null_string}, lst2tbl(l))
+ eq({ null_string, '\n', '\n', null_string, '\n', '\n', null_string }, lst2tbl(l))
end)
itp('writes string containing a single NL twice', function()
local l = list()
eq(0, encode_list_write(l, '\n'))
- eq({null_string, null_string}, lst2tbl(l))
+ eq({ null_string, null_string }, lst2tbl(l))
eq(0, encode_list_write(l, '\n'))
- eq({null_string, null_string, null_string}, lst2tbl(l))
+ eq({ null_string, null_string, null_string }, lst2tbl(l))
end)
itp('writes string containing a few NLs twice', function()
local l = list()
eq(0, encode_list_write(l, '\n\n\n'))
- eq({null_string, null_string, null_string, null_string}, lst2tbl(l))
+ eq({ null_string, null_string, null_string, null_string }, lst2tbl(l))
eq(0, encode_list_write(l, '\n\n\n'))
- eq({null_string, null_string, null_string, null_string, null_string, null_string, null_string}, lst2tbl(l))
+ eq(
+ { null_string, null_string, null_string, null_string, null_string, null_string, null_string },
+ lst2tbl(l)
+ )
end)
end)
diff --git a/test/unit/eval/helpers.lua b/test/unit/eval/helpers.lua
index 883f01bd84..6402e1f8c9 100644
--- a/test/unit/eval/helpers.lua
+++ b/test/unit/eval/helpers.lua
@@ -6,21 +6,25 @@ local to_cstr = helpers.to_cstr
local ffi = helpers.ffi
local eq = helpers.eq
-local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h',
- './src/nvim/hashtab.h', './src/nvim/memory.h')
-
-local null_string = {[true]='NULL string'}
-local null_list = {[true]='NULL list'}
-local null_dict = {[true]='NULL dict'}
-local type_key = {[true]='type key'}
-local locks_key = {[true]='locks key'}
-local list_type = {[true]='list type'}
-local dict_type = {[true]='dict type'}
-local func_type = {[true]='func type'}
-local int_type = {[true]='int type'}
-local flt_type = {[true]='flt type'}
-
-local nil_value = {[true]='nil'}
+local eval = cimport(
+ './src/nvim/eval.h',
+ './src/nvim/eval/typval.h',
+ './src/nvim/hashtab.h',
+ './src/nvim/memory.h'
+)
+
+local null_string = { [true] = 'NULL string' }
+local null_list = { [true] = 'NULL list' }
+local null_dict = { [true] = 'NULL dict' }
+local type_key = { [true] = 'type key' }
+local locks_key = { [true] = 'locks key' }
+local list_type = { [true] = 'list type' }
+local dict_type = { [true] = 'dict type' }
+local func_type = { [true] = 'func type' }
+local int_type = { [true] = 'int type' }
+local flt_type = { [true] = 'flt type' }
+
+local nil_value = { [true] = 'nil' }
local lua2typvalt
@@ -35,11 +39,13 @@ end
local function li_alloc(nogc)
local gcfunc = tv_list_item_free
- if nogc then gcfunc = nil end
+ if nogc then
+ gcfunc = nil
+ end
local li = ffi.gc(tv_list_item_alloc(), gcfunc)
li.li_next = nil
li.li_prev = nil
- li.li_tv = {v_type=eval.VAR_UNKNOWN, v_lock=eval.VAR_UNLOCKED}
+ li.li_tv = { v_type = eval.VAR_UNKNOWN, v_lock = eval.VAR_UNLOCKED }
return li
end
@@ -121,11 +127,11 @@ local function partial2lua(pt, processed)
end
end
return {
- [type_key]=func_type,
- value=value,
- auto=auto,
- args=argv,
- dict=dict,
+ [type_key] = func_type,
+ value = value,
+ auto = auto,
+ args = argv,
+ dict = dict,
}
end
@@ -148,7 +154,7 @@ local function typvalt2lua_tab_init()
})[tonumber(t.vval.v_special)]
end,
[tonumber(eval.VAR_NUMBER)] = function(t)
- return {[type_key]=int_type, value=tonumber(t.vval.v_number)}
+ return { [type_key] = int_type, value = tonumber(t.vval.v_number) }
end,
[tonumber(eval.VAR_FLOAT)] = function(t)
return tonumber(t.vval.v_float)
@@ -168,7 +174,7 @@ local function typvalt2lua_tab_init()
return dct2tbl(t.vval.v_dict, processed)
end,
[tonumber(eval.VAR_FUNC)] = function(t, processed)
- return {[type_key]=func_type, value=typvalt2lua_tab[eval.VAR_STRING](t, processed or {})}
+ return { [type_key] = func_type, value = typvalt2lua_tab[eval.VAR_STRING](t, processed or {}) }
end,
[tonumber(eval.VAR_PARTIAL)] = function(t, processed)
local p_key = ptr2key(t)
@@ -182,15 +188,17 @@ end
typvalt2lua = function(t, processed)
typvalt2lua_tab_init()
- return ((typvalt2lua_tab[tonumber(t.v_type)] or function(t_inner)
- assert(false, 'Converting ' .. tonumber(t_inner.v_type) .. ' was not implemented yet')
- end)(t, processed or {}))
+ return (
+ (typvalt2lua_tab[tonumber(t.v_type)] or function(t_inner)
+ assert(false, 'Converting ' .. tonumber(t_inner.v_type) .. ' was not implemented yet')
+ end)(t, processed or {})
+ )
end
local function list_iter(l)
local init_s = {
- idx=0,
- li=l.lv_first,
+ idx = 0,
+ li = l.lv_first,
}
local function f(s, _)
-- (listitem_T *) NULL is equal to nil, but yet it is not false.
@@ -222,7 +230,7 @@ lst2tbl = function(l, processed)
if processed[p_key] then
return processed[p_key]
end
- local ret = {[type_key]=list_type}
+ local ret = { [type_key] = list_type }
processed[p_key] = ret
for i, li in list_iter(l) do
ret[i] = typvalt2lua(li.li_tv, processed)
@@ -238,11 +246,13 @@ local hi_key_removed = nil
local function dict_iter(d, return_hi)
hi_key_removed = hi_key_removed or eval._hash_key_removed()
local init_s = {
- todo=d.dv_hashtab.ht_used,
- hi=d.dv_hashtab.ht_array,
+ todo = d.dv_hashtab.ht_used,
+ hi = d.dv_hashtab.ht_array,
}
local function f(s, _)
- if s.todo == 0 then return nil end
+ if s.todo == 0 then
+ return nil
+ end
while s.todo > 0 do
if s.hi.hi_key ~= nil and s.hi.hi_key ~= hi_key_removed then
local key = ffi.string(s.hi.hi_key)
@@ -250,8 +260,7 @@ local function dict_iter(d, return_hi)
if return_hi then
ret = s.hi
else
- ret = ffi.cast('dictitem_T*',
- s.hi.hi_key - ffi.offsetof('dictitem_T', 'di_key'))
+ ret = ffi.cast('dictitem_T*', s.hi.hi_key - ffi.offsetof('dictitem_T', 'di_key'))
end
s.todo = s.todo - 1
s.hi = s.hi + 1
@@ -269,7 +278,7 @@ local function first_di(d)
end
local function dict_items(d)
- local ret = {[0]=0}
+ local ret = { [0] = 0 }
for k, hi in dict_iter(d) do
ret[k] = hi
ret[0] = ret[0] + 1
@@ -301,12 +310,12 @@ local typvalt = function(typ, vval)
elseif type(typ) == 'string' then
typ = eval[typ]
end
- return ffi.gc(ffi.new('typval_T', {v_type=typ, vval=vval}), eval.tv_clear)
+ return ffi.gc(ffi.new('typval_T', { v_type = typ, vval = vval }), eval.tv_clear)
end
local lua2typvalt_type_tab = {
[int_type] = function(l, _)
- return typvalt(eval.VAR_NUMBER, {v_number=l.value})
+ return typvalt(eval.VAR_NUMBER, { v_number = l.value })
end,
[flt_type] = function(l, processed)
return lua2typvalt(l.value, processed)
@@ -314,31 +323,34 @@ local lua2typvalt_type_tab = {
[list_type] = function(l, processed)
if processed[l] then
processed[l].lv_refcount = processed[l].lv_refcount + 1
- return typvalt(eval.VAR_LIST, {v_list=processed[l]})
+ return typvalt(eval.VAR_LIST, { v_list = processed[l] })
end
local lst = populate_list(eval.tv_list_alloc(#l), l, processed)
- return typvalt(eval.VAR_LIST, {v_list=lst})
+ return typvalt(eval.VAR_LIST, { v_list = lst })
end,
[dict_type] = function(l, processed)
if processed[l] then
processed[l].dv_refcount = processed[l].dv_refcount + 1
- return typvalt(eval.VAR_DICT, {v_dict=processed[l]})
+ return typvalt(eval.VAR_DICT, { v_dict = processed[l] })
end
local dct = populate_dict(eval.tv_dict_alloc(), l, processed)
- return typvalt(eval.VAR_DICT, {v_dict=dct})
+ return typvalt(eval.VAR_DICT, { v_dict = dct })
end,
[func_type] = function(l, processed)
if processed[l] then
processed[l].pt_refcount = processed[l].pt_refcount + 1
- return typvalt(eval.VAR_PARTIAL, {v_partial=processed[l]})
+ return typvalt(eval.VAR_PARTIAL, { v_partial = processed[l] })
end
if l.args or l.dict then
- local pt = populate_partial(ffi.gc(ffi.cast('partial_T*',
- eval.xcalloc(1, ffi.sizeof('partial_T'))), nil), l, processed)
- return typvalt(eval.VAR_PARTIAL, {v_partial=pt})
+ local pt = populate_partial(
+ ffi.gc(ffi.cast('partial_T*', eval.xcalloc(1, ffi.sizeof('partial_T'))), nil),
+ l,
+ processed
+ )
+ return typvalt(eval.VAR_PARTIAL, { v_partial = pt })
else
return typvalt(eval.VAR_FUNC, {
- v_string=eval.xmemdupz(to_cstr(l.value), #l.value)
+ v_string = eval.xmemdupz(to_cstr(l.value), #l.value),
})
end
end,
@@ -349,12 +361,12 @@ local special_vals = nil
lua2typvalt = function(l, processed)
if not special_vals then
special_vals = {
- [null_string] = {'VAR_STRING', {v_string=ffi.cast('char*', nil)}},
- [null_list] = {'VAR_LIST', {v_list=ffi.cast('list_T*', nil)}},
- [null_dict] = {'VAR_DICT', {v_dict=ffi.cast('dict_T*', nil)}},
- [nil_value] = {'VAR_SPECIAL', {v_special=eval.kSpecialVarNull}},
- [true] = {'VAR_BOOL', {v_bool=eval.kBoolVarTrue}},
- [false] = {'VAR_BOOL', {v_bool=eval.kBoolVarFalse}},
+ [null_string] = { 'VAR_STRING', { v_string = ffi.cast('char*', nil) } },
+ [null_list] = { 'VAR_LIST', { v_list = ffi.cast('list_T*', nil) } },
+ [null_dict] = { 'VAR_DICT', { v_dict = ffi.cast('dict_T*', nil) } },
+ [nil_value] = { 'VAR_SPECIAL', { v_special = eval.kSpecialVarNull } },
+ [true] = { 'VAR_BOOL', { v_bool = eval.kBoolVarTrue } },
+ [false] = { 'VAR_BOOL', { v_bool = eval.kBoolVarFalse } },
}
for k, v in pairs(special_vals) do
@@ -382,9 +394,9 @@ lua2typvalt = function(l, processed)
end
end
elseif type(l) == 'number' then
- return typvalt(eval.VAR_FLOAT, {v_float=l})
+ return typvalt(eval.VAR_FLOAT, { v_float = l })
elseif type(l) == 'string' then
- return typvalt(eval.VAR_STRING, {v_string=eval.xmemdupz(to_cstr(l), #l)})
+ return typvalt(eval.VAR_STRING, { v_string = eval.xmemdupz(to_cstr(l), #l) })
elseif type(l) == 'cdata' then
local tv = typvalt(eval.VAR_UNKNOWN)
eval.tv_copy(l, tv)
@@ -408,43 +420,64 @@ local function alloc_len(len, get_ptr)
end
local alloc_logging_helpers = {
- list = function(l) return {func='calloc', args={1, ffi.sizeof('list_T')}, ret=void(l)} end,
- li = function(li) return {func='malloc', args={ffi.sizeof('listitem_T')}, ret=void(li)} end,
- dict = function(d) return {func='calloc', args={1, ffi.sizeof('dict_T')}, ret=void(d)} end,
+ list = function(l)
+ return { func = 'calloc', args = { 1, ffi.sizeof('list_T') }, ret = void(l) }
+ end,
+ li = function(li)
+ return { func = 'malloc', args = { ffi.sizeof('listitem_T') }, ret = void(li) }
+ end,
+ dict = function(d)
+ return { func = 'calloc', args = { 1, ffi.sizeof('dict_T') }, ret = void(d) }
+ end,
di = function(di, size)
- size = alloc_len(size, function() return di.di_key end)
- return {func='malloc', args={ffi.offsetof('dictitem_T', 'di_key') + size + 1}, ret=void(di)}
+ size = alloc_len(size, function()
+ return di.di_key
+ end)
+ return {
+ func = 'malloc',
+ args = { ffi.offsetof('dictitem_T', 'di_key') + size + 1 },
+ ret = void(di),
+ }
end,
str = function(s, size)
- size = alloc_len(size, function() return s end)
- return {func='malloc', args={size + 1}, ret=void(s)}
+ size = alloc_len(size, function()
+ return s
+ end)
+ return { func = 'malloc', args = { size + 1 }, ret = void(s) }
end,
- dwatcher = function(w) return {func='malloc', args={ffi.sizeof('DictWatcher')}, ret=void(w)} end,
+ dwatcher = function(w)
+ return { func = 'malloc', args = { ffi.sizeof('DictWatcher') }, ret = void(w) }
+ end,
- freed = function(p) return {func='free', args={type(p) == 'table' and p or void(p)}} end,
+ freed = function(p)
+ return { func = 'free', args = { type(p) == 'table' and p or void(p) } }
+ end,
-- lua_…: allocated by this file, not by some Neovim function
- lua_pt = function(pt) return {func='calloc', args={1, ffi.sizeof('partial_T')}, ret=void(pt)} end,
+ lua_pt = function(pt)
+ return { func = 'calloc', args = { 1, ffi.sizeof('partial_T') }, ret = void(pt) }
+ end,
lua_tvs = function(argv, argc)
argc = alloc_len(argc)
- return {func='malloc', args={ffi.sizeof('typval_T')*argc}, ret=void(argv)}
+ return { func = 'malloc', args = { ffi.sizeof('typval_T') * argc }, ret = void(argv) }
end,
}
local function int(n)
- return {[type_key]=int_type, value=n}
+ return { [type_key] = int_type, value = n }
end
local function list(...)
- return populate_list(ffi.gc(eval.tv_list_alloc(select('#', ...)),
- eval.tv_list_unref),
- {...}, {})
+ return populate_list(
+ ffi.gc(eval.tv_list_alloc(select('#', ...)), eval.tv_list_unref),
+ { ... },
+ {}
+ )
end
local function dict(d)
- return populate_dict(ffi.gc(eval.tv_dict_alloc(), eval.tv_dict_free),
- d or {}, {})
+ return populate_dict(ffi.gc(eval.tv_dict_alloc(), eval.tv_dict_free), d or {}, {})
end
local callback2tbl_type_tab = nil
@@ -454,14 +487,16 @@ local function init_callback2tbl_type_tab()
return
end
callback2tbl_type_tab = {
- [tonumber(eval.kCallbackNone)] = function(_) return {type='none'} end,
+ [tonumber(eval.kCallbackNone)] = function(_)
+ return { type = 'none' }
+ end,
[tonumber(eval.kCallbackFuncref)] = function(cb)
- return {type='fref', fref=ffi.string(cb.data.funcref)}
+ return { type = 'fref', fref = ffi.string(cb.data.funcref) }
end,
[tonumber(eval.kCallbackPartial)] = function(cb)
local lua_pt = partial2lua(cb.data.partial)
- return {type='pt', fref=ffi.string(lua_pt.value), pt=lua_pt}
- end
+ return { type = 'pt', fref = ffi.string(lua_pt.value), pt = lua_pt }
+ end,
}
end
@@ -473,15 +508,18 @@ end
local function tbl2callback(tbl)
local ret = nil
if tbl.type == 'none' then
- ret = ffi.new('Callback[1]', {{type=eval.kCallbackNone}})
+ ret = ffi.new('Callback[1]', { { type = eval.kCallbackNone } })
elseif tbl.type == 'fref' then
- ret = ffi.new('Callback[1]', {{type=eval.kCallbackFuncref,
- data={funcref=eval.xstrdup(tbl.fref)}}})
+ ret = ffi.new(
+ 'Callback[1]',
+ { { type = eval.kCallbackFuncref, data = { funcref = eval.xstrdup(tbl.fref) } } }
+ )
elseif tbl.type == 'pt' then
- local pt = ffi.gc(ffi.cast('partial_T*',
- eval.xcalloc(1, ffi.sizeof('partial_T'))), nil)
- ret = ffi.new('Callback[1]', {{type=eval.kCallbackPartial,
- data={partial=populate_partial(pt, tbl.pt, {})}}})
+ local pt = ffi.gc(ffi.cast('partial_T*', eval.xcalloc(1, ffi.sizeof('partial_T'))), nil)
+ ret = ffi.new(
+ 'Callback[1]',
+ { { type = eval.kCallbackPartial, data = { partial = populate_partial(pt, tbl.pt, {}) } } }
+ )
else
assert(false)
end
@@ -495,24 +533,23 @@ local function dict_watchers(d)
local qs = {}
local key_patterns = {}
while q ~= h do
- local qitem = ffi.cast('DictWatcher *',
- ffi.cast('char *', q) - ffi.offsetof('DictWatcher', 'node'))
+ local qitem =
+ ffi.cast('DictWatcher *', ffi.cast('char *', q) - ffi.offsetof('DictWatcher', 'node'))
ret[#ret + 1] = {
- cb=callback2tbl(qitem.callback),
- pat=ffi.string(qitem.key_pattern, qitem.key_pattern_len),
- busy=qitem.busy,
+ cb = callback2tbl(qitem.callback),
+ pat = ffi.string(qitem.key_pattern, qitem.key_pattern_len),
+ busy = qitem.busy,
}
qs[#qs + 1] = qitem
- key_patterns[#key_patterns + 1] = {qitem.key_pattern, qitem.key_pattern_len}
+ key_patterns[#key_patterns + 1] = { qitem.key_pattern, qitem.key_pattern_len }
q = q.next
end
return ret, qs, key_patterns
end
local function eval0(expr)
- local tv = ffi.gc(ffi.new('typval_T', {v_type=eval.VAR_UNKNOWN}),
- eval.tv_clear)
- local evalarg = ffi.new('evalarg_T', {eval_flags = eval.EVAL_EVALUATE})
+ local tv = ffi.gc(ffi.new('typval_T', { v_type = eval.VAR_UNKNOWN }), eval.tv_clear)
+ local evalarg = ffi.new('evalarg_T', { eval_flags = eval.EVAL_EVALUATE })
if eval.eval0(to_cstr(expr), tv, nil, evalarg) == 0 then
return nil
else
@@ -521,49 +558,49 @@ local function eval0(expr)
end
return {
- int=int,
+ int = int,
- null_string=null_string,
- null_list=null_list,
- null_dict=null_dict,
- list_type=list_type,
- dict_type=dict_type,
- func_type=func_type,
- int_type=int_type,
- flt_type=flt_type,
+ null_string = null_string,
+ null_list = null_list,
+ null_dict = null_dict,
+ list_type = list_type,
+ dict_type = dict_type,
+ func_type = func_type,
+ int_type = int_type,
+ flt_type = flt_type,
- nil_value=nil_value,
+ nil_value = nil_value,
- type_key=type_key,
- locks_key=locks_key,
+ type_key = type_key,
+ locks_key = locks_key,
- list=list,
- dict=dict,
- lst2tbl=lst2tbl,
- dct2tbl=dct2tbl,
+ list = list,
+ dict = dict,
+ lst2tbl = lst2tbl,
+ dct2tbl = dct2tbl,
- lua2typvalt=lua2typvalt,
- typvalt2lua=typvalt2lua,
+ lua2typvalt = lua2typvalt,
+ typvalt2lua = typvalt2lua,
- typvalt=typvalt,
+ typvalt = typvalt,
- li_alloc=li_alloc,
- tv_list_item_free=tv_list_item_free,
+ li_alloc = li_alloc,
+ tv_list_item_free = tv_list_item_free,
- dict_iter=dict_iter,
- list_iter=list_iter,
- first_di=first_di,
+ dict_iter = dict_iter,
+ list_iter = list_iter,
+ first_di = first_di,
- alloc_logging_helpers=alloc_logging_helpers,
+ alloc_logging_helpers = alloc_logging_helpers,
- list_items=list_items,
- dict_items=dict_items,
+ list_items = list_items,
+ dict_items = dict_items,
- dict_watchers=dict_watchers,
- tbl2callback=tbl2callback,
- callback2tbl=callback2tbl,
+ dict_watchers = dict_watchers,
+ tbl2callback = tbl2callback,
+ callback2tbl = callback2tbl,
- eval0=eval0,
+ eval0 = eval0,
- empty_list = {[type_key]=list_type},
+ empty_list = { [type_key] = list_type },
}
diff --git a/test/unit/eval/tricks_spec.lua b/test/unit/eval/tricks_spec.lua
index 7aa0f0f6e6..ed26fd44e4 100644
--- a/test/unit/eval/tricks_spec.lua
+++ b/test/unit/eval/tricks_spec.lua
@@ -8,8 +8,7 @@ local eq = helpers.eq
local eval0 = eval_helpers.eval0
-local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h',
- './src/nvim/memory.h')
+local eval = cimport('./src/nvim/eval.h', './src/nvim/eval/typval.h', './src/nvim/memory.h')
describe('NULL typval_T', function()
itp('is produced by $XXX_UNEXISTENT_VAR_XXX', function()
diff --git a/test/unit/eval/tv_clear_spec.lua b/test/unit/eval/tv_clear_spec.lua
index ca37301b32..a34cf6082a 100644
--- a/test/unit/eval/tv_clear_spec.lua
+++ b/test/unit/eval/tv_clear_spec.lua
@@ -28,8 +28,8 @@ end)
describe('tv_clear()', function()
itp('successfully frees all lists in [&l [1], *l, *l]', function()
- local l_inner = {1}
- local list = {l_inner, l_inner, l_inner}
+ local l_inner = { 1 }
+ local list = { l_inner, l_inner, l_inner }
local list_tv = ffi.gc(lua2typvalt(list), nil)
local list_p = list_tv.vval.v_list
local lis = list_items(list_p)
@@ -55,8 +55,8 @@ describe('tv_clear()', function()
})
end)
itp('successfully frees all lists in [&l [], *l, *l]', function()
- local l_inner = {[type_key]=list_type}
- local list = {l_inner, l_inner, l_inner}
+ local l_inner = { [type_key] = list_type }
+ local list = { l_inner, l_inner, l_inner }
local list_tv = ffi.gc(lua2typvalt(list), nil)
local list_p = list_tv.vval.v_list
local lis = list_items(list_p)
@@ -80,7 +80,7 @@ describe('tv_clear()', function()
end)
itp('successfully frees all dictionaries in [&d {}, *d]', function()
local d_inner = {}
- local list = {d_inner, d_inner}
+ local list = { d_inner, d_inner }
local list_tv = ffi.gc(lua2typvalt(list), nil)
local list_p = list_tv.vval.v_list
local lis = list_items(list_p)
@@ -101,8 +101,8 @@ describe('tv_clear()', function()
})
end)
itp('successfully frees all dictionaries in [&d {a: 1}, *d]', function()
- local d_inner = {a=1}
- local list = {d_inner, d_inner}
+ local d_inner = { a = 1 }
+ local list = { d_inner, d_inner }
local list_tv = ffi.gc(lua2typvalt(list), nil)
local list_p = list_tv.vval.v_list
local lis = list_items(list_p)
diff --git a/test/unit/eval/typval_spec.lua b/test/unit/eval/typval_spec.lua
index 34a1299725..6edd164438 100644
--- a/test/unit/eval/typval_spec.lua
+++ b/test/unit/eval/typval_spec.lua
@@ -14,7 +14,7 @@ local cimport = helpers.cimport
local to_cstr = helpers.to_cstr
local alloc_log_new = helpers.alloc_log_new
local concat_tables = helpers.concat_tables
-local map = helpers.tbl_map
+local map = vim.tbl_map
local a = eval_helpers.alloc_logging_helpers
local int = eval_helpers.int
@@ -41,21 +41,25 @@ local callback2tbl = eval_helpers.callback2tbl
local tbl2callback = eval_helpers.tbl2callback
local dict_watchers = eval_helpers.dict_watchers
-local lib = cimport('./src/nvim/eval/typval.h', './src/nvim/memory.h',
- './src/nvim/mbyte.h', './src/nvim/garray.h',
- './src/nvim/eval.h', './src/nvim/vim_defs.h',
- './src/nvim/globals.h')
+local lib = cimport(
+ './src/nvim/eval/typval.h',
+ './src/nvim/memory.h',
+ './src/nvim/mbyte.h',
+ './src/nvim/garray.h',
+ './src/nvim/eval.h',
+ './src/nvim/vim_defs.h',
+ './src/nvim/globals.h'
+)
local function vimconv_alloc()
- return ffi.gc(
- ffi.cast('vimconv_T*', lib.xcalloc(1, ffi.sizeof('vimconv_T'))), function(vc)
- lib.convert_setup(vc, nil, nil)
- lib.xfree(vc)
- end)
+ return ffi.gc(ffi.cast('vimconv_T*', lib.xcalloc(1, ffi.sizeof('vimconv_T'))), function(vc)
+ lib.convert_setup(vc, nil, nil)
+ lib.xfree(vc)
+ end)
end
local function list_watch_alloc(li)
- return ffi.cast('listwatch_T*', ffi.new('listwatch_T[1]', {{lw_item=li}}))
+ return ffi.cast('listwatch_T*', ffi.new('listwatch_T[1]', { { lw_item = li } }))
end
local function list_watch(l, li)
@@ -66,12 +70,14 @@ end
local function get_alloc_rets(exp_log, res)
setmetatable(res, {
- __index={
- freed=function(r, n) return {func='free', args={r[n]}} end
- }
+ __index = {
+ freed = function(r, n)
+ return { func = 'free', args = { r[n] } }
+ end,
+ },
})
- for i = 1,#exp_log do
- if ({malloc=true, calloc=true})[exp_log[i].func] then
+ for i = 1, #exp_log do
+ if ({ malloc = true, calloc = true })[exp_log[i].func] then
res[#res + 1] = exp_log[i].ret
end
end
@@ -89,8 +95,7 @@ after_each(function()
end)
local function ga_alloc(itemsize, growsize)
- local ga = ffi.gc(ffi.cast('garray_T*', ffi.new('garray_T[1]', {})),
- lib.ga_clear)
+ local ga = ffi.gc(ffi.cast('garray_T*', ffi.new('garray_T[1]', {})), lib.ga_clear)
lib.ga_init(ga, itemsize or 1, growsize or 80)
return ga
end
@@ -100,7 +105,7 @@ local function check_emsg(f, msg)
if saved_last_msg_hist == nil then
saved_last_msg_hist = nil
end
- local ret = {f()}
+ local ret = { f() }
local last_msg = lib.last_msg_hist ~= nil and ffi.string(lib.last_msg_hist.msg) or nil
if msg ~= nil then
eq(msg, last_msg)
@@ -167,8 +172,9 @@ describe('typval.c', function()
a.str(lis[4].li_tv.vval.v_string, 1),
a.li(lis[4]),
})
- local strings = map(function(li) return li.li_tv.vval.v_string end,
- lis)
+ local strings = map(function(li)
+ return li.li_tv.vval.v_string
+ end, lis)
eq(lis[2], lib.tv_list_item_remove(l, lis[1]))
alloc_log:check({
@@ -213,20 +219,26 @@ describe('typval.c', function()
})
eq(lis[5], lib.tv_list_item_remove(l, lis[4]))
- alloc_log:check({a.freed(lis[4])})
- eq({lis[1], lis[5], lis[7]}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item})
+ alloc_log:check({ a.freed(lis[4]) })
+ eq({ lis[1], lis[5], lis[7] }, { lws[1].lw_item, lws[2].lw_item, lws[3].lw_item })
eq(lis[3], lib.tv_list_item_remove(l, lis[2]))
- alloc_log:check({a.freed(lis[2])})
- eq({lis[1], lis[5], lis[7]}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item})
+ alloc_log:check({ a.freed(lis[2]) })
+ eq({ lis[1], lis[5], lis[7] }, { lws[1].lw_item, lws[2].lw_item, lws[3].lw_item })
eq(nil, lib.tv_list_item_remove(l, lis[7]))
- alloc_log:check({a.freed(lis[7])})
- eq({lis[1], lis[5], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil})
+ alloc_log:check({ a.freed(lis[7]) })
+ eq(
+ { lis[1], lis[5], nil },
+ { lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil }
+ )
eq(lis[3], lib.tv_list_item_remove(l, lis[1]))
- alloc_log:check({a.freed(lis[1])})
- eq({lis[3], lis[5], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil})
+ alloc_log:check({ a.freed(lis[1]) })
+ eq(
+ { lis[3], lis[5], nil },
+ { lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil }
+ )
lib.tv_list_watch_remove(l, lws[2])
lib.tv_list_watch_remove(l, lws[3])
@@ -285,7 +297,7 @@ describe('typval.c', function()
alloc_log:check(get_alloc_rets({
a.list(l1),
a.li(l1.lv_first),
- a.str(l1.lv_last.li_tv.vval.v_string, #('abc')),
+ a.str(l1.lv_last.li_tv.vval.v_string, #'abc'),
a.li(l1.lv_last),
a.list(l2),
a.dict(l2.lv_first.li_tv.vval.v_dict),
@@ -324,7 +336,7 @@ describe('typval.c', function()
alloc_log:check(get_alloc_rets({
a.list(l1),
a.li(l1.lv_first),
- a.str(l1.lv_last.li_tv.vval.v_string, #('abc')),
+ a.str(l1.lv_last.li_tv.vval.v_string, #'abc'),
a.li(l1.lv_last),
a.list(l2),
a.dict(l2.lv_first.li_tv.vval.v_dict),
@@ -348,8 +360,7 @@ describe('typval.c', function()
end)
end)
describe('free_contents()', function()
- itp('recursively frees list, except for the list structure itself',
- function()
+ itp('recursively frees list, except for the list structure itself', function()
local l1 = ffi.gc(list(1, 'abc'), nil)
local l2 = ffi.gc(list({}), nil)
local l3 = ffi.gc(list(empty_list), nil)
@@ -357,7 +368,7 @@ describe('typval.c', function()
alloc_log:check(get_alloc_rets({
a.list(l1),
a.li(l1.lv_first),
- a.str(l1.lv_last.li_tv.vval.v_string, #('abc')),
+ a.str(l1.lv_last.li_tv.vval.v_string, #'abc'),
a.li(l1.lv_last),
a.list(l2),
a.dict(l2.lv_first.li_tv.vval.v_dict),
@@ -406,7 +417,7 @@ describe('typval.c', function()
end)
describe('drop_items()', function()
itp('works', function()
- local l_tv = lua2typvalt({1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13})
+ local l_tv = lua2typvalt({ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 })
local l = l_tv.vval.v_list
local lis = list_items(l)
-- Three watchers: pointing to first, middle and last elements.
@@ -418,20 +429,29 @@ describe('typval.c', function()
alloc_log:clear()
lib.tv_list_drop_items(l, lis[1], lis[3])
- eq({4, 5, 6, 7, 8, 9, 10, 11, 12, 13}, typvalt2lua(l_tv))
- eq({lis[4], lis[7], lis[13]}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item})
+ eq({ 4, 5, 6, 7, 8, 9, 10, 11, 12, 13 }, typvalt2lua(l_tv))
+ eq({ lis[4], lis[7], lis[13] }, { lws[1].lw_item, lws[2].lw_item, lws[3].lw_item })
lib.tv_list_drop_items(l, lis[11], lis[13])
- eq({4, 5, 6, 7, 8, 9, 10}, typvalt2lua(l_tv))
- eq({lis[4], lis[7], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil})
+ eq({ 4, 5, 6, 7, 8, 9, 10 }, typvalt2lua(l_tv))
+ eq(
+ { lis[4], lis[7], nil },
+ { lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil }
+ )
lib.tv_list_drop_items(l, lis[6], lis[8])
- eq({4, 5, 9, 10}, typvalt2lua(l_tv))
- eq({lis[4], lis[9], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil})
+ eq({ 4, 5, 9, 10 }, typvalt2lua(l_tv))
+ eq(
+ { lis[4], lis[9], nil },
+ { lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil }
+ )
lib.tv_list_drop_items(l, lis[4], lis[10])
eq(empty_list, typvalt2lua(l_tv))
- eq({true, true, true}, {lws[1].lw_item == nil, lws[2].lw_item == nil, lws[3].lw_item == nil})
+ eq(
+ { true, true, true },
+ { lws[1].lw_item == nil, lws[2].lw_item == nil, lws[3].lw_item == nil }
+ )
lib.tv_list_watch_remove(l, lws[1])
lib.tv_list_watch_remove(l, lws[2])
@@ -442,10 +462,13 @@ describe('typval.c', function()
end)
describe('remove_items()', function()
itp('works', function()
- local l_tv = lua2typvalt({'1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13'})
+ local l_tv =
+ lua2typvalt({ '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13' })
local l = l_tv.vval.v_list
local lis = list_items(l)
- local strings = map(function(li) return li.li_tv.vval.v_string end, lis)
+ local strings = map(function(li)
+ return li.li_tv.vval.v_string
+ end, lis)
-- Three watchers: pointing to first, middle and last elements.
local lws = {
list_watch(l, lis[1]),
@@ -455,8 +478,8 @@ describe('typval.c', function()
alloc_log:clear()
lib.tv_list_remove_items(l, lis[1], lis[3])
- eq({'4', '5', '6', '7', '8', '9', '10', '11', '12', '13'}, typvalt2lua(l_tv))
- eq({lis[4], lis[7], lis[13]}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item})
+ eq({ '4', '5', '6', '7', '8', '9', '10', '11', '12', '13' }, typvalt2lua(l_tv))
+ eq({ lis[4], lis[7], lis[13] }, { lws[1].lw_item, lws[2].lw_item, lws[3].lw_item })
alloc_log:check({
a.freed(strings[1]),
a.freed(lis[1]),
@@ -467,8 +490,11 @@ describe('typval.c', function()
})
lib.tv_list_remove_items(l, lis[11], lis[13])
- eq({'4', '5', '6', '7', '8', '9', '10'}, typvalt2lua(l_tv))
- eq({lis[4], lis[7], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil})
+ eq({ '4', '5', '6', '7', '8', '9', '10' }, typvalt2lua(l_tv))
+ eq(
+ { lis[4], lis[7], nil },
+ { lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil }
+ )
alloc_log:check({
a.freed(strings[11]),
a.freed(lis[11]),
@@ -479,8 +505,11 @@ describe('typval.c', function()
})
lib.tv_list_remove_items(l, lis[6], lis[8])
- eq({'4', '5', '9', '10'}, typvalt2lua(l_tv))
- eq({lis[4], lis[9], nil}, {lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil})
+ eq({ '4', '5', '9', '10' }, typvalt2lua(l_tv))
+ eq(
+ { lis[4], lis[9], nil },
+ { lws[1].lw_item, lws[2].lw_item, lws[3].lw_item == nil and nil }
+ )
alloc_log:check({
a.freed(strings[6]),
a.freed(lis[6]),
@@ -492,7 +521,10 @@ describe('typval.c', function()
lib.tv_list_remove_items(l, lis[4], lis[10])
eq(empty_list, typvalt2lua(l_tv))
- eq({true, true, true}, {lws[1].lw_item == nil, lws[2].lw_item == nil, lws[3].lw_item == nil})
+ eq(
+ { true, true, true },
+ { lws[1].lw_item == nil, lws[2].lw_item == nil, lws[3].lw_item == nil }
+ )
alloc_log:check({
a.freed(strings[4]),
a.freed(lis[4]),
@@ -514,28 +546,28 @@ describe('typval.c', function()
describe('insert', function()
describe('()', function()
itp('works', function()
- local l_tv = lua2typvalt({1, 2, 3, 4, 5, 6, 7})
+ local l_tv = lua2typvalt({ 1, 2, 3, 4, 5, 6, 7 })
local l = l_tv.vval.v_list
local lis = list_items(l)
local li
li = li_alloc(true)
- li.li_tv = {v_type=lib.VAR_FLOAT, vval={v_float=100500}}
+ li.li_tv = { v_type = lib.VAR_FLOAT, vval = { v_float = 100500 } }
lib.tv_list_insert(l, li, nil)
eq(l.lv_last, li)
- eq({1, 2, 3, 4, 5, 6, 7, 100500}, typvalt2lua(l_tv))
+ eq({ 1, 2, 3, 4, 5, 6, 7, 100500 }, typvalt2lua(l_tv))
li = li_alloc(true)
- li.li_tv = {v_type=lib.VAR_FLOAT, vval={v_float=0}}
+ li.li_tv = { v_type = lib.VAR_FLOAT, vval = { v_float = 0 } }
lib.tv_list_insert(l, li, lis[1])
eq(l.lv_first, li)
- eq({0, 1, 2, 3, 4, 5, 6, 7, 100500}, typvalt2lua(l_tv))
+ eq({ 0, 1, 2, 3, 4, 5, 6, 7, 100500 }, typvalt2lua(l_tv))
li = li_alloc(true)
- li.li_tv = {v_type=lib.VAR_FLOAT, vval={v_float=4.5}}
+ li.li_tv = { v_type = lib.VAR_FLOAT, vval = { v_float = 4.5 } }
lib.tv_list_insert(l, li, lis[5])
eq(list_items(l)[6], li)
- eq({0, 1, 2, 3, 4, 4.5, 5, 6, 7, 100500}, typvalt2lua(l_tv))
+ eq({ 0, 1, 2, 3, 4, 4.5, 5, 6, 7, 100500 }, typvalt2lua(l_tv))
end)
itp('works with an empty list', function()
local l_tv = lua2typvalt(empty_list)
@@ -545,10 +577,10 @@ describe('typval.c', function()
eq(nil, l.lv_last)
local li = li_alloc(true)
- li.li_tv = {v_type=lib.VAR_FLOAT, vval={v_float=100500}}
+ li.li_tv = { v_type = lib.VAR_FLOAT, vval = { v_float = 100500 } }
lib.tv_list_insert(l, li, nil)
eq(l.lv_last, li)
- eq({100500}, typvalt2lua(l_tv))
+ eq({ 100500 }, typvalt2lua(l_tv))
end)
end)
describe('tv()', function()
@@ -577,7 +609,7 @@ describe('typval.c', function()
a.str(l.lv_first.li_tv.vval.v_string, 'test'),
})
- eq({'test', empty_list}, typvalt2lua(l_tv))
+ eq({ 'test', empty_list }, typvalt2lua(l_tv))
end)
end)
end)
@@ -602,7 +634,7 @@ describe('typval.c', function()
a.li(l.lv_last),
})
- eq({{1}, null_list}, typvalt2lua(l_tv))
+ eq({ { 1 }, null_list }, typvalt2lua(l_tv))
end)
end)
describe('dict()', function()
@@ -610,7 +642,7 @@ describe('typval.c', function()
local l_tv = lua2typvalt(empty_list)
local l = l_tv.vval.v_list
- local l_d_tv = lua2typvalt({test=1})
+ local l_d_tv = lua2typvalt({ test = 1 })
local l_d = l_d_tv.vval.v_dict
alloc_log:clear()
eq(1, l_d.dv_refcount)
@@ -626,7 +658,7 @@ describe('typval.c', function()
a.li(l.lv_last),
})
- eq({{test=1}, null_dict}, typvalt2lua(l_tv))
+ eq({ { test = 1 }, null_dict }, typvalt2lua(l_tv))
end)
end)
describe('string()', function()
@@ -657,7 +689,7 @@ describe('typval.c', function()
a.li(l.lv_last),
})
- eq({'tes', null_string, null_string, 'test'}, typvalt2lua(l_tv))
+ eq({ 'tes', null_string, null_string, 'test' }, typvalt2lua(l_tv))
end)
end)
describe('allocated string()', function()
@@ -682,7 +714,7 @@ describe('typval.c', function()
a.li(l.lv_last),
})
- eq({'test', null_string, null_string}, typvalt2lua(l_tv))
+ eq({ 'test', null_string, null_string }, typvalt2lua(l_tv))
end)
end)
describe('number()', function()
@@ -701,7 +733,7 @@ describe('typval.c', function()
a.li(l.lv_last),
})
- eq({int(-100500), int(100500)}, typvalt2lua(l_tv))
+ eq({ int(-100500), int(100500) }, typvalt2lua(l_tv))
end)
end)
describe('tv()', function()
@@ -730,7 +762,7 @@ describe('typval.c', function()
a.str(l.lv_last.li_tv.vval.v_string, 'test'),
})
- eq({empty_list, 'test'}, typvalt2lua(l_tv))
+ eq({ empty_list, 'test' }, typvalt2lua(l_tv))
end)
end)
describe('owned tv()', function()
@@ -761,7 +793,7 @@ describe('typval.c', function()
a.li(l.lv_last),
})
- eq({empty_list, 'test'}, typvalt2lua(l_tv))
+ eq({ empty_list, 'test' }, typvalt2lua(l_tv))
end)
end)
end)
@@ -777,7 +809,7 @@ describe('typval.c', function()
end)
itp('copies list correctly without converting items', function()
do
- local v = {{['«']='»'}, {'„'}, 1, '“', null_string, null_list, null_dict}
+ local v = { { ['«'] = '»' }, { '„' }, 1, '“', null_string, null_list, null_dict }
local l_tv = lua2typvalt(v)
local l = l_tv.vval.v_list
local lis = list_items(l)
@@ -821,7 +853,7 @@ describe('typval.c', function()
a.list(l_deepcopy1),
a.li(lis_deepcopy1[1]),
a.dict(lis_deepcopy1[1].li_tv.vval.v_dict),
- a.di(di_deepcopy1, #('«')),
+ a.di(di_deepcopy1, #'«'),
a.str(di_deepcopy1.di_tv.vval.v_string, #v[1]['«']),
a.li(lis_deepcopy1[2]),
a.list(lis_deepcopy1[2].li_tv.vval.v_list),
@@ -842,7 +874,7 @@ describe('typval.c', function()
-- UTF-8 ↔ latin1 conversions needs no iconv
eq(OK, lib.convert_setup(vc, to_cstr('utf-8'), to_cstr('latin1')))
- local v = {{['«']='»'}, {'„'}, 1, '“', null_string, null_list, null_dict}
+ local v = { { ['«'] = '»' }, { '„' }, 1, '“', null_string, null_list, null_dict }
local l_tv = lua2typvalt(v)
local l = l_tv.vval.v_list
local lis = list_items(l)
@@ -857,8 +889,10 @@ describe('typval.c', function()
local lis_deepcopy1 = list_items(l_deepcopy1)
neq(lis[1].li_tv.vval.v_dict, lis_deepcopy1[1].li_tv.vval.v_dict)
neq(lis[2].li_tv.vval.v_list, lis_deepcopy1[2].li_tv.vval.v_list)
- eq({{['\171']='\187'}, {'\191'}, 1, '\191', null_string, null_list, null_dict},
- lst2tbl(l_deepcopy1))
+ eq(
+ { { ['\171'] = '\187' }, { '\191' }, 1, '\191', null_string, null_list, null_dict },
+ lst2tbl(l_deepcopy1)
+ )
local di_deepcopy1 = first_di(lis_deepcopy1[1].li_tv.vval.v_dict)
alloc_log:clear_tmp_allocs()
alloc_log:check({
@@ -881,18 +915,18 @@ describe('typval.c', function()
end)
itp('returns different/same containers with(out) copyID', function()
local l_inner_tv = lua2typvalt(empty_list)
- local l_tv = lua2typvalt({l_inner_tv, l_inner_tv})
+ local l_tv = lua2typvalt({ l_inner_tv, l_inner_tv })
eq(3, l_inner_tv.vval.v_list.lv_refcount)
local l = l_tv.vval.v_list
eq(l.lv_first.li_tv.vval.v_list, l.lv_last.li_tv.vval.v_list)
local l_copy1 = tv_list_copy(nil, l, true, 0)
neq(l_copy1.lv_first.li_tv.vval.v_list, l_copy1.lv_last.li_tv.vval.v_list)
- eq({empty_list, empty_list}, lst2tbl(l_copy1))
+ eq({ empty_list, empty_list }, lst2tbl(l_copy1))
local l_copy2 = tv_list_copy(nil, l, true, 2)
eq(l_copy2.lv_first.li_tv.vval.v_list, l_copy2.lv_last.li_tv.vval.v_list)
- eq({empty_list, empty_list}, lst2tbl(l_copy2))
+ eq({ empty_list, empty_list }, lst2tbl(l_copy2))
eq(3, l_inner_tv.vval.v_list.lv_refcount)
end)
@@ -934,7 +968,7 @@ describe('typval.c', function()
})
eq(1, l.lv_refcount)
eq(2, l.lv_last.li_tv.vval.v_dict.dv_refcount)
- eq({1, {}, 1, {}}, lst2tbl(l))
+ eq({ 1, {}, 1, {} }, lst2tbl(l))
l = list(1, {})
alloc_log:clear()
@@ -946,7 +980,7 @@ describe('typval.c', function()
a.li(l.lv_last.li_prev.li_prev),
a.li(l.lv_last.li_prev),
})
- eq({1, 1, {}, {}}, lst2tbl(l))
+ eq({ 1, 1, {}, {} }, lst2tbl(l))
eq(1, l.lv_refcount)
eq(2, l.lv_last.li_tv.vval.v_dict.dv_refcount)
@@ -960,7 +994,7 @@ describe('typval.c', function()
a.li(l.lv_first),
a.li(l.lv_first.li_next),
})
- eq({1, {}, 1, {}}, lst2tbl(l))
+ eq({ 1, {}, 1, {} }, lst2tbl(l))
eq(1, l.lv_refcount)
eq(2, l.lv_last.li_tv.vval.v_dict.dv_refcount)
end)
@@ -973,28 +1007,25 @@ describe('typval.c', function()
eq(1, el.lv_refcount)
lib.tv_list_extend(l, el, nil)
- alloc_log:check({
- })
+ alloc_log:check({})
eq(1, l.lv_refcount)
eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount)
eq(1, el.lv_refcount)
- eq({1, {}}, lst2tbl(l))
+ eq({ 1, {} }, lst2tbl(l))
lib.tv_list_extend(l, el, l.lv_first)
- alloc_log:check({
- })
+ alloc_log:check({})
eq(1, l.lv_refcount)
eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount)
eq(1, el.lv_refcount)
- eq({1, {}}, lst2tbl(l))
+ eq({ 1, {} }, lst2tbl(l))
lib.tv_list_extend(l, el, l.lv_last)
- alloc_log:check({
- })
+ alloc_log:check({})
eq(1, l.lv_refcount)
eq(1, l.lv_last.li_tv.vval.v_dict.dv_refcount)
eq(1, el.lv_refcount)
- eq({1, {}}, lst2tbl(l))
+ eq({ 1, {} }, lst2tbl(l))
end)
itp('can extend list with another non-empty list', function()
local l
@@ -1014,7 +1045,7 @@ describe('typval.c', function()
})
eq(1, l2.lv_refcount)
eq(2, l2.lv_last.li_tv.vval.v_list.lv_refcount)
- eq({1, {}, 42, empty_list}, lst2tbl(l))
+ eq({ 1, {}, 42, empty_list }, lst2tbl(l))
lib.tv_list_free(l)
eq(1, l2.lv_last.li_tv.vval.v_list.lv_refcount)
@@ -1030,7 +1061,7 @@ describe('typval.c', function()
})
eq(1, l2.lv_refcount)
eq(2, l2.lv_last.li_tv.vval.v_list.lv_refcount)
- eq({42, empty_list, 1, {}}, lst2tbl(l))
+ eq({ 42, empty_list, 1, {} }, lst2tbl(l))
lib.tv_list_free(l)
eq(1, l2.lv_last.li_tv.vval.v_list.lv_refcount)
@@ -1046,7 +1077,7 @@ describe('typval.c', function()
})
eq(1, l2.lv_refcount)
eq(2, l2.lv_last.li_tv.vval.v_list.lv_refcount)
- eq({1, 42, empty_list, {}}, lst2tbl(l))
+ eq({ 1, 42, empty_list, {} }, lst2tbl(l))
lib.tv_list_free(l)
eq(1, l2.lv_last.li_tv.vval.v_list.lv_refcount)
end)
@@ -1062,7 +1093,7 @@ describe('typval.c', function()
eq(OK, lib.tv_list_concat(nil, l, rettv1))
eq(1, l.lv_refcount)
eq(tonumber(lib.VAR_LIST), tonumber(rettv1.v_type))
- eq({1, {}}, typvalt2lua(rettv1))
+ eq({ 1, {} }, typvalt2lua(rettv1))
eq(1, rettv1.vval.v_list.lv_refcount)
alloc_log:check({
a.list(rettv1.vval.v_list),
@@ -1075,7 +1106,7 @@ describe('typval.c', function()
eq(OK, lib.tv_list_concat(l, nil, rettv2))
eq(1, l.lv_refcount)
eq(tonumber(lib.VAR_LIST), tonumber(rettv2.v_type))
- eq({1, {}}, typvalt2lua(rettv2))
+ eq({ 1, {} }, typvalt2lua(rettv2))
eq(1, rettv2.vval.v_list.lv_refcount)
alloc_log:check({
a.list(rettv2.vval.v_list),
@@ -1112,7 +1143,7 @@ describe('typval.c', function()
a.li(rettv.vval.v_list.lv_last.li_prev),
a.li(rettv.vval.v_list.lv_last),
})
- eq({1, {}, 3, empty_list}, typvalt2lua(rettv))
+ eq({ 1, {}, 3, empty_list }, typvalt2lua(rettv))
end)
itp('can concatenate list with itself', function()
local l = list(1, {})
@@ -1131,7 +1162,7 @@ describe('typval.c', function()
a.li(rettv.vval.v_list.lv_last.li_prev),
a.li(rettv.vval.v_list.lv_last),
})
- eq({1, {}, 1, {}}, typvalt2lua(rettv))
+ eq({ 1, {}, 1, {} }, typvalt2lua(rettv))
end)
itp('can concatenate empty non-NULL lists', function()
local l = list(1, {})
@@ -1154,7 +1185,7 @@ describe('typval.c', function()
a.li(rettv1.vval.v_list.lv_first),
a.li(rettv1.vval.v_list.lv_last),
})
- eq({1, {}}, typvalt2lua(rettv1))
+ eq({ 1, {} }, typvalt2lua(rettv1))
local rettv2 = typvalt()
eq(OK, lib.tv_list_concat(le, l, rettv2))
@@ -1167,7 +1198,7 @@ describe('typval.c', function()
a.li(rettv2.vval.v_list.lv_first),
a.li(rettv2.vval.v_list.lv_last),
})
- eq({1, {}}, typvalt2lua(rettv2))
+ eq({ 1, {} }, typvalt2lua(rettv2))
local rettv3 = typvalt()
eq(OK, lib.tv_list_concat(le, le, rettv3))
@@ -1257,15 +1288,15 @@ describe('typval.c', function()
-- indicates that tv_equal_recurse_limit and recursive_cnt were set which
-- is essential. This argument will be set when comparing inner lists.
itp('compares lists correctly when case is not ignored', function()
- local l1 = list('abc', {1, 2, 'Abc'}, 'def')
- local l2 = list('abc', {1, 2, 'Abc'})
- local l3 = list('abc', {1, 2, 'Abc'}, 'Def')
- local l4 = list('abc', {1, 2, 'Abc', 4}, 'def')
- local l5 = list('Abc', {1, 2, 'Abc'}, 'def')
- local l6 = list('abc', {1, 2, 'Abc'}, 'def')
- local l7 = list('abc', {1, 2, 'abc'}, 'def')
+ local l1 = list('abc', { 1, 2, 'Abc' }, 'def')
+ local l2 = list('abc', { 1, 2, 'Abc' })
+ local l3 = list('abc', { 1, 2, 'Abc' }, 'Def')
+ local l4 = list('abc', { 1, 2, 'Abc', 4 }, 'def')
+ local l5 = list('Abc', { 1, 2, 'Abc' }, 'def')
+ local l6 = list('abc', { 1, 2, 'Abc' }, 'def')
+ local l7 = list('abc', { 1, 2, 'abc' }, 'def')
local l8 = list('abc', nil, 'def')
- local l9 = list('abc', {1, 2, nil}, 'def')
+ local l9 = list('abc', { 1, 2, nil }, 'def')
eq(true, lib.tv_list_equal(l1, l1, false, false))
eq(false, lib.tv_list_equal(l1, l2, false, false))
@@ -1278,15 +1309,15 @@ describe('typval.c', function()
eq(false, lib.tv_list_equal(l1, l9, false, false))
end)
itp('compares lists correctly when case is ignored', function()
- local l1 = list('abc', {1, 2, 'Abc'}, 'def')
- local l2 = list('abc', {1, 2, 'Abc'})
- local l3 = list('abc', {1, 2, 'Abc'}, 'Def')
- local l4 = list('abc', {1, 2, 'Abc', 4}, 'def')
- local l5 = list('Abc', {1, 2, 'Abc'}, 'def')
- local l6 = list('abc', {1, 2, 'Abc'}, 'def')
- local l7 = list('abc', {1, 2, 'abc'}, 'def')
+ local l1 = list('abc', { 1, 2, 'Abc' }, 'def')
+ local l2 = list('abc', { 1, 2, 'Abc' })
+ local l3 = list('abc', { 1, 2, 'Abc' }, 'Def')
+ local l4 = list('abc', { 1, 2, 'Abc', 4 }, 'def')
+ local l5 = list('Abc', { 1, 2, 'Abc' }, 'def')
+ local l6 = list('abc', { 1, 2, 'Abc' }, 'def')
+ local l7 = list('abc', { 1, 2, 'abc' }, 'def')
local l8 = list('abc', nil, 'def')
- local l9 = list('abc', {1, 2, nil}, 'def')
+ local l9 = list('abc', { 1, 2, nil }, 'def')
eq(true, lib.tv_list_equal(l1, l1, true, false))
eq(false, lib.tv_list_equal(l1, l2, true, false))
@@ -1355,7 +1386,7 @@ describe('typval.c', function()
describe('nr()', function()
local function tv_list_find_nr(l, n, msg)
return check_emsg(function()
- local err = ffi.new('bool[1]', {false})
+ local err = ffi.new('bool[1]', { false })
local ret = lib.tv_list_find_nr(l, n, err)
return (err[0] == true), ret
end, msg)
@@ -1364,10 +1395,10 @@ describe('typval.c', function()
local l = list(int(1), int(2), int(3), int(4), int(5))
alloc_log:clear()
- eq({false, 1}, {tv_list_find_nr(l, -5)})
- eq({false, 5}, {tv_list_find_nr(l, 4)})
- eq({false, 3}, {tv_list_find_nr(l, 2)})
- eq({false, 3}, {tv_list_find_nr(l, -3)})
+ eq({ false, 1 }, { tv_list_find_nr(l, -5) })
+ eq({ false, 5 }, { tv_list_find_nr(l, 4) })
+ eq({ false, 3 }, { tv_list_find_nr(l, 2) })
+ eq({ false, 3 }, { tv_list_find_nr(l, -3) })
alloc_log:check({})
end)
@@ -1375,10 +1406,10 @@ describe('typval.c', function()
local l = list('1', '2', '3', '4', '5')
alloc_log:clear()
- eq({false, 1}, {tv_list_find_nr(l, -5)})
- eq({false, 5}, {tv_list_find_nr(l, 4)})
- eq({false, 3}, {tv_list_find_nr(l, 2)})
- eq({false, 3}, {tv_list_find_nr(l, -3)})
+ eq({ false, 1 }, { tv_list_find_nr(l, -5) })
+ eq({ false, 5 }, { tv_list_find_nr(l, 4) })
+ eq({ false, 3 }, { tv_list_find_nr(l, 2) })
+ eq({ false, 3 }, { tv_list_find_nr(l, -3) })
alloc_log:check({})
end)
@@ -1386,15 +1417,15 @@ describe('typval.c', function()
local l = list(null_string)
alloc_log:clear()
- eq({false, 0}, {tv_list_find_nr(l, 0)})
+ eq({ false, 0 }, { tv_list_find_nr(l, 0) })
alloc_log:check({})
end)
itp('errors out on NULL lists', function()
- eq({true, -1}, {tv_list_find_nr(nil, -5)})
- eq({true, -1}, {tv_list_find_nr(nil, 4)})
- eq({true, -1}, {tv_list_find_nr(nil, 2)})
- eq({true, -1}, {tv_list_find_nr(nil, -3)})
+ eq({ true, -1 }, { tv_list_find_nr(nil, -5) })
+ eq({ true, -1 }, { tv_list_find_nr(nil, 4) })
+ eq({ true, -1 }, { tv_list_find_nr(nil, 2) })
+ eq({ true, -1 }, { tv_list_find_nr(nil, -3) })
alloc_log:check({})
end)
@@ -1402,20 +1433,20 @@ describe('typval.c', function()
local l = list(int(1), int(2), int(3), int(4), int(5))
alloc_log:clear()
- eq({true, -1}, {tv_list_find_nr(l, -6)})
- eq({true, -1}, {tv_list_find_nr(l, 5)})
+ eq({ true, -1 }, { tv_list_find_nr(l, -6) })
+ eq({ true, -1 }, { tv_list_find_nr(l, 5) })
alloc_log:check({})
end)
itp('errors out on invalid types', function()
local l = list(1, empty_list, {})
- eq({true, 0}, {tv_list_find_nr(l, 0, 'E805: Using a Float as a Number')})
- eq({true, 0}, {tv_list_find_nr(l, 1, 'E745: Using a List as a Number')})
- eq({true, 0}, {tv_list_find_nr(l, 2, 'E728: Using a Dictionary as a Number')})
- eq({true, 0}, {tv_list_find_nr(l, -1, 'E728: Using a Dictionary as a Number')})
- eq({true, 0}, {tv_list_find_nr(l, -2, 'E745: Using a List as a Number')})
- eq({true, 0}, {tv_list_find_nr(l, -3, 'E805: Using a Float as a Number')})
+ eq({ true, 0 }, { tv_list_find_nr(l, 0, 'E805: Using a Float as a Number') })
+ eq({ true, 0 }, { tv_list_find_nr(l, 1, 'E745: Using a List as a Number') })
+ eq({ true, 0 }, { tv_list_find_nr(l, 2, 'E728: Using a Dictionary as a Number') })
+ eq({ true, 0 }, { tv_list_find_nr(l, -1, 'E728: Using a Dictionary as a Number') })
+ eq({ true, 0 }, { tv_list_find_nr(l, -2, 'E745: Using a List as a Number') })
+ eq({ true, 0 }, { tv_list_find_nr(l, -3, 'E805: Using a Float as a Number') })
end)
end)
local function tv_list_find_str(l, n, msg)
@@ -1439,7 +1470,7 @@ describe('typval.c', function()
eq('3', tv_list_find_str(l, 2))
eq('3', tv_list_find_str(l, -3))
- alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null)})
+ alloc_log:check({ a.freed(alloc_log.null), a.freed(alloc_log.null) })
end)
itp('returns string when used with VAR_STRING items', function()
local l = list('1', '2', '3', '4', '5')
@@ -1499,7 +1530,7 @@ describe('typval.c', function()
itp('works with an empty key', function()
local d = dict({})
eq({}, dict_watchers(d))
- local cb = ffi.gc(tbl2callback({type='none'}), nil)
+ local cb = ffi.gc(tbl2callback({ type = 'none' }), nil)
alloc_log:clear()
lib.tv_dict_watcher_add(d, '*', 0, cb[0])
local ws, qs = dict_watchers(d)
@@ -1508,7 +1539,7 @@ describe('typval.c', function()
a.dwatcher(qs[1]),
a.str(key_p, 0),
})
- eq({{busy=false, cb={type='none'}, pat=''}}, ws)
+ eq({ { busy = false, cb = { type = 'none' }, pat = '' } }, ws)
eq(true, lib.tv_dict_watcher_remove(d, 'x', 0, cb[0]))
alloc_log:check({
a.freed(key_p),
@@ -1519,19 +1550,29 @@ describe('typval.c', function()
itp('works with multiple callbacks', function()
local d = dict({})
eq({}, dict_watchers(d))
- alloc_log:check({a.dict(d)})
+ alloc_log:check({ a.dict(d) })
local cbs = {}
- cbs[1] = {'te', ffi.gc(tbl2callback({type='none'}), nil)}
+ cbs[1] = { 'te', ffi.gc(tbl2callback({ type = 'none' }), nil) }
alloc_log:check({})
- cbs[2] = {'foo', ffi.gc(tbl2callback({type='fref', fref='tr'}), nil)}
+ cbs[2] = { 'foo', ffi.gc(tbl2callback({ type = 'fref', fref = 'tr' }), nil) }
alloc_log:check({
- a.str(cbs[2][2].data.funcref, #('tr')),
+ a.str(cbs[2][2].data.funcref, #'tr'),
})
- cbs[3] = {'te', ffi.gc(tbl2callback({type='pt', fref='tr', pt={
- value='tr',
- args={'test'},
- dict={},
- }}), nil)}
+ cbs[3] = {
+ 'te',
+ ffi.gc(
+ tbl2callback({
+ type = 'pt',
+ fref = 'tr',
+ pt = {
+ value = 'tr',
+ args = { 'test' },
+ dict = {},
+ },
+ }),
+ nil
+ ),
+ }
local pt3 = cbs[3][2].data.partial
local pt3_argv = pt3.pt_argv
local pt3_dict = pt3.pt_dict
@@ -1540,22 +1581,32 @@ describe('typval.c', function()
alloc_log:check({
a.lua_pt(pt3),
a.lua_tvs(pt3_argv, pt3.pt_argc),
- a.str(pt3_str_arg, #('test')),
+ a.str(pt3_str_arg, #'test'),
a.dict(pt3_dict),
- a.str(pt3_name, #('tr')),
+ a.str(pt3_name, #'tr'),
})
for _, v in ipairs(cbs) do
- lib.tv_dict_watcher_add(d, v[1], #(v[1]), v[2][0])
+ lib.tv_dict_watcher_add(d, v[1], #v[1], v[2][0])
end
local ws, qs, kps = dict_watchers(d)
- eq({{busy=false, pat=cbs[1][1], cb={type='none'}},
- {busy=false, pat=cbs[2][1], cb={type='fref', fref='tr'}},
- {busy=false, pat=cbs[3][1], cb={type='pt', fref='tr', pt={
- [type_key]=func_type,
- value='tr',
- args={'test'},
- dict={},
- }}}}, ws)
+ eq({
+ { busy = false, pat = cbs[1][1], cb = { type = 'none' } },
+ { busy = false, pat = cbs[2][1], cb = { type = 'fref', fref = 'tr' } },
+ {
+ busy = false,
+ pat = cbs[3][1],
+ cb = {
+ type = 'pt',
+ fref = 'tr',
+ pt = {
+ [type_key] = func_type,
+ value = 'tr',
+ args = { 'test' },
+ dict = {},
+ },
+ },
+ },
+ }, ws)
alloc_log:check({
a.dwatcher(qs[1]),
a.str(kps[1][1], kps[1][2]),
@@ -1571,13 +1622,23 @@ describe('typval.c', function()
a.freed(qs[2]),
})
eq(false, lib.tv_dict_watcher_remove(d, cbs[2][1], #cbs[2][1], cbs[2][2][0]))
- eq({{busy=false, pat=cbs[1][1], cb={type='none'}},
- {busy=false, pat=cbs[3][1], cb={type='pt', fref='tr', pt={
- [type_key]=func_type,
- value='tr',
- args={'test'},
- dict={},
- }}}}, dict_watchers(d))
+ eq({
+ { busy = false, pat = cbs[1][1], cb = { type = 'none' } },
+ {
+ busy = false,
+ pat = cbs[3][1],
+ cb = {
+ type = 'pt',
+ fref = 'tr',
+ pt = {
+ [type_key] = func_type,
+ value = 'tr',
+ args = { 'test' },
+ dict = {},
+ },
+ },
+ },
+ }, dict_watchers(d))
eq(true, lib.tv_dict_watcher_remove(d, cbs[3][1], #cbs[3][1], cbs[3][2][0]))
alloc_log:check({
a.freed(pt3_str_arg),
@@ -1589,7 +1650,7 @@ describe('typval.c', function()
a.freed(qs[3]),
})
eq(false, lib.tv_dict_watcher_remove(d, cbs[3][1], #cbs[3][1], cbs[3][2][0]))
- eq({{busy=false, pat=cbs[1][1], cb={type='none'}}}, dict_watchers(d))
+ eq({ { busy = false, pat = cbs[1][1], cb = { type = 'none' } } }, dict_watchers(d))
eq(true, lib.tv_dict_watcher_remove(d, cbs[1][1], #cbs[1][1], cbs[1][2][0]))
alloc_log:check({
a.freed(kps[1][1]),
@@ -1615,14 +1676,14 @@ describe('typval.c', function()
di = ffi.gc(lib.tv_dict_item_alloc_len(s, len or #s), nil)
end
eq(s:sub(1, len), ffi.string(di.di_key))
- alloc_log:check({a.di(di, len)})
+ alloc_log:check({ a.di(di, len) })
if tv then
di.di_tv = ffi.gc(tv, nil)
else
di.di_tv.v_type = lib.VAR_UNKNOWN
end
lib.tv_dict_item_free(di)
- alloc_log:check(concat_tables(more_frees, {a.freed(di)}))
+ alloc_log:check(concat_tables(more_frees, { a.freed(di) }))
end
local function check_tv_dict_item_alloc(s, tv, more_frees)
return check_tv_dict_item_alloc_len(s, nil, tv, more_frees)
@@ -1634,26 +1695,30 @@ describe('typval.c', function()
check_tv_dict_item_alloc_len('', 0)
check_tv_dict_item_alloc_len('TEST', 2)
local tv = lua2typvalt('test')
- alloc_log:check({a.str(tv.vval.v_string, #('test'))})
- check_tv_dict_item_alloc('', tv, {a.freed(tv.vval.v_string)})
+ alloc_log:check({ a.str(tv.vval.v_string, #'test') })
+ check_tv_dict_item_alloc('', tv, { a.freed(tv.vval.v_string) })
tv = lua2typvalt('test')
- alloc_log:check({a.str(tv.vval.v_string, #('test'))})
- check_tv_dict_item_alloc_len('', 0, tv, {a.freed(tv.vval.v_string)})
+ alloc_log:check({ a.str(tv.vval.v_string, #'test') })
+ check_tv_dict_item_alloc_len('', 0, tv, { a.freed(tv.vval.v_string) })
end)
end)
describe('add()/remove()', function()
itp('works', function()
local d = dict()
eq({}, dct2tbl(d))
- alloc_log:check({a.dict(d)})
+ alloc_log:check({ a.dict(d) })
local di = ffi.gc(lib.tv_dict_item_alloc(''), nil)
local tv = lua2typvalt('test')
di.di_tv = ffi.gc(tv, nil)
- alloc_log:check({a.di(di, ''), a.str(tv.vval.v_string, 'test')})
+ alloc_log:check({ a.di(di, ''), a.str(tv.vval.v_string, 'test') })
eq(OK, lib.tv_dict_add(d, di))
alloc_log:check({})
- eq(FAIL, check_emsg(function() return lib.tv_dict_add(d, di) end,
- 'E685: Internal error: hash_add(): duplicate key ""'))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add(d, di)
+ end, 'E685: Internal error: hash_add(): duplicate key ""')
+ )
alloc_log:clear()
lib.tv_dict_item_remove(d, di)
alloc_log:check({
@@ -1679,28 +1744,28 @@ describe('typval.c', function()
end)
itp('works with empty key', function()
local lua_d = {
- ['']=0,
- t=1,
- te=2,
- tes=3,
- test=4,
- testt=5,
+ [''] = 0,
+ t = 1,
+ te = 2,
+ tes = 3,
+ test = 4,
+ testt = 5,
}
local d = dict(lua_d)
alloc_log:clear()
eq(lua_d, dct2tbl(d))
alloc_log:check({})
local dis = dict_items(d)
- eq({0, '', dis['']}, {tv_dict_find(d, '', 0)})
+ eq({ 0, '', dis[''] }, { tv_dict_find(d, '', 0) })
end)
itp('works with len properly', function()
local lua_d = {
- ['']=0,
- t=1,
- te=2,
- tes=3,
- test=4,
- testt=5,
+ [''] = 0,
+ t = 1,
+ te = 2,
+ tes = 3,
+ test = 4,
+ testt = 5,
}
local d = dict(lua_d)
alloc_log:clear()
@@ -1708,80 +1773,125 @@ describe('typval.c', function()
alloc_log:check({})
for i = 0, 5 do
local v, k = tv_dict_find(d, 'testt', i)
- eq({i, ('testt'):sub(1, i)}, {v, k})
+ eq({ i, ('testt'):sub(1, i) }, { v, k })
end
- eq(nil, tv_dict_find(d, 'testt', 6)) -- Should take NUL byte
+ eq(nil, tv_dict_find(d, 'testt', 6)) -- Should take NUL byte
eq(5, tv_dict_find(d, 'testt', -1))
alloc_log:check({})
end)
end)
describe('get_number()', function()
itp('works with NULL dict', function()
- eq(0, check_emsg(function() return lib.tv_dict_get_number(nil, 'test') end,
- nil))
+ eq(
+ 0,
+ check_emsg(function()
+ return lib.tv_dict_get_number(nil, 'test')
+ end, nil)
+ )
end)
itp('works', function()
- local d = ffi.gc(dict({test={}}), nil)
- eq(0, check_emsg(function() return lib.tv_dict_get_number(d, 'test') end,
- 'E728: Using a Dictionary as a Number'))
- d = ffi.gc(dict({tes=int(42), t=44, te='43'}), nil)
+ local d = ffi.gc(dict({ test = {} }), nil)
+ eq(
+ 0,
+ check_emsg(function()
+ return lib.tv_dict_get_number(d, 'test')
+ end, 'E728: Using a Dictionary as a Number')
+ )
+ d = ffi.gc(dict({ tes = int(42), t = 44, te = '43' }), nil)
alloc_log:clear()
- eq(0, check_emsg(function() return lib.tv_dict_get_number(d, 'test') end,
- nil))
- eq(42, check_emsg(function() return lib.tv_dict_get_number(d, 'tes') end,
- nil))
- eq(43, check_emsg(function() return lib.tv_dict_get_number(d, 'te') end,
- nil))
+ eq(
+ 0,
+ check_emsg(function()
+ return lib.tv_dict_get_number(d, 'test')
+ end, nil)
+ )
+ eq(
+ 42,
+ check_emsg(function()
+ return lib.tv_dict_get_number(d, 'tes')
+ end, nil)
+ )
+ eq(
+ 43,
+ check_emsg(function()
+ return lib.tv_dict_get_number(d, 'te')
+ end, nil)
+ )
alloc_log:check({})
- eq(0, check_emsg(function() return lib.tv_dict_get_number(d, 't') end,
- 'E805: Using a Float as a Number'))
+ eq(
+ 0,
+ check_emsg(function()
+ return lib.tv_dict_get_number(d, 't')
+ end, 'E805: Using a Float as a Number')
+ )
end)
end)
describe('get_string()', function()
itp('works with NULL dict', function()
- eq(nil, check_emsg(function() return lib.tv_dict_get_string(nil, 'test', false) end,
- nil))
+ eq(
+ nil,
+ check_emsg(function()
+ return lib.tv_dict_get_string(nil, 'test', false)
+ end, nil)
+ )
end)
itp('works', function()
- local d = ffi.gc(dict({test={}}), nil)
- eq('', ffi.string(check_emsg(function() return lib.tv_dict_get_string(d, 'test', false) end,
- 'E731: Using a Dictionary as a String')))
- d = ffi.gc(dict({tes=int(42), t=44, te='43', xx=int(45)}), nil)
+ local d = ffi.gc(dict({ test = {} }), nil)
+ eq(
+ '',
+ ffi.string(check_emsg(function()
+ return lib.tv_dict_get_string(d, 'test', false)
+ end, 'E731: Using a Dictionary as a String'))
+ )
+ d = ffi.gc(dict({ tes = int(42), t = 44, te = '43', xx = int(45) }), nil)
alloc_log:clear()
local dis = dict_items(d)
- eq(nil, check_emsg(function() return lib.tv_dict_get_string(d, 'test', false) end,
- nil))
- local s42 = check_emsg(function() return lib.tv_dict_get_string(d, 'tes', false) end,
- nil)
+ eq(
+ nil,
+ check_emsg(function()
+ return lib.tv_dict_get_string(d, 'test', false)
+ end, nil)
+ )
+ local s42 = check_emsg(function()
+ return lib.tv_dict_get_string(d, 'tes', false)
+ end, nil)
eq('42', ffi.string(s42))
- local s45 = check_emsg(function() return lib.tv_dict_get_string(d, 'xx', false) end,
- nil)
+ local s45 = check_emsg(function()
+ return lib.tv_dict_get_string(d, 'xx', false)
+ end, nil)
eq(s42, s45)
eq('45', ffi.string(s45))
eq('45', ffi.string(s42))
- local s43 = check_emsg(function() return lib.tv_dict_get_string(d, 'te', false) end,
- nil)
+ local s43 = check_emsg(function()
+ return lib.tv_dict_get_string(d, 'te', false)
+ end, nil)
eq('43', ffi.string(s43))
neq(s42, s43)
eq(s43, dis.te.di_tv.vval.v_string)
alloc_log:check({})
- local s44 = check_emsg(function() return lib.tv_dict_get_string(d, 't', false) end,
- nil)
+ local s44 = check_emsg(function()
+ return lib.tv_dict_get_string(d, 't', false)
+ end, nil)
eq('44.0', ffi.string(s44))
- alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null)})
+ alloc_log:check({ a.freed(alloc_log.null), a.freed(alloc_log.null) })
end)
itp('allocates a string copy when requested', function()
local function tv_dict_get_string_alloc(d, key, emsg, is_float)
alloc_log:clear()
- local ret = check_emsg(function() return lib.tv_dict_get_string(d, key, true) end,
- emsg)
+ local ret = check_emsg(function()
+ return lib.tv_dict_get_string(d, key, true)
+ end, emsg)
local s_ret = (ret ~= nil) and ffi.string(ret) or nil
if not emsg then
if s_ret then
if is_float then
- alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null), a.str(ret, s_ret)})
+ alloc_log:check({
+ a.freed(alloc_log.null),
+ a.freed(alloc_log.null),
+ a.str(ret, s_ret),
+ })
else
- alloc_log:check({a.str(ret, s_ret)})
+ alloc_log:check({ a.str(ret, s_ret) })
end
else
alloc_log:check({})
@@ -1790,9 +1900,9 @@ describe('typval.c', function()
lib.xfree(ret)
return s_ret
end
- local d = ffi.gc(dict({test={}}), nil)
+ local d = ffi.gc(dict({ test = {} }), nil)
eq('', tv_dict_get_string_alloc(d, 'test', 'E731: Using a Dictionary as a String'))
- d = ffi.gc(dict({tes=int(42), t=44, te='43', xx=int(45)}), nil)
+ d = ffi.gc(dict({ tes = int(42), t = 44, te = '43', xx = int(45) }), nil)
alloc_log:clear()
eq(nil, tv_dict_get_string_alloc(d, 'test'))
eq('42', tv_dict_get_string_alloc(d, 'tes'))
@@ -1805,12 +1915,13 @@ describe('typval.c', function()
local function tv_dict_get_string_buf(d, key, is_float, buf, emsg)
buf = buf or ffi.gc(lib.xmalloc(lib.NUMBUFLEN), lib.xfree)
alloc_log:clear()
- local ret = check_emsg(function() return lib.tv_dict_get_string_buf(d, key, buf) end,
- emsg)
+ local ret = check_emsg(function()
+ return lib.tv_dict_get_string_buf(d, key, buf)
+ end, emsg)
local s_ret = (ret ~= nil) and ffi.string(ret) or nil
if not emsg then
if is_float then
- alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null)})
+ alloc_log:check({ a.freed(alloc_log.null), a.freed(alloc_log.null) })
else
alloc_log:check({})
end
@@ -1822,12 +1933,12 @@ describe('typval.c', function()
end)
itp('works', function()
local lua_d = {
- ['']={},
- t=1,
- te=int(2),
- tes=empty_list,
- test='tset',
- testt=5,
+ [''] = {},
+ t = 1,
+ te = int(2),
+ tes = empty_list,
+ test = 'tset',
+ testt = 5,
}
local d = dict(lua_d)
alloc_log:clear()
@@ -1851,12 +1962,13 @@ describe('typval.c', function()
def = def or ffi.gc(lib.xstrdup('DEFAULT'), lib.xfree)
len = len or #key
alloc_log:clear()
- local ret = check_emsg(function() return lib.tv_dict_get_string_buf_chk(d, key, len, buf, def) end,
- emsg)
+ local ret = check_emsg(function()
+ return lib.tv_dict_get_string_buf_chk(d, key, len, buf, def)
+ end, emsg)
local s_ret = (ret ~= nil) and ffi.string(ret) or nil
if not emsg then
if is_float then
- alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null)})
+ alloc_log:check({ a.freed(alloc_log.null), a.freed(alloc_log.null) })
else
alloc_log:check({})
end
@@ -1868,12 +1980,12 @@ describe('typval.c', function()
end)
itp('works', function()
local lua_d = {
- ['']={},
- t=1,
- te=int(2),
- tes=empty_list,
- test='tset',
- testt=5,
+ [''] = {},
+ t = 1,
+ te = int(2),
+ tes = empty_list,
+ test = 'tset',
+ testt = 5,
}
local d = dict(lua_d)
alloc_log:clear()
@@ -1901,7 +2013,8 @@ describe('typval.c', function()
describe('get_callback()', function()
local function tv_dict_get_callback(d, key, key_len, emsg)
key_len = key_len or #key
- local cb = ffi.gc(ffi.cast('Callback*', lib.xmalloc(ffi.sizeof('Callback'))), lib.callback_free)
+ local cb =
+ ffi.gc(ffi.cast('Callback*', lib.xmalloc(ffi.sizeof('Callback'))), lib.callback_free)
alloc_log:clear()
local ret = check_emsg(function()
return lib.tv_dict_get_callback(d, key, key_len, cb)
@@ -1910,35 +2023,59 @@ describe('typval.c', function()
return cb_lua, ret
end
itp('works with NULL dict', function()
- eq({{type='none'}, true}, {tv_dict_get_callback(nil, '')})
+ eq({ { type = 'none' }, true }, { tv_dict_get_callback(nil, '') })
end)
itp('works', function()
local lua_d = {
- ['']='tr',
- t=int(1),
- te={[type_key]=func_type, value='tr'},
- tes={[type_key]=func_type, value='tr', args={'a', 'b'}},
- test={[type_key]=func_type, value='Test', dict={test=1}, args={}},
- testt={[type_key]=func_type, value='Test', dict={test=1}, args={1}},
+ [''] = 'tr',
+ t = int(1),
+ te = { [type_key] = func_type, value = 'tr' },
+ tes = { [type_key] = func_type, value = 'tr', args = { 'a', 'b' } },
+ test = { [type_key] = func_type, value = 'Test', dict = { test = 1 }, args = {} },
+ testt = { [type_key] = func_type, value = 'Test', dict = { test = 1 }, args = { 1 } },
}
local d = dict(lua_d)
eq(lua_d, dct2tbl(d))
- eq({{type='fref', fref='tr'}, true},
- {tv_dict_get_callback(d, '', -1)})
- eq({{type='none'}, true},
- {tv_dict_get_callback(d, 'x', -1)})
- eq({{type='fref', fref='tr'}, true},
- {tv_dict_get_callback(d, 'testt', 0)})
- eq({{type='none'}, false},
- {tv_dict_get_callback(d, 'test', 1, 'E6000: Argument is not a function or function name')})
- eq({{type='fref', fref='tr'}, true},
- {tv_dict_get_callback(d, 'testt', 2)})
- eq({{ type='pt', fref='tr', pt={ [type_key]=func_type, value='tr', args={ 'a', 'b' } } }, true},
- {tv_dict_get_callback(d, 'testt', 3)})
- eq({{ type='pt', fref='Test', pt={ [type_key]=func_type, value='Test', dict={ test=1 }, args={} } }, true},
- {tv_dict_get_callback(d, 'testt', 4)})
- eq({{ type='pt', fref='Test', pt={ [type_key]=func_type, value='Test', dict={ test=1 }, args={1} } }, true},
- {tv_dict_get_callback(d, 'testt', 5)})
+ eq({ { type = 'fref', fref = 'tr' }, true }, { tv_dict_get_callback(d, '', -1) })
+ eq({ { type = 'none' }, true }, { tv_dict_get_callback(d, 'x', -1) })
+ eq({ { type = 'fref', fref = 'tr' }, true }, { tv_dict_get_callback(d, 'testt', 0) })
+ eq({ { type = 'none' }, false }, {
+ tv_dict_get_callback(
+ d,
+ 'test',
+ 1,
+ 'E6000: Argument is not a function or function name'
+ ),
+ })
+ eq({ { type = 'fref', fref = 'tr' }, true }, { tv_dict_get_callback(d, 'testt', 2) })
+ eq({
+ {
+ type = 'pt',
+ fref = 'tr',
+ pt = {
+ [type_key] = func_type,
+ value = 'tr',
+ args = { 'a', 'b' },
+ },
+ },
+ true,
+ }, { tv_dict_get_callback(d, 'testt', 3) })
+ eq({
+ {
+ type = 'pt',
+ fref = 'Test',
+ pt = { [type_key] = func_type, value = 'Test', dict = { test = 1 }, args = {} },
+ },
+ true,
+ }, { tv_dict_get_callback(d, 'testt', 4) })
+ eq({
+ {
+ type = 'pt',
+ fref = 'Test',
+ pt = { [type_key] = func_type, value = 'Test', dict = { test = 1 }, args = { 1 } },
+ },
+ true,
+ }, { tv_dict_get_callback(d, 'testt', 5) })
end)
end)
end)
@@ -1946,22 +2083,26 @@ describe('typval.c', function()
describe('()', function()
itp('works', function()
local di = lib.tv_dict_item_alloc_len('t-est', 5)
- alloc_log:check({a.di(di, 't-est')})
+ alloc_log:check({ a.di(di, 't-est') })
di.di_tv.v_type = lib.VAR_NUMBER
di.di_tv.vval.v_number = 42
- local d = dict({test=10})
+ local d = dict({ test = 10 })
local dis = dict_items(d)
alloc_log:check({
a.dict(d),
- a.di(dis.test, 'test')
+ a.di(dis.test, 'test'),
})
- eq({test=10}, dct2tbl(d))
+ eq({ test = 10 }, dct2tbl(d))
alloc_log:clear()
eq(OK, lib.tv_dict_add(d, di))
alloc_log:check({})
- eq({test=10, ['t-est']=int(42)}, dct2tbl(d))
- eq(FAIL, check_emsg(function() return lib.tv_dict_add(d, di) end,
- 'E685: Internal error: hash_add(): duplicate key "t-est"'))
+ eq({ test = 10, ['t-est'] = int(42) }, dct2tbl(d))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add(d, di)
+ end, 'E685: Internal error: hash_add(): duplicate key "t-est"')
+ )
end)
end)
describe('list()', function()
@@ -1969,21 +2110,29 @@ describe('typval.c', function()
local l = list(1, 2, 3)
alloc_log:clear()
eq(1, l.lv_refcount)
- local d = dict({test=10})
+ local d = dict({ test = 10 })
alloc_log:clear()
- eq({test=10}, dct2tbl(d))
+ eq({ test = 10 }, dct2tbl(d))
eq(OK, lib.tv_dict_add_list(d, 'testt', 3, l))
local dis = dict_items(d)
- alloc_log:check({a.di(dis.tes, 'tes')})
- eq({test=10, tes={1, 2, 3}}, dct2tbl(d))
+ alloc_log:check({ a.di(dis.tes, 'tes') })
+ eq({ test = 10, tes = { 1, 2, 3 } }, dct2tbl(d))
eq(2, l.lv_refcount)
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_list(d, 'testt', 3, l) end,
- 'E685: Internal error: hash_add(): duplicate key "tes"'))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_list(d, 'testt', 3, l)
+ end, 'E685: Internal error: hash_add(): duplicate key "tes"')
+ )
eq(2, l.lv_refcount)
alloc_log:clear()
lib.emsg_skip = lib.emsg_skip + 1
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_list(d, 'testt', 3, l) end,
- nil))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_list(d, 'testt', 3, l)
+ end, nil)
+ )
eq(2, l.lv_refcount)
lib.emsg_skip = lib.emsg_skip - 1
alloc_log:clear_tmp_allocs()
@@ -1992,24 +2141,32 @@ describe('typval.c', function()
end)
describe('dict()', function()
itp('works', function()
- local d2 = dict({foo=42})
+ local d2 = dict({ foo = 42 })
alloc_log:clear()
eq(1, d2.dv_refcount)
- local d = dict({test=10})
+ local d = dict({ test = 10 })
alloc_log:clear()
- eq({test=10}, dct2tbl(d))
+ eq({ test = 10 }, dct2tbl(d))
eq(OK, lib.tv_dict_add_dict(d, 'testt', 3, d2))
local dis = dict_items(d)
- alloc_log:check({a.di(dis.tes, 'tes')})
- eq({test=10, tes={foo=42}}, dct2tbl(d))
+ alloc_log:check({ a.di(dis.tes, 'tes') })
+ eq({ test = 10, tes = { foo = 42 } }, dct2tbl(d))
eq(2, d2.dv_refcount)
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_dict(d, 'testt', 3, d2) end,
- 'E685: Internal error: hash_add(): duplicate key "tes"'))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_dict(d, 'testt', 3, d2)
+ end, 'E685: Internal error: hash_add(): duplicate key "tes"')
+ )
eq(2, d2.dv_refcount)
alloc_log:clear()
lib.emsg_skip = lib.emsg_skip + 1
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_dict(d, 'testt', 3, d2) end,
- nil))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_dict(d, 'testt', 3, d2)
+ end, nil)
+ )
eq(2, d2.dv_refcount)
lib.emsg_skip = lib.emsg_skip - 1
alloc_log:clear_tmp_allocs()
@@ -2018,19 +2175,27 @@ describe('typval.c', function()
end)
describe('nr()', function()
itp('works', function()
- local d = dict({test=10})
+ local d = dict({ test = 10 })
alloc_log:clear()
- eq({test=10}, dct2tbl(d))
+ eq({ test = 10 }, dct2tbl(d))
eq(OK, lib.tv_dict_add_nr(d, 'testt', 3, 2))
local dis = dict_items(d)
- alloc_log:check({a.di(dis.tes, 'tes')})
- eq({test=10, tes=int(2)}, dct2tbl(d))
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_nr(d, 'testt', 3, 2) end,
- 'E685: Internal error: hash_add(): duplicate key "tes"'))
+ alloc_log:check({ a.di(dis.tes, 'tes') })
+ eq({ test = 10, tes = int(2) }, dct2tbl(d))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_nr(d, 'testt', 3, 2)
+ end, 'E685: Internal error: hash_add(): duplicate key "tes"')
+ )
alloc_log:clear()
lib.emsg_skip = lib.emsg_skip + 1
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_nr(d, 'testt', 3, 2) end,
- nil))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_nr(d, 'testt', 3, 2)
+ end, nil)
+ )
lib.emsg_skip = lib.emsg_skip - 1
alloc_log:clear_tmp_allocs()
alloc_log:check({})
@@ -2038,19 +2203,27 @@ describe('typval.c', function()
end)
describe('float()', function()
itp('works', function()
- local d = dict({test=10})
+ local d = dict({ test = 10 })
alloc_log:clear()
- eq({test=10}, dct2tbl(d))
+ eq({ test = 10 }, dct2tbl(d))
eq(OK, lib.tv_dict_add_float(d, 'testt', 3, 1.5))
local dis = dict_items(d)
- alloc_log:check({a.di(dis.tes, 'tes')})
- eq({test=10, tes=1.5}, dct2tbl(d))
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_float(d, 'testt', 3, 1.5) end,
- 'E685: Internal error: hash_add(): duplicate key "tes"'))
+ alloc_log:check({ a.di(dis.tes, 'tes') })
+ eq({ test = 10, tes = 1.5 }, dct2tbl(d))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_float(d, 'testt', 3, 1.5)
+ end, 'E685: Internal error: hash_add(): duplicate key "tes"')
+ )
alloc_log:clear()
lib.emsg_skip = lib.emsg_skip + 1
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_float(d, 'testt', 3, 1.5) end,
- nil))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_float(d, 'testt', 3, 1.5)
+ end, nil)
+ )
lib.emsg_skip = lib.emsg_skip - 1
alloc_log:clear_tmp_allocs()
alloc_log:check({})
@@ -2058,22 +2231,30 @@ describe('typval.c', function()
end)
describe('str()', function()
itp('works', function()
- local d = dict({test=10})
+ local d = dict({ test = 10 })
alloc_log:clear()
- eq({test=10}, dct2tbl(d))
+ eq({ test = 10 }, dct2tbl(d))
eq(OK, lib.tv_dict_add_str(d, 'testt', 3, 'TEST'))
local dis = dict_items(d)
alloc_log:check({
a.str(dis.tes.di_tv.vval.v_string, 'TEST'),
a.di(dis.tes, 'tes'),
})
- eq({test=10, tes='TEST'}, dct2tbl(d))
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_str(d, 'testt', 3, 'TEST') end,
- 'E685: Internal error: hash_add(): duplicate key "tes"'))
+ eq({ test = 10, tes = 'TEST' }, dct2tbl(d))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_str(d, 'testt', 3, 'TEST')
+ end, 'E685: Internal error: hash_add(): duplicate key "tes"')
+ )
alloc_log:clear()
lib.emsg_skip = lib.emsg_skip + 1
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_str(d, 'testt', 3, 'TEST') end,
- nil))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_str(d, 'testt', 3, 'TEST')
+ end, nil)
+ )
lib.emsg_skip = lib.emsg_skip - 1
alloc_log:clear_tmp_allocs()
alloc_log:check({})
@@ -2081,8 +2262,8 @@ describe('typval.c', function()
end)
describe('allocated_str()', function()
itp('works', function()
- local d = dict({test=10})
- eq({test=10}, dct2tbl(d))
+ local d = dict({ test = 10 })
+ eq({ test = 10 }, dct2tbl(d))
alloc_log:clear()
local s1 = lib.xstrdup('TEST')
local s2 = lib.xstrdup('TEST')
@@ -2097,13 +2278,21 @@ describe('typval.c', function()
alloc_log:check({
a.di(dis.tes, 'tes'),
})
- eq({test=10, tes='TEST'}, dct2tbl(d))
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_allocated_str(d, 'testt', 3, s2) end,
- 'E685: Internal error: hash_add(): duplicate key "tes"'))
+ eq({ test = 10, tes = 'TEST' }, dct2tbl(d))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_allocated_str(d, 'testt', 3, s2)
+ end, 'E685: Internal error: hash_add(): duplicate key "tes"')
+ )
alloc_log:clear()
lib.emsg_skip = lib.emsg_skip + 1
- eq(FAIL, check_emsg(function() return lib.tv_dict_add_allocated_str(d, 'testt', 3, s3) end,
- nil))
+ eq(
+ FAIL,
+ check_emsg(function()
+ return lib.tv_dict_add_allocated_str(d, 'testt', 3, s3)
+ end, nil)
+ )
lib.emsg_skip = lib.emsg_skip - 1
alloc_log:clear_tmp_allocs()
alloc_log:check({
@@ -2115,7 +2304,7 @@ describe('typval.c', function()
describe('clear()', function()
itp('works', function()
local d = dict()
- alloc_log:check({a.dict(d)})
+ alloc_log:check({ a.dict(d) })
eq({}, dct2tbl(d))
lib.tv_dict_clear(d)
eq({}, dct2tbl(d))
@@ -2123,32 +2312,34 @@ describe('typval.c', function()
local dis = dict_items(d)
local di = dis.TES
local di_s = di.di_tv.vval.v_string
- alloc_log:check({a.str(di_s), a.di(di)})
- eq({TES='tEsT'}, dct2tbl(d))
+ alloc_log:check({ a.str(di_s), a.di(di) })
+ eq({ TES = 'tEsT' }, dct2tbl(d))
lib.tv_dict_clear(d)
- alloc_log:check({a.freed(di_s), a.freed(di)})
+ alloc_log:check({ a.freed(di_s), a.freed(di) })
eq({}, dct2tbl(d))
end)
end)
describe('extend()', function()
local function tv_dict_extend(d1, d2, action, emsg)
- action = action or "force"
- check_emsg(function() return lib.tv_dict_extend(d1, d2, action) end, emsg)
+ action = action or 'force'
+ check_emsg(function()
+ return lib.tv_dict_extend(d1, d2, action)
+ end, emsg)
end
itp('works', function()
local d1 = dict()
- alloc_log:check({a.dict(d1)})
+ alloc_log:check({ a.dict(d1) })
eq({}, dct2tbl(d1))
local d2 = dict()
- alloc_log:check({a.dict(d2)})
+ alloc_log:check({ a.dict(d2) })
eq({}, dct2tbl(d2))
tv_dict_extend(d1, d2, 'error')
tv_dict_extend(d1, d2, 'keep')
tv_dict_extend(d1, d2, 'force')
alloc_log:check({})
- d1 = dict({a='TEST'})
- eq({a='TEST'}, dct2tbl(d1))
+ d1 = dict({ a = 'TEST' })
+ eq({ a = 'TEST' }, dct2tbl(d1))
local dis1 = dict_items(d1)
local a1_s = dis1.a.di_tv.vval.v_string
alloc_log:clear_tmp_allocs()
@@ -2157,8 +2348,8 @@ describe('typval.c', function()
a.di(dis1.a),
a.str(a1_s),
})
- d2 = dict({a='TSET'})
- eq({a='TSET'}, dct2tbl(d2))
+ d2 = dict({ a = 'TSET' })
+ eq({ a = 'TSET' }, dct2tbl(d2))
local dis2 = dict_items(d2)
local a2_s = dis2.a.di_tv.vval.v_string
alloc_log:clear_tmp_allocs()
@@ -2169,72 +2360,66 @@ describe('typval.c', function()
})
tv_dict_extend(d1, d2, 'error', 'E737: Key already exists: a')
- eq({a='TEST'}, dct2tbl(d1))
- eq({a='TSET'}, dct2tbl(d2))
+ eq({ a = 'TEST' }, dct2tbl(d1))
+ eq({ a = 'TSET' }, dct2tbl(d2))
alloc_log:clear()
tv_dict_extend(d1, d2, 'keep')
alloc_log:check({})
- eq({a='TEST'}, dct2tbl(d1))
- eq({a='TSET'}, dct2tbl(d2))
+ eq({ a = 'TEST' }, dct2tbl(d1))
+ eq({ a = 'TSET' }, dct2tbl(d2))
tv_dict_extend(d1, d2, 'force')
alloc_log:check({
a.freed(a1_s),
a.str(dis1.a.di_tv.vval.v_string),
})
- eq({a='TSET'}, dct2tbl(d1))
- eq({a='TSET'}, dct2tbl(d2))
+ eq({ a = 'TSET' }, dct2tbl(d1))
+ eq({ a = 'TSET' }, dct2tbl(d2))
end)
pending('disallows overriding builtin or user functions: here be the dragons', function()
-- pending: see TODO below
local d = dict()
d.dv_scope = lib.VAR_DEF_SCOPE
local f_lua = {
- [type_key]=func_type,
- value='tr',
+ [type_key] = func_type,
+ value = 'tr',
}
local f_tv = lua2typvalt(f_lua)
local p_lua = {
- [type_key]=func_type,
- value='tr',
- args={1},
+ [type_key] = func_type,
+ value = 'tr',
+ args = { 1 },
}
local p_tv = lua2typvalt(p_lua)
eq(lib.VAR_PARTIAL, p_tv.v_type)
- local d2 = dict({tr=f_tv})
- local d3 = dict({tr=p_tv})
- local d4 = dict({['TEST:THIS']=p_tv})
- local d5 = dict({Test=f_tv})
- local d6 = dict({Test=p_tv})
+ local d2 = dict({ tr = f_tv })
+ local d3 = dict({ tr = p_tv })
+ local d4 = dict({ ['TEST:THIS'] = p_tv })
+ local d5 = dict({ Test = f_tv })
+ local d6 = dict({ Test = p_tv })
eval0([[execute("function Test()\nendfunction")]])
-- TODO: test breaks at this point
- tv_dict_extend(d, d2, 'force',
- 'E704: Funcref variable name must start with a capital: tr')
- tv_dict_extend(d, d3, 'force',
- 'E704: Funcref variable name must start with a capital: tr')
- tv_dict_extend(d, d4, 'force',
- 'E461: Illegal variable name: TEST:THIS')
- tv_dict_extend(d, d5, 'force',
- 'E705: Variable name conflicts with existing function: Test')
- tv_dict_extend(d, d6, 'force',
- 'E705: Variable name conflicts with existing function: Test')
+ tv_dict_extend(d, d2, 'force', 'E704: Funcref variable name must start with a capital: tr')
+ tv_dict_extend(d, d3, 'force', 'E704: Funcref variable name must start with a capital: tr')
+ tv_dict_extend(d, d4, 'force', 'E461: Illegal variable name: TEST:THIS')
+ tv_dict_extend(d, d5, 'force', 'E705: Variable name conflicts with existing function: Test')
+ tv_dict_extend(d, d6, 'force', 'E705: Variable name conflicts with existing function: Test')
eq({}, dct2tbl(d))
d.dv_scope = lib.VAR_SCOPE
- tv_dict_extend(d, d4, 'force',
- 'E461: Illegal variable name: TEST:THIS')
+ tv_dict_extend(d, d4, 'force', 'E461: Illegal variable name: TEST:THIS')
eq({}, dct2tbl(d))
tv_dict_extend(d, d2, 'force')
- eq({tr=f_lua}, dct2tbl(d))
+ eq({ tr = f_lua }, dct2tbl(d))
tv_dict_extend(d, d3, 'force')
- eq({tr=p_lua}, dct2tbl(d))
+ eq({ tr = p_lua }, dct2tbl(d))
tv_dict_extend(d, d5, 'force')
- eq({tr=p_lua, Test=f_lua}, dct2tbl(d))
+ eq({ tr = p_lua, Test = f_lua }, dct2tbl(d))
tv_dict_extend(d, d6, 'force')
- eq({tr=p_lua, Test=p_lua}, dct2tbl(d))
+ eq({ tr = p_lua, Test = p_lua }, dct2tbl(d))
end)
itp('cares about locks and read-only items', function()
- local d_lua = {tv_locked=1, tv_fixed=2, di_ro=3, di_ro_sbx=4}
+ local d_lua = { tv_locked = 1, tv_fixed = 2, di_ro = 3, di_ro_sbx = 4 }
local d = dict(d_lua)
local dis = dict_items(d)
dis.tv_locked.di_tv.v_lock = lib.VAR_LOCKED
@@ -2242,14 +2427,19 @@ describe('typval.c', function()
dis.di_ro.di_flags = bit.bor(dis.di_ro.di_flags, lib.DI_FLAGS_RO)
dis.di_ro_sbx.di_flags = bit.bor(dis.di_ro_sbx.di_flags, lib.DI_FLAGS_RO_SBX)
lib.sandbox = true
- local d1 = dict({tv_locked=41})
- local d2 = dict({tv_fixed=42})
- local d3 = dict({di_ro=43})
- local d4 = dict({di_ro_sbx=44})
+ local d1 = dict({ tv_locked = 41 })
+ local d2 = dict({ tv_fixed = 42 })
+ local d3 = dict({ di_ro = 43 })
+ local d4 = dict({ di_ro_sbx = 44 })
tv_dict_extend(d, d1, 'force', 'E741: Value is locked: extend() argument')
tv_dict_extend(d, d2, 'force', 'E742: Cannot change value of extend() argument')
tv_dict_extend(d, d3, 'force', 'E46: Cannot change read-only variable "extend() argument"')
- tv_dict_extend(d, d4, 'force', 'E794: Cannot set variable in the sandbox: "extend() argument"')
+ tv_dict_extend(
+ d,
+ d4,
+ 'force',
+ 'E794: Cannot set variable in the sandbox: "extend() argument"'
+ )
eq(d_lua, dct2tbl(d))
lib.sandbox = false
tv_dict_extend(d, d4, 'force')
@@ -2264,20 +2454,20 @@ describe('typval.c', function()
itp('works', function()
eq(true, tv_dict_equal(nil, nil))
local d1 = dict()
- alloc_log:check({a.dict(d1)})
+ alloc_log:check({ a.dict(d1) })
eq(1, d1.dv_refcount)
eq(true, tv_dict_equal(nil, d1))
eq(true, tv_dict_equal(d1, nil))
eq(true, tv_dict_equal(d1, d1))
eq(1, d1.dv_refcount)
alloc_log:check({})
- local d_upper = dict({a='TEST'})
+ local d_upper = dict({ a = 'TEST' })
local dis_upper = dict_items(d_upper)
- local d_lower = dict({a='test'})
+ local d_lower = dict({ a = 'test' })
local dis_lower = dict_items(d_lower)
- local d_kupper_upper = dict({A='TEST'})
+ local d_kupper_upper = dict({ A = 'TEST' })
local dis_kupper_upper = dict_items(d_kupper_upper)
- local d_kupper_lower = dict({A='test'})
+ local d_kupper_lower = dict({ A = 'test' })
local dis_kupper_lower = dict_items(d_kupper_lower)
alloc_log:clear_tmp_allocs()
alloc_log:check({
@@ -2320,7 +2510,15 @@ describe('typval.c', function()
end)
itp('copies dict correctly without converting items', function()
do
- local v = {a={['«']='»'}, b={'„'}, ['1']=1, ['«»']='“', ns=null_string, nl=null_list, nd=null_dict}
+ local v = {
+ a = { ['«'] = '»' },
+ b = { '„' },
+ ['1'] = 1,
+ ['«»'] = '“',
+ ns = null_string,
+ nl = null_list,
+ nd = null_dict,
+ }
local d_tv = lua2typvalt(v)
local d = d_tv.vval.v_dict
local dis = dict_items(d)
@@ -2358,7 +2556,15 @@ describe('typval.c', function()
-- UTF-8 ↔ latin1 conversions need no iconv
eq(OK, lib.convert_setup(vc, to_cstr('utf-8'), to_cstr('latin1')))
- local v = {a={['«']='»'}, b={'„'}, ['1']=1, ['«»']='“', ns=null_string, nl=null_list, nd=null_dict}
+ local v = {
+ a = { ['«'] = '»' },
+ b = { '„' },
+ ['1'] = 1,
+ ['«»'] = '“',
+ ns = null_string,
+ nl = null_list,
+ nd = null_dict,
+ }
local d_tv = lua2typvalt(v)
local d = d_tv.vval.v_dict
local dis = dict_items(d)
@@ -2373,14 +2579,21 @@ describe('typval.c', function()
local dis_deepcopy1 = dict_items(d_deepcopy1)
neq(dis.a.di_tv.vval.v_dict, dis_deepcopy1.a.di_tv.vval.v_dict)
neq(dis.b.di_tv.vval.v_list, dis_deepcopy1.b.di_tv.vval.v_list)
- eq({a={['\171']='\187'}, b={'\191'}, ['1']=1, ['\171\187']='\191', ns=null_string, nl=null_list, nd=null_dict},
- dct2tbl(d_deepcopy1))
+ eq({
+ a = { ['\171'] = '\187' },
+ b = { '\191' },
+ ['1'] = 1,
+ ['\171\187'] = '\191',
+ ns = null_string,
+ nl = null_list,
+ nd = null_dict,
+ }, dct2tbl(d_deepcopy1))
alloc_log:clear_tmp_allocs()
alloc_log:clear()
end)
itp('returns different/same containers with(out) copyID', function()
local d_inner_tv = lua2typvalt({})
- local d_tv = lua2typvalt({a=d_inner_tv, b=d_inner_tv})
+ local d_tv = lua2typvalt({ a = d_inner_tv, b = d_inner_tv })
eq(3, d_inner_tv.vval.v_dict.dv_refcount)
local d = d_tv.vval.v_dict
local dis = dict_items(d)
@@ -2389,12 +2602,12 @@ describe('typval.c', function()
local d_copy1 = tv_dict_copy(nil, d, true, 0)
local dis_copy1 = dict_items(d_copy1)
neq(dis_copy1.a.di_tv.vval.v_dict, dis_copy1.b.di_tv.vval.v_dict)
- eq({a={}, b={}}, dct2tbl(d_copy1))
+ eq({ a = {}, b = {} }, dct2tbl(d_copy1))
local d_copy2 = tv_dict_copy(nil, d, true, 2)
local dis_copy2 = dict_items(d_copy2)
eq(dis_copy2.a.di_tv.vval.v_dict, dis_copy2.b.di_tv.vval.v_dict)
- eq({a={}, b={}}, dct2tbl(d_copy2))
+ eq({ a = {}, b = {} }, dct2tbl(d_copy2))
eq(3, d_inner_tv.vval.v_dict.dv_refcount)
end)
@@ -2420,9 +2633,9 @@ describe('typval.c', function()
end)
describe('set_keys_readonly()', function()
itp('works', function()
- local d = dict({a=true})
+ local d = dict({ a = true })
local dis = dict_items(d)
- alloc_log:check({a.dict(d), a.di(dis.a)})
+ alloc_log:check({ a.dict(d), a.di(dis.a) })
eq(0, bit.band(dis.a.di_flags, lib.DI_FLAGS_RO))
eq(0, bit.band(dis.a.di_flags, lib.DI_FLAGS_FIX))
lib.tv_dict_set_keys_readonly(d)
@@ -2472,23 +2685,52 @@ describe('typval.c', function()
local dd_d = nil
dd.dd = dd
for _, v in ipairs({
- {nil_value},
- {null_string, nil, function() return {a.freed(alloc_log.null)} end},
- {0},
- {int(0)},
- {true},
- {false},
- {'true', function(tv) return {a.str(tv.vval.v_string)} end},
- {{}, function(tv) return {a.dict(tv.vval.v_dict)} end},
- {empty_list, function(tv) return {a.list(tv.vval.v_list)} end},
- {ll, function(tv)
- ll_l = tv.vval.v_list
- return {a.list(tv.vval.v_list), a.li(tv.vval.v_list.lv_first)}
- end, defalloc},
- {dd, function(tv)
- dd_d = tv.vval.v_dict
- return {a.dict(tv.vval.v_dict), a.di(first_di(tv.vval.v_dict))}
- end, defalloc},
+ { nil_value },
+ {
+ null_string,
+ nil,
+ function()
+ return { a.freed(alloc_log.null) }
+ end,
+ },
+ { 0 },
+ { int(0) },
+ { true },
+ { false },
+ {
+ 'true',
+ function(tv)
+ return { a.str(tv.vval.v_string) }
+ end,
+ },
+ {
+ {},
+ function(tv)
+ return { a.dict(tv.vval.v_dict) }
+ end,
+ },
+ {
+ empty_list,
+ function(tv)
+ return { a.list(tv.vval.v_list) }
+ end,
+ },
+ {
+ ll,
+ function(tv)
+ ll_l = tv.vval.v_list
+ return { a.list(tv.vval.v_list), a.li(tv.vval.v_list.lv_first) }
+ end,
+ defalloc,
+ },
+ {
+ dd,
+ function(tv)
+ dd_d = tv.vval.v_dict
+ return { a.dict(tv.vval.v_dict), a.di(first_di(tv.vval.v_dict)) }
+ end,
+ defalloc,
+ },
}) do
local tv = lua2typvalt(v[1])
local alloc_rets = {}
@@ -2503,26 +2745,45 @@ describe('typval.c', function()
describe('copy()', function()
itp('works', function()
local function strallocs(tv)
- return {a.str(tv.vval.v_string)}
+ return { a.str(tv.vval.v_string) }
end
for _, v in ipairs({
- {nil_value},
- {null_string},
- {0},
- {int(0)},
- {true},
- {false},
- {{}, function(tv) return {a.dict(tv.vval.v_dict)} end, nil, function(from, to)
- eq(2, to.vval.v_dict.dv_refcount)
- eq(to.vval.v_dict, from.vval.v_dict)
- end},
- {empty_list, function(tv) return {a.list(tv.vval.v_list)} end, nil, function(from, to)
- eq(2, to.vval.v_list.lv_refcount)
- eq(to.vval.v_list, from.vval.v_list)
- end},
- {'test', strallocs, strallocs, function(from, to)
- neq(to.vval.v_string, from.vval.v_string)
- end},
+ { nil_value },
+ { null_string },
+ { 0 },
+ { int(0) },
+ { true },
+ { false },
+ {
+ {},
+ function(tv)
+ return { a.dict(tv.vval.v_dict) }
+ end,
+ nil,
+ function(from, to)
+ eq(2, to.vval.v_dict.dv_refcount)
+ eq(to.vval.v_dict, from.vval.v_dict)
+ end,
+ },
+ {
+ empty_list,
+ function(tv)
+ return { a.list(tv.vval.v_list) }
+ end,
+ nil,
+ function(from, to)
+ eq(2, to.vval.v_list.lv_refcount)
+ eq(to.vval.v_list, from.vval.v_list)
+ end,
+ },
+ {
+ 'test',
+ strallocs,
+ strallocs,
+ function(from, to)
+ neq(to.vval.v_string, from.vval.v_string)
+ end,
+ },
}) do
local from = lua2typvalt(v[1])
alloc_log:check((v[2] or defalloc)(from))
@@ -2540,9 +2801,9 @@ describe('typval.c', function()
describe('item_lock()', function()
itp('does not alter VAR_PARTIAL', function()
local p_tv = lua2typvalt({
- [type_key]=func_type,
- value='tr',
- dict={},
+ [type_key] = func_type,
+ value = 'tr',
+ dict = {},
})
lib.tv_item_lock(p_tv, -1, true, false)
eq(lib.VAR_UNLOCKED, p_tv.vval.v_partial.pt_dict.dv_lock)
@@ -2641,18 +2902,18 @@ describe('typval.c', function()
end
itp('works', function()
eq(false, tv_check_lock(lib.VAR_UNLOCKED, 'test', 3))
- eq(true, tv_check_lock(lib.VAR_LOCKED, 'test', 3,
- 'E741: Value is locked: tes'))
- eq(true, tv_check_lock(lib.VAR_FIXED, 'test', 3,
- 'E742: Cannot change value of tes'))
- eq(true, tv_check_lock(lib.VAR_LOCKED, nil, 0,
- 'E741: Value is locked: Unknown'))
- eq(true, tv_check_lock(lib.VAR_FIXED, nil, 0,
- 'E742: Cannot change value of Unknown'))
- eq(true, tv_check_lock(lib.VAR_LOCKED, nil, lib.kTVCstring,
- 'E741: Value is locked: Unknown'))
- eq(true, tv_check_lock(lib.VAR_FIXED, 'test', lib.kTVCstring,
- 'E742: Cannot change value of test'))
+ eq(true, tv_check_lock(lib.VAR_LOCKED, 'test', 3, 'E741: Value is locked: tes'))
+ eq(true, tv_check_lock(lib.VAR_FIXED, 'test', 3, 'E742: Cannot change value of tes'))
+ eq(true, tv_check_lock(lib.VAR_LOCKED, nil, 0, 'E741: Value is locked: Unknown'))
+ eq(true, tv_check_lock(lib.VAR_FIXED, nil, 0, 'E742: Cannot change value of Unknown'))
+ eq(
+ true,
+ tv_check_lock(lib.VAR_LOCKED, nil, lib.kTVCstring, 'E741: Value is locked: Unknown')
+ )
+ eq(
+ true,
+ tv_check_lock(lib.VAR_FIXED, 'test', lib.kTVCstring, 'E742: Cannot change value of test')
+ )
end)
end)
describe('equal()', function()
@@ -2683,15 +2944,15 @@ describe('typval.c', function()
-- indicates that tv_equal_recurse_limit and recursive_cnt were set which
-- is essential. This argument will be set when comparing inner lists.
itp('compares lists correctly when case is not ignored', function()
- local l1 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'def'})
- local l2 = lua2typvalt({'abc', {1, 2, 'Abc'}})
- local l3 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'Def'})
- local l4 = lua2typvalt({'abc', {1, 2, 'Abc', 4}, 'def'})
- local l5 = lua2typvalt({'Abc', {1, 2, 'Abc'}, 'def'})
- local l6 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'def'})
- local l7 = lua2typvalt({'abc', {1, 2, 'abc'}, 'def'})
- local l8 = lua2typvalt({'abc', nil, 'def'})
- local l9 = lua2typvalt({'abc', {1, 2, nil}, 'def'})
+ local l1 = lua2typvalt({ 'abc', { 1, 2, 'Abc' }, 'def' })
+ local l2 = lua2typvalt({ 'abc', { 1, 2, 'Abc' } })
+ local l3 = lua2typvalt({ 'abc', { 1, 2, 'Abc' }, 'Def' })
+ local l4 = lua2typvalt({ 'abc', { 1, 2, 'Abc', 4 }, 'def' })
+ local l5 = lua2typvalt({ 'Abc', { 1, 2, 'Abc' }, 'def' })
+ local l6 = lua2typvalt({ 'abc', { 1, 2, 'Abc' }, 'def' })
+ local l7 = lua2typvalt({ 'abc', { 1, 2, 'abc' }, 'def' })
+ local l8 = lua2typvalt({ 'abc', nil, 'def' })
+ local l9 = lua2typvalt({ 'abc', { 1, 2, nil }, 'def' })
eq(true, lib.tv_equal(l1, l1, false, false))
eq(false, lib.tv_equal(l1, l2, false, false))
@@ -2704,15 +2965,15 @@ describe('typval.c', function()
eq(false, lib.tv_equal(l1, l9, false, false))
end)
itp('compares lists correctly when case is ignored', function()
- local l1 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'def'})
- local l2 = lua2typvalt({'abc', {1, 2, 'Abc'}})
- local l3 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'Def'})
- local l4 = lua2typvalt({'abc', {1, 2, 'Abc', 4}, 'def'})
- local l5 = lua2typvalt({'Abc', {1, 2, 'Abc'}, 'def'})
- local l6 = lua2typvalt({'abc', {1, 2, 'Abc'}, 'def'})
- local l7 = lua2typvalt({'abc', {1, 2, 'abc'}, 'def'})
- local l8 = lua2typvalt({'abc', nil, 'def'})
- local l9 = lua2typvalt({'abc', {1, 2, nil}, 'def'})
+ local l1 = lua2typvalt({ 'abc', { 1, 2, 'Abc' }, 'def' })
+ local l2 = lua2typvalt({ 'abc', { 1, 2, 'Abc' } })
+ local l3 = lua2typvalt({ 'abc', { 1, 2, 'Abc' }, 'Def' })
+ local l4 = lua2typvalt({ 'abc', { 1, 2, 'Abc', 4 }, 'def' })
+ local l5 = lua2typvalt({ 'Abc', { 1, 2, 'Abc' }, 'def' })
+ local l6 = lua2typvalt({ 'abc', { 1, 2, 'Abc' }, 'def' })
+ local l7 = lua2typvalt({ 'abc', { 1, 2, 'abc' }, 'def' })
+ local l8 = lua2typvalt({ 'abc', nil, 'def' })
+ local l9 = lua2typvalt({ 'abc', { 1, 2, nil }, 'def' })
eq(true, lib.tv_equal(l1, l1, true, false))
eq(false, lib.tv_equal(l1, l2, true, false))
@@ -2732,20 +2993,20 @@ describe('typval.c', function()
eq(true, tv_equal(nd, nd))
alloc_log:check({})
local d1 = lua2typvalt({})
- alloc_log:check({a.dict(d1.vval.v_dict)})
+ alloc_log:check({ a.dict(d1.vval.v_dict) })
eq(1, d1.vval.v_dict.dv_refcount)
eq(true, tv_equal(nd, d1))
eq(true, tv_equal(d1, nd))
eq(true, tv_equal(d1, d1))
eq(1, d1.vval.v_dict.dv_refcount)
alloc_log:check({})
- local d_upper = lua2typvalt({a='TEST'})
+ local d_upper = lua2typvalt({ a = 'TEST' })
local dis_upper = dict_items(d_upper.vval.v_dict)
- local d_lower = lua2typvalt({a='test'})
+ local d_lower = lua2typvalt({ a = 'test' })
local dis_lower = dict_items(d_lower.vval.v_dict)
- local d_kupper_upper = lua2typvalt({A='TEST'})
+ local d_kupper_upper = lua2typvalt({ A = 'TEST' })
local dis_kupper_upper = dict_items(d_kupper_upper.vval.v_dict)
- local d_kupper_lower = lua2typvalt({A='test'})
+ local d_kupper_lower = lua2typvalt({ A = 'test' })
local dis_kupper_lower = dict_items(d_kupper_lower.vval.v_dict)
alloc_log:clear_tmp_allocs()
alloc_log:check({
@@ -2781,24 +3042,31 @@ describe('typval.c', function()
itp('works', function()
local tv = typvalt()
local mem = lib.xmalloc(1)
- tv.vval.v_list = mem -- Should crash when actually accessed
+ tv.vval.v_list = mem -- Should crash when actually accessed
alloc_log:clear()
for _, v in ipairs({
- {lib.VAR_NUMBER, nil},
- {lib.VAR_FLOAT, 'E805: Expected a Number or a String, Float found'},
- {lib.VAR_PARTIAL, 'E703: Expected a Number or a String, Funcref found'},
- {lib.VAR_FUNC, 'E703: Expected a Number or a String, Funcref found'},
- {lib.VAR_LIST, 'E745: Expected a Number or a String, List found'},
- {lib.VAR_DICT, 'E728: Expected a Number or a String, Dictionary found'},
- {lib.VAR_SPECIAL, 'E5300: Expected a Number or a String'},
- {lib.VAR_UNKNOWN, 'E685: Internal error: tv_check_str_or_nr(UNKNOWN)'},
+ { lib.VAR_NUMBER, nil },
+ { lib.VAR_FLOAT, 'E805: Expected a Number or a String, Float found' },
+ { lib.VAR_PARTIAL, 'E703: Expected a Number or a String, Funcref found' },
+ { lib.VAR_FUNC, 'E703: Expected a Number or a String, Funcref found' },
+ { lib.VAR_LIST, 'E745: Expected a Number or a String, List found' },
+ { lib.VAR_DICT, 'E728: Expected a Number or a String, Dictionary found' },
+ { lib.VAR_SPECIAL, 'E5300: Expected a Number or a String' },
+ { lib.VAR_UNKNOWN, 'E685: Internal error: tv_check_str_or_nr(UNKNOWN)' },
}) do
local typ = v[1]
local emsg = v[2]
local ret = true
- if emsg then ret = false end
+ if emsg then
+ ret = false
+ end
tv.v_type = typ
- eq(ret, check_emsg(function() return lib.tv_check_str_or_nr(tv) end, emsg))
+ eq(
+ ret,
+ check_emsg(function()
+ return lib.tv_check_str_or_nr(tv)
+ end, emsg)
+ )
if emsg then
alloc_log:clear()
else
@@ -2811,24 +3079,31 @@ describe('typval.c', function()
itp('works', function()
local tv = typvalt()
local mem = lib.xmalloc(1)
- tv.vval.v_list = mem -- Should crash when actually accessed
+ tv.vval.v_list = mem -- Should crash when actually accessed
alloc_log:clear()
for _, v in ipairs({
- {lib.VAR_NUMBER, nil},
- {lib.VAR_FLOAT, 'E805: Using a Float as a Number'},
- {lib.VAR_PARTIAL, 'E703: Using a Funcref as a Number'},
- {lib.VAR_FUNC, 'E703: Using a Funcref as a Number'},
- {lib.VAR_LIST, 'E745: Using a List as a Number'},
- {lib.VAR_DICT, 'E728: Using a Dictionary as a Number'},
- {lib.VAR_SPECIAL, nil},
- {lib.VAR_UNKNOWN, 'E685: using an invalid value as a Number'},
+ { lib.VAR_NUMBER, nil },
+ { lib.VAR_FLOAT, 'E805: Using a Float as a Number' },
+ { lib.VAR_PARTIAL, 'E703: Using a Funcref as a Number' },
+ { lib.VAR_FUNC, 'E703: Using a Funcref as a Number' },
+ { lib.VAR_LIST, 'E745: Using a List as a Number' },
+ { lib.VAR_DICT, 'E728: Using a Dictionary as a Number' },
+ { lib.VAR_SPECIAL, nil },
+ { lib.VAR_UNKNOWN, 'E685: using an invalid value as a Number' },
}) do
local typ = v[1]
local emsg = v[2]
local ret = true
- if emsg then ret = false end
+ if emsg then
+ ret = false
+ end
tv.v_type = typ
- eq(ret, check_emsg(function() return lib.tv_check_num(tv) end, emsg))
+ eq(
+ ret,
+ check_emsg(function()
+ return lib.tv_check_num(tv)
+ end, emsg)
+ )
if emsg then
alloc_log:clear()
else
@@ -2841,25 +3116,32 @@ describe('typval.c', function()
itp('works', function()
local tv = typvalt()
local mem = lib.xmalloc(1)
- tv.vval.v_list = mem -- Should crash when actually accessed
+ tv.vval.v_list = mem -- Should crash when actually accessed
alloc_log:clear()
for _, v in ipairs({
- {lib.VAR_NUMBER, nil},
- {lib.VAR_FLOAT, nil},
- {lib.VAR_PARTIAL, 'E729: Using a Funcref as a String'},
- {lib.VAR_FUNC, 'E729: Using a Funcref as a String'},
- {lib.VAR_LIST, 'E730: Using a List as a String'},
- {lib.VAR_DICT, 'E731: Using a Dictionary as a String'},
- {lib.VAR_BOOL, nil},
- {lib.VAR_SPECIAL, nil},
- {lib.VAR_UNKNOWN, 'E908: Using an invalid value as a String'},
+ { lib.VAR_NUMBER, nil },
+ { lib.VAR_FLOAT, nil },
+ { lib.VAR_PARTIAL, 'E729: Using a Funcref as a String' },
+ { lib.VAR_FUNC, 'E729: Using a Funcref as a String' },
+ { lib.VAR_LIST, 'E730: Using a List as a String' },
+ { lib.VAR_DICT, 'E731: Using a Dictionary as a String' },
+ { lib.VAR_BOOL, nil },
+ { lib.VAR_SPECIAL, nil },
+ { lib.VAR_UNKNOWN, 'E908: Using an invalid value as a String' },
}) do
local typ = v[1]
local emsg = v[2]
local ret = true
- if emsg then ret = false end
+ if emsg then
+ ret = false
+ end
tv.v_type = typ
- eq(ret, check_emsg(function() return lib.tv_check_str(tv) end, emsg))
+ eq(
+ ret,
+ check_emsg(function()
+ return lib.tv_check_str(tv)
+ end, emsg)
+ )
if emsg then
alloc_log:clear()
else
@@ -2873,24 +3155,29 @@ describe('typval.c', function()
describe('number()', function()
itp('works', function()
for _, v in ipairs({
- {lib.VAR_NUMBER, {v_number=42}, nil, 42},
- {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, 100500},
- {lib.VAR_FLOAT, {v_float=42.53}, 'E805: Using a Float as a Number', 0},
- {lib.VAR_PARTIAL, {v_partial=NULL}, 'E703: Using a Funcref as a Number', 0},
- {lib.VAR_FUNC, {v_string=NULL}, 'E703: Using a Funcref as a Number', 0},
- {lib.VAR_LIST, {v_list=NULL}, 'E745: Using a List as a Number', 0},
- {lib.VAR_DICT, {v_dict=NULL}, 'E728: Using a Dictionary as a Number', 0},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 0},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 1},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 0},
- {lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', 0},
+ { lib.VAR_NUMBER, { v_number = 42 }, nil, 42 },
+ { lib.VAR_STRING, { v_string = to_cstr('100500') }, nil, 100500 },
+ { lib.VAR_FLOAT, { v_float = 42.53 }, 'E805: Using a Float as a Number', 0 },
+ { lib.VAR_PARTIAL, { v_partial = NULL }, 'E703: Using a Funcref as a Number', 0 },
+ { lib.VAR_FUNC, { v_string = NULL }, 'E703: Using a Funcref as a Number', 0 },
+ { lib.VAR_LIST, { v_list = NULL }, 'E745: Using a List as a Number', 0 },
+ { lib.VAR_DICT, { v_dict = NULL }, 'E728: Using a Dictionary as a Number', 0 },
+ { lib.VAR_SPECIAL, { v_special = lib.kSpecialVarNull }, nil, 0 },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarTrue }, nil, 1 },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarFalse }, nil, 0 },
+ { lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', 0 },
}) do
-- Using to_cstr, cannot free with tv_clear
local tv = ffi.gc(typvalt(v[1], v[2]), nil)
alloc_log:check({})
local emsg = v[3]
local ret = v[4]
- eq(ret, check_emsg(function() return lib.tv_get_number(tv) end, emsg))
+ eq(
+ ret,
+ check_emsg(function()
+ return lib.tv_get_number(tv)
+ end, emsg)
+ )
if emsg then
alloc_log:clear()
else
@@ -2902,28 +3189,31 @@ describe('typval.c', function()
describe('number_chk()', function()
itp('works', function()
for _, v in ipairs({
- {lib.VAR_NUMBER, {v_number=42}, nil, 42},
- {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, 100500},
- {lib.VAR_FLOAT, {v_float=42.53}, 'E805: Using a Float as a Number', 0},
- {lib.VAR_PARTIAL, {v_partial=NULL}, 'E703: Using a Funcref as a Number', 0},
- {lib.VAR_FUNC, {v_string=NULL}, 'E703: Using a Funcref as a Number', 0},
- {lib.VAR_LIST, {v_list=NULL}, 'E745: Using a List as a Number', 0},
- {lib.VAR_DICT, {v_dict=NULL}, 'E728: Using a Dictionary as a Number', 0},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 0},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 1},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 0},
- {lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', 0},
+ { lib.VAR_NUMBER, { v_number = 42 }, nil, 42 },
+ { lib.VAR_STRING, { v_string = to_cstr('100500') }, nil, 100500 },
+ { lib.VAR_FLOAT, { v_float = 42.53 }, 'E805: Using a Float as a Number', 0 },
+ { lib.VAR_PARTIAL, { v_partial = NULL }, 'E703: Using a Funcref as a Number', 0 },
+ { lib.VAR_FUNC, { v_string = NULL }, 'E703: Using a Funcref as a Number', 0 },
+ { lib.VAR_LIST, { v_list = NULL }, 'E745: Using a List as a Number', 0 },
+ { lib.VAR_DICT, { v_dict = NULL }, 'E728: Using a Dictionary as a Number', 0 },
+ { lib.VAR_SPECIAL, { v_special = lib.kSpecialVarNull }, nil, 0 },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarTrue }, nil, 1 },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarFalse }, nil, 0 },
+ { lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', 0 },
}) do
-- Using to_cstr, cannot free with tv_clear
local tv = ffi.gc(typvalt(v[1], v[2]), nil)
alloc_log:check({})
local emsg = v[3]
- local ret = {v[4], not not emsg}
- eq(ret, check_emsg(function()
- local err = ffi.new('bool[1]', {false})
- local res = lib.tv_get_number_chk(tv, err)
- return {res, err[0]}
- end, emsg))
+ local ret = { v[4], not not emsg }
+ eq(
+ ret,
+ check_emsg(function()
+ local err = ffi.new('bool[1]', { false })
+ local res = lib.tv_get_number_chk(tv, err)
+ return { res, err[0] }
+ end, emsg)
+ )
if emsg then
alloc_log:clear()
else
@@ -2935,18 +3225,18 @@ describe('typval.c', function()
describe('lnum()', function()
itp('works', function()
for _, v in ipairs({
- {lib.VAR_NUMBER, {v_number=42}, nil, 42},
- {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, 100500},
- {lib.VAR_STRING, {v_string=to_cstr('.')}, nil, 46},
- {lib.VAR_FLOAT, {v_float=42.53}, 'E805: Using a Float as a Number', -1},
- {lib.VAR_PARTIAL, {v_partial=NULL}, 'E703: Using a Funcref as a Number', -1},
- {lib.VAR_FUNC, {v_string=NULL}, 'E703: Using a Funcref as a Number', -1},
- {lib.VAR_LIST, {v_list=NULL}, 'E745: Using a List as a Number', -1},
- {lib.VAR_DICT, {v_dict=NULL}, 'E728: Using a Dictionary as a Number', -1},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 0},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 1},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 0},
- {lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', -1},
+ { lib.VAR_NUMBER, { v_number = 42 }, nil, 42 },
+ { lib.VAR_STRING, { v_string = to_cstr('100500') }, nil, 100500 },
+ { lib.VAR_STRING, { v_string = to_cstr('.') }, nil, 46 },
+ { lib.VAR_FLOAT, { v_float = 42.53 }, 'E805: Using a Float as a Number', -1 },
+ { lib.VAR_PARTIAL, { v_partial = NULL }, 'E703: Using a Funcref as a Number', -1 },
+ { lib.VAR_FUNC, { v_string = NULL }, 'E703: Using a Funcref as a Number', -1 },
+ { lib.VAR_LIST, { v_list = NULL }, 'E745: Using a List as a Number', -1 },
+ { lib.VAR_DICT, { v_dict = NULL }, 'E728: Using a Dictionary as a Number', -1 },
+ { lib.VAR_SPECIAL, { v_special = lib.kSpecialVarNull }, nil, 0 },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarTrue }, nil, 1 },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarFalse }, nil, 0 },
+ { lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_number(UNKNOWN)', -1 },
}) do
lib.curwin.w_cursor.lnum = 46
-- Using to_cstr, cannot free with tv_clear
@@ -2954,7 +3244,12 @@ describe('typval.c', function()
alloc_log:check({})
local emsg = v[3]
local ret = v[4]
- eq(ret, check_emsg(function() return lib.tv_get_lnum(tv) end, emsg))
+ eq(
+ ret,
+ check_emsg(function()
+ return lib.tv_get_lnum(tv)
+ end, emsg)
+ )
if emsg then
alloc_log:clear()
else
@@ -2966,24 +3261,49 @@ describe('typval.c', function()
describe('float()', function()
itp('works', function()
for _, v in ipairs({
- {lib.VAR_NUMBER, {v_number=42}, nil, 42},
- {lib.VAR_STRING, {v_string=to_cstr('100500')}, 'E892: Using a String as a Float', 0},
- {lib.VAR_FLOAT, {v_float=42.53}, nil, 42.53},
- {lib.VAR_PARTIAL, {v_partial=NULL}, 'E891: Using a Funcref as a Float', 0},
- {lib.VAR_FUNC, {v_string=NULL}, 'E891: Using a Funcref as a Float', 0},
- {lib.VAR_LIST, {v_list=NULL}, 'E893: Using a List as a Float', 0},
- {lib.VAR_DICT, {v_dict=NULL}, 'E894: Using a Dictionary as a Float', 0},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, 'E907: Using a special value as a Float', 0},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, 'E362: Using a boolean value as a Float', 0},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, 'E362: Using a boolean value as a Float', 0},
- {lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_float(UNKNOWN)', 0},
+ { lib.VAR_NUMBER, { v_number = 42 }, nil, 42 },
+ {
+ lib.VAR_STRING,
+ { v_string = to_cstr('100500') },
+ 'E892: Using a String as a Float',
+ 0,
+ },
+ { lib.VAR_FLOAT, { v_float = 42.53 }, nil, 42.53 },
+ { lib.VAR_PARTIAL, { v_partial = NULL }, 'E891: Using a Funcref as a Float', 0 },
+ { lib.VAR_FUNC, { v_string = NULL }, 'E891: Using a Funcref as a Float', 0 },
+ { lib.VAR_LIST, { v_list = NULL }, 'E893: Using a List as a Float', 0 },
+ { lib.VAR_DICT, { v_dict = NULL }, 'E894: Using a Dictionary as a Float', 0 },
+ {
+ lib.VAR_SPECIAL,
+ { v_special = lib.kSpecialVarNull },
+ 'E907: Using a special value as a Float',
+ 0,
+ },
+ {
+ lib.VAR_BOOL,
+ { v_bool = lib.kBoolVarTrue },
+ 'E362: Using a boolean value as a Float',
+ 0,
+ },
+ {
+ lib.VAR_BOOL,
+ { v_bool = lib.kBoolVarFalse },
+ 'E362: Using a boolean value as a Float',
+ 0,
+ },
+ { lib.VAR_UNKNOWN, nil, 'E685: Internal error: tv_get_float(UNKNOWN)', 0 },
}) do
-- Using to_cstr, cannot free with tv_clear
local tv = ffi.gc(typvalt(v[1], v[2]), nil)
alloc_log:check({})
local emsg = v[3]
local ret = v[4]
- eq(ret, check_emsg(function() return lib.tv_get_float(tv) end, emsg))
+ eq(
+ ret,
+ check_emsg(function()
+ return lib.tv_get_float(tv)
+ end, emsg)
+ )
if emsg then
alloc_log:clear()
else
@@ -3001,24 +3321,31 @@ describe('typval.c', function()
alloc_log:check({})
local emsg = v[3]
local ret = v[4]
- eq(ret, check_emsg(function()
- local res, buf = fn(tv)
- if tv.v_type == lib.VAR_NUMBER or tv.v_type == lib.VAR_FLOAT
- or tv.v_type == lib.VAR_SPECIAL or tv.v_type == lib.VAR_BOOL then
- eq(buf, res)
- else
- neq(buf, res)
- end
- if res ~= nil then
- return ffi.string(res)
- else
- return nil
- end
- end, emsg))
+ eq(
+ ret,
+ check_emsg(function()
+ local res, buf = fn(tv)
+ if
+ tv.v_type == lib.VAR_NUMBER
+ or tv.v_type == lib.VAR_FLOAT
+ or tv.v_type == lib.VAR_SPECIAL
+ or tv.v_type == lib.VAR_BOOL
+ then
+ eq(buf, res)
+ else
+ neq(buf, res)
+ end
+ if res ~= nil then
+ return ffi.string(res)
+ else
+ return nil
+ end
+ end, emsg)
+ )
if emsg then
alloc_log:clear()
elseif tv.v_type == lib.VAR_FLOAT then
- alloc_log:check({a.freed(alloc_log.null), a.freed(alloc_log.null)})
+ alloc_log:check({ a.freed(alloc_log.null), a.freed(alloc_log.null) })
else
alloc_log:check({})
end
@@ -3030,17 +3357,17 @@ describe('typval.c', function()
local buf_chk = lib.tv_get_string_chk(lua2typvalt(int(1)))
neq(buf, buf_chk)
test_string_fn({
- {lib.VAR_NUMBER, {v_number=42}, nil, '42'},
- {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, '100500'},
- {lib.VAR_FLOAT, {v_float=42.53}, nil, '42.53'},
- {lib.VAR_PARTIAL, {v_partial=NULL}, 'E729: Using a Funcref as a String', ''},
- {lib.VAR_FUNC, {v_string=NULL}, 'E729: Using a Funcref as a String', ''},
- {lib.VAR_LIST, {v_list=NULL}, 'E730: Using a List as a String', ''},
- {lib.VAR_DICT, {v_dict=NULL}, 'E731: Using a Dictionary as a String', ''},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'v:null'},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 'v:true'},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 'v:false'},
- {lib.VAR_UNKNOWN, nil, 'E908: Using an invalid value as a String', ''},
+ { lib.VAR_NUMBER, { v_number = 42 }, nil, '42' },
+ { lib.VAR_STRING, { v_string = to_cstr('100500') }, nil, '100500' },
+ { lib.VAR_FLOAT, { v_float = 42.53 }, nil, '42.53' },
+ { lib.VAR_PARTIAL, { v_partial = NULL }, 'E729: Using a Funcref as a String', '' },
+ { lib.VAR_FUNC, { v_string = NULL }, 'E729: Using a Funcref as a String', '' },
+ { lib.VAR_LIST, { v_list = NULL }, 'E730: Using a List as a String', '' },
+ { lib.VAR_DICT, { v_dict = NULL }, 'E731: Using a Dictionary as a String', '' },
+ { lib.VAR_SPECIAL, { v_special = lib.kSpecialVarNull }, nil, 'v:null' },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarTrue }, nil, 'v:true' },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarFalse }, nil, 'v:false' },
+ { lib.VAR_UNKNOWN, nil, 'E908: Using an invalid value as a String', '' },
}, function(tv)
return lib.tv_get_string(tv), buf
end)
@@ -3050,17 +3377,17 @@ describe('typval.c', function()
itp('works', function()
local buf = lib.tv_get_string_chk(lua2typvalt(int(1)))
test_string_fn({
- {lib.VAR_NUMBER, {v_number=42}, nil, '42'},
- {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, '100500'},
- {lib.VAR_FLOAT, {v_float=42.53}, nil, '42.53'},
- {lib.VAR_PARTIAL, {v_partial=NULL}, 'E729: Using a Funcref as a String', nil},
- {lib.VAR_FUNC, {v_string=NULL}, 'E729: Using a Funcref as a String', nil},
- {lib.VAR_LIST, {v_list=NULL}, 'E730: Using a List as a String', nil},
- {lib.VAR_DICT, {v_dict=NULL}, 'E731: Using a Dictionary as a String', nil},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'v:null'},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 'v:true'},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 'v:false'},
- {lib.VAR_UNKNOWN, nil, 'E908: Using an invalid value as a String', nil},
+ { lib.VAR_NUMBER, { v_number = 42 }, nil, '42' },
+ { lib.VAR_STRING, { v_string = to_cstr('100500') }, nil, '100500' },
+ { lib.VAR_FLOAT, { v_float = 42.53 }, nil, '42.53' },
+ { lib.VAR_PARTIAL, { v_partial = NULL }, 'E729: Using a Funcref as a String', nil },
+ { lib.VAR_FUNC, { v_string = NULL }, 'E729: Using a Funcref as a String', nil },
+ { lib.VAR_LIST, { v_list = NULL }, 'E730: Using a List as a String', nil },
+ { lib.VAR_DICT, { v_dict = NULL }, 'E731: Using a Dictionary as a String', nil },
+ { lib.VAR_SPECIAL, { v_special = lib.kSpecialVarNull }, nil, 'v:null' },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarTrue }, nil, 'v:true' },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarFalse }, nil, 'v:false' },
+ { lib.VAR_UNKNOWN, nil, 'E908: Using an invalid value as a String', nil },
}, function(tv)
return lib.tv_get_string_chk(tv), buf
end)
@@ -3069,19 +3396,19 @@ describe('typval.c', function()
describe('string_buf()', function()
itp('works', function()
test_string_fn({
- {lib.VAR_NUMBER, {v_number=42}, nil, '42'},
- {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, '100500'},
- {lib.VAR_FLOAT, {v_float=42.53}, nil, '42.53'},
- {lib.VAR_PARTIAL, {v_partial=NULL}, 'E729: Using a Funcref as a String', ''},
- {lib.VAR_FUNC, {v_string=NULL}, 'E729: Using a Funcref as a String', ''},
- {lib.VAR_LIST, {v_list=NULL}, 'E730: Using a List as a String', ''},
- {lib.VAR_DICT, {v_dict=NULL}, 'E731: Using a Dictionary as a String', ''},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'v:null'},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 'v:true'},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 'v:false'},
- {lib.VAR_UNKNOWN, nil, 'E908: Using an invalid value as a String', ''},
+ { lib.VAR_NUMBER, { v_number = 42 }, nil, '42' },
+ { lib.VAR_STRING, { v_string = to_cstr('100500') }, nil, '100500' },
+ { lib.VAR_FLOAT, { v_float = 42.53 }, nil, '42.53' },
+ { lib.VAR_PARTIAL, { v_partial = NULL }, 'E729: Using a Funcref as a String', '' },
+ { lib.VAR_FUNC, { v_string = NULL }, 'E729: Using a Funcref as a String', '' },
+ { lib.VAR_LIST, { v_list = NULL }, 'E730: Using a List as a String', '' },
+ { lib.VAR_DICT, { v_dict = NULL }, 'E731: Using a Dictionary as a String', '' },
+ { lib.VAR_SPECIAL, { v_special = lib.kSpecialVarNull }, nil, 'v:null' },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarTrue }, nil, 'v:true' },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarFalse }, nil, 'v:false' },
+ { lib.VAR_UNKNOWN, nil, 'E908: Using an invalid value as a String', '' },
}, function(tv)
- local buf = ffi.new('char[?]', lib.NUMBUFLEN, {0})
+ local buf = ffi.new('char[?]', lib.NUMBUFLEN, { 0 })
return lib.tv_get_string_buf(tv, buf), buf
end)
end)
@@ -3089,19 +3416,19 @@ describe('typval.c', function()
describe('string_buf_chk()', function()
itp('works', function()
test_string_fn({
- {lib.VAR_NUMBER, {v_number=42}, nil, '42'},
- {lib.VAR_STRING, {v_string=to_cstr('100500')}, nil, '100500'},
- {lib.VAR_FLOAT, {v_float=42.53}, nil, '42.53'},
- {lib.VAR_PARTIAL, {v_partial=NULL}, 'E729: Using a Funcref as a String', nil},
- {lib.VAR_FUNC, {v_string=NULL}, 'E729: Using a Funcref as a String', nil},
- {lib.VAR_LIST, {v_list=NULL}, 'E730: Using a List as a String', nil},
- {lib.VAR_DICT, {v_dict=NULL}, 'E731: Using a Dictionary as a String', nil},
- {lib.VAR_SPECIAL, {v_special=lib.kSpecialVarNull}, nil, 'v:null'},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarTrue}, nil, 'v:true'},
- {lib.VAR_BOOL, {v_bool=lib.kBoolVarFalse}, nil, 'v:false'},
- {lib.VAR_UNKNOWN, nil, 'E908: Using an invalid value as a String', nil},
+ { lib.VAR_NUMBER, { v_number = 42 }, nil, '42' },
+ { lib.VAR_STRING, { v_string = to_cstr('100500') }, nil, '100500' },
+ { lib.VAR_FLOAT, { v_float = 42.53 }, nil, '42.53' },
+ { lib.VAR_PARTIAL, { v_partial = NULL }, 'E729: Using a Funcref as a String', nil },
+ { lib.VAR_FUNC, { v_string = NULL }, 'E729: Using a Funcref as a String', nil },
+ { lib.VAR_LIST, { v_list = NULL }, 'E730: Using a List as a String', nil },
+ { lib.VAR_DICT, { v_dict = NULL }, 'E731: Using a Dictionary as a String', nil },
+ { lib.VAR_SPECIAL, { v_special = lib.kSpecialVarNull }, nil, 'v:null' },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarTrue }, nil, 'v:true' },
+ { lib.VAR_BOOL, { v_bool = lib.kBoolVarFalse }, nil, 'v:false' },
+ { lib.VAR_UNKNOWN, nil, 'E908: Using an invalid value as a String', nil },
}, function(tv)
- local buf = ffi.new('char[?]', lib.NUMBUFLEN, {0})
+ local buf = ffi.new('char[?]', lib.NUMBUFLEN, { 0 })
return lib.tv_get_string_buf_chk(tv, buf), buf
end)
end)
diff --git a/test/unit/fileio_spec.lua b/test/unit/fileio_spec.lua
index 066d013b19..1284f84222 100644
--- a/test/unit/fileio_spec.lua
+++ b/test/unit/fileio_spec.lua
@@ -1,24 +1,23 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
--{:cimport, :internalize, :eq, :neq, :ffi, :lib, :cstr, :to_cstr} = require 'test.unit.helpers'
-local eq = helpers.eq
-local ffi = helpers.ffi
+local eq = helpers.eq
+local ffi = helpers.ffi
local to_cstr = helpers.to_cstr
-local NULL = helpers.NULL
+local NULL = helpers.NULL
-local fileio = helpers.cimport("./src/nvim/fileio.h")
+local fileio = helpers.cimport('./src/nvim/fileio.h')
describe('file_pat functions', function()
describe('file_pat_to_reg_pat', function()
-
local file_pat_to_reg_pat = function(pat)
local res = fileio.file_pat_to_reg_pat(to_cstr(pat), NULL, NULL, 0)
return ffi.string(res)
end
itp('returns ^path$ regex for literal path input', function()
- eq( '^path$', file_pat_to_reg_pat('path'))
+ eq('^path$', file_pat_to_reg_pat('path'))
end)
itp('does not prepend ^ when there is a starting glob (*)', function()
@@ -34,13 +33,15 @@ describe('file_pat functions', function()
end)
itp('replaces the bash any character (?) with the regex any character (.)', function()
- eq('^foo.bar$', file_pat_to_reg_pat('foo?bar'))
+ eq('^foo.bar$', file_pat_to_reg_pat('foo?bar'))
end)
- itp('replaces a glob (*) in the middle of a path with regex multiple any character (.*)',
- function()
- eq('^foo.*bar$', file_pat_to_reg_pat('foo*bar'))
- end)
+ itp(
+ 'replaces a glob (*) in the middle of a path with regex multiple any character (.*)',
+ function()
+ eq('^foo.*bar$', file_pat_to_reg_pat('foo*bar'))
+ end
+ )
itp([[unescapes \? to ?]], function()
eq('^foo?bar$', file_pat_to_reg_pat([[foo\?bar]]))
diff --git a/test/unit/fixtures/multiqueue.c b/test/unit/fixtures/multiqueue.c
index 3a5ddab4b8..149daca893 100644
--- a/test/unit/fixtures/multiqueue.c
+++ b/test/unit/fixtures/multiqueue.c
@@ -6,7 +6,7 @@
void ut_multiqueue_put(MultiQueue *self, const char *str)
{
- multiqueue_put(self, NULL, 1, str);
+ multiqueue_put(self, NULL, (void *)str);
}
const char *ut_multiqueue_get(MultiQueue *self)
diff --git a/test/unit/formatc.lua b/test/unit/formatc.lua
index c94f0d88f7..ce9cb81f4a 100644
--- a/test/unit/formatc.lua
+++ b/test/unit/formatc.lua
@@ -24,103 +24,145 @@ SOFTWARE. --]]
-- work.
-- see: http://lua-users.org/wiki/LpegRecipes
-local lpeg = require "lpeg"
+local lpeg = require 'lpeg'
local C, P, R, S, V = lpeg.C, lpeg.P, lpeg.R, lpeg.S, lpeg.V
local Carg, Cc, Cp, Ct = lpeg.Carg, lpeg.Cc, lpeg.Cp, lpeg.Ct
-local tokens = P { "tokens";
+local tokens = P {
+ 'tokens',
-- Comment of form /* ... */
- comment = Ct(P"/*" * C((V"newline" + (1 - P"*/"))^0) * P"*/" * Cc"comment"),
+ comment = Ct(P '/*' * C((V 'newline' + (1 - P '*/')) ^ 0) * P '*/' * Cc 'comment'),
-- Single line comment
- line_comment = Ct(P"//" * C((1 - V"newline")^0) * Cc"comment_line"),
+ line_comment = Ct(P '//' * C((1 - V 'newline') ^ 0) * Cc 'comment_line'),
-- Single platform independent line break which increments line number
- newline = (P"\r\n" + P"\n\r" + S"\r\n") * (Cp() * Carg(1)) / function(pos, state)
+ newline = (P '\r\n' + P '\n\r' + S '\r\n') * (Cp() * Carg(1)) / function(pos, state)
state.line = state.line + 1
state.line_start = pos
end,
-- Line continuation
- line_extend = Ct(C(P[[\]] * V"newline") * Cc"line_extend"),
+ line_extend = Ct(C(P [[\]] * V 'newline') * Cc 'line_extend'),
-- Whitespace of any length (includes newlines)
- whitespace = Ct(C((S" \t" + V"newline")^1) * Cc"whitespace"),
+ whitespace = Ct(C((S ' \t' + V 'newline') ^ 1) * Cc 'whitespace'),
-- Special form of #include with filename followed in angled brackets (matches 3 tokens)
- include = Ct(C(P"#include") * Cc"preprocessor") *
- Ct(C(S" \t"^1) * Cc"whitespace") *
- Ct(C(P"<" * (1 - P">")^1 * P">") * Cc"string"),
+ include = Ct(C(P '#include') * Cc 'preprocessor') * Ct(C(S ' \t' ^ 1) * Cc 'whitespace') * Ct(
+ C(P '<' * (1 - P '>') ^ 1 * P '>') * Cc 'string'
+ ),
-- Preprocessor instruction
- preprocessor = V"include" +
- Ct(C(P"#" * P" "^0 * ( P"define" + P"elif" + P"else" + P"endif" + P"#" +
- P"error" + P"ifdef" + P"ifndef" + P"if" + P"import" +
- P"include" + P"line" + P"pragma" + P"undef" + P"using" +
- P"pragma"
- ) * #S" \r\n\t") * Cc"preprocessor"),
+ preprocessor = V 'include'
+ + Ct(
+ C(
+ P '#'
+ * P ' ' ^ 0
+ * (P 'define' + P 'elif' + P 'else' + P 'endif' + P '#' + P 'error' + P 'ifdef' + P 'ifndef' + P 'if' + P 'import' + P 'include' + P 'line' + P 'pragma' + P 'undef' + P 'using' + P 'pragma')
+ * #S ' \r\n\t'
+ ) * Cc 'preprocessor'
+ ),
-- Identifier of form [a-zA-Z_][a-zA-Z0-9_]*
- identifier = Ct(C(R("az","AZ","__") * R("09","az","AZ","__")^0) * Cc"identifier"),
+ identifier = Ct(C(R('az', 'AZ', '__') * R('09', 'az', 'AZ', '__') ^ 0) * Cc 'identifier'),
-- Single character in a string
- sstring_char = R("\001&","([","]\255") + (P"\\" * S[[ntvbrfa\?'"0x]]),
- dstring_char = R("\001!","#[","]\255") + (P"\\" * S[[ntvbrfa\?'"0x]]),
+ sstring_char = R('\001&', '([', ']\255') + (P '\\' * S [[ntvbrfa\?'"0x]]),
+ dstring_char = R('\001!', '#[', ']\255') + (P '\\' * S [[ntvbrfa\?'"0x]]),
-- String literal
- string = Ct(C(P"'" * (V"sstring_char" + P'"')^0 * P"'" +
- P'"' * (V"dstring_char" + P"'")^0 * P'"') * Cc"string"),
+ string = Ct(
+ C(
+ P "'" * (V 'sstring_char' + P '"') ^ 0 * P "'"
+ + P '"' * (V 'dstring_char' + P "'") ^ 0 * P '"'
+ ) * Cc 'string'
+ ),
-- Operator
- operator = Ct(C(P">>=" + P"<<=" + P"..." +
- P"::" + P"<<" + P">>" + P"<=" + P">=" + P"==" + P"!=" +
- P"||" + P"&&" + P"++" + P"--" + P"->" + P"+=" + P"-=" +
- P"*=" + P"/=" + P"|=" + P"&=" + P"^=" + S"+-*/=<>%^|&.?:!~,") * Cc"operator"),
+ operator = Ct(
+ C(
+ P '>>='
+ + P '<<='
+ + P '...'
+ + P '::'
+ + P '<<'
+ + P '>>'
+ + P '<='
+ + P '>='
+ + P '=='
+ + P '!='
+ + P '||'
+ + P '&&'
+ + P '++'
+ + P '--'
+ + P '->'
+ + P '+='
+ + P '-='
+ + P '*='
+ + P '/='
+ + P '|='
+ + P '&='
+ + P '^='
+ + S '+-*/=<>%^|&.?:!~,'
+ ) * Cc 'operator'
+ ),
-- Misc. char (token type is the character itself)
- char = Ct(C(S"[]{}();") / function(x) return x, x end),
+ char = Ct(C(S '[]{}();') / function(x)
+ return x, x
+ end),
-- Hex, octal or decimal number
- int = Ct(C((P"0x" * R("09","af","AF")^1) + (P"0" * R"07"^0) + R"09"^1) * Cc"integer"),
+ int = Ct(
+ C((P '0x' * R('09', 'af', 'AF') ^ 1) + (P '0' * R '07' ^ 0) + R '09' ^ 1) * Cc 'integer'
+ ),
-- Floating point number
- f_exponent = S"eE" + S"+-"^-1 * R"09"^1,
- f_terminator = S"fFlL",
- float = Ct(C(
- R"09"^1 * V"f_exponent" * V"f_terminator"^-1 +
- R"09"^0 * P"." * R"09"^1 * V"f_exponent"^-1 * V"f_terminator"^-1 +
- R"09"^1 * P"." * R"09"^0 * V"f_exponent"^-1 * V"f_terminator"^-1
- ) * Cc"float"),
+ f_exponent = S 'eE' + S '+-' ^ -1 * R '09' ^ 1,
+ f_terminator = S 'fFlL',
+ float = Ct(
+ C(
+ R '09' ^ 1 * V 'f_exponent' * V 'f_terminator' ^ -1
+ + R '09' ^ 0 * P '.' * R '09' ^ 1 * V 'f_exponent' ^ -1 * V 'f_terminator' ^ -1
+ + R '09' ^ 1 * P '.' * R '09' ^ 0 * V 'f_exponent' ^ -1 * V 'f_terminator' ^ -1
+ ) * Cc 'float'
+ ),
-- Any token
- token = V"comment" +
- V"line_comment" +
- V"identifier" +
- V"whitespace" +
- V"line_extend" +
- V"preprocessor" +
- V"string" +
- V"char" +
- V"operator" +
- V"float" +
- V"int",
+ token = V 'comment'
+ + V 'line_comment'
+ + V 'identifier'
+ + V 'whitespace'
+ + V 'line_extend'
+ + V 'preprocessor'
+ + V 'string'
+ + V 'char'
+ + V 'operator'
+ + V 'float'
+ + V 'int',
-- Error for when nothing else matches
error = (Cp() * C(P(1) ^ -8) * Carg(1)) / function(pos, where, state)
- error(("Tokenising error on line %i, position %i, near '%s'")
- :format(state.line, pos - state.line_start + 1, where))
+ error(
+ ("Tokenising error on line %i, position %i, near '%s'"):format(
+ state.line,
+ pos - state.line_start + 1,
+ where
+ )
+ )
end,
-- Match end of input or throw error
- finish = -P(1) + V"error",
+ finish = -P(1) + V 'error',
-- Match stream of tokens into a table
- tokens = Ct(V"token" ^ 0) * V"finish",
+ tokens = Ct(V 'token' ^ 0) * V 'finish',
}
local function TokeniseC(str)
- return tokens:match(str, 1, {line = 1, line_start = 1})
+ return tokens:match(str, 1, { line = 1, line_start = 1 })
end
local function set(t)
@@ -131,16 +173,43 @@ local function set(t)
return s
end
-local C_keywords = set { -- luacheck: ignore
- "break", "case", "char", "const", "continue", "default", "do", "double",
- "else", "enum", "extern", "float", "for", "goto", "if", "int", "long",
- "register", "return", "short", "signed", "sizeof", "static", "struct",
- "switch", "typedef", "union", "unsigned", "void", "volatile", "while",
+local C_keywords = set { -- luacheck: ignore
+ 'break',
+ 'case',
+ 'char',
+ 'const',
+ 'continue',
+ 'default',
+ 'do',
+ 'double',
+ 'else',
+ 'enum',
+ 'extern',
+ 'float',
+ 'for',
+ 'goto',
+ 'if',
+ 'int',
+ 'long',
+ 'register',
+ 'return',
+ 'short',
+ 'signed',
+ 'sizeof',
+ 'static',
+ 'struct',
+ 'switch',
+ 'typedef',
+ 'union',
+ 'unsigned',
+ 'void',
+ 'volatile',
+ 'while',
}
-- Very primitive C formatter that tries to put "things" inside braces on one
-- line. This is a step done after preprocessing the C source to ensure that
--- the duplicate line detecter can more reliably pick out identical declarations.
+-- the duplicate line detector can more reliably pick out identical declarations.
--
-- an example:
-- struct mystruct
@@ -174,7 +243,7 @@ local function formatc(str)
-- if we're not inside a block, we're at the basic statement level,
-- and ';' indicates we're at the end of a statement, so we put end
-- it with a newline.
- token[1] = token[1] .. "\n"
+ token[1] = token[1] .. '\n'
end_at_brace = false
end
elseif typ == 'identifier' then
@@ -194,20 +263,20 @@ local function formatc(str)
-- if we're not inside a block, we're at the basic statement level,
-- and ';' indicates we're at the end of a statement, so we put end
-- it with a newline.
- token[1] = ";\n"
+ token[1] = ';\n'
end
elseif typ == 'whitespace' then
-- replace all whitespace by one space
- local repl = " "
+ local repl = ' '
-- except when allow_on_nl is true and there's a newline in the whitespace
- if string.find(token[1], "[\r\n]+") and allow_one_nl == true then
+ if string.find(token[1], '[\r\n]+') and allow_one_nl == true then
-- in that case we replace all whitespace by one newline
- repl = "\n"
+ repl = '\n'
allow_one_nl = false
end
- token[1] = string.gsub(token[1], "%s+", repl)
+ token[1] = string.gsub(token[1], '%s+', repl)
end
result[#result + 1] = token[1]
end
@@ -216,8 +285,8 @@ local function formatc(str)
end
-- standalone operation (very handy for debugging)
-local function standalone(...) -- luacheck: ignore
- local Preprocess = require("preprocess")
+local function standalone(...) -- luacheck: ignore
+ local Preprocess = require('preprocess')
Preprocess.add_to_include_path('./../../src')
Preprocess.add_to_include_path('./../../build/include')
Preprocess.add_to_include_path('./../../.deps/usr/include')
@@ -226,9 +295,9 @@ local function standalone(...) -- luacheck: ignore
local formatted
if #arg == 2 and arg[2] == 'no' then
- formatted = raw
+ formatted = raw
else
- formatted = formatc(raw)
+ formatted = formatc(raw)
end
print(formatted)
diff --git a/test/unit/garray_spec.lua b/test/unit/garray_spec.lua
index 5d41dd39ec..0f947c42b8 100644
--- a/test/unit/garray_spec.lua
+++ b/test/unit/garray_spec.lua
@@ -1,4 +1,4 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local cimport = helpers.cimport
@@ -47,7 +47,7 @@ local ga_size = function(garr)
return ga_len(garr) * ga_itemsize(garr)
end
-local ga_maxsize = function(garr) -- luacheck: ignore
+local ga_maxsize = function(garr) -- luacheck: ignore
return ga_maxlen(garr) * ga_itemsize(garr)
end
@@ -157,7 +157,9 @@ local ga_append_ints = function(garr, ...)
end
-- enhanced constructors
-local garray_ctype = function(...) return ffi.typeof('garray_T[1]')(...) end
+local garray_ctype = function(...)
+ return ffi.typeof('garray_T[1]')(...)
+end
local new_garray = function()
local garr = garray_ctype()
return ffi.gc(garr, ga_clear)
@@ -165,7 +167,7 @@ end
local new_string_garray = function()
local garr = garray_ctype()
- ga_init(garr, ffi.sizeof("unsigned char *"), 1)
+ ga_init(garr, ffi.sizeof('unsigned char *'), 1)
return ffi.gc(garr, ga_clear_strings)
end
@@ -182,7 +184,6 @@ local ga_scramble = function(garr)
end
describe('garray', function()
-
describe('ga_init', function()
itp('initializes the values of the garray', function()
local garr = new_garray()
@@ -199,9 +200,9 @@ describe('garray', function()
local function new_and_grow(itemsize_, growsize_, req)
local garr = new_garray()
ga_init(garr, itemsize_, growsize_)
- eq(0, ga_size(garr)) -- should be 0 at first
- eq(NULL, ga_data(garr)) -- should be NULL
- ga_grow(garr, req) -- add space for `req` items
+ eq(0, ga_size(garr)) -- should be 0 at first
+ eq(NULL, ga_data(garr)) -- should be NULL
+ ga_grow(garr, req) -- add space for `req` items
return garr
end
@@ -210,8 +211,8 @@ describe('garray', function()
growsize = 4
local grow_by = growsize - 1
local garr = new_and_grow(itemsize, growsize, grow_by)
- neq(NULL, ga_data(garr)) -- data should be a ptr to memory
- eq(growsize, ga_maxlen(garr)) -- we requested LESS than growsize, so...
+ neq(NULL, ga_data(garr)) -- data should be a ptr to memory
+ eq(growsize, ga_maxlen(garr)) -- we requested LESS than growsize, so...
end)
itp('grows by num items if num > growsize', function()
@@ -219,8 +220,8 @@ describe('garray', function()
growsize = 4
local grow_by = growsize + 1
local garr = new_and_grow(itemsize, growsize, grow_by)
- neq(NULL, ga_data(garr)) -- data should be a ptr to memory
- eq(grow_by, ga_maxlen(garr)) -- we requested MORE than growsize, so...
+ neq(NULL, ga_data(garr)) -- data should be a ptr to memory
+ eq(grow_by, ga_maxlen(garr)) -- we requested MORE than growsize, so...
end)
itp('does not grow when nothing is requested', function()
@@ -252,7 +253,7 @@ describe('garray', function()
-- this is the actual ga_append, the others are just emulated lua
-- versions
local garr = new_garray()
- ga_init(garr, ffi.sizeof("uint8_t"), 1)
+ ga_init(garr, ffi.sizeof('uint8_t'), 1)
ga_append(garr, 'h')
ga_append(garr, 'e')
ga_append(garr, 'l')
@@ -265,13 +266,13 @@ describe('garray', function()
itp('can append integers', function()
local garr = new_garray()
- ga_init(garr, ffi.sizeof("int"), 1)
+ ga_init(garr, ffi.sizeof('int'), 1)
local input = {
-20,
94,
867615,
90927,
- 86
+ 86,
}
ga_append_ints(garr, unpack(input))
local ints = ga_data_as_ints(garr)
@@ -283,11 +284,11 @@ describe('garray', function()
itp('can append strings to a growing array of strings', function()
local garr = new_string_garray()
local input = {
- "some",
- "str",
- "\r\n\râ—â—â—â—â—â—,,,",
- "hmm",
- "got it"
+ 'some',
+ 'str',
+ '\r\n\râ—â—â—â—â—â—,,,',
+ 'hmm',
+ 'got it',
}
ga_append_strings(garr, unpack(input))
-- check that we can get the same strings out of the array
@@ -301,8 +302,8 @@ describe('garray', function()
describe('ga_concat', function()
itp('concatenates the parameter to the growing byte array', function()
local garr = new_garray()
- ga_init(garr, ffi.sizeof("char"), 1)
- local str = "ohwellâ—â—"
+ ga_init(garr, ffi.sizeof('char'), 1)
+ local str = 'ohwellâ—â—'
local loop = 5
for _ = 1, loop do
ga_concat(garr, str)
@@ -331,21 +332,21 @@ describe('garray', function()
describe('ga_concat_strings', function()
itp('returns an empty string when concatenating an empty array', function()
- test_concat_fn({ }, ga_concat_strings)
+ test_concat_fn({}, ga_concat_strings)
end)
itp('can concatenate a non-empty array', function()
test_concat_fn({
'oh',
'my',
- 'neovim'
+ 'neovim',
}, ga_concat_strings)
end)
end)
describe('ga_concat_strings_sep', function()
itp('returns an empty string when concatenating an empty array', function()
- test_concat_fn({ }, ga_concat_strings_sep, '---')
+ test_concat_fn({}, ga_concat_strings_sep, '---')
end)
itp('can concatenate a non-empty array', function()
@@ -353,7 +354,7 @@ describe('garray', function()
test_concat_fn({
'oh',
'my',
- 'neovim'
+ 'neovim',
}, ga_concat_strings_sep, sep)
end)
end)
@@ -370,13 +371,13 @@ describe('garray', function()
'bbb',
'ccc',
'ccc',
- 'dddâ—â—'
+ 'dddâ—â—',
}
local sorted_dedup_input = {
'aaa',
'bbb',
'ccc',
- 'dddâ—â—'
+ 'dddâ—â—',
}
ga_append_strings(garr, unpack(input))
ga_remove_duplicate_strings(garr)
diff --git a/test/unit/helpers.lua b/test/unit/helpers.lua
index 8d581dac49..ab4a59cfdb 100644
--- a/test/unit/helpers.lua
+++ b/test/unit/helpers.lua
@@ -2,24 +2,24 @@ local ffi = require('ffi')
local formatc = require('test.unit.formatc')
local Set = require('test.unit.set')
local Preprocess = require('test.unit.preprocess')
-local Paths = require('test.cmakeconfig.paths')
local global_helpers = require('test.helpers')
+local paths = global_helpers.paths
local assert = require('luassert')
local say = require('say')
local check_cores = global_helpers.check_cores
local dedent = global_helpers.dedent
local neq = global_helpers.neq
-local map = global_helpers.tbl_map
+local map = vim.tbl_map
local eq = global_helpers.eq
-local trim = global_helpers.trim
+local trim = vim.trim
-- add some standard header locations
-for _, p in ipairs(Paths.include_paths) do
+for _, p in ipairs(paths.include_paths) do
Preprocess.add_to_include_path(p)
end
-local child_pid = nil --- @type integer
+local child_pid = nil --- @type integer?
--- @generic F: function
--- @param func F
--- @return F
@@ -49,7 +49,7 @@ local function child_call(func, ret)
return function(...)
local child_calls = child_calls_mod or child_calls_init
if child_pid ~= 0 then
- child_calls[#child_calls + 1] = {func=func, args={...}}
+ child_calls[#child_calls + 1] = { func = func, args = { ... } }
return ret
else
return func(...)
@@ -62,7 +62,7 @@ end
--- @param func function
local function child_call_once(func, ...)
if child_pid ~= 0 then
- child_calls_mod_once[#child_calls_mod_once + 1] = { func = func, args = {...} }
+ child_calls_mod_once[#child_calls_mod_once + 1] = { func = func, args = { ... } }
else
func(...)
end
@@ -75,7 +75,7 @@ local child_cleanups_mod_once = nil --- @type ChildCall[]?
local function child_cleanup_once(func, ...)
local child_cleanups = child_cleanups_mod_once
if child_pid ~= 0 then
- child_cleanups[#child_cleanups + 1] = {func=func, args={...}}
+ child_cleanups[#child_cleanups + 1] = { func = func, args = { ... } }
else
func(...)
end
@@ -133,25 +133,28 @@ local pragma_pack_id = 1
local function filter_complex_blocks(body)
local result = {} --- @type string[]
- for line in body:gmatch("[^\r\n]+") do
- if not (string.find(line, "(^)", 1, true) ~= nil
- or string.find(line, "_ISwupper", 1, true)
- or string.find(line, "_Float")
- or string.find(line, "__s128")
- or string.find(line, "__u128")
- or string.find(line, "msgpack_zone_push_finalizer")
- or string.find(line, "msgpack_unpacker_reserve_buffer")
- or string.find(line, "value_init_")
- or string.find(line, "UUID_NULL") -- static const uuid_t UUID_NULL = {...}
- or string.find(line, "inline _Bool")) then
+ for line in body:gmatch('[^\r\n]+') do
+ if
+ not (
+ string.find(line, '(^)', 1, true) ~= nil
+ or string.find(line, '_ISwupper', 1, true)
+ or string.find(line, '_Float')
+ or string.find(line, '__s128')
+ or string.find(line, '__u128')
+ or string.find(line, 'msgpack_zone_push_finalizer')
+ or string.find(line, 'msgpack_unpacker_reserve_buffer')
+ or string.find(line, 'value_init_')
+ or string.find(line, 'UUID_NULL') -- static const uuid_t UUID_NULL = {...}
+ or string.find(line, 'inline _Bool')
+ )
+ then
result[#result + 1] = line
end
end
- return table.concat(result, "\n")
+ return table.concat(result, '\n')
end
-
local cdef = ffi.cdef
local cimportstr
@@ -184,9 +187,8 @@ local function cimport(...)
previous_defines = previous_defines_init
cdefs = cdefs_init
end
- for _, path in ipairs({...}) do
- if not (path:sub(1, 1) == '/' or path:sub(1, 1) == '.'
- or path:sub(2, 2) == ':') then
+ for _, path in ipairs({ ... }) do
+ if not (path:sub(1, 1) == '/' or path:sub(1, 1) == '.' or path:sub(2, 2) == ':') then
path = './' .. path
end
if not preprocess_cache[path] then
@@ -205,15 +207,15 @@ local function cimport(...)
body = filter_complex_blocks(body)
-- add the formatted lines to a set
local new_cdefs = Set:new()
- for line in body:gmatch("[^\r\n]+") do
+ for line in body:gmatch('[^\r\n]+') do
line = trim(line)
-- give each #pragma pack an unique id, so that they don't get removed
-- if they are inserted into the set
-- (they are needed in the right order with the struct definitions,
- -- otherwise luajit has wrong memory layouts for the sturcts)
- if line:match("#pragma%s+pack") then
+ -- otherwise luajit has wrong memory layouts for the structs)
+ if line:match('#pragma%s+pack') then
--- @type string
- line = line .. " // " .. pragma_pack_id
+ line = line .. ' // ' .. pragma_pack_id
pragma_pack_id = pragma_pack_id + 1
end
new_cdefs:add(line)
@@ -277,13 +279,13 @@ end
local function alloc_log_new()
local log = {
- log={}, --- @type ChildCallLog[]
- lib=cimport('./src/nvim/memory.h'), --- @type table<string,function>
- original_functions={}, --- @type table<string,function>
- null={['\0:is_null']=true},
+ log = {}, --- @type ChildCallLog[]
+ lib = cimport('./src/nvim/memory.h'), --- @type table<string,function>
+ original_functions = {}, --- @type table<string,function>
+ null = { ['\0:is_null'] = true },
}
- local allocator_functions = {'malloc', 'free', 'calloc', 'realloc'}
+ local allocator_functions = { 'malloc', 'free', 'calloc', 'realloc' }
function log:save_original_functions()
for _, funcname in ipairs(allocator_functions) do
@@ -301,7 +303,7 @@ local function alloc_log_new()
local kk = k
self.lib['mem_' .. k] = function(...)
--- @type ChildCallLog
- local log_entry = { func = kk, args = {...} }
+ local log_entry = { func = kk, args = { ... } }
self.log[#self.log + 1] = log_entry
if kk == 'free' then
self.original_functions[kk](...)
@@ -314,7 +316,9 @@ local function alloc_log_new()
log_entry.args[i] = self.null
end
end
- if self.hook then self:hook(log_entry) end
+ if self.hook then
+ self:hook(log_entry)
+ end
if log_entry.ret then
return log_entry.ret
end
@@ -355,7 +359,7 @@ local function alloc_log_new()
end
end
table.sort(toremove)
- for i = #toremove,1,-1 do
+ for i = #toremove, 1, -1 do
table.remove(self.log, toremove[i])
end
end
@@ -365,11 +369,9 @@ local function alloc_log_new()
log:set_mocks()
end
- function log:before_each()
- end
+ function log:before_each() end
- function log:after_each()
- end
+ function log:after_each() end
log:setup()
@@ -397,13 +399,12 @@ function sc.fork()
end
function sc.pipe()
- local ret = ffi.new('int[2]', {-1, -1})
+ local ret = ffi.new('int[2]', { -1, -1 })
ffi.errno(0)
local res = ffi.C.pipe(ret)
- if (res ~= 0) then
+ if res ~= 0 then
local err = ffi.errno(0)
- assert(res == 0, ("pipe() error: %u: %s"):format(
- err, ffi.string(ffi.C.strerror(err))))
+ assert(res == 0, ('pipe() error: %u: %s'):format(err, ffi.string(ffi.C.strerror(err))))
end
assert(ret[0] ~= -1 and ret[1] ~= -1)
return ret[0], ret[1]
@@ -411,19 +412,16 @@ end
--- @return string
function sc.read(rd, len)
- local ret = ffi.new('char[?]', len, {0})
+ local ret = ffi.new('char[?]', len, { 0 })
local total_bytes_read = 0
ffi.errno(0)
while total_bytes_read < len do
- local bytes_read = tonumber(ffi.C.read(
- rd,
- ffi.cast('void*', ret + total_bytes_read),
- len - total_bytes_read))
+ local bytes_read =
+ tonumber(ffi.C.read(rd, ffi.cast('void*', ret + total_bytes_read), len - total_bytes_read))
if bytes_read == -1 then
local err = ffi.errno(0)
if err ~= ffi.C.kPOSIXErrnoEINTR then
- assert(false, ("read() error: %u: %s"):format(
- err, ffi.string(ffi.C.strerror(err))))
+ assert(false, ('read() error: %u: %s'):format(err, ffi.string(ffi.C.strerror(err))))
end
elseif bytes_read == 0 then
break
@@ -439,15 +437,16 @@ function sc.write(wr, s)
local total_bytes_written = 0
ffi.errno(0)
while total_bytes_written < #s do
- local bytes_written = tonumber(ffi.C.write(
- wr,
- ffi.cast('void*', wbuf + total_bytes_written),
- #s - total_bytes_written))
+ local bytes_written = tonumber(
+ ffi.C.write(wr, ffi.cast('void*', wbuf + total_bytes_written), #s - total_bytes_written)
+ )
if bytes_written == -1 then
local err = ffi.errno(0)
if err ~= ffi.C.kPOSIXErrnoEINTR then
- assert(false, ("write() error: %u: %s ('%s')"):format(
- err, ffi.string(ffi.C.strerror(err)), s))
+ assert(
+ false,
+ ("write() error: %u: %s ('%s')"):format(err, ffi.string(ffi.C.strerror(err)), s)
+ )
end
elseif bytes_written == 0 then
break
@@ -464,7 +463,7 @@ sc.close = ffi.C.close
--- @return integer
function sc.wait(pid)
ffi.errno(0)
- local stat_loc = ffi.new('int[1]', {0})
+ local stat_loc = ffi.new('int[1]', { 0 })
while true do
local r = ffi.C.waitpid(pid, stat_loc, ffi.C.kPOSIXWaitWUNTRACED)
if r == -1 then
@@ -472,8 +471,7 @@ function sc.wait(pid)
if err == ffi.C.kPOSIXErrnoECHILD then
break
elseif err ~= ffi.C.kPOSIXErrnoEINTR then
- assert(false, ("waitpid() error: %u: %s"):format(
- err, ffi.string(ffi.C.strerror(err))))
+ assert(false, ('waitpid() error: %u: %s'):format(err, ffi.string(ffi.C.strerror(err))))
end
else
assert(r == pid)
@@ -489,7 +487,7 @@ sc.exit = ffi.C._exit
local function format_list(lst)
local ret = {} --- @type string[]
for _, v in ipairs(lst) do
- ret[#ret+1] = assert:format({v, n=1})[1]
+ ret[#ret + 1] = assert:format({ v, n = 1 })[1]
end
return table.concat(ret, ', ')
end
@@ -498,9 +496,8 @@ if os.getenv('NVIM_TEST_PRINT_SYSCALLS') == '1' then
for k_, v_ in pairs(sc) do
(function(k, v)
sc[k] = function(...)
- local rets = {v(...)}
- io.stderr:write(('%s(%s) = %s\n'):format(k, format_list({...}),
- format_list(rets)))
+ local rets = { v(...) }
+ io.stderr:write(('%s(%s) = %s\n'):format(k, format_list({ ... }), format_list(rets)))
return unpack(rets)
end
end)(k_, v_)
@@ -512,9 +509,13 @@ local function just_fail(_)
end
say:set('assertion.just_fail.positive', '%s')
say:set('assertion.just_fail.negative', '%s')
-assert:register('assertion', 'just_fail', just_fail,
- 'assertion.just_fail.positive',
- 'assertion.just_fail.negative')
+assert:register(
+ 'assertion',
+ 'just_fail',
+ just_fail,
+ 'assertion.just_fail.positive',
+ 'assertion.just_fail.negative'
+)
local hook_fnamelen = 30
local hook_sfnamelen = 30
@@ -561,7 +562,7 @@ local function child_sethook(wr)
local info = nil --- @type debuginfo?
if use_prev then
info = prev_info
- elseif reason ~= 'tail return' then -- tail return
+ elseif reason ~= 'tail return' then -- tail return
info = debug.getinfo(2, 'nSl')
end
@@ -609,17 +610,20 @@ local function child_sethook(wr)
-- assert(-1 <= lnum and lnum <= 99999)
local lnum_s = lnum == -1 and 'nknwn' or ('%u'):format(lnum)
--- @type string
- local msg = ( -- lua does not support %*
+ local msg = ( -- lua does not support %*
''
.. msgchar
.. whatchar
.. namewhatchar
.. ' '
- .. source .. (' '):rep(hook_sfnamelen - #source)
+ .. source
+ .. (' '):rep(hook_sfnamelen - #source)
.. ':'
- .. funcname .. (' '):rep(hook_fnamelen - #funcname)
+ .. funcname
+ .. (' '):rep(hook_fnamelen - #funcname)
.. ':'
- .. ('0'):rep(hook_numlen - #lnum_s) .. lnum_s
+ .. ('0'):rep(hook_numlen - #lnum_s)
+ .. lnum_s
.. '\n'
)
-- eq(hook_msglen, #msg)
@@ -724,7 +728,7 @@ local function check_child_err(rd)
--- @type string
err = err .. '\nNo end of trace occurred'
end
- local cc_err, cc_emsg = pcall(check_cores, Paths.test_luajit_prg, true)
+ local cc_err, cc_emsg = pcall(check_cores, paths.test_luajit_prg, true)
if not cc_err then
--- @type string
err = err .. '\ncheck_cores failed: ' .. cc_emsg
@@ -742,16 +746,16 @@ local function itp_parent(rd, pid, allow_failure, location)
sc.close(rd)
if not ok then
if allow_failure then
- io.stderr:write('Errorred out ('..status..'):\n' .. tostring(emsg) .. '\n')
+ io.stderr:write('Errorred out (' .. status .. '):\n' .. tostring(emsg) .. '\n')
os.execute([[
sh -c "source ci/common/test.sh
- check_core_dumps --delete \"]] .. Paths.test_luajit_prg .. [[\""]])
+ check_core_dumps --delete \"]] .. paths.test_luajit_prg .. [[\""]])
else
- error(tostring(emsg)..'\nexit code: '..status)
+ error(tostring(emsg) .. '\nexit code: ' .. status)
end
elseif status ~= 0 then
if not allow_failure then
- error("child process errored out with status "..status.."!\n\n"..location)
+ error('child process errored out with status ' .. status .. '!\n\n' .. location)
end
end
end
@@ -760,7 +764,9 @@ local function gen_itp(it)
child_calls_mod = {}
child_calls_mod_once = {}
child_cleanups_mod_once = {}
- preprocess_cache_mod = map(function(v) return v end, preprocess_cache_init)
+ preprocess_cache_mod = map(function(v)
+ return v
+ end, preprocess_cache_init)
previous_defines_mod = previous_defines_init
cdefs_mod = cdefs_init:copy()
local function itp(name, func, allow_failure)
@@ -791,11 +797,15 @@ local function gen_itp(it)
end
local function cppimport(path)
- return cimport(Paths.test_source_path .. '/test/includes/pre/' .. path)
+ return cimport(paths.test_source_path .. '/test/includes/pre/' .. path)
end
-cimport('./src/nvim/types.h', './src/nvim/main.h', './src/nvim/os/time.h',
- './src/nvim/os/fs.h')
+cimport(
+ './src/nvim/types_defs.h',
+ './src/nvim/main.h',
+ './src/nvim/os/time.h',
+ './src/nvim/os/fs.h'
+)
local function conv_enum(etab, eval)
local n = tonumber(eval)
@@ -844,7 +854,7 @@ local function ptr2addr(ptr)
return tonumber(ffi.cast('intptr_t', ffi.cast('void *', ptr)))
end
-local s = ffi.new('char[64]', {0})
+local s = ffi.new('char[64]', { 0 })
local function ptr2key(ptr)
ffi.C.snprintf(s, ffi.sizeof(s), '%p', ffi.cast('void *', ptr))
@@ -853,7 +863,9 @@ end
local function is_asan()
cimport('./src/nvim/version.h')
- local status, res = pcall(function() return lib.version_cflags end)
+ local status, res = pcall(function()
+ return lib.version_cflags
+ end)
if status then
return ffi.string(res):match('-fsanitize=[a-z,]*address')
else
@@ -892,7 +904,7 @@ local module = {
is_asan = is_asan,
}
--- @class test.unit.helpers: test.unit.helpers.module, test.helpers
-module = global_helpers.tbl_extend('error', module, global_helpers)
+module = vim.tbl_extend('error', module, global_helpers)
return function()
return module
diff --git a/test/unit/indent_spec.lua b/test/unit/indent_spec.lua
index ec86822b55..7902918c54 100644
--- a/test/unit/indent_spec.lua
+++ b/test/unit/indent_spec.lua
@@ -1,10 +1,12 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
-local eq = helpers.eq
+local to_cstr = helpers.to_cstr
+local ffi = helpers.ffi
+local eq = helpers.eq
-local indent = helpers.cimport("./src/nvim/indent.h")
-local globals = helpers.cimport("./src/nvim/globals.h")
+local indent = helpers.cimport('./src/nvim/indent.h')
+local globals = helpers.cimport('./src/nvim/globals.h')
describe('get_sts_value', function()
itp([[returns 'softtabstop' when it is non-negative]], function()
@@ -28,3 +30,31 @@ describe('get_sts_value', function()
eq(tabstop, indent.get_sts_value())
end)
end)
+
+describe('indent_size_ts()', function()
+ itp('works for spaces', function()
+ local line = to_cstr((' '):rep(7) .. 'a ')
+ eq(7, indent.indent_size_ts(line, 100, nil))
+ end)
+
+ itp('works for tabs and spaces', function()
+ local line = to_cstr(' \t \t \t\t a ')
+ eq(19, indent.indent_size_ts(line, 4, nil))
+ end)
+
+ itp('works for tabs and spaces with empty vts', function()
+ local vts = ffi.new('int[1]') -- zero initialized => first element (size) == 0
+ local line = to_cstr(' \t \t \t\t a ')
+ eq(23, indent.indent_size_ts(line, 4, vts))
+ end)
+
+ itp('works for tabs and spaces with vts', function()
+ local vts = ffi.new('int[3]')
+ vts[0] = 2 -- zero indexed
+ vts[1] = 7
+ vts[2] = 2
+
+ local line = to_cstr(' \t \t \t\t a ')
+ eq(18, indent.indent_size_ts(line, 4, vts))
+ end)
+end)
diff --git a/test/unit/keycodes_spec.lua b/test/unit/keycodes_spec.lua
index 4da3d37aaa..4a81c62ac1 100644
--- a/test/unit/keycodes_spec.lua
+++ b/test/unit/keycodes_spec.lua
@@ -1,15 +1,14 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
-local ffi = helpers.ffi
-local eq = helpers.eq
-local neq = helpers.neq
+local ffi = helpers.ffi
+local eq = helpers.eq
+local neq = helpers.neq
local keycodes = helpers.cimport('./src/nvim/keycodes.h')
local NULL = helpers.NULL
describe('keycodes.c', function()
-
describe('find_special_key()', function()
local srcp = ffi.new('const unsigned char *[1]')
local modp = ffi.new('int[1]')
@@ -28,31 +27,26 @@ describe('keycodes.c', function()
itp('case-insensitive', function()
-- Compare other capitalizations to this.
srcp[0] = '<C-A>'
- local all_caps_key =
- keycodes.find_special_key(srcp, 5, modp, 0, NULL)
+ local all_caps_key = keycodes.find_special_key(srcp, 5, modp, 0, NULL)
local all_caps_mod = modp[0]
srcp[0] = '<C-a>'
- eq(all_caps_key,
- keycodes.find_special_key(srcp, 5, modp, 0, NULL))
+ eq(all_caps_key, keycodes.find_special_key(srcp, 5, modp, 0, NULL))
eq(all_caps_mod, modp[0])
srcp[0] = '<c-A>'
- eq(all_caps_key,
- keycodes.find_special_key(srcp, 5, modp, 0, NULL))
+ eq(all_caps_key, keycodes.find_special_key(srcp, 5, modp, 0, NULL))
eq(all_caps_mod, modp[0])
srcp[0] = '<c-a>'
- eq(all_caps_key,
- keycodes.find_special_key(srcp, 5, modp, 0, NULL))
+ eq(all_caps_key, keycodes.find_special_key(srcp, 5, modp, 0, NULL))
eq(all_caps_mod, modp[0])
end)
itp('double-quote in keycode #7411', function()
-- Unescaped with in_string=false
srcp[0] = '<C-">'
- eq(string.byte('"'),
- keycodes.find_special_key(srcp, 5, modp, 0, NULL))
+ eq(string.byte('"'), keycodes.find_special_key(srcp, 5, modp, 0, NULL))
-- Unescaped with in_string=true
eq(0, keycodes.find_special_key(srcp, 5, modp, keycodes.FSK_IN_STRING, NULL))
@@ -64,9 +58,7 @@ describe('keycodes.c', function()
eq(0, keycodes.find_special_key(srcp, 6, modp, 0, NULL))
-- Escaped with in_string=true
- eq(string.byte('"'),
- keycodes.find_special_key(srcp, 6, modp, keycodes.FSK_IN_STRING, NULL))
+ eq(string.byte('"'), keycodes.find_special_key(srcp, 6, modp, keycodes.FSK_IN_STRING, NULL))
end)
end)
-
end)
diff --git a/test/unit/marktree_spec.lua b/test/unit/marktree_spec.lua
index 3f9dd4df12..b0a861727d 100644
--- a/test/unit/marktree_spec.lua
+++ b/test/unit/marktree_spec.lua
@@ -1,15 +1,17 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
-local ffi = helpers.ffi
-local eq = helpers.eq
-local ok = helpers.ok
+local ffi = helpers.ffi
+local eq = helpers.eq
+local ok = helpers.ok
-local lib = helpers.cimport("./src/nvim/marktree.h")
+local lib = helpers.cimport('./src/nvim/marktree.h')
local function tablelength(t)
local count = 0
- for _ in pairs(t) do count = count + 1 end
+ for _ in pairs(t) do
+ count = count + 1
+ end
return count
end
@@ -32,15 +34,14 @@ local function shadoworder(tree, shadow, iter, giveorder)
local mark = lib.marktree_itr_current(iter)
local id = tonumber(mark.id)
local spos = shadow[id]
- if (mark.pos.row ~= spos[1] or mark.pos.col ~= spos[2]) then
- error("invalid pos for "..id..":("..mark.pos.row..", "..mark.pos.col..") instead of ("..spos[1]..", "..spos[2]..")")
- end
+ eq(mark.pos.row, spos[1], mark.id)
+ eq(mark.pos.col, spos[2], mark.id)
if lib.mt_right_test(mark) ~= spos[3] then
- error("invalid gravity for "..id..":("..mark.pos.row..", "..mark.pos.col..")")
+ error('invalid gravity for ' .. id .. ':(' .. mark.pos.row .. ', ' .. mark.pos.col .. ')')
end
if count > 0 then
if not pos_leq(last, spos) then
- error("DISORDER")
+ error('DISORDER')
end
end
count = count + 1
@@ -52,17 +53,21 @@ local function shadoworder(tree, shadow, iter, giveorder)
until not lib.marktree_itr_next(tree, iter)
local shadowlen = tablelength(shadow)
if shadowlen ~= count then
- error("missed some keys? (shadow "..shadowlen..", tree "..count..")")
+ error('missed some keys? (shadow ' .. shadowlen .. ', tree ' .. count .. ')')
end
return id2pos, pos2id
end
local function shadowsplice(shadow, start, old_extent, new_extent)
- local old_end = {start[1] + old_extent[1],
- (old_extent[1] == 0 and start[2] or 0) + old_extent[2]}
- local new_end = {start[1] + new_extent[1],
- (new_extent[1] == 0 and start[2] or 0) + new_extent[2]}
- local delta = {new_end[1] - old_end[1], new_end[2] - old_end[2]}
+ local old_end = {
+ start[1] + old_extent[1],
+ (old_extent[1] == 0 and start[2] or 0) + old_extent[2],
+ }
+ local new_end = {
+ start[1] + new_extent[1],
+ (new_extent[1] == 0 and start[2] or 0) + new_extent[2],
+ }
+ local delta = { new_end[1] - old_end[1], new_end[2] - old_end[2] }
for _, pos in pairs(shadow) do
if pos_leq(start, pos) then
if pos_leq(pos, old_end) then
@@ -82,23 +87,31 @@ local function shadowsplice(shadow, start, old_extent, new_extent)
end
end
-local function dosplice(tree, shadow, start, old_extent, new_extent)
- lib.marktree_splice(tree, start[1], start[2], old_extent[1], old_extent[2], new_extent[1], new_extent[2])
- shadowsplice(shadow, start, old_extent, new_extent)
+local function dosplice(tree, shadow, start, old, new)
+ lib.marktree_splice(tree, start[1], start[2], old[1], old[2], new[1], new[2])
+ shadowsplice(shadow, start, old, new)
end
local ns = 10
local last_id = nil
-local function put(tree, row, col, gravitate, end_row, end_col, end_gravitate)
+local function put(tree, row, col, gravity, end_row, end_col, end_gravity)
last_id = last_id + 1
local my_id = last_id
end_row = end_row or -1
end_col = end_col or -1
- end_gravitate = end_gravitate or false
+ end_gravity = end_gravity or false
+
+ lib.marktree_put_test(tree, ns, my_id, row, col, gravity, end_row, end_col, end_gravity, false)
+ return my_id
+end
- lib.marktree_put_test(tree, ns, my_id, row, col, gravitate, end_row, end_col, end_gravitate);
+local function put_meta(tree, row, col, gravitate, meta)
+ last_id = last_id + 1
+ local my_id = last_id
+
+ lib.marktree_put_test(tree, ns, my_id, row, col, gravitate, -1, -1, false, meta)
return my_id
end
@@ -108,18 +121,18 @@ describe('marktree', function()
end)
itp('works', function()
- local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
+ local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
local shadow = {}
- local iter = ffi.new("MarkTreeIter[1]")
- local iter2 = ffi.new("MarkTreeIter[1]")
+ local iter = ffi.new('MarkTreeIter[1]')
+ local iter2 = ffi.new('MarkTreeIter[1]')
- for i = 1,100 do
- for j = 1,100 do
- local gravitate = (i%2) > 0
+ for i = 1, 100 do
+ for j = 1, 100 do
+ local gravitate = (i % 2) > 0
local id = put(tree, j, i, gravitate)
ok(id > 0)
eq(nil, shadow[id])
- shadow[id] = {j,i,gravitate}
+ shadow[id] = { j, i, gravitate }
end
-- checking every insert is too slow, but this is ok
lib.marktree_check(tree)
@@ -133,7 +146,7 @@ describe('marktree', function()
eq({}, pos2id) -- not set if not requested
eq({}, id2pos)
- for i,ipos in pairs(shadow) do
+ for i, ipos in pairs(shadow) do
local p = lib.marktree_lookup_ns(tree, ns, i, false, iter)
eq(ipos[1], p.pos.row)
eq(ipos[2], p.pos.col)
@@ -145,7 +158,7 @@ describe('marktree', function()
-- local k2 = lib.marktree_itr_current(iter)
end
- for i,ipos in pairs(shadow) do
+ for i, ipos in pairs(shadow) do
lib.marktree_itr_get(tree, ipos[1], ipos[2], iter)
local k = lib.marktree_itr_current(iter)
eq(i, tonumber(k.id))
@@ -160,9 +173,9 @@ describe('marktree', function()
shadow[tonumber(del.id)] = nil
shadoworder(tree, shadow, iter)
- for _, ci in ipairs({0,-1,1,-2,2,-10,10}) do
- for i = 1,100 do
- lib.marktree_itr_get(tree, i, 50+ci, iter)
+ for _, ci in ipairs({ 0, -1, 1, -2, 2, -10, 10 }) do
+ for i = 1, 100 do
+ lib.marktree_itr_get(tree, i, 50 + ci, iter)
local k = lib.marktree_itr_current(iter)
local id = tonumber(k.id)
eq(shadow[id][1], k.pos.row)
@@ -177,14 +190,14 @@ describe('marktree', function()
-- NB: this is quite rudimentary. We rely on
-- functional tests exercising splicing quite a bit
lib.marktree_check(tree)
- dosplice(tree, shadow, {2,2}, {0,5}, {1, 2})
+ dosplice(tree, shadow, { 2, 2 }, { 0, 5 }, { 1, 2 })
lib.marktree_check(tree)
shadoworder(tree, shadow, iter)
- dosplice(tree, shadow, {30,2}, {30,5}, {1, 2})
+ dosplice(tree, shadow, { 30, 2 }, { 30, 5 }, { 1, 2 })
lib.marktree_check(tree)
shadoworder(tree, shadow, iter)
- dosplice(tree, shadow, {5,3}, {0,2}, {0, 5})
+ dosplice(tree, shadow, { 5, 3 }, { 0, 2 }, { 0, 5 })
shadoworder(tree, shadow, iter)
lib.marktree_check(tree)
@@ -209,7 +222,7 @@ describe('marktree', function()
-- Check iterator validity for 2 specific edge cases:
-- https://github.com/neovim/neovim/pull/14719
lib.marktree_clear(tree)
- for i = 1,20 do
+ for i = 1, 20 do
put(tree, i, i, false)
end
@@ -224,45 +237,59 @@ describe('marktree', function()
itp("'intersect_mov' function works correctly", function()
local function mov(x, y, w)
- local xa = ffi.new("uint64_t[?]", #x)
- for i, xi in ipairs(x) do xa[i-1] = xi end
- local ya = ffi.new("uint64_t[?]", #y)
- for i, yi in ipairs(y) do ya[i-1] = yi end
- local wa = ffi.new("uint64_t[?]", #w)
- for i, wi in ipairs(w) do wa[i-1] = wi end
+ local xa = ffi.new('uint64_t[?]', #x)
+ for i, xi in ipairs(x) do
+ xa[i - 1] = xi
+ end
+ local ya = ffi.new('uint64_t[?]', #y)
+ for i, yi in ipairs(y) do
+ ya[i - 1] = yi
+ end
+ local wa = ffi.new('uint64_t[?]', #w)
+ for i, wi in ipairs(w) do
+ wa[i - 1] = wi
+ end
local dummy_size = #x + #y + #w
- local wouta = ffi.new("uint64_t[?]", dummy_size)
- local douta = ffi.new("uint64_t[?]", dummy_size)
- local wsize = ffi.new("size_t[1]")
+ local wouta = ffi.new('uint64_t[?]', dummy_size)
+ local douta = ffi.new('uint64_t[?]', dummy_size)
+ local wsize = ffi.new('size_t[1]')
wsize[0] = dummy_size
- local dsize = ffi.new("size_t[1]")
+ local dsize = ffi.new('size_t[1]')
dsize[0] = dummy_size
local status = lib.intersect_mov_test(xa, #x, ya, #y, wa, #w, wouta, wsize, douta, dsize)
- if status == 0 then error'wowza' end
+ if status == 0 then
+ error 'wowza'
+ end
local wout, dout = {}, {}
- for i = 0,tonumber(wsize[0])-1 do table.insert(wout, tonumber(wouta[i])) end
- for i = 0,tonumber(dsize[0])-1 do table.insert(dout, tonumber(douta[i])) end
- return {wout, dout}
- end
-
- eq({{}, {}}, mov({}, {2, 3}, {2, 3}))
- eq({{2, 3}, {}}, mov({}, {}, {2, 3}))
- eq({{2, 3}, {}}, mov({2, 3}, {}, {}))
- eq({{}, {2,3}}, mov({}, {2,3}, {}))
-
- eq({{1, 5}, {}}, mov({1,2,5}, {2, 3}, {3}))
- eq({{1, 2}, {}}, mov({1,2,5}, {5, 10}, {10}))
- eq({{1, 2}, {5}}, mov({1,2}, {5, 10}, {10}))
- eq({{1,3,5,7,9}, {2,4,6,8,10}}, mov({1,3,5,7,9}, {2,4,6,8,10}, {}))
- eq({{1,3,5,7,9}, {2,6,10}}, mov({1,3,5,7,9}, {2,4,6,8,10}, {4, 8}))
- eq({{1,4,7}, {2,5,8}}, mov({1,3,4,6,7,9}, {2,3,5,6,8,9}, {}))
- eq({{1,4,7}, {}}, mov({1,3,4,6,7,9}, {2,3,5,6,8,9}, {2,5,8}))
- eq({{0,1,4,7,10}, {}}, mov({1,3,4,6,7,9}, {2,3,5,6,8,9}, {0,2,5,8,10}))
- end)
+ for i = 0, tonumber(wsize[0]) - 1 do
+ table.insert(wout, tonumber(wouta[i]))
+ end
+ for i = 0, tonumber(dsize[0]) - 1 do
+ table.insert(dout, tonumber(douta[i]))
+ end
+ return { wout, dout }
+ end
+ eq({ {}, {} }, mov({}, { 2, 3 }, { 2, 3 }))
+ eq({ { 2, 3 }, {} }, mov({}, {}, { 2, 3 }))
+ eq({ { 2, 3 }, {} }, mov({ 2, 3 }, {}, {}))
+ eq({ {}, { 2, 3 } }, mov({}, { 2, 3 }, {}))
+
+ eq({ { 1, 5 }, {} }, mov({ 1, 2, 5 }, { 2, 3 }, { 3 }))
+ eq({ { 1, 2 }, {} }, mov({ 1, 2, 5 }, { 5, 10 }, { 10 }))
+ eq({ { 1, 2 }, { 5 } }, mov({ 1, 2 }, { 5, 10 }, { 10 }))
+ eq({ { 1, 3, 5, 7, 9 }, { 2, 4, 6, 8, 10 } }, mov({ 1, 3, 5, 7, 9 }, { 2, 4, 6, 8, 10 }, {}))
+ eq({ { 1, 3, 5, 7, 9 }, { 2, 6, 10 } }, mov({ 1, 3, 5, 7, 9 }, { 2, 4, 6, 8, 10 }, { 4, 8 }))
+ eq({ { 1, 4, 7 }, { 2, 5, 8 } }, mov({ 1, 3, 4, 6, 7, 9 }, { 2, 3, 5, 6, 8, 9 }, {}))
+ eq({ { 1, 4, 7 }, {} }, mov({ 1, 3, 4, 6, 7, 9 }, { 2, 3, 5, 6, 8, 9 }, { 2, 5, 8 }))
+ eq(
+ { { 0, 1, 4, 7, 10 }, {} },
+ mov({ 1, 3, 4, 6, 7, 9 }, { 2, 3, 5, 6, 8, 9 }, { 0, 2, 5, 8, 10 })
+ )
+ end)
local function check_intersections(tree)
lib.marktree_check(tree)
@@ -279,13 +306,13 @@ describe('marktree', function()
if not val then
local str2 = lib.mt_inspect(tree, true, true)
local dot2 = ffi.string(str2.data, str2.size)
- print("actual:\n\n".."Xafile.dot".."\n\nexpected:\n\n".."Xefile.dot".."\n")
- print("nivå", tree[0].root.level);
+ print('actual:\n\n' .. 'Xafile.dot' .. '\n\nexpected:\n\n' .. 'Xefile.dot' .. '\n')
+ print('nivå', tree[0].root.level)
io.stdout:flush()
- local afil = io.open("Xafile.dot", "wb")
+ local afil = io.open('Xafile.dot', 'wb')
afil:write(dot1)
afil:close()
- local efil = io.open("Xefile.dot", "wb")
+ local efil = io.open('Xefile.dot', 'wb')
efil:write(dot2)
efil:close()
ok(false)
@@ -295,28 +322,28 @@ describe('marktree', function()
end
itp('works with intersections', function()
- local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
+ local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
local ids = {}
- for i = 1,80 do
- table.insert(ids, put(tree, 1, i, false, 2, 100-i, false))
+ for i = 1, 80 do
+ table.insert(ids, put(tree, 1, i, false, 2, 100 - i, false))
check_intersections(tree)
end
- for i = 1,80 do
+ for i = 1, 80 do
lib.marktree_del_pair_test(tree, ns, ids[i])
check_intersections(tree)
end
ids = {}
- for i = 1,80 do
- table.insert(ids, put(tree, 1, i, false, 2, 100-i, false))
+ for i = 1, 80 do
+ table.insert(ids, put(tree, 1, i, false, 2, 100 - i, false))
check_intersections(tree)
end
- for i = 1,10 do
- for j = 1,8 do
- local ival = (j-1)*10+i
+ for i = 1, 10 do
+ for j = 1, 8 do
+ local ival = (j - 1) * 10 + i
lib.marktree_del_pair_test(tree, ns, ids[ival])
check_intersections(tree)
end
@@ -324,12 +351,12 @@ describe('marktree', function()
end)
itp('works with intersections with a big tree', function()
- local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
+ local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
local ids = {}
- for i = 1,1000 do
- table.insert(ids, put(tree, 1, i, false, 2, 1000-i, false))
+ for i = 1, 1000 do
+ table.insert(ids, put(tree, 1, i, false, 2, 1000 - i, false))
if i % 10 == 1 then
check_intersections(tree)
end
@@ -339,13 +366,13 @@ describe('marktree', function()
eq(2000, tree[0].n_keys)
ok(tree[0].root.level >= 2)
- local iter = ffi.new("MarkTreeIter[1]")
+ local iter = ffi.new('MarkTreeIter[1]')
local k = 0
- for i = 1,20 do
- for j = 1,50 do
+ for i = 1, 20 do
+ for j = 1, 50 do
k = k + 1
- local ival = (j-1)*20+i
+ local ival = (j - 1) * 20 + i
if false == true then -- if there actually is a failure, this branch will fail out at the actual spot of the error
lib.marktree_lookup_ns(tree, ns, ids[ival], false, iter)
lib.marktree_del_itr(tree, iter, false)
@@ -367,10 +394,10 @@ describe('marktree', function()
end)
itp('works with intersections and marktree_splice', function()
- local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
+ local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
- for i = 1,1000 do
- put(tree, 1, i, false, 2, 1000-i, false)
+ for i = 1, 1000 do
+ put(tree, 1, i, false, 2, 1000 - i, false)
if i % 10 == 1 then
check_intersections(tree)
end
@@ -380,15 +407,15 @@ describe('marktree', function()
eq(2000, tree[0].n_keys)
ok(tree[0].root.level >= 2)
- for _ = 1,10 do
+ for _ = 1, 10 do
lib.marktree_splice(tree, 0, 0, 0, 100, 0, 0)
check_intersections(tree)
end
end)
itp('marktree_move should preserve key order', function()
- local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
- local iter = ffi.new("MarkTreeIter[1]")
+ local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
+ local iter = ffi.new('MarkTreeIter[1]')
local ids = {}
-- new index and old index look the same, but still have to move because
@@ -405,31 +432,30 @@ describe('marktree', function()
end)
itp('works with intersections and marktree_move', function()
- local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
+ local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
local ids = {}
- for i = 1,1000 do
- table.insert(ids, put(tree, 1, i, false, 2, 1000-i, false))
+ for i = 1, 1000 do
+ table.insert(ids, put(tree, 1, i, false, 2, 1000 - i, false))
if i % 10 == 1 then
check_intersections(tree)
end
end
- local iter = ffi.new("MarkTreeIter[1]")
- for i = 1,1000 do
- local which = i%2
+ local iter = ffi.new('MarkTreeIter[1]')
+ for i = 1, 1000 do
+ local which = i % 2
lib.marktree_lookup_ns(tree, ns, ids[i], which, iter)
- lib.marktree_move(tree, iter, 1+which, 500+i)
+ lib.marktree_move(tree, iter, 1 + which, 500 + i)
if i % 10 == 1 then
check_intersections(tree)
end
end
-
end)
itp('works with intersections with a even bigger tree', function()
- local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
+ local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
local ids = {}
@@ -441,21 +467,21 @@ describe('marktree', function()
at_row[i] = {}
end
- local size = 1000*size_factor
+ local size = 1000 * size_factor
local k = 1
while k <= size do
- for row1 = 1,9 do
- for row2 = row1,10 do -- note row2 can be == row1, leads to empty ranges being tested when k > size/2
+ for row1 = 1, 9 do
+ for row2 = row1, 10 do -- note row2 can be == row1, leads to empty ranges being tested when k > size/2
if k > size then
break
end
- local id = put(tree, row1, k, false, row2, size-k, false)
+ local id = put(tree, row1, k, false, row2, size - k, false)
table.insert(ids, id)
- for i = row1+1, row2 do
+ for i = row1 + 1, row2 do
table.insert(at_row[i], id)
end
--if tree[0].root.level == 4 then error("kk"..k) end
- if k % 100*size_factor == 1 or (k < 2000 and k%100 == 1) then
+ if k % 100 * size_factor == 1 or (k < 2000 and k % 100 == 1) then
check_intersections(tree)
end
k = k + 1
@@ -463,13 +489,13 @@ describe('marktree', function()
end
end
- eq(2*size, tree[0].n_keys)
+ eq(2 * size, tree[0].n_keys)
ok(tree[0].root.level >= 3)
check_intersections(tree)
- local iter = ffi.new("MarkTreeIter[1]")
- local pair = ffi.new("MTPair[1]")
- for i = 1,10 do
+ local iter = ffi.new('MarkTreeIter[1]')
+ local pair = ffi.new('MTPair[1]')
+ for i = 1, 10 do
-- use array as set and not {[id]=true} map, to detect duplicates
local set = {}
eq(true, ffi.C.marktree_itr_get_overlap(tree, i, 0, iter))
@@ -482,14 +508,14 @@ describe('marktree', function()
end
k = 0
- for i = 1,100 do
- for j = 1,(10*size_factor) do
+ for i = 1, 100 do
+ for j = 1, (10 * size_factor) do
k = k + 1
- local ival = (j-1)*100+i
+ local ival = (j - 1) * 100 + i
lib.marktree_del_pair_test(tree, ns, ids[ival])
-- just a few stickprov, if there is trouble we need to check
-- everyone using the code in the "big tree" case above
- if k % 100*size_factor == 0 or (k > 3000 and k % 200 == 0) then
+ if k % 100 * size_factor == 0 or (k > 3000 and k % 200 == 0) then
check_intersections(tree)
end
end
@@ -499,7 +525,7 @@ describe('marktree', function()
end)
itp('works with intersections with a even bigger tree and splice', function()
- local tree = ffi.new("MarkTree[1]") -- zero initialized by luajit
+ local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
-- too much overhead on ASAN
local size_factor = helpers.is_asan() and 3 or 10
@@ -509,20 +535,20 @@ describe('marktree', function()
at_row[i] = {}
end
- local size = 1000*size_factor
+ local size = 1000 * size_factor
local k = 1
while k <= size do
- for row1 = 1,9 do
- for row2 = row1,10 do -- note row2 can be == row1, leads to empty ranges being tested when k > size/2
+ for row1 = 1, 9 do
+ for row2 = row1, 10 do -- note row2 can be == row1, leads to empty ranges being tested when k > size/2
if k > size then
break
end
- local id = put(tree, row1, k, false, row2, size-k, false)
- for i = row1+1, row2 do
+ local id = put(tree, row1, k, false, row2, size - k, false)
+ for i = row1 + 1, row2 do
table.insert(at_row[i], id)
end
--if tree[0].root.level == 4 then error("kk"..k) end
- if k % 100*size_factor == 1 or (k < 2000 and k%100 == 1) then
+ if k % 100 * size_factor == 1 or (k < 2000 and k % 100 == 1) then
check_intersections(tree)
end
k = k + 1
@@ -530,15 +556,93 @@ describe('marktree', function()
end
end
- eq(2*size, tree[0].n_keys)
+ eq(2 * size, tree[0].n_keys)
ok(tree[0].root.level >= 3)
check_intersections(tree)
- for _ = 1,10 do
+ for _ = 1, 10 do
for j = 3, 8 do
lib.marktree_splice(tree, j, 0, 0, 200, 0, 0)
check_intersections(tree)
end
end
end)
+
+ itp('works with meta counts', function()
+ local tree = ffi.new('MarkTree[1]') -- zero initialized by luajit
+
+ -- add
+ local shadow = {}
+ for i = 1, 100 do
+ for j = 1, 100 do
+ local gravitate = (i % 2) > 0
+ local inline = (j == 3 or j == 50 or j == 51 or j == 55) and i % 11 == 1
+ inline = inline or ((j >= 80 and j < 85) and i % 3 == 1)
+ local id = put_meta(tree, j, i, gravitate, inline)
+ if inline then
+ shadow[id] = { j, i, gravitate }
+ end
+ end
+ -- checking every insert is too slow, but this is ok
+ lib.marktree_check(tree)
+ end
+
+ lib.marktree_check(tree)
+ local iter = ffi.new('MarkTreeIter[1]')
+ local filter = ffi.new('uint32_t[4]')
+ filter[0] = -1
+ ok(lib.marktree_itr_get_filter(tree, 0, 0, 101, 0, filter, iter))
+ local seen = {}
+ repeat
+ local mark = lib.marktree_itr_current(iter)
+ eq(nil, seen[mark.id])
+ seen[mark.id] = true
+ eq(mark.pos.row, shadow[mark.id][1])
+ eq(mark.pos.col, shadow[mark.id][2])
+ until not lib.marktree_itr_next_filter(tree, iter, 101, 0, filter)
+ eq(tablelength(seen), tablelength(shadow))
+
+ -- test skipping subtrees to find the filtered mark at line 50
+ for i = 4, 50 do
+ ok(lib.marktree_itr_get_filter(tree, i, 0, 60, 0, filter, iter))
+ local mark = lib.marktree_itr_current(iter)
+ eq({ 50, 50, 1 }, { mark.id, mark.pos.row, mark.pos.col })
+ end
+
+ -- delete
+ for id = 1, 10000, 2 do
+ lib.marktree_lookup_ns(tree, ns, id, false, iter)
+ if shadow[id] then
+ local mark = lib.marktree_itr_current(iter)
+ eq(mark.pos.row, shadow[id][1])
+ eq(mark.pos.col, shadow[id][2])
+ shadow[id] = nil
+ end
+ lib.marktree_del_itr(tree, iter, false)
+ if id % 100 == 1 then
+ lib.marktree_check(tree)
+ end
+ end
+
+ -- Splice!
+ dosplice(tree, shadow, { 82, 0 }, { 0, 50 }, { 0, 0 })
+ lib.marktree_check(tree)
+
+ dosplice(tree, shadow, { 81, 50 }, { 2, 50 }, { 1, 0 })
+ lib.marktree_check(tree)
+
+ dosplice(tree, shadow, { 2, 50 }, { 1, 50 }, { 0, 10 })
+ lib.marktree_check(tree)
+
+ ok(lib.marktree_itr_get_filter(tree, 0, 0, 101, 0, filter, iter))
+ seen = {}
+ repeat
+ local mark = lib.marktree_itr_current(iter)
+ eq(nil, seen[mark.id])
+ seen[mark.id] = true
+ eq(mark.pos.row, shadow[mark.id][1])
+ eq(mark.pos.col, shadow[mark.id][2])
+ until not lib.marktree_itr_next_filter(tree, iter, 101, 0, filter)
+ eq(tablelength(seen), tablelength(shadow))
+ end)
end)
diff --git a/test/unit/mbyte_spec.lua b/test/unit/mbyte_spec.lua
index cd94624570..00a8c06ceb 100644
--- a/test/unit/mbyte_spec.lua
+++ b/test/unit/mbyte_spec.lua
@@ -1,8 +1,8 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
-local ffi = helpers.ffi
-local eq = helpers.eq
+local ffi = helpers.ffi
+local eq = helpers.eq
local lib = helpers.cimport('./src/nvim/mbyte.h', './src/nvim/charset.h', './src/nvim/grid.h')
@@ -16,13 +16,12 @@ describe('mbyte', function()
return table.concat(s)
end
- before_each(function()
- end)
+ before_each(function() end)
itp('utf_ptr2char', function()
-- For strings with length 1 the first byte is returned.
for c = 0, 255 do
- eq(c, lib.utf_ptr2char(to_string({c, 0})))
+ eq(c, lib.utf_ptr2char(to_string({ c, 0 })))
end
-- Some ill formed byte sequences that should not be recognized as UTF-8
@@ -48,126 +47,230 @@ describe('mbyte', function()
describe('utfc_ptr2schar_len', function()
local function test_seq(seq)
- local firstc = ffi.new("int[1]")
- local buf = ffi.new("char[32]")
+ local firstc = ffi.new('int[1]')
+ local buf = ffi.new('char[32]')
lib.schar_get(buf, lib.utfc_ptr2schar_len(to_string(seq), #seq, firstc))
- return {ffi.string(buf), firstc[0]}
+ return { ffi.string(buf), firstc[0] }
end
local function byte(val)
- return {string.char(val), val}
+ return { string.char(val), val }
end
itp('1-byte sequences', function()
- eq({'', 0}, test_seq{0})
+ eq({ '', 0 }, test_seq { 0 })
for c = 1, 127 do
- eq(byte(c), test_seq{c})
+ eq(byte(c), test_seq { c })
end
for c = 128, 255 do
- eq({'', c}, test_seq{c})
+ eq({ '', c }, test_seq { c })
end
end)
itp('2-byte sequences', function()
-- No combining characters
- eq(byte(0x7f), test_seq{0x7f, 0x7f})
+ eq(byte(0x7f), test_seq { 0x7f, 0x7f })
-- No combining characters
- eq(byte(0x7f), test_seq{0x7f, 0x80})
+ eq(byte(0x7f), test_seq { 0x7f, 0x80 })
-- No UTF-8 sequence
- eq({'', 0xc2}, test_seq{0xc2, 0x7f})
+ eq({ '', 0xc2 }, test_seq { 0xc2, 0x7f })
-- One UTF-8 character
- eq({'\xc2\x80', 0x80}, test_seq{0xc2, 0x80})
+ eq({ '\xc2\x80', 0x80 }, test_seq { 0xc2, 0x80 })
-- No UTF-8 sequence
- eq({'', 0xc2}, test_seq{0xc2, 0xc0})
+ eq({ '', 0xc2 }, test_seq { 0xc2, 0xc0 })
end)
itp('3-byte sequences', function()
-- No second UTF-8 character
- eq(byte(0x7f), test_seq{0x7f, 0x80, 0x80})
+ eq(byte(0x7f), test_seq { 0x7f, 0x80, 0x80 })
-- No combining character
- eq(byte(0x7f), test_seq{0x7f, 0xc2, 0x80})
+ eq(byte(0x7f), test_seq { 0x7f, 0xc2, 0x80 })
-- Combining character is U+0300
- eq({"\x7f\xcc\x80", 0x7f}, test_seq{0x7f, 0xcc, 0x80})
+ eq({ '\x7f\xcc\x80', 0x7f }, test_seq { 0x7f, 0xcc, 0x80 })
-- No UTF-8 sequence
- eq({'', 0xc2}, test_seq{0xc2, 0x7f, 0xcc})
+ eq({ '', 0xc2 }, test_seq { 0xc2, 0x7f, 0xcc })
-- Incomplete combining character
- eq({"\xc2\x80", 0x80}, test_seq{0xc2, 0x80, 0xcc})
+ eq({ '\xc2\x80', 0x80 }, test_seq { 0xc2, 0x80, 0xcc })
-- One UTF-8 character (composing only)
- eq({" \xe2\x83\x90", 0x20d0}, test_seq{0xe2, 0x83, 0x90})
+ eq({ ' \xe2\x83\x90', 0x20d0 }, test_seq { 0xe2, 0x83, 0x90 })
end)
itp('4-byte sequences', function()
-
-- No following combining character
- eq(byte(0x7f), test_seq{0x7f, 0x7f, 0xcc, 0x80})
+ eq(byte(0x7f), test_seq { 0x7f, 0x7f, 0xcc, 0x80 })
-- No second UTF-8 character
- eq(byte(0x7f), test_seq{0x7f, 0xc2, 0xcc, 0x80})
+ eq(byte(0x7f), test_seq { 0x7f, 0xc2, 0xcc, 0x80 })
-- Combining character U+0300
- eq({"\x7f\xcc\x80", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc})
+ eq({ '\x7f\xcc\x80', 0x7f }, test_seq { 0x7f, 0xcc, 0x80, 0xcc })
-- No UTF-8 sequence
- eq({'', 0xc2}, test_seq{0xc2, 0x7f, 0xcc, 0x80})
+ eq({ '', 0xc2 }, test_seq { 0xc2, 0x7f, 0xcc, 0x80 })
-- No following UTF-8 character
- eq({"\xc2\x80", 0x80}, test_seq{0xc2, 0x80, 0xcc, 0xcc})
+ eq({ '\xc2\x80', 0x80 }, test_seq { 0xc2, 0x80, 0xcc, 0xcc })
-- Combining character U+0301
- eq({"\xc2\x80\xcc\x81", 0x80}, test_seq{0xc2, 0x80, 0xcc, 0x81})
+ eq({ '\xc2\x80\xcc\x81', 0x80 }, test_seq { 0xc2, 0x80, 0xcc, 0x81 })
-- One UTF-8 character
- eq({"\xf4\x80\x80\x80", 0x100000}, test_seq{0xf4, 0x80, 0x80, 0x80})
+ eq({ '\xf4\x80\x80\x80', 0x100000 }, test_seq { 0xf4, 0x80, 0x80, 0x80 })
end)
itp('5+-byte sequences', function()
-- No following combining character
- eq(byte(0x7f), test_seq{0x7f, 0x7f, 0xcc, 0x80, 0x80})
+ eq(byte(0x7f), test_seq { 0x7f, 0x7f, 0xcc, 0x80, 0x80 })
-- No second UTF-8 character
- eq(byte(0x7f), test_seq{0x7f, 0xc2, 0xcc, 0x80, 0x80})
+ eq(byte(0x7f), test_seq { 0x7f, 0xc2, 0xcc, 0x80, 0x80 })
-- Combining character U+0300
- eq({"\x7f\xcc\x80", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x00})
+ eq({ '\x7f\xcc\x80', 0x7f }, test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x00 })
-- Combining characters U+0300 and U+0301
- eq({"\x7f\xcc\x80\xcc\x81", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81})
+ eq({ '\x7f\xcc\x80\xcc\x81', 0x7f }, test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81 })
-- Combining characters U+0300, U+0301, U+0302
- eq({"\x7f\xcc\x80\xcc\x81\xcc\x82", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82})
+ eq(
+ { '\x7f\xcc\x80\xcc\x81\xcc\x82', 0x7f },
+ test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82 }
+ )
-- Combining characters U+0300, U+0301, U+0302, U+0303
- eq({"\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83})
+ eq(
+ { '\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83', 0x7f },
+ test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83 }
+ )
-- Combining characters U+0300, U+0301, U+0302, U+0303, U+0304
- eq({"\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83, 0xcc, 0x84})
+ eq(
+ { '\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84', 0x7f },
+ test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83, 0xcc, 0x84 }
+ )
-- Combining characters U+0300, U+0301, U+0302, U+0303, U+0304, U+0305
- eq({"\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84\xcc\x85", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83, 0xcc, 0x84, 0xcc, 0x85})
+ eq(
+ { '\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84\xcc\x85', 0x7f },
+ test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83, 0xcc, 0x84, 0xcc, 0x85 }
+ )
-- Combining characters U+0300, U+0301, U+0302, U+0303, U+0304, U+0305, U+0306
- eq({"\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84\xcc\x85\xcc\x86", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xcc, 0x83, 0xcc, 0x84, 0xcc, 0x85, 0xcc, 0x86})
+ eq(
+ { '\x7f\xcc\x80\xcc\x81\xcc\x82\xcc\x83\xcc\x84\xcc\x85\xcc\x86', 0x7f },
+ test_seq {
+ 0x7f,
+ 0xcc,
+ 0x80,
+ 0xcc,
+ 0x81,
+ 0xcc,
+ 0x82,
+ 0xcc,
+ 0x83,
+ 0xcc,
+ 0x84,
+ 0xcc,
+ 0x85,
+ 0xcc,
+ 0x86,
+ }
+ )
-- Only three following combining characters U+0300, U+0301, U+0302
- eq({"\x7f\xcc\x80\xcc\x81\xcc\x82", 0x7f}, test_seq{0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xc2, 0x80, 0xcc, 0x84, 0xcc, 0x85})
+ eq(
+ { '\x7f\xcc\x80\xcc\x81\xcc\x82', 0x7f },
+ test_seq { 0x7f, 0xcc, 0x80, 0xcc, 0x81, 0xcc, 0x82, 0xc2, 0x80, 0xcc, 0x84, 0xcc, 0x85 }
+ )
-- No UTF-8 sequence
- eq({'', 0xc2}, test_seq{0xc2, 0x7f, 0xcc, 0x80, 0x80})
+ eq({ '', 0xc2 }, test_seq { 0xc2, 0x7f, 0xcc, 0x80, 0x80 })
-- No following UTF-8 character
- eq({"\xc2\x80", 0x80}, test_seq{0xc2, 0x80, 0xcc, 0xcc, 0x80})
+ eq({ '\xc2\x80', 0x80 }, test_seq { 0xc2, 0x80, 0xcc, 0xcc, 0x80 })
-- Combining character U+0301
- eq({"\xc2\x80\xcc\x81", 0x80}, test_seq{0xc2, 0x80, 0xcc, 0x81, 0x7f})
+ eq({ '\xc2\x80\xcc\x81', 0x80 }, test_seq { 0xc2, 0x80, 0xcc, 0x81, 0x7f })
-- Combining character U+0301
- eq({"\xc2\x80\xcc\x81", 0x80}, test_seq{0xc2, 0x80, 0xcc, 0x81, 0xcc})
+ eq({ '\xc2\x80\xcc\x81', 0x80 }, test_seq { 0xc2, 0x80, 0xcc, 0x81, 0xcc })
-- One UTF-8 character
- eq({"\xf4\x80\x80\x80", 0x100000}, test_seq{0xf4, 0x80, 0x80, 0x80, 0x7f})
+ eq({ '\xf4\x80\x80\x80', 0x100000 }, test_seq { 0xf4, 0x80, 0x80, 0x80, 0x7f })
-- One UTF-8 character
- eq({"\xf4\x80\x80\x80", 0x100000}, test_seq{0xf4, 0x80, 0x80, 0x80, 0x80})
+ eq({ '\xf4\x80\x80\x80', 0x100000 }, test_seq { 0xf4, 0x80, 0x80, 0x80, 0x80 })
-- One UTF-8 character
- eq({"\xf4\x80\x80\x80", 0x100000}, test_seq{0xf4, 0x80, 0x80, 0x80, 0xcc})
+ eq({ '\xf4\x80\x80\x80', 0x100000 }, test_seq { 0xf4, 0x80, 0x80, 0x80, 0xcc })
-- Combining characters U+1AB0 and U+0301
- eq({"\xf4\x80\x80\x80\xe1\xaa\xb0\xcc\x81", 0x100000}, test_seq{0xf4, 0x80, 0x80, 0x80, 0xe1, 0xaa, 0xb0, 0xcc, 0x81})
+ eq(
+ { '\xf4\x80\x80\x80\xe1\xaa\xb0\xcc\x81', 0x100000 },
+ test_seq { 0xf4, 0x80, 0x80, 0x80, 0xe1, 0xaa, 0xb0, 0xcc, 0x81 }
+ )
end)
-
end)
+ describe('utf_cp_bounds_len', function()
+ local to_cstr = helpers.to_cstr
+
+ local tests = {
+ {
+ name = 'for valid string',
+ str = 'iÀiiâ± iâ± â± ð€€i',
+ offsets = {
+ b = { 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 1, 2, 0, 1, 2, 0, 1, 2, 3, 0 },
+ e = { 1, 2, 1, 1, 1, 3, 2, 1, 1, 3, 2, 1, 3, 2, 1, 4, 3, 2, 1, 1 },
+ },
+ },
+ {
+ name = 'for string with incomplete sequence',
+ str = 'i\xC3iÀⱠiÀ\xE2\xB1Ⱡ\xF0\x90\x80',
+ offsets = {
+ b = { 0, 0, 0, 0, 1, 0, 1, 2, 0, 0, 1, 0, 0, 0, 1, 2, 0, 0, 0 },
+ e = { 1, 1, 1, 2, 1, 3, 2, 1, 1, 2, 1, 1, 1, 3, 2, 1, 1, 1, 1 },
+ },
+ },
+ {
+ name = 'for string with trailing bytes after multibyte',
+ str = 'iÀ\xA0â± \xA0â± ð€€\xA0i',
+ offsets = {
+ b = { 0, 0, 1, 0, 0, 1, 2, 0, 0, 1, 2, 0, 1, 2, 3, 0, 0 },
+ e = { 1, 2, 1, 1, 3, 2, 1, 1, 3, 2, 1, 4, 3, 2, 1, 1, 1 },
+ },
+ },
+ }
+
+ for _, test in ipairs(tests) do
+ itp(test.name, function()
+ local cstr = to_cstr(test.str)
+ local b_offsets, e_offsets = {}, {}
+ for i = 1, #test.str do
+ local result = lib.utf_cp_bounds_len(cstr, cstr + i - 1, #test.str - (i - 1))
+ table.insert(b_offsets, result.begin_off)
+ table.insert(e_offsets, result.end_off)
+ end
+ eq(test.offsets, { b = b_offsets, e = e_offsets })
+ end)
+ end
+
+ itp('does not read before start', function()
+ local str = 'ð€€'
+ local expected_offsets = { b = { 0, 0, 0 }, e = { 1, 1, 1 } }
+ local cstr = to_cstr(str) + 1
+ local b_offsets, e_offsets = {}, {}
+ for i = 1, 3 do
+ local result = lib.utf_cp_bounds_len(cstr, cstr + i - 1, 3 - (i - 1))
+ table.insert(b_offsets, result.begin_off)
+ table.insert(e_offsets, result.end_off)
+ end
+ eq(expected_offsets, { b = b_offsets, e = e_offsets })
+ end)
+
+ itp('does not read past the end', function()
+ local str = 'ð€€'
+ local expected_offsets = { b = { 0, 0, 0 }, e = { 1, 1, 1 } }
+ local cstr = to_cstr(str)
+ local b_offsets, e_offsets = {}, {}
+ for i = 1, 3 do
+ local result = lib.utf_cp_bounds_len(cstr, cstr + i - 1, 3 - (i - 1))
+ table.insert(b_offsets, result.begin_off)
+ table.insert(e_offsets, result.end_off)
+ end
+ eq(expected_offsets, { b = b_offsets, e = e_offsets })
+ end)
+ end)
end)
diff --git a/test/unit/memory_spec.lua b/test/unit/memory_spec.lua
index bd72c8bf47..8be55fdbf3 100644
--- a/test/unit/memory_spec.lua
+++ b/test/unit/memory_spec.lua
@@ -1,4 +1,4 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local cimport = helpers.cimport
@@ -11,7 +11,7 @@ local cimp = cimport('stdlib.h', './src/nvim/memory.h')
describe('xstrlcat()', function()
local function test_xstrlcat(dst, src, dsize)
- assert.is_true(dsize >= 1 + string.len(dst)) -- sanity check for tests
+ assert.is_true(dsize >= 1 + string.len(dst)) -- sanity check for tests
local dst_cstr = cstr(dsize, dst)
local src_cstr = to_cstr(src)
eq(string.len(dst .. src), cimp.xstrlcat(dst_cstr, src_cstr, dsize))
@@ -19,34 +19,32 @@ describe('xstrlcat()', function()
end
local function test_xstrlcat_overlap(dst, src_idx, dsize)
- assert.is_true(dsize >= 1 + string.len(dst)) -- sanity check for tests
+ assert.is_true(dsize >= 1 + string.len(dst)) -- sanity check for tests
local dst_cstr = cstr(dsize, dst)
- local src_cstr = dst_cstr + src_idx -- pointer into `dst` (overlaps)
- eq(string.len(dst) + string.len(dst) - src_idx,
- cimp.xstrlcat(dst_cstr, src_cstr, dsize))
+ local src_cstr = dst_cstr + src_idx -- pointer into `dst` (overlaps)
+ eq(string.len(dst) + string.len(dst) - src_idx, cimp.xstrlcat(dst_cstr, src_cstr, dsize))
return ffi.string(dst_cstr)
end
itp('concatenates strings', function()
eq('ab', test_xstrlcat('a', 'b', 3))
eq('ab', test_xstrlcat('a', 'b', 4096))
- eq('ABC×™×”Zdefgi×™×”Z', test_xstrlcat('ABC×™×”Z', 'defgi×™×”Z', 4096))
- eq('b', test_xstrlcat('', 'b', 4096))
- eq('a', test_xstrlcat('a', '', 4096))
+ eq('ABC×™×”Zdefgi×™×”Z', test_xstrlcat('ABC×™×”Z', 'defgi×™×”Z', 4096))
+ eq('b', test_xstrlcat('', 'b', 4096))
+ eq('a', test_xstrlcat('a', '', 4096))
end)
itp('concatenates overlapping strings', function()
- eq('abcabc', test_xstrlcat_overlap('abc', 0, 7))
- eq('abca', test_xstrlcat_overlap('abc', 0, 5))
- eq('abcb', test_xstrlcat_overlap('abc', 1, 5))
- eq('abcc', test_xstrlcat_overlap('abc', 2, 10))
- eq('abcabc', test_xstrlcat_overlap('abc', 0, 2343))
+ eq('abcabc', test_xstrlcat_overlap('abc', 0, 7))
+ eq('abca', test_xstrlcat_overlap('abc', 0, 5))
+ eq('abcb', test_xstrlcat_overlap('abc', 1, 5))
+ eq('abcc', test_xstrlcat_overlap('abc', 2, 10))
+ eq('abcabc', test_xstrlcat_overlap('abc', 0, 2343))
end)
itp('truncates if `dsize` is too small', function()
eq('a', test_xstrlcat('a', 'b', 2))
eq('', test_xstrlcat('', 'b', 1))
- eq('ABC×™×”Zd', test_xstrlcat('ABC×™×”Z', 'defgi×™×”Z', 10))
+ eq('ABC×™×”Zd', test_xstrlcat('ABC×™×”Z', 'defgi×™×”Z', 10))
end)
-
end)
diff --git a/test/unit/message_spec.lua b/test/unit/message_spec.lua
index 0d5268d199..71aa74d90d 100644
--- a/test/unit/message_spec.lua
+++ b/test/unit/message_spec.lua
@@ -1,12 +1,11 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local ffi = helpers.ffi
local eq = helpers.eq
local to_cstr = helpers.to_cstr
-local cimp = helpers.cimport('./src/nvim/message.h', './src/nvim/memory.h',
- './src/nvim/strings.h')
+local cimp = helpers.cimport('./src/nvim/message.h', './src/nvim/memory.h', './src/nvim/strings.h')
describe('trunc_string', function()
local buflen = 40
@@ -34,8 +33,8 @@ describe('trunc_string', function()
{ ['desc'] = 'by copy', ['func'] = test_copy },
}
- for _,t in ipairs(permutations) do
- describe('populates buf '..t.desc, function()
+ for _, t in ipairs(permutations) do
+ describe('populates buf ' .. t.desc, function()
itp('with a small string', function()
t.func('text', 'text')
end)
diff --git a/test/unit/msgpack_spec.lua b/test/unit/msgpack_spec.lua
index c573714714..bd663a3c75 100644
--- a/test/unit/msgpack_spec.lua
+++ b/test/unit/msgpack_spec.lua
@@ -35,32 +35,36 @@ end
describe('msgpack', function()
describe('unpacker', function()
- itp('does not crash when paused between `cells` and `wrap` params of `grid_line` #25184', function()
- -- [kMessageTypeNotification, "redraw", [
- -- ["grid_line",
- -- [2, 0, 0, [[" " , 0, 77]], false]
- -- ]
- -- ]]
- local payload =
- '\x93\x02\xa6\x72\x65\x64\x72\x61\x77\x91\x92\xa9\x67\x72\x69\x64\x5f\x6c\x69\x6e\x65\x95\x02\x00\x00\x91\x93\xa1\x20\x00\x4d\xc2'
+ itp(
+ 'does not crash when paused between `cells` and `wrap` params of `grid_line` #25184',
+ function()
+ -- [kMessageTypeNotification, "redraw", [
+ -- ["grid_line",
+ -- [2, 0, 0, [[" " , 0, 77]], false]
+ -- ]
+ -- ]]
+ local payload =
+ '\x93\x02\xa6\x72\x65\x64\x72\x61\x77\x91\x92\xa9\x67\x72\x69\x64\x5f\x6c\x69\x6e\x65\x95\x02\x00\x00\x91\x93\xa1\x20\x00\x4d\xc2'
- local unpacker = make_unpacker()
- lib.unpacker_init(unpacker)
+ local unpacker = make_unpacker()
+ lib.unpacker_init(unpacker)
- unpacker_goto(unpacker, payload, payload:len() - 1)
- local finished = unpacker_advance(unpacker)
- eq(finished, false)
+ unpacker_goto(unpacker, payload, payload:len() - 1)
+ local finished = unpacker_advance(unpacker)
+ eq(finished, false)
- unpacker[0].read_size = unpacker[0].read_size + 1
- finished = unpacker_advance(unpacker)
- eq(finished, true)
- end)
+ unpacker[0].read_size = unpacker[0].read_size + 1
+ finished = unpacker_advance(unpacker)
+ eq(finished, true)
+ end
+ )
itp('does not crash when parsing grid_line event with 0 `cells` #25184', function()
local unpacker = make_unpacker()
lib.unpacker_init(unpacker)
- unpacker_goto(unpacker,
+ unpacker_goto(
+ unpacker,
-- [kMessageTypeNotification, "redraw", [
-- ["grid_line",
-- [2, 0, 0, [], false]
diff --git a/test/unit/multiqueue_spec.lua b/test/unit/multiqueue_spec.lua
index bb08a8386f..f6d11ebed0 100644
--- a/test/unit/multiqueue_spec.lua
+++ b/test/unit/multiqueue_spec.lua
@@ -1,4 +1,4 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local child_call_once = helpers.child_call_once
@@ -6,9 +6,9 @@ local cimport = helpers.cimport
local ffi = helpers.ffi
local eq = helpers.eq
-local multiqueue = cimport("./test/unit/fixtures/multiqueue.h")
+local multiqueue = cimport('./test/unit/fixtures/multiqueue.h')
-describe("multiqueue (multi-level event-queue)", function()
+describe('multiqueue (multi-level event-queue)', function()
local parent, child1, child2, child3
local function put(q, str)
diff --git a/test/unit/optionstr_spec.lua b/test/unit/optionstr_spec.lua
index 2e7198a63a..7666db910e 100644
--- a/test/unit/optionstr_spec.lua
+++ b/test/unit/optionstr_spec.lua
@@ -1,28 +1,27 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local to_cstr = helpers.to_cstr
-local eq = helpers.eq
+local eq = helpers.eq
-local optionstr = helpers.cimport("./src/nvim/optionstr.h")
+local optionstr = helpers.cimport('./src/nvim/optionstr.h')
local check_ff_value = function(ff)
return optionstr.check_ff_value(to_cstr(ff))
end
describe('check_ff_value', function()
-
itp('views empty string as valid', function()
- eq(1, check_ff_value(""))
+ eq(1, check_ff_value(''))
end)
itp('views "unix", "dos" and "mac" as valid', function()
- eq(1, check_ff_value("unix"))
- eq(1, check_ff_value("dos"))
- eq(1, check_ff_value("mac"))
+ eq(1, check_ff_value('unix'))
+ eq(1, check_ff_value('dos'))
+ eq(1, check_ff_value('mac'))
end)
itp('views "foo" as invalid', function()
- eq(0, check_ff_value("foo"))
+ eq(0, check_ff_value('foo'))
end)
end)
diff --git a/test/unit/os/env_spec.lua b/test/unit/os/env_spec.lua
index 24b92edee5..2c638fcb37 100644
--- a/test/unit/os/env_spec.lua
+++ b/test/unit/os/env_spec.lua
@@ -62,7 +62,7 @@ describe('env.c', function()
eq('non-empty', os.getenv(name))
end)
- itp("`overwrite` behavior", function()
+ itp('`overwrite` behavior', function()
local name = 'NVIM_UNIT_TEST_SETENV_2N'
local value = 'NVIM_UNIT_TEST_SETENV_2V'
local value_updated = 'NVIM_UNIT_TEST_SETENV_2V_UPDATED'
@@ -79,7 +79,7 @@ describe('env.c', function()
itp('appends :/foo/bar to $PATH', function()
local original_path = os.getenv('PATH')
eq(true, cimp.os_setenv_append_path(to_cstr('/foo/bar/baz.exe')))
- eq(original_path..':/foo/bar', os.getenv('PATH'))
+ eq(original_path .. ':/foo/bar', os.getenv('PATH'))
end)
itp('avoids redundant separator when appending to $PATH #7377', function()
@@ -166,7 +166,7 @@ describe('env.c', function()
local test_value = 'NVIM_UNIT_TEST_GETENVNAME_AT_INDEX_1V'
os_setenv(test_name, test_value, 1)
local i = 0
- local names = { }
+ local names = {}
local found_name = false
local name = cimp.os_getenvname_at_index(i)
while name ~= NULL do
@@ -245,7 +245,7 @@ describe('env.c', function()
local input = '~/foo ~ foo'
local homedir = cstr(255, '')
cimp.expand_env_esc(to_cstr('~'), homedir, 255, false, true, NULL)
- local output_expected = ffi.string(homedir) .. "/foo ~ foo"
+ local output_expected = ffi.string(homedir) .. '/foo ~ foo'
local output = cstr(255, '')
cimp.expand_env_esc(to_cstr(input), output, 255, false, true, NULL)
eq(ffi.string(output), ffi.string(output_expected))
@@ -256,7 +256,7 @@ describe('env.c', function()
local dst = cstr(255, '')
cimp.expand_env_esc(to_cstr('~'), dst, 255, false, true, NULL)
local homedir = ffi.string(dst)
- local output_expected = homedir .. "/foo " .. homedir .. " foo"
+ local output_expected = homedir .. '/foo ' .. homedir .. ' foo'
local output = cstr(255, '')
cimp.expand_env_esc(input, output, 255, false, false, NULL)
eq(output_expected, ffi.string(output))
@@ -267,8 +267,9 @@ describe('env.c', function()
cimp.os_get_username(name_out, 100)
local curuser = ffi.string(name_out)
- local src = to_cstr("~"..curuser.."/Vcs/django-rest-framework/rest_framework/renderers.py")
- local dst = cstr(256, "~"..curuser)
+ local src =
+ to_cstr('~' .. curuser .. '/Vcs/django-rest-framework/rest_framework/renderers.py')
+ local dst = cstr(256, '~' .. curuser)
cimp.expand_env_esc(src, dst, 256, false, false, NULL)
local len = string.len(ffi.string(dst))
assert.True(len > 56)
@@ -283,7 +284,7 @@ describe('env.c', function()
cimp.expand_env_esc(input, output, 5, false, true, NULL)
-- Make sure the first few characters are copied properly and that there is a
-- terminating null character
- for i=0,3 do
+ for i = 0, 3 do
eq(input[i], output[i])
end
eq(0, output[4])
@@ -304,7 +305,7 @@ describe('env.c', function()
-- terminating null character
-- expand_env_esc SHOULD NOT expand the variable if there is not enough space to
-- contain the result
- for i=0,3 do
+ for i = 0, 3 do
eq(output[i], input[i])
end
eq(output[4], 0)
diff --git a/test/unit/os/fileio_spec.lua b/test/unit/os/fileio_spec.lua
index fd30ca70da..617141fd3a 100644
--- a/test/unit/os/fileio_spec.lua
+++ b/test/unit/os/fileio_spec.lua
@@ -1,4 +1,4 @@
-local luv = require('luv')
+local uv = vim.uv
local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
@@ -26,7 +26,7 @@ local linkb = dir .. '/broken.lnk'
local filec = dir .. '/created-file.dat'
before_each(function()
- mkdir(dir);
+ mkdir(dir)
local f1 = io.open(file1, 'w')
f1:write(fcontents)
@@ -36,8 +36,8 @@ before_each(function()
f2:write(fcontents)
f2:close()
- luv.fs_symlink('file1.dat', linkf)
- luv.fs_symlink('broken.dat', linkb)
+ uv.fs_symlink('file1.dat', linkf)
+ uv.fs_symlink('broken.dat', linkb)
end)
after_each(function()
@@ -46,7 +46,7 @@ after_each(function()
os.remove(linkf)
os.remove(linkb)
os.remove(filec)
- luv.fs_rmdir(dir)
+ uv.fs_rmdir(dir)
end)
local function file_open(fname, flags, mode)
@@ -55,32 +55,16 @@ local function file_open(fname, flags, mode)
return ret1, ret2
end
-local function file_open_new(fname, flags, mode)
- local ret1 = ffi.new('int[?]', 1, {0})
- local ret2 = ffi.gc(m.file_open_new(ret1, fname, flags, mode), nil)
- return ret1[0], ret2
-end
-
local function file_open_fd(fd, flags)
local ret2 = ffi.new('FileDescriptor')
local ret1 = m.file_open_fd(ret2, fd, flags)
return ret1, ret2
end
-local function file_open_fd_new(fd, flags)
- local ret1 = ffi.new('int[?]', 1, {0})
- local ret2 = ffi.gc(m.file_open_fd_new(ret1, fd, flags), nil)
- return ret1[0], ret2
-end
-
local function file_write(fp, buf)
return m.file_write(fp, buf, #buf)
end
-local function msgpack_file_write(fp, buf)
- return m.msgpack_file_write(fp, buf, #buf)
-end
-
local function file_read(fp, size)
local buf = nil
if size == nil then
@@ -116,37 +100,17 @@ describe('file_open_fd', function()
local fd = m.os_open(file1, m.kO_RDONLY, 0)
local err, fp = file_open_fd(fd, m.kFileReadOnly)
eq(0, err)
- eq({#fcontents, fcontents}, {file_read(fp, #fcontents)})
+ eq({ #fcontents, fcontents }, { file_read(fp, #fcontents) })
eq(0, m.file_close(fp, false))
end)
itp('can use file descriptor returned by os_open for writing', function()
- eq(nil, luv.fs_stat(filec))
+ eq(nil, uv.fs_stat(filec))
local fd = m.os_open(filec, m.kO_WRONLY + m.kO_CREAT, 384)
local err, fp = file_open_fd(fd, m.kFileWriteOnly)
eq(0, err)
eq(4, file_write(fp, 'test'))
eq(0, m.file_close(fp, false))
- eq(4, luv.fs_stat(filec).size)
- eq('test', io.open(filec):read('*a'))
- end)
-end)
-
-describe('file_open_fd_new', function()
- itp('can use file descriptor returned by os_open for reading', function()
- local fd = m.os_open(file1, m.kO_RDONLY, 0)
- local err, fp = file_open_fd_new(fd, m.kFileReadOnly)
- eq(0, err)
- eq({#fcontents, fcontents}, {file_read(fp, #fcontents)})
- eq(0, m.file_free(fp, false))
- end)
- itp('can use file descriptor returned by os_open for writing', function()
- eq(nil, luv.fs_stat(filec))
- local fd = m.os_open(filec, m.kO_WRONLY + m.kO_CREAT, 384)
- local err, fp = file_open_fd_new(fd, m.kFileWriteOnly)
- eq(0, err)
- eq(4, file_write(fp, 'test'))
- eq(0, m.file_free(fp, false))
- eq(4, luv.fs_stat(filec).size)
+ eq(4, uv.fs_stat(filec).size)
eq('test', io.open(filec):read('*a'))
end)
end)
@@ -155,7 +119,7 @@ describe('file_open', function()
itp('can create a rwx------ file with kFileCreate', function()
local err, fp = file_open(filec, m.kFileCreate, 448)
eq(0, err)
- local attrs = luv.fs_stat(filec)
+ local attrs = uv.fs_stat(filec)
eq(33216, attrs.mode)
eq(0, m.file_close(fp, false))
end)
@@ -163,7 +127,7 @@ describe('file_open', function()
itp('can create a rw------- file with kFileCreate', function()
local err, fp = file_open(filec, m.kFileCreate, 384)
eq(0, err)
- local attrs = luv.fs_stat(filec)
+ local attrs = uv.fs_stat(filec)
eq(33152, attrs.mode)
eq(0, m.file_close(fp, false))
end)
@@ -171,7 +135,7 @@ describe('file_open', function()
itp('can create a rwx------ file with kFileCreateOnly', function()
local err, fp = file_open(filec, m.kFileCreateOnly, 448)
eq(0, err)
- local attrs = luv.fs_stat(filec)
+ local attrs = uv.fs_stat(filec)
eq(33216, attrs.mode)
eq(0, m.file_close(fp, false))
end)
@@ -179,7 +143,7 @@ describe('file_open', function()
itp('can create a rw------- file with kFileCreateOnly', function()
local err, fp = file_open(filec, m.kFileCreateOnly, 384)
eq(0, err)
- local attrs = luv.fs_stat(filec)
+ local attrs = uv.fs_stat(filec)
eq(33152, attrs.mode)
eq(0, m.file_close(fp, false))
end)
@@ -193,7 +157,9 @@ describe('file_open', function()
local err, _ = file_open(linkf, m.kFileNoSymlink, 384)
-- err is UV_EMLINK in FreeBSD, but if I use `ok(err == m.UV_ELOOP or err ==
-- m.UV_EMLINK)`, then I loose the ability to see actual `err` value.
- if err ~= m.UV_ELOOP then eq(m.UV_EMLINK, err) end
+ if err ~= m.UV_ELOOP then
+ eq(m.UV_EMLINK, err)
+ end
end)
itp('can open an existing file write-only with kFileCreate', function()
@@ -229,7 +195,7 @@ describe('file_open', function()
eq(0, err)
eq(true, fp.wr)
eq(0, m.file_close(fp, false))
- local attrs = luv.fs_stat(file1)
+ local attrs = uv.fs_stat(file1)
eq(0, attrs.size)
end)
@@ -238,24 +204,23 @@ describe('file_open', function()
eq(0, err)
eq(true, fp.wr)
eq(0, m.file_close(fp, false))
- local attrs = luv.fs_stat(file1)
+ local attrs = uv.fs_stat(file1)
eq(4096, attrs.size)
end)
itp('fails to create a file with just kFileWriteOnly', function()
local err, _ = file_open(filec, m.kFileWriteOnly, 384)
eq(m.UV_ENOENT, err)
- local attrs = luv.fs_stat(filec)
+ local attrs = uv.fs_stat(filec)
eq(nil, attrs)
end)
- itp('can truncate an existing file with kFileTruncate when opening a symlink',
- function()
+ itp('can truncate an existing file with kFileTruncate when opening a symlink', function()
local err, fp = file_open(linkf, m.kFileTruncate, 384)
eq(0, err)
eq(true, fp.wr)
eq(0, m.file_close(fp, false))
- local attrs = luv.fs_stat(file1)
+ local attrs = uv.fs_stat(file1)
eq(0, attrs.size)
end)
@@ -275,42 +240,15 @@ describe('file_open', function()
end)
end)
-describe('file_open_new', function()
- itp('can open a file read-only', function()
- local err, fp = file_open_new(file1, 0, 384)
- eq(0, err)
- eq(false, fp.wr)
- eq(0, m.file_free(fp, false))
- end)
-
- itp('fails to open an existing file with kFileCreateOnly', function()
- local err, fp = file_open_new(file1, m.kFileCreateOnly, 384)
- eq(m.UV_EEXIST, err)
- eq(nil, fp)
- end)
-end)
-
describe('file_close', function()
itp('can flush writes to disk also with true argument', function()
local err, fp = file_open(filec, m.kFileCreateOnly, 384)
eq(0, err)
local wsize = file_write(fp, 'test')
eq(4, wsize)
- eq(0, luv.fs_stat(filec).size)
+ eq(0, uv.fs_stat(filec).size)
eq(0, m.file_close(fp, true))
- eq(wsize, luv.fs_stat(filec).size)
- end)
-end)
-
-describe('file_free', function()
- itp('can flush writes to disk also with true argument', function()
- local err, fp = file_open_new(filec, m.kFileCreateOnly, 384)
- eq(0, err)
- local wsize = file_write(fp, 'test')
- eq(4, wsize)
- eq(0, luv.fs_stat(filec).size)
- eq(0, m.file_free(fp, true))
- eq(wsize, luv.fs_stat(filec).size)
+ eq(wsize, uv.fs_stat(filec).size)
end)
end)
@@ -319,12 +257,12 @@ describe('file_fsync', function()
local err, fp = file_open(filec, m.kFileCreateOnly, 384)
eq(0, file_fsync(fp))
eq(0, err)
- eq(0, luv.fs_stat(filec).size)
+ eq(0, uv.fs_stat(filec).size)
local wsize = file_write(fp, 'test')
eq(4, wsize)
- eq(0, luv.fs_stat(filec).size)
+ eq(0, uv.fs_stat(filec).size)
eq(0, file_fsync(fp))
- eq(wsize, luv.fs_stat(filec).size)
+ eq(wsize, uv.fs_stat(filec).size)
eq(0, m.file_close(fp, false))
end)
end)
@@ -334,12 +272,12 @@ describe('file_flush', function()
local err, fp = file_open(filec, m.kFileCreateOnly, 384)
eq(0, file_flush(fp))
eq(0, err)
- eq(0, luv.fs_stat(filec).size)
+ eq(0, uv.fs_stat(filec).size)
local wsize = file_write(fp, 'test')
eq(4, wsize)
- eq(0, luv.fs_stat(filec).size)
+ eq(0, uv.fs_stat(filec).size)
eq(0, file_flush(fp))
- eq(wsize, luv.fs_stat(filec).size)
+ eq(wsize, uv.fs_stat(filec).size)
eq(0, m.file_close(fp, false))
end)
end)
@@ -356,10 +294,9 @@ describe('file_read', function()
local exp_s = fcontents:sub(shift + 1, shift + size)
if shift + size >= #fcontents then
exp_err = #fcontents - shift
- exp_s = (fcontents:sub(shift + 1, shift + size)
- .. (('\0'):rep(size - exp_err)))
+ exp_s = (fcontents:sub(shift + 1, shift + size) .. (('\0'):rep(size - exp_err)))
end
- eq({exp_err, exp_s}, {file_read(fp, size)})
+ eq({ exp_err, exp_s }, { file_read(fp, size) })
shift = shift + size
end
eq(0, m.file_close(fp, false))
@@ -369,8 +306,8 @@ describe('file_read', function()
local err, fp = file_open(file1, 0, 384)
eq(0, err)
eq(false, fp.wr)
- eq({#fcontents, fcontents}, {file_read(fp, #fcontents)})
- eq({0, ('\0'):rep(#fcontents)}, {file_read(fp, #fcontents)})
+ eq({ #fcontents, fcontents }, { file_read(fp, #fcontents) })
+ eq({ 0, ('\0'):rep(#fcontents) }, { file_read(fp, #fcontents) })
eq(0, m.file_close(fp, false))
end)
@@ -378,9 +315,8 @@ describe('file_read', function()
local err, fp = file_open(file1, 0, 384)
eq(0, err)
eq(false, fp.wr)
- eq({5, fcontents:sub(1, 5)}, {file_read(fp, 5)})
- eq({#fcontents - 5, fcontents:sub(6) .. (('\0'):rep(5))},
- {file_read(fp, #fcontents)})
+ eq({ 5, fcontents:sub(1, 5) }, { file_read(fp, 5) })
+ eq({ #fcontents - 5, fcontents:sub(6) .. (('\0'):rep(5)) }, { file_read(fp, #fcontents) })
eq(0, m.file_close(fp, false))
end)
@@ -395,10 +331,9 @@ describe('file_read', function()
local exp_s = fcontents:sub(shift + 1, shift + size)
if shift + size >= #fcontents then
exp_err = #fcontents - shift
- exp_s = (fcontents:sub(shift + 1, shift + size)
- .. (('\0'):rep(size - exp_err)))
+ exp_s = (fcontents:sub(shift + 1, shift + size) .. (('\0'):rep(size - exp_err)))
end
- eq({exp_err, exp_s}, {file_read(fp, size)})
+ eq({ exp_err, exp_s }, { file_read(fp, size) })
shift = shift + size
end
eq(0, m.file_close(fp, false))
@@ -413,7 +348,7 @@ describe('file_write', function()
local wr = file_write(fp, fcontents)
eq(#fcontents, wr)
eq(0, m.file_close(fp, false))
- eq(wr, luv.fs_stat(filec).size)
+ eq(wr, uv.fs_stat(filec).size)
eq(fcontents, io.open(filec):read('*a'))
end)
@@ -430,7 +365,7 @@ describe('file_write', function()
shift = shift + size
end
eq(0, m.file_close(fp, false))
- eq(#fcontents, luv.fs_stat(filec).size)
+ eq(#fcontents, uv.fs_stat(filec).size)
eq(fcontents, io.open(filec):read('*a'))
end)
@@ -447,19 +382,7 @@ describe('file_write', function()
shift = shift + size
end
eq(0, m.file_close(fp, false))
- eq(#fcontents, luv.fs_stat(filec).size)
- eq(fcontents, io.open(filec):read('*a'))
- end)
-end)
-
-describe('msgpack_file_write', function()
- itp('can write the whole file at once', function()
- local err, fp = file_open(filec, m.kFileCreateOnly, 384)
- eq(0, err)
- eq(true, fp.wr)
- local wr = msgpack_file_write(fp, fcontents)
- eq(0, wr)
- eq(0, m.file_close(fp, false))
+ eq(#fcontents, uv.fs_stat(filec).size)
eq(fcontents, io.open(filec):read('*a'))
end)
end)
diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua
index 8f45d2b0c7..c15cd12fef 100644
--- a/test/unit/os/fs_spec.lua
+++ b/test/unit/os/fs_spec.lua
@@ -1,4 +1,4 @@
-local luv = require('luv')
+local uv = vim.uv
local bit = require('bit')
local helpers = require('test.unit.helpers')(after_each)
@@ -17,7 +17,7 @@ local OK = helpers.OK
local FAIL = helpers.FAIL
local NULL = helpers.NULL
local mkdir = helpers.mkdir
-local endswith = helpers.endswith
+local endswith = vim.endswith
local NODE_NORMAL = 0
local NODE_WRITABLE = 1
@@ -46,11 +46,11 @@ local function unset_bit(number, to_unset)
end
local function assert_file_exists(filepath)
- neq(nil, luv.fs_stat(filepath))
+ neq(nil, uv.fs_stat(filepath))
end
local function assert_file_does_not_exist(filepath)
- eq(nil, luv.fs_stat(filepath))
+ eq(nil, uv.fs_stat(filepath))
end
local function os_setperm(filename, perm)
@@ -68,14 +68,14 @@ describe('fs.c', function()
end
before_each(function()
- mkdir('unit-test-directory');
+ mkdir('unit-test-directory')
io.open('unit-test-directory/test.file', 'w'):close()
io.open('unit-test-directory/test_2.file', 'w'):close()
- luv.fs_symlink('test.file', 'unit-test-directory/test_link.file')
+ uv.fs_symlink('test.file', 'unit-test-directory/test_link.file')
- luv.fs_symlink('non_existing_file.file', 'unit-test-directory/test_broken_link.file')
+ uv.fs_symlink('non_existing_file.file', 'unit-test-directory/test_broken_link.file')
-- The tests are invoked with an absolute path to `busted` executable.
absolute_executable = arg[0]
-- Split the absolute_executable path into a directory and filename.
@@ -88,19 +88,19 @@ describe('fs.c', function()
os.remove('unit-test-directory/test_link.file')
os.remove('unit-test-directory/test_hlink.file')
os.remove('unit-test-directory/test_broken_link.file')
- luv.fs_rmdir('unit-test-directory')
+ uv.fs_rmdir('unit-test-directory')
end)
describe('os_dirname', function()
itp('returns OK and writes current directory to the buffer', function()
- local length = string.len(luv.cwd()) + 1
+ local length = string.len(uv.cwd()) + 1
local buf = cstr(length, '')
eq(OK, fs.os_dirname(buf, length))
- eq(luv.cwd(), ffi.string(buf))
+ eq(uv.cwd(), ffi.string(buf))
end)
itp('returns FAIL if the buffer is too small', function()
- local length = string.len(luv.cwd()) + 1
+ local length = string.len(uv.cwd()) + 1
local buf = cstr(length - 1, '')
eq(FAIL, fs.os_dirname(buf, length - 1))
end)
@@ -115,8 +115,8 @@ describe('fs.c', function()
eq(OK, fs.os_dirname(expected_cwd, length))
-- os_chdir returns 0 for success, not OK (1).
- neq(0, fs.os_chdir('~')) -- fail
- neq(0, fs.os_chdir('~/')) -- fail
+ neq(0, fs.os_chdir('~')) -- fail
+ neq(0, fs.os_chdir('~/')) -- fail
eq(OK, fs.os_dirname(cwd, length))
-- CWD did not change.
@@ -197,24 +197,24 @@ describe('fs.c', function()
itp('returns the absolute path when given an executable inside $PATH', function()
local fullpath = exe('ls')
- eq(1, fs.path_is_absolute(to_cstr(fullpath)))
+ eq(true, fs.path_is_absolute(to_cstr(fullpath)))
end)
itp('returns the absolute path when given an executable relative to the current dir', function()
- local old_dir = luv.cwd()
+ local old_dir = uv.cwd()
- luv.chdir(directory)
+ uv.chdir(directory)
-- Rely on currentdir to resolve symlinks, if any. Testing against
-- the absolute path taken from arg[0] may result in failure where
-- the path has a symlink in it.
- local canonical = luv.cwd() .. '/' .. executable_name
+ local canonical = uv.cwd() .. '/' .. executable_name
local expected = exe(canonical)
local relative_executable = './' .. executable_name
local res = exe(relative_executable)
-- Don't test yet; we need to chdir back first.
- luv.chdir(old_dir)
+ uv.chdir(old_dir)
eq(expected, res)
end)
end)
@@ -276,39 +276,42 @@ describe('fs.c', function()
describe('os_fchown', function()
local filename = 'unit-test-directory/test.file'
itp('does not change owner and group if respective IDs are equal to -1', function()
- local uid = luv.fs_stat(filename).uid
- local gid = luv.fs_stat(filename).gid
+ local uid = uv.fs_stat(filename).uid
+ local gid = uv.fs_stat(filename).gid
eq(0, os_fchown(filename, -1, -1))
- eq(uid, luv.fs_stat(filename).uid)
- return eq(gid, luv.fs_stat(filename).gid)
+ eq(uid, uv.fs_stat(filename).uid)
+ return eq(gid, uv.fs_stat(filename).gid)
end)
-- Some systems may not have `id` utility.
- if (os.execute('id -G > /dev/null 2>&1') ~= 0) then
+ if os.execute('id -G > /dev/null 2>&1') ~= 0 then
pending('skipped (missing `id` utility)', function() end)
else
- itp('owner of a file may change the group of the file to any group of which that owner is a member', function()
- local file_gid = luv.fs_stat(filename).gid
-
- -- Gets ID of any group of which current user is a member except the
- -- group that owns the file.
- local id_fd = io.popen('id -G')
- local new_gid = id_fd:read('*n')
- if (new_gid == file_gid) then
- new_gid = id_fd:read('*n')
+ itp(
+ 'owner of a file may change the group of the file to any group of which that owner is a member',
+ function()
+ local file_gid = uv.fs_stat(filename).gid
+
+ -- Gets ID of any group of which current user is a member except the
+ -- group that owns the file.
+ local id_fd = io.popen('id -G')
+ local new_gid = id_fd:read('*n')
+ if new_gid == file_gid then
+ new_gid = id_fd:read('*n')
+ end
+ id_fd:close()
+
+ -- User can be a member of only one group.
+ -- In that case we can not perform this test.
+ if new_gid then
+ eq(0, (os_fchown(filename, -1, new_gid)))
+ eq(new_gid, uv.fs_stat(filename).gid)
+ end
end
- id_fd:close()
-
- -- User can be a member of only one group.
- -- In that case we can not perform this test.
- if new_gid then
- eq(0, (os_fchown(filename, -1, new_gid)))
- eq(new_gid, luv.fs_stat(filename).gid)
- end
- end)
+ )
end
- if (ffi.os == 'Windows' or ffi.C.geteuid() == 0) then
+ if ffi.os == 'Windows' or ffi.C.geteuid() == 0 then
pending('skipped (uv_fs_chown is no-op on Windows)', function() end)
else
itp('returns nonzero if process has not enough permissions', function()
@@ -318,7 +321,6 @@ describe('fs.c', function()
end
end)
-
describe('os_file_is_readable', function()
itp('returns false if the file is not readable', function()
local perm = os_getperm('unit-test-directory/test.file')
@@ -330,13 +332,11 @@ describe('fs.c', function()
end)
itp('returns false if the file does not exist', function()
- eq(false, os_file_is_readable(
- 'unit-test-directory/what_are_you_smoking.gif'))
+ eq(false, os_file_is_readable('unit-test-directory/what_are_you_smoking.gif'))
end)
itp('returns true if the file is readable', function()
- eq(true, os_file_is_readable(
- 'unit-test-directory/test.file'))
+ eq(true, os_file_is_readable('unit-test-directory/test.file'))
end)
end)
@@ -387,7 +387,7 @@ describe('fs.c', function()
else
buf = ffi.new('char[?]', size + 1, ('\0'):rep(size))
end
- local eof = ffi.new('bool[?]', 1, {true})
+ local eof = ffi.new('bool[?]', 1, { true })
local ret2 = fs.os_read(fd, eof, buf, size, false)
local ret1 = eof[0]
local ret3 = ''
@@ -400,16 +400,16 @@ describe('fs.c', function()
local bufs = {}
for i, size in ipairs(sizes) do
bufs[i] = {
- iov_base=ffi.new('char[?]', size + 1, ('\0'):rep(size)),
- iov_len=size,
+ iov_base = ffi.new('char[?]', size + 1, ('\0'):rep(size)),
+ iov_len = size,
}
end
local iov = ffi.new('struct iovec[?]', #sizes, bufs)
- local eof = ffi.new('bool[?]', 1, {true})
+ local eof = ffi.new('bool[?]', 1, { true })
local ret2 = fs.os_readv(fd, eof, iov, #sizes, false)
local ret1 = eof[0]
local ret3 = {}
- for i = 1,#sizes do
+ for i = 1, #sizes do
-- Warning: iov may not be used.
ret3[i] = ffi.string(bufs[i].iov_base, bufs[i].iov_len)
end
@@ -445,7 +445,7 @@ describe('fs.c', function()
eq(OK, (os_rename(test, not_exist)))
eq(false, (os_path_exists(test)))
eq(true, (os_path_exists(not_exist)))
- eq(OK, (os_rename(not_exist, test))) -- restore test file
+ eq(OK, (os_rename(not_exist, test))) -- restore test file
end)
itp('fail if source file does not exist', function()
@@ -494,14 +494,19 @@ describe('fs.c', function()
local dup0 = fs.os_dup(0)
local dup1 = fs.os_dup(1)
local dup2 = fs.os_dup(2)
- local tbl = {[0]=true, [1]=true, [2]=true,
- [tonumber(dup0)]=true, [tonumber(dup1)]=true,
- [tonumber(dup2)]=true}
+ local tbl = {
+ [0] = true,
+ [1] = true,
+ [2] = true,
+ [tonumber(dup0)] = true,
+ [tonumber(dup1)] = true,
+ [tonumber(dup2)] = true,
+ }
local i = 0
for _, _ in pairs(tbl) do
i = i + 1
end
- eq(i, 6) -- All fds must be unique
+ eq(i, 6) -- All fds must be unique
end)
end)
@@ -522,12 +527,15 @@ describe('fs.c', function()
eq(ffi.C.UV_ENOENT, (os_open('non-existing-file', ffi.C.kO_RDWR, 0)))
end)
- itp('returns non-negative for O_CREAT on a non-existing file which then can be closed', function()
- assert_file_does_not_exist(new_file)
- local fd = os_open(new_file, ffi.C.kO_CREAT, 0)
- assert.is_true(0 <= fd)
- eq(0, os_close(fd))
- end)
+ itp(
+ 'returns non-negative for O_CREAT on a non-existing file which then can be closed',
+ function()
+ assert_file_does_not_exist(new_file)
+ local fd = os_open(new_file, ffi.C.kO_CREAT, 0)
+ assert.is_true(0 <= fd)
+ eq(0, os_close(fd))
+ end
+ )
itp('returns non-negative for O_CREAT on a existing file which then can be closed', function()
assert_file_exists(existing_file)
@@ -544,26 +552,29 @@ describe('fs.c', function()
itp('sets `rwx` permissions for O_CREAT 700 which then can be closed', function()
assert_file_does_not_exist(new_file)
--create the file
- local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber("700", 8))
+ local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber('700', 8))
--verify permissions
- eq(33216, luv.fs_stat(new_file).mode)
+ eq(33216, uv.fs_stat(new_file).mode)
eq(0, os_close(fd))
end)
itp('sets `rw` permissions for O_CREAT 600 which then can be closed', function()
assert_file_does_not_exist(new_file)
--create the file
- local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber("600", 8))
+ local fd = os_open(new_file, ffi.C.kO_CREAT, tonumber('600', 8))
--verify permissions
- eq(33152, luv.fs_stat(new_file).mode)
+ eq(33152, uv.fs_stat(new_file).mode)
eq(0, os_close(fd))
end)
- itp('returns a non-negative file descriptor for an existing file which then can be closed', function()
- local fd = os_open(existing_file, ffi.C.kO_RDWR, 0)
- assert.is_true(0 <= fd)
- eq(0, os_close(fd))
- end)
+ itp(
+ 'returns a non-negative file descriptor for an existing file which then can be closed',
+ function()
+ local fd = os_open(existing_file, ffi.C.kO_RDWR, 0)
+ assert.is_true(0 <= fd)
+ eq(0, os_close(fd))
+ end
+ )
end)
describe('os_close', function()
@@ -589,43 +600,48 @@ describe('fs.c', function()
itp('can read zero bytes from a file', function()
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
ok(fd >= 0)
- eq({false, 0, ''}, {os_read(fd, nil)})
- eq({false, 0, ''}, {os_read(fd, 0)})
+ eq({ false, 0, '' }, { os_read(fd, nil) })
+ eq({ false, 0, '' }, { os_read(fd, 0) })
eq(0, os_close(fd))
end)
itp('can read from a file multiple times', function()
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
ok(fd >= 0)
- eq({false, 2, '\000\001'}, {os_read(fd, 2)})
- eq({false, 2, '\002\003'}, {os_read(fd, 2)})
+ eq({ false, 2, '\000\001' }, { os_read(fd, 2) })
+ eq({ false, 2, '\002\003' }, { os_read(fd, 2) })
eq(0, os_close(fd))
end)
itp('can read the whole file at once and then report eof', function()
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
ok(fd >= 0)
- eq({false, #fcontents, fcontents}, {os_read(fd, #fcontents)})
- eq({true, 0, ('\0'):rep(#fcontents)}, {os_read(fd, #fcontents)})
+ eq({ false, #fcontents, fcontents }, { os_read(fd, #fcontents) })
+ eq({ true, 0, ('\0'):rep(#fcontents) }, { os_read(fd, #fcontents) })
eq(0, os_close(fd))
end)
itp('can read the whole file in two calls, one partially', function()
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
ok(fd >= 0)
- eq({false, #fcontents * 3/4, fcontents:sub(1, #fcontents * 3/4)},
- {os_read(fd, #fcontents * 3/4)})
- eq({true,
- (#fcontents * 1/4),
- fcontents:sub(#fcontents * 3/4 + 1) .. ('\0'):rep(#fcontents * 2/4)},
- {os_read(fd, #fcontents * 3/4)})
+ eq(
+ { false, #fcontents * 3 / 4, fcontents:sub(1, #fcontents * 3 / 4) },
+ { os_read(fd, #fcontents * 3 / 4) }
+ )
+ eq({
+ true,
+ (#fcontents * 1 / 4),
+ fcontents:sub(#fcontents * 3 / 4 + 1) .. ('\0'):rep(#fcontents * 2 / 4),
+ }, { os_read(fd, #fcontents * 3 / 4) })
eq(0, os_close(fd))
end)
end)
describe('os_readv', function()
-- Function may be absent
- if not pcall(function() return fs.os_readv end) then
+ if not pcall(function()
+ return fs.os_readv
+ end) then
return
end
local file = 'test-unit-os-fs_spec-os_readv.dat'
@@ -643,45 +659,53 @@ describe('fs.c', function()
itp('can read zero bytes from a file', function()
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
ok(fd >= 0)
- eq({false, 0, {}}, {os_readv(fd, {})})
- eq({false, 0, {'', '', ''}}, {os_readv(fd, {0, 0, 0})})
+ eq({ false, 0, {} }, { os_readv(fd, {}) })
+ eq({ false, 0, { '', '', '' } }, { os_readv(fd, { 0, 0, 0 }) })
eq(0, os_close(fd))
end)
itp('can read from a file multiple times to a differently-sized buffers', function()
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
ok(fd >= 0)
- eq({false, 2, {'\000\001'}}, {os_readv(fd, {2})})
- eq({false, 5, {'\002\003', '\004\005\006'}}, {os_readv(fd, {2, 3})})
+ eq({ false, 2, { '\000\001' } }, { os_readv(fd, { 2 }) })
+ eq({ false, 5, { '\002\003', '\004\005\006' } }, { os_readv(fd, { 2, 3 }) })
eq(0, os_close(fd))
end)
itp('can read the whole file at once and then report eof', function()
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
ok(fd >= 0)
- eq({false,
- #fcontents,
- {fcontents:sub(1, #fcontents * 1/4),
- fcontents:sub(#fcontents * 1/4 + 1, #fcontents * 3/4),
- fcontents:sub(#fcontents * 3/4 + 1, #fcontents * 15/16),
- fcontents:sub(#fcontents * 15/16 + 1, #fcontents)}},
- {os_readv(fd, {#fcontents * 1/4,
- #fcontents * 2/4,
- #fcontents * 3/16,
- #fcontents * 1/16})})
- eq({true, 0, {'\0'}}, {os_readv(fd, {1})})
+ eq({
+ false,
+ #fcontents,
+ {
+ fcontents:sub(1, #fcontents * 1 / 4),
+ fcontents:sub(#fcontents * 1 / 4 + 1, #fcontents * 3 / 4),
+ fcontents:sub(#fcontents * 3 / 4 + 1, #fcontents * 15 / 16),
+ fcontents:sub(#fcontents * 15 / 16 + 1, #fcontents),
+ },
+ }, {
+ os_readv(
+ fd,
+ { #fcontents * 1 / 4, #fcontents * 2 / 4, #fcontents * 3 / 16, #fcontents * 1 / 16 }
+ ),
+ })
+ eq({ true, 0, { '\0' } }, { os_readv(fd, { 1 }) })
eq(0, os_close(fd))
end)
itp('can read the whole file in two calls, one partially', function()
local fd = os_open(file, ffi.C.kO_RDONLY, 0)
ok(fd >= 0)
- eq({false, #fcontents * 3/4, {fcontents:sub(1, #fcontents * 3/4)}},
- {os_readv(fd, {#fcontents * 3/4})})
- eq({true,
- (#fcontents * 1/4),
- {fcontents:sub(#fcontents * 3/4 + 1) .. ('\0'):rep(#fcontents * 2/4)}},
- {os_readv(fd, {#fcontents * 3/4})})
+ eq(
+ { false, #fcontents * 3 / 4, { fcontents:sub(1, #fcontents * 3 / 4) } },
+ { os_readv(fd, { #fcontents * 3 / 4 }) }
+ )
+ eq({
+ true,
+ (#fcontents * 1 / 4),
+ { fcontents:sub(#fcontents * 3 / 4 + 1) .. ('\0'):rep(#fcontents * 2 / 4) },
+ }, { os_readv(fd, { #fcontents * 3 / 4 }) })
eq(0, os_close(fd))
end)
end)
@@ -744,8 +768,8 @@ describe('fs.c', function()
end
local function os_mkdir_recurse(path, mode)
- local failed_str = ffi.new('char *[1]', {nil})
- local created_str = ffi.new('char *[1]', {nil})
+ local failed_str = ffi.new('char *[1]', { nil })
+ local created_str = ffi.new('char *[1]', { nil })
local ret = fs.os_mkdir_recurse(path, mode, failed_str, created_str)
local failed_dir = failed_str[0]
if failed_dir ~= nil then
@@ -769,7 +793,7 @@ describe('fs.c', function()
eq(false, (os_isdir('unit-test-directory/new-dir')))
eq(0, (os_mkdir('unit-test-directory/new-dir', mode)))
eq(true, (os_isdir('unit-test-directory/new-dir')))
- luv.fs_rmdir('unit-test-directory/new-dir')
+ uv.fs_rmdir('unit-test-directory/new-dir')
end)
end)
@@ -784,8 +808,7 @@ describe('fs.c', function()
itp('fails to create a directory where there is a file', function()
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
- local ret, failed_dir, created_dir = os_mkdir_recurse(
- 'unit-test-directory/test.file', mode)
+ local ret, failed_dir, created_dir = os_mkdir_recurse('unit-test-directory/test.file', mode)
neq(0, ret)
eq('unit-test-directory/test.file', failed_dir)
eq(nil, created_dir)
@@ -793,8 +816,8 @@ describe('fs.c', function()
itp('fails to create a directory where there is a file in path', function()
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
- local ret, failed_dir, created_dir = os_mkdir_recurse(
- 'unit-test-directory/test.file/test', mode)
+ local ret, failed_dir, created_dir =
+ os_mkdir_recurse('unit-test-directory/test.file/test', mode)
neq(0, ret)
eq('unit-test-directory/test.file', failed_dir)
eq(nil, created_dir)
@@ -802,44 +825,44 @@ describe('fs.c', function()
itp('succeeds to create a directory', function()
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
- local ret, failed_dir, created_dir = os_mkdir_recurse(
- 'unit-test-directory/new-dir-recurse', mode)
+ local ret, failed_dir, created_dir =
+ os_mkdir_recurse('unit-test-directory/new-dir-recurse', mode)
eq(0, ret)
eq(nil, failed_dir)
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
eq(true, os_isdir('unit-test-directory/new-dir-recurse'))
- luv.fs_rmdir('unit-test-directory/new-dir-recurse')
+ uv.fs_rmdir('unit-test-directory/new-dir-recurse')
eq(false, os_isdir('unit-test-directory/new-dir-recurse'))
end)
itp('succeeds to create a directory ending with ///', function()
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
- local ret, failed_dir, created_dir = os_mkdir_recurse(
- 'unit-test-directory/new-dir-recurse///', mode)
+ local ret, failed_dir, created_dir =
+ os_mkdir_recurse('unit-test-directory/new-dir-recurse///', mode)
eq(0, ret)
eq(nil, failed_dir)
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
eq(true, os_isdir('unit-test-directory/new-dir-recurse'))
- luv.fs_rmdir('unit-test-directory/new-dir-recurse')
+ uv.fs_rmdir('unit-test-directory/new-dir-recurse')
eq(false, os_isdir('unit-test-directory/new-dir-recurse'))
end)
itp('succeeds to create a directory ending with /', function()
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
- local ret, failed_dir, created_dir = os_mkdir_recurse(
- 'unit-test-directory/new-dir-recurse/', mode)
+ local ret, failed_dir, created_dir =
+ os_mkdir_recurse('unit-test-directory/new-dir-recurse/', mode)
eq(0, ret)
eq(nil, failed_dir)
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
eq(true, os_isdir('unit-test-directory/new-dir-recurse'))
- luv.fs_rmdir('unit-test-directory/new-dir-recurse')
+ uv.fs_rmdir('unit-test-directory/new-dir-recurse')
eq(false, os_isdir('unit-test-directory/new-dir-recurse'))
end)
itp('succeeds to create a directory tree', function()
local mode = ffi.C.kS_IRUSR + ffi.C.kS_IWUSR + ffi.C.kS_IXUSR
- local ret, failed_dir, created_dir = os_mkdir_recurse(
- 'unit-test-directory/new-dir-recurse/1/2/3', mode)
+ local ret, failed_dir, created_dir =
+ os_mkdir_recurse('unit-test-directory/new-dir-recurse/1/2/3', mode)
eq(0, ret)
eq(nil, failed_dir)
ok(endswith(created_dir, 'unit-test-directory/new-dir-recurse'))
@@ -847,10 +870,10 @@ describe('fs.c', function()
eq(true, os_isdir('unit-test-directory/new-dir-recurse/1'))
eq(true, os_isdir('unit-test-directory/new-dir-recurse/1/2'))
eq(true, os_isdir('unit-test-directory/new-dir-recurse/1/2/3'))
- luv.fs_rmdir('unit-test-directory/new-dir-recurse/1/2/3')
- luv.fs_rmdir('unit-test-directory/new-dir-recurse/1/2')
- luv.fs_rmdir('unit-test-directory/new-dir-recurse/1')
- luv.fs_rmdir('unit-test-directory/new-dir-recurse')
+ uv.fs_rmdir('unit-test-directory/new-dir-recurse/1/2/3')
+ uv.fs_rmdir('unit-test-directory/new-dir-recurse/1/2')
+ uv.fs_rmdir('unit-test-directory/new-dir-recurse/1')
+ uv.fs_rmdir('unit-test-directory/new-dir-recurse')
eq(false, os_isdir('unit-test-directory/new-dir-recurse'))
end)
end)
@@ -1015,7 +1038,7 @@ describe('fs.c', function()
file:write('some bytes to get filesize != 0')
file:flush()
file:close()
- local size = luv.fs_stat(path).size
+ local size = uv.fs_stat(path).size
local info = file_info_new()
assert.is_true(fs.os_fileinfo(path, info))
eq(size, fs.os_fileinfo_size(info))
@@ -1029,7 +1052,7 @@ describe('fs.c', function()
local info = file_info_new()
assert.is_true(fs.os_fileinfo(path, info))
eq(1, fs.os_fileinfo_hardlinks(info))
- luv.fs_link(path, path_link)
+ uv.fs_link(path, path_link)
assert.is_true(fs.os_fileinfo(path, info))
eq(2, fs.os_fileinfo_hardlinks(info))
end)
@@ -1038,7 +1061,7 @@ describe('fs.c', function()
describe('os_fileinfo_blocksize', function()
itp('returns the correct blocksize of a file', function()
local path = 'unit-test-directory/test.file'
- local blksize = luv.fs_stat(path).blksize
+ local blksize = uv.fs_stat(path).blksize
local info = file_info_new()
assert.is_true(fs.os_fileinfo(path, info))
if blksize then
diff --git a/test/unit/os/shell_spec.lua b/test/unit/os/shell_spec.lua
index 3fb1afed44..ae162f2317 100644
--- a/test/unit/os/shell_spec.lua
+++ b/test/unit/os/shell_spec.lua
@@ -21,9 +21,7 @@ describe('shell functions', function()
end)
local function shell_build_argv(cmd, extra_args)
- local res = cimported.shell_build_argv(
- cmd and to_cstr(cmd),
- extra_args and to_cstr(extra_args))
+ local res = cimported.shell_build_argv(cmd and to_cstr(cmd), extra_args and to_cstr(extra_args))
-- `res` is zero-indexed (C pointer, not Lua table)!
local argc = 0
local ret = {}
@@ -40,9 +38,7 @@ describe('shell functions', function()
local function shell_argv_to_str(argv_table)
-- C string array (char **).
- local argv = (argv_table
- and ffi.new("char*[?]", #argv_table+1)
- or NULL)
+ local argv = (argv_table and ffi.new('char*[?]', #argv_table + 1) or NULL)
local argc = 1
while argv_table ~= nil and argv_table[argc] ~= nil do
@@ -64,8 +60,7 @@ describe('shell functions', function()
local output = ffi.new('char *[1]')
local nread = ffi.new('size_t[1]')
- local argv = ffi.cast('char**',
- cimported.shell_build_argv(to_cstr(cmd), nil))
+ local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr(cmd), nil))
local status = cimported.os_system(argv, input_or, input_len, output, nread)
return status, intern(output[0], nread[0])
@@ -101,37 +96,35 @@ describe('shell functions', function()
describe('shell_build_argv', function()
itp('works with NULL arguments', function()
- eq({'/bin/sh'}, shell_build_argv(nil, nil))
+ eq({ '/bin/sh' }, shell_build_argv(nil, nil))
end)
itp('works with cmd', function()
- eq({'/bin/sh', '-c', 'abc def'}, shell_build_argv('abc def', nil))
+ eq({ '/bin/sh', '-c', 'abc def' }, shell_build_argv('abc def', nil))
end)
itp('works with extra_args', function()
- eq({'/bin/sh', 'ghi jkl'}, shell_build_argv(nil, 'ghi jkl'))
+ eq({ '/bin/sh', 'ghi jkl' }, shell_build_argv(nil, 'ghi jkl'))
end)
itp('works with cmd and extra_args', function()
- eq({'/bin/sh', 'ghi jkl', '-c', 'abc def'}, shell_build_argv('abc def', 'ghi jkl'))
+ eq({ '/bin/sh', 'ghi jkl', '-c', 'abc def' }, shell_build_argv('abc def', 'ghi jkl'))
end)
itp('splits and unquotes &shell and &shellcmdflag', function()
cimported.p_sh = to_cstr('/Program" "Files/zsh -f')
cimported.p_shcf = to_cstr('-x -o "sh word split" "-"c')
- eq({'/Program Files/zsh', '-f',
- 'ghi jkl',
- '-x', '-o', 'sh word split',
- '-c', 'abc def'},
- shell_build_argv('abc def', 'ghi jkl'))
+ eq(
+ { '/Program Files/zsh', '-f', 'ghi jkl', '-x', '-o', 'sh word split', '-c', 'abc def' },
+ shell_build_argv('abc def', 'ghi jkl')
+ )
end)
itp('applies shellxescape (p_sxe) and shellxquote (p_sxq)', function()
cimported.p_sxq = to_cstr('(')
cimported.p_sxe = to_cstr('"&|<>()@^')
- local argv = ffi.cast('char**',
- cimported.shell_build_argv(to_cstr('echo &|<>()@^'), nil))
+ local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo &|<>()@^'), nil))
eq(ffi.string(argv[0]), '/bin/sh')
eq(ffi.string(argv[1]), '-c')
eq(ffi.string(argv[2]), '(echo ^&^|^<^>^(^)^@^^)')
@@ -142,8 +135,7 @@ describe('shell functions', function()
cimported.p_sxq = to_cstr('"(')
cimported.p_sxe = to_cstr('"&|<>()@^')
- local argv = ffi.cast('char**', cimported.shell_build_argv(
- to_cstr('echo -n some text'), nil))
+ local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
eq(ffi.string(argv[0]), '/bin/sh')
eq(ffi.string(argv[1]), '-c')
eq(ffi.string(argv[2]), '"(echo -n some text)"')
@@ -154,8 +146,7 @@ describe('shell functions', function()
cimported.p_sxq = to_cstr('"')
cimported.p_sxe = to_cstr('')
- local argv = ffi.cast('char**', cimported.shell_build_argv(
- to_cstr('echo -n some text'), nil))
+ local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
eq(ffi.string(argv[0]), '/bin/sh')
eq(ffi.string(argv[1]), '-c')
eq(ffi.string(argv[2]), '"echo -n some text"')
@@ -163,8 +154,7 @@ describe('shell functions', function()
end)
itp('with empty shellxquote/shellxescape', function()
- local argv = ffi.cast('char**', cimported.shell_build_argv(
- to_cstr('echo -n some text'), nil))
+ local argv = ffi.cast('char**', cimported.shell_build_argv(to_cstr('echo -n some text'), nil))
eq(ffi.string(argv[0]), '/bin/sh')
eq(ffi.string(argv[1]), '-c')
eq(ffi.string(argv[2]), 'echo -n some text')
@@ -176,9 +166,11 @@ describe('shell functions', function()
eq('', shell_argv_to_str({ nil }))
eq("''", shell_argv_to_str({ '' }))
eq("'foo' '' 'bar'", shell_argv_to_str({ 'foo', '', 'bar' }))
- eq("'/bin/sh' '-c' 'abc def'", shell_argv_to_str({'/bin/sh', '-c', 'abc def'}))
- eq("'abc def' 'ghi jkl'", shell_argv_to_str({'abc def', 'ghi jkl'}))
- eq("'/bin/sh' '-c' 'abc def' '"..('x'):rep(225).."...",
- shell_argv_to_str({'/bin/sh', '-c', 'abc def', ('x'):rep(999)}))
+ eq("'/bin/sh' '-c' 'abc def'", shell_argv_to_str({ '/bin/sh', '-c', 'abc def' }))
+ eq("'abc def' 'ghi jkl'", shell_argv_to_str({ 'abc def', 'ghi jkl' }))
+ eq(
+ "'/bin/sh' '-c' 'abc def' '" .. ('x'):rep(225) .. '...',
+ shell_argv_to_str({ '/bin/sh', '-c', 'abc def', ('x'):rep(999) })
+ )
end)
end)
diff --git a/test/unit/path_spec.lua b/test/unit/path_spec.lua
index 23f71cfe78..c564ec119e 100644
--- a/test/unit/path_spec.lua
+++ b/test/unit/path_spec.lua
@@ -1,4 +1,4 @@
-local luv = require('luv')
+local uv = vim.uv
local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
@@ -27,7 +27,7 @@ describe('path.c', function()
end)
teardown(function()
- luv.fs_rmdir('unit-test-directory')
+ uv.fs_rmdir('unit-test-directory')
end)
local function path_full_dir_name(directory, buf, len)
@@ -37,34 +37,34 @@ describe('path.c', function()
before_each(function()
-- Create empty string buffer which will contain the resulting path.
- length = string.len(luv.cwd()) + 22
+ length = string.len(uv.cwd()) + 22
buffer = cstr(length, '')
end)
itp('returns the absolute directory name of a given relative one', function()
local result = path_full_dir_name('..', buffer, length)
eq(OK, result)
- local old_dir = luv.cwd()
- luv.chdir('..')
- local expected = luv.cwd()
- luv.chdir(old_dir)
+ local old_dir = uv.cwd()
+ uv.chdir('..')
+ local expected = uv.cwd()
+ uv.chdir(old_dir)
eq(expected, (ffi.string(buffer)))
end)
itp('returns the current directory name if the given string is empty', function()
eq(OK, (path_full_dir_name('', buffer, length)))
- eq(luv.cwd(), (ffi.string(buffer)))
+ eq(uv.cwd(), (ffi.string(buffer)))
end)
itp('works with a normal relative dir', function()
local result = path_full_dir_name('unit-test-directory', buffer, length)
- eq(luv.cwd() .. '/unit-test-directory', (ffi.string(buffer)))
+ eq(uv.cwd() .. '/unit-test-directory', (ffi.string(buffer)))
eq(OK, result)
end)
itp('works with a non-existing relative dir', function()
local result = path_full_dir_name('does-not-exist', buffer, length)
- eq(luv.cwd() .. '/does-not-exist', (ffi.string(buffer)))
+ eq(uv.cwd() .. '/does-not-exist', (ffi.string(buffer)))
eq(OK, result)
end)
@@ -184,7 +184,7 @@ describe('path.c', function()
itp('returns the executable name of an invocation given a relative invocation', function()
local invk, len = invocation_path_tail('directory/exe a b c')
- compare("exe a b c", invk, len)
+ compare('exe a b c', invk, len)
eq(3, len)
end)
@@ -202,7 +202,7 @@ describe('path.c', function()
itp('does not count arguments to the executable as part of its path', function()
local invk, len = invocation_path_tail('exe a/b\\c')
- compare("exe a/b\\c", invk, len)
+ compare('exe a/b\\c', invk, len)
eq(3, len)
end)
@@ -212,17 +212,17 @@ describe('path.c', function()
end)
itp('is equivalent to path_tail when args do not contain a path separator', function()
- local ptail = cimp.path_tail(to_cstr("a/b/c x y z"))
+ local ptail = cimp.path_tail(to_cstr('a/b/c x y z'))
neq(NULL, ptail)
local tail = ffi.string(ptail)
- local invk, _ = invocation_path_tail("a/b/c x y z")
+ local invk, _ = invocation_path_tail('a/b/c x y z')
eq(tail, ffi.string(invk))
end)
itp('is not equivalent to path_tail when args contain a path separator', function()
- local ptail = cimp.path_tail(to_cstr("a/b/c x y/z"))
+ local ptail = cimp.path_tail(to_cstr('a/b/c x y/z'))
neq(NULL, ptail)
- local invk, _ = invocation_path_tail("a/b/c x y/z")
+ local invk, _ = invocation_path_tail('a/b/c x y/z')
neq((ffi.string(ptail)), (ffi.string(invk)))
end)
end)
@@ -270,27 +270,27 @@ describe('path.c', function()
end)
describe('path_try_shorten_fname', function()
- local cwd = luv.cwd()
+ local cwd = uv.cwd()
before_each(function()
mkdir('ut_directory')
end)
after_each(function()
- luv.chdir(cwd)
- luv.fs_rmdir('ut_directory')
+ uv.chdir(cwd)
+ uv.fs_rmdir('ut_directory')
end)
describe('path_try_shorten_fname', function()
itp('returns shortened path if possible', function()
- luv.chdir('ut_directory')
- local full = to_cstr(luv.cwd() .. '/subdir/file.txt')
+ uv.chdir('ut_directory')
+ local full = to_cstr(uv.cwd() .. '/subdir/file.txt')
eq('subdir/file.txt', (ffi.string(cimp.path_try_shorten_fname(full))))
end)
itp('returns `full_path` if a shorter version is not possible', function()
- local old = luv.cwd()
- luv.chdir('ut_directory')
+ local old = uv.cwd()
+ uv.chdir('ut_directory')
local full = old .. '/subdir/file.txt'
eq(full, (ffi.string(cimp.path_try_shorten_fname(to_cstr(full)))))
end)
@@ -302,14 +302,14 @@ describe('path_try_shorten_fname', function()
end)
describe('path.c path_guess_exepath', function()
- local cwd = luv.cwd()
+ local cwd = uv.cwd()
- for _,name in ipairs({'./nvim', '.nvim', 'foo/nvim'}) do
- itp('"'..name..'" returns name catenated with CWD', function()
+ for _, name in ipairs({ './nvim', '.nvim', 'foo/nvim' }) do
+ itp('"' .. name .. '" returns name catenated with CWD', function()
local bufsize = 255
local buf = cstr(bufsize, '')
cimp.path_guess_exepath(name, buf, bufsize)
- eq(cwd..'/'..name, ffi.string(buf))
+ eq(cwd .. '/' .. name, ffi.string(buf))
end)
end
@@ -331,10 +331,10 @@ describe('path.c path_guess_exepath', function()
itp('does not crash if $PATH item exceeds MAXPATHL', function()
local orig_path_env = os.getenv('PATH')
- local name = 'cat' -- Some executable in $PATH.
+ local name = 'cat' -- Some executable in $PATH.
local bufsize = 255
local buf = cstr(bufsize, '')
- local insane_path = orig_path_env..':'..(("x/"):rep(4097))
+ local insane_path = orig_path_env .. ':' .. (('x/'):rep(4097))
cimp.os_setenv('PATH', insane_path, true)
cimp.path_guess_exepath(name, buf, bufsize)
@@ -345,7 +345,7 @@ describe('path.c path_guess_exepath', function()
end)
itp('returns full path found in $PATH', function()
- local name = 'cat' -- Some executable in $PATH.
+ local name = 'cat' -- Some executable in $PATH.
local bufsize = 255
local buf = cstr(bufsize, '')
cimp.path_guess_exepath(name, buf, bufsize)
@@ -356,7 +356,7 @@ end)
describe('path.c', function()
setup(function()
- mkdir('unit-test-directory');
+ mkdir('unit-test-directory')
io.open('unit-test-directory/test.file', 'w'):close()
-- Since the tests are executed, they are called by an executable. We use
@@ -365,12 +365,12 @@ describe('path.c', function()
-- Split absolute_executable into a directory and the actual file name for
-- later usage.
- local directory, executable_name = string.match(absolute_executable, '^(.*)/(.*)$') -- luacheck: ignore
+ local directory, executable_name = string.match(absolute_executable, '^(.*)/(.*)$') -- luacheck: ignore
end)
teardown(function()
os.remove('unit-test-directory/test.file')
- luv.fs_rmdir('unit-test-directory')
+ uv.fs_rmdir('unit-test-directory')
end)
describe('vim_FullName', function()
@@ -422,7 +422,7 @@ describe('path.c', function()
end)
itp('concatenates filename if it does not contain a slash', function()
- local expected = luv.cwd() .. '/test.file'
+ local expected = uv.cwd() .. '/test.file'
local filename = 'test.file'
local buflen = get_buf_len(expected, filename)
local do_expand = 1
@@ -432,7 +432,7 @@ describe('path.c', function()
end)
itp('concatenates directory name if it does not contain a slash', function()
- local expected = luv.cwd() .. '/..'
+ local expected = uv.cwd() .. '/..'
local filename = '..'
local buflen = get_buf_len(expected, filename)
local do_expand = 1
@@ -441,18 +441,21 @@ describe('path.c', function()
eq(OK, result)
end)
- itp('enters given directory (instead of just concatenating the strings) if possible and if path contains a slash', function()
- local old_dir = luv.cwd()
- luv.chdir('..')
- local expected = luv.cwd() .. '/test.file'
- luv.chdir(old_dir)
- local filename = '../test.file'
- local buflen = get_buf_len(expected, filename)
- local do_expand = 1
- local buf, result = vim_FullName(filename, buflen, do_expand)
- eq(expected, ffi.string(buf))
- eq(OK, result)
- end)
+ itp(
+ 'enters given directory (instead of just concatenating the strings) if possible and if path contains a slash',
+ function()
+ local old_dir = uv.cwd()
+ uv.chdir('..')
+ local expected = uv.cwd() .. '/test.file'
+ uv.chdir(old_dir)
+ local filename = '../test.file'
+ local buflen = get_buf_len(expected, filename)
+ local do_expand = 1
+ local buf, result = vim_FullName(filename, buflen, do_expand)
+ eq(expected, ffi.string(buf))
+ eq(OK, result)
+ end
+ )
itp('just copies the path if it is already absolute and force=0', function()
local absolute_path = '/absolute/path'
@@ -474,7 +477,7 @@ describe('path.c', function()
end)
itp('works with some "normal" relative path with directories', function()
- local expected = luv.cwd() .. '/unit-test-directory/test.file'
+ local expected = uv.cwd() .. '/unit-test-directory/test.file'
local filename = 'unit-test-directory/test.file'
local buflen = get_buf_len(expected, filename)
local do_expand = 1
@@ -484,7 +487,7 @@ describe('path.c', function()
end)
itp('does not modify the given filename', function()
- local expected = luv.cwd() .. '/unit-test-directory/test.file'
+ local expected = uv.cwd() .. '/unit-test-directory/test.file'
local filename = to_cstr('unit-test-directory/test.file')
local buflen = string.len(expected) + 1
local buf = cstr(buflen, '')
@@ -507,7 +510,7 @@ describe('path.c', function()
end)
itp('does not remove trailing slash from non-existing relative directory #20847', function()
- local expected = luv.cwd() .. '/non_existing_dir/'
+ local expected = uv.cwd() .. '/non_existing_dir/'
local filename = 'non_existing_dir/'
local buflen = get_buf_len(expected, filename)
local do_expand = 1
@@ -517,7 +520,7 @@ describe('path.c', function()
end)
itp('expands "./" to the current directory #7117', function()
- local expected = luv.cwd() .. '/unit-test-directory/test.file'
+ local expected = uv.cwd() .. '/unit-test-directory/test.file'
local filename = './unit-test-directory/test.file'
local buflen = get_buf_len(expected, filename)
local do_expand = 1
@@ -527,7 +530,7 @@ describe('path.c', function()
end)
itp('collapses "foo/../foo" to "foo" #7117', function()
- local expected = luv.cwd() .. '/unit-test-directory/test.file'
+ local expected = uv.cwd() .. '/unit-test-directory/test.file'
local filename = 'unit-test-directory/../unit-test-directory/test.file'
local buflen = get_buf_len(expected, filename)
local do_expand = 1
@@ -544,8 +547,12 @@ describe('path.c', function()
return ffi.string(c_file)
end
- before_each(function() mkdir('CamelCase') end)
- after_each(function() luv.fs_rmdir('CamelCase') end)
+ before_each(function()
+ mkdir('CamelCase')
+ end)
+ after_each(function()
+ uv.fs_rmdir('CamelCase')
+ end)
if ffi.os == 'Windows' or ffi.os == 'OSX' then
itp('Corrects the case of file names in Mac and Windows', function()
@@ -565,14 +572,14 @@ describe('path.c', function()
local path1 = cstr(100, 'path1')
local to_append = to_cstr('path2')
eq(OK, (cimp.append_path(path1, to_append, 100)))
- eq("path1/path2", (ffi.string(path1)))
+ eq('path1/path2', (ffi.string(path1)))
end)
itp('joins given paths without adding an unnecessary slash', function()
local path1 = cstr(100, 'path1/')
local to_append = to_cstr('path2')
eq(OK, cimp.append_path(path1, to_append, 100))
- eq("path1/path2", (ffi.string(path1)))
+ eq('path1/path2', (ffi.string(path1)))
end)
itp('fails and uses filename if there is not enough space left for to_append', function()
@@ -610,15 +617,15 @@ describe('path.c', function()
end
itp('returns true if filename starts with a slash', function()
- eq(OK, path_is_absolute('/some/directory/'))
+ eq(true, path_is_absolute('/some/directory/'))
end)
itp('returns true if filename starts with a tilde', function()
- eq(OK, path_is_absolute('~/in/my/home~/directory'))
+ eq(true, path_is_absolute('~/in/my/home~/directory'))
end)
itp('returns false if filename starts not with slash nor tilde', function()
- eq(FAIL, path_is_absolute('not/in/my/home~/directory'))
+ eq(false, path_is_absolute('not/in/my/home~/directory'))
end)
end)
diff --git a/test/unit/preprocess.lua b/test/unit/preprocess.lua
index e356695c14..6294114e1e 100644
--- a/test/unit/preprocess.lua
+++ b/test/unit/preprocess.lua
@@ -1,7 +1,7 @@
-- helps managing loading different headers into the LuaJIT ffi. Untested on
-- windows, will probably need quite a bit of adjustment to run there.
-local ffi = require("ffi")
+local ffi = require('ffi')
local global_helpers = require('test.helpers')
local argss_to_cmd = global_helpers.argss_to_cmd
@@ -12,37 +12,37 @@ local repeated_read_cmd = global_helpers.repeated_read_cmd
--- @type Compiler[]
local ccs = {}
-local env_cc = os.getenv("CC")
+local env_cc = os.getenv('CC')
if env_cc then
- table.insert(ccs, {path = {"/usr/bin/env", env_cc}, type = "gcc"})
+ table.insert(ccs, { path = { '/usr/bin/env', env_cc }, type = 'gcc' })
end
-if ffi.os == "Windows" then
- table.insert(ccs, {path = {"cl"}, type = "msvc"})
+if ffi.os == 'Windows' then
+ table.insert(ccs, { path = { 'cl' }, type = 'msvc' })
end
-table.insert(ccs, {path = {"/usr/bin/env", "cc"}, type = "gcc"})
-table.insert(ccs, {path = {"/usr/bin/env", "gcc"}, type = "gcc"})
-table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.9"}, type = "gcc"})
-table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.8"}, type = "gcc"})
-table.insert(ccs, {path = {"/usr/bin/env", "gcc-4.7"}, type = "gcc"})
-table.insert(ccs, {path = {"/usr/bin/env", "clang"}, type = "clang"})
-table.insert(ccs, {path = {"/usr/bin/env", "icc"}, type = "gcc"})
+table.insert(ccs, { path = { '/usr/bin/env', 'cc' }, type = 'gcc' })
+table.insert(ccs, { path = { '/usr/bin/env', 'gcc' }, type = 'gcc' })
+table.insert(ccs, { path = { '/usr/bin/env', 'gcc-4.9' }, type = 'gcc' })
+table.insert(ccs, { path = { '/usr/bin/env', 'gcc-4.8' }, type = 'gcc' })
+table.insert(ccs, { path = { '/usr/bin/env', 'gcc-4.7' }, type = 'gcc' })
+table.insert(ccs, { path = { '/usr/bin/env', 'clang' }, type = 'clang' })
+table.insert(ccs, { path = { '/usr/bin/env', 'icc' }, type = 'gcc' })
-- parse Makefile format dependencies into a Lua table
--- @param deps string
--- @return string[]
local function parse_make_deps(deps)
-- remove line breaks and line concatenators
- deps = deps:gsub("\n", ""):gsub("\\", "")
+ deps = deps:gsub('\n', ''):gsub('\\', '')
-- remove the Makefile "target:" element
- deps = deps:gsub(".+:", "")
+ deps = deps:gsub('.+:', '')
-- remove redundant spaces
- deps = deps:gsub(" +", " ")
+ deps = deps:gsub(' +', ' ')
-- split according to token (space in this case)
local headers = {} --- @type string[]
- for token in deps:gmatch("[^%s]+") do
+ for token in deps:gmatch('[^%s]+') do
-- headers[token] = true
headers[#headers + 1] = token
end
@@ -50,9 +50,9 @@ local function parse_make_deps(deps)
-- resolve path redirections (..) to normalize all paths
for i, v in ipairs(headers) do
-- double dots (..)
- headers[i] = v:gsub("/[^/%s]+/%.%.", "")
+ headers[i] = v:gsub('/[^/%s]+/%.%.', '')
-- single dot (.)
- headers[i] = v:gsub("%./", "")
+ headers[i] = v:gsub('%./', '')
end
return headers
@@ -80,7 +80,7 @@ local function headerize(headers, global)
formatted[#formatted + 1] = string.format(fmt, hdr)
end
- return table.concat(formatted, "\n")
+ return table.concat(formatted, '\n')
end
--- @class Gcc
@@ -90,8 +90,8 @@ end
--- @field get_declarations_extra_flags string[]
local Gcc = {
preprocessor_extra_flags = {},
- get_defines_extra_flags = {'-std=c99', '-dM', '-E'},
- get_declarations_extra_flags = {'-std=c99', '-P', '-E'},
+ get_defines_extra_flags = { '-std=c99', '-dM', '-E' },
+ get_declarations_extra_flags = { '-std=c99', '-P', '-E' },
}
--- @param name string
@@ -115,13 +115,13 @@ end
function Gcc:init_defines()
-- preprocessor flags that will hopefully make the compiler produce C
-- declarations that the LuaJIT ffi understands.
- self:define('aligned', {'ARGS'}, '')
- self:define('__attribute__', {'ARGS'}, '')
- self:define('__asm', {'ARGS'}, '')
- self:define('__asm__', {'ARGS'}, '')
+ self:define('aligned', { 'ARGS' }, '')
+ self:define('__attribute__', { 'ARGS' }, '')
+ self:define('__asm', { 'ARGS' }, '')
+ self:define('__asm__', { 'ARGS' }, '')
self:define('__inline__', nil, '')
self:define('EXTERN', nil, 'extern')
- self:define('INIT', {'...'}, '')
+ self:define('INIT', { '...' }, '')
self:define('_GNU_SOURCE')
self:define('INCLUDE_GENERATED_DECLARATIONS')
self:define('UNIT_TESTING')
@@ -158,9 +158,9 @@ end
--- @return string[]?
function Gcc:dependencies(hdr)
--- @type string
- local cmd = argss_to_cmd(self.path, {'-M', hdr}) .. ' 2>&1'
+ local cmd = argss_to_cmd(self.path, { '-M', hdr }) .. ' 2>&1'
local out = assert(io.popen(cmd))
- local deps = out:read("*a")
+ local deps = out:read('*a')
out:close()
if deps then
return parse_make_deps(deps)
@@ -174,10 +174,14 @@ function Gcc:filter_standard_defines(defines)
local pseudoheader_fname = 'tmp_empty_pseudoheader.h'
local pseudoheader_file = assert(io.open(pseudoheader_fname, 'w'))
pseudoheader_file:close()
- local standard_defines = assert(repeated_read_cmd(self.path,
- self.preprocessor_extra_flags,
- self.get_defines_extra_flags,
- {pseudoheader_fname}))
+ local standard_defines = assert(
+ repeated_read_cmd(
+ self.path,
+ self.preprocessor_extra_flags,
+ self.get_defines_extra_flags,
+ { pseudoheader_fname }
+ )
+ )
os.remove(pseudoheader_fname)
self.standard_defines = {} --- @type table<string,true>
for line in standard_defines:gmatch('[^\n]+') do
@@ -192,7 +196,7 @@ function Gcc:filter_standard_defines(defines)
end
end
- return table.concat(ret, "\n")
+ return table.concat(ret, '\n')
end
--- returns a stream representing a preprocessed form of the passed-in headers.
@@ -202,24 +206,33 @@ end
--- @return string, string
function Gcc:preprocess(previous_defines, ...)
-- create pseudo-header
- local pseudoheader = headerize({...}, false)
+ local pseudoheader = headerize({ ... }, false)
local pseudoheader_fname = 'tmp_pseudoheader.h'
local pseudoheader_file = assert(io.open(pseudoheader_fname, 'w'))
pseudoheader_file:write(previous_defines)
- pseudoheader_file:write("\n")
+ pseudoheader_file:write('\n')
pseudoheader_file:write(pseudoheader)
pseudoheader_file:flush()
pseudoheader_file:close()
- local defines = assert(repeated_read_cmd(self.path, self.preprocessor_extra_flags,
- self.get_defines_extra_flags,
- {pseudoheader_fname}))
+ local defines = assert(
+ repeated_read_cmd(
+ self.path,
+ self.preprocessor_extra_flags,
+ self.get_defines_extra_flags,
+ { pseudoheader_fname }
+ )
+ )
defines = self:filter_standard_defines(defines)
- local declarations = assert(repeated_read_cmd(self.path,
- self.preprocessor_extra_flags,
- self.get_declarations_extra_flags,
- {pseudoheader_fname}))
+ local declarations = assert(
+ repeated_read_cmd(
+ self.path,
+ self.preprocessor_extra_flags,
+ self.get_declarations_extra_flags,
+ { pseudoheader_fname }
+ )
+ )
os.remove(pseudoheader_fname)
@@ -233,10 +246,10 @@ end
--- @return Gcc?
local function find_best_cc(compilers)
for _, meta in pairs(compilers) do
- local version = assert(io.popen(tostring(meta.path) .. " -v 2>&1"))
+ local version = assert(io.popen(tostring(meta.path) .. ' -v 2>&1'))
version:close()
if version then
- return Gcc:new({path = meta.path})
+ return Gcc:new({ path = meta.path })
end
end
end
diff --git a/test/unit/profile_spec.lua b/test/unit/profile_spec.lua
index 08e5cedbab..011d3632d5 100644
--- a/test/unit/profile_spec.lua
+++ b/test/unit/profile_spec.lua
@@ -10,11 +10,11 @@ local prof = cimport('./src/nvim/profile.h')
local function split(inputstr, sep)
if sep == nil then
- sep = "%s"
+ sep = '%s'
end
local t, i = {}, 1
- for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
+ for str in string.gmatch(inputstr, '([^' .. sep .. ']+)') do
t[i] = str
i = i + 1
end
@@ -23,36 +23,44 @@ local function split(inputstr, sep)
end
local function trim(s)
- local from = s:match"^%s*()"
- return from > #s and "" or s:match(".*%S", from)
+ local from = s:match '^%s*()'
+ return from > #s and '' or s:match('.*%S', from)
end
local function starts(str, start)
- return string.sub(str, 1, string.len(start)) == start
+ return string.sub(str, 1, string.len(start)) == start
end
local function cmp_assert(v1, v2, op, opstr)
local res = op(v1, v2)
if res == false then
- print(string.format("expected: %f %s %f", v1, opstr, v2))
+ print(string.format('expected: %f %s %f', v1, opstr, v2))
end
assert.is_true(res)
end
-local function lt(a, b) -- luacheck: ignore
- cmp_assert(a, b, function(x, y) return x < y end, "<")
+local function lt(a, b) -- luacheck: ignore
+ cmp_assert(a, b, function(x, y)
+ return x < y
+ end, '<')
end
-local function lte(a, b) -- luacheck: ignore
- cmp_assert(a, b, function(x, y) return x <= y end, "<=")
+local function lte(a, b) -- luacheck: ignore
+ cmp_assert(a, b, function(x, y)
+ return x <= y
+ end, '<=')
end
-local function gt(a, b) -- luacheck: ignore
- cmp_assert(a, b, function(x, y) return x > y end, ">")
+local function gt(a, b) -- luacheck: ignore
+ cmp_assert(a, b, function(x, y)
+ return x > y
+ end, '>')
end
local function gte(a, b)
- cmp_assert(a, b, function(x, y) return x >= y end, ">=")
+ cmp_assert(a, b, function(x, y)
+ return x >= y
+ end, '>=')
end
-- missing functions:
@@ -61,21 +69,43 @@ end
-- profile_set_wait
-- profile_sub_wait
describe('profiling related functions', function()
- local function profile_start() return prof.profile_start() end
- local function profile_end(t) return prof.profile_end(t) end
- local function profile_zero() return prof.profile_zero() end
- local function profile_setlimit(ms) return prof.profile_setlimit(ms) end
- local function profile_passed_limit(t) return prof.profile_passed_limit(t) end
- local function profile_add(t1, t2) return prof.profile_add(t1, t2) end
- local function profile_sub(t1, t2) return prof.profile_sub(t1, t2) end
- local function profile_divide(t, cnt) return prof.profile_divide(t, cnt) end
- local function profile_cmp(t1, t2) return prof.profile_cmp(t1, t2) end
- local function profile_equal(t1, t2) return prof.profile_equal(t1, t2) end
- local function profile_msg(t) return ffi.string(prof.profile_msg(t)) end
-
- local function toseconds(t) -- luacheck: ignore
+ local function profile_start()
+ return prof.profile_start()
+ end
+ local function profile_end(t)
+ return prof.profile_end(t)
+ end
+ local function profile_zero()
+ return prof.profile_zero()
+ end
+ local function profile_setlimit(ms)
+ return prof.profile_setlimit(ms)
+ end
+ local function profile_passed_limit(t)
+ return prof.profile_passed_limit(t)
+ end
+ local function profile_add(t1, t2)
+ return prof.profile_add(t1, t2)
+ end
+ local function profile_sub(t1, t2)
+ return prof.profile_sub(t1, t2)
+ end
+ local function profile_divide(t, cnt)
+ return prof.profile_divide(t, cnt)
+ end
+ local function profile_cmp(t1, t2)
+ return prof.profile_cmp(t1, t2)
+ end
+ local function profile_equal(t1, t2)
+ return prof.profile_equal(t1, t2)
+ end
+ local function profile_msg(t)
+ return ffi.string(prof.profile_msg(t))
+ end
+
+ local function toseconds(t) -- luacheck: ignore
local str = trim(profile_msg(t))
- local spl = split(str, ".")
+ local spl = split(str, '.')
local s, us = spl[1], spl[2]
return tonumber(s) + tonumber(us) / 1000000
end
@@ -199,14 +229,14 @@ describe('profiling related functions', function()
describe('profile_msg', function()
itp('prints the zero time as 0.00000', function()
local str = trim(profile_msg(profile_zero()))
- eq(str, "0.000000")
+ eq(str, '0.000000')
end)
itp('prints the time passed, in seconds.microsends', function()
local start = profile_start()
local endt = profile_end(start)
local str = trim(profile_msg(endt))
- local spl = split(str, ".")
+ local spl = split(str, '.')
-- string has two parts (before dot and after dot)
eq(2, #spl)
@@ -215,11 +245,11 @@ describe('profiling related functions', function()
-- zero seconds have passed (if this is not true, either LuaJIT is too
-- slow or the profiling functions are too slow and need to be fixed)
- eq(s, "0")
+ eq(s, '0')
-- more or less the same goes for the microsecond part, if it doesn't
-- start with 0, it's too slow.
- assert.is_true(starts(us, "0"))
+ assert.is_true(starts(us, '0'))
end)
end)
diff --git a/test/unit/rbuffer_spec.lua b/test/unit/rbuffer_spec.lua
index e9104dd5c4..328e5b93da 100644
--- a/test/unit/rbuffer_spec.lua
+++ b/test/unit/rbuffer_spec.lua
@@ -1,4 +1,4 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local eq = helpers.eq
@@ -7,7 +7,7 @@ local cstr = helpers.cstr
local to_cstr = helpers.to_cstr
local child_call_once = helpers.child_call_once
-local rbuffer = helpers.cimport("./test/unit/fixtures/rbuffer.h")
+local rbuffer = helpers.cimport('./test/unit/fixtures/rbuffer.h')
describe('rbuffer functions', function()
local capacity = 16
@@ -56,7 +56,7 @@ describe('rbuffer functions', function()
describe('with empty buffer in one contiguous chunk', function()
itp('is called once with the empty chunk', function()
collect_write_chunks()
- eq({'0000000000000000'}, chunks)
+ eq({ '0000000000000000' }, chunks)
end)
end)
@@ -64,7 +64,7 @@ describe('rbuffer functions', function()
itp('is called once with the empty chunk', function()
write('string')
collect_write_chunks()
- eq({'0000000000'}, chunks)
+ eq({ '0000000000' }, chunks)
end)
end)
@@ -81,7 +81,7 @@ describe('rbuffer functions', function()
write('1234567890')
read(8)
collect_write_chunks()
- eq({'000000', '12345678'}, chunks)
+ eq({ '000000', '12345678' }, chunks)
end)
end)
@@ -90,7 +90,7 @@ describe('rbuffer functions', function()
write('12345678')
read(8)
collect_write_chunks()
- eq({'00000000', '12345678'}, chunks)
+ eq({ '00000000', '12345678' }, chunks)
end)
end)
@@ -129,7 +129,7 @@ describe('rbuffer functions', function()
itp('is called once with the filled chunk', function()
write('string')
collect_read_chunks()
- eq({'string'}, chunks)
+ eq({ 'string' }, chunks)
end)
end)
@@ -137,7 +137,7 @@ describe('rbuffer functions', function()
itp('is called once with the filled chunk', function()
write('abcdefghijklmnopq')
collect_read_chunks()
- eq({'abcdefghijklmnop'}, chunks)
+ eq({ 'abcdefghijklmnop' }, chunks)
end)
end)
@@ -147,7 +147,7 @@ describe('rbuffer functions', function()
read(10)
write('long string')
collect_read_chunks()
- eq({'long s', 'tring'}, chunks)
+ eq({ 'long s', 'tring' }, chunks)
end)
end)
@@ -157,7 +157,7 @@ describe('rbuffer functions', function()
read(8)
write('abcdefghijklmnopq')
collect_read_chunks()
- eq({'abcdefgh', 'ijklmnop'}, chunks)
+ eq({ 'abcdefgh', 'ijklmnop' }, chunks)
end)
end)
end)
@@ -167,7 +167,7 @@ describe('rbuffer functions', function()
local function collect_chars()
rbuffer.ut_rbuffer_each(rbuf, function(c, i)
- table.insert(chars, {string.char(c), tonumber(i)})
+ table.insert(chars, { string.char(c), tonumber(i) })
end)
end
before_each(function()
@@ -187,8 +187,19 @@ describe('rbuffer functions', function()
read(10)
write('long string')
collect_chars()
- eq({{'l', 0}, {'o', 1}, {'n', 2}, {'g', 3}, {' ', 4}, {'s', 5},
- {'t', 6}, {'r', 7}, {'i', 8}, {'n', 9}, {'g', 10}}, chars)
+ eq({
+ { 'l', 0 },
+ { 'o', 1 },
+ { 'n', 2 },
+ { 'g', 3 },
+ { ' ', 4 },
+ { 's', 5 },
+ { 't', 6 },
+ { 'r', 7 },
+ { 'i', 8 },
+ { 'n', 9 },
+ { 'g', 10 },
+ }, chars)
end)
end)
end)
@@ -198,7 +209,7 @@ describe('rbuffer functions', function()
local function collect_chars()
rbuffer.ut_rbuffer_each_reverse(rbuf, function(c, i)
- table.insert(chars, {string.char(c), tonumber(i)})
+ table.insert(chars, { string.char(c), tonumber(i) })
end)
end
before_each(function()
@@ -218,8 +229,19 @@ describe('rbuffer functions', function()
read(10)
write('long string')
collect_chars()
- eq({{'g', 10}, {'n', 9}, {'i', 8}, {'r', 7}, {'t', 6}, {'s', 5},
- {' ', 4}, {'g', 3}, {'n', 2}, {'o', 1}, {'l', 0}}, chars)
+ eq({
+ { 'g', 10 },
+ { 'n', 9 },
+ { 'i', 8 },
+ { 'r', 7 },
+ { 't', 6 },
+ { 's', 5 },
+ { ' ', 4 },
+ { 'g', 3 },
+ { 'n', 2 },
+ { 'o', 1 },
+ { 'l', 0 },
+ }, chars)
end)
end)
end)
diff --git a/test/unit/search_spec.lua b/test/unit/search_spec.lua
index be905bf5f0..efe49f974a 100644
--- a/test/unit/search_spec.lua
+++ b/test/unit/search_spec.lua
@@ -1,42 +1,42 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local to_cstr = helpers.to_cstr
-local eq = helpers.eq
+local eq = helpers.eq
-local search = helpers.cimport("./src/nvim/search.h")
+local search = helpers.cimport('./src/nvim/search.h')
local globals = helpers.cimport('./src/nvim/globals.h')
local ffi = helpers.ffi
itp('pat_has_uppercase', function()
-- works on empty string
- eq(false, search.pat_has_uppercase(to_cstr("")))
+ eq(false, search.pat_has_uppercase(to_cstr('')))
-- works with utf uppercase
- eq(false, search.pat_has_uppercase(to_cstr("ä")))
- eq(true, search.pat_has_uppercase(to_cstr("Ä")))
- eq(true, search.pat_has_uppercase(to_cstr("äaÅ")))
+ eq(false, search.pat_has_uppercase(to_cstr('ä')))
+ eq(true, search.pat_has_uppercase(to_cstr('Ä')))
+ eq(true, search.pat_has_uppercase(to_cstr('äaÅ')))
-- works when pat ends with backslash
- eq(false, search.pat_has_uppercase(to_cstr("\\")))
- eq(false, search.pat_has_uppercase(to_cstr("ab$\\")))
+ eq(false, search.pat_has_uppercase(to_cstr('\\')))
+ eq(false, search.pat_has_uppercase(to_cstr('ab$\\')))
-- skips escaped characters
- eq(false, search.pat_has_uppercase(to_cstr("\\Ab")))
- eq(true, search.pat_has_uppercase(to_cstr("\\AU")))
+ eq(false, search.pat_has_uppercase(to_cstr('\\Ab')))
+ eq(true, search.pat_has_uppercase(to_cstr('\\AU')))
-- skips _X escaped characters
- eq(false, search.pat_has_uppercase(to_cstr("\\_Ab")))
- eq(true, search.pat_has_uppercase(to_cstr("\\_AU")))
+ eq(false, search.pat_has_uppercase(to_cstr('\\_Ab')))
+ eq(true, search.pat_has_uppercase(to_cstr('\\_AU')))
-- skips %X escaped characters
- eq(false, search.pat_has_uppercase(to_cstr("aa\\%Ab")))
- eq(true, search.pat_has_uppercase(to_cstr("aab\\%AU")))
+ eq(false, search.pat_has_uppercase(to_cstr('aa\\%Ab')))
+ eq(true, search.pat_has_uppercase(to_cstr('aab\\%AU')))
end)
describe('search_regcomp', function()
- local search_regcomp = function(pat, pat_save, pat_use, options )
- local regmatch = ffi.new("regmmatch_T")
+ local search_regcomp = function(pat, pat_save, pat_use, options)
+ local regmatch = ffi.new('regmmatch_T')
local fail = search.search_regcomp(to_cstr(pat), nil, pat_save, pat_use, options, regmatch)
return fail, regmatch
end
@@ -45,13 +45,13 @@ describe('search_regcomp', function()
return helpers.internalize(search.get_search_pat())
end
- itp("accepts regexp pattern with invalid utf", function()
+ itp('accepts regexp pattern with invalid utf', function()
--crafted to call reverse_text with invalid utf
globals.curwin.w_onebuf_opt.wo_rl = 1
globals.curwin.w_onebuf_opt.wo_rlc = to_cstr('s')
globals.cmdmod.cmod_flags = globals.CMOD_KEEPPATTERNS
- local fail = search_regcomp("a\192", 0,0,0)
+ local fail = search_regcomp('a\192', 0, 0, 0)
eq(1, fail)
- eq("\192a", get_search_pat())
+ eq('\192a', get_search_pat())
end)
end)
diff --git a/test/unit/set.lua b/test/unit/set.lua
index 7c30be32aa..f93238cc47 100644
--- a/test/unit/set.lua
+++ b/test/unit/set.lua
@@ -33,7 +33,7 @@ end
--- @return Set
function Set:copy()
- local obj = {nelem = self.nelem, tbl = {}, items = {}} --- @type Set
+ local obj = { nelem = self.nelem, tbl = {}, items = {} } --- @type Set
for k, v in pairs(self.tbl) do
obj.tbl[k] = v
end
@@ -128,13 +128,13 @@ function Set:to_table()
-- there might be gaps in @tbl, so we have to be careful and sort first
local keys = {} --- @type string[]
for idx, _ in pairs(self.tbl) do
- keys[#keys+1] = idx
+ keys[#keys + 1] = idx
end
table.sort(keys)
local copy = {} --- @type string[]
for _, idx in ipairs(keys) do
- copy[#copy+1] = self.tbl[idx]
+ copy[#copy + 1] = self.tbl[idx]
end
return copy
end
diff --git a/test/unit/statusline_spec.lua b/test/unit/statusline_spec.lua
index a124a588e9..83ba4176c5 100644
--- a/test/unit/statusline_spec.lua
+++ b/test/unit/statusline_spec.lua
@@ -1,14 +1,15 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local to_cstr = helpers.to_cstr
local get_str = helpers.ffi.string
-local eq = helpers.eq
-local NULL = helpers.NULL
+local eq = helpers.eq
+local NULL = helpers.NULL
-local buffer = helpers.cimport("./src/nvim/buffer.h")
-local globals = helpers.cimport("./src/nvim/globals.h")
-local stl = helpers.cimport("./src/nvim/statusline.h")
+local buffer = helpers.cimport('./src/nvim/buffer.h')
+local globals = helpers.cimport('./src/nvim/globals.h')
+local stl = helpers.cimport('./src/nvim/statusline.h')
+local grid = helpers.cimport('./src/nvim/grid.h')
describe('build_stl_str_hl', function()
local buffer_byte_size = 100
@@ -22,23 +23,29 @@ describe('build_stl_str_hl', function()
-- .fillchar The fill character used in the statusline
-- .maximum_cell_count The number of cells available in the statusline
local function build_stl_str_hl(arg)
- output_buffer = to_cstr(string.rep(" ", buffer_byte_size))
+ output_buffer = to_cstr(string.rep(' ', buffer_byte_size))
local pat = arg.pat or ''
- local fillchar = arg.fillchar or (' '):byte()
+ local fillchar = arg.fillchar or ' '
local maximum_cell_count = arg.maximum_cell_count or buffer_byte_size
+ if type(fillchar) == type('') then
+ fillchar = grid.schar_from_str(fillchar)
+ end
- return stl.build_stl_str_hl(globals.curwin,
- output_buffer,
- buffer_byte_size,
- to_cstr(pat),
- NULL,
- 0,
- fillchar,
- maximum_cell_count,
- NULL,
- NULL,
- NULL)
+ return stl.build_stl_str_hl(
+ globals.curwin,
+ output_buffer,
+ buffer_byte_size,
+ to_cstr(pat),
+ -1,
+ 0,
+ fillchar,
+ maximum_cell_count,
+ NULL,
+ NULL,
+ NULL,
+ NULL
+ )
end
-- Use this function to simplify testing the comparison between
@@ -54,17 +61,12 @@ describe('build_stl_str_hl', function()
-- .expected_byte_length The expected byte length of the string (defaults to byte length of expected_stl)
-- .file_name The name of the file to be tested (useful in %f type tests)
-- .fillchar The character that will be used to fill any 'extra' space in the stl
- local function statusline_test(description,
- statusline_cell_count,
- input_stl,
- expected_stl,
- arg)
-
+ local function statusline_test(description, statusline_cell_count, input_stl, expected_stl, arg)
-- arg is the optional parameter
-- so we either fill in option with arg or an empty dictionary
local option = arg or {}
- local fillchar = option.fillchar or (' '):byte()
+ local fillchar = option.fillchar or ' '
local expected_cell_count = option.expected_cell_count or statusline_cell_count
local expected_byte_length = option.expected_byte_length or #expected_stl
@@ -75,9 +77,11 @@ describe('build_stl_str_hl', function()
buffer.setfname(globals.curbuf, nil, NULL, 1)
end
- local result_cell_count = build_stl_str_hl{pat=input_stl,
- maximum_cell_count=statusline_cell_count,
- fillchar=fillchar}
+ local result_cell_count = build_stl_str_hl {
+ pat = input_stl,
+ maximum_cell_count = statusline_cell_count,
+ fillchar = fillchar,
+ }
eq(expected_stl, get_str(output_buffer, expected_byte_length))
eq(expected_cell_count, result_cell_count)
@@ -85,198 +89,383 @@ describe('build_stl_str_hl', function()
end
-- expression testing
- statusline_test('Should expand expression', 2,
- '%!expand(20+1)', '21')
- statusline_test('Should expand broken expression to itself', 11,
- '%!expand(20+1', 'expand(20+1')
+ statusline_test('Should expand expression', 2, '%!expand(20+1)', '21')
+ statusline_test('Should expand broken expression to itself', 11, '%!expand(20+1', 'expand(20+1')
-- file name testing
- statusline_test('should print no file name', 10,
- '%f', '[No Name]',
- {expected_cell_count=9})
- statusline_test('should print the relative file name', 30,
- '%f', 'test/unit/buffer_spec.lua',
- {file_name='test/unit/buffer_spec.lua', expected_cell_count=25})
- statusline_test('should print the full file name', 40,
- '%F', '/test/unit/buffer_spec.lua',
- {file_name='/test/unit/buffer_spec.lua', expected_cell_count=26})
+ statusline_test('should print no file name', 10, '%f', '[No Name]', { expected_cell_count = 9 })
+ statusline_test(
+ 'should print the relative file name',
+ 30,
+ '%f',
+ 'test/unit/buffer_spec.lua',
+ { file_name = 'test/unit/buffer_spec.lua', expected_cell_count = 25 }
+ )
+ statusline_test(
+ 'should print the full file name',
+ 40,
+ '%F',
+ '/test/unit/buffer_spec.lua',
+ { file_name = '/test/unit/buffer_spec.lua', expected_cell_count = 26 }
+ )
-- fillchar testing
- statusline_test('should handle `!` as a fillchar', 10,
- 'abcde%=', 'abcde!!!!!',
- {fillchar=('!'):byte()})
- statusline_test('should handle `~` as a fillchar', 10,
- '%=abcde', '~~~~~abcde',
- {fillchar=('~'):byte()})
- statusline_test('should put fillchar `!` in between text', 10,
- 'abc%=def', 'abc!!!!def',
- {fillchar=('!'):byte()})
- statusline_test('should put fillchar `~` in between text', 10,
- 'abc%=def', 'abc~~~~def',
- {fillchar=('~'):byte()})
- statusline_test('should put fillchar `â”` in between text', 10,
- 'abc%=def', 'abcâ”â”â”â”def',
- {fillchar=0x2501})
- statusline_test('should handle zero-fillchar as a space', 10,
- 'abcde%=', 'abcde ',
- {fillchar=0})
- statusline_test('should print the tail file name', 80,
- '%t', 'buffer_spec.lua',
- {file_name='test/unit/buffer_spec.lua', expected_cell_count=15})
+ statusline_test(
+ 'should handle `!` as a fillchar',
+ 10,
+ 'abcde%=',
+ 'abcde!!!!!',
+ { fillchar = '!' }
+ )
+ statusline_test(
+ 'should handle `~` as a fillchar',
+ 10,
+ '%=abcde',
+ '~~~~~abcde',
+ { fillchar = '~' }
+ )
+ statusline_test(
+ 'should put fillchar `!` in between text',
+ 10,
+ 'abc%=def',
+ 'abc!!!!def',
+ { fillchar = '!' }
+ )
+ statusline_test(
+ 'should put fillchar `~` in between text',
+ 10,
+ 'abc%=def',
+ 'abc~~~~def',
+ { fillchar = '~' }
+ )
+ statusline_test(
+ 'should put fillchar `â”` in between text',
+ 10,
+ 'abc%=def',
+ 'abcâ”â”â”â”def',
+ { fillchar = 'â”' }
+ )
+ statusline_test(
+ 'should handle zero-fillchar as a space',
+ 10,
+ 'abcde%=',
+ 'abcde ',
+ { fillchar = 0 }
+ )
+ statusline_test(
+ 'should print the tail file name',
+ 80,
+ '%t',
+ 'buffer_spec.lua',
+ { file_name = 'test/unit/buffer_spec.lua', expected_cell_count = 15 }
+ )
-- standard text testing
- statusline_test('should copy plain text', 80,
- 'this is a test', 'this is a test',
- {expected_cell_count=14})
+ statusline_test(
+ 'should copy plain text',
+ 80,
+ 'this is a test',
+ 'this is a test',
+ { expected_cell_count = 14 }
+ )
-- line number testing
- statusline_test('should print the buffer number', 80,
- '%n', '1',
- {expected_cell_count=1})
- statusline_test('should print the current line number in the buffer', 80,
- '%l', '0',
- {expected_cell_count=1})
- statusline_test('should print the number of lines in the buffer', 80,
- '%L', '1',
- {expected_cell_count=1})
+ statusline_test('should print the buffer number', 80, '%n', '1', { expected_cell_count = 1 })
+ statusline_test(
+ 'should print the current line number in the buffer',
+ 80,
+ '%l',
+ '0',
+ { expected_cell_count = 1 }
+ )
+ statusline_test(
+ 'should print the number of lines in the buffer',
+ 80,
+ '%L',
+ '1',
+ { expected_cell_count = 1 }
+ )
-- truncation testing
- statusline_test('should truncate when standard text pattern is too long', 10,
- '0123456789abcde', '<6789abcde')
- statusline_test('should truncate when using =', 10,
- 'abcdef%=ghijkl', 'abcdef<jkl')
- statusline_test('should truncate centered text when using ==', 10,
- 'abcde%=gone%=fghij', 'abcde<ghij')
- statusline_test('should respect the `<` marker', 10,
- 'abc%<defghijkl', 'abc<ghijkl')
- statusline_test('should truncate at `<` with one `=`, test 1', 10,
- 'abc%<def%=ghijklmno', 'abc<jklmno')
- statusline_test('should truncate at `<` with one `=`, test 2', 10,
- 'abcdef%=ghijkl%<mno', 'abcdefghi>')
- statusline_test('should truncate at `<` with one `=`, test 3', 10,
- 'abc%<def%=ghijklmno', 'abc<jklmno')
- statusline_test('should truncate at `<` with one `=`, test 4', 10,
- 'abc%<def%=ghij', 'abcdefghij')
- statusline_test('should truncate at `<` with one `=`, test 4', 10,
- 'abc%<def%=ghijk', 'abc<fghijk')
+ statusline_test(
+ 'should truncate when standard text pattern is too long',
+ 10,
+ '0123456789abcde',
+ '<6789abcde'
+ )
+ statusline_test('should truncate when using =', 10, 'abcdef%=ghijkl', 'abcdef<jkl')
+ statusline_test(
+ 'should truncate centered text when using ==',
+ 10,
+ 'abcde%=gone%=fghij',
+ 'abcde<ghij'
+ )
+ statusline_test('should respect the `<` marker', 10, 'abc%<defghijkl', 'abc<ghijkl')
+ statusline_test(
+ 'should truncate at `<` with one `=`, test 1',
+ 10,
+ 'abc%<def%=ghijklmno',
+ 'abc<jklmno'
+ )
+ statusline_test(
+ 'should truncate at `<` with one `=`, test 2',
+ 10,
+ 'abcdef%=ghijkl%<mno',
+ 'abcdefghi>'
+ )
+ statusline_test(
+ 'should truncate at `<` with one `=`, test 3',
+ 10,
+ 'abc%<def%=ghijklmno',
+ 'abc<jklmno'
+ )
+ statusline_test('should truncate at `<` with one `=`, test 4', 10, 'abc%<def%=ghij', 'abcdefghij')
+ statusline_test(
+ 'should truncate at `<` with one `=`, test 4',
+ 10,
+ 'abc%<def%=ghijk',
+ 'abc<fghijk'
+ )
- statusline_test('should truncate at `<` with many `=`, test 4', 10,
- 'ab%<cdef%=g%=h%=ijk', 'ab<efghijk')
+ statusline_test(
+ 'should truncate at `<` with many `=`, test 4',
+ 10,
+ 'ab%<cdef%=g%=h%=ijk',
+ 'ab<efghijk'
+ )
- statusline_test('should truncate at the first `<`', 10,
- 'abc%<def%<ghijklm', 'abc<hijklm')
+ statusline_test('should truncate at the first `<`', 10, 'abc%<def%<ghijklm', 'abc<hijklm')
statusline_test('should ignore trailing %', 3, 'abc%', 'abc')
-- alignment testing with fillchar
- local function statusline_test_align(description,
- statusline_cell_count,
- input_stl,
- expected_stl,
- arg)
+ local function statusline_test_align(
+ description,
+ statusline_cell_count,
+ input_stl,
+ expected_stl,
+ arg
+ )
arg = arg or {}
- statusline_test(description .. ' without fillchar',
- statusline_cell_count, input_stl, expected_stl:gsub('%~', ' '), arg)
- arg.fillchar = ('!'):byte()
- statusline_test(description .. ' with fillchar `!`',
- statusline_cell_count, input_stl, expected_stl:gsub('%~', '!'), arg)
- arg.fillchar = 0x2501
- statusline_test(description .. ' with fillchar `â”`',
- statusline_cell_count, input_stl, expected_stl:gsub('%~', 'â”'), arg)
+ statusline_test(
+ description .. ' without fillchar',
+ statusline_cell_count,
+ input_stl,
+ expected_stl:gsub('%~', ' '),
+ arg
+ )
+ arg.fillchar = '!'
+ statusline_test(
+ description .. ' with fillchar `!`',
+ statusline_cell_count,
+ input_stl,
+ expected_stl:gsub('%~', '!'),
+ arg
+ )
+ arg.fillchar = 'â”'
+ statusline_test(
+ description .. ' with fillchar `â”`',
+ statusline_cell_count,
+ input_stl,
+ expected_stl:gsub('%~', 'â”'),
+ arg
+ )
end
- statusline_test_align('should right align when using =', 20,
- 'neo%=vim', 'neo~~~~~~~~~~~~~~vim')
- statusline_test_align('should, when possible, center text when using %=text%=', 20,
- 'abc%=neovim%=def', 'abc~~~~neovim~~~~def')
- statusline_test_align('should handle uneven spacing in the buffer when using %=text%=', 20,
- 'abc%=neo_vim%=def', 'abc~~~neo_vim~~~~def')
- statusline_test_align('should have equal spaces even with non-equal sides when using =', 20,
- 'foobar%=test%=baz', 'foobar~~~test~~~~baz')
- statusline_test_align('should have equal spaces even with longer right side when using =', 20,
- 'a%=test%=longtext', 'a~~~test~~~~longtext')
- statusline_test_align('should handle an empty left side when using ==', 20,
- '%=test%=baz', '~~~~~~test~~~~~~~baz')
- statusline_test_align('should handle an empty right side when using ==', 20,
- 'foobar%=test%=', 'foobar~~~~~test~~~~~')
- statusline_test_align('should handle consecutive empty ==', 20,
- '%=%=test%=', '~~~~~~~~~~test~~~~~~')
- statusline_test_align('should handle an = alone', 20,
- '%=', '~~~~~~~~~~~~~~~~~~~~')
- statusline_test_align('should right align text when it is alone with =', 20,
- '%=foo', '~~~~~~~~~~~~~~~~~foo')
- statusline_test_align('should left align text when it is alone with =', 20,
- 'foo%=', 'foo~~~~~~~~~~~~~~~~~')
+ statusline_test_align('should right align when using =', 20, 'neo%=vim', 'neo~~~~~~~~~~~~~~vim')
+ statusline_test_align(
+ 'should, when possible, center text when using %=text%=',
+ 20,
+ 'abc%=neovim%=def',
+ 'abc~~~~neovim~~~~def'
+ )
+ statusline_test_align(
+ 'should handle uneven spacing in the buffer when using %=text%=',
+ 20,
+ 'abc%=neo_vim%=def',
+ 'abc~~~neo_vim~~~~def'
+ )
+ statusline_test_align(
+ 'should have equal spaces even with non-equal sides when using =',
+ 20,
+ 'foobar%=test%=baz',
+ 'foobar~~~test~~~~baz'
+ )
+ statusline_test_align(
+ 'should have equal spaces even with longer right side when using =',
+ 20,
+ 'a%=test%=longtext',
+ 'a~~~test~~~~longtext'
+ )
+ statusline_test_align(
+ 'should handle an empty left side when using ==',
+ 20,
+ '%=test%=baz',
+ '~~~~~~test~~~~~~~baz'
+ )
+ statusline_test_align(
+ 'should handle an empty right side when using ==',
+ 20,
+ 'foobar%=test%=',
+ 'foobar~~~~~test~~~~~'
+ )
+ statusline_test_align(
+ 'should handle consecutive empty ==',
+ 20,
+ '%=%=test%=',
+ '~~~~~~~~~~test~~~~~~'
+ )
+ statusline_test_align('should handle an = alone', 20, '%=', '~~~~~~~~~~~~~~~~~~~~')
+ statusline_test_align(
+ 'should right align text when it is alone with =',
+ 20,
+ '%=foo',
+ '~~~~~~~~~~~~~~~~~foo'
+ )
+ statusline_test_align(
+ 'should left align text when it is alone with =',
+ 20,
+ 'foo%=',
+ 'foo~~~~~~~~~~~~~~~~~'
+ )
- statusline_test_align('should approximately center text when using %=text%=', 21,
- 'abc%=neovim%=def', 'abc~~~~neovim~~~~~def')
- statusline_test_align('should completely fill the buffer when using %=text%=', 21,
- 'abc%=neo_vim%=def', 'abc~~~~neo_vim~~~~def')
- statusline_test_align('should have equal spacing even with non-equal sides when using =', 21,
- 'foobar%=test%=baz', 'foobar~~~~test~~~~baz')
- statusline_test_align('should have equal spacing even with longer right side when using =', 21,
- 'a%=test%=longtext', 'a~~~~test~~~~longtext')
- statusline_test_align('should handle an empty left side when using ==', 21,
- '%=test%=baz', '~~~~~~~test~~~~~~~baz')
- statusline_test_align('should handle an empty right side when using ==', 21,
- 'foobar%=test%=', 'foobar~~~~~test~~~~~~')
+ statusline_test_align(
+ 'should approximately center text when using %=text%=',
+ 21,
+ 'abc%=neovim%=def',
+ 'abc~~~~neovim~~~~~def'
+ )
+ statusline_test_align(
+ 'should completely fill the buffer when using %=text%=',
+ 21,
+ 'abc%=neo_vim%=def',
+ 'abc~~~~neo_vim~~~~def'
+ )
+ statusline_test_align(
+ 'should have equal spacing even with non-equal sides when using =',
+ 21,
+ 'foobar%=test%=baz',
+ 'foobar~~~~test~~~~baz'
+ )
+ statusline_test_align(
+ 'should have equal spacing even with longer right side when using =',
+ 21,
+ 'a%=test%=longtext',
+ 'a~~~~test~~~~longtext'
+ )
+ statusline_test_align(
+ 'should handle an empty left side when using ==',
+ 21,
+ '%=test%=baz',
+ '~~~~~~~test~~~~~~~baz'
+ )
+ statusline_test_align(
+ 'should handle an empty right side when using ==',
+ 21,
+ 'foobar%=test%=',
+ 'foobar~~~~~test~~~~~~'
+ )
- statusline_test_align('should quadrant the text when using 3 %=', 40,
- 'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~ef')
- statusline_test_align('should work well with %t', 40,
- '%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~right_aligned',
- {file_name='test/unit/buffer_spec.lua'})
- statusline_test_align('should work well with %t and regular text', 40,
- 'l%=m_l %t m_r%=r', 'l~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
- {file_name='test/unit/buffer_spec.lua'})
- statusline_test_align('should work well with %=, %t, %L, and %l', 40,
- '%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~ 1 ~~~~~~~~~~ 0',
- {file_name='test/unit/buffer_spec.lua'})
+ statusline_test_align(
+ 'should quadrant the text when using 3 %=',
+ 40,
+ 'abcd%=n%=eovim%=ef',
+ 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~ef'
+ )
+ statusline_test_align(
+ 'should work well with %t',
+ 40,
+ '%t%=right_aligned',
+ 'buffer_spec.lua~~~~~~~~~~~~right_aligned',
+ { file_name = 'test/unit/buffer_spec.lua' }
+ )
+ statusline_test_align(
+ 'should work well with %t and regular text',
+ 40,
+ 'l%=m_l %t m_r%=r',
+ 'l~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
+ { file_name = 'test/unit/buffer_spec.lua' }
+ )
+ statusline_test_align(
+ 'should work well with %=, %t, %L, and %l',
+ 40,
+ '%t %= %L %= %l',
+ 'buffer_spec.lua ~~~~~~~~~ 1 ~~~~~~~~~~ 0',
+ { file_name = 'test/unit/buffer_spec.lua' }
+ )
- statusline_test_align('should quadrant the text when using 3 %=', 41,
- 'abcd%=n%=eovim%=ef', 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~~ef')
- statusline_test_align('should work well with %t', 41,
- '%t%=right_aligned', 'buffer_spec.lua~~~~~~~~~~~~~right_aligned',
- {file_name='test/unit/buffer_spec.lua'})
- statusline_test_align('should work well with %t and regular text', 41,
- 'l%=m_l %t m_r%=r', 'l~~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
- {file_name='test/unit/buffer_spec.lua'})
- statusline_test_align('should work well with %=, %t, %L, and %l', 41,
- '%t %= %L %= %l', 'buffer_spec.lua ~~~~~~~~~~ 1 ~~~~~~~~~~ 0',
- {file_name='test/unit/buffer_spec.lua'})
+ statusline_test_align(
+ 'should quadrant the text when using 3 %=',
+ 41,
+ 'abcd%=n%=eovim%=ef',
+ 'abcd~~~~~~~~~n~~~~~~~~~eovim~~~~~~~~~~~ef'
+ )
+ statusline_test_align(
+ 'should work well with %t',
+ 41,
+ '%t%=right_aligned',
+ 'buffer_spec.lua~~~~~~~~~~~~~right_aligned',
+ { file_name = 'test/unit/buffer_spec.lua' }
+ )
+ statusline_test_align(
+ 'should work well with %t and regular text',
+ 41,
+ 'l%=m_l %t m_r%=r',
+ 'l~~~~~~~~m_l buffer_spec.lua m_r~~~~~~~~r',
+ { file_name = 'test/unit/buffer_spec.lua' }
+ )
+ statusline_test_align(
+ 'should work well with %=, %t, %L, and %l',
+ 41,
+ '%t %= %L %= %l',
+ 'buffer_spec.lua ~~~~~~~~~~ 1 ~~~~~~~~~~ 0',
+ { file_name = 'test/unit/buffer_spec.lua' }
+ )
- statusline_test_align('should work with 10 %=', 50,
+ statusline_test_align(
+ 'should work with 10 %=',
+ 50,
'aaaa%=b%=c%=d%=e%=fg%=hi%=jk%=lmnop%=qrstuv%=wxyz',
- 'aaaa~~b~~c~~d~~e~~fg~~hi~~jk~~lmnop~~qrstuv~~~wxyz')
+ 'aaaa~~b~~c~~d~~e~~fg~~hi~~jk~~lmnop~~qrstuv~~~wxyz'
+ )
-- stl item testing
local tabline = ''
for i = 1, 1000 do
tabline = tabline .. (i % 2 == 0 and '%#TabLineSel#' or '%#TabLineFill#') .. tostring(i % 2)
end
- statusline_test('should handle a large amount of any items', 20,
- tabline,
- '<1010101010101010101') -- Should not show any error
- statusline_test('should handle a larger amount of = than stl initial item', 20,
+ statusline_test('should handle a large amount of any items', 20, tabline, '<1010101010101010101') -- Should not show any error
+ statusline_test(
+ 'should handle a larger amount of = than stl initial item',
+ 20,
('%='):rep(STL_INITIAL_ITEMS * 5),
- ' ') -- Should not show any error
- statusline_test('should handle many extra characters', 20,
+ ' '
+ ) -- Should not show any error
+ statusline_test(
+ 'should handle many extra characters',
+ 20,
'a' .. ('a'):rep(STL_INITIAL_ITEMS * 5),
- '<aaaaaaaaaaaaaaaaaaa') -- Does not show any error
- statusline_test('should handle many extra characters and flags', 20,
+ '<aaaaaaaaaaaaaaaaaaa'
+ ) -- Does not show any error
+ statusline_test(
+ 'should handle many extra characters and flags',
+ 20,
'a' .. ('%=a'):rep(STL_INITIAL_ITEMS * 2),
- 'a<aaaaaaaaaaaaaaaaaa') -- Should not show any error
+ 'a<aaaaaaaaaaaaaaaaaa'
+ ) -- Should not show any error
-- multi-byte testing
- statusline_test('should handle multibyte characters', 10,
- 'Ĉ%=x', 'Ĉ x')
- statusline_test('should handle multibyte characters and different fillchars', 10,
- 'Ä„%=mid%=end', 'Ä„@mid@@end',
- {fillchar=('@'):byte()})
+ statusline_test('should handle multibyte characters', 10, 'Ĉ%=x', 'Ĉ x')
+ statusline_test(
+ 'should handle multibyte characters and different fillchars',
+ 10,
+ 'Ä„%=mid%=end',
+ 'Ä„@mid@@end',
+ { fillchar = '@' }
+ )
-- escaping % testing
statusline_test('should handle escape of %', 4, 'abc%%', 'abc%')
statusline_test('case where escaped % does not fit', 3, 'abc%%abcabc', '<bc')
statusline_test('escaped % is first', 1, '%%', '%')
-
end)
diff --git a/test/unit/strings_spec.lua b/test/unit/strings_spec.lua
index 6d7aceb4b2..eea669c964 100644
--- a/test/unit/strings_spec.lua
+++ b/test/unit/strings_spec.lua
@@ -1,4 +1,4 @@
-local helpers = require("test.unit.helpers")(after_each)
+local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
local cimport = helpers.cimport
@@ -6,8 +6,7 @@ local eq = helpers.eq
local ffi = helpers.ffi
local to_cstr = helpers.to_cstr
-local strings = cimport('stdlib.h', './src/nvim/strings.h',
- './src/nvim/memory.h')
+local strings = cimport('stdlib.h', './src/nvim/strings.h', './src/nvim/memory.h')
describe('vim_strsave_escaped()', function()
local vim_strsave_escaped = function(s, chars)
@@ -21,19 +20,19 @@ describe('vim_strsave_escaped()', function()
end
itp('precedes by a backslash all chars from second argument', function()
- eq([[\a\b\c\d]], vim_strsave_escaped('abcd','abcd'))
+ eq([[\a\b\c\d]], vim_strsave_escaped('abcd', 'abcd'))
end)
itp('precedes by a backslash chars only from second argument', function()
- eq([[\a\bcd]], vim_strsave_escaped('abcd','ab'))
+ eq([[\a\bcd]], vim_strsave_escaped('abcd', 'ab'))
end)
itp('returns a copy of passed string if second argument is empty', function()
- eq('text \n text', vim_strsave_escaped('text \n text',''))
+ eq('text \n text', vim_strsave_escaped('text \n text', ''))
end)
itp('returns an empty string if first argument is empty string', function()
- eq('', vim_strsave_escaped('','\r'))
+ eq('', vim_strsave_escaped('', '\r'))
end)
itp('returns a copy of passed string if it does not contain chars from 2nd argument', function()
@@ -148,14 +147,30 @@ describe('vim_snprintf()', function()
end
end
- local function i(n) return ffi.cast('int', n) end
- local function l(n) return ffi.cast('long', n) end
- local function ll(n) return ffi.cast('long long', n) end
- local function z(n) return ffi.cast('ptrdiff_t', n) end
- local function u(n) return ffi.cast('unsigned', n) end
- local function ul(n) return ffi.cast('unsigned long', n) end
- local function ull(n) return ffi.cast('unsigned long long', n) end
- local function uz(n) return ffi.cast('size_t', n) end
+ local function i(n)
+ return ffi.cast('int', n)
+ end
+ local function l(n)
+ return ffi.cast('long', n)
+ end
+ local function ll(n)
+ return ffi.cast('long long', n)
+ end
+ local function z(n)
+ return ffi.cast('ptrdiff_t', n)
+ end
+ local function u(n)
+ return ffi.cast('unsigned', n)
+ end
+ local function ul(n)
+ return ffi.cast('unsigned long', n)
+ end
+ local function ull(n)
+ return ffi.cast('unsigned long long', n)
+ end
+ local function uz(n)
+ return ffi.cast('size_t', n)
+ end
itp('truncation', function()
for bsize = 0, 14 do
@@ -232,49 +247,51 @@ describe('vim_snprintf()', function()
end)
end)
-describe('strcase_save()' , function()
+describe('strcase_save()', function()
local strcase_save = function(input_string, upper)
local res = strings.strcase_save(to_cstr(input_string), upper)
return ffi.string(res)
end
itp('decodes overlong encoded characters.', function()
- eq("A", strcase_save("\xc1\x81", true))
- eq("a", strcase_save("\xc1\x81", false))
+ eq('A', strcase_save('\xc1\x81', true))
+ eq('a', strcase_save('\xc1\x81', false))
end)
end)
-describe("reverse_text", function()
+describe('reverse_text', function()
local reverse_text = function(str)
return helpers.internalize(strings.reverse_text(to_cstr(str)))
end
- itp("handles empty string", function()
- eq("", reverse_text(""))
+ itp('handles empty string', function()
+ eq('', reverse_text(''))
end)
- itp("handles simple cases", function()
- eq("a", reverse_text("a"))
- eq("ba", reverse_text("ab"))
+ itp('handles simple cases', function()
+ eq('a', reverse_text('a'))
+ eq('ba', reverse_text('ab'))
end)
- itp("handles multibyte characters", function()
- eq("bα", reverse_text("αb"))
- eq("Yötön yö", reverse_text("öy nötöY"))
+ itp('handles multibyte characters', function()
+ eq('bα', reverse_text('αb'))
+ eq('Yötön yö', reverse_text('öy nötöY'))
end)
- itp("handles combining chars", function()
- local utf8_COMBINING_RING_ABOVE = "\204\138"
- local utf8_COMBINING_RING_BELOW = "\204\165"
- eq("bba" .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. "aa",
- reverse_text("aaa" .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. "bb"))
+ itp('handles combining chars', function()
+ local utf8_COMBINING_RING_ABOVE = '\204\138'
+ local utf8_COMBINING_RING_BELOW = '\204\165'
+ eq(
+ 'bba' .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. 'aa',
+ reverse_text('aaa' .. utf8_COMBINING_RING_ABOVE .. utf8_COMBINING_RING_BELOW .. 'bb')
+ )
end)
- itp("treats invalid utf as separate characters", function()
- eq("\192ba", reverse_text("ab\192"))
+ itp('treats invalid utf as separate characters', function()
+ eq('\192ba', reverse_text('ab\192'))
end)
- itp("treats an incomplete utf continuation sequence as valid", function()
- eq("\194ba", reverse_text("ab\194"))
+ itp('treats an incomplete utf continuation sequence as valid', function()
+ eq('\194ba', reverse_text('ab\194'))
end)
end)
diff --git a/test/unit/undo_spec.lua b/test/unit/undo_spec.lua
index ee4203b94c..0e2f38a8c8 100644
--- a/test/unit/undo_spec.lua
+++ b/test/unit/undo_spec.lua
@@ -1,8 +1,8 @@
local helpers = require('test.unit.helpers')(after_each)
local itp = helpers.gen_itp(it)
-local luv = require('luv')
+local uv = vim.uv
local child_call_once = helpers.child_call_once
-local sleep = helpers.sleep
+local sleep = uv.sleep
local ffi = helpers.ffi
local cimport = helpers.cimport
@@ -23,7 +23,7 @@ local buffer_hash = nil
child_call_once(function()
if old_p_udir == nil then
- old_p_udir = options.p_udir -- save the old value of p_udir (undodir)
+ old_p_udir = options.p_udir -- save the old value of p_udir (undodir)
end
-- create a new buffer
@@ -39,21 +39,20 @@ child_call_once(function()
undo.u_compute_hash(file_buffer, buffer_hash)
end)
-
describe('u_write_undo', function()
setup(function()
mkdir('unit-test-directory')
- luv.chdir('unit-test-directory')
- options.p_udir = to_cstr(luv.cwd()) -- set p_udir to be the test dir
+ uv.chdir('unit-test-directory')
+ options.p_udir = to_cstr(uv.cwd()) -- set p_udir to be the test dir
end)
teardown(function()
- luv.chdir('..')
- local success, err = luv.fs_rmdir('unit-test-directory')
+ uv.chdir('..')
+ local success, err = uv.fs_rmdir('unit-test-directory')
if not success then
- print(err) -- inform tester if directory fails to delete
+ print(err) -- inform tester if directory fails to delete
end
- options.p_udir = old_p_udir --restore old p_udir
+ options.p_udir = old_p_udir --restore old p_udir
end)
-- Lua wrapper for u_write_undo
@@ -68,24 +67,24 @@ describe('u_write_undo', function()
itp('writes an undo file to undodir given a buffer and hash', function()
u_write_undo(nil, false, file_buffer, buffer_hash)
local correct_name = ffi.string(undo.u_get_undo_file_name(file_buffer.b_ffname, false))
- local undo_file = io.open(correct_name, "r")
+ local undo_file = io.open(correct_name, 'r')
neq(undo_file, nil)
- local success, err = os.remove(correct_name) -- delete the file now that we're done with it.
+ local success, err = os.remove(correct_name) -- delete the file now that we're done with it.
if not success then
- print(err) -- inform tester if undofile fails to delete
+ print(err) -- inform tester if undofile fails to delete
end
end)
itp('writes a correctly-named undo file to undodir given a name, buffer, and hash', function()
- local correct_name = "undofile.test"
+ local correct_name = 'undofile.test'
u_write_undo(correct_name, false, file_buffer, buffer_hash)
- local undo_file = io.open(correct_name, "r")
+ local undo_file = io.open(correct_name, 'r')
neq(undo_file, nil)
- local success, err = os.remove(correct_name) -- delete the file now that we're done with it.
+ local success, err = os.remove(correct_name) -- delete the file now that we're done with it.
if not success then
- print(err) -- inform tester if undofile fails to delete
+ print(err) -- inform tester if undofile fails to delete
end
end)
@@ -96,11 +95,11 @@ describe('u_write_undo', function()
itp('writes the undofile with the same permissions as the original file', function()
-- Create Test file and set permissions
- local test_file_name = "./test.file"
- local test_permission_file = io.open(test_file_name, "w")
- test_permission_file:write("testing permissions")
+ local test_file_name = './test.file'
+ local test_permission_file = io.open(test_file_name, 'w')
+ test_permission_file:write('testing permissions')
test_permission_file:close()
- local test_permissions = luv.fs_stat(test_file_name).mode
+ local test_permissions = uv.fs_stat(test_file_name).mode
-- Create vim buffer
local c_file = to_cstr(test_file_name)
@@ -113,23 +112,23 @@ describe('u_write_undo', function()
local undo_file_name = ffi.string(undo.u_get_undo_file_name(file_buffer.b_ffname, false))
-- Find out the permissions of the new file
- local permissions = luv.fs_stat(undo_file_name).mode
+ local permissions = uv.fs_stat(undo_file_name).mode
eq(test_permissions, permissions)
-- delete the file now that we're done with it.
local success, err = os.remove(test_file_name)
if not success then
- print(err) -- inform tester if undofile fails to delete
+ print(err) -- inform tester if undofile fails to delete
end
success, err = os.remove(undo_file_name)
if not success then
- print(err) -- inform tester if undofile fails to delete
+ print(err) -- inform tester if undofile fails to delete
end
end)
itp('writes an undofile only readable by the user if the buffer is unnamed', function()
local correct_permissions = 33152
- local undo_file_name = "test.undo"
+ local undo_file_name = 'test.undo'
-- Create vim buffer
file_buffer = buffer.buflist_new(nil, nil, 1, buffer.BLN_LISTED)
@@ -138,18 +137,18 @@ describe('u_write_undo', function()
u_write_undo(undo_file_name, false, file_buffer, buffer_hash)
-- Find out the permissions of the new file
- local permissions = luv.fs_stat(undo_file_name).mode
+ local permissions = uv.fs_stat(undo_file_name).mode
eq(correct_permissions, permissions)
-- delete the file now that we're done with it.
local success, err = os.remove(undo_file_name)
if not success then
- print(err) -- inform tester if undofile fails to delete
+ print(err) -- inform tester if undofile fails to delete
end
end)
itp('forces writing undo file for :wundo! command', function()
- local file_contents = "testing permissions"
+ local file_contents = 'testing permissions'
-- Write a text file where the undofile should go
local correct_name = ffi.string(undo.u_get_undo_file_name(file_buffer.b_ffname, false))
helpers.write_file(correct_name, file_contents, true, false)
@@ -160,9 +159,9 @@ describe('u_write_undo', function()
local undo_file_contents = helpers.read_file(correct_name)
neq(file_contents, undo_file_contents)
- local success, deletion_err = os.remove(correct_name) -- delete the file now that we're done with it.
+ local success, deletion_err = os.remove(correct_name) -- delete the file now that we're done with it.
if not success then
- print(deletion_err) -- inform tester if undofile fails to delete
+ print(deletion_err) -- inform tester if undofile fails to delete
end
end)
@@ -170,19 +169,19 @@ describe('u_write_undo', function()
u_write_undo(nil, false, file_buffer, buffer_hash)
local correct_name = ffi.string(undo.u_get_undo_file_name(file_buffer.b_ffname, false))
- local file_last_modified = luv.fs_stat(correct_name).mtime.sec
+ local file_last_modified = uv.fs_stat(correct_name).mtime.sec
- sleep(1000) -- Ensure difference in timestamps.
- file_buffer.b_u_numhead = 1 -- Mark it as if there are changes
+ sleep(1000) -- Ensure difference in timestamps.
+ file_buffer.b_u_numhead = 1 -- Mark it as if there are changes
u_write_undo(nil, false, file_buffer, buffer_hash)
- local file_last_modified_2 = luv.fs_stat(correct_name).mtime.sec
+ local file_last_modified_2 = uv.fs_stat(correct_name).mtime.sec
-- print(file_last_modified, file_last_modified_2)
neq(file_last_modified, file_last_modified_2)
- local success, err = os.remove(correct_name) -- delete the file now that we're done with it.
+ local success, err = os.remove(correct_name) -- delete the file now that we're done with it.
if not success then
- print(err) -- inform tester if undofile fails to delete
+ print(err) -- inform tester if undofile fails to delete
end
end)
@@ -195,16 +194,16 @@ describe('u_write_undo', function()
end)
itp('does not write an undo file if there is no undo information for the buffer', function()
- file_buffer.b_u_numhead = 0 -- Mark it as if there is no undo information
+ file_buffer.b_u_numhead = 0 -- Mark it as if there is no undo information
local correct_name = ffi.string(undo.u_get_undo_file_name(file_buffer.b_ffname, false))
- local existing_file = io.open(correct_name,"r")
+ local existing_file = io.open(correct_name, 'r')
if existing_file then
existing_file:close()
os.remove(correct_name)
end
u_write_undo(nil, false, file_buffer, buffer_hash)
- local undo_file = io.open(correct_name, "r")
+ local undo_file = io.open(correct_name, 'r')
eq(undo_file, nil)
end)
diff --git a/test/unit/viml/expressions/lexer_spec.lua b/test/unit/viml/expressions/lexer_spec.lua
index 358e858d61..96052a5ce1 100644
--- a/test/unit/viml/expressions/lexer_spec.lua
+++ b/test/unit/viml/expressions/lexer_spec.lua
@@ -83,24 +83,23 @@ local function eltkn2lua(pstate, tkn)
type = conv_eltkn_type(tkn.type),
}
pstate_set_str(pstate, tkn.start, tkn.len, ret)
- if not ret.error and (#(ret.str) ~= ret.len) then
+ if not ret.error and (#ret.str ~= ret.len) then
ret.error = '#str /= len'
end
if ret.type == 'Comparison' then
ret.data = {
type = conv_cmp_type(tkn.data.cmp.type),
ccs = conv_ccs(tkn.data.cmp.ccs),
- inv = (not not tkn.data.cmp.inv),
+ inv = not not tkn.data.cmp.inv,
}
elseif ret.type == 'Multiplication' then
ret.data = { type = conv_enum(eltkn_mul_type_tab, tkn.data.mul.type) }
elseif bracket_types[ret.type] then
- ret.data = { closing = (not not tkn.data.brc.closing) }
+ ret.data = { closing = not not tkn.data.brc.closing }
elseif ret.type == 'Register' then
ret.data = { name = intchar2lua(tkn.data.reg.name) }
- elseif (ret.type == 'SingleQuotedString'
- or ret.type == 'DoubleQuotedString') then
- ret.data = { closed = (not not tkn.data.str.closed) }
+ elseif ret.type == 'SingleQuotedString' or ret.type == 'DoubleQuotedString' then
+ ret.data = { closed = not not tkn.data.str.closed }
elseif ret.type == 'Option' then
ret.data = {
scope = conv_enum(eltkn_opt_scope_tab, tkn.data.opt.scope),
@@ -109,16 +108,15 @@ local function eltkn2lua(pstate, tkn)
elseif ret.type == 'PlainIdentifier' then
ret.data = {
scope = intchar2lua(tkn.data.var.scope),
- autoload = (not not tkn.data.var.autoload),
+ autoload = not not tkn.data.var.autoload,
}
elseif ret.type == 'Number' then
ret.data = {
- is_float = (not not tkn.data.num.is_float),
+ is_float = not not tkn.data.num.is_float,
base = tonumber(tkn.data.num.base),
}
- ret.data.val = tonumber(tkn.data.num.is_float
- and tkn.data.num.val.floating
- or tkn.data.num.val.integer)
+ ret.data.val =
+ tonumber(tkn.data.num.is_float and tkn.data.num.val.floating or tkn.data.num.val.integer)
elseif ret.type == 'Assignment' then
ret.data = { type = conv_expr_asgn_type(tkn.data.ass.type) }
elseif ret.type == 'Invalid' then
@@ -150,156 +148,263 @@ describe('Expressions lexer', function()
end
end
local function singl_eltkn_test(typ, str, data)
- local pstate = new_pstate({str})
- eq({data=data, len=#str, start={col=0, line=0}, str=str, type=typ},
- next_eltkn(pstate, flags))
+ local pstate = new_pstate({ str })
+ eq(
+ { data = data, len = #str, start = { col = 0, line = 0 }, str = str, type = typ },
+ next_eltkn(pstate, flags)
+ )
check_advance(pstate, #str, 0)
- if not (
+ if
+ not (
typ == 'Spacing'
or (typ == 'Register' and str == '@')
- or ((typ == 'SingleQuotedString' or typ == 'DoubleQuotedString')
- and not data.closed)
- ) then
- pstate = new_pstate({str .. ' '})
- eq({data=data, len=#str, start={col=0, line=0}, str=str, type=typ},
- next_eltkn(pstate, flags))
+ or ((typ == 'SingleQuotedString' or typ == 'DoubleQuotedString') and not data.closed)
+ )
+ then
+ pstate = new_pstate({ str .. ' ' })
+ eq(
+ { data = data, len = #str, start = { col = 0, line = 0 }, str = str, type = typ },
+ next_eltkn(pstate, flags)
+ )
check_advance(pstate, #str, 0)
end
- pstate = new_pstate({'x' .. str})
+ pstate = new_pstate({ 'x' .. str })
pstate.pos.col = 1
- eq({data=data, len=#str, start={col=1, line=0}, str=str, type=typ},
- next_eltkn(pstate, flags))
+ eq(
+ { data = data, len = #str, start = { col = 1, line = 0 }, str = str, type = typ },
+ next_eltkn(pstate, flags)
+ )
check_advance(pstate, #str, 1)
end
local function scope_test(scope)
- singl_eltkn_test('PlainIdentifier', scope .. ':test#var', {autoload=true, scope=scope})
- singl_eltkn_test('PlainIdentifier', scope .. ':', {autoload=false, scope=scope})
+ singl_eltkn_test('PlainIdentifier', scope .. ':test#var', { autoload = true, scope = scope })
+ singl_eltkn_test('PlainIdentifier', scope .. ':', { autoload = false, scope = scope })
end
local function comparison_test(op, inv_op, cmp_type)
- singl_eltkn_test('Comparison', op, {type=cmp_type, inv=false, ccs='UseOption'})
- singl_eltkn_test('Comparison', inv_op, {type=cmp_type, inv=true, ccs='UseOption'})
- singl_eltkn_test('Comparison', op .. '#', {type=cmp_type, inv=false, ccs='MatchCase'})
- singl_eltkn_test('Comparison', inv_op .. '#', {type=cmp_type, inv=true, ccs='MatchCase'})
- singl_eltkn_test('Comparison', op .. '?', {type=cmp_type, inv=false, ccs='IgnoreCase'})
- singl_eltkn_test('Comparison', inv_op .. '?', {type=cmp_type, inv=true, ccs='IgnoreCase'})
+ singl_eltkn_test('Comparison', op, { type = cmp_type, inv = false, ccs = 'UseOption' })
+ singl_eltkn_test('Comparison', inv_op, { type = cmp_type, inv = true, ccs = 'UseOption' })
+ singl_eltkn_test('Comparison', op .. '#', { type = cmp_type, inv = false, ccs = 'MatchCase' })
+ singl_eltkn_test(
+ 'Comparison',
+ inv_op .. '#',
+ { type = cmp_type, inv = true, ccs = 'MatchCase' }
+ )
+ singl_eltkn_test('Comparison', op .. '?', { type = cmp_type, inv = false, ccs = 'IgnoreCase' })
+ singl_eltkn_test(
+ 'Comparison',
+ inv_op .. '?',
+ { type = cmp_type, inv = true, ccs = 'IgnoreCase' }
+ )
end
local function simple_test(pstate_arg, exp_type, exp_len, exp)
local pstate = new_pstate(pstate_arg)
exp = shallowcopy(exp)
exp.type = exp_type
- exp.len = exp_len or #(pstate_arg[0])
+ exp.len = exp_len or #pstate_arg[0]
exp.start = { col = 0, line = 0 }
eq(exp, next_eltkn(pstate, flags))
end
local function stable_tests()
- singl_eltkn_test('Parenthesis', '(', {closing=false})
- singl_eltkn_test('Parenthesis', ')', {closing=true})
- singl_eltkn_test('Bracket', '[', {closing=false})
- singl_eltkn_test('Bracket', ']', {closing=true})
- singl_eltkn_test('FigureBrace', '{', {closing=false})
- singl_eltkn_test('FigureBrace', '}', {closing=true})
+ singl_eltkn_test('Parenthesis', '(', { closing = false })
+ singl_eltkn_test('Parenthesis', ')', { closing = true })
+ singl_eltkn_test('Bracket', '[', { closing = false })
+ singl_eltkn_test('Bracket', ']', { closing = true })
+ singl_eltkn_test('FigureBrace', '{', { closing = false })
+ singl_eltkn_test('FigureBrace', '}', { closing = true })
singl_eltkn_test('Question', '?')
singl_eltkn_test('Colon', ':')
singl_eltkn_test('Dot', '.')
- singl_eltkn_test('Assignment', '.=', {type='Concat'})
+ singl_eltkn_test('Assignment', '.=', { type = 'Concat' })
singl_eltkn_test('Plus', '+')
- singl_eltkn_test('Assignment', '+=', {type='Add'})
+ singl_eltkn_test('Assignment', '+=', { type = 'Add' })
singl_eltkn_test('Comma', ',')
- singl_eltkn_test('Multiplication', '*', {type='Mul'})
- singl_eltkn_test('Multiplication', '/', {type='Div'})
- singl_eltkn_test('Multiplication', '%', {type='Mod'})
+ singl_eltkn_test('Multiplication', '*', { type = 'Mul' })
+ singl_eltkn_test('Multiplication', '/', { type = 'Div' })
+ singl_eltkn_test('Multiplication', '%', { type = 'Mod' })
singl_eltkn_test('Spacing', ' \t\t \t\t')
singl_eltkn_test('Spacing', ' ')
singl_eltkn_test('Spacing', '\t')
- singl_eltkn_test('Invalid', '\x01\x02\x03', {error='E15: Invalid control character present in input: %.*s'})
- singl_eltkn_test('Number', '0123', {is_float=false, base=8, val=83})
- singl_eltkn_test('Number', '01234567', {is_float=false, base=8, val=342391})
- singl_eltkn_test('Number', '012345678', {is_float=false, base=10, val=12345678})
- singl_eltkn_test('Number', '0x123', {is_float=false, base=16, val=291})
- singl_eltkn_test('Number', '0x56FF', {is_float=false, base=16, val=22271})
- singl_eltkn_test('Number', '0xabcdef', {is_float=false, base=16, val=11259375})
- singl_eltkn_test('Number', '0xABCDEF', {is_float=false, base=16, val=11259375})
- singl_eltkn_test('Number', '0x0', {is_float=false, base=16, val=0})
- singl_eltkn_test('Number', '00', {is_float=false, base=8, val=0})
- singl_eltkn_test('Number', '0b0', {is_float=false, base=2, val=0})
- singl_eltkn_test('Number', '0b010111', {is_float=false, base=2, val=23})
- singl_eltkn_test('Number', '0b100111', {is_float=false, base=2, val=39})
- singl_eltkn_test('Number', '0', {is_float=false, base=10, val=0})
- singl_eltkn_test('Number', '9', {is_float=false, base=10, val=9})
+ singl_eltkn_test(
+ 'Invalid',
+ '\x01\x02\x03',
+ { error = 'E15: Invalid control character present in input: %.*s' }
+ )
+ singl_eltkn_test('Number', '0123', { is_float = false, base = 8, val = 83 })
+ singl_eltkn_test('Number', '01234567', { is_float = false, base = 8, val = 342391 })
+ singl_eltkn_test('Number', '012345678', { is_float = false, base = 10, val = 12345678 })
+ singl_eltkn_test('Number', '0x123', { is_float = false, base = 16, val = 291 })
+ singl_eltkn_test('Number', '0x56FF', { is_float = false, base = 16, val = 22271 })
+ singl_eltkn_test('Number', '0xabcdef', { is_float = false, base = 16, val = 11259375 })
+ singl_eltkn_test('Number', '0xABCDEF', { is_float = false, base = 16, val = 11259375 })
+ singl_eltkn_test('Number', '0x0', { is_float = false, base = 16, val = 0 })
+ singl_eltkn_test('Number', '00', { is_float = false, base = 8, val = 0 })
+ singl_eltkn_test('Number', '0b0', { is_float = false, base = 2, val = 0 })
+ singl_eltkn_test('Number', '0b010111', { is_float = false, base = 2, val = 23 })
+ singl_eltkn_test('Number', '0b100111', { is_float = false, base = 2, val = 39 })
+ singl_eltkn_test('Number', '0', { is_float = false, base = 10, val = 0 })
+ singl_eltkn_test('Number', '9', { is_float = false, base = 10, val = 9 })
singl_eltkn_test('Env', '$abc')
singl_eltkn_test('Env', '$')
- singl_eltkn_test('PlainIdentifier', 'test', {autoload=false, scope=0})
- singl_eltkn_test('PlainIdentifier', '_test', {autoload=false, scope=0})
- singl_eltkn_test('PlainIdentifier', '_test_foo', {autoload=false, scope=0})
- singl_eltkn_test('PlainIdentifier', 't', {autoload=false, scope=0})
- singl_eltkn_test('PlainIdentifier', 'test5', {autoload=false, scope=0})
- singl_eltkn_test('PlainIdentifier', 't0', {autoload=false, scope=0})
- singl_eltkn_test('PlainIdentifier', 'test#var', {autoload=true, scope=0})
- singl_eltkn_test('PlainIdentifier', 'test#var#val###', {autoload=true, scope=0})
- singl_eltkn_test('PlainIdentifier', 't#####', {autoload=true, scope=0})
+ singl_eltkn_test('PlainIdentifier', 'test', { autoload = false, scope = 0 })
+ singl_eltkn_test('PlainIdentifier', '_test', { autoload = false, scope = 0 })
+ singl_eltkn_test('PlainIdentifier', '_test_foo', { autoload = false, scope = 0 })
+ singl_eltkn_test('PlainIdentifier', 't', { autoload = false, scope = 0 })
+ singl_eltkn_test('PlainIdentifier', 'test5', { autoload = false, scope = 0 })
+ singl_eltkn_test('PlainIdentifier', 't0', { autoload = false, scope = 0 })
+ singl_eltkn_test('PlainIdentifier', 'test#var', { autoload = true, scope = 0 })
+ singl_eltkn_test('PlainIdentifier', 'test#var#val###', { autoload = true, scope = 0 })
+ singl_eltkn_test('PlainIdentifier', 't#####', { autoload = true, scope = 0 })
singl_eltkn_test('And', '&&')
singl_eltkn_test('Or', '||')
- singl_eltkn_test('Invalid', '&', {error='E112: Option name missing: %.*s'})
- singl_eltkn_test('Option', '&opt', {scope='Unspecified', name='opt'})
- singl_eltkn_test('Option', '&t_xx', {scope='Unspecified', name='t_xx'})
- singl_eltkn_test('Option', '&t_\r\r', {scope='Unspecified', name='t_\r\r'})
- singl_eltkn_test('Option', '&t_\t\t', {scope='Unspecified', name='t_\t\t'})
- singl_eltkn_test('Option', '&t_ ', {scope='Unspecified', name='t_ '})
- singl_eltkn_test('Option', '&g:opt', {scope='Global', name='opt'})
- singl_eltkn_test('Option', '&l:opt', {scope='Local', name='opt'})
- singl_eltkn_test('Invalid', '&l:', {error='E112: Option name missing: %.*s'})
- singl_eltkn_test('Invalid', '&g:', {error='E112: Option name missing: %.*s'})
- singl_eltkn_test('Register', '@', {name=-1})
- singl_eltkn_test('Register', '@a', {name='a'})
- singl_eltkn_test('Register', '@\r', {name=13})
- singl_eltkn_test('Register', '@ ', {name=' '})
- singl_eltkn_test('Register', '@\t', {name=9})
- singl_eltkn_test('SingleQuotedString', '\'test', {closed=false})
- singl_eltkn_test('SingleQuotedString', '\'test\'', {closed=true})
- singl_eltkn_test('SingleQuotedString', '\'\'\'\'', {closed=true})
- singl_eltkn_test('SingleQuotedString', '\'x\'\'\'', {closed=true})
- singl_eltkn_test('SingleQuotedString', '\'\'\'x\'', {closed=true})
- singl_eltkn_test('SingleQuotedString', '\'\'\'', {closed=false})
- singl_eltkn_test('SingleQuotedString', '\'x\'\'', {closed=false})
- singl_eltkn_test('SingleQuotedString', '\'\'\'x', {closed=false})
- singl_eltkn_test('DoubleQuotedString', '"test', {closed=false})
- singl_eltkn_test('DoubleQuotedString', '"test"', {closed=true})
- singl_eltkn_test('DoubleQuotedString', '"\\""', {closed=true})
- singl_eltkn_test('DoubleQuotedString', '"x\\""', {closed=true})
- singl_eltkn_test('DoubleQuotedString', '"\\"x"', {closed=true})
- singl_eltkn_test('DoubleQuotedString', '"\\"', {closed=false})
- singl_eltkn_test('DoubleQuotedString', '"x\\"', {closed=false})
- singl_eltkn_test('DoubleQuotedString', '"\\"x', {closed=false})
+ singl_eltkn_test('Invalid', '&', { error = 'E112: Option name missing: %.*s' })
+ singl_eltkn_test('Option', '&opt', { scope = 'Unspecified', name = 'opt' })
+ singl_eltkn_test('Option', '&t_xx', { scope = 'Unspecified', name = 't_xx' })
+ singl_eltkn_test('Option', '&t_\r\r', { scope = 'Unspecified', name = 't_\r\r' })
+ singl_eltkn_test('Option', '&t_\t\t', { scope = 'Unspecified', name = 't_\t\t' })
+ singl_eltkn_test('Option', '&t_ ', { scope = 'Unspecified', name = 't_ ' })
+ singl_eltkn_test('Option', '&g:opt', { scope = 'Global', name = 'opt' })
+ singl_eltkn_test('Option', '&l:opt', { scope = 'Local', name = 'opt' })
+ singl_eltkn_test('Invalid', '&l:', { error = 'E112: Option name missing: %.*s' })
+ singl_eltkn_test('Invalid', '&g:', { error = 'E112: Option name missing: %.*s' })
+ singl_eltkn_test('Register', '@', { name = -1 })
+ singl_eltkn_test('Register', '@a', { name = 'a' })
+ singl_eltkn_test('Register', '@\r', { name = 13 })
+ singl_eltkn_test('Register', '@ ', { name = ' ' })
+ singl_eltkn_test('Register', '@\t', { name = 9 })
+ singl_eltkn_test('SingleQuotedString', "'test", { closed = false })
+ singl_eltkn_test('SingleQuotedString', "'test'", { closed = true })
+ singl_eltkn_test('SingleQuotedString', "''''", { closed = true })
+ singl_eltkn_test('SingleQuotedString', "'x'''", { closed = true })
+ singl_eltkn_test('SingleQuotedString', "'''x'", { closed = true })
+ singl_eltkn_test('SingleQuotedString', "'''", { closed = false })
+ singl_eltkn_test('SingleQuotedString', "'x''", { closed = false })
+ singl_eltkn_test('SingleQuotedString', "'''x", { closed = false })
+ singl_eltkn_test('DoubleQuotedString', '"test', { closed = false })
+ singl_eltkn_test('DoubleQuotedString', '"test"', { closed = true })
+ singl_eltkn_test('DoubleQuotedString', '"\\""', { closed = true })
+ singl_eltkn_test('DoubleQuotedString', '"x\\""', { closed = true })
+ singl_eltkn_test('DoubleQuotedString', '"\\"x"', { closed = true })
+ singl_eltkn_test('DoubleQuotedString', '"\\"', { closed = false })
+ singl_eltkn_test('DoubleQuotedString', '"x\\"', { closed = false })
+ singl_eltkn_test('DoubleQuotedString', '"\\"x', { closed = false })
singl_eltkn_test('Not', '!')
- singl_eltkn_test('Assignment', '=', {type='Plain'})
+ singl_eltkn_test('Assignment', '=', { type = 'Plain' })
comparison_test('==', '!=', 'Equal')
comparison_test('=~', '!~', 'Matches')
comparison_test('>', '<=', 'Greater')
comparison_test('>=', '<', 'GreaterOrEqual')
singl_eltkn_test('Minus', '-')
- singl_eltkn_test('Assignment', '-=', {type='Subtract'})
+ singl_eltkn_test('Assignment', '-=', { type = 'Subtract' })
singl_eltkn_test('Arrow', '->')
- singl_eltkn_test('Invalid', '~', {error='E15: Unidentified character: %.*s'})
- simple_test({{data=nil, size=0}}, 'EOC', 0, {error='start.col >= #pstr'})
- simple_test({''}, 'EOC', 0, {error='start.col >= #pstr'})
- simple_test({'2.'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2e5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.2.'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.0x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.0e'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.0e+'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.0e-'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.0e+x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.0e-x'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.0e+1a'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.0e-1a'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'0b102'}, 'Number', 4, {data={is_float=false, base=2, val=2}, str='0b10'})
- simple_test({'10F'}, 'Number', 2, {data={is_float=false, base=10, val=10}, str='10'})
- simple_test({'0x0123456789ABCDEFG'}, 'Number', 18, {data={is_float=false, base=16, val=81985529216486895}, str='0x0123456789ABCDEF'})
- simple_test({{data='00', size=2}}, 'Number', 2, {data={is_float=false, base=8, val=0}, str='00'})
- simple_test({{data='009', size=2}}, 'Number', 2, {data={is_float=false, base=8, val=0}, str='00'})
- simple_test({{data='01', size=1}}, 'Number', 1, {data={is_float=false, base=10, val=0}, str='0'})
+ singl_eltkn_test('Invalid', '~', { error = 'E15: Unidentified character: %.*s' })
+ simple_test({ { data = nil, size = 0 } }, 'EOC', 0, { error = 'start.col >= #pstr' })
+ simple_test({ '' }, 'EOC', 0, { error = 'start.col >= #pstr' })
+ simple_test(
+ { '2.' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2e5' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.x' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.2.' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.0x' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.0e' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.0e+' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.0e-' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.0e+x' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.0e-x' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.0e+1a' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.0e-1a' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '0b102' },
+ 'Number',
+ 4,
+ { data = { is_float = false, base = 2, val = 2 }, str = '0b10' }
+ )
+ simple_test(
+ { '10F' },
+ 'Number',
+ 2,
+ { data = { is_float = false, base = 10, val = 10 }, str = '10' }
+ )
+ simple_test({ '0x0123456789ABCDEFG' }, 'Number', 18, {
+ data = { is_float = false, base = 16, val = 81985529216486895 },
+ str = '0x0123456789ABCDEF',
+ })
+ simple_test(
+ { { data = '00', size = 2 } },
+ 'Number',
+ 2,
+ { data = { is_float = false, base = 8, val = 0 }, str = '00' }
+ )
+ simple_test(
+ { { data = '009', size = 2 } },
+ 'Number',
+ 2,
+ { data = { is_float = false, base = 8, val = 0 }, str = '00' }
+ )
+ simple_test(
+ { { data = '01', size = 1 } },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 0 }, str = '0' }
+ )
end
local function regular_scope_tests()
@@ -312,29 +417,104 @@ describe('Expressions lexer', function()
scope_test('l')
scope_test('a')
- simple_test({'g:'}, 'PlainIdentifier', 2, {data={scope='g', autoload=false}, str='g:'})
- simple_test({'g:is#foo'}, 'PlainIdentifier', 8, {data={scope='g', autoload=true}, str='g:is#foo'})
- simple_test({'g:isnot#foo'}, 'PlainIdentifier', 11, {data={scope='g', autoload=true}, str='g:isnot#foo'})
+ simple_test(
+ { 'g:' },
+ 'PlainIdentifier',
+ 2,
+ { data = { scope = 'g', autoload = false }, str = 'g:' }
+ )
+ simple_test(
+ { 'g:is#foo' },
+ 'PlainIdentifier',
+ 8,
+ { data = { scope = 'g', autoload = true }, str = 'g:is#foo' }
+ )
+ simple_test(
+ { 'g:isnot#foo' },
+ 'PlainIdentifier',
+ 11,
+ { data = { scope = 'g', autoload = true }, str = 'g:isnot#foo' }
+ )
end
local function regular_is_tests()
comparison_test('is', 'isnot', 'Identical')
- simple_test({'is'}, 'Comparison', 2, {data={type='Identical', inv=false, ccs='UseOption'}, str='is'})
- simple_test({'isnot'}, 'Comparison', 5, {data={type='Identical', inv=true, ccs='UseOption'}, str='isnot'})
- simple_test({'is?'}, 'Comparison', 3, {data={type='Identical', inv=false, ccs='IgnoreCase'}, str='is?'})
- simple_test({'isnot?'}, 'Comparison', 6, {data={type='Identical', inv=true, ccs='IgnoreCase'}, str='isnot?'})
- simple_test({'is#'}, 'Comparison', 3, {data={type='Identical', inv=false, ccs='MatchCase'}, str='is#'})
- simple_test({'isnot#'}, 'Comparison', 6, {data={type='Identical', inv=true, ccs='MatchCase'}, str='isnot#'})
- simple_test({'is#foo'}, 'Comparison', 3, {data={type='Identical', inv=false, ccs='MatchCase'}, str='is#'})
- simple_test({'isnot#foo'}, 'Comparison', 6, {data={type='Identical', inv=true, ccs='MatchCase'}, str='isnot#'})
+ simple_test(
+ { 'is' },
+ 'Comparison',
+ 2,
+ { data = { type = 'Identical', inv = false, ccs = 'UseOption' }, str = 'is' }
+ )
+ simple_test(
+ { 'isnot' },
+ 'Comparison',
+ 5,
+ { data = { type = 'Identical', inv = true, ccs = 'UseOption' }, str = 'isnot' }
+ )
+ simple_test(
+ { 'is?' },
+ 'Comparison',
+ 3,
+ { data = { type = 'Identical', inv = false, ccs = 'IgnoreCase' }, str = 'is?' }
+ )
+ simple_test(
+ { 'isnot?' },
+ 'Comparison',
+ 6,
+ { data = { type = 'Identical', inv = true, ccs = 'IgnoreCase' }, str = 'isnot?' }
+ )
+ simple_test(
+ { 'is#' },
+ 'Comparison',
+ 3,
+ { data = { type = 'Identical', inv = false, ccs = 'MatchCase' }, str = 'is#' }
+ )
+ simple_test(
+ { 'isnot#' },
+ 'Comparison',
+ 6,
+ { data = { type = 'Identical', inv = true, ccs = 'MatchCase' }, str = 'isnot#' }
+ )
+ simple_test(
+ { 'is#foo' },
+ 'Comparison',
+ 3,
+ { data = { type = 'Identical', inv = false, ccs = 'MatchCase' }, str = 'is#' }
+ )
+ simple_test(
+ { 'isnot#foo' },
+ 'Comparison',
+ 6,
+ { data = { type = 'Identical', inv = true, ccs = 'MatchCase' }, str = 'isnot#' }
+ )
end
local function regular_number_tests()
- simple_test({'2.0'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.0e5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.0e+5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({'2.0e-5'}, 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
+ simple_test(
+ { '2.0' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.0e5' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.0e+5' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { '2.0e-5' },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
end
local function regular_eoc_tests()
@@ -369,7 +549,12 @@ describe('Expressions lexer', function()
regular_is_tests()
regular_number_tests()
- simple_test({'g:'}, 'PlainIdentifier', 1, {data={scope=0, autoload=false}, str='g'})
+ simple_test(
+ { 'g:' },
+ 'PlainIdentifier',
+ 1,
+ { data = { scope = 0, autoload = false }, str = 'g' }
+ )
end)
itp('allows floats', function()
flags = tonumber(lib.kELFlagAllowFloat)
@@ -379,20 +564,72 @@ describe('Expressions lexer', function()
regular_scope_tests()
regular_is_tests()
- simple_test({'2.2'}, 'Number', 3, {data={is_float=true, base=10, val=2.2}, str='2.2'})
- simple_test({'2.0e5'}, 'Number', 5, {data={is_float=true, base=10, val=2e5}, str='2.0e5'})
- simple_test({'2.0e+5'}, 'Number', 6, {data={is_float=true, base=10, val=2e5}, str='2.0e+5'})
- simple_test({'2.0e-5'}, 'Number', 6, {data={is_float=true, base=10, val=2e-5}, str='2.0e-5'})
- simple_test({'2.500000e-5'}, 'Number', 11, {data={is_float=true, base=10, val=2.5e-5}, str='2.500000e-5'})
- simple_test({'2.5555e2'}, 'Number', 8, {data={is_float=true, base=10, val=2.5555e2}, str='2.5555e2'})
- simple_test({'2.5555e+2'}, 'Number', 9, {data={is_float=true, base=10, val=2.5555e2}, str='2.5555e+2'})
- simple_test({'2.5555e-2'}, 'Number', 9, {data={is_float=true, base=10, val=2.5555e-2}, str='2.5555e-2'})
- simple_test({{data='2.5e-5', size=3}},
- 'Number', 3, {data={is_float=true, base=10, val=2.5}, str='2.5'})
- simple_test({{data='2.5e5', size=4}},
- 'Number', 1, {data={is_float=false, base=10, val=2}, str='2'})
- simple_test({{data='2.5e-50', size=6}},
- 'Number', 6, {data={is_float=true, base=10, val=2.5e-5}, str='2.5e-5'})
+ simple_test(
+ { '2.2' },
+ 'Number',
+ 3,
+ { data = { is_float = true, base = 10, val = 2.2 }, str = '2.2' }
+ )
+ simple_test(
+ { '2.0e5' },
+ 'Number',
+ 5,
+ { data = { is_float = true, base = 10, val = 2e5 }, str = '2.0e5' }
+ )
+ simple_test(
+ { '2.0e+5' },
+ 'Number',
+ 6,
+ { data = { is_float = true, base = 10, val = 2e5 }, str = '2.0e+5' }
+ )
+ simple_test(
+ { '2.0e-5' },
+ 'Number',
+ 6,
+ { data = { is_float = true, base = 10, val = 2e-5 }, str = '2.0e-5' }
+ )
+ simple_test(
+ { '2.500000e-5' },
+ 'Number',
+ 11,
+ { data = { is_float = true, base = 10, val = 2.5e-5 }, str = '2.500000e-5' }
+ )
+ simple_test(
+ { '2.5555e2' },
+ 'Number',
+ 8,
+ { data = { is_float = true, base = 10, val = 2.5555e2 }, str = '2.5555e2' }
+ )
+ simple_test(
+ { '2.5555e+2' },
+ 'Number',
+ 9,
+ { data = { is_float = true, base = 10, val = 2.5555e2 }, str = '2.5555e+2' }
+ )
+ simple_test(
+ { '2.5555e-2' },
+ 'Number',
+ 9,
+ { data = { is_float = true, base = 10, val = 2.5555e-2 }, str = '2.5555e-2' }
+ )
+ simple_test(
+ { { data = '2.5e-5', size = 3 } },
+ 'Number',
+ 3,
+ { data = { is_float = true, base = 10, val = 2.5 }, str = '2.5' }
+ )
+ simple_test(
+ { { data = '2.5e5', size = 4 } },
+ 'Number',
+ 1,
+ { data = { is_float = false, base = 10, val = 2 }, str = '2' }
+ )
+ simple_test(
+ { { data = '2.5e-50', size = 6 } },
+ 'Number',
+ 6,
+ { data = { is_float = true, base = 10, val = 2.5e-5 }, str = '2.5e-5' }
+ )
end)
itp('treats `is` as an identifier', function()
flags = tonumber(lib.kELFlagIsNotCmp)
@@ -402,14 +639,54 @@ describe('Expressions lexer', function()
regular_scope_tests()
regular_number_tests()
- simple_test({'is'}, 'PlainIdentifier', 2, {data={scope=0, autoload=false}, str='is'})
- simple_test({'isnot'}, 'PlainIdentifier', 5, {data={scope=0, autoload=false}, str='isnot'})
- simple_test({'is?'}, 'PlainIdentifier', 2, {data={scope=0, autoload=false}, str='is'})
- simple_test({'isnot?'}, 'PlainIdentifier', 5, {data={scope=0, autoload=false}, str='isnot'})
- simple_test({'is#'}, 'PlainIdentifier', 3, {data={scope=0, autoload=true}, str='is#'})
- simple_test({'isnot#'}, 'PlainIdentifier', 6, {data={scope=0, autoload=true}, str='isnot#'})
- simple_test({'is#foo'}, 'PlainIdentifier', 6, {data={scope=0, autoload=true}, str='is#foo'})
- simple_test({'isnot#foo'}, 'PlainIdentifier', 9, {data={scope=0, autoload=true}, str='isnot#foo'})
+ simple_test(
+ { 'is' },
+ 'PlainIdentifier',
+ 2,
+ { data = { scope = 0, autoload = false }, str = 'is' }
+ )
+ simple_test(
+ { 'isnot' },
+ 'PlainIdentifier',
+ 5,
+ { data = { scope = 0, autoload = false }, str = 'isnot' }
+ )
+ simple_test(
+ { 'is?' },
+ 'PlainIdentifier',
+ 2,
+ { data = { scope = 0, autoload = false }, str = 'is' }
+ )
+ simple_test(
+ { 'isnot?' },
+ 'PlainIdentifier',
+ 5,
+ { data = { scope = 0, autoload = false }, str = 'isnot' }
+ )
+ simple_test(
+ { 'is#' },
+ 'PlainIdentifier',
+ 3,
+ { data = { scope = 0, autoload = true }, str = 'is#' }
+ )
+ simple_test(
+ { 'isnot#' },
+ 'PlainIdentifier',
+ 6,
+ { data = { scope = 0, autoload = true }, str = 'isnot#' }
+ )
+ simple_test(
+ { 'is#foo' },
+ 'PlainIdentifier',
+ 6,
+ { data = { scope = 0, autoload = true }, str = 'is#foo' }
+ )
+ simple_test(
+ { 'isnot#foo' },
+ 'PlainIdentifier',
+ 9,
+ { data = { scope = 0, autoload = true }, str = 'isnot#foo' }
+ )
end)
itp('forbids EOC', function()
flags = tonumber(lib.kELFlagForbidEOC)
@@ -419,8 +696,8 @@ describe('Expressions lexer', function()
regular_is_tests()
regular_number_tests()
- singl_eltkn_test('Invalid', '|', {error='E15: Unexpected EOC character: %.*s'})
- singl_eltkn_test('Invalid', '\0', {error='E15: Unexpected EOC character: %.*s'})
- singl_eltkn_test('Invalid', '\n', {error='E15: Unexpected EOC character: %.*s'})
+ singl_eltkn_test('Invalid', '|', { error = 'E15: Unexpected EOC character: %.*s' })
+ singl_eltkn_test('Invalid', '\0', { error = 'E15: Unexpected EOC character: %.*s' })
+ singl_eltkn_test('Invalid', '\n', { error = 'E15: Unexpected EOC character: %.*s' })
end)
end)
diff --git a/test/unit/viml/expressions/parser_spec.lua b/test/unit/viml/expressions/parser_spec.lua
index 51a703b593..c7d3f8532f 100644
--- a/test/unit/viml/expressions/parser_spec.lua
+++ b/test/unit/viml/expressions/parser_spec.lua
@@ -14,8 +14,8 @@ local ffi = helpers.ffi
local neq = helpers.neq
local eq = helpers.eq
local mergedicts_copy = helpers.mergedicts_copy
-local format_string = helpers.format_string
-local format_luav = helpers.format_luav
+local format_string = require('test.format_string').format_string
+local format_luav = require('test.format_string').format_luav
local intchar2lua = helpers.intchar2lua
local dictdiff = helpers.dictdiff
@@ -25,100 +25,99 @@ local conv_cmp_type = viml_helpers.conv_cmp_type
local pstate_set_str = viml_helpers.pstate_set_str
local conv_expr_asgn_type = viml_helpers.conv_expr_asgn_type
-local lib = cimport('./src/nvim/viml/parser/expressions.h',
- './src/nvim/syntax.h')
+local lib = cimport('./src/nvim/viml/parser/expressions.h', './src/nvim/syntax.h')
local alloc_log = alloc_log_new()
local predefined_hl_defs = {
-- From highlight_init_both
- Conceal=true,
- Cursor=true,
- lCursor=true,
- DiffText=true,
- ErrorMsg=true,
- IncSearch=true,
- ModeMsg=true,
- NonText=true,
- PmenuSbar=true,
- StatusLine=true,
- StatusLineNC=true,
- TabLineFill=true,
- TabLineSel=true,
- TermCursor=true,
- VertSplit=true,
- WildMenu=true,
- WinSeparator=true,
- EndOfBuffer=true,
- QuickFixLine=true,
- Substitute=true,
- Whitespace=true,
- Error=true,
- Todo=true,
- String=true,
- Character=true,
- Number=true,
- Boolean=true,
- Float=true,
- Function=true,
- Conditional=true,
- Repeat=true,
- Label=true,
- Operator=true,
- Keyword=true,
- Exception=true,
- Include=true,
- Define=true,
- Macro=true,
- PreCondit=true,
- StorageClass=true,
- Structure=true,
- Typedef=true,
- Tag=true,
- SpecialChar=true,
- Delimiter=true,
- SpecialComment=true,
- Debug=true,
+ Conceal = true,
+ Cursor = true,
+ lCursor = true,
+ DiffText = true,
+ ErrorMsg = true,
+ IncSearch = true,
+ ModeMsg = true,
+ NonText = true,
+ PmenuSbar = true,
+ StatusLine = true,
+ StatusLineNC = true,
+ TabLineFill = true,
+ TabLineSel = true,
+ TermCursor = true,
+ VertSplit = true,
+ WildMenu = true,
+ WinSeparator = true,
+ EndOfBuffer = true,
+ QuickFixLine = true,
+ Substitute = true,
+ Whitespace = true,
+ Error = true,
+ Todo = true,
+ String = true,
+ Character = true,
+ Number = true,
+ Boolean = true,
+ Float = true,
+ Function = true,
+ Conditional = true,
+ Repeat = true,
+ Label = true,
+ Operator = true,
+ Keyword = true,
+ Exception = true,
+ Include = true,
+ Define = true,
+ Macro = true,
+ PreCondit = true,
+ StorageClass = true,
+ Structure = true,
+ Typedef = true,
+ Tag = true,
+ SpecialChar = true,
+ Delimiter = true,
+ SpecialComment = true,
+ Debug = true,
-- From highlight_init_(dark|light)
- ColorColumn=true,
- CursorColumn=true,
- CursorLine=true,
- CursorLineNr=true,
- DiffAdd=true,
- DiffChange=true,
- DiffDelete=true,
- Directory=true,
- FoldColumn=true,
- Folded=true,
- LineNr=true,
- MatchParen=true,
- MoreMsg=true,
- Pmenu=true,
- PmenuSel=true,
- PmenuThumb=true,
- Question=true,
- Search=true,
- SignColumn=true,
- SpecialKey=true,
- SpellBad=true,
- SpellCap=true,
- SpellLocal=true,
- SpellRare=true,
- TabLine=true,
- Title=true,
- Visual=true,
- WarningMsg=true,
- Normal=true,
- Comment=true,
- Constant=true,
- Special=true,
- Identifier=true,
- Statement=true,
- PreProc=true,
- Type=true,
- Underlined=true,
- Ignore=true,
+ ColorColumn = true,
+ CursorColumn = true,
+ CursorLine = true,
+ CursorLineNr = true,
+ DiffAdd = true,
+ DiffChange = true,
+ DiffDelete = true,
+ Directory = true,
+ FoldColumn = true,
+ Folded = true,
+ LineNr = true,
+ MatchParen = true,
+ MoreMsg = true,
+ Pmenu = true,
+ PmenuSel = true,
+ PmenuThumb = true,
+ Question = true,
+ Search = true,
+ SignColumn = true,
+ SpecialKey = true,
+ SpellBad = true,
+ SpellCap = true,
+ SpellLocal = true,
+ SpellRare = true,
+ TabLine = true,
+ Title = true,
+ Visual = true,
+ WarningMsg = true,
+ Normal = true,
+ Comment = true,
+ Constant = true,
+ Special = true,
+ Identifier = true,
+ Statement = true,
+ PreProc = true,
+ Type = true,
+ Underlined = true,
+ Ignore = true,
}
local nvim_hl_defs = {}
@@ -136,22 +135,18 @@ child_call_once(function()
-- linking, otherwise it will be created as cleared. So existence
-- of the group is checked here and not in the next pass over
-- nvim_hl_defs.
- eq(true, not not (nvim_hl_defs[grp_link]
- or predefined_hl_defs[grp_link]))
- eq(false, not not (nvim_hl_defs[new_grp]
- or predefined_hl_defs[new_grp]))
- nvim_hl_defs[new_grp] = {'link', grp_link}
+ eq(true, not not (nvim_hl_defs[grp_link] or predefined_hl_defs[grp_link]))
+ eq(false, not not (nvim_hl_defs[new_grp] or predefined_hl_defs[new_grp]))
+ nvim_hl_defs[new_grp] = { 'link', grp_link }
else
local new_grp, grp_args = s:match('^(%w+) (.*)')
neq(nil, new_grp)
- eq(false, not not (nvim_hl_defs[new_grp]
- or predefined_hl_defs[new_grp]))
- nvim_hl_defs[new_grp] = {'definition', grp_args}
+ eq(false, not not (nvim_hl_defs[new_grp] or predefined_hl_defs[new_grp]))
+ nvim_hl_defs[new_grp] = { 'definition', grp_args }
end
end)
if not err then
- msg = format_string(
- 'Error while processing string %s at position %u:\n%s', s, i, msg)
+ msg = format_string('Error while processing string %s at position %u:\n%s', s, i, msg)
error(msg)
end
i = i + 1
@@ -185,12 +180,12 @@ local function hls_to_hl_fs(hls)
local col_shift = col - next_col
assert(col_shift >= 0)
next_col = col + #str
- ret[i] = format_string('hl(%r, %r%s)',
- group,
- str,
- (col_shift == 0
- and ''
- or (', %u'):format(col_shift)))
+ ret[i] = format_string(
+ 'hl(%r, %r%s)',
+ group,
+ str,
+ (col_shift == 0 and '' or (', %u'):format(col_shift))
+ )
end
return ret
end
@@ -205,9 +200,9 @@ local function format_check(expr, format_check_data, opts)
dig_len = #opts.funcname + 2
else
print(format_string('\n_check_parsing(%r, %r, {', opts, expr))
- dig_len = #('_check_parsing(, \'') + #(format_string('%r', opts))
+ dig_len = #"_check_parsing(, '" + #(format_string('%r', opts))
end
- local digits = ' --' .. (' '):rep(dig_len - #(' --'))
+ local digits = ' --' .. (' '):rep(dig_len - #' --')
local digits2 = digits:sub(1, -10)
for i = 0, #expr - 1 do
if i % 10 == 0 then
@@ -240,10 +235,9 @@ local function format_check(expr, format_check_data, opts)
diffs[flags] = dictdiff(zdata, v)
if diffs[flags] then
if flags == 3 + zflags then
- if (dictdiff(format_check_data[1 + zflags],
- format_check_data[3 + zflags]) == nil
- or dictdiff(format_check_data[2 + zflags],
- format_check_data[3 + zflags]) == nil)
+ if
+ dictdiff(format_check_data[1 + zflags], format_check_data[3 + zflags]) == nil
+ or dictdiff(format_check_data[2 + zflags], format_check_data[3 + zflags]) == nil
then
diffs[flags] = nil
else
@@ -268,7 +262,7 @@ local function format_check(expr, format_check_data, opts)
end
if diff.hl_fs then
print(' hl_fs = ' .. format_luav(diff.hl_fs, ' ', {
- literal_strings=true
+ literal_strings = true,
}) .. ',')
end
print(' },')
@@ -280,47 +274,54 @@ local function format_check(expr, format_check_data, opts)
end
local east_node_type_tab
-make_enum_conv_tab(lib, {
- 'kExprNodeMissing',
- 'kExprNodeOpMissing',
- 'kExprNodeTernary',
- 'kExprNodeTernaryValue',
- 'kExprNodeRegister',
- 'kExprNodeSubscript',
- 'kExprNodeListLiteral',
- 'kExprNodeUnaryPlus',
- 'kExprNodeBinaryPlus',
- 'kExprNodeNested',
- 'kExprNodeCall',
- 'kExprNodePlainIdentifier',
- 'kExprNodePlainKey',
- 'kExprNodeComplexIdentifier',
- 'kExprNodeUnknownFigure',
- 'kExprNodeLambda',
- 'kExprNodeDictLiteral',
- 'kExprNodeCurlyBracesIdentifier',
- 'kExprNodeComma',
- 'kExprNodeColon',
- 'kExprNodeArrow',
- 'kExprNodeComparison',
- 'kExprNodeConcat',
- 'kExprNodeConcatOrSubscript',
- 'kExprNodeInteger',
- 'kExprNodeFloat',
- 'kExprNodeSingleQuotedString',
- 'kExprNodeDoubleQuotedString',
- 'kExprNodeOr',
- 'kExprNodeAnd',
- 'kExprNodeUnaryMinus',
- 'kExprNodeBinaryMinus',
- 'kExprNodeNot',
- 'kExprNodeMultiplication',
- 'kExprNodeDivision',
- 'kExprNodeMod',
- 'kExprNodeOption',
- 'kExprNodeEnvironment',
- 'kExprNodeAssignment',
-}, 'kExprNode', function(ret) east_node_type_tab = ret end)
+make_enum_conv_tab(
+ lib,
+ {
+ 'kExprNodeMissing',
+ 'kExprNodeOpMissing',
+ 'kExprNodeTernary',
+ 'kExprNodeTernaryValue',
+ 'kExprNodeRegister',
+ 'kExprNodeSubscript',
+ 'kExprNodeListLiteral',
+ 'kExprNodeUnaryPlus',
+ 'kExprNodeBinaryPlus',
+ 'kExprNodeNested',
+ 'kExprNodeCall',
+ 'kExprNodePlainIdentifier',
+ 'kExprNodePlainKey',
+ 'kExprNodeComplexIdentifier',
+ 'kExprNodeUnknownFigure',
+ 'kExprNodeLambda',
+ 'kExprNodeDictLiteral',
+ 'kExprNodeCurlyBracesIdentifier',
+ 'kExprNodeComma',
+ 'kExprNodeColon',
+ 'kExprNodeArrow',
+ 'kExprNodeComparison',
+ 'kExprNodeConcat',
+ 'kExprNodeConcatOrSubscript',
+ 'kExprNodeInteger',
+ 'kExprNodeFloat',
+ 'kExprNodeSingleQuotedString',
+ 'kExprNodeDoubleQuotedString',
+ 'kExprNodeOr',
+ 'kExprNodeAnd',
+ 'kExprNodeUnaryMinus',
+ 'kExprNodeBinaryMinus',
+ 'kExprNodeNot',
+ 'kExprNodeMultiplication',
+ 'kExprNodeDivision',
+ 'kExprNodeMod',
+ 'kExprNodeOption',
+ 'kExprNodeEnvironment',
+ 'kExprNodeAssignment',
+ },
+ 'kExprNode',
+ function(ret)
+ east_node_type_tab = ret
+ end
+)
local function conv_east_node_type(typ)
return conv_enum(east_node_type_tab, typ)
@@ -346,25 +347,35 @@ local function eastnode2lua(pstate, eastnode, checked_nodes)
ret_str = ('%u:%u:%s'):format(str.start.line, str.start.col, str.str)
end
if typ == 'Register' then
- typ = typ .. ('(name=%s)'):format(
- tostring(intchar2lua(eastnode.data.reg.name)))
+ typ = typ .. ('(name=%s)'):format(tostring(intchar2lua(eastnode.data.reg.name)))
elseif typ == 'PlainIdentifier' then
- typ = typ .. ('(scope=%s,ident=%s)'):format(
- tostring(intchar2lua(eastnode.data.var.scope)),
- ffi.string(eastnode.data.var.ident, eastnode.data.var.ident_len))
+ typ = typ
+ .. ('(scope=%s,ident=%s)'):format(
+ tostring(intchar2lua(eastnode.data.var.scope)),
+ ffi.string(eastnode.data.var.ident, eastnode.data.var.ident_len)
+ )
elseif typ == 'PlainKey' then
- typ = typ .. ('(key=%s)'):format(
- ffi.string(eastnode.data.var.ident, eastnode.data.var.ident_len))
- elseif (typ == 'UnknownFigure' or typ == 'DictLiteral'
- or typ == 'CurlyBracesIdentifier' or typ == 'Lambda') then
- typ = typ .. ('(%s)'):format(
- (eastnode.data.fig.type_guesses.allow_lambda and '\\' or '-')
- .. (eastnode.data.fig.type_guesses.allow_dict and 'd' or '-')
- .. (eastnode.data.fig.type_guesses.allow_ident and 'i' or '-'))
+ typ = typ
+ .. ('(key=%s)'):format(ffi.string(eastnode.data.var.ident, eastnode.data.var.ident_len))
+ elseif
+ typ == 'UnknownFigure'
+ or typ == 'DictLiteral'
+ or typ == 'CurlyBracesIdentifier'
+ or typ == 'Lambda'
+ then
+ typ = typ
+ .. ('(%s)'):format(
+ (eastnode.data.fig.type_guesses.allow_lambda and '\\' or '-')
+ .. (eastnode.data.fig.type_guesses.allow_dict and 'd' or '-')
+ .. (eastnode.data.fig.type_guesses.allow_ident and 'i' or '-')
+ )
elseif typ == 'Comparison' then
- typ = typ .. ('(type=%s,inv=%u,ccs=%s)'):format(
- conv_cmp_type(eastnode.data.cmp.type), eastnode.data.cmp.inv and 1 or 0,
- conv_ccs(eastnode.data.cmp.ccs))
+ typ = typ
+ .. ('(type=%s,inv=%u,ccs=%s)'):format(
+ conv_cmp_type(eastnode.data.cmp.type),
+ eastnode.data.cmp.inv and 1 or 0,
+ conv_ccs(eastnode.data.cmp.ccs)
+ )
elseif typ == 'Integer' then
typ = typ .. ('(val=%u)'):format(tonumber(eastnode.data.num.value))
elseif typ == 'Float' then
@@ -380,11 +391,13 @@ local function eastnode2lua(pstate, eastnode, checked_nodes)
typ = ('%s(scope=%s,ident=%s)'):format(
typ,
tostring(intchar2lua(eastnode.data.opt.scope)),
- ffi.string(eastnode.data.opt.ident, eastnode.data.opt.ident_len))
+ ffi.string(eastnode.data.opt.ident, eastnode.data.opt.ident_len)
+ )
elseif typ == 'Environment' then
typ = ('%s(ident=%s)'):format(
typ,
- ffi.string(eastnode.data.env.ident, eastnode.data.env.ident_len))
+ ffi.string(eastnode.data.env.ident, eastnode.data.env.ident_len)
+ )
elseif typ == 'Assignment' then
typ = ('%s(%s)'):format(typ, conv_expr_asgn_type(eastnode.data.ass.type))
end
@@ -433,22 +446,21 @@ local function phl2lua(pstate)
local ret = {}
for i = 0, (tonumber(pstate.colors.size) - 1) do
local chunk = pstate.colors.items[i]
- local chunk_tbl = pstate_set_str(
- pstate, chunk.start, chunk.end_col - chunk.start.col, {
- group = ffi.string(chunk.group),
- })
+ local chunk_tbl = pstate_set_str(pstate, chunk.start, chunk.end_col - chunk.start.col, {
+ group = ffi.string(chunk.group),
+ })
ret[i + 1] = ('%s:%u:%u:%s'):format(
chunk_tbl.group,
chunk_tbl.start.line,
chunk_tbl.start.col,
- chunk_tbl.str)
+ chunk_tbl.str
+ )
end
return ret
end
describe('Expressions parser', function()
- local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs,
- nz_flags_exps)
+ local function _check_parsing(opts, str, exp_ast, exp_highlighting_fs, nz_flags_exps)
local zflags = opts.flags[1]
nz_flags_exps = nz_flags_exps or {}
local format_check_data = {}
@@ -460,12 +472,12 @@ describe('Expressions parser', function()
end
alloc_log:check({})
- local pstate = new_pstate({str})
+ local pstate = new_pstate({ str })
local east = lib.viml_pexpr_parse(pstate, flags)
local ast = east2lua(str, pstate, east)
local hls = phl2lua(pstate)
if exp_ast == nil then
- format_check_data[flags] = {ast=ast, hl_fs=hls_to_hl_fs(hls)}
+ format_check_data[flags] = { ast = ast, hl_fs = hls_to_hl_fs(hls) }
else
local exps = {
ast = exp_ast,
@@ -499,8 +511,7 @@ describe('Expressions parser', function()
alloc_log:check({})
end)
if not err then
- msg = format_string('Error while processing test (%r, %u):\n%s',
- str, flags, msg)
+ msg = format_string('Error while processing test (%r, %u):\n%s', str, flags, msg)
error(msg)
end
end
@@ -514,16 +525,11 @@ describe('Expressions parser', function()
error(('Unknown group: Nvim%s'):format(group))
end
local col = next_col + (shift or 0)
- return (('%s:%u:%u:%s'):format(
- 'Nvim' .. group,
- 0,
- col,
- str)), (col + #str)
+ return (('%s:%u:%u:%s'):format('Nvim' .. group, 0, col, str)), (col + #str)
end
end
local function fmtn(typ, args, rest)
return ('%s(%s)%s'):format(typ, args, rest)
end
- require('test.unit.viml.expressions.parser_tests')(
- itp, _check_parsing, hl, fmtn)
+ require('test.unit.viml.expressions.parser_tests')(itp, _check_parsing, hl, fmtn)
end)
diff --git a/test/unit/viml/expressions/parser_tests.lua b/test/unit/viml/expressions/parser_tests.lua
index da61672bb1..aa2bf740de 100644
--- a/test/unit/viml/expressions/parser_tests.lua
+++ b/test/unit/viml/expressions/parser_tests.lua
@@ -1,15 +1,13 @@
-local global_helpers = require('test.helpers')
-
-local REMOVE_THIS = global_helpers.REMOVE_THIS
+local REMOVE_THIS = vim.NIL
return function(itp, _check_parsing, hl, fmtn)
local function check_parsing(...)
- return _check_parsing({flags={0, 1, 2, 3}, funcname='check_parsing'}, ...)
+ return _check_parsing({ flags = { 0, 1, 2, 3 }, funcname = 'check_parsing' }, ...)
end
local function check_asgn_parsing(...)
return _check_parsing({
- flags={4, 5, 6, 7},
- funcname='check_asgn_parsing',
+ flags = { 4, 5, 6, 7 },
+ funcname = 'check_asgn_parsing',
}, ...)
end
itp('works with + and @a', function()
@@ -142,7 +140,7 @@ return function(itp, _check_parsing, hl, fmtn)
len = 2,
err = REMOVE_THIS,
ast = {
- 'Register(name=a):0:0:@a'
+ 'Register(name=a):0:0:@a',
},
},
hl_fs = {
@@ -174,7 +172,7 @@ return function(itp, _check_parsing, hl, fmtn)
len = 6,
err = REMOVE_THIS,
ast = {
- 'Register(name=a):0:0: @a'
+ 'Register(name=a):0:0: @a',
},
},
hl_fs = {
@@ -541,7 +539,7 @@ return function(itp, _check_parsing, hl, fmtn)
children = {
{
'Nested:0:4:(',
- children = { 'Register(name=b):0:5:@b' }
+ children = { 'Register(name=b):0:5:@b' },
},
},
},
@@ -579,7 +577,7 @@ return function(itp, _check_parsing, hl, fmtn)
children = {
{
'Nested:0:4:(',
- children = { 'Register(name=b):0:5:@b' }
+ children = { 'Register(name=b):0:5:@b' },
},
},
},
@@ -600,13 +598,13 @@ return function(itp, _check_parsing, hl, fmtn)
hl('BinaryPlus', '+'),
hl('Register', '@c'),
})
- check_parsing(
- '@a + (@b + @c) + @d(@e) + (+@f) + ((+@g(@h))(@j)(@k))(@l)', {--[[
+ check_parsing('@a + (@b + @c) + @d(@e) + (+@f) + ((+@g(@h))(@j)(@k))(@l)', {--[[
| | | | | | | | || | | || | | ||| || || || ||
000000000011111111112222222222333333333344444444445555555
012345678901234567890123456789012345678901234567890123456
]]
- ast = {{
+ ast = {
+ {
'BinaryPlus:0:31: +',
children = {
{
@@ -696,45 +694,46 @@ return function(itp, _check_parsing, hl, fmtn)
},
},
},
- }},
- }, {
- hl('Register', '@a'),
- hl('BinaryPlus', '+', 1),
- hl('NestingParenthesis', '(', 1),
- hl('Register', '@b'),
- hl('BinaryPlus', '+', 1),
- hl('Register', '@c', 1),
- hl('NestingParenthesis', ')'),
- hl('BinaryPlus', '+', 1),
- hl('Register', '@d', 1),
- hl('CallingParenthesis', '('),
- hl('Register', '@e'),
- hl('CallingParenthesis', ')'),
- hl('BinaryPlus', '+', 1),
- hl('NestingParenthesis', '(', 1),
- hl('UnaryPlus', '+'),
- hl('Register', '@f'),
- hl('NestingParenthesis', ')'),
- hl('BinaryPlus', '+', 1),
- hl('NestingParenthesis', '(', 1),
- hl('NestingParenthesis', '('),
- hl('UnaryPlus', '+'),
- hl('Register', '@g'),
- hl('CallingParenthesis', '('),
- hl('Register', '@h'),
- hl('CallingParenthesis', ')'),
- hl('NestingParenthesis', ')'),
- hl('CallingParenthesis', '('),
- hl('Register', '@j'),
- hl('CallingParenthesis', ')'),
- hl('CallingParenthesis', '('),
- hl('Register', '@k'),
- hl('CallingParenthesis', ')'),
- hl('NestingParenthesis', ')'),
- hl('CallingParenthesis', '('),
- hl('Register', '@l'),
- hl('CallingParenthesis', ')'),
- })
+ },
+ },
+ }, {
+ hl('Register', '@a'),
+ hl('BinaryPlus', '+', 1),
+ hl('NestingParenthesis', '(', 1),
+ hl('Register', '@b'),
+ hl('BinaryPlus', '+', 1),
+ hl('Register', '@c', 1),
+ hl('NestingParenthesis', ')'),
+ hl('BinaryPlus', '+', 1),
+ hl('Register', '@d', 1),
+ hl('CallingParenthesis', '('),
+ hl('Register', '@e'),
+ hl('CallingParenthesis', ')'),
+ hl('BinaryPlus', '+', 1),
+ hl('NestingParenthesis', '(', 1),
+ hl('UnaryPlus', '+'),
+ hl('Register', '@f'),
+ hl('NestingParenthesis', ')'),
+ hl('BinaryPlus', '+', 1),
+ hl('NestingParenthesis', '(', 1),
+ hl('NestingParenthesis', '('),
+ hl('UnaryPlus', '+'),
+ hl('Register', '@g'),
+ hl('CallingParenthesis', '('),
+ hl('Register', '@h'),
+ hl('CallingParenthesis', ')'),
+ hl('NestingParenthesis', ')'),
+ hl('CallingParenthesis', '('),
+ hl('Register', '@j'),
+ hl('CallingParenthesis', ')'),
+ hl('CallingParenthesis', '('),
+ hl('Register', '@k'),
+ hl('CallingParenthesis', ')'),
+ hl('NestingParenthesis', ')'),
+ hl('CallingParenthesis', '('),
+ hl('Register', '@l'),
+ hl('CallingParenthesis', ')'),
+ })
check_parsing('@a)', {
-- 012
ast = {
@@ -1078,25 +1077,25 @@ return function(itp, _check_parsing, hl, fmtn)
end)
itp('works with variable names, including curly braces ones', function()
check_parsing('var', {
- ast = {
- 'PlainIdentifier(scope=0,ident=var):0:0:var',
- },
+ ast = {
+ 'PlainIdentifier(scope=0,ident=var):0:0:var',
+ },
}, {
hl('IdentifierName', 'var'),
})
check_parsing('g:var', {
- ast = {
- 'PlainIdentifier(scope=g,ident=var):0:0:g:var',
- },
+ ast = {
+ 'PlainIdentifier(scope=g,ident=var):0:0:g:var',
+ },
}, {
hl('IdentifierScope', 'g'),
hl('IdentifierScopeDelimiter', ':'),
hl('IdentifierName', 'var'),
})
check_parsing('g:', {
- ast = {
- 'PlainIdentifier(scope=g,ident=):0:0:g:',
- },
+ ast = {
+ 'PlainIdentifier(scope=g,ident=):0:0:g:',
+ },
}, {
hl('IdentifierScope', 'g'),
hl('IdentifierScopeDelimiter', ':'),
@@ -1141,7 +1140,7 @@ return function(itp, _check_parsing, hl, fmtn)
children = {
{
'OpMissing:0:3:',
- children={
+ children = {
'PlainIdentifier(scope=a,ident=):0:1:a:',
'Register(name=b):0:3:@b',
},
@@ -1783,7 +1782,7 @@ return function(itp, _check_parsing, hl, fmtn)
{
'Comma:0:3:,',
children = {
- 'PlainIdentifier(scope=0,ident=b):0:2:b',
+ 'PlainIdentifier(scope=0,ident=b):0:2:b',
{
'Comma:0:5:,',
children = {
@@ -1819,7 +1818,7 @@ return function(itp, _check_parsing, hl, fmtn)
{
'Comma:0:3:,',
children = {
- 'PlainIdentifier(scope=0,ident=b):0:2:b',
+ 'PlainIdentifier(scope=0,ident=b):0:2:b',
{
'Comma:0:5:,',
children = {
@@ -2851,7 +2850,7 @@ return function(itp, _check_parsing, hl, fmtn)
},
err = {
arg = '{a : b',
- msg = 'E723: Missing end of Dictionary \'}\': %.*s',
+ msg = "E723: Missing end of Dictionary '}': %.*s",
},
}, {
hl('Dict', '{'),
@@ -3182,7 +3181,7 @@ return function(itp, _check_parsing, hl, fmtn)
},
err = {
arg = '?b',
- msg = 'E109: Missing \':\' after \'?\': %.*s',
+ msg = "E109: Missing ':' after '?': %.*s",
},
}, {
hl('IdentifierName', 'a'),
@@ -3207,7 +3206,7 @@ return function(itp, _check_parsing, hl, fmtn)
},
err = {
arg = '?b:',
- msg = 'E109: Missing \':\' after \'?\': %.*s',
+ msg = "E109: Missing ':' after '?': %.*s",
},
}, {
hl('IdentifierName', 'a'),
@@ -4840,7 +4839,7 @@ return function(itp, _check_parsing, hl, fmtn)
},
err = {
arg = '[1',
- msg = 'E697: Missing end of List \']\': %.*s',
+ msg = "E697: Missing end of List ']': %.*s",
},
}, {
hl('List', '['),
@@ -4848,15 +4847,15 @@ return function(itp, _check_parsing, hl, fmtn)
})
end)
itp('works with strings', function()
- check_parsing('\'abc\'', {
+ check_parsing("'abc'", {
-- 01234
ast = {
- fmtn('SingleQuotedString', 'val="abc"', ':0:0:\'abc\''),
+ fmtn('SingleQuotedString', 'val="abc"', ":0:0:'abc'"),
},
}, {
- hl('SingleQuote', '\''),
+ hl('SingleQuote', "'"),
hl('SingleQuotedBody', 'abc'),
- hl('SingleQuote', '\''),
+ hl('SingleQuote', "'"),
})
check_parsing('"abc"', {
-- 01234
@@ -4868,14 +4867,14 @@ return function(itp, _check_parsing, hl, fmtn)
hl('DoubleQuotedBody', 'abc'),
hl('DoubleQuote', '"'),
})
- check_parsing('\'\'', {
+ check_parsing("''", {
-- 01
ast = {
- fmtn('SingleQuotedString', 'val=NULL', ':0:0:\'\''),
+ fmtn('SingleQuotedString', 'val=NULL', ":0:0:''"),
},
}, {
- hl('SingleQuote', '\''),
- hl('SingleQuote', '\''),
+ hl('SingleQuote', "'"),
+ hl('SingleQuote', "'"),
})
check_parsing('""', {
-- 01
@@ -4898,17 +4897,17 @@ return function(itp, _check_parsing, hl, fmtn)
}, {
hl('InvalidDoubleQuote', '"'),
})
- check_parsing('\'', {
+ check_parsing("'", {
-- 0
ast = {
- fmtn('SingleQuotedString', 'val=NULL', ':0:0:\''),
+ fmtn('SingleQuotedString', 'val=NULL', ":0:0:'"),
},
err = {
- arg = '\'',
+ arg = "'",
msg = 'E115: Missing single quote: %.*s',
},
}, {
- hl('InvalidSingleQuote', '\''),
+ hl('InvalidSingleQuote', "'"),
})
check_parsing('"a', {
-- 01
@@ -4923,71 +4922,71 @@ return function(itp, _check_parsing, hl, fmtn)
hl('InvalidDoubleQuote', '"'),
hl('InvalidDoubleQuotedBody', 'a'),
})
- check_parsing('\'a', {
+ check_parsing("'a", {
-- 01
ast = {
- fmtn('SingleQuotedString', 'val="a"', ':0:0:\'a'),
+ fmtn('SingleQuotedString', 'val="a"', ":0:0:'a"),
},
err = {
- arg = '\'a',
+ arg = "'a",
msg = 'E115: Missing single quote: %.*s',
},
}, {
- hl('InvalidSingleQuote', '\''),
+ hl('InvalidSingleQuote', "'"),
hl('InvalidSingleQuotedBody', 'a'),
})
- check_parsing('\'abc\'\'def\'', {
+ check_parsing("'abc''def'", {
-- 0123456789
ast = {
- fmtn('SingleQuotedString', 'val="abc\'def"', ':0:0:\'abc\'\'def\''),
+ fmtn('SingleQuotedString', 'val="abc\'def"', ":0:0:'abc''def'"),
},
}, {
- hl('SingleQuote', '\''),
+ hl('SingleQuote', "'"),
hl('SingleQuotedBody', 'abc'),
- hl('SingleQuotedQuote', '\'\''),
+ hl('SingleQuotedQuote', "''"),
hl('SingleQuotedBody', 'def'),
- hl('SingleQuote', '\''),
+ hl('SingleQuote', "'"),
})
- check_parsing('\'abc\'\'', {
+ check_parsing("'abc''", {
-- 012345
ast = {
- fmtn('SingleQuotedString', 'val="abc\'"', ':0:0:\'abc\'\''),
+ fmtn('SingleQuotedString', 'val="abc\'"', ":0:0:'abc''"),
},
err = {
- arg = '\'abc\'\'',
+ arg = "'abc''",
msg = 'E115: Missing single quote: %.*s',
},
}, {
- hl('InvalidSingleQuote', '\''),
+ hl('InvalidSingleQuote', "'"),
hl('InvalidSingleQuotedBody', 'abc'),
- hl('InvalidSingleQuotedQuote', '\'\''),
+ hl('InvalidSingleQuotedQuote', "''"),
})
- check_parsing('\'\'\'\'\'\'\'\'', {
+ check_parsing("''''''''", {
-- 01234567
ast = {
- fmtn('SingleQuotedString', 'val="\'\'\'"', ':0:0:\'\'\'\'\'\'\'\''),
+ fmtn('SingleQuotedString', "val=\"'''\"", ":0:0:''''''''"),
},
}, {
- hl('SingleQuote', '\''),
- hl('SingleQuotedQuote', '\'\''),
- hl('SingleQuotedQuote', '\'\''),
- hl('SingleQuotedQuote', '\'\''),
- hl('SingleQuote', '\''),
+ hl('SingleQuote', "'"),
+ hl('SingleQuotedQuote', "''"),
+ hl('SingleQuotedQuote', "''"),
+ hl('SingleQuotedQuote', "''"),
+ hl('SingleQuote', "'"),
})
- check_parsing('\'\'\'a\'\'\'\'bc\'', {
+ check_parsing("'''a''''bc'", {
-- 01234567890
-- 0 1
ast = {
- fmtn('SingleQuotedString', 'val="\'a\'\'bc"', ':0:0:\'\'\'a\'\'\'\'bc\''),
+ fmtn('SingleQuotedString', "val=\"'a''bc\"", ":0:0:'''a''''bc'"),
},
}, {
- hl('SingleQuote', '\''),
- hl('SingleQuotedQuote', '\'\''),
+ hl('SingleQuote', "'"),
+ hl('SingleQuotedQuote', "''"),
hl('SingleQuotedBody', 'a'),
- hl('SingleQuotedQuote', '\'\''),
- hl('SingleQuotedQuote', '\'\''),
+ hl('SingleQuotedQuote', "''"),
+ hl('SingleQuotedQuote', "''"),
hl('SingleQuotedBody', 'bc'),
- hl('SingleQuote', '\''),
+ hl('SingleQuote', "'"),
})
check_parsing('"\\"\\"\\"\\""', {
-- 0123456789
@@ -5006,7 +5005,11 @@ return function(itp, _check_parsing, hl, fmtn)
-- 0123456789012345678901234
-- 0 1 2
ast = {
- fmtn('DoubleQuotedString', 'val="abc\\"def\\"ghi\\"jkl\\"mno"', ':0:0:"abc\\"def\\"ghi\\"jkl\\"mno"'),
+ fmtn(
+ 'DoubleQuotedString',
+ 'val="abc\\"def\\"ghi\\"jkl\\"mno"',
+ ':0:0:"abc\\"def\\"ghi\\"jkl\\"mno"'
+ ),
},
}, {
hl('DoubleQuote', '"'),
@@ -6977,8 +6980,7 @@ return function(itp, _check_parsing, hl, fmtn)
arg = '\0002&A:\000',
msg = 'E15: Expected value, got EOC: %.*s',
},
- }, {
- }, {
+ }, {}, {
[2] = {
ast = {
len = REMOVE_THIS,
@@ -7025,7 +7027,7 @@ return function(itp, _check_parsing, hl, fmtn)
},
},
})
- check_parsing({data='01', size=1}, {
+ check_parsing({ data = '01', size = 1 }, {
len = 1,
ast = {
'Integer(val=0):0:0:0',
@@ -7033,7 +7035,7 @@ return function(itp, _check_parsing, hl, fmtn)
}, {
hl('Number', '0'),
})
- check_parsing({data='001', size=2}, {
+ check_parsing({ data = '001', size = 2 }, {
len = 2,
ast = {
'Integer(val=0):0:0:00',
@@ -7076,8 +7078,7 @@ return function(itp, _check_parsing, hl, fmtn)
arg = '|"\\U\\',
msg = 'E15: Expected value, got EOC: %.*s',
},
- }, {
- }, {
+ }, {}, {
[2] = {
ast = {
len = REMOVE_THIS,
@@ -7109,8 +7110,7 @@ return function(itp, _check_parsing, hl, fmtn)
arg = '|"\\e"',
msg = 'E15: Expected value, got EOC: %.*s',
},
- }, {
- }, {
+ }, {}, {
[2] = {
ast = {
len = REMOVE_THIS,
@@ -7142,8 +7142,7 @@ return function(itp, _check_parsing, hl, fmtn)
arg = '|\029',
msg = 'E15: Expected value, got EOC: %.*s',
},
- }, {
- }, {
+ }, {}, {
[2] = {
ast = {
len = REMOVE_THIS,
@@ -7373,7 +7372,7 @@ return function(itp, _check_parsing, hl, fmtn)
hl_fs = {
[2] = REMOVE_THIS,
[3] = REMOVE_THIS,
- }
+ },
},
})
diff --git a/test/unit/viml/helpers.lua b/test/unit/viml/helpers.lua
index 9d8102e023..92661e3027 100644
--- a/test/unit/viml/helpers.lua
+++ b/test/unit/viml/helpers.lua
@@ -76,7 +76,7 @@ local function pstate_set_str(pstate, start, len, ret)
ret = ret or {}
ret.start = {
line = tonumber(start.line),
- col = tonumber(start.col)
+ col = tonumber(start.col),
}
ret.len = tonumber(len)
ret.str, ret.error = pstate_str(pstate, start, len)
@@ -84,36 +84,57 @@ local function pstate_set_str(pstate, start, len, ret)
end
local eltkn_cmp_type_tab
-make_enum_conv_tab(lib, {
- 'kExprCmpEqual',
- 'kExprCmpMatches',
- 'kExprCmpGreater',
- 'kExprCmpGreaterOrEqual',
- 'kExprCmpIdentical',
-}, 'kExprCmp', function(ret) eltkn_cmp_type_tab = ret end)
+make_enum_conv_tab(
+ lib,
+ {
+ 'kExprCmpEqual',
+ 'kExprCmpMatches',
+ 'kExprCmpGreater',
+ 'kExprCmpGreaterOrEqual',
+ 'kExprCmpIdentical',
+ },
+ 'kExprCmp',
+ function(ret)
+ eltkn_cmp_type_tab = ret
+ end
+)
local function conv_cmp_type(typ)
return conv_enum(eltkn_cmp_type_tab, typ)
end
local ccs_tab
-make_enum_conv_tab(lib, {
- 'kCCStrategyUseOption',
- 'kCCStrategyMatchCase',
- 'kCCStrategyIgnoreCase',
-}, 'kCCStrategy', function(ret) ccs_tab = ret end)
+make_enum_conv_tab(
+ lib,
+ {
+ 'kCCStrategyUseOption',
+ 'kCCStrategyMatchCase',
+ 'kCCStrategyIgnoreCase',
+ },
+ 'kCCStrategy',
+ function(ret)
+ ccs_tab = ret
+ end
+)
local function conv_ccs(ccs)
return conv_enum(ccs_tab, ccs)
end
local expr_asgn_type_tab
-make_enum_conv_tab(lib, {
- 'kExprAsgnPlain',
- 'kExprAsgnAdd',
- 'kExprAsgnSubtract',
- 'kExprAsgnConcat',
-}, 'kExprAsgn', function(ret) expr_asgn_type_tab = ret end)
+make_enum_conv_tab(
+ lib,
+ {
+ 'kExprAsgnPlain',
+ 'kExprAsgnAdd',
+ 'kExprAsgnSubtract',
+ 'kExprAsgnConcat',
+ },
+ 'kExprAsgn',
+ function(ret)
+ expr_asgn_type_tab = ret
+ end
+)
local function conv_expr_asgn_type(expr_asgn_type)
return conv_enum(expr_asgn_type_tab, expr_asgn_type)